FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavformat/mov.c
Date: 2026-08-28 22:32:55
Exec Total Coverage
Lines: 4764 7470 63.8%
Functions: 192 231 83.1%
Branches: 2727 5051 54.0%

Line Branch Exec Source
1 /*
2 * MOV demuxer
3 * Copyright (c) 2001 Fabrice Bellard
4 * Copyright (c) 2009 Baptiste Coudurier <baptiste dot coudurier at gmail dot com>
5 *
6 * first version by Francois Revol <revol@free.fr>
7 * seek function by Gael Chardon <gael.dev@4now.net>
8 *
9 * This file is part of FFmpeg.
10 *
11 * FFmpeg is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Lesser General Public
13 * License as published by the Free Software Foundation; either
14 * version 2.1 of the License, or (at your option) any later version.
15 *
16 * FFmpeg is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * Lesser General Public License for more details.
20 *
21 * You should have received a copy of the GNU Lesser General Public
22 * License along with FFmpeg; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
24 */
25
26 #include "config_components.h"
27
28 #include <inttypes.h>
29 #include <limits.h>
30 #include <stdint.h>
31 #include <stdlib.h>
32
33 #include "libavutil/attributes.h"
34 #include "libavutil/bprint.h"
35 #include "libavutil/channel_layout.h"
36 #include "libavutil/dovi_meta.h"
37 #include "libavutil/internal.h"
38 #include "libavutil/intreadwrite.h"
39 #include "libavutil/intfloat.h"
40 #include "libavutil/mathematics.h"
41 #include "libavutil/avassert.h"
42 #include "libavutil/avstring.h"
43 #include "libavutil/dict.h"
44 #include "libavutil/display.h"
45 #include "libavutil/mem.h"
46 #include "libavutil/opt.h"
47 #include "libavutil/aes.h"
48 #include "libavutil/aes_ctr.h"
49 #include "libavutil/pixdesc.h"
50 #include "libavutil/sha.h"
51 #include "libavutil/spherical.h"
52 #include "libavutil/stereo3d.h"
53 #include "libavutil/timecode.h"
54 #include "libavutil/uuid.h"
55 #include "libavcodec/ac3tab.h"
56 #include "libavcodec/exif.h"
57 #include "libavcodec/flac.h"
58 #include "libavcodec/hevc/hevc.h"
59 #include "libavcodec/mpegaudiodecheader.h"
60 #include "libavcodec/mlp_parse.h"
61 #include "avformat.h"
62 #include "internal.h"
63 #include "avio_internal.h"
64 #include "demux.h"
65 #include "dvdclut.h"
66 #include "iamf_parse.h"
67 #include "iamf_reader.h"
68 #include "dovi_isom.h"
69 #include "riff.h"
70 #include "isom.h"
71 #include "libavcodec/get_bits.h"
72 #include "id3v1.h"
73 #include "mov_chan.h"
74 #include "replaygain.h"
75
76 #if CONFIG_ZLIB
77 #include <zlib.h>
78 #endif
79
80 #include "qtpalette.h"
81
82 /* those functions parse an atom */
83 /* links atom IDs to parse functions */
84 typedef struct MOVParseTableEntry {
85 uint32_t type;
86 int (*parse)(MOVContext *ctx, AVIOContext *pb, MOVAtom atom);
87 } MOVParseTableEntry;
88
89 static int mov_read_default(MOVContext *c, AVIOContext *pb, MOVAtom atom);
90 static int mov_read_mfra(MOVContext *c, AVIOContext *f);
91 static void mov_free_stream_context(AVFormatContext *s, AVStream *st);
92
93 32 static int mov_metadata_track_or_disc_number(MOVContext *c, AVIOContext *pb,
94 unsigned len, const char *key)
95 {
96 char buf[16];
97
98 32 short current, total = 0;
99 32 avio_rb16(pb); // unknown
100 32 current = avio_rb16(pb);
101
1/2
✓ Branch 0 taken 32 times.
✗ Branch 1 not taken.
32 if (len >= 6)
102 32 total = avio_rb16(pb);
103
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 25 times.
32 if (!total)
104 7 snprintf(buf, sizeof(buf), "%d", current);
105 else
106 25 snprintf(buf, sizeof(buf), "%d/%d", current, total);
107 32 c->fc->event_flags |= AVFMT_EVENT_FLAG_METADATA_UPDATED;
108 32 av_dict_set(&c->fc->metadata, key, buf, 0);
109
110 32 return 0;
111 }
112
113 static int mov_metadata_int8_bypass_padding(MOVContext *c, AVIOContext *pb,
114 unsigned len, const char *key)
115 {
116 /* bypass padding bytes */
117 avio_r8(pb);
118 avio_r8(pb);
119 avio_r8(pb);
120
121 c->fc->event_flags |= AVFMT_EVENT_FLAG_METADATA_UPDATED;
122 av_dict_set_int(&c->fc->metadata, key, avio_r8(pb), 0);
123
124 return 0;
125 }
126
127 30 static int mov_metadata_int8_no_padding(MOVContext *c, AVIOContext *pb,
128 unsigned len, const char *key)
129 {
130 30 c->fc->event_flags |= AVFMT_EVENT_FLAG_METADATA_UPDATED;
131 30 av_dict_set_int(&c->fc->metadata, key, avio_r8(pb), 0);
132
133 30 return 0;
134 }
135
136 12 static int mov_metadata_gnre(MOVContext *c, AVIOContext *pb,
137 unsigned len, const char *key)
138 {
139 short genre;
140
141 12 avio_r8(pb); // unknown
142
143 12 genre = avio_r8(pb);
144
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)
145 return 0;
146 12 c->fc->event_flags |= AVFMT_EVENT_FLAG_METADATA_UPDATED;
147 12 av_dict_set(&c->fc->metadata, key, ff_id3v1_genre_str[genre-1], 0);
148
149 12 return 0;
150 }
151
152 static const uint32_t mac_to_unicode[128] = {
153 0x00C4,0x00C5,0x00C7,0x00C9,0x00D1,0x00D6,0x00DC,0x00E1,
154 0x00E0,0x00E2,0x00E4,0x00E3,0x00E5,0x00E7,0x00E9,0x00E8,
155 0x00EA,0x00EB,0x00ED,0x00EC,0x00EE,0x00EF,0x00F1,0x00F3,
156 0x00F2,0x00F4,0x00F6,0x00F5,0x00FA,0x00F9,0x00FB,0x00FC,
157 0x2020,0x00B0,0x00A2,0x00A3,0x00A7,0x2022,0x00B6,0x00DF,
158 0x00AE,0x00A9,0x2122,0x00B4,0x00A8,0x2260,0x00C6,0x00D8,
159 0x221E,0x00B1,0x2264,0x2265,0x00A5,0x00B5,0x2202,0x2211,
160 0x220F,0x03C0,0x222B,0x00AA,0x00BA,0x03A9,0x00E6,0x00F8,
161 0x00BF,0x00A1,0x00AC,0x221A,0x0192,0x2248,0x2206,0x00AB,
162 0x00BB,0x2026,0x00A0,0x00C0,0x00C3,0x00D5,0x0152,0x0153,
163 0x2013,0x2014,0x201C,0x201D,0x2018,0x2019,0x00F7,0x25CA,
164 0x00FF,0x0178,0x2044,0x20AC,0x2039,0x203A,0xFB01,0xFB02,
165 0x2021,0x00B7,0x201A,0x201E,0x2030,0x00C2,0x00CA,0x00C1,
166 0x00CB,0x00C8,0x00CD,0x00CE,0x00CF,0x00CC,0x00D3,0x00D4,
167 0xF8FF,0x00D2,0x00DA,0x00DB,0x00D9,0x0131,0x02C6,0x02DC,
168 0x00AF,0x02D8,0x02D9,0x02DA,0x00B8,0x02DD,0x02DB,0x02C7,
169 };
170
171 365 static int mov_read_mac_string(MOVContext *c, AVIOContext *pb, int len,
172 char *dst, int dstlen)
173 {
174 365 char *p = dst;
175 365 char *end = dst+dstlen-1;
176 int i;
177
178
2/2
✓ Branch 0 taken 3125 times.
✓ Branch 1 taken 365 times.
3490 for (i = 0; i < len; i++) {
179 3125 uint8_t t, c = avio_r8(pb);
180
181
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3125 times.
3125 if (p >= end)
182 continue;
183
184
2/2
✓ Branch 0 taken 3117 times.
✓ Branch 1 taken 8 times.
3125 if (c < 0x80)
185 3117 *p++ = c;
186
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 else if (p < end)
187
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;);
188 }
189 365 *p = 0;
190 365 return p - dst;
191 }
192
193 /**
194 * Get the requested item.
195 */
196 166 static HEIFItem *get_heif_item(MOVContext *c, unsigned id)
197 {
198 166 HEIFItem *item = NULL;
199
200
2/2
✓ Branch 0 taken 368 times.
✓ Branch 1 taken 12 times.
380 for (int i = 0; i < c->nb_heif_item; i++) {
201
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)
202 214 continue;
203
204 154 item = c->heif_item[i];
205 154 break;
206 }
207
208 166 return item;
209 }
210
211 /**
212 * Get the current stream in the parsing process. This can either be the
213 * latest stream added to the context, or the stream referenced by an item.
214 */
215 270 static AVStream *get_curr_st(MOVContext *c)
216 {
217 270 AVStream *st = NULL;
218 HEIFItem *item;
219
220
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 270 times.
270 if (c->fc->nb_streams < 1)
221 return NULL;
222
223
2/2
✓ Branch 0 taken 221 times.
✓ Branch 1 taken 49 times.
270 if (c->cur_item_id == -1)
224 221 return c->fc->streams[c->fc->nb_streams-1];
225
226 49 item = get_heif_item(c, c->cur_item_id);
227
1/2
✓ Branch 0 taken 49 times.
✗ Branch 1 not taken.
49 if (item)
228 49 st = item->st;
229
230 49 return st;
231 }
232
233 16 static int mov_read_covr(MOVContext *c, AVIOContext *pb, int type, int len)
234 {
235 AVStream *st;
236 MOVStreamContext *sc;
237 enum AVCodecID id;
238 int ret;
239
240
2/4
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
16 switch (type) {
241 9 case 0xd: id = AV_CODEC_ID_MJPEG; break;
242 7 case 0xe: id = AV_CODEC_ID_PNG; break;
243 case 0x1b: id = AV_CODEC_ID_BMP; break;
244 default:
245 av_log(c->fc, AV_LOG_WARNING, "Unknown cover type: 0x%x.\n", type);
246 avio_skip(pb, len);
247 return 0;
248 }
249
250 16 sc = av_mallocz(sizeof(*sc));
251
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 if (!sc)
252 return AVERROR(ENOMEM);
253 16 ret = ff_add_attached_pic(c->fc, NULL, pb, NULL, len);
254
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 if (ret < 0) {
255 av_free(sc);
256 return ret;
257 }
258 16 st = c->fc->streams[c->fc->nb_streams - 1];
259 16 st->priv_data = sc;
260 16 sc->id = st->id;
261 16 sc->refcount = 1;
262
263
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) {
264
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 9 times.
16 if (AV_RB64(st->attached_pic.data) == 0x89504e470d0a1a0a) {
265 7 id = AV_CODEC_ID_PNG;
266 } else {
267 9 id = AV_CODEC_ID_MJPEG;
268 }
269 }
270 16 st->codecpar->codec_id = id;
271
272 16 return 0;
273 }
274
275 // 3GPP TS 26.244
276 static int mov_metadata_loci(MOVContext *c, AVIOContext *pb, unsigned len)
277 {
278 char language[4] = { 0 };
279 char buf[200], place[100];
280 uint16_t langcode = 0;
281 double longitude, latitude, altitude;
282 const char *key = "location";
283
284 if (len < 4 + 2 + 1 + 1 + 4 + 4 + 4) {
285 av_log(c->fc, AV_LOG_ERROR, "loci too short\n");
286 return AVERROR_INVALIDDATA;
287 }
288
289 avio_skip(pb, 4); // version+flags
290 langcode = avio_rb16(pb);
291 ff_mov_lang_to_iso639(langcode, language);
292 len -= 6;
293
294 len -= avio_get_str(pb, len, place, sizeof(place));
295 if (len < 1) {
296 av_log(c->fc, AV_LOG_ERROR, "place name too long\n");
297 return AVERROR_INVALIDDATA;
298 }
299 avio_skip(pb, 1); // role
300 len -= 1;
301
302 if (len < 12) {
303 av_log(c->fc, AV_LOG_ERROR,
304 "loci too short (%u bytes left, need at least %d)\n", len, 12);
305 return AVERROR_INVALIDDATA;
306 }
307 longitude = ((int32_t) avio_rb32(pb)) / (float) (1 << 16);
308 latitude = ((int32_t) avio_rb32(pb)) / (float) (1 << 16);
309 altitude = ((int32_t) avio_rb32(pb)) / (float) (1 << 16);
310
311 // Try to output in the same format as the ?xyz field
312 snprintf(buf, sizeof(buf), "%+08.4f%+09.4f", latitude, longitude);
313 if (altitude)
314 av_strlcatf(buf, sizeof(buf), "%+f", altitude);
315 av_strlcatf(buf, sizeof(buf), "/%s", place);
316
317 if (*language && strcmp(language, "und")) {
318 char key2[16];
319 snprintf(key2, sizeof(key2), "%s-%s", key, language);
320 av_dict_set(&c->fc->metadata, key2, buf, 0);
321 }
322 c->fc->event_flags |= AVFMT_EVENT_FLAG_METADATA_UPDATED;
323 return av_dict_set(&c->fc->metadata, key, buf, 0);
324 }
325
326 static int mov_metadata_hmmt(MOVContext *c, AVIOContext *pb, unsigned len)
327 {
328 int i, n_hmmt;
329
330 if (len < 2)
331 return 0;
332 if (c->ignore_chapters)
333 return 0;
334
335 n_hmmt = avio_rb32(pb);
336 if (n_hmmt > len / 4)
337 return AVERROR_INVALIDDATA;
338 for (i = 0; i < n_hmmt && !pb->eof_reached; i++) {
339 int moment_time = avio_rb32(pb);
340 avpriv_new_chapter(c->fc, i, av_make_q(1, 1000), moment_time, AV_NOPTS_VALUE, NULL);
341 }
342 if (avio_feof(pb))
343 return AVERROR_INVALIDDATA;
344 return 0;
345 }
346
347 544 static int mov_read_udta_string(MOVContext *c, AVIOContext *pb, MOVAtom atom)
348 {
349 544 char tmp_key[AV_FOURCC_MAX_STRING_SIZE] = {0};
350 544 char key2[32], language[4] = {0};
351 544 char *str = NULL;
352 544 const char *key = NULL;
353 544 uint16_t langcode = 0;
354 544 uint32_t data_type = 0, str_size_alloc;
355 uint64_t str_size;
356 544 int (*parse)(MOVContext*, AVIOContext*, unsigned, const char*) = NULL;
357 544 int raw = 0;
358 544 int num = 0;
359 AVDictionary **metadata;
360
361
3/4
✓ Branch 0 taken 29 times.
✓ Branch 1 taken 515 times.
✓ Branch 2 taken 29 times.
✗ Branch 3 not taken.
544 if (c->trak_index >= 0 && c->trak_index < c->fc->nb_streams)
362 29 metadata = &c->fc->streams[c->trak_index]->metadata;
363 else
364 515 metadata = &c->fc->metadata;
365
366
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 47 times.
✗ Branch 62 not taken.
✗ Branch 63 not taken.
✗ Branch 64 not taken.
✗ Branch 65 not taken.
✗ Branch 66 not taken.
✗ Branch 67 not taken.
✓ Branch 68 taken 63 times.
✓ Branch 69 taken 67 times.
✗ Branch 70 not taken.
✗ Branch 71 not taken.
✗ Branch 72 not taken.
✓ Branch 73 taken 3 times.
✓ Branch 74 taken 5 times.
544 switch (atom.type) {
367 3 case MKTAG( '@','P','R','M'): key = "premiere_version"; raw = 1; break;
368 3 case MKTAG( '@','P','R','Q'): key = "quicktime_version"; raw = 1; break;
369 2 case MKTAG( 'X','M','P','_'):
370
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (c->export_xmp) { key = "xmp"; raw = 1; } break;
371 16 case MKTAG( 'a','A','R','T'): key = "album_artist"; break;
372 case MKTAG( 'a','k','I','D'): key = "account_type";
373 parse = mov_metadata_int8_no_padding; break;
374 case MKTAG( 'a','p','I','D'): key = "account_id"; break;
375 case MKTAG( 'c','a','t','g'): key = "category"; break;
376 15 case MKTAG( 'c','p','i','l'): key = "compilation";
377 15 parse = mov_metadata_int8_no_padding; break;
378 2 case MKTAG( 'c','p','r','t'): key = "copyright"; break;
379 case MKTAG( 'd','e','s','c'): key = "description"; break;
380 16 case MKTAG( 'd','i','s','k'): key = "disc";
381 16 parse = mov_metadata_track_or_disc_number; break;
382 case MKTAG( 'e','g','i','d'): key = "episode_uid";
383 parse = mov_metadata_int8_no_padding; break;
384 case MKTAG( 'F','I','R','M'): key = "firmware"; raw = 1; break;
385 12 case MKTAG( 'g','n','r','e'): key = "genre";
386 12 parse = mov_metadata_gnre; break;
387 case MKTAG( 'h','d','v','d'): key = "hd_video";
388 parse = mov_metadata_int8_no_padding; break;
389 case MKTAG( 'H','M','M','T'):
390 return mov_metadata_hmmt(c, pb, atom.size);
391 case MKTAG( 'k','e','y','w'): key = "keywords"; break;
392 case MKTAG( 'l','d','e','s'): key = "synopsis"; break;
393 case MKTAG( 'l','o','c','i'):
394 return mov_metadata_loci(c, pb, atom.size);
395 case MKTAG( 'm','a','n','u'): key = "make"; break;
396 case MKTAG( 'm','o','d','l'): key = "model"; break;
397 5 case MKTAG( 'n','a','m','e'): key = "name"; break;
398 case MKTAG( 'p','c','s','t'): key = "podcast";
399 parse = mov_metadata_int8_no_padding; break;
400 15 case MKTAG( 'p','g','a','p'): key = "gapless_playback";
401 15 parse = mov_metadata_int8_no_padding; break;
402 case MKTAG( 'p','u','r','d'): key = "purchase_date"; break;
403 case MKTAG( 'r','t','n','g'): key = "rating";
404 parse = mov_metadata_int8_no_padding; break;
405 case MKTAG( 's','o','a','a'): key = "sort_album_artist"; break;
406 case MKTAG( 's','o','a','l'): key = "sort_album"; break;
407 case MKTAG( 's','o','a','r'): key = "sort_artist"; break;
408 case MKTAG( 's','o','c','o'): key = "sort_composer"; break;
409 case MKTAG( 's','o','n','m'): key = "sort_name"; break;
410 case MKTAG( 's','o','s','n'): key = "sort_show"; break;
411 case MKTAG( 's','t','i','k'): key = "media_type";
412 parse = mov_metadata_int8_no_padding; break;
413 16 case MKTAG( 't','r','k','n'): key = "track";
414 16 parse = mov_metadata_track_or_disc_number; break;
415 case MKTAG( 't','v','e','n'): key = "episode_id"; break;
416 case MKTAG( 't','v','e','s'): key = "episode_sort";
417 parse = mov_metadata_int8_bypass_padding; break;
418 case MKTAG( 't','v','n','n'): key = "network"; break;
419 case MKTAG( 't','v','s','h'): key = "show"; break;
420 case MKTAG( 't','v','s','n'): key = "season_number";
421 parse = mov_metadata_int8_bypass_padding; break;
422 21 case MKTAG(0xa9,'A','R','T'): key = "artist"; break;
423 case MKTAG(0xa9,'P','R','D'): key = "producer"; break;
424 20 case MKTAG(0xa9,'a','l','b'): key = "album"; break;
425 3 case MKTAG(0xa9,'a','u','t'): key = "artist"; break;
426 case MKTAG(0xa9,'c','h','p'): key = "chapter"; break;
427 12 case MKTAG(0xa9,'c','m','t'): key = "comment"; break;
428 case MKTAG(0xa9,'c','o','m'): key = "composer"; break;
429 4 case MKTAG(0xa9,'c','p','y'): key = "copyright"; break;
430 20 case MKTAG(0xa9,'d','a','y'): key = "date"; break;
431 case MKTAG(0xa9,'d','i','r'): key = "director"; break;
432 case MKTAG(0xa9,'d','i','s'): key = "disclaimer"; break;
433 case MKTAG(0xa9,'e','d','1'): key = "edit_date"; break;
434 2 case MKTAG(0xa9,'e','n','c'): key = "encoder"; break;
435 case MKTAG(0xa9,'f','m','t'): key = "original_format"; break;
436 5 case MKTAG(0xa9,'g','e','n'): key = "genre"; break;
437 case MKTAG(0xa9,'g','r','p'): key = "grouping"; break;
438 case MKTAG(0xa9,'h','s','t'): key = "host_computer"; break;
439 case MKTAG(0xa9,'i','n','f'): key = "comment"; break;
440 case MKTAG(0xa9,'l','y','r'): key = "lyrics"; break;
441 5 case MKTAG(0xa9,'m','a','k'): key = "make"; break;
442 5 case MKTAG(0xa9,'m','o','d'): key = "model"; break;
443 47 case MKTAG(0xa9,'n','a','m'): key = "title"; break;
444 case MKTAG(0xa9,'o','p','e'): key = "original_artist"; break;
445 case MKTAG(0xa9,'p','r','d'): key = "producer"; break;
446 case MKTAG(0xa9,'p','r','f'): key = "performers"; break;
447 case MKTAG(0xa9,'r','e','q'): key = "playback_requirements"; break;
448 case MKTAG(0xa9,'s','r','c'): key = "original_source"; break;
449 case MKTAG(0xa9,'s','t','3'): key = "subtitle"; break;
450 63 case MKTAG(0xa9,'s','w','r'): key = "encoder"; break;
451 67 case MKTAG(0xa9,'t','o','o'): key = "encoder"; break;
452 case MKTAG(0xa9,'t','r','k'): key = "track"; break;
453 case MKTAG(0xa9,'u','r','l'): key = "URL"; break;
454 case MKTAG(0xa9,'w','r','n'): key = "warning"; break;
455 3 case MKTAG(0xa9,'w','r','t'): key = "composer"; break;
456 5 case MKTAG(0xa9,'x','y','z'): key = "location"; break;
457 }
458 7 retry:
459
3/4
✓ Branch 0 taken 367 times.
✓ Branch 1 taken 184 times.
✓ Branch 2 taken 367 times.
✗ Branch 3 not taken.
902 if (c->itunes_metadata && atom.size > 8) {
460 367 int data_size = avio_rb32(pb);
461 367 int tag = avio_rl32(pb);
462
3/6
✓ Branch 0 taken 367 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 367 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 367 times.
✗ Branch 5 not taken.
367 if (tag == MKTAG('d','a','t','a') && data_size <= atom.size && data_size >= 16) {
463 367 data_type = avio_rb32(pb); // type
464 367 avio_rb32(pb); // unknown
465 367 str_size = data_size - 16;
466 367 atom.size -= 16;
467
468
5/6
✓ Branch 0 taken 97 times.
✓ Branch 1 taken 270 times.
✓ Branch 2 taken 59 times.
✓ Branch 3 taken 38 times.
✓ Branch 4 taken 59 times.
✗ Branch 5 not taken.
367 if (!key && c->found_hdlr_mdta && c->meta_keys) {
469 59 uint32_t index = av_bswap32(atom.type); // BE number has been read as LE
470
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) {
471 59 key = c->meta_keys[index];
472 } else if (atom.type != MKTAG('c', 'o', 'v', 'r')) {
473 av_log(c->fc, AV_LOG_WARNING,
474 "The index of 'data' is out of range: %"PRId32" < 1 or >= %d.\n",
475 index, c->meta_keys_count);
476 }
477 }
478
4/4
✓ Branch 0 taken 351 times.
✓ Branch 1 taken 16 times.
✓ Branch 2 taken 329 times.
✓ Branch 3 taken 22 times.
367 if (atom.type == MKTAG('c', 'o', 'v', 'r') ||
479
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 329 times.
329 (key && !strcmp(key, "com.apple.quicktime.artwork"))) {
480 16 int ret = mov_read_covr(c, pb, data_type, str_size);
481
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 if (ret < 0) {
482 av_log(c->fc, AV_LOG_ERROR, "Error parsing cover art.\n");
483 return ret;
484 }
485 16 atom.size -= str_size;
486
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 14 times.
16 if (atom.size > 8)
487 2 goto retry;
488 14 return ret;
489 }
490 } else return 0;
491
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) {
492 109 str_size = avio_rb16(pb); // string length
493
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 104 times.
109 if (str_size > atom.size) {
494 5 raw = 1;
495 5 avio_seek(pb, -2, SEEK_CUR);
496 5 av_log(c->fc, AV_LOG_WARNING, "UDTA parsing failed retrying raw\n");
497 5 goto retry;
498 }
499 104 langcode = avio_rb16(pb);
500 104 ff_mov_lang_to_iso639(langcode, language);
501 104 atom.size -= 4;
502 } else
503 75 str_size = atom.size;
504
505
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 530 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
530 if (c->export_all && !key) {
506 key = av_fourcc_make_string(tmp_key, atom.type);
507 }
508
509
2/2
✓ Branch 0 taken 86 times.
✓ Branch 1 taken 444 times.
530 if (!key)
510 86 return 0;
511
2/4
✓ Branch 0 taken 444 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 444 times.
444 if (atom.size < 0 || str_size >= INT_MAX/2)
512 return AVERROR_INVALIDDATA;
513
514 // Allocates enough space if data_type is a int32 or float32 number, otherwise
515 // worst-case requirement for output string in case of utf8 coded input
516
3/4
✓ Branch 0 taken 45 times.
✓ Branch 1 taken 399 times.
✓ Branch 2 taken 45 times.
✗ Branch 3 not taken.
444 num = (data_type >= 21 && data_type <= 23);
517
4/4
✓ Branch 0 taken 399 times.
✓ Branch 1 taken 45 times.
✓ Branch 2 taken 388 times.
✓ Branch 3 taken 11 times.
444 str_size_alloc = (num ? 512 : (raw ? str_size : str_size * 2)) + 1;
518 444 str = av_mallocz(str_size_alloc);
519
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 444 times.
444 if (!str)
520 return AVERROR(ENOMEM);
521
522
2/2
✓ Branch 0 taken 74 times.
✓ Branch 1 taken 370 times.
444 if (parse)
523 74 parse(c, pb, str_size, key);
524 else {
525
8/10
✓ Branch 0 taken 359 times.
✓ Branch 1 taken 11 times.
✓ Branch 2 taken 359 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 105 times.
✓ Branch 5 taken 254 times.
✓ Branch 6 taken 91 times.
✓ Branch 7 taken 14 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 91 times.
370 if (!raw && (data_type == 3 || (data_type == 0 && (langcode < 0x400 || langcode == 0x7fff)))) { // MAC Encoded
526 14 mov_read_mac_string(c, pb, str_size, str, str_size_alloc);
527
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 354 times.
356 } else if (data_type == 21) { // BE signed integer, variable size
528 2 int val = 0;
529
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (str_size == 1)
530 val = (int8_t)avio_r8(pb);
531
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 else if (str_size == 2)
532 val = (int16_t)avio_rb16(pb);
533
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 else if (str_size == 3)
534 val = ((int32_t)(avio_rb24(pb)<<8))>>8;
535
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 else if (str_size == 4)
536 2 val = (int32_t)avio_rb32(pb);
537
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (snprintf(str, str_size_alloc, "%d", val) >= str_size_alloc) {
538 av_log(c->fc, AV_LOG_ERROR,
539 "Failed to store the number (%d) in string.\n", val);
540 av_free(str);
541 return AVERROR_INVALIDDATA;
542 }
543
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 354 times.
354 } else if (data_type == 22) { // BE unsigned integer, variable size
544 unsigned int val = 0;
545 if (str_size == 1)
546 val = avio_r8(pb);
547 else if (str_size == 2)
548 val = avio_rb16(pb);
549 else if (str_size == 3)
550 val = avio_rb24(pb);
551 else if (str_size == 4)
552 val = avio_rb32(pb);
553 if (snprintf(str, str_size_alloc, "%u", val) >= str_size_alloc) {
554 av_log(c->fc, AV_LOG_ERROR,
555 "Failed to store the number (%u) in string.\n", val);
556 av_free(str);
557 return AVERROR_INVALIDDATA;
558 }
559
3/4
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 341 times.
✓ Branch 2 taken 13 times.
✗ Branch 3 not taken.
367 } else if (data_type == 23 && str_size >= 4) { // BE float32
560 13 float val = av_int2float(avio_rb32(pb));
561
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 13 times.
13 if (snprintf(str, str_size_alloc, "%f", val) >= str_size_alloc) {
562 av_log(c->fc, AV_LOG_ERROR,
563 "Failed to store the float32 number (%f) in string.\n", val);
564 av_free(str);
565 return AVERROR_INVALIDDATA;
566 }
567
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 341 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
341 } else if (data_type > 1 && data_type != 4) {
568 // data_type can be 0 if not set at all above. data_type 1 means
569 // UTF8 and 4 means "UTF8 sort". For any other type (UTF16 or e.g.
570 // a picture), don't return it blindly in a string that is supposed
571 // to be UTF8 text.
572 av_log(c->fc, AV_LOG_WARNING, "Skipping unhandled metadata %s of type %"PRIu32"\n", key, data_type);
573 av_free(str);
574 return 0;
575 } else {
576 341 int ret = ffio_read_size(pb, str, str_size);
577
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 341 times.
341 if (ret < 0) {
578 av_free(str);
579 return ret;
580 }
581 341 str[str_size] = 0;
582 }
583 370 c->fc->event_flags |= AVFMT_EVENT_FLAG_METADATA_UPDATED;
584
4/4
✓ Branch 0 taken 255 times.
✓ Branch 1 taken 115 times.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 254 times.
370 if (c->itunes_metadata && av_dict_get(*metadata, key, NULL, 0))
585 1 av_dict_set(metadata, key, ";", AV_DICT_APPEND);
586
2/2
✓ Branch 0 taken 255 times.
✓ Branch 1 taken 115 times.
370 av_dict_set(metadata, key, str, c->itunes_metadata ? AV_DICT_APPEND : 0);
587
4/4
✓ Branch 0 taken 104 times.
✓ Branch 1 taken 266 times.
✓ Branch 2 taken 37 times.
✓ Branch 3 taken 67 times.
370 if (*language && strcmp(language, "und")) {
588 37 snprintf(key2, sizeof(key2), "%s-%s", key, language);
589 37 av_dict_set(metadata, key2, str, 0);
590 }
591
2/2
✓ Branch 0 taken 132 times.
✓ Branch 1 taken 238 times.
370 if (!strcmp(key, "encoder")) {
592 int major, minor, micro;
593
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 131 times.
132 if (sscanf(str, "HandBrake %d.%d.%d", &major, &minor, &micro) == 3) {
594 1 c->handbrake_version = 1000000*major + 1000*minor + micro;
595 }
596 }
597
598 370 atom.size -= str_size;
599 370 av_freep(&str);
600
601 // Read remaining data atoms for multi-valued iTunes tags (e.g. multiple
602 // artists stored as multiple data atoms within one tag atom), consistent
603 // with the existing covr path.
604 // Note: multiple sibling tag atoms with the same key (e.g. three separate
605 // ©ART atoms under ilst) are handled by the AV_DICT_APPEND logic above,
606 // since mov_read_udta_string() is called once per tag atom.
607
3/4
✓ Branch 0 taken 255 times.
✓ Branch 1 taken 115 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 255 times.
370 if (c->itunes_metadata && atom.size > 8)
608 goto retry;
609 }
610
611 444 av_freep(&str);
612 444 return 0;
613 }
614
615 12 static int mov_read_chpl(MOVContext *c, AVIOContext *pb, MOVAtom atom)
616 {
617 int64_t start;
618 int i, nb_chapters, str_len, version;
619 char str[256+1];
620 int ret;
621
622
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (c->ignore_chapters)
623 return 0;
624
625
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if ((atom.size -= 5) < 0)
626 return 0;
627
628 12 version = avio_r8(pb);
629 12 avio_rb24(pb);
630
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
12 if (version)
631 12 avio_rb32(pb); // ???
632 12 nb_chapters = avio_r8(pb);
633
634
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 12 times.
30 for (i = 0; i < nb_chapters; i++) {
635
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (atom.size < 9)
636 return 0;
637
638 18 start = avio_rb64(pb);
639 18 str_len = avio_r8(pb);
640
641
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if ((atom.size -= 9+str_len) < 0)
642 return 0;
643
644 18 ret = ffio_read_size(pb, str, str_len);
645
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (ret < 0)
646 return ret;
647 18 str[str_len] = 0;
648 18 avpriv_new_chapter(c->fc, i, (AVRational){1,10000000}, start, AV_NOPTS_VALUE, str);
649 }
650 12 return 0;
651 }
652
653 #define MIN_DATA_ENTRY_BOX_SIZE 12
654 673 static int mov_read_dref(MOVContext *c, AVIOContext *pb, MOVAtom atom)
655 {
656 AVStream *st;
657 MOVStreamContext *sc;
658 int entries, i, j;
659
660
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 673 times.
673 if (c->fc->nb_streams < 1)
661 return 0;
662 673 st = c->fc->streams[c->fc->nb_streams-1];
663 673 sc = st->priv_data;
664
665 673 avio_rb32(pb); // version + flags
666 673 entries = avio_rb32(pb);
667
1/2
✓ Branch 0 taken 673 times.
✗ Branch 1 not taken.
673 if (!entries ||
668
1/2
✓ Branch 0 taken 673 times.
✗ Branch 1 not taken.
673 entries > (atom.size - 1) / MIN_DATA_ENTRY_BOX_SIZE + 1 ||
669
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 673 times.
673 entries >= UINT_MAX / sizeof(*sc->drefs))
670 return AVERROR_INVALIDDATA;
671
672
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 673 times.
673 for (i = 0; i < sc->drefs_count; i++) {
673 MOVDref *dref = &sc->drefs[i];
674 av_freep(&dref->path);
675 av_freep(&dref->dir);
676 }
677 673 av_free(sc->drefs);
678 673 sc->drefs_count = 0;
679 673 sc->drefs = av_mallocz(entries * sizeof(*sc->drefs));
680
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 673 times.
673 if (!sc->drefs)
681 return AVERROR(ENOMEM);
682 673 sc->drefs_count = entries;
683
684
2/2
✓ Branch 0 taken 673 times.
✓ Branch 1 taken 673 times.
1346 for (i = 0; i < entries; i++) {
685 673 MOVDref *dref = &sc->drefs[i];
686 673 uint32_t size = avio_rb32(pb);
687 673 int64_t next = avio_tell(pb);
688
689
3/6
✓ Branch 0 taken 673 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 673 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 673 times.
673 if (size < 12 || next < 0 || next > INT64_MAX - size)
690 return AVERROR_INVALIDDATA;
691
692 673 next += size - 4;
693
694 673 dref->type = avio_rl32(pb);
695 673 avio_rb32(pb); // version + flags
696
697
3/4
✓ Branch 0 taken 120 times.
✓ Branch 1 taken 553 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 120 times.
673 if (dref->type == MKTAG('a','l','i','s') && size > 150) {
698 /* macintosh alias record */
699 uint16_t volume_len, len;
700 int16_t type;
701 int ret;
702
703 avio_skip(pb, 10);
704
705 volume_len = avio_r8(pb);
706 volume_len = FFMIN(volume_len, 27);
707 ret = ffio_read_size(pb, dref->volume, 27);
708 if (ret < 0)
709 return ret;
710 dref->volume[volume_len] = 0;
711 av_log(c->fc, AV_LOG_DEBUG, "volume %s, len %d\n", dref->volume, volume_len);
712
713 avio_skip(pb, 12);
714
715 len = avio_r8(pb);
716 len = FFMIN(len, 63);
717 ret = ffio_read_size(pb, dref->filename, 63);
718 if (ret < 0)
719 return ret;
720 dref->filename[len] = 0;
721 av_log(c->fc, AV_LOG_DEBUG, "filename %s, len %d\n", dref->filename, len);
722
723 avio_skip(pb, 16);
724
725 /* read next level up_from_alias/down_to_target */
726 dref->nlvl_from = avio_rb16(pb);
727 dref->nlvl_to = avio_rb16(pb);
728 av_log(c->fc, AV_LOG_DEBUG, "nlvl from %d, nlvl to %d\n",
729 dref->nlvl_from, dref->nlvl_to);
730
731 avio_skip(pb, 16);
732
733 for (type = 0; type != -1 && avio_tell(pb) < next; ) {
734 if (avio_feof(pb))
735 return AVERROR_EOF;
736 type = avio_rb16(pb);
737 len = avio_rb16(pb);
738 av_log(c->fc, AV_LOG_DEBUG, "type %d, len %d\n", type, len);
739 if (len&1)
740 len += 1;
741 if (type == 2) { // absolute path
742 av_free(dref->path);
743 dref->path = av_mallocz(len+1);
744 if (!dref->path)
745 return AVERROR(ENOMEM);
746
747 ret = ffio_read_size(pb, dref->path, len);
748 if (ret < 0) {
749 av_freep(&dref->path);
750 return ret;
751 }
752 if (len > volume_len && !strncmp(dref->path, dref->volume, volume_len)) {
753 len -= volume_len;
754 memmove(dref->path, dref->path+volume_len, len);
755 dref->path[len] = 0;
756 }
757 // trim string of any ending zeros
758 for (j = len - 1; j >= 0; j--) {
759 if (dref->path[j] == 0)
760 len--;
761 else
762 break;
763 }
764 for (j = 0; j < len; j++)
765 if (dref->path[j] == ':' || dref->path[j] == 0)
766 dref->path[j] = '/';
767 av_log(c->fc, AV_LOG_DEBUG, "path %s\n", dref->path);
768 } else if (type == 0) { // directory name
769 av_free(dref->dir);
770 dref->dir = av_malloc(len+1);
771 if (!dref->dir)
772 return AVERROR(ENOMEM);
773
774 ret = ffio_read_size(pb, dref->dir, len);
775 if (ret < 0) {
776 av_freep(&dref->dir);
777 return ret;
778 }
779 dref->dir[len] = 0;
780 for (j = 0; j < len; j++)
781 if (dref->dir[j] == ':')
782 dref->dir[j] = '/';
783 av_log(c->fc, AV_LOG_DEBUG, "dir %s\n", dref->dir);
784 } else
785 avio_skip(pb, len);
786 }
787 } else {
788 673 av_log(c->fc, AV_LOG_DEBUG, "Unknown dref type 0x%08"PRIx32" size %"PRIu32"\n",
789 dref->type, size);
790 673 entries--;
791 673 i--;
792 }
793 673 avio_seek(pb, next, SEEK_SET);
794 }
795 673 return 0;
796 }
797
798 1226 static int mov_read_hdlr(MOVContext *c, AVIOContext *pb, MOVAtom atom)
799 {
800 AVStream *st;
801 uint32_t type;
802 uint32_t ctype;
803 int64_t title_size;
804 char *title_str;
805 int ret;
806
807 1226 avio_r8(pb); /* version */
808 1226 avio_rb24(pb); /* flags */
809
810 /* component type */
811 1226 ctype = avio_rl32(pb);
812 1226 type = avio_rl32(pb); /* component subtype */
813
814 1226 av_log(c->fc, AV_LOG_TRACE, "ctype=%s\n", av_fourcc2str(ctype));
815 1226 av_log(c->fc, AV_LOG_TRACE, "stype=%s\n", av_fourcc2str(type));
816
817
2/2
✓ Branch 0 taken 184 times.
✓ Branch 1 taken 1042 times.
1226 if (c->trak_index < 0) { // meta not inside a trak
818
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 173 times.
184 if (type == MKTAG('m','d','t','a')) {
819 11 c->found_hdlr_mdta = 1;
820 }
821 184 return 0;
822 }
823
824 1042 st = c->fc->streams[c->fc->nb_streams-1];
825
826
2/2
✓ Branch 0 taken 337 times.
✓ Branch 1 taken 705 times.
1042 if (type == MKTAG('v','i','d','e'))
827 337 st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
828
2/2
✓ Branch 0 taken 279 times.
✓ Branch 1 taken 426 times.
705 else if (type == MKTAG('s','o','u','n'))
829 279 st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
830
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 426 times.
426 else if (type == MKTAG('m','1','a',' '))
831 st->codecpar->codec_id = AV_CODEC_ID_MP2;
832
2/4
✓ Branch 0 taken 426 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 426 times.
426 else if ((type == MKTAG('s','u','b','p')) || (type == MKTAG('c','l','c','p')))
833 st->codecpar->codec_type = AVMEDIA_TYPE_SUBTITLE;
834
835 1042 avio_rb32(pb); /* component manufacture */
836 1042 avio_rb32(pb); /* component flags */
837 1042 avio_rb32(pb); /* component flags mask */
838
839 1042 title_size = atom.size - 24;
840
2/2
✓ Branch 0 taken 1039 times.
✓ Branch 1 taken 3 times.
1042 if (title_size > 0) {
841
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1039 times.
1039 if (title_size > FFMIN(INT_MAX, SIZE_MAX-1))
842 return AVERROR_INVALIDDATA;
843 1039 title_str = av_malloc(title_size + 1); /* Add null terminator */
844
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1039 times.
1039 if (!title_str)
845 return AVERROR(ENOMEM);
846
847 1039 ret = ffio_read_size(pb, title_str, title_size);
848
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1039 times.
1039 if (ret < 0) {
849 av_freep(&title_str);
850 return ret;
851 }
852 1039 title_str[title_size] = 0;
853
2/2
✓ Branch 0 taken 982 times.
✓ Branch 1 taken 57 times.
1039 if (title_str[0]) {
854
4/4
✓ Branch 0 taken 714 times.
✓ Branch 1 taken 268 times.
✓ Branch 2 taken 712 times.
✓ Branch 3 taken 2 times.
982 int off = (!c->isom && title_str[0] == title_size - 1);
855 // flag added so as to not set stream handler name if already set from mdia->hdlr
856 982 av_dict_set(&st->metadata, "handler_name", title_str + off, AV_DICT_DONT_OVERWRITE);
857 }
858 1039 av_freep(&title_str);
859 }
860
861 1042 return 0;
862 }
863
864 187 static int mov_read_esds(MOVContext *c, AVIOContext *pb, MOVAtom atom)
865 {
866 187 return ff_mov_read_esds(c->fc, pb);
867 }
868
869 8 static int mov_read_dac3(MOVContext *c, AVIOContext *pb, MOVAtom atom)
870 {
871 AVStream *st;
872 AVPacketSideData *sd;
873 enum AVAudioServiceType *ast;
874 int ac3info, acmod, lfeon, bsmod;
875 uint64_t mask;
876
877
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (c->fc->nb_streams < 1)
878 return 0;
879 8 st = c->fc->streams[c->fc->nb_streams-1];
880
881 8 sd = av_packet_side_data_new(&st->codecpar->coded_side_data,
882 8 &st->codecpar->nb_coded_side_data,
883 AV_PKT_DATA_AUDIO_SERVICE_TYPE,
884 sizeof(*ast), 0);
885
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (!sd)
886 return AVERROR(ENOMEM);
887
888 8 ast = (enum AVAudioServiceType*)sd->data;
889 8 ac3info = avio_rb24(pb);
890 8 bsmod = (ac3info >> 14) & 0x7;
891 8 acmod = (ac3info >> 11) & 0x7;
892 8 lfeon = (ac3info >> 10) & 0x1;
893
894 8 mask = ff_ac3_channel_layout_tab[acmod];
895
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 7 times.
8 if (lfeon)
896 1 mask |= AV_CH_LOW_FREQUENCY;
897 8 av_channel_layout_uninit(&st->codecpar->ch_layout);
898 8 av_channel_layout_from_mask(&st->codecpar->ch_layout, mask);
899
900 8 *ast = bsmod;
901
2/4
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 8 times.
8 if (st->codecpar->ch_layout.nb_channels > 1 && bsmod == 0x7)
902 *ast = AV_AUDIO_SERVICE_TYPE_KARAOKE;
903
904 8 return 0;
905 }
906
907 #if CONFIG_IAMFDEC
908 12 static int mov_read_iacb(MOVContext *c, AVIOContext *pb, MOVAtom atom)
909 {
910 AVStream *st;
911 MOVStreamContext *sc;
912 FFIOContext b;
913 AVIOContext *descriptor_pb;
914 AVDictionary *metadata;
915 IAMFContext *iamf;
916 int64_t start_time, duration;
917 unsigned descriptors_size;
918 int nb_frames, disposition;
919 int version, ret;
920
921
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (atom.size < 5)
922 return AVERROR_INVALIDDATA;
923
924
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (c->fc->nb_streams < 1)
925 return 0;
926
927 12 version = avio_r8(pb);
928
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (version != 1) {
929 av_log(c->fc, AV_LOG_ERROR, "%s configurationVersion %d",
930 version < 1 ? "invalid" : "unsupported", version);
931 return AVERROR_INVALIDDATA;
932 }
933
934 12 descriptors_size = ffio_read_leb(pb);
935
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)
936 return AVERROR_INVALIDDATA;
937
938 12 st = c->fc->streams[c->fc->nb_streams - 1];
939 12 sc = st->priv_data;
940
941
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (st->codecpar->extradata) {
942 av_log(c->fc, AV_LOG_WARNING, "ignoring iacb\n");
943 return 0;
944 }
945
946 12 sc->iamf = av_mallocz(sizeof(*sc->iamf));
947
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (!sc->iamf)
948 return AVERROR(ENOMEM);
949 12 iamf = &sc->iamf->iamf;
950
951 12 ret = ff_alloc_extradata(st->codecpar, descriptors_size);
952
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (ret < 0)
953 return ret;
954
955 12 ret = avio_read(pb, st->codecpar->extradata, descriptors_size);
956
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (ret != descriptors_size)
957 return ret < 0 ? ret : AVERROR_INVALIDDATA;
958
959 12 ffio_init_read_context(&b, st->codecpar->extradata, descriptors_size);
960 12 descriptor_pb = &b.pub;
961
962 12 ret = ff_iamfdec_read_descriptors(iamf, descriptor_pb, descriptors_size, c->fc);
963
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (ret < 0)
964 return ret;
965
966 12 metadata = st->metadata;
967 12 st->metadata = NULL;
968 12 start_time = st->start_time;
969 12 nb_frames = st->nb_frames;
970 12 duration = st->duration;
971 12 disposition = st->disposition;
972
973
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 12 times.
24 for (int i = 0; i < iamf->nb_audio_elements; i++) {
974 12 IAMFAudioElement *audio_element = iamf->audio_elements[i];
975 const AVIAMFAudioElement *element;
976 AVStreamGroup *stg =
977 12 avformat_stream_group_create(c->fc, AV_STREAM_GROUP_PARAMS_IAMF_AUDIO_ELEMENT, NULL);
978
979
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (!stg) {
980 ret = AVERROR(ENOMEM);
981 goto fail;
982 }
983
984 12 av_iamf_audio_element_free(&stg->params.iamf_audio_element);
985 12 stg->id = audio_element->audio_element_id;
986 /* Transfer ownership */
987 12 element = stg->params.iamf_audio_element = audio_element->element;
988 12 audio_element->element = NULL;
989
990
2/2
✓ Branch 0 taken 64 times.
✓ Branch 1 taken 12 times.
76 for (int j = 0; j < audio_element->nb_substreams; j++) {
991 64 IAMFSubStream *substream = &audio_element->substreams[j];
992 AVStream *stream;
993
994
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) {
995
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 10 times.
12 if (audio_element->layers[0].substream_count != 1)
996 2 disposition &= ~AV_DISPOSITION_DEFAULT;
997 12 stream = st;
998 } else
999 52 stream = avformat_new_stream(c->fc, NULL);
1000
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 64 times.
64 if (!stream) {
1001 ret = AVERROR(ENOMEM);
1002 goto fail;
1003 }
1004
1005 64 stream->start_time = start_time;
1006 64 stream->nb_frames = nb_frames;
1007 64 stream->duration = duration;
1008 64 stream->disposition = disposition;
1009
2/2
✓ Branch 0 taken 52 times.
✓ Branch 1 taken 12 times.
64 if (stream != st) {
1010 52 stream->priv_data = sc;
1011 52 sc->refcount++;
1012 }
1013
1014
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 56 times.
64 if (element->audio_element_type == AV_IAMF_AUDIO_ELEMENT_TYPE_SCENE)
1015 8 stream->disposition |= AV_DISPOSITION_DEPENDENT;
1016
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) {
1017 52 stream->disposition |= AV_DISPOSITION_DEPENDENT;
1018
2/2
✓ Branch 0 taken 46 times.
✓ Branch 1 taken 6 times.
52 if (audio_element->layers[0].substream_count == 1)
1019 46 stream->disposition &= ~AV_DISPOSITION_DEFAULT;
1020 }
1021
1022 64 ret = avcodec_parameters_copy(stream->codecpar, substream->codecpar);
1023
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 64 times.
64 if (ret < 0)
1024 goto fail;
1025
1026 64 stream->id = substream->audio_substream_id;
1027
1028 64 avpriv_set_pts_info(st, 64, 1, sc->time_scale);
1029
1030 64 ret = avformat_stream_group_add_stream(stg, stream);
1031
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 64 times.
64 if (ret < 0)
1032 goto fail;
1033 }
1034
1035 12 ret = av_dict_copy(&stg->metadata, metadata, 0);
1036
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (ret < 0)
1037 goto fail;
1038 }
1039
1040
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 12 times.
24 for (int i = 0; i < iamf->nb_mix_presentations; i++) {
1041 12 IAMFMixPresentation *mix_presentation = iamf->mix_presentations[i];
1042 12 const AVIAMFMixPresentation *mix = mix_presentation->cmix;
1043 AVStreamGroup *stg =
1044 12 avformat_stream_group_create(c->fc, AV_STREAM_GROUP_PARAMS_IAMF_MIX_PRESENTATION, NULL);
1045
1046
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (!stg) {
1047 ret = AVERROR(ENOMEM);
1048 goto fail;
1049 }
1050
1051 12 av_iamf_mix_presentation_free(&stg->params.iamf_mix_presentation);
1052 12 stg->id = mix_presentation->mix_presentation_id;
1053 /* Transfer ownership */
1054 12 stg->params.iamf_mix_presentation = mix_presentation->mix;
1055 12 mix_presentation->mix = NULL;
1056
1057
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 12 times.
26 for (int j = 0; j < mix->nb_submixes; j++) {
1058 14 const AVIAMFSubmix *submix = mix->submixes[j];
1059
1060
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 14 times.
28 for (int k = 0; k < submix->nb_elements; k++) {
1061 14 const AVIAMFSubmixElement *submix_element = submix->elements[k];
1062 14 const AVStreamGroup *audio_element = NULL;
1063
1064
1/2
✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
14 for (int l = 0; l < c->fc->nb_stream_groups; l++)
1065
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 &&
1066
1/2
✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
14 c->fc->stream_groups[l]->id == submix_element->audio_element_id) {
1067 14 audio_element = c->fc->stream_groups[l];
1068 14 break;
1069 }
1070
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
14 av_assert0(audio_element);
1071
1072
2/2
✓ Branch 0 taken 66 times.
✓ Branch 1 taken 14 times.
80 for (int l = 0; l < audio_element->nb_streams; l++) {
1073 66 ret = avformat_stream_group_add_stream(stg, audio_element->streams[l]);
1074
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))
1075 goto fail;
1076 }
1077 }
1078 }
1079
1080 12 ret = av_dict_copy(&stg->metadata, metadata, 0);
1081
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (ret < 0)
1082 goto fail;
1083 }
1084
1085 12 ret = 0;
1086 12 fail:
1087 12 av_dict_free(&metadata);
1088
1089 12 return ret;
1090 }
1091 #endif
1092
1093 5 static int mov_read_srat(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1094 {
1095 AVStream *st;
1096 int32_t sample_rate;
1097
1098
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)
1099 return 0;
1100
1101 5 st = c->fc->streams[c->fc->nb_streams-1];
1102
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (st->codecpar->codec_type != AVMEDIA_TYPE_AUDIO) {
1103 av_log(c->fc, AV_LOG_WARNING, "'srat' within non-audio sample entry, skip\n");
1104 return 0;
1105 }
1106
1107
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (!c->isom) {
1108 av_log(c->fc, AV_LOG_WARNING, "'srat' within non-isom, skip\n");
1109 return 0;
1110 }
1111
1112 5 avio_skip(pb, 4); // version+flags
1113 5 sample_rate = avio_rb32(pb);
1114
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 if (sample_rate > 0) {
1115 5 av_log(c->fc, AV_LOG_DEBUG,
1116 "overwrite sample rate from %d to %d by 'srat'\n",
1117 5 st->codecpar->sample_rate, sample_rate);
1118 5 st->codecpar->sample_rate = sample_rate;
1119 } else {
1120 av_log(c->fc, AV_LOG_WARNING,
1121 "ignore invalid sample rate %d in 'srat'\n", sample_rate);
1122 }
1123
1124 5 return 0;
1125 }
1126
1127 4 static int mov_read_dec3(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1128 {
1129 AVStream *st;
1130 AVPacketSideData *sd;
1131 enum AVAudioServiceType *ast;
1132 int eac3info, acmod, lfeon, bsmod;
1133 uint64_t mask;
1134
1135
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (c->fc->nb_streams < 1)
1136 return 0;
1137 4 st = c->fc->streams[c->fc->nb_streams-1];
1138
1139 4 sd = av_packet_side_data_new(&st->codecpar->coded_side_data,
1140 4 &st->codecpar->nb_coded_side_data,
1141 AV_PKT_DATA_AUDIO_SERVICE_TYPE,
1142 sizeof(*ast), 0);
1143
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!sd)
1144 return AVERROR(ENOMEM);
1145
1146 4 ast = (enum AVAudioServiceType*)sd->data;
1147
1148 /* No need to parse fields for additional independent substreams and its
1149 * associated dependent substreams since libavcodec's E-AC-3 decoder
1150 * does not support them yet. */
1151 4 avio_rb16(pb); /* data_rate and num_ind_sub */
1152 4 eac3info = avio_rb24(pb);
1153 4 bsmod = (eac3info >> 12) & 0x1f;
1154 4 acmod = (eac3info >> 9) & 0x7;
1155 4 lfeon = (eac3info >> 8) & 0x1;
1156
1157 4 mask = ff_ac3_channel_layout_tab[acmod];
1158
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 3 times.
4 if (lfeon)
1159 1 mask |= AV_CH_LOW_FREQUENCY;
1160 4 av_channel_layout_uninit(&st->codecpar->ch_layout);
1161 4 av_channel_layout_from_mask(&st->codecpar->ch_layout, mask);
1162
1163 4 *ast = bsmod;
1164
2/4
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
4 if (st->codecpar->ch_layout.nb_channels > 1 && bsmod == 0x7)
1165 *ast = AV_AUDIO_SERVICE_TYPE_KARAOKE;
1166
1167 4 return 0;
1168 }
1169
1170 /* Maps the DTS `StreamConstruction` field (ETSI TS 102 114 Table E-2) to the
1171 * coarse FFmpeg DTS profile enum. Extension-substream XLL maps to HD_MA;
1172 * extension-substream XXCH, X96, or XBR maps to HD_HRA; core-substream XCH or
1173 * XXCH maps to ES; core-substream X96 maps to 96/24; a core component alone
1174 * maps to DTS; and extension-substream LBR maps to Express. Value 0 (undefined)
1175 * and values outside 1..21 map to AV_PROFILE_UNKNOWN. */
1176 static int mov_dts_stream_construction_to_profile(unsigned int sc)
1177 {
1178 static const int profile[22] = {
1179 [ 1] = AV_PROFILE_DTS, /* core Core */
1180 [ 2] = AV_PROFILE_DTS_ES, /* core Core + core XCH */
1181 [ 3] = AV_PROFILE_DTS_ES, /* core Core + core XXCH */
1182 [ 4] = AV_PROFILE_DTS_96_24, /* core Core + core X96 */
1183 [ 5] = AV_PROFILE_DTS_HD_HRA, /* core Core + ext XXCH */
1184 [ 6] = AV_PROFILE_DTS_HD_HRA, /* core Core + ext XBR */
1185 [ 7] = AV_PROFILE_DTS_HD_HRA, /* core Core + core XCH + ext XBR */
1186 [ 8] = AV_PROFILE_DTS_HD_HRA, /* core Core + core XXCH + ext XBR */
1187 [ 9] = AV_PROFILE_DTS_HD_HRA, /* core Core + ext XXCH + ext XBR */
1188 [10] = AV_PROFILE_DTS_HD_HRA, /* core Core + ext X96 */
1189 [11] = AV_PROFILE_DTS_HD_HRA, /* core Core + core XCH + ext X96 */
1190 [12] = AV_PROFILE_DTS_HD_HRA, /* core Core + core XXCH + ext X96 */
1191 [13] = AV_PROFILE_DTS_HD_HRA, /* core Core + ext XXCH + ext X96 */
1192 [14] = AV_PROFILE_DTS_HD_MA, /* core Core + ext XLL */
1193 [15] = AV_PROFILE_DTS_HD_MA, /* core Core + core XCH + ext XLL */
1194 [16] = AV_PROFILE_DTS_HD_MA, /* core Core + core X96 + ext XLL */
1195 [17] = AV_PROFILE_DTS_HD_MA, /* ext XLL */
1196 [18] = AV_PROFILE_DTS_EXPRESS, /* ext LBR */
1197 [19] = AV_PROFILE_DTS, /* ext Core */
1198 [20] = AV_PROFILE_DTS_HD_HRA, /* ext Core + ext XXCH */
1199 [21] = AV_PROFILE_DTS_HD_MA, /* ext Core + ext XLL */
1200 };
1201 if (!sc || sc > 21)
1202 return AV_PROFILE_UNKNOWN;
1203 return profile[sc];
1204 }
1205
1206 /* Maps the 16-bit DTS `ChannelLayout` bitmask (ETSI TS 102 114 Table E-5) to an
1207 * ffmpeg channel mask. Pair bits follow Table 7-10 / DCA_SPEAKER_PAIR_*;
1208 * LwRw (0x0400) and LssRss (0x0800) must not collapse onto SIDE like LsRs. */
1209 static uint64_t mov_dts_channel_layout_to_mask(unsigned int code)
1210 {
1211 static const struct { unsigned int dts; uint64_t av; } map[] = {
1212 { 0x0001, AV_CH_FRONT_CENTER },
1213 { 0x0002, AV_CH_FRONT_LEFT | AV_CH_FRONT_RIGHT },
1214 { 0x0004, AV_CH_SIDE_LEFT | AV_CH_SIDE_RIGHT },
1215 { 0x0008, AV_CH_LOW_FREQUENCY },
1216 { 0x0010, AV_CH_BACK_CENTER },
1217 { 0x0020, AV_CH_TOP_FRONT_LEFT | AV_CH_TOP_FRONT_RIGHT },
1218 { 0x0040, AV_CH_BACK_LEFT | AV_CH_BACK_RIGHT },
1219 { 0x0080, AV_CH_TOP_FRONT_CENTER },
1220 { 0x0100, AV_CH_TOP_CENTER },
1221 { 0x0200, AV_CH_FRONT_LEFT_OF_CENTER | AV_CH_FRONT_RIGHT_OF_CENTER },
1222 { 0x0400, AV_CH_WIDE_LEFT | AV_CH_WIDE_RIGHT },
1223 { 0x0800, AV_CH_SIDE_SURROUND_LEFT | AV_CH_SIDE_SURROUND_RIGHT },
1224 { 0x1000, AV_CH_LOW_FREQUENCY_2 },
1225 { 0x2000, AV_CH_TOP_SIDE_LEFT | AV_CH_TOP_SIDE_RIGHT },
1226 { 0x4000, AV_CH_TOP_BACK_CENTER },
1227 { 0x8000, AV_CH_TOP_BACK_LEFT | AV_CH_TOP_BACK_RIGHT },
1228 };
1229 uint64_t mask = 0;
1230 int i;
1231 for (i = 0; i < FF_ARRAY_ELEMS(map); i++)
1232 if (code & map[i].dts)
1233 mask |= map[i].av;
1234 return mask;
1235 }
1236
1237 static int mov_read_ddts(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1238 {
1239 #define DDTS_SIZE 20
1240 uint8_t buf[DDTS_SIZE + AV_INPUT_BUFFER_PADDING_SIZE];
1241 AVStream *st = NULL;
1242 uint32_t frame_duration_code = 0;
1243 uint32_t channel_layout_code = 0;
1244 uint64_t channel_layout_mask;
1245 unsigned int stream_construction;
1246 unsigned int representation_type;
1247 GetBitContext gb;
1248 int ret;
1249
1250 if ((ret = ffio_read_size(pb, buf, DDTS_SIZE)) < 0)
1251 return ret;
1252
1253 init_get_bits(&gb, buf, 8 * DDTS_SIZE);
1254
1255 if (c->fc->nb_streams < 1) {
1256 return 0;
1257 }
1258 st = c->fc->streams[c->fc->nb_streams-1];
1259
1260 st->codecpar->sample_rate = get_bits_long(&gb, 32);
1261 if (st->codecpar->sample_rate <= 0) {
1262 av_log(c->fc, AV_LOG_ERROR, "Invalid sample rate %d\n", st->codecpar->sample_rate);
1263 return AVERROR_INVALIDDATA;
1264 }
1265 skip_bits_long(&gb, 32); /* max bitrate */
1266 st->codecpar->bit_rate = get_bits_long(&gb, 32);
1267 st->codecpar->bits_per_coded_sample = get_bits(&gb, 8);
1268 frame_duration_code = get_bits(&gb, 2);
1269 stream_construction = get_bits(&gb, 5); /* Table E-2 - profile source */
1270 skip_bits(&gb, 1); /* CoreLFEPresent */
1271 skip_bits(&gb, 6); /* CoreLayout */
1272 skip_bits(&gb, 14); /* CoreSize */
1273 skip_bits(&gb, 1); /* StereoDownmix */
1274 representation_type = get_bits(&gb, 3);
1275 channel_layout_code = get_bits(&gb, 16);
1276
1277 st->codecpar->frame_size =
1278 (frame_duration_code == 0) ? 512 :
1279 (frame_duration_code == 1) ? 1024 :
1280 (frame_duration_code == 2) ? 2048 :
1281 (frame_duration_code == 3) ? 4096 : 0;
1282
1283 /* Publish StreamConstruction as codecpar->profile, including for encrypted
1284 * tracks where frame headers cannot be inspected. */
1285 st->codecpar->profile = mov_dts_stream_construction_to_profile(stream_construction);
1286
1287 channel_layout_mask = mov_dts_channel_layout_to_mask(channel_layout_code);
1288 if (channel_layout_mask) {
1289 av_channel_layout_uninit(&st->codecpar->ch_layout);
1290 av_channel_layout_from_mask(&st->codecpar->ch_layout, channel_layout_mask);
1291 } else if (representation_type == 2 || representation_type == 3) {
1292 av_channel_layout_uninit(&st->codecpar->ch_layout);
1293 st->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO;
1294 }
1295
1296 return 0;
1297 }
1298
1299 50 static int mov_read_chan(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1300 {
1301 AVStream *st;
1302
1303
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 50 times.
50 if (c->fc->nb_streams < 1)
1304 return 0;
1305 50 st = c->fc->streams[c->fc->nb_streams-1];
1306
1307
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 50 times.
50 if (atom.size < 16)
1308 return 0;
1309
1310 /* skip version and flags */
1311 50 avio_skip(pb, 4);
1312
1313 50 ff_mov_read_chan(c->fc, pb, st, atom.size - 4);
1314
1315 50 return 0;
1316 }
1317
1318 5 static int mov_read_chnl(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1319 {
1320 5 int64_t end = av_sat_add64(avio_tell(pb), atom.size);
1321 int version, flags;
1322 int ret;
1323 AVStream *st;
1324
1325
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (c->fc->nb_streams < 1)
1326 return 0;
1327 5 st = c->fc->streams[c->fc->nb_streams-1];
1328
1329 5 version = avio_r8(pb);
1330 5 flags = avio_rb24(pb);
1331
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) {
1332 av_log(c->fc, AV_LOG_WARNING,
1333 "Unsupported 'chnl' box with version %d, flags: %#x\n",
1334 version, flags);
1335 return 0;
1336 }
1337
1338 5 ret = ff_mov_read_chnl(c->fc, pb, st, version);
1339
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (ret < 0) {
1340 avio_seek(pb, end, SEEK_SET);
1341 return 0;
1342 }
1343
1344
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
5 if (avio_tell(pb) != end) {
1345 av_log(c->fc, AV_LOG_WARNING, "skip %" PRId64 " bytes of unknown data inside chnl\n",
1346 end - avio_tell(pb));
1347 avio_seek(pb, end, SEEK_SET);
1348 }
1349 5 return ret;
1350 }
1351
1352 2 static int mov_read_wfex(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1353 {
1354 AVStream *st;
1355 int ret;
1356
1357
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (c->fc->nb_streams < 1)
1358 return 0;
1359 2 st = c->fc->streams[c->fc->nb_streams-1];
1360
1361
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)
1362 av_log(c->fc, AV_LOG_WARNING, "get_wav_header failed\n");
1363
1364 2 return ret;
1365 }
1366
1367 18 static int mov_read_clap(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1368 {
1369 AVStream *st;
1370 HEIFItem *item;
1371 AVPacketSideData *sd;
1372 18 int width, height, err = 0;
1373 AVRational aperture_width, aperture_height, horiz_off, vert_off;
1374 AVRational pc_x, pc_y;
1375 uint64_t top, bottom, left, right;
1376
1377 18 item = get_heif_item(c, c->cur_item_id);
1378 18 st = get_curr_st(c);
1379
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (!st)
1380 return 0;
1381
1382 18 width = st->codecpar->width;
1383 18 height = st->codecpar->height;
1384
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) {
1385 6 width = item->width;
1386 6 height = item->height;
1387 }
1388
2/4
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 18 times.
18 if (!width || !height) {
1389 err = AVERROR_INVALIDDATA;
1390 goto fail;
1391 }
1392
1393 18 aperture_width.num = avio_rb32(pb);
1394 18 aperture_width.den = avio_rb32(pb);
1395 18 aperture_height.num = avio_rb32(pb);
1396 18 aperture_height.den = avio_rb32(pb);
1397
1398 18 horiz_off.num = avio_rb32(pb);
1399 18 horiz_off.den = avio_rb32(pb);
1400 18 vert_off.num = avio_rb32(pb);
1401 18 vert_off.den = avio_rb32(pb);
1402
1403
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 ||
1404
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 ||
1405
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) {
1406 err = AVERROR_INVALIDDATA;
1407 goto fail;
1408 }
1409
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) ||
1410 15 (av_cmp_q((AVRational) { height, 1 }, aperture_height) < 0)) {
1411 3 err = AVERROR_INVALIDDATA;
1412 3 goto fail;
1413 }
1414 15 av_log(c->fc, AV_LOG_TRACE, "clap: apertureWidth %d/%d, apertureHeight %d/%d "
1415 "horizOff %d/%d vertOff %d/%d\n",
1416 aperture_width.num, aperture_width.den, aperture_height.num, aperture_height.den,
1417 horiz_off.num, horiz_off.den, vert_off.num, vert_off.den);
1418
1419 15 pc_x = av_mul_q((AVRational) { width - 1, 1 }, (AVRational) { 1, 2 });
1420 15 pc_x = av_add_q(pc_x, horiz_off);
1421 15 pc_y = av_mul_q((AVRational) { height - 1, 1 }, (AVRational) { 1, 2 });
1422 15 pc_y = av_add_q(pc_y, vert_off);
1423
1424 15 aperture_width = av_sub_q(aperture_width, (AVRational) { 1, 1 });
1425 15 aperture_width = av_mul_q(aperture_width, (AVRational) { 1, 2 });
1426 15 aperture_height = av_sub_q(aperture_height, (AVRational) { 1, 1 });
1427 15 aperture_height = av_mul_q(aperture_height, (AVRational) { 1, 2 });
1428
1429 15 left = av_q2d(av_sub_q(pc_x, aperture_width));
1430 15 right = av_q2d(av_add_q(pc_x, aperture_width));
1431 15 top = av_q2d(av_sub_q(pc_y, aperture_height));
1432 15 bottom = av_q2d(av_add_q(pc_y, aperture_height));
1433
1434
1/2
✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
15 if (bottom > (height - 1) ||
1435
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 15 times.
15 right > (width - 1)) {
1436 err = AVERROR_INVALIDDATA;
1437 goto fail;
1438 }
1439
1440 15 bottom = height - 1 - bottom;
1441 15 right = width - 1 - right;
1442
1443
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 9 times.
15 if (!(left | right | top | bottom))
1444 6 return 0;
1445
1446
1/2
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
9 if ((left + right) >= width ||
1447
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 (top + bottom) >= height) {
1448 err = AVERROR_INVALIDDATA;
1449 goto fail;
1450 }
1451
1452 9 sd = av_packet_side_data_new(&st->codecpar->coded_side_data,
1453 9 &st->codecpar->nb_coded_side_data,
1454 AV_PKT_DATA_FRAME_CROPPING,
1455 sizeof(uint32_t) * 4, 0);
1456
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if (!sd)
1457 return AVERROR(ENOMEM);
1458
1459 9 AV_WL32A(sd->data, top);
1460 9 AV_WL32A(sd->data + 4, bottom);
1461 9 AV_WL32A(sd->data + 8, left);
1462 9 AV_WL32A(sd->data + 12, right);
1463
1464 12 fail:
1465
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 9 times.
12 if (err < 0) {
1466 3 int explode = !!(c->fc->error_recognition & AV_EF_EXPLODE);
1467
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");
1468
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if (!explode)
1469 3 err = 0;
1470 }
1471
1472 12 return err;
1473 }
1474
1475 /* This atom overrides any previously set aspect ratio */
1476 90 static int mov_read_pasp(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1477 {
1478 90 const int num = avio_rb32(pb);
1479 90 const int den = avio_rb32(pb);
1480 AVStream *st;
1481 MOVStreamContext *sc;
1482
1483
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 90 times.
90 if (c->fc->nb_streams < 1)
1484 return 0;
1485 90 st = c->fc->streams[c->fc->nb_streams-1];
1486 90 sc = st->priv_data;
1487
1488 90 av_log(c->fc, AV_LOG_TRACE, "pasp: hSpacing %d, vSpacing %d\n", num, den);
1489
1490
2/2
✓ Branch 0 taken 88 times.
✓ Branch 1 taken 2 times.
90 if (den != 0) {
1491 88 sc->h_spacing = num;
1492 88 sc->v_spacing = den;
1493 }
1494 90 return 0;
1495 }
1496
1497 /* this atom contains actual media data */
1498 1026 static int mov_read_mdat(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1499 {
1500
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1026 times.
1026 if (atom.size == 0) /* wrong one (MP4) */
1501 return 0;
1502 1026 c->found_mdat=1;
1503 1026 return 0; /* now go for moov */
1504 }
1505
1506 #define DRM_BLOB_SIZE 56
1507
1508 static int mov_read_adrm(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1509 {
1510 uint8_t intermediate_key[20];
1511 uint8_t intermediate_iv[20];
1512 uint8_t input[64];
1513 uint8_t output[64];
1514 uint8_t file_checksum[20];
1515 uint8_t calculated_checksum[20];
1516 char checksum_string[2 * sizeof(file_checksum) + 1];
1517 struct AVSHA *sha;
1518 int i;
1519 int ret = 0;
1520 uint8_t *activation_bytes = c->activation_bytes;
1521 uint8_t *fixed_key = c->audible_fixed_key;
1522
1523 c->aax_mode = 1;
1524
1525 sha = av_sha_alloc();
1526 if (!sha)
1527 return AVERROR(ENOMEM);
1528 av_free(c->aes_decrypt);
1529 c->aes_decrypt = av_aes_alloc();
1530 if (!c->aes_decrypt) {
1531 ret = AVERROR(ENOMEM);
1532 goto fail;
1533 }
1534
1535 /* drm blob processing */
1536 avio_read(pb, output, 8); // go to offset 8, absolute position 0x251
1537 avio_read(pb, input, DRM_BLOB_SIZE);
1538 avio_read(pb, output, 4); // go to offset 4, absolute position 0x28d
1539 ret = ffio_read_size(pb, file_checksum, 20);
1540 if (ret < 0)
1541 goto fail;
1542
1543 // required by external tools
1544 ff_data_to_hex(checksum_string, file_checksum, sizeof(file_checksum), 1);
1545 av_log(c->fc, AV_LOG_INFO, "[aax] file checksum == %s\n", checksum_string);
1546
1547 /* verify activation data */
1548 if (!activation_bytes) {
1549 av_log(c->fc, AV_LOG_WARNING, "[aax] activation_bytes option is missing!\n");
1550 ret = 0; /* allow ffprobe to continue working on .aax files */
1551 goto fail;
1552 }
1553 if (c->activation_bytes_size != 4) {
1554 av_log(c->fc, AV_LOG_FATAL, "[aax] activation_bytes value needs to be 4 bytes!\n");
1555 ret = AVERROR(EINVAL);
1556 goto fail;
1557 }
1558
1559 /* verify fixed key */
1560 if (c->audible_fixed_key_size != 16) {
1561 av_log(c->fc, AV_LOG_FATAL, "[aax] audible_fixed_key value needs to be 16 bytes!\n");
1562 ret = AVERROR(EINVAL);
1563 goto fail;
1564 }
1565
1566 /* AAX (and AAX+) key derivation */
1567 av_sha_init(sha, 160);
1568 av_sha_update(sha, fixed_key, 16);
1569 av_sha_update(sha, activation_bytes, 4);
1570 av_sha_final(sha, intermediate_key);
1571 av_sha_init(sha, 160);
1572 av_sha_update(sha, fixed_key, 16);
1573 av_sha_update(sha, intermediate_key, 20);
1574 av_sha_update(sha, activation_bytes, 4);
1575 av_sha_final(sha, intermediate_iv);
1576 av_sha_init(sha, 160);
1577 av_sha_update(sha, intermediate_key, 16);
1578 av_sha_update(sha, intermediate_iv, 16);
1579 av_sha_final(sha, calculated_checksum);
1580 if (memcmp(calculated_checksum, file_checksum, 20)) { // critical error
1581 av_log(c->fc, AV_LOG_ERROR, "[aax] mismatch in checksums!\n");
1582 ret = AVERROR_INVALIDDATA;
1583 goto fail;
1584 }
1585 av_aes_init(c->aes_decrypt, intermediate_key, 128, 1);
1586 av_aes_crypt(c->aes_decrypt, output, input, DRM_BLOB_SIZE >> 4, intermediate_iv, 1);
1587 for (i = 0; i < 4; i++) {
1588 // file data (in output) is stored in big-endian mode
1589 if (activation_bytes[i] != output[3 - i]) { // critical error
1590 av_log(c->fc, AV_LOG_ERROR, "[aax] error in drm blob decryption!\n");
1591 ret = AVERROR_INVALIDDATA;
1592 goto fail;
1593 }
1594 }
1595 memcpy(c->file_key, output + 8, 16);
1596 memcpy(input, output + 26, 16);
1597 av_sha_init(sha, 160);
1598 av_sha_update(sha, input, 16);
1599 av_sha_update(sha, c->file_key, 16);
1600 av_sha_update(sha, fixed_key, 16);
1601 av_sha_final(sha, c->file_iv);
1602
1603 fail:
1604 av_free(sha);
1605
1606 return ret;
1607 }
1608
1609 static int mov_aaxc_crypto(MOVContext *c)
1610 {
1611 if (c->audible_key_size != 16) {
1612 av_log(c->fc, AV_LOG_FATAL, "[aaxc] audible_key value needs to be 16 bytes!\n");
1613 return AVERROR(EINVAL);
1614 }
1615
1616 if (c->audible_iv_size != 16) {
1617 av_log(c->fc, AV_LOG_FATAL, "[aaxc] audible_iv value needs to be 16 bytes!\n");
1618 return AVERROR(EINVAL);
1619 }
1620
1621 c->aes_decrypt = av_aes_alloc();
1622 if (!c->aes_decrypt) {
1623 return AVERROR(ENOMEM);
1624 }
1625
1626 memcpy(c->file_key, c->audible_key, 16);
1627 memcpy(c->file_iv, c->audible_iv, 16);
1628 c->aax_mode = 1;
1629
1630 return 0;
1631 }
1632
1633 // Audible AAX (and AAX+) bytestream decryption
1634 static int aax_filter(uint8_t *input, int size, MOVContext *c)
1635 {
1636 int blocks = 0;
1637 unsigned char iv[16];
1638
1639 memcpy(iv, c->file_iv, 16); // iv is overwritten
1640 blocks = size >> 4; // trailing bytes are not encrypted!
1641 av_aes_init(c->aes_decrypt, c->file_key, 128, 1);
1642 av_aes_crypt(c->aes_decrypt, input, input, blocks, iv, 1);
1643
1644 return 0;
1645 }
1646
1647 /* read major brand, minor version and compatible brands and store them as metadata */
1648 526 static int mov_read_ftyp(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1649 {
1650 uint32_t minor_ver;
1651 int comp_brand_size;
1652 char* comp_brands_str;
1653 526 uint8_t type[5] = {0};
1654 526 int ret = ffio_read_size(pb, type, 4);
1655
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 526 times.
526 if (ret < 0)
1656 return ret;
1657
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 526 times.
526 if (c->fc->nb_streams) {
1658 if (c->fc->strict_std_compliance >= FF_COMPLIANCE_STRICT)
1659 return AVERROR_INVALIDDATA;
1660 av_log(c->fc, AV_LOG_DEBUG, "Ignoring duplicate FTYP\n");
1661 return 0;
1662 }
1663
1664
2/2
✓ Branch 0 taken 284 times.
✓ Branch 1 taken 242 times.
526 if (strcmp(type, "qt "))
1665 284 c->isom = 1;
1666 526 av_log(c->fc, AV_LOG_DEBUG, "ISO: File Type Major Brand: %.4s\n",(char *)&type);
1667 526 av_dict_set(&c->fc->metadata, "major_brand", type, 0);
1668 526 minor_ver = avio_rb32(pb); /* minor version */
1669 526 av_dict_set_int(&c->fc->metadata, "minor_version", minor_ver, 0);
1670
1671 526 comp_brand_size = atom.size - 8;
1672
2/4
✓ Branch 0 taken 526 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 526 times.
526 if (comp_brand_size < 0 || comp_brand_size == INT_MAX)
1673 return AVERROR_INVALIDDATA;
1674 526 comp_brands_str = av_malloc(comp_brand_size + 1); /* Add null terminator */
1675
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 526 times.
526 if (!comp_brands_str)
1676 return AVERROR(ENOMEM);
1677
1678 526 ret = ffio_read_size(pb, comp_brands_str, comp_brand_size);
1679
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 526 times.
526 if (ret < 0) {
1680 av_freep(&comp_brands_str);
1681 return ret;
1682 }
1683 526 comp_brands_str[comp_brand_size] = 0;
1684 526 av_dict_set(&c->fc->metadata, "compatible_brands",
1685 comp_brands_str, AV_DICT_DONT_STRDUP_VAL);
1686
1687 // Logic for handling Audible's .aaxc files
1688
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 526 times.
526 if (!strcmp(type, "aaxc")) {
1689 mov_aaxc_crypto(c);
1690 }
1691
1692 526 return 0;
1693 }
1694
1695 /* this atom should contain all header atoms */
1696 554 static int mov_read_moov(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1697 {
1698 int ret;
1699
1700
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 554 times.
554 if (c->found_moov) {
1701 av_log(c->fc, AV_LOG_WARNING, "Found duplicated MOOV Atom. Skipped it\n");
1702 avio_skip(pb, atom.size);
1703 return 0;
1704 }
1705
1706
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 554 times.
554 if ((ret = mov_read_default(c, pb, atom)) < 0)
1707 return ret;
1708 /* we parsed the 'moov' atom, we can terminate the parsing as soon as we find the 'mdat' */
1709 /* so we don't parse the whole file if over a network */
1710 554 c->found_moov=1;
1711 554 return 0; /* now go for mdat */
1712 }
1713
1714 3207 static MOVFragmentStreamInfo * get_frag_stream_info(
1715 MOVFragmentIndex *frag_index,
1716 int index,
1717 int id)
1718 {
1719 int i;
1720 MOVFragmentIndexItem * item;
1721
1722
2/4
✓ Branch 0 taken 3207 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 3207 times.
3207 if (index < 0 || index >= frag_index->nb_items)
1723 return NULL;
1724 3207 item = &frag_index->item[index];
1725
1/2
✓ Branch 0 taken 3391 times.
✗ Branch 1 not taken.
3391 for (i = 0; i < item->nb_stream_info; i++)
1726
2/2
✓ Branch 0 taken 3207 times.
✓ Branch 1 taken 184 times.
3391 if (item->stream_info[i].id == id)
1727 3207 return &item->stream_info[i];
1728
1729 // This shouldn't happen
1730 return NULL;
1731 }
1732
1733 499 static void set_frag_stream(MOVFragmentIndex *frag_index, int id)
1734 {
1735 int i;
1736 MOVFragmentIndexItem * item;
1737
1738
1/2
✓ Branch 0 taken 499 times.
✗ Branch 1 not taken.
499 if (frag_index->current < 0 ||
1739
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 499 times.
499 frag_index->current >= frag_index->nb_items)
1740 return;
1741
1742 499 item = &frag_index->item[frag_index->current];
1743
1/2
✓ Branch 0 taken 558 times.
✗ Branch 1 not taken.
558 for (i = 0; i < item->nb_stream_info; i++)
1744
2/2
✓ Branch 0 taken 499 times.
✓ Branch 1 taken 59 times.
558 if (item->stream_info[i].id == id) {
1745 499 item->current = i;
1746 499 return;
1747 }
1748
1749 // id not found. This shouldn't happen.
1750 item->current = -1;
1751 }
1752
1753 1436 static MOVFragmentStreamInfo * get_current_frag_stream_info(
1754 MOVFragmentIndex *frag_index)
1755 {
1756 MOVFragmentIndexItem *item;
1757
1/2
✓ Branch 0 taken 1436 times.
✗ Branch 1 not taken.
1436 if (frag_index->current < 0 ||
1758
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 1430 times.
1436 frag_index->current >= frag_index->nb_items)
1759 6 return NULL;
1760
1761 1430 item = &frag_index->item[frag_index->current];
1762
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)
1763 1430 return &item->stream_info[item->current];
1764
1765 // This shouldn't happen
1766 return NULL;
1767 }
1768
1769 899 static int search_frag_moof_offset(MOVFragmentIndex *frag_index, int64_t offset)
1770 {
1771 int a, b, m;
1772 int64_t moof_offset;
1773
1774 // Optimize for appending new entries
1775
2/2
✓ Branch 0 taken 881 times.
✓ Branch 1 taken 18 times.
899 if (!frag_index->nb_items ||
1776
2/2
✓ Branch 0 taken 464 times.
✓ Branch 1 taken 417 times.
881 frag_index->item[frag_index->nb_items - 1].moof_offset < offset)
1777 482 return frag_index->nb_items;
1778
1779 417 a = -1;
1780 417 b = frag_index->nb_items;
1781
1782
2/2
✓ Branch 0 taken 2677 times.
✓ Branch 1 taken 417 times.
3094 while (b - a > 1) {
1783 2677 m = (a + b) >> 1;
1784 2677 moof_offset = frag_index->item[m].moof_offset;
1785
2/2
✓ Branch 0 taken 747 times.
✓ Branch 1 taken 1930 times.
2677 if (moof_offset >= offset)
1786 747 b = m;
1787
2/2
✓ Branch 0 taken 2345 times.
✓ Branch 1 taken 332 times.
2677 if (moof_offset <= offset)
1788 2345 a = m;
1789 }
1790 417 return b;
1791 }
1792
1793 7 static int64_t get_stream_info_time(MOVFragmentStreamInfo * frag_stream_info)
1794 {
1795
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 av_assert0(frag_stream_info);
1796
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (frag_stream_info->sidx_pts != AV_NOPTS_VALUE)
1797 return frag_stream_info->sidx_pts;
1798
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 3 times.
7 if (frag_stream_info->first_tfra_pts != AV_NOPTS_VALUE)
1799 4 return frag_stream_info->first_tfra_pts;
1800 3 return frag_stream_info->tfdt_dts;
1801 }
1802
1803 226 static int64_t get_frag_time(AVFormatContext *s, AVStream *dst_st,
1804 MOVFragmentIndex *frag_index, int index)
1805 {
1806 MOVFragmentStreamInfo * frag_stream_info;
1807 226 MOVStreamContext *sc = dst_st->priv_data;
1808 int64_t timestamp;
1809 int i, j;
1810
1811 // If the stream is referenced by any sidx, limit the search
1812 // to fragments that referenced this stream in the sidx
1813
2/2
✓ Branch 0 taken 219 times.
✓ Branch 1 taken 7 times.
226 if (sc->has_sidx) {
1814 219 frag_stream_info = get_frag_stream_info(frag_index, index, sc->id);
1815
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 219 times.
219 if (!frag_stream_info)
1816 return AV_NOPTS_VALUE;
1817
1/2
✓ Branch 0 taken 219 times.
✗ Branch 1 not taken.
219 if (frag_stream_info->sidx_pts != AV_NOPTS_VALUE)
1818 219 return frag_stream_info->sidx_pts;
1819 if (frag_stream_info->first_tfra_pts != AV_NOPTS_VALUE)
1820 return frag_stream_info->first_tfra_pts;
1821 return frag_stream_info->sidx_pts;
1822 }
1823
1824
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++) {
1825
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)
1826 5 continue;
1827 7 AVStream *frag_stream = NULL;
1828 7 frag_stream_info = &frag_index->item[index].stream_info[i];
1829
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 7 times.
21 for (j = 0; j < s->nb_streams; j++) {
1830 14 MOVStreamContext *sc2 = s->streams[j]->priv_data;
1831
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 7 times.
14 if (sc2->id == frag_stream_info->id)
1832 7 frag_stream = s->streams[j];
1833 }
1834
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (!frag_stream) {
1835 av_log(s, AV_LOG_WARNING, "No stream matching sidx ID found.\n");
1836 continue;
1837 }
1838 7 timestamp = get_stream_info_time(frag_stream_info);
1839
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 3 times.
7 if (timestamp != AV_NOPTS_VALUE)
1840 4 return av_rescale_q(timestamp, frag_stream->time_base, dst_st->time_base);
1841 }
1842 3 return AV_NOPTS_VALUE;
1843 }
1844
1845 28 static int search_frag_timestamp(AVFormatContext *s, MOVFragmentIndex *frag_index,
1846 AVStream *st, int64_t timestamp)
1847 {
1848 int a, b, m, m0;
1849 int64_t frag_time;
1850
1851 28 a = -1;
1852 28 b = frag_index->nb_items;
1853
1854
2/2
✓ Branch 0 taken 224 times.
✓ Branch 1 taken 28 times.
252 while (b - a > 1) {
1855 224 m0 = m = (a + b) >> 1;
1856
1857
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 &&
1858 226 (frag_time = get_frag_time(s, st, frag_index, m)) == AV_NOPTS_VALUE)
1859 3 m++;
1860
1861
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)
1862 95 a = m;
1863 else
1864 129 b = m0;
1865 }
1866
1867 28 return a;
1868 }
1869
1870 851 static int update_frag_index(MOVContext *c, int64_t offset)
1871 {
1872 int index, i;
1873 MOVFragmentIndexItem * item;
1874 MOVFragmentStreamInfo * frag_stream_info;
1875
1876 // If moof_offset already exists in frag_index, return index to it
1877 851 index = search_frag_moof_offset(&c->frag_index, offset);
1878
2/2
✓ Branch 0 taken 376 times.
✓ Branch 1 taken 475 times.
851 if (index < c->frag_index.nb_items &&
1879
2/2
✓ Branch 0 taken 374 times.
✓ Branch 1 taken 2 times.
376 c->frag_index.item[index].moof_offset == offset)
1880 374 return index;
1881
1882 // offset is not yet in frag index.
1883 // Insert new item at index (sorted by moof offset)
1884 477 item = av_fast_realloc(c->frag_index.item,
1885 477 &c->frag_index.allocated_size,
1886 477 (c->frag_index.nb_items + 1) *
1887 sizeof(*c->frag_index.item));
1888
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 477 times.
477 if (!item)
1889 return -1;
1890 477 c->frag_index.item = item;
1891
1892 477 frag_stream_info = av_realloc_array(NULL, c->fc->nb_streams,
1893 sizeof(*item->stream_info));
1894
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 477 times.
477 if (!frag_stream_info)
1895 return -1;
1896
1897
2/2
✓ Branch 0 taken 579 times.
✓ Branch 1 taken 477 times.
1056 for (i = 0; i < c->fc->nb_streams; i++) {
1898 // Avoid building frag index if streams lack track id.
1899 579 MOVStreamContext *sc = c->fc->streams[i]->priv_data;
1900
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 579 times.
579 if (sc->id < 0) {
1901 av_free(frag_stream_info);
1902 return AVERROR_INVALIDDATA;
1903 }
1904
1905 579 frag_stream_info[i].id = sc->id;
1906 579 frag_stream_info[i].sidx_pts = AV_NOPTS_VALUE;
1907 579 frag_stream_info[i].tfdt_dts = AV_NOPTS_VALUE;
1908 579 frag_stream_info[i].next_trun_dts = AV_NOPTS_VALUE;
1909 579 frag_stream_info[i].first_tfra_pts = AV_NOPTS_VALUE;
1910 579 frag_stream_info[i].index_base = -1;
1911 579 frag_stream_info[i].index_entry = -1;
1912 579 frag_stream_info[i].encryption_index = NULL;
1913 579 frag_stream_info[i].stsd_id = -1;
1914 }
1915
1916
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 475 times.
477 if (index < c->frag_index.nb_items)
1917 2 memmove(c->frag_index.item + index + 1, c->frag_index.item + index,
1918 2 (c->frag_index.nb_items - index) * sizeof(*c->frag_index.item));
1919
1920 477 item = &c->frag_index.item[index];
1921 477 item->headers_read = 0;
1922 477 item->current = 0;
1923 477 item->nb_stream_info = c->fc->nb_streams;
1924 477 item->moof_offset = offset;
1925 477 item->stream_info = frag_stream_info;
1926 477 c->frag_index.nb_items++;
1927
1928 477 return index;
1929 }
1930
1931 499 static void fix_frag_index_entries(MOVFragmentIndex *frag_index, int index,
1932 int id, int entries)
1933 {
1934 int i;
1935 MOVFragmentStreamInfo * frag_stream_info;
1936
1937
1/2
✓ Branch 0 taken 499 times.
✗ Branch 1 not taken.
499 if (index < 0)
1938 499 return;
1939 for (i = index; i < frag_index->nb_items; i++) {
1940 frag_stream_info = get_frag_stream_info(frag_index, i, id);
1941 if (frag_stream_info && frag_stream_info->index_entry >= 0)
1942 frag_stream_info->index_entry += entries;
1943 }
1944 }
1945
1946 473 static int mov_read_moof(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1947 {
1948 // Set by mov_read_tfhd(). mov_read_trun() will reject files missing tfhd.
1949 473 c->fragment.found_tfhd = 0;
1950
1951
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) {
1952 1 c->has_looked_for_mfra = 1;
1953
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (pb->seekable & AVIO_SEEKABLE_NORMAL) {
1954 int ret;
1955 1 av_log(c->fc, AV_LOG_VERBOSE, "stream has moof boxes, will look "
1956 "for a mfra\n");
1957
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 if ((ret = mov_read_mfra(c, pb)) < 0) {
1958 av_log(c->fc, AV_LOG_VERBOSE, "found a moof box but failed to "
1959 "read the mfra (may be a live ismv)\n");
1960 }
1961 } else {
1962 av_log(c->fc, AV_LOG_VERBOSE, "found a moof box but stream is not "
1963 "seekable, can not look for mfra\n");
1964 }
1965 }
1966 473 c->fragment.moof_offset = c->fragment.implicit_offset = avio_tell(pb) - 8;
1967 473 av_log(c->fc, AV_LOG_TRACE, "moof offset %"PRIx64"\n", c->fragment.moof_offset);
1968 473 c->frag_index.current = update_frag_index(c, c->fragment.moof_offset);
1969 473 return mov_read_default(c, pb, atom);
1970 }
1971
1972 1224 static void mov_metadata_creation_time(MOVContext *c, AVIOContext *pb, AVDictionary **metadata, int version)
1973 {
1974 int64_t time;
1975
2/2
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 1209 times.
1224 if (version == 1) {
1976 15 time = avio_rb64(pb);
1977 15 avio_rb64(pb);
1978
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 15 times.
15 if (time < 0) {
1979 av_log(c->fc, AV_LOG_DEBUG, "creation_time is negative\n");
1980 return;
1981 }
1982 } else {
1983 1209 time = avio_rb32(pb);
1984 1209 avio_rb32(pb); /* modification time */
1985
4/4
✓ Branch 0 taken 575 times.
✓ Branch 1 taken 634 times.
✓ Branch 2 taken 48 times.
✓ Branch 3 taken 527 times.
1209 if (time > 0 && time < 2082844800) {
1986 48 av_log(c->fc, AV_LOG_WARNING, "Detected creation time before 1970, parsing as unix timestamp.\n");
1987 48 time += 2082844800;
1988 }
1989 }
1990
2/2
✓ Branch 0 taken 581 times.
✓ Branch 1 taken 643 times.
1224 if (time) {
1991 581 time -= 2082844800; /* seconds between 1904-01-01 and Epoch */
1992
1993
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 581 times.
581 if ((int64_t)(time * 1000000ULL) / 1000000 != time) {
1994 av_log(c->fc, AV_LOG_DEBUG, "creation_time is not representable\n");
1995 return;
1996 }
1997
1998 581 ff_dict_set_timestamp(metadata, "creation_time", time * 1000000);
1999 }
2000 }
2001
2002 673 static int mov_read_mdhd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2003 {
2004 AVStream *st;
2005 MOVStreamContext *sc;
2006 int version;
2007 673 char language[4] = {0};
2008 unsigned lang;
2009
2010
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 673 times.
673 if (c->fc->nb_streams < 1)
2011 return 0;
2012 673 st = c->fc->streams[c->fc->nb_streams-1];
2013 673 sc = st->priv_data;
2014
2015
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 673 times.
673 if (sc->time_scale) {
2016 av_log(c->fc, AV_LOG_ERROR, "Multiple mdhd?\n");
2017 return AVERROR_INVALIDDATA;
2018 }
2019
2020 673 version = avio_r8(pb);
2021
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 673 times.
673 if (version > 1) {
2022 avpriv_request_sample(c->fc, "Version %d", version);
2023 return AVERROR_PATCHWELCOME;
2024 }
2025 673 avio_rb24(pb); /* flags */
2026 673 mov_metadata_creation_time(c, pb, &st->metadata, version);
2027
2028 673 sc->time_scale = avio_rb32(pb);
2029
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 673 times.
673 if (sc->time_scale <= 0) {
2030 av_log(c->fc, AV_LOG_ERROR, "Invalid mdhd time scale %d, defaulting to 1\n", sc->time_scale);
2031 sc->time_scale = 1;
2032 }
2033
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 660 times.
673 st->duration = (version == 1) ? avio_rb64(pb) : avio_rb32(pb); /* duration */
2034
2035
6/6
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 660 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 9 times.
✓ Branch 4 taken 660 times.
✓ Branch 5 taken 4 times.
673 if ((version == 1 && st->duration == UINT64_MAX) ||
2036
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 660 times.
660 (version != 1 && st->duration == UINT32_MAX)) {
2037 9 st->duration = 0;
2038 }
2039
2040 673 lang = avio_rb16(pb); /* language */
2041
2/2
✓ Branch 1 taken 499 times.
✓ Branch 2 taken 174 times.
673 if (ff_mov_lang_to_iso639(lang, language))
2042 499 av_dict_set(&st->metadata, "language", language, 0);
2043 673 avio_rb16(pb); /* quality */
2044
2045 673 return 0;
2046 }
2047
2048 551 static int mov_read_mvhd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2049 {
2050 int i;
2051 551 int version = avio_r8(pb); /* version */
2052 551 avio_rb24(pb); /* flags */
2053
2054 551 mov_metadata_creation_time(c, pb, &c->fc->metadata, version);
2055 551 c->time_scale = avio_rb32(pb); /* time scale */
2056
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 551 times.
551 if (c->time_scale <= 0) {
2057 av_log(c->fc, AV_LOG_ERROR, "Invalid mvhd time scale %d, defaulting to 1\n", c->time_scale);
2058 c->time_scale = 1;
2059 }
2060 551 av_log(c->fc, AV_LOG_TRACE, "time scale = %i\n", c->time_scale);
2061
2062
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 549 times.
551 c->duration = (version == 1) ? avio_rb64(pb) : avio_rb32(pb); /* duration */
2063 551 avio_rb32(pb); /* preferred scale */
2064
2065 551 avio_rb16(pb); /* preferred volume */
2066
2067 551 avio_skip(pb, 10); /* reserved */
2068
2069 /* movie display matrix, store it in main context and use it later on */
2070
2/2
✓ Branch 0 taken 1653 times.
✓ Branch 1 taken 551 times.
2204 for (i = 0; i < 3; i++) {
2071 1653 c->movie_display_matrix[i][0] = avio_rb32(pb); // 16.16 fixed point
2072 1653 c->movie_display_matrix[i][1] = avio_rb32(pb); // 16.16 fixed point
2073 1653 c->movie_display_matrix[i][2] = avio_rb32(pb); // 2.30 fixed point
2074 }
2075
2076 551 avio_rb32(pb); /* preview time */
2077 551 avio_rb32(pb); /* preview duration */
2078 551 avio_rb32(pb); /* poster time */
2079 551 avio_rb32(pb); /* selection time */
2080 551 avio_rb32(pb); /* selection duration */
2081 551 avio_rb32(pb); /* current time */
2082 551 avio_rb32(pb); /* next track ID */
2083
2084 551 return 0;
2085 }
2086
2087 7 static void set_last_stream_little_endian(AVFormatContext *fc)
2088 {
2089 AVStream *st;
2090
2091
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (fc->nb_streams < 1)
2092 return;
2093 7 st = fc->streams[fc->nb_streams-1];
2094
2095
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) {
2096 5 case AV_CODEC_ID_PCM_S16BE:
2097 5 st->codecpar->codec_id = AV_CODEC_ID_PCM_S16LE;
2098 5 break;
2099 1 case AV_CODEC_ID_PCM_S24BE:
2100 1 st->codecpar->codec_id = AV_CODEC_ID_PCM_S24LE;
2101 1 break;
2102 case AV_CODEC_ID_PCM_S32BE:
2103 st->codecpar->codec_id = AV_CODEC_ID_PCM_S32LE;
2104 break;
2105 1 case AV_CODEC_ID_PCM_F32BE:
2106 1 st->codecpar->codec_id = AV_CODEC_ID_PCM_F32LE;
2107 1 break;
2108 case AV_CODEC_ID_PCM_F64BE:
2109 st->codecpar->codec_id = AV_CODEC_ID_PCM_F64LE;
2110 break;
2111 default:
2112 break;
2113 }
2114 }
2115
2116 5 static int mov_read_enda(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2117 {
2118 5 int little_endian = avio_rb16(pb) & 0xFF;
2119 5 av_log(c->fc, AV_LOG_TRACE, "enda %d\n", little_endian);
2120
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 4 times.
5 if (little_endian == 1)
2121 1 set_last_stream_little_endian(c->fc);
2122 5 return 0;
2123 }
2124
2125 6 static int mov_read_pcmc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2126 {
2127 int format_flags;
2128 int version, flags;
2129 int pcm_sample_size;
2130 6 AVFormatContext *fc = c->fc;
2131 AVStream *st;
2132 MOVStreamContext *sc;
2133
2134
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (atom.size < 6) {
2135 av_log(c->fc, AV_LOG_ERROR, "Empty pcmC box\n");
2136 return AVERROR_INVALIDDATA;
2137 }
2138
2139 6 version = avio_r8(pb);
2140 6 flags = avio_rb24(pb);
2141
2142
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) {
2143 av_log(c->fc, AV_LOG_ERROR,
2144 "Unsupported 'pcmC' box with version %d, flags: %x",
2145 version, flags);
2146 return AVERROR_INVALIDDATA;
2147 }
2148
2149 6 format_flags = avio_r8(pb);
2150 6 pcm_sample_size = avio_r8(pb);
2151
2152
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (fc->nb_streams < 1)
2153 return AVERROR_INVALIDDATA;
2154
2155 6 st = fc->streams[fc->nb_streams - 1];
2156 6 sc = st->priv_data;
2157
2158
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 5 times.
6 if (sc->format == MOV_MP4_FPCM_TAG) {
2159
1/3
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
1 switch (pcm_sample_size) {
2160 1 case 32:
2161 1 st->codecpar->codec_id = AV_CODEC_ID_PCM_F32BE;
2162 1 break;
2163 case 64:
2164 st->codecpar->codec_id = AV_CODEC_ID_PCM_F64BE;
2165 break;
2166 default:
2167 av_log(fc, AV_LOG_ERROR, "invalid pcm_sample_size %d for %s\n",
2168 pcm_sample_size,
2169 av_fourcc2str(sc->format));
2170 return AVERROR_INVALIDDATA;
2171 }
2172
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 } else if (sc->format == MOV_MP4_IPCM_TAG) {
2173
1/4
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
5 switch (pcm_sample_size) {
2174 5 case 16:
2175 5 st->codecpar->codec_id = AV_CODEC_ID_PCM_S16BE;
2176 5 break;
2177 case 24:
2178 st->codecpar->codec_id = AV_CODEC_ID_PCM_S24BE;
2179 break;
2180 case 32:
2181 st->codecpar->codec_id = AV_CODEC_ID_PCM_S32BE;
2182 break;
2183 default:
2184 av_log(fc, AV_LOG_ERROR, "invalid pcm_sample_size %d for %s\n",
2185 pcm_sample_size,
2186 av_fourcc2str(sc->format));
2187 return AVERROR_INVALIDDATA;
2188 }
2189 } else {
2190 av_log(fc, AV_LOG_ERROR, "'pcmC' with invalid sample entry '%s'\n",
2191 av_fourcc2str(sc->format));
2192 return AVERROR_INVALIDDATA;
2193 }
2194
2195
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
2196 6 set_last_stream_little_endian(c->fc);
2197 6 st->codecpar->bits_per_coded_sample = av_get_bits_per_sample(st->codecpar->codec_id);
2198
2199 6 return 0;
2200 }
2201
2202 55 static int mov_read_colr(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2203 {
2204 AVStream *st;
2205 55 HEIFItem *item = NULL;
2206 55 char color_parameter_type[5] = { 0 };
2207 uint16_t color_primaries, color_trc, color_matrix;
2208 int ret;
2209
2210 55 st = get_curr_st(c);
2211
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 55 times.
55 if (!st) {
2212 item = get_heif_item(c, c->cur_item_id);
2213 if (!item)
2214 return 0;
2215 }
2216
2217 55 ret = ffio_read_size(pb, color_parameter_type, 4);
2218
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 55 times.
55 if (ret < 0)
2219 return ret;
2220
2/2
✓ Branch 0 taken 33 times.
✓ Branch 1 taken 22 times.
55 if (strncmp(color_parameter_type, "nclx", 4) &&
2221
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 33 times.
33 strncmp(color_parameter_type, "nclc", 4) &&
2222 strncmp(color_parameter_type, "prof", 4)) {
2223 av_log(c->fc, AV_LOG_WARNING, "unsupported color_parameter_type %s\n",
2224 color_parameter_type);
2225 return 0;
2226 }
2227
2228
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 55 times.
55 if (!strncmp(color_parameter_type, "prof", 4)) {
2229 AVPacketSideData *sd;
2230 uint8_t *icc_profile;
2231 if (st) {
2232 sd = av_packet_side_data_new(&st->codecpar->coded_side_data,
2233 &st->codecpar->nb_coded_side_data,
2234 AV_PKT_DATA_ICC_PROFILE,
2235 atom.size - 4, 0);
2236 if (!sd)
2237 return AVERROR(ENOMEM);
2238 icc_profile = sd->data;
2239 } else {
2240 if (c->heif_icc_profile_items >= c->fc->max_streams) {
2241 av_log(c->fc, AV_LOG_WARNING,
2242 "HEIF ICC profile copies exceed cap %d; ignoring further items\n",
2243 c->fc->max_streams);
2244 return 0;
2245 }
2246 av_freep(&item->icc_profile);
2247 icc_profile = item->icc_profile = av_malloc(atom.size - 4);
2248 if (!icc_profile) {
2249 item->icc_profile_size = 0;
2250 return AVERROR(ENOMEM);
2251 }
2252 item->icc_profile_size = atom.size - 4;
2253 c->heif_icc_profile_items++;
2254 }
2255 ret = ffio_read_size(pb, icc_profile, atom.size - 4);
2256 if (ret < 0)
2257 return ret;
2258
1/2
✓ Branch 0 taken 55 times.
✗ Branch 1 not taken.
55 } else if (st) {
2259 55 color_primaries = avio_rb16(pb);
2260 55 color_trc = avio_rb16(pb);
2261 55 color_matrix = avio_rb16(pb);
2262
2263 55 av_log(c->fc, AV_LOG_TRACE,
2264 "%s: pri %d trc %d matrix %d",
2265 color_parameter_type, color_primaries, color_trc, color_matrix);
2266
2267
2/2
✓ Branch 0 taken 22 times.
✓ Branch 1 taken 33 times.
55 if (!strncmp(color_parameter_type, "nclx", 4)) {
2268 22 uint8_t color_range = avio_r8(pb) >> 7;
2269 22 av_log(c->fc, AV_LOG_TRACE, " full %"PRIu8"", color_range);
2270
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 20 times.
22 if (color_range)
2271 2 st->codecpar->color_range = AVCOL_RANGE_JPEG;
2272 else
2273 20 st->codecpar->color_range = AVCOL_RANGE_MPEG;
2274 }
2275
2276
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 55 times.
55 if (!av_color_primaries_name(color_primaries))
2277 color_primaries = AVCOL_PRI_UNSPECIFIED;
2278
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 55 times.
55 if (!av_color_transfer_name(color_trc))
2279 color_trc = AVCOL_TRC_UNSPECIFIED;
2280
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 55 times.
55 if (!av_color_space_name(color_matrix))
2281 color_matrix = AVCOL_SPC_UNSPECIFIED;
2282
2283 55 st->codecpar->color_primaries = color_primaries;
2284 55 st->codecpar->color_trc = color_trc;
2285 55 st->codecpar->color_space = color_matrix;
2286 55 av_log(c->fc, AV_LOG_TRACE, "\n");
2287 }
2288 55 return 0;
2289 }
2290
2291 118 static int mov_read_fiel(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2292 {
2293 AVStream *st;
2294 unsigned mov_field_order;
2295 118 enum AVFieldOrder decoded_field_order = AV_FIELD_UNKNOWN;
2296
2297
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 118 times.
118 if (c->fc->nb_streams < 1) // will happen with jp2 files
2298 return 0;
2299 118 st = c->fc->streams[c->fc->nb_streams-1];
2300
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 118 times.
118 if (atom.size < 2)
2301 return AVERROR_INVALIDDATA;
2302 118 mov_field_order = avio_rb16(pb);
2303
2/2
✓ Branch 0 taken 96 times.
✓ Branch 1 taken 22 times.
118 if ((mov_field_order & 0xFF00) == 0x0100)
2304 96 decoded_field_order = AV_FIELD_PROGRESSIVE;
2305
1/2
✓ Branch 0 taken 22 times.
✗ Branch 1 not taken.
22 else if ((mov_field_order & 0xFF00) == 0x0200) {
2306
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) {
2307 1 case 0x01: decoded_field_order = AV_FIELD_TT;
2308 1 break;
2309 case 0x06: decoded_field_order = AV_FIELD_BB;
2310 break;
2311 1 case 0x09: decoded_field_order = AV_FIELD_TB;
2312 1 break;
2313 20 case 0x0E: decoded_field_order = AV_FIELD_BT;
2314 20 break;
2315 }
2316 }
2317
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) {
2318 av_log(c->fc, AV_LOG_ERROR, "Unknown MOV field order 0x%04x\n", mov_field_order);
2319 }
2320 118 st->codecpar->field_order = decoded_field_order;
2321
2322 118 return 0;
2323 }
2324
2325 69 static int mov_realloc_extradata(AVCodecParameters *par, MOVAtom atom)
2326 {
2327 69 int err = 0;
2328 69 uint64_t size = (uint64_t)par->extradata_size + atom.size + 8 + AV_INPUT_BUFFER_PADDING_SIZE;
2329
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)
2330 return AVERROR_INVALIDDATA;
2331
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 69 times.
69 if ((err = av_reallocp(&par->extradata, size)) < 0) {
2332 par->extradata_size = 0;
2333 return err;
2334 }
2335 69 par->extradata_size = size - AV_INPUT_BUFFER_PADDING_SIZE;
2336 69 return 0;
2337 }
2338
2339 /* Read a whole atom into the extradata return the size of the atom read, possibly truncated if != atom.size */
2340 65 static int64_t mov_read_atom_into_extradata(MOVContext *c, AVIOContext *pb, MOVAtom atom,
2341 AVCodecParameters *par, uint8_t *buf)
2342 {
2343 65 int64_t result = atom.size;
2344 int err;
2345
2346 65 AV_WB32(buf , atom.size + 8);
2347 65 AV_WL32(buf + 4, atom.type);
2348 65 err = ffio_read_size(pb, buf + 8, atom.size);
2349
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 65 times.
65 if (err < 0) {
2350 par->extradata_size -= atom.size;
2351 return err;
2352
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 65 times.
65 } else if (err < atom.size) {
2353 av_log(c->fc, AV_LOG_WARNING, "truncated extradata\n");
2354 par->extradata_size -= atom.size - err;
2355 result = err;
2356 }
2357 65 memset(buf + 8 + err, 0, AV_INPUT_BUFFER_PADDING_SIZE);
2358 65 return result;
2359 }
2360
2361 /* FIXME modify QDM2/SVQ3/H.264 decoders to take full atom as extradata */
2362 58 static int mov_read_extradata(MOVContext *c, AVIOContext *pb, MOVAtom atom,
2363 enum AVCodecID codec_id)
2364 {
2365 AVStream *st;
2366 uint64_t original_size;
2367 int err;
2368
2369
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 58 times.
58 if (c->fc->nb_streams < 1) // will happen with jp2 files
2370 return 0;
2371 58 st = c->fc->streams[c->fc->nb_streams-1];
2372
2373
2/2
✓ Branch 0 taken 19 times.
✓ Branch 1 taken 39 times.
58 if (st->codecpar->codec_id != codec_id)
2374 19 return 0; /* unexpected codec_id - don't mess with extradata */
2375
2376 39 original_size = st->codecpar->extradata_size;
2377 39 err = mov_realloc_extradata(st->codecpar, atom);
2378
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 39 times.
39 if (err)
2379 return err;
2380
2381 39 err = mov_read_atom_into_extradata(c, pb, atom, st->codecpar, st->codecpar->extradata + original_size);
2382
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 39 times.
39 if (err < 0)
2383 return err;
2384 39 return 0; // Note: this is the original behavior to ignore truncation.
2385 }
2386
2387 /* wrapper functions for reading ALAC/AVS/MJPEG/MJPEG2000 extradata atoms only for those codecs */
2388 16 static int mov_read_alac(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2389 {
2390 16 return mov_read_extradata(c, pb, atom, AV_CODEC_ID_ALAC);
2391 }
2392
2393 static int mov_read_avss(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2394 {
2395 return mov_read_extradata(c, pb, atom, AV_CODEC_ID_CAVS);
2396 }
2397
2398 static int mov_read_jp2h(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2399 {
2400 return mov_read_extradata(c, pb, atom, AV_CODEC_ID_JPEG2000);
2401 }
2402
2403 static int mov_read_dpxe(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2404 {
2405 return mov_read_extradata(c, pb, atom, AV_CODEC_ID_R10K);
2406 }
2407
2408 19 static int mov_read_avid(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2409 {
2410 19 int ret = mov_read_extradata(c, pb, atom, AV_CODEC_ID_AVUI);
2411
1/2
✓ Branch 0 taken 19 times.
✗ Branch 1 not taken.
19 if (!ret)
2412 19 ret = mov_read_extradata(c, pb, atom, AV_CODEC_ID_DNXHD);
2413 19 return ret;
2414 }
2415
2416 static int mov_read_targa_y216(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2417 {
2418 int ret = mov_read_extradata(c, pb, atom, AV_CODEC_ID_TARGA_Y216);
2419
2420 if (!ret && c->fc->nb_streams >= 1) {
2421 AVCodecParameters *par = c->fc->streams[c->fc->nb_streams-1]->codecpar;
2422 if (par->extradata_size >= 40) {
2423 par->height = AV_RB16(&par->extradata[36]);
2424 par->width = AV_RB16(&par->extradata[38]);
2425 }
2426 }
2427 return ret;
2428 }
2429
2430 16 static int mov_read_ares(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2431 {
2432
1/2
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
16 if (c->fc->nb_streams >= 1) {
2433 16 AVStream *const st = c->fc->streams[c->fc->nb_streams - 1];
2434 16 FFStream *const sti = ffstream(st);
2435 16 AVCodecParameters *par = st->codecpar;
2436
2437
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 if (par->codec_tag == MKTAG('A', 'V', 'i', 'n') &&
2438 par->codec_id == AV_CODEC_ID_H264 &&
2439 atom.size > 11) {
2440 int cid;
2441 avio_skip(pb, 10);
2442 cid = avio_rb16(pb);
2443 /* For AVID AVCI50, force width of 1440 to be able to select the correct SPS and PPS */
2444 if (cid == 0xd4d || cid == 0xd4e)
2445 par->width = 1440;
2446 return 0;
2447
1/2
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
16 } else if ((par->codec_tag == MKTAG('A', 'V', 'd', '1') ||
2448
1/2
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
16 par->codec_tag == MKTAG('A', 'V', 'j', '2') ||
2449
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 3 times.
16 par->codec_tag == MKTAG('A', 'V', 'd', 'n')) &&
2450
1/2
✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
13 atom.size >= 24) {
2451 int num, den;
2452 13 avio_skip(pb, 12);
2453 13 num = avio_rb32(pb);
2454 13 den = avio_rb32(pb);
2455
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)
2456 return 0;
2457
2/3
✓ Branch 1 taken 12 times.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
13 switch (avio_rb32(pb)) {
2458 12 case 2:
2459
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (den >= INT_MAX / 2)
2460 return 0;
2461 12 den *= 2;
2462 av_fallthrough;
2463 13 case 1:
2464 13 sti->display_aspect_ratio = (AVRational){ num, den };
2465 av_fallthrough;
2466 13 default:
2467 13 return 0;
2468 }
2469 }
2470 }
2471
2472 3 return mov_read_avid(c, pb, atom);
2473 }
2474
2475 26 static int mov_read_aclr(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2476 {
2477 26 int ret = 0;
2478 26 int length = 0;
2479 uint64_t original_size;
2480
1/2
✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
26 if (c->fc->nb_streams >= 1) {
2481 26 AVCodecParameters *par = c->fc->streams[c->fc->nb_streams-1]->codecpar;
2482
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 26 times.
26 if (par->codec_id == AV_CODEC_ID_H264)
2483 return 0;
2484
1/2
✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
26 if (atom.size == 16) {
2485 26 original_size = par->extradata_size;
2486 26 ret = mov_realloc_extradata(par, atom);
2487
1/2
✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
26 if (!ret) {
2488 26 length = mov_read_atom_into_extradata(c, pb, atom, par, par->extradata + original_size);
2489
1/2
✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
26 if (length == atom.size) {
2490 26 const uint8_t range_value = par->extradata[original_size + 19];
2491
1/3
✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
26 switch (range_value) {
2492 26 case 1:
2493 26 par->color_range = AVCOL_RANGE_MPEG;
2494 26 break;
2495 case 2:
2496 par->color_range = AVCOL_RANGE_JPEG;
2497 break;
2498 default:
2499 av_log(c->fc, AV_LOG_WARNING, "ignored unknown aclr value (%d)\n", range_value);
2500 break;
2501 }
2502 ff_dlog(c->fc, "color_range: %d\n", par->color_range);
2503 } else {
2504 /* For some reason the whole atom was not added to the extradata */
2505 av_log(c->fc, AV_LOG_ERROR, "aclr not decoded - incomplete atom\n");
2506 }
2507 } else {
2508 av_log(c->fc, AV_LOG_ERROR, "aclr not decoded - unable to add atom to extradata\n");
2509 }
2510 } else {
2511 av_log(c->fc, AV_LOG_WARNING, "aclr not decoded - unexpected size %"PRId64"\n", atom.size);
2512 }
2513 }
2514
2515 26 return ret;
2516 }
2517
2518 4 static int mov_read_svq3(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2519 {
2520 4 return mov_read_extradata(c, pb, atom, AV_CODEC_ID_SVQ3);
2521 }
2522
2523 33 static int mov_read_wave(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2524 {
2525 AVStream *st;
2526 int ret;
2527
2528
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 33 times.
33 if (c->fc->nb_streams < 1)
2529 return 0;
2530 33 st = c->fc->streams[c->fc->nb_streams-1];
2531
2532
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 33 times.
33 if ((uint64_t)atom.size > (1<<30))
2533 return AVERROR_INVALIDDATA;
2534
2535
2/2
✓ Branch 0 taken 31 times.
✓ Branch 1 taken 2 times.
33 if (st->codecpar->codec_id == AV_CODEC_ID_QDM2 ||
2536
1/2
✓ Branch 0 taken 31 times.
✗ Branch 1 not taken.
31 st->codecpar->codec_id == AV_CODEC_ID_QDMC ||
2537
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 31 times.
31 st->codecpar->codec_id == AV_CODEC_ID_SPEEX) {
2538 // pass all frma atom to codec, needed at least for QDMC and QDM2
2539 2 ret = ff_get_extradata(c->fc, st->codecpar, pb, atom.size);
2540
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (ret < 0)
2541 return ret;
2542
1/2
✓ Branch 0 taken 31 times.
✗ Branch 1 not taken.
31 } else if (atom.size > 8) { /* to read frma, esds atoms */
2543
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) {
2544 uint64_t buffer;
2545 10 ret = ffio_ensure_seekback(pb, 8);
2546
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (ret < 0)
2547 return ret;
2548 10 buffer = avio_rb64(pb);
2549 10 atom.size -= 8;
2550
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 if ( (buffer & 0xFFFFFFFF) == MKBETAG('f','r','m','a')
2551
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 && buffer >> 32 <= atom.size
2552
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 && buffer >> 32 >= 8) {
2553 10 avio_skip(pb, -8);
2554 10 atom.size += 8;
2555 } else if (!st->codecpar->extradata_size) {
2556 #define ALAC_EXTRADATA_SIZE 36
2557 st->codecpar->extradata = av_mallocz(ALAC_EXTRADATA_SIZE + AV_INPUT_BUFFER_PADDING_SIZE);
2558 if (!st->codecpar->extradata)
2559 return AVERROR(ENOMEM);
2560 st->codecpar->extradata_size = ALAC_EXTRADATA_SIZE;
2561 AV_WB32(st->codecpar->extradata , ALAC_EXTRADATA_SIZE);
2562 AV_WB32(st->codecpar->extradata + 4, MKTAG('a','l','a','c'));
2563 AV_WB64(st->codecpar->extradata + 12, buffer);
2564 avio_read(pb, st->codecpar->extradata + 20, 16);
2565 avio_skip(pb, atom.size - 24);
2566 return 0;
2567 }
2568 }
2569
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 31 times.
31 if ((ret = mov_read_default(c, pb, atom)) < 0)
2570 return ret;
2571 } else
2572 avio_skip(pb, atom.size);
2573 33 return 0;
2574 }
2575
2576 /**
2577 * This function reads atom content and puts data in extradata without tag
2578 * nor size unlike mov_read_extradata.
2579 */
2580 186 static int mov_read_glbl(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2581 {
2582 AVStream *st;
2583 int ret;
2584
2585 186 st = get_curr_st(c);
2586
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 186 times.
186 if (!st)
2587 return 0;
2588
2589
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 186 times.
186 if ((uint64_t)atom.size > (1<<30))
2590 return AVERROR_INVALIDDATA;
2591
2592
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 185 times.
186 if (atom.type == MKTAG('v','v','c','C')) {
2593 1 avio_skip(pb, 4);
2594 1 atom.size -= 4;
2595 }
2596
2597
2/2
✓ Branch 0 taken 182 times.
✓ Branch 1 taken 4 times.
186 if (atom.size >= 10) {
2598 // Broken files created by legacy versions of libavformat will
2599 // wrap a whole fiel atom inside of a glbl atom.
2600 182 unsigned size = avio_rb32(pb);
2601 182 unsigned type = avio_rl32(pb);
2602
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 182 times.
182 if (avio_feof(pb))
2603 return AVERROR_INVALIDDATA;
2604 182 avio_seek(pb, -8, SEEK_CUR);
2605
3/4
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 172 times.
✓ Branch 2 taken 10 times.
✗ Branch 3 not taken.
182 if (type == MKTAG('f','i','e','l') && size == atom.size)
2606 10 return mov_read_default(c, pb, atom);
2607 }
2608
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 176 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
176 if (st->codecpar->extradata_size > 1 && st->codecpar->extradata) {
2609 av_log(c->fc, AV_LOG_WARNING, "ignoring multiple glbl\n");
2610 return 0;
2611 }
2612 176 ret = ff_get_extradata(c->fc, st->codecpar, pb, atom.size);
2613
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 176 times.
176 if (ret < 0)
2614 return ret;
2615
3/4
✓ Branch 0 taken 68 times.
✓ Branch 1 taken 108 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 68 times.
176 if (atom.type == MKTAG('h','v','c','C') && st->codecpar->codec_tag == MKTAG('d','v','h','1'))
2616 /* HEVC-based Dolby Vision derived from hvc1.
2617 Happens to match with an identifier
2618 previously utilized for DV. Thus, if we have
2619 the hvcC extradata box available as specified,
2620 set codec to HEVC */
2621 st->codecpar->codec_id = AV_CODEC_ID_HEVC;
2622
2623 176 return 0;
2624 }
2625
2626 2 static int mov_read_dvc1(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2627 {
2628 AVStream *st;
2629 uint8_t profile_level;
2630 int ret;
2631
2632
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (c->fc->nb_streams < 1)
2633 return 0;
2634 2 st = c->fc->streams[c->fc->nb_streams-1];
2635
2636
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)
2637 return AVERROR_INVALIDDATA;
2638
2639 2 profile_level = avio_r8(pb);
2640
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if ((profile_level & 0xf0) != 0xc0)
2641 return 0;
2642
2643 2 avio_seek(pb, 6, SEEK_CUR);
2644 2 ret = ff_get_extradata(c->fc, st->codecpar, pb, atom.size - 7);
2645
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (ret < 0)
2646 return ret;
2647
2648 2 return 0;
2649 }
2650
2651 52 static int mov_find_tref_id(const MovTref *tag, uint32_t id)
2652 {
2653
2/2
✓ Branch 0 taken 31 times.
✓ Branch 1 taken 33 times.
64 for (int i = 0; i < tag->nb_id; i++) {
2654
2/2
✓ Branch 0 taken 19 times.
✓ Branch 1 taken 12 times.
31 if (tag->id[i] == id)
2655 19 return 1;
2656 }
2657 33 return 0;
2658 }
2659
2660 33 static int mov_add_tref_id(MovTref *tag, uint32_t id)
2661 {
2662 33 int ret = mov_find_tref_id(tag, id);
2663
2664
1/2
✓ Branch 0 taken 33 times.
✗ Branch 1 not taken.
33 if (!ret) {
2665 33 uint32_t *tmp = av_realloc_array(tag->id, tag->nb_id + 1, sizeof(*tag->id));
2666
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 33 times.
33 if (!tmp)
2667 return AVERROR(ENOMEM);
2668 33 tag->id = tmp;
2669 33 tag->id[tag->nb_id++] = id;
2670 }
2671
2672 33 return 0;
2673 }
2674
2675 1433 static MovTref *mov_find_tref_tag(const MOVStreamContext *sc, uint32_t name)
2676 {
2677
2/2
✓ Branch 0 taken 155 times.
✓ Branch 1 taken 1383 times.
1538 for (int i = 0; i < sc->nb_tref_tags; i++) {
2678 155 MovTref *entry = &sc->tref_tags[i];
2679
2680
2/2
✓ Branch 0 taken 50 times.
✓ Branch 1 taken 105 times.
155 if (entry->name == name)
2681 50 return entry;
2682 }
2683 1383 return NULL;
2684 }
2685
2686 29 static MovTref *mov_add_tref_tag(MOVStreamContext *sc, uint32_t name)
2687 {
2688 29 MovTref *tag = mov_find_tref_tag(sc, name);
2689
2690
1/2
✓ Branch 0 taken 29 times.
✗ Branch 1 not taken.
29 if (!tag) {
2691 29 MovTref *tmp = av_realloc_array(sc->tref_tags, sc->nb_tref_tags + 1,
2692 sizeof(*sc->tref_tags));
2693
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 29 times.
29 if (!tmp)
2694 return NULL;
2695 29 sc->tref_tags = tmp;
2696 29 tag = &sc->tref_tags[sc->nb_tref_tags++];
2697 29 *tag = (MovTref){ .name = name };
2698 }
2699
2700 29 return tag;
2701 }
2702
2703 11 static int mov_read_cdsc_rndr(MOVContext* c, AVIOContext* pb, MOVAtom atom)
2704 {
2705 AVStream* st;
2706 MOVStreamContext* sc;
2707
2708
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (c->fc->nb_streams < 1)
2709 return 0;
2710
2711
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (atom.size > 4) {
2712 av_log(c->fc, AV_LOG_ERROR, "Only a single tref of type cdsc/rndr is supported\n");
2713 return AVERROR_PATCHWELCOME;
2714 }
2715
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (atom.size < 4)
2716 return AVERROR_INVALIDDATA;
2717
2718 11 st = get_curr_st(c);
2719
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (!st)
2720 return AVERROR_INVALIDDATA;
2721 11 sc = st->priv_data;
2722
2723 11 MovTref *tag = mov_add_tref_tag(sc, atom.type);
2724
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (!tag)
2725 return AVERROR(ENOMEM);
2726
2727 11 int ret = mov_add_tref_id(tag, avio_rb32(pb));
2728
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (ret < 0)
2729 return ret;
2730
2731 11 return 0;
2732 }
2733
2734 static int mov_read_sbas(MOVContext* c, AVIOContext* pb, MOVAtom atom)
2735 {
2736 AVStream* st;
2737 MOVStreamContext* sc;
2738
2739 if (c->fc->nb_streams < 1)
2740 return 0;
2741
2742 /* For SBAS this should be fine - though beware if someone implements a
2743 * tref atom processor that doesn't drop down to default then this may
2744 * be lost. */
2745 if (atom.size > 4) {
2746 av_log(c->fc, AV_LOG_ERROR, "Only a single tref of type sbas is supported\n");
2747 return AVERROR_PATCHWELCOME;
2748 }
2749 if (atom.size < 4)
2750 return AVERROR_INVALIDDATA;
2751
2752 st = c->fc->streams[c->fc->nb_streams - 1];
2753 sc = st->priv_data;
2754
2755 MovTref *tag = mov_add_tref_tag(sc, atom.type);
2756 if (!tag)
2757 return AVERROR(ENOMEM);
2758
2759 int ret = mov_add_tref_id(tag, avio_rb32(pb));
2760 if (ret < 0)
2761 return ret;
2762
2763 return 0;
2764 }
2765
2766 static int mov_read_vdep(MOVContext* c, AVIOContext* pb, MOVAtom atom)
2767 {
2768 AVStream* st;
2769 MOVStreamContext* sc;
2770
2771 if (c->fc->nb_streams < 1)
2772 return 0;
2773
2774 if (atom.size > 4)
2775 av_log(c->fc, AV_LOG_WARNING, "More than one vdep reference is not supported.\n");
2776 if (atom.size < 4)
2777 return AVERROR_INVALIDDATA;
2778
2779 st = c->fc->streams[c->fc->nb_streams - 1];
2780 sc = st->priv_data;
2781
2782 MovTref *tag = mov_add_tref_tag(sc, atom.type);
2783 if (!tag)
2784 return AVERROR(ENOMEM);
2785
2786 int ret = mov_add_tref_id(tag, avio_rb32(pb));
2787 if (ret < 0)
2788 return ret;
2789
2790 return 0;
2791 }
2792
2793 /**
2794 * An strf atom is a BITMAPINFOHEADER struct. This struct is 40 bytes itself,
2795 * but can have extradata appended at the end after the 40 bytes belonging
2796 * to the struct.
2797 */
2798 static int mov_read_strf(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2799 {
2800 AVStream *st;
2801 int ret;
2802
2803 if (c->fc->nb_streams < 1)
2804 return 0;
2805 if (atom.size <= 40)
2806 return 0;
2807 st = c->fc->streams[c->fc->nb_streams-1];
2808
2809 if ((uint64_t)atom.size > (1<<30))
2810 return AVERROR_INVALIDDATA;
2811
2812 avio_skip(pb, 40);
2813 ret = ff_get_extradata(c->fc, st->codecpar, pb, atom.size - 40);
2814 if (ret < 0)
2815 return ret;
2816
2817 return 0;
2818 }
2819
2820 673 static int mov_read_stco(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2821 {
2822 AVStream *st;
2823 MOVStreamContext *sc;
2824 unsigned int i, entries;
2825
2826
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 673 times.
673 if (c->trak_index < 0) {
2827 av_log(c->fc, AV_LOG_WARNING, "STCO outside TRAK\n");
2828 return 0;
2829 }
2830
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 673 times.
673 if (c->fc->nb_streams < 1)
2831 return 0;
2832 673 st = c->fc->streams[c->fc->nb_streams-1];
2833 673 sc = st->priv_data;
2834
2835 673 avio_r8(pb); /* version */
2836 673 avio_rb24(pb); /* flags */
2837
2838 // Clamp allocation size for `chunk_offsets` -- don't throw an error for an
2839 // invalid count since the EOF path doesn't throw either.
2840 673 entries = avio_rb32(pb);
2841 673 entries =
2842
2/2
✓ Branch 0 taken 668 times.
✓ Branch 1 taken 5 times.
673 FFMIN(entries,
2843 FFMAX(0, (atom.size - 8) /
2844 (atom.type == MKTAG('s', 't', 'c', 'o') ? 4 : 8)));
2845
2846
2/2
✓ Branch 0 taken 29 times.
✓ Branch 1 taken 644 times.
673 if (!entries)
2847 29 return 0;
2848
2849
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 644 times.
644 if (sc->chunk_offsets) {
2850 av_log(c->fc, AV_LOG_WARNING, "Ignoring duplicated STCO atom\n");
2851 return 0;
2852 }
2853
2854 644 av_free(sc->chunk_offsets);
2855 644 sc->chunk_count = 0;
2856 644 sc->chunk_offsets = av_malloc_array(entries, sizeof(*sc->chunk_offsets));
2857
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 644 times.
644 if (!sc->chunk_offsets)
2858 return AVERROR(ENOMEM);
2859 644 sc->chunk_count = entries;
2860
2861
2/2
✓ Branch 0 taken 640 times.
✓ Branch 1 taken 4 times.
644 if (atom.type == MKTAG('s','t','c','o'))
2862
3/4
✓ Branch 0 taken 43305 times.
✓ Branch 1 taken 640 times.
✓ Branch 2 taken 43305 times.
✗ Branch 3 not taken.
43945 for (i = 0; i < entries && !pb->eof_reached; i++)
2863 43305 sc->chunk_offsets[i] = avio_rb32(pb);
2864
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 else if (atom.type == MKTAG('c','o','6','4'))
2865
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++) {
2866 136336 sc->chunk_offsets[i] = avio_rb64(pb);
2867
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 136336 times.
136336 if (sc->chunk_offsets[i] < 0) {
2868 av_log(c->fc, AV_LOG_WARNING, "Impossible chunk_offset\n");
2869 sc->chunk_offsets[i] = 0;
2870 }
2871 }
2872 else
2873 return AVERROR_INVALIDDATA;
2874
2875 644 sc->chunk_count = i;
2876
2877
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 644 times.
644 if (pb->eof_reached) {
2878 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted STCO atom\n");
2879 return AVERROR_EOF;
2880 }
2881
2882 644 return 0;
2883 }
2884
2885 737 static int mov_codec_id(AVStream *st, uint32_t format)
2886 {
2887 737 int id = ff_codec_get_id(ff_codec_movaudio_tags, format);
2888
2889
2/2
✓ Branch 0 taken 481 times.
✓ Branch 1 taken 256 times.
737 if (id <= 0 &&
2890
2/2
✓ Branch 0 taken 478 times.
✓ Branch 1 taken 3 times.
481 ((format & 0xFFFF) == 'm' + ('s' << 8) ||
2891
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 478 times.
478 (format & 0xFFFF) == 'T' + ('S' << 8)))
2892 3 id = ff_codec_get_id(ff_codec_wav_tags, av_bswap32(format) & 0xFFFF);
2893
2894
4/4
✓ Branch 0 taken 337 times.
✓ Branch 1 taken 400 times.
✓ Branch 2 taken 259 times.
✓ Branch 3 taken 78 times.
737 if (st->codecpar->codec_type != AVMEDIA_TYPE_VIDEO && id > 0) {
2895 259 st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
2896
3/4
✓ Branch 0 taken 458 times.
✓ Branch 1 taken 20 times.
✓ Branch 2 taken 458 times.
✗ Branch 3 not taken.
478 } else if (st->codecpar->codec_type != AVMEDIA_TYPE_AUDIO &&
2897 /* skip old ASF MPEG-4 tag */
2898
2/2
✓ Branch 0 taken 454 times.
✓ Branch 1 taken 4 times.
458 format && format != MKTAG('m','p','4','s')) {
2899 454 id = ff_codec_get_id(ff_codec_movvideo_tags, format);
2900
2/2
✓ Branch 0 taken 64 times.
✓ Branch 1 taken 390 times.
454 if (id <= 0)
2901 64 id = ff_codec_get_id(ff_codec_bmp_tags, format);
2902
2/2
✓ Branch 0 taken 394 times.
✓ Branch 1 taken 60 times.
454 if (id > 0)
2903 394 st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
2904
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 53 times.
60 else if (st->codecpar->codec_type == AVMEDIA_TYPE_DATA ||
2905
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 6 times.
7 (st->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE &&
2906
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 st->codecpar->codec_id == AV_CODEC_ID_NONE)) {
2907 53 id = ff_codec_get_id(ff_codec_movsubtitle_tags, format);
2908
2/2
✓ Branch 0 taken 47 times.
✓ Branch 1 taken 6 times.
53 if (id <= 0) {
2909
2/2
✓ Branch 0 taken 39 times.
✓ Branch 1 taken 4 times.
90 id = (format == MOV_MP4_TTML_TAG || format == MOV_ISMV_TTML_TAG) ?
2910
2/2
✓ Branch 0 taken 43 times.
✓ Branch 1 taken 4 times.
90 AV_CODEC_ID_TTML : id;
2911 }
2912
2913
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 39 times.
53 if (id > 0)
2914 14 st->codecpar->codec_type = AVMEDIA_TYPE_SUBTITLE;
2915 else
2916 39 id = ff_codec_get_id(ff_codec_movdata_tags, format);
2917 }
2918 }
2919
2920 737 st->codecpar->codec_tag = format;
2921
2922 737 return id;
2923 }
2924
2925 351 static void mov_parse_stsd_video(MOVContext *c, AVIOContext *pb,
2926 AVStream *st, MOVStreamContext *sc)
2927 {
2928 351 uint8_t codec_name[32] = { 0 };
2929 int64_t stsd_start;
2930 unsigned int len;
2931 351 uint32_t id = 0;
2932
2933 /* The first 16 bytes of the video sample description are already
2934 * read in ff_mov_read_stsd_entries() */
2935 351 stsd_start = avio_tell(pb) - 16;
2936
2937
2/2
✓ Branch 0 taken 110 times.
✓ Branch 1 taken 241 times.
351 if (c->isom) {
2938 110 avio_skip(pb, 2); /* pre_defined */
2939 110 avio_skip(pb, 2); /* reserved */
2940 110 avio_skip(pb, 12); /* pre_defined */
2941 } else {
2942 241 avio_rb16(pb); /* version */
2943 241 avio_rb16(pb); /* revision level */
2944 241 id = avio_rl32(pb); /* vendor */
2945 241 av_dict_set(&st->metadata, "vendor_id", av_fourcc2str(id), 0);
2946 241 avio_rb32(pb); /* temporal quality */
2947 241 avio_rb32(pb); /* spatial quality */
2948 }
2949
2950 351 st->codecpar->width = avio_rb16(pb); /* width */
2951 351 st->codecpar->height = avio_rb16(pb); /* height */
2952
2953 351 avio_rb32(pb); /* horiz resolution */
2954 351 avio_rb32(pb); /* vert resolution */
2955 351 avio_rb32(pb); /* data size, always 0 */
2956 351 avio_rb16(pb); /* frames per samples */
2957
2958 351 len = avio_r8(pb); /* codec name, pascal string */
2959
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 350 times.
351 if (len > 31)
2960 1 len = 31;
2961 351 mov_read_mac_string(c, pb, len, codec_name, sizeof(codec_name));
2962
2/2
✓ Branch 0 taken 348 times.
✓ Branch 1 taken 3 times.
351 if (len < 31)
2963 348 avio_skip(pb, 31 - len);
2964
2965
2/2
✓ Branch 0 taken 269 times.
✓ Branch 1 taken 82 times.
351 if (codec_name[0])
2966 269 av_dict_set(&st->metadata, "encoder", codec_name, 0);
2967
2968 /* codec_tag YV12 triggers an UV swap in rawdec.c */
2969
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 351 times.
351 if (!strncmp(codec_name, "Planar Y'CbCr 8-bit 4:2:0", 25)) {
2970 st->codecpar->codec_tag = MKTAG('I', '4', '2', '0');
2971 st->codecpar->width &= ~1;
2972 st->codecpar->height &= ~1;
2973 }
2974 /* Flash Media Server uses tag H.263 with Sorenson Spark */
2975
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 351 times.
351 if (st->codecpar->codec_tag == MKTAG('H','2','6','3') &&
2976 !strncmp(codec_name, "Sorenson H263", 13))
2977 st->codecpar->codec_id = AV_CODEC_ID_FLV1;
2978
2979 351 st->codecpar->bits_per_coded_sample = avio_rb16(pb); /* depth */
2980
2981 351 avio_seek(pb, stsd_start, SEEK_SET);
2982
2983
2/2
✓ Branch 1 taken 18 times.
✓ Branch 2 taken 333 times.
351 if (ff_get_qtpalette(st->codecpar->codec_id, pb, sc->palette)) {
2984 18 st->codecpar->bits_per_coded_sample &= 0x1F;
2985 18 sc->has_palette = 1;
2986 }
2987 351 }
2988
2989 279 static void mov_parse_stsd_audio(MOVContext *c, AVIOContext *pb,
2990 AVStream *st, MOVStreamContext *sc)
2991 {
2992 int bits_per_sample, flags;
2993 279 uint16_t version = avio_rb16(pb);
2994 279 uint32_t id = 0;
2995 279 AVDictionaryEntry *compatible_brands = av_dict_get(c->fc->metadata, "compatible_brands", NULL, AV_DICT_MATCH_CASE);
2996 int channel_count;
2997
2998
2/2
✓ Branch 0 taken 192 times.
✓ Branch 1 taken 87 times.
279 if (c->isom)
2999 192 avio_skip(pb, 6); /* reserved */
3000 else {
3001 87 avio_rb16(pb); /* revision level */
3002 87 id = avio_rl32(pb); /* vendor */
3003 87 av_dict_set(&st->metadata, "vendor_id", av_fourcc2str(id), 0);
3004 }
3005
3006 279 channel_count = avio_rb16(pb);
3007
3008 279 st->codecpar->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC;
3009 279 st->codecpar->ch_layout.nb_channels = channel_count;
3010 279 st->codecpar->bits_per_coded_sample = avio_rb16(pb); /* sample size */
3011 279 av_log(c->fc, AV_LOG_TRACE, "audio channels %d\n", channel_count);
3012
3013 279 sc->audio_cid = avio_rb16(pb);
3014 279 avio_rb16(pb); /* packet size = 0 */
3015
3016 279 st->codecpar->sample_rate = ((avio_rb32(pb) >> 16));
3017
3018 // Read QT version 1 fields. In version 0 these do not exist.
3019 279 av_log(c->fc, AV_LOG_TRACE, "version =%d, isom =%d\n", version, c->isom);
3020
3/4
✓ Branch 0 taken 192 times.
✓ Branch 1 taken 87 times.
✓ Branch 2 taken 192 times.
✗ Branch 3 not taken.
279 if (!c->isom ||
3021
1/2
✓ Branch 0 taken 192 times.
✗ Branch 1 not taken.
192 (compatible_brands && strstr(compatible_brands->value, "qt ")) ||
3022
4/4
✓ Branch 0 taken 187 times.
✓ Branch 1 taken 5 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 183 times.
192 (sc->stsd_version == 0 && version > 0)) {
3023
2/2
✓ Branch 0 taken 49 times.
✓ Branch 1 taken 42 times.
91 if (version == 1) {
3024 49 sc->samples_per_frame = avio_rb32(pb);
3025 49 avio_rb32(pb); /* bytes per packet */
3026 49 sc->bytes_per_frame = avio_rb32(pb);
3027 49 avio_rb32(pb); /* bytes per sample */
3028
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 38 times.
42 } else if (version == 2) {
3029 4 avio_rb32(pb); /* sizeof struct only */
3030 4 st->codecpar->sample_rate = av_int2double(avio_rb64(pb));
3031 4 channel_count = avio_rb32(pb);
3032 4 st->codecpar->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC;
3033 4 st->codecpar->ch_layout.nb_channels = channel_count;
3034 4 avio_rb32(pb); /* always 0x7F000000 */
3035 4 st->codecpar->bits_per_coded_sample = avio_rb32(pb);
3036
3037 4 flags = avio_rb32(pb); /* lpcm format specific flag */
3038 4 sc->bytes_per_frame = avio_rb32(pb);
3039 4 sc->samples_per_frame = avio_rb32(pb);
3040
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (st->codecpar->codec_tag == MKTAG('l','p','c','m'))
3041 st->codecpar->codec_id =
3042 ff_mov_get_lpcm_codec_id(st->codecpar->bits_per_coded_sample,
3043 flags);
3044 }
3045
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)) {
3046 /* can't correctly handle variable sized packet as audio unit */
3047
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 62 times.
62 switch (st->codecpar->codec_id) {
3048 case AV_CODEC_ID_MP2:
3049 case AV_CODEC_ID_MP3:
3050 ffstream(st)->need_parsing = AVSTREAM_PARSE_FULL;
3051 break;
3052 }
3053 }
3054 }
3055
3056
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 279 times.
279 if (sc->format == 0) {
3057 if (st->codecpar->bits_per_coded_sample == 8)
3058 st->codecpar->codec_id = mov_codec_id(st, MKTAG('r','a','w',' '));
3059 else if (st->codecpar->bits_per_coded_sample == 16)
3060 st->codecpar->codec_id = mov_codec_id(st, MKTAG('t','w','o','s'));
3061 }
3062
3063
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 235 times.
279 switch (st->codecpar->codec_id) {
3064 7 case AV_CODEC_ID_PCM_S8:
3065 case AV_CODEC_ID_PCM_U8:
3066
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (st->codecpar->bits_per_coded_sample == 16)
3067 st->codecpar->codec_id = AV_CODEC_ID_PCM_S16BE;
3068 7 break;
3069 21 case AV_CODEC_ID_PCM_S16LE:
3070 case AV_CODEC_ID_PCM_S16BE:
3071
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 19 times.
21 if (st->codecpar->bits_per_coded_sample == 8)
3072 2 st->codecpar->codec_id = AV_CODEC_ID_PCM_S8;
3073
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 19 times.
19 else if (st->codecpar->bits_per_coded_sample == 24)
3074 st->codecpar->codec_id =
3075 st->codecpar->codec_id == AV_CODEC_ID_PCM_S16BE ?
3076 AV_CODEC_ID_PCM_S24BE : AV_CODEC_ID_PCM_S24LE;
3077
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 19 times.
19 else if (st->codecpar->bits_per_coded_sample == 32)
3078 st->codecpar->codec_id =
3079 st->codecpar->codec_id == AV_CODEC_ID_PCM_S16BE ?
3080 AV_CODEC_ID_PCM_S32BE : AV_CODEC_ID_PCM_S32LE;
3081 21 break;
3082 /* set values for old format before stsd version 1 appeared */
3083 2 case AV_CODEC_ID_MACE3:
3084 2 sc->samples_per_frame = 6;
3085 2 sc->bytes_per_frame = 2 * st->codecpar->ch_layout.nb_channels;
3086 2 break;
3087 8 case AV_CODEC_ID_MACE6:
3088 8 sc->samples_per_frame = 6;
3089 8 sc->bytes_per_frame = 1 * st->codecpar->ch_layout.nb_channels;
3090 8 break;
3091 5 case AV_CODEC_ID_ADPCM_IMA_QT:
3092 5 sc->samples_per_frame = 64;
3093 5 sc->bytes_per_frame = 34 * st->codecpar->ch_layout.nb_channels;
3094 5 break;
3095 1 case AV_CODEC_ID_GSM:
3096 1 sc->samples_per_frame = 160;
3097 1 sc->bytes_per_frame = 33;
3098 1 break;
3099 235 default:
3100 235 break;
3101 }
3102
3103 279 bits_per_sample = av_get_bits_per_sample(st->codecpar->codec_id);
3104
3/4
✓ Branch 0 taken 50 times.
✓ Branch 1 taken 229 times.
✓ Branch 2 taken 50 times.
✗ Branch 3 not taken.
279 if (bits_per_sample && (bits_per_sample >> 3) * (uint64_t)st->codecpar->ch_layout.nb_channels <= INT_MAX) {
3105 50 st->codecpar->bits_per_coded_sample = bits_per_sample;
3106 50 sc->sample_size = (bits_per_sample >> 3) * st->codecpar->ch_layout.nb_channels;
3107 }
3108 279 }
3109
3110 15 static void mov_parse_stsd_subtitle(MOVContext *c, AVIOContext *pb,
3111 AVStream *st, MOVStreamContext *sc,
3112 int64_t size)
3113 {
3114 // ttxt stsd contains display flags, justification, background
3115 // color, fonts, and default styles, so fake an atom to read it
3116 15 MOVAtom fake_atom = { .size = size };
3117 // mp4s contains a regular esds atom, dfxp ISMV TTML has no content
3118 // in extradata unlike stpp MP4 TTML.
3119
1/2
✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
15 if (st->codecpar->codec_tag != AV_RL32("mp4s") &&
3120
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 4 times.
15 st->codecpar->codec_tag != MOV_ISMV_TTML_TAG)
3121 11 mov_read_glbl(c, pb, fake_atom);
3122 15 st->codecpar->width = sc->width;
3123 15 st->codecpar->height = sc->height;
3124 15 }
3125
3126 43 static int mov_parse_stsd_data(MOVContext *c, AVIOContext *pb,
3127 AVStream *st, MOVStreamContext *sc,
3128 int64_t size)
3129 {
3130 int ret;
3131
3132
2/2
✓ Branch 0 taken 19 times.
✓ Branch 1 taken 24 times.
43 if (st->codecpar->codec_tag == MKTAG('t','m','c','d')) {
3133
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 19 times.
19 if ((int)size != size)
3134 return AVERROR(ENOMEM);
3135
3136 19 ret = ff_get_extradata(c->fc, st->codecpar, pb, size);
3137
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 19 times.
19 if (ret < 0)
3138 return ret;
3139
1/2
✓ Branch 0 taken 19 times.
✗ Branch 1 not taken.
19 if (size > 16) {
3140 19 MOVStreamContext *tmcd_ctx = st->priv_data;
3141 int val;
3142 19 val = AV_RB32(st->codecpar->extradata + 4);
3143 19 tmcd_ctx->tmcd_flags = val;
3144 19 st->avg_frame_rate.num = AV_RB32(st->codecpar->extradata + 8); /* timescale */
3145 19 st->avg_frame_rate.den = AV_RB32(st->codecpar->extradata + 12); /* frameDuration */
3146 19 tmcd_ctx->tmcd_nb_frames = st->codecpar->extradata[16]; /* number of frames */
3147
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 15 times.
19 if (size > 30) {
3148 4 uint32_t len = AV_RB32(st->codecpar->extradata + 18); /* name atom length */
3149 4 uint32_t format = AV_RB32(st->codecpar->extradata + 22);
3150
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) {
3151 4 uint16_t str_size = AV_RB16(st->codecpar->extradata + 26); /* string length */
3152
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 &&
3153
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 st->codecpar->extradata[30] /* Don't add empty string */) {
3154 4 char *reel_name = av_malloc(str_size + 1);
3155
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!reel_name)
3156 return AVERROR(ENOMEM);
3157 4 memcpy(reel_name, st->codecpar->extradata + 30, str_size);
3158 4 reel_name[str_size] = 0; /* Add null terminator */
3159 4 av_dict_set(&st->metadata, "reel_name", reel_name,
3160 AV_DICT_DONT_STRDUP_VAL);
3161 }
3162 }
3163 }
3164 }
3165
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 22 times.
24 } else if (st->codecpar->codec_id == AV_CODEC_ID_ITUT_T35) {
3166 2 int t35_identifier_length = avio_r8(pb);
3167
3168
2/4
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
2 if (t35_identifier_length <= 0 || t35_identifier_length >= size)
3169 return AVERROR_INVALIDDATA;
3170
3171 2 ret = ff_get_extradata(c->fc, st->codecpar, pb, t35_identifier_length);
3172
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (ret < 0)
3173 return ret;
3174
3175 2 int hrsd_len = size - t35_identifier_length - 1;
3176
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (hrsd_len > 0) {
3177 uint8_t *hrsd_str = av_malloc(hrsd_len + 1);
3178 if (!hrsd_str)
3179 return AVERROR(ENOMEM);
3180
3181 ret = ffio_read_size(pb, hrsd_str, hrsd_len);
3182 if (ret < 0) {
3183 av_free(hrsd_str);
3184 return ret;
3185 }
3186 if (hrsd_str[0]) {
3187 hrsd_str[hrsd_len] = 0;
3188 ret = av_dict_set(&st->metadata, "description", hrsd_str, AV_DICT_DONT_OVERWRITE);
3189 }
3190 av_free(hrsd_str);
3191 }
3192 } else {
3193 /* other codec type, just skip (rtp, mp4s ...) */
3194 22 avio_skip(pb, size);
3195 }
3196 43 return 0;
3197 }
3198
3199 673 static int mov_finalize_stsd_codec(MOVContext *c, AVIOContext *pb,
3200 AVStream *st, MOVStreamContext *sc)
3201 {
3202 673 FFStream *const sti = ffstream(st);
3203
3204
2/2
✓ Branch 0 taken 279 times.
✓ Branch 1 taken 394 times.
673 if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO &&
3205
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 279 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
279 !st->codecpar->sample_rate && sc->time_scale > 1)
3206 st->codecpar->sample_rate = sc->time_scale;
3207
3208 /* special codec parameters handling */
3209
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 14 times.
✓ Branch 8 taken 109 times.
✓ Branch 9 taken 505 times.
673 switch (st->codecpar->codec_id) {
3210 #if CONFIG_DV_DEMUXER
3211 case AV_CODEC_ID_DVAUDIO:
3212 if (c->dv_fctx) {
3213 avpriv_request_sample(c->fc, "multiple DV audio streams");
3214 return AVERROR(ENOSYS);
3215 }
3216
3217 c->dv_fctx = avformat_alloc_context();
3218 if (!c->dv_fctx) {
3219 av_log(c->fc, AV_LOG_ERROR, "dv demux context alloc error\n");
3220 return AVERROR(ENOMEM);
3221 }
3222 c->dv_demux = avpriv_dv_init_demux(c->dv_fctx);
3223 if (!c->dv_demux) {
3224 av_log(c->fc, AV_LOG_ERROR, "dv demux context init error\n");
3225 return AVERROR(ENOMEM);
3226 }
3227 sc->dv_audio_container = 1;
3228 st->codecpar->codec_id = AV_CODEC_ID_PCM_S16LE;
3229 break;
3230 #endif
3231 /* no ifdef since parameters are always those */
3232 case AV_CODEC_ID_QCELP:
3233 av_channel_layout_uninit(&st->codecpar->ch_layout);
3234 st->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO;
3235 // force sample rate for qcelp when not stored in mov
3236 if (st->codecpar->codec_tag != MKTAG('Q','c','l','p'))
3237 st->codecpar->sample_rate = 8000;
3238 // FIXME: Why is the following needed for some files?
3239 sc->samples_per_frame = 160;
3240 if (!sc->bytes_per_frame)
3241 sc->bytes_per_frame = 35;
3242 break;
3243 case AV_CODEC_ID_AMR_NB:
3244 av_channel_layout_uninit(&st->codecpar->ch_layout);
3245 st->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO;
3246 /* force sample rate for amr, stsd in 3gp does not store sample rate */
3247 st->codecpar->sample_rate = 8000;
3248 break;
3249 11 case AV_CODEC_ID_AMR_WB:
3250 11 av_channel_layout_uninit(&st->codecpar->ch_layout);
3251 11 st->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO;
3252 11 st->codecpar->sample_rate = 16000;
3253 11 break;
3254 3 case AV_CODEC_ID_MP2:
3255 case AV_CODEC_ID_MP3:
3256 /* force type after stsd for m1a hdlr */
3257 3 st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
3258 3 break;
3259 15 case AV_CODEC_ID_GSM:
3260 case AV_CODEC_ID_ADPCM_MS:
3261 case AV_CODEC_ID_ADPCM_IMA_WAV:
3262 case AV_CODEC_ID_ILBC:
3263 case AV_CODEC_ID_MACE3:
3264 case AV_CODEC_ID_MACE6:
3265 case AV_CODEC_ID_QDM2:
3266 15 st->codecpar->block_align = sc->bytes_per_frame;
3267 15 break;
3268 16 case AV_CODEC_ID_ALAC:
3269
1/2
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
16 if (st->codecpar->extradata_size == 36) {
3270 16 int channel_count = AV_RB8(st->codecpar->extradata + 21);
3271
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 if (st->codecpar->ch_layout.nb_channels != channel_count) {
3272 av_channel_layout_uninit(&st->codecpar->ch_layout);
3273 st->codecpar->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC;
3274 st->codecpar->ch_layout.nb_channels = channel_count;
3275 }
3276 16 st->codecpar->sample_rate = AV_RB32(st->codecpar->extradata + 32);
3277 }
3278 16 break;
3279 14 case AV_CODEC_ID_AC3:
3280 case AV_CODEC_ID_EAC3:
3281 case AV_CODEC_ID_MPEG1VIDEO:
3282 case AV_CODEC_ID_VC1:
3283 case AV_CODEC_ID_VP8:
3284 case AV_CODEC_ID_VP9:
3285 14 sti->need_parsing = AVSTREAM_PARSE_FULL;
3286 14 break;
3287 109 case AV_CODEC_ID_PRORES_RAW:
3288 case AV_CODEC_ID_PRORES:
3289 case AV_CODEC_ID_APV:
3290 case AV_CODEC_ID_EVC:
3291 case AV_CODEC_ID_LCEVC:
3292 case AV_CODEC_ID_AV1:
3293 /* field_order detection of H264 requires parsing */
3294 case AV_CODEC_ID_H264:
3295 109 sti->need_parsing = AVSTREAM_PARSE_HEADERS;
3296 109 break;
3297 505 default:
3298 505 break;
3299 }
3300 673 return 0;
3301 }
3302
3303 688 static int mov_skip_multiple_stsd(MOVContext *c, AVIOContext *pb,
3304 int codec_tag, int format,
3305 int64_t size)
3306 {
3307
3/4
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 673 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 15 times.
688 if (codec_tag &&
3308 (codec_tag != format &&
3309 // AVID 1:1 samples with differing data format and codec tag exist
3310 (codec_tag != AV_RL32("AV1x") || format != AV_RL32("AVup")) &&
3311 // prores is allowed to have differing data format and codec tag
3312 codec_tag != AV_RL32("apcn") && codec_tag != AV_RL32("apch") &&
3313 // so is dv (sigh)
3314 codec_tag != AV_RL32("dvpp") && codec_tag != AV_RL32("dvcp") &&
3315 (c->fc->video_codec_id ? ff_codec_get_id(ff_codec_movvideo_tags, format) != c->fc->video_codec_id
3316 : codec_tag != MKTAG('j','p','e','g')))) {
3317 /* Multiple fourcc, we skip JPEG. This is not correct, we should
3318 * export it as a separate AVStream but this needs a few changes
3319 * in the MOV demuxer, patch welcome. */
3320
3321 av_log(c->fc, AV_LOG_WARNING, "multiple fourcc not supported\n");
3322 avio_skip(pb, size);
3323 return 1;
3324 }
3325
3326 688 return 0;
3327 }
3328
3329 688 static int mov_finalize_stsd_entry(MOVContext *c, AVStream *st)
3330 {
3331 int ret;
3332
3333 /* special codec parameters handling */
3334
2/2
✓ Branch 0 taken 82 times.
✓ Branch 1 taken 606 times.
688 switch (st->codecpar->codec_id) {
3335 82 case AV_CODEC_ID_H264:
3336 // done for ai5q, ai52, ai55, ai1q, ai12 and ai15.
3337
1/30
✗ Branch 0 not taken.
✓ Branch 1 taken 82 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.
82 if (!st->codecpar->extradata_size && TAG_IS_AVCI(st->codecpar->codec_tag)) {
3338 ret = ff_generate_avci_extradata(st);
3339 if (ret < 0)
3340 return ret;
3341 }
3342 82 break;
3343 606 default:
3344 606 break;
3345 }
3346
3347 688 return 0;
3348 }
3349
3350 673 int ff_mov_read_stsd_entries(MOVContext *c, AVIOContext *pb, int entries)
3351 {
3352 AVStream *st;
3353 MOVStreamContext *sc;
3354 int pseudo_stream_id;
3355
3356
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 673 times.
673 av_assert0 (c->fc->nb_streams >= 1);
3357 673 st = c->fc->streams[c->fc->nb_streams-1];
3358 673 sc = st->priv_data;
3359
3360 673 for (pseudo_stream_id = 0;
3361
3/4
✓ Branch 0 taken 688 times.
✓ Branch 1 taken 673 times.
✓ Branch 2 taken 688 times.
✗ Branch 3 not taken.
1361 pseudo_stream_id < entries && !pb->eof_reached;
3362 688 pseudo_stream_id++) {
3363 //Parsing Sample description table
3364 enum AVCodecID id;
3365 688 int ret, dref_id = 1;
3366 688 MOVAtom a = { AV_RL32("stsd") };
3367 688 int64_t start_pos = avio_tell(pb);
3368 688 int64_t size = avio_rb32(pb); /* size */
3369 688 uint32_t format = avio_rl32(pb); /* data format */
3370
3371
1/2
✓ Branch 0 taken 688 times.
✗ Branch 1 not taken.
688 if (size >= 16) {
3372 688 avio_rb32(pb); /* reserved */
3373 688 avio_rb16(pb); /* reserved */
3374 688 dref_id = avio_rb16(pb);
3375 } else if (size <= 7) {
3376 av_log(c->fc, AV_LOG_ERROR,
3377 "invalid size %"PRId64" in stsd\n", size);
3378 return AVERROR_INVALIDDATA;
3379 }
3380
3381
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 688 times.
688 if (mov_skip_multiple_stsd(c, pb, st->codecpar->codec_tag, format,
3382 688 size - (avio_tell(pb) - start_pos))) {
3383 sc->stsd_count++;
3384 continue;
3385 }
3386
3387
2/2
✓ Branch 0 taken 673 times.
✓ Branch 1 taken 15 times.
688 sc->pseudo_stream_id = st->codecpar->codec_tag ? -1 : pseudo_stream_id;
3388 688 sc->dref_id= dref_id;
3389 688 sc->format = format;
3390
3391 688 id = mov_codec_id(st, format);
3392
3393 688 av_log(c->fc, AV_LOG_TRACE,
3394 "size=%"PRId64" 4CC=%s codec_type=%d\n", size,
3395 688 av_fourcc2str(format), st->codecpar->codec_type);
3396
3397 688 st->codecpar->codec_id = id;
3398
2/2
✓ Branch 0 taken 351 times.
✓ Branch 1 taken 337 times.
688 if (st->codecpar->codec_type==AVMEDIA_TYPE_VIDEO) {
3399 351 mov_parse_stsd_video(c, pb, st, sc);
3400
2/2
✓ Branch 0 taken 279 times.
✓ Branch 1 taken 58 times.
337 } else if (st->codecpar->codec_type==AVMEDIA_TYPE_AUDIO) {
3401 279 mov_parse_stsd_audio(c, pb, st, sc);
3402
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 279 times.
279 if (st->codecpar->sample_rate < 0) {
3403 av_log(c->fc, AV_LOG_ERROR, "Invalid sample rate %d\n", st->codecpar->sample_rate);
3404 return AVERROR_INVALIDDATA;
3405 }
3406
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 279 times.
279 if (st->codecpar->ch_layout.nb_channels < 0) {
3407 av_log(c->fc, AV_LOG_ERROR, "Invalid channels %d\n", st->codecpar->ch_layout.nb_channels);
3408 return AVERROR_INVALIDDATA;
3409 }
3410
2/2
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 43 times.
58 } else if (st->codecpar->codec_type==AVMEDIA_TYPE_SUBTITLE){
3411 15 mov_parse_stsd_subtitle(c, pb, st, sc,
3412 15 size - (avio_tell(pb) - start_pos));
3413 } else {
3414 43 ret = mov_parse_stsd_data(c, pb, st, sc,
3415 43 size - (avio_tell(pb) - start_pos));
3416
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 43 times.
43 if (ret < 0)
3417 return ret;
3418 }
3419 /* this will read extra atoms at the end (wave, alac, damr, avcC, hvcC, SMI ...) */
3420 688 a.size = size - (avio_tell(pb) - start_pos);
3421
2/2
✓ Branch 0 taken 549 times.
✓ Branch 1 taken 139 times.
688 if (a.size > 8) {
3422
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 549 times.
549 if ((ret = mov_read_default(c, pb, a)) < 0)
3423 return ret;
3424
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 138 times.
139 } else if (a.size > 0)
3425 1 avio_skip(pb, a.size);
3426
3427 688 ret = mov_finalize_stsd_entry(c, st);
3428
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 688 times.
688 if (ret < 0)
3429 return ret;
3430
3431
3/4
✓ Branch 0 taken 688 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 405 times.
✓ Branch 3 taken 283 times.
688 if (sc->extradata && st->codecpar->extradata) {
3432 405 int extra_size = st->codecpar->extradata_size;
3433
3434 /* Move the current stream extradata to the stream context one. */
3435 405 sc->extradata_size[pseudo_stream_id] = extra_size;
3436 405 sc->extradata[pseudo_stream_id] = st->codecpar->extradata;
3437 405 st->codecpar->extradata = NULL;
3438 405 st->codecpar->extradata_size = 0;
3439 }
3440 688 sc->stsd_count++;
3441 }
3442
3443
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 673 times.
673 if (pb->eof_reached) {
3444 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted STSD atom\n");
3445 return AVERROR_EOF;
3446 }
3447
3448 673 return 0;
3449 }
3450
3451 673 static int mov_read_stsd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3452 {
3453 AVStream *st;
3454 MOVStreamContext *sc;
3455 int ret, entries;
3456
3457
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 673 times.
673 if (c->fc->nb_streams < 1)
3458 return 0;
3459 673 st = c->fc->streams[c->fc->nb_streams - 1];
3460 673 sc = st->priv_data;
3461
3462
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 673 times.
673 if (sc->extradata) {
3463 av_log(c->fc, AV_LOG_ERROR,
3464 "Duplicate stsd found in this track.\n");
3465 return AVERROR_INVALIDDATA;
3466 }
3467
3468 673 sc->stsd_version = avio_r8(pb);
3469 673 avio_rb24(pb); /* flags */
3470 673 entries = avio_rb32(pb);
3471
3472 /* Each entry contains a size (4 bytes) and format (4 bytes). */
3473
3/6
✓ Branch 0 taken 673 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 673 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 673 times.
673 if (entries <= 0 || entries > atom.size / 8 || entries > 1024) {
3474 av_log(c->fc, AV_LOG_ERROR, "invalid STSD entries %d\n", entries);
3475 return AVERROR_INVALIDDATA;
3476 }
3477
3478 /* Prepare space for hosting multiple extradata. */
3479 673 sc->extradata = av_calloc(entries, sizeof(*sc->extradata));
3480
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 673 times.
673 if (!sc->extradata)
3481 return AVERROR(ENOMEM);
3482
3483 673 sc->extradata_size = av_calloc(entries, sizeof(*sc->extradata_size));
3484
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 673 times.
673 if (!sc->extradata_size) {
3485 ret = AVERROR(ENOMEM);
3486 goto fail;
3487 }
3488
3489 673 ret = ff_mov_read_stsd_entries(c, pb, entries);
3490
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 673 times.
673 if (ret < 0)
3491 goto fail;
3492
3493 /* Restore back the primary extradata. */
3494 673 av_freep(&st->codecpar->extradata);
3495 673 st->codecpar->extradata_size = sc->extradata_size[0];
3496
2/2
✓ Branch 0 taken 391 times.
✓ Branch 1 taken 282 times.
673 if (sc->extradata_size[0]) {
3497 391 st->codecpar->extradata = av_mallocz(sc->extradata_size[0] + AV_INPUT_BUFFER_PADDING_SIZE);
3498
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 391 times.
391 if (!st->codecpar->extradata)
3499 return AVERROR(ENOMEM);
3500 391 memcpy(st->codecpar->extradata, sc->extradata[0], sc->extradata_size[0]);
3501 }
3502
3503 673 return mov_finalize_stsd_codec(c, pb, st, sc);
3504 fail:
3505 if (sc->extradata) {
3506 int j;
3507 for (j = 0; j < sc->stsd_count; j++)
3508 av_freep(&sc->extradata[j]);
3509 }
3510
3511 sc->stsd_count = 0;
3512 av_freep(&sc->extradata);
3513 av_freep(&sc->extradata_size);
3514 return ret;
3515 }
3516
3517 673 static int mov_read_stsc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3518 {
3519 AVStream *st;
3520 MOVStreamContext *sc;
3521 unsigned int i, entries;
3522
3523
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 673 times.
673 if (c->trak_index < 0) {
3524 av_log(c->fc, AV_LOG_WARNING, "STSC outside TRAK\n");
3525 return 0;
3526 }
3527
3528
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 673 times.
673 if (c->fc->nb_streams < 1)
3529 return 0;
3530 673 st = c->fc->streams[c->fc->nb_streams-1];
3531 673 sc = st->priv_data;
3532
3533 673 avio_r8(pb); /* version */
3534 673 avio_rb24(pb); /* flags */
3535
3536 673 entries = avio_rb32(pb);
3537
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 673 times.
673 if ((uint64_t)entries * 12 + 4 > atom.size)
3538 return AVERROR_INVALIDDATA;
3539
3540 673 av_log(c->fc, AV_LOG_TRACE, "track[%u].stsc.entries = %u\n", c->fc->nb_streams - 1, entries);
3541
3542
2/2
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 645 times.
673 if (!entries)
3543 28 return 0;
3544
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 645 times.
645 if (sc->stsc_data) {
3545 av_log(c->fc, AV_LOG_WARNING, "Ignoring duplicated STSC atom\n");
3546 return 0;
3547 }
3548 645 av_free(sc->stsc_data);
3549 645 sc->stsc_count = 0;
3550 645 sc->stsc_data = av_malloc_array(entries, sizeof(*sc->stsc_data));
3551
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 645 times.
645 if (!sc->stsc_data)
3552 return AVERROR(ENOMEM);
3553
3554
3/4
✓ Branch 0 taken 3863 times.
✓ Branch 1 taken 645 times.
✓ Branch 2 taken 3863 times.
✗ Branch 3 not taken.
4508 for (i = 0; i < entries && !pb->eof_reached; i++) {
3555 3863 sc->stsc_data[i].first = avio_rb32(pb);
3556 3863 sc->stsc_data[i].count = avio_rb32(pb);
3557 3863 sc->stsc_data[i].id = avio_rb32(pb);
3558 }
3559
3560 645 sc->stsc_count = i;
3561
2/2
✓ Branch 0 taken 3863 times.
✓ Branch 1 taken 645 times.
4508 for (i = sc->stsc_count - 1; i < UINT_MAX; i--) {
3562 3863 int64_t first_min = i + 1;
3563
5/6
✓ Branch 0 taken 3218 times.
✓ Branch 1 taken 645 times.
✓ Branch 2 taken 3218 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3218 times.
✓ Branch 5 taken 645 times.
3863 if ((i+1 < sc->stsc_count && sc->stsc_data[i].first >= sc->stsc_data[i+1].first) ||
3564
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) ||
3565
1/2
✓ Branch 0 taken 3863 times.
✗ Branch 1 not taken.
3863 sc->stsc_data[i].first < first_min ||
3566
1/2
✓ Branch 0 taken 3863 times.
✗ Branch 1 not taken.
3863 sc->stsc_data[i].count < 1 ||
3567
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3863 times.
3863 sc->stsc_data[i].id < 1) {
3568 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);
3569 if (i+1 >= sc->stsc_count) {
3570 if (sc->stsc_data[i].count == 0 && i > 0) {
3571 sc->stsc_count --;
3572 continue;
3573 }
3574 sc->stsc_data[i].first = FFMAX(sc->stsc_data[i].first, first_min);
3575 if (i > 0 && sc->stsc_data[i].first <= sc->stsc_data[i-1].first)
3576 sc->stsc_data[i].first = FFMIN(sc->stsc_data[i-1].first + 1LL, INT_MAX);
3577 sc->stsc_data[i].count = FFMAX(sc->stsc_data[i].count, 1);
3578 sc->stsc_data[i].id = FFMAX(sc->stsc_data[i].id, 1);
3579 continue;
3580 }
3581 av_assert0(sc->stsc_data[i+1].first >= 2);
3582 // We replace this entry by the next valid
3583 sc->stsc_data[i].first = sc->stsc_data[i+1].first - 1;
3584 sc->stsc_data[i].count = sc->stsc_data[i+1].count;
3585 sc->stsc_data[i].id = sc->stsc_data[i+1].id;
3586 }
3587 }
3588
3589
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 645 times.
645 if (pb->eof_reached) {
3590 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted STSC atom\n");
3591 return AVERROR_EOF;
3592 }
3593
3594 645 return 0;
3595 }
3596
3597 353476 static inline int mov_stsc_index_valid(unsigned int index, unsigned int count)
3598 {
3599 353476 return index < count - 1;
3600 }
3601
3602 /* Compute the samples value for the stsc entry at the given index. */
3603 57252 static inline int64_t mov_get_stsc_samples(MOVStreamContext *sc, unsigned int index)
3604 {
3605 int chunk_count;
3606
3607
2/2
✓ Branch 1 taken 57056 times.
✓ Branch 2 taken 196 times.
57252 if (mov_stsc_index_valid(index, sc->stsc_count))
3608 57056 chunk_count = sc->stsc_data[index + 1].first - sc->stsc_data[index].first;
3609 else {
3610 // Validation for stsc / stco happens earlier in mov_read_stsc + mov_read_trak.
3611
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 196 times.
196 av_assert0(sc->stsc_data[index].first <= sc->chunk_count);
3612 196 chunk_count = sc->chunk_count - (sc->stsc_data[index].first - 1);
3613 }
3614
3615 57252 return sc->stsc_data[index].count * (int64_t)chunk_count;
3616 }
3617
3618 static int mov_read_stps(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3619 {
3620 AVStream *st;
3621 MOVStreamContext *sc;
3622 unsigned i, entries;
3623
3624 if (c->trak_index < 0) {
3625 av_log(c->fc, AV_LOG_WARNING, "STPS outside TRAK\n");
3626 return 0;
3627 }
3628
3629 if (c->fc->nb_streams < 1)
3630 return 0;
3631 st = c->fc->streams[c->fc->nb_streams-1];
3632 sc = st->priv_data;
3633
3634 avio_rb32(pb); // version + flags
3635
3636 entries = avio_rb32(pb);
3637 if (sc->stps_data)
3638 av_log(c->fc, AV_LOG_WARNING, "Duplicated STPS atom\n");
3639 av_free(sc->stps_data);
3640 sc->stps_count = 0;
3641 sc->stps_data = av_malloc_array(entries, sizeof(*sc->stps_data));
3642 if (!sc->stps_data)
3643 return AVERROR(ENOMEM);
3644
3645 for (i = 0; i < entries && !pb->eof_reached; i++) {
3646 sc->stps_data[i] = avio_rb32(pb);
3647 }
3648
3649 sc->stps_count = i;
3650
3651 if (pb->eof_reached) {
3652 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted STPS atom\n");
3653 return AVERROR_EOF;
3654 }
3655
3656 return 0;
3657 }
3658
3659 168 static int mov_read_stss(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3660 {
3661 AVStream *st;
3662 FFStream *sti;
3663 MOVStreamContext *sc;
3664 unsigned int i, entries;
3665
3666
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 168 times.
168 if (c->trak_index < 0) {
3667 av_log(c->fc, AV_LOG_WARNING, "STSS outside TRAK\n");
3668 return 0;
3669 }
3670
3671
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 168 times.
168 if (c->fc->nb_streams < 1)
3672 return 0;
3673 168 st = c->fc->streams[c->fc->nb_streams-1];
3674 168 sti = ffstream(st);
3675 168 sc = st->priv_data;
3676
3677 168 avio_r8(pb); /* version */
3678 168 avio_rb24(pb); /* flags */
3679
3680 168 entries = avio_rb32(pb);
3681
3682 168 av_log(c->fc, AV_LOG_TRACE, "keyframe_count = %u\n", entries);
3683
3684
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 154 times.
168 if (!entries) {
3685 14 sc->keyframe_absent = 1;
3686
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)
3687 sti->need_parsing = AVSTREAM_PARSE_HEADERS;
3688 14 return 0;
3689 }
3690
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 154 times.
154 if (sc->keyframes)
3691 av_log(c->fc, AV_LOG_WARNING, "Duplicated STSS atom\n");
3692
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 154 times.
154 if (entries >= UINT_MAX / sizeof(int))
3693 return AVERROR_INVALIDDATA;
3694 154 av_freep(&sc->keyframes);
3695 154 sc->keyframe_count = 0;
3696 154 sc->keyframes = av_malloc_array(entries, sizeof(*sc->keyframes));
3697
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 154 times.
154 if (!sc->keyframes)
3698 return AVERROR(ENOMEM);
3699
3700
3/4
✓ Branch 0 taken 5740 times.
✓ Branch 1 taken 154 times.
✓ Branch 2 taken 5740 times.
✗ Branch 3 not taken.
5894 for (i = 0; i < entries && !pb->eof_reached; i++) {
3701 5740 sc->keyframes[i] = avio_rb32(pb);
3702 }
3703
3704 154 sc->keyframe_count = i;
3705
3706
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 154 times.
154 if (pb->eof_reached) {
3707 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted STSS atom\n");
3708 return AVERROR_EOF;
3709 }
3710
3711 154 return 0;
3712 }
3713
3714 673 static int mov_read_stsz(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3715 {
3716 AVStream *st;
3717 MOVStreamContext *sc;
3718 unsigned int i, entries, sample_size, field_size, num_bytes;
3719 GetBitContext gb;
3720 unsigned char* buf;
3721 int ret;
3722
3723
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 673 times.
673 if (c->trak_index < 0) {
3724 av_log(c->fc, AV_LOG_WARNING, "STSZ outside TRAK\n");
3725 return 0;
3726 }
3727
3728
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 673 times.
673 if (c->fc->nb_streams < 1)
3729 return 0;
3730 673 st = c->fc->streams[c->fc->nb_streams-1];
3731 673 sc = st->priv_data;
3732
3733 673 avio_r8(pb); /* version */
3734 673 avio_rb24(pb); /* flags */
3735
3736
1/2
✓ Branch 0 taken 673 times.
✗ Branch 1 not taken.
673 if (atom.type == MKTAG('s','t','s','z')) {
3737 673 sample_size = avio_rb32(pb);
3738
2/2
✓ Branch 0 taken 630 times.
✓ Branch 1 taken 43 times.
673 if (!sc->sample_size) /* do not overwrite value computed in stsd */
3739 630 sc->sample_size = sample_size;
3740 673 sc->stsz_sample_size = sample_size;
3741 673 field_size = 32;
3742 } else {
3743 sample_size = 0;
3744 avio_rb24(pb); /* reserved */
3745 field_size = avio_r8(pb);
3746 }
3747 673 entries = avio_rb32(pb);
3748
3749 673 av_log(c->fc, AV_LOG_TRACE, "sample_size = %u sample_count = %u\n", sc->sample_size, entries);
3750
3751 673 sc->sample_count = entries;
3752
2/2
✓ Branch 0 taken 218 times.
✓ Branch 1 taken 455 times.
673 if (sample_size)
3753 218 return 0;
3754
3755
4/8
✓ Branch 0 taken 455 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 455 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 455 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 455 times.
455 if (field_size != 4 && field_size != 8 && field_size != 16 && field_size != 32) {
3756 av_log(c->fc, AV_LOG_ERROR, "Invalid sample field size %u\n", field_size);
3757 return AVERROR_INVALIDDATA;
3758 }
3759
3760
2/2
✓ Branch 0 taken 29 times.
✓ Branch 1 taken 426 times.
455 if (!entries)
3761 29 return 0;
3762
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 426 times.
426 if (entries >= (INT_MAX - 4 - 8 * AV_INPUT_BUFFER_PADDING_SIZE) / field_size)
3763 return AVERROR_INVALIDDATA;
3764
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 426 times.
426 if (sc->sample_sizes)
3765 av_log(c->fc, AV_LOG_WARNING, "Duplicated STSZ atom\n");
3766 426 av_free(sc->sample_sizes);
3767 426 sc->sample_count = 0;
3768 426 sc->sample_sizes = av_malloc_array(entries, sizeof(*sc->sample_sizes));
3769
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 426 times.
426 if (!sc->sample_sizes)
3770 return AVERROR(ENOMEM);
3771
3772 426 num_bytes = (entries*field_size+4)>>3;
3773
3774 426 buf = av_malloc(num_bytes+AV_INPUT_BUFFER_PADDING_SIZE);
3775
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 426 times.
426 if (!buf) {
3776 av_freep(&sc->sample_sizes);
3777 return AVERROR(ENOMEM);
3778 }
3779
3780 426 ret = ffio_read_size(pb, buf, num_bytes);
3781
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 426 times.
426 if (ret < 0) {
3782 av_freep(&sc->sample_sizes);
3783 av_free(buf);
3784 av_log(c->fc, AV_LOG_WARNING, "STSZ atom truncated\n");
3785 return 0;
3786 }
3787
3788 426 init_get_bits(&gb, buf, 8*num_bytes);
3789
3790
2/2
✓ Branch 0 taken 238666 times.
✓ Branch 1 taken 426 times.
239092 for (i = 0; i < entries; i++) {
3791 238666 sc->sample_sizes[i] = get_bits_long(&gb, field_size);
3792
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 238666 times.
238666 if (sc->sample_sizes[i] > INT64_MAX - sc->data_size) {
3793 av_free(buf);
3794 av_log(c->fc, AV_LOG_ERROR, "Sample size overflow in STSZ\n");
3795 return AVERROR_INVALIDDATA;
3796 }
3797 238666 sc->data_size += sc->sample_sizes[i];
3798 }
3799
3800 426 sc->sample_count = i;
3801
3802 426 av_free(buf);
3803
3804 426 return 0;
3805 }
3806
3807 673 static int mov_read_stts(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3808 {
3809 AVStream *st;
3810 MOVStreamContext *sc;
3811 unsigned int i, entries;
3812 673 int64_t duration = 0;
3813 673 int64_t total_sample_count = 0;
3814 673 int64_t current_dts = 0;
3815 673 int64_t corrected_dts = 0;
3816
3817
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 673 times.
673 if (c->trak_index < 0) {
3818 av_log(c->fc, AV_LOG_WARNING, "STTS outside TRAK\n");
3819 return 0;
3820 }
3821
3822
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 673 times.
673 if (c->fc->nb_streams < 1)
3823 return 0;
3824 673 st = c->fc->streams[c->fc->nb_streams-1];
3825 673 sc = st->priv_data;
3826
3827 673 avio_r8(pb); /* version */
3828 673 avio_rb24(pb); /* flags */
3829 673 entries = avio_rb32(pb);
3830
3831 673 av_log(c->fc, AV_LOG_TRACE, "track[%u].stts.entries = %u\n",
3832 673 c->fc->nb_streams-1, entries);
3833
3834
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 673 times.
673 if (sc->stts_data)
3835 av_log(c->fc, AV_LOG_WARNING, "Duplicated STTS atom\n");
3836 673 av_freep(&sc->stts_data);
3837 673 sc->stts_count = 0;
3838
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 673 times.
673 if (entries >= INT_MAX / sizeof(*sc->stts_data))
3839 return AVERROR(ENOMEM);
3840
3841
3/4
✓ Branch 0 taken 3047 times.
✓ Branch 1 taken 673 times.
✓ Branch 2 taken 3047 times.
✗ Branch 3 not taken.
3720 for (i = 0; i < entries && !pb->eof_reached; i++) {
3842 unsigned int sample_duration;
3843 unsigned int sample_count;
3844 3047 unsigned int min_entries = FFMIN(FFMAX(i + 1, 1024 * 1024), entries);
3845 3047 MOVStts *stts_data = av_fast_realloc(sc->stts_data, &sc->stts_allocated_size,
3846 min_entries * sizeof(*sc->stts_data));
3847
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3047 times.
3047 if (!stts_data) {
3848 av_freep(&sc->stts_data);
3849 sc->stts_count = 0;
3850 return AVERROR(ENOMEM);
3851 }
3852 3047 sc->stts_count = min_entries;
3853 3047 sc->stts_data = stts_data;
3854
3855 3047 sample_count = avio_rb32(pb);
3856 3047 sample_duration = avio_rb32(pb);
3857
3858 3047 sc->stts_data[i].count= sample_count;
3859 3047 sc->stts_data[i].duration= sample_duration;
3860
3861 3047 av_log(c->fc, AV_LOG_TRACE, "sample_count=%u, sample_duration=%u\n",
3862 sample_count, sample_duration);
3863
3864 /* STTS sample offsets are uint32 but some files store it as int32
3865 * with negative values used to correct DTS delays.
3866 There may be abnormally large values as well. */
3867
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 3046 times.
3047 if (sample_duration > c->max_stts_delta) {
3868 // assume high delta is a correction if negative when cast as int32
3869 1 int32_t delta_magnitude = (int32_t)sample_duration;
3870 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",
3871 sample_duration, i, sample_count, st->index);
3872 1 sc->stts_data[i].duration = 1;
3873
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);
3874 } else {
3875 3046 corrected_dts += sample_duration * (uint64_t)sample_count;
3876 }
3877
3878 3047 current_dts += sc->stts_data[i].duration * (uint64_t)sample_count;
3879
3880
2/2
✓ Branch 0 taken 22 times.
✓ Branch 1 taken 3025 times.
3047 if (current_dts > corrected_dts) {
3881 22 int64_t drift = av_sat_sub64(current_dts, corrected_dts) / FFMAX(sample_count, 1);
3882
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;
3883 22 current_dts -= correction * (uint64_t)sample_count;
3884 22 sc->stts_data[i].duration -= correction;
3885 }
3886
3887 3047 duration+=(int64_t)sc->stts_data[i].duration*(uint64_t)sc->stts_data[i].count;
3888 3047 total_sample_count+=sc->stts_data[i].count;
3889 }
3890
3891 673 sc->stts_count = i;
3892
3893
2/2
✓ Branch 0 taken 644 times.
✓ Branch 1 taken 29 times.
673 if (duration > 0 &&
3894
1/2
✓ Branch 0 taken 644 times.
✗ Branch 1 not taken.
644 duration <= INT64_MAX - sc->duration_for_fps &&
3895
1/2
✓ Branch 0 taken 644 times.
✗ Branch 1 not taken.
644 total_sample_count <= INT_MAX - sc->nb_frames_for_fps) {
3896 644 sc->duration_for_fps += duration;
3897 644 sc->nb_frames_for_fps += total_sample_count;
3898 }
3899
3900
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 673 times.
673 if (pb->eof_reached) {
3901 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted STTS atom\n");
3902 return AVERROR_EOF;
3903 }
3904
3905 673 st->nb_frames= total_sample_count;
3906
2/2
✓ Branch 0 taken 644 times.
✓ Branch 1 taken 29 times.
673 if (duration)
3907 644 st->duration= FFMIN(st->duration, duration);
3908
3909 // All samples have zero duration. They have higher chance be chose by
3910 // mov_find_next_sample, which leads to seek again and again.
3911 //
3912 // It's AVERROR_INVALIDDATA actually, but such files exist in the wild.
3913 // So only mark data stream as discarded for safety.
3914
3/4
✓ Branch 0 taken 29 times.
✓ Branch 1 taken 644 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 29 times.
673 if (!duration && sc->stts_count &&
3915 st->codecpar->codec_type == AVMEDIA_TYPE_DATA) {
3916 av_log(c->fc, AV_LOG_WARNING,
3917 "All samples in data stream index:id [%d:%d] have zero "
3918 "duration, stream set to be discarded by default. Override "
3919 "using AVStream->discard or -discard for ffmpeg command.\n",
3920 st->index, sc->id);
3921 st->discard = AVDISCARD_ALL;
3922 }
3923 673 sc->track_end = duration;
3924 673 return 0;
3925 }
3926
3927 46 static int mov_read_sdtp(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3928 {
3929 AVStream *st;
3930 MOVStreamContext *sc;
3931 unsigned int i;
3932 int64_t entries;
3933
3934
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 46 times.
46 if (c->fc->nb_streams < 1)
3935 return 0;
3936 46 st = c->fc->streams[c->fc->nb_streams - 1];
3937 46 sc = st->priv_data;
3938
3939 46 avio_r8(pb); /* version */
3940 46 avio_rb24(pb); /* flags */
3941 46 entries = atom.size - 4;
3942
3943 46 av_log(c->fc, AV_LOG_TRACE, "track[%u].sdtp.entries = %" PRId64 "\n",
3944 46 c->fc->nb_streams - 1, entries);
3945
3946
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 38 times.
46 if (sc->sdtp_data)
3947 8 av_log(c->fc, AV_LOG_WARNING, "Duplicated SDTP atom\n");
3948 46 av_freep(&sc->sdtp_data);
3949 46 sc->sdtp_count = 0;
3950
3951
2/4
✓ Branch 0 taken 46 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 46 times.
46 if (entries < 0 || entries > UINT_MAX)
3952 return AVERROR(ERANGE);
3953
3954 46 sc->sdtp_data = av_malloc(entries);
3955
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 46 times.
46 if (!sc->sdtp_data)
3956 return AVERROR(ENOMEM);
3957
3958
3/4
✓ Branch 0 taken 3823 times.
✓ Branch 1 taken 46 times.
✓ Branch 2 taken 3823 times.
✗ Branch 3 not taken.
3869 for (i = 0; i < entries && !pb->eof_reached; i++)
3959 3823 sc->sdtp_data[i] = avio_r8(pb);
3960 46 sc->sdtp_count = i;
3961
3962 46 return 0;
3963 }
3964
3965 13728 static void mov_update_dts_shift(MOVStreamContext *sc, int duration, void *logctx)
3966 {
3967
2/2
✓ Branch 0 taken 1136 times.
✓ Branch 1 taken 12592 times.
13728 if (duration < 0) {
3968
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1136 times.
1136 if (duration == INT_MIN) {
3969 av_log(logctx, AV_LOG_WARNING, "mov_update_dts_shift(): dts_shift set to %d\n", INT_MAX);
3970 duration++;
3971 }
3972 1136 sc->dts_shift = FFMAX(sc->dts_shift, -duration);
3973 }
3974 13728 }
3975
3976 76 static int mov_read_ctts(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3977 {
3978 AVStream *st;
3979 MOVStreamContext *sc;
3980 76 unsigned int i, entries, ctts_count = 0;
3981
3982
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 76 times.
76 if (c->trak_index < 0) {
3983 av_log(c->fc, AV_LOG_WARNING, "CTTS outside TRAK\n");
3984 return 0;
3985 }
3986
3987
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 76 times.
76 if (c->fc->nb_streams < 1)
3988 return 0;
3989 76 st = c->fc->streams[c->fc->nb_streams-1];
3990 76 sc = st->priv_data;
3991
3992 76 avio_r8(pb); /* version */
3993 76 avio_rb24(pb); /* flags */
3994 76 entries = avio_rb32(pb);
3995
3996 76 av_log(c->fc, AV_LOG_TRACE, "track[%u].ctts.entries = %u\n", c->fc->nb_streams - 1, entries);
3997
3998
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 72 times.
76 if (!entries)
3999 4 return 0;
4000
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 72 times.
72 if (entries >= UINT_MAX / sizeof(*sc->ctts_data))
4001 return AVERROR_INVALIDDATA;
4002 72 av_freep(&sc->ctts_data);
4003 72 sc->ctts_data = av_fast_realloc(NULL, &sc->ctts_allocated_size, entries * sizeof(*sc->ctts_data));
4004
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 72 times.
72 if (!sc->ctts_data)
4005 return AVERROR(ENOMEM);
4006
4007
3/4
✓ Branch 0 taken 5153 times.
✓ Branch 1 taken 72 times.
✓ Branch 2 taken 5153 times.
✗ Branch 3 not taken.
5225 for (i = 0; i < entries && !pb->eof_reached; i++) {
4008 MOVCtts *ctts_data;
4009 5153 const size_t min_size_needed = (ctts_count + 1) * sizeof(MOVCtts);
4010 5153 const size_t requested_size =
4011 5153 min_size_needed > sc->ctts_allocated_size ?
4012
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5153 times.
5153 FFMAX(min_size_needed, 2 * sc->ctts_allocated_size) :
4013 min_size_needed;
4014 5153 int count = avio_rb32(pb);
4015 5153 int duration = avio_rb32(pb);
4016
4017
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5153 times.
5153 if (count <= 0) {
4018 av_log(c->fc, AV_LOG_TRACE,
4019 "ignoring CTTS entry with count=%d duration=%d\n",
4020 count, duration);
4021 continue;
4022 }
4023
4024
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5153 times.
5153 if (ctts_count >= UINT_MAX / sizeof(MOVCtts) - 1)
4025 return AVERROR(ENOMEM);
4026
4027 5153 ctts_data = av_fast_realloc(sc->ctts_data, &sc->ctts_allocated_size, requested_size);
4028
4029
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5153 times.
5153 if (!ctts_data)
4030 return AVERROR(ENOMEM);
4031
4032 5153 sc->ctts_data = ctts_data;
4033
4034 5153 ctts_data[ctts_count].count = count;
4035 5153 ctts_data[ctts_count].offset = duration;
4036 5153 ctts_count++;
4037
4038 5153 av_log(c->fc, AV_LOG_TRACE, "count=%d, duration=%d\n",
4039 count, duration);
4040
4041
2/2
✓ Branch 0 taken 5021 times.
✓ Branch 1 taken 132 times.
5153 if (i+2<entries)
4042 5021 mov_update_dts_shift(sc, duration, c->fc);
4043 }
4044
4045 72 sc->ctts_count = ctts_count;
4046
4047
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 72 times.
72 if (pb->eof_reached) {
4048 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted CTTS atom\n");
4049 return AVERROR_EOF;
4050 }
4051
4052 72 av_log(c->fc, AV_LOG_TRACE, "dts shift %d\n", sc->dts_shift);
4053
4054 72 return 0;
4055 }
4056
4057 51 static int mov_read_sgpd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
4058 {
4059 AVStream *st;
4060 MOVStreamContext *sc;
4061 uint8_t version;
4062 uint32_t grouping_type;
4063 uint32_t default_length;
4064 av_unused uint32_t default_group_description_index;
4065 uint32_t entry_count;
4066
4067
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 51 times.
51 if (c->fc->nb_streams < 1)
4068 return 0;
4069 51 st = c->fc->streams[c->fc->nb_streams - 1];
4070 51 sc = st->priv_data;
4071
4072 51 version = avio_r8(pb); /* version */
4073 51 avio_rb24(pb); /* flags */
4074 51 grouping_type = avio_rl32(pb);
4075
4076 /*
4077 * This function only supports "sync" boxes, but the code is able to parse
4078 * other boxes (such as "tscl", "tsas" and "stsa")
4079 */
4080
2/2
✓ Branch 0 taken 46 times.
✓ Branch 1 taken 5 times.
51 if (grouping_type != MKTAG('s','y','n','c'))
4081 46 return 0;
4082
4083
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 default_length = version >= 1 ? avio_rb32(pb) : 0;
4084
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 default_group_description_index = version >= 2 ? avio_rb32(pb) : 0;
4085 5 entry_count = avio_rb32(pb);
4086
4087
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (entry_count > atom.size)
4088 return AVERROR_INVALIDDATA;
4089
4090 5 av_freep(&sc->sgpd_sync);
4091 5 sc->sgpd_sync_count = entry_count;
4092 5 sc->sgpd_sync = av_calloc(entry_count, sizeof(*sc->sgpd_sync));
4093
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (!sc->sgpd_sync)
4094 return AVERROR(ENOMEM);
4095
4096
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++) {
4097 8 uint32_t description_length = default_length;
4098
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)
4099 description_length = avio_rb32(pb);
4100
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 if (grouping_type == MKTAG('s','y','n','c')) {
4101 8 const uint8_t nal_unit_type = avio_r8(pb) & 0x3f;
4102 8 sc->sgpd_sync[i] = nal_unit_type;
4103 8 description_length -= 1;
4104 }
4105 8 avio_skip(pb, description_length);
4106 }
4107
4108
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (pb->eof_reached) {
4109 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted SGPD atom\n");
4110 return AVERROR_EOF;
4111 }
4112
4113 5 return 0;
4114 }
4115
4116 47 static int mov_read_sbgp(MOVContext *c, AVIOContext *pb, MOVAtom atom)
4117 {
4118 AVStream *st;
4119 MOVStreamContext *sc;
4120 unsigned int i, entries;
4121 uint8_t version;
4122 uint32_t grouping_type;
4123 MOVSbgp *table, **tablep;
4124 int *table_count;
4125
4126
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 47 times.
47 if (c->fc->nb_streams < 1)
4127 return 0;
4128 47 st = c->fc->streams[c->fc->nb_streams-1];
4129 47 sc = st->priv_data;
4130
4131 47 version = avio_r8(pb); /* version */
4132 47 avio_rb24(pb); /* flags */
4133 47 grouping_type = avio_rl32(pb);
4134
4135
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 46 times.
47 if (grouping_type == MKTAG('r','a','p',' ')) {
4136 1 tablep = &sc->rap_group;
4137 1 table_count = &sc->rap_group_count;
4138
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 41 times.
46 } else if (grouping_type == MKTAG('s','y','n','c')) {
4139 5 tablep = &sc->sync_group;
4140 5 table_count = &sc->sync_group_count;
4141 } else {
4142 41 return 0;
4143 }
4144
4145
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (version == 1)
4146 avio_rb32(pb); /* grouping_type_parameter */
4147
4148 6 entries = avio_rb32(pb);
4149
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (!entries)
4150 return 0;
4151
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (*tablep)
4152 av_log(c->fc, AV_LOG_WARNING, "Duplicated SBGP %s atom\n", av_fourcc2str(grouping_type));
4153 6 av_freep(tablep);
4154 6 table = av_malloc_array(entries, sizeof(*table));
4155
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (!table)
4156 return AVERROR(ENOMEM);
4157 6 *tablep = table;
4158
4159
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++) {
4160 32 table[i].count = avio_rb32(pb); /* sample_count */
4161 32 table[i].index = avio_rb32(pb); /* group_description_index */
4162 }
4163
4164 6 *table_count = i;
4165
4166
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (pb->eof_reached) {
4167 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted SBGP atom\n");
4168 return AVERROR_EOF;
4169 }
4170
4171 6 return 0;
4172 }
4173
4174 /**
4175 * Get ith edit list entry (media time, duration).
4176 */
4177 1015 static int get_edit_list_entry(MOVContext *mov,
4178 const MOVStreamContext *msc,
4179 unsigned int edit_list_index,
4180 int64_t *edit_list_media_time,
4181 int64_t *edit_list_duration,
4182 int64_t global_timescale)
4183 {
4184
2/2
✓ Branch 0 taken 493 times.
✓ Branch 1 taken 522 times.
1015 if (edit_list_index == msc->elst_count) {
4185 493 return 0;
4186 }
4187 522 *edit_list_media_time = msc->elst_data[edit_list_index].time;
4188 522 *edit_list_duration = msc->elst_data[edit_list_index].duration;
4189
4190 /* duration is in global timescale units;convert to msc timescale */
4191
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 522 times.
522 if (global_timescale == 0) {
4192 avpriv_request_sample(mov->fc, "Support for mvhd.timescale = 0 with editlists");
4193 return 0;
4194 }
4195 522 *edit_list_duration = av_rescale(*edit_list_duration, msc->time_scale,
4196 global_timescale);
4197
4198
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 522 times.
522 if (*edit_list_duration + (uint64_t)*edit_list_media_time > INT64_MAX)
4199 *edit_list_duration = 0;
4200
4201 522 return 1;
4202 }
4203
4204 /**
4205 * Find the closest previous frame to the timestamp_pts, in e_old index
4206 * entries. Searching for just any frame / just key frames can be controlled by
4207 * last argument 'flag'.
4208 * Note that if ctts_data is not NULL, we will always search for a key frame
4209 * irrespective of the value of 'flag'. If we don't find any keyframe, we will
4210 * return the first frame of the video.
4211 *
4212 * Here the timestamp_pts is considered to be a presentation timestamp and
4213 * the timestamp of index entries are considered to be decoding timestamps.
4214 *
4215 * Returns 0 if successful in finding a frame, else returns -1.
4216 * Places the found index corresponding output arg.
4217 *
4218 * If ctts_old is not NULL, then refines the searched entry by searching
4219 * backwards from the found timestamp, to find the frame with correct PTS.
4220 *
4221 * Places the found ctts_index and ctts_sample in corresponding output args.
4222 */
4223 522 static int find_prev_closest_index(AVStream *st,
4224 AVIndexEntry *e_old,
4225 int nb_old,
4226 MOVTimeToSample *tts_data,
4227 int64_t tts_count,
4228 int64_t timestamp_pts,
4229 int flag,
4230 int64_t* index,
4231 int64_t* tts_index,
4232 int64_t* tts_sample)
4233 {
4234 522 MOVStreamContext *msc = st->priv_data;
4235 522 FFStream *const sti = ffstream(st);
4236 522 AVIndexEntry *e_keep = sti->index_entries;
4237 522 int nb_keep = sti->nb_index_entries;
4238 522 int64_t i = 0;
4239
4240
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 522 times.
522 av_assert0(index);
4241
4242 // If dts_shift > 0, then all the index timestamps will have to be offset by
4243 // at least dts_shift amount to obtain PTS.
4244 // Hence we decrement the searched timestamp_pts by dts_shift to find the closest index element.
4245
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 513 times.
522 if (msc->dts_shift > 0) {
4246 9 timestamp_pts -= msc->dts_shift;
4247 }
4248
4249 522 sti->index_entries = e_old;
4250 522 sti->nb_index_entries = nb_old;
4251 522 *index = av_index_search_timestamp(st, timestamp_pts, flag | AVSEEK_FLAG_BACKWARD);
4252
4253 // Keep going backwards in the index entries until the timestamp is the same.
4254
2/2
✓ Branch 0 taken 521 times.
✓ Branch 1 taken 1 times.
522 if (*index >= 0) {
4255
3/4
✓ Branch 0 taken 27 times.
✓ Branch 1 taken 494 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 27 times.
521 for (i = *index; i > 0 && e_old[i].timestamp == e_old[i - 1].timestamp;
4256 i--) {
4257 if ((flag & AVSEEK_FLAG_ANY) ||
4258 (e_old[i - 1].flags & AVINDEX_KEYFRAME)) {
4259 *index = i - 1;
4260 }
4261 }
4262 }
4263
4264 // If we have CTTS then refine the search, by searching backwards over PTS
4265 // computed by adding corresponding CTTS durations to index timestamps.
4266
4/4
✓ Branch 0 taken 80 times.
✓ Branch 1 taken 442 times.
✓ Branch 2 taken 79 times.
✓ Branch 3 taken 1 times.
522 if (msc->ctts_count && *index >= 0) {
4267
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 79 times.
79 av_assert0(tts_index);
4268
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 79 times.
79 av_assert0(tts_sample);
4269 // Find out the ctts_index for the found frame.
4270 79 *tts_index = 0;
4271 79 *tts_sample = 0;
4272
2/2
✓ Branch 0 taken 214 times.
✓ Branch 1 taken 79 times.
293 for (int64_t index_tts_count = 0; index_tts_count < *index; index_tts_count++) {
4273
1/2
✓ Branch 0 taken 214 times.
✗ Branch 1 not taken.
214 if (*tts_index < tts_count) {
4274 214 (*tts_sample)++;
4275
1/2
✓ Branch 0 taken 214 times.
✗ Branch 1 not taken.
214 if (tts_data[*tts_index].count == *tts_sample) {
4276 214 (*tts_index)++;
4277 214 *tts_sample = 0;
4278 }
4279 }
4280 }
4281
4282
4/6
✓ Branch 0 taken 89 times.
✓ Branch 1 taken 7 times.
✓ Branch 2 taken 89 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 89 times.
✗ Branch 5 not taken.
96 while (*index >= 0 && (*tts_index) >= 0 && (*tts_index) < tts_count) {
4283 // Find a "key frame" with PTS <= timestamp_pts (So that we can decode B-frames correctly).
4284 // No need to add dts_shift to the timestamp here because timestamp_pts has already been
4285 // compensated by dts_shift above.
4286
2/2
✓ Branch 0 taken 77 times.
✓ Branch 1 taken 12 times.
89 if ((e_old[*index].timestamp + tts_data[*tts_index].offset) <= timestamp_pts &&
4287
2/2
✓ Branch 0 taken 72 times.
✓ Branch 1 taken 5 times.
77 (e_old[*index].flags & AVINDEX_KEYFRAME)) {
4288 72 break;
4289 }
4290
4291 17 (*index)--;
4292
1/2
✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
17 if (*tts_sample == 0) {
4293 17 (*tts_index)--;
4294
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 7 times.
17 if (*tts_index >= 0)
4295 10 *tts_sample = tts_data[*tts_index].count - 1;
4296 } else {
4297 (*tts_sample)--;
4298 }
4299 }
4300 }
4301
4302 /* restore AVStream state*/
4303 522 sti->index_entries = e_keep;
4304 522 sti->nb_index_entries = nb_keep;
4305
2/2
✓ Branch 0 taken 514 times.
✓ Branch 1 taken 8 times.
522 return *index >= 0 ? 0 : -1;
4306 }
4307
4308 /**
4309 * Add index entry with the given values, to the end of ffstream(st)->index_entries.
4310 * Returns the new size ffstream(st)->index_entries if successful, else returns -1.
4311 *
4312 * This function is similar to ff_add_index_entry in libavformat/utils.c
4313 * except that here we are always unconditionally adding an index entry to
4314 * the end, instead of searching the entries list and skipping the add if
4315 * there is an existing entry with the same timestamp.
4316 * This is needed because the mov_fix_index calls this func with the same
4317 * unincremented timestamp for successive discarded frames.
4318 */
4319 360390 static int64_t add_index_entry(AVStream *st, int64_t pos, int64_t timestamp,
4320 int size, int distance, int flags)
4321 {
4322 360390 FFStream *const sti = ffstream(st);
4323 AVIndexEntry *entries, *ie;
4324 360390 int64_t index = -1;
4325 360390 const size_t min_size_needed = (sti->nb_index_entries + 1) * sizeof(AVIndexEntry);
4326
4327 // Double the allocation each time, to lower memory fragmentation.
4328 // Another difference from ff_add_index_entry function.
4329 360390 const size_t requested_size =
4330 360390 min_size_needed > sti->index_entries_allocated_size ?
4331
2/2
✓ Branch 0 taken 2247 times.
✓ Branch 1 taken 358143 times.
360390 FFMAX(min_size_needed, 2 * sti->index_entries_allocated_size) :
4332 min_size_needed;
4333
4334
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 360390 times.
360390 if (sti->nb_index_entries + 1U >= UINT_MAX / sizeof(AVIndexEntry))
4335 return -1;
4336
4337 360390 entries = av_fast_realloc(sti->index_entries,
4338 &sti->index_entries_allocated_size,
4339 requested_size);
4340
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 360390 times.
360390 if (!entries)
4341 return -1;
4342
4343 360390 sti->index_entries = entries;
4344
4345 360390 index = sti->nb_index_entries++;
4346 360390 ie= &entries[index];
4347
4348 360390 ie->pos = pos;
4349 360390 ie->timestamp = timestamp;
4350 360390 ie->min_distance= distance;
4351 360390 ie->size= size;
4352 360390 ie->flags = flags;
4353 360390 return index;
4354 }
4355
4356 /**
4357 * Rewrite timestamps of index entries in the range [end_index - frame_duration_buffer_size, end_index)
4358 * by subtracting end_ts successively by the amounts given in frame_duration_buffer.
4359 */
4360 47 static void fix_index_entry_timestamps(AVStream* st, int end_index, int64_t end_ts,
4361 int64_t* frame_duration_buffer,
4362 int frame_duration_buffer_size) {
4363 47 FFStream *const sti = ffstream(st);
4364 47 int i = 0;
4365
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);
4366
2/2
✓ Branch 0 taken 191 times.
✓ Branch 1 taken 47 times.
238 for (i = 0; i < frame_duration_buffer_size; i++) {
4367 191 end_ts -= frame_duration_buffer[frame_duration_buffer_size - 1 - i];
4368 191 sti->index_entries[end_index - 1 - i].timestamp = end_ts;
4369 }
4370 47 }
4371
4372 195163 static int add_tts_entry(MOVTimeToSample **tts_data, unsigned int *tts_count, unsigned int *allocated_size,
4373 int count, int offset, unsigned int duration)
4374 {
4375 MOVTimeToSample *tts_buf_new;
4376 195163 const size_t min_size_needed = (*tts_count + 1) * sizeof(MOVTimeToSample);
4377 195163 const size_t requested_size =
4378 195163 min_size_needed > *allocated_size ?
4379
2/2
✓ Branch 0 taken 1577 times.
✓ Branch 1 taken 193586 times.
195163 FFMAX(min_size_needed, 2 * (*allocated_size)) :
4380 min_size_needed;
4381
4382
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 195163 times.
195163 if ((unsigned)(*tts_count) >= UINT_MAX / sizeof(MOVTimeToSample) - 1)
4383 return -1;
4384
4385 195163 tts_buf_new = av_fast_realloc(*tts_data, allocated_size, requested_size);
4386
4387
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 195163 times.
195163 if (!tts_buf_new)
4388 return -1;
4389
4390 195163 *tts_data = tts_buf_new;
4391
4392 195163 tts_buf_new[*tts_count].count = count;
4393 195163 tts_buf_new[*tts_count].offset = offset;
4394 195163 tts_buf_new[*tts_count].duration = duration;
4395
4396 195163 *tts_count = (*tts_count) + 1;
4397 195163 return 0;
4398 }
4399
4400 #define MAX_REORDER_DELAY 16
4401 687 static void mov_estimate_video_delay(MOVContext *c, AVStream* st)
4402 {
4403 687 MOVStreamContext *msc = st->priv_data;
4404 687 FFStream *const sti = ffstream(st);
4405 687 int ctts_ind = 0;
4406 687 int ctts_sample = 0;
4407 int64_t pts_buf[MAX_REORDER_DELAY + 1]; // Circular buffer to sort pts.
4408 687 int buf_start = 0;
4409 int j, r, num_swaps;
4410
4411
2/2
✓ Branch 0 taken 11679 times.
✓ Branch 1 taken 687 times.
12366 for (j = 0; j < MAX_REORDER_DELAY + 1; j++)
4412 11679 pts_buf[j] = INT64_MIN;
4413
4414
3/4
✓ Branch 0 taken 687 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 72 times.
✓ Branch 3 taken 615 times.
687 if (st->codecpar->video_delay <= 0 && msc->ctts_count &&
4415
2/2
✓ Branch 0 taken 45 times.
✓ Branch 1 taken 27 times.
72 st->codecpar->codec_id == AV_CODEC_ID_H264) {
4416 45 st->codecpar->video_delay = 0;
4417
3/4
✓ Branch 0 taken 138365 times.
✓ Branch 1 taken 45 times.
✓ Branch 2 taken 138365 times.
✗ Branch 3 not taken.
138410 for (int ind = 0; ind < sti->nb_index_entries && ctts_ind < msc->tts_count; ++ind) {
4418 // Point j to the last elem of the buffer and insert the current pts there.
4419 138365 j = buf_start;
4420 138365 buf_start = (buf_start + 1);
4421
2/2
✓ Branch 0 taken 8115 times.
✓ Branch 1 taken 130250 times.
138365 if (buf_start == MAX_REORDER_DELAY + 1)
4422 8115 buf_start = 0;
4423
4424 138365 pts_buf[j] = sti->index_entries[ind].timestamp + msc->tts_data[ctts_ind].offset;
4425
4426 // The timestamps that are already in the sorted buffer, and are greater than the
4427 // current pts, are exactly the timestamps that need to be buffered to output PTS
4428 // in correct sorted order.
4429 // Hence the video delay (which is the buffer size used to sort DTS and output PTS),
4430 // can be computed as the maximum no. of swaps any particular timestamp needs to
4431 // go through, to keep this buffer in sorted order.
4432 138365 num_swaps = 0;
4433
2/2
✓ Branch 0 taken 142605 times.
✓ Branch 1 taken 4 times.
142609 while (j != buf_start) {
4434 142605 r = j - 1;
4435
2/2
✓ Branch 0 taken 8407 times.
✓ Branch 1 taken 134198 times.
142605 if (r < 0) r = MAX_REORDER_DELAY;
4436
2/2
✓ Branch 0 taken 4244 times.
✓ Branch 1 taken 138361 times.
142605 if (pts_buf[j] < pts_buf[r]) {
4437 4244 FFSWAP(int64_t, pts_buf[j], pts_buf[r]);
4438 4244 ++num_swaps;
4439 } else {
4440 138361 break;
4441 }
4442 4244 j = r;
4443 }
4444 138365 st->codecpar->video_delay = FFMAX(st->codecpar->video_delay, num_swaps);
4445
4446 138365 ctts_sample++;
4447
1/2
✓ Branch 0 taken 138365 times.
✗ Branch 1 not taken.
138365 if (ctts_sample == msc->tts_data[ctts_ind].count) {
4448 138365 ctts_ind++;
4449 138365 ctts_sample = 0;
4450 }
4451 }
4452 45 av_log(c->fc, AV_LOG_DEBUG, "Setting codecpar->delay to %d for stream st: %d\n",
4453 45 st->codecpar->video_delay, st->index);
4454 }
4455 687 }
4456
4457 116638 static void mov_current_sample_inc(MOVStreamContext *sc)
4458 {
4459 116638 sc->current_sample++;
4460 116638 sc->current_index++;
4461
2/2
✓ Branch 0 taken 70640 times.
✓ Branch 1 taken 45998 times.
116638 if (sc->index_ranges &&
4462
2/2
✓ Branch 0 taken 477 times.
✓ Branch 1 taken 70163 times.
70640 sc->current_index >= sc->current_index_range->end &&
4463
1/2
✓ Branch 0 taken 477 times.
✗ Branch 1 not taken.
477 sc->current_index_range->end) {
4464 477 sc->current_index_range++;
4465 477 sc->current_index = sc->current_index_range->start;
4466 }
4467 116638 }
4468
4469 static void mov_current_sample_dec(MOVStreamContext *sc)
4470 {
4471 sc->current_sample--;
4472 sc->current_index--;
4473 if (sc->index_ranges &&
4474 sc->current_index < sc->current_index_range->start &&
4475 sc->current_index_range > sc->index_ranges) {
4476 sc->current_index_range--;
4477 sc->current_index = sc->current_index_range->end - 1;
4478 }
4479 }
4480
4481 337 static void mov_current_sample_set(MOVStreamContext *sc, int current_sample)
4482 {
4483 int64_t range_size;
4484
4485 337 sc->current_sample = current_sample;
4486 337 sc->current_index = current_sample;
4487
2/2
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 309 times.
337 if (!sc->index_ranges) {
4488 28 return;
4489 }
4490
4491 309 for (sc->current_index_range = sc->index_ranges;
4492
1/2
✓ Branch 0 taken 309 times.
✗ Branch 1 not taken.
309 sc->current_index_range->end;
4493 sc->current_index_range++) {
4494 309 range_size = sc->current_index_range->end - sc->current_index_range->start;
4495
1/2
✓ Branch 0 taken 309 times.
✗ Branch 1 not taken.
309 if (range_size > current_sample) {
4496 309 sc->current_index = sc->current_index_range->start + current_sample;
4497 309 break;
4498 }
4499 current_sample -= range_size;
4500 }
4501 }
4502
4503 /**
4504 * Fix ffstream(st)->index_entries, so that it contains only the entries (and the entries
4505 * which are needed to decode them) that fall in the edit list time ranges.
4506 * Also fixes the timestamps of the index entries to match the timeline
4507 * specified the edit lists.
4508 */
4509 687 static void mov_fix_index(MOVContext *mov, AVStream *st)
4510 {
4511 687 MOVStreamContext *msc = st->priv_data;
4512 687 FFStream *const sti = ffstream(st);
4513 687 AVIndexEntry *e_old = sti->index_entries;
4514 687 int nb_old = sti->nb_index_entries;
4515 687 const AVIndexEntry *e_old_end = e_old + nb_old;
4516 687 const AVIndexEntry *current = NULL;
4517 687 MOVTimeToSample *tts_data_old = msc->tts_data;
4518 687 int64_t tts_index_old = 0;
4519 687 int64_t tts_sample_old = 0;
4520 687 int64_t tts_count_old = msc->tts_count;
4521 687 int64_t edit_list_media_time = 0;
4522 687 int64_t edit_list_duration = 0;
4523 687 int64_t frame_duration = 0;
4524 687 int64_t edit_list_dts_counter = 0;
4525 687 int64_t edit_list_dts_entry_end = 0;
4526 687 int64_t edit_list_start_tts_sample = 0;
4527 int64_t curr_cts;
4528 687 int64_t curr_ctts = 0;
4529 687 int64_t empty_edits_sum_duration = 0;
4530 687 int64_t edit_list_index = 0;
4531 int64_t index;
4532 int flags;
4533 687 int64_t start_dts = 0;
4534 687 int64_t edit_list_start_encountered = 0;
4535 687 int64_t search_timestamp = 0;
4536 687 int64_t* frame_duration_buffer = NULL;
4537 687 int num_discarded_begin = 0;
4538 687 int first_non_zero_audio_edit = -1;
4539 687 int packet_skip_samples = 0;
4540 687 MOVIndexRange *current_index_range = NULL;
4541 687 int found_keyframe_after_edit = 0;
4542 687 int found_non_empty_edit = 0;
4543
4544
4/6
✓ Branch 0 taken 493 times.
✓ Branch 1 taken 194 times.
✓ Branch 2 taken 493 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 493 times.
687 if (!msc->elst_data || msc->elst_count <= 0 || nb_old <= 0) {
4545 194 return;
4546 }
4547
4548 // allocate the index ranges array
4549 493 msc->index_ranges = av_malloc_array(msc->elst_count + 1,
4550 sizeof(msc->index_ranges[0]));
4551
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 493 times.
493 if (!msc->index_ranges) {
4552 av_log(mov->fc, AV_LOG_ERROR, "Cannot allocate index ranges buffer\n");
4553 return;
4554 }
4555 493 msc->current_index_range = msc->index_ranges;
4556
4557 // Clean AVStream from traces of old index
4558 493 sti->index_entries = NULL;
4559 493 sti->index_entries_allocated_size = 0;
4560 493 sti->nb_index_entries = 0;
4561
4562 // Clean time to sample fields of MOVStreamContext
4563 493 msc->tts_data = NULL;
4564 493 msc->tts_count = 0;
4565 493 msc->tts_index = 0;
4566 493 msc->tts_sample = 0;
4567 493 msc->tts_allocated_size = 0;
4568
4569 // Reinitialize min_corrected_pts so that it can be computed again.
4570 493 msc->min_corrected_pts = -1;
4571
4572 // If the dts_shift is positive (in case of negative ctts values in mov),
4573 // then negate the DTS by dts_shift
4574
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 484 times.
493 if (msc->dts_shift > 0) {
4575 9 edit_list_dts_entry_end -= msc->dts_shift;
4576 9 av_log(mov->fc, AV_LOG_DEBUG, "Shifting DTS by %d because of negative CTTS.\n", msc->dts_shift);
4577 }
4578
4579 493 start_dts = edit_list_dts_entry_end;
4580
4581
2/2
✓ Branch 0 taken 522 times.
✓ Branch 1 taken 493 times.
1508 while (get_edit_list_entry(mov, msc, edit_list_index, &edit_list_media_time,
4582 1015 &edit_list_duration, mov->time_scale)) {
4583 522 av_log(mov->fc, AV_LOG_DEBUG, "Processing st: %d, edit list %"PRId64" - media time: %"PRId64", duration: %"PRId64"\n",
4584 st->index, edit_list_index, edit_list_media_time, edit_list_duration);
4585 522 edit_list_index++;
4586 522 edit_list_dts_counter = edit_list_dts_entry_end;
4587 522 edit_list_dts_entry_end = av_sat_add64(edit_list_dts_entry_end, edit_list_duration);
4588
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 522 times.
522 if (edit_list_dts_entry_end == INT64_MAX) {
4589 av_log(mov->fc, AV_LOG_ERROR, "Cannot calculate dts entry length with duration %"PRId64"\n",
4590 edit_list_duration);
4591 break;
4592 }
4593 522 num_discarded_begin = 0;
4594
4/4
✓ Branch 0 taken 497 times.
✓ Branch 1 taken 25 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 493 times.
522 if (!found_non_empty_edit && edit_list_media_time == -1) {
4595 4 empty_edits_sum_duration += edit_list_duration;
4596 4 continue;
4597 }
4598 518 found_non_empty_edit = 1;
4599
4600 // If we encounter a non-negative edit list reset the skip_samples/initial_padding fields and set them
4601 // according to the edit list below.
4602
2/2
✓ Branch 0 taken 159 times.
✓ Branch 1 taken 359 times.
518 if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
4603
1/2
✓ Branch 0 taken 159 times.
✗ Branch 1 not taken.
159 if (first_non_zero_audio_edit < 0) {
4604 159 first_non_zero_audio_edit = 1;
4605 } else {
4606 first_non_zero_audio_edit = 0;
4607 }
4608
4609
1/2
✓ Branch 0 taken 159 times.
✗ Branch 1 not taken.
159 if (first_non_zero_audio_edit > 0)
4610 159 sti->skip_samples = st->codecpar->initial_padding = 0;
4611 }
4612
4613 // While reordering frame index according to edit list we must handle properly
4614 // the scenario when edit list entry starts from none key frame.
4615 // We find closest previous key frame and preserve it and consequent frames in index.
4616 // All frames which are outside edit list entry time boundaries will be dropped after decoding.
4617 518 search_timestamp = edit_list_media_time;
4618
2/2
✓ Branch 0 taken 159 times.
✓ Branch 1 taken 359 times.
518 if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
4619 // Audio decoders like AAC need need a decoder delay samples previous to the current sample,
4620 // to correctly decode this frame. Hence for audio we seek to a frame 1 sec. before the
4621 // edit_list_media_time to cover the decoder delay.
4622 159 search_timestamp = FFMAX(search_timestamp - msc->time_scale, e_old[0].timestamp);
4623 }
4624
4625
2/2
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 514 times.
518 if (find_prev_closest_index(st, e_old, nb_old, tts_data_old, tts_count_old, search_timestamp, 0,
4626 &index, &tts_index_old, &tts_sample_old) < 0) {
4627 4 av_log(mov->fc, AV_LOG_WARNING,
4628 "st: %d edit list: %"PRId64" Missing key frame while searching for timestamp: %"PRId64"\n",
4629 st->index, edit_list_index, search_timestamp);
4630
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,
4631 &index, &tts_index_old, &tts_sample_old) < 0) {
4632 4 av_log(mov->fc, AV_LOG_WARNING,
4633 "st: %d edit list %"PRId64" Cannot find an index entry before timestamp: %"PRId64".\n",
4634 st->index, edit_list_index, search_timestamp);
4635 4 index = 0;
4636 4 tts_index_old = 0;
4637 4 tts_sample_old = 0;
4638 }
4639 }
4640 518 current = e_old + index;
4641 518 edit_list_start_tts_sample = tts_sample_old;
4642
4643 // Iterate over index and arrange it according to edit list
4644 518 edit_list_start_encountered = 0;
4645 518 found_keyframe_after_edit = 0;
4646
2/2
✓ Branch 0 taken 360390 times.
✓ Branch 1 taken 130 times.
360520 for (; current < e_old_end; current++, index++) {
4647 // check if frame outside edit list mark it for discard
4648 720780 frame_duration = (current + 1 < e_old_end) ?
4649
2/2
✓ Branch 0 taken 359905 times.
✓ Branch 1 taken 485 times.
360390 ((current + 1)->timestamp - current->timestamp) : edit_list_duration;
4650
4651 360390 flags = current->flags;
4652
4653 // frames (pts) before or after edit list
4654 360390 curr_cts = current->timestamp + msc->dts_shift;
4655 360390 curr_ctts = 0;
4656
4657
4/4
✓ Branch 0 taken 195175 times.
✓ Branch 1 taken 165215 times.
✓ Branch 2 taken 195163 times.
✓ Branch 3 taken 12 times.
360390 if (tts_data_old && tts_index_old < tts_count_old) {
4658 195163 curr_ctts = tts_data_old[tts_index_old].offset;
4659 195163 av_log(mov->fc, AV_LOG_TRACE, "stts: %"PRId64" ctts: %"PRId64", tts_index: %"PRId64", tts_count: %"PRId64"\n",
4660 curr_cts, curr_ctts, tts_index_old, tts_count_old);
4661 195163 curr_cts += curr_ctts;
4662 195163 tts_sample_old++;
4663
1/2
✓ Branch 0 taken 195163 times.
✗ Branch 1 not taken.
195163 if (tts_sample_old == tts_data_old[tts_index_old].count) {
4664
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 195163 times.
195163 if (add_tts_entry(&msc->tts_data, &msc->tts_count,
4665 &msc->tts_allocated_size,
4666 195163 tts_data_old[tts_index_old].count - edit_list_start_tts_sample,
4667 195163 tts_data_old[tts_index_old].offset, tts_data_old[tts_index_old].duration) == -1) {
4668 av_log(mov->fc, AV_LOG_ERROR, "Cannot add Time To Sample entry %"PRId64" - {%"PRId64", %d}\n",
4669 tts_index_old,
4670 tts_data_old[tts_index_old].count - edit_list_start_tts_sample,
4671 tts_data_old[tts_index_old].offset);
4672 break;
4673 }
4674 195163 tts_index_old++;
4675 195163 tts_sample_old = 0;
4676 195163 edit_list_start_tts_sample = 0;
4677 }
4678 }
4679
4680
4/4
✓ Branch 0 taken 360170 times.
✓ Branch 1 taken 220 times.
✓ Branch 2 taken 157 times.
✓ Branch 3 taken 360013 times.
360390 if (curr_cts < edit_list_media_time || curr_cts >= (edit_list_duration + edit_list_media_time)) {
4681
4/4
✓ Branch 0 taken 121 times.
✓ Branch 1 taken 256 times.
✓ Branch 2 taken 77 times.
✓ Branch 3 taken 44 times.
377 if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO && st->codecpar->codec_id != AV_CODEC_ID_VORBIS &&
4682
4/6
✓ Branch 0 taken 77 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 25 times.
✓ Branch 3 taken 52 times.
✓ Branch 4 taken 25 times.
✗ Branch 5 not taken.
77 curr_cts < edit_list_media_time && curr_cts + frame_duration > edit_list_media_time &&
4683 first_non_zero_audio_edit > 0) {
4684 25 packet_skip_samples = edit_list_media_time - curr_cts;
4685 25 sti->skip_samples += packet_skip_samples;
4686
4687 // Shift the index entry timestamp by packet_skip_samples to be correct.
4688 25 edit_list_dts_counter -= packet_skip_samples;
4689
1/2
✓ Branch 0 taken 25 times.
✗ Branch 1 not taken.
25 if (edit_list_start_encountered == 0) {
4690 25 edit_list_start_encountered = 1;
4691 // Make timestamps strictly monotonically increasing for audio, by rewriting timestamps for
4692 // discarded packets.
4693
2/2
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 10 times.
25 if (frame_duration_buffer) {
4694 15 fix_index_entry_timestamps(st, sti->nb_index_entries, edit_list_dts_counter,
4695 frame_duration_buffer, num_discarded_begin);
4696 15 av_freep(&frame_duration_buffer);
4697 }
4698 }
4699
4700 25 av_log(mov->fc, AV_LOG_DEBUG, "skip %d audio samples from curr_cts: %"PRId64"\n", packet_skip_samples, curr_cts);
4701 } else {
4702 352 flags |= AVINDEX_DISCARD_FRAME;
4703 352 av_log(mov->fc, AV_LOG_DEBUG, "drop a frame at curr_cts: %"PRId64" @ %"PRId64"\n", curr_cts, index);
4704
4705
2/2
✓ Branch 0 taken 193 times.
✓ Branch 1 taken 159 times.
352 if (edit_list_start_encountered == 0) {
4706 193 num_discarded_begin++;
4707 193 frame_duration_buffer = av_realloc(frame_duration_buffer,
4708 num_discarded_begin * sizeof(int64_t));
4709
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 193 times.
193 if (!frame_duration_buffer) {
4710 av_log(mov->fc, AV_LOG_ERROR, "Cannot reallocate frame duration buffer\n");
4711 break;
4712 }
4713 193 frame_duration_buffer[num_discarded_begin - 1] = frame_duration;
4714
4715 // Increment skip_samples for the first non-zero audio edit list
4716
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 &&
4717
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) {
4718 52 sti->skip_samples += frame_duration;
4719 }
4720 }
4721 }
4722 } else {
4723
2/2
✓ Branch 0 taken 492 times.
✓ Branch 1 taken 359521 times.
360013 if (msc->min_corrected_pts < 0) {
4724 492 msc->min_corrected_pts = edit_list_dts_counter + curr_ctts + msc->dts_shift;
4725 } else {
4726 359521 msc->min_corrected_pts = FFMIN(msc->min_corrected_pts, edit_list_dts_counter + curr_ctts + msc->dts_shift);
4727 }
4728
2/2
✓ Branch 0 taken 491 times.
✓ Branch 1 taken 359522 times.
360013 if (edit_list_start_encountered == 0) {
4729 491 edit_list_start_encountered = 1;
4730 // Make timestamps strictly monotonically increasing by rewriting timestamps for
4731 // discarded packets.
4732
2/2
✓ Branch 0 taken 32 times.
✓ Branch 1 taken 459 times.
491 if (frame_duration_buffer) {
4733 32 fix_index_entry_timestamps(st, sti->nb_index_entries, edit_list_dts_counter,
4734 frame_duration_buffer, num_discarded_begin);
4735 32 av_freep(&frame_duration_buffer);
4736 }
4737 }
4738 }
4739
4740
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 360390 times.
360390 if (add_index_entry(st, current->pos, edit_list_dts_counter, current->size,
4741 360390 current->min_distance, flags) == -1) {
4742 av_log(mov->fc, AV_LOG_ERROR, "Cannot add index entry\n");
4743 break;
4744 }
4745
4746 // Update the index ranges array
4747
4/4
✓ Branch 0 taken 359897 times.
✓ Branch 1 taken 493 times.
✓ Branch 2 taken 23 times.
✓ Branch 3 taken 359874 times.
360390 if (!current_index_range || index != current_index_range->end) {
4748 516 current_index_range = current_index_range ? current_index_range + 1
4749
2/2
✓ Branch 0 taken 23 times.
✓ Branch 1 taken 493 times.
516 : msc->index_ranges;
4750 516 current_index_range->start = index;
4751 }
4752 360390 current_index_range->end = index + 1;
4753
4754 // Only start incrementing DTS in frame_duration amounts, when we encounter a frame in edit list.
4755
2/2
✓ Branch 0 taken 360197 times.
✓ Branch 1 taken 193 times.
360390 if (edit_list_start_encountered > 0) {
4756 360197 edit_list_dts_counter = edit_list_dts_counter + frame_duration;
4757 }
4758
4759 // Break when found first key frame after edit entry completion
4760
2/2
✓ Branch 0 taken 706 times.
✓ Branch 1 taken 359684 times.
360390 if ((curr_cts + frame_duration >= (edit_list_duration + edit_list_media_time)) &&
4761
4/4
✓ Branch 0 taken 298 times.
✓ Branch 1 taken 408 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 297 times.
706 ((flags & AVINDEX_KEYFRAME) || ((st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO)))) {
4762
2/2
✓ Branch 0 taken 32 times.
✓ Branch 1 taken 377 times.
409 if (msc->ctts_count) {
4763 // If we have CTTS and this is the first keyframe after edit elist,
4764 // wait for one more, because there might be trailing B-frames after this I-frame
4765 // that do belong to the edit.
4766
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) {
4767 21 found_keyframe_after_edit = 1;
4768 21 continue;
4769 }
4770
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (tts_sample_old != 0) {
4771 if (add_tts_entry(&msc->tts_data, &msc->tts_count,
4772 &msc->tts_allocated_size,
4773 tts_sample_old - edit_list_start_tts_sample,
4774 tts_data_old[tts_index_old].offset, tts_data_old[tts_index_old].duration) == -1) {
4775 av_log(mov->fc, AV_LOG_ERROR, "Cannot add Time To Sample entry %"PRId64" - {%"PRId64", %d}\n",
4776 tts_index_old, tts_sample_old - edit_list_start_tts_sample,
4777 tts_data_old[tts_index_old].offset);
4778 break;
4779 }
4780 }
4781 }
4782 388 break;
4783 }
4784 }
4785 }
4786 // If there are empty edits, then msc->min_corrected_pts might be positive
4787 // intentionally. So we subtract the sum duration of empty edits here.
4788 493 msc->min_corrected_pts -= empty_edits_sum_duration;
4789
4790 // If the minimum pts turns out to be greater than zero after fixing the index, then we subtract the
4791 // dts by that amount to make the first pts zero.
4792
2/2
✓ Branch 0 taken 292 times.
✓ Branch 1 taken 201 times.
493 if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
4793
2/2
✓ Branch 0 taken 54 times.
✓ Branch 1 taken 238 times.
292 if (msc->min_corrected_pts > 0) {
4794 54 av_log(mov->fc, AV_LOG_DEBUG, "Offset DTS by %"PRId64" to make first pts zero.\n", msc->min_corrected_pts);
4795
2/2
✓ Branch 0 taken 3135 times.
✓ Branch 1 taken 54 times.
3189 for (int i = 0; i < sti->nb_index_entries; ++i)
4796 3135 sti->index_entries[i].timestamp -= msc->min_corrected_pts;
4797 }
4798 }
4799 // Start time should be equal to zero or the duration of any empty edits.
4800 493 st->start_time = empty_edits_sum_duration;
4801
4802 // Update av stream length, if it ends up shorter than the track's media duration
4803 493 st->duration = FFMIN(st->duration, edit_list_dts_entry_end - start_dts);
4804 493 st->codecpar->initial_padding = sti->skip_samples;
4805
4806 // Free the old index and the old CTTS structures
4807 493 av_free(e_old);
4808 493 av_free(tts_data_old);
4809 493 av_freep(&frame_duration_buffer);
4810
4811 // Null terminate the index ranges array
4812 493 current_index_range = current_index_range ? current_index_range + 1
4813
1/2
✓ Branch 0 taken 493 times.
✗ Branch 1 not taken.
493 : msc->index_ranges;
4814 493 current_index_range->start = 0;
4815 493 current_index_range->end = 0;
4816 493 msc->current_index = msc->index_ranges[0].start;
4817 }
4818
4819 5 static uint32_t get_sgpd_sync_index(const MOVStreamContext *sc, int nal_unit_type)
4820 {
4821
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 for (uint32_t i = 0; i < sc->sgpd_sync_count; i++)
4822
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 3 times.
8 if (sc->sgpd_sync[i] == nal_unit_type)
4823 5 return i + 1;
4824 return 0;
4825 }
4826
4827 716 static int build_open_gop_key_points(AVStream *st)
4828 {
4829 int k;
4830 716 int sample_id = 0;
4831 uint32_t cra_index;
4832 716 MOVStreamContext *sc = st->priv_data;
4833
4834
4/4
✓ Branch 0 taken 65 times.
✓ Branch 1 taken 651 times.
✓ Branch 2 taken 60 times.
✓ Branch 3 taken 5 times.
716 if (st->codecpar->codec_id != AV_CODEC_ID_HEVC || !sc->sync_group_count)
4835 711 return 0;
4836
4837 /* Build an unrolled index of the samples */
4838 5 sc->sample_offsets_count = 0;
4839
2/2
✓ Branch 0 taken 322 times.
✓ Branch 1 taken 5 times.
327 for (uint32_t i = 0; i < sc->ctts_count; i++) {
4840
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 322 times.
322 if (sc->ctts_data[i].count > INT_MAX - sc->sample_offsets_count)
4841 return AVERROR(ENOMEM);
4842 322 sc->sample_offsets_count += sc->ctts_data[i].count;
4843 }
4844 5 av_freep(&sc->sample_offsets);
4845 5 sc->sample_offsets = av_calloc(sc->sample_offsets_count, sizeof(*sc->sample_offsets));
4846
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (!sc->sample_offsets)
4847 return AVERROR(ENOMEM);
4848 5 k = 0;
4849
2/2
✓ Branch 0 taken 322 times.
✓ Branch 1 taken 5 times.
327 for (uint32_t i = 0; i < sc->ctts_count; i++)
4850
2/2
✓ Branch 0 taken 322 times.
✓ Branch 1 taken 322 times.
644 for (int j = 0; j < sc->ctts_data[i].count; j++)
4851 322 sc->sample_offsets[k++] = sc->ctts_data[i].offset;
4852
4853 /* The following HEVC NAL type reveal the use of open GOP sync points
4854 * (TODO: BLA types may also be concerned) */
4855 5 cra_index = get_sgpd_sync_index(sc, HEVC_NAL_CRA_NUT); /* Clean Random Access */
4856
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (!cra_index)
4857 return 0;
4858
4859 /* Build a list of open-GOP key samples */
4860 5 sc->open_key_samples_count = 0;
4861
2/2
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 5 times.
33 for (uint32_t i = 0; i < sc->sync_group_count; i++)
4862
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 17 times.
28 if (sc->sync_group[i].index == cra_index) {
4863
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)
4864 return AVERROR(ENOMEM);
4865 11 sc->open_key_samples_count += sc->sync_group[i].count;
4866 }
4867 5 av_freep(&sc->open_key_samples);
4868 5 sc->open_key_samples = av_calloc(sc->open_key_samples_count, sizeof(*sc->open_key_samples));
4869
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (!sc->open_key_samples)
4870 return AVERROR(ENOMEM);
4871 5 k = 0;
4872
2/2
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 5 times.
33 for (uint32_t i = 0; i < sc->sync_group_count; i++) {
4873 28 const MOVSbgp *sg = &sc->sync_group[i];
4874
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 17 times.
28 if (sg->index == cra_index)
4875
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 11 times.
22 for (uint32_t j = 0; j < sg->count; j++)
4876 11 sc->open_key_samples[k++] = sample_id;
4877
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
28 if (sg->count > INT_MAX - sample_id)
4878 return AVERROR_PATCHWELCOME;
4879 28 sample_id += sg->count;
4880 }
4881
4882 /* Identify the minimal time step between samples */
4883 5 sc->min_sample_duration = UINT_MAX;
4884
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 5 times.
16 for (uint32_t i = 0; i < sc->stts_count; i++)
4885 11 sc->min_sample_duration = FFMIN(sc->min_sample_duration, sc->stts_data[i].duration);
4886
4887 5 return 0;
4888 }
4889
4890 #define MOV_MERGE_CTTS 1
4891 #define MOV_MERGE_STTS 2
4892 /*
4893 * Merge stts and ctts arrays into a new combined array.
4894 * stts_count and ctts_count may be left untouched as they will be
4895 * used to check for the presence of either of them.
4896 */
4897 687 static int mov_merge_tts_data(MOVContext *mov, AVStream *st, int flags)
4898 {
4899 687 MOVStreamContext *sc = st->priv_data;
4900
3/4
✓ Branch 0 taken 72 times.
✓ Branch 1 taken 615 times.
✓ Branch 2 taken 72 times.
✗ Branch 3 not taken.
687 int ctts = sc->ctts_data && (flags & MOV_MERGE_CTTS);
4901
3/4
✓ Branch 0 taken 687 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 619 times.
✓ Branch 3 taken 68 times.
687 int stts = sc->stts_data && (flags & MOV_MERGE_STTS);
4902 687 int idx = 0;
4903
4904
3/4
✓ Branch 0 taken 615 times.
✓ Branch 1 taken 72 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 615 times.
687 if (!sc->ctts_data && !sc->stts_data)
4905 return 0;
4906 // Expand time to sample entries such that we have a 1-1 mapping with samples
4907
2/4
✓ Branch 0 taken 687 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 687 times.
687 if (!sc->sample_count || sc->sample_count >= UINT_MAX / sizeof(*sc->tts_data))
4908 return -1;
4909
4910
2/2
✓ Branch 0 taken 72 times.
✓ Branch 1 taken 615 times.
687 if (ctts) {
4911 144 sc->tts_data = av_fast_realloc(NULL, &sc->tts_allocated_size,
4912 72 sc->sample_count * sizeof(*sc->tts_data));
4913
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 72 times.
72 if (!sc->tts_data)
4914 return -1;
4915
4916 72 memset(sc->tts_data, 0, sc->tts_allocated_size);
4917
4918
2/2
✓ Branch 0 taken 5153 times.
✓ Branch 1 taken 72 times.
5225 for (int i = 0; i < sc->ctts_count &&
4919
1/2
✓ Branch 0 taken 5153 times.
✗ Branch 1 not taken.
10306 idx < sc->sample_count; i++)
4920
2/2
✓ Branch 0 taken 139297 times.
✓ Branch 1 taken 5153 times.
144450 for (int j = 0; j < sc->ctts_data[i].count &&
4921
1/2
✓ Branch 0 taken 139297 times.
✗ Branch 1 not taken.
139297 idx < sc->sample_count; j++) {
4922 139297 sc->tts_data[idx].offset = sc->ctts_data[i].offset;
4923 139297 sc->tts_data[idx++].count = 1;
4924 }
4925
4926 72 sc->tts_count = idx;
4927 } else
4928 615 sc->ctts_count = 0;
4929 687 av_freep(&sc->ctts_data);
4930 687 sc->ctts_allocated_size = 0;
4931
4932 687 idx = 0;
4933
2/2
✓ Branch 0 taken 619 times.
✓ Branch 1 taken 68 times.
687 if (stts) {
4934 619 MOVTimeToSample *tts_data = av_fast_realloc(sc->tts_data, &sc->tts_allocated_size,
4935 619 sc->sample_count * sizeof(*sc->tts_data));
4936
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 619 times.
619 if (!tts_data)
4937 return -1;
4938
4939
2/2
✓ Branch 0 taken 547 times.
✓ Branch 1 taken 72 times.
619 if (!sc->tts_data)
4940 547 memset(tts_data, 0, sc->tts_allocated_size);
4941 619 sc->tts_data = tts_data;
4942
4943
2/2
✓ Branch 0 taken 3022 times.
✓ Branch 1 taken 619 times.
3641 for (int i = 0; i < sc->stts_count &&
4944
1/2
✓ Branch 0 taken 3022 times.
✗ Branch 1 not taken.
6044 idx < sc->sample_count; i++)
4945
2/2
✓ Branch 0 taken 247964 times.
✓ Branch 1 taken 3022 times.
250986 for (int j = 0; j < sc->stts_data[i].count &&
4946
1/2
✓ Branch 0 taken 247964 times.
✗ Branch 1 not taken.
247964 idx < sc->sample_count; j++) {
4947 247964 sc->tts_data[idx].duration = sc->stts_data[i].duration;
4948 247964 sc->tts_data[idx++].count = 1;
4949 }
4950
4951 619 sc->tts_count = FFMAX(sc->tts_count, idx);
4952 } else
4953 68 sc->stts_count = 0;
4954 687 av_freep(&sc->stts_data);
4955 687 sc->stts_allocated_size = 0;
4956
4957 687 return 0;
4958 }
4959
4960 716 static void mov_build_index(MOVContext *mov, AVStream *st)
4961 {
4962 716 MOVStreamContext *sc = st->priv_data;
4963 716 FFStream *const sti = ffstream(st);
4964 int64_t current_offset;
4965 716 int64_t current_dts = 0;
4966 716 unsigned int stts_index = 0;
4967 716 unsigned int stsc_index = 0;
4968 716 unsigned int stss_index = 0;
4969 716 unsigned int stps_index = 0;
4970 unsigned int i, j;
4971 716 uint64_t stream_size = 0;
4972
4973 716 int ret = build_open_gop_key_points(st);
4974
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 716 times.
716 if (ret < 0)
4975 return;
4976
4977
2/2
✓ Branch 0 taken 496 times.
✓ Branch 1 taken 220 times.
716 if (sc->elst_count) {
4978 496 int i, edit_start_index = 0, multiple_edits = 0;
4979 496 int64_t empty_duration = 0; // empty duration of the first edit list entry
4980 496 int64_t start_time = 0; // start time of the media
4981
4982
2/2
✓ Branch 0 taken 525 times.
✓ Branch 1 taken 496 times.
1021 for (i = 0; i < sc->elst_count; i++) {
4983 525 const MOVElst *e = &sc->elst_data[i];
4984
4/4
✓ Branch 0 taken 496 times.
✓ Branch 1 taken 29 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 492 times.
525 if (i == 0 && e->time == -1) {
4985 /* if empty, the first entry is the start time of the stream
4986 * relative to the presentation itself */
4987 4 empty_duration = e->duration;
4988 4 edit_start_index = 1;
4989
3/4
✓ Branch 0 taken 496 times.
✓ Branch 1 taken 25 times.
✓ Branch 2 taken 496 times.
✗ Branch 3 not taken.
521 } else if (i == edit_start_index && e->time >= 0) {
4990 496 start_time = e->time;
4991 } else {
4992 25 multiple_edits = 1;
4993 }
4994 }
4995
4996
3/4
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 489 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 7 times.
496 if (multiple_edits && !mov->advanced_editlist) {
4997 if (mov->advanced_editlist_autodisabled)
4998 av_log(mov->fc, AV_LOG_WARNING, "multiple edit list entries, "
4999 "not supported in fragmented MP4 files\n");
5000 else
5001 av_log(mov->fc, AV_LOG_WARNING, "multiple edit list entries, "
5002 "Use -advanced_editlist to correctly decode otherwise "
5003 "a/v desync might occur\n");
5004 }
5005
5006 /* adjust first dts according to edit list */
5007
5/6
✓ Branch 0 taken 492 times.
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 107 times.
✓ Branch 3 taken 385 times.
✓ Branch 4 taken 111 times.
✗ Branch 5 not taken.
496 if ((empty_duration || start_time) && mov->time_scale > 0) {
5008
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 107 times.
111 if (empty_duration)
5009 4 empty_duration = av_rescale(empty_duration, sc->time_scale, mov->time_scale);
5010
5011
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 111 times.
111 if (av_sat_sub64(start_time, empty_duration) != start_time - (uint64_t)empty_duration)
5012 av_log(mov->fc, AV_LOG_WARNING, "start_time - empty_duration is not representable\n");
5013
5014 111 sc->time_offset = start_time - (uint64_t)empty_duration;
5015 111 sc->min_corrected_pts = start_time;
5016
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 110 times.
111 if (!mov->advanced_editlist)
5017 1 current_dts = -av_clip64(sc->time_offset, -INT64_MAX, INT64_MAX);
5018 }
5019
5020
4/4
✓ Branch 0 taken 489 times.
✓ Branch 1 taken 7 times.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 486 times.
496 if (!multiple_edits && !mov->advanced_editlist &&
5021
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)
5022 st->codecpar->initial_padding = av_rescale_q(start_time, st->time_base,
5023 (AVRational){1, st->codecpar->sample_rate});
5024 }
5025
5026 /* only use old uncompressed audio chunk demuxing when stts specifies it */
5027
2/2
✓ Branch 0 taken 279 times.
✓ Branch 1 taken 437 times.
716 if (!(st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO &&
5028
5/6
✓ Branch 0 taken 231 times.
✓ Branch 1 taken 48 times.
✓ Branch 2 taken 231 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 163 times.
✓ Branch 5 taken 68 times.
898 sc->stts_count == 1 && sc->stts_data && sc->stts_data[0].duration == 1)) {
5029 648 unsigned int current_sample = 0;
5030 648 unsigned int stts_sample = 0;
5031 unsigned int sample_size;
5032 648 unsigned int distance = 0;
5033 648 unsigned int rap_group_index = 0;
5034 648 unsigned int rap_group_sample = 0;
5035
3/4
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 647 times.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
648 int rap_group_present = sc->rap_group_count && sc->rap_group;
5036
4/8
✓ Branch 0 taken 154 times.
✓ Branch 1 taken 494 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 154 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 494 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
648 int key_off = (sc->keyframe_count && sc->keyframes[0] > 0) || (sc->stps_count && sc->stps_data[0] > 0);
5037
5038
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 648 times.
648 av_assert0(sc->dts_shift >= 0);
5039
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 648 times.
648 if (current_dts < INT64_MIN + sc->dts_shift)
5040 return;
5041 648 current_dts -= sc->dts_shift;
5042
4/6
✓ Branch 0 taken 619 times.
✓ Branch 1 taken 29 times.
✓ Branch 2 taken 619 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 619 times.
648 if (!sc->sample_count || sti->nb_index_entries || sc->tts_count)
5043 29 return;
5044
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 619 times.
619 if (sc->sample_count >= UINT_MAX / sizeof(*sti->index_entries) - sti->nb_index_entries)
5045 return;
5046
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 619 times.
619 if (av_reallocp_array(&sti->index_entries,
5047 619 sti->nb_index_entries + sc->sample_count,
5048 sizeof(*sti->index_entries)) < 0) {
5049 sti->nb_index_entries = 0;
5050 return;
5051 }
5052 619 sti->index_entries_allocated_size = (sti->nb_index_entries + sc->sample_count) * sizeof(*sti->index_entries);
5053
5054 619 ret = mov_merge_tts_data(mov, st, MOV_MERGE_CTTS | MOV_MERGE_STTS);
5055
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 619 times.
619 if (ret < 0)
5056 return;
5057
5058
2/2
✓ Branch 0 taken 174124 times.
✓ Branch 1 taken 619 times.
174743 for (i = 0; i < sc->chunk_count; i++) {
5059
2/2
✓ Branch 0 taken 173505 times.
✓ Branch 1 taken 619 times.
174124 int64_t next_offset = i+1 < sc->chunk_count ? sc->chunk_offsets[i+1] : INT64_MAX;
5060 174124 current_offset = sc->chunk_offsets[i];
5061
2/2
✓ Branch 1 taken 8684 times.
✓ Branch 2 taken 167987 times.
176671 while (mov_stsc_index_valid(stsc_index, sc->stsc_count) &&
5062
2/2
✓ Branch 0 taken 2547 times.
✓ Branch 1 taken 6137 times.
8684 i + 1 == sc->stsc_data[stsc_index + 1].first)
5063 2547 stsc_index++;
5064
5065
4/6
✓ Branch 0 taken 174124 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7409 times.
✓ Branch 3 taken 166715 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 7409 times.
174124 if (next_offset > current_offset && sc->sample_size>0 && sc->sample_size < sc->stsz_sample_size &&
5066 sc->stsc_data[stsc_index].count * (int64_t)sc->stsz_sample_size > next_offset - current_offset) {
5067 av_log(mov->fc, AV_LOG_WARNING, "STSZ sample size %d invalid (too large), ignoring\n", sc->stsz_sample_size);
5068 sc->stsz_sample_size = sc->sample_size;
5069 }
5070
3/4
✓ Branch 0 taken 7409 times.
✓ Branch 1 taken 166715 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 7409 times.
174124 if (sc->stsz_sample_size>0 && sc->stsz_sample_size < sc->sample_size) {
5071 av_log(mov->fc, AV_LOG_WARNING, "STSZ sample size %d invalid (too small), ignoring\n", sc->stsz_sample_size);
5072 sc->stsz_sample_size = sc->sample_size;
5073 }
5074
5075
2/2
✓ Branch 0 taken 247964 times.
✓ Branch 1 taken 174124 times.
422088 for (j = 0; j < sc->stsc_data[stsc_index].count; j++) {
5076 247964 int keyframe = 0;
5077
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 247964 times.
247964 if (current_sample >= sc->sample_count) {
5078 av_log(mov->fc, AV_LOG_ERROR, "wrong sample count\n");
5079 return;
5080 }
5081
5082
6/6
✓ Branch 0 taken 238253 times.
✓ Branch 1 taken 9711 times.
✓ Branch 2 taken 153158 times.
✓ Branch 3 taken 85095 times.
✓ Branch 4 taken 5740 times.
✓ Branch 5 taken 147418 times.
247964 if (!sc->keyframe_absent && (!sc->keyframe_count || current_sample+key_off == sc->keyframes[stss_index])) {
5083 90835 keyframe = 1;
5084
2/2
✓ Branch 0 taken 5586 times.
✓ Branch 1 taken 85249 times.
90835 if (stss_index + 1 < sc->keyframe_count)
5085 5586 stss_index++;
5086
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 157129 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
157129 } else if (sc->stps_count && current_sample+key_off == sc->stps_data[stps_index]) {
5087 keyframe = 1;
5088 if (stps_index + 1 < sc->stps_count)
5089 stps_index++;
5090 }
5091
3/4
✓ Branch 0 taken 188 times.
✓ Branch 1 taken 247776 times.
✓ Branch 2 taken 188 times.
✗ Branch 3 not taken.
247964 if (rap_group_present && rap_group_index < sc->rap_group_count) {
5092
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 186 times.
188 if (sc->rap_group[rap_group_index].index > 0)
5093 2 keyframe = 1;
5094
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 184 times.
188 if (++rap_group_sample == sc->rap_group[rap_group_index].count) {
5095 4 rap_group_sample = 0;
5096 4 rap_group_index++;
5097 }
5098 }
5099
2/2
✓ Branch 0 taken 9711 times.
✓ Branch 1 taken 238253 times.
247964 if (sc->keyframe_absent
5100
1/2
✓ Branch 0 taken 9711 times.
✗ Branch 1 not taken.
9711 && !sc->stps_count
5101
1/2
✓ Branch 0 taken 9711 times.
✗ Branch 1 not taken.
9711 && !rap_group_present
5102
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)))
5103 8839 keyframe = 1;
5104
2/2
✓ Branch 0 taken 99674 times.
✓ Branch 1 taken 148290 times.
247964 if (keyframe)
5105 99674 distance = 0;
5106
2/2
✓ Branch 0 taken 9298 times.
✓ Branch 1 taken 238666 times.
247964 sample_size = sc->stsz_sample_size > 0 ? sc->stsz_sample_size : sc->sample_sizes[current_sample];
5107
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 247964 times.
247964 if (current_offset > INT64_MAX - sample_size) {
5108 av_log(mov->fc, AV_LOG_ERROR, "Current offset %"PRId64" or sample size %u is too large\n",
5109 current_offset,
5110 sample_size);
5111 return;
5112 }
5113
5114
2/2
✓ Branch 0 taken 247871 times.
✓ Branch 1 taken 93 times.
247964 if (sc->pseudo_stream_id == -1 ||
5115
1/2
✓ Branch 0 taken 247871 times.
✗ Branch 1 not taken.
247871 sc->stsc_data[stsc_index].id - 1 == sc->pseudo_stream_id) {
5116 AVIndexEntry *e;
5117
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 247964 times.
247964 if (sample_size > 0x3FFFFFFF) {
5118 av_log(mov->fc, AV_LOG_ERROR, "Sample size %u is too large\n", sample_size);
5119 return;
5120 }
5121 247964 e = &sti->index_entries[sti->nb_index_entries++];
5122 247964 e->pos = current_offset;
5123 247964 e->timestamp = current_dts;
5124 247964 e->size = sample_size;
5125 247964 e->min_distance = distance;
5126 247964 e->flags = keyframe ? AVINDEX_KEYFRAME : 0;
5127 247964 av_log(mov->fc, AV_LOG_TRACE, "AVIndex stream %d, sample %u, offset %"PRIx64", dts %"PRId64", "
5128 "size %u, distance %u, keyframe %d\n", st->index, current_sample,
5129 current_offset, current_dts, sample_size, distance, keyframe);
5130
4/4
✓ Branch 0 taken 155495 times.
✓ Branch 1 taken 92469 times.
✓ Branch 2 taken 10862 times.
✓ Branch 3 taken 144633 times.
247964 if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && sti->nb_index_entries < 100)
5131 10862 ff_rfps_add_frame(mov->fc, st, current_dts);
5132 }
5133
5134 247964 current_offset += sample_size;
5135 247964 stream_size += sample_size;
5136
5137
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 247964 times.
247964 if (current_dts > INT64_MAX - sc->tts_data[stts_index].duration)
5138 return;
5139 247964 current_dts += sc->tts_data[stts_index].duration;
5140
5141 247964 distance++;
5142 247964 stts_sample++;
5143 247964 current_sample++;
5144
3/4
✓ Branch 0 taken 247345 times.
✓ Branch 1 taken 619 times.
✓ Branch 2 taken 247345 times.
✗ Branch 3 not taken.
247964 if (stts_index + 1 < sc->tts_count && stts_sample == sc->tts_data[stts_index].count) {
5145 247345 stts_sample = 0;
5146 247345 stts_index++;
5147 }
5148 }
5149 }
5150
2/2
✓ Branch 0 taken 576 times.
✓ Branch 1 taken 43 times.
619 if (st->duration > 0)
5151 576 st->codecpar->bit_rate = stream_size*8*sc->time_scale/st->duration;
5152 } else {
5153 68 unsigned chunk_samples, total = 0;
5154
5155
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)
5156 return;
5157
5158 // compute total chunk count
5159
2/2
✓ Branch 0 taken 739 times.
✓ Branch 1 taken 68 times.
807 for (i = 0; i < sc->stsc_count; i++) {
5160 unsigned count, chunk_count;
5161
5162 739 chunk_samples = sc->stsc_data[i].count;
5163
2/2
✓ Branch 0 taken 671 times.
✓ Branch 1 taken 68 times.
739 if (i != sc->stsc_count - 1 &&
5164
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) {
5165 av_log(mov->fc, AV_LOG_ERROR, "error unaligned chunk\n");
5166 return;
5167 }
5168
5169
2/2
✓ Branch 0 taken 75 times.
✓ Branch 1 taken 664 times.
739 if (sc->samples_per_frame >= 160) { // gsm
5170 75 count = chunk_samples / sc->samples_per_frame;
5171
2/2
✓ Branch 0 taken 531 times.
✓ Branch 1 taken 133 times.
664 } else if (sc->samples_per_frame > 1) {
5172 531 unsigned samples = (1024/sc->samples_per_frame)*sc->samples_per_frame;
5173 531 count = (chunk_samples+samples-1) / samples;
5174 } else {
5175 133 count = (chunk_samples+1023) / 1024;
5176 }
5177
5178
2/2
✓ Branch 1 taken 671 times.
✓ Branch 2 taken 68 times.
739 if (mov_stsc_index_valid(i, sc->stsc_count))
5179 671 chunk_count = sc->stsc_data[i+1].first - sc->stsc_data[i].first;
5180 else
5181 68 chunk_count = sc->chunk_count - (sc->stsc_data[i].first - 1);
5182 739 total += chunk_count * count;
5183 }
5184
5185 68 av_log(mov->fc, AV_LOG_TRACE, "chunk count %u\n", total);
5186
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 68 times.
68 if (total >= UINT_MAX / sizeof(*sti->index_entries) - sti->nb_index_entries)
5187 return;
5188
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 68 times.
68 if (av_reallocp_array(&sti->index_entries,
5189 68 sti->nb_index_entries + total,
5190 sizeof(*sti->index_entries)) < 0) {
5191 sti->nb_index_entries = 0;
5192 return;
5193 }
5194 68 sti->index_entries_allocated_size = (sti->nb_index_entries + total) * sizeof(*sti->index_entries);
5195
5196 // populate index
5197
2/2
✓ Branch 0 taken 5560 times.
✓ Branch 1 taken 68 times.
5628 for (i = 0; i < sc->chunk_count; i++) {
5198 5560 current_offset = sc->chunk_offsets[i];
5199
2/2
✓ Branch 1 taken 5399 times.
✓ Branch 2 taken 161 times.
5560 if (mov_stsc_index_valid(stsc_index, sc->stsc_count) &&
5200
2/2
✓ Branch 0 taken 671 times.
✓ Branch 1 taken 4728 times.
5399 i + 1 == sc->stsc_data[stsc_index + 1].first)
5201 671 stsc_index++;
5202 5560 chunk_samples = sc->stsc_data[stsc_index].count;
5203
5204
2/2
✓ Branch 0 taken 165262 times.
✓ Branch 1 taken 5560 times.
170822 while (chunk_samples > 0) {
5205 AVIndexEntry *e;
5206 unsigned size, samples;
5207
5208
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) {
5209 avpriv_request_sample(mov->fc,
5210 "Zero bytes per frame, but %d samples per frame",
5211 sc->samples_per_frame);
5212 return;
5213 }
5214
5215
2/2
✓ Branch 0 taken 14358 times.
✓ Branch 1 taken 150904 times.
165262 if (sc->samples_per_frame >= 160) { // gsm
5216 14358 samples = sc->samples_per_frame;
5217 14358 size = sc->bytes_per_frame;
5218 } else {
5219
2/2
✓ Branch 0 taken 9563 times.
✓ Branch 1 taken 141341 times.
150904 if (sc->samples_per_frame > 1) {
5220 9563 samples = FFMIN((1024 / sc->samples_per_frame)*
5221 sc->samples_per_frame, chunk_samples);
5222 9563 size = (samples / sc->samples_per_frame) * sc->bytes_per_frame;
5223 } else {
5224 141341 samples = FFMIN(1024, chunk_samples);
5225 141341 size = samples * sc->sample_size;
5226 }
5227 }
5228
5229
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 165262 times.
165262 if (sti->nb_index_entries >= total) {
5230 av_log(mov->fc, AV_LOG_ERROR, "wrong chunk count %u\n", total);
5231 return;
5232 }
5233
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 165262 times.
165262 if (size > 0x3FFFFFFF) {
5234 av_log(mov->fc, AV_LOG_ERROR, "Sample size %u is too large\n", size);
5235 return;
5236 }
5237 165262 e = &sti->index_entries[sti->nb_index_entries++];
5238 165262 e->pos = current_offset;
5239 165262 e->timestamp = current_dts;
5240 165262 e->size = size;
5241 165262 e->min_distance = 0;
5242 165262 e->flags = AVINDEX_KEYFRAME;
5243 165262 av_log(mov->fc, AV_LOG_TRACE, "AVIndex stream %d, chunk %u, offset %"PRIx64", dts %"PRId64", "
5244 "size %u, duration %u\n", st->index, i, current_offset, current_dts,
5245 size, samples);
5246
5247 165262 current_offset += size;
5248
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 165262 times.
165262 if (current_dts > INT64_MAX - samples)
5249 return;
5250 165262 current_dts += samples;
5251 165262 chunk_samples -= samples;
5252 }
5253 }
5254
5255 68 ret = mov_merge_tts_data(mov, st, MOV_MERGE_CTTS);
5256
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 68 times.
68 if (ret < 0)
5257 return;
5258 }
5259
5260
2/4
✓ Branch 0 taken 687 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 687 times.
✗ Branch 3 not taken.
687 if (!mov->ignore_editlist && mov->advanced_editlist) {
5261 // Fix index according to edit lists.
5262 687 mov_fix_index(mov, st);
5263 }
5264
5265 // Update start time of the stream.
5266
5/6
✓ Branch 0 taken 194 times.
✓ Branch 1 taken 493 times.
✓ Branch 2 taken 71 times.
✓ Branch 3 taken 123 times.
✓ Branch 4 taken 71 times.
✗ Branch 5 not taken.
687 if (st->start_time == AV_NOPTS_VALUE && st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && sti->nb_index_entries > 0) {
5267 71 st->start_time = av_sat_add64(sti->index_entries[0].timestamp, sc->dts_shift);
5268
1/2
✓ Branch 0 taken 71 times.
✗ Branch 1 not taken.
71 if (sc->tts_data) {
5269 71 st->start_time = av_sat_add64(st->start_time, sc->tts_data[0].offset);
5270 }
5271 }
5272
5273 687 mov_estimate_video_delay(mov, st);
5274 }
5275
5276 typedef struct MOVPresentationSample {
5277 int index;
5278 int64_t pts;
5279 } MOVPresentationSample;
5280
5281 12202 static int mov_compare_presentation_samples(const void *a, const void *b)
5282 {
5283 12202 const MOVPresentationSample *sa = a;
5284 12202 const MOVPresentationSample *sb = b;
5285
5286
2/2
✓ Branch 0 taken 12198 times.
✓ Branch 1 taken 4 times.
12202 if (sa->pts != sb->pts)
5287 12198 return (sa->pts > sb->pts) - (sa->pts < sb->pts);
5288 4 return (sa->index > sb->index) - (sa->index < sb->index);
5289 }
5290
5291 /*
5292 * Set sample durations from adjacent presentation timestamps.
5293 */
5294 673 static void mov_update_sample_durations(MOVContext *mov, AVStream *st)
5295 {
5296 673 MOVStreamContext *sc = st->priv_data;
5297 673 FFStream *const sti = ffstream(st);
5298 673 MOVPresentationSample *samples = NULL;
5299 673 MOVTimeToSample *tts_data = NULL;
5300 673 unsigned int tts_index = 0, tts_sample = 0;
5301 673 int count = sti->nb_index_entries;
5302
5303 /* A single STTS entry describes a fixed sample delta. */
5304
2/2
✓ Branch 0 taken 337 times.
✓ Branch 1 taken 336 times.
673 if (st->codecpar->codec_type != AVMEDIA_TYPE_VIDEO ||
5305
4/4
✓ Branch 0 taken 68 times.
✓ Branch 1 taken 269 times.
✓ Branch 2 taken 12 times.
✓ Branch 3 taken 56 times.
337 !sc->ctts_count || sc->stts_count < 2 ||
5306
2/4
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
✗ Branch 3 not taken.
12 !sc->tts_data || count < 2 ||
5307
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 count >= UINT_MAX / sizeof(*tts_data))
5308 661 return;
5309
5310 12 samples = av_malloc_array(count, sizeof(*samples));
5311 12 tts_data = av_malloc_array(count, sizeof(*tts_data));
5312
2/4
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 12 times.
12 if (!samples || !tts_data)
5313 goto fail;
5314
5315
2/2
✓ Branch 0 taken 2654 times.
✓ Branch 1 taken 12 times.
2666 for (int i = 0; i < count; i++) {
5316 int64_t dts, offset;
5317
5318
2/4
✓ Branch 0 taken 2654 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2654 times.
2654 if (tts_index >= sc->tts_count || !sc->tts_data[tts_index].count)
5319 goto fail;
5320
5321 2654 tts_data[i] = sc->tts_data[tts_index];
5322 2654 tts_data[i].count = 1;
5323
5324 2654 dts = sti->index_entries[i].timestamp;
5325 2654 offset = (int64_t)sc->dts_shift + tts_data[i].offset;
5326
3/4
✓ Branch 0 taken 2654 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2613 times.
✓ Branch 3 taken 41 times.
2654 if (dts == AV_NOPTS_VALUE ||
5327
2/4
✓ Branch 0 taken 2613 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2654 times.
2654 (offset > 0 && dts > INT64_MAX - offset) ||
5328 (offset < 0 && dts < INT64_MIN - offset))
5329 goto fail;
5330
5331 2654 samples[i].index = i;
5332 2654 samples[i].pts = dts + offset;
5333
5334
1/2
✓ Branch 0 taken 2654 times.
✗ Branch 1 not taken.
2654 if (++tts_sample == sc->tts_data[tts_index].count) {
5335 2654 tts_index++;
5336 2654 tts_sample = 0;
5337 }
5338 }
5339
2/4
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 12 times.
12 if (tts_index != sc->tts_count || tts_sample)
5340 goto fail;
5341
5342 12 qsort(samples, count, sizeof(*samples), mov_compare_presentation_samples);
5343
5344
2/2
✓ Branch 0 taken 2624 times.
✓ Branch 1 taken 10 times.
2634 for (int i = 0; i + 1 < count; i++) {
5345 uint64_t duration;
5346
5347
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2622 times.
2624 if (samples[i].pts >= samples[i + 1].pts)
5348 2 goto fail;
5349
5350 /*
5351 * In VFR streams with reordered frames, STTS deltas follow decode
5352 * order while AVPacket.duration follows presentation order. CTTS
5353 * may produce presentation intervals that cannot be obtained by
5354 * merely permuting the STTS deltas, so derive each known duration
5355 * from adjacent PTS.
5356 */
5357 2622 duration = (uint64_t)samples[i + 1].pts - samples[i].pts;
5358
2/4
✓ Branch 0 taken 2622 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2622 times.
2622 if (!duration || duration > UINT_MAX)
5359 goto fail;
5360
5361 2622 tts_data[samples[i].index].duration = (unsigned int)duration;
5362 }
5363
5364 10 av_log(mov->fc, AV_LOG_DEBUG,
5365 "Updated sample durations in presentation order for stream %d\n",
5366 st->index);
5367
5368 10 av_freep(&sc->tts_data);
5369 10 sc->tts_data = tts_data;
5370 10 sc->tts_count = count;
5371 10 sc->tts_allocated_size = count * sizeof(*tts_data);
5372 10 tts_data = NULL;
5373
5374 12 fail:
5375 12 av_free(samples);
5376 12 av_free(tts_data);
5377 }
5378
5379 static int test_same_origin(const char *src, const char *ref) {
5380 char src_proto[64];
5381 char ref_proto[64];
5382 char src_auth[256];
5383 char ref_auth[256];
5384 char src_host[256];
5385 char ref_host[256];
5386 int src_port=-1;
5387 int ref_port=-1;
5388
5389 av_url_split(src_proto, sizeof(src_proto), src_auth, sizeof(src_auth), src_host, sizeof(src_host), &src_port, NULL, 0, src);
5390 av_url_split(ref_proto, sizeof(ref_proto), ref_auth, sizeof(ref_auth), ref_host, sizeof(ref_host), &ref_port, NULL, 0, ref);
5391
5392 if (strlen(src) == 0) {
5393 return -1;
5394 } else if (strlen(src_auth) + 1 >= sizeof(src_auth) ||
5395 strlen(ref_auth) + 1 >= sizeof(ref_auth) ||
5396 strlen(src_host) + 1 >= sizeof(src_host) ||
5397 strlen(ref_host) + 1 >= sizeof(ref_host)) {
5398 return 0;
5399 } else if (strcmp(src_proto, ref_proto) ||
5400 strcmp(src_auth, ref_auth) ||
5401 strcmp(src_host, ref_host) ||
5402 src_port != ref_port) {
5403 return 0;
5404 } else
5405 return 1;
5406 }
5407
5408 static int mov_open_dref(MOVContext *c, AVIOContext **pb, const char *src, MOVDref *ref)
5409 {
5410 /* try relative path, we do not try the absolute because it can leak information about our
5411 system to an attacker */
5412 if (ref->nlvl_to > 0 && ref->nlvl_from > 0) {
5413 char filename[1025];
5414 const char *src_path;
5415 int i, l;
5416
5417 /* find a source dir */
5418 src_path = strrchr(src, '/');
5419 if (src_path)
5420 src_path++;
5421 else
5422 src_path = src;
5423
5424 /* find a next level down to target */
5425 for (i = 0, l = strlen(ref->path) - 1; l >= 0; l--)
5426 if (ref->path[l] == '/') {
5427 if (i == ref->nlvl_to - 1)
5428 break;
5429 else
5430 i++;
5431 }
5432
5433 /* compose filename if next level down to target was found */
5434 if (i == ref->nlvl_to - 1 && src_path - src < sizeof(filename)) {
5435 memcpy(filename, src, src_path - src);
5436 filename[src_path - src] = 0;
5437
5438 for (i = 1; i < ref->nlvl_from; i++)
5439 av_strlcat(filename, "../", sizeof(filename));
5440
5441 av_strlcat(filename, ref->path + l + 1, sizeof(filename));
5442 if (!c->use_absolute_path) {
5443 int same_origin = test_same_origin(src, filename);
5444
5445 if (!same_origin) {
5446 av_log(c->fc, AV_LOG_ERROR,
5447 "Reference with mismatching origin, %s not tried for security reasons, "
5448 "set demuxer option use_absolute_path to allow it anyway\n",
5449 ref->path);
5450 return AVERROR(ENOENT);
5451 }
5452
5453 if (strstr(ref->path + l + 1, "..") ||
5454 strstr(ref->path + l + 1, ":") ||
5455 (ref->nlvl_from > 1 && same_origin < 0) ||
5456 (filename[0] == '/' && src_path == src))
5457 return AVERROR(ENOENT);
5458 }
5459
5460 if (strlen(filename) + 1 == sizeof(filename))
5461 return AVERROR(ENOENT);
5462 if (!c->fc->io_open(c->fc, pb, filename, AVIO_FLAG_READ, NULL))
5463 return 0;
5464 }
5465 } else if (c->use_absolute_path) {
5466 av_log(c->fc, AV_LOG_WARNING, "Using absolute path on user request, "
5467 "this is a possible security issue\n");
5468 if (!c->fc->io_open(c->fc, pb, ref->path, AVIO_FLAG_READ, NULL))
5469 return 0;
5470 } else {
5471 av_log(c->fc, AV_LOG_ERROR,
5472 "Absolute path %s not tried for security reasons, "
5473 "set demuxer option use_absolute_path to allow absolute paths\n",
5474 ref->path);
5475 }
5476
5477 return AVERROR(ENOENT);
5478 }
5479
5480 1457 static void fix_timescale(MOVContext *c, MOVStreamContext *sc)
5481 {
5482
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 1441 times.
1457 if (sc->time_scale <= 0) {
5483 16 av_log(c->fc, AV_LOG_WARNING, "stream %d, timescale not set\n", sc->ffindex);
5484 16 sc->time_scale = c->time_scale;
5485
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 if (sc->time_scale <= 0)
5486 sc->time_scale = 1;
5487 }
5488 1457 }
5489
5490 #if CONFIG_IAMFDEC
5491 12 static int mov_update_iamf_streams(MOVContext *c, const AVStream *st)
5492 {
5493 12 const MOVStreamContext *sc = st->priv_data;
5494 12 const IAMFContext *iamf = &sc->iamf->iamf;
5495
5496
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 12 times.
24 for (int i = 0; i < iamf->nb_audio_elements; i++) {
5497 12 const AVStreamGroup *stg = NULL;
5498
5499
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 12 times.
36 for (int j = 0; j < c->fc->nb_stream_groups; j++)
5500
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)
5501 12 stg = c->fc->stream_groups[j];
5502
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 av_assert0(stg);
5503
5504
2/2
✓ Branch 0 taken 64 times.
✓ Branch 1 taken 12 times.
76 for (int j = 0; j < stg->nb_streams; j++) {
5505 64 const FFStream *sti = cffstream(st);
5506 64 AVStream *out = stg->streams[j];
5507 64 FFStream *out_sti = ffstream(stg->streams[j]);
5508
5509 64 out->codecpar->bit_rate = 0;
5510
5511
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 52 times.
64 if (out == st)
5512 12 continue;
5513
5514 52 out->time_base = st->time_base;
5515 52 out->start_time = st->start_time;
5516 52 out->duration = st->duration;
5517 52 out->nb_frames = st->nb_frames;
5518 52 out->discard = st->discard;
5519
5520
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 52 times.
52 av_assert0(!out_sti->index_entries);
5521 52 out_sti->index_entries = av_malloc(sti->index_entries_allocated_size);
5522
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 52 times.
52 if (!out_sti->index_entries)
5523 return AVERROR(ENOMEM);
5524
5525 52 out_sti->index_entries_allocated_size = sti->index_entries_allocated_size;
5526 52 out_sti->nb_index_entries = sti->nb_index_entries;
5527 52 out_sti->skip_samples = sti->skip_samples;
5528 52 memcpy(out_sti->index_entries, sti->index_entries, sti->index_entries_allocated_size);
5529 }
5530 }
5531
5532 12 return 0;
5533 }
5534 #endif
5535
5536 716 static int sanity_checks(void *log_obj, MOVStreamContext *sc, int index)
5537 {
5538
4/6
✓ Branch 0 taken 687 times.
✓ Branch 1 taken 29 times.
✓ Branch 2 taken 687 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 687 times.
✗ Branch 5 not taken.
716 if ((sc->chunk_count && (!sc->stts_count || !sc->stsc_count ||
5539
3/4
✓ Branch 0 taken 426 times.
✓ Branch 1 taken 261 times.
✓ Branch 2 taken 426 times.
✗ Branch 3 not taken.
687 (!sc->sample_size && !sc->sample_count))) ||
5540
3/4
✓ Branch 0 taken 687 times.
✓ Branch 1 taken 29 times.
✓ Branch 2 taken 687 times.
✗ Branch 3 not taken.
716 (sc->sample_count && (!sc->chunk_count ||
5541
3/4
✓ Branch 0 taken 426 times.
✓ Branch 1 taken 261 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 426 times.
687 (!sc->sample_size && !sc->sample_sizes)))) {
5542 av_log(log_obj, AV_LOG_ERROR, "stream %d, missing mandatory atoms, broken header\n",
5543 index);
5544 return 1;
5545 }
5546
5547
3/4
✓ Branch 0 taken 687 times.
✓ Branch 1 taken 29 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 687 times.
716 if (sc->stsc_count && sc->stsc_data[ sc->stsc_count - 1 ].first > sc->chunk_count) {
5548 av_log(log_obj, AV_LOG_ERROR, "stream %d, contradictionary STSC and STCO\n",
5549 index);
5550 return 2;
5551 }
5552 716 return 0;
5553 }
5554
5555 673 static int mov_read_trak(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5556 {
5557 AVStream *st;
5558 MOVStreamContext *sc;
5559 int ret;
5560
5561 673 st = avformat_new_stream(c->fc, NULL);
5562
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 673 times.
673 if (!st) return AVERROR(ENOMEM);
5563 673 st->id = -1;
5564 673 sc = av_mallocz(sizeof(MOVStreamContext));
5565
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 673 times.
673 if (!sc) return AVERROR(ENOMEM);
5566
5567 673 st->priv_data = sc;
5568 673 st->codecpar->codec_type = AVMEDIA_TYPE_DATA;
5569 673 sc->ffindex = st->index;
5570 673 c->trak_index = st->index;
5571 673 sc->refcount = 1;
5572
5573
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 673 times.
673 if ((ret = mov_read_default(c, pb, atom)) < 0)
5574 return ret;
5575
5576 673 c->trak_index = -1;
5577
5578 // Here stsc refers to a chunk not described in stco. This is technically invalid,
5579 // but we can overlook it (clearing stsc) whenever stts_count == 0 (indicating no samples).
5580
5/6
✓ Branch 0 taken 29 times.
✓ Branch 1 taken 644 times.
✓ Branch 2 taken 29 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 28 times.
673 if (!sc->chunk_count && !sc->stts_count && sc->stsc_count) {
5581 1 sc->stsc_count = 0;
5582 1 av_freep(&sc->stsc_data);
5583 }
5584
5585 673 ret = sanity_checks(c->fc, sc, st->index);
5586
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 673 times.
673 if (ret)
5587 return ret > 1 ? AVERROR_INVALIDDATA : 0;
5588
5589 673 fix_timescale(c, sc);
5590
5591 673 avpriv_set_pts_info(st, 64, 1, sc->time_scale);
5592
5593 /*
5594 * Advanced edit list support does not work with fragemented MP4s, which
5595 * have stsc, stsz, stco, and stts with zero entries in the moov atom.
5596 * In these files, trun atoms may be streamed in.
5597 */
5598
4/4
✓ Branch 0 taken 29 times.
✓ Branch 1 taken 644 times.
✓ Branch 2 taken 20 times.
✓ Branch 3 taken 9 times.
673 if (!sc->stts_count && c->advanced_editlist) {
5599
5600 20 av_log(c->fc, AV_LOG_VERBOSE, "advanced_editlist does not work with fragmented "
5601 "MP4. disabling.\n");
5602 20 c->advanced_editlist = 0;
5603 20 c->advanced_editlist_autodisabled = 1;
5604 }
5605
5606 673 mov_build_index(c, st);
5607 /*
5608 * Fragment samples are appended later by mov_read_trun() and are not
5609 * covered by this non-fragmented track update.
5610 */
5611 673 mov_update_sample_durations(c, st);
5612
5613 #if CONFIG_IAMFDEC
5614
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 661 times.
673 if (sc->iamf) {
5615 12 ret = mov_update_iamf_streams(c, st);
5616
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (ret < 0)
5617 return ret;
5618 }
5619 #endif
5620
5621
3/4
✓ Branch 0 taken 672 times.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 672 times.
673 if (sc->dref_id-1 < sc->drefs_count && sc->drefs[sc->dref_id-1].path) {
5622 MOVDref *dref = &sc->drefs[sc->dref_id - 1];
5623 if (c->enable_drefs) {
5624 if (mov_open_dref(c, &sc->pb, c->fc->url, dref) < 0)
5625 av_log(c->fc, AV_LOG_ERROR,
5626 "stream %d, error opening alias: path='%s', dir='%s', "
5627 "filename='%s', volume='%s', nlvl_from=%d, nlvl_to=%d\n",
5628 st->index, dref->path, dref->dir, dref->filename,
5629 dref->volume, dref->nlvl_from, dref->nlvl_to);
5630 } else {
5631 av_log(c->fc, AV_LOG_WARNING,
5632 "Skipped opening external track: "
5633 "stream %d, alias: path='%s', dir='%s', "
5634 "filename='%s', volume='%s', nlvl_from=%d, nlvl_to=%d."
5635 "Set enable_drefs to allow this.\n",
5636 st->index, dref->path, dref->dir, dref->filename,
5637 dref->volume, dref->nlvl_from, dref->nlvl_to);
5638 }
5639 } else {
5640 673 sc->pb = c->fc->pb;
5641 673 sc->pb_is_copied = 1;
5642 }
5643
5644
2/2
✓ Branch 0 taken 337 times.
✓ Branch 1 taken 336 times.
673 if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
5645
3/4
✓ Branch 0 taken 320 times.
✓ Branch 1 taken 17 times.
✓ Branch 2 taken 320 times.
✗ Branch 3 not taken.
337 int stts_constant = sc->stts_count && sc->tts_count;
5646
3/4
✓ Branch 0 taken 78 times.
✓ Branch 1 taken 259 times.
✓ Branch 2 taken 78 times.
✗ Branch 3 not taken.
337 if (sc->h_spacing && sc->v_spacing)
5647 78 av_reduce(&st->sample_aspect_ratio.num, &st->sample_aspect_ratio.den,
5648 78 sc->h_spacing, sc->v_spacing, INT_MAX);
5649
4/6
✓ Branch 0 taken 256 times.
✓ Branch 1 taken 81 times.
✓ Branch 2 taken 256 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 256 times.
✗ Branch 5 not taken.
337 if (!st->sample_aspect_ratio.num && st->codecpar->width && st->codecpar->height &&
5650
2/4
✓ Branch 0 taken 256 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 256 times.
✗ Branch 3 not taken.
256 sc->height && sc->width &&
5651
2/4
✓ Branch 0 taken 256 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 256 times.
256 (st->codecpar->width != sc->width || st->codecpar->height != sc->height)) {
5652 av_reduce(&st->sample_aspect_ratio.num, &st->sample_aspect_ratio.den,
5653 (int64_t)st->codecpar->height * sc->width,
5654 (int64_t)st->codecpar->width * sc->height, INT_MAX);
5655 }
5656
5657 #if FF_API_R_FRAME_RATE
5658
4/4
✓ Branch 0 taken 155318 times.
✓ Branch 1 taken 17 times.
✓ Branch 2 taken 154998 times.
✓ Branch 3 taken 320 times.
155335 for (unsigned int i = 1; sc->stts_count && i + 1 < sc->tts_count; i++) {
5659
2/2
✓ Branch 0 taken 152504 times.
✓ Branch 1 taken 2494 times.
154998 if (sc->tts_data[i].duration == sc->tts_data[0].duration)
5660 152504 continue;
5661 2494 stts_constant = 0;
5662 }
5663
2/2
✓ Branch 0 taken 302 times.
✓ Branch 1 taken 35 times.
337 if (stts_constant)
5664 302 av_reduce(&st->r_frame_rate.num, &st->r_frame_rate.den,
5665 302 sc->time_scale, sc->tts_data[0].duration, INT_MAX);
5666 #endif
5667 }
5668
5669 #if CONFIG_H261_DECODER || CONFIG_H263_DECODER || CONFIG_MPEG4_DECODER
5670
2/2
✓ Branch 0 taken 27 times.
✓ Branch 1 taken 646 times.
673 switch (st->codecpar->codec_id) {
5671 #if CONFIG_H261_DECODER
5672 27 case AV_CODEC_ID_H261:
5673 #endif
5674 #if CONFIG_H263_DECODER
5675 case AV_CODEC_ID_H263:
5676 #endif
5677 #if CONFIG_MPEG4_DECODER
5678 case AV_CODEC_ID_MPEG4:
5679 #endif
5680 27 st->codecpar->width = 0; /* let decoder init width/height */
5681 27 st->codecpar->height= 0;
5682 27 break;
5683 }
5684 #endif
5685
5686 // If the duration of the mp3 packets is not constant, then they could need a parser
5687
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 670 times.
673 if (st->codecpar->codec_id == AV_CODEC_ID_MP3
5688
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 && sc->time_scale == st->codecpar->sample_rate) {
5689 3 int stts_constant = 1;
5690
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++) {
5691
1/2
✓ Branch 0 taken 365 times.
✗ Branch 1 not taken.
365 if (sc->tts_data[i].duration == sc->tts_data[0].duration)
5692 365 continue;
5693 stts_constant = 0;
5694 }
5695
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!stts_constant)
5696 ffstream(st)->need_parsing = AVSTREAM_PARSE_FULL;
5697 }
5698 /* Do not need those anymore. */
5699 673 av_freep(&sc->chunk_offsets);
5700 673 av_freep(&sc->sample_sizes);
5701 673 av_freep(&sc->keyframes);
5702 673 av_freep(&sc->stps_data);
5703 673 av_freep(&sc->elst_data);
5704 673 av_freep(&sc->rap_group);
5705 673 av_freep(&sc->sync_group);
5706 673 av_freep(&sc->sgpd_sync);
5707
5708 673 return 0;
5709 }
5710
5711 165 static int mov_read_ilst(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5712 {
5713 int ret;
5714 165 c->itunes_metadata = 1;
5715 165 ret = mov_read_default(c, pb, atom);
5716 165 c->itunes_metadata = 0;
5717 165 return ret;
5718 }
5719
5720 11 static int mov_read_keys(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5721 {
5722 uint32_t count;
5723 uint32_t i;
5724
5725
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (atom.size < 8)
5726 return 0;
5727
5728 11 avio_skip(pb, 4);
5729 11 count = avio_rb32(pb);
5730 11 atom.size -= 8;
5731
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (count >= UINT_MAX / sizeof(*c->meta_keys)) {
5732 av_log(c->fc, AV_LOG_ERROR,
5733 "The 'keys' atom with the invalid key count: %"PRIu32"\n", count);
5734 return AVERROR_INVALIDDATA;
5735 }
5736
5737 11 c->meta_keys_count = count + 1;
5738 11 c->meta_keys = av_mallocz(c->meta_keys_count * sizeof(*c->meta_keys));
5739
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (!c->meta_keys)
5740 return AVERROR(ENOMEM);
5741
5742
2/2
✓ Branch 0 taken 58 times.
✓ Branch 1 taken 11 times.
69 for (i = 1; i <= count; ++i) {
5743 58 uint32_t key_size = avio_rb32(pb);
5744 58 uint32_t type = avio_rl32(pb);
5745
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) {
5746 av_log(c->fc, AV_LOG_ERROR,
5747 "The key# %"PRIu32" in meta has invalid size:"
5748 "%"PRIu32"\n", i, key_size);
5749 return AVERROR_INVALIDDATA;
5750 }
5751 58 atom.size -= key_size;
5752 58 key_size -= 8;
5753
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 58 times.
58 if (type != MKTAG('m','d','t','a')) {
5754 avio_skip(pb, key_size);
5755 continue;
5756 }
5757 58 c->meta_keys[i] = av_mallocz(key_size + 1);
5758
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 58 times.
58 if (!c->meta_keys[i])
5759 return AVERROR(ENOMEM);
5760 58 avio_read(pb, c->meta_keys[i], key_size);
5761 }
5762
5763 11 return 0;
5764 }
5765
5766 73 static int mov_read_custom(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5767 {
5768 73 int64_t end = av_sat_add64(avio_tell(pb), atom.size);
5769 73 uint8_t *key = NULL, *val = NULL, *mean = NULL;
5770 int i;
5771 73 int ret = 0;
5772 AVStream *st;
5773
5774
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 73 times.
73 if (c->fc->nb_streams < 1)
5775 return 0;
5776 73 st = c->fc->streams[c->fc->nb_streams-1];
5777
5778
2/2
✓ Branch 0 taken 219 times.
✓ Branch 1 taken 73 times.
292 for (i = 0; i < 3; i++) {
5779 uint8_t **p;
5780 uint32_t len, tag;
5781
5782
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 219 times.
219 if (end - avio_tell(pb) <= 12)
5783 break;
5784
5785 219 len = avio_rb32(pb);
5786 219 tag = avio_rl32(pb);
5787 219 avio_skip(pb, 4); // flags
5788
5789
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))
5790 break;
5791 219 len -= 12;
5792
5793
2/2
✓ Branch 0 taken 73 times.
✓ Branch 1 taken 146 times.
219 if (tag == MKTAG('m', 'e', 'a', 'n'))
5794 73 p = &mean;
5795
2/2
✓ Branch 0 taken 73 times.
✓ Branch 1 taken 73 times.
146 else if (tag == MKTAG('n', 'a', 'm', 'e'))
5796 73 p = &key;
5797
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) {
5798 73 avio_skip(pb, 4);
5799 73 len -= 4;
5800 73 p = &val;
5801 } else
5802 break;
5803
5804
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 219 times.
219 if (*p)
5805 break;
5806
5807 219 *p = av_malloc(len + 1);
5808
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 219 times.
219 if (!*p) {
5809 ret = AVERROR(ENOMEM);
5810 break;
5811 }
5812 219 ret = ffio_read_size(pb, *p, len);
5813
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 219 times.
219 if (ret < 0) {
5814 av_freep(p);
5815 break;
5816 }
5817 219 (*p)[len] = 0;
5818 }
5819
5820
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) {
5821
2/2
✓ Branch 0 taken 35 times.
✓ Branch 1 taken 38 times.
73 if (strcmp(key, "iTunSMPB") == 0) {
5822 int64_t priming, remainder, samples;
5823
1/2
✓ Branch 1 taken 35 times.
✗ Branch 2 not taken.
35 if (ff_itunes_parse_smpb(val, &priming, &remainder, &samples) >= 0) {
5824
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)
5825 35 st->codecpar->initial_padding = priming = av_rescale_q(priming, st->time_base,
5826 35 (AVRational){ 1, st->codecpar->sample_rate });
5827
1/2
✓ Branch 0 taken 35 times.
✗ Branch 1 not taken.
35 if (remainder > 0) {
5828 35 int64_t duration = av_rescale_q(st->duration, st->time_base,
5829 35 (AVRational){ 1, st->codecpar->sample_rate });
5830 35 remainder = av_rescale_q(remainder, st->time_base,
5831 35 (AVRational){ 1, st->codecpar->sample_rate });
5832 35 samples = av_rescale_q(samples, st->time_base,
5833 35 (AVRational){ 1, st->codecpar->sample_rate });
5834
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) {
5835 35 ffstream(st)->first_discard_sample = duration - remainder;
5836 35 ffstream(st)->last_discard_sample = duration;
5837 }
5838 }
5839 35 av_log(c->fc, AV_LOG_DEBUG, "Parsed iTunSMPB: priming %"PRId64", "
5840 "remainder %"PRId64" samples %"PRId64"\n",
5841 priming, remainder, samples);
5842 }
5843 }
5844
1/2
✓ Branch 0 taken 73 times.
✗ Branch 1 not taken.
73 if (strcmp(mean, "com.apple.iTunes") == 0 &&
5845
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 71 times.
73 strcmp(key, "DISCSUBTITLE") == 0) {
5846 2 av_dict_set(&c->fc->metadata, "disc_subtitle", val,
5847 AV_DICT_DONT_STRDUP_VAL);
5848 2 val = NULL;
5849 }
5850
2/2
✓ Branch 0 taken 63 times.
✓ Branch 1 taken 10 times.
136 if (strcmp(key, "cdec") != 0) {
5851 63 av_dict_set(&c->fc->metadata, key, val,
5852 AV_DICT_DONT_STRDUP_KEY | AV_DICT_DONT_STRDUP_VAL);
5853 63 key = val = NULL;
5854 }
5855 } else {
5856 av_log(c->fc, AV_LOG_VERBOSE,
5857 "Unhandled or malformed custom metadata of size %"PRId64"\n", atom.size);
5858 }
5859
5860 73 avio_seek(pb, end, SEEK_SET);
5861 73 av_freep(&key);
5862 73 av_freep(&val);
5863 73 av_freep(&mean);
5864 73 return ret;
5865 }
5866
5867 43 static int heif_add_stream(MOVContext *c, HEIFItem *item)
5868 {
5869 MOVStreamContext *sc;
5870 AVStream *st;
5871
5872 43 st = avformat_new_stream(c->fc, NULL);
5873
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 43 times.
43 if (!st)
5874 return AVERROR(ENOMEM);
5875 43 sc = av_mallocz(sizeof(MOVStreamContext));
5876
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 43 times.
43 if (!sc)
5877 goto fail;
5878
5879 43 item->st = st;
5880 43 st->id = item->item_id;
5881 43 st->priv_data = sc;
5882 43 st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
5883 43 st->codecpar->codec_id = mov_codec_id(st, item->type);
5884 43 sc->id = st->id;
5885 43 sc->ffindex = st->index;
5886 43 st->avg_frame_rate.num = st->avg_frame_rate.den = 1;
5887 43 st->time_base.num = st->time_base.den = 1;
5888 43 st->nb_frames = 1;
5889 43 sc->time_scale = 1;
5890 43 sc->pb = c->fc->pb;
5891 43 sc->pb_is_copied = 1;
5892 43 sc->refcount = 1;
5893
5894
1/2
✓ Branch 0 taken 43 times.
✗ Branch 1 not taken.
43 if (item->name)
5895 43 av_dict_set(&st->metadata, "title", item->name, 0);
5896
5897 // Populate the necessary fields used by mov_build_index.
5898 43 sc->stsc_data = av_malloc_array(1, sizeof(*sc->stsc_data));
5899
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 43 times.
43 if (!sc->stsc_data)
5900 goto fail;
5901 43 sc->stsc_count = 1;
5902 43 sc->stsc_data[0].first = 1;
5903 43 sc->stsc_data[0].count = 1;
5904 43 sc->stsc_data[0].id = 1;
5905 43 sc->chunk_offsets = av_malloc_array(1, sizeof(*sc->chunk_offsets));
5906
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 43 times.
43 if (!sc->chunk_offsets)
5907 goto fail;
5908 43 sc->chunk_count = 1;
5909 43 sc->stts_data = av_malloc_array(1, sizeof(*sc->stts_data));
5910
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 43 times.
43 if (!sc->stts_data)
5911 goto fail;
5912 43 sc->stts_count = 1;
5913 43 sc->stts_data[0].count = 1;
5914 // Not used for still images. But needed by mov_build_index.
5915 43 sc->stts_data[0].duration = 0;
5916
5917 43 return 0;
5918 fail:
5919 mov_free_stream_context(c->fc, st);
5920 ff_remove_stream(c->fc, st);
5921 item->st = NULL;
5922
5923 return AVERROR(ENOMEM);
5924 }
5925
5926 187 static int mov_read_meta(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5927 {
5928
1/2
✓ Branch 0 taken 547 times.
✗ Branch 1 not taken.
547 while (atom.size > 8) {
5929 uint32_t tag;
5930
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 547 times.
547 if (avio_feof(pb))
5931 return AVERROR_EOF;
5932 547 tag = avio_rl32(pb);
5933 547 atom.size -= 4;
5934
2/2
✓ Branch 0 taken 187 times.
✓ Branch 1 taken 360 times.
547 if (tag == MKTAG('h','d','l','r')) {
5935 187 avio_seek(pb, -8, SEEK_CUR);
5936 187 atom.size += 8;
5937 187 return mov_read_default(c, pb, atom);
5938 }
5939 }
5940 return 0;
5941 }
5942
5943 // return 1 when matrix is identity, 0 otherwise
5944 #define IS_MATRIX_IDENT(matrix) \
5945 ( (matrix)[0][0] == (1 << 16) && \
5946 (matrix)[1][1] == (1 << 16) && \
5947 (matrix)[2][2] == (1 << 30) && \
5948 !(matrix)[0][1] && !(matrix)[0][2] && \
5949 !(matrix)[1][0] && !(matrix)[1][2] && \
5950 !(matrix)[2][0] && !(matrix)[2][1])
5951
5952 673 static int mov_read_tkhd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5953 {
5954 int i, j, e;
5955 int width;
5956 int height;
5957 int display_matrix[3][3];
5958 673 int res_display_matrix[3][3] = { { 0 } };
5959 AVStream *st;
5960 MOVStreamContext *sc;
5961 int version;
5962 int flags;
5963
5964
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 673 times.
673 if (c->fc->nb_streams < 1)
5965 return 0;
5966 673 st = c->fc->streams[c->fc->nb_streams-1];
5967 673 sc = st->priv_data;
5968
5969 // Each stream (trak) should have exactly 1 tkhd. This catches bad files and
5970 // avoids corrupting AVStreams mapped to an earlier tkhd.
5971
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 673 times.
673 if (st->id != -1)
5972 return AVERROR_INVALIDDATA;
5973
5974 673 version = avio_r8(pb);
5975 673 flags = avio_rb24(pb);
5976 673 st->disposition |= (flags & MOV_TKHD_FLAG_ENABLED) ? AV_DISPOSITION_DEFAULT : 0;
5977
5978
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 660 times.
673 if (version == 1) {
5979 13 avio_rb64(pb);
5980 13 avio_rb64(pb);
5981 } else {
5982 660 avio_rb32(pb); /* creation time */
5983 660 avio_rb32(pb); /* modification time */
5984 }
5985 673 st->id = (int)avio_rb32(pb); /* track id (NOT 0 !)*/
5986 673 sc->id = st->id;
5987 673 avio_rb32(pb); /* reserved */
5988
5989 /* highlevel (considering edits) duration in movie timebase */
5990
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 660 times.
673 (version == 1) ? avio_rb64(pb) : avio_rb32(pb);
5991 673 avio_rb32(pb); /* reserved */
5992 673 avio_rb32(pb); /* reserved */
5993
5994 673 avio_rb16(pb); /* layer */
5995 673 avio_rb16(pb); /* alternate group */
5996 673 avio_rb16(pb); /* volume */
5997 673 avio_rb16(pb); /* reserved */
5998
5999 //read in the display matrix (outlined in ISO 14496-12, Section 6.2.2)
6000 // they're kept in fixed point format through all calculations
6001 // save u,v,z to store the whole matrix in the AV_PKT_DATA_DISPLAYMATRIX
6002 // side data, but the scale factor is not needed to calculate aspect ratio
6003
2/2
✓ Branch 0 taken 2019 times.
✓ Branch 1 taken 673 times.
2692 for (i = 0; i < 3; i++) {
6004 2019 display_matrix[i][0] = avio_rb32(pb); // 16.16 fixed point
6005 2019 display_matrix[i][1] = avio_rb32(pb); // 16.16 fixed point
6006 2019 display_matrix[i][2] = avio_rb32(pb); // 2.30 fixed point
6007 }
6008
6009 673 width = avio_rb32(pb); // 16.16 fixed point track width
6010 673 height = avio_rb32(pb); // 16.16 fixed point track height
6011 673 sc->width = width >> 16;
6012 673 sc->height = height >> 16;
6013
6014 // apply the moov display matrix (after the tkhd one)
6015
2/2
✓ Branch 0 taken 2019 times.
✓ Branch 1 taken 673 times.
2692 for (i = 0; i < 3; i++) {
6016 2019 const int sh[3] = { 16, 16, 30 };
6017
2/2
✓ Branch 0 taken 6057 times.
✓ Branch 1 taken 2019 times.
8076 for (j = 0; j < 3; j++) {
6018
2/2
✓ Branch 0 taken 18171 times.
✓ Branch 1 taken 6057 times.
24228 for (e = 0; e < 3; e++) {
6019 18171 res_display_matrix[i][j] +=
6020 18171 ((int64_t) display_matrix[i][e] *
6021 18171 c->movie_display_matrix[e][j]) >> sh[e];
6022 }
6023 }
6024 }
6025
6026 // save the matrix when it is not the default identity
6027
10/18
✓ Branch 0 taken 664 times.
✓ Branch 1 taken 9 times.
✓ Branch 2 taken 664 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 664 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 664 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 664 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 664 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 664 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 664 times.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✓ Branch 17 taken 664 times.
673 if (!IS_MATRIX_IDENT(res_display_matrix)) {
6028 9 av_freep(&sc->display_matrix);
6029 9 sc->display_matrix = av_malloc(sizeof(int32_t) * 9);
6030
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if (!sc->display_matrix)
6031 return AVERROR(ENOMEM);
6032
6033
2/2
✓ Branch 0 taken 27 times.
✓ Branch 1 taken 9 times.
36 for (i = 0; i < 3; i++)
6034
2/2
✓ Branch 0 taken 81 times.
✓ Branch 1 taken 27 times.
108 for (j = 0; j < 3; j++)
6035 81 sc->display_matrix[i * 3 + j] = res_display_matrix[i][j];
6036 }
6037
6038 // transform the display width/height according to the matrix
6039 // to keep the same scale, use [width height 1<<16]
6040
5/6
✓ Branch 0 taken 347 times.
✓ Branch 1 taken 326 times.
✓ Branch 2 taken 347 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 8 times.
✓ Branch 5 taken 339 times.
673 if (width && height && sc->display_matrix) {
6041 double disp_transform[2];
6042
6043
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 8 times.
24 for (i = 0; i < 2; i++)
6044 16 disp_transform[i] = hypot(sc->display_matrix[0 + i],
6045 16 sc->display_matrix[3 + i]);
6046
6047
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 &&
6048
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) &&
6049
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 5 times.
8 fabs((disp_transform[0] / disp_transform[1]) - 1.0) > 0.01)
6050 3 st->sample_aspect_ratio = av_d2q(
6051 3 disp_transform[0] / disp_transform[1],
6052 INT_MAX);
6053 }
6054 673 return 0;
6055 }
6056
6057 499 static int mov_read_tfhd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6058 {
6059 499 MOVFragment *frag = &c->fragment;
6060 499 MOVTrackExt *trex = NULL;
6061 int flags, track_id, i;
6062 MOVFragmentStreamInfo * frag_stream_info;
6063
6064 499 avio_r8(pb); /* version */
6065 499 flags = avio_rb24(pb);
6066
6067 499 track_id = avio_rb32(pb);
6068
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 499 times.
499 if (!track_id)
6069 return AVERROR_INVALIDDATA;
6070
1/2
✓ Branch 0 taken 558 times.
✗ Branch 1 not taken.
558 for (i = 0; i < c->trex_count; i++)
6071
2/2
✓ Branch 0 taken 499 times.
✓ Branch 1 taken 59 times.
558 if (c->trex_data[i].track_id == track_id) {
6072 499 trex = &c->trex_data[i];
6073 499 break;
6074 }
6075
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 499 times.
499 if (!trex) {
6076 av_log(c->fc, AV_LOG_WARNING, "could not find corresponding trex (id %u)\n", track_id);
6077 return 0;
6078 }
6079 499 c->fragment.found_tfhd = 1;
6080 499 frag->track_id = track_id;
6081 499 set_frag_stream(&c->frag_index, track_id);
6082
6083 998 frag->base_data_offset = flags & MOV_TFHD_BASE_DATA_OFFSET ?
6084
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 499 times.
998 avio_rb64(pb) : flags & MOV_TFHD_DEFAULT_BASE_IS_MOOF ?
6085
2/2
✓ Branch 0 taken 426 times.
✓ Branch 1 taken 73 times.
499 frag->moof_offset : frag->implicit_offset;
6086
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;
6087
6088 998 frag->duration = flags & MOV_TFHD_DEFAULT_DURATION ?
6089
2/2
✓ Branch 0 taken 64 times.
✓ Branch 1 taken 435 times.
499 avio_rb32(pb) : trex->duration;
6090 998 frag->size = flags & MOV_TFHD_DEFAULT_SIZE ?
6091
2/2
✓ Branch 0 taken 59 times.
✓ Branch 1 taken 440 times.
499 avio_rb32(pb) : trex->size;
6092 998 frag->flags = flags & MOV_TFHD_DEFAULT_FLAGS ?
6093
2/2
✓ Branch 0 taken 133 times.
✓ Branch 1 taken 366 times.
499 avio_rb32(pb) : trex->flags;
6094 499 av_log(c->fc, AV_LOG_TRACE, "frag flags 0x%x\n", frag->flags);
6095
6096 499 frag_stream_info = get_current_frag_stream_info(&c->frag_index);
6097
1/2
✓ Branch 0 taken 499 times.
✗ Branch 1 not taken.
499 if (frag_stream_info) {
6098 499 frag_stream_info->next_trun_dts = AV_NOPTS_VALUE;
6099 499 frag_stream_info->stsd_id = frag->stsd_id;
6100 }
6101 499 return 0;
6102 }
6103
6104 2 static int mov_read_chap(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6105 {
6106 unsigned i, num;
6107 void *new_tracks;
6108
6109 2 num = atom.size / 4;
6110
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if (!(new_tracks = av_malloc_array(num, sizeof(int))))
6111 return AVERROR(ENOMEM);
6112
6113 2 av_free(c->chapter_tracks);
6114 2 c->chapter_tracks = new_tracks;
6115 2 c->nb_chapter_tracks = num;
6116
6117
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++)
6118 2 c->chapter_tracks[i] = avio_rb32(pb);
6119
6120 2 c->nb_chapter_tracks = i;
6121
6122 2 return 0;
6123 }
6124
6125 28 static int mov_read_trex(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6126 {
6127 MOVTrackExt *trex;
6128 int err;
6129
6130
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))
6131 return AVERROR_INVALIDDATA;
6132
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 28 times.
28 if ((err = av_reallocp_array(&c->trex_data, c->trex_count + 1,
6133 sizeof(*c->trex_data))) < 0) {
6134 c->trex_count = 0;
6135 return err;
6136 }
6137
6138 28 c->fc->duration = AV_NOPTS_VALUE; // the duration from mvhd is not representing the whole file when fragments are used.
6139
6140 28 trex = &c->trex_data[c->trex_count++];
6141 28 avio_r8(pb); /* version */
6142 28 avio_rb24(pb); /* flags */
6143 28 trex->track_id = avio_rb32(pb);
6144 28 trex->stsd_id = avio_rb32(pb);
6145 28 trex->duration = avio_rb32(pb);
6146 28 trex->size = avio_rb32(pb);
6147 28 trex->flags = avio_rb32(pb);
6148 28 return 0;
6149 }
6150
6151 426 static int mov_read_tfdt(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6152 {
6153 426 MOVFragment *frag = &c->fragment;
6154 426 AVStream *st = NULL;
6155 MOVStreamContext *sc;
6156 int version, i;
6157 MOVFragmentStreamInfo * frag_stream_info;
6158 int64_t base_media_decode_time;
6159
6160
1/2
✓ Branch 0 taken 453 times.
✗ Branch 1 not taken.
453 for (i = 0; i < c->fc->nb_streams; i++) {
6161 453 sc = c->fc->streams[i]->priv_data;
6162
2/2
✓ Branch 0 taken 426 times.
✓ Branch 1 taken 27 times.
453 if (sc->id == frag->track_id) {
6163 426 st = c->fc->streams[i];
6164 426 break;
6165 }
6166 }
6167
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 426 times.
426 if (!st) {
6168 av_log(c->fc, AV_LOG_WARNING, "could not find corresponding track id %u\n", frag->track_id);
6169 return 0;
6170 }
6171 426 sc = st->priv_data;
6172
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)
6173 return 0;
6174 426 version = avio_r8(pb);
6175 426 avio_rb24(pb); /* flags */
6176
2/2
✓ Branch 0 taken 56 times.
✓ Branch 1 taken 370 times.
426 if (version) {
6177 56 base_media_decode_time = avio_rb64(pb);
6178 } else {
6179 370 base_media_decode_time = avio_rb32(pb);
6180 }
6181
6182 426 frag_stream_info = get_current_frag_stream_info(&c->frag_index);
6183
1/2
✓ Branch 0 taken 426 times.
✗ Branch 1 not taken.
426 if (frag_stream_info)
6184 426 frag_stream_info->tfdt_dts = base_media_decode_time;
6185 426 sc->track_end = base_media_decode_time;
6186
6187 426 return 0;
6188 }
6189
6190 499 static int mov_read_trun(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6191 {
6192 499 MOVFragment *frag = &c->fragment;
6193 499 AVStream *st = NULL;
6194 499 FFStream *sti = NULL;
6195 MOVStreamContext *sc;
6196 MOVTimeToSample *tts_data;
6197 uint64_t offset;
6198 499 int64_t dts, pts = AV_NOPTS_VALUE;
6199 499 int data_offset = 0;
6200 499 unsigned entries, first_sample_flags = frag->flags;
6201 int flags, distance, i;
6202 499 int64_t prev_dts = AV_NOPTS_VALUE;
6203 499 int next_frag_index = -1, index_entry_pos;
6204 size_t requested_size;
6205 size_t old_allocated_size;
6206 AVIndexEntry *new_entries;
6207 MOVFragmentStreamInfo * frag_stream_info;
6208
6209
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 499 times.
499 if (!frag->found_tfhd) {
6210 av_log(c->fc, AV_LOG_ERROR, "trun track id unknown, no tfhd was found\n");
6211 return AVERROR_INVALIDDATA;
6212 }
6213
6214
1/2
✓ Branch 0 taken 558 times.
✗ Branch 1 not taken.
558 for (i = 0; i < c->fc->nb_streams; i++) {
6215 558 sc = c->fc->streams[i]->priv_data;
6216
2/2
✓ Branch 0 taken 499 times.
✓ Branch 1 taken 59 times.
558 if (sc->id == frag->track_id) {
6217 499 st = c->fc->streams[i];
6218 499 sti = ffstream(st);
6219 499 break;
6220 }
6221 }
6222
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 499 times.
499 if (!st) {
6223 av_log(c->fc, AV_LOG_WARNING, "could not find corresponding track id %u\n", frag->track_id);
6224 return 0;
6225 }
6226 499 sc = st->priv_data;
6227
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)
6228 return 0;
6229
6230 // Find the next frag_index index that has a valid index_entry for
6231 // the current track_id.
6232 //
6233 // A valid index_entry means the trun for the fragment was read
6234 // and it's samples are in index_entries at the given position.
6235 // New index entries will be inserted before the index_entry found.
6236 499 index_entry_pos = sti->nb_index_entries;
6237
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++) {
6238 1634 frag_stream_info = get_frag_stream_info(&c->frag_index, i, frag->track_id);
6239
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) {
6240 next_frag_index = i;
6241 index_entry_pos = frag_stream_info->index_entry;
6242 break;
6243 }
6244 }
6245
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 499 times.
499 av_assert0(index_entry_pos <= sti->nb_index_entries);
6246
6247 499 avio_r8(pb); /* version */
6248 499 flags = avio_rb24(pb);
6249 499 entries = avio_rb32(pb);
6250 499 av_log(c->fc, AV_LOG_TRACE, "flags 0x%x entries %u\n", flags, entries);
6251
6252
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))
6253 return AVERROR_INVALIDDATA;
6254
1/2
✓ Branch 0 taken 499 times.
✗ Branch 1 not taken.
499 if (flags & MOV_TRUN_DATA_OFFSET) data_offset = avio_rb32(pb);
6255
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);
6256
6257 499 int entry_size = !!(flags & MOV_TRUN_SAMPLE_DURATION) * 4
6258 499 + !!(flags & MOV_TRUN_SAMPLE_SIZE) * 4
6259 499 + !!(flags & MOV_TRUN_SAMPLE_FLAGS) * 4
6260 499 + !!(flags & MOV_TRUN_SAMPLE_CTS) * 4;
6261 499 int64_t sample_data_size = avio_size(sc->pb);
6262 499 int64_t max_entries = INT64_MAX;
6263
6264
2/2
✓ Branch 0 taken 498 times.
✓ Branch 1 taken 1 times.
499 if (sample_data_size > 0)
6265 498 max_entries = sample_data_size - sti->nb_index_entries;
6266
2/2
✓ Branch 0 taken 473 times.
✓ Branch 1 taken 26 times.
499 if (entry_size) {
6267
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 473 times.
473 int64_t size = sc->pb == pb ? sample_data_size : avio_size(pb);
6268 473 int64_t pos = avio_tell(pb);
6269 473 int64_t left = atom.size - 8 - !!(flags & MOV_TRUN_DATA_OFFSET) * 4
6270 473 - !!(flags & MOV_TRUN_FIRST_SAMPLE_FLAGS) * 4;
6271
6272
3/4
✓ Branch 0 taken 473 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 472 times.
✓ Branch 3 taken 1 times.
473 if (pos >= 0 && size >= pos)
6273 472 left = FFMIN(left, size - pos);
6274 473 max_entries = FFMIN(max_entries, left / entry_size);
6275 }
6276
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 499 times.
499 if (entries > max_entries) {
6277 av_log(c->fc, AV_LOG_ERROR, "trun sample count %u exceeds the %"PRId64" "
6278 "samples the input can hold\n", entries, max_entries);
6279 return AVERROR_INVALIDDATA;
6280 }
6281
6282 499 frag_stream_info = get_current_frag_stream_info(&c->frag_index);
6283
1/2
✓ Branch 0 taken 499 times.
✗ Branch 1 not taken.
499 if (frag_stream_info) {
6284
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 499 times.
499 if (frag_stream_info->next_trun_dts != AV_NOPTS_VALUE) {
6285 dts = frag_stream_info->next_trun_dts - sc->time_offset;
6286
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 496 times.
499 } else if (frag_stream_info->first_tfra_pts != AV_NOPTS_VALUE &&
6287
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 c->use_mfra_for == FF_MOV_FLAG_MFRA_PTS) {
6288 3 pts = frag_stream_info->first_tfra_pts;
6289 3 av_log(c->fc, AV_LOG_DEBUG, "found mfra time %"PRId64
6290 ", using it for pts\n", pts);
6291
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 496 times.
496 } else if (frag_stream_info->first_tfra_pts != AV_NOPTS_VALUE &&
6292 c->use_mfra_for == FF_MOV_FLAG_MFRA_DTS) {
6293 dts = frag_stream_info->first_tfra_pts;
6294 av_log(c->fc, AV_LOG_DEBUG, "found mfra time %"PRId64
6295 ", using it for dts\n", pts);
6296 } else {
6297 496 int has_tfdt = frag_stream_info->tfdt_dts != AV_NOPTS_VALUE;
6298 496 int has_sidx = frag_stream_info->sidx_pts != AV_NOPTS_VALUE;
6299
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;
6300
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;
6301
6302
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 496 times.
496 if (fallback_sidx) {
6303 av_log(c->fc, AV_LOG_DEBUG, "use_tfdt set but no tfdt found, using sidx instead\n");
6304 }
6305
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 496 times.
496 if (fallback_tfdt) {
6306 av_log(c->fc, AV_LOG_DEBUG, "use_tfdt not set but no sidx found, using tfdt instead\n");
6307 }
6308
6309
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) {
6310 423 dts = frag_stream_info->tfdt_dts - sc->time_offset;
6311 423 av_log(c->fc, AV_LOG_DEBUG, "found tfdt time %"PRId64
6312 ", using it for dts\n", dts);
6313
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) {
6314 // FIXME: sidx earliest_presentation_time is *PTS*, s.b.
6315 // pts = frag_stream_info->sidx_pts;
6316 dts = frag_stream_info->sidx_pts;
6317 av_log(c->fc, AV_LOG_DEBUG, "found sidx time %"PRId64
6318 ", using it for dts\n", frag_stream_info->sidx_pts);
6319 } else {
6320 73 dts = sc->track_end - sc->time_offset;
6321 73 av_log(c->fc, AV_LOG_DEBUG, "found track end time %"PRId64
6322 ", using it for dts\n", dts);
6323 }
6324 }
6325 } else {
6326 dts = sc->track_end - sc->time_offset;
6327 av_log(c->fc, AV_LOG_DEBUG, "found track end time %"PRId64
6328 ", using it for dts\n", dts);
6329 }
6330 499 offset = frag->base_data_offset + data_offset;
6331 499 distance = 0;
6332 499 av_log(c->fc, AV_LOG_TRACE, "first sample flags 0x%x\n", first_sample_flags);
6333
6334 // realloc space for new index entries
6335
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 499 times.
499 if ((uint64_t)sti->nb_index_entries + entries >= UINT_MAX / sizeof(AVIndexEntry)) {
6336 entries = UINT_MAX / sizeof(AVIndexEntry) - sti->nb_index_entries;
6337 av_log(c->fc, AV_LOG_ERROR, "Failed to add index entry\n");
6338 }
6339
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 499 times.
499 if (entries == 0)
6340 return 0;
6341
6342 499 requested_size = (sti->nb_index_entries + entries) * sizeof(AVIndexEntry);
6343 499 new_entries = av_fast_realloc(sti->index_entries,
6344 &sti->index_entries_allocated_size,
6345 requested_size);
6346
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 499 times.
499 if (!new_entries)
6347 return AVERROR(ENOMEM);
6348 499 sti->index_entries= new_entries;
6349
6350 499 requested_size = (sti->nb_index_entries + entries) * sizeof(*sc->tts_data);
6351 499 old_allocated_size = sc->tts_allocated_size;
6352 499 tts_data = av_fast_realloc(sc->tts_data, &sc->tts_allocated_size,
6353 requested_size);
6354
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 499 times.
499 if (!tts_data)
6355 return AVERROR(ENOMEM);
6356 499 sc->tts_data = tts_data;
6357
6358 // In case there were samples without time to sample entries, ensure they get
6359 // zero valued entries. This ensures clips which mix boxes with and
6360 // without time to sample entries don't pickup uninitialized data.
6361 499 memset((uint8_t*)(sc->tts_data) + old_allocated_size, 0,
6362 499 sc->tts_allocated_size - old_allocated_size);
6363
6364
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 499 times.
499 if (index_entry_pos < sti->nb_index_entries) {
6365 // Make hole in index_entries and tts_data for new samples
6366 memmove(sti->index_entries + index_entry_pos + entries,
6367 sti->index_entries + index_entry_pos,
6368 sizeof(*sti->index_entries) *
6369 (sti->nb_index_entries - index_entry_pos));
6370 memmove(sc->tts_data + index_entry_pos + entries,
6371 sc->tts_data + index_entry_pos,
6372 sizeof(*sc->tts_data) * (sc->tts_count - index_entry_pos));
6373 if (index_entry_pos < sc->current_sample) {
6374 sc->current_sample += entries;
6375 }
6376 }
6377
6378 499 sti->nb_index_entries += entries;
6379 499 sc->tts_count = sti->nb_index_entries;
6380 499 sc->stts_count = sti->nb_index_entries;
6381
2/2
✓ Branch 0 taken 386 times.
✓ Branch 1 taken 113 times.
499 if (flags & MOV_TRUN_SAMPLE_CTS)
6382 386 sc->ctts_count = sti->nb_index_entries;
6383
6384 // Record the index_entry position in frag_index of this fragment
6385
1/2
✓ Branch 0 taken 499 times.
✗ Branch 1 not taken.
499 if (frag_stream_info) {
6386 499 frag_stream_info->index_entry = index_entry_pos;
6387
1/2
✓ Branch 0 taken 499 times.
✗ Branch 1 not taken.
499 if (frag_stream_info->index_base < 0)
6388 499 frag_stream_info->index_base = index_entry_pos;
6389 }
6390
6391
2/2
✓ Branch 0 taken 472 times.
✓ Branch 1 taken 27 times.
499 if (index_entry_pos > 0)
6392 472 prev_dts = sti->index_entries[index_entry_pos-1].timestamp;
6393
6394
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++) {
6395 8707 unsigned sample_size = frag->size;
6396
2/2
✓ Branch 0 taken 8208 times.
✓ Branch 1 taken 499 times.
8707 int sample_flags = i ? frag->flags : first_sample_flags;
6397 8707 unsigned sample_duration = frag->duration;
6398 8707 unsigned ctts_duration = 0;
6399 8707 int keyframe = 0;
6400 8707 int index_entry_flags = 0;
6401
6402
2/2
✓ Branch 0 taken 1674 times.
✓ Branch 1 taken 7033 times.
8707 if (flags & MOV_TRUN_SAMPLE_DURATION) sample_duration = avio_rb32(pb);
6403
2/2
✓ Branch 0 taken 8649 times.
✓ Branch 1 taken 58 times.
8707 if (flags & MOV_TRUN_SAMPLE_SIZE) sample_size = avio_rb32(pb);
6404
2/2
✓ Branch 0 taken 981 times.
✓ Branch 1 taken 7726 times.
8707 if (flags & MOV_TRUN_SAMPLE_FLAGS) sample_flags = avio_rb32(pb);
6405
2/2
✓ Branch 0 taken 6576 times.
✓ Branch 1 taken 2131 times.
8707 if (flags & MOV_TRUN_SAMPLE_CTS) ctts_duration = avio_rb32(pb);
6406
6407 8707 mov_update_dts_shift(sc, ctts_duration, c->fc);
6408
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 8704 times.
8707 if (pts != AV_NOPTS_VALUE) {
6409 3 dts = pts - sc->dts_shift;
6410
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (flags & MOV_TRUN_SAMPLE_CTS) {
6411 dts -= ctts_duration;
6412 } else {
6413 3 dts -= sc->time_offset;
6414 }
6415 3 av_log(c->fc, AV_LOG_DEBUG,
6416 "pts %"PRId64" calculated dts %"PRId64
6417 " sc->dts_shift %d ctts.duration %d"
6418 " sc->time_offset %"PRId64
6419 " flags & MOV_TRUN_SAMPLE_CTS %d\n",
6420 pts, dts,
6421 sc->dts_shift, ctts_duration,
6422 sc->time_offset, flags & MOV_TRUN_SAMPLE_CTS);
6423 3 pts = AV_NOPTS_VALUE;
6424 }
6425
6426 8707 keyframe =
6427 8707 !(sample_flags & (MOV_FRAG_SAMPLE_FLAG_IS_NON_SYNC |
6428 MOV_FRAG_SAMPLE_FLAG_DEPENDS_YES));
6429
2/2
✓ Branch 0 taken 646 times.
✓ Branch 1 taken 8061 times.
8707 if (keyframe) {
6430 646 distance = 0;
6431 646 index_entry_flags |= AVINDEX_KEYFRAME;
6432 }
6433 // Fragments can overlap in time. Discard overlapping frames after
6434 // decoding.
6435
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 8683 times.
8707 if (prev_dts >= dts)
6436 24 index_entry_flags |= AVINDEX_DISCARD_FRAME;
6437
6438 8707 sti->index_entries[index_entry_pos].pos = offset;
6439 8707 sti->index_entries[index_entry_pos].timestamp = dts;
6440 8707 sti->index_entries[index_entry_pos].size = sample_size;
6441 8707 sti->index_entries[index_entry_pos].min_distance = distance;
6442 8707 sti->index_entries[index_entry_pos].flags = index_entry_flags;
6443
6444 8707 sc->tts_data[index_entry_pos].count = 1;
6445 8707 sc->tts_data[index_entry_pos].offset = ctts_duration;
6446 8707 sc->tts_data[index_entry_pos].duration = sample_duration;
6447 8707 index_entry_pos++;
6448
6449 8707 av_log(c->fc, AV_LOG_TRACE, "AVIndex stream %d, sample %d, offset %"PRIx64", dts %"PRId64", "
6450 "size %u, distance %d, keyframe %d\n", st->index,
6451 index_entry_pos, offset, dts, sample_size, distance, keyframe);
6452 8707 distance++;
6453
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 8707 times.
8707 if (av_sat_add64(dts, sample_duration) != dts + (uint64_t)sample_duration)
6454 return AVERROR_INVALIDDATA;
6455
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8707 times.
8707 if (!sample_size)
6456 return AVERROR_INVALIDDATA;
6457 8707 dts += sample_duration;
6458 8707 offset += sample_size;
6459 8707 sc->data_size += sample_size;
6460
6461
1/2
✓ Branch 0 taken 8707 times.
✗ Branch 1 not taken.
8707 if (sample_duration <= INT64_MAX - sc->duration_for_fps &&
6462
1/2
✓ Branch 0 taken 8707 times.
✗ Branch 1 not taken.
8707 1 <= INT_MAX - sc->nb_frames_for_fps
6463 ) {
6464 8707 sc->duration_for_fps += sample_duration;
6465 8707 sc->nb_frames_for_fps ++;
6466 }
6467 }
6468
1/2
✓ Branch 0 taken 499 times.
✗ Branch 1 not taken.
499 if (frag_stream_info)
6469 499 frag_stream_info->next_trun_dts = dts + sc->time_offset;
6470
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 499 times.
499 if (i < entries) {
6471 // EOF found before reading all entries. Fix the hole this would
6472 // leave in index_entries and tts_data
6473 int gap = entries - i;
6474 memmove(sti->index_entries + index_entry_pos,
6475 sti->index_entries + index_entry_pos + gap,
6476 sizeof(*sti->index_entries) *
6477 (sti->nb_index_entries - (index_entry_pos + gap)));
6478 memmove(sc->tts_data + index_entry_pos,
6479 sc->tts_data + index_entry_pos + gap,
6480 sizeof(*sc->tts_data) *
6481 (sc->tts_count - (index_entry_pos + gap)));
6482
6483 sti->nb_index_entries -= gap;
6484 sc->tts_count -= gap;
6485 if (index_entry_pos < sc->current_sample) {
6486 sc->current_sample -= gap;
6487 }
6488 entries = i;
6489 }
6490
6491 // The end of this new fragment may overlap in time with the start
6492 // of the next fragment in index_entries. Mark the samples in the next
6493 // fragment that overlap with AVINDEX_DISCARD_FRAME
6494 499 prev_dts = AV_NOPTS_VALUE;
6495
1/2
✓ Branch 0 taken 499 times.
✗ Branch 1 not taken.
499 if (index_entry_pos > 0)
6496 499 prev_dts = sti->index_entries[index_entry_pos-1].timestamp;
6497
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 499 times.
499 for (int i = index_entry_pos; i < sti->nb_index_entries; i++) {
6498 if (prev_dts < sti->index_entries[i].timestamp)
6499 break;
6500 sti->index_entries[i].flags |= AVINDEX_DISCARD_FRAME;
6501 }
6502
6503 // If a hole was created to insert the new index_entries into,
6504 // the index_entry recorded for all subsequent moof must
6505 // be incremented by the number of entries inserted.
6506 499 fix_frag_index_entries(&c->frag_index, next_frag_index,
6507 499 frag->track_id, entries);
6508
6509
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 499 times.
499 if (pb->eof_reached) {
6510 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted TRUN atom\n");
6511 return AVERROR_EOF;
6512 }
6513
6514 499 frag->implicit_offset = offset;
6515
6516 499 sc->track_end = dts + sc->time_offset;
6517
2/2
✓ Branch 0 taken 116 times.
✓ Branch 1 taken 383 times.
499 if (st->duration < sc->track_end)
6518 116 st->duration = sc->track_end;
6519
6520 499 return 0;
6521 }
6522
6523 46 static int mov_read_sidx(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6524 {
6525 46 int64_t stream_size = avio_size(pb);
6526 46 int64_t offset = av_sat_add64(avio_tell(pb), atom.size), pts, timestamp;
6527 uint8_t version, is_complete;
6528 int64_t offadd;
6529 unsigned i, j, track_id, item_count;
6530 46 AVStream *st = NULL;
6531 46 AVStream *ref_st = NULL;
6532 46 MOVStreamContext *sc, *ref_sc = NULL;
6533 AVRational timescale;
6534
6535 46 version = avio_r8(pb);
6536
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 46 times.
46 if (version > 1) {
6537 avpriv_request_sample(c->fc, "sidx version %u", version);
6538 return 0;
6539 }
6540
6541 46 avio_rb24(pb); // flags
6542
6543 46 track_id = avio_rb32(pb); // Reference ID
6544
1/2
✓ Branch 0 taken 46 times.
✗ Branch 1 not taken.
46 for (i = 0; i < c->fc->nb_streams; i++) {
6545 46 sc = c->fc->streams[i]->priv_data;
6546
1/2
✓ Branch 0 taken 46 times.
✗ Branch 1 not taken.
46 if (sc->id == track_id) {
6547 46 st = c->fc->streams[i];
6548 46 break;
6549 }
6550 }
6551
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 46 times.
46 if (!st) {
6552 av_log(c->fc, AV_LOG_WARNING, "could not find corresponding track id %d\n", track_id);
6553 return 0;
6554 }
6555
6556 46 sc = st->priv_data;
6557
6558 46 timescale = av_make_q(1, avio_rb32(pb));
6559
6560
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 46 times.
46 if (timescale.den <= 0) {
6561 av_log(c->fc, AV_LOG_ERROR, "Invalid sidx timescale 1/%d\n", timescale.den);
6562 return AVERROR_INVALIDDATA;
6563 }
6564
6565
2/2
✓ Branch 0 taken 45 times.
✓ Branch 1 taken 1 times.
46 if (version == 0) {
6566 45 pts = avio_rb32(pb);
6567 45 offadd= avio_rb32(pb);
6568 } else {
6569 1 pts = avio_rb64(pb);
6570 1 offadd= avio_rb64(pb);
6571 }
6572
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 46 times.
46 if (av_sat_add64(offset, offadd) != offset + (uint64_t)offadd)
6573 return AVERROR_INVALIDDATA;
6574
6575 46 offset += (uint64_t)offadd;
6576
6577 46 avio_rb16(pb); // reserved
6578
6579 46 item_count = avio_rb16(pb);
6580
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 46 times.
46 if (item_count == 0)
6581 return AVERROR_INVALIDDATA;
6582
6583
2/2
✓ Branch 0 taken 372 times.
✓ Branch 1 taken 46 times.
418 for (i = 0; i < item_count; i++) {
6584 int index;
6585 MOVFragmentStreamInfo * frag_stream_info;
6586 372 uint32_t size = avio_rb32(pb);
6587 372 uint32_t duration = avio_rb32(pb);
6588
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 372 times.
372 if (size & 0x80000000) {
6589 avpriv_request_sample(c->fc, "sidx reference_type 1");
6590 return AVERROR_PATCHWELCOME;
6591 }
6592 372 avio_rb32(pb); // sap_flags
6593 372 timestamp = av_rescale_q(pts, timescale, st->time_base);
6594
6595 372 index = update_frag_index(c, offset);
6596 372 frag_stream_info = get_frag_stream_info(&c->frag_index, index, track_id);
6597
1/2
✓ Branch 0 taken 372 times.
✗ Branch 1 not taken.
372 if (frag_stream_info)
6598 372 frag_stream_info->sidx_pts = timestamp;
6599
6600
1/2
✓ Branch 1 taken 372 times.
✗ Branch 2 not taken.
372 if (av_sat_add64(offset, size) != offset + (uint64_t)size ||
6601
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 372 times.
372 av_sat_add64(pts, duration) != pts + (uint64_t)duration
6602 )
6603 return AVERROR_INVALIDDATA;
6604 372 offset += size;
6605 372 pts += duration;
6606 }
6607
6608 46 st->duration = sc->track_end = pts;
6609
6610 46 sc->has_sidx = 1;
6611
6612 // See if the remaining bytes are just an mfra which we can ignore.
6613 46 is_complete = offset == stream_size;
6614
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 ) {
6615 int64_t ret;
6616 38 int64_t original_pos = avio_tell(pb);
6617
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 35 times.
38 if (!c->have_read_mfra_size) {
6618
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
3 if ((ret = avio_seek(pb, stream_size - 4, SEEK_SET)) < 0)
6619 return ret;
6620 3 c->mfra_size = avio_rb32(pb);
6621 3 c->have_read_mfra_size = 1;
6622
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
3 if ((ret = avio_seek(pb, original_pos, SEEK_SET)) < 0)
6623 return ret;
6624 }
6625
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 38 times.
38 if (offset == stream_size - c->mfra_size)
6626 is_complete = 1;
6627 }
6628
6629
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 39 times.
46 if (is_complete) {
6630 // Find first entry in fragment index that came from an sidx.
6631 // This will pretty much always be the first entry.
6632
2/2
✓ Branch 0 taken 371 times.
✓ Branch 1 taken 7 times.
378 for (i = 0; i < c->frag_index.nb_items; i++) {
6633 371 MOVFragmentIndexItem * item = &c->frag_index.item[i];
6634
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++) {
6635 MOVFragmentStreamInfo * si;
6636 7 si = &item->stream_info[j];
6637
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 if (si->sidx_pts != AV_NOPTS_VALUE) {
6638 7 ref_st = c->fc->streams[j];
6639 7 ref_sc = ref_st->priv_data;
6640 7 break;
6641 }
6642 }
6643 }
6644
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++) {
6645 7 st = c->fc->streams[i];
6646 7 sc = st->priv_data;
6647
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (!sc->has_sidx) {
6648 st->duration = sc->track_end = av_rescale(ref_st->duration, sc->time_scale, ref_sc->time_scale);
6649 }
6650 }
6651
6652
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 if (offadd == 0)
6653 7 c->frag_index.complete = 1;
6654 }
6655
6656 46 return 0;
6657 }
6658
6659 /* this atom should be null (from specs), but some buggy files put the 'moov' atom inside it... */
6660 /* like the files created with Adobe Premiere 5.0, for samples see */
6661 /* http://graphics.tudelft.nl/~wouter/publications/soundtests/ */
6662 279 static int mov_read_wide(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6663 {
6664 int err;
6665
6666
1/2
✓ Branch 0 taken 279 times.
✗ Branch 1 not taken.
279 if (atom.size < 8)
6667 279 return 0; /* continue */
6668 if (avio_rb32(pb) != 0) { /* 0 sized mdat atom... use the 'wide' atom size */
6669 avio_skip(pb, atom.size - 4);
6670 return 0;
6671 }
6672 atom.type = avio_rl32(pb);
6673 atom.size -= 8;
6674 if (atom.type != MKTAG('m','d','a','t')) {
6675 avio_skip(pb, atom.size);
6676 return 0;
6677 }
6678 err = mov_read_mdat(c, pb, atom);
6679 return err;
6680 }
6681
6682 3 static int mov_read_cmov(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6683 {
6684 #if CONFIG_ZLIB
6685 FFIOContext ctx;
6686 uint8_t *cmov_data;
6687 uint8_t *moov_data; /* uncompressed data */
6688 long cmov_len, moov_len;
6689 3 int ret = -1;
6690
6691 3 avio_rb32(pb); /* dcom atom */
6692
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
3 if (avio_rl32(pb) != MKTAG('d','c','o','m'))
6693 return AVERROR_INVALIDDATA;
6694
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
3 if (avio_rl32(pb) != MKTAG('z','l','i','b')) {
6695 av_log(c->fc, AV_LOG_ERROR, "unknown compression for cmov atom !\n");
6696 return AVERROR_INVALIDDATA;
6697 }
6698 3 avio_rb32(pb); /* cmvd atom */
6699
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
3 if (avio_rl32(pb) != MKTAG('c','m','v','d'))
6700 return AVERROR_INVALIDDATA;
6701 3 moov_len = avio_rb32(pb); /* uncompressed size */
6702 3 cmov_len = atom.size - 6 * 4;
6703
6704 3 cmov_data = av_malloc(cmov_len);
6705
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!cmov_data)
6706 return AVERROR(ENOMEM);
6707 3 moov_data = av_malloc(moov_len);
6708
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!moov_data) {
6709 av_free(cmov_data);
6710 return AVERROR(ENOMEM);
6711 }
6712 3 ret = ffio_read_size(pb, cmov_data, cmov_len);
6713
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (ret < 0)
6714 goto free_and_return;
6715
6716 3 ret = AVERROR_INVALIDDATA;
6717
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)
6718 goto free_and_return;
6719 3 ffio_init_read_context(&ctx, moov_data, moov_len);
6720 3 ctx.pub.seekable = AVIO_SEEKABLE_NORMAL;
6721 3 atom.type = MKTAG('m','o','o','v');
6722 3 atom.size = moov_len;
6723 3 ret = mov_read_default(c, &ctx.pub, atom);
6724 3 free_and_return:
6725 3 av_free(moov_data);
6726 3 av_free(cmov_data);
6727 3 return ret;
6728 #else
6729 av_log(c->fc, AV_LOG_ERROR, "this file requires zlib support compiled in\n");
6730 return AVERROR(ENOSYS);
6731 #endif
6732 }
6733
6734 /* edit list atom */
6735 496 static int mov_read_elst(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6736 {
6737 MOVStreamContext *sc;
6738 int i, edit_count, version;
6739 int64_t elst_entry_size;
6740
6741
2/4
✓ Branch 0 taken 496 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 496 times.
496 if (c->fc->nb_streams < 1 || c->ignore_editlist)
6742 return 0;
6743 496 sc = c->fc->streams[c->fc->nb_streams-1]->priv_data;
6744
6745 496 version = avio_r8(pb); /* version */
6746 496 avio_rb24(pb); /* flags */
6747 496 edit_count = avio_rb32(pb); /* entries */
6748 496 atom.size -= 8;
6749
6750
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 496 times.
496 elst_entry_size = version == 1 ? 20 : 12;
6751
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 495 times.
496 if (atom.size != edit_count * elst_entry_size) {
6752
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (c->fc->strict_std_compliance >= FF_COMPLIANCE_STRICT) {
6753 av_log(c->fc, AV_LOG_ERROR, "Invalid edit list entry_count: %d for elst atom of size: %"PRId64" bytes.\n",
6754 edit_count, atom.size + 8);
6755 return AVERROR_INVALIDDATA;
6756 } else {
6757 1 edit_count = atom.size / elst_entry_size;
6758
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (edit_count * elst_entry_size != atom.size) {
6759 av_log(c->fc, AV_LOG_WARNING, "ELST atom of %"PRId64" bytes, bigger than %d entries.\n", atom.size, edit_count);
6760 }
6761 }
6762 }
6763
6764
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 496 times.
496 if (!edit_count)
6765 return 0;
6766
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 496 times.
496 if (sc->elst_data)
6767 av_log(c->fc, AV_LOG_WARNING, "Duplicated ELST atom\n");
6768 496 av_free(sc->elst_data);
6769 496 sc->elst_count = 0;
6770 496 sc->elst_data = av_malloc_array(edit_count, sizeof(*sc->elst_data));
6771
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 496 times.
496 if (!sc->elst_data)
6772 return AVERROR(ENOMEM);
6773
6774 496 av_log(c->fc, AV_LOG_TRACE, "track[%u].edit_count = %i\n", c->fc->nb_streams - 1, edit_count);
6775
4/6
✓ Branch 0 taken 525 times.
✓ Branch 1 taken 496 times.
✓ Branch 2 taken 525 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 525 times.
✗ Branch 5 not taken.
1021 for (i = 0; i < edit_count && atom.size > 0 && !pb->eof_reached; i++) {
6776 525 MOVElst *e = &sc->elst_data[i];
6777
6778
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 525 times.
525 if (version == 1) {
6779 e->duration = avio_rb64(pb);
6780 e->time = avio_rb64(pb);
6781 atom.size -= 16;
6782 } else {
6783 525 e->duration = avio_rb32(pb); /* segment duration */
6784 525 e->time = (int32_t)avio_rb32(pb); /* media time */
6785 525 atom.size -= 8;
6786 }
6787 525 e->rate = avio_rb32(pb) / 65536.0;
6788 525 atom.size -= 4;
6789 525 av_log(c->fc, AV_LOG_TRACE, "duration=%"PRId64" time=%"PRId64" rate=%f\n",
6790 525 e->duration, e->time, e->rate);
6791
6792
3/4
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 521 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
525 if (e->time < 0 && e->time != -1 &&
6793 c->fc->strict_std_compliance >= FF_COMPLIANCE_STRICT) {
6794 av_log(c->fc, AV_LOG_ERROR, "Track %d, edit %d: Invalid edit list media time=%"PRId64"\n",
6795 c->fc->nb_streams-1, i, e->time);
6796 return AVERROR_INVALIDDATA;
6797 }
6798
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 525 times.
525 if (e->duration < 0) {
6799 av_log(c->fc, AV_LOG_ERROR, "Track %d, edit %d: Invalid edit list duration=%"PRId64"\n",
6800 c->fc->nb_streams-1, i, e->duration);
6801 return AVERROR_INVALIDDATA;
6802 }
6803 }
6804 496 sc->elst_count = i;
6805
6806 496 return 0;
6807 }
6808
6809 18 static int mov_read_tmcd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6810 {
6811 MOVStreamContext *sc;
6812 int err;
6813
6814
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (c->fc->nb_streams < 1)
6815 return AVERROR_INVALIDDATA;
6816 18 sc = c->fc->streams[c->fc->nb_streams - 1]->priv_data;
6817
6818
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (atom.size % sizeof(uint32_t))
6819 return AVERROR_INVALIDDATA;
6820
6821 18 MovTref *tag = mov_add_tref_tag(sc, atom.type);
6822
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (!tag)
6823 return AVERROR(ENOMEM);
6824
6825 18 int nb_timecode_track = atom.size >> 2;
6826
2/2
✓ Branch 0 taken 22 times.
✓ Branch 1 taken 18 times.
40 for (int i = 0; i < nb_timecode_track; i++) {
6827
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 22 times.
22 if (avio_feof(pb))
6828 return AVERROR_INVALIDDATA;
6829 22 err = mov_add_tref_id(tag, avio_rb32(pb));
6830
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 22 times.
22 if (err < 0)
6831 return err;
6832 }
6833
6834 18 return 0;
6835 }
6836
6837 static int mov_read_vpcc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6838 {
6839 AVStream *st;
6840 int version, color_range, color_primaries, color_trc, color_space;
6841
6842 if (c->fc->nb_streams < 1)
6843 return 0;
6844 st = c->fc->streams[c->fc->nb_streams - 1];
6845
6846 if (atom.size < 5) {
6847 av_log(c->fc, AV_LOG_ERROR, "Empty VP Codec Configuration box\n");
6848 return AVERROR_INVALIDDATA;
6849 }
6850
6851 version = avio_r8(pb);
6852 if (version != 1) {
6853 av_log(c->fc, AV_LOG_WARNING, "Unsupported VP Codec Configuration box version %d\n", version);
6854 return 0;
6855 }
6856 avio_skip(pb, 3); /* flags */
6857
6858 avio_skip(pb, 2); /* profile + level */
6859 color_range = avio_r8(pb); /* bitDepth, chromaSubsampling, videoFullRangeFlag */
6860 color_primaries = avio_r8(pb);
6861 color_trc = avio_r8(pb);
6862 color_space = avio_r8(pb);
6863 if (avio_rb16(pb)) /* codecIntializationDataSize */
6864 return AVERROR_INVALIDDATA;
6865
6866 if (!av_color_primaries_name(color_primaries))
6867 color_primaries = AVCOL_PRI_UNSPECIFIED;
6868 if (!av_color_transfer_name(color_trc))
6869 color_trc = AVCOL_TRC_UNSPECIFIED;
6870 if (!av_color_space_name(color_space))
6871 color_space = AVCOL_SPC_UNSPECIFIED;
6872
6873 st->codecpar->color_range = (color_range & 1) ? AVCOL_RANGE_JPEG : AVCOL_RANGE_MPEG;
6874 st->codecpar->color_primaries = color_primaries;
6875 st->codecpar->color_trc = color_trc;
6876 st->codecpar->color_space = color_space;
6877
6878 return 0;
6879 }
6880
6881 static int mov_read_smdm(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6882 {
6883 MOVStreamContext *sc;
6884 int i, version;
6885
6886 if (c->fc->nb_streams < 1)
6887 return AVERROR_INVALIDDATA;
6888
6889 sc = c->fc->streams[c->fc->nb_streams - 1]->priv_data;
6890
6891 if (atom.size < 5) {
6892 av_log(c->fc, AV_LOG_ERROR, "Empty Mastering Display Metadata box\n");
6893 return AVERROR_INVALIDDATA;
6894 }
6895
6896 version = avio_r8(pb);
6897 if (version) {
6898 av_log(c->fc, AV_LOG_WARNING, "Unsupported Mastering Display Metadata box version %d\n", version);
6899 return 0;
6900 }
6901 if (sc->mastering) {
6902 av_log(c->fc, AV_LOG_WARNING, "Ignoring duplicate Mastering Display Metadata\n");
6903 return 0;
6904 }
6905
6906 avio_skip(pb, 3); /* flags */
6907
6908 sc->mastering = av_mastering_display_metadata_alloc_size(&sc->mastering_size);
6909 if (!sc->mastering)
6910 return AVERROR(ENOMEM);
6911
6912 for (i = 0; i < 3; i++) {
6913 sc->mastering->display_primaries[i][0] = av_make_q(avio_rb16(pb), 1 << 16);
6914 sc->mastering->display_primaries[i][1] = av_make_q(avio_rb16(pb), 1 << 16);
6915 }
6916 sc->mastering->white_point[0] = av_make_q(avio_rb16(pb), 1 << 16);
6917 sc->mastering->white_point[1] = av_make_q(avio_rb16(pb), 1 << 16);
6918
6919 sc->mastering->max_luminance = av_make_q(avio_rb32(pb), 1 << 8);
6920 sc->mastering->min_luminance = av_make_q(avio_rb32(pb), 1 << 14);
6921
6922 sc->mastering->has_primaries = 1;
6923 sc->mastering->has_luminance = 1;
6924
6925 return 0;
6926 }
6927
6928 static int mov_read_mdcv(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6929 {
6930 MOVStreamContext *sc;
6931 const int mapping[3] = {1, 2, 0};
6932 const int chroma_den = 50000;
6933 const int luma_den = 10000;
6934 int i;
6935
6936 if (c->fc->nb_streams < 1)
6937 return AVERROR_INVALIDDATA;
6938
6939 sc = c->fc->streams[c->fc->nb_streams - 1]->priv_data;
6940
6941 if (atom.size < 24) {
6942 av_log(c->fc, AV_LOG_ERROR, "Invalid Mastering Display Color Volume box\n");
6943 return AVERROR_INVALIDDATA;
6944 }
6945
6946 if (sc->mastering) {
6947 av_log(c->fc, AV_LOG_WARNING, "Ignoring duplicate Mastering Display Color Volume\n");
6948 return 0;
6949 }
6950
6951 sc->mastering = av_mastering_display_metadata_alloc_size(&sc->mastering_size);
6952 if (!sc->mastering)
6953 return AVERROR(ENOMEM);
6954
6955 for (i = 0; i < 3; i++) {
6956 const int j = mapping[i];
6957 sc->mastering->display_primaries[j][0] = av_make_q(avio_rb16(pb), chroma_den);
6958 sc->mastering->display_primaries[j][1] = av_make_q(avio_rb16(pb), chroma_den);
6959 }
6960 sc->mastering->white_point[0] = av_make_q(avio_rb16(pb), chroma_den);
6961 sc->mastering->white_point[1] = av_make_q(avio_rb16(pb), chroma_den);
6962
6963 sc->mastering->max_luminance = av_make_q(avio_rb32(pb), luma_den);
6964 sc->mastering->min_luminance = av_make_q(avio_rb32(pb), luma_den);
6965
6966 sc->mastering->has_luminance = 1;
6967 sc->mastering->has_primaries = 1;
6968
6969 return 0;
6970 }
6971
6972 static int mov_read_coll(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6973 {
6974 MOVStreamContext *sc;
6975 int version;
6976
6977 if (c->fc->nb_streams < 1)
6978 return AVERROR_INVALIDDATA;
6979
6980 sc = c->fc->streams[c->fc->nb_streams - 1]->priv_data;
6981
6982 if (atom.size < 5) {
6983 av_log(c->fc, AV_LOG_ERROR, "Empty Content Light Level box\n");
6984 return AVERROR_INVALIDDATA;
6985 }
6986
6987 version = avio_r8(pb);
6988 if (version) {
6989 av_log(c->fc, AV_LOG_WARNING, "Unsupported Content Light Level box version %d\n", version);
6990 return 0;
6991 }
6992 avio_skip(pb, 3); /* flags */
6993
6994 if (sc->coll){
6995 av_log(c->fc, AV_LOG_WARNING, "Ignoring duplicate COLL\n");
6996 return 0;
6997 }
6998
6999 sc->coll = av_content_light_metadata_alloc(&sc->coll_size);
7000 if (!sc->coll)
7001 return AVERROR(ENOMEM);
7002
7003 sc->coll->MaxCLL = avio_rb16(pb);
7004 sc->coll->MaxFALL = avio_rb16(pb);
7005
7006 return 0;
7007 }
7008
7009 static int mov_read_clli(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7010 {
7011 MOVStreamContext *sc;
7012
7013 if (c->fc->nb_streams < 1)
7014 return AVERROR_INVALIDDATA;
7015
7016 sc = c->fc->streams[c->fc->nb_streams - 1]->priv_data;
7017
7018 if (atom.size < 4) {
7019 av_log(c->fc, AV_LOG_ERROR, "Empty Content Light Level Info box\n");
7020 return AVERROR_INVALIDDATA;
7021 }
7022
7023 if (sc->coll){
7024 av_log(c->fc, AV_LOG_WARNING, "Ignoring duplicate CLLI/COLL\n");
7025 return 0;
7026 }
7027
7028 sc->coll = av_content_light_metadata_alloc(&sc->coll_size);
7029 if (!sc->coll)
7030 return AVERROR(ENOMEM);
7031
7032 sc->coll->MaxCLL = avio_rb16(pb);
7033 sc->coll->MaxFALL = avio_rb16(pb);
7034
7035 return 0;
7036 }
7037
7038 4 static int mov_read_amve(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7039 {
7040 MOVStreamContext *sc;
7041 4 const int illuminance_den = 10000;
7042 4 const int ambient_den = 50000;
7043
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (c->fc->nb_streams < 1)
7044 return AVERROR_INVALIDDATA;
7045 4 sc = c->fc->streams[c->fc->nb_streams - 1]->priv_data;
7046
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (atom.size < 6) {
7047 av_log(c->fc, AV_LOG_ERROR, "Empty Ambient Viewing Environment Info box\n");
7048 return AVERROR_INVALIDDATA;
7049 }
7050
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (sc->ambient){
7051 av_log(c->fc, AV_LOG_WARNING, "Ignoring duplicate AMVE\n");
7052 return 0;
7053 }
7054 4 sc->ambient = av_ambient_viewing_environment_alloc(&sc->ambient_size);
7055
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!sc->ambient)
7056 return AVERROR(ENOMEM);
7057 4 sc->ambient->ambient_illuminance = av_make_q(avio_rb32(pb), illuminance_den);
7058 4 sc->ambient->ambient_light_x = av_make_q(avio_rb16(pb), ambient_den);
7059 4 sc->ambient->ambient_light_y = av_make_q(avio_rb16(pb), ambient_den);
7060 4 return 0;
7061 }
7062
7063 1 static int mov_read_st3d(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7064 {
7065 AVStream *st;
7066 MOVStreamContext *sc;
7067 enum AVStereo3DType type;
7068 int mode;
7069
7070
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (c->fc->nb_streams < 1)
7071 return 0;
7072
7073 1 st = c->fc->streams[c->fc->nb_streams - 1];
7074 1 sc = st->priv_data;
7075
7076
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (atom.size < 5) {
7077 av_log(c->fc, AV_LOG_ERROR, "Empty stereoscopic video box\n");
7078 return AVERROR_INVALIDDATA;
7079 }
7080
7081
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (sc->stereo3d)
7082 return AVERROR_INVALIDDATA;
7083
7084 1 avio_skip(pb, 4); /* version + flags */
7085
7086 1 mode = avio_r8(pb);
7087
1/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
1 switch (mode) {
7088 1 case 0:
7089 1 type = AV_STEREO3D_2D;
7090 1 break;
7091 case 1:
7092 type = AV_STEREO3D_TOPBOTTOM;
7093 break;
7094 case 2:
7095 type = AV_STEREO3D_SIDEBYSIDE;
7096 break;
7097 default:
7098 av_log(c->fc, AV_LOG_WARNING, "Unknown st3d mode value %d\n", mode);
7099 return 0;
7100 }
7101
7102 1 sc->stereo3d = av_stereo3d_alloc_size(&sc->stereo3d_size);
7103
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!sc->stereo3d)
7104 return AVERROR(ENOMEM);
7105
7106 1 sc->stereo3d->type = type;
7107 1 return 0;
7108 }
7109
7110 static int mov_read_pack(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7111 {
7112 AVStream *st;
7113 MOVStreamContext *sc;
7114 int size = 0;
7115 int64_t remaining;
7116 uint32_t tag = 0;
7117 enum AVStereo3DType type = AV_STEREO3D_2D;
7118
7119 if (c->fc->nb_streams < 1)
7120 return 0;
7121
7122 st = c->fc->streams[c->fc->nb_streams - 1];
7123 sc = st->priv_data;
7124
7125 remaining = atom.size;
7126 while (remaining > 0) {
7127 size = avio_rb32(pb);
7128 if (size < 8 || size > remaining ) {
7129 av_log(c->fc, AV_LOG_ERROR, "Invalid child size in pack box\n");
7130 return AVERROR_INVALIDDATA;
7131 }
7132
7133 tag = avio_rl32(pb);
7134 switch (tag) {
7135 case MKTAG('p','k','i','n'): {
7136 if (size != 16) {
7137 av_log(c->fc, AV_LOG_ERROR, "Invalid size of pkin box: %d\n", size);
7138 return AVERROR_INVALIDDATA;
7139 }
7140 avio_skip(pb, 1); // version
7141 avio_skip(pb, 3); // flags
7142
7143 tag = avio_rl32(pb);
7144 switch (tag) {
7145 case MKTAG('s','i','d','e'):
7146 type = AV_STEREO3D_SIDEBYSIDE;
7147 break;
7148 case MKTAG('o','v','e','r'):
7149 type = AV_STEREO3D_TOPBOTTOM;
7150 break;
7151 case 0:
7152 // This means value will be set in another layer
7153 break;
7154 default:
7155 av_log(c->fc, AV_LOG_WARNING, "Unknown tag in pkin: %s\n",
7156 av_fourcc2str(tag));
7157 avio_skip(pb, size - 8);
7158 break;
7159 }
7160
7161 break;
7162 }
7163 default:
7164 av_log(c->fc, AV_LOG_WARNING, "Unknown tag in pack: %s\n",
7165 av_fourcc2str(tag));
7166 avio_skip(pb, size - 8);
7167 break;
7168 }
7169 remaining -= size;
7170 }
7171
7172 if (remaining != 0) {
7173 av_log(c->fc, AV_LOG_ERROR, "Broken pack box\n");
7174 return AVERROR_INVALIDDATA;
7175 }
7176
7177 if (type == AV_STEREO3D_2D)
7178 return 0;
7179
7180 if (!sc->stereo3d) {
7181 sc->stereo3d = av_stereo3d_alloc_size(&sc->stereo3d_size);
7182 if (!sc->stereo3d)
7183 return AVERROR(ENOMEM);
7184 }
7185
7186 sc->stereo3d->type = type;
7187
7188 return 0;
7189 }
7190
7191 1 static int mov_read_sv3d(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7192 {
7193 AVStream *st;
7194 MOVStreamContext *sc;
7195 int size, version, layout;
7196 int32_t yaw, pitch, roll;
7197 1 uint32_t l = 0, t = 0, r = 0, b = 0;
7198 1 uint32_t tag, padding = 0;
7199 enum AVSphericalProjection projection;
7200
7201
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (c->fc->nb_streams < 1)
7202 return 0;
7203
7204 1 st = c->fc->streams[c->fc->nb_streams - 1];
7205 1 sc = st->priv_data;
7206
7207
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (atom.size < 8) {
7208 av_log(c->fc, AV_LOG_ERROR, "Empty spherical video box\n");
7209 return AVERROR_INVALIDDATA;
7210 }
7211
7212 1 size = avio_rb32(pb);
7213
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)
7214 return AVERROR_INVALIDDATA;
7215
7216 1 tag = avio_rl32(pb);
7217
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (tag != MKTAG('s','v','h','d')) {
7218 av_log(c->fc, AV_LOG_ERROR, "Missing spherical video header\n");
7219 return 0;
7220 }
7221 1 version = avio_r8(pb);
7222
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (version != 0) {
7223 av_log(c->fc, AV_LOG_WARNING, "Unknown spherical version %d\n",
7224 version);
7225 return 0;
7226 }
7227 1 avio_skip(pb, 3); /* flags */
7228 1 avio_skip(pb, size - 12); /* metadata_source */
7229
7230 1 size = avio_rb32(pb);
7231
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (size > atom.size)
7232 return AVERROR_INVALIDDATA;
7233
7234 1 tag = avio_rl32(pb);
7235
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (tag != MKTAG('p','r','o','j')) {
7236 av_log(c->fc, AV_LOG_ERROR, "Missing projection box\n");
7237 return 0;
7238 }
7239
7240 1 size = avio_rb32(pb);
7241
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (size > atom.size)
7242 return AVERROR_INVALIDDATA;
7243
7244 1 tag = avio_rl32(pb);
7245
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (tag != MKTAG('p','r','h','d')) {
7246 av_log(c->fc, AV_LOG_ERROR, "Missing projection header box\n");
7247 return 0;
7248 }
7249 1 version = avio_r8(pb);
7250
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (version != 0) {
7251 av_log(c->fc, AV_LOG_WARNING, "Unknown spherical version %d\n",
7252 version);
7253 return 0;
7254 }
7255 1 avio_skip(pb, 3); /* flags */
7256
7257 /* 16.16 fixed point */
7258 1 yaw = avio_rb32(pb);
7259 1 pitch = avio_rb32(pb);
7260 1 roll = avio_rb32(pb);
7261
7262 1 size = avio_rb32(pb);
7263
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (size > atom.size)
7264 return AVERROR_INVALIDDATA;
7265
7266 1 tag = avio_rl32(pb);
7267 1 version = avio_r8(pb);
7268
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (version != 0) {
7269 av_log(c->fc, AV_LOG_WARNING, "Unknown spherical version %d\n",
7270 version);
7271 return 0;
7272 }
7273 1 avio_skip(pb, 3); /* flags */
7274
1/3
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 switch (tag) {
7275 case MKTAG('c','b','m','p'):
7276 layout = avio_rb32(pb);
7277 if (layout) {
7278 av_log(c->fc, AV_LOG_WARNING,
7279 "Unsupported cubemap layout %d\n", layout);
7280 return 0;
7281 }
7282 projection = AV_SPHERICAL_CUBEMAP;
7283 padding = avio_rb32(pb);
7284 break;
7285 1 case MKTAG('e','q','u','i'):
7286 1 t = avio_rb32(pb);
7287 1 b = avio_rb32(pb);
7288 1 l = avio_rb32(pb);
7289 1 r = avio_rb32(pb);
7290
7291
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) {
7292 av_log(c->fc, AV_LOG_ERROR,
7293 "Invalid bounding rectangle coordinates "
7294 "%"PRIu32",%"PRIu32",%"PRIu32",%"PRIu32"\n", l, t, r, b);
7295 return AVERROR_INVALIDDATA;
7296 }
7297
7298
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)
7299 1 projection = AV_SPHERICAL_EQUIRECTANGULAR_TILE;
7300 else
7301 projection = AV_SPHERICAL_EQUIRECTANGULAR;
7302 1 break;
7303 default:
7304 av_log(c->fc, AV_LOG_ERROR, "Unknown projection type: %s\n", av_fourcc2str(tag));
7305 return 0;
7306 }
7307
7308 1 sc->spherical = av_spherical_alloc(&sc->spherical_size);
7309
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!sc->spherical)
7310 return AVERROR(ENOMEM);
7311
7312 1 sc->spherical->projection = projection;
7313
7314 1 sc->spherical->yaw = yaw;
7315 1 sc->spherical->pitch = pitch;
7316 1 sc->spherical->roll = roll;
7317
7318 1 sc->spherical->padding = padding;
7319
7320 1 sc->spherical->bound_left = l;
7321 1 sc->spherical->bound_top = t;
7322 1 sc->spherical->bound_right = r;
7323 1 sc->spherical->bound_bottom = b;
7324
7325 1 return 0;
7326 }
7327
7328 3 static int mov_read_vexu_proj(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7329 {
7330 AVStream *st;
7331 MOVStreamContext *sc;
7332 int size;
7333 uint32_t tag;
7334 enum AVSphericalProjection projection;
7335
7336
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (c->fc->nb_streams < 1)
7337 return 0;
7338
7339 3 st = c->fc->streams[c->fc->nb_streams - 1];
7340 3 sc = st->priv_data;
7341
7342
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (atom.size < 16) {
7343 av_log(c->fc, AV_LOG_ERROR, "Invalid size for proj box: %"PRIu64"\n", atom.size);
7344 return AVERROR_INVALIDDATA;
7345 }
7346
7347 3 size = avio_rb32(pb);
7348
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (size < 16) {
7349 av_log(c->fc, AV_LOG_ERROR, "Invalid size for prji box: %d\n", size);
7350 return AVERROR_INVALIDDATA;
7351
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 } else if (size > 16) {
7352 av_log(c->fc, AV_LOG_WARNING, "Box has more bytes (%d) than prji box required (16) \n", size);
7353 }
7354
7355 3 tag = avio_rl32(pb);
7356
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (tag != MKTAG('p','r','j','i')) {
7357 av_log(c->fc, AV_LOG_ERROR, "Invalid child box of proj box: %s\n",
7358 av_fourcc2str(tag));
7359 return AVERROR_INVALIDDATA;
7360 }
7361
7362 // version and flags, only support (0, 0)
7363 3 unsigned n = avio_rl32(pb);
7364
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (n != 0) {
7365 av_log(c->fc, AV_LOG_ERROR, "prji version %u, flag %u are not supported\n",
7366 n & 0xFF, n >> 8);
7367 return AVERROR_PATCHWELCOME;
7368 }
7369
7370 3 tag = avio_rl32(pb);
7371
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) {
7372 3 case MKTAG('r','e','c','t'):
7373 3 projection = AV_SPHERICAL_RECTILINEAR;
7374 3 break;
7375 case MKTAG('e','q','u','i'):
7376 projection = AV_SPHERICAL_EQUIRECTANGULAR;
7377 break;
7378 case MKTAG('h','e','q','u'):
7379 projection = AV_SPHERICAL_HALF_EQUIRECTANGULAR;
7380 break;
7381 case MKTAG('f','i','s','h'):
7382 projection = AV_SPHERICAL_FISHEYE;
7383 break;
7384 case MKTAG('p','r','i','m'):
7385 projection = AV_SPHERICAL_PARAMETRIC_IMMERSIVE;
7386 break;
7387 default:
7388 av_log(c->fc, AV_LOG_ERROR, "Invalid projection type in prji box: %s\n", av_fourcc2str(tag));
7389 return AVERROR_INVALIDDATA;
7390 }
7391
7392 3 sc->spherical = av_spherical_alloc(&sc->spherical_size);
7393
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!sc->spherical)
7394 return AVERROR(ENOMEM);
7395
7396 3 sc->spherical->projection = projection;
7397
7398 3 return 0;
7399 }
7400
7401 3 static int mov_read_eyes(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7402 {
7403 AVStream *st;
7404 MOVStreamContext *sc;
7405 3 int size, flags = 0;
7406 int64_t remaining;
7407 3 uint32_t tag, baseline = 0;
7408 3 enum AVStereo3DView view = AV_STEREO3D_VIEW_UNSPEC;
7409 3 enum AVStereo3DType type = AV_STEREO3D_2D;
7410 3 enum AVStereo3DPrimaryEye primary_eye = AV_PRIMARY_EYE_NONE;
7411 3 AVRational horizontal_disparity_adjustment = { 0, 1 };
7412
7413
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (c->fc->nb_streams < 1)
7414 return 0;
7415
7416 3 st = c->fc->streams[c->fc->nb_streams - 1];
7417 3 sc = st->priv_data;
7418
7419 3 remaining = atom.size;
7420
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 3 times.
12 while (remaining > 0) {
7421 9 size = avio_rb32(pb);
7422
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 ) {
7423 av_log(c->fc, AV_LOG_ERROR, "Invalid child size in eyes box\n");
7424 return AVERROR_INVALIDDATA;
7425 }
7426
7427 9 tag = avio_rl32(pb);
7428
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) {
7429 3 case MKTAG('s','t','r','i'): {
7430 int has_right, has_left;
7431 uint8_t tmp;
7432
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (size != 13) {
7433 av_log(c->fc, AV_LOG_ERROR, "Invalid size of stri box: %d\n", size);
7434 return AVERROR_INVALIDDATA;
7435 }
7436 3 avio_skip(pb, 1); // version
7437 3 avio_skip(pb, 3); // flags
7438
7439 3 tmp = avio_r8(pb);
7440
7441 // eye_views_reversed
7442
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (tmp & 8) {
7443 flags |= AV_STEREO3D_FLAG_INVERT;
7444 }
7445 // has_additional_views
7446 3 if (tmp & 4) {
7447 // skip...
7448 }
7449
7450 3 has_right = tmp & 2; // has_right_eye_view
7451 3 has_left = tmp & 1; // has_left_eye_view
7452
7453
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)
7454 3 view = AV_STEREO3D_VIEW_PACKED;
7455 else if (has_left)
7456 view = AV_STEREO3D_VIEW_LEFT;
7457 else if (has_right)
7458 view = AV_STEREO3D_VIEW_RIGHT;
7459
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)
7460 3 type = AV_STEREO3D_UNSPEC;
7461
7462 3 break;
7463 }
7464 case MKTAG('h','e','r','o'): {
7465 int tmp;
7466 if (size != 13) {
7467 av_log(c->fc, AV_LOG_ERROR, "Invalid size of hero box: %d\n", size);
7468 return AVERROR_INVALIDDATA;
7469 }
7470 avio_skip(pb, 1); // version
7471 avio_skip(pb, 3); // flags
7472
7473 tmp = avio_r8(pb);
7474 if (tmp == 0)
7475 primary_eye = AV_PRIMARY_EYE_NONE;
7476 else if (tmp == 1)
7477 primary_eye = AV_PRIMARY_EYE_LEFT;
7478 else if (tmp == 2)
7479 primary_eye = AV_PRIMARY_EYE_RIGHT;
7480 else
7481 av_log(c->fc, AV_LOG_WARNING, "Unknown hero eye type: %d\n", tmp);
7482
7483 break;
7484 }
7485 3 case MKTAG('c','a','m','s'): {
7486 uint32_t subtag;
7487 int subsize;
7488
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (size != 24) {
7489 av_log(c->fc, AV_LOG_ERROR, "Invalid size of cams box: %d\n", size);
7490 return AVERROR_INVALIDDATA;
7491 }
7492
7493 3 subsize = avio_rb32(pb);
7494
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (subsize != 16) {
7495 av_log(c->fc, AV_LOG_ERROR, "Invalid size of blin box: %d\n", size);
7496 return AVERROR_INVALIDDATA;
7497 }
7498
7499 3 subtag = avio_rl32(pb);
7500
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (subtag != MKTAG('b','l','i','n')) {
7501 av_log(c->fc, AV_LOG_ERROR, "Expected blin box, got %s\n",
7502 av_fourcc2str(subtag));
7503 return AVERROR_INVALIDDATA;
7504 }
7505
7506 3 avio_skip(pb, 1); // version
7507 3 avio_skip(pb, 3); // flags
7508
7509 3 baseline = avio_rb32(pb);
7510
7511 3 break;
7512 }
7513 3 case MKTAG('c','m','f','y'): {
7514 uint32_t subtag;
7515 int subsize;
7516 int32_t adjustment;
7517
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (size != 24) {
7518 av_log(c->fc, AV_LOG_ERROR, "Invalid size of cmfy box: %d\n", size);
7519 return AVERROR_INVALIDDATA;
7520 }
7521
7522 3 subsize = avio_rb32(pb);
7523
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (subsize != 16) {
7524 av_log(c->fc, AV_LOG_ERROR, "Invalid size of dadj box: %d\n", size);
7525 return AVERROR_INVALIDDATA;
7526 }
7527
7528 3 subtag = avio_rl32(pb);
7529
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (subtag != MKTAG('d','a','d','j')) {
7530 av_log(c->fc, AV_LOG_ERROR, "Expected dadj box, got %s\n",
7531 av_fourcc2str(subtag));
7532 return AVERROR_INVALIDDATA;
7533 }
7534
7535 3 avio_skip(pb, 1); // version
7536 3 avio_skip(pb, 3); // flags
7537
7538 3 adjustment = (int32_t) avio_rb32(pb);
7539
7540 3 horizontal_disparity_adjustment.num = (int) adjustment;
7541 3 horizontal_disparity_adjustment.den = 10000;
7542
7543 3 break;
7544 }
7545 default:
7546 av_log(c->fc, AV_LOG_WARNING, "Unknown tag in eyes: %s\n",
7547 av_fourcc2str(tag));
7548 avio_skip(pb, size - 8);
7549 break;
7550 }
7551 9 remaining -= size;
7552 }
7553
7554
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (remaining != 0) {
7555 av_log(c->fc, AV_LOG_ERROR, "Broken eyes box\n");
7556 return AVERROR_INVALIDDATA;
7557 }
7558
7559
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (type == AV_STEREO3D_2D)
7560 return 0;
7561
7562
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if (!sc->stereo3d) {
7563 3 sc->stereo3d = av_stereo3d_alloc_size(&sc->stereo3d_size);
7564
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!sc->stereo3d)
7565 return AVERROR(ENOMEM);
7566 }
7567
7568 3 sc->stereo3d->flags = flags;
7569 3 sc->stereo3d->type = type;
7570 3 sc->stereo3d->view = view;
7571 3 sc->stereo3d->primary_eye = primary_eye;
7572 3 sc->stereo3d->baseline = baseline;
7573 3 sc->stereo3d->horizontal_disparity_adjustment = horizontal_disparity_adjustment;
7574
7575 3 return 0;
7576 }
7577
7578 3 static int mov_read_vexu(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7579 {
7580 int size;
7581 int64_t remaining;
7582 uint32_t tag;
7583
7584
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (c->fc->nb_streams < 1)
7585 return 0;
7586
7587
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (atom.size < 8) {
7588 av_log(c->fc, AV_LOG_ERROR, "Empty video extension usage box\n");
7589 return AVERROR_INVALIDDATA;
7590 }
7591
7592 3 remaining = atom.size;
7593
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 3 times.
9 while (remaining > 0) {
7594 6 size = avio_rb32(pb);
7595
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 ) {
7596 av_log(c->fc, AV_LOG_ERROR, "Invalid child size in vexu box\n");
7597 return AVERROR_INVALIDDATA;
7598 }
7599
7600 6 tag = avio_rl32(pb);
7601
2/4
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
6 switch (tag) {
7602 3 case MKTAG('p','r','o','j'): {
7603 3 MOVAtom proj = { tag, size - 8 };
7604 3 int ret = mov_read_vexu_proj(c, pb, proj);
7605
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (ret < 0)
7606 return ret;
7607 3 break;
7608 }
7609 3 case MKTAG('e','y','e','s'): {
7610 3 MOVAtom eyes = { tag, size - 8 };
7611 3 int ret = mov_read_eyes(c, pb, eyes);
7612
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (ret < 0)
7613 return ret;
7614 3 break;
7615 }
7616 case MKTAG('p','a','c','k'): {
7617 MOVAtom pack = { tag, size - 8 };
7618 int ret = mov_read_pack(c, pb, pack);
7619 if (ret < 0)
7620 return ret;
7621 break;
7622 }
7623 default:
7624 av_log(c->fc, AV_LOG_WARNING, "Unknown tag in vexu: %s\n",
7625 av_fourcc2str(tag));
7626 avio_skip(pb, size - 8);
7627 break;
7628 }
7629 6 remaining -= size;
7630 }
7631
7632
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (remaining != 0) {
7633 av_log(c->fc, AV_LOG_ERROR, "Broken vexu box\n");
7634 return AVERROR_INVALIDDATA;
7635 }
7636
7637 3 return 0;
7638 }
7639
7640 3 static int mov_read_hfov(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7641 {
7642 AVStream *st;
7643 MOVStreamContext *sc;
7644
7645
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (c->fc->nb_streams < 1)
7646 return 0;
7647
7648 3 st = c->fc->streams[c->fc->nb_streams - 1];
7649 3 sc = st->priv_data;
7650
7651
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (atom.size != 4) {
7652 av_log(c->fc, AV_LOG_ERROR, "Invalid size of hfov box: %"PRIu64"\n", atom.size);
7653 return AVERROR_INVALIDDATA;
7654 }
7655
7656
7657
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!sc->stereo3d) {
7658 sc->stereo3d = av_stereo3d_alloc_size(&sc->stereo3d_size);
7659 if (!sc->stereo3d)
7660 return AVERROR(ENOMEM);
7661 }
7662
7663 3 sc->stereo3d->horizontal_field_of_view.num = avio_rb32(pb);
7664 3 sc->stereo3d->horizontal_field_of_view.den = 1000; // thousands of a degree
7665
7666 3 return 0;
7667 }
7668
7669 static int mov_parse_uuid_spherical(MOVStreamContext *sc, AVIOContext *pb, size_t len)
7670 {
7671 int ret = 0;
7672 uint8_t *buffer = av_malloc(len + 1);
7673 const char *val;
7674
7675 if (!buffer)
7676 return AVERROR(ENOMEM);
7677 buffer[len] = '\0';
7678
7679 ret = ffio_read_size(pb, buffer, len);
7680 if (ret < 0)
7681 goto out;
7682
7683 /* Check for mandatory keys and values, try to support XML as best-effort */
7684 if (!sc->spherical &&
7685 av_stristr(buffer, "<GSpherical:StitchingSoftware>") &&
7686 (val = av_stristr(buffer, "<GSpherical:Spherical>")) &&
7687 av_stristr(val, "true") &&
7688 (val = av_stristr(buffer, "<GSpherical:Stitched>")) &&
7689 av_stristr(val, "true") &&
7690 (val = av_stristr(buffer, "<GSpherical:ProjectionType>")) &&
7691 av_stristr(val, "equirectangular")) {
7692 sc->spherical = av_spherical_alloc(&sc->spherical_size);
7693 if (!sc->spherical)
7694 goto out;
7695
7696 sc->spherical->projection = AV_SPHERICAL_EQUIRECTANGULAR;
7697
7698 if (av_stristr(buffer, "<GSpherical:StereoMode>") && !sc->stereo3d) {
7699 enum AVStereo3DType mode;
7700
7701 if (av_stristr(buffer, "left-right"))
7702 mode = AV_STEREO3D_SIDEBYSIDE;
7703 else if (av_stristr(buffer, "top-bottom"))
7704 mode = AV_STEREO3D_TOPBOTTOM;
7705 else
7706 mode = AV_STEREO3D_2D;
7707
7708 sc->stereo3d = av_stereo3d_alloc_size(&sc->stereo3d_size);
7709 if (!sc->stereo3d)
7710 goto out;
7711
7712 sc->stereo3d->type = mode;
7713 }
7714
7715 /* orientation */
7716 val = av_stristr(buffer, "<GSpherical:InitialViewHeadingDegrees>");
7717 if (val)
7718 sc->spherical->yaw = strtol(val, NULL, 10) * (1 << 16);
7719 val = av_stristr(buffer, "<GSpherical:InitialViewPitchDegrees>");
7720 if (val)
7721 sc->spherical->pitch = strtol(val, NULL, 10) * (1 << 16);
7722 val = av_stristr(buffer, "<GSpherical:InitialViewRollDegrees>");
7723 if (val)
7724 sc->spherical->roll = strtol(val, NULL, 10) * (1 << 16);
7725 }
7726
7727 out:
7728 av_free(buffer);
7729 return ret;
7730 }
7731
7732 69 static int mov_read_uuid(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7733 {
7734 AVStream *st;
7735 MOVStreamContext *sc;
7736 int64_t ret;
7737 AVUUID uuid;
7738 static const AVUUID uuid_isml_manifest = {
7739 0xa5, 0xd4, 0x0b, 0x30, 0xe8, 0x14, 0x11, 0xdd,
7740 0xba, 0x2f, 0x08, 0x00, 0x20, 0x0c, 0x9a, 0x66
7741 };
7742 static const AVUUID uuid_xmp = {
7743 0xbe, 0x7a, 0xcf, 0xcb, 0x97, 0xa9, 0x42, 0xe8,
7744 0x9c, 0x71, 0x99, 0x94, 0x91, 0xe3, 0xaf, 0xac
7745 };
7746 static const AVUUID uuid_spherical = {
7747 0xff, 0xcc, 0x82, 0x63, 0xf8, 0x55, 0x4a, 0x93,
7748 0x88, 0x14, 0x58, 0x7a, 0x02, 0x52, 0x1f, 0xdd,
7749 };
7750
7751
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))
7752 return AVERROR_INVALIDDATA;
7753
7754
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 66 times.
69 if (c->fc->nb_streams < 1)
7755 3 return 0;
7756 66 st = c->fc->streams[c->fc->nb_streams - 1];
7757 66 sc = st->priv_data;
7758
7759 66 ret = ffio_read_size(pb, uuid, AV_UUID_LEN);
7760
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 66 times.
66 if (ret < 0)
7761 return ret;
7762
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 66 times.
66 if (av_uuid_equal(uuid, uuid_isml_manifest)) {
7763 uint8_t *buffer, *ptr;
7764 char *endptr;
7765 size_t len = atom.size - AV_UUID_LEN;
7766
7767 if (len < 4) {
7768 return AVERROR_INVALIDDATA;
7769 }
7770 ret = avio_skip(pb, 4); // zeroes
7771 len -= 4;
7772
7773 buffer = av_mallocz(len + 1);
7774 if (!buffer) {
7775 return AVERROR(ENOMEM);
7776 }
7777 ret = ffio_read_size(pb, buffer, len);
7778 if (ret < 0) {
7779 av_free(buffer);
7780 return ret;
7781 }
7782
7783 ptr = buffer;
7784 while ((ptr = av_stristr(ptr, "systemBitrate=\""))) {
7785 ptr += sizeof("systemBitrate=\"") - 1;
7786 c->bitrates_count++;
7787 c->bitrates = av_realloc_f(c->bitrates, c->bitrates_count, sizeof(*c->bitrates));
7788 if (!c->bitrates) {
7789 c->bitrates_count = 0;
7790 av_free(buffer);
7791 return AVERROR(ENOMEM);
7792 }
7793 errno = 0;
7794 ret = strtol(ptr, &endptr, 10);
7795 if (ret < 0 || errno || *endptr != '"') {
7796 c->bitrates[c->bitrates_count - 1] = 0;
7797 } else {
7798 c->bitrates[c->bitrates_count - 1] = ret;
7799 }
7800 }
7801
7802 av_free(buffer);
7803
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 66 times.
66 } else if (av_uuid_equal(uuid, uuid_xmp)) {
7804 uint8_t *buffer;
7805 size_t len = atom.size - AV_UUID_LEN;
7806 if (c->export_xmp) {
7807 buffer = av_mallocz(len + 1);
7808 if (!buffer) {
7809 return AVERROR(ENOMEM);
7810 }
7811 ret = ffio_read_size(pb, buffer, len);
7812 if (ret < 0) {
7813 av_free(buffer);
7814 return ret;
7815 }
7816 buffer[len] = '\0';
7817 av_dict_set(&c->fc->metadata, "xmp",
7818 buffer, AV_DICT_DONT_STRDUP_VAL);
7819 } else {
7820 // skip all uuid atom, which makes it fast for long uuid-xmp file
7821 ret = avio_skip(pb, len);
7822 if (ret < 0)
7823 return ret;
7824 }
7825
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 66 times.
66 } else if (av_uuid_equal(uuid, uuid_spherical)) {
7826 size_t len = atom.size - AV_UUID_LEN;
7827 ret = mov_parse_uuid_spherical(sc, pb, len);
7828 if (ret < 0)
7829 return ret;
7830 if (!sc->spherical)
7831 av_log(c->fc, AV_LOG_WARNING, "Invalid spherical metadata found\n");
7832 }
7833
7834 66 return 0;
7835 }
7836
7837 233 static int mov_read_free(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7838 {
7839 int ret;
7840 uint8_t content[16];
7841
7842
2/2
✓ Branch 0 taken 126 times.
✓ Branch 1 taken 107 times.
233 if (atom.size < 8)
7843 126 return 0;
7844
7845 107 ret = ffio_read_size(pb, content, FFMIN(sizeof(content), atom.size));
7846
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 107 times.
107 if (ret < 0)
7847 return ret;
7848
7849
2/2
✓ Branch 0 taken 45 times.
✓ Branch 1 taken 62 times.
107 if ( !c->found_moov
7850
2/2
✓ Branch 0 taken 22 times.
✓ Branch 1 taken 23 times.
45 && !c->found_mdat
7851
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 22 times.
22 && !memcmp(content, "Anevia\x1A\x1A", 8)
7852 && c->use_mfra_for == FF_MOV_FLAG_MFRA_AUTO) {
7853 c->use_mfra_for = FF_MOV_FLAG_MFRA_PTS;
7854 }
7855
7856 107 return 0;
7857 }
7858
7859 37 static int mov_read_frma(MOVContext *c, AVIOContext *pb, MOVAtom atom)
7860 {
7861 37 uint32_t format = avio_rl32(pb);
7862 MOVStreamContext *sc;
7863 enum AVCodecID id;
7864 AVStream *st;
7865
7866
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 37 times.
37 if (c->fc->nb_streams < 1)
7867 return 0;
7868 37 st = c->fc->streams[c->fc->nb_streams - 1];
7869 37 sc = st->priv_data;
7870
7871
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 31 times.
37 switch (sc->format)
7872 {
7873 6 case MKTAG('e','n','c','v'): // encrypted video
7874 case MKTAG('e','n','c','a'): // encrypted audio
7875 6 id = mov_codec_id(st, format);
7876
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (st->codecpar->codec_id != AV_CODEC_ID_NONE &&
7877 st->codecpar->codec_id != id) {
7878 av_log(c->fc, AV_LOG_WARNING,
7879 "ignoring 'frma' atom of '%.4s', stream has codec id %d\n",
7880 (char*)&format, st->codecpar->codec_id);
7881 break;
7882 }
7883
7884 6 st->codecpar->codec_id = id;
7885 6 sc->format = format;
7886 6 break;
7887
7888 31 default:
7889
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 31 times.
31 if (format != sc->format) {
7890 av_log(c->fc, AV_LOG_WARNING,
7891 "ignoring 'frma' atom of '%.4s', stream format is '%.4s'\n",
7892 (char*)&format, (char*)&sc->format);
7893 }
7894 31 break;
7895 }
7896
7897 37 return 0;
7898 }
7899
7900 /**
7901 * Gets the current encryption info and associated current stream context. If
7902 * we are parsing a track fragment, this will return the specific encryption
7903 * info for this fragment; otherwise this will return the global encryption
7904 * info for the current stream.
7905 */
7906 12 static int get_current_encryption_info(MOVContext *c, MOVEncryptionIndex **encryption_index, MOVStreamContext **sc)
7907 {
7908 MOVFragmentStreamInfo *frag_stream_info;
7909 AVStream *st;
7910 int i;
7911
7912 12 frag_stream_info = get_current_frag_stream_info(&c->frag_index);
7913
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 6 times.
12 if (frag_stream_info) {
7914
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 for (i = 0; i < c->fc->nb_streams; i++) {
7915 6 *sc = c->fc->streams[i]->priv_data;
7916
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 if ((*sc)->id == frag_stream_info->id) {
7917 6 st = c->fc->streams[i];
7918 6 break;
7919 }
7920 }
7921
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (i == c->fc->nb_streams)
7922 return 0;
7923 6 *sc = st->priv_data;
7924
7925
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 4 times.
6 if (!frag_stream_info->encryption_index) {
7926 // If this stream isn't encrypted, don't create the index.
7927
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!(*sc)->cenc.default_encrypted_sample)
7928 return 0;
7929 2 frag_stream_info->encryption_index = av_mallocz(sizeof(*frag_stream_info->encryption_index));
7930
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!frag_stream_info->encryption_index)
7931 return AVERROR(ENOMEM);
7932 }
7933 6 *encryption_index = frag_stream_info->encryption_index;
7934 6 return 1;
7935 } else {
7936 // No current track fragment, using stream level encryption info.
7937
7938
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (c->fc->nb_streams < 1)
7939 return 0;
7940 6 st = c->fc->streams[c->fc->nb_streams - 1];
7941 6 *sc = st->priv_data;
7942
7943
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (!(*sc)->cenc.encryption_index) {
7944 // If this stream isn't encrypted, don't create the index.
7945 if (!(*sc)->cenc.default_encrypted_sample)
7946 return 0;
7947 (*sc)->cenc.encryption_index = av_mallocz(sizeof(*frag_stream_info->encryption_index));
7948 if (!(*sc)->cenc.encryption_index)
7949 return AVERROR(ENOMEM);
7950 }
7951
7952 6 *encryption_index = (*sc)->cenc.encryption_index;
7953 6 return 1;
7954 }
7955 }
7956
7957 144 static int mov_read_sample_encryption_info(MOVContext *c, AVIOContext *pb, MOVStreamContext *sc, AVEncryptionInfo **sample, int use_subsamples)
7958 {
7959 int i, ret;
7960 unsigned int subsample_count;
7961 AVSubsampleEncryptionInfo *subsamples;
7962
7963
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 144 times.
144 if (!sc->cenc.default_encrypted_sample) {
7964 av_log(c->fc, AV_LOG_ERROR, "Missing schm or tenc\n");
7965 return AVERROR_INVALIDDATA;
7966 }
7967
7968
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) {
7969 144 *sample = av_encryption_info_clone(sc->cenc.default_encrypted_sample);
7970
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 144 times.
144 if (!*sample)
7971 return AVERROR(ENOMEM);
7972 } else
7973 *sample = NULL;
7974
7975
1/2
✓ Branch 0 taken 144 times.
✗ Branch 1 not taken.
144 if (sc->cenc.per_sample_iv_size != 0) {
7976
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) {
7977 av_log(c->fc, AV_LOG_ERROR, "failed to read the initialization vector\n");
7978 av_encryption_info_free(*sample);
7979 *sample = NULL;
7980 return ret;
7981 }
7982 }
7983
7984
1/2
✓ Branch 0 taken 144 times.
✗ Branch 1 not taken.
144 if (use_subsamples) {
7985 144 subsample_count = avio_rb16(pb);
7986 144 av_free((*sample)->subsamples);
7987 144 (*sample)->subsamples = av_calloc(subsample_count, sizeof(*subsamples));
7988
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 144 times.
144 if (!(*sample)->subsamples) {
7989 av_encryption_info_free(*sample);
7990 *sample = NULL;
7991 return AVERROR(ENOMEM);
7992 }
7993
7994
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++) {
7995 144 (*sample)->subsamples[i].bytes_of_clear_data = avio_rb16(pb);
7996 144 (*sample)->subsamples[i].bytes_of_protected_data = avio_rb32(pb);
7997 }
7998
7999
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 144 times.
144 if (pb->eof_reached) {
8000 av_log(c->fc, AV_LOG_ERROR, "hit EOF while reading sub-sample encryption info\n");
8001 av_encryption_info_free(*sample);
8002 *sample = NULL;
8003 return AVERROR_INVALIDDATA;
8004 }
8005 144 (*sample)->subsample_count = subsample_count;
8006 }
8007
8008 144 return 0;
8009 }
8010
8011 4 static int mov_read_senc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8012 {
8013 AVEncryptionInfo **encrypted_samples;
8014 MOVEncryptionIndex *encryption_index;
8015 MOVStreamContext *sc;
8016 int use_subsamples, ret;
8017 4 unsigned int sample_count, i, alloc_size = 0;
8018
8019 4 ret = get_current_encryption_info(c, &encryption_index, &sc);
8020
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (ret != 1)
8021 return ret;
8022
8023
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 if (encryption_index->nb_encrypted_samples) {
8024 // This can happen if we have both saio/saiz and senc atoms.
8025 2 av_log(c->fc, AV_LOG_DEBUG, "Ignoring duplicate encryption info in senc\n");
8026 2 return 0;
8027 }
8028
8029 2 avio_r8(pb); /* version */
8030 2 use_subsamples = avio_rb24(pb) & 0x02; /* flags */
8031
8032 2 sample_count = avio_rb32(pb);
8033
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (sample_count >= INT_MAX / sizeof(*encrypted_samples))
8034 return AVERROR(ENOMEM);
8035
8036
2/2
✓ Branch 0 taken 96 times.
✓ Branch 1 taken 2 times.
98 for (i = 0; i < sample_count; i++) {
8037 96 unsigned int min_samples = FFMIN(FFMAX(i + 1, 1024 * 1024), sample_count);
8038 96 encrypted_samples = av_fast_realloc(encryption_index->encrypted_samples, &alloc_size,
8039 min_samples * sizeof(*encrypted_samples));
8040
1/2
✓ Branch 0 taken 96 times.
✗ Branch 1 not taken.
96 if (encrypted_samples) {
8041 96 encryption_index->encrypted_samples = encrypted_samples;
8042
8043 96 ret = mov_read_sample_encryption_info(
8044 96 c, pb, sc, &encryption_index->encrypted_samples[i], use_subsamples);
8045 } else {
8046 ret = AVERROR(ENOMEM);
8047 }
8048
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 96 times.
96 if (pb->eof_reached) {
8049 av_log(c->fc, AV_LOG_ERROR, "Hit EOF while reading senc\n");
8050 if (ret >= 0)
8051 av_encryption_info_free(encryption_index->encrypted_samples[i]);
8052 ret = AVERROR_INVALIDDATA;
8053 }
8054
8055
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 96 times.
96 if (ret < 0) {
8056 for (; i > 0; i--)
8057 av_encryption_info_free(encryption_index->encrypted_samples[i - 1]);
8058 av_freep(&encryption_index->encrypted_samples);
8059 return ret;
8060 }
8061 }
8062 2 encryption_index->nb_encrypted_samples = sample_count;
8063
8064 2 return 0;
8065 }
8066
8067 2 static int mov_parse_auxiliary_info(MOVContext *c, MOVStreamContext *sc, AVIOContext *pb, MOVEncryptionIndex *encryption_index)
8068 {
8069 AVEncryptionInfo **sample, **encrypted_samples;
8070 int64_t prev_pos;
8071 size_t sample_count, sample_info_size, i;
8072 2 int ret = 0;
8073 2 unsigned int alloc_size = 0;
8074
8075
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (encryption_index->nb_encrypted_samples)
8076 return 0;
8077 2 sample_count = encryption_index->auxiliary_info_sample_count;
8078
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (encryption_index->auxiliary_offsets_count != 1) {
8079 av_log(c->fc, AV_LOG_ERROR, "Multiple auxiliary info chunks are not supported\n");
8080 return AVERROR_PATCHWELCOME;
8081 }
8082
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (sample_count >= INT_MAX / sizeof(*encrypted_samples))
8083 return AVERROR(ENOMEM);
8084
8085 2 prev_pos = avio_tell(pb);
8086
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (!(pb->seekable & AVIO_SEEKABLE_NORMAL) ||
8087
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]) {
8088 av_log(c->fc, AV_LOG_INFO, "Failed to seek for auxiliary info, will only parse senc atoms for encryption info\n");
8089 goto finish;
8090 }
8091
8092
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++) {
8093 48 unsigned int min_samples = FFMIN(FFMAX(i + 1, 1024 * 1024), sample_count);
8094 48 encrypted_samples = av_fast_realloc(encryption_index->encrypted_samples, &alloc_size,
8095 min_samples * sizeof(*encrypted_samples));
8096
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 48 times.
48 if (!encrypted_samples) {
8097 ret = AVERROR(ENOMEM);
8098 goto finish;
8099 }
8100 48 encryption_index->encrypted_samples = encrypted_samples;
8101
8102 48 sample = &encryption_index->encrypted_samples[i];
8103 96 sample_info_size = encryption_index->auxiliary_info_default_size
8104 48 ? encryption_index->auxiliary_info_default_size
8105
1/2
✓ Branch 0 taken 48 times.
✗ Branch 1 not taken.
48 : encryption_index->auxiliary_info_sizes[i];
8106
8107 48 ret = mov_read_sample_encryption_info(c, pb, sc, sample, sample_info_size > sc->cenc.per_sample_iv_size);
8108
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 48 times.
48 if (ret < 0)
8109 goto finish;
8110 }
8111
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (pb->eof_reached) {
8112 av_log(c->fc, AV_LOG_ERROR, "Hit EOF while reading auxiliary info\n");
8113 ret = AVERROR_INVALIDDATA;
8114 } else {
8115 2 encryption_index->nb_encrypted_samples = sample_count;
8116 }
8117
8118 2 finish:
8119 2 avio_seek(pb, prev_pos, SEEK_SET);
8120
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (ret < 0) {
8121 for (; i > 0; i--) {
8122 av_encryption_info_free(encryption_index->encrypted_samples[i - 1]);
8123 }
8124 av_freep(&encryption_index->encrypted_samples);
8125 }
8126 2 return ret;
8127 }
8128
8129 4 static int mov_read_saiz(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8130 {
8131 MOVEncryptionIndex *encryption_index;
8132 MOVStreamContext *sc;
8133 int ret;
8134 unsigned int sample_count, aux_info_type, aux_info_param;
8135
8136 4 ret = get_current_encryption_info(c, &encryption_index, &sc);
8137
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (ret != 1)
8138 return ret;
8139
8140
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 if (encryption_index->nb_encrypted_samples) {
8141 // This can happen if we have both saio/saiz and senc atoms.
8142 2 av_log(c->fc, AV_LOG_DEBUG, "Ignoring duplicate encryption info in saiz\n");
8143 2 return 0;
8144 }
8145
8146
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (encryption_index->auxiliary_info_sample_count) {
8147 av_log(c->fc, AV_LOG_ERROR, "Duplicate saiz atom\n");
8148 return AVERROR_INVALIDDATA;
8149 }
8150
8151 2 avio_r8(pb); /* version */
8152
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if (avio_rb24(pb) & 0x01) { /* flags */
8153 aux_info_type = avio_rb32(pb);
8154 aux_info_param = avio_rb32(pb);
8155 if (sc->cenc.default_encrypted_sample) {
8156 if (aux_info_type != sc->cenc.default_encrypted_sample->scheme) {
8157 av_log(c->fc, AV_LOG_DEBUG, "Ignoring saiz box with non-zero aux_info_type\n");
8158 return 0;
8159 }
8160 if (aux_info_param != 0) {
8161 av_log(c->fc, AV_LOG_DEBUG, "Ignoring saiz box with non-zero aux_info_type_parameter\n");
8162 return 0;
8163 }
8164 } else {
8165 // Didn't see 'schm' or 'tenc', so this isn't encrypted.
8166 if ((aux_info_type == MKBETAG('c','e','n','c') ||
8167 aux_info_type == MKBETAG('c','e','n','s') ||
8168 aux_info_type == MKBETAG('c','b','c','1') ||
8169 aux_info_type == MKBETAG('c','b','c','s')) &&
8170 aux_info_param == 0) {
8171 av_log(c->fc, AV_LOG_ERROR, "Saw encrypted saiz without schm/tenc\n");
8172 return AVERROR_INVALIDDATA;
8173 } else {
8174 return 0;
8175 }
8176 }
8177
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 } else if (!sc->cenc.default_encrypted_sample) {
8178 // Didn't see 'schm' or 'tenc', so this isn't encrypted.
8179 return 0;
8180 }
8181
8182 2 encryption_index->auxiliary_info_default_size = avio_r8(pb);
8183 2 sample_count = avio_rb32(pb);
8184
8185
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (encryption_index->auxiliary_info_default_size == 0) {
8186 if (sample_count == 0)
8187 return AVERROR_INVALIDDATA;
8188
8189 encryption_index->auxiliary_info_sizes = av_malloc(sample_count);
8190 if (!encryption_index->auxiliary_info_sizes)
8191 return AVERROR(ENOMEM);
8192
8193 ret = avio_read(pb, encryption_index->auxiliary_info_sizes, sample_count);
8194 if (ret != sample_count) {
8195 av_freep(&encryption_index->auxiliary_info_sizes);
8196
8197 if (ret >= 0)
8198 ret = AVERROR_INVALIDDATA;
8199 av_log(c->fc, AV_LOG_ERROR, "Failed to read the auxiliary info, %s\n",
8200 av_err2str(ret));
8201 return ret;
8202 }
8203 }
8204 2 encryption_index->auxiliary_info_sample_count = sample_count;
8205
8206
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (encryption_index->auxiliary_offsets_count) {
8207 return mov_parse_auxiliary_info(c, sc, pb, encryption_index);
8208 }
8209
8210 2 return 0;
8211 }
8212
8213 4 static int mov_read_saio(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8214 {
8215 uint64_t *auxiliary_offsets;
8216 MOVEncryptionIndex *encryption_index;
8217 MOVStreamContext *sc;
8218 int i, ret;
8219 unsigned int version, entry_count, aux_info_type, aux_info_param;
8220 4 unsigned int alloc_size = 0;
8221
8222 4 ret = get_current_encryption_info(c, &encryption_index, &sc);
8223
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (ret != 1)
8224 return ret;
8225
8226
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 if (encryption_index->nb_encrypted_samples) {
8227 // This can happen if we have both saio/saiz and senc atoms.
8228 2 av_log(c->fc, AV_LOG_DEBUG, "Ignoring duplicate encryption info in saio\n");
8229 2 return 0;
8230 }
8231
8232
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (encryption_index->auxiliary_offsets_count) {
8233 av_log(c->fc, AV_LOG_ERROR, "Duplicate saio atom\n");
8234 return AVERROR_INVALIDDATA;
8235 }
8236
8237 2 version = avio_r8(pb); /* version */
8238
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if (avio_rb24(pb) & 0x01) { /* flags */
8239 aux_info_type = avio_rb32(pb);
8240 aux_info_param = avio_rb32(pb);
8241 if (sc->cenc.default_encrypted_sample) {
8242 if (aux_info_type != sc->cenc.default_encrypted_sample->scheme) {
8243 av_log(c->fc, AV_LOG_DEBUG, "Ignoring saio box with non-zero aux_info_type\n");
8244 return 0;
8245 }
8246 if (aux_info_param != 0) {
8247 av_log(c->fc, AV_LOG_DEBUG, "Ignoring saio box with non-zero aux_info_type_parameter\n");
8248 return 0;
8249 }
8250 } else {
8251 // Didn't see 'schm' or 'tenc', so this isn't encrypted.
8252 if ((aux_info_type == MKBETAG('c','e','n','c') ||
8253 aux_info_type == MKBETAG('c','e','n','s') ||
8254 aux_info_type == MKBETAG('c','b','c','1') ||
8255 aux_info_type == MKBETAG('c','b','c','s')) &&
8256 aux_info_param == 0) {
8257 av_log(c->fc, AV_LOG_ERROR, "Saw encrypted saio without schm/tenc\n");
8258 return AVERROR_INVALIDDATA;
8259 } else {
8260 return 0;
8261 }
8262 }
8263
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 } else if (!sc->cenc.default_encrypted_sample) {
8264 // Didn't see 'schm' or 'tenc', so this isn't encrypted.
8265 return 0;
8266 }
8267
8268 2 entry_count = avio_rb32(pb);
8269
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (entry_count >= INT_MAX / sizeof(*auxiliary_offsets))
8270 return AVERROR(ENOMEM);
8271
8272
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++) {
8273
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);
8274 2 auxiliary_offsets = av_fast_realloc(
8275 2 encryption_index->auxiliary_offsets, &alloc_size,
8276 min_offsets * sizeof(*auxiliary_offsets));
8277
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!auxiliary_offsets) {
8278 av_freep(&encryption_index->auxiliary_offsets);
8279 return AVERROR(ENOMEM);
8280 }
8281 2 encryption_index->auxiliary_offsets = auxiliary_offsets;
8282
8283
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (version == 0) {
8284 2 encryption_index->auxiliary_offsets[i] = avio_rb32(pb);
8285 } else {
8286 encryption_index->auxiliary_offsets[i] = avio_rb64(pb);
8287 }
8288
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (c->frag_index.current >= 0) {
8289 2 encryption_index->auxiliary_offsets[i] += c->fragment.base_data_offset;
8290 }
8291 }
8292
8293
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (pb->eof_reached) {
8294 av_log(c->fc, AV_LOG_ERROR, "Hit EOF while reading saio\n");
8295 av_freep(&encryption_index->auxiliary_offsets);
8296 return AVERROR_INVALIDDATA;
8297 }
8298
8299 2 encryption_index->auxiliary_offsets_count = entry_count;
8300
8301
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (encryption_index->auxiliary_info_sample_count) {
8302 2 return mov_parse_auxiliary_info(c, sc, pb, encryption_index);
8303 }
8304
8305 return 0;
8306 }
8307
8308 4 static int mov_read_pssh(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8309 {
8310 AVEncryptionInitInfo *info, *old_init_info;
8311 uint8_t **key_ids;
8312 AVStream *st;
8313 const AVPacketSideData *old_side_data;
8314 uint8_t *side_data, *extra_data;
8315 size_t side_data_size;
8316 4 int ret = 0;
8317 4 unsigned int version, kid_count, extra_data_size, alloc_size = 0;
8318
8319
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (c->fc->nb_streams < 1)
8320 return 0;
8321 4 st = c->fc->streams[c->fc->nb_streams-1];
8322
8323 4 version = avio_r8(pb); /* version */
8324 4 avio_rb24(pb); /* flags */
8325
8326 4 info = av_encryption_init_info_alloc(/* system_id_size */ 16, /* num_key_ids */ 0,
8327 /* key_id_size */ 16, /* data_size */ 0);
8328
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!info)
8329 return AVERROR(ENOMEM);
8330
8331
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
4 if ((ret = ffio_read_size(pb, info->system_id, 16)) < 0) {
8332 av_log(c->fc, AV_LOG_ERROR, "Failed to read the system id\n");
8333 goto finish;
8334 }
8335
8336
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if (version > 0) {
8337 4 kid_count = avio_rb32(pb);
8338
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (kid_count >= INT_MAX / sizeof(*key_ids)) {
8339 ret = AVERROR(ENOMEM);
8340 goto finish;
8341 }
8342
8343
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++) {
8344 4 unsigned int min_kid_count = FFMIN(FFMAX(i + 1, 1024), kid_count);
8345 4 key_ids = av_fast_realloc(info->key_ids, &alloc_size,
8346 min_kid_count * sizeof(*key_ids));
8347
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!key_ids) {
8348 ret = AVERROR(ENOMEM);
8349 goto finish;
8350 }
8351 4 info->key_ids = key_ids;
8352
8353 4 info->key_ids[i] = av_mallocz(16);
8354
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!info->key_ids[i]) {
8355 ret = AVERROR(ENOMEM);
8356 goto finish;
8357 }
8358 4 info->num_key_ids = i + 1;
8359
8360
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
4 if ((ret = ffio_read_size(pb, info->key_ids[i], 16)) < 0) {
8361 av_log(c->fc, AV_LOG_ERROR, "Failed to read the key id\n");
8362 goto finish;
8363 }
8364 }
8365
8366
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (pb->eof_reached) {
8367 av_log(c->fc, AV_LOG_ERROR, "Hit EOF while reading pssh\n");
8368 ret = AVERROR_INVALIDDATA;
8369 goto finish;
8370 }
8371 }
8372
8373 4 extra_data_size = avio_rb32(pb);
8374 4 extra_data = av_malloc(extra_data_size);
8375
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!extra_data) {
8376 ret = AVERROR(ENOMEM);
8377 goto finish;
8378 }
8379 4 ret = avio_read(pb, extra_data, extra_data_size);
8380
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (ret != extra_data_size) {
8381 av_free(extra_data);
8382
8383 if (ret >= 0)
8384 ret = AVERROR_INVALIDDATA;
8385 goto finish;
8386 }
8387
8388 4 av_freep(&info->data); // malloc(0) may still allocate something.
8389 4 info->data = extra_data;
8390 4 info->data_size = extra_data_size;
8391
8392 // If there is existing initialization data, append to the list.
8393 4 old_side_data = av_packet_side_data_get(st->codecpar->coded_side_data, st->codecpar->nb_coded_side_data,
8394 AV_PKT_DATA_ENCRYPTION_INIT_INFO);
8395
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (old_side_data) {
8396 old_init_info = av_encryption_init_info_get_side_data(old_side_data->data, old_side_data->size);
8397 if (old_init_info) {
8398 // Append to the end of the list.
8399 for (AVEncryptionInitInfo *cur = old_init_info;; cur = cur->next) {
8400 if (!cur->next) {
8401 cur->next = info;
8402 break;
8403 }
8404 }
8405 info = old_init_info;
8406 } else {
8407 // Assume existing side-data will be valid, so the only error we could get is OOM.
8408 ret = AVERROR(ENOMEM);
8409 goto finish;
8410 }
8411 }
8412
8413 4 side_data = av_encryption_init_info_add_side_data(info, &side_data_size);
8414
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!side_data) {
8415 ret = AVERROR(ENOMEM);
8416 goto finish;
8417 }
8418
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if (!av_packet_side_data_add(&st->codecpar->coded_side_data,
8419 4 &st->codecpar->nb_coded_side_data,
8420 AV_PKT_DATA_ENCRYPTION_INIT_INFO,
8421 side_data, side_data_size, 0))
8422 av_free(side_data);
8423
8424 4 finish:
8425 4 av_encryption_init_info_free(info);
8426 4 return ret;
8427 }
8428
8429 6 static int mov_read_schm(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8430 {
8431 AVStream *st;
8432 MOVStreamContext *sc;
8433
8434
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (c->fc->nb_streams < 1)
8435 return 0;
8436 6 st = c->fc->streams[c->fc->nb_streams-1];
8437 6 sc = st->priv_data;
8438
8439
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (sc->pseudo_stream_id != 0) {
8440 av_log(c->fc, AV_LOG_ERROR, "schm boxes are only supported in first sample descriptor\n");
8441 return AVERROR_PATCHWELCOME;
8442 }
8443
8444
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (atom.size < 8)
8445 return AVERROR_INVALIDDATA;
8446
8447 6 avio_rb32(pb); /* version and flags */
8448
8449
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 if (!sc->cenc.default_encrypted_sample) {
8450 6 sc->cenc.default_encrypted_sample = av_encryption_info_alloc(0, 16, 16);
8451
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (!sc->cenc.default_encrypted_sample) {
8452 return AVERROR(ENOMEM);
8453 }
8454 }
8455
8456 6 sc->cenc.default_encrypted_sample->scheme = avio_rb32(pb);
8457 6 return 0;
8458 }
8459
8460 6 static int mov_read_tenc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8461 {
8462 AVStream *st;
8463 MOVStreamContext *sc;
8464 unsigned int version, pattern, is_protected, iv_size;
8465
8466
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (c->fc->nb_streams < 1)
8467 return 0;
8468 6 st = c->fc->streams[c->fc->nb_streams-1];
8469 6 sc = st->priv_data;
8470
8471
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (sc->pseudo_stream_id != 0) {
8472 av_log(c->fc, AV_LOG_ERROR, "tenc atom are only supported in first sample descriptor\n");
8473 return AVERROR_PATCHWELCOME;
8474 }
8475
8476
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (!sc->cenc.default_encrypted_sample) {
8477 sc->cenc.default_encrypted_sample = av_encryption_info_alloc(0, 16, 16);
8478 if (!sc->cenc.default_encrypted_sample) {
8479 return AVERROR(ENOMEM);
8480 }
8481 }
8482
8483
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (atom.size < 20)
8484 return AVERROR_INVALIDDATA;
8485
8486 6 version = avio_r8(pb); /* version */
8487 6 avio_rb24(pb); /* flags */
8488
8489 6 avio_r8(pb); /* reserved */
8490 6 pattern = avio_r8(pb);
8491
8492
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (version > 0) {
8493 sc->cenc.default_encrypted_sample->crypt_byte_block = pattern >> 4;
8494 sc->cenc.default_encrypted_sample->skip_byte_block = pattern & 0xf;
8495 }
8496
8497 6 is_protected = avio_r8(pb);
8498
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) {
8499 // The whole stream should be by-default encrypted.
8500 6 sc->cenc.encryption_index = av_mallocz(sizeof(MOVEncryptionIndex));
8501
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (!sc->cenc.encryption_index)
8502 return AVERROR(ENOMEM);
8503 }
8504 6 sc->cenc.per_sample_iv_size = avio_r8(pb);
8505
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 &&
8506 sc->cenc.per_sample_iv_size != 16) {
8507 av_log(c->fc, AV_LOG_ERROR, "invalid per-sample IV size value\n");
8508 return AVERROR_INVALIDDATA;
8509 }
8510
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) {
8511 av_log(c->fc, AV_LOG_ERROR, "failed to read the default key ID\n");
8512 return AVERROR_INVALIDDATA;
8513 }
8514
8515
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) {
8516 2 iv_size = avio_r8(pb);
8517
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) {
8518 av_log(c->fc, AV_LOG_ERROR, "invalid default_constant_IV_size in tenc atom\n");
8519 return AVERROR_INVALIDDATA;
8520 }
8521
8522
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) {
8523 av_log(c->fc, AV_LOG_ERROR, "failed to read the default IV\n");
8524 return AVERROR_INVALIDDATA;
8525 }
8526 }
8527
8528 6 return 0;
8529 }
8530
8531 static int mov_read_dfla(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8532 {
8533 AVStream *st;
8534 int last, type, size, ret;
8535 uint8_t buf[4];
8536
8537 if (c->fc->nb_streams < 1)
8538 return 0;
8539 st = c->fc->streams[c->fc->nb_streams-1];
8540
8541 if ((uint64_t)atom.size > (1<<30) || atom.size < 42)
8542 return AVERROR_INVALIDDATA;
8543
8544 /* Check FlacSpecificBox version. */
8545 if (avio_r8(pb) != 0)
8546 return AVERROR_INVALIDDATA;
8547
8548 avio_rb24(pb); /* Flags */
8549
8550 if (avio_read(pb, buf, sizeof(buf)) != sizeof(buf)) {
8551 av_log(c->fc, AV_LOG_ERROR, "failed to read FLAC metadata block header\n");
8552 return pb->error < 0 ? pb->error : AVERROR_INVALIDDATA;
8553 }
8554 flac_parse_block_header(buf, &last, &type, &size);
8555
8556 if (type != FLAC_METADATA_TYPE_STREAMINFO || size != FLAC_STREAMINFO_SIZE) {
8557 av_log(c->fc, AV_LOG_ERROR, "STREAMINFO must be first FLACMetadataBlock\n");
8558 return AVERROR_INVALIDDATA;
8559 }
8560
8561 ret = ff_get_extradata(c->fc, st->codecpar, pb, size);
8562 if (ret < 0)
8563 return ret;
8564
8565 if (!last)
8566 av_log(c->fc, AV_LOG_WARNING, "non-STREAMINFO FLACMetadataBlock(s) ignored\n");
8567
8568 return 0;
8569 }
8570
8571 6 static int get_key_from_kid(uint8_t* out, int len, MOVContext *c, AVEncryptionInfo *sample) {
8572 AVDictionaryEntry *key_entry_hex;
8573 char kid_hex[16*2+1];
8574
8575
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) {
8576 av_log(c->fc, AV_LOG_ERROR, "invalid default decryption key length: got %d, expected %d\n", c->decryption_default_key_len, len);
8577 return -1;
8578 }
8579
8580
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3 times.
6 if (!c->decryption_keys) {
8581
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 av_assert0(c->decryption_default_key);
8582 3 memcpy(out, c->decryption_default_key, len);
8583 3 return 0;
8584 }
8585
8586
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (sample->key_id_size != 16) {
8587 av_log(c->fc, AV_LOG_ERROR, "invalid key ID size: got %u, expected 16\n", sample->key_id_size);
8588 return -1;
8589 }
8590
8591 3 ff_data_to_hex(kid_hex, sample->key_id, 16, 1);
8592 3 key_entry_hex = av_dict_get(c->decryption_keys, kid_hex, NULL, AV_DICT_DONT_STRDUP_KEY|AV_DICT_DONT_STRDUP_VAL);
8593
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!key_entry_hex) {
8594 if (!c->decryption_default_key) {
8595 av_log(c->fc, AV_LOG_ERROR, "unable to find KID %s\n", kid_hex);
8596 return -1;
8597 }
8598 memcpy(out, c->decryption_default_key, len);
8599 return 0;
8600 }
8601
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (strlen(key_entry_hex->value) != len*2) {
8602 return -1;
8603 }
8604 3 ff_hex_to_data(out, key_entry_hex->value);
8605 3 return 0;
8606 }
8607
8608 292 static int cenc_scheme_decrypt(MOVContext *c, MOVStreamContext *sc, AVEncryptionInfo *sample, uint8_t *input, int size)
8609 {
8610 int i, ret;
8611 int bytes_of_protected_data;
8612 uint8_t decryption_key[AES_CTR_KEY_SIZE];
8613
8614
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 286 times.
292 if (!sc->cenc.aes_ctr) {
8615 6 ret = get_key_from_kid(decryption_key, sizeof(decryption_key), c, sample);
8616
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (ret < 0) {
8617 return ret;
8618 }
8619
8620 /* initialize the cipher */
8621 6 sc->cenc.aes_ctr = av_aes_ctr_alloc();
8622
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (!sc->cenc.aes_ctr) {
8623 return AVERROR(ENOMEM);
8624 }
8625
8626 6 ret = av_aes_ctr_init(sc->cenc.aes_ctr, decryption_key);
8627
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (ret < 0) {
8628 return ret;
8629 }
8630 }
8631
8632 292 av_aes_ctr_set_full_iv(sc->cenc.aes_ctr, sample->iv);
8633
8634
2/2
✓ Branch 0 taken 96 times.
✓ Branch 1 taken 196 times.
292 if (!sample->subsample_count) {
8635 /* decrypt the whole packet */
8636 96 av_aes_ctr_crypt(sc->cenc.aes_ctr, input, input, size);
8637 96 return 0;
8638 }
8639
8640
2/2
✓ Branch 0 taken 196 times.
✓ Branch 1 taken 196 times.
392 for (i = 0; i < sample->subsample_count; i++) {
8641
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) {
8642 av_log(c->fc, AV_LOG_ERROR, "subsample size exceeds the packet size left\n");
8643 return AVERROR_INVALIDDATA;
8644 }
8645
8646 /* skip the clear bytes */
8647 196 input += sample->subsamples[i].bytes_of_clear_data;
8648 196 size -= sample->subsamples[i].bytes_of_clear_data;
8649
8650 /* decrypt the encrypted bytes */
8651
8652 196 bytes_of_protected_data = sample->subsamples[i].bytes_of_protected_data;
8653 196 av_aes_ctr_crypt(sc->cenc.aes_ctr, input, input, bytes_of_protected_data);
8654
8655 196 input += bytes_of_protected_data;
8656 196 size -= bytes_of_protected_data;
8657 }
8658
8659
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 196 times.
196 if (size > 0) {
8660 av_log(c->fc, AV_LOG_ERROR, "leftover packet bytes after subsample processing\n");
8661 return AVERROR_INVALIDDATA;
8662 }
8663
8664 196 return 0;
8665 }
8666
8667 static int cbc1_scheme_decrypt(MOVContext *c, MOVStreamContext *sc, AVEncryptionInfo *sample, uint8_t *input, int size)
8668 {
8669 int i, ret;
8670 int num_of_encrypted_blocks;
8671 uint8_t iv[16];
8672 uint8_t decryption_key[16];
8673
8674 if (!sc->cenc.aes_ctx) {
8675 ret = get_key_from_kid(decryption_key, sizeof(decryption_key), c, sample);
8676 if (ret < 0) {
8677 return ret;
8678 }
8679
8680 /* initialize the cipher */
8681 sc->cenc.aes_ctx = av_aes_alloc();
8682 if (!sc->cenc.aes_ctx) {
8683 return AVERROR(ENOMEM);
8684 }
8685
8686 ret = av_aes_init(sc->cenc.aes_ctx, decryption_key, 16 * 8, 1);
8687 if (ret < 0) {
8688 return ret;
8689 }
8690 }
8691
8692 memcpy(iv, sample->iv, 16);
8693
8694 /* whole-block full sample encryption */
8695 if (!sample->subsample_count) {
8696 /* decrypt the whole packet */
8697 av_aes_crypt(sc->cenc.aes_ctx, input, input, size/16, iv, 1);
8698 return 0;
8699 }
8700
8701 for (i = 0; i < sample->subsample_count; i++) {
8702 if (sample->subsamples[i].bytes_of_clear_data + (int64_t)sample->subsamples[i].bytes_of_protected_data > size) {
8703 av_log(c->fc, AV_LOG_ERROR, "subsample size exceeds the packet size left\n");
8704 return AVERROR_INVALIDDATA;
8705 }
8706
8707 if (sample->subsamples[i].bytes_of_protected_data % 16) {
8708 av_log(c->fc, AV_LOG_ERROR, "subsample BytesOfProtectedData is not a multiple of 16\n");
8709 return AVERROR_INVALIDDATA;
8710 }
8711
8712 /* skip the clear bytes */
8713 input += sample->subsamples[i].bytes_of_clear_data;
8714 size -= sample->subsamples[i].bytes_of_clear_data;
8715
8716 /* decrypt the encrypted bytes */
8717 num_of_encrypted_blocks = sample->subsamples[i].bytes_of_protected_data/16;
8718 if (num_of_encrypted_blocks > 0) {
8719 av_aes_crypt(sc->cenc.aes_ctx, input, input, num_of_encrypted_blocks, iv, 1);
8720 }
8721 input += sample->subsamples[i].bytes_of_protected_data;
8722 size -= sample->subsamples[i].bytes_of_protected_data;
8723 }
8724
8725 if (size > 0) {
8726 av_log(c->fc, AV_LOG_ERROR, "leftover packet bytes after subsample processing\n");
8727 return AVERROR_INVALIDDATA;
8728 }
8729
8730 return 0;
8731 }
8732
8733 static int cens_scheme_decrypt(MOVContext *c, MOVStreamContext *sc, AVEncryptionInfo *sample, uint8_t *input, int size)
8734 {
8735 int i, ret, rem_bytes;
8736 uint8_t *data;
8737 uint8_t decryption_key[AES_CTR_KEY_SIZE];
8738
8739 if (!sc->cenc.aes_ctr) {
8740 ret = get_key_from_kid(decryption_key, sizeof(decryption_key), c, sample);
8741 if (ret < 0) {
8742 return ret;
8743 }
8744
8745 /* initialize the cipher */
8746 sc->cenc.aes_ctr = av_aes_ctr_alloc();
8747 if (!sc->cenc.aes_ctr) {
8748 return AVERROR(ENOMEM);
8749 }
8750
8751 ret = av_aes_ctr_init(sc->cenc.aes_ctr, decryption_key);
8752 if (ret < 0) {
8753 return ret;
8754 }
8755 }
8756
8757 av_aes_ctr_set_full_iv(sc->cenc.aes_ctr, sample->iv);
8758
8759 /* whole-block full sample encryption */
8760 if (!sample->subsample_count) {
8761 /* decrypt the whole packet */
8762 av_aes_ctr_crypt(sc->cenc.aes_ctr, input, input, size);
8763 return 0;
8764 } else if (!sample->crypt_byte_block && !sample->skip_byte_block) {
8765 av_log(c->fc, AV_LOG_ERROR, "pattern encryption is not present in 'cens' scheme\n");
8766 return AVERROR_INVALIDDATA;
8767 }
8768
8769 for (i = 0; i < sample->subsample_count; i++) {
8770 if (sample->subsamples[i].bytes_of_clear_data + (int64_t)sample->subsamples[i].bytes_of_protected_data > size) {
8771 av_log(c->fc, AV_LOG_ERROR, "subsample size exceeds the packet size left\n");
8772 return AVERROR_INVALIDDATA;
8773 }
8774
8775 /* skip the clear bytes */
8776 input += sample->subsamples[i].bytes_of_clear_data;
8777 size -= sample->subsamples[i].bytes_of_clear_data;
8778
8779 /* decrypt the encrypted bytes */
8780 data = input;
8781 rem_bytes = sample->subsamples[i].bytes_of_protected_data;
8782 while (rem_bytes > 0) {
8783 if (rem_bytes < 16*sample->crypt_byte_block) {
8784 break;
8785 }
8786 av_aes_ctr_crypt(sc->cenc.aes_ctr, data, data, 16*sample->crypt_byte_block);
8787 data += 16*sample->crypt_byte_block;
8788 rem_bytes -= 16*sample->crypt_byte_block;
8789 data += FFMIN(16*sample->skip_byte_block, rem_bytes);
8790 rem_bytes -= FFMIN(16*sample->skip_byte_block, rem_bytes);
8791 }
8792 input += sample->subsamples[i].bytes_of_protected_data;
8793 size -= sample->subsamples[i].bytes_of_protected_data;
8794 }
8795
8796 if (size > 0) {
8797 av_log(c->fc, AV_LOG_ERROR, "leftover packet bytes after subsample processing\n");
8798 return AVERROR_INVALIDDATA;
8799 }
8800
8801 return 0;
8802 }
8803
8804 static int cbcs_scheme_decrypt(MOVContext *c, MOVStreamContext *sc, AVEncryptionInfo *sample, uint8_t *input, int size)
8805 {
8806 int i, ret, rem_bytes;
8807 uint8_t iv[16];
8808 uint8_t *data;
8809 uint8_t decryption_key[16];
8810
8811 if (!sc->cenc.aes_ctx) {
8812 ret = get_key_from_kid(decryption_key, sizeof(decryption_key), c, sample);
8813 if (ret < 0) {
8814 return ret;
8815 }
8816
8817 /* initialize the cipher */
8818 sc->cenc.aes_ctx = av_aes_alloc();
8819 if (!sc->cenc.aes_ctx) {
8820 return AVERROR(ENOMEM);
8821 }
8822
8823 ret = av_aes_init(sc->cenc.aes_ctx, decryption_key, 16 * 8, 1);
8824 if (ret < 0) {
8825 return ret;
8826 }
8827 }
8828
8829 /* whole-block full sample encryption */
8830 if (!sample->subsample_count) {
8831 /* decrypt the whole packet */
8832 memcpy(iv, sample->iv, 16);
8833 av_aes_crypt(sc->cenc.aes_ctx, input, input, size/16, iv, 1);
8834 return 0;
8835 } else if (!sample->crypt_byte_block && !sample->skip_byte_block) {
8836 av_log(c->fc, AV_LOG_ERROR, "pattern encryption is not present in 'cbcs' scheme\n");
8837 return AVERROR_INVALIDDATA;
8838 }
8839
8840 for (i = 0; i < sample->subsample_count; i++) {
8841 if (sample->subsamples[i].bytes_of_clear_data + (int64_t)sample->subsamples[i].bytes_of_protected_data > size) {
8842 av_log(c->fc, AV_LOG_ERROR, "subsample size exceeds the packet size left\n");
8843 return AVERROR_INVALIDDATA;
8844 }
8845
8846 /* skip the clear bytes */
8847 input += sample->subsamples[i].bytes_of_clear_data;
8848 size -= sample->subsamples[i].bytes_of_clear_data;
8849
8850 /* decrypt the encrypted bytes */
8851 memcpy(iv, sample->iv, 16);
8852 data = input;
8853 rem_bytes = sample->subsamples[i].bytes_of_protected_data;
8854 while (rem_bytes > 0) {
8855 if (rem_bytes < 16*sample->crypt_byte_block) {
8856 break;
8857 }
8858 av_aes_crypt(sc->cenc.aes_ctx, data, data, sample->crypt_byte_block, iv, 1);
8859 data += 16*sample->crypt_byte_block;
8860 rem_bytes -= 16*sample->crypt_byte_block;
8861 data += FFMIN(16*sample->skip_byte_block, rem_bytes);
8862 rem_bytes -= FFMIN(16*sample->skip_byte_block, rem_bytes);
8863 }
8864 input += sample->subsamples[i].bytes_of_protected_data;
8865 size -= sample->subsamples[i].bytes_of_protected_data;
8866 }
8867
8868 if (size > 0) {
8869 av_log(c->fc, AV_LOG_ERROR, "leftover packet bytes after subsample processing\n");
8870 return AVERROR_INVALIDDATA;
8871 }
8872
8873 return 0;
8874 }
8875
8876 292 static int cenc_decrypt(MOVContext *c, MOVStreamContext *sc, AVEncryptionInfo *sample, uint8_t *input, int size)
8877 {
8878
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) {
8879 292 return cenc_scheme_decrypt(c, sc, sample, input, size);
8880 } else if (sample->scheme == MKBETAG('c','b','c','1') && !sample->crypt_byte_block && !sample->skip_byte_block) {
8881 return cbc1_scheme_decrypt(c, sc, sample, input, size);
8882 } else if (sample->scheme == MKBETAG('c','e','n','s')) {
8883 return cens_scheme_decrypt(c, sc, sample, input, size);
8884 } else if (sample->scheme == MKBETAG('c','b','c','s')) {
8885 return cbcs_scheme_decrypt(c, sc, sample, input, size);
8886 } else {
8887 av_log(c->fc, AV_LOG_ERROR, "invalid encryption scheme\n");
8888 return AVERROR_INVALIDDATA;
8889 }
8890 }
8891
8892 107301 static MOVFragmentStreamInfo *get_frag_stream_info_from_pkt(MOVFragmentIndex *frag_index, AVPacket *pkt, int id)
8893 {
8894 107301 int current = frag_index->current;
8895
8896
2/2
✓ Branch 0 taken 106325 times.
✓ Branch 1 taken 976 times.
107301 if (!frag_index->nb_items)
8897 106325 return NULL;
8898
8899 // Check frag_index->current is the right one for pkt. It can out of sync.
8900
2/4
✓ Branch 0 taken 976 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 976 times.
✗ Branch 3 not taken.
976 if (current >= 0 && current < frag_index->nb_items) {
8901
2/2
✓ Branch 0 taken 950 times.
✓ Branch 1 taken 26 times.
976 if (frag_index->item[current].moof_offset < pkt->pos &&
8902
2/2
✓ Branch 0 taken 608 times.
✓ Branch 1 taken 342 times.
950 (current + 1 == frag_index->nb_items ||
8903
2/2
✓ Branch 0 taken 533 times.
✓ Branch 1 taken 75 times.
608 frag_index->item[current + 1].moof_offset > pkt->pos))
8904 875 return get_frag_stream_info(frag_index, current, id);
8905 }
8906
8907
8908
2/2
✓ Branch 0 taken 4553 times.
✓ Branch 1 taken 8 times.
4561 for (int i = 0; i < frag_index->nb_items; i++) {
8909
2/2
✓ Branch 0 taken 93 times.
✓ Branch 1 taken 4460 times.
4553 if (frag_index->item[i].moof_offset > pkt->pos)
8910 93 break;
8911 4460 current = i;
8912 }
8913 101 frag_index->current = current;
8914 101 return get_frag_stream_info(frag_index, current, id);
8915 }
8916
8917 107301 static int cenc_filter(MOVContext *mov, AVStream* st, MOVStreamContext *sc, AVPacket *pkt, int current_index)
8918 {
8919 MOVFragmentStreamInfo *frag_stream_info;
8920 MOVEncryptionIndex *encryption_index;
8921 AVEncryptionInfo *encrypted_sample;
8922 int encrypted_index, ret;
8923
8924 107301 frag_stream_info = get_frag_stream_info_from_pkt(&mov->frag_index, pkt, sc->id);
8925 107301 encrypted_index = current_index;
8926 107301 encryption_index = NULL;
8927
2/2
✓ Branch 0 taken 976 times.
✓ Branch 1 taken 106325 times.
107301 if (frag_stream_info) {
8928 // Note this only supports encryption info in the first sample descriptor.
8929
2/2
✓ Branch 0 taken 928 times.
✓ Branch 1 taken 48 times.
976 if (frag_stream_info->stsd_id == 1) {
8930
2/2
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 880 times.
928 if (frag_stream_info->encryption_index) {
8931 48 encrypted_index = current_index - frag_stream_info->index_base;
8932 48 encryption_index = frag_stream_info->encryption_index;
8933 } else {
8934 880 encryption_index = sc->cenc.encryption_index;
8935 }
8936 }
8937 } else {
8938 106325 encryption_index = sc->cenc.encryption_index;
8939 }
8940
8941
2/2
✓ Branch 0 taken 292 times.
✓ Branch 1 taken 107009 times.
107301 if (encryption_index) {
8942
2/2
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 244 times.
292 if (encryption_index->auxiliary_info_sample_count &&
8943
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 48 times.
48 !encryption_index->nb_encrypted_samples) {
8944 av_log(mov->fc, AV_LOG_ERROR, "saiz atom found without saio\n");
8945 return AVERROR_INVALIDDATA;
8946 }
8947
2/2
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 244 times.
292 if (encryption_index->auxiliary_offsets_count &&
8948
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 48 times.
48 !encryption_index->nb_encrypted_samples) {
8949 av_log(mov->fc, AV_LOG_ERROR, "saio atom found without saiz\n");
8950 return AVERROR_INVALIDDATA;
8951 }
8952
8953 292 encrypted_sample = NULL;
8954
2/2
✓ Branch 0 taken 96 times.
✓ Branch 1 taken 196 times.
292 if (!encryption_index->nb_encrypted_samples) {
8955 // Full-sample encryption with default settings.
8956 96 encrypted_sample = sc->cenc.default_encrypted_sample;
8957
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) {
8958 // Per-sample setting override.
8959 196 encrypted_sample = encryption_index->encrypted_samples[encrypted_index];
8960
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 196 times.
196 if (!encrypted_sample) {
8961 encrypted_sample = sc->cenc.default_encrypted_sample;
8962 }
8963 }
8964
8965
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 292 times.
292 if (!encrypted_sample) {
8966 av_log(mov->fc, AV_LOG_ERROR, "Incorrect number of samples in encryption info\n");
8967 return AVERROR_INVALIDDATA;
8968 }
8969
8970
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) {
8971 292 return cenc_decrypt(mov, sc, encrypted_sample, pkt->data, pkt->size);
8972 } else {
8973 size_t size;
8974 uint8_t *side_data = av_encryption_info_add_side_data(encrypted_sample, &size);
8975 if (!side_data)
8976 return AVERROR(ENOMEM);
8977 ret = av_packet_add_side_data(pkt, AV_PKT_DATA_ENCRYPTION_INFO, side_data, size);
8978 if (ret < 0)
8979 av_free(side_data);
8980 return ret;
8981 }
8982 }
8983
8984 107009 return 0;
8985 }
8986
8987 static int mov_read_dops(MOVContext *c, AVIOContext *pb, MOVAtom atom)
8988 {
8989 const int OPUS_SEEK_PREROLL_MS = 80;
8990 int ret;
8991 AVStream *st;
8992 size_t size;
8993 uint16_t pre_skip;
8994
8995 if (c->fc->nb_streams < 1)
8996 return 0;
8997 st = c->fc->streams[c->fc->nb_streams-1];
8998
8999 if ((uint64_t)atom.size > (1<<30) || atom.size < 11 || st->codecpar->extradata)
9000 return AVERROR_INVALIDDATA;
9001
9002 /* Check OpusSpecificBox version. */
9003 if (avio_r8(pb) != 0) {
9004 av_log(c->fc, AV_LOG_ERROR, "unsupported OpusSpecificBox version\n");
9005 return AVERROR_INVALIDDATA;
9006 }
9007
9008 /* OpusSpecificBox size plus magic for Ogg OpusHead header. */
9009 size = atom.size + 8;
9010
9011 if ((ret = ff_alloc_extradata(st->codecpar, size)) < 0)
9012 return ret;
9013
9014 AV_WL32A(st->codecpar->extradata, MKTAG('O','p','u','s'));
9015 AV_WL32A(st->codecpar->extradata + 4, MKTAG('H','e','a','d'));
9016 AV_WB8(st->codecpar->extradata + 8, 1); /* OpusHead version */
9017 if ((ret = ffio_read_size(pb, st->codecpar->extradata + 9, size - 9)) < 0) {
9018 av_freep(&st->codecpar->extradata);
9019 st->codecpar->extradata_size = 0;
9020 return ret;
9021 }
9022
9023 /* OpusSpecificBox is stored in big-endian, but OpusHead is
9024 little-endian; aside from the preceding magic and version they're
9025 otherwise currently identical. Data after output gain at offset 16
9026 doesn't need to be bytewapped. */
9027 pre_skip = AV_RB16A(st->codecpar->extradata + 10);
9028 AV_WL16A(st->codecpar->extradata + 10, pre_skip);
9029 AV_WL32A(st->codecpar->extradata + 12, AV_RB32A(st->codecpar->extradata + 12));
9030 AV_WL16A(st->codecpar->extradata + 16, AV_RB16A(st->codecpar->extradata + 16));
9031
9032 st->codecpar->initial_padding = pre_skip;
9033 st->codecpar->seek_preroll = av_rescale_q(OPUS_SEEK_PREROLL_MS,
9034 (AVRational){1, 1000},
9035 (AVRational){1, 48000});
9036
9037 return 0;
9038 }
9039
9040 static int mov_read_dmlp(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9041 {
9042 AVStream *st;
9043 unsigned format_info;
9044 int channel_assignment, channel_assignment1, channel_assignment2;
9045 int ratebits;
9046 uint64_t chmask;
9047
9048 if (c->fc->nb_streams < 1)
9049 return 0;
9050 st = c->fc->streams[c->fc->nb_streams-1];
9051
9052 if (atom.size < 10)
9053 return AVERROR_INVALIDDATA;
9054
9055 format_info = avio_rb32(pb);
9056
9057 ratebits = (format_info >> 28) & 0xF;
9058 channel_assignment1 = (format_info >> 15) & 0x1F;
9059 channel_assignment2 = format_info & 0x1FFF;
9060 if (channel_assignment2)
9061 channel_assignment = channel_assignment2;
9062 else
9063 channel_assignment = channel_assignment1;
9064
9065 st->codecpar->frame_size = 40 << (ratebits & 0x7);
9066 st->codecpar->sample_rate = mlp_samplerate(ratebits);
9067
9068 av_channel_layout_uninit(&st->codecpar->ch_layout);
9069 chmask = truehd_layout(channel_assignment);
9070 av_channel_layout_from_mask(&st->codecpar->ch_layout, chmask);
9071
9072 return 0;
9073 }
9074
9075 11 static int mov_read_dvcc_dvvc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9076 {
9077 AVStream *st;
9078 uint8_t buf[ISOM_DVCC_DVVC_SIZE];
9079 int ret;
9080 11 int64_t read_size = atom.size;
9081
9082
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (c->fc->nb_streams < 1)
9083 return 0;
9084 11 st = c->fc->streams[c->fc->nb_streams-1];
9085
9086 // At most 24 bytes
9087 11 read_size = FFMIN(read_size, ISOM_DVCC_DVVC_SIZE);
9088
9089
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 11 times.
11 if ((ret = ffio_read_size(pb, buf, read_size)) < 0)
9090 return ret;
9091
9092 11 return ff_isom_parse_dvcc_dvvc(c->fc, st, buf, read_size);
9093 }
9094
9095 7 static int mov_read_hvce(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9096 {
9097 AVStream *st;
9098 AVPacketSideData *sd;
9099 int ret;
9100
9101
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (c->fc->nb_streams < 1)
9102 return 0;
9103 7 st = c->fc->streams[c->fc->nb_streams - 1];
9104
9105
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)
9106 return AVERROR_INVALIDDATA;
9107
9108 7 sd = av_packet_side_data_new(&st->codecpar->coded_side_data,
9109 7 &st->codecpar->nb_coded_side_data,
9110 AV_PKT_DATA_HEVC_CONF,
9111 7 atom.size, 0);
9112
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (!sd)
9113 return AVERROR(ENOMEM);
9114
9115 7 ret = ffio_read_size(pb, sd->data, atom.size);
9116
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (ret < 0)
9117 return ret;
9118
9119 7 return 0;
9120 }
9121
9122 4 static int mov_read_lhvc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9123 {
9124 AVStream *st;
9125 uint8_t *buf;
9126 int ret, old_size, num_arrays;
9127
9128
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (c->fc->nb_streams < 1)
9129 return 0;
9130 4 st = c->fc->streams[c->fc->nb_streams-1];
9131
9132
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!st->codecpar->extradata_size)
9133 // TODO: handle lhvC when present before hvcC
9134 return 0;
9135
9136
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 ||
9137
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 atom.size > INT_MAX - AV_INPUT_BUFFER_PADDING_SIZE) {
9138 return AVERROR_INVALIDDATA;
9139 }
9140
9141 4 buf = av_malloc(atom.size + AV_INPUT_BUFFER_PADDING_SIZE);
9142
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!buf)
9143 return AVERROR(ENOMEM);
9144 4 memset(buf + atom.size, 0, AV_INPUT_BUFFER_PADDING_SIZE);
9145
9146 4 ret = ffio_read_size(pb, buf, atom.size);
9147
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (ret < 0) {
9148 av_free(buf);
9149 av_log(c->fc, AV_LOG_WARNING, "lhvC atom truncated\n");
9150 return 0;
9151 }
9152
9153 4 num_arrays = buf[5];
9154 4 old_size = st->codecpar->extradata_size;
9155 4 atom.size -= 8 /* account for mov_realloc_extradata offsetting */
9156 + 6 /* lhvC bytes before the arrays*/;
9157
9158 4 ret = mov_realloc_extradata(st->codecpar, atom);
9159
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (ret < 0) {
9160 av_free(buf);
9161 return ret;
9162 }
9163
9164 4 st->codecpar->extradata[22] += num_arrays;
9165 4 memcpy(st->codecpar->extradata + old_size, buf + 6, atom.size + 8);
9166
9167 4 st->disposition |= AV_DISPOSITION_MULTILAYER;
9168
9169 4 av_free(buf);
9170 4 return 0;
9171 }
9172
9173 4 static int mov_read_kind(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9174 {
9175 4 AVFormatContext *ctx = c->fc;
9176 4 AVStream *st = NULL;
9177 AVBPrint scheme_buf, value_buf;
9178 4 int64_t scheme_str_len = 0, value_str_len = 0;
9179 4 int version, flags, ret = AVERROR_BUG;
9180 4 int64_t size = atom.size;
9181
9182
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (atom.size < 6)
9183 // 4 bytes for version + flags, 2x 1 byte for null
9184 return AVERROR_INVALIDDATA;
9185
9186
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (c->fc->nb_streams < 1)
9187 return 0;
9188 4 st = c->fc->streams[c->fc->nb_streams-1];
9189
9190 4 version = avio_r8(pb);
9191 4 flags = avio_rb24(pb);
9192 4 size -= 4;
9193
9194
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) {
9195 av_log(ctx, AV_LOG_ERROR,
9196 "Unsupported 'kind' box with version %d, flags: %x",
9197 version, flags);
9198 return AVERROR_INVALIDDATA;
9199 }
9200
9201 4 av_bprint_init(&scheme_buf, 0, AV_BPRINT_SIZE_UNLIMITED);
9202 4 av_bprint_init(&value_buf, 0, AV_BPRINT_SIZE_UNLIMITED);
9203
9204
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,
9205 size)) < 0) {
9206 ret = scheme_str_len;
9207 goto cleanup;
9208 }
9209
9210
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (scheme_str_len + 1 >= size) {
9211 // we need to have another string, even if nullptr.
9212 // we check with + 1 since we expect that if size was not hit,
9213 // an additional null was read.
9214 ret = AVERROR_INVALIDDATA;
9215 goto cleanup;
9216 }
9217
9218 4 size -= scheme_str_len + 1;
9219
9220
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,
9221 size)) < 0) {
9222 ret = value_str_len;
9223 goto cleanup;
9224 }
9225
9226
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (value_str_len == size) {
9227 // in case of no trailing null, box is not valid.
9228 ret = AVERROR_INVALIDDATA;
9229 goto cleanup;
9230 }
9231
9232 4 av_log(ctx, AV_LOG_TRACE,
9233 "%s stream %d KindBox(scheme: %s, value: %s)\n",
9234 4 av_get_media_type_string(st->codecpar->codec_type),
9235 st->index,
9236 scheme_buf.str, value_buf.str);
9237
9238
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++) {
9239 4 const struct MP4TrackKindMapping map = ff_mov_track_kind_table[i];
9240
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
4 if (!av_strstart(scheme_buf.str, map.scheme_uri, NULL))
9241 continue;
9242
9243
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 4 times.
24 for (int j = 0; map.value_maps[j].disposition; j++) {
9244 20 const struct MP4TrackKindValueMapping value_map = map.value_maps[j];
9245
2/2
✓ Branch 1 taken 16 times.
✓ Branch 2 taken 4 times.
20 if (!av_strstart(value_buf.str, value_map.value, NULL))
9246 16 continue;
9247
9248 4 st->disposition |= value_map.disposition;
9249 }
9250 }
9251
9252 4 ret = 0;
9253
9254 4 cleanup:
9255
9256 4 av_bprint_finalize(&scheme_buf, NULL);
9257 4 av_bprint_finalize(&value_buf, NULL);
9258
9259 4 return ret;
9260 }
9261
9262 static int mov_read_SA3D(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9263 {
9264 AVStream *st;
9265 AVChannelLayout ch_layout = { 0 };
9266 int ret, i, version, type;
9267 int ambisonic_order, channel_order, normalization, channel_count;
9268 int ambi_channels, non_diegetic_channels;
9269
9270 if (c->fc->nb_streams < 1)
9271 return 0;
9272
9273 st = c->fc->streams[c->fc->nb_streams - 1];
9274
9275 if (atom.size < 16) {
9276 av_log(c->fc, AV_LOG_ERROR, "SA3D audio box too small\n");
9277 return AVERROR_INVALIDDATA;
9278 }
9279
9280 version = avio_r8(pb);
9281 if (version) {
9282 av_log(c->fc, AV_LOG_WARNING, "Unsupported SA3D box version %d\n", version);
9283 return 0;
9284 }
9285
9286 type = avio_r8(pb);
9287 if (type & 0x7f) {
9288 av_log(c->fc, AV_LOG_WARNING,
9289 "Unsupported ambisonic type %d\n", type & 0x7f);
9290 return 0;
9291 }
9292 non_diegetic_channels = (type >> 7) * 2; // head_locked_stereo
9293
9294 ambisonic_order = avio_rb32(pb);
9295
9296 channel_order = avio_r8(pb);
9297 if (channel_order) {
9298 av_log(c->fc, AV_LOG_WARNING,
9299 "Unsupported channel_order %d\n", channel_order);
9300 return 0;
9301 }
9302
9303 normalization = avio_r8(pb);
9304 if (normalization) {
9305 av_log(c->fc, AV_LOG_WARNING,
9306 "Unsupported normalization %d\n", normalization);
9307 return 0;
9308 }
9309
9310 channel_count = avio_rb32(pb);
9311 if (ambisonic_order < 0 || ambisonic_order > 31 ||
9312 channel_count != ((ambisonic_order + 1LL) * (ambisonic_order + 1LL) +
9313 non_diegetic_channels)) {
9314 av_log(c->fc, AV_LOG_ERROR,
9315 "Invalid number of channels (%d / %d)\n",
9316 channel_count, ambisonic_order);
9317 return 0;
9318 }
9319 ambi_channels = channel_count - non_diegetic_channels;
9320
9321 ret = av_channel_layout_custom_init(&ch_layout, channel_count);
9322 if (ret < 0)
9323 return 0;
9324
9325 for (i = 0; i < channel_count; i++) {
9326 unsigned channel = avio_rb32(pb);
9327
9328 if (channel >= channel_count) {
9329 av_log(c->fc, AV_LOG_ERROR, "Invalid channel index (%d / %d)\n",
9330 channel, ambisonic_order);
9331 av_channel_layout_uninit(&ch_layout);
9332 return 0;
9333 }
9334 if (channel >= ambi_channels)
9335 ch_layout.u.map[i].id = channel - ambi_channels;
9336 else
9337 ch_layout.u.map[i].id = AV_CHAN_AMBISONIC_BASE + channel;
9338 }
9339
9340 ret = av_channel_layout_retype(&ch_layout, 0, AV_CHANNEL_LAYOUT_RETYPE_FLAG_CANONICAL);
9341 if (ret < 0) {
9342 av_channel_layout_uninit(&ch_layout);
9343 return 0;
9344 }
9345
9346 av_channel_layout_uninit(&st->codecpar->ch_layout);
9347 st->codecpar->ch_layout = ch_layout;
9348
9349 return 0;
9350 }
9351
9352 static int mov_read_SAND(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9353 {
9354 AVStream *st;
9355 int version;
9356
9357 if (c->fc->nb_streams < 1)
9358 return 0;
9359
9360 st = c->fc->streams[c->fc->nb_streams - 1];
9361
9362 if (atom.size < 5) {
9363 av_log(c->fc, AV_LOG_ERROR, "Empty SAND audio box\n");
9364 return AVERROR_INVALIDDATA;
9365 }
9366
9367 version = avio_r8(pb);
9368 if (version) {
9369 av_log(c->fc, AV_LOG_WARNING, "Unsupported SAND box version %d\n", version);
9370 return 0;
9371 }
9372
9373 st->disposition |= AV_DISPOSITION_NON_DIEGETIC;
9374
9375 return 0;
9376 }
9377
9378 171 static int rb_size(AVIOContext *pb, int64_t *value, int size)
9379 {
9380
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 160 times.
171 if (size == 0)
9381 11 *value = 0;
9382
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 160 times.
160 else if (size == 1)
9383 *value = avio_r8(pb);
9384
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 160 times.
160 else if (size == 2)
9385 *value = avio_rb16(pb);
9386
1/2
✓ Branch 0 taken 160 times.
✗ Branch 1 not taken.
160 else if (size == 4)
9387 160 *value = avio_rb32(pb);
9388 else if (size == 8) {
9389 *value = avio_rb64(pb);
9390 if (*value < 0)
9391 return -1;
9392 } else
9393 return -1;
9394 171 return size;
9395 }
9396
9397 18 static int mov_read_pitm(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9398 {
9399 18 avio_rb32(pb); // version & flags.
9400 18 c->primary_item_id = avio_rb16(pb);
9401 18 av_log(c->fc, AV_LOG_TRACE, "pitm: primary_item_id %d\n", c->primary_item_id);
9402 18 return atom.size;
9403 }
9404
9405 9 static int mov_read_idat(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9406 {
9407 9 c->idat_offset = avio_tell(pb);
9408 9 return 0;
9409 }
9410
9411 18 static int mov_read_iloc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9412 {
9413 HEIFItem **heif_item;
9414 int version, offset_size, length_size, base_offset_size, index_size;
9415 int item_count, extent_count;
9416 int64_t base_offset, extent_offset, extent_length;
9417 uint8_t value;
9418
9419
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (c->found_iloc) {
9420 av_log(c->fc, AV_LOG_INFO, "Duplicate iloc box found\n");
9421 return 0;
9422 }
9423
9424 18 version = avio_r8(pb);
9425 18 avio_rb24(pb); // flags.
9426
9427 18 value = avio_r8(pb);
9428 18 offset_size = (value >> 4) & 0xF;
9429 18 length_size = value & 0xF;
9430 18 value = avio_r8(pb);
9431 18 base_offset_size = (value >> 4) & 0xF;
9432
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 7 times.
18 index_size = !version ? 0 : (value & 0xF);
9433
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (index_size) {
9434 avpriv_report_missing_feature(c->fc, "iloc: index_size != 0");
9435 return AVERROR_PATCHWELCOME;
9436 }
9437
1/2
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
18 item_count = (version < 2) ? avio_rb16(pb) : avio_rb32(pb);
9438
9439
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (item_count > atom.size)
9440 return AVERROR_INVALIDDATA;
9441
9442 18 heif_item = av_realloc_array(c->heif_item, FFMAX(item_count, c->nb_heif_item), sizeof(*c->heif_item));
9443
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (!heif_item)
9444 return AVERROR(ENOMEM);
9445 18 c->heif_item = heif_item;
9446
1/2
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
18 if (item_count > c->nb_heif_item)
9447 18 memset(&c->heif_item[c->nb_heif_item], 0,
9448 18 sizeof(*c->heif_item) * (item_count - c->nb_heif_item));
9449 18 c->nb_heif_item = FFMAX(c->nb_heif_item, item_count);
9450
9451 18 av_log(c->fc, AV_LOG_TRACE, "iloc: item_count %d\n", item_count);
9452
2/2
✓ Branch 0 taken 57 times.
✓ Branch 1 taken 18 times.
75 for (int i = 0; i < item_count; i++) {
9453 57 HEIFItem *item = NULL;
9454
1/2
✓ Branch 0 taken 57 times.
✗ Branch 1 not taken.
57 int item_id = (version < 2) ? avio_rb16(pb) : avio_rb32(pb);
9455
2/2
✓ Branch 0 taken 45 times.
✓ Branch 1 taken 12 times.
57 int offset_type = (version > 0) ? avio_rb16(pb) & 0xf : 0;
9456 int j;
9457
9458
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 57 times.
57 if (avio_feof(pb))
9459 return AVERROR_INVALIDDATA;
9460
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 57 times.
57 if (offset_type > 1) {
9461 avpriv_report_missing_feature(c->fc, "iloc offset type %d", offset_type);
9462 return AVERROR_PATCHWELCOME;
9463 }
9464
9465 57 avio_rb16(pb); // data_reference_index.
9466
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 57 times.
57 if (rb_size(pb, &base_offset, base_offset_size) < 0)
9467 return AVERROR_INVALIDDATA;
9468 57 extent_count = avio_rb16(pb);
9469
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 57 times.
57 if (extent_count > 1) {
9470 // For still AVIF images, we only support one extent item.
9471 avpriv_report_missing_feature(c->fc, "iloc: extent_count > 1");
9472 return AVERROR_PATCHWELCOME;
9473 }
9474
9475
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 ||
9476 57 rb_size(pb, &extent_length, length_size) < 0 ||
9477
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 57 times.
57 base_offset > INT64_MAX - extent_offset)
9478 return AVERROR_INVALIDDATA;
9479
9480
1/2
✓ Branch 0 taken 140 times.
✗ Branch 1 not taken.
140 for (j = 0; j < c->nb_heif_item; j++) {
9481 140 item = c->heif_item[j];
9482
2/2
✓ Branch 0 taken 57 times.
✓ Branch 1 taken 83 times.
140 if (!item)
9483 57 item = c->heif_item[j] = av_mallocz(sizeof(*item));
9484
1/2
✓ Branch 0 taken 83 times.
✗ Branch 1 not taken.
83 else if (item->item_id != item_id)
9485 83 continue;
9486 57 break;
9487 }
9488
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 57 times.
57 if (!item)
9489 return AVERROR(ENOMEM);
9490
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 57 times.
57 if (j == c->nb_heif_item)
9491 return AVERROR_INVALIDDATA;
9492
9493 57 item->item_id = item_id;
9494
9495
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 48 times.
57 if (offset_type == 1)
9496 9 item->is_idat_relative = 1;
9497 57 item->extent_length = extent_length;
9498 57 item->extent_offset = base_offset + extent_offset;
9499 57 av_log(c->fc, AV_LOG_TRACE, "iloc: item_idx %d, item->item_id %d, offset_type %d, "
9500 "extent_offset %"PRId64", extent_length %"PRId64"\n",
9501 i, item->item_id, offset_type, item->extent_offset, item->extent_length);
9502 }
9503
9504 18 c->found_iloc = 1;
9505 18 return atom.size;
9506 }
9507
9508 57 static int mov_read_infe(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9509 {
9510 57 HEIFItem *item = NULL;
9511 AVBPrint item_name;
9512 57 int64_t size = atom.size;
9513 uint32_t item_type;
9514 int item_id;
9515 int i, version, ret;
9516
9517 57 version = avio_r8(pb);
9518 57 avio_rb24(pb); // flags.
9519 57 size -= 4;
9520
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 57 times.
57 if (size < 0)
9521 return AVERROR_INVALIDDATA;
9522
9523
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 57 times.
57 if (version < 2) {
9524 avpriv_report_missing_feature(c->fc, "infe version < 2");
9525 avio_skip(pb, size);
9526 return 1;
9527 }
9528
9529
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 57 times.
57 item_id = version > 2 ? avio_rb32(pb) : avio_rb16(pb);
9530 57 avio_rb16(pb); // item_protection_index
9531 57 item_type = avio_rl32(pb);
9532 57 size -= 8;
9533
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 57 times.
57 if (size < 1)
9534 return AVERROR_INVALIDDATA;
9535
9536 57 av_bprint_init(&item_name, 0, AV_BPRINT_SIZE_UNLIMITED);
9537 57 ret = ff_read_string_to_bprint_overwrite(pb, &item_name, size);
9538
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 57 times.
57 if (ret < 0) {
9539 av_bprint_finalize(&item_name, NULL);
9540 return ret;
9541 }
9542
9543 57 av_log(c->fc, AV_LOG_TRACE, "infe: item_id %d, item_type %s, item_name %s\n",
9544 57 item_id, av_fourcc2str(item_type), item_name.str);
9545
9546 57 size -= ret + 1;
9547
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 55 times.
57 if (size > 0)
9548 2 avio_skip(pb, size);
9549
9550
1/2
✓ Branch 0 taken 140 times.
✗ Branch 1 not taken.
140 for (i = 0; i < c->nb_heif_item; i++) {
9551 140 item = c->heif_item[i];
9552
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 140 times.
140 if (!item)
9553 item = c->heif_item[i] = av_mallocz(sizeof(*item));
9554
2/2
✓ Branch 0 taken 83 times.
✓ Branch 1 taken 57 times.
140 else if (item->item_id != item_id)
9555 83 continue;
9556 57 break;
9557 }
9558
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 57 times.
57 if (!item) {
9559 av_bprint_finalize(&item_name, NULL);
9560 return AVERROR(ENOMEM);
9561 }
9562
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 57 times.
57 if (i == c->nb_heif_item) {
9563 av_bprint_finalize(&item_name, NULL);
9564 return AVERROR_INVALIDDATA;
9565 }
9566
9567 57 av_freep(&item->name);
9568
2/2
✓ Branch 0 taken 56 times.
✓ Branch 1 taken 1 times.
57 av_bprint_finalize(&item_name, ret ? &item->name : NULL);
9569 57 item->item_id = item_id;
9570 57 item->type = item_type;
9571
9572
2/2
✓ Branch 0 taken 43 times.
✓ Branch 1 taken 14 times.
57 switch (item_type) {
9573 43 case MKTAG('a','v','0','1'):
9574 case MKTAG('j','p','e','g'):
9575 case MKTAG('h','v','c','1'):
9576 43 ret = heif_add_stream(c, item);
9577
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 43 times.
43 if (ret < 0)
9578 return ret;
9579 43 break;
9580 }
9581
9582 57 return 0;
9583 }
9584
9585 18 static int mov_read_iinf(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9586 {
9587 HEIFItem **heif_item;
9588 int entry_count;
9589 18 int version, got_stream = 0, ret, i;
9590
9591
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (c->found_iinf) {
9592 av_log(c->fc, AV_LOG_WARNING, "Duplicate iinf box found\n");
9593 return 0;
9594 }
9595
9596 18 version = avio_r8(pb);
9597 18 avio_rb24(pb); // flags.
9598
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 entry_count = version ? avio_rb32(pb) : avio_rb16(pb);
9599
9600
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (entry_count > atom.size)
9601 return AVERROR_INVALIDDATA;
9602
9603 18 heif_item = av_realloc_array(c->heif_item, FFMAX(entry_count, c->nb_heif_item), sizeof(*c->heif_item));
9604
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (!heif_item)
9605 return AVERROR(ENOMEM);
9606 18 c->heif_item = heif_item;
9607
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (entry_count > c->nb_heif_item)
9608 memset(&c->heif_item[c->nb_heif_item], 0,
9609 sizeof(*c->heif_item) * (entry_count - c->nb_heif_item));
9610 18 c->nb_heif_item = FFMAX(c->nb_heif_item, entry_count);
9611
9612
2/2
✓ Branch 0 taken 57 times.
✓ Branch 1 taken 18 times.
75 for (i = 0; i < entry_count; i++) {
9613 MOVAtom infe;
9614
9615 57 infe.size = avio_rb32(pb) - 8;
9616 57 infe.type = avio_rl32(pb);
9617
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 57 times.
57 if (avio_feof(pb)) {
9618 ret = AVERROR_INVALIDDATA;
9619 goto fail;
9620 }
9621 57 ret = mov_read_infe(c, pb, infe);
9622
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 57 times.
57 if (ret < 0)
9623 goto fail;
9624
1/2
✓ Branch 0 taken 57 times.
✗ Branch 1 not taken.
57 if (!ret)
9625 57 got_stream = 1;
9626 }
9627
9628 18 c->found_iinf = got_stream;
9629 18 return 0;
9630 fail:
9631 for (; i >= 0; i--) {
9632 HEIFItem *item = c->heif_item[i];
9633
9634 if (!item)
9635 continue;
9636
9637 av_freep(&item->name);
9638 }
9639 return ret;
9640 }
9641
9642 9 static int mov_read_iref_dimg(MOVContext *c, AVIOContext *pb, int version)
9643 {
9644 9 HEIFItem *item = NULL;
9645 HEIFGrid *grid;
9646 int entries, i;
9647
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 int from_item_id = version ? avio_rb32(pb) : avio_rb16(pb);
9648 9 int ret = 0;
9649
9650
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 for (int i = 0; i < c->nb_heif_grid; i++) {
9651 if (c->heif_grid[i].item->item_id == from_item_id) {
9652 av_log(c->fc, AV_LOG_ERROR, "More than one 'dimg' box "
9653 "referencing the same Derived Image item\n");
9654 return AVERROR_INVALIDDATA;
9655 }
9656 }
9657
1/2
✓ Branch 0 taken 35 times.
✗ Branch 1 not taken.
35 for (int i = 0; i < c->nb_heif_item; i++) {
9658
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)
9659 26 continue;
9660 9 item = c->heif_item[i];
9661
9662
1/2
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
9 switch (item->type) {
9663 9 case MKTAG('g','r','i','d'):
9664 case MKTAG('i','o','v','l'):
9665 9 break;
9666 default:
9667 avpriv_report_missing_feature(c->fc, "Derived Image item of type %s",
9668 av_fourcc2str(item->type));
9669 return 0;
9670 }
9671 9 break;
9672 }
9673
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if (!item) {
9674 av_log(c->fc, AV_LOG_ERROR, "Missing grid information\n");
9675 return AVERROR_INVALIDDATA;
9676 }
9677
9678 9 entries = avio_rb16(pb);
9679
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if (!entries) {
9680 av_log(c->fc, AV_LOG_ERROR,
9681 "Derived image item references no input images\n");
9682 return AVERROR_INVALIDDATA;
9683 }
9684
9685 9 grid = av_realloc_array(c->heif_grid, c->nb_heif_grid + 1U,
9686 sizeof(*c->heif_grid));
9687
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if (!grid)
9688 return AVERROR(ENOMEM);
9689 9 c->heif_grid = grid;
9690 9 grid = &grid[c->nb_heif_grid];
9691
9692 9 grid->tile_id_list = av_malloc_array(entries, sizeof(*grid->tile_id_list));
9693 9 grid->tile_idx_list = av_calloc(entries, sizeof(*grid->tile_idx_list));
9694 9 grid->tile_item_list = av_calloc(entries, sizeof(*grid->tile_item_list));
9695
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) {
9696 ret = AVERROR(ENOMEM);
9697 goto fail;
9698 }
9699 /* 'to' item ids */
9700
2/2
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 9 times.
37 for (i = 0; i < entries; i++) {
9701
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
28 grid->tile_id_list[i] = version ? avio_rb32(pb) : avio_rb16(pb);
9702
9703
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 28 times.
28 if (avio_feof(pb)) {
9704 ret = AVERROR_INVALIDDATA;
9705 goto fail;
9706 }
9707 }
9708
9709 9 grid->nb_tiles = entries;
9710 9 grid->item = item;
9711 9 ++c->nb_heif_grid;
9712
9713 9 av_log(c->fc, AV_LOG_TRACE, "dimg: from_item_id %d, entries %d\n",
9714 from_item_id, entries);
9715
9716 9 return 0;
9717 fail:
9718 av_freep(&grid->tile_id_list);
9719 av_freep(&grid->tile_idx_list);
9720 av_freep(&grid->tile_item_list);
9721
9722 return ret;
9723 }
9724
9725 11 static int mov_read_iref_cdsc(MOVContext *c, AVIOContext *pb, uint32_t type, int version, uint32_t size)
9726 {
9727 11 HEIFItem *from_item = NULL;
9728 int entries;
9729
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 int item_id_size = version ? 4 : 2;
9730
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 int from_item_id = version ? avio_rb32(pb) : avio_rb16(pb);
9731 11 const HEIFItemRef ref = { type, from_item_id };
9732
9733 11 from_item = get_heif_item(c, from_item_id);
9734
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (!from_item) {
9735 av_log(c->fc, AV_LOG_ERROR, "Missing stream referenced by thmb item\n");
9736 return AVERROR_INVALIDDATA;
9737 }
9738
9739 11 entries = avio_rb16(pb);
9740
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) {
9741 av_log(c->fc, AV_LOG_ERROR, "iref %s entry count %d exceeds the sub-box size\n",
9742 av_fourcc2str(type), entries);
9743 return AVERROR_INVALIDDATA;
9744 }
9745 /* 'to' item ids */
9746
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 11 times.
22 for (int i = 0; i < entries; i++) {
9747
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));
9748
9749
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 11 times.
11 if (avio_feof(pb))
9750 return AVERROR_INVALIDDATA;
9751
9752
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (!item) {
9753 av_log(c->fc, AV_LOG_WARNING, "Missing stream referenced by %s item\n",
9754 av_fourcc2str(type));
9755 continue;
9756 }
9757
9758
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 11 times.
11 if (!av_dynarray2_add((void **)&item->iref_list, &item->nb_iref_list,
9759 sizeof(*item->iref_list), (const uint8_t *)&ref))
9760 return AVERROR(ENOMEM);
9761 }
9762
9763 11 av_log(c->fc, AV_LOG_TRACE, "%s: from_item_id %d, entries %d\n",
9764 11 av_fourcc2str(type), from_item_id, entries);
9765
9766 11 return 0;
9767 }
9768
9769 14 static int mov_read_iref(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9770 {
9771 14 int version = avio_r8(pb);
9772 int ret;
9773
9774 14 avio_rb24(pb); // flags
9775 14 atom.size -= 4;
9776
9777
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
14 if (version > 1) {
9778 av_log(c->fc, AV_LOG_WARNING, "Unknown iref box version %d\n", version);
9779 return 0;
9780 }
9781
9782
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 14 times.
34 while (atom.size) {
9783 20 int64_t next = avio_tell(pb);
9784 20 uint32_t type, size = avio_rb32(pb);
9785
9786
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)
9787 return AVERROR_INVALIDDATA;
9788
9789 20 next += size;
9790 20 type = avio_rl32(pb);
9791
2/3
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 11 times.
✗ Branch 2 not taken.
20 switch (type) {
9792 9 case MKTAG('d','i','m','g'):
9793 9 ret = mov_read_iref_dimg(c, pb, version);
9794
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if (ret < 0)
9795 return ret;
9796 20 break;
9797 11 case MKTAG('c','d','s','c'):
9798 case MKTAG('t','h','m','b'):
9799 11 ret = mov_read_iref_cdsc(c, pb, type, version, size - 8);
9800
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (ret < 0)
9801 return ret;
9802 11 break;
9803 default:
9804 av_log(c->fc, AV_LOG_DEBUG, "Unknown iref type %s size %"PRIu32"\n",
9805 av_fourcc2str(type), size);
9806 }
9807
9808 20 atom.size -= size;
9809 20 avio_seek(pb, next, SEEK_SET);
9810 }
9811 14 return 0;
9812 }
9813
9814 52 static int mov_read_ispe(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9815 {
9816 HEIFItem *item;
9817 uint32_t width, height;
9818
9819 52 avio_r8(pb); /* version */
9820 52 avio_rb24(pb); /* flags */
9821 52 width = avio_rb32(pb);
9822 52 height = avio_rb32(pb);
9823
9824 52 av_log(c->fc, AV_LOG_TRACE, "ispe: item_id %d, width %"PRIu32", height %"PRIu32"\n",
9825 c->cur_item_id, width, height);
9826
9827
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) {
9828 av_log(c->fc, AV_LOG_ERROR, "Invalid ispe dimensions %"PRIu32"x%"PRIu32"\n",
9829 width, height);
9830 return AVERROR_INVALIDDATA;
9831 }
9832
9833 52 item = get_heif_item(c, c->cur_item_id);
9834
1/2
✓ Branch 0 taken 52 times.
✗ Branch 1 not taken.
52 if (item) {
9835 52 item->width = width;
9836 52 item->height = height;
9837 }
9838
9839 52 return 0;
9840 }
9841
9842 8 static int mov_read_irot(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9843 {
9844 HEIFItem *item;
9845 int angle;
9846
9847 8 angle = avio_r8(pb) & 0x3;
9848
9849 8 av_log(c->fc, AV_LOG_TRACE, "irot: item_id %d, angle %u\n",
9850 c->cur_item_id, angle);
9851
9852 8 item = get_heif_item(c, c->cur_item_id);
9853
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 if (item) {
9854 // angle * 90 specifies the angle (in anti-clockwise direction)
9855 // in units of degrees.
9856 8 item->rotation = angle * 90;
9857 }
9858
9859 8 return 0;
9860 }
9861
9862 6 static int mov_read_imir(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9863 {
9864 HEIFItem *item;
9865 int axis;
9866
9867 6 axis = avio_r8(pb) & 0x1;
9868
9869 6 av_log(c->fc, AV_LOG_TRACE, "imir: item_id %d, axis %u\n",
9870 c->cur_item_id, axis);
9871
9872 6 item = get_heif_item(c, c->cur_item_id);
9873
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 if (item) {
9874 6 item->hflip = axis;
9875 6 item->vflip = !axis;
9876 }
9877
9878 6 return 0;
9879 }
9880
9881 18 static int mov_read_iprp(MOVContext *c, AVIOContext *pb, MOVAtom atom)
9882 {
9883 typedef struct MOVAtoms {
9884 FFIOContext b;
9885 uint32_t type;
9886 int64_t size;
9887 uint8_t *data;
9888 } MOVAtoms;
9889 18 MOVAtoms *atoms = NULL;
9890 MOVAtom a;
9891 unsigned count;
9892 18 int nb_atoms = 0;
9893 int version, flags;
9894 int ret;
9895
9896 18 a.size = avio_rb32(pb);
9897 18 a.type = avio_rl32(pb);
9898
9899
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'))
9900 return AVERROR_INVALIDDATA;
9901
9902 18 a.size -= 8;
9903
2/2
✓ Branch 0 taken 80 times.
✓ Branch 1 taken 18 times.
98 while (a.size >= 8) {
9904 80 MOVAtoms *ref = av_dynarray2_add((void**)&atoms, &nb_atoms, sizeof(MOVAtoms), NULL);
9905
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 80 times.
80 if (!ref) {
9906 ret = AVERROR(ENOMEM);
9907 goto fail;
9908 }
9909 80 ref->data = NULL;
9910 80 ref->size = avio_rb32(pb);
9911 80 ref->type = avio_rl32(pb);
9912
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)
9913 break;
9914 80 ref->data = av_malloc(ref->size);
9915
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 80 times.
80 if (!ref->data) {
9916 ret = AVERROR_INVALIDDATA;
9917 goto fail;
9918 }
9919 80 av_log(c->fc, AV_LOG_TRACE, "ipco: index %d, box type %s\n", nb_atoms, av_fourcc2str(ref->type));
9920 80 avio_seek(pb, -8, SEEK_CUR);
9921
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 80 times.
80 if (avio_read(pb, ref->data, ref->size) != ref->size) {
9922 ret = AVERROR_INVALIDDATA;
9923 goto fail;
9924 }
9925 80 ffio_init_read_context(&ref->b, ref->data, ref->size);
9926 80 a.size -= ref->size;
9927 }
9928
9929
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (a.size) {
9930 ret = AVERROR_INVALIDDATA;
9931 goto fail;
9932 }
9933
9934 18 a.size = avio_rb32(pb);
9935 18 a.type = avio_rl32(pb);
9936
9937
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')) {
9938 ret = AVERROR_INVALIDDATA;
9939 goto fail;
9940 }
9941
9942 18 version = avio_r8(pb);
9943 18 flags = avio_rb24(pb);
9944 18 count = avio_rb32(pb);
9945
9946
2/2
✓ Branch 0 taken 52 times.
✓ Branch 1 taken 18 times.
70 for (int i = 0; i < count; i++) {
9947
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 52 times.
52 int item_id = version ? avio_rb32(pb) : avio_rb16(pb);
9948 52 int assoc_count = avio_r8(pb);
9949
9950
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 52 times.
52 if (avio_feof(pb)) {
9951 ret = AVERROR_INVALIDDATA;
9952 goto fail;
9953 }
9954
9955
2/2
✓ Branch 0 taken 125 times.
✓ Branch 1 taken 52 times.
177 for (int j = 0; j < assoc_count; j++) {
9956 MOVAtoms *ref;
9957 125 int index = avio_r8(pb) & 0x7f;
9958
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 125 times.
125 if (flags & 1) {
9959 index <<= 8;
9960 index |= avio_r8(pb);
9961 }
9962
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) {
9963 ret = AVERROR_INVALIDDATA;
9964 goto fail;
9965 }
9966 125 ref = &atoms[--index];
9967
9968 125 av_log(c->fc, AV_LOG_TRACE, "ipma: property_index %d, item_id %d, item_type %s\n",
9969 125 index + 1, item_id, av_fourcc2str(ref->type));
9970
9971 125 c->cur_item_id = item_id;
9972
9973 125 ret = mov_read_default(c, &ref->b.pub,
9974 125 (MOVAtom) { .size = ref->size,
9975 .type = MKTAG('i','p','c','o') });
9976
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 125 times.
125 if (ret < 0)
9977 goto fail;
9978 125 ffio_init_read_context(&ref->b, ref->data, ref->size);
9979 }
9980 }
9981
9982 18 ret = 0;
9983 18 fail:
9984 18 c->cur_item_id = -1;
9985
2/2
✓ Branch 0 taken 80 times.
✓ Branch 1 taken 18 times.
98 for (int i = 0; i < nb_atoms; i++)
9986 80 av_free(atoms[i].data);
9987 18 av_free(atoms);
9988
9989 18 return ret;
9990 }
9991
9992 static const MOVParseTableEntry mov_default_parse_table[] = {
9993 { MKTAG('A','C','L','R'), mov_read_aclr },
9994 { MKTAG('A','P','R','G'), mov_read_avid },
9995 { MKTAG('A','A','L','P'), mov_read_avid },
9996 { MKTAG('A','R','E','S'), mov_read_ares },
9997 { MKTAG('a','v','s','s'), mov_read_avss },
9998 { MKTAG('a','v','1','C'), mov_read_glbl },
9999 { MKTAG('c','h','p','l'), mov_read_chpl },
10000 { MKTAG('c','o','6','4'), mov_read_stco },
10001 { MKTAG('c','o','l','r'), mov_read_colr },
10002 { MKTAG('c','t','t','s'), mov_read_ctts }, /* composition time to sample */
10003 { MKTAG('d','i','n','f'), mov_read_default },
10004 { MKTAG('D','p','x','E'), mov_read_dpxe },
10005 { MKTAG('d','r','e','f'), mov_read_dref },
10006 { MKTAG('e','d','t','s'), mov_read_default },
10007 { MKTAG('e','l','s','t'), mov_read_elst },
10008 { MKTAG('e','n','d','a'), mov_read_enda },
10009 { MKTAG('f','i','e','l'), mov_read_fiel },
10010 { MKTAG('a','d','r','m'), mov_read_adrm },
10011 { MKTAG('f','t','y','p'), mov_read_ftyp },
10012 { MKTAG('g','l','b','l'), mov_read_glbl },
10013 { MKTAG('h','d','l','r'), mov_read_hdlr },
10014 { MKTAG('i','l','s','t'), mov_read_ilst },
10015 { MKTAG('j','p','2','h'), mov_read_jp2h },
10016 { MKTAG('m','d','a','t'), mov_read_mdat },
10017 { MKTAG('m','d','h','d'), mov_read_mdhd },
10018 { MKTAG('m','d','i','a'), mov_read_default },
10019 { MKTAG('m','e','t','a'), mov_read_meta },
10020 { MKTAG('m','i','n','f'), mov_read_default },
10021 { MKTAG('m','o','o','f'), mov_read_moof },
10022 { MKTAG('m','o','o','v'), mov_read_moov },
10023 { MKTAG('m','v','e','x'), mov_read_default },
10024 { MKTAG('m','v','h','d'), mov_read_mvhd },
10025 { MKTAG('S','M','I',' '), mov_read_svq3 },
10026 { MKTAG('a','l','a','c'), mov_read_alac }, /* alac specific atom */
10027 { MKTAG('a','v','c','C'), mov_read_glbl },
10028 { MKTAG('p','a','s','p'), mov_read_pasp },
10029 { MKTAG('c','l','a','p'), mov_read_clap },
10030 { MKTAG('c','d','s','c'), mov_read_cdsc_rndr },
10031 { MKTAG('r','n','d','r'), mov_read_cdsc_rndr },
10032 { MKTAG('s','b','a','s'), mov_read_sbas },
10033 { MKTAG('v','d','e','p'), mov_read_vdep },
10034 { MKTAG('s','i','d','x'), mov_read_sidx },
10035 { MKTAG('s','t','b','l'), mov_read_default },
10036 { MKTAG('s','t','c','o'), mov_read_stco },
10037 { MKTAG('s','t','p','s'), mov_read_stps },
10038 { MKTAG('s','t','r','f'), mov_read_strf },
10039 { MKTAG('s','t','s','c'), mov_read_stsc },
10040 { MKTAG('s','t','s','d'), mov_read_stsd }, /* sample description */
10041 { MKTAG('s','t','s','s'), mov_read_stss }, /* sync sample */
10042 { MKTAG('s','t','s','z'), mov_read_stsz }, /* sample size */
10043 { MKTAG('s','t','t','s'), mov_read_stts },
10044 { MKTAG('s','t','z','2'), mov_read_stsz }, /* compact sample size */
10045 { MKTAG('s','d','t','p'), mov_read_sdtp }, /* independent and disposable samples */
10046 { MKTAG('t','k','h','d'), mov_read_tkhd }, /* track header */
10047 { MKTAG('t','f','d','t'), mov_read_tfdt },
10048 { MKTAG('t','f','h','d'), mov_read_tfhd }, /* track fragment header */
10049 { MKTAG('t','r','a','k'), mov_read_trak },
10050 { MKTAG('t','r','a','f'), mov_read_default },
10051 { MKTAG('t','r','e','f'), mov_read_default },
10052 { MKTAG('t','m','c','d'), mov_read_tmcd },
10053 { MKTAG('c','h','a','p'), mov_read_chap },
10054 { MKTAG('t','r','e','x'), mov_read_trex },
10055 { MKTAG('t','r','u','n'), mov_read_trun },
10056 { MKTAG('u','d','t','a'), mov_read_default },
10057 { MKTAG('w','a','v','e'), mov_read_wave },
10058 { MKTAG('e','s','d','s'), mov_read_esds },
10059 { MKTAG('d','a','c','3'), mov_read_dac3 }, /* AC-3 info */
10060 { MKTAG('d','e','c','3'), mov_read_dec3 }, /* EAC-3 info */
10061 { MKTAG('d','d','t','s'), mov_read_ddts }, /* DTS audio descriptor */
10062 { MKTAG('w','i','d','e'), mov_read_wide }, /* place holder */
10063 { MKTAG('w','f','e','x'), mov_read_wfex },
10064 { MKTAG('c','m','o','v'), mov_read_cmov },
10065 { MKTAG('c','h','a','n'), mov_read_chan }, /* channel layout from quicktime */
10066 { MKTAG('c','h','n','l'), mov_read_chnl }, /* channel layout from ISO-14496-12 */
10067 { MKTAG('d','v','c','1'), mov_read_dvc1 },
10068 { MKTAG('s','g','p','d'), mov_read_sgpd },
10069 { MKTAG('s','b','g','p'), mov_read_sbgp },
10070 { MKTAG('h','v','c','C'), mov_read_glbl },
10071 { MKTAG('v','v','c','C'), mov_read_glbl },
10072 { MKTAG('u','u','i','d'), mov_read_uuid },
10073 { MKTAG('C','i','n', 0x8e), mov_read_targa_y216 },
10074 { MKTAG('f','r','e','e'), mov_read_free },
10075 { MKTAG('-','-','-','-'), mov_read_custom },
10076 { MKTAG('s','i','n','f'), mov_read_default },
10077 { MKTAG('f','r','m','a'), mov_read_frma },
10078 { MKTAG('s','e','n','c'), mov_read_senc },
10079 { MKTAG('s','a','i','z'), mov_read_saiz },
10080 { MKTAG('s','a','i','o'), mov_read_saio },
10081 { MKTAG('p','s','s','h'), mov_read_pssh },
10082 { MKTAG('s','c','h','m'), mov_read_schm },
10083 { MKTAG('s','c','h','i'), mov_read_default },
10084 { MKTAG('t','e','n','c'), mov_read_tenc },
10085 { MKTAG('d','f','L','a'), mov_read_dfla },
10086 { MKTAG('s','t','3','d'), mov_read_st3d }, /* stereoscopic 3D video box */
10087 { MKTAG('s','v','3','d'), mov_read_sv3d }, /* spherical video box */
10088 { MKTAG('v','e','x','u'), mov_read_vexu }, /* video extension usage */
10089 { MKTAG('h','f','o','v'), mov_read_hfov },
10090 { MKTAG('d','O','p','s'), mov_read_dops },
10091 { MKTAG('d','m','l','p'), mov_read_dmlp },
10092 { MKTAG('S','m','D','m'), mov_read_smdm },
10093 { MKTAG('C','o','L','L'), mov_read_coll },
10094 { MKTAG('v','p','c','C'), mov_read_vpcc },
10095 { MKTAG('m','d','c','v'), mov_read_mdcv },
10096 { MKTAG('c','l','l','i'), mov_read_clli },
10097 { MKTAG('d','v','c','C'), mov_read_dvcc_dvvc },
10098 { MKTAG('d','v','v','C'), mov_read_dvcc_dvvc },
10099 { MKTAG('d','v','w','C'), mov_read_dvcc_dvvc },
10100 { MKTAG('h','v','c','E'), mov_read_hvce },
10101 { MKTAG('k','i','n','d'), mov_read_kind },
10102 { MKTAG('S','A','3','D'), mov_read_SA3D }, /* ambisonic audio box */
10103 { MKTAG('S','A','N','D'), mov_read_SAND }, /* non diegetic audio box */
10104 { MKTAG('i','l','o','c'), mov_read_iloc },
10105 { MKTAG('p','c','m','C'), mov_read_pcmc }, /* PCM configuration box */
10106 { MKTAG('p','i','t','m'), mov_read_pitm },
10107 { MKTAG('e','v','c','C'), mov_read_glbl },
10108 { MKTAG('i','d','a','t'), mov_read_idat },
10109 { MKTAG('i','m','i','r'), mov_read_imir },
10110 { MKTAG('i','r','e','f'), mov_read_iref },
10111 { MKTAG('i','s','p','e'), mov_read_ispe },
10112 { MKTAG('i','r','o','t'), mov_read_irot },
10113 { MKTAG('i','p','r','p'), mov_read_iprp },
10114 { MKTAG('i','i','n','f'), mov_read_iinf },
10115 { MKTAG('a','m','v','e'), mov_read_amve }, /* ambient viewing environment box */
10116 { MKTAG('l','h','v','C'), mov_read_lhvc },
10117 { MKTAG('l','v','c','C'), mov_read_glbl },
10118 { MKTAG('a','p','v','C'), mov_read_glbl },
10119 #if CONFIG_IAMFDEC
10120 { MKTAG('i','a','c','b'), mov_read_iacb },
10121 #endif
10122 { MKTAG('s','r','a','t'), mov_read_srat },
10123 { 0, NULL }
10124 };
10125
10126 7394 static int mov_read_default(MOVContext *c, AVIOContext *pb, MOVAtom atom)
10127 {
10128 7394 int64_t total_size = 0;
10129 MOVAtom a;
10130 int i;
10131
10132
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7394 times.
7394 if (c->atom_depth > 10) {
10133 av_log(c->fc, AV_LOG_ERROR, "Atoms too deeply nested\n");
10134 return AVERROR_INVALIDDATA;
10135 }
10136 7394 c->atom_depth ++;
10137
10138
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7394 times.
7394 if (atom.size < 0)
10139 atom.size = INT64_MAX;
10140
2/2
✓ Branch 0 taken 21149 times.
✓ Branch 1 taken 6841 times.
27990 while (total_size <= atom.size - 8) {
10141 21149 int (*parse)(MOVContext*, AVIOContext*, MOVAtom) = NULL;
10142 21149 a.size = avio_rb32(pb);
10143 21149 a.type = avio_rl32(pb);
10144
2/2
✓ Branch 1 taken 7 times.
✓ Branch 2 taken 21142 times.
21149 if (avio_feof(pb))
10145 7 break;
10146
3/4
✓ Branch 0 taken 233 times.
✓ Branch 1 taken 20909 times.
✓ Branch 2 taken 233 times.
✗ Branch 3 not taken.
21142 if (((a.type == MKTAG('f','r','e','e') && c->moov_retry) ||
10147
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 21142 times.
21142 a.type == MKTAG('h','o','o','v')) &&
10148 a.size >= 8 &&
10149 c->fc->strict_std_compliance < FF_COMPLIANCE_STRICT) {
10150 uint32_t type;
10151 avio_skip(pb, 4);
10152 type = avio_rl32(pb);
10153 if (avio_feof(pb))
10154 break;
10155 avio_seek(pb, -8, SEEK_CUR);
10156 if (type == MKTAG('m','v','h','d') ||
10157 type == MKTAG('c','m','o','v')) {
10158 av_log(c->fc, AV_LOG_ERROR, "Detected moov in a free or hoov atom.\n");
10159 a.type = MKTAG('m','o','o','v');
10160 }
10161 }
10162
2/2
✓ Branch 0 taken 18001 times.
✓ Branch 1 taken 3141 times.
21142 if (atom.type != MKTAG('r','o','o','t') &&
10163
2/2
✓ Branch 0 taken 16383 times.
✓ Branch 1 taken 1618 times.
18001 atom.type != MKTAG('m','o','o','v')) {
10164
1/2
✓ Branch 0 taken 16383 times.
✗ Branch 1 not taken.
16383 if (a.type == MKTAG('t','r','a','k') ||
10165
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16383 times.
16383 a.type == MKTAG('m','d','a','t')) {
10166 av_log(c->fc, AV_LOG_ERROR, "Broken file, trak/mdat not at top-level\n");
10167 avio_skip(pb, -8);
10168 c->atom_depth --;
10169 546 return 0;
10170 }
10171 }
10172 21142 total_size += 8;
10173
3/4
✓ Branch 0 taken 29 times.
✓ Branch 1 taken 21113 times.
✓ Branch 2 taken 29 times.
✗ Branch 3 not taken.
21142 if (a.size == 1 && total_size + 8 <= atom.size) { /* 64 bit extended size */
10174 29 a.size = avio_rb64(pb) - 8;
10175 29 total_size += 8;
10176 }
10177 21142 av_log(c->fc, AV_LOG_TRACE, "type:'%s' parent:'%s' sz: %"PRId64" %"PRId64" %"PRId64"\n",
10178 21142 av_fourcc2str(a.type), av_fourcc2str(atom.type), a.size, total_size, atom.size);
10179
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 21137 times.
21142 if (a.size == 0) {
10180 5 a.size = atom.size - total_size + 8;
10181 }
10182
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 21142 times.
21142 if (a.size < 0)
10183 break;
10184 21142 a.size -= 8;
10185
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 21142 times.
21142 if (a.size < 0)
10186 break;
10187 21142 a.size = FFMIN(a.size, atom.size - total_size);
10188
10189
2/2
✓ Branch 0 taken 1015106 times.
✓ Branch 1 taken 2136 times.
1017242 for (i = 0; mov_default_parse_table[i].type; i++)
10190
2/2
✓ Branch 0 taken 19006 times.
✓ Branch 1 taken 996100 times.
1015106 if (mov_default_parse_table[i].type == a.type) {
10191 19006 parse = mov_default_parse_table[i].parse;
10192 19006 break;
10193 }
10194
10195 // container is user data
10196
4/4
✓ Branch 0 taken 2136 times.
✓ Branch 1 taken 19006 times.
✓ Branch 2 taken 1957 times.
✓ Branch 3 taken 179 times.
21142 if (!parse && (atom.type == MKTAG('u','d','t','a') ||
10197
2/2
✓ Branch 0 taken 365 times.
✓ Branch 1 taken 1592 times.
1957 atom.type == MKTAG('i','l','s','t')))
10198 544 parse = mov_read_udta_string;
10199
10200 // Supports parsing the QuickTime Metadata Keys.
10201 // https://developer.apple.com/library/mac/documentation/QuickTime/QTFF/Metadata/Metadata.html
10202
4/4
✓ Branch 0 taken 1592 times.
✓ Branch 1 taken 19550 times.
✓ Branch 2 taken 11 times.
✓ Branch 3 taken 1581 times.
21142 if (!parse && c->found_hdlr_mdta &&
10203
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 atom.type == MKTAG('m','e','t','a') &&
10204
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 a.type == MKTAG('k','e','y','s') &&
10205
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 c->meta_keys_count == 0) {
10206 11 parse = mov_read_keys;
10207 }
10208
10209
2/2
✓ Branch 0 taken 1581 times.
✓ Branch 1 taken 19561 times.
21142 if (!parse) { /* skip leaf atoms data */
10210 1581 avio_skip(pb, a.size);
10211 } else {
10212 19561 int64_t start_pos = avio_tell(pb);
10213 int64_t left;
10214 19561 int err = parse(c, pb, a);
10215
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 19561 times.
19561 if (err < 0) {
10216 c->atom_depth --;
10217 return err;
10218 }
10219
5/6
✓ Branch 0 taken 3794 times.
✓ Branch 1 taken 15767 times.
✓ Branch 2 taken 3399 times.
✓ Branch 3 taken 395 times.
✓ Branch 4 taken 3399 times.
✗ Branch 5 not taken.
19561 if (c->found_moov && c->found_mdat && a.size <= INT64_MAX - start_pos &&
10220
7/8
✓ Branch 0 taken 3398 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 3398 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3384 times.
✓ Branch 5 taken 14 times.
✓ Branch 6 taken 531 times.
✓ Branch 7 taken 2853 times.
6783 ((!(pb->seekable & AVIO_SEEKABLE_NORMAL) || c->fc->flags & AVFMT_FLAG_IGNIDX || c->frag_index.complete) ||
10221 3384 start_pos + a.size == avio_size(pb))) {
10222
5/6
✓ Branch 0 taken 545 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 545 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 14 times.
✓ Branch 5 taken 531 times.
546 if (!(pb->seekable & AVIO_SEEKABLE_NORMAL) || c->fc->flags & AVFMT_FLAG_IGNIDX || c->frag_index.complete)
10223 15 c->next_root_atom = start_pos + a.size;
10224 546 c->atom_depth --;
10225 546 return 0;
10226 }
10227 19015 left = a.size - avio_tell(pb) + start_pos;
10228
2/2
✓ Branch 0 taken 1637 times.
✓ Branch 1 taken 17378 times.
19015 if (left > 0) /* skip garbage at atom end */
10229 1637 avio_skip(pb, left);
10230
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 17376 times.
17378 else if (left < 0) {
10231 2 av_log(c->fc, AV_LOG_WARNING,
10232 "overread end of atom '%s' by %"PRId64" bytes\n",
10233 2 av_fourcc2str(a.type), -left);
10234 2 avio_seek(pb, left, SEEK_CUR);
10235 }
10236 }
10237
10238 20596 total_size += a.size;
10239 }
10240
10241
4/4
✓ Branch 0 taken 109 times.
✓ Branch 1 taken 6739 times.
✓ Branch 2 taken 102 times.
✓ Branch 3 taken 7 times.
6848 if (total_size < atom.size && atom.size < 0x7ffff)
10242 102 avio_skip(pb, atom.size - total_size);
10243
10244 6848 c->atom_depth --;
10245 6848 return 0;
10246 }
10247
10248 7957 static int mov_probe(const AVProbeData *p)
10249 {
10250 int64_t offset;
10251 uint32_t tag;
10252 7957 int score = 0;
10253 7957 int moov_offset = -1;
10254
10255 /* check file header */
10256 7957 offset = 0;
10257 9765 for (;;) {
10258 int64_t size;
10259 17722 int minsize = 8;
10260 /* ignore invalid offset */
10261
2/2
✓ Branch 0 taken 7957 times.
✓ Branch 1 taken 9765 times.
17722 if ((offset + 8ULL) > (unsigned int)p->buf_size)
10262 7957 break;
10263 9765 size = AV_RB32(p->buf + offset);
10264
3/4
✓ Branch 0 taken 530 times.
✓ Branch 1 taken 9235 times.
✓ Branch 2 taken 530 times.
✗ Branch 3 not taken.
9765 if (size == 1 && offset + 16 <= (unsigned int)p->buf_size) {
10265 530 size = AV_RB64(p->buf+offset + 8);
10266 530 minsize = 16;
10267
2/2
✓ Branch 0 taken 72 times.
✓ Branch 1 taken 9163 times.
9235 } else if (size == 0) {
10268 72 size = p->buf_size - offset;
10269 }
10270
2/2
✓ Branch 0 taken 402 times.
✓ Branch 1 taken 9363 times.
9765 if (size < minsize) {
10271 402 offset += 4;
10272 402 continue;
10273 }
10274 9363 tag = AV_RL32(p->buf + offset + 4);
10275
5/6
✓ Branch 0 taken 145 times.
✓ Branch 1 taken 944 times.
✓ Branch 2 taken 390 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 7883 times.
9363 switch(tag) {
10276 /* check for obvious tags */
10277 145 case MKTAG('m','o','o','v'):
10278 145 moov_offset = offset + 4;
10279 av_fallthrough;
10280 1089 case MKTAG('m','d','a','t'):
10281 case MKTAG('p','n','o','t'): /* detect movs with preview pics like ew.mov and april.mov */
10282 case MKTAG('u','d','t','a'): /* Packet Video PVAuthor adds this and a lot of more junk */
10283 case MKTAG('f','t','y','p'):
10284
2/2
✓ Branch 0 taken 494 times.
✓ Branch 1 taken 595 times.
1089 if (tag == MKTAG('f','t','y','p') &&
10285
1/2
✓ Branch 0 taken 494 times.
✗ Branch 1 not taken.
494 ( AV_RL32(p->buf + offset + 8) == MKTAG('j','p','2',' ')
10286
1/2
✓ Branch 0 taken 494 times.
✗ Branch 1 not taken.
494 || AV_RL32(p->buf + offset + 8) == MKTAG('j','p','x',' ')
10287
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 487 times.
494 || AV_RL32(p->buf + offset + 8) == MKTAG('j','x','l',' ')
10288 )) {
10289 7 score = FFMAX(score, 5);
10290 } else {
10291 1082 score = AVPROBE_SCORE_MAX;
10292 }
10293 1089 break;
10294 /* those are more common words, so rate then a bit less */
10295 390 case MKTAG('e','d','i','w'): /* xdcam files have reverted first tags */
10296 case MKTAG('w','i','d','e'):
10297 case MKTAG('f','r','e','e'):
10298 case MKTAG('j','u','n','k'):
10299 case MKTAG('p','i','c','t'):
10300 390 score = FFMAX(score, AVPROBE_SCORE_MAX - 5);
10301 390 break;
10302 case MKTAG(0x82,0x82,0x7f,0x7d):
10303 score = FFMAX(score, AVPROBE_SCORE_EXTENSION - 5);
10304 break;
10305 1 case MKTAG('s','k','i','p'):
10306 case MKTAG('u','u','i','d'):
10307 case MKTAG('p','r','f','l'):
10308 /* if we only find those cause probedata is too small at least rate them */
10309 1 score = FFMAX(score, AVPROBE_SCORE_EXTENSION);
10310 1 break;
10311 }
10312
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9363 times.
9363 if (size > INT64_MAX - offset)
10313 break;
10314 9363 offset += size;
10315 }
10316
4/4
✓ Branch 0 taken 524 times.
✓ Branch 1 taken 7433 times.
✓ Branch 2 taken 145 times.
✓ Branch 3 taken 379 times.
7957 if (score > AVPROBE_SCORE_MAX - 50 && moov_offset != -1) {
10317 /* moov atom in the header - we should make sure that this is not a
10318 * MOV-packed MPEG-PS */
10319 145 offset = moov_offset;
10320
10321
2/2
✓ Branch 0 taken 142026 times.
✓ Branch 1 taken 145 times.
142171 while (offset < (p->buf_size - 16)) { /* Sufficient space */
10322 /* We found an actual hdlr atom */
10323
2/2
✓ Branch 0 taken 147 times.
✓ Branch 1 taken 141879 times.
142026 if (AV_RL32(p->buf + offset ) == MKTAG('h','d','l','r') &&
10324
2/2
✓ Branch 0 taken 22 times.
✓ Branch 1 taken 125 times.
147 AV_RL32(p->buf + offset + 8) == MKTAG('m','h','l','r') &&
10325
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 22 times.
22 AV_RL32(p->buf + offset + 12) == MKTAG('M','P','E','G')) {
10326 av_log(NULL, AV_LOG_WARNING, "Found media data tag MPEG indicating this is a MOV-packed MPEG-PS.\n");
10327 /* We found a media handler reference atom describing an
10328 * MPEG-PS-in-MOV, return a
10329 * low score to force expanding the probe window until
10330 * mpegps_probe finds what it needs */
10331 return 5;
10332 } else {
10333 /* Keep looking */
10334 142026 offset += 2;
10335 }
10336 }
10337 }
10338
10339 7957 return score;
10340 }
10341
10342 // must be done after parsing all trak because there's no order requirement
10343 2 static void mov_read_chapters(AVFormatContext *s)
10344 {
10345 2 MOVContext *mov = s->priv_data;
10346 MOVStreamContext *sc;
10347 int64_t cur_pos;
10348 int i, j;
10349 int chapter_track;
10350
10351
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 for (j = 0; j < mov->nb_chapter_tracks; j++) {
10352 2 AVStream *st = NULL;
10353 2 FFStream *sti = NULL;
10354 2 chapter_track = mov->chapter_tracks[j];
10355
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 for (i = 0; i < s->nb_streams; i++) {
10356 4 sc = mov->fc->streams[i]->priv_data;
10357
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 if (sc->id == chapter_track) {
10358 2 st = s->streams[i];
10359 2 break;
10360 }
10361 }
10362
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!st) {
10363 av_log(s, AV_LOG_ERROR, "Referenced QT chapter track not found\n");
10364 continue;
10365 }
10366 2 sti = ffstream(st);
10367
10368 2 sc = st->priv_data;
10369 2 cur_pos = avio_tell(sc->pb);
10370
10371
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
10372 st->disposition |= AV_DISPOSITION_ATTACHED_PIC | AV_DISPOSITION_TIMED_THUMBNAILS;
10373 if (!st->attached_pic.data && sti->nb_index_entries) {
10374 // Retrieve the first frame, if possible
10375 AVIndexEntry *sample = &sti->index_entries[0];
10376 if (avio_seek(sc->pb, sample->pos, SEEK_SET) != sample->pos) {
10377 av_log(s, AV_LOG_ERROR, "Failed to retrieve first frame\n");
10378 goto finish;
10379 }
10380
10381 if (ff_add_attached_pic(s, st, sc->pb, NULL, sample->size) < 0)
10382 goto finish;
10383 }
10384 } else {
10385 2 st->codecpar->codec_type = AVMEDIA_TYPE_DATA;
10386 2 st->codecpar->codec_id = AV_CODEC_ID_BIN_DATA;
10387 2 st->discard = AVDISCARD_ALL;
10388
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 2 times.
10 for (int i = 0; i < sti->nb_index_entries; i++) {
10389 8 AVIndexEntry *sample = &sti->index_entries[i];
10390
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;
10391 uint8_t *title;
10392 uint16_t ch;
10393 int len, title_len;
10394
10395
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (end < sample->timestamp) {
10396 av_log(s, AV_LOG_WARNING, "ignoring stream duration which is shorter than chapters\n");
10397 end = AV_NOPTS_VALUE;
10398 }
10399
10400
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
8 if (avio_seek(sc->pb, sample->pos, SEEK_SET) != sample->pos) {
10401 av_log(s, AV_LOG_ERROR, "Chapter %d not found in file\n", i);
10402 goto finish;
10403 }
10404
10405 // the first two bytes are the length of the title
10406 8 len = avio_rb16(sc->pb);
10407
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (len > sample->size-2)
10408 continue;
10409 8 title_len = 2*len + 1;
10410
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
8 if (!(title = av_mallocz(title_len)))
10411 goto finish;
10412
10413 // The samples could theoretically be in any encoding if there's an encd
10414 // atom following, but in practice are only utf-8 or utf-16, distinguished
10415 // instead by the presence of a BOM
10416
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (!len) {
10417 title[0] = 0;
10418 } else {
10419 8 ch = avio_rb16(sc->pb);
10420
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (ch == 0xfeff)
10421 avio_get_str16be(sc->pb, len, title, title_len);
10422
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 else if (ch == 0xfffe)
10423 avio_get_str16le(sc->pb, len, title, title_len);
10424 else {
10425 8 AV_WB16(title, ch);
10426
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)
10427 title[len] = 0;
10428 else
10429 8 avio_get_str(sc->pb, INT_MAX, title + 2, len - 1);
10430 }
10431 }
10432
10433 8 avpriv_new_chapter(s, i, st->time_base, sample->timestamp, end, title);
10434 8 av_freep(&title);
10435 }
10436 }
10437 2 finish:
10438 2 avio_seek(sc->pb, cur_pos, SEEK_SET);
10439 }
10440 2 }
10441
10442 19 static int parse_timecode_in_framenum_format(AVFormatContext *s, AVStream *st,
10443 int64_t value, int flags)
10444 {
10445 AVTimecode tc;
10446 char buf[AV_TIMECODE_STR_SIZE];
10447 19 AVRational rate = st->avg_frame_rate;
10448 19 int ret = av_timecode_init(&tc, rate, flags, 0, s);
10449
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 19 times.
19 if (ret < 0)
10450 return ret;
10451 19 av_dict_set(&st->metadata, "timecode",
10452 19 av_timecode_make_string(&tc, buf, value), 0);
10453 19 return 0;
10454 }
10455
10456 static int mov_read_rtmd_track(AVFormatContext *s, AVStream *st)
10457 {
10458 MOVStreamContext *sc = st->priv_data;
10459 FFStream *const sti = ffstream(st);
10460 char buf[AV_TIMECODE_STR_SIZE];
10461 int64_t cur_pos = avio_tell(sc->pb);
10462 int hh, mm, ss, ff, drop;
10463
10464 if (!sti->nb_index_entries)
10465 return -1;
10466
10467 avio_seek(sc->pb, sti->index_entries->pos, SEEK_SET);
10468 avio_skip(s->pb, 13);
10469 hh = avio_r8(s->pb);
10470 mm = avio_r8(s->pb);
10471 ss = avio_r8(s->pb);
10472 drop = avio_r8(s->pb);
10473 ff = avio_r8(s->pb);
10474 snprintf(buf, AV_TIMECODE_STR_SIZE, "%02d:%02d:%02d%c%02d",
10475 hh, mm, ss, drop ? ';' : ':', ff);
10476 av_dict_set(&st->metadata, "timecode", buf, 0);
10477
10478 avio_seek(sc->pb, cur_pos, SEEK_SET);
10479 return 0;
10480 }
10481
10482 19 static int mov_read_timecode_track(AVFormatContext *s, AVStream *st)
10483 {
10484 19 MOVStreamContext *sc = st->priv_data;
10485 19 FFStream *const sti = ffstream(st);
10486 19 int flags = 0;
10487 19 int64_t cur_pos = avio_tell(sc->pb);
10488 int64_t value;
10489 19 AVRational tc_rate = st->avg_frame_rate;
10490 19 int tmcd_nb_frames = sc->tmcd_nb_frames;
10491 int rounded_tc_rate;
10492
10493
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 19 times.
19 if (!sti->nb_index_entries)
10494 return -1;
10495
10496
3/6
✓ Branch 0 taken 19 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 19 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 19 times.
19 if (!tc_rate.num || !tc_rate.den || !tmcd_nb_frames)
10497 return -1;
10498
10499 19 avio_seek(sc->pb, sti->index_entries->pos, SEEK_SET);
10500 19 value = avio_rb32(s->pb);
10501
10502
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 10 times.
19 if (sc->tmcd_flags & 0x0001) flags |= AV_TIMECODE_FLAG_DROPFRAME;
10503
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 18 times.
19 if (sc->tmcd_flags & 0x0002) flags |= AV_TIMECODE_FLAG_24HOURSMAX;
10504
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 18 times.
19 if (sc->tmcd_flags & 0x0004) flags |= AV_TIMECODE_FLAG_ALLOWNEGATIVE;
10505
10506 /* Assume Counter flag is set to 1 in tmcd track (even though it is likely
10507 * not the case) and thus assume "frame number format" instead of QT one.
10508 * No sample with tmcd track can be found with a QT timecode at the moment,
10509 * despite what the tmcd track "suggests" (Counter flag set to 0 means QT
10510 * format). */
10511
10512 /* 60 fps content have tmcd_nb_frames set to 30 but tc_rate set to 60, so
10513 * we multiply the frame number with the quotient.
10514 * See tickets #9492, #9710. */
10515 19 rounded_tc_rate = (tc_rate.num + tc_rate.den / 2LL) / tc_rate.den;
10516 /* Work around files where tmcd_nb_frames is rounded down from frame rate
10517 * instead of up. See ticket #5978. */
10518
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 9 times.
19 if (tmcd_nb_frames == tc_rate.num / tc_rate.den &&
10519
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 s->strict_std_compliance < FF_COMPLIANCE_STRICT)
10520 10 tmcd_nb_frames = rounded_tc_rate;
10521 19 value = av_rescale(value, rounded_tc_rate, tmcd_nb_frames);
10522
10523 19 parse_timecode_in_framenum_format(s, st, value, flags);
10524
10525 19 avio_seek(sc->pb, cur_pos, SEEK_SET);
10526 19 return 0;
10527 }
10528
10529 1311 static void mov_free_encryption_index(MOVEncryptionIndex **index) {
10530 int i;
10531
3/4
✓ Branch 0 taken 1311 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1303 times.
✓ Branch 3 taken 8 times.
1311 if (!index || !*index) return;
10532
2/2
✓ Branch 0 taken 144 times.
✓ Branch 1 taken 8 times.
152 for (i = 0; i < (*index)->nb_encrypted_samples; i++) {
10533 144 av_encryption_info_free((*index)->encrypted_samples[i]);
10534 }
10535 8 av_freep(&(*index)->encrypted_samples);
10536 8 av_freep(&(*index)->auxiliary_info_sizes);
10537 8 av_freep(&(*index)->auxiliary_offsets);
10538 8 av_freep(index);
10539 }
10540
10541 784 static void mov_free_stream_context(AVFormatContext *s, AVStream *st)
10542 {
10543 784 MOVStreamContext *sc = st->priv_data;
10544
10545
3/4
✓ Branch 0 taken 784 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 52 times.
✓ Branch 3 taken 732 times.
784 if (!sc || --sc->refcount) {
10546 52 st->priv_data = NULL;
10547 52 return;
10548 }
10549
10550 732 av_freep(&sc->tts_data);
10551
2/2
✓ Branch 0 taken 673 times.
✓ Branch 1 taken 732 times.
1405 for (int i = 0; i < sc->drefs_count; i++) {
10552 673 av_freep(&sc->drefs[i].path);
10553 673 av_freep(&sc->drefs[i].dir);
10554 }
10555 732 av_freep(&sc->drefs);
10556
10557 732 sc->drefs_count = 0;
10558
10559
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 716 times.
732 if (!sc->pb_is_copied)
10560 16 ff_format_io_close(s, &sc->pb);
10561
10562 732 sc->pb = NULL;
10563 732 av_freep(&sc->chunk_offsets);
10564 732 av_freep(&sc->stsc_data);
10565 732 av_freep(&sc->sample_sizes);
10566 732 av_freep(&sc->keyframes);
10567 732 av_freep(&sc->ctts_data);
10568 732 av_freep(&sc->stts_data);
10569 732 av_freep(&sc->sdtp_data);
10570 732 av_freep(&sc->stps_data);
10571 732 av_freep(&sc->elst_data);
10572 732 av_freep(&sc->rap_group);
10573 732 av_freep(&sc->sync_group);
10574 732 av_freep(&sc->sgpd_sync);
10575 732 av_freep(&sc->sample_offsets);
10576 732 av_freep(&sc->open_key_samples);
10577 732 av_freep(&sc->display_matrix);
10578 732 av_freep(&sc->index_ranges);
10579
2/2
✓ Branch 0 taken 29 times.
✓ Branch 1 taken 732 times.
761 for (int i = 0; i < sc->nb_tref_tags; i++)
10580 29 av_freep(&sc->tref_tags[i].id);
10581 732 av_freep(&sc->tref_tags);
10582
10583
2/2
✓ Branch 0 taken 673 times.
✓ Branch 1 taken 59 times.
732 if (sc->extradata)
10584
2/2
✓ Branch 0 taken 688 times.
✓ Branch 1 taken 673 times.
1361 for (int i = 0; i < sc->stsd_count; i++)
10585 688 av_free(sc->extradata[i]);
10586 732 av_freep(&sc->extradata);
10587 732 av_freep(&sc->extradata_size);
10588
10589 732 mov_free_encryption_index(&sc->cenc.encryption_index);
10590 732 av_encryption_info_free(sc->cenc.default_encrypted_sample);
10591 732 av_aes_ctr_free(sc->cenc.aes_ctr);
10592
10593 732 av_freep(&sc->stereo3d);
10594 732 av_freep(&sc->spherical);
10595 732 av_freep(&sc->mastering);
10596 732 av_freep(&sc->coll);
10597 732 av_freep(&sc->ambient);
10598
10599 #if CONFIG_IAMFDEC
10600
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 720 times.
732 if (sc->iamf)
10601 12 ff_iamf_read_deinit(sc->iamf);
10602 #endif
10603 732 av_freep(&sc->iamf);
10604 }
10605
10606 569 static int mov_read_close(AVFormatContext *s)
10607 {
10608 569 MOVContext *mov = s->priv_data;
10609 int i, j;
10610
10611
2/2
✓ Branch 0 taken 784 times.
✓ Branch 1 taken 569 times.
1353 for (i = 0; i < s->nb_streams; i++) {
10612 784 AVStream *st = s->streams[i];
10613
10614 784 mov_free_stream_context(s, st);
10615 }
10616
10617 569 av_freep(&mov->dv_demux);
10618 569 avformat_free_context(mov->dv_fctx);
10619 569 mov->dv_fctx = NULL;
10620
10621
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 558 times.
569 if (mov->meta_keys) {
10622
2/2
✓ Branch 0 taken 58 times.
✓ Branch 1 taken 11 times.
69 for (i = 1; i < mov->meta_keys_count; i++) {
10623 58 av_freep(&mov->meta_keys[i]);
10624 }
10625 11 av_freep(&mov->meta_keys);
10626 }
10627
10628 569 av_freep(&mov->trex_data);
10629 569 av_freep(&mov->bitrates);
10630
10631
2/2
✓ Branch 0 taken 477 times.
✓ Branch 1 taken 569 times.
1046 for (i = 0; i < mov->frag_index.nb_items; i++) {
10632 477 MOVFragmentStreamInfo *frag = mov->frag_index.item[i].stream_info;
10633
2/2
✓ Branch 0 taken 579 times.
✓ Branch 1 taken 477 times.
1056 for (j = 0; j < mov->frag_index.item[i].nb_stream_info; j++) {
10634 579 mov_free_encryption_index(&frag[j].encryption_index);
10635 }
10636 477 av_freep(&mov->frag_index.item[i].stream_info);
10637 }
10638 569 av_freep(&mov->frag_index.item);
10639
10640 569 av_freep(&mov->aes_decrypt);
10641 569 av_freep(&mov->chapter_tracks);
10642
2/2
✓ Branch 0 taken 57 times.
✓ Branch 1 taken 569 times.
626 for (i = 0; i < mov->nb_heif_item; i++) {
10643
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 57 times.
57 if (!mov->heif_item[i])
10644 continue;
10645 57 av_freep(&mov->heif_item[i]->name);
10646 57 av_freep(&mov->heif_item[i]->iref_list);
10647 57 av_freep(&mov->heif_item[i]->icc_profile);
10648 57 av_freep(&mov->heif_item[i]);
10649 }
10650 569 av_freep(&mov->heif_item);
10651
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 569 times.
578 for (i = 0; i < mov->nb_heif_grid; i++) {
10652 9 av_freep(&mov->heif_grid[i].tile_id_list);
10653 9 av_freep(&mov->heif_grid[i].tile_idx_list);
10654 9 av_freep(&mov->heif_grid[i].tile_item_list);
10655 }
10656 569 av_freep(&mov->heif_grid);
10657
10658 569 return 0;
10659 }
10660
10661 19 static int tmcd_is_referenced(AVFormatContext *s, int tmcd_id)
10662 {
10663 int i;
10664
10665
1/2
✓ Branch 0 taken 19 times.
✗ Branch 1 not taken.
19 for (i = 0; i < s->nb_streams; i++) {
10666 19 AVStream *st = s->streams[i];
10667 19 MOVStreamContext *sc = st->priv_data;
10668 19 MovTref *tag = mov_find_tref_tag(sc, MKTAG('t','m','c','d'));
10669
10670
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 19 times.
19 if (!tag)
10671 continue;
10672
1/2
✓ Branch 1 taken 19 times.
✗ Branch 2 not taken.
19 if (mov_find_tref_id(tag, tmcd_id))
10673 19 return 1;
10674 }
10675 return 0;
10676 }
10677
10678 /* look for a tmcd track not referenced by any video track, and export it globally */
10679 569 static void export_orphan_timecode(AVFormatContext *s)
10680 {
10681 int i;
10682
10683
2/2
✓ Branch 0 taken 784 times.
✓ Branch 1 taken 569 times.
1353 for (i = 0; i < s->nb_streams; i++) {
10684 784 AVStream *st = s->streams[i];
10685
10686
3/4
✓ Branch 0 taken 19 times.
✓ Branch 1 taken 765 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 19 times.
803 if (st->codecpar->codec_tag == MKTAG('t','m','c','d') &&
10687 19 !tmcd_is_referenced(s, st->id)) {
10688 AVDictionaryEntry *tcr = av_dict_get(st->metadata, "timecode", NULL, 0);
10689 if (tcr) {
10690 av_dict_set(&s->metadata, "timecode", tcr->value, 0);
10691 break;
10692 }
10693 }
10694 }
10695 569 }
10696
10697 3 static int read_tfra(MOVContext *mov, AVIOContext *f)
10698 {
10699 int version, fieldlength, i, j;
10700 3 int64_t pos = avio_tell(f);
10701 3 uint32_t size = avio_rb32(f);
10702 unsigned track_id, item_count;
10703
10704
2/2
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 2 times.
3 if (avio_rb32(f) != MKBETAG('t', 'f', 'r', 'a')) {
10705 1 return 1;
10706 }
10707 2 av_log(mov->fc, AV_LOG_VERBOSE, "found tfra\n");
10708
10709 2 version = avio_r8(f);
10710 2 avio_rb24(f);
10711 2 track_id = avio_rb32(f);
10712 2 fieldlength = avio_rb32(f);
10713 2 item_count = avio_rb32(f);
10714
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 2 times.
8 for (i = 0; i < item_count; i++) {
10715 int64_t time, offset;
10716 int index;
10717 MOVFragmentStreamInfo * frag_stream_info;
10718
10719
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
6 if (avio_feof(f)) {
10720 return AVERROR_INVALIDDATA;
10721 }
10722
10723
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (version == 1) {
10724 time = avio_rb64(f);
10725 offset = avio_rb64(f);
10726 } else {
10727 6 time = avio_rb32(f);
10728 6 offset = avio_rb32(f);
10729 }
10730
10731 // The first sample of each stream in a fragment is always a random
10732 // access sample. So it's entry in the tfra can be used as the
10733 // initial PTS of the fragment.
10734 6 index = update_frag_index(mov, offset);
10735 6 frag_stream_info = get_frag_stream_info(&mov->frag_index, index, track_id);
10736
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 if (frag_stream_info &&
10737
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 frag_stream_info->first_tfra_pts == AV_NOPTS_VALUE)
10738 6 frag_stream_info->first_tfra_pts = time;
10739
10740
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 6 times.
12 for (j = 0; j < ((fieldlength >> 4) & 3) + 1; j++)
10741 6 avio_r8(f);
10742
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 6 times.
12 for (j = 0; j < ((fieldlength >> 2) & 3) + 1; j++)
10743 6 avio_r8(f);
10744
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 6 times.
12 for (j = 0; j < ((fieldlength >> 0) & 3) + 1; j++)
10745 6 avio_r8(f);
10746 }
10747
10748 2 avio_seek(f, pos + size, SEEK_SET);
10749 2 return 0;
10750 }
10751
10752 1 static int mov_read_mfra(MOVContext *c, AVIOContext *f)
10753 {
10754 1 int64_t stream_size = avio_size(f);
10755 1 int64_t original_pos = avio_tell(f);
10756 int64_t seek_ret;
10757 1 int ret = -1;
10758
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 if ((seek_ret = avio_seek(f, stream_size - 4, SEEK_SET)) < 0) {
10759 ret = seek_ret;
10760 goto fail;
10761 }
10762 1 c->mfra_size = avio_rb32(f);
10763 1 c->have_read_mfra_size = 1;
10764
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
1 if (!c->mfra_size || c->mfra_size > stream_size) {
10765 av_log(c->fc, AV_LOG_DEBUG, "doesn't look like mfra (unreasonable size)\n");
10766 goto fail;
10767 }
10768
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 if ((seek_ret = avio_seek(f, -((int64_t) c->mfra_size), SEEK_CUR)) < 0) {
10769 ret = seek_ret;
10770 goto fail;
10771 }
10772
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 if (avio_rb32(f) != c->mfra_size) {
10773 av_log(c->fc, AV_LOG_DEBUG, "doesn't look like mfra (size mismatch)\n");
10774 goto fail;
10775 }
10776
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 if (avio_rb32(f) != MKBETAG('m', 'f', 'r', 'a')) {
10777 av_log(c->fc, AV_LOG_DEBUG, "doesn't look like mfra (tag mismatch)\n");
10778 goto fail;
10779 }
10780 1 av_log(c->fc, AV_LOG_VERBOSE, "stream has mfra\n");
10781 do {
10782 3 ret = read_tfra(c, f);
10783
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (ret < 0)
10784 goto fail;
10785
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 times.
3 } while (!ret);
10786 1 ret = 0;
10787 1 c->frag_index.complete = 1;
10788 1 fail:
10789 1 seek_ret = avio_seek(f, original_pos, SEEK_SET);
10790
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (seek_ret < 0) {
10791 av_log(c->fc, AV_LOG_ERROR,
10792 "failed to seek back after looking for mfra\n");
10793 ret = seek_ret;
10794 }
10795 1 return ret;
10796 }
10797
10798 static int set_icc_profile_from_item(AVPacketSideData **coded_side_data, int *nb_coded_side_data,
10799 const HEIFItem *item)
10800 {
10801 AVPacketSideData *sd = av_packet_side_data_new(coded_side_data, nb_coded_side_data,
10802 AV_PKT_DATA_ICC_PROFILE,
10803 item->icc_profile_size, 0);
10804 if (!sd)
10805 return AVERROR(ENOMEM);
10806
10807 memcpy(sd->data, item->icc_profile, item->icc_profile_size);
10808
10809 return 0;
10810 }
10811
10812 6 static int set_display_matrix_from_item(AVPacketSideData **coded_side_data, int *nb_coded_side_data,
10813 const HEIFItem *item)
10814 {
10815 int32_t *matrix;
10816 6 AVPacketSideData *sd = av_packet_side_data_new(coded_side_data,
10817 nb_coded_side_data,
10818 AV_PKT_DATA_DISPLAYMATRIX,
10819 9 * sizeof(*matrix), 0);
10820
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (!sd)
10821 return AVERROR(ENOMEM);
10822
10823 6 matrix = (int32_t*)sd->data;
10824 /* rotation is in the counter-clockwise direction whereas
10825 * av_display_rotation_set() expects its argument to be
10826 * oriented clockwise, so we need to negate it. */
10827 6 av_display_rotation_set(matrix, -item->rotation);
10828 6 av_display_matrix_flip(matrix, item->hflip, item->vflip);
10829
10830 6 return 0;
10831 }
10832
10833 5 static int read_image_grid(AVFormatContext *s, const HEIFGrid *grid,
10834 AVStreamGroupTileGrid *tile_grid)
10835 {
10836 5 MOVContext *c = s->priv_data;
10837 5 const HEIFItem *item = grid->item;
10838 5 int64_t coded_width = 0, coded_height = 0;
10839 5 int64_t offset = 0, pos = avio_tell(s->pb);
10840 5 int64_t x = 0, y = 0;
10841 5 int i = 0;
10842 int tile_rows, tile_cols;
10843 int flags, size;
10844
10845
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (!(s->pb->seekable & AVIO_SEEKABLE_NORMAL)) {
10846 av_log(c->fc, AV_LOG_INFO, "grid box with non seekable input\n");
10847 return AVERROR_PATCHWELCOME;
10848 }
10849
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 if (item->is_idat_relative) {
10850
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (!c->idat_offset) {
10851 av_log(c->fc, AV_LOG_ERROR, "missing idat box required by the image grid\n");
10852 return AVERROR_INVALIDDATA;
10853 }
10854 5 offset = c->idat_offset;
10855 }
10856
10857
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (offset > INT64_MAX - item->extent_offset)
10858 return AVERROR_INVALIDDATA;
10859
10860 5 avio_seek(s->pb, item->extent_offset + offset, SEEK_SET);
10861
10862 5 avio_r8(s->pb); /* version */
10863 5 flags = avio_r8(s->pb);
10864
10865 5 tile_rows = avio_r8(s->pb) + 1;
10866 5 tile_cols = avio_r8(s->pb) + 1;
10867 /* actual width and height of output image */
10868
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 tile_grid->width = (flags & 1) ? avio_rb32(s->pb) : avio_rb16(s->pb);
10869
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 tile_grid->height = (flags & 1) ? avio_rb32(s->pb) : avio_rb16(s->pb);
10870
10871 5 av_log(c->fc, AV_LOG_TRACE, "grid: grid_rows %d grid_cols %d output_width %d output_height %d\n",
10872 tile_rows, tile_cols, tile_grid->width, tile_grid->height);
10873
10874 5 avio_seek(s->pb, pos, SEEK_SET);
10875
10876 5 size = tile_rows * tile_cols;
10877 5 tile_grid->nb_tiles = grid->nb_tiles;
10878
10879
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (tile_grid->nb_tiles != size)
10880 return AVERROR_INVALIDDATA;
10881
10882
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 5 times.
15 for (int i = 0; i < tile_cols; i++)
10883 10 coded_width += grid->tile_item_list[i]->width;
10884
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 5 times.
15 for (int i = 0; i < size; i += tile_cols)
10885 10 coded_height += grid->tile_item_list[i]->height;
10886
10887
2/4
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 5 times.
5 if (coded_width > INT_MAX || coded_height > INT_MAX)
10888 return AVERROR_INVALIDDATA;
10889
10890 5 tile_grid->coded_width = coded_width;
10891 5 tile_grid->coded_height = coded_height;
10892
10893 5 tile_grid->offsets = av_calloc(tile_grid->nb_tiles, sizeof(*tile_grid->offsets));
10894
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (!tile_grid->offsets)
10895 return AVERROR(ENOMEM);
10896
10897
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 5 times.
15 while (y < tile_grid->coded_height) {
10898 10 int left_col = i;
10899
10900
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 10 times.
30 while (x < tile_grid->coded_width) {
10901
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 20 times.
20 if (i == tile_grid->nb_tiles)
10902 return AVERROR_INVALIDDATA;
10903
10904 20 tile_grid->offsets[i].idx = grid->tile_idx_list[i];
10905 20 tile_grid->offsets[i].horizontal = x;
10906 20 tile_grid->offsets[i].vertical = y;
10907
10908 20 x += grid->tile_item_list[i++]->width;
10909 }
10910
10911
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (x > tile_grid->coded_width) {
10912 av_log(c->fc, AV_LOG_ERROR, "Non uniform HEIF tiles\n");
10913 return AVERROR_INVALIDDATA;
10914 }
10915
10916 10 x = 0;
10917 10 y += grid->tile_item_list[left_col]->height;
10918 }
10919
10920
2/4
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 5 times.
5 if (y > tile_grid->coded_height || i != tile_grid->nb_tiles) {
10921 av_log(c->fc, AV_LOG_ERROR, "Non uniform HEIF tiles\n");
10922 return AVERROR_INVALIDDATA;
10923 }
10924
10925 5 return 0;
10926 }
10927
10928 4 static int read_image_iovl(AVFormatContext *s, const HEIFGrid *grid,
10929 AVStreamGroupTileGrid *tile_grid)
10930 {
10931 4 MOVContext *c = s->priv_data;
10932 4 const HEIFItem *item = grid->item;
10933 uint16_t canvas_fill_value[4];
10934 4 int64_t offset = 0, pos = avio_tell(s->pb);
10935 4 int ret = 0, flags;
10936
10937
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!(s->pb->seekable & AVIO_SEEKABLE_NORMAL)) {
10938 av_log(c->fc, AV_LOG_INFO, "iovl box with non seekable input\n");
10939 return AVERROR_PATCHWELCOME;
10940 }
10941
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if (item->is_idat_relative) {
10942
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!c->idat_offset) {
10943 av_log(c->fc, AV_LOG_ERROR, "missing idat box required by the image overlay\n");
10944 return AVERROR_INVALIDDATA;
10945 }
10946 4 offset = c->idat_offset;
10947 }
10948
10949
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (offset > INT64_MAX - item->extent_offset)
10950 return AVERROR_INVALIDDATA;
10951
10952 4 avio_seek(s->pb, item->extent_offset + offset, SEEK_SET);
10953
10954 4 avio_r8(s->pb); /* version */
10955 4 flags = avio_r8(s->pb);
10956
10957
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 4 times.
20 for (int i = 0; i < 4; i++)
10958 16 canvas_fill_value[i] = avio_rb16(s->pb);
10959 4 av_log(c->fc, AV_LOG_TRACE, "iovl: canvas_fill_value { %u, %u, %u, %u }\n",
10960 4 canvas_fill_value[0], canvas_fill_value[1],
10961 4 canvas_fill_value[2], canvas_fill_value[3]);
10962
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 4 times.
20 for (int i = 0; i < 4; i++)
10963 16 tile_grid->background[i] = canvas_fill_value[i];
10964
10965 /* actual width and height of output image */
10966 4 tile_grid->width =
10967
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 tile_grid->coded_width = (flags & 1) ? avio_rb32(s->pb) : avio_rb16(s->pb);
10968 4 tile_grid->height =
10969
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 tile_grid->coded_height = (flags & 1) ? avio_rb32(s->pb) : avio_rb16(s->pb);
10970
10971 4 av_log(c->fc, AV_LOG_TRACE, "iovl: output_width %d, output_height %d\n",
10972 tile_grid->width, tile_grid->height);
10973
10974 4 tile_grid->nb_tiles = grid->nb_tiles;
10975 4 tile_grid->offsets = av_malloc_array(tile_grid->nb_tiles, sizeof(*tile_grid->offsets));
10976
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!tile_grid->offsets) {
10977 ret = AVERROR(ENOMEM);
10978 goto fail;
10979 }
10980
10981
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 4 times.
12 for (int i = 0; i < tile_grid->nb_tiles; i++) {
10982 8 tile_grid->offsets[i].idx = grid->tile_idx_list[i];
10983
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 tile_grid->offsets[i].horizontal = (flags & 1) ? avio_rb32(s->pb) : avio_rb16(s->pb);
10984
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 tile_grid->offsets[i].vertical = (flags & 1) ? avio_rb32(s->pb) : avio_rb16(s->pb);
10985 8 av_log(c->fc, AV_LOG_TRACE, "iovl: stream_idx[%d] %u, "
10986 "horizontal_offset[%d] %d, vertical_offset[%d] %d\n",
10987 8 i, tile_grid->offsets[i].idx,
10988 8 i, tile_grid->offsets[i].horizontal, i, tile_grid->offsets[i].vertical);
10989 }
10990
10991 4 fail:
10992 4 avio_seek(s->pb, pos, SEEK_SET);
10993
10994 4 return ret;
10995 }
10996
10997 2 static int mov_parse_exif_item(AVFormatContext *s,
10998 AVPacketSideData **coded_side_data, int *nb_coded_side_data,
10999 const HEIFItem *ref)
11000 {
11001 2 MOVContext *c = s->priv_data;
11002 AVPacketSideData *sd;
11003 2 AVExifMetadata ifd = { 0 };
11004 AVBufferRef *buf;
11005 2 int64_t offset = 0, pos = avio_tell(s->pb);
11006 2 unsigned orientation_id = av_exif_get_tag_id("Orientation");
11007 int err;
11008
11009
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!(s->pb->seekable & AVIO_SEEKABLE_NORMAL)) {
11010 av_log(c->fc, AV_LOG_WARNING, "Exif metadata with non seekable input\n");
11011 return AVERROR_PATCHWELCOME;
11012 }
11013
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (ref->is_idat_relative) {
11014 if (!c->idat_offset) {
11015 av_log(c->fc, AV_LOG_ERROR, "missing idat box required by the Exif metadata\n");
11016 return AVERROR_INVALIDDATA;
11017 }
11018 offset = c->idat_offset;
11019 }
11020
11021 2 buf = av_buffer_alloc(ref->extent_length);
11022
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!buf)
11023 return AVERROR(ENOMEM);
11024
11025
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (offset > INT64_MAX - ref->extent_offset) {
11026 err = AVERROR(ENOMEM);
11027 goto fail;
11028 }
11029
11030 2 avio_seek(s->pb, ref->extent_offset + offset, SEEK_SET);
11031 2 err = avio_read(s->pb, buf->data, ref->extent_length);
11032
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (err != ref->extent_length) {
11033 if (err > 0)
11034 err = AVERROR_INVALIDDATA;
11035 goto fail;
11036 }
11037
11038 // HEIF spec states that Exif metadata is informative. The irot item property is
11039 // the normative source of rotation information. So we remove any Orientation tag
11040 // present in the Exif buffer.
11041 2 err = av_exif_parse_buffer(s, buf->data, ref->extent_length, &ifd, AV_EXIF_T_OFF);
11042
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (err < 0) {
11043 av_log(s, AV_LOG_ERROR, "Unable to parse Exif metadata\n");
11044 goto fail;
11045 }
11046
11047 2 err = av_exif_remove_entry(s, &ifd, orientation_id, 0);
11048
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (err < 0)
11049 goto fail;
11050
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 else if (!err)
11051 goto finish;
11052
11053 2 av_buffer_unref(&buf);
11054 2 err = av_exif_write(s, &ifd, &buf, AV_EXIF_T_OFF);
11055
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (err < 0)
11056 goto fail;
11057
11058 2 finish:
11059 2 offset = AV_RB32(buf->data) + 4;
11060
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (offset >= buf->size) {
11061 err = AVERROR_INVALIDDATA;
11062 goto fail;
11063 }
11064 2 sd = av_packet_side_data_new(coded_side_data, nb_coded_side_data,
11065 2 AV_PKT_DATA_EXIF, buf->size - offset, 0);
11066
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!sd) {
11067 err = AVERROR(ENOMEM);
11068 goto fail;
11069 }
11070 2 memcpy(sd->data, buf->data + offset, buf->size - offset);
11071
11072 2 err = 0;
11073 2 fail:
11074 2 av_buffer_unref(&buf);
11075 2 av_exif_free(&ifd);
11076 2 avio_seek(s->pb, pos, SEEK_SET);
11077
11078 2 return err;
11079 }
11080
11081 9 static int mov_parse_tiles(AVFormatContext *s)
11082 {
11083 9 MOVContext *mov = s->priv_data;
11084
11085
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 9 times.
18 for (int i = 0; i < mov->nb_heif_grid; i++) {
11086 9 AVStreamGroup *stg = avformat_stream_group_create(s, AV_STREAM_GROUP_PARAMS_TILE_GRID, NULL);
11087 AVStreamGroupTileGrid *tile_grid;
11088 9 const HEIFGrid *grid = &mov->heif_grid[i];
11089 9 int err, loop = 1;
11090
11091
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if (!stg)
11092 return AVERROR(ENOMEM);
11093
11094 9 stg->id = grid->item->item_id;
11095 9 tile_grid = stg->params.tile_grid;
11096
11097
2/2
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 9 times.
37 for (int j = 0; j < grid->nb_tiles; j++) {
11098 28 int tile_id = grid->tile_id_list[j];
11099 int k;
11100
11101
1/2
✓ Branch 0 taken 60 times.
✗ Branch 1 not taken.
60 for (k = 0; k < mov->nb_heif_item; k++) {
11102 60 HEIFItem *item = mov->heif_item[k];
11103 AVStream *st;
11104
11105
3/4
✓ Branch 0 taken 60 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 32 times.
✓ Branch 3 taken 28 times.
60 if (!item || item->item_id != tile_id)
11106 32 continue;
11107 28 st = item->st;
11108
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
28 if (!st) {
11109 av_log(s, AV_LOG_WARNING, "HEIF item id %d from grid id %d doesn't "
11110 "reference a stream\n",
11111 tile_id, grid->item->item_id);
11112 ff_remove_stream_group(s, stg);
11113 loop = 0;
11114 break;
11115 }
11116
11117 28 grid->tile_item_list[j] = item;
11118 28 grid->tile_idx_list[j] = stg->nb_streams;
11119
11120 28 err = avformat_stream_group_add_stream(stg, st);
11121
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 26 times.
28 if (err < 0) {
11122 int l;
11123
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (err != AVERROR(EEXIST))
11124 return err;
11125
11126
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 for (l = 0; l < stg->nb_streams; l++)
11127
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (stg->streams[l]->index == st->index)
11128 2 break;
11129
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 av_assert0(l < stg->nb_streams);
11130 2 grid->tile_idx_list[j] = l;
11131 }
11132
11133
2/2
✓ Branch 0 taken 22 times.
✓ Branch 1 taken 6 times.
28 if (item->item_id != mov->primary_item_id)
11134 22 st->disposition |= AV_DISPOSITION_DEPENDENT;
11135 28 break;
11136 }
11137
11138
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
28 if (k == mov->nb_heif_item) {
11139 av_assert0(loop);
11140 av_log(s, AV_LOG_WARNING, "HEIF item id %d referenced by grid id %d doesn't "
11141 "exist\n",
11142 tile_id, grid->item->item_id);
11143 ff_remove_stream_group(s, stg);
11144 loop = 0;
11145 }
11146
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
28 if (!loop)
11147 break;
11148 }
11149
11150
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if (!loop)
11151 continue;
11152
11153
2/3
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
9 switch (grid->item->type) {
11154 5 case MKTAG('g','r','i','d'):
11155 5 err = read_image_grid(s, grid, tile_grid);
11156 5 break;
11157 4 case MKTAG('i','o','v','l'):
11158 4 err = read_image_iovl(s, grid, tile_grid);
11159 4 break;
11160 default:
11161 av_assert0(0);
11162 }
11163
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if (err < 0)
11164 return err;
11165
11166
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 for (int j = 0; j < grid->item->nb_iref_list; j++) {
11167 HEIFItem *ref = get_heif_item(mov, grid->item->iref_list[j].item_id);
11168
11169 av_assert0(ref);
11170 switch(ref->type) {
11171 case MKTAG('E','x','i','f'):
11172 err = mov_parse_exif_item(s, &tile_grid->coded_side_data,
11173 &tile_grid->nb_coded_side_data, ref);
11174 if (err < 0 && (s->error_recognition & AV_EF_EXPLODE))
11175 return err;
11176 break;
11177 default:
11178 break;
11179 }
11180 }
11181
11182 /* rotation */
11183
3/6
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 9 times.
9 if (grid->item->rotation || grid->item->hflip || grid->item->vflip) {
11184 err = set_display_matrix_from_item(&tile_grid->coded_side_data,
11185 &tile_grid->nb_coded_side_data, grid->item);
11186 if (err < 0)
11187 return err;
11188 }
11189
11190 /* ICC profile */
11191
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if (grid->item->icc_profile_size) {
11192 err = set_icc_profile_from_item(&tile_grid->coded_side_data,
11193 &tile_grid->nb_coded_side_data, grid->item);
11194 if (err < 0)
11195 return err;
11196 }
11197
11198
1/2
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
9 if (grid->item->name)
11199 9 av_dict_set(&stg->metadata, "title", grid->item->name, 0);
11200
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 4 times.
9 if (grid->item->item_id == mov->primary_item_id)
11201 5 stg->disposition |= AV_DISPOSITION_DEFAULT;
11202 }
11203
11204 9 return 0;
11205 }
11206
11207 18 static int mov_parse_heif_items(AVFormatContext *s)
11208 {
11209 18 MOVContext *mov = s->priv_data;
11210 int err;
11211
11212
2/2
✓ Branch 0 taken 57 times.
✓ Branch 1 taken 18 times.
75 for (int i = 0; i < mov->nb_heif_item; i++) {
11213 57 HEIFItem *item = mov->heif_item[i];
11214 MOVStreamContext *sc;
11215 AVStream *st;
11216 57 int64_t offset = 0;
11217
11218
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 57 times.
57 if (!item)
11219 continue;
11220
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 43 times.
57 if (!item->st) {
11221 14 continue;
11222 }
11223
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 43 times.
43 if (item->is_idat_relative) {
11224 if (!mov->idat_offset) {
11225 av_log(s, AV_LOG_ERROR, "Missing idat box for item %d\n", item->item_id);
11226 return AVERROR_INVALIDDATA;
11227 }
11228 offset = mov->idat_offset;
11229 }
11230
11231 43 st = item->st;
11232 43 sc = st->priv_data;
11233 43 st->codecpar->width = item->width;
11234 43 st->codecpar->height = item->height;
11235
11236 43 sc->sample_size = sc->stsz_sample_size = item->extent_length;
11237 43 sc->sample_count = 1;
11238
11239 43 err = sanity_checks(s, sc, st->index);
11240
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 43 times.
43 if (err)
11241 return AVERROR_INVALIDDATA;
11242
11243
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 43 times.
43 if (offset > INT64_MAX - item->extent_offset)
11244 return AVERROR_INVALIDDATA;
11245
11246 43 sc->chunk_offsets[0] = item->extent_offset + offset;
11247
11248
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 30 times.
43 if (item->item_id == mov->primary_item_id)
11249 13 st->disposition |= AV_DISPOSITION_DEFAULT;
11250
11251
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 43 times.
54 for (int j = 0; j < item->nb_iref_list; j++) {
11252 11 HEIFItem *ref = get_heif_item(mov, item->iref_list[j].item_id);
11253
11254
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 av_assert0(ref);
11255
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 9 times.
11 switch(ref->type) {
11256 2 case MKTAG('E','x','i','f'):
11257 2 err = mov_parse_exif_item(s, &st->codecpar->coded_side_data,
11258 2 &st->codecpar->nb_coded_side_data, ref);
11259
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
2 if (err < 0 && (s->error_recognition & AV_EF_EXPLODE))
11260 return err;
11261 2 break;
11262 9 default:
11263 9 break;
11264 }
11265 }
11266
11267
4/6
✓ Branch 0 taken 37 times.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 37 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 37 times.
43 if (item->rotation || item->hflip || item->vflip) {
11268 6 err = set_display_matrix_from_item(&st->codecpar->coded_side_data,
11269 6 &st->codecpar->nb_coded_side_data, item);
11270
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (err < 0)
11271 return err;
11272 }
11273
11274 43 mov_build_index(mov, st);
11275 }
11276
11277
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 9 times.
18 if (mov->nb_heif_grid) {
11278 9 err = mov_parse_tiles(s);
11279
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if (err < 0)
11280 return err;
11281 }
11282
11283 18 return 0;
11284 }
11285
11286 569 static int mov_parse_tmcd_streams(AVFormatContext *s)
11287 {
11288 int err;
11289
11290
2/2
✓ Branch 0 taken 784 times.
✓ Branch 1 taken 569 times.
1353 for (int i = 0; i < s->nb_streams; i++) {
11291 AVStreamGroup *stg;
11292 const AVDictionaryEntry *tcr;
11293 784 AVStream *st = s->streams[i];
11294
11295
2/2
✓ Branch 0 taken 765 times.
✓ Branch 1 taken 19 times.
784 if (st->codecpar->codec_tag != MKTAG('t','m','c','d'))
11296 765 continue;
11297
11298 19 stg = avformat_stream_group_create(s, AV_STREAM_GROUP_PARAMS_TREF, NULL);
11299
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 19 times.
19 if (!stg)
11300 return AVERROR(ENOMEM);
11301
11302 19 stg->id = st->id;
11303 19 tcr = av_dict_get(st->metadata, "timecode", NULL, 0);
11304
11305
2/2
✓ Branch 0 taken 61 times.
✓ Branch 1 taken 19 times.
80 for (int j = 0; j < s->nb_streams; j++) {
11306 61 AVStream *st2 = s->streams[j];
11307 61 MOVStreamContext *sc2 = st2->priv_data;
11308 61 MovTref *tag = mov_find_tref_tag(sc2, MKTAG('t','m','c','d'));
11309
11310
2/2
✓ Branch 0 taken 41 times.
✓ Branch 1 taken 20 times.
61 if (!tag)
11311 41 continue;
11312
11313
2/2
✓ Branch 0 taken 32 times.
✓ Branch 1 taken 20 times.
52 for (int k = 0; k < tag->nb_id; k++) {
11314
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 20 times.
32 if (tag->id[k] != st->id)
11315 12 continue;
11316
11317 20 err = avformat_stream_group_add_stream(stg, st2);
11318
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 20 times.
20 if (err < 0)
11319 return err;
11320
11321
1/2
✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
20 if (tcr)
11322 20 av_dict_set(&st2->metadata, "timecode", tcr->value, AV_DICT_DONT_OVERWRITE);
11323 }
11324 }
11325
11326
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 19 times.
19 if (!stg->nb_streams) {
11327 ff_remove_stream_group(s, stg);
11328 continue;
11329 }
11330
11331 19 err = avformat_stream_group_add_stream(stg, st);
11332
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 19 times.
19 if (err < 0)
11333 return err;
11334
11335 19 stg->params.tref->metadata_index = stg->nb_streams - 1;
11336 }
11337 569 export_orphan_timecode(s);
11338
11339 569 return 0;
11340 }
11341
11342 11 static AVStream *mov_find_reference_track(AVFormatContext *s, AVStream *st,
11343 uint32_t *tref_id, int nb_tref_id, int first_index)
11344 {
11345
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (!nb_tref_id)
11346 return NULL;
11347
11348
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 for (int i = first_index; i < s->nb_streams; i++)
11349
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 for (int j = 0; j < nb_tref_id; j++)
11350
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 if (s->streams[i]->index != st->index &&
11351
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 s->streams[i]->id == tref_id[j])
11352 11 return s->streams[i];
11353
11354 return NULL;
11355 }
11356
11357 569 static int mov_parse_cdsc_and_rndr_streams(AVFormatContext *s)
11358 {
11359 static const uint32_t tref_tags[] = {
11360 MKTAG('c','d','s','c'),
11361 MKTAG('r','n','d','r'),
11362 };
11363
11364 int err;
11365
11366 // Don't try to add a group if there's only one track
11367
2/2
✓ Branch 0 taken 453 times.
✓ Branch 1 taken 116 times.
569 if (s->nb_streams <= 1)
11368 453 return 0;
11369
11370
2/2
✓ Branch 0 taken 331 times.
✓ Branch 1 taken 116 times.
447 for (int i = 0; i < s->nb_streams; i++) {
11371 331 AVStream *st = s->streams[i];
11372 331 MOVStreamContext *sc = st->priv_data;
11373
11374
2/2
✓ Branch 0 taken 662 times.
✓ Branch 1 taken 331 times.
993 for (int c = 0; c < FF_ARRAY_ELEMS(tref_tags); c++) {
11375 AVStreamGroup *stg;
11376 AVStream *st_ref;
11377 662 MovTref *tag = mov_find_tref_tag(sc, tref_tags[c]);
11378
11379
2/2
✓ Branch 0 taken 651 times.
✓ Branch 1 taken 11 times.
662 if (!tag)
11380 651 continue;
11381
11382 11 st_ref = mov_find_reference_track(s, st, tag->id, tag->nb_id, 0);
11383
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (!st_ref) {
11384 int loglevel = (s->error_recognition & AV_EF_EXPLODE) ? AV_LOG_ERROR : AV_LOG_WARNING;
11385 av_log(s, loglevel, "Failed to find referenced stream\n");
11386 if (s->error_recognition & AV_EF_EXPLODE)
11387 return AVERROR_INVALIDDATA;
11388 continue;
11389 }
11390
11391 11 stg = avformat_stream_group_create(s, AV_STREAM_GROUP_PARAMS_TREF, NULL);
11392
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (!stg)
11393 return AVERROR(ENOMEM);
11394
11395 11 stg->id = st_ref->id;
11396
11397 11 err = avformat_stream_group_add_stream(stg, st_ref);
11398
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (err < 0)
11399 return err;
11400
11401 11 err = avformat_stream_group_add_stream(stg, st);
11402
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (err < 0)
11403 return err;
11404
11405 11 stg->params.tref->metadata_index = stg->nb_streams - 1;
11406 }
11407 }
11408
11409 116 return 0;
11410 }
11411
11412 569 static int mov_parse_lcevc_streams(AVFormatContext *s)
11413 {
11414 int err;
11415
11416 // Don't try to add a group if there's only one track
11417
2/2
✓ Branch 0 taken 453 times.
✓ Branch 1 taken 116 times.
569 if (s->nb_streams <= 1)
11418 453 return 0;
11419
11420
2/2
✓ Branch 0 taken 331 times.
✓ Branch 1 taken 116 times.
447 for (int i = 0; i < s->nb_streams; i++) {
11421 AVStreamGroup *stg;
11422 331 AVStream *st = s->streams[i];
11423 AVStream *st_base;
11424 331 MOVStreamContext *sc = st->priv_data;
11425 331 MovTref *tag = mov_find_tref_tag(sc, MKTAG('s','b','a','s'));
11426 331 int j = 0;
11427
11428 /* Find an enhancement stream. */
11429
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 331 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
331 if (st->codecpar->codec_id != AV_CODEC_ID_LCEVC || !tag)
11430 331 continue;
11431
11432 stg = avformat_stream_group_create(s, AV_STREAM_GROUP_PARAMS_LCEVC, NULL);
11433 if (!stg)
11434 return AVERROR(ENOMEM);
11435
11436 stg->id = st->id;
11437 stg->params.layered_video->width = st->codecpar->width;
11438 stg->params.layered_video->height = st->codecpar->height;
11439
11440 while (st_base = mov_find_reference_track(s, st, tag->id, tag->nb_id, j)) {
11441 err = avformat_stream_group_add_stream(stg, st_base);
11442 if (err < 0)
11443 return err;
11444
11445 j = st_base->index + 1;
11446 }
11447 if (!j) {
11448 int loglevel = (s->error_recognition & AV_EF_EXPLODE) ? AV_LOG_ERROR : AV_LOG_WARNING;
11449 av_log(s, loglevel, "Failed to find base stream for LCEVC stream\n");
11450 ff_remove_stream_group(s, stg);
11451 if (s->error_recognition & AV_EF_EXPLODE)
11452 return AVERROR_INVALIDDATA;
11453 continue;
11454 }
11455
11456 err = avformat_stream_group_add_stream(stg, st);
11457 if (err < 0)
11458 return err;
11459
11460 stg->params.layered_video->el_index = stg->nb_streams - 1;
11461 }
11462
11463 116 return 0;
11464 }
11465
11466 569 static int mov_parse_dovi_streams(AVFormatContext *s)
11467 {
11468 int err;
11469
11470
2/2
✓ Branch 0 taken 453 times.
✓ Branch 1 taken 116 times.
569 if (s->nb_streams <= 1)
11471 453 return 0;
11472
11473 /* Identify legacy dual-track Dolby Vision profile 7 carriage per Annex
11474 * C of "Dolby Vision Streams Within the ISO Base Media File Format",
11475 * v2.7.1. The 'vdep' track reference type is shared with depth video
11476 * and multi-view dependencies. The spec-mandated DV-specific sample
11477 * entry combined with the dvcC configuration record disambiguates
11478 * those uses. */
11479
2/2
✓ Branch 0 taken 331 times.
✓ Branch 1 taken 116 times.
447 for (int i = 0; i < s->nb_streams; i++) {
11480 AVStreamGroup *stg;
11481 331 AVStream *st = s->streams[i];
11482 AVStream *st_base;
11483 331 MOVStreamContext *sc = st->priv_data;
11484 331 MovTref *tag = mov_find_tref_tag(sc, MKTAG('v','d','e','p'));
11485 const AVPacketSideData *sd;
11486 const AVDOVIDecoderConfigurationRecord *dovi;
11487
11488
3/4
✓ Branch 0 taken 42 times.
✓ Branch 1 taken 289 times.
✓ Branch 2 taken 42 times.
✗ Branch 3 not taken.
331 if (st->codecpar->codec_id != AV_CODEC_ID_HEVC || !tag)
11489 331 continue;
11490
11491 if (st->codecpar->codec_tag != MKTAG('d','v','h','e') &&
11492 st->codecpar->codec_tag != MKTAG('d','v','h','1'))
11493 continue;
11494
11495 sd = av_packet_side_data_get(st->codecpar->coded_side_data,
11496 st->codecpar->nb_coded_side_data,
11497 AV_PKT_DATA_DOVI_CONF);
11498 if (!sd)
11499 continue;
11500 dovi = (const AVDOVIDecoderConfigurationRecord *)sd->data;
11501
11502 /* EL track of a dual-track stream: rpu_present_flag = 1,
11503 * el_present_flag = 1, bl_present_flag = 0, dv_profile = 7. */
11504 if (dovi->dv_profile != 7 || !dovi->rpu_present_flag ||
11505 !dovi->el_present_flag || dovi->bl_present_flag)
11506 continue;
11507
11508 st_base = mov_find_reference_track(s, st, tag->id, tag->nb_id, 0);
11509 if (!st_base) {
11510 int loglevel = (s->error_recognition & AV_EF_EXPLODE) ? AV_LOG_ERROR : AV_LOG_WARNING;
11511 av_log(s, loglevel, "Failed to find base layer for Dolby Vision EL stream\n");
11512 if (s->error_recognition & AV_EF_EXPLODE)
11513 return AVERROR_INVALIDDATA;
11514 continue;
11515 }
11516
11517 stg = avformat_stream_group_create(s, AV_STREAM_GROUP_PARAMS_DOLBY_VISION, NULL);
11518 if (!stg)
11519 return AVERROR(ENOMEM);
11520
11521 stg->id = st->id;
11522
11523 err = avformat_stream_group_add_stream(stg, st_base);
11524 if (err < 0)
11525 return err;
11526
11527 err = avformat_stream_group_add_stream(stg, st);
11528 if (err < 0)
11529 return err;
11530
11531 stg->params.layered_video->el_index = stg->nb_streams - 1;
11532 stg->params.layered_video->width = st_base->codecpar->width;
11533 stg->params.layered_video->height = st_base->codecpar->height;
11534 }
11535
11536 116 return 0;
11537 }
11538
11539 569 static void fix_stream_ids(AVFormatContext *s)
11540 {
11541 569 int highest_id = 0, lowest_iamf_id = INT_MAX;
11542
11543
2/2
✓ Branch 0 taken 784 times.
✓ Branch 1 taken 569 times.
1353 for (int i = 0; i < s->nb_streams; i++) {
11544 784 const AVStream *st = s->streams[i];
11545 784 const MOVStreamContext *sc = st->priv_data;
11546
2/2
✓ Branch 0 taken 720 times.
✓ Branch 1 taken 64 times.
784 if (!sc->iamf)
11547 720 highest_id = FFMAX(highest_id, st->id);
11548 }
11549
11550
2/2
✓ Branch 0 taken 63 times.
✓ Branch 1 taken 569 times.
632 for (int i = 0; i < s->nb_stream_groups; i++) {
11551 63 AVStreamGroup *stg = s->stream_groups[i];
11552
2/2
✓ Branch 0 taken 51 times.
✓ Branch 1 taken 12 times.
63 if (stg->type != AV_STREAM_GROUP_PARAMS_IAMF_AUDIO_ELEMENT)
11553 51 continue;
11554
2/2
✓ Branch 0 taken 64 times.
✓ Branch 1 taken 12 times.
76 for (int j = 0; j < stg->nb_streams; j++) {
11555 64 AVStream *st = stg->streams[j];
11556 64 lowest_iamf_id = FFMIN(lowest_iamf_id, st->id);
11557 }
11558 }
11559
11560
2/2
✓ Branch 0 taken 561 times.
✓ Branch 1 taken 8 times.
569 if (highest_id < lowest_iamf_id)
11561 561 return;
11562
11563 8 highest_id += !lowest_iamf_id;
11564
4/4
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 2 times.
12 for (int i = 0; highest_id > 1 && i < s->nb_stream_groups; i++) {
11565 4 AVStreamGroup *stg = s->stream_groups[i];
11566
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 if (stg->type != AV_STREAM_GROUP_PARAMS_IAMF_AUDIO_ELEMENT)
11567 2 continue;
11568
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 2 times.
16 for (int j = 0; j < stg->nb_streams; j++) {
11569 14 AVStream *st = stg->streams[j];
11570 14 MOVStreamContext *sc = st->priv_data;
11571 14 st->id += highest_id;
11572 14 sc->iamf_stream_offset = highest_id;
11573 }
11574 }
11575 }
11576
11577 569 static int mov_read_header(AVFormatContext *s)
11578 {
11579 569 MOVContext *mov = s->priv_data;
11580 569 AVIOContext *pb = s->pb;
11581 int j, err;
11582 569 MOVAtom atom = { AV_RL32("root") };
11583 int i;
11584
11585 569 mov->fc = s;
11586 569 mov->trak_index = -1;
11587 569 mov->primary_item_id = -1;
11588 569 mov->cur_item_id = -1;
11589 /* .mov and .mp4 aren't streamable anyway (only progressive download if moov is before mdat) */
11590
2/2
✓ Branch 0 taken 568 times.
✓ Branch 1 taken 1 times.
569 if (pb->seekable & AVIO_SEEKABLE_NORMAL)
11591 568 atom.size = avio_size(pb);
11592 else
11593 1 atom.size = INT64_MAX;
11594
11595 /* check MOV header */
11596 do {
11597
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 569 times.
569 if (mov->moov_retry)
11598 avio_seek(pb, 0, SEEK_SET);
11599
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 569 times.
569 if ((err = mov_read_default(mov, pb, atom)) < 0) {
11600 av_log(s, AV_LOG_ERROR, "error reading header\n");
11601 return err;
11602 }
11603 1137 } while ((pb->seekable & AVIO_SEEKABLE_NORMAL) &&
11604
6/10
✓ Branch 0 taken 568 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 18 times.
✓ Branch 3 taken 550 times.
✓ Branch 4 taken 18 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 18 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
569 !mov->found_moov && (!mov->found_iloc || !mov->found_iinf) && !mov->moov_retry++);
11605
3/6
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 551 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 18 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
569 if (!mov->found_moov && !mov->found_iloc && !mov->found_iinf) {
11606 av_log(s, AV_LOG_ERROR, "moov atom not found\n");
11607 return AVERROR_INVALIDDATA;
11608 }
11609 569 av_log(mov->fc, AV_LOG_TRACE, "on_parse_exit_offset=%"PRId64"\n", avio_tell(pb));
11610
11611
3/4
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 551 times.
✓ Branch 2 taken 18 times.
✗ Branch 3 not taken.
569 if (mov->found_iloc && mov->found_iinf) {
11612 18 err = mov_parse_heif_items(s);
11613
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (err < 0)
11614 return err;
11615 }
11616 // prevent iloc and iinf boxes from being parsed while reading packets.
11617 // this is needed because an iinf box may have been parsed but ignored
11618 // for having old infe boxes which create no streams.
11619 569 mov->found_iloc = mov->found_iinf = 1;
11620
11621
2/2
✓ Branch 0 taken 568 times.
✓ Branch 1 taken 1 times.
569 if (pb->seekable & AVIO_SEEKABLE_NORMAL) {
11622
3/4
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 566 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
568 if (mov->nb_chapter_tracks > 0 && !mov->ignore_chapters)
11623 2 mov_read_chapters(s);
11624
2/2
✓ Branch 0 taken 783 times.
✓ Branch 1 taken 568 times.
1351 for (i = 0; i < s->nb_streams; i++)
11625
2/2
✓ Branch 0 taken 19 times.
✓ Branch 1 taken 764 times.
783 if (s->streams[i]->codecpar->codec_tag == AV_RL32("tmcd")) {
11626 19 mov_read_timecode_track(s, s->streams[i]);
11627
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 764 times.
764 } else if (s->streams[i]->codecpar->codec_tag == AV_RL32("rtmd")) {
11628 mov_read_rtmd_track(s, s->streams[i]);
11629 }
11630 }
11631
11632 /* Create metadata stream groups. */
11633 569 err = mov_parse_cdsc_and_rndr_streams(s);
11634
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 569 times.
569 if (err < 0)
11635 return err;
11636
11637 /* copy timecode metadata from tmcd tracks to the related video streams */
11638 569 err = mov_parse_tmcd_streams(s);
11639
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 569 times.
569 if (err < 0)
11640 return err;
11641
11642 /* Create LCEVC stream groups. */
11643 569 err = mov_parse_lcevc_streams(s);
11644
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 569 times.
569 if (err < 0)
11645 return err;
11646
11647 /* Create Dolby Vision Profile 7 stream groups. */
11648 569 err = mov_parse_dovi_streams(s);
11649
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 569 times.
569 if (err < 0)
11650 return err;
11651
11652
2/2
✓ Branch 0 taken 784 times.
✓ Branch 1 taken 569 times.
1353 for (i = 0; i < s->nb_streams; i++) {
11653 784 AVStream *st = s->streams[i];
11654 784 FFStream *const sti = ffstream(st);
11655 784 MOVStreamContext *sc = st->priv_data;
11656 784 uint32_t dvdsub_clut[FF_DVDCLUT_CLUT_LEN] = {0};
11657 784 fix_timescale(mov, sc);
11658
11659 /* Set the primary extradata based on the first Sample if it doesn't reference the first stsd entry. */
11660
6/6
✓ Branch 0 taken 739 times.
✓ Branch 1 taken 45 times.
✓ Branch 2 taken 696 times.
✓ Branch 3 taken 43 times.
✓ Branch 4 taken 632 times.
✓ Branch 5 taken 64 times.
784 if (sc->stsc_count && sc->extradata_size && !sc->iamf &&
11661
3/4
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 629 times.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
632 sc->stsc_data[0].id > 1 && sc->stsc_data[0].id <= sc->stsd_count) {
11662 3 sc->last_stsd_index = sc->stsc_data[0].id - 1;
11663 3 av_freep(&st->codecpar->extradata);
11664 3 st->codecpar->extradata_size = sc->extradata_size[sc->last_stsd_index];
11665
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if (sc->extradata_size[sc->last_stsd_index]) {
11666 3 st->codecpar->extradata = av_mallocz(sc->extradata_size[sc->last_stsd_index] + AV_INPUT_BUFFER_PADDING_SIZE);
11667
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!st->codecpar->extradata)
11668 return AVERROR(ENOMEM);
11669 3 memcpy(st->codecpar->extradata, sc->extradata[sc->last_stsd_index], sc->extradata_size[sc->last_stsd_index]);
11670 }
11671 }
11672
11673
2/2
✓ Branch 0 taken 331 times.
✓ Branch 1 taken 453 times.
784 if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO &&
11674
2/2
✓ Branch 0 taken 144 times.
✓ Branch 1 taken 187 times.
331 st->codecpar->codec_id == AV_CODEC_ID_AAC) {
11675 144 sti->skip_samples = st->codecpar->initial_padding;
11676 }
11677
5/6
✓ Branch 0 taken 396 times.
✓ Branch 1 taken 388 times.
✓ Branch 2 taken 337 times.
✓ Branch 3 taken 59 times.
✓ Branch 4 taken 337 times.
✗ Branch 5 not taken.
784 if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && sc->nb_frames_for_fps > 0 && sc->duration_for_fps > 0)
11678 337 av_reduce(&st->avg_frame_rate.num, &st->avg_frame_rate.den,
11679 337 sc->time_scale*(int64_t)sc->nb_frames_for_fps, sc->duration_for_fps, INT_MAX);
11680
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 772 times.
784 if (st->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE) {
11681
3/4
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
12 if (st->codecpar->width <= 0 || st->codecpar->height <= 0) {
11682 8 st->codecpar->width = sc->width;
11683 8 st->codecpar->height = sc->height;
11684 }
11685
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (st->codecpar->codec_id == AV_CODEC_ID_DVD_SUBTITLE &&
11686 st->codecpar->extradata_size == FF_DVDCLUT_CLUT_SIZE) {
11687
11688 for (j = 0; j < FF_DVDCLUT_CLUT_LEN; j++)
11689 dvdsub_clut[j] = AV_RB32(st->codecpar->extradata + j * 4);
11690
11691 err = ff_dvdclut_yuv_to_rgb(dvdsub_clut, FF_DVDCLUT_CLUT_SIZE);
11692 if (err < 0)
11693 return err;
11694
11695 av_freep(&st->codecpar->extradata);
11696 st->codecpar->extradata_size = 0;
11697
11698 err = ff_dvdclut_palette_extradata_cat(dvdsub_clut, FF_DVDCLUT_CLUT_SIZE,
11699 st->codecpar);
11700 if (err < 0)
11701 return err;
11702 }
11703 }
11704
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 783 times.
784 if (mov->handbrake_version &&
11705
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 mov->handbrake_version <= 1000000*0 + 1000*10 + 2 && // 0.10.2
11706 st->codecpar->codec_id == AV_CODEC_ID_MP3) {
11707 av_log(s, AV_LOG_VERBOSE, "Forcing full parsing for mp3 stream\n");
11708 sti->need_parsing = AVSTREAM_PARSE_FULL;
11709 }
11710 }
11711
11712
3/4
✓ Branch 0 taken 550 times.
✓ Branch 1 taken 19 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 550 times.
569 if (mov->trex_data || mov->use_mfra_for > 0) {
11713
2/2
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 19 times.
47 for (i = 0; i < s->nb_streams; i++) {
11714 28 AVStream *st = s->streams[i];
11715 28 MOVStreamContext *sc = st->priv_data;
11716
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 4 times.
28 if (sc->duration_for_fps > 0) {
11717 /* Akin to sc->data_size * 8 * sc->time_scale / sc->duration_for_fps but accounting for overflows. */
11718 24 st->codecpar->bit_rate = av_rescale(sc->data_size, ((int64_t) sc->time_scale) * 8, sc->duration_for_fps);
11719
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 24 times.
24 if (st->codecpar->bit_rate == INT64_MIN) {
11720 av_log(s, AV_LOG_WARNING, "Overflow during bit rate calculation %"PRId64" * 8 * %d\n",
11721 sc->data_size, sc->time_scale);
11722 st->codecpar->bit_rate = 0;
11723 if (s->error_recognition & AV_EF_EXPLODE)
11724 return AVERROR_INVALIDDATA;
11725 }
11726 }
11727 }
11728 }
11729
11730
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 569 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
569 for (i = 0; i < mov->bitrates_count && i < s->nb_streams; i++) {
11731 if (mov->bitrates[i]) {
11732 s->streams[i]->codecpar->bit_rate = mov->bitrates[i];
11733 }
11734 }
11735
11736 569 ff_rfps_calculate(s);
11737
11738
2/2
✓ Branch 0 taken 784 times.
✓ Branch 1 taken 569 times.
1353 for (i = 0; i < s->nb_streams; i++) {
11739 784 AVStream *st = s->streams[i];
11740 784 MOVStreamContext *sc = st->priv_data;
11741
11742
3/3
✓ Branch 0 taken 331 times.
✓ Branch 1 taken 396 times.
✓ Branch 2 taken 57 times.
784 switch (st->codecpar->codec_type) {
11743 331 case AVMEDIA_TYPE_AUDIO:
11744 331 err = ff_replaygain_export(st, s->metadata);
11745
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 331 times.
331 if (err < 0)
11746 return err;
11747 331 break;
11748 396 case AVMEDIA_TYPE_VIDEO:
11749
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 388 times.
396 if (sc->display_matrix) {
11750
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (!av_packet_side_data_add(&st->codecpar->coded_side_data, &st->codecpar->nb_coded_side_data,
11751 AV_PKT_DATA_DISPLAYMATRIX,
11752 8 (uint8_t*)sc->display_matrix, sizeof(int32_t) * 9, 0))
11753 return AVERROR(ENOMEM);
11754
11755 8 sc->display_matrix = NULL;
11756 }
11757
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 392 times.
396 if (sc->stereo3d) {
11758
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!av_packet_side_data_add(&st->codecpar->coded_side_data, &st->codecpar->nb_coded_side_data,
11759 AV_PKT_DATA_STEREO3D,
11760 4 (uint8_t *)sc->stereo3d, sc->stereo3d_size, 0))
11761 return AVERROR(ENOMEM);
11762
11763 4 sc->stereo3d = NULL;
11764 }
11765
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 392 times.
396 if (sc->spherical) {
11766
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!av_packet_side_data_add(&st->codecpar->coded_side_data, &st->codecpar->nb_coded_side_data,
11767 AV_PKT_DATA_SPHERICAL,
11768 4 (uint8_t *)sc->spherical, sc->spherical_size, 0))
11769 return AVERROR(ENOMEM);
11770
11771 4 sc->spherical = NULL;
11772 }
11773
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 396 times.
396 if (sc->mastering) {
11774 if (!av_packet_side_data_add(&st->codecpar->coded_side_data, &st->codecpar->nb_coded_side_data,
11775 AV_PKT_DATA_MASTERING_DISPLAY_METADATA,
11776 (uint8_t *)sc->mastering, sc->mastering_size, 0))
11777 return AVERROR(ENOMEM);
11778
11779 sc->mastering = NULL;
11780 }
11781
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 396 times.
396 if (sc->coll) {
11782 if (!av_packet_side_data_add(&st->codecpar->coded_side_data, &st->codecpar->nb_coded_side_data,
11783 AV_PKT_DATA_CONTENT_LIGHT_LEVEL,
11784 (uint8_t *)sc->coll, sc->coll_size, 0))
11785 return AVERROR(ENOMEM);
11786
11787 sc->coll = NULL;
11788 }
11789
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 392 times.
396 if (sc->ambient) {
11790
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!av_packet_side_data_add(&st->codecpar->coded_side_data, &st->codecpar->nb_coded_side_data,
11791 AV_PKT_DATA_AMBIENT_VIEWING_ENVIRONMENT,
11792 4 (uint8_t *) sc->ambient, sc->ambient_size, 0))
11793 return AVERROR(ENOMEM);
11794
11795 4 sc->ambient = NULL;
11796 }
11797 396 break;
11798 }
11799 }
11800
11801 569 fix_stream_ids(s);
11802
11803 569 ff_configure_buffers_for_index(s, AV_TIME_BASE);
11804
11805
2/2
✓ Branch 0 taken 477 times.
✓ Branch 1 taken 569 times.
1046 for (i = 0; i < mov->frag_index.nb_items; i++)
11806
2/2
✓ Branch 0 taken 467 times.
✓ Branch 1 taken 10 times.
477 if (mov->frag_index.item[i].moof_offset <= mov->fragment.moof_offset)
11807 467 mov->frag_index.item[i].headers_read = 1;
11808
11809 569 return 0;
11810 }
11811
11812 117240 static AVIndexEntry *mov_find_next_sample(AVFormatContext *s, AVStream **st)
11813 {
11814 117240 AVIndexEntry *sample = NULL;
11815 117240 int64_t best_dts = INT64_MAX;
11816 int i;
11817 117240 MOVContext *mov = s->priv_data;
11818
3/4
✓ Branch 0 taken 117240 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 45 times.
✓ Branch 3 taken 117195 times.
117240 int no_interleave = !mov->interleaved_read || !(s->pb->seekable & AVIO_SEEKABLE_NORMAL);
11819
2/2
✓ Branch 0 taken 151573 times.
✓ Branch 1 taken 117240 times.
268813 for (i = 0; i < s->nb_streams; i++) {
11820 151573 AVStream *avst = s->streams[i];
11821 151573 FFStream *const avsti = ffstream(avst);
11822 151573 MOVStreamContext *msc = avst->priv_data;
11823
4/4
✓ Branch 0 taken 142050 times.
✓ Branch 1 taken 9523 times.
✓ Branch 2 taken 138553 times.
✓ Branch 3 taken 3497 times.
151573 if (msc->pb && msc->current_sample < avsti->nb_index_entries) {
11824 138553 AVIndexEntry *current_sample = &avsti->index_entries[msc->current_sample];
11825 138553 int64_t dts = av_rescale(current_sample->timestamp, AV_TIME_BASE, msc->time_scale);
11826
2/2
✓ Branch 0 taken 123138 times.
✓ Branch 1 taken 15415 times.
138553 uint64_t dtsdiff = best_dts > dts ? best_dts - (uint64_t)dts : ((uint64_t)dts - best_dts);
11827 138553 av_log(s, AV_LOG_TRACE, "stream %d, sample %d, dts %"PRId64"\n", i, msc->current_sample, dts);
11828
3/6
✓ Branch 0 taken 21879 times.
✓ Branch 1 taken 116674 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 21879 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
138553 if (!sample || (no_interleave && current_sample->pos < sample->pos) ||
11829
1/2
✓ Branch 0 taken 21879 times.
✗ Branch 1 not taken.
21879 ((s->pb->seekable & AVIO_SEEKABLE_NORMAL) &&
11830
5/10
✗ Branch 0 not taken.
✓ Branch 1 taken 21879 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 21879 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 21879 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 19681 times.
✓ Branch 9 taken 2198 times.
21879 ((msc->pb != s->pb && dts < best_dts) || (msc->pb == s->pb && dts != AV_NOPTS_VALUE &&
11831
4/4
✓ Branch 0 taken 11521 times.
✓ Branch 1 taken 8160 times.
✓ Branch 2 taken 2198 times.
✓ Branch 3 taken 11521 times.
21879 ((dtsdiff <= AV_TIME_BASE && current_sample->pos < sample->pos) ||
11832
3/4
✓ Branch 0 taken 761 times.
✓ Branch 1 taken 1437 times.
✓ Branch 2 taken 761 times.
✗ Branch 3 not taken.
2198 (dtsdiff > AV_TIME_BASE && dts < best_dts && mov->interleaved_read)))))) {
11833 125595 sample = current_sample;
11834 125595 best_dts = dts;
11835 125595 *st = avst;
11836 }
11837 }
11838 }
11839 117240 return sample;
11840 }
11841
11842 9 static int should_retry(AVIOContext *pb, int error_code) {
11843
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
9 if (error_code == AVERROR_EOF || avio_feof(pb))
11844 9 return 0;
11845
11846 return 1;
11847 }
11848
11849 49 static int mov_switch_root(AVFormatContext *s, int64_t target, int index)
11850 {
11851 int ret;
11852 49 MOVContext *mov = s->priv_data;
11853
11854
3/4
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 48 times.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
49 if (index >= 0 && index < mov->frag_index.nb_items)
11855 1 target = mov->frag_index.item[index].moof_offset;
11856
2/4
✓ Branch 0 taken 49 times.
✗ Branch 1 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 49 times.
49 if (target >= 0 && avio_seek(s->pb, target, SEEK_SET) != target) {
11857 av_log(mov->fc, AV_LOG_ERROR, "root atom offset 0x%"PRIx64": partial file\n", target);
11858 return AVERROR_INVALIDDATA;
11859 }
11860
11861 49 mov->next_root_atom = 0;
11862
4/6
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 48 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 times.
49 if ((index < 0 && target >= 0) || index >= mov->frag_index.nb_items)
11863 48 index = search_frag_moof_offset(&mov->frag_index, target);
11864
3/4
✓ Branch 0 taken 49 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 42 times.
✓ Branch 3 taken 7 times.
49 if (index >= 0 && index < mov->frag_index.nb_items &&
11865
1/2
✓ Branch 0 taken 42 times.
✗ Branch 1 not taken.
42 mov->frag_index.item[index].moof_offset == target) {
11866
2/2
✓ Branch 0 taken 38 times.
✓ Branch 1 taken 4 times.
42 if (index + 1 < mov->frag_index.nb_items)
11867 38 mov->next_root_atom = mov->frag_index.item[index + 1].moof_offset;
11868
2/2
✓ Branch 0 taken 36 times.
✓ Branch 1 taken 6 times.
42 if (mov->frag_index.item[index].headers_read)
11869 36 return 0;
11870 6 mov->frag_index.item[index].headers_read = 1;
11871 }
11872
11873 13 mov->found_mdat = 0;
11874
11875 13 ret = mov_read_default(mov, s->pb, (MOVAtom){ AV_RL32("root"), INT64_MAX });
11876
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 13 times.
13 if (ret < 0)
11877 return ret;
11878
2/2
✓ Branch 1 taken 7 times.
✓ Branch 2 taken 6 times.
13 if (avio_feof(s->pb))
11879 7 return AVERROR_EOF;
11880 6 av_log(s, AV_LOG_TRACE, "read fragments, offset 0x%"PRIx64"\n", avio_tell(s->pb));
11881
11882 6 return 1;
11883 }
11884
11885 16 static int mov_change_extradata(AVStream *st, AVPacket *pkt)
11886 {
11887 16 MOVStreamContext *sc = st->priv_data;
11888 uint8_t *side, *extradata;
11889 int extradata_size;
11890
11891 /* Save the current index. */
11892 16 sc->last_stsd_index = sc->stsc_data[sc->stsc_index].id - 1;
11893
11894 /* Notify the decoder that extradata changed. */
11895 16 extradata_size = sc->extradata_size[sc->last_stsd_index];
11896 16 extradata = sc->extradata[sc->last_stsd_index];
11897
4/6
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 13 times.
✓ Branch 3 taken 3 times.
✓ Branch 4 taken 13 times.
✗ Branch 5 not taken.
16 if (st->discard != AVDISCARD_ALL && extradata_size > 0 && extradata) {
11898 13 side = av_packet_new_side_data(pkt,
11899 AV_PKT_DATA_NEW_EXTRADATA,
11900 extradata_size);
11901
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 13 times.
13 if (!side)
11902 return AVERROR(ENOMEM);
11903 13 memcpy(side, extradata, extradata_size);
11904 }
11905
11906 16 return 0;
11907 }
11908
11909 static int get_eia608_packet(AVIOContext *pb, AVPacket *pkt, int src_size)
11910 {
11911 /* We can't make assumptions about the structure of the payload,
11912 because it may include multiple cdat and cdt2 samples. */
11913 const uint32_t cdat = AV_RB32("cdat");
11914 const uint32_t cdt2 = AV_RB32("cdt2");
11915 int ret, out_size = 0;
11916
11917 /* a valid payload must have size, 4cc, and at least 1 byte pair: */
11918 if (src_size < 10)
11919 return AVERROR_INVALIDDATA;
11920
11921 /* avoid an int overflow: */
11922 if ((src_size - 8) / 2 >= INT_MAX / 3)
11923 return AVERROR_INVALIDDATA;
11924
11925 ret = av_new_packet(pkt, ((src_size - 8) / 2) * 3);
11926 if (ret < 0)
11927 return ret;
11928
11929 /* parse and re-format the c608 payload in one pass. */
11930 while (src_size >= 10) {
11931 const uint32_t atom_size = avio_rb32(pb);
11932 const uint32_t atom_type = avio_rb32(pb);
11933 const uint32_t data_size = atom_size - 8;
11934 const uint8_t cc_field =
11935 atom_type == cdat ? 1 :
11936 atom_type == cdt2 ? 2 :
11937 0;
11938
11939 /* account for bytes consumed for atom size and type. */
11940 src_size -= 8;
11941
11942 /* make sure the data size stays within the buffer boundaries. */
11943 if (data_size < 2 || data_size > src_size) {
11944 ret = AVERROR_INVALIDDATA;
11945 break;
11946 }
11947
11948 /* make sure the data size is consistent with N byte pairs. */
11949 if (data_size % 2 != 0) {
11950 ret = AVERROR_INVALIDDATA;
11951 break;
11952 }
11953
11954 if (!cc_field) {
11955 /* neither cdat or cdt2 ... skip it */
11956 avio_skip(pb, data_size);
11957 src_size -= data_size;
11958 continue;
11959 }
11960
11961 for (uint32_t i = 0; i < data_size; i += 2) {
11962 pkt->data[out_size] = (0x1F << 3) | (1 << 2) | (cc_field - 1);
11963 pkt->data[out_size + 1] = avio_r8(pb);
11964 pkt->data[out_size + 2] = avio_r8(pb);
11965 out_size += 3;
11966 src_size -= 2;
11967 }
11968 }
11969
11970 if (src_size > 0)
11971 /* skip any remaining unread portion of the input payload */
11972 avio_skip(pb, src_size);
11973
11974 av_shrink_packet(pkt, out_size);
11975 return ret;
11976 }
11977
11978 116629 static int mov_finalize_packet(AVFormatContext *s, AVStream *st, AVIndexEntry *sample,
11979 int64_t current_index, AVPacket *pkt)
11980 {
11981 116629 MOVContext *mov = s->priv_data;
11982 116629 MOVStreamContext *sc = st->priv_data;
11983
11984 116629 pkt->stream_index = sc->ffindex;
11985 116629 pkt->dts = sample->timestamp;
11986
2/2
✓ Branch 0 taken 295 times.
✓ Branch 1 taken 116334 times.
116629 if (sample->flags & AVINDEX_DISCARD_FRAME) {
11987 295 pkt->flags |= AV_PKT_FLAG_DISCARD;
11988 }
11989
4/4
✓ Branch 0 taken 96695 times.
✓ Branch 1 taken 19934 times.
✓ Branch 2 taken 96683 times.
✓ Branch 3 taken 12 times.
116629 if (sc->stts_count && sc->tts_index < sc->tts_count)
11990 96683 pkt->duration = sc->tts_data[sc->tts_index].duration;
11991
3/4
✓ Branch 0 taken 4504 times.
✓ Branch 1 taken 112125 times.
✓ Branch 2 taken 4504 times.
✗ Branch 3 not taken.
116629 if (sc->ctts_count && sc->tts_index < sc->tts_count) {
11992 4504 pkt->pts = av_sat_add64(pkt->dts, av_sat_add64(sc->dts_shift, sc->tts_data[sc->tts_index].offset));
11993 } else {
11994
2/2
✓ Branch 0 taken 15870 times.
✓ Branch 1 taken 96255 times.
112125 if (pkt->duration == 0) {
11995 15870 int64_t next_dts = (sc->current_sample < ffstream(st)->nb_index_entries) ?
11996
2/2
✓ Branch 0 taken 15778 times.
✓ Branch 1 taken 92 times.
15870 ffstream(st)->index_entries[sc->current_sample].timestamp : st->duration;
11997
2/2
✓ Branch 0 taken 15824 times.
✓ Branch 1 taken 46 times.
15870 if (next_dts >= pkt->dts)
11998 15824 pkt->duration = next_dts - pkt->dts;
11999 }
12000 112125 pkt->pts = pkt->dts;
12001 }
12002
12003
4/4
✓ Branch 0 taken 98378 times.
✓ Branch 1 taken 18251 times.
✓ Branch 2 taken 98300 times.
✓ Branch 3 taken 78 times.
116629 if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO && !mov->fragment.found_tfhd &&
12004
2/2
✓ Branch 1 taken 227 times.
✓ Branch 2 taken 98073 times.
98300 sc->current_sample >= ffstream(st)->nb_index_entries) {
12005 227 int64_t pts = av_rescale_q(pkt->pts, st->time_base, (AVRational){ 1, st->codecpar->sample_rate });
12006 227 int64_t total = av_rescale_q(st->duration, st->time_base, (AVRational){ 1, st->codecpar->sample_rate });
12007 227 int64_t duration = pkt->duration;
12008
12009
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 225 times.
227 if (st->duration < pkt->pts) {
12010 2 duration = 0;
12011 } else
12012 225 duration = FFMIN(duration, (uint64_t)st->duration - pkt->pts);
12013
12014 227 duration = av_rescale_q(duration, st->time_base, (AVRational){ 1, st->codecpar->sample_rate });
12015
12016
2/2
✓ Branch 1 taken 189 times.
✓ Branch 2 taken 38 times.
227 if (!ffstream(st)->first_discard_sample)
12017 189 ffstream(st)->first_discard_sample = av_sat_add64(pts, duration);
12018
2/2
✓ Branch 1 taken 189 times.
✓ Branch 2 taken 38 times.
227 if (!ffstream(st)->last_discard_sample)
12019 189 ffstream(st)->last_discard_sample = total;
12020 }
12021
12022
4/4
✓ Branch 0 taken 96695 times.
✓ Branch 1 taken 19934 times.
✓ Branch 2 taken 96683 times.
✓ Branch 3 taken 12 times.
116629 if (sc->tts_data && sc->tts_index < sc->tts_count) {
12023 /* update tts context */
12024 96683 sc->tts_sample++;
12025
1/2
✓ Branch 0 taken 96683 times.
✗ Branch 1 not taken.
96683 if (sc->tts_index < sc->tts_count &&
12026
1/2
✓ Branch 0 taken 96683 times.
✗ Branch 1 not taken.
96683 sc->tts_data[sc->tts_index].count == sc->tts_sample) {
12027 96683 sc->tts_index++;
12028 96683 sc->tts_sample = 0;
12029 }
12030 }
12031
12032
4/4
✓ Branch 0 taken 1061 times.
✓ Branch 1 taken 115568 times.
✓ Branch 2 taken 929 times.
✓ Branch 3 taken 132 times.
116629 if (sc->sdtp_data && sc->current_sample <= sc->sdtp_count) {
12033 929 uint8_t sample_flags = sc->sdtp_data[sc->current_sample - 1];
12034 929 uint8_t sample_is_depended_on = (sample_flags >> 2) & 0x3;
12035
2/2
✓ Branch 0 taken 323 times.
✓ Branch 1 taken 606 times.
929 pkt->flags |= sample_is_depended_on == MOV_SAMPLE_DEPENDENCY_NO ? AV_PKT_FLAG_DISPOSABLE : 0;
12036 }
12037 116629 pkt->flags |= sample->flags & AVINDEX_KEYFRAME ? AV_PKT_FLAG_KEY : 0;
12038 116629 pkt->pos = sample->pos;
12039
12040 /* Multiple stsd handling. */
12041
2/2
✓ Branch 0 taken 113254 times.
✓ Branch 1 taken 3375 times.
116629 if (sc->stsc_data) {
12042
1/2
✓ Branch 0 taken 113254 times.
✗ Branch 1 not taken.
113254 if (sc->stsc_data[sc->stsc_index].id > 0 &&
12043
2/2
✓ Branch 0 taken 113211 times.
✓ Branch 1 taken 43 times.
113254 sc->stsc_data[sc->stsc_index].id - 1 < sc->stsd_count &&
12044
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 113195 times.
113211 sc->stsc_data[sc->stsc_index].id - 1 != sc->last_stsd_index) {
12045 16 int ret = mov_change_extradata(st, pkt);
12046
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 if (ret < 0)
12047 return ret;
12048 }
12049
12050 /* Update the stsc index for the next sample */
12051 113254 sc->stsc_sample++;
12052
2/2
✓ Branch 1 taken 56871 times.
✓ Branch 2 taken 56383 times.
113254 if (mov_stsc_index_valid(sc->stsc_index, sc->stsc_count) &&
12053
2/2
✓ Branch 1 taken 1211 times.
✓ Branch 2 taken 55660 times.
56871 mov_get_stsc_samples(sc, sc->stsc_index) == sc->stsc_sample) {
12054 1211 sc->stsc_index++;
12055 1211 sc->stsc_sample = 0;
12056 }
12057 }
12058
12059 116629 return 0;
12060 }
12061
12062 107953 static int mov_read_packet(AVFormatContext *s, AVPacket *pkt)
12063 {
12064 107953 MOVContext *mov = s->priv_data;
12065 MOVStreamContext *sc;
12066 AVIndexEntry *sample;
12067 107953 AVStream *st = NULL;
12068 107953 FFStream *avsti = NULL;
12069 int64_t current_index;
12070 int ret;
12071 int i;
12072 107953 mov->fc = s;
12073 9287 retry:
12074
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 117240 times.
117240 if (s->pb->pos == 0) {
12075
12076 // Discard current fragment index
12077 if (mov->frag_index.allocated_size > 0) {
12078 for(int i = 0; i < mov->frag_index.nb_items; i++) {
12079 av_freep(&mov->frag_index.item[i].stream_info);
12080 }
12081 av_freep(&mov->frag_index.item);
12082 mov->frag_index.nb_items = 0;
12083 mov->frag_index.allocated_size = 0;
12084 mov->frag_index.current = -1;
12085 mov->frag_index.complete = 0;
12086 }
12087
12088 for (i = 0; i < s->nb_streams; i++) {
12089 AVStream *avst = s->streams[i];
12090 MOVStreamContext *msc = avst->priv_data;
12091
12092 // Clear current sample
12093 mov_current_sample_set(msc, 0);
12094 msc->tts_index = 0;
12095
12096 // Discard current index entries
12097 avsti = ffstream(avst);
12098 if (avsti->index_entries_allocated_size > 0) {
12099 av_freep(&avsti->index_entries);
12100 avsti->index_entries_allocated_size = 0;
12101 avsti->nb_index_entries = 0;
12102 }
12103 }
12104
12105 if ((ret = mov_switch_root(s, -1, -1)) < 0)
12106 return ret;
12107 }
12108 117240 sample = mov_find_next_sample(s, &st);
12109
6/6
✓ Branch 0 taken 116674 times.
✓ Branch 1 taken 566 times.
✓ Branch 2 taken 653 times.
✓ Branch 3 taken 116021 times.
✓ Branch 4 taken 36 times.
✓ Branch 5 taken 617 times.
117240 if (!sample || (mov->next_root_atom && sample->pos > mov->next_root_atom)) {
12110
2/2
✓ Branch 0 taken 554 times.
✓ Branch 1 taken 48 times.
602 if (!mov->next_root_atom)
12111 554 return AVERROR_EOF;
12112
2/2
✓ Branch 1 taken 7 times.
✓ Branch 2 taken 41 times.
48 if ((ret = mov_switch_root(s, mov->next_root_atom, -1)) < 0)
12113 7 return ret;
12114 41 goto retry;
12115 }
12116 116638 sc = st->priv_data;
12117 /* must be done just before reading, to avoid infinite loop on sample */
12118 116638 current_index = sc->current_index;
12119 116638 mov_current_sample_inc(sc);
12120
12121
2/2
✓ Branch 0 taken 617 times.
✓ Branch 1 taken 116021 times.
116638 if (mov->next_root_atom) {
12122 617 sample->pos = FFMIN(sample->pos, mov->next_root_atom);
12123 617 sample->size = FFMIN(sample->size, (mov->next_root_atom - sample->pos));
12124 }
12125
12126
4/4
✓ Branch 0 taken 9256 times.
✓ Branch 1 taken 107382 times.
✓ Branch 2 taken 10 times.
✓ Branch 3 taken 9246 times.
116638 if (st->discard != AVDISCARD_ALL || sc->iamf) {
12127 107392 int64_t ret64 = avio_seek(sc->pb, sample->pos, SEEK_SET);
12128
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 107385 times.
107392 if (ret64 != sample->pos) {
12129 7 av_log(mov->fc, AV_LOG_ERROR, "stream %d, offset 0x%"PRIx64": partial file\n",
12130 sc->ffindex, sample->pos);
12131
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
7 if (should_retry(sc->pb, ret64)) {
12132 mov_current_sample_dec(sc);
12133
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 } else if (ret64 < 0) {
12134 7 return (int)ret64;
12135 }
12136 return AVERROR_INVALIDDATA;
12137 }
12138
12139
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 107385 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
107385 if (st->discard == AVDISCARD_NONKEY && !(sample->flags & AVINDEX_KEYFRAME)) {
12140 av_log(mov->fc, AV_LOG_DEBUG, "Nonkey frame from stream %d discarded due to AVDISCARD_NONKEY\n", sc->ffindex);
12141 goto retry;
12142 }
12143
12144
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 107385 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
107385 if (st->codecpar->codec_id == AV_CODEC_ID_EIA_608 && sample->size > 8)
12145 ret = get_eia608_packet(sc->pb, pkt, sample->size);
12146 #if CONFIG_IAMFDEC
12147
2/2
✓ Branch 0 taken 82 times.
✓ Branch 1 taken 107303 times.
107385 else if (sc->iamf) {
12148 int64_t pts, dts, pos, duration;
12149 82 int flags, size = sample->size;
12150 82 ret = mov_finalize_packet(s, st, sample, current_index, pkt);
12151 82 pts = pkt->pts; dts = pkt->dts;
12152 82 pos = pkt->pos; flags = pkt->flags;
12153 82 duration = pkt->duration;
12154
3/4
✓ Branch 0 taken 536 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 454 times.
✓ Branch 3 taken 82 times.
536 while (!ret && size > 0) {
12155 454 ret = ff_iamf_read_packet(s, sc->iamf, sc->pb, size, sc->iamf_stream_offset, pkt);
12156
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 454 times.
454 if (ret < 0) {
12157 if (should_retry(sc->pb, ret))
12158 mov_current_sample_dec(sc);
12159 return ret;
12160 }
12161 454 size -= ret;
12162
12163
2/2
✓ Branch 0 taken 120 times.
✓ Branch 1 taken 334 times.
454 if (pkt->flags & AV_PKT_FLAG_DISCARD) {
12164 120 av_packet_unref(pkt);
12165 120 ret = 0;
12166 120 continue;
12167 }
12168 334 pkt->pts = pts; pkt->dts = dts;
12169 334 pkt->pos = pos; pkt->flags |= flags;
12170 334 pkt->duration = duration;
12171 334 ret = ff_buffer_packet(s, pkt);
12172 }
12173
1/2
✓ Branch 0 taken 82 times.
✗ Branch 1 not taken.
82 if (!ret)
12174 82 return FFERROR_REDO;
12175 }
12176 #endif
12177
3/4
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 107300 times.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
107306 else if (st->codecpar->codec_id == AV_CODEC_ID_APV && sample->size > 4) {
12178 3 uint32_t au_size = avio_rb32(sc->pb);
12179 3 int explode = !!(mov->fc->error_recognition & AV_EF_EXPLODE);
12180
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (au_size > sample->size - 4) {
12181 av_log(s, explode ? AV_LOG_ERROR : AV_LOG_WARNING,
12182 "APV au_size %u exceeds sample body %d\n",
12183 au_size, sample->size - 4);
12184 if (explode)
12185 return AVERROR_INVALIDDATA;
12186 au_size = sample->size - 4;
12187 }
12188 3 ret = av_get_packet(sc->pb, pkt, au_size);
12189 } else
12190 107300 ret = av_get_packet(sc->pb, pkt, sample->size);
12191
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 107301 times.
107303 if (ret < 0) {
12192
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if (should_retry(sc->pb, ret)) {
12193 mov_current_sample_dec(sc);
12194 }
12195 2 return ret;
12196 }
12197 #if CONFIG_DV_DEMUXER
12198
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 107301 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
107301 if (mov->dv_demux && sc->dv_audio_container) {
12199 ret = avpriv_dv_produce_packet(mov->dv_demux, NULL, pkt->data, pkt->size, pkt->pos);
12200 av_packet_unref(pkt);
12201 if (ret < 0)
12202 return ret;
12203 ret = avpriv_dv_get_packet(mov->dv_demux, pkt);
12204 if (ret < 0)
12205 return ret;
12206 }
12207 #endif
12208
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 107283 times.
107301 if (sc->has_palette) {
12209 uint8_t *pal;
12210
12211 18 pal = av_packet_new_side_data(pkt, AV_PKT_DATA_PALETTE, AVPALETTE_SIZE);
12212
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (!pal) {
12213 av_log(mov->fc, AV_LOG_ERROR, "Cannot append palette to packet\n");
12214 } else {
12215 18 memcpy(pal, sc->palette, AVPALETTE_SIZE);
12216 18 sc->has_palette = 0;
12217 }
12218 }
12219
4/6
✓ Branch 0 taken 329 times.
✓ Branch 1 taken 106972 times.
✓ Branch 3 taken 329 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 329 times.
✗ Branch 6 not taken.
107301 if (st->codecpar->codec_id == AV_CODEC_ID_MP3 && !ffstream(st)->need_parsing && pkt->size > 4) {
12220
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 329 times.
329 if (ff_mpa_check_header(AV_RB32(pkt->data)) < 0)
12221 ffstream(st)->need_parsing = AVSTREAM_PARSE_FULL;
12222 }
12223 }
12224
12225 116547 ret = mov_finalize_packet(s, st, sample, current_index, pkt);
12226
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 116547 times.
116547 if (ret < 0)
12227 return ret;
12228
12229
2/2
✓ Branch 0 taken 9246 times.
✓ Branch 1 taken 107301 times.
116547 if (st->discard == AVDISCARD_ALL)
12230 9246 goto retry;
12231
12232
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 107301 times.
107301 if (mov->aax_mode)
12233 aax_filter(pkt->data, pkt->size, mov);
12234
12235 107301 ret = cenc_filter(mov, st, sc, pkt, current_index);
12236
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 107301 times.
107301 if (ret < 0) {
12237 return ret;
12238 }
12239
12240 107301 return 0;
12241 }
12242
12243 363 static int mov_seek_fragment(AVFormatContext *s, AVStream *st, int64_t timestamp)
12244 {
12245 363 MOVContext *mov = s->priv_data;
12246 int index;
12247
12248
2/2
✓ Branch 0 taken 335 times.
✓ Branch 1 taken 28 times.
363 if (!mov->frag_index.complete)
12249 335 return 0;
12250
12251 28 index = search_frag_timestamp(s, &mov->frag_index, st, timestamp);
12252
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 24 times.
28 if (index < 0)
12253 4 index = 0;
12254
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 27 times.
28 if (!mov->frag_index.item[index].headers_read)
12255 1 return mov_switch_root(s, -1, index);
12256
1/2
✓ Branch 0 taken 27 times.
✗ Branch 1 not taken.
27 if (index + 1 < mov->frag_index.nb_items)
12257 27 mov->next_root_atom = mov->frag_index.item[index + 1].moof_offset;
12258
12259 27 return 0;
12260 }
12261
12262 static int is_open_key_sample(const MOVStreamContext *sc, int sample)
12263 {
12264 // TODO: a bisect search would scale much better
12265 for (int i = 0; i < sc->open_key_samples_count; i++) {
12266 const int oks = sc->open_key_samples[i];
12267 if (oks == sample)
12268 return 1;
12269 if (oks > sample) /* list is monotically increasing so we can stop early */
12270 break;
12271 }
12272 return 0;
12273 }
12274
12275 /*
12276 * Some key sample may be key frames but not IDR frames, so a random access to
12277 * them may not be allowed.
12278 */
12279 231 static int can_seek_to_key_sample(AVStream *st, int sample, int64_t requested_pts)
12280 {
12281 231 MOVStreamContext *sc = st->priv_data;
12282 231 FFStream *const sti = ffstream(st);
12283 int64_t key_sample_dts, key_sample_pts;
12284
12285
1/2
✓ Branch 0 taken 231 times.
✗ Branch 1 not taken.
231 if (st->codecpar->codec_id != AV_CODEC_ID_HEVC)
12286 231 return 1;
12287
12288 if (sample >= sc->sample_offsets_count)
12289 return 1;
12290
12291 av_assert0(sample >= 0);
12292 key_sample_dts = sti->index_entries[sample].timestamp;
12293 key_sample_pts = key_sample_dts + sc->sample_offsets[sample] + sc->dts_shift;
12294
12295 /*
12296 * If the sample needs to be presented before an open key sample, they may
12297 * not be decodable properly, even though they come after in decoding
12298 * order.
12299 */
12300 if (is_open_key_sample(sc, sample) && key_sample_pts > requested_pts)
12301 return 0;
12302
12303 return 1;
12304 }
12305
12306 363 static int mov_seek_stream(AVFormatContext *s, AVStream *st, int64_t timestamp, int flags)
12307 {
12308 363 MOVStreamContext *sc = st->priv_data;
12309 363 FFStream *const sti = ffstream(st);
12310 int sample, time_sample, ret, requested_sample;
12311 int64_t next_ts;
12312 unsigned int i;
12313
12314 // Here we consider timestamp to be PTS, hence try to offset it so that we
12315 // can search over the DTS timeline.
12316 363 timestamp -= (sc->min_corrected_pts + sc->dts_shift);
12317
12318 363 ret = mov_seek_fragment(s, st, timestamp);
12319
1/2
✓ Branch 0 taken 363 times.
✗ Branch 1 not taken.
363 if (ret < 0)
12320 return ret;
12321
12322 for (;;) {
12323 363 sample = av_index_search_timestamp(st, timestamp, flags);
12324 363 av_log(s, AV_LOG_TRACE, "stream %d, timestamp %"PRId64", sample %d\n", st->index, timestamp, sample);
12325
5/6
✓ Branch 0 taken 69 times.
✓ Branch 1 taken 294 times.
✓ Branch 2 taken 69 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 43 times.
✓ Branch 5 taken 26 times.
363 if (sample < 0 && sti->nb_index_entries && timestamp < sti->index_entries[0].timestamp)
12326 43 sample = 0;
12327
2/2
✓ Branch 0 taken 26 times.
✓ Branch 1 taken 337 times.
363 if (sample < 0) /* not sure what to do */
12328 26 return AVERROR_INVALIDDATA;
12329
12330
3/4
✓ Branch 0 taken 231 times.
✓ Branch 1 taken 106 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 231 times.
337 if (!sample || can_seek_to_key_sample(st, sample, timestamp))
12331 break;
12332
12333 next_ts = timestamp - FFMAX(sc->min_sample_duration, 1);
12334 requested_sample = av_index_search_timestamp(st, next_ts, flags);
12335 if (requested_sample < 0)
12336 return AVERROR_INVALIDDATA;
12337
12338 // If we've reached a different sample trying to find a good pts to
12339 // seek to, give up searching because we'll end up seeking back to
12340 // sample 0 on every seek.
12341 if (sample != requested_sample && !can_seek_to_key_sample(st, requested_sample, next_ts))
12342 break;
12343
12344 timestamp = next_ts;
12345 }
12346
12347 337 mov_current_sample_set(sc, sample);
12348 337 av_log(s, AV_LOG_TRACE, "stream %d, found sample %d\n", st->index, sc->current_sample);
12349 /* adjust time to sample index */
12350
2/2
✓ Branch 0 taken 212 times.
✓ Branch 1 taken 125 times.
337 if (sc->tts_data) {
12351 212 time_sample = 0;
12352
1/2
✓ Branch 0 taken 60308 times.
✗ Branch 1 not taken.
60308 for (i = 0; i < sc->tts_count; i++) {
12353 60308 int next = time_sample + sc->tts_data[i].count;
12354
2/2
✓ Branch 0 taken 212 times.
✓ Branch 1 taken 60096 times.
60308 if (next > sc->current_sample) {
12355 212 sc->tts_index = i;
12356 212 sc->tts_sample = sc->current_sample - time_sample;
12357 212 break;
12358 }
12359 60096 time_sample = next;
12360 }
12361 }
12362
12363 /* adjust stsd index */
12364
2/2
✓ Branch 0 taken 309 times.
✓ Branch 1 taken 28 times.
337 if (sc->chunk_count) {
12365 309 time_sample = 0;
12366
1/2
✓ Branch 0 taken 381 times.
✗ Branch 1 not taken.
381 for (i = 0; i < sc->stsc_count; i++) {
12367 381 int64_t next = time_sample + mov_get_stsc_samples(sc, i);
12368
2/2
✓ Branch 0 taken 309 times.
✓ Branch 1 taken 72 times.
381 if (next > sc->current_sample) {
12369 309 sc->stsc_index = i;
12370 309 sc->stsc_sample = sc->current_sample - time_sample;
12371 309 break;
12372 }
12373
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 72 times.
72 av_assert0(next == (int)next);
12374 72 time_sample = next;
12375 }
12376 }
12377
12378 337 return sample;
12379 }
12380
12381 337 static int64_t mov_get_skip_samples(AVStream *st, int sample)
12382 {
12383 337 FFStream *const sti = ffstream(st);
12384 337 int64_t first_ts = sti->index_entries[0].timestamp;
12385 337 int64_t ts = sti->index_entries[sample].timestamp;
12386 int64_t off;
12387
12388
2/2
✓ Branch 0 taken 185 times.
✓ Branch 1 taken 152 times.
337 if (st->codecpar->codec_type != AVMEDIA_TYPE_AUDIO)
12389 185 return 0;
12390
12391 /* compute skip samples according to stream initial_padding, seek ts and first ts */
12392 152 off = av_rescale_q(ts - first_ts, st->time_base,
12393 152 (AVRational){1, st->codecpar->sample_rate});
12394 152 return FFMAX(st->codecpar->initial_padding - off, 0);
12395 }
12396
12397 341 static int mov_read_seek(AVFormatContext *s, int stream_index, int64_t sample_time, int flags)
12398 {
12399 341 MOVContext *mc = s->priv_data;
12400 AVStream *st;
12401 FFStream *sti;
12402 int sample;
12403 int i;
12404
12405
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 341 times.
341 if (stream_index >= s->nb_streams)
12406 return AVERROR_INVALIDDATA;
12407
12408 341 st = s->streams[stream_index];
12409 341 sti = ffstream(st);
12410 341 sample = mov_seek_stream(s, st, sample_time, flags);
12411
2/2
✓ Branch 0 taken 26 times.
✓ Branch 1 taken 315 times.
341 if (sample < 0)
12412 26 return sample;
12413
12414
1/2
✓ Branch 0 taken 315 times.
✗ Branch 1 not taken.
315 if (mc->seek_individually) {
12415 /* adjust seek timestamp to found sample timestamp */
12416 315 int64_t seek_timestamp = sti->index_entries[sample].timestamp;
12417 315 sti->skip_samples = mov_get_skip_samples(st, sample);
12418
12419
2/2
✓ Branch 0 taken 337 times.
✓ Branch 1 taken 315 times.
652 for (i = 0; i < s->nb_streams; i++) {
12420 337 AVStream *const st = s->streams[i];
12421 337 FFStream *const sti = ffstream(st);
12422 int64_t timestamp;
12423
12424
2/2
✓ Branch 0 taken 315 times.
✓ Branch 1 taken 22 times.
337 if (stream_index == i)
12425 315 continue;
12426
12427 22 timestamp = av_rescale_q(seek_timestamp, s->streams[stream_index]->time_base, st->time_base);
12428 22 sample = mov_seek_stream(s, st, timestamp, flags);
12429
1/2
✓ Branch 0 taken 22 times.
✗ Branch 1 not taken.
22 if (sample >= 0)
12430 22 sti->skip_samples = mov_get_skip_samples(st, sample);
12431 }
12432 } else {
12433 for (i = 0; i < s->nb_streams; i++) {
12434 MOVStreamContext *sc;
12435 st = s->streams[i];
12436 sc = st->priv_data;
12437 mov_current_sample_set(sc, 0);
12438 }
12439 while (1) {
12440 MOVStreamContext *sc;
12441 AVIndexEntry *entry = mov_find_next_sample(s, &st);
12442 if (!entry)
12443 return AVERROR_INVALIDDATA;
12444 sc = st->priv_data;
12445 if (sc->ffindex == stream_index && sc->current_sample == sample)
12446 break;
12447 mov_current_sample_inc(sc);
12448 }
12449 }
12450 315 return 0;
12451 }
12452
12453 #define OFFSET(x) offsetof(MOVContext, x)
12454 #define FLAGS AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_DECODING_PARAM
12455 static const AVOption mov_options[] = {
12456 {"use_absolute_path",
12457 "allow using absolute path when opening alias, this is a possible security issue",
12458 OFFSET(use_absolute_path), AV_OPT_TYPE_BOOL, {.i64 = 0},
12459 0, 1, FLAGS},
12460 {"seek_streams_individually",
12461 "Seek each stream individually to the closest point",
12462 OFFSET(seek_individually), AV_OPT_TYPE_BOOL, { .i64 = 1 },
12463 0, 1, FLAGS},
12464 {"ignore_editlist", "Ignore the edit list atom.", OFFSET(ignore_editlist), AV_OPT_TYPE_BOOL, {.i64 = 0},
12465 0, 1, FLAGS},
12466 {"advanced_editlist",
12467 "Modify the AVIndex according to the editlists. Use this option to decode in the order specified by the edits.",
12468 OFFSET(advanced_editlist), AV_OPT_TYPE_BOOL, {.i64 = 1},
12469 0, 1, FLAGS},
12470 {"ignore_chapters", "", OFFSET(ignore_chapters), AV_OPT_TYPE_BOOL, {.i64 = 0},
12471 0, 1, FLAGS},
12472 {"use_mfra_for",
12473 "use mfra for fragment timestamps",
12474 OFFSET(use_mfra_for), AV_OPT_TYPE_INT, {.i64 = FF_MOV_FLAG_MFRA_AUTO},
12475 -1, FF_MOV_FLAG_MFRA_PTS, FLAGS,
12476 .unit = "use_mfra_for"},
12477 {"auto", "auto", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_MFRA_AUTO}, 0, 0,
12478 FLAGS, .unit = "use_mfra_for" },
12479 {"dts", "dts", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_MFRA_DTS}, 0, 0,
12480 FLAGS, .unit = "use_mfra_for" },
12481 {"pts", "pts", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_MFRA_PTS}, 0, 0,
12482 FLAGS, .unit = "use_mfra_for" },
12483 {"use_tfdt", "use tfdt for fragment timestamps", OFFSET(use_tfdt), AV_OPT_TYPE_BOOL, {.i64 = 1},
12484 0, 1, FLAGS},
12485 { "export_all", "Export unrecognized metadata entries", OFFSET(export_all),
12486 AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, .flags = FLAGS },
12487 { "export_xmp", "Export full XMP metadata", OFFSET(export_xmp),
12488 AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, .flags = FLAGS },
12489 { "activation_bytes", "Secret bytes for Audible AAX files", OFFSET(activation_bytes),
12490 AV_OPT_TYPE_BINARY, .flags = AV_OPT_FLAG_DECODING_PARAM },
12491 { "audible_key", "AES-128 Key for Audible AAXC files", OFFSET(audible_key),
12492 AV_OPT_TYPE_BINARY, .flags = AV_OPT_FLAG_DECODING_PARAM },
12493 { "audible_iv", "AES-128 IV for Audible AAXC files", OFFSET(audible_iv),
12494 AV_OPT_TYPE_BINARY, .flags = AV_OPT_FLAG_DECODING_PARAM },
12495 { "audible_fixed_key", // extracted from libAAX_SDK.so and AAXSDKWin.dll files!
12496 "Fixed key used for handling Audible AAX files", OFFSET(audible_fixed_key),
12497 AV_OPT_TYPE_BINARY, {.str="77214d4b196a87cd520045fd20a51d67"},
12498 .flags = AV_OPT_FLAG_DECODING_PARAM },
12499 { "decryption_key", "The default media decryption key (hex)", OFFSET(decryption_default_key), AV_OPT_TYPE_BINARY, .flags = AV_OPT_FLAG_DECODING_PARAM },
12500 { "decryption_keys", "The media decryption keys by KID (hex)", OFFSET(decryption_keys), AV_OPT_TYPE_DICT, .flags = AV_OPT_FLAG_DECODING_PARAM },
12501 { "enable_drefs", "Enable external track support.", OFFSET(enable_drefs), AV_OPT_TYPE_BOOL,
12502 {.i64 = 0}, 0, 1, FLAGS },
12503 { "max_stts_delta", "treat offsets above this value as invalid", OFFSET(max_stts_delta), AV_OPT_TYPE_INT, {.i64 = UINT_MAX-48000*10 }, 0, UINT_MAX, .flags = AV_OPT_FLAG_DECODING_PARAM },
12504 { "interleaved_read", "Interleave packets from multiple tracks at demuxer level", OFFSET(interleaved_read), AV_OPT_TYPE_BOOL, {.i64 = 1 }, 0, 1, .flags = AV_OPT_FLAG_DECODING_PARAM },
12505
12506 { NULL },
12507 };
12508
12509 static const AVClass mov_class = {
12510 .class_name = "mov,mp4,m4a,3gp,3g2,mj2",
12511 .item_name = av_default_item_name,
12512 .option = mov_options,
12513 .version = LIBAVUTIL_VERSION_INT,
12514 };
12515
12516 const FFInputFormat ff_mov_demuxer = {
12517 .p.name = "mov,mp4,m4a,3gp,3g2,mj2",
12518 .p.long_name = NULL_IF_CONFIG_SMALL("QuickTime / MOV"),
12519 .p.priv_class = &mov_class,
12520 .p.extensions = "mov,mp4,m4a,3gp,3g2,mj2,psp,m4v,m4b,ism,ismv,isma,f4v,avif,heic,heif",
12521 .p.flags = AVFMT_NO_BYTE_SEEK | AVFMT_SEEK_TO_PTS | AVFMT_SHOW_IDS,
12522 .priv_data_size = sizeof(MOVContext),
12523 .flags_internal = FF_INFMT_FLAG_INIT_CLEANUP,
12524 .read_probe = mov_probe,
12525 .read_header = mov_read_header,
12526 .read_packet = mov_read_packet,
12527 .read_close = mov_read_close,
12528 .read_seek = mov_read_seek,
12529 };
12530