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)
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 snprintf(tmp_key, 5, "%.4s", (char*)&atom.type);
453 if (atom.size < 0 || str_size >= INT_MAX/2)
454 return AVERROR_INVALIDDATA;
456 // Allocates enough space if data_type is a int32 or float32 number, otherwise
457 // worst-case requirement for output string in case of utf8 coded input
458 num = (data_type >= 21 && data_type <= 23);
459 str_size_alloc = (num ? 512 : (raw ? str_size : str_size * 2)) + 1;
460 str = av_mallocz(str_size_alloc);
462 return AVERROR(ENOMEM);
465 parse(c, pb, str_size, key);
467 if (!raw && (data_type == 3 || (data_type == 0 && (langcode < 0x400 || langcode == 0x7fff)))) { // MAC Encoded
468 mov_read_mac_string(c, pb, str_size, str, str_size_alloc);
469 } else if (data_type == 21) { // BE signed integer, variable size
472 val = (int8_t)avio_r8(pb);
473 else if (str_size == 2)
474 val = (int16_t)avio_rb16(pb);
475 else if (str_size == 3)
476 val = ((int32_t)(avio_rb24(pb)<<8))>>8;
477 else if (str_size == 4)
478 val = (int32_t)avio_rb32(pb);
479 if (snprintf(str, str_size_alloc, "%d", val) >= str_size_alloc) {
480 av_log(c->fc, AV_LOG_ERROR,
481 "Failed to store the number (%d) in string.\n", val);
483 return AVERROR_INVALIDDATA;
485 } else if (data_type == 22) { // BE unsigned integer, variable size
486 unsigned int val = 0;
489 else if (str_size == 2)
491 else if (str_size == 3)
493 else if (str_size == 4)
495 if (snprintf(str, str_size_alloc, "%u", val) >= str_size_alloc) {
496 av_log(c->fc, AV_LOG_ERROR,
497 "Failed to store the number (%u) in string.\n", val);
499 return AVERROR_INVALIDDATA;
501 } else if (data_type == 23 && str_size >= 4) { // BE float32
502 float val = av_int2float(avio_rb32(pb));
503 if (snprintf(str, str_size_alloc, "%f", val) >= str_size_alloc) {
504 av_log(c->fc, AV_LOG_ERROR,
505 "Failed to store the float32 number (%f) in string.\n", val);
507 return AVERROR_INVALIDDATA;
510 int ret = ffio_read_size(pb, str, str_size);
517 c->fc->event_flags |= AVFMT_EVENT_FLAG_METADATA_UPDATED;
518 av_dict_set(&c->fc->metadata, key, str, 0);
519 if (*language && strcmp(language, "und")) {
520 snprintf(key2, sizeof(key2), "%s-%s", key, language);
521 av_dict_set(&c->fc->metadata, key2, str, 0);
523 if (!strcmp(key, "encoder")) {
524 int major, minor, micro;
525 if (sscanf(str, "HandBrake %d.%d.%d", &major, &minor, µ) == 3) {
526 c->handbrake_version = 1000000*major + 1000*minor + micro;
535 static int mov_read_chpl(MOVContext *c, AVIOContext *pb, MOVAtom atom)
538 int i, nb_chapters, str_len, version;
542 if (c->ignore_chapters)
545 if ((atom.size -= 5) < 0)
548 version = avio_r8(pb);
551 avio_rb32(pb); // ???
552 nb_chapters = avio_r8(pb);
554 for (i = 0; i < nb_chapters; i++) {
558 start = avio_rb64(pb);
559 str_len = avio_r8(pb);
561 if ((atom.size -= 9+str_len) < 0)
564 ret = ffio_read_size(pb, str, str_len);
568 avpriv_new_chapter(c->fc, i, (AVRational){1,10000000}, start, AV_NOPTS_VALUE, str);
573 #define MIN_DATA_ENTRY_BOX_SIZE 12
574 static int mov_read_dref(MOVContext *c, AVIOContext *pb, MOVAtom atom)
577 MOVStreamContext *sc;
580 if (c->fc->nb_streams < 1)
582 st = c->fc->streams[c->fc->nb_streams-1];
585 avio_rb32(pb); // version + flags
586 entries = avio_rb32(pb);
588 entries > (atom.size - 1) / MIN_DATA_ENTRY_BOX_SIZE + 1 ||
589 entries >= UINT_MAX / sizeof(*sc->drefs))
590 return AVERROR_INVALIDDATA;
594 sc->drefs = av_mallocz(entries * sizeof(*sc->drefs));
596 return AVERROR(ENOMEM);
597 sc->drefs_count = entries;
599 for (i = 0; i < entries; i++) {
600 MOVDref *dref = &sc->drefs[i];
601 uint32_t size = avio_rb32(pb);
602 int64_t next = avio_tell(pb) + size - 4;
605 return AVERROR_INVALIDDATA;
607 dref->type = avio_rl32(pb);
608 avio_rb32(pb); // version + flags
610 if (dref->type == MKTAG('a','l','i','s') && size > 150) {
611 /* macintosh alias record */
612 uint16_t volume_len, len;
618 volume_len = avio_r8(pb);
619 volume_len = FFMIN(volume_len, 27);
620 ret = ffio_read_size(pb, dref->volume, 27);
623 dref->volume[volume_len] = 0;
624 av_log(c->fc, AV_LOG_DEBUG, "volume %s, len %d\n", dref->volume, volume_len);
629 len = FFMIN(len, 63);
630 ret = ffio_read_size(pb, dref->filename, 63);
633 dref->filename[len] = 0;
634 av_log(c->fc, AV_LOG_DEBUG, "filename %s, len %d\n", dref->filename, len);
638 /* read next level up_from_alias/down_to_target */
639 dref->nlvl_from = avio_rb16(pb);
640 dref->nlvl_to = avio_rb16(pb);
641 av_log(c->fc, AV_LOG_DEBUG, "nlvl from %d, nlvl to %d\n",
642 dref->nlvl_from, dref->nlvl_to);
646 for (type = 0; type != -1 && avio_tell(pb) < next; ) {
649 type = avio_rb16(pb);
651 av_log(c->fc, AV_LOG_DEBUG, "type %d, len %d\n", type, len);
654 if (type == 2) { // absolute path
656 dref->path = av_mallocz(len+1);
658 return AVERROR(ENOMEM);
660 ret = ffio_read_size(pb, dref->path, len);
662 av_freep(&dref->path);
665 if (len > volume_len && !strncmp(dref->path, dref->volume, volume_len)) {
667 memmove(dref->path, dref->path+volume_len, len);
670 // trim string of any ending zeros
671 for (j = len - 1; j >= 0; j--) {
672 if (dref->path[j] == 0)
677 for (j = 0; j < len; j++)
678 if (dref->path[j] == ':' || dref->path[j] == 0)
680 av_log(c->fc, AV_LOG_DEBUG, "path %s\n", dref->path);
681 } else if (type == 0) { // directory name
683 dref->dir = av_malloc(len+1);
685 return AVERROR(ENOMEM);
687 ret = ffio_read_size(pb, dref->dir, len);
689 av_freep(&dref->dir);
693 for (j = 0; j < len; j++)
694 if (dref->dir[j] == ':')
696 av_log(c->fc, AV_LOG_DEBUG, "dir %s\n", dref->dir);
701 av_log(c->fc, AV_LOG_DEBUG, "Unknown dref type 0x%08"PRIx32" size %"PRIu32"\n",
706 avio_seek(pb, next, SEEK_SET);
711 static int mov_read_hdlr(MOVContext *c, AVIOContext *pb, MOVAtom atom)
720 avio_r8(pb); /* version */
721 avio_rb24(pb); /* flags */
724 ctype = avio_rl32(pb);
725 type = avio_rl32(pb); /* component subtype */
727 av_log(c->fc, AV_LOG_TRACE, "ctype=%s\n", av_fourcc2str(ctype));
728 av_log(c->fc, AV_LOG_TRACE, "stype=%s\n", av_fourcc2str(type));
730 if (c->trak_index < 0) { // meta not inside a trak
731 if (type == MKTAG('m','d','t','a')) {
732 c->found_hdlr_mdta = 1;
737 st = c->fc->streams[c->fc->nb_streams-1];
739 if (type == MKTAG('v','i','d','e'))
740 st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
741 else if (type == MKTAG('s','o','u','n'))
742 st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
743 else if (type == MKTAG('m','1','a',' '))
744 st->codecpar->codec_id = AV_CODEC_ID_MP2;
745 else if ((type == MKTAG('s','u','b','p')) || (type == MKTAG('c','l','c','p')))
746 st->codecpar->codec_type = AVMEDIA_TYPE_SUBTITLE;
748 avio_rb32(pb); /* component manufacture */
749 avio_rb32(pb); /* component flags */
750 avio_rb32(pb); /* component flags mask */
752 title_size = atom.size - 24;
753 if (title_size > 0) {
754 if (title_size > FFMIN(INT_MAX, SIZE_MAX-1))
755 return AVERROR_INVALIDDATA;
756 title_str = av_malloc(title_size + 1); /* Add null terminator */
758 return AVERROR(ENOMEM);
760 ret = ffio_read_size(pb, title_str, title_size);
762 av_freep(&title_str);
765 title_str[title_size] = 0;
767 int off = (!c->isom && title_str[0] == title_size - 1);
768 // flag added so as to not set stream handler name if already set from mdia->hdlr
769 av_dict_set(&st->metadata, "handler_name", title_str + off, AV_DICT_DONT_OVERWRITE);
771 av_freep(&title_str);
777 static int mov_read_esds(MOVContext *c, AVIOContext *pb, MOVAtom atom)
779 return ff_mov_read_esds(c->fc, pb);
782 static int mov_read_dac3(MOVContext *c, AVIOContext *pb, MOVAtom atom)
785 enum AVAudioServiceType *ast;
786 int ac3info, acmod, lfeon, bsmod;
788 if (c->fc->nb_streams < 1)
790 st = c->fc->streams[c->fc->nb_streams-1];
792 ast = (enum AVAudioServiceType*)av_stream_new_side_data(st, AV_PKT_DATA_AUDIO_SERVICE_TYPE,
795 return AVERROR(ENOMEM);
797 ac3info = avio_rb24(pb);
798 bsmod = (ac3info >> 14) & 0x7;
799 acmod = (ac3info >> 11) & 0x7;
800 lfeon = (ac3info >> 10) & 0x1;
801 st->codecpar->channels = ((int[]){2,1,2,3,3,4,4,5})[acmod] + lfeon;
802 st->codecpar->channel_layout = avpriv_ac3_channel_layout_tab[acmod];
804 st->codecpar->channel_layout |= AV_CH_LOW_FREQUENCY;
806 if (st->codecpar->channels > 1 && bsmod == 0x7)
807 *ast = AV_AUDIO_SERVICE_TYPE_KARAOKE;
809 #if FF_API_LAVF_AVCTX
810 FF_DISABLE_DEPRECATION_WARNINGS
811 st->codec->audio_service_type = *ast;
812 FF_ENABLE_DEPRECATION_WARNINGS
818 static int mov_read_dec3(MOVContext *c, AVIOContext *pb, MOVAtom atom)
821 enum AVAudioServiceType *ast;
822 int eac3info, acmod, lfeon, bsmod;
824 if (c->fc->nb_streams < 1)
826 st = c->fc->streams[c->fc->nb_streams-1];
828 ast = (enum AVAudioServiceType*)av_stream_new_side_data(st, AV_PKT_DATA_AUDIO_SERVICE_TYPE,
831 return AVERROR(ENOMEM);
833 /* No need to parse fields for additional independent substreams and its
834 * associated dependent substreams since libavcodec's E-AC-3 decoder
835 * does not support them yet. */
836 avio_rb16(pb); /* data_rate and num_ind_sub */
837 eac3info = avio_rb24(pb);
838 bsmod = (eac3info >> 12) & 0x1f;
839 acmod = (eac3info >> 9) & 0x7;
840 lfeon = (eac3info >> 8) & 0x1;
841 st->codecpar->channel_layout = avpriv_ac3_channel_layout_tab[acmod];
843 st->codecpar->channel_layout |= AV_CH_LOW_FREQUENCY;
844 st->codecpar->channels = av_get_channel_layout_nb_channels(st->codecpar->channel_layout);
846 if (st->codecpar->channels > 1 && bsmod == 0x7)
847 *ast = AV_AUDIO_SERVICE_TYPE_KARAOKE;
849 #if FF_API_LAVF_AVCTX
850 FF_DISABLE_DEPRECATION_WARNINGS
851 st->codec->audio_service_type = *ast;
852 FF_ENABLE_DEPRECATION_WARNINGS
858 static int mov_read_ddts(MOVContext *c, AVIOContext *pb, MOVAtom atom)
860 const uint32_t ddts_size = 20;
863 uint32_t frame_duration_code = 0;
864 uint32_t channel_layout_code = 0;
868 buf = av_malloc(ddts_size + AV_INPUT_BUFFER_PADDING_SIZE);
870 return AVERROR(ENOMEM);
872 if ((ret = ffio_read_size(pb, buf, ddts_size)) < 0) {
877 init_get_bits(&gb, buf, 8*ddts_size);
879 if (c->fc->nb_streams < 1) {
883 st = c->fc->streams[c->fc->nb_streams-1];
885 st->codecpar->sample_rate = get_bits_long(&gb, 32);
886 if (st->codecpar->sample_rate <= 0) {
887 av_log(c->fc, AV_LOG_ERROR, "Invalid sample rate %d\n", st->codecpar->sample_rate);
889 return AVERROR_INVALIDDATA;
891 skip_bits_long(&gb, 32); /* max bitrate */
892 st->codecpar->bit_rate = get_bits_long(&gb, 32);
893 st->codecpar->bits_per_coded_sample = get_bits(&gb, 8);
894 frame_duration_code = get_bits(&gb, 2);
895 skip_bits(&gb, 30); /* various fields */
896 channel_layout_code = get_bits(&gb, 16);
898 st->codecpar->frame_size =
899 (frame_duration_code == 0) ? 512 :
900 (frame_duration_code == 1) ? 1024 :
901 (frame_duration_code == 2) ? 2048 :
902 (frame_duration_code == 3) ? 4096 : 0;
904 if (channel_layout_code > 0xff) {
905 av_log(c->fc, AV_LOG_WARNING, "Unsupported DTS audio channel layout");
907 st->codecpar->channel_layout =
908 ((channel_layout_code & 0x1) ? AV_CH_FRONT_CENTER : 0) |
909 ((channel_layout_code & 0x2) ? AV_CH_FRONT_LEFT : 0) |
910 ((channel_layout_code & 0x2) ? AV_CH_FRONT_RIGHT : 0) |
911 ((channel_layout_code & 0x4) ? AV_CH_SIDE_LEFT : 0) |
912 ((channel_layout_code & 0x4) ? AV_CH_SIDE_RIGHT : 0) |
913 ((channel_layout_code & 0x8) ? AV_CH_LOW_FREQUENCY : 0);
915 st->codecpar->channels = av_get_channel_layout_nb_channels(st->codecpar->channel_layout);
921 static int mov_read_chan(MOVContext *c, AVIOContext *pb, MOVAtom atom)
925 if (c->fc->nb_streams < 1)
927 st = c->fc->streams[c->fc->nb_streams-1];
932 /* skip version and flags */
935 ff_mov_read_chan(c->fc, pb, st, atom.size - 4);
940 static int mov_read_wfex(MOVContext *c, AVIOContext *pb, MOVAtom atom)
945 if (c->fc->nb_streams < 1)
947 st = c->fc->streams[c->fc->nb_streams-1];
949 if ((ret = ff_get_wav_header(c->fc, pb, st->codecpar, atom.size, 0)) < 0)
950 av_log(c->fc, AV_LOG_WARNING, "get_wav_header failed\n");
955 static int mov_read_pasp(MOVContext *c, AVIOContext *pb, MOVAtom atom)
957 const int num = avio_rb32(pb);
958 const int den = avio_rb32(pb);
961 if (c->fc->nb_streams < 1)
963 st = c->fc->streams[c->fc->nb_streams-1];
965 if ((st->sample_aspect_ratio.den != 1 || st->sample_aspect_ratio.num) && // default
966 (den != st->sample_aspect_ratio.den || num != st->sample_aspect_ratio.num)) {
967 av_log(c->fc, AV_LOG_WARNING,
968 "sample aspect ratio already set to %d:%d, ignoring 'pasp' atom (%d:%d)\n",
969 st->sample_aspect_ratio.num, st->sample_aspect_ratio.den,
971 } else if (den != 0) {
972 av_reduce(&st->sample_aspect_ratio.num, &st->sample_aspect_ratio.den,
978 /* this atom contains actual media data */
979 static int mov_read_mdat(MOVContext *c, AVIOContext *pb, MOVAtom atom)
981 if (atom.size == 0) /* wrong one (MP4) */
984 return 0; /* now go for moov */
987 #define DRM_BLOB_SIZE 56
989 static int mov_read_adrm(MOVContext *c, AVIOContext *pb, MOVAtom atom)
991 uint8_t intermediate_key[20];
992 uint8_t intermediate_iv[20];
995 uint8_t file_checksum[20];
996 uint8_t calculated_checksum[20];
1000 uint8_t *activation_bytes = c->activation_bytes;
1001 uint8_t *fixed_key = c->audible_fixed_key;
1005 sha = av_sha_alloc();
1007 return AVERROR(ENOMEM);
1008 av_free(c->aes_decrypt);
1009 c->aes_decrypt = av_aes_alloc();
1010 if (!c->aes_decrypt) {
1011 ret = AVERROR(ENOMEM);
1015 /* drm blob processing */
1016 avio_read(pb, output, 8); // go to offset 8, absolute position 0x251
1017 avio_read(pb, input, DRM_BLOB_SIZE);
1018 avio_read(pb, output, 4); // go to offset 4, absolute position 0x28d
1019 avio_read(pb, file_checksum, 20);
1021 av_log(c->fc, AV_LOG_INFO, "[aax] file checksum == "); // required by external tools
1022 for (i = 0; i < 20; i++)
1023 av_log(c->fc, AV_LOG_INFO, "%02x", file_checksum[i]);
1024 av_log(c->fc, AV_LOG_INFO, "\n");
1026 /* verify activation data */
1027 if (!activation_bytes) {
1028 av_log(c->fc, AV_LOG_WARNING, "[aax] activation_bytes option is missing!\n");
1029 ret = 0; /* allow ffprobe to continue working on .aax files */
1032 if (c->activation_bytes_size != 4) {
1033 av_log(c->fc, AV_LOG_FATAL, "[aax] activation_bytes value needs to be 4 bytes!\n");
1034 ret = AVERROR(EINVAL);
1038 /* verify fixed key */
1039 if (c->audible_fixed_key_size != 16) {
1040 av_log(c->fc, AV_LOG_FATAL, "[aax] audible_fixed_key value needs to be 16 bytes!\n");
1041 ret = AVERROR(EINVAL);
1045 /* AAX (and AAX+) key derivation */
1046 av_sha_init(sha, 160);
1047 av_sha_update(sha, fixed_key, 16);
1048 av_sha_update(sha, activation_bytes, 4);
1049 av_sha_final(sha, intermediate_key);
1050 av_sha_init(sha, 160);
1051 av_sha_update(sha, fixed_key, 16);
1052 av_sha_update(sha, intermediate_key, 20);
1053 av_sha_update(sha, activation_bytes, 4);
1054 av_sha_final(sha, intermediate_iv);
1055 av_sha_init(sha, 160);
1056 av_sha_update(sha, intermediate_key, 16);
1057 av_sha_update(sha, intermediate_iv, 16);
1058 av_sha_final(sha, calculated_checksum);
1059 if (memcmp(calculated_checksum, file_checksum, 20)) { // critical error
1060 av_log(c->fc, AV_LOG_ERROR, "[aax] mismatch in checksums!\n");
1061 ret = AVERROR_INVALIDDATA;
1064 av_aes_init(c->aes_decrypt, intermediate_key, 128, 1);
1065 av_aes_crypt(c->aes_decrypt, output, input, DRM_BLOB_SIZE >> 4, intermediate_iv, 1);
1066 for (i = 0; i < 4; i++) {
1067 // file data (in output) is stored in big-endian mode
1068 if (activation_bytes[i] != output[3 - i]) { // critical error
1069 av_log(c->fc, AV_LOG_ERROR, "[aax] error in drm blob decryption!\n");
1070 ret = AVERROR_INVALIDDATA;
1074 memcpy(c->file_key, output + 8, 16);
1075 memcpy(input, output + 26, 16);
1076 av_sha_init(sha, 160);
1077 av_sha_update(sha, input, 16);
1078 av_sha_update(sha, c->file_key, 16);
1079 av_sha_update(sha, fixed_key, 16);
1080 av_sha_final(sha, c->file_iv);
1088 // Audible AAX (and AAX+) bytestream decryption
1089 static int aax_filter(uint8_t *input, int size, MOVContext *c)
1092 unsigned char iv[16];
1094 memcpy(iv, c->file_iv, 16); // iv is overwritten
1095 blocks = size >> 4; // trailing bytes are not encrypted!
1096 av_aes_init(c->aes_decrypt, c->file_key, 128, 1);
1097 av_aes_crypt(c->aes_decrypt, input, input, blocks, iv, 1);
1102 /* read major brand, minor version and compatible brands and store them as metadata */
1103 static int mov_read_ftyp(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1106 int comp_brand_size;
1107 char* comp_brands_str;
1108 uint8_t type[5] = {0};
1109 int ret = ffio_read_size(pb, type, 4);
1113 if (strcmp(type, "qt "))
1115 av_log(c->fc, AV_LOG_DEBUG, "ISO: File Type Major Brand: %.4s\n",(char *)&type);
1116 av_dict_set(&c->fc->metadata, "major_brand", type, 0);
1117 minor_ver = avio_rb32(pb); /* minor version */
1118 av_dict_set_int(&c->fc->metadata, "minor_version", minor_ver, 0);
1120 comp_brand_size = atom.size - 8;
1121 if (comp_brand_size < 0)
1122 return AVERROR_INVALIDDATA;
1123 comp_brands_str = av_malloc(comp_brand_size + 1); /* Add null terminator */
1124 if (!comp_brands_str)
1125 return AVERROR(ENOMEM);
1127 ret = ffio_read_size(pb, comp_brands_str, comp_brand_size);
1129 av_freep(&comp_brands_str);
1132 comp_brands_str[comp_brand_size] = 0;
1133 av_dict_set(&c->fc->metadata, "compatible_brands",
1134 comp_brands_str, AV_DICT_DONT_STRDUP_VAL);
1139 /* this atom should contain all header atoms */
1140 static int mov_read_moov(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1144 if (c->found_moov) {
1145 av_log(c->fc, AV_LOG_WARNING, "Found duplicated MOOV Atom. Skipped it\n");
1146 avio_skip(pb, atom.size);
1150 if ((ret = mov_read_default(c, pb, atom)) < 0)
1152 /* we parsed the 'moov' atom, we can terminate the parsing as soon as we find the 'mdat' */
1153 /* so we don't parse the whole file if over a network */
1155 return 0; /* now go for mdat */
1158 static MOVFragmentStreamInfo * get_frag_stream_info(
1159 MOVFragmentIndex *frag_index,
1164 MOVFragmentIndexItem * item;
1166 if (index < 0 || index >= frag_index->nb_items)
1168 item = &frag_index->item[index];
1169 for (i = 0; i < item->nb_stream_info; i++)
1170 if (item->stream_info[i].id == id)
1171 return &item->stream_info[i];
1173 // This shouldn't happen
1177 static void set_frag_stream(MOVFragmentIndex *frag_index, int id)
1180 MOVFragmentIndexItem * item;
1182 if (frag_index->current < 0 ||
1183 frag_index->current >= frag_index->nb_items)
1186 item = &frag_index->item[frag_index->current];
1187 for (i = 0; i < item->nb_stream_info; i++)
1188 if (item->stream_info[i].id == id) {
1193 // id not found. This shouldn't happen.
1197 static MOVFragmentStreamInfo * get_current_frag_stream_info(
1198 MOVFragmentIndex *frag_index)
1200 MOVFragmentIndexItem *item;
1201 if (frag_index->current < 0 ||
1202 frag_index->current >= frag_index->nb_items)
1205 item = &frag_index->item[frag_index->current];
1206 if (item->current >= 0 && item->current < item->nb_stream_info)
1207 return &item->stream_info[item->current];
1209 // This shouldn't happen
1213 static int search_frag_moof_offset(MOVFragmentIndex *frag_index, int64_t offset)
1216 int64_t moof_offset;
1218 // Optimize for appending new entries
1219 if (!frag_index->nb_items ||
1220 frag_index->item[frag_index->nb_items - 1].moof_offset < offset)
1221 return frag_index->nb_items;
1224 b = frag_index->nb_items;
1228 moof_offset = frag_index->item[m].moof_offset;
1229 if (moof_offset >= offset)
1231 if (moof_offset <= offset)
1237 static int64_t get_stream_info_time(MOVFragmentStreamInfo * frag_stream_info)
1239 av_assert0(frag_stream_info);
1240 if (frag_stream_info->sidx_pts != AV_NOPTS_VALUE)
1241 return frag_stream_info->sidx_pts;
1242 if (frag_stream_info->first_tfra_pts != AV_NOPTS_VALUE)
1243 return frag_stream_info->first_tfra_pts;
1244 return frag_stream_info->tfdt_dts;
1247 static int64_t get_frag_time(MOVFragmentIndex *frag_index,
1248 int index, int track_id)
1250 MOVFragmentStreamInfo * frag_stream_info;
1254 if (track_id >= 0) {
1255 frag_stream_info = get_frag_stream_info(frag_index, index, track_id);
1256 return frag_stream_info->sidx_pts;
1259 for (i = 0; i < frag_index->item[index].nb_stream_info; i++) {
1260 frag_stream_info = &frag_index->item[index].stream_info[i];
1261 timestamp = get_stream_info_time(frag_stream_info);
1262 if (timestamp != AV_NOPTS_VALUE)
1265 return AV_NOPTS_VALUE;
1268 static int search_frag_timestamp(MOVFragmentIndex *frag_index,
1269 AVStream *st, int64_t timestamp)
1276 // If the stream is referenced by any sidx, limit the search
1277 // to fragments that referenced this stream in the sidx
1278 MOVStreamContext *sc = st->priv_data;
1284 b = frag_index->nb_items;
1287 m0 = m = (a + b) >> 1;
1290 (frag_time = get_frag_time(frag_index, m, id)) == AV_NOPTS_VALUE)
1293 if (m < b && frag_time <= timestamp)
1302 static int update_frag_index(MOVContext *c, int64_t offset)
1305 MOVFragmentIndexItem * item;
1306 MOVFragmentStreamInfo * frag_stream_info;
1308 // If moof_offset already exists in frag_index, return index to it
1309 index = search_frag_moof_offset(&c->frag_index, offset);
1310 if (index < c->frag_index.nb_items &&
1311 c->frag_index.item[index].moof_offset == offset)
1314 // offset is not yet in frag index.
1315 // Insert new item at index (sorted by moof offset)
1316 item = av_fast_realloc(c->frag_index.item,
1317 &c->frag_index.allocated_size,
1318 (c->frag_index.nb_items + 1) *
1319 sizeof(*c->frag_index.item));
1322 c->frag_index.item = item;
1324 frag_stream_info = av_realloc_array(NULL, c->fc->nb_streams,
1325 sizeof(*item->stream_info));
1326 if (!frag_stream_info)
1329 for (i = 0; i < c->fc->nb_streams; i++) {
1330 // Avoid building frag index if streams lack track id.
1331 if (c->fc->streams[i]->id < 0) {
1332 av_free(frag_stream_info);
1333 return AVERROR_INVALIDDATA;
1336 frag_stream_info[i].id = c->fc->streams[i]->id;
1337 frag_stream_info[i].sidx_pts = AV_NOPTS_VALUE;
1338 frag_stream_info[i].tfdt_dts = AV_NOPTS_VALUE;
1339 frag_stream_info[i].next_trun_dts = AV_NOPTS_VALUE;
1340 frag_stream_info[i].first_tfra_pts = AV_NOPTS_VALUE;
1341 frag_stream_info[i].index_entry = -1;
1342 frag_stream_info[i].encryption_index = NULL;
1345 if (index < c->frag_index.nb_items)
1346 memmove(c->frag_index.item + index + 1, c->frag_index.item + index,
1347 (c->frag_index.nb_items - index) * sizeof(*c->frag_index.item));
1349 item = &c->frag_index.item[index];
1350 item->headers_read = 0;
1352 item->nb_stream_info = c->fc->nb_streams;
1353 item->moof_offset = offset;
1354 item->stream_info = frag_stream_info;
1355 c->frag_index.nb_items++;
1360 static void fix_frag_index_entries(MOVFragmentIndex *frag_index, int index,
1361 int id, int entries)
1364 MOVFragmentStreamInfo * frag_stream_info;
1368 for (i = index; i < frag_index->nb_items; i++) {
1369 frag_stream_info = get_frag_stream_info(frag_index, i, id);
1370 if (frag_stream_info && frag_stream_info->index_entry >= 0)
1371 frag_stream_info->index_entry += entries;
1375 static int mov_read_moof(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1377 // Set by mov_read_tfhd(). mov_read_trun() will reject files missing tfhd.
1378 c->fragment.found_tfhd = 0;
1380 if (!c->has_looked_for_mfra && c->use_mfra_for > 0) {
1381 c->has_looked_for_mfra = 1;
1382 if (pb->seekable & AVIO_SEEKABLE_NORMAL) {
1384 av_log(c->fc, AV_LOG_VERBOSE, "stream has moof boxes, will look "
1386 if ((ret = mov_read_mfra(c, pb)) < 0) {
1387 av_log(c->fc, AV_LOG_VERBOSE, "found a moof box but failed to "
1388 "read the mfra (may be a live ismv)\n");
1391 av_log(c->fc, AV_LOG_VERBOSE, "found a moof box but stream is not "
1392 "seekable, can not look for mfra\n");
1395 c->fragment.moof_offset = c->fragment.implicit_offset = avio_tell(pb) - 8;
1396 av_log(c->fc, AV_LOG_TRACE, "moof offset %"PRIx64"\n", c->fragment.moof_offset);
1397 c->frag_index.current = update_frag_index(c, c->fragment.moof_offset);
1398 return mov_read_default(c, pb, atom);
1401 static void mov_metadata_creation_time(AVDictionary **metadata, int64_t time, void *logctx)
1404 if(time >= 2082844800)
1405 time -= 2082844800; /* seconds between 1904-01-01 and Epoch */
1407 if ((int64_t)(time * 1000000ULL) / 1000000 != time) {
1408 av_log(logctx, AV_LOG_DEBUG, "creation_time is not representable\n");
1412 avpriv_dict_set_timestamp(metadata, "creation_time", time * 1000000);
1416 static int mov_read_mdhd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1419 MOVStreamContext *sc;
1421 char language[4] = {0};
1423 int64_t creation_time;
1425 if (c->fc->nb_streams < 1)
1427 st = c->fc->streams[c->fc->nb_streams-1];
1430 if (sc->time_scale) {
1431 av_log(c->fc, AV_LOG_ERROR, "Multiple mdhd?\n");
1432 return AVERROR_INVALIDDATA;
1435 version = avio_r8(pb);
1437 avpriv_request_sample(c->fc, "Version %d", version);
1438 return AVERROR_PATCHWELCOME;
1440 avio_rb24(pb); /* flags */
1442 creation_time = avio_rb64(pb);
1445 creation_time = avio_rb32(pb);
1446 avio_rb32(pb); /* modification time */
1448 mov_metadata_creation_time(&st->metadata, creation_time, c->fc);
1450 sc->time_scale = avio_rb32(pb);
1451 if (sc->time_scale <= 0) {
1452 av_log(c->fc, AV_LOG_ERROR, "Invalid mdhd time scale %d, defaulting to 1\n", sc->time_scale);
1455 st->duration = (version == 1) ? avio_rb64(pb) : avio_rb32(pb); /* duration */
1457 lang = avio_rb16(pb); /* language */
1458 if (ff_mov_lang_to_iso639(lang, language))
1459 av_dict_set(&st->metadata, "language", language, 0);
1460 avio_rb16(pb); /* quality */
1465 static int mov_read_mvhd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1468 int64_t creation_time;
1469 int version = avio_r8(pb); /* version */
1470 avio_rb24(pb); /* flags */
1473 creation_time = avio_rb64(pb);
1476 creation_time = avio_rb32(pb);
1477 avio_rb32(pb); /* modification time */
1479 mov_metadata_creation_time(&c->fc->metadata, creation_time, c->fc);
1480 c->time_scale = avio_rb32(pb); /* time scale */
1481 if (c->time_scale <= 0) {
1482 av_log(c->fc, AV_LOG_ERROR, "Invalid mvhd time scale %d, defaulting to 1\n", c->time_scale);
1485 av_log(c->fc, AV_LOG_TRACE, "time scale = %i\n", c->time_scale);
1487 c->duration = (version == 1) ? avio_rb64(pb) : avio_rb32(pb); /* duration */
1488 // set the AVCodecContext duration because the duration of individual tracks
1489 // may be inaccurate
1490 if (c->time_scale > 0 && !c->trex_data)
1491 c->fc->duration = av_rescale(c->duration, AV_TIME_BASE, c->time_scale);
1492 avio_rb32(pb); /* preferred scale */
1494 avio_rb16(pb); /* preferred volume */
1496 avio_skip(pb, 10); /* reserved */
1498 /* movie display matrix, store it in main context and use it later on */
1499 for (i = 0; i < 3; i++) {
1500 c->movie_display_matrix[i][0] = avio_rb32(pb); // 16.16 fixed point
1501 c->movie_display_matrix[i][1] = avio_rb32(pb); // 16.16 fixed point
1502 c->movie_display_matrix[i][2] = avio_rb32(pb); // 2.30 fixed point
1505 avio_rb32(pb); /* preview time */
1506 avio_rb32(pb); /* preview duration */
1507 avio_rb32(pb); /* poster time */
1508 avio_rb32(pb); /* selection time */
1509 avio_rb32(pb); /* selection duration */
1510 avio_rb32(pb); /* current time */
1511 avio_rb32(pb); /* next track ID */
1516 static int mov_read_enda(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1521 if (c->fc->nb_streams < 1)
1523 st = c->fc->streams[c->fc->nb_streams-1];
1525 little_endian = avio_rb16(pb) & 0xFF;
1526 av_log(c->fc, AV_LOG_TRACE, "enda %d\n", little_endian);
1527 if (little_endian == 1) {
1528 switch (st->codecpar->codec_id) {
1529 case AV_CODEC_ID_PCM_S24BE:
1530 st->codecpar->codec_id = AV_CODEC_ID_PCM_S24LE;
1532 case AV_CODEC_ID_PCM_S32BE:
1533 st->codecpar->codec_id = AV_CODEC_ID_PCM_S32LE;
1535 case AV_CODEC_ID_PCM_F32BE:
1536 st->codecpar->codec_id = AV_CODEC_ID_PCM_F32LE;
1538 case AV_CODEC_ID_PCM_F64BE:
1539 st->codecpar->codec_id = AV_CODEC_ID_PCM_F64LE;
1548 static int mov_read_colr(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1551 uint8_t *icc_profile;
1552 char color_parameter_type[5] = { 0 };
1553 uint16_t color_primaries, color_trc, color_matrix;
1556 if (c->fc->nb_streams < 1)
1558 st = c->fc->streams[c->fc->nb_streams - 1];
1560 ret = ffio_read_size(pb, color_parameter_type, 4);
1563 if (strncmp(color_parameter_type, "nclx", 4) &&
1564 strncmp(color_parameter_type, "nclc", 4) &&
1565 strncmp(color_parameter_type, "prof", 4)) {
1566 av_log(c->fc, AV_LOG_WARNING, "unsupported color_parameter_type %s\n",
1567 color_parameter_type);
1571 if (!strncmp(color_parameter_type, "prof", 4)) {
1572 icc_profile = av_stream_new_side_data(st, AV_PKT_DATA_ICC_PROFILE, atom.size - 4);
1574 return AVERROR(ENOMEM);
1575 ret = ffio_read_size(pb, icc_profile, atom.size - 4);
1580 color_primaries = avio_rb16(pb);
1581 color_trc = avio_rb16(pb);
1582 color_matrix = avio_rb16(pb);
1584 av_log(c->fc, AV_LOG_TRACE,
1585 "%s: pri %d trc %d matrix %d",
1586 color_parameter_type, color_primaries, color_trc, color_matrix);
1588 if (!strncmp(color_parameter_type, "nclx", 4)) {
1589 uint8_t color_range = avio_r8(pb) >> 7;
1590 av_log(c->fc, AV_LOG_TRACE, " full %"PRIu8"", color_range);
1592 st->codecpar->color_range = AVCOL_RANGE_JPEG;
1594 st->codecpar->color_range = AVCOL_RANGE_MPEG;
1597 if (!av_color_primaries_name(color_primaries))
1598 color_primaries = AVCOL_PRI_UNSPECIFIED;
1599 if (!av_color_transfer_name(color_trc))
1600 color_trc = AVCOL_TRC_UNSPECIFIED;
1601 if (!av_color_space_name(color_matrix))
1602 color_matrix = AVCOL_SPC_UNSPECIFIED;
1604 st->codecpar->color_primaries = color_primaries;
1605 st->codecpar->color_trc = color_trc;
1606 st->codecpar->color_space = color_matrix;
1607 av_log(c->fc, AV_LOG_TRACE, "\n");
1612 static int mov_read_fiel(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1615 unsigned mov_field_order;
1616 enum AVFieldOrder decoded_field_order = AV_FIELD_UNKNOWN;
1618 if (c->fc->nb_streams < 1) // will happen with jp2 files
1620 st = c->fc->streams[c->fc->nb_streams-1];
1622 return AVERROR_INVALIDDATA;
1623 mov_field_order = avio_rb16(pb);
1624 if ((mov_field_order & 0xFF00) == 0x0100)
1625 decoded_field_order = AV_FIELD_PROGRESSIVE;
1626 else if ((mov_field_order & 0xFF00) == 0x0200) {
1627 switch (mov_field_order & 0xFF) {
1628 case 0x01: decoded_field_order = AV_FIELD_TT;
1630 case 0x06: decoded_field_order = AV_FIELD_BB;
1632 case 0x09: decoded_field_order = AV_FIELD_TB;
1634 case 0x0E: decoded_field_order = AV_FIELD_BT;
1638 if (decoded_field_order == AV_FIELD_UNKNOWN && mov_field_order) {
1639 av_log(c->fc, AV_LOG_ERROR, "Unknown MOV field order 0x%04x\n", mov_field_order);
1641 st->codecpar->field_order = decoded_field_order;
1646 static int mov_realloc_extradata(AVCodecParameters *par, MOVAtom atom)
1649 uint64_t size = (uint64_t)par->extradata_size + atom.size + 8 + AV_INPUT_BUFFER_PADDING_SIZE;
1650 if (size > INT_MAX || (uint64_t)atom.size > INT_MAX)
1651 return AVERROR_INVALIDDATA;
1652 if ((err = av_reallocp(&par->extradata, size)) < 0) {
1653 par->extradata_size = 0;
1656 par->extradata_size = size - AV_INPUT_BUFFER_PADDING_SIZE;
1660 /* Read a whole atom into the extradata return the size of the atom read, possibly truncated if != atom.size */
1661 static int64_t mov_read_atom_into_extradata(MOVContext *c, AVIOContext *pb, MOVAtom atom,
1662 AVCodecParameters *par, uint8_t *buf)
1664 int64_t result = atom.size;
1667 AV_WB32(buf , atom.size + 8);
1668 AV_WL32(buf + 4, atom.type);
1669 err = ffio_read_size(pb, buf + 8, atom.size);
1671 par->extradata_size -= atom.size;
1673 } else if (err < atom.size) {
1674 av_log(c->fc, AV_LOG_WARNING, "truncated extradata\n");
1675 par->extradata_size -= atom.size - err;
1678 memset(buf + 8 + err, 0, AV_INPUT_BUFFER_PADDING_SIZE);
1682 /* FIXME modify QDM2/SVQ3/H.264 decoders to take full atom as extradata */
1683 static int mov_read_extradata(MOVContext *c, AVIOContext *pb, MOVAtom atom,
1684 enum AVCodecID codec_id)
1687 uint64_t original_size;
1690 if (c->fc->nb_streams < 1) // will happen with jp2 files
1692 st = c->fc->streams[c->fc->nb_streams-1];
1694 if (st->codecpar->codec_id != codec_id)
1695 return 0; /* unexpected codec_id - don't mess with extradata */
1697 original_size = st->codecpar->extradata_size;
1698 err = mov_realloc_extradata(st->codecpar, atom);
1702 err = mov_read_atom_into_extradata(c, pb, atom, st->codecpar, st->codecpar->extradata + original_size);
1705 return 0; // Note: this is the original behavior to ignore truncation.
1708 /* wrapper functions for reading ALAC/AVS/MJPEG/MJPEG2000 extradata atoms only for those codecs */
1709 static int mov_read_alac(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1711 return mov_read_extradata(c, pb, atom, AV_CODEC_ID_ALAC);
1714 static int mov_read_avss(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1716 return mov_read_extradata(c, pb, atom, AV_CODEC_ID_AVS);
1719 static int mov_read_jp2h(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1721 return mov_read_extradata(c, pb, atom, AV_CODEC_ID_JPEG2000);
1724 static int mov_read_dpxe(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1726 return mov_read_extradata(c, pb, atom, AV_CODEC_ID_R10K);
1729 static int mov_read_avid(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1731 int ret = mov_read_extradata(c, pb, atom, AV_CODEC_ID_AVUI);
1733 ret = mov_read_extradata(c, pb, atom, AV_CODEC_ID_DNXHD);
1737 static int mov_read_targa_y216(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1739 int ret = mov_read_extradata(c, pb, atom, AV_CODEC_ID_TARGA_Y216);
1741 if (!ret && c->fc->nb_streams >= 1) {
1742 AVCodecParameters *par = c->fc->streams[c->fc->nb_streams-1]->codecpar;
1743 if (par->extradata_size >= 40) {
1744 par->height = AV_RB16(&par->extradata[36]);
1745 par->width = AV_RB16(&par->extradata[38]);
1751 static int mov_read_ares(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1753 if (c->fc->nb_streams >= 1) {
1754 AVCodecParameters *par = c->fc->streams[c->fc->nb_streams-1]->codecpar;
1755 if (par->codec_tag == MKTAG('A', 'V', 'i', 'n') &&
1756 par->codec_id == AV_CODEC_ID_H264 &&
1760 cid = avio_rb16(pb);
1761 /* For AVID AVCI50, force width of 1440 to be able to select the correct SPS and PPS */
1762 if (cid == 0xd4d || cid == 0xd4e)
1765 } else if ((par->codec_tag == MKTAG('A', 'V', 'd', '1') ||
1766 par->codec_tag == MKTAG('A', 'V', 'j', '2') ||
1767 par->codec_tag == MKTAG('A', 'V', 'd', 'n')) &&
1771 num = avio_rb32(pb);
1772 den = avio_rb32(pb);
1773 if (num <= 0 || den <= 0)
1775 switch (avio_rb32(pb)) {
1777 if (den >= INT_MAX / 2)
1781 c->fc->streams[c->fc->nb_streams-1]->display_aspect_ratio.num = num;
1782 c->fc->streams[c->fc->nb_streams-1]->display_aspect_ratio.den = den;
1789 return mov_read_avid(c, pb, atom);
1792 static int mov_read_aclr(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1796 uint64_t original_size;
1797 if (c->fc->nb_streams >= 1) {
1798 AVCodecParameters *par = c->fc->streams[c->fc->nb_streams-1]->codecpar;
1799 if (par->codec_id == AV_CODEC_ID_H264)
1801 if (atom.size == 16) {
1802 original_size = par->extradata_size;
1803 ret = mov_realloc_extradata(par, atom);
1805 length = mov_read_atom_into_extradata(c, pb, atom, par, par->extradata + original_size);
1806 if (length == atom.size) {
1807 const uint8_t range_value = par->extradata[original_size + 19];
1808 switch (range_value) {
1810 par->color_range = AVCOL_RANGE_MPEG;
1813 par->color_range = AVCOL_RANGE_JPEG;
1816 av_log(c->fc, AV_LOG_WARNING, "ignored unknown aclr value (%d)\n", range_value);
1819 ff_dlog(c->fc, "color_range: %d\n", par->color_range);
1821 /* For some reason the whole atom was not added to the extradata */
1822 av_log(c->fc, AV_LOG_ERROR, "aclr not decoded - incomplete atom\n");
1825 av_log(c->fc, AV_LOG_ERROR, "aclr not decoded - unable to add atom to extradata\n");
1828 av_log(c->fc, AV_LOG_WARNING, "aclr not decoded - unexpected size %"PRId64"\n", atom.size);
1835 static int mov_read_svq3(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1837 return mov_read_extradata(c, pb, atom, AV_CODEC_ID_SVQ3);
1840 static int mov_read_wave(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1845 if (c->fc->nb_streams < 1)
1847 st = c->fc->streams[c->fc->nb_streams-1];
1849 if ((uint64_t)atom.size > (1<<30))
1850 return AVERROR_INVALIDDATA;
1852 if (st->codecpar->codec_id == AV_CODEC_ID_QDM2 ||
1853 st->codecpar->codec_id == AV_CODEC_ID_QDMC ||
1854 st->codecpar->codec_id == AV_CODEC_ID_SPEEX) {
1855 // pass all frma atom to codec, needed at least for QDMC and QDM2
1856 ret = ff_get_extradata(c->fc, st->codecpar, pb, atom.size);
1859 } else if (atom.size > 8) { /* to read frma, esds atoms */
1860 if (st->codecpar->codec_id == AV_CODEC_ID_ALAC && atom.size >= 24) {
1862 ret = ffio_ensure_seekback(pb, 8);
1865 buffer = avio_rb64(pb);
1867 if ( (buffer & 0xFFFFFFFF) == MKBETAG('f','r','m','a')
1868 && buffer >> 32 <= atom.size
1869 && buffer >> 32 >= 8) {
1872 } else if (!st->codecpar->extradata_size) {
1873 #define ALAC_EXTRADATA_SIZE 36
1874 st->codecpar->extradata = av_mallocz(ALAC_EXTRADATA_SIZE + AV_INPUT_BUFFER_PADDING_SIZE);
1875 if (!st->codecpar->extradata)
1876 return AVERROR(ENOMEM);
1877 st->codecpar->extradata_size = ALAC_EXTRADATA_SIZE;
1878 AV_WB32(st->codecpar->extradata , ALAC_EXTRADATA_SIZE);
1879 AV_WB32(st->codecpar->extradata + 4, MKTAG('a','l','a','c'));
1880 AV_WB64(st->codecpar->extradata + 12, buffer);
1881 avio_read(pb, st->codecpar->extradata + 20, 16);
1882 avio_skip(pb, atom.size - 24);
1886 if ((ret = mov_read_default(c, pb, atom)) < 0)
1889 avio_skip(pb, atom.size);
1894 * This function reads atom content and puts data in extradata without tag
1895 * nor size unlike mov_read_extradata.
1897 static int mov_read_glbl(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1902 if (c->fc->nb_streams < 1)
1904 st = c->fc->streams[c->fc->nb_streams-1];
1906 if ((uint64_t)atom.size > (1<<30))
1907 return AVERROR_INVALIDDATA;
1909 if (atom.size >= 10) {
1910 // Broken files created by legacy versions of libavformat will
1911 // wrap a whole fiel atom inside of a glbl atom.
1912 unsigned size = avio_rb32(pb);
1913 unsigned type = avio_rl32(pb);
1914 avio_seek(pb, -8, SEEK_CUR);
1915 if (type == MKTAG('f','i','e','l') && size == atom.size)
1916 return mov_read_default(c, pb, atom);
1918 if (st->codecpar->extradata_size > 1 && st->codecpar->extradata) {
1919 av_log(c->fc, AV_LOG_WARNING, "ignoring multiple glbl\n");
1922 ret = ff_get_extradata(c->fc, st->codecpar, pb, atom.size);
1925 if (atom.type == MKTAG('h','v','c','C') && st->codecpar->codec_tag == MKTAG('d','v','h','1'))
1926 /* HEVC-based Dolby Vision derived from hvc1.
1927 Happens to match with an identifier
1928 previously utilized for DV. Thus, if we have
1929 the hvcC extradata box available as specified,
1930 set codec to HEVC */
1931 st->codecpar->codec_id = AV_CODEC_ID_HEVC;
1936 static int mov_read_dvc1(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1939 uint8_t profile_level;
1942 if (c->fc->nb_streams < 1)
1944 st = c->fc->streams[c->fc->nb_streams-1];
1946 if (atom.size >= (1<<28) || atom.size < 7)
1947 return AVERROR_INVALIDDATA;
1949 profile_level = avio_r8(pb);
1950 if ((profile_level & 0xf0) != 0xc0)
1953 avio_seek(pb, 6, SEEK_CUR);
1954 ret = ff_get_extradata(c->fc, st->codecpar, pb, atom.size - 7);
1962 * An strf atom is a BITMAPINFOHEADER struct. This struct is 40 bytes itself,
1963 * but can have extradata appended at the end after the 40 bytes belonging
1966 static int mov_read_strf(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1971 if (c->fc->nb_streams < 1)
1973 if (atom.size <= 40)
1975 st = c->fc->streams[c->fc->nb_streams-1];
1977 if ((uint64_t)atom.size > (1<<30))
1978 return AVERROR_INVALIDDATA;
1981 ret = ff_get_extradata(c->fc, st->codecpar, pb, atom.size - 40);
1988 static int mov_read_stco(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1991 MOVStreamContext *sc;
1992 unsigned int i, entries;
1994 if (c->trak_index < 0) {
1995 av_log(c->fc, AV_LOG_WARNING, "STCO outside TRAK\n");
1998 if (c->fc->nb_streams < 1)
2000 st = c->fc->streams[c->fc->nb_streams-1];
2003 avio_r8(pb); /* version */
2004 avio_rb24(pb); /* flags */
2006 entries = avio_rb32(pb);
2011 if (sc->chunk_offsets)
2012 av_log(c->fc, AV_LOG_WARNING, "Duplicated STCO atom\n");
2013 av_free(sc->chunk_offsets);
2014 sc->chunk_count = 0;
2015 sc->chunk_offsets = av_malloc_array(entries, sizeof(*sc->chunk_offsets));
2016 if (!sc->chunk_offsets)
2017 return AVERROR(ENOMEM);
2018 sc->chunk_count = entries;
2020 if (atom.type == MKTAG('s','t','c','o'))
2021 for (i = 0; i < entries && !pb->eof_reached; i++)
2022 sc->chunk_offsets[i] = avio_rb32(pb);
2023 else if (atom.type == MKTAG('c','o','6','4'))
2024 for (i = 0; i < entries && !pb->eof_reached; i++)
2025 sc->chunk_offsets[i] = avio_rb64(pb);
2027 return AVERROR_INVALIDDATA;
2029 sc->chunk_count = i;
2031 if (pb->eof_reached) {
2032 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted STCO atom\n");
2039 static int mov_codec_id(AVStream *st, uint32_t format)
2041 int id = ff_codec_get_id(ff_codec_movaudio_tags, format);
2044 ((format & 0xFFFF) == 'm' + ('s' << 8) ||
2045 (format & 0xFFFF) == 'T' + ('S' << 8)))
2046 id = ff_codec_get_id(ff_codec_wav_tags, av_bswap32(format) & 0xFFFF);
2048 if (st->codecpar->codec_type != AVMEDIA_TYPE_VIDEO && id > 0) {
2049 st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
2050 } else if (st->codecpar->codec_type != AVMEDIA_TYPE_AUDIO &&
2051 /* skip old ASF MPEG-4 tag */
2052 format && format != MKTAG('m','p','4','s')) {
2053 id = ff_codec_get_id(ff_codec_movvideo_tags, format);
2055 id = ff_codec_get_id(ff_codec_bmp_tags, format);
2057 st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
2058 else if (st->codecpar->codec_type == AVMEDIA_TYPE_DATA ||
2059 (st->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE &&
2060 st->codecpar->codec_id == AV_CODEC_ID_NONE)) {
2061 id = ff_codec_get_id(ff_codec_movsubtitle_tags, format);
2063 st->codecpar->codec_type = AVMEDIA_TYPE_SUBTITLE;
2065 id = ff_codec_get_id(ff_codec_movdata_tags, format);
2069 st->codecpar->codec_tag = format;
2074 static void mov_parse_stsd_video(MOVContext *c, AVIOContext *pb,
2075 AVStream *st, MOVStreamContext *sc)
2077 uint8_t codec_name[32] = { 0 };
2081 /* The first 16 bytes of the video sample description are already
2082 * read in ff_mov_read_stsd_entries() */
2083 stsd_start = avio_tell(pb) - 16;
2085 avio_rb16(pb); /* version */
2086 avio_rb16(pb); /* revision level */
2087 avio_rb32(pb); /* vendor */
2088 avio_rb32(pb); /* temporal quality */
2089 avio_rb32(pb); /* spatial quality */
2091 st->codecpar->width = avio_rb16(pb); /* width */
2092 st->codecpar->height = avio_rb16(pb); /* height */
2094 avio_rb32(pb); /* horiz resolution */
2095 avio_rb32(pb); /* vert resolution */
2096 avio_rb32(pb); /* data size, always 0 */
2097 avio_rb16(pb); /* frames per samples */
2099 len = avio_r8(pb); /* codec name, pascal string */
2102 mov_read_mac_string(c, pb, len, codec_name, sizeof(codec_name));
2104 avio_skip(pb, 31 - len);
2107 av_dict_set(&st->metadata, "encoder", codec_name, 0);
2109 /* codec_tag YV12 triggers an UV swap in rawdec.c */
2110 if (!strncmp(codec_name, "Planar Y'CbCr 8-bit 4:2:0", 25)) {
2111 st->codecpar->codec_tag = MKTAG('I', '4', '2', '0');
2112 st->codecpar->width &= ~1;
2113 st->codecpar->height &= ~1;
2115 /* Flash Media Server uses tag H.263 with Sorenson Spark */
2116 if (st->codecpar->codec_tag == MKTAG('H','2','6','3') &&
2117 !strncmp(codec_name, "Sorenson H263", 13))
2118 st->codecpar->codec_id = AV_CODEC_ID_FLV1;
2120 st->codecpar->bits_per_coded_sample = avio_rb16(pb); /* depth */
2122 avio_seek(pb, stsd_start, SEEK_SET);
2124 if (ff_get_qtpalette(st->codecpar->codec_id, pb, sc->palette)) {
2125 st->codecpar->bits_per_coded_sample &= 0x1F;
2126 sc->has_palette = 1;
2130 static void mov_parse_stsd_audio(MOVContext *c, AVIOContext *pb,
2131 AVStream *st, MOVStreamContext *sc)
2133 int bits_per_sample, flags;
2134 uint16_t version = avio_rb16(pb);
2135 AVDictionaryEntry *compatible_brands = av_dict_get(c->fc->metadata, "compatible_brands", NULL, AV_DICT_MATCH_CASE);
2137 avio_rb16(pb); /* revision level */
2138 avio_rb32(pb); /* vendor */
2140 st->codecpar->channels = avio_rb16(pb); /* channel count */
2141 st->codecpar->bits_per_coded_sample = avio_rb16(pb); /* sample size */
2142 av_log(c->fc, AV_LOG_TRACE, "audio channels %d\n", st->codecpar->channels);
2144 sc->audio_cid = avio_rb16(pb);
2145 avio_rb16(pb); /* packet size = 0 */
2147 st->codecpar->sample_rate = ((avio_rb32(pb) >> 16));
2149 // Read QT version 1 fields. In version 0 these do not exist.
2150 av_log(c->fc, AV_LOG_TRACE, "version =%d, isom =%d\n", version, c->isom);
2152 (compatible_brands && strstr(compatible_brands->value, "qt ")) ||
2153 (sc->stsd_version == 0 && version > 0)) {
2155 sc->samples_per_frame = avio_rb32(pb);
2156 avio_rb32(pb); /* bytes per packet */
2157 sc->bytes_per_frame = avio_rb32(pb);
2158 avio_rb32(pb); /* bytes per sample */
2159 } else if (version == 2) {
2160 avio_rb32(pb); /* sizeof struct only */
2161 st->codecpar->sample_rate = av_int2double(avio_rb64(pb));
2162 st->codecpar->channels = avio_rb32(pb);
2163 avio_rb32(pb); /* always 0x7F000000 */
2164 st->codecpar->bits_per_coded_sample = avio_rb32(pb);
2166 flags = avio_rb32(pb); /* lpcm format specific flag */
2167 sc->bytes_per_frame = avio_rb32(pb);
2168 sc->samples_per_frame = avio_rb32(pb);
2169 if (st->codecpar->codec_tag == MKTAG('l','p','c','m'))
2170 st->codecpar->codec_id =
2171 ff_mov_get_lpcm_codec_id(st->codecpar->bits_per_coded_sample,
2174 if (version == 0 || (version == 1 && sc->audio_cid != -2)) {
2175 /* can't correctly handle variable sized packet as audio unit */
2176 switch (st->codecpar->codec_id) {
2177 case AV_CODEC_ID_MP2:
2178 case AV_CODEC_ID_MP3:
2179 st->need_parsing = AVSTREAM_PARSE_FULL;
2185 if (sc->format == 0) {
2186 if (st->codecpar->bits_per_coded_sample == 8)
2187 st->codecpar->codec_id = mov_codec_id(st, MKTAG('r','a','w',' '));
2188 else if (st->codecpar->bits_per_coded_sample == 16)
2189 st->codecpar->codec_id = mov_codec_id(st, MKTAG('t','w','o','s'));
2192 switch (st->codecpar->codec_id) {
2193 case AV_CODEC_ID_PCM_S8:
2194 case AV_CODEC_ID_PCM_U8:
2195 if (st->codecpar->bits_per_coded_sample == 16)
2196 st->codecpar->codec_id = AV_CODEC_ID_PCM_S16BE;
2198 case AV_CODEC_ID_PCM_S16LE:
2199 case AV_CODEC_ID_PCM_S16BE:
2200 if (st->codecpar->bits_per_coded_sample == 8)
2201 st->codecpar->codec_id = AV_CODEC_ID_PCM_S8;
2202 else if (st->codecpar->bits_per_coded_sample == 24)
2203 st->codecpar->codec_id =
2204 st->codecpar->codec_id == AV_CODEC_ID_PCM_S16BE ?
2205 AV_CODEC_ID_PCM_S24BE : AV_CODEC_ID_PCM_S24LE;
2206 else if (st->codecpar->bits_per_coded_sample == 32)
2207 st->codecpar->codec_id =
2208 st->codecpar->codec_id == AV_CODEC_ID_PCM_S16BE ?
2209 AV_CODEC_ID_PCM_S32BE : AV_CODEC_ID_PCM_S32LE;
2211 /* set values for old format before stsd version 1 appeared */
2212 case AV_CODEC_ID_MACE3:
2213 sc->samples_per_frame = 6;
2214 sc->bytes_per_frame = 2 * st->codecpar->channels;
2216 case AV_CODEC_ID_MACE6:
2217 sc->samples_per_frame = 6;
2218 sc->bytes_per_frame = 1 * st->codecpar->channels;
2220 case AV_CODEC_ID_ADPCM_IMA_QT:
2221 sc->samples_per_frame = 64;
2222 sc->bytes_per_frame = 34 * st->codecpar->channels;
2224 case AV_CODEC_ID_GSM:
2225 sc->samples_per_frame = 160;
2226 sc->bytes_per_frame = 33;
2232 bits_per_sample = av_get_bits_per_sample(st->codecpar->codec_id);
2233 if (bits_per_sample) {
2234 st->codecpar->bits_per_coded_sample = bits_per_sample;
2235 sc->sample_size = (bits_per_sample >> 3) * st->codecpar->channels;
2239 static void mov_parse_stsd_subtitle(MOVContext *c, AVIOContext *pb,
2240 AVStream *st, MOVStreamContext *sc,
2243 // ttxt stsd contains display flags, justification, background
2244 // color, fonts, and default styles, so fake an atom to read it
2245 MOVAtom fake_atom = { .size = size };
2246 // mp4s contains a regular esds atom
2247 if (st->codecpar->codec_tag != AV_RL32("mp4s"))
2248 mov_read_glbl(c, pb, fake_atom);
2249 st->codecpar->width = sc->width;
2250 st->codecpar->height = sc->height;
2253 static uint32_t yuv_to_rgba(uint32_t ycbcr)
2258 y = (ycbcr >> 16) & 0xFF;
2259 cr = (ycbcr >> 8) & 0xFF;
2262 b = av_clip_uint8((1164 * (y - 16) + 2018 * (cb - 128)) / 1000);
2263 g = av_clip_uint8((1164 * (y - 16) - 813 * (cr - 128) - 391 * (cb - 128)) / 1000);
2264 r = av_clip_uint8((1164 * (y - 16) + 1596 * (cr - 128) ) / 1000);
2266 return (r << 16) | (g << 8) | b;
2269 static int mov_rewrite_dvd_sub_extradata(AVStream *st)
2271 char buf[256] = {0};
2272 uint8_t *src = st->codecpar->extradata;
2275 if (st->codecpar->extradata_size != 64)
2278 if (st->codecpar->width > 0 && st->codecpar->height > 0)
2279 snprintf(buf, sizeof(buf), "size: %dx%d\n",
2280 st->codecpar->width, st->codecpar->height);
2281 av_strlcat(buf, "palette: ", sizeof(buf));
2283 for (i = 0; i < 16; i++) {
2284 uint32_t yuv = AV_RB32(src + i * 4);
2285 uint32_t rgba = yuv_to_rgba(yuv);
2287 av_strlcatf(buf, sizeof(buf), "%06"PRIx32"%s", rgba, i != 15 ? ", " : "");
2290 if (av_strlcat(buf, "\n", sizeof(buf)) >= sizeof(buf))
2293 ret = ff_alloc_extradata(st->codecpar, strlen(buf));
2296 memcpy(st->codecpar->extradata, buf, st->codecpar->extradata_size);
2301 static int mov_parse_stsd_data(MOVContext *c, AVIOContext *pb,
2302 AVStream *st, MOVStreamContext *sc,
2307 if (st->codecpar->codec_tag == MKTAG('t','m','c','d')) {
2308 if ((int)size != size)
2309 return AVERROR(ENOMEM);
2311 ret = ff_get_extradata(c->fc, st->codecpar, pb, size);
2315 MOVStreamContext *tmcd_ctx = st->priv_data;
2317 val = AV_RB32(st->codecpar->extradata + 4);
2318 tmcd_ctx->tmcd_flags = val;
2319 st->avg_frame_rate.num = AV_RB32(st->codecpar->extradata + 8); /* timescale */
2320 st->avg_frame_rate.den = AV_RB32(st->codecpar->extradata + 12); /* frameDuration */
2321 #if FF_API_LAVF_AVCTX
2322 FF_DISABLE_DEPRECATION_WARNINGS
2323 st->codec->time_base = av_inv_q(st->avg_frame_rate);
2324 FF_ENABLE_DEPRECATION_WARNINGS
2326 /* adjust for per frame dur in counter mode */
2327 if (tmcd_ctx->tmcd_flags & 0x0008) {
2328 int timescale = AV_RB32(st->codecpar->extradata + 8);
2329 int framedur = AV_RB32(st->codecpar->extradata + 12);
2330 st->avg_frame_rate.num *= timescale;
2331 st->avg_frame_rate.den *= framedur;
2332 #if FF_API_LAVF_AVCTX
2333 FF_DISABLE_DEPRECATION_WARNINGS
2334 st->codec->time_base.den *= timescale;
2335 st->codec->time_base.num *= framedur;
2336 FF_ENABLE_DEPRECATION_WARNINGS
2340 uint32_t len = AV_RB32(st->codecpar->extradata + 18); /* name atom length */
2341 uint32_t format = AV_RB32(st->codecpar->extradata + 22);
2342 if (format == AV_RB32("name") && (int64_t)size >= (int64_t)len + 18) {
2343 uint16_t str_size = AV_RB16(st->codecpar->extradata + 26); /* string length */
2344 if (str_size > 0 && size >= (int)str_size + 30 &&
2345 st->codecpar->extradata[30] /* Don't add empty string */) {
2346 char *reel_name = av_malloc(str_size + 1);
2348 return AVERROR(ENOMEM);
2349 memcpy(reel_name, st->codecpar->extradata + 30, str_size);
2350 reel_name[str_size] = 0; /* Add null terminator */
2351 av_dict_set(&st->metadata, "reel_name", reel_name,
2352 AV_DICT_DONT_STRDUP_VAL);
2358 /* other codec type, just skip (rtp, mp4s ...) */
2359 avio_skip(pb, size);
2364 static int mov_finalize_stsd_codec(MOVContext *c, AVIOContext *pb,
2365 AVStream *st, MOVStreamContext *sc)
2367 if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO &&
2368 !st->codecpar->sample_rate && sc->time_scale > 1)
2369 st->codecpar->sample_rate = sc->time_scale;
2371 /* special codec parameters handling */
2372 switch (st->codecpar->codec_id) {
2373 #if CONFIG_DV_DEMUXER
2374 case AV_CODEC_ID_DVAUDIO:
2375 c->dv_fctx = avformat_alloc_context();
2377 av_log(c->fc, AV_LOG_ERROR, "dv demux context alloc error\n");
2378 return AVERROR(ENOMEM);
2380 c->dv_demux = avpriv_dv_init_demux(c->dv_fctx);
2382 av_log(c->fc, AV_LOG_ERROR, "dv demux context init error\n");
2383 return AVERROR(ENOMEM);
2385 sc->dv_audio_container = 1;
2386 st->codecpar->codec_id = AV_CODEC_ID_PCM_S16LE;
2389 /* no ifdef since parameters are always those */
2390 case AV_CODEC_ID_QCELP:
2391 st->codecpar->channels = 1;
2392 // force sample rate for qcelp when not stored in mov
2393 if (st->codecpar->codec_tag != MKTAG('Q','c','l','p'))
2394 st->codecpar->sample_rate = 8000;
2395 // FIXME: Why is the following needed for some files?
2396 sc->samples_per_frame = 160;
2397 if (!sc->bytes_per_frame)
2398 sc->bytes_per_frame = 35;
2400 case AV_CODEC_ID_AMR_NB:
2401 st->codecpar->channels = 1;
2402 /* force sample rate for amr, stsd in 3gp does not store sample rate */
2403 st->codecpar->sample_rate = 8000;
2405 case AV_CODEC_ID_AMR_WB:
2406 st->codecpar->channels = 1;
2407 st->codecpar->sample_rate = 16000;
2409 case AV_CODEC_ID_MP2:
2410 case AV_CODEC_ID_MP3:
2411 /* force type after stsd for m1a hdlr */
2412 st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
2414 case AV_CODEC_ID_GSM:
2415 case AV_CODEC_ID_ADPCM_MS:
2416 case AV_CODEC_ID_ADPCM_IMA_WAV:
2417 case AV_CODEC_ID_ILBC:
2418 case AV_CODEC_ID_MACE3:
2419 case AV_CODEC_ID_MACE6:
2420 case AV_CODEC_ID_QDM2:
2421 st->codecpar->block_align = sc->bytes_per_frame;
2423 case AV_CODEC_ID_ALAC:
2424 if (st->codecpar->extradata_size == 36) {
2425 st->codecpar->channels = AV_RB8 (st->codecpar->extradata + 21);
2426 st->codecpar->sample_rate = AV_RB32(st->codecpar->extradata + 32);
2429 case AV_CODEC_ID_AC3:
2430 case AV_CODEC_ID_EAC3:
2431 case AV_CODEC_ID_MPEG1VIDEO:
2432 case AV_CODEC_ID_VC1:
2433 case AV_CODEC_ID_VP8:
2434 case AV_CODEC_ID_VP9:
2435 st->need_parsing = AVSTREAM_PARSE_FULL;
2443 static int mov_skip_multiple_stsd(MOVContext *c, AVIOContext *pb,
2444 int codec_tag, int format,
2447 int video_codec_id = ff_codec_get_id(ff_codec_movvideo_tags, format);
2450 (codec_tag != format &&
2451 // AVID 1:1 samples with differing data format and codec tag exist
2452 (codec_tag != AV_RL32("AV1x") || format != AV_RL32("AVup")) &&
2453 // prores is allowed to have differing data format and codec tag
2454 codec_tag != AV_RL32("apcn") && codec_tag != AV_RL32("apch") &&
2456 codec_tag != AV_RL32("dvpp") && codec_tag != AV_RL32("dvcp") &&
2457 (c->fc->video_codec_id ? video_codec_id != c->fc->video_codec_id
2458 : codec_tag != MKTAG('j','p','e','g')))) {
2459 /* Multiple fourcc, we skip JPEG. This is not correct, we should
2460 * export it as a separate AVStream but this needs a few changes
2461 * in the MOV demuxer, patch welcome. */
2463 av_log(c->fc, AV_LOG_WARNING, "multiple fourcc not supported\n");
2464 avio_skip(pb, size);
2471 int ff_mov_read_stsd_entries(MOVContext *c, AVIOContext *pb, int entries)
2474 MOVStreamContext *sc;
2475 int pseudo_stream_id;
2477 av_assert0 (c->fc->nb_streams >= 1);
2478 st = c->fc->streams[c->fc->nb_streams-1];
2481 for (pseudo_stream_id = 0;
2482 pseudo_stream_id < entries && !pb->eof_reached;
2483 pseudo_stream_id++) {
2484 //Parsing Sample description table
2486 int ret, dref_id = 1;
2487 MOVAtom a = { AV_RL32("stsd") };
2488 int64_t start_pos = avio_tell(pb);
2489 int64_t size = avio_rb32(pb); /* size */
2490 uint32_t format = avio_rl32(pb); /* data format */
2493 avio_rb32(pb); /* reserved */
2494 avio_rb16(pb); /* reserved */
2495 dref_id = avio_rb16(pb);
2496 } else if (size <= 7) {
2497 av_log(c->fc, AV_LOG_ERROR,
2498 "invalid size %"PRId64" in stsd\n", size);
2499 return AVERROR_INVALIDDATA;
2502 if (mov_skip_multiple_stsd(c, pb, st->codecpar->codec_tag, format,
2503 size - (avio_tell(pb) - start_pos))) {
2508 sc->pseudo_stream_id = st->codecpar->codec_tag ? -1 : pseudo_stream_id;
2509 sc->dref_id= dref_id;
2510 sc->format = format;
2512 id = mov_codec_id(st, format);
2514 av_log(c->fc, AV_LOG_TRACE,
2515 "size=%"PRId64" 4CC=%s codec_type=%d\n", size,
2516 av_fourcc2str(format), st->codecpar->codec_type);
2518 st->codecpar->codec_id = id;
2519 if (st->codecpar->codec_type==AVMEDIA_TYPE_VIDEO) {
2520 mov_parse_stsd_video(c, pb, st, sc);
2521 } else if (st->codecpar->codec_type==AVMEDIA_TYPE_AUDIO) {
2522 mov_parse_stsd_audio(c, pb, st, sc);
2523 if (st->codecpar->sample_rate < 0) {
2524 av_log(c->fc, AV_LOG_ERROR, "Invalid sample rate %d\n", st->codecpar->sample_rate);
2525 return AVERROR_INVALIDDATA;
2527 } else if (st->codecpar->codec_type==AVMEDIA_TYPE_SUBTITLE){
2528 mov_parse_stsd_subtitle(c, pb, st, sc,
2529 size - (avio_tell(pb) - start_pos));
2531 ret = mov_parse_stsd_data(c, pb, st, sc,
2532 size - (avio_tell(pb) - start_pos));
2536 /* this will read extra atoms at the end (wave, alac, damr, avcC, hvcC, SMI ...) */
2537 a.size = size - (avio_tell(pb) - start_pos);
2539 if ((ret = mov_read_default(c, pb, a)) < 0)
2541 } else if (a.size > 0)
2542 avio_skip(pb, a.size);
2544 if (sc->extradata && st->codecpar->extradata) {
2545 int extra_size = st->codecpar->extradata_size;
2547 /* Move the current stream extradata to the stream context one. */
2548 sc->extradata_size[pseudo_stream_id] = extra_size;
2549 sc->extradata[pseudo_stream_id] = st->codecpar->extradata;
2550 st->codecpar->extradata = NULL;
2551 st->codecpar->extradata_size = 0;
2556 if (pb->eof_reached) {
2557 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted STSD atom\n");
2564 static int mov_read_stsd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2567 MOVStreamContext *sc;
2570 if (c->fc->nb_streams < 1)
2572 st = c->fc->streams[c->fc->nb_streams - 1];
2575 sc->stsd_version = avio_r8(pb);
2576 avio_rb24(pb); /* flags */
2577 entries = avio_rb32(pb);
2579 /* Each entry contains a size (4 bytes) and format (4 bytes). */
2580 if (entries <= 0 || entries > atom.size / 8) {
2581 av_log(c->fc, AV_LOG_ERROR, "invalid STSD entries %d\n", entries);
2582 return AVERROR_INVALIDDATA;
2585 if (sc->extradata) {
2586 av_log(c->fc, AV_LOG_ERROR,
2587 "Duplicate stsd found in this track.\n");
2588 return AVERROR_INVALIDDATA;
2591 /* Prepare space for hosting multiple extradata. */
2592 sc->extradata = av_mallocz_array(entries, sizeof(*sc->extradata));
2594 return AVERROR(ENOMEM);
2596 sc->extradata_size = av_mallocz_array(entries, sizeof(*sc->extradata_size));
2597 if (!sc->extradata_size) {
2598 ret = AVERROR(ENOMEM);
2602 ret = ff_mov_read_stsd_entries(c, pb, entries);
2606 /* Restore back the primary extradata. */
2607 av_freep(&st->codecpar->extradata);
2608 st->codecpar->extradata_size = sc->extradata_size[0];
2609 if (sc->extradata_size[0]) {
2610 st->codecpar->extradata = av_mallocz(sc->extradata_size[0] + AV_INPUT_BUFFER_PADDING_SIZE);
2611 if (!st->codecpar->extradata)
2612 return AVERROR(ENOMEM);
2613 memcpy(st->codecpar->extradata, sc->extradata[0], sc->extradata_size[0]);
2616 return mov_finalize_stsd_codec(c, pb, st, sc);
2618 if (sc->extradata) {
2620 for (j = 0; j < sc->stsd_count; j++)
2621 av_freep(&sc->extradata[j]);
2624 av_freep(&sc->extradata);
2625 av_freep(&sc->extradata_size);
2629 static int mov_read_stsc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2632 MOVStreamContext *sc;
2633 unsigned int i, entries;
2635 if (c->fc->nb_streams < 1)
2637 st = c->fc->streams[c->fc->nb_streams-1];
2640 avio_r8(pb); /* version */
2641 avio_rb24(pb); /* flags */
2643 entries = avio_rb32(pb);
2644 if ((uint64_t)entries * 12 + 4 > atom.size)
2645 return AVERROR_INVALIDDATA;
2647 av_log(c->fc, AV_LOG_TRACE, "track[%u].stsc.entries = %u\n", c->fc->nb_streams - 1, entries);
2652 av_log(c->fc, AV_LOG_WARNING, "Duplicated STSC atom\n");
2653 av_free(sc->stsc_data);
2655 sc->stsc_data = av_malloc_array(entries, sizeof(*sc->stsc_data));
2657 return AVERROR(ENOMEM);
2659 for (i = 0; i < entries && !pb->eof_reached; i++) {
2660 sc->stsc_data[i].first = avio_rb32(pb);
2661 sc->stsc_data[i].count = avio_rb32(pb);
2662 sc->stsc_data[i].id = avio_rb32(pb);
2666 for (i = sc->stsc_count - 1; i < UINT_MAX; i--) {
2667 int64_t first_min = i + 1;
2668 if ((i+1 < sc->stsc_count && sc->stsc_data[i].first >= sc->stsc_data[i+1].first) ||
2669 (i > 0 && sc->stsc_data[i].first <= sc->stsc_data[i-1].first) ||
2670 sc->stsc_data[i].first < first_min ||
2671 sc->stsc_data[i].count < 1 ||
2672 sc->stsc_data[i].id < 1) {
2673 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);
2674 if (i+1 >= sc->stsc_count) {
2675 if (sc->stsc_data[i].count == 0 && i > 0) {
2679 sc->stsc_data[i].first = FFMAX(sc->stsc_data[i].first, first_min);
2680 if (i > 0 && sc->stsc_data[i].first <= sc->stsc_data[i-1].first)
2681 sc->stsc_data[i].first = FFMIN(sc->stsc_data[i-1].first + 1LL, INT_MAX);
2682 sc->stsc_data[i].count = FFMAX(sc->stsc_data[i].count, 1);
2683 sc->stsc_data[i].id = FFMAX(sc->stsc_data[i].id, 1);
2686 av_assert0(sc->stsc_data[i+1].first >= 2);
2687 // We replace this entry by the next valid
2688 sc->stsc_data[i].first = sc->stsc_data[i+1].first - 1;
2689 sc->stsc_data[i].count = sc->stsc_data[i+1].count;
2690 sc->stsc_data[i].id = sc->stsc_data[i+1].id;
2694 if (pb->eof_reached) {
2695 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted STSC atom\n");
2702 static inline int mov_stsc_index_valid(unsigned int index, unsigned int count)
2704 return index < count - 1;
2707 /* Compute the samples value for the stsc entry at the given index. */
2708 static inline int64_t mov_get_stsc_samples(MOVStreamContext *sc, unsigned int index)
2712 if (mov_stsc_index_valid(index, sc->stsc_count))
2713 chunk_count = sc->stsc_data[index + 1].first - sc->stsc_data[index].first;
2715 // Validation for stsc / stco happens earlier in mov_read_stsc + mov_read_trak.
2716 av_assert0(sc->stsc_data[index].first <= sc->chunk_count);
2717 chunk_count = sc->chunk_count - (sc->stsc_data[index].first - 1);
2720 return sc->stsc_data[index].count * (int64_t)chunk_count;
2723 static int mov_read_stps(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2726 MOVStreamContext *sc;
2727 unsigned i, entries;
2729 if (c->fc->nb_streams < 1)
2731 st = c->fc->streams[c->fc->nb_streams-1];
2734 avio_rb32(pb); // version + flags
2736 entries = avio_rb32(pb);
2738 av_log(c->fc, AV_LOG_WARNING, "Duplicated STPS atom\n");
2739 av_free(sc->stps_data);
2741 sc->stps_data = av_malloc_array(entries, sizeof(*sc->stps_data));
2743 return AVERROR(ENOMEM);
2745 for (i = 0; i < entries && !pb->eof_reached; i++) {
2746 sc->stps_data[i] = avio_rb32(pb);
2751 if (pb->eof_reached) {
2752 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted STPS atom\n");
2759 static int mov_read_stss(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2762 MOVStreamContext *sc;
2763 unsigned int i, entries;
2765 if (c->fc->nb_streams < 1)
2767 st = c->fc->streams[c->fc->nb_streams-1];
2770 avio_r8(pb); /* version */
2771 avio_rb24(pb); /* flags */
2773 entries = avio_rb32(pb);
2775 av_log(c->fc, AV_LOG_TRACE, "keyframe_count = %u\n", entries);
2779 sc->keyframe_absent = 1;
2780 if (!st->need_parsing && st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO)
2781 st->need_parsing = AVSTREAM_PARSE_HEADERS;
2785 av_log(c->fc, AV_LOG_WARNING, "Duplicated STSS atom\n");
2786 if (entries >= UINT_MAX / sizeof(int))
2787 return AVERROR_INVALIDDATA;
2788 av_freep(&sc->keyframes);
2789 sc->keyframe_count = 0;
2790 sc->keyframes = av_malloc_array(entries, sizeof(*sc->keyframes));
2792 return AVERROR(ENOMEM);
2794 for (i = 0; i < entries && !pb->eof_reached; i++) {
2795 sc->keyframes[i] = avio_rb32(pb);
2798 sc->keyframe_count = i;
2800 if (pb->eof_reached) {
2801 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted STSS atom\n");
2808 static int mov_read_stsz(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2811 MOVStreamContext *sc;
2812 unsigned int i, entries, sample_size, field_size, num_bytes;
2817 if (c->fc->nb_streams < 1)
2819 st = c->fc->streams[c->fc->nb_streams-1];
2822 avio_r8(pb); /* version */
2823 avio_rb24(pb); /* flags */
2825 if (atom.type == MKTAG('s','t','s','z')) {
2826 sample_size = avio_rb32(pb);
2827 if (!sc->sample_size) /* do not overwrite value computed in stsd */
2828 sc->sample_size = sample_size;
2829 sc->stsz_sample_size = sample_size;
2833 avio_rb24(pb); /* reserved */
2834 field_size = avio_r8(pb);
2836 entries = avio_rb32(pb);
2838 av_log(c->fc, AV_LOG_TRACE, "sample_size = %u sample_count = %u\n", sc->sample_size, entries);
2840 sc->sample_count = entries;
2844 if (field_size != 4 && field_size != 8 && field_size != 16 && field_size != 32) {
2845 av_log(c->fc, AV_LOG_ERROR, "Invalid sample field size %u\n", field_size);
2846 return AVERROR_INVALIDDATA;
2851 if (entries >= (UINT_MAX - 4) / field_size)
2852 return AVERROR_INVALIDDATA;
2853 if (sc->sample_sizes)
2854 av_log(c->fc, AV_LOG_WARNING, "Duplicated STSZ atom\n");
2855 av_free(sc->sample_sizes);
2856 sc->sample_count = 0;
2857 sc->sample_sizes = av_malloc_array(entries, sizeof(*sc->sample_sizes));
2858 if (!sc->sample_sizes)
2859 return AVERROR(ENOMEM);
2861 num_bytes = (entries*field_size+4)>>3;
2863 buf = av_malloc(num_bytes+AV_INPUT_BUFFER_PADDING_SIZE);
2865 av_freep(&sc->sample_sizes);
2866 return AVERROR(ENOMEM);
2869 ret = ffio_read_size(pb, buf, num_bytes);
2871 av_freep(&sc->sample_sizes);
2873 av_log(c->fc, AV_LOG_WARNING, "STSZ atom truncated\n");
2877 init_get_bits(&gb, buf, 8*num_bytes);
2879 for (i = 0; i < entries && !pb->eof_reached; i++) {
2880 sc->sample_sizes[i] = get_bits_long(&gb, field_size);
2881 if (sc->sample_sizes[i] < 0) {
2883 av_log(c->fc, AV_LOG_ERROR, "Invalid sample size %d\n", sc->sample_sizes[i]);
2884 return AVERROR_INVALIDDATA;
2886 sc->data_size += sc->sample_sizes[i];
2889 sc->sample_count = i;
2893 if (pb->eof_reached) {
2894 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted STSZ atom\n");
2901 static int mov_read_stts(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2904 MOVStreamContext *sc;
2905 unsigned int i, entries, alloc_size = 0;
2907 int64_t total_sample_count=0;
2909 if (c->fc->nb_streams < 1)
2911 st = c->fc->streams[c->fc->nb_streams-1];
2914 avio_r8(pb); /* version */
2915 avio_rb24(pb); /* flags */
2916 entries = avio_rb32(pb);
2918 av_log(c->fc, AV_LOG_TRACE, "track[%u].stts.entries = %u\n",
2919 c->fc->nb_streams-1, entries);
2922 av_log(c->fc, AV_LOG_WARNING, "Duplicated STTS atom\n");
2923 av_freep(&sc->stts_data);
2925 if (entries >= INT_MAX / sizeof(*sc->stts_data))
2926 return AVERROR(ENOMEM);
2928 for (i = 0; i < entries && !pb->eof_reached; i++) {
2929 int sample_duration;
2930 unsigned int sample_count;
2931 unsigned int min_entries = FFMIN(FFMAX(i + 1, 1024 * 1024), entries);
2932 MOVStts *stts_data = av_fast_realloc(sc->stts_data, &alloc_size,
2933 min_entries * sizeof(*sc->stts_data));
2935 av_freep(&sc->stts_data);
2937 return AVERROR(ENOMEM);
2939 sc->stts_count = min_entries;
2940 sc->stts_data = stts_data;
2942 sample_count=avio_rb32(pb);
2943 sample_duration = avio_rb32(pb);
2945 sc->stts_data[i].count= sample_count;
2946 sc->stts_data[i].duration= sample_duration;
2948 av_log(c->fc, AV_LOG_TRACE, "sample_count=%d, sample_duration=%d\n",
2949 sample_count, sample_duration);
2951 duration+=(int64_t)sample_duration*(uint64_t)sample_count;
2952 total_sample_count+=sample_count;
2958 duration <= INT64_MAX - sc->duration_for_fps &&
2959 total_sample_count <= INT_MAX - sc->nb_frames_for_fps
2961 sc->duration_for_fps += duration;
2962 sc->nb_frames_for_fps += total_sample_count;
2965 if (pb->eof_reached) {
2966 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted STTS atom\n");
2970 st->nb_frames= total_sample_count;
2972 st->duration= FFMIN(st->duration, duration);
2973 sc->track_end = duration;
2977 static int mov_read_sdtp(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2980 MOVStreamContext *sc;
2983 if (c->fc->nb_streams < 1)
2985 st = c->fc->streams[c->fc->nb_streams - 1];
2988 avio_r8(pb); /* version */
2989 avio_rb24(pb); /* flags */
2990 entries = atom.size - 4;
2992 av_log(c->fc, AV_LOG_TRACE, "track[%u].sdtp.entries = %" PRId64 "\n",
2993 c->fc->nb_streams - 1, entries);
2996 av_log(c->fc, AV_LOG_WARNING, "Duplicated SDTP atom\n");
2997 av_freep(&sc->sdtp_data);
3000 sc->sdtp_data = av_mallocz(entries);
3002 return AVERROR(ENOMEM);
3004 for (i = 0; i < entries && !pb->eof_reached; i++)
3005 sc->sdtp_data[i] = avio_r8(pb);
3011 static void mov_update_dts_shift(MOVStreamContext *sc, int duration, void *logctx)
3014 if (duration == INT_MIN) {
3015 av_log(logctx, AV_LOG_WARNING, "mov_update_dts_shift(): dts_shift set to %d\n", INT_MAX);
3018 sc->dts_shift = FFMAX(sc->dts_shift, -duration);
3022 static int mov_read_ctts(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3025 MOVStreamContext *sc;
3026 unsigned int i, entries, ctts_count = 0;
3028 if (c->fc->nb_streams < 1)
3030 st = c->fc->streams[c->fc->nb_streams-1];
3033 avio_r8(pb); /* version */
3034 avio_rb24(pb); /* flags */
3035 entries = avio_rb32(pb);
3037 av_log(c->fc, AV_LOG_TRACE, "track[%u].ctts.entries = %u\n", c->fc->nb_streams - 1, entries);
3041 if (entries >= UINT_MAX / sizeof(*sc->ctts_data))
3042 return AVERROR_INVALIDDATA;
3043 av_freep(&sc->ctts_data);
3044 sc->ctts_data = av_fast_realloc(NULL, &sc->ctts_allocated_size, entries * sizeof(*sc->ctts_data));
3046 return AVERROR(ENOMEM);
3048 for (i = 0; i < entries && !pb->eof_reached; i++) {
3049 int count =avio_rb32(pb);
3050 int duration =avio_rb32(pb);
3053 av_log(c->fc, AV_LOG_TRACE,
3054 "ignoring CTTS entry with count=%d duration=%d\n",
3059 add_ctts_entry(&sc->ctts_data, &ctts_count, &sc->ctts_allocated_size,
3062 av_log(c->fc, AV_LOG_TRACE, "count=%d, duration=%d\n",
3065 if (FFNABS(duration) < -(1<<28) && i+2<entries) {
3066 av_log(c->fc, AV_LOG_WARNING, "CTTS invalid\n");
3067 av_freep(&sc->ctts_data);
3073 mov_update_dts_shift(sc, duration, c->fc);
3076 sc->ctts_count = ctts_count;
3078 if (pb->eof_reached) {
3079 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted CTTS atom\n");
3083 av_log(c->fc, AV_LOG_TRACE, "dts shift %d\n", sc->dts_shift);
3088 static int mov_read_sbgp(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3091 MOVStreamContext *sc;
3092 unsigned int i, entries;
3094 uint32_t grouping_type;
3096 if (c->fc->nb_streams < 1)
3098 st = c->fc->streams[c->fc->nb_streams-1];
3101 version = avio_r8(pb); /* version */
3102 avio_rb24(pb); /* flags */
3103 grouping_type = avio_rl32(pb);
3104 if (grouping_type != MKTAG( 'r','a','p',' '))
3105 return 0; /* only support 'rap ' grouping */
3107 avio_rb32(pb); /* grouping_type_parameter */
3109 entries = avio_rb32(pb);
3113 av_log(c->fc, AV_LOG_WARNING, "Duplicated SBGP atom\n");
3114 av_free(sc->rap_group);
3115 sc->rap_group_count = 0;
3116 sc->rap_group = av_malloc_array(entries, sizeof(*sc->rap_group));
3118 return AVERROR(ENOMEM);
3120 for (i = 0; i < entries && !pb->eof_reached; i++) {
3121 sc->rap_group[i].count = avio_rb32(pb); /* sample_count */
3122 sc->rap_group[i].index = avio_rb32(pb); /* group_description_index */
3125 sc->rap_group_count = i;
3127 if (pb->eof_reached) {
3128 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted SBGP atom\n");
3136 * Get ith edit list entry (media time, duration).
3138 static int get_edit_list_entry(MOVContext *mov,
3139 const MOVStreamContext *msc,
3140 unsigned int edit_list_index,
3141 int64_t *edit_list_media_time,
3142 int64_t *edit_list_duration,
3143 int64_t global_timescale)
3145 if (edit_list_index == msc->elst_count) {
3148 *edit_list_media_time = msc->elst_data[edit_list_index].time;
3149 *edit_list_duration = msc->elst_data[edit_list_index].duration;
3151 /* duration is in global timescale units;convert to msc timescale */
3152 if (global_timescale == 0) {
3153 avpriv_request_sample(mov->fc, "Support for mvhd.timescale = 0 with editlists");
3156 *edit_list_duration = av_rescale(*edit_list_duration, msc->time_scale,
3162 * Find the closest previous frame to the timestamp_pts, in e_old index
3163 * entries. Searching for just any frame / just key frames can be controlled by
3164 * last argument 'flag'.
3165 * Note that if ctts_data is not NULL, we will always search for a key frame
3166 * irrespective of the value of 'flag'. If we don't find any keyframe, we will
3167 * return the first frame of the video.
3169 * Here the timestamp_pts is considered to be a presentation timestamp and
3170 * the timestamp of index entries are considered to be decoding timestamps.
3172 * Returns 0 if successful in finding a frame, else returns -1.
3173 * Places the found index corresponding output arg.
3175 * If ctts_old is not NULL, then refines the searched entry by searching
3176 * backwards from the found timestamp, to find the frame with correct PTS.
3178 * Places the found ctts_index and ctts_sample in corresponding output args.
3180 static int find_prev_closest_index(AVStream *st,
3181 AVIndexEntry *e_old,
3185 int64_t timestamp_pts,
3188 int64_t* ctts_index,
3189 int64_t* ctts_sample)
3191 MOVStreamContext *msc = st->priv_data;
3192 AVIndexEntry *e_keep = st->index_entries;
3193 int nb_keep = st->nb_index_entries;
3195 int64_t index_ctts_count;
3199 // If dts_shift > 0, then all the index timestamps will have to be offset by
3200 // at least dts_shift amount to obtain PTS.
3201 // Hence we decrement the searched timestamp_pts by dts_shift to find the closest index element.
3202 if (msc->dts_shift > 0) {
3203 timestamp_pts -= msc->dts_shift;
3206 st->index_entries = e_old;
3207 st->nb_index_entries = nb_old;
3208 *index = av_index_search_timestamp(st, timestamp_pts, flag | AVSEEK_FLAG_BACKWARD);
3210 // Keep going backwards in the index entries until the timestamp is the same.
3212 for (i = *index; i > 0 && e_old[i].timestamp == e_old[i - 1].timestamp;
3214 if ((flag & AVSEEK_FLAG_ANY) ||
3215 (e_old[i - 1].flags & AVINDEX_KEYFRAME)) {
3221 // If we have CTTS then refine the search, by searching backwards over PTS
3222 // computed by adding corresponding CTTS durations to index timestamps.
3223 if (ctts_data && *index >= 0) {
3224 av_assert0(ctts_index);
3225 av_assert0(ctts_sample);
3226 // Find out the ctts_index for the found frame.
3229 for (index_ctts_count = 0; index_ctts_count < *index; index_ctts_count++) {
3230 if (*ctts_index < ctts_count) {
3232 if (ctts_data[*ctts_index].count == *ctts_sample) {
3239 while (*index >= 0 && (*ctts_index) >= 0 && (*ctts_index) < ctts_count) {
3240 // Find a "key frame" with PTS <= timestamp_pts (So that we can decode B-frames correctly).
3241 // No need to add dts_shift to the timestamp here becase timestamp_pts has already been
3242 // compensated by dts_shift above.
3243 if ((e_old[*index].timestamp + ctts_data[*ctts_index].duration) <= timestamp_pts &&
3244 (e_old[*index].flags & AVINDEX_KEYFRAME)) {
3249 if (*ctts_sample == 0) {
3251 if (*ctts_index >= 0)
3252 *ctts_sample = ctts_data[*ctts_index].count - 1;
3259 /* restore AVStream state*/
3260 st->index_entries = e_keep;
3261 st->nb_index_entries = nb_keep;
3262 return *index >= 0 ? 0 : -1;
3266 * Add index entry with the given values, to the end of st->index_entries.
3267 * Returns the new size st->index_entries if successful, else returns -1.
3269 * This function is similar to ff_add_index_entry in libavformat/utils.c
3270 * except that here we are always unconditionally adding an index entry to
3271 * the end, instead of searching the entries list and skipping the add if
3272 * there is an existing entry with the same timestamp.
3273 * This is needed because the mov_fix_index calls this func with the same
3274 * unincremented timestamp for successive discarded frames.
3276 static int64_t add_index_entry(AVStream *st, int64_t pos, int64_t timestamp,
3277 int size, int distance, int flags)
3279 AVIndexEntry *entries, *ie;
3281 const size_t min_size_needed = (st->nb_index_entries + 1) * sizeof(AVIndexEntry);
3283 // Double the allocation each time, to lower memory fragmentation.
3284 // Another difference from ff_add_index_entry function.
3285 const size_t requested_size =
3286 min_size_needed > st->index_entries_allocated_size ?
3287 FFMAX(min_size_needed, 2 * st->index_entries_allocated_size) :
3290 if((unsigned)st->nb_index_entries + 1 >= UINT_MAX / sizeof(AVIndexEntry))
3293 entries = av_fast_realloc(st->index_entries,
3294 &st->index_entries_allocated_size,
3299 st->index_entries= entries;
3301 index= st->nb_index_entries++;
3302 ie= &entries[index];
3305 ie->timestamp = timestamp;
3306 ie->min_distance= distance;
3313 * Rewrite timestamps of index entries in the range [end_index - frame_duration_buffer_size, end_index)
3314 * by subtracting end_ts successively by the amounts given in frame_duration_buffer.
3316 static void fix_index_entry_timestamps(AVStream* st, int end_index, int64_t end_ts,
3317 int64_t* frame_duration_buffer,
3318 int frame_duration_buffer_size) {
3320 av_assert0(end_index >= 0 && end_index <= st->nb_index_entries);
3321 for (i = 0; i < frame_duration_buffer_size; i++) {
3322 end_ts -= frame_duration_buffer[frame_duration_buffer_size - 1 - i];
3323 st->index_entries[end_index - 1 - i].timestamp = end_ts;
3328 * Append a new ctts entry to ctts_data.
3329 * Returns the new ctts_count if successful, else returns -1.
3331 static int64_t add_ctts_entry(MOVStts** ctts_data, unsigned int* ctts_count, unsigned int* allocated_size,
3332 int count, int duration)
3334 MOVStts *ctts_buf_new;
3335 const size_t min_size_needed = (*ctts_count + 1) * sizeof(MOVStts);
3336 const size_t requested_size =
3337 min_size_needed > *allocated_size ?
3338 FFMAX(min_size_needed, 2 * (*allocated_size)) :
3341 if((unsigned)(*ctts_count) >= UINT_MAX / sizeof(MOVStts) - 1)
3344 ctts_buf_new = av_fast_realloc(*ctts_data, allocated_size, requested_size);
3349 *ctts_data = ctts_buf_new;
3351 ctts_buf_new[*ctts_count].count = count;
3352 ctts_buf_new[*ctts_count].duration = duration;
3354 *ctts_count = (*ctts_count) + 1;
3358 #define MAX_REORDER_DELAY 16
3359 static void mov_estimate_video_delay(MOVContext *c, AVStream* st) {
3360 MOVStreamContext *msc = st->priv_data;
3363 int ctts_sample = 0;
3364 int64_t pts_buf[MAX_REORDER_DELAY + 1]; // Circular buffer to sort pts.
3366 int j, r, num_swaps;
3368 for (j = 0; j < MAX_REORDER_DELAY + 1; j++)
3369 pts_buf[j] = INT64_MIN;
3371 if (st->codecpar->video_delay <= 0 && msc->ctts_data &&
3372 st->codecpar->codec_id == AV_CODEC_ID_H264) {
3373 st->codecpar->video_delay = 0;
3374 for(ind = 0; ind < st->nb_index_entries && ctts_ind < msc->ctts_count; ++ind) {
3375 // Point j to the last elem of the buffer and insert the current pts there.
3377 buf_start = (buf_start + 1);
3378 if (buf_start == MAX_REORDER_DELAY + 1)
3381 pts_buf[j] = st->index_entries[ind].timestamp + msc->ctts_data[ctts_ind].duration;
3383 // The timestamps that are already in the sorted buffer, and are greater than the
3384 // current pts, are exactly the timestamps that need to be buffered to output PTS
3385 // in correct sorted order.
3386 // Hence the video delay (which is the buffer size used to sort DTS and output PTS),
3387 // can be computed as the maximum no. of swaps any particular timestamp needs to
3388 // go through, to keep this buffer in sorted order.
3390 while (j != buf_start) {
3392 if (r < 0) r = MAX_REORDER_DELAY;
3393 if (pts_buf[j] < pts_buf[r]) {
3394 FFSWAP(int64_t, pts_buf[j], pts_buf[r]);
3401 st->codecpar->video_delay = FFMAX(st->codecpar->video_delay, num_swaps);
3404 if (ctts_sample == msc->ctts_data[ctts_ind].count) {
3409 av_log(c->fc, AV_LOG_DEBUG, "Setting codecpar->delay to %d for stream st: %d\n",
3410 st->codecpar->video_delay, st->index);
3414 static void mov_current_sample_inc(MOVStreamContext *sc)
3416 sc->current_sample++;
3417 sc->current_index++;
3418 if (sc->index_ranges &&
3419 sc->current_index >= sc->current_index_range->end &&
3420 sc->current_index_range->end) {
3421 sc->current_index_range++;
3422 sc->current_index = sc->current_index_range->start;
3426 static void mov_current_sample_dec(MOVStreamContext *sc)
3428 sc->current_sample--;
3429 sc->current_index--;
3430 if (sc->index_ranges &&
3431 sc->current_index < sc->current_index_range->start &&
3432 sc->current_index_range > sc->index_ranges) {
3433 sc->current_index_range--;
3434 sc->current_index = sc->current_index_range->end - 1;
3438 static void mov_current_sample_set(MOVStreamContext *sc, int current_sample)
3442 sc->current_sample = current_sample;
3443 sc->current_index = current_sample;
3444 if (!sc->index_ranges) {
3448 for (sc->current_index_range = sc->index_ranges;
3449 sc->current_index_range->end;
3450 sc->current_index_range++) {
3451 range_size = sc->current_index_range->end - sc->current_index_range->start;
3452 if (range_size > current_sample) {
3453 sc->current_index = sc->current_index_range->start + current_sample;
3456 current_sample -= range_size;
3461 * Fix st->index_entries, so that it contains only the entries (and the entries
3462 * which are needed to decode them) that fall in the edit list time ranges.
3463 * Also fixes the timestamps of the index entries to match the timeline
3464 * specified the edit lists.
3466 static void mov_fix_index(MOVContext *mov, AVStream *st)
3468 MOVStreamContext *msc = st->priv_data;
3469 AVIndexEntry *e_old = st->index_entries;
3470 int nb_old = st->nb_index_entries;
3471 const AVIndexEntry *e_old_end = e_old + nb_old;
3472 const AVIndexEntry *current = NULL;
3473 MOVStts *ctts_data_old = msc->ctts_data;
3474 int64_t ctts_index_old = 0;
3475 int64_t ctts_sample_old = 0;
3476 int64_t ctts_count_old = msc->ctts_count;
3477 int64_t edit_list_media_time = 0;
3478 int64_t edit_list_duration = 0;
3479 int64_t frame_duration = 0;
3480 int64_t edit_list_dts_counter = 0;
3481 int64_t edit_list_dts_entry_end = 0;
3482 int64_t edit_list_start_ctts_sample = 0;
3484 int64_t curr_ctts = 0;
3485 int64_t empty_edits_sum_duration = 0;
3486 int64_t edit_list_index = 0;
3489 int64_t start_dts = 0;
3490 int64_t edit_list_start_encountered = 0;
3491 int64_t search_timestamp = 0;
3492 int64_t* frame_duration_buffer = NULL;
3493 int num_discarded_begin = 0;
3494 int first_non_zero_audio_edit = -1;
3495 int packet_skip_samples = 0;
3496 MOVIndexRange *current_index_range;
3498 int found_keyframe_after_edit = 0;
3499 int found_non_empty_edit = 0;
3501 if (!msc->elst_data || msc->elst_count <= 0 || nb_old <= 0) {
3505 // allocate the index ranges array
3506 msc->index_ranges = av_malloc((msc->elst_count + 1) * sizeof(msc->index_ranges[0]));
3507 if (!msc->index_ranges) {
3508 av_log(mov->fc, AV_LOG_ERROR, "Cannot allocate index ranges buffer\n");
3511 msc->current_index_range = msc->index_ranges;
3512 current_index_range = msc->index_ranges - 1;
3514 // Clean AVStream from traces of old index
3515 st->index_entries = NULL;
3516 st->index_entries_allocated_size = 0;
3517 st->nb_index_entries = 0;
3519 // Clean ctts fields of MOVStreamContext
3520 msc->ctts_data = NULL;
3521 msc->ctts_count = 0;
3522 msc->ctts_index = 0;
3523 msc->ctts_sample = 0;
3524 msc->ctts_allocated_size = 0;
3526 // Reinitialize min_corrected_pts so that it can be computed again.
3527 msc->min_corrected_pts = -1;
3529 // If the dts_shift is positive (in case of negative ctts values in mov),
3530 // then negate the DTS by dts_shift
3531 if (msc->dts_shift > 0) {
3532 edit_list_dts_entry_end -= msc->dts_shift;
3533 av_log(mov->fc, AV_LOG_DEBUG, "Shifting DTS by %d because of negative CTTS.\n", msc->dts_shift);
3536 start_dts = edit_list_dts_entry_end;
3538 while (get_edit_list_entry(mov, msc, edit_list_index, &edit_list_media_time,
3539 &edit_list_duration, mov->time_scale)) {
3540 av_log(mov->fc, AV_LOG_DEBUG, "Processing st: %d, edit list %"PRId64" - media time: %"PRId64", duration: %"PRId64"\n",
3541 st->index, edit_list_index, edit_list_media_time, edit_list_duration);
3543 edit_list_dts_counter = edit_list_dts_entry_end;
3544 edit_list_dts_entry_end += edit_list_duration;
3545 num_discarded_begin = 0;
3546 if (!found_non_empty_edit && edit_list_media_time == -1) {
3547 empty_edits_sum_duration += edit_list_duration;
3550 found_non_empty_edit = 1;
3552 // If we encounter a non-negative edit list reset the skip_samples/start_pad fields and set them
3553 // according to the edit list below.
3554 if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
3555 if (first_non_zero_audio_edit < 0) {
3556 first_non_zero_audio_edit = 1;
3558 first_non_zero_audio_edit = 0;
3561 if (first_non_zero_audio_edit > 0)
3562 st->skip_samples = msc->start_pad = 0;
3565 // While reordering frame index according to edit list we must handle properly
3566 // the scenario when edit list entry starts from none key frame.
3567 // We find closest previous key frame and preserve it and consequent frames in index.
3568 // All frames which are outside edit list entry time boundaries will be dropped after decoding.
3569 search_timestamp = edit_list_media_time;
3570 if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
3571 // Audio decoders like AAC need need a decoder delay samples previous to the current sample,
3572 // to correctly decode this frame. Hence for audio we seek to a frame 1 sec. before the
3573 // edit_list_media_time to cover the decoder delay.
3574 search_timestamp = FFMAX(search_timestamp - msc->time_scale, e_old[0].timestamp);
3577 if (find_prev_closest_index(st, e_old, nb_old, ctts_data_old, ctts_count_old, search_timestamp, 0,
3578 &index, &ctts_index_old, &ctts_sample_old) < 0) {
3579 av_log(mov->fc, AV_LOG_WARNING,
3580 "st: %d edit list: %"PRId64" Missing key frame while searching for timestamp: %"PRId64"\n",
3581 st->index, edit_list_index, search_timestamp);
3582 if (find_prev_closest_index(st, e_old, nb_old, ctts_data_old, ctts_count_old, search_timestamp, AVSEEK_FLAG_ANY,
3583 &index, &ctts_index_old, &ctts_sample_old) < 0) {
3584 av_log(mov->fc, AV_LOG_WARNING,
3585 "st: %d edit list %"PRId64" Cannot find an index entry before timestamp: %"PRId64".\n",
3586 st->index, edit_list_index, search_timestamp);
3589 ctts_sample_old = 0;
3592 current = e_old + index;
3593 edit_list_start_ctts_sample = ctts_sample_old;
3595 // Iterate over index and arrange it according to edit list
3596 edit_list_start_encountered = 0;
3597 found_keyframe_after_edit = 0;
3598 for (; current < e_old_end; current++, index++) {
3599 // check if frame outside edit list mark it for discard
3600 frame_duration = (current + 1 < e_old_end) ?
3601 ((current + 1)->timestamp - current->timestamp) : edit_list_duration;
3603 flags = current->flags;
3605 // frames (pts) before or after edit list
3606 curr_cts = current->timestamp + msc->dts_shift;
3609 if (ctts_data_old && ctts_index_old < ctts_count_old) {
3610 curr_ctts = ctts_data_old[ctts_index_old].duration;
3611 av_log(mov->fc, AV_LOG_DEBUG, "stts: %"PRId64" ctts: %"PRId64", ctts_index: %"PRId64", ctts_count: %"PRId64"\n",
3612 curr_cts, curr_ctts, ctts_index_old, ctts_count_old);
3613 curr_cts += curr_ctts;
3615 if (ctts_sample_old == ctts_data_old[ctts_index_old].count) {
3616 if (add_ctts_entry(&msc->ctts_data, &msc->ctts_count,
3617 &msc->ctts_allocated_size,
3618 ctts_data_old[ctts_index_old].count - edit_list_start_ctts_sample,
3619 ctts_data_old[ctts_index_old].duration) == -1) {
3620 av_log(mov->fc, AV_LOG_ERROR, "Cannot add CTTS entry %"PRId64" - {%"PRId64", %d}\n",
3622 ctts_data_old[ctts_index_old].count - edit_list_start_ctts_sample,
3623 ctts_data_old[ctts_index_old].duration);
3627 ctts_sample_old = 0;
3628 edit_list_start_ctts_sample = 0;
3632 if (curr_cts < edit_list_media_time || curr_cts >= (edit_list_duration + edit_list_media_time)) {
3633 if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO && st->codecpar->codec_id != AV_CODEC_ID_VORBIS &&
3634 curr_cts < edit_list_media_time && curr_cts + frame_duration > edit_list_media_time &&
3635 first_non_zero_audio_edit > 0) {
3636 packet_skip_samples = edit_list_media_time - curr_cts;
3637 st->skip_samples += packet_skip_samples;
3639 // Shift the index entry timestamp by packet_skip_samples to be correct.
3640 edit_list_dts_counter -= packet_skip_samples;
3641 if (edit_list_start_encountered == 0) {
3642 edit_list_start_encountered = 1;
3643 // Make timestamps strictly monotonically increasing for audio, by rewriting timestamps for
3644 // discarded packets.
3645 if (frame_duration_buffer) {
3646 fix_index_entry_timestamps(st, st->nb_index_entries, edit_list_dts_counter,
3647 frame_duration_buffer, num_discarded_begin);
3648 av_freep(&frame_duration_buffer);
3652 av_log(mov->fc, AV_LOG_DEBUG, "skip %d audio samples from curr_cts: %"PRId64"\n", packet_skip_samples, curr_cts);
3654 flags |= AVINDEX_DISCARD_FRAME;
3655 av_log(mov->fc, AV_LOG_DEBUG, "drop a frame at curr_cts: %"PRId64" @ %"PRId64"\n", curr_cts, index);
3657 if (edit_list_start_encountered == 0) {
3658 num_discarded_begin++;
3659 frame_duration_buffer = av_realloc(frame_duration_buffer,
3660 num_discarded_begin * sizeof(int64_t));
3661 if (!frame_duration_buffer) {
3662 av_log(mov->fc, AV_LOG_ERROR, "Cannot reallocate frame duration buffer\n");
3665 frame_duration_buffer[num_discarded_begin - 1] = frame_duration;
3667 // Increment skip_samples for the first non-zero audio edit list
3668 if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO &&
3669 first_non_zero_audio_edit > 0 && st->codecpar->codec_id != AV_CODEC_ID_VORBIS) {
3670 st->skip_samples += frame_duration;
3675 if (msc->min_corrected_pts < 0) {
3676 msc->min_corrected_pts = edit_list_dts_counter + curr_ctts + msc->dts_shift;
3678 msc->min_corrected_pts = FFMIN(msc->min_corrected_pts, edit_list_dts_counter + curr_ctts + msc->dts_shift);
3680 if (edit_list_start_encountered == 0) {
3681 edit_list_start_encountered = 1;
3682 // Make timestamps strictly monotonically increasing by rewriting timestamps for
3683 // discarded packets.
3684 if (frame_duration_buffer) {
3685 fix_index_entry_timestamps(st, st->nb_index_entries, edit_list_dts_counter,
3686 frame_duration_buffer, num_discarded_begin);
3687 av_freep(&frame_duration_buffer);
3692 if (add_index_entry(st, current->pos, edit_list_dts_counter, current->size,
3693 current->min_distance, flags) == -1) {
3694 av_log(mov->fc, AV_LOG_ERROR, "Cannot add index entry\n");
3698 // Update the index ranges array
3699 if (current_index_range < msc->index_ranges || index != current_index_range->end) {
3700 current_index_range++;
3701 current_index_range->start = index;
3703 current_index_range->end = index + 1;
3705 // Only start incrementing DTS in frame_duration amounts, when we encounter a frame in edit list.
3706 if (edit_list_start_encountered > 0) {
3707 edit_list_dts_counter = edit_list_dts_counter + frame_duration;
3710 // Break when found first key frame after edit entry completion
3711 if ((curr_cts + frame_duration >= (edit_list_duration + edit_list_media_time)) &&
3712 ((flags & AVINDEX_KEYFRAME) || ((st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO)))) {
3713 if (ctts_data_old) {
3714 // If we have CTTS and this is the first keyframe after edit elist,
3715 // wait for one more, because there might be trailing B-frames after this I-frame
3716 // that do belong to the edit.
3717 if (st->codecpar->codec_type != AVMEDIA_TYPE_AUDIO && found_keyframe_after_edit == 0) {
3718 found_keyframe_after_edit = 1;
3721 if (ctts_sample_old != 0) {
3722 if (add_ctts_entry(&msc->ctts_data, &msc->ctts_count,
3723 &msc->ctts_allocated_size,
3724 ctts_sample_old - edit_list_start_ctts_sample,
3725 ctts_data_old[ctts_index_old].duration) == -1) {
3726 av_log(mov->fc, AV_LOG_ERROR, "Cannot add CTTS entry %"PRId64" - {%"PRId64", %d}\n",
3727 ctts_index_old, ctts_sample_old - edit_list_start_ctts_sample,
3728 ctts_data_old[ctts_index_old].duration);
3737 // If there are empty edits, then msc->min_corrected_pts might be positive
3738 // intentionally. So we subtract the sum duration of emtpy edits here.
3739 msc->min_corrected_pts -= empty_edits_sum_duration;
3741 // If the minimum pts turns out to be greater than zero after fixing the index, then we subtract the
3742 // dts by that amount to make the first pts zero.
3743 if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
3744 if (msc->min_corrected_pts > 0) {
3745 av_log(mov->fc, AV_LOG_DEBUG, "Offset DTS by %"PRId64" to make first pts zero.\n", msc->min_corrected_pts);
3746 for (i = 0; i < st->nb_index_entries; ++i) {
3747 st->index_entries[i].timestamp -= msc->min_corrected_pts;
3751 // Start time should be equal to zero or the duration of any empty edits.
3752 st->start_time = empty_edits_sum_duration;
3754 // Update av stream length, if it ends up shorter than the track's media duration
3755 st->duration = FFMIN(st->duration, edit_list_dts_entry_end - start_dts);
3756 msc->start_pad = st->skip_samples;
3758 // Free the old index and the old CTTS structures
3760 av_free(ctts_data_old);
3761 av_freep(&frame_duration_buffer);
3763 // Null terminate the index ranges array
3764 current_index_range++;
3765 current_index_range->start = 0;
3766 current_index_range->end = 0;
3767 msc->current_index = msc->index_ranges[0].start;
3770 static void mov_build_index(MOVContext *mov, AVStream *st)
3772 MOVStreamContext *sc = st->priv_data;
3773 int64_t current_offset;
3774 int64_t current_dts = 0;
3775 unsigned int stts_index = 0;
3776 unsigned int stsc_index = 0;
3777 unsigned int stss_index = 0;
3778 unsigned int stps_index = 0;
3780 uint64_t stream_size = 0;
3781 MOVStts *ctts_data_old = sc->ctts_data;
3782 unsigned int ctts_count_old = sc->ctts_count;
3784 if (sc->elst_count) {
3785 int i, edit_start_index = 0, multiple_edits = 0;
3786 int64_t empty_duration = 0; // empty duration of the first edit list entry
3787 int64_t start_time = 0; // start time of the media
3789 for (i = 0; i < sc->elst_count; i++) {
3790 const MOVElst *e = &sc->elst_data[i];
3791 if (i == 0 && e->time == -1) {
3792 /* if empty, the first entry is the start time of the stream
3793 * relative to the presentation itself */
3794 empty_duration = e->duration;
3795 edit_start_index = 1;
3796 } else if (i == edit_start_index && e->time >= 0) {
3797 start_time = e->time;
3803 if (multiple_edits && !mov->advanced_editlist)
3804 av_log(mov->fc, AV_LOG_WARNING, "multiple edit list entries, "
3805 "Use -advanced_editlist to correctly decode otherwise "
3806 "a/v desync might occur\n");
3808 /* adjust first dts according to edit list */
3809 if ((empty_duration || start_time) && mov->time_scale > 0) {
3811 empty_duration = av_rescale(empty_duration, sc->time_scale, mov->time_scale);
3812 sc->time_offset = start_time - empty_duration;
3813 sc->min_corrected_pts = start_time;
3814 if (!mov->advanced_editlist)
3815 current_dts = -sc->time_offset;
3818 if (!multiple_edits && !mov->advanced_editlist &&
3819 st->codecpar->codec_id == AV_CODEC_ID_AAC && start_time > 0)
3820 sc->start_pad = start_time;
3823 /* only use old uncompressed audio chunk demuxing when stts specifies it */
3824 if (!(st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO &&
3825 sc->stts_count == 1 && sc->stts_data[0].duration == 1)) {
3826 unsigned int current_sample = 0;
3827 unsigned int stts_sample = 0;
3828 unsigned int sample_size;
3829 unsigned int distance = 0;
3830 unsigned int rap_group_index = 0;
3831 unsigned int rap_group_sample = 0;
3832 int64_t last_dts = 0;
3833 int64_t dts_correction = 0;
3834 int rap_group_present = sc->rap_group_count && sc->rap_group;
3835 int key_off = (sc->keyframe_count && sc->keyframes[0] > 0) || (sc->stps_count && sc->stps_data[0] > 0);
3837 current_dts -= sc->dts_shift;
3838 last_dts = current_dts;
3840 if (!sc->sample_count || st->nb_index_entries)
3842 if (sc->sample_count >= UINT_MAX / sizeof(*st->index_entries) - st->nb_index_entries)
3844 if (av_reallocp_array(&st->index_entries,
3845 st->nb_index_entries + sc->sample_count,
3846 sizeof(*st->index_entries)) < 0) {
3847 st->nb_index_entries = 0;
3850 st->index_entries_allocated_size = (st->nb_index_entries + sc->sample_count) * sizeof(*st->index_entries);
3852 if (ctts_data_old) {
3853 // Expand ctts entries such that we have a 1-1 mapping with samples
3854 if (sc->sample_count >= UINT_MAX / sizeof(*sc->ctts_data))
3857 sc->ctts_allocated_size = 0;
3858 sc->ctts_data = av_fast_realloc(NULL, &sc->ctts_allocated_size,
3859 sc->sample_count * sizeof(*sc->ctts_data));
3860 if (!sc->ctts_data) {
3861 av_free(ctts_data_old);
3865 memset((uint8_t*)(sc->ctts_data), 0, sc->ctts_allocated_size);
3867 for (i = 0; i < ctts_count_old &&
3868 sc->ctts_count < sc->sample_count; i++)
3869 for (j = 0; j < ctts_data_old[i].count &&
3870 sc->ctts_count < sc->sample_count; j++)
3871 add_ctts_entry(&sc->ctts_data, &sc->ctts_count,
3872 &sc->ctts_allocated_size, 1,
3873 ctts_data_old[i].duration);
3874 av_free(ctts_data_old);
3877 for (i = 0; i < sc->chunk_count; i++) {
3878 int64_t next_offset = i+1 < sc->chunk_count ? sc->chunk_offsets[i+1] : INT64_MAX;
3879 current_offset = sc->chunk_offsets[i];
3880 while (mov_stsc_index_valid(stsc_index, sc->stsc_count) &&
3881 i + 1 == sc->stsc_data[stsc_index + 1].first)
3884 if (next_offset > current_offset && sc->sample_size>0 && sc->sample_size < sc->stsz_sample_size &&
3885 sc->stsc_data[stsc_index].count * (int64_t)sc->stsz_sample_size > next_offset - current_offset) {
3886 av_log(mov->fc, AV_LOG_WARNING, "STSZ sample size %d invalid (too large), ignoring\n", sc->stsz_sample_size);
3887 sc->stsz_sample_size = sc->sample_size;
3889 if (sc->stsz_sample_size>0 && sc->stsz_sample_size < sc->sample_size) {
3890 av_log(mov->fc, AV_LOG_WARNING, "STSZ sample size %d invalid (too small), ignoring\n", sc->stsz_sample_size);
3891 sc->stsz_sample_size = sc->sample_size;
3894 for (j = 0; j < sc->stsc_data[stsc_index].count; j++) {
3896 if (current_sample >= sc->sample_count) {
3897 av_log(mov->fc, AV_LOG_ERROR, "wrong sample count\n");
3901 if (!sc->keyframe_absent && (!sc->keyframe_count || current_sample+key_off == sc->keyframes[stss_index])) {
3903 if (stss_index + 1 < sc->keyframe_count)
3905 } else if (sc->stps_count && current_sample+key_off == sc->stps_data[stps_index]) {
3907 if (stps_index + 1 < sc->stps_count)
3910 if (rap_group_present && rap_group_index < sc->rap_group_count) {
3911 if (sc->rap_group[rap_group_index].index > 0)
3913 if (++rap_group_sample == sc->rap_group[rap_group_index].count) {
3914 rap_group_sample = 0;
3918 if (sc->keyframe_absent
3920 && !rap_group_present
3921 && (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO || (i==0 && j==0)))
3925 sample_size = sc->stsz_sample_size > 0 ? sc->stsz_sample_size : sc->sample_sizes[current_sample];
3926 if (sc->pseudo_stream_id == -1 ||
3927 sc->stsc_data[stsc_index].id - 1 == sc->pseudo_stream_id) {
3929 if (sample_size > 0x3FFFFFFF) {
3930 av_log(mov->fc, AV_LOG_ERROR, "Sample size %u is too large\n", sample_size);
3933 e = &st->index_entries[st->nb_index_entries++];
3934 e->pos = current_offset;
3935 e->timestamp = current_dts;
3936 e->size = sample_size;
3937 e->min_distance = distance;
3938 e->flags = keyframe ? AVINDEX_KEYFRAME : 0;
3939 av_log(mov->fc, AV_LOG_TRACE, "AVIndex stream %d, sample %u, offset %"PRIx64", dts %"PRId64", "
3940 "size %u, distance %u, keyframe %d\n", st->index, current_sample,
3941 current_offset, current_dts, sample_size, distance, keyframe);
3942 if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && st->nb_index_entries < 100)
3943 ff_rfps_add_frame(mov->fc, st, current_dts);
3946 current_offset += sample_size;
3947 stream_size += sample_size;
3949 /* A negative sample duration is invalid based on the spec,
3950 * but some samples need it to correct the DTS. */
3951 if (sc->stts_data[stts_index].duration < 0) {
3952 av_log(mov->fc, AV_LOG_WARNING,
3953 "Invalid SampleDelta %d in STTS, at %d st:%d\n",
3954 sc->stts_data[stts_index].duration, stts_index,
3956 dts_correction += sc->stts_data[stts_index].duration - 1;
3957 sc->stts_data[stts_index].duration = 1;
3959 current_dts += sc->stts_data[stts_index].duration;
3960 if (!dts_correction || current_dts + dts_correction > last_dts) {
3961 current_dts += dts_correction;
3964 /* Avoid creating non-monotonous DTS */
3965 dts_correction += current_dts - last_dts - 1;
3966 current_dts = last_dts + 1;
3968 last_dts = current_dts;
3972 if (stts_index + 1 < sc->stts_count && stts_sample == sc->stts_data[stts_index].count) {
3978 if (st->duration > 0)
3979 st->codecpar->bit_rate = stream_size*8*sc->time_scale/st->duration;
3981 unsigned chunk_samples, total = 0;
3983 if (!sc->chunk_count)
3986 // compute total chunk count
3987 for (i = 0; i < sc->stsc_count; i++) {
3988 unsigned count, chunk_count;
3990 chunk_samples = sc->stsc_data[i].count;
3991 if (i != sc->stsc_count - 1 &&
3992 sc->samples_per_frame && chunk_samples % sc->samples_per_frame) {
3993 av_log(mov->fc, AV_LOG_ERROR, "error unaligned chunk\n");
3997 if (sc->samples_per_frame >= 160) { // gsm
3998 count = chunk_samples / sc->samples_per_frame;
3999 } else if (sc->samples_per_frame > 1) {
4000 unsigned samples = (1024/sc->samples_per_frame)*sc->samples_per_frame;
4001 count = (chunk_samples+samples-1) / samples;
4003 count = (chunk_samples+1023) / 1024;
4006 if (mov_stsc_index_valid(i, sc->stsc_count))
4007 chunk_count = sc->stsc_data[i+1].first - sc->stsc_data[i].first;
4009 chunk_count = sc->chunk_count - (sc->stsc_data[i].first - 1);
4010 total += chunk_count * count;
4013 av_log(mov->fc, AV_LOG_TRACE, "chunk count %u\n", total);
4014 if (total >= UINT_MAX / sizeof(*st->index_entries) - st->nb_index_entries)
4016 if (av_reallocp_array(&st->index_entries,
4017 st->nb_index_entries + total,
4018 sizeof(*st->index_entries)) < 0) {
4019 st->nb_index_entries = 0;
4022 st->index_entries_allocated_size = (st->nb_index_entries + total) * sizeof(*st->index_entries);
4025 for (i = 0; i < sc->chunk_count; i++) {
4026 current_offset = sc->chunk_offsets[i];
4027 if (mov_stsc_index_valid(stsc_index, sc->stsc_count) &&
4028 i + 1 == sc->stsc_data[stsc_index + 1].first)
4030 chunk_samples = sc->stsc_data[stsc_index].count;
4032 while (chunk_samples > 0) {
4034 unsigned size, samples;
4036 if (sc->samples_per_frame > 1 && !sc->bytes_per_frame) {
4037 avpriv_request_sample(mov->fc,
4038 "Zero bytes per frame, but %d samples per frame",
4039 sc->samples_per_frame);
4043 if (sc->samples_per_frame >= 160) { // gsm
4044 samples = sc->samples_per_frame;
4045 size = sc->bytes_per_frame;
4047 if (sc->samples_per_frame > 1) {
4048 samples = FFMIN((1024 / sc->samples_per_frame)*
4049 sc->samples_per_frame, chunk_samples);
4050 size = (samples / sc->samples_per_frame) * sc->bytes_per_frame;
4052 samples = FFMIN(1024, chunk_samples);
4053 size = samples * sc->sample_size;
4057 if (st->nb_index_entries >= total) {
4058 av_log(mov->fc, AV_LOG_ERROR, "wrong chunk count %u\n", total);
4061 if (size > 0x3FFFFFFF) {
4062 av_log(mov->fc, AV_LOG_ERROR, "Sample size %u is too large\n", size);
4065 e = &st->index_entries[st->nb_index_entries++];
4066 e->pos = current_offset;
4067 e->timestamp = current_dts;
4069 e->min_distance = 0;
4070 e->flags = AVINDEX_KEYFRAME;
4071 av_log(mov->fc, AV_LOG_TRACE, "AVIndex stream %d, chunk %u, offset %"PRIx64", dts %"PRId64", "
4072 "size %u, duration %u\n", st->index, i, current_offset, current_dts,
4075 current_offset += size;
4076 current_dts += samples;
4077 chunk_samples -= samples;
4082 if (!mov->ignore_editlist && mov->advanced_editlist) {
4083 // Fix index according to edit lists.
4084 mov_fix_index(mov, st);
4087 // Update start time of the stream.
4088 if (st->start_time == AV_NOPTS_VALUE && st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && st->nb_index_entries > 0) {
4089 st->start_time = st->index_entries[0].timestamp + sc->dts_shift;
4090 if (sc->ctts_data) {
4091 st->start_time += sc->ctts_data[0].duration;
4095 mov_estimate_video_delay(mov, st);
4098 static int test_same_origin(const char *src, const char *ref) {
4108 av_url_split(src_proto, sizeof(src_proto), src_auth, sizeof(src_auth), src_host, sizeof(src_host), &src_port, NULL, 0, src);
4109 av_url_split(ref_proto, sizeof(ref_proto), ref_auth, sizeof(ref_auth), ref_host, sizeof(ref_host), &ref_port, NULL, 0, ref);
4111 if (strlen(src) == 0) {
4113 } else if (strlen(src_auth) + 1 >= sizeof(src_auth) ||
4114 strlen(ref_auth) + 1 >= sizeof(ref_auth) ||
4115 strlen(src_host) + 1 >= sizeof(src_host) ||
4116 strlen(ref_host) + 1 >= sizeof(ref_host)) {
4118 } else if (strcmp(src_proto, ref_proto) ||
4119 strcmp(src_auth, ref_auth) ||
4120 strcmp(src_host, ref_host) ||
4121 src_port != ref_port) {
4127 static int mov_open_dref(MOVContext *c, AVIOContext **pb, const char *src, MOVDref *ref)
4129 /* try relative path, we do not try the absolute because it can leak information about our
4130 system to an attacker */
4131 if (ref->nlvl_to > 0 && ref->nlvl_from > 0) {
4132 char filename[1025];
4133 const char *src_path;
4136 /* find a source dir */
4137 src_path = strrchr(src, '/');
4143 /* find a next level down to target */
4144 for (i = 0, l = strlen(ref->path) - 1; l >= 0; l--)
4145 if (ref->path[l] == '/') {
4146 if (i == ref->nlvl_to - 1)
4152 /* compose filename if next level down to target was found */
4153 if (i == ref->nlvl_to - 1 && src_path - src < sizeof(filename)) {
4154 memcpy(filename, src, src_path - src);
4155 filename[src_path - src] = 0;
4157 for (i = 1; i < ref->nlvl_from; i++)
4158 av_strlcat(filename, "../", sizeof(filename));
4160 av_strlcat(filename, ref->path + l + 1, sizeof(filename));
4161 if (!c->use_absolute_path) {
4162 int same_origin = test_same_origin(src, filename);
4165 av_log(c->fc, AV_LOG_ERROR,
4166 "Reference with mismatching origin, %s not tried for security reasons, "
4167 "set demuxer option use_absolute_path to allow it anyway\n",
4169 return AVERROR(ENOENT);
4172 if(strstr(ref->path + l + 1, "..") ||
4173 strstr(ref->path + l + 1, ":") ||
4174 (ref->nlvl_from > 1 && same_origin < 0) ||
4175 (filename[0] == '/' && src_path == src))
4176 return AVERROR(ENOENT);
4179 if (strlen(filename) + 1 == sizeof(filename))
4180 return AVERROR(ENOENT);
4181 if (!c->fc->io_open(c->fc, pb, filename, AVIO_FLAG_READ, NULL))
4184 } else if (c->use_absolute_path) {
4185 av_log(c->fc, AV_LOG_WARNING, "Using absolute path on user request, "
4186 "this is a possible security issue\n");
4187 if (!c->fc->io_open(c->fc, pb, ref->path, AVIO_FLAG_READ, NULL))
4190 av_log(c->fc, AV_LOG_ERROR,
4191 "Absolute path %s not tried for security reasons, "
4192 "set demuxer option use_absolute_path to allow absolute paths\n",
4196 return AVERROR(ENOENT);
4199 static void fix_timescale(MOVContext *c, MOVStreamContext *sc)
4201 if (sc->time_scale <= 0) {
4202 av_log(c->fc, AV_LOG_WARNING, "stream %d, timescale not set\n", sc->ffindex);
4203 sc->time_scale = c->time_scale;
4204 if (sc->time_scale <= 0)
4209 static int mov_read_trak(MOVContext *c, AVIOContext *pb, MOVAtom atom)
4212 MOVStreamContext *sc;
4215 st = avformat_new_stream(c->fc, NULL);
4216 if (!st) return AVERROR(ENOMEM);
4218 sc = av_mallocz(sizeof(MOVStreamContext));
4219 if (!sc) return AVERROR(ENOMEM);
4222 st->codecpar->codec_type = AVMEDIA_TYPE_DATA;
4223 sc->ffindex = st->index;
4224 c->trak_index = st->index;
4226 if ((ret = mov_read_default(c, pb, atom)) < 0)
4231 // Here stsc refers to a chunk not described in stco. This is technically invalid,
4232 // but we can overlook it (clearing stsc) whenever stts_count == 0 (indicating no samples).
4233 if (!sc->chunk_count && !sc->stts_count && sc->stsc_count) {
4235 av_freep(&sc->stsc_data);
4239 if ((sc->chunk_count && (!sc->stts_count || !sc->stsc_count ||
4240 (!sc->sample_size && !sc->sample_count))) ||
4241 (!sc->chunk_count && sc->sample_count)) {
4242 av_log(c->fc, AV_LOG_ERROR, "stream %d, missing mandatory atoms, broken header\n",
4246 if (sc->stsc_count && sc->stsc_data[ sc->stsc_count - 1 ].first > sc->chunk_count) {
4247 av_log(c->fc, AV_LOG_ERROR, "stream %d, contradictionary STSC and STCO\n",
4249 return AVERROR_INVALIDDATA;
4252 fix_timescale(c, sc);
4254 avpriv_set_pts_info(st, 64, 1, sc->time_scale);
4256 mov_build_index(c, st);
4258 if (sc->dref_id-1 < sc->drefs_count && sc->drefs[sc->dref_id-1].path) {
4259 MOVDref *dref = &sc->drefs[sc->dref_id - 1];
4260 if (c->enable_drefs) {
4261 if (mov_open_dref(c, &sc->pb, c->fc->url, dref) < 0)
4262 av_log(c->fc, AV_LOG_ERROR,
4263 "stream %d, error opening alias: path='%s', dir='%s', "
4264 "filename='%s', volume='%s', nlvl_from=%d, nlvl_to=%d\n",
4265 st->index, dref->path, dref->dir, dref->filename,
4266 dref->volume, dref->nlvl_from, dref->nlvl_to);
4268 av_log(c->fc, AV_LOG_WARNING,
4269 "Skipped opening external track: "
4270 "stream %d, alias: path='%s', dir='%s', "
4271 "filename='%s', volume='%s', nlvl_from=%d, nlvl_to=%d."
4272 "Set enable_drefs to allow this.\n",
4273 st->index, dref->path, dref->dir, dref->filename,
4274 dref->volume, dref->nlvl_from, dref->nlvl_to);
4278 sc->pb_is_copied = 1;
4281 if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
4282 if (!st->sample_aspect_ratio.num && st->codecpar->width && st->codecpar->height &&
4283 sc->height && sc->width &&
4284 (st->codecpar->width != sc->width || st->codecpar->height != sc->height)) {
4285 st->sample_aspect_ratio = av_d2q(((double)st->codecpar->height * sc->width) /
4286 ((double)st->codecpar->width * sc->height), INT_MAX);
4289 #if FF_API_R_FRAME_RATE
4290 if (sc->stts_count == 1 || (sc->stts_count == 2 && sc->stts_data[1].count == 1))
4291 av_reduce(&st->r_frame_rate.num, &st->r_frame_rate.den,
4292 sc->time_scale, sc->stts_data[0].duration, INT_MAX);
4296 // done for ai5q, ai52, ai55, ai1q, ai12 and ai15.
4297 if (!st->codecpar->extradata_size && st->codecpar->codec_id == AV_CODEC_ID_H264 &&
4298 TAG_IS_AVCI(st->codecpar->codec_tag)) {
4299 ret = ff_generate_avci_extradata(st);
4304 switch (st->codecpar->codec_id) {
4305 #if CONFIG_H261_DECODER
4306 case AV_CODEC_ID_H261:
4308 #if CONFIG_H263_DECODER
4309 case AV_CODEC_ID_H263:
4311 #if CONFIG_MPEG4_DECODER
4312 case AV_CODEC_ID_MPEG4:
4314 st->codecpar->width = 0; /* let decoder init width/height */
4315 st->codecpar->height= 0;
4319 // If the duration of the mp3 packets is not constant, then they could need a parser
4320 if (st->codecpar->codec_id == AV_CODEC_ID_MP3
4321 && sc->stts_count > 3
4322 && sc->stts_count*10 > st->nb_frames
4323 && sc->time_scale == st->codecpar->sample_rate) {
4324 st->need_parsing = AVSTREAM_PARSE_FULL;
4326 /* Do not need those anymore. */
4327 av_freep(&sc->chunk_offsets);
4328 av_freep(&sc->sample_sizes);
4329 av_freep(&sc->keyframes);
4330 av_freep(&sc->stts_data);
4331 av_freep(&sc->stps_data);
4332 av_freep(&sc->elst_data);
4333 av_freep(&sc->rap_group);
4338 static int mov_read_ilst(MOVContext *c, AVIOContext *pb, MOVAtom atom)
4341 c->itunes_metadata = 1;
4342 ret = mov_read_default(c, pb, atom);
4343 c->itunes_metadata = 0;
4347 static int mov_read_keys(MOVContext *c, AVIOContext *pb, MOVAtom atom)
4356 count = avio_rb32(pb);
4357 if (count > UINT_MAX / sizeof(*c->meta_keys) - 1) {
4358 av_log(c->fc, AV_LOG_ERROR,
4359 "The 'keys' atom with the invalid key count: %"PRIu32"\n", count);
4360 return AVERROR_INVALIDDATA;
4363 c->meta_keys_count = count + 1;
4364 c->meta_keys = av_mallocz(c->meta_keys_count * sizeof(*c->meta_keys));
4366 return AVERROR(ENOMEM);
4368 for (i = 1; i <= count; ++i) {
4369 uint32_t key_size = avio_rb32(pb);
4370 uint32_t type = avio_rl32(pb);
4372 av_log(c->fc, AV_LOG_ERROR,
4373 "The key# %"PRIu32" in meta has invalid size:"
4374 "%"PRIu32"\n", i, key_size);
4375 return AVERROR_INVALIDDATA;
4378 if (type != MKTAG('m','d','t','a')) {
4379 avio_skip(pb, key_size);
4381 c->meta_keys[i] = av_mallocz(key_size + 1);
4382 if (!c->meta_keys[i])
4383 return AVERROR(ENOMEM);
4384 avio_read(pb, c->meta_keys[i], key_size);
4390 static int mov_read_custom(MOVContext *c, AVIOContext *pb, MOVAtom atom)
4392 int64_t end = avio_tell(pb) + atom.size;
4393 uint8_t *key = NULL, *val = NULL, *mean = NULL;
4397 MOVStreamContext *sc;
4399 if (c->fc->nb_streams < 1)
4401 st = c->fc->streams[c->fc->nb_streams-1];
4404 for (i = 0; i < 3; i++) {
4408 if (end - avio_tell(pb) <= 12)
4411 len = avio_rb32(pb);
4412 tag = avio_rl32(pb);
4413 avio_skip(pb, 4); // flags
4415 if (len < 12 || len - 12 > end - avio_tell(pb))
4419 if (tag == MKTAG('m', 'e', 'a', 'n'))
4421 else if (tag == MKTAG('n', 'a', 'm', 'e'))
4423 else if (tag == MKTAG('d', 'a', 't', 'a') && len > 4) {
4433 *p = av_malloc(len + 1);
4435 ret = AVERROR(ENOMEM);
4438 ret = ffio_read_size(pb, *p, len);
4446 if (mean && key && val) {
4447 if (strcmp(key, "iTunSMPB") == 0) {
4448 int priming, remainder, samples;
4449 if(sscanf(val, "%*X %X %X %X", &priming, &remainder, &samples) == 3){
4450 if(priming>0 && priming<16384)
4451 sc->start_pad = priming;
4454 if (strcmp(key, "cdec") != 0) {
4455 av_dict_set(&c->fc->metadata, key, val,
4456 AV_DICT_DONT_STRDUP_KEY | AV_DICT_DONT_STRDUP_VAL);
4460 av_log(c->fc, AV_LOG_VERBOSE,
4461 "Unhandled or malformed custom metadata of size %"PRId64"\n", atom.size);
4464 avio_seek(pb, end, SEEK_SET);
4471 static int mov_read_meta(MOVContext *c, AVIOContext *pb, MOVAtom atom)
4473 while (atom.size > 8) {
4477 tag = avio_rl32(pb);
4479 if (tag == MKTAG('h','d','l','r')) {
4480 avio_seek(pb, -8, SEEK_CUR);
4482 return mov_read_default(c, pb, atom);
4488 // return 1 when matrix is identity, 0 otherwise
4489 #define IS_MATRIX_IDENT(matrix) \
4490 ( (matrix)[0][0] == (1 << 16) && \
4491 (matrix)[1][1] == (1 << 16) && \
4492 (matrix)[2][2] == (1 << 30) && \
4493 !(matrix)[0][1] && !(matrix)[0][2] && \
4494 !(matrix)[1][0] && !(matrix)[1][2] && \
4495 !(matrix)[2][0] && !(matrix)[2][1])
4497 static int mov_read_tkhd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
4502 int display_matrix[3][3];
4503 int res_display_matrix[3][3] = { { 0 } };
4505 MOVStreamContext *sc;
4509 if (c->fc->nb_streams < 1)
4511 st = c->fc->streams[c->fc->nb_streams-1];
4514 // Each stream (trak) should have exactly 1 tkhd. This catches bad files and
4515 // avoids corrupting AVStreams mapped to an earlier tkhd.
4517 return AVERROR_INVALIDDATA;
4519 version = avio_r8(pb);
4520 flags = avio_rb24(pb);
4521 st->disposition |= (flags & MOV_TKHD_FLAG_ENABLED) ? AV_DISPOSITION_DEFAULT : 0;
4527 avio_rb32(pb); /* creation time */
4528 avio_rb32(pb); /* modification time */
4530 st->id = (int)avio_rb32(pb); /* track id (NOT 0 !)*/
4531 avio_rb32(pb); /* reserved */
4533 /* highlevel (considering edits) duration in movie timebase */
4534 (version == 1) ? avio_rb64(pb) : avio_rb32(pb);
4535 avio_rb32(pb); /* reserved */
4536 avio_rb32(pb); /* reserved */
4538 avio_rb16(pb); /* layer */
4539 avio_rb16(pb); /* alternate group */
4540 avio_rb16(pb); /* volume */
4541 avio_rb16(pb); /* reserved */
4543 //read in the display matrix (outlined in ISO 14496-12, Section 6.2.2)
4544 // they're kept in fixed point format through all calculations
4545 // save u,v,z to store the whole matrix in the AV_PKT_DATA_DISPLAYMATRIX
4546 // side data, but the scale factor is not needed to calculate aspect ratio
4547 for (i = 0; i < 3; i++) {
4548 display_matrix[i][0] = avio_rb32(pb); // 16.16 fixed point
4549 display_matrix[i][1] = avio_rb32(pb); // 16.16 fixed point
4550 display_matrix[i][2] = avio_rb32(pb); // 2.30 fixed point
4553 width = avio_rb32(pb); // 16.16 fixed point track width
4554 height = avio_rb32(pb); // 16.16 fixed point track height
4555 sc->width = width >> 16;
4556 sc->height = height >> 16;
4558 // apply the moov display matrix (after the tkhd one)
4559 for (i = 0; i < 3; i++) {
4560 const int sh[3] = { 16, 16, 30 };
4561 for (j = 0; j < 3; j++) {
4562 for (e = 0; e < 3; e++) {
4563 res_display_matrix[i][j] +=
4564 ((int64_t) display_matrix[i][e] *
4565 c->movie_display_matrix[e][j]) >> sh[e];
4570 // save the matrix when it is not the default identity
4571 if (!IS_MATRIX_IDENT(res_display_matrix)) {
4574 av_freep(&sc->display_matrix);
4575 sc->display_matrix = av_malloc(sizeof(int32_t) * 9);
4576 if (!sc->display_matrix)
4577 return AVERROR(ENOMEM);
4579 for (i = 0; i < 3; i++)
4580 for (j = 0; j < 3; j++)
4581 sc->display_matrix[i * 3 + j] = res_display_matrix[i][j];
4583 #if FF_API_OLD_ROTATE_API
4584 rotate = av_display_rotation_get(sc->display_matrix);
4585 if (!isnan(rotate)) {
4586 char rotate_buf[64];
4588 if (rotate < 0) // for backward compatibility
4590 snprintf(rotate_buf, sizeof(rotate_buf), "%g", rotate);
4591 av_dict_set(&st->metadata, "rotate", rotate_buf, 0);
4596 // transform the display width/height according to the matrix
4597 // to keep the same scale, use [width height 1<<16]
4598 if (width && height && sc->display_matrix) {
4599 double disp_transform[2];
4601 for (i = 0; i < 2; i++)
4602 disp_transform[i] = hypot(sc->display_matrix[0 + i],
4603 sc->display_matrix[3 + i]);
4605 if (disp_transform[0] > 0 && disp_transform[1] > 0 &&
4606 disp_transform[0] < (1<<24) && disp_transform[1] < (1<<24) &&
4607 fabs((disp_transform[0] / disp_transform[1]) - 1.0) > 0.01)
4608 st->sample_aspect_ratio = av_d2q(
4609 disp_transform[0] / disp_transform[1],
4615 static int mov_read_tfhd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
4617 MOVFragment *frag = &c->fragment;
4618 MOVTrackExt *trex = NULL;
4619 int flags, track_id, i;
4620 MOVFragmentStreamInfo * frag_stream_info;
4622 avio_r8(pb); /* version */
4623 flags = avio_rb24(pb);
4625 track_id = avio_rb32(pb);
4627 return AVERROR_INVALIDDATA;
4628 for (i = 0; i < c->trex_count; i++)
4629 if (c->trex_data[i].track_id == track_id) {
4630 trex = &c->trex_data[i];
4634 av_log(c->fc, AV_LOG_WARNING, "could not find corresponding trex (id %u)\n", track_id);
4637 c->fragment.found_tfhd = 1;
4638 frag->track_id = track_id;
4639 set_frag_stream(&c->frag_index, track_id);
4641 frag->base_data_offset = flags & MOV_TFHD_BASE_DATA_OFFSET ?
4642 avio_rb64(pb) : flags & MOV_TFHD_DEFAULT_BASE_IS_MOOF ?
4643 frag->moof_offset : frag->implicit_offset;
4644 frag->stsd_id = flags & MOV_TFHD_STSD_ID ? avio_rb32(pb) : trex->stsd_id;
4646 frag->duration = flags & MOV_TFHD_DEFAULT_DURATION ?
4647 avio_rb32(pb) : trex->duration;
4648 frag->size = flags & MOV_TFHD_DEFAULT_SIZE ?
4649 avio_rb32(pb) : trex->size;
4650 frag->flags = flags & MOV_TFHD_DEFAULT_FLAGS ?
4651 avio_rb32(pb) : trex->flags;
4652 av_log(c->fc, AV_LOG_TRACE, "frag flags 0x%x\n", frag->flags);
4654 frag_stream_info = get_current_frag_stream_info(&c->frag_index);
4655 if (frag_stream_info)
4656 frag_stream_info->next_trun_dts = AV_NOPTS_VALUE;
4661 static int mov_read_chap(MOVContext *c, AVIOContext *pb, MOVAtom atom)
4666 num = atom.size / 4;
4667 if (!(new_tracks = av_malloc_array(num, sizeof(int))))
4668 return AVERROR(ENOMEM);
4670 av_free(c->chapter_tracks);
4671 c->chapter_tracks = new_tracks;
4672 c->nb_chapter_tracks = num;
4674 for (i = 0; i < num && !pb->eof_reached; i++)
4675 c->chapter_tracks[i] = avio_rb32(pb);
4680 static int mov_read_trex(MOVContext *c, AVIOContext *pb, MOVAtom atom)
4685 if ((uint64_t)c->trex_count+1 >= UINT_MAX / sizeof(*c->trex_data))
4686 return AVERROR_INVALIDDATA;
4687 if ((err = av_reallocp_array(&c->trex_data, c->trex_count + 1,
4688 sizeof(*c->trex_data))) < 0) {
4693 c->fc->duration = AV_NOPTS_VALUE; // the duration from mvhd is not representing the whole file when fragments are used.
4695 trex = &c->trex_data[c->trex_count++];
4696 avio_r8(pb); /* version */
4697 avio_rb24(pb); /* flags */
4698 trex->track_id = avio_rb32(pb);
4699 trex->stsd_id = avio_rb32(pb);
4700 trex->duration = avio_rb32(pb);
4701 trex->size = avio_rb32(pb);
4702 trex->flags = avio_rb32(pb);
4706 static int mov_read_tfdt(MOVContext *c, AVIOContext *pb, MOVAtom atom)
4708 MOVFragment *frag = &c->fragment;
4709 AVStream *st = NULL;
4710 MOVStreamContext *sc;
4712 MOVFragmentStreamInfo * frag_stream_info;
4713 int64_t base_media_decode_time;
4715 for (i = 0; i < c->fc->nb_streams; i++) {
4716 if (c->fc->streams[i]->id == frag->track_id) {
4717 st = c->fc->streams[i];
4722 av_log(c->fc, AV_LOG_WARNING, "could not find corresponding track id %u\n", frag->track_id);
4726 if (sc->pseudo_stream_id + 1 != frag->stsd_id && sc->pseudo_stream_id != -1)
4728 version = avio_r8(pb);
4729 avio_rb24(pb); /* flags */
4731 base_media_decode_time = avio_rb64(pb);
4733 base_media_decode_time = avio_rb32(pb);
4736 frag_stream_info = get_current_frag_stream_info(&c->frag_index);
4737 if (frag_stream_info)
4738 frag_stream_info->tfdt_dts = base_media_decode_time;
4739 sc->track_end = base_media_decode_time;
4744 static int mov_read_trun(MOVContext *c, AVIOContext *pb, MOVAtom atom)
4746 MOVFragment *frag = &c->fragment;
4747 AVStream *st = NULL;
4748 MOVStreamContext *sc;
4751 int64_t dts, pts = AV_NOPTS_VALUE;
4752 int data_offset = 0;
4753 unsigned entries, first_sample_flags = frag->flags;
4754 int flags, distance, i;
4755 int64_t prev_dts = AV_NOPTS_VALUE;
4756 int next_frag_index = -1, index_entry_pos;
4757 size_t requested_size;
4758 size_t old_ctts_allocated_size;
4759 AVIndexEntry *new_entries;
4760 MOVFragmentStreamInfo * frag_stream_info;
4762 if (!frag->found_tfhd) {
4763 av_log(c->fc, AV_LOG_ERROR, "trun track id unknown, no tfhd was found\n");
4764 return AVERROR_INVALIDDATA;
4767 for (i = 0; i < c->fc->nb_streams; i++) {
4768 if (c->fc->streams[i]->id == frag->track_id) {
4769 st = c->fc->streams[i];
4774 av_log(c->fc, AV_LOG_WARNING, "could not find corresponding track id %u\n", frag->track_id);
4778 if (sc->pseudo_stream_id+1 != frag->stsd_id && sc->pseudo_stream_id != -1)
4781 // Find the next frag_index index that has a valid index_entry for
4782 // the current track_id.
4784 // A valid index_entry means the trun for the fragment was read
4785 // and it's samples are in index_entries at the given position.
4786 // New index entries will be inserted before the index_entry found.
4787 index_entry_pos = st->nb_index_entries;
4788 for (i = c->frag_index.current + 1; i < c->frag_index.nb_items; i++) {
4789 frag_stream_info = get_frag_stream_info(&c->frag_index, i, frag->track_id);
4790 if (frag_stream_info && frag_stream_info->index_entry >= 0) {
4791 next_frag_index = i;
4792 index_entry_pos = frag_stream_info->index_entry;
4796 av_assert0(index_entry_pos <= st->nb_index_entries);
4798 avio_r8(pb); /* version */
4799 flags = avio_rb24(pb);
4800 entries = avio_rb32(pb);
4801 av_log(c->fc, AV_LOG_TRACE, "flags 0x%x entries %u\n", flags, entries);
4803 if ((uint64_t)entries+sc->ctts_count >= UINT_MAX/sizeof(*sc->ctts_data))
4804 return AVERROR_INVALIDDATA;
4805 if (flags & MOV_TRUN_DATA_OFFSET) data_offset = avio_rb32(pb);
4806 if (flags & MOV_TRUN_FIRST_SAMPLE_FLAGS) first_sample_flags = avio_rb32(pb);
4808 frag_stream_info = get_current_frag_stream_info(&c->frag_index);
4809 if (frag_stream_info)
4811 if (frag_stream_info->next_trun_dts != AV_NOPTS_VALUE) {
4812 dts = frag_stream_info->next_trun_dts - sc->time_offset;
4813 } else if (frag_stream_info->first_tfra_pts != AV_NOPTS_VALUE &&
4814 c->use_mfra_for == FF_MOV_FLAG_MFRA_PTS) {
4815 pts = frag_stream_info->first_tfra_pts;
4816 av_log(c->fc, AV_LOG_DEBUG, "found mfra time %"PRId64
4817 ", using it for pts\n", pts);
4818 } else if (frag_stream_info->first_tfra_pts != AV_NOPTS_VALUE &&
4819 c->use_mfra_for == FF_MOV_FLAG_MFRA_DTS) {
4820 dts = frag_stream_info->first_tfra_pts;
4821 av_log(c->fc, AV_LOG_DEBUG, "found mfra time %"PRId64
4822 ", using it for dts\n", pts);
4823 } else if (frag_stream_info->sidx_pts != AV_NOPTS_VALUE) {
4824 // FIXME: sidx earliest_presentation_time is *PTS*, s.b.
4825 // pts = frag_stream_info->sidx_pts;
4826 dts = frag_stream_info->sidx_pts - sc->time_offset;
4827 av_log(c->fc, AV_LOG_DEBUG, "found sidx time %"PRId64
4828 ", using it for pts\n", pts);
4829 } else if (frag_stream_info->tfdt_dts != AV_NOPTS_VALUE) {
4830 dts = frag_stream_info->tfdt_dts - sc->time_offset;
4831 av_log(c->fc, AV_LOG_DEBUG, "found tfdt time %"PRId64
4832 ", using it for dts\n", dts);
4834 dts = sc->track_end - sc->time_offset;
4835 av_log(c->fc, AV_LOG_DEBUG, "found track end time %"PRId64
4836 ", using it for dts\n", dts);
4839 dts = sc->track_end - sc->time_offset;
4840 av_log(c->fc, AV_LOG_DEBUG, "found track end time %"PRId64
4841 ", using it for dts\n", dts);
4843 offset = frag->base_data_offset + data_offset;
4845 av_log(c->fc, AV_LOG_TRACE, "first sample flags 0x%x\n", first_sample_flags);
4847 // realloc space for new index entries
4848 if((uint64_t)st->nb_index_entries + entries >= UINT_MAX / sizeof(AVIndexEntry)) {
4849 entries = UINT_MAX / sizeof(AVIndexEntry) - st->nb_index_entries;
4850 av_log(c->fc, AV_LOG_ERROR, "Failed to add index entry\n");
4855 requested_size = (st->nb_index_entries + entries) * sizeof(AVIndexEntry);
4856 new_entries = av_fast_realloc(st->index_entries,
4857 &st->index_entries_allocated_size,
4860 return AVERROR(ENOMEM);
4861 st->index_entries= new_entries;
4863 requested_size = (st->nb_index_entries + entries) * sizeof(*sc->ctts_data);
4864 old_ctts_allocated_size = sc->ctts_allocated_size;
4865 ctts_data = av_fast_realloc(sc->ctts_data, &sc->ctts_allocated_size,
4868 return AVERROR(ENOMEM);
4869 sc->ctts_data = ctts_data;
4871 // In case there were samples without ctts entries, ensure they get
4872 // zero valued entries. This ensures clips which mix boxes with and
4873 // without ctts entries don't pickup uninitialized data.
4874 memset((uint8_t*)(sc->ctts_data) + old_ctts_allocated_size, 0,
4875 sc->ctts_allocated_size - old_ctts_allocated_size);
4877 if (index_entry_pos < st->nb_index_entries) {
4878 // Make hole in index_entries and ctts_data for new samples
4879 memmove(st->index_entries + index_entry_pos + entries,
4880 st->index_entries + index_entry_pos,
4881 sizeof(*st->index_entries) *
4882 (st->nb_index_entries - index_entry_pos));
4883 memmove(sc->ctts_data + index_entry_pos + entries,
4884 sc->ctts_data + index_entry_pos,
4885 sizeof(*sc->ctts_data) * (sc->ctts_count - index_entry_pos));
4886 if (index_entry_pos < sc->current_sample) {
4887 sc->current_sample += entries;
4891 st->nb_index_entries += entries;
4892 sc->ctts_count = st->nb_index_entries;
4894 // Record the index_entry position in frag_index of this fragment
4895 if (frag_stream_info)
4896 frag_stream_info->index_entry = index_entry_pos;
4898 if (index_entry_pos > 0)
4899 prev_dts = st->index_entries[index_entry_pos-1].timestamp;
4901 for (i = 0; i < entries && !pb->eof_reached; i++) {
4902 unsigned sample_size = frag->size;
4903 int sample_flags = i ? frag->flags : first_sample_flags;
4904 unsigned sample_duration = frag->duration;
4905 unsigned ctts_duration = 0;
4907 int index_entry_flags = 0;
4909 if (flags & MOV_TRUN_SAMPLE_DURATION) sample_duration = avio_rb32(pb);
4910 if (flags & MOV_TRUN_SAMPLE_SIZE) sample_size = avio_rb32(pb);
4911 if (flags & MOV_TRUN_SAMPLE_FLAGS) sample_flags = avio_rb32(pb);
4912 if (flags & MOV_TRUN_SAMPLE_CTS) ctts_duration = avio_rb32(pb);
4914 mov_update_dts_shift(sc, ctts_duration, c->fc);
4915 if (pts != AV_NOPTS_VALUE) {
4916 dts = pts - sc->dts_shift;
4917 if (flags & MOV_TRUN_SAMPLE_CTS) {
4918 dts -= ctts_duration;
4920 dts -= sc->time_offset;
4922 av_log(c->fc, AV_LOG_DEBUG,
4923 "pts %"PRId64" calculated dts %"PRId64
4924 " sc->dts_shift %d ctts.duration %d"
4925 " sc->time_offset %"PRId64
4926 " flags & MOV_TRUN_SAMPLE_CTS %d\n",
4928 sc->dts_shift, ctts_duration,
4929 sc->time_offset, flags & MOV_TRUN_SAMPLE_CTS);
4930 pts = AV_NOPTS_VALUE;
4933 if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO)
4937 !(sample_flags & (MOV_FRAG_SAMPLE_FLAG_IS_NON_SYNC |
4938 MOV_FRAG_SAMPLE_FLAG_DEPENDS_YES));
4941 index_entry_flags |= AVINDEX_KEYFRAME;
4943 // Fragments can overlap in time. Discard overlapping frames after
4945 if (prev_dts >= dts)
4946 index_entry_flags |= AVINDEX_DISCARD_FRAME;
4948 st->index_entries[index_entry_pos].pos = offset;
4949 st->index_entries[index_entry_pos].timestamp = dts;
4950 st->index_entries[index_entry_pos].size= sample_size;
4951 st->index_entries[index_entry_pos].min_distance= distance;
4952 st->index_entries[index_entry_pos].flags = index_entry_flags;
4954 sc->ctts_data[index_entry_pos].count = 1;
4955 sc->ctts_data[index_entry_pos].duration = ctts_duration;
4958 av_log(c->fc, AV_LOG_TRACE, "AVIndex stream %d, sample %d, offset %"PRIx64", dts %"PRId64", "
4959 "size %u, distance %d, keyframe %d\n", st->index,
4960 index_entry_pos, offset, dts, sample_size, distance, keyframe);
4962 dts += sample_duration;
4963 offset += sample_size;
4964 sc->data_size += sample_size;
4966 if (sample_duration <= INT64_MAX - sc->duration_for_fps &&
4967 1 <= INT_MAX - sc->nb_frames_for_fps
4969 sc->duration_for_fps += sample_duration;
4970 sc->nb_frames_for_fps ++;
4973 if (frag_stream_info)
4974 frag_stream_info->next_trun_dts = dts + sc->time_offset;
4976 // EOF found before reading all entries. Fix the hole this would
4977 // leave in index_entries and ctts_data
4978 int gap = entries - i;
4979 memmove(st->index_entries + index_entry_pos,
4980 st->index_entries + index_entry_pos + gap,
4981 sizeof(*st->index_entries) *
4982 (st->nb_index_entries - (index_entry_pos + gap)));
4983 memmove(sc->ctts_data + index_entry_pos,
4984 sc->ctts_data + index_entry_pos + gap,
4985 sizeof(*sc->ctts_data) *
4986 (sc->ctts_count - (index_entry_pos + gap)));
4988 st->nb_index_entries -= gap;
4989 sc->ctts_count -= gap;
4990 if (index_entry_pos < sc->current_sample) {
4991 sc->current_sample -= gap;
4996 // The end of this new fragment may overlap in time with the start
4997 // of the next fragment in index_entries. Mark the samples in the next
4998 // fragment that overlap with AVINDEX_DISCARD_FRAME
4999 prev_dts = AV_NOPTS_VALUE;
5000 if (index_entry_pos > 0)
5001 prev_dts = st->index_entries[index_entry_pos-1].timestamp;
5002 for (i = index_entry_pos; i < st->nb_index_entries; i++) {
5003 if (prev_dts < st->index_entries[i].timestamp)
5005 st->index_entries[i].flags |= AVINDEX_DISCARD_FRAME;
5008 // If a hole was created to insert the new index_entries into,
5009 // the index_entry recorded for all subsequent moof must
5010 // be incremented by the number of entries inserted.
5011 fix_frag_index_entries(&c->frag_index, next_frag_index,
5012 frag->track_id, entries);
5014 if (pb->eof_reached) {
5015 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted TRUN atom\n");
5019 frag->implicit_offset = offset;
5021 sc->track_end = dts + sc->time_offset;
5022 if (st->duration < sc->track_end)
5023 st->duration = sc->track_end;
5028 static int mov_read_sidx(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5030 int64_t offset = avio_tell(pb) + atom.size, pts, timestamp;
5032 unsigned i, j, track_id, item_count;
5033 AVStream *st = NULL;
5034 AVStream *ref_st = NULL;
5035 MOVStreamContext *sc, *ref_sc = NULL;
5036 AVRational timescale;
5038 version = avio_r8(pb);
5040 avpriv_request_sample(c->fc, "sidx version %u", version);
5044 avio_rb24(pb); // flags
5046 track_id = avio_rb32(pb); // Reference ID
5047 for (i = 0; i < c->fc->nb_streams; i++) {
5048 if (c->fc->streams[i]->id == track_id) {
5049 st = c->fc->streams[i];
5054 av_log(c->fc, AV_LOG_WARNING, "could not find corresponding track id %d\n", track_id);
5060 timescale = av_make_q(1, avio_rb32(pb));
5062 if (timescale.den <= 0) {
5063 av_log(c->fc, AV_LOG_ERROR, "Invalid sidx timescale 1/%d\n", timescale.den);
5064 return AVERROR_INVALIDDATA;
5068 pts = avio_rb32(pb);
5069 offset += avio_rb32(pb);
5071 pts = avio_rb64(pb);
5072 offset += avio_rb64(pb);
5075 avio_rb16(pb); // reserved
5077 item_count = avio_rb16(pb);
5079 for (i = 0; i < item_count; i++) {
5081 MOVFragmentStreamInfo * frag_stream_info;
5082 uint32_t size = avio_rb32(pb);
5083 uint32_t duration = avio_rb32(pb);
5084 if (size & 0x80000000) {
5085 avpriv_request_sample(c->fc, "sidx reference_type 1");
5086 return AVERROR_PATCHWELCOME;
5088 avio_rb32(pb); // sap_flags
5089 timestamp = av_rescale_q(pts, timescale, st->time_base);
5091 index = update_frag_index(c, offset);
5092 frag_stream_info = get_frag_stream_info(&c->frag_index, index, track_id);
5093 if (frag_stream_info)
5094 frag_stream_info->sidx_pts = timestamp;
5100 st->duration = sc->track_end = pts;
5104 if (offset == avio_size(pb)) {
5105 // Find first entry in fragment index that came from an sidx.
5106 // This will pretty much always be the first entry.
5107 for (i = 0; i < c->frag_index.nb_items; i++) {
5108 MOVFragmentIndexItem * item = &c->frag_index.item[i];
5109 for (j = 0; ref_st == NULL && j < item->nb_stream_info; j++) {
5110 MOVFragmentStreamInfo * si;
5111 si = &item->stream_info[j];
5112 if (si->sidx_pts != AV_NOPTS_VALUE) {
5113 ref_st = c->fc->streams[j];
5114 ref_sc = ref_st->priv_data;
5119 if (ref_st) for (i = 0; i < c->fc->nb_streams; i++) {
5120 st = c->fc->streams[i];
5122 if (!sc->has_sidx) {
5123 st->duration = sc->track_end = av_rescale(ref_st->duration, sc->time_scale, ref_sc->time_scale);
5127 c->frag_index.complete = 1;
5133 /* this atom should be null (from specs), but some buggy files put the 'moov' atom inside it... */
5134 /* like the files created with Adobe Premiere 5.0, for samples see */
5135 /* http://graphics.tudelft.nl/~wouter/publications/soundtests/ */
5136 static int mov_read_wide(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5141 return 0; /* continue */
5142 if (avio_rb32(pb) != 0) { /* 0 sized mdat atom... use the 'wide' atom size */
5143 avio_skip(pb, atom.size - 4);
5146 atom.type = avio_rl32(pb);
5148 if (atom.type != MKTAG('m','d','a','t')) {
5149 avio_skip(pb, atom.size);
5152 err = mov_read_mdat(c, pb, atom);
5156 static int mov_read_cmov(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5161 uint8_t *moov_data; /* uncompressed data */
5162 long cmov_len, moov_len;
5165 avio_rb32(pb); /* dcom atom */
5166 if (avio_rl32(pb) != MKTAG('d','c','o','m'))
5167 return AVERROR_INVALIDDATA;
5168 if (avio_rl32(pb) != MKTAG('z','l','i','b')) {
5169 av_log(c->fc, AV_LOG_ERROR, "unknown compression for cmov atom !\n");
5170 return AVERROR_INVALIDDATA;
5172 avio_rb32(pb); /* cmvd atom */
5173 if (avio_rl32(pb) != MKTAG('c','m','v','d'))
5174 return AVERROR_INVALIDDATA;
5175 moov_len = avio_rb32(pb); /* uncompressed size */
5176 cmov_len = atom.size - 6 * 4;
5178 cmov_data = av_malloc(cmov_len);
5180 return AVERROR(ENOMEM);
5181 moov_data = av_malloc(moov_len);
5184 return AVERROR(ENOMEM);
5186 ret = ffio_read_size(pb, cmov_data, cmov_len);
5188 goto free_and_return;
5190 ret = AVERROR_INVALIDDATA;
5191 if (uncompress (moov_data, (uLongf *) &moov_len, (const Bytef *)cmov_data, cmov_len) != Z_OK)
5192 goto free_and_return;
5193 if (ffio_init_context(&ctx, moov_data, moov_len, 0, NULL, NULL, NULL, NULL) != 0)
5194 goto free_and_return;
5195 ctx.seekable = AVIO_SEEKABLE_NORMAL;
5196 atom.type = MKTAG('m','o','o','v');
5197 atom.size = moov_len;
5198 ret = mov_read_default(c, &ctx, atom);
5204 av_log(c->fc, AV_LOG_ERROR, "this file requires zlib support compiled in\n");
5205 return AVERROR(ENOSYS);
5209 /* edit list atom */
5210 static int mov_read_elst(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5212 MOVStreamContext *sc;
5213 int i, edit_count, version;
5214 int64_t elst_entry_size;
5216 if (c->fc->nb_streams < 1 || c->ignore_editlist)
5218 sc = c->fc->streams[c->fc->nb_streams-1]->priv_data;
5220 version = avio_r8(pb); /* version */
5221 avio_rb24(pb); /* flags */
5222 edit_count = avio_rb32(pb); /* entries */
5225 elst_entry_size = version == 1 ? 20 : 12;
5226 if (atom.size != edit_count * elst_entry_size) {
5227 if (c->fc->strict_std_compliance >= FF_COMPLIANCE_STRICT) {
5228 av_log(c->fc, AV_LOG_ERROR, "Invalid edit list entry_count: %d for elst atom of size: %"PRId64" bytes.\n",
5229 edit_count, atom.size + 8);
5230 return AVERROR_INVALIDDATA;
5232 edit_count = atom.size / elst_entry_size;
5233 if (edit_count * elst_entry_size != atom.size) {
5234 av_log(c->fc, AV_LOG_WARNING, "ELST atom of %"PRId64" bytes, bigger than %d entries.", atom.size, edit_count);
5242 av_log(c->fc, AV_LOG_WARNING, "Duplicated ELST atom\n");
5243 av_free(sc->elst_data);
5245 sc->elst_data = av_malloc_array(edit_count, sizeof(*sc->elst_data));
5247 return AVERROR(ENOMEM);
5249 av_log(c->fc, AV_LOG_TRACE, "track[%u].edit_count = %i\n", c->fc->nb_streams - 1, edit_count);
5250 for (i = 0; i < edit_count && atom.size > 0 && !pb->eof_reached; i++) {
5251 MOVElst *e = &sc->elst_data[i];
5254 e->duration = avio_rb64(pb);
5255 e->time = avio_rb64(pb);
5258 e->duration = avio_rb32(pb); /* segment duration */
5259 e->time = (int32_t)avio_rb32(pb); /* media time */
5262 e->rate = avio_rb32(pb) / 65536.0;
5264 av_log(c->fc, AV_LOG_TRACE, "duration=%"PRId64" time=%"PRId64" rate=%f\n",
5265 e->duration, e->time, e->rate);
5267 if (e->time < 0 && e->time != -1 &&
5268 c->fc->strict_std_compliance >= FF_COMPLIANCE_STRICT) {
5269 av_log(c->fc, AV_LOG_ERROR, "Track %d, edit %d: Invalid edit list media time=%"PRId64"\n",
5270 c->fc->nb_streams-1, i, e->time);
5271 return AVERROR_INVALIDDATA;
5279 static int mov_read_tmcd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5281 MOVStreamContext *sc;
5283 if (c->fc->nb_streams < 1)
5284 return AVERROR_INVALIDDATA;
5285 sc = c->fc->streams[c->fc->nb_streams - 1]->priv_data;
5286 sc->timecode_track = avio_rb32(pb);
5290 static int mov_read_av1c(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5295 if (c->fc->nb_streams < 1)
5297 st = c->fc->streams[c->fc->nb_streams - 1];
5299 if (atom.size < 4) {
5300 av_log(c->fc, AV_LOG_ERROR, "Empty AV1 Codec Configuration Box\n");
5301 return AVERROR_INVALIDDATA;
5304 /* For now, propagate only the OBUs, if any. Once libavcodec is
5305 updated to handle isobmff style extradata this can be removed. */
5311 ret = ff_get_extradata(c->fc, st->codecpar, pb, atom.size - 4);
5318 static int mov_read_vpcc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5321 int version, color_range, color_primaries, color_trc, color_space;
5323 if (c->fc->nb_streams < 1)
5325 st = c->fc->streams[c->fc->nb_streams - 1];
5327 if (atom.size < 5) {
5328 av_log(c->fc, AV_LOG_ERROR, "Empty VP Codec Configuration box\n");
5329 return AVERROR_INVALIDDATA;
5332 version = avio_r8(pb);
5334 av_log(c->fc, AV_LOG_WARNING, "Unsupported VP Codec Configuration box version %d\n", version);
5337 avio_skip(pb, 3); /* flags */
5339 avio_skip(pb, 2); /* profile + level */
5340 color_range = avio_r8(pb); /* bitDepth, chromaSubsampling, videoFullRangeFlag */
5341 color_primaries = avio_r8(pb);
5342 color_trc = avio_r8(pb);
5343 color_space = avio_r8(pb);
5344 if (avio_rb16(pb)) /* codecIntializationDataSize */
5345 return AVERROR_INVALIDDATA;
5347 if (!av_color_primaries_name(color_primaries))
5348 color_primaries = AVCOL_PRI_UNSPECIFIED;
5349 if (!av_color_transfer_name(color_trc))
5350 color_trc = AVCOL_TRC_UNSPECIFIED;
5351 if (!av_color_space_name(color_space))
5352 color_space = AVCOL_SPC_UNSPECIFIED;
5354 st->codecpar->color_range = (color_range & 1) ? AVCOL_RANGE_JPEG : AVCOL_RANGE_MPEG;
5355 st->codecpar->color_primaries = color_primaries;
5356 st->codecpar->color_trc = color_trc;
5357 st->codecpar->color_space = color_space;
5362 static int mov_read_smdm(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5364 MOVStreamContext *sc;
5367 if (c->fc->nb_streams < 1)
5368 return AVERROR_INVALIDDATA;
5370 sc = c->fc->streams[c->fc->nb_streams - 1]->priv_data;
5372 if (atom.size < 5) {
5373 av_log(c->fc, AV_LOG_ERROR, "Empty Mastering Display Metadata box\n");
5374 return AVERROR_INVALIDDATA;
5377 version = avio_r8(pb);
5379 av_log(c->fc, AV_LOG_WARNING, "Unsupported Mastering Display Metadata box version %d\n", version);
5382 avio_skip(pb, 3); /* flags */
5384 sc->mastering = av_mastering_display_metadata_alloc();
5386 return AVERROR(ENOMEM);
5388 for (i = 0; i < 3; i++) {
5389 sc->mastering->display_primaries[i][0] = av_make_q(avio_rb16(pb), 1 << 16);
5390 sc->mastering->display_primaries[i][1] = av_make_q(avio_rb16(pb), 1 << 16);
5392 sc->mastering->white_point[0] = av_make_q(avio_rb16(pb), 1 << 16);
5393 sc->mastering->white_point[1] = av_make_q(avio_rb16(pb), 1 << 16);
5395 sc->mastering->max_luminance = av_make_q(avio_rb32(pb), 1 << 8);
5396 sc->mastering->min_luminance = av_make_q(avio_rb32(pb), 1 << 14);
5398 sc->mastering->has_primaries = 1;
5399 sc->mastering->has_luminance = 1;
5404 static int mov_read_mdcv(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5406 MOVStreamContext *sc;
5407 const int mapping[3] = {1, 2, 0};
5408 const int chroma_den = 50000;
5409 const int luma_den = 10000;
5412 if (c->fc->nb_streams < 1)
5413 return AVERROR_INVALIDDATA;
5415 sc = c->fc->streams[c->fc->nb_streams - 1]->priv_data;
5417 if (atom.size < 24) {
5418 av_log(c->fc, AV_LOG_ERROR, "Invalid Mastering Display Color Volume box\n");
5419 return AVERROR_INVALIDDATA;
5422 sc->mastering = av_mastering_display_metadata_alloc();
5424 return AVERROR(ENOMEM);
5426 for (i = 0; i < 3; i++) {
5427 const int j = mapping[i];
5428 sc->mastering->display_primaries[j][0] = av_make_q(avio_rb16(pb), chroma_den);
5429 sc->mastering->display_primaries[j][1] = av_make_q(avio_rb16(pb), chroma_den);
5431 sc->mastering->white_point[0] = av_make_q(avio_rb16(pb), chroma_den);
5432 sc->mastering->white_point[1] = av_make_q(avio_rb16(pb), chroma_den);
5434 sc->mastering->max_luminance = av_make_q(avio_rb32(pb), luma_den);
5435 sc->mastering->min_luminance = av_make_q(avio_rb32(pb), luma_den);
5437 sc->mastering->has_luminance = 1;
5438 sc->mastering->has_primaries = 1;
5443 static int mov_read_coll(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5445 MOVStreamContext *sc;
5448 if (c->fc->nb_streams < 1)
5449 return AVERROR_INVALIDDATA;
5451 sc = c->fc->streams[c->fc->nb_streams - 1]->priv_data;
5453 if (atom.size < 5) {
5454 av_log(c->fc, AV_LOG_ERROR, "Empty Content Light Level box\n");
5455 return AVERROR_INVALIDDATA;
5458 version = avio_r8(pb);
5460 av_log(c->fc, AV_LOG_WARNING, "Unsupported Content Light Level box version %d\n", version);
5463 avio_skip(pb, 3); /* flags */
5465 sc->coll = av_content_light_metadata_alloc(&sc->coll_size);
5467 return AVERROR(ENOMEM);
5469 sc->coll->MaxCLL = avio_rb16(pb);
5470 sc->coll->MaxFALL = avio_rb16(pb);
5475 static int mov_read_clli(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5477 MOVStreamContext *sc;
5479 if (c->fc->nb_streams < 1)
5480 return AVERROR_INVALIDDATA;
5482 sc = c->fc->streams[c->fc->nb_streams - 1]->priv_data;
5484 if (atom.size < 4) {
5485 av_log(c->fc, AV_LOG_ERROR, "Empty Content Light Level Info box\n");
5486 return AVERROR_INVALIDDATA;
5489 sc->coll = av_content_light_metadata_alloc(&sc->coll_size);
5491 return AVERROR(ENOMEM);
5493 sc->coll->MaxCLL = avio_rb16(pb);
5494 sc->coll->MaxFALL = avio_rb16(pb);
5499 static int mov_read_st3d(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5502 MOVStreamContext *sc;
5503 enum AVStereo3DType type;
5506 if (c->fc->nb_streams < 1)
5509 st = c->fc->streams[c->fc->nb_streams - 1];
5512 if (atom.size < 5) {
5513 av_log(c->fc, AV_LOG_ERROR, "Empty stereoscopic video box\n");
5514 return AVERROR_INVALIDDATA;
5516 avio_skip(pb, 4); /* version + flags */
5521 type = AV_STEREO3D_2D;
5524 type = AV_STEREO3D_TOPBOTTOM;
5527 type = AV_STEREO3D_SIDEBYSIDE;
5530 av_log(c->fc, AV_LOG_WARNING, "Unknown st3d mode value %d\n", mode);
5534 sc->stereo3d = av_stereo3d_alloc();
5536 return AVERROR(ENOMEM);
5538 sc->stereo3d->type = type;
5542 static int mov_read_sv3d(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5545 MOVStreamContext *sc;
5546 int size, version, layout;
5547 int32_t yaw, pitch, roll;
5548 uint32_t l = 0, t = 0, r = 0, b = 0;
5549 uint32_t tag, padding = 0;
5550 enum AVSphericalProjection projection;
5552 if (c->fc->nb_streams < 1)
5555 st = c->fc->streams[c->fc->nb_streams - 1];
5558 if (atom.size < 8) {
5559 av_log(c->fc, AV_LOG_ERROR, "Empty spherical video box\n");
5560 return AVERROR_INVALIDDATA;
5563 size = avio_rb32(pb);
5564 if (size <= 12 || size > atom.size)
5565 return AVERROR_INVALIDDATA;
5567 tag = avio_rl32(pb);
5568 if (tag != MKTAG('s','v','h','d')) {
5569 av_log(c->fc, AV_LOG_ERROR, "Missing spherical video header\n");
5572 version = avio_r8(pb);
5574 av_log(c->fc, AV_LOG_WARNING, "Unknown spherical version %d\n",
5578 avio_skip(pb, 3); /* flags */
5579 avio_skip(pb, size - 12); /* metadata_source */
5581 size = avio_rb32(pb);
5582 if (size > atom.size)
5583 return AVERROR_INVALIDDATA;
5585 tag = avio_rl32(pb);
5586 if (tag != MKTAG('p','r','o','j')) {
5587 av_log(c->fc, AV_LOG_ERROR, "Missing projection box\n");
5591 size = avio_rb32(pb);
5592 if (size > atom.size)
5593 return AVERROR_INVALIDDATA;
5595 tag = avio_rl32(pb);
5596 if (tag != MKTAG('p','r','h','d')) {
5597 av_log(c->fc, AV_LOG_ERROR, "Missing projection header box\n");
5600 version = avio_r8(pb);
5602 av_log(c->fc, AV_LOG_WARNING, "Unknown spherical version %d\n",
5606 avio_skip(pb, 3); /* flags */
5608 /* 16.16 fixed point */
5609 yaw = avio_rb32(pb);
5610 pitch = avio_rb32(pb);
5611 roll = avio_rb32(pb);
5613 size = avio_rb32(pb);
5614 if (size > atom.size)
5615 return AVERROR_INVALIDDATA;
5617 tag = avio_rl32(pb);
5618 version = avio_r8(pb);
5620 av_log(c->fc, AV_LOG_WARNING, "Unknown spherical version %d\n",
5624 avio_skip(pb, 3); /* flags */
5626 case MKTAG('c','b','m','p'):
5627 layout = avio_rb32(pb);
5629 av_log(c->fc, AV_LOG_WARNING,
5630 "Unsupported cubemap layout %d\n", layout);
5633 projection = AV_SPHERICAL_CUBEMAP;
5634 padding = avio_rb32(pb);
5636 case MKTAG('e','q','u','i'):
5642 if (b >= UINT_MAX - t || r >= UINT_MAX - l) {
5643 av_log(c->fc, AV_LOG_ERROR,
5644 "Invalid bounding rectangle coordinates "
5645 "%"PRIu32",%"PRIu32",%"PRIu32",%"PRIu32"\n", l, t, r, b);
5646 return AVERROR_INVALIDDATA;
5649 if (l || t || r || b)
5650 projection = AV_SPHERICAL_EQUIRECTANGULAR_TILE;
5652 projection = AV_SPHERICAL_EQUIRECTANGULAR;
5655 av_log(c->fc, AV_LOG_ERROR, "Unknown projection type: %s\n", av_fourcc2str(tag));
5659 sc->spherical = av_spherical_alloc(&sc->spherical_size);
5661 return AVERROR(ENOMEM);
5663 sc->spherical->projection = projection;
5665 sc->spherical->yaw = yaw;
5666 sc->spherical->pitch = pitch;
5667 sc->spherical->roll = roll;
5669 sc->spherical->padding = padding;
5671 sc->spherical->bound_left = l;
5672 sc->spherical->bound_top = t;
5673 sc->spherical->bound_right = r;
5674 sc->spherical->bound_bottom = b;
5679 static int mov_parse_uuid_spherical(MOVStreamContext *sc, AVIOContext *pb, size_t len)
5682 uint8_t *buffer = av_malloc(len + 1);
5686 return AVERROR(ENOMEM);
5689 ret = ffio_read_size(pb, buffer, len);
5693 /* Check for mandatory keys and values, try to support XML as best-effort */
5694 if (!sc->spherical &&
5695 av_stristr(buffer, "<GSpherical:StitchingSoftware>") &&
5696 (val = av_stristr(buffer, "<GSpherical:Spherical>")) &&
5697 av_stristr(val, "true") &&
5698 (val = av_stristr(buffer, "<GSpherical:Stitched>")) &&
5699 av_stristr(val, "true") &&
5700 (val = av_stristr(buffer, "<GSpherical:ProjectionType>")) &&
5701 av_stristr(val, "equirectangular")) {
5702 sc->spherical = av_spherical_alloc(&sc->spherical_size);
5706 sc->spherical->projection = AV_SPHERICAL_EQUIRECTANGULAR;
5708 if (av_stristr(buffer, "<GSpherical:StereoMode>") && !sc->stereo3d) {
5709 enum AVStereo3DType mode;
5711 if (av_stristr(buffer, "left-right"))
5712 mode = AV_STEREO3D_SIDEBYSIDE;
5713 else if (av_stristr(buffer, "top-bottom"))
5714 mode = AV_STEREO3D_TOPBOTTOM;
5716 mode = AV_STEREO3D_2D;
5718 sc->stereo3d = av_stereo3d_alloc();
5722 sc->stereo3d->type = mode;
5726 val = av_stristr(buffer, "<GSpherical:InitialViewHeadingDegrees>");
5728 sc->spherical->yaw = strtol(val, NULL, 10) * (1 << 16);
5729 val = av_stristr(buffer, "<GSpherical:InitialViewPitchDegrees>");
5731 sc->spherical->pitch = strtol(val, NULL, 10) * (1 << 16);
5732 val = av_stristr(buffer, "<GSpherical:InitialViewRollDegrees>");
5734 sc->spherical->roll = strtol(val, NULL, 10) * (1 << 16);
5742 static int mov_read_uuid(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5745 MOVStreamContext *sc;
5748 static const uint8_t uuid_isml_manifest[] = {
5749 0xa5, 0xd4, 0x0b, 0x30, 0xe8, 0x14, 0x11, 0xdd,
5750 0xba, 0x2f, 0x08, 0x00, 0x20, 0x0c, 0x9a, 0x66
5752 static const uint8_t uuid_xmp[] = {
5753 0xbe, 0x7a, 0xcf, 0xcb, 0x97, 0xa9, 0x42, 0xe8,
5754 0x9c, 0x71, 0x99, 0x94, 0x91, 0xe3, 0xaf, 0xac
5756 static const uint8_t uuid_spherical[] = {
5757 0xff, 0xcc, 0x82, 0x63, 0xf8, 0x55, 0x4a, 0x93,
5758 0x88, 0x14, 0x58, 0x7a, 0x02, 0x52, 0x1f, 0xdd,
5761 if (atom.size < sizeof(uuid) || atom.size >= FFMIN(INT_MAX, SIZE_MAX))
5762 return AVERROR_INVALIDDATA;
5764 if (c->fc->nb_streams < 1)
5766 st = c->fc->streams[c->fc->nb_streams - 1];
5769 ret = ffio_read_size(pb, uuid, sizeof(uuid));
5772 if (!memcmp(uuid, uuid_isml_manifest, sizeof(uuid))) {
5773 uint8_t *buffer, *ptr;
5775 size_t len = atom.size - sizeof(uuid);
5778 return AVERROR_INVALIDDATA;
5780 ret = avio_skip(pb, 4); // zeroes
5783 buffer = av_mallocz(len + 1);
5785 return AVERROR(ENOMEM);
5787 ret = ffio_read_size(pb, buffer, len);
5794 while ((ptr = av_stristr(ptr, "systemBitrate=\""))) {
5795 ptr += sizeof("systemBitrate=\"") - 1;
5796 c->bitrates_count++;
5797 c->bitrates = av_realloc_f(c->bitrates, c->bitrates_count, sizeof(*c->bitrates));
5799 c->bitrates_count = 0;
5801 return AVERROR(ENOMEM);
5804 ret = strtol(ptr, &endptr, 10);
5805 if (ret < 0 || errno || *endptr != '"') {
5806 c->bitrates[c->bitrates_count - 1] = 0;
5808 c->bitrates[c->bitrates_count - 1] = ret;
5813 } else if (!memcmp(uuid, uuid_xmp, sizeof(uuid))) {
5815 size_t len = atom.size - sizeof(uuid);
5816 if (c->export_xmp) {
5817 buffer = av_mallocz(len + 1);
5819 return AVERROR(ENOMEM);
5821 ret = ffio_read_size(pb, buffer, len);
5827 av_dict_set(&c->fc->metadata, "xmp",
5828 buffer, AV_DICT_DONT_STRDUP_VAL);
5830 // skip all uuid atom, which makes it fast for long uuid-xmp file
5831 ret = avio_skip(pb, len);
5835 } else if (!memcmp(uuid, uuid_spherical, sizeof(uuid))) {
5836 size_t len = atom.size - sizeof(uuid);
5837 ret = mov_parse_uuid_spherical(sc, pb, len);
5841 av_log(c->fc, AV_LOG_WARNING, "Invalid spherical metadata found\n");
5847 static int mov_read_free(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5850 uint8_t content[16];
5855 ret = avio_read(pb, content, FFMIN(sizeof(content), atom.size));
5861 && !memcmp(content, "Anevia\x1A\x1A", 8)
5862 && c->use_mfra_for == FF_MOV_FLAG_MFRA_AUTO) {
5863 c->use_mfra_for = FF_MOV_FLAG_MFRA_PTS;
5869 static int mov_read_frma(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5871 uint32_t format = avio_rl32(pb);
5872 MOVStreamContext *sc;
5876 if (c->fc->nb_streams < 1)
5878 st = c->fc->streams[c->fc->nb_streams - 1];
5883 case MKTAG('e','n','c','v'): // encrypted video
5884 case MKTAG('e','n','c','a'): // encrypted audio
5885 id = mov_codec_id(st, format);
5886 if (st->codecpar->codec_id != AV_CODEC_ID_NONE &&
5887 st->codecpar->codec_id != id) {
5888 av_log(c->fc, AV_LOG_WARNING,
5889 "ignoring 'frma' atom of '%.4s', stream has codec id %d\n",
5890 (char*)&format, st->codecpar->codec_id);
5894 st->codecpar->codec_id = id;
5895 sc->format = format;
5899 if (format != sc->format) {
5900 av_log(c->fc, AV_LOG_WARNING,
5901 "ignoring 'frma' atom of '%.4s', stream format is '%.4s'\n",
5902 (char*)&format, (char*)&sc->format);
5911 * Gets the current encryption info and associated current stream context. If
5912 * we are parsing a track fragment, this will return the specific encryption
5913 * info for this fragment; otherwise this will return the global encryption
5914 * info for the current stream.
5916 static int get_current_encryption_info(MOVContext *c, MOVEncryptionIndex **encryption_index, MOVStreamContext **sc)
5918 MOVFragmentStreamInfo *frag_stream_info;
5922 frag_stream_info = get_current_frag_stream_info(&c->frag_index);
5923 if (frag_stream_info) {
5924 for (i = 0; i < c->fc->nb_streams; i++) {
5925 if (c->fc->streams[i]->id == frag_stream_info->id) {
5926 st = c->fc->streams[i];
5930 if (i == c->fc->nb_streams)
5932 *sc = st->priv_data;
5934 if (!frag_stream_info->encryption_index) {
5935 // If this stream isn't encrypted, don't create the index.
5936 if (!(*sc)->cenc.default_encrypted_sample)
5938 frag_stream_info->encryption_index = av_mallocz(sizeof(*frag_stream_info->encryption_index));
5939 if (!frag_stream_info->encryption_index)
5940 return AVERROR(ENOMEM);
5942 *encryption_index = frag_stream_info->encryption_index;
5945 // No current track fragment, using stream level encryption info.
5947 if (c->fc->nb_streams < 1)
5949 st = c->fc->streams[c->fc->nb_streams - 1];
5950 *sc = st->priv_data;
5952 if (!(*sc)->cenc.encryption_index) {
5953 // If this stream isn't encrypted, don't create the index.
5954 if (!(*sc)->cenc.default_encrypted_sample)
5956 (*sc)->cenc.encryption_index = av_mallocz(sizeof(*frag_stream_info->encryption_index));
5957 if (!(*sc)->cenc.encryption_index)
5958 return AVERROR(ENOMEM);
5961 *encryption_index = (*sc)->cenc.encryption_index;
5966 static int mov_read_sample_encryption_info(MOVContext *c, AVIOContext *pb, MOVStreamContext *sc, AVEncryptionInfo **sample, int use_subsamples)
5969 unsigned int subsample_count;
5970 AVSubsampleEncryptionInfo *subsamples;
5972 if (!sc->cenc.default_encrypted_sample) {
5973 av_log(c->fc, AV_LOG_ERROR, "Missing schm or tenc\n");
5974 return AVERROR_INVALIDDATA;
5977 *sample = av_encryption_info_clone(sc->cenc.default_encrypted_sample);
5979 return AVERROR(ENOMEM);
5981 if (sc->cenc.per_sample_iv_size != 0) {
5982 if ((ret = ffio_read_size(pb, (*sample)->iv, sc->cenc.per_sample_iv_size)) < 0) {
5983 av_log(c->fc, AV_LOG_ERROR, "failed to read the initialization vector\n");
5984 av_encryption_info_free(*sample);
5990 if (use_subsamples) {
5991 subsample_count = avio_rb16(pb);
5992 av_free((*sample)->subsamples);
5993 (*sample)->subsamples = av_mallocz_array(subsample_count, sizeof(*subsamples));
5994 if (!(*sample)->subsamples) {
5995 av_encryption_info_free(*sample);
5997 return AVERROR(ENOMEM);
6000 for (i = 0; i < subsample_count && !pb->eof_reached; i++) {
6001 (*sample)->subsamples[i].bytes_of_clear_data = avio_rb16(pb);
6002 (*sample)->subsamples[i].bytes_of_protected_data = avio_rb32(pb);
6005 if (pb->eof_reached) {
6006 av_log(c->fc, AV_LOG_ERROR, "hit EOF while reading sub-sample encryption info\n");
6007 av_encryption_info_free(*sample);
6009 return AVERROR_INVALIDDATA;
6011 (*sample)->subsample_count = subsample_count;
6017 static int mov_read_senc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6019 AVEncryptionInfo **encrypted_samples;
6020 MOVEncryptionIndex *encryption_index;
6021 MOVStreamContext *sc;
6022 int use_subsamples, ret;
6023 unsigned int sample_count, i, alloc_size = 0;
6025 ret = get_current_encryption_info(c, &encryption_index, &sc);
6029 if (encryption_index->nb_encrypted_samples) {
6030 // This can happen if we have both saio/saiz and senc atoms.
6031 av_log(c->fc, AV_LOG_DEBUG, "Ignoring duplicate encryption info in senc\n");
6035 avio_r8(pb); /* version */
6036 use_subsamples = avio_rb24(pb) & 0x02; /* flags */
6038 sample_count = avio_rb32(pb);
6039 if (sample_count >= INT_MAX / sizeof(*encrypted_samples))
6040 return AVERROR(ENOMEM);
6042 for (i = 0; i < sample_count; i++) {
6043 unsigned int min_samples = FFMIN(FFMAX(i + 1, 1024 * 1024), sample_count);
6044 encrypted_samples = av_fast_realloc(encryption_index->encrypted_samples, &alloc_size,
6045 min_samples * sizeof(*encrypted_samples));
6046 if (encrypted_samples) {
6047 encryption_index->encrypted_samples = encrypted_samples;
6049 ret = mov_read_sample_encryption_info(
6050 c, pb, sc, &encryption_index->encrypted_samples[i], use_subsamples);
6052 ret = AVERROR(ENOMEM);
6054 if (pb->eof_reached) {
6055 av_log(c->fc, AV_LOG_ERROR, "Hit EOF while reading senc\n");
6056 ret = AVERROR_INVALIDDATA;
6061 av_encryption_info_free(encryption_index->encrypted_samples[i - 1]);
6062 av_freep(&encryption_index->encrypted_samples);
6066 encryption_index->nb_encrypted_samples = sample_count;
6071 static int mov_parse_auxiliary_info(MOVContext *c, MOVStreamContext *sc, AVIOContext *pb, MOVEncryptionIndex *encryption_index)
6073 AVEncryptionInfo **sample, **encrypted_samples;
6075 size_t sample_count, sample_info_size, i;
6077 unsigned int alloc_size = 0;
6079 if (encryption_index->nb_encrypted_samples)
6081 sample_count = encryption_index->auxiliary_info_sample_count;
6082 if (encryption_index->auxiliary_offsets_count != 1) {
6083 av_log(c->fc, AV_LOG_ERROR, "Multiple auxiliary info chunks are not supported\n");
6084 return AVERROR_PATCHWELCOME;
6086 if (sample_count >= INT_MAX / sizeof(*encrypted_samples))
6087 return AVERROR(ENOMEM);
6089 prev_pos = avio_tell(pb);
6090 if (!(pb->seekable & AVIO_SEEKABLE_NORMAL) ||
6091 avio_seek(pb, encryption_index->auxiliary_offsets[0], SEEK_SET) != encryption_index->auxiliary_offsets[0]) {
6092 av_log(c->fc, AV_LOG_INFO, "Failed to seek for auxiliary info, will only parse senc atoms for encryption info\n");
6096 for (i = 0; i < sample_count && !pb->eof_reached; i++) {
6097 unsigned int min_samples = FFMIN(FFMAX(i + 1, 1024 * 1024), sample_count);
6098 encrypted_samples = av_fast_realloc(encryption_index->encrypted_samples, &alloc_size,
6099 min_samples * sizeof(*encrypted_samples));
6100 if (!encrypted_samples) {
6101 ret = AVERROR(ENOMEM);
6104 encryption_index->encrypted_samples = encrypted_samples;
6106 sample = &encryption_index->encrypted_samples[i];
6107 sample_info_size = encryption_index->auxiliary_info_default_size
6108 ? encryption_index->auxiliary_info_default_size
6109 : encryption_index->auxiliary_info_sizes[i];
6111 ret = mov_read_sample_encryption_info(c, pb, sc, sample, sample_info_size > sc->cenc.per_sample_iv_size);
6115 if (pb->eof_reached) {
6116 av_log(c->fc, AV_LOG_ERROR, "Hit EOF while reading auxiliary info\n");
6117 ret = AVERROR_INVALIDDATA;
6119 encryption_index->nb_encrypted_samples = sample_count;
6123 avio_seek(pb, prev_pos, SEEK_SET);
6125 for (; i > 0; i--) {
6126 av_encryption_info_free(encryption_index->encrypted_samples[i - 1]);
6128 av_freep(&encryption_index->encrypted_samples);
6134 * Tries to read the given number of bytes from the stream and puts it in a
6135 * newly allocated buffer. This reads in small chunks to avoid allocating large
6136 * memory if the file contains an invalid/malicious size value.
6138 static int mov_try_read_block(AVIOContext *pb, size_t size, uint8_t **data)
6140 const unsigned int block_size = 1024 * 1024;
6141 uint8_t *buffer = NULL;
6142 unsigned int alloc_size = 0, offset = 0;
6143 while (offset < size) {
6144 unsigned int new_size =
6145 alloc_size >= INT_MAX - block_size ? INT_MAX : alloc_size + block_size;
6146 uint8_t *new_buffer = av_fast_realloc(buffer, &alloc_size, new_size);
6147 unsigned int to_read = FFMIN(size, alloc_size) - offset;
6150 return AVERROR(ENOMEM);
6152 buffer = new_buffer;
6154 if (avio_read(pb, buffer + offset, to_read) != to_read) {
6156 return AVERROR_INVALIDDATA;
6165 static int mov_read_saiz(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6167 MOVEncryptionIndex *encryption_index;
6168 MOVStreamContext *sc;
6170 unsigned int sample_count, aux_info_type, aux_info_param;
6172 ret = get_current_encryption_info(c, &encryption_index, &sc);
6176 if (encryption_index->nb_encrypted_samples) {
6177 // This can happen if we have both saio/saiz and senc atoms.
6178 av_log(c->fc, AV_LOG_DEBUG, "Ignoring duplicate encryption info in saiz\n");
6182 if (encryption_index->auxiliary_info_sample_count) {
6183 av_log(c->fc, AV_LOG_ERROR, "Duplicate saiz atom\n");
6184 return AVERROR_INVALIDDATA;
6187 avio_r8(pb); /* version */
6188 if (avio_rb24(pb) & 0x01) { /* flags */
6189 aux_info_type = avio_rb32(pb);
6190 aux_info_param = avio_rb32(pb);
6191 if (sc->cenc.default_encrypted_sample) {
6192 if (aux_info_type != sc->cenc.default_encrypted_sample->scheme) {
6193 av_log(c->fc, AV_LOG_DEBUG, "Ignoring saiz box with non-zero aux_info_type\n");
6196 if (aux_info_param != 0) {
6197 av_log(c->fc, AV_LOG_DEBUG, "Ignoring saiz box with non-zero aux_info_type_parameter\n");
6201 // Didn't see 'schm' or 'tenc', so this isn't encrypted.
6202 if ((aux_info_type == MKBETAG('c','e','n','c') ||
6203 aux_info_type == MKBETAG('c','e','n','s') ||
6204 aux_info_type == MKBETAG('c','b','c','1') ||
6205 aux_info_type == MKBETAG('c','b','c','s')) &&
6206 aux_info_param == 0) {
6207 av_log(c->fc, AV_LOG_ERROR, "Saw encrypted saiz without schm/tenc\n");
6208 return AVERROR_INVALIDDATA;
6213 } else if (!sc->cenc.default_encrypted_sample) {
6214 // Didn't see 'schm' or 'tenc', so this isn't encrypted.
6218 encryption_index->auxiliary_info_default_size = avio_r8(pb);
6219 sample_count = avio_rb32(pb);
6220 encryption_index->auxiliary_info_sample_count = sample_count;
6222 if (encryption_index->auxiliary_info_default_size == 0) {
6223 ret = mov_try_read_block(pb, sample_count, &encryption_index->auxiliary_info_sizes);
6225 av_log(c->fc, AV_LOG_ERROR, "Failed to read the auxiliary info\n");
6230 if (encryption_index->auxiliary_offsets_count) {
6231 return mov_parse_auxiliary_info(c, sc, pb, encryption_index);
6237 static int mov_read_saio(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6239 uint64_t *auxiliary_offsets;
6240 MOVEncryptionIndex *encryption_index;
6241 MOVStreamContext *sc;
6243 unsigned int version, entry_count, aux_info_type, aux_info_param;
6244 unsigned int alloc_size = 0;
6246 ret = get_current_encryption_info(c, &encryption_index, &sc);
6250 if (encryption_index->nb_encrypted_samples) {
6251 // This can happen if we have both saio/saiz and senc atoms.
6252 av_log(c->fc, AV_LOG_DEBUG, "Ignoring duplicate encryption info in saio\n");
6256 if (encryption_index->auxiliary_offsets_count) {
6257 av_log(c->fc, AV_LOG_ERROR, "Duplicate saio atom\n");
6258 return AVERROR_INVALIDDATA;
6261 version = avio_r8(pb); /* version */
6262 if (avio_rb24(pb) & 0x01) { /* flags */
6263 aux_info_type = avio_rb32(pb);
6264 aux_info_param = avio_rb32(pb);
6265 if (sc->cenc.default_encrypted_sample) {
6266 if (aux_info_type != sc->cenc.default_encrypted_sample->scheme) {
6267 av_log(c->fc, AV_LOG_DEBUG, "Ignoring saio box with non-zero aux_info_type\n");
6270 if (aux_info_param != 0) {
6271 av_log(c->fc, AV_LOG_DEBUG, "Ignoring saio box with non-zero aux_info_type_parameter\n");
6275 // Didn't see 'schm' or 'tenc', so this isn't encrypted.
6276 if ((aux_info_type == MKBETAG('c','e','n','c') ||
6277 aux_info_type == MKBETAG('c','e','n','s') ||
6278 aux_info_type == MKBETAG('c','b','c','1') ||
6279 aux_info_type == MKBETAG('c','b','c','s')) &&
6280 aux_info_param == 0) {
6281 av_log(c->fc, AV_LOG_ERROR, "Saw encrypted saio without schm/tenc\n");
6282 return AVERROR_INVALIDDATA;
6287 } else if (!sc->cenc.default_encrypted_sample) {
6288 // Didn't see 'schm' or 'tenc', so this isn't encrypted.
6292 entry_count = avio_rb32(pb);
6293 if (entry_count >= INT_MAX / sizeof(*auxiliary_offsets))
6294 return AVERROR(ENOMEM);
6296 for (i = 0; i < entry_count && !pb->eof_reached; i++) {
6297 unsigned int min_offsets = FFMIN(FFMAX(i + 1, 1024), entry_count);
6298 auxiliary_offsets = av_fast_realloc(
6299 encryption_index->auxiliary_offsets, &alloc_size,
6300 min_offsets * sizeof(*auxiliary_offsets));
6301 if (!auxiliary_offsets) {
6302 av_freep(&encryption_index->auxiliary_offsets);
6303 return AVERROR(ENOMEM);
6305 encryption_index->auxiliary_offsets = auxiliary_offsets;
6308 encryption_index->auxiliary_offsets[i] = avio_rb32(pb);
6310 encryption_index->auxiliary_offsets[i] = avio_rb64(pb);
6312 if (c->frag_index.current >= 0) {
6313 encryption_index->auxiliary_offsets[i] += c->fragment.base_data_offset;
6317 if (pb->eof_reached) {
6318 av_log(c->fc, AV_LOG_ERROR, "Hit EOF while reading saio\n");
6319 av_freep(&encryption_index->auxiliary_offsets);
6320 return AVERROR_INVALIDDATA;
6323 encryption_index->auxiliary_offsets_count = entry_count;
6325 if (encryption_index->auxiliary_info_sample_count) {
6326 return mov_parse_auxiliary_info(c, sc, pb, encryption_index);
6332 static int mov_read_pssh(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6334 AVEncryptionInitInfo *info, *old_init_info;
6337 uint8_t *side_data, *extra_data, *old_side_data;
6338 size_t side_data_size;
6339 int ret = 0, old_side_data_size;
6340 unsigned int version, kid_count, extra_data_size, alloc_size = 0;
6342 if (c->fc->nb_streams < 1)
6344 st = c->fc->streams[c->fc->nb_streams-1];
6346 version = avio_r8(pb); /* version */
6347 avio_rb24(pb); /* flags */
6349 info = av_encryption_init_info_alloc(/* system_id_size */ 16, /* num_key_ids */ 0,
6350 /* key_id_size */ 16, /* data_size */ 0);
6352 return AVERROR(ENOMEM);
6354 if ((ret = ffio_read_size(pb, info->system_id, 16)) < 0) {
6355 av_log(c->fc, AV_LOG_ERROR, "Failed to read the system id\n");
6360 kid_count = avio_rb32(pb);
6361 if (kid_count >= INT_MAX / sizeof(*key_ids)) {
6362 ret = AVERROR(ENOMEM);
6366 for (unsigned int i = 0; i < kid_count && !pb->eof_reached; i++) {
6367 unsigned int min_kid_count = FFMIN(FFMAX(i + 1, 1024), kid_count);
6368 key_ids = av_fast_realloc(info->key_ids, &alloc_size,
6369 min_kid_count * sizeof(*key_ids));
6371 ret = AVERROR(ENOMEM);
6374 info->key_ids = key_ids;
6376 info->key_ids[i] = av_mallocz(16);
6377 if (!info->key_ids[i]) {
6378 ret = AVERROR(ENOMEM);
6381 info->num_key_ids = i + 1;
6383 if ((ret = ffio_read_size(pb, info->key_ids[i], 16)) < 0) {
6384 av_log(c->fc, AV_LOG_ERROR, "Failed to read the key id\n");
6389 if (pb->eof_reached) {
6390 av_log(c->fc, AV_LOG_ERROR, "Hit EOF while reading pssh\n");
6391 ret = AVERROR_INVALIDDATA;
6396 extra_data_size = avio_rb32(pb);
6397 ret = mov_try_read_block(pb, extra_data_size, &extra_data);
6401 av_freep(&info->data); // malloc(0) may still allocate something.
6402 info->data = extra_data;
6403 info->data_size = extra_data_size;
6405 // If there is existing initialization data, append to the list.
6406 old_side_data = av_stream_get_side_data(st, AV_PKT_DATA_ENCRYPTION_INIT_INFO, &old_side_data_size);
6407 if (old_side_data) {
6408 old_init_info = av_encryption_init_info_get_side_data(old_side_data, old_side_data_size);
6409 if (old_init_info) {
6410 // Append to the end of the list.
6411 for (AVEncryptionInitInfo *cur = old_init_info;; cur = cur->next) {
6417 info = old_init_info;
6419 // Assume existing side-data will be valid, so the only error we could get is OOM.
6420 ret = AVERROR(ENOMEM);
6425 side_data = av_encryption_init_info_add_side_data(info, &side_data_size);
6427 ret = AVERROR(ENOMEM);
6430 ret = av_stream_add_side_data(st, AV_PKT_DATA_ENCRYPTION_INIT_INFO,
6431 side_data, side_data_size);
6436 av_encryption_init_info_free(info);
6440 static int mov_read_schm(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6443 MOVStreamContext *sc;
6445 if (c->fc->nb_streams < 1)
6447 st = c->fc->streams[c->fc->nb_streams-1];
6450 if (sc->pseudo_stream_id != 0) {
6451 av_log(c->fc, AV_LOG_ERROR, "schm boxes are only supported in first sample descriptor\n");
6452 return AVERROR_PATCHWELCOME;
6456 return AVERROR_INVALIDDATA;
6458 avio_rb32(pb); /* version and flags */
6460 if (!sc->cenc.default_encrypted_sample) {
6461 sc->cenc.default_encrypted_sample = av_encryption_info_alloc(0, 16, 16);
6462 if (!sc->cenc.default_encrypted_sample) {
6463 return AVERROR(ENOMEM);
6467 sc->cenc.default_encrypted_sample->scheme = avio_rb32(pb);
6471 static int mov_read_tenc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6474 MOVStreamContext *sc;
6475 unsigned int version, pattern, is_protected, iv_size;
6477 if (c->fc->nb_streams < 1)
6479 st = c->fc->streams[c->fc->nb_streams-1];
6482 if (sc->pseudo_stream_id != 0) {
6483 av_log(c->fc, AV_LOG_ERROR, "tenc atom are only supported in first sample descriptor\n");
6484 return AVERROR_PATCHWELCOME;
6487 if (!sc->cenc.default_encrypted_sample) {
6488 sc->cenc.default_encrypted_sample = av_encryption_info_alloc(0, 16, 16);
6489 if (!sc->cenc.default_encrypted_sample) {
6490 return AVERROR(ENOMEM);
6495 return AVERROR_INVALIDDATA;
6497 version = avio_r8(pb); /* version */
6498 avio_rb24(pb); /* flags */
6500 avio_r8(pb); /* reserved */
6501 pattern = avio_r8(pb);
6504 sc->cenc.default_encrypted_sample->crypt_byte_block = pattern >> 4;
6505 sc->cenc.default_encrypted_sample->skip_byte_block = pattern & 0xf;
6508 is_protected = avio_r8(pb);
6509 if (is_protected && !sc->cenc.encryption_index) {
6510 // The whole stream should be by-default encrypted.
6511 sc->cenc.encryption_index = av_mallocz(sizeof(MOVEncryptionIndex));
6512 if (!sc->cenc.encryption_index)
6513 return AVERROR(ENOMEM);
6515 sc->cenc.per_sample_iv_size = avio_r8(pb);
6516 if (sc->cenc.per_sample_iv_size != 0 && sc->cenc.per_sample_iv_size != 8 &&
6517 sc->cenc.per_sample_iv_size != 16) {
6518 av_log(c->fc, AV_LOG_ERROR, "invalid per-sample IV size value\n");
6519 return AVERROR_INVALIDDATA;
6521 if (avio_read(pb, sc->cenc.default_encrypted_sample->key_id, 16) != 16) {
6522 av_log(c->fc, AV_LOG_ERROR, "failed to read the default key ID\n");
6523 return AVERROR_INVALIDDATA;
6526 if (is_protected && !sc->cenc.per_sample_iv_size) {
6527 iv_size = avio_r8(pb);
6528 if (iv_size != 8 && iv_size != 16) {
6529 av_log(c->fc, AV_LOG_ERROR, "invalid default_constant_IV_size in tenc atom\n");
6530 return AVERROR_INVALIDDATA;
6533 if (avio_read(pb, sc->cenc.default_encrypted_sample->iv, iv_size) != iv_size) {
6534 av_log(c->fc, AV_LOG_ERROR, "failed to read the default IV\n");
6535 return AVERROR_INVALIDDATA;
6542 static int mov_read_dfla(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6545 int last, type, size, ret;
6548 if (c->fc->nb_streams < 1)
6550 st = c->fc->streams[c->fc->nb_streams-1];
6552 if ((uint64_t)atom.size > (1<<30) || atom.size < 42)
6553 return AVERROR_INVALIDDATA;
6555 /* Check FlacSpecificBox version. */
6556 if (avio_r8(pb) != 0)
6557 return AVERROR_INVALIDDATA;
6559 avio_rb24(pb); /* Flags */
6561 avio_read(pb, buf, sizeof(buf));
6562 flac_parse_block_header(buf, &last, &type, &size);
6564 if (type != FLAC_METADATA_TYPE_STREAMINFO || size != FLAC_STREAMINFO_SIZE) {
6565 av_log(c->fc, AV_LOG_ERROR, "STREAMINFO must be first FLACMetadataBlock\n");
6566 return AVERROR_INVALIDDATA;
6569 ret = ff_get_extradata(c->fc, st->codecpar, pb, size);
6574 av_log(c->fc, AV_LOG_WARNING, "non-STREAMINFO FLACMetadataBlock(s) ignored\n");
6579 static int cenc_decrypt(MOVContext *c, MOVStreamContext *sc, AVEncryptionInfo *sample, uint8_t *input, int size)
6583 if (sample->scheme != MKBETAG('c','e','n','c') || sample->crypt_byte_block != 0 || sample->skip_byte_block != 0) {
6584 av_log(c->fc, AV_LOG_ERROR, "Only the 'cenc' encryption scheme is supported\n");
6585 return AVERROR_PATCHWELCOME;
6588 if (!sc->cenc.aes_ctr) {
6589 /* initialize the cipher */
6590 sc->cenc.aes_ctr = av_aes_ctr_alloc();
6591 if (!sc->cenc.aes_ctr) {
6592 return AVERROR(ENOMEM);
6595 ret = av_aes_ctr_init(sc->cenc.aes_ctr, c->decryption_key);
6601 av_aes_ctr_set_full_iv(sc->cenc.aes_ctr, sample->iv);
6603 if (!sample->subsample_count)
6605 /* decrypt the whole packet */
6606 av_aes_ctr_crypt(sc->cenc.aes_ctr, input, input, size);
6610 for (i = 0; i < sample->subsample_count; i++)
6612 if (sample->subsamples[i].bytes_of_clear_data + sample->subsamples[i].bytes_of_protected_data > size) {
6613 av_log(c->fc, AV_LOG_ERROR, "subsample size exceeds the packet size left\n");
6614 return AVERROR_INVALIDDATA;
6617 /* skip the clear bytes */
6618 input += sample->subsamples[i].bytes_of_clear_data;
6619 size -= sample->subsamples[i].bytes_of_clear_data;
6621 /* decrypt the encrypted bytes */
6622 av_aes_ctr_crypt(sc->cenc.aes_ctr, input, input, sample->subsamples[i].bytes_of_protected_data);
6623 input += sample->subsamples[i].bytes_of_protected_data;
6624 size -= sample->subsamples[i].bytes_of_protected_data;
6628 av_log(c->fc, AV_LOG_ERROR, "leftover packet bytes after subsample processing\n");
6629 return AVERROR_INVALIDDATA;
6635 static int cenc_filter(MOVContext *mov, AVStream* st, MOVStreamContext *sc, AVPacket *pkt, int current_index)
6637 MOVFragmentStreamInfo *frag_stream_info;
6638 MOVEncryptionIndex *encryption_index;
6639 AVEncryptionInfo *encrypted_sample;
6640 int encrypted_index, ret;
6642 frag_stream_info = get_frag_stream_info(&mov->frag_index, mov->frag_index.current, st->id);
6643 encrypted_index = current_index;
6644 encryption_index = NULL;
6645 if (frag_stream_info) {
6646 // Note this only supports encryption info in the first sample descriptor.
6647 if (mov->fragment.stsd_id == 1) {
6648 if (frag_stream_info->encryption_index) {
6649 encrypted_index = current_index - frag_stream_info->index_entry;
6650 encryption_index = frag_stream_info->encryption_index;
6652 encryption_index = sc->cenc.encryption_index;
6656 encryption_index = sc->cenc.encryption_index;
6659 if (encryption_index) {
6660 if (encryption_index->auxiliary_info_sample_count &&
6661 !encryption_index->nb_encrypted_samples) {
6662 av_log(mov->fc, AV_LOG_ERROR, "saiz atom found without saio\n");
6663 return AVERROR_INVALIDDATA;
6665 if (encryption_index->auxiliary_offsets_count &&
6666 !encryption_index->nb_encrypted_samples) {
6667 av_log(mov->fc, AV_LOG_ERROR, "saio atom found without saiz\n");
6668 return AVERROR_INVALIDDATA;
6671 if (!encryption_index->nb_encrypted_samples) {
6672 // Full-sample encryption with default settings.
6673 encrypted_sample = sc->cenc.default_encrypted_sample;
6674 } else if (encrypted_index >= 0 && encrypted_index < encryption_index->nb_encrypted_samples) {
6675 // Per-sample setting override.
6676 encrypted_sample = encryption_index->encrypted_samples[encrypted_index];
6678 av_log(mov->fc, AV_LOG_ERROR, "Incorrect number of samples in encryption info\n");
6679 return AVERROR_INVALIDDATA;
6682 if (mov->decryption_key) {
6683 return cenc_decrypt(mov, sc, encrypted_sample, pkt->data, pkt->size);
6686 uint8_t *side_data = av_encryption_info_add_side_data(encrypted_sample, &size);
6688 return AVERROR(ENOMEM);
6689 ret = av_packet_add_side_data(pkt, AV_PKT_DATA_ENCRYPTION_INFO, side_data, size);
6699 static int mov_read_dops(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6701 const int OPUS_SEEK_PREROLL_MS = 80;
6707 if (c->fc->nb_streams < 1)
6709 st = c->fc->streams[c->fc->nb_streams-1];
6711 if ((uint64_t)atom.size > (1<<30) || atom.size < 11)
6712 return AVERROR_INVALIDDATA;
6714 /* Check OpusSpecificBox version. */
6715 if (avio_r8(pb) != 0) {
6716 av_log(c->fc, AV_LOG_ERROR, "unsupported OpusSpecificBox version\n");
6717 return AVERROR_INVALIDDATA;
6720 /* OpusSpecificBox size plus magic for Ogg OpusHead header. */
6721 size = atom.size + 8;
6723 if ((ret = ff_alloc_extradata(st->codecpar, size)) < 0)
6726 AV_WL32(st->codecpar->extradata, MKTAG('O','p','u','s'));
6727 AV_WL32(st->codecpar->extradata + 4, MKTAG('H','e','a','d'));
6728 AV_WB8(st->codecpar->extradata + 8, 1); /* OpusHead version */
6729 avio_read(pb, st->codecpar->extradata + 9, size - 9);
6731 /* OpusSpecificBox is stored in big-endian, but OpusHead is
6732 little-endian; aside from the preceeding magic and version they're
6733 otherwise currently identical. Data after output gain at offset 16
6734 doesn't need to be bytewapped. */
6735 pre_skip = AV_RB16(st->codecpar->extradata + 10);
6736 AV_WL16(st->codecpar->extradata + 10, pre_skip);
6737 AV_WL32(st->codecpar->extradata + 12, AV_RB32(st->codecpar->extradata + 12));
6738 AV_WL16(st->codecpar->extradata + 16, AV_RB16(st->codecpar->extradata + 16));
6740 st->codecpar->initial_padding = pre_skip;
6741 st->codecpar->seek_preroll = av_rescale_q(OPUS_SEEK_PREROLL_MS,
6742 (AVRational){1, 1000},
6743 (AVRational){1, 48000});
6748 static int mov_read_dmlp(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6751 unsigned format_info;
6752 int channel_assignment, channel_assignment1, channel_assignment2;
6755 if (c->fc->nb_streams < 1)
6757 st = c->fc->streams[c->fc->nb_streams-1];
6760 return AVERROR_INVALIDDATA;
6762 format_info = avio_rb32(pb);
6764 ratebits = (format_info >> 28) & 0xF;
6765 channel_assignment1 = (format_info >> 15) & 0x1F;
6766 channel_assignment2 = format_info & 0x1FFF;
6767 if (channel_assignment2)
6768 channel_assignment = channel_assignment2;
6770 channel_assignment = channel_assignment1;
6772 st->codecpar->frame_size = 40 << (ratebits & 0x7);
6773 st->codecpar->sample_rate = mlp_samplerate(ratebits);
6774 st->codecpar->channels = truehd_channels(channel_assignment);
6775 st->codecpar->channel_layout = truehd_layout(channel_assignment);
6780 static int mov_read_dvcc_dvvc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6784 AVDOVIDecoderConfigurationRecord *dovi;
6788 if (c->fc->nb_streams < 1)
6790 st = c->fc->streams[c->fc->nb_streams-1];
6792 if ((uint64_t)atom.size > (1<<30) || atom.size < 4)
6793 return AVERROR_INVALIDDATA;
6795 dovi = av_dovi_alloc(&dovi_size);
6797 return AVERROR(ENOMEM);
6799 dovi->dv_version_major = avio_r8(pb);
6800 dovi->dv_version_minor = avio_r8(pb);
6802 buf = avio_rb16(pb);
6803 dovi->dv_profile = (buf >> 9) & 0x7f; // 7 bits
6804 dovi->dv_level = (buf >> 3) & 0x3f; // 6 bits
6805 dovi->rpu_present_flag = (buf >> 2) & 0x01; // 1 bit
6806 dovi->el_present_flag = (buf >> 1) & 0x01; // 1 bit
6807 dovi->bl_present_flag = buf & 0x01; // 1 bit
6808 if (atom.size >= 24) { // 4 + 4 + 4 * 4
6810 dovi->dv_bl_signal_compatibility_id = (buf >> 4) & 0x0f; // 4 bits
6812 // 0 stands for None
6813 // Dolby Vision V1.2.93 profiles and levels
6814 dovi->dv_bl_signal_compatibility_id = 0;
6817 ret = av_stream_add_side_data(st, AV_PKT_DATA_DOVI_CONF,
6818 (uint8_t *)dovi, dovi_size);
6824 av_log(c, AV_LOG_TRACE, "DOVI in dvcC/dvvC box, version: %d.%d, profile: %d, level: %d, "
6825 "rpu flag: %d, el flag: %d, bl flag: %d, compatibility id: %d\n",
6826 dovi->dv_version_major, dovi->dv_version_minor,
6827 dovi->dv_profile, dovi->dv_level,
6828 dovi->rpu_present_flag,
6829 dovi->el_present_flag,
6830 dovi->bl_present_flag,
6831 dovi->dv_bl_signal_compatibility_id
6837 static const MOVParseTableEntry mov_default_parse_table[] = {
6838 { MKTAG('A','C','L','R'), mov_read_aclr },
6839 { MKTAG('A','P','R','G'), mov_read_avid },
6840 { MKTAG('A','A','L','P'), mov_read_avid },
6841 { MKTAG('A','R','E','S'), mov_read_ares },
6842 { MKTAG('a','v','s','s'), mov_read_avss },
6843 { MKTAG('a','v','1','C'), mov_read_av1c },
6844 { MKTAG('c','h','p','l'), mov_read_chpl },
6845 { MKTAG('c','o','6','4'), mov_read_stco },
6846 { MKTAG('c','o','l','r'), mov_read_colr },
6847 { MKTAG('c','t','t','s'), mov_read_ctts }, /* composition time to sample */
6848 { MKTAG('d','i','n','f'), mov_read_default },
6849 { MKTAG('D','p','x','E'), mov_read_dpxe },
6850 { MKTAG('d','r','e','f'), mov_read_dref },
6851 { MKTAG('e','d','t','s'), mov_read_default },
6852 { MKTAG('e','l','s','t'), mov_read_elst },
6853 { MKTAG('e','n','d','a'), mov_read_enda },
6854 { MKTAG('f','i','e','l'), mov_read_fiel },
6855 { MKTAG('a','d','r','m'), mov_read_adrm },
6856 { MKTAG('f','t','y','p'), mov_read_ftyp },
6857 { MKTAG('g','l','b','l'), mov_read_glbl },
6858 { MKTAG('h','d','l','r'), mov_read_hdlr },
6859 { MKTAG('i','l','s','t'), mov_read_ilst },
6860 { MKTAG('j','p','2','h'), mov_read_jp2h },
6861 { MKTAG('m','d','a','t'), mov_read_mdat },
6862 { MKTAG('m','d','h','d'), mov_read_mdhd },
6863 { MKTAG('m','d','i','a'), mov_read_default },
6864 { MKTAG('m','e','t','a'), mov_read_meta },
6865 { MKTAG('m','i','n','f'), mov_read_default },
6866 { MKTAG('m','o','o','f'), mov_read_moof },
6867 { MKTAG('m','o','o','v'), mov_read_moov },
6868 { MKTAG('m','v','e','x'), mov_read_default },
6869 { MKTAG('m','v','h','d'), mov_read_mvhd },
6870 { MKTAG('S','M','I',' '), mov_read_svq3 },
6871 { MKTAG('a','l','a','c'), mov_read_alac }, /* alac specific atom */
6872 { MKTAG('a','v','c','C'), mov_read_glbl },
6873 { MKTAG('p','a','s','p'), mov_read_pasp },
6874 { MKTAG('s','i','d','x'), mov_read_sidx },
6875 { MKTAG('s','t','b','l'), mov_read_default },
6876 { MKTAG('s','t','c','o'), mov_read_stco },
6877 { MKTAG('s','t','p','s'), mov_read_stps },
6878 { MKTAG('s','t','r','f'), mov_read_strf },
6879 { MKTAG('s','t','s','c'), mov_read_stsc },
6880 { MKTAG('s','t','s','d'), mov_read_stsd }, /* sample description */
6881 { MKTAG('s','t','s','s'), mov_read_stss }, /* sync sample */
6882 { MKTAG('s','t','s','z'), mov_read_stsz }, /* sample size */
6883 { MKTAG('s','t','t','s'), mov_read_stts },
6884 { MKTAG('s','t','z','2'), mov_read_stsz }, /* compact sample size */
6885 { MKTAG('s','d','t','p'), mov_read_sdtp }, /* independent and disposable samples */
6886 { MKTAG('t','k','h','d'), mov_read_tkhd }, /* track header */
6887 { MKTAG('t','f','d','t'), mov_read_tfdt },
6888 { MKTAG('t','f','h','d'), mov_read_tfhd }, /* track fragment header */
6889 { MKTAG('t','r','a','k'), mov_read_trak },
6890 { MKTAG('t','r','a','f'), mov_read_default },
6891 { MKTAG('t','r','e','f'), mov_read_default },
6892 { MKTAG('t','m','c','d'), mov_read_tmcd },
6893 { MKTAG('c','h','a','p'), mov_read_chap },
6894 { MKTAG('t','r','e','x'), mov_read_trex },
6895 { MKTAG('t','r','u','n'), mov_read_trun },
6896 { MKTAG('u','d','t','a'), mov_read_default },
6897 { MKTAG('w','a','v','e'), mov_read_wave },
6898 { MKTAG('e','s','d','s'), mov_read_esds },
6899 { MKTAG('d','a','c','3'), mov_read_dac3 }, /* AC-3 info */
6900 { MKTAG('d','e','c','3'), mov_read_dec3 }, /* EAC-3 info */
6901 { MKTAG('d','d','t','s'), mov_read_ddts }, /* DTS audio descriptor */
6902 { MKTAG('w','i','d','e'), mov_read_wide }, /* place holder */
6903 { MKTAG('w','f','e','x'), mov_read_wfex },
6904 { MKTAG('c','m','o','v'), mov_read_cmov },
6905 { MKTAG('c','h','a','n'), mov_read_chan }, /* channel layout */
6906 { MKTAG('d','v','c','1'), mov_read_dvc1 },
6907 { MKTAG('s','b','g','p'), mov_read_sbgp },
6908 { MKTAG('h','v','c','C'), mov_read_glbl },
6909 { MKTAG('u','u','i','d'), mov_read_uuid },
6910 { MKTAG('C','i','n', 0x8e), mov_read_targa_y216 },
6911 { MKTAG('f','r','e','e'), mov_read_free },
6912 { MKTAG('-','-','-','-'), mov_read_custom },
6913 { MKTAG('s','i','n','f'), mov_read_default },
6914 { MKTAG('f','r','m','a'), mov_read_frma },
6915 { MKTAG('s','e','n','c'), mov_read_senc },
6916 { MKTAG('s','a','i','z'), mov_read_saiz },
6917 { MKTAG('s','a','i','o'), mov_read_saio },
6918 { MKTAG('p','s','s','h'), mov_read_pssh },
6919 { MKTAG('s','c','h','m'), mov_read_schm },
6920 { MKTAG('s','c','h','i'), mov_read_default },
6921 { MKTAG('t','e','n','c'), mov_read_tenc },
6922 { MKTAG('d','f','L','a'), mov_read_dfla },
6923 { MKTAG('s','t','3','d'), mov_read_st3d }, /* stereoscopic 3D video box */
6924 { MKTAG('s','v','3','d'), mov_read_sv3d }, /* spherical video box */
6925 { MKTAG('d','O','p','s'), mov_read_dops },
6926 { MKTAG('d','m','l','p'), mov_read_dmlp },
6927 { MKTAG('S','m','D','m'), mov_read_smdm },
6928 { MKTAG('C','o','L','L'), mov_read_coll },
6929 { MKTAG('v','p','c','C'), mov_read_vpcc },
6930 { MKTAG('m','d','c','v'), mov_read_mdcv },
6931 { MKTAG('c','l','l','i'), mov_read_clli },
6932 { MKTAG('d','v','c','C'), mov_read_dvcc_dvvc },
6933 { MKTAG('d','v','v','C'), mov_read_dvcc_dvvc },
6937 static int mov_read_default(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6939 int64_t total_size = 0;
6943 if (c->atom_depth > 10) {
6944 av_log(c->fc, AV_LOG_ERROR, "Atoms too deeply nested\n");
6945 return AVERROR_INVALIDDATA;
6950 atom.size = INT64_MAX;
6951 while (total_size <= atom.size - 8 && !avio_feof(pb)) {
6952 int (*parse)(MOVContext*, AVIOContext*, MOVAtom) = NULL;
6955 if (atom.size >= 8) {
6956 a.size = avio_rb32(pb);
6957 a.type = avio_rl32(pb);
6958 if (((a.type == MKTAG('f','r','e','e') && c->moov_retry) ||
6959 a.type == MKTAG('h','o','o','v')) &&
6961 c->fc->strict_std_compliance < FF_COMPLIANCE_STRICT) {
6963 uint32_t *type = (uint32_t *)buf + 1;
6964 if (avio_read(pb, buf, 8) != 8)
6965 return AVERROR_INVALIDDATA;
6966 avio_seek(pb, -8, SEEK_CUR);
6967 if (*type == MKTAG('m','v','h','d') ||
6968 *type == MKTAG('c','m','o','v')) {
6969 av_log(c->fc, AV_LOG_ERROR, "Detected moov in a free or hoov atom.\n");
6970 a.type = MKTAG('m','o','o','v');
6973 if (atom.type != MKTAG('r','o','o','t') &&
6974 atom.type != MKTAG('m','o','o','v'))
6976 if (a.type == MKTAG('t','r','a','k') || a.type == MKTAG('m','d','a','t'))
6978 av_log(c->fc, AV_LOG_ERROR, "Broken file, trak/mdat not at top-level\n");
6985 if (a.size == 1 && total_size + 8 <= atom.size) { /* 64 bit extended size */
6986 a.size = avio_rb64(pb) - 8;
6990 av_log(c->fc, AV_LOG_TRACE, "type:'%s' parent:'%s' sz: %"PRId64" %"PRId64" %"PRId64"\n",
6991 av_fourcc2str(a.type), av_fourcc2str(atom.type), a.size, total_size, atom.size);
6993 a.size = atom.size - total_size + 8;
6998 a.size = FFMIN(a.size, atom.size - total_size);
7000 for (i = 0; mov_default_parse_table[i].type; i++)
7001 if (mov_default_parse_table[i].type == a.type) {
7002 parse = mov_default_parse_table[i].parse;
7006 // container is user data
7007 if (!parse && (atom.type == MKTAG('u','d','t','a') ||
7008 atom.type == MKTAG('i','l','s','t')))
7009 parse = mov_read_udta_string;
7011 // Supports parsing the QuickTime Metadata Keys.
7012 // https://developer.apple.com/library/mac/documentation/QuickTime/QTFF/Metadata/Metadata.html
7013 if (!parse && c->found_hdlr_mdta &&
7014 atom.type == MKTAG('m','e','t','a') &&
7015 a.type == MKTAG('k','e','y','s') &&
7016 c->meta_keys_count == 0) {
7017 parse = mov_read_keys;
7020 if (!parse) { /* skip leaf atoms data */
7021 avio_skip(pb, a.size);
7023 int64_t start_pos = avio_tell(pb);
7025 int err = parse(c, pb, a);
7030 if (c->found_moov && c->found_mdat &&
7031 ((!(pb->seekable & AVIO_SEEKABLE_NORMAL) || c->fc->flags & AVFMT_FLAG_IGNIDX || c->frag_index.complete) ||
7032 start_pos + a.size == avio_size(pb))) {
7033 if (!(pb->seekable & AVIO_SEEKABLE_NORMAL) || c->fc->flags & AVFMT_FLAG_IGNIDX || c->frag_index.complete)
7034 c->next_root_atom = start_pos + a.size;
7038 left = a.size - avio_tell(pb) + start_pos;
7039 if (left > 0) /* skip garbage at atom end */
7040 avio_skip(pb, left);
7041 else if (left < 0) {
7042 av_log(c->fc, AV_LOG_WARNING,
7043 "overread end of atom '%.4s' by %"PRId64" bytes\n",
7044 (char*)&a.type, -left);
7045 avio_seek(pb, left, SEEK_CUR);
7049 total_size += a.size;
7052 if (total_size < atom.size && atom.size < 0x7ffff)
7053 avio_skip(pb, atom.size - total_size);
7059 static int mov_probe(const AVProbeData *p)
7064 int moov_offset = -1;
7066 /* check file header */
7069 /* ignore invalid offset */
7070 if ((offset + 8) > (unsigned int)p->buf_size)
7072 tag = AV_RL32(p->buf + offset + 4);
7074 /* check for obvious tags */
7075 case MKTAG('m','o','o','v'):
7076 moov_offset = offset + 4;
7077 case MKTAG('m','d','a','t'):
7078 case MKTAG('p','n','o','t'): /* detect movs with preview pics like ew.mov and april.mov */
7079 case MKTAG('u','d','t','a'): /* Packet Video PVAuthor adds this and a lot of more junk */
7080 case MKTAG('f','t','y','p'):
7081 if (AV_RB32(p->buf+offset) < 8 &&
7082 (AV_RB32(p->buf+offset) != 1 ||
7083 offset + 12 > (unsigned int)p->buf_size ||
7084 AV_RB64(p->buf+offset + 8) == 0)) {
7085 score = FFMAX(score, AVPROBE_SCORE_EXTENSION);
7086 } else if (tag == MKTAG('f','t','y','p') &&
7087 ( AV_RL32(p->buf + offset + 8) == MKTAG('j','p','2',' ')
7088 || AV_RL32(p->buf + offset + 8) == MKTAG('j','p','x',' ')
7090 score = FFMAX(score, 5);
7092 score = AVPROBE_SCORE_MAX;
7094 offset = FFMAX(4, AV_RB32(p->buf+offset)) + offset;
7096 /* those are more common words, so rate then a bit less */
7097 case MKTAG('e','d','i','w'): /* xdcam files have reverted first tags */
7098 case MKTAG('w','i','d','e'):
7099 case MKTAG('f','r','e','e'):
7100 case MKTAG('j','u','n','k'):
7101 case MKTAG('p','i','c','t'):
7102 score = FFMAX(score, AVPROBE_SCORE_MAX - 5);
7103 offset = FFMAX(4, AV_RB32(p->buf+offset)) + offset;
7105 case MKTAG(0x82,0x82,0x7f,0x7d):
7106 case MKTAG('s','k','i','p'):
7107 case MKTAG('u','u','i','d'):
7108 case MKTAG('p','r','f','l'):
7109 /* if we only find those cause probedata is too small at least rate them */
7110 score = FFMAX(score, AVPROBE_SCORE_EXTENSION);
7111 offset = FFMAX(4, AV_RB32(p->buf+offset)) + offset;
7114 offset = FFMAX(4, AV_RB32(p->buf+offset)) + offset;
7117 if(score > AVPROBE_SCORE_MAX - 50 && moov_offset != -1) {
7118 /* moov atom in the header - we should make sure that this is not a
7119 * MOV-packed MPEG-PS */
7120 offset = moov_offset;
7122 while(offset < (p->buf_size - 16)){ /* Sufficient space */
7123 /* We found an actual hdlr atom */
7124 if(AV_RL32(p->buf + offset ) == MKTAG('h','d','l','r') &&
7125 AV_RL32(p->buf + offset + 8) == MKTAG('m','h','l','r') &&
7126 AV_RL32(p->buf + offset + 12) == MKTAG('M','P','E','G')){
7127 av_log(NULL, AV_LOG_WARNING, "Found media data tag MPEG indicating this is a MOV-packed MPEG-PS.\n");
7128 /* We found a media handler reference atom describing an
7129 * MPEG-PS-in-MOV, return a
7130 * low score to force expanding the probe window until
7131 * mpegps_probe finds what it needs */
7142 // must be done after parsing all trak because there's no order requirement
7143 static void mov_read_chapters(AVFormatContext *s)
7145 MOVContext *mov = s->priv_data;
7147 MOVStreamContext *sc;
7152 for (j = 0; j < mov->nb_chapter_tracks; j++) {
7153 chapter_track = mov->chapter_tracks[j];
7155 for (i = 0; i < s->nb_streams; i++)
7156 if (s->streams[i]->id == chapter_track) {
7161 av_log(s, AV_LOG_ERROR, "Referenced QT chapter track not found\n");
7166 cur_pos = avio_tell(sc->pb);
7168 if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
7169 st->disposition |= AV_DISPOSITION_ATTACHED_PIC | AV_DISPOSITION_TIMED_THUMBNAILS;
7170 if (st->nb_index_entries) {
7171 // Retrieve the first frame, if possible
7172 AVIndexEntry *sample = &st->index_entries[0];
7173 if (avio_seek(sc->pb, sample->pos, SEEK_SET) != sample->pos) {
7174 av_log(s, AV_LOG_ERROR, "Failed to retrieve first frame\n");
7178 if (av_get_packet(sc->pb, &st->attached_pic, sample->size) < 0)
7181 st->attached_pic.stream_index = st->index;
7182 st->attached_pic.flags |= AV_PKT_FLAG_KEY;
7185 st->codecpar->codec_type = AVMEDIA_TYPE_DATA;
7186 st->codecpar->codec_id = AV_CODEC_ID_BIN_DATA;
7187 st->discard = AVDISCARD_ALL;
7188 for (i = 0; i < st->nb_index_entries; i++) {
7189 AVIndexEntry *sample = &st->index_entries[i];
7190 int64_t end = i+1 < st->nb_index_entries ? st->index_entries[i+1].timestamp : st->duration;
7195 if (end < sample->timestamp) {
7196 av_log(s, AV_LOG_WARNING, "ignoring stream duration which is shorter than chapters\n");
7197 end = AV_NOPTS_VALUE;
7200 if (avio_seek(sc->pb, sample->pos, SEEK_SET) != sample->pos) {
7201 av_log(s, AV_LOG_ERROR, "Chapter %d not found in file\n", i);
7205 // the first two bytes are the length of the title
7206 len = avio_rb16(sc->pb);
7207 if (len > sample->size-2)
7209 title_len = 2*len + 1;
7210 if (!(title = av_mallocz(title_len)))
7213 // The samples could theoretically be in any encoding if there's an encd
7214 // atom following, but in practice are only utf-8 or utf-16, distinguished
7215 // instead by the presence of a BOM
7219 ch = avio_rb16(sc->pb);
7221 avio_get_str16be(sc->pb, len, title, title_len);
7222 else if (ch == 0xfffe)
7223 avio_get_str16le(sc->pb, len, title, title_len);
7226 if (len == 1 || len == 2)
7229 avio_get_str(sc->pb, INT_MAX, title + 2, len - 1);
7233 avpriv_new_chapter(s, i, st->time_base, sample->timestamp, end, title);
7238 avio_seek(sc->pb, cur_pos, SEEK_SET);
7242 static int parse_timecode_in_framenum_format(AVFormatContext *s, AVStream *st,
7243 uint32_t value, int flags)
7246 char buf[AV_TIMECODE_STR_SIZE];
7247 AVRational rate = st->avg_frame_rate;
7248 int ret = av_timecode_init(&tc, rate, flags, 0, s);
7251 av_dict_set(&st->metadata, "timecode",
7252 av_timecode_make_string(&tc, buf, value), 0);
7256 static int mov_read_rtmd_track(AVFormatContext *s, AVStream *st)
7258 MOVStreamContext *sc = st->priv_data;
7259 char buf[AV_TIMECODE_STR_SIZE];
7260 int64_t cur_pos = avio_tell(sc->pb);
7261 int hh, mm, ss, ff, drop;
7263 if (!st->nb_index_entries)
7266 avio_seek(sc->pb, st->index_entries->pos, SEEK_SET);
7267 avio_skip(s->pb, 13);
7268 hh = avio_r8(s->pb);
7269 mm = avio_r8(s->pb);
7270 ss = avio_r8(s->pb);
7271 drop = avio_r8(s->pb);
7272 ff = avio_r8(s->pb);
7273 snprintf(buf, AV_TIMECODE_STR_SIZE, "%02d:%02d:%02d%c%02d",
7274 hh, mm, ss, drop ? ';' : ':', ff);
7275 av_dict_set(&st->metadata, "timecode", buf, 0);
7277 avio_seek(sc->pb, cur_pos, SEEK_SET);
7281 static int mov_read_timecode_track(AVFormatContext *s, AVStream *st)
7283 MOVStreamContext *sc = st->priv_data;
7285 int64_t cur_pos = avio_tell(sc->pb);
7288 if (!st->nb_index_entries)
7291 avio_seek(sc->pb, st->index_entries->pos, SEEK_SET);
7292 value = avio_rb32(s->pb);
7294 if (sc->tmcd_flags & 0x0001) flags |= AV_TIMECODE_FLAG_DROPFRAME;
7295 if (sc->tmcd_flags & 0x0002) flags |= AV_TIMECODE_FLAG_24HOURSMAX;
7296 if (sc->tmcd_flags & 0x0004) flags |= AV_TIMECODE_FLAG_ALLOWNEGATIVE;
7298 /* Assume Counter flag is set to 1 in tmcd track (even though it is likely
7299 * not the case) and thus assume "frame number format" instead of QT one.
7300 * No sample with tmcd track can be found with a QT timecode at the moment,
7301 * despite what the tmcd track "suggests" (Counter flag set to 0 means QT
7303 parse_timecode_in_framenum_format(s, st, value, flags);
7305 avio_seek(sc->pb, cur_pos, SEEK_SET);
7309 static void mov_free_encryption_index(MOVEncryptionIndex **index) {
7311 if (!index || !*index) return;
7312 for (i = 0; i < (*index)->nb_encrypted_samples; i++) {
7313 av_encryption_info_free((*index)->encrypted_samples[i]);
7315 av_freep(&(*index)->encrypted_samples);
7316 av_freep(&(*index)->auxiliary_info_sizes);
7317 av_freep(&(*index)->auxiliary_offsets);
7321 static int mov_read_close(AVFormatContext *s)
7323 MOVContext *mov = s->priv_data;
7326 for (i = 0; i < s->nb_streams; i++) {
7327 AVStream *st = s->streams[i];
7328 MOVStreamContext *sc = st->priv_data;
7333 av_freep(&sc->ctts_data);
7334 for (j = 0; j < sc->drefs_count; j++) {
7335 av_freep(&sc->drefs[j].path);
7336 av_freep(&sc->drefs[j].dir);
7338 av_freep(&sc->drefs);
7340 sc->drefs_count = 0;
7342 if (!sc->pb_is_copied)
7343 ff_format_io_close(s, &sc->pb);
7346 av_freep(&sc->chunk_offsets);
7347 av_freep(&sc->stsc_data);
7348 av_freep(&sc->sample_sizes);
7349 av_freep(&sc->keyframes);
7350 av_freep(&sc->stts_data);
7351 av_freep(&sc->sdtp_data);
7352 av_freep(&sc->stps_data);
7353 av_freep(&sc->elst_data);
7354 av_freep(&sc->rap_group);
7355 av_freep(&sc->display_matrix);
7356 av_freep(&sc->index_ranges);
7359 for (j = 0; j < sc->stsd_count; j++)
7360 av_free(sc->extradata[j]);
7361 av_freep(&sc->extradata);
7362 av_freep(&sc->extradata_size);
7364 mov_free_encryption_index(&sc->cenc.encryption_index);
7365 av_encryption_info_free(sc->cenc.default_encrypted_sample);
7366 av_aes_ctr_free(sc->cenc.aes_ctr);
7368 av_freep(&sc->stereo3d);
7369 av_freep(&sc->spherical);
7370 av_freep(&sc->mastering);
7371 av_freep(&sc->coll);
7374 if (mov->dv_demux) {
7375 avformat_free_context(mov->dv_fctx);
7376 mov->dv_fctx = NULL;
7379 if (mov->meta_keys) {
7380 for (i = 1; i < mov->meta_keys_count; i++) {
7381 av_freep(&mov->meta_keys[i]);
7383 av_freep(&mov->meta_keys);
7386 av_freep(&mov->trex_data);
7387 av_freep(&mov->bitrates);
7389 for (i = 0; i < mov->frag_index.nb_items; i++) {
7390 MOVFragmentStreamInfo *frag = mov->frag_index.item[i].stream_info;
7391 for (j = 0; j < mov->frag_index.item[i].nb_stream_info; j++) {
7392 mov_free_encryption_index(&frag[j].encryption_index);
7394 av_freep(&mov->frag_index.item[i].stream_info);
7396 av_freep(&mov->frag_index.item);
7398 av_freep(&mov->aes_decrypt);
7399 av_freep(&mov->chapter_tracks);
7404 static int tmcd_is_referenced(AVFormatContext *s, int tmcd_id)
7408 for (i = 0; i < s->nb_streams; i++) {
7409 AVStream *st = s->streams[i];
7410 MOVStreamContext *sc = st->priv_data;
7412 if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO &&
7413 sc->timecode_track == tmcd_id)
7419 /* look for a tmcd track not referenced by any video track, and export it globally */
7420 static void export_orphan_timecode(AVFormatContext *s)
7424 for (i = 0; i < s->nb_streams; i++) {
7425 AVStream *st = s->streams[i];
7427 if (st->codecpar->codec_tag == MKTAG('t','m','c','d') &&
7428 !tmcd_is_referenced(s, i + 1)) {
7429 AVDictionaryEntry *tcr = av_dict_get(st->metadata, "timecode", NULL, 0);
7431 av_dict_set(&s->metadata, "timecode", tcr->value, 0);
7438 static int read_tfra(MOVContext *mov, AVIOContext *f)
7440 int version, fieldlength, i, j;
7441 int64_t pos = avio_tell(f);
7442 uint32_t size = avio_rb32(f);
7443 unsigned track_id, item_count;
7445 if (avio_rb32(f) != MKBETAG('t', 'f', 'r', 'a')) {
7448 av_log(mov->fc, AV_LOG_VERBOSE, "found tfra\n");
7450 version = avio_r8(f);
7452 track_id = avio_rb32(f);
7453 fieldlength = avio_rb32(f);
7454 item_count = avio_rb32(f);
7455 for (i = 0; i < item_count; i++) {
7456 int64_t time, offset;
7458 MOVFragmentStreamInfo * frag_stream_info;
7461 return AVERROR_INVALIDDATA;
7465 time = avio_rb64(f);
7466 offset = avio_rb64(f);
7468 time = avio_rb32(f);
7469 offset = avio_rb32(f);
7472 // The first sample of each stream in a fragment is always a random
7473 // access sample. So it's entry in the tfra can be used as the
7474 // initial PTS of the fragment.
7475 index = update_frag_index(mov, offset);
7476 frag_stream_info = get_frag_stream_info(&mov->frag_index, index, track_id);
7477 if (frag_stream_info &&
7478 frag_stream_info->first_tfra_pts == AV_NOPTS_VALUE)
7479 frag_stream_info->first_tfra_pts = time;
7481 for (j = 0; j < ((fieldlength >> 4) & 3) + 1; j++)
7483 for (j = 0; j < ((fieldlength >> 2) & 3) + 1; j++)
7485 for (j = 0; j < ((fieldlength >> 0) & 3) + 1; j++)
7489 avio_seek(f, pos + size, SEEK_SET);
7493 static int mov_read_mfra(MOVContext *c, AVIOContext *f)
7495 int64_t stream_size = avio_size(f);
7496 int64_t original_pos = avio_tell(f);
7500 if ((seek_ret = avio_seek(f, stream_size - 4, SEEK_SET)) < 0) {
7504 mfra_size = avio_rb32(f);
7505 if (mfra_size < 0 || mfra_size > stream_size) {
7506 av_log(c->fc, AV_LOG_DEBUG, "doesn't look like mfra (unreasonable size)\n");
7509 if ((seek_ret = avio_seek(f, -mfra_size, SEEK_CUR)) < 0) {
7513 if (avio_rb32(f) != mfra_size) {
7514 av_log(c->fc, AV_LOG_DEBUG, "doesn't look like mfra (size mismatch)\n");
7517 if (avio_rb32(f) != MKBETAG('m', 'f', 'r', 'a')) {
7518 av_log(c->fc, AV_LOG_DEBUG, "doesn't look like mfra (tag mismatch)\n");
7521 av_log(c->fc, AV_LOG_VERBOSE, "stream has mfra\n");
7523 ret = read_tfra(c, f);
7529 seek_ret = avio_seek(f, original_pos, SEEK_SET);
7531 av_log(c->fc, AV_LOG_ERROR,
7532 "failed to seek back after looking for mfra\n");
7538 static int mov_read_header(AVFormatContext *s)
7540 MOVContext *mov = s->priv_data;
7541 AVIOContext *pb = s->pb;
7543 MOVAtom atom = { AV_RL32("root") };
7546 if (mov->decryption_key_len != 0 && mov->decryption_key_len != AES_CTR_KEY_SIZE) {
7547 av_log(s, AV_LOG_ERROR, "Invalid decryption key len %d expected %d\n",
7548 mov->decryption_key_len, AES_CTR_KEY_SIZE);
7549 return AVERROR(EINVAL);
7553 mov->trak_index = -1;
7554 /* .mov and .mp4 aren't streamable anyway (only progressive download if moov is before mdat) */
7555 if (pb->seekable & AVIO_SEEKABLE_NORMAL)
7556 atom.size = avio_size(pb);
7558 atom.size = INT64_MAX;
7560 /* check MOV header */
7562 if (mov->moov_retry)
7563 avio_seek(pb, 0, SEEK_SET);
7564 if ((err = mov_read_default(mov, pb, atom)) < 0) {
7565 av_log(s, AV_LOG_ERROR, "error reading header\n");
7568 } while ((pb->seekable & AVIO_SEEKABLE_NORMAL) && !mov->found_moov && !mov->moov_retry++);
7569 if (!mov->found_moov) {
7570 av_log(s, AV_LOG_ERROR, "moov atom not found\n");
7571 err = AVERROR_INVALIDDATA;
7574 av_log(mov->fc, AV_LOG_TRACE, "on_parse_exit_offset=%"PRId64"\n", avio_tell(pb));
7576 if (pb->seekable & AVIO_SEEKABLE_NORMAL) {
7577 if (mov->nb_chapter_tracks > 0 && !mov->ignore_chapters)
7578 mov_read_chapters(s);
7579 for (i = 0; i < s->nb_streams; i++)
7580 if (s->streams[i]->codecpar->codec_tag == AV_RL32("tmcd")) {
7581 mov_read_timecode_track(s, s->streams[i]);
7582 } else if (s->streams[i]->codecpar->codec_tag == AV_RL32("rtmd")) {
7583 mov_read_rtmd_track(s, s->streams[i]);
7587 /* copy timecode metadata from tmcd tracks to the related video streams */
7588 for (i = 0; i < s->nb_streams; i++) {
7589 AVStream *st = s->streams[i];
7590 MOVStreamContext *sc = st->priv_data;
7591 if (sc->timecode_track > 0) {
7592 AVDictionaryEntry *tcr;
7593 int tmcd_st_id = -1;
7595 for (j = 0; j < s->nb_streams; j++)
7596 if (s->streams[j]->id == sc->timecode_track)
7599 if (tmcd_st_id < 0 || tmcd_st_id == i)
7601 tcr = av_dict_get(s->streams[tmcd_st_id]->metadata, "timecode", NULL, 0);
7603 av_dict_set(&st->metadata, "timecode", tcr->value, 0);
7606 export_orphan_timecode(s);
7608 for (i = 0; i < s->nb_streams; i++) {
7609 AVStream *st = s->streams[i];
7610 MOVStreamContext *sc = st->priv_data;
7611 fix_timescale(mov, sc);
7612 if(st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO && st->codecpar->codec_id == AV_CODEC_ID_AAC) {
7613 st->skip_samples = sc->start_pad;
7615 if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && sc->nb_frames_for_fps > 0 && sc->duration_for_fps > 0)
7616 av_reduce(&st->avg_frame_rate.num, &st->avg_frame_rate.den,
7617 sc->time_scale*(int64_t)sc->nb_frames_for_fps, sc->duration_for_fps, INT_MAX);
7618 if (st->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE) {
7619 if (st->codecpar->width <= 0 || st->codecpar->height <= 0) {
7620 st->codecpar->width = sc->width;
7621 st->codecpar->height = sc->height;
7623 if (st->codecpar->codec_id == AV_CODEC_ID_DVD_SUBTITLE) {
7624 if ((err = mov_rewrite_dvd_sub_extradata(st)) < 0)
7628 if (mov->handbrake_version &&
7629 mov->handbrake_version <= 1000000*0 + 1000*10 + 2 && // 0.10.2
7630 st->codecpar->codec_id == AV_CODEC_ID_MP3
7632 av_log(s, AV_LOG_VERBOSE, "Forcing full parsing for mp3 stream\n");
7633 st->need_parsing = AVSTREAM_PARSE_FULL;
7637 if (mov->trex_data) {
7638 for (i = 0; i < s->nb_streams; i++) {
7639 AVStream *st = s->streams[i];
7640 MOVStreamContext *sc = st->priv_data;
7641 if (st->duration > 0) {
7642 if (sc->data_size > INT64_MAX / sc->time_scale / 8) {
7643 av_log(s, AV_LOG_ERROR, "Overflow during bit rate calculation %"PRId64" * 8 * %d\n",
7644 sc->data_size, sc->time_scale);
7645 err = AVERROR_INVALIDDATA;
7648 st->codecpar->bit_rate = sc->data_size * 8 * sc->time_scale / st->duration;
7653 if (mov->use_mfra_for > 0) {
7654 for (i = 0; i < s->nb_streams; i++) {
7655 AVStream *st = s->streams[i];
7656 MOVStreamContext *sc = st->priv_data;
7657 if (sc->duration_for_fps > 0) {
7658 if (sc->data_size > INT64_MAX / sc->time_scale / 8) {
7659 av_log(s, AV_LOG_ERROR, "Overflow during bit rate calculation %"PRId64" * 8 * %d\n",
7660 sc->data_size, sc->time_scale);
7661 err = AVERROR_INVALIDDATA;
7664 st->codecpar->bit_rate = sc->data_size * 8 * sc->time_scale /
7665 sc->duration_for_fps;
7670 for (i = 0; i < mov->bitrates_count && i < s->nb_streams; i++) {
7671 if (mov->bitrates[i]) {
7672 s->streams[i]->codecpar->bit_rate = mov->bitrates[i];
7676 ff_rfps_calculate(s);
7678 for (i = 0; i < s->nb_streams; i++) {
7679 AVStream *st = s->streams[i];
7680 MOVStreamContext *sc = st->priv_data;
7682 switch (st->codecpar->codec_type) {
7683 case AVMEDIA_TYPE_AUDIO:
7684 err = ff_replaygain_export(st, s->metadata);
7689 case AVMEDIA_TYPE_VIDEO:
7690 if (sc->display_matrix) {
7691 err = av_stream_add_side_data(st, AV_PKT_DATA_DISPLAYMATRIX, (uint8_t*)sc->display_matrix,
7692 sizeof(int32_t) * 9);
7696 sc->display_matrix = NULL;
7699 err = av_stream_add_side_data(st, AV_PKT_DATA_STEREO3D,
7700 (uint8_t *)sc->stereo3d,
7701 sizeof(*sc->stereo3d));
7705 sc->stereo3d = NULL;
7707 if (sc->spherical) {
7708 err = av_stream_add_side_data(st, AV_PKT_DATA_SPHERICAL,
7709 (uint8_t *)sc->spherical,
7710 sc->spherical_size);
7714 sc->spherical = NULL;
7716 if (sc->mastering) {
7717 err = av_stream_add_side_data(st, AV_PKT_DATA_MASTERING_DISPLAY_METADATA,
7718 (uint8_t *)sc->mastering,
7719 sizeof(*sc->mastering));
7723 sc->mastering = NULL;
7726 err = av_stream_add_side_data(st, AV_PKT_DATA_CONTENT_LIGHT_LEVEL,
7727 (uint8_t *)sc->coll,
7737 ff_configure_buffers_for_index(s, AV_TIME_BASE);
7739 for (i = 0; i < mov->frag_index.nb_items; i++)
7740 if (mov->frag_index.item[i].moof_offset <= mov->fragment.moof_offset)
7741 mov->frag_index.item[i].headers_read = 1;
7749 static AVIndexEntry *mov_find_next_sample(AVFormatContext *s, AVStream **st)
7751 AVIndexEntry *sample = NULL;
7752 int64_t best_dts = INT64_MAX;
7754 for (i = 0; i < s->nb_streams; i++) {
7755 AVStream *avst = s->streams[i];
7756 MOVStreamContext *msc = avst->priv_data;
7757 if (msc->pb && msc->current_sample < avst->nb_index_entries) {
7758 AVIndexEntry *current_sample = &avst->index_entries[msc->current_sample];
7759 int64_t dts = av_rescale(current_sample->timestamp, AV_TIME_BASE, msc->time_scale);
7760 av_log(s, AV_LOG_TRACE, "stream %d, sample %d, dts %"PRId64"\n", i, msc->current_sample, dts);
7761 if (!sample || (!(s->pb->seekable & AVIO_SEEKABLE_NORMAL) && current_sample->pos < sample->pos) ||
7762 ((s->pb->seekable & AVIO_SEEKABLE_NORMAL) &&
7763 ((msc->pb != s->pb && dts < best_dts) || (msc->pb == s->pb && dts != AV_NOPTS_VALUE &&
7764 ((FFABS(best_dts - dts) <= AV_TIME_BASE && current_sample->pos < sample->pos) ||
7765 (FFABS(best_dts - dts) > AV_TIME_BASE && dts < best_dts)))))) {
7766 sample = current_sample;
7775 static int should_retry(AVIOContext *pb, int error_code) {
7776 if (error_code == AVERROR_EOF || avio_feof(pb))
7782 static int mov_switch_root(AVFormatContext *s, int64_t target, int index)
7785 MOVContext *mov = s->priv_data;
7787 if (index >= 0 && index < mov->frag_index.nb_items)
7788 target = mov->frag_index.item[index].moof_offset;
7789 if (avio_seek(s->pb, target, SEEK_SET) != target) {
7790 av_log(mov->fc, AV_LOG_ERROR, "root atom offset 0x%"PRIx64": partial file\n", target);
7791 return AVERROR_INVALIDDATA;
7794 mov->next_root_atom = 0;
7795 if (index < 0 || index >= mov->frag_index.nb_items)
7796 index = search_frag_moof_offset(&mov->frag_index, target);
7797 if (index < mov->frag_index.nb_items &&
7798 mov->frag_index.item[index].moof_offset == target) {
7799 if (index + 1 < mov->frag_index.nb_items)
7800 mov->next_root_atom = mov->frag_index.item[index + 1].moof_offset;
7801 if (mov->frag_index.item[index].headers_read)
7803 mov->frag_index.item[index].headers_read = 1;
7806 mov->found_mdat = 0;
7808 ret = mov_read_default(mov, s->pb, (MOVAtom){ AV_RL32("root"), INT64_MAX });
7811 if (avio_feof(s->pb))
7813 av_log(s, AV_LOG_TRACE, "read fragments, offset 0x%"PRIx64"\n", avio_tell(s->pb));
7818 static int mov_change_extradata(MOVStreamContext *sc, AVPacket *pkt)
7820 uint8_t *side, *extradata;
7823 /* Save the current index. */
7824 sc->last_stsd_index = sc->stsc_data[sc->stsc_index].id - 1;
7826 /* Notify the decoder that extradata changed. */
7827 extradata_size = sc->extradata_size[sc->last_stsd_index];
7828 extradata = sc->extradata[sc->last_stsd_index];
7829 if (extradata_size > 0 && extradata) {
7830 side = av_packet_new_side_data(pkt,
7831 AV_PKT_DATA_NEW_EXTRADATA,
7834 return AVERROR(ENOMEM);
7835 memcpy(side, extradata, extradata_size);
7841 static int get_eia608_packet(AVIOContext *pb, AVPacket *pkt, int size)
7846 return AVERROR_INVALIDDATA;
7847 new_size = ((size - 8) / 2) * 3;
7848 ret = av_new_packet(pkt, new_size);
7853 for (int j = 0; j < new_size; j += 3) {
7854 pkt->data[j] = 0xFC;
7855 pkt->data[j+1] = avio_r8(pb);
7856 pkt->data[j+2] = avio_r8(pb);
7862 static int mov_read_packet(AVFormatContext *s, AVPacket *pkt)
7864 MOVContext *mov = s->priv_data;
7865 MOVStreamContext *sc;
7866 AVIndexEntry *sample;
7867 AVStream *st = NULL;
7868 int64_t current_index;
7872 sample = mov_find_next_sample(s, &st);
7873 if (!sample || (mov->next_root_atom && sample->pos > mov->next_root_atom)) {
7874 if (!mov->next_root_atom)
7876 if ((ret = mov_switch_root(s, mov->next_root_atom, -1)) < 0)
7881 /* must be done just before reading, to avoid infinite loop on sample */
7882 current_index = sc->current_index;
7883 mov_current_sample_inc(sc);
7885 if (mov->next_root_atom) {
7886 sample->pos = FFMIN(sample->pos, mov->next_root_atom);
7887 sample->size = FFMIN(sample->size, (mov->next_root_atom - sample->pos));
7890 if (st->discard != AVDISCARD_ALL) {
7891 int64_t ret64 = avio_seek(sc->pb, sample->pos, SEEK_SET);
7892 if (ret64 != sample->pos) {
7893 av_log(mov->fc, AV_LOG_ERROR, "stream %d, offset 0x%"PRIx64": partial file\n",
7894 sc->ffindex, sample->pos);
7895 if (should_retry(sc->pb, ret64)) {
7896 mov_current_sample_dec(sc);
7898 return AVERROR_INVALIDDATA;
7901 if( st->discard == AVDISCARD_NONKEY && 0==(sample->flags & AVINDEX_KEYFRAME) ) {
7902 av_log(mov->fc, AV_LOG_DEBUG, "Nonkey frame from stream %d discarded due to AVDISCARD_NONKEY\n", sc->ffindex);
7906 if (st->codecpar->codec_id == AV_CODEC_ID_EIA_608 && sample->size > 8)
7907 ret = get_eia608_packet(sc->pb, pkt, sample->size);
7909 ret = av_get_packet(sc->pb, pkt, sample->size);
7911 if (should_retry(sc->pb, ret)) {
7912 mov_current_sample_dec(sc);
7916 if (sc->has_palette) {
7919 pal = av_packet_new_side_data(pkt, AV_PKT_DATA_PALETTE, AVPALETTE_SIZE);
7921 av_log(mov->fc, AV_LOG_ERROR, "Cannot append palette to packet\n");
7923 memcpy(pal, sc->palette, AVPALETTE_SIZE);
7924 sc->has_palette = 0;
7927 #if CONFIG_DV_DEMUXER
7928 if (mov->dv_demux && sc->dv_audio_container) {
7929 avpriv_dv_produce_packet(mov->dv_demux, pkt, pkt->data, pkt->size, pkt->pos);
7930 av_freep(&pkt->data);
7932 ret = avpriv_dv_get_packet(mov->dv_demux, pkt);
7937 if (st->codecpar->codec_id == AV_CODEC_ID_MP3 && !st->need_parsing && pkt->size > 4) {
7938 if (ff_mpa_check_header(AV_RB32(pkt->data)) < 0)
7939 st->need_parsing = AVSTREAM_PARSE_FULL;
7943 pkt->stream_index = sc->ffindex;
7944 pkt->dts = sample->timestamp;
7945 if (sample->flags & AVINDEX_DISCARD_FRAME) {
7946 pkt->flags |= AV_PKT_FLAG_DISCARD;
7948 if (sc->ctts_data && sc->ctts_index < sc->ctts_count) {
7949 pkt->pts = pkt->dts + sc->dts_shift + sc->ctts_data[sc->ctts_index].duration;
7950 /* update ctts context */
7952 if (sc->ctts_index < sc->ctts_count &&
7953 sc->ctts_data[sc->ctts_index].count == sc->ctts_sample) {
7955 sc->ctts_sample = 0;
7958 int64_t next_dts = (sc->current_sample < st->nb_index_entries) ?
7959 st->index_entries[sc->current_sample].timestamp : st->duration;
7961 if (next_dts >= pkt->dts)
7962 pkt->duration = next_dts - pkt->dts;
7963 pkt->pts = pkt->dts;
7965 if (st->discard == AVDISCARD_ALL)
7967 if (sc->sdtp_data && sc->current_sample <= sc->sdtp_count) {
7968 uint8_t sample_flags = sc->sdtp_data[sc->current_sample - 1];
7969 uint8_t sample_is_depended_on = (sample_flags >> 2) & 0x3;
7970 pkt->flags |= sample_is_depended_on == MOV_SAMPLE_DEPENDENCY_NO ? AV_PKT_FLAG_DISPOSABLE : 0;
7972 pkt->flags |= sample->flags & AVINDEX_KEYFRAME ? AV_PKT_FLAG_KEY : 0;
7973 pkt->pos = sample->pos;
7975 /* Multiple stsd handling. */
7976 if (sc->stsc_data) {
7977 /* Keep track of the stsc index for the given sample, then check
7978 * if the stsd index is different from the last used one. */
7980 if (mov_stsc_index_valid(sc->stsc_index, sc->stsc_count) &&
7981 mov_get_stsc_samples(sc, sc->stsc_index) == sc->stsc_sample) {
7983 sc->stsc_sample = 0;
7984 /* Do not check indexes after a switch. */
7985 } else if (sc->stsc_data[sc->stsc_index].id > 0 &&
7986 sc->stsc_data[sc->stsc_index].id - 1 < sc->stsd_count &&
7987 sc->stsc_data[sc->stsc_index].id - 1 != sc->last_stsd_index) {
7988 ret = mov_change_extradata(sc, pkt);
7995 aax_filter(pkt->data, pkt->size, mov);
7997 ret = cenc_filter(mov, st, sc, pkt, current_index);
8005 static int mov_seek_fragment(AVFormatContext *s, AVStream *st, int64_t timestamp)
8007 MOVContext *mov = s->priv_data;
8010 if (!mov->frag_index.complete)
8013 index = search_frag_timestamp(&mov->frag_index, st, timestamp);
8016 if (!mov->frag_index.item[index].headers_read)
8017 return mov_switch_root(s, -1, index);
8018 if (index + 1 < mov->frag_index.nb_items)
8019 mov->next_root_atom = mov->frag_index.item[index + 1].moof_offset;
8024 static int mov_seek_stream(AVFormatContext *s, AVStream *st, int64_t timestamp, int flags)
8026 MOVStreamContext *sc = st->priv_data;
8027 int sample, time_sample, ret;
8030 // Here we consider timestamp to be PTS, hence try to offset it so that we
8031 // can search over the DTS timeline.
8032 timestamp -= (sc->min_corrected_pts + sc->dts_shift);
8034 ret = mov_seek_fragment(s, st, timestamp);
8038 sample = av_index_search_timestamp(st, timestamp, flags);
8039 av_log(s, AV_LOG_TRACE, "stream %d, timestamp %"PRId64", sample %d\n", st->index, timestamp, sample);
8040 if (sample < 0 && st->nb_index_entries && timestamp < st->index_entries[0].timestamp)
8042 if (sample < 0) /* not sure what to do */
8043 return AVERROR_INVALIDDATA;
8044 mov_current_sample_set(sc, sample);
8045 av_log(s, AV_LOG_TRACE, "stream %d, found sample %d\n", st->index, sc->current_sample);
8046 /* adjust ctts index */
8047 if (sc->ctts_data) {
8049 for (i = 0; i < sc->ctts_count; i++) {
8050 int next = time_sample + sc->ctts_data[i].count;
8051 if (next > sc->current_sample) {
8053 sc->ctts_sample = sc->current_sample - time_sample;
8060 /* adjust stsd index */
8061 if (sc->chunk_count) {
8063 for (i = 0; i < sc->stsc_count; i++) {
8064 int64_t next = time_sample + mov_get_stsc_samples(sc, i);
8065 if (next > sc->current_sample) {
8067 sc->stsc_sample = sc->current_sample - time_sample;
8070 av_assert0(next == (int)next);
8078 static int mov_read_seek(AVFormatContext *s, int stream_index, int64_t sample_time, int flags)
8080 MOVContext *mc = s->priv_data;
8085 if (stream_index >= s->nb_streams)
8086 return AVERROR_INVALIDDATA;
8088 st = s->streams[stream_index];
8089 sample = mov_seek_stream(s, st, sample_time, flags);
8093 if (mc->seek_individually) {
8094 /* adjust seek timestamp to found sample timestamp */
8095 int64_t seek_timestamp = st->index_entries[sample].timestamp;
8097 for (i = 0; i < s->nb_streams; i++) {
8099 MOVStreamContext *sc = s->streams[i]->priv_data;
8101 st->skip_samples = (sample_time <= 0) ? sc->start_pad : 0;
8103 if (stream_index == i)
8106 timestamp = av_rescale_q(seek_timestamp, s->streams[stream_index]->time_base, st->time_base);
8107 mov_seek_stream(s, st, timestamp, flags);
8110 for (i = 0; i < s->nb_streams; i++) {
8111 MOVStreamContext *sc;
8114 mov_current_sample_set(sc, 0);
8117 MOVStreamContext *sc;
8118 AVIndexEntry *entry = mov_find_next_sample(s, &st);
8120 return AVERROR_INVALIDDATA;
8122 if (sc->ffindex == stream_index && sc->current_sample == sample)
8124 mov_current_sample_inc(sc);
8130 #define OFFSET(x) offsetof(MOVContext, x)
8131 #define FLAGS AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_DECODING_PARAM
8132 static const AVOption mov_options[] = {
8133 {"use_absolute_path",
8134 "allow using absolute path when opening alias, this is a possible security issue",
8135 OFFSET(use_absolute_path), AV_OPT_TYPE_BOOL, {.i64 = 0},
8137 {"seek_streams_individually",
8138 "Seek each stream individually to the closest point",
8139 OFFSET(seek_individually), AV_OPT_TYPE_BOOL, { .i64 = 1 },
8141 {"ignore_editlist", "Ignore the edit list atom.", OFFSET(ignore_editlist), AV_OPT_TYPE_BOOL, {.i64 = 0},
8143 {"advanced_editlist",
8144 "Modify the AVIndex according to the editlists. Use this option to decode in the order specified by the edits.",
8145 OFFSET(advanced_editlist), AV_OPT_TYPE_BOOL, {.i64 = 1},
8147 {"ignore_chapters", "", OFFSET(ignore_chapters), AV_OPT_TYPE_BOOL, {.i64 = 0},
8150 "use mfra for fragment timestamps",
8151 OFFSET(use_mfra_for), AV_OPT_TYPE_INT, {.i64 = FF_MOV_FLAG_MFRA_AUTO},
8152 -1, FF_MOV_FLAG_MFRA_PTS, FLAGS,
8154 {"auto", "auto", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_MFRA_AUTO}, 0, 0,
8155 FLAGS, "use_mfra_for" },
8156 {"dts", "dts", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_MFRA_DTS}, 0, 0,
8157 FLAGS, "use_mfra_for" },
8158 {"pts", "pts", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_MFRA_PTS}, 0, 0,
8159 FLAGS, "use_mfra_for" },
8160 { "export_all", "Export unrecognized metadata entries", OFFSET(export_all),
8161 AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, .flags = FLAGS },
8162 { "export_xmp", "Export full XMP metadata", OFFSET(export_xmp),
8163 AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, .flags = FLAGS },
8164 { "activation_bytes", "Secret bytes for Audible AAX files", OFFSET(activation_bytes),
8165 AV_OPT_TYPE_BINARY, .flags = AV_OPT_FLAG_DECODING_PARAM },
8166 { "audible_fixed_key", // extracted from libAAX_SDK.so and AAXSDKWin.dll files!
8167 "Fixed key used for handling Audible AAX files", OFFSET(audible_fixed_key),
8168 AV_OPT_TYPE_BINARY, {.str="77214d4b196a87cd520045fd20a51d67"},
8169 .flags = AV_OPT_FLAG_DECODING_PARAM },
8170 { "decryption_key", "The media decryption key (hex)", OFFSET(decryption_key), AV_OPT_TYPE_BINARY, .flags = AV_OPT_FLAG_DECODING_PARAM },
8171 { "enable_drefs", "Enable external track support.", OFFSET(enable_drefs), AV_OPT_TYPE_BOOL,
8172 {.i64 = 0}, 0, 1, FLAGS },
8177 static const AVClass mov_class = {
8178 .class_name = "mov,mp4,m4a,3gp,3g2,mj2",
8179 .item_name = av_default_item_name,
8180 .option = mov_options,
8181 .version = LIBAVUTIL_VERSION_INT,
8184 AVInputFormat ff_mov_demuxer = {
8185 .name = "mov,mp4,m4a,3gp,3g2,mj2",
8186 .long_name = NULL_IF_CONFIG_SMALL("QuickTime / MOV"),
8187 .priv_class = &mov_class,
8188 .priv_data_size = sizeof(MOVContext),
8189 .extensions = "mov,mp4,m4a,3gp,3g2,mj2,psp,m4b,ism,ismv,isma,f4v",
8190 .read_probe = mov_probe,
8191 .read_header = mov_read_header,
8192 .read_packet = mov_read_packet,
8193 .read_close = mov_read_close,
8194 .read_seek = mov_read_seek,
8195 .flags = AVFMT_NO_BYTE_SEEK | AVFMT_SEEK_TO_PTS,