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 AVFormatContext 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]->internal->display_aspect_ratio.num = num;
1771 c->fc->streams[c->fc->nb_streams-1]->internal->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->internal->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->internal->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->internal->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->internal->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 stream_size = avio_size(pb);
5021 int64_t offset = avio_tell(pb) + atom.size, pts, timestamp;
5022 uint8_t version, is_complete;
5023 unsigned i, j, track_id, item_count;
5024 AVStream *st = NULL;
5025 AVStream *ref_st = NULL;
5026 MOVStreamContext *sc, *ref_sc = NULL;
5027 AVRational timescale;
5029 version = avio_r8(pb);
5031 avpriv_request_sample(c->fc, "sidx version %u", version);
5035 avio_rb24(pb); // flags
5037 track_id = avio_rb32(pb); // Reference ID
5038 for (i = 0; i < c->fc->nb_streams; i++) {
5039 if (c->fc->streams[i]->id == track_id) {
5040 st = c->fc->streams[i];
5045 av_log(c->fc, AV_LOG_WARNING, "could not find corresponding track id %d\n", track_id);
5051 timescale = av_make_q(1, avio_rb32(pb));
5053 if (timescale.den <= 0) {
5054 av_log(c->fc, AV_LOG_ERROR, "Invalid sidx timescale 1/%d\n", timescale.den);
5055 return AVERROR_INVALIDDATA;
5059 pts = avio_rb32(pb);
5060 offset += avio_rb32(pb);
5062 pts = avio_rb64(pb);
5063 offset += avio_rb64(pb);
5066 avio_rb16(pb); // reserved
5068 item_count = avio_rb16(pb);
5070 for (i = 0; i < item_count; i++) {
5072 MOVFragmentStreamInfo * frag_stream_info;
5073 uint32_t size = avio_rb32(pb);
5074 uint32_t duration = avio_rb32(pb);
5075 if (size & 0x80000000) {
5076 avpriv_request_sample(c->fc, "sidx reference_type 1");
5077 return AVERROR_PATCHWELCOME;
5079 avio_rb32(pb); // sap_flags
5080 timestamp = av_rescale_q(pts, timescale, st->time_base);
5082 index = update_frag_index(c, offset);
5083 frag_stream_info = get_frag_stream_info(&c->frag_index, index, track_id);
5084 if (frag_stream_info)
5085 frag_stream_info->sidx_pts = timestamp;
5091 st->duration = sc->track_end = pts;
5095 // See if the remaining bytes are just an mfra which we can ignore.
5096 is_complete = offset == stream_size;
5097 if (!is_complete && (pb->seekable & AVIO_SEEKABLE_NORMAL)) {
5099 int64_t original_pos = avio_tell(pb);
5100 if (!c->have_read_mfra_size) {
5101 if ((ret = avio_seek(pb, stream_size - 4, SEEK_SET)) < 0)
5103 c->mfra_size = avio_rb32(pb);
5104 c->have_read_mfra_size = 1;
5105 if ((ret = avio_seek(pb, original_pos, SEEK_SET)) < 0)
5108 if (offset + c->mfra_size == stream_size)
5113 // Find first entry in fragment index that came from an sidx.
5114 // This will pretty much always be the first entry.
5115 for (i = 0; i < c->frag_index.nb_items; i++) {
5116 MOVFragmentIndexItem * item = &c->frag_index.item[i];
5117 for (j = 0; ref_st == NULL && j < item->nb_stream_info; j++) {
5118 MOVFragmentStreamInfo * si;
5119 si = &item->stream_info[j];
5120 if (si->sidx_pts != AV_NOPTS_VALUE) {
5121 ref_st = c->fc->streams[j];
5122 ref_sc = ref_st->priv_data;
5127 if (ref_st) for (i = 0; i < c->fc->nb_streams; i++) {
5128 st = c->fc->streams[i];
5130 if (!sc->has_sidx) {
5131 st->duration = sc->track_end = av_rescale(ref_st->duration, sc->time_scale, ref_sc->time_scale);
5135 c->frag_index.complete = 1;
5141 /* this atom should be null (from specs), but some buggy files put the 'moov' atom inside it... */
5142 /* like the files created with Adobe Premiere 5.0, for samples see */
5143 /* http://graphics.tudelft.nl/~wouter/publications/soundtests/ */
5144 static int mov_read_wide(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5149 return 0; /* continue */
5150 if (avio_rb32(pb) != 0) { /* 0 sized mdat atom... use the 'wide' atom size */
5151 avio_skip(pb, atom.size - 4);
5154 atom.type = avio_rl32(pb);
5156 if (atom.type != MKTAG('m','d','a','t')) {
5157 avio_skip(pb, atom.size);
5160 err = mov_read_mdat(c, pb, atom);
5164 static int mov_read_cmov(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5169 uint8_t *moov_data; /* uncompressed data */
5170 long cmov_len, moov_len;
5173 avio_rb32(pb); /* dcom atom */
5174 if (avio_rl32(pb) != MKTAG('d','c','o','m'))
5175 return AVERROR_INVALIDDATA;
5176 if (avio_rl32(pb) != MKTAG('z','l','i','b')) {
5177 av_log(c->fc, AV_LOG_ERROR, "unknown compression for cmov atom !\n");
5178 return AVERROR_INVALIDDATA;
5180 avio_rb32(pb); /* cmvd atom */
5181 if (avio_rl32(pb) != MKTAG('c','m','v','d'))
5182 return AVERROR_INVALIDDATA;
5183 moov_len = avio_rb32(pb); /* uncompressed size */
5184 cmov_len = atom.size - 6 * 4;
5186 cmov_data = av_malloc(cmov_len);
5188 return AVERROR(ENOMEM);
5189 moov_data = av_malloc(moov_len);
5192 return AVERROR(ENOMEM);
5194 ret = ffio_read_size(pb, cmov_data, cmov_len);
5196 goto free_and_return;
5198 ret = AVERROR_INVALIDDATA;
5199 if (uncompress (moov_data, (uLongf *) &moov_len, (const Bytef *)cmov_data, cmov_len) != Z_OK)
5200 goto free_and_return;
5201 if (ffio_init_context(&ctx, moov_data, moov_len, 0, NULL, NULL, NULL, NULL) != 0)
5202 goto free_and_return;
5203 ctx.seekable = AVIO_SEEKABLE_NORMAL;
5204 atom.type = MKTAG('m','o','o','v');
5205 atom.size = moov_len;
5206 ret = mov_read_default(c, &ctx, atom);
5212 av_log(c->fc, AV_LOG_ERROR, "this file requires zlib support compiled in\n");
5213 return AVERROR(ENOSYS);
5217 /* edit list atom */
5218 static int mov_read_elst(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5220 MOVStreamContext *sc;
5221 int i, edit_count, version;
5222 int64_t elst_entry_size;
5224 if (c->fc->nb_streams < 1 || c->ignore_editlist)
5226 sc = c->fc->streams[c->fc->nb_streams-1]->priv_data;
5228 version = avio_r8(pb); /* version */
5229 avio_rb24(pb); /* flags */
5230 edit_count = avio_rb32(pb); /* entries */
5233 elst_entry_size = version == 1 ? 20 : 12;
5234 if (atom.size != edit_count * elst_entry_size) {
5235 if (c->fc->strict_std_compliance >= FF_COMPLIANCE_STRICT) {
5236 av_log(c->fc, AV_LOG_ERROR, "Invalid edit list entry_count: %d for elst atom of size: %"PRId64" bytes.\n",
5237 edit_count, atom.size + 8);
5238 return AVERROR_INVALIDDATA;
5240 edit_count = atom.size / elst_entry_size;
5241 if (edit_count * elst_entry_size != atom.size) {
5242 av_log(c->fc, AV_LOG_WARNING, "ELST atom of %"PRId64" bytes, bigger than %d entries.\n", atom.size, edit_count);
5250 av_log(c->fc, AV_LOG_WARNING, "Duplicated ELST atom\n");
5251 av_free(sc->elst_data);
5253 sc->elst_data = av_malloc_array(edit_count, sizeof(*sc->elst_data));
5255 return AVERROR(ENOMEM);
5257 av_log(c->fc, AV_LOG_TRACE, "track[%u].edit_count = %i\n", c->fc->nb_streams - 1, edit_count);
5258 for (i = 0; i < edit_count && atom.size > 0 && !pb->eof_reached; i++) {
5259 MOVElst *e = &sc->elst_data[i];
5262 e->duration = avio_rb64(pb);
5263 e->time = avio_rb64(pb);
5266 e->duration = avio_rb32(pb); /* segment duration */
5267 e->time = (int32_t)avio_rb32(pb); /* media time */
5270 e->rate = avio_rb32(pb) / 65536.0;
5272 av_log(c->fc, AV_LOG_TRACE, "duration=%"PRId64" time=%"PRId64" rate=%f\n",
5273 e->duration, e->time, e->rate);
5275 if (e->time < 0 && e->time != -1 &&
5276 c->fc->strict_std_compliance >= FF_COMPLIANCE_STRICT) {
5277 av_log(c->fc, AV_LOG_ERROR, "Track %d, edit %d: Invalid edit list media time=%"PRId64"\n",
5278 c->fc->nb_streams-1, i, e->time);
5279 return AVERROR_INVALIDDATA;
5287 static int mov_read_tmcd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5289 MOVStreamContext *sc;
5291 if (c->fc->nb_streams < 1)
5292 return AVERROR_INVALIDDATA;
5293 sc = c->fc->streams[c->fc->nb_streams - 1]->priv_data;
5294 sc->timecode_track = avio_rb32(pb);
5298 static int mov_read_av1c(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5303 if (c->fc->nb_streams < 1)
5305 st = c->fc->streams[c->fc->nb_streams - 1];
5307 if (atom.size < 4) {
5308 av_log(c->fc, AV_LOG_ERROR, "Empty AV1 Codec Configuration Box\n");
5309 return AVERROR_INVALIDDATA;
5312 /* For now, propagate only the OBUs, if any. Once libavcodec is
5313 updated to handle isobmff style extradata this can be removed. */
5319 ret = ff_get_extradata(c->fc, st->codecpar, pb, atom.size - 4);
5326 static int mov_read_vpcc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5329 int version, color_range, color_primaries, color_trc, color_space;
5331 if (c->fc->nb_streams < 1)
5333 st = c->fc->streams[c->fc->nb_streams - 1];
5335 if (atom.size < 5) {
5336 av_log(c->fc, AV_LOG_ERROR, "Empty VP Codec Configuration box\n");
5337 return AVERROR_INVALIDDATA;
5340 version = avio_r8(pb);
5342 av_log(c->fc, AV_LOG_WARNING, "Unsupported VP Codec Configuration box version %d\n", version);
5345 avio_skip(pb, 3); /* flags */
5347 avio_skip(pb, 2); /* profile + level */
5348 color_range = avio_r8(pb); /* bitDepth, chromaSubsampling, videoFullRangeFlag */
5349 color_primaries = avio_r8(pb);
5350 color_trc = avio_r8(pb);
5351 color_space = avio_r8(pb);
5352 if (avio_rb16(pb)) /* codecIntializationDataSize */
5353 return AVERROR_INVALIDDATA;
5355 if (!av_color_primaries_name(color_primaries))
5356 color_primaries = AVCOL_PRI_UNSPECIFIED;
5357 if (!av_color_transfer_name(color_trc))
5358 color_trc = AVCOL_TRC_UNSPECIFIED;
5359 if (!av_color_space_name(color_space))
5360 color_space = AVCOL_SPC_UNSPECIFIED;
5362 st->codecpar->color_range = (color_range & 1) ? AVCOL_RANGE_JPEG : AVCOL_RANGE_MPEG;
5363 st->codecpar->color_primaries = color_primaries;
5364 st->codecpar->color_trc = color_trc;
5365 st->codecpar->color_space = color_space;
5370 static int mov_read_smdm(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5372 MOVStreamContext *sc;
5375 if (c->fc->nb_streams < 1)
5376 return AVERROR_INVALIDDATA;
5378 sc = c->fc->streams[c->fc->nb_streams - 1]->priv_data;
5380 if (atom.size < 5) {
5381 av_log(c->fc, AV_LOG_ERROR, "Empty Mastering Display Metadata box\n");
5382 return AVERROR_INVALIDDATA;
5385 version = avio_r8(pb);
5387 av_log(c->fc, AV_LOG_WARNING, "Unsupported Mastering Display Metadata box version %d\n", version);
5390 avio_skip(pb, 3); /* flags */
5392 sc->mastering = av_mastering_display_metadata_alloc();
5394 return AVERROR(ENOMEM);
5396 for (i = 0; i < 3; i++) {
5397 sc->mastering->display_primaries[i][0] = av_make_q(avio_rb16(pb), 1 << 16);
5398 sc->mastering->display_primaries[i][1] = av_make_q(avio_rb16(pb), 1 << 16);
5400 sc->mastering->white_point[0] = av_make_q(avio_rb16(pb), 1 << 16);
5401 sc->mastering->white_point[1] = av_make_q(avio_rb16(pb), 1 << 16);
5403 sc->mastering->max_luminance = av_make_q(avio_rb32(pb), 1 << 8);
5404 sc->mastering->min_luminance = av_make_q(avio_rb32(pb), 1 << 14);
5406 sc->mastering->has_primaries = 1;
5407 sc->mastering->has_luminance = 1;
5412 static int mov_read_mdcv(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5414 MOVStreamContext *sc;
5415 const int mapping[3] = {1, 2, 0};
5416 const int chroma_den = 50000;
5417 const int luma_den = 10000;
5420 if (c->fc->nb_streams < 1)
5421 return AVERROR_INVALIDDATA;
5423 sc = c->fc->streams[c->fc->nb_streams - 1]->priv_data;
5425 if (atom.size < 24) {
5426 av_log(c->fc, AV_LOG_ERROR, "Invalid Mastering Display Color Volume box\n");
5427 return AVERROR_INVALIDDATA;
5430 sc->mastering = av_mastering_display_metadata_alloc();
5432 return AVERROR(ENOMEM);
5434 for (i = 0; i < 3; i++) {
5435 const int j = mapping[i];
5436 sc->mastering->display_primaries[j][0] = av_make_q(avio_rb16(pb), chroma_den);
5437 sc->mastering->display_primaries[j][1] = av_make_q(avio_rb16(pb), chroma_den);
5439 sc->mastering->white_point[0] = av_make_q(avio_rb16(pb), chroma_den);
5440 sc->mastering->white_point[1] = av_make_q(avio_rb16(pb), chroma_den);
5442 sc->mastering->max_luminance = av_make_q(avio_rb32(pb), luma_den);
5443 sc->mastering->min_luminance = av_make_q(avio_rb32(pb), luma_den);
5445 sc->mastering->has_luminance = 1;
5446 sc->mastering->has_primaries = 1;
5451 static int mov_read_coll(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5453 MOVStreamContext *sc;
5456 if (c->fc->nb_streams < 1)
5457 return AVERROR_INVALIDDATA;
5459 sc = c->fc->streams[c->fc->nb_streams - 1]->priv_data;
5461 if (atom.size < 5) {
5462 av_log(c->fc, AV_LOG_ERROR, "Empty Content Light Level box\n");
5463 return AVERROR_INVALIDDATA;
5466 version = avio_r8(pb);
5468 av_log(c->fc, AV_LOG_WARNING, "Unsupported Content Light Level box version %d\n", version);
5471 avio_skip(pb, 3); /* flags */
5473 sc->coll = av_content_light_metadata_alloc(&sc->coll_size);
5475 return AVERROR(ENOMEM);
5477 sc->coll->MaxCLL = avio_rb16(pb);
5478 sc->coll->MaxFALL = avio_rb16(pb);
5483 static int mov_read_clli(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5485 MOVStreamContext *sc;
5487 if (c->fc->nb_streams < 1)
5488 return AVERROR_INVALIDDATA;
5490 sc = c->fc->streams[c->fc->nb_streams - 1]->priv_data;
5492 if (atom.size < 4) {
5493 av_log(c->fc, AV_LOG_ERROR, "Empty Content Light Level Info box\n");
5494 return AVERROR_INVALIDDATA;
5497 sc->coll = av_content_light_metadata_alloc(&sc->coll_size);
5499 return AVERROR(ENOMEM);
5501 sc->coll->MaxCLL = avio_rb16(pb);
5502 sc->coll->MaxFALL = avio_rb16(pb);
5507 static int mov_read_st3d(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5510 MOVStreamContext *sc;
5511 enum AVStereo3DType type;
5514 if (c->fc->nb_streams < 1)
5517 st = c->fc->streams[c->fc->nb_streams - 1];
5520 if (atom.size < 5) {
5521 av_log(c->fc, AV_LOG_ERROR, "Empty stereoscopic video box\n");
5522 return AVERROR_INVALIDDATA;
5524 avio_skip(pb, 4); /* version + flags */
5529 type = AV_STEREO3D_2D;
5532 type = AV_STEREO3D_TOPBOTTOM;
5535 type = AV_STEREO3D_SIDEBYSIDE;
5538 av_log(c->fc, AV_LOG_WARNING, "Unknown st3d mode value %d\n", mode);
5542 sc->stereo3d = av_stereo3d_alloc();
5544 return AVERROR(ENOMEM);
5546 sc->stereo3d->type = type;
5550 static int mov_read_sv3d(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5553 MOVStreamContext *sc;
5554 int size, version, layout;
5555 int32_t yaw, pitch, roll;
5556 uint32_t l = 0, t = 0, r = 0, b = 0;
5557 uint32_t tag, padding = 0;
5558 enum AVSphericalProjection projection;
5560 if (c->fc->nb_streams < 1)
5563 st = c->fc->streams[c->fc->nb_streams - 1];
5566 if (atom.size < 8) {
5567 av_log(c->fc, AV_LOG_ERROR, "Empty spherical video box\n");
5568 return AVERROR_INVALIDDATA;
5571 size = avio_rb32(pb);
5572 if (size <= 12 || size > atom.size)
5573 return AVERROR_INVALIDDATA;
5575 tag = avio_rl32(pb);
5576 if (tag != MKTAG('s','v','h','d')) {
5577 av_log(c->fc, AV_LOG_ERROR, "Missing spherical video header\n");
5580 version = avio_r8(pb);
5582 av_log(c->fc, AV_LOG_WARNING, "Unknown spherical version %d\n",
5586 avio_skip(pb, 3); /* flags */
5587 avio_skip(pb, size - 12); /* metadata_source */
5589 size = avio_rb32(pb);
5590 if (size > atom.size)
5591 return AVERROR_INVALIDDATA;
5593 tag = avio_rl32(pb);
5594 if (tag != MKTAG('p','r','o','j')) {
5595 av_log(c->fc, AV_LOG_ERROR, "Missing projection box\n");
5599 size = avio_rb32(pb);
5600 if (size > atom.size)
5601 return AVERROR_INVALIDDATA;
5603 tag = avio_rl32(pb);
5604 if (tag != MKTAG('p','r','h','d')) {
5605 av_log(c->fc, AV_LOG_ERROR, "Missing projection header box\n");
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 /* 16.16 fixed point */
5617 yaw = avio_rb32(pb);
5618 pitch = avio_rb32(pb);
5619 roll = avio_rb32(pb);
5621 size = avio_rb32(pb);
5622 if (size > atom.size)
5623 return AVERROR_INVALIDDATA;
5625 tag = avio_rl32(pb);
5626 version = avio_r8(pb);
5628 av_log(c->fc, AV_LOG_WARNING, "Unknown spherical version %d\n",
5632 avio_skip(pb, 3); /* flags */
5634 case MKTAG('c','b','m','p'):
5635 layout = avio_rb32(pb);
5637 av_log(c->fc, AV_LOG_WARNING,
5638 "Unsupported cubemap layout %d\n", layout);
5641 projection = AV_SPHERICAL_CUBEMAP;
5642 padding = avio_rb32(pb);
5644 case MKTAG('e','q','u','i'):
5650 if (b >= UINT_MAX - t || r >= UINT_MAX - l) {
5651 av_log(c->fc, AV_LOG_ERROR,
5652 "Invalid bounding rectangle coordinates "
5653 "%"PRIu32",%"PRIu32",%"PRIu32",%"PRIu32"\n", l, t, r, b);
5654 return AVERROR_INVALIDDATA;
5657 if (l || t || r || b)
5658 projection = AV_SPHERICAL_EQUIRECTANGULAR_TILE;
5660 projection = AV_SPHERICAL_EQUIRECTANGULAR;
5663 av_log(c->fc, AV_LOG_ERROR, "Unknown projection type: %s\n", av_fourcc2str(tag));
5667 sc->spherical = av_spherical_alloc(&sc->spherical_size);
5669 return AVERROR(ENOMEM);
5671 sc->spherical->projection = projection;
5673 sc->spherical->yaw = yaw;
5674 sc->spherical->pitch = pitch;
5675 sc->spherical->roll = roll;
5677 sc->spherical->padding = padding;
5679 sc->spherical->bound_left = l;
5680 sc->spherical->bound_top = t;
5681 sc->spherical->bound_right = r;
5682 sc->spherical->bound_bottom = b;
5687 static int mov_parse_uuid_spherical(MOVStreamContext *sc, AVIOContext *pb, size_t len)
5690 uint8_t *buffer = av_malloc(len + 1);
5694 return AVERROR(ENOMEM);
5697 ret = ffio_read_size(pb, buffer, len);
5701 /* Check for mandatory keys and values, try to support XML as best-effort */
5702 if (!sc->spherical &&
5703 av_stristr(buffer, "<GSpherical:StitchingSoftware>") &&
5704 (val = av_stristr(buffer, "<GSpherical:Spherical>")) &&
5705 av_stristr(val, "true") &&
5706 (val = av_stristr(buffer, "<GSpherical:Stitched>")) &&
5707 av_stristr(val, "true") &&
5708 (val = av_stristr(buffer, "<GSpherical:ProjectionType>")) &&
5709 av_stristr(val, "equirectangular")) {
5710 sc->spherical = av_spherical_alloc(&sc->spherical_size);
5714 sc->spherical->projection = AV_SPHERICAL_EQUIRECTANGULAR;
5716 if (av_stristr(buffer, "<GSpherical:StereoMode>") && !sc->stereo3d) {
5717 enum AVStereo3DType mode;
5719 if (av_stristr(buffer, "left-right"))
5720 mode = AV_STEREO3D_SIDEBYSIDE;
5721 else if (av_stristr(buffer, "top-bottom"))
5722 mode = AV_STEREO3D_TOPBOTTOM;
5724 mode = AV_STEREO3D_2D;
5726 sc->stereo3d = av_stereo3d_alloc();
5730 sc->stereo3d->type = mode;
5734 val = av_stristr(buffer, "<GSpherical:InitialViewHeadingDegrees>");
5736 sc->spherical->yaw = strtol(val, NULL, 10) * (1 << 16);
5737 val = av_stristr(buffer, "<GSpherical:InitialViewPitchDegrees>");
5739 sc->spherical->pitch = strtol(val, NULL, 10) * (1 << 16);
5740 val = av_stristr(buffer, "<GSpherical:InitialViewRollDegrees>");
5742 sc->spherical->roll = strtol(val, NULL, 10) * (1 << 16);
5750 static int mov_read_uuid(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5753 MOVStreamContext *sc;
5756 static const uint8_t uuid_isml_manifest[] = {
5757 0xa5, 0xd4, 0x0b, 0x30, 0xe8, 0x14, 0x11, 0xdd,
5758 0xba, 0x2f, 0x08, 0x00, 0x20, 0x0c, 0x9a, 0x66
5760 static const uint8_t uuid_xmp[] = {
5761 0xbe, 0x7a, 0xcf, 0xcb, 0x97, 0xa9, 0x42, 0xe8,
5762 0x9c, 0x71, 0x99, 0x94, 0x91, 0xe3, 0xaf, 0xac
5764 static const uint8_t uuid_spherical[] = {
5765 0xff, 0xcc, 0x82, 0x63, 0xf8, 0x55, 0x4a, 0x93,
5766 0x88, 0x14, 0x58, 0x7a, 0x02, 0x52, 0x1f, 0xdd,
5769 if (atom.size < sizeof(uuid) || atom.size >= FFMIN(INT_MAX, SIZE_MAX))
5770 return AVERROR_INVALIDDATA;
5772 if (c->fc->nb_streams < 1)
5774 st = c->fc->streams[c->fc->nb_streams - 1];
5777 ret = ffio_read_size(pb, uuid, sizeof(uuid));
5780 if (!memcmp(uuid, uuid_isml_manifest, sizeof(uuid))) {
5781 uint8_t *buffer, *ptr;
5783 size_t len = atom.size - sizeof(uuid);
5786 return AVERROR_INVALIDDATA;
5788 ret = avio_skip(pb, 4); // zeroes
5791 buffer = av_mallocz(len + 1);
5793 return AVERROR(ENOMEM);
5795 ret = ffio_read_size(pb, buffer, len);
5802 while ((ptr = av_stristr(ptr, "systemBitrate=\""))) {
5803 ptr += sizeof("systemBitrate=\"") - 1;
5804 c->bitrates_count++;
5805 c->bitrates = av_realloc_f(c->bitrates, c->bitrates_count, sizeof(*c->bitrates));
5807 c->bitrates_count = 0;
5809 return AVERROR(ENOMEM);
5812 ret = strtol(ptr, &endptr, 10);
5813 if (ret < 0 || errno || *endptr != '"') {
5814 c->bitrates[c->bitrates_count - 1] = 0;
5816 c->bitrates[c->bitrates_count - 1] = ret;
5821 } else if (!memcmp(uuid, uuid_xmp, sizeof(uuid))) {
5823 size_t len = atom.size - sizeof(uuid);
5824 if (c->export_xmp) {
5825 buffer = av_mallocz(len + 1);
5827 return AVERROR(ENOMEM);
5829 ret = ffio_read_size(pb, buffer, len);
5835 av_dict_set(&c->fc->metadata, "xmp",
5836 buffer, AV_DICT_DONT_STRDUP_VAL);
5838 // skip all uuid atom, which makes it fast for long uuid-xmp file
5839 ret = avio_skip(pb, len);
5843 } else if (!memcmp(uuid, uuid_spherical, sizeof(uuid))) {
5844 size_t len = atom.size - sizeof(uuid);
5845 ret = mov_parse_uuid_spherical(sc, pb, len);
5849 av_log(c->fc, AV_LOG_WARNING, "Invalid spherical metadata found\n");
5855 static int mov_read_free(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5858 uint8_t content[16];
5863 ret = avio_read(pb, content, FFMIN(sizeof(content), atom.size));
5869 && !memcmp(content, "Anevia\x1A\x1A", 8)
5870 && c->use_mfra_for == FF_MOV_FLAG_MFRA_AUTO) {
5871 c->use_mfra_for = FF_MOV_FLAG_MFRA_PTS;
5877 static int mov_read_frma(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5879 uint32_t format = avio_rl32(pb);
5880 MOVStreamContext *sc;
5884 if (c->fc->nb_streams < 1)
5886 st = c->fc->streams[c->fc->nb_streams - 1];
5891 case MKTAG('e','n','c','v'): // encrypted video
5892 case MKTAG('e','n','c','a'): // encrypted audio
5893 id = mov_codec_id(st, format);
5894 if (st->codecpar->codec_id != AV_CODEC_ID_NONE &&
5895 st->codecpar->codec_id != id) {
5896 av_log(c->fc, AV_LOG_WARNING,
5897 "ignoring 'frma' atom of '%.4s', stream has codec id %d\n",
5898 (char*)&format, st->codecpar->codec_id);
5902 st->codecpar->codec_id = id;
5903 sc->format = format;
5907 if (format != sc->format) {
5908 av_log(c->fc, AV_LOG_WARNING,
5909 "ignoring 'frma' atom of '%.4s', stream format is '%.4s'\n",
5910 (char*)&format, (char*)&sc->format);
5919 * Gets the current encryption info and associated current stream context. If
5920 * we are parsing a track fragment, this will return the specific encryption
5921 * info for this fragment; otherwise this will return the global encryption
5922 * info for the current stream.
5924 static int get_current_encryption_info(MOVContext *c, MOVEncryptionIndex **encryption_index, MOVStreamContext **sc)
5926 MOVFragmentStreamInfo *frag_stream_info;
5930 frag_stream_info = get_current_frag_stream_info(&c->frag_index);
5931 if (frag_stream_info) {
5932 for (i = 0; i < c->fc->nb_streams; i++) {
5933 if (c->fc->streams[i]->id == frag_stream_info->id) {
5934 st = c->fc->streams[i];
5938 if (i == c->fc->nb_streams)
5940 *sc = st->priv_data;
5942 if (!frag_stream_info->encryption_index) {
5943 // If this stream isn't encrypted, don't create the index.
5944 if (!(*sc)->cenc.default_encrypted_sample)
5946 frag_stream_info->encryption_index = av_mallocz(sizeof(*frag_stream_info->encryption_index));
5947 if (!frag_stream_info->encryption_index)
5948 return AVERROR(ENOMEM);
5950 *encryption_index = frag_stream_info->encryption_index;
5953 // No current track fragment, using stream level encryption info.
5955 if (c->fc->nb_streams < 1)
5957 st = c->fc->streams[c->fc->nb_streams - 1];
5958 *sc = st->priv_data;
5960 if (!(*sc)->cenc.encryption_index) {
5961 // If this stream isn't encrypted, don't create the index.
5962 if (!(*sc)->cenc.default_encrypted_sample)
5964 (*sc)->cenc.encryption_index = av_mallocz(sizeof(*frag_stream_info->encryption_index));
5965 if (!(*sc)->cenc.encryption_index)
5966 return AVERROR(ENOMEM);
5969 *encryption_index = (*sc)->cenc.encryption_index;
5974 static int mov_read_sample_encryption_info(MOVContext *c, AVIOContext *pb, MOVStreamContext *sc, AVEncryptionInfo **sample, int use_subsamples)
5977 unsigned int subsample_count;
5978 AVSubsampleEncryptionInfo *subsamples;
5980 if (!sc->cenc.default_encrypted_sample) {
5981 av_log(c->fc, AV_LOG_ERROR, "Missing schm or tenc\n");
5982 return AVERROR_INVALIDDATA;
5985 *sample = av_encryption_info_clone(sc->cenc.default_encrypted_sample);
5987 return AVERROR(ENOMEM);
5989 if (sc->cenc.per_sample_iv_size != 0) {
5990 if ((ret = ffio_read_size(pb, (*sample)->iv, sc->cenc.per_sample_iv_size)) < 0) {
5991 av_log(c->fc, AV_LOG_ERROR, "failed to read the initialization vector\n");
5992 av_encryption_info_free(*sample);
5998 if (use_subsamples) {
5999 subsample_count = avio_rb16(pb);
6000 av_free((*sample)->subsamples);
6001 (*sample)->subsamples = av_mallocz_array(subsample_count, sizeof(*subsamples));
6002 if (!(*sample)->subsamples) {
6003 av_encryption_info_free(*sample);
6005 return AVERROR(ENOMEM);
6008 for (i = 0; i < subsample_count && !pb->eof_reached; i++) {
6009 (*sample)->subsamples[i].bytes_of_clear_data = avio_rb16(pb);
6010 (*sample)->subsamples[i].bytes_of_protected_data = avio_rb32(pb);
6013 if (pb->eof_reached) {
6014 av_log(c->fc, AV_LOG_ERROR, "hit EOF while reading sub-sample encryption info\n");
6015 av_encryption_info_free(*sample);
6017 return AVERROR_INVALIDDATA;
6019 (*sample)->subsample_count = subsample_count;
6025 static int mov_read_senc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6027 AVEncryptionInfo **encrypted_samples;
6028 MOVEncryptionIndex *encryption_index;
6029 MOVStreamContext *sc;
6030 int use_subsamples, ret;
6031 unsigned int sample_count, i, alloc_size = 0;
6033 ret = get_current_encryption_info(c, &encryption_index, &sc);
6037 if (encryption_index->nb_encrypted_samples) {
6038 // This can happen if we have both saio/saiz and senc atoms.
6039 av_log(c->fc, AV_LOG_DEBUG, "Ignoring duplicate encryption info in senc\n");
6043 avio_r8(pb); /* version */
6044 use_subsamples = avio_rb24(pb) & 0x02; /* flags */
6046 sample_count = avio_rb32(pb);
6047 if (sample_count >= INT_MAX / sizeof(*encrypted_samples))
6048 return AVERROR(ENOMEM);
6050 for (i = 0; i < sample_count; i++) {
6051 unsigned int min_samples = FFMIN(FFMAX(i + 1, 1024 * 1024), sample_count);
6052 encrypted_samples = av_fast_realloc(encryption_index->encrypted_samples, &alloc_size,
6053 min_samples * sizeof(*encrypted_samples));
6054 if (encrypted_samples) {
6055 encryption_index->encrypted_samples = encrypted_samples;
6057 ret = mov_read_sample_encryption_info(
6058 c, pb, sc, &encryption_index->encrypted_samples[i], use_subsamples);
6060 ret = AVERROR(ENOMEM);
6062 if (pb->eof_reached) {
6063 av_log(c->fc, AV_LOG_ERROR, "Hit EOF while reading senc\n");
6064 ret = AVERROR_INVALIDDATA;
6069 av_encryption_info_free(encryption_index->encrypted_samples[i - 1]);
6070 av_freep(&encryption_index->encrypted_samples);
6074 encryption_index->nb_encrypted_samples = sample_count;
6079 static int mov_parse_auxiliary_info(MOVContext *c, MOVStreamContext *sc, AVIOContext *pb, MOVEncryptionIndex *encryption_index)
6081 AVEncryptionInfo **sample, **encrypted_samples;
6083 size_t sample_count, sample_info_size, i;
6085 unsigned int alloc_size = 0;
6087 if (encryption_index->nb_encrypted_samples)
6089 sample_count = encryption_index->auxiliary_info_sample_count;
6090 if (encryption_index->auxiliary_offsets_count != 1) {
6091 av_log(c->fc, AV_LOG_ERROR, "Multiple auxiliary info chunks are not supported\n");
6092 return AVERROR_PATCHWELCOME;
6094 if (sample_count >= INT_MAX / sizeof(*encrypted_samples))
6095 return AVERROR(ENOMEM);
6097 prev_pos = avio_tell(pb);
6098 if (!(pb->seekable & AVIO_SEEKABLE_NORMAL) ||
6099 avio_seek(pb, encryption_index->auxiliary_offsets[0], SEEK_SET) != encryption_index->auxiliary_offsets[0]) {
6100 av_log(c->fc, AV_LOG_INFO, "Failed to seek for auxiliary info, will only parse senc atoms for encryption info\n");
6104 for (i = 0; i < sample_count && !pb->eof_reached; i++) {
6105 unsigned int min_samples = FFMIN(FFMAX(i + 1, 1024 * 1024), sample_count);
6106 encrypted_samples = av_fast_realloc(encryption_index->encrypted_samples, &alloc_size,
6107 min_samples * sizeof(*encrypted_samples));
6108 if (!encrypted_samples) {
6109 ret = AVERROR(ENOMEM);
6112 encryption_index->encrypted_samples = encrypted_samples;
6114 sample = &encryption_index->encrypted_samples[i];
6115 sample_info_size = encryption_index->auxiliary_info_default_size
6116 ? encryption_index->auxiliary_info_default_size
6117 : encryption_index->auxiliary_info_sizes[i];
6119 ret = mov_read_sample_encryption_info(c, pb, sc, sample, sample_info_size > sc->cenc.per_sample_iv_size);
6123 if (pb->eof_reached) {
6124 av_log(c->fc, AV_LOG_ERROR, "Hit EOF while reading auxiliary info\n");
6125 ret = AVERROR_INVALIDDATA;
6127 encryption_index->nb_encrypted_samples = sample_count;
6131 avio_seek(pb, prev_pos, SEEK_SET);
6133 for (; i > 0; i--) {
6134 av_encryption_info_free(encryption_index->encrypted_samples[i - 1]);
6136 av_freep(&encryption_index->encrypted_samples);
6142 * Tries to read the given number of bytes from the stream and puts it in a
6143 * newly allocated buffer. This reads in small chunks to avoid allocating large
6144 * memory if the file contains an invalid/malicious size value.
6146 static int mov_try_read_block(AVIOContext *pb, size_t size, uint8_t **data)
6148 const unsigned int block_size = 1024 * 1024;
6149 uint8_t *buffer = NULL;
6150 unsigned int alloc_size = 0, offset = 0;
6151 while (offset < size) {
6152 unsigned int new_size =
6153 alloc_size >= INT_MAX - block_size ? INT_MAX : alloc_size + block_size;
6154 uint8_t *new_buffer = av_fast_realloc(buffer, &alloc_size, new_size);
6155 unsigned int to_read = FFMIN(size, alloc_size) - offset;
6158 return AVERROR(ENOMEM);
6160 buffer = new_buffer;
6162 if (avio_read(pb, buffer + offset, to_read) != to_read) {
6164 return AVERROR_INVALIDDATA;
6173 static int mov_read_saiz(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6175 MOVEncryptionIndex *encryption_index;
6176 MOVStreamContext *sc;
6178 unsigned int sample_count, aux_info_type, aux_info_param;
6180 ret = get_current_encryption_info(c, &encryption_index, &sc);
6184 if (encryption_index->nb_encrypted_samples) {
6185 // This can happen if we have both saio/saiz and senc atoms.
6186 av_log(c->fc, AV_LOG_DEBUG, "Ignoring duplicate encryption info in saiz\n");
6190 if (encryption_index->auxiliary_info_sample_count) {
6191 av_log(c->fc, AV_LOG_ERROR, "Duplicate saiz atom\n");
6192 return AVERROR_INVALIDDATA;
6195 avio_r8(pb); /* version */
6196 if (avio_rb24(pb) & 0x01) { /* flags */
6197 aux_info_type = avio_rb32(pb);
6198 aux_info_param = avio_rb32(pb);
6199 if (sc->cenc.default_encrypted_sample) {
6200 if (aux_info_type != sc->cenc.default_encrypted_sample->scheme) {
6201 av_log(c->fc, AV_LOG_DEBUG, "Ignoring saiz box with non-zero aux_info_type\n");
6204 if (aux_info_param != 0) {
6205 av_log(c->fc, AV_LOG_DEBUG, "Ignoring saiz box with non-zero aux_info_type_parameter\n");
6209 // Didn't see 'schm' or 'tenc', so this isn't encrypted.
6210 if ((aux_info_type == MKBETAG('c','e','n','c') ||
6211 aux_info_type == MKBETAG('c','e','n','s') ||
6212 aux_info_type == MKBETAG('c','b','c','1') ||
6213 aux_info_type == MKBETAG('c','b','c','s')) &&
6214 aux_info_param == 0) {
6215 av_log(c->fc, AV_LOG_ERROR, "Saw encrypted saiz without schm/tenc\n");
6216 return AVERROR_INVALIDDATA;
6221 } else if (!sc->cenc.default_encrypted_sample) {
6222 // Didn't see 'schm' or 'tenc', so this isn't encrypted.
6226 encryption_index->auxiliary_info_default_size = avio_r8(pb);
6227 sample_count = avio_rb32(pb);
6228 encryption_index->auxiliary_info_sample_count = sample_count;
6230 if (encryption_index->auxiliary_info_default_size == 0) {
6231 ret = mov_try_read_block(pb, sample_count, &encryption_index->auxiliary_info_sizes);
6233 av_log(c->fc, AV_LOG_ERROR, "Failed to read the auxiliary info\n");
6238 if (encryption_index->auxiliary_offsets_count) {
6239 return mov_parse_auxiliary_info(c, sc, pb, encryption_index);
6245 static int mov_read_saio(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6247 uint64_t *auxiliary_offsets;
6248 MOVEncryptionIndex *encryption_index;
6249 MOVStreamContext *sc;
6251 unsigned int version, entry_count, aux_info_type, aux_info_param;
6252 unsigned int alloc_size = 0;
6254 ret = get_current_encryption_info(c, &encryption_index, &sc);
6258 if (encryption_index->nb_encrypted_samples) {
6259 // This can happen if we have both saio/saiz and senc atoms.
6260 av_log(c->fc, AV_LOG_DEBUG, "Ignoring duplicate encryption info in saio\n");
6264 if (encryption_index->auxiliary_offsets_count) {
6265 av_log(c->fc, AV_LOG_ERROR, "Duplicate saio atom\n");
6266 return AVERROR_INVALIDDATA;
6269 version = avio_r8(pb); /* version */
6270 if (avio_rb24(pb) & 0x01) { /* flags */
6271 aux_info_type = avio_rb32(pb);
6272 aux_info_param = avio_rb32(pb);
6273 if (sc->cenc.default_encrypted_sample) {
6274 if (aux_info_type != sc->cenc.default_encrypted_sample->scheme) {
6275 av_log(c->fc, AV_LOG_DEBUG, "Ignoring saio box with non-zero aux_info_type\n");
6278 if (aux_info_param != 0) {
6279 av_log(c->fc, AV_LOG_DEBUG, "Ignoring saio box with non-zero aux_info_type_parameter\n");
6283 // Didn't see 'schm' or 'tenc', so this isn't encrypted.
6284 if ((aux_info_type == MKBETAG('c','e','n','c') ||
6285 aux_info_type == MKBETAG('c','e','n','s') ||
6286 aux_info_type == MKBETAG('c','b','c','1') ||
6287 aux_info_type == MKBETAG('c','b','c','s')) &&
6288 aux_info_param == 0) {
6289 av_log(c->fc, AV_LOG_ERROR, "Saw encrypted saio without schm/tenc\n");
6290 return AVERROR_INVALIDDATA;
6295 } else if (!sc->cenc.default_encrypted_sample) {
6296 // Didn't see 'schm' or 'tenc', so this isn't encrypted.
6300 entry_count = avio_rb32(pb);
6301 if (entry_count >= INT_MAX / sizeof(*auxiliary_offsets))
6302 return AVERROR(ENOMEM);
6304 for (i = 0; i < entry_count && !pb->eof_reached; i++) {
6305 unsigned int min_offsets = FFMIN(FFMAX(i + 1, 1024), entry_count);
6306 auxiliary_offsets = av_fast_realloc(
6307 encryption_index->auxiliary_offsets, &alloc_size,
6308 min_offsets * sizeof(*auxiliary_offsets));
6309 if (!auxiliary_offsets) {
6310 av_freep(&encryption_index->auxiliary_offsets);
6311 return AVERROR(ENOMEM);
6313 encryption_index->auxiliary_offsets = auxiliary_offsets;
6316 encryption_index->auxiliary_offsets[i] = avio_rb32(pb);
6318 encryption_index->auxiliary_offsets[i] = avio_rb64(pb);
6320 if (c->frag_index.current >= 0) {
6321 encryption_index->auxiliary_offsets[i] += c->fragment.base_data_offset;
6325 if (pb->eof_reached) {
6326 av_log(c->fc, AV_LOG_ERROR, "Hit EOF while reading saio\n");
6327 av_freep(&encryption_index->auxiliary_offsets);
6328 return AVERROR_INVALIDDATA;
6331 encryption_index->auxiliary_offsets_count = entry_count;
6333 if (encryption_index->auxiliary_info_sample_count) {
6334 return mov_parse_auxiliary_info(c, sc, pb, encryption_index);
6340 static int mov_read_pssh(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6342 AVEncryptionInitInfo *info, *old_init_info;
6345 uint8_t *side_data, *extra_data, *old_side_data;
6346 size_t side_data_size;
6347 int ret = 0, old_side_data_size;
6348 unsigned int version, kid_count, extra_data_size, alloc_size = 0;
6350 if (c->fc->nb_streams < 1)
6352 st = c->fc->streams[c->fc->nb_streams-1];
6354 version = avio_r8(pb); /* version */
6355 avio_rb24(pb); /* flags */
6357 info = av_encryption_init_info_alloc(/* system_id_size */ 16, /* num_key_ids */ 0,
6358 /* key_id_size */ 16, /* data_size */ 0);
6360 return AVERROR(ENOMEM);
6362 if ((ret = ffio_read_size(pb, info->system_id, 16)) < 0) {
6363 av_log(c->fc, AV_LOG_ERROR, "Failed to read the system id\n");
6368 kid_count = avio_rb32(pb);
6369 if (kid_count >= INT_MAX / sizeof(*key_ids)) {
6370 ret = AVERROR(ENOMEM);
6374 for (unsigned int i = 0; i < kid_count && !pb->eof_reached; i++) {
6375 unsigned int min_kid_count = FFMIN(FFMAX(i + 1, 1024), kid_count);
6376 key_ids = av_fast_realloc(info->key_ids, &alloc_size,
6377 min_kid_count * sizeof(*key_ids));
6379 ret = AVERROR(ENOMEM);
6382 info->key_ids = key_ids;
6384 info->key_ids[i] = av_mallocz(16);
6385 if (!info->key_ids[i]) {
6386 ret = AVERROR(ENOMEM);
6389 info->num_key_ids = i + 1;
6391 if ((ret = ffio_read_size(pb, info->key_ids[i], 16)) < 0) {
6392 av_log(c->fc, AV_LOG_ERROR, "Failed to read the key id\n");
6397 if (pb->eof_reached) {
6398 av_log(c->fc, AV_LOG_ERROR, "Hit EOF while reading pssh\n");
6399 ret = AVERROR_INVALIDDATA;
6404 extra_data_size = avio_rb32(pb);
6405 ret = mov_try_read_block(pb, extra_data_size, &extra_data);
6409 av_freep(&info->data); // malloc(0) may still allocate something.
6410 info->data = extra_data;
6411 info->data_size = extra_data_size;
6413 // If there is existing initialization data, append to the list.
6414 old_side_data = av_stream_get_side_data(st, AV_PKT_DATA_ENCRYPTION_INIT_INFO, &old_side_data_size);
6415 if (old_side_data) {
6416 old_init_info = av_encryption_init_info_get_side_data(old_side_data, old_side_data_size);
6417 if (old_init_info) {
6418 // Append to the end of the list.
6419 for (AVEncryptionInitInfo *cur = old_init_info;; cur = cur->next) {
6425 info = old_init_info;
6427 // Assume existing side-data will be valid, so the only error we could get is OOM.
6428 ret = AVERROR(ENOMEM);
6433 side_data = av_encryption_init_info_add_side_data(info, &side_data_size);
6435 ret = AVERROR(ENOMEM);
6438 ret = av_stream_add_side_data(st, AV_PKT_DATA_ENCRYPTION_INIT_INFO,
6439 side_data, side_data_size);
6444 av_encryption_init_info_free(info);
6448 static int mov_read_schm(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6451 MOVStreamContext *sc;
6453 if (c->fc->nb_streams < 1)
6455 st = c->fc->streams[c->fc->nb_streams-1];
6458 if (sc->pseudo_stream_id != 0) {
6459 av_log(c->fc, AV_LOG_ERROR, "schm boxes are only supported in first sample descriptor\n");
6460 return AVERROR_PATCHWELCOME;
6464 return AVERROR_INVALIDDATA;
6466 avio_rb32(pb); /* version and flags */
6468 if (!sc->cenc.default_encrypted_sample) {
6469 sc->cenc.default_encrypted_sample = av_encryption_info_alloc(0, 16, 16);
6470 if (!sc->cenc.default_encrypted_sample) {
6471 return AVERROR(ENOMEM);
6475 sc->cenc.default_encrypted_sample->scheme = avio_rb32(pb);
6479 static int mov_read_tenc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6482 MOVStreamContext *sc;
6483 unsigned int version, pattern, is_protected, iv_size;
6485 if (c->fc->nb_streams < 1)
6487 st = c->fc->streams[c->fc->nb_streams-1];
6490 if (sc->pseudo_stream_id != 0) {
6491 av_log(c->fc, AV_LOG_ERROR, "tenc atom are only supported in first sample descriptor\n");
6492 return AVERROR_PATCHWELCOME;
6495 if (!sc->cenc.default_encrypted_sample) {
6496 sc->cenc.default_encrypted_sample = av_encryption_info_alloc(0, 16, 16);
6497 if (!sc->cenc.default_encrypted_sample) {
6498 return AVERROR(ENOMEM);
6503 return AVERROR_INVALIDDATA;
6505 version = avio_r8(pb); /* version */
6506 avio_rb24(pb); /* flags */
6508 avio_r8(pb); /* reserved */
6509 pattern = avio_r8(pb);
6512 sc->cenc.default_encrypted_sample->crypt_byte_block = pattern >> 4;
6513 sc->cenc.default_encrypted_sample->skip_byte_block = pattern & 0xf;
6516 is_protected = avio_r8(pb);
6517 if (is_protected && !sc->cenc.encryption_index) {
6518 // The whole stream should be by-default encrypted.
6519 sc->cenc.encryption_index = av_mallocz(sizeof(MOVEncryptionIndex));
6520 if (!sc->cenc.encryption_index)
6521 return AVERROR(ENOMEM);
6523 sc->cenc.per_sample_iv_size = avio_r8(pb);
6524 if (sc->cenc.per_sample_iv_size != 0 && sc->cenc.per_sample_iv_size != 8 &&
6525 sc->cenc.per_sample_iv_size != 16) {
6526 av_log(c->fc, AV_LOG_ERROR, "invalid per-sample IV size value\n");
6527 return AVERROR_INVALIDDATA;
6529 if (avio_read(pb, sc->cenc.default_encrypted_sample->key_id, 16) != 16) {
6530 av_log(c->fc, AV_LOG_ERROR, "failed to read the default key ID\n");
6531 return AVERROR_INVALIDDATA;
6534 if (is_protected && !sc->cenc.per_sample_iv_size) {
6535 iv_size = avio_r8(pb);
6536 if (iv_size != 8 && iv_size != 16) {
6537 av_log(c->fc, AV_LOG_ERROR, "invalid default_constant_IV_size in tenc atom\n");
6538 return AVERROR_INVALIDDATA;
6541 if (avio_read(pb, sc->cenc.default_encrypted_sample->iv, iv_size) != iv_size) {
6542 av_log(c->fc, AV_LOG_ERROR, "failed to read the default IV\n");
6543 return AVERROR_INVALIDDATA;
6550 static int mov_read_dfla(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6553 int last, type, size, ret;
6556 if (c->fc->nb_streams < 1)
6558 st = c->fc->streams[c->fc->nb_streams-1];
6560 if ((uint64_t)atom.size > (1<<30) || atom.size < 42)
6561 return AVERROR_INVALIDDATA;
6563 /* Check FlacSpecificBox version. */
6564 if (avio_r8(pb) != 0)
6565 return AVERROR_INVALIDDATA;
6567 avio_rb24(pb); /* Flags */
6569 avio_read(pb, buf, sizeof(buf));
6570 flac_parse_block_header(buf, &last, &type, &size);
6572 if (type != FLAC_METADATA_TYPE_STREAMINFO || size != FLAC_STREAMINFO_SIZE) {
6573 av_log(c->fc, AV_LOG_ERROR, "STREAMINFO must be first FLACMetadataBlock\n");
6574 return AVERROR_INVALIDDATA;
6577 ret = ff_get_extradata(c->fc, st->codecpar, pb, size);
6582 av_log(c->fc, AV_LOG_WARNING, "non-STREAMINFO FLACMetadataBlock(s) ignored\n");
6587 static int cenc_decrypt(MOVContext *c, MOVStreamContext *sc, AVEncryptionInfo *sample, uint8_t *input, int size)
6591 if (sample->scheme != MKBETAG('c','e','n','c') || sample->crypt_byte_block != 0 || sample->skip_byte_block != 0) {
6592 av_log(c->fc, AV_LOG_ERROR, "Only the 'cenc' encryption scheme is supported\n");
6593 return AVERROR_PATCHWELCOME;
6596 if (!sc->cenc.aes_ctr) {
6597 /* initialize the cipher */
6598 sc->cenc.aes_ctr = av_aes_ctr_alloc();
6599 if (!sc->cenc.aes_ctr) {
6600 return AVERROR(ENOMEM);
6603 ret = av_aes_ctr_init(sc->cenc.aes_ctr, c->decryption_key);
6609 av_aes_ctr_set_full_iv(sc->cenc.aes_ctr, sample->iv);
6611 if (!sample->subsample_count) {
6612 /* decrypt the whole packet */
6613 av_aes_ctr_crypt(sc->cenc.aes_ctr, input, input, size);
6617 for (i = 0; i < sample->subsample_count; i++) {
6618 if (sample->subsamples[i].bytes_of_clear_data + sample->subsamples[i].bytes_of_protected_data > size) {
6619 av_log(c->fc, AV_LOG_ERROR, "subsample size exceeds the packet size left\n");
6620 return AVERROR_INVALIDDATA;
6623 /* skip the clear bytes */
6624 input += sample->subsamples[i].bytes_of_clear_data;
6625 size -= sample->subsamples[i].bytes_of_clear_data;
6627 /* decrypt the encrypted bytes */
6628 av_aes_ctr_crypt(sc->cenc.aes_ctr, input, input, sample->subsamples[i].bytes_of_protected_data);
6629 input += sample->subsamples[i].bytes_of_protected_data;
6630 size -= sample->subsamples[i].bytes_of_protected_data;
6634 av_log(c->fc, AV_LOG_ERROR, "leftover packet bytes after subsample processing\n");
6635 return AVERROR_INVALIDDATA;
6641 static int cenc_filter(MOVContext *mov, AVStream* st, MOVStreamContext *sc, AVPacket *pkt, int current_index)
6643 MOVFragmentStreamInfo *frag_stream_info;
6644 MOVEncryptionIndex *encryption_index;
6645 AVEncryptionInfo *encrypted_sample;
6646 int encrypted_index, ret;
6648 frag_stream_info = get_frag_stream_info(&mov->frag_index, mov->frag_index.current, st->id);
6649 encrypted_index = current_index;
6650 encryption_index = NULL;
6651 if (frag_stream_info) {
6652 // Note this only supports encryption info in the first sample descriptor.
6653 if (mov->fragment.stsd_id == 1) {
6654 if (frag_stream_info->encryption_index) {
6655 encrypted_index = current_index - frag_stream_info->index_entry;
6656 encryption_index = frag_stream_info->encryption_index;
6658 encryption_index = sc->cenc.encryption_index;
6662 encryption_index = sc->cenc.encryption_index;
6665 if (encryption_index) {
6666 if (encryption_index->auxiliary_info_sample_count &&
6667 !encryption_index->nb_encrypted_samples) {
6668 av_log(mov->fc, AV_LOG_ERROR, "saiz atom found without saio\n");
6669 return AVERROR_INVALIDDATA;
6671 if (encryption_index->auxiliary_offsets_count &&
6672 !encryption_index->nb_encrypted_samples) {
6673 av_log(mov->fc, AV_LOG_ERROR, "saio atom found without saiz\n");
6674 return AVERROR_INVALIDDATA;
6677 if (!encryption_index->nb_encrypted_samples) {
6678 // Full-sample encryption with default settings.
6679 encrypted_sample = sc->cenc.default_encrypted_sample;
6680 } else if (encrypted_index >= 0 && encrypted_index < encryption_index->nb_encrypted_samples) {
6681 // Per-sample setting override.
6682 encrypted_sample = encryption_index->encrypted_samples[encrypted_index];
6684 av_log(mov->fc, AV_LOG_ERROR, "Incorrect number of samples in encryption info\n");
6685 return AVERROR_INVALIDDATA;
6688 if (mov->decryption_key) {
6689 return cenc_decrypt(mov, sc, encrypted_sample, pkt->data, pkt->size);
6692 uint8_t *side_data = av_encryption_info_add_side_data(encrypted_sample, &size);
6694 return AVERROR(ENOMEM);
6695 ret = av_packet_add_side_data(pkt, AV_PKT_DATA_ENCRYPTION_INFO, side_data, size);
6705 static int mov_read_dops(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6707 const int OPUS_SEEK_PREROLL_MS = 80;
6713 if (c->fc->nb_streams < 1)
6715 st = c->fc->streams[c->fc->nb_streams-1];
6717 if ((uint64_t)atom.size > (1<<30) || atom.size < 11)
6718 return AVERROR_INVALIDDATA;
6720 /* Check OpusSpecificBox version. */
6721 if (avio_r8(pb) != 0) {
6722 av_log(c->fc, AV_LOG_ERROR, "unsupported OpusSpecificBox version\n");
6723 return AVERROR_INVALIDDATA;
6726 /* OpusSpecificBox size plus magic for Ogg OpusHead header. */
6727 size = atom.size + 8;
6729 if ((ret = ff_alloc_extradata(st->codecpar, size)) < 0)
6732 AV_WL32(st->codecpar->extradata, MKTAG('O','p','u','s'));
6733 AV_WL32(st->codecpar->extradata + 4, MKTAG('H','e','a','d'));
6734 AV_WB8(st->codecpar->extradata + 8, 1); /* OpusHead version */
6735 avio_read(pb, st->codecpar->extradata + 9, size - 9);
6737 /* OpusSpecificBox is stored in big-endian, but OpusHead is
6738 little-endian; aside from the preceeding magic and version they're
6739 otherwise currently identical. Data after output gain at offset 16
6740 doesn't need to be bytewapped. */
6741 pre_skip = AV_RB16(st->codecpar->extradata + 10);
6742 AV_WL16(st->codecpar->extradata + 10, pre_skip);
6743 AV_WL32(st->codecpar->extradata + 12, AV_RB32(st->codecpar->extradata + 12));
6744 AV_WL16(st->codecpar->extradata + 16, AV_RB16(st->codecpar->extradata + 16));
6746 st->codecpar->initial_padding = pre_skip;
6747 st->codecpar->seek_preroll = av_rescale_q(OPUS_SEEK_PREROLL_MS,
6748 (AVRational){1, 1000},
6749 (AVRational){1, 48000});
6754 static int mov_read_dmlp(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6757 unsigned format_info;
6758 int channel_assignment, channel_assignment1, channel_assignment2;
6761 if (c->fc->nb_streams < 1)
6763 st = c->fc->streams[c->fc->nb_streams-1];
6766 return AVERROR_INVALIDDATA;
6768 format_info = avio_rb32(pb);
6770 ratebits = (format_info >> 28) & 0xF;
6771 channel_assignment1 = (format_info >> 15) & 0x1F;
6772 channel_assignment2 = format_info & 0x1FFF;
6773 if (channel_assignment2)
6774 channel_assignment = channel_assignment2;
6776 channel_assignment = channel_assignment1;
6778 st->codecpar->frame_size = 40 << (ratebits & 0x7);
6779 st->codecpar->sample_rate = mlp_samplerate(ratebits);
6780 st->codecpar->channels = truehd_channels(channel_assignment);
6781 st->codecpar->channel_layout = truehd_layout(channel_assignment);
6786 static int mov_read_dvcc_dvvc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6790 AVDOVIDecoderConfigurationRecord *dovi;
6794 if (c->fc->nb_streams < 1)
6796 st = c->fc->streams[c->fc->nb_streams-1];
6798 if ((uint64_t)atom.size > (1<<30) || atom.size < 4)
6799 return AVERROR_INVALIDDATA;
6801 dovi = av_dovi_alloc(&dovi_size);
6803 return AVERROR(ENOMEM);
6805 dovi->dv_version_major = avio_r8(pb);
6806 dovi->dv_version_minor = avio_r8(pb);
6808 buf = avio_rb16(pb);
6809 dovi->dv_profile = (buf >> 9) & 0x7f; // 7 bits
6810 dovi->dv_level = (buf >> 3) & 0x3f; // 6 bits
6811 dovi->rpu_present_flag = (buf >> 2) & 0x01; // 1 bit
6812 dovi->el_present_flag = (buf >> 1) & 0x01; // 1 bit
6813 dovi->bl_present_flag = buf & 0x01; // 1 bit
6814 if (atom.size >= 24) { // 4 + 4 + 4 * 4
6816 dovi->dv_bl_signal_compatibility_id = (buf >> 4) & 0x0f; // 4 bits
6818 // 0 stands for None
6819 // Dolby Vision V1.2.93 profiles and levels
6820 dovi->dv_bl_signal_compatibility_id = 0;
6823 ret = av_stream_add_side_data(st, AV_PKT_DATA_DOVI_CONF,
6824 (uint8_t *)dovi, dovi_size);
6830 av_log(c, AV_LOG_TRACE, "DOVI in dvcC/dvvC box, version: %d.%d, profile: %d, level: %d, "
6831 "rpu flag: %d, el flag: %d, bl flag: %d, compatibility id: %d\n",
6832 dovi->dv_version_major, dovi->dv_version_minor,
6833 dovi->dv_profile, dovi->dv_level,
6834 dovi->rpu_present_flag,
6835 dovi->el_present_flag,
6836 dovi->bl_present_flag,
6837 dovi->dv_bl_signal_compatibility_id
6843 static const MOVParseTableEntry mov_default_parse_table[] = {
6844 { MKTAG('A','C','L','R'), mov_read_aclr },
6845 { MKTAG('A','P','R','G'), mov_read_avid },
6846 { MKTAG('A','A','L','P'), mov_read_avid },
6847 { MKTAG('A','R','E','S'), mov_read_ares },
6848 { MKTAG('a','v','s','s'), mov_read_avss },
6849 { MKTAG('a','v','1','C'), mov_read_av1c },
6850 { MKTAG('c','h','p','l'), mov_read_chpl },
6851 { MKTAG('c','o','6','4'), mov_read_stco },
6852 { MKTAG('c','o','l','r'), mov_read_colr },
6853 { MKTAG('c','t','t','s'), mov_read_ctts }, /* composition time to sample */
6854 { MKTAG('d','i','n','f'), mov_read_default },
6855 { MKTAG('D','p','x','E'), mov_read_dpxe },
6856 { MKTAG('d','r','e','f'), mov_read_dref },
6857 { MKTAG('e','d','t','s'), mov_read_default },
6858 { MKTAG('e','l','s','t'), mov_read_elst },
6859 { MKTAG('e','n','d','a'), mov_read_enda },
6860 { MKTAG('f','i','e','l'), mov_read_fiel },
6861 { MKTAG('a','d','r','m'), mov_read_adrm },
6862 { MKTAG('f','t','y','p'), mov_read_ftyp },
6863 { MKTAG('g','l','b','l'), mov_read_glbl },
6864 { MKTAG('h','d','l','r'), mov_read_hdlr },
6865 { MKTAG('i','l','s','t'), mov_read_ilst },
6866 { MKTAG('j','p','2','h'), mov_read_jp2h },
6867 { MKTAG('m','d','a','t'), mov_read_mdat },
6868 { MKTAG('m','d','h','d'), mov_read_mdhd },
6869 { MKTAG('m','d','i','a'), mov_read_default },
6870 { MKTAG('m','e','t','a'), mov_read_meta },
6871 { MKTAG('m','i','n','f'), mov_read_default },
6872 { MKTAG('m','o','o','f'), mov_read_moof },
6873 { MKTAG('m','o','o','v'), mov_read_moov },
6874 { MKTAG('m','v','e','x'), mov_read_default },
6875 { MKTAG('m','v','h','d'), mov_read_mvhd },
6876 { MKTAG('S','M','I',' '), mov_read_svq3 },
6877 { MKTAG('a','l','a','c'), mov_read_alac }, /* alac specific atom */
6878 { MKTAG('a','v','c','C'), mov_read_glbl },
6879 { MKTAG('p','a','s','p'), mov_read_pasp },
6880 { MKTAG('s','i','d','x'), mov_read_sidx },
6881 { MKTAG('s','t','b','l'), mov_read_default },
6882 { MKTAG('s','t','c','o'), mov_read_stco },
6883 { MKTAG('s','t','p','s'), mov_read_stps },
6884 { MKTAG('s','t','r','f'), mov_read_strf },
6885 { MKTAG('s','t','s','c'), mov_read_stsc },
6886 { MKTAG('s','t','s','d'), mov_read_stsd }, /* sample description */
6887 { MKTAG('s','t','s','s'), mov_read_stss }, /* sync sample */
6888 { MKTAG('s','t','s','z'), mov_read_stsz }, /* sample size */
6889 { MKTAG('s','t','t','s'), mov_read_stts },
6890 { MKTAG('s','t','z','2'), mov_read_stsz }, /* compact sample size */
6891 { MKTAG('s','d','t','p'), mov_read_sdtp }, /* independent and disposable samples */
6892 { MKTAG('t','k','h','d'), mov_read_tkhd }, /* track header */
6893 { MKTAG('t','f','d','t'), mov_read_tfdt },
6894 { MKTAG('t','f','h','d'), mov_read_tfhd }, /* track fragment header */
6895 { MKTAG('t','r','a','k'), mov_read_trak },
6896 { MKTAG('t','r','a','f'), mov_read_default },
6897 { MKTAG('t','r','e','f'), mov_read_default },
6898 { MKTAG('t','m','c','d'), mov_read_tmcd },
6899 { MKTAG('c','h','a','p'), mov_read_chap },
6900 { MKTAG('t','r','e','x'), mov_read_trex },
6901 { MKTAG('t','r','u','n'), mov_read_trun },
6902 { MKTAG('u','d','t','a'), mov_read_default },
6903 { MKTAG('w','a','v','e'), mov_read_wave },
6904 { MKTAG('e','s','d','s'), mov_read_esds },
6905 { MKTAG('d','a','c','3'), mov_read_dac3 }, /* AC-3 info */
6906 { MKTAG('d','e','c','3'), mov_read_dec3 }, /* EAC-3 info */
6907 { MKTAG('d','d','t','s'), mov_read_ddts }, /* DTS audio descriptor */
6908 { MKTAG('w','i','d','e'), mov_read_wide }, /* place holder */
6909 { MKTAG('w','f','e','x'), mov_read_wfex },
6910 { MKTAG('c','m','o','v'), mov_read_cmov },
6911 { MKTAG('c','h','a','n'), mov_read_chan }, /* channel layout */
6912 { MKTAG('d','v','c','1'), mov_read_dvc1 },
6913 { MKTAG('s','b','g','p'), mov_read_sbgp },
6914 { MKTAG('h','v','c','C'), mov_read_glbl },
6915 { MKTAG('u','u','i','d'), mov_read_uuid },
6916 { MKTAG('C','i','n', 0x8e), mov_read_targa_y216 },
6917 { MKTAG('f','r','e','e'), mov_read_free },
6918 { MKTAG('-','-','-','-'), mov_read_custom },
6919 { MKTAG('s','i','n','f'), mov_read_default },
6920 { MKTAG('f','r','m','a'), mov_read_frma },
6921 { MKTAG('s','e','n','c'), mov_read_senc },
6922 { MKTAG('s','a','i','z'), mov_read_saiz },
6923 { MKTAG('s','a','i','o'), mov_read_saio },
6924 { MKTAG('p','s','s','h'), mov_read_pssh },
6925 { MKTAG('s','c','h','m'), mov_read_schm },
6926 { MKTAG('s','c','h','i'), mov_read_default },
6927 { MKTAG('t','e','n','c'), mov_read_tenc },
6928 { MKTAG('d','f','L','a'), mov_read_dfla },
6929 { MKTAG('s','t','3','d'), mov_read_st3d }, /* stereoscopic 3D video box */
6930 { MKTAG('s','v','3','d'), mov_read_sv3d }, /* spherical video box */
6931 { MKTAG('d','O','p','s'), mov_read_dops },
6932 { MKTAG('d','m','l','p'), mov_read_dmlp },
6933 { MKTAG('S','m','D','m'), mov_read_smdm },
6934 { MKTAG('C','o','L','L'), mov_read_coll },
6935 { MKTAG('v','p','c','C'), mov_read_vpcc },
6936 { MKTAG('m','d','c','v'), mov_read_mdcv },
6937 { MKTAG('c','l','l','i'), mov_read_clli },
6938 { MKTAG('d','v','c','C'), mov_read_dvcc_dvvc },
6939 { MKTAG('d','v','v','C'), mov_read_dvcc_dvvc },
6943 static int mov_read_default(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6945 int64_t total_size = 0;
6949 if (c->atom_depth > 10) {
6950 av_log(c->fc, AV_LOG_ERROR, "Atoms too deeply nested\n");
6951 return AVERROR_INVALIDDATA;
6956 atom.size = INT64_MAX;
6957 while (total_size <= atom.size - 8 && !avio_feof(pb)) {
6958 int (*parse)(MOVContext*, AVIOContext*, MOVAtom) = NULL;
6961 if (atom.size >= 8) {
6962 a.size = avio_rb32(pb);
6963 a.type = avio_rl32(pb);
6964 if (((a.type == MKTAG('f','r','e','e') && c->moov_retry) ||
6965 a.type == MKTAG('h','o','o','v')) &&
6967 c->fc->strict_std_compliance < FF_COMPLIANCE_STRICT) {
6970 type = avio_rl32(pb);
6971 avio_seek(pb, -8, SEEK_CUR);
6972 if (type == MKTAG('m','v','h','d') ||
6973 type == MKTAG('c','m','o','v')) {
6974 av_log(c->fc, AV_LOG_ERROR, "Detected moov in a free or hoov atom.\n");
6975 a.type = MKTAG('m','o','o','v');
6978 if (atom.type != MKTAG('r','o','o','t') &&
6979 atom.type != MKTAG('m','o','o','v')) {
6980 if (a.type == MKTAG('t','r','a','k') ||
6981 a.type == MKTAG('m','d','a','t')) {
6982 av_log(c->fc, AV_LOG_ERROR, "Broken file, trak/mdat not at top-level\n");
6989 if (a.size == 1 && total_size + 8 <= atom.size) { /* 64 bit extended size */
6990 a.size = avio_rb64(pb) - 8;
6994 av_log(c->fc, AV_LOG_TRACE, "type:'%s' parent:'%s' sz: %"PRId64" %"PRId64" %"PRId64"\n",
6995 av_fourcc2str(a.type), av_fourcc2str(atom.type), a.size, total_size, atom.size);
6997 a.size = atom.size - total_size + 8;
7002 a.size = FFMIN(a.size, atom.size - total_size);
7004 for (i = 0; mov_default_parse_table[i].type; i++)
7005 if (mov_default_parse_table[i].type == a.type) {
7006 parse = mov_default_parse_table[i].parse;
7010 // container is user data
7011 if (!parse && (atom.type == MKTAG('u','d','t','a') ||
7012 atom.type == MKTAG('i','l','s','t')))
7013 parse = mov_read_udta_string;
7015 // Supports parsing the QuickTime Metadata Keys.
7016 // https://developer.apple.com/library/mac/documentation/QuickTime/QTFF/Metadata/Metadata.html
7017 if (!parse && c->found_hdlr_mdta &&
7018 atom.type == MKTAG('m','e','t','a') &&
7019 a.type == MKTAG('k','e','y','s') &&
7020 c->meta_keys_count == 0) {
7021 parse = mov_read_keys;
7024 if (!parse) { /* skip leaf atoms data */
7025 avio_skip(pb, a.size);
7027 int64_t start_pos = avio_tell(pb);
7029 int err = parse(c, pb, a);
7034 if (c->found_moov && c->found_mdat &&
7035 ((!(pb->seekable & AVIO_SEEKABLE_NORMAL) || c->fc->flags & AVFMT_FLAG_IGNIDX || c->frag_index.complete) ||
7036 start_pos + a.size == avio_size(pb))) {
7037 if (!(pb->seekable & AVIO_SEEKABLE_NORMAL) || c->fc->flags & AVFMT_FLAG_IGNIDX || c->frag_index.complete)
7038 c->next_root_atom = start_pos + a.size;
7042 left = a.size - avio_tell(pb) + start_pos;
7043 if (left > 0) /* skip garbage at atom end */
7044 avio_skip(pb, left);
7045 else if (left < 0) {
7046 av_log(c->fc, AV_LOG_WARNING,
7047 "overread end of atom '%s' by %"PRId64" bytes\n",
7048 av_fourcc2str(a.type), -left);
7049 avio_seek(pb, left, SEEK_CUR);
7053 total_size += a.size;
7056 if (total_size < atom.size && atom.size < 0x7ffff)
7057 avio_skip(pb, atom.size - total_size);
7063 static int mov_probe(const AVProbeData *p)
7068 int moov_offset = -1;
7070 /* check file header */
7073 /* ignore invalid offset */
7074 if ((offset + 8) > (unsigned int)p->buf_size)
7076 tag = AV_RL32(p->buf + offset + 4);
7078 /* check for obvious tags */
7079 case MKTAG('m','o','o','v'):
7080 moov_offset = offset + 4;
7081 case MKTAG('m','d','a','t'):
7082 case MKTAG('p','n','o','t'): /* detect movs with preview pics like ew.mov and april.mov */
7083 case MKTAG('u','d','t','a'): /* Packet Video PVAuthor adds this and a lot of more junk */
7084 case MKTAG('f','t','y','p'):
7085 if (AV_RB32(p->buf+offset) < 8 &&
7086 (AV_RB32(p->buf+offset) != 1 ||
7087 offset + 12 > (unsigned int)p->buf_size ||
7088 AV_RB64(p->buf+offset + 8) == 0)) {
7089 score = FFMAX(score, AVPROBE_SCORE_EXTENSION);
7090 } else if (tag == MKTAG('f','t','y','p') &&
7091 ( AV_RL32(p->buf + offset + 8) == MKTAG('j','p','2',' ')
7092 || AV_RL32(p->buf + offset + 8) == MKTAG('j','p','x',' ')
7094 score = FFMAX(score, 5);
7096 score = AVPROBE_SCORE_MAX;
7098 offset = FFMAX(4, AV_RB32(p->buf+offset)) + offset;
7100 /* those are more common words, so rate then a bit less */
7101 case MKTAG('e','d','i','w'): /* xdcam files have reverted first tags */
7102 case MKTAG('w','i','d','e'):
7103 case MKTAG('f','r','e','e'):
7104 case MKTAG('j','u','n','k'):
7105 case MKTAG('p','i','c','t'):
7106 score = FFMAX(score, AVPROBE_SCORE_MAX - 5);
7107 offset = FFMAX(4, AV_RB32(p->buf+offset)) + offset;
7109 case MKTAG(0x82,0x82,0x7f,0x7d):
7110 case MKTAG('s','k','i','p'):
7111 case MKTAG('u','u','i','d'):
7112 case MKTAG('p','r','f','l'):
7113 /* if we only find those cause probedata is too small at least rate them */
7114 score = FFMAX(score, AVPROBE_SCORE_EXTENSION);
7115 offset = FFMAX(4, AV_RB32(p->buf+offset)) + offset;
7118 offset = FFMAX(4, AV_RB32(p->buf+offset)) + offset;
7121 if (score > AVPROBE_SCORE_MAX - 50 && moov_offset != -1) {
7122 /* moov atom in the header - we should make sure that this is not a
7123 * MOV-packed MPEG-PS */
7124 offset = moov_offset;
7126 while (offset < (p->buf_size - 16)) { /* Sufficient space */
7127 /* We found an actual hdlr atom */
7128 if (AV_RL32(p->buf + offset ) == MKTAG('h','d','l','r') &&
7129 AV_RL32(p->buf + offset + 8) == MKTAG('m','h','l','r') &&
7130 AV_RL32(p->buf + offset + 12) == MKTAG('M','P','E','G')) {
7131 av_log(NULL, AV_LOG_WARNING, "Found media data tag MPEG indicating this is a MOV-packed MPEG-PS.\n");
7132 /* We found a media handler reference atom describing an
7133 * MPEG-PS-in-MOV, return a
7134 * low score to force expanding the probe window until
7135 * mpegps_probe finds what it needs */
7147 // must be done after parsing all trak because there's no order requirement
7148 static void mov_read_chapters(AVFormatContext *s)
7150 MOVContext *mov = s->priv_data;
7152 MOVStreamContext *sc;
7157 for (j = 0; j < mov->nb_chapter_tracks; j++) {
7158 chapter_track = mov->chapter_tracks[j];
7160 for (i = 0; i < s->nb_streams; i++)
7161 if (s->streams[i]->id == chapter_track) {
7166 av_log(s, AV_LOG_ERROR, "Referenced QT chapter track not found\n");
7171 cur_pos = avio_tell(sc->pb);
7173 if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
7174 st->disposition |= AV_DISPOSITION_ATTACHED_PIC | AV_DISPOSITION_TIMED_THUMBNAILS;
7175 if (st->nb_index_entries) {
7176 // Retrieve the first frame, if possible
7177 AVIndexEntry *sample = &st->index_entries[0];
7178 if (avio_seek(sc->pb, sample->pos, SEEK_SET) != sample->pos) {
7179 av_log(s, AV_LOG_ERROR, "Failed to retrieve first frame\n");
7183 if (av_get_packet(sc->pb, &st->attached_pic, sample->size) < 0)
7186 st->attached_pic.stream_index = st->index;
7187 st->attached_pic.flags |= AV_PKT_FLAG_KEY;
7190 st->codecpar->codec_type = AVMEDIA_TYPE_DATA;
7191 st->codecpar->codec_id = AV_CODEC_ID_BIN_DATA;
7192 st->discard = AVDISCARD_ALL;
7193 for (i = 0; i < st->nb_index_entries; i++) {
7194 AVIndexEntry *sample = &st->index_entries[i];
7195 int64_t end = i+1 < st->nb_index_entries ? st->index_entries[i+1].timestamp : st->duration;
7200 if (end < sample->timestamp) {
7201 av_log(s, AV_LOG_WARNING, "ignoring stream duration which is shorter than chapters\n");
7202 end = AV_NOPTS_VALUE;
7205 if (avio_seek(sc->pb, sample->pos, SEEK_SET) != sample->pos) {
7206 av_log(s, AV_LOG_ERROR, "Chapter %d not found in file\n", i);
7210 // the first two bytes are the length of the title
7211 len = avio_rb16(sc->pb);
7212 if (len > sample->size-2)
7214 title_len = 2*len + 1;
7215 if (!(title = av_mallocz(title_len)))
7218 // The samples could theoretically be in any encoding if there's an encd
7219 // atom following, but in practice are only utf-8 or utf-16, distinguished
7220 // instead by the presence of a BOM
7224 ch = avio_rb16(sc->pb);
7226 avio_get_str16be(sc->pb, len, title, title_len);
7227 else if (ch == 0xfffe)
7228 avio_get_str16le(sc->pb, len, title, title_len);
7231 if (len == 1 || len == 2)
7234 avio_get_str(sc->pb, INT_MAX, title + 2, len - 1);
7238 avpriv_new_chapter(s, i, st->time_base, sample->timestamp, end, title);
7243 avio_seek(sc->pb, cur_pos, SEEK_SET);
7247 static int parse_timecode_in_framenum_format(AVFormatContext *s, AVStream *st,
7248 uint32_t value, int flags)
7251 char buf[AV_TIMECODE_STR_SIZE];
7252 AVRational rate = st->avg_frame_rate;
7253 int ret = av_timecode_init(&tc, rate, flags, 0, s);
7256 av_dict_set(&st->metadata, "timecode",
7257 av_timecode_make_string(&tc, buf, value), 0);
7261 static int mov_read_rtmd_track(AVFormatContext *s, AVStream *st)
7263 MOVStreamContext *sc = st->priv_data;
7264 char buf[AV_TIMECODE_STR_SIZE];
7265 int64_t cur_pos = avio_tell(sc->pb);
7266 int hh, mm, ss, ff, drop;
7268 if (!st->nb_index_entries)
7271 avio_seek(sc->pb, st->index_entries->pos, SEEK_SET);
7272 avio_skip(s->pb, 13);
7273 hh = avio_r8(s->pb);
7274 mm = avio_r8(s->pb);
7275 ss = avio_r8(s->pb);
7276 drop = avio_r8(s->pb);
7277 ff = avio_r8(s->pb);
7278 snprintf(buf, AV_TIMECODE_STR_SIZE, "%02d:%02d:%02d%c%02d",
7279 hh, mm, ss, drop ? ';' : ':', ff);
7280 av_dict_set(&st->metadata, "timecode", buf, 0);
7282 avio_seek(sc->pb, cur_pos, SEEK_SET);
7286 static int mov_read_timecode_track(AVFormatContext *s, AVStream *st)
7288 MOVStreamContext *sc = st->priv_data;
7290 int64_t cur_pos = avio_tell(sc->pb);
7293 if (!st->nb_index_entries)
7296 avio_seek(sc->pb, st->index_entries->pos, SEEK_SET);
7297 value = avio_rb32(s->pb);
7299 if (sc->tmcd_flags & 0x0001) flags |= AV_TIMECODE_FLAG_DROPFRAME;
7300 if (sc->tmcd_flags & 0x0002) flags |= AV_TIMECODE_FLAG_24HOURSMAX;
7301 if (sc->tmcd_flags & 0x0004) flags |= AV_TIMECODE_FLAG_ALLOWNEGATIVE;
7303 /* Assume Counter flag is set to 1 in tmcd track (even though it is likely
7304 * not the case) and thus assume "frame number format" instead of QT one.
7305 * No sample with tmcd track can be found with a QT timecode at the moment,
7306 * despite what the tmcd track "suggests" (Counter flag set to 0 means QT
7308 parse_timecode_in_framenum_format(s, st, value, flags);
7310 avio_seek(sc->pb, cur_pos, SEEK_SET);
7314 static void mov_free_encryption_index(MOVEncryptionIndex **index) {
7316 if (!index || !*index) return;
7317 for (i = 0; i < (*index)->nb_encrypted_samples; i++) {
7318 av_encryption_info_free((*index)->encrypted_samples[i]);
7320 av_freep(&(*index)->encrypted_samples);
7321 av_freep(&(*index)->auxiliary_info_sizes);
7322 av_freep(&(*index)->auxiliary_offsets);
7326 static int mov_read_close(AVFormatContext *s)
7328 MOVContext *mov = s->priv_data;
7331 for (i = 0; i < s->nb_streams; i++) {
7332 AVStream *st = s->streams[i];
7333 MOVStreamContext *sc = st->priv_data;
7338 av_freep(&sc->ctts_data);
7339 for (j = 0; j < sc->drefs_count; j++) {
7340 av_freep(&sc->drefs[j].path);
7341 av_freep(&sc->drefs[j].dir);
7343 av_freep(&sc->drefs);
7345 sc->drefs_count = 0;
7347 if (!sc->pb_is_copied)
7348 ff_format_io_close(s, &sc->pb);
7351 av_freep(&sc->chunk_offsets);
7352 av_freep(&sc->stsc_data);
7353 av_freep(&sc->sample_sizes);
7354 av_freep(&sc->keyframes);
7355 av_freep(&sc->stts_data);
7356 av_freep(&sc->sdtp_data);
7357 av_freep(&sc->stps_data);
7358 av_freep(&sc->elst_data);
7359 av_freep(&sc->rap_group);
7360 av_freep(&sc->display_matrix);
7361 av_freep(&sc->index_ranges);
7364 for (j = 0; j < sc->stsd_count; j++)
7365 av_free(sc->extradata[j]);
7366 av_freep(&sc->extradata);
7367 av_freep(&sc->extradata_size);
7369 mov_free_encryption_index(&sc->cenc.encryption_index);
7370 av_encryption_info_free(sc->cenc.default_encrypted_sample);
7371 av_aes_ctr_free(sc->cenc.aes_ctr);
7373 av_freep(&sc->stereo3d);
7374 av_freep(&sc->spherical);
7375 av_freep(&sc->mastering);
7376 av_freep(&sc->coll);
7379 av_freep(&mov->dv_demux);
7380 avformat_free_context(mov->dv_fctx);
7381 mov->dv_fctx = NULL;
7383 if (mov->meta_keys) {
7384 for (i = 1; i < mov->meta_keys_count; i++) {
7385 av_freep(&mov->meta_keys[i]);
7387 av_freep(&mov->meta_keys);
7390 av_freep(&mov->trex_data);
7391 av_freep(&mov->bitrates);
7393 for (i = 0; i < mov->frag_index.nb_items; i++) {
7394 MOVFragmentStreamInfo *frag = mov->frag_index.item[i].stream_info;
7395 for (j = 0; j < mov->frag_index.item[i].nb_stream_info; j++) {
7396 mov_free_encryption_index(&frag[j].encryption_index);
7398 av_freep(&mov->frag_index.item[i].stream_info);
7400 av_freep(&mov->frag_index.item);
7402 av_freep(&mov->aes_decrypt);
7403 av_freep(&mov->chapter_tracks);
7408 static int tmcd_is_referenced(AVFormatContext *s, int tmcd_id)
7412 for (i = 0; i < s->nb_streams; i++) {
7413 AVStream *st = s->streams[i];
7414 MOVStreamContext *sc = st->priv_data;
7416 if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO &&
7417 sc->timecode_track == tmcd_id)
7423 /* look for a tmcd track not referenced by any video track, and export it globally */
7424 static void export_orphan_timecode(AVFormatContext *s)
7428 for (i = 0; i < s->nb_streams; i++) {
7429 AVStream *st = s->streams[i];
7431 if (st->codecpar->codec_tag == MKTAG('t','m','c','d') &&
7432 !tmcd_is_referenced(s, i + 1)) {
7433 AVDictionaryEntry *tcr = av_dict_get(st->metadata, "timecode", NULL, 0);
7435 av_dict_set(&s->metadata, "timecode", tcr->value, 0);
7442 static int read_tfra(MOVContext *mov, AVIOContext *f)
7444 int version, fieldlength, i, j;
7445 int64_t pos = avio_tell(f);
7446 uint32_t size = avio_rb32(f);
7447 unsigned track_id, item_count;
7449 if (avio_rb32(f) != MKBETAG('t', 'f', 'r', 'a')) {
7452 av_log(mov->fc, AV_LOG_VERBOSE, "found tfra\n");
7454 version = avio_r8(f);
7456 track_id = avio_rb32(f);
7457 fieldlength = avio_rb32(f);
7458 item_count = avio_rb32(f);
7459 for (i = 0; i < item_count; i++) {
7460 int64_t time, offset;
7462 MOVFragmentStreamInfo * frag_stream_info;
7465 return AVERROR_INVALIDDATA;
7469 time = avio_rb64(f);
7470 offset = avio_rb64(f);
7472 time = avio_rb32(f);
7473 offset = avio_rb32(f);
7476 // The first sample of each stream in a fragment is always a random
7477 // access sample. So it's entry in the tfra can be used as the
7478 // initial PTS of the fragment.
7479 index = update_frag_index(mov, offset);
7480 frag_stream_info = get_frag_stream_info(&mov->frag_index, index, track_id);
7481 if (frag_stream_info &&
7482 frag_stream_info->first_tfra_pts == AV_NOPTS_VALUE)
7483 frag_stream_info->first_tfra_pts = time;
7485 for (j = 0; j < ((fieldlength >> 4) & 3) + 1; j++)
7487 for (j = 0; j < ((fieldlength >> 2) & 3) + 1; j++)
7489 for (j = 0; j < ((fieldlength >> 0) & 3) + 1; j++)
7493 avio_seek(f, pos + size, SEEK_SET);
7497 static int mov_read_mfra(MOVContext *c, AVIOContext *f)
7499 int64_t stream_size = avio_size(f);
7500 int64_t original_pos = avio_tell(f);
7503 if ((seek_ret = avio_seek(f, stream_size - 4, SEEK_SET)) < 0) {
7507 c->mfra_size = avio_rb32(f);
7508 c->have_read_mfra_size = 1;
7509 if (!c->mfra_size || c->mfra_size > stream_size) {
7510 av_log(c->fc, AV_LOG_DEBUG, "doesn't look like mfra (unreasonable size)\n");
7513 if ((seek_ret = avio_seek(f, -((int64_t) c->mfra_size), SEEK_CUR)) < 0) {
7517 if (avio_rb32(f) != c->mfra_size) {
7518 av_log(c->fc, AV_LOG_DEBUG, "doesn't look like mfra (size mismatch)\n");
7521 if (avio_rb32(f) != MKBETAG('m', 'f', 'r', 'a')) {
7522 av_log(c->fc, AV_LOG_DEBUG, "doesn't look like mfra (tag mismatch)\n");
7525 av_log(c->fc, AV_LOG_VERBOSE, "stream has mfra\n");
7527 ret = read_tfra(c, f);
7532 c->frag_index.complete = 1;
7534 seek_ret = avio_seek(f, original_pos, SEEK_SET);
7536 av_log(c->fc, AV_LOG_ERROR,
7537 "failed to seek back after looking for mfra\n");
7543 static int mov_read_header(AVFormatContext *s)
7545 MOVContext *mov = s->priv_data;
7546 AVIOContext *pb = s->pb;
7548 MOVAtom atom = { AV_RL32("root") };
7551 if (mov->decryption_key_len != 0 && mov->decryption_key_len != AES_CTR_KEY_SIZE) {
7552 av_log(s, AV_LOG_ERROR, "Invalid decryption key len %d expected %d\n",
7553 mov->decryption_key_len, AES_CTR_KEY_SIZE);
7554 return AVERROR(EINVAL);
7558 mov->trak_index = -1;
7559 /* .mov and .mp4 aren't streamable anyway (only progressive download if moov is before mdat) */
7560 if (pb->seekable & AVIO_SEEKABLE_NORMAL)
7561 atom.size = avio_size(pb);
7563 atom.size = INT64_MAX;
7565 /* check MOV header */
7567 if (mov->moov_retry)
7568 avio_seek(pb, 0, SEEK_SET);
7569 if ((err = mov_read_default(mov, pb, atom)) < 0) {
7570 av_log(s, AV_LOG_ERROR, "error reading header\n");
7573 } while ((pb->seekable & AVIO_SEEKABLE_NORMAL) && !mov->found_moov && !mov->moov_retry++);
7574 if (!mov->found_moov) {
7575 av_log(s, AV_LOG_ERROR, "moov atom not found\n");
7576 err = AVERROR_INVALIDDATA;
7579 av_log(mov->fc, AV_LOG_TRACE, "on_parse_exit_offset=%"PRId64"\n", avio_tell(pb));
7581 if (pb->seekable & AVIO_SEEKABLE_NORMAL) {
7582 if (mov->nb_chapter_tracks > 0 && !mov->ignore_chapters)
7583 mov_read_chapters(s);
7584 for (i = 0; i < s->nb_streams; i++)
7585 if (s->streams[i]->codecpar->codec_tag == AV_RL32("tmcd")) {
7586 mov_read_timecode_track(s, s->streams[i]);
7587 } else if (s->streams[i]->codecpar->codec_tag == AV_RL32("rtmd")) {
7588 mov_read_rtmd_track(s, s->streams[i]);
7592 /* copy timecode metadata from tmcd tracks to the related video streams */
7593 for (i = 0; i < s->nb_streams; i++) {
7594 AVStream *st = s->streams[i];
7595 MOVStreamContext *sc = st->priv_data;
7596 if (sc->timecode_track > 0) {
7597 AVDictionaryEntry *tcr;
7598 int tmcd_st_id = -1;
7600 for (j = 0; j < s->nb_streams; j++)
7601 if (s->streams[j]->id == sc->timecode_track)
7604 if (tmcd_st_id < 0 || tmcd_st_id == i)
7606 tcr = av_dict_get(s->streams[tmcd_st_id]->metadata, "timecode", NULL, 0);
7608 av_dict_set(&st->metadata, "timecode", tcr->value, 0);
7611 export_orphan_timecode(s);
7613 for (i = 0; i < s->nb_streams; i++) {
7614 AVStream *st = s->streams[i];
7615 MOVStreamContext *sc = st->priv_data;
7616 fix_timescale(mov, sc);
7617 if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO &&
7618 st->codecpar->codec_id == AV_CODEC_ID_AAC) {
7619 st->internal->skip_samples = sc->start_pad;
7621 if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && sc->nb_frames_for_fps > 0 && sc->duration_for_fps > 0)
7622 av_reduce(&st->avg_frame_rate.num, &st->avg_frame_rate.den,
7623 sc->time_scale*(int64_t)sc->nb_frames_for_fps, sc->duration_for_fps, INT_MAX);
7624 if (st->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE) {
7625 if (st->codecpar->width <= 0 || st->codecpar->height <= 0) {
7626 st->codecpar->width = sc->width;
7627 st->codecpar->height = sc->height;
7629 if (st->codecpar->codec_id == AV_CODEC_ID_DVD_SUBTITLE) {
7630 if ((err = mov_rewrite_dvd_sub_extradata(st)) < 0)
7634 if (mov->handbrake_version &&
7635 mov->handbrake_version <= 1000000*0 + 1000*10 + 2 && // 0.10.2
7636 st->codecpar->codec_id == AV_CODEC_ID_MP3) {
7637 av_log(s, AV_LOG_VERBOSE, "Forcing full parsing for mp3 stream\n");
7638 st->need_parsing = AVSTREAM_PARSE_FULL;
7642 if (mov->trex_data) {
7643 for (i = 0; i < s->nb_streams; i++) {
7644 AVStream *st = s->streams[i];
7645 MOVStreamContext *sc = st->priv_data;
7646 if (st->duration > 0) {
7647 if (sc->data_size > INT64_MAX / sc->time_scale / 8) {
7648 av_log(s, AV_LOG_ERROR, "Overflow during bit rate calculation %"PRId64" * 8 * %d\n",
7649 sc->data_size, sc->time_scale);
7650 err = AVERROR_INVALIDDATA;
7653 st->codecpar->bit_rate = sc->data_size * 8 * sc->time_scale / st->duration;
7658 if (mov->use_mfra_for > 0) {
7659 for (i = 0; i < s->nb_streams; i++) {
7660 AVStream *st = s->streams[i];
7661 MOVStreamContext *sc = st->priv_data;
7662 if (sc->duration_for_fps > 0) {
7663 if (sc->data_size > INT64_MAX / sc->time_scale / 8) {
7664 av_log(s, AV_LOG_ERROR, "Overflow during bit rate calculation %"PRId64" * 8 * %d\n",
7665 sc->data_size, sc->time_scale);
7666 err = AVERROR_INVALIDDATA;
7669 st->codecpar->bit_rate = sc->data_size * 8 * sc->time_scale /
7670 sc->duration_for_fps;
7675 for (i = 0; i < mov->bitrates_count && i < s->nb_streams; i++) {
7676 if (mov->bitrates[i]) {
7677 s->streams[i]->codecpar->bit_rate = mov->bitrates[i];
7681 ff_rfps_calculate(s);
7683 for (i = 0; i < s->nb_streams; i++) {
7684 AVStream *st = s->streams[i];
7685 MOVStreamContext *sc = st->priv_data;
7687 switch (st->codecpar->codec_type) {
7688 case AVMEDIA_TYPE_AUDIO:
7689 err = ff_replaygain_export(st, s->metadata);
7693 case AVMEDIA_TYPE_VIDEO:
7694 if (sc->display_matrix) {
7695 err = av_stream_add_side_data(st, AV_PKT_DATA_DISPLAYMATRIX, (uint8_t*)sc->display_matrix,
7696 sizeof(int32_t) * 9);
7700 sc->display_matrix = NULL;
7703 err = av_stream_add_side_data(st, AV_PKT_DATA_STEREO3D,
7704 (uint8_t *)sc->stereo3d,
7705 sizeof(*sc->stereo3d));
7709 sc->stereo3d = NULL;
7711 if (sc->spherical) {
7712 err = av_stream_add_side_data(st, AV_PKT_DATA_SPHERICAL,
7713 (uint8_t *)sc->spherical,
7714 sc->spherical_size);
7718 sc->spherical = NULL;
7720 if (sc->mastering) {
7721 err = av_stream_add_side_data(st, AV_PKT_DATA_MASTERING_DISPLAY_METADATA,
7722 (uint8_t *)sc->mastering,
7723 sizeof(*sc->mastering));
7727 sc->mastering = NULL;
7730 err = av_stream_add_side_data(st, AV_PKT_DATA_CONTENT_LIGHT_LEVEL,
7731 (uint8_t *)sc->coll,
7741 ff_configure_buffers_for_index(s, AV_TIME_BASE);
7743 for (i = 0; i < mov->frag_index.nb_items; i++)
7744 if (mov->frag_index.item[i].moof_offset <= mov->fragment.moof_offset)
7745 mov->frag_index.item[i].headers_read = 1;
7753 static AVIndexEntry *mov_find_next_sample(AVFormatContext *s, AVStream **st)
7755 AVIndexEntry *sample = NULL;
7756 int64_t best_dts = INT64_MAX;
7758 for (i = 0; i < s->nb_streams; i++) {
7759 AVStream *avst = s->streams[i];
7760 MOVStreamContext *msc = avst->priv_data;
7761 if (msc->pb && msc->current_sample < avst->nb_index_entries) {
7762 AVIndexEntry *current_sample = &avst->index_entries[msc->current_sample];
7763 int64_t dts = av_rescale(current_sample->timestamp, AV_TIME_BASE, msc->time_scale);
7764 av_log(s, AV_LOG_TRACE, "stream %d, sample %d, dts %"PRId64"\n", i, msc->current_sample, dts);
7765 if (!sample || (!(s->pb->seekable & AVIO_SEEKABLE_NORMAL) && current_sample->pos < sample->pos) ||
7766 ((s->pb->seekable & AVIO_SEEKABLE_NORMAL) &&
7767 ((msc->pb != s->pb && dts < best_dts) || (msc->pb == s->pb && dts != AV_NOPTS_VALUE &&
7768 ((FFABS(best_dts - dts) <= AV_TIME_BASE && current_sample->pos < sample->pos) ||
7769 (FFABS(best_dts - dts) > AV_TIME_BASE && dts < best_dts)))))) {
7770 sample = current_sample;
7779 static int should_retry(AVIOContext *pb, int error_code) {
7780 if (error_code == AVERROR_EOF || avio_feof(pb))
7786 static int mov_switch_root(AVFormatContext *s, int64_t target, int index)
7789 MOVContext *mov = s->priv_data;
7791 if (index >= 0 && index < mov->frag_index.nb_items)
7792 target = mov->frag_index.item[index].moof_offset;
7793 if (avio_seek(s->pb, target, SEEK_SET) != target) {
7794 av_log(mov->fc, AV_LOG_ERROR, "root atom offset 0x%"PRIx64": partial file\n", target);
7795 return AVERROR_INVALIDDATA;
7798 mov->next_root_atom = 0;
7799 if (index < 0 || index >= mov->frag_index.nb_items)
7800 index = search_frag_moof_offset(&mov->frag_index, target);
7801 if (index < mov->frag_index.nb_items &&
7802 mov->frag_index.item[index].moof_offset == target) {
7803 if (index + 1 < mov->frag_index.nb_items)
7804 mov->next_root_atom = mov->frag_index.item[index + 1].moof_offset;
7805 if (mov->frag_index.item[index].headers_read)
7807 mov->frag_index.item[index].headers_read = 1;
7810 mov->found_mdat = 0;
7812 ret = mov_read_default(mov, s->pb, (MOVAtom){ AV_RL32("root"), INT64_MAX });
7815 if (avio_feof(s->pb))
7817 av_log(s, AV_LOG_TRACE, "read fragments, offset 0x%"PRIx64"\n", avio_tell(s->pb));
7822 static int mov_change_extradata(MOVStreamContext *sc, AVPacket *pkt)
7824 uint8_t *side, *extradata;
7827 /* Save the current index. */
7828 sc->last_stsd_index = sc->stsc_data[sc->stsc_index].id - 1;
7830 /* Notify the decoder that extradata changed. */
7831 extradata_size = sc->extradata_size[sc->last_stsd_index];
7832 extradata = sc->extradata[sc->last_stsd_index];
7833 if (extradata_size > 0 && extradata) {
7834 side = av_packet_new_side_data(pkt,
7835 AV_PKT_DATA_NEW_EXTRADATA,
7838 return AVERROR(ENOMEM);
7839 memcpy(side, extradata, extradata_size);
7845 static int get_eia608_packet(AVIOContext *pb, AVPacket *pkt, int size)
7850 return AVERROR_INVALIDDATA;
7851 new_size = ((size - 8) / 2) * 3;
7852 ret = av_new_packet(pkt, new_size);
7857 for (int j = 0; j < new_size; j += 3) {
7858 pkt->data[j] = 0xFC;
7859 pkt->data[j+1] = avio_r8(pb);
7860 pkt->data[j+2] = avio_r8(pb);
7866 static int mov_read_packet(AVFormatContext *s, AVPacket *pkt)
7868 MOVContext *mov = s->priv_data;
7869 MOVStreamContext *sc;
7870 AVIndexEntry *sample;
7871 AVStream *st = NULL;
7872 int64_t current_index;
7876 sample = mov_find_next_sample(s, &st);
7877 if (!sample || (mov->next_root_atom && sample->pos > mov->next_root_atom)) {
7878 if (!mov->next_root_atom)
7880 if ((ret = mov_switch_root(s, mov->next_root_atom, -1)) < 0)
7885 /* must be done just before reading, to avoid infinite loop on sample */
7886 current_index = sc->current_index;
7887 mov_current_sample_inc(sc);
7889 if (mov->next_root_atom) {
7890 sample->pos = FFMIN(sample->pos, mov->next_root_atom);
7891 sample->size = FFMIN(sample->size, (mov->next_root_atom - sample->pos));
7894 if (st->discard != AVDISCARD_ALL) {
7895 int64_t ret64 = avio_seek(sc->pb, sample->pos, SEEK_SET);
7896 if (ret64 != sample->pos) {
7897 av_log(mov->fc, AV_LOG_ERROR, "stream %d, offset 0x%"PRIx64": partial file\n",
7898 sc->ffindex, sample->pos);
7899 if (should_retry(sc->pb, ret64)) {
7900 mov_current_sample_dec(sc);
7902 return AVERROR_INVALIDDATA;
7905 if (st->discard == AVDISCARD_NONKEY && !(sample->flags & AVINDEX_KEYFRAME)) {
7906 av_log(mov->fc, AV_LOG_DEBUG, "Nonkey frame from stream %d discarded due to AVDISCARD_NONKEY\n", sc->ffindex);
7910 if (st->codecpar->codec_id == AV_CODEC_ID_EIA_608 && sample->size > 8)
7911 ret = get_eia608_packet(sc->pb, pkt, sample->size);
7913 ret = av_get_packet(sc->pb, pkt, sample->size);
7915 if (should_retry(sc->pb, ret)) {
7916 mov_current_sample_dec(sc);
7920 #if CONFIG_DV_DEMUXER
7921 if (mov->dv_demux && sc->dv_audio_container) {
7922 AVBufferRef *buf = pkt->buf;
7923 ret = avpriv_dv_produce_packet(mov->dv_demux, pkt, pkt->data, pkt->size, pkt->pos);
7925 av_packet_unref(pkt);
7928 ret = avpriv_dv_get_packet(mov->dv_demux, pkt);
7933 if (sc->has_palette) {
7936 pal = av_packet_new_side_data(pkt, AV_PKT_DATA_PALETTE, AVPALETTE_SIZE);
7938 av_log(mov->fc, AV_LOG_ERROR, "Cannot append palette to packet\n");
7940 memcpy(pal, sc->palette, AVPALETTE_SIZE);
7941 sc->has_palette = 0;
7944 if (st->codecpar->codec_id == AV_CODEC_ID_MP3 && !st->need_parsing && pkt->size > 4) {
7945 if (ff_mpa_check_header(AV_RB32(pkt->data)) < 0)
7946 st->need_parsing = AVSTREAM_PARSE_FULL;
7950 pkt->stream_index = sc->ffindex;
7951 pkt->dts = sample->timestamp;
7952 if (sample->flags & AVINDEX_DISCARD_FRAME) {
7953 pkt->flags |= AV_PKT_FLAG_DISCARD;
7955 if (sc->ctts_data && sc->ctts_index < sc->ctts_count) {
7956 pkt->pts = pkt->dts + sc->dts_shift + sc->ctts_data[sc->ctts_index].duration;
7957 /* update ctts context */
7959 if (sc->ctts_index < sc->ctts_count &&
7960 sc->ctts_data[sc->ctts_index].count == sc->ctts_sample) {
7962 sc->ctts_sample = 0;
7965 int64_t next_dts = (sc->current_sample < st->nb_index_entries) ?
7966 st->index_entries[sc->current_sample].timestamp : st->duration;
7968 if (next_dts >= pkt->dts)
7969 pkt->duration = next_dts - pkt->dts;
7970 pkt->pts = pkt->dts;
7972 if (st->discard == AVDISCARD_ALL)
7974 if (sc->sdtp_data && sc->current_sample <= sc->sdtp_count) {
7975 uint8_t sample_flags = sc->sdtp_data[sc->current_sample - 1];
7976 uint8_t sample_is_depended_on = (sample_flags >> 2) & 0x3;
7977 pkt->flags |= sample_is_depended_on == MOV_SAMPLE_DEPENDENCY_NO ? AV_PKT_FLAG_DISPOSABLE : 0;
7979 pkt->flags |= sample->flags & AVINDEX_KEYFRAME ? AV_PKT_FLAG_KEY : 0;
7980 pkt->pos = sample->pos;
7982 /* Multiple stsd handling. */
7983 if (sc->stsc_data) {
7984 /* Keep track of the stsc index for the given sample, then check
7985 * if the stsd index is different from the last used one. */
7987 if (mov_stsc_index_valid(sc->stsc_index, sc->stsc_count) &&
7988 mov_get_stsc_samples(sc, sc->stsc_index) == sc->stsc_sample) {
7990 sc->stsc_sample = 0;
7991 /* Do not check indexes after a switch. */
7992 } else if (sc->stsc_data[sc->stsc_index].id > 0 &&
7993 sc->stsc_data[sc->stsc_index].id - 1 < sc->stsd_count &&
7994 sc->stsc_data[sc->stsc_index].id - 1 != sc->last_stsd_index) {
7995 ret = mov_change_extradata(sc, pkt);
8002 aax_filter(pkt->data, pkt->size, mov);
8004 ret = cenc_filter(mov, st, sc, pkt, current_index);
8012 static int mov_seek_fragment(AVFormatContext *s, AVStream *st, int64_t timestamp)
8014 MOVContext *mov = s->priv_data;
8017 if (!mov->frag_index.complete)
8020 index = search_frag_timestamp(&mov->frag_index, st, timestamp);
8023 if (!mov->frag_index.item[index].headers_read)
8024 return mov_switch_root(s, -1, index);
8025 if (index + 1 < mov->frag_index.nb_items)
8026 mov->next_root_atom = mov->frag_index.item[index + 1].moof_offset;
8031 static int mov_seek_stream(AVFormatContext *s, AVStream *st, int64_t timestamp, int flags)
8033 MOVStreamContext *sc = st->priv_data;
8034 int sample, time_sample, ret;
8037 // Here we consider timestamp to be PTS, hence try to offset it so that we
8038 // can search over the DTS timeline.
8039 timestamp -= (sc->min_corrected_pts + sc->dts_shift);
8041 ret = mov_seek_fragment(s, st, timestamp);
8045 sample = av_index_search_timestamp(st, timestamp, flags);
8046 av_log(s, AV_LOG_TRACE, "stream %d, timestamp %"PRId64", sample %d\n", st->index, timestamp, sample);
8047 if (sample < 0 && st->nb_index_entries && timestamp < st->index_entries[0].timestamp)
8049 if (sample < 0) /* not sure what to do */
8050 return AVERROR_INVALIDDATA;
8051 mov_current_sample_set(sc, sample);
8052 av_log(s, AV_LOG_TRACE, "stream %d, found sample %d\n", st->index, sc->current_sample);
8053 /* adjust ctts index */
8054 if (sc->ctts_data) {
8056 for (i = 0; i < sc->ctts_count; i++) {
8057 int next = time_sample + sc->ctts_data[i].count;
8058 if (next > sc->current_sample) {
8060 sc->ctts_sample = sc->current_sample - time_sample;
8067 /* adjust stsd index */
8068 if (sc->chunk_count) {
8070 for (i = 0; i < sc->stsc_count; i++) {
8071 int64_t next = time_sample + mov_get_stsc_samples(sc, i);
8072 if (next > sc->current_sample) {
8074 sc->stsc_sample = sc->current_sample - time_sample;
8077 av_assert0(next == (int)next);
8085 static int mov_read_seek(AVFormatContext *s, int stream_index, int64_t sample_time, int flags)
8087 MOVContext *mc = s->priv_data;
8092 if (stream_index >= s->nb_streams)
8093 return AVERROR_INVALIDDATA;
8095 st = s->streams[stream_index];
8096 sample = mov_seek_stream(s, st, sample_time, flags);
8100 if (mc->seek_individually) {
8101 /* adjust seek timestamp to found sample timestamp */
8102 int64_t seek_timestamp = st->index_entries[sample].timestamp;
8104 for (i = 0; i < s->nb_streams; i++) {
8106 MOVStreamContext *sc = s->streams[i]->priv_data;
8108 st->internal->skip_samples = (sample_time <= 0) ? sc->start_pad : 0;
8110 if (stream_index == i)
8113 timestamp = av_rescale_q(seek_timestamp, s->streams[stream_index]->time_base, st->time_base);
8114 mov_seek_stream(s, st, timestamp, flags);
8117 for (i = 0; i < s->nb_streams; i++) {
8118 MOVStreamContext *sc;
8121 mov_current_sample_set(sc, 0);
8124 MOVStreamContext *sc;
8125 AVIndexEntry *entry = mov_find_next_sample(s, &st);
8127 return AVERROR_INVALIDDATA;
8129 if (sc->ffindex == stream_index && sc->current_sample == sample)
8131 mov_current_sample_inc(sc);
8137 #define OFFSET(x) offsetof(MOVContext, x)
8138 #define FLAGS AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_DECODING_PARAM
8139 static const AVOption mov_options[] = {
8140 {"use_absolute_path",
8141 "allow using absolute path when opening alias, this is a possible security issue",
8142 OFFSET(use_absolute_path), AV_OPT_TYPE_BOOL, {.i64 = 0},
8144 {"seek_streams_individually",
8145 "Seek each stream individually to the closest point",
8146 OFFSET(seek_individually), AV_OPT_TYPE_BOOL, { .i64 = 1 },
8148 {"ignore_editlist", "Ignore the edit list atom.", OFFSET(ignore_editlist), AV_OPT_TYPE_BOOL, {.i64 = 0},
8150 {"advanced_editlist",
8151 "Modify the AVIndex according to the editlists. Use this option to decode in the order specified by the edits.",
8152 OFFSET(advanced_editlist), AV_OPT_TYPE_BOOL, {.i64 = 1},
8154 {"ignore_chapters", "", OFFSET(ignore_chapters), AV_OPT_TYPE_BOOL, {.i64 = 0},
8157 "use mfra for fragment timestamps",
8158 OFFSET(use_mfra_for), AV_OPT_TYPE_INT, {.i64 = FF_MOV_FLAG_MFRA_AUTO},
8159 -1, FF_MOV_FLAG_MFRA_PTS, FLAGS,
8161 {"auto", "auto", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_MFRA_AUTO}, 0, 0,
8162 FLAGS, "use_mfra_for" },
8163 {"dts", "dts", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_MFRA_DTS}, 0, 0,
8164 FLAGS, "use_mfra_for" },
8165 {"pts", "pts", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_MFRA_PTS}, 0, 0,
8166 FLAGS, "use_mfra_for" },
8167 { "export_all", "Export unrecognized metadata entries", OFFSET(export_all),
8168 AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, .flags = FLAGS },
8169 { "export_xmp", "Export full XMP metadata", OFFSET(export_xmp),
8170 AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, .flags = FLAGS },
8171 { "activation_bytes", "Secret bytes for Audible AAX files", OFFSET(activation_bytes),
8172 AV_OPT_TYPE_BINARY, .flags = AV_OPT_FLAG_DECODING_PARAM },
8173 { "audible_fixed_key", // extracted from libAAX_SDK.so and AAXSDKWin.dll files!
8174 "Fixed key used for handling Audible AAX files", OFFSET(audible_fixed_key),
8175 AV_OPT_TYPE_BINARY, {.str="77214d4b196a87cd520045fd20a51d67"},
8176 .flags = AV_OPT_FLAG_DECODING_PARAM },
8177 { "decryption_key", "The media decryption key (hex)", OFFSET(decryption_key), AV_OPT_TYPE_BINARY, .flags = AV_OPT_FLAG_DECODING_PARAM },
8178 { "enable_drefs", "Enable external track support.", OFFSET(enable_drefs), AV_OPT_TYPE_BOOL,
8179 {.i64 = 0}, 0, 1, FLAGS },
8184 static const AVClass mov_class = {
8185 .class_name = "mov,mp4,m4a,3gp,3g2,mj2",
8186 .item_name = av_default_item_name,
8187 .option = mov_options,
8188 .version = LIBAVUTIL_VERSION_INT,
8191 AVInputFormat ff_mov_demuxer = {
8192 .name = "mov,mp4,m4a,3gp,3g2,mj2",
8193 .long_name = NULL_IF_CONFIG_SMALL("QuickTime / MOV"),
8194 .priv_class = &mov_class,
8195 .priv_data_size = sizeof(MOVContext),
8196 .extensions = "mov,mp4,m4a,3gp,3g2,mj2,psp,m4b,ism,ismv,isma,f4v",
8197 .read_probe = mov_probe,
8198 .read_header = mov_read_header,
8199 .read_packet = mov_read_packet,
8200 .read_close = mov_read_close,
8201 .read_seek = mov_read_seek,
8202 .flags = AVFMT_NO_BYTE_SEEK | AVFMT_SEEK_TO_PTS,