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 , 225 },
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 int 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: %Lx %Lx %Lx\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)
674 version = get_byte(pb); /* version */
676 return 1; /* unsupported */
678 get_byte(pb); get_byte(pb);
679 get_byte(pb); /* flags */
681 (version==1)?get_be64(pb):get_be32(pb); /* creation time */
682 (version==1)?get_be64(pb):get_be32(pb); /* modification time */
684 c->streams[c->fc->nb_streams-1]->time_scale = get_be32(pb);
685 c->fc->streams[c->fc->nb_streams-1]->duration = (version==1)?get_be64(pb):get_be32(pb); /* duration */
687 lang = get_be16(pb); /* language */
688 ff_mov_lang_to_iso639(lang, c->fc->streams[c->fc->nb_streams-1]->language);
689 get_be16(pb); /* quality */
694 static int mov_read_mvhd(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
696 get_byte(pb); /* version */
697 get_byte(pb); get_byte(pb); get_byte(pb); /* flags */
699 get_be32(pb); /* creation time */
700 get_be32(pb); /* modification time */
701 c->time_scale = get_be32(pb); /* time scale */
703 av_log(NULL, AV_LOG_DEBUG, "time scale = %i\n", c->time_scale);
705 c->duration = get_be32(pb); /* duration */
706 get_be32(pb); /* preferred scale */
708 get_be16(pb); /* preferred volume */
710 url_fskip(pb, 10); /* reserved */
712 url_fskip(pb, 36); /* display matrix */
714 get_be32(pb); /* preview time */
715 get_be32(pb); /* preview duration */
716 get_be32(pb); /* poster time */
717 get_be32(pb); /* selection time */
718 get_be32(pb); /* selection duration */
719 get_be32(pb); /* current time */
720 get_be32(pb); /* next track ID */
725 static int mov_read_smi(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
727 AVStream *st = c->fc->streams[c->fc->nb_streams-1];
729 if((uint64_t)atom.size > (1<<30))
732 // currently SVQ3 decoder expect full STSD header - so let's fake it
733 // this should be fixed and just SMI header should be passed
734 av_free(st->codec->extradata);
735 st->codec->extradata_size = 0x5a + atom.size;
736 st->codec->extradata = (uint8_t*) av_mallocz(st->codec->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE);
738 if (st->codec->extradata) {
739 strcpy(st->codec->extradata, "SVQ3"); // fake
740 get_buffer(pb, st->codec->extradata + 0x5a, atom.size);
741 dprintf("Reading SMI %Ld %s\n", atom.size, (char*)st->codec->extradata + 0x5a);
743 url_fskip(pb, atom.size);
748 static int mov_read_enda(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
750 AVStream *st = c->fc->streams[c->fc->nb_streams-1];
751 int little_endian = get_be16(pb);
754 switch (st->codec->codec_id) {
755 case CODEC_ID_PCM_S24BE:
756 st->codec->codec_id = CODEC_ID_PCM_S24LE;
758 case CODEC_ID_PCM_S32BE:
759 st->codec->codec_id = CODEC_ID_PCM_S32LE;
768 static int mov_read_alac(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
770 AVStream *st = c->fc->streams[c->fc->nb_streams-1];
772 // currently ALAC decoder expect full atom header - so let's fake it
773 // this should be fixed and just ALAC header should be passed
775 av_free(st->codec->extradata);
776 st->codec->extradata_size = 36;
777 st->codec->extradata = (uint8_t*) av_mallocz(st->codec->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE);
779 if (st->codec->extradata) {
780 strcpy(st->codec->extradata + 4, "alac"); // fake
781 get_buffer(pb, st->codec->extradata + 8, 36 - 8);
782 dprintf("Reading alac %Ld %s\n", st->codec->extradata_size, (char*)st->codec->extradata);
784 url_fskip(pb, atom.size);
788 static int mov_read_wave(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
790 offset_t start_pos = url_ftell(pb);
791 AVStream *st = c->fc->streams[c->fc->nb_streams-1];
793 if((uint64_t)atom.size > (1<<30))
796 if (st->codec->codec_id == CODEC_ID_QDM2) {
797 // pass all frma atom to codec, needed at least for QDM2
798 av_free(st->codec->extradata);
799 st->codec->extradata_size = atom.size;
800 st->codec->extradata = (uint8_t*) av_mallocz(st->codec->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE);
802 if (st->codec->extradata) {
803 get_buffer(pb, st->codec->extradata, atom.size);
805 url_fskip(pb, atom.size);
806 } else if (atom.size > 8) { /* to read frma, esds atoms */
807 mov_read_default(c, pb, atom);
808 } else if (atom.size > 0)
809 url_fskip(pb, atom.size);
810 /* in any case, skip garbage */
811 url_fskip(pb, atom.size - ((url_ftell(pb) - start_pos)));
815 static int mov_read_jp2h(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
817 AVStream *st = c->fc->streams[c->fc->nb_streams-1];
819 if((uint64_t)atom.size > (1<<30))
822 av_free(st->codec->extradata);
824 st->codec->extradata_size = atom.size + 8;
825 st->codec->extradata = (uint8_t*) av_mallocz(st->codec->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE);
827 /* pass all jp2h atom to codec */
828 if (st->codec->extradata) {
829 strcpy(st->codec->extradata + 4, "jp2h");
830 get_buffer(pb, st->codec->extradata + 8, atom.size);
832 url_fskip(pb, atom.size);
836 static int mov_read_avcC(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
838 AVStream *st = c->fc->streams[c->fc->nb_streams-1];
840 if((uint64_t)atom.size > (1<<30))
843 av_free(st->codec->extradata);
845 st->codec->extradata_size = atom.size;
846 st->codec->extradata = (uint8_t*) av_mallocz(st->codec->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE);
848 if (st->codec->extradata) {
849 get_buffer(pb, st->codec->extradata, atom.size);
851 url_fskip(pb, atom.size);
856 static int mov_read_stco(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
858 AVStream *st = c->fc->streams[c->fc->nb_streams-1];
859 MOVStreamContext *sc = (MOVStreamContext *)st->priv_data;
860 unsigned int i, entries;
862 get_byte(pb); /* version */
863 get_byte(pb); get_byte(pb); get_byte(pb); /* flags */
865 entries = get_be32(pb);
867 if(entries >= UINT_MAX/sizeof(int64_t))
870 sc->chunk_count = entries;
871 sc->chunk_offsets = (int64_t*) av_malloc(entries * sizeof(int64_t));
872 if (!sc->chunk_offsets)
874 if (atom.type == MKTAG('s', 't', 'c', 'o')) {
875 for(i=0; i<entries; i++) {
876 sc->chunk_offsets[i] = get_be32(pb);
878 } else if (atom.type == MKTAG('c', 'o', '6', '4')) {
879 for(i=0; i<entries; i++) {
880 sc->chunk_offsets[i] = get_be64(pb);
885 for(i=0; i<c->fc->nb_streams; i++){
886 MOVStreamContext *sc2 = (MOVStreamContext *)c->fc->streams[i]->priv_data;
887 if(sc2 && sc2->chunk_offsets){
888 int64_t first= sc2->chunk_offsets[0];
889 int64_t last= sc2->chunk_offsets[sc2->chunk_count-1];
890 if(first >= sc->chunk_offsets[entries-1] || last <= sc->chunk_offsets[0])
897 static int mov_read_stsd(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
899 AVStream *st = c->fc->streams[c->fc->nb_streams-1];
900 MOVStreamContext *sc = (MOVStreamContext *)st->priv_data;
901 int entries, frames_per_sample;
903 uint8_t codec_name[32];
905 /* for palette traversal */
913 unsigned char *color_table;
915 unsigned char r, g, b;
917 get_byte(pb); /* version */
918 get_byte(pb); get_byte(pb); get_byte(pb); /* flags */
920 entries = get_be32(pb);
922 while(entries--) { //Parsing Sample description table
924 MOV_atom_t a = { 0, 0, 0 };
925 offset_t start_pos = url_ftell(pb);
926 int size = get_be32(pb); /* size */
927 format = get_le32(pb); /* data format */
929 get_be32(pb); /* reserved */
930 get_be16(pb); /* reserved */
931 get_be16(pb); /* index */
933 dprintf("size=%d 4CC= %c%c%c%c codec_type=%d\n",
935 (format >> 0) & 0xff, (format >> 8) & 0xff, (format >> 16) & 0xff, (format >> 24) & 0xff,
936 st->codec->codec_type);
937 st->codec->codec_tag = format;
938 /* codec_type is set earlier by read_hdlr */
939 if(st->codec->codec_type==CODEC_TYPE_VIDEO) {
940 /* for MPEG4: set codec type by looking for it */
941 id = codec_get_id(mov_video_tags, format);
943 id = codec_get_id(codec_bmp_tags, format);
944 st->codec->codec_id = id;
945 get_be16(pb); /* version */
946 get_be16(pb); /* revision level */
947 get_be32(pb); /* vendor */
948 get_be32(pb); /* temporal quality */
949 get_be32(pb); /* spacial quality */
950 if(st->codec->codec_id == CODEC_ID_MPEG4){ //FIXME this is silly
954 st->codec->width = get_be16(pb); /* width */
955 st->codec->height = get_be16(pb); /* height */
957 get_be32(pb); /* horiz resolution */
958 get_be32(pb); /* vert resolution */
959 get_be32(pb); /* data size, always 0 */
960 frames_per_sample = get_be16(pb); /* frames per samples */
962 av_log(NULL, AV_LOG_DEBUG, "frames/samples = %d\n", frames_per_sample);
964 get_buffer(pb, codec_name, 32); /* codec name, pascal string (FIXME: true for mp4?) */
965 if (codec_name[0] <= 31) {
966 memcpy(st->codec->codec_name, &codec_name[1],codec_name[0]);
967 st->codec->codec_name[codec_name[0]] = 0;
970 st->codec->bits_per_sample = get_be16(pb); /* depth */
971 st->codec->color_table_id = get_be16(pb); /* colortable id */
973 /* These are set in mov_read_stts and might already be set!
974 st->codec->time_base.den = 25;
975 st->codec->time_base.num = 1;
978 /* figure out the palette situation */
979 color_depth = st->codec->bits_per_sample & 0x1F;
980 color_greyscale = st->codec->bits_per_sample & 0x20;
982 /* if the depth is 2, 4, or 8 bpp, file is palettized */
983 if ((color_depth == 2) || (color_depth == 4) ||
984 (color_depth == 8)) {
986 if (color_greyscale) {
988 /* compute the greyscale palette */
989 color_count = 1 << color_depth;
991 color_dec = 256 / (color_count - 1);
992 for (j = 0; j < color_count; j++) {
993 r = g = b = color_index;
994 c->palette_control.palette[j] =
995 (r << 16) | (g << 8) | (b);
996 color_index -= color_dec;
1001 } else if (st->codec->color_table_id & 0x08) {
1003 /* if flag bit 3 is set, use the default palette */
1004 color_count = 1 << color_depth;
1005 if (color_depth == 2)
1006 color_table = ff_qt_default_palette_4;
1007 else if (color_depth == 4)
1008 color_table = ff_qt_default_palette_16;
1010 color_table = ff_qt_default_palette_256;
1012 for (j = 0; j < color_count; j++) {
1013 r = color_table[j * 4 + 0];
1014 g = color_table[j * 4 + 1];
1015 b = color_table[j * 4 + 2];
1016 c->palette_control.palette[j] =
1017 (r << 16) | (g << 8) | (b);
1022 /* load the palette from the file */
1023 color_start = get_be32(pb);
1024 color_count = get_be16(pb);
1025 color_end = get_be16(pb);
1026 for (j = color_start; j <= color_end; j++) {
1027 /* each R, G, or B component is 16 bits;
1028 * only use the top 8 bits; skip alpha bytes
1038 c->palette_control.palette[j] =
1039 (r << 16) | (g << 8) | (b);
1043 st->codec->palctrl = &c->palette_control;
1044 st->codec->palctrl->palette_changed = 1;
1046 st->codec->palctrl = NULL;
1047 } else if(st->codec->codec_type==CODEC_TYPE_AUDIO) {
1048 uint16_t version = get_be16(pb);
1050 st->codec->codec_id = codec_get_id(mov_audio_tags, format);
1051 get_be16(pb); /* revision level */
1052 get_be32(pb); /* vendor */
1054 st->codec->channels = get_be16(pb); /* channel count */
1055 st->codec->bits_per_sample = get_be16(pb); /* sample size */
1056 /* do we need to force to 16 for AMR ? */
1058 /* handle specific s8 codec */
1059 get_be16(pb); /* compression id = 0*/
1060 get_be16(pb); /* packet size = 0 */
1062 st->codec->sample_rate = ((get_be32(pb) >> 16));
1064 switch (st->codec->codec_id) {
1065 case CODEC_ID_PCM_S16BE:
1066 if (st->codec->bits_per_sample == 8)
1067 st->codec->codec_id = CODEC_ID_PCM_S8;
1069 case CODEC_ID_PCM_U8:
1070 if (st->codec->bits_per_sample == 16)
1071 st->codec->codec_id = CODEC_ID_PCM_S16BE;
1072 st->codec->bit_rate = st->codec->sample_rate * 8;
1074 case CODEC_ID_AMR_WB:
1075 st->codec->sample_rate = 16000; /* should really we ? */
1076 st->codec->channels=1; /* really needed */
1078 case CODEC_ID_AMR_NB:
1079 st->codec->sample_rate = 8000; /* should really we ? */
1080 st->codec->channels=1; /* really needed */
1086 //Read QT version 1 fields. In version 0 theese dont exist
1087 dprintf("version =%d mp4=%d\n",version,c->mp4);
1089 get_be32(pb); /* samples per packet */
1090 get_be32(pb); /* bytes per packet */
1091 get_be32(pb); /* bytes per frame */
1092 get_be32(pb); /* bytes per sample */
1093 } else if(version==2) {
1094 get_be32(pb); /* sizeof struct only */
1095 st->codec->sample_rate = av_int2dbl(get_be64(pb)); /* float 64 */
1096 st->codec->channels = get_be32(pb);
1097 get_be32(pb); /* always 0x7F000000 */
1098 get_be32(pb); /* bits per channel if sound is uncompressed */
1099 get_be32(pb); /* lcpm format specific flag */
1100 get_be32(pb); /* bytes per audio packet if constant */
1101 get_be32(pb); /* lpcm frames per audio packet if constant */
1104 /* other codec type, just skip (rtp, mp4s, tmcd ...) */
1105 url_fskip(pb, size - (url_ftell(pb) - start_pos));
1107 /* this will read extra atoms at the end (wave, alac, damr, avcC, SMI ...) */
1108 a.size = size - (url_ftell(pb) - start_pos);
1110 mov_read_default(c, pb, a);
1111 else if (a.size > 0)
1112 url_fskip(pb, a.size);
1115 if(st->codec->codec_type==CODEC_TYPE_AUDIO && st->codec->sample_rate==0 && sc->time_scale>1) {
1116 st->codec->sample_rate= sc->time_scale;
1122 static int mov_read_stsc(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
1124 AVStream *st = c->fc->streams[c->fc->nb_streams-1];
1125 MOVStreamContext *sc = (MOVStreamContext *)st->priv_data;
1126 unsigned int i, entries;
1128 get_byte(pb); /* version */
1129 get_byte(pb); get_byte(pb); get_byte(pb); /* flags */
1131 entries = get_be32(pb);
1133 if(entries >= UINT_MAX / sizeof(MOV_sample_to_chunk_tbl))
1137 av_log(NULL, AV_LOG_DEBUG, "track[%i].stsc.entries = %i\n", c->fc->nb_streams-1, entries);
1139 sc->sample_to_chunk_sz = entries;
1140 sc->sample_to_chunk = (MOV_sample_to_chunk_tbl*) av_malloc(entries * sizeof(MOV_sample_to_chunk_tbl));
1141 if (!sc->sample_to_chunk)
1143 for(i=0; i<entries; i++) {
1144 sc->sample_to_chunk[i].first = get_be32(pb);
1145 sc->sample_to_chunk[i].count = get_be32(pb);
1146 sc->sample_to_chunk[i].id = get_be32(pb);
1151 static int mov_read_stss(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
1153 AVStream *st = c->fc->streams[c->fc->nb_streams-1];
1154 MOVStreamContext *sc = (MOVStreamContext *)st->priv_data;
1155 unsigned int i, entries;
1157 get_byte(pb); /* version */
1158 get_byte(pb); get_byte(pb); get_byte(pb); /* flags */
1160 entries = get_be32(pb);
1162 if(entries >= UINT_MAX / sizeof(long))
1165 sc->keyframe_count = entries;
1167 av_log(NULL, AV_LOG_DEBUG, "keyframe_count = %ld\n", sc->keyframe_count);
1169 sc->keyframes = (long*) av_malloc(entries * sizeof(long));
1172 for(i=0; i<entries; i++) {
1173 sc->keyframes[i] = get_be32(pb);
1175 /* av_log(NULL, AV_LOG_DEBUG, "keyframes[]=%ld\n", sc->keyframes[i]); */
1181 static int mov_read_stsz(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
1183 AVStream *st = c->fc->streams[c->fc->nb_streams-1];
1184 MOVStreamContext *sc = (MOVStreamContext *)st->priv_data;
1185 unsigned int i, entries;
1187 get_byte(pb); /* version */
1188 get_byte(pb); get_byte(pb); get_byte(pb); /* flags */
1190 sc->sample_size = get_be32(pb);
1191 entries = get_be32(pb);
1192 if(entries >= UINT_MAX / sizeof(long))
1195 sc->sample_count = entries;
1197 av_log(NULL, AV_LOG_DEBUG, "sample_size = %ld sample_count = %ld\n", sc->sample_size, sc->sample_count);
1200 return 0; /* there isn't any table following */
1201 sc->sample_sizes = (long*) av_malloc(entries * sizeof(long));
1202 if (!sc->sample_sizes)
1204 for(i=0; i<entries; i++) {
1205 sc->sample_sizes[i] = get_be32(pb);
1207 av_log(NULL, AV_LOG_DEBUG, "sample_sizes[]=%ld\n", sc->sample_sizes[i]);
1213 static int mov_read_stts(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
1215 AVStream *st = c->fc->streams[c->fc->nb_streams-1];
1216 MOVStreamContext *sc = (MOVStreamContext *)st->priv_data;
1217 unsigned int i, entries;
1219 int64_t total_sample_count=0;
1221 get_byte(pb); /* version */
1222 get_byte(pb); get_byte(pb); get_byte(pb); /* flags */
1223 entries = get_be32(pb);
1224 if(entries >= UINT_MAX / sizeof(Time2Sample))
1227 sc->stts_count = entries;
1228 sc->stts_data = av_malloc(entries * sizeof(Time2Sample));
1231 av_log(NULL, AV_LOG_DEBUG, "track[%i].stts.entries = %i\n", c->fc->nb_streams-1, entries);
1236 for(i=0; i<entries; i++) {
1237 int sample_duration;
1240 sample_count=get_be32(pb);
1241 sample_duration = get_be32(pb);
1242 sc->stts_data[i].count= sample_count;
1243 sc->stts_data[i].duration= sample_duration;
1245 sc->time_rate= ff_gcd(sc->time_rate, sample_duration);
1247 dprintf("sample_count=%d, sample_duration=%d\n",sample_count,sample_duration);
1249 duration+=sample_duration*sample_count;
1250 total_sample_count+=sample_count;
1253 st->nb_frames= total_sample_count;
1255 st->duration= duration;
1259 static int mov_read_ctts(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
1261 AVStream *st = c->fc->streams[c->fc->nb_streams-1];
1262 MOVStreamContext *sc = (MOVStreamContext *)st->priv_data;
1263 unsigned int i, entries;
1265 get_byte(pb); /* version */
1266 get_byte(pb); get_byte(pb); get_byte(pb); /* flags */
1267 entries = get_be32(pb);
1268 if(entries >= UINT_MAX / sizeof(Time2Sample))
1271 sc->ctts_count = entries;
1272 sc->ctts_data = av_malloc(entries * sizeof(Time2Sample));
1274 dprintf("track[%i].ctts.entries = %i\n", c->fc->nb_streams-1, entries);
1276 for(i=0; i<entries; i++) {
1277 int count =get_be32(pb);
1278 int duration =get_be32(pb);
1280 sc->ctts_data[i].count = count;
1281 sc->ctts_data[i].duration= duration;
1283 sc->time_rate= ff_gcd(sc->time_rate, duration);
1288 static int mov_read_trak(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
1291 MOVStreamContext *sc;
1293 st = av_new_stream(c->fc, c->fc->nb_streams);
1295 sc = (MOVStreamContext*) av_mallocz(sizeof(MOVStreamContext));
1301 sc->sample_to_chunk_index = -1;
1303 st->codec->codec_type = CODEC_TYPE_MOV_OTHER;
1304 st->start_time = 0; /* XXX: check */
1305 c->streams[c->fc->nb_streams-1] = sc;
1307 return mov_read_default(c, pb, atom);
1310 static int mov_read_tkhd(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
1314 st = c->fc->streams[c->fc->nb_streams-1];
1316 get_byte(pb); /* version */
1318 get_byte(pb); get_byte(pb);
1319 get_byte(pb); /* flags */
1321 MOV_TRACK_ENABLED 0x0001
1322 MOV_TRACK_IN_MOVIE 0x0002
1323 MOV_TRACK_IN_PREVIEW 0x0004
1324 MOV_TRACK_IN_POSTER 0x0008
1327 get_be32(pb); /* creation time */
1328 get_be32(pb); /* modification time */
1329 st->id = (int)get_be32(pb); /* track id (NOT 0 !)*/
1330 get_be32(pb); /* reserved */
1331 st->start_time = 0; /* check */
1332 get_be32(pb); /* highlevel (considering edits) duration in movie timebase */
1333 get_be32(pb); /* reserved */
1334 get_be32(pb); /* reserved */
1336 get_be16(pb); /* layer */
1337 get_be16(pb); /* alternate group */
1338 get_be16(pb); /* volume */
1339 get_be16(pb); /* reserved */
1341 url_fskip(pb, 36); /* display matrix */
1343 /* those are fixed-point */
1344 /*st->codec->width =*/ get_be32(pb) >> 16; /* track width */
1345 /*st->codec->height =*/ get_be32(pb) >> 16; /* track height */
1350 /* this atom should be null (from specs), but some buggy files put the 'moov' atom inside it... */
1351 /* like the files created with Adobe Premiere 5.0, for samples see */
1352 /* http://graphics.tudelft.nl/~wouter/publications/soundtests/ */
1353 static int mov_read_wide(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
1358 return 0; /* continue */
1359 if (get_be32(pb) != 0) { /* 0 sized mdat atom... use the 'wide' atom size */
1360 url_fskip(pb, atom.size - 4);
1363 atom.type = get_le32(pb);
1366 if (atom.type != MKTAG('m', 'd', 'a', 't')) {
1367 url_fskip(pb, atom.size);
1370 err = mov_read_mdat(c, pb, atom);
1376 static int null_read_packet(void *opaque, uint8_t *buf, int buf_size)
1381 static int mov_read_cmov(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
1385 uint8_t *moov_data; /* uncompressed data */
1386 long cmov_len, moov_len;
1389 get_be32(pb); /* dcom atom */
1390 if (get_le32(pb) != MKTAG( 'd', 'c', 'o', 'm' ))
1392 if (get_le32(pb) != MKTAG( 'z', 'l', 'i', 'b' )) {
1393 av_log(NULL, AV_LOG_ERROR, "unknown compression for cmov atom !");
1396 get_be32(pb); /* cmvd atom */
1397 if (get_le32(pb) != MKTAG( 'c', 'm', 'v', 'd' ))
1399 moov_len = get_be32(pb); /* uncompressed size */
1400 cmov_len = atom.size - 6 * 4;
1402 cmov_data = (uint8_t *) av_malloc(cmov_len);
1405 moov_data = (uint8_t *) av_malloc(moov_len);
1410 get_buffer(pb, cmov_data, cmov_len);
1411 if(uncompress (moov_data, (uLongf *) &moov_len, (const Bytef *)cmov_data, cmov_len) != Z_OK)
1413 if(init_put_byte(&ctx, moov_data, moov_len, 0, NULL, null_read_packet, NULL, NULL) != 0)
1415 ctx.buf_end = ctx.buffer + moov_len;
1416 atom.type = MKTAG( 'm', 'o', 'o', 'v' );
1418 atom.size = moov_len;
1420 // { int fd = open("/tmp/uncompheader.mov", O_WRONLY | O_CREAT); write(fd, moov_data, moov_len); close(fd); }
1422 ret = mov_read_default(c, &ctx, atom);
1430 /* edit list atom */
1431 static int mov_read_elst(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
1435 get_byte(pb); /* version */
1436 get_byte(pb); get_byte(pb); get_byte(pb); /* flags */
1437 edit_count= c->streams[c->fc->nb_streams-1]->edit_count = get_be32(pb); /* entries */
1439 for(i=0; i<edit_count; i++){
1440 get_be32(pb); /* Track duration */
1441 get_be32(pb); /* Media time */
1442 get_be32(pb); /* Media rate */
1444 dprintf("track[%i].edit_count = %i\n", c->fc->nb_streams-1, c->streams[c->fc->nb_streams-1]->edit_count);
1448 static const MOVParseTableEntry mov_default_parse_table[] = {
1450 { MKTAG( 'c', 'o', '6', '4' ), mov_read_stco },
1451 { MKTAG( 'c', 'p', 'r', 't' ), mov_read_default },
1452 { MKTAG( 'c', 'r', 'h', 'd' ), mov_read_default },
1453 { MKTAG( 'c', 't', 't', 's' ), mov_read_ctts }, /* composition time to sample */
1454 { MKTAG( 'd', 'i', 'n', 'f' ), mov_read_default }, /* data information */
1455 { MKTAG( 'd', 'p', 'n', 'd' ), mov_read_leaf },
1456 { MKTAG( 'd', 'r', 'e', 'f' ), mov_read_leaf },
1457 { MKTAG( 'e', 'd', 't', 's' ), mov_read_default },
1458 { MKTAG( 'e', 'l', 's', 't' ), mov_read_elst },
1459 { MKTAG( 'e', 'n', 'd', 'a' ), mov_read_enda },
1460 { MKTAG( 'f', 'r', 'e', 'e' ), mov_read_leaf },
1461 { MKTAG( 'f', 't', 'y', 'p' ), mov_read_ftyp },
1462 { MKTAG( 'h', 'd', 'l', 'r' ), mov_read_hdlr },
1463 { MKTAG( 'h', 'i', 'n', 't' ), mov_read_leaf },
1464 { MKTAG( 'h', 'm', 'h', 'd' ), mov_read_leaf },
1465 { MKTAG( 'i', 'o', 'd', 's' ), mov_read_leaf },
1466 { MKTAG( 'j', 'p', '2', 'h' ), mov_read_jp2h },
1467 { MKTAG( 'm', 'd', 'a', 't' ), mov_read_mdat },
1468 { MKTAG( 'm', 'd', 'h', 'd' ), mov_read_mdhd },
1469 { MKTAG( 'm', 'd', 'i', 'a' ), mov_read_default },
1470 { MKTAG( 'm', 'i', 'n', 'f' ), mov_read_default },
1471 { MKTAG( 'm', 'o', 'o', 'v' ), mov_read_moov },
1472 { MKTAG( 'm', 'p', '4', 'a' ), mov_read_default },
1473 { MKTAG( 'm', 'p', '4', 's' ), mov_read_default },
1474 { MKTAG( 'm', 'p', '4', 'v' ), mov_read_default },
1475 { MKTAG( 'm', 'p', 'o', 'd' ), mov_read_leaf },
1476 { MKTAG( 'm', 'v', 'h', 'd' ), mov_read_mvhd },
1477 { MKTAG( 'n', 'm', 'h', 'd' ), mov_read_leaf },
1478 { MKTAG( 'o', 'd', 'h', 'd' ), mov_read_default },
1479 { MKTAG( 's', 'd', 'h', 'd' ), mov_read_default },
1480 { MKTAG( 's', 'k', 'i', 'p' ), mov_read_leaf },
1481 { MKTAG( 's', 'm', 'h', 'd' ), mov_read_leaf }, /* sound media info header */
1482 { MKTAG( 'S', 'M', 'I', ' ' ), mov_read_smi }, /* Sorenson extension ??? */
1483 { MKTAG( 'a', 'l', 'a', 'c' ), mov_read_alac }, /* alac specific atom */
1484 { MKTAG( 'a', 'v', 'c', 'C' ), mov_read_avcC },
1485 { MKTAG( 's', 't', 'b', 'l' ), mov_read_default },
1486 { MKTAG( 's', 't', 'c', 'o' ), mov_read_stco },
1487 { MKTAG( 's', 't', 'd', 'p' ), mov_read_default },
1488 { MKTAG( 's', 't', 's', 'c' ), mov_read_stsc },
1489 { MKTAG( 's', 't', 's', 'd' ), mov_read_stsd }, /* sample description */
1490 { MKTAG( 's', 't', 's', 'h' ), mov_read_default },
1491 { MKTAG( 's', 't', 's', 's' ), mov_read_stss }, /* sync sample */
1492 { MKTAG( 's', 't', 's', 'z' ), mov_read_stsz }, /* sample size */
1493 { MKTAG( 's', 't', 't', 's' ), mov_read_stts },
1494 { MKTAG( 't', 'k', 'h', 'd' ), mov_read_tkhd }, /* track header */
1495 { MKTAG( 't', 'r', 'a', 'k' ), mov_read_trak },
1496 { MKTAG( 't', 'r', 'e', 'f' ), mov_read_default }, /* not really */
1497 { MKTAG( 'u', 'd', 't', 'a' ), mov_read_leaf },
1498 { MKTAG( 'u', 'r', 'l', ' ' ), mov_read_leaf },
1499 { MKTAG( 'u', 'r', 'n', ' ' ), mov_read_leaf },
1500 { MKTAG( 'u', 'u', 'i', 'd' ), mov_read_leaf },
1501 { MKTAG( 'v', 'm', 'h', 'd' ), mov_read_leaf }, /* video media info header */
1502 { MKTAG( 'w', 'a', 'v', 'e' ), mov_read_wave },
1504 { MKTAG( 'M', 'D', 'E', 'S' ), mov_read_leaf },
1506 { MKTAG( 'c', 'h', 'a', 'p' ), mov_read_leaf },
1507 { MKTAG( 'c', 'l', 'i', 'p' ), mov_read_default },
1508 { MKTAG( 'c', 'r', 'g', 'n' ), mov_read_leaf },
1509 { MKTAG( 'c', 't', 'a', 'b' ), mov_read_ctab },
1510 { MKTAG( 'e', 's', 'd', 's' ), mov_read_esds },
1511 { MKTAG( 'k', 'm', 'a', 't' ), mov_read_leaf },
1512 { MKTAG( 'm', 'a', 't', 't' ), mov_read_default },
1513 { MKTAG( 'r', 'd', 'r', 'f' ), mov_read_leaf },
1514 { MKTAG( 'r', 'm', 'd', 'a' ), mov_read_default },
1515 { MKTAG( 'r', 'm', 'd', 'r' ), mov_read_leaf },
1516 { MKTAG( 'r', 'm', 'r', 'a' ), mov_read_default },
1517 { MKTAG( 's', 'c', 'p', 't' ), mov_read_leaf },
1518 { MKTAG( 's', 's', 'r', 'c' ), mov_read_leaf },
1519 { MKTAG( 's', 'y', 'n', 'c' ), mov_read_leaf },
1520 { MKTAG( 't', 'c', 'm', 'd' ), mov_read_leaf },
1521 { MKTAG( 'w', 'i', 'd', 'e' ), mov_read_wide }, /* place holder */
1522 //{ MKTAG( 'r', 'm', 'q', 'u' ), mov_read_leaf },
1524 { MKTAG( 'c', 'm', 'o', 'v' ), mov_read_cmov },
1526 { MKTAG( 'c', 'm', 'o', 'v' ), mov_read_leaf },
1528 { 0L, mov_read_leaf }
1531 static void mov_free_stream_context(MOVStreamContext *sc)
1534 av_freep(&sc->chunk_offsets);
1535 av_freep(&sc->sample_to_chunk);
1536 av_freep(&sc->sample_sizes);
1537 av_freep(&sc->keyframes);
1538 av_freep(&sc->stts_data);
1539 av_freep(&sc->ctts_data);
1544 static inline uint32_t mov_to_tag(uint8_t *buf)
1546 return MKTAG(buf[0], buf[1], buf[2], buf[3]);
1549 static inline uint32_t to_be32(uint8_t *buf)
1551 return (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3];
1554 /* XXX: is it sufficient ? */
1555 static int mov_probe(AVProbeData *p)
1557 unsigned int offset;
1561 /* check file header */
1562 if (p->buf_size <= 12)
1566 /* ignore invalid offset */
1567 if ((offset + 8) > (unsigned int)p->buf_size)
1569 tag = mov_to_tag(p->buf + offset + 4);
1571 /* check for obvious tags */
1572 case MKTAG( 'j', 'P', ' ', ' ' ): /* jpeg 2000 signature */
1573 case MKTAG( 'm', 'o', 'o', 'v' ):
1574 case MKTAG( 'm', 'd', 'a', 't' ):
1575 case MKTAG( 'p', 'n', 'o', 't' ): /* detect movs with preview pics like ew.mov and april.mov */
1576 case MKTAG( 'u', 'd', 't', 'a' ): /* Packet Video PVAuthor adds this and a lot of more junk */
1577 return AVPROBE_SCORE_MAX;
1578 /* those are more common words, so rate then a bit less */
1579 case MKTAG( 'w', 'i', 'd', 'e' ):
1580 case MKTAG( 'f', 'r', 'e', 'e' ):
1581 case MKTAG( 'j', 'u', 'n', 'k' ):
1582 case MKTAG( 'p', 'i', 'c', 't' ):
1583 return AVPROBE_SCORE_MAX - 5;
1584 case MKTAG( 'f', 't', 'y', 'p' ):
1585 case MKTAG( 's', 'k', 'i', 'p' ):
1586 case MKTAG( 'u', 'u', 'i', 'd' ):
1587 offset = to_be32(p->buf+offset) + offset;
1588 /* if we only find those cause probedata is too small at least rate them */
1589 score = AVPROBE_SCORE_MAX - 50;
1592 /* unrecognized tag */
1599 static int mov_read_header(AVFormatContext *s, AVFormatParameters *ap)
1601 MOVContext *mov = (MOVContext *) s->priv_data;
1602 ByteIOContext *pb = &s->pb;
1604 MOV_atom_t atom = { 0, 0, 0 };
1607 mov->parse_table = mov_default_parse_table;
1609 if(!url_is_streamed(pb)) /* .mov and .mp4 aren't streamable anyway (only progressive download if moov is before mdat) */
1610 atom.size = url_fsize(pb);
1612 atom.size = 0x7FFFFFFFFFFFFFFFLL;
1614 /* check MOV header */
1615 err = mov_read_default(mov, pb, atom);
1616 if (err<0 || (!mov->found_moov && !mov->found_mdat)) {
1617 av_log(s, AV_LOG_ERROR, "mov: header not found !!! (err:%d, moov:%d, mdat:%d) pos:%"PRId64"\n",
1618 err, mov->found_moov, mov->found_mdat, url_ftell(pb));
1621 dprintf("on_parse_exit_offset=%d\n", (int) url_ftell(pb));
1623 /* some cleanup : make sure we are on the mdat atom */
1624 if(!url_is_streamed(pb) && (url_ftell(pb) != mov->mdat_offset))
1625 url_fseek(pb, mov->mdat_offset, SEEK_SET);
1627 mov->next_chunk_offset = mov->mdat_offset; /* initialise reading */
1628 mov->total_streams = nb = s->nb_streams;
1631 for(i=0; i<s->nb_streams;) {
1632 if(s->streams[i]->codec->codec_type == CODEC_TYPE_MOV_OTHER) {/* not audio, not video, delete */
1633 av_free(s->streams[i]);
1634 for(j=i+1; j<s->nb_streams; j++)
1635 s->streams[j-1] = s->streams[j];
1640 for(i=0; i<s->nb_streams;i++) {
1641 MOVStreamContext *sc = (MOVStreamContext *)s->streams[i]->priv_data;
1646 sc->time_scale= mov->time_scale;
1647 av_set_pts_info(s->streams[i], 64, sc->time_rate, sc->time_scale);
1649 if(s->streams[i]->duration != AV_NOPTS_VALUE){
1650 assert(s->streams[i]->duration % sc->time_rate == 0);
1651 s->streams[i]->duration /= sc->time_rate;
1655 sc->is_ff_stream = 1;
1661 /* Yes, this is ugly... I didn't write the specs of QT :p */
1662 /* XXX:remove useless commented code sometime */
1663 static int mov_read_packet(AVFormatContext *s, AVPacket *pkt)
1665 MOVContext *mov = (MOVContext *) s->priv_data;
1666 MOVStreamContext *sc;
1668 int64_t offset = INT64_MAX;
1669 int64_t best_dts = INT64_MAX;
1677 idx = sc->sample_to_chunk_index;
1679 if (idx < 0) return 0;
1680 dprintf("sc[ffid %d]->sample_size = %ld\n", sc->ffindex, sc->sample_size);
1681 //size = sc->sample_sizes[sc->current_sample];
1682 // that ain't working...
1683 //size = (sc->sample_size)?sc->sample_size:sc->sample_sizes[sc->current_sample];
1684 size = (sc->sample_size > 1)?sc->sample_size:sc->sample_sizes[sc->current_sample];
1686 sc->current_sample++;
1687 sc->left_in_chunk--;
1689 if (sc->left_in_chunk <= 0)
1691 offset = mov->next_chunk_offset;
1692 /* extract the sample */
1699 if(offset == INT64_MAX)
1700 best_dts= INT64_MAX;
1701 for(i=0; i<mov->total_streams; i++) {
1702 MOVStreamContext *msc = mov->streams[i];
1704 if ((msc->next_chunk < msc->chunk_count) && msc->next_chunk >= 0){
1705 if (msc->sample_to_time_index < msc->stts_count && mov->ni) {
1707 int index= msc->sample_to_time_index;
1708 int sample= msc->sample_to_time_sample;
1709 int time= msc->sample_to_time_time;
1710 int duration = msc->stts_data[index].duration;
1711 int count = msc->stts_data[index].count;
1712 if (sample + count < msc->current_sample) {
1714 time += count*duration;
1716 duration = msc->stts_data[index].duration;
1718 dts = time + (msc->current_sample-1 - sample) * (int64_t)duration;
1719 dts = av_rescale(dts, AV_TIME_BASE, msc->time_scale);
1720 dprintf("stream: %d dts: %Ld best_dts: %Ld offset: %Ld \n", i, dts, best_dts, offset);
1724 offset = msc->chunk_offsets[msc->next_chunk];
1727 if ((msc->chunk_offsets[msc->next_chunk] < offset)) {
1729 offset = msc->chunk_offsets[msc->next_chunk];
1734 if (!sc || offset==INT64_MAX)
1739 if(mov->next_chunk_offset < offset) { /* some meta data */
1740 url_fskip(&s->pb, (offset - mov->next_chunk_offset));
1741 mov->next_chunk_offset = offset;
1744 if(!sc->is_ff_stream || (s->streams[sc->ffindex]->discard >= AVDISCARD_ALL)) {
1745 url_fskip(&s->pb, (offset - mov->next_chunk_offset));
1746 mov->next_chunk_offset = offset;
1751 /* now get the chunk size... */
1753 for(i=0; i<mov->total_streams; i++) {
1754 MOVStreamContext *msc = mov->streams[i];
1755 if ((msc->next_chunk < msc->chunk_count)
1756 && msc->chunk_offsets[msc->next_chunk] - offset < size
1757 && msc->chunk_offsets[msc->next_chunk] > offset)
1758 size = msc->chunk_offsets[msc->next_chunk] - offset;
1761 #ifdef MOV_MINOLTA_FIX
1762 //Make sure that size is according to sample_size (Needed by .mov files
1763 //created on a Minolta Dimage Xi where audio chunks contains waste data in the end)
1764 //Maybe we should really not only check sc->sample_size, but also sc->sample_sizes
1765 //but I have no such movies
1766 if (sc->sample_size > 0) {
1768 for(i=0; i<(sc->sample_to_chunk_sz); i++) {
1769 if( (sc->sample_to_chunk[i].first)<=(sc->next_chunk) )
1771 // I can't figure out why for PCM audio sample_size is always 1
1772 // (it should actually be channels*bits_per_second/8) but it is.
1773 AVCodecContext* cod = s->streams[sc->ffindex]->codec;
1774 if (sc->sample_size == 1 && (cod->codec_id == CODEC_ID_PCM_S16BE || cod->codec_id == CODEC_ID_PCM_S16LE))
1775 foundsize=(sc->sample_to_chunk[i].count*cod->channels*cod->bits_per_sample)/8;
1777 foundsize=sc->sample_to_chunk[i].count*sc->sample_size;
1779 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);
1781 if( (foundsize>0) && (foundsize<size) )
1786 #endif //MOV_MINOLTA_FIX
1788 idx = sc->sample_to_chunk_index;
1789 if (idx + 1 < sc->sample_to_chunk_sz && sc->next_chunk >= sc->sample_to_chunk[idx + 1].first)
1791 sc->sample_to_chunk_index = idx;
1792 /* split chunks into samples */
1793 if (sc->sample_size == 0 || sc->sample_size > 100) {
1794 if (idx >= 0 && sc->sample_to_chunk[idx].count != 1) {
1796 /* we'll have to get those samples before next chunk */
1797 sc->left_in_chunk = sc->sample_to_chunk[idx].count - 1;
1798 size = (sc->sample_size > 1)?sc->sample_size:sc->sample_sizes[sc->current_sample];
1801 sc->current_sample++;
1802 }else if(idx + 1 < sc->sample_to_chunk_sz){
1803 sc->current_sample += sc->sample_to_chunk[idx].count;
1807 dprintf("chunk: %lli -> %lli (%i)\n", offset, offset + size, size);
1808 if(size == 0x0FFFFFFF)
1809 size = mov->mdat_size + mov->mdat_offset - offset;
1814 url_fseek(&s->pb, offset, SEEK_SET);
1816 av_get_packet(&s->pb, pkt, size);
1817 pkt->stream_index = sc->ffindex;
1819 // If the keyframes table exists, mark any samples that are in the table as key frames.
1820 // If no table exists, treat very sample as a key frame.
1821 if (sc->keyframes) {
1823 b = sc->keyframe_count - 1;
1826 m = (a + b + 1) >> 1;
1827 if (sc->keyframes[m] > sc->current_sample) {
1834 if (sc->keyframes[a] == sc->current_sample)
1835 pkt->flags |= PKT_FLAG_KEY;
1838 pkt->flags |= PKT_FLAG_KEY;
1840 mov->next_chunk_offset = offset + size;
1842 /* find the corresponding dts */
1843 if (sc && sc->sample_to_time_index < sc->stts_count && pkt) {
1846 unsigned int duration = sc->stts_data[sc->sample_to_time_index].duration;
1847 count = sc->stts_data[sc->sample_to_time_index].count;
1848 if ((sc->sample_to_time_sample + count) < sc->current_sample) {
1849 sc->sample_to_time_sample += count;
1850 sc->sample_to_time_time += count*duration;
1851 sc->sample_to_time_index ++;
1852 duration = sc->stts_data[sc->sample_to_time_index].duration;
1854 dts = sc->sample_to_time_time + (sc->current_sample-1 - sc->sample_to_time_sample) * (int64_t)duration;
1855 /* find the corresponding pts */
1856 if (sc->sample_to_ctime_index < sc->ctts_count) {
1857 int duration = sc->ctts_data[sc->sample_to_ctime_index].duration;
1858 int count = sc->ctts_data[sc->sample_to_ctime_index].count;
1860 if ((sc->sample_to_ctime_sample + count) < sc->current_sample) {
1861 sc->sample_to_ctime_sample += count;
1862 sc->sample_to_ctime_index ++;
1863 duration = sc->ctts_data[sc->sample_to_ctime_index].duration;
1865 pts = dts + duration;
1869 st= s->streams[ sc->ffindex ];
1870 assert(pts % st->time_base.num == 0);
1871 assert(dts % st->time_base.num == 0);
1873 pkt->pts = pts / st->time_base.num;
1874 pkt->dts = dts / st->time_base.num;
1875 dprintf("stream #%d smp #%ld dts = %lld pts = %lld (smp:%ld time:%lld idx:%d ent:%d count:%d dur:%d)\n"
1876 , pkt->stream_index, sc->current_sample-1, pkt->dts, pkt->pts
1877 , sc->sample_to_time_sample
1878 , sc->sample_to_time_time
1879 , sc->sample_to_time_index
1888 #if defined(MOV_SEEK)
1890 * Seek method based on the one described in the Appendix C of QTFileFormat.pdf
1892 static int mov_read_seek(AVFormatContext *s, int stream_index, int64_t sample_time, int flags)
1894 MOVContext* mov = (MOVContext *) s->priv_data;
1895 MOVStreamContext* sc;
1898 int32_t seek_sample, sample;
1902 int32_t left_in_chunk;
1903 int64_t chunk_file_offset;
1904 int64_t sample_file_offset;
1905 int32_t first_chunk_sample;
1906 int32_t sample_to_chunk_idx;
1907 int sample_to_time_index;
1908 long sample_to_time_sample = 0;
1909 uint64_t sample_to_time_time = 0;
1912 // Find the corresponding mov stream
1913 for (mov_idx = 0; mov_idx < mov->total_streams; mov_idx++)
1914 if (mov->streams[mov_idx]->ffindex == stream_index)
1916 if (mov_idx == mov->total_streams) {
1917 av_log(s, AV_LOG_ERROR, "mov: requested stream was not found in mov streams (idx=%i)\n", stream_index);
1920 sc = mov->streams[mov_idx];
1922 sample_time *= s->streams[stream_index]->time_base.num;
1924 // Step 1. Find the edit that contains the requested time (elst)
1925 if (sc->edit_count && 0) {
1926 // FIXME should handle edit list
1927 av_log(s, AV_LOG_ERROR, "mov: does not handle seeking in files that contain edit list (c:%d)\n", sc->edit_count);
1931 // Step 2. Find the corresponding sample using the Time-to-sample atom (stts) */
1932 dprintf("Searching for time %li in stream #%i (time_scale=%i)\n", (long)sample_time, mov_idx, sc->time_scale);
1933 start_time = 0; // FIXME use elst atom
1934 sample = 1; // sample are 0 based in table
1936 for (i = 0; i < sc->stts_count; i++) {
1937 count = sc->stts_data[i].count;
1938 duration = sc->stts_data[i].duration;
1939 if ((start_time + count*duration) > sample_time) {
1940 sample_to_time_time = start_time;
1941 sample_to_time_index = i;
1942 sample_to_time_sample = sample;
1943 sample += (sample_time - start_time) / duration;
1947 start_time += count * duration;
1949 sample_to_time_time = start_time;
1950 sample_to_time_index = i;
1951 /* NOTE: despite what qt doc say, the dt value (Display Time in qt vocabulary) computed with the stts atom
1952 is a decoding time stamp (dts) not a presentation time stamp. And as usual dts != pts for stream with b frames */
1954 dprintf("Found time %li at sample #%u\n", (long)sample_time, sample);
1955 if (sample > sc->sample_count) {
1956 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);
1960 // Step 3. Find the prior sync. sample using the Sync sample atom (stss)
1961 if (sc->keyframes) {
1963 b = sc->keyframe_count - 1;
1965 m = (a + b + 1) >> 1;
1966 if (sc->keyframes[m] > sample) {
1972 // for low latency prob: always use the previous keyframe, just uncomment the next line
1974 seek_sample = sc->keyframes[a];
1977 seek_sample = sample; // else all samples are key frames
1978 dprintf("Found nearest keyframe at sample #%i \n", seek_sample);
1980 // Step 4. Find the chunk of the sample using the Sample-to-chunk-atom (stsc)
1981 for (first_chunk_sample = 1, i = 0; i < (sc->sample_to_chunk_sz - 1); i++) {
1982 b = (sc->sample_to_chunk[i + 1].first - sc->sample_to_chunk[i].first) * sc->sample_to_chunk[i].count;
1983 if (seek_sample >= first_chunk_sample && seek_sample < (first_chunk_sample + b))
1985 first_chunk_sample += b;
1987 chunk = sc->sample_to_chunk[i].first + (seek_sample - first_chunk_sample) / sc->sample_to_chunk[i].count;
1988 left_in_chunk = sc->sample_to_chunk[i].count - (seek_sample - first_chunk_sample) % sc->sample_to_chunk[i].count;
1989 first_chunk_sample += ((seek_sample - first_chunk_sample) / sc->sample_to_chunk[i].count) * sc->sample_to_chunk[i].count;
1990 sample_to_chunk_idx = i;
1991 dprintf("Sample was found in chunk #%i at sample offset %i (idx %i)\n", chunk, seek_sample - first_chunk_sample, sample_to_chunk_idx);
1993 // Step 5. Find the offset of the chunk using the chunk offset atom
1994 if (!sc->chunk_offsets) {
1995 av_log(s, AV_LOG_ERROR, "mov: no chunk offset atom, unable to seek\n");
1998 if (chunk > sc->chunk_count) {
1999 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);
2002 chunk_file_offset = sc->chunk_offsets[chunk - 1];
2003 dprintf("Chunk file offset is #%llu \n", chunk_file_offset);
2005 // Step 6. Find the byte offset within the chunk using the sample size atom
2006 sample_file_offset = chunk_file_offset;
2007 if (sc->sample_size)
2008 sample_file_offset += (seek_sample - first_chunk_sample) * sc->sample_size;
2010 for (i = 0; i < (seek_sample - first_chunk_sample); i++) {
2011 sample_file_offset += sc->sample_sizes[first_chunk_sample + i - 1];
2014 dprintf("Sample file offset is #%llu \n", sample_file_offset);
2016 // Step 6. Update the parser
2018 mov->next_chunk_offset = sample_file_offset;
2019 // Update current stream state
2020 sc->current_sample = seek_sample - 1; // zero based
2021 sc->left_in_chunk = left_in_chunk;
2022 sc->next_chunk = chunk; // +1 -1 (zero based)
2023 sc->sample_to_chunk_index = sample_to_chunk_idx;
2025 // Update other streams
2026 for (i = 0; i<mov->total_streams; i++) {
2027 MOVStreamContext *msc;
2028 if (i == mov_idx) continue;
2029 // Find the nearest 'next' chunk
2030 msc = mov->streams[i];
2032 b = msc->chunk_count - 1;
2034 m = (a + b + 1) >> 1;
2035 if (msc->chunk_offsets[m] > chunk_file_offset) {
2041 msc->next_chunk = a;
2042 if (msc->chunk_offsets[a] < chunk_file_offset && a < (msc->chunk_count-1))
2044 dprintf("Nearest next chunk for stream #%i is #%li @%lli\n", i, msc->next_chunk+1, msc->chunk_offsets[msc->next_chunk]);
2046 // Compute sample count and index in the sample_to_chunk table (what a pity)
2047 msc->sample_to_chunk_index = 0;
2048 msc->current_sample = 0;
2049 for(; msc->sample_to_chunk_index < (msc->sample_to_chunk_sz - 1)
2050 && msc->sample_to_chunk[msc->sample_to_chunk_index + 1].first <= (1 + msc->next_chunk); msc->sample_to_chunk_index++) {
2051 msc->current_sample += (msc->sample_to_chunk[msc->sample_to_chunk_index + 1].first - msc->sample_to_chunk[msc->sample_to_chunk_index].first) \
2052 * msc->sample_to_chunk[msc->sample_to_chunk_index].count;
2054 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;
2055 msc->left_in_chunk = msc->sample_to_chunk[msc->sample_to_chunk_index].count - 1;
2056 // Find corresponding position in stts (used later to compute dts)
2059 for (msc->sample_to_time_index = 0; msc->sample_to_time_index < msc->stts_count; msc->sample_to_time_index++) {
2060 count = msc->stts_data[msc->sample_to_time_index].count;
2061 duration = msc->stts_data[msc->sample_to_time_index].duration;
2062 if ((sample + count - 1) > msc->current_sample) {
2063 msc->sample_to_time_time = start_time;
2064 msc->sample_to_time_sample = sample;
2068 start_time += count * duration;
2071 for (msc->sample_to_ctime_index = 0; msc->sample_to_ctime_index < msc->ctts_count; msc->sample_to_ctime_index++) {
2072 count = msc->ctts_data[msc->sample_to_ctime_index].count;
2073 duration = msc->ctts_data[msc->sample_to_ctime_index].duration;
2074 if ((sample + count - 1) > msc->current_sample) {
2075 msc->sample_to_ctime_sample = sample;
2080 dprintf("Next Sample for stream #%i is #%li @%li\n", i, msc->current_sample + 1, msc->sample_to_chunk_index + 1);
2086 static int mov_read_close(AVFormatContext *s)
2089 MOVContext *mov = (MOVContext *) s->priv_data;
2090 for(i=0; i<mov->total_streams; i++)
2091 mov_free_stream_context(mov->streams[i]);
2092 /* free color tabs */
2093 for(i=0; i<mov->ctab_size; i++)
2094 av_freep(&mov->ctab[i]);
2095 av_freep(&mov->ctab);
2099 static AVInputFormat mov_iformat = {
2100 "mov,mp4,m4a,3gp,3g2,mj2",
2101 "QuickTime/MPEG4/Motion JPEG 2000 format",
2107 #if defined(MOV_SEEK)
2114 av_register_input_format(&mov_iformat);