3 * Copyright (c) 2001 Fabrice Bellard.
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
33 * First version by Francois Revol revol@free.fr
34 * Seek function by Gael Chardon gael.dev@4now.net
36 * Features and limitations:
37 * - reads most of the QT files I have (at least the structure),
38 * the exceptions are .mov with zlib compressed headers ('cmov' section). It shouldn't be hard to implement.
39 * FIXED, Francois Revol, 07/17/2002
40 * - ffmpeg has nearly none of the usual QuickTime codecs,
41 * although I succesfully dumped raw and mp3 audio tracks off .mov files.
42 * Sample QuickTime files with mp3 audio can be found at: http://www.3ivx.com/showcase.html
43 * - .mp4 parsing is still hazardous, although the format really is QuickTime with some minor changes
44 * (to make .mov parser crash maybe ?), despite what they say in the MPEG FAQ at
45 * http://mpeg.telecomitalialab.com/faq.htm
46 * - the code is quite ugly... maybe I won't do it recursive next time :-)
47 * - seek is not supported with files that contain edit list
49 * Funny I didn't know about http://sourceforge.net/projects/qt-ffmpeg/
50 * when coding this :) (it's a writer anyway)
52 * Reference documents:
53 * http://www.geocities.com/xhelmboyx/quicktime/formats/qtm-layout.txt
55 * http://developer.apple.com/documentation/QuickTime/QTFF/
56 * http://developer.apple.com/documentation/QuickTime/QTFF/qtff.pdf
57 * QuickTime is a trademark of Apple (AFAIK :))
60 #include "qtpalette.h"
69 /* Special handling for movies created with Minolta Dimaxe Xi*/
70 /* this fix should not interfere with other .mov files, but just in case*/
71 #define MOV_MINOLTA_FIX
73 /* some streams in QT (and in MP4 mostly) aren't either video nor audio */
74 /* so we first list them as this, then clean up the list of streams we give back, */
75 /* getting rid of these */
76 #define CODEC_TYPE_MOV_OTHER (enum CodecType) 2
78 /* http://gpac.sourceforge.net/tutorial/mediatypes.htm */
79 const CodecTag ff_mov_obj_type[] = {
80 { CODEC_ID_MPEG4 , 32 },
81 { CODEC_ID_H264 , 33 },
82 { CODEC_ID_AAC , 64 },
83 { CODEC_ID_MPEG2VIDEO, 96 }, /* MPEG2 Simple */
84 { CODEC_ID_MPEG2VIDEO, 97 }, /* MPEG2 Main */
85 { CODEC_ID_MPEG2VIDEO, 98 }, /* MPEG2 SNR */
86 { CODEC_ID_MPEG2VIDEO, 99 }, /* MPEG2 Spatial */
87 { CODEC_ID_MPEG2VIDEO, 100 }, /* MPEG2 High */
88 { CODEC_ID_MPEG2VIDEO, 101 }, /* MPEG2 422 */
89 { CODEC_ID_AAC , 102 }, /* MPEG2 AAC Main */
90 { CODEC_ID_AAC , 103 }, /* MPEG2 AAC Low */
91 { CODEC_ID_AAC , 104 }, /* MPEG2 AAC SSR */
92 { CODEC_ID_MP3 , 105 },
93 { CODEC_ID_MPEG1VIDEO, 106 },
94 { CODEC_ID_MP2 , 107 },
95 { CODEC_ID_MJPEG , 108 },
96 { CODEC_ID_PCM_S16LE , 224 },
97 { CODEC_ID_VORBIS , 221 },
98 { CODEC_ID_AC3 , 226 },
99 { CODEC_ID_PCM_ALAW , 227 },
100 { CODEC_ID_PCM_MULAW , 228 },
101 { CODEC_ID_PCM_S16BE , 230 },
102 { CODEC_ID_H263 , 242 },
103 { CODEC_ID_H261 , 243 },
107 static const CodecTag mov_video_tags[] = {
108 /* { CODEC_ID_, MKTAG('c', 'v', 'i', 'd') }, *//* Cinepak */
109 /* { CODEC_ID_H263, MKTAG('r', 'a', 'w', ' ') }, *//* Uncompressed RGB */
110 /* { CODEC_ID_H263, MKTAG('Y', 'u', 'v', '2') }, *//* Uncompressed YUV422 */
111 /* { CODEC_ID_RAWVIDEO, MKTAG('A', 'V', 'U', 'I') }, *//* YUV with alpha-channel (AVID Uncompressed) */
116 { CODEC_ID_MJPEG, MKTAG('j', 'p', 'e', 'g') }, /* PhotoJPEG */
117 { CODEC_ID_MPEG1VIDEO, MKTAG('m', 'p', 'e', 'g') }, /* MPEG */
118 { CODEC_ID_MJPEG, MKTAG('m', 'j', 'p', 'a') }, /* Motion-JPEG (format A) */
119 { CODEC_ID_MJPEGB, MKTAG('m', 'j', 'p', 'b') }, /* Motion-JPEG (format B) */
120 { CODEC_ID_MJPEG, MKTAG('A', 'V', 'D', 'J') }, /* MJPEG with alpha-channel (AVID JFIF meridien compressed) */
121 /* { CODEC_ID_MJPEG, MKTAG('A', 'V', 'R', 'n') }, *//* MJPEG with alpha-channel (AVID ABVB/Truevision NuVista) */
122 /* { CODEC_ID_GIF, MKTAG('g', 'i', 'f', ' ') }, *//* embedded gif files as frames (usually one "click to play movie" frame) */
124 { CODEC_ID_SVQ1, MKTAG('S', 'V', 'Q', '1') }, /* Sorenson Video v1 */
125 { CODEC_ID_SVQ1, MKTAG('s', 'v', 'q', '1') }, /* Sorenson Video v1 */
126 { CODEC_ID_SVQ1, MKTAG('s', 'v', 'q', 'i') }, /* Sorenson Video v1 (from QT specs)*/
127 { CODEC_ID_SVQ3, MKTAG('S', 'V', 'Q', '3') }, /* Sorenson Video v3 */
128 { CODEC_ID_MPEG4, MKTAG('m', 'p', '4', 'v') },
129 { CODEC_ID_MPEG4, MKTAG('D', 'I', 'V', 'X') }, /* OpenDiVX *//* sample files at http://heroinewarrior.com/xmovie.php3 use this tag */
130 { CODEC_ID_MPEG4, MKTAG('X', 'V', 'I', 'D') },
131 { CODEC_ID_MPEG4, MKTAG('3', 'I', 'V', '2') }, /* experimental: 3IVX files before ivx D4 4.5.1 */
132 /* { CODEC_ID_, MKTAG('I', 'V', '5', '0') }, *//* Indeo 5.0 */
133 { CODEC_ID_H263, MKTAG('h', '2', '6', '3') }, /* H263 */
134 { CODEC_ID_H263, MKTAG('s', '2', '6', '3') }, /* H263 ?? works */
135 { CODEC_ID_DVVIDEO, MKTAG('d', 'v', 'c', ' ') }, /* DV NTSC */
136 { CODEC_ID_DVVIDEO, MKTAG('d', 'v', 'c', 'p') }, /* DV PAL */
137 /* { CODEC_ID_DVVIDEO, MKTAG('A', 'V', 'd', 'v') }, *//* AVID dv */
138 { CODEC_ID_VP3, MKTAG('V', 'P', '3', '1') }, /* On2 VP3 */
139 { CODEC_ID_RPZA, MKTAG('r', 'p', 'z', 'a') }, /* Apple Video (RPZA) */
140 { CODEC_ID_CINEPAK, MKTAG('c', 'v', 'i', 'd') }, /* Cinepak */
141 { CODEC_ID_8BPS, MKTAG('8', 'B', 'P', 'S') }, /* Planar RGB (8BPS) */
142 { CODEC_ID_SMC, MKTAG('s', 'm', 'c', ' ') }, /* Apple Graphics (SMC) */
143 { CODEC_ID_QTRLE, MKTAG('r', 'l', 'e', ' ') }, /* Apple Animation (RLE) */
144 { CODEC_ID_QDRAW, MKTAG('q', 'd', 'r', 'w') }, /* QuickDraw */
145 { CODEC_ID_H264, MKTAG('a', 'v', 'c', '1') }, /* AVC-1/H.264 */
146 { CODEC_ID_MPEG2VIDEO, MKTAG('h', 'd', 'v', '2') }, /* MPEG2 produced by Sony HD camera */
147 { CODEC_ID_MPEG2VIDEO, MKTAG('h', 'd', 'v', '3') }, /* HDV produced by FCP */
148 { CODEC_ID_MPEG2VIDEO, MKTAG('m', 'x', '5', 'n') }, /* MPEG2 IMX NTSC 525/60 50mb/s produced by FCP */
149 { CODEC_ID_MPEG2VIDEO, MKTAG('m', 'x', '5', 'p') }, /* MPEG2 IMX PAL 625/50 50mb/s produced by FCP */
150 { CODEC_ID_MPEG2VIDEO, MKTAG('m', 'x', '3', 'n') }, /* MPEG2 IMX NTSC 525/60 30mb/s produced by FCP */
151 { CODEC_ID_MPEG2VIDEO, MKTAG('m', 'x', '3', 'p') }, /* MPEG2 IMX PAL 625/50 30mb/s produced by FCP */
152 { CODEC_ID_DVVIDEO, MKTAG('d', 'v', 'p', 'p') }, /* DVCPRO PAL produced by FCP */
153 //{ CODEC_ID_DVVIDEO, MKTAG('d', 'v', 'h', '5') }, /* DVCPRO HD 50i produced by FCP */
154 //{ CODEC_ID_DVVIDEO, MKTAG('d', 'v', 'h', '6') }, /* DVCPRO HD 60i produced by FCP */
155 { CODEC_ID_DVVIDEO, MKTAG('d', 'v', '5', 'p') }, /* DVCPRO50 PAL produced by FCP */
156 { CODEC_ID_DVVIDEO, MKTAG('d', 'v', '5', 'n') }, /* DVCPRO50 NTSC produced by FCP */
157 { CODEC_ID_DVVIDEO, MKTAG('A', 'V', 'd', 'v') }, /* AVID DV */
158 //{ CODEC_ID_JPEG2000, MKTAG('m', 'j', 'p', '2') }, /* JPEG 2000 produced by FCP */
159 { CODEC_ID_NONE, 0 },
162 static const CodecTag mov_audio_tags[] = {
163 { CODEC_ID_PCM_S32BE, MKTAG('i', 'n', '3', '2') },
164 { CODEC_ID_PCM_S24BE, MKTAG('i', 'n', '2', '4') },
165 /* { CODEC_ID_PCM_S16BE, MKTAG('N', 'O', 'N', 'E') }, *//* uncompressed */
166 { CODEC_ID_PCM_S16BE, MKTAG('t', 'w', 'o', 's') }, /* 16 bits */
167 /* { CODEC_ID_PCM_S8, MKTAG('t', 'w', 'o', 's') },*/ /* 8 bits */
168 { CODEC_ID_PCM_U8, MKTAG('r', 'a', 'w', ' ') }, /* 8 bits unsigned */
169 { CODEC_ID_PCM_S16LE, MKTAG('s', 'o', 'w', 't') }, /* */
170 { CODEC_ID_PCM_MULAW, MKTAG('u', 'l', 'a', 'w') }, /* */
171 { CODEC_ID_PCM_ALAW, MKTAG('a', 'l', 'a', 'w') }, /* */
172 { CODEC_ID_ADPCM_IMA_QT, MKTAG('i', 'm', 'a', '4') }, /* IMA-4 ADPCM */
173 { CODEC_ID_MACE3, MKTAG('M', 'A', 'C', '3') }, /* Macintosh Audio Compression and Expansion 3:1 */
174 { CODEC_ID_MACE6, MKTAG('M', 'A', 'C', '6') }, /* Macintosh Audio Compression and Expansion 6:1 */
176 { CODEC_ID_MP2, MKTAG('.', 'm', 'p', '3') }, /* MPEG layer 3 */ /* sample files at http://www.3ivx.com/showcase.html use this tag */
177 { CODEC_ID_MP2, 0x6D730055 }, /* MPEG layer 3 */
178 { CODEC_ID_MP2, 0x5500736D }, /* MPEG layer 3 *//* XXX: check endianness */
179 /* { CODEC_ID_OGG_VORBIS, MKTAG('O', 'g', 'g', 'S') }, *//* sample files at http://heroinewarrior.com/xmovie.php3 use this tag */
181 { CODEC_ID_AAC, MKTAG('m', 'p', '4', 'a') }, /* MPEG-4 AAC */
182 /* The standard for mpeg4 audio is still not normalised AFAIK anyway */
183 { CODEC_ID_AMR_NB, MKTAG('s', 'a', 'm', 'r') }, /* AMR-NB 3gp */
184 { CODEC_ID_AMR_WB, MKTAG('s', 'a', 'w', 'b') }, /* AMR-WB 3gp */
185 { CODEC_ID_AC3, MKTAG('m', 's', 0x20, 0x00) }, /* Dolby AC-3 */
186 { CODEC_ID_ALAC,MKTAG('a', 'l', 'a', 'c') }, /* Apple Lossless */
187 { CODEC_ID_QDM2,MKTAG('Q', 'D', 'M', '2') }, /* QDM2 */
188 { CODEC_ID_NONE, 0 },
191 /* map numeric codes from mdhd atom to ISO 639 */
192 /* cf. QTFileFormat.pdf p253, qtff.pdf p205 */
193 /* http://developer.apple.com/documentation/mac/Text/Text-368.html */
194 /* deprecated by putting the code as 3*5bit ascii */
195 static const char *mov_mdhd_language_map[] = {
197 "eng", "fra", "ger", "ita", "dut", "sve", "spa", "dan", "por", "nor",
198 "heb", "jpn", "ara", "fin", "gre", "ice", "mlt", "tur", "hr "/*scr*/, "chi"/*ace?*/,
199 "urd", "hin", "tha", "kor", "lit", "pol", "hun", "est", "lav", NULL,
200 "fo ", NULL, "rus", "chi", NULL, "iri", "alb", "ron", "ces", "slk",
201 "slv", "yid", "sr ", "mac", "bul", "ukr", "bel", "uzb", "kaz", "aze",
203 "aze", "arm", "geo", "mol", "kir", "tgk", "tuk", "mon", NULL, "pus",
204 "kur", "kas", "snd", "tib", "nep", "san", "mar", "ben", "asm", "guj",
205 "pa ", "ori", "mal", "kan", "tam", "tel", NULL, "bur", "khm", "lao",
207 "vie", "ind", "tgl", "may", "may", "amh", "tir", "orm", "som", "swa",
209 NULL, "run", NULL, "mlg", "epo", NULL, NULL, NULL, NULL, NULL,
211 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
212 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
213 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, "wel", "baq",
214 "cat", "lat", "que", "grn", "aym", "tat", "uig", "dzo", "jav"
217 /* the QuickTime file format is quite convoluted...
218 * it has lots of index tables, each indexing something in another one...
219 * Here we just use what is needed to read the chunks
222 typedef struct MOV_sample_to_chunk_tbl {
226 } MOV_sample_to_chunk_tbl;
231 int64_t size; /* total size (excluding the size and type fields) */
243 uint32_t flags; // 24bit
245 /* 0x03 ESDescrTag */
247 #define MP4ODescrTag 0x01
248 #define MP4IODescrTag 0x02
249 #define MP4ESDescrTag 0x03
250 #define MP4DecConfigDescrTag 0x04
251 #define MP4DecSpecificDescrTag 0x05
252 #define MP4SLConfigDescrTag 0x06
253 #define MP4ContentIdDescrTag 0x07
254 #define MP4SupplContentIdDescrTag 0x08
255 #define MP4IPIPtrDescrTag 0x09
256 #define MP4IPMPPtrDescrTag 0x0A
257 #define MP4IPMPDescrTag 0x0B
258 #define MP4RegistrationDescrTag 0x0D
259 #define MP4ESIDIncDescrTag 0x0E
260 #define MP4ESIDRefDescrTag 0x0F
261 #define MP4FileIODescrTag 0x10
262 #define MP4FileODescrTag 0x11
263 #define MP4ExtProfileLevelDescrTag 0x13
264 #define MP4ExtDescrTagsStart 0x80
265 #define MP4ExtDescrTagsEnd 0xFE
266 uint8_t stream_priority;
268 /* 0x04 DecConfigDescrTag */
269 uint8_t object_type_id;
271 /* XXX: really streamType is
272 * only 6bit, followed by:
276 uint32_t buffer_size_db; // 24
277 uint32_t max_bitrate;
278 uint32_t avg_bitrate;
280 /* 0x05 DecSpecificDescrTag */
281 uint8_t decoder_cfg_len;
282 uint8_t *decoder_cfg;
284 /* 0x06 SLConfigDescrTag */
285 uint8_t sl_config_len;
289 struct MOVParseTableEntry;
291 typedef struct MOVStreamContext {
292 int ffindex; /* the ffmpeg stream id */
293 int is_ff_stream; /* Is this stream presented to ffmpeg ? i.e. is this an audio or video stream ? */
296 int64_t *chunk_offsets;
298 Time2Sample *stts_data;
300 Time2Sample *ctts_data;
301 int edit_count; /* number of 'edit' (elst atom) */
302 long sample_to_chunk_sz;
303 MOV_sample_to_chunk_tbl *sample_to_chunk;
304 long sample_to_chunk_index;
305 int sample_to_time_index;
306 long sample_to_time_sample;
307 uint64_t sample_to_time_time;
308 int sample_to_ctime_index;
309 int sample_to_ctime_sample;
318 long left_in_chunk; /* how many samples before next chunk */
322 typedef struct MOVContext {
323 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) */
326 int64_t duration; /* duration of the longest track */
327 int found_moov; /* when both 'moov' and 'mdat' sections has been found */
328 int found_mdat; /* we suppose we have enough data to read the file */
331 int ni; ///< non interleaved mode
333 /* some streams listed here aren't presented to the ffmpeg API, since they aren't either video nor audio
334 * but we need the info to be able to skip data from those streams in the 'mdat' section
336 MOVStreamContext *streams[MAX_STREAMS];
338 int64_t next_chunk_offset;
339 MOVStreamContext *partial; /* != 0 : there is still to read in the current chunk */
341 MOV_ctab_t **ctab; /* color tables */
342 const struct MOVParseTableEntry *parse_table; /* could be eventually used to change the table */
343 /* NOTE: for recursion save to/ restore from local variable! */
345 AVPaletteControl palette_control;
349 /* XXX: it's the first time I make a recursive parser I think... sorry if it's ugly :P */
351 /* those functions parse an atom */
353 1: found what I wanted, exit
354 0: continue to parse next atom
355 -1: error occured, exit
357 typedef int (*mov_parse_function)(MOVContext *ctx, ByteIOContext *pb, MOV_atom_t atom);
359 /* links atom IDs to parse functions */
360 typedef struct MOVParseTableEntry {
362 mov_parse_function func;
363 } MOVParseTableEntry;
365 static int ff_mov_lang_to_iso639(int code, char *to)
368 /* is it the mangled iso code? */
369 /* see http://www.geocities.com/xhelmboyx/quicktime/formats/mp4-layout.txt */
371 for (i = 2; i >= 0; i--) {
372 to[i] = 0x60 + (code & 0x1f);
377 /* old fashion apple lang code */
378 if (code >= (sizeof(mov_mdhd_language_map)/sizeof(char *)))
380 if (!mov_mdhd_language_map[code])
382 strncpy(to, mov_mdhd_language_map[code], 4);
386 int ff_mov_iso639_to_lang(const char *lang, int mp4)
390 /* old way, only for QT? */
391 for (i = 0; !mp4 && (i < (sizeof(mov_mdhd_language_map)/sizeof(char *))); i++) {
392 if (mov_mdhd_language_map[i] && !strcmp(lang, mov_mdhd_language_map[i]))
395 /* XXX:can we do that in mov too? */
398 /* handle undefined as such */
402 for (i = 0; i < 3; i++) {
403 unsigned char c = (unsigned char)lang[i];
414 static int mov_read_leaf(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
417 url_fskip(pb, atom.size);
418 /* url_seek(pb, atom_offset+atom.size, SEEK_SET); */
422 static int mov_read_default(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
424 int64_t total_size = 0;
429 a.offset = atom.offset;
432 atom.size = 0x7fffffffffffffffLL;
433 while(((total_size + 8) < atom.size) && !url_feof(pb) && !err) {
437 a.size = get_be32(pb);
438 a.type = get_le32(pb);
442 dprintf("type: %08x %.4s sz: %"PRIx64" %"PRIx64" %"PRIx64"\n", a.type, (char*)&a.type, a.size, atom.size, total_size);
443 if (a.size == 1) { /* 64 bit extended size */
444 a.size = get_be64(pb) - 8;
449 a.size = atom.size - total_size;
453 for (i = 0; c->parse_table[i].type != 0L
454 && c->parse_table[i].type != a.type; i++)
462 if (c->parse_table[i].type == 0) { /* skip leaf atoms data */
463 url_fskip(pb, a.size);
465 offset_t start_pos = url_ftell(pb);
467 err = (c->parse_table[i].func)(c, pb, a);
468 left = a.size - url_ftell(pb) + start_pos;
469 if (left > 0) /* skip garbage at atom end */
474 total_size += a.size;
477 if (!err && total_size < atom.size && atom.size < 0x7ffff) {
478 url_fskip(pb, atom.size - total_size);
484 static int mov_read_ctab(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
487 url_fskip(pb, atom.size); // for now
489 VERY VERY BROKEN, NEVER execute this, needs rewrite
492 c->ctab = av_realloc(c->ctab, ++c->ctab_size);
493 t = c->ctab[c->ctab_size];
494 t->seed = get_be32(pb);
495 t->flags = get_be16(pb);
496 t->size = get_be16(pb) + 1;
497 len = 2 * t->size * 4;
499 t->clrs = av_malloc(len); // 16bit A R G B
501 get_buffer(pb, t->clrs, len);
508 static int mov_read_hdlr(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
510 AVStream *st = c->fc->streams[c->fc->nb_streams-1];
515 get_byte(pb); /* version */
516 get_byte(pb); get_byte(pb); get_byte(pb); /* flags */
519 ctype = get_le32(pb);
520 type = get_le32(pb); /* component subtype */
522 dprintf("ctype= %c%c%c%c (0x%08lx)\n", *((char *)&ctype), ((char *)&ctype)[1], ((char *)&ctype)[2], ((char *)&ctype)[3], (long) ctype);
523 dprintf("stype= %c%c%c%c\n", *((char *)&type), ((char *)&type)[1], ((char *)&type)[2], ((char *)&type)[3]);
524 if(ctype == MKTAG('m', 'h', 'l', 'r')) /* MOV */
528 if(type == MKTAG('v', 'i', 'd', 'e'))
529 st->codec->codec_type = CODEC_TYPE_VIDEO;
530 else if(type == MKTAG('s', 'o', 'u', 'n'))
531 st->codec->codec_type = CODEC_TYPE_AUDIO;
532 get_be32(pb); /* component manufacture */
533 get_be32(pb); /* component flags */
534 get_be32(pb); /* component flags mask */
537 return 0; /* nothing left to read */
538 /* XXX: MP4 uses a C string, not a pascal one */
543 while(get_byte(pb) && (++len < (atom.size - 24)));
545 /* .mov: PASCAL string */
550 url_fskip(pb, atom.size - (url_ftell(pb) - atom.offset));
554 static int mov_mp4_read_descr_len(ByteIOContext *pb)
559 int c = get_byte(pb);
560 len = (len << 7) | (c & 0x7f);
567 static int mov_mp4_read_descr(ByteIOContext *pb, int *tag)
571 len = mov_mp4_read_descr_len(pb);
572 dprintf("MPEG4 description: tag=0x%02x len=%d\n", *tag, len);
576 static int mov_read_esds(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
578 AVStream *st = c->fc->streams[c->fc->nb_streams-1];
579 MOVStreamContext *sc = (MOVStreamContext *)st->priv_data;
582 /* Well, broken but suffisant for some MP4 streams */
583 get_be32(pb); /* version + flags */
584 len = mov_mp4_read_descr(pb, &tag);
585 if (tag == MP4ESDescrTag) {
586 get_be16(pb); /* ID */
587 get_byte(pb); /* priority */
589 get_be16(pb); /* ID */
591 len = mov_mp4_read_descr(pb, &tag);
592 if (tag == MP4DecConfigDescrTag) {
593 sc->esds.object_type_id = get_byte(pb);
594 sc->esds.stream_type = get_byte(pb);
595 sc->esds.buffer_size_db = get_be24(pb);
596 sc->esds.max_bitrate = get_be32(pb);
597 sc->esds.avg_bitrate = get_be32(pb);
599 st->codec->codec_id= codec_get_id(ff_mov_obj_type, sc->esds.object_type_id);
600 len = mov_mp4_read_descr(pb, &tag);
601 if (tag == MP4DecSpecificDescrTag) {
602 dprintf("Specific MPEG4 header len=%d\n", len);
603 st->codec->extradata = (uint8_t*) av_mallocz(len + FF_INPUT_BUFFER_PADDING_SIZE);
604 if (st->codec->extradata) {
605 get_buffer(pb, st->codec->extradata, len);
606 st->codec->extradata_size = len;
608 if ((*(uint8_t *)st->codec->extradata >> 3) == 29) {
609 st->codec->codec_id = CODEC_ID_MP3ON4;
617 /* this atom contains actual media data */
618 static int mov_read_mdat(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
620 if(atom.size == 0) /* wrong one (MP4) */
623 c->mdat_offset = atom.offset;
624 c->mdat_size = atom.size;
626 return 1; /* found both, just go */
627 url_fskip(pb, atom.size);
628 return 0; /* now go for moov */
631 static int mov_read_ftyp(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
633 uint32_t type = get_le32(pb);
637 case MKTAG('i', 's', 'o', 'm'):
638 case MKTAG('m', 'p', '4', '1'):
639 case MKTAG('m', 'p', '4', '2'):
640 case MKTAG('3', 'g', 'p', '1'):
641 case MKTAG('3', 'g', 'p', '2'):
642 case MKTAG('3', 'g', '2', 'a'):
643 case MKTAG('3', 'g', 'p', '3'):
644 case MKTAG('3', 'g', 'p', '4'):
645 case MKTAG('3', 'g', 'p', '5'):
646 case MKTAG('m', 'm', 'p', '4'): /* Mobile MP4 */
647 case MKTAG('M', '4', 'A', ' '): /* Apple iTunes AAC-LC Audio */
648 case MKTAG('M', '4', 'P', ' '): /* Apple iTunes AAC-LC Protected Audio */
649 case MKTAG('m', 'j', 'p', '2'): /* Motion Jpeg 2000 */
651 case MKTAG('q', 't', ' ', ' '):
653 av_log(c->fc, AV_LOG_DEBUG, "ISO: File Type Major Brand: %.4s\n",(char *)&type);
655 get_be32(pb); /* minor version */
656 url_fskip(pb, atom.size - 8);
660 /* this atom should contain all header atoms */
661 static int mov_read_moov(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
665 err = mov_read_default(c, pb, atom);
666 /* we parsed the 'moov' atom, we can terminate the parsing as soon as we find the 'mdat' */
667 /* so we don't parse the whole file if over a network */
670 return 1; /* found both, just go */
671 return 0; /* now go for mdat */
675 static int mov_read_mdhd(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
677 AVStream *st = c->fc->streams[c->fc->nb_streams-1];
678 MOVStreamContext *sc = (MOVStreamContext *)st->priv_data;
679 int version = get_byte(pb);
683 return 1; /* unsupported */
685 get_byte(pb); get_byte(pb);
686 get_byte(pb); /* flags */
692 get_be32(pb); /* creation time */
693 get_be32(pb); /* modification time */
696 sc->time_scale = get_be32(pb);
697 st->duration = (version == 1) ? get_be64(pb) : get_be32(pb); /* duration */
699 lang = get_be16(pb); /* language */
700 ff_mov_lang_to_iso639(lang, st->language);
701 get_be16(pb); /* quality */
706 static int mov_read_mvhd(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
708 int version = get_byte(pb); /* version */
709 get_byte(pb); get_byte(pb); get_byte(pb); /* flags */
715 get_be32(pb); /* creation time */
716 get_be32(pb); /* modification time */
718 c->time_scale = get_be32(pb); /* time scale */
720 av_log(NULL, AV_LOG_DEBUG, "time scale = %i\n", c->time_scale);
722 c->duration = (version == 1) ? get_be64(pb) : get_be32(pb); /* duration */
723 get_be32(pb); /* preferred scale */
725 get_be16(pb); /* preferred volume */
727 url_fskip(pb, 10); /* reserved */
729 url_fskip(pb, 36); /* display matrix */
731 get_be32(pb); /* preview time */
732 get_be32(pb); /* preview duration */
733 get_be32(pb); /* poster time */
734 get_be32(pb); /* selection time */
735 get_be32(pb); /* selection duration */
736 get_be32(pb); /* current time */
737 get_be32(pb); /* next track ID */
742 static int mov_read_smi(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
744 AVStream *st = c->fc->streams[c->fc->nb_streams-1];
746 if((uint64_t)atom.size > (1<<30))
749 // currently SVQ3 decoder expect full STSD header - so let's fake it
750 // this should be fixed and just SMI header should be passed
751 av_free(st->codec->extradata);
752 st->codec->extradata_size = 0x5a + atom.size;
753 st->codec->extradata = (uint8_t*) av_mallocz(st->codec->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE);
755 if (st->codec->extradata) {
756 strcpy(st->codec->extradata, "SVQ3"); // fake
757 get_buffer(pb, st->codec->extradata + 0x5a, atom.size);
758 dprintf("Reading SMI %"PRId64" %s\n", atom.size, (char*)st->codec->extradata + 0x5a);
760 url_fskip(pb, atom.size);
765 static int mov_read_enda(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
767 AVStream *st = c->fc->streams[c->fc->nb_streams-1];
768 int little_endian = get_be16(pb);
771 switch (st->codec->codec_id) {
772 case CODEC_ID_PCM_S24BE:
773 st->codec->codec_id = CODEC_ID_PCM_S24LE;
775 case CODEC_ID_PCM_S32BE:
776 st->codec->codec_id = CODEC_ID_PCM_S32LE;
785 static int mov_read_alac(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
787 AVStream *st = c->fc->streams[c->fc->nb_streams-1];
789 // currently ALAC decoder expect full atom header - so let's fake it
790 // this should be fixed and just ALAC header should be passed
792 av_free(st->codec->extradata);
793 st->codec->extradata_size = 36;
794 st->codec->extradata = (uint8_t*) av_mallocz(st->codec->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE);
796 if (st->codec->extradata) {
797 strcpy(st->codec->extradata + 4, "alac"); // fake
798 get_buffer(pb, st->codec->extradata + 8, 36 - 8);
799 dprintf("Reading alac %d %s\n", st->codec->extradata_size, (char*)st->codec->extradata);
801 url_fskip(pb, atom.size);
805 static int mov_read_wave(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
807 AVStream *st = c->fc->streams[c->fc->nb_streams-1];
809 if((uint64_t)atom.size > (1<<30))
812 if (st->codec->codec_id == CODEC_ID_QDM2) {
813 // pass all frma atom to codec, needed at least for QDM2
814 av_free(st->codec->extradata);
815 st->codec->extradata_size = atom.size;
816 st->codec->extradata = (uint8_t*) av_mallocz(st->codec->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE);
818 if (st->codec->extradata) {
819 get_buffer(pb, st->codec->extradata, atom.size);
821 url_fskip(pb, atom.size);
822 } else if (atom.size > 8) { /* to read frma, esds atoms */
823 mov_read_default(c, pb, atom);
825 url_fskip(pb, atom.size);
829 static int mov_read_jp2h(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
831 AVStream *st = c->fc->streams[c->fc->nb_streams-1];
833 if((uint64_t)atom.size > (1<<30))
836 av_free(st->codec->extradata);
838 st->codec->extradata_size = atom.size + 8;
839 st->codec->extradata = (uint8_t*) av_mallocz(st->codec->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE);
841 /* pass all jp2h atom to codec */
842 if (st->codec->extradata) {
843 strcpy(st->codec->extradata + 4, "jp2h");
844 get_buffer(pb, st->codec->extradata + 8, atom.size);
846 url_fskip(pb, atom.size);
850 static int mov_read_avcC(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
852 AVStream *st = c->fc->streams[c->fc->nb_streams-1];
854 if((uint64_t)atom.size > (1<<30))
857 av_free(st->codec->extradata);
859 st->codec->extradata_size = atom.size;
860 st->codec->extradata = (uint8_t*) av_mallocz(st->codec->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE);
862 if (st->codec->extradata) {
863 get_buffer(pb, st->codec->extradata, atom.size);
865 url_fskip(pb, atom.size);
870 static int mov_read_stco(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
872 AVStream *st = c->fc->streams[c->fc->nb_streams-1];
873 MOVStreamContext *sc = (MOVStreamContext *)st->priv_data;
874 unsigned int i, entries;
876 get_byte(pb); /* version */
877 get_byte(pb); get_byte(pb); get_byte(pb); /* flags */
879 entries = get_be32(pb);
881 if(entries >= UINT_MAX/sizeof(int64_t))
884 sc->chunk_count = entries;
885 sc->chunk_offsets = (int64_t*) av_malloc(entries * sizeof(int64_t));
886 if (!sc->chunk_offsets)
888 if (atom.type == MKTAG('s', 't', 'c', 'o')) {
889 for(i=0; i<entries; i++) {
890 sc->chunk_offsets[i] = get_be32(pb);
892 } else if (atom.type == MKTAG('c', 'o', '6', '4')) {
893 for(i=0; i<entries; i++) {
894 sc->chunk_offsets[i] = get_be64(pb);
899 for(i=0; i<c->fc->nb_streams; i++){
900 MOVStreamContext *sc2 = (MOVStreamContext *)c->fc->streams[i]->priv_data;
901 if(sc2 && sc2->chunk_offsets){
902 int64_t first= sc2->chunk_offsets[0];
903 int64_t last= sc2->chunk_offsets[sc2->chunk_count-1];
904 if(first >= sc->chunk_offsets[entries-1] || last <= sc->chunk_offsets[0])
911 static int mov_read_stsd(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
913 AVStream *st = c->fc->streams[c->fc->nb_streams-1];
914 MOVStreamContext *sc = (MOVStreamContext *)st->priv_data;
915 int entries, frames_per_sample;
917 uint8_t codec_name[32];
919 /* for palette traversal */
927 unsigned char *color_table;
929 unsigned char r, g, b;
931 get_byte(pb); /* version */
932 get_byte(pb); get_byte(pb); get_byte(pb); /* flags */
934 entries = get_be32(pb);
936 while(entries--) { //Parsing Sample description table
938 MOV_atom_t a = { 0, 0, 0 };
939 offset_t start_pos = url_ftell(pb);
940 int size = get_be32(pb); /* size */
941 format = get_le32(pb); /* data format */
943 get_be32(pb); /* reserved */
944 get_be16(pb); /* reserved */
945 get_be16(pb); /* index */
947 st->codec->codec_tag = format;
948 id = codec_get_id(mov_audio_tags, format);
950 st->codec->codec_type = CODEC_TYPE_AUDIO;
951 } else if (format && format != MKTAG('m', 'p', '4', 's')) { /* skip old asf mpeg4 tag */
952 id = codec_get_id(mov_video_tags, format);
954 id = codec_get_id(codec_bmp_tags, format);
956 st->codec->codec_type = CODEC_TYPE_VIDEO;
959 dprintf("size=%d 4CC= %c%c%c%c codec_type=%d\n",
961 (format >> 0) & 0xff, (format >> 8) & 0xff, (format >> 16) & 0xff, (format >> 24) & 0xff,
962 st->codec->codec_type);
964 if(st->codec->codec_type==CODEC_TYPE_VIDEO) {
965 st->codec->codec_id = id;
966 get_be16(pb); /* version */
967 get_be16(pb); /* revision level */
968 get_be32(pb); /* vendor */
969 get_be32(pb); /* temporal quality */
970 get_be32(pb); /* spacial quality */
972 st->codec->width = get_be16(pb); /* width */
973 st->codec->height = get_be16(pb); /* height */
975 get_be32(pb); /* horiz resolution */
976 get_be32(pb); /* vert resolution */
977 get_be32(pb); /* data size, always 0 */
978 frames_per_sample = get_be16(pb); /* frames per samples */
980 av_log(NULL, AV_LOG_DEBUG, "frames/samples = %d\n", frames_per_sample);
982 get_buffer(pb, codec_name, 32); /* codec name, pascal string (FIXME: true for mp4?) */
983 if (codec_name[0] <= 31) {
984 memcpy(st->codec->codec_name, &codec_name[1],codec_name[0]);
985 st->codec->codec_name[codec_name[0]] = 0;
988 st->codec->bits_per_sample = get_be16(pb); /* depth */
989 st->codec->color_table_id = get_be16(pb); /* colortable id */
991 /* These are set in mov_read_stts and might already be set!
992 st->codec->time_base.den = 25;
993 st->codec->time_base.num = 1;
996 /* figure out the palette situation */
997 color_depth = st->codec->bits_per_sample & 0x1F;
998 color_greyscale = st->codec->bits_per_sample & 0x20;
1000 /* if the depth is 2, 4, or 8 bpp, file is palettized */
1001 if ((color_depth == 2) || (color_depth == 4) ||
1002 (color_depth == 8)) {
1004 if (color_greyscale) {
1006 /* compute the greyscale palette */
1007 color_count = 1 << color_depth;
1009 color_dec = 256 / (color_count - 1);
1010 for (j = 0; j < color_count; j++) {
1011 r = g = b = color_index;
1012 c->palette_control.palette[j] =
1013 (r << 16) | (g << 8) | (b);
1014 color_index -= color_dec;
1015 if (color_index < 0)
1019 } else if (st->codec->color_table_id & 0x08) {
1021 /* if flag bit 3 is set, use the default palette */
1022 color_count = 1 << color_depth;
1023 if (color_depth == 2)
1024 color_table = ff_qt_default_palette_4;
1025 else if (color_depth == 4)
1026 color_table = ff_qt_default_palette_16;
1028 color_table = ff_qt_default_palette_256;
1030 for (j = 0; j < color_count; j++) {
1031 r = color_table[j * 4 + 0];
1032 g = color_table[j * 4 + 1];
1033 b = color_table[j * 4 + 2];
1034 c->palette_control.palette[j] =
1035 (r << 16) | (g << 8) | (b);
1040 /* load the palette from the file */
1041 color_start = get_be32(pb);
1042 color_count = get_be16(pb);
1043 color_end = get_be16(pb);
1044 for (j = color_start; j <= color_end; j++) {
1045 /* each R, G, or B component is 16 bits;
1046 * only use the top 8 bits; skip alpha bytes
1056 c->palette_control.palette[j] =
1057 (r << 16) | (g << 8) | (b);
1061 st->codec->palctrl = &c->palette_control;
1062 st->codec->palctrl->palette_changed = 1;
1064 st->codec->palctrl = NULL;
1065 } else if(st->codec->codec_type==CODEC_TYPE_AUDIO) {
1066 uint16_t version = get_be16(pb);
1068 st->codec->codec_id = id;
1069 get_be16(pb); /* revision level */
1070 get_be32(pb); /* vendor */
1072 st->codec->channels = get_be16(pb); /* channel count */
1073 st->codec->bits_per_sample = get_be16(pb); /* sample size */
1074 /* do we need to force to 16 for AMR ? */
1076 /* handle specific s8 codec */
1077 get_be16(pb); /* compression id = 0*/
1078 get_be16(pb); /* packet size = 0 */
1080 st->codec->sample_rate = ((get_be32(pb) >> 16));
1082 switch (st->codec->codec_id) {
1083 case CODEC_ID_PCM_S16LE:
1084 case CODEC_ID_PCM_S16BE:
1085 if (st->codec->bits_per_sample == 8)
1086 st->codec->codec_id = CODEC_ID_PCM_S8;
1087 st->codec->bit_rate = st->codec->sample_rate * 8;
1089 case CODEC_ID_PCM_U8:
1090 if (st->codec->bits_per_sample == 16)
1091 st->codec->codec_id = CODEC_ID_PCM_S16BE;
1092 st->codec->bit_rate = st->codec->sample_rate * 8;
1094 case CODEC_ID_AMR_WB:
1095 st->codec->sample_rate = 16000; /* should really we ? */
1096 st->codec->channels=1; /* really needed */
1098 case CODEC_ID_AMR_NB:
1099 st->codec->sample_rate = 8000; /* should really we ? */
1100 st->codec->channels=1; /* really needed */
1106 //Read QT version 1 fields. In version 0 theese dont exist
1107 dprintf("version =%d mp4=%d\n",version,c->mp4);
1109 get_be32(pb); /* samples per packet */
1110 get_be32(pb); /* bytes per packet */
1111 get_be32(pb); /* bytes per frame */
1112 get_be32(pb); /* bytes per sample */
1113 } else if(version==2) {
1114 get_be32(pb); /* sizeof struct only */
1115 st->codec->sample_rate = av_int2dbl(get_be64(pb)); /* float 64 */
1116 st->codec->channels = get_be32(pb);
1117 get_be32(pb); /* always 0x7F000000 */
1118 get_be32(pb); /* bits per channel if sound is uncompressed */
1119 get_be32(pb); /* lcpm format specific flag */
1120 get_be32(pb); /* bytes per audio packet if constant */
1121 get_be32(pb); /* lpcm frames per audio packet if constant */
1124 /* other codec type, just skip (rtp, mp4s, tmcd ...) */
1125 url_fskip(pb, size - (url_ftell(pb) - start_pos));
1127 /* this will read extra atoms at the end (wave, alac, damr, avcC, SMI ...) */
1128 a.size = size - (url_ftell(pb) - start_pos);
1130 mov_read_default(c, pb, a);
1131 else if (a.size > 0)
1132 url_fskip(pb, a.size);
1135 if(st->codec->codec_type==CODEC_TYPE_AUDIO && st->codec->sample_rate==0 && sc->time_scale>1) {
1136 st->codec->sample_rate= sc->time_scale;
1139 switch (st->codec->codec_id) {
1143 #ifdef CONFIG_VORBIS_DECODER
1144 case CODEC_ID_VORBIS:
1146 case CODEC_ID_MP3ON4:
1147 st->codec->sample_rate= 0; /* let decoder init parameters properly */
1156 static int mov_read_stsc(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
1158 AVStream *st = c->fc->streams[c->fc->nb_streams-1];
1159 MOVStreamContext *sc = (MOVStreamContext *)st->priv_data;
1160 unsigned int i, entries;
1162 get_byte(pb); /* version */
1163 get_byte(pb); get_byte(pb); get_byte(pb); /* flags */
1165 entries = get_be32(pb);
1167 if(entries >= UINT_MAX / sizeof(MOV_sample_to_chunk_tbl))
1171 av_log(NULL, AV_LOG_DEBUG, "track[%i].stsc.entries = %i\n", c->fc->nb_streams-1, entries);
1173 sc->sample_to_chunk_sz = entries;
1174 sc->sample_to_chunk = (MOV_sample_to_chunk_tbl*) av_malloc(entries * sizeof(MOV_sample_to_chunk_tbl));
1175 if (!sc->sample_to_chunk)
1177 for(i=0; i<entries; i++) {
1178 sc->sample_to_chunk[i].first = get_be32(pb);
1179 sc->sample_to_chunk[i].count = get_be32(pb);
1180 sc->sample_to_chunk[i].id = get_be32(pb);
1185 static int mov_read_stss(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
1187 AVStream *st = c->fc->streams[c->fc->nb_streams-1];
1188 MOVStreamContext *sc = (MOVStreamContext *)st->priv_data;
1189 unsigned int i, entries;
1191 get_byte(pb); /* version */
1192 get_byte(pb); get_byte(pb); get_byte(pb); /* flags */
1194 entries = get_be32(pb);
1196 if(entries >= UINT_MAX / sizeof(long))
1199 sc->keyframe_count = entries;
1201 av_log(NULL, AV_LOG_DEBUG, "keyframe_count = %ld\n", sc->keyframe_count);
1203 sc->keyframes = (long*) av_malloc(entries * sizeof(long));
1206 for(i=0; i<entries; i++) {
1207 sc->keyframes[i] = get_be32(pb);
1209 /* av_log(NULL, AV_LOG_DEBUG, "keyframes[]=%ld\n", sc->keyframes[i]); */
1215 static int mov_read_stsz(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
1217 AVStream *st = c->fc->streams[c->fc->nb_streams-1];
1218 MOVStreamContext *sc = (MOVStreamContext *)st->priv_data;
1219 unsigned int i, entries;
1221 get_byte(pb); /* version */
1222 get_byte(pb); get_byte(pb); get_byte(pb); /* flags */
1224 sc->sample_size = get_be32(pb);
1225 entries = get_be32(pb);
1226 if(entries >= UINT_MAX / sizeof(long))
1229 sc->sample_count = entries;
1231 av_log(NULL, AV_LOG_DEBUG, "sample_size = %ld sample_count = %ld\n", sc->sample_size, sc->sample_count);
1233 if(sc->sample_size) {
1234 /* override sample size for uncompressed sound */
1235 switch (st->codec->codec_id) {
1236 case CODEC_ID_PCM_S32BE:
1237 case CODEC_ID_PCM_S32LE:
1238 sc->sample_size = 4 * st->codec->channels;
1240 case CODEC_ID_PCM_S24BE:
1241 case CODEC_ID_PCM_S24LE:
1242 sc->sample_size = 3 * st->codec->channels;
1244 case CODEC_ID_PCM_S16BE:
1245 case CODEC_ID_PCM_S16LE:
1246 sc->sample_size = 2 * st->codec->channels;
1248 case CODEC_ID_PCM_MULAW:
1249 case CODEC_ID_PCM_ALAW:
1250 case CODEC_ID_PCM_S8:
1251 case CODEC_ID_PCM_U8:
1252 sc->sample_size = 1 * st->codec->channels;
1257 assert(sc->sample_size);
1258 return 0; /* there isn't any table following */
1260 sc->sample_sizes = (long*) av_malloc(entries * sizeof(long));
1261 if (!sc->sample_sizes)
1263 for(i=0; i<entries; i++) {
1264 sc->sample_sizes[i] = get_be32(pb);
1266 av_log(NULL, AV_LOG_DEBUG, "sample_sizes[]=%ld\n", sc->sample_sizes[i]);
1272 static int mov_read_stts(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
1274 AVStream *st = c->fc->streams[c->fc->nb_streams-1];
1275 MOVStreamContext *sc = (MOVStreamContext *)st->priv_data;
1276 unsigned int i, entries;
1278 int64_t total_sample_count=0;
1280 get_byte(pb); /* version */
1281 get_byte(pb); get_byte(pb); get_byte(pb); /* flags */
1282 entries = get_be32(pb);
1283 if(entries >= UINT_MAX / sizeof(Time2Sample))
1286 sc->stts_count = entries;
1287 sc->stts_data = av_malloc(entries * sizeof(Time2Sample));
1290 av_log(NULL, AV_LOG_DEBUG, "track[%i].stts.entries = %i\n", c->fc->nb_streams-1, entries);
1295 for(i=0; i<entries; i++) {
1296 int sample_duration;
1299 sample_count=get_be32(pb);
1300 sample_duration = get_be32(pb);
1301 sc->stts_data[i].count= sample_count;
1302 sc->stts_data[i].duration= sample_duration;
1304 sc->time_rate= ff_gcd(sc->time_rate, sample_duration);
1306 dprintf("sample_count=%d, sample_duration=%d\n",sample_count,sample_duration);
1308 duration+=(int64_t)sample_duration*sample_count;
1309 total_sample_count+=sample_count;
1312 st->nb_frames= total_sample_count;
1314 st->duration= duration;
1318 static int mov_read_ctts(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
1320 AVStream *st = c->fc->streams[c->fc->nb_streams-1];
1321 MOVStreamContext *sc = (MOVStreamContext *)st->priv_data;
1322 unsigned int i, entries;
1324 get_byte(pb); /* version */
1325 get_byte(pb); get_byte(pb); get_byte(pb); /* flags */
1326 entries = get_be32(pb);
1327 if(entries >= UINT_MAX / sizeof(Time2Sample))
1330 sc->ctts_count = entries;
1331 sc->ctts_data = av_malloc(entries * sizeof(Time2Sample));
1333 dprintf("track[%i].ctts.entries = %i\n", c->fc->nb_streams-1, entries);
1335 for(i=0; i<entries; i++) {
1336 int count =get_be32(pb);
1337 int duration =get_be32(pb);
1340 av_log(c->fc, AV_LOG_ERROR, "negative ctts, ignoring\n");
1342 url_fskip(pb, 8 * (entries - i - 1));
1345 sc->ctts_data[i].count = count;
1346 sc->ctts_data[i].duration= duration;
1348 sc->time_rate= ff_gcd(sc->time_rate, duration);
1353 static int mov_read_trak(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
1356 MOVStreamContext *sc;
1358 st = av_new_stream(c->fc, c->fc->nb_streams);
1360 sc = (MOVStreamContext*) av_mallocz(sizeof(MOVStreamContext));
1366 sc->sample_to_chunk_index = -1;
1368 st->codec->codec_type = CODEC_TYPE_MOV_OTHER;
1369 st->start_time = 0; /* XXX: check */
1370 c->streams[c->fc->nb_streams-1] = sc;
1372 return mov_read_default(c, pb, atom);
1375 static int mov_read_tkhd(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
1377 AVStream *st = c->fc->streams[c->fc->nb_streams-1];
1378 int version = get_byte(pb);
1380 get_byte(pb); get_byte(pb);
1381 get_byte(pb); /* flags */
1383 MOV_TRACK_ENABLED 0x0001
1384 MOV_TRACK_IN_MOVIE 0x0002
1385 MOV_TRACK_IN_PREVIEW 0x0004
1386 MOV_TRACK_IN_POSTER 0x0008
1393 get_be32(pb); /* creation time */
1394 get_be32(pb); /* modification time */
1396 st->id = (int)get_be32(pb); /* track id (NOT 0 !)*/
1397 get_be32(pb); /* reserved */
1398 st->start_time = 0; /* check */
1399 (version == 1) ? get_be64(pb) : get_be32(pb); /* highlevel (considering edits) duration in movie timebase */
1400 get_be32(pb); /* reserved */
1401 get_be32(pb); /* reserved */
1403 get_be16(pb); /* layer */
1404 get_be16(pb); /* alternate group */
1405 get_be16(pb); /* volume */
1406 get_be16(pb); /* reserved */
1408 url_fskip(pb, 36); /* display matrix */
1410 /* those are fixed-point */
1411 /*st->codec->width =*/ get_be32(pb) >> 16; /* track width */
1412 /*st->codec->height =*/ get_be32(pb) >> 16; /* track height */
1417 /* this atom should be null (from specs), but some buggy files put the 'moov' atom inside it... */
1418 /* like the files created with Adobe Premiere 5.0, for samples see */
1419 /* http://graphics.tudelft.nl/~wouter/publications/soundtests/ */
1420 static int mov_read_wide(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
1425 return 0; /* continue */
1426 if (get_be32(pb) != 0) { /* 0 sized mdat atom... use the 'wide' atom size */
1427 url_fskip(pb, atom.size - 4);
1430 atom.type = get_le32(pb);
1433 if (atom.type != MKTAG('m', 'd', 'a', 't')) {
1434 url_fskip(pb, atom.size);
1437 err = mov_read_mdat(c, pb, atom);
1443 static int null_read_packet(void *opaque, uint8_t *buf, int buf_size)
1448 static int mov_read_cmov(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
1452 uint8_t *moov_data; /* uncompressed data */
1453 long cmov_len, moov_len;
1456 get_be32(pb); /* dcom atom */
1457 if (get_le32(pb) != MKTAG( 'd', 'c', 'o', 'm' ))
1459 if (get_le32(pb) != MKTAG( 'z', 'l', 'i', 'b' )) {
1460 av_log(NULL, AV_LOG_ERROR, "unknown compression for cmov atom !");
1463 get_be32(pb); /* cmvd atom */
1464 if (get_le32(pb) != MKTAG( 'c', 'm', 'v', 'd' ))
1466 moov_len = get_be32(pb); /* uncompressed size */
1467 cmov_len = atom.size - 6 * 4;
1469 cmov_data = (uint8_t *) av_malloc(cmov_len);
1472 moov_data = (uint8_t *) av_malloc(moov_len);
1477 get_buffer(pb, cmov_data, cmov_len);
1478 if(uncompress (moov_data, (uLongf *) &moov_len, (const Bytef *)cmov_data, cmov_len) != Z_OK)
1480 if(init_put_byte(&ctx, moov_data, moov_len, 0, NULL, null_read_packet, NULL, NULL) != 0)
1482 ctx.buf_end = ctx.buffer + moov_len;
1483 atom.type = MKTAG( 'm', 'o', 'o', 'v' );
1485 atom.size = moov_len;
1487 // { int fd = open("/tmp/uncompheader.mov", O_WRONLY | O_CREAT); write(fd, moov_data, moov_len); close(fd); }
1489 ret = mov_read_default(c, &ctx, atom);
1497 /* edit list atom */
1498 static int mov_read_elst(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
1502 get_byte(pb); /* version */
1503 get_byte(pb); get_byte(pb); get_byte(pb); /* flags */
1504 edit_count= c->streams[c->fc->nb_streams-1]->edit_count = get_be32(pb); /* entries */
1506 for(i=0; i<edit_count; i++){
1507 get_be32(pb); /* Track duration */
1508 get_be32(pb); /* Media time */
1509 get_be32(pb); /* Media rate */
1511 dprintf("track[%i].edit_count = %i\n", c->fc->nb_streams-1, c->streams[c->fc->nb_streams-1]->edit_count);
1515 static const MOVParseTableEntry mov_default_parse_table[] = {
1517 { MKTAG( 'c', 'o', '6', '4' ), mov_read_stco },
1518 { MKTAG( 'c', 'p', 'r', 't' ), mov_read_default },
1519 { MKTAG( 'c', 'r', 'h', 'd' ), mov_read_default },
1520 { MKTAG( 'c', 't', 't', 's' ), mov_read_ctts }, /* composition time to sample */
1521 { MKTAG( 'd', 'i', 'n', 'f' ), mov_read_default }, /* data information */
1522 { MKTAG( 'd', 'p', 'n', 'd' ), mov_read_leaf },
1523 { MKTAG( 'd', 'r', 'e', 'f' ), mov_read_leaf },
1524 { MKTAG( 'e', 'd', 't', 's' ), mov_read_default },
1525 { MKTAG( 'e', 'l', 's', 't' ), mov_read_elst },
1526 { MKTAG( 'e', 'n', 'd', 'a' ), mov_read_enda },
1527 { MKTAG( 'f', 'r', 'e', 'e' ), mov_read_leaf },
1528 { MKTAG( 'f', 't', 'y', 'p' ), mov_read_ftyp },
1529 { MKTAG( 'h', 'd', 'l', 'r' ), mov_read_hdlr },
1530 { MKTAG( 'h', 'i', 'n', 't' ), mov_read_leaf },
1531 { MKTAG( 'h', 'm', 'h', 'd' ), mov_read_leaf },
1532 { MKTAG( 'i', 'o', 'd', 's' ), mov_read_leaf },
1533 { MKTAG( 'j', 'p', '2', 'h' ), mov_read_jp2h },
1534 { MKTAG( 'm', 'd', 'a', 't' ), mov_read_mdat },
1535 { MKTAG( 'm', 'd', 'h', 'd' ), mov_read_mdhd },
1536 { MKTAG( 'm', 'd', 'i', 'a' ), mov_read_default },
1537 { MKTAG( 'm', 'i', 'n', 'f' ), mov_read_default },
1538 { MKTAG( 'm', 'o', 'o', 'v' ), mov_read_moov },
1539 { MKTAG( 'm', 'p', '4', 'a' ), mov_read_default },
1540 { MKTAG( 'm', 'p', '4', 's' ), mov_read_default },
1541 { MKTAG( 'm', 'p', '4', 'v' ), mov_read_default },
1542 { MKTAG( 'm', 'p', 'o', 'd' ), mov_read_leaf },
1543 { MKTAG( 'm', 'v', 'h', 'd' ), mov_read_mvhd },
1544 { MKTAG( 'n', 'm', 'h', 'd' ), mov_read_leaf },
1545 { MKTAG( 'o', 'd', 'h', 'd' ), mov_read_default },
1546 { MKTAG( 's', 'd', 'h', 'd' ), mov_read_default },
1547 { MKTAG( 's', 'k', 'i', 'p' ), mov_read_leaf },
1548 { MKTAG( 's', 'm', 'h', 'd' ), mov_read_leaf }, /* sound media info header */
1549 { MKTAG( 'S', 'M', 'I', ' ' ), mov_read_smi }, /* Sorenson extension ??? */
1550 { MKTAG( 'a', 'l', 'a', 'c' ), mov_read_alac }, /* alac specific atom */
1551 { MKTAG( 'a', 'v', 'c', 'C' ), mov_read_avcC },
1552 { MKTAG( 's', 't', 'b', 'l' ), mov_read_default },
1553 { MKTAG( 's', 't', 'c', 'o' ), mov_read_stco },
1554 { MKTAG( 's', 't', 'd', 'p' ), mov_read_default },
1555 { MKTAG( 's', 't', 's', 'c' ), mov_read_stsc },
1556 { MKTAG( 's', 't', 's', 'd' ), mov_read_stsd }, /* sample description */
1557 { MKTAG( 's', 't', 's', 'h' ), mov_read_default },
1558 { MKTAG( 's', 't', 's', 's' ), mov_read_stss }, /* sync sample */
1559 { MKTAG( 's', 't', 's', 'z' ), mov_read_stsz }, /* sample size */
1560 { MKTAG( 's', 't', 't', 's' ), mov_read_stts },
1561 { MKTAG( 't', 'k', 'h', 'd' ), mov_read_tkhd }, /* track header */
1562 { MKTAG( 't', 'r', 'a', 'k' ), mov_read_trak },
1563 { MKTAG( 't', 'r', 'e', 'f' ), mov_read_default }, /* not really */
1564 { MKTAG( 'u', 'd', 't', 'a' ), mov_read_leaf },
1565 { MKTAG( 'u', 'r', 'l', ' ' ), mov_read_leaf },
1566 { MKTAG( 'u', 'r', 'n', ' ' ), mov_read_leaf },
1567 { MKTAG( 'u', 'u', 'i', 'd' ), mov_read_leaf },
1568 { MKTAG( 'v', 'm', 'h', 'd' ), mov_read_leaf }, /* video media info header */
1569 { MKTAG( 'w', 'a', 'v', 'e' ), mov_read_wave },
1571 { MKTAG( 'M', 'D', 'E', 'S' ), mov_read_leaf },
1573 { MKTAG( 'c', 'h', 'a', 'p' ), mov_read_leaf },
1574 { MKTAG( 'c', 'l', 'i', 'p' ), mov_read_default },
1575 { MKTAG( 'c', 'r', 'g', 'n' ), mov_read_leaf },
1576 { MKTAG( 'c', 't', 'a', 'b' ), mov_read_ctab },
1577 { MKTAG( 'e', 's', 'd', 's' ), mov_read_esds },
1578 { MKTAG( 'k', 'm', 'a', 't' ), mov_read_leaf },
1579 { MKTAG( 'm', 'a', 't', 't' ), mov_read_default },
1580 { MKTAG( 'r', 'd', 'r', 'f' ), mov_read_leaf },
1581 { MKTAG( 'r', 'm', 'd', 'a' ), mov_read_default },
1582 { MKTAG( 'r', 'm', 'd', 'r' ), mov_read_leaf },
1583 { MKTAG( 'r', 'm', 'r', 'a' ), mov_read_default },
1584 { MKTAG( 's', 'c', 'p', 't' ), mov_read_leaf },
1585 { MKTAG( 's', 's', 'r', 'c' ), mov_read_leaf },
1586 { MKTAG( 's', 'y', 'n', 'c' ), mov_read_leaf },
1587 { MKTAG( 't', 'c', 'm', 'd' ), mov_read_leaf },
1588 { MKTAG( 'w', 'i', 'd', 'e' ), mov_read_wide }, /* place holder */
1589 //{ MKTAG( 'r', 'm', 'q', 'u' ), mov_read_leaf },
1591 { MKTAG( 'c', 'm', 'o', 'v' ), mov_read_cmov },
1593 { MKTAG( 'c', 'm', 'o', 'v' ), mov_read_leaf },
1595 { 0L, mov_read_leaf }
1598 static void mov_free_stream_context(MOVStreamContext *sc)
1601 av_freep(&sc->chunk_offsets);
1602 av_freep(&sc->sample_to_chunk);
1603 av_freep(&sc->sample_sizes);
1604 av_freep(&sc->keyframes);
1605 av_freep(&sc->stts_data);
1606 av_freep(&sc->ctts_data);
1611 static inline uint32_t mov_to_tag(uint8_t *buf)
1613 return MKTAG(buf[0], buf[1], buf[2], buf[3]);
1616 static inline uint32_t to_be32(uint8_t *buf)
1618 return (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3];
1621 /* XXX: is it sufficient ? */
1622 static int mov_probe(AVProbeData *p)
1624 unsigned int offset;
1628 /* check file header */
1629 if (p->buf_size <= 12)
1633 /* ignore invalid offset */
1634 if ((offset + 8) > (unsigned int)p->buf_size)
1636 tag = mov_to_tag(p->buf + offset + 4);
1638 /* check for obvious tags */
1639 case MKTAG( 'j', 'P', ' ', ' ' ): /* jpeg 2000 signature */
1640 case MKTAG( 'm', 'o', 'o', 'v' ):
1641 case MKTAG( 'm', 'd', 'a', 't' ):
1642 case MKTAG( 'p', 'n', 'o', 't' ): /* detect movs with preview pics like ew.mov and april.mov */
1643 case MKTAG( 'u', 'd', 't', 'a' ): /* Packet Video PVAuthor adds this and a lot of more junk */
1644 return AVPROBE_SCORE_MAX;
1645 /* those are more common words, so rate then a bit less */
1646 case MKTAG( 'w', 'i', 'd', 'e' ):
1647 case MKTAG( 'f', 'r', 'e', 'e' ):
1648 case MKTAG( 'j', 'u', 'n', 'k' ):
1649 case MKTAG( 'p', 'i', 'c', 't' ):
1650 return AVPROBE_SCORE_MAX - 5;
1651 case MKTAG( 'f', 't', 'y', 'p' ):
1652 case MKTAG( 's', 'k', 'i', 'p' ):
1653 case MKTAG( 'u', 'u', 'i', 'd' ):
1654 offset = to_be32(p->buf+offset) + offset;
1655 /* if we only find those cause probedata is too small at least rate them */
1656 score = AVPROBE_SCORE_MAX - 50;
1659 /* unrecognized tag */
1666 static int mov_read_header(AVFormatContext *s, AVFormatParameters *ap)
1668 MOVContext *mov = (MOVContext *) s->priv_data;
1669 ByteIOContext *pb = &s->pb;
1671 MOV_atom_t atom = { 0, 0, 0 };
1674 mov->parse_table = mov_default_parse_table;
1676 if(!url_is_streamed(pb)) /* .mov and .mp4 aren't streamable anyway (only progressive download if moov is before mdat) */
1677 atom.size = url_fsize(pb);
1679 atom.size = 0x7FFFFFFFFFFFFFFFLL;
1681 /* check MOV header */
1682 err = mov_read_default(mov, pb, atom);
1683 if (err<0 || (!mov->found_moov && !mov->found_mdat)) {
1684 av_log(s, AV_LOG_ERROR, "mov: header not found !!! (err:%d, moov:%d, mdat:%d) pos:%"PRId64"\n",
1685 err, mov->found_moov, mov->found_mdat, url_ftell(pb));
1688 dprintf("on_parse_exit_offset=%d\n", (int) url_ftell(pb));
1690 /* some cleanup : make sure we are on the mdat atom */
1691 if(!url_is_streamed(pb) && (url_ftell(pb) != mov->mdat_offset))
1692 url_fseek(pb, mov->mdat_offset, SEEK_SET);
1694 mov->next_chunk_offset = mov->mdat_offset; /* initialise reading */
1695 mov->total_streams = nb = s->nb_streams;
1698 for(i=0; i<s->nb_streams;) {
1699 if(s->streams[i]->codec->codec_type == CODEC_TYPE_MOV_OTHER) {/* not audio, not video, delete */
1700 av_free(s->streams[i]);
1701 for(j=i+1; j<s->nb_streams; j++)
1702 s->streams[j-1] = s->streams[j];
1707 for(i=0; i<s->nb_streams;i++) {
1708 MOVStreamContext *sc = (MOVStreamContext *)s->streams[i]->priv_data;
1713 sc->time_scale= mov->time_scale;
1714 av_set_pts_info(s->streams[i], 64, sc->time_rate, sc->time_scale);
1716 if(s->streams[i]->duration != AV_NOPTS_VALUE){
1717 assert(s->streams[i]->duration % sc->time_rate == 0);
1718 s->streams[i]->duration /= sc->time_rate;
1722 sc->is_ff_stream = 1;
1728 /* Yes, this is ugly... I didn't write the specs of QT :p */
1729 /* XXX:remove useless commented code sometime */
1730 static int mov_read_packet(AVFormatContext *s, AVPacket *pkt)
1732 MOVContext *mov = (MOVContext *) s->priv_data;
1733 MOVStreamContext *sc;
1735 int64_t offset = INT64_MAX;
1736 int64_t best_dts = INT64_MAX;
1738 int next_sample= -99;
1745 idx = sc->sample_to_chunk_index;
1747 if (idx < 0) return 0;
1748 dprintf("sc[ffid %d]->sample_size = %ld\n", sc->ffindex, sc->sample_size);
1749 //size = sc->sample_sizes[sc->current_sample];
1750 // that ain't working...
1751 //size = (sc->sample_size)?sc->sample_size:sc->sample_sizes[sc->current_sample];
1752 size = (sc->sample_size > 1)?sc->sample_size:sc->sample_sizes[sc->current_sample];
1754 next_sample= sc->current_sample+1;
1756 sc->left_in_chunk--;
1758 if (sc->left_in_chunk <= 0)
1760 offset = mov->next_chunk_offset;
1761 /* extract the sample */
1768 if(offset == INT64_MAX)
1769 best_dts= INT64_MAX;
1770 for(i=0; i<mov->total_streams; i++) {
1771 MOVStreamContext *msc = mov->streams[i];
1773 if ((msc->next_chunk < msc->chunk_count) && msc->next_chunk >= 0){
1774 if (msc->sample_to_time_index < msc->stts_count && mov->ni) {
1776 int index= msc->sample_to_time_index;
1777 int sample= msc->sample_to_time_sample;
1778 int time= msc->sample_to_time_time;
1779 int duration = msc->stts_data[index].duration;
1780 int count = msc->stts_data[index].count;
1781 if (sample + count <= msc->current_sample) {
1783 time += count*duration;
1785 duration = msc->stts_data[index].duration;
1787 dts = time + (msc->current_sample - sample) * (int64_t)duration;
1788 dts = av_rescale(dts, AV_TIME_BASE, msc->time_scale);
1789 dprintf("stream: %d dts: %"PRId64" best_dts: %"PRId64" offset: %"PRId64"\n", i, dts, best_dts, offset);
1793 offset = msc->chunk_offsets[msc->next_chunk];
1796 if ((msc->chunk_offsets[msc->next_chunk] < offset)) {
1798 offset = msc->chunk_offsets[msc->next_chunk];
1803 if (!sc || offset==INT64_MAX)
1808 if(mov->next_chunk_offset < offset) { /* some meta data */
1809 url_fskip(&s->pb, (offset - mov->next_chunk_offset));
1810 mov->next_chunk_offset = offset;
1813 if(!sc->is_ff_stream || (s->streams[sc->ffindex]->discard >= AVDISCARD_ALL)) {
1814 url_fskip(&s->pb, (offset - mov->next_chunk_offset));
1815 mov->next_chunk_offset = offset;
1820 /* now get the chunk size... */
1822 for(i=0; i<mov->total_streams; i++) {
1823 MOVStreamContext *msc = mov->streams[i];
1824 if ((msc->next_chunk < msc->chunk_count)
1825 && msc->chunk_offsets[msc->next_chunk] - offset < size
1826 && msc->chunk_offsets[msc->next_chunk] > offset)
1827 size = msc->chunk_offsets[msc->next_chunk] - offset;
1830 #ifdef MOV_MINOLTA_FIX
1831 //Make sure that size is according to sample_size (Needed by .mov files
1832 //created on a Minolta Dimage Xi where audio chunks contains waste data in the end)
1833 //Maybe we should really not only check sc->sample_size, but also sc->sample_sizes
1834 //but I have no such movies
1835 if (sc->sample_size > 0) {
1837 for(i=0; i<(sc->sample_to_chunk_sz); i++) {
1838 if( (sc->sample_to_chunk[i].first)<=(sc->next_chunk) )
1840 foundsize=sc->sample_to_chunk[i].count*sc->sample_size;
1842 dprintf("sample_to_chunk first=%ld count=%ld, id=%ld\n", sc->sample_to_chunk[i].first, sc->sample_to_chunk[i].count, sc->sample_to_chunk[i].id);
1844 if( (foundsize>0) && (foundsize<size) )
1849 #endif //MOV_MINOLTA_FIX
1851 idx = sc->sample_to_chunk_index;
1852 if (idx + 1 < sc->sample_to_chunk_sz && sc->next_chunk >= sc->sample_to_chunk[idx + 1].first)
1854 sc->sample_to_chunk_index = idx;
1855 /* split chunks into samples */
1856 if (sc->sample_size == 0 || sc->sample_size > 100) {
1857 if (idx >= 0 && sc->sample_to_chunk[idx].count != 1) {
1859 /* we'll have to get those samples before next chunk */
1860 sc->left_in_chunk = sc->sample_to_chunk[idx].count - 1;
1861 size = (sc->sample_size > 1)?sc->sample_size:sc->sample_sizes[sc->current_sample];
1864 next_sample= sc->current_sample+1;
1865 }else if(idx < sc->sample_to_chunk_sz){
1866 next_sample= sc->current_sample + sc->sample_to_chunk[idx].count;
1868 next_sample= sc->current_sample;
1871 dprintf("chunk: %"PRId64" -> %"PRId64" (%i)\n", offset, offset + size, size);
1872 if(size == 0x0FFFFFFF)
1873 size = mov->mdat_size + mov->mdat_offset - offset;
1878 url_fseek(&s->pb, offset, SEEK_SET);
1880 av_get_packet(&s->pb, pkt, size);
1881 pkt->stream_index = sc->ffindex;
1883 // If the keyframes table exists, mark any samples that are in the table as key frames.
1884 // If no table exists, treat very sample as a key frame.
1885 if (sc->keyframes) {
1887 b = sc->keyframe_count - 1;
1890 m = (a + b + 1) >> 1;
1891 if (sc->keyframes[m] > sc->current_sample) {
1898 if (sc->keyframes[a] == sc->current_sample)
1899 pkt->flags |= PKT_FLAG_KEY;
1902 pkt->flags |= PKT_FLAG_KEY;
1904 mov->next_chunk_offset = offset + size;
1906 /* find the corresponding dts */
1907 if (sc && sc->sample_to_time_index < sc->stts_count && pkt) {
1910 unsigned int duration = sc->stts_data[sc->sample_to_time_index].duration;
1911 count = sc->stts_data[sc->sample_to_time_index].count;
1912 if ((sc->sample_to_time_sample + count) <= sc->current_sample) {
1913 sc->sample_to_time_sample += count;
1914 sc->sample_to_time_time += count*duration;
1915 sc->sample_to_time_index ++;
1916 duration = sc->stts_data[sc->sample_to_time_index].duration;
1918 dts = sc->sample_to_time_time + (sc->current_sample - sc->sample_to_time_sample) * (int64_t)duration;
1919 /* find the corresponding pts */
1920 if (sc->sample_to_ctime_index < sc->ctts_count) {
1921 int duration = sc->ctts_data[sc->sample_to_ctime_index].duration;
1922 int count = sc->ctts_data[sc->sample_to_ctime_index].count;
1924 if ((sc->sample_to_ctime_sample + count) <= sc->current_sample) {
1925 sc->sample_to_ctime_sample += count;
1926 sc->sample_to_ctime_index ++;
1927 duration = sc->ctts_data[sc->sample_to_ctime_index].duration;
1929 pts = dts + duration;
1933 st= s->streams[ sc->ffindex ];
1934 assert(pts % st->time_base.num == 0);
1935 assert(dts % st->time_base.num == 0);
1937 pkt->pts = pts / st->time_base.num;
1938 pkt->dts = dts / st->time_base.num;
1939 dprintf("stream #%d smp #%ld dts = %"PRId64" pts = %"PRId64" (smp:%ld time:%"PRId64" idx:%d ent:%d count:%d dur:%d)\n"
1940 , pkt->stream_index, sc->current_sample-1, pkt->dts, pkt->pts
1941 , sc->sample_to_time_sample
1942 , sc->sample_to_time_time
1943 , sc->sample_to_time_index
1949 assert(next_sample>=0);
1950 sc->current_sample= next_sample;
1955 #if defined(MOV_SEEK)
1957 * Seek method based on the one described in the Appendix C of QTFileFormat.pdf
1959 static int mov_read_seek(AVFormatContext *s, int stream_index, int64_t sample_time, int flags)
1961 MOVContext* mov = (MOVContext *) s->priv_data;
1962 MOVStreamContext* sc;
1965 int32_t seek_sample, sample;
1969 int32_t left_in_chunk;
1970 int64_t chunk_file_offset;
1971 int64_t sample_file_offset;
1972 int32_t first_chunk_sample;
1973 int32_t sample_to_chunk_idx;
1974 int sample_to_time_index;
1975 long sample_to_time_sample = 0;
1976 uint64_t sample_to_time_time = 0;
1979 // Find the corresponding mov stream
1980 for (mov_idx = 0; mov_idx < mov->total_streams; mov_idx++)
1981 if (mov->streams[mov_idx]->ffindex == stream_index)
1983 if (mov_idx == mov->total_streams) {
1984 av_log(s, AV_LOG_ERROR, "mov: requested stream was not found in mov streams (idx=%i)\n", stream_index);
1987 sc = mov->streams[mov_idx];
1989 sample_time *= s->streams[stream_index]->time_base.num;
1991 // Step 1. Find the edit that contains the requested time (elst)
1992 if (sc->edit_count && 0) {
1993 // FIXME should handle edit list
1994 av_log(s, AV_LOG_ERROR, "mov: does not handle seeking in files that contain edit list (c:%d)\n", sc->edit_count);
1998 // Step 2. Find the corresponding sample using the Time-to-sample atom (stts) */
1999 dprintf("Searching for time %li in stream #%i (time_scale=%i)\n", (long)sample_time, mov_idx, sc->time_scale);
2000 start_time = 0; // FIXME use elst atom
2001 sample = 1; // sample are 0 based in table
2003 for (i = 0; i < sc->stts_count; i++) {
2004 count = sc->stts_data[i].count;
2005 duration = sc->stts_data[i].duration;
2006 if ((start_time + count*duration) > sample_time) {
2007 sample_to_time_time = start_time;
2008 sample_to_time_index = i;
2009 sample_to_time_sample = sample;
2010 sample += (sample_time - start_time) / duration;
2014 start_time += count * duration;
2016 sample_to_time_time = start_time;
2017 sample_to_time_index = i;
2018 /* NOTE: despite what qt doc say, the dt value (Display Time in qt vocabulary) computed with the stts atom
2019 is a decoding time stamp (dts) not a presentation time stamp. And as usual dts != pts for stream with b frames */
2021 dprintf("Found time %li at sample #%u\n", (long)sample_time, sample);
2022 if (sample > sc->sample_count) {
2023 av_log(s, AV_LOG_ERROR, "mov: sample pos is too high, unable to seek (req. sample=%i, sample count=%ld)\n", sample, sc->sample_count);
2027 // Step 3. Find the prior sync. sample using the Sync sample atom (stss)
2028 if (sc->keyframes) {
2030 b = sc->keyframe_count - 1;
2032 m = (a + b + 1) >> 1;
2033 if (sc->keyframes[m] > sample) {
2039 // for low latency prob: always use the previous keyframe, just uncomment the next line
2041 seek_sample = sc->keyframes[a];
2044 seek_sample = sample; // else all samples are key frames
2045 dprintf("Found nearest keyframe at sample #%i \n", seek_sample);
2047 // Step 4. Find the chunk of the sample using the Sample-to-chunk-atom (stsc)
2048 for (first_chunk_sample = 1, i = 0; i < (sc->sample_to_chunk_sz - 1); i++) {
2049 b = (sc->sample_to_chunk[i + 1].first - sc->sample_to_chunk[i].first) * sc->sample_to_chunk[i].count;
2050 if (seek_sample >= first_chunk_sample && seek_sample < (first_chunk_sample + b))
2052 first_chunk_sample += b;
2054 chunk = sc->sample_to_chunk[i].first + (seek_sample - first_chunk_sample) / sc->sample_to_chunk[i].count;
2055 left_in_chunk = sc->sample_to_chunk[i].count - (seek_sample - first_chunk_sample) % sc->sample_to_chunk[i].count;
2056 first_chunk_sample += ((seek_sample - first_chunk_sample) / sc->sample_to_chunk[i].count) * sc->sample_to_chunk[i].count;
2057 sample_to_chunk_idx = i;
2058 dprintf("Sample was found in chunk #%i at sample offset %i (idx %i)\n", chunk, seek_sample - first_chunk_sample, sample_to_chunk_idx);
2060 // Step 5. Find the offset of the chunk using the chunk offset atom
2061 if (!sc->chunk_offsets) {
2062 av_log(s, AV_LOG_ERROR, "mov: no chunk offset atom, unable to seek\n");
2065 if (chunk > sc->chunk_count) {
2066 av_log(s, AV_LOG_ERROR, "mov: chunk offset atom too short, unable to seek (req. chunk=%i, chunk count=%li)\n", chunk, sc->chunk_count);
2069 chunk_file_offset = sc->chunk_offsets[chunk - 1];
2070 dprintf("Chunk file offset is #%"PRIu64"\n", chunk_file_offset);
2072 // Step 6. Find the byte offset within the chunk using the sample size atom
2073 sample_file_offset = chunk_file_offset;
2074 if (sc->sample_size)
2075 sample_file_offset += (seek_sample - first_chunk_sample) * sc->sample_size;
2077 for (i = 0; i < (seek_sample - first_chunk_sample); i++) {
2078 sample_file_offset += sc->sample_sizes[first_chunk_sample + i - 1];
2081 dprintf("Sample file offset is #%"PRIu64"\n", sample_file_offset);
2083 // Step 6. Update the parser
2085 mov->next_chunk_offset = sample_file_offset;
2086 // Update current stream state
2087 sc->current_sample = seek_sample - 1; // zero based
2088 sc->left_in_chunk = left_in_chunk;
2089 sc->next_chunk = chunk; // +1 -1 (zero based)
2090 sc->sample_to_chunk_index = sample_to_chunk_idx;
2092 // Update other streams
2093 for (i = 0; i<mov->total_streams; i++) {
2094 MOVStreamContext *msc;
2095 if (i == mov_idx) continue;
2096 // Find the nearest 'next' chunk
2097 msc = mov->streams[i];
2099 b = msc->chunk_count - 1;
2101 m = (a + b + 1) >> 1;
2102 if (msc->chunk_offsets[m] > chunk_file_offset) {
2108 msc->next_chunk = a;
2109 if (msc->chunk_offsets[a] < chunk_file_offset && a < (msc->chunk_count-1))
2111 dprintf("Nearest next chunk for stream #%i is #%li @%"PRId64"\n", i, msc->next_chunk+1, msc->chunk_offsets[msc->next_chunk]);
2113 // Compute sample count and index in the sample_to_chunk table (what a pity)
2114 msc->sample_to_chunk_index = 0;
2115 msc->current_sample = 0;
2116 for(; msc->sample_to_chunk_index < (msc->sample_to_chunk_sz - 1)
2117 && msc->sample_to_chunk[msc->sample_to_chunk_index + 1].first <= (1 + msc->next_chunk); msc->sample_to_chunk_index++) {
2118 msc->current_sample += (msc->sample_to_chunk[msc->sample_to_chunk_index + 1].first - msc->sample_to_chunk[msc->sample_to_chunk_index].first) \
2119 * msc->sample_to_chunk[msc->sample_to_chunk_index].count;
2121 msc->current_sample += (msc->next_chunk - (msc->sample_to_chunk[msc->sample_to_chunk_index].first - 1)) * sc->sample_to_chunk[msc->sample_to_chunk_index].count;
2122 msc->left_in_chunk = msc->sample_to_chunk[msc->sample_to_chunk_index].count - 1;
2123 // Find corresponding position in stts (used later to compute dts)
2126 for (msc->sample_to_time_index = 0; msc->sample_to_time_index < msc->stts_count; msc->sample_to_time_index++) {
2127 count = msc->stts_data[msc->sample_to_time_index].count;
2128 duration = msc->stts_data[msc->sample_to_time_index].duration;
2129 if ((sample + count - 1) > msc->current_sample) {
2130 msc->sample_to_time_time = start_time;
2131 msc->sample_to_time_sample = sample;
2135 start_time += count * duration;
2138 for (msc->sample_to_ctime_index = 0; msc->sample_to_ctime_index < msc->ctts_count; msc->sample_to_ctime_index++) {
2139 count = msc->ctts_data[msc->sample_to_ctime_index].count;
2140 duration = msc->ctts_data[msc->sample_to_ctime_index].duration;
2141 if ((sample + count - 1) > msc->current_sample) {
2142 msc->sample_to_ctime_sample = sample;
2147 dprintf("Next Sample for stream #%i is #%li @%li\n", i, msc->current_sample + 1, msc->sample_to_chunk_index + 1);
2153 static int mov_read_close(AVFormatContext *s)
2156 MOVContext *mov = (MOVContext *) s->priv_data;
2157 for(i=0; i<mov->total_streams; i++)
2158 mov_free_stream_context(mov->streams[i]);
2159 /* free color tabs */
2160 for(i=0; i<mov->ctab_size; i++)
2161 av_freep(&mov->ctab[i]);
2162 av_freep(&mov->ctab);
2166 static AVInputFormat mov_iformat = {
2167 "mov,mp4,m4a,3gp,3g2,mj2",
2168 "QuickTime/MPEG4/Motion JPEG 2000 format",
2174 #if defined(MOV_SEEK)
2181 av_register_input_format(&mov_iformat);