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"
69 /* Special handling for movies created with Minolta Dimaxe Xi*/
70 /* this fix should not interfere with other .mov files, but just in case*/
71 #define MOV_MINOLTA_FIX
73 /* some streams in QT (and in MP4 mostly) aren't either video nor audio */
74 /* so we first list them as this, then clean up the list of streams we give back, */
75 /* getting rid of these */
76 #define CODEC_TYPE_MOV_OTHER (enum CodecType) 2
78 /* http://gpac.sourceforge.net/tutorial/mediatypes.htm */
79 const CodecTag ff_mov_obj_type[] = {
80 { CODEC_ID_MPEG4 , 32 },
81 { CODEC_ID_H264 , 33 },
82 { CODEC_ID_AAC , 64 },
83 { CODEC_ID_MPEG2VIDEO, 96 }, /* MPEG2 Simple */
84 { CODEC_ID_MPEG2VIDEO, 97 }, /* MPEG2 Main */
85 { CODEC_ID_MPEG2VIDEO, 98 }, /* MPEG2 SNR */
86 { CODEC_ID_MPEG2VIDEO, 99 }, /* MPEG2 Spatial */
87 { CODEC_ID_MPEG2VIDEO, 100 }, /* MPEG2 High */
88 { CODEC_ID_MPEG2VIDEO, 101 }, /* MPEG2 422 */
89 { CODEC_ID_AAC , 102 }, /* MPEG2 AAC Main */
90 { CODEC_ID_AAC , 103 }, /* MPEG2 AAC Low */
91 { CODEC_ID_AAC , 104 }, /* MPEG2 AAC SSR */
92 { CODEC_ID_MP3 , 105 },
93 { CODEC_ID_MPEG1VIDEO, 106 },
94 { CODEC_ID_MP2 , 107 },
95 { CODEC_ID_MJPEG , 108 },
96 { CODEC_ID_PCM_S16LE , 224 },
97 { CODEC_ID_VORBIS , 221 },
98 { CODEC_ID_AC3 , 226 },
99 { CODEC_ID_PCM_ALAW , 227 },
100 { CODEC_ID_PCM_MULAW , 228 },
101 { CODEC_ID_PCM_S16BE , 230 },
102 { CODEC_ID_H263 , 242 },
103 { CODEC_ID_H261 , 243 },
107 static const CodecTag mov_video_tags[] = {
108 /* { CODEC_ID_, MKTAG('c', 'v', 'i', 'd') }, *//* Cinepak */
109 /* { CODEC_ID_H263, MKTAG('r', 'a', 'w', ' ') }, *//* Uncompressed RGB */
110 /* { CODEC_ID_H263, MKTAG('Y', 'u', 'v', '2') }, *//* Uncompressed YUV422 */
111 /* { CODEC_ID_RAWVIDEO, MKTAG('A', 'V', 'U', 'I') }, *//* YUV with alpha-channel (AVID Uncompressed) */
116 { CODEC_ID_MJPEG, MKTAG('j', 'p', 'e', 'g') }, /* PhotoJPEG */
117 { CODEC_ID_MPEG1VIDEO, MKTAG('m', 'p', 'e', 'g') }, /* MPEG */
118 { CODEC_ID_MJPEG, MKTAG('m', 'j', 'p', 'a') }, /* Motion-JPEG (format A) */
119 { CODEC_ID_MJPEG, MKTAG('m', 'j', 'p', 'b') }, /* Motion-JPEG (format B) */
120 { CODEC_ID_MJPEG, MKTAG('A', 'V', 'D', 'J') }, /* MJPEG with alpha-channel (AVID JFIF meridien compressed) */
121 /* { CODEC_ID_MJPEG, MKTAG('A', 'V', 'R', 'n') }, *//* MJPEG with alpha-channel (AVID ABVB/Truevision NuVista) */
122 /* { CODEC_ID_GIF, MKTAG('g', 'i', 'f', ' ') }, *//* embedded gif files as frames (usually one "click to play movie" frame) */
124 { CODEC_ID_SVQ1, MKTAG('S', 'V', 'Q', '1') }, /* Sorenson Video v1 */
125 { CODEC_ID_SVQ1, MKTAG('s', 'v', 'q', '1') }, /* Sorenson Video v1 */
126 { CODEC_ID_SVQ1, MKTAG('s', 'v', 'q', 'i') }, /* Sorenson Video v1 (from QT specs)*/
127 { CODEC_ID_SVQ3, MKTAG('S', 'V', 'Q', '3') }, /* Sorenson Video v3 */
128 { CODEC_ID_MPEG4, MKTAG('m', 'p', '4', 'v') },
129 { CODEC_ID_MPEG4, MKTAG('D', 'I', 'V', 'X') }, /* OpenDiVX *//* sample files at http://heroinewarrior.com/xmovie.php3 use this tag */
130 { CODEC_ID_MPEG4, MKTAG('X', 'V', 'I', 'D') },
131 { CODEC_ID_MPEG4, MKTAG('3', 'I', 'V', '2') }, /* experimental: 3IVX files before ivx D4 4.5.1 */
132 /* { CODEC_ID_, MKTAG('I', 'V', '5', '0') }, *//* Indeo 5.0 */
133 { CODEC_ID_H263, MKTAG('h', '2', '6', '3') }, /* H263 */
134 { CODEC_ID_H263, MKTAG('s', '2', '6', '3') }, /* H263 ?? works */
135 { CODEC_ID_DVVIDEO, MKTAG('d', 'v', 'c', ' ') }, /* DV NTSC */
136 { CODEC_ID_DVVIDEO, MKTAG('d', 'v', 'c', 'p') }, /* DV PAL */
137 /* { CODEC_ID_DVVIDEO, MKTAG('A', 'V', 'd', 'v') }, *//* AVID dv */
138 { CODEC_ID_VP3, MKTAG('V', 'P', '3', '1') }, /* On2 VP3 */
139 { CODEC_ID_RPZA, MKTAG('r', 'p', 'z', 'a') }, /* Apple Video (RPZA) */
140 { CODEC_ID_CINEPAK, MKTAG('c', 'v', 'i', 'd') }, /* Cinepak */
141 { CODEC_ID_8BPS, MKTAG('8', 'B', 'P', 'S') }, /* Planar RGB (8BPS) */
142 { CODEC_ID_SMC, MKTAG('s', 'm', 'c', ' ') }, /* Apple Graphics (SMC) */
143 { CODEC_ID_QTRLE, MKTAG('r', 'l', 'e', ' ') }, /* Apple Animation (RLE) */
144 { CODEC_ID_QDRAW, MKTAG('q', 'd', 'r', 'w') }, /* QuickDraw */
145 { CODEC_ID_H264, MKTAG('a', 'v', 'c', '1') }, /* AVC-1/H.264 */
146 { CODEC_ID_MPEG2VIDEO, MKTAG('h', 'd', 'v', '2') }, /* MPEG2 produced by Sony HD camera */
147 { CODEC_ID_MPEG2VIDEO, MKTAG('h', 'd', 'v', '3') }, /* HDV produced by FCP */
148 { CODEC_ID_MPEG2VIDEO, MKTAG('m', 'x', '5', 'n') }, /* MPEG2 IMX NTSC 525/60 50mb/s produced by FCP */
149 { CODEC_ID_MPEG2VIDEO, MKTAG('m', 'x', '5', 'p') }, /* MPEG2 IMX PAL 625/50 50mb/s produced by FCP */
150 { CODEC_ID_MPEG2VIDEO, MKTAG('m', 'x', '3', 'n') }, /* MPEG2 IMX NTSC 525/60 30mb/s produced by FCP */
151 { CODEC_ID_MPEG2VIDEO, MKTAG('m', 'x', '3', 'p') }, /* MPEG2 IMX PAL 625/50 30mb/s produced by FCP */
152 { CODEC_ID_DVVIDEO, MKTAG('d', 'v', 'p', 'p') }, /* DVCPRO PAL produced by FCP */
153 //{ CODEC_ID_DVVIDEO, MKTAG('d', 'v', 'h', '5') }, /* DVCPRO HD 50i produced by FCP */
154 //{ CODEC_ID_DVVIDEO, MKTAG('d', 'v', 'h', '6') }, /* DVCPRO HD 60i produced by FCP */
155 { CODEC_ID_DVVIDEO, MKTAG('d', 'v', '5', 'p') }, /* DVCPRO50 PAL produced by FCP */
156 { CODEC_ID_DVVIDEO, MKTAG('d', 'v', '5', 'n') }, /* DVCPRO50 NTSC produced by FCP */
157 //{ CODEC_ID_JPEG2000, MKTAG('m', 'j', 'p', '2') }, /* JPEG 2000 produced by FCP */
158 { CODEC_ID_NONE, 0 },
161 static const CodecTag mov_audio_tags[] = {
162 { CODEC_ID_PCM_S32BE, MKTAG('i', 'n', '3', '2') },
163 { CODEC_ID_PCM_S24BE, MKTAG('i', 'n', '2', '4') },
164 /* { CODEC_ID_PCM_S16BE, MKTAG('N', 'O', 'N', 'E') }, *//* uncompressed */
165 { CODEC_ID_PCM_S16BE, MKTAG('t', 'w', 'o', 's') }, /* 16 bits */
166 /* { CODEC_ID_PCM_S8, MKTAG('t', 'w', 'o', 's') },*/ /* 8 bits */
167 { CODEC_ID_PCM_U8, MKTAG('r', 'a', 'w', ' ') }, /* 8 bits unsigned */
168 { CODEC_ID_PCM_S16LE, MKTAG('s', 'o', 'w', 't') }, /* */
169 { CODEC_ID_PCM_MULAW, MKTAG('u', 'l', 'a', 'w') }, /* */
170 { CODEC_ID_PCM_ALAW, MKTAG('a', 'l', 'a', 'w') }, /* */
171 { CODEC_ID_ADPCM_IMA_QT, MKTAG('i', 'm', 'a', '4') }, /* IMA-4 ADPCM */
172 { CODEC_ID_MACE3, MKTAG('M', 'A', 'C', '3') }, /* Macintosh Audio Compression and Expansion 3:1 */
173 { CODEC_ID_MACE6, MKTAG('M', 'A', 'C', '6') }, /* Macintosh Audio Compression and Expansion 6:1 */
175 { CODEC_ID_MP2, MKTAG('.', 'm', 'p', '3') }, /* MPEG layer 3 */ /* sample files at http://www.3ivx.com/showcase.html use this tag */
176 { CODEC_ID_MP2, 0x6D730055 }, /* MPEG layer 3 */
177 { CODEC_ID_MP2, 0x5500736D }, /* MPEG layer 3 *//* XXX: check endianness */
178 /* { CODEC_ID_OGG_VORBIS, MKTAG('O', 'g', 'g', 'S') }, *//* sample files at http://heroinewarrior.com/xmovie.php3 use this tag */
180 { CODEC_ID_AAC, MKTAG('m', 'p', '4', 'a') }, /* MPEG-4 AAC */
181 /* The standard for mpeg4 audio is still not normalised AFAIK anyway */
182 { CODEC_ID_AMR_NB, MKTAG('s', 'a', 'm', 'r') }, /* AMR-NB 3gp */
183 { CODEC_ID_AMR_WB, MKTAG('s', 'a', 'w', 'b') }, /* AMR-WB 3gp */
184 { CODEC_ID_AC3, MKTAG('m', 's', 0x20, 0x00) }, /* Dolby AC-3 */
185 { CODEC_ID_ALAC,MKTAG('a', 'l', 'a', 'c') }, /* Apple Lossless */
186 { CODEC_ID_QDM2,MKTAG('Q', 'D', 'M', '2') }, /* QDM2 */
187 { CODEC_ID_NONE, 0 },
190 /* map numeric codes from mdhd atom to ISO 639 */
191 /* cf. QTFileFormat.pdf p253, qtff.pdf p205 */
192 /* http://developer.apple.com/documentation/mac/Text/Text-368.html */
193 /* deprecated by putting the code as 3*5bit ascii */
194 static const char *mov_mdhd_language_map[] = {
196 "eng", "fra", "ger", "ita", "dut", "sve", "spa", "dan", "por", "nor",
197 "heb", "jpn", "ara", "fin", "gre", "ice", "mlt", "tur", "hr "/*scr*/, "chi"/*ace?*/,
198 "urd", "hin", "tha", "kor", "lit", "pol", "hun", "est", "lav", NULL,
199 "fo ", NULL, "rus", "chi", NULL, "iri", "alb", "ron", "ces", "slk",
200 "slv", "yid", "sr ", "mac", "bul", "ukr", "bel", "uzb", "kaz", "aze",
202 "aze", "arm", "geo", "mol", "kir", "tgk", "tuk", "mon", NULL, "pus",
203 "kur", "kas", "snd", "tib", "nep", "san", "mar", "ben", "asm", "guj",
204 "pa ", "ori", "mal", "kan", "tam", "tel", NULL, "bur", "khm", "lao",
206 "vie", "ind", "tgl", "may", "may", "amh", "tir", "orm", "som", "swa",
208 NULL, "run", NULL, "mlg", "epo", NULL, NULL, NULL, NULL, NULL,
210 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
211 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
212 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, "wel", "baq",
213 "cat", "lat", "que", "grn", "aym", "tat", "uig", "dzo", "jav"
216 /* the QuickTime file format is quite convoluted...
217 * it has lots of index tables, each indexing something in another one...
218 * Here we just use what is needed to read the chunks
221 typedef struct MOV_sample_to_chunk_tbl {
225 } MOV_sample_to_chunk_tbl;
230 int64_t size; /* total size (excluding the size and type fields) */
242 uint32_t flags; // 24bit
244 /* 0x03 ESDescrTag */
246 #define MP4ODescrTag 0x01
247 #define MP4IODescrTag 0x02
248 #define MP4ESDescrTag 0x03
249 #define MP4DecConfigDescrTag 0x04
250 #define MP4DecSpecificDescrTag 0x05
251 #define MP4SLConfigDescrTag 0x06
252 #define MP4ContentIdDescrTag 0x07
253 #define MP4SupplContentIdDescrTag 0x08
254 #define MP4IPIPtrDescrTag 0x09
255 #define MP4IPMPPtrDescrTag 0x0A
256 #define MP4IPMPDescrTag 0x0B
257 #define MP4RegistrationDescrTag 0x0D
258 #define MP4ESIDIncDescrTag 0x0E
259 #define MP4ESIDRefDescrTag 0x0F
260 #define MP4FileIODescrTag 0x10
261 #define MP4FileODescrTag 0x11
262 #define MP4ExtProfileLevelDescrTag 0x13
263 #define MP4ExtDescrTagsStart 0x80
264 #define MP4ExtDescrTagsEnd 0xFE
265 uint8_t stream_priority;
267 /* 0x04 DecConfigDescrTag */
268 uint8_t object_type_id;
270 /* XXX: really streamType is
271 * only 6bit, followed by:
275 uint32_t buffer_size_db; // 24
276 uint32_t max_bitrate;
277 uint32_t avg_bitrate;
279 /* 0x05 DecSpecificDescrTag */
280 uint8_t decoder_cfg_len;
281 uint8_t *decoder_cfg;
283 /* 0x06 SLConfigDescrTag */
284 uint8_t sl_config_len;
288 struct MOVParseTableEntry;
290 typedef struct MOVStreamContext {
291 int ffindex; /* the ffmpeg stream id */
292 int is_ff_stream; /* Is this stream presented to ffmpeg ? i.e. is this an audio or video stream ? */
295 int64_t *chunk_offsets;
297 Time2Sample *stts_data;
299 Time2Sample *ctts_data;
300 int edit_count; /* number of 'edit' (elst atom) */
301 long sample_to_chunk_sz;
302 MOV_sample_to_chunk_tbl *sample_to_chunk;
303 long sample_to_chunk_index;
304 int sample_to_time_index;
305 long sample_to_time_sample;
306 uint64_t sample_to_time_time;
307 int sample_to_ctime_index;
308 int sample_to_ctime_sample;
317 long left_in_chunk; /* how many samples before next chunk */
321 typedef struct MOVContext {
322 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) */
325 int64_t duration; /* duration of the longest track */
326 int found_moov; /* when both 'moov' and 'mdat' sections has been found */
327 int found_mdat; /* we suppose we have enough data to read the file */
330 int ni; ///< non interleaved mode
332 /* some streams listed here aren't presented to the ffmpeg API, since they aren't either video nor audio
333 * but we need the info to be able to skip data from those streams in the 'mdat' section
335 MOVStreamContext *streams[MAX_STREAMS];
337 int64_t next_chunk_offset;
338 MOVStreamContext *partial; /* != 0 : there is still to read in the current chunk */
340 MOV_ctab_t **ctab; /* color tables */
341 const struct MOVParseTableEntry *parse_table; /* could be eventually used to change the table */
342 /* NOTE: for recursion save to/ restore from local variable! */
344 AVPaletteControl palette_control;
348 /* XXX: it's the first time I make a recursive parser I think... sorry if it's ugly :P */
350 /* those functions parse an atom */
352 1: found what I wanted, exit
353 0: continue to parse next atom
354 -1: error occured, exit
356 typedef int (*mov_parse_function)(MOVContext *ctx, ByteIOContext *pb, MOV_atom_t atom);
358 /* links atom IDs to parse functions */
359 typedef struct MOVParseTableEntry {
361 mov_parse_function func;
362 } MOVParseTableEntry;
364 static int ff_mov_lang_to_iso639(int code, char *to)
367 /* is it the mangled iso code? */
368 /* see http://www.geocities.com/xhelmboyx/quicktime/formats/mp4-layout.txt */
370 for (i = 2; i >= 0; i--) {
371 to[i] = 0x60 + (code & 0x1f);
376 /* old fashion apple lang code */
377 if (code >= (sizeof(mov_mdhd_language_map)/sizeof(char *)))
379 if (!mov_mdhd_language_map[code])
381 strncpy(to, mov_mdhd_language_map[code], 4);
385 extern int ff_mov_iso639_to_lang(const char *lang, int mp4); /* for movenc.c */
386 int ff_mov_iso639_to_lang(const char *lang, int mp4)
390 /* old way, only for QT? */
391 for (i = 0; !mp4 && (i < (sizeof(mov_mdhd_language_map)/sizeof(char *))); i++) {
392 if (mov_mdhd_language_map[i] && !strcmp(lang, mov_mdhd_language_map[i]))
395 /* XXX:can we do that in mov too? */
398 /* handle undefined as such */
402 for (i = 0; i < 3; i++) {
403 unsigned char c = (unsigned char)lang[i];
414 static int mov_read_leaf(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
417 url_fskip(pb, atom.size);
418 /* url_seek(pb, atom_offset+atom.size, SEEK_SET); */
422 static int mov_read_default(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
424 int64_t total_size = 0;
429 a.offset = atom.offset;
432 atom.size = 0x7fffffffffffffffLL;
433 while(((total_size + 8) < atom.size) && !url_feof(pb) && !err) {
437 a.size = get_be32(pb);
438 a.type = get_le32(pb);
442 dprintf("type: %08x %.4s sz: %"PRIx64" %"PRIx64" %"PRIx64"\n", a.type, (char*)&a.type, a.size, atom.size, total_size);
443 if (a.size == 1) { /* 64 bit extended size */
444 a.size = get_be64(pb) - 8;
449 a.size = atom.size - total_size;
453 for (i = 0; c->parse_table[i].type != 0L
454 && c->parse_table[i].type != a.type; i++)
462 if (c->parse_table[i].type == 0) { /* skip leaf atoms data */
463 url_fskip(pb, a.size);
465 err = (c->parse_table[i].func)(c, pb, a);
469 total_size += a.size;
472 if (!err && total_size < atom.size && atom.size < 0x7ffff) {
473 url_fskip(pb, atom.size - total_size);
479 static int mov_read_ctab(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
482 url_fskip(pb, atom.size); // for now
484 VERY VERY BROKEN, NEVER execute this, needs rewrite
487 c->ctab = av_realloc(c->ctab, ++c->ctab_size);
488 t = c->ctab[c->ctab_size];
489 t->seed = get_be32(pb);
490 t->flags = get_be16(pb);
491 t->size = get_be16(pb) + 1;
492 len = 2 * t->size * 4;
494 t->clrs = av_malloc(len); // 16bit A R G B
496 get_buffer(pb, t->clrs, len);
503 static int mov_read_hdlr(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
505 AVStream *st = c->fc->streams[c->fc->nb_streams-1];
510 get_byte(pb); /* version */
511 get_byte(pb); get_byte(pb); get_byte(pb); /* flags */
514 ctype = get_le32(pb);
515 type = get_le32(pb); /* component subtype */
517 dprintf("ctype= %c%c%c%c (0x%08lx)\n", *((char *)&ctype), ((char *)&ctype)[1], ((char *)&ctype)[2], ((char *)&ctype)[3], (long) ctype);
518 dprintf("stype= %c%c%c%c\n", *((char *)&type), ((char *)&type)[1], ((char *)&type)[2], ((char *)&type)[3]);
519 if(ctype == MKTAG('m', 'h', 'l', 'r')) /* MOV */
523 if(type == MKTAG('v', 'i', 'd', 'e'))
524 st->codec->codec_type = CODEC_TYPE_VIDEO;
525 else if(type == MKTAG('s', 'o', 'u', 'n'))
526 st->codec->codec_type = CODEC_TYPE_AUDIO;
527 get_be32(pb); /* component manufacture */
528 get_be32(pb); /* component flags */
529 get_be32(pb); /* component flags mask */
532 return 0; /* nothing left to read */
533 /* XXX: MP4 uses a C string, not a pascal one */
538 while(get_byte(pb) && (++len < (atom.size - 24)));
540 /* .mov: PASCAL string */
545 url_fskip(pb, atom.size - (url_ftell(pb) - atom.offset));
549 static int mov_mp4_read_descr_len(ByteIOContext *pb)
554 int c = get_byte(pb);
555 len = (len << 7) | (c & 0x7f);
562 static int mov_mp4_read_descr(ByteIOContext *pb, int *tag)
566 len = mov_mp4_read_descr_len(pb);
567 dprintf("MPEG4 description: tag=0x%02x len=%d\n", *tag, len);
571 static int mov_read_esds(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
573 AVStream *st = c->fc->streams[c->fc->nb_streams-1];
574 MOVStreamContext *sc = (MOVStreamContext *)st->priv_data;
575 int64_t start_pos = url_ftell(pb);
578 /* Well, broken but suffisant for some MP4 streams */
579 get_be32(pb); /* version + flags */
580 len = mov_mp4_read_descr(pb, &tag);
581 if (tag == MP4ESDescrTag) {
582 get_be16(pb); /* ID */
583 get_byte(pb); /* priority */
585 get_be16(pb); /* ID */
587 len = mov_mp4_read_descr(pb, &tag);
588 if (tag == MP4DecConfigDescrTag) {
589 sc->esds.object_type_id = get_byte(pb);
590 sc->esds.stream_type = get_byte(pb);
591 sc->esds.buffer_size_db = get_be24(pb);
592 sc->esds.max_bitrate = get_be32(pb);
593 sc->esds.avg_bitrate = get_be32(pb);
595 st->codec->codec_id= codec_get_id(ff_mov_obj_type, sc->esds.object_type_id);
596 len = mov_mp4_read_descr(pb, &tag);
597 if (tag == MP4DecSpecificDescrTag) {
598 dprintf("Specific MPEG4 header len=%d\n", len);
599 st->codec->extradata = (uint8_t*) av_mallocz(len + FF_INPUT_BUFFER_PADDING_SIZE);
600 if (st->codec->extradata) {
601 get_buffer(pb, st->codec->extradata, len);
602 st->codec->extradata_size = len;
606 /* in any case, skip garbage */
607 url_fskip(pb, atom.size - ((url_ftell(pb) - start_pos)));
611 /* this atom contains actual media data */
612 static int mov_read_mdat(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
614 if(atom.size == 0) /* wrong one (MP4) */
617 c->mdat_offset = atom.offset;
618 c->mdat_size = atom.size;
620 return 1; /* found both, just go */
621 url_fskip(pb, atom.size);
622 return 0; /* now go for moov */
625 static int mov_read_ftyp(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
627 uint32_t type = get_le32(pb);
631 case MKTAG('i', 's', 'o', 'm'):
632 case MKTAG('m', 'p', '4', '1'):
633 case MKTAG('m', 'p', '4', '2'):
634 case MKTAG('3', 'g', 'p', '1'):
635 case MKTAG('3', 'g', 'p', '2'):
636 case MKTAG('3', 'g', '2', 'a'):
637 case MKTAG('3', 'g', 'p', '3'):
638 case MKTAG('3', 'g', 'p', '4'):
639 case MKTAG('3', 'g', 'p', '5'):
640 case MKTAG('m', 'm', 'p', '4'): /* Mobile MP4 */
641 case MKTAG('M', '4', 'A', ' '): /* Apple iTunes AAC-LC Audio */
642 case MKTAG('M', '4', 'P', ' '): /* Apple iTunes AAC-LC Protected Audio */
643 case MKTAG('m', 'j', 'p', '2'): /* Motion Jpeg 2000 */
645 case MKTAG('q', 't', ' ', ' '):
647 av_log(c->fc, AV_LOG_DEBUG, "ISO: File Type Major Brand: %.4s\n",(char *)&type);
649 get_be32(pb); /* minor version */
650 url_fskip(pb, atom.size - 8);
654 /* this atom should contain all header atoms */
655 static int mov_read_moov(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
659 err = mov_read_default(c, pb, atom);
660 /* we parsed the 'moov' atom, we can terminate the parsing as soon as we find the 'mdat' */
661 /* so we don't parse the whole file if over a network */
664 return 1; /* found both, just go */
665 return 0; /* now go for mdat */
669 static int mov_read_mdhd(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
671 AVStream *st = c->fc->streams[c->fc->nb_streams-1];
672 MOVStreamContext *sc = (MOVStreamContext *)st->priv_data;
673 int version = get_byte(pb);
677 return 1; /* unsupported */
679 get_byte(pb); get_byte(pb);
680 get_byte(pb); /* flags */
686 get_be32(pb); /* creation time */
687 get_be32(pb); /* modification time */
690 sc->time_scale = get_be32(pb);
691 st->duration = (version == 1) ? get_be64(pb) : get_be32(pb); /* duration */
693 lang = get_be16(pb); /* language */
694 ff_mov_lang_to_iso639(lang, st->language);
695 get_be16(pb); /* quality */
700 static int mov_read_mvhd(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
702 int version = get_byte(pb); /* version */
703 get_byte(pb); get_byte(pb); get_byte(pb); /* flags */
709 get_be32(pb); /* creation time */
710 get_be32(pb); /* modification time */
712 c->time_scale = get_be32(pb); /* time scale */
714 av_log(NULL, AV_LOG_DEBUG, "time scale = %i\n", c->time_scale);
716 c->duration = (version == 1) ? get_be64(pb) : get_be32(pb); /* duration */
717 get_be32(pb); /* preferred scale */
719 get_be16(pb); /* preferred volume */
721 url_fskip(pb, 10); /* reserved */
723 url_fskip(pb, 36); /* display matrix */
725 get_be32(pb); /* preview time */
726 get_be32(pb); /* preview duration */
727 get_be32(pb); /* poster time */
728 get_be32(pb); /* selection time */
729 get_be32(pb); /* selection duration */
730 get_be32(pb); /* current time */
731 get_be32(pb); /* next track ID */
736 static int mov_read_smi(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
738 AVStream *st = c->fc->streams[c->fc->nb_streams-1];
740 if((uint64_t)atom.size > (1<<30))
743 // currently SVQ3 decoder expect full STSD header - so let's fake it
744 // this should be fixed and just SMI header should be passed
745 av_free(st->codec->extradata);
746 st->codec->extradata_size = 0x5a + atom.size;
747 st->codec->extradata = (uint8_t*) av_mallocz(st->codec->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE);
749 if (st->codec->extradata) {
750 strcpy(st->codec->extradata, "SVQ3"); // fake
751 get_buffer(pb, st->codec->extradata + 0x5a, atom.size);
752 dprintf("Reading SMI %"PRId64" %s\n", atom.size, (char*)st->codec->extradata + 0x5a);
754 url_fskip(pb, atom.size);
759 static int mov_read_enda(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
761 AVStream *st = c->fc->streams[c->fc->nb_streams-1];
762 int little_endian = get_be16(pb);
765 switch (st->codec->codec_id) {
766 case CODEC_ID_PCM_S24BE:
767 st->codec->codec_id = CODEC_ID_PCM_S24LE;
769 case CODEC_ID_PCM_S32BE:
770 st->codec->codec_id = CODEC_ID_PCM_S32LE;
779 static int mov_read_alac(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
781 AVStream *st = c->fc->streams[c->fc->nb_streams-1];
783 // currently ALAC decoder expect full atom header - so let's fake it
784 // this should be fixed and just ALAC header should be passed
786 av_free(st->codec->extradata);
787 st->codec->extradata_size = 36;
788 st->codec->extradata = (uint8_t*) av_mallocz(st->codec->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE);
790 if (st->codec->extradata) {
791 strcpy(st->codec->extradata + 4, "alac"); // fake
792 get_buffer(pb, st->codec->extradata + 8, 36 - 8);
793 dprintf("Reading alac %d %s\n", st->codec->extradata_size, (char*)st->codec->extradata);
795 url_fskip(pb, atom.size);
799 static int mov_read_wave(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
801 offset_t start_pos = url_ftell(pb);
802 AVStream *st = c->fc->streams[c->fc->nb_streams-1];
804 if((uint64_t)atom.size > (1<<30))
807 if (st->codec->codec_id == CODEC_ID_QDM2) {
808 // pass all frma atom to codec, needed at least for QDM2
809 av_free(st->codec->extradata);
810 st->codec->extradata_size = atom.size;
811 st->codec->extradata = (uint8_t*) av_mallocz(st->codec->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE);
813 if (st->codec->extradata) {
814 get_buffer(pb, st->codec->extradata, atom.size);
816 url_fskip(pb, atom.size);
817 } else if (atom.size > 8) { /* to read frma, esds atoms */
818 mov_read_default(c, pb, atom);
819 } else if (atom.size > 0)
820 url_fskip(pb, atom.size);
821 /* in any case, skip garbage */
822 url_fskip(pb, atom.size - ((url_ftell(pb) - start_pos)));
826 static int mov_read_jp2h(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
828 AVStream *st = c->fc->streams[c->fc->nb_streams-1];
830 if((uint64_t)atom.size > (1<<30))
833 av_free(st->codec->extradata);
835 st->codec->extradata_size = atom.size + 8;
836 st->codec->extradata = (uint8_t*) av_mallocz(st->codec->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE);
838 /* pass all jp2h atom to codec */
839 if (st->codec->extradata) {
840 strcpy(st->codec->extradata + 4, "jp2h");
841 get_buffer(pb, st->codec->extradata + 8, atom.size);
843 url_fskip(pb, atom.size);
847 static int mov_read_avcC(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
849 AVStream *st = c->fc->streams[c->fc->nb_streams-1];
851 if((uint64_t)atom.size > (1<<30))
854 av_free(st->codec->extradata);
856 st->codec->extradata_size = atom.size;
857 st->codec->extradata = (uint8_t*) av_mallocz(st->codec->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE);
859 if (st->codec->extradata) {
860 get_buffer(pb, st->codec->extradata, atom.size);
862 url_fskip(pb, atom.size);
867 static int mov_read_stco(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
869 AVStream *st = c->fc->streams[c->fc->nb_streams-1];
870 MOVStreamContext *sc = (MOVStreamContext *)st->priv_data;
871 unsigned int i, entries;
873 get_byte(pb); /* version */
874 get_byte(pb); get_byte(pb); get_byte(pb); /* flags */
876 entries = get_be32(pb);
878 if(entries >= UINT_MAX/sizeof(int64_t))
881 sc->chunk_count = entries;
882 sc->chunk_offsets = (int64_t*) av_malloc(entries * sizeof(int64_t));
883 if (!sc->chunk_offsets)
885 if (atom.type == MKTAG('s', 't', 'c', 'o')) {
886 for(i=0; i<entries; i++) {
887 sc->chunk_offsets[i] = get_be32(pb);
889 } else if (atom.type == MKTAG('c', 'o', '6', '4')) {
890 for(i=0; i<entries; i++) {
891 sc->chunk_offsets[i] = get_be64(pb);
896 for(i=0; i<c->fc->nb_streams; i++){
897 MOVStreamContext *sc2 = (MOVStreamContext *)c->fc->streams[i]->priv_data;
898 if(sc2 && sc2->chunk_offsets){
899 int64_t first= sc2->chunk_offsets[0];
900 int64_t last= sc2->chunk_offsets[sc2->chunk_count-1];
901 if(first >= sc->chunk_offsets[entries-1] || last <= sc->chunk_offsets[0])
908 static int mov_read_stsd(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
910 AVStream *st = c->fc->streams[c->fc->nb_streams-1];
911 MOVStreamContext *sc = (MOVStreamContext *)st->priv_data;
912 int entries, frames_per_sample;
914 uint8_t codec_name[32];
916 /* for palette traversal */
924 unsigned char *color_table;
926 unsigned char r, g, b;
928 get_byte(pb); /* version */
929 get_byte(pb); get_byte(pb); get_byte(pb); /* flags */
931 entries = get_be32(pb);
933 while(entries--) { //Parsing Sample description table
935 MOV_atom_t a = { 0, 0, 0 };
936 offset_t start_pos = url_ftell(pb);
937 int size = get_be32(pb); /* size */
938 format = get_le32(pb); /* data format */
940 get_be32(pb); /* reserved */
941 get_be16(pb); /* reserved */
942 get_be16(pb); /* index */
944 dprintf("size=%d 4CC= %c%c%c%c codec_type=%d\n",
946 (format >> 0) & 0xff, (format >> 8) & 0xff, (format >> 16) & 0xff, (format >> 24) & 0xff,
947 st->codec->codec_type);
948 st->codec->codec_tag = format;
949 /* codec_type is set earlier by read_hdlr */
950 if(st->codec->codec_type==CODEC_TYPE_VIDEO) {
951 /* for MPEG4: set codec type by looking for it */
952 id = codec_get_id(mov_video_tags, format);
954 id = codec_get_id(codec_bmp_tags, format);
955 st->codec->codec_id = id;
956 get_be16(pb); /* version */
957 get_be16(pb); /* revision level */
958 get_be32(pb); /* vendor */
959 get_be32(pb); /* temporal quality */
960 get_be32(pb); /* spacial quality */
961 if(st->codec->codec_id == CODEC_ID_MPEG4){ //FIXME this is silly
965 st->codec->width = get_be16(pb); /* width */
966 st->codec->height = get_be16(pb); /* height */
968 get_be32(pb); /* horiz resolution */
969 get_be32(pb); /* vert resolution */
970 get_be32(pb); /* data size, always 0 */
971 frames_per_sample = get_be16(pb); /* frames per samples */
973 av_log(NULL, AV_LOG_DEBUG, "frames/samples = %d\n", frames_per_sample);
975 get_buffer(pb, codec_name, 32); /* codec name, pascal string (FIXME: true for mp4?) */
976 if (codec_name[0] <= 31) {
977 memcpy(st->codec->codec_name, &codec_name[1],codec_name[0]);
978 st->codec->codec_name[codec_name[0]] = 0;
981 st->codec->bits_per_sample = get_be16(pb); /* depth */
982 st->codec->color_table_id = get_be16(pb); /* colortable id */
984 /* These are set in mov_read_stts and might already be set!
985 st->codec->time_base.den = 25;
986 st->codec->time_base.num = 1;
989 /* figure out the palette situation */
990 color_depth = st->codec->bits_per_sample & 0x1F;
991 color_greyscale = st->codec->bits_per_sample & 0x20;
993 /* if the depth is 2, 4, or 8 bpp, file is palettized */
994 if ((color_depth == 2) || (color_depth == 4) ||
995 (color_depth == 8)) {
997 if (color_greyscale) {
999 /* compute the greyscale palette */
1000 color_count = 1 << color_depth;
1002 color_dec = 256 / (color_count - 1);
1003 for (j = 0; j < color_count; j++) {
1004 r = g = b = color_index;
1005 c->palette_control.palette[j] =
1006 (r << 16) | (g << 8) | (b);
1007 color_index -= color_dec;
1008 if (color_index < 0)
1012 } else if (st->codec->color_table_id & 0x08) {
1014 /* if flag bit 3 is set, use the default palette */
1015 color_count = 1 << color_depth;
1016 if (color_depth == 2)
1017 color_table = ff_qt_default_palette_4;
1018 else if (color_depth == 4)
1019 color_table = ff_qt_default_palette_16;
1021 color_table = ff_qt_default_palette_256;
1023 for (j = 0; j < color_count; j++) {
1024 r = color_table[j * 4 + 0];
1025 g = color_table[j * 4 + 1];
1026 b = color_table[j * 4 + 2];
1027 c->palette_control.palette[j] =
1028 (r << 16) | (g << 8) | (b);
1033 /* load the palette from the file */
1034 color_start = get_be32(pb);
1035 color_count = get_be16(pb);
1036 color_end = get_be16(pb);
1037 for (j = color_start; j <= color_end; j++) {
1038 /* each R, G, or B component is 16 bits;
1039 * only use the top 8 bits; skip alpha bytes
1049 c->palette_control.palette[j] =
1050 (r << 16) | (g << 8) | (b);
1054 st->codec->palctrl = &c->palette_control;
1055 st->codec->palctrl->palette_changed = 1;
1057 st->codec->palctrl = NULL;
1058 } else if(st->codec->codec_type==CODEC_TYPE_AUDIO) {
1059 uint16_t version = get_be16(pb);
1061 st->codec->codec_id = codec_get_id(mov_audio_tags, format);
1062 get_be16(pb); /* revision level */
1063 get_be32(pb); /* vendor */
1065 st->codec->channels = get_be16(pb); /* channel count */
1066 st->codec->bits_per_sample = get_be16(pb); /* sample size */
1067 /* do we need to force to 16 for AMR ? */
1069 /* handle specific s8 codec */
1070 get_be16(pb); /* compression id = 0*/
1071 get_be16(pb); /* packet size = 0 */
1073 st->codec->sample_rate = ((get_be32(pb) >> 16));
1075 switch (st->codec->codec_id) {
1076 case CODEC_ID_PCM_S16LE:
1077 case CODEC_ID_PCM_S16BE:
1078 if (st->codec->bits_per_sample == 8)
1079 st->codec->codec_id = CODEC_ID_PCM_S8;
1080 st->codec->bit_rate = st->codec->sample_rate * 8;
1082 case CODEC_ID_PCM_U8:
1083 if (st->codec->bits_per_sample == 16)
1084 st->codec->codec_id = CODEC_ID_PCM_S16BE;
1085 st->codec->bit_rate = st->codec->sample_rate * 8;
1087 case CODEC_ID_AMR_WB:
1088 st->codec->sample_rate = 16000; /* should really we ? */
1089 st->codec->channels=1; /* really needed */
1091 case CODEC_ID_AMR_NB:
1092 st->codec->sample_rate = 8000; /* should really we ? */
1093 st->codec->channels=1; /* really needed */
1099 //Read QT version 1 fields. In version 0 theese dont exist
1100 dprintf("version =%d mp4=%d\n",version,c->mp4);
1102 get_be32(pb); /* samples per packet */
1103 get_be32(pb); /* bytes per packet */
1104 get_be32(pb); /* bytes per frame */
1105 get_be32(pb); /* bytes per sample */
1106 } else if(version==2) {
1107 get_be32(pb); /* sizeof struct only */
1108 st->codec->sample_rate = av_int2dbl(get_be64(pb)); /* float 64 */
1109 st->codec->channels = get_be32(pb);
1110 get_be32(pb); /* always 0x7F000000 */
1111 get_be32(pb); /* bits per channel if sound is uncompressed */
1112 get_be32(pb); /* lcpm format specific flag */
1113 get_be32(pb); /* bytes per audio packet if constant */
1114 get_be32(pb); /* lpcm frames per audio packet if constant */
1117 /* other codec type, just skip (rtp, mp4s, tmcd ...) */
1118 url_fskip(pb, size - (url_ftell(pb) - start_pos));
1120 /* this will read extra atoms at the end (wave, alac, damr, avcC, SMI ...) */
1121 a.size = size - (url_ftell(pb) - start_pos);
1123 mov_read_default(c, pb, a);
1124 else if (a.size > 0)
1125 url_fskip(pb, a.size);
1128 if(st->codec->codec_type==CODEC_TYPE_AUDIO && st->codec->sample_rate==0 && sc->time_scale>1) {
1129 st->codec->sample_rate= sc->time_scale;
1135 static int mov_read_stsc(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
1137 AVStream *st = c->fc->streams[c->fc->nb_streams-1];
1138 MOVStreamContext *sc = (MOVStreamContext *)st->priv_data;
1139 unsigned int i, entries;
1141 get_byte(pb); /* version */
1142 get_byte(pb); get_byte(pb); get_byte(pb); /* flags */
1144 entries = get_be32(pb);
1146 if(entries >= UINT_MAX / sizeof(MOV_sample_to_chunk_tbl))
1150 av_log(NULL, AV_LOG_DEBUG, "track[%i].stsc.entries = %i\n", c->fc->nb_streams-1, entries);
1152 sc->sample_to_chunk_sz = entries;
1153 sc->sample_to_chunk = (MOV_sample_to_chunk_tbl*) av_malloc(entries * sizeof(MOV_sample_to_chunk_tbl));
1154 if (!sc->sample_to_chunk)
1156 for(i=0; i<entries; i++) {
1157 sc->sample_to_chunk[i].first = get_be32(pb);
1158 sc->sample_to_chunk[i].count = get_be32(pb);
1159 sc->sample_to_chunk[i].id = get_be32(pb);
1164 static int mov_read_stss(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
1166 AVStream *st = c->fc->streams[c->fc->nb_streams-1];
1167 MOVStreamContext *sc = (MOVStreamContext *)st->priv_data;
1168 unsigned int i, entries;
1170 get_byte(pb); /* version */
1171 get_byte(pb); get_byte(pb); get_byte(pb); /* flags */
1173 entries = get_be32(pb);
1175 if(entries >= UINT_MAX / sizeof(long))
1178 sc->keyframe_count = entries;
1180 av_log(NULL, AV_LOG_DEBUG, "keyframe_count = %ld\n", sc->keyframe_count);
1182 sc->keyframes = (long*) av_malloc(entries * sizeof(long));
1185 for(i=0; i<entries; i++) {
1186 sc->keyframes[i] = get_be32(pb);
1188 /* av_log(NULL, AV_LOG_DEBUG, "keyframes[]=%ld\n", sc->keyframes[i]); */
1194 static int mov_read_stsz(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
1196 AVStream *st = c->fc->streams[c->fc->nb_streams-1];
1197 MOVStreamContext *sc = (MOVStreamContext *)st->priv_data;
1198 unsigned int i, entries;
1200 get_byte(pb); /* version */
1201 get_byte(pb); get_byte(pb); get_byte(pb); /* flags */
1203 sc->sample_size = get_be32(pb);
1204 entries = get_be32(pb);
1205 if(entries >= UINT_MAX / sizeof(long))
1208 sc->sample_count = entries;
1210 av_log(NULL, AV_LOG_DEBUG, "sample_size = %ld sample_count = %ld\n", sc->sample_size, sc->sample_count);
1212 if(sc->sample_size) {
1213 /* override sample size for uncompressed sound */
1214 switch (st->codec->codec_id) {
1215 case CODEC_ID_PCM_S32BE:
1216 case CODEC_ID_PCM_S32LE:
1217 sc->sample_size = 4 * st->codec->channels;
1219 case CODEC_ID_PCM_S24BE:
1220 case CODEC_ID_PCM_S24LE:
1221 sc->sample_size = 3 * st->codec->channels;
1223 case CODEC_ID_PCM_S16BE:
1224 case CODEC_ID_PCM_S16LE:
1225 sc->sample_size = 2 * st->codec->channels;
1227 case CODEC_ID_PCM_MULAW:
1228 case CODEC_ID_PCM_ALAW:
1229 case CODEC_ID_PCM_S8:
1230 case CODEC_ID_PCM_U8:
1231 sc->sample_size = 1 * st->codec->channels;
1236 assert(sc->sample_size);
1237 return 0; /* there isn't any table following */
1239 sc->sample_sizes = (long*) av_malloc(entries * sizeof(long));
1240 if (!sc->sample_sizes)
1242 for(i=0; i<entries; i++) {
1243 sc->sample_sizes[i] = get_be32(pb);
1245 av_log(NULL, AV_LOG_DEBUG, "sample_sizes[]=%ld\n", sc->sample_sizes[i]);
1251 static int mov_read_stts(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
1253 AVStream *st = c->fc->streams[c->fc->nb_streams-1];
1254 MOVStreamContext *sc = (MOVStreamContext *)st->priv_data;
1255 unsigned int i, entries;
1257 int64_t total_sample_count=0;
1259 get_byte(pb); /* version */
1260 get_byte(pb); get_byte(pb); get_byte(pb); /* flags */
1261 entries = get_be32(pb);
1262 if(entries >= UINT_MAX / sizeof(Time2Sample))
1265 sc->stts_count = entries;
1266 sc->stts_data = av_malloc(entries * sizeof(Time2Sample));
1269 av_log(NULL, AV_LOG_DEBUG, "track[%i].stts.entries = %i\n", c->fc->nb_streams-1, entries);
1274 for(i=0; i<entries; i++) {
1275 int sample_duration;
1278 sample_count=get_be32(pb);
1279 sample_duration = get_be32(pb);
1280 sc->stts_data[i].count= sample_count;
1281 sc->stts_data[i].duration= sample_duration;
1283 sc->time_rate= ff_gcd(sc->time_rate, sample_duration);
1285 dprintf("sample_count=%d, sample_duration=%d\n",sample_count,sample_duration);
1287 duration+=(int64_t)sample_duration*sample_count;
1288 total_sample_count+=sample_count;
1291 st->nb_frames= total_sample_count;
1293 st->duration= duration;
1297 static int mov_read_ctts(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
1299 AVStream *st = c->fc->streams[c->fc->nb_streams-1];
1300 MOVStreamContext *sc = (MOVStreamContext *)st->priv_data;
1301 unsigned int i, entries;
1303 get_byte(pb); /* version */
1304 get_byte(pb); get_byte(pb); get_byte(pb); /* flags */
1305 entries = get_be32(pb);
1306 if(entries >= UINT_MAX / sizeof(Time2Sample))
1309 sc->ctts_count = entries;
1310 sc->ctts_data = av_malloc(entries * sizeof(Time2Sample));
1312 dprintf("track[%i].ctts.entries = %i\n", c->fc->nb_streams-1, entries);
1314 for(i=0; i<entries; i++) {
1315 int count =get_be32(pb);
1316 int duration =get_be32(pb);
1318 sc->ctts_data[i].count = count;
1319 sc->ctts_data[i].duration= duration;
1321 sc->time_rate= ff_gcd(sc->time_rate, duration);
1326 static int mov_read_trak(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
1329 MOVStreamContext *sc;
1331 st = av_new_stream(c->fc, c->fc->nb_streams);
1333 sc = (MOVStreamContext*) av_mallocz(sizeof(MOVStreamContext));
1339 sc->sample_to_chunk_index = -1;
1341 st->codec->codec_type = CODEC_TYPE_MOV_OTHER;
1342 st->start_time = 0; /* XXX: check */
1343 c->streams[c->fc->nb_streams-1] = sc;
1345 return mov_read_default(c, pb, atom);
1348 static int mov_read_tkhd(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
1350 AVStream *st = c->fc->streams[c->fc->nb_streams-1];
1351 int version = get_byte(pb);
1353 get_byte(pb); get_byte(pb);
1354 get_byte(pb); /* flags */
1356 MOV_TRACK_ENABLED 0x0001
1357 MOV_TRACK_IN_MOVIE 0x0002
1358 MOV_TRACK_IN_PREVIEW 0x0004
1359 MOV_TRACK_IN_POSTER 0x0008
1366 get_be32(pb); /* creation time */
1367 get_be32(pb); /* modification time */
1369 st->id = (int)get_be32(pb); /* track id (NOT 0 !)*/
1370 get_be32(pb); /* reserved */
1371 st->start_time = 0; /* check */
1372 (version == 1) ? get_be64(pb) : get_be32(pb); /* highlevel (considering edits) duration in movie timebase */
1373 get_be32(pb); /* reserved */
1374 get_be32(pb); /* reserved */
1376 get_be16(pb); /* layer */
1377 get_be16(pb); /* alternate group */
1378 get_be16(pb); /* volume */
1379 get_be16(pb); /* reserved */
1381 url_fskip(pb, 36); /* display matrix */
1383 /* those are fixed-point */
1384 /*st->codec->width =*/ get_be32(pb) >> 16; /* track width */
1385 /*st->codec->height =*/ get_be32(pb) >> 16; /* track height */
1390 /* this atom should be null (from specs), but some buggy files put the 'moov' atom inside it... */
1391 /* like the files created with Adobe Premiere 5.0, for samples see */
1392 /* http://graphics.tudelft.nl/~wouter/publications/soundtests/ */
1393 static int mov_read_wide(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
1398 return 0; /* continue */
1399 if (get_be32(pb) != 0) { /* 0 sized mdat atom... use the 'wide' atom size */
1400 url_fskip(pb, atom.size - 4);
1403 atom.type = get_le32(pb);
1406 if (atom.type != MKTAG('m', 'd', 'a', 't')) {
1407 url_fskip(pb, atom.size);
1410 err = mov_read_mdat(c, pb, atom);
1416 static int null_read_packet(void *opaque, uint8_t *buf, int buf_size)
1421 static int mov_read_cmov(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
1425 uint8_t *moov_data; /* uncompressed data */
1426 long cmov_len, moov_len;
1429 get_be32(pb); /* dcom atom */
1430 if (get_le32(pb) != MKTAG( 'd', 'c', 'o', 'm' ))
1432 if (get_le32(pb) != MKTAG( 'z', 'l', 'i', 'b' )) {
1433 av_log(NULL, AV_LOG_ERROR, "unknown compression for cmov atom !");
1436 get_be32(pb); /* cmvd atom */
1437 if (get_le32(pb) != MKTAG( 'c', 'm', 'v', 'd' ))
1439 moov_len = get_be32(pb); /* uncompressed size */
1440 cmov_len = atom.size - 6 * 4;
1442 cmov_data = (uint8_t *) av_malloc(cmov_len);
1445 moov_data = (uint8_t *) av_malloc(moov_len);
1450 get_buffer(pb, cmov_data, cmov_len);
1451 if(uncompress (moov_data, (uLongf *) &moov_len, (const Bytef *)cmov_data, cmov_len) != Z_OK)
1453 if(init_put_byte(&ctx, moov_data, moov_len, 0, NULL, null_read_packet, NULL, NULL) != 0)
1455 ctx.buf_end = ctx.buffer + moov_len;
1456 atom.type = MKTAG( 'm', 'o', 'o', 'v' );
1458 atom.size = moov_len;
1460 // { int fd = open("/tmp/uncompheader.mov", O_WRONLY | O_CREAT); write(fd, moov_data, moov_len); close(fd); }
1462 ret = mov_read_default(c, &ctx, atom);
1470 /* edit list atom */
1471 static int mov_read_elst(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
1475 get_byte(pb); /* version */
1476 get_byte(pb); get_byte(pb); get_byte(pb); /* flags */
1477 edit_count= c->streams[c->fc->nb_streams-1]->edit_count = get_be32(pb); /* entries */
1479 for(i=0; i<edit_count; i++){
1480 get_be32(pb); /* Track duration */
1481 get_be32(pb); /* Media time */
1482 get_be32(pb); /* Media rate */
1484 dprintf("track[%i].edit_count = %i\n", c->fc->nb_streams-1, c->streams[c->fc->nb_streams-1]->edit_count);
1488 static const MOVParseTableEntry mov_default_parse_table[] = {
1490 { MKTAG( 'c', 'o', '6', '4' ), mov_read_stco },
1491 { MKTAG( 'c', 'p', 'r', 't' ), mov_read_default },
1492 { MKTAG( 'c', 'r', 'h', 'd' ), mov_read_default },
1493 { MKTAG( 'c', 't', 't', 's' ), mov_read_ctts }, /* composition time to sample */
1494 { MKTAG( 'd', 'i', 'n', 'f' ), mov_read_default }, /* data information */
1495 { MKTAG( 'd', 'p', 'n', 'd' ), mov_read_leaf },
1496 { MKTAG( 'd', 'r', 'e', 'f' ), mov_read_leaf },
1497 { MKTAG( 'e', 'd', 't', 's' ), mov_read_default },
1498 { MKTAG( 'e', 'l', 's', 't' ), mov_read_elst },
1499 { MKTAG( 'e', 'n', 'd', 'a' ), mov_read_enda },
1500 { MKTAG( 'f', 'r', 'e', 'e' ), mov_read_leaf },
1501 { MKTAG( 'f', 't', 'y', 'p' ), mov_read_ftyp },
1502 { MKTAG( 'h', 'd', 'l', 'r' ), mov_read_hdlr },
1503 { MKTAG( 'h', 'i', 'n', 't' ), mov_read_leaf },
1504 { MKTAG( 'h', 'm', 'h', 'd' ), mov_read_leaf },
1505 { MKTAG( 'i', 'o', 'd', 's' ), mov_read_leaf },
1506 { MKTAG( 'j', 'p', '2', 'h' ), mov_read_jp2h },
1507 { MKTAG( 'm', 'd', 'a', 't' ), mov_read_mdat },
1508 { MKTAG( 'm', 'd', 'h', 'd' ), mov_read_mdhd },
1509 { MKTAG( 'm', 'd', 'i', 'a' ), mov_read_default },
1510 { MKTAG( 'm', 'i', 'n', 'f' ), mov_read_default },
1511 { MKTAG( 'm', 'o', 'o', 'v' ), mov_read_moov },
1512 { MKTAG( 'm', 'p', '4', 'a' ), mov_read_default },
1513 { MKTAG( 'm', 'p', '4', 's' ), mov_read_default },
1514 { MKTAG( 'm', 'p', '4', 'v' ), mov_read_default },
1515 { MKTAG( 'm', 'p', 'o', 'd' ), mov_read_leaf },
1516 { MKTAG( 'm', 'v', 'h', 'd' ), mov_read_mvhd },
1517 { MKTAG( 'n', 'm', 'h', 'd' ), mov_read_leaf },
1518 { MKTAG( 'o', 'd', 'h', 'd' ), mov_read_default },
1519 { MKTAG( 's', 'd', 'h', 'd' ), mov_read_default },
1520 { MKTAG( 's', 'k', 'i', 'p' ), mov_read_leaf },
1521 { MKTAG( 's', 'm', 'h', 'd' ), mov_read_leaf }, /* sound media info header */
1522 { MKTAG( 'S', 'M', 'I', ' ' ), mov_read_smi }, /* Sorenson extension ??? */
1523 { MKTAG( 'a', 'l', 'a', 'c' ), mov_read_alac }, /* alac specific atom */
1524 { MKTAG( 'a', 'v', 'c', 'C' ), mov_read_avcC },
1525 { MKTAG( 's', 't', 'b', 'l' ), mov_read_default },
1526 { MKTAG( 's', 't', 'c', 'o' ), mov_read_stco },
1527 { MKTAG( 's', 't', 'd', 'p' ), mov_read_default },
1528 { MKTAG( 's', 't', 's', 'c' ), mov_read_stsc },
1529 { MKTAG( 's', 't', 's', 'd' ), mov_read_stsd }, /* sample description */
1530 { MKTAG( 's', 't', 's', 'h' ), mov_read_default },
1531 { MKTAG( 's', 't', 's', 's' ), mov_read_stss }, /* sync sample */
1532 { MKTAG( 's', 't', 's', 'z' ), mov_read_stsz }, /* sample size */
1533 { MKTAG( 's', 't', 't', 's' ), mov_read_stts },
1534 { MKTAG( 't', 'k', 'h', 'd' ), mov_read_tkhd }, /* track header */
1535 { MKTAG( 't', 'r', 'a', 'k' ), mov_read_trak },
1536 { MKTAG( 't', 'r', 'e', 'f' ), mov_read_default }, /* not really */
1537 { MKTAG( 'u', 'd', 't', 'a' ), mov_read_leaf },
1538 { MKTAG( 'u', 'r', 'l', ' ' ), mov_read_leaf },
1539 { MKTAG( 'u', 'r', 'n', ' ' ), mov_read_leaf },
1540 { MKTAG( 'u', 'u', 'i', 'd' ), mov_read_leaf },
1541 { MKTAG( 'v', 'm', 'h', 'd' ), mov_read_leaf }, /* video media info header */
1542 { MKTAG( 'w', 'a', 'v', 'e' ), mov_read_wave },
1544 { MKTAG( 'M', 'D', 'E', 'S' ), mov_read_leaf },
1546 { MKTAG( 'c', 'h', 'a', 'p' ), mov_read_leaf },
1547 { MKTAG( 'c', 'l', 'i', 'p' ), mov_read_default },
1548 { MKTAG( 'c', 'r', 'g', 'n' ), mov_read_leaf },
1549 { MKTAG( 'c', 't', 'a', 'b' ), mov_read_ctab },
1550 { MKTAG( 'e', 's', 'd', 's' ), mov_read_esds },
1551 { MKTAG( 'k', 'm', 'a', 't' ), mov_read_leaf },
1552 { MKTAG( 'm', 'a', 't', 't' ), mov_read_default },
1553 { MKTAG( 'r', 'd', 'r', 'f' ), mov_read_leaf },
1554 { MKTAG( 'r', 'm', 'd', 'a' ), mov_read_default },
1555 { MKTAG( 'r', 'm', 'd', 'r' ), mov_read_leaf },
1556 { MKTAG( 'r', 'm', 'r', 'a' ), mov_read_default },
1557 { MKTAG( 's', 'c', 'p', 't' ), mov_read_leaf },
1558 { MKTAG( 's', 's', 'r', 'c' ), mov_read_leaf },
1559 { MKTAG( 's', 'y', 'n', 'c' ), mov_read_leaf },
1560 { MKTAG( 't', 'c', 'm', 'd' ), mov_read_leaf },
1561 { MKTAG( 'w', 'i', 'd', 'e' ), mov_read_wide }, /* place holder */
1562 //{ MKTAG( 'r', 'm', 'q', 'u' ), mov_read_leaf },
1564 { MKTAG( 'c', 'm', 'o', 'v' ), mov_read_cmov },
1566 { MKTAG( 'c', 'm', 'o', 'v' ), mov_read_leaf },
1568 { 0L, mov_read_leaf }
1571 static void mov_free_stream_context(MOVStreamContext *sc)
1574 av_freep(&sc->chunk_offsets);
1575 av_freep(&sc->sample_to_chunk);
1576 av_freep(&sc->sample_sizes);
1577 av_freep(&sc->keyframes);
1578 av_freep(&sc->stts_data);
1579 av_freep(&sc->ctts_data);
1584 static inline uint32_t mov_to_tag(uint8_t *buf)
1586 return MKTAG(buf[0], buf[1], buf[2], buf[3]);
1589 static inline uint32_t to_be32(uint8_t *buf)
1591 return (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3];
1594 /* XXX: is it sufficient ? */
1595 static int mov_probe(AVProbeData *p)
1597 unsigned int offset;
1601 /* check file header */
1602 if (p->buf_size <= 12)
1606 /* ignore invalid offset */
1607 if ((offset + 8) > (unsigned int)p->buf_size)
1609 tag = mov_to_tag(p->buf + offset + 4);
1611 /* check for obvious tags */
1612 case MKTAG( 'j', 'P', ' ', ' ' ): /* jpeg 2000 signature */
1613 case MKTAG( 'm', 'o', 'o', 'v' ):
1614 case MKTAG( 'm', 'd', 'a', 't' ):
1615 case MKTAG( 'p', 'n', 'o', 't' ): /* detect movs with preview pics like ew.mov and april.mov */
1616 case MKTAG( 'u', 'd', 't', 'a' ): /* Packet Video PVAuthor adds this and a lot of more junk */
1617 return AVPROBE_SCORE_MAX;
1618 /* those are more common words, so rate then a bit less */
1619 case MKTAG( 'w', 'i', 'd', 'e' ):
1620 case MKTAG( 'f', 'r', 'e', 'e' ):
1621 case MKTAG( 'j', 'u', 'n', 'k' ):
1622 case MKTAG( 'p', 'i', 'c', 't' ):
1623 return AVPROBE_SCORE_MAX - 5;
1624 case MKTAG( 'f', 't', 'y', 'p' ):
1625 case MKTAG( 's', 'k', 'i', 'p' ):
1626 case MKTAG( 'u', 'u', 'i', 'd' ):
1627 offset = to_be32(p->buf+offset) + offset;
1628 /* if we only find those cause probedata is too small at least rate them */
1629 score = AVPROBE_SCORE_MAX - 50;
1632 /* unrecognized tag */
1639 static int mov_read_header(AVFormatContext *s, AVFormatParameters *ap)
1641 MOVContext *mov = (MOVContext *) s->priv_data;
1642 ByteIOContext *pb = &s->pb;
1644 MOV_atom_t atom = { 0, 0, 0 };
1647 mov->parse_table = mov_default_parse_table;
1649 if(!url_is_streamed(pb)) /* .mov and .mp4 aren't streamable anyway (only progressive download if moov is before mdat) */
1650 atom.size = url_fsize(pb);
1652 atom.size = 0x7FFFFFFFFFFFFFFFLL;
1654 /* check MOV header */
1655 err = mov_read_default(mov, pb, atom);
1656 if (err<0 || (!mov->found_moov && !mov->found_mdat)) {
1657 av_log(s, AV_LOG_ERROR, "mov: header not found !!! (err:%d, moov:%d, mdat:%d) pos:%"PRId64"\n",
1658 err, mov->found_moov, mov->found_mdat, url_ftell(pb));
1661 dprintf("on_parse_exit_offset=%d\n", (int) url_ftell(pb));
1663 /* some cleanup : make sure we are on the mdat atom */
1664 if(!url_is_streamed(pb) && (url_ftell(pb) != mov->mdat_offset))
1665 url_fseek(pb, mov->mdat_offset, SEEK_SET);
1667 mov->next_chunk_offset = mov->mdat_offset; /* initialise reading */
1668 mov->total_streams = nb = s->nb_streams;
1671 for(i=0; i<s->nb_streams;) {
1672 if(s->streams[i]->codec->codec_type == CODEC_TYPE_MOV_OTHER) {/* not audio, not video, delete */
1673 av_free(s->streams[i]);
1674 for(j=i+1; j<s->nb_streams; j++)
1675 s->streams[j-1] = s->streams[j];
1680 for(i=0; i<s->nb_streams;i++) {
1681 MOVStreamContext *sc = (MOVStreamContext *)s->streams[i]->priv_data;
1686 sc->time_scale= mov->time_scale;
1687 av_set_pts_info(s->streams[i], 64, sc->time_rate, sc->time_scale);
1689 if(s->streams[i]->duration != AV_NOPTS_VALUE){
1690 assert(s->streams[i]->duration % sc->time_rate == 0);
1691 s->streams[i]->duration /= sc->time_rate;
1695 sc->is_ff_stream = 1;
1701 /* Yes, this is ugly... I didn't write the specs of QT :p */
1702 /* XXX:remove useless commented code sometime */
1703 static int mov_read_packet(AVFormatContext *s, AVPacket *pkt)
1705 MOVContext *mov = (MOVContext *) s->priv_data;
1706 MOVStreamContext *sc;
1708 int64_t offset = INT64_MAX;
1709 int64_t best_dts = INT64_MAX;
1711 int next_sample= -99;
1718 idx = sc->sample_to_chunk_index;
1720 if (idx < 0) return 0;
1721 dprintf("sc[ffid %d]->sample_size = %ld\n", sc->ffindex, sc->sample_size);
1722 //size = sc->sample_sizes[sc->current_sample];
1723 // that ain't working...
1724 //size = (sc->sample_size)?sc->sample_size:sc->sample_sizes[sc->current_sample];
1725 size = (sc->sample_size > 1)?sc->sample_size:sc->sample_sizes[sc->current_sample];
1727 next_sample= sc->current_sample+1;
1729 sc->left_in_chunk--;
1731 if (sc->left_in_chunk <= 0)
1733 offset = mov->next_chunk_offset;
1734 /* extract the sample */
1741 if(offset == INT64_MAX)
1742 best_dts= INT64_MAX;
1743 for(i=0; i<mov->total_streams; i++) {
1744 MOVStreamContext *msc = mov->streams[i];
1746 if ((msc->next_chunk < msc->chunk_count) && msc->next_chunk >= 0){
1747 if (msc->sample_to_time_index < msc->stts_count && mov->ni) {
1749 int index= msc->sample_to_time_index;
1750 int sample= msc->sample_to_time_sample;
1751 int time= msc->sample_to_time_time;
1752 int duration = msc->stts_data[index].duration;
1753 int count = msc->stts_data[index].count;
1754 if (sample + count <= msc->current_sample) {
1756 time += count*duration;
1758 duration = msc->stts_data[index].duration;
1760 dts = time + (msc->current_sample - sample) * (int64_t)duration;
1761 dts = av_rescale(dts, AV_TIME_BASE, msc->time_scale);
1762 dprintf("stream: %d dts: %"PRId64" best_dts: %"PRId64" offset: %"PRId64"\n", i, dts, best_dts, offset);
1766 offset = msc->chunk_offsets[msc->next_chunk];
1769 if ((msc->chunk_offsets[msc->next_chunk] < offset)) {
1771 offset = msc->chunk_offsets[msc->next_chunk];
1776 if (!sc || offset==INT64_MAX)
1781 if(mov->next_chunk_offset < offset) { /* some meta data */
1782 url_fskip(&s->pb, (offset - mov->next_chunk_offset));
1783 mov->next_chunk_offset = offset;
1786 if(!sc->is_ff_stream || (s->streams[sc->ffindex]->discard >= AVDISCARD_ALL)) {
1787 url_fskip(&s->pb, (offset - mov->next_chunk_offset));
1788 mov->next_chunk_offset = offset;
1793 /* now get the chunk size... */
1795 for(i=0; i<mov->total_streams; i++) {
1796 MOVStreamContext *msc = mov->streams[i];
1797 if ((msc->next_chunk < msc->chunk_count)
1798 && msc->chunk_offsets[msc->next_chunk] - offset < size
1799 && msc->chunk_offsets[msc->next_chunk] > offset)
1800 size = msc->chunk_offsets[msc->next_chunk] - offset;
1803 #ifdef MOV_MINOLTA_FIX
1804 //Make sure that size is according to sample_size (Needed by .mov files
1805 //created on a Minolta Dimage Xi where audio chunks contains waste data in the end)
1806 //Maybe we should really not only check sc->sample_size, but also sc->sample_sizes
1807 //but I have no such movies
1808 if (sc->sample_size > 0) {
1810 for(i=0; i<(sc->sample_to_chunk_sz); i++) {
1811 if( (sc->sample_to_chunk[i].first)<=(sc->next_chunk) )
1813 foundsize=sc->sample_to_chunk[i].count*sc->sample_size;
1815 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);
1817 if( (foundsize>0) && (foundsize<size) )
1822 #endif //MOV_MINOLTA_FIX
1824 idx = sc->sample_to_chunk_index;
1825 if (idx + 1 < sc->sample_to_chunk_sz && sc->next_chunk >= sc->sample_to_chunk[idx + 1].first)
1827 sc->sample_to_chunk_index = idx;
1828 /* split chunks into samples */
1829 if (sc->sample_size == 0 || sc->sample_size > 100) {
1830 if (idx >= 0 && sc->sample_to_chunk[idx].count != 1) {
1832 /* we'll have to get those samples before next chunk */
1833 sc->left_in_chunk = sc->sample_to_chunk[idx].count - 1;
1834 size = (sc->sample_size > 1)?sc->sample_size:sc->sample_sizes[sc->current_sample];
1837 next_sample= sc->current_sample+1;
1838 }else if(idx < sc->sample_to_chunk_sz){
1839 next_sample= sc->current_sample + sc->sample_to_chunk[idx].count;
1841 next_sample= sc->current_sample;
1844 dprintf("chunk: %"PRId64" -> %"PRId64" (%i)\n", offset, offset + size, size);
1845 if(size == 0x0FFFFFFF)
1846 size = mov->mdat_size + mov->mdat_offset - offset;
1851 url_fseek(&s->pb, offset, SEEK_SET);
1853 av_get_packet(&s->pb, pkt, size);
1854 pkt->stream_index = sc->ffindex;
1856 // If the keyframes table exists, mark any samples that are in the table as key frames.
1857 // If no table exists, treat very sample as a key frame.
1858 if (sc->keyframes) {
1860 b = sc->keyframe_count - 1;
1863 m = (a + b + 1) >> 1;
1864 if (sc->keyframes[m] > sc->current_sample) {
1871 if (sc->keyframes[a] == sc->current_sample)
1872 pkt->flags |= PKT_FLAG_KEY;
1875 pkt->flags |= PKT_FLAG_KEY;
1877 mov->next_chunk_offset = offset + size;
1879 /* find the corresponding dts */
1880 if (sc && sc->sample_to_time_index < sc->stts_count && pkt) {
1883 unsigned int duration = sc->stts_data[sc->sample_to_time_index].duration;
1884 count = sc->stts_data[sc->sample_to_time_index].count;
1885 if ((sc->sample_to_time_sample + count) <= sc->current_sample) {
1886 sc->sample_to_time_sample += count;
1887 sc->sample_to_time_time += count*duration;
1888 sc->sample_to_time_index ++;
1889 duration = sc->stts_data[sc->sample_to_time_index].duration;
1891 dts = sc->sample_to_time_time + (sc->current_sample - sc->sample_to_time_sample) * (int64_t)duration;
1892 /* find the corresponding pts */
1893 if (sc->sample_to_ctime_index < sc->ctts_count) {
1894 int duration = sc->ctts_data[sc->sample_to_ctime_index].duration;
1895 int count = sc->ctts_data[sc->sample_to_ctime_index].count;
1897 if ((sc->sample_to_ctime_sample + count) <= sc->current_sample) {
1898 sc->sample_to_ctime_sample += count;
1899 sc->sample_to_ctime_index ++;
1900 duration = sc->ctts_data[sc->sample_to_ctime_index].duration;
1902 pts = dts + duration;
1906 st= s->streams[ sc->ffindex ];
1907 assert(pts % st->time_base.num == 0);
1908 assert(dts % st->time_base.num == 0);
1910 pkt->pts = pts / st->time_base.num;
1911 pkt->dts = dts / st->time_base.num;
1912 dprintf("stream #%d smp #%ld dts = %"PRId64" pts = %"PRId64" (smp:%ld time:%"PRId64" idx:%d ent:%d count:%d dur:%d)\n"
1913 , pkt->stream_index, sc->current_sample-1, pkt->dts, pkt->pts
1914 , sc->sample_to_time_sample
1915 , sc->sample_to_time_time
1916 , sc->sample_to_time_index
1922 assert(next_sample>=0);
1923 sc->current_sample= next_sample;
1928 #if defined(MOV_SEEK)
1930 * Seek method based on the one described in the Appendix C of QTFileFormat.pdf
1932 static int mov_read_seek(AVFormatContext *s, int stream_index, int64_t sample_time, int flags)
1934 MOVContext* mov = (MOVContext *) s->priv_data;
1935 MOVStreamContext* sc;
1938 int32_t seek_sample, sample;
1942 int32_t left_in_chunk;
1943 int64_t chunk_file_offset;
1944 int64_t sample_file_offset;
1945 int32_t first_chunk_sample;
1946 int32_t sample_to_chunk_idx;
1947 int sample_to_time_index;
1948 long sample_to_time_sample = 0;
1949 uint64_t sample_to_time_time = 0;
1952 // Find the corresponding mov stream
1953 for (mov_idx = 0; mov_idx < mov->total_streams; mov_idx++)
1954 if (mov->streams[mov_idx]->ffindex == stream_index)
1956 if (mov_idx == mov->total_streams) {
1957 av_log(s, AV_LOG_ERROR, "mov: requested stream was not found in mov streams (idx=%i)\n", stream_index);
1960 sc = mov->streams[mov_idx];
1962 sample_time *= s->streams[stream_index]->time_base.num;
1964 // Step 1. Find the edit that contains the requested time (elst)
1965 if (sc->edit_count && 0) {
1966 // FIXME should handle edit list
1967 av_log(s, AV_LOG_ERROR, "mov: does not handle seeking in files that contain edit list (c:%d)\n", sc->edit_count);
1971 // Step 2. Find the corresponding sample using the Time-to-sample atom (stts) */
1972 dprintf("Searching for time %li in stream #%i (time_scale=%i)\n", (long)sample_time, mov_idx, sc->time_scale);
1973 start_time = 0; // FIXME use elst atom
1974 sample = 1; // sample are 0 based in table
1976 for (i = 0; i < sc->stts_count; i++) {
1977 count = sc->stts_data[i].count;
1978 duration = sc->stts_data[i].duration;
1979 if ((start_time + count*duration) > sample_time) {
1980 sample_to_time_time = start_time;
1981 sample_to_time_index = i;
1982 sample_to_time_sample = sample;
1983 sample += (sample_time - start_time) / duration;
1987 start_time += count * duration;
1989 sample_to_time_time = start_time;
1990 sample_to_time_index = i;
1991 /* NOTE: despite what qt doc say, the dt value (Display Time in qt vocabulary) computed with the stts atom
1992 is a decoding time stamp (dts) not a presentation time stamp. And as usual dts != pts for stream with b frames */
1994 dprintf("Found time %li at sample #%u\n", (long)sample_time, sample);
1995 if (sample > sc->sample_count) {
1996 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);
2000 // Step 3. Find the prior sync. sample using the Sync sample atom (stss)
2001 if (sc->keyframes) {
2003 b = sc->keyframe_count - 1;
2005 m = (a + b + 1) >> 1;
2006 if (sc->keyframes[m] > sample) {
2012 // for low latency prob: always use the previous keyframe, just uncomment the next line
2014 seek_sample = sc->keyframes[a];
2017 seek_sample = sample; // else all samples are key frames
2018 dprintf("Found nearest keyframe at sample #%i \n", seek_sample);
2020 // Step 4. Find the chunk of the sample using the Sample-to-chunk-atom (stsc)
2021 for (first_chunk_sample = 1, i = 0; i < (sc->sample_to_chunk_sz - 1); i++) {
2022 b = (sc->sample_to_chunk[i + 1].first - sc->sample_to_chunk[i].first) * sc->sample_to_chunk[i].count;
2023 if (seek_sample >= first_chunk_sample && seek_sample < (first_chunk_sample + b))
2025 first_chunk_sample += b;
2027 chunk = sc->sample_to_chunk[i].first + (seek_sample - first_chunk_sample) / sc->sample_to_chunk[i].count;
2028 left_in_chunk = sc->sample_to_chunk[i].count - (seek_sample - first_chunk_sample) % sc->sample_to_chunk[i].count;
2029 first_chunk_sample += ((seek_sample - first_chunk_sample) / sc->sample_to_chunk[i].count) * sc->sample_to_chunk[i].count;
2030 sample_to_chunk_idx = i;
2031 dprintf("Sample was found in chunk #%i at sample offset %i (idx %i)\n", chunk, seek_sample - first_chunk_sample, sample_to_chunk_idx);
2033 // Step 5. Find the offset of the chunk using the chunk offset atom
2034 if (!sc->chunk_offsets) {
2035 av_log(s, AV_LOG_ERROR, "mov: no chunk offset atom, unable to seek\n");
2038 if (chunk > sc->chunk_count) {
2039 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);
2042 chunk_file_offset = sc->chunk_offsets[chunk - 1];
2043 dprintf("Chunk file offset is #%"PRIu64"\n", chunk_file_offset);
2045 // Step 6. Find the byte offset within the chunk using the sample size atom
2046 sample_file_offset = chunk_file_offset;
2047 if (sc->sample_size)
2048 sample_file_offset += (seek_sample - first_chunk_sample) * sc->sample_size;
2050 for (i = 0; i < (seek_sample - first_chunk_sample); i++) {
2051 sample_file_offset += sc->sample_sizes[first_chunk_sample + i - 1];
2054 dprintf("Sample file offset is #%"PRIu64"\n", sample_file_offset);
2056 // Step 6. Update the parser
2058 mov->next_chunk_offset = sample_file_offset;
2059 // Update current stream state
2060 sc->current_sample = seek_sample - 1; // zero based
2061 sc->left_in_chunk = left_in_chunk;
2062 sc->next_chunk = chunk; // +1 -1 (zero based)
2063 sc->sample_to_chunk_index = sample_to_chunk_idx;
2065 // Update other streams
2066 for (i = 0; i<mov->total_streams; i++) {
2067 MOVStreamContext *msc;
2068 if (i == mov_idx) continue;
2069 // Find the nearest 'next' chunk
2070 msc = mov->streams[i];
2072 b = msc->chunk_count - 1;
2074 m = (a + b + 1) >> 1;
2075 if (msc->chunk_offsets[m] > chunk_file_offset) {
2081 msc->next_chunk = a;
2082 if (msc->chunk_offsets[a] < chunk_file_offset && a < (msc->chunk_count-1))
2084 dprintf("Nearest next chunk for stream #%i is #%li @%"PRId64"\n", i, msc->next_chunk+1, msc->chunk_offsets[msc->next_chunk]);
2086 // Compute sample count and index in the sample_to_chunk table (what a pity)
2087 msc->sample_to_chunk_index = 0;
2088 msc->current_sample = 0;
2089 for(; msc->sample_to_chunk_index < (msc->sample_to_chunk_sz - 1)
2090 && msc->sample_to_chunk[msc->sample_to_chunk_index + 1].first <= (1 + msc->next_chunk); msc->sample_to_chunk_index++) {
2091 msc->current_sample += (msc->sample_to_chunk[msc->sample_to_chunk_index + 1].first - msc->sample_to_chunk[msc->sample_to_chunk_index].first) \
2092 * msc->sample_to_chunk[msc->sample_to_chunk_index].count;
2094 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;
2095 msc->left_in_chunk = msc->sample_to_chunk[msc->sample_to_chunk_index].count - 1;
2096 // Find corresponding position in stts (used later to compute dts)
2099 for (msc->sample_to_time_index = 0; msc->sample_to_time_index < msc->stts_count; msc->sample_to_time_index++) {
2100 count = msc->stts_data[msc->sample_to_time_index].count;
2101 duration = msc->stts_data[msc->sample_to_time_index].duration;
2102 if ((sample + count - 1) > msc->current_sample) {
2103 msc->sample_to_time_time = start_time;
2104 msc->sample_to_time_sample = sample;
2108 start_time += count * duration;
2111 for (msc->sample_to_ctime_index = 0; msc->sample_to_ctime_index < msc->ctts_count; msc->sample_to_ctime_index++) {
2112 count = msc->ctts_data[msc->sample_to_ctime_index].count;
2113 duration = msc->ctts_data[msc->sample_to_ctime_index].duration;
2114 if ((sample + count - 1) > msc->current_sample) {
2115 msc->sample_to_ctime_sample = sample;
2120 dprintf("Next Sample for stream #%i is #%li @%li\n", i, msc->current_sample + 1, msc->sample_to_chunk_index + 1);
2126 static int mov_read_close(AVFormatContext *s)
2129 MOVContext *mov = (MOVContext *) s->priv_data;
2130 for(i=0; i<mov->total_streams; i++)
2131 mov_free_stream_context(mov->streams[i]);
2132 /* free color tabs */
2133 for(i=0; i<mov->ctab_size; i++)
2134 av_freep(&mov->ctab[i]);
2135 av_freep(&mov->ctab);
2139 static AVInputFormat mov_iformat = {
2140 "mov,mp4,m4a,3gp,3g2,mj2",
2141 "QuickTime/MPEG4/Motion JPEG 2000 format",
2147 #if defined(MOV_SEEK)
2154 av_register_input_format(&mov_iformat);