3 * Copyright (c) 2001 Fabrice Bellard
4 * Copyright (c) 2009 Baptiste Coudurier <baptiste dot coudurier at gmail dot com>
6 * first version by Francois Revol <revol@free.fr>
7 * seek function by Gael Chardon <gael.dev@4now.net>
9 * This file is part of FFmpeg.
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.
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.
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
30 #include "libavutil/attributes.h"
31 #include "libavutil/channel_layout.h"
32 #include "libavutil/internal.h"
33 #include "libavutil/intreadwrite.h"
34 #include "libavutil/intfloat.h"
35 #include "libavutil/mathematics.h"
36 #include "libavutil/time_internal.h"
37 #include "libavutil/avassert.h"
38 #include "libavutil/avstring.h"
39 #include "libavutil/dict.h"
40 #include "libavutil/display.h"
41 #include "libavutil/opt.h"
42 #include "libavutil/aes.h"
43 #include "libavutil/aes_ctr.h"
44 #include "libavutil/pixdesc.h"
45 #include "libavutil/sha.h"
46 #include "libavutil/spherical.h"
47 #include "libavutil/stereo3d.h"
48 #include "libavutil/timecode.h"
49 #include "libavutil/dovi_meta.h"
50 #include "libavcodec/ac3tab.h"
51 #include "libavcodec/flac.h"
52 #include "libavcodec/mpegaudiodecheader.h"
53 #include "libavcodec/mlp_parse.h"
56 #include "avio_internal.h"
59 #include "libavcodec/get_bits.h"
62 #include "replaygain.h"
68 #include "qtpalette.h"
70 /* those functions parse an atom */
71 /* links atom IDs to parse functions */
72 typedef struct MOVParseTableEntry {
74 int (*parse)(MOVContext *ctx, AVIOContext *pb, MOVAtom atom);
77 static int mov_read_default(MOVContext *c, AVIOContext *pb, MOVAtom atom);
78 static int mov_read_mfra(MOVContext *c, AVIOContext *f);
79 static int64_t add_ctts_entry(MOVStts** ctts_data, unsigned int* ctts_count, unsigned int* allocated_size,
80 int count, int duration);
82 static int mov_metadata_track_or_disc_number(MOVContext *c, AVIOContext *pb,
83 unsigned len, const char *key)
87 short current, total = 0;
88 avio_rb16(pb); // unknown
89 current = avio_rb16(pb);
91 total = avio_rb16(pb);
93 snprintf(buf, sizeof(buf), "%d", current);
95 snprintf(buf, sizeof(buf), "%d/%d", current, total);
96 c->fc->event_flags |= AVFMT_EVENT_FLAG_METADATA_UPDATED;
97 av_dict_set(&c->fc->metadata, key, buf, 0);
102 static int mov_metadata_int8_bypass_padding(MOVContext *c, AVIOContext *pb,
103 unsigned len, const char *key)
105 /* bypass padding bytes */
110 c->fc->event_flags |= AVFMT_EVENT_FLAG_METADATA_UPDATED;
111 av_dict_set_int(&c->fc->metadata, key, avio_r8(pb), 0);
116 static int mov_metadata_int8_no_padding(MOVContext *c, AVIOContext *pb,
117 unsigned len, const char *key)
119 c->fc->event_flags |= AVFMT_EVENT_FLAG_METADATA_UPDATED;
120 av_dict_set_int(&c->fc->metadata, key, avio_r8(pb), 0);
125 static int mov_metadata_gnre(MOVContext *c, AVIOContext *pb,
126 unsigned len, const char *key)
130 avio_r8(pb); // unknown
133 if (genre < 1 || genre > ID3v1_GENRE_MAX)
135 c->fc->event_flags |= AVFMT_EVENT_FLAG_METADATA_UPDATED;
136 av_dict_set(&c->fc->metadata, key, ff_id3v1_genre_str[genre-1], 0);
141 static const uint32_t mac_to_unicode[128] = {
142 0x00C4,0x00C5,0x00C7,0x00C9,0x00D1,0x00D6,0x00DC,0x00E1,
143 0x00E0,0x00E2,0x00E4,0x00E3,0x00E5,0x00E7,0x00E9,0x00E8,
144 0x00EA,0x00EB,0x00ED,0x00EC,0x00EE,0x00EF,0x00F1,0x00F3,
145 0x00F2,0x00F4,0x00F6,0x00F5,0x00FA,0x00F9,0x00FB,0x00FC,
146 0x2020,0x00B0,0x00A2,0x00A3,0x00A7,0x2022,0x00B6,0x00DF,
147 0x00AE,0x00A9,0x2122,0x00B4,0x00A8,0x2260,0x00C6,0x00D8,
148 0x221E,0x00B1,0x2264,0x2265,0x00A5,0x00B5,0x2202,0x2211,
149 0x220F,0x03C0,0x222B,0x00AA,0x00BA,0x03A9,0x00E6,0x00F8,
150 0x00BF,0x00A1,0x00AC,0x221A,0x0192,0x2248,0x2206,0x00AB,
151 0x00BB,0x2026,0x00A0,0x00C0,0x00C3,0x00D5,0x0152,0x0153,
152 0x2013,0x2014,0x201C,0x201D,0x2018,0x2019,0x00F7,0x25CA,
153 0x00FF,0x0178,0x2044,0x20AC,0x2039,0x203A,0xFB01,0xFB02,
154 0x2021,0x00B7,0x201A,0x201E,0x2030,0x00C2,0x00CA,0x00C1,
155 0x00CB,0x00C8,0x00CD,0x00CE,0x00CF,0x00CC,0x00D3,0x00D4,
156 0xF8FF,0x00D2,0x00DA,0x00DB,0x00D9,0x0131,0x02C6,0x02DC,
157 0x00AF,0x02D8,0x02D9,0x02DA,0x00B8,0x02DD,0x02DB,0x02C7,
160 static int mov_read_mac_string(MOVContext *c, AVIOContext *pb, int len,
161 char *dst, int dstlen)
164 char *end = dst+dstlen-1;
167 for (i = 0; i < len; i++) {
168 uint8_t t, c = avio_r8(pb);
176 PUT_UTF8(mac_to_unicode[c-0x80], t, if (p < end) *p++ = t;);
182 static int mov_read_covr(MOVContext *c, AVIOContext *pb, int type, int len)
185 MOVStreamContext *sc;
190 case 0xd: id = AV_CODEC_ID_MJPEG; break;
191 case 0xe: id = AV_CODEC_ID_PNG; break;
192 case 0x1b: id = AV_CODEC_ID_BMP; break;
194 av_log(c->fc, AV_LOG_WARNING, "Unknown cover type: 0x%x.\n", type);
199 st = avformat_new_stream(c->fc, NULL);
201 return AVERROR(ENOMEM);
202 sc = av_mallocz(sizeof(*sc));
204 return AVERROR(ENOMEM);
207 ret = av_get_packet(pb, &st->attached_pic, len);
211 if (st->attached_pic.size >= 8 && id != AV_CODEC_ID_BMP) {
212 if (AV_RB64(st->attached_pic.data) == 0x89504e470d0a1a0a) {
213 id = AV_CODEC_ID_PNG;
215 id = AV_CODEC_ID_MJPEG;
219 st->disposition |= AV_DISPOSITION_ATTACHED_PIC;
221 st->attached_pic.stream_index = st->index;
222 st->attached_pic.flags |= AV_PKT_FLAG_KEY;
224 st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
225 st->codecpar->codec_id = id;
231 static int mov_metadata_loci(MOVContext *c, AVIOContext *pb, unsigned len)
233 char language[4] = { 0 };
234 char buf[200], place[100];
235 uint16_t langcode = 0;
236 double longitude, latitude, altitude;
237 const char *key = "location";
239 if (len < 4 + 2 + 1 + 1 + 4 + 4 + 4) {
240 av_log(c->fc, AV_LOG_ERROR, "loci too short\n");
241 return AVERROR_INVALIDDATA;
244 avio_skip(pb, 4); // version+flags
245 langcode = avio_rb16(pb);
246 ff_mov_lang_to_iso639(langcode, language);
249 len -= avio_get_str(pb, len, place, sizeof(place));
251 av_log(c->fc, AV_LOG_ERROR, "place name too long\n");
252 return AVERROR_INVALIDDATA;
254 avio_skip(pb, 1); // role
258 av_log(c->fc, AV_LOG_ERROR,
259 "loci too short (%u bytes left, need at least %d)\n", len, 12);
260 return AVERROR_INVALIDDATA;
262 longitude = ((int32_t) avio_rb32(pb)) / (float) (1 << 16);
263 latitude = ((int32_t) avio_rb32(pb)) / (float) (1 << 16);
264 altitude = ((int32_t) avio_rb32(pb)) / (float) (1 << 16);
266 // Try to output in the same format as the ?xyz field
267 snprintf(buf, sizeof(buf), "%+08.4f%+09.4f", latitude, longitude);
269 av_strlcatf(buf, sizeof(buf), "%+f", altitude);
270 av_strlcatf(buf, sizeof(buf), "/%s", place);
272 if (*language && strcmp(language, "und")) {
274 snprintf(key2, sizeof(key2), "%s-%s", key, language);
275 av_dict_set(&c->fc->metadata, key2, buf, 0);
277 c->fc->event_flags |= AVFMT_EVENT_FLAG_METADATA_UPDATED;
278 return av_dict_set(&c->fc->metadata, key, buf, 0);
281 static int mov_metadata_hmmt(MOVContext *c, AVIOContext *pb, unsigned len)
287 if (c->ignore_chapters)
290 n_hmmt = avio_rb32(pb);
291 for (i = 0; i < n_hmmt && !pb->eof_reached; i++) {
292 int moment_time = avio_rb32(pb);
293 avpriv_new_chapter(c->fc, i, av_make_q(1, 1000), moment_time, AV_NOPTS_VALUE, NULL);
298 static int mov_read_udta_string(MOVContext *c, AVIOContext *pb, MOVAtom atom)
300 char tmp_key[AV_FOURCC_MAX_STRING_SIZE] = {0};
301 char key2[32], language[4] = {0};
303 const char *key = NULL;
304 uint16_t langcode = 0;
305 uint32_t data_type = 0, str_size, str_size_alloc;
306 int (*parse)(MOVContext*, AVIOContext*, unsigned, const char*) = NULL;
311 case MKTAG( '@','P','R','M'): key = "premiere_version"; raw = 1; break;
312 case MKTAG( '@','P','R','Q'): key = "quicktime_version"; raw = 1; break;
313 case MKTAG( 'X','M','P','_'):
314 if (c->export_xmp) { key = "xmp"; raw = 1; } break;
315 case MKTAG( 'a','A','R','T'): key = "album_artist"; break;
316 case MKTAG( 'a','k','I','D'): key = "account_type";
317 parse = mov_metadata_int8_no_padding; break;
318 case MKTAG( 'a','p','I','D'): key = "account_id"; break;
319 case MKTAG( 'c','a','t','g'): key = "category"; break;
320 case MKTAG( 'c','p','i','l'): key = "compilation";
321 parse = mov_metadata_int8_no_padding; break;
322 case MKTAG( 'c','p','r','t'): key = "copyright"; break;
323 case MKTAG( 'd','e','s','c'): key = "description"; break;
324 case MKTAG( 'd','i','s','k'): key = "disc";
325 parse = mov_metadata_track_or_disc_number; break;
326 case MKTAG( 'e','g','i','d'): key = "episode_uid";
327 parse = mov_metadata_int8_no_padding; break;
328 case MKTAG( 'F','I','R','M'): key = "firmware"; raw = 1; break;
329 case MKTAG( 'g','n','r','e'): key = "genre";
330 parse = mov_metadata_gnre; break;
331 case MKTAG( 'h','d','v','d'): key = "hd_video";
332 parse = mov_metadata_int8_no_padding; break;
333 case MKTAG( 'H','M','M','T'):
334 return mov_metadata_hmmt(c, pb, atom.size);
335 case MKTAG( 'k','e','y','w'): key = "keywords"; break;
336 case MKTAG( 'l','d','e','s'): key = "synopsis"; break;
337 case MKTAG( 'l','o','c','i'):
338 return mov_metadata_loci(c, pb, atom.size);
339 case MKTAG( 'm','a','n','u'): key = "make"; break;
340 case MKTAG( 'm','o','d','l'): key = "model"; break;
341 case MKTAG( 'p','c','s','t'): key = "podcast";
342 parse = mov_metadata_int8_no_padding; break;
343 case MKTAG( 'p','g','a','p'): key = "gapless_playback";
344 parse = mov_metadata_int8_no_padding; break;
345 case MKTAG( 'p','u','r','d'): key = "purchase_date"; break;
346 case MKTAG( 'r','t','n','g'): key = "rating";
347 parse = mov_metadata_int8_no_padding; break;
348 case MKTAG( 's','o','a','a'): key = "sort_album_artist"; break;
349 case MKTAG( 's','o','a','l'): key = "sort_album"; break;
350 case MKTAG( 's','o','a','r'): key = "sort_artist"; break;
351 case MKTAG( 's','o','c','o'): key = "sort_composer"; break;
352 case MKTAG( 's','o','n','m'): key = "sort_name"; break;
353 case MKTAG( 's','o','s','n'): key = "sort_show"; break;
354 case MKTAG( 's','t','i','k'): key = "media_type";
355 parse = mov_metadata_int8_no_padding; break;
356 case MKTAG( 't','r','k','n'): key = "track";
357 parse = mov_metadata_track_or_disc_number; break;
358 case MKTAG( 't','v','e','n'): key = "episode_id"; break;
359 case MKTAG( 't','v','e','s'): key = "episode_sort";
360 parse = mov_metadata_int8_bypass_padding; break;
361 case MKTAG( 't','v','n','n'): key = "network"; break;
362 case MKTAG( 't','v','s','h'): key = "show"; break;
363 case MKTAG( 't','v','s','n'): key = "season_number";
364 parse = mov_metadata_int8_bypass_padding; break;
365 case MKTAG(0xa9,'A','R','T'): key = "artist"; break;
366 case MKTAG(0xa9,'P','R','D'): key = "producer"; break;
367 case MKTAG(0xa9,'a','l','b'): key = "album"; break;
368 case MKTAG(0xa9,'a','u','t'): key = "artist"; break;
369 case MKTAG(0xa9,'c','h','p'): key = "chapter"; break;
370 case MKTAG(0xa9,'c','m','t'): key = "comment"; break;
371 case MKTAG(0xa9,'c','o','m'): key = "composer"; break;
372 case MKTAG(0xa9,'c','p','y'): key = "copyright"; break;
373 case MKTAG(0xa9,'d','a','y'): key = "date"; break;
374 case MKTAG(0xa9,'d','i','r'): key = "director"; break;
375 case MKTAG(0xa9,'d','i','s'): key = "disclaimer"; break;
376 case MKTAG(0xa9,'e','d','1'): key = "edit_date"; break;
377 case MKTAG(0xa9,'e','n','c'): key = "encoder"; break;
378 case MKTAG(0xa9,'f','m','t'): key = "original_format"; break;
379 case MKTAG(0xa9,'g','e','n'): key = "genre"; break;
380 case MKTAG(0xa9,'g','r','p'): key = "grouping"; break;
381 case MKTAG(0xa9,'h','s','t'): key = "host_computer"; break;
382 case MKTAG(0xa9,'i','n','f'): key = "comment"; break;
383 case MKTAG(0xa9,'l','y','r'): key = "lyrics"; break;
384 case MKTAG(0xa9,'m','a','k'): key = "make"; break;
385 case MKTAG(0xa9,'m','o','d'): key = "model"; break;
386 case MKTAG(0xa9,'n','a','m'): key = "title"; break;
387 case MKTAG(0xa9,'o','p','e'): key = "original_artist"; break;
388 case MKTAG(0xa9,'p','r','d'): key = "producer"; break;
389 case MKTAG(0xa9,'p','r','f'): key = "performers"; break;
390 case MKTAG(0xa9,'r','e','q'): key = "playback_requirements"; break;
391 case MKTAG(0xa9,'s','r','c'): key = "original_source"; break;
392 case MKTAG(0xa9,'s','t','3'): key = "subtitle"; break;
393 case MKTAG(0xa9,'s','w','r'): key = "encoder"; break;
394 case MKTAG(0xa9,'t','o','o'): key = "encoder"; break;
395 case MKTAG(0xa9,'t','r','k'): key = "track"; break;
396 case MKTAG(0xa9,'u','r','l'): key = "URL"; break;
397 case MKTAG(0xa9,'w','r','n'): key = "warning"; break;
398 case MKTAG(0xa9,'w','r','t'): key = "composer"; break;
399 case MKTAG(0xa9,'x','y','z'): key = "location"; break;
402 if (c->itunes_metadata && atom.size > 8) {
403 int data_size = avio_rb32(pb);
404 int tag = avio_rl32(pb);
405 if (tag == MKTAG('d','a','t','a') && data_size <= atom.size) {
406 data_type = avio_rb32(pb); // type
407 avio_rb32(pb); // unknown
408 str_size = data_size - 16;
411 if (atom.type == MKTAG('c', 'o', 'v', 'r')) {
412 int ret = mov_read_covr(c, pb, data_type, str_size);
414 av_log(c->fc, AV_LOG_ERROR, "Error parsing cover art.\n");
417 atom.size -= str_size;
421 } else if (!key && c->found_hdlr_mdta && c->meta_keys) {
422 uint32_t index = AV_RB32(&atom.type);
423 if (index < c->meta_keys_count && index > 0) {
424 key = c->meta_keys[index];
426 av_log(c->fc, AV_LOG_WARNING,
427 "The index of 'data' is out of range: %"PRId32" < 1 or >= %d.\n",
428 index, c->meta_keys_count);
432 } else if (atom.size > 4 && key && !c->itunes_metadata && !raw) {
433 str_size = avio_rb16(pb); // string length
434 if (str_size > atom.size) {
436 avio_seek(pb, -2, SEEK_CUR);
437 av_log(c->fc, AV_LOG_WARNING, "UDTA parsing failed retrying raw\n");
440 langcode = avio_rb16(pb);
441 ff_mov_lang_to_iso639(langcode, language);
444 str_size = atom.size;
446 if (c->export_all && !key) {
447 key = av_fourcc_make_string(tmp_key, atom.type);
452 if (atom.size < 0 || str_size >= INT_MAX/2)
453 return AVERROR_INVALIDDATA;
455 // Allocates enough space if data_type is a int32 or float32 number, otherwise
456 // worst-case requirement for output string in case of utf8 coded input
457 num = (data_type >= 21 && data_type <= 23);
458 str_size_alloc = (num ? 512 : (raw ? str_size : str_size * 2)) + 1;
459 str = av_mallocz(str_size_alloc);
461 return AVERROR(ENOMEM);
464 parse(c, pb, str_size, key);
466 if (!raw && (data_type == 3 || (data_type == 0 && (langcode < 0x400 || langcode == 0x7fff)))) { // MAC Encoded
467 mov_read_mac_string(c, pb, str_size, str, str_size_alloc);
468 } else if (data_type == 21) { // BE signed integer, variable size
471 val = (int8_t)avio_r8(pb);
472 else if (str_size == 2)
473 val = (int16_t)avio_rb16(pb);
474 else if (str_size == 3)
475 val = ((int32_t)(avio_rb24(pb)<<8))>>8;
476 else if (str_size == 4)
477 val = (int32_t)avio_rb32(pb);
478 if (snprintf(str, str_size_alloc, "%d", val) >= str_size_alloc) {
479 av_log(c->fc, AV_LOG_ERROR,
480 "Failed to store the number (%d) in string.\n", val);
482 return AVERROR_INVALIDDATA;
484 } else if (data_type == 22) { // BE unsigned integer, variable size
485 unsigned int val = 0;
488 else if (str_size == 2)
490 else if (str_size == 3)
492 else if (str_size == 4)
494 if (snprintf(str, str_size_alloc, "%u", val) >= str_size_alloc) {
495 av_log(c->fc, AV_LOG_ERROR,
496 "Failed to store the number (%u) in string.\n", val);
498 return AVERROR_INVALIDDATA;
500 } else if (data_type == 23 && str_size >= 4) { // BE float32
501 float val = av_int2float(avio_rb32(pb));
502 if (snprintf(str, str_size_alloc, "%f", val) >= str_size_alloc) {
503 av_log(c->fc, AV_LOG_ERROR,
504 "Failed to store the float32 number (%f) in string.\n", val);
506 return AVERROR_INVALIDDATA;
509 int ret = ffio_read_size(pb, str, str_size);
516 c->fc->event_flags |= AVFMT_EVENT_FLAG_METADATA_UPDATED;
517 av_dict_set(&c->fc->metadata, key, str, 0);
518 if (*language && strcmp(language, "und")) {
519 snprintf(key2, sizeof(key2), "%s-%s", key, language);
520 av_dict_set(&c->fc->metadata, key2, str, 0);
522 if (!strcmp(key, "encoder")) {
523 int major, minor, micro;
524 if (sscanf(str, "HandBrake %d.%d.%d", &major, &minor, µ) == 3) {
525 c->handbrake_version = 1000000*major + 1000*minor + micro;
534 static int mov_read_chpl(MOVContext *c, AVIOContext *pb, MOVAtom atom)
537 int i, nb_chapters, str_len, version;
541 if (c->ignore_chapters)
544 if ((atom.size -= 5) < 0)
547 version = avio_r8(pb);
550 avio_rb32(pb); // ???
551 nb_chapters = avio_r8(pb);
553 for (i = 0; i < nb_chapters; i++) {
557 start = avio_rb64(pb);
558 str_len = avio_r8(pb);
560 if ((atom.size -= 9+str_len) < 0)
563 ret = ffio_read_size(pb, str, str_len);
567 avpriv_new_chapter(c->fc, i, (AVRational){1,10000000}, start, AV_NOPTS_VALUE, str);
572 #define MIN_DATA_ENTRY_BOX_SIZE 12
573 static int mov_read_dref(MOVContext *c, AVIOContext *pb, MOVAtom atom)
576 MOVStreamContext *sc;
579 if (c->fc->nb_streams < 1)
581 st = c->fc->streams[c->fc->nb_streams-1];
584 avio_rb32(pb); // version + flags
585 entries = avio_rb32(pb);
587 entries > (atom.size - 1) / MIN_DATA_ENTRY_BOX_SIZE + 1 ||
588 entries >= UINT_MAX / sizeof(*sc->drefs))
589 return AVERROR_INVALIDDATA;
593 sc->drefs = av_mallocz(entries * sizeof(*sc->drefs));
595 return AVERROR(ENOMEM);
596 sc->drefs_count = entries;
598 for (i = 0; i < entries; i++) {
599 MOVDref *dref = &sc->drefs[i];
600 uint32_t size = avio_rb32(pb);
601 int64_t next = avio_tell(pb) + size - 4;
604 return AVERROR_INVALIDDATA;
606 dref->type = avio_rl32(pb);
607 avio_rb32(pb); // version + flags
609 if (dref->type == MKTAG('a','l','i','s') && size > 150) {
610 /* macintosh alias record */
611 uint16_t volume_len, len;
617 volume_len = avio_r8(pb);
618 volume_len = FFMIN(volume_len, 27);
619 ret = ffio_read_size(pb, dref->volume, 27);
622 dref->volume[volume_len] = 0;
623 av_log(c->fc, AV_LOG_DEBUG, "volume %s, len %d\n", dref->volume, volume_len);
628 len = FFMIN(len, 63);
629 ret = ffio_read_size(pb, dref->filename, 63);
632 dref->filename[len] = 0;
633 av_log(c->fc, AV_LOG_DEBUG, "filename %s, len %d\n", dref->filename, len);
637 /* read next level up_from_alias/down_to_target */
638 dref->nlvl_from = avio_rb16(pb);
639 dref->nlvl_to = avio_rb16(pb);
640 av_log(c->fc, AV_LOG_DEBUG, "nlvl from %d, nlvl to %d\n",
641 dref->nlvl_from, dref->nlvl_to);
645 for (type = 0; type != -1 && avio_tell(pb) < next; ) {
648 type = avio_rb16(pb);
650 av_log(c->fc, AV_LOG_DEBUG, "type %d, len %d\n", type, len);
653 if (type == 2) { // absolute path
655 dref->path = av_mallocz(len+1);
657 return AVERROR(ENOMEM);
659 ret = ffio_read_size(pb, dref->path, len);
661 av_freep(&dref->path);
664 if (len > volume_len && !strncmp(dref->path, dref->volume, volume_len)) {
666 memmove(dref->path, dref->path+volume_len, len);
669 // trim string of any ending zeros
670 for (j = len - 1; j >= 0; j--) {
671 if (dref->path[j] == 0)
676 for (j = 0; j < len; j++)
677 if (dref->path[j] == ':' || dref->path[j] == 0)
679 av_log(c->fc, AV_LOG_DEBUG, "path %s\n", dref->path);
680 } else if (type == 0) { // directory name
682 dref->dir = av_malloc(len+1);
684 return AVERROR(ENOMEM);
686 ret = ffio_read_size(pb, dref->dir, len);
688 av_freep(&dref->dir);
692 for (j = 0; j < len; j++)
693 if (dref->dir[j] == ':')
695 av_log(c->fc, AV_LOG_DEBUG, "dir %s\n", dref->dir);
700 av_log(c->fc, AV_LOG_DEBUG, "Unknown dref type 0x%08"PRIx32" size %"PRIu32"\n",
705 avio_seek(pb, next, SEEK_SET);
710 static int mov_read_hdlr(MOVContext *c, AVIOContext *pb, MOVAtom atom)
719 avio_r8(pb); /* version */
720 avio_rb24(pb); /* flags */
723 ctype = avio_rl32(pb);
724 type = avio_rl32(pb); /* component subtype */
726 av_log(c->fc, AV_LOG_TRACE, "ctype=%s\n", av_fourcc2str(ctype));
727 av_log(c->fc, AV_LOG_TRACE, "stype=%s\n", av_fourcc2str(type));
729 if (c->trak_index < 0) { // meta not inside a trak
730 if (type == MKTAG('m','d','t','a')) {
731 c->found_hdlr_mdta = 1;
736 st = c->fc->streams[c->fc->nb_streams-1];
738 if (type == MKTAG('v','i','d','e'))
739 st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
740 else if (type == MKTAG('s','o','u','n'))
741 st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
742 else if (type == MKTAG('m','1','a',' '))
743 st->codecpar->codec_id = AV_CODEC_ID_MP2;
744 else if ((type == MKTAG('s','u','b','p')) || (type == MKTAG('c','l','c','p')))
745 st->codecpar->codec_type = AVMEDIA_TYPE_SUBTITLE;
747 avio_rb32(pb); /* component manufacture */
748 avio_rb32(pb); /* component flags */
749 avio_rb32(pb); /* component flags mask */
751 title_size = atom.size - 24;
752 if (title_size > 0) {
753 if (title_size > FFMIN(INT_MAX, SIZE_MAX-1))
754 return AVERROR_INVALIDDATA;
755 title_str = av_malloc(title_size + 1); /* Add null terminator */
757 return AVERROR(ENOMEM);
759 ret = ffio_read_size(pb, title_str, title_size);
761 av_freep(&title_str);
764 title_str[title_size] = 0;
766 int off = (!c->isom && title_str[0] == title_size - 1);
767 // flag added so as to not set stream handler name if already set from mdia->hdlr
768 av_dict_set(&st->metadata, "handler_name", title_str + off, AV_DICT_DONT_OVERWRITE);
770 av_freep(&title_str);
776 static int mov_read_esds(MOVContext *c, AVIOContext *pb, MOVAtom atom)
778 return ff_mov_read_esds(c->fc, pb);
781 static int mov_read_dac3(MOVContext *c, AVIOContext *pb, MOVAtom atom)
784 enum AVAudioServiceType *ast;
785 int ac3info, acmod, lfeon, bsmod;
787 if (c->fc->nb_streams < 1)
789 st = c->fc->streams[c->fc->nb_streams-1];
791 ast = (enum AVAudioServiceType*)av_stream_new_side_data(st, AV_PKT_DATA_AUDIO_SERVICE_TYPE,
794 return AVERROR(ENOMEM);
796 ac3info = avio_rb24(pb);
797 bsmod = (ac3info >> 14) & 0x7;
798 acmod = (ac3info >> 11) & 0x7;
799 lfeon = (ac3info >> 10) & 0x1;
800 st->codecpar->channels = ((int[]){2,1,2,3,3,4,4,5})[acmod] + lfeon;
801 st->codecpar->channel_layout = avpriv_ac3_channel_layout_tab[acmod];
803 st->codecpar->channel_layout |= AV_CH_LOW_FREQUENCY;
805 if (st->codecpar->channels > 1 && bsmod == 0x7)
806 *ast = AV_AUDIO_SERVICE_TYPE_KARAOKE;
808 #if FF_API_LAVF_AVCTX
809 FF_DISABLE_DEPRECATION_WARNINGS
810 st->codec->audio_service_type = *ast;
811 FF_ENABLE_DEPRECATION_WARNINGS
817 static int mov_read_dec3(MOVContext *c, AVIOContext *pb, MOVAtom atom)
820 enum AVAudioServiceType *ast;
821 int eac3info, acmod, lfeon, bsmod;
823 if (c->fc->nb_streams < 1)
825 st = c->fc->streams[c->fc->nb_streams-1];
827 ast = (enum AVAudioServiceType*)av_stream_new_side_data(st, AV_PKT_DATA_AUDIO_SERVICE_TYPE,
830 return AVERROR(ENOMEM);
832 /* No need to parse fields for additional independent substreams and its
833 * associated dependent substreams since libavcodec's E-AC-3 decoder
834 * does not support them yet. */
835 avio_rb16(pb); /* data_rate and num_ind_sub */
836 eac3info = avio_rb24(pb);
837 bsmod = (eac3info >> 12) & 0x1f;
838 acmod = (eac3info >> 9) & 0x7;
839 lfeon = (eac3info >> 8) & 0x1;
840 st->codecpar->channel_layout = avpriv_ac3_channel_layout_tab[acmod];
842 st->codecpar->channel_layout |= AV_CH_LOW_FREQUENCY;
843 st->codecpar->channels = av_get_channel_layout_nb_channels(st->codecpar->channel_layout);
845 if (st->codecpar->channels > 1 && bsmod == 0x7)
846 *ast = AV_AUDIO_SERVICE_TYPE_KARAOKE;
848 #if FF_API_LAVF_AVCTX
849 FF_DISABLE_DEPRECATION_WARNINGS
850 st->codec->audio_service_type = *ast;
851 FF_ENABLE_DEPRECATION_WARNINGS
857 static int mov_read_ddts(MOVContext *c, AVIOContext *pb, MOVAtom atom)
860 uint8_t buf[DDTS_SIZE + AV_INPUT_BUFFER_PADDING_SIZE];
862 uint32_t frame_duration_code = 0;
863 uint32_t channel_layout_code = 0;
867 if ((ret = ffio_read_size(pb, buf, DDTS_SIZE)) < 0)
870 init_get_bits(&gb, buf, 8 * DDTS_SIZE);
872 if (c->fc->nb_streams < 1) {
875 st = c->fc->streams[c->fc->nb_streams-1];
877 st->codecpar->sample_rate = get_bits_long(&gb, 32);
878 if (st->codecpar->sample_rate <= 0) {
879 av_log(c->fc, AV_LOG_ERROR, "Invalid sample rate %d\n", st->codecpar->sample_rate);
880 return AVERROR_INVALIDDATA;
882 skip_bits_long(&gb, 32); /* max bitrate */
883 st->codecpar->bit_rate = get_bits_long(&gb, 32);
884 st->codecpar->bits_per_coded_sample = get_bits(&gb, 8);
885 frame_duration_code = get_bits(&gb, 2);
886 skip_bits(&gb, 30); /* various fields */
887 channel_layout_code = get_bits(&gb, 16);
889 st->codecpar->frame_size =
890 (frame_duration_code == 0) ? 512 :
891 (frame_duration_code == 1) ? 1024 :
892 (frame_duration_code == 2) ? 2048 :
893 (frame_duration_code == 3) ? 4096 : 0;
895 if (channel_layout_code > 0xff) {
896 av_log(c->fc, AV_LOG_WARNING, "Unsupported DTS audio channel layout\n");
898 st->codecpar->channel_layout =
899 ((channel_layout_code & 0x1) ? AV_CH_FRONT_CENTER : 0) |
900 ((channel_layout_code & 0x2) ? AV_CH_FRONT_LEFT : 0) |
901 ((channel_layout_code & 0x2) ? AV_CH_FRONT_RIGHT : 0) |
902 ((channel_layout_code & 0x4) ? AV_CH_SIDE_LEFT : 0) |
903 ((channel_layout_code & 0x4) ? AV_CH_SIDE_RIGHT : 0) |
904 ((channel_layout_code & 0x8) ? AV_CH_LOW_FREQUENCY : 0);
906 st->codecpar->channels = av_get_channel_layout_nb_channels(st->codecpar->channel_layout);
911 static int mov_read_chan(MOVContext *c, AVIOContext *pb, MOVAtom atom)
915 if (c->fc->nb_streams < 1)
917 st = c->fc->streams[c->fc->nb_streams-1];
922 /* skip version and flags */
925 ff_mov_read_chan(c->fc, pb, st, atom.size - 4);
930 static int mov_read_wfex(MOVContext *c, AVIOContext *pb, MOVAtom atom)
935 if (c->fc->nb_streams < 1)
937 st = c->fc->streams[c->fc->nb_streams-1];
939 if ((ret = ff_get_wav_header(c->fc, pb, st->codecpar, atom.size, 0)) < 0)
940 av_log(c->fc, AV_LOG_WARNING, "get_wav_header failed\n");
945 static int mov_read_pasp(MOVContext *c, AVIOContext *pb, MOVAtom atom)
947 const int num = avio_rb32(pb);
948 const int den = avio_rb32(pb);
951 if (c->fc->nb_streams < 1)
953 st = c->fc->streams[c->fc->nb_streams-1];
955 if ((st->sample_aspect_ratio.den != 1 || st->sample_aspect_ratio.num) && // default
956 (den != st->sample_aspect_ratio.den || num != st->sample_aspect_ratio.num)) {
957 av_log(c->fc, AV_LOG_WARNING,
958 "sample aspect ratio already set to %d:%d, ignoring 'pasp' atom (%d:%d)\n",
959 st->sample_aspect_ratio.num, st->sample_aspect_ratio.den,
961 } else if (den != 0) {
962 av_reduce(&st->sample_aspect_ratio.num, &st->sample_aspect_ratio.den,
968 /* this atom contains actual media data */
969 static int mov_read_mdat(MOVContext *c, AVIOContext *pb, MOVAtom atom)
971 if (atom.size == 0) /* wrong one (MP4) */
974 return 0; /* now go for moov */
977 #define DRM_BLOB_SIZE 56
979 static int mov_read_adrm(MOVContext *c, AVIOContext *pb, MOVAtom atom)
981 uint8_t intermediate_key[20];
982 uint8_t intermediate_iv[20];
985 uint8_t file_checksum[20];
986 uint8_t calculated_checksum[20];
990 uint8_t *activation_bytes = c->activation_bytes;
991 uint8_t *fixed_key = c->audible_fixed_key;
995 sha = av_sha_alloc();
997 return AVERROR(ENOMEM);
998 av_free(c->aes_decrypt);
999 c->aes_decrypt = av_aes_alloc();
1000 if (!c->aes_decrypt) {
1001 ret = AVERROR(ENOMEM);
1005 /* drm blob processing */
1006 avio_read(pb, output, 8); // go to offset 8, absolute position 0x251
1007 avio_read(pb, input, DRM_BLOB_SIZE);
1008 avio_read(pb, output, 4); // go to offset 4, absolute position 0x28d
1009 avio_read(pb, file_checksum, 20);
1011 av_log(c->fc, AV_LOG_INFO, "[aax] file checksum == "); // required by external tools
1012 for (i = 0; i < 20; i++)
1013 av_log(c->fc, AV_LOG_INFO, "%02x", file_checksum[i]);
1014 av_log(c->fc, AV_LOG_INFO, "\n");
1016 /* verify activation data */
1017 if (!activation_bytes) {
1018 av_log(c->fc, AV_LOG_WARNING, "[aax] activation_bytes option is missing!\n");
1019 ret = 0; /* allow ffprobe to continue working on .aax files */
1022 if (c->activation_bytes_size != 4) {
1023 av_log(c->fc, AV_LOG_FATAL, "[aax] activation_bytes value needs to be 4 bytes!\n");
1024 ret = AVERROR(EINVAL);
1028 /* verify fixed key */
1029 if (c->audible_fixed_key_size != 16) {
1030 av_log(c->fc, AV_LOG_FATAL, "[aax] audible_fixed_key value needs to be 16 bytes!\n");
1031 ret = AVERROR(EINVAL);
1035 /* AAX (and AAX+) key derivation */
1036 av_sha_init(sha, 160);
1037 av_sha_update(sha, fixed_key, 16);
1038 av_sha_update(sha, activation_bytes, 4);
1039 av_sha_final(sha, intermediate_key);
1040 av_sha_init(sha, 160);
1041 av_sha_update(sha, fixed_key, 16);
1042 av_sha_update(sha, intermediate_key, 20);
1043 av_sha_update(sha, activation_bytes, 4);
1044 av_sha_final(sha, intermediate_iv);
1045 av_sha_init(sha, 160);
1046 av_sha_update(sha, intermediate_key, 16);
1047 av_sha_update(sha, intermediate_iv, 16);
1048 av_sha_final(sha, calculated_checksum);
1049 if (memcmp(calculated_checksum, file_checksum, 20)) { // critical error
1050 av_log(c->fc, AV_LOG_ERROR, "[aax] mismatch in checksums!\n");
1051 ret = AVERROR_INVALIDDATA;
1054 av_aes_init(c->aes_decrypt, intermediate_key, 128, 1);
1055 av_aes_crypt(c->aes_decrypt, output, input, DRM_BLOB_SIZE >> 4, intermediate_iv, 1);
1056 for (i = 0; i < 4; i++) {
1057 // file data (in output) is stored in big-endian mode
1058 if (activation_bytes[i] != output[3 - i]) { // critical error
1059 av_log(c->fc, AV_LOG_ERROR, "[aax] error in drm blob decryption!\n");
1060 ret = AVERROR_INVALIDDATA;
1064 memcpy(c->file_key, output + 8, 16);
1065 memcpy(input, output + 26, 16);
1066 av_sha_init(sha, 160);
1067 av_sha_update(sha, input, 16);
1068 av_sha_update(sha, c->file_key, 16);
1069 av_sha_update(sha, fixed_key, 16);
1070 av_sha_final(sha, c->file_iv);
1078 // Audible AAX (and AAX+) bytestream decryption
1079 static int aax_filter(uint8_t *input, int size, MOVContext *c)
1082 unsigned char iv[16];
1084 memcpy(iv, c->file_iv, 16); // iv is overwritten
1085 blocks = size >> 4; // trailing bytes are not encrypted!
1086 av_aes_init(c->aes_decrypt, c->file_key, 128, 1);
1087 av_aes_crypt(c->aes_decrypt, input, input, blocks, iv, 1);
1092 /* read major brand, minor version and compatible brands and store them as metadata */
1093 static int mov_read_ftyp(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1096 int comp_brand_size;
1097 char* comp_brands_str;
1098 uint8_t type[5] = {0};
1099 int ret = ffio_read_size(pb, type, 4);
1103 if (strcmp(type, "qt "))
1105 av_log(c->fc, AV_LOG_DEBUG, "ISO: File Type Major Brand: %.4s\n",(char *)&type);
1106 av_dict_set(&c->fc->metadata, "major_brand", type, 0);
1107 minor_ver = avio_rb32(pb); /* minor version */
1108 av_dict_set_int(&c->fc->metadata, "minor_version", minor_ver, 0);
1110 comp_brand_size = atom.size - 8;
1111 if (comp_brand_size < 0 || comp_brand_size == INT_MAX)
1112 return AVERROR_INVALIDDATA;
1113 comp_brands_str = av_malloc(comp_brand_size + 1); /* Add null terminator */
1114 if (!comp_brands_str)
1115 return AVERROR(ENOMEM);
1117 ret = ffio_read_size(pb, comp_brands_str, comp_brand_size);
1119 av_freep(&comp_brands_str);
1122 comp_brands_str[comp_brand_size] = 0;
1123 av_dict_set(&c->fc->metadata, "compatible_brands",
1124 comp_brands_str, AV_DICT_DONT_STRDUP_VAL);
1129 /* this atom should contain all header atoms */
1130 static int mov_read_moov(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1134 if (c->found_moov) {
1135 av_log(c->fc, AV_LOG_WARNING, "Found duplicated MOOV Atom. Skipped it\n");
1136 avio_skip(pb, atom.size);
1140 if ((ret = mov_read_default(c, pb, atom)) < 0)
1142 /* we parsed the 'moov' atom, we can terminate the parsing as soon as we find the 'mdat' */
1143 /* so we don't parse the whole file if over a network */
1145 return 0; /* now go for mdat */
1148 static MOVFragmentStreamInfo * get_frag_stream_info(
1149 MOVFragmentIndex *frag_index,
1154 MOVFragmentIndexItem * item;
1156 if (index < 0 || index >= frag_index->nb_items)
1158 item = &frag_index->item[index];
1159 for (i = 0; i < item->nb_stream_info; i++)
1160 if (item->stream_info[i].id == id)
1161 return &item->stream_info[i];
1163 // This shouldn't happen
1167 static void set_frag_stream(MOVFragmentIndex *frag_index, int id)
1170 MOVFragmentIndexItem * item;
1172 if (frag_index->current < 0 ||
1173 frag_index->current >= frag_index->nb_items)
1176 item = &frag_index->item[frag_index->current];
1177 for (i = 0; i < item->nb_stream_info; i++)
1178 if (item->stream_info[i].id == id) {
1183 // id not found. This shouldn't happen.
1187 static MOVFragmentStreamInfo * get_current_frag_stream_info(
1188 MOVFragmentIndex *frag_index)
1190 MOVFragmentIndexItem *item;
1191 if (frag_index->current < 0 ||
1192 frag_index->current >= frag_index->nb_items)
1195 item = &frag_index->item[frag_index->current];
1196 if (item->current >= 0 && item->current < item->nb_stream_info)
1197 return &item->stream_info[item->current];
1199 // This shouldn't happen
1203 static int search_frag_moof_offset(MOVFragmentIndex *frag_index, int64_t offset)
1206 int64_t moof_offset;
1208 // Optimize for appending new entries
1209 if (!frag_index->nb_items ||
1210 frag_index->item[frag_index->nb_items - 1].moof_offset < offset)
1211 return frag_index->nb_items;
1214 b = frag_index->nb_items;
1218 moof_offset = frag_index->item[m].moof_offset;
1219 if (moof_offset >= offset)
1221 if (moof_offset <= offset)
1227 static int64_t get_stream_info_time(MOVFragmentStreamInfo * frag_stream_info)
1229 av_assert0(frag_stream_info);
1230 if (frag_stream_info->sidx_pts != AV_NOPTS_VALUE)
1231 return frag_stream_info->sidx_pts;
1232 if (frag_stream_info->first_tfra_pts != AV_NOPTS_VALUE)
1233 return frag_stream_info->first_tfra_pts;
1234 return frag_stream_info->tfdt_dts;
1237 static int64_t get_frag_time(MOVFragmentIndex *frag_index,
1238 int index, int track_id)
1240 MOVFragmentStreamInfo * frag_stream_info;
1244 if (track_id >= 0) {
1245 frag_stream_info = get_frag_stream_info(frag_index, index, track_id);
1246 return frag_stream_info->sidx_pts;
1249 for (i = 0; i < frag_index->item[index].nb_stream_info; i++) {
1250 frag_stream_info = &frag_index->item[index].stream_info[i];
1251 timestamp = get_stream_info_time(frag_stream_info);
1252 if (timestamp != AV_NOPTS_VALUE)
1255 return AV_NOPTS_VALUE;
1258 static int search_frag_timestamp(MOVFragmentIndex *frag_index,
1259 AVStream *st, int64_t timestamp)
1266 // If the stream is referenced by any sidx, limit the search
1267 // to fragments that referenced this stream in the sidx
1268 MOVStreamContext *sc = st->priv_data;
1274 b = frag_index->nb_items;
1277 m0 = m = (a + b) >> 1;
1280 (frag_time = get_frag_time(frag_index, m, id)) == AV_NOPTS_VALUE)
1283 if (m < b && frag_time <= timestamp)
1292 static int update_frag_index(MOVContext *c, int64_t offset)
1295 MOVFragmentIndexItem * item;
1296 MOVFragmentStreamInfo * frag_stream_info;
1298 // If moof_offset already exists in frag_index, return index to it
1299 index = search_frag_moof_offset(&c->frag_index, offset);
1300 if (index < c->frag_index.nb_items &&
1301 c->frag_index.item[index].moof_offset == offset)
1304 // offset is not yet in frag index.
1305 // Insert new item at index (sorted by moof offset)
1306 item = av_fast_realloc(c->frag_index.item,
1307 &c->frag_index.allocated_size,
1308 (c->frag_index.nb_items + 1) *
1309 sizeof(*c->frag_index.item));
1312 c->frag_index.item = item;
1314 frag_stream_info = av_realloc_array(NULL, c->fc->nb_streams,
1315 sizeof(*item->stream_info));
1316 if (!frag_stream_info)
1319 for (i = 0; i < c->fc->nb_streams; i++) {
1320 // Avoid building frag index if streams lack track id.
1321 if (c->fc->streams[i]->id < 0) {
1322 av_free(frag_stream_info);
1323 return AVERROR_INVALIDDATA;
1326 frag_stream_info[i].id = c->fc->streams[i]->id;
1327 frag_stream_info[i].sidx_pts = AV_NOPTS_VALUE;
1328 frag_stream_info[i].tfdt_dts = AV_NOPTS_VALUE;
1329 frag_stream_info[i].next_trun_dts = AV_NOPTS_VALUE;
1330 frag_stream_info[i].first_tfra_pts = AV_NOPTS_VALUE;
1331 frag_stream_info[i].index_entry = -1;
1332 frag_stream_info[i].encryption_index = NULL;
1335 if (index < c->frag_index.nb_items)
1336 memmove(c->frag_index.item + index + 1, c->frag_index.item + index,
1337 (c->frag_index.nb_items - index) * sizeof(*c->frag_index.item));
1339 item = &c->frag_index.item[index];
1340 item->headers_read = 0;
1342 item->nb_stream_info = c->fc->nb_streams;
1343 item->moof_offset = offset;
1344 item->stream_info = frag_stream_info;
1345 c->frag_index.nb_items++;
1350 static void fix_frag_index_entries(MOVFragmentIndex *frag_index, int index,
1351 int id, int entries)
1354 MOVFragmentStreamInfo * frag_stream_info;
1358 for (i = index; i < frag_index->nb_items; i++) {
1359 frag_stream_info = get_frag_stream_info(frag_index, i, id);
1360 if (frag_stream_info && frag_stream_info->index_entry >= 0)
1361 frag_stream_info->index_entry += entries;
1365 static int mov_read_moof(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1367 // Set by mov_read_tfhd(). mov_read_trun() will reject files missing tfhd.
1368 c->fragment.found_tfhd = 0;
1370 if (!c->has_looked_for_mfra && c->use_mfra_for > 0) {
1371 c->has_looked_for_mfra = 1;
1372 if (pb->seekable & AVIO_SEEKABLE_NORMAL) {
1374 av_log(c->fc, AV_LOG_VERBOSE, "stream has moof boxes, will look "
1376 if ((ret = mov_read_mfra(c, pb)) < 0) {
1377 av_log(c->fc, AV_LOG_VERBOSE, "found a moof box but failed to "
1378 "read the mfra (may be a live ismv)\n");
1381 av_log(c->fc, AV_LOG_VERBOSE, "found a moof box but stream is not "
1382 "seekable, can not look for mfra\n");
1385 c->fragment.moof_offset = c->fragment.implicit_offset = avio_tell(pb) - 8;
1386 av_log(c->fc, AV_LOG_TRACE, "moof offset %"PRIx64"\n", c->fragment.moof_offset);
1387 c->frag_index.current = update_frag_index(c, c->fragment.moof_offset);
1388 return mov_read_default(c, pb, atom);
1391 static void mov_metadata_creation_time(AVDictionary **metadata, int64_t time, void *logctx)
1394 if (time >= 2082844800)
1395 time -= 2082844800; /* seconds between 1904-01-01 and Epoch */
1397 if ((int64_t)(time * 1000000ULL) / 1000000 != time) {
1398 av_log(logctx, AV_LOG_DEBUG, "creation_time is not representable\n");
1402 avpriv_dict_set_timestamp(metadata, "creation_time", time * 1000000);
1406 static int mov_read_mdhd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1409 MOVStreamContext *sc;
1411 char language[4] = {0};
1413 int64_t creation_time;
1415 if (c->fc->nb_streams < 1)
1417 st = c->fc->streams[c->fc->nb_streams-1];
1420 if (sc->time_scale) {
1421 av_log(c->fc, AV_LOG_ERROR, "Multiple mdhd?\n");
1422 return AVERROR_INVALIDDATA;
1425 version = avio_r8(pb);
1427 avpriv_request_sample(c->fc, "Version %d", version);
1428 return AVERROR_PATCHWELCOME;
1430 avio_rb24(pb); /* flags */
1432 creation_time = avio_rb64(pb);
1435 creation_time = avio_rb32(pb);
1436 avio_rb32(pb); /* modification time */
1438 mov_metadata_creation_time(&st->metadata, creation_time, c->fc);
1440 sc->time_scale = avio_rb32(pb);
1441 if (sc->time_scale <= 0) {
1442 av_log(c->fc, AV_LOG_ERROR, "Invalid mdhd time scale %d, defaulting to 1\n", sc->time_scale);
1445 st->duration = (version == 1) ? avio_rb64(pb) : avio_rb32(pb); /* duration */
1447 lang = avio_rb16(pb); /* language */
1448 if (ff_mov_lang_to_iso639(lang, language))
1449 av_dict_set(&st->metadata, "language", language, 0);
1450 avio_rb16(pb); /* quality */
1455 static int mov_read_mvhd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1458 int64_t creation_time;
1459 int version = avio_r8(pb); /* version */
1460 avio_rb24(pb); /* flags */
1463 creation_time = avio_rb64(pb);
1466 creation_time = avio_rb32(pb);
1467 avio_rb32(pb); /* modification time */
1469 mov_metadata_creation_time(&c->fc->metadata, creation_time, c->fc);
1470 c->time_scale = avio_rb32(pb); /* time scale */
1471 if (c->time_scale <= 0) {
1472 av_log(c->fc, AV_LOG_ERROR, "Invalid mvhd time scale %d, defaulting to 1\n", c->time_scale);
1475 av_log(c->fc, AV_LOG_TRACE, "time scale = %i\n", c->time_scale);
1477 c->duration = (version == 1) ? avio_rb64(pb) : avio_rb32(pb); /* duration */
1478 // set the AVCodecContext duration because the duration of individual tracks
1479 // may be inaccurate
1480 if (c->time_scale > 0 && !c->trex_data)
1481 c->fc->duration = av_rescale(c->duration, AV_TIME_BASE, c->time_scale);
1482 avio_rb32(pb); /* preferred scale */
1484 avio_rb16(pb); /* preferred volume */
1486 avio_skip(pb, 10); /* reserved */
1488 /* movie display matrix, store it in main context and use it later on */
1489 for (i = 0; i < 3; i++) {
1490 c->movie_display_matrix[i][0] = avio_rb32(pb); // 16.16 fixed point
1491 c->movie_display_matrix[i][1] = avio_rb32(pb); // 16.16 fixed point
1492 c->movie_display_matrix[i][2] = avio_rb32(pb); // 2.30 fixed point
1495 avio_rb32(pb); /* preview time */
1496 avio_rb32(pb); /* preview duration */
1497 avio_rb32(pb); /* poster time */
1498 avio_rb32(pb); /* selection time */
1499 avio_rb32(pb); /* selection duration */
1500 avio_rb32(pb); /* current time */
1501 avio_rb32(pb); /* next track ID */
1506 static int mov_read_enda(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1511 if (c->fc->nb_streams < 1)
1513 st = c->fc->streams[c->fc->nb_streams-1];
1515 little_endian = avio_rb16(pb) & 0xFF;
1516 av_log(c->fc, AV_LOG_TRACE, "enda %d\n", little_endian);
1517 if (little_endian == 1) {
1518 switch (st->codecpar->codec_id) {
1519 case AV_CODEC_ID_PCM_S24BE:
1520 st->codecpar->codec_id = AV_CODEC_ID_PCM_S24LE;
1522 case AV_CODEC_ID_PCM_S32BE:
1523 st->codecpar->codec_id = AV_CODEC_ID_PCM_S32LE;
1525 case AV_CODEC_ID_PCM_F32BE:
1526 st->codecpar->codec_id = AV_CODEC_ID_PCM_F32LE;
1528 case AV_CODEC_ID_PCM_F64BE:
1529 st->codecpar->codec_id = AV_CODEC_ID_PCM_F64LE;
1538 static int mov_read_colr(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1541 uint8_t *icc_profile;
1542 char color_parameter_type[5] = { 0 };
1543 uint16_t color_primaries, color_trc, color_matrix;
1546 if (c->fc->nb_streams < 1)
1548 st = c->fc->streams[c->fc->nb_streams - 1];
1550 ret = ffio_read_size(pb, color_parameter_type, 4);
1553 if (strncmp(color_parameter_type, "nclx", 4) &&
1554 strncmp(color_parameter_type, "nclc", 4) &&
1555 strncmp(color_parameter_type, "prof", 4)) {
1556 av_log(c->fc, AV_LOG_WARNING, "unsupported color_parameter_type %s\n",
1557 color_parameter_type);
1561 if (!strncmp(color_parameter_type, "prof", 4)) {
1562 icc_profile = av_stream_new_side_data(st, AV_PKT_DATA_ICC_PROFILE, atom.size - 4);
1564 return AVERROR(ENOMEM);
1565 ret = ffio_read_size(pb, icc_profile, atom.size - 4);
1569 color_primaries = avio_rb16(pb);
1570 color_trc = avio_rb16(pb);
1571 color_matrix = avio_rb16(pb);
1573 av_log(c->fc, AV_LOG_TRACE,
1574 "%s: pri %d trc %d matrix %d",
1575 color_parameter_type, color_primaries, color_trc, color_matrix);
1577 if (!strncmp(color_parameter_type, "nclx", 4)) {
1578 uint8_t color_range = avio_r8(pb) >> 7;
1579 av_log(c->fc, AV_LOG_TRACE, " full %"PRIu8"", color_range);
1581 st->codecpar->color_range = AVCOL_RANGE_JPEG;
1583 st->codecpar->color_range = AVCOL_RANGE_MPEG;
1586 if (!av_color_primaries_name(color_primaries))
1587 color_primaries = AVCOL_PRI_UNSPECIFIED;
1588 if (!av_color_transfer_name(color_trc))
1589 color_trc = AVCOL_TRC_UNSPECIFIED;
1590 if (!av_color_space_name(color_matrix))
1591 color_matrix = AVCOL_SPC_UNSPECIFIED;
1593 st->codecpar->color_primaries = color_primaries;
1594 st->codecpar->color_trc = color_trc;
1595 st->codecpar->color_space = color_matrix;
1596 av_log(c->fc, AV_LOG_TRACE, "\n");
1601 static int mov_read_fiel(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1604 unsigned mov_field_order;
1605 enum AVFieldOrder decoded_field_order = AV_FIELD_UNKNOWN;
1607 if (c->fc->nb_streams < 1) // will happen with jp2 files
1609 st = c->fc->streams[c->fc->nb_streams-1];
1611 return AVERROR_INVALIDDATA;
1612 mov_field_order = avio_rb16(pb);
1613 if ((mov_field_order & 0xFF00) == 0x0100)
1614 decoded_field_order = AV_FIELD_PROGRESSIVE;
1615 else if ((mov_field_order & 0xFF00) == 0x0200) {
1616 switch (mov_field_order & 0xFF) {
1617 case 0x01: decoded_field_order = AV_FIELD_TT;
1619 case 0x06: decoded_field_order = AV_FIELD_BB;
1621 case 0x09: decoded_field_order = AV_FIELD_TB;
1623 case 0x0E: decoded_field_order = AV_FIELD_BT;
1627 if (decoded_field_order == AV_FIELD_UNKNOWN && mov_field_order) {
1628 av_log(c->fc, AV_LOG_ERROR, "Unknown MOV field order 0x%04x\n", mov_field_order);
1630 st->codecpar->field_order = decoded_field_order;
1635 static int mov_realloc_extradata(AVCodecParameters *par, MOVAtom atom)
1638 uint64_t size = (uint64_t)par->extradata_size + atom.size + 8 + AV_INPUT_BUFFER_PADDING_SIZE;
1639 if (size > INT_MAX || (uint64_t)atom.size > INT_MAX)
1640 return AVERROR_INVALIDDATA;
1641 if ((err = av_reallocp(&par->extradata, size)) < 0) {
1642 par->extradata_size = 0;
1645 par->extradata_size = size - AV_INPUT_BUFFER_PADDING_SIZE;
1649 /* Read a whole atom into the extradata return the size of the atom read, possibly truncated if != atom.size */
1650 static int64_t mov_read_atom_into_extradata(MOVContext *c, AVIOContext *pb, MOVAtom atom,
1651 AVCodecParameters *par, uint8_t *buf)
1653 int64_t result = atom.size;
1656 AV_WB32(buf , atom.size + 8);
1657 AV_WL32(buf + 4, atom.type);
1658 err = ffio_read_size(pb, buf + 8, atom.size);
1660 par->extradata_size -= atom.size;
1662 } else if (err < atom.size) {
1663 av_log(c->fc, AV_LOG_WARNING, "truncated extradata\n");
1664 par->extradata_size -= atom.size - err;
1667 memset(buf + 8 + err, 0, AV_INPUT_BUFFER_PADDING_SIZE);
1671 /* FIXME modify QDM2/SVQ3/H.264 decoders to take full atom as extradata */
1672 static int mov_read_extradata(MOVContext *c, AVIOContext *pb, MOVAtom atom,
1673 enum AVCodecID codec_id)
1676 uint64_t original_size;
1679 if (c->fc->nb_streams < 1) // will happen with jp2 files
1681 st = c->fc->streams[c->fc->nb_streams-1];
1683 if (st->codecpar->codec_id != codec_id)
1684 return 0; /* unexpected codec_id - don't mess with extradata */
1686 original_size = st->codecpar->extradata_size;
1687 err = mov_realloc_extradata(st->codecpar, atom);
1691 err = mov_read_atom_into_extradata(c, pb, atom, st->codecpar, st->codecpar->extradata + original_size);
1694 return 0; // Note: this is the original behavior to ignore truncation.
1697 /* wrapper functions for reading ALAC/AVS/MJPEG/MJPEG2000 extradata atoms only for those codecs */
1698 static int mov_read_alac(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1700 return mov_read_extradata(c, pb, atom, AV_CODEC_ID_ALAC);
1703 static int mov_read_avss(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1705 return mov_read_extradata(c, pb, atom, AV_CODEC_ID_AVS);
1708 static int mov_read_jp2h(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1710 return mov_read_extradata(c, pb, atom, AV_CODEC_ID_JPEG2000);
1713 static int mov_read_dpxe(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1715 return mov_read_extradata(c, pb, atom, AV_CODEC_ID_R10K);
1718 static int mov_read_avid(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1720 int ret = mov_read_extradata(c, pb, atom, AV_CODEC_ID_AVUI);
1722 ret = mov_read_extradata(c, pb, atom, AV_CODEC_ID_DNXHD);
1726 static int mov_read_targa_y216(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1728 int ret = mov_read_extradata(c, pb, atom, AV_CODEC_ID_TARGA_Y216);
1730 if (!ret && c->fc->nb_streams >= 1) {
1731 AVCodecParameters *par = c->fc->streams[c->fc->nb_streams-1]->codecpar;
1732 if (par->extradata_size >= 40) {
1733 par->height = AV_RB16(&par->extradata[36]);
1734 par->width = AV_RB16(&par->extradata[38]);
1740 static int mov_read_ares(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1742 if (c->fc->nb_streams >= 1) {
1743 AVCodecParameters *par = c->fc->streams[c->fc->nb_streams-1]->codecpar;
1744 if (par->codec_tag == MKTAG('A', 'V', 'i', 'n') &&
1745 par->codec_id == AV_CODEC_ID_H264 &&
1749 cid = avio_rb16(pb);
1750 /* For AVID AVCI50, force width of 1440 to be able to select the correct SPS and PPS */
1751 if (cid == 0xd4d || cid == 0xd4e)
1754 } else if ((par->codec_tag == MKTAG('A', 'V', 'd', '1') ||
1755 par->codec_tag == MKTAG('A', 'V', 'j', '2') ||
1756 par->codec_tag == MKTAG('A', 'V', 'd', 'n')) &&
1760 num = avio_rb32(pb);
1761 den = avio_rb32(pb);
1762 if (num <= 0 || den <= 0)
1764 switch (avio_rb32(pb)) {
1766 if (den >= INT_MAX / 2)
1770 c->fc->streams[c->fc->nb_streams-1]->display_aspect_ratio.num = num;
1771 c->fc->streams[c->fc->nb_streams-1]->display_aspect_ratio.den = den;
1778 return mov_read_avid(c, pb, atom);
1781 static int mov_read_aclr(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1785 uint64_t original_size;
1786 if (c->fc->nb_streams >= 1) {
1787 AVCodecParameters *par = c->fc->streams[c->fc->nb_streams-1]->codecpar;
1788 if (par->codec_id == AV_CODEC_ID_H264)
1790 if (atom.size == 16) {
1791 original_size = par->extradata_size;
1792 ret = mov_realloc_extradata(par, atom);
1794 length = mov_read_atom_into_extradata(c, pb, atom, par, par->extradata + original_size);
1795 if (length == atom.size) {
1796 const uint8_t range_value = par->extradata[original_size + 19];
1797 switch (range_value) {
1799 par->color_range = AVCOL_RANGE_MPEG;
1802 par->color_range = AVCOL_RANGE_JPEG;
1805 av_log(c->fc, AV_LOG_WARNING, "ignored unknown aclr value (%d)\n", range_value);
1808 ff_dlog(c->fc, "color_range: %d\n", par->color_range);
1810 /* For some reason the whole atom was not added to the extradata */
1811 av_log(c->fc, AV_LOG_ERROR, "aclr not decoded - incomplete atom\n");
1814 av_log(c->fc, AV_LOG_ERROR, "aclr not decoded - unable to add atom to extradata\n");
1817 av_log(c->fc, AV_LOG_WARNING, "aclr not decoded - unexpected size %"PRId64"\n", atom.size);
1824 static int mov_read_svq3(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1826 return mov_read_extradata(c, pb, atom, AV_CODEC_ID_SVQ3);
1829 static int mov_read_wave(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1834 if (c->fc->nb_streams < 1)
1836 st = c->fc->streams[c->fc->nb_streams-1];
1838 if ((uint64_t)atom.size > (1<<30))
1839 return AVERROR_INVALIDDATA;
1841 if (st->codecpar->codec_id == AV_CODEC_ID_QDM2 ||
1842 st->codecpar->codec_id == AV_CODEC_ID_QDMC ||
1843 st->codecpar->codec_id == AV_CODEC_ID_SPEEX) {
1844 // pass all frma atom to codec, needed at least for QDMC and QDM2
1845 ret = ff_get_extradata(c->fc, st->codecpar, pb, atom.size);
1848 } else if (atom.size > 8) { /* to read frma, esds atoms */
1849 if (st->codecpar->codec_id == AV_CODEC_ID_ALAC && atom.size >= 24) {
1851 ret = ffio_ensure_seekback(pb, 8);
1854 buffer = avio_rb64(pb);
1856 if ( (buffer & 0xFFFFFFFF) == MKBETAG('f','r','m','a')
1857 && buffer >> 32 <= atom.size
1858 && buffer >> 32 >= 8) {
1861 } else if (!st->codecpar->extradata_size) {
1862 #define ALAC_EXTRADATA_SIZE 36
1863 st->codecpar->extradata = av_mallocz(ALAC_EXTRADATA_SIZE + AV_INPUT_BUFFER_PADDING_SIZE);
1864 if (!st->codecpar->extradata)
1865 return AVERROR(ENOMEM);
1866 st->codecpar->extradata_size = ALAC_EXTRADATA_SIZE;
1867 AV_WB32(st->codecpar->extradata , ALAC_EXTRADATA_SIZE);
1868 AV_WB32(st->codecpar->extradata + 4, MKTAG('a','l','a','c'));
1869 AV_WB64(st->codecpar->extradata + 12, buffer);
1870 avio_read(pb, st->codecpar->extradata + 20, 16);
1871 avio_skip(pb, atom.size - 24);
1875 if ((ret = mov_read_default(c, pb, atom)) < 0)
1878 avio_skip(pb, atom.size);
1883 * This function reads atom content and puts data in extradata without tag
1884 * nor size unlike mov_read_extradata.
1886 static int mov_read_glbl(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1891 if (c->fc->nb_streams < 1)
1893 st = c->fc->streams[c->fc->nb_streams-1];
1895 if ((uint64_t)atom.size > (1<<30))
1896 return AVERROR_INVALIDDATA;
1898 if (atom.size >= 10) {
1899 // Broken files created by legacy versions of libavformat will
1900 // wrap a whole fiel atom inside of a glbl atom.
1901 unsigned size = avio_rb32(pb);
1902 unsigned type = avio_rl32(pb);
1903 avio_seek(pb, -8, SEEK_CUR);
1904 if (type == MKTAG('f','i','e','l') && size == atom.size)
1905 return mov_read_default(c, pb, atom);
1907 if (st->codecpar->extradata_size > 1 && st->codecpar->extradata) {
1908 av_log(c->fc, AV_LOG_WARNING, "ignoring multiple glbl\n");
1911 ret = ff_get_extradata(c->fc, st->codecpar, pb, atom.size);
1914 if (atom.type == MKTAG('h','v','c','C') && st->codecpar->codec_tag == MKTAG('d','v','h','1'))
1915 /* HEVC-based Dolby Vision derived from hvc1.
1916 Happens to match with an identifier
1917 previously utilized for DV. Thus, if we have
1918 the hvcC extradata box available as specified,
1919 set codec to HEVC */
1920 st->codecpar->codec_id = AV_CODEC_ID_HEVC;
1925 static int mov_read_dvc1(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1928 uint8_t profile_level;
1931 if (c->fc->nb_streams < 1)
1933 st = c->fc->streams[c->fc->nb_streams-1];
1935 if (atom.size >= (1<<28) || atom.size < 7)
1936 return AVERROR_INVALIDDATA;
1938 profile_level = avio_r8(pb);
1939 if ((profile_level & 0xf0) != 0xc0)
1942 avio_seek(pb, 6, SEEK_CUR);
1943 ret = ff_get_extradata(c->fc, st->codecpar, pb, atom.size - 7);
1951 * An strf atom is a BITMAPINFOHEADER struct. This struct is 40 bytes itself,
1952 * but can have extradata appended at the end after the 40 bytes belonging
1955 static int mov_read_strf(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1960 if (c->fc->nb_streams < 1)
1962 if (atom.size <= 40)
1964 st = c->fc->streams[c->fc->nb_streams-1];
1966 if ((uint64_t)atom.size > (1<<30))
1967 return AVERROR_INVALIDDATA;
1970 ret = ff_get_extradata(c->fc, st->codecpar, pb, atom.size - 40);
1977 static int mov_read_stco(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1980 MOVStreamContext *sc;
1981 unsigned int i, entries;
1983 if (c->trak_index < 0) {
1984 av_log(c->fc, AV_LOG_WARNING, "STCO outside TRAK\n");
1987 if (c->fc->nb_streams < 1)
1989 st = c->fc->streams[c->fc->nb_streams-1];
1992 avio_r8(pb); /* version */
1993 avio_rb24(pb); /* flags */
1995 entries = avio_rb32(pb);
2000 if (sc->chunk_offsets)
2001 av_log(c->fc, AV_LOG_WARNING, "Duplicated STCO atom\n");
2002 av_free(sc->chunk_offsets);
2003 sc->chunk_count = 0;
2004 sc->chunk_offsets = av_malloc_array(entries, sizeof(*sc->chunk_offsets));
2005 if (!sc->chunk_offsets)
2006 return AVERROR(ENOMEM);
2007 sc->chunk_count = entries;
2009 if (atom.type == MKTAG('s','t','c','o'))
2010 for (i = 0; i < entries && !pb->eof_reached; i++)
2011 sc->chunk_offsets[i] = avio_rb32(pb);
2012 else if (atom.type == MKTAG('c','o','6','4'))
2013 for (i = 0; i < entries && !pb->eof_reached; i++)
2014 sc->chunk_offsets[i] = avio_rb64(pb);
2016 return AVERROR_INVALIDDATA;
2018 sc->chunk_count = i;
2020 if (pb->eof_reached) {
2021 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted STCO atom\n");
2028 static int mov_codec_id(AVStream *st, uint32_t format)
2030 int id = ff_codec_get_id(ff_codec_movaudio_tags, format);
2033 ((format & 0xFFFF) == 'm' + ('s' << 8) ||
2034 (format & 0xFFFF) == 'T' + ('S' << 8)))
2035 id = ff_codec_get_id(ff_codec_wav_tags, av_bswap32(format) & 0xFFFF);
2037 if (st->codecpar->codec_type != AVMEDIA_TYPE_VIDEO && id > 0) {
2038 st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
2039 } else if (st->codecpar->codec_type != AVMEDIA_TYPE_AUDIO &&
2040 /* skip old ASF MPEG-4 tag */
2041 format && format != MKTAG('m','p','4','s')) {
2042 id = ff_codec_get_id(ff_codec_movvideo_tags, format);
2044 id = ff_codec_get_id(ff_codec_bmp_tags, format);
2046 st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
2047 else if (st->codecpar->codec_type == AVMEDIA_TYPE_DATA ||
2048 (st->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE &&
2049 st->codecpar->codec_id == AV_CODEC_ID_NONE)) {
2050 id = ff_codec_get_id(ff_codec_movsubtitle_tags, format);
2052 st->codecpar->codec_type = AVMEDIA_TYPE_SUBTITLE;
2054 id = ff_codec_get_id(ff_codec_movdata_tags, format);
2058 st->codecpar->codec_tag = format;
2063 static void mov_parse_stsd_video(MOVContext *c, AVIOContext *pb,
2064 AVStream *st, MOVStreamContext *sc)
2066 uint8_t codec_name[32] = { 0 };
2070 /* The first 16 bytes of the video sample description are already
2071 * read in ff_mov_read_stsd_entries() */
2072 stsd_start = avio_tell(pb) - 16;
2074 avio_rb16(pb); /* version */
2075 avio_rb16(pb); /* revision level */
2076 avio_rb32(pb); /* vendor */
2077 avio_rb32(pb); /* temporal quality */
2078 avio_rb32(pb); /* spatial quality */
2080 st->codecpar->width = avio_rb16(pb); /* width */
2081 st->codecpar->height = avio_rb16(pb); /* height */
2083 avio_rb32(pb); /* horiz resolution */
2084 avio_rb32(pb); /* vert resolution */
2085 avio_rb32(pb); /* data size, always 0 */
2086 avio_rb16(pb); /* frames per samples */
2088 len = avio_r8(pb); /* codec name, pascal string */
2091 mov_read_mac_string(c, pb, len, codec_name, sizeof(codec_name));
2093 avio_skip(pb, 31 - len);
2096 av_dict_set(&st->metadata, "encoder", codec_name, 0);
2098 /* codec_tag YV12 triggers an UV swap in rawdec.c */
2099 if (!strncmp(codec_name, "Planar Y'CbCr 8-bit 4:2:0", 25)) {
2100 st->codecpar->codec_tag = MKTAG('I', '4', '2', '0');
2101 st->codecpar->width &= ~1;
2102 st->codecpar->height &= ~1;
2104 /* Flash Media Server uses tag H.263 with Sorenson Spark */
2105 if (st->codecpar->codec_tag == MKTAG('H','2','6','3') &&
2106 !strncmp(codec_name, "Sorenson H263", 13))
2107 st->codecpar->codec_id = AV_CODEC_ID_FLV1;
2109 st->codecpar->bits_per_coded_sample = avio_rb16(pb); /* depth */
2111 avio_seek(pb, stsd_start, SEEK_SET);
2113 if (ff_get_qtpalette(st->codecpar->codec_id, pb, sc->palette)) {
2114 st->codecpar->bits_per_coded_sample &= 0x1F;
2115 sc->has_palette = 1;
2119 static void mov_parse_stsd_audio(MOVContext *c, AVIOContext *pb,
2120 AVStream *st, MOVStreamContext *sc)
2122 int bits_per_sample, flags;
2123 uint16_t version = avio_rb16(pb);
2124 AVDictionaryEntry *compatible_brands = av_dict_get(c->fc->metadata, "compatible_brands", NULL, AV_DICT_MATCH_CASE);
2126 avio_rb16(pb); /* revision level */
2127 avio_rb32(pb); /* vendor */
2129 st->codecpar->channels = avio_rb16(pb); /* channel count */
2130 st->codecpar->bits_per_coded_sample = avio_rb16(pb); /* sample size */
2131 av_log(c->fc, AV_LOG_TRACE, "audio channels %d\n", st->codecpar->channels);
2133 sc->audio_cid = avio_rb16(pb);
2134 avio_rb16(pb); /* packet size = 0 */
2136 st->codecpar->sample_rate = ((avio_rb32(pb) >> 16));
2138 // Read QT version 1 fields. In version 0 these do not exist.
2139 av_log(c->fc, AV_LOG_TRACE, "version =%d, isom =%d\n", version, c->isom);
2141 (compatible_brands && strstr(compatible_brands->value, "qt ")) ||
2142 (sc->stsd_version == 0 && version > 0)) {
2144 sc->samples_per_frame = avio_rb32(pb);
2145 avio_rb32(pb); /* bytes per packet */
2146 sc->bytes_per_frame = avio_rb32(pb);
2147 avio_rb32(pb); /* bytes per sample */
2148 } else if (version == 2) {
2149 avio_rb32(pb); /* sizeof struct only */
2150 st->codecpar->sample_rate = av_int2double(avio_rb64(pb));
2151 st->codecpar->channels = avio_rb32(pb);
2152 avio_rb32(pb); /* always 0x7F000000 */
2153 st->codecpar->bits_per_coded_sample = avio_rb32(pb);
2155 flags = avio_rb32(pb); /* lpcm format specific flag */
2156 sc->bytes_per_frame = avio_rb32(pb);
2157 sc->samples_per_frame = avio_rb32(pb);
2158 if (st->codecpar->codec_tag == MKTAG('l','p','c','m'))
2159 st->codecpar->codec_id =
2160 ff_mov_get_lpcm_codec_id(st->codecpar->bits_per_coded_sample,
2163 if (version == 0 || (version == 1 && sc->audio_cid != -2)) {
2164 /* can't correctly handle variable sized packet as audio unit */
2165 switch (st->codecpar->codec_id) {
2166 case AV_CODEC_ID_MP2:
2167 case AV_CODEC_ID_MP3:
2168 st->need_parsing = AVSTREAM_PARSE_FULL;
2174 if (sc->format == 0) {
2175 if (st->codecpar->bits_per_coded_sample == 8)
2176 st->codecpar->codec_id = mov_codec_id(st, MKTAG('r','a','w',' '));
2177 else if (st->codecpar->bits_per_coded_sample == 16)
2178 st->codecpar->codec_id = mov_codec_id(st, MKTAG('t','w','o','s'));
2181 switch (st->codecpar->codec_id) {
2182 case AV_CODEC_ID_PCM_S8:
2183 case AV_CODEC_ID_PCM_U8:
2184 if (st->codecpar->bits_per_coded_sample == 16)
2185 st->codecpar->codec_id = AV_CODEC_ID_PCM_S16BE;
2187 case AV_CODEC_ID_PCM_S16LE:
2188 case AV_CODEC_ID_PCM_S16BE:
2189 if (st->codecpar->bits_per_coded_sample == 8)
2190 st->codecpar->codec_id = AV_CODEC_ID_PCM_S8;
2191 else if (st->codecpar->bits_per_coded_sample == 24)
2192 st->codecpar->codec_id =
2193 st->codecpar->codec_id == AV_CODEC_ID_PCM_S16BE ?
2194 AV_CODEC_ID_PCM_S24BE : AV_CODEC_ID_PCM_S24LE;
2195 else if (st->codecpar->bits_per_coded_sample == 32)
2196 st->codecpar->codec_id =
2197 st->codecpar->codec_id == AV_CODEC_ID_PCM_S16BE ?
2198 AV_CODEC_ID_PCM_S32BE : AV_CODEC_ID_PCM_S32LE;
2200 /* set values for old format before stsd version 1 appeared */
2201 case AV_CODEC_ID_MACE3:
2202 sc->samples_per_frame = 6;
2203 sc->bytes_per_frame = 2 * st->codecpar->channels;
2205 case AV_CODEC_ID_MACE6:
2206 sc->samples_per_frame = 6;
2207 sc->bytes_per_frame = 1 * st->codecpar->channels;
2209 case AV_CODEC_ID_ADPCM_IMA_QT:
2210 sc->samples_per_frame = 64;
2211 sc->bytes_per_frame = 34 * st->codecpar->channels;
2213 case AV_CODEC_ID_GSM:
2214 sc->samples_per_frame = 160;
2215 sc->bytes_per_frame = 33;
2221 bits_per_sample = av_get_bits_per_sample(st->codecpar->codec_id);
2222 if (bits_per_sample) {
2223 st->codecpar->bits_per_coded_sample = bits_per_sample;
2224 sc->sample_size = (bits_per_sample >> 3) * st->codecpar->channels;
2228 static void mov_parse_stsd_subtitle(MOVContext *c, AVIOContext *pb,
2229 AVStream *st, MOVStreamContext *sc,
2232 // ttxt stsd contains display flags, justification, background
2233 // color, fonts, and default styles, so fake an atom to read it
2234 MOVAtom fake_atom = { .size = size };
2235 // mp4s contains a regular esds atom
2236 if (st->codecpar->codec_tag != AV_RL32("mp4s"))
2237 mov_read_glbl(c, pb, fake_atom);
2238 st->codecpar->width = sc->width;
2239 st->codecpar->height = sc->height;
2242 static uint32_t yuv_to_rgba(uint32_t ycbcr)
2247 y = (ycbcr >> 16) & 0xFF;
2248 cr = (ycbcr >> 8) & 0xFF;
2251 b = av_clip_uint8((1164 * (y - 16) + 2018 * (cb - 128)) / 1000);
2252 g = av_clip_uint8((1164 * (y - 16) - 813 * (cr - 128) - 391 * (cb - 128)) / 1000);
2253 r = av_clip_uint8((1164 * (y - 16) + 1596 * (cr - 128) ) / 1000);
2255 return (r << 16) | (g << 8) | b;
2258 static int mov_rewrite_dvd_sub_extradata(AVStream *st)
2260 char buf[256] = {0};
2261 uint8_t *src = st->codecpar->extradata;
2264 if (st->codecpar->extradata_size != 64)
2267 if (st->codecpar->width > 0 && st->codecpar->height > 0)
2268 snprintf(buf, sizeof(buf), "size: %dx%d\n",
2269 st->codecpar->width, st->codecpar->height);
2270 av_strlcat(buf, "palette: ", sizeof(buf));
2272 for (i = 0; i < 16; i++) {
2273 uint32_t yuv = AV_RB32(src + i * 4);
2274 uint32_t rgba = yuv_to_rgba(yuv);
2276 av_strlcatf(buf, sizeof(buf), "%06"PRIx32"%s", rgba, i != 15 ? ", " : "");
2279 if (av_strlcat(buf, "\n", sizeof(buf)) >= sizeof(buf))
2282 ret = ff_alloc_extradata(st->codecpar, strlen(buf));
2285 memcpy(st->codecpar->extradata, buf, st->codecpar->extradata_size);
2290 static int mov_parse_stsd_data(MOVContext *c, AVIOContext *pb,
2291 AVStream *st, MOVStreamContext *sc,
2296 if (st->codecpar->codec_tag == MKTAG('t','m','c','d')) {
2297 if ((int)size != size)
2298 return AVERROR(ENOMEM);
2300 ret = ff_get_extradata(c->fc, st->codecpar, pb, size);
2304 MOVStreamContext *tmcd_ctx = st->priv_data;
2306 val = AV_RB32(st->codecpar->extradata + 4);
2307 tmcd_ctx->tmcd_flags = val;
2308 st->avg_frame_rate.num = AV_RB32(st->codecpar->extradata + 8); /* timescale */
2309 st->avg_frame_rate.den = AV_RB32(st->codecpar->extradata + 12); /* frameDuration */
2310 #if FF_API_LAVF_AVCTX
2311 FF_DISABLE_DEPRECATION_WARNINGS
2312 st->codec->time_base = av_inv_q(st->avg_frame_rate);
2313 FF_ENABLE_DEPRECATION_WARNINGS
2315 /* adjust for per frame dur in counter mode */
2316 if (tmcd_ctx->tmcd_flags & 0x0008) {
2317 int timescale = AV_RB32(st->codecpar->extradata + 8);
2318 int framedur = AV_RB32(st->codecpar->extradata + 12);
2319 st->avg_frame_rate.num *= timescale;
2320 st->avg_frame_rate.den *= framedur;
2321 #if FF_API_LAVF_AVCTX
2322 FF_DISABLE_DEPRECATION_WARNINGS
2323 st->codec->time_base.den *= timescale;
2324 st->codec->time_base.num *= framedur;
2325 FF_ENABLE_DEPRECATION_WARNINGS
2329 uint32_t len = AV_RB32(st->codecpar->extradata + 18); /* name atom length */
2330 uint32_t format = AV_RB32(st->codecpar->extradata + 22);
2331 if (format == AV_RB32("name") && (int64_t)size >= (int64_t)len + 18) {
2332 uint16_t str_size = AV_RB16(st->codecpar->extradata + 26); /* string length */
2333 if (str_size > 0 && size >= (int)str_size + 30 &&
2334 st->codecpar->extradata[30] /* Don't add empty string */) {
2335 char *reel_name = av_malloc(str_size + 1);
2337 return AVERROR(ENOMEM);
2338 memcpy(reel_name, st->codecpar->extradata + 30, str_size);
2339 reel_name[str_size] = 0; /* Add null terminator */
2340 av_dict_set(&st->metadata, "reel_name", reel_name,
2341 AV_DICT_DONT_STRDUP_VAL);
2347 /* other codec type, just skip (rtp, mp4s ...) */
2348 avio_skip(pb, size);
2353 static int mov_finalize_stsd_codec(MOVContext *c, AVIOContext *pb,
2354 AVStream *st, MOVStreamContext *sc)
2356 if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO &&
2357 !st->codecpar->sample_rate && sc->time_scale > 1)
2358 st->codecpar->sample_rate = sc->time_scale;
2360 /* special codec parameters handling */
2361 switch (st->codecpar->codec_id) {
2362 #if CONFIG_DV_DEMUXER
2363 case AV_CODEC_ID_DVAUDIO:
2364 c->dv_fctx = avformat_alloc_context();
2366 av_log(c->fc, AV_LOG_ERROR, "dv demux context alloc error\n");
2367 return AVERROR(ENOMEM);
2369 c->dv_demux = avpriv_dv_init_demux(c->dv_fctx);
2371 av_log(c->fc, AV_LOG_ERROR, "dv demux context init error\n");
2372 return AVERROR(ENOMEM);
2374 sc->dv_audio_container = 1;
2375 st->codecpar->codec_id = AV_CODEC_ID_PCM_S16LE;
2378 /* no ifdef since parameters are always those */
2379 case AV_CODEC_ID_QCELP:
2380 st->codecpar->channels = 1;
2381 // force sample rate for qcelp when not stored in mov
2382 if (st->codecpar->codec_tag != MKTAG('Q','c','l','p'))
2383 st->codecpar->sample_rate = 8000;
2384 // FIXME: Why is the following needed for some files?
2385 sc->samples_per_frame = 160;
2386 if (!sc->bytes_per_frame)
2387 sc->bytes_per_frame = 35;
2389 case AV_CODEC_ID_AMR_NB:
2390 st->codecpar->channels = 1;
2391 /* force sample rate for amr, stsd in 3gp does not store sample rate */
2392 st->codecpar->sample_rate = 8000;
2394 case AV_CODEC_ID_AMR_WB:
2395 st->codecpar->channels = 1;
2396 st->codecpar->sample_rate = 16000;
2398 case AV_CODEC_ID_MP2:
2399 case AV_CODEC_ID_MP3:
2400 /* force type after stsd for m1a hdlr */
2401 st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
2403 case AV_CODEC_ID_GSM:
2404 case AV_CODEC_ID_ADPCM_MS:
2405 case AV_CODEC_ID_ADPCM_IMA_WAV:
2406 case AV_CODEC_ID_ILBC:
2407 case AV_CODEC_ID_MACE3:
2408 case AV_CODEC_ID_MACE6:
2409 case AV_CODEC_ID_QDM2:
2410 st->codecpar->block_align = sc->bytes_per_frame;
2412 case AV_CODEC_ID_ALAC:
2413 if (st->codecpar->extradata_size == 36) {
2414 st->codecpar->channels = AV_RB8 (st->codecpar->extradata + 21);
2415 st->codecpar->sample_rate = AV_RB32(st->codecpar->extradata + 32);
2418 case AV_CODEC_ID_AC3:
2419 case AV_CODEC_ID_EAC3:
2420 case AV_CODEC_ID_MPEG1VIDEO:
2421 case AV_CODEC_ID_VC1:
2422 case AV_CODEC_ID_VP8:
2423 case AV_CODEC_ID_VP9:
2424 st->need_parsing = AVSTREAM_PARSE_FULL;
2426 case AV_CODEC_ID_AV1:
2427 st->need_parsing = AVSTREAM_PARSE_HEADERS;
2435 static int mov_skip_multiple_stsd(MOVContext *c, AVIOContext *pb,
2436 int codec_tag, int format,
2439 int video_codec_id = ff_codec_get_id(ff_codec_movvideo_tags, format);
2442 (codec_tag != format &&
2443 // AVID 1:1 samples with differing data format and codec tag exist
2444 (codec_tag != AV_RL32("AV1x") || format != AV_RL32("AVup")) &&
2445 // prores is allowed to have differing data format and codec tag
2446 codec_tag != AV_RL32("apcn") && codec_tag != AV_RL32("apch") &&
2448 codec_tag != AV_RL32("dvpp") && codec_tag != AV_RL32("dvcp") &&
2449 (c->fc->video_codec_id ? video_codec_id != c->fc->video_codec_id
2450 : codec_tag != MKTAG('j','p','e','g')))) {
2451 /* Multiple fourcc, we skip JPEG. This is not correct, we should
2452 * export it as a separate AVStream but this needs a few changes
2453 * in the MOV demuxer, patch welcome. */
2455 av_log(c->fc, AV_LOG_WARNING, "multiple fourcc not supported\n");
2456 avio_skip(pb, size);
2463 int ff_mov_read_stsd_entries(MOVContext *c, AVIOContext *pb, int entries)
2466 MOVStreamContext *sc;
2467 int pseudo_stream_id;
2469 av_assert0 (c->fc->nb_streams >= 1);
2470 st = c->fc->streams[c->fc->nb_streams-1];
2473 for (pseudo_stream_id = 0;
2474 pseudo_stream_id < entries && !pb->eof_reached;
2475 pseudo_stream_id++) {
2476 //Parsing Sample description table
2478 int ret, dref_id = 1;
2479 MOVAtom a = { AV_RL32("stsd") };
2480 int64_t start_pos = avio_tell(pb);
2481 int64_t size = avio_rb32(pb); /* size */
2482 uint32_t format = avio_rl32(pb); /* data format */
2485 avio_rb32(pb); /* reserved */
2486 avio_rb16(pb); /* reserved */
2487 dref_id = avio_rb16(pb);
2488 } else if (size <= 7) {
2489 av_log(c->fc, AV_LOG_ERROR,
2490 "invalid size %"PRId64" in stsd\n", size);
2491 return AVERROR_INVALIDDATA;
2494 if (mov_skip_multiple_stsd(c, pb, st->codecpar->codec_tag, format,
2495 size - (avio_tell(pb) - start_pos))) {
2500 sc->pseudo_stream_id = st->codecpar->codec_tag ? -1 : pseudo_stream_id;
2501 sc->dref_id= dref_id;
2502 sc->format = format;
2504 id = mov_codec_id(st, format);
2506 av_log(c->fc, AV_LOG_TRACE,
2507 "size=%"PRId64" 4CC=%s codec_type=%d\n", size,
2508 av_fourcc2str(format), st->codecpar->codec_type);
2510 st->codecpar->codec_id = id;
2511 if (st->codecpar->codec_type==AVMEDIA_TYPE_VIDEO) {
2512 mov_parse_stsd_video(c, pb, st, sc);
2513 } else if (st->codecpar->codec_type==AVMEDIA_TYPE_AUDIO) {
2514 mov_parse_stsd_audio(c, pb, st, sc);
2515 if (st->codecpar->sample_rate < 0) {
2516 av_log(c->fc, AV_LOG_ERROR, "Invalid sample rate %d\n", st->codecpar->sample_rate);
2517 return AVERROR_INVALIDDATA;
2519 } else if (st->codecpar->codec_type==AVMEDIA_TYPE_SUBTITLE){
2520 mov_parse_stsd_subtitle(c, pb, st, sc,
2521 size - (avio_tell(pb) - start_pos));
2523 ret = mov_parse_stsd_data(c, pb, st, sc,
2524 size - (avio_tell(pb) - start_pos));
2528 /* this will read extra atoms at the end (wave, alac, damr, avcC, hvcC, SMI ...) */
2529 a.size = size - (avio_tell(pb) - start_pos);
2531 if ((ret = mov_read_default(c, pb, a)) < 0)
2533 } else if (a.size > 0)
2534 avio_skip(pb, a.size);
2536 if (sc->extradata && st->codecpar->extradata) {
2537 int extra_size = st->codecpar->extradata_size;
2539 /* Move the current stream extradata to the stream context one. */
2540 sc->extradata_size[pseudo_stream_id] = extra_size;
2541 sc->extradata[pseudo_stream_id] = st->codecpar->extradata;
2542 st->codecpar->extradata = NULL;
2543 st->codecpar->extradata_size = 0;
2548 if (pb->eof_reached) {
2549 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted STSD atom\n");
2556 static int mov_read_stsd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2559 MOVStreamContext *sc;
2562 if (c->fc->nb_streams < 1)
2564 st = c->fc->streams[c->fc->nb_streams - 1];
2567 sc->stsd_version = avio_r8(pb);
2568 avio_rb24(pb); /* flags */
2569 entries = avio_rb32(pb);
2571 /* Each entry contains a size (4 bytes) and format (4 bytes). */
2572 if (entries <= 0 || entries > atom.size / 8) {
2573 av_log(c->fc, AV_LOG_ERROR, "invalid STSD entries %d\n", entries);
2574 return AVERROR_INVALIDDATA;
2577 if (sc->extradata) {
2578 av_log(c->fc, AV_LOG_ERROR,
2579 "Duplicate stsd found in this track.\n");
2580 return AVERROR_INVALIDDATA;
2583 /* Prepare space for hosting multiple extradata. */
2584 sc->extradata = av_mallocz_array(entries, sizeof(*sc->extradata));
2586 return AVERROR(ENOMEM);
2588 sc->extradata_size = av_mallocz_array(entries, sizeof(*sc->extradata_size));
2589 if (!sc->extradata_size) {
2590 ret = AVERROR(ENOMEM);
2594 ret = ff_mov_read_stsd_entries(c, pb, entries);
2598 /* Restore back the primary extradata. */
2599 av_freep(&st->codecpar->extradata);
2600 st->codecpar->extradata_size = sc->extradata_size[0];
2601 if (sc->extradata_size[0]) {
2602 st->codecpar->extradata = av_mallocz(sc->extradata_size[0] + AV_INPUT_BUFFER_PADDING_SIZE);
2603 if (!st->codecpar->extradata)
2604 return AVERROR(ENOMEM);
2605 memcpy(st->codecpar->extradata, sc->extradata[0], sc->extradata_size[0]);
2608 return mov_finalize_stsd_codec(c, pb, st, sc);
2610 if (sc->extradata) {
2612 for (j = 0; j < sc->stsd_count; j++)
2613 av_freep(&sc->extradata[j]);
2616 av_freep(&sc->extradata);
2617 av_freep(&sc->extradata_size);
2621 static int mov_read_stsc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2624 MOVStreamContext *sc;
2625 unsigned int i, entries;
2627 if (c->fc->nb_streams < 1)
2629 st = c->fc->streams[c->fc->nb_streams-1];
2632 avio_r8(pb); /* version */
2633 avio_rb24(pb); /* flags */
2635 entries = avio_rb32(pb);
2636 if ((uint64_t)entries * 12 + 4 > atom.size)
2637 return AVERROR_INVALIDDATA;
2639 av_log(c->fc, AV_LOG_TRACE, "track[%u].stsc.entries = %u\n", c->fc->nb_streams - 1, entries);
2644 av_log(c->fc, AV_LOG_WARNING, "Duplicated STSC atom\n");
2645 av_free(sc->stsc_data);
2647 sc->stsc_data = av_malloc_array(entries, sizeof(*sc->stsc_data));
2649 return AVERROR(ENOMEM);
2651 for (i = 0; i < entries && !pb->eof_reached; i++) {
2652 sc->stsc_data[i].first = avio_rb32(pb);
2653 sc->stsc_data[i].count = avio_rb32(pb);
2654 sc->stsc_data[i].id = avio_rb32(pb);
2658 for (i = sc->stsc_count - 1; i < UINT_MAX; i--) {
2659 int64_t first_min = i + 1;
2660 if ((i+1 < sc->stsc_count && sc->stsc_data[i].first >= sc->stsc_data[i+1].first) ||
2661 (i > 0 && sc->stsc_data[i].first <= sc->stsc_data[i-1].first) ||
2662 sc->stsc_data[i].first < first_min ||
2663 sc->stsc_data[i].count < 1 ||
2664 sc->stsc_data[i].id < 1) {
2665 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);
2666 if (i+1 >= sc->stsc_count) {
2667 if (sc->stsc_data[i].count == 0 && i > 0) {
2671 sc->stsc_data[i].first = FFMAX(sc->stsc_data[i].first, first_min);
2672 if (i > 0 && sc->stsc_data[i].first <= sc->stsc_data[i-1].first)
2673 sc->stsc_data[i].first = FFMIN(sc->stsc_data[i-1].first + 1LL, INT_MAX);
2674 sc->stsc_data[i].count = FFMAX(sc->stsc_data[i].count, 1);
2675 sc->stsc_data[i].id = FFMAX(sc->stsc_data[i].id, 1);
2678 av_assert0(sc->stsc_data[i+1].first >= 2);
2679 // We replace this entry by the next valid
2680 sc->stsc_data[i].first = sc->stsc_data[i+1].first - 1;
2681 sc->stsc_data[i].count = sc->stsc_data[i+1].count;
2682 sc->stsc_data[i].id = sc->stsc_data[i+1].id;
2686 if (pb->eof_reached) {
2687 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted STSC atom\n");
2694 static inline int mov_stsc_index_valid(unsigned int index, unsigned int count)
2696 return index < count - 1;
2699 /* Compute the samples value for the stsc entry at the given index. */
2700 static inline int64_t mov_get_stsc_samples(MOVStreamContext *sc, unsigned int index)
2704 if (mov_stsc_index_valid(index, sc->stsc_count))
2705 chunk_count = sc->stsc_data[index + 1].first - sc->stsc_data[index].first;
2707 // Validation for stsc / stco happens earlier in mov_read_stsc + mov_read_trak.
2708 av_assert0(sc->stsc_data[index].first <= sc->chunk_count);
2709 chunk_count = sc->chunk_count - (sc->stsc_data[index].first - 1);
2712 return sc->stsc_data[index].count * (int64_t)chunk_count;
2715 static int mov_read_stps(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2718 MOVStreamContext *sc;
2719 unsigned i, entries;
2721 if (c->fc->nb_streams < 1)
2723 st = c->fc->streams[c->fc->nb_streams-1];
2726 avio_rb32(pb); // version + flags
2728 entries = avio_rb32(pb);
2730 av_log(c->fc, AV_LOG_WARNING, "Duplicated STPS atom\n");
2731 av_free(sc->stps_data);
2733 sc->stps_data = av_malloc_array(entries, sizeof(*sc->stps_data));
2735 return AVERROR(ENOMEM);
2737 for (i = 0; i < entries && !pb->eof_reached; i++) {
2738 sc->stps_data[i] = avio_rb32(pb);
2743 if (pb->eof_reached) {
2744 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted STPS atom\n");
2751 static int mov_read_stss(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2754 MOVStreamContext *sc;
2755 unsigned int i, entries;
2757 if (c->fc->nb_streams < 1)
2759 st = c->fc->streams[c->fc->nb_streams-1];
2762 avio_r8(pb); /* version */
2763 avio_rb24(pb); /* flags */
2765 entries = avio_rb32(pb);
2767 av_log(c->fc, AV_LOG_TRACE, "keyframe_count = %u\n", entries);
2770 sc->keyframe_absent = 1;
2771 if (!st->need_parsing && st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO)
2772 st->need_parsing = AVSTREAM_PARSE_HEADERS;
2776 av_log(c->fc, AV_LOG_WARNING, "Duplicated STSS atom\n");
2777 if (entries >= UINT_MAX / sizeof(int))
2778 return AVERROR_INVALIDDATA;
2779 av_freep(&sc->keyframes);
2780 sc->keyframe_count = 0;
2781 sc->keyframes = av_malloc_array(entries, sizeof(*sc->keyframes));
2783 return AVERROR(ENOMEM);
2785 for (i = 0; i < entries && !pb->eof_reached; i++) {
2786 sc->keyframes[i] = avio_rb32(pb);
2789 sc->keyframe_count = i;
2791 if (pb->eof_reached) {
2792 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted STSS atom\n");
2799 static int mov_read_stsz(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2802 MOVStreamContext *sc;
2803 unsigned int i, entries, sample_size, field_size, num_bytes;
2808 if (c->fc->nb_streams < 1)
2810 st = c->fc->streams[c->fc->nb_streams-1];
2813 avio_r8(pb); /* version */
2814 avio_rb24(pb); /* flags */
2816 if (atom.type == MKTAG('s','t','s','z')) {
2817 sample_size = avio_rb32(pb);
2818 if (!sc->sample_size) /* do not overwrite value computed in stsd */
2819 sc->sample_size = sample_size;
2820 sc->stsz_sample_size = sample_size;
2824 avio_rb24(pb); /* reserved */
2825 field_size = avio_r8(pb);
2827 entries = avio_rb32(pb);
2829 av_log(c->fc, AV_LOG_TRACE, "sample_size = %u sample_count = %u\n", sc->sample_size, entries);
2831 sc->sample_count = entries;
2835 if (field_size != 4 && field_size != 8 && field_size != 16 && field_size != 32) {
2836 av_log(c->fc, AV_LOG_ERROR, "Invalid sample field size %u\n", field_size);
2837 return AVERROR_INVALIDDATA;
2842 if (entries >= (UINT_MAX - 4) / field_size)
2843 return AVERROR_INVALIDDATA;
2844 if (sc->sample_sizes)
2845 av_log(c->fc, AV_LOG_WARNING, "Duplicated STSZ atom\n");
2846 av_free(sc->sample_sizes);
2847 sc->sample_count = 0;
2848 sc->sample_sizes = av_malloc_array(entries, sizeof(*sc->sample_sizes));
2849 if (!sc->sample_sizes)
2850 return AVERROR(ENOMEM);
2852 num_bytes = (entries*field_size+4)>>3;
2854 buf = av_malloc(num_bytes+AV_INPUT_BUFFER_PADDING_SIZE);
2856 av_freep(&sc->sample_sizes);
2857 return AVERROR(ENOMEM);
2860 ret = ffio_read_size(pb, buf, num_bytes);
2862 av_freep(&sc->sample_sizes);
2864 av_log(c->fc, AV_LOG_WARNING, "STSZ atom truncated\n");
2868 init_get_bits(&gb, buf, 8*num_bytes);
2870 for (i = 0; i < entries && !pb->eof_reached; i++) {
2871 sc->sample_sizes[i] = get_bits_long(&gb, field_size);
2872 if (sc->sample_sizes[i] < 0) {
2874 av_log(c->fc, AV_LOG_ERROR, "Invalid sample size %d\n", sc->sample_sizes[i]);
2875 return AVERROR_INVALIDDATA;
2877 sc->data_size += sc->sample_sizes[i];
2880 sc->sample_count = i;
2884 if (pb->eof_reached) {
2885 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted STSZ atom\n");
2892 static int mov_read_stts(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2895 MOVStreamContext *sc;
2896 unsigned int i, entries, alloc_size = 0;
2897 int64_t duration = 0;
2898 int64_t total_sample_count = 0;
2900 if (c->fc->nb_streams < 1)
2902 st = c->fc->streams[c->fc->nb_streams-1];
2905 avio_r8(pb); /* version */
2906 avio_rb24(pb); /* flags */
2907 entries = avio_rb32(pb);
2909 av_log(c->fc, AV_LOG_TRACE, "track[%u].stts.entries = %u\n",
2910 c->fc->nb_streams-1, entries);
2913 av_log(c->fc, AV_LOG_WARNING, "Duplicated STTS atom\n");
2914 av_freep(&sc->stts_data);
2916 if (entries >= INT_MAX / sizeof(*sc->stts_data))
2917 return AVERROR(ENOMEM);
2919 for (i = 0; i < entries && !pb->eof_reached; i++) {
2920 int sample_duration;
2921 unsigned int sample_count;
2922 unsigned int min_entries = FFMIN(FFMAX(i + 1, 1024 * 1024), entries);
2923 MOVStts *stts_data = av_fast_realloc(sc->stts_data, &alloc_size,
2924 min_entries * sizeof(*sc->stts_data));
2926 av_freep(&sc->stts_data);
2928 return AVERROR(ENOMEM);
2930 sc->stts_count = min_entries;
2931 sc->stts_data = stts_data;
2933 sample_count = avio_rb32(pb);
2934 sample_duration = avio_rb32(pb);
2936 sc->stts_data[i].count= sample_count;
2937 sc->stts_data[i].duration= sample_duration;
2939 av_log(c->fc, AV_LOG_TRACE, "sample_count=%d, sample_duration=%d\n",
2940 sample_count, sample_duration);
2942 duration+=(int64_t)sample_duration*(uint64_t)sample_count;
2943 total_sample_count+=sample_count;
2949 duration <= INT64_MAX - sc->duration_for_fps &&
2950 total_sample_count <= INT_MAX - sc->nb_frames_for_fps) {
2951 sc->duration_for_fps += duration;
2952 sc->nb_frames_for_fps += total_sample_count;
2955 if (pb->eof_reached) {
2956 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted STTS atom\n");
2960 st->nb_frames= total_sample_count;
2962 st->duration= FFMIN(st->duration, duration);
2963 sc->track_end = duration;
2967 static int mov_read_sdtp(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2970 MOVStreamContext *sc;
2973 if (c->fc->nb_streams < 1)
2975 st = c->fc->streams[c->fc->nb_streams - 1];
2978 avio_r8(pb); /* version */
2979 avio_rb24(pb); /* flags */
2980 entries = atom.size - 4;
2982 av_log(c->fc, AV_LOG_TRACE, "track[%u].sdtp.entries = %" PRId64 "\n",
2983 c->fc->nb_streams - 1, entries);
2986 av_log(c->fc, AV_LOG_WARNING, "Duplicated SDTP atom\n");
2987 av_freep(&sc->sdtp_data);
2990 sc->sdtp_data = av_mallocz(entries);
2992 return AVERROR(ENOMEM);
2994 for (i = 0; i < entries && !pb->eof_reached; i++)
2995 sc->sdtp_data[i] = avio_r8(pb);
3001 static void mov_update_dts_shift(MOVStreamContext *sc, int duration, void *logctx)
3004 if (duration == INT_MIN) {
3005 av_log(logctx, AV_LOG_WARNING, "mov_update_dts_shift(): dts_shift set to %d\n", INT_MAX);
3008 sc->dts_shift = FFMAX(sc->dts_shift, -duration);
3012 static int mov_read_ctts(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3015 MOVStreamContext *sc;
3016 unsigned int i, entries, ctts_count = 0;
3018 if (c->fc->nb_streams < 1)
3020 st = c->fc->streams[c->fc->nb_streams-1];
3023 avio_r8(pb); /* version */
3024 avio_rb24(pb); /* flags */
3025 entries = avio_rb32(pb);
3027 av_log(c->fc, AV_LOG_TRACE, "track[%u].ctts.entries = %u\n", c->fc->nb_streams - 1, entries);
3031 if (entries >= UINT_MAX / sizeof(*sc->ctts_data))
3032 return AVERROR_INVALIDDATA;
3033 av_freep(&sc->ctts_data);
3034 sc->ctts_data = av_fast_realloc(NULL, &sc->ctts_allocated_size, entries * sizeof(*sc->ctts_data));
3036 return AVERROR(ENOMEM);
3038 for (i = 0; i < entries && !pb->eof_reached; i++) {
3039 int count = avio_rb32(pb);
3040 int duration = avio_rb32(pb);
3043 av_log(c->fc, AV_LOG_TRACE,
3044 "ignoring CTTS entry with count=%d duration=%d\n",
3049 add_ctts_entry(&sc->ctts_data, &ctts_count, &sc->ctts_allocated_size,
3052 av_log(c->fc, AV_LOG_TRACE, "count=%d, duration=%d\n",
3055 if (FFNABS(duration) < -(1<<28) && i+2<entries) {
3056 av_log(c->fc, AV_LOG_WARNING, "CTTS invalid\n");
3057 av_freep(&sc->ctts_data);
3063 mov_update_dts_shift(sc, duration, c->fc);
3066 sc->ctts_count = ctts_count;
3068 if (pb->eof_reached) {
3069 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted CTTS atom\n");
3073 av_log(c->fc, AV_LOG_TRACE, "dts shift %d\n", sc->dts_shift);
3078 static int mov_read_sbgp(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3081 MOVStreamContext *sc;
3082 unsigned int i, entries;
3084 uint32_t grouping_type;
3086 if (c->fc->nb_streams < 1)
3088 st = c->fc->streams[c->fc->nb_streams-1];
3091 version = avio_r8(pb); /* version */
3092 avio_rb24(pb); /* flags */
3093 grouping_type = avio_rl32(pb);
3094 if (grouping_type != MKTAG( 'r','a','p',' '))
3095 return 0; /* only support 'rap ' grouping */
3097 avio_rb32(pb); /* grouping_type_parameter */
3099 entries = avio_rb32(pb);
3103 av_log(c->fc, AV_LOG_WARNING, "Duplicated SBGP atom\n");
3104 av_free(sc->rap_group);
3105 sc->rap_group_count = 0;
3106 sc->rap_group = av_malloc_array(entries, sizeof(*sc->rap_group));
3108 return AVERROR(ENOMEM);
3110 for (i = 0; i < entries && !pb->eof_reached; i++) {
3111 sc->rap_group[i].count = avio_rb32(pb); /* sample_count */
3112 sc->rap_group[i].index = avio_rb32(pb); /* group_description_index */
3115 sc->rap_group_count = i;
3117 if (pb->eof_reached) {
3118 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted SBGP atom\n");
3126 * Get ith edit list entry (media time, duration).
3128 static int get_edit_list_entry(MOVContext *mov,
3129 const MOVStreamContext *msc,
3130 unsigned int edit_list_index,
3131 int64_t *edit_list_media_time,
3132 int64_t *edit_list_duration,
3133 int64_t global_timescale)
3135 if (edit_list_index == msc->elst_count) {
3138 *edit_list_media_time = msc->elst_data[edit_list_index].time;
3139 *edit_list_duration = msc->elst_data[edit_list_index].duration;
3141 /* duration is in global timescale units;convert to msc timescale */
3142 if (global_timescale == 0) {
3143 avpriv_request_sample(mov->fc, "Support for mvhd.timescale = 0 with editlists");
3146 *edit_list_duration = av_rescale(*edit_list_duration, msc->time_scale,
3152 * Find the closest previous frame to the timestamp_pts, in e_old index
3153 * entries. Searching for just any frame / just key frames can be controlled by
3154 * last argument 'flag'.
3155 * Note that if ctts_data is not NULL, we will always search for a key frame
3156 * irrespective of the value of 'flag'. If we don't find any keyframe, we will
3157 * return the first frame of the video.
3159 * Here the timestamp_pts is considered to be a presentation timestamp and
3160 * the timestamp of index entries are considered to be decoding timestamps.
3162 * Returns 0 if successful in finding a frame, else returns -1.
3163 * Places the found index corresponding output arg.
3165 * If ctts_old is not NULL, then refines the searched entry by searching
3166 * backwards from the found timestamp, to find the frame with correct PTS.
3168 * Places the found ctts_index and ctts_sample in corresponding output args.
3170 static int find_prev_closest_index(AVStream *st,
3171 AVIndexEntry *e_old,
3175 int64_t timestamp_pts,
3178 int64_t* ctts_index,
3179 int64_t* ctts_sample)
3181 MOVStreamContext *msc = st->priv_data;
3182 AVIndexEntry *e_keep = st->index_entries;
3183 int nb_keep = st->nb_index_entries;
3185 int64_t index_ctts_count;
3189 // If dts_shift > 0, then all the index timestamps will have to be offset by
3190 // at least dts_shift amount to obtain PTS.
3191 // Hence we decrement the searched timestamp_pts by dts_shift to find the closest index element.
3192 if (msc->dts_shift > 0) {
3193 timestamp_pts -= msc->dts_shift;
3196 st->index_entries = e_old;
3197 st->nb_index_entries = nb_old;
3198 *index = av_index_search_timestamp(st, timestamp_pts, flag | AVSEEK_FLAG_BACKWARD);
3200 // Keep going backwards in the index entries until the timestamp is the same.
3202 for (i = *index; i > 0 && e_old[i].timestamp == e_old[i - 1].timestamp;
3204 if ((flag & AVSEEK_FLAG_ANY) ||
3205 (e_old[i - 1].flags & AVINDEX_KEYFRAME)) {
3211 // If we have CTTS then refine the search, by searching backwards over PTS
3212 // computed by adding corresponding CTTS durations to index timestamps.
3213 if (ctts_data && *index >= 0) {
3214 av_assert0(ctts_index);
3215 av_assert0(ctts_sample);
3216 // Find out the ctts_index for the found frame.
3219 for (index_ctts_count = 0; index_ctts_count < *index; index_ctts_count++) {
3220 if (*ctts_index < ctts_count) {
3222 if (ctts_data[*ctts_index].count == *ctts_sample) {
3229 while (*index >= 0 && (*ctts_index) >= 0 && (*ctts_index) < ctts_count) {
3230 // Find a "key frame" with PTS <= timestamp_pts (So that we can decode B-frames correctly).
3231 // No need to add dts_shift to the timestamp here becase timestamp_pts has already been
3232 // compensated by dts_shift above.
3233 if ((e_old[*index].timestamp + ctts_data[*ctts_index].duration) <= timestamp_pts &&
3234 (e_old[*index].flags & AVINDEX_KEYFRAME)) {
3239 if (*ctts_sample == 0) {
3241 if (*ctts_index >= 0)
3242 *ctts_sample = ctts_data[*ctts_index].count - 1;
3249 /* restore AVStream state*/
3250 st->index_entries = e_keep;
3251 st->nb_index_entries = nb_keep;
3252 return *index >= 0 ? 0 : -1;
3256 * Add index entry with the given values, to the end of st->index_entries.
3257 * Returns the new size st->index_entries if successful, else returns -1.
3259 * This function is similar to ff_add_index_entry in libavformat/utils.c
3260 * except that here we are always unconditionally adding an index entry to
3261 * the end, instead of searching the entries list and skipping the add if
3262 * there is an existing entry with the same timestamp.
3263 * This is needed because the mov_fix_index calls this func with the same
3264 * unincremented timestamp for successive discarded frames.
3266 static int64_t add_index_entry(AVStream *st, int64_t pos, int64_t timestamp,
3267 int size, int distance, int flags)
3269 AVIndexEntry *entries, *ie;
3271 const size_t min_size_needed = (st->nb_index_entries + 1) * sizeof(AVIndexEntry);
3273 // Double the allocation each time, to lower memory fragmentation.
3274 // Another difference from ff_add_index_entry function.
3275 const size_t requested_size =
3276 min_size_needed > st->index_entries_allocated_size ?
3277 FFMAX(min_size_needed, 2 * st->index_entries_allocated_size) :
3280 if (st->nb_index_entries + 1U >= UINT_MAX / sizeof(AVIndexEntry))
3283 entries = av_fast_realloc(st->index_entries,
3284 &st->index_entries_allocated_size,
3289 st->index_entries= entries;
3291 index= st->nb_index_entries++;
3292 ie= &entries[index];
3295 ie->timestamp = timestamp;
3296 ie->min_distance= distance;
3303 * Rewrite timestamps of index entries in the range [end_index - frame_duration_buffer_size, end_index)
3304 * by subtracting end_ts successively by the amounts given in frame_duration_buffer.
3306 static void fix_index_entry_timestamps(AVStream* st, int end_index, int64_t end_ts,
3307 int64_t* frame_duration_buffer,
3308 int frame_duration_buffer_size) {
3310 av_assert0(end_index >= 0 && end_index <= st->nb_index_entries);
3311 for (i = 0; i < frame_duration_buffer_size; i++) {
3312 end_ts -= frame_duration_buffer[frame_duration_buffer_size - 1 - i];
3313 st->index_entries[end_index - 1 - i].timestamp = end_ts;
3318 * Append a new ctts entry to ctts_data.
3319 * Returns the new ctts_count if successful, else returns -1.
3321 static int64_t add_ctts_entry(MOVStts** ctts_data, unsigned int* ctts_count, unsigned int* allocated_size,
3322 int count, int duration)
3324 MOVStts *ctts_buf_new;
3325 const size_t min_size_needed = (*ctts_count + 1) * sizeof(MOVStts);
3326 const size_t requested_size =
3327 min_size_needed > *allocated_size ?
3328 FFMAX(min_size_needed, 2 * (*allocated_size)) :
3331 if ((unsigned)(*ctts_count) >= UINT_MAX / sizeof(MOVStts) - 1)
3334 ctts_buf_new = av_fast_realloc(*ctts_data, allocated_size, requested_size);
3339 *ctts_data = ctts_buf_new;
3341 ctts_buf_new[*ctts_count].count = count;
3342 ctts_buf_new[*ctts_count].duration = duration;
3344 *ctts_count = (*ctts_count) + 1;
3348 #define MAX_REORDER_DELAY 16
3349 static void mov_estimate_video_delay(MOVContext *c, AVStream* st)
3351 MOVStreamContext *msc = st->priv_data;
3354 int ctts_sample = 0;
3355 int64_t pts_buf[MAX_REORDER_DELAY + 1]; // Circular buffer to sort pts.
3357 int j, r, num_swaps;
3359 for (j = 0; j < MAX_REORDER_DELAY + 1; j++)
3360 pts_buf[j] = INT64_MIN;
3362 if (st->codecpar->video_delay <= 0 && msc->ctts_data &&
3363 st->codecpar->codec_id == AV_CODEC_ID_H264) {
3364 st->codecpar->video_delay = 0;
3365 for (ind = 0; ind < st->nb_index_entries && ctts_ind < msc->ctts_count; ++ind) {
3366 // Point j to the last elem of the buffer and insert the current pts there.
3368 buf_start = (buf_start + 1);
3369 if (buf_start == MAX_REORDER_DELAY + 1)
3372 pts_buf[j] = st->index_entries[ind].timestamp + msc->ctts_data[ctts_ind].duration;
3374 // The timestamps that are already in the sorted buffer, and are greater than the
3375 // current pts, are exactly the timestamps that need to be buffered to output PTS
3376 // in correct sorted order.
3377 // Hence the video delay (which is the buffer size used to sort DTS and output PTS),
3378 // can be computed as the maximum no. of swaps any particular timestamp needs to
3379 // go through, to keep this buffer in sorted order.
3381 while (j != buf_start) {
3383 if (r < 0) r = MAX_REORDER_DELAY;
3384 if (pts_buf[j] < pts_buf[r]) {
3385 FFSWAP(int64_t, pts_buf[j], pts_buf[r]);
3392 st->codecpar->video_delay = FFMAX(st->codecpar->video_delay, num_swaps);
3395 if (ctts_sample == msc->ctts_data[ctts_ind].count) {
3400 av_log(c->fc, AV_LOG_DEBUG, "Setting codecpar->delay to %d for stream st: %d\n",
3401 st->codecpar->video_delay, st->index);
3405 static void mov_current_sample_inc(MOVStreamContext *sc)
3407 sc->current_sample++;
3408 sc->current_index++;
3409 if (sc->index_ranges &&
3410 sc->current_index >= sc->current_index_range->end &&
3411 sc->current_index_range->end) {
3412 sc->current_index_range++;
3413 sc->current_index = sc->current_index_range->start;
3417 static void mov_current_sample_dec(MOVStreamContext *sc)
3419 sc->current_sample--;
3420 sc->current_index--;
3421 if (sc->index_ranges &&
3422 sc->current_index < sc->current_index_range->start &&
3423 sc->current_index_range > sc->index_ranges) {
3424 sc->current_index_range--;
3425 sc->current_index = sc->current_index_range->end - 1;
3429 static void mov_current_sample_set(MOVStreamContext *sc, int current_sample)
3433 sc->current_sample = current_sample;
3434 sc->current_index = current_sample;
3435 if (!sc->index_ranges) {
3439 for (sc->current_index_range = sc->index_ranges;
3440 sc->current_index_range->end;
3441 sc->current_index_range++) {
3442 range_size = sc->current_index_range->end - sc->current_index_range->start;
3443 if (range_size > current_sample) {
3444 sc->current_index = sc->current_index_range->start + current_sample;
3447 current_sample -= range_size;
3452 * Fix st->index_entries, so that it contains only the entries (and the entries
3453 * which are needed to decode them) that fall in the edit list time ranges.
3454 * Also fixes the timestamps of the index entries to match the timeline
3455 * specified the edit lists.
3457 static void mov_fix_index(MOVContext *mov, AVStream *st)
3459 MOVStreamContext *msc = st->priv_data;
3460 AVIndexEntry *e_old = st->index_entries;
3461 int nb_old = st->nb_index_entries;
3462 const AVIndexEntry *e_old_end = e_old + nb_old;
3463 const AVIndexEntry *current = NULL;
3464 MOVStts *ctts_data_old = msc->ctts_data;
3465 int64_t ctts_index_old = 0;
3466 int64_t ctts_sample_old = 0;
3467 int64_t ctts_count_old = msc->ctts_count;
3468 int64_t edit_list_media_time = 0;
3469 int64_t edit_list_duration = 0;
3470 int64_t frame_duration = 0;
3471 int64_t edit_list_dts_counter = 0;
3472 int64_t edit_list_dts_entry_end = 0;
3473 int64_t edit_list_start_ctts_sample = 0;
3475 int64_t curr_ctts = 0;
3476 int64_t empty_edits_sum_duration = 0;
3477 int64_t edit_list_index = 0;
3480 int64_t start_dts = 0;
3481 int64_t edit_list_start_encountered = 0;
3482 int64_t search_timestamp = 0;
3483 int64_t* frame_duration_buffer = NULL;
3484 int num_discarded_begin = 0;
3485 int first_non_zero_audio_edit = -1;
3486 int packet_skip_samples = 0;
3487 MOVIndexRange *current_index_range;
3489 int found_keyframe_after_edit = 0;
3490 int found_non_empty_edit = 0;
3492 if (!msc->elst_data || msc->elst_count <= 0 || nb_old <= 0) {
3496 // allocate the index ranges array
3497 msc->index_ranges = av_malloc((msc->elst_count + 1) * sizeof(msc->index_ranges[0]));
3498 if (!msc->index_ranges) {
3499 av_log(mov->fc, AV_LOG_ERROR, "Cannot allocate index ranges buffer\n");
3502 msc->current_index_range = msc->index_ranges;
3503 current_index_range = msc->index_ranges - 1;
3505 // Clean AVStream from traces of old index
3506 st->index_entries = NULL;
3507 st->index_entries_allocated_size = 0;
3508 st->nb_index_entries = 0;
3510 // Clean ctts fields of MOVStreamContext
3511 msc->ctts_data = NULL;
3512 msc->ctts_count = 0;
3513 msc->ctts_index = 0;
3514 msc->ctts_sample = 0;
3515 msc->ctts_allocated_size = 0;
3517 // Reinitialize min_corrected_pts so that it can be computed again.
3518 msc->min_corrected_pts = -1;
3520 // If the dts_shift is positive (in case of negative ctts values in mov),
3521 // then negate the DTS by dts_shift
3522 if (msc->dts_shift > 0) {
3523 edit_list_dts_entry_end -= msc->dts_shift;
3524 av_log(mov->fc, AV_LOG_DEBUG, "Shifting DTS by %d because of negative CTTS.\n", msc->dts_shift);
3527 start_dts = edit_list_dts_entry_end;
3529 while (get_edit_list_entry(mov, msc, edit_list_index, &edit_list_media_time,
3530 &edit_list_duration, mov->time_scale)) {
3531 av_log(mov->fc, AV_LOG_DEBUG, "Processing st: %d, edit list %"PRId64" - media time: %"PRId64", duration: %"PRId64"\n",
3532 st->index, edit_list_index, edit_list_media_time, edit_list_duration);
3534 edit_list_dts_counter = edit_list_dts_entry_end;
3535 edit_list_dts_entry_end += edit_list_duration;
3536 num_discarded_begin = 0;
3537 if (!found_non_empty_edit && edit_list_media_time == -1) {
3538 empty_edits_sum_duration += edit_list_duration;
3541 found_non_empty_edit = 1;
3543 // If we encounter a non-negative edit list reset the skip_samples/start_pad fields and set them
3544 // according to the edit list below.
3545 if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
3546 if (first_non_zero_audio_edit < 0) {
3547 first_non_zero_audio_edit = 1;
3549 first_non_zero_audio_edit = 0;
3552 if (first_non_zero_audio_edit > 0)
3553 st->skip_samples = msc->start_pad = 0;
3556 // While reordering frame index according to edit list we must handle properly
3557 // the scenario when edit list entry starts from none key frame.
3558 // We find closest previous key frame and preserve it and consequent frames in index.
3559 // All frames which are outside edit list entry time boundaries will be dropped after decoding.
3560 search_timestamp = edit_list_media_time;
3561 if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
3562 // Audio decoders like AAC need need a decoder delay samples previous to the current sample,
3563 // to correctly decode this frame. Hence for audio we seek to a frame 1 sec. before the
3564 // edit_list_media_time to cover the decoder delay.
3565 search_timestamp = FFMAX(search_timestamp - msc->time_scale, e_old[0].timestamp);
3568 if (find_prev_closest_index(st, e_old, nb_old, ctts_data_old, ctts_count_old, search_timestamp, 0,
3569 &index, &ctts_index_old, &ctts_sample_old) < 0) {
3570 av_log(mov->fc, AV_LOG_WARNING,
3571 "st: %d edit list: %"PRId64" Missing key frame while searching for timestamp: %"PRId64"\n",
3572 st->index, edit_list_index, search_timestamp);
3573 if (find_prev_closest_index(st, e_old, nb_old, ctts_data_old, ctts_count_old, search_timestamp, AVSEEK_FLAG_ANY,
3574 &index, &ctts_index_old, &ctts_sample_old) < 0) {
3575 av_log(mov->fc, AV_LOG_WARNING,
3576 "st: %d edit list %"PRId64" Cannot find an index entry before timestamp: %"PRId64".\n",
3577 st->index, edit_list_index, search_timestamp);
3580 ctts_sample_old = 0;
3583 current = e_old + index;
3584 edit_list_start_ctts_sample = ctts_sample_old;
3586 // Iterate over index and arrange it according to edit list
3587 edit_list_start_encountered = 0;
3588 found_keyframe_after_edit = 0;
3589 for (; current < e_old_end; current++, index++) {
3590 // check if frame outside edit list mark it for discard
3591 frame_duration = (current + 1 < e_old_end) ?
3592 ((current + 1)->timestamp - current->timestamp) : edit_list_duration;
3594 flags = current->flags;
3596 // frames (pts) before or after edit list
3597 curr_cts = current->timestamp + msc->dts_shift;
3600 if (ctts_data_old && ctts_index_old < ctts_count_old) {
3601 curr_ctts = ctts_data_old[ctts_index_old].duration;
3602 av_log(mov->fc, AV_LOG_DEBUG, "stts: %"PRId64" ctts: %"PRId64", ctts_index: %"PRId64", ctts_count: %"PRId64"\n",
3603 curr_cts, curr_ctts, ctts_index_old, ctts_count_old);
3604 curr_cts += curr_ctts;
3606 if (ctts_sample_old == ctts_data_old[ctts_index_old].count) {
3607 if (add_ctts_entry(&msc->ctts_data, &msc->ctts_count,
3608 &msc->ctts_allocated_size,
3609 ctts_data_old[ctts_index_old].count - edit_list_start_ctts_sample,
3610 ctts_data_old[ctts_index_old].duration) == -1) {
3611 av_log(mov->fc, AV_LOG_ERROR, "Cannot add CTTS entry %"PRId64" - {%"PRId64", %d}\n",
3613 ctts_data_old[ctts_index_old].count - edit_list_start_ctts_sample,
3614 ctts_data_old[ctts_index_old].duration);
3618 ctts_sample_old = 0;
3619 edit_list_start_ctts_sample = 0;
3623 if (curr_cts < edit_list_media_time || curr_cts >= (edit_list_duration + edit_list_media_time)) {
3624 if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO && st->codecpar->codec_id != AV_CODEC_ID_VORBIS &&
3625 curr_cts < edit_list_media_time && curr_cts + frame_duration > edit_list_media_time &&
3626 first_non_zero_audio_edit > 0) {
3627 packet_skip_samples = edit_list_media_time - curr_cts;
3628 st->skip_samples += packet_skip_samples;
3630 // Shift the index entry timestamp by packet_skip_samples to be correct.
3631 edit_list_dts_counter -= packet_skip_samples;
3632 if (edit_list_start_encountered == 0) {
3633 edit_list_start_encountered = 1;
3634 // Make timestamps strictly monotonically increasing for audio, by rewriting timestamps for
3635 // discarded packets.
3636 if (frame_duration_buffer) {
3637 fix_index_entry_timestamps(st, st->nb_index_entries, edit_list_dts_counter,
3638 frame_duration_buffer, num_discarded_begin);
3639 av_freep(&frame_duration_buffer);
3643 av_log(mov->fc, AV_LOG_DEBUG, "skip %d audio samples from curr_cts: %"PRId64"\n", packet_skip_samples, curr_cts);
3645 flags |= AVINDEX_DISCARD_FRAME;
3646 av_log(mov->fc, AV_LOG_DEBUG, "drop a frame at curr_cts: %"PRId64" @ %"PRId64"\n", curr_cts, index);
3648 if (edit_list_start_encountered == 0) {
3649 num_discarded_begin++;
3650 frame_duration_buffer = av_realloc(frame_duration_buffer,
3651 num_discarded_begin * sizeof(int64_t));
3652 if (!frame_duration_buffer) {
3653 av_log(mov->fc, AV_LOG_ERROR, "Cannot reallocate frame duration buffer\n");
3656 frame_duration_buffer[num_discarded_begin - 1] = frame_duration;
3658 // Increment skip_samples for the first non-zero audio edit list
3659 if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO &&
3660 first_non_zero_audio_edit > 0 && st->codecpar->codec_id != AV_CODEC_ID_VORBIS) {
3661 st->skip_samples += frame_duration;
3666 if (msc->min_corrected_pts < 0) {
3667 msc->min_corrected_pts = edit_list_dts_counter + curr_ctts + msc->dts_shift;
3669 msc->min_corrected_pts = FFMIN(msc->min_corrected_pts, edit_list_dts_counter + curr_ctts + msc->dts_shift);
3671 if (edit_list_start_encountered == 0) {
3672 edit_list_start_encountered = 1;
3673 // Make timestamps strictly monotonically increasing by rewriting timestamps for
3674 // discarded packets.
3675 if (frame_duration_buffer) {
3676 fix_index_entry_timestamps(st, st->nb_index_entries, edit_list_dts_counter,
3677 frame_duration_buffer, num_discarded_begin);
3678 av_freep(&frame_duration_buffer);
3683 if (add_index_entry(st, current->pos, edit_list_dts_counter, current->size,
3684 current->min_distance, flags) == -1) {
3685 av_log(mov->fc, AV_LOG_ERROR, "Cannot add index entry\n");
3689 // Update the index ranges array
3690 if (current_index_range < msc->index_ranges || index != current_index_range->end) {
3691 current_index_range++;
3692 current_index_range->start = index;
3694 current_index_range->end = index + 1;
3696 // Only start incrementing DTS in frame_duration amounts, when we encounter a frame in edit list.
3697 if (edit_list_start_encountered > 0) {
3698 edit_list_dts_counter = edit_list_dts_counter + frame_duration;
3701 // Break when found first key frame after edit entry completion
3702 if ((curr_cts + frame_duration >= (edit_list_duration + edit_list_media_time)) &&
3703 ((flags & AVINDEX_KEYFRAME) || ((st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO)))) {
3704 if (ctts_data_old) {
3705 // If we have CTTS and this is the first keyframe after edit elist,
3706 // wait for one more, because there might be trailing B-frames after this I-frame
3707 // that do belong to the edit.
3708 if (st->codecpar->codec_type != AVMEDIA_TYPE_AUDIO && found_keyframe_after_edit == 0) {
3709 found_keyframe_after_edit = 1;
3712 if (ctts_sample_old != 0) {
3713 if (add_ctts_entry(&msc->ctts_data, &msc->ctts_count,
3714 &msc->ctts_allocated_size,
3715 ctts_sample_old - edit_list_start_ctts_sample,
3716 ctts_data_old[ctts_index_old].duration) == -1) {
3717 av_log(mov->fc, AV_LOG_ERROR, "Cannot add CTTS entry %"PRId64" - {%"PRId64", %d}\n",
3718 ctts_index_old, ctts_sample_old - edit_list_start_ctts_sample,
3719 ctts_data_old[ctts_index_old].duration);
3728 // If there are empty edits, then msc->min_corrected_pts might be positive
3729 // intentionally. So we subtract the sum duration of emtpy edits here.
3730 msc->min_corrected_pts -= empty_edits_sum_duration;
3732 // If the minimum pts turns out to be greater than zero after fixing the index, then we subtract the
3733 // dts by that amount to make the first pts zero.
3734 if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
3735 if (msc->min_corrected_pts > 0) {
3736 av_log(mov->fc, AV_LOG_DEBUG, "Offset DTS by %"PRId64" to make first pts zero.\n", msc->min_corrected_pts);
3737 for (i = 0; i < st->nb_index_entries; ++i) {
3738 st->index_entries[i].timestamp -= msc->min_corrected_pts;
3742 // Start time should be equal to zero or the duration of any empty edits.
3743 st->start_time = empty_edits_sum_duration;
3745 // Update av stream length, if it ends up shorter than the track's media duration
3746 st->duration = FFMIN(st->duration, edit_list_dts_entry_end - start_dts);
3747 msc->start_pad = st->skip_samples;
3749 // Free the old index and the old CTTS structures
3751 av_free(ctts_data_old);
3752 av_freep(&frame_duration_buffer);
3754 // Null terminate the index ranges array
3755 current_index_range++;
3756 current_index_range->start = 0;
3757 current_index_range->end = 0;
3758 msc->current_index = msc->index_ranges[0].start;
3761 static void mov_build_index(MOVContext *mov, AVStream *st)
3763 MOVStreamContext *sc = st->priv_data;
3764 int64_t current_offset;
3765 int64_t current_dts = 0;
3766 unsigned int stts_index = 0;
3767 unsigned int stsc_index = 0;
3768 unsigned int stss_index = 0;
3769 unsigned int stps_index = 0;
3771 uint64_t stream_size = 0;
3772 MOVStts *ctts_data_old = sc->ctts_data;
3773 unsigned int ctts_count_old = sc->ctts_count;
3775 if (sc->elst_count) {
3776 int i, edit_start_index = 0, multiple_edits = 0;
3777 int64_t empty_duration = 0; // empty duration of the first edit list entry
3778 int64_t start_time = 0; // start time of the media
3780 for (i = 0; i < sc->elst_count; i++) {
3781 const MOVElst *e = &sc->elst_data[i];
3782 if (i == 0 && e->time == -1) {
3783 /* if empty, the first entry is the start time of the stream
3784 * relative to the presentation itself */
3785 empty_duration = e->duration;
3786 edit_start_index = 1;
3787 } else if (i == edit_start_index && e->time >= 0) {
3788 start_time = e->time;
3794 if (multiple_edits && !mov->advanced_editlist)
3795 av_log(mov->fc, AV_LOG_WARNING, "multiple edit list entries, "
3796 "Use -advanced_editlist to correctly decode otherwise "
3797 "a/v desync might occur\n");
3799 /* adjust first dts according to edit list */
3800 if ((empty_duration || start_time) && mov->time_scale > 0) {
3802 empty_duration = av_rescale(empty_duration, sc->time_scale, mov->time_scale);
3803 sc->time_offset = start_time - empty_duration;
3804 sc->min_corrected_pts = start_time;
3805 if (!mov->advanced_editlist)
3806 current_dts = -sc->time_offset;
3809 if (!multiple_edits && !mov->advanced_editlist &&
3810 st->codecpar->codec_id == AV_CODEC_ID_AAC && start_time > 0)
3811 sc->start_pad = start_time;
3814 /* only use old uncompressed audio chunk demuxing when stts specifies it */
3815 if (!(st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO &&
3816 sc->stts_count == 1 && sc->stts_data[0].duration == 1)) {
3817 unsigned int current_sample = 0;
3818 unsigned int stts_sample = 0;
3819 unsigned int sample_size;
3820 unsigned int distance = 0;
3821 unsigned int rap_group_index = 0;
3822 unsigned int rap_group_sample = 0;
3823 int64_t last_dts = 0;
3824 int64_t dts_correction = 0;
3825 int rap_group_present = sc->rap_group_count && sc->rap_group;
3826 int key_off = (sc->keyframe_count && sc->keyframes[0] > 0) || (sc->stps_count && sc->stps_data[0] > 0);
3828 current_dts -= sc->dts_shift;
3829 last_dts = current_dts;
3831 if (!sc->sample_count || st->nb_index_entries)
3833 if (sc->sample_count >= UINT_MAX / sizeof(*st->index_entries) - st->nb_index_entries)
3835 if (av_reallocp_array(&st->index_entries,
3836 st->nb_index_entries + sc->sample_count,
3837 sizeof(*st->index_entries)) < 0) {
3838 st->nb_index_entries = 0;
3841 st->index_entries_allocated_size = (st->nb_index_entries + sc->sample_count) * sizeof(*st->index_entries);
3843 if (ctts_data_old) {
3844 // Expand ctts entries such that we have a 1-1 mapping with samples
3845 if (sc->sample_count >= UINT_MAX / sizeof(*sc->ctts_data))
3848 sc->ctts_allocated_size = 0;
3849 sc->ctts_data = av_fast_realloc(NULL, &sc->ctts_allocated_size,
3850 sc->sample_count * sizeof(*sc->ctts_data));
3851 if (!sc->ctts_data) {
3852 av_free(ctts_data_old);
3856 memset((uint8_t*)(sc->ctts_data), 0, sc->ctts_allocated_size);
3858 for (i = 0; i < ctts_count_old &&
3859 sc->ctts_count < sc->sample_count; i++)
3860 for (j = 0; j < ctts_data_old[i].count &&
3861 sc->ctts_count < sc->sample_count; j++)
3862 add_ctts_entry(&sc->ctts_data, &sc->ctts_count,
3863 &sc->ctts_allocated_size, 1,
3864 ctts_data_old[i].duration);
3865 av_free(ctts_data_old);
3868 for (i = 0; i < sc->chunk_count; i++) {
3869 int64_t next_offset = i+1 < sc->chunk_count ? sc->chunk_offsets[i+1] : INT64_MAX;
3870 current_offset = sc->chunk_offsets[i];
3871 while (mov_stsc_index_valid(stsc_index, sc->stsc_count) &&
3872 i + 1 == sc->stsc_data[stsc_index + 1].first)
3875 if (next_offset > current_offset && sc->sample_size>0 && sc->sample_size < sc->stsz_sample_size &&
3876 sc->stsc_data[stsc_index].count * (int64_t)sc->stsz_sample_size > next_offset - current_offset) {
3877 av_log(mov->fc, AV_LOG_WARNING, "STSZ sample size %d invalid (too large), ignoring\n", sc->stsz_sample_size);
3878 sc->stsz_sample_size = sc->sample_size;
3880 if (sc->stsz_sample_size>0 && sc->stsz_sample_size < sc->sample_size) {
3881 av_log(mov->fc, AV_LOG_WARNING, "STSZ sample size %d invalid (too small), ignoring\n", sc->stsz_sample_size);
3882 sc->stsz_sample_size = sc->sample_size;
3885 for (j = 0; j < sc->stsc_data[stsc_index].count; j++) {
3887 if (current_sample >= sc->sample_count) {
3888 av_log(mov->fc, AV_LOG_ERROR, "wrong sample count\n");
3892 if (!sc->keyframe_absent && (!sc->keyframe_count || current_sample+key_off == sc->keyframes[stss_index])) {
3894 if (stss_index + 1 < sc->keyframe_count)
3896 } else if (sc->stps_count && current_sample+key_off == sc->stps_data[stps_index]) {
3898 if (stps_index + 1 < sc->stps_count)
3901 if (rap_group_present && rap_group_index < sc->rap_group_count) {
3902 if (sc->rap_group[rap_group_index].index > 0)
3904 if (++rap_group_sample == sc->rap_group[rap_group_index].count) {
3905 rap_group_sample = 0;
3909 if (sc->keyframe_absent
3911 && !rap_group_present
3912 && (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO || (i==0 && j==0)))
3916 sample_size = sc->stsz_sample_size > 0 ? sc->stsz_sample_size : sc->sample_sizes[current_sample];
3917 if (sc->pseudo_stream_id == -1 ||
3918 sc->stsc_data[stsc_index].id - 1 == sc->pseudo_stream_id) {
3920 if (sample_size > 0x3FFFFFFF) {
3921 av_log(mov->fc, AV_LOG_ERROR, "Sample size %u is too large\n", sample_size);
3924 e = &st->index_entries[st->nb_index_entries++];
3925 e->pos = current_offset;
3926 e->timestamp = current_dts;
3927 e->size = sample_size;
3928 e->min_distance = distance;
3929 e->flags = keyframe ? AVINDEX_KEYFRAME : 0;
3930 av_log(mov->fc, AV_LOG_TRACE, "AVIndex stream %d, sample %u, offset %"PRIx64", dts %"PRId64", "
3931 "size %u, distance %u, keyframe %d\n", st->index, current_sample,
3932 current_offset, current_dts, sample_size, distance, keyframe);
3933 if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && st->nb_index_entries < 100)
3934 ff_rfps_add_frame(mov->fc, st, current_dts);
3937 current_offset += sample_size;
3938 stream_size += sample_size;
3940 /* A negative sample duration is invalid based on the spec,
3941 * but some samples need it to correct the DTS. */
3942 if (sc->stts_data[stts_index].duration < 0) {
3943 av_log(mov->fc, AV_LOG_WARNING,
3944 "Invalid SampleDelta %d in STTS, at %d st:%d\n",
3945 sc->stts_data[stts_index].duration, stts_index,
3947 dts_correction += sc->stts_data[stts_index].duration - 1;
3948 sc->stts_data[stts_index].duration = 1;
3950 current_dts += sc->stts_data[stts_index].duration;
3951 if (!dts_correction || current_dts + dts_correction > last_dts) {
3952 current_dts += dts_correction;
3955 /* Avoid creating non-monotonous DTS */
3956 dts_correction += current_dts - last_dts - 1;
3957 current_dts = last_dts + 1;
3959 last_dts = current_dts;
3963 if (stts_index + 1 < sc->stts_count && stts_sample == sc->stts_data[stts_index].count) {
3969 if (st->duration > 0)
3970 st->codecpar->bit_rate = stream_size*8*sc->time_scale/st->duration;
3972 unsigned chunk_samples, total = 0;
3974 if (!sc->chunk_count)
3977 // compute total chunk count
3978 for (i = 0; i < sc->stsc_count; i++) {
3979 unsigned count, chunk_count;
3981 chunk_samples = sc->stsc_data[i].count;
3982 if (i != sc->stsc_count - 1 &&
3983 sc->samples_per_frame && chunk_samples % sc->samples_per_frame) {
3984 av_log(mov->fc, AV_LOG_ERROR, "error unaligned chunk\n");
3988 if (sc->samples_per_frame >= 160) { // gsm
3989 count = chunk_samples / sc->samples_per_frame;
3990 } else if (sc->samples_per_frame > 1) {
3991 unsigned samples = (1024/sc->samples_per_frame)*sc->samples_per_frame;
3992 count = (chunk_samples+samples-1) / samples;
3994 count = (chunk_samples+1023) / 1024;
3997 if (mov_stsc_index_valid(i, sc->stsc_count))
3998 chunk_count = sc->stsc_data[i+1].first - sc->stsc_data[i].first;
4000 chunk_count = sc->chunk_count - (sc->stsc_data[i].first - 1);
4001 total += chunk_count * count;
4004 av_log(mov->fc, AV_LOG_TRACE, "chunk count %u\n", total);
4005 if (total >= UINT_MAX / sizeof(*st->index_entries) - st->nb_index_entries)
4007 if (av_reallocp_array(&st->index_entries,
4008 st->nb_index_entries + total,
4009 sizeof(*st->index_entries)) < 0) {
4010 st->nb_index_entries = 0;
4013 st->index_entries_allocated_size = (st->nb_index_entries + total) * sizeof(*st->index_entries);
4016 for (i = 0; i < sc->chunk_count; i++) {
4017 current_offset = sc->chunk_offsets[i];
4018 if (mov_stsc_index_valid(stsc_index, sc->stsc_count) &&
4019 i + 1 == sc->stsc_data[stsc_index + 1].first)
4021 chunk_samples = sc->stsc_data[stsc_index].count;
4023 while (chunk_samples > 0) {
4025 unsigned size, samples;
4027 if (sc->samples_per_frame > 1 && !sc->bytes_per_frame) {
4028 avpriv_request_sample(mov->fc,
4029 "Zero bytes per frame, but %d samples per frame",
4030 sc->samples_per_frame);
4034 if (sc->samples_per_frame >= 160) { // gsm
4035 samples = sc->samples_per_frame;
4036 size = sc->bytes_per_frame;
4038 if (sc->samples_per_frame > 1) {
4039 samples = FFMIN((1024 / sc->samples_per_frame)*
4040 sc->samples_per_frame, chunk_samples);
4041 size = (samples / sc->samples_per_frame) * sc->bytes_per_frame;
4043 samples = FFMIN(1024, chunk_samples);
4044 size = samples * sc->sample_size;
4048 if (st->nb_index_entries >= total) {
4049 av_log(mov->fc, AV_LOG_ERROR, "wrong chunk count %u\n", total);
4052 if (size > 0x3FFFFFFF) {
4053 av_log(mov->fc, AV_LOG_ERROR, "Sample size %u is too large\n", size);
4056 e = &st->index_entries[st->nb_index_entries++];
4057 e->pos = current_offset;
4058 e->timestamp = current_dts;
4060 e->min_distance = 0;
4061 e->flags = AVINDEX_KEYFRAME;
4062 av_log(mov->fc, AV_LOG_TRACE, "AVIndex stream %d, chunk %u, offset %"PRIx64", dts %"PRId64", "
4063 "size %u, duration %u\n", st->index, i, current_offset, current_dts,
4066 current_offset += size;
4067 current_dts += samples;
4068 chunk_samples -= samples;
4073 if (!mov->ignore_editlist && mov->advanced_editlist) {
4074 // Fix index according to edit lists.
4075 mov_fix_index(mov, st);
4078 // Update start time of the stream.
4079 if (st->start_time == AV_NOPTS_VALUE && st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && st->nb_index_entries > 0) {
4080 st->start_time = st->index_entries[0].timestamp + sc->dts_shift;
4081 if (sc->ctts_data) {
4082 st->start_time += sc->ctts_data[0].duration;
4086 mov_estimate_video_delay(mov, st);
4089 static int test_same_origin(const char *src, const char *ref) {
4099 av_url_split(src_proto, sizeof(src_proto), src_auth, sizeof(src_auth), src_host, sizeof(src_host), &src_port, NULL, 0, src);
4100 av_url_split(ref_proto, sizeof(ref_proto), ref_auth, sizeof(ref_auth), ref_host, sizeof(ref_host), &ref_port, NULL, 0, ref);
4102 if (strlen(src) == 0) {
4104 } else if (strlen(src_auth) + 1 >= sizeof(src_auth) ||
4105 strlen(ref_auth) + 1 >= sizeof(ref_auth) ||
4106 strlen(src_host) + 1 >= sizeof(src_host) ||
4107 strlen(ref_host) + 1 >= sizeof(ref_host)) {
4109 } else if (strcmp(src_proto, ref_proto) ||
4110 strcmp(src_auth, ref_auth) ||
4111 strcmp(src_host, ref_host) ||
4112 src_port != ref_port) {
4118 static int mov_open_dref(MOVContext *c, AVIOContext **pb, const char *src, MOVDref *ref)
4120 /* try relative path, we do not try the absolute because it can leak information about our
4121 system to an attacker */
4122 if (ref->nlvl_to > 0 && ref->nlvl_from > 0) {
4123 char filename[1025];
4124 const char *src_path;
4127 /* find a source dir */
4128 src_path = strrchr(src, '/');
4134 /* find a next level down to target */
4135 for (i = 0, l = strlen(ref->path) - 1; l >= 0; l--)
4136 if (ref->path[l] == '/') {
4137 if (i == ref->nlvl_to - 1)
4143 /* compose filename if next level down to target was found */
4144 if (i == ref->nlvl_to - 1 && src_path - src < sizeof(filename)) {
4145 memcpy(filename, src, src_path - src);
4146 filename[src_path - src] = 0;
4148 for (i = 1; i < ref->nlvl_from; i++)
4149 av_strlcat(filename, "../", sizeof(filename));
4151 av_strlcat(filename, ref->path + l + 1, sizeof(filename));
4152 if (!c->use_absolute_path) {
4153 int same_origin = test_same_origin(src, filename);
4156 av_log(c->fc, AV_LOG_ERROR,
4157 "Reference with mismatching origin, %s not tried for security reasons, "
4158 "set demuxer option use_absolute_path to allow it anyway\n",
4160 return AVERROR(ENOENT);
4163 if (strstr(ref->path + l + 1, "..") ||
4164 strstr(ref->path + l + 1, ":") ||
4165 (ref->nlvl_from > 1 && same_origin < 0) ||
4166 (filename[0] == '/' && src_path == src))
4167 return AVERROR(ENOENT);
4170 if (strlen(filename) + 1 == sizeof(filename))
4171 return AVERROR(ENOENT);
4172 if (!c->fc->io_open(c->fc, pb, filename, AVIO_FLAG_READ, NULL))
4175 } else if (c->use_absolute_path) {
4176 av_log(c->fc, AV_LOG_WARNING, "Using absolute path on user request, "
4177 "this is a possible security issue\n");
4178 if (!c->fc->io_open(c->fc, pb, ref->path, AVIO_FLAG_READ, NULL))
4181 av_log(c->fc, AV_LOG_ERROR,
4182 "Absolute path %s not tried for security reasons, "
4183 "set demuxer option use_absolute_path to allow absolute paths\n",
4187 return AVERROR(ENOENT);
4190 static void fix_timescale(MOVContext *c, MOVStreamContext *sc)
4192 if (sc->time_scale <= 0) {
4193 av_log(c->fc, AV_LOG_WARNING, "stream %d, timescale not set\n", sc->ffindex);
4194 sc->time_scale = c->time_scale;
4195 if (sc->time_scale <= 0)
4200 static int mov_read_trak(MOVContext *c, AVIOContext *pb, MOVAtom atom)
4203 MOVStreamContext *sc;
4206 st = avformat_new_stream(c->fc, NULL);
4207 if (!st) return AVERROR(ENOMEM);
4209 sc = av_mallocz(sizeof(MOVStreamContext));
4210 if (!sc) return AVERROR(ENOMEM);
4213 st->codecpar->codec_type = AVMEDIA_TYPE_DATA;
4214 sc->ffindex = st->index;
4215 c->trak_index = st->index;
4217 if ((ret = mov_read_default(c, pb, atom)) < 0)
4222 // Here stsc refers to a chunk not described in stco. This is technically invalid,
4223 // but we can overlook it (clearing stsc) whenever stts_count == 0 (indicating no samples).
4224 if (!sc->chunk_count && !sc->stts_count && sc->stsc_count) {
4226 av_freep(&sc->stsc_data);
4230 if ((sc->chunk_count && (!sc->stts_count || !sc->stsc_count ||
4231 (!sc->sample_size && !sc->sample_count))) ||
4232 (!sc->chunk_count && sc->sample_count)) {
4233 av_log(c->fc, AV_LOG_ERROR, "stream %d, missing mandatory atoms, broken header\n",
4237 if (sc->stsc_count && sc->stsc_data[ sc->stsc_count - 1 ].first > sc->chunk_count) {
4238 av_log(c->fc, AV_LOG_ERROR, "stream %d, contradictionary STSC and STCO\n",
4240 return AVERROR_INVALIDDATA;
4243 fix_timescale(c, sc);
4245 avpriv_set_pts_info(st, 64, 1, sc->time_scale);
4247 mov_build_index(c, st);
4249 if (sc->dref_id-1 < sc->drefs_count && sc->drefs[sc->dref_id-1].path) {
4250 MOVDref *dref = &sc->drefs[sc->dref_id - 1];
4251 if (c->enable_drefs) {
4252 if (mov_open_dref(c, &sc->pb, c->fc->url, dref) < 0)
4253 av_log(c->fc, AV_LOG_ERROR,
4254 "stream %d, error opening alias: path='%s', dir='%s', "
4255 "filename='%s', volume='%s', nlvl_from=%d, nlvl_to=%d\n",
4256 st->index, dref->path, dref->dir, dref->filename,
4257 dref->volume, dref->nlvl_from, dref->nlvl_to);
4259 av_log(c->fc, AV_LOG_WARNING,
4260 "Skipped opening external track: "
4261 "stream %d, alias: path='%s', dir='%s', "
4262 "filename='%s', volume='%s', nlvl_from=%d, nlvl_to=%d."
4263 "Set enable_drefs to allow this.\n",
4264 st->index, dref->path, dref->dir, dref->filename,
4265 dref->volume, dref->nlvl_from, dref->nlvl_to);
4269 sc->pb_is_copied = 1;
4272 if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
4273 if (!st->sample_aspect_ratio.num && st->codecpar->width && st->codecpar->height &&
4274 sc->height && sc->width &&
4275 (st->codecpar->width != sc->width || st->codecpar->height != sc->height)) {
4276 st->sample_aspect_ratio = av_d2q(((double)st->codecpar->height * sc->width) /
4277 ((double)st->codecpar->width * sc->height), INT_MAX);
4280 #if FF_API_R_FRAME_RATE
4281 if (sc->stts_count == 1 || (sc->stts_count == 2 && sc->stts_data[1].count == 1))
4282 av_reduce(&st->r_frame_rate.num, &st->r_frame_rate.den,
4283 sc->time_scale, sc->stts_data[0].duration, INT_MAX);
4287 // done for ai5q, ai52, ai55, ai1q, ai12 and ai15.
4288 if (!st->codecpar->extradata_size && st->codecpar->codec_id == AV_CODEC_ID_H264 &&
4289 TAG_IS_AVCI(st->codecpar->codec_tag)) {
4290 ret = ff_generate_avci_extradata(st);
4295 switch (st->codecpar->codec_id) {
4296 #if CONFIG_H261_DECODER
4297 case AV_CODEC_ID_H261:
4299 #if CONFIG_H263_DECODER
4300 case AV_CODEC_ID_H263:
4302 #if CONFIG_MPEG4_DECODER
4303 case AV_CODEC_ID_MPEG4:
4305 st->codecpar->width = 0; /* let decoder init width/height */
4306 st->codecpar->height= 0;
4310 // If the duration of the mp3 packets is not constant, then they could need a parser
4311 if (st->codecpar->codec_id == AV_CODEC_ID_MP3
4312 && sc->stts_count > 3
4313 && sc->stts_count*10 > st->nb_frames
4314 && sc->time_scale == st->codecpar->sample_rate) {
4315 st->need_parsing = AVSTREAM_PARSE_FULL;
4317 /* Do not need those anymore. */
4318 av_freep(&sc->chunk_offsets);
4319 av_freep(&sc->sample_sizes);
4320 av_freep(&sc->keyframes);
4321 av_freep(&sc->stts_data);
4322 av_freep(&sc->stps_data);
4323 av_freep(&sc->elst_data);
4324 av_freep(&sc->rap_group);
4329 static int mov_read_ilst(MOVContext *c, AVIOContext *pb, MOVAtom atom)
4332 c->itunes_metadata = 1;
4333 ret = mov_read_default(c, pb, atom);
4334 c->itunes_metadata = 0;
4338 static int mov_read_keys(MOVContext *c, AVIOContext *pb, MOVAtom atom)
4347 count = avio_rb32(pb);
4348 if (count > UINT_MAX / sizeof(*c->meta_keys) - 1) {
4349 av_log(c->fc, AV_LOG_ERROR,
4350 "The 'keys' atom with the invalid key count: %"PRIu32"\n", count);
4351 return AVERROR_INVALIDDATA;
4354 c->meta_keys_count = count + 1;
4355 c->meta_keys = av_mallocz(c->meta_keys_count * sizeof(*c->meta_keys));
4357 return AVERROR(ENOMEM);
4359 for (i = 1; i <= count; ++i) {
4360 uint32_t key_size = avio_rb32(pb);
4361 uint32_t type = avio_rl32(pb);
4363 av_log(c->fc, AV_LOG_ERROR,
4364 "The key# %"PRIu32" in meta has invalid size:"
4365 "%"PRIu32"\n", i, key_size);
4366 return AVERROR_INVALIDDATA;
4369 if (type != MKTAG('m','d','t','a')) {
4370 avio_skip(pb, key_size);
4372 c->meta_keys[i] = av_mallocz(key_size + 1);
4373 if (!c->meta_keys[i])
4374 return AVERROR(ENOMEM);
4375 avio_read(pb, c->meta_keys[i], key_size);
4381 static int mov_read_custom(MOVContext *c, AVIOContext *pb, MOVAtom atom)
4383 int64_t end = avio_tell(pb) + atom.size;
4384 uint8_t *key = NULL, *val = NULL, *mean = NULL;
4388 MOVStreamContext *sc;
4390 if (c->fc->nb_streams < 1)
4392 st = c->fc->streams[c->fc->nb_streams-1];
4395 for (i = 0; i < 3; i++) {
4399 if (end - avio_tell(pb) <= 12)
4402 len = avio_rb32(pb);
4403 tag = avio_rl32(pb);
4404 avio_skip(pb, 4); // flags
4406 if (len < 12 || len - 12 > end - avio_tell(pb))
4410 if (tag == MKTAG('m', 'e', 'a', 'n'))
4412 else if (tag == MKTAG('n', 'a', 'm', 'e'))
4414 else if (tag == MKTAG('d', 'a', 't', 'a') && len > 4) {
4424 *p = av_malloc(len + 1);
4426 ret = AVERROR(ENOMEM);
4429 ret = ffio_read_size(pb, *p, len);
4437 if (mean && key && val) {
4438 if (strcmp(key, "iTunSMPB") == 0) {
4439 int priming, remainder, samples;
4440 if(sscanf(val, "%*X %X %X %X", &priming, &remainder, &samples) == 3){
4441 if(priming>0 && priming<16384)
4442 sc->start_pad = priming;
4445 if (strcmp(key, "cdec") != 0) {
4446 av_dict_set(&c->fc->metadata, key, val,
4447 AV_DICT_DONT_STRDUP_KEY | AV_DICT_DONT_STRDUP_VAL);
4451 av_log(c->fc, AV_LOG_VERBOSE,
4452 "Unhandled or malformed custom metadata of size %"PRId64"\n", atom.size);
4455 avio_seek(pb, end, SEEK_SET);
4462 static int mov_read_meta(MOVContext *c, AVIOContext *pb, MOVAtom atom)
4464 while (atom.size > 8) {
4468 tag = avio_rl32(pb);
4470 if (tag == MKTAG('h','d','l','r')) {
4471 avio_seek(pb, -8, SEEK_CUR);
4473 return mov_read_default(c, pb, atom);
4479 // return 1 when matrix is identity, 0 otherwise
4480 #define IS_MATRIX_IDENT(matrix) \
4481 ( (matrix)[0][0] == (1 << 16) && \
4482 (matrix)[1][1] == (1 << 16) && \
4483 (matrix)[2][2] == (1 << 30) && \
4484 !(matrix)[0][1] && !(matrix)[0][2] && \
4485 !(matrix)[1][0] && !(matrix)[1][2] && \
4486 !(matrix)[2][0] && !(matrix)[2][1])
4488 static int mov_read_tkhd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
4493 int display_matrix[3][3];
4494 int res_display_matrix[3][3] = { { 0 } };
4496 MOVStreamContext *sc;
4500 if (c->fc->nb_streams < 1)
4502 st = c->fc->streams[c->fc->nb_streams-1];
4505 // Each stream (trak) should have exactly 1 tkhd. This catches bad files and
4506 // avoids corrupting AVStreams mapped to an earlier tkhd.
4508 return AVERROR_INVALIDDATA;
4510 version = avio_r8(pb);
4511 flags = avio_rb24(pb);
4512 st->disposition |= (flags & MOV_TKHD_FLAG_ENABLED) ? AV_DISPOSITION_DEFAULT : 0;
4518 avio_rb32(pb); /* creation time */
4519 avio_rb32(pb); /* modification time */
4521 st->id = (int)avio_rb32(pb); /* track id (NOT 0 !)*/
4522 avio_rb32(pb); /* reserved */
4524 /* highlevel (considering edits) duration in movie timebase */
4525 (version == 1) ? avio_rb64(pb) : avio_rb32(pb);
4526 avio_rb32(pb); /* reserved */
4527 avio_rb32(pb); /* reserved */
4529 avio_rb16(pb); /* layer */
4530 avio_rb16(pb); /* alternate group */
4531 avio_rb16(pb); /* volume */
4532 avio_rb16(pb); /* reserved */
4534 //read in the display matrix (outlined in ISO 14496-12, Section 6.2.2)
4535 // they're kept in fixed point format through all calculations
4536 // save u,v,z to store the whole matrix in the AV_PKT_DATA_DISPLAYMATRIX
4537 // side data, but the scale factor is not needed to calculate aspect ratio
4538 for (i = 0; i < 3; i++) {
4539 display_matrix[i][0] = avio_rb32(pb); // 16.16 fixed point
4540 display_matrix[i][1] = avio_rb32(pb); // 16.16 fixed point
4541 display_matrix[i][2] = avio_rb32(pb); // 2.30 fixed point
4544 width = avio_rb32(pb); // 16.16 fixed point track width
4545 height = avio_rb32(pb); // 16.16 fixed point track height
4546 sc->width = width >> 16;
4547 sc->height = height >> 16;
4549 // apply the moov display matrix (after the tkhd one)
4550 for (i = 0; i < 3; i++) {
4551 const int sh[3] = { 16, 16, 30 };
4552 for (j = 0; j < 3; j++) {
4553 for (e = 0; e < 3; e++) {
4554 res_display_matrix[i][j] +=
4555 ((int64_t) display_matrix[i][e] *
4556 c->movie_display_matrix[e][j]) >> sh[e];
4561 // save the matrix when it is not the default identity
4562 if (!IS_MATRIX_IDENT(res_display_matrix)) {
4565 av_freep(&sc->display_matrix);
4566 sc->display_matrix = av_malloc(sizeof(int32_t) * 9);
4567 if (!sc->display_matrix)
4568 return AVERROR(ENOMEM);
4570 for (i = 0; i < 3; i++)
4571 for (j = 0; j < 3; j++)
4572 sc->display_matrix[i * 3 + j] = res_display_matrix[i][j];
4574 #if FF_API_OLD_ROTATE_API
4575 rotate = av_display_rotation_get(sc->display_matrix);
4576 if (!isnan(rotate)) {
4577 char rotate_buf[64];
4579 if (rotate < 0) // for backward compatibility
4581 snprintf(rotate_buf, sizeof(rotate_buf), "%g", rotate);
4582 av_dict_set(&st->metadata, "rotate", rotate_buf, 0);
4587 // transform the display width/height according to the matrix
4588 // to keep the same scale, use [width height 1<<16]
4589 if (width && height && sc->display_matrix) {
4590 double disp_transform[2];
4592 for (i = 0; i < 2; i++)
4593 disp_transform[i] = hypot(sc->display_matrix[0 + i],
4594 sc->display_matrix[3 + i]);
4596 if (disp_transform[0] > 0 && disp_transform[1] > 0 &&
4597 disp_transform[0] < (1<<24) && disp_transform[1] < (1<<24) &&
4598 fabs((disp_transform[0] / disp_transform[1]) - 1.0) > 0.01)
4599 st->sample_aspect_ratio = av_d2q(
4600 disp_transform[0] / disp_transform[1],
4606 static int mov_read_tfhd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
4608 MOVFragment *frag = &c->fragment;
4609 MOVTrackExt *trex = NULL;
4610 int flags, track_id, i;
4611 MOVFragmentStreamInfo * frag_stream_info;
4613 avio_r8(pb); /* version */
4614 flags = avio_rb24(pb);
4616 track_id = avio_rb32(pb);
4618 return AVERROR_INVALIDDATA;
4619 for (i = 0; i < c->trex_count; i++)
4620 if (c->trex_data[i].track_id == track_id) {
4621 trex = &c->trex_data[i];
4625 av_log(c->fc, AV_LOG_WARNING, "could not find corresponding trex (id %u)\n", track_id);
4628 c->fragment.found_tfhd = 1;
4629 frag->track_id = track_id;
4630 set_frag_stream(&c->frag_index, track_id);
4632 frag->base_data_offset = flags & MOV_TFHD_BASE_DATA_OFFSET ?
4633 avio_rb64(pb) : flags & MOV_TFHD_DEFAULT_BASE_IS_MOOF ?
4634 frag->moof_offset : frag->implicit_offset;
4635 frag->stsd_id = flags & MOV_TFHD_STSD_ID ? avio_rb32(pb) : trex->stsd_id;
4637 frag->duration = flags & MOV_TFHD_DEFAULT_DURATION ?
4638 avio_rb32(pb) : trex->duration;
4639 frag->size = flags & MOV_TFHD_DEFAULT_SIZE ?
4640 avio_rb32(pb) : trex->size;
4641 frag->flags = flags & MOV_TFHD_DEFAULT_FLAGS ?
4642 avio_rb32(pb) : trex->flags;
4643 av_log(c->fc, AV_LOG_TRACE, "frag flags 0x%x\n", frag->flags);
4645 frag_stream_info = get_current_frag_stream_info(&c->frag_index);
4646 if (frag_stream_info)
4647 frag_stream_info->next_trun_dts = AV_NOPTS_VALUE;
4652 static int mov_read_chap(MOVContext *c, AVIOContext *pb, MOVAtom atom)
4657 num = atom.size / 4;
4658 if (!(new_tracks = av_malloc_array(num, sizeof(int))))
4659 return AVERROR(ENOMEM);
4661 av_free(c->chapter_tracks);
4662 c->chapter_tracks = new_tracks;
4663 c->nb_chapter_tracks = num;
4665 for (i = 0; i < num && !pb->eof_reached; i++)
4666 c->chapter_tracks[i] = avio_rb32(pb);
4671 static int mov_read_trex(MOVContext *c, AVIOContext *pb, MOVAtom atom)
4676 if ((uint64_t)c->trex_count+1 >= UINT_MAX / sizeof(*c->trex_data))
4677 return AVERROR_INVALIDDATA;
4678 if ((err = av_reallocp_array(&c->trex_data, c->trex_count + 1,
4679 sizeof(*c->trex_data))) < 0) {
4684 c->fc->duration = AV_NOPTS_VALUE; // the duration from mvhd is not representing the whole file when fragments are used.
4686 trex = &c->trex_data[c->trex_count++];
4687 avio_r8(pb); /* version */
4688 avio_rb24(pb); /* flags */
4689 trex->track_id = avio_rb32(pb);
4690 trex->stsd_id = avio_rb32(pb);
4691 trex->duration = avio_rb32(pb);
4692 trex->size = avio_rb32(pb);
4693 trex->flags = avio_rb32(pb);
4697 static int mov_read_tfdt(MOVContext *c, AVIOContext *pb, MOVAtom atom)
4699 MOVFragment *frag = &c->fragment;
4700 AVStream *st = NULL;
4701 MOVStreamContext *sc;
4703 MOVFragmentStreamInfo * frag_stream_info;
4704 int64_t base_media_decode_time;
4706 for (i = 0; i < c->fc->nb_streams; i++) {
4707 if (c->fc->streams[i]->id == frag->track_id) {
4708 st = c->fc->streams[i];
4713 av_log(c->fc, AV_LOG_WARNING, "could not find corresponding track id %u\n", frag->track_id);
4717 if (sc->pseudo_stream_id + 1 != frag->stsd_id && sc->pseudo_stream_id != -1)
4719 version = avio_r8(pb);
4720 avio_rb24(pb); /* flags */
4722 base_media_decode_time = avio_rb64(pb);
4724 base_media_decode_time = avio_rb32(pb);
4727 frag_stream_info = get_current_frag_stream_info(&c->frag_index);
4728 if (frag_stream_info)
4729 frag_stream_info->tfdt_dts = base_media_decode_time;
4730 sc->track_end = base_media_decode_time;
4735 static int mov_read_trun(MOVContext *c, AVIOContext *pb, MOVAtom atom)
4737 MOVFragment *frag = &c->fragment;
4738 AVStream *st = NULL;
4739 MOVStreamContext *sc;
4742 int64_t dts, pts = AV_NOPTS_VALUE;
4743 int data_offset = 0;
4744 unsigned entries, first_sample_flags = frag->flags;
4745 int flags, distance, i;
4746 int64_t prev_dts = AV_NOPTS_VALUE;
4747 int next_frag_index = -1, index_entry_pos;
4748 size_t requested_size;
4749 size_t old_ctts_allocated_size;
4750 AVIndexEntry *new_entries;
4751 MOVFragmentStreamInfo * frag_stream_info;
4753 if (!frag->found_tfhd) {
4754 av_log(c->fc, AV_LOG_ERROR, "trun track id unknown, no tfhd was found\n");
4755 return AVERROR_INVALIDDATA;
4758 for (i = 0; i < c->fc->nb_streams; i++) {
4759 if (c->fc->streams[i]->id == frag->track_id) {
4760 st = c->fc->streams[i];
4765 av_log(c->fc, AV_LOG_WARNING, "could not find corresponding track id %u\n", frag->track_id);
4769 if (sc->pseudo_stream_id+1 != frag->stsd_id && sc->pseudo_stream_id != -1)
4772 // Find the next frag_index index that has a valid index_entry for
4773 // the current track_id.
4775 // A valid index_entry means the trun for the fragment was read
4776 // and it's samples are in index_entries at the given position.
4777 // New index entries will be inserted before the index_entry found.
4778 index_entry_pos = st->nb_index_entries;
4779 for (i = c->frag_index.current + 1; i < c->frag_index.nb_items; i++) {
4780 frag_stream_info = get_frag_stream_info(&c->frag_index, i, frag->track_id);
4781 if (frag_stream_info && frag_stream_info->index_entry >= 0) {
4782 next_frag_index = i;
4783 index_entry_pos = frag_stream_info->index_entry;
4787 av_assert0(index_entry_pos <= st->nb_index_entries);
4789 avio_r8(pb); /* version */
4790 flags = avio_rb24(pb);
4791 entries = avio_rb32(pb);
4792 av_log(c->fc, AV_LOG_TRACE, "flags 0x%x entries %u\n", flags, entries);
4794 if ((uint64_t)entries+sc->ctts_count >= UINT_MAX/sizeof(*sc->ctts_data))
4795 return AVERROR_INVALIDDATA;
4796 if (flags & MOV_TRUN_DATA_OFFSET) data_offset = avio_rb32(pb);
4797 if (flags & MOV_TRUN_FIRST_SAMPLE_FLAGS) first_sample_flags = avio_rb32(pb);
4799 frag_stream_info = get_current_frag_stream_info(&c->frag_index);
4800 if (frag_stream_info) {
4801 if (frag_stream_info->next_trun_dts != AV_NOPTS_VALUE) {
4802 dts = frag_stream_info->next_trun_dts - sc->time_offset;
4803 } else if (frag_stream_info->first_tfra_pts != AV_NOPTS_VALUE &&
4804 c->use_mfra_for == FF_MOV_FLAG_MFRA_PTS) {
4805 pts = frag_stream_info->first_tfra_pts;
4806 av_log(c->fc, AV_LOG_DEBUG, "found mfra time %"PRId64
4807 ", using it for pts\n", pts);
4808 } else if (frag_stream_info->first_tfra_pts != AV_NOPTS_VALUE &&
4809 c->use_mfra_for == FF_MOV_FLAG_MFRA_DTS) {
4810 dts = frag_stream_info->first_tfra_pts;
4811 av_log(c->fc, AV_LOG_DEBUG, "found mfra time %"PRId64
4812 ", using it for dts\n", pts);
4813 } else if (frag_stream_info->sidx_pts != AV_NOPTS_VALUE) {
4814 // FIXME: sidx earliest_presentation_time is *PTS*, s.b.
4815 // pts = frag_stream_info->sidx_pts;
4816 dts = frag_stream_info->sidx_pts - sc->time_offset;
4817 av_log(c->fc, AV_LOG_DEBUG, "found sidx time %"PRId64
4818 ", using it for pts\n", pts);
4819 } else if (frag_stream_info->tfdt_dts != AV_NOPTS_VALUE) {
4820 dts = frag_stream_info->tfdt_dts - sc->time_offset;
4821 av_log(c->fc, AV_LOG_DEBUG, "found tfdt time %"PRId64
4822 ", using it for dts\n", dts);
4824 dts = sc->track_end - sc->time_offset;
4825 av_log(c->fc, AV_LOG_DEBUG, "found track end time %"PRId64
4826 ", using it for dts\n", dts);
4829 dts = sc->track_end - sc->time_offset;
4830 av_log(c->fc, AV_LOG_DEBUG, "found track end time %"PRId64
4831 ", using it for dts\n", dts);
4833 offset = frag->base_data_offset + data_offset;
4835 av_log(c->fc, AV_LOG_TRACE, "first sample flags 0x%x\n", first_sample_flags);
4837 // realloc space for new index entries
4838 if((uint64_t)st->nb_index_entries + entries >= UINT_MAX / sizeof(AVIndexEntry)) {
4839 entries = UINT_MAX / sizeof(AVIndexEntry) - st->nb_index_entries;
4840 av_log(c->fc, AV_LOG_ERROR, "Failed to add index entry\n");
4845 requested_size = (st->nb_index_entries + entries) * sizeof(AVIndexEntry);
4846 new_entries = av_fast_realloc(st->index_entries,
4847 &st->index_entries_allocated_size,
4850 return AVERROR(ENOMEM);
4851 st->index_entries= new_entries;
4853 requested_size = (st->nb_index_entries + entries) * sizeof(*sc->ctts_data);
4854 old_ctts_allocated_size = sc->ctts_allocated_size;
4855 ctts_data = av_fast_realloc(sc->ctts_data, &sc->ctts_allocated_size,
4858 return AVERROR(ENOMEM);
4859 sc->ctts_data = ctts_data;
4861 // In case there were samples without ctts entries, ensure they get
4862 // zero valued entries. This ensures clips which mix boxes with and
4863 // without ctts entries don't pickup uninitialized data.
4864 memset((uint8_t*)(sc->ctts_data) + old_ctts_allocated_size, 0,
4865 sc->ctts_allocated_size - old_ctts_allocated_size);
4867 if (index_entry_pos < st->nb_index_entries) {
4868 // Make hole in index_entries and ctts_data for new samples
4869 memmove(st->index_entries + index_entry_pos + entries,
4870 st->index_entries + index_entry_pos,
4871 sizeof(*st->index_entries) *
4872 (st->nb_index_entries - index_entry_pos));
4873 memmove(sc->ctts_data + index_entry_pos + entries,
4874 sc->ctts_data + index_entry_pos,
4875 sizeof(*sc->ctts_data) * (sc->ctts_count - index_entry_pos));
4876 if (index_entry_pos < sc->current_sample) {
4877 sc->current_sample += entries;
4881 st->nb_index_entries += entries;
4882 sc->ctts_count = st->nb_index_entries;
4884 // Record the index_entry position in frag_index of this fragment
4885 if (frag_stream_info)
4886 frag_stream_info->index_entry = index_entry_pos;
4888 if (index_entry_pos > 0)
4889 prev_dts = st->index_entries[index_entry_pos-1].timestamp;
4891 for (i = 0; i < entries && !pb->eof_reached; i++) {
4892 unsigned sample_size = frag->size;
4893 int sample_flags = i ? frag->flags : first_sample_flags;
4894 unsigned sample_duration = frag->duration;
4895 unsigned ctts_duration = 0;
4897 int index_entry_flags = 0;
4899 if (flags & MOV_TRUN_SAMPLE_DURATION) sample_duration = avio_rb32(pb);
4900 if (flags & MOV_TRUN_SAMPLE_SIZE) sample_size = avio_rb32(pb);
4901 if (flags & MOV_TRUN_SAMPLE_FLAGS) sample_flags = avio_rb32(pb);
4902 if (flags & MOV_TRUN_SAMPLE_CTS) ctts_duration = avio_rb32(pb);
4904 mov_update_dts_shift(sc, ctts_duration, c->fc);
4905 if (pts != AV_NOPTS_VALUE) {
4906 dts = pts - sc->dts_shift;
4907 if (flags & MOV_TRUN_SAMPLE_CTS) {
4908 dts -= ctts_duration;
4910 dts -= sc->time_offset;
4912 av_log(c->fc, AV_LOG_DEBUG,
4913 "pts %"PRId64" calculated dts %"PRId64
4914 " sc->dts_shift %d ctts.duration %d"
4915 " sc->time_offset %"PRId64
4916 " flags & MOV_TRUN_SAMPLE_CTS %d\n",
4918 sc->dts_shift, ctts_duration,
4919 sc->time_offset, flags & MOV_TRUN_SAMPLE_CTS);
4920 pts = AV_NOPTS_VALUE;
4923 if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO)
4927 !(sample_flags & (MOV_FRAG_SAMPLE_FLAG_IS_NON_SYNC |
4928 MOV_FRAG_SAMPLE_FLAG_DEPENDS_YES));
4931 index_entry_flags |= AVINDEX_KEYFRAME;
4933 // Fragments can overlap in time. Discard overlapping frames after
4935 if (prev_dts >= dts)
4936 index_entry_flags |= AVINDEX_DISCARD_FRAME;
4938 st->index_entries[index_entry_pos].pos = offset;
4939 st->index_entries[index_entry_pos].timestamp = dts;
4940 st->index_entries[index_entry_pos].size= sample_size;
4941 st->index_entries[index_entry_pos].min_distance= distance;
4942 st->index_entries[index_entry_pos].flags = index_entry_flags;
4944 sc->ctts_data[index_entry_pos].count = 1;
4945 sc->ctts_data[index_entry_pos].duration = ctts_duration;
4948 av_log(c->fc, AV_LOG_TRACE, "AVIndex stream %d, sample %d, offset %"PRIx64", dts %"PRId64", "
4949 "size %u, distance %d, keyframe %d\n", st->index,
4950 index_entry_pos, offset, dts, sample_size, distance, keyframe);
4952 dts += sample_duration;
4953 offset += sample_size;
4954 sc->data_size += sample_size;
4956 if (sample_duration <= INT64_MAX - sc->duration_for_fps &&
4957 1 <= INT_MAX - sc->nb_frames_for_fps
4959 sc->duration_for_fps += sample_duration;
4960 sc->nb_frames_for_fps ++;
4963 if (frag_stream_info)
4964 frag_stream_info->next_trun_dts = dts + sc->time_offset;
4966 // EOF found before reading all entries. Fix the hole this would
4967 // leave in index_entries and ctts_data
4968 int gap = entries - i;
4969 memmove(st->index_entries + index_entry_pos,
4970 st->index_entries + index_entry_pos + gap,
4971 sizeof(*st->index_entries) *
4972 (st->nb_index_entries - (index_entry_pos + gap)));
4973 memmove(sc->ctts_data + index_entry_pos,
4974 sc->ctts_data + index_entry_pos + gap,
4975 sizeof(*sc->ctts_data) *
4976 (sc->ctts_count - (index_entry_pos + gap)));
4978 st->nb_index_entries -= gap;
4979 sc->ctts_count -= gap;
4980 if (index_entry_pos < sc->current_sample) {
4981 sc->current_sample -= gap;
4986 // The end of this new fragment may overlap in time with the start
4987 // of the next fragment in index_entries. Mark the samples in the next
4988 // fragment that overlap with AVINDEX_DISCARD_FRAME
4989 prev_dts = AV_NOPTS_VALUE;
4990 if (index_entry_pos > 0)
4991 prev_dts = st->index_entries[index_entry_pos-1].timestamp;
4992 for (i = index_entry_pos; i < st->nb_index_entries; i++) {
4993 if (prev_dts < st->index_entries[i].timestamp)
4995 st->index_entries[i].flags |= AVINDEX_DISCARD_FRAME;
4998 // If a hole was created to insert the new index_entries into,
4999 // the index_entry recorded for all subsequent moof must
5000 // be incremented by the number of entries inserted.
5001 fix_frag_index_entries(&c->frag_index, next_frag_index,
5002 frag->track_id, entries);
5004 if (pb->eof_reached) {
5005 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted TRUN atom\n");
5009 frag->implicit_offset = offset;
5011 sc->track_end = dts + sc->time_offset;
5012 if (st->duration < sc->track_end)
5013 st->duration = sc->track_end;
5018 static int mov_read_sidx(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5020 int64_t offset = avio_tell(pb) + atom.size, pts, timestamp;
5022 unsigned i, j, track_id, item_count;
5023 AVStream *st = NULL;
5024 AVStream *ref_st = NULL;
5025 MOVStreamContext *sc, *ref_sc = NULL;
5026 AVRational timescale;
5028 version = avio_r8(pb);
5030 avpriv_request_sample(c->fc, "sidx version %u", version);
5034 avio_rb24(pb); // flags
5036 track_id = avio_rb32(pb); // Reference ID
5037 for (i = 0; i < c->fc->nb_streams; i++) {
5038 if (c->fc->streams[i]->id == track_id) {
5039 st = c->fc->streams[i];
5044 av_log(c->fc, AV_LOG_WARNING, "could not find corresponding track id %d\n", track_id);
5050 timescale = av_make_q(1, avio_rb32(pb));
5052 if (timescale.den <= 0) {
5053 av_log(c->fc, AV_LOG_ERROR, "Invalid sidx timescale 1/%d\n", timescale.den);
5054 return AVERROR_INVALIDDATA;
5058 pts = avio_rb32(pb);
5059 offset += avio_rb32(pb);
5061 pts = avio_rb64(pb);
5062 offset += avio_rb64(pb);
5065 avio_rb16(pb); // reserved
5067 item_count = avio_rb16(pb);
5069 for (i = 0; i < item_count; i++) {
5071 MOVFragmentStreamInfo * frag_stream_info;
5072 uint32_t size = avio_rb32(pb);
5073 uint32_t duration = avio_rb32(pb);
5074 if (size & 0x80000000) {
5075 avpriv_request_sample(c->fc, "sidx reference_type 1");
5076 return AVERROR_PATCHWELCOME;
5078 avio_rb32(pb); // sap_flags
5079 timestamp = av_rescale_q(pts, timescale, st->time_base);
5081 index = update_frag_index(c, offset);
5082 frag_stream_info = get_frag_stream_info(&c->frag_index, index, track_id);
5083 if (frag_stream_info)
5084 frag_stream_info->sidx_pts = timestamp;
5090 st->duration = sc->track_end = pts;
5094 if (offset == avio_size(pb)) {
5095 // Find first entry in fragment index that came from an sidx.
5096 // This will pretty much always be the first entry.
5097 for (i = 0; i < c->frag_index.nb_items; i++) {
5098 MOVFragmentIndexItem * item = &c->frag_index.item[i];
5099 for (j = 0; ref_st == NULL && j < item->nb_stream_info; j++) {
5100 MOVFragmentStreamInfo * si;
5101 si = &item->stream_info[j];
5102 if (si->sidx_pts != AV_NOPTS_VALUE) {
5103 ref_st = c->fc->streams[j];
5104 ref_sc = ref_st->priv_data;
5109 if (ref_st) for (i = 0; i < c->fc->nb_streams; i++) {
5110 st = c->fc->streams[i];
5112 if (!sc->has_sidx) {
5113 st->duration = sc->track_end = av_rescale(ref_st->duration, sc->time_scale, ref_sc->time_scale);
5117 c->frag_index.complete = 1;
5123 /* this atom should be null (from specs), but some buggy files put the 'moov' atom inside it... */
5124 /* like the files created with Adobe Premiere 5.0, for samples see */
5125 /* http://graphics.tudelft.nl/~wouter/publications/soundtests/ */
5126 static int mov_read_wide(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5131 return 0; /* continue */
5132 if (avio_rb32(pb) != 0) { /* 0 sized mdat atom... use the 'wide' atom size */
5133 avio_skip(pb, atom.size - 4);
5136 atom.type = avio_rl32(pb);
5138 if (atom.type != MKTAG('m','d','a','t')) {
5139 avio_skip(pb, atom.size);
5142 err = mov_read_mdat(c, pb, atom);
5146 static int mov_read_cmov(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5151 uint8_t *moov_data; /* uncompressed data */
5152 long cmov_len, moov_len;
5155 avio_rb32(pb); /* dcom atom */
5156 if (avio_rl32(pb) != MKTAG('d','c','o','m'))
5157 return AVERROR_INVALIDDATA;
5158 if (avio_rl32(pb) != MKTAG('z','l','i','b')) {
5159 av_log(c->fc, AV_LOG_ERROR, "unknown compression for cmov atom !\n");
5160 return AVERROR_INVALIDDATA;
5162 avio_rb32(pb); /* cmvd atom */
5163 if (avio_rl32(pb) != MKTAG('c','m','v','d'))
5164 return AVERROR_INVALIDDATA;
5165 moov_len = avio_rb32(pb); /* uncompressed size */
5166 cmov_len = atom.size - 6 * 4;
5168 cmov_data = av_malloc(cmov_len);
5170 return AVERROR(ENOMEM);
5171 moov_data = av_malloc(moov_len);
5174 return AVERROR(ENOMEM);
5176 ret = ffio_read_size(pb, cmov_data, cmov_len);
5178 goto free_and_return;
5180 ret = AVERROR_INVALIDDATA;
5181 if (uncompress (moov_data, (uLongf *) &moov_len, (const Bytef *)cmov_data, cmov_len) != Z_OK)
5182 goto free_and_return;
5183 if (ffio_init_context(&ctx, moov_data, moov_len, 0, NULL, NULL, NULL, NULL) != 0)
5184 goto free_and_return;
5185 ctx.seekable = AVIO_SEEKABLE_NORMAL;
5186 atom.type = MKTAG('m','o','o','v');
5187 atom.size = moov_len;
5188 ret = mov_read_default(c, &ctx, atom);
5194 av_log(c->fc, AV_LOG_ERROR, "this file requires zlib support compiled in\n");
5195 return AVERROR(ENOSYS);
5199 /* edit list atom */
5200 static int mov_read_elst(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5202 MOVStreamContext *sc;
5203 int i, edit_count, version;
5204 int64_t elst_entry_size;
5206 if (c->fc->nb_streams < 1 || c->ignore_editlist)
5208 sc = c->fc->streams[c->fc->nb_streams-1]->priv_data;
5210 version = avio_r8(pb); /* version */
5211 avio_rb24(pb); /* flags */
5212 edit_count = avio_rb32(pb); /* entries */
5215 elst_entry_size = version == 1 ? 20 : 12;
5216 if (atom.size != edit_count * elst_entry_size) {
5217 if (c->fc->strict_std_compliance >= FF_COMPLIANCE_STRICT) {
5218 av_log(c->fc, AV_LOG_ERROR, "Invalid edit list entry_count: %d for elst atom of size: %"PRId64" bytes.\n",
5219 edit_count, atom.size + 8);
5220 return AVERROR_INVALIDDATA;
5222 edit_count = atom.size / elst_entry_size;
5223 if (edit_count * elst_entry_size != atom.size) {
5224 av_log(c->fc, AV_LOG_WARNING, "ELST atom of %"PRId64" bytes, bigger than %d entries.\n", atom.size, edit_count);
5232 av_log(c->fc, AV_LOG_WARNING, "Duplicated ELST atom\n");
5233 av_free(sc->elst_data);
5235 sc->elst_data = av_malloc_array(edit_count, sizeof(*sc->elst_data));
5237 return AVERROR(ENOMEM);
5239 av_log(c->fc, AV_LOG_TRACE, "track[%u].edit_count = %i\n", c->fc->nb_streams - 1, edit_count);
5240 for (i = 0; i < edit_count && atom.size > 0 && !pb->eof_reached; i++) {
5241 MOVElst *e = &sc->elst_data[i];
5244 e->duration = avio_rb64(pb);
5245 e->time = avio_rb64(pb);
5248 e->duration = avio_rb32(pb); /* segment duration */
5249 e->time = (int32_t)avio_rb32(pb); /* media time */
5252 e->rate = avio_rb32(pb) / 65536.0;
5254 av_log(c->fc, AV_LOG_TRACE, "duration=%"PRId64" time=%"PRId64" rate=%f\n",
5255 e->duration, e->time, e->rate);
5257 if (e->time < 0 && e->time != -1 &&
5258 c->fc->strict_std_compliance >= FF_COMPLIANCE_STRICT) {
5259 av_log(c->fc, AV_LOG_ERROR, "Track %d, edit %d: Invalid edit list media time=%"PRId64"\n",
5260 c->fc->nb_streams-1, i, e->time);
5261 return AVERROR_INVALIDDATA;
5269 static int mov_read_tmcd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5271 MOVStreamContext *sc;
5273 if (c->fc->nb_streams < 1)
5274 return AVERROR_INVALIDDATA;
5275 sc = c->fc->streams[c->fc->nb_streams - 1]->priv_data;
5276 sc->timecode_track = avio_rb32(pb);
5280 static int mov_read_av1c(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5285 if (c->fc->nb_streams < 1)
5287 st = c->fc->streams[c->fc->nb_streams - 1];
5289 if (atom.size < 4) {
5290 av_log(c->fc, AV_LOG_ERROR, "Empty AV1 Codec Configuration Box\n");
5291 return AVERROR_INVALIDDATA;
5294 /* For now, propagate only the OBUs, if any. Once libavcodec is
5295 updated to handle isobmff style extradata this can be removed. */
5301 ret = ff_get_extradata(c->fc, st->codecpar, pb, atom.size - 4);
5308 static int mov_read_vpcc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5311 int version, color_range, color_primaries, color_trc, color_space;
5313 if (c->fc->nb_streams < 1)
5315 st = c->fc->streams[c->fc->nb_streams - 1];
5317 if (atom.size < 5) {
5318 av_log(c->fc, AV_LOG_ERROR, "Empty VP Codec Configuration box\n");
5319 return AVERROR_INVALIDDATA;
5322 version = avio_r8(pb);
5324 av_log(c->fc, AV_LOG_WARNING, "Unsupported VP Codec Configuration box version %d\n", version);
5327 avio_skip(pb, 3); /* flags */
5329 avio_skip(pb, 2); /* profile + level */
5330 color_range = avio_r8(pb); /* bitDepth, chromaSubsampling, videoFullRangeFlag */
5331 color_primaries = avio_r8(pb);
5332 color_trc = avio_r8(pb);
5333 color_space = avio_r8(pb);
5334 if (avio_rb16(pb)) /* codecIntializationDataSize */
5335 return AVERROR_INVALIDDATA;
5337 if (!av_color_primaries_name(color_primaries))
5338 color_primaries = AVCOL_PRI_UNSPECIFIED;
5339 if (!av_color_transfer_name(color_trc))
5340 color_trc = AVCOL_TRC_UNSPECIFIED;
5341 if (!av_color_space_name(color_space))
5342 color_space = AVCOL_SPC_UNSPECIFIED;
5344 st->codecpar->color_range = (color_range & 1) ? AVCOL_RANGE_JPEG : AVCOL_RANGE_MPEG;
5345 st->codecpar->color_primaries = color_primaries;
5346 st->codecpar->color_trc = color_trc;
5347 st->codecpar->color_space = color_space;
5352 static int mov_read_smdm(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5354 MOVStreamContext *sc;
5357 if (c->fc->nb_streams < 1)
5358 return AVERROR_INVALIDDATA;
5360 sc = c->fc->streams[c->fc->nb_streams - 1]->priv_data;
5362 if (atom.size < 5) {
5363 av_log(c->fc, AV_LOG_ERROR, "Empty Mastering Display Metadata box\n");
5364 return AVERROR_INVALIDDATA;
5367 version = avio_r8(pb);
5369 av_log(c->fc, AV_LOG_WARNING, "Unsupported Mastering Display Metadata box version %d\n", version);
5372 avio_skip(pb, 3); /* flags */
5374 sc->mastering = av_mastering_display_metadata_alloc();
5376 return AVERROR(ENOMEM);
5378 for (i = 0; i < 3; i++) {
5379 sc->mastering->display_primaries[i][0] = av_make_q(avio_rb16(pb), 1 << 16);
5380 sc->mastering->display_primaries[i][1] = av_make_q(avio_rb16(pb), 1 << 16);
5382 sc->mastering->white_point[0] = av_make_q(avio_rb16(pb), 1 << 16);
5383 sc->mastering->white_point[1] = av_make_q(avio_rb16(pb), 1 << 16);
5385 sc->mastering->max_luminance = av_make_q(avio_rb32(pb), 1 << 8);
5386 sc->mastering->min_luminance = av_make_q(avio_rb32(pb), 1 << 14);
5388 sc->mastering->has_primaries = 1;
5389 sc->mastering->has_luminance = 1;
5394 static int mov_read_mdcv(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5396 MOVStreamContext *sc;
5397 const int mapping[3] = {1, 2, 0};
5398 const int chroma_den = 50000;
5399 const int luma_den = 10000;
5402 if (c->fc->nb_streams < 1)
5403 return AVERROR_INVALIDDATA;
5405 sc = c->fc->streams[c->fc->nb_streams - 1]->priv_data;
5407 if (atom.size < 24) {
5408 av_log(c->fc, AV_LOG_ERROR, "Invalid Mastering Display Color Volume box\n");
5409 return AVERROR_INVALIDDATA;
5412 sc->mastering = av_mastering_display_metadata_alloc();
5414 return AVERROR(ENOMEM);
5416 for (i = 0; i < 3; i++) {
5417 const int j = mapping[i];
5418 sc->mastering->display_primaries[j][0] = av_make_q(avio_rb16(pb), chroma_den);
5419 sc->mastering->display_primaries[j][1] = av_make_q(avio_rb16(pb), chroma_den);
5421 sc->mastering->white_point[0] = av_make_q(avio_rb16(pb), chroma_den);
5422 sc->mastering->white_point[1] = av_make_q(avio_rb16(pb), chroma_den);
5424 sc->mastering->max_luminance = av_make_q(avio_rb32(pb), luma_den);
5425 sc->mastering->min_luminance = av_make_q(avio_rb32(pb), luma_den);
5427 sc->mastering->has_luminance = 1;
5428 sc->mastering->has_primaries = 1;
5433 static int mov_read_coll(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5435 MOVStreamContext *sc;
5438 if (c->fc->nb_streams < 1)
5439 return AVERROR_INVALIDDATA;
5441 sc = c->fc->streams[c->fc->nb_streams - 1]->priv_data;
5443 if (atom.size < 5) {
5444 av_log(c->fc, AV_LOG_ERROR, "Empty Content Light Level box\n");
5445 return AVERROR_INVALIDDATA;
5448 version = avio_r8(pb);
5450 av_log(c->fc, AV_LOG_WARNING, "Unsupported Content Light Level box version %d\n", version);
5453 avio_skip(pb, 3); /* flags */
5455 sc->coll = av_content_light_metadata_alloc(&sc->coll_size);
5457 return AVERROR(ENOMEM);
5459 sc->coll->MaxCLL = avio_rb16(pb);
5460 sc->coll->MaxFALL = avio_rb16(pb);
5465 static int mov_read_clli(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5467 MOVStreamContext *sc;
5469 if (c->fc->nb_streams < 1)
5470 return AVERROR_INVALIDDATA;
5472 sc = c->fc->streams[c->fc->nb_streams - 1]->priv_data;
5474 if (atom.size < 4) {
5475 av_log(c->fc, AV_LOG_ERROR, "Empty Content Light Level Info box\n");
5476 return AVERROR_INVALIDDATA;
5479 sc->coll = av_content_light_metadata_alloc(&sc->coll_size);
5481 return AVERROR(ENOMEM);
5483 sc->coll->MaxCLL = avio_rb16(pb);
5484 sc->coll->MaxFALL = avio_rb16(pb);
5489 static int mov_read_st3d(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5492 MOVStreamContext *sc;
5493 enum AVStereo3DType type;
5496 if (c->fc->nb_streams < 1)
5499 st = c->fc->streams[c->fc->nb_streams - 1];
5502 if (atom.size < 5) {
5503 av_log(c->fc, AV_LOG_ERROR, "Empty stereoscopic video box\n");
5504 return AVERROR_INVALIDDATA;
5506 avio_skip(pb, 4); /* version + flags */
5511 type = AV_STEREO3D_2D;
5514 type = AV_STEREO3D_TOPBOTTOM;
5517 type = AV_STEREO3D_SIDEBYSIDE;
5520 av_log(c->fc, AV_LOG_WARNING, "Unknown st3d mode value %d\n", mode);
5524 sc->stereo3d = av_stereo3d_alloc();
5526 return AVERROR(ENOMEM);
5528 sc->stereo3d->type = type;
5532 static int mov_read_sv3d(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5535 MOVStreamContext *sc;
5536 int size, version, layout;
5537 int32_t yaw, pitch, roll;
5538 uint32_t l = 0, t = 0, r = 0, b = 0;
5539 uint32_t tag, padding = 0;
5540 enum AVSphericalProjection projection;
5542 if (c->fc->nb_streams < 1)
5545 st = c->fc->streams[c->fc->nb_streams - 1];
5548 if (atom.size < 8) {
5549 av_log(c->fc, AV_LOG_ERROR, "Empty spherical video box\n");
5550 return AVERROR_INVALIDDATA;
5553 size = avio_rb32(pb);
5554 if (size <= 12 || size > atom.size)
5555 return AVERROR_INVALIDDATA;
5557 tag = avio_rl32(pb);
5558 if (tag != MKTAG('s','v','h','d')) {
5559 av_log(c->fc, AV_LOG_ERROR, "Missing spherical video header\n");
5562 version = avio_r8(pb);
5564 av_log(c->fc, AV_LOG_WARNING, "Unknown spherical version %d\n",
5568 avio_skip(pb, 3); /* flags */
5569 avio_skip(pb, size - 12); /* metadata_source */
5571 size = avio_rb32(pb);
5572 if (size > atom.size)
5573 return AVERROR_INVALIDDATA;
5575 tag = avio_rl32(pb);
5576 if (tag != MKTAG('p','r','o','j')) {
5577 av_log(c->fc, AV_LOG_ERROR, "Missing projection box\n");
5581 size = avio_rb32(pb);
5582 if (size > atom.size)
5583 return AVERROR_INVALIDDATA;
5585 tag = avio_rl32(pb);
5586 if (tag != MKTAG('p','r','h','d')) {
5587 av_log(c->fc, AV_LOG_ERROR, "Missing projection header box\n");
5590 version = avio_r8(pb);
5592 av_log(c->fc, AV_LOG_WARNING, "Unknown spherical version %d\n",
5596 avio_skip(pb, 3); /* flags */
5598 /* 16.16 fixed point */
5599 yaw = avio_rb32(pb);
5600 pitch = avio_rb32(pb);
5601 roll = avio_rb32(pb);
5603 size = avio_rb32(pb);
5604 if (size > atom.size)
5605 return AVERROR_INVALIDDATA;
5607 tag = avio_rl32(pb);
5608 version = avio_r8(pb);
5610 av_log(c->fc, AV_LOG_WARNING, "Unknown spherical version %d\n",
5614 avio_skip(pb, 3); /* flags */
5616 case MKTAG('c','b','m','p'):
5617 layout = avio_rb32(pb);
5619 av_log(c->fc, AV_LOG_WARNING,
5620 "Unsupported cubemap layout %d\n", layout);
5623 projection = AV_SPHERICAL_CUBEMAP;
5624 padding = avio_rb32(pb);
5626 case MKTAG('e','q','u','i'):
5632 if (b >= UINT_MAX - t || r >= UINT_MAX - l) {
5633 av_log(c->fc, AV_LOG_ERROR,
5634 "Invalid bounding rectangle coordinates "
5635 "%"PRIu32",%"PRIu32",%"PRIu32",%"PRIu32"\n", l, t, r, b);
5636 return AVERROR_INVALIDDATA;
5639 if (l || t || r || b)
5640 projection = AV_SPHERICAL_EQUIRECTANGULAR_TILE;
5642 projection = AV_SPHERICAL_EQUIRECTANGULAR;
5645 av_log(c->fc, AV_LOG_ERROR, "Unknown projection type: %s\n", av_fourcc2str(tag));
5649 sc->spherical = av_spherical_alloc(&sc->spherical_size);
5651 return AVERROR(ENOMEM);
5653 sc->spherical->projection = projection;
5655 sc->spherical->yaw = yaw;
5656 sc->spherical->pitch = pitch;
5657 sc->spherical->roll = roll;
5659 sc->spherical->padding = padding;
5661 sc->spherical->bound_left = l;
5662 sc->spherical->bound_top = t;
5663 sc->spherical->bound_right = r;
5664 sc->spherical->bound_bottom = b;
5669 static int mov_parse_uuid_spherical(MOVStreamContext *sc, AVIOContext *pb, size_t len)
5672 uint8_t *buffer = av_malloc(len + 1);
5676 return AVERROR(ENOMEM);
5679 ret = ffio_read_size(pb, buffer, len);
5683 /* Check for mandatory keys and values, try to support XML as best-effort */
5684 if (!sc->spherical &&
5685 av_stristr(buffer, "<GSpherical:StitchingSoftware>") &&
5686 (val = av_stristr(buffer, "<GSpherical:Spherical>")) &&
5687 av_stristr(val, "true") &&
5688 (val = av_stristr(buffer, "<GSpherical:Stitched>")) &&
5689 av_stristr(val, "true") &&
5690 (val = av_stristr(buffer, "<GSpherical:ProjectionType>")) &&
5691 av_stristr(val, "equirectangular")) {
5692 sc->spherical = av_spherical_alloc(&sc->spherical_size);
5696 sc->spherical->projection = AV_SPHERICAL_EQUIRECTANGULAR;
5698 if (av_stristr(buffer, "<GSpherical:StereoMode>") && !sc->stereo3d) {
5699 enum AVStereo3DType mode;
5701 if (av_stristr(buffer, "left-right"))
5702 mode = AV_STEREO3D_SIDEBYSIDE;
5703 else if (av_stristr(buffer, "top-bottom"))
5704 mode = AV_STEREO3D_TOPBOTTOM;
5706 mode = AV_STEREO3D_2D;
5708 sc->stereo3d = av_stereo3d_alloc();
5712 sc->stereo3d->type = mode;
5716 val = av_stristr(buffer, "<GSpherical:InitialViewHeadingDegrees>");
5718 sc->spherical->yaw = strtol(val, NULL, 10) * (1 << 16);
5719 val = av_stristr(buffer, "<GSpherical:InitialViewPitchDegrees>");
5721 sc->spherical->pitch = strtol(val, NULL, 10) * (1 << 16);
5722 val = av_stristr(buffer, "<GSpherical:InitialViewRollDegrees>");
5724 sc->spherical->roll = strtol(val, NULL, 10) * (1 << 16);
5732 static int mov_read_uuid(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5735 MOVStreamContext *sc;
5738 static const uint8_t uuid_isml_manifest[] = {
5739 0xa5, 0xd4, 0x0b, 0x30, 0xe8, 0x14, 0x11, 0xdd,
5740 0xba, 0x2f, 0x08, 0x00, 0x20, 0x0c, 0x9a, 0x66
5742 static const uint8_t uuid_xmp[] = {
5743 0xbe, 0x7a, 0xcf, 0xcb, 0x97, 0xa9, 0x42, 0xe8,
5744 0x9c, 0x71, 0x99, 0x94, 0x91, 0xe3, 0xaf, 0xac
5746 static const uint8_t uuid_spherical[] = {
5747 0xff, 0xcc, 0x82, 0x63, 0xf8, 0x55, 0x4a, 0x93,
5748 0x88, 0x14, 0x58, 0x7a, 0x02, 0x52, 0x1f, 0xdd,
5751 if (atom.size < sizeof(uuid) || atom.size >= FFMIN(INT_MAX, SIZE_MAX))
5752 return AVERROR_INVALIDDATA;
5754 if (c->fc->nb_streams < 1)
5756 st = c->fc->streams[c->fc->nb_streams - 1];
5759 ret = ffio_read_size(pb, uuid, sizeof(uuid));
5762 if (!memcmp(uuid, uuid_isml_manifest, sizeof(uuid))) {
5763 uint8_t *buffer, *ptr;
5765 size_t len = atom.size - sizeof(uuid);
5768 return AVERROR_INVALIDDATA;
5770 ret = avio_skip(pb, 4); // zeroes
5773 buffer = av_mallocz(len + 1);
5775 return AVERROR(ENOMEM);
5777 ret = ffio_read_size(pb, buffer, len);
5784 while ((ptr = av_stristr(ptr, "systemBitrate=\""))) {
5785 ptr += sizeof("systemBitrate=\"") - 1;
5786 c->bitrates_count++;
5787 c->bitrates = av_realloc_f(c->bitrates, c->bitrates_count, sizeof(*c->bitrates));
5789 c->bitrates_count = 0;
5791 return AVERROR(ENOMEM);
5794 ret = strtol(ptr, &endptr, 10);
5795 if (ret < 0 || errno || *endptr != '"') {
5796 c->bitrates[c->bitrates_count - 1] = 0;
5798 c->bitrates[c->bitrates_count - 1] = ret;
5803 } else if (!memcmp(uuid, uuid_xmp, sizeof(uuid))) {
5805 size_t len = atom.size - sizeof(uuid);
5806 if (c->export_xmp) {
5807 buffer = av_mallocz(len + 1);
5809 return AVERROR(ENOMEM);
5811 ret = ffio_read_size(pb, buffer, len);
5817 av_dict_set(&c->fc->metadata, "xmp",
5818 buffer, AV_DICT_DONT_STRDUP_VAL);
5820 // skip all uuid atom, which makes it fast for long uuid-xmp file
5821 ret = avio_skip(pb, len);
5825 } else if (!memcmp(uuid, uuid_spherical, sizeof(uuid))) {
5826 size_t len = atom.size - sizeof(uuid);
5827 ret = mov_parse_uuid_spherical(sc, pb, len);
5831 av_log(c->fc, AV_LOG_WARNING, "Invalid spherical metadata found\n");
5837 static int mov_read_free(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5840 uint8_t content[16];
5845 ret = avio_read(pb, content, FFMIN(sizeof(content), atom.size));
5851 && !memcmp(content, "Anevia\x1A\x1A", 8)
5852 && c->use_mfra_for == FF_MOV_FLAG_MFRA_AUTO) {
5853 c->use_mfra_for = FF_MOV_FLAG_MFRA_PTS;
5859 static int mov_read_frma(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5861 uint32_t format = avio_rl32(pb);
5862 MOVStreamContext *sc;
5866 if (c->fc->nb_streams < 1)
5868 st = c->fc->streams[c->fc->nb_streams - 1];
5873 case MKTAG('e','n','c','v'): // encrypted video
5874 case MKTAG('e','n','c','a'): // encrypted audio
5875 id = mov_codec_id(st, format);
5876 if (st->codecpar->codec_id != AV_CODEC_ID_NONE &&
5877 st->codecpar->codec_id != id) {
5878 av_log(c->fc, AV_LOG_WARNING,
5879 "ignoring 'frma' atom of '%.4s', stream has codec id %d\n",
5880 (char*)&format, st->codecpar->codec_id);
5884 st->codecpar->codec_id = id;
5885 sc->format = format;
5889 if (format != sc->format) {
5890 av_log(c->fc, AV_LOG_WARNING,
5891 "ignoring 'frma' atom of '%.4s', stream format is '%.4s'\n",
5892 (char*)&format, (char*)&sc->format);
5901 * Gets the current encryption info and associated current stream context. If
5902 * we are parsing a track fragment, this will return the specific encryption
5903 * info for this fragment; otherwise this will return the global encryption
5904 * info for the current stream.
5906 static int get_current_encryption_info(MOVContext *c, MOVEncryptionIndex **encryption_index, MOVStreamContext **sc)
5908 MOVFragmentStreamInfo *frag_stream_info;
5912 frag_stream_info = get_current_frag_stream_info(&c->frag_index);
5913 if (frag_stream_info) {
5914 for (i = 0; i < c->fc->nb_streams; i++) {
5915 if (c->fc->streams[i]->id == frag_stream_info->id) {
5916 st = c->fc->streams[i];
5920 if (i == c->fc->nb_streams)
5922 *sc = st->priv_data;
5924 if (!frag_stream_info->encryption_index) {
5925 // If this stream isn't encrypted, don't create the index.
5926 if (!(*sc)->cenc.default_encrypted_sample)
5928 frag_stream_info->encryption_index = av_mallocz(sizeof(*frag_stream_info->encryption_index));
5929 if (!frag_stream_info->encryption_index)
5930 return AVERROR(ENOMEM);
5932 *encryption_index = frag_stream_info->encryption_index;
5935 // No current track fragment, using stream level encryption info.
5937 if (c->fc->nb_streams < 1)
5939 st = c->fc->streams[c->fc->nb_streams - 1];
5940 *sc = st->priv_data;
5942 if (!(*sc)->cenc.encryption_index) {
5943 // If this stream isn't encrypted, don't create the index.
5944 if (!(*sc)->cenc.default_encrypted_sample)
5946 (*sc)->cenc.encryption_index = av_mallocz(sizeof(*frag_stream_info->encryption_index));
5947 if (!(*sc)->cenc.encryption_index)
5948 return AVERROR(ENOMEM);
5951 *encryption_index = (*sc)->cenc.encryption_index;
5956 static int mov_read_sample_encryption_info(MOVContext *c, AVIOContext *pb, MOVStreamContext *sc, AVEncryptionInfo **sample, int use_subsamples)
5959 unsigned int subsample_count;
5960 AVSubsampleEncryptionInfo *subsamples;
5962 if (!sc->cenc.default_encrypted_sample) {
5963 av_log(c->fc, AV_LOG_ERROR, "Missing schm or tenc\n");
5964 return AVERROR_INVALIDDATA;
5967 *sample = av_encryption_info_clone(sc->cenc.default_encrypted_sample);
5969 return AVERROR(ENOMEM);
5971 if (sc->cenc.per_sample_iv_size != 0) {
5972 if ((ret = ffio_read_size(pb, (*sample)->iv, sc->cenc.per_sample_iv_size)) < 0) {
5973 av_log(c->fc, AV_LOG_ERROR, "failed to read the initialization vector\n");
5974 av_encryption_info_free(*sample);
5980 if (use_subsamples) {
5981 subsample_count = avio_rb16(pb);
5982 av_free((*sample)->subsamples);
5983 (*sample)->subsamples = av_mallocz_array(subsample_count, sizeof(*subsamples));
5984 if (!(*sample)->subsamples) {
5985 av_encryption_info_free(*sample);
5987 return AVERROR(ENOMEM);
5990 for (i = 0; i < subsample_count && !pb->eof_reached; i++) {
5991 (*sample)->subsamples[i].bytes_of_clear_data = avio_rb16(pb);
5992 (*sample)->subsamples[i].bytes_of_protected_data = avio_rb32(pb);
5995 if (pb->eof_reached) {
5996 av_log(c->fc, AV_LOG_ERROR, "hit EOF while reading sub-sample encryption info\n");
5997 av_encryption_info_free(*sample);
5999 return AVERROR_INVALIDDATA;
6001 (*sample)->subsample_count = subsample_count;
6007 static int mov_read_senc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6009 AVEncryptionInfo **encrypted_samples;
6010 MOVEncryptionIndex *encryption_index;
6011 MOVStreamContext *sc;
6012 int use_subsamples, ret;
6013 unsigned int sample_count, i, alloc_size = 0;
6015 ret = get_current_encryption_info(c, &encryption_index, &sc);
6019 if (encryption_index->nb_encrypted_samples) {
6020 // This can happen if we have both saio/saiz and senc atoms.
6021 av_log(c->fc, AV_LOG_DEBUG, "Ignoring duplicate encryption info in senc\n");
6025 avio_r8(pb); /* version */
6026 use_subsamples = avio_rb24(pb) & 0x02; /* flags */
6028 sample_count = avio_rb32(pb);
6029 if (sample_count >= INT_MAX / sizeof(*encrypted_samples))
6030 return AVERROR(ENOMEM);
6032 for (i = 0; i < sample_count; i++) {
6033 unsigned int min_samples = FFMIN(FFMAX(i + 1, 1024 * 1024), sample_count);
6034 encrypted_samples = av_fast_realloc(encryption_index->encrypted_samples, &alloc_size,
6035 min_samples * sizeof(*encrypted_samples));
6036 if (encrypted_samples) {
6037 encryption_index->encrypted_samples = encrypted_samples;
6039 ret = mov_read_sample_encryption_info(
6040 c, pb, sc, &encryption_index->encrypted_samples[i], use_subsamples);
6042 ret = AVERROR(ENOMEM);
6044 if (pb->eof_reached) {
6045 av_log(c->fc, AV_LOG_ERROR, "Hit EOF while reading senc\n");
6046 ret = AVERROR_INVALIDDATA;
6051 av_encryption_info_free(encryption_index->encrypted_samples[i - 1]);
6052 av_freep(&encryption_index->encrypted_samples);
6056 encryption_index->nb_encrypted_samples = sample_count;
6061 static int mov_parse_auxiliary_info(MOVContext *c, MOVStreamContext *sc, AVIOContext *pb, MOVEncryptionIndex *encryption_index)
6063 AVEncryptionInfo **sample, **encrypted_samples;
6065 size_t sample_count, sample_info_size, i;
6067 unsigned int alloc_size = 0;
6069 if (encryption_index->nb_encrypted_samples)
6071 sample_count = encryption_index->auxiliary_info_sample_count;
6072 if (encryption_index->auxiliary_offsets_count != 1) {
6073 av_log(c->fc, AV_LOG_ERROR, "Multiple auxiliary info chunks are not supported\n");
6074 return AVERROR_PATCHWELCOME;
6076 if (sample_count >= INT_MAX / sizeof(*encrypted_samples))
6077 return AVERROR(ENOMEM);
6079 prev_pos = avio_tell(pb);
6080 if (!(pb->seekable & AVIO_SEEKABLE_NORMAL) ||
6081 avio_seek(pb, encryption_index->auxiliary_offsets[0], SEEK_SET) != encryption_index->auxiliary_offsets[0]) {
6082 av_log(c->fc, AV_LOG_INFO, "Failed to seek for auxiliary info, will only parse senc atoms for encryption info\n");
6086 for (i = 0; i < sample_count && !pb->eof_reached; i++) {
6087 unsigned int min_samples = FFMIN(FFMAX(i + 1, 1024 * 1024), sample_count);
6088 encrypted_samples = av_fast_realloc(encryption_index->encrypted_samples, &alloc_size,
6089 min_samples * sizeof(*encrypted_samples));
6090 if (!encrypted_samples) {
6091 ret = AVERROR(ENOMEM);
6094 encryption_index->encrypted_samples = encrypted_samples;
6096 sample = &encryption_index->encrypted_samples[i];
6097 sample_info_size = encryption_index->auxiliary_info_default_size
6098 ? encryption_index->auxiliary_info_default_size
6099 : encryption_index->auxiliary_info_sizes[i];
6101 ret = mov_read_sample_encryption_info(c, pb, sc, sample, sample_info_size > sc->cenc.per_sample_iv_size);
6105 if (pb->eof_reached) {
6106 av_log(c->fc, AV_LOG_ERROR, "Hit EOF while reading auxiliary info\n");
6107 ret = AVERROR_INVALIDDATA;
6109 encryption_index->nb_encrypted_samples = sample_count;
6113 avio_seek(pb, prev_pos, SEEK_SET);
6115 for (; i > 0; i--) {
6116 av_encryption_info_free(encryption_index->encrypted_samples[i - 1]);
6118 av_freep(&encryption_index->encrypted_samples);
6124 * Tries to read the given number of bytes from the stream and puts it in a
6125 * newly allocated buffer. This reads in small chunks to avoid allocating large
6126 * memory if the file contains an invalid/malicious size value.
6128 static int mov_try_read_block(AVIOContext *pb, size_t size, uint8_t **data)
6130 const unsigned int block_size = 1024 * 1024;
6131 uint8_t *buffer = NULL;
6132 unsigned int alloc_size = 0, offset = 0;
6133 while (offset < size) {
6134 unsigned int new_size =
6135 alloc_size >= INT_MAX - block_size ? INT_MAX : alloc_size + block_size;
6136 uint8_t *new_buffer = av_fast_realloc(buffer, &alloc_size, new_size);
6137 unsigned int to_read = FFMIN(size, alloc_size) - offset;
6140 return AVERROR(ENOMEM);
6142 buffer = new_buffer;
6144 if (avio_read(pb, buffer + offset, to_read) != to_read) {
6146 return AVERROR_INVALIDDATA;
6155 static int mov_read_saiz(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6157 MOVEncryptionIndex *encryption_index;
6158 MOVStreamContext *sc;
6160 unsigned int sample_count, aux_info_type, aux_info_param;
6162 ret = get_current_encryption_info(c, &encryption_index, &sc);
6166 if (encryption_index->nb_encrypted_samples) {
6167 // This can happen if we have both saio/saiz and senc atoms.
6168 av_log(c->fc, AV_LOG_DEBUG, "Ignoring duplicate encryption info in saiz\n");
6172 if (encryption_index->auxiliary_info_sample_count) {
6173 av_log(c->fc, AV_LOG_ERROR, "Duplicate saiz atom\n");
6174 return AVERROR_INVALIDDATA;
6177 avio_r8(pb); /* version */
6178 if (avio_rb24(pb) & 0x01) { /* flags */
6179 aux_info_type = avio_rb32(pb);
6180 aux_info_param = avio_rb32(pb);
6181 if (sc->cenc.default_encrypted_sample) {
6182 if (aux_info_type != sc->cenc.default_encrypted_sample->scheme) {
6183 av_log(c->fc, AV_LOG_DEBUG, "Ignoring saiz box with non-zero aux_info_type\n");
6186 if (aux_info_param != 0) {
6187 av_log(c->fc, AV_LOG_DEBUG, "Ignoring saiz box with non-zero aux_info_type_parameter\n");
6191 // Didn't see 'schm' or 'tenc', so this isn't encrypted.
6192 if ((aux_info_type == MKBETAG('c','e','n','c') ||
6193 aux_info_type == MKBETAG('c','e','n','s') ||
6194 aux_info_type == MKBETAG('c','b','c','1') ||
6195 aux_info_type == MKBETAG('c','b','c','s')) &&
6196 aux_info_param == 0) {
6197 av_log(c->fc, AV_LOG_ERROR, "Saw encrypted saiz without schm/tenc\n");
6198 return AVERROR_INVALIDDATA;
6203 } else if (!sc->cenc.default_encrypted_sample) {
6204 // Didn't see 'schm' or 'tenc', so this isn't encrypted.
6208 encryption_index->auxiliary_info_default_size = avio_r8(pb);
6209 sample_count = avio_rb32(pb);
6210 encryption_index->auxiliary_info_sample_count = sample_count;
6212 if (encryption_index->auxiliary_info_default_size == 0) {
6213 ret = mov_try_read_block(pb, sample_count, &encryption_index->auxiliary_info_sizes);
6215 av_log(c->fc, AV_LOG_ERROR, "Failed to read the auxiliary info\n");
6220 if (encryption_index->auxiliary_offsets_count) {
6221 return mov_parse_auxiliary_info(c, sc, pb, encryption_index);
6227 static int mov_read_saio(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6229 uint64_t *auxiliary_offsets;
6230 MOVEncryptionIndex *encryption_index;
6231 MOVStreamContext *sc;
6233 unsigned int version, entry_count, aux_info_type, aux_info_param;
6234 unsigned int alloc_size = 0;
6236 ret = get_current_encryption_info(c, &encryption_index, &sc);
6240 if (encryption_index->nb_encrypted_samples) {
6241 // This can happen if we have both saio/saiz and senc atoms.
6242 av_log(c->fc, AV_LOG_DEBUG, "Ignoring duplicate encryption info in saio\n");
6246 if (encryption_index->auxiliary_offsets_count) {
6247 av_log(c->fc, AV_LOG_ERROR, "Duplicate saio atom\n");
6248 return AVERROR_INVALIDDATA;
6251 version = avio_r8(pb); /* version */
6252 if (avio_rb24(pb) & 0x01) { /* flags */
6253 aux_info_type = avio_rb32(pb);
6254 aux_info_param = avio_rb32(pb);
6255 if (sc->cenc.default_encrypted_sample) {
6256 if (aux_info_type != sc->cenc.default_encrypted_sample->scheme) {
6257 av_log(c->fc, AV_LOG_DEBUG, "Ignoring saio box with non-zero aux_info_type\n");
6260 if (aux_info_param != 0) {
6261 av_log(c->fc, AV_LOG_DEBUG, "Ignoring saio box with non-zero aux_info_type_parameter\n");
6265 // Didn't see 'schm' or 'tenc', so this isn't encrypted.
6266 if ((aux_info_type == MKBETAG('c','e','n','c') ||
6267 aux_info_type == MKBETAG('c','e','n','s') ||
6268 aux_info_type == MKBETAG('c','b','c','1') ||
6269 aux_info_type == MKBETAG('c','b','c','s')) &&
6270 aux_info_param == 0) {
6271 av_log(c->fc, AV_LOG_ERROR, "Saw encrypted saio without schm/tenc\n");
6272 return AVERROR_INVALIDDATA;
6277 } else if (!sc->cenc.default_encrypted_sample) {
6278 // Didn't see 'schm' or 'tenc', so this isn't encrypted.
6282 entry_count = avio_rb32(pb);
6283 if (entry_count >= INT_MAX / sizeof(*auxiliary_offsets))
6284 return AVERROR(ENOMEM);
6286 for (i = 0; i < entry_count && !pb->eof_reached; i++) {
6287 unsigned int min_offsets = FFMIN(FFMAX(i + 1, 1024), entry_count);
6288 auxiliary_offsets = av_fast_realloc(
6289 encryption_index->auxiliary_offsets, &alloc_size,
6290 min_offsets * sizeof(*auxiliary_offsets));
6291 if (!auxiliary_offsets) {
6292 av_freep(&encryption_index->auxiliary_offsets);
6293 return AVERROR(ENOMEM);
6295 encryption_index->auxiliary_offsets = auxiliary_offsets;
6298 encryption_index->auxiliary_offsets[i] = avio_rb32(pb);
6300 encryption_index->auxiliary_offsets[i] = avio_rb64(pb);
6302 if (c->frag_index.current >= 0) {
6303 encryption_index->auxiliary_offsets[i] += c->fragment.base_data_offset;
6307 if (pb->eof_reached) {
6308 av_log(c->fc, AV_LOG_ERROR, "Hit EOF while reading saio\n");
6309 av_freep(&encryption_index->auxiliary_offsets);
6310 return AVERROR_INVALIDDATA;
6313 encryption_index->auxiliary_offsets_count = entry_count;
6315 if (encryption_index->auxiliary_info_sample_count) {
6316 return mov_parse_auxiliary_info(c, sc, pb, encryption_index);
6322 static int mov_read_pssh(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6324 AVEncryptionInitInfo *info, *old_init_info;
6327 uint8_t *side_data, *extra_data, *old_side_data;
6328 size_t side_data_size;
6329 int ret = 0, old_side_data_size;
6330 unsigned int version, kid_count, extra_data_size, alloc_size = 0;
6332 if (c->fc->nb_streams < 1)
6334 st = c->fc->streams[c->fc->nb_streams-1];
6336 version = avio_r8(pb); /* version */
6337 avio_rb24(pb); /* flags */
6339 info = av_encryption_init_info_alloc(/* system_id_size */ 16, /* num_key_ids */ 0,
6340 /* key_id_size */ 16, /* data_size */ 0);
6342 return AVERROR(ENOMEM);
6344 if ((ret = ffio_read_size(pb, info->system_id, 16)) < 0) {
6345 av_log(c->fc, AV_LOG_ERROR, "Failed to read the system id\n");
6350 kid_count = avio_rb32(pb);
6351 if (kid_count >= INT_MAX / sizeof(*key_ids)) {
6352 ret = AVERROR(ENOMEM);
6356 for (unsigned int i = 0; i < kid_count && !pb->eof_reached; i++) {
6357 unsigned int min_kid_count = FFMIN(FFMAX(i + 1, 1024), kid_count);
6358 key_ids = av_fast_realloc(info->key_ids, &alloc_size,
6359 min_kid_count * sizeof(*key_ids));
6361 ret = AVERROR(ENOMEM);
6364 info->key_ids = key_ids;
6366 info->key_ids[i] = av_mallocz(16);
6367 if (!info->key_ids[i]) {
6368 ret = AVERROR(ENOMEM);
6371 info->num_key_ids = i + 1;
6373 if ((ret = ffio_read_size(pb, info->key_ids[i], 16)) < 0) {
6374 av_log(c->fc, AV_LOG_ERROR, "Failed to read the key id\n");
6379 if (pb->eof_reached) {
6380 av_log(c->fc, AV_LOG_ERROR, "Hit EOF while reading pssh\n");
6381 ret = AVERROR_INVALIDDATA;
6386 extra_data_size = avio_rb32(pb);
6387 ret = mov_try_read_block(pb, extra_data_size, &extra_data);
6391 av_freep(&info->data); // malloc(0) may still allocate something.
6392 info->data = extra_data;
6393 info->data_size = extra_data_size;
6395 // If there is existing initialization data, append to the list.
6396 old_side_data = av_stream_get_side_data(st, AV_PKT_DATA_ENCRYPTION_INIT_INFO, &old_side_data_size);
6397 if (old_side_data) {
6398 old_init_info = av_encryption_init_info_get_side_data(old_side_data, old_side_data_size);
6399 if (old_init_info) {
6400 // Append to the end of the list.
6401 for (AVEncryptionInitInfo *cur = old_init_info;; cur = cur->next) {
6407 info = old_init_info;
6409 // Assume existing side-data will be valid, so the only error we could get is OOM.
6410 ret = AVERROR(ENOMEM);
6415 side_data = av_encryption_init_info_add_side_data(info, &side_data_size);
6417 ret = AVERROR(ENOMEM);
6420 ret = av_stream_add_side_data(st, AV_PKT_DATA_ENCRYPTION_INIT_INFO,
6421 side_data, side_data_size);
6426 av_encryption_init_info_free(info);
6430 static int mov_read_schm(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6433 MOVStreamContext *sc;
6435 if (c->fc->nb_streams < 1)
6437 st = c->fc->streams[c->fc->nb_streams-1];
6440 if (sc->pseudo_stream_id != 0) {
6441 av_log(c->fc, AV_LOG_ERROR, "schm boxes are only supported in first sample descriptor\n");
6442 return AVERROR_PATCHWELCOME;
6446 return AVERROR_INVALIDDATA;
6448 avio_rb32(pb); /* version and flags */
6450 if (!sc->cenc.default_encrypted_sample) {
6451 sc->cenc.default_encrypted_sample = av_encryption_info_alloc(0, 16, 16);
6452 if (!sc->cenc.default_encrypted_sample) {
6453 return AVERROR(ENOMEM);
6457 sc->cenc.default_encrypted_sample->scheme = avio_rb32(pb);
6461 static int mov_read_tenc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6464 MOVStreamContext *sc;
6465 unsigned int version, pattern, is_protected, iv_size;
6467 if (c->fc->nb_streams < 1)
6469 st = c->fc->streams[c->fc->nb_streams-1];
6472 if (sc->pseudo_stream_id != 0) {
6473 av_log(c->fc, AV_LOG_ERROR, "tenc atom are only supported in first sample descriptor\n");
6474 return AVERROR_PATCHWELCOME;
6477 if (!sc->cenc.default_encrypted_sample) {
6478 sc->cenc.default_encrypted_sample = av_encryption_info_alloc(0, 16, 16);
6479 if (!sc->cenc.default_encrypted_sample) {
6480 return AVERROR(ENOMEM);
6485 return AVERROR_INVALIDDATA;
6487 version = avio_r8(pb); /* version */
6488 avio_rb24(pb); /* flags */
6490 avio_r8(pb); /* reserved */
6491 pattern = avio_r8(pb);
6494 sc->cenc.default_encrypted_sample->crypt_byte_block = pattern >> 4;
6495 sc->cenc.default_encrypted_sample->skip_byte_block = pattern & 0xf;
6498 is_protected = avio_r8(pb);
6499 if (is_protected && !sc->cenc.encryption_index) {
6500 // The whole stream should be by-default encrypted.
6501 sc->cenc.encryption_index = av_mallocz(sizeof(MOVEncryptionIndex));
6502 if (!sc->cenc.encryption_index)
6503 return AVERROR(ENOMEM);
6505 sc->cenc.per_sample_iv_size = avio_r8(pb);
6506 if (sc->cenc.per_sample_iv_size != 0 && sc->cenc.per_sample_iv_size != 8 &&
6507 sc->cenc.per_sample_iv_size != 16) {
6508 av_log(c->fc, AV_LOG_ERROR, "invalid per-sample IV size value\n");
6509 return AVERROR_INVALIDDATA;
6511 if (avio_read(pb, sc->cenc.default_encrypted_sample->key_id, 16) != 16) {
6512 av_log(c->fc, AV_LOG_ERROR, "failed to read the default key ID\n");
6513 return AVERROR_INVALIDDATA;
6516 if (is_protected && !sc->cenc.per_sample_iv_size) {
6517 iv_size = avio_r8(pb);
6518 if (iv_size != 8 && iv_size != 16) {
6519 av_log(c->fc, AV_LOG_ERROR, "invalid default_constant_IV_size in tenc atom\n");
6520 return AVERROR_INVALIDDATA;
6523 if (avio_read(pb, sc->cenc.default_encrypted_sample->iv, iv_size) != iv_size) {
6524 av_log(c->fc, AV_LOG_ERROR, "failed to read the default IV\n");
6525 return AVERROR_INVALIDDATA;
6532 static int mov_read_dfla(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6535 int last, type, size, ret;
6538 if (c->fc->nb_streams < 1)
6540 st = c->fc->streams[c->fc->nb_streams-1];
6542 if ((uint64_t)atom.size > (1<<30) || atom.size < 42)
6543 return AVERROR_INVALIDDATA;
6545 /* Check FlacSpecificBox version. */
6546 if (avio_r8(pb) != 0)
6547 return AVERROR_INVALIDDATA;
6549 avio_rb24(pb); /* Flags */
6551 avio_read(pb, buf, sizeof(buf));
6552 flac_parse_block_header(buf, &last, &type, &size);
6554 if (type != FLAC_METADATA_TYPE_STREAMINFO || size != FLAC_STREAMINFO_SIZE) {
6555 av_log(c->fc, AV_LOG_ERROR, "STREAMINFO must be first FLACMetadataBlock\n");
6556 return AVERROR_INVALIDDATA;
6559 ret = ff_get_extradata(c->fc, st->codecpar, pb, size);
6564 av_log(c->fc, AV_LOG_WARNING, "non-STREAMINFO FLACMetadataBlock(s) ignored\n");
6569 static int cenc_decrypt(MOVContext *c, MOVStreamContext *sc, AVEncryptionInfo *sample, uint8_t *input, int size)
6573 if (sample->scheme != MKBETAG('c','e','n','c') || sample->crypt_byte_block != 0 || sample->skip_byte_block != 0) {
6574 av_log(c->fc, AV_LOG_ERROR, "Only the 'cenc' encryption scheme is supported\n");
6575 return AVERROR_PATCHWELCOME;
6578 if (!sc->cenc.aes_ctr) {
6579 /* initialize the cipher */
6580 sc->cenc.aes_ctr = av_aes_ctr_alloc();
6581 if (!sc->cenc.aes_ctr) {
6582 return AVERROR(ENOMEM);
6585 ret = av_aes_ctr_init(sc->cenc.aes_ctr, c->decryption_key);
6591 av_aes_ctr_set_full_iv(sc->cenc.aes_ctr, sample->iv);
6593 if (!sample->subsample_count) {
6594 /* decrypt the whole packet */
6595 av_aes_ctr_crypt(sc->cenc.aes_ctr, input, input, size);
6599 for (i = 0; i < sample->subsample_count; i++) {
6600 if (sample->subsamples[i].bytes_of_clear_data + sample->subsamples[i].bytes_of_protected_data > size) {
6601 av_log(c->fc, AV_LOG_ERROR, "subsample size exceeds the packet size left\n");
6602 return AVERROR_INVALIDDATA;
6605 /* skip the clear bytes */
6606 input += sample->subsamples[i].bytes_of_clear_data;
6607 size -= sample->subsamples[i].bytes_of_clear_data;
6609 /* decrypt the encrypted bytes */
6610 av_aes_ctr_crypt(sc->cenc.aes_ctr, input, input, sample->subsamples[i].bytes_of_protected_data);
6611 input += sample->subsamples[i].bytes_of_protected_data;
6612 size -= sample->subsamples[i].bytes_of_protected_data;
6616 av_log(c->fc, AV_LOG_ERROR, "leftover packet bytes after subsample processing\n");
6617 return AVERROR_INVALIDDATA;
6623 static int cenc_filter(MOVContext *mov, AVStream* st, MOVStreamContext *sc, AVPacket *pkt, int current_index)
6625 MOVFragmentStreamInfo *frag_stream_info;
6626 MOVEncryptionIndex *encryption_index;
6627 AVEncryptionInfo *encrypted_sample;
6628 int encrypted_index, ret;
6630 frag_stream_info = get_frag_stream_info(&mov->frag_index, mov->frag_index.current, st->id);
6631 encrypted_index = current_index;
6632 encryption_index = NULL;
6633 if (frag_stream_info) {
6634 // Note this only supports encryption info in the first sample descriptor.
6635 if (mov->fragment.stsd_id == 1) {
6636 if (frag_stream_info->encryption_index) {
6637 encrypted_index = current_index - frag_stream_info->index_entry;
6638 encryption_index = frag_stream_info->encryption_index;
6640 encryption_index = sc->cenc.encryption_index;
6644 encryption_index = sc->cenc.encryption_index;
6647 if (encryption_index) {
6648 if (encryption_index->auxiliary_info_sample_count &&
6649 !encryption_index->nb_encrypted_samples) {
6650 av_log(mov->fc, AV_LOG_ERROR, "saiz atom found without saio\n");
6651 return AVERROR_INVALIDDATA;
6653 if (encryption_index->auxiliary_offsets_count &&
6654 !encryption_index->nb_encrypted_samples) {
6655 av_log(mov->fc, AV_LOG_ERROR, "saio atom found without saiz\n");
6656 return AVERROR_INVALIDDATA;
6659 if (!encryption_index->nb_encrypted_samples) {
6660 // Full-sample encryption with default settings.
6661 encrypted_sample = sc->cenc.default_encrypted_sample;
6662 } else if (encrypted_index >= 0 && encrypted_index < encryption_index->nb_encrypted_samples) {
6663 // Per-sample setting override.
6664 encrypted_sample = encryption_index->encrypted_samples[encrypted_index];
6666 av_log(mov->fc, AV_LOG_ERROR, "Incorrect number of samples in encryption info\n");
6667 return AVERROR_INVALIDDATA;
6670 if (mov->decryption_key) {
6671 return cenc_decrypt(mov, sc, encrypted_sample, pkt->data, pkt->size);
6674 uint8_t *side_data = av_encryption_info_add_side_data(encrypted_sample, &size);
6676 return AVERROR(ENOMEM);
6677 ret = av_packet_add_side_data(pkt, AV_PKT_DATA_ENCRYPTION_INFO, side_data, size);
6687 static int mov_read_dops(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6689 const int OPUS_SEEK_PREROLL_MS = 80;
6695 if (c->fc->nb_streams < 1)
6697 st = c->fc->streams[c->fc->nb_streams-1];
6699 if ((uint64_t)atom.size > (1<<30) || atom.size < 11)
6700 return AVERROR_INVALIDDATA;
6702 /* Check OpusSpecificBox version. */
6703 if (avio_r8(pb) != 0) {
6704 av_log(c->fc, AV_LOG_ERROR, "unsupported OpusSpecificBox version\n");
6705 return AVERROR_INVALIDDATA;
6708 /* OpusSpecificBox size plus magic for Ogg OpusHead header. */
6709 size = atom.size + 8;
6711 if ((ret = ff_alloc_extradata(st->codecpar, size)) < 0)
6714 AV_WL32(st->codecpar->extradata, MKTAG('O','p','u','s'));
6715 AV_WL32(st->codecpar->extradata + 4, MKTAG('H','e','a','d'));
6716 AV_WB8(st->codecpar->extradata + 8, 1); /* OpusHead version */
6717 avio_read(pb, st->codecpar->extradata + 9, size - 9);
6719 /* OpusSpecificBox is stored in big-endian, but OpusHead is
6720 little-endian; aside from the preceeding magic and version they're
6721 otherwise currently identical. Data after output gain at offset 16
6722 doesn't need to be bytewapped. */
6723 pre_skip = AV_RB16(st->codecpar->extradata + 10);
6724 AV_WL16(st->codecpar->extradata + 10, pre_skip);
6725 AV_WL32(st->codecpar->extradata + 12, AV_RB32(st->codecpar->extradata + 12));
6726 AV_WL16(st->codecpar->extradata + 16, AV_RB16(st->codecpar->extradata + 16));
6728 st->codecpar->initial_padding = pre_skip;
6729 st->codecpar->seek_preroll = av_rescale_q(OPUS_SEEK_PREROLL_MS,
6730 (AVRational){1, 1000},
6731 (AVRational){1, 48000});
6736 static int mov_read_dmlp(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6739 unsigned format_info;
6740 int channel_assignment, channel_assignment1, channel_assignment2;
6743 if (c->fc->nb_streams < 1)
6745 st = c->fc->streams[c->fc->nb_streams-1];
6748 return AVERROR_INVALIDDATA;
6750 format_info = avio_rb32(pb);
6752 ratebits = (format_info >> 28) & 0xF;
6753 channel_assignment1 = (format_info >> 15) & 0x1F;
6754 channel_assignment2 = format_info & 0x1FFF;
6755 if (channel_assignment2)
6756 channel_assignment = channel_assignment2;
6758 channel_assignment = channel_assignment1;
6760 st->codecpar->frame_size = 40 << (ratebits & 0x7);
6761 st->codecpar->sample_rate = mlp_samplerate(ratebits);
6762 st->codecpar->channels = truehd_channels(channel_assignment);
6763 st->codecpar->channel_layout = truehd_layout(channel_assignment);
6768 static int mov_read_dvcc_dvvc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6772 AVDOVIDecoderConfigurationRecord *dovi;
6776 if (c->fc->nb_streams < 1)
6778 st = c->fc->streams[c->fc->nb_streams-1];
6780 if ((uint64_t)atom.size > (1<<30) || atom.size < 4)
6781 return AVERROR_INVALIDDATA;
6783 dovi = av_dovi_alloc(&dovi_size);
6785 return AVERROR(ENOMEM);
6787 dovi->dv_version_major = avio_r8(pb);
6788 dovi->dv_version_minor = avio_r8(pb);
6790 buf = avio_rb16(pb);
6791 dovi->dv_profile = (buf >> 9) & 0x7f; // 7 bits
6792 dovi->dv_level = (buf >> 3) & 0x3f; // 6 bits
6793 dovi->rpu_present_flag = (buf >> 2) & 0x01; // 1 bit
6794 dovi->el_present_flag = (buf >> 1) & 0x01; // 1 bit
6795 dovi->bl_present_flag = buf & 0x01; // 1 bit
6796 if (atom.size >= 24) { // 4 + 4 + 4 * 4
6798 dovi->dv_bl_signal_compatibility_id = (buf >> 4) & 0x0f; // 4 bits
6800 // 0 stands for None
6801 // Dolby Vision V1.2.93 profiles and levels
6802 dovi->dv_bl_signal_compatibility_id = 0;
6805 ret = av_stream_add_side_data(st, AV_PKT_DATA_DOVI_CONF,
6806 (uint8_t *)dovi, dovi_size);
6812 av_log(c, AV_LOG_TRACE, "DOVI in dvcC/dvvC box, version: %d.%d, profile: %d, level: %d, "
6813 "rpu flag: %d, el flag: %d, bl flag: %d, compatibility id: %d\n",
6814 dovi->dv_version_major, dovi->dv_version_minor,
6815 dovi->dv_profile, dovi->dv_level,
6816 dovi->rpu_present_flag,
6817 dovi->el_present_flag,
6818 dovi->bl_present_flag,
6819 dovi->dv_bl_signal_compatibility_id
6825 static const MOVParseTableEntry mov_default_parse_table[] = {
6826 { MKTAG('A','C','L','R'), mov_read_aclr },
6827 { MKTAG('A','P','R','G'), mov_read_avid },
6828 { MKTAG('A','A','L','P'), mov_read_avid },
6829 { MKTAG('A','R','E','S'), mov_read_ares },
6830 { MKTAG('a','v','s','s'), mov_read_avss },
6831 { MKTAG('a','v','1','C'), mov_read_av1c },
6832 { MKTAG('c','h','p','l'), mov_read_chpl },
6833 { MKTAG('c','o','6','4'), mov_read_stco },
6834 { MKTAG('c','o','l','r'), mov_read_colr },
6835 { MKTAG('c','t','t','s'), mov_read_ctts }, /* composition time to sample */
6836 { MKTAG('d','i','n','f'), mov_read_default },
6837 { MKTAG('D','p','x','E'), mov_read_dpxe },
6838 { MKTAG('d','r','e','f'), mov_read_dref },
6839 { MKTAG('e','d','t','s'), mov_read_default },
6840 { MKTAG('e','l','s','t'), mov_read_elst },
6841 { MKTAG('e','n','d','a'), mov_read_enda },
6842 { MKTAG('f','i','e','l'), mov_read_fiel },
6843 { MKTAG('a','d','r','m'), mov_read_adrm },
6844 { MKTAG('f','t','y','p'), mov_read_ftyp },
6845 { MKTAG('g','l','b','l'), mov_read_glbl },
6846 { MKTAG('h','d','l','r'), mov_read_hdlr },
6847 { MKTAG('i','l','s','t'), mov_read_ilst },
6848 { MKTAG('j','p','2','h'), mov_read_jp2h },
6849 { MKTAG('m','d','a','t'), mov_read_mdat },
6850 { MKTAG('m','d','h','d'), mov_read_mdhd },
6851 { MKTAG('m','d','i','a'), mov_read_default },
6852 { MKTAG('m','e','t','a'), mov_read_meta },
6853 { MKTAG('m','i','n','f'), mov_read_default },
6854 { MKTAG('m','o','o','f'), mov_read_moof },
6855 { MKTAG('m','o','o','v'), mov_read_moov },
6856 { MKTAG('m','v','e','x'), mov_read_default },
6857 { MKTAG('m','v','h','d'), mov_read_mvhd },
6858 { MKTAG('S','M','I',' '), mov_read_svq3 },
6859 { MKTAG('a','l','a','c'), mov_read_alac }, /* alac specific atom */
6860 { MKTAG('a','v','c','C'), mov_read_glbl },
6861 { MKTAG('p','a','s','p'), mov_read_pasp },
6862 { MKTAG('s','i','d','x'), mov_read_sidx },
6863 { MKTAG('s','t','b','l'), mov_read_default },
6864 { MKTAG('s','t','c','o'), mov_read_stco },
6865 { MKTAG('s','t','p','s'), mov_read_stps },
6866 { MKTAG('s','t','r','f'), mov_read_strf },
6867 { MKTAG('s','t','s','c'), mov_read_stsc },
6868 { MKTAG('s','t','s','d'), mov_read_stsd }, /* sample description */
6869 { MKTAG('s','t','s','s'), mov_read_stss }, /* sync sample */
6870 { MKTAG('s','t','s','z'), mov_read_stsz }, /* sample size */
6871 { MKTAG('s','t','t','s'), mov_read_stts },
6872 { MKTAG('s','t','z','2'), mov_read_stsz }, /* compact sample size */
6873 { MKTAG('s','d','t','p'), mov_read_sdtp }, /* independent and disposable samples */
6874 { MKTAG('t','k','h','d'), mov_read_tkhd }, /* track header */
6875 { MKTAG('t','f','d','t'), mov_read_tfdt },
6876 { MKTAG('t','f','h','d'), mov_read_tfhd }, /* track fragment header */
6877 { MKTAG('t','r','a','k'), mov_read_trak },
6878 { MKTAG('t','r','a','f'), mov_read_default },
6879 { MKTAG('t','r','e','f'), mov_read_default },
6880 { MKTAG('t','m','c','d'), mov_read_tmcd },
6881 { MKTAG('c','h','a','p'), mov_read_chap },
6882 { MKTAG('t','r','e','x'), mov_read_trex },
6883 { MKTAG('t','r','u','n'), mov_read_trun },
6884 { MKTAG('u','d','t','a'), mov_read_default },
6885 { MKTAG('w','a','v','e'), mov_read_wave },
6886 { MKTAG('e','s','d','s'), mov_read_esds },
6887 { MKTAG('d','a','c','3'), mov_read_dac3 }, /* AC-3 info */
6888 { MKTAG('d','e','c','3'), mov_read_dec3 }, /* EAC-3 info */
6889 { MKTAG('d','d','t','s'), mov_read_ddts }, /* DTS audio descriptor */
6890 { MKTAG('w','i','d','e'), mov_read_wide }, /* place holder */
6891 { MKTAG('w','f','e','x'), mov_read_wfex },
6892 { MKTAG('c','m','o','v'), mov_read_cmov },
6893 { MKTAG('c','h','a','n'), mov_read_chan }, /* channel layout */
6894 { MKTAG('d','v','c','1'), mov_read_dvc1 },
6895 { MKTAG('s','b','g','p'), mov_read_sbgp },
6896 { MKTAG('h','v','c','C'), mov_read_glbl },
6897 { MKTAG('u','u','i','d'), mov_read_uuid },
6898 { MKTAG('C','i','n', 0x8e), mov_read_targa_y216 },
6899 { MKTAG('f','r','e','e'), mov_read_free },
6900 { MKTAG('-','-','-','-'), mov_read_custom },
6901 { MKTAG('s','i','n','f'), mov_read_default },
6902 { MKTAG('f','r','m','a'), mov_read_frma },
6903 { MKTAG('s','e','n','c'), mov_read_senc },
6904 { MKTAG('s','a','i','z'), mov_read_saiz },
6905 { MKTAG('s','a','i','o'), mov_read_saio },
6906 { MKTAG('p','s','s','h'), mov_read_pssh },
6907 { MKTAG('s','c','h','m'), mov_read_schm },
6908 { MKTAG('s','c','h','i'), mov_read_default },
6909 { MKTAG('t','e','n','c'), mov_read_tenc },
6910 { MKTAG('d','f','L','a'), mov_read_dfla },
6911 { MKTAG('s','t','3','d'), mov_read_st3d }, /* stereoscopic 3D video box */
6912 { MKTAG('s','v','3','d'), mov_read_sv3d }, /* spherical video box */
6913 { MKTAG('d','O','p','s'), mov_read_dops },
6914 { MKTAG('d','m','l','p'), mov_read_dmlp },
6915 { MKTAG('S','m','D','m'), mov_read_smdm },
6916 { MKTAG('C','o','L','L'), mov_read_coll },
6917 { MKTAG('v','p','c','C'), mov_read_vpcc },
6918 { MKTAG('m','d','c','v'), mov_read_mdcv },
6919 { MKTAG('c','l','l','i'), mov_read_clli },
6920 { MKTAG('d','v','c','C'), mov_read_dvcc_dvvc },
6921 { MKTAG('d','v','v','C'), mov_read_dvcc_dvvc },
6925 static int mov_read_default(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6927 int64_t total_size = 0;
6931 if (c->atom_depth > 10) {
6932 av_log(c->fc, AV_LOG_ERROR, "Atoms too deeply nested\n");
6933 return AVERROR_INVALIDDATA;
6938 atom.size = INT64_MAX;
6939 while (total_size <= atom.size - 8 && !avio_feof(pb)) {
6940 int (*parse)(MOVContext*, AVIOContext*, MOVAtom) = NULL;
6943 if (atom.size >= 8) {
6944 a.size = avio_rb32(pb);
6945 a.type = avio_rl32(pb);
6946 if (((a.type == MKTAG('f','r','e','e') && c->moov_retry) ||
6947 a.type == MKTAG('h','o','o','v')) &&
6949 c->fc->strict_std_compliance < FF_COMPLIANCE_STRICT) {
6952 type = avio_rl32(pb);
6953 avio_seek(pb, -8, SEEK_CUR);
6954 if (type == MKTAG('m','v','h','d') ||
6955 type == MKTAG('c','m','o','v')) {
6956 av_log(c->fc, AV_LOG_ERROR, "Detected moov in a free or hoov atom.\n");
6957 a.type = MKTAG('m','o','o','v');
6960 if (atom.type != MKTAG('r','o','o','t') &&
6961 atom.type != MKTAG('m','o','o','v')) {
6962 if (a.type == MKTAG('t','r','a','k') ||
6963 a.type == MKTAG('m','d','a','t')) {
6964 av_log(c->fc, AV_LOG_ERROR, "Broken file, trak/mdat not at top-level\n");
6971 if (a.size == 1 && total_size + 8 <= atom.size) { /* 64 bit extended size */
6972 a.size = avio_rb64(pb) - 8;
6976 av_log(c->fc, AV_LOG_TRACE, "type:'%s' parent:'%s' sz: %"PRId64" %"PRId64" %"PRId64"\n",
6977 av_fourcc2str(a.type), av_fourcc2str(atom.type), a.size, total_size, atom.size);
6979 a.size = atom.size - total_size + 8;
6984 a.size = FFMIN(a.size, atom.size - total_size);
6986 for (i = 0; mov_default_parse_table[i].type; i++)
6987 if (mov_default_parse_table[i].type == a.type) {
6988 parse = mov_default_parse_table[i].parse;
6992 // container is user data
6993 if (!parse && (atom.type == MKTAG('u','d','t','a') ||
6994 atom.type == MKTAG('i','l','s','t')))
6995 parse = mov_read_udta_string;
6997 // Supports parsing the QuickTime Metadata Keys.
6998 // https://developer.apple.com/library/mac/documentation/QuickTime/QTFF/Metadata/Metadata.html
6999 if (!parse && c->found_hdlr_mdta &&
7000 atom.type == MKTAG('m','e','t','a') &&
7001 a.type == MKTAG('k','e','y','s') &&
7002 c->meta_keys_count == 0) {
7003 parse = mov_read_keys;
7006 if (!parse) { /* skip leaf atoms data */
7007 avio_skip(pb, a.size);
7009 int64_t start_pos = avio_tell(pb);
7011 int err = parse(c, pb, a);
7016 if (c->found_moov && c->found_mdat &&
7017 ((!(pb->seekable & AVIO_SEEKABLE_NORMAL) || c->fc->flags & AVFMT_FLAG_IGNIDX || c->frag_index.complete) ||
7018 start_pos + a.size == avio_size(pb))) {
7019 if (!(pb->seekable & AVIO_SEEKABLE_NORMAL) || c->fc->flags & AVFMT_FLAG_IGNIDX || c->frag_index.complete)
7020 c->next_root_atom = start_pos + a.size;
7024 left = a.size - avio_tell(pb) + start_pos;
7025 if (left > 0) /* skip garbage at atom end */
7026 avio_skip(pb, left);
7027 else if (left < 0) {
7028 av_log(c->fc, AV_LOG_WARNING,
7029 "overread end of atom '%s' by %"PRId64" bytes\n",
7030 av_fourcc2str(a.type), -left);
7031 avio_seek(pb, left, SEEK_CUR);
7035 total_size += a.size;
7038 if (total_size < atom.size && atom.size < 0x7ffff)
7039 avio_skip(pb, atom.size - total_size);
7045 static int mov_probe(const AVProbeData *p)
7050 int moov_offset = -1;
7052 /* check file header */
7055 /* ignore invalid offset */
7056 if ((offset + 8) > (unsigned int)p->buf_size)
7058 tag = AV_RL32(p->buf + offset + 4);
7060 /* check for obvious tags */
7061 case MKTAG('m','o','o','v'):
7062 moov_offset = offset + 4;
7063 case MKTAG('m','d','a','t'):
7064 case MKTAG('p','n','o','t'): /* detect movs with preview pics like ew.mov and april.mov */
7065 case MKTAG('u','d','t','a'): /* Packet Video PVAuthor adds this and a lot of more junk */
7066 case MKTAG('f','t','y','p'):
7067 if (AV_RB32(p->buf+offset) < 8 &&
7068 (AV_RB32(p->buf+offset) != 1 ||
7069 offset + 12 > (unsigned int)p->buf_size ||
7070 AV_RB64(p->buf+offset + 8) == 0)) {
7071 score = FFMAX(score, AVPROBE_SCORE_EXTENSION);
7072 } else if (tag == MKTAG('f','t','y','p') &&
7073 ( AV_RL32(p->buf + offset + 8) == MKTAG('j','p','2',' ')
7074 || AV_RL32(p->buf + offset + 8) == MKTAG('j','p','x',' ')
7076 score = FFMAX(score, 5);
7078 score = AVPROBE_SCORE_MAX;
7080 offset = FFMAX(4, AV_RB32(p->buf+offset)) + offset;
7082 /* those are more common words, so rate then a bit less */
7083 case MKTAG('e','d','i','w'): /* xdcam files have reverted first tags */
7084 case MKTAG('w','i','d','e'):
7085 case MKTAG('f','r','e','e'):
7086 case MKTAG('j','u','n','k'):
7087 case MKTAG('p','i','c','t'):
7088 score = FFMAX(score, AVPROBE_SCORE_MAX - 5);
7089 offset = FFMAX(4, AV_RB32(p->buf+offset)) + offset;
7091 case MKTAG(0x82,0x82,0x7f,0x7d):
7092 case MKTAG('s','k','i','p'):
7093 case MKTAG('u','u','i','d'):
7094 case MKTAG('p','r','f','l'):
7095 /* if we only find those cause probedata is too small at least rate them */
7096 score = FFMAX(score, AVPROBE_SCORE_EXTENSION);
7097 offset = FFMAX(4, AV_RB32(p->buf+offset)) + offset;
7100 offset = FFMAX(4, AV_RB32(p->buf+offset)) + offset;
7103 if (score > AVPROBE_SCORE_MAX - 50 && moov_offset != -1) {
7104 /* moov atom in the header - we should make sure that this is not a
7105 * MOV-packed MPEG-PS */
7106 offset = moov_offset;
7108 while (offset < (p->buf_size - 16)) { /* Sufficient space */
7109 /* We found an actual hdlr atom */
7110 if (AV_RL32(p->buf + offset ) == MKTAG('h','d','l','r') &&
7111 AV_RL32(p->buf + offset + 8) == MKTAG('m','h','l','r') &&
7112 AV_RL32(p->buf + offset + 12) == MKTAG('M','P','E','G')) {
7113 av_log(NULL, AV_LOG_WARNING, "Found media data tag MPEG indicating this is a MOV-packed MPEG-PS.\n");
7114 /* We found a media handler reference atom describing an
7115 * MPEG-PS-in-MOV, return a
7116 * low score to force expanding the probe window until
7117 * mpegps_probe finds what it needs */
7129 // must be done after parsing all trak because there's no order requirement
7130 static void mov_read_chapters(AVFormatContext *s)
7132 MOVContext *mov = s->priv_data;
7134 MOVStreamContext *sc;
7139 for (j = 0; j < mov->nb_chapter_tracks; j++) {
7140 chapter_track = mov->chapter_tracks[j];
7142 for (i = 0; i < s->nb_streams; i++)
7143 if (s->streams[i]->id == chapter_track) {
7148 av_log(s, AV_LOG_ERROR, "Referenced QT chapter track not found\n");
7153 cur_pos = avio_tell(sc->pb);
7155 if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
7156 st->disposition |= AV_DISPOSITION_ATTACHED_PIC | AV_DISPOSITION_TIMED_THUMBNAILS;
7157 if (st->nb_index_entries) {
7158 // Retrieve the first frame, if possible
7159 AVIndexEntry *sample = &st->index_entries[0];
7160 if (avio_seek(sc->pb, sample->pos, SEEK_SET) != sample->pos) {
7161 av_log(s, AV_LOG_ERROR, "Failed to retrieve first frame\n");
7165 if (av_get_packet(sc->pb, &st->attached_pic, sample->size) < 0)
7168 st->attached_pic.stream_index = st->index;
7169 st->attached_pic.flags |= AV_PKT_FLAG_KEY;
7172 st->codecpar->codec_type = AVMEDIA_TYPE_DATA;
7173 st->codecpar->codec_id = AV_CODEC_ID_BIN_DATA;
7174 st->discard = AVDISCARD_ALL;
7175 for (i = 0; i < st->nb_index_entries; i++) {
7176 AVIndexEntry *sample = &st->index_entries[i];
7177 int64_t end = i+1 < st->nb_index_entries ? st->index_entries[i+1].timestamp : st->duration;
7182 if (end < sample->timestamp) {
7183 av_log(s, AV_LOG_WARNING, "ignoring stream duration which is shorter than chapters\n");
7184 end = AV_NOPTS_VALUE;
7187 if (avio_seek(sc->pb, sample->pos, SEEK_SET) != sample->pos) {
7188 av_log(s, AV_LOG_ERROR, "Chapter %d not found in file\n", i);
7192 // the first two bytes are the length of the title
7193 len = avio_rb16(sc->pb);
7194 if (len > sample->size-2)
7196 title_len = 2*len + 1;
7197 if (!(title = av_mallocz(title_len)))
7200 // The samples could theoretically be in any encoding if there's an encd
7201 // atom following, but in practice are only utf-8 or utf-16, distinguished
7202 // instead by the presence of a BOM
7206 ch = avio_rb16(sc->pb);
7208 avio_get_str16be(sc->pb, len, title, title_len);
7209 else if (ch == 0xfffe)
7210 avio_get_str16le(sc->pb, len, title, title_len);
7213 if (len == 1 || len == 2)
7216 avio_get_str(sc->pb, INT_MAX, title + 2, len - 1);
7220 avpriv_new_chapter(s, i, st->time_base, sample->timestamp, end, title);
7225 avio_seek(sc->pb, cur_pos, SEEK_SET);
7229 static int parse_timecode_in_framenum_format(AVFormatContext *s, AVStream *st,
7230 uint32_t value, int flags)
7233 char buf[AV_TIMECODE_STR_SIZE];
7234 AVRational rate = st->avg_frame_rate;
7235 int ret = av_timecode_init(&tc, rate, flags, 0, s);
7238 av_dict_set(&st->metadata, "timecode",
7239 av_timecode_make_string(&tc, buf, value), 0);
7243 static int mov_read_rtmd_track(AVFormatContext *s, AVStream *st)
7245 MOVStreamContext *sc = st->priv_data;
7246 char buf[AV_TIMECODE_STR_SIZE];
7247 int64_t cur_pos = avio_tell(sc->pb);
7248 int hh, mm, ss, ff, drop;
7250 if (!st->nb_index_entries)
7253 avio_seek(sc->pb, st->index_entries->pos, SEEK_SET);
7254 avio_skip(s->pb, 13);
7255 hh = avio_r8(s->pb);
7256 mm = avio_r8(s->pb);
7257 ss = avio_r8(s->pb);
7258 drop = avio_r8(s->pb);
7259 ff = avio_r8(s->pb);
7260 snprintf(buf, AV_TIMECODE_STR_SIZE, "%02d:%02d:%02d%c%02d",
7261 hh, mm, ss, drop ? ';' : ':', ff);
7262 av_dict_set(&st->metadata, "timecode", buf, 0);
7264 avio_seek(sc->pb, cur_pos, SEEK_SET);
7268 static int mov_read_timecode_track(AVFormatContext *s, AVStream *st)
7270 MOVStreamContext *sc = st->priv_data;
7272 int64_t cur_pos = avio_tell(sc->pb);
7275 if (!st->nb_index_entries)
7278 avio_seek(sc->pb, st->index_entries->pos, SEEK_SET);
7279 value = avio_rb32(s->pb);
7281 if (sc->tmcd_flags & 0x0001) flags |= AV_TIMECODE_FLAG_DROPFRAME;
7282 if (sc->tmcd_flags & 0x0002) flags |= AV_TIMECODE_FLAG_24HOURSMAX;
7283 if (sc->tmcd_flags & 0x0004) flags |= AV_TIMECODE_FLAG_ALLOWNEGATIVE;
7285 /* Assume Counter flag is set to 1 in tmcd track (even though it is likely
7286 * not the case) and thus assume "frame number format" instead of QT one.
7287 * No sample with tmcd track can be found with a QT timecode at the moment,
7288 * despite what the tmcd track "suggests" (Counter flag set to 0 means QT
7290 parse_timecode_in_framenum_format(s, st, value, flags);
7292 avio_seek(sc->pb, cur_pos, SEEK_SET);
7296 static void mov_free_encryption_index(MOVEncryptionIndex **index) {
7298 if (!index || !*index) return;
7299 for (i = 0; i < (*index)->nb_encrypted_samples; i++) {
7300 av_encryption_info_free((*index)->encrypted_samples[i]);
7302 av_freep(&(*index)->encrypted_samples);
7303 av_freep(&(*index)->auxiliary_info_sizes);
7304 av_freep(&(*index)->auxiliary_offsets);
7308 static int mov_read_close(AVFormatContext *s)
7310 MOVContext *mov = s->priv_data;
7313 for (i = 0; i < s->nb_streams; i++) {
7314 AVStream *st = s->streams[i];
7315 MOVStreamContext *sc = st->priv_data;
7320 av_freep(&sc->ctts_data);
7321 for (j = 0; j < sc->drefs_count; j++) {
7322 av_freep(&sc->drefs[j].path);
7323 av_freep(&sc->drefs[j].dir);
7325 av_freep(&sc->drefs);
7327 sc->drefs_count = 0;
7329 if (!sc->pb_is_copied)
7330 ff_format_io_close(s, &sc->pb);
7333 av_freep(&sc->chunk_offsets);
7334 av_freep(&sc->stsc_data);
7335 av_freep(&sc->sample_sizes);
7336 av_freep(&sc->keyframes);
7337 av_freep(&sc->stts_data);
7338 av_freep(&sc->sdtp_data);
7339 av_freep(&sc->stps_data);
7340 av_freep(&sc->elst_data);
7341 av_freep(&sc->rap_group);
7342 av_freep(&sc->display_matrix);
7343 av_freep(&sc->index_ranges);
7346 for (j = 0; j < sc->stsd_count; j++)
7347 av_free(sc->extradata[j]);
7348 av_freep(&sc->extradata);
7349 av_freep(&sc->extradata_size);
7351 mov_free_encryption_index(&sc->cenc.encryption_index);
7352 av_encryption_info_free(sc->cenc.default_encrypted_sample);
7353 av_aes_ctr_free(sc->cenc.aes_ctr);
7355 av_freep(&sc->stereo3d);
7356 av_freep(&sc->spherical);
7357 av_freep(&sc->mastering);
7358 av_freep(&sc->coll);
7361 av_freep(&mov->dv_demux);
7362 avformat_free_context(mov->dv_fctx);
7363 mov->dv_fctx = NULL;
7365 if (mov->meta_keys) {
7366 for (i = 1; i < mov->meta_keys_count; i++) {
7367 av_freep(&mov->meta_keys[i]);
7369 av_freep(&mov->meta_keys);
7372 av_freep(&mov->trex_data);
7373 av_freep(&mov->bitrates);
7375 for (i = 0; i < mov->frag_index.nb_items; i++) {
7376 MOVFragmentStreamInfo *frag = mov->frag_index.item[i].stream_info;
7377 for (j = 0; j < mov->frag_index.item[i].nb_stream_info; j++) {
7378 mov_free_encryption_index(&frag[j].encryption_index);
7380 av_freep(&mov->frag_index.item[i].stream_info);
7382 av_freep(&mov->frag_index.item);
7384 av_freep(&mov->aes_decrypt);
7385 av_freep(&mov->chapter_tracks);
7390 static int tmcd_is_referenced(AVFormatContext *s, int tmcd_id)
7394 for (i = 0; i < s->nb_streams; i++) {
7395 AVStream *st = s->streams[i];
7396 MOVStreamContext *sc = st->priv_data;
7398 if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO &&
7399 sc->timecode_track == tmcd_id)
7405 /* look for a tmcd track not referenced by any video track, and export it globally */
7406 static void export_orphan_timecode(AVFormatContext *s)
7410 for (i = 0; i < s->nb_streams; i++) {
7411 AVStream *st = s->streams[i];
7413 if (st->codecpar->codec_tag == MKTAG('t','m','c','d') &&
7414 !tmcd_is_referenced(s, i + 1)) {
7415 AVDictionaryEntry *tcr = av_dict_get(st->metadata, "timecode", NULL, 0);
7417 av_dict_set(&s->metadata, "timecode", tcr->value, 0);
7424 static int read_tfra(MOVContext *mov, AVIOContext *f)
7426 int version, fieldlength, i, j;
7427 int64_t pos = avio_tell(f);
7428 uint32_t size = avio_rb32(f);
7429 unsigned track_id, item_count;
7431 if (avio_rb32(f) != MKBETAG('t', 'f', 'r', 'a')) {
7434 av_log(mov->fc, AV_LOG_VERBOSE, "found tfra\n");
7436 version = avio_r8(f);
7438 track_id = avio_rb32(f);
7439 fieldlength = avio_rb32(f);
7440 item_count = avio_rb32(f);
7441 for (i = 0; i < item_count; i++) {
7442 int64_t time, offset;
7444 MOVFragmentStreamInfo * frag_stream_info;
7447 return AVERROR_INVALIDDATA;
7451 time = avio_rb64(f);
7452 offset = avio_rb64(f);
7454 time = avio_rb32(f);
7455 offset = avio_rb32(f);
7458 // The first sample of each stream in a fragment is always a random
7459 // access sample. So it's entry in the tfra can be used as the
7460 // initial PTS of the fragment.
7461 index = update_frag_index(mov, offset);
7462 frag_stream_info = get_frag_stream_info(&mov->frag_index, index, track_id);
7463 if (frag_stream_info &&
7464 frag_stream_info->first_tfra_pts == AV_NOPTS_VALUE)
7465 frag_stream_info->first_tfra_pts = time;
7467 for (j = 0; j < ((fieldlength >> 4) & 3) + 1; j++)
7469 for (j = 0; j < ((fieldlength >> 2) & 3) + 1; j++)
7471 for (j = 0; j < ((fieldlength >> 0) & 3) + 1; j++)
7475 avio_seek(f, pos + size, SEEK_SET);
7479 static int mov_read_mfra(MOVContext *c, AVIOContext *f)
7481 int64_t stream_size = avio_size(f);
7482 int64_t original_pos = avio_tell(f);
7486 if ((seek_ret = avio_seek(f, stream_size - 4, SEEK_SET)) < 0) {
7490 mfra_size = avio_rb32(f);
7491 if (mfra_size < 0 || mfra_size > stream_size) {
7492 av_log(c->fc, AV_LOG_DEBUG, "doesn't look like mfra (unreasonable size)\n");
7495 if ((seek_ret = avio_seek(f, -mfra_size, SEEK_CUR)) < 0) {
7499 if (avio_rb32(f) != mfra_size) {
7500 av_log(c->fc, AV_LOG_DEBUG, "doesn't look like mfra (size mismatch)\n");
7503 if (avio_rb32(f) != MKBETAG('m', 'f', 'r', 'a')) {
7504 av_log(c->fc, AV_LOG_DEBUG, "doesn't look like mfra (tag mismatch)\n");
7507 av_log(c->fc, AV_LOG_VERBOSE, "stream has mfra\n");
7509 ret = read_tfra(c, f);
7515 seek_ret = avio_seek(f, original_pos, SEEK_SET);
7517 av_log(c->fc, AV_LOG_ERROR,
7518 "failed to seek back after looking for mfra\n");
7524 static int mov_read_header(AVFormatContext *s)
7526 MOVContext *mov = s->priv_data;
7527 AVIOContext *pb = s->pb;
7529 MOVAtom atom = { AV_RL32("root") };
7532 if (mov->decryption_key_len != 0 && mov->decryption_key_len != AES_CTR_KEY_SIZE) {
7533 av_log(s, AV_LOG_ERROR, "Invalid decryption key len %d expected %d\n",
7534 mov->decryption_key_len, AES_CTR_KEY_SIZE);
7535 return AVERROR(EINVAL);
7539 mov->trak_index = -1;
7540 /* .mov and .mp4 aren't streamable anyway (only progressive download if moov is before mdat) */
7541 if (pb->seekable & AVIO_SEEKABLE_NORMAL)
7542 atom.size = avio_size(pb);
7544 atom.size = INT64_MAX;
7546 /* check MOV header */
7548 if (mov->moov_retry)
7549 avio_seek(pb, 0, SEEK_SET);
7550 if ((err = mov_read_default(mov, pb, atom)) < 0) {
7551 av_log(s, AV_LOG_ERROR, "error reading header\n");
7554 } while ((pb->seekable & AVIO_SEEKABLE_NORMAL) && !mov->found_moov && !mov->moov_retry++);
7555 if (!mov->found_moov) {
7556 av_log(s, AV_LOG_ERROR, "moov atom not found\n");
7557 err = AVERROR_INVALIDDATA;
7560 av_log(mov->fc, AV_LOG_TRACE, "on_parse_exit_offset=%"PRId64"\n", avio_tell(pb));
7562 if (pb->seekable & AVIO_SEEKABLE_NORMAL) {
7563 if (mov->nb_chapter_tracks > 0 && !mov->ignore_chapters)
7564 mov_read_chapters(s);
7565 for (i = 0; i < s->nb_streams; i++)
7566 if (s->streams[i]->codecpar->codec_tag == AV_RL32("tmcd")) {
7567 mov_read_timecode_track(s, s->streams[i]);
7568 } else if (s->streams[i]->codecpar->codec_tag == AV_RL32("rtmd")) {
7569 mov_read_rtmd_track(s, s->streams[i]);
7573 /* copy timecode metadata from tmcd tracks to the related video streams */
7574 for (i = 0; i < s->nb_streams; i++) {
7575 AVStream *st = s->streams[i];
7576 MOVStreamContext *sc = st->priv_data;
7577 if (sc->timecode_track > 0) {
7578 AVDictionaryEntry *tcr;
7579 int tmcd_st_id = -1;
7581 for (j = 0; j < s->nb_streams; j++)
7582 if (s->streams[j]->id == sc->timecode_track)
7585 if (tmcd_st_id < 0 || tmcd_st_id == i)
7587 tcr = av_dict_get(s->streams[tmcd_st_id]->metadata, "timecode", NULL, 0);
7589 av_dict_set(&st->metadata, "timecode", tcr->value, 0);
7592 export_orphan_timecode(s);
7594 for (i = 0; i < s->nb_streams; i++) {
7595 AVStream *st = s->streams[i];
7596 MOVStreamContext *sc = st->priv_data;
7597 fix_timescale(mov, sc);
7598 if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO &&
7599 st->codecpar->codec_id == AV_CODEC_ID_AAC) {
7600 st->skip_samples = sc->start_pad;
7602 if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && sc->nb_frames_for_fps > 0 && sc->duration_for_fps > 0)
7603 av_reduce(&st->avg_frame_rate.num, &st->avg_frame_rate.den,
7604 sc->time_scale*(int64_t)sc->nb_frames_for_fps, sc->duration_for_fps, INT_MAX);
7605 if (st->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE) {
7606 if (st->codecpar->width <= 0 || st->codecpar->height <= 0) {
7607 st->codecpar->width = sc->width;
7608 st->codecpar->height = sc->height;
7610 if (st->codecpar->codec_id == AV_CODEC_ID_DVD_SUBTITLE) {
7611 if ((err = mov_rewrite_dvd_sub_extradata(st)) < 0)
7615 if (mov->handbrake_version &&
7616 mov->handbrake_version <= 1000000*0 + 1000*10 + 2 && // 0.10.2
7617 st->codecpar->codec_id == AV_CODEC_ID_MP3) {
7618 av_log(s, AV_LOG_VERBOSE, "Forcing full parsing for mp3 stream\n");
7619 st->need_parsing = AVSTREAM_PARSE_FULL;
7623 if (mov->trex_data) {
7624 for (i = 0; i < s->nb_streams; i++) {
7625 AVStream *st = s->streams[i];
7626 MOVStreamContext *sc = st->priv_data;
7627 if (st->duration > 0) {
7628 if (sc->data_size > INT64_MAX / sc->time_scale / 8) {
7629 av_log(s, AV_LOG_ERROR, "Overflow during bit rate calculation %"PRId64" * 8 * %d\n",
7630 sc->data_size, sc->time_scale);
7631 err = AVERROR_INVALIDDATA;
7634 st->codecpar->bit_rate = sc->data_size * 8 * sc->time_scale / st->duration;
7639 if (mov->use_mfra_for > 0) {
7640 for (i = 0; i < s->nb_streams; i++) {
7641 AVStream *st = s->streams[i];
7642 MOVStreamContext *sc = st->priv_data;
7643 if (sc->duration_for_fps > 0) {
7644 if (sc->data_size > INT64_MAX / sc->time_scale / 8) {
7645 av_log(s, AV_LOG_ERROR, "Overflow during bit rate calculation %"PRId64" * 8 * %d\n",
7646 sc->data_size, sc->time_scale);
7647 err = AVERROR_INVALIDDATA;
7650 st->codecpar->bit_rate = sc->data_size * 8 * sc->time_scale /
7651 sc->duration_for_fps;
7656 for (i = 0; i < mov->bitrates_count && i < s->nb_streams; i++) {
7657 if (mov->bitrates[i]) {
7658 s->streams[i]->codecpar->bit_rate = mov->bitrates[i];
7662 ff_rfps_calculate(s);
7664 for (i = 0; i < s->nb_streams; i++) {
7665 AVStream *st = s->streams[i];
7666 MOVStreamContext *sc = st->priv_data;
7668 switch (st->codecpar->codec_type) {
7669 case AVMEDIA_TYPE_AUDIO:
7670 err = ff_replaygain_export(st, s->metadata);
7674 case AVMEDIA_TYPE_VIDEO:
7675 if (sc->display_matrix) {
7676 err = av_stream_add_side_data(st, AV_PKT_DATA_DISPLAYMATRIX, (uint8_t*)sc->display_matrix,
7677 sizeof(int32_t) * 9);
7681 sc->display_matrix = NULL;
7684 err = av_stream_add_side_data(st, AV_PKT_DATA_STEREO3D,
7685 (uint8_t *)sc->stereo3d,
7686 sizeof(*sc->stereo3d));
7690 sc->stereo3d = NULL;
7692 if (sc->spherical) {
7693 err = av_stream_add_side_data(st, AV_PKT_DATA_SPHERICAL,
7694 (uint8_t *)sc->spherical,
7695 sc->spherical_size);
7699 sc->spherical = NULL;
7701 if (sc->mastering) {
7702 err = av_stream_add_side_data(st, AV_PKT_DATA_MASTERING_DISPLAY_METADATA,
7703 (uint8_t *)sc->mastering,
7704 sizeof(*sc->mastering));
7708 sc->mastering = NULL;
7711 err = av_stream_add_side_data(st, AV_PKT_DATA_CONTENT_LIGHT_LEVEL,
7712 (uint8_t *)sc->coll,
7722 ff_configure_buffers_for_index(s, AV_TIME_BASE);
7724 for (i = 0; i < mov->frag_index.nb_items; i++)
7725 if (mov->frag_index.item[i].moof_offset <= mov->fragment.moof_offset)
7726 mov->frag_index.item[i].headers_read = 1;
7734 static AVIndexEntry *mov_find_next_sample(AVFormatContext *s, AVStream **st)
7736 AVIndexEntry *sample = NULL;
7737 int64_t best_dts = INT64_MAX;
7739 for (i = 0; i < s->nb_streams; i++) {
7740 AVStream *avst = s->streams[i];
7741 MOVStreamContext *msc = avst->priv_data;
7742 if (msc->pb && msc->current_sample < avst->nb_index_entries) {
7743 AVIndexEntry *current_sample = &avst->index_entries[msc->current_sample];
7744 int64_t dts = av_rescale(current_sample->timestamp, AV_TIME_BASE, msc->time_scale);
7745 av_log(s, AV_LOG_TRACE, "stream %d, sample %d, dts %"PRId64"\n", i, msc->current_sample, dts);
7746 if (!sample || (!(s->pb->seekable & AVIO_SEEKABLE_NORMAL) && current_sample->pos < sample->pos) ||
7747 ((s->pb->seekable & AVIO_SEEKABLE_NORMAL) &&
7748 ((msc->pb != s->pb && dts < best_dts) || (msc->pb == s->pb && dts != AV_NOPTS_VALUE &&
7749 ((FFABS(best_dts - dts) <= AV_TIME_BASE && current_sample->pos < sample->pos) ||
7750 (FFABS(best_dts - dts) > AV_TIME_BASE && dts < best_dts)))))) {
7751 sample = current_sample;
7760 static int should_retry(AVIOContext *pb, int error_code) {
7761 if (error_code == AVERROR_EOF || avio_feof(pb))
7767 static int mov_switch_root(AVFormatContext *s, int64_t target, int index)
7770 MOVContext *mov = s->priv_data;
7772 if (index >= 0 && index < mov->frag_index.nb_items)
7773 target = mov->frag_index.item[index].moof_offset;
7774 if (avio_seek(s->pb, target, SEEK_SET) != target) {
7775 av_log(mov->fc, AV_LOG_ERROR, "root atom offset 0x%"PRIx64": partial file\n", target);
7776 return AVERROR_INVALIDDATA;
7779 mov->next_root_atom = 0;
7780 if (index < 0 || index >= mov->frag_index.nb_items)
7781 index = search_frag_moof_offset(&mov->frag_index, target);
7782 if (index < mov->frag_index.nb_items &&
7783 mov->frag_index.item[index].moof_offset == target) {
7784 if (index + 1 < mov->frag_index.nb_items)
7785 mov->next_root_atom = mov->frag_index.item[index + 1].moof_offset;
7786 if (mov->frag_index.item[index].headers_read)
7788 mov->frag_index.item[index].headers_read = 1;
7791 mov->found_mdat = 0;
7793 ret = mov_read_default(mov, s->pb, (MOVAtom){ AV_RL32("root"), INT64_MAX });
7796 if (avio_feof(s->pb))
7798 av_log(s, AV_LOG_TRACE, "read fragments, offset 0x%"PRIx64"\n", avio_tell(s->pb));
7803 static int mov_change_extradata(MOVStreamContext *sc, AVPacket *pkt)
7805 uint8_t *side, *extradata;
7808 /* Save the current index. */
7809 sc->last_stsd_index = sc->stsc_data[sc->stsc_index].id - 1;
7811 /* Notify the decoder that extradata changed. */
7812 extradata_size = sc->extradata_size[sc->last_stsd_index];
7813 extradata = sc->extradata[sc->last_stsd_index];
7814 if (extradata_size > 0 && extradata) {
7815 side = av_packet_new_side_data(pkt,
7816 AV_PKT_DATA_NEW_EXTRADATA,
7819 return AVERROR(ENOMEM);
7820 memcpy(side, extradata, extradata_size);
7826 static int get_eia608_packet(AVIOContext *pb, AVPacket *pkt, int size)
7831 return AVERROR_INVALIDDATA;
7832 new_size = ((size - 8) / 2) * 3;
7833 ret = av_new_packet(pkt, new_size);
7838 for (int j = 0; j < new_size; j += 3) {
7839 pkt->data[j] = 0xFC;
7840 pkt->data[j+1] = avio_r8(pb);
7841 pkt->data[j+2] = avio_r8(pb);
7847 static int mov_read_packet(AVFormatContext *s, AVPacket *pkt)
7849 MOVContext *mov = s->priv_data;
7850 MOVStreamContext *sc;
7851 AVIndexEntry *sample;
7852 AVStream *st = NULL;
7853 int64_t current_index;
7857 sample = mov_find_next_sample(s, &st);
7858 if (!sample || (mov->next_root_atom && sample->pos > mov->next_root_atom)) {
7859 if (!mov->next_root_atom)
7861 if ((ret = mov_switch_root(s, mov->next_root_atom, -1)) < 0)
7866 /* must be done just before reading, to avoid infinite loop on sample */
7867 current_index = sc->current_index;
7868 mov_current_sample_inc(sc);
7870 if (mov->next_root_atom) {
7871 sample->pos = FFMIN(sample->pos, mov->next_root_atom);
7872 sample->size = FFMIN(sample->size, (mov->next_root_atom - sample->pos));
7875 if (st->discard != AVDISCARD_ALL) {
7876 int64_t ret64 = avio_seek(sc->pb, sample->pos, SEEK_SET);
7877 if (ret64 != sample->pos) {
7878 av_log(mov->fc, AV_LOG_ERROR, "stream %d, offset 0x%"PRIx64": partial file\n",
7879 sc->ffindex, sample->pos);
7880 if (should_retry(sc->pb, ret64)) {
7881 mov_current_sample_dec(sc);
7883 return AVERROR_INVALIDDATA;
7886 if (st->discard == AVDISCARD_NONKEY && !(sample->flags & AVINDEX_KEYFRAME)) {
7887 av_log(mov->fc, AV_LOG_DEBUG, "Nonkey frame from stream %d discarded due to AVDISCARD_NONKEY\n", sc->ffindex);
7891 if (st->codecpar->codec_id == AV_CODEC_ID_EIA_608 && sample->size > 8)
7892 ret = get_eia608_packet(sc->pb, pkt, sample->size);
7894 ret = av_get_packet(sc->pb, pkt, sample->size);
7896 if (should_retry(sc->pb, ret)) {
7897 mov_current_sample_dec(sc);
7901 #if CONFIG_DV_DEMUXER
7902 if (mov->dv_demux && sc->dv_audio_container) {
7903 AVBufferRef *buf = pkt->buf;
7904 ret = avpriv_dv_produce_packet(mov->dv_demux, pkt, pkt->data, pkt->size, pkt->pos);
7906 av_packet_unref(pkt);
7909 ret = avpriv_dv_get_packet(mov->dv_demux, pkt);
7914 if (sc->has_palette) {
7917 pal = av_packet_new_side_data(pkt, AV_PKT_DATA_PALETTE, AVPALETTE_SIZE);
7919 av_log(mov->fc, AV_LOG_ERROR, "Cannot append palette to packet\n");
7921 memcpy(pal, sc->palette, AVPALETTE_SIZE);
7922 sc->has_palette = 0;
7925 if (st->codecpar->codec_id == AV_CODEC_ID_MP3 && !st->need_parsing && pkt->size > 4) {
7926 if (ff_mpa_check_header(AV_RB32(pkt->data)) < 0)
7927 st->need_parsing = AVSTREAM_PARSE_FULL;
7931 pkt->stream_index = sc->ffindex;
7932 pkt->dts = sample->timestamp;
7933 if (sample->flags & AVINDEX_DISCARD_FRAME) {
7934 pkt->flags |= AV_PKT_FLAG_DISCARD;
7936 if (sc->ctts_data && sc->ctts_index < sc->ctts_count) {
7937 pkt->pts = pkt->dts + sc->dts_shift + sc->ctts_data[sc->ctts_index].duration;
7938 /* update ctts context */
7940 if (sc->ctts_index < sc->ctts_count &&
7941 sc->ctts_data[sc->ctts_index].count == sc->ctts_sample) {
7943 sc->ctts_sample = 0;
7946 int64_t next_dts = (sc->current_sample < st->nb_index_entries) ?
7947 st->index_entries[sc->current_sample].timestamp : st->duration;
7949 if (next_dts >= pkt->dts)
7950 pkt->duration = next_dts - pkt->dts;
7951 pkt->pts = pkt->dts;
7953 if (st->discard == AVDISCARD_ALL)
7955 if (sc->sdtp_data && sc->current_sample <= sc->sdtp_count) {
7956 uint8_t sample_flags = sc->sdtp_data[sc->current_sample - 1];
7957 uint8_t sample_is_depended_on = (sample_flags >> 2) & 0x3;
7958 pkt->flags |= sample_is_depended_on == MOV_SAMPLE_DEPENDENCY_NO ? AV_PKT_FLAG_DISPOSABLE : 0;
7960 pkt->flags |= sample->flags & AVINDEX_KEYFRAME ? AV_PKT_FLAG_KEY : 0;
7961 pkt->pos = sample->pos;
7963 /* Multiple stsd handling. */
7964 if (sc->stsc_data) {
7965 /* Keep track of the stsc index for the given sample, then check
7966 * if the stsd index is different from the last used one. */
7968 if (mov_stsc_index_valid(sc->stsc_index, sc->stsc_count) &&
7969 mov_get_stsc_samples(sc, sc->stsc_index) == sc->stsc_sample) {
7971 sc->stsc_sample = 0;
7972 /* Do not check indexes after a switch. */
7973 } else if (sc->stsc_data[sc->stsc_index].id > 0 &&
7974 sc->stsc_data[sc->stsc_index].id - 1 < sc->stsd_count &&
7975 sc->stsc_data[sc->stsc_index].id - 1 != sc->last_stsd_index) {
7976 ret = mov_change_extradata(sc, pkt);
7983 aax_filter(pkt->data, pkt->size, mov);
7985 ret = cenc_filter(mov, st, sc, pkt, current_index);
7993 static int mov_seek_fragment(AVFormatContext *s, AVStream *st, int64_t timestamp)
7995 MOVContext *mov = s->priv_data;
7998 if (!mov->frag_index.complete)
8001 index = search_frag_timestamp(&mov->frag_index, st, timestamp);
8004 if (!mov->frag_index.item[index].headers_read)
8005 return mov_switch_root(s, -1, index);
8006 if (index + 1 < mov->frag_index.nb_items)
8007 mov->next_root_atom = mov->frag_index.item[index + 1].moof_offset;
8012 static int mov_seek_stream(AVFormatContext *s, AVStream *st, int64_t timestamp, int flags)
8014 MOVStreamContext *sc = st->priv_data;
8015 int sample, time_sample, ret;
8018 // Here we consider timestamp to be PTS, hence try to offset it so that we
8019 // can search over the DTS timeline.
8020 timestamp -= (sc->min_corrected_pts + sc->dts_shift);
8022 ret = mov_seek_fragment(s, st, timestamp);
8026 sample = av_index_search_timestamp(st, timestamp, flags);
8027 av_log(s, AV_LOG_TRACE, "stream %d, timestamp %"PRId64", sample %d\n", st->index, timestamp, sample);
8028 if (sample < 0 && st->nb_index_entries && timestamp < st->index_entries[0].timestamp)
8030 if (sample < 0) /* not sure what to do */
8031 return AVERROR_INVALIDDATA;
8032 mov_current_sample_set(sc, sample);
8033 av_log(s, AV_LOG_TRACE, "stream %d, found sample %d\n", st->index, sc->current_sample);
8034 /* adjust ctts index */
8035 if (sc->ctts_data) {
8037 for (i = 0; i < sc->ctts_count; i++) {
8038 int next = time_sample + sc->ctts_data[i].count;
8039 if (next > sc->current_sample) {
8041 sc->ctts_sample = sc->current_sample - time_sample;
8048 /* adjust stsd index */
8049 if (sc->chunk_count) {
8051 for (i = 0; i < sc->stsc_count; i++) {
8052 int64_t next = time_sample + mov_get_stsc_samples(sc, i);
8053 if (next > sc->current_sample) {
8055 sc->stsc_sample = sc->current_sample - time_sample;
8058 av_assert0(next == (int)next);
8066 static int mov_read_seek(AVFormatContext *s, int stream_index, int64_t sample_time, int flags)
8068 MOVContext *mc = s->priv_data;
8073 if (stream_index >= s->nb_streams)
8074 return AVERROR_INVALIDDATA;
8076 st = s->streams[stream_index];
8077 sample = mov_seek_stream(s, st, sample_time, flags);
8081 if (mc->seek_individually) {
8082 /* adjust seek timestamp to found sample timestamp */
8083 int64_t seek_timestamp = st->index_entries[sample].timestamp;
8085 for (i = 0; i < s->nb_streams; i++) {
8087 MOVStreamContext *sc = s->streams[i]->priv_data;
8089 st->skip_samples = (sample_time <= 0) ? sc->start_pad : 0;
8091 if (stream_index == i)
8094 timestamp = av_rescale_q(seek_timestamp, s->streams[stream_index]->time_base, st->time_base);
8095 mov_seek_stream(s, st, timestamp, flags);
8098 for (i = 0; i < s->nb_streams; i++) {
8099 MOVStreamContext *sc;
8102 mov_current_sample_set(sc, 0);
8105 MOVStreamContext *sc;
8106 AVIndexEntry *entry = mov_find_next_sample(s, &st);
8108 return AVERROR_INVALIDDATA;
8110 if (sc->ffindex == stream_index && sc->current_sample == sample)
8112 mov_current_sample_inc(sc);
8118 #define OFFSET(x) offsetof(MOVContext, x)
8119 #define FLAGS AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_DECODING_PARAM
8120 static const AVOption mov_options[] = {
8121 {"use_absolute_path",
8122 "allow using absolute path when opening alias, this is a possible security issue",
8123 OFFSET(use_absolute_path), AV_OPT_TYPE_BOOL, {.i64 = 0},
8125 {"seek_streams_individually",
8126 "Seek each stream individually to the closest point",
8127 OFFSET(seek_individually), AV_OPT_TYPE_BOOL, { .i64 = 1 },
8129 {"ignore_editlist", "Ignore the edit list atom.", OFFSET(ignore_editlist), AV_OPT_TYPE_BOOL, {.i64 = 0},
8131 {"advanced_editlist",
8132 "Modify the AVIndex according to the editlists. Use this option to decode in the order specified by the edits.",
8133 OFFSET(advanced_editlist), AV_OPT_TYPE_BOOL, {.i64 = 1},
8135 {"ignore_chapters", "", OFFSET(ignore_chapters), AV_OPT_TYPE_BOOL, {.i64 = 0},
8138 "use mfra for fragment timestamps",
8139 OFFSET(use_mfra_for), AV_OPT_TYPE_INT, {.i64 = FF_MOV_FLAG_MFRA_AUTO},
8140 -1, FF_MOV_FLAG_MFRA_PTS, FLAGS,
8142 {"auto", "auto", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_MFRA_AUTO}, 0, 0,
8143 FLAGS, "use_mfra_for" },
8144 {"dts", "dts", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_MFRA_DTS}, 0, 0,
8145 FLAGS, "use_mfra_for" },
8146 {"pts", "pts", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_MFRA_PTS}, 0, 0,
8147 FLAGS, "use_mfra_for" },
8148 { "export_all", "Export unrecognized metadata entries", OFFSET(export_all),
8149 AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, .flags = FLAGS },
8150 { "export_xmp", "Export full XMP metadata", OFFSET(export_xmp),
8151 AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, .flags = FLAGS },
8152 { "activation_bytes", "Secret bytes for Audible AAX files", OFFSET(activation_bytes),
8153 AV_OPT_TYPE_BINARY, .flags = AV_OPT_FLAG_DECODING_PARAM },
8154 { "audible_fixed_key", // extracted from libAAX_SDK.so and AAXSDKWin.dll files!
8155 "Fixed key used for handling Audible AAX files", OFFSET(audible_fixed_key),
8156 AV_OPT_TYPE_BINARY, {.str="77214d4b196a87cd520045fd20a51d67"},
8157 .flags = AV_OPT_FLAG_DECODING_PARAM },
8158 { "decryption_key", "The media decryption key (hex)", OFFSET(decryption_key), AV_OPT_TYPE_BINARY, .flags = AV_OPT_FLAG_DECODING_PARAM },
8159 { "enable_drefs", "Enable external track support.", OFFSET(enable_drefs), AV_OPT_TYPE_BOOL,
8160 {.i64 = 0}, 0, 1, FLAGS },
8165 static const AVClass mov_class = {
8166 .class_name = "mov,mp4,m4a,3gp,3g2,mj2",
8167 .item_name = av_default_item_name,
8168 .option = mov_options,
8169 .version = LIBAVUTIL_VERSION_INT,
8172 AVInputFormat ff_mov_demuxer = {
8173 .name = "mov,mp4,m4a,3gp,3g2,mj2",
8174 .long_name = NULL_IF_CONFIG_SMALL("QuickTime / MOV"),
8175 .priv_class = &mov_class,
8176 .priv_data_size = sizeof(MOVContext),
8177 .extensions = "mov,mp4,m4a,3gp,3g2,mj2,psp,m4b,ism,ismv,isma,f4v",
8178 .read_probe = mov_probe,
8179 .read_header = mov_read_header,
8180 .read_packet = mov_read_packet,
8181 .read_close = mov_read_close,
8182 .read_seek = mov_read_seek,
8183 .flags = AVFMT_NO_BYTE_SEEK | AVFMT_SEEK_TO_PTS,