3 * Copyright (c) 2001 Fabrice Bellard.
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
33 * First version by Francois Revol revol@free.fr
34 * Seek function by Gael Chardon gael.dev@4now.net
36 * Features and limitations:
37 * - reads most of the QT files I have (at least the structure),
38 * the exceptions are .mov with zlib compressed headers ('cmov' section). It shouldn't be hard to implement.
39 * FIXED, Francois Revol, 07/17/2002
40 * - ffmpeg has nearly none of the usual QuickTime codecs,
41 * although I succesfully dumped raw and mp3 audio tracks off .mov files.
42 * Sample QuickTime files with mp3 audio can be found at: http://www.3ivx.com/showcase.html
43 * - .mp4 parsing is still hazardous, although the format really is QuickTime with some minor changes
44 * (to make .mov parser crash maybe ?), despite what they say in the MPEG FAQ at
45 * http://mpeg.telecomitalialab.com/faq.htm
46 * - the code is quite ugly... maybe I won't do it recursive next time :-)
47 * - seek is not supported with files that contain edit list
49 * Funny I didn't know about http://sourceforge.net/projects/qt-ffmpeg/
50 * when coding this :) (it's a writer anyway)
52 * Reference documents:
53 * http://www.geocities.com/xhelmboyx/quicktime/formats/qtm-layout.txt
55 * http://developer.apple.com/documentation/QuickTime/QTFF/
56 * http://developer.apple.com/documentation/QuickTime/QTFF/qtff.pdf
57 * QuickTime is a trademark of Apple (AFAIK :))
60 #include "qtpalette.h"
66 /* http://gpac.sourceforge.net/tutorial/mediatypes.htm */
67 const CodecTag ff_mov_obj_type[] = {
68 { CODEC_ID_MPEG4 , 32 },
69 { CODEC_ID_H264 , 33 },
70 { CODEC_ID_AAC , 64 },
71 { CODEC_ID_MPEG2VIDEO, 96 }, /* MPEG2 Simple */
72 { CODEC_ID_MPEG2VIDEO, 97 }, /* MPEG2 Main */
73 { CODEC_ID_MPEG2VIDEO, 98 }, /* MPEG2 SNR */
74 { CODEC_ID_MPEG2VIDEO, 99 }, /* MPEG2 Spatial */
75 { CODEC_ID_MPEG2VIDEO, 100 }, /* MPEG2 High */
76 { CODEC_ID_MPEG2VIDEO, 101 }, /* MPEG2 422 */
77 { CODEC_ID_AAC , 102 }, /* MPEG2 AAC Main */
78 { CODEC_ID_AAC , 103 }, /* MPEG2 AAC Low */
79 { CODEC_ID_AAC , 104 }, /* MPEG2 AAC SSR */
80 { CODEC_ID_MP3 , 105 },
81 { CODEC_ID_MPEG1VIDEO, 106 },
82 { CODEC_ID_MP2 , 107 },
83 { CODEC_ID_MJPEG , 108 },
84 { CODEC_ID_PCM_S16LE , 224 },
85 { CODEC_ID_VORBIS , 221 },
86 { CODEC_ID_AC3 , 226 },
87 { CODEC_ID_PCM_ALAW , 227 },
88 { CODEC_ID_PCM_MULAW , 228 },
89 { CODEC_ID_PCM_S16BE , 230 },
90 { CODEC_ID_H263 , 242 },
91 { CODEC_ID_H261 , 243 },
95 static const CodecTag mov_video_tags[] = {
96 /* { CODEC_ID_, MKTAG('c', 'v', 'i', 'd') }, *//* Cinepak */
97 /* { CODEC_ID_H263, MKTAG('r', 'a', 'w', ' ') }, *//* Uncompressed RGB */
98 /* { CODEC_ID_H263, MKTAG('Y', 'u', 'v', '2') }, *//* Uncompressed YUV422 */
99 /* { CODEC_ID_RAWVIDEO, MKTAG('A', 'V', 'U', 'I') }, *//* YUV with alpha-channel (AVID Uncompressed) */
104 { CODEC_ID_MJPEG, MKTAG('j', 'p', 'e', 'g') }, /* PhotoJPEG */
105 { CODEC_ID_MPEG1VIDEO, MKTAG('m', 'p', 'e', 'g') }, /* MPEG */
106 { CODEC_ID_MJPEG, MKTAG('m', 'j', 'p', 'a') }, /* Motion-JPEG (format A) */
107 { CODEC_ID_MJPEGB, MKTAG('m', 'j', 'p', 'b') }, /* Motion-JPEG (format B) */
108 { CODEC_ID_MJPEG, MKTAG('A', 'V', 'D', 'J') }, /* MJPEG with alpha-channel (AVID JFIF meridien compressed) */
109 /* { CODEC_ID_MJPEG, MKTAG('A', 'V', 'R', 'n') }, *//* MJPEG with alpha-channel (AVID ABVB/Truevision NuVista) */
110 /* { CODEC_ID_GIF, MKTAG('g', 'i', 'f', ' ') }, *//* embedded gif files as frames (usually one "click to play movie" frame) */
112 { CODEC_ID_SVQ1, MKTAG('S', 'V', 'Q', '1') }, /* Sorenson Video v1 */
113 { CODEC_ID_SVQ1, MKTAG('s', 'v', 'q', '1') }, /* Sorenson Video v1 */
114 { CODEC_ID_SVQ1, MKTAG('s', 'v', 'q', 'i') }, /* Sorenson Video v1 (from QT specs)*/
115 { CODEC_ID_SVQ3, MKTAG('S', 'V', 'Q', '3') }, /* Sorenson Video v3 */
116 { CODEC_ID_MPEG4, MKTAG('m', 'p', '4', 'v') },
117 { CODEC_ID_MPEG4, MKTAG('D', 'I', 'V', 'X') }, /* OpenDiVX *//* sample files at http://heroinewarrior.com/xmovie.php3 use this tag */
118 { CODEC_ID_MPEG4, MKTAG('X', 'V', 'I', 'D') },
119 { CODEC_ID_MPEG4, MKTAG('3', 'I', 'V', '2') }, /* experimental: 3IVX files before ivx D4 4.5.1 */
120 /* { CODEC_ID_, MKTAG('I', 'V', '5', '0') }, *//* Indeo 5.0 */
121 { CODEC_ID_H263, MKTAG('h', '2', '6', '3') }, /* H263 */
122 { CODEC_ID_H263, MKTAG('s', '2', '6', '3') }, /* H263 ?? works */
123 { CODEC_ID_DVVIDEO, MKTAG('d', 'v', 'c', ' ') }, /* DV NTSC */
124 { CODEC_ID_DVVIDEO, MKTAG('d', 'v', 'c', 'p') }, /* DV PAL */
125 /* { CODEC_ID_DVVIDEO, MKTAG('A', 'V', 'd', 'v') }, *//* AVID dv */
126 { CODEC_ID_VP3, MKTAG('V', 'P', '3', '1') }, /* On2 VP3 */
127 { CODEC_ID_RPZA, MKTAG('r', 'p', 'z', 'a') }, /* Apple Video (RPZA) */
128 { CODEC_ID_CINEPAK, MKTAG('c', 'v', 'i', 'd') }, /* Cinepak */
129 { CODEC_ID_8BPS, MKTAG('8', 'B', 'P', 'S') }, /* Planar RGB (8BPS) */
130 { CODEC_ID_SMC, MKTAG('s', 'm', 'c', ' ') }, /* Apple Graphics (SMC) */
131 { CODEC_ID_QTRLE, MKTAG('r', 'l', 'e', ' ') }, /* Apple Animation (RLE) */
132 { CODEC_ID_QDRAW, MKTAG('q', 'd', 'r', 'w') }, /* QuickDraw */
133 { CODEC_ID_H264, MKTAG('a', 'v', 'c', '1') }, /* AVC-1/H.264 */
134 { CODEC_ID_MPEG2VIDEO, MKTAG('h', 'd', 'v', '2') }, /* MPEG2 produced by Sony HD camera */
135 { CODEC_ID_MPEG2VIDEO, MKTAG('h', 'd', 'v', '3') }, /* HDV produced by FCP */
136 { CODEC_ID_MPEG2VIDEO, MKTAG('m', 'x', '5', 'n') }, /* MPEG2 IMX NTSC 525/60 50mb/s produced by FCP */
137 { CODEC_ID_MPEG2VIDEO, MKTAG('m', 'x', '5', 'p') }, /* MPEG2 IMX PAL 625/50 50mb/s produced by FCP */
138 { CODEC_ID_MPEG2VIDEO, MKTAG('m', 'x', '3', 'n') }, /* MPEG2 IMX NTSC 525/60 30mb/s produced by FCP */
139 { CODEC_ID_MPEG2VIDEO, MKTAG('m', 'x', '3', 'p') }, /* MPEG2 IMX PAL 625/50 30mb/s produced by FCP */
140 { CODEC_ID_DVVIDEO, MKTAG('d', 'v', 'p', 'p') }, /* DVCPRO PAL produced by FCP */
141 //{ CODEC_ID_DVVIDEO, MKTAG('d', 'v', 'h', '5') }, /* DVCPRO HD 50i produced by FCP */
142 //{ CODEC_ID_DVVIDEO, MKTAG('d', 'v', 'h', '6') }, /* DVCPRO HD 60i produced by FCP */
143 { CODEC_ID_DVVIDEO, MKTAG('d', 'v', '5', 'p') }, /* DVCPRO50 PAL produced by FCP */
144 { CODEC_ID_DVVIDEO, MKTAG('d', 'v', '5', 'n') }, /* DVCPRO50 NTSC produced by FCP */
145 { CODEC_ID_DVVIDEO, MKTAG('A', 'V', 'd', 'v') }, /* AVID DV */
146 //{ CODEC_ID_JPEG2000, MKTAG('m', 'j', 'p', '2') }, /* JPEG 2000 produced by FCP */
147 { CODEC_ID_RAWVIDEO, MKTAG('2', 'v', 'u', 'y') }, /* UNCOMPRESSED 8BIT 4:2:2 */
148 { CODEC_ID_NONE, 0 },
151 static const CodecTag mov_audio_tags[] = {
152 { CODEC_ID_PCM_S32BE, MKTAG('i', 'n', '3', '2') },
153 { CODEC_ID_PCM_S24BE, MKTAG('i', 'n', '2', '4') },
154 /* { CODEC_ID_PCM_S16BE, MKTAG('N', 'O', 'N', 'E') }, *//* uncompressed */
155 { CODEC_ID_PCM_S16BE, MKTAG('t', 'w', 'o', 's') }, /* 16 bits */
156 /* { CODEC_ID_PCM_S8, MKTAG('t', 'w', 'o', 's') },*/ /* 8 bits */
157 { CODEC_ID_PCM_U8, MKTAG('r', 'a', 'w', ' ') }, /* 8 bits unsigned */
158 { CODEC_ID_PCM_S16LE, MKTAG('s', 'o', 'w', 't') }, /* */
159 { CODEC_ID_PCM_MULAW, MKTAG('u', 'l', 'a', 'w') }, /* */
160 { CODEC_ID_PCM_ALAW, MKTAG('a', 'l', 'a', 'w') }, /* */
161 { CODEC_ID_ADPCM_IMA_QT, MKTAG('i', 'm', 'a', '4') }, /* IMA-4 ADPCM */
162 { CODEC_ID_ADPCM_MS, MKTAG('m', 's', 0x00, 0x02) }, /* MS ADPCM */
163 { CODEC_ID_MACE3, MKTAG('M', 'A', 'C', '3') }, /* Macintosh Audio Compression and Expansion 3:1 */
164 { CODEC_ID_MACE6, MKTAG('M', 'A', 'C', '6') }, /* Macintosh Audio Compression and Expansion 6:1 */
166 { CODEC_ID_MP2, MKTAG('.', 'm', 'p', '3') }, /* MPEG layer 3 */ /* sample files at http://www.3ivx.com/showcase.html use this tag */
167 { CODEC_ID_MP2, 0x6D730055 }, /* MPEG layer 3 */
168 { CODEC_ID_MP2, 0x5500736D }, /* MPEG layer 3 *//* XXX: check endianness */
169 /* { CODEC_ID_OGG_VORBIS, MKTAG('O', 'g', 'g', 'S') }, *//* sample files at http://heroinewarrior.com/xmovie.php3 use this tag */
171 { CODEC_ID_AAC, MKTAG('m', 'p', '4', 'a') }, /* MPEG-4 AAC */
172 /* The standard for mpeg4 audio is still not normalised AFAIK anyway */
173 { CODEC_ID_AMR_NB, MKTAG('s', 'a', 'm', 'r') }, /* AMR-NB 3gp */
174 { CODEC_ID_AMR_WB, MKTAG('s', 'a', 'w', 'b') }, /* AMR-WB 3gp */
175 { CODEC_ID_AC3, MKTAG('m', 's', 0x20, 0x00) }, /* Dolby AC-3 */
176 { CODEC_ID_ALAC,MKTAG('a', 'l', 'a', 'c') }, /* Apple Lossless */
177 { CODEC_ID_QDM2,MKTAG('Q', 'D', 'M', '2') }, /* QDM2 */
178 { CODEC_ID_NONE, 0 },
181 /* map numeric codes from mdhd atom to ISO 639 */
182 /* cf. QTFileFormat.pdf p253, qtff.pdf p205 */
183 /* http://developer.apple.com/documentation/mac/Text/Text-368.html */
184 /* deprecated by putting the code as 3*5bit ascii */
185 static const char *mov_mdhd_language_map[] = {
187 "eng", "fra", "ger", "ita", "dut", "sve", "spa", "dan", "por", "nor",
188 "heb", "jpn", "ara", "fin", "gre", "ice", "mlt", "tur", "hr "/*scr*/, "chi"/*ace?*/,
189 "urd", "hin", "tha", "kor", "lit", "pol", "hun", "est", "lav", NULL,
190 "fo ", NULL, "rus", "chi", NULL, "iri", "alb", "ron", "ces", "slk",
191 "slv", "yid", "sr ", "mac", "bul", "ukr", "bel", "uzb", "kaz", "aze",
193 "aze", "arm", "geo", "mol", "kir", "tgk", "tuk", "mon", NULL, "pus",
194 "kur", "kas", "snd", "tib", "nep", "san", "mar", "ben", "asm", "guj",
195 "pa ", "ori", "mal", "kan", "tam", "tel", NULL, "bur", "khm", "lao",
197 "vie", "ind", "tgl", "may", "may", "amh", "tir", "orm", "som", "swa",
199 NULL, "run", NULL, "mlg", "epo", NULL, NULL, NULL, NULL, NULL,
201 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
202 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
203 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, "wel", "baq",
204 "cat", "lat", "que", "grn", "aym", "tat", "uig", "dzo", "jav"
207 /* the QuickTime file format is quite convoluted...
208 * it has lots of index tables, each indexing something in another one...
209 * Here we just use what is needed to read the chunks
212 typedef struct MOV_sample_to_chunk_tbl {
216 } MOV_sample_to_chunk_tbl;
221 int64_t size; /* total size (excluding the size and type fields) */
231 typedef struct MOV_mdat_atom_s {
238 uint32_t flags; // 24bit
240 /* 0x03 ESDescrTag */
242 #define MP4ODescrTag 0x01
243 #define MP4IODescrTag 0x02
244 #define MP4ESDescrTag 0x03
245 #define MP4DecConfigDescrTag 0x04
246 #define MP4DecSpecificDescrTag 0x05
247 #define MP4SLConfigDescrTag 0x06
248 #define MP4ContentIdDescrTag 0x07
249 #define MP4SupplContentIdDescrTag 0x08
250 #define MP4IPIPtrDescrTag 0x09
251 #define MP4IPMPPtrDescrTag 0x0A
252 #define MP4IPMPDescrTag 0x0B
253 #define MP4RegistrationDescrTag 0x0D
254 #define MP4ESIDIncDescrTag 0x0E
255 #define MP4ESIDRefDescrTag 0x0F
256 #define MP4FileIODescrTag 0x10
257 #define MP4FileODescrTag 0x11
258 #define MP4ExtProfileLevelDescrTag 0x13
259 #define MP4ExtDescrTagsStart 0x80
260 #define MP4ExtDescrTagsEnd 0xFE
261 uint8_t stream_priority;
263 /* 0x04 DecConfigDescrTag */
264 uint8_t object_type_id;
266 /* XXX: really streamType is
267 * only 6bit, followed by:
271 uint32_t buffer_size_db; // 24
272 uint32_t max_bitrate;
273 uint32_t avg_bitrate;
275 /* 0x05 DecSpecificDescrTag */
276 uint8_t decoder_cfg_len;
277 uint8_t *decoder_cfg;
279 /* 0x06 SLConfigDescrTag */
280 uint8_t sl_config_len;
284 struct MOVParseTableEntry;
286 typedef struct MOVStreamContext {
287 int ffindex; /* the ffmpeg stream id */
290 int64_t *chunk_offsets;
292 Time2Sample *stts_data;
294 Time2Sample *ctts_data;
295 int edit_count; /* number of 'edit' (elst atom) */
296 long sample_to_chunk_sz;
297 MOV_sample_to_chunk_tbl *sample_to_chunk;
298 int sample_to_ctime_index;
299 int sample_to_ctime_sample;
309 AVRational sample_size_v1;
312 typedef struct MOVContext {
313 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) */
316 int64_t duration; /* duration of the longest track */
317 int found_moov; /* when both 'moov' and 'mdat' sections has been found */
318 int found_mdat; /* we suppose we have enough data to read the file */
322 /* some streams listed here aren't presented to the ffmpeg API, since they aren't either video nor audio
323 * but we need the info to be able to skip data from those streams in the 'mdat' section
325 MOVStreamContext *streams[MAX_STREAMS];
328 MOV_ctab_t **ctab; /* color tables */
329 const struct MOVParseTableEntry *parse_table; /* could be eventually used to change the table */
330 /* NOTE: for recursion save to/ restore from local variable! */
332 AVPaletteControl palette_control;
333 MOV_mdat_atom_t *mdat_list;
338 /* XXX: it's the first time I make a recursive parser I think... sorry if it's ugly :P */
340 /* those functions parse an atom */
342 1: found what I wanted, exit
343 0: continue to parse next atom
344 -1: error occured, exit
346 typedef int (*mov_parse_function)(MOVContext *ctx, ByteIOContext *pb, MOV_atom_t atom);
348 /* links atom IDs to parse functions */
349 typedef struct MOVParseTableEntry {
351 mov_parse_function func;
352 } MOVParseTableEntry;
354 static int ff_mov_lang_to_iso639(int code, char *to)
357 /* is it the mangled iso code? */
358 /* see http://www.geocities.com/xhelmboyx/quicktime/formats/mp4-layout.txt */
360 for (i = 2; i >= 0; i--) {
361 to[i] = 0x60 + (code & 0x1f);
366 /* old fashion apple lang code */
367 if (code >= (sizeof(mov_mdhd_language_map)/sizeof(char *)))
369 if (!mov_mdhd_language_map[code])
371 strncpy(to, mov_mdhd_language_map[code], 4);
375 int ff_mov_iso639_to_lang(const char *lang, int mp4)
379 /* old way, only for QT? */
380 for (i = 0; !mp4 && (i < (sizeof(mov_mdhd_language_map)/sizeof(char *))); i++) {
381 if (mov_mdhd_language_map[i] && !strcmp(lang, mov_mdhd_language_map[i]))
384 /* XXX:can we do that in mov too? */
387 /* handle undefined as such */
391 for (i = 0; i < 3; i++) {
392 unsigned char c = (unsigned char)lang[i];
403 static int mov_read_leaf(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
406 url_fskip(pb, atom.size);
407 /* url_seek(pb, atom_offset+atom.size, SEEK_SET); */
411 static int mov_read_default(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
413 int64_t total_size = 0;
418 a.offset = atom.offset;
421 atom.size = 0x7fffffffffffffffLL;
422 while(((total_size + 8) < atom.size) && !url_feof(pb) && !err) {
426 a.size = get_be32(pb);
427 a.type = get_le32(pb);
431 dprintf("type: %08x %.4s sz: %"PRIx64" %"PRIx64" %"PRIx64"\n", a.type, (char*)&a.type, a.size, atom.size, total_size);
432 if (a.size == 1) { /* 64 bit extended size */
433 a.size = get_be64(pb) - 8;
438 a.size = atom.size - total_size;
442 for (i = 0; c->parse_table[i].type != 0L
443 && c->parse_table[i].type != a.type; i++)
451 if (c->parse_table[i].type == 0) { /* skip leaf atoms data */
452 url_fskip(pb, a.size);
454 offset_t start_pos = url_ftell(pb);
456 err = (c->parse_table[i].func)(c, pb, a);
457 left = a.size - url_ftell(pb) + start_pos;
458 if (left > 0) /* skip garbage at atom end */
463 total_size += a.size;
466 if (!err && total_size < atom.size && atom.size < 0x7ffff) {
467 url_fskip(pb, atom.size - total_size);
473 static int mov_read_ctab(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
476 url_fskip(pb, atom.size); // for now
478 VERY VERY BROKEN, NEVER execute this, needs rewrite
481 c->ctab = av_realloc(c->ctab, ++c->ctab_size);
482 t = c->ctab[c->ctab_size];
483 t->seed = get_be32(pb);
484 t->flags = get_be16(pb);
485 t->size = get_be16(pb) + 1;
486 len = 2 * t->size * 4;
488 t->clrs = av_malloc(len); // 16bit A R G B
490 get_buffer(pb, t->clrs, len);
497 static int mov_read_hdlr(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
499 AVStream *st = c->fc->streams[c->fc->nb_streams-1];
504 get_byte(pb); /* version */
505 get_byte(pb); get_byte(pb); get_byte(pb); /* flags */
508 ctype = get_le32(pb);
509 type = get_le32(pb); /* component subtype */
511 dprintf("ctype= %c%c%c%c (0x%08lx)\n", *((char *)&ctype), ((char *)&ctype)[1], ((char *)&ctype)[2], ((char *)&ctype)[3], (long) ctype);
512 dprintf("stype= %c%c%c%c\n", *((char *)&type), ((char *)&type)[1], ((char *)&type)[2], ((char *)&type)[3]);
513 if(ctype == MKTAG('m', 'h', 'l', 'r')) /* MOV */
517 if(type == MKTAG('v', 'i', 'd', 'e'))
518 st->codec->codec_type = CODEC_TYPE_VIDEO;
519 else if(type == MKTAG('s', 'o', 'u', 'n'))
520 st->codec->codec_type = CODEC_TYPE_AUDIO;
521 get_be32(pb); /* component manufacture */
522 get_be32(pb); /* component flags */
523 get_be32(pb); /* component flags mask */
526 return 0; /* nothing left to read */
527 /* XXX: MP4 uses a C string, not a pascal one */
532 while(get_byte(pb) && (++len < (atom.size - 24)));
534 /* .mov: PASCAL string */
539 url_fskip(pb, atom.size - (url_ftell(pb) - atom.offset));
543 static int mov_mp4_read_descr_len(ByteIOContext *pb)
548 int c = get_byte(pb);
549 len = (len << 7) | (c & 0x7f);
556 static int mov_mp4_read_descr(ByteIOContext *pb, int *tag)
560 len = mov_mp4_read_descr_len(pb);
561 dprintf("MPEG4 description: tag=0x%02x len=%d\n", *tag, len);
565 static int mov_read_esds(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
567 AVStream *st = c->fc->streams[c->fc->nb_streams-1];
568 MOVStreamContext *sc = (MOVStreamContext *)st->priv_data;
571 /* Well, broken but suffisant for some MP4 streams */
572 get_be32(pb); /* version + flags */
573 len = mov_mp4_read_descr(pb, &tag);
574 if (tag == MP4ESDescrTag) {
575 get_be16(pb); /* ID */
576 get_byte(pb); /* priority */
578 get_be16(pb); /* ID */
580 len = mov_mp4_read_descr(pb, &tag);
581 if (tag == MP4DecConfigDescrTag) {
582 sc->esds.object_type_id = get_byte(pb);
583 sc->esds.stream_type = get_byte(pb);
584 sc->esds.buffer_size_db = get_be24(pb);
585 sc->esds.max_bitrate = get_be32(pb);
586 sc->esds.avg_bitrate = get_be32(pb);
588 st->codec->codec_id= codec_get_id(ff_mov_obj_type, sc->esds.object_type_id);
589 len = mov_mp4_read_descr(pb, &tag);
590 if (tag == MP4DecSpecificDescrTag) {
591 dprintf("Specific MPEG4 header len=%d\n", len);
592 st->codec->extradata = (uint8_t*) av_mallocz(len + FF_INPUT_BUFFER_PADDING_SIZE);
593 if (st->codec->extradata) {
594 get_buffer(pb, st->codec->extradata, len);
595 st->codec->extradata_size = len;
597 if ((*(uint8_t *)st->codec->extradata >> 3) == 29) {
598 st->codec->codec_id = CODEC_ID_MP3ON4;
606 /* this atom contains actual media data */
607 static int mov_read_mdat(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
609 if(atom.size == 0) /* wrong one (MP4) */
611 c->mdat_list = av_realloc(c->mdat_list, (c->mdat_count + 1) * sizeof(*c->mdat_list));
612 c->mdat_list[c->mdat_count].offset = atom.offset;
613 c->mdat_list[c->mdat_count].size = atom.size;
616 c->mdat_offset = atom.offset;
617 c->mdat_size = atom.size;
619 return 1; /* found both, just go */
620 url_fskip(pb, atom.size);
621 return 0; /* now go for moov */
624 static int mov_read_ftyp(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
626 uint32_t type = get_le32(pb);
630 case MKTAG('i', 's', 'o', 'm'):
631 case MKTAG('m', 'p', '4', '1'):
632 case MKTAG('m', 'p', '4', '2'):
633 case MKTAG('3', 'g', 'p', '1'):
634 case MKTAG('3', 'g', 'p', '2'):
635 case MKTAG('3', 'g', '2', 'a'):
636 case MKTAG('3', 'g', 'p', '3'):
637 case MKTAG('3', 'g', 'p', '4'):
638 case MKTAG('3', 'g', 'p', '5'):
639 case MKTAG('m', 'm', 'p', '4'): /* Mobile MP4 */
640 case MKTAG('M', '4', 'A', ' '): /* Apple iTunes AAC-LC Audio */
641 case MKTAG('M', '4', 'P', ' '): /* Apple iTunes AAC-LC Protected Audio */
642 case MKTAG('m', 'j', 'p', '2'): /* Motion Jpeg 2000 */
644 case MKTAG('q', 't', ' ', ' '):
646 av_log(c->fc, AV_LOG_DEBUG, "ISO: File Type Major Brand: %.4s\n",(char *)&type);
648 get_be32(pb); /* minor version */
649 url_fskip(pb, atom.size - 8);
653 /* this atom should contain all header atoms */
654 static int mov_read_moov(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
658 err = mov_read_default(c, pb, atom);
659 /* we parsed the 'moov' atom, we can terminate the parsing as soon as we find the 'mdat' */
660 /* so we don't parse the whole file if over a network */
663 return 1; /* found both, just go */
664 return 0; /* now go for mdat */
668 static int mov_read_mdhd(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
670 AVStream *st = c->fc->streams[c->fc->nb_streams-1];
671 MOVStreamContext *sc = (MOVStreamContext *)st->priv_data;
672 int version = get_byte(pb);
676 return 1; /* unsupported */
678 get_byte(pb); get_byte(pb);
679 get_byte(pb); /* flags */
685 get_be32(pb); /* creation time */
686 get_be32(pb); /* modification time */
689 sc->time_scale = get_be32(pb);
690 st->duration = (version == 1) ? get_be64(pb) : get_be32(pb); /* duration */
692 lang = get_be16(pb); /* language */
693 ff_mov_lang_to_iso639(lang, st->language);
694 get_be16(pb); /* quality */
699 static int mov_read_mvhd(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
701 int version = get_byte(pb); /* version */
702 get_byte(pb); get_byte(pb); get_byte(pb); /* flags */
708 get_be32(pb); /* creation time */
709 get_be32(pb); /* modification time */
711 c->time_scale = get_be32(pb); /* time scale */
713 av_log(NULL, AV_LOG_DEBUG, "time scale = %i\n", c->time_scale);
715 c->duration = (version == 1) ? get_be64(pb) : get_be32(pb); /* duration */
716 get_be32(pb); /* preferred scale */
718 get_be16(pb); /* preferred volume */
720 url_fskip(pb, 10); /* reserved */
722 url_fskip(pb, 36); /* display matrix */
724 get_be32(pb); /* preview time */
725 get_be32(pb); /* preview duration */
726 get_be32(pb); /* poster time */
727 get_be32(pb); /* selection time */
728 get_be32(pb); /* selection duration */
729 get_be32(pb); /* current time */
730 get_be32(pb); /* next track ID */
735 static int mov_read_smi(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
737 AVStream *st = c->fc->streams[c->fc->nb_streams-1];
739 if((uint64_t)atom.size > (1<<30))
742 // currently SVQ3 decoder expect full STSD header - so let's fake it
743 // this should be fixed and just SMI header should be passed
744 av_free(st->codec->extradata);
745 st->codec->extradata_size = 0x5a + atom.size;
746 st->codec->extradata = (uint8_t*) av_mallocz(st->codec->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE);
748 if (st->codec->extradata) {
749 strcpy(st->codec->extradata, "SVQ3"); // fake
750 get_buffer(pb, st->codec->extradata + 0x5a, atom.size);
751 dprintf("Reading SMI %"PRId64" %s\n", atom.size, (char*)st->codec->extradata + 0x5a);
753 url_fskip(pb, atom.size);
758 static int mov_read_enda(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
760 AVStream *st = c->fc->streams[c->fc->nb_streams-1];
761 int little_endian = get_be16(pb);
764 switch (st->codec->codec_id) {
765 case CODEC_ID_PCM_S24BE:
766 st->codec->codec_id = CODEC_ID_PCM_S24LE;
768 case CODEC_ID_PCM_S32BE:
769 st->codec->codec_id = CODEC_ID_PCM_S32LE;
778 static int mov_read_alac(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
780 AVStream *st = c->fc->streams[c->fc->nb_streams-1];
782 // currently ALAC decoder expect full atom header - so let's fake it
783 // this should be fixed and just ALAC header should be passed
785 av_free(st->codec->extradata);
786 st->codec->extradata_size = 36;
787 st->codec->extradata = (uint8_t*) av_mallocz(st->codec->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE);
789 if (st->codec->extradata) {
790 strcpy(st->codec->extradata + 4, "alac"); // fake
791 get_buffer(pb, st->codec->extradata + 8, 36 - 8);
792 dprintf("Reading alac %d %s\n", st->codec->extradata_size, (char*)st->codec->extradata);
794 url_fskip(pb, atom.size);
798 static int mov_read_wave(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
800 AVStream *st = c->fc->streams[c->fc->nb_streams-1];
802 if((uint64_t)atom.size > (1<<30))
805 if (st->codec->codec_id == CODEC_ID_QDM2) {
806 // pass all frma atom to codec, needed at least for QDM2
807 av_free(st->codec->extradata);
808 st->codec->extradata_size = atom.size;
809 st->codec->extradata = (uint8_t*) av_mallocz(st->codec->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE);
811 if (st->codec->extradata) {
812 get_buffer(pb, st->codec->extradata, atom.size);
814 url_fskip(pb, atom.size);
815 } else if (atom.size > 8) { /* to read frma, esds atoms */
816 mov_read_default(c, pb, atom);
818 url_fskip(pb, atom.size);
822 static int mov_read_jp2h(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
824 AVStream *st = c->fc->streams[c->fc->nb_streams-1];
826 if((uint64_t)atom.size > (1<<30))
829 av_free(st->codec->extradata);
831 st->codec->extradata_size = atom.size + 8;
832 st->codec->extradata = (uint8_t*) av_mallocz(st->codec->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE);
834 /* pass all jp2h atom to codec */
835 if (st->codec->extradata) {
836 strcpy(st->codec->extradata + 4, "jp2h");
837 get_buffer(pb, st->codec->extradata + 8, atom.size);
839 url_fskip(pb, atom.size);
843 static int mov_read_avcC(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
845 AVStream *st = c->fc->streams[c->fc->nb_streams-1];
847 if((uint64_t)atom.size > (1<<30))
850 av_free(st->codec->extradata);
852 st->codec->extradata_size = atom.size;
853 st->codec->extradata = (uint8_t*) av_mallocz(st->codec->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE);
855 if (st->codec->extradata) {
856 get_buffer(pb, st->codec->extradata, atom.size);
858 url_fskip(pb, atom.size);
863 static int mov_read_stco(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
865 AVStream *st = c->fc->streams[c->fc->nb_streams-1];
866 MOVStreamContext *sc = (MOVStreamContext *)st->priv_data;
867 unsigned int i, entries;
869 get_byte(pb); /* version */
870 get_byte(pb); get_byte(pb); get_byte(pb); /* flags */
872 entries = get_be32(pb);
874 if(entries >= UINT_MAX/sizeof(int64_t))
877 sc->chunk_count = entries;
878 sc->chunk_offsets = (int64_t*) av_malloc(entries * sizeof(int64_t));
879 if (!sc->chunk_offsets)
881 if (atom.type == MKTAG('s', 't', 'c', 'o')) {
882 for(i=0; i<entries; i++) {
883 sc->chunk_offsets[i] = get_be32(pb);
885 } else if (atom.type == MKTAG('c', 'o', '6', '4')) {
886 for(i=0; i<entries; i++) {
887 sc->chunk_offsets[i] = get_be64(pb);
895 static int mov_read_stsd(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
897 AVStream *st = c->fc->streams[c->fc->nb_streams-1];
898 MOVStreamContext *sc = (MOVStreamContext *)st->priv_data;
899 int entries, frames_per_sample;
901 uint8_t codec_name[32];
903 /* for palette traversal */
911 unsigned char *color_table;
913 unsigned char r, g, b;
915 get_byte(pb); /* version */
916 get_byte(pb); get_byte(pb); get_byte(pb); /* flags */
918 entries = get_be32(pb);
920 while(entries--) { //Parsing Sample description table
922 MOV_atom_t a = { 0, 0, 0 };
923 offset_t start_pos = url_ftell(pb);
924 int size = get_be32(pb); /* size */
925 format = get_le32(pb); /* data format */
927 get_be32(pb); /* reserved */
928 get_be16(pb); /* reserved */
929 get_be16(pb); /* index */
931 if (st->codec->codec_tag) {
932 /* multiple fourcc, just skip for now */
933 url_fskip(pb, size - (url_ftell(pb) - start_pos));
937 st->codec->codec_tag = format;
938 id = codec_get_id(mov_audio_tags, format);
940 st->codec->codec_type = CODEC_TYPE_AUDIO;
941 } else if (format && format != MKTAG('m', 'p', '4', 's')) { /* skip old asf mpeg4 tag */
942 id = codec_get_id(mov_video_tags, format);
944 id = codec_get_id(codec_bmp_tags, format);
946 st->codec->codec_type = CODEC_TYPE_VIDEO;
949 dprintf("size=%d 4CC= %c%c%c%c codec_type=%d\n",
951 (format >> 0) & 0xff, (format >> 8) & 0xff, (format >> 16) & 0xff, (format >> 24) & 0xff,
952 st->codec->codec_type);
954 if(st->codec->codec_type==CODEC_TYPE_VIDEO) {
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 */
962 st->codec->width = get_be16(pb); /* width */
963 st->codec->height = get_be16(pb); /* height */
965 get_be32(pb); /* horiz resolution */
966 get_be32(pb); /* vert resolution */
967 get_be32(pb); /* data size, always 0 */
968 frames_per_sample = get_be16(pb); /* frames per samples */
970 av_log(NULL, AV_LOG_DEBUG, "frames/samples = %d\n", frames_per_sample);
972 get_buffer(pb, codec_name, 32); /* codec name, pascal string (FIXME: true for mp4?) */
973 if (codec_name[0] <= 31) {
974 memcpy(st->codec->codec_name, &codec_name[1],codec_name[0]);
975 st->codec->codec_name[codec_name[0]] = 0;
978 st->codec->bits_per_sample = get_be16(pb); /* depth */
979 st->codec->color_table_id = get_be16(pb); /* colortable id */
981 /* figure out the palette situation */
982 color_depth = st->codec->bits_per_sample & 0x1F;
983 color_greyscale = st->codec->bits_per_sample & 0x20;
985 /* if the depth is 2, 4, or 8 bpp, file is palettized */
986 if ((color_depth == 2) || (color_depth == 4) ||
987 (color_depth == 8)) {
989 if (color_greyscale) {
991 /* compute the greyscale palette */
992 color_count = 1 << color_depth;
994 color_dec = 256 / (color_count - 1);
995 for (j = 0; j < color_count; j++) {
996 r = g = b = color_index;
997 c->palette_control.palette[j] =
998 (r << 16) | (g << 8) | (b);
999 color_index -= color_dec;
1000 if (color_index < 0)
1004 } else if (st->codec->color_table_id & 0x08) {
1006 /* if flag bit 3 is set, use the default palette */
1007 color_count = 1 << color_depth;
1008 if (color_depth == 2)
1009 color_table = ff_qt_default_palette_4;
1010 else if (color_depth == 4)
1011 color_table = ff_qt_default_palette_16;
1013 color_table = ff_qt_default_palette_256;
1015 for (j = 0; j < color_count; j++) {
1016 r = color_table[j * 4 + 0];
1017 g = color_table[j * 4 + 1];
1018 b = color_table[j * 4 + 2];
1019 c->palette_control.palette[j] =
1020 (r << 16) | (g << 8) | (b);
1025 /* load the palette from the file */
1026 color_start = get_be32(pb);
1027 color_count = get_be16(pb);
1028 color_end = get_be16(pb);
1029 for (j = color_start; j <= color_end; j++) {
1030 /* each R, G, or B component is 16 bits;
1031 * only use the top 8 bits; skip alpha bytes
1041 c->palette_control.palette[j] =
1042 (r << 16) | (g << 8) | (b);
1046 st->codec->palctrl = &c->palette_control;
1047 st->codec->palctrl->palette_changed = 1;
1049 st->codec->palctrl = NULL;
1050 } else if(st->codec->codec_type==CODEC_TYPE_AUDIO) {
1051 int bits_per_sample;
1052 uint16_t version = get_be16(pb);
1054 st->codec->codec_id = id;
1055 get_be16(pb); /* revision level */
1056 get_be32(pb); /* vendor */
1058 st->codec->channels = get_be16(pb); /* channel count */
1059 st->codec->bits_per_sample = get_be16(pb); /* sample size */
1060 /* do we need to force to 16 for AMR ? */
1062 /* handle specific s8 codec */
1063 get_be16(pb); /* compression id = 0*/
1064 get_be16(pb); /* packet size = 0 */
1066 st->codec->sample_rate = ((get_be32(pb) >> 16));
1068 switch (st->codec->codec_id) {
1069 case CODEC_ID_PCM_S8:
1070 case CODEC_ID_PCM_U8:
1071 if (st->codec->bits_per_sample == 16)
1072 st->codec->codec_id = CODEC_ID_PCM_S16BE;
1074 case CODEC_ID_PCM_S16LE:
1075 case CODEC_ID_PCM_S16BE:
1076 if (st->codec->bits_per_sample == 8)
1077 st->codec->codec_id = CODEC_ID_PCM_S8;
1079 case CODEC_ID_AMR_WB:
1080 st->codec->sample_rate = 16000; /* should really we ? */
1081 st->codec->channels=1; /* really needed */
1083 case CODEC_ID_AMR_NB:
1084 st->codec->sample_rate = 8000; /* should really we ? */
1085 st->codec->channels=1; /* really needed */
1091 bits_per_sample = av_get_bits_per_sample(st->codec->codec_id);
1092 if (bits_per_sample) {
1093 st->codec->bits_per_sample = bits_per_sample;
1094 sc->sample_size = (bits_per_sample >> 3) * st->codec->channels;
1097 //Read QT version 1 fields. In version 0 theese dont exist
1098 dprintf("version =%d mp4=%d\n",version,c->mp4);
1100 sc->sample_size_v1.den = get_be32(pb); /* samples per packet */
1101 get_be32(pb); /* bytes per packet */
1102 sc->sample_size_v1.num = get_be32(pb); /* bytes per frame */
1103 get_be32(pb); /* bytes per sample */
1104 } else if(version==2) {
1105 get_be32(pb); /* sizeof struct only */
1106 st->codec->sample_rate = av_int2dbl(get_be64(pb)); /* float 64 */
1107 st->codec->channels = get_be32(pb);
1108 get_be32(pb); /* always 0x7F000000 */
1109 get_be32(pb); /* bits per channel if sound is uncompressed */
1110 get_be32(pb); /* lcpm format specific flag */
1111 get_be32(pb); /* bytes per audio packet if constant */
1112 get_be32(pb); /* lpcm frames per audio packet if constant */
1115 /* other codec type, just skip (rtp, mp4s, tmcd ...) */
1116 url_fskip(pb, size - (url_ftell(pb) - start_pos));
1118 /* this will read extra atoms at the end (wave, alac, damr, avcC, SMI ...) */
1119 a.size = size - (url_ftell(pb) - start_pos);
1121 mov_read_default(c, pb, a);
1122 else if (a.size > 0)
1123 url_fskip(pb, a.size);
1126 if(st->codec->codec_type==CODEC_TYPE_AUDIO && st->codec->sample_rate==0 && sc->time_scale>1) {
1127 st->codec->sample_rate= sc->time_scale;
1130 switch (st->codec->codec_id) {
1134 #ifdef CONFIG_VORBIS_DECODER
1135 case CODEC_ID_VORBIS:
1137 case CODEC_ID_MP3ON4:
1138 st->codec->sample_rate= 0; /* let decoder init parameters properly */
1147 static int mov_read_stsc(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
1149 AVStream *st = c->fc->streams[c->fc->nb_streams-1];
1150 MOVStreamContext *sc = (MOVStreamContext *)st->priv_data;
1151 unsigned int i, entries;
1153 get_byte(pb); /* version */
1154 get_byte(pb); get_byte(pb); get_byte(pb); /* flags */
1156 entries = get_be32(pb);
1158 if(entries >= UINT_MAX / sizeof(MOV_sample_to_chunk_tbl))
1162 av_log(NULL, AV_LOG_DEBUG, "track[%i].stsc.entries = %i\n", c->fc->nb_streams-1, entries);
1164 sc->sample_to_chunk_sz = entries;
1165 sc->sample_to_chunk = (MOV_sample_to_chunk_tbl*) av_malloc(entries * sizeof(MOV_sample_to_chunk_tbl));
1166 if (!sc->sample_to_chunk)
1168 for(i=0; i<entries; i++) {
1169 sc->sample_to_chunk[i].first = get_be32(pb);
1170 sc->sample_to_chunk[i].count = get_be32(pb);
1171 sc->sample_to_chunk[i].id = get_be32(pb);
1176 static int mov_read_stss(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
1178 AVStream *st = c->fc->streams[c->fc->nb_streams-1];
1179 MOVStreamContext *sc = (MOVStreamContext *)st->priv_data;
1180 unsigned int i, entries;
1182 get_byte(pb); /* version */
1183 get_byte(pb); get_byte(pb); get_byte(pb); /* flags */
1185 entries = get_be32(pb);
1187 if(entries >= UINT_MAX / sizeof(long))
1190 sc->keyframe_count = entries;
1192 av_log(NULL, AV_LOG_DEBUG, "keyframe_count = %ld\n", sc->keyframe_count);
1194 sc->keyframes = (long*) av_malloc(entries * sizeof(long));
1197 for(i=0; i<entries; i++) {
1198 sc->keyframes[i] = get_be32(pb);
1200 /* av_log(NULL, AV_LOG_DEBUG, "keyframes[]=%ld\n", sc->keyframes[i]); */
1206 static int mov_read_stsz(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
1208 AVStream *st = c->fc->streams[c->fc->nb_streams-1];
1209 MOVStreamContext *sc = (MOVStreamContext *)st->priv_data;
1210 unsigned int i, entries, sample_size;
1212 get_byte(pb); /* version */
1213 get_byte(pb); get_byte(pb); get_byte(pb); /* flags */
1215 sample_size = get_be32(pb);
1216 if (!sc->sample_size) /* do not overwrite value computed in stsd */
1217 sc->sample_size = sample_size;
1218 entries = get_be32(pb);
1219 if(entries >= UINT_MAX / sizeof(long))
1222 sc->sample_count = entries;
1227 av_log(NULL, AV_LOG_DEBUG, "sample_size = %ld sample_count = %ld\n", sc->sample_size, sc->sample_count);
1229 sc->sample_sizes = (long*) av_malloc(entries * sizeof(long));
1230 if (!sc->sample_sizes)
1232 for(i=0; i<entries; i++) {
1233 sc->sample_sizes[i] = get_be32(pb);
1235 av_log(NULL, AV_LOG_DEBUG, "sample_sizes[]=%ld\n", sc->sample_sizes[i]);
1241 static int mov_read_stts(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
1243 AVStream *st = c->fc->streams[c->fc->nb_streams-1];
1244 MOVStreamContext *sc = (MOVStreamContext *)st->priv_data;
1245 unsigned int i, entries;
1247 int64_t total_sample_count=0;
1249 get_byte(pb); /* version */
1250 get_byte(pb); get_byte(pb); get_byte(pb); /* flags */
1251 entries = get_be32(pb);
1252 if(entries >= UINT_MAX / sizeof(Time2Sample))
1255 sc->stts_count = entries;
1256 sc->stts_data = av_malloc(entries * sizeof(Time2Sample));
1259 av_log(NULL, AV_LOG_DEBUG, "track[%i].stts.entries = %i\n", c->fc->nb_streams-1, entries);
1264 for(i=0; i<entries; i++) {
1265 int sample_duration;
1268 sample_count=get_be32(pb);
1269 sample_duration = get_be32(pb);
1270 sc->stts_data[i].count= sample_count;
1271 sc->stts_data[i].duration= sample_duration;
1273 sc->time_rate= ff_gcd(sc->time_rate, sample_duration);
1275 dprintf("sample_count=%d, sample_duration=%d\n",sample_count,sample_duration);
1277 duration+=(int64_t)sample_duration*sample_count;
1278 total_sample_count+=sample_count;
1281 st->nb_frames= total_sample_count;
1283 st->duration= duration;
1287 static int mov_read_ctts(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
1289 AVStream *st = c->fc->streams[c->fc->nb_streams-1];
1290 MOVStreamContext *sc = (MOVStreamContext *)st->priv_data;
1291 unsigned int i, entries;
1293 get_byte(pb); /* version */
1294 get_byte(pb); get_byte(pb); get_byte(pb); /* flags */
1295 entries = get_be32(pb);
1296 if(entries >= UINT_MAX / sizeof(Time2Sample))
1299 sc->ctts_count = entries;
1300 sc->ctts_data = av_malloc(entries * sizeof(Time2Sample));
1302 dprintf("track[%i].ctts.entries = %i\n", c->fc->nb_streams-1, entries);
1304 for(i=0; i<entries; i++) {
1305 int count =get_be32(pb);
1306 int duration =get_be32(pb);
1309 av_log(c->fc, AV_LOG_ERROR, "negative ctts, ignoring\n");
1311 url_fskip(pb, 8 * (entries - i - 1));
1314 sc->ctts_data[i].count = count;
1315 sc->ctts_data[i].duration= duration;
1317 sc->time_rate= ff_gcd(sc->time_rate, duration);
1322 static int mov_read_trak(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
1325 MOVStreamContext *sc;
1327 st = av_new_stream(c->fc, c->fc->nb_streams);
1329 sc = (MOVStreamContext*) av_mallocz(sizeof(MOVStreamContext));
1336 st->codec->codec_type = CODEC_TYPE_DATA;
1337 st->start_time = 0; /* XXX: check */
1338 c->streams[c->fc->nb_streams-1] = sc;
1340 return mov_read_default(c, pb, atom);
1343 static int mov_read_tkhd(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
1345 AVStream *st = c->fc->streams[c->fc->nb_streams-1];
1346 int version = get_byte(pb);
1348 get_byte(pb); get_byte(pb);
1349 get_byte(pb); /* flags */
1351 MOV_TRACK_ENABLED 0x0001
1352 MOV_TRACK_IN_MOVIE 0x0002
1353 MOV_TRACK_IN_PREVIEW 0x0004
1354 MOV_TRACK_IN_POSTER 0x0008
1361 get_be32(pb); /* creation time */
1362 get_be32(pb); /* modification time */
1364 st->id = (int)get_be32(pb); /* track id (NOT 0 !)*/
1365 get_be32(pb); /* reserved */
1366 st->start_time = 0; /* check */
1367 (version == 1) ? get_be64(pb) : get_be32(pb); /* highlevel (considering edits) duration in movie timebase */
1368 get_be32(pb); /* reserved */
1369 get_be32(pb); /* reserved */
1371 get_be16(pb); /* layer */
1372 get_be16(pb); /* alternate group */
1373 get_be16(pb); /* volume */
1374 get_be16(pb); /* reserved */
1376 url_fskip(pb, 36); /* display matrix */
1378 /* those are fixed-point */
1379 get_be32(pb); /* track width */
1380 get_be32(pb); /* track height */
1385 /* this atom should be null (from specs), but some buggy files put the 'moov' atom inside it... */
1386 /* like the files created with Adobe Premiere 5.0, for samples see */
1387 /* http://graphics.tudelft.nl/~wouter/publications/soundtests/ */
1388 static int mov_read_wide(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
1393 return 0; /* continue */
1394 if (get_be32(pb) != 0) { /* 0 sized mdat atom... use the 'wide' atom size */
1395 url_fskip(pb, atom.size - 4);
1398 atom.type = get_le32(pb);
1401 if (atom.type != MKTAG('m', 'd', 'a', 't')) {
1402 url_fskip(pb, atom.size);
1405 err = mov_read_mdat(c, pb, atom);
1411 static int null_read_packet(void *opaque, uint8_t *buf, int buf_size)
1416 static int mov_read_cmov(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
1420 uint8_t *moov_data; /* uncompressed data */
1421 long cmov_len, moov_len;
1424 get_be32(pb); /* dcom atom */
1425 if (get_le32(pb) != MKTAG( 'd', 'c', 'o', 'm' ))
1427 if (get_le32(pb) != MKTAG( 'z', 'l', 'i', 'b' )) {
1428 av_log(NULL, AV_LOG_ERROR, "unknown compression for cmov atom !");
1431 get_be32(pb); /* cmvd atom */
1432 if (get_le32(pb) != MKTAG( 'c', 'm', 'v', 'd' ))
1434 moov_len = get_be32(pb); /* uncompressed size */
1435 cmov_len = atom.size - 6 * 4;
1437 cmov_data = (uint8_t *) av_malloc(cmov_len);
1440 moov_data = (uint8_t *) av_malloc(moov_len);
1445 get_buffer(pb, cmov_data, cmov_len);
1446 if(uncompress (moov_data, (uLongf *) &moov_len, (const Bytef *)cmov_data, cmov_len) != Z_OK)
1448 if(init_put_byte(&ctx, moov_data, moov_len, 0, NULL, null_read_packet, NULL, NULL) != 0)
1450 ctx.buf_end = ctx.buffer + moov_len;
1451 atom.type = MKTAG( 'm', 'o', 'o', 'v' );
1453 atom.size = moov_len;
1455 // { int fd = open("/tmp/uncompheader.mov", O_WRONLY | O_CREAT); write(fd, moov_data, moov_len); close(fd); }
1457 ret = mov_read_default(c, &ctx, atom);
1465 /* edit list atom */
1466 static int mov_read_elst(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
1470 get_byte(pb); /* version */
1471 get_byte(pb); get_byte(pb); get_byte(pb); /* flags */
1472 edit_count= c->streams[c->fc->nb_streams-1]->edit_count = get_be32(pb); /* entries */
1474 for(i=0; i<edit_count; i++){
1475 get_be32(pb); /* Track duration */
1476 get_be32(pb); /* Media time */
1477 get_be32(pb); /* Media rate */
1479 dprintf("track[%i].edit_count = %i\n", c->fc->nb_streams-1, c->streams[c->fc->nb_streams-1]->edit_count);
1483 static const MOVParseTableEntry mov_default_parse_table[] = {
1485 { MKTAG( 'c', 'o', '6', '4' ), mov_read_stco },
1486 { MKTAG( 'c', 'p', 'r', 't' ), mov_read_default },
1487 { MKTAG( 'c', 'r', 'h', 'd' ), mov_read_default },
1488 { MKTAG( 'c', 't', 't', 's' ), mov_read_ctts }, /* composition time to sample */
1489 { MKTAG( 'd', 'i', 'n', 'f' ), mov_read_default }, /* data information */
1490 { MKTAG( 'd', 'p', 'n', 'd' ), mov_read_leaf },
1491 { MKTAG( 'd', 'r', 'e', 'f' ), mov_read_leaf },
1492 { MKTAG( 'e', 'd', 't', 's' ), mov_read_default },
1493 { MKTAG( 'e', 'l', 's', 't' ), mov_read_elst },
1494 { MKTAG( 'e', 'n', 'd', 'a' ), mov_read_enda },
1495 { MKTAG( 'f', 'r', 'e', 'e' ), mov_read_leaf },
1496 { MKTAG( 'f', 't', 'y', 'p' ), mov_read_ftyp },
1497 { MKTAG( 'h', 'd', 'l', 'r' ), mov_read_hdlr },
1498 { MKTAG( 'h', 'i', 'n', 't' ), mov_read_leaf },
1499 { MKTAG( 'h', 'm', 'h', 'd' ), mov_read_leaf },
1500 { MKTAG( 'i', 'o', 'd', 's' ), mov_read_leaf },
1501 { MKTAG( 'j', 'p', '2', 'h' ), mov_read_jp2h },
1502 { MKTAG( 'm', 'd', 'a', 't' ), mov_read_mdat },
1503 { MKTAG( 'm', 'd', 'h', 'd' ), mov_read_mdhd },
1504 { MKTAG( 'm', 'd', 'i', 'a' ), mov_read_default },
1505 { MKTAG( 'm', 'i', 'n', 'f' ), mov_read_default },
1506 { MKTAG( 'm', 'o', 'o', 'v' ), mov_read_moov },
1507 { MKTAG( 'm', 'p', '4', 'a' ), mov_read_default },
1508 { MKTAG( 'm', 'p', '4', 's' ), mov_read_default },
1509 { MKTAG( 'm', 'p', '4', 'v' ), mov_read_default },
1510 { MKTAG( 'm', 'p', 'o', 'd' ), mov_read_leaf },
1511 { MKTAG( 'm', 'v', 'h', 'd' ), mov_read_mvhd },
1512 { MKTAG( 'n', 'm', 'h', 'd' ), mov_read_leaf },
1513 { MKTAG( 'o', 'd', 'h', 'd' ), mov_read_default },
1514 { MKTAG( 's', 'd', 'h', 'd' ), mov_read_default },
1515 { MKTAG( 's', 'k', 'i', 'p' ), mov_read_leaf },
1516 { MKTAG( 's', 'm', 'h', 'd' ), mov_read_leaf }, /* sound media info header */
1517 { MKTAG( 'S', 'M', 'I', ' ' ), mov_read_smi }, /* Sorenson extension ??? */
1518 { MKTAG( 'a', 'l', 'a', 'c' ), mov_read_alac }, /* alac specific atom */
1519 { MKTAG( 'a', 'v', 'c', 'C' ), mov_read_avcC },
1520 { MKTAG( 's', 't', 'b', 'l' ), mov_read_default },
1521 { MKTAG( 's', 't', 'c', 'o' ), mov_read_stco },
1522 { MKTAG( 's', 't', 'd', 'p' ), mov_read_default },
1523 { MKTAG( 's', 't', 's', 'c' ), mov_read_stsc },
1524 { MKTAG( 's', 't', 's', 'd' ), mov_read_stsd }, /* sample description */
1525 { MKTAG( 's', 't', 's', 'h' ), mov_read_default },
1526 { MKTAG( 's', 't', 's', 's' ), mov_read_stss }, /* sync sample */
1527 { MKTAG( 's', 't', 's', 'z' ), mov_read_stsz }, /* sample size */
1528 { MKTAG( 's', 't', 't', 's' ), mov_read_stts },
1529 { MKTAG( 't', 'k', 'h', 'd' ), mov_read_tkhd }, /* track header */
1530 { MKTAG( 't', 'r', 'a', 'k' ), mov_read_trak },
1531 { MKTAG( 't', 'r', 'e', 'f' ), mov_read_default }, /* not really */
1532 { MKTAG( 'u', 'd', 't', 'a' ), mov_read_leaf },
1533 { MKTAG( 'u', 'r', 'l', ' ' ), mov_read_leaf },
1534 { MKTAG( 'u', 'r', 'n', ' ' ), mov_read_leaf },
1535 { MKTAG( 'u', 'u', 'i', 'd' ), mov_read_leaf },
1536 { MKTAG( 'v', 'm', 'h', 'd' ), mov_read_leaf }, /* video media info header */
1537 { MKTAG( 'w', 'a', 'v', 'e' ), mov_read_wave },
1539 { MKTAG( 'M', 'D', 'E', 'S' ), mov_read_leaf },
1541 { MKTAG( 'c', 'h', 'a', 'p' ), mov_read_leaf },
1542 { MKTAG( 'c', 'l', 'i', 'p' ), mov_read_default },
1543 { MKTAG( 'c', 'r', 'g', 'n' ), mov_read_leaf },
1544 { MKTAG( 'c', 't', 'a', 'b' ), mov_read_ctab },
1545 { MKTAG( 'e', 's', 'd', 's' ), mov_read_esds },
1546 { MKTAG( 'k', 'm', 'a', 't' ), mov_read_leaf },
1547 { MKTAG( 'm', 'a', 't', 't' ), mov_read_default },
1548 { MKTAG( 'r', 'd', 'r', 'f' ), mov_read_leaf },
1549 { MKTAG( 'r', 'm', 'd', 'a' ), mov_read_default },
1550 { MKTAG( 'r', 'm', 'd', 'r' ), mov_read_leaf },
1551 { MKTAG( 'r', 'm', 'r', 'a' ), mov_read_default },
1552 { MKTAG( 's', 'c', 'p', 't' ), mov_read_leaf },
1553 { MKTAG( 's', 's', 'r', 'c' ), mov_read_leaf },
1554 { MKTAG( 's', 'y', 'n', 'c' ), mov_read_leaf },
1555 { MKTAG( 't', 'c', 'm', 'd' ), mov_read_leaf },
1556 { MKTAG( 'w', 'i', 'd', 'e' ), mov_read_wide }, /* place holder */
1557 //{ MKTAG( 'r', 'm', 'q', 'u' ), mov_read_leaf },
1559 { MKTAG( 'c', 'm', 'o', 'v' ), mov_read_cmov },
1561 { MKTAG( 'c', 'm', 'o', 'v' ), mov_read_leaf },
1563 { 0L, mov_read_leaf }
1566 static void mov_free_stream_context(MOVStreamContext *sc)
1569 av_freep(&sc->ctts_data);
1574 /* XXX: is it sufficient ? */
1575 static int mov_probe(AVProbeData *p)
1577 unsigned int offset;
1581 /* check file header */
1582 if (p->buf_size <= 12)
1586 /* ignore invalid offset */
1587 if ((offset + 8) > (unsigned int)p->buf_size)
1589 tag = LE_32(p->buf + offset + 4);
1591 /* check for obvious tags */
1592 case MKTAG( 'j', 'P', ' ', ' ' ): /* jpeg 2000 signature */
1593 case MKTAG( 'm', 'o', 'o', 'v' ):
1594 case MKTAG( 'm', 'd', 'a', 't' ):
1595 case MKTAG( 'p', 'n', 'o', 't' ): /* detect movs with preview pics like ew.mov and april.mov */
1596 case MKTAG( 'u', 'd', 't', 'a' ): /* Packet Video PVAuthor adds this and a lot of more junk */
1597 return AVPROBE_SCORE_MAX;
1598 /* those are more common words, so rate then a bit less */
1599 case MKTAG( 'w', 'i', 'd', 'e' ):
1600 case MKTAG( 'f', 'r', 'e', 'e' ):
1601 case MKTAG( 'j', 'u', 'n', 'k' ):
1602 case MKTAG( 'p', 'i', 'c', 't' ):
1603 return AVPROBE_SCORE_MAX - 5;
1604 case MKTAG( 'f', 't', 'y', 'p' ):
1605 case MKTAG( 's', 'k', 'i', 'p' ):
1606 case MKTAG( 'u', 'u', 'i', 'd' ):
1607 offset = BE_32(p->buf+offset) + offset;
1608 /* if we only find those cause probedata is too small at least rate them */
1609 score = AVPROBE_SCORE_MAX - 50;
1612 /* unrecognized tag */
1619 static void mov_build_index(MOVContext *mov, AVStream *st)
1621 MOVStreamContext *sc = st->priv_data;
1622 offset_t current_offset;
1623 int64_t current_dts = 0;
1629 if (sc->sample_sizes || st->codec->codec_type == CODEC_TYPE_VIDEO) {
1630 int keyframe, sample_size;
1631 int current_sample = 0;
1632 int stts_sample = 0;
1635 st->nb_frames = sc->sample_count;
1636 for (i = 0; i < sc->chunk_count; i++) {
1637 current_offset = sc->chunk_offsets[i];
1638 if (stsc_index + 1 < sc->sample_to_chunk_sz && i + 1 == sc->sample_to_chunk[stsc_index + 1].first)
1640 for (j = 0; j < sc->sample_to_chunk[stsc_index].count; j++) {
1641 keyframe = !sc->keyframe_count || current_sample + 1 == sc->keyframes[stss_index];
1644 if (stss_index + 1 < sc->keyframe_count)
1647 sample_size = sc->sample_size > 0 ? sc->sample_size : sc->sample_sizes[current_sample];
1648 dprintf("AVIndex stream %d, sample %d, offset %llx, dts %lld, size %d, distance %d, keyframe %d\n",
1649 st->index, current_sample, current_offset, current_dts, sample_size, distance, keyframe);
1650 av_add_index_entry(st, current_offset, current_dts, sample_size, distance, keyframe ? AVINDEX_KEYFRAME : 0);
1651 current_offset += sample_size;
1652 assert(sc->stts_data[stts_index].duration % sc->time_rate == 0);
1653 current_dts += sc->stts_data[stts_index].duration / sc->time_rate;
1656 if (current_sample + 1 < sc->sample_count)
1658 if (stts_index + 1 < sc->stts_count && stts_sample == sc->stts_data[stts_index].count) {
1664 } else { /* read whole chunk */
1665 int chunk_samples, chunk_size, chunk_duration;
1667 for (i = 0; i < sc->chunk_count; i++) {
1668 current_offset = sc->chunk_offsets[i];
1669 if (stsc_index + 1 < sc->sample_to_chunk_sz && i + 1 == sc->sample_to_chunk[stsc_index + 1].first)
1671 chunk_samples = sc->sample_to_chunk[stsc_index].count;
1672 /* get chunk size */
1673 if (sc->sample_size > 1)
1674 chunk_size = chunk_samples * sc->sample_size;
1675 else if (sc->sample_size_v1.den > 0 && (chunk_samples * sc->sample_size_v1.num % sc->sample_size_v1.den == 0))
1676 chunk_size = chunk_samples * sc->sample_size_v1.num / sc->sample_size_v1.den;
1677 else { /* workaround to find nearest next chunk offset */
1678 chunk_size = INT_MAX;
1679 for (j = 0; j < mov->total_streams; j++) {
1680 MOVStreamContext *msc = mov->streams[j];
1682 for (k = msc->next_chunk; k < msc->chunk_count; k++) {
1683 if (msc->chunk_offsets[k] > current_offset && msc->chunk_offsets[k] - current_offset < chunk_size) {
1684 chunk_size = msc->chunk_offsets[k] - current_offset;
1685 msc->next_chunk = k;
1690 /* check for last chunk */
1691 if (chunk_size == INT_MAX)
1692 for (j = 0; j < mov->mdat_count; j++) {
1693 dprintf("mdat %d, offset %llx, size %lld, current offset %llx\n",
1694 j, mov->mdat_list[j].offset, mov->mdat_list[j].size, current_offset);
1695 if (mov->mdat_list[j].offset <= current_offset && mov->mdat_list[j].offset + mov->mdat_list[j].size > current_offset)
1696 chunk_size = mov->mdat_list[j].offset + mov->mdat_list[j].size - current_offset;
1698 assert(chunk_size != INT_MAX);
1699 for (j = 0; j < mov->total_streams; j++) {
1700 mov->streams[j]->next_chunk = 0;
1703 av_add_index_entry(st, current_offset, current_dts, chunk_size, 0, AVINDEX_KEYFRAME);
1704 /* get chunk duration */
1706 while (chunk_samples > 0) {
1707 if (chunk_samples < sc->stts_data[stts_index].count) {
1708 chunk_duration += sc->stts_data[stts_index].duration * chunk_samples;
1709 sc->stts_data[stts_index].count -= chunk_samples;
1712 chunk_duration += sc->stts_data[stts_index].duration * chunk_samples;
1713 chunk_samples -= sc->stts_data[stts_index].count;
1714 if (stts_index + 1 < sc->stts_count) {
1719 dprintf("AVIndex stream %d, chunk %d, offset %llx, dts %lld, size %d, duration %d\n",
1720 st->index, i, current_offset, current_dts, chunk_size, chunk_duration);
1721 assert(chunk_duration % sc->time_rate == 0);
1722 current_dts += chunk_duration / sc->time_rate;
1725 /* adjust sample count to avindex entries */
1726 sc->sample_count = st->nb_index_entries;
1729 static int mov_read_header(AVFormatContext *s, AVFormatParameters *ap)
1731 MOVContext *mov = (MOVContext *) s->priv_data;
1732 ByteIOContext *pb = &s->pb;
1734 MOV_atom_t atom = { 0, 0, 0 };
1737 mov->parse_table = mov_default_parse_table;
1739 if(!url_is_streamed(pb)) /* .mov and .mp4 aren't streamable anyway (only progressive download if moov is before mdat) */
1740 atom.size = url_fsize(pb);
1742 atom.size = 0x7FFFFFFFFFFFFFFFLL;
1744 /* check MOV header */
1745 err = mov_read_default(mov, pb, atom);
1746 if (err<0 || (!mov->found_moov && !mov->found_mdat)) {
1747 av_log(s, AV_LOG_ERROR, "mov: header not found !!! (err:%d, moov:%d, mdat:%d) pos:%"PRId64"\n",
1748 err, mov->found_moov, mov->found_mdat, url_ftell(pb));
1751 dprintf("on_parse_exit_offset=%d\n", (int) url_ftell(pb));
1753 /* some cleanup : make sure we are on the mdat atom */
1754 if(!url_is_streamed(pb) && (url_ftell(pb) != mov->mdat_offset))
1755 url_fseek(pb, mov->mdat_offset, SEEK_SET);
1757 mov->total_streams = s->nb_streams;
1759 for(i=0; i<mov->total_streams; i++) {
1760 MOVStreamContext *sc = mov->streams[i];
1765 sc->time_scale= mov->time_scale;
1766 av_set_pts_info(s->streams[i], 64, sc->time_rate, sc->time_scale);
1768 if(s->streams[i]->duration != AV_NOPTS_VALUE){
1769 assert(s->streams[i]->duration % sc->time_rate == 0);
1770 s->streams[i]->duration /= sc->time_rate;
1773 mov_build_index(mov, s->streams[i]);
1776 for(i=0; i<mov->total_streams; i++) {
1777 /* dont need those anymore */
1778 av_freep(&mov->streams[i]->chunk_offsets);
1779 av_freep(&mov->streams[i]->sample_to_chunk);
1780 av_freep(&mov->streams[i]->sample_sizes);
1781 av_freep(&mov->streams[i]->keyframes);
1782 av_freep(&mov->streams[i]->stts_data);
1784 av_freep(&mov->mdat_list);
1788 static int mov_read_packet(AVFormatContext *s, AVPacket *pkt)
1790 MOVContext *mov = s->priv_data;
1791 MOVStreamContext *sc = 0;
1792 AVIndexEntry *sample = 0;
1793 int64_t best_dts = INT64_MAX;
1796 for (i = 0; i < mov->total_streams; i++) {
1797 MOVStreamContext *msc = mov->streams[i];
1799 if (s->streams[i]->discard != AVDISCARD_ALL && msc->current_sample < msc->sample_count) {
1800 AVIndexEntry *current_sample = &s->streams[i]->index_entries[msc->current_sample];
1801 int64_t dts = av_rescale(current_sample->timestamp * (int64_t)msc->time_rate, AV_TIME_BASE, msc->time_scale);
1803 dprintf("stream %d, sample %ld, dts %lld\n", i, msc->current_sample, dts);
1804 if (dts < best_dts) {
1805 sample = current_sample;
1813 /* must be done just before reading, to avoid infinite loop on sample */
1814 sc->current_sample++;
1815 if (sample->pos >= url_fsize(&s->pb)) {
1816 av_log(mov->fc, AV_LOG_ERROR, "stream %d, offset 0x%llx: partial file\n", sc->ffindex, sample->pos);
1819 url_fseek(&s->pb, sample->pos, SEEK_SET);
1820 av_get_packet(&s->pb, pkt, sample->size);
1821 pkt->stream_index = sc->ffindex;
1822 pkt->dts = sample->timestamp;
1823 if (sc->ctts_data) {
1824 assert(sc->ctts_data[sc->sample_to_ctime_index].duration % sc->time_rate == 0);
1825 pkt->pts = pkt->dts + sc->ctts_data[sc->sample_to_ctime_index].duration / sc->time_rate;
1826 /* update ctts context */
1827 sc->sample_to_ctime_sample++;
1828 if (sc->sample_to_ctime_index < sc->ctts_count && sc->ctts_data[sc->sample_to_ctime_index].count == sc->sample_to_ctime_sample) {
1829 sc->sample_to_ctime_index++;
1830 sc->sample_to_ctime_sample = 0;
1833 pkt->pts = pkt->dts;
1835 pkt->flags |= sample->flags & AVINDEX_KEYFRAME ? PKT_FLAG_KEY : 0;
1836 pkt->pos = sample->pos;
1837 dprintf("stream %d, pts %lld, dts %lld, pos 0x%llx, duration %d\n", pkt->stream_index, pkt->pts, pkt->dts, pkt->pos, pkt->duration);
1841 static int mov_seek_stream(AVStream *st, int64_t timestamp, int flags)
1843 MOVStreamContext *sc = st->priv_data;
1844 int sample, time_sample;
1847 sample = av_index_search_timestamp(st, timestamp, flags);
1848 dprintf("stream %d, timestamp %lld, sample %d\n", st->index, timestamp, sample);
1849 if (sample < 0) /* not sure what to do */
1851 sc->current_sample = sample;
1852 dprintf("stream %d, found sample %ld\n", st->index, sc->current_sample);
1853 /* adjust ctts index */
1854 if (sc->ctts_data) {
1856 for (i = 0; i < sc->ctts_count; i++) {
1857 time_sample += sc->ctts_data[i].count;
1858 if (time_sample >= sc->current_sample) {
1859 sc->sample_to_ctime_index = i;
1860 sc->sample_to_ctime_sample = time_sample - sc->current_sample;
1868 static int mov_read_seek(AVFormatContext *s, int stream_index, int64_t sample_time, int flags)
1871 int64_t seek_timestamp, timestamp;
1875 if (stream_index >= s->nb_streams)
1878 st = s->streams[stream_index];
1879 sample = mov_seek_stream(st, sample_time, flags);
1883 /* adjust seek timestamp to found sample timestamp */
1884 seek_timestamp = st->index_entries[sample].timestamp;
1886 for (i = 0; i < s->nb_streams; i++) {
1888 if (stream_index == i || st->discard == AVDISCARD_ALL)
1891 timestamp = av_rescale_q(seek_timestamp, s->streams[stream_index]->time_base, st->time_base);
1892 mov_seek_stream(st, timestamp, flags);
1897 static int mov_read_close(AVFormatContext *s)
1900 MOVContext *mov = (MOVContext *) s->priv_data;
1901 for(i=0; i<mov->total_streams; i++)
1902 mov_free_stream_context(mov->streams[i]);
1903 /* free color tabs */
1904 for(i=0; i<mov->ctab_size; i++)
1905 av_freep(&mov->ctab[i]);
1906 av_freep(&mov->ctab);
1910 static AVInputFormat mov_demuxer = {
1911 "mov,mp4,m4a,3gp,3g2,mj2",
1912 "QuickTime/MPEG4/Motion JPEG 2000 format",
1923 av_register_input_format(&mov_demuxer);