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;
1081 case CODEC_ID_PCM_U8:
1082 if (st->codec->bits_per_sample == 16)
1083 st->codec->codec_id = CODEC_ID_PCM_S16BE;
1084 st->codec->bit_rate = st->codec->sample_rate * 8;
1086 case CODEC_ID_AMR_WB:
1087 st->codec->sample_rate = 16000; /* should really we ? */
1088 st->codec->channels=1; /* really needed */
1090 case CODEC_ID_AMR_NB:
1091 st->codec->sample_rate = 8000; /* should really we ? */
1092 st->codec->channels=1; /* really needed */
1098 //Read QT version 1 fields. In version 0 theese dont exist
1099 dprintf("version =%d mp4=%d\n",version,c->mp4);
1101 get_be32(pb); /* samples per packet */
1102 get_be32(pb); /* bytes per packet */
1103 get_be32(pb); /* bytes per frame */
1104 get_be32(pb); /* bytes per sample */
1105 } else if(version==2) {
1106 get_be32(pb); /* sizeof struct only */
1107 st->codec->sample_rate = av_int2dbl(get_be64(pb)); /* float 64 */
1108 st->codec->channels = get_be32(pb);
1109 get_be32(pb); /* always 0x7F000000 */
1110 get_be32(pb); /* bits per channel if sound is uncompressed */
1111 get_be32(pb); /* lcpm format specific flag */
1112 get_be32(pb); /* bytes per audio packet if constant */
1113 get_be32(pb); /* lpcm frames per audio packet if constant */
1116 /* other codec type, just skip (rtp, mp4s, tmcd ...) */
1117 url_fskip(pb, size - (url_ftell(pb) - start_pos));
1119 /* this will read extra atoms at the end (wave, alac, damr, avcC, SMI ...) */
1120 a.size = size - (url_ftell(pb) - start_pos);
1122 mov_read_default(c, pb, a);
1123 else if (a.size > 0)
1124 url_fskip(pb, a.size);
1127 if(st->codec->codec_type==CODEC_TYPE_AUDIO && st->codec->sample_rate==0 && sc->time_scale>1) {
1128 st->codec->sample_rate= sc->time_scale;
1134 static int mov_read_stsc(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
1136 AVStream *st = c->fc->streams[c->fc->nb_streams-1];
1137 MOVStreamContext *sc = (MOVStreamContext *)st->priv_data;
1138 unsigned int i, entries;
1140 get_byte(pb); /* version */
1141 get_byte(pb); get_byte(pb); get_byte(pb); /* flags */
1143 entries = get_be32(pb);
1145 if(entries >= UINT_MAX / sizeof(MOV_sample_to_chunk_tbl))
1149 av_log(NULL, AV_LOG_DEBUG, "track[%i].stsc.entries = %i\n", c->fc->nb_streams-1, entries);
1151 sc->sample_to_chunk_sz = entries;
1152 sc->sample_to_chunk = (MOV_sample_to_chunk_tbl*) av_malloc(entries * sizeof(MOV_sample_to_chunk_tbl));
1153 if (!sc->sample_to_chunk)
1155 for(i=0; i<entries; i++) {
1156 sc->sample_to_chunk[i].first = get_be32(pb);
1157 sc->sample_to_chunk[i].count = get_be32(pb);
1158 sc->sample_to_chunk[i].id = get_be32(pb);
1163 static int mov_read_stss(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
1165 AVStream *st = c->fc->streams[c->fc->nb_streams-1];
1166 MOVStreamContext *sc = (MOVStreamContext *)st->priv_data;
1167 unsigned int i, entries;
1169 get_byte(pb); /* version */
1170 get_byte(pb); get_byte(pb); get_byte(pb); /* flags */
1172 entries = get_be32(pb);
1174 if(entries >= UINT_MAX / sizeof(long))
1177 sc->keyframe_count = entries;
1179 av_log(NULL, AV_LOG_DEBUG, "keyframe_count = %ld\n", sc->keyframe_count);
1181 sc->keyframes = (long*) av_malloc(entries * sizeof(long));
1184 for(i=0; i<entries; i++) {
1185 sc->keyframes[i] = get_be32(pb);
1187 /* av_log(NULL, AV_LOG_DEBUG, "keyframes[]=%ld\n", sc->keyframes[i]); */
1193 static int mov_read_stsz(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
1195 AVStream *st = c->fc->streams[c->fc->nb_streams-1];
1196 MOVStreamContext *sc = (MOVStreamContext *)st->priv_data;
1197 unsigned int i, entries;
1199 get_byte(pb); /* version */
1200 get_byte(pb); get_byte(pb); get_byte(pb); /* flags */
1202 sc->sample_size = get_be32(pb);
1203 entries = get_be32(pb);
1204 if(entries >= UINT_MAX / sizeof(long))
1207 sc->sample_count = entries;
1209 av_log(NULL, AV_LOG_DEBUG, "sample_size = %ld sample_count = %ld\n", sc->sample_size, sc->sample_count);
1211 if(sc->sample_size) {
1212 /* override sample size for uncompressed sound */
1213 switch (st->codec->codec_id) {
1214 case CODEC_ID_PCM_S32BE:
1215 case CODEC_ID_PCM_S32LE:
1216 sc->sample_size = 4 * st->codec->channels;
1218 case CODEC_ID_PCM_S24BE:
1219 case CODEC_ID_PCM_S24LE:
1220 sc->sample_size = 3 * st->codec->channels;
1222 case CODEC_ID_PCM_S16BE:
1223 case CODEC_ID_PCM_S16LE:
1224 sc->sample_size = 2 * st->codec->channels;
1226 case CODEC_ID_PCM_MULAW:
1227 case CODEC_ID_PCM_ALAW:
1228 case CODEC_ID_PCM_S8:
1229 case CODEC_ID_PCM_U8:
1230 sc->sample_size = 1 * st->codec->channels;
1235 assert(sc->sample_size);
1236 return 0; /* there isn't any table following */
1238 sc->sample_sizes = (long*) av_malloc(entries * sizeof(long));
1239 if (!sc->sample_sizes)
1241 for(i=0; i<entries; i++) {
1242 sc->sample_sizes[i] = get_be32(pb);
1244 av_log(NULL, AV_LOG_DEBUG, "sample_sizes[]=%ld\n", sc->sample_sizes[i]);
1250 static int mov_read_stts(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
1252 AVStream *st = c->fc->streams[c->fc->nb_streams-1];
1253 MOVStreamContext *sc = (MOVStreamContext *)st->priv_data;
1254 unsigned int i, entries;
1256 int64_t total_sample_count=0;
1258 get_byte(pb); /* version */
1259 get_byte(pb); get_byte(pb); get_byte(pb); /* flags */
1260 entries = get_be32(pb);
1261 if(entries >= UINT_MAX / sizeof(Time2Sample))
1264 sc->stts_count = entries;
1265 sc->stts_data = av_malloc(entries * sizeof(Time2Sample));
1268 av_log(NULL, AV_LOG_DEBUG, "track[%i].stts.entries = %i\n", c->fc->nb_streams-1, entries);
1273 for(i=0; i<entries; i++) {
1274 int sample_duration;
1277 sample_count=get_be32(pb);
1278 sample_duration = get_be32(pb);
1279 sc->stts_data[i].count= sample_count;
1280 sc->stts_data[i].duration= sample_duration;
1282 sc->time_rate= ff_gcd(sc->time_rate, sample_duration);
1284 dprintf("sample_count=%d, sample_duration=%d\n",sample_count,sample_duration);
1286 duration+=(int64_t)sample_duration*sample_count;
1287 total_sample_count+=sample_count;
1290 st->nb_frames= total_sample_count;
1292 st->duration= duration;
1296 static int mov_read_ctts(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
1298 AVStream *st = c->fc->streams[c->fc->nb_streams-1];
1299 MOVStreamContext *sc = (MOVStreamContext *)st->priv_data;
1300 unsigned int i, entries;
1302 get_byte(pb); /* version */
1303 get_byte(pb); get_byte(pb); get_byte(pb); /* flags */
1304 entries = get_be32(pb);
1305 if(entries >= UINT_MAX / sizeof(Time2Sample))
1308 sc->ctts_count = entries;
1309 sc->ctts_data = av_malloc(entries * sizeof(Time2Sample));
1311 dprintf("track[%i].ctts.entries = %i\n", c->fc->nb_streams-1, entries);
1313 for(i=0; i<entries; i++) {
1314 int count =get_be32(pb);
1315 int duration =get_be32(pb);
1317 sc->ctts_data[i].count = count;
1318 sc->ctts_data[i].duration= duration;
1320 sc->time_rate= ff_gcd(sc->time_rate, duration);
1325 static int mov_read_trak(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
1328 MOVStreamContext *sc;
1330 st = av_new_stream(c->fc, c->fc->nb_streams);
1332 sc = (MOVStreamContext*) av_mallocz(sizeof(MOVStreamContext));
1338 sc->sample_to_chunk_index = -1;
1340 st->codec->codec_type = CODEC_TYPE_MOV_OTHER;
1341 st->start_time = 0; /* XXX: check */
1342 c->streams[c->fc->nb_streams-1] = sc;
1344 return mov_read_default(c, pb, atom);
1347 static int mov_read_tkhd(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
1349 AVStream *st = c->fc->streams[c->fc->nb_streams-1];
1350 int version = get_byte(pb);
1352 get_byte(pb); get_byte(pb);
1353 get_byte(pb); /* flags */
1355 MOV_TRACK_ENABLED 0x0001
1356 MOV_TRACK_IN_MOVIE 0x0002
1357 MOV_TRACK_IN_PREVIEW 0x0004
1358 MOV_TRACK_IN_POSTER 0x0008
1365 get_be32(pb); /* creation time */
1366 get_be32(pb); /* modification time */
1368 st->id = (int)get_be32(pb); /* track id (NOT 0 !)*/
1369 get_be32(pb); /* reserved */
1370 st->start_time = 0; /* check */
1371 (version == 1) ? get_be64(pb) : get_be32(pb); /* highlevel (considering edits) duration in movie timebase */
1372 get_be32(pb); /* reserved */
1373 get_be32(pb); /* reserved */
1375 get_be16(pb); /* layer */
1376 get_be16(pb); /* alternate group */
1377 get_be16(pb); /* volume */
1378 get_be16(pb); /* reserved */
1380 url_fskip(pb, 36); /* display matrix */
1382 /* those are fixed-point */
1383 /*st->codec->width =*/ get_be32(pb) >> 16; /* track width */
1384 /*st->codec->height =*/ get_be32(pb) >> 16; /* track height */
1389 /* this atom should be null (from specs), but some buggy files put the 'moov' atom inside it... */
1390 /* like the files created with Adobe Premiere 5.0, for samples see */
1391 /* http://graphics.tudelft.nl/~wouter/publications/soundtests/ */
1392 static int mov_read_wide(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
1397 return 0; /* continue */
1398 if (get_be32(pb) != 0) { /* 0 sized mdat atom... use the 'wide' atom size */
1399 url_fskip(pb, atom.size - 4);
1402 atom.type = get_le32(pb);
1405 if (atom.type != MKTAG('m', 'd', 'a', 't')) {
1406 url_fskip(pb, atom.size);
1409 err = mov_read_mdat(c, pb, atom);
1415 static int null_read_packet(void *opaque, uint8_t *buf, int buf_size)
1420 static int mov_read_cmov(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
1424 uint8_t *moov_data; /* uncompressed data */
1425 long cmov_len, moov_len;
1428 get_be32(pb); /* dcom atom */
1429 if (get_le32(pb) != MKTAG( 'd', 'c', 'o', 'm' ))
1431 if (get_le32(pb) != MKTAG( 'z', 'l', 'i', 'b' )) {
1432 av_log(NULL, AV_LOG_ERROR, "unknown compression for cmov atom !");
1435 get_be32(pb); /* cmvd atom */
1436 if (get_le32(pb) != MKTAG( 'c', 'm', 'v', 'd' ))
1438 moov_len = get_be32(pb); /* uncompressed size */
1439 cmov_len = atom.size - 6 * 4;
1441 cmov_data = (uint8_t *) av_malloc(cmov_len);
1444 moov_data = (uint8_t *) av_malloc(moov_len);
1449 get_buffer(pb, cmov_data, cmov_len);
1450 if(uncompress (moov_data, (uLongf *) &moov_len, (const Bytef *)cmov_data, cmov_len) != Z_OK)
1452 if(init_put_byte(&ctx, moov_data, moov_len, 0, NULL, null_read_packet, NULL, NULL) != 0)
1454 ctx.buf_end = ctx.buffer + moov_len;
1455 atom.type = MKTAG( 'm', 'o', 'o', 'v' );
1457 atom.size = moov_len;
1459 // { int fd = open("/tmp/uncompheader.mov", O_WRONLY | O_CREAT); write(fd, moov_data, moov_len); close(fd); }
1461 ret = mov_read_default(c, &ctx, atom);
1469 /* edit list atom */
1470 static int mov_read_elst(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
1474 get_byte(pb); /* version */
1475 get_byte(pb); get_byte(pb); get_byte(pb); /* flags */
1476 edit_count= c->streams[c->fc->nb_streams-1]->edit_count = get_be32(pb); /* entries */
1478 for(i=0; i<edit_count; i++){
1479 get_be32(pb); /* Track duration */
1480 get_be32(pb); /* Media time */
1481 get_be32(pb); /* Media rate */
1483 dprintf("track[%i].edit_count = %i\n", c->fc->nb_streams-1, c->streams[c->fc->nb_streams-1]->edit_count);
1487 static const MOVParseTableEntry mov_default_parse_table[] = {
1489 { MKTAG( 'c', 'o', '6', '4' ), mov_read_stco },
1490 { MKTAG( 'c', 'p', 'r', 't' ), mov_read_default },
1491 { MKTAG( 'c', 'r', 'h', 'd' ), mov_read_default },
1492 { MKTAG( 'c', 't', 't', 's' ), mov_read_ctts }, /* composition time to sample */
1493 { MKTAG( 'd', 'i', 'n', 'f' ), mov_read_default }, /* data information */
1494 { MKTAG( 'd', 'p', 'n', 'd' ), mov_read_leaf },
1495 { MKTAG( 'd', 'r', 'e', 'f' ), mov_read_leaf },
1496 { MKTAG( 'e', 'd', 't', 's' ), mov_read_default },
1497 { MKTAG( 'e', 'l', 's', 't' ), mov_read_elst },
1498 { MKTAG( 'e', 'n', 'd', 'a' ), mov_read_enda },
1499 { MKTAG( 'f', 'r', 'e', 'e' ), mov_read_leaf },
1500 { MKTAG( 'f', 't', 'y', 'p' ), mov_read_ftyp },
1501 { MKTAG( 'h', 'd', 'l', 'r' ), mov_read_hdlr },
1502 { MKTAG( 'h', 'i', 'n', 't' ), mov_read_leaf },
1503 { MKTAG( 'h', 'm', 'h', 'd' ), mov_read_leaf },
1504 { MKTAG( 'i', 'o', 'd', 's' ), mov_read_leaf },
1505 { MKTAG( 'j', 'p', '2', 'h' ), mov_read_jp2h },
1506 { MKTAG( 'm', 'd', 'a', 't' ), mov_read_mdat },
1507 { MKTAG( 'm', 'd', 'h', 'd' ), mov_read_mdhd },
1508 { MKTAG( 'm', 'd', 'i', 'a' ), mov_read_default },
1509 { MKTAG( 'm', 'i', 'n', 'f' ), mov_read_default },
1510 { MKTAG( 'm', 'o', 'o', 'v' ), mov_read_moov },
1511 { MKTAG( 'm', 'p', '4', 'a' ), mov_read_default },
1512 { MKTAG( 'm', 'p', '4', 's' ), mov_read_default },
1513 { MKTAG( 'm', 'p', '4', 'v' ), mov_read_default },
1514 { MKTAG( 'm', 'p', 'o', 'd' ), mov_read_leaf },
1515 { MKTAG( 'm', 'v', 'h', 'd' ), mov_read_mvhd },
1516 { MKTAG( 'n', 'm', 'h', 'd' ), mov_read_leaf },
1517 { MKTAG( 'o', 'd', 'h', 'd' ), mov_read_default },
1518 { MKTAG( 's', 'd', 'h', 'd' ), mov_read_default },
1519 { MKTAG( 's', 'k', 'i', 'p' ), mov_read_leaf },
1520 { MKTAG( 's', 'm', 'h', 'd' ), mov_read_leaf }, /* sound media info header */
1521 { MKTAG( 'S', 'M', 'I', ' ' ), mov_read_smi }, /* Sorenson extension ??? */
1522 { MKTAG( 'a', 'l', 'a', 'c' ), mov_read_alac }, /* alac specific atom */
1523 { MKTAG( 'a', 'v', 'c', 'C' ), mov_read_avcC },
1524 { MKTAG( 's', 't', 'b', 'l' ), mov_read_default },
1525 { MKTAG( 's', 't', 'c', 'o' ), mov_read_stco },
1526 { MKTAG( 's', 't', 'd', 'p' ), mov_read_default },
1527 { MKTAG( 's', 't', 's', 'c' ), mov_read_stsc },
1528 { MKTAG( 's', 't', 's', 'd' ), mov_read_stsd }, /* sample description */
1529 { MKTAG( 's', 't', 's', 'h' ), mov_read_default },
1530 { MKTAG( 's', 't', 's', 's' ), mov_read_stss }, /* sync sample */
1531 { MKTAG( 's', 't', 's', 'z' ), mov_read_stsz }, /* sample size */
1532 { MKTAG( 's', 't', 't', 's' ), mov_read_stts },
1533 { MKTAG( 't', 'k', 'h', 'd' ), mov_read_tkhd }, /* track header */
1534 { MKTAG( 't', 'r', 'a', 'k' ), mov_read_trak },
1535 { MKTAG( 't', 'r', 'e', 'f' ), mov_read_default }, /* not really */
1536 { MKTAG( 'u', 'd', 't', 'a' ), mov_read_leaf },
1537 { MKTAG( 'u', 'r', 'l', ' ' ), mov_read_leaf },
1538 { MKTAG( 'u', 'r', 'n', ' ' ), mov_read_leaf },
1539 { MKTAG( 'u', 'u', 'i', 'd' ), mov_read_leaf },
1540 { MKTAG( 'v', 'm', 'h', 'd' ), mov_read_leaf }, /* video media info header */
1541 { MKTAG( 'w', 'a', 'v', 'e' ), mov_read_wave },
1543 { MKTAG( 'M', 'D', 'E', 'S' ), mov_read_leaf },
1545 { MKTAG( 'c', 'h', 'a', 'p' ), mov_read_leaf },
1546 { MKTAG( 'c', 'l', 'i', 'p' ), mov_read_default },
1547 { MKTAG( 'c', 'r', 'g', 'n' ), mov_read_leaf },
1548 { MKTAG( 'c', 't', 'a', 'b' ), mov_read_ctab },
1549 { MKTAG( 'e', 's', 'd', 's' ), mov_read_esds },
1550 { MKTAG( 'k', 'm', 'a', 't' ), mov_read_leaf },
1551 { MKTAG( 'm', 'a', 't', 't' ), mov_read_default },
1552 { MKTAG( 'r', 'd', 'r', 'f' ), mov_read_leaf },
1553 { MKTAG( 'r', 'm', 'd', 'a' ), mov_read_default },
1554 { MKTAG( 'r', 'm', 'd', 'r' ), mov_read_leaf },
1555 { MKTAG( 'r', 'm', 'r', 'a' ), mov_read_default },
1556 { MKTAG( 's', 'c', 'p', 't' ), mov_read_leaf },
1557 { MKTAG( 's', 's', 'r', 'c' ), mov_read_leaf },
1558 { MKTAG( 's', 'y', 'n', 'c' ), mov_read_leaf },
1559 { MKTAG( 't', 'c', 'm', 'd' ), mov_read_leaf },
1560 { MKTAG( 'w', 'i', 'd', 'e' ), mov_read_wide }, /* place holder */
1561 //{ MKTAG( 'r', 'm', 'q', 'u' ), mov_read_leaf },
1563 { MKTAG( 'c', 'm', 'o', 'v' ), mov_read_cmov },
1565 { MKTAG( 'c', 'm', 'o', 'v' ), mov_read_leaf },
1567 { 0L, mov_read_leaf }
1570 static void mov_free_stream_context(MOVStreamContext *sc)
1573 av_freep(&sc->chunk_offsets);
1574 av_freep(&sc->sample_to_chunk);
1575 av_freep(&sc->sample_sizes);
1576 av_freep(&sc->keyframes);
1577 av_freep(&sc->stts_data);
1578 av_freep(&sc->ctts_data);
1583 static inline uint32_t mov_to_tag(uint8_t *buf)
1585 return MKTAG(buf[0], buf[1], buf[2], buf[3]);
1588 static inline uint32_t to_be32(uint8_t *buf)
1590 return (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3];
1593 /* XXX: is it sufficient ? */
1594 static int mov_probe(AVProbeData *p)
1596 unsigned int offset;
1600 /* check file header */
1601 if (p->buf_size <= 12)
1605 /* ignore invalid offset */
1606 if ((offset + 8) > (unsigned int)p->buf_size)
1608 tag = mov_to_tag(p->buf + offset + 4);
1610 /* check for obvious tags */
1611 case MKTAG( 'j', 'P', ' ', ' ' ): /* jpeg 2000 signature */
1612 case MKTAG( 'm', 'o', 'o', 'v' ):
1613 case MKTAG( 'm', 'd', 'a', 't' ):
1614 case MKTAG( 'p', 'n', 'o', 't' ): /* detect movs with preview pics like ew.mov and april.mov */
1615 case MKTAG( 'u', 'd', 't', 'a' ): /* Packet Video PVAuthor adds this and a lot of more junk */
1616 return AVPROBE_SCORE_MAX;
1617 /* those are more common words, so rate then a bit less */
1618 case MKTAG( 'w', 'i', 'd', 'e' ):
1619 case MKTAG( 'f', 'r', 'e', 'e' ):
1620 case MKTAG( 'j', 'u', 'n', 'k' ):
1621 case MKTAG( 'p', 'i', 'c', 't' ):
1622 return AVPROBE_SCORE_MAX - 5;
1623 case MKTAG( 'f', 't', 'y', 'p' ):
1624 case MKTAG( 's', 'k', 'i', 'p' ):
1625 case MKTAG( 'u', 'u', 'i', 'd' ):
1626 offset = to_be32(p->buf+offset) + offset;
1627 /* if we only find those cause probedata is too small at least rate them */
1628 score = AVPROBE_SCORE_MAX - 50;
1631 /* unrecognized tag */
1638 static int mov_read_header(AVFormatContext *s, AVFormatParameters *ap)
1640 MOVContext *mov = (MOVContext *) s->priv_data;
1641 ByteIOContext *pb = &s->pb;
1643 MOV_atom_t atom = { 0, 0, 0 };
1646 mov->parse_table = mov_default_parse_table;
1648 if(!url_is_streamed(pb)) /* .mov and .mp4 aren't streamable anyway (only progressive download if moov is before mdat) */
1649 atom.size = url_fsize(pb);
1651 atom.size = 0x7FFFFFFFFFFFFFFFLL;
1653 /* check MOV header */
1654 err = mov_read_default(mov, pb, atom);
1655 if (err<0 || (!mov->found_moov && !mov->found_mdat)) {
1656 av_log(s, AV_LOG_ERROR, "mov: header not found !!! (err:%d, moov:%d, mdat:%d) pos:%"PRId64"\n",
1657 err, mov->found_moov, mov->found_mdat, url_ftell(pb));
1660 dprintf("on_parse_exit_offset=%d\n", (int) url_ftell(pb));
1662 /* some cleanup : make sure we are on the mdat atom */
1663 if(!url_is_streamed(pb) && (url_ftell(pb) != mov->mdat_offset))
1664 url_fseek(pb, mov->mdat_offset, SEEK_SET);
1666 mov->next_chunk_offset = mov->mdat_offset; /* initialise reading */
1667 mov->total_streams = nb = s->nb_streams;
1670 for(i=0; i<s->nb_streams;) {
1671 if(s->streams[i]->codec->codec_type == CODEC_TYPE_MOV_OTHER) {/* not audio, not video, delete */
1672 av_free(s->streams[i]);
1673 for(j=i+1; j<s->nb_streams; j++)
1674 s->streams[j-1] = s->streams[j];
1679 for(i=0; i<s->nb_streams;i++) {
1680 MOVStreamContext *sc = (MOVStreamContext *)s->streams[i]->priv_data;
1685 sc->time_scale= mov->time_scale;
1686 av_set_pts_info(s->streams[i], 64, sc->time_rate, sc->time_scale);
1688 if(s->streams[i]->duration != AV_NOPTS_VALUE){
1689 assert(s->streams[i]->duration % sc->time_rate == 0);
1690 s->streams[i]->duration /= sc->time_rate;
1694 sc->is_ff_stream = 1;
1700 /* Yes, this is ugly... I didn't write the specs of QT :p */
1701 /* XXX:remove useless commented code sometime */
1702 static int mov_read_packet(AVFormatContext *s, AVPacket *pkt)
1704 MOVContext *mov = (MOVContext *) s->priv_data;
1705 MOVStreamContext *sc;
1707 int64_t offset = INT64_MAX;
1708 int64_t best_dts = INT64_MAX;
1710 int next_sample= -99;
1717 idx = sc->sample_to_chunk_index;
1719 if (idx < 0) return 0;
1720 dprintf("sc[ffid %d]->sample_size = %ld\n", sc->ffindex, sc->sample_size);
1721 //size = sc->sample_sizes[sc->current_sample];
1722 // that ain't working...
1723 //size = (sc->sample_size)?sc->sample_size:sc->sample_sizes[sc->current_sample];
1724 size = (sc->sample_size > 1)?sc->sample_size:sc->sample_sizes[sc->current_sample];
1726 next_sample= sc->current_sample+1;
1728 sc->left_in_chunk--;
1730 if (sc->left_in_chunk <= 0)
1732 offset = mov->next_chunk_offset;
1733 /* extract the sample */
1740 if(offset == INT64_MAX)
1741 best_dts= INT64_MAX;
1742 for(i=0; i<mov->total_streams; i++) {
1743 MOVStreamContext *msc = mov->streams[i];
1745 if ((msc->next_chunk < msc->chunk_count) && msc->next_chunk >= 0){
1746 if (msc->sample_to_time_index < msc->stts_count && mov->ni) {
1748 int index= msc->sample_to_time_index;
1749 int sample= msc->sample_to_time_sample;
1750 int time= msc->sample_to_time_time;
1751 int duration = msc->stts_data[index].duration;
1752 int count = msc->stts_data[index].count;
1753 if (sample + count <= msc->current_sample) {
1755 time += count*duration;
1757 duration = msc->stts_data[index].duration;
1759 dts = time + (msc->current_sample - sample) * (int64_t)duration;
1760 dts = av_rescale(dts, AV_TIME_BASE, msc->time_scale);
1761 dprintf("stream: %d dts: %"PRId64" best_dts: %"PRId64" offset: %"PRId64"\n", i, dts, best_dts, offset);
1765 offset = msc->chunk_offsets[msc->next_chunk];
1768 if ((msc->chunk_offsets[msc->next_chunk] < offset)) {
1770 offset = msc->chunk_offsets[msc->next_chunk];
1775 if (!sc || offset==INT64_MAX)
1780 if(mov->next_chunk_offset < offset) { /* some meta data */
1781 url_fskip(&s->pb, (offset - mov->next_chunk_offset));
1782 mov->next_chunk_offset = offset;
1785 if(!sc->is_ff_stream || (s->streams[sc->ffindex]->discard >= AVDISCARD_ALL)) {
1786 url_fskip(&s->pb, (offset - mov->next_chunk_offset));
1787 mov->next_chunk_offset = offset;
1792 /* now get the chunk size... */
1794 for(i=0; i<mov->total_streams; i++) {
1795 MOVStreamContext *msc = mov->streams[i];
1796 if ((msc->next_chunk < msc->chunk_count)
1797 && msc->chunk_offsets[msc->next_chunk] - offset < size
1798 && msc->chunk_offsets[msc->next_chunk] > offset)
1799 size = msc->chunk_offsets[msc->next_chunk] - offset;
1802 #ifdef MOV_MINOLTA_FIX
1803 //Make sure that size is according to sample_size (Needed by .mov files
1804 //created on a Minolta Dimage Xi where audio chunks contains waste data in the end)
1805 //Maybe we should really not only check sc->sample_size, but also sc->sample_sizes
1806 //but I have no such movies
1807 if (sc->sample_size > 0) {
1809 for(i=0; i<(sc->sample_to_chunk_sz); i++) {
1810 if( (sc->sample_to_chunk[i].first)<=(sc->next_chunk) )
1812 foundsize=sc->sample_to_chunk[i].count*sc->sample_size;
1814 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);
1816 if( (foundsize>0) && (foundsize<size) )
1821 #endif //MOV_MINOLTA_FIX
1823 idx = sc->sample_to_chunk_index;
1824 if (idx + 1 < sc->sample_to_chunk_sz && sc->next_chunk >= sc->sample_to_chunk[idx + 1].first)
1826 sc->sample_to_chunk_index = idx;
1827 /* split chunks into samples */
1828 if (sc->sample_size == 0 || sc->sample_size > 100) {
1829 if (idx >= 0 && sc->sample_to_chunk[idx].count != 1) {
1831 /* we'll have to get those samples before next chunk */
1832 sc->left_in_chunk = sc->sample_to_chunk[idx].count - 1;
1833 size = (sc->sample_size > 1)?sc->sample_size:sc->sample_sizes[sc->current_sample];
1836 next_sample= sc->current_sample+1;
1837 }else if(idx < sc->sample_to_chunk_sz){
1838 next_sample= sc->current_sample + sc->sample_to_chunk[idx].count;
1840 next_sample= sc->current_sample;
1843 dprintf("chunk: %"PRId64" -> %"PRId64" (%i)\n", offset, offset + size, size);
1844 if(size == 0x0FFFFFFF)
1845 size = mov->mdat_size + mov->mdat_offset - offset;
1850 url_fseek(&s->pb, offset, SEEK_SET);
1852 av_get_packet(&s->pb, pkt, size);
1853 pkt->stream_index = sc->ffindex;
1855 // If the keyframes table exists, mark any samples that are in the table as key frames.
1856 // If no table exists, treat very sample as a key frame.
1857 if (sc->keyframes) {
1859 b = sc->keyframe_count - 1;
1862 m = (a + b + 1) >> 1;
1863 if (sc->keyframes[m] > sc->current_sample) {
1870 if (sc->keyframes[a] == sc->current_sample)
1871 pkt->flags |= PKT_FLAG_KEY;
1874 pkt->flags |= PKT_FLAG_KEY;
1876 mov->next_chunk_offset = offset + size;
1878 /* find the corresponding dts */
1879 if (sc && sc->sample_to_time_index < sc->stts_count && pkt) {
1882 unsigned int duration = sc->stts_data[sc->sample_to_time_index].duration;
1883 count = sc->stts_data[sc->sample_to_time_index].count;
1884 if ((sc->sample_to_time_sample + count) <= sc->current_sample) {
1885 sc->sample_to_time_sample += count;
1886 sc->sample_to_time_time += count*duration;
1887 sc->sample_to_time_index ++;
1888 duration = sc->stts_data[sc->sample_to_time_index].duration;
1890 dts = sc->sample_to_time_time + (sc->current_sample - sc->sample_to_time_sample) * (int64_t)duration;
1891 /* find the corresponding pts */
1892 if (sc->sample_to_ctime_index < sc->ctts_count) {
1893 int duration = sc->ctts_data[sc->sample_to_ctime_index].duration;
1894 int count = sc->ctts_data[sc->sample_to_ctime_index].count;
1896 if ((sc->sample_to_ctime_sample + count) <= sc->current_sample) {
1897 sc->sample_to_ctime_sample += count;
1898 sc->sample_to_ctime_index ++;
1899 duration = sc->ctts_data[sc->sample_to_ctime_index].duration;
1901 pts = dts + duration;
1905 st= s->streams[ sc->ffindex ];
1906 assert(pts % st->time_base.num == 0);
1907 assert(dts % st->time_base.num == 0);
1909 pkt->pts = pts / st->time_base.num;
1910 pkt->dts = dts / st->time_base.num;
1911 dprintf("stream #%d smp #%ld dts = %"PRId64" pts = %"PRId64" (smp:%ld time:%"PRId64" idx:%d ent:%d count:%d dur:%d)\n"
1912 , pkt->stream_index, sc->current_sample-1, pkt->dts, pkt->pts
1913 , sc->sample_to_time_sample
1914 , sc->sample_to_time_time
1915 , sc->sample_to_time_index
1921 assert(next_sample>=0);
1922 sc->current_sample= next_sample;
1927 #if defined(MOV_SEEK)
1929 * Seek method based on the one described in the Appendix C of QTFileFormat.pdf
1931 static int mov_read_seek(AVFormatContext *s, int stream_index, int64_t sample_time, int flags)
1933 MOVContext* mov = (MOVContext *) s->priv_data;
1934 MOVStreamContext* sc;
1937 int32_t seek_sample, sample;
1941 int32_t left_in_chunk;
1942 int64_t chunk_file_offset;
1943 int64_t sample_file_offset;
1944 int32_t first_chunk_sample;
1945 int32_t sample_to_chunk_idx;
1946 int sample_to_time_index;
1947 long sample_to_time_sample = 0;
1948 uint64_t sample_to_time_time = 0;
1951 // Find the corresponding mov stream
1952 for (mov_idx = 0; mov_idx < mov->total_streams; mov_idx++)
1953 if (mov->streams[mov_idx]->ffindex == stream_index)
1955 if (mov_idx == mov->total_streams) {
1956 av_log(s, AV_LOG_ERROR, "mov: requested stream was not found in mov streams (idx=%i)\n", stream_index);
1959 sc = mov->streams[mov_idx];
1961 sample_time *= s->streams[stream_index]->time_base.num;
1963 // Step 1. Find the edit that contains the requested time (elst)
1964 if (sc->edit_count && 0) {
1965 // FIXME should handle edit list
1966 av_log(s, AV_LOG_ERROR, "mov: does not handle seeking in files that contain edit list (c:%d)\n", sc->edit_count);
1970 // Step 2. Find the corresponding sample using the Time-to-sample atom (stts) */
1971 dprintf("Searching for time %li in stream #%i (time_scale=%i)\n", (long)sample_time, mov_idx, sc->time_scale);
1972 start_time = 0; // FIXME use elst atom
1973 sample = 1; // sample are 0 based in table
1975 for (i = 0; i < sc->stts_count; i++) {
1976 count = sc->stts_data[i].count;
1977 duration = sc->stts_data[i].duration;
1978 if ((start_time + count*duration) > sample_time) {
1979 sample_to_time_time = start_time;
1980 sample_to_time_index = i;
1981 sample_to_time_sample = sample;
1982 sample += (sample_time - start_time) / duration;
1986 start_time += count * duration;
1988 sample_to_time_time = start_time;
1989 sample_to_time_index = i;
1990 /* NOTE: despite what qt doc say, the dt value (Display Time in qt vocabulary) computed with the stts atom
1991 is a decoding time stamp (dts) not a presentation time stamp. And as usual dts != pts for stream with b frames */
1993 dprintf("Found time %li at sample #%u\n", (long)sample_time, sample);
1994 if (sample > sc->sample_count) {
1995 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);
1999 // Step 3. Find the prior sync. sample using the Sync sample atom (stss)
2000 if (sc->keyframes) {
2002 b = sc->keyframe_count - 1;
2004 m = (a + b + 1) >> 1;
2005 if (sc->keyframes[m] > sample) {
2011 // for low latency prob: always use the previous keyframe, just uncomment the next line
2013 seek_sample = sc->keyframes[a];
2016 seek_sample = sample; // else all samples are key frames
2017 dprintf("Found nearest keyframe at sample #%i \n", seek_sample);
2019 // Step 4. Find the chunk of the sample using the Sample-to-chunk-atom (stsc)
2020 for (first_chunk_sample = 1, i = 0; i < (sc->sample_to_chunk_sz - 1); i++) {
2021 b = (sc->sample_to_chunk[i + 1].first - sc->sample_to_chunk[i].first) * sc->sample_to_chunk[i].count;
2022 if (seek_sample >= first_chunk_sample && seek_sample < (first_chunk_sample + b))
2024 first_chunk_sample += b;
2026 chunk = sc->sample_to_chunk[i].first + (seek_sample - first_chunk_sample) / sc->sample_to_chunk[i].count;
2027 left_in_chunk = sc->sample_to_chunk[i].count - (seek_sample - first_chunk_sample) % sc->sample_to_chunk[i].count;
2028 first_chunk_sample += ((seek_sample - first_chunk_sample) / sc->sample_to_chunk[i].count) * sc->sample_to_chunk[i].count;
2029 sample_to_chunk_idx = i;
2030 dprintf("Sample was found in chunk #%i at sample offset %i (idx %i)\n", chunk, seek_sample - first_chunk_sample, sample_to_chunk_idx);
2032 // Step 5. Find the offset of the chunk using the chunk offset atom
2033 if (!sc->chunk_offsets) {
2034 av_log(s, AV_LOG_ERROR, "mov: no chunk offset atom, unable to seek\n");
2037 if (chunk > sc->chunk_count) {
2038 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);
2041 chunk_file_offset = sc->chunk_offsets[chunk - 1];
2042 dprintf("Chunk file offset is #%"PRIu64"\n", chunk_file_offset);
2044 // Step 6. Find the byte offset within the chunk using the sample size atom
2045 sample_file_offset = chunk_file_offset;
2046 if (sc->sample_size)
2047 sample_file_offset += (seek_sample - first_chunk_sample) * sc->sample_size;
2049 for (i = 0; i < (seek_sample - first_chunk_sample); i++) {
2050 sample_file_offset += sc->sample_sizes[first_chunk_sample + i - 1];
2053 dprintf("Sample file offset is #%"PRIu64"\n", sample_file_offset);
2055 // Step 6. Update the parser
2057 mov->next_chunk_offset = sample_file_offset;
2058 // Update current stream state
2059 sc->current_sample = seek_sample - 1; // zero based
2060 sc->left_in_chunk = left_in_chunk;
2061 sc->next_chunk = chunk; // +1 -1 (zero based)
2062 sc->sample_to_chunk_index = sample_to_chunk_idx;
2064 // Update other streams
2065 for (i = 0; i<mov->total_streams; i++) {
2066 MOVStreamContext *msc;
2067 if (i == mov_idx) continue;
2068 // Find the nearest 'next' chunk
2069 msc = mov->streams[i];
2071 b = msc->chunk_count - 1;
2073 m = (a + b + 1) >> 1;
2074 if (msc->chunk_offsets[m] > chunk_file_offset) {
2080 msc->next_chunk = a;
2081 if (msc->chunk_offsets[a] < chunk_file_offset && a < (msc->chunk_count-1))
2083 dprintf("Nearest next chunk for stream #%i is #%li @%"PRId64"\n", i, msc->next_chunk+1, msc->chunk_offsets[msc->next_chunk]);
2085 // Compute sample count and index in the sample_to_chunk table (what a pity)
2086 msc->sample_to_chunk_index = 0;
2087 msc->current_sample = 0;
2088 for(; msc->sample_to_chunk_index < (msc->sample_to_chunk_sz - 1)
2089 && msc->sample_to_chunk[msc->sample_to_chunk_index + 1].first <= (1 + msc->next_chunk); msc->sample_to_chunk_index++) {
2090 msc->current_sample += (msc->sample_to_chunk[msc->sample_to_chunk_index + 1].first - msc->sample_to_chunk[msc->sample_to_chunk_index].first) \
2091 * msc->sample_to_chunk[msc->sample_to_chunk_index].count;
2093 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;
2094 msc->left_in_chunk = msc->sample_to_chunk[msc->sample_to_chunk_index].count - 1;
2095 // Find corresponding position in stts (used later to compute dts)
2098 for (msc->sample_to_time_index = 0; msc->sample_to_time_index < msc->stts_count; msc->sample_to_time_index++) {
2099 count = msc->stts_data[msc->sample_to_time_index].count;
2100 duration = msc->stts_data[msc->sample_to_time_index].duration;
2101 if ((sample + count - 1) > msc->current_sample) {
2102 msc->sample_to_time_time = start_time;
2103 msc->sample_to_time_sample = sample;
2107 start_time += count * duration;
2110 for (msc->sample_to_ctime_index = 0; msc->sample_to_ctime_index < msc->ctts_count; msc->sample_to_ctime_index++) {
2111 count = msc->ctts_data[msc->sample_to_ctime_index].count;
2112 duration = msc->ctts_data[msc->sample_to_ctime_index].duration;
2113 if ((sample + count - 1) > msc->current_sample) {
2114 msc->sample_to_ctime_sample = sample;
2119 dprintf("Next Sample for stream #%i is #%li @%li\n", i, msc->current_sample + 1, msc->sample_to_chunk_index + 1);
2125 static int mov_read_close(AVFormatContext *s)
2128 MOVContext *mov = (MOVContext *) s->priv_data;
2129 for(i=0; i<mov->total_streams; i++)
2130 mov_free_stream_context(mov->streams[i]);
2131 /* free color tabs */
2132 for(i=0; i<mov->ctab_size; i++)
2133 av_freep(&mov->ctab[i]);
2134 av_freep(&mov->ctab);
2138 static AVInputFormat mov_iformat = {
2139 "mov,mp4,m4a,3gp,3g2,mj2",
2140 "QuickTime/MPEG4/Motion JPEG 2000 format",
2146 #if defined(MOV_SEEK)
2153 av_register_input_format(&mov_iformat);