3 * Copyright (c) 2001 Fabrice Bellard.
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
30 * First version by Francois Revol revol@free.fr
31 * Seek function by Gael Chardon gael.dev@4now.net
33 * Features and limitations:
34 * - reads most of the QT files I have (at least the structure),
35 * the exceptions are .mov with zlib compressed headers ('cmov' section). It shouldn't be hard to implement.
36 * FIXED, Francois Revol, 07/17/2002
37 * - ffmpeg has nearly none of the usual QuickTime codecs,
38 * although I succesfully dumped raw and mp3 audio tracks off .mov files.
39 * Sample QuickTime files with mp3 audio can be found at: http://www.3ivx.com/showcase.html
40 * - .mp4 parsing is still hazardous, although the format really is QuickTime with some minor changes
41 * (to make .mov parser crash maybe ?), despite what they say in the MPEG FAQ at
42 * http://mpeg.telecomitalialab.com/faq.htm
43 * - the code is quite ugly... maybe I won't do it recursive next time :-)
44 * - seek is not supported with files that contain edit list
46 * Funny I didn't know about http://sourceforge.net/projects/qt-ffmpeg/
47 * when coding this :) (it's a writer anyway)
49 * Reference documents:
50 * http://www.geocities.com/xhelmboyx/quicktime/formats/qtm-layout.txt
52 * http://developer.apple.com/documentation/QuickTime/QTFF/
53 * http://developer.apple.com/documentation/QuickTime/QTFF/qtff.pdf
54 * QuickTime is a trademark of Apple (AFAIK :))
63 #include "qtpalette.h"
66 /* Allows seeking (MOV_SPLIT_CHUNKS should also be defined) */
69 /* allows chunk splitting - should work now... */
70 /* in case you can't read a file, try commenting */
71 #define MOV_SPLIT_CHUNKS
73 /* Special handling for movies created with Minolta Dimaxe Xi*/
74 /* this fix should not interfere with other .mov files, but just in case*/
75 #define MOV_MINOLTA_FIX
77 /* some streams in QT (and in MP4 mostly) aren't either video nor audio */
78 /* so we first list them as this, then clean up the list of streams we give back, */
79 /* getting rid of these */
80 #define CODEC_TYPE_MOV_OTHER (enum CodecType) 2
82 static const CodecTag mov_video_tags[] = {
83 /* { CODEC_ID_, MKTAG('c', 'v', 'i', 'd') }, *//* Cinepak */
84 /* { CODEC_ID_H263, MKTAG('r', 'a', 'w', ' ') }, *//* Uncompressed RGB */
85 /* { CODEC_ID_H263, MKTAG('Y', 'u', 'v', '2') }, *//* Uncompressed YUV422 */
86 /* { CODEC_ID_RAWVIDEO, MKTAG('A', 'V', 'U', 'I') }, *//* YUV with alpha-channel (AVID Uncompressed) */
91 { CODEC_ID_MJPEG, MKTAG('j', 'p', 'e', 'g') }, /* PhotoJPEG */
92 { CODEC_ID_MPEG1VIDEO, MKTAG('m', 'p', 'e', 'g') }, /* MPEG */
93 { CODEC_ID_MJPEG, MKTAG('m', 'j', 'p', 'a') }, /* Motion-JPEG (format A) */
94 { CODEC_ID_MJPEG, MKTAG('m', 'j', 'p', 'b') }, /* Motion-JPEG (format B) */
95 { CODEC_ID_MJPEG, MKTAG('A', 'V', 'D', 'J') }, /* MJPEG with alpha-channel (AVID JFIF meridien compressed) */
96 /* { CODEC_ID_MJPEG, MKTAG('A', 'V', 'R', 'n') }, *//* MJPEG with alpha-channel (AVID ABVB/Truevision NuVista) */
97 /* { CODEC_ID_GIF, MKTAG('g', 'i', 'f', ' ') }, *//* embedded gif files as frames (usually one "click to play movie" frame) */
99 { CODEC_ID_SVQ1, MKTAG('S', 'V', 'Q', '1') }, /* Sorenson Video v1 */
100 { CODEC_ID_SVQ1, MKTAG('s', 'v', 'q', '1') }, /* Sorenson Video v1 */
101 { CODEC_ID_SVQ1, MKTAG('s', 'v', 'q', 'i') }, /* Sorenson Video v1 (from QT specs)*/
102 { CODEC_ID_SVQ3, MKTAG('S', 'V', 'Q', '3') }, /* Sorenson Video v3 */
103 { CODEC_ID_MPEG4, MKTAG('m', 'p', '4', 'v') },
104 { CODEC_ID_MPEG4, MKTAG('D', 'I', 'V', 'X') }, /* OpenDiVX *//* sample files at http://heroinewarrior.com/xmovie.php3 use this tag */
105 { CODEC_ID_MPEG4, MKTAG('X', 'V', 'I', 'D') },
106 { CODEC_ID_MPEG4, MKTAG('3', 'I', 'V', '2') }, /* experimental: 3IVX files before ivx D4 4.5.1 */
107 /* { CODEC_ID_, MKTAG('I', 'V', '5', '0') }, *//* Indeo 5.0 */
108 { CODEC_ID_H263, MKTAG('h', '2', '6', '3') }, /* H263 */
109 { CODEC_ID_H263, MKTAG('s', '2', '6', '3') }, /* H263 ?? works */
110 { CODEC_ID_DVVIDEO, MKTAG('d', 'v', 'c', ' ') }, /* DV NTSC */
111 { CODEC_ID_DVVIDEO, MKTAG('d', 'v', 'c', 'p') }, /* DV PAL */
112 /* { CODEC_ID_DVVIDEO, MKTAG('A', 'V', 'd', 'v') }, *//* AVID dv */
113 { CODEC_ID_VP3, MKTAG('V', 'P', '3', '1') }, /* On2 VP3 */
114 { CODEC_ID_RPZA, MKTAG('r', 'p', 'z', 'a') }, /* Apple Video (RPZA) */
115 { CODEC_ID_CINEPAK, MKTAG('c', 'v', 'i', 'd') }, /* Cinepak */
116 { CODEC_ID_8BPS, MKTAG('8', 'B', 'P', 'S') }, /* Planar RGB (8BPS) */
117 { CODEC_ID_SMC, MKTAG('s', 'm', 'c', ' ') }, /* Apple Graphics (SMC) */
118 { CODEC_ID_QTRLE, MKTAG('r', 'l', 'e', ' ') }, /* Apple Animation (RLE) */
119 { CODEC_ID_QDRAW, MKTAG('q', 'd', 'r', 'w') }, /* QuickDraw */
120 { CODEC_ID_H264, MKTAG('a', 'v', 'c', '1') }, /* AVC-1/H.264 */
121 { CODEC_ID_MPEG2VIDEO, MKTAG('h', 'd', 'v', '2') }, /* MPEG2 produced by Sony HD camera */
122 { CODEC_ID_NONE, 0 },
125 static const CodecTag mov_audio_tags[] = {
126 /* { CODEC_ID_PCM_S16BE, MKTAG('N', 'O', 'N', 'E') }, *//* uncompressed */
127 { CODEC_ID_PCM_S16BE, MKTAG('t', 'w', 'o', 's') }, /* 16 bits */
128 /* { CODEC_ID_PCM_S8, MKTAG('t', 'w', 'o', 's') },*/ /* 8 bits */
129 { CODEC_ID_PCM_U8, MKTAG('r', 'a', 'w', ' ') }, /* 8 bits unsigned */
130 { CODEC_ID_PCM_S16LE, MKTAG('s', 'o', 'w', 't') }, /* */
131 { CODEC_ID_PCM_MULAW, MKTAG('u', 'l', 'a', 'w') }, /* */
132 { CODEC_ID_PCM_ALAW, MKTAG('a', 'l', 'a', 'w') }, /* */
133 { CODEC_ID_ADPCM_IMA_QT, MKTAG('i', 'm', 'a', '4') }, /* IMA-4 ADPCM */
134 { CODEC_ID_MACE3, MKTAG('M', 'A', 'C', '3') }, /* Macintosh Audio Compression and Expansion 3:1 */
135 { CODEC_ID_MACE6, MKTAG('M', 'A', 'C', '6') }, /* Macintosh Audio Compression and Expansion 6:1 */
137 { CODEC_ID_MP2, MKTAG('.', 'm', 'p', '3') }, /* MPEG layer 3 */ /* sample files at http://www.3ivx.com/showcase.html use this tag */
138 { CODEC_ID_MP2, 0x6D730055 }, /* MPEG layer 3 */
139 { CODEC_ID_MP2, 0x5500736D }, /* MPEG layer 3 *//* XXX: check endianness */
140 /* { CODEC_ID_OGG_VORBIS, MKTAG('O', 'g', 'g', 'S') }, *//* sample files at http://heroinewarrior.com/xmovie.php3 use this tag */
142 { CODEC_ID_AAC, MKTAG('m', 'p', '4', 'a') }, /* MPEG-4 AAC */
143 /* The standard for mpeg4 audio is still not normalised AFAIK anyway */
144 { CODEC_ID_AMR_NB, MKTAG('s', 'a', 'm', 'r') }, /* AMR-NB 3gp */
145 { CODEC_ID_AMR_WB, MKTAG('s', 'a', 'w', 'b') }, /* AMR-WB 3gp */
146 { CODEC_ID_AC3, MKTAG('m', 's', 0x20, 0x00) }, /* Dolby AC-3 */
147 { CODEC_ID_ALAC,MKTAG('a', 'l', 'a', 'c') }, /* Apple Lossless */
148 { CODEC_ID_QDM2,MKTAG('Q', 'D', 'M', '2') }, /* QDM2 */
149 { CODEC_ID_NONE, 0 },
152 /* map numeric codes from mdhd atom to ISO 639 */
153 /* cf. QTFileFormat.pdf p253, qtff.pdf p205 */
154 /* http://developer.apple.com/documentation/mac/Text/Text-368.html */
155 /* deprecated by putting the code as 3*5bit ascii */
156 static const char *mov_mdhd_language_map[] = {
158 "eng", "fra", "ger", "ita", "dut", "sve", "spa", "dan", "por", "nor",
159 "heb", "jpn", "ara", "fin", "gre", "ice", "mlt", "tur", "hr "/*scr*/, "chi"/*ace?*/,
160 "urd", "hin", "tha", "kor", "lit", "pol", "hun", "est", "lav", NULL,
161 "fo ", NULL, "rus", "chi", NULL, "iri", "alb", "ron", "ces", "slk",
162 "slv", "yid", "sr ", "mac", "bul", "ukr", "bel", "uzb", "kaz", "aze",
164 "aze", "arm", "geo", "mol", "kir", "tgk", "tuk", "mon", NULL, "pus",
165 "kur", "kas", "snd", "tib", "nep", "san", "mar", "ben", "asm", "guj",
166 "pa ", "ori", "mal", "kan", "tam", "tel", NULL, "bur", "khm", "lao",
168 "vie", "ind", "tgl", "may", "may", "amh", "tir", "orm", "som", "swa",
170 NULL, "run", NULL, "mlg", "epo", NULL, NULL, NULL, NULL, NULL,
172 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
173 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
174 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, "wel", "baq",
175 "cat", "lat", "que", "grn", "aym", "tat", "uig", "dzo", "jav"
178 /* the QuickTime file format is quite convoluted...
179 * it has lots of index tables, each indexing something in another one...
180 * Here we just use what is needed to read the chunks
183 typedef struct MOV_sample_to_chunk_tbl {
187 } MOV_sample_to_chunk_tbl;
192 int64_t size; /* total size (excluding the size and type fields) */
204 uint32_t flags; // 24bit
206 /* 0x03 ESDescrTag */
208 #define MP4ODescrTag 0x01
209 #define MP4IODescrTag 0x02
210 #define MP4ESDescrTag 0x03
211 #define MP4DecConfigDescrTag 0x04
212 #define MP4DecSpecificDescrTag 0x05
213 #define MP4SLConfigDescrTag 0x06
214 #define MP4ContentIdDescrTag 0x07
215 #define MP4SupplContentIdDescrTag 0x08
216 #define MP4IPIPtrDescrTag 0x09
217 #define MP4IPMPPtrDescrTag 0x0A
218 #define MP4IPMPDescrTag 0x0B
219 #define MP4RegistrationDescrTag 0x0D
220 #define MP4ESIDIncDescrTag 0x0E
221 #define MP4ESIDRefDescrTag 0x0F
222 #define MP4FileIODescrTag 0x10
223 #define MP4FileODescrTag 0x11
224 #define MP4ExtProfileLevelDescrTag 0x13
225 #define MP4ExtDescrTagsStart 0x80
226 #define MP4ExtDescrTagsEnd 0xFE
227 uint8_t stream_priority;
229 /* 0x04 DecConfigDescrTag */
230 uint8_t object_type_id;
232 /* XXX: really streamType is
233 * only 6bit, followed by:
237 uint32_t buffer_size_db; // 24
238 uint32_t max_bitrate;
239 uint32_t avg_bitrate;
241 /* 0x05 DecSpecificDescrTag */
242 uint8_t decoder_cfg_len;
243 uint8_t *decoder_cfg;
245 /* 0x06 SLConfigDescrTag */
246 uint8_t sl_config_len;
250 struct MOVParseTableEntry;
252 typedef struct Time2Sample{
257 typedef struct MOVStreamContext {
258 int ffindex; /* the ffmpeg stream id */
259 int is_ff_stream; /* Is this stream presented to ffmpeg ? i.e. is this an audio or video stream ? */
262 int64_t *chunk_offsets;
264 Time2Sample *stts_data;
266 Time2Sample *ctts_data;
267 int edit_count; /* number of 'edit' (elst atom) */
268 long sample_to_chunk_sz;
269 MOV_sample_to_chunk_tbl *sample_to_chunk;
270 long sample_to_chunk_index;
271 int sample_to_time_index;
272 long sample_to_time_sample;
273 uint64_t sample_to_time_time;
274 int sample_to_ctime_index;
275 int sample_to_ctime_sample;
283 long left_in_chunk; /* how many samples before next chunk */
287 typedef struct MOVContext {
288 int mp4; /* set to 1 as soon as we are sure that the file is an .mp4 file (even some header parsing depends on this) */
291 int duration; /* duration of the longest track */
292 int found_moov; /* when both 'moov' and 'mdat' sections has been found */
293 int found_mdat; /* we suppose we have enough data to read the file */
296 int ni; ///< non interleaved mode
298 /* some streams listed here aren't presented to the ffmpeg API, since they aren't either video nor audio
299 * but we need the info to be able to skip data from those streams in the 'mdat' section
301 MOVStreamContext *streams[MAX_STREAMS];
303 int64_t next_chunk_offset;
304 MOVStreamContext *partial; /* != 0 : there is still to read in the current chunk */
306 MOV_ctab_t **ctab; /* color tables */
307 const struct MOVParseTableEntry *parse_table; /* could be eventually used to change the table */
308 /* NOTE: for recursion save to/ restore from local variable! */
310 AVPaletteControl palette_control;
314 /* XXX: it's the first time I make a recursive parser I think... sorry if it's ugly :P */
316 /* those functions parse an atom */
318 1: found what I wanted, exit
319 0: continue to parse next atom
320 -1: error occured, exit
322 typedef int (*mov_parse_function)(MOVContext *ctx, ByteIOContext *pb, MOV_atom_t atom);
324 /* links atom IDs to parse functions */
325 typedef struct MOVParseTableEntry {
327 mov_parse_function func;
328 } MOVParseTableEntry;
332 * XXX: static sux, even more in a multithreaded environment...
333 * Avoid them. This is here just to help debugging.
335 static int debug_indent = 0;
336 void print_atom(const char *str, MOV_atom_t atom)
339 tag = (unsigned int) atom.type;
341 if(tag == 0) tag = MKTAG('N', 'U', 'L', 'L');
343 av_log(NULL, AV_LOG_DEBUG, "|");
344 av_log(NULL, AV_LOG_DEBUG, "parse:");
345 av_log(NULL, AV_LOG_DEBUG, " %s: tag=%c%c%c%c offset=0x%x size=0x%x\n",
350 (unsigned int)atom.offset,
351 (unsigned int)atom.size);
352 assert((unsigned int)atom.size < 0x7fffffff);// catching errors
355 #define print_atom(a,b)
358 static int ff_mov_lang_to_iso639(int code, char *to)
361 /* is it the mangled iso code? */
362 /* see http://www.geocities.com/xhelmboyx/quicktime/formats/mp4-layout.txt */
364 for (i = 2; i >= 0; i--) {
365 to[i] = 0x60 + (code & 0x1f);
370 /* old fashion apple lang code */
371 if (code >= (sizeof(mov_mdhd_language_map)/sizeof(char *)))
373 if (!mov_mdhd_language_map[code])
375 strncpy(to, mov_mdhd_language_map[code], 4);
379 extern int ff_mov_iso639_to_lang(const char *lang, int mp4); /* for movenc.c */
380 int ff_mov_iso639_to_lang(const char *lang, int mp4)
384 /* old way, only for QT? */
385 for (i = 0; !mp4 && (i < (sizeof(mov_mdhd_language_map)/sizeof(char *))); i++) {
386 if (mov_mdhd_language_map[i] && !strcmp(lang, mov_mdhd_language_map[i]))
389 /* XXX:can we do that in mov too? */
392 /* handle undefined as such */
396 for (i = 0; i < 3; i++) {
397 unsigned char c = (unsigned char)lang[i];
408 static int mov_read_leaf(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
410 print_atom("leaf", atom);
413 url_fskip(pb, atom.size);
414 /* url_seek(pb, atom_offset+atom.size, SEEK_SET); */
418 static int mov_read_default(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
420 int64_t total_size = 0;
426 print_atom("default", atom);
430 a.offset = atom.offset;
433 atom.size = 0x7fffffffffffffffLL;
434 while(((total_size + 8) < atom.size) && !url_feof(pb) && !err) {
438 a.size = get_be32(pb);
439 a.type = get_le32(pb);
443 //av_log(NULL, AV_LOG_DEBUG, "type: %08x %.4s sz: %Lx %Lx %Lx\n", type, (char*)&type, size, atom.size, total_size);
444 if (a.size == 1) { /* 64 bit extended size */
445 a.size = get_be64(pb) - 8;
450 a.size = atom.size - total_size;
454 for (i = 0; c->parse_table[i].type != 0L
455 && c->parse_table[i].type != a.type; i++)
463 // av_log(NULL, AV_LOG_DEBUG, " i=%ld\n", i);
464 if (c->parse_table[i].type == 0) { /* skip leaf atoms data */
465 // url_seek(pb, atom.offset+atom.size, SEEK_SET);
467 print_atom("unknown", a);
469 url_fskip(pb, a.size);
472 //char b[5] = { type & 0xff, (type >> 8) & 0xff, (type >> 16) & 0xff, (type >> 24) & 0xff, 0 };
473 //print_atom(b, type, offset, size);
475 err = (c->parse_table[i].func)(c, pb, a);
479 total_size += a.size;
482 if (!err && total_size < atom.size && atom.size < 0x7ffff) {
483 //av_log(NULL, AV_LOG_DEBUG, "RESET %Ld %Ld err:%d\n", atom.size, total_size, err);
484 url_fskip(pb, atom.size - total_size);
493 static int mov_read_ctab(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
496 url_fskip(pb, atom.size); // for now
498 VERY VERY BROKEN, NEVER execute this, needs rewrite
501 c->ctab = av_realloc(c->ctab, ++c->ctab_size);
502 t = c->ctab[c->ctab_size];
503 t->seed = get_be32(pb);
504 t->flags = get_be16(pb);
505 t->size = get_be16(pb) + 1;
506 len = 2 * t->size * 4;
508 t->clrs = av_malloc(len); // 16bit A R G B
510 get_buffer(pb, t->clrs, len);
517 static int mov_read_hdlr(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
519 AVStream *st = c->fc->streams[c->fc->nb_streams-1];
524 print_atom("hdlr", atom);
526 get_byte(pb); /* version */
527 get_byte(pb); get_byte(pb); get_byte(pb); /* flags */
530 ctype = get_le32(pb);
531 type = get_le32(pb); /* component subtype */
534 av_log(NULL, AV_LOG_DEBUG, "ctype= %c%c%c%c (0x%08lx)\n", *((char *)&ctype), ((char *)&ctype)[1], ((char *)&ctype)[2], ((char *)&ctype)[3], (long) ctype);
535 av_log(NULL, AV_LOG_DEBUG, "stype= %c%c%c%c\n", *((char *)&type), ((char *)&type)[1], ((char *)&type)[2], ((char *)&type)[3]);
538 /* XXX: yeah this is ugly... */
539 if(ctype == MKTAG('m', 'h', 'l', 'r')) { /* MOV */
540 if(type == MKTAG('v', 'i', 'd', 'e'))
542 else if(type == MKTAG('s', 'o', 'u', 'n'))
544 } else if(ctype == 0) { /* MP4 */
545 if(type == MKTAG('v', 'i', 'd', 'e'))
547 else if(type == MKTAG('s', 'o', 'u', 'n'))
549 else if(type == MKTAG('o', 'd', 's', 'm'))
551 else if(type == MKTAG('s', 'd', 's', 'm'))
553 } else puts("hdlr: meta");
556 if(ctype == MKTAG('m', 'h', 'l', 'r')) { /* MOV */
557 /* helps parsing the string hereafter... */
559 if(type == MKTAG('v', 'i', 'd', 'e'))
560 st->codec->codec_type = CODEC_TYPE_VIDEO;
561 else if(type == MKTAG('s', 'o', 'u', 'n'))
562 st->codec->codec_type = CODEC_TYPE_AUDIO;
563 } else if(ctype == 0) { /* MP4 */
564 /* helps parsing the string hereafter... */
566 if(type == MKTAG('v', 'i', 'd', 'e'))
567 st->codec->codec_type = CODEC_TYPE_VIDEO;
568 else if(type == MKTAG('s', 'o', 'u', 'n'))
569 st->codec->codec_type = CODEC_TYPE_AUDIO;
571 get_be32(pb); /* component manufacture */
572 get_be32(pb); /* component flags */
573 get_be32(pb); /* component flags mask */
576 return 0; /* nothing left to read */
577 /* XXX: MP4 uses a C string, not a pascal one */
582 while(get_byte(pb) && (++len < (atom.size - 24)));
584 /* .mov: PASCAL string */
590 buf = (uint8_t*) av_malloc(len+1);
592 get_buffer(pb, buf, len);
594 av_log(NULL, AV_LOG_DEBUG, "**buf='%s'\n", buf);
601 url_fskip(pb, atom.size - (url_ftell(pb) - atom.offset));
605 static int mov_mp4_read_descr_len(ByteIOContext *pb)
610 int c = get_byte(pb);
611 len = (len << 7) | (c & 0x7f);
618 static int mov_mp4_read_descr(ByteIOContext *pb, int *tag)
622 len = mov_mp4_read_descr_len(pb);
624 av_log(NULL, AV_LOG_DEBUG, "MPEG4 description: tag=0x%02x len=%d\n", *tag, len);
629 static int mov_read_esds(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
631 AVStream *st = c->fc->streams[c->fc->nb_streams-1];
632 MOVStreamContext *sc = (MOVStreamContext *)st->priv_data;
633 int64_t start_pos = url_ftell(pb);
636 print_atom("esds", atom);
638 /* Well, broken but suffisant for some MP4 streams */
639 get_be32(pb); /* version + flags */
640 len = mov_mp4_read_descr(pb, &tag);
641 if (tag == MP4ESDescrTag) {
642 get_be16(pb); /* ID */
643 get_byte(pb); /* priority */
645 get_be16(pb); /* ID */
647 len = mov_mp4_read_descr(pb, &tag);
648 if (tag == MP4DecConfigDescrTag) {
649 sc->esds.object_type_id = get_byte(pb);
650 sc->esds.stream_type = get_byte(pb);
651 sc->esds.buffer_size_db = get_be24(pb);
652 sc->esds.max_bitrate = get_be32(pb);
653 sc->esds.avg_bitrate = get_be32(pb);
655 len = mov_mp4_read_descr(pb, &tag);
656 //av_log(NULL, AV_LOG_DEBUG, "LEN %d TAG %d m:%d a:%d\n", len, tag, sc->esds.max_bitrate, sc->esds.avg_bitrate);
657 if (tag == MP4DecSpecificDescrTag) {
659 av_log(NULL, AV_LOG_DEBUG, "Specific MPEG4 header len=%d\n", len);
661 st->codec->extradata = (uint8_t*) av_mallocz(len + FF_INPUT_BUFFER_PADDING_SIZE);
662 if (st->codec->extradata) {
663 get_buffer(pb, st->codec->extradata, len);
664 st->codec->extradata_size = len;
668 /* in any case, skip garbage */
669 url_fskip(pb, atom.size - ((url_ftell(pb) - start_pos)));
673 /* this atom contains actual media data */
674 static int mov_read_mdat(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
676 print_atom("mdat", atom);
678 if(atom.size == 0) /* wrong one (MP4) */
681 c->mdat_offset = atom.offset;
682 c->mdat_size = atom.size;
684 return 1; /* found both, just go */
685 url_fskip(pb, atom.size);
686 return 0; /* now go for moov */
689 /* this atom should contain all header atoms */
690 static int mov_read_moov(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
694 print_atom("moov", atom);
696 err = mov_read_default(c, pb, atom);
697 /* we parsed the 'moov' atom, we can terminate the parsing as soon as we find the 'mdat' */
698 /* so we don't parse the whole file if over a network */
701 return 1; /* found both, just go */
702 return 0; /* now go for mdat */
706 static int mov_read_mdhd(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
710 print_atom("mdhd", atom);
712 version = get_byte(pb); /* version */
714 return 1; /* unsupported */
716 get_byte(pb); get_byte(pb);
717 get_byte(pb); /* flags */
719 (version==1)?get_be64(pb):get_be32(pb); /* creation time */
720 (version==1)?get_be64(pb):get_be32(pb); /* modification time */
722 c->streams[c->fc->nb_streams-1]->time_scale = get_be32(pb);
723 av_set_pts_info(c->fc->streams[c->fc->nb_streams-1], 64, 1, c->streams[c->fc->nb_streams-1]->time_scale);
726 av_log(NULL, AV_LOG_DEBUG, "track[%i].time_scale = %i\n", c->fc->nb_streams-1, c->streams[c->fc->nb_streams-1]->time_scale); /* time scale */
728 c->fc->streams[c->fc->nb_streams-1]->duration = (version==1)?get_be64(pb):get_be32(pb); /* duration */
730 lang = get_be16(pb); /* language */
731 ff_mov_lang_to_iso639(lang, c->fc->streams[c->fc->nb_streams-1]->language);
732 get_be16(pb); /* quality */
737 static int mov_read_mvhd(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
739 print_atom("mvhd", atom);
741 get_byte(pb); /* version */
742 get_byte(pb); get_byte(pb); get_byte(pb); /* flags */
744 get_be32(pb); /* creation time */
745 get_be32(pb); /* modification time */
746 c->time_scale = get_be32(pb); /* time scale */
748 av_log(NULL, AV_LOG_DEBUG, "time scale = %i\n", c->time_scale);
750 c->duration = get_be32(pb); /* duration */
751 get_be32(pb); /* preferred scale */
753 get_be16(pb); /* preferred volume */
755 url_fskip(pb, 10); /* reserved */
757 url_fskip(pb, 36); /* display matrix */
759 get_be32(pb); /* preview time */
760 get_be32(pb); /* preview duration */
761 get_be32(pb); /* poster time */
762 get_be32(pb); /* selection time */
763 get_be32(pb); /* selection duration */
764 get_be32(pb); /* current time */
765 get_be32(pb); /* next track ID */
770 static int mov_read_smi(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
772 AVStream *st = c->fc->streams[c->fc->nb_streams-1];
774 if((uint64_t)atom.size > (1<<30))
777 // currently SVQ3 decoder expect full STSD header - so let's fake it
778 // this should be fixed and just SMI header should be passed
779 av_free(st->codec->extradata);
780 st->codec->extradata_size = 0x5a + atom.size;
781 st->codec->extradata = (uint8_t*) av_mallocz(st->codec->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE);
783 if (st->codec->extradata) {
784 strcpy(st->codec->extradata, "SVQ3"); // fake
785 get_buffer(pb, st->codec->extradata + 0x5a, atom.size);
786 //av_log(NULL, AV_LOG_DEBUG, "Reading SMI %Ld %s\n", atom.size, (char*)st->codec->extradata + 0x5a);
788 url_fskip(pb, atom.size);
793 static int mov_read_wave(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
795 AVStream *st = c->fc->streams[c->fc->nb_streams-1];
797 if((uint64_t)atom.size > (1<<30))
800 // pass all frma atom to codec, needed at least for QDM2
801 av_free(st->codec->extradata);
802 st->codec->extradata_size = atom.size;
803 st->codec->extradata = (uint8_t*) av_mallocz(st->codec->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE);
805 if (st->codec->extradata) {
806 get_buffer(pb, st->codec->extradata, atom.size);
807 //av_log(NULL, AV_LOG_DEBUG, "Reading frma %Ld %s\n", atom.size, (char*)st->codec->extradata);
809 url_fskip(pb, atom.size);
814 static int mov_read_avcC(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
816 AVStream *st = c->fc->streams[c->fc->nb_streams-1];
818 if((uint64_t)atom.size > (1<<30))
821 av_free(st->codec->extradata);
823 st->codec->extradata_size = atom.size;
824 st->codec->extradata = (uint8_t*) av_mallocz(st->codec->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE);
826 if (st->codec->extradata) {
827 get_buffer(pb, st->codec->extradata, atom.size);
829 url_fskip(pb, atom.size);
834 static int mov_read_stco(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
836 AVStream *st = c->fc->streams[c->fc->nb_streams-1];
837 MOVStreamContext *sc = (MOVStreamContext *)st->priv_data;
838 unsigned int i, entries;
840 print_atom("stco", atom);
842 get_byte(pb); /* version */
843 get_byte(pb); get_byte(pb); get_byte(pb); /* flags */
845 entries = get_be32(pb);
847 if(entries >= UINT_MAX/sizeof(int64_t))
850 sc->chunk_count = entries;
851 sc->chunk_offsets = (int64_t*) av_malloc(entries * sizeof(int64_t));
852 if (!sc->chunk_offsets)
854 if (atom.type == MKTAG('s', 't', 'c', 'o')) {
855 for(i=0; i<entries; i++) {
856 sc->chunk_offsets[i] = get_be32(pb);
858 } else if (atom.type == MKTAG('c', 'o', '6', '4')) {
859 for(i=0; i<entries; i++) {
860 sc->chunk_offsets[i] = get_be64(pb);
865 for(i=0; i<c->fc->nb_streams; i++){
866 MOVStreamContext *sc2 = (MOVStreamContext *)c->fc->streams[i]->priv_data;
867 if(sc2 && sc2->chunk_offsets){
868 int64_t first= sc2->chunk_offsets[0];
869 int64_t last= sc2->chunk_offsets[sc2->chunk_count-1];
870 if(first >= sc->chunk_offsets[entries-1] || last <= sc->chunk_offsets[0])
876 for(i=0; i<entries; i++) {
877 av_log(NULL, AV_LOG_DEBUG, "chunk offset=0x%Lx\n", sc->chunk_offsets[i]);
884 static int mov_read_stsd(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
886 AVStream *st = c->fc->streams[c->fc->nb_streams-1];
887 MOVStreamContext *sc = (MOVStreamContext *)st->priv_data;
888 int entries, frames_per_sample;
890 uint8_t codec_name[32];
892 /* for palette traversal */
900 unsigned char *color_table;
902 unsigned char r, g, b;
904 print_atom("stsd", atom);
906 get_byte(pb); /* version */
907 get_byte(pb); get_byte(pb); get_byte(pb); /* flags */
909 entries = get_be32(pb);
911 while(entries--) { //Parsing Sample description table
913 int size = get_be32(pb); /* size */
914 format = get_le32(pb); /* data format */
916 get_be32(pb); /* reserved */
917 get_be16(pb); /* reserved */
918 get_be16(pb); /* index */
920 /* for MPEG4: set codec type by looking for it */
921 id = codec_get_id(mov_video_tags, format);
924 codec = avcodec_find_decoder(id);
926 st->codec->codec_type = codec->type;
929 av_log(NULL, AV_LOG_DEBUG, "size=%d 4CC= %c%c%c%c codec_type=%d\n",
931 (format >> 0) & 0xff,
932 (format >> 8) & 0xff,
933 (format >> 16) & 0xff,
934 (format >> 24) & 0xff,
935 st->codec->codec_type);
937 st->codec->codec_tag = format;
938 if(st->codec->codec_type==CODEC_TYPE_VIDEO) {
939 MOV_atom_t a = { 0, 0, 0 };
940 st->codec->codec_id = id;
941 get_be16(pb); /* version */
942 get_be16(pb); /* revision level */
943 get_be32(pb); /* vendor */
944 get_be32(pb); /* temporal quality */
945 get_be32(pb); /* spacial quality */
946 if(st->codec->codec_id == CODEC_ID_MPEG4){ //FIXME this is silly
950 st->codec->width = get_be16(pb); /* width */
951 st->codec->height = get_be16(pb); /* height */
953 get_be32(pb); /* horiz resolution */
954 get_be32(pb); /* vert resolution */
955 get_be32(pb); /* data size, always 0 */
956 frames_per_sample = get_be16(pb); /* frames per samples */
958 av_log(NULL, AV_LOG_DEBUG, "frames/samples = %d\n", frames_per_sample);
960 get_buffer(pb, codec_name, 32); /* codec name, pascal string (FIXME: true for mp4?) */
961 if (codec_name[0] <= 31) {
962 memcpy(st->codec->codec_name, &codec_name[1],codec_name[0]);
963 st->codec->codec_name[codec_name[0]] = 0;
966 st->codec->bits_per_sample = get_be16(pb); /* depth */
967 st->codec->color_table_id = get_be16(pb); /* colortable id */
969 /* These are set in mov_read_stts and might already be set!
970 st->codec->time_base.den = 25;
971 st->codec->time_base.num = 1;
973 size -= (16+8*4+2+32+2*2);
979 a.size = get_be32(pb);
980 a.type = get_le32(pb);
983 av_log(NULL, AV_LOG_DEBUG, "VIDEO: atom_type=%c%c%c%c atom.size=%Ld size_left=%d\n",
984 (a.type >> 0) & 0xff,
985 (a.type >> 8) & 0xff,
986 (a.type >> 16) & 0xff,
987 (a.type >> 24) & 0xff,
990 start_pos = url_ftell(pb);
993 case MKTAG('e', 's', 'd', 's'):
996 /* Well, broken but suffisant for some MP4 streams */
997 get_be32(pb); /* version + flags */
998 len = mov_mp4_read_descr(pb, &tag);
1001 get_be16(pb); /* ID */
1002 get_byte(pb); /* priority */
1003 len = mov_mp4_read_descr(pb, &tag);
1006 /* MP4DecConfigDescrTag */
1007 get_byte(pb); /* objectTypeId */
1008 get_be32(pb); /* streamType + buffer size */
1009 get_be32(pb); /* max bit rate */
1010 get_be32(pb); /* avg bit rate */
1011 len = mov_mp4_read_descr(pb, &tag);
1014 /* MP4DecSpecificDescrTag */
1016 av_log(NULL, AV_LOG_DEBUG, "Specific MPEG4 header len=%d\n", len);
1018 sc->header_data = av_mallocz(len);
1019 if (sc->header_data) {
1020 get_buffer(pb, sc->header_data, len);
1021 sc->header_len = len;
1024 /* in any case, skip garbage */
1031 av_log(NULL, AV_LOG_DEBUG, "ATOMENEWSIZE %Ld %d\n", atom.size, url_ftell(pb) - start_pos);
1032 if (atom.size > 8) {
1033 url_fskip(pb, (atom.size - 8) -
1034 ((url_ftell(pb) - start_pos)));
1035 size -= atom.size - 8;
1039 /* unknown extension */
1040 url_fskip(pb, size);
1044 /* figure out the palette situation */
1045 color_depth = st->codec->bits_per_sample & 0x1F;
1046 color_greyscale = st->codec->bits_per_sample & 0x20;
1048 /* if the depth is 2, 4, or 8 bpp, file is palettized */
1049 if ((color_depth == 2) || (color_depth == 4) ||
1050 (color_depth == 8)) {
1052 if (color_greyscale) {
1054 /* compute the greyscale palette */
1055 color_count = 1 << color_depth;
1057 color_dec = 256 / (color_count - 1);
1058 for (j = 0; j < color_count; j++) {
1059 r = g = b = color_index;
1060 c->palette_control.palette[j] =
1061 (r << 16) | (g << 8) | (b);
1062 color_index -= color_dec;
1063 if (color_index < 0)
1067 } else if (st->codec->color_table_id & 0x08) {
1069 /* if flag bit 3 is set, use the default palette */
1070 color_count = 1 << color_depth;
1071 if (color_depth == 2)
1072 color_table = ff_qt_default_palette_4;
1073 else if (color_depth == 4)
1074 color_table = ff_qt_default_palette_16;
1076 color_table = ff_qt_default_palette_256;
1078 for (j = 0; j < color_count; j++) {
1079 r = color_table[j * 4 + 0];
1080 g = color_table[j * 4 + 1];
1081 b = color_table[j * 4 + 2];
1082 c->palette_control.palette[j] =
1083 (r << 16) | (g << 8) | (b);
1088 /* load the palette from the file */
1089 color_start = get_be32(pb);
1090 color_count = get_be16(pb);
1091 color_end = get_be16(pb);
1092 for (j = color_start; j <= color_end; j++) {
1093 /* each R, G, or B component is 16 bits;
1094 * only use the top 8 bits; skip alpha bytes
1104 c->palette_control.palette[j] =
1105 (r << 16) | (g << 8) | (b);
1109 st->codec->palctrl = &c->palette_control;
1110 st->codec->palctrl->palette_changed = 1;
1112 st->codec->palctrl = NULL;
1115 mov_read_default(c, pb, a);
1118 st->codec->codec_id = codec_get_id(mov_audio_tags, format);
1119 if(st->codec->codec_id==CODEC_ID_AMR_NB || st->codec->codec_id==CODEC_ID_AMR_WB) //from TS26.244
1122 av_log(NULL, AV_LOG_DEBUG, "AMR-NB or AMR-WB audio identified!!\n");
1124 get_be32(pb);get_be32(pb); //Reserved_8
1125 get_be16(pb);//Reserved_2
1126 get_be16(pb);//Reserved_2
1127 get_be32(pb);//Reserved_4
1128 get_be16(pb);//TimeScale
1129 get_be16(pb);//Reserved_2
1131 //AMRSpecificBox.(10 bytes)
1133 get_be32(pb); //size
1134 get_be32(pb); //type=='damr'
1135 get_be32(pb); //vendor
1136 get_byte(pb); //decoder version
1137 get_be16(pb); //mode_set
1138 get_byte(pb); //mode_change_period
1139 get_byte(pb); //frames_per_sample
1141 st->duration = AV_NOPTS_VALUE;//Not possible to get from this info, must count number of AMR frames
1142 if(st->codec->codec_id==CODEC_ID_AMR_NB)
1144 st->codec->sample_rate=8000;
1145 st->codec->channels=1;
1149 st->codec->sample_rate=16000;
1150 st->codec->channels=1;
1152 st->codec->bits_per_sample=16;
1153 st->codec->bit_rate=0; /*It is not possible to tell this before we have
1154 an audio frame and even then every frame can be different*/
1156 else if( st->codec->codec_tag == MKTAG( 'm', 'p', '4', 's' ))
1158 //This is some stuff for the hint track, lets ignore it!
1159 //Do some mp4 auto detect.
1162 url_fskip(pb, size); /* The mp4s atom also contians a esds atom that we can skip*/
1164 else if( st->codec->codec_tag == MKTAG( 'm', 'p', '4', 'a' ))
1169 /* Handle mp4 audio tag */
1170 mp4_version=get_be16(pb);/*version*/
1171 get_be16(pb); /*revesion*/
1173 st->codec->channels = get_be16(pb); /* channels */
1174 st->codec->bits_per_sample = get_be16(pb); /* bits per sample */
1176 st->codec->sample_rate = get_be16(pb); /* sample rate, not always correct */
1177 if(st->codec->sample_rate == 1) //nonsese rate? -> ignore
1178 st->codec->sample_rate= 0;
1186 a.size=size-(16+20+16);
1189 a.size=size-(16+20);
1191 a.offset=url_ftell(pb);
1193 mov_read_default(c, pb, a);
1195 /* Get correct sample rate from extradata */
1196 if(st->codec->extradata_size) {
1197 const int samplerate_table[] = {
1198 96000, 88200, 64000, 48000, 44100, 32000,
1199 24000, 22050, 16000, 12000, 11025, 8000,
1202 unsigned char *px = st->codec->extradata;
1203 // 5 bits objectTypeIndex, 4 bits sampleRateIndex, 4 bits channels
1204 int samplerate_index = ((px[0] & 7) << 1) + ((px[1] >> 7) & 1);
1205 st->codec->sample_rate = samplerate_table[samplerate_index];
1206 st->codec->channels = (px[1] >> 3) & 15;
1209 else if( st->codec->codec_tag == MKTAG( 'a', 'l', 'a', 'c' ))
1211 /* Handle alac audio tag + special extradata */
1212 get_be32(pb); /* version */
1214 st->codec->channels = get_be16(pb); /* channels */
1215 st->codec->bits_per_sample = get_be16(pb); /* bits per sample */
1217 st->codec->sample_rate = get_be16(pb);
1220 /* fetch the 36-byte extradata needed for alac decoding */
1221 st->codec->extradata_size = 36;
1222 st->codec->extradata = (uint8_t*)
1223 av_mallocz(st->codec->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE);
1224 get_buffer(pb, st->codec->extradata, st->codec->extradata_size);
1226 else if(size>=(16+20))
1227 {//16 bytes read, reading atleast 20 more
1230 av_log(NULL, AV_LOG_DEBUG, "audio size=0x%X\n",size);
1232 version = get_be16(pb); /* version */
1233 get_be16(pb); /* revision level */
1234 get_be32(pb); /* vendor */
1236 st->codec->channels = get_be16(pb); /* channel count */
1237 st->codec->bits_per_sample = get_be16(pb); /* sample size */
1239 /* handle specific s8 codec */
1240 get_be16(pb); /* compression id = 0*/
1241 get_be16(pb); /* packet size = 0 */
1243 st->codec->sample_rate = ((get_be32(pb) >> 16));
1244 //av_log(NULL, AV_LOG_DEBUG, "CODECID %d %d %.4s\n", st->codec->codec_id, CODEC_ID_PCM_S16BE, (char*)&format);
1246 switch (st->codec->codec_id) {
1247 case CODEC_ID_PCM_S16BE:
1248 if (st->codec->bits_per_sample == 8)
1249 st->codec->codec_id = CODEC_ID_PCM_S8;
1251 case CODEC_ID_PCM_U8:
1252 st->codec->bit_rate = st->codec->sample_rate * 8;
1258 //Read QT version 1 fields. In version 0 theese dont exist
1260 av_log(NULL, AV_LOG_DEBUG, "version =%d mp4=%d\n",version,c->mp4);
1261 av_log(NULL, AV_LOG_DEBUG, "size-(16+20+16)=%d\n",size-(16+20+16));
1263 if((version==1) && size>=(16+20+16))
1265 get_be32(pb); /* samples per packet */
1266 get_be32(pb); /* bytes per packet */
1267 get_be32(pb); /* bytes per frame */
1268 get_be32(pb); /* bytes per sample */
1271 //Optional, additional atom-based fields
1272 MOV_atom_t a = { format, url_ftell(pb), size - (16 + 20 + 16 + 8) };
1274 av_log(NULL, AV_LOG_DEBUG, "offest=0x%X, sizeleft=%d=0x%x,format=%c%c%c%c\n",(int)url_ftell(pb),size - (16 + 20 + 16 ),size - (16 + 20 + 16 ),
1275 (format >> 0) & 0xff,
1276 (format >> 8) & 0xff,
1277 (format >> 16) & 0xff,
1278 (format >> 24) & 0xff);
1280 mov_read_default(c, pb, a);
1285 //We should be down to 0 bytes here, but lets make sure.
1289 av_log(NULL, AV_LOG_DEBUG, "skipping 0x%X bytes\n",size-(16+20));
1291 url_fskip(pb, size);
1297 //Unknown size, but lets do our best and skip the rest.
1299 av_log(NULL, AV_LOG_DEBUG, "Strange size, skipping 0x%X bytes\n",size);
1301 url_fskip(pb, size);
1306 if(st->codec->codec_type==CODEC_TYPE_AUDIO && st->codec->sample_rate==0 && sc->time_scale>1) {
1307 st->codec->sample_rate= sc->time_scale;
1313 static int mov_read_stsc(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
1315 AVStream *st = c->fc->streams[c->fc->nb_streams-1];
1316 MOVStreamContext *sc = (MOVStreamContext *)st->priv_data;
1317 unsigned int i, entries;
1319 print_atom("stsc", atom);
1321 get_byte(pb); /* version */
1322 get_byte(pb); get_byte(pb); get_byte(pb); /* flags */
1324 entries = get_be32(pb);
1326 if(entries >= UINT_MAX / sizeof(MOV_sample_to_chunk_tbl))
1330 av_log(NULL, AV_LOG_DEBUG, "track[%i].stsc.entries = %i\n", c->fc->nb_streams-1, entries);
1332 sc->sample_to_chunk_sz = entries;
1333 sc->sample_to_chunk = (MOV_sample_to_chunk_tbl*) av_malloc(entries * sizeof(MOV_sample_to_chunk_tbl));
1334 if (!sc->sample_to_chunk)
1336 for(i=0; i<entries; i++) {
1337 sc->sample_to_chunk[i].first = get_be32(pb);
1338 sc->sample_to_chunk[i].count = get_be32(pb);
1339 sc->sample_to_chunk[i].id = get_be32(pb);
1341 /* av_log(NULL, AV_LOG_DEBUG, "sample_to_chunk first=%ld count=%ld, id=%ld\n", sc->sample_to_chunk[i].first, sc->sample_to_chunk[i].count, sc->sample_to_chunk[i].id); */
1347 static int mov_read_stss(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
1349 AVStream *st = c->fc->streams[c->fc->nb_streams-1];
1350 MOVStreamContext *sc = (MOVStreamContext *)st->priv_data;
1351 unsigned int i, entries;
1353 print_atom("stss", atom);
1355 get_byte(pb); /* version */
1356 get_byte(pb); get_byte(pb); get_byte(pb); /* flags */
1358 entries = get_be32(pb);
1360 if(entries >= UINT_MAX / sizeof(long))
1363 sc->keyframe_count = entries;
1365 av_log(NULL, AV_LOG_DEBUG, "keyframe_count = %ld\n", sc->keyframe_count);
1367 sc->keyframes = (long*) av_malloc(entries * sizeof(long));
1370 for(i=0; i<entries; i++) {
1371 sc->keyframes[i] = get_be32(pb);
1373 /* av_log(NULL, AV_LOG_DEBUG, "keyframes[]=%ld\n", sc->keyframes[i]); */
1379 static int mov_read_stsz(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
1381 AVStream *st = c->fc->streams[c->fc->nb_streams-1];
1382 MOVStreamContext *sc = (MOVStreamContext *)st->priv_data;
1383 unsigned int i, entries;
1385 print_atom("stsz", atom);
1387 get_byte(pb); /* version */
1388 get_byte(pb); get_byte(pb); get_byte(pb); /* flags */
1390 sc->sample_size = get_be32(pb);
1391 entries = get_be32(pb);
1392 if(entries >= UINT_MAX / sizeof(long))
1395 sc->sample_count = entries;
1397 av_log(NULL, AV_LOG_DEBUG, "sample_size = %ld sample_count = %ld\n", sc->sample_size, sc->sample_count);
1400 return 0; /* there isn't any table following */
1401 sc->sample_sizes = (long*) av_malloc(entries * sizeof(long));
1402 if (!sc->sample_sizes)
1404 for(i=0; i<entries; i++) {
1405 sc->sample_sizes[i] = get_be32(pb);
1407 av_log(NULL, AV_LOG_DEBUG, "sample_sizes[]=%ld\n", sc->sample_sizes[i]);
1413 static int mov_read_stts(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
1415 AVStream *st = c->fc->streams[c->fc->nb_streams-1];
1416 //MOVStreamContext *sc = (MOVStreamContext *)st->priv_data;
1417 unsigned int i, entries;
1419 int64_t total_sample_count=0;
1421 print_atom("stts", atom);
1423 get_byte(pb); /* version */
1424 get_byte(pb); get_byte(pb); get_byte(pb); /* flags */
1425 entries = get_be32(pb);
1426 if(entries >= UINT_MAX / sizeof(Time2Sample))
1429 c->streams[c->fc->nb_streams-1]->stts_count = entries;
1430 c->streams[c->fc->nb_streams-1]->stts_data = av_malloc(entries * sizeof(Time2Sample));
1433 av_log(NULL, AV_LOG_DEBUG, "track[%i].stts.entries = %i\n", c->fc->nb_streams-1, entries);
1435 for(i=0; i<entries; i++) {
1436 int sample_duration;
1439 sample_count=get_be32(pb);
1440 sample_duration = get_be32(pb);
1441 c->streams[c->fc->nb_streams - 1]->stts_data[i].count= sample_count;
1442 c->streams[c->fc->nb_streams - 1]->stts_data[i].duration= sample_duration;
1445 av_log(NULL, AV_LOG_DEBUG, "sample_count=%d, sample_duration=%d\n",sample_count,sample_duration);
1447 duration+=sample_duration*sample_count;
1448 total_sample_count+=sample_count;
1451 st->nb_frames= total_sample_count;
1453 st->duration= duration;
1457 static int mov_read_ctts(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
1459 // AVStream *st = c->fc->streams[c->fc->nb_streams-1];
1460 //MOVStreamContext *sc = (MOVStreamContext *)st->priv_data;
1461 unsigned int i, entries;
1463 print_atom("ctts", atom);
1465 get_byte(pb); /* version */
1466 get_byte(pb); get_byte(pb); get_byte(pb); /* flags */
1467 entries = get_be32(pb);
1468 if(entries >= UINT_MAX / sizeof(Time2Sample))
1471 c->streams[c->fc->nb_streams-1]->ctts_count = entries;
1472 c->streams[c->fc->nb_streams-1]->ctts_data = av_malloc(entries * sizeof(Time2Sample));
1475 av_log(NULL, AV_LOG_DEBUG, "track[%i].ctts.entries = %i\n", c->fc->nb_streams-1, entries);
1477 for(i=0; i<entries; i++) {
1478 c->streams[c->fc->nb_streams - 1]->ctts_data[i].count= get_be32(pb);
1479 c->streams[c->fc->nb_streams - 1]->ctts_data[i].duration= get_be32(pb);
1484 static int mov_read_trak(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
1487 MOVStreamContext *sc;
1489 print_atom("trak", atom);
1491 st = av_new_stream(c->fc, c->fc->nb_streams);
1493 sc = (MOVStreamContext*) av_mallocz(sizeof(MOVStreamContext));
1499 sc->sample_to_chunk_index = -1;
1501 st->codec->codec_type = CODEC_TYPE_MOV_OTHER;
1502 st->start_time = 0; /* XXX: check */
1503 c->streams[c->fc->nb_streams-1] = sc;
1505 return mov_read_default(c, pb, atom);
1508 static int mov_read_tkhd(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
1512 print_atom("tkhd", atom);
1514 st = c->fc->streams[c->fc->nb_streams-1];
1516 get_byte(pb); /* version */
1518 get_byte(pb); get_byte(pb);
1519 get_byte(pb); /* flags */
1521 MOV_TRACK_ENABLED 0x0001
1522 MOV_TRACK_IN_MOVIE 0x0002
1523 MOV_TRACK_IN_PREVIEW 0x0004
1524 MOV_TRACK_IN_POSTER 0x0008
1527 get_be32(pb); /* creation time */
1528 get_be32(pb); /* modification time */
1529 st->id = (int)get_be32(pb); /* track id (NOT 0 !)*/
1530 get_be32(pb); /* reserved */
1531 st->start_time = 0; /* check */
1532 get_be32(pb); /* highlevel (considering edits) duration in movie timebase */
1533 get_be32(pb); /* reserved */
1534 get_be32(pb); /* reserved */
1536 get_be16(pb); /* layer */
1537 get_be16(pb); /* alternate group */
1538 get_be16(pb); /* volume */
1539 get_be16(pb); /* reserved */
1541 url_fskip(pb, 36); /* display matrix */
1543 /* those are fixed-point */
1544 /*st->codec->width =*/ get_be32(pb) >> 16; /* track width */
1545 /*st->codec->height =*/ get_be32(pb) >> 16; /* track height */
1550 /* this atom should be null (from specs), but some buggy files put the 'moov' atom inside it... */
1551 /* like the files created with Adobe Premiere 5.0, for samples see */
1552 /* http://graphics.tudelft.nl/~wouter/publications/soundtests/ */
1553 static int mov_read_wide(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
1558 print_atom("wide", atom);
1562 return 0; /* continue */
1563 if (get_be32(pb) != 0) { /* 0 sized mdat atom... use the 'wide' atom size */
1564 url_fskip(pb, atom.size - 4);
1567 atom.type = get_le32(pb);
1570 if (atom.type != MKTAG('m', 'd', 'a', 't')) {
1571 url_fskip(pb, atom.size);
1574 err = mov_read_mdat(c, pb, atom);
1583 static int null_read_packet(void *opaque, uint8_t *buf, int buf_size)
1588 static int mov_read_cmov(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
1592 uint8_t *moov_data; /* uncompressed data */
1593 long cmov_len, moov_len;
1596 print_atom("cmov", atom);
1598 get_be32(pb); /* dcom atom */
1599 if (get_le32(pb) != MKTAG( 'd', 'c', 'o', 'm' ))
1601 if (get_le32(pb) != MKTAG( 'z', 'l', 'i', 'b' )) {
1602 av_log(NULL, AV_LOG_DEBUG, "unknown compression for cmov atom !");
1605 get_be32(pb); /* cmvd atom */
1606 if (get_le32(pb) != MKTAG( 'c', 'm', 'v', 'd' ))
1608 moov_len = get_be32(pb); /* uncompressed size */
1609 cmov_len = atom.size - 6 * 4;
1611 cmov_data = (uint8_t *) av_malloc(cmov_len);
1614 moov_data = (uint8_t *) av_malloc(moov_len);
1619 get_buffer(pb, cmov_data, cmov_len);
1620 if(uncompress (moov_data, (uLongf *) &moov_len, (const Bytef *)cmov_data, cmov_len) != Z_OK)
1622 if(init_put_byte(&ctx, moov_data, moov_len, 0, NULL, null_read_packet, NULL, NULL) != 0)
1624 ctx.buf_end = ctx.buffer + moov_len;
1625 atom.type = MKTAG( 'm', 'o', 'o', 'v' );
1627 atom.size = moov_len;
1629 { int fd = open("/tmp/uncompheader.mov", O_WRONLY | O_CREAT); write(fd, moov_data, moov_len); close(fd); }
1631 ret = mov_read_default(c, &ctx, atom);
1639 /* edit list atom */
1640 static int mov_read_elst(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
1643 print_atom("elst", atom);
1645 get_byte(pb); /* version */
1646 get_byte(pb); get_byte(pb); get_byte(pb); /* flags */
1647 edit_count= c->streams[c->fc->nb_streams-1]->edit_count = get_be32(pb); /* entries */
1649 for(i=0; i<edit_count; i++){
1650 get_be32(pb); /* Track duration */
1651 get_be32(pb); /* Media time */
1652 get_be32(pb); /* Media rate */
1655 av_log(NULL, AV_LOG_DEBUG, "track[%i].edit_count = %i\n", c->fc->nb_streams-1, c->streams[c->fc->nb_streams-1]->edit_count);
1660 static const MOVParseTableEntry mov_default_parse_table[] = {
1662 { MKTAG( 'c', 'o', '6', '4' ), mov_read_stco },
1663 { MKTAG( 'c', 'p', 'r', 't' ), mov_read_default },
1664 { MKTAG( 'c', 'r', 'h', 'd' ), mov_read_default },
1665 { MKTAG( 'c', 't', 't', 's' ), mov_read_ctts }, /* composition time to sample */
1666 { MKTAG( 'd', 'i', 'n', 'f' ), mov_read_default }, /* data information */
1667 { MKTAG( 'd', 'p', 'n', 'd' ), mov_read_leaf },
1668 { MKTAG( 'd', 'r', 'e', 'f' ), mov_read_leaf },
1669 { MKTAG( 'e', 'd', 't', 's' ), mov_read_default },
1670 { MKTAG( 'e', 'l', 's', 't' ), mov_read_elst },
1671 { MKTAG( 'f', 'r', 'e', 'e' ), mov_read_leaf },
1672 { MKTAG( 'h', 'd', 'l', 'r' ), mov_read_hdlr },
1673 { MKTAG( 'h', 'i', 'n', 't' ), mov_read_leaf },
1674 { MKTAG( 'h', 'm', 'h', 'd' ), mov_read_leaf },
1675 { MKTAG( 'i', 'o', 'd', 's' ), mov_read_leaf },
1676 { MKTAG( 'm', 'd', 'a', 't' ), mov_read_mdat },
1677 { MKTAG( 'm', 'd', 'h', 'd' ), mov_read_mdhd },
1678 { MKTAG( 'm', 'd', 'i', 'a' ), mov_read_default },
1679 { MKTAG( 'm', 'i', 'n', 'f' ), mov_read_default },
1680 { MKTAG( 'm', 'o', 'o', 'v' ), mov_read_moov },
1681 { MKTAG( 'm', 'p', '4', 'a' ), mov_read_default },
1682 { MKTAG( 'm', 'p', '4', 's' ), mov_read_default },
1683 { MKTAG( 'm', 'p', '4', 'v' ), mov_read_default },
1684 { MKTAG( 'm', 'p', 'o', 'd' ), mov_read_leaf },
1685 { MKTAG( 'm', 'v', 'h', 'd' ), mov_read_mvhd },
1686 { MKTAG( 'n', 'm', 'h', 'd' ), mov_read_leaf },
1687 { MKTAG( 'o', 'd', 'h', 'd' ), mov_read_default },
1688 { MKTAG( 's', 'd', 'h', 'd' ), mov_read_default },
1689 { MKTAG( 's', 'k', 'i', 'p' ), mov_read_leaf },
1690 { MKTAG( 's', 'm', 'h', 'd' ), mov_read_leaf }, /* sound media info header */
1691 { MKTAG( 'S', 'M', 'I', ' ' ), mov_read_smi }, /* Sorenson extension ??? */
1692 { MKTAG( 'a', 'v', 'c', 'C' ), mov_read_avcC },
1693 { MKTAG( 's', 't', 'b', 'l' ), mov_read_default },
1694 { MKTAG( 's', 't', 'c', 'o' ), mov_read_stco },
1695 { MKTAG( 's', 't', 'd', 'p' ), mov_read_default },
1696 { MKTAG( 's', 't', 's', 'c' ), mov_read_stsc },
1697 { MKTAG( 's', 't', 's', 'd' ), mov_read_stsd }, /* sample description */
1698 { MKTAG( 's', 't', 's', 'h' ), mov_read_default },
1699 { MKTAG( 's', 't', 's', 's' ), mov_read_stss }, /* sync sample */
1700 { MKTAG( 's', 't', 's', 'z' ), mov_read_stsz }, /* sample size */
1701 { MKTAG( 's', 't', 't', 's' ), mov_read_stts },
1702 { MKTAG( 't', 'k', 'h', 'd' ), mov_read_tkhd }, /* track header */
1703 { MKTAG( 't', 'r', 'a', 'k' ), mov_read_trak },
1704 { MKTAG( 't', 'r', 'e', 'f' ), mov_read_default }, /* not really */
1705 { MKTAG( 'u', 'd', 't', 'a' ), mov_read_leaf },
1706 { MKTAG( 'u', 'r', 'l', ' ' ), mov_read_leaf },
1707 { MKTAG( 'u', 'r', 'n', ' ' ), mov_read_leaf },
1708 { MKTAG( 'u', 'u', 'i', 'd' ), mov_read_leaf },
1709 { MKTAG( 'v', 'm', 'h', 'd' ), mov_read_leaf }, /* video media info header */
1710 { MKTAG( 'w', 'a', 'v', 'e' ), mov_read_wave },
1712 { MKTAG( 'M', 'D', 'E', 'S' ), mov_read_leaf },
1714 { MKTAG( 'c', 'h', 'a', 'p' ), mov_read_leaf },
1715 { MKTAG( 'c', 'l', 'i', 'p' ), mov_read_default },
1716 { MKTAG( 'c', 'r', 'g', 'n' ), mov_read_leaf },
1717 { MKTAG( 'c', 't', 'a', 'b' ), mov_read_ctab },
1718 { MKTAG( 'e', 's', 'd', 's' ), mov_read_esds },
1719 { MKTAG( 'k', 'm', 'a', 't' ), mov_read_leaf },
1720 { MKTAG( 'm', 'a', 't', 't' ), mov_read_default },
1721 { MKTAG( 'r', 'd', 'r', 'f' ), mov_read_leaf },
1722 { MKTAG( 'r', 'm', 'd', 'a' ), mov_read_default },
1723 { MKTAG( 'r', 'm', 'd', 'r' ), mov_read_leaf },
1724 { MKTAG( 'r', 'm', 'r', 'a' ), mov_read_default },
1725 { MKTAG( 's', 'c', 'p', 't' ), mov_read_leaf },
1726 { MKTAG( 's', 's', 'r', 'c' ), mov_read_leaf },
1727 { MKTAG( 's', 'y', 'n', 'c' ), mov_read_leaf },
1728 { MKTAG( 't', 'c', 'm', 'd' ), mov_read_leaf },
1729 { MKTAG( 'w', 'i', 'd', 'e' ), mov_read_wide }, /* place holder */
1730 //{ MKTAG( 'r', 'm', 'q', 'u' ), mov_read_leaf },
1732 { MKTAG( 'c', 'm', 'o', 'v' ), mov_read_cmov },
1734 { MKTAG( 'c', 'm', 'o', 'v' ), mov_read_leaf },
1736 { 0L, mov_read_leaf }
1739 static void mov_free_stream_context(MOVStreamContext *sc)
1742 av_freep(&sc->chunk_offsets);
1743 av_freep(&sc->sample_to_chunk);
1744 av_freep(&sc->sample_sizes);
1745 av_freep(&sc->keyframes);
1746 av_freep(&sc->stts_data);
1747 av_freep(&sc->ctts_data);
1752 static inline uint32_t mov_to_tag(uint8_t *buf)
1754 return MKTAG(buf[0], buf[1], buf[2], buf[3]);
1757 static inline uint32_t to_be32(uint8_t *buf)
1759 return (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3];
1762 /* XXX: is it sufficient ? */
1763 static int mov_probe(AVProbeData *p)
1765 unsigned int offset;
1769 /* check file header */
1770 if (p->buf_size <= 12)
1774 /* ignore invalid offset */
1775 if ((offset + 8) > (unsigned int)p->buf_size)
1777 tag = mov_to_tag(p->buf + offset + 4);
1779 /* check for obvious tags */
1780 case MKTAG( 'm', 'o', 'o', 'v' ):
1781 case MKTAG( 'm', 'd', 'a', 't' ):
1782 case MKTAG( 'p', 'n', 'o', 't' ): /* detect movs with preview pics like ew.mov and april.mov */
1783 case MKTAG( 'u', 'd', 't', 'a' ): /* Packet Video PVAuthor adds this and a lot of more junk */
1784 return AVPROBE_SCORE_MAX;
1785 /* those are more common words, so rate then a bit less */
1786 case MKTAG( 'w', 'i', 'd', 'e' ):
1787 case MKTAG( 'f', 'r', 'e', 'e' ):
1788 case MKTAG( 'j', 'u', 'n', 'k' ):
1789 case MKTAG( 'p', 'i', 'c', 't' ):
1790 return AVPROBE_SCORE_MAX - 5;
1791 case MKTAG( 'f', 't', 'y', 'p' ):
1792 case MKTAG( 's', 'k', 'i', 'p' ):
1793 case MKTAG( 'u', 'u', 'i', 'd' ):
1794 offset = to_be32(p->buf+offset) + offset;
1795 /* if we only find those cause probedata is too small at least rate them */
1796 score = AVPROBE_SCORE_MAX - 50;
1799 /* unrecognized tag */
1806 static int mov_read_header(AVFormatContext *s, AVFormatParameters *ap)
1808 MOVContext *mov = (MOVContext *) s->priv_data;
1809 ByteIOContext *pb = &s->pb;
1811 MOV_atom_t atom = { 0, 0, 0 };
1814 mov->parse_table = mov_default_parse_table;
1816 /* XXX: I think we should auto detect */
1817 if(s->iformat->name[1] == 'p')
1820 if(!url_is_streamed(pb)) /* .mov and .mp4 aren't streamable anyway (only progressive download if moov is before mdat) */
1821 atom.size = url_fsize(pb);
1823 atom.size = 0x7FFFFFFFFFFFFFFFLL;
1826 av_log(NULL, AV_LOG_DEBUG, "filesz=%Ld\n", atom.size);
1829 /* check MOV header */
1830 err = mov_read_default(mov, pb, atom);
1831 if (err<0 || (!mov->found_moov && !mov->found_mdat)) {
1832 av_log(s, AV_LOG_ERROR, "mov: header not found !!! (err:%d, moov:%d, mdat:%d) pos:%"PRId64"\n",
1833 err, mov->found_moov, mov->found_mdat, url_ftell(pb));
1837 av_log(NULL, AV_LOG_DEBUG, "on_parse_exit_offset=%d\n", (int) url_ftell(pb));
1839 /* some cleanup : make sure we are on the mdat atom */
1840 if(!url_is_streamed(pb) && (url_ftell(pb) != mov->mdat_offset))
1841 url_fseek(pb, mov->mdat_offset, SEEK_SET);
1843 mov->next_chunk_offset = mov->mdat_offset; /* initialise reading */
1846 av_log(NULL, AV_LOG_DEBUG, "mdat_reset_offset=%d\n", (int) url_ftell(pb));
1850 av_log(NULL, AV_LOG_DEBUG, "streams= %d\n", s->nb_streams);
1852 mov->total_streams = nb = s->nb_streams;
1855 for(i=0; i<s->nb_streams;) {
1856 if(s->streams[i]->codec->codec_type == CODEC_TYPE_MOV_OTHER) {/* not audio, not video, delete */
1857 av_free(s->streams[i]);
1858 for(j=i+1; j<s->nb_streams; j++)
1859 s->streams[j-1] = s->streams[j];
1864 for(i=0; i<s->nb_streams;i++) {
1865 MOVStreamContext *sc;
1866 sc = (MOVStreamContext *)s->streams[i]->priv_data;
1868 sc->is_ff_stream = 1;
1872 av_log(NULL, AV_LOG_DEBUG, "real streams= %d\n", s->nb_streams);
1877 /* Yes, this is ugly... I didn't write the specs of QT :p */
1878 /* XXX:remove useless commented code sometime */
1879 static int mov_read_packet(AVFormatContext *s, AVPacket *pkt)
1881 MOVContext *mov = (MOVContext *) s->priv_data;
1882 MOVStreamContext *sc;
1883 int64_t offset = INT64_MAX;
1884 int64_t best_dts = INT64_MAX;
1890 #ifdef MOV_SPLIT_CHUNKS
1893 idx = sc->sample_to_chunk_index;
1895 if (idx < 0) return 0;
1897 fprintf(stderr, "sc[ffid %d]->sample_size = %d\n", sc->ffindex, sc->sample_size);
1899 //size = sc->sample_sizes[sc->current_sample];
1900 // that ain't working...
1901 //size = (sc->sample_size)?sc->sample_size:sc->sample_sizes[sc->current_sample];
1902 size = (sc->sample_size > 1)?sc->sample_size:sc->sample_sizes[sc->current_sample];
1904 sc->current_sample++;
1905 sc->left_in_chunk--;
1907 if (sc->left_in_chunk <= 0)
1909 offset = mov->next_chunk_offset;
1910 /* extract the sample */
1918 if(offset == INT64_MAX)
1919 best_dts= INT64_MAX;
1920 for(i=0; i<mov->total_streams; i++) {
1921 MOVStreamContext *msc = mov->streams[i];
1923 if ((msc->next_chunk < msc->chunk_count) && msc->next_chunk >= 0){
1924 if (msc->sample_to_time_index < msc->stts_count && mov->ni) {
1926 int index= msc->sample_to_time_index;
1927 int sample= msc->sample_to_time_sample;
1928 int time= msc->sample_to_time_time;
1929 int duration = msc->stts_data[index].duration;
1930 int count = msc->stts_data[index].count;
1931 if (sample + count < msc->current_sample) {
1933 time += count*duration;
1935 duration = msc->stts_data[index].duration;
1937 dts = time + (msc->current_sample-1 - sample) * (int64_t)duration;
1938 dts = av_rescale(dts, AV_TIME_BASE, msc->time_scale);
1939 // av_log(NULL, AV_LOG_DEBUG, "%d %Ld %Ld %Ld \n", i, dts, best_dts, offset);
1943 offset = msc->chunk_offsets[msc->next_chunk];
1946 //av_log(NULL, AV_LOG_DEBUG, "MOCHUNK %ld %d %p pos:%Ld\n", mov->streams[i]->next_chunk, mov->total_streams, mov->streams[i], url_ftell(&s->pb));
1947 if ((msc->chunk_offsets[msc->next_chunk] < offset)) {
1949 offset = msc->chunk_offsets[msc->next_chunk];
1950 //av_log(NULL, AV_LOG_DEBUG, "SELETED %Ld i:%d\n", offset, i);
1955 if (!sc || offset==INT64_MAX)
1960 if(mov->next_chunk_offset < offset) { /* some meta data */
1961 url_fskip(&s->pb, (offset - mov->next_chunk_offset));
1962 mov->next_chunk_offset = offset;
1965 //av_log(NULL, AV_LOG_DEBUG, "chunk: [%i] %lli -> %lli\n", st_id, mov->next_chunk_offset, offset);
1966 if(!sc->is_ff_stream || (s->streams[sc->ffindex]->discard >= AVDISCARD_ALL)) {
1967 url_fskip(&s->pb, (offset - mov->next_chunk_offset));
1968 mov->next_chunk_offset = offset;
1973 /* now get the chunk size... */
1975 for(i=0; i<mov->total_streams; i++) {
1976 MOVStreamContext *msc = mov->streams[i];
1977 if ((msc->next_chunk < msc->chunk_count)
1978 && msc->chunk_offsets[msc->next_chunk] - offset < size
1979 && msc->chunk_offsets[msc->next_chunk] > offset)
1980 size = msc->chunk_offsets[msc->next_chunk] - offset;
1983 #ifdef MOV_MINOLTA_FIX
1984 //Make sure that size is according to sample_size (Needed by .mov files
1985 //created on a Minolta Dimage Xi where audio chunks contains waste data in the end)
1986 //Maybe we should really not only check sc->sample_size, but also sc->sample_sizes
1987 //but I have no such movies
1988 if (sc->sample_size > 0) {
1990 for(i=0; i<(sc->sample_to_chunk_sz); i++) {
1991 if( (sc->sample_to_chunk[i].first)<=(sc->next_chunk) )
1993 // I can't figure out why for PCM audio sample_size is always 1
1994 // (it should actually be channels*bits_per_second/8) but it is.
1995 AVCodecContext* cod = s->streams[sc->ffindex]->codec;
1996 if (sc->sample_size == 1 && (cod->codec_id == CODEC_ID_PCM_S16BE || cod->codec_id == CODEC_ID_PCM_S16LE))
1997 foundsize=(sc->sample_to_chunk[i].count*cod->channels*cod->bits_per_sample)/8;
1999 foundsize=sc->sample_to_chunk[i].count*sc->sample_size;
2002 av_log(NULL, AV_LOG_DEBUG, "sample_to_chunk first=%ld count=%ld, id=%ld\n", sc->sample_to_chunk[i].first, sc->sample_to_chunk[i].count, sc->sample_to_chunk[i].id);
2005 if( (foundsize>0) && (foundsize<size) )
2008 /*av_log(NULL, AV_LOG_DEBUG, "this size should actually be %d\n",foundsize);*/
2013 #endif //MOV_MINOLTA_FIX
2015 idx = sc->sample_to_chunk_index;
2016 if (idx + 1 < sc->sample_to_chunk_sz && sc->next_chunk >= sc->sample_to_chunk[idx + 1].first)
2018 sc->sample_to_chunk_index = idx;
2019 #ifdef MOV_SPLIT_CHUNKS
2020 /* split chunks into samples */
2021 if (sc->sample_size == 0 || sc->sample_size > 100) {
2022 if (idx >= 0 && sc->sample_to_chunk[idx].count != 1) {
2024 /* we'll have to get those samples before next chunk */
2025 sc->left_in_chunk = sc->sample_to_chunk[idx].count - 1;
2026 size = (sc->sample_size > 1)?sc->sample_size:sc->sample_sizes[sc->current_sample];
2029 sc->current_sample++;
2030 }else if(idx + 1 < sc->sample_to_chunk_sz){
2031 sc->current_sample += sc->sample_size * sc->sample_to_chunk[idx].count;
2037 av_log(NULL, AV_LOG_DEBUG, "chunk: %lli -> %lli (%i)\n", offset, offset + size, size);
2039 if(size == 0x0FFFFFFF)
2040 size = mov->mdat_size + mov->mdat_offset - offset;
2045 url_fseek(&s->pb, offset, SEEK_SET);
2047 av_get_packet(&s->pb, pkt, size);
2048 pkt->stream_index = sc->ffindex;
2050 // If the keyframes table exists, mark any samples that are in the table as key frames.
2051 // If no table exists, treat very sample as a key frame.
2052 if (sc->keyframes) {
2054 b = sc->keyframe_count - 1;
2057 m = (a + b + 1) >> 1;
2058 if (sc->keyframes[m] > sc->current_sample) {
2065 if (sc->keyframes[a] == sc->current_sample)
2066 pkt->flags |= PKT_FLAG_KEY;
2069 pkt->flags |= PKT_FLAG_KEY;
2073 av_log(NULL, AV_LOG_DEBUG, "Packet (%d, %ld) ", pkt->stream_index, pkt->size);
2075 av_log(NULL, AV_LOG_DEBUG, "%02x ", pkt->data[i]);
2077 av_log(NULL, AV_LOG_DEBUG, "%c ", (pkt->data[i]) & 0x7F);
2078 av_log(NULL, AV_LOG_DEBUG, "\n");
2082 mov->next_chunk_offset = offset + size;
2084 /* find the corresponding dts */
2085 if (sc && sc->sample_to_time_index < sc->stts_count && pkt) {
2088 unsigned int duration = sc->stts_data[sc->sample_to_time_index].duration;
2089 count = sc->stts_data[sc->sample_to_time_index].count;
2090 if ((sc->sample_to_time_sample + count) < sc->current_sample) {
2091 sc->sample_to_time_sample += count;
2092 sc->sample_to_time_time += count*duration;
2093 sc->sample_to_time_index ++;
2094 duration = sc->stts_data[sc->sample_to_time_index].duration;
2096 dts = sc->sample_to_time_time + (sc->current_sample-1 - sc->sample_to_time_sample) * (int64_t)duration;
2097 /* find the corresponding pts */
2098 if (sc->sample_to_ctime_index < sc->ctts_count) {
2099 int duration = sc->ctts_data[sc->sample_to_ctime_index].duration;
2100 int count = sc->ctts_data[sc->sample_to_ctime_index].count;
2102 if ((sc->sample_to_ctime_sample + count) < sc->current_sample) {
2103 sc->sample_to_ctime_sample += count;
2104 sc->sample_to_ctime_index ++;
2105 duration = sc->ctts_data[sc->sample_to_ctime_index].duration;
2107 pts = dts + duration;
2113 av_log(NULL, AV_LOG_DEBUG, "stream #%d smp #%ld dts = %lld pts = %lld (smp:%ld time:%lld idx:%d ent:%d count:%d dur:%d)\n"
2114 , pkt->stream_index, sc->current_sample-1, pkt->dts, pkt->pts
2115 , sc->sample_to_time_sample
2116 , sc->sample_to_time_time
2117 , sc->sample_to_time_index
2127 #if defined(MOV_SPLIT_CHUNKS) && defined(MOV_SEEK)
2129 * Seek method based on the one described in the Appendix C of QTFileFormat.pdf
2131 static int mov_read_seek(AVFormatContext *s, int stream_index, int64_t sample_time, int flags)
2133 MOVContext* mov = (MOVContext *) s->priv_data;
2134 MOVStreamContext* sc;
2137 int32_t seek_sample, sample;
2141 int32_t left_in_chunk;
2142 int64_t chunk_file_offset;
2143 int64_t sample_file_offset;
2144 int32_t first_chunk_sample;
2145 int32_t sample_to_chunk_idx;
2146 int sample_to_time_index;
2147 long sample_to_time_sample = 0;
2148 uint64_t sample_to_time_time = 0;
2151 // Find the corresponding mov stream
2152 for (mov_idx = 0; mov_idx < mov->total_streams; mov_idx++)
2153 if (mov->streams[mov_idx]->ffindex == stream_index)
2155 if (mov_idx == mov->total_streams) {
2156 av_log(s, AV_LOG_ERROR, "mov: requested stream was not found in mov streams (idx=%i)\n", stream_index);
2159 sc = mov->streams[mov_idx];
2161 // Step 1. Find the edit that contains the requested time (elst)
2162 if (sc->edit_count) {
2163 // FIXME should handle edit list
2164 av_log(s, AV_LOG_ERROR, "mov: does not handle seeking in files that contain edit list (c:%d)\n", sc->edit_count);
2168 // Step 2. Find the corresponding sample using the Time-to-sample atom (stts) */
2170 av_log(s, AV_LOG_DEBUG, "Searching for time %li in stream #%i (time_scale=%i)\n", (long)timestamp, mov_idx, sc->time_scale);
2172 start_time = 0; // FIXME use elst atom
2173 sample = 1; // sample are 0 based in table
2175 av_log(s, AV_LOG_DEBUG, "Searching for sample_time %li \n", (long)sample_time);
2177 for (i = 0; i < sc->stts_count; i++) {
2178 count = sc->stts_data[i].count;
2179 duration = sc->stts_data[i].duration;
2180 //av_log(s, AV_LOG_DEBUG, "> sample_time %lli \n", (long)sample_time);
2181 //av_log(s, AV_LOG_DEBUG, "> count=%i duration=%i\n", count, duration);
2182 if ((start_time + count*duration) > sample_time) {
2183 sample_to_time_time = start_time;
2184 sample_to_time_index = i;
2185 sample_to_time_sample = sample;
2186 sample += (sample_time - start_time) / duration;
2190 start_time += count * duration;
2192 sample_to_time_time = start_time;
2193 sample_to_time_index = i;
2194 /* NOTE: despite what qt doc say, the dt value (Display Time in qt vocabulary) computed with the stts atom
2195 is a decoding time stamp (dts) not a presentation time stamp. And as usual dts != pts for stream with b frames */
2198 av_log(s, AV_LOG_DEBUG, "Found time %li at sample #%u\n", (long)sample_time, sample);
2200 if (sample > sc->sample_count) {
2201 av_log(s, AV_LOG_ERROR, "mov: sample pos is too high, unable to seek (req. sample=%i, sample count=%ld)\n", sample, sc->sample_count);
2205 // Step 3. Find the prior sync. sample using the Sync sample atom (stss)
2206 if (sc->keyframes) {
2208 b = sc->keyframe_count - 1;
2210 m = (a + b + 1) >> 1;
2211 if (sc->keyframes[m] > sample) {
2217 // av_log(s, AV_LOG_DEBUG, "a=%i (%i) b=%i (%i) m=%i (%i) stream #%i\n", a, sc->keyframes[a], b, sc->keyframes[b], m, sc->keyframes[m], mov_idx);
2220 // for low latency prob: always use the previous keyframe, just uncomment the next line
2222 seek_sample = sc->keyframes[a];
2225 seek_sample = sample; // else all samples are key frames
2227 av_log(s, AV_LOG_DEBUG, "Found nearest keyframe at sample #%i \n", seek_sample);
2230 // Step 4. Find the chunk of the sample using the Sample-to-chunk-atom (stsc)
2231 for (first_chunk_sample = 1, i = 0; i < (sc->sample_to_chunk_sz - 1); i++) {
2232 b = (sc->sample_to_chunk[i + 1].first - sc->sample_to_chunk[i].first) * sc->sample_to_chunk[i].count;
2233 if (seek_sample >= first_chunk_sample && seek_sample < (first_chunk_sample + b))
2235 first_chunk_sample += b;
2237 chunk = sc->sample_to_chunk[i].first + (seek_sample - first_chunk_sample) / sc->sample_to_chunk[i].count;
2238 left_in_chunk = sc->sample_to_chunk[i].count - (seek_sample - first_chunk_sample) % sc->sample_to_chunk[i].count;
2239 first_chunk_sample += ((seek_sample - first_chunk_sample) / sc->sample_to_chunk[i].count) * sc->sample_to_chunk[i].count;
2240 sample_to_chunk_idx = i;
2242 av_log(s, AV_LOG_DEBUG, "Sample was found in chunk #%i at sample offset %i (idx %i)\n", chunk, seek_sample - first_chunk_sample, sample_to_chunk_idx);
2245 // Step 5. Find the offset of the chunk using the chunk offset atom
2246 if (!sc->chunk_offsets) {
2247 av_log(s, AV_LOG_ERROR, "mov: no chunk offset atom, unable to seek\n");
2250 if (chunk > sc->chunk_count) {
2251 av_log(s, AV_LOG_ERROR, "mov: chunk offset atom too short, unable to seek (req. chunk=%i, chunk count=%li)\n", chunk, sc->chunk_count);
2254 chunk_file_offset = sc->chunk_offsets[chunk - 1];
2256 av_log(s, AV_LOG_DEBUG, "Chunk file offset is #%llu \n", chunk_file_offset);
2259 // Step 6. Find the byte offset within the chunk using the sample size atom
2260 sample_file_offset = chunk_file_offset;
2261 if (sc->sample_size)
2262 sample_file_offset += (seek_sample - first_chunk_sample) * sc->sample_size;
2264 for (i = 0; i < (seek_sample - first_chunk_sample); i++) {
2265 sample_file_offset += sc->sample_sizes[first_chunk_sample + i - 1];
2269 av_log(s, AV_LOG_DEBUG, "Sample file offset is #%llu \n", sample_file_offset);
2272 // Step 6. Update the parser
2274 mov->next_chunk_offset = sample_file_offset;
2275 // Update current stream state
2276 sc->current_sample = seek_sample - 1; // zero based
2277 sc->left_in_chunk = left_in_chunk;
2278 sc->next_chunk = chunk; // +1 -1 (zero based)
2279 sc->sample_to_chunk_index = sample_to_chunk_idx;
2281 // Update other streams
2282 for (i = 0; i<mov->total_streams; i++) {
2283 MOVStreamContext *msc;
2284 if (i == mov_idx) continue;
2285 // Find the nearest 'next' chunk
2286 msc = mov->streams[i];
2288 b = msc->chunk_count - 1;
2290 m = (a + b + 1) >> 1;
2291 if (msc->chunk_offsets[m] > chunk_file_offset) {
2297 /* av_log(s, AV_LOG_DEBUG, "a=%i (%li) b=%i (%li) m=%i (%li) stream #%i\n"
2298 , a, (long)msc->chunk_offsets[a], b, (long)msc->chunk_offsets[b], m, (long)msc->chunk_offsets[m], i); */
2301 msc->next_chunk = a;
2302 if (msc->chunk_offsets[a] < chunk_file_offset && a < (msc->chunk_count-1))
2305 av_log(s, AV_LOG_DEBUG, "Nearest next chunk for stream #%i is #%i @%lli\n", i, msc->next_chunk+1, msc->chunk_offsets[msc->next_chunk]);
2307 // Compute sample count and index in the sample_to_chunk table (what a pity)
2308 msc->sample_to_chunk_index = 0;
2309 msc->current_sample = 0;
2310 for(; msc->sample_to_chunk_index < (msc->sample_to_chunk_sz - 1)
2311 && msc->sample_to_chunk[msc->sample_to_chunk_index + 1].first <= (1 + msc->next_chunk); msc->sample_to_chunk_index++) {
2312 msc->current_sample += (msc->sample_to_chunk[msc->sample_to_chunk_index + 1].first - msc->sample_to_chunk[msc->sample_to_chunk_index].first) \
2313 * msc->sample_to_chunk[msc->sample_to_chunk_index].count;
2315 msc->current_sample += (msc->next_chunk - (msc->sample_to_chunk[msc->sample_to_chunk_index].first - 1)) * sc->sample_to_chunk[msc->sample_to_chunk_index].count;
2316 msc->left_in_chunk = msc->sample_to_chunk[msc->sample_to_chunk_index].count - 1;
2317 // Find corresponding position in stts (used later to compute dts)
2320 for (msc->sample_to_time_index = 0; msc->sample_to_time_index < msc->stts_count; msc->sample_to_time_index++) {
2321 count = msc->stts_data[msc->sample_to_time_index].count;
2322 duration = msc->stts_data[msc->sample_to_time_index].duration;
2323 if ((sample + count - 1) > msc->current_sample) {
2324 msc->sample_to_time_time = start_time;
2325 msc->sample_to_time_sample = sample;
2329 start_time += count * duration;
2332 for (msc->sample_to_ctime_index = 0; msc->sample_to_ctime_index < msc->ctts_count; msc->sample_to_ctime_index++) {
2333 count = msc->ctts_data[msc->sample_to_ctime_index].count;
2334 duration = msc->ctts_data[msc->sample_to_ctime_index].duration;
2335 if ((sample + count - 1) > msc->current_sample) {
2336 msc->sample_to_ctime_sample = sample;
2342 av_log(s, AV_LOG_DEBUG, "Next Sample for stream #%i is #%i @%i\n", i, msc->current_sample + 1, msc->sample_to_chunk_index + 1);
2349 static int mov_read_close(AVFormatContext *s)
2352 MOVContext *mov = (MOVContext *) s->priv_data;
2353 for(i=0; i<mov->total_streams; i++)
2354 mov_free_stream_context(mov->streams[i]);
2355 /* free color tabs */
2356 for(i=0; i<mov->ctab_size; i++)
2357 av_freep(&mov->ctab[i]);
2358 av_freep(&mov->ctab);
2362 static AVInputFormat mov_iformat = {
2363 "mov,mp4,m4a,3gp,3g2",
2364 "QuickTime/MPEG4 format",
2370 #if defined(MOV_SPLIT_CHUNKS) && defined(MOV_SEEK)
2377 av_register_input_format(&mov_iformat);