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
33 * First version by Francois Revol revol@free.fr
34 * Seek function by Gael Chardon gael.dev@4now.net
36 * Features and limitations:
37 * - reads most of the QT files I have (at least the structure),
38 * the exceptions are .mov with zlib compressed headers ('cmov' section). It shouldn't be hard to implement.
39 * FIXED, Francois Revol, 07/17/2002
40 * - ffmpeg has nearly none of the usual QuickTime codecs,
41 * although I succesfully dumped raw and mp3 audio tracks off .mov files.
42 * Sample QuickTime files with mp3 audio can be found at: http://www.3ivx.com/showcase.html
43 * - .mp4 parsing is still hazardous, although the format really is QuickTime with some minor changes
44 * (to make .mov parser crash maybe ?), despite what they say in the MPEG FAQ at
45 * http://mpeg.telecomitalialab.com/faq.htm
46 * - the code is quite ugly... maybe I won't do it recursive next time :-)
47 * - seek is not supported with files that contain edit list
49 * Funny I didn't know about http://sourceforge.net/projects/qt-ffmpeg/
50 * when coding this :) (it's a writer anyway)
52 * Reference documents:
53 * http://www.geocities.com/xhelmboyx/quicktime/formats/qtm-layout.txt
55 * http://developer.apple.com/documentation/QuickTime/QTFF/
56 * http://developer.apple.com/documentation/QuickTime/QTFF/qtff.pdf
57 * QuickTime is a trademark of Apple (AFAIK :))
60 #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 /* http://gpac.sourceforge.net/tutorial/mediatypes.htm */
83 const CodecTag ff_mov_obj_type[] = {
84 { CODEC_ID_MPEG4 , 32 },
85 { CODEC_ID_H264 , 33 },
86 { CODEC_ID_AAC , 64 },
87 { CODEC_ID_MPEG2VIDEO, 96 }, /* MPEG2 Simple */
88 { CODEC_ID_MPEG2VIDEO, 97 }, /* MPEG2 Main */
89 { CODEC_ID_MPEG2VIDEO, 98 }, /* MPEG2 SNR */
90 { CODEC_ID_MPEG2VIDEO, 99 }, /* MPEG2 Spatial */
91 { CODEC_ID_MPEG2VIDEO, 100 }, /* MPEG2 High */
92 { CODEC_ID_MPEG2VIDEO, 101 }, /* MPEG2 422 */
93 { CODEC_ID_AAC , 102 }, /* MPEG2 AAC Main */
94 { CODEC_ID_AAC , 103 }, /* MPEG2 AAC Low */
95 { CODEC_ID_AAC , 104 }, /* MPEG2 AAC SSR */
96 { CODEC_ID_MP3 , 105 },
97 { CODEC_ID_MPEG1VIDEO, 106 },
98 { CODEC_ID_MP2 , 107 },
99 { CODEC_ID_MJPEG , 108 },
100 { CODEC_ID_PCM_S16LE , 224 },
101 { CODEC_ID_VORBIS , 225 },
102 { CODEC_ID_AC3 , 226 },
103 { CODEC_ID_PCM_ALAW , 227 },
104 { CODEC_ID_PCM_MULAW , 228 },
105 { CODEC_ID_PCM_S16BE , 230 },
106 { CODEC_ID_H263 , 242 },
107 { CODEC_ID_H261 , 243 },
111 static const CodecTag mov_video_tags[] = {
112 /* { CODEC_ID_, MKTAG('c', 'v', 'i', 'd') }, *//* Cinepak */
113 /* { CODEC_ID_H263, MKTAG('r', 'a', 'w', ' ') }, *//* Uncompressed RGB */
114 /* { CODEC_ID_H263, MKTAG('Y', 'u', 'v', '2') }, *//* Uncompressed YUV422 */
115 /* { CODEC_ID_RAWVIDEO, MKTAG('A', 'V', 'U', 'I') }, *//* YUV with alpha-channel (AVID Uncompressed) */
120 { CODEC_ID_MJPEG, MKTAG('j', 'p', 'e', 'g') }, /* PhotoJPEG */
121 { CODEC_ID_MPEG1VIDEO, MKTAG('m', 'p', 'e', 'g') }, /* MPEG */
122 { CODEC_ID_MJPEG, MKTAG('m', 'j', 'p', 'a') }, /* Motion-JPEG (format A) */
123 { CODEC_ID_MJPEG, MKTAG('m', 'j', 'p', 'b') }, /* Motion-JPEG (format B) */
124 { CODEC_ID_MJPEG, MKTAG('A', 'V', 'D', 'J') }, /* MJPEG with alpha-channel (AVID JFIF meridien compressed) */
125 /* { CODEC_ID_MJPEG, MKTAG('A', 'V', 'R', 'n') }, *//* MJPEG with alpha-channel (AVID ABVB/Truevision NuVista) */
126 /* { CODEC_ID_GIF, MKTAG('g', 'i', 'f', ' ') }, *//* embedded gif files as frames (usually one "click to play movie" frame) */
128 { CODEC_ID_SVQ1, MKTAG('S', 'V', 'Q', '1') }, /* Sorenson Video v1 */
129 { CODEC_ID_SVQ1, MKTAG('s', 'v', 'q', '1') }, /* Sorenson Video v1 */
130 { CODEC_ID_SVQ1, MKTAG('s', 'v', 'q', 'i') }, /* Sorenson Video v1 (from QT specs)*/
131 { CODEC_ID_SVQ3, MKTAG('S', 'V', 'Q', '3') }, /* Sorenson Video v3 */
132 { CODEC_ID_MPEG4, MKTAG('m', 'p', '4', 'v') },
133 { CODEC_ID_MPEG4, MKTAG('D', 'I', 'V', 'X') }, /* OpenDiVX *//* sample files at http://heroinewarrior.com/xmovie.php3 use this tag */
134 { CODEC_ID_MPEG4, MKTAG('X', 'V', 'I', 'D') },
135 { CODEC_ID_MPEG4, MKTAG('3', 'I', 'V', '2') }, /* experimental: 3IVX files before ivx D4 4.5.1 */
136 /* { CODEC_ID_, MKTAG('I', 'V', '5', '0') }, *//* Indeo 5.0 */
137 { CODEC_ID_H263, MKTAG('h', '2', '6', '3') }, /* H263 */
138 { CODEC_ID_H263, MKTAG('s', '2', '6', '3') }, /* H263 ?? works */
139 { CODEC_ID_DVVIDEO, MKTAG('d', 'v', 'c', ' ') }, /* DV NTSC */
140 { CODEC_ID_DVVIDEO, MKTAG('d', 'v', 'c', 'p') }, /* DV PAL */
141 /* { CODEC_ID_DVVIDEO, MKTAG('A', 'V', 'd', 'v') }, *//* AVID dv */
142 { CODEC_ID_VP3, MKTAG('V', 'P', '3', '1') }, /* On2 VP3 */
143 { CODEC_ID_RPZA, MKTAG('r', 'p', 'z', 'a') }, /* Apple Video (RPZA) */
144 { CODEC_ID_CINEPAK, MKTAG('c', 'v', 'i', 'd') }, /* Cinepak */
145 { CODEC_ID_8BPS, MKTAG('8', 'B', 'P', 'S') }, /* Planar RGB (8BPS) */
146 { CODEC_ID_SMC, MKTAG('s', 'm', 'c', ' ') }, /* Apple Graphics (SMC) */
147 { CODEC_ID_QTRLE, MKTAG('r', 'l', 'e', ' ') }, /* Apple Animation (RLE) */
148 { CODEC_ID_QDRAW, MKTAG('q', 'd', 'r', 'w') }, /* QuickDraw */
149 { CODEC_ID_H264, MKTAG('a', 'v', 'c', '1') }, /* AVC-1/H.264 */
150 { CODEC_ID_MPEG2VIDEO, MKTAG('h', 'd', 'v', '2') }, /* MPEG2 produced by Sony HD camera */
151 { CODEC_ID_NONE, 0 },
154 static const CodecTag mov_audio_tags[] = {
155 /* { CODEC_ID_PCM_S16BE, MKTAG('N', 'O', 'N', 'E') }, *//* uncompressed */
156 { CODEC_ID_PCM_S16BE, MKTAG('t', 'w', 'o', 's') }, /* 16 bits */
157 /* { CODEC_ID_PCM_S8, MKTAG('t', 'w', 'o', 's') },*/ /* 8 bits */
158 { CODEC_ID_PCM_U8, MKTAG('r', 'a', 'w', ' ') }, /* 8 bits unsigned */
159 { CODEC_ID_PCM_S16LE, MKTAG('s', 'o', 'w', 't') }, /* */
160 { CODEC_ID_PCM_MULAW, MKTAG('u', 'l', 'a', 'w') }, /* */
161 { CODEC_ID_PCM_ALAW, MKTAG('a', 'l', 'a', 'w') }, /* */
162 { CODEC_ID_ADPCM_IMA_QT, MKTAG('i', 'm', 'a', '4') }, /* IMA-4 ADPCM */
163 { CODEC_ID_MACE3, MKTAG('M', 'A', 'C', '3') }, /* Macintosh Audio Compression and Expansion 3:1 */
164 { CODEC_ID_MACE6, MKTAG('M', 'A', 'C', '6') }, /* Macintosh Audio Compression and Expansion 6:1 */
166 { CODEC_ID_MP2, MKTAG('.', 'm', 'p', '3') }, /* MPEG layer 3 */ /* sample files at http://www.3ivx.com/showcase.html use this tag */
167 { CODEC_ID_MP2, 0x6D730055 }, /* MPEG layer 3 */
168 { CODEC_ID_MP2, 0x5500736D }, /* MPEG layer 3 *//* XXX: check endianness */
169 /* { CODEC_ID_OGG_VORBIS, MKTAG('O', 'g', 'g', 'S') }, *//* sample files at http://heroinewarrior.com/xmovie.php3 use this tag */
171 { CODEC_ID_AAC, MKTAG('m', 'p', '4', 'a') }, /* MPEG-4 AAC */
172 /* The standard for mpeg4 audio is still not normalised AFAIK anyway */
173 { CODEC_ID_AMR_NB, MKTAG('s', 'a', 'm', 'r') }, /* AMR-NB 3gp */
174 { CODEC_ID_AMR_WB, MKTAG('s', 'a', 'w', 'b') }, /* AMR-WB 3gp */
175 { CODEC_ID_AC3, MKTAG('m', 's', 0x20, 0x00) }, /* Dolby AC-3 */
176 { CODEC_ID_ALAC,MKTAG('a', 'l', 'a', 'c') }, /* Apple Lossless */
177 { CODEC_ID_QDM2,MKTAG('Q', 'D', 'M', '2') }, /* QDM2 */
178 { CODEC_ID_NONE, 0 },
181 /* map numeric codes from mdhd atom to ISO 639 */
182 /* cf. QTFileFormat.pdf p253, qtff.pdf p205 */
183 /* http://developer.apple.com/documentation/mac/Text/Text-368.html */
184 /* deprecated by putting the code as 3*5bit ascii */
185 static const char *mov_mdhd_language_map[] = {
187 "eng", "fra", "ger", "ita", "dut", "sve", "spa", "dan", "por", "nor",
188 "heb", "jpn", "ara", "fin", "gre", "ice", "mlt", "tur", "hr "/*scr*/, "chi"/*ace?*/,
189 "urd", "hin", "tha", "kor", "lit", "pol", "hun", "est", "lav", NULL,
190 "fo ", NULL, "rus", "chi", NULL, "iri", "alb", "ron", "ces", "slk",
191 "slv", "yid", "sr ", "mac", "bul", "ukr", "bel", "uzb", "kaz", "aze",
193 "aze", "arm", "geo", "mol", "kir", "tgk", "tuk", "mon", NULL, "pus",
194 "kur", "kas", "snd", "tib", "nep", "san", "mar", "ben", "asm", "guj",
195 "pa ", "ori", "mal", "kan", "tam", "tel", NULL, "bur", "khm", "lao",
197 "vie", "ind", "tgl", "may", "may", "amh", "tir", "orm", "som", "swa",
199 NULL, "run", NULL, "mlg", "epo", NULL, NULL, NULL, NULL, NULL,
201 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
202 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
203 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, "wel", "baq",
204 "cat", "lat", "que", "grn", "aym", "tat", "uig", "dzo", "jav"
207 /* the QuickTime file format is quite convoluted...
208 * it has lots of index tables, each indexing something in another one...
209 * Here we just use what is needed to read the chunks
212 typedef struct MOV_sample_to_chunk_tbl {
216 } MOV_sample_to_chunk_tbl;
221 int64_t size; /* total size (excluding the size and type fields) */
233 uint32_t flags; // 24bit
235 /* 0x03 ESDescrTag */
237 #define MP4ODescrTag 0x01
238 #define MP4IODescrTag 0x02
239 #define MP4ESDescrTag 0x03
240 #define MP4DecConfigDescrTag 0x04
241 #define MP4DecSpecificDescrTag 0x05
242 #define MP4SLConfigDescrTag 0x06
243 #define MP4ContentIdDescrTag 0x07
244 #define MP4SupplContentIdDescrTag 0x08
245 #define MP4IPIPtrDescrTag 0x09
246 #define MP4IPMPPtrDescrTag 0x0A
247 #define MP4IPMPDescrTag 0x0B
248 #define MP4RegistrationDescrTag 0x0D
249 #define MP4ESIDIncDescrTag 0x0E
250 #define MP4ESIDRefDescrTag 0x0F
251 #define MP4FileIODescrTag 0x10
252 #define MP4FileODescrTag 0x11
253 #define MP4ExtProfileLevelDescrTag 0x13
254 #define MP4ExtDescrTagsStart 0x80
255 #define MP4ExtDescrTagsEnd 0xFE
256 uint8_t stream_priority;
258 /* 0x04 DecConfigDescrTag */
259 uint8_t object_type_id;
261 /* XXX: really streamType is
262 * only 6bit, followed by:
266 uint32_t buffer_size_db; // 24
267 uint32_t max_bitrate;
268 uint32_t avg_bitrate;
270 /* 0x05 DecSpecificDescrTag */
271 uint8_t decoder_cfg_len;
272 uint8_t *decoder_cfg;
274 /* 0x06 SLConfigDescrTag */
275 uint8_t sl_config_len;
279 struct MOVParseTableEntry;
281 typedef struct Time2Sample{
286 typedef struct MOVStreamContext {
287 int ffindex; /* the ffmpeg stream id */
288 int is_ff_stream; /* Is this stream presented to ffmpeg ? i.e. is this an audio or video stream ? */
291 int64_t *chunk_offsets;
293 Time2Sample *stts_data;
295 Time2Sample *ctts_data;
296 int edit_count; /* number of 'edit' (elst atom) */
297 long sample_to_chunk_sz;
298 MOV_sample_to_chunk_tbl *sample_to_chunk;
299 long sample_to_chunk_index;
300 int sample_to_time_index;
301 long sample_to_time_sample;
302 uint64_t sample_to_time_time;
303 int sample_to_ctime_index;
304 int sample_to_ctime_sample;
313 long left_in_chunk; /* how many samples before next chunk */
317 typedef struct MOVContext {
318 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) */
321 int duration; /* duration of the longest track */
322 int found_moov; /* when both 'moov' and 'mdat' sections has been found */
323 int found_mdat; /* we suppose we have enough data to read the file */
326 int ni; ///< non interleaved mode
328 /* some streams listed here aren't presented to the ffmpeg API, since they aren't either video nor audio
329 * but we need the info to be able to skip data from those streams in the 'mdat' section
331 MOVStreamContext *streams[MAX_STREAMS];
333 int64_t next_chunk_offset;
334 MOVStreamContext *partial; /* != 0 : there is still to read in the current chunk */
336 MOV_ctab_t **ctab; /* color tables */
337 const struct MOVParseTableEntry *parse_table; /* could be eventually used to change the table */
338 /* NOTE: for recursion save to/ restore from local variable! */
340 AVPaletteControl palette_control;
344 /* XXX: it's the first time I make a recursive parser I think... sorry if it's ugly :P */
346 /* those functions parse an atom */
348 1: found what I wanted, exit
349 0: continue to parse next atom
350 -1: error occured, exit
352 typedef int (*mov_parse_function)(MOVContext *ctx, ByteIOContext *pb, MOV_atom_t atom);
354 /* links atom IDs to parse functions */
355 typedef struct MOVParseTableEntry {
357 mov_parse_function func;
358 } MOVParseTableEntry;
360 static int ff_mov_lang_to_iso639(int code, char *to)
363 /* is it the mangled iso code? */
364 /* see http://www.geocities.com/xhelmboyx/quicktime/formats/mp4-layout.txt */
366 for (i = 2; i >= 0; i--) {
367 to[i] = 0x60 + (code & 0x1f);
372 /* old fashion apple lang code */
373 if (code >= (sizeof(mov_mdhd_language_map)/sizeof(char *)))
375 if (!mov_mdhd_language_map[code])
377 strncpy(to, mov_mdhd_language_map[code], 4);
381 extern int ff_mov_iso639_to_lang(const char *lang, int mp4); /* for movenc.c */
382 int ff_mov_iso639_to_lang(const char *lang, int mp4)
386 /* old way, only for QT? */
387 for (i = 0; !mp4 && (i < (sizeof(mov_mdhd_language_map)/sizeof(char *))); i++) {
388 if (mov_mdhd_language_map[i] && !strcmp(lang, mov_mdhd_language_map[i]))
391 /* XXX:can we do that in mov too? */
394 /* handle undefined as such */
398 for (i = 0; i < 3; i++) {
399 unsigned char c = (unsigned char)lang[i];
410 static int mov_read_leaf(MOVContext *c, ByteIOContext *pb, MOV_atom_t 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;
425 a.offset = atom.offset;
428 atom.size = 0x7fffffffffffffffLL;
429 while(((total_size + 8) < atom.size) && !url_feof(pb) && !err) {
433 a.size = get_be32(pb);
434 a.type = get_le32(pb);
438 dprintf("type: %08x %.4s sz: %Lx %Lx %Lx\n", a.type, (char*)&a.type, a.size, atom.size, total_size);
439 if (a.size == 1) { /* 64 bit extended size */
440 a.size = get_be64(pb) - 8;
445 a.size = atom.size - total_size;
449 for (i = 0; c->parse_table[i].type != 0L
450 && c->parse_table[i].type != a.type; i++)
458 if (c->parse_table[i].type == 0) { /* skip leaf atoms data */
459 url_fskip(pb, a.size);
461 err = (c->parse_table[i].func)(c, pb, a);
465 total_size += a.size;
468 if (!err && total_size < atom.size && atom.size < 0x7ffff) {
469 url_fskip(pb, atom.size - total_size);
475 static int mov_read_ctab(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
478 url_fskip(pb, atom.size); // for now
480 VERY VERY BROKEN, NEVER execute this, needs rewrite
483 c->ctab = av_realloc(c->ctab, ++c->ctab_size);
484 t = c->ctab[c->ctab_size];
485 t->seed = get_be32(pb);
486 t->flags = get_be16(pb);
487 t->size = get_be16(pb) + 1;
488 len = 2 * t->size * 4;
490 t->clrs = av_malloc(len); // 16bit A R G B
492 get_buffer(pb, t->clrs, len);
499 static int mov_read_hdlr(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
501 AVStream *st = c->fc->streams[c->fc->nb_streams-1];
506 get_byte(pb); /* version */
507 get_byte(pb); get_byte(pb); get_byte(pb); /* flags */
510 ctype = get_le32(pb);
511 type = get_le32(pb); /* component subtype */
513 dprintf("ctype= %c%c%c%c (0x%08lx)\n", *((char *)&ctype), ((char *)&ctype)[1], ((char *)&ctype)[2], ((char *)&ctype)[3], (long) ctype);
514 dprintf("stype= %c%c%c%c\n", *((char *)&type), ((char *)&type)[1], ((char *)&type)[2], ((char *)&type)[3]);
515 if(ctype == MKTAG('m', 'h', 'l', 'r')) { /* MOV */
516 /* helps parsing the string hereafter... */
518 if(type == MKTAG('v', 'i', 'd', 'e'))
519 st->codec->codec_type = CODEC_TYPE_VIDEO;
520 else if(type == MKTAG('s', 'o', 'u', 'n'))
521 st->codec->codec_type = CODEC_TYPE_AUDIO;
522 } else if(ctype == 0) { /* MP4 */
523 /* helps parsing the string hereafter... */
525 if(type == MKTAG('v', 'i', 'd', 'e'))
526 st->codec->codec_type = CODEC_TYPE_VIDEO;
527 else if(type == MKTAG('s', 'o', 'u', 'n'))
528 st->codec->codec_type = CODEC_TYPE_AUDIO;
530 get_be32(pb); /* component manufacture */
531 get_be32(pb); /* component flags */
532 get_be32(pb); /* component flags mask */
535 return 0; /* nothing left to read */
536 /* XXX: MP4 uses a C string, not a pascal one */
541 while(get_byte(pb) && (++len < (atom.size - 24)));
543 /* .mov: PASCAL string */
548 url_fskip(pb, atom.size - (url_ftell(pb) - atom.offset));
552 static int mov_mp4_read_descr_len(ByteIOContext *pb)
557 int c = get_byte(pb);
558 len = (len << 7) | (c & 0x7f);
565 static int mov_mp4_read_descr(ByteIOContext *pb, int *tag)
569 len = mov_mp4_read_descr_len(pb);
570 dprintf("MPEG4 description: tag=0x%02x len=%d\n", *tag, len);
574 static int mov_read_esds(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
576 AVStream *st = c->fc->streams[c->fc->nb_streams-1];
577 MOVStreamContext *sc = (MOVStreamContext *)st->priv_data;
578 int64_t start_pos = url_ftell(pb);
581 /* Well, broken but suffisant for some MP4 streams */
582 get_be32(pb); /* version + flags */
583 len = mov_mp4_read_descr(pb, &tag);
584 if (tag == MP4ESDescrTag) {
585 get_be16(pb); /* ID */
586 get_byte(pb); /* priority */
588 get_be16(pb); /* ID */
590 len = mov_mp4_read_descr(pb, &tag);
591 if (tag == MP4DecConfigDescrTag) {
592 sc->esds.object_type_id = get_byte(pb);
593 sc->esds.stream_type = get_byte(pb);
594 sc->esds.buffer_size_db = get_be24(pb);
595 sc->esds.max_bitrate = get_be32(pb);
596 sc->esds.avg_bitrate = get_be32(pb);
598 st->codec->codec_id= codec_get_id(ff_mov_obj_type, sc->esds.object_type_id);
599 len = mov_mp4_read_descr(pb, &tag);
600 if (tag == MP4DecSpecificDescrTag) {
601 dprintf("Specific MPEG4 header len=%d\n", len);
602 st->codec->extradata = (uint8_t*) av_mallocz(len + FF_INPUT_BUFFER_PADDING_SIZE);
603 if (st->codec->extradata) {
604 get_buffer(pb, st->codec->extradata, len);
605 st->codec->extradata_size = len;
609 /* in any case, skip garbage */
610 url_fskip(pb, atom.size - ((url_ftell(pb) - start_pos)));
614 /* this atom contains actual media data */
615 static int mov_read_mdat(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
617 if(atom.size == 0) /* wrong one (MP4) */
620 c->mdat_offset = atom.offset;
621 c->mdat_size = atom.size;
623 return 1; /* found both, just go */
624 url_fskip(pb, atom.size);
625 return 0; /* now go for moov */
628 /* this atom should contain all header atoms */
629 static int mov_read_moov(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
633 err = mov_read_default(c, pb, atom);
634 /* we parsed the 'moov' atom, we can terminate the parsing as soon as we find the 'mdat' */
635 /* so we don't parse the whole file if over a network */
638 return 1; /* found both, just go */
639 return 0; /* now go for mdat */
643 static int mov_read_mdhd(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
648 version = get_byte(pb); /* version */
650 return 1; /* unsupported */
652 get_byte(pb); get_byte(pb);
653 get_byte(pb); /* flags */
655 (version==1)?get_be64(pb):get_be32(pb); /* creation time */
656 (version==1)?get_be64(pb):get_be32(pb); /* modification time */
658 c->streams[c->fc->nb_streams-1]->time_scale = get_be32(pb);
659 c->fc->streams[c->fc->nb_streams-1]->duration = (version==1)?get_be64(pb):get_be32(pb); /* duration */
661 lang = get_be16(pb); /* language */
662 ff_mov_lang_to_iso639(lang, c->fc->streams[c->fc->nb_streams-1]->language);
663 get_be16(pb); /* quality */
668 static int mov_read_mvhd(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
670 get_byte(pb); /* version */
671 get_byte(pb); get_byte(pb); get_byte(pb); /* flags */
673 get_be32(pb); /* creation time */
674 get_be32(pb); /* modification time */
675 c->time_scale = get_be32(pb); /* time scale */
677 av_log(NULL, AV_LOG_DEBUG, "time scale = %i\n", c->time_scale);
679 c->duration = get_be32(pb); /* duration */
680 get_be32(pb); /* preferred scale */
682 get_be16(pb); /* preferred volume */
684 url_fskip(pb, 10); /* reserved */
686 url_fskip(pb, 36); /* display matrix */
688 get_be32(pb); /* preview time */
689 get_be32(pb); /* preview duration */
690 get_be32(pb); /* poster time */
691 get_be32(pb); /* selection time */
692 get_be32(pb); /* selection duration */
693 get_be32(pb); /* current time */
694 get_be32(pb); /* next track ID */
699 static int mov_read_smi(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
701 AVStream *st = c->fc->streams[c->fc->nb_streams-1];
703 if((uint64_t)atom.size > (1<<30))
706 // currently SVQ3 decoder expect full STSD header - so let's fake it
707 // this should be fixed and just SMI header should be passed
708 av_free(st->codec->extradata);
709 st->codec->extradata_size = 0x5a + atom.size;
710 st->codec->extradata = (uint8_t*) av_mallocz(st->codec->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE);
712 if (st->codec->extradata) {
713 strcpy(st->codec->extradata, "SVQ3"); // fake
714 get_buffer(pb, st->codec->extradata + 0x5a, atom.size);
715 dprintf("Reading SMI %Ld %s\n", atom.size, (char*)st->codec->extradata + 0x5a);
717 url_fskip(pb, atom.size);
722 static int mov_read_wave(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
724 AVStream *st = c->fc->streams[c->fc->nb_streams-1];
726 if((uint64_t)atom.size > (1<<30))
729 if (st->codec->codec_id == CODEC_ID_QDM2) {
730 // pass all frma atom to codec, needed at least for QDM2
731 av_free(st->codec->extradata);
732 st->codec->extradata_size = atom.size;
733 st->codec->extradata = (uint8_t*) av_mallocz(st->codec->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE);
735 if (st->codec->extradata) {
736 get_buffer(pb, st->codec->extradata, atom.size);
738 url_fskip(pb, atom.size);
739 } else if (atom.size > 8) { /* to read frma, esds atoms */
740 mov_read_default(c, pb, atom);
741 } else if (atom.size > 0)
742 url_fskip(pb, atom.size);
746 static int mov_read_avcC(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
748 AVStream *st = c->fc->streams[c->fc->nb_streams-1];
750 if((uint64_t)atom.size > (1<<30))
753 av_free(st->codec->extradata);
755 st->codec->extradata_size = atom.size;
756 st->codec->extradata = (uint8_t*) av_mallocz(st->codec->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE);
758 if (st->codec->extradata) {
759 get_buffer(pb, st->codec->extradata, atom.size);
761 url_fskip(pb, atom.size);
766 static int mov_read_stco(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
768 AVStream *st = c->fc->streams[c->fc->nb_streams-1];
769 MOVStreamContext *sc = (MOVStreamContext *)st->priv_data;
770 unsigned int i, entries;
772 get_byte(pb); /* version */
773 get_byte(pb); get_byte(pb); get_byte(pb); /* flags */
775 entries = get_be32(pb);
777 if(entries >= UINT_MAX/sizeof(int64_t))
780 sc->chunk_count = entries;
781 sc->chunk_offsets = (int64_t*) av_malloc(entries * sizeof(int64_t));
782 if (!sc->chunk_offsets)
784 if (atom.type == MKTAG('s', 't', 'c', 'o')) {
785 for(i=0; i<entries; i++) {
786 sc->chunk_offsets[i] = get_be32(pb);
788 } else if (atom.type == MKTAG('c', 'o', '6', '4')) {
789 for(i=0; i<entries; i++) {
790 sc->chunk_offsets[i] = get_be64(pb);
795 for(i=0; i<c->fc->nb_streams; i++){
796 MOVStreamContext *sc2 = (MOVStreamContext *)c->fc->streams[i]->priv_data;
797 if(sc2 && sc2->chunk_offsets){
798 int64_t first= sc2->chunk_offsets[0];
799 int64_t last= sc2->chunk_offsets[sc2->chunk_count-1];
800 if(first >= sc->chunk_offsets[entries-1] || last <= sc->chunk_offsets[0])
807 static int mov_read_stsd(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
809 AVStream *st = c->fc->streams[c->fc->nb_streams-1];
810 MOVStreamContext *sc = (MOVStreamContext *)st->priv_data;
811 int entries, frames_per_sample;
813 uint8_t codec_name[32];
815 /* for palette traversal */
823 unsigned char *color_table;
825 unsigned char r, g, b;
827 get_byte(pb); /* version */
828 get_byte(pb); get_byte(pb); get_byte(pb); /* flags */
830 entries = get_be32(pb);
832 while(entries--) { //Parsing Sample description table
834 offset_t start_pos = url_ftell(pb);
835 int size = get_be32(pb); /* size */
836 format = get_le32(pb); /* data format */
838 get_be32(pb); /* reserved */
839 get_be16(pb); /* reserved */
840 get_be16(pb); /* index */
842 /* for MPEG4: set codec type by looking for it */
843 id = codec_get_id(mov_video_tags, format);
845 id = codec_get_id(codec_bmp_tags, format);
848 codec = avcodec_find_decoder(id);
850 st->codec->codec_type = codec->type;
852 dprintf("size=%d 4CC= %c%c%c%c codec_type=%d\n",
854 (format >> 0) & 0xff, (format >> 8) & 0xff, (format >> 16) & 0xff, (format >> 24) & 0xff,
855 st->codec->codec_type);
856 st->codec->codec_tag = format;
857 if(st->codec->codec_type==CODEC_TYPE_VIDEO) {
858 MOV_atom_t a = { 0, 0, 0 };
859 st->codec->codec_id = id;
860 get_be16(pb); /* version */
861 get_be16(pb); /* revision level */
862 get_be32(pb); /* vendor */
863 get_be32(pb); /* temporal quality */
864 get_be32(pb); /* spacial quality */
865 if(st->codec->codec_id == CODEC_ID_MPEG4){ //FIXME this is silly
869 st->codec->width = get_be16(pb); /* width */
870 st->codec->height = get_be16(pb); /* height */
872 get_be32(pb); /* horiz resolution */
873 get_be32(pb); /* vert resolution */
874 get_be32(pb); /* data size, always 0 */
875 frames_per_sample = get_be16(pb); /* frames per samples */
877 av_log(NULL, AV_LOG_DEBUG, "frames/samples = %d\n", frames_per_sample);
879 get_buffer(pb, codec_name, 32); /* codec name, pascal string (FIXME: true for mp4?) */
880 if (codec_name[0] <= 31) {
881 memcpy(st->codec->codec_name, &codec_name[1],codec_name[0]);
882 st->codec->codec_name[codec_name[0]] = 0;
885 st->codec->bits_per_sample = get_be16(pb); /* depth */
886 st->codec->color_table_id = get_be16(pb); /* colortable id */
888 /* These are set in mov_read_stts and might already be set!
889 st->codec->time_base.den = 25;
890 st->codec->time_base.num = 1;
897 a.size = get_be32(pb);
898 a.type = get_le32(pb);
901 av_log(NULL, AV_LOG_DEBUG, "VIDEO: atom_type=%c%c%c%c atom.size=%Ld size_left=%d\n",
902 (a.type >> 0) & 0xff,
903 (a.type >> 8) & 0xff,
904 (a.type >> 16) & 0xff,
905 (a.type >> 24) & 0xff,
908 start_pos = url_ftell(pb);
911 case MKTAG('e', 's', 'd', 's'):
914 /* Well, broken but suffisant for some MP4 streams */
915 get_be32(pb); /* version + flags */
916 len = mov_mp4_read_descr(pb, &tag);
919 get_be16(pb); /* ID */
920 get_byte(pb); /* priority */
921 len = mov_mp4_read_descr(pb, &tag);
924 /* MP4DecConfigDescrTag */
925 get_byte(pb); /* objectTypeId */
926 get_be32(pb); /* streamType + buffer size */
927 get_be32(pb); /* max bit rate */
928 get_be32(pb); /* avg bit rate */
929 len = mov_mp4_read_descr(pb, &tag);
932 /* MP4DecSpecificDescrTag */
933 sc->header_data = av_mallocz(len);
934 if (sc->header_data) {
935 get_buffer(pb, sc->header_data, len);
936 sc->header_len = len;
939 /* in any case, skip garbage */
946 dprintf("ATOMENEWSIZE %Ld %d\n", atom.size, url_ftell(pb) - start_pos);
948 url_fskip(pb, (atom.size - 8) -
949 ((url_ftell(pb) - start_pos)));
950 size -= atom.size - 8;
954 /* unknown extension */
959 /* figure out the palette situation */
960 color_depth = st->codec->bits_per_sample & 0x1F;
961 color_greyscale = st->codec->bits_per_sample & 0x20;
963 /* if the depth is 2, 4, or 8 bpp, file is palettized */
964 if ((color_depth == 2) || (color_depth == 4) ||
965 (color_depth == 8)) {
967 if (color_greyscale) {
969 /* compute the greyscale palette */
970 color_count = 1 << color_depth;
972 color_dec = 256 / (color_count - 1);
973 for (j = 0; j < color_count; j++) {
974 r = g = b = color_index;
975 c->palette_control.palette[j] =
976 (r << 16) | (g << 8) | (b);
977 color_index -= color_dec;
982 } else if (st->codec->color_table_id & 0x08) {
984 /* if flag bit 3 is set, use the default palette */
985 color_count = 1 << color_depth;
986 if (color_depth == 2)
987 color_table = ff_qt_default_palette_4;
988 else if (color_depth == 4)
989 color_table = ff_qt_default_palette_16;
991 color_table = ff_qt_default_palette_256;
993 for (j = 0; j < color_count; j++) {
994 r = color_table[j * 4 + 0];
995 g = color_table[j * 4 + 1];
996 b = color_table[j * 4 + 2];
997 c->palette_control.palette[j] =
998 (r << 16) | (g << 8) | (b);
1003 /* load the palette from the file */
1004 color_start = get_be32(pb);
1005 color_count = get_be16(pb);
1006 color_end = get_be16(pb);
1007 for (j = color_start; j <= color_end; j++) {
1008 /* each R, G, or B component is 16 bits;
1009 * only use the top 8 bits; skip alpha bytes
1019 c->palette_control.palette[j] =
1020 (r << 16) | (g << 8) | (b);
1024 st->codec->palctrl = &c->palette_control;
1025 st->codec->palctrl->palette_changed = 1;
1027 st->codec->palctrl = NULL;
1029 a.size = size - (url_ftell(pb) - start_pos);
1031 mov_read_default(c, pb, a);
1032 else if (a.size > 0)
1033 url_fskip(pb, a.size);
1036 st->codec->codec_id = codec_get_id(mov_audio_tags, format);
1037 if(st->codec->codec_id==CODEC_ID_AMR_NB || st->codec->codec_id==CODEC_ID_AMR_WB) //from TS26.244
1039 dprintf("AMR audio identified %d!!\n", st->codec->codec_id);
1040 get_be32(pb);get_be32(pb); //Reserved_8
1041 get_be16(pb);//Reserved_2
1042 get_be16(pb);//Reserved_2
1043 get_be32(pb);//Reserved_4
1044 get_be16(pb);//TimeScale
1045 get_be16(pb);//Reserved_2
1047 //AMRSpecificBox.(10 bytes)
1049 get_be32(pb); //size
1050 get_be32(pb); //type=='damr'
1051 get_be32(pb); //vendor
1052 get_byte(pb); //decoder version
1053 get_be16(pb); //mode_set
1054 get_byte(pb); //mode_change_period
1055 get_byte(pb); //frames_per_sample
1057 st->duration = AV_NOPTS_VALUE;//Not possible to get from this info, must count number of AMR frames
1058 if(st->codec->codec_id==CODEC_ID_AMR_NB)
1060 st->codec->sample_rate=8000;
1061 st->codec->channels=1;
1065 st->codec->sample_rate=16000;
1066 st->codec->channels=1;
1068 st->codec->bits_per_sample=16;
1069 st->codec->bit_rate=0; /*It is not possible to tell this before we have
1070 an audio frame and even then every frame can be different*/
1072 else if( st->codec->codec_tag == MKTAG( 'm', 'p', '4', 's' ))
1074 //This is some stuff for the hint track, lets ignore it!
1075 //Do some mp4 auto detect.
1078 url_fskip(pb, size); /* The mp4s atom also contians a esds atom that we can skip*/
1080 else if( st->codec->codec_tag == MKTAG( 'm', 'p', '4', 'a' ))
1085 /* Handle mp4 audio tag */
1086 mp4_version=get_be16(pb);/*version*/
1087 get_be16(pb); /*revesion*/
1089 st->codec->channels = get_be16(pb); /* channels */
1090 st->codec->bits_per_sample = get_be16(pb); /* bits per sample */
1092 st->codec->sample_rate = get_be16(pb); /* sample rate, not always correct */
1093 if(st->codec->sample_rate == 1) //nonsese rate? -> ignore
1094 st->codec->sample_rate= 0;
1102 a.size=size-(16+20+16);
1105 a.size=size-(16+20);
1107 a.offset=url_ftell(pb);
1109 mov_read_default(c, pb, a);
1111 /* Get correct sample rate from extradata */
1112 if(st->codec->extradata_size) {
1113 const int samplerate_table[] = {
1114 96000, 88200, 64000, 48000, 44100, 32000,
1115 24000, 22050, 16000, 12000, 11025, 8000,
1118 unsigned char *px = st->codec->extradata;
1119 // 5 bits objectTypeIndex, 4 bits sampleRateIndex, 4 bits channels
1120 int samplerate_index = ((px[0] & 7) << 1) + ((px[1] >> 7) & 1);
1121 st->codec->sample_rate = samplerate_table[samplerate_index];
1122 st->codec->channels = (px[1] >> 3) & 15;
1125 else if( st->codec->codec_tag == MKTAG( 'a', 'l', 'a', 'c' ))
1127 /* Handle alac audio tag + special extradata */
1128 get_be32(pb); /* version */
1130 st->codec->channels = get_be16(pb); /* channels */
1131 st->codec->bits_per_sample = get_be16(pb); /* bits per sample */
1133 st->codec->sample_rate = get_be16(pb);
1136 /* fetch the 36-byte extradata needed for alac decoding */
1137 st->codec->extradata_size = 36;
1138 st->codec->extradata = (uint8_t*)
1139 av_mallocz(st->codec->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE);
1140 get_buffer(pb, st->codec->extradata, st->codec->extradata_size);
1142 else if(size>=(16+20))
1143 {//16 bytes read, reading atleast 20 more
1145 version = get_be16(pb); /* version */
1146 get_be16(pb); /* revision level */
1147 get_be32(pb); /* vendor */
1149 st->codec->channels = get_be16(pb); /* channel count */
1150 st->codec->bits_per_sample = get_be16(pb); /* sample size */
1152 /* handle specific s8 codec */
1153 get_be16(pb); /* compression id = 0*/
1154 get_be16(pb); /* packet size = 0 */
1156 st->codec->sample_rate = ((get_be32(pb) >> 16));
1158 switch (st->codec->codec_id) {
1159 case CODEC_ID_PCM_S16BE:
1160 if (st->codec->bits_per_sample == 8)
1161 st->codec->codec_id = CODEC_ID_PCM_S8;
1163 case CODEC_ID_PCM_U8:
1164 st->codec->bit_rate = st->codec->sample_rate * 8;
1170 //Read QT version 1 fields. In version 0 theese dont exist
1171 dprintf("version =%d mp4=%d\n",version,c->mp4);
1172 if((version==1) && size>=(16+20+16))
1174 get_be32(pb); /* samples per packet */
1175 get_be32(pb); /* bytes per packet */
1176 get_be32(pb); /* bytes per frame */
1177 get_be32(pb); /* bytes per sample */
1180 //Optional, additional atom-based fields
1181 MOV_atom_t a = { format, url_ftell(pb), size - (16 + 20 + 16 + 8) };
1182 mov_read_default(c, pb, a);
1187 //We should be down to 0 bytes here, but lets make sure.
1190 dprintf("skipping 0x%X bytes\n",size-(16+20));
1191 url_fskip(pb, size);
1198 //Unknown size, but lets do our best and skip the rest.
1199 dprintf("Strange size, skipping 0x%X bytes\n",size);
1200 url_fskip(pb, size);
1205 if(st->codec->codec_type==CODEC_TYPE_AUDIO && st->codec->sample_rate==0 && sc->time_scale>1) {
1206 st->codec->sample_rate= sc->time_scale;
1212 static int mov_read_stsc(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
1214 AVStream *st = c->fc->streams[c->fc->nb_streams-1];
1215 MOVStreamContext *sc = (MOVStreamContext *)st->priv_data;
1216 unsigned int i, entries;
1218 get_byte(pb); /* version */
1219 get_byte(pb); get_byte(pb); get_byte(pb); /* flags */
1221 entries = get_be32(pb);
1223 if(entries >= UINT_MAX / sizeof(MOV_sample_to_chunk_tbl))
1227 av_log(NULL, AV_LOG_DEBUG, "track[%i].stsc.entries = %i\n", c->fc->nb_streams-1, entries);
1229 sc->sample_to_chunk_sz = entries;
1230 sc->sample_to_chunk = (MOV_sample_to_chunk_tbl*) av_malloc(entries * sizeof(MOV_sample_to_chunk_tbl));
1231 if (!sc->sample_to_chunk)
1233 for(i=0; i<entries; i++) {
1234 sc->sample_to_chunk[i].first = get_be32(pb);
1235 sc->sample_to_chunk[i].count = get_be32(pb);
1236 sc->sample_to_chunk[i].id = get_be32(pb);
1241 static int mov_read_stss(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
1243 AVStream *st = c->fc->streams[c->fc->nb_streams-1];
1244 MOVStreamContext *sc = (MOVStreamContext *)st->priv_data;
1245 unsigned int i, entries;
1247 get_byte(pb); /* version */
1248 get_byte(pb); get_byte(pb); get_byte(pb); /* flags */
1250 entries = get_be32(pb);
1252 if(entries >= UINT_MAX / sizeof(long))
1255 sc->keyframe_count = entries;
1257 av_log(NULL, AV_LOG_DEBUG, "keyframe_count = %ld\n", sc->keyframe_count);
1259 sc->keyframes = (long*) av_malloc(entries * sizeof(long));
1262 for(i=0; i<entries; i++) {
1263 sc->keyframes[i] = get_be32(pb);
1265 /* av_log(NULL, AV_LOG_DEBUG, "keyframes[]=%ld\n", sc->keyframes[i]); */
1271 static int mov_read_stsz(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
1273 AVStream *st = c->fc->streams[c->fc->nb_streams-1];
1274 MOVStreamContext *sc = (MOVStreamContext *)st->priv_data;
1275 unsigned int i, entries;
1277 get_byte(pb); /* version */
1278 get_byte(pb); get_byte(pb); get_byte(pb); /* flags */
1280 sc->sample_size = get_be32(pb);
1281 entries = get_be32(pb);
1282 if(entries >= UINT_MAX / sizeof(long))
1285 sc->sample_count = entries;
1287 av_log(NULL, AV_LOG_DEBUG, "sample_size = %ld sample_count = %ld\n", sc->sample_size, sc->sample_count);
1290 return 0; /* there isn't any table following */
1291 sc->sample_sizes = (long*) av_malloc(entries * sizeof(long));
1292 if (!sc->sample_sizes)
1294 for(i=0; i<entries; i++) {
1295 sc->sample_sizes[i] = get_be32(pb);
1297 av_log(NULL, AV_LOG_DEBUG, "sample_sizes[]=%ld\n", sc->sample_sizes[i]);
1303 static int mov_read_stts(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
1305 AVStream *st = c->fc->streams[c->fc->nb_streams-1];
1306 MOVStreamContext *sc = (MOVStreamContext *)st->priv_data;
1307 unsigned int i, entries;
1309 int64_t total_sample_count=0;
1311 get_byte(pb); /* version */
1312 get_byte(pb); get_byte(pb); get_byte(pb); /* flags */
1313 entries = get_be32(pb);
1314 if(entries >= UINT_MAX / sizeof(Time2Sample))
1317 sc->stts_count = entries;
1318 sc->stts_data = av_malloc(entries * sizeof(Time2Sample));
1321 av_log(NULL, AV_LOG_DEBUG, "track[%i].stts.entries = %i\n", c->fc->nb_streams-1, entries);
1326 for(i=0; i<entries; i++) {
1327 int sample_duration;
1330 sample_count=get_be32(pb);
1331 sample_duration = get_be32(pb);
1332 sc->stts_data[i].count= sample_count;
1333 sc->stts_data[i].duration= sample_duration;
1335 sc->time_rate= ff_gcd(sc->time_rate, sample_duration);
1337 dprintf("sample_count=%d, sample_duration=%d\n",sample_count,sample_duration);
1339 duration+=sample_duration*sample_count;
1340 total_sample_count+=sample_count;
1343 st->nb_frames= total_sample_count;
1345 st->duration= duration;
1349 static int mov_read_ctts(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
1351 unsigned int i, entries;
1353 get_byte(pb); /* version */
1354 get_byte(pb); get_byte(pb); get_byte(pb); /* flags */
1355 entries = get_be32(pb);
1356 if(entries >= UINT_MAX / sizeof(Time2Sample))
1359 c->streams[c->fc->nb_streams-1]->ctts_count = entries;
1360 c->streams[c->fc->nb_streams-1]->ctts_data = av_malloc(entries * sizeof(Time2Sample));
1362 dprintf("track[%i].ctts.entries = %i\n", c->fc->nb_streams-1, entries);
1364 for(i=0; i<entries; i++) {
1365 c->streams[c->fc->nb_streams - 1]->ctts_data[i].count= get_be32(pb);
1366 c->streams[c->fc->nb_streams - 1]->ctts_data[i].duration= get_be32(pb);
1371 static int mov_read_trak(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
1374 MOVStreamContext *sc;
1376 st = av_new_stream(c->fc, c->fc->nb_streams);
1378 sc = (MOVStreamContext*) av_mallocz(sizeof(MOVStreamContext));
1384 sc->sample_to_chunk_index = -1;
1386 st->codec->codec_type = CODEC_TYPE_MOV_OTHER;
1387 st->start_time = 0; /* XXX: check */
1388 c->streams[c->fc->nb_streams-1] = sc;
1390 return mov_read_default(c, pb, atom);
1393 static int mov_read_tkhd(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
1397 st = c->fc->streams[c->fc->nb_streams-1];
1399 get_byte(pb); /* version */
1401 get_byte(pb); get_byte(pb);
1402 get_byte(pb); /* flags */
1404 MOV_TRACK_ENABLED 0x0001
1405 MOV_TRACK_IN_MOVIE 0x0002
1406 MOV_TRACK_IN_PREVIEW 0x0004
1407 MOV_TRACK_IN_POSTER 0x0008
1410 get_be32(pb); /* creation time */
1411 get_be32(pb); /* modification time */
1412 st->id = (int)get_be32(pb); /* track id (NOT 0 !)*/
1413 get_be32(pb); /* reserved */
1414 st->start_time = 0; /* check */
1415 get_be32(pb); /* highlevel (considering edits) duration in movie timebase */
1416 get_be32(pb); /* reserved */
1417 get_be32(pb); /* reserved */
1419 get_be16(pb); /* layer */
1420 get_be16(pb); /* alternate group */
1421 get_be16(pb); /* volume */
1422 get_be16(pb); /* reserved */
1424 url_fskip(pb, 36); /* display matrix */
1426 /* those are fixed-point */
1427 /*st->codec->width =*/ get_be32(pb) >> 16; /* track width */
1428 /*st->codec->height =*/ get_be32(pb) >> 16; /* track height */
1433 /* this atom should be null (from specs), but some buggy files put the 'moov' atom inside it... */
1434 /* like the files created with Adobe Premiere 5.0, for samples see */
1435 /* http://graphics.tudelft.nl/~wouter/publications/soundtests/ */
1436 static int mov_read_wide(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
1441 return 0; /* continue */
1442 if (get_be32(pb) != 0) { /* 0 sized mdat atom... use the 'wide' atom size */
1443 url_fskip(pb, atom.size - 4);
1446 atom.type = get_le32(pb);
1449 if (atom.type != MKTAG('m', 'd', 'a', 't')) {
1450 url_fskip(pb, atom.size);
1453 err = mov_read_mdat(c, pb, atom);
1459 static int null_read_packet(void *opaque, uint8_t *buf, int buf_size)
1464 static int mov_read_cmov(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
1468 uint8_t *moov_data; /* uncompressed data */
1469 long cmov_len, moov_len;
1472 get_be32(pb); /* dcom atom */
1473 if (get_le32(pb) != MKTAG( 'd', 'c', 'o', 'm' ))
1475 if (get_le32(pb) != MKTAG( 'z', 'l', 'i', 'b' )) {
1476 av_log(NULL, AV_LOG_ERROR, "unknown compression for cmov atom !");
1479 get_be32(pb); /* cmvd atom */
1480 if (get_le32(pb) != MKTAG( 'c', 'm', 'v', 'd' ))
1482 moov_len = get_be32(pb); /* uncompressed size */
1483 cmov_len = atom.size - 6 * 4;
1485 cmov_data = (uint8_t *) av_malloc(cmov_len);
1488 moov_data = (uint8_t *) av_malloc(moov_len);
1493 get_buffer(pb, cmov_data, cmov_len);
1494 if(uncompress (moov_data, (uLongf *) &moov_len, (const Bytef *)cmov_data, cmov_len) != Z_OK)
1496 if(init_put_byte(&ctx, moov_data, moov_len, 0, NULL, null_read_packet, NULL, NULL) != 0)
1498 ctx.buf_end = ctx.buffer + moov_len;
1499 atom.type = MKTAG( 'm', 'o', 'o', 'v' );
1501 atom.size = moov_len;
1503 // { int fd = open("/tmp/uncompheader.mov", O_WRONLY | O_CREAT); write(fd, moov_data, moov_len); close(fd); }
1505 ret = mov_read_default(c, &ctx, atom);
1513 /* edit list atom */
1514 static int mov_read_elst(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
1518 get_byte(pb); /* version */
1519 get_byte(pb); get_byte(pb); get_byte(pb); /* flags */
1520 edit_count= c->streams[c->fc->nb_streams-1]->edit_count = get_be32(pb); /* entries */
1522 for(i=0; i<edit_count; i++){
1523 get_be32(pb); /* Track duration */
1524 get_be32(pb); /* Media time */
1525 get_be32(pb); /* Media rate */
1527 dprintf("track[%i].edit_count = %i\n", c->fc->nb_streams-1, c->streams[c->fc->nb_streams-1]->edit_count);
1531 static const MOVParseTableEntry mov_default_parse_table[] = {
1533 { MKTAG( 'c', 'o', '6', '4' ), mov_read_stco },
1534 { MKTAG( 'c', 'p', 'r', 't' ), mov_read_default },
1535 { MKTAG( 'c', 'r', 'h', 'd' ), mov_read_default },
1536 { MKTAG( 'c', 't', 't', 's' ), mov_read_ctts }, /* composition time to sample */
1537 { MKTAG( 'd', 'i', 'n', 'f' ), mov_read_default }, /* data information */
1538 { MKTAG( 'd', 'p', 'n', 'd' ), mov_read_leaf },
1539 { MKTAG( 'd', 'r', 'e', 'f' ), mov_read_leaf },
1540 { MKTAG( 'e', 'd', 't', 's' ), mov_read_default },
1541 { MKTAG( 'e', 'l', 's', 't' ), mov_read_elst },
1542 { MKTAG( 'f', 'r', 'e', 'e' ), mov_read_leaf },
1543 { MKTAG( 'h', 'd', 'l', 'r' ), mov_read_hdlr },
1544 { MKTAG( 'h', 'i', 'n', 't' ), mov_read_leaf },
1545 { MKTAG( 'h', 'm', 'h', 'd' ), mov_read_leaf },
1546 { MKTAG( 'i', 'o', 'd', 's' ), mov_read_leaf },
1547 { MKTAG( 'm', 'd', 'a', 't' ), mov_read_mdat },
1548 { MKTAG( 'm', 'd', 'h', 'd' ), mov_read_mdhd },
1549 { MKTAG( 'm', 'd', 'i', 'a' ), mov_read_default },
1550 { MKTAG( 'm', 'i', 'n', 'f' ), mov_read_default },
1551 { MKTAG( 'm', 'o', 'o', 'v' ), mov_read_moov },
1552 { MKTAG( 'm', 'p', '4', 'a' ), mov_read_default },
1553 { MKTAG( 'm', 'p', '4', 's' ), mov_read_default },
1554 { MKTAG( 'm', 'p', '4', 'v' ), mov_read_default },
1555 { MKTAG( 'm', 'p', 'o', 'd' ), mov_read_leaf },
1556 { MKTAG( 'm', 'v', 'h', 'd' ), mov_read_mvhd },
1557 { MKTAG( 'n', 'm', 'h', 'd' ), mov_read_leaf },
1558 { MKTAG( 'o', 'd', 'h', 'd' ), mov_read_default },
1559 { MKTAG( 's', 'd', 'h', 'd' ), mov_read_default },
1560 { MKTAG( 's', 'k', 'i', 'p' ), mov_read_leaf },
1561 { MKTAG( 's', 'm', 'h', 'd' ), mov_read_leaf }, /* sound media info header */
1562 { MKTAG( 'S', 'M', 'I', ' ' ), mov_read_smi }, /* Sorenson extension ??? */
1563 { MKTAG( 'a', 'v', 'c', 'C' ), mov_read_avcC },
1564 { MKTAG( 's', 't', 'b', 'l' ), mov_read_default },
1565 { MKTAG( 's', 't', 'c', 'o' ), mov_read_stco },
1566 { MKTAG( 's', 't', 'd', 'p' ), mov_read_default },
1567 { MKTAG( 's', 't', 's', 'c' ), mov_read_stsc },
1568 { MKTAG( 's', 't', 's', 'd' ), mov_read_stsd }, /* sample description */
1569 { MKTAG( 's', 't', 's', 'h' ), mov_read_default },
1570 { MKTAG( 's', 't', 's', 's' ), mov_read_stss }, /* sync sample */
1571 { MKTAG( 's', 't', 's', 'z' ), mov_read_stsz }, /* sample size */
1572 { MKTAG( 's', 't', 't', 's' ), mov_read_stts },
1573 { MKTAG( 't', 'k', 'h', 'd' ), mov_read_tkhd }, /* track header */
1574 { MKTAG( 't', 'r', 'a', 'k' ), mov_read_trak },
1575 { MKTAG( 't', 'r', 'e', 'f' ), mov_read_default }, /* not really */
1576 { MKTAG( 'u', 'd', 't', 'a' ), mov_read_leaf },
1577 { MKTAG( 'u', 'r', 'l', ' ' ), mov_read_leaf },
1578 { MKTAG( 'u', 'r', 'n', ' ' ), mov_read_leaf },
1579 { MKTAG( 'u', 'u', 'i', 'd' ), mov_read_leaf },
1580 { MKTAG( 'v', 'm', 'h', 'd' ), mov_read_leaf }, /* video media info header */
1581 { MKTAG( 'w', 'a', 'v', 'e' ), mov_read_wave },
1583 { MKTAG( 'M', 'D', 'E', 'S' ), mov_read_leaf },
1585 { MKTAG( 'c', 'h', 'a', 'p' ), mov_read_leaf },
1586 { MKTAG( 'c', 'l', 'i', 'p' ), mov_read_default },
1587 { MKTAG( 'c', 'r', 'g', 'n' ), mov_read_leaf },
1588 { MKTAG( 'c', 't', 'a', 'b' ), mov_read_ctab },
1589 { MKTAG( 'e', 's', 'd', 's' ), mov_read_esds },
1590 { MKTAG( 'k', 'm', 'a', 't' ), mov_read_leaf },
1591 { MKTAG( 'm', 'a', 't', 't' ), mov_read_default },
1592 { MKTAG( 'r', 'd', 'r', 'f' ), mov_read_leaf },
1593 { MKTAG( 'r', 'm', 'd', 'a' ), mov_read_default },
1594 { MKTAG( 'r', 'm', 'd', 'r' ), mov_read_leaf },
1595 { MKTAG( 'r', 'm', 'r', 'a' ), mov_read_default },
1596 { MKTAG( 's', 'c', 'p', 't' ), mov_read_leaf },
1597 { MKTAG( 's', 's', 'r', 'c' ), mov_read_leaf },
1598 { MKTAG( 's', 'y', 'n', 'c' ), mov_read_leaf },
1599 { MKTAG( 't', 'c', 'm', 'd' ), mov_read_leaf },
1600 { MKTAG( 'w', 'i', 'd', 'e' ), mov_read_wide }, /* place holder */
1601 //{ MKTAG( 'r', 'm', 'q', 'u' ), mov_read_leaf },
1603 { MKTAG( 'c', 'm', 'o', 'v' ), mov_read_cmov },
1605 { MKTAG( 'c', 'm', 'o', 'v' ), mov_read_leaf },
1607 { 0L, mov_read_leaf }
1610 static void mov_free_stream_context(MOVStreamContext *sc)
1613 av_freep(&sc->chunk_offsets);
1614 av_freep(&sc->sample_to_chunk);
1615 av_freep(&sc->sample_sizes);
1616 av_freep(&sc->keyframes);
1617 av_freep(&sc->stts_data);
1618 av_freep(&sc->ctts_data);
1623 static inline uint32_t mov_to_tag(uint8_t *buf)
1625 return MKTAG(buf[0], buf[1], buf[2], buf[3]);
1628 static inline uint32_t to_be32(uint8_t *buf)
1630 return (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3];
1633 /* XXX: is it sufficient ? */
1634 static int mov_probe(AVProbeData *p)
1636 unsigned int offset;
1640 /* check file header */
1641 if (p->buf_size <= 12)
1645 /* ignore invalid offset */
1646 if ((offset + 8) > (unsigned int)p->buf_size)
1648 tag = mov_to_tag(p->buf + offset + 4);
1650 /* check for obvious tags */
1651 case MKTAG( 'm', 'o', 'o', 'v' ):
1652 case MKTAG( 'm', 'd', 'a', 't' ):
1653 case MKTAG( 'p', 'n', 'o', 't' ): /* detect movs with preview pics like ew.mov and april.mov */
1654 case MKTAG( 'u', 'd', 't', 'a' ): /* Packet Video PVAuthor adds this and a lot of more junk */
1655 return AVPROBE_SCORE_MAX;
1656 /* those are more common words, so rate then a bit less */
1657 case MKTAG( 'w', 'i', 'd', 'e' ):
1658 case MKTAG( 'f', 'r', 'e', 'e' ):
1659 case MKTAG( 'j', 'u', 'n', 'k' ):
1660 case MKTAG( 'p', 'i', 'c', 't' ):
1661 return AVPROBE_SCORE_MAX - 5;
1662 case MKTAG( 'f', 't', 'y', 'p' ):
1663 case MKTAG( 's', 'k', 'i', 'p' ):
1664 case MKTAG( 'u', 'u', 'i', 'd' ):
1665 offset = to_be32(p->buf+offset) + offset;
1666 /* if we only find those cause probedata is too small at least rate them */
1667 score = AVPROBE_SCORE_MAX - 50;
1670 /* unrecognized tag */
1677 static int mov_read_header(AVFormatContext *s, AVFormatParameters *ap)
1679 MOVContext *mov = (MOVContext *) s->priv_data;
1680 ByteIOContext *pb = &s->pb;
1682 MOV_atom_t atom = { 0, 0, 0 };
1685 mov->parse_table = mov_default_parse_table;
1687 /* XXX: I think we should auto detect */
1688 if(s->iformat->name[1] == 'p')
1691 if(!url_is_streamed(pb)) /* .mov and .mp4 aren't streamable anyway (only progressive download if moov is before mdat) */
1692 atom.size = url_fsize(pb);
1694 atom.size = 0x7FFFFFFFFFFFFFFFLL;
1696 /* check MOV header */
1697 err = mov_read_default(mov, pb, atom);
1698 if (err<0 || (!mov->found_moov && !mov->found_mdat)) {
1699 av_log(s, AV_LOG_ERROR, "mov: header not found !!! (err:%d, moov:%d, mdat:%d) pos:%"PRId64"\n",
1700 err, mov->found_moov, mov->found_mdat, url_ftell(pb));
1703 dprintf("on_parse_exit_offset=%d\n", (int) url_ftell(pb));
1705 /* some cleanup : make sure we are on the mdat atom */
1706 if(!url_is_streamed(pb) && (url_ftell(pb) != mov->mdat_offset))
1707 url_fseek(pb, mov->mdat_offset, SEEK_SET);
1709 mov->next_chunk_offset = mov->mdat_offset; /* initialise reading */
1710 mov->total_streams = nb = s->nb_streams;
1713 for(i=0; i<s->nb_streams;) {
1714 if(s->streams[i]->codec->codec_type == CODEC_TYPE_MOV_OTHER) {/* not audio, not video, delete */
1715 av_free(s->streams[i]);
1716 for(j=i+1; j<s->nb_streams; j++)
1717 s->streams[j-1] = s->streams[j];
1722 for(i=0; i<s->nb_streams;i++) {
1723 MOVStreamContext *sc = (MOVStreamContext *)s->streams[i]->priv_data;
1727 av_set_pts_info(s->streams[i], 64, sc->time_rate, sc->time_scale);
1729 assert(s->streams[i]->duration % sc->time_rate == 0);
1730 s->streams[i]->duration /= sc->time_rate;
1733 sc->is_ff_stream = 1;
1739 /* Yes, this is ugly... I didn't write the specs of QT :p */
1740 /* XXX:remove useless commented code sometime */
1741 static int mov_read_packet(AVFormatContext *s, AVPacket *pkt)
1743 MOVContext *mov = (MOVContext *) s->priv_data;
1744 MOVStreamContext *sc;
1746 int64_t offset = INT64_MAX;
1747 int64_t best_dts = INT64_MAX;
1753 #ifdef MOV_SPLIT_CHUNKS
1756 idx = sc->sample_to_chunk_index;
1758 if (idx < 0) return 0;
1759 dprintf("sc[ffid %d]->sample_size = %ld\n", sc->ffindex, sc->sample_size);
1760 //size = sc->sample_sizes[sc->current_sample];
1761 // that ain't working...
1762 //size = (sc->sample_size)?sc->sample_size:sc->sample_sizes[sc->current_sample];
1763 size = (sc->sample_size > 1)?sc->sample_size:sc->sample_sizes[sc->current_sample];
1765 sc->current_sample++;
1766 sc->left_in_chunk--;
1768 if (sc->left_in_chunk <= 0)
1770 offset = mov->next_chunk_offset;
1771 /* extract the sample */
1779 if(offset == INT64_MAX)
1780 best_dts= INT64_MAX;
1781 for(i=0; i<mov->total_streams; i++) {
1782 MOVStreamContext *msc = mov->streams[i];
1784 if ((msc->next_chunk < msc->chunk_count) && msc->next_chunk >= 0){
1785 if (msc->sample_to_time_index < msc->stts_count && mov->ni) {
1787 int index= msc->sample_to_time_index;
1788 int sample= msc->sample_to_time_sample;
1789 int time= msc->sample_to_time_time;
1790 int duration = msc->stts_data[index].duration;
1791 int count = msc->stts_data[index].count;
1792 if (sample + count < msc->current_sample) {
1794 time += count*duration;
1796 duration = msc->stts_data[index].duration;
1798 dts = time + (msc->current_sample-1 - sample) * (int64_t)duration;
1799 dts = av_rescale(dts, AV_TIME_BASE, msc->time_scale);
1800 dprintf("stream: %d dts: %Ld best_dts: %Ld offset: %Ld \n", i, dts, best_dts, offset);
1804 offset = msc->chunk_offsets[msc->next_chunk];
1807 if ((msc->chunk_offsets[msc->next_chunk] < offset)) {
1809 offset = msc->chunk_offsets[msc->next_chunk];
1814 if (!sc || offset==INT64_MAX)
1819 if(mov->next_chunk_offset < offset) { /* some meta data */
1820 url_fskip(&s->pb, (offset - mov->next_chunk_offset));
1821 mov->next_chunk_offset = offset;
1824 if(!sc->is_ff_stream || (s->streams[sc->ffindex]->discard >= AVDISCARD_ALL)) {
1825 url_fskip(&s->pb, (offset - mov->next_chunk_offset));
1826 mov->next_chunk_offset = offset;
1831 /* now get the chunk size... */
1833 for(i=0; i<mov->total_streams; i++) {
1834 MOVStreamContext *msc = mov->streams[i];
1835 if ((msc->next_chunk < msc->chunk_count)
1836 && msc->chunk_offsets[msc->next_chunk] - offset < size
1837 && msc->chunk_offsets[msc->next_chunk] > offset)
1838 size = msc->chunk_offsets[msc->next_chunk] - offset;
1841 #ifdef MOV_MINOLTA_FIX
1842 //Make sure that size is according to sample_size (Needed by .mov files
1843 //created on a Minolta Dimage Xi where audio chunks contains waste data in the end)
1844 //Maybe we should really not only check sc->sample_size, but also sc->sample_sizes
1845 //but I have no such movies
1846 if (sc->sample_size > 0) {
1848 for(i=0; i<(sc->sample_to_chunk_sz); i++) {
1849 if( (sc->sample_to_chunk[i].first)<=(sc->next_chunk) )
1851 // I can't figure out why for PCM audio sample_size is always 1
1852 // (it should actually be channels*bits_per_second/8) but it is.
1853 AVCodecContext* cod = s->streams[sc->ffindex]->codec;
1854 if (sc->sample_size == 1 && (cod->codec_id == CODEC_ID_PCM_S16BE || cod->codec_id == CODEC_ID_PCM_S16LE))
1855 foundsize=(sc->sample_to_chunk[i].count*cod->channels*cod->bits_per_sample)/8;
1857 foundsize=sc->sample_to_chunk[i].count*sc->sample_size;
1859 dprintf("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);
1861 if( (foundsize>0) && (foundsize<size) )
1866 #endif //MOV_MINOLTA_FIX
1868 idx = sc->sample_to_chunk_index;
1869 if (idx + 1 < sc->sample_to_chunk_sz && sc->next_chunk >= sc->sample_to_chunk[idx + 1].first)
1871 sc->sample_to_chunk_index = idx;
1872 #ifdef MOV_SPLIT_CHUNKS
1873 /* split chunks into samples */
1874 if (sc->sample_size == 0 || sc->sample_size > 100) {
1875 if (idx >= 0 && sc->sample_to_chunk[idx].count != 1) {
1877 /* we'll have to get those samples before next chunk */
1878 sc->left_in_chunk = sc->sample_to_chunk[idx].count - 1;
1879 size = (sc->sample_size > 1)?sc->sample_size:sc->sample_sizes[sc->current_sample];
1882 sc->current_sample++;
1883 }else if(idx + 1 < sc->sample_to_chunk_sz){
1884 sc->current_sample += sc->sample_size * sc->sample_to_chunk[idx].count;
1889 dprintf("chunk: %lli -> %lli (%i)\n", offset, offset + size, size);
1890 if(size == 0x0FFFFFFF)
1891 size = mov->mdat_size + mov->mdat_offset - offset;
1896 url_fseek(&s->pb, offset, SEEK_SET);
1898 av_get_packet(&s->pb, pkt, size);
1899 pkt->stream_index = sc->ffindex;
1901 // If the keyframes table exists, mark any samples that are in the table as key frames.
1902 // If no table exists, treat very sample as a key frame.
1903 if (sc->keyframes) {
1905 b = sc->keyframe_count - 1;
1908 m = (a + b + 1) >> 1;
1909 if (sc->keyframes[m] > sc->current_sample) {
1916 if (sc->keyframes[a] == sc->current_sample)
1917 pkt->flags |= PKT_FLAG_KEY;
1920 pkt->flags |= PKT_FLAG_KEY;
1922 mov->next_chunk_offset = offset + size;
1924 /* find the corresponding dts */
1925 if (sc && sc->sample_to_time_index < sc->stts_count && pkt) {
1928 unsigned int duration = sc->stts_data[sc->sample_to_time_index].duration;
1929 count = sc->stts_data[sc->sample_to_time_index].count;
1930 if ((sc->sample_to_time_sample + count) < sc->current_sample) {
1931 sc->sample_to_time_sample += count;
1932 sc->sample_to_time_time += count*duration;
1933 sc->sample_to_time_index ++;
1934 duration = sc->stts_data[sc->sample_to_time_index].duration;
1936 dts = sc->sample_to_time_time + (sc->current_sample-1 - sc->sample_to_time_sample) * (int64_t)duration;
1937 /* find the corresponding pts */
1938 if (sc->sample_to_ctime_index < sc->ctts_count) {
1939 int duration = sc->ctts_data[sc->sample_to_ctime_index].duration;
1940 int count = sc->ctts_data[sc->sample_to_ctime_index].count;
1942 if ((sc->sample_to_ctime_sample + count) < sc->current_sample) {
1943 sc->sample_to_ctime_sample += count;
1944 sc->sample_to_ctime_index ++;
1945 duration = sc->ctts_data[sc->sample_to_ctime_index].duration;
1947 pts = dts + duration;
1951 st= s->streams[ sc->ffindex ];
1952 assert(pts % st->time_base.num == 0);
1953 assert(dts % st->time_base.num == 0);
1955 pkt->pts = pts / st->time_base.num;
1956 pkt->dts = dts / st->time_base.num;
1957 dprintf("stream #%d smp #%ld dts = %lld pts = %lld (smp:%ld time:%lld idx:%d ent:%d count:%d dur:%d)\n"
1958 , pkt->stream_index, sc->current_sample-1, pkt->dts, pkt->pts
1959 , sc->sample_to_time_sample
1960 , sc->sample_to_time_time
1961 , sc->sample_to_time_index
1970 #if defined(MOV_SPLIT_CHUNKS) && defined(MOV_SEEK)
1972 * Seek method based on the one described in the Appendix C of QTFileFormat.pdf
1974 static int mov_read_seek(AVFormatContext *s, int stream_index, int64_t sample_time, int flags)
1976 MOVContext* mov = (MOVContext *) s->priv_data;
1977 MOVStreamContext* sc;
1980 int32_t seek_sample, sample;
1984 int32_t left_in_chunk;
1985 int64_t chunk_file_offset;
1986 int64_t sample_file_offset;
1987 int32_t first_chunk_sample;
1988 int32_t sample_to_chunk_idx;
1989 int sample_to_time_index;
1990 long sample_to_time_sample = 0;
1991 uint64_t sample_to_time_time = 0;
1994 // Find the corresponding mov stream
1995 for (mov_idx = 0; mov_idx < mov->total_streams; mov_idx++)
1996 if (mov->streams[mov_idx]->ffindex == stream_index)
1998 if (mov_idx == mov->total_streams) {
1999 av_log(s, AV_LOG_ERROR, "mov: requested stream was not found in mov streams (idx=%i)\n", stream_index);
2002 sc = mov->streams[mov_idx];
2004 sample_time *= s->streams[stream_index]->time_base.num;
2006 // Step 1. Find the edit that contains the requested time (elst)
2007 if (sc->edit_count && 0) {
2008 // FIXME should handle edit list
2009 av_log(s, AV_LOG_ERROR, "mov: does not handle seeking in files that contain edit list (c:%d)\n", sc->edit_count);
2013 // Step 2. Find the corresponding sample using the Time-to-sample atom (stts) */
2014 dprintf("Searching for time %li in stream #%i (time_scale=%i)\n", (long)sample_time, mov_idx, sc->time_scale);
2015 start_time = 0; // FIXME use elst atom
2016 sample = 1; // sample are 0 based in table
2018 for (i = 0; i < sc->stts_count; i++) {
2019 count = sc->stts_data[i].count;
2020 duration = sc->stts_data[i].duration;
2021 if ((start_time + count*duration) > sample_time) {
2022 sample_to_time_time = start_time;
2023 sample_to_time_index = i;
2024 sample_to_time_sample = sample;
2025 sample += (sample_time - start_time) / duration;
2029 start_time += count * duration;
2031 sample_to_time_time = start_time;
2032 sample_to_time_index = i;
2033 /* NOTE: despite what qt doc say, the dt value (Display Time in qt vocabulary) computed with the stts atom
2034 is a decoding time stamp (dts) not a presentation time stamp. And as usual dts != pts for stream with b frames */
2036 dprintf("Found time %li at sample #%u\n", (long)sample_time, sample);
2037 if (sample > sc->sample_count) {
2038 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);
2042 // Step 3. Find the prior sync. sample using the Sync sample atom (stss)
2043 if (sc->keyframes) {
2045 b = sc->keyframe_count - 1;
2047 m = (a + b + 1) >> 1;
2048 if (sc->keyframes[m] > sample) {
2054 // for low latency prob: always use the previous keyframe, just uncomment the next line
2056 seek_sample = sc->keyframes[a];
2059 seek_sample = sample; // else all samples are key frames
2060 dprintf("Found nearest keyframe at sample #%i \n", seek_sample);
2062 // Step 4. Find the chunk of the sample using the Sample-to-chunk-atom (stsc)
2063 for (first_chunk_sample = 1, i = 0; i < (sc->sample_to_chunk_sz - 1); i++) {
2064 b = (sc->sample_to_chunk[i + 1].first - sc->sample_to_chunk[i].first) * sc->sample_to_chunk[i].count;
2065 if (seek_sample >= first_chunk_sample && seek_sample < (first_chunk_sample + b))
2067 first_chunk_sample += b;
2069 chunk = sc->sample_to_chunk[i].first + (seek_sample - first_chunk_sample) / sc->sample_to_chunk[i].count;
2070 left_in_chunk = sc->sample_to_chunk[i].count - (seek_sample - first_chunk_sample) % sc->sample_to_chunk[i].count;
2071 first_chunk_sample += ((seek_sample - first_chunk_sample) / sc->sample_to_chunk[i].count) * sc->sample_to_chunk[i].count;
2072 sample_to_chunk_idx = i;
2073 dprintf("Sample was found in chunk #%i at sample offset %i (idx %i)\n", chunk, seek_sample - first_chunk_sample, sample_to_chunk_idx);
2075 // Step 5. Find the offset of the chunk using the chunk offset atom
2076 if (!sc->chunk_offsets) {
2077 av_log(s, AV_LOG_ERROR, "mov: no chunk offset atom, unable to seek\n");
2080 if (chunk > sc->chunk_count) {
2081 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);
2084 chunk_file_offset = sc->chunk_offsets[chunk - 1];
2085 dprintf("Chunk file offset is #%llu \n", chunk_file_offset);
2087 // Step 6. Find the byte offset within the chunk using the sample size atom
2088 sample_file_offset = chunk_file_offset;
2089 if (sc->sample_size)
2090 sample_file_offset += (seek_sample - first_chunk_sample) * sc->sample_size;
2092 for (i = 0; i < (seek_sample - first_chunk_sample); i++) {
2093 sample_file_offset += sc->sample_sizes[first_chunk_sample + i - 1];
2096 dprintf("Sample file offset is #%llu \n", sample_file_offset);
2098 // Step 6. Update the parser
2100 mov->next_chunk_offset = sample_file_offset;
2101 // Update current stream state
2102 sc->current_sample = seek_sample - 1; // zero based
2103 sc->left_in_chunk = left_in_chunk;
2104 sc->next_chunk = chunk; // +1 -1 (zero based)
2105 sc->sample_to_chunk_index = sample_to_chunk_idx;
2107 // Update other streams
2108 for (i = 0; i<mov->total_streams; i++) {
2109 MOVStreamContext *msc;
2110 if (i == mov_idx) continue;
2111 // Find the nearest 'next' chunk
2112 msc = mov->streams[i];
2114 b = msc->chunk_count - 1;
2116 m = (a + b + 1) >> 1;
2117 if (msc->chunk_offsets[m] > chunk_file_offset) {
2123 msc->next_chunk = a;
2124 if (msc->chunk_offsets[a] < chunk_file_offset && a < (msc->chunk_count-1))
2126 dprintf("Nearest next chunk for stream #%i is #%li @%lli\n", i, msc->next_chunk+1, msc->chunk_offsets[msc->next_chunk]);
2128 // Compute sample count and index in the sample_to_chunk table (what a pity)
2129 msc->sample_to_chunk_index = 0;
2130 msc->current_sample = 0;
2131 for(; msc->sample_to_chunk_index < (msc->sample_to_chunk_sz - 1)
2132 && msc->sample_to_chunk[msc->sample_to_chunk_index + 1].first <= (1 + msc->next_chunk); msc->sample_to_chunk_index++) {
2133 msc->current_sample += (msc->sample_to_chunk[msc->sample_to_chunk_index + 1].first - msc->sample_to_chunk[msc->sample_to_chunk_index].first) \
2134 * msc->sample_to_chunk[msc->sample_to_chunk_index].count;
2136 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;
2137 msc->left_in_chunk = msc->sample_to_chunk[msc->sample_to_chunk_index].count - 1;
2138 // Find corresponding position in stts (used later to compute dts)
2141 for (msc->sample_to_time_index = 0; msc->sample_to_time_index < msc->stts_count; msc->sample_to_time_index++) {
2142 count = msc->stts_data[msc->sample_to_time_index].count;
2143 duration = msc->stts_data[msc->sample_to_time_index].duration;
2144 if ((sample + count - 1) > msc->current_sample) {
2145 msc->sample_to_time_time = start_time;
2146 msc->sample_to_time_sample = sample;
2150 start_time += count * duration;
2153 for (msc->sample_to_ctime_index = 0; msc->sample_to_ctime_index < msc->ctts_count; msc->sample_to_ctime_index++) {
2154 count = msc->ctts_data[msc->sample_to_ctime_index].count;
2155 duration = msc->ctts_data[msc->sample_to_ctime_index].duration;
2156 if ((sample + count - 1) > msc->current_sample) {
2157 msc->sample_to_ctime_sample = sample;
2162 dprintf("Next Sample for stream #%i is #%li @%li\n", i, msc->current_sample + 1, msc->sample_to_chunk_index + 1);
2168 static int mov_read_close(AVFormatContext *s)
2171 MOVContext *mov = (MOVContext *) s->priv_data;
2172 for(i=0; i<mov->total_streams; i++)
2173 mov_free_stream_context(mov->streams[i]);
2174 /* free color tabs */
2175 for(i=0; i<mov->ctab_size; i++)
2176 av_freep(&mov->ctab[i]);
2177 av_freep(&mov->ctab);
2181 static AVInputFormat mov_iformat = {
2182 "mov,mp4,m4a,3gp,3g2",
2183 "QuickTime/MPEG4 format",
2189 #if defined(MOV_SPLIT_CHUNKS) && defined(MOV_SEEK)
2196 av_register_input_format(&mov_iformat);