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)
861 uint8_t buf[DDTS_SIZE + AV_INPUT_BUFFER_PADDING_SIZE];
863 uint32_t frame_duration_code = 0;
864 uint32_t channel_layout_code = 0;
868 if ((ret = ffio_read_size(pb, buf, DDTS_SIZE)) < 0)
871 init_get_bits(&gb, buf, 8 * DDTS_SIZE);
873 if (c->fc->nb_streams < 1) {
876 st = c->fc->streams[c->fc->nb_streams-1];
878 st->codecpar->sample_rate = get_bits_long(&gb, 32);
879 if (st->codecpar->sample_rate <= 0) {
880 av_log(c->fc, AV_LOG_ERROR, "Invalid sample rate %d\n", st->codecpar->sample_rate);
881 return AVERROR_INVALIDDATA;
883 skip_bits_long(&gb, 32); /* max bitrate */
884 st->codecpar->bit_rate = get_bits_long(&gb, 32);
885 st->codecpar->bits_per_coded_sample = get_bits(&gb, 8);
886 frame_duration_code = get_bits(&gb, 2);
887 skip_bits(&gb, 30); /* various fields */
888 channel_layout_code = get_bits(&gb, 16);
890 st->codecpar->frame_size =
891 (frame_duration_code == 0) ? 512 :
892 (frame_duration_code == 1) ? 1024 :
893 (frame_duration_code == 2) ? 2048 :
894 (frame_duration_code == 3) ? 4096 : 0;
896 if (channel_layout_code > 0xff) {
897 av_log(c->fc, AV_LOG_WARNING, "Unsupported DTS audio channel layout");
899 st->codecpar->channel_layout =
900 ((channel_layout_code & 0x1) ? AV_CH_FRONT_CENTER : 0) |
901 ((channel_layout_code & 0x2) ? AV_CH_FRONT_LEFT : 0) |
902 ((channel_layout_code & 0x2) ? AV_CH_FRONT_RIGHT : 0) |
903 ((channel_layout_code & 0x4) ? AV_CH_SIDE_LEFT : 0) |
904 ((channel_layout_code & 0x4) ? AV_CH_SIDE_RIGHT : 0) |
905 ((channel_layout_code & 0x8) ? AV_CH_LOW_FREQUENCY : 0);
907 st->codecpar->channels = av_get_channel_layout_nb_channels(st->codecpar->channel_layout);
912 static int mov_read_chan(MOVContext *c, AVIOContext *pb, MOVAtom atom)
916 if (c->fc->nb_streams < 1)
918 st = c->fc->streams[c->fc->nb_streams-1];
923 /* skip version and flags */
926 ff_mov_read_chan(c->fc, pb, st, atom.size - 4);
931 static int mov_read_wfex(MOVContext *c, AVIOContext *pb, MOVAtom atom)
936 if (c->fc->nb_streams < 1)
938 st = c->fc->streams[c->fc->nb_streams-1];
940 if ((ret = ff_get_wav_header(c->fc, pb, st->codecpar, atom.size, 0)) < 0)
941 av_log(c->fc, AV_LOG_WARNING, "get_wav_header failed\n");
946 static int mov_read_pasp(MOVContext *c, AVIOContext *pb, MOVAtom atom)
948 const int num = avio_rb32(pb);
949 const int den = avio_rb32(pb);
952 if (c->fc->nb_streams < 1)
954 st = c->fc->streams[c->fc->nb_streams-1];
956 if ((st->sample_aspect_ratio.den != 1 || st->sample_aspect_ratio.num) && // default
957 (den != st->sample_aspect_ratio.den || num != st->sample_aspect_ratio.num)) {
958 av_log(c->fc, AV_LOG_WARNING,
959 "sample aspect ratio already set to %d:%d, ignoring 'pasp' atom (%d:%d)\n",
960 st->sample_aspect_ratio.num, st->sample_aspect_ratio.den,
962 } else if (den != 0) {
963 av_reduce(&st->sample_aspect_ratio.num, &st->sample_aspect_ratio.den,
969 /* this atom contains actual media data */
970 static int mov_read_mdat(MOVContext *c, AVIOContext *pb, MOVAtom atom)
972 if (atom.size == 0) /* wrong one (MP4) */
975 return 0; /* now go for moov */
978 #define DRM_BLOB_SIZE 56
980 static int mov_read_adrm(MOVContext *c, AVIOContext *pb, MOVAtom atom)
982 uint8_t intermediate_key[20];
983 uint8_t intermediate_iv[20];
986 uint8_t file_checksum[20];
987 uint8_t calculated_checksum[20];
991 uint8_t *activation_bytes = c->activation_bytes;
992 uint8_t *fixed_key = c->audible_fixed_key;
996 sha = av_sha_alloc();
998 return AVERROR(ENOMEM);
999 av_free(c->aes_decrypt);
1000 c->aes_decrypt = av_aes_alloc();
1001 if (!c->aes_decrypt) {
1002 ret = AVERROR(ENOMEM);
1006 /* drm blob processing */
1007 avio_read(pb, output, 8); // go to offset 8, absolute position 0x251
1008 avio_read(pb, input, DRM_BLOB_SIZE);
1009 avio_read(pb, output, 4); // go to offset 4, absolute position 0x28d
1010 avio_read(pb, file_checksum, 20);
1012 av_log(c->fc, AV_LOG_INFO, "[aax] file checksum == "); // required by external tools
1013 for (i = 0; i < 20; i++)
1014 av_log(c->fc, AV_LOG_INFO, "%02x", file_checksum[i]);
1015 av_log(c->fc, AV_LOG_INFO, "\n");
1017 /* verify activation data */
1018 if (!activation_bytes) {
1019 av_log(c->fc, AV_LOG_WARNING, "[aax] activation_bytes option is missing!\n");
1020 ret = 0; /* allow ffprobe to continue working on .aax files */
1023 if (c->activation_bytes_size != 4) {
1024 av_log(c->fc, AV_LOG_FATAL, "[aax] activation_bytes value needs to be 4 bytes!\n");
1025 ret = AVERROR(EINVAL);
1029 /* verify fixed key */
1030 if (c->audible_fixed_key_size != 16) {
1031 av_log(c->fc, AV_LOG_FATAL, "[aax] audible_fixed_key value needs to be 16 bytes!\n");
1032 ret = AVERROR(EINVAL);
1036 /* AAX (and AAX+) key derivation */
1037 av_sha_init(sha, 160);
1038 av_sha_update(sha, fixed_key, 16);
1039 av_sha_update(sha, activation_bytes, 4);
1040 av_sha_final(sha, intermediate_key);
1041 av_sha_init(sha, 160);
1042 av_sha_update(sha, fixed_key, 16);
1043 av_sha_update(sha, intermediate_key, 20);
1044 av_sha_update(sha, activation_bytes, 4);
1045 av_sha_final(sha, intermediate_iv);
1046 av_sha_init(sha, 160);
1047 av_sha_update(sha, intermediate_key, 16);
1048 av_sha_update(sha, intermediate_iv, 16);
1049 av_sha_final(sha, calculated_checksum);
1050 if (memcmp(calculated_checksum, file_checksum, 20)) { // critical error
1051 av_log(c->fc, AV_LOG_ERROR, "[aax] mismatch in checksums!\n");
1052 ret = AVERROR_INVALIDDATA;
1055 av_aes_init(c->aes_decrypt, intermediate_key, 128, 1);
1056 av_aes_crypt(c->aes_decrypt, output, input, DRM_BLOB_SIZE >> 4, intermediate_iv, 1);
1057 for (i = 0; i < 4; i++) {
1058 // file data (in output) is stored in big-endian mode
1059 if (activation_bytes[i] != output[3 - i]) { // critical error
1060 av_log(c->fc, AV_LOG_ERROR, "[aax] error in drm blob decryption!\n");
1061 ret = AVERROR_INVALIDDATA;
1065 memcpy(c->file_key, output + 8, 16);
1066 memcpy(input, output + 26, 16);
1067 av_sha_init(sha, 160);
1068 av_sha_update(sha, input, 16);
1069 av_sha_update(sha, c->file_key, 16);
1070 av_sha_update(sha, fixed_key, 16);
1071 av_sha_final(sha, c->file_iv);
1079 // Audible AAX (and AAX+) bytestream decryption
1080 static int aax_filter(uint8_t *input, int size, MOVContext *c)
1083 unsigned char iv[16];
1085 memcpy(iv, c->file_iv, 16); // iv is overwritten
1086 blocks = size >> 4; // trailing bytes are not encrypted!
1087 av_aes_init(c->aes_decrypt, c->file_key, 128, 1);
1088 av_aes_crypt(c->aes_decrypt, input, input, blocks, iv, 1);
1093 /* read major brand, minor version and compatible brands and store them as metadata */
1094 static int mov_read_ftyp(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1097 int comp_brand_size;
1098 char* comp_brands_str;
1099 uint8_t type[5] = {0};
1100 int ret = ffio_read_size(pb, type, 4);
1104 if (strcmp(type, "qt "))
1106 av_log(c->fc, AV_LOG_DEBUG, "ISO: File Type Major Brand: %.4s\n",(char *)&type);
1107 av_dict_set(&c->fc->metadata, "major_brand", type, 0);
1108 minor_ver = avio_rb32(pb); /* minor version */
1109 av_dict_set_int(&c->fc->metadata, "minor_version", minor_ver, 0);
1111 comp_brand_size = atom.size - 8;
1112 if (comp_brand_size < 0)
1113 return AVERROR_INVALIDDATA;
1114 comp_brands_str = av_malloc(comp_brand_size + 1); /* Add null terminator */
1115 if (!comp_brands_str)
1116 return AVERROR(ENOMEM);
1118 ret = ffio_read_size(pb, comp_brands_str, comp_brand_size);
1120 av_freep(&comp_brands_str);
1123 comp_brands_str[comp_brand_size] = 0;
1124 av_dict_set(&c->fc->metadata, "compatible_brands",
1125 comp_brands_str, AV_DICT_DONT_STRDUP_VAL);
1130 /* this atom should contain all header atoms */
1131 static int mov_read_moov(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1135 if (c->found_moov) {
1136 av_log(c->fc, AV_LOG_WARNING, "Found duplicated MOOV Atom. Skipped it\n");
1137 avio_skip(pb, atom.size);
1141 if ((ret = mov_read_default(c, pb, atom)) < 0)
1143 /* we parsed the 'moov' atom, we can terminate the parsing as soon as we find the 'mdat' */
1144 /* so we don't parse the whole file if over a network */
1146 return 0; /* now go for mdat */
1149 static MOVFragmentStreamInfo * get_frag_stream_info(
1150 MOVFragmentIndex *frag_index,
1155 MOVFragmentIndexItem * item;
1157 if (index < 0 || index >= frag_index->nb_items)
1159 item = &frag_index->item[index];
1160 for (i = 0; i < item->nb_stream_info; i++)
1161 if (item->stream_info[i].id == id)
1162 return &item->stream_info[i];
1164 // This shouldn't happen
1168 static void set_frag_stream(MOVFragmentIndex *frag_index, int id)
1171 MOVFragmentIndexItem * item;
1173 if (frag_index->current < 0 ||
1174 frag_index->current >= frag_index->nb_items)
1177 item = &frag_index->item[frag_index->current];
1178 for (i = 0; i < item->nb_stream_info; i++)
1179 if (item->stream_info[i].id == id) {
1184 // id not found. This shouldn't happen.
1188 static MOVFragmentStreamInfo * get_current_frag_stream_info(
1189 MOVFragmentIndex *frag_index)
1191 MOVFragmentIndexItem *item;
1192 if (frag_index->current < 0 ||
1193 frag_index->current >= frag_index->nb_items)
1196 item = &frag_index->item[frag_index->current];
1197 if (item->current >= 0 && item->current < item->nb_stream_info)
1198 return &item->stream_info[item->current];
1200 // This shouldn't happen
1204 static int search_frag_moof_offset(MOVFragmentIndex *frag_index, int64_t offset)
1207 int64_t moof_offset;
1209 // Optimize for appending new entries
1210 if (!frag_index->nb_items ||
1211 frag_index->item[frag_index->nb_items - 1].moof_offset < offset)
1212 return frag_index->nb_items;
1215 b = frag_index->nb_items;
1219 moof_offset = frag_index->item[m].moof_offset;
1220 if (moof_offset >= offset)
1222 if (moof_offset <= offset)
1228 static int64_t get_stream_info_time(MOVFragmentStreamInfo * frag_stream_info)
1230 av_assert0(frag_stream_info);
1231 if (frag_stream_info->sidx_pts != AV_NOPTS_VALUE)
1232 return frag_stream_info->sidx_pts;
1233 if (frag_stream_info->first_tfra_pts != AV_NOPTS_VALUE)
1234 return frag_stream_info->first_tfra_pts;
1235 return frag_stream_info->tfdt_dts;
1238 static int64_t get_frag_time(MOVFragmentIndex *frag_index,
1239 int index, int track_id)
1241 MOVFragmentStreamInfo * frag_stream_info;
1245 if (track_id >= 0) {
1246 frag_stream_info = get_frag_stream_info(frag_index, index, track_id);
1247 return frag_stream_info->sidx_pts;
1250 for (i = 0; i < frag_index->item[index].nb_stream_info; i++) {
1251 frag_stream_info = &frag_index->item[index].stream_info[i];
1252 timestamp = get_stream_info_time(frag_stream_info);
1253 if (timestamp != AV_NOPTS_VALUE)
1256 return AV_NOPTS_VALUE;
1259 static int search_frag_timestamp(MOVFragmentIndex *frag_index,
1260 AVStream *st, int64_t timestamp)
1267 // If the stream is referenced by any sidx, limit the search
1268 // to fragments that referenced this stream in the sidx
1269 MOVStreamContext *sc = st->priv_data;
1275 b = frag_index->nb_items;
1278 m0 = m = (a + b) >> 1;
1281 (frag_time = get_frag_time(frag_index, m, id)) == AV_NOPTS_VALUE)
1284 if (m < b && frag_time <= timestamp)
1293 static int update_frag_index(MOVContext *c, int64_t offset)
1296 MOVFragmentIndexItem * item;
1297 MOVFragmentStreamInfo * frag_stream_info;
1299 // If moof_offset already exists in frag_index, return index to it
1300 index = search_frag_moof_offset(&c->frag_index, offset);
1301 if (index < c->frag_index.nb_items &&
1302 c->frag_index.item[index].moof_offset == offset)
1305 // offset is not yet in frag index.
1306 // Insert new item at index (sorted by moof offset)
1307 item = av_fast_realloc(c->frag_index.item,
1308 &c->frag_index.allocated_size,
1309 (c->frag_index.nb_items + 1) *
1310 sizeof(*c->frag_index.item));
1313 c->frag_index.item = item;
1315 frag_stream_info = av_realloc_array(NULL, c->fc->nb_streams,
1316 sizeof(*item->stream_info));
1317 if (!frag_stream_info)
1320 for (i = 0; i < c->fc->nb_streams; i++) {
1321 // Avoid building frag index if streams lack track id.
1322 if (c->fc->streams[i]->id < 0) {
1323 av_free(frag_stream_info);
1324 return AVERROR_INVALIDDATA;
1327 frag_stream_info[i].id = c->fc->streams[i]->id;
1328 frag_stream_info[i].sidx_pts = AV_NOPTS_VALUE;
1329 frag_stream_info[i].tfdt_dts = AV_NOPTS_VALUE;
1330 frag_stream_info[i].next_trun_dts = AV_NOPTS_VALUE;
1331 frag_stream_info[i].first_tfra_pts = AV_NOPTS_VALUE;
1332 frag_stream_info[i].index_entry = -1;
1333 frag_stream_info[i].encryption_index = NULL;
1336 if (index < c->frag_index.nb_items)
1337 memmove(c->frag_index.item + index + 1, c->frag_index.item + index,
1338 (c->frag_index.nb_items - index) * sizeof(*c->frag_index.item));
1340 item = &c->frag_index.item[index];
1341 item->headers_read = 0;
1343 item->nb_stream_info = c->fc->nb_streams;
1344 item->moof_offset = offset;
1345 item->stream_info = frag_stream_info;
1346 c->frag_index.nb_items++;
1351 static void fix_frag_index_entries(MOVFragmentIndex *frag_index, int index,
1352 int id, int entries)
1355 MOVFragmentStreamInfo * frag_stream_info;
1359 for (i = index; i < frag_index->nb_items; i++) {
1360 frag_stream_info = get_frag_stream_info(frag_index, i, id);
1361 if (frag_stream_info && frag_stream_info->index_entry >= 0)
1362 frag_stream_info->index_entry += entries;
1366 static int mov_read_moof(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1368 // Set by mov_read_tfhd(). mov_read_trun() will reject files missing tfhd.
1369 c->fragment.found_tfhd = 0;
1371 if (!c->has_looked_for_mfra && c->use_mfra_for > 0) {
1372 c->has_looked_for_mfra = 1;
1373 if (pb->seekable & AVIO_SEEKABLE_NORMAL) {
1375 av_log(c->fc, AV_LOG_VERBOSE, "stream has moof boxes, will look "
1377 if ((ret = mov_read_mfra(c, pb)) < 0) {
1378 av_log(c->fc, AV_LOG_VERBOSE, "found a moof box but failed to "
1379 "read the mfra (may be a live ismv)\n");
1382 av_log(c->fc, AV_LOG_VERBOSE, "found a moof box but stream is not "
1383 "seekable, can not look for mfra\n");
1386 c->fragment.moof_offset = c->fragment.implicit_offset = avio_tell(pb) - 8;
1387 av_log(c->fc, AV_LOG_TRACE, "moof offset %"PRIx64"\n", c->fragment.moof_offset);
1388 c->frag_index.current = update_frag_index(c, c->fragment.moof_offset);
1389 return mov_read_default(c, pb, atom);
1392 static void mov_metadata_creation_time(AVDictionary **metadata, int64_t time, void *logctx)
1395 if(time >= 2082844800)
1396 time -= 2082844800; /* seconds between 1904-01-01 and Epoch */
1398 if ((int64_t)(time * 1000000ULL) / 1000000 != time) {
1399 av_log(logctx, AV_LOG_DEBUG, "creation_time is not representable\n");
1403 avpriv_dict_set_timestamp(metadata, "creation_time", time * 1000000);
1407 static int mov_read_mdhd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1410 MOVStreamContext *sc;
1412 char language[4] = {0};
1414 int64_t creation_time;
1416 if (c->fc->nb_streams < 1)
1418 st = c->fc->streams[c->fc->nb_streams-1];
1421 if (sc->time_scale) {
1422 av_log(c->fc, AV_LOG_ERROR, "Multiple mdhd?\n");
1423 return AVERROR_INVALIDDATA;
1426 version = avio_r8(pb);
1428 avpriv_request_sample(c->fc, "Version %d", version);
1429 return AVERROR_PATCHWELCOME;
1431 avio_rb24(pb); /* flags */
1433 creation_time = avio_rb64(pb);
1436 creation_time = avio_rb32(pb);
1437 avio_rb32(pb); /* modification time */
1439 mov_metadata_creation_time(&st->metadata, creation_time, c->fc);
1441 sc->time_scale = avio_rb32(pb);
1442 if (sc->time_scale <= 0) {
1443 av_log(c->fc, AV_LOG_ERROR, "Invalid mdhd time scale %d, defaulting to 1\n", sc->time_scale);
1446 st->duration = (version == 1) ? avio_rb64(pb) : avio_rb32(pb); /* duration */
1448 lang = avio_rb16(pb); /* language */
1449 if (ff_mov_lang_to_iso639(lang, language))
1450 av_dict_set(&st->metadata, "language", language, 0);
1451 avio_rb16(pb); /* quality */
1456 static int mov_read_mvhd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1459 int64_t creation_time;
1460 int version = avio_r8(pb); /* version */
1461 avio_rb24(pb); /* flags */
1464 creation_time = avio_rb64(pb);
1467 creation_time = avio_rb32(pb);
1468 avio_rb32(pb); /* modification time */
1470 mov_metadata_creation_time(&c->fc->metadata, creation_time, c->fc);
1471 c->time_scale = avio_rb32(pb); /* time scale */
1472 if (c->time_scale <= 0) {
1473 av_log(c->fc, AV_LOG_ERROR, "Invalid mvhd time scale %d, defaulting to 1\n", c->time_scale);
1476 av_log(c->fc, AV_LOG_TRACE, "time scale = %i\n", c->time_scale);
1478 c->duration = (version == 1) ? avio_rb64(pb) : avio_rb32(pb); /* duration */
1479 // set the AVCodecContext duration because the duration of individual tracks
1480 // may be inaccurate
1481 if (c->time_scale > 0 && !c->trex_data)
1482 c->fc->duration = av_rescale(c->duration, AV_TIME_BASE, c->time_scale);
1483 avio_rb32(pb); /* preferred scale */
1485 avio_rb16(pb); /* preferred volume */
1487 avio_skip(pb, 10); /* reserved */
1489 /* movie display matrix, store it in main context and use it later on */
1490 for (i = 0; i < 3; i++) {
1491 c->movie_display_matrix[i][0] = avio_rb32(pb); // 16.16 fixed point
1492 c->movie_display_matrix[i][1] = avio_rb32(pb); // 16.16 fixed point
1493 c->movie_display_matrix[i][2] = avio_rb32(pb); // 2.30 fixed point
1496 avio_rb32(pb); /* preview time */
1497 avio_rb32(pb); /* preview duration */
1498 avio_rb32(pb); /* poster time */
1499 avio_rb32(pb); /* selection time */
1500 avio_rb32(pb); /* selection duration */
1501 avio_rb32(pb); /* current time */
1502 avio_rb32(pb); /* next track ID */
1507 static int mov_read_enda(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1512 if (c->fc->nb_streams < 1)
1514 st = c->fc->streams[c->fc->nb_streams-1];
1516 little_endian = avio_rb16(pb) & 0xFF;
1517 av_log(c->fc, AV_LOG_TRACE, "enda %d\n", little_endian);
1518 if (little_endian == 1) {
1519 switch (st->codecpar->codec_id) {
1520 case AV_CODEC_ID_PCM_S24BE:
1521 st->codecpar->codec_id = AV_CODEC_ID_PCM_S24LE;
1523 case AV_CODEC_ID_PCM_S32BE:
1524 st->codecpar->codec_id = AV_CODEC_ID_PCM_S32LE;
1526 case AV_CODEC_ID_PCM_F32BE:
1527 st->codecpar->codec_id = AV_CODEC_ID_PCM_F32LE;
1529 case AV_CODEC_ID_PCM_F64BE:
1530 st->codecpar->codec_id = AV_CODEC_ID_PCM_F64LE;
1539 static int mov_read_colr(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1542 uint8_t *icc_profile;
1543 char color_parameter_type[5] = { 0 };
1544 uint16_t color_primaries, color_trc, color_matrix;
1547 if (c->fc->nb_streams < 1)
1549 st = c->fc->streams[c->fc->nb_streams - 1];
1551 ret = ffio_read_size(pb, color_parameter_type, 4);
1554 if (strncmp(color_parameter_type, "nclx", 4) &&
1555 strncmp(color_parameter_type, "nclc", 4) &&
1556 strncmp(color_parameter_type, "prof", 4)) {
1557 av_log(c->fc, AV_LOG_WARNING, "unsupported color_parameter_type %s\n",
1558 color_parameter_type);
1562 if (!strncmp(color_parameter_type, "prof", 4)) {
1563 icc_profile = av_stream_new_side_data(st, AV_PKT_DATA_ICC_PROFILE, atom.size - 4);
1565 return AVERROR(ENOMEM);
1566 ret = ffio_read_size(pb, icc_profile, atom.size - 4);
1571 color_primaries = avio_rb16(pb);
1572 color_trc = avio_rb16(pb);
1573 color_matrix = avio_rb16(pb);
1575 av_log(c->fc, AV_LOG_TRACE,
1576 "%s: pri %d trc %d matrix %d",
1577 color_parameter_type, color_primaries, color_trc, color_matrix);
1579 if (!strncmp(color_parameter_type, "nclx", 4)) {
1580 uint8_t color_range = avio_r8(pb) >> 7;
1581 av_log(c->fc, AV_LOG_TRACE, " full %"PRIu8"", color_range);
1583 st->codecpar->color_range = AVCOL_RANGE_JPEG;
1585 st->codecpar->color_range = AVCOL_RANGE_MPEG;
1588 if (!av_color_primaries_name(color_primaries))
1589 color_primaries = AVCOL_PRI_UNSPECIFIED;
1590 if (!av_color_transfer_name(color_trc))
1591 color_trc = AVCOL_TRC_UNSPECIFIED;
1592 if (!av_color_space_name(color_matrix))
1593 color_matrix = AVCOL_SPC_UNSPECIFIED;
1595 st->codecpar->color_primaries = color_primaries;
1596 st->codecpar->color_trc = color_trc;
1597 st->codecpar->color_space = color_matrix;
1598 av_log(c->fc, AV_LOG_TRACE, "\n");
1603 static int mov_read_fiel(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1606 unsigned mov_field_order;
1607 enum AVFieldOrder decoded_field_order = AV_FIELD_UNKNOWN;
1609 if (c->fc->nb_streams < 1) // will happen with jp2 files
1611 st = c->fc->streams[c->fc->nb_streams-1];
1613 return AVERROR_INVALIDDATA;
1614 mov_field_order = avio_rb16(pb);
1615 if ((mov_field_order & 0xFF00) == 0x0100)
1616 decoded_field_order = AV_FIELD_PROGRESSIVE;
1617 else if ((mov_field_order & 0xFF00) == 0x0200) {
1618 switch (mov_field_order & 0xFF) {
1619 case 0x01: decoded_field_order = AV_FIELD_TT;
1621 case 0x06: decoded_field_order = AV_FIELD_BB;
1623 case 0x09: decoded_field_order = AV_FIELD_TB;
1625 case 0x0E: decoded_field_order = AV_FIELD_BT;
1629 if (decoded_field_order == AV_FIELD_UNKNOWN && mov_field_order) {
1630 av_log(c->fc, AV_LOG_ERROR, "Unknown MOV field order 0x%04x\n", mov_field_order);
1632 st->codecpar->field_order = decoded_field_order;
1637 static int mov_realloc_extradata(AVCodecParameters *par, MOVAtom atom)
1640 uint64_t size = (uint64_t)par->extradata_size + atom.size + 8 + AV_INPUT_BUFFER_PADDING_SIZE;
1641 if (size > INT_MAX || (uint64_t)atom.size > INT_MAX)
1642 return AVERROR_INVALIDDATA;
1643 if ((err = av_reallocp(&par->extradata, size)) < 0) {
1644 par->extradata_size = 0;
1647 par->extradata_size = size - AV_INPUT_BUFFER_PADDING_SIZE;
1651 /* Read a whole atom into the extradata return the size of the atom read, possibly truncated if != atom.size */
1652 static int64_t mov_read_atom_into_extradata(MOVContext *c, AVIOContext *pb, MOVAtom atom,
1653 AVCodecParameters *par, uint8_t *buf)
1655 int64_t result = atom.size;
1658 AV_WB32(buf , atom.size + 8);
1659 AV_WL32(buf + 4, atom.type);
1660 err = ffio_read_size(pb, buf + 8, atom.size);
1662 par->extradata_size -= atom.size;
1664 } else if (err < atom.size) {
1665 av_log(c->fc, AV_LOG_WARNING, "truncated extradata\n");
1666 par->extradata_size -= atom.size - err;
1669 memset(buf + 8 + err, 0, AV_INPUT_BUFFER_PADDING_SIZE);
1673 /* FIXME modify QDM2/SVQ3/H.264 decoders to take full atom as extradata */
1674 static int mov_read_extradata(MOVContext *c, AVIOContext *pb, MOVAtom atom,
1675 enum AVCodecID codec_id)
1678 uint64_t original_size;
1681 if (c->fc->nb_streams < 1) // will happen with jp2 files
1683 st = c->fc->streams[c->fc->nb_streams-1];
1685 if (st->codecpar->codec_id != codec_id)
1686 return 0; /* unexpected codec_id - don't mess with extradata */
1688 original_size = st->codecpar->extradata_size;
1689 err = mov_realloc_extradata(st->codecpar, atom);
1693 err = mov_read_atom_into_extradata(c, pb, atom, st->codecpar, st->codecpar->extradata + original_size);
1696 return 0; // Note: this is the original behavior to ignore truncation.
1699 /* wrapper functions for reading ALAC/AVS/MJPEG/MJPEG2000 extradata atoms only for those codecs */
1700 static int mov_read_alac(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1702 return mov_read_extradata(c, pb, atom, AV_CODEC_ID_ALAC);
1705 static int mov_read_avss(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1707 return mov_read_extradata(c, pb, atom, AV_CODEC_ID_AVS);
1710 static int mov_read_jp2h(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1712 return mov_read_extradata(c, pb, atom, AV_CODEC_ID_JPEG2000);
1715 static int mov_read_dpxe(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1717 return mov_read_extradata(c, pb, atom, AV_CODEC_ID_R10K);
1720 static int mov_read_avid(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1722 int ret = mov_read_extradata(c, pb, atom, AV_CODEC_ID_AVUI);
1724 ret = mov_read_extradata(c, pb, atom, AV_CODEC_ID_DNXHD);
1728 static int mov_read_targa_y216(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1730 int ret = mov_read_extradata(c, pb, atom, AV_CODEC_ID_TARGA_Y216);
1732 if (!ret && c->fc->nb_streams >= 1) {
1733 AVCodecParameters *par = c->fc->streams[c->fc->nb_streams-1]->codecpar;
1734 if (par->extradata_size >= 40) {
1735 par->height = AV_RB16(&par->extradata[36]);
1736 par->width = AV_RB16(&par->extradata[38]);
1742 static int mov_read_ares(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1744 if (c->fc->nb_streams >= 1) {
1745 AVCodecParameters *par = c->fc->streams[c->fc->nb_streams-1]->codecpar;
1746 if (par->codec_tag == MKTAG('A', 'V', 'i', 'n') &&
1747 par->codec_id == AV_CODEC_ID_H264 &&
1751 cid = avio_rb16(pb);
1752 /* For AVID AVCI50, force width of 1440 to be able to select the correct SPS and PPS */
1753 if (cid == 0xd4d || cid == 0xd4e)
1756 } else if ((par->codec_tag == MKTAG('A', 'V', 'd', '1') ||
1757 par->codec_tag == MKTAG('A', 'V', 'j', '2') ||
1758 par->codec_tag == MKTAG('A', 'V', 'd', 'n')) &&
1762 num = avio_rb32(pb);
1763 den = avio_rb32(pb);
1764 if (num <= 0 || den <= 0)
1766 switch (avio_rb32(pb)) {
1768 if (den >= INT_MAX / 2)
1772 c->fc->streams[c->fc->nb_streams-1]->display_aspect_ratio.num = num;
1773 c->fc->streams[c->fc->nb_streams-1]->display_aspect_ratio.den = den;
1780 return mov_read_avid(c, pb, atom);
1783 static int mov_read_aclr(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1787 uint64_t original_size;
1788 if (c->fc->nb_streams >= 1) {
1789 AVCodecParameters *par = c->fc->streams[c->fc->nb_streams-1]->codecpar;
1790 if (par->codec_id == AV_CODEC_ID_H264)
1792 if (atom.size == 16) {
1793 original_size = par->extradata_size;
1794 ret = mov_realloc_extradata(par, atom);
1796 length = mov_read_atom_into_extradata(c, pb, atom, par, par->extradata + original_size);
1797 if (length == atom.size) {
1798 const uint8_t range_value = par->extradata[original_size + 19];
1799 switch (range_value) {
1801 par->color_range = AVCOL_RANGE_MPEG;
1804 par->color_range = AVCOL_RANGE_JPEG;
1807 av_log(c->fc, AV_LOG_WARNING, "ignored unknown aclr value (%d)\n", range_value);
1810 ff_dlog(c->fc, "color_range: %d\n", par->color_range);
1812 /* For some reason the whole atom was not added to the extradata */
1813 av_log(c->fc, AV_LOG_ERROR, "aclr not decoded - incomplete atom\n");
1816 av_log(c->fc, AV_LOG_ERROR, "aclr not decoded - unable to add atom to extradata\n");
1819 av_log(c->fc, AV_LOG_WARNING, "aclr not decoded - unexpected size %"PRId64"\n", atom.size);
1826 static int mov_read_svq3(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1828 return mov_read_extradata(c, pb, atom, AV_CODEC_ID_SVQ3);
1831 static int mov_read_wave(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1836 if (c->fc->nb_streams < 1)
1838 st = c->fc->streams[c->fc->nb_streams-1];
1840 if ((uint64_t)atom.size > (1<<30))
1841 return AVERROR_INVALIDDATA;
1843 if (st->codecpar->codec_id == AV_CODEC_ID_QDM2 ||
1844 st->codecpar->codec_id == AV_CODEC_ID_QDMC ||
1845 st->codecpar->codec_id == AV_CODEC_ID_SPEEX) {
1846 // pass all frma atom to codec, needed at least for QDMC and QDM2
1847 ret = ff_get_extradata(c->fc, st->codecpar, pb, atom.size);
1850 } else if (atom.size > 8) { /* to read frma, esds atoms */
1851 if (st->codecpar->codec_id == AV_CODEC_ID_ALAC && atom.size >= 24) {
1853 ret = ffio_ensure_seekback(pb, 8);
1856 buffer = avio_rb64(pb);
1858 if ( (buffer & 0xFFFFFFFF) == MKBETAG('f','r','m','a')
1859 && buffer >> 32 <= atom.size
1860 && buffer >> 32 >= 8) {
1863 } else if (!st->codecpar->extradata_size) {
1864 #define ALAC_EXTRADATA_SIZE 36
1865 st->codecpar->extradata = av_mallocz(ALAC_EXTRADATA_SIZE + AV_INPUT_BUFFER_PADDING_SIZE);
1866 if (!st->codecpar->extradata)
1867 return AVERROR(ENOMEM);
1868 st->codecpar->extradata_size = ALAC_EXTRADATA_SIZE;
1869 AV_WB32(st->codecpar->extradata , ALAC_EXTRADATA_SIZE);
1870 AV_WB32(st->codecpar->extradata + 4, MKTAG('a','l','a','c'));
1871 AV_WB64(st->codecpar->extradata + 12, buffer);
1872 avio_read(pb, st->codecpar->extradata + 20, 16);
1873 avio_skip(pb, atom.size - 24);
1877 if ((ret = mov_read_default(c, pb, atom)) < 0)
1880 avio_skip(pb, atom.size);
1885 * This function reads atom content and puts data in extradata without tag
1886 * nor size unlike mov_read_extradata.
1888 static int mov_read_glbl(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1893 if (c->fc->nb_streams < 1)
1895 st = c->fc->streams[c->fc->nb_streams-1];
1897 if ((uint64_t)atom.size > (1<<30))
1898 return AVERROR_INVALIDDATA;
1900 if (atom.size >= 10) {
1901 // Broken files created by legacy versions of libavformat will
1902 // wrap a whole fiel atom inside of a glbl atom.
1903 unsigned size = avio_rb32(pb);
1904 unsigned type = avio_rl32(pb);
1905 avio_seek(pb, -8, SEEK_CUR);
1906 if (type == MKTAG('f','i','e','l') && size == atom.size)
1907 return mov_read_default(c, pb, atom);
1909 if (st->codecpar->extradata_size > 1 && st->codecpar->extradata) {
1910 av_log(c->fc, AV_LOG_WARNING, "ignoring multiple glbl\n");
1913 ret = ff_get_extradata(c->fc, st->codecpar, pb, atom.size);
1916 if (atom.type == MKTAG('h','v','c','C') && st->codecpar->codec_tag == MKTAG('d','v','h','1'))
1917 /* HEVC-based Dolby Vision derived from hvc1.
1918 Happens to match with an identifier
1919 previously utilized for DV. Thus, if we have
1920 the hvcC extradata box available as specified,
1921 set codec to HEVC */
1922 st->codecpar->codec_id = AV_CODEC_ID_HEVC;
1927 static int mov_read_dvc1(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1930 uint8_t profile_level;
1933 if (c->fc->nb_streams < 1)
1935 st = c->fc->streams[c->fc->nb_streams-1];
1937 if (atom.size >= (1<<28) || atom.size < 7)
1938 return AVERROR_INVALIDDATA;
1940 profile_level = avio_r8(pb);
1941 if ((profile_level & 0xf0) != 0xc0)
1944 avio_seek(pb, 6, SEEK_CUR);
1945 ret = ff_get_extradata(c->fc, st->codecpar, pb, atom.size - 7);
1953 * An strf atom is a BITMAPINFOHEADER struct. This struct is 40 bytes itself,
1954 * but can have extradata appended at the end after the 40 bytes belonging
1957 static int mov_read_strf(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1962 if (c->fc->nb_streams < 1)
1964 if (atom.size <= 40)
1966 st = c->fc->streams[c->fc->nb_streams-1];
1968 if ((uint64_t)atom.size > (1<<30))
1969 return AVERROR_INVALIDDATA;
1972 ret = ff_get_extradata(c->fc, st->codecpar, pb, atom.size - 40);
1979 static int mov_read_stco(MOVContext *c, AVIOContext *pb, MOVAtom atom)
1982 MOVStreamContext *sc;
1983 unsigned int i, entries;
1985 if (c->trak_index < 0) {
1986 av_log(c->fc, AV_LOG_WARNING, "STCO outside TRAK\n");
1989 if (c->fc->nb_streams < 1)
1991 st = c->fc->streams[c->fc->nb_streams-1];
1994 avio_r8(pb); /* version */
1995 avio_rb24(pb); /* flags */
1997 entries = avio_rb32(pb);
2002 if (sc->chunk_offsets)
2003 av_log(c->fc, AV_LOG_WARNING, "Duplicated STCO atom\n");
2004 av_free(sc->chunk_offsets);
2005 sc->chunk_count = 0;
2006 sc->chunk_offsets = av_malloc_array(entries, sizeof(*sc->chunk_offsets));
2007 if (!sc->chunk_offsets)
2008 return AVERROR(ENOMEM);
2009 sc->chunk_count = entries;
2011 if (atom.type == MKTAG('s','t','c','o'))
2012 for (i = 0; i < entries && !pb->eof_reached; i++)
2013 sc->chunk_offsets[i] = avio_rb32(pb);
2014 else if (atom.type == MKTAG('c','o','6','4'))
2015 for (i = 0; i < entries && !pb->eof_reached; i++)
2016 sc->chunk_offsets[i] = avio_rb64(pb);
2018 return AVERROR_INVALIDDATA;
2020 sc->chunk_count = i;
2022 if (pb->eof_reached) {
2023 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted STCO atom\n");
2030 static int mov_codec_id(AVStream *st, uint32_t format)
2032 int id = ff_codec_get_id(ff_codec_movaudio_tags, format);
2035 ((format & 0xFFFF) == 'm' + ('s' << 8) ||
2036 (format & 0xFFFF) == 'T' + ('S' << 8)))
2037 id = ff_codec_get_id(ff_codec_wav_tags, av_bswap32(format) & 0xFFFF);
2039 if (st->codecpar->codec_type != AVMEDIA_TYPE_VIDEO && id > 0) {
2040 st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
2041 } else if (st->codecpar->codec_type != AVMEDIA_TYPE_AUDIO &&
2042 /* skip old ASF MPEG-4 tag */
2043 format && format != MKTAG('m','p','4','s')) {
2044 id = ff_codec_get_id(ff_codec_movvideo_tags, format);
2046 id = ff_codec_get_id(ff_codec_bmp_tags, format);
2048 st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
2049 else if (st->codecpar->codec_type == AVMEDIA_TYPE_DATA ||
2050 (st->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE &&
2051 st->codecpar->codec_id == AV_CODEC_ID_NONE)) {
2052 id = ff_codec_get_id(ff_codec_movsubtitle_tags, format);
2054 st->codecpar->codec_type = AVMEDIA_TYPE_SUBTITLE;
2056 id = ff_codec_get_id(ff_codec_movdata_tags, format);
2060 st->codecpar->codec_tag = format;
2065 static void mov_parse_stsd_video(MOVContext *c, AVIOContext *pb,
2066 AVStream *st, MOVStreamContext *sc)
2068 uint8_t codec_name[32] = { 0 };
2072 /* The first 16 bytes of the video sample description are already
2073 * read in ff_mov_read_stsd_entries() */
2074 stsd_start = avio_tell(pb) - 16;
2076 avio_rb16(pb); /* version */
2077 avio_rb16(pb); /* revision level */
2078 avio_rb32(pb); /* vendor */
2079 avio_rb32(pb); /* temporal quality */
2080 avio_rb32(pb); /* spatial quality */
2082 st->codecpar->width = avio_rb16(pb); /* width */
2083 st->codecpar->height = avio_rb16(pb); /* height */
2085 avio_rb32(pb); /* horiz resolution */
2086 avio_rb32(pb); /* vert resolution */
2087 avio_rb32(pb); /* data size, always 0 */
2088 avio_rb16(pb); /* frames per samples */
2090 len = avio_r8(pb); /* codec name, pascal string */
2093 mov_read_mac_string(c, pb, len, codec_name, sizeof(codec_name));
2095 avio_skip(pb, 31 - len);
2098 av_dict_set(&st->metadata, "encoder", codec_name, 0);
2100 /* codec_tag YV12 triggers an UV swap in rawdec.c */
2101 if (!strncmp(codec_name, "Planar Y'CbCr 8-bit 4:2:0", 25)) {
2102 st->codecpar->codec_tag = MKTAG('I', '4', '2', '0');
2103 st->codecpar->width &= ~1;
2104 st->codecpar->height &= ~1;
2106 /* Flash Media Server uses tag H.263 with Sorenson Spark */
2107 if (st->codecpar->codec_tag == MKTAG('H','2','6','3') &&
2108 !strncmp(codec_name, "Sorenson H263", 13))
2109 st->codecpar->codec_id = AV_CODEC_ID_FLV1;
2111 st->codecpar->bits_per_coded_sample = avio_rb16(pb); /* depth */
2113 avio_seek(pb, stsd_start, SEEK_SET);
2115 if (ff_get_qtpalette(st->codecpar->codec_id, pb, sc->palette)) {
2116 st->codecpar->bits_per_coded_sample &= 0x1F;
2117 sc->has_palette = 1;
2121 static void mov_parse_stsd_audio(MOVContext *c, AVIOContext *pb,
2122 AVStream *st, MOVStreamContext *sc)
2124 int bits_per_sample, flags;
2125 uint16_t version = avio_rb16(pb);
2126 AVDictionaryEntry *compatible_brands = av_dict_get(c->fc->metadata, "compatible_brands", NULL, AV_DICT_MATCH_CASE);
2128 avio_rb16(pb); /* revision level */
2129 avio_rb32(pb); /* vendor */
2131 st->codecpar->channels = avio_rb16(pb); /* channel count */
2132 st->codecpar->bits_per_coded_sample = avio_rb16(pb); /* sample size */
2133 av_log(c->fc, AV_LOG_TRACE, "audio channels %d\n", st->codecpar->channels);
2135 sc->audio_cid = avio_rb16(pb);
2136 avio_rb16(pb); /* packet size = 0 */
2138 st->codecpar->sample_rate = ((avio_rb32(pb) >> 16));
2140 // Read QT version 1 fields. In version 0 these do not exist.
2141 av_log(c->fc, AV_LOG_TRACE, "version =%d, isom =%d\n", version, c->isom);
2143 (compatible_brands && strstr(compatible_brands->value, "qt ")) ||
2144 (sc->stsd_version == 0 && version > 0)) {
2146 sc->samples_per_frame = avio_rb32(pb);
2147 avio_rb32(pb); /* bytes per packet */
2148 sc->bytes_per_frame = avio_rb32(pb);
2149 avio_rb32(pb); /* bytes per sample */
2150 } else if (version == 2) {
2151 avio_rb32(pb); /* sizeof struct only */
2152 st->codecpar->sample_rate = av_int2double(avio_rb64(pb));
2153 st->codecpar->channels = avio_rb32(pb);
2154 avio_rb32(pb); /* always 0x7F000000 */
2155 st->codecpar->bits_per_coded_sample = avio_rb32(pb);
2157 flags = avio_rb32(pb); /* lpcm format specific flag */
2158 sc->bytes_per_frame = avio_rb32(pb);
2159 sc->samples_per_frame = avio_rb32(pb);
2160 if (st->codecpar->codec_tag == MKTAG('l','p','c','m'))
2161 st->codecpar->codec_id =
2162 ff_mov_get_lpcm_codec_id(st->codecpar->bits_per_coded_sample,
2165 if (version == 0 || (version == 1 && sc->audio_cid != -2)) {
2166 /* can't correctly handle variable sized packet as audio unit */
2167 switch (st->codecpar->codec_id) {
2168 case AV_CODEC_ID_MP2:
2169 case AV_CODEC_ID_MP3:
2170 st->need_parsing = AVSTREAM_PARSE_FULL;
2176 if (sc->format == 0) {
2177 if (st->codecpar->bits_per_coded_sample == 8)
2178 st->codecpar->codec_id = mov_codec_id(st, MKTAG('r','a','w',' '));
2179 else if (st->codecpar->bits_per_coded_sample == 16)
2180 st->codecpar->codec_id = mov_codec_id(st, MKTAG('t','w','o','s'));
2183 switch (st->codecpar->codec_id) {
2184 case AV_CODEC_ID_PCM_S8:
2185 case AV_CODEC_ID_PCM_U8:
2186 if (st->codecpar->bits_per_coded_sample == 16)
2187 st->codecpar->codec_id = AV_CODEC_ID_PCM_S16BE;
2189 case AV_CODEC_ID_PCM_S16LE:
2190 case AV_CODEC_ID_PCM_S16BE:
2191 if (st->codecpar->bits_per_coded_sample == 8)
2192 st->codecpar->codec_id = AV_CODEC_ID_PCM_S8;
2193 else if (st->codecpar->bits_per_coded_sample == 24)
2194 st->codecpar->codec_id =
2195 st->codecpar->codec_id == AV_CODEC_ID_PCM_S16BE ?
2196 AV_CODEC_ID_PCM_S24BE : AV_CODEC_ID_PCM_S24LE;
2197 else if (st->codecpar->bits_per_coded_sample == 32)
2198 st->codecpar->codec_id =
2199 st->codecpar->codec_id == AV_CODEC_ID_PCM_S16BE ?
2200 AV_CODEC_ID_PCM_S32BE : AV_CODEC_ID_PCM_S32LE;
2202 /* set values for old format before stsd version 1 appeared */
2203 case AV_CODEC_ID_MACE3:
2204 sc->samples_per_frame = 6;
2205 sc->bytes_per_frame = 2 * st->codecpar->channels;
2207 case AV_CODEC_ID_MACE6:
2208 sc->samples_per_frame = 6;
2209 sc->bytes_per_frame = 1 * st->codecpar->channels;
2211 case AV_CODEC_ID_ADPCM_IMA_QT:
2212 sc->samples_per_frame = 64;
2213 sc->bytes_per_frame = 34 * st->codecpar->channels;
2215 case AV_CODEC_ID_GSM:
2216 sc->samples_per_frame = 160;
2217 sc->bytes_per_frame = 33;
2223 bits_per_sample = av_get_bits_per_sample(st->codecpar->codec_id);
2224 if (bits_per_sample) {
2225 st->codecpar->bits_per_coded_sample = bits_per_sample;
2226 sc->sample_size = (bits_per_sample >> 3) * st->codecpar->channels;
2230 static void mov_parse_stsd_subtitle(MOVContext *c, AVIOContext *pb,
2231 AVStream *st, MOVStreamContext *sc,
2234 // ttxt stsd contains display flags, justification, background
2235 // color, fonts, and default styles, so fake an atom to read it
2236 MOVAtom fake_atom = { .size = size };
2237 // mp4s contains a regular esds atom
2238 if (st->codecpar->codec_tag != AV_RL32("mp4s"))
2239 mov_read_glbl(c, pb, fake_atom);
2240 st->codecpar->width = sc->width;
2241 st->codecpar->height = sc->height;
2244 static uint32_t yuv_to_rgba(uint32_t ycbcr)
2249 y = (ycbcr >> 16) & 0xFF;
2250 cr = (ycbcr >> 8) & 0xFF;
2253 b = av_clip_uint8((1164 * (y - 16) + 2018 * (cb - 128)) / 1000);
2254 g = av_clip_uint8((1164 * (y - 16) - 813 * (cr - 128) - 391 * (cb - 128)) / 1000);
2255 r = av_clip_uint8((1164 * (y - 16) + 1596 * (cr - 128) ) / 1000);
2257 return (r << 16) | (g << 8) | b;
2260 static int mov_rewrite_dvd_sub_extradata(AVStream *st)
2262 char buf[256] = {0};
2263 uint8_t *src = st->codecpar->extradata;
2266 if (st->codecpar->extradata_size != 64)
2269 if (st->codecpar->width > 0 && st->codecpar->height > 0)
2270 snprintf(buf, sizeof(buf), "size: %dx%d\n",
2271 st->codecpar->width, st->codecpar->height);
2272 av_strlcat(buf, "palette: ", sizeof(buf));
2274 for (i = 0; i < 16; i++) {
2275 uint32_t yuv = AV_RB32(src + i * 4);
2276 uint32_t rgba = yuv_to_rgba(yuv);
2278 av_strlcatf(buf, sizeof(buf), "%06"PRIx32"%s", rgba, i != 15 ? ", " : "");
2281 if (av_strlcat(buf, "\n", sizeof(buf)) >= sizeof(buf))
2284 ret = ff_alloc_extradata(st->codecpar, strlen(buf));
2287 memcpy(st->codecpar->extradata, buf, st->codecpar->extradata_size);
2292 static int mov_parse_stsd_data(MOVContext *c, AVIOContext *pb,
2293 AVStream *st, MOVStreamContext *sc,
2298 if (st->codecpar->codec_tag == MKTAG('t','m','c','d')) {
2299 if ((int)size != size)
2300 return AVERROR(ENOMEM);
2302 ret = ff_get_extradata(c->fc, st->codecpar, pb, size);
2306 MOVStreamContext *tmcd_ctx = st->priv_data;
2308 val = AV_RB32(st->codecpar->extradata + 4);
2309 tmcd_ctx->tmcd_flags = val;
2310 st->avg_frame_rate.num = AV_RB32(st->codecpar->extradata + 8); /* timescale */
2311 st->avg_frame_rate.den = AV_RB32(st->codecpar->extradata + 12); /* frameDuration */
2312 #if FF_API_LAVF_AVCTX
2313 FF_DISABLE_DEPRECATION_WARNINGS
2314 st->codec->time_base = av_inv_q(st->avg_frame_rate);
2315 FF_ENABLE_DEPRECATION_WARNINGS
2317 /* adjust for per frame dur in counter mode */
2318 if (tmcd_ctx->tmcd_flags & 0x0008) {
2319 int timescale = AV_RB32(st->codecpar->extradata + 8);
2320 int framedur = AV_RB32(st->codecpar->extradata + 12);
2321 st->avg_frame_rate.num *= timescale;
2322 st->avg_frame_rate.den *= framedur;
2323 #if FF_API_LAVF_AVCTX
2324 FF_DISABLE_DEPRECATION_WARNINGS
2325 st->codec->time_base.den *= timescale;
2326 st->codec->time_base.num *= framedur;
2327 FF_ENABLE_DEPRECATION_WARNINGS
2331 uint32_t len = AV_RB32(st->codecpar->extradata + 18); /* name atom length */
2332 uint32_t format = AV_RB32(st->codecpar->extradata + 22);
2333 if (format == AV_RB32("name") && (int64_t)size >= (int64_t)len + 18) {
2334 uint16_t str_size = AV_RB16(st->codecpar->extradata + 26); /* string length */
2335 if (str_size > 0 && size >= (int)str_size + 30 &&
2336 st->codecpar->extradata[30] /* Don't add empty string */) {
2337 char *reel_name = av_malloc(str_size + 1);
2339 return AVERROR(ENOMEM);
2340 memcpy(reel_name, st->codecpar->extradata + 30, str_size);
2341 reel_name[str_size] = 0; /* Add null terminator */
2342 av_dict_set(&st->metadata, "reel_name", reel_name,
2343 AV_DICT_DONT_STRDUP_VAL);
2349 /* other codec type, just skip (rtp, mp4s ...) */
2350 avio_skip(pb, size);
2355 static int mov_finalize_stsd_codec(MOVContext *c, AVIOContext *pb,
2356 AVStream *st, MOVStreamContext *sc)
2358 if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO &&
2359 !st->codecpar->sample_rate && sc->time_scale > 1)
2360 st->codecpar->sample_rate = sc->time_scale;
2362 /* special codec parameters handling */
2363 switch (st->codecpar->codec_id) {
2364 #if CONFIG_DV_DEMUXER
2365 case AV_CODEC_ID_DVAUDIO:
2366 c->dv_fctx = avformat_alloc_context();
2368 av_log(c->fc, AV_LOG_ERROR, "dv demux context alloc error\n");
2369 return AVERROR(ENOMEM);
2371 c->dv_demux = avpriv_dv_init_demux(c->dv_fctx);
2373 av_log(c->fc, AV_LOG_ERROR, "dv demux context init error\n");
2374 return AVERROR(ENOMEM);
2376 sc->dv_audio_container = 1;
2377 st->codecpar->codec_id = AV_CODEC_ID_PCM_S16LE;
2380 /* no ifdef since parameters are always those */
2381 case AV_CODEC_ID_QCELP:
2382 st->codecpar->channels = 1;
2383 // force sample rate for qcelp when not stored in mov
2384 if (st->codecpar->codec_tag != MKTAG('Q','c','l','p'))
2385 st->codecpar->sample_rate = 8000;
2386 // FIXME: Why is the following needed for some files?
2387 sc->samples_per_frame = 160;
2388 if (!sc->bytes_per_frame)
2389 sc->bytes_per_frame = 35;
2391 case AV_CODEC_ID_AMR_NB:
2392 st->codecpar->channels = 1;
2393 /* force sample rate for amr, stsd in 3gp does not store sample rate */
2394 st->codecpar->sample_rate = 8000;
2396 case AV_CODEC_ID_AMR_WB:
2397 st->codecpar->channels = 1;
2398 st->codecpar->sample_rate = 16000;
2400 case AV_CODEC_ID_MP2:
2401 case AV_CODEC_ID_MP3:
2402 /* force type after stsd for m1a hdlr */
2403 st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
2405 case AV_CODEC_ID_GSM:
2406 case AV_CODEC_ID_ADPCM_MS:
2407 case AV_CODEC_ID_ADPCM_IMA_WAV:
2408 case AV_CODEC_ID_ILBC:
2409 case AV_CODEC_ID_MACE3:
2410 case AV_CODEC_ID_MACE6:
2411 case AV_CODEC_ID_QDM2:
2412 st->codecpar->block_align = sc->bytes_per_frame;
2414 case AV_CODEC_ID_ALAC:
2415 if (st->codecpar->extradata_size == 36) {
2416 st->codecpar->channels = AV_RB8 (st->codecpar->extradata + 21);
2417 st->codecpar->sample_rate = AV_RB32(st->codecpar->extradata + 32);
2420 case AV_CODEC_ID_AC3:
2421 case AV_CODEC_ID_EAC3:
2422 case AV_CODEC_ID_MPEG1VIDEO:
2423 case AV_CODEC_ID_VC1:
2424 case AV_CODEC_ID_VP8:
2425 case AV_CODEC_ID_VP9:
2426 st->need_parsing = AVSTREAM_PARSE_FULL;
2434 static int mov_skip_multiple_stsd(MOVContext *c, AVIOContext *pb,
2435 int codec_tag, int format,
2438 int video_codec_id = ff_codec_get_id(ff_codec_movvideo_tags, format);
2441 (codec_tag != format &&
2442 // AVID 1:1 samples with differing data format and codec tag exist
2443 (codec_tag != AV_RL32("AV1x") || format != AV_RL32("AVup")) &&
2444 // prores is allowed to have differing data format and codec tag
2445 codec_tag != AV_RL32("apcn") && codec_tag != AV_RL32("apch") &&
2447 codec_tag != AV_RL32("dvpp") && codec_tag != AV_RL32("dvcp") &&
2448 (c->fc->video_codec_id ? video_codec_id != c->fc->video_codec_id
2449 : codec_tag != MKTAG('j','p','e','g')))) {
2450 /* Multiple fourcc, we skip JPEG. This is not correct, we should
2451 * export it as a separate AVStream but this needs a few changes
2452 * in the MOV demuxer, patch welcome. */
2454 av_log(c->fc, AV_LOG_WARNING, "multiple fourcc not supported\n");
2455 avio_skip(pb, size);
2462 int ff_mov_read_stsd_entries(MOVContext *c, AVIOContext *pb, int entries)
2465 MOVStreamContext *sc;
2466 int pseudo_stream_id;
2468 av_assert0 (c->fc->nb_streams >= 1);
2469 st = c->fc->streams[c->fc->nb_streams-1];
2472 for (pseudo_stream_id = 0;
2473 pseudo_stream_id < entries && !pb->eof_reached;
2474 pseudo_stream_id++) {
2475 //Parsing Sample description table
2477 int ret, dref_id = 1;
2478 MOVAtom a = { AV_RL32("stsd") };
2479 int64_t start_pos = avio_tell(pb);
2480 int64_t size = avio_rb32(pb); /* size */
2481 uint32_t format = avio_rl32(pb); /* data format */
2484 avio_rb32(pb); /* reserved */
2485 avio_rb16(pb); /* reserved */
2486 dref_id = avio_rb16(pb);
2487 } else if (size <= 7) {
2488 av_log(c->fc, AV_LOG_ERROR,
2489 "invalid size %"PRId64" in stsd\n", size);
2490 return AVERROR_INVALIDDATA;
2493 if (mov_skip_multiple_stsd(c, pb, st->codecpar->codec_tag, format,
2494 size - (avio_tell(pb) - start_pos))) {
2499 sc->pseudo_stream_id = st->codecpar->codec_tag ? -1 : pseudo_stream_id;
2500 sc->dref_id= dref_id;
2501 sc->format = format;
2503 id = mov_codec_id(st, format);
2505 av_log(c->fc, AV_LOG_TRACE,
2506 "size=%"PRId64" 4CC=%s codec_type=%d\n", size,
2507 av_fourcc2str(format), st->codecpar->codec_type);
2509 st->codecpar->codec_id = id;
2510 if (st->codecpar->codec_type==AVMEDIA_TYPE_VIDEO) {
2511 mov_parse_stsd_video(c, pb, st, sc);
2512 } else if (st->codecpar->codec_type==AVMEDIA_TYPE_AUDIO) {
2513 mov_parse_stsd_audio(c, pb, st, sc);
2514 if (st->codecpar->sample_rate < 0) {
2515 av_log(c->fc, AV_LOG_ERROR, "Invalid sample rate %d\n", st->codecpar->sample_rate);
2516 return AVERROR_INVALIDDATA;
2518 } else if (st->codecpar->codec_type==AVMEDIA_TYPE_SUBTITLE){
2519 mov_parse_stsd_subtitle(c, pb, st, sc,
2520 size - (avio_tell(pb) - start_pos));
2522 ret = mov_parse_stsd_data(c, pb, st, sc,
2523 size - (avio_tell(pb) - start_pos));
2527 /* this will read extra atoms at the end (wave, alac, damr, avcC, hvcC, SMI ...) */
2528 a.size = size - (avio_tell(pb) - start_pos);
2530 if ((ret = mov_read_default(c, pb, a)) < 0)
2532 } else if (a.size > 0)
2533 avio_skip(pb, a.size);
2535 if (sc->extradata && st->codecpar->extradata) {
2536 int extra_size = st->codecpar->extradata_size;
2538 /* Move the current stream extradata to the stream context one. */
2539 sc->extradata_size[pseudo_stream_id] = extra_size;
2540 sc->extradata[pseudo_stream_id] = st->codecpar->extradata;
2541 st->codecpar->extradata = NULL;
2542 st->codecpar->extradata_size = 0;
2547 if (pb->eof_reached) {
2548 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted STSD atom\n");
2555 static int mov_read_stsd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2558 MOVStreamContext *sc;
2561 if (c->fc->nb_streams < 1)
2563 st = c->fc->streams[c->fc->nb_streams - 1];
2566 sc->stsd_version = avio_r8(pb);
2567 avio_rb24(pb); /* flags */
2568 entries = avio_rb32(pb);
2570 /* Each entry contains a size (4 bytes) and format (4 bytes). */
2571 if (entries <= 0 || entries > atom.size / 8) {
2572 av_log(c->fc, AV_LOG_ERROR, "invalid STSD entries %d\n", entries);
2573 return AVERROR_INVALIDDATA;
2576 if (sc->extradata) {
2577 av_log(c->fc, AV_LOG_ERROR,
2578 "Duplicate stsd found in this track.\n");
2579 return AVERROR_INVALIDDATA;
2582 /* Prepare space for hosting multiple extradata. */
2583 sc->extradata = av_mallocz_array(entries, sizeof(*sc->extradata));
2585 return AVERROR(ENOMEM);
2587 sc->extradata_size = av_mallocz_array(entries, sizeof(*sc->extradata_size));
2588 if (!sc->extradata_size) {
2589 ret = AVERROR(ENOMEM);
2593 ret = ff_mov_read_stsd_entries(c, pb, entries);
2597 /* Restore back the primary extradata. */
2598 av_freep(&st->codecpar->extradata);
2599 st->codecpar->extradata_size = sc->extradata_size[0];
2600 if (sc->extradata_size[0]) {
2601 st->codecpar->extradata = av_mallocz(sc->extradata_size[0] + AV_INPUT_BUFFER_PADDING_SIZE);
2602 if (!st->codecpar->extradata)
2603 return AVERROR(ENOMEM);
2604 memcpy(st->codecpar->extradata, sc->extradata[0], sc->extradata_size[0]);
2607 return mov_finalize_stsd_codec(c, pb, st, sc);
2609 if (sc->extradata) {
2611 for (j = 0; j < sc->stsd_count; j++)
2612 av_freep(&sc->extradata[j]);
2615 av_freep(&sc->extradata);
2616 av_freep(&sc->extradata_size);
2620 static int mov_read_stsc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2623 MOVStreamContext *sc;
2624 unsigned int i, entries;
2626 if (c->fc->nb_streams < 1)
2628 st = c->fc->streams[c->fc->nb_streams-1];
2631 avio_r8(pb); /* version */
2632 avio_rb24(pb); /* flags */
2634 entries = avio_rb32(pb);
2635 if ((uint64_t)entries * 12 + 4 > atom.size)
2636 return AVERROR_INVALIDDATA;
2638 av_log(c->fc, AV_LOG_TRACE, "track[%u].stsc.entries = %u\n", c->fc->nb_streams - 1, entries);
2643 av_log(c->fc, AV_LOG_WARNING, "Duplicated STSC atom\n");
2644 av_free(sc->stsc_data);
2646 sc->stsc_data = av_malloc_array(entries, sizeof(*sc->stsc_data));
2648 return AVERROR(ENOMEM);
2650 for (i = 0; i < entries && !pb->eof_reached; i++) {
2651 sc->stsc_data[i].first = avio_rb32(pb);
2652 sc->stsc_data[i].count = avio_rb32(pb);
2653 sc->stsc_data[i].id = avio_rb32(pb);
2657 for (i = sc->stsc_count - 1; i < UINT_MAX; i--) {
2658 int64_t first_min = i + 1;
2659 if ((i+1 < sc->stsc_count && sc->stsc_data[i].first >= sc->stsc_data[i+1].first) ||
2660 (i > 0 && sc->stsc_data[i].first <= sc->stsc_data[i-1].first) ||
2661 sc->stsc_data[i].first < first_min ||
2662 sc->stsc_data[i].count < 1 ||
2663 sc->stsc_data[i].id < 1) {
2664 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);
2665 if (i+1 >= sc->stsc_count) {
2666 if (sc->stsc_data[i].count == 0 && i > 0) {
2670 sc->stsc_data[i].first = FFMAX(sc->stsc_data[i].first, first_min);
2671 if (i > 0 && sc->stsc_data[i].first <= sc->stsc_data[i-1].first)
2672 sc->stsc_data[i].first = FFMIN(sc->stsc_data[i-1].first + 1LL, INT_MAX);
2673 sc->stsc_data[i].count = FFMAX(sc->stsc_data[i].count, 1);
2674 sc->stsc_data[i].id = FFMAX(sc->stsc_data[i].id, 1);
2677 av_assert0(sc->stsc_data[i+1].first >= 2);
2678 // We replace this entry by the next valid
2679 sc->stsc_data[i].first = sc->stsc_data[i+1].first - 1;
2680 sc->stsc_data[i].count = sc->stsc_data[i+1].count;
2681 sc->stsc_data[i].id = sc->stsc_data[i+1].id;
2685 if (pb->eof_reached) {
2686 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted STSC atom\n");
2693 static inline int mov_stsc_index_valid(unsigned int index, unsigned int count)
2695 return index < count - 1;
2698 /* Compute the samples value for the stsc entry at the given index. */
2699 static inline int64_t mov_get_stsc_samples(MOVStreamContext *sc, unsigned int index)
2703 if (mov_stsc_index_valid(index, sc->stsc_count))
2704 chunk_count = sc->stsc_data[index + 1].first - sc->stsc_data[index].first;
2706 // Validation for stsc / stco happens earlier in mov_read_stsc + mov_read_trak.
2707 av_assert0(sc->stsc_data[index].first <= sc->chunk_count);
2708 chunk_count = sc->chunk_count - (sc->stsc_data[index].first - 1);
2711 return sc->stsc_data[index].count * (int64_t)chunk_count;
2714 static int mov_read_stps(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2717 MOVStreamContext *sc;
2718 unsigned i, entries;
2720 if (c->fc->nb_streams < 1)
2722 st = c->fc->streams[c->fc->nb_streams-1];
2725 avio_rb32(pb); // version + flags
2727 entries = avio_rb32(pb);
2729 av_log(c->fc, AV_LOG_WARNING, "Duplicated STPS atom\n");
2730 av_free(sc->stps_data);
2732 sc->stps_data = av_malloc_array(entries, sizeof(*sc->stps_data));
2734 return AVERROR(ENOMEM);
2736 for (i = 0; i < entries && !pb->eof_reached; i++) {
2737 sc->stps_data[i] = avio_rb32(pb);
2742 if (pb->eof_reached) {
2743 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted STPS atom\n");
2750 static int mov_read_stss(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2753 MOVStreamContext *sc;
2754 unsigned int i, entries;
2756 if (c->fc->nb_streams < 1)
2758 st = c->fc->streams[c->fc->nb_streams-1];
2761 avio_r8(pb); /* version */
2762 avio_rb24(pb); /* flags */
2764 entries = avio_rb32(pb);
2766 av_log(c->fc, AV_LOG_TRACE, "keyframe_count = %u\n", entries);
2770 sc->keyframe_absent = 1;
2771 if (!st->need_parsing && st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO)
2772 st->need_parsing = AVSTREAM_PARSE_HEADERS;
2776 av_log(c->fc, AV_LOG_WARNING, "Duplicated STSS atom\n");
2777 if (entries >= UINT_MAX / sizeof(int))
2778 return AVERROR_INVALIDDATA;
2779 av_freep(&sc->keyframes);
2780 sc->keyframe_count = 0;
2781 sc->keyframes = av_malloc_array(entries, sizeof(*sc->keyframes));
2783 return AVERROR(ENOMEM);
2785 for (i = 0; i < entries && !pb->eof_reached; i++) {
2786 sc->keyframes[i] = avio_rb32(pb);
2789 sc->keyframe_count = i;
2791 if (pb->eof_reached) {
2792 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted STSS atom\n");
2799 static int mov_read_stsz(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2802 MOVStreamContext *sc;
2803 unsigned int i, entries, sample_size, field_size, num_bytes;
2808 if (c->fc->nb_streams < 1)
2810 st = c->fc->streams[c->fc->nb_streams-1];
2813 avio_r8(pb); /* version */
2814 avio_rb24(pb); /* flags */
2816 if (atom.type == MKTAG('s','t','s','z')) {
2817 sample_size = avio_rb32(pb);
2818 if (!sc->sample_size) /* do not overwrite value computed in stsd */
2819 sc->sample_size = sample_size;
2820 sc->stsz_sample_size = sample_size;
2824 avio_rb24(pb); /* reserved */
2825 field_size = avio_r8(pb);
2827 entries = avio_rb32(pb);
2829 av_log(c->fc, AV_LOG_TRACE, "sample_size = %u sample_count = %u\n", sc->sample_size, entries);
2831 sc->sample_count = entries;
2835 if (field_size != 4 && field_size != 8 && field_size != 16 && field_size != 32) {
2836 av_log(c->fc, AV_LOG_ERROR, "Invalid sample field size %u\n", field_size);
2837 return AVERROR_INVALIDDATA;
2842 if (entries >= (UINT_MAX - 4) / field_size)
2843 return AVERROR_INVALIDDATA;
2844 if (sc->sample_sizes)
2845 av_log(c->fc, AV_LOG_WARNING, "Duplicated STSZ atom\n");
2846 av_free(sc->sample_sizes);
2847 sc->sample_count = 0;
2848 sc->sample_sizes = av_malloc_array(entries, sizeof(*sc->sample_sizes));
2849 if (!sc->sample_sizes)
2850 return AVERROR(ENOMEM);
2852 num_bytes = (entries*field_size+4)>>3;
2854 buf = av_malloc(num_bytes+AV_INPUT_BUFFER_PADDING_SIZE);
2856 av_freep(&sc->sample_sizes);
2857 return AVERROR(ENOMEM);
2860 ret = ffio_read_size(pb, buf, num_bytes);
2862 av_freep(&sc->sample_sizes);
2864 av_log(c->fc, AV_LOG_WARNING, "STSZ atom truncated\n");
2868 init_get_bits(&gb, buf, 8*num_bytes);
2870 for (i = 0; i < entries && !pb->eof_reached; i++) {
2871 sc->sample_sizes[i] = get_bits_long(&gb, field_size);
2872 if (sc->sample_sizes[i] < 0) {
2874 av_log(c->fc, AV_LOG_ERROR, "Invalid sample size %d\n", sc->sample_sizes[i]);
2875 return AVERROR_INVALIDDATA;
2877 sc->data_size += sc->sample_sizes[i];
2880 sc->sample_count = i;
2884 if (pb->eof_reached) {
2885 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted STSZ atom\n");
2892 static int mov_read_stts(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2895 MOVStreamContext *sc;
2896 unsigned int i, entries, alloc_size = 0;
2898 int64_t total_sample_count=0;
2900 if (c->fc->nb_streams < 1)
2902 st = c->fc->streams[c->fc->nb_streams-1];
2905 avio_r8(pb); /* version */
2906 avio_rb24(pb); /* flags */
2907 entries = avio_rb32(pb);
2909 av_log(c->fc, AV_LOG_TRACE, "track[%u].stts.entries = %u\n",
2910 c->fc->nb_streams-1, entries);
2913 av_log(c->fc, AV_LOG_WARNING, "Duplicated STTS atom\n");
2914 av_freep(&sc->stts_data);
2916 if (entries >= INT_MAX / sizeof(*sc->stts_data))
2917 return AVERROR(ENOMEM);
2919 for (i = 0; i < entries && !pb->eof_reached; i++) {
2920 int sample_duration;
2921 unsigned int sample_count;
2922 unsigned int min_entries = FFMIN(FFMAX(i + 1, 1024 * 1024), entries);
2923 MOVStts *stts_data = av_fast_realloc(sc->stts_data, &alloc_size,
2924 min_entries * sizeof(*sc->stts_data));
2926 av_freep(&sc->stts_data);
2928 return AVERROR(ENOMEM);
2930 sc->stts_count = min_entries;
2931 sc->stts_data = stts_data;
2933 sample_count=avio_rb32(pb);
2934 sample_duration = avio_rb32(pb);
2936 sc->stts_data[i].count= sample_count;
2937 sc->stts_data[i].duration= sample_duration;
2939 av_log(c->fc, AV_LOG_TRACE, "sample_count=%d, sample_duration=%d\n",
2940 sample_count, sample_duration);
2942 duration+=(int64_t)sample_duration*(uint64_t)sample_count;
2943 total_sample_count+=sample_count;
2949 duration <= INT64_MAX - sc->duration_for_fps &&
2950 total_sample_count <= INT_MAX - sc->nb_frames_for_fps
2952 sc->duration_for_fps += duration;
2953 sc->nb_frames_for_fps += total_sample_count;
2956 if (pb->eof_reached) {
2957 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted STTS atom\n");
2961 st->nb_frames= total_sample_count;
2963 st->duration= FFMIN(st->duration, duration);
2964 sc->track_end = duration;
2968 static int mov_read_sdtp(MOVContext *c, AVIOContext *pb, MOVAtom atom)
2971 MOVStreamContext *sc;
2974 if (c->fc->nb_streams < 1)
2976 st = c->fc->streams[c->fc->nb_streams - 1];
2979 avio_r8(pb); /* version */
2980 avio_rb24(pb); /* flags */
2981 entries = atom.size - 4;
2983 av_log(c->fc, AV_LOG_TRACE, "track[%u].sdtp.entries = %" PRId64 "\n",
2984 c->fc->nb_streams - 1, entries);
2987 av_log(c->fc, AV_LOG_WARNING, "Duplicated SDTP atom\n");
2988 av_freep(&sc->sdtp_data);
2991 sc->sdtp_data = av_mallocz(entries);
2993 return AVERROR(ENOMEM);
2995 for (i = 0; i < entries && !pb->eof_reached; i++)
2996 sc->sdtp_data[i] = avio_r8(pb);
3002 static void mov_update_dts_shift(MOVStreamContext *sc, int duration, void *logctx)
3005 if (duration == INT_MIN) {
3006 av_log(logctx, AV_LOG_WARNING, "mov_update_dts_shift(): dts_shift set to %d\n", INT_MAX);
3009 sc->dts_shift = FFMAX(sc->dts_shift, -duration);
3013 static int mov_read_ctts(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3016 MOVStreamContext *sc;
3017 unsigned int i, entries, ctts_count = 0;
3019 if (c->fc->nb_streams < 1)
3021 st = c->fc->streams[c->fc->nb_streams-1];
3024 avio_r8(pb); /* version */
3025 avio_rb24(pb); /* flags */
3026 entries = avio_rb32(pb);
3028 av_log(c->fc, AV_LOG_TRACE, "track[%u].ctts.entries = %u\n", c->fc->nb_streams - 1, entries);
3032 if (entries >= UINT_MAX / sizeof(*sc->ctts_data))
3033 return AVERROR_INVALIDDATA;
3034 av_freep(&sc->ctts_data);
3035 sc->ctts_data = av_fast_realloc(NULL, &sc->ctts_allocated_size, entries * sizeof(*sc->ctts_data));
3037 return AVERROR(ENOMEM);
3039 for (i = 0; i < entries && !pb->eof_reached; i++) {
3040 int count =avio_rb32(pb);
3041 int duration =avio_rb32(pb);
3044 av_log(c->fc, AV_LOG_TRACE,
3045 "ignoring CTTS entry with count=%d duration=%d\n",
3050 add_ctts_entry(&sc->ctts_data, &ctts_count, &sc->ctts_allocated_size,
3053 av_log(c->fc, AV_LOG_TRACE, "count=%d, duration=%d\n",
3056 if (FFNABS(duration) < -(1<<28) && i+2<entries) {
3057 av_log(c->fc, AV_LOG_WARNING, "CTTS invalid\n");
3058 av_freep(&sc->ctts_data);
3064 mov_update_dts_shift(sc, duration, c->fc);
3067 sc->ctts_count = ctts_count;
3069 if (pb->eof_reached) {
3070 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted CTTS atom\n");
3074 av_log(c->fc, AV_LOG_TRACE, "dts shift %d\n", sc->dts_shift);
3079 static int mov_read_sbgp(MOVContext *c, AVIOContext *pb, MOVAtom atom)
3082 MOVStreamContext *sc;
3083 unsigned int i, entries;
3085 uint32_t grouping_type;
3087 if (c->fc->nb_streams < 1)
3089 st = c->fc->streams[c->fc->nb_streams-1];
3092 version = avio_r8(pb); /* version */
3093 avio_rb24(pb); /* flags */
3094 grouping_type = avio_rl32(pb);
3095 if (grouping_type != MKTAG( 'r','a','p',' '))
3096 return 0; /* only support 'rap ' grouping */
3098 avio_rb32(pb); /* grouping_type_parameter */
3100 entries = avio_rb32(pb);
3104 av_log(c->fc, AV_LOG_WARNING, "Duplicated SBGP atom\n");
3105 av_free(sc->rap_group);
3106 sc->rap_group_count = 0;
3107 sc->rap_group = av_malloc_array(entries, sizeof(*sc->rap_group));
3109 return AVERROR(ENOMEM);
3111 for (i = 0; i < entries && !pb->eof_reached; i++) {
3112 sc->rap_group[i].count = avio_rb32(pb); /* sample_count */
3113 sc->rap_group[i].index = avio_rb32(pb); /* group_description_index */
3116 sc->rap_group_count = i;
3118 if (pb->eof_reached) {
3119 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted SBGP atom\n");
3127 * Get ith edit list entry (media time, duration).
3129 static int get_edit_list_entry(MOVContext *mov,
3130 const MOVStreamContext *msc,
3131 unsigned int edit_list_index,
3132 int64_t *edit_list_media_time,
3133 int64_t *edit_list_duration,
3134 int64_t global_timescale)
3136 if (edit_list_index == msc->elst_count) {
3139 *edit_list_media_time = msc->elst_data[edit_list_index].time;
3140 *edit_list_duration = msc->elst_data[edit_list_index].duration;
3142 /* duration is in global timescale units;convert to msc timescale */
3143 if (global_timescale == 0) {
3144 avpriv_request_sample(mov->fc, "Support for mvhd.timescale = 0 with editlists");
3147 *edit_list_duration = av_rescale(*edit_list_duration, msc->time_scale,
3153 * Find the closest previous frame to the timestamp_pts, in e_old index
3154 * entries. Searching for just any frame / just key frames can be controlled by
3155 * last argument 'flag'.
3156 * Note that if ctts_data is not NULL, we will always search for a key frame
3157 * irrespective of the value of 'flag'. If we don't find any keyframe, we will
3158 * return the first frame of the video.
3160 * Here the timestamp_pts is considered to be a presentation timestamp and
3161 * the timestamp of index entries are considered to be decoding timestamps.
3163 * Returns 0 if successful in finding a frame, else returns -1.
3164 * Places the found index corresponding output arg.
3166 * If ctts_old is not NULL, then refines the searched entry by searching
3167 * backwards from the found timestamp, to find the frame with correct PTS.
3169 * Places the found ctts_index and ctts_sample in corresponding output args.
3171 static int find_prev_closest_index(AVStream *st,
3172 AVIndexEntry *e_old,
3176 int64_t timestamp_pts,
3179 int64_t* ctts_index,
3180 int64_t* ctts_sample)
3182 MOVStreamContext *msc = st->priv_data;
3183 AVIndexEntry *e_keep = st->index_entries;
3184 int nb_keep = st->nb_index_entries;
3186 int64_t index_ctts_count;
3190 // If dts_shift > 0, then all the index timestamps will have to be offset by
3191 // at least dts_shift amount to obtain PTS.
3192 // Hence we decrement the searched timestamp_pts by dts_shift to find the closest index element.
3193 if (msc->dts_shift > 0) {
3194 timestamp_pts -= msc->dts_shift;
3197 st->index_entries = e_old;
3198 st->nb_index_entries = nb_old;
3199 *index = av_index_search_timestamp(st, timestamp_pts, flag | AVSEEK_FLAG_BACKWARD);
3201 // Keep going backwards in the index entries until the timestamp is the same.
3203 for (i = *index; i > 0 && e_old[i].timestamp == e_old[i - 1].timestamp;
3205 if ((flag & AVSEEK_FLAG_ANY) ||
3206 (e_old[i - 1].flags & AVINDEX_KEYFRAME)) {
3212 // If we have CTTS then refine the search, by searching backwards over PTS
3213 // computed by adding corresponding CTTS durations to index timestamps.
3214 if (ctts_data && *index >= 0) {
3215 av_assert0(ctts_index);
3216 av_assert0(ctts_sample);
3217 // Find out the ctts_index for the found frame.
3220 for (index_ctts_count = 0; index_ctts_count < *index; index_ctts_count++) {
3221 if (*ctts_index < ctts_count) {
3223 if (ctts_data[*ctts_index].count == *ctts_sample) {
3230 while (*index >= 0 && (*ctts_index) >= 0 && (*ctts_index) < ctts_count) {
3231 // Find a "key frame" with PTS <= timestamp_pts (So that we can decode B-frames correctly).
3232 // No need to add dts_shift to the timestamp here becase timestamp_pts has already been
3233 // compensated by dts_shift above.
3234 if ((e_old[*index].timestamp + ctts_data[*ctts_index].duration) <= timestamp_pts &&
3235 (e_old[*index].flags & AVINDEX_KEYFRAME)) {
3240 if (*ctts_sample == 0) {
3242 if (*ctts_index >= 0)
3243 *ctts_sample = ctts_data[*ctts_index].count - 1;
3250 /* restore AVStream state*/
3251 st->index_entries = e_keep;
3252 st->nb_index_entries = nb_keep;
3253 return *index >= 0 ? 0 : -1;
3257 * Add index entry with the given values, to the end of st->index_entries.
3258 * Returns the new size st->index_entries if successful, else returns -1.
3260 * This function is similar to ff_add_index_entry in libavformat/utils.c
3261 * except that here we are always unconditionally adding an index entry to
3262 * the end, instead of searching the entries list and skipping the add if
3263 * there is an existing entry with the same timestamp.
3264 * This is needed because the mov_fix_index calls this func with the same
3265 * unincremented timestamp for successive discarded frames.
3267 static int64_t add_index_entry(AVStream *st, int64_t pos, int64_t timestamp,
3268 int size, int distance, int flags)
3270 AVIndexEntry *entries, *ie;
3272 const size_t min_size_needed = (st->nb_index_entries + 1) * sizeof(AVIndexEntry);
3274 // Double the allocation each time, to lower memory fragmentation.
3275 // Another difference from ff_add_index_entry function.
3276 const size_t requested_size =
3277 min_size_needed > st->index_entries_allocated_size ?
3278 FFMAX(min_size_needed, 2 * st->index_entries_allocated_size) :
3281 if((unsigned)st->nb_index_entries + 1 >= UINT_MAX / sizeof(AVIndexEntry))
3284 entries = av_fast_realloc(st->index_entries,
3285 &st->index_entries_allocated_size,
3290 st->index_entries= entries;
3292 index= st->nb_index_entries++;
3293 ie= &entries[index];
3296 ie->timestamp = timestamp;
3297 ie->min_distance= distance;
3304 * Rewrite timestamps of index entries in the range [end_index - frame_duration_buffer_size, end_index)
3305 * by subtracting end_ts successively by the amounts given in frame_duration_buffer.
3307 static void fix_index_entry_timestamps(AVStream* st, int end_index, int64_t end_ts,
3308 int64_t* frame_duration_buffer,
3309 int frame_duration_buffer_size) {
3311 av_assert0(end_index >= 0 && end_index <= st->nb_index_entries);
3312 for (i = 0; i < frame_duration_buffer_size; i++) {
3313 end_ts -= frame_duration_buffer[frame_duration_buffer_size - 1 - i];
3314 st->index_entries[end_index - 1 - i].timestamp = end_ts;
3319 * Append a new ctts entry to ctts_data.
3320 * Returns the new ctts_count if successful, else returns -1.
3322 static int64_t add_ctts_entry(MOVStts** ctts_data, unsigned int* ctts_count, unsigned int* allocated_size,
3323 int count, int duration)
3325 MOVStts *ctts_buf_new;
3326 const size_t min_size_needed = (*ctts_count + 1) * sizeof(MOVStts);
3327 const size_t requested_size =
3328 min_size_needed > *allocated_size ?
3329 FFMAX(min_size_needed, 2 * (*allocated_size)) :
3332 if((unsigned)(*ctts_count) >= UINT_MAX / sizeof(MOVStts) - 1)
3335 ctts_buf_new = av_fast_realloc(*ctts_data, allocated_size, requested_size);
3340 *ctts_data = ctts_buf_new;
3342 ctts_buf_new[*ctts_count].count = count;
3343 ctts_buf_new[*ctts_count].duration = duration;
3345 *ctts_count = (*ctts_count) + 1;
3349 #define MAX_REORDER_DELAY 16
3350 static void mov_estimate_video_delay(MOVContext *c, AVStream* st) {
3351 MOVStreamContext *msc = st->priv_data;
3354 int ctts_sample = 0;
3355 int64_t pts_buf[MAX_REORDER_DELAY + 1]; // Circular buffer to sort pts.
3357 int j, r, num_swaps;
3359 for (j = 0; j < MAX_REORDER_DELAY + 1; j++)
3360 pts_buf[j] = INT64_MIN;
3362 if (st->codecpar->video_delay <= 0 && msc->ctts_data &&
3363 st->codecpar->codec_id == AV_CODEC_ID_H264) {
3364 st->codecpar->video_delay = 0;
3365 for(ind = 0; ind < st->nb_index_entries && ctts_ind < msc->ctts_count; ++ind) {
3366 // Point j to the last elem of the buffer and insert the current pts there.
3368 buf_start = (buf_start + 1);
3369 if (buf_start == MAX_REORDER_DELAY + 1)
3372 pts_buf[j] = st->index_entries[ind].timestamp + msc->ctts_data[ctts_ind].duration;
3374 // The timestamps that are already in the sorted buffer, and are greater than the
3375 // current pts, are exactly the timestamps that need to be buffered to output PTS
3376 // in correct sorted order.
3377 // Hence the video delay (which is the buffer size used to sort DTS and output PTS),
3378 // can be computed as the maximum no. of swaps any particular timestamp needs to
3379 // go through, to keep this buffer in sorted order.
3381 while (j != buf_start) {
3383 if (r < 0) r = MAX_REORDER_DELAY;
3384 if (pts_buf[j] < pts_buf[r]) {
3385 FFSWAP(int64_t, pts_buf[j], pts_buf[r]);
3392 st->codecpar->video_delay = FFMAX(st->codecpar->video_delay, num_swaps);
3395 if (ctts_sample == msc->ctts_data[ctts_ind].count) {
3400 av_log(c->fc, AV_LOG_DEBUG, "Setting codecpar->delay to %d for stream st: %d\n",
3401 st->codecpar->video_delay, st->index);
3405 static void mov_current_sample_inc(MOVStreamContext *sc)
3407 sc->current_sample++;
3408 sc->current_index++;
3409 if (sc->index_ranges &&
3410 sc->current_index >= sc->current_index_range->end &&
3411 sc->current_index_range->end) {
3412 sc->current_index_range++;
3413 sc->current_index = sc->current_index_range->start;
3417 static void mov_current_sample_dec(MOVStreamContext *sc)
3419 sc->current_sample--;
3420 sc->current_index--;
3421 if (sc->index_ranges &&
3422 sc->current_index < sc->current_index_range->start &&
3423 sc->current_index_range > sc->index_ranges) {
3424 sc->current_index_range--;
3425 sc->current_index = sc->current_index_range->end - 1;
3429 static void mov_current_sample_set(MOVStreamContext *sc, int current_sample)
3433 sc->current_sample = current_sample;
3434 sc->current_index = current_sample;
3435 if (!sc->index_ranges) {
3439 for (sc->current_index_range = sc->index_ranges;
3440 sc->current_index_range->end;
3441 sc->current_index_range++) {
3442 range_size = sc->current_index_range->end - sc->current_index_range->start;
3443 if (range_size > current_sample) {
3444 sc->current_index = sc->current_index_range->start + current_sample;
3447 current_sample -= range_size;
3452 * Fix st->index_entries, so that it contains only the entries (and the entries
3453 * which are needed to decode them) that fall in the edit list time ranges.
3454 * Also fixes the timestamps of the index entries to match the timeline
3455 * specified the edit lists.
3457 static void mov_fix_index(MOVContext *mov, AVStream *st)
3459 MOVStreamContext *msc = st->priv_data;
3460 AVIndexEntry *e_old = st->index_entries;
3461 int nb_old = st->nb_index_entries;
3462 const AVIndexEntry *e_old_end = e_old + nb_old;
3463 const AVIndexEntry *current = NULL;
3464 MOVStts *ctts_data_old = msc->ctts_data;
3465 int64_t ctts_index_old = 0;
3466 int64_t ctts_sample_old = 0;
3467 int64_t ctts_count_old = msc->ctts_count;
3468 int64_t edit_list_media_time = 0;
3469 int64_t edit_list_duration = 0;
3470 int64_t frame_duration = 0;
3471 int64_t edit_list_dts_counter = 0;
3472 int64_t edit_list_dts_entry_end = 0;
3473 int64_t edit_list_start_ctts_sample = 0;
3475 int64_t curr_ctts = 0;
3476 int64_t empty_edits_sum_duration = 0;
3477 int64_t edit_list_index = 0;
3480 int64_t start_dts = 0;
3481 int64_t edit_list_start_encountered = 0;
3482 int64_t search_timestamp = 0;
3483 int64_t* frame_duration_buffer = NULL;
3484 int num_discarded_begin = 0;
3485 int first_non_zero_audio_edit = -1;
3486 int packet_skip_samples = 0;
3487 MOVIndexRange *current_index_range;
3489 int found_keyframe_after_edit = 0;
3490 int found_non_empty_edit = 0;
3492 if (!msc->elst_data || msc->elst_count <= 0 || nb_old <= 0) {
3496 // allocate the index ranges array
3497 msc->index_ranges = av_malloc((msc->elst_count + 1) * sizeof(msc->index_ranges[0]));
3498 if (!msc->index_ranges) {
3499 av_log(mov->fc, AV_LOG_ERROR, "Cannot allocate index ranges buffer\n");
3502 msc->current_index_range = msc->index_ranges;
3503 current_index_range = msc->index_ranges - 1;
3505 // Clean AVStream from traces of old index
3506 st->index_entries = NULL;
3507 st->index_entries_allocated_size = 0;
3508 st->nb_index_entries = 0;
3510 // Clean ctts fields of MOVStreamContext
3511 msc->ctts_data = NULL;
3512 msc->ctts_count = 0;
3513 msc->ctts_index = 0;
3514 msc->ctts_sample = 0;
3515 msc->ctts_allocated_size = 0;
3517 // Reinitialize min_corrected_pts so that it can be computed again.
3518 msc->min_corrected_pts = -1;
3520 // If the dts_shift is positive (in case of negative ctts values in mov),
3521 // then negate the DTS by dts_shift
3522 if (msc->dts_shift > 0) {
3523 edit_list_dts_entry_end -= msc->dts_shift;
3524 av_log(mov->fc, AV_LOG_DEBUG, "Shifting DTS by %d because of negative CTTS.\n", msc->dts_shift);
3527 start_dts = edit_list_dts_entry_end;
3529 while (get_edit_list_entry(mov, msc, edit_list_index, &edit_list_media_time,
3530 &edit_list_duration, mov->time_scale)) {
3531 av_log(mov->fc, AV_LOG_DEBUG, "Processing st: %d, edit list %"PRId64" - media time: %"PRId64", duration: %"PRId64"\n",
3532 st->index, edit_list_index, edit_list_media_time, edit_list_duration);
3534 edit_list_dts_counter = edit_list_dts_entry_end;
3535 edit_list_dts_entry_end += edit_list_duration;
3536 num_discarded_begin = 0;
3537 if (!found_non_empty_edit && edit_list_media_time == -1) {
3538 empty_edits_sum_duration += edit_list_duration;
3541 found_non_empty_edit = 1;
3543 // If we encounter a non-negative edit list reset the skip_samples/start_pad fields and set them
3544 // according to the edit list below.
3545 if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
3546 if (first_non_zero_audio_edit < 0) {
3547 first_non_zero_audio_edit = 1;
3549 first_non_zero_audio_edit = 0;
3552 if (first_non_zero_audio_edit > 0)
3553 st->skip_samples = msc->start_pad = 0;
3556 // While reordering frame index according to edit list we must handle properly
3557 // the scenario when edit list entry starts from none key frame.
3558 // We find closest previous key frame and preserve it and consequent frames in index.
3559 // All frames which are outside edit list entry time boundaries will be dropped after decoding.
3560 search_timestamp = edit_list_media_time;
3561 if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
3562 // Audio decoders like AAC need need a decoder delay samples previous to the current sample,
3563 // to correctly decode this frame. Hence for audio we seek to a frame 1 sec. before the
3564 // edit_list_media_time to cover the decoder delay.
3565 search_timestamp = FFMAX(search_timestamp - msc->time_scale, e_old[0].timestamp);
3568 if (find_prev_closest_index(st, e_old, nb_old, ctts_data_old, ctts_count_old, search_timestamp, 0,
3569 &index, &ctts_index_old, &ctts_sample_old) < 0) {
3570 av_log(mov->fc, AV_LOG_WARNING,
3571 "st: %d edit list: %"PRId64" Missing key frame while searching for timestamp: %"PRId64"\n",
3572 st->index, edit_list_index, search_timestamp);
3573 if (find_prev_closest_index(st, e_old, nb_old, ctts_data_old, ctts_count_old, search_timestamp, AVSEEK_FLAG_ANY,
3574 &index, &ctts_index_old, &ctts_sample_old) < 0) {
3575 av_log(mov->fc, AV_LOG_WARNING,
3576 "st: %d edit list %"PRId64" Cannot find an index entry before timestamp: %"PRId64".\n",
3577 st->index, edit_list_index, search_timestamp);
3580 ctts_sample_old = 0;
3583 current = e_old + index;
3584 edit_list_start_ctts_sample = ctts_sample_old;
3586 // Iterate over index and arrange it according to edit list
3587 edit_list_start_encountered = 0;
3588 found_keyframe_after_edit = 0;
3589 for (; current < e_old_end; current++, index++) {
3590 // check if frame outside edit list mark it for discard
3591 frame_duration = (current + 1 < e_old_end) ?
3592 ((current + 1)->timestamp - current->timestamp) : edit_list_duration;
3594 flags = current->flags;
3596 // frames (pts) before or after edit list
3597 curr_cts = current->timestamp + msc->dts_shift;
3600 if (ctts_data_old && ctts_index_old < ctts_count_old) {
3601 curr_ctts = ctts_data_old[ctts_index_old].duration;
3602 av_log(mov->fc, AV_LOG_DEBUG, "stts: %"PRId64" ctts: %"PRId64", ctts_index: %"PRId64", ctts_count: %"PRId64"\n",
3603 curr_cts, curr_ctts, ctts_index_old, ctts_count_old);
3604 curr_cts += curr_ctts;
3606 if (ctts_sample_old == ctts_data_old[ctts_index_old].count) {
3607 if (add_ctts_entry(&msc->ctts_data, &msc->ctts_count,
3608 &msc->ctts_allocated_size,
3609 ctts_data_old[ctts_index_old].count - edit_list_start_ctts_sample,
3610 ctts_data_old[ctts_index_old].duration) == -1) {
3611 av_log(mov->fc, AV_LOG_ERROR, "Cannot add CTTS entry %"PRId64" - {%"PRId64", %d}\n",
3613 ctts_data_old[ctts_index_old].count - edit_list_start_ctts_sample,
3614 ctts_data_old[ctts_index_old].duration);
3618 ctts_sample_old = 0;
3619 edit_list_start_ctts_sample = 0;
3623 if (curr_cts < edit_list_media_time || curr_cts >= (edit_list_duration + edit_list_media_time)) {
3624 if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO && st->codecpar->codec_id != AV_CODEC_ID_VORBIS &&
3625 curr_cts < edit_list_media_time && curr_cts + frame_duration > edit_list_media_time &&
3626 first_non_zero_audio_edit > 0) {
3627 packet_skip_samples = edit_list_media_time - curr_cts;
3628 st->skip_samples += packet_skip_samples;
3630 // Shift the index entry timestamp by packet_skip_samples to be correct.
3631 edit_list_dts_counter -= packet_skip_samples;
3632 if (edit_list_start_encountered == 0) {
3633 edit_list_start_encountered = 1;
3634 // Make timestamps strictly monotonically increasing for audio, by rewriting timestamps for
3635 // discarded packets.
3636 if (frame_duration_buffer) {
3637 fix_index_entry_timestamps(st, st->nb_index_entries, edit_list_dts_counter,
3638 frame_duration_buffer, num_discarded_begin);
3639 av_freep(&frame_duration_buffer);
3643 av_log(mov->fc, AV_LOG_DEBUG, "skip %d audio samples from curr_cts: %"PRId64"\n", packet_skip_samples, curr_cts);
3645 flags |= AVINDEX_DISCARD_FRAME;
3646 av_log(mov->fc, AV_LOG_DEBUG, "drop a frame at curr_cts: %"PRId64" @ %"PRId64"\n", curr_cts, index);
3648 if (edit_list_start_encountered == 0) {
3649 num_discarded_begin++;
3650 frame_duration_buffer = av_realloc(frame_duration_buffer,
3651 num_discarded_begin * sizeof(int64_t));
3652 if (!frame_duration_buffer) {
3653 av_log(mov->fc, AV_LOG_ERROR, "Cannot reallocate frame duration buffer\n");
3656 frame_duration_buffer[num_discarded_begin - 1] = frame_duration;
3658 // Increment skip_samples for the first non-zero audio edit list
3659 if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO &&
3660 first_non_zero_audio_edit > 0 && st->codecpar->codec_id != AV_CODEC_ID_VORBIS) {
3661 st->skip_samples += frame_duration;
3666 if (msc->min_corrected_pts < 0) {
3667 msc->min_corrected_pts = edit_list_dts_counter + curr_ctts + msc->dts_shift;
3669 msc->min_corrected_pts = FFMIN(msc->min_corrected_pts, edit_list_dts_counter + curr_ctts + msc->dts_shift);
3671 if (edit_list_start_encountered == 0) {
3672 edit_list_start_encountered = 1;
3673 // Make timestamps strictly monotonically increasing by rewriting timestamps for
3674 // discarded packets.
3675 if (frame_duration_buffer) {
3676 fix_index_entry_timestamps(st, st->nb_index_entries, edit_list_dts_counter,
3677 frame_duration_buffer, num_discarded_begin);
3678 av_freep(&frame_duration_buffer);
3683 if (add_index_entry(st, current->pos, edit_list_dts_counter, current->size,
3684 current->min_distance, flags) == -1) {
3685 av_log(mov->fc, AV_LOG_ERROR, "Cannot add index entry\n");
3689 // Update the index ranges array
3690 if (current_index_range < msc->index_ranges || index != current_index_range->end) {
3691 current_index_range++;
3692 current_index_range->start = index;
3694 current_index_range->end = index + 1;
3696 // Only start incrementing DTS in frame_duration amounts, when we encounter a frame in edit list.
3697 if (edit_list_start_encountered > 0) {
3698 edit_list_dts_counter = edit_list_dts_counter + frame_duration;
3701 // Break when found first key frame after edit entry completion
3702 if ((curr_cts + frame_duration >= (edit_list_duration + edit_list_media_time)) &&
3703 ((flags & AVINDEX_KEYFRAME) || ((st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO)))) {
3704 if (ctts_data_old) {
3705 // If we have CTTS and this is the first keyframe after edit elist,
3706 // wait for one more, because there might be trailing B-frames after this I-frame
3707 // that do belong to the edit.
3708 if (st->codecpar->codec_type != AVMEDIA_TYPE_AUDIO && found_keyframe_after_edit == 0) {
3709 found_keyframe_after_edit = 1;
3712 if (ctts_sample_old != 0) {
3713 if (add_ctts_entry(&msc->ctts_data, &msc->ctts_count,
3714 &msc->ctts_allocated_size,
3715 ctts_sample_old - edit_list_start_ctts_sample,
3716 ctts_data_old[ctts_index_old].duration) == -1) {
3717 av_log(mov->fc, AV_LOG_ERROR, "Cannot add CTTS entry %"PRId64" - {%"PRId64", %d}\n",
3718 ctts_index_old, ctts_sample_old - edit_list_start_ctts_sample,
3719 ctts_data_old[ctts_index_old].duration);
3728 // If there are empty edits, then msc->min_corrected_pts might be positive
3729 // intentionally. So we subtract the sum duration of emtpy edits here.
3730 msc->min_corrected_pts -= empty_edits_sum_duration;
3732 // If the minimum pts turns out to be greater than zero after fixing the index, then we subtract the
3733 // dts by that amount to make the first pts zero.
3734 if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
3735 if (msc->min_corrected_pts > 0) {
3736 av_log(mov->fc, AV_LOG_DEBUG, "Offset DTS by %"PRId64" to make first pts zero.\n", msc->min_corrected_pts);
3737 for (i = 0; i < st->nb_index_entries; ++i) {
3738 st->index_entries[i].timestamp -= msc->min_corrected_pts;
3742 // Start time should be equal to zero or the duration of any empty edits.
3743 st->start_time = empty_edits_sum_duration;
3745 // Update av stream length, if it ends up shorter than the track's media duration
3746 st->duration = FFMIN(st->duration, edit_list_dts_entry_end - start_dts);
3747 msc->start_pad = st->skip_samples;
3749 // Free the old index and the old CTTS structures
3751 av_free(ctts_data_old);
3752 av_freep(&frame_duration_buffer);
3754 // Null terminate the index ranges array
3755 current_index_range++;
3756 current_index_range->start = 0;
3757 current_index_range->end = 0;
3758 msc->current_index = msc->index_ranges[0].start;
3761 static void mov_build_index(MOVContext *mov, AVStream *st)
3763 MOVStreamContext *sc = st->priv_data;
3764 int64_t current_offset;
3765 int64_t current_dts = 0;
3766 unsigned int stts_index = 0;
3767 unsigned int stsc_index = 0;
3768 unsigned int stss_index = 0;
3769 unsigned int stps_index = 0;
3771 uint64_t stream_size = 0;
3772 MOVStts *ctts_data_old = sc->ctts_data;
3773 unsigned int ctts_count_old = sc->ctts_count;
3775 if (sc->elst_count) {
3776 int i, edit_start_index = 0, multiple_edits = 0;
3777 int64_t empty_duration = 0; // empty duration of the first edit list entry
3778 int64_t start_time = 0; // start time of the media
3780 for (i = 0; i < sc->elst_count; i++) {
3781 const MOVElst *e = &sc->elst_data[i];
3782 if (i == 0 && e->time == -1) {
3783 /* if empty, the first entry is the start time of the stream
3784 * relative to the presentation itself */
3785 empty_duration = e->duration;
3786 edit_start_index = 1;
3787 } else if (i == edit_start_index && e->time >= 0) {
3788 start_time = e->time;
3794 if (multiple_edits && !mov->advanced_editlist)
3795 av_log(mov->fc, AV_LOG_WARNING, "multiple edit list entries, "
3796 "Use -advanced_editlist to correctly decode otherwise "
3797 "a/v desync might occur\n");
3799 /* adjust first dts according to edit list */
3800 if ((empty_duration || start_time) && mov->time_scale > 0) {
3802 empty_duration = av_rescale(empty_duration, sc->time_scale, mov->time_scale);
3803 sc->time_offset = start_time - empty_duration;
3804 sc->min_corrected_pts = start_time;
3805 if (!mov->advanced_editlist)
3806 current_dts = -sc->time_offset;
3809 if (!multiple_edits && !mov->advanced_editlist &&
3810 st->codecpar->codec_id == AV_CODEC_ID_AAC && start_time > 0)
3811 sc->start_pad = start_time;
3814 /* only use old uncompressed audio chunk demuxing when stts specifies it */
3815 if (!(st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO &&
3816 sc->stts_count == 1 && sc->stts_data[0].duration == 1)) {
3817 unsigned int current_sample = 0;
3818 unsigned int stts_sample = 0;
3819 unsigned int sample_size;
3820 unsigned int distance = 0;
3821 unsigned int rap_group_index = 0;
3822 unsigned int rap_group_sample = 0;
3823 int64_t last_dts = 0;
3824 int64_t dts_correction = 0;
3825 int rap_group_present = sc->rap_group_count && sc->rap_group;
3826 int key_off = (sc->keyframe_count && sc->keyframes[0] > 0) || (sc->stps_count && sc->stps_data[0] > 0);
3828 current_dts -= sc->dts_shift;
3829 last_dts = current_dts;
3831 if (!sc->sample_count || st->nb_index_entries)
3833 if (sc->sample_count >= UINT_MAX / sizeof(*st->index_entries) - st->nb_index_entries)
3835 if (av_reallocp_array(&st->index_entries,
3836 st->nb_index_entries + sc->sample_count,
3837 sizeof(*st->index_entries)) < 0) {
3838 st->nb_index_entries = 0;
3841 st->index_entries_allocated_size = (st->nb_index_entries + sc->sample_count) * sizeof(*st->index_entries);
3843 if (ctts_data_old) {
3844 // Expand ctts entries such that we have a 1-1 mapping with samples
3845 if (sc->sample_count >= UINT_MAX / sizeof(*sc->ctts_data))
3848 sc->ctts_allocated_size = 0;
3849 sc->ctts_data = av_fast_realloc(NULL, &sc->ctts_allocated_size,
3850 sc->sample_count * sizeof(*sc->ctts_data));
3851 if (!sc->ctts_data) {
3852 av_free(ctts_data_old);
3856 memset((uint8_t*)(sc->ctts_data), 0, sc->ctts_allocated_size);
3858 for (i = 0; i < ctts_count_old &&
3859 sc->ctts_count < sc->sample_count; i++)
3860 for (j = 0; j < ctts_data_old[i].count &&
3861 sc->ctts_count < sc->sample_count; j++)
3862 add_ctts_entry(&sc->ctts_data, &sc->ctts_count,
3863 &sc->ctts_allocated_size, 1,
3864 ctts_data_old[i].duration);
3865 av_free(ctts_data_old);
3868 for (i = 0; i < sc->chunk_count; i++) {
3869 int64_t next_offset = i+1 < sc->chunk_count ? sc->chunk_offsets[i+1] : INT64_MAX;
3870 current_offset = sc->chunk_offsets[i];
3871 while (mov_stsc_index_valid(stsc_index, sc->stsc_count) &&
3872 i + 1 == sc->stsc_data[stsc_index + 1].first)
3875 if (next_offset > current_offset && sc->sample_size>0 && sc->sample_size < sc->stsz_sample_size &&
3876 sc->stsc_data[stsc_index].count * (int64_t)sc->stsz_sample_size > next_offset - current_offset) {
3877 av_log(mov->fc, AV_LOG_WARNING, "STSZ sample size %d invalid (too large), ignoring\n", sc->stsz_sample_size);
3878 sc->stsz_sample_size = sc->sample_size;
3880 if (sc->stsz_sample_size>0 && sc->stsz_sample_size < sc->sample_size) {
3881 av_log(mov->fc, AV_LOG_WARNING, "STSZ sample size %d invalid (too small), ignoring\n", sc->stsz_sample_size);
3882 sc->stsz_sample_size = sc->sample_size;
3885 for (j = 0; j < sc->stsc_data[stsc_index].count; j++) {
3887 if (current_sample >= sc->sample_count) {
3888 av_log(mov->fc, AV_LOG_ERROR, "wrong sample count\n");
3892 if (!sc->keyframe_absent && (!sc->keyframe_count || current_sample+key_off == sc->keyframes[stss_index])) {
3894 if (stss_index + 1 < sc->keyframe_count)
3896 } else if (sc->stps_count && current_sample+key_off == sc->stps_data[stps_index]) {
3898 if (stps_index + 1 < sc->stps_count)
3901 if (rap_group_present && rap_group_index < sc->rap_group_count) {
3902 if (sc->rap_group[rap_group_index].index > 0)
3904 if (++rap_group_sample == sc->rap_group[rap_group_index].count) {
3905 rap_group_sample = 0;
3909 if (sc->keyframe_absent
3911 && !rap_group_present
3912 && (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO || (i==0 && j==0)))
3916 sample_size = sc->stsz_sample_size > 0 ? sc->stsz_sample_size : sc->sample_sizes[current_sample];
3917 if (sc->pseudo_stream_id == -1 ||
3918 sc->stsc_data[stsc_index].id - 1 == sc->pseudo_stream_id) {
3920 if (sample_size > 0x3FFFFFFF) {
3921 av_log(mov->fc, AV_LOG_ERROR, "Sample size %u is too large\n", sample_size);
3924 e = &st->index_entries[st->nb_index_entries++];
3925 e->pos = current_offset;
3926 e->timestamp = current_dts;
3927 e->size = sample_size;
3928 e->min_distance = distance;
3929 e->flags = keyframe ? AVINDEX_KEYFRAME : 0;
3930 av_log(mov->fc, AV_LOG_TRACE, "AVIndex stream %d, sample %u, offset %"PRIx64", dts %"PRId64", "
3931 "size %u, distance %u, keyframe %d\n", st->index, current_sample,
3932 current_offset, current_dts, sample_size, distance, keyframe);
3933 if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && st->nb_index_entries < 100)
3934 ff_rfps_add_frame(mov->fc, st, current_dts);
3937 current_offset += sample_size;
3938 stream_size += sample_size;
3940 /* A negative sample duration is invalid based on the spec,
3941 * but some samples need it to correct the DTS. */
3942 if (sc->stts_data[stts_index].duration < 0) {
3943 av_log(mov->fc, AV_LOG_WARNING,
3944 "Invalid SampleDelta %d in STTS, at %d st:%d\n",
3945 sc->stts_data[stts_index].duration, stts_index,
3947 dts_correction += sc->stts_data[stts_index].duration - 1;
3948 sc->stts_data[stts_index].duration = 1;
3950 current_dts += sc->stts_data[stts_index].duration;
3951 if (!dts_correction || current_dts + dts_correction > last_dts) {
3952 current_dts += dts_correction;
3955 /* Avoid creating non-monotonous DTS */
3956 dts_correction += current_dts - last_dts - 1;
3957 current_dts = last_dts + 1;
3959 last_dts = current_dts;
3963 if (stts_index + 1 < sc->stts_count && stts_sample == sc->stts_data[stts_index].count) {
3969 if (st->duration > 0)
3970 st->codecpar->bit_rate = stream_size*8*sc->time_scale/st->duration;
3972 unsigned chunk_samples, total = 0;
3974 if (!sc->chunk_count)
3977 // compute total chunk count
3978 for (i = 0; i < sc->stsc_count; i++) {
3979 unsigned count, chunk_count;
3981 chunk_samples = sc->stsc_data[i].count;
3982 if (i != sc->stsc_count - 1 &&
3983 sc->samples_per_frame && chunk_samples % sc->samples_per_frame) {
3984 av_log(mov->fc, AV_LOG_ERROR, "error unaligned chunk\n");
3988 if (sc->samples_per_frame >= 160) { // gsm
3989 count = chunk_samples / sc->samples_per_frame;
3990 } else if (sc->samples_per_frame > 1) {
3991 unsigned samples = (1024/sc->samples_per_frame)*sc->samples_per_frame;
3992 count = (chunk_samples+samples-1) / samples;
3994 count = (chunk_samples+1023) / 1024;
3997 if (mov_stsc_index_valid(i, sc->stsc_count))
3998 chunk_count = sc->stsc_data[i+1].first - sc->stsc_data[i].first;
4000 chunk_count = sc->chunk_count - (sc->stsc_data[i].first - 1);
4001 total += chunk_count * count;
4004 av_log(mov->fc, AV_LOG_TRACE, "chunk count %u\n", total);
4005 if (total >= UINT_MAX / sizeof(*st->index_entries) - st->nb_index_entries)
4007 if (av_reallocp_array(&st->index_entries,
4008 st->nb_index_entries + total,
4009 sizeof(*st->index_entries)) < 0) {
4010 st->nb_index_entries = 0;
4013 st->index_entries_allocated_size = (st->nb_index_entries + total) * sizeof(*st->index_entries);
4016 for (i = 0; i < sc->chunk_count; i++) {
4017 current_offset = sc->chunk_offsets[i];
4018 if (mov_stsc_index_valid(stsc_index, sc->stsc_count) &&
4019 i + 1 == sc->stsc_data[stsc_index + 1].first)
4021 chunk_samples = sc->stsc_data[stsc_index].count;
4023 while (chunk_samples > 0) {
4025 unsigned size, samples;
4027 if (sc->samples_per_frame > 1 && !sc->bytes_per_frame) {
4028 avpriv_request_sample(mov->fc,
4029 "Zero bytes per frame, but %d samples per frame",
4030 sc->samples_per_frame);
4034 if (sc->samples_per_frame >= 160) { // gsm
4035 samples = sc->samples_per_frame;
4036 size = sc->bytes_per_frame;
4038 if (sc->samples_per_frame > 1) {
4039 samples = FFMIN((1024 / sc->samples_per_frame)*
4040 sc->samples_per_frame, chunk_samples);
4041 size = (samples / sc->samples_per_frame) * sc->bytes_per_frame;
4043 samples = FFMIN(1024, chunk_samples);
4044 size = samples * sc->sample_size;
4048 if (st->nb_index_entries >= total) {
4049 av_log(mov->fc, AV_LOG_ERROR, "wrong chunk count %u\n", total);
4052 if (size > 0x3FFFFFFF) {
4053 av_log(mov->fc, AV_LOG_ERROR, "Sample size %u is too large\n", size);
4056 e = &st->index_entries[st->nb_index_entries++];
4057 e->pos = current_offset;
4058 e->timestamp = current_dts;
4060 e->min_distance = 0;
4061 e->flags = AVINDEX_KEYFRAME;
4062 av_log(mov->fc, AV_LOG_TRACE, "AVIndex stream %d, chunk %u, offset %"PRIx64", dts %"PRId64", "
4063 "size %u, duration %u\n", st->index, i, current_offset, current_dts,
4066 current_offset += size;
4067 current_dts += samples;
4068 chunk_samples -= samples;
4073 if (!mov->ignore_editlist && mov->advanced_editlist) {
4074 // Fix index according to edit lists.
4075 mov_fix_index(mov, st);
4078 // Update start time of the stream.
4079 if (st->start_time == AV_NOPTS_VALUE && st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && st->nb_index_entries > 0) {
4080 st->start_time = st->index_entries[0].timestamp + sc->dts_shift;
4081 if (sc->ctts_data) {
4082 st->start_time += sc->ctts_data[0].duration;
4086 mov_estimate_video_delay(mov, st);
4089 static int test_same_origin(const char *src, const char *ref) {
4099 av_url_split(src_proto, sizeof(src_proto), src_auth, sizeof(src_auth), src_host, sizeof(src_host), &src_port, NULL, 0, src);
4100 av_url_split(ref_proto, sizeof(ref_proto), ref_auth, sizeof(ref_auth), ref_host, sizeof(ref_host), &ref_port, NULL, 0, ref);
4102 if (strlen(src) == 0) {
4104 } else if (strlen(src_auth) + 1 >= sizeof(src_auth) ||
4105 strlen(ref_auth) + 1 >= sizeof(ref_auth) ||
4106 strlen(src_host) + 1 >= sizeof(src_host) ||
4107 strlen(ref_host) + 1 >= sizeof(ref_host)) {
4109 } else if (strcmp(src_proto, ref_proto) ||
4110 strcmp(src_auth, ref_auth) ||
4111 strcmp(src_host, ref_host) ||
4112 src_port != ref_port) {
4118 static int mov_open_dref(MOVContext *c, AVIOContext **pb, const char *src, MOVDref *ref)
4120 /* try relative path, we do not try the absolute because it can leak information about our
4121 system to an attacker */
4122 if (ref->nlvl_to > 0 && ref->nlvl_from > 0) {
4123 char filename[1025];
4124 const char *src_path;
4127 /* find a source dir */
4128 src_path = strrchr(src, '/');
4134 /* find a next level down to target */
4135 for (i = 0, l = strlen(ref->path) - 1; l >= 0; l--)
4136 if (ref->path[l] == '/') {
4137 if (i == ref->nlvl_to - 1)
4143 /* compose filename if next level down to target was found */
4144 if (i == ref->nlvl_to - 1 && src_path - src < sizeof(filename)) {
4145 memcpy(filename, src, src_path - src);
4146 filename[src_path - src] = 0;
4148 for (i = 1; i < ref->nlvl_from; i++)
4149 av_strlcat(filename, "../", sizeof(filename));
4151 av_strlcat(filename, ref->path + l + 1, sizeof(filename));
4152 if (!c->use_absolute_path) {
4153 int same_origin = test_same_origin(src, filename);
4156 av_log(c->fc, AV_LOG_ERROR,
4157 "Reference with mismatching origin, %s not tried for security reasons, "
4158 "set demuxer option use_absolute_path to allow it anyway\n",
4160 return AVERROR(ENOENT);
4163 if(strstr(ref->path + l + 1, "..") ||
4164 strstr(ref->path + l + 1, ":") ||
4165 (ref->nlvl_from > 1 && same_origin < 0) ||
4166 (filename[0] == '/' && src_path == src))
4167 return AVERROR(ENOENT);
4170 if (strlen(filename) + 1 == sizeof(filename))
4171 return AVERROR(ENOENT);
4172 if (!c->fc->io_open(c->fc, pb, filename, AVIO_FLAG_READ, NULL))
4175 } else if (c->use_absolute_path) {
4176 av_log(c->fc, AV_LOG_WARNING, "Using absolute path on user request, "
4177 "this is a possible security issue\n");
4178 if (!c->fc->io_open(c->fc, pb, ref->path, AVIO_FLAG_READ, NULL))
4181 av_log(c->fc, AV_LOG_ERROR,
4182 "Absolute path %s not tried for security reasons, "
4183 "set demuxer option use_absolute_path to allow absolute paths\n",
4187 return AVERROR(ENOENT);
4190 static void fix_timescale(MOVContext *c, MOVStreamContext *sc)
4192 if (sc->time_scale <= 0) {
4193 av_log(c->fc, AV_LOG_WARNING, "stream %d, timescale not set\n", sc->ffindex);
4194 sc->time_scale = c->time_scale;
4195 if (sc->time_scale <= 0)
4200 static int mov_read_trak(MOVContext *c, AVIOContext *pb, MOVAtom atom)
4203 MOVStreamContext *sc;
4206 st = avformat_new_stream(c->fc, NULL);
4207 if (!st) return AVERROR(ENOMEM);
4209 sc = av_mallocz(sizeof(MOVStreamContext));
4210 if (!sc) return AVERROR(ENOMEM);
4213 st->codecpar->codec_type = AVMEDIA_TYPE_DATA;
4214 sc->ffindex = st->index;
4215 c->trak_index = st->index;
4217 if ((ret = mov_read_default(c, pb, atom)) < 0)
4222 // Here stsc refers to a chunk not described in stco. This is technically invalid,
4223 // but we can overlook it (clearing stsc) whenever stts_count == 0 (indicating no samples).
4224 if (!sc->chunk_count && !sc->stts_count && sc->stsc_count) {
4226 av_freep(&sc->stsc_data);
4230 if ((sc->chunk_count && (!sc->stts_count || !sc->stsc_count ||
4231 (!sc->sample_size && !sc->sample_count))) ||
4232 (!sc->chunk_count && sc->sample_count)) {
4233 av_log(c->fc, AV_LOG_ERROR, "stream %d, missing mandatory atoms, broken header\n",
4237 if (sc->stsc_count && sc->stsc_data[ sc->stsc_count - 1 ].first > sc->chunk_count) {
4238 av_log(c->fc, AV_LOG_ERROR, "stream %d, contradictionary STSC and STCO\n",
4240 return AVERROR_INVALIDDATA;
4243 fix_timescale(c, sc);
4245 avpriv_set_pts_info(st, 64, 1, sc->time_scale);
4247 mov_build_index(c, st);
4249 if (sc->dref_id-1 < sc->drefs_count && sc->drefs[sc->dref_id-1].path) {
4250 MOVDref *dref = &sc->drefs[sc->dref_id - 1];
4251 if (c->enable_drefs) {
4252 if (mov_open_dref(c, &sc->pb, c->fc->url, dref) < 0)
4253 av_log(c->fc, AV_LOG_ERROR,
4254 "stream %d, error opening alias: path='%s', dir='%s', "
4255 "filename='%s', volume='%s', nlvl_from=%d, nlvl_to=%d\n",
4256 st->index, dref->path, dref->dir, dref->filename,
4257 dref->volume, dref->nlvl_from, dref->nlvl_to);
4259 av_log(c->fc, AV_LOG_WARNING,
4260 "Skipped opening external track: "
4261 "stream %d, alias: path='%s', dir='%s', "
4262 "filename='%s', volume='%s', nlvl_from=%d, nlvl_to=%d."
4263 "Set enable_drefs to allow this.\n",
4264 st->index, dref->path, dref->dir, dref->filename,
4265 dref->volume, dref->nlvl_from, dref->nlvl_to);
4269 sc->pb_is_copied = 1;
4272 if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
4273 if (!st->sample_aspect_ratio.num && st->codecpar->width && st->codecpar->height &&
4274 sc->height && sc->width &&
4275 (st->codecpar->width != sc->width || st->codecpar->height != sc->height)) {
4276 st->sample_aspect_ratio = av_d2q(((double)st->codecpar->height * sc->width) /
4277 ((double)st->codecpar->width * sc->height), INT_MAX);
4280 #if FF_API_R_FRAME_RATE
4281 if (sc->stts_count == 1 || (sc->stts_count == 2 && sc->stts_data[1].count == 1))
4282 av_reduce(&st->r_frame_rate.num, &st->r_frame_rate.den,
4283 sc->time_scale, sc->stts_data[0].duration, INT_MAX);
4287 // done for ai5q, ai52, ai55, ai1q, ai12 and ai15.
4288 if (!st->codecpar->extradata_size && st->codecpar->codec_id == AV_CODEC_ID_H264 &&
4289 TAG_IS_AVCI(st->codecpar->codec_tag)) {
4290 ret = ff_generate_avci_extradata(st);
4295 switch (st->codecpar->codec_id) {
4296 #if CONFIG_H261_DECODER
4297 case AV_CODEC_ID_H261:
4299 #if CONFIG_H263_DECODER
4300 case AV_CODEC_ID_H263:
4302 #if CONFIG_MPEG4_DECODER
4303 case AV_CODEC_ID_MPEG4:
4305 st->codecpar->width = 0; /* let decoder init width/height */
4306 st->codecpar->height= 0;
4310 // If the duration of the mp3 packets is not constant, then they could need a parser
4311 if (st->codecpar->codec_id == AV_CODEC_ID_MP3
4312 && sc->stts_count > 3
4313 && sc->stts_count*10 > st->nb_frames
4314 && sc->time_scale == st->codecpar->sample_rate) {
4315 st->need_parsing = AVSTREAM_PARSE_FULL;
4317 /* Do not need those anymore. */
4318 av_freep(&sc->chunk_offsets);
4319 av_freep(&sc->sample_sizes);
4320 av_freep(&sc->keyframes);
4321 av_freep(&sc->stts_data);
4322 av_freep(&sc->stps_data);
4323 av_freep(&sc->elst_data);
4324 av_freep(&sc->rap_group);
4329 static int mov_read_ilst(MOVContext *c, AVIOContext *pb, MOVAtom atom)
4332 c->itunes_metadata = 1;
4333 ret = mov_read_default(c, pb, atom);
4334 c->itunes_metadata = 0;
4338 static int mov_read_keys(MOVContext *c, AVIOContext *pb, MOVAtom atom)
4347 count = avio_rb32(pb);
4348 if (count > UINT_MAX / sizeof(*c->meta_keys) - 1) {
4349 av_log(c->fc, AV_LOG_ERROR,
4350 "The 'keys' atom with the invalid key count: %"PRIu32"\n", count);
4351 return AVERROR_INVALIDDATA;
4354 c->meta_keys_count = count + 1;
4355 c->meta_keys = av_mallocz(c->meta_keys_count * sizeof(*c->meta_keys));
4357 return AVERROR(ENOMEM);
4359 for (i = 1; i <= count; ++i) {
4360 uint32_t key_size = avio_rb32(pb);
4361 uint32_t type = avio_rl32(pb);
4363 av_log(c->fc, AV_LOG_ERROR,
4364 "The key# %"PRIu32" in meta has invalid size:"
4365 "%"PRIu32"\n", i, key_size);
4366 return AVERROR_INVALIDDATA;
4369 if (type != MKTAG('m','d','t','a')) {
4370 avio_skip(pb, key_size);
4372 c->meta_keys[i] = av_mallocz(key_size + 1);
4373 if (!c->meta_keys[i])
4374 return AVERROR(ENOMEM);
4375 avio_read(pb, c->meta_keys[i], key_size);
4381 static int mov_read_custom(MOVContext *c, AVIOContext *pb, MOVAtom atom)
4383 int64_t end = avio_tell(pb) + atom.size;
4384 uint8_t *key = NULL, *val = NULL, *mean = NULL;
4388 MOVStreamContext *sc;
4390 if (c->fc->nb_streams < 1)
4392 st = c->fc->streams[c->fc->nb_streams-1];
4395 for (i = 0; i < 3; i++) {
4399 if (end - avio_tell(pb) <= 12)
4402 len = avio_rb32(pb);
4403 tag = avio_rl32(pb);
4404 avio_skip(pb, 4); // flags
4406 if (len < 12 || len - 12 > end - avio_tell(pb))
4410 if (tag == MKTAG('m', 'e', 'a', 'n'))
4412 else if (tag == MKTAG('n', 'a', 'm', 'e'))
4414 else if (tag == MKTAG('d', 'a', 't', 'a') && len > 4) {
4424 *p = av_malloc(len + 1);
4426 ret = AVERROR(ENOMEM);
4429 ret = ffio_read_size(pb, *p, len);
4437 if (mean && key && val) {
4438 if (strcmp(key, "iTunSMPB") == 0) {
4439 int priming, remainder, samples;
4440 if(sscanf(val, "%*X %X %X %X", &priming, &remainder, &samples) == 3){
4441 if(priming>0 && priming<16384)
4442 sc->start_pad = priming;
4445 if (strcmp(key, "cdec") != 0) {
4446 av_dict_set(&c->fc->metadata, key, val,
4447 AV_DICT_DONT_STRDUP_KEY | AV_DICT_DONT_STRDUP_VAL);
4451 av_log(c->fc, AV_LOG_VERBOSE,
4452 "Unhandled or malformed custom metadata of size %"PRId64"\n", atom.size);
4455 avio_seek(pb, end, SEEK_SET);
4462 static int mov_read_meta(MOVContext *c, AVIOContext *pb, MOVAtom atom)
4464 while (atom.size > 8) {
4468 tag = avio_rl32(pb);
4470 if (tag == MKTAG('h','d','l','r')) {
4471 avio_seek(pb, -8, SEEK_CUR);
4473 return mov_read_default(c, pb, atom);
4479 // return 1 when matrix is identity, 0 otherwise
4480 #define IS_MATRIX_IDENT(matrix) \
4481 ( (matrix)[0][0] == (1 << 16) && \
4482 (matrix)[1][1] == (1 << 16) && \
4483 (matrix)[2][2] == (1 << 30) && \
4484 !(matrix)[0][1] && !(matrix)[0][2] && \
4485 !(matrix)[1][0] && !(matrix)[1][2] && \
4486 !(matrix)[2][0] && !(matrix)[2][1])
4488 static int mov_read_tkhd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
4493 int display_matrix[3][3];
4494 int res_display_matrix[3][3] = { { 0 } };
4496 MOVStreamContext *sc;
4500 if (c->fc->nb_streams < 1)
4502 st = c->fc->streams[c->fc->nb_streams-1];
4505 // Each stream (trak) should have exactly 1 tkhd. This catches bad files and
4506 // avoids corrupting AVStreams mapped to an earlier tkhd.
4508 return AVERROR_INVALIDDATA;
4510 version = avio_r8(pb);
4511 flags = avio_rb24(pb);
4512 st->disposition |= (flags & MOV_TKHD_FLAG_ENABLED) ? AV_DISPOSITION_DEFAULT : 0;
4518 avio_rb32(pb); /* creation time */
4519 avio_rb32(pb); /* modification time */
4521 st->id = (int)avio_rb32(pb); /* track id (NOT 0 !)*/
4522 avio_rb32(pb); /* reserved */
4524 /* highlevel (considering edits) duration in movie timebase */
4525 (version == 1) ? avio_rb64(pb) : avio_rb32(pb);
4526 avio_rb32(pb); /* reserved */
4527 avio_rb32(pb); /* reserved */
4529 avio_rb16(pb); /* layer */
4530 avio_rb16(pb); /* alternate group */
4531 avio_rb16(pb); /* volume */
4532 avio_rb16(pb); /* reserved */
4534 //read in the display matrix (outlined in ISO 14496-12, Section 6.2.2)
4535 // they're kept in fixed point format through all calculations
4536 // save u,v,z to store the whole matrix in the AV_PKT_DATA_DISPLAYMATRIX
4537 // side data, but the scale factor is not needed to calculate aspect ratio
4538 for (i = 0; i < 3; i++) {
4539 display_matrix[i][0] = avio_rb32(pb); // 16.16 fixed point
4540 display_matrix[i][1] = avio_rb32(pb); // 16.16 fixed point
4541 display_matrix[i][2] = avio_rb32(pb); // 2.30 fixed point
4544 width = avio_rb32(pb); // 16.16 fixed point track width
4545 height = avio_rb32(pb); // 16.16 fixed point track height
4546 sc->width = width >> 16;
4547 sc->height = height >> 16;
4549 // apply the moov display matrix (after the tkhd one)
4550 for (i = 0; i < 3; i++) {
4551 const int sh[3] = { 16, 16, 30 };
4552 for (j = 0; j < 3; j++) {
4553 for (e = 0; e < 3; e++) {
4554 res_display_matrix[i][j] +=
4555 ((int64_t) display_matrix[i][e] *
4556 c->movie_display_matrix[e][j]) >> sh[e];
4561 // save the matrix when it is not the default identity
4562 if (!IS_MATRIX_IDENT(res_display_matrix)) {
4565 av_freep(&sc->display_matrix);
4566 sc->display_matrix = av_malloc(sizeof(int32_t) * 9);
4567 if (!sc->display_matrix)
4568 return AVERROR(ENOMEM);
4570 for (i = 0; i < 3; i++)
4571 for (j = 0; j < 3; j++)
4572 sc->display_matrix[i * 3 + j] = res_display_matrix[i][j];
4574 #if FF_API_OLD_ROTATE_API
4575 rotate = av_display_rotation_get(sc->display_matrix);
4576 if (!isnan(rotate)) {
4577 char rotate_buf[64];
4579 if (rotate < 0) // for backward compatibility
4581 snprintf(rotate_buf, sizeof(rotate_buf), "%g", rotate);
4582 av_dict_set(&st->metadata, "rotate", rotate_buf, 0);
4587 // transform the display width/height according to the matrix
4588 // to keep the same scale, use [width height 1<<16]
4589 if (width && height && sc->display_matrix) {
4590 double disp_transform[2];
4592 for (i = 0; i < 2; i++)
4593 disp_transform[i] = hypot(sc->display_matrix[0 + i],
4594 sc->display_matrix[3 + i]);
4596 if (disp_transform[0] > 0 && disp_transform[1] > 0 &&
4597 disp_transform[0] < (1<<24) && disp_transform[1] < (1<<24) &&
4598 fabs((disp_transform[0] / disp_transform[1]) - 1.0) > 0.01)
4599 st->sample_aspect_ratio = av_d2q(
4600 disp_transform[0] / disp_transform[1],
4606 static int mov_read_tfhd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
4608 MOVFragment *frag = &c->fragment;
4609 MOVTrackExt *trex = NULL;
4610 int flags, track_id, i;
4611 MOVFragmentStreamInfo * frag_stream_info;
4613 avio_r8(pb); /* version */
4614 flags = avio_rb24(pb);
4616 track_id = avio_rb32(pb);
4618 return AVERROR_INVALIDDATA;
4619 for (i = 0; i < c->trex_count; i++)
4620 if (c->trex_data[i].track_id == track_id) {
4621 trex = &c->trex_data[i];
4625 av_log(c->fc, AV_LOG_WARNING, "could not find corresponding trex (id %u)\n", track_id);
4628 c->fragment.found_tfhd = 1;
4629 frag->track_id = track_id;
4630 set_frag_stream(&c->frag_index, track_id);
4632 frag->base_data_offset = flags & MOV_TFHD_BASE_DATA_OFFSET ?
4633 avio_rb64(pb) : flags & MOV_TFHD_DEFAULT_BASE_IS_MOOF ?
4634 frag->moof_offset : frag->implicit_offset;
4635 frag->stsd_id = flags & MOV_TFHD_STSD_ID ? avio_rb32(pb) : trex->stsd_id;
4637 frag->duration = flags & MOV_TFHD_DEFAULT_DURATION ?
4638 avio_rb32(pb) : trex->duration;
4639 frag->size = flags & MOV_TFHD_DEFAULT_SIZE ?
4640 avio_rb32(pb) : trex->size;
4641 frag->flags = flags & MOV_TFHD_DEFAULT_FLAGS ?
4642 avio_rb32(pb) : trex->flags;
4643 av_log(c->fc, AV_LOG_TRACE, "frag flags 0x%x\n", frag->flags);
4645 frag_stream_info = get_current_frag_stream_info(&c->frag_index);
4646 if (frag_stream_info)
4647 frag_stream_info->next_trun_dts = AV_NOPTS_VALUE;
4652 static int mov_read_chap(MOVContext *c, AVIOContext *pb, MOVAtom atom)
4657 num = atom.size / 4;
4658 if (!(new_tracks = av_malloc_array(num, sizeof(int))))
4659 return AVERROR(ENOMEM);
4661 av_free(c->chapter_tracks);
4662 c->chapter_tracks = new_tracks;
4663 c->nb_chapter_tracks = num;
4665 for (i = 0; i < num && !pb->eof_reached; i++)
4666 c->chapter_tracks[i] = avio_rb32(pb);
4671 static int mov_read_trex(MOVContext *c, AVIOContext *pb, MOVAtom atom)
4676 if ((uint64_t)c->trex_count+1 >= UINT_MAX / sizeof(*c->trex_data))
4677 return AVERROR_INVALIDDATA;
4678 if ((err = av_reallocp_array(&c->trex_data, c->trex_count + 1,
4679 sizeof(*c->trex_data))) < 0) {
4684 c->fc->duration = AV_NOPTS_VALUE; // the duration from mvhd is not representing the whole file when fragments are used.
4686 trex = &c->trex_data[c->trex_count++];
4687 avio_r8(pb); /* version */
4688 avio_rb24(pb); /* flags */
4689 trex->track_id = avio_rb32(pb);
4690 trex->stsd_id = avio_rb32(pb);
4691 trex->duration = avio_rb32(pb);
4692 trex->size = avio_rb32(pb);
4693 trex->flags = avio_rb32(pb);
4697 static int mov_read_tfdt(MOVContext *c, AVIOContext *pb, MOVAtom atom)
4699 MOVFragment *frag = &c->fragment;
4700 AVStream *st = NULL;
4701 MOVStreamContext *sc;
4703 MOVFragmentStreamInfo * frag_stream_info;
4704 int64_t base_media_decode_time;
4706 for (i = 0; i < c->fc->nb_streams; i++) {
4707 if (c->fc->streams[i]->id == frag->track_id) {
4708 st = c->fc->streams[i];
4713 av_log(c->fc, AV_LOG_WARNING, "could not find corresponding track id %u\n", frag->track_id);
4717 if (sc->pseudo_stream_id + 1 != frag->stsd_id && sc->pseudo_stream_id != -1)
4719 version = avio_r8(pb);
4720 avio_rb24(pb); /* flags */
4722 base_media_decode_time = avio_rb64(pb);
4724 base_media_decode_time = avio_rb32(pb);
4727 frag_stream_info = get_current_frag_stream_info(&c->frag_index);
4728 if (frag_stream_info)
4729 frag_stream_info->tfdt_dts = base_media_decode_time;
4730 sc->track_end = base_media_decode_time;
4735 static int mov_read_trun(MOVContext *c, AVIOContext *pb, MOVAtom atom)
4737 MOVFragment *frag = &c->fragment;
4738 AVStream *st = NULL;
4739 MOVStreamContext *sc;
4742 int64_t dts, pts = AV_NOPTS_VALUE;
4743 int data_offset = 0;
4744 unsigned entries, first_sample_flags = frag->flags;
4745 int flags, distance, i;
4746 int64_t prev_dts = AV_NOPTS_VALUE;
4747 int next_frag_index = -1, index_entry_pos;
4748 size_t requested_size;
4749 size_t old_ctts_allocated_size;
4750 AVIndexEntry *new_entries;
4751 MOVFragmentStreamInfo * frag_stream_info;
4753 if (!frag->found_tfhd) {
4754 av_log(c->fc, AV_LOG_ERROR, "trun track id unknown, no tfhd was found\n");
4755 return AVERROR_INVALIDDATA;
4758 for (i = 0; i < c->fc->nb_streams; i++) {
4759 if (c->fc->streams[i]->id == frag->track_id) {
4760 st = c->fc->streams[i];
4765 av_log(c->fc, AV_LOG_WARNING, "could not find corresponding track id %u\n", frag->track_id);
4769 if (sc->pseudo_stream_id+1 != frag->stsd_id && sc->pseudo_stream_id != -1)
4772 // Find the next frag_index index that has a valid index_entry for
4773 // the current track_id.
4775 // A valid index_entry means the trun for the fragment was read
4776 // and it's samples are in index_entries at the given position.
4777 // New index entries will be inserted before the index_entry found.
4778 index_entry_pos = st->nb_index_entries;
4779 for (i = c->frag_index.current + 1; i < c->frag_index.nb_items; i++) {
4780 frag_stream_info = get_frag_stream_info(&c->frag_index, i, frag->track_id);
4781 if (frag_stream_info && frag_stream_info->index_entry >= 0) {
4782 next_frag_index = i;
4783 index_entry_pos = frag_stream_info->index_entry;
4787 av_assert0(index_entry_pos <= st->nb_index_entries);
4789 avio_r8(pb); /* version */
4790 flags = avio_rb24(pb);
4791 entries = avio_rb32(pb);
4792 av_log(c->fc, AV_LOG_TRACE, "flags 0x%x entries %u\n", flags, entries);
4794 if ((uint64_t)entries+sc->ctts_count >= UINT_MAX/sizeof(*sc->ctts_data))
4795 return AVERROR_INVALIDDATA;
4796 if (flags & MOV_TRUN_DATA_OFFSET) data_offset = avio_rb32(pb);
4797 if (flags & MOV_TRUN_FIRST_SAMPLE_FLAGS) first_sample_flags = avio_rb32(pb);
4799 frag_stream_info = get_current_frag_stream_info(&c->frag_index);
4800 if (frag_stream_info)
4802 if (frag_stream_info->next_trun_dts != AV_NOPTS_VALUE) {
4803 dts = frag_stream_info->next_trun_dts - sc->time_offset;
4804 } else if (frag_stream_info->first_tfra_pts != AV_NOPTS_VALUE &&
4805 c->use_mfra_for == FF_MOV_FLAG_MFRA_PTS) {
4806 pts = frag_stream_info->first_tfra_pts;
4807 av_log(c->fc, AV_LOG_DEBUG, "found mfra time %"PRId64
4808 ", using it for pts\n", pts);
4809 } else if (frag_stream_info->first_tfra_pts != AV_NOPTS_VALUE &&
4810 c->use_mfra_for == FF_MOV_FLAG_MFRA_DTS) {
4811 dts = frag_stream_info->first_tfra_pts;
4812 av_log(c->fc, AV_LOG_DEBUG, "found mfra time %"PRId64
4813 ", using it for dts\n", pts);
4814 } else if (frag_stream_info->sidx_pts != AV_NOPTS_VALUE) {
4815 // FIXME: sidx earliest_presentation_time is *PTS*, s.b.
4816 // pts = frag_stream_info->sidx_pts;
4817 dts = frag_stream_info->sidx_pts - sc->time_offset;
4818 av_log(c->fc, AV_LOG_DEBUG, "found sidx time %"PRId64
4819 ", using it for pts\n", pts);
4820 } else if (frag_stream_info->tfdt_dts != AV_NOPTS_VALUE) {
4821 dts = frag_stream_info->tfdt_dts - sc->time_offset;
4822 av_log(c->fc, AV_LOG_DEBUG, "found tfdt time %"PRId64
4823 ", using it for dts\n", dts);
4825 dts = sc->track_end - sc->time_offset;
4826 av_log(c->fc, AV_LOG_DEBUG, "found track end time %"PRId64
4827 ", using it for dts\n", dts);
4830 dts = sc->track_end - sc->time_offset;
4831 av_log(c->fc, AV_LOG_DEBUG, "found track end time %"PRId64
4832 ", using it for dts\n", dts);
4834 offset = frag->base_data_offset + data_offset;
4836 av_log(c->fc, AV_LOG_TRACE, "first sample flags 0x%x\n", first_sample_flags);
4838 // realloc space for new index entries
4839 if((uint64_t)st->nb_index_entries + entries >= UINT_MAX / sizeof(AVIndexEntry)) {
4840 entries = UINT_MAX / sizeof(AVIndexEntry) - st->nb_index_entries;
4841 av_log(c->fc, AV_LOG_ERROR, "Failed to add index entry\n");
4846 requested_size = (st->nb_index_entries + entries) * sizeof(AVIndexEntry);
4847 new_entries = av_fast_realloc(st->index_entries,
4848 &st->index_entries_allocated_size,
4851 return AVERROR(ENOMEM);
4852 st->index_entries= new_entries;
4854 requested_size = (st->nb_index_entries + entries) * sizeof(*sc->ctts_data);
4855 old_ctts_allocated_size = sc->ctts_allocated_size;
4856 ctts_data = av_fast_realloc(sc->ctts_data, &sc->ctts_allocated_size,
4859 return AVERROR(ENOMEM);
4860 sc->ctts_data = ctts_data;
4862 // In case there were samples without ctts entries, ensure they get
4863 // zero valued entries. This ensures clips which mix boxes with and
4864 // without ctts entries don't pickup uninitialized data.
4865 memset((uint8_t*)(sc->ctts_data) + old_ctts_allocated_size, 0,
4866 sc->ctts_allocated_size - old_ctts_allocated_size);
4868 if (index_entry_pos < st->nb_index_entries) {
4869 // Make hole in index_entries and ctts_data for new samples
4870 memmove(st->index_entries + index_entry_pos + entries,
4871 st->index_entries + index_entry_pos,
4872 sizeof(*st->index_entries) *
4873 (st->nb_index_entries - index_entry_pos));
4874 memmove(sc->ctts_data + index_entry_pos + entries,
4875 sc->ctts_data + index_entry_pos,
4876 sizeof(*sc->ctts_data) * (sc->ctts_count - index_entry_pos));
4877 if (index_entry_pos < sc->current_sample) {
4878 sc->current_sample += entries;
4882 st->nb_index_entries += entries;
4883 sc->ctts_count = st->nb_index_entries;
4885 // Record the index_entry position in frag_index of this fragment
4886 if (frag_stream_info)
4887 frag_stream_info->index_entry = index_entry_pos;
4889 if (index_entry_pos > 0)
4890 prev_dts = st->index_entries[index_entry_pos-1].timestamp;
4892 for (i = 0; i < entries && !pb->eof_reached; i++) {
4893 unsigned sample_size = frag->size;
4894 int sample_flags = i ? frag->flags : first_sample_flags;
4895 unsigned sample_duration = frag->duration;
4896 unsigned ctts_duration = 0;
4898 int index_entry_flags = 0;
4900 if (flags & MOV_TRUN_SAMPLE_DURATION) sample_duration = avio_rb32(pb);
4901 if (flags & MOV_TRUN_SAMPLE_SIZE) sample_size = avio_rb32(pb);
4902 if (flags & MOV_TRUN_SAMPLE_FLAGS) sample_flags = avio_rb32(pb);
4903 if (flags & MOV_TRUN_SAMPLE_CTS) ctts_duration = avio_rb32(pb);
4905 mov_update_dts_shift(sc, ctts_duration, c->fc);
4906 if (pts != AV_NOPTS_VALUE) {
4907 dts = pts - sc->dts_shift;
4908 if (flags & MOV_TRUN_SAMPLE_CTS) {
4909 dts -= ctts_duration;
4911 dts -= sc->time_offset;
4913 av_log(c->fc, AV_LOG_DEBUG,
4914 "pts %"PRId64" calculated dts %"PRId64
4915 " sc->dts_shift %d ctts.duration %d"
4916 " sc->time_offset %"PRId64
4917 " flags & MOV_TRUN_SAMPLE_CTS %d\n",
4919 sc->dts_shift, ctts_duration,
4920 sc->time_offset, flags & MOV_TRUN_SAMPLE_CTS);
4921 pts = AV_NOPTS_VALUE;
4924 if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO)
4928 !(sample_flags & (MOV_FRAG_SAMPLE_FLAG_IS_NON_SYNC |
4929 MOV_FRAG_SAMPLE_FLAG_DEPENDS_YES));
4932 index_entry_flags |= AVINDEX_KEYFRAME;
4934 // Fragments can overlap in time. Discard overlapping frames after
4936 if (prev_dts >= dts)
4937 index_entry_flags |= AVINDEX_DISCARD_FRAME;
4939 st->index_entries[index_entry_pos].pos = offset;
4940 st->index_entries[index_entry_pos].timestamp = dts;
4941 st->index_entries[index_entry_pos].size= sample_size;
4942 st->index_entries[index_entry_pos].min_distance= distance;
4943 st->index_entries[index_entry_pos].flags = index_entry_flags;
4945 sc->ctts_data[index_entry_pos].count = 1;
4946 sc->ctts_data[index_entry_pos].duration = ctts_duration;
4949 av_log(c->fc, AV_LOG_TRACE, "AVIndex stream %d, sample %d, offset %"PRIx64", dts %"PRId64", "
4950 "size %u, distance %d, keyframe %d\n", st->index,
4951 index_entry_pos, offset, dts, sample_size, distance, keyframe);
4953 dts += sample_duration;
4954 offset += sample_size;
4955 sc->data_size += sample_size;
4957 if (sample_duration <= INT64_MAX - sc->duration_for_fps &&
4958 1 <= INT_MAX - sc->nb_frames_for_fps
4960 sc->duration_for_fps += sample_duration;
4961 sc->nb_frames_for_fps ++;
4964 if (frag_stream_info)
4965 frag_stream_info->next_trun_dts = dts + sc->time_offset;
4967 // EOF found before reading all entries. Fix the hole this would
4968 // leave in index_entries and ctts_data
4969 int gap = entries - i;
4970 memmove(st->index_entries + index_entry_pos,
4971 st->index_entries + index_entry_pos + gap,
4972 sizeof(*st->index_entries) *
4973 (st->nb_index_entries - (index_entry_pos + gap)));
4974 memmove(sc->ctts_data + index_entry_pos,
4975 sc->ctts_data + index_entry_pos + gap,
4976 sizeof(*sc->ctts_data) *
4977 (sc->ctts_count - (index_entry_pos + gap)));
4979 st->nb_index_entries -= gap;
4980 sc->ctts_count -= gap;
4981 if (index_entry_pos < sc->current_sample) {
4982 sc->current_sample -= gap;
4987 // The end of this new fragment may overlap in time with the start
4988 // of the next fragment in index_entries. Mark the samples in the next
4989 // fragment that overlap with AVINDEX_DISCARD_FRAME
4990 prev_dts = AV_NOPTS_VALUE;
4991 if (index_entry_pos > 0)
4992 prev_dts = st->index_entries[index_entry_pos-1].timestamp;
4993 for (i = index_entry_pos; i < st->nb_index_entries; i++) {
4994 if (prev_dts < st->index_entries[i].timestamp)
4996 st->index_entries[i].flags |= AVINDEX_DISCARD_FRAME;
4999 // If a hole was created to insert the new index_entries into,
5000 // the index_entry recorded for all subsequent moof must
5001 // be incremented by the number of entries inserted.
5002 fix_frag_index_entries(&c->frag_index, next_frag_index,
5003 frag->track_id, entries);
5005 if (pb->eof_reached) {
5006 av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted TRUN atom\n");
5010 frag->implicit_offset = offset;
5012 sc->track_end = dts + sc->time_offset;
5013 if (st->duration < sc->track_end)
5014 st->duration = sc->track_end;
5019 static int mov_read_sidx(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5021 int64_t offset = avio_tell(pb) + atom.size, pts, timestamp;
5023 unsigned i, j, track_id, item_count;
5024 AVStream *st = NULL;
5025 AVStream *ref_st = NULL;
5026 MOVStreamContext *sc, *ref_sc = NULL;
5027 AVRational timescale;
5029 version = avio_r8(pb);
5031 avpriv_request_sample(c->fc, "sidx version %u", version);
5035 avio_rb24(pb); // flags
5037 track_id = avio_rb32(pb); // Reference ID
5038 for (i = 0; i < c->fc->nb_streams; i++) {
5039 if (c->fc->streams[i]->id == track_id) {
5040 st = c->fc->streams[i];
5045 av_log(c->fc, AV_LOG_WARNING, "could not find corresponding track id %d\n", track_id);
5051 timescale = av_make_q(1, avio_rb32(pb));
5053 if (timescale.den <= 0) {
5054 av_log(c->fc, AV_LOG_ERROR, "Invalid sidx timescale 1/%d\n", timescale.den);
5055 return AVERROR_INVALIDDATA;
5059 pts = avio_rb32(pb);
5060 offset += avio_rb32(pb);
5062 pts = avio_rb64(pb);
5063 offset += avio_rb64(pb);
5066 avio_rb16(pb); // reserved
5068 item_count = avio_rb16(pb);
5070 for (i = 0; i < item_count; i++) {
5072 MOVFragmentStreamInfo * frag_stream_info;
5073 uint32_t size = avio_rb32(pb);
5074 uint32_t duration = avio_rb32(pb);
5075 if (size & 0x80000000) {
5076 avpriv_request_sample(c->fc, "sidx reference_type 1");
5077 return AVERROR_PATCHWELCOME;
5079 avio_rb32(pb); // sap_flags
5080 timestamp = av_rescale_q(pts, timescale, st->time_base);
5082 index = update_frag_index(c, offset);
5083 frag_stream_info = get_frag_stream_info(&c->frag_index, index, track_id);
5084 if (frag_stream_info)
5085 frag_stream_info->sidx_pts = timestamp;
5091 st->duration = sc->track_end = pts;
5095 if (offset == avio_size(pb)) {
5096 // Find first entry in fragment index that came from an sidx.
5097 // This will pretty much always be the first entry.
5098 for (i = 0; i < c->frag_index.nb_items; i++) {
5099 MOVFragmentIndexItem * item = &c->frag_index.item[i];
5100 for (j = 0; ref_st == NULL && j < item->nb_stream_info; j++) {
5101 MOVFragmentStreamInfo * si;
5102 si = &item->stream_info[j];
5103 if (si->sidx_pts != AV_NOPTS_VALUE) {
5104 ref_st = c->fc->streams[j];
5105 ref_sc = ref_st->priv_data;
5110 if (ref_st) for (i = 0; i < c->fc->nb_streams; i++) {
5111 st = c->fc->streams[i];
5113 if (!sc->has_sidx) {
5114 st->duration = sc->track_end = av_rescale(ref_st->duration, sc->time_scale, ref_sc->time_scale);
5118 c->frag_index.complete = 1;
5124 /* this atom should be null (from specs), but some buggy files put the 'moov' atom inside it... */
5125 /* like the files created with Adobe Premiere 5.0, for samples see */
5126 /* http://graphics.tudelft.nl/~wouter/publications/soundtests/ */
5127 static int mov_read_wide(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5132 return 0; /* continue */
5133 if (avio_rb32(pb) != 0) { /* 0 sized mdat atom... use the 'wide' atom size */
5134 avio_skip(pb, atom.size - 4);
5137 atom.type = avio_rl32(pb);
5139 if (atom.type != MKTAG('m','d','a','t')) {
5140 avio_skip(pb, atom.size);
5143 err = mov_read_mdat(c, pb, atom);
5147 static int mov_read_cmov(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5152 uint8_t *moov_data; /* uncompressed data */
5153 long cmov_len, moov_len;
5156 avio_rb32(pb); /* dcom atom */
5157 if (avio_rl32(pb) != MKTAG('d','c','o','m'))
5158 return AVERROR_INVALIDDATA;
5159 if (avio_rl32(pb) != MKTAG('z','l','i','b')) {
5160 av_log(c->fc, AV_LOG_ERROR, "unknown compression for cmov atom !\n");
5161 return AVERROR_INVALIDDATA;
5163 avio_rb32(pb); /* cmvd atom */
5164 if (avio_rl32(pb) != MKTAG('c','m','v','d'))
5165 return AVERROR_INVALIDDATA;
5166 moov_len = avio_rb32(pb); /* uncompressed size */
5167 cmov_len = atom.size - 6 * 4;
5169 cmov_data = av_malloc(cmov_len);
5171 return AVERROR(ENOMEM);
5172 moov_data = av_malloc(moov_len);
5175 return AVERROR(ENOMEM);
5177 ret = ffio_read_size(pb, cmov_data, cmov_len);
5179 goto free_and_return;
5181 ret = AVERROR_INVALIDDATA;
5182 if (uncompress (moov_data, (uLongf *) &moov_len, (const Bytef *)cmov_data, cmov_len) != Z_OK)
5183 goto free_and_return;
5184 if (ffio_init_context(&ctx, moov_data, moov_len, 0, NULL, NULL, NULL, NULL) != 0)
5185 goto free_and_return;
5186 ctx.seekable = AVIO_SEEKABLE_NORMAL;
5187 atom.type = MKTAG('m','o','o','v');
5188 atom.size = moov_len;
5189 ret = mov_read_default(c, &ctx, atom);
5195 av_log(c->fc, AV_LOG_ERROR, "this file requires zlib support compiled in\n");
5196 return AVERROR(ENOSYS);
5200 /* edit list atom */
5201 static int mov_read_elst(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5203 MOVStreamContext *sc;
5204 int i, edit_count, version;
5205 int64_t elst_entry_size;
5207 if (c->fc->nb_streams < 1 || c->ignore_editlist)
5209 sc = c->fc->streams[c->fc->nb_streams-1]->priv_data;
5211 version = avio_r8(pb); /* version */
5212 avio_rb24(pb); /* flags */
5213 edit_count = avio_rb32(pb); /* entries */
5216 elst_entry_size = version == 1 ? 20 : 12;
5217 if (atom.size != edit_count * elst_entry_size) {
5218 if (c->fc->strict_std_compliance >= FF_COMPLIANCE_STRICT) {
5219 av_log(c->fc, AV_LOG_ERROR, "Invalid edit list entry_count: %d for elst atom of size: %"PRId64" bytes.\n",
5220 edit_count, atom.size + 8);
5221 return AVERROR_INVALIDDATA;
5223 edit_count = atom.size / elst_entry_size;
5224 if (edit_count * elst_entry_size != atom.size) {
5225 av_log(c->fc, AV_LOG_WARNING, "ELST atom of %"PRId64" bytes, bigger than %d entries.", atom.size, edit_count);
5233 av_log(c->fc, AV_LOG_WARNING, "Duplicated ELST atom\n");
5234 av_free(sc->elst_data);
5236 sc->elst_data = av_malloc_array(edit_count, sizeof(*sc->elst_data));
5238 return AVERROR(ENOMEM);
5240 av_log(c->fc, AV_LOG_TRACE, "track[%u].edit_count = %i\n", c->fc->nb_streams - 1, edit_count);
5241 for (i = 0; i < edit_count && atom.size > 0 && !pb->eof_reached; i++) {
5242 MOVElst *e = &sc->elst_data[i];
5245 e->duration = avio_rb64(pb);
5246 e->time = avio_rb64(pb);
5249 e->duration = avio_rb32(pb); /* segment duration */
5250 e->time = (int32_t)avio_rb32(pb); /* media time */
5253 e->rate = avio_rb32(pb) / 65536.0;
5255 av_log(c->fc, AV_LOG_TRACE, "duration=%"PRId64" time=%"PRId64" rate=%f\n",
5256 e->duration, e->time, e->rate);
5258 if (e->time < 0 && e->time != -1 &&
5259 c->fc->strict_std_compliance >= FF_COMPLIANCE_STRICT) {
5260 av_log(c->fc, AV_LOG_ERROR, "Track %d, edit %d: Invalid edit list media time=%"PRId64"\n",
5261 c->fc->nb_streams-1, i, e->time);
5262 return AVERROR_INVALIDDATA;
5270 static int mov_read_tmcd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5272 MOVStreamContext *sc;
5274 if (c->fc->nb_streams < 1)
5275 return AVERROR_INVALIDDATA;
5276 sc = c->fc->streams[c->fc->nb_streams - 1]->priv_data;
5277 sc->timecode_track = avio_rb32(pb);
5281 static int mov_read_av1c(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5286 if (c->fc->nb_streams < 1)
5288 st = c->fc->streams[c->fc->nb_streams - 1];
5290 if (atom.size < 4) {
5291 av_log(c->fc, AV_LOG_ERROR, "Empty AV1 Codec Configuration Box\n");
5292 return AVERROR_INVALIDDATA;
5295 /* For now, propagate only the OBUs, if any. Once libavcodec is
5296 updated to handle isobmff style extradata this can be removed. */
5302 ret = ff_get_extradata(c->fc, st->codecpar, pb, atom.size - 4);
5309 static int mov_read_vpcc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5312 int version, color_range, color_primaries, color_trc, color_space;
5314 if (c->fc->nb_streams < 1)
5316 st = c->fc->streams[c->fc->nb_streams - 1];
5318 if (atom.size < 5) {
5319 av_log(c->fc, AV_LOG_ERROR, "Empty VP Codec Configuration box\n");
5320 return AVERROR_INVALIDDATA;
5323 version = avio_r8(pb);
5325 av_log(c->fc, AV_LOG_WARNING, "Unsupported VP Codec Configuration box version %d\n", version);
5328 avio_skip(pb, 3); /* flags */
5330 avio_skip(pb, 2); /* profile + level */
5331 color_range = avio_r8(pb); /* bitDepth, chromaSubsampling, videoFullRangeFlag */
5332 color_primaries = avio_r8(pb);
5333 color_trc = avio_r8(pb);
5334 color_space = avio_r8(pb);
5335 if (avio_rb16(pb)) /* codecIntializationDataSize */
5336 return AVERROR_INVALIDDATA;
5338 if (!av_color_primaries_name(color_primaries))
5339 color_primaries = AVCOL_PRI_UNSPECIFIED;
5340 if (!av_color_transfer_name(color_trc))
5341 color_trc = AVCOL_TRC_UNSPECIFIED;
5342 if (!av_color_space_name(color_space))
5343 color_space = AVCOL_SPC_UNSPECIFIED;
5345 st->codecpar->color_range = (color_range & 1) ? AVCOL_RANGE_JPEG : AVCOL_RANGE_MPEG;
5346 st->codecpar->color_primaries = color_primaries;
5347 st->codecpar->color_trc = color_trc;
5348 st->codecpar->color_space = color_space;
5353 static int mov_read_smdm(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5355 MOVStreamContext *sc;
5358 if (c->fc->nb_streams < 1)
5359 return AVERROR_INVALIDDATA;
5361 sc = c->fc->streams[c->fc->nb_streams - 1]->priv_data;
5363 if (atom.size < 5) {
5364 av_log(c->fc, AV_LOG_ERROR, "Empty Mastering Display Metadata box\n");
5365 return AVERROR_INVALIDDATA;
5368 version = avio_r8(pb);
5370 av_log(c->fc, AV_LOG_WARNING, "Unsupported Mastering Display Metadata box version %d\n", version);
5373 avio_skip(pb, 3); /* flags */
5375 sc->mastering = av_mastering_display_metadata_alloc();
5377 return AVERROR(ENOMEM);
5379 for (i = 0; i < 3; i++) {
5380 sc->mastering->display_primaries[i][0] = av_make_q(avio_rb16(pb), 1 << 16);
5381 sc->mastering->display_primaries[i][1] = av_make_q(avio_rb16(pb), 1 << 16);
5383 sc->mastering->white_point[0] = av_make_q(avio_rb16(pb), 1 << 16);
5384 sc->mastering->white_point[1] = av_make_q(avio_rb16(pb), 1 << 16);
5386 sc->mastering->max_luminance = av_make_q(avio_rb32(pb), 1 << 8);
5387 sc->mastering->min_luminance = av_make_q(avio_rb32(pb), 1 << 14);
5389 sc->mastering->has_primaries = 1;
5390 sc->mastering->has_luminance = 1;
5395 static int mov_read_mdcv(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5397 MOVStreamContext *sc;
5398 const int mapping[3] = {1, 2, 0};
5399 const int chroma_den = 50000;
5400 const int luma_den = 10000;
5403 if (c->fc->nb_streams < 1)
5404 return AVERROR_INVALIDDATA;
5406 sc = c->fc->streams[c->fc->nb_streams - 1]->priv_data;
5408 if (atom.size < 24) {
5409 av_log(c->fc, AV_LOG_ERROR, "Invalid Mastering Display Color Volume box\n");
5410 return AVERROR_INVALIDDATA;
5413 sc->mastering = av_mastering_display_metadata_alloc();
5415 return AVERROR(ENOMEM);
5417 for (i = 0; i < 3; i++) {
5418 const int j = mapping[i];
5419 sc->mastering->display_primaries[j][0] = av_make_q(avio_rb16(pb), chroma_den);
5420 sc->mastering->display_primaries[j][1] = av_make_q(avio_rb16(pb), chroma_den);
5422 sc->mastering->white_point[0] = av_make_q(avio_rb16(pb), chroma_den);
5423 sc->mastering->white_point[1] = av_make_q(avio_rb16(pb), chroma_den);
5425 sc->mastering->max_luminance = av_make_q(avio_rb32(pb), luma_den);
5426 sc->mastering->min_luminance = av_make_q(avio_rb32(pb), luma_den);
5428 sc->mastering->has_luminance = 1;
5429 sc->mastering->has_primaries = 1;
5434 static int mov_read_coll(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5436 MOVStreamContext *sc;
5439 if (c->fc->nb_streams < 1)
5440 return AVERROR_INVALIDDATA;
5442 sc = c->fc->streams[c->fc->nb_streams - 1]->priv_data;
5444 if (atom.size < 5) {
5445 av_log(c->fc, AV_LOG_ERROR, "Empty Content Light Level box\n");
5446 return AVERROR_INVALIDDATA;
5449 version = avio_r8(pb);
5451 av_log(c->fc, AV_LOG_WARNING, "Unsupported Content Light Level box version %d\n", version);
5454 avio_skip(pb, 3); /* flags */
5456 sc->coll = av_content_light_metadata_alloc(&sc->coll_size);
5458 return AVERROR(ENOMEM);
5460 sc->coll->MaxCLL = avio_rb16(pb);
5461 sc->coll->MaxFALL = avio_rb16(pb);
5466 static int mov_read_clli(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5468 MOVStreamContext *sc;
5470 if (c->fc->nb_streams < 1)
5471 return AVERROR_INVALIDDATA;
5473 sc = c->fc->streams[c->fc->nb_streams - 1]->priv_data;
5475 if (atom.size < 4) {
5476 av_log(c->fc, AV_LOG_ERROR, "Empty Content Light Level Info box\n");
5477 return AVERROR_INVALIDDATA;
5480 sc->coll = av_content_light_metadata_alloc(&sc->coll_size);
5482 return AVERROR(ENOMEM);
5484 sc->coll->MaxCLL = avio_rb16(pb);
5485 sc->coll->MaxFALL = avio_rb16(pb);
5490 static int mov_read_st3d(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5493 MOVStreamContext *sc;
5494 enum AVStereo3DType type;
5497 if (c->fc->nb_streams < 1)
5500 st = c->fc->streams[c->fc->nb_streams - 1];
5503 if (atom.size < 5) {
5504 av_log(c->fc, AV_LOG_ERROR, "Empty stereoscopic video box\n");
5505 return AVERROR_INVALIDDATA;
5507 avio_skip(pb, 4); /* version + flags */
5512 type = AV_STEREO3D_2D;
5515 type = AV_STEREO3D_TOPBOTTOM;
5518 type = AV_STEREO3D_SIDEBYSIDE;
5521 av_log(c->fc, AV_LOG_WARNING, "Unknown st3d mode value %d\n", mode);
5525 sc->stereo3d = av_stereo3d_alloc();
5527 return AVERROR(ENOMEM);
5529 sc->stereo3d->type = type;
5533 static int mov_read_sv3d(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5536 MOVStreamContext *sc;
5537 int size, version, layout;
5538 int32_t yaw, pitch, roll;
5539 uint32_t l = 0, t = 0, r = 0, b = 0;
5540 uint32_t tag, padding = 0;
5541 enum AVSphericalProjection projection;
5543 if (c->fc->nb_streams < 1)
5546 st = c->fc->streams[c->fc->nb_streams - 1];
5549 if (atom.size < 8) {
5550 av_log(c->fc, AV_LOG_ERROR, "Empty spherical video box\n");
5551 return AVERROR_INVALIDDATA;
5554 size = avio_rb32(pb);
5555 if (size <= 12 || size > atom.size)
5556 return AVERROR_INVALIDDATA;
5558 tag = avio_rl32(pb);
5559 if (tag != MKTAG('s','v','h','d')) {
5560 av_log(c->fc, AV_LOG_ERROR, "Missing spherical video header\n");
5563 version = avio_r8(pb);
5565 av_log(c->fc, AV_LOG_WARNING, "Unknown spherical version %d\n",
5569 avio_skip(pb, 3); /* flags */
5570 avio_skip(pb, size - 12); /* metadata_source */
5572 size = avio_rb32(pb);
5573 if (size > atom.size)
5574 return AVERROR_INVALIDDATA;
5576 tag = avio_rl32(pb);
5577 if (tag != MKTAG('p','r','o','j')) {
5578 av_log(c->fc, AV_LOG_ERROR, "Missing projection box\n");
5582 size = avio_rb32(pb);
5583 if (size > atom.size)
5584 return AVERROR_INVALIDDATA;
5586 tag = avio_rl32(pb);
5587 if (tag != MKTAG('p','r','h','d')) {
5588 av_log(c->fc, AV_LOG_ERROR, "Missing projection header box\n");
5591 version = avio_r8(pb);
5593 av_log(c->fc, AV_LOG_WARNING, "Unknown spherical version %d\n",
5597 avio_skip(pb, 3); /* flags */
5599 /* 16.16 fixed point */
5600 yaw = avio_rb32(pb);
5601 pitch = avio_rb32(pb);
5602 roll = avio_rb32(pb);
5604 size = avio_rb32(pb);
5605 if (size > atom.size)
5606 return AVERROR_INVALIDDATA;
5608 tag = avio_rl32(pb);
5609 version = avio_r8(pb);
5611 av_log(c->fc, AV_LOG_WARNING, "Unknown spherical version %d\n",
5615 avio_skip(pb, 3); /* flags */
5617 case MKTAG('c','b','m','p'):
5618 layout = avio_rb32(pb);
5620 av_log(c->fc, AV_LOG_WARNING,
5621 "Unsupported cubemap layout %d\n", layout);
5624 projection = AV_SPHERICAL_CUBEMAP;
5625 padding = avio_rb32(pb);
5627 case MKTAG('e','q','u','i'):
5633 if (b >= UINT_MAX - t || r >= UINT_MAX - l) {
5634 av_log(c->fc, AV_LOG_ERROR,
5635 "Invalid bounding rectangle coordinates "
5636 "%"PRIu32",%"PRIu32",%"PRIu32",%"PRIu32"\n", l, t, r, b);
5637 return AVERROR_INVALIDDATA;
5640 if (l || t || r || b)
5641 projection = AV_SPHERICAL_EQUIRECTANGULAR_TILE;
5643 projection = AV_SPHERICAL_EQUIRECTANGULAR;
5646 av_log(c->fc, AV_LOG_ERROR, "Unknown projection type: %s\n", av_fourcc2str(tag));
5650 sc->spherical = av_spherical_alloc(&sc->spherical_size);
5652 return AVERROR(ENOMEM);
5654 sc->spherical->projection = projection;
5656 sc->spherical->yaw = yaw;
5657 sc->spherical->pitch = pitch;
5658 sc->spherical->roll = roll;
5660 sc->spherical->padding = padding;
5662 sc->spherical->bound_left = l;
5663 sc->spherical->bound_top = t;
5664 sc->spherical->bound_right = r;
5665 sc->spherical->bound_bottom = b;
5670 static int mov_parse_uuid_spherical(MOVStreamContext *sc, AVIOContext *pb, size_t len)
5673 uint8_t *buffer = av_malloc(len + 1);
5677 return AVERROR(ENOMEM);
5680 ret = ffio_read_size(pb, buffer, len);
5684 /* Check for mandatory keys and values, try to support XML as best-effort */
5685 if (!sc->spherical &&
5686 av_stristr(buffer, "<GSpherical:StitchingSoftware>") &&
5687 (val = av_stristr(buffer, "<GSpherical:Spherical>")) &&
5688 av_stristr(val, "true") &&
5689 (val = av_stristr(buffer, "<GSpherical:Stitched>")) &&
5690 av_stristr(val, "true") &&
5691 (val = av_stristr(buffer, "<GSpherical:ProjectionType>")) &&
5692 av_stristr(val, "equirectangular")) {
5693 sc->spherical = av_spherical_alloc(&sc->spherical_size);
5697 sc->spherical->projection = AV_SPHERICAL_EQUIRECTANGULAR;
5699 if (av_stristr(buffer, "<GSpherical:StereoMode>") && !sc->stereo3d) {
5700 enum AVStereo3DType mode;
5702 if (av_stristr(buffer, "left-right"))
5703 mode = AV_STEREO3D_SIDEBYSIDE;
5704 else if (av_stristr(buffer, "top-bottom"))
5705 mode = AV_STEREO3D_TOPBOTTOM;
5707 mode = AV_STEREO3D_2D;
5709 sc->stereo3d = av_stereo3d_alloc();
5713 sc->stereo3d->type = mode;
5717 val = av_stristr(buffer, "<GSpherical:InitialViewHeadingDegrees>");
5719 sc->spherical->yaw = strtol(val, NULL, 10) * (1 << 16);
5720 val = av_stristr(buffer, "<GSpherical:InitialViewPitchDegrees>");
5722 sc->spherical->pitch = strtol(val, NULL, 10) * (1 << 16);
5723 val = av_stristr(buffer, "<GSpherical:InitialViewRollDegrees>");
5725 sc->spherical->roll = strtol(val, NULL, 10) * (1 << 16);
5733 static int mov_read_uuid(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5736 MOVStreamContext *sc;
5739 static const uint8_t uuid_isml_manifest[] = {
5740 0xa5, 0xd4, 0x0b, 0x30, 0xe8, 0x14, 0x11, 0xdd,
5741 0xba, 0x2f, 0x08, 0x00, 0x20, 0x0c, 0x9a, 0x66
5743 static const uint8_t uuid_xmp[] = {
5744 0xbe, 0x7a, 0xcf, 0xcb, 0x97, 0xa9, 0x42, 0xe8,
5745 0x9c, 0x71, 0x99, 0x94, 0x91, 0xe3, 0xaf, 0xac
5747 static const uint8_t uuid_spherical[] = {
5748 0xff, 0xcc, 0x82, 0x63, 0xf8, 0x55, 0x4a, 0x93,
5749 0x88, 0x14, 0x58, 0x7a, 0x02, 0x52, 0x1f, 0xdd,
5752 if (atom.size < sizeof(uuid) || atom.size >= FFMIN(INT_MAX, SIZE_MAX))
5753 return AVERROR_INVALIDDATA;
5755 if (c->fc->nb_streams < 1)
5757 st = c->fc->streams[c->fc->nb_streams - 1];
5760 ret = ffio_read_size(pb, uuid, sizeof(uuid));
5763 if (!memcmp(uuid, uuid_isml_manifest, sizeof(uuid))) {
5764 uint8_t *buffer, *ptr;
5766 size_t len = atom.size - sizeof(uuid);
5769 return AVERROR_INVALIDDATA;
5771 ret = avio_skip(pb, 4); // zeroes
5774 buffer = av_mallocz(len + 1);
5776 return AVERROR(ENOMEM);
5778 ret = ffio_read_size(pb, buffer, len);
5785 while ((ptr = av_stristr(ptr, "systemBitrate=\""))) {
5786 ptr += sizeof("systemBitrate=\"") - 1;
5787 c->bitrates_count++;
5788 c->bitrates = av_realloc_f(c->bitrates, c->bitrates_count, sizeof(*c->bitrates));
5790 c->bitrates_count = 0;
5792 return AVERROR(ENOMEM);
5795 ret = strtol(ptr, &endptr, 10);
5796 if (ret < 0 || errno || *endptr != '"') {
5797 c->bitrates[c->bitrates_count - 1] = 0;
5799 c->bitrates[c->bitrates_count - 1] = ret;
5804 } else if (!memcmp(uuid, uuid_xmp, sizeof(uuid))) {
5806 size_t len = atom.size - sizeof(uuid);
5807 if (c->export_xmp) {
5808 buffer = av_mallocz(len + 1);
5810 return AVERROR(ENOMEM);
5812 ret = ffio_read_size(pb, buffer, len);
5818 av_dict_set(&c->fc->metadata, "xmp",
5819 buffer, AV_DICT_DONT_STRDUP_VAL);
5821 // skip all uuid atom, which makes it fast for long uuid-xmp file
5822 ret = avio_skip(pb, len);
5826 } else if (!memcmp(uuid, uuid_spherical, sizeof(uuid))) {
5827 size_t len = atom.size - sizeof(uuid);
5828 ret = mov_parse_uuid_spherical(sc, pb, len);
5832 av_log(c->fc, AV_LOG_WARNING, "Invalid spherical metadata found\n");
5838 static int mov_read_free(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5841 uint8_t content[16];
5846 ret = avio_read(pb, content, FFMIN(sizeof(content), atom.size));
5852 && !memcmp(content, "Anevia\x1A\x1A", 8)
5853 && c->use_mfra_for == FF_MOV_FLAG_MFRA_AUTO) {
5854 c->use_mfra_for = FF_MOV_FLAG_MFRA_PTS;
5860 static int mov_read_frma(MOVContext *c, AVIOContext *pb, MOVAtom atom)
5862 uint32_t format = avio_rl32(pb);
5863 MOVStreamContext *sc;
5867 if (c->fc->nb_streams < 1)
5869 st = c->fc->streams[c->fc->nb_streams - 1];
5874 case MKTAG('e','n','c','v'): // encrypted video
5875 case MKTAG('e','n','c','a'): // encrypted audio
5876 id = mov_codec_id(st, format);
5877 if (st->codecpar->codec_id != AV_CODEC_ID_NONE &&
5878 st->codecpar->codec_id != id) {
5879 av_log(c->fc, AV_LOG_WARNING,
5880 "ignoring 'frma' atom of '%.4s', stream has codec id %d\n",
5881 (char*)&format, st->codecpar->codec_id);
5885 st->codecpar->codec_id = id;
5886 sc->format = format;
5890 if (format != sc->format) {
5891 av_log(c->fc, AV_LOG_WARNING,
5892 "ignoring 'frma' atom of '%.4s', stream format is '%.4s'\n",
5893 (char*)&format, (char*)&sc->format);
5902 * Gets the current encryption info and associated current stream context. If
5903 * we are parsing a track fragment, this will return the specific encryption
5904 * info for this fragment; otherwise this will return the global encryption
5905 * info for the current stream.
5907 static int get_current_encryption_info(MOVContext *c, MOVEncryptionIndex **encryption_index, MOVStreamContext **sc)
5909 MOVFragmentStreamInfo *frag_stream_info;
5913 frag_stream_info = get_current_frag_stream_info(&c->frag_index);
5914 if (frag_stream_info) {
5915 for (i = 0; i < c->fc->nb_streams; i++) {
5916 if (c->fc->streams[i]->id == frag_stream_info->id) {
5917 st = c->fc->streams[i];
5921 if (i == c->fc->nb_streams)
5923 *sc = st->priv_data;
5925 if (!frag_stream_info->encryption_index) {
5926 // If this stream isn't encrypted, don't create the index.
5927 if (!(*sc)->cenc.default_encrypted_sample)
5929 frag_stream_info->encryption_index = av_mallocz(sizeof(*frag_stream_info->encryption_index));
5930 if (!frag_stream_info->encryption_index)
5931 return AVERROR(ENOMEM);
5933 *encryption_index = frag_stream_info->encryption_index;
5936 // No current track fragment, using stream level encryption info.
5938 if (c->fc->nb_streams < 1)
5940 st = c->fc->streams[c->fc->nb_streams - 1];
5941 *sc = st->priv_data;
5943 if (!(*sc)->cenc.encryption_index) {
5944 // If this stream isn't encrypted, don't create the index.
5945 if (!(*sc)->cenc.default_encrypted_sample)
5947 (*sc)->cenc.encryption_index = av_mallocz(sizeof(*frag_stream_info->encryption_index));
5948 if (!(*sc)->cenc.encryption_index)
5949 return AVERROR(ENOMEM);
5952 *encryption_index = (*sc)->cenc.encryption_index;
5957 static int mov_read_sample_encryption_info(MOVContext *c, AVIOContext *pb, MOVStreamContext *sc, AVEncryptionInfo **sample, int use_subsamples)
5960 unsigned int subsample_count;
5961 AVSubsampleEncryptionInfo *subsamples;
5963 if (!sc->cenc.default_encrypted_sample) {
5964 av_log(c->fc, AV_LOG_ERROR, "Missing schm or tenc\n");
5965 return AVERROR_INVALIDDATA;
5968 *sample = av_encryption_info_clone(sc->cenc.default_encrypted_sample);
5970 return AVERROR(ENOMEM);
5972 if (sc->cenc.per_sample_iv_size != 0) {
5973 if ((ret = ffio_read_size(pb, (*sample)->iv, sc->cenc.per_sample_iv_size)) < 0) {
5974 av_log(c->fc, AV_LOG_ERROR, "failed to read the initialization vector\n");
5975 av_encryption_info_free(*sample);
5981 if (use_subsamples) {
5982 subsample_count = avio_rb16(pb);
5983 av_free((*sample)->subsamples);
5984 (*sample)->subsamples = av_mallocz_array(subsample_count, sizeof(*subsamples));
5985 if (!(*sample)->subsamples) {
5986 av_encryption_info_free(*sample);
5988 return AVERROR(ENOMEM);
5991 for (i = 0; i < subsample_count && !pb->eof_reached; i++) {
5992 (*sample)->subsamples[i].bytes_of_clear_data = avio_rb16(pb);
5993 (*sample)->subsamples[i].bytes_of_protected_data = avio_rb32(pb);
5996 if (pb->eof_reached) {
5997 av_log(c->fc, AV_LOG_ERROR, "hit EOF while reading sub-sample encryption info\n");
5998 av_encryption_info_free(*sample);
6000 return AVERROR_INVALIDDATA;
6002 (*sample)->subsample_count = subsample_count;
6008 static int mov_read_senc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6010 AVEncryptionInfo **encrypted_samples;
6011 MOVEncryptionIndex *encryption_index;
6012 MOVStreamContext *sc;
6013 int use_subsamples, ret;
6014 unsigned int sample_count, i, alloc_size = 0;
6016 ret = get_current_encryption_info(c, &encryption_index, &sc);
6020 if (encryption_index->nb_encrypted_samples) {
6021 // This can happen if we have both saio/saiz and senc atoms.
6022 av_log(c->fc, AV_LOG_DEBUG, "Ignoring duplicate encryption info in senc\n");
6026 avio_r8(pb); /* version */
6027 use_subsamples = avio_rb24(pb) & 0x02; /* flags */
6029 sample_count = avio_rb32(pb);
6030 if (sample_count >= INT_MAX / sizeof(*encrypted_samples))
6031 return AVERROR(ENOMEM);
6033 for (i = 0; i < sample_count; i++) {
6034 unsigned int min_samples = FFMIN(FFMAX(i + 1, 1024 * 1024), sample_count);
6035 encrypted_samples = av_fast_realloc(encryption_index->encrypted_samples, &alloc_size,
6036 min_samples * sizeof(*encrypted_samples));
6037 if (encrypted_samples) {
6038 encryption_index->encrypted_samples = encrypted_samples;
6040 ret = mov_read_sample_encryption_info(
6041 c, pb, sc, &encryption_index->encrypted_samples[i], use_subsamples);
6043 ret = AVERROR(ENOMEM);
6045 if (pb->eof_reached) {
6046 av_log(c->fc, AV_LOG_ERROR, "Hit EOF while reading senc\n");
6047 ret = AVERROR_INVALIDDATA;
6052 av_encryption_info_free(encryption_index->encrypted_samples[i - 1]);
6053 av_freep(&encryption_index->encrypted_samples);
6057 encryption_index->nb_encrypted_samples = sample_count;
6062 static int mov_parse_auxiliary_info(MOVContext *c, MOVStreamContext *sc, AVIOContext *pb, MOVEncryptionIndex *encryption_index)
6064 AVEncryptionInfo **sample, **encrypted_samples;
6066 size_t sample_count, sample_info_size, i;
6068 unsigned int alloc_size = 0;
6070 if (encryption_index->nb_encrypted_samples)
6072 sample_count = encryption_index->auxiliary_info_sample_count;
6073 if (encryption_index->auxiliary_offsets_count != 1) {
6074 av_log(c->fc, AV_LOG_ERROR, "Multiple auxiliary info chunks are not supported\n");
6075 return AVERROR_PATCHWELCOME;
6077 if (sample_count >= INT_MAX / sizeof(*encrypted_samples))
6078 return AVERROR(ENOMEM);
6080 prev_pos = avio_tell(pb);
6081 if (!(pb->seekable & AVIO_SEEKABLE_NORMAL) ||
6082 avio_seek(pb, encryption_index->auxiliary_offsets[0], SEEK_SET) != encryption_index->auxiliary_offsets[0]) {
6083 av_log(c->fc, AV_LOG_INFO, "Failed to seek for auxiliary info, will only parse senc atoms for encryption info\n");
6087 for (i = 0; i < sample_count && !pb->eof_reached; i++) {
6088 unsigned int min_samples = FFMIN(FFMAX(i + 1, 1024 * 1024), sample_count);
6089 encrypted_samples = av_fast_realloc(encryption_index->encrypted_samples, &alloc_size,
6090 min_samples * sizeof(*encrypted_samples));
6091 if (!encrypted_samples) {
6092 ret = AVERROR(ENOMEM);
6095 encryption_index->encrypted_samples = encrypted_samples;
6097 sample = &encryption_index->encrypted_samples[i];
6098 sample_info_size = encryption_index->auxiliary_info_default_size
6099 ? encryption_index->auxiliary_info_default_size
6100 : encryption_index->auxiliary_info_sizes[i];
6102 ret = mov_read_sample_encryption_info(c, pb, sc, sample, sample_info_size > sc->cenc.per_sample_iv_size);
6106 if (pb->eof_reached) {
6107 av_log(c->fc, AV_LOG_ERROR, "Hit EOF while reading auxiliary info\n");
6108 ret = AVERROR_INVALIDDATA;
6110 encryption_index->nb_encrypted_samples = sample_count;
6114 avio_seek(pb, prev_pos, SEEK_SET);
6116 for (; i > 0; i--) {
6117 av_encryption_info_free(encryption_index->encrypted_samples[i - 1]);
6119 av_freep(&encryption_index->encrypted_samples);
6125 * Tries to read the given number of bytes from the stream and puts it in a
6126 * newly allocated buffer. This reads in small chunks to avoid allocating large
6127 * memory if the file contains an invalid/malicious size value.
6129 static int mov_try_read_block(AVIOContext *pb, size_t size, uint8_t **data)
6131 const unsigned int block_size = 1024 * 1024;
6132 uint8_t *buffer = NULL;
6133 unsigned int alloc_size = 0, offset = 0;
6134 while (offset < size) {
6135 unsigned int new_size =
6136 alloc_size >= INT_MAX - block_size ? INT_MAX : alloc_size + block_size;
6137 uint8_t *new_buffer = av_fast_realloc(buffer, &alloc_size, new_size);
6138 unsigned int to_read = FFMIN(size, alloc_size) - offset;
6141 return AVERROR(ENOMEM);
6143 buffer = new_buffer;
6145 if (avio_read(pb, buffer + offset, to_read) != to_read) {
6147 return AVERROR_INVALIDDATA;
6156 static int mov_read_saiz(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6158 MOVEncryptionIndex *encryption_index;
6159 MOVStreamContext *sc;
6161 unsigned int sample_count, aux_info_type, aux_info_param;
6163 ret = get_current_encryption_info(c, &encryption_index, &sc);
6167 if (encryption_index->nb_encrypted_samples) {
6168 // This can happen if we have both saio/saiz and senc atoms.
6169 av_log(c->fc, AV_LOG_DEBUG, "Ignoring duplicate encryption info in saiz\n");
6173 if (encryption_index->auxiliary_info_sample_count) {
6174 av_log(c->fc, AV_LOG_ERROR, "Duplicate saiz atom\n");
6175 return AVERROR_INVALIDDATA;
6178 avio_r8(pb); /* version */
6179 if (avio_rb24(pb) & 0x01) { /* flags */
6180 aux_info_type = avio_rb32(pb);
6181 aux_info_param = avio_rb32(pb);
6182 if (sc->cenc.default_encrypted_sample) {
6183 if (aux_info_type != sc->cenc.default_encrypted_sample->scheme) {
6184 av_log(c->fc, AV_LOG_DEBUG, "Ignoring saiz box with non-zero aux_info_type\n");
6187 if (aux_info_param != 0) {
6188 av_log(c->fc, AV_LOG_DEBUG, "Ignoring saiz box with non-zero aux_info_type_parameter\n");
6192 // Didn't see 'schm' or 'tenc', so this isn't encrypted.
6193 if ((aux_info_type == MKBETAG('c','e','n','c') ||
6194 aux_info_type == MKBETAG('c','e','n','s') ||
6195 aux_info_type == MKBETAG('c','b','c','1') ||
6196 aux_info_type == MKBETAG('c','b','c','s')) &&
6197 aux_info_param == 0) {
6198 av_log(c->fc, AV_LOG_ERROR, "Saw encrypted saiz without schm/tenc\n");
6199 return AVERROR_INVALIDDATA;
6204 } else if (!sc->cenc.default_encrypted_sample) {
6205 // Didn't see 'schm' or 'tenc', so this isn't encrypted.
6209 encryption_index->auxiliary_info_default_size = avio_r8(pb);
6210 sample_count = avio_rb32(pb);
6211 encryption_index->auxiliary_info_sample_count = sample_count;
6213 if (encryption_index->auxiliary_info_default_size == 0) {
6214 ret = mov_try_read_block(pb, sample_count, &encryption_index->auxiliary_info_sizes);
6216 av_log(c->fc, AV_LOG_ERROR, "Failed to read the auxiliary info\n");
6221 if (encryption_index->auxiliary_offsets_count) {
6222 return mov_parse_auxiliary_info(c, sc, pb, encryption_index);
6228 static int mov_read_saio(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6230 uint64_t *auxiliary_offsets;
6231 MOVEncryptionIndex *encryption_index;
6232 MOVStreamContext *sc;
6234 unsigned int version, entry_count, aux_info_type, aux_info_param;
6235 unsigned int alloc_size = 0;
6237 ret = get_current_encryption_info(c, &encryption_index, &sc);
6241 if (encryption_index->nb_encrypted_samples) {
6242 // This can happen if we have both saio/saiz and senc atoms.
6243 av_log(c->fc, AV_LOG_DEBUG, "Ignoring duplicate encryption info in saio\n");
6247 if (encryption_index->auxiliary_offsets_count) {
6248 av_log(c->fc, AV_LOG_ERROR, "Duplicate saio atom\n");
6249 return AVERROR_INVALIDDATA;
6252 version = avio_r8(pb); /* version */
6253 if (avio_rb24(pb) & 0x01) { /* flags */
6254 aux_info_type = avio_rb32(pb);
6255 aux_info_param = avio_rb32(pb);
6256 if (sc->cenc.default_encrypted_sample) {
6257 if (aux_info_type != sc->cenc.default_encrypted_sample->scheme) {
6258 av_log(c->fc, AV_LOG_DEBUG, "Ignoring saio box with non-zero aux_info_type\n");
6261 if (aux_info_param != 0) {
6262 av_log(c->fc, AV_LOG_DEBUG, "Ignoring saio box with non-zero aux_info_type_parameter\n");
6266 // Didn't see 'schm' or 'tenc', so this isn't encrypted.
6267 if ((aux_info_type == MKBETAG('c','e','n','c') ||
6268 aux_info_type == MKBETAG('c','e','n','s') ||
6269 aux_info_type == MKBETAG('c','b','c','1') ||
6270 aux_info_type == MKBETAG('c','b','c','s')) &&
6271 aux_info_param == 0) {
6272 av_log(c->fc, AV_LOG_ERROR, "Saw encrypted saio without schm/tenc\n");
6273 return AVERROR_INVALIDDATA;
6278 } else if (!sc->cenc.default_encrypted_sample) {
6279 // Didn't see 'schm' or 'tenc', so this isn't encrypted.
6283 entry_count = avio_rb32(pb);
6284 if (entry_count >= INT_MAX / sizeof(*auxiliary_offsets))
6285 return AVERROR(ENOMEM);
6287 for (i = 0; i < entry_count && !pb->eof_reached; i++) {
6288 unsigned int min_offsets = FFMIN(FFMAX(i + 1, 1024), entry_count);
6289 auxiliary_offsets = av_fast_realloc(
6290 encryption_index->auxiliary_offsets, &alloc_size,
6291 min_offsets * sizeof(*auxiliary_offsets));
6292 if (!auxiliary_offsets) {
6293 av_freep(&encryption_index->auxiliary_offsets);
6294 return AVERROR(ENOMEM);
6296 encryption_index->auxiliary_offsets = auxiliary_offsets;
6299 encryption_index->auxiliary_offsets[i] = avio_rb32(pb);
6301 encryption_index->auxiliary_offsets[i] = avio_rb64(pb);
6303 if (c->frag_index.current >= 0) {
6304 encryption_index->auxiliary_offsets[i] += c->fragment.base_data_offset;
6308 if (pb->eof_reached) {
6309 av_log(c->fc, AV_LOG_ERROR, "Hit EOF while reading saio\n");
6310 av_freep(&encryption_index->auxiliary_offsets);
6311 return AVERROR_INVALIDDATA;
6314 encryption_index->auxiliary_offsets_count = entry_count;
6316 if (encryption_index->auxiliary_info_sample_count) {
6317 return mov_parse_auxiliary_info(c, sc, pb, encryption_index);
6323 static int mov_read_pssh(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6325 AVEncryptionInitInfo *info, *old_init_info;
6328 uint8_t *side_data, *extra_data, *old_side_data;
6329 size_t side_data_size;
6330 int ret = 0, old_side_data_size;
6331 unsigned int version, kid_count, extra_data_size, alloc_size = 0;
6333 if (c->fc->nb_streams < 1)
6335 st = c->fc->streams[c->fc->nb_streams-1];
6337 version = avio_r8(pb); /* version */
6338 avio_rb24(pb); /* flags */
6340 info = av_encryption_init_info_alloc(/* system_id_size */ 16, /* num_key_ids */ 0,
6341 /* key_id_size */ 16, /* data_size */ 0);
6343 return AVERROR(ENOMEM);
6345 if ((ret = ffio_read_size(pb, info->system_id, 16)) < 0) {
6346 av_log(c->fc, AV_LOG_ERROR, "Failed to read the system id\n");
6351 kid_count = avio_rb32(pb);
6352 if (kid_count >= INT_MAX / sizeof(*key_ids)) {
6353 ret = AVERROR(ENOMEM);
6357 for (unsigned int i = 0; i < kid_count && !pb->eof_reached; i++) {
6358 unsigned int min_kid_count = FFMIN(FFMAX(i + 1, 1024), kid_count);
6359 key_ids = av_fast_realloc(info->key_ids, &alloc_size,
6360 min_kid_count * sizeof(*key_ids));
6362 ret = AVERROR(ENOMEM);
6365 info->key_ids = key_ids;
6367 info->key_ids[i] = av_mallocz(16);
6368 if (!info->key_ids[i]) {
6369 ret = AVERROR(ENOMEM);
6372 info->num_key_ids = i + 1;
6374 if ((ret = ffio_read_size(pb, info->key_ids[i], 16)) < 0) {
6375 av_log(c->fc, AV_LOG_ERROR, "Failed to read the key id\n");
6380 if (pb->eof_reached) {
6381 av_log(c->fc, AV_LOG_ERROR, "Hit EOF while reading pssh\n");
6382 ret = AVERROR_INVALIDDATA;
6387 extra_data_size = avio_rb32(pb);
6388 ret = mov_try_read_block(pb, extra_data_size, &extra_data);
6392 av_freep(&info->data); // malloc(0) may still allocate something.
6393 info->data = extra_data;
6394 info->data_size = extra_data_size;
6396 // If there is existing initialization data, append to the list.
6397 old_side_data = av_stream_get_side_data(st, AV_PKT_DATA_ENCRYPTION_INIT_INFO, &old_side_data_size);
6398 if (old_side_data) {
6399 old_init_info = av_encryption_init_info_get_side_data(old_side_data, old_side_data_size);
6400 if (old_init_info) {
6401 // Append to the end of the list.
6402 for (AVEncryptionInitInfo *cur = old_init_info;; cur = cur->next) {
6408 info = old_init_info;
6410 // Assume existing side-data will be valid, so the only error we could get is OOM.
6411 ret = AVERROR(ENOMEM);
6416 side_data = av_encryption_init_info_add_side_data(info, &side_data_size);
6418 ret = AVERROR(ENOMEM);
6421 ret = av_stream_add_side_data(st, AV_PKT_DATA_ENCRYPTION_INIT_INFO,
6422 side_data, side_data_size);
6427 av_encryption_init_info_free(info);
6431 static int mov_read_schm(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6434 MOVStreamContext *sc;
6436 if (c->fc->nb_streams < 1)
6438 st = c->fc->streams[c->fc->nb_streams-1];
6441 if (sc->pseudo_stream_id != 0) {
6442 av_log(c->fc, AV_LOG_ERROR, "schm boxes are only supported in first sample descriptor\n");
6443 return AVERROR_PATCHWELCOME;
6447 return AVERROR_INVALIDDATA;
6449 avio_rb32(pb); /* version and flags */
6451 if (!sc->cenc.default_encrypted_sample) {
6452 sc->cenc.default_encrypted_sample = av_encryption_info_alloc(0, 16, 16);
6453 if (!sc->cenc.default_encrypted_sample) {
6454 return AVERROR(ENOMEM);
6458 sc->cenc.default_encrypted_sample->scheme = avio_rb32(pb);
6462 static int mov_read_tenc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6465 MOVStreamContext *sc;
6466 unsigned int version, pattern, is_protected, iv_size;
6468 if (c->fc->nb_streams < 1)
6470 st = c->fc->streams[c->fc->nb_streams-1];
6473 if (sc->pseudo_stream_id != 0) {
6474 av_log(c->fc, AV_LOG_ERROR, "tenc atom are only supported in first sample descriptor\n");
6475 return AVERROR_PATCHWELCOME;
6478 if (!sc->cenc.default_encrypted_sample) {
6479 sc->cenc.default_encrypted_sample = av_encryption_info_alloc(0, 16, 16);
6480 if (!sc->cenc.default_encrypted_sample) {
6481 return AVERROR(ENOMEM);
6486 return AVERROR_INVALIDDATA;
6488 version = avio_r8(pb); /* version */
6489 avio_rb24(pb); /* flags */
6491 avio_r8(pb); /* reserved */
6492 pattern = avio_r8(pb);
6495 sc->cenc.default_encrypted_sample->crypt_byte_block = pattern >> 4;
6496 sc->cenc.default_encrypted_sample->skip_byte_block = pattern & 0xf;
6499 is_protected = avio_r8(pb);
6500 if (is_protected && !sc->cenc.encryption_index) {
6501 // The whole stream should be by-default encrypted.
6502 sc->cenc.encryption_index = av_mallocz(sizeof(MOVEncryptionIndex));
6503 if (!sc->cenc.encryption_index)
6504 return AVERROR(ENOMEM);
6506 sc->cenc.per_sample_iv_size = avio_r8(pb);
6507 if (sc->cenc.per_sample_iv_size != 0 && sc->cenc.per_sample_iv_size != 8 &&
6508 sc->cenc.per_sample_iv_size != 16) {
6509 av_log(c->fc, AV_LOG_ERROR, "invalid per-sample IV size value\n");
6510 return AVERROR_INVALIDDATA;
6512 if (avio_read(pb, sc->cenc.default_encrypted_sample->key_id, 16) != 16) {
6513 av_log(c->fc, AV_LOG_ERROR, "failed to read the default key ID\n");
6514 return AVERROR_INVALIDDATA;
6517 if (is_protected && !sc->cenc.per_sample_iv_size) {
6518 iv_size = avio_r8(pb);
6519 if (iv_size != 8 && iv_size != 16) {
6520 av_log(c->fc, AV_LOG_ERROR, "invalid default_constant_IV_size in tenc atom\n");
6521 return AVERROR_INVALIDDATA;
6524 if (avio_read(pb, sc->cenc.default_encrypted_sample->iv, iv_size) != iv_size) {
6525 av_log(c->fc, AV_LOG_ERROR, "failed to read the default IV\n");
6526 return AVERROR_INVALIDDATA;
6533 static int mov_read_dfla(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6536 int last, type, size, ret;
6539 if (c->fc->nb_streams < 1)
6541 st = c->fc->streams[c->fc->nb_streams-1];
6543 if ((uint64_t)atom.size > (1<<30) || atom.size < 42)
6544 return AVERROR_INVALIDDATA;
6546 /* Check FlacSpecificBox version. */
6547 if (avio_r8(pb) != 0)
6548 return AVERROR_INVALIDDATA;
6550 avio_rb24(pb); /* Flags */
6552 avio_read(pb, buf, sizeof(buf));
6553 flac_parse_block_header(buf, &last, &type, &size);
6555 if (type != FLAC_METADATA_TYPE_STREAMINFO || size != FLAC_STREAMINFO_SIZE) {
6556 av_log(c->fc, AV_LOG_ERROR, "STREAMINFO must be first FLACMetadataBlock\n");
6557 return AVERROR_INVALIDDATA;
6560 ret = ff_get_extradata(c->fc, st->codecpar, pb, size);
6565 av_log(c->fc, AV_LOG_WARNING, "non-STREAMINFO FLACMetadataBlock(s) ignored\n");
6570 static int cenc_decrypt(MOVContext *c, MOVStreamContext *sc, AVEncryptionInfo *sample, uint8_t *input, int size)
6574 if (sample->scheme != MKBETAG('c','e','n','c') || sample->crypt_byte_block != 0 || sample->skip_byte_block != 0) {
6575 av_log(c->fc, AV_LOG_ERROR, "Only the 'cenc' encryption scheme is supported\n");
6576 return AVERROR_PATCHWELCOME;
6579 if (!sc->cenc.aes_ctr) {
6580 /* initialize the cipher */
6581 sc->cenc.aes_ctr = av_aes_ctr_alloc();
6582 if (!sc->cenc.aes_ctr) {
6583 return AVERROR(ENOMEM);
6586 ret = av_aes_ctr_init(sc->cenc.aes_ctr, c->decryption_key);
6592 av_aes_ctr_set_full_iv(sc->cenc.aes_ctr, sample->iv);
6594 if (!sample->subsample_count)
6596 /* decrypt the whole packet */
6597 av_aes_ctr_crypt(sc->cenc.aes_ctr, input, input, size);
6601 for (i = 0; i < sample->subsample_count; i++)
6603 if (sample->subsamples[i].bytes_of_clear_data + sample->subsamples[i].bytes_of_protected_data > size) {
6604 av_log(c->fc, AV_LOG_ERROR, "subsample size exceeds the packet size left\n");
6605 return AVERROR_INVALIDDATA;
6608 /* skip the clear bytes */
6609 input += sample->subsamples[i].bytes_of_clear_data;
6610 size -= sample->subsamples[i].bytes_of_clear_data;
6612 /* decrypt the encrypted bytes */
6613 av_aes_ctr_crypt(sc->cenc.aes_ctr, input, input, sample->subsamples[i].bytes_of_protected_data);
6614 input += sample->subsamples[i].bytes_of_protected_data;
6615 size -= sample->subsamples[i].bytes_of_protected_data;
6619 av_log(c->fc, AV_LOG_ERROR, "leftover packet bytes after subsample processing\n");
6620 return AVERROR_INVALIDDATA;
6626 static int cenc_filter(MOVContext *mov, AVStream* st, MOVStreamContext *sc, AVPacket *pkt, int current_index)
6628 MOVFragmentStreamInfo *frag_stream_info;
6629 MOVEncryptionIndex *encryption_index;
6630 AVEncryptionInfo *encrypted_sample;
6631 int encrypted_index, ret;
6633 frag_stream_info = get_frag_stream_info(&mov->frag_index, mov->frag_index.current, st->id);
6634 encrypted_index = current_index;
6635 encryption_index = NULL;
6636 if (frag_stream_info) {
6637 // Note this only supports encryption info in the first sample descriptor.
6638 if (mov->fragment.stsd_id == 1) {
6639 if (frag_stream_info->encryption_index) {
6640 encrypted_index = current_index - frag_stream_info->index_entry;
6641 encryption_index = frag_stream_info->encryption_index;
6643 encryption_index = sc->cenc.encryption_index;
6647 encryption_index = sc->cenc.encryption_index;
6650 if (encryption_index) {
6651 if (encryption_index->auxiliary_info_sample_count &&
6652 !encryption_index->nb_encrypted_samples) {
6653 av_log(mov->fc, AV_LOG_ERROR, "saiz atom found without saio\n");
6654 return AVERROR_INVALIDDATA;
6656 if (encryption_index->auxiliary_offsets_count &&
6657 !encryption_index->nb_encrypted_samples) {
6658 av_log(mov->fc, AV_LOG_ERROR, "saio atom found without saiz\n");
6659 return AVERROR_INVALIDDATA;
6662 if (!encryption_index->nb_encrypted_samples) {
6663 // Full-sample encryption with default settings.
6664 encrypted_sample = sc->cenc.default_encrypted_sample;
6665 } else if (encrypted_index >= 0 && encrypted_index < encryption_index->nb_encrypted_samples) {
6666 // Per-sample setting override.
6667 encrypted_sample = encryption_index->encrypted_samples[encrypted_index];
6669 av_log(mov->fc, AV_LOG_ERROR, "Incorrect number of samples in encryption info\n");
6670 return AVERROR_INVALIDDATA;
6673 if (mov->decryption_key) {
6674 return cenc_decrypt(mov, sc, encrypted_sample, pkt->data, pkt->size);
6677 uint8_t *side_data = av_encryption_info_add_side_data(encrypted_sample, &size);
6679 return AVERROR(ENOMEM);
6680 ret = av_packet_add_side_data(pkt, AV_PKT_DATA_ENCRYPTION_INFO, side_data, size);
6690 static int mov_read_dops(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6692 const int OPUS_SEEK_PREROLL_MS = 80;
6698 if (c->fc->nb_streams < 1)
6700 st = c->fc->streams[c->fc->nb_streams-1];
6702 if ((uint64_t)atom.size > (1<<30) || atom.size < 11)
6703 return AVERROR_INVALIDDATA;
6705 /* Check OpusSpecificBox version. */
6706 if (avio_r8(pb) != 0) {
6707 av_log(c->fc, AV_LOG_ERROR, "unsupported OpusSpecificBox version\n");
6708 return AVERROR_INVALIDDATA;
6711 /* OpusSpecificBox size plus magic for Ogg OpusHead header. */
6712 size = atom.size + 8;
6714 if ((ret = ff_alloc_extradata(st->codecpar, size)) < 0)
6717 AV_WL32(st->codecpar->extradata, MKTAG('O','p','u','s'));
6718 AV_WL32(st->codecpar->extradata + 4, MKTAG('H','e','a','d'));
6719 AV_WB8(st->codecpar->extradata + 8, 1); /* OpusHead version */
6720 avio_read(pb, st->codecpar->extradata + 9, size - 9);
6722 /* OpusSpecificBox is stored in big-endian, but OpusHead is
6723 little-endian; aside from the preceeding magic and version they're
6724 otherwise currently identical. Data after output gain at offset 16
6725 doesn't need to be bytewapped. */
6726 pre_skip = AV_RB16(st->codecpar->extradata + 10);
6727 AV_WL16(st->codecpar->extradata + 10, pre_skip);
6728 AV_WL32(st->codecpar->extradata + 12, AV_RB32(st->codecpar->extradata + 12));
6729 AV_WL16(st->codecpar->extradata + 16, AV_RB16(st->codecpar->extradata + 16));
6731 st->codecpar->initial_padding = pre_skip;
6732 st->codecpar->seek_preroll = av_rescale_q(OPUS_SEEK_PREROLL_MS,
6733 (AVRational){1, 1000},
6734 (AVRational){1, 48000});
6739 static int mov_read_dmlp(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6742 unsigned format_info;
6743 int channel_assignment, channel_assignment1, channel_assignment2;
6746 if (c->fc->nb_streams < 1)
6748 st = c->fc->streams[c->fc->nb_streams-1];
6751 return AVERROR_INVALIDDATA;
6753 format_info = avio_rb32(pb);
6755 ratebits = (format_info >> 28) & 0xF;
6756 channel_assignment1 = (format_info >> 15) & 0x1F;
6757 channel_assignment2 = format_info & 0x1FFF;
6758 if (channel_assignment2)
6759 channel_assignment = channel_assignment2;
6761 channel_assignment = channel_assignment1;
6763 st->codecpar->frame_size = 40 << (ratebits & 0x7);
6764 st->codecpar->sample_rate = mlp_samplerate(ratebits);
6765 st->codecpar->channels = truehd_channels(channel_assignment);
6766 st->codecpar->channel_layout = truehd_layout(channel_assignment);
6771 static int mov_read_dvcc_dvvc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6775 AVDOVIDecoderConfigurationRecord *dovi;
6779 if (c->fc->nb_streams < 1)
6781 st = c->fc->streams[c->fc->nb_streams-1];
6783 if ((uint64_t)atom.size > (1<<30) || atom.size < 4)
6784 return AVERROR_INVALIDDATA;
6786 dovi = av_dovi_alloc(&dovi_size);
6788 return AVERROR(ENOMEM);
6790 dovi->dv_version_major = avio_r8(pb);
6791 dovi->dv_version_minor = avio_r8(pb);
6793 buf = avio_rb16(pb);
6794 dovi->dv_profile = (buf >> 9) & 0x7f; // 7 bits
6795 dovi->dv_level = (buf >> 3) & 0x3f; // 6 bits
6796 dovi->rpu_present_flag = (buf >> 2) & 0x01; // 1 bit
6797 dovi->el_present_flag = (buf >> 1) & 0x01; // 1 bit
6798 dovi->bl_present_flag = buf & 0x01; // 1 bit
6799 if (atom.size >= 24) { // 4 + 4 + 4 * 4
6801 dovi->dv_bl_signal_compatibility_id = (buf >> 4) & 0x0f; // 4 bits
6803 // 0 stands for None
6804 // Dolby Vision V1.2.93 profiles and levels
6805 dovi->dv_bl_signal_compatibility_id = 0;
6808 ret = av_stream_add_side_data(st, AV_PKT_DATA_DOVI_CONF,
6809 (uint8_t *)dovi, dovi_size);
6815 av_log(c, AV_LOG_TRACE, "DOVI in dvcC/dvvC box, version: %d.%d, profile: %d, level: %d, "
6816 "rpu flag: %d, el flag: %d, bl flag: %d, compatibility id: %d\n",
6817 dovi->dv_version_major, dovi->dv_version_minor,
6818 dovi->dv_profile, dovi->dv_level,
6819 dovi->rpu_present_flag,
6820 dovi->el_present_flag,
6821 dovi->bl_present_flag,
6822 dovi->dv_bl_signal_compatibility_id
6828 static const MOVParseTableEntry mov_default_parse_table[] = {
6829 { MKTAG('A','C','L','R'), mov_read_aclr },
6830 { MKTAG('A','P','R','G'), mov_read_avid },
6831 { MKTAG('A','A','L','P'), mov_read_avid },
6832 { MKTAG('A','R','E','S'), mov_read_ares },
6833 { MKTAG('a','v','s','s'), mov_read_avss },
6834 { MKTAG('a','v','1','C'), mov_read_av1c },
6835 { MKTAG('c','h','p','l'), mov_read_chpl },
6836 { MKTAG('c','o','6','4'), mov_read_stco },
6837 { MKTAG('c','o','l','r'), mov_read_colr },
6838 { MKTAG('c','t','t','s'), mov_read_ctts }, /* composition time to sample */
6839 { MKTAG('d','i','n','f'), mov_read_default },
6840 { MKTAG('D','p','x','E'), mov_read_dpxe },
6841 { MKTAG('d','r','e','f'), mov_read_dref },
6842 { MKTAG('e','d','t','s'), mov_read_default },
6843 { MKTAG('e','l','s','t'), mov_read_elst },
6844 { MKTAG('e','n','d','a'), mov_read_enda },
6845 { MKTAG('f','i','e','l'), mov_read_fiel },
6846 { MKTAG('a','d','r','m'), mov_read_adrm },
6847 { MKTAG('f','t','y','p'), mov_read_ftyp },
6848 { MKTAG('g','l','b','l'), mov_read_glbl },
6849 { MKTAG('h','d','l','r'), mov_read_hdlr },
6850 { MKTAG('i','l','s','t'), mov_read_ilst },
6851 { MKTAG('j','p','2','h'), mov_read_jp2h },
6852 { MKTAG('m','d','a','t'), mov_read_mdat },
6853 { MKTAG('m','d','h','d'), mov_read_mdhd },
6854 { MKTAG('m','d','i','a'), mov_read_default },
6855 { MKTAG('m','e','t','a'), mov_read_meta },
6856 { MKTAG('m','i','n','f'), mov_read_default },
6857 { MKTAG('m','o','o','f'), mov_read_moof },
6858 { MKTAG('m','o','o','v'), mov_read_moov },
6859 { MKTAG('m','v','e','x'), mov_read_default },
6860 { MKTAG('m','v','h','d'), mov_read_mvhd },
6861 { MKTAG('S','M','I',' '), mov_read_svq3 },
6862 { MKTAG('a','l','a','c'), mov_read_alac }, /* alac specific atom */
6863 { MKTAG('a','v','c','C'), mov_read_glbl },
6864 { MKTAG('p','a','s','p'), mov_read_pasp },
6865 { MKTAG('s','i','d','x'), mov_read_sidx },
6866 { MKTAG('s','t','b','l'), mov_read_default },
6867 { MKTAG('s','t','c','o'), mov_read_stco },
6868 { MKTAG('s','t','p','s'), mov_read_stps },
6869 { MKTAG('s','t','r','f'), mov_read_strf },
6870 { MKTAG('s','t','s','c'), mov_read_stsc },
6871 { MKTAG('s','t','s','d'), mov_read_stsd }, /* sample description */
6872 { MKTAG('s','t','s','s'), mov_read_stss }, /* sync sample */
6873 { MKTAG('s','t','s','z'), mov_read_stsz }, /* sample size */
6874 { MKTAG('s','t','t','s'), mov_read_stts },
6875 { MKTAG('s','t','z','2'), mov_read_stsz }, /* compact sample size */
6876 { MKTAG('s','d','t','p'), mov_read_sdtp }, /* independent and disposable samples */
6877 { MKTAG('t','k','h','d'), mov_read_tkhd }, /* track header */
6878 { MKTAG('t','f','d','t'), mov_read_tfdt },
6879 { MKTAG('t','f','h','d'), mov_read_tfhd }, /* track fragment header */
6880 { MKTAG('t','r','a','k'), mov_read_trak },
6881 { MKTAG('t','r','a','f'), mov_read_default },
6882 { MKTAG('t','r','e','f'), mov_read_default },
6883 { MKTAG('t','m','c','d'), mov_read_tmcd },
6884 { MKTAG('c','h','a','p'), mov_read_chap },
6885 { MKTAG('t','r','e','x'), mov_read_trex },
6886 { MKTAG('t','r','u','n'), mov_read_trun },
6887 { MKTAG('u','d','t','a'), mov_read_default },
6888 { MKTAG('w','a','v','e'), mov_read_wave },
6889 { MKTAG('e','s','d','s'), mov_read_esds },
6890 { MKTAG('d','a','c','3'), mov_read_dac3 }, /* AC-3 info */
6891 { MKTAG('d','e','c','3'), mov_read_dec3 }, /* EAC-3 info */
6892 { MKTAG('d','d','t','s'), mov_read_ddts }, /* DTS audio descriptor */
6893 { MKTAG('w','i','d','e'), mov_read_wide }, /* place holder */
6894 { MKTAG('w','f','e','x'), mov_read_wfex },
6895 { MKTAG('c','m','o','v'), mov_read_cmov },
6896 { MKTAG('c','h','a','n'), mov_read_chan }, /* channel layout */
6897 { MKTAG('d','v','c','1'), mov_read_dvc1 },
6898 { MKTAG('s','b','g','p'), mov_read_sbgp },
6899 { MKTAG('h','v','c','C'), mov_read_glbl },
6900 { MKTAG('u','u','i','d'), mov_read_uuid },
6901 { MKTAG('C','i','n', 0x8e), mov_read_targa_y216 },
6902 { MKTAG('f','r','e','e'), mov_read_free },
6903 { MKTAG('-','-','-','-'), mov_read_custom },
6904 { MKTAG('s','i','n','f'), mov_read_default },
6905 { MKTAG('f','r','m','a'), mov_read_frma },
6906 { MKTAG('s','e','n','c'), mov_read_senc },
6907 { MKTAG('s','a','i','z'), mov_read_saiz },
6908 { MKTAG('s','a','i','o'), mov_read_saio },
6909 { MKTAG('p','s','s','h'), mov_read_pssh },
6910 { MKTAG('s','c','h','m'), mov_read_schm },
6911 { MKTAG('s','c','h','i'), mov_read_default },
6912 { MKTAG('t','e','n','c'), mov_read_tenc },
6913 { MKTAG('d','f','L','a'), mov_read_dfla },
6914 { MKTAG('s','t','3','d'), mov_read_st3d }, /* stereoscopic 3D video box */
6915 { MKTAG('s','v','3','d'), mov_read_sv3d }, /* spherical video box */
6916 { MKTAG('d','O','p','s'), mov_read_dops },
6917 { MKTAG('d','m','l','p'), mov_read_dmlp },
6918 { MKTAG('S','m','D','m'), mov_read_smdm },
6919 { MKTAG('C','o','L','L'), mov_read_coll },
6920 { MKTAG('v','p','c','C'), mov_read_vpcc },
6921 { MKTAG('m','d','c','v'), mov_read_mdcv },
6922 { MKTAG('c','l','l','i'), mov_read_clli },
6923 { MKTAG('d','v','c','C'), mov_read_dvcc_dvvc },
6924 { MKTAG('d','v','v','C'), mov_read_dvcc_dvvc },
6928 static int mov_read_default(MOVContext *c, AVIOContext *pb, MOVAtom atom)
6930 int64_t total_size = 0;
6934 if (c->atom_depth > 10) {
6935 av_log(c->fc, AV_LOG_ERROR, "Atoms too deeply nested\n");
6936 return AVERROR_INVALIDDATA;
6941 atom.size = INT64_MAX;
6942 while (total_size <= atom.size - 8 && !avio_feof(pb)) {
6943 int (*parse)(MOVContext*, AVIOContext*, MOVAtom) = NULL;
6946 if (atom.size >= 8) {
6947 a.size = avio_rb32(pb);
6948 a.type = avio_rl32(pb);
6949 if (((a.type == MKTAG('f','r','e','e') && c->moov_retry) ||
6950 a.type == MKTAG('h','o','o','v')) &&
6952 c->fc->strict_std_compliance < FF_COMPLIANCE_STRICT) {
6954 uint32_t *type = (uint32_t *)buf + 1;
6955 if (avio_read(pb, buf, 8) != 8)
6956 return AVERROR_INVALIDDATA;
6957 avio_seek(pb, -8, SEEK_CUR);
6958 if (*type == MKTAG('m','v','h','d') ||
6959 *type == MKTAG('c','m','o','v')) {
6960 av_log(c->fc, AV_LOG_ERROR, "Detected moov in a free or hoov atom.\n");
6961 a.type = MKTAG('m','o','o','v');
6964 if (atom.type != MKTAG('r','o','o','t') &&
6965 atom.type != MKTAG('m','o','o','v'))
6967 if (a.type == MKTAG('t','r','a','k') || a.type == MKTAG('m','d','a','t'))
6969 av_log(c->fc, AV_LOG_ERROR, "Broken file, trak/mdat not at top-level\n");
6976 if (a.size == 1 && total_size + 8 <= atom.size) { /* 64 bit extended size */
6977 a.size = avio_rb64(pb) - 8;
6981 av_log(c->fc, AV_LOG_TRACE, "type:'%s' parent:'%s' sz: %"PRId64" %"PRId64" %"PRId64"\n",
6982 av_fourcc2str(a.type), av_fourcc2str(atom.type), a.size, total_size, atom.size);
6984 a.size = atom.size - total_size + 8;
6989 a.size = FFMIN(a.size, atom.size - total_size);
6991 for (i = 0; mov_default_parse_table[i].type; i++)
6992 if (mov_default_parse_table[i].type == a.type) {
6993 parse = mov_default_parse_table[i].parse;
6997 // container is user data
6998 if (!parse && (atom.type == MKTAG('u','d','t','a') ||
6999 atom.type == MKTAG('i','l','s','t')))
7000 parse = mov_read_udta_string;
7002 // Supports parsing the QuickTime Metadata Keys.
7003 // https://developer.apple.com/library/mac/documentation/QuickTime/QTFF/Metadata/Metadata.html
7004 if (!parse && c->found_hdlr_mdta &&
7005 atom.type == MKTAG('m','e','t','a') &&
7006 a.type == MKTAG('k','e','y','s') &&
7007 c->meta_keys_count == 0) {
7008 parse = mov_read_keys;
7011 if (!parse) { /* skip leaf atoms data */
7012 avio_skip(pb, a.size);
7014 int64_t start_pos = avio_tell(pb);
7016 int err = parse(c, pb, a);
7021 if (c->found_moov && c->found_mdat &&
7022 ((!(pb->seekable & AVIO_SEEKABLE_NORMAL) || c->fc->flags & AVFMT_FLAG_IGNIDX || c->frag_index.complete) ||
7023 start_pos + a.size == avio_size(pb))) {
7024 if (!(pb->seekable & AVIO_SEEKABLE_NORMAL) || c->fc->flags & AVFMT_FLAG_IGNIDX || c->frag_index.complete)
7025 c->next_root_atom = start_pos + a.size;
7029 left = a.size - avio_tell(pb) + start_pos;
7030 if (left > 0) /* skip garbage at atom end */
7031 avio_skip(pb, left);
7032 else if (left < 0) {
7033 av_log(c->fc, AV_LOG_WARNING,
7034 "overread end of atom '%.4s' by %"PRId64" bytes\n",
7035 (char*)&a.type, -left);
7036 avio_seek(pb, left, SEEK_CUR);
7040 total_size += a.size;
7043 if (total_size < atom.size && atom.size < 0x7ffff)
7044 avio_skip(pb, atom.size - total_size);
7050 static int mov_probe(const AVProbeData *p)
7055 int moov_offset = -1;
7057 /* check file header */
7060 /* ignore invalid offset */
7061 if ((offset + 8) > (unsigned int)p->buf_size)
7063 tag = AV_RL32(p->buf + offset + 4);
7065 /* check for obvious tags */
7066 case MKTAG('m','o','o','v'):
7067 moov_offset = offset + 4;
7068 case MKTAG('m','d','a','t'):
7069 case MKTAG('p','n','o','t'): /* detect movs with preview pics like ew.mov and april.mov */
7070 case MKTAG('u','d','t','a'): /* Packet Video PVAuthor adds this and a lot of more junk */
7071 case MKTAG('f','t','y','p'):
7072 if (AV_RB32(p->buf+offset) < 8 &&
7073 (AV_RB32(p->buf+offset) != 1 ||
7074 offset + 12 > (unsigned int)p->buf_size ||
7075 AV_RB64(p->buf+offset + 8) == 0)) {
7076 score = FFMAX(score, AVPROBE_SCORE_EXTENSION);
7077 } else if (tag == MKTAG('f','t','y','p') &&
7078 ( AV_RL32(p->buf + offset + 8) == MKTAG('j','p','2',' ')
7079 || AV_RL32(p->buf + offset + 8) == MKTAG('j','p','x',' ')
7081 score = FFMAX(score, 5);
7083 score = AVPROBE_SCORE_MAX;
7085 offset = FFMAX(4, AV_RB32(p->buf+offset)) + offset;
7087 /* those are more common words, so rate then a bit less */
7088 case MKTAG('e','d','i','w'): /* xdcam files have reverted first tags */
7089 case MKTAG('w','i','d','e'):
7090 case MKTAG('f','r','e','e'):
7091 case MKTAG('j','u','n','k'):
7092 case MKTAG('p','i','c','t'):
7093 score = FFMAX(score, AVPROBE_SCORE_MAX - 5);
7094 offset = FFMAX(4, AV_RB32(p->buf+offset)) + offset;
7096 case MKTAG(0x82,0x82,0x7f,0x7d):
7097 case MKTAG('s','k','i','p'):
7098 case MKTAG('u','u','i','d'):
7099 case MKTAG('p','r','f','l'):
7100 /* if we only find those cause probedata is too small at least rate them */
7101 score = FFMAX(score, AVPROBE_SCORE_EXTENSION);
7102 offset = FFMAX(4, AV_RB32(p->buf+offset)) + offset;
7105 offset = FFMAX(4, AV_RB32(p->buf+offset)) + offset;
7108 if(score > AVPROBE_SCORE_MAX - 50 && moov_offset != -1) {
7109 /* moov atom in the header - we should make sure that this is not a
7110 * MOV-packed MPEG-PS */
7111 offset = moov_offset;
7113 while(offset < (p->buf_size - 16)){ /* Sufficient space */
7114 /* We found an actual hdlr atom */
7115 if(AV_RL32(p->buf + offset ) == MKTAG('h','d','l','r') &&
7116 AV_RL32(p->buf + offset + 8) == MKTAG('m','h','l','r') &&
7117 AV_RL32(p->buf + offset + 12) == MKTAG('M','P','E','G')){
7118 av_log(NULL, AV_LOG_WARNING, "Found media data tag MPEG indicating this is a MOV-packed MPEG-PS.\n");
7119 /* We found a media handler reference atom describing an
7120 * MPEG-PS-in-MOV, return a
7121 * low score to force expanding the probe window until
7122 * mpegps_probe finds what it needs */
7133 // must be done after parsing all trak because there's no order requirement
7134 static void mov_read_chapters(AVFormatContext *s)
7136 MOVContext *mov = s->priv_data;
7138 MOVStreamContext *sc;
7143 for (j = 0; j < mov->nb_chapter_tracks; j++) {
7144 chapter_track = mov->chapter_tracks[j];
7146 for (i = 0; i < s->nb_streams; i++)
7147 if (s->streams[i]->id == chapter_track) {
7152 av_log(s, AV_LOG_ERROR, "Referenced QT chapter track not found\n");
7157 cur_pos = avio_tell(sc->pb);
7159 if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
7160 st->disposition |= AV_DISPOSITION_ATTACHED_PIC | AV_DISPOSITION_TIMED_THUMBNAILS;
7161 if (st->nb_index_entries) {
7162 // Retrieve the first frame, if possible
7163 AVIndexEntry *sample = &st->index_entries[0];
7164 if (avio_seek(sc->pb, sample->pos, SEEK_SET) != sample->pos) {
7165 av_log(s, AV_LOG_ERROR, "Failed to retrieve first frame\n");
7169 if (av_get_packet(sc->pb, &st->attached_pic, sample->size) < 0)
7172 st->attached_pic.stream_index = st->index;
7173 st->attached_pic.flags |= AV_PKT_FLAG_KEY;
7176 st->codecpar->codec_type = AVMEDIA_TYPE_DATA;
7177 st->codecpar->codec_id = AV_CODEC_ID_BIN_DATA;
7178 st->discard = AVDISCARD_ALL;
7179 for (i = 0; i < st->nb_index_entries; i++) {
7180 AVIndexEntry *sample = &st->index_entries[i];
7181 int64_t end = i+1 < st->nb_index_entries ? st->index_entries[i+1].timestamp : st->duration;
7186 if (end < sample->timestamp) {
7187 av_log(s, AV_LOG_WARNING, "ignoring stream duration which is shorter than chapters\n");
7188 end = AV_NOPTS_VALUE;
7191 if (avio_seek(sc->pb, sample->pos, SEEK_SET) != sample->pos) {
7192 av_log(s, AV_LOG_ERROR, "Chapter %d not found in file\n", i);
7196 // the first two bytes are the length of the title
7197 len = avio_rb16(sc->pb);
7198 if (len > sample->size-2)
7200 title_len = 2*len + 1;
7201 if (!(title = av_mallocz(title_len)))
7204 // The samples could theoretically be in any encoding if there's an encd
7205 // atom following, but in practice are only utf-8 or utf-16, distinguished
7206 // instead by the presence of a BOM
7210 ch = avio_rb16(sc->pb);
7212 avio_get_str16be(sc->pb, len, title, title_len);
7213 else if (ch == 0xfffe)
7214 avio_get_str16le(sc->pb, len, title, title_len);
7217 if (len == 1 || len == 2)
7220 avio_get_str(sc->pb, INT_MAX, title + 2, len - 1);
7224 avpriv_new_chapter(s, i, st->time_base, sample->timestamp, end, title);
7229 avio_seek(sc->pb, cur_pos, SEEK_SET);
7233 static int parse_timecode_in_framenum_format(AVFormatContext *s, AVStream *st,
7234 uint32_t value, int flags)
7237 char buf[AV_TIMECODE_STR_SIZE];
7238 AVRational rate = st->avg_frame_rate;
7239 int ret = av_timecode_init(&tc, rate, flags, 0, s);
7242 av_dict_set(&st->metadata, "timecode",
7243 av_timecode_make_string(&tc, buf, value), 0);
7247 static int mov_read_rtmd_track(AVFormatContext *s, AVStream *st)
7249 MOVStreamContext *sc = st->priv_data;
7250 char buf[AV_TIMECODE_STR_SIZE];
7251 int64_t cur_pos = avio_tell(sc->pb);
7252 int hh, mm, ss, ff, drop;
7254 if (!st->nb_index_entries)
7257 avio_seek(sc->pb, st->index_entries->pos, SEEK_SET);
7258 avio_skip(s->pb, 13);
7259 hh = avio_r8(s->pb);
7260 mm = avio_r8(s->pb);
7261 ss = avio_r8(s->pb);
7262 drop = avio_r8(s->pb);
7263 ff = avio_r8(s->pb);
7264 snprintf(buf, AV_TIMECODE_STR_SIZE, "%02d:%02d:%02d%c%02d",
7265 hh, mm, ss, drop ? ';' : ':', ff);
7266 av_dict_set(&st->metadata, "timecode", buf, 0);
7268 avio_seek(sc->pb, cur_pos, SEEK_SET);
7272 static int mov_read_timecode_track(AVFormatContext *s, AVStream *st)
7274 MOVStreamContext *sc = st->priv_data;
7276 int64_t cur_pos = avio_tell(sc->pb);
7279 if (!st->nb_index_entries)
7282 avio_seek(sc->pb, st->index_entries->pos, SEEK_SET);
7283 value = avio_rb32(s->pb);
7285 if (sc->tmcd_flags & 0x0001) flags |= AV_TIMECODE_FLAG_DROPFRAME;
7286 if (sc->tmcd_flags & 0x0002) flags |= AV_TIMECODE_FLAG_24HOURSMAX;
7287 if (sc->tmcd_flags & 0x0004) flags |= AV_TIMECODE_FLAG_ALLOWNEGATIVE;
7289 /* Assume Counter flag is set to 1 in tmcd track (even though it is likely
7290 * not the case) and thus assume "frame number format" instead of QT one.
7291 * No sample with tmcd track can be found with a QT timecode at the moment,
7292 * despite what the tmcd track "suggests" (Counter flag set to 0 means QT
7294 parse_timecode_in_framenum_format(s, st, value, flags);
7296 avio_seek(sc->pb, cur_pos, SEEK_SET);
7300 static void mov_free_encryption_index(MOVEncryptionIndex **index) {
7302 if (!index || !*index) return;
7303 for (i = 0; i < (*index)->nb_encrypted_samples; i++) {
7304 av_encryption_info_free((*index)->encrypted_samples[i]);
7306 av_freep(&(*index)->encrypted_samples);
7307 av_freep(&(*index)->auxiliary_info_sizes);
7308 av_freep(&(*index)->auxiliary_offsets);
7312 static int mov_read_close(AVFormatContext *s)
7314 MOVContext *mov = s->priv_data;
7317 for (i = 0; i < s->nb_streams; i++) {
7318 AVStream *st = s->streams[i];
7319 MOVStreamContext *sc = st->priv_data;
7324 av_freep(&sc->ctts_data);
7325 for (j = 0; j < sc->drefs_count; j++) {
7326 av_freep(&sc->drefs[j].path);
7327 av_freep(&sc->drefs[j].dir);
7329 av_freep(&sc->drefs);
7331 sc->drefs_count = 0;
7333 if (!sc->pb_is_copied)
7334 ff_format_io_close(s, &sc->pb);
7337 av_freep(&sc->chunk_offsets);
7338 av_freep(&sc->stsc_data);
7339 av_freep(&sc->sample_sizes);
7340 av_freep(&sc->keyframes);
7341 av_freep(&sc->stts_data);
7342 av_freep(&sc->sdtp_data);
7343 av_freep(&sc->stps_data);
7344 av_freep(&sc->elst_data);
7345 av_freep(&sc->rap_group);
7346 av_freep(&sc->display_matrix);
7347 av_freep(&sc->index_ranges);
7350 for (j = 0; j < sc->stsd_count; j++)
7351 av_free(sc->extradata[j]);
7352 av_freep(&sc->extradata);
7353 av_freep(&sc->extradata_size);
7355 mov_free_encryption_index(&sc->cenc.encryption_index);
7356 av_encryption_info_free(sc->cenc.default_encrypted_sample);
7357 av_aes_ctr_free(sc->cenc.aes_ctr);
7359 av_freep(&sc->stereo3d);
7360 av_freep(&sc->spherical);
7361 av_freep(&sc->mastering);
7362 av_freep(&sc->coll);
7365 if (mov->dv_demux) {
7366 avformat_free_context(mov->dv_fctx);
7367 mov->dv_fctx = NULL;
7370 if (mov->meta_keys) {
7371 for (i = 1; i < mov->meta_keys_count; i++) {
7372 av_freep(&mov->meta_keys[i]);
7374 av_freep(&mov->meta_keys);
7377 av_freep(&mov->trex_data);
7378 av_freep(&mov->bitrates);
7380 for (i = 0; i < mov->frag_index.nb_items; i++) {
7381 MOVFragmentStreamInfo *frag = mov->frag_index.item[i].stream_info;
7382 for (j = 0; j < mov->frag_index.item[i].nb_stream_info; j++) {
7383 mov_free_encryption_index(&frag[j].encryption_index);
7385 av_freep(&mov->frag_index.item[i].stream_info);
7387 av_freep(&mov->frag_index.item);
7389 av_freep(&mov->aes_decrypt);
7390 av_freep(&mov->chapter_tracks);
7395 static int tmcd_is_referenced(AVFormatContext *s, int tmcd_id)
7399 for (i = 0; i < s->nb_streams; i++) {
7400 AVStream *st = s->streams[i];
7401 MOVStreamContext *sc = st->priv_data;
7403 if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO &&
7404 sc->timecode_track == tmcd_id)
7410 /* look for a tmcd track not referenced by any video track, and export it globally */
7411 static void export_orphan_timecode(AVFormatContext *s)
7415 for (i = 0; i < s->nb_streams; i++) {
7416 AVStream *st = s->streams[i];
7418 if (st->codecpar->codec_tag == MKTAG('t','m','c','d') &&
7419 !tmcd_is_referenced(s, i + 1)) {
7420 AVDictionaryEntry *tcr = av_dict_get(st->metadata, "timecode", NULL, 0);
7422 av_dict_set(&s->metadata, "timecode", tcr->value, 0);
7429 static int read_tfra(MOVContext *mov, AVIOContext *f)
7431 int version, fieldlength, i, j;
7432 int64_t pos = avio_tell(f);
7433 uint32_t size = avio_rb32(f);
7434 unsigned track_id, item_count;
7436 if (avio_rb32(f) != MKBETAG('t', 'f', 'r', 'a')) {
7439 av_log(mov->fc, AV_LOG_VERBOSE, "found tfra\n");
7441 version = avio_r8(f);
7443 track_id = avio_rb32(f);
7444 fieldlength = avio_rb32(f);
7445 item_count = avio_rb32(f);
7446 for (i = 0; i < item_count; i++) {
7447 int64_t time, offset;
7449 MOVFragmentStreamInfo * frag_stream_info;
7452 return AVERROR_INVALIDDATA;
7456 time = avio_rb64(f);
7457 offset = avio_rb64(f);
7459 time = avio_rb32(f);
7460 offset = avio_rb32(f);
7463 // The first sample of each stream in a fragment is always a random
7464 // access sample. So it's entry in the tfra can be used as the
7465 // initial PTS of the fragment.
7466 index = update_frag_index(mov, offset);
7467 frag_stream_info = get_frag_stream_info(&mov->frag_index, index, track_id);
7468 if (frag_stream_info &&
7469 frag_stream_info->first_tfra_pts == AV_NOPTS_VALUE)
7470 frag_stream_info->first_tfra_pts = time;
7472 for (j = 0; j < ((fieldlength >> 4) & 3) + 1; j++)
7474 for (j = 0; j < ((fieldlength >> 2) & 3) + 1; j++)
7476 for (j = 0; j < ((fieldlength >> 0) & 3) + 1; j++)
7480 avio_seek(f, pos + size, SEEK_SET);
7484 static int mov_read_mfra(MOVContext *c, AVIOContext *f)
7486 int64_t stream_size = avio_size(f);
7487 int64_t original_pos = avio_tell(f);
7491 if ((seek_ret = avio_seek(f, stream_size - 4, SEEK_SET)) < 0) {
7495 mfra_size = avio_rb32(f);
7496 if (mfra_size < 0 || mfra_size > stream_size) {
7497 av_log(c->fc, AV_LOG_DEBUG, "doesn't look like mfra (unreasonable size)\n");
7500 if ((seek_ret = avio_seek(f, -mfra_size, SEEK_CUR)) < 0) {
7504 if (avio_rb32(f) != mfra_size) {
7505 av_log(c->fc, AV_LOG_DEBUG, "doesn't look like mfra (size mismatch)\n");
7508 if (avio_rb32(f) != MKBETAG('m', 'f', 'r', 'a')) {
7509 av_log(c->fc, AV_LOG_DEBUG, "doesn't look like mfra (tag mismatch)\n");
7512 av_log(c->fc, AV_LOG_VERBOSE, "stream has mfra\n");
7514 ret = read_tfra(c, f);
7520 seek_ret = avio_seek(f, original_pos, SEEK_SET);
7522 av_log(c->fc, AV_LOG_ERROR,
7523 "failed to seek back after looking for mfra\n");
7529 static int mov_read_header(AVFormatContext *s)
7531 MOVContext *mov = s->priv_data;
7532 AVIOContext *pb = s->pb;
7534 MOVAtom atom = { AV_RL32("root") };
7537 if (mov->decryption_key_len != 0 && mov->decryption_key_len != AES_CTR_KEY_SIZE) {
7538 av_log(s, AV_LOG_ERROR, "Invalid decryption key len %d expected %d\n",
7539 mov->decryption_key_len, AES_CTR_KEY_SIZE);
7540 return AVERROR(EINVAL);
7544 mov->trak_index = -1;
7545 /* .mov and .mp4 aren't streamable anyway (only progressive download if moov is before mdat) */
7546 if (pb->seekable & AVIO_SEEKABLE_NORMAL)
7547 atom.size = avio_size(pb);
7549 atom.size = INT64_MAX;
7551 /* check MOV header */
7553 if (mov->moov_retry)
7554 avio_seek(pb, 0, SEEK_SET);
7555 if ((err = mov_read_default(mov, pb, atom)) < 0) {
7556 av_log(s, AV_LOG_ERROR, "error reading header\n");
7559 } while ((pb->seekable & AVIO_SEEKABLE_NORMAL) && !mov->found_moov && !mov->moov_retry++);
7560 if (!mov->found_moov) {
7561 av_log(s, AV_LOG_ERROR, "moov atom not found\n");
7562 err = AVERROR_INVALIDDATA;
7565 av_log(mov->fc, AV_LOG_TRACE, "on_parse_exit_offset=%"PRId64"\n", avio_tell(pb));
7567 if (pb->seekable & AVIO_SEEKABLE_NORMAL) {
7568 if (mov->nb_chapter_tracks > 0 && !mov->ignore_chapters)
7569 mov_read_chapters(s);
7570 for (i = 0; i < s->nb_streams; i++)
7571 if (s->streams[i]->codecpar->codec_tag == AV_RL32("tmcd")) {
7572 mov_read_timecode_track(s, s->streams[i]);
7573 } else if (s->streams[i]->codecpar->codec_tag == AV_RL32("rtmd")) {
7574 mov_read_rtmd_track(s, s->streams[i]);
7578 /* copy timecode metadata from tmcd tracks to the related video streams */
7579 for (i = 0; i < s->nb_streams; i++) {
7580 AVStream *st = s->streams[i];
7581 MOVStreamContext *sc = st->priv_data;
7582 if (sc->timecode_track > 0) {
7583 AVDictionaryEntry *tcr;
7584 int tmcd_st_id = -1;
7586 for (j = 0; j < s->nb_streams; j++)
7587 if (s->streams[j]->id == sc->timecode_track)
7590 if (tmcd_st_id < 0 || tmcd_st_id == i)
7592 tcr = av_dict_get(s->streams[tmcd_st_id]->metadata, "timecode", NULL, 0);
7594 av_dict_set(&st->metadata, "timecode", tcr->value, 0);
7597 export_orphan_timecode(s);
7599 for (i = 0; i < s->nb_streams; i++) {
7600 AVStream *st = s->streams[i];
7601 MOVStreamContext *sc = st->priv_data;
7602 fix_timescale(mov, sc);
7603 if(st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO && st->codecpar->codec_id == AV_CODEC_ID_AAC) {
7604 st->skip_samples = sc->start_pad;
7606 if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && sc->nb_frames_for_fps > 0 && sc->duration_for_fps > 0)
7607 av_reduce(&st->avg_frame_rate.num, &st->avg_frame_rate.den,
7608 sc->time_scale*(int64_t)sc->nb_frames_for_fps, sc->duration_for_fps, INT_MAX);
7609 if (st->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE) {
7610 if (st->codecpar->width <= 0 || st->codecpar->height <= 0) {
7611 st->codecpar->width = sc->width;
7612 st->codecpar->height = sc->height;
7614 if (st->codecpar->codec_id == AV_CODEC_ID_DVD_SUBTITLE) {
7615 if ((err = mov_rewrite_dvd_sub_extradata(st)) < 0)
7619 if (mov->handbrake_version &&
7620 mov->handbrake_version <= 1000000*0 + 1000*10 + 2 && // 0.10.2
7621 st->codecpar->codec_id == AV_CODEC_ID_MP3
7623 av_log(s, AV_LOG_VERBOSE, "Forcing full parsing for mp3 stream\n");
7624 st->need_parsing = AVSTREAM_PARSE_FULL;
7628 if (mov->trex_data) {
7629 for (i = 0; i < s->nb_streams; i++) {
7630 AVStream *st = s->streams[i];
7631 MOVStreamContext *sc = st->priv_data;
7632 if (st->duration > 0) {
7633 if (sc->data_size > INT64_MAX / sc->time_scale / 8) {
7634 av_log(s, AV_LOG_ERROR, "Overflow during bit rate calculation %"PRId64" * 8 * %d\n",
7635 sc->data_size, sc->time_scale);
7636 err = AVERROR_INVALIDDATA;
7639 st->codecpar->bit_rate = sc->data_size * 8 * sc->time_scale / st->duration;
7644 if (mov->use_mfra_for > 0) {
7645 for (i = 0; i < s->nb_streams; i++) {
7646 AVStream *st = s->streams[i];
7647 MOVStreamContext *sc = st->priv_data;
7648 if (sc->duration_for_fps > 0) {
7649 if (sc->data_size > INT64_MAX / sc->time_scale / 8) {
7650 av_log(s, AV_LOG_ERROR, "Overflow during bit rate calculation %"PRId64" * 8 * %d\n",
7651 sc->data_size, sc->time_scale);
7652 err = AVERROR_INVALIDDATA;
7655 st->codecpar->bit_rate = sc->data_size * 8 * sc->time_scale /
7656 sc->duration_for_fps;
7661 for (i = 0; i < mov->bitrates_count && i < s->nb_streams; i++) {
7662 if (mov->bitrates[i]) {
7663 s->streams[i]->codecpar->bit_rate = mov->bitrates[i];
7667 ff_rfps_calculate(s);
7669 for (i = 0; i < s->nb_streams; i++) {
7670 AVStream *st = s->streams[i];
7671 MOVStreamContext *sc = st->priv_data;
7673 switch (st->codecpar->codec_type) {
7674 case AVMEDIA_TYPE_AUDIO:
7675 err = ff_replaygain_export(st, s->metadata);
7680 case AVMEDIA_TYPE_VIDEO:
7681 if (sc->display_matrix) {
7682 err = av_stream_add_side_data(st, AV_PKT_DATA_DISPLAYMATRIX, (uint8_t*)sc->display_matrix,
7683 sizeof(int32_t) * 9);
7687 sc->display_matrix = NULL;
7690 err = av_stream_add_side_data(st, AV_PKT_DATA_STEREO3D,
7691 (uint8_t *)sc->stereo3d,
7692 sizeof(*sc->stereo3d));
7696 sc->stereo3d = NULL;
7698 if (sc->spherical) {
7699 err = av_stream_add_side_data(st, AV_PKT_DATA_SPHERICAL,
7700 (uint8_t *)sc->spherical,
7701 sc->spherical_size);
7705 sc->spherical = NULL;
7707 if (sc->mastering) {
7708 err = av_stream_add_side_data(st, AV_PKT_DATA_MASTERING_DISPLAY_METADATA,
7709 (uint8_t *)sc->mastering,
7710 sizeof(*sc->mastering));
7714 sc->mastering = NULL;
7717 err = av_stream_add_side_data(st, AV_PKT_DATA_CONTENT_LIGHT_LEVEL,
7718 (uint8_t *)sc->coll,
7728 ff_configure_buffers_for_index(s, AV_TIME_BASE);
7730 for (i = 0; i < mov->frag_index.nb_items; i++)
7731 if (mov->frag_index.item[i].moof_offset <= mov->fragment.moof_offset)
7732 mov->frag_index.item[i].headers_read = 1;
7740 static AVIndexEntry *mov_find_next_sample(AVFormatContext *s, AVStream **st)
7742 AVIndexEntry *sample = NULL;
7743 int64_t best_dts = INT64_MAX;
7745 for (i = 0; i < s->nb_streams; i++) {
7746 AVStream *avst = s->streams[i];
7747 MOVStreamContext *msc = avst->priv_data;
7748 if (msc->pb && msc->current_sample < avst->nb_index_entries) {
7749 AVIndexEntry *current_sample = &avst->index_entries[msc->current_sample];
7750 int64_t dts = av_rescale(current_sample->timestamp, AV_TIME_BASE, msc->time_scale);
7751 av_log(s, AV_LOG_TRACE, "stream %d, sample %d, dts %"PRId64"\n", i, msc->current_sample, dts);
7752 if (!sample || (!(s->pb->seekable & AVIO_SEEKABLE_NORMAL) && current_sample->pos < sample->pos) ||
7753 ((s->pb->seekable & AVIO_SEEKABLE_NORMAL) &&
7754 ((msc->pb != s->pb && dts < best_dts) || (msc->pb == s->pb && dts != AV_NOPTS_VALUE &&
7755 ((FFABS(best_dts - dts) <= AV_TIME_BASE && current_sample->pos < sample->pos) ||
7756 (FFABS(best_dts - dts) > AV_TIME_BASE && dts < best_dts)))))) {
7757 sample = current_sample;
7766 static int should_retry(AVIOContext *pb, int error_code) {
7767 if (error_code == AVERROR_EOF || avio_feof(pb))
7773 static int mov_switch_root(AVFormatContext *s, int64_t target, int index)
7776 MOVContext *mov = s->priv_data;
7778 if (index >= 0 && index < mov->frag_index.nb_items)
7779 target = mov->frag_index.item[index].moof_offset;
7780 if (avio_seek(s->pb, target, SEEK_SET) != target) {
7781 av_log(mov->fc, AV_LOG_ERROR, "root atom offset 0x%"PRIx64": partial file\n", target);
7782 return AVERROR_INVALIDDATA;
7785 mov->next_root_atom = 0;
7786 if (index < 0 || index >= mov->frag_index.nb_items)
7787 index = search_frag_moof_offset(&mov->frag_index, target);
7788 if (index < mov->frag_index.nb_items &&
7789 mov->frag_index.item[index].moof_offset == target) {
7790 if (index + 1 < mov->frag_index.nb_items)
7791 mov->next_root_atom = mov->frag_index.item[index + 1].moof_offset;
7792 if (mov->frag_index.item[index].headers_read)
7794 mov->frag_index.item[index].headers_read = 1;
7797 mov->found_mdat = 0;
7799 ret = mov_read_default(mov, s->pb, (MOVAtom){ AV_RL32("root"), INT64_MAX });
7802 if (avio_feof(s->pb))
7804 av_log(s, AV_LOG_TRACE, "read fragments, offset 0x%"PRIx64"\n", avio_tell(s->pb));
7809 static int mov_change_extradata(MOVStreamContext *sc, AVPacket *pkt)
7811 uint8_t *side, *extradata;
7814 /* Save the current index. */
7815 sc->last_stsd_index = sc->stsc_data[sc->stsc_index].id - 1;
7817 /* Notify the decoder that extradata changed. */
7818 extradata_size = sc->extradata_size[sc->last_stsd_index];
7819 extradata = sc->extradata[sc->last_stsd_index];
7820 if (extradata_size > 0 && extradata) {
7821 side = av_packet_new_side_data(pkt,
7822 AV_PKT_DATA_NEW_EXTRADATA,
7825 return AVERROR(ENOMEM);
7826 memcpy(side, extradata, extradata_size);
7832 static int get_eia608_packet(AVIOContext *pb, AVPacket *pkt, int size)
7837 return AVERROR_INVALIDDATA;
7838 new_size = ((size - 8) / 2) * 3;
7839 ret = av_new_packet(pkt, new_size);
7844 for (int j = 0; j < new_size; j += 3) {
7845 pkt->data[j] = 0xFC;
7846 pkt->data[j+1] = avio_r8(pb);
7847 pkt->data[j+2] = avio_r8(pb);
7853 static int mov_read_packet(AVFormatContext *s, AVPacket *pkt)
7855 MOVContext *mov = s->priv_data;
7856 MOVStreamContext *sc;
7857 AVIndexEntry *sample;
7858 AVStream *st = NULL;
7859 int64_t current_index;
7863 sample = mov_find_next_sample(s, &st);
7864 if (!sample || (mov->next_root_atom && sample->pos > mov->next_root_atom)) {
7865 if (!mov->next_root_atom)
7867 if ((ret = mov_switch_root(s, mov->next_root_atom, -1)) < 0)
7872 /* must be done just before reading, to avoid infinite loop on sample */
7873 current_index = sc->current_index;
7874 mov_current_sample_inc(sc);
7876 if (mov->next_root_atom) {
7877 sample->pos = FFMIN(sample->pos, mov->next_root_atom);
7878 sample->size = FFMIN(sample->size, (mov->next_root_atom - sample->pos));
7881 if (st->discard != AVDISCARD_ALL) {
7882 int64_t ret64 = avio_seek(sc->pb, sample->pos, SEEK_SET);
7883 if (ret64 != sample->pos) {
7884 av_log(mov->fc, AV_LOG_ERROR, "stream %d, offset 0x%"PRIx64": partial file\n",
7885 sc->ffindex, sample->pos);
7886 if (should_retry(sc->pb, ret64)) {
7887 mov_current_sample_dec(sc);
7889 return AVERROR_INVALIDDATA;
7892 if( st->discard == AVDISCARD_NONKEY && 0==(sample->flags & AVINDEX_KEYFRAME) ) {
7893 av_log(mov->fc, AV_LOG_DEBUG, "Nonkey frame from stream %d discarded due to AVDISCARD_NONKEY\n", sc->ffindex);
7897 if (st->codecpar->codec_id == AV_CODEC_ID_EIA_608 && sample->size > 8)
7898 ret = get_eia608_packet(sc->pb, pkt, sample->size);
7900 ret = av_get_packet(sc->pb, pkt, sample->size);
7902 if (should_retry(sc->pb, ret)) {
7903 mov_current_sample_dec(sc);
7907 if (sc->has_palette) {
7910 pal = av_packet_new_side_data(pkt, AV_PKT_DATA_PALETTE, AVPALETTE_SIZE);
7912 av_log(mov->fc, AV_LOG_ERROR, "Cannot append palette to packet\n");
7914 memcpy(pal, sc->palette, AVPALETTE_SIZE);
7915 sc->has_palette = 0;
7918 #if CONFIG_DV_DEMUXER
7919 if (mov->dv_demux && sc->dv_audio_container) {
7920 avpriv_dv_produce_packet(mov->dv_demux, pkt, pkt->data, pkt->size, pkt->pos);
7921 av_freep(&pkt->data);
7923 ret = avpriv_dv_get_packet(mov->dv_demux, pkt);
7928 if (st->codecpar->codec_id == AV_CODEC_ID_MP3 && !st->need_parsing && pkt->size > 4) {
7929 if (ff_mpa_check_header(AV_RB32(pkt->data)) < 0)
7930 st->need_parsing = AVSTREAM_PARSE_FULL;
7934 pkt->stream_index = sc->ffindex;
7935 pkt->dts = sample->timestamp;
7936 if (sample->flags & AVINDEX_DISCARD_FRAME) {
7937 pkt->flags |= AV_PKT_FLAG_DISCARD;
7939 if (sc->ctts_data && sc->ctts_index < sc->ctts_count) {
7940 pkt->pts = pkt->dts + sc->dts_shift + sc->ctts_data[sc->ctts_index].duration;
7941 /* update ctts context */
7943 if (sc->ctts_index < sc->ctts_count &&
7944 sc->ctts_data[sc->ctts_index].count == sc->ctts_sample) {
7946 sc->ctts_sample = 0;
7949 int64_t next_dts = (sc->current_sample < st->nb_index_entries) ?
7950 st->index_entries[sc->current_sample].timestamp : st->duration;
7952 if (next_dts >= pkt->dts)
7953 pkt->duration = next_dts - pkt->dts;
7954 pkt->pts = pkt->dts;
7956 if (st->discard == AVDISCARD_ALL)
7958 if (sc->sdtp_data && sc->current_sample <= sc->sdtp_count) {
7959 uint8_t sample_flags = sc->sdtp_data[sc->current_sample - 1];
7960 uint8_t sample_is_depended_on = (sample_flags >> 2) & 0x3;
7961 pkt->flags |= sample_is_depended_on == MOV_SAMPLE_DEPENDENCY_NO ? AV_PKT_FLAG_DISPOSABLE : 0;
7963 pkt->flags |= sample->flags & AVINDEX_KEYFRAME ? AV_PKT_FLAG_KEY : 0;
7964 pkt->pos = sample->pos;
7966 /* Multiple stsd handling. */
7967 if (sc->stsc_data) {
7968 /* Keep track of the stsc index for the given sample, then check
7969 * if the stsd index is different from the last used one. */
7971 if (mov_stsc_index_valid(sc->stsc_index, sc->stsc_count) &&
7972 mov_get_stsc_samples(sc, sc->stsc_index) == sc->stsc_sample) {
7974 sc->stsc_sample = 0;
7975 /* Do not check indexes after a switch. */
7976 } else if (sc->stsc_data[sc->stsc_index].id > 0 &&
7977 sc->stsc_data[sc->stsc_index].id - 1 < sc->stsd_count &&
7978 sc->stsc_data[sc->stsc_index].id - 1 != sc->last_stsd_index) {
7979 ret = mov_change_extradata(sc, pkt);
7986 aax_filter(pkt->data, pkt->size, mov);
7988 ret = cenc_filter(mov, st, sc, pkt, current_index);
7996 static int mov_seek_fragment(AVFormatContext *s, AVStream *st, int64_t timestamp)
7998 MOVContext *mov = s->priv_data;
8001 if (!mov->frag_index.complete)
8004 index = search_frag_timestamp(&mov->frag_index, st, timestamp);
8007 if (!mov->frag_index.item[index].headers_read)
8008 return mov_switch_root(s, -1, index);
8009 if (index + 1 < mov->frag_index.nb_items)
8010 mov->next_root_atom = mov->frag_index.item[index + 1].moof_offset;
8015 static int mov_seek_stream(AVFormatContext *s, AVStream *st, int64_t timestamp, int flags)
8017 MOVStreamContext *sc = st->priv_data;
8018 int sample, time_sample, ret;
8021 // Here we consider timestamp to be PTS, hence try to offset it so that we
8022 // can search over the DTS timeline.
8023 timestamp -= (sc->min_corrected_pts + sc->dts_shift);
8025 ret = mov_seek_fragment(s, st, timestamp);
8029 sample = av_index_search_timestamp(st, timestamp, flags);
8030 av_log(s, AV_LOG_TRACE, "stream %d, timestamp %"PRId64", sample %d\n", st->index, timestamp, sample);
8031 if (sample < 0 && st->nb_index_entries && timestamp < st->index_entries[0].timestamp)
8033 if (sample < 0) /* not sure what to do */
8034 return AVERROR_INVALIDDATA;
8035 mov_current_sample_set(sc, sample);
8036 av_log(s, AV_LOG_TRACE, "stream %d, found sample %d\n", st->index, sc->current_sample);
8037 /* adjust ctts index */
8038 if (sc->ctts_data) {
8040 for (i = 0; i < sc->ctts_count; i++) {
8041 int next = time_sample + sc->ctts_data[i].count;
8042 if (next > sc->current_sample) {
8044 sc->ctts_sample = sc->current_sample - time_sample;
8051 /* adjust stsd index */
8052 if (sc->chunk_count) {
8054 for (i = 0; i < sc->stsc_count; i++) {
8055 int64_t next = time_sample + mov_get_stsc_samples(sc, i);
8056 if (next > sc->current_sample) {
8058 sc->stsc_sample = sc->current_sample - time_sample;
8061 av_assert0(next == (int)next);
8069 static int mov_read_seek(AVFormatContext *s, int stream_index, int64_t sample_time, int flags)
8071 MOVContext *mc = s->priv_data;
8076 if (stream_index >= s->nb_streams)
8077 return AVERROR_INVALIDDATA;
8079 st = s->streams[stream_index];
8080 sample = mov_seek_stream(s, st, sample_time, flags);
8084 if (mc->seek_individually) {
8085 /* adjust seek timestamp to found sample timestamp */
8086 int64_t seek_timestamp = st->index_entries[sample].timestamp;
8088 for (i = 0; i < s->nb_streams; i++) {
8090 MOVStreamContext *sc = s->streams[i]->priv_data;
8092 st->skip_samples = (sample_time <= 0) ? sc->start_pad : 0;
8094 if (stream_index == i)
8097 timestamp = av_rescale_q(seek_timestamp, s->streams[stream_index]->time_base, st->time_base);
8098 mov_seek_stream(s, st, timestamp, flags);
8101 for (i = 0; i < s->nb_streams; i++) {
8102 MOVStreamContext *sc;
8105 mov_current_sample_set(sc, 0);
8108 MOVStreamContext *sc;
8109 AVIndexEntry *entry = mov_find_next_sample(s, &st);
8111 return AVERROR_INVALIDDATA;
8113 if (sc->ffindex == stream_index && sc->current_sample == sample)
8115 mov_current_sample_inc(sc);
8121 #define OFFSET(x) offsetof(MOVContext, x)
8122 #define FLAGS AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_DECODING_PARAM
8123 static const AVOption mov_options[] = {
8124 {"use_absolute_path",
8125 "allow using absolute path when opening alias, this is a possible security issue",
8126 OFFSET(use_absolute_path), AV_OPT_TYPE_BOOL, {.i64 = 0},
8128 {"seek_streams_individually",
8129 "Seek each stream individually to the closest point",
8130 OFFSET(seek_individually), AV_OPT_TYPE_BOOL, { .i64 = 1 },
8132 {"ignore_editlist", "Ignore the edit list atom.", OFFSET(ignore_editlist), AV_OPT_TYPE_BOOL, {.i64 = 0},
8134 {"advanced_editlist",
8135 "Modify the AVIndex according to the editlists. Use this option to decode in the order specified by the edits.",
8136 OFFSET(advanced_editlist), AV_OPT_TYPE_BOOL, {.i64 = 1},
8138 {"ignore_chapters", "", OFFSET(ignore_chapters), AV_OPT_TYPE_BOOL, {.i64 = 0},
8141 "use mfra for fragment timestamps",
8142 OFFSET(use_mfra_for), AV_OPT_TYPE_INT, {.i64 = FF_MOV_FLAG_MFRA_AUTO},
8143 -1, FF_MOV_FLAG_MFRA_PTS, FLAGS,
8145 {"auto", "auto", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_MFRA_AUTO}, 0, 0,
8146 FLAGS, "use_mfra_for" },
8147 {"dts", "dts", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_MFRA_DTS}, 0, 0,
8148 FLAGS, "use_mfra_for" },
8149 {"pts", "pts", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_MFRA_PTS}, 0, 0,
8150 FLAGS, "use_mfra_for" },
8151 { "export_all", "Export unrecognized metadata entries", OFFSET(export_all),
8152 AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, .flags = FLAGS },
8153 { "export_xmp", "Export full XMP metadata", OFFSET(export_xmp),
8154 AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, .flags = FLAGS },
8155 { "activation_bytes", "Secret bytes for Audible AAX files", OFFSET(activation_bytes),
8156 AV_OPT_TYPE_BINARY, .flags = AV_OPT_FLAG_DECODING_PARAM },
8157 { "audible_fixed_key", // extracted from libAAX_SDK.so and AAXSDKWin.dll files!
8158 "Fixed key used for handling Audible AAX files", OFFSET(audible_fixed_key),
8159 AV_OPT_TYPE_BINARY, {.str="77214d4b196a87cd520045fd20a51d67"},
8160 .flags = AV_OPT_FLAG_DECODING_PARAM },
8161 { "decryption_key", "The media decryption key (hex)", OFFSET(decryption_key), AV_OPT_TYPE_BINARY, .flags = AV_OPT_FLAG_DECODING_PARAM },
8162 { "enable_drefs", "Enable external track support.", OFFSET(enable_drefs), AV_OPT_TYPE_BOOL,
8163 {.i64 = 0}, 0, 1, FLAGS },
8168 static const AVClass mov_class = {
8169 .class_name = "mov,mp4,m4a,3gp,3g2,mj2",
8170 .item_name = av_default_item_name,
8171 .option = mov_options,
8172 .version = LIBAVUTIL_VERSION_INT,
8175 AVInputFormat ff_mov_demuxer = {
8176 .name = "mov,mp4,m4a,3gp,3g2,mj2",
8177 .long_name = NULL_IF_CONFIG_SMALL("QuickTime / MOV"),
8178 .priv_class = &mov_class,
8179 .priv_data_size = sizeof(MOVContext),
8180 .extensions = "mov,mp4,m4a,3gp,3g2,mj2,psp,m4b,ism,ismv,isma,f4v",
8181 .read_probe = mov_probe,
8182 .read_header = mov_read_header,
8183 .read_packet = mov_read_packet,
8184 .read_close = mov_read_close,
8185 .read_seek = mov_read_seek,
8186 .flags = AVFMT_NO_BYTE_SEEK | AVFMT_SEEK_TO_PTS,