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 long sample_to_chunk_index;
299 int sample_to_time_index;
300 long sample_to_time_sample;
301 uint64_t sample_to_time_time;
302 int sample_to_ctime_index;
303 int sample_to_ctime_sample;
312 long left_in_chunk; /* how many samples before next chunk */
314 AVRational sample_size_v1;
317 typedef struct MOVContext {
318 int mp4; /* set to 1 as soon as we are sure that the file is an .mp4 file (even some header parsing depends on this) */
321 int64_t duration; /* duration of the longest track */
322 int found_moov; /* when both 'moov' and 'mdat' sections has been found */
323 int found_mdat; /* we suppose we have enough data to read the file */
326 int ni; ///< non interleaved mode
328 /* some streams listed here aren't presented to the ffmpeg API, since they aren't either video nor audio
329 * but we need the info to be able to skip data from those streams in the 'mdat' section
331 MOVStreamContext *streams[MAX_STREAMS];
333 int64_t next_chunk_offset;
334 MOVStreamContext *partial; /* != 0 : there is still to read in the current chunk */
336 MOV_ctab_t **ctab; /* color tables */
337 const struct MOVParseTableEntry *parse_table; /* could be eventually used to change the table */
338 /* NOTE: for recursion save to/ restore from local variable! */
340 AVPaletteControl palette_control;
341 MOV_mdat_atom_t *mdat_list;
346 /* XXX: it's the first time I make a recursive parser I think... sorry if it's ugly :P */
348 /* those functions parse an atom */
350 1: found what I wanted, exit
351 0: continue to parse next atom
352 -1: error occured, exit
354 typedef int (*mov_parse_function)(MOVContext *ctx, ByteIOContext *pb, MOV_atom_t atom);
356 /* links atom IDs to parse functions */
357 typedef struct MOVParseTableEntry {
359 mov_parse_function func;
360 } MOVParseTableEntry;
362 static int ff_mov_lang_to_iso639(int code, char *to)
365 /* is it the mangled iso code? */
366 /* see http://www.geocities.com/xhelmboyx/quicktime/formats/mp4-layout.txt */
368 for (i = 2; i >= 0; i--) {
369 to[i] = 0x60 + (code & 0x1f);
374 /* old fashion apple lang code */
375 if (code >= (sizeof(mov_mdhd_language_map)/sizeof(char *)))
377 if (!mov_mdhd_language_map[code])
379 strncpy(to, mov_mdhd_language_map[code], 4);
383 int ff_mov_iso639_to_lang(const char *lang, int mp4)
387 /* old way, only for QT? */
388 for (i = 0; !mp4 && (i < (sizeof(mov_mdhd_language_map)/sizeof(char *))); i++) {
389 if (mov_mdhd_language_map[i] && !strcmp(lang, mov_mdhd_language_map[i]))
392 /* XXX:can we do that in mov too? */
395 /* handle undefined as such */
399 for (i = 0; i < 3; i++) {
400 unsigned char c = (unsigned char)lang[i];
411 static int mov_read_leaf(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
414 url_fskip(pb, atom.size);
415 /* url_seek(pb, atom_offset+atom.size, SEEK_SET); */
419 static int mov_read_default(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
421 int64_t total_size = 0;
426 a.offset = atom.offset;
429 atom.size = 0x7fffffffffffffffLL;
430 while(((total_size + 8) < atom.size) && !url_feof(pb) && !err) {
434 a.size = get_be32(pb);
435 a.type = get_le32(pb);
439 dprintf("type: %08x %.4s sz: %"PRIx64" %"PRIx64" %"PRIx64"\n", a.type, (char*)&a.type, a.size, atom.size, total_size);
440 if (a.size == 1) { /* 64 bit extended size */
441 a.size = get_be64(pb) - 8;
446 a.size = atom.size - total_size;
450 for (i = 0; c->parse_table[i].type != 0L
451 && c->parse_table[i].type != a.type; i++)
459 if (c->parse_table[i].type == 0) { /* skip leaf atoms data */
460 url_fskip(pb, a.size);
462 offset_t start_pos = url_ftell(pb);
464 err = (c->parse_table[i].func)(c, pb, a);
465 left = a.size - url_ftell(pb) + start_pos;
466 if (left > 0) /* skip garbage at atom end */
471 total_size += a.size;
474 if (!err && total_size < atom.size && atom.size < 0x7ffff) {
475 url_fskip(pb, atom.size - total_size);
481 static int mov_read_ctab(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
484 url_fskip(pb, atom.size); // for now
486 VERY VERY BROKEN, NEVER execute this, needs rewrite
489 c->ctab = av_realloc(c->ctab, ++c->ctab_size);
490 t = c->ctab[c->ctab_size];
491 t->seed = get_be32(pb);
492 t->flags = get_be16(pb);
493 t->size = get_be16(pb) + 1;
494 len = 2 * t->size * 4;
496 t->clrs = av_malloc(len); // 16bit A R G B
498 get_buffer(pb, t->clrs, len);
505 static int mov_read_hdlr(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
507 AVStream *st = c->fc->streams[c->fc->nb_streams-1];
512 get_byte(pb); /* version */
513 get_byte(pb); get_byte(pb); get_byte(pb); /* flags */
516 ctype = get_le32(pb);
517 type = get_le32(pb); /* component subtype */
519 dprintf("ctype= %c%c%c%c (0x%08lx)\n", *((char *)&ctype), ((char *)&ctype)[1], ((char *)&ctype)[2], ((char *)&ctype)[3], (long) ctype);
520 dprintf("stype= %c%c%c%c\n", *((char *)&type), ((char *)&type)[1], ((char *)&type)[2], ((char *)&type)[3]);
521 if(ctype == MKTAG('m', 'h', 'l', 'r')) /* MOV */
525 if(type == MKTAG('v', 'i', 'd', 'e'))
526 st->codec->codec_type = CODEC_TYPE_VIDEO;
527 else if(type == MKTAG('s', 'o', 'u', 'n'))
528 st->codec->codec_type = CODEC_TYPE_AUDIO;
529 get_be32(pb); /* component manufacture */
530 get_be32(pb); /* component flags */
531 get_be32(pb); /* component flags mask */
534 return 0; /* nothing left to read */
535 /* XXX: MP4 uses a C string, not a pascal one */
540 while(get_byte(pb) && (++len < (atom.size - 24)));
542 /* .mov: PASCAL string */
547 url_fskip(pb, atom.size - (url_ftell(pb) - atom.offset));
551 static int mov_mp4_read_descr_len(ByteIOContext *pb)
556 int c = get_byte(pb);
557 len = (len << 7) | (c & 0x7f);
564 static int mov_mp4_read_descr(ByteIOContext *pb, int *tag)
568 len = mov_mp4_read_descr_len(pb);
569 dprintf("MPEG4 description: tag=0x%02x len=%d\n", *tag, len);
573 static int mov_read_esds(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
575 AVStream *st = c->fc->streams[c->fc->nb_streams-1];
576 MOVStreamContext *sc = (MOVStreamContext *)st->priv_data;
579 /* Well, broken but suffisant for some MP4 streams */
580 get_be32(pb); /* version + flags */
581 len = mov_mp4_read_descr(pb, &tag);
582 if (tag == MP4ESDescrTag) {
583 get_be16(pb); /* ID */
584 get_byte(pb); /* priority */
586 get_be16(pb); /* ID */
588 len = mov_mp4_read_descr(pb, &tag);
589 if (tag == MP4DecConfigDescrTag) {
590 sc->esds.object_type_id = get_byte(pb);
591 sc->esds.stream_type = get_byte(pb);
592 sc->esds.buffer_size_db = get_be24(pb);
593 sc->esds.max_bitrate = get_be32(pb);
594 sc->esds.avg_bitrate = get_be32(pb);
596 st->codec->codec_id= codec_get_id(ff_mov_obj_type, sc->esds.object_type_id);
597 len = mov_mp4_read_descr(pb, &tag);
598 if (tag == MP4DecSpecificDescrTag) {
599 dprintf("Specific MPEG4 header len=%d\n", len);
600 st->codec->extradata = (uint8_t*) av_mallocz(len + FF_INPUT_BUFFER_PADDING_SIZE);
601 if (st->codec->extradata) {
602 get_buffer(pb, st->codec->extradata, len);
603 st->codec->extradata_size = len;
605 if ((*(uint8_t *)st->codec->extradata >> 3) == 29) {
606 st->codec->codec_id = CODEC_ID_MP3ON4;
614 /* this atom contains actual media data */
615 static int mov_read_mdat(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
617 if(atom.size == 0) /* wrong one (MP4) */
619 c->mdat_list = av_realloc(c->mdat_list, (c->mdat_count + 1) * sizeof(*c->mdat_list));
620 c->mdat_list[c->mdat_count].offset = atom.offset;
621 c->mdat_list[c->mdat_count].size = atom.size;
624 c->mdat_offset = atom.offset;
625 c->mdat_size = atom.size;
627 return 1; /* found both, just go */
628 url_fskip(pb, atom.size);
629 return 0; /* now go for moov */
632 static int mov_read_ftyp(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
634 uint32_t type = get_le32(pb);
638 case MKTAG('i', 's', 'o', 'm'):
639 case MKTAG('m', 'p', '4', '1'):
640 case MKTAG('m', 'p', '4', '2'):
641 case MKTAG('3', 'g', 'p', '1'):
642 case MKTAG('3', 'g', 'p', '2'):
643 case MKTAG('3', 'g', '2', 'a'):
644 case MKTAG('3', 'g', 'p', '3'):
645 case MKTAG('3', 'g', 'p', '4'):
646 case MKTAG('3', 'g', 'p', '5'):
647 case MKTAG('m', 'm', 'p', '4'): /* Mobile MP4 */
648 case MKTAG('M', '4', 'A', ' '): /* Apple iTunes AAC-LC Audio */
649 case MKTAG('M', '4', 'P', ' '): /* Apple iTunes AAC-LC Protected Audio */
650 case MKTAG('m', 'j', 'p', '2'): /* Motion Jpeg 2000 */
652 case MKTAG('q', 't', ' ', ' '):
654 av_log(c->fc, AV_LOG_DEBUG, "ISO: File Type Major Brand: %.4s\n",(char *)&type);
656 get_be32(pb); /* minor version */
657 url_fskip(pb, atom.size - 8);
661 /* this atom should contain all header atoms */
662 static int mov_read_moov(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
666 err = mov_read_default(c, pb, atom);
667 /* we parsed the 'moov' atom, we can terminate the parsing as soon as we find the 'mdat' */
668 /* so we don't parse the whole file if over a network */
671 return 1; /* found both, just go */
672 return 0; /* now go for mdat */
676 static int mov_read_mdhd(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
678 AVStream *st = c->fc->streams[c->fc->nb_streams-1];
679 MOVStreamContext *sc = (MOVStreamContext *)st->priv_data;
680 int version = get_byte(pb);
684 return 1; /* unsupported */
686 get_byte(pb); get_byte(pb);
687 get_byte(pb); /* flags */
693 get_be32(pb); /* creation time */
694 get_be32(pb); /* modification time */
697 sc->time_scale = get_be32(pb);
698 st->duration = (version == 1) ? get_be64(pb) : get_be32(pb); /* duration */
700 lang = get_be16(pb); /* language */
701 ff_mov_lang_to_iso639(lang, st->language);
702 get_be16(pb); /* quality */
707 static int mov_read_mvhd(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
709 int version = get_byte(pb); /* version */
710 get_byte(pb); get_byte(pb); get_byte(pb); /* flags */
716 get_be32(pb); /* creation time */
717 get_be32(pb); /* modification time */
719 c->time_scale = get_be32(pb); /* time scale */
721 av_log(NULL, AV_LOG_DEBUG, "time scale = %i\n", c->time_scale);
723 c->duration = (version == 1) ? get_be64(pb) : get_be32(pb); /* duration */
724 get_be32(pb); /* preferred scale */
726 get_be16(pb); /* preferred volume */
728 url_fskip(pb, 10); /* reserved */
730 url_fskip(pb, 36); /* display matrix */
732 get_be32(pb); /* preview time */
733 get_be32(pb); /* preview duration */
734 get_be32(pb); /* poster time */
735 get_be32(pb); /* selection time */
736 get_be32(pb); /* selection duration */
737 get_be32(pb); /* current time */
738 get_be32(pb); /* next track ID */
743 static int mov_read_smi(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
745 AVStream *st = c->fc->streams[c->fc->nb_streams-1];
747 if((uint64_t)atom.size > (1<<30))
750 // currently SVQ3 decoder expect full STSD header - so let's fake it
751 // this should be fixed and just SMI header should be passed
752 av_free(st->codec->extradata);
753 st->codec->extradata_size = 0x5a + atom.size;
754 st->codec->extradata = (uint8_t*) av_mallocz(st->codec->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE);
756 if (st->codec->extradata) {
757 strcpy(st->codec->extradata, "SVQ3"); // fake
758 get_buffer(pb, st->codec->extradata + 0x5a, atom.size);
759 dprintf("Reading SMI %"PRId64" %s\n", atom.size, (char*)st->codec->extradata + 0x5a);
761 url_fskip(pb, atom.size);
766 static int mov_read_enda(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
768 AVStream *st = c->fc->streams[c->fc->nb_streams-1];
769 int little_endian = get_be16(pb);
772 switch (st->codec->codec_id) {
773 case CODEC_ID_PCM_S24BE:
774 st->codec->codec_id = CODEC_ID_PCM_S24LE;
776 case CODEC_ID_PCM_S32BE:
777 st->codec->codec_id = CODEC_ID_PCM_S32LE;
786 static int mov_read_alac(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
788 AVStream *st = c->fc->streams[c->fc->nb_streams-1];
790 // currently ALAC decoder expect full atom header - so let's fake it
791 // this should be fixed and just ALAC header should be passed
793 av_free(st->codec->extradata);
794 st->codec->extradata_size = 36;
795 st->codec->extradata = (uint8_t*) av_mallocz(st->codec->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE);
797 if (st->codec->extradata) {
798 strcpy(st->codec->extradata + 4, "alac"); // fake
799 get_buffer(pb, st->codec->extradata + 8, 36 - 8);
800 dprintf("Reading alac %d %s\n", st->codec->extradata_size, (char*)st->codec->extradata);
802 url_fskip(pb, atom.size);
806 static int mov_read_wave(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
808 AVStream *st = c->fc->streams[c->fc->nb_streams-1];
810 if((uint64_t)atom.size > (1<<30))
813 if (st->codec->codec_id == CODEC_ID_QDM2) {
814 // pass all frma atom to codec, needed at least for QDM2
815 av_free(st->codec->extradata);
816 st->codec->extradata_size = atom.size;
817 st->codec->extradata = (uint8_t*) av_mallocz(st->codec->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE);
819 if (st->codec->extradata) {
820 get_buffer(pb, st->codec->extradata, atom.size);
822 url_fskip(pb, atom.size);
823 } else if (atom.size > 8) { /* to read frma, esds atoms */
824 mov_read_default(c, pb, atom);
826 url_fskip(pb, atom.size);
830 static int mov_read_jp2h(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
832 AVStream *st = c->fc->streams[c->fc->nb_streams-1];
834 if((uint64_t)atom.size > (1<<30))
837 av_free(st->codec->extradata);
839 st->codec->extradata_size = atom.size + 8;
840 st->codec->extradata = (uint8_t*) av_mallocz(st->codec->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE);
842 /* pass all jp2h atom to codec */
843 if (st->codec->extradata) {
844 strcpy(st->codec->extradata + 4, "jp2h");
845 get_buffer(pb, st->codec->extradata + 8, atom.size);
847 url_fskip(pb, atom.size);
851 static int mov_read_avcC(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
853 AVStream *st = c->fc->streams[c->fc->nb_streams-1];
855 if((uint64_t)atom.size > (1<<30))
858 av_free(st->codec->extradata);
860 st->codec->extradata_size = atom.size;
861 st->codec->extradata = (uint8_t*) av_mallocz(st->codec->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE);
863 if (st->codec->extradata) {
864 get_buffer(pb, st->codec->extradata, atom.size);
866 url_fskip(pb, atom.size);
871 static int mov_read_stco(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
873 AVStream *st = c->fc->streams[c->fc->nb_streams-1];
874 MOVStreamContext *sc = (MOVStreamContext *)st->priv_data;
875 unsigned int i, entries;
877 get_byte(pb); /* version */
878 get_byte(pb); get_byte(pb); get_byte(pb); /* flags */
880 entries = get_be32(pb);
882 if(entries >= UINT_MAX/sizeof(int64_t))
885 sc->chunk_count = entries;
886 sc->chunk_offsets = (int64_t*) av_malloc(entries * sizeof(int64_t));
887 if (!sc->chunk_offsets)
889 if (atom.type == MKTAG('s', 't', 'c', 'o')) {
890 for(i=0; i<entries; i++) {
891 sc->chunk_offsets[i] = get_be32(pb);
893 } else if (atom.type == MKTAG('c', 'o', '6', '4')) {
894 for(i=0; i<entries; i++) {
895 sc->chunk_offsets[i] = get_be64(pb);
900 for(i=0; i<c->fc->nb_streams; i++){
901 MOVStreamContext *sc2 = (MOVStreamContext *)c->fc->streams[i]->priv_data;
902 if(sc2 && sc2->chunk_offsets){
903 int64_t first= sc2->chunk_offsets[0];
904 int64_t last= sc2->chunk_offsets[sc2->chunk_count-1];
905 if(first >= sc->chunk_offsets[entries-1] || last <= sc->chunk_offsets[0])
912 static int mov_read_stsd(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
914 AVStream *st = c->fc->streams[c->fc->nb_streams-1];
915 MOVStreamContext *sc = (MOVStreamContext *)st->priv_data;
916 int entries, frames_per_sample;
918 uint8_t codec_name[32];
920 /* for palette traversal */
928 unsigned char *color_table;
930 unsigned char r, g, b;
932 get_byte(pb); /* version */
933 get_byte(pb); get_byte(pb); get_byte(pb); /* flags */
935 entries = get_be32(pb);
937 while(entries--) { //Parsing Sample description table
939 MOV_atom_t a = { 0, 0, 0 };
940 offset_t start_pos = url_ftell(pb);
941 int size = get_be32(pb); /* size */
942 format = get_le32(pb); /* data format */
944 get_be32(pb); /* reserved */
945 get_be16(pb); /* reserved */
946 get_be16(pb); /* index */
948 if (st->codec->codec_tag) {
949 /* multiple fourcc, just skip for now */
950 url_fskip(pb, size - (url_ftell(pb) - start_pos));
954 st->codec->codec_tag = format;
955 id = codec_get_id(mov_audio_tags, format);
957 st->codec->codec_type = CODEC_TYPE_AUDIO;
958 } else if (format && format != MKTAG('m', 'p', '4', 's')) { /* skip old asf mpeg4 tag */
959 id = codec_get_id(mov_video_tags, format);
961 id = codec_get_id(codec_bmp_tags, format);
963 st->codec->codec_type = CODEC_TYPE_VIDEO;
966 dprintf("size=%d 4CC= %c%c%c%c codec_type=%d\n",
968 (format >> 0) & 0xff, (format >> 8) & 0xff, (format >> 16) & 0xff, (format >> 24) & 0xff,
969 st->codec->codec_type);
971 if(st->codec->codec_type==CODEC_TYPE_VIDEO) {
972 st->codec->codec_id = id;
973 get_be16(pb); /* version */
974 get_be16(pb); /* revision level */
975 get_be32(pb); /* vendor */
976 get_be32(pb); /* temporal quality */
977 get_be32(pb); /* spacial quality */
979 st->codec->width = get_be16(pb); /* width */
980 st->codec->height = get_be16(pb); /* height */
982 get_be32(pb); /* horiz resolution */
983 get_be32(pb); /* vert resolution */
984 get_be32(pb); /* data size, always 0 */
985 frames_per_sample = get_be16(pb); /* frames per samples */
987 av_log(NULL, AV_LOG_DEBUG, "frames/samples = %d\n", frames_per_sample);
989 get_buffer(pb, codec_name, 32); /* codec name, pascal string (FIXME: true for mp4?) */
990 if (codec_name[0] <= 31) {
991 memcpy(st->codec->codec_name, &codec_name[1],codec_name[0]);
992 st->codec->codec_name[codec_name[0]] = 0;
995 st->codec->bits_per_sample = get_be16(pb); /* depth */
996 st->codec->color_table_id = get_be16(pb); /* colortable id */
998 /* figure out the palette situation */
999 color_depth = st->codec->bits_per_sample & 0x1F;
1000 color_greyscale = st->codec->bits_per_sample & 0x20;
1002 /* if the depth is 2, 4, or 8 bpp, file is palettized */
1003 if ((color_depth == 2) || (color_depth == 4) ||
1004 (color_depth == 8)) {
1006 if (color_greyscale) {
1008 /* compute the greyscale palette */
1009 color_count = 1 << color_depth;
1011 color_dec = 256 / (color_count - 1);
1012 for (j = 0; j < color_count; j++) {
1013 r = g = b = color_index;
1014 c->palette_control.palette[j] =
1015 (r << 16) | (g << 8) | (b);
1016 color_index -= color_dec;
1017 if (color_index < 0)
1021 } else if (st->codec->color_table_id & 0x08) {
1023 /* if flag bit 3 is set, use the default palette */
1024 color_count = 1 << color_depth;
1025 if (color_depth == 2)
1026 color_table = ff_qt_default_palette_4;
1027 else if (color_depth == 4)
1028 color_table = ff_qt_default_palette_16;
1030 color_table = ff_qt_default_palette_256;
1032 for (j = 0; j < color_count; j++) {
1033 r = color_table[j * 4 + 0];
1034 g = color_table[j * 4 + 1];
1035 b = color_table[j * 4 + 2];
1036 c->palette_control.palette[j] =
1037 (r << 16) | (g << 8) | (b);
1042 /* load the palette from the file */
1043 color_start = get_be32(pb);
1044 color_count = get_be16(pb);
1045 color_end = get_be16(pb);
1046 for (j = color_start; j <= color_end; j++) {
1047 /* each R, G, or B component is 16 bits;
1048 * only use the top 8 bits; skip alpha bytes
1058 c->palette_control.palette[j] =
1059 (r << 16) | (g << 8) | (b);
1063 st->codec->palctrl = &c->palette_control;
1064 st->codec->palctrl->palette_changed = 1;
1066 st->codec->palctrl = NULL;
1067 } else if(st->codec->codec_type==CODEC_TYPE_AUDIO) {
1068 int bits_per_sample;
1069 uint16_t version = get_be16(pb);
1071 st->codec->codec_id = id;
1072 get_be16(pb); /* revision level */
1073 get_be32(pb); /* vendor */
1075 st->codec->channels = get_be16(pb); /* channel count */
1076 st->codec->bits_per_sample = get_be16(pb); /* sample size */
1077 /* do we need to force to 16 for AMR ? */
1079 /* handle specific s8 codec */
1080 get_be16(pb); /* compression id = 0*/
1081 get_be16(pb); /* packet size = 0 */
1083 st->codec->sample_rate = ((get_be32(pb) >> 16));
1085 switch (st->codec->codec_id) {
1086 case CODEC_ID_PCM_S8:
1087 case CODEC_ID_PCM_U8:
1088 if (st->codec->bits_per_sample == 16)
1089 st->codec->codec_id = CODEC_ID_PCM_S16BE;
1091 case CODEC_ID_PCM_S16LE:
1092 case CODEC_ID_PCM_S16BE:
1093 if (st->codec->bits_per_sample == 8)
1094 st->codec->codec_id = CODEC_ID_PCM_S8;
1096 case CODEC_ID_AMR_WB:
1097 st->codec->sample_rate = 16000; /* should really we ? */
1098 st->codec->channels=1; /* really needed */
1100 case CODEC_ID_AMR_NB:
1101 st->codec->sample_rate = 8000; /* should really we ? */
1102 st->codec->channels=1; /* really needed */
1108 bits_per_sample = av_get_bits_per_sample(st->codec->codec_id);
1109 if (bits_per_sample) {
1110 st->codec->bits_per_sample = bits_per_sample;
1111 sc->sample_size = (bits_per_sample >> 3) * st->codec->channels;
1114 //Read QT version 1 fields. In version 0 theese dont exist
1115 dprintf("version =%d mp4=%d\n",version,c->mp4);
1117 sc->sample_size_v1.den = get_be32(pb); /* samples per packet */
1118 get_be32(pb); /* bytes per packet */
1119 sc->sample_size_v1.num = get_be32(pb); /* bytes per frame */
1120 get_be32(pb); /* bytes per sample */
1121 } else if(version==2) {
1122 get_be32(pb); /* sizeof struct only */
1123 st->codec->sample_rate = av_int2dbl(get_be64(pb)); /* float 64 */
1124 st->codec->channels = get_be32(pb);
1125 get_be32(pb); /* always 0x7F000000 */
1126 get_be32(pb); /* bits per channel if sound is uncompressed */
1127 get_be32(pb); /* lcpm format specific flag */
1128 get_be32(pb); /* bytes per audio packet if constant */
1129 get_be32(pb); /* lpcm frames per audio packet if constant */
1132 /* other codec type, just skip (rtp, mp4s, tmcd ...) */
1133 url_fskip(pb, size - (url_ftell(pb) - start_pos));
1135 /* this will read extra atoms at the end (wave, alac, damr, avcC, SMI ...) */
1136 a.size = size - (url_ftell(pb) - start_pos);
1138 mov_read_default(c, pb, a);
1139 else if (a.size > 0)
1140 url_fskip(pb, a.size);
1143 if(st->codec->codec_type==CODEC_TYPE_AUDIO && st->codec->sample_rate==0 && sc->time_scale>1) {
1144 st->codec->sample_rate= sc->time_scale;
1147 switch (st->codec->codec_id) {
1151 #ifdef CONFIG_VORBIS_DECODER
1152 case CODEC_ID_VORBIS:
1154 case CODEC_ID_MP3ON4:
1155 st->codec->sample_rate= 0; /* let decoder init parameters properly */
1164 static int mov_read_stsc(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
1166 AVStream *st = c->fc->streams[c->fc->nb_streams-1];
1167 MOVStreamContext *sc = (MOVStreamContext *)st->priv_data;
1168 unsigned int i, entries;
1170 get_byte(pb); /* version */
1171 get_byte(pb); get_byte(pb); get_byte(pb); /* flags */
1173 entries = get_be32(pb);
1175 if(entries >= UINT_MAX / sizeof(MOV_sample_to_chunk_tbl))
1179 av_log(NULL, AV_LOG_DEBUG, "track[%i].stsc.entries = %i\n", c->fc->nb_streams-1, entries);
1181 sc->sample_to_chunk_sz = entries;
1182 sc->sample_to_chunk = (MOV_sample_to_chunk_tbl*) av_malloc(entries * sizeof(MOV_sample_to_chunk_tbl));
1183 if (!sc->sample_to_chunk)
1185 for(i=0; i<entries; i++) {
1186 sc->sample_to_chunk[i].first = get_be32(pb);
1187 sc->sample_to_chunk[i].count = get_be32(pb);
1188 sc->sample_to_chunk[i].id = get_be32(pb);
1193 static int mov_read_stss(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
1195 AVStream *st = c->fc->streams[c->fc->nb_streams-1];
1196 MOVStreamContext *sc = (MOVStreamContext *)st->priv_data;
1197 unsigned int i, entries;
1199 get_byte(pb); /* version */
1200 get_byte(pb); get_byte(pb); get_byte(pb); /* flags */
1202 entries = get_be32(pb);
1204 if(entries >= UINT_MAX / sizeof(long))
1207 sc->keyframe_count = entries;
1209 av_log(NULL, AV_LOG_DEBUG, "keyframe_count = %ld\n", sc->keyframe_count);
1211 sc->keyframes = (long*) av_malloc(entries * sizeof(long));
1214 for(i=0; i<entries; i++) {
1215 sc->keyframes[i] = get_be32(pb);
1217 /* av_log(NULL, AV_LOG_DEBUG, "keyframes[]=%ld\n", sc->keyframes[i]); */
1223 static int mov_read_stsz(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
1225 AVStream *st = c->fc->streams[c->fc->nb_streams-1];
1226 MOVStreamContext *sc = (MOVStreamContext *)st->priv_data;
1227 unsigned int i, entries, sample_size;
1229 get_byte(pb); /* version */
1230 get_byte(pb); get_byte(pb); get_byte(pb); /* flags */
1232 sample_size = get_be32(pb);
1233 if (!sc->sample_size) /* do not overwrite value computed in stsd */
1234 sc->sample_size = sample_size;
1235 entries = get_be32(pb);
1236 if(entries >= UINT_MAX / sizeof(long))
1239 sc->sample_count = entries;
1244 av_log(NULL, AV_LOG_DEBUG, "sample_size = %ld sample_count = %ld\n", sc->sample_size, sc->sample_count);
1246 sc->sample_sizes = (long*) av_malloc(entries * sizeof(long));
1247 if (!sc->sample_sizes)
1249 for(i=0; i<entries; i++) {
1250 sc->sample_sizes[i] = get_be32(pb);
1252 av_log(NULL, AV_LOG_DEBUG, "sample_sizes[]=%ld\n", sc->sample_sizes[i]);
1258 static int mov_read_stts(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
1260 AVStream *st = c->fc->streams[c->fc->nb_streams-1];
1261 MOVStreamContext *sc = (MOVStreamContext *)st->priv_data;
1262 unsigned int i, entries;
1264 int64_t total_sample_count=0;
1266 get_byte(pb); /* version */
1267 get_byte(pb); get_byte(pb); get_byte(pb); /* flags */
1268 entries = get_be32(pb);
1269 if(entries >= UINT_MAX / sizeof(Time2Sample))
1272 sc->stts_count = entries;
1273 sc->stts_data = av_malloc(entries * sizeof(Time2Sample));
1276 av_log(NULL, AV_LOG_DEBUG, "track[%i].stts.entries = %i\n", c->fc->nb_streams-1, entries);
1281 for(i=0; i<entries; i++) {
1282 int sample_duration;
1285 sample_count=get_be32(pb);
1286 sample_duration = get_be32(pb);
1287 sc->stts_data[i].count= sample_count;
1288 sc->stts_data[i].duration= sample_duration;
1290 sc->time_rate= ff_gcd(sc->time_rate, sample_duration);
1292 dprintf("sample_count=%d, sample_duration=%d\n",sample_count,sample_duration);
1294 duration+=(int64_t)sample_duration*sample_count;
1295 total_sample_count+=sample_count;
1298 st->nb_frames= total_sample_count;
1300 st->duration= duration;
1304 static int mov_read_ctts(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
1306 AVStream *st = c->fc->streams[c->fc->nb_streams-1];
1307 MOVStreamContext *sc = (MOVStreamContext *)st->priv_data;
1308 unsigned int i, entries;
1310 get_byte(pb); /* version */
1311 get_byte(pb); get_byte(pb); get_byte(pb); /* flags */
1312 entries = get_be32(pb);
1313 if(entries >= UINT_MAX / sizeof(Time2Sample))
1316 sc->ctts_count = entries;
1317 sc->ctts_data = av_malloc(entries * sizeof(Time2Sample));
1319 dprintf("track[%i].ctts.entries = %i\n", c->fc->nb_streams-1, entries);
1321 for(i=0; i<entries; i++) {
1322 int count =get_be32(pb);
1323 int duration =get_be32(pb);
1326 av_log(c->fc, AV_LOG_ERROR, "negative ctts, ignoring\n");
1328 url_fskip(pb, 8 * (entries - i - 1));
1331 sc->ctts_data[i].count = count;
1332 sc->ctts_data[i].duration= duration;
1334 sc->time_rate= ff_gcd(sc->time_rate, duration);
1339 static int mov_read_trak(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
1342 MOVStreamContext *sc;
1344 st = av_new_stream(c->fc, c->fc->nb_streams);
1346 sc = (MOVStreamContext*) av_mallocz(sizeof(MOVStreamContext));
1352 sc->sample_to_chunk_index = -1;
1354 st->codec->codec_type = CODEC_TYPE_DATA;
1355 st->start_time = 0; /* XXX: check */
1356 c->streams[c->fc->nb_streams-1] = sc;
1358 return mov_read_default(c, pb, atom);
1361 static int mov_read_tkhd(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
1363 AVStream *st = c->fc->streams[c->fc->nb_streams-1];
1364 int version = get_byte(pb);
1366 get_byte(pb); get_byte(pb);
1367 get_byte(pb); /* flags */
1369 MOV_TRACK_ENABLED 0x0001
1370 MOV_TRACK_IN_MOVIE 0x0002
1371 MOV_TRACK_IN_PREVIEW 0x0004
1372 MOV_TRACK_IN_POSTER 0x0008
1379 get_be32(pb); /* creation time */
1380 get_be32(pb); /* modification time */
1382 st->id = (int)get_be32(pb); /* track id (NOT 0 !)*/
1383 get_be32(pb); /* reserved */
1384 st->start_time = 0; /* check */
1385 (version == 1) ? get_be64(pb) : get_be32(pb); /* highlevel (considering edits) duration in movie timebase */
1386 get_be32(pb); /* reserved */
1387 get_be32(pb); /* reserved */
1389 get_be16(pb); /* layer */
1390 get_be16(pb); /* alternate group */
1391 get_be16(pb); /* volume */
1392 get_be16(pb); /* reserved */
1394 url_fskip(pb, 36); /* display matrix */
1396 /* those are fixed-point */
1397 get_be32(pb); /* track width */
1398 get_be32(pb); /* track height */
1403 /* this atom should be null (from specs), but some buggy files put the 'moov' atom inside it... */
1404 /* like the files created with Adobe Premiere 5.0, for samples see */
1405 /* http://graphics.tudelft.nl/~wouter/publications/soundtests/ */
1406 static int mov_read_wide(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
1411 return 0; /* continue */
1412 if (get_be32(pb) != 0) { /* 0 sized mdat atom... use the 'wide' atom size */
1413 url_fskip(pb, atom.size - 4);
1416 atom.type = get_le32(pb);
1419 if (atom.type != MKTAG('m', 'd', 'a', 't')) {
1420 url_fskip(pb, atom.size);
1423 err = mov_read_mdat(c, pb, atom);
1429 static int null_read_packet(void *opaque, uint8_t *buf, int buf_size)
1434 static int mov_read_cmov(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
1438 uint8_t *moov_data; /* uncompressed data */
1439 long cmov_len, moov_len;
1442 get_be32(pb); /* dcom atom */
1443 if (get_le32(pb) != MKTAG( 'd', 'c', 'o', 'm' ))
1445 if (get_le32(pb) != MKTAG( 'z', 'l', 'i', 'b' )) {
1446 av_log(NULL, AV_LOG_ERROR, "unknown compression for cmov atom !");
1449 get_be32(pb); /* cmvd atom */
1450 if (get_le32(pb) != MKTAG( 'c', 'm', 'v', 'd' ))
1452 moov_len = get_be32(pb); /* uncompressed size */
1453 cmov_len = atom.size - 6 * 4;
1455 cmov_data = (uint8_t *) av_malloc(cmov_len);
1458 moov_data = (uint8_t *) av_malloc(moov_len);
1463 get_buffer(pb, cmov_data, cmov_len);
1464 if(uncompress (moov_data, (uLongf *) &moov_len, (const Bytef *)cmov_data, cmov_len) != Z_OK)
1466 if(init_put_byte(&ctx, moov_data, moov_len, 0, NULL, null_read_packet, NULL, NULL) != 0)
1468 ctx.buf_end = ctx.buffer + moov_len;
1469 atom.type = MKTAG( 'm', 'o', 'o', 'v' );
1471 atom.size = moov_len;
1473 // { int fd = open("/tmp/uncompheader.mov", O_WRONLY | O_CREAT); write(fd, moov_data, moov_len); close(fd); }
1475 ret = mov_read_default(c, &ctx, atom);
1483 /* edit list atom */
1484 static int mov_read_elst(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
1488 get_byte(pb); /* version */
1489 get_byte(pb); get_byte(pb); get_byte(pb); /* flags */
1490 edit_count= c->streams[c->fc->nb_streams-1]->edit_count = get_be32(pb); /* entries */
1492 for(i=0; i<edit_count; i++){
1493 get_be32(pb); /* Track duration */
1494 get_be32(pb); /* Media time */
1495 get_be32(pb); /* Media rate */
1497 dprintf("track[%i].edit_count = %i\n", c->fc->nb_streams-1, c->streams[c->fc->nb_streams-1]->edit_count);
1501 static const MOVParseTableEntry mov_default_parse_table[] = {
1503 { MKTAG( 'c', 'o', '6', '4' ), mov_read_stco },
1504 { MKTAG( 'c', 'p', 'r', 't' ), mov_read_default },
1505 { MKTAG( 'c', 'r', 'h', 'd' ), mov_read_default },
1506 { MKTAG( 'c', 't', 't', 's' ), mov_read_ctts }, /* composition time to sample */
1507 { MKTAG( 'd', 'i', 'n', 'f' ), mov_read_default }, /* data information */
1508 { MKTAG( 'd', 'p', 'n', 'd' ), mov_read_leaf },
1509 { MKTAG( 'd', 'r', 'e', 'f' ), mov_read_leaf },
1510 { MKTAG( 'e', 'd', 't', 's' ), mov_read_default },
1511 { MKTAG( 'e', 'l', 's', 't' ), mov_read_elst },
1512 { MKTAG( 'e', 'n', 'd', 'a' ), mov_read_enda },
1513 { MKTAG( 'f', 'r', 'e', 'e' ), mov_read_leaf },
1514 { MKTAG( 'f', 't', 'y', 'p' ), mov_read_ftyp },
1515 { MKTAG( 'h', 'd', 'l', 'r' ), mov_read_hdlr },
1516 { MKTAG( 'h', 'i', 'n', 't' ), mov_read_leaf },
1517 { MKTAG( 'h', 'm', 'h', 'd' ), mov_read_leaf },
1518 { MKTAG( 'i', 'o', 'd', 's' ), mov_read_leaf },
1519 { MKTAG( 'j', 'p', '2', 'h' ), mov_read_jp2h },
1520 { MKTAG( 'm', 'd', 'a', 't' ), mov_read_mdat },
1521 { MKTAG( 'm', 'd', 'h', 'd' ), mov_read_mdhd },
1522 { MKTAG( 'm', 'd', 'i', 'a' ), mov_read_default },
1523 { MKTAG( 'm', 'i', 'n', 'f' ), mov_read_default },
1524 { MKTAG( 'm', 'o', 'o', 'v' ), mov_read_moov },
1525 { MKTAG( 'm', 'p', '4', 'a' ), mov_read_default },
1526 { MKTAG( 'm', 'p', '4', 's' ), mov_read_default },
1527 { MKTAG( 'm', 'p', '4', 'v' ), mov_read_default },
1528 { MKTAG( 'm', 'p', 'o', 'd' ), mov_read_leaf },
1529 { MKTAG( 'm', 'v', 'h', 'd' ), mov_read_mvhd },
1530 { MKTAG( 'n', 'm', 'h', 'd' ), mov_read_leaf },
1531 { MKTAG( 'o', 'd', 'h', 'd' ), mov_read_default },
1532 { MKTAG( 's', 'd', 'h', 'd' ), mov_read_default },
1533 { MKTAG( 's', 'k', 'i', 'p' ), mov_read_leaf },
1534 { MKTAG( 's', 'm', 'h', 'd' ), mov_read_leaf }, /* sound media info header */
1535 { MKTAG( 'S', 'M', 'I', ' ' ), mov_read_smi }, /* Sorenson extension ??? */
1536 { MKTAG( 'a', 'l', 'a', 'c' ), mov_read_alac }, /* alac specific atom */
1537 { MKTAG( 'a', 'v', 'c', 'C' ), mov_read_avcC },
1538 { MKTAG( 's', 't', 'b', 'l' ), mov_read_default },
1539 { MKTAG( 's', 't', 'c', 'o' ), mov_read_stco },
1540 { MKTAG( 's', 't', 'd', 'p' ), mov_read_default },
1541 { MKTAG( 's', 't', 's', 'c' ), mov_read_stsc },
1542 { MKTAG( 's', 't', 's', 'd' ), mov_read_stsd }, /* sample description */
1543 { MKTAG( 's', 't', 's', 'h' ), mov_read_default },
1544 { MKTAG( 's', 't', 's', 's' ), mov_read_stss }, /* sync sample */
1545 { MKTAG( 's', 't', 's', 'z' ), mov_read_stsz }, /* sample size */
1546 { MKTAG( 's', 't', 't', 's' ), mov_read_stts },
1547 { MKTAG( 't', 'k', 'h', 'd' ), mov_read_tkhd }, /* track header */
1548 { MKTAG( 't', 'r', 'a', 'k' ), mov_read_trak },
1549 { MKTAG( 't', 'r', 'e', 'f' ), mov_read_default }, /* not really */
1550 { MKTAG( 'u', 'd', 't', 'a' ), mov_read_leaf },
1551 { MKTAG( 'u', 'r', 'l', ' ' ), mov_read_leaf },
1552 { MKTAG( 'u', 'r', 'n', ' ' ), mov_read_leaf },
1553 { MKTAG( 'u', 'u', 'i', 'd' ), mov_read_leaf },
1554 { MKTAG( 'v', 'm', 'h', 'd' ), mov_read_leaf }, /* video media info header */
1555 { MKTAG( 'w', 'a', 'v', 'e' ), mov_read_wave },
1557 { MKTAG( 'M', 'D', 'E', 'S' ), mov_read_leaf },
1559 { MKTAG( 'c', 'h', 'a', 'p' ), mov_read_leaf },
1560 { MKTAG( 'c', 'l', 'i', 'p' ), mov_read_default },
1561 { MKTAG( 'c', 'r', 'g', 'n' ), mov_read_leaf },
1562 { MKTAG( 'c', 't', 'a', 'b' ), mov_read_ctab },
1563 { MKTAG( 'e', 's', 'd', 's' ), mov_read_esds },
1564 { MKTAG( 'k', 'm', 'a', 't' ), mov_read_leaf },
1565 { MKTAG( 'm', 'a', 't', 't' ), mov_read_default },
1566 { MKTAG( 'r', 'd', 'r', 'f' ), mov_read_leaf },
1567 { MKTAG( 'r', 'm', 'd', 'a' ), mov_read_default },
1568 { MKTAG( 'r', 'm', 'd', 'r' ), mov_read_leaf },
1569 { MKTAG( 'r', 'm', 'r', 'a' ), mov_read_default },
1570 { MKTAG( 's', 'c', 'p', 't' ), mov_read_leaf },
1571 { MKTAG( 's', 's', 'r', 'c' ), mov_read_leaf },
1572 { MKTAG( 's', 'y', 'n', 'c' ), mov_read_leaf },
1573 { MKTAG( 't', 'c', 'm', 'd' ), mov_read_leaf },
1574 { MKTAG( 'w', 'i', 'd', 'e' ), mov_read_wide }, /* place holder */
1575 //{ MKTAG( 'r', 'm', 'q', 'u' ), mov_read_leaf },
1577 { MKTAG( 'c', 'm', 'o', 'v' ), mov_read_cmov },
1579 { MKTAG( 'c', 'm', 'o', 'v' ), mov_read_leaf },
1581 { 0L, mov_read_leaf }
1584 static void mov_free_stream_context(MOVStreamContext *sc)
1587 av_freep(&sc->stts_data);
1588 av_freep(&sc->ctts_data);
1593 static inline uint32_t mov_to_tag(uint8_t *buf)
1595 return MKTAG(buf[0], buf[1], buf[2], buf[3]);
1598 static inline uint32_t to_be32(uint8_t *buf)
1600 return (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3];
1603 /* XXX: is it sufficient ? */
1604 static int mov_probe(AVProbeData *p)
1606 unsigned int offset;
1610 /* check file header */
1611 if (p->buf_size <= 12)
1615 /* ignore invalid offset */
1616 if ((offset + 8) > (unsigned int)p->buf_size)
1618 tag = mov_to_tag(p->buf + offset + 4);
1620 /* check for obvious tags */
1621 case MKTAG( 'j', 'P', ' ', ' ' ): /* jpeg 2000 signature */
1622 case MKTAG( 'm', 'o', 'o', 'v' ):
1623 case MKTAG( 'm', 'd', 'a', 't' ):
1624 case MKTAG( 'p', 'n', 'o', 't' ): /* detect movs with preview pics like ew.mov and april.mov */
1625 case MKTAG( 'u', 'd', 't', 'a' ): /* Packet Video PVAuthor adds this and a lot of more junk */
1626 return AVPROBE_SCORE_MAX;
1627 /* those are more common words, so rate then a bit less */
1628 case MKTAG( 'w', 'i', 'd', 'e' ):
1629 case MKTAG( 'f', 'r', 'e', 'e' ):
1630 case MKTAG( 'j', 'u', 'n', 'k' ):
1631 case MKTAG( 'p', 'i', 'c', 't' ):
1632 return AVPROBE_SCORE_MAX - 5;
1633 case MKTAG( 'f', 't', 'y', 'p' ):
1634 case MKTAG( 's', 'k', 'i', 'p' ):
1635 case MKTAG( 'u', 'u', 'i', 'd' ):
1636 offset = to_be32(p->buf+offset) + offset;
1637 /* if we only find those cause probedata is too small at least rate them */
1638 score = AVPROBE_SCORE_MAX - 50;
1641 /* unrecognized tag */
1648 static void mov_build_index(MOVContext *mov, AVStream *st)
1650 MOVStreamContext *sc = st->priv_data;
1651 offset_t current_offset;
1652 int64_t current_dts = 0;
1658 if (sc->sample_sizes || st->codec->codec_type == CODEC_TYPE_VIDEO) {
1659 int keyframe, sample_size;
1660 int current_sample = 0;
1661 int stts_sample = 0;
1664 st->nb_frames = sc->sample_count;
1665 for (i = 0; i < sc->chunk_count; i++) {
1666 current_offset = sc->chunk_offsets[i];
1667 if (stsc_index + 1 < sc->sample_to_chunk_sz && i + 1 == sc->sample_to_chunk[stsc_index + 1].first)
1669 for (j = 0; j < sc->sample_to_chunk[stsc_index].count; j++) {
1670 keyframe = !sc->keyframe_count || current_sample + 1 == sc->keyframes[stss_index];
1673 if (stss_index + 1 < sc->keyframe_count)
1676 sample_size = sc->sample_size > 0 ? sc->sample_size : sc->sample_sizes[current_sample];
1677 dprintf("AVIndex stream %d, sample %d, offset %llx, dts %lld, size %d, distance %d, keyframe %d\n",
1678 st->index, current_sample, current_offset, current_dts, sample_size, distance, keyframe);
1679 av_add_index_entry(st, current_offset, current_dts, sample_size, distance, keyframe ? AVINDEX_KEYFRAME : 0);
1680 current_offset += sample_size;
1681 assert(sc->stts_data[stts_index].duration % sc->time_rate == 0);
1682 current_dts += sc->stts_data[stts_index].duration / sc->time_rate;
1685 if (current_sample + 1 < sc->sample_count)
1687 if (stts_index + 1 < sc->stts_count && stts_sample == sc->stts_data[stts_index].count) {
1693 } else { /* read whole chunk */
1694 int chunk_samples, chunk_size, chunk_duration;
1696 for (i = 0; i < sc->chunk_count; i++) {
1697 current_offset = sc->chunk_offsets[i];
1698 if (stsc_index + 1 < sc->sample_to_chunk_sz && i + 1 == sc->sample_to_chunk[stsc_index + 1].first)
1700 chunk_samples = sc->sample_to_chunk[stsc_index].count;
1701 /* get chunk size */
1702 if (sc->sample_size > 1)
1703 chunk_size = chunk_samples * sc->sample_size;
1704 else if (sc->sample_size_v1.den > 0 && (chunk_samples * sc->sample_size_v1.num % sc->sample_size_v1.den == 0))
1705 chunk_size = chunk_samples * sc->sample_size_v1.num / sc->sample_size_v1.den;
1706 else { /* workaround to find nearest next chunk offset */
1707 chunk_size = INT_MAX;
1708 for (j = 0; j < mov->total_streams; j++) {
1709 MOVStreamContext *msc = mov->streams[j];
1711 for (k = msc->next_chunk; k < msc->chunk_count; k++) {
1712 if (msc->chunk_offsets[k] > current_offset && msc->chunk_offsets[k] - current_offset < chunk_size) {
1713 chunk_size = msc->chunk_offsets[k] - current_offset;
1714 msc->next_chunk = k;
1719 /* check for last chunk */
1720 if (chunk_size == INT_MAX)
1721 for (j = 0; j < mov->mdat_count; j++) {
1722 dprintf("mdat %d, offset %llx, size %lld, current offset %llx\n",
1723 j, mov->mdat_list[j].offset, mov->mdat_list[j].size, current_offset);
1724 if (mov->mdat_list[j].offset <= current_offset && mov->mdat_list[j].offset + mov->mdat_list[j].size > current_offset)
1725 chunk_size = mov->mdat_list[j].offset + mov->mdat_list[j].size - current_offset;
1727 assert(chunk_size != INT_MAX);
1728 for (j = 0; j < mov->total_streams; j++) {
1729 mov->streams[j]->next_chunk = 0;
1732 av_add_index_entry(st, current_offset, current_dts, chunk_size, 0, AVINDEX_KEYFRAME);
1733 /* get chunk duration */
1735 while (chunk_samples > 0) {
1736 if (chunk_samples < sc->stts_data[stts_index].count) {
1737 chunk_duration += sc->stts_data[stts_index].duration * chunk_samples;
1738 sc->stts_data[stts_index].count -= chunk_samples;
1741 chunk_duration += sc->stts_data[stts_index].duration * chunk_samples;
1742 chunk_samples -= sc->stts_data[stts_index].count;
1743 if (stts_index + 1 < sc->stts_count) {
1748 dprintf("AVIndex stream %d, chunk %d, offset %llx, dts %lld, size %d, duration %d\n",
1749 st->index, i, current_offset, current_dts, chunk_size, chunk_duration);
1750 assert(chunk_duration % sc->time_rate == 0);
1751 current_dts += chunk_duration / sc->time_rate;
1753 /* adjust sample count to chunk count */
1754 sc->sample_count = sc->chunk_count;
1758 static int mov_read_header(AVFormatContext *s, AVFormatParameters *ap)
1760 MOVContext *mov = (MOVContext *) s->priv_data;
1761 ByteIOContext *pb = &s->pb;
1763 MOV_atom_t atom = { 0, 0, 0 };
1766 mov->parse_table = mov_default_parse_table;
1768 if(!url_is_streamed(pb)) /* .mov and .mp4 aren't streamable anyway (only progressive download if moov is before mdat) */
1769 atom.size = url_fsize(pb);
1771 atom.size = 0x7FFFFFFFFFFFFFFFLL;
1773 /* check MOV header */
1774 err = mov_read_default(mov, pb, atom);
1775 if (err<0 || (!mov->found_moov && !mov->found_mdat)) {
1776 av_log(s, AV_LOG_ERROR, "mov: header not found !!! (err:%d, moov:%d, mdat:%d) pos:%"PRId64"\n",
1777 err, mov->found_moov, mov->found_mdat, url_ftell(pb));
1780 dprintf("on_parse_exit_offset=%d\n", (int) url_ftell(pb));
1782 /* some cleanup : make sure we are on the mdat atom */
1783 if(!url_is_streamed(pb) && (url_ftell(pb) != mov->mdat_offset))
1784 url_fseek(pb, mov->mdat_offset, SEEK_SET);
1786 mov->next_chunk_offset = mov->mdat_offset; /* initialise reading */
1787 mov->total_streams = s->nb_streams;
1789 for(i=0; i<mov->total_streams; i++) {
1790 MOVStreamContext *sc = mov->streams[i];
1795 sc->time_scale= mov->time_scale;
1796 av_set_pts_info(s->streams[i], 64, sc->time_rate, sc->time_scale);
1798 if(s->streams[i]->duration != AV_NOPTS_VALUE){
1799 assert(s->streams[i]->duration % sc->time_rate == 0);
1800 s->streams[i]->duration /= sc->time_rate;
1803 mov_build_index(mov, s->streams[i]);
1806 for(i=0; i<mov->total_streams; i++) {
1807 /* dont need those anymore */
1808 av_freep(&mov->streams[i]->chunk_offsets);
1809 av_freep(&mov->streams[i]->sample_to_chunk);
1810 av_freep(&mov->streams[i]->sample_sizes);
1811 av_freep(&mov->streams[i]->keyframes);
1812 av_freep(&mov->streams[i]->stts_data);
1814 av_freep(&mov->mdat_list);
1818 static int mov_read_packet(AVFormatContext *s, AVPacket *pkt)
1820 MOVContext *mov = s->priv_data;
1821 MOVStreamContext *sc = 0;
1822 AVIndexEntry *sample = 0;
1823 int64_t best_dts = INT64_MAX;
1826 for (i = 0; i < mov->total_streams; i++) {
1827 MOVStreamContext *msc = mov->streams[i];
1829 if (s->streams[i]->discard != AVDISCARD_ALL && msc->current_sample < msc->sample_count) {
1830 AVIndexEntry *current_sample = &s->streams[i]->index_entries[msc->current_sample];
1831 int64_t dts = av_rescale(current_sample->timestamp * (int64_t)msc->time_rate, AV_TIME_BASE, msc->time_scale);
1833 dprintf("stream %d, sample %ld, dts %lld\n", i, msc->current_sample, dts);
1834 if (dts < best_dts) {
1835 sample = current_sample;
1843 /* must be done just before reading, to avoid infinite loop on sample */
1844 sc->current_sample++;
1845 url_fseek(&s->pb, sample->pos, SEEK_SET);
1846 if (av_get_packet(&s->pb, pkt, sample->size) <= 0) {
1847 av_log(s, AV_LOG_ERROR, "stream %d, error reading packet at offset 0x%llx, maybe partial file\n", sc->ffindex, sample->pos);
1850 pkt->stream_index = sc->ffindex;
1851 pkt->dts = sample->timestamp;
1852 if (sc->ctts_data) {
1853 assert(sc->ctts_data[sc->sample_to_ctime_index].duration % sc->time_rate == 0);
1854 pkt->pts = pkt->dts + sc->ctts_data[sc->sample_to_ctime_index].duration / sc->time_rate;
1855 /* update ctts context */
1856 sc->sample_to_ctime_sample++;
1857 if (sc->sample_to_ctime_index < sc->ctts_count && sc->ctts_data[sc->sample_to_ctime_index].count == sc->sample_to_ctime_sample) {
1858 sc->sample_to_ctime_index++;
1859 sc->sample_to_ctime_sample = 0;
1862 pkt->pts = pkt->dts;
1864 pkt->flags |= sample->flags & AVINDEX_KEYFRAME ? PKT_FLAG_KEY : 0;
1865 pkt->pos = sample->pos;
1866 dprintf("stream %d, pts %lld, dts %lld, pos 0x%llx, duration %d\n", pkt->stream_index, pkt->pts, pkt->dts, pkt->pos, pkt->duration);
1870 static int mov_seek_stream(AVStream *st, int64_t timestamp, int flags)
1872 MOVStreamContext *sc = st->priv_data;
1873 int sample, time_sample;
1876 sample = av_index_search_timestamp(st, timestamp, flags);
1877 dprintf("stream %d, timestamp %lld, sample %d\n", st->index, timestamp, sample);
1878 if (sample < 0) /* not sure what to do */
1880 sc->current_sample = sample;
1881 dprintf("stream %d, found sample %ld\n", st->index, sc->current_sample);
1882 /* adjust ctts index */
1883 if (sc->ctts_data) {
1885 for (i = 0; i < sc->ctts_count; i++) {
1886 time_sample += sc->ctts_data[i].count;
1887 if (time_sample >= sc->current_sample) {
1888 sc->sample_to_ctime_index = i;
1889 sc->sample_to_ctime_sample = time_sample - sc->current_sample;
1897 static int mov_read_seek(AVFormatContext *s, int stream_index, int64_t sample_time, int flags)
1900 int64_t seek_timestamp, timestamp;
1904 if (stream_index >= s->nb_streams)
1907 st = s->streams[stream_index];
1908 sample = mov_seek_stream(st, sample_time, flags);
1912 /* adjust seek timestamp to found sample timestamp */
1913 seek_timestamp = st->index_entries[sample].timestamp;
1915 for (i = 0; i < s->nb_streams; i++) {
1917 if (stream_index == i || st->discard == AVDISCARD_ALL)
1920 timestamp = av_rescale_q(seek_timestamp, s->streams[stream_index]->time_base, st->time_base);
1921 mov_seek_stream(st, timestamp, flags);
1926 static int mov_read_close(AVFormatContext *s)
1929 MOVContext *mov = (MOVContext *) s->priv_data;
1930 for(i=0; i<mov->total_streams; i++)
1931 mov_free_stream_context(mov->streams[i]);
1932 /* free color tabs */
1933 for(i=0; i<mov->ctab_size; i++)
1934 av_freep(&mov->ctab[i]);
1935 av_freep(&mov->ctab);
1939 static AVInputFormat mov_iformat = {
1940 "mov,mp4,m4a,3gp,3g2,mj2",
1941 "QuickTime/MPEG4/Motion JPEG 2000 format",
1952 av_register_input_format(&mov_iformat);