export all tracks to libavformat layer
[libav.git] / libavformat / mov.c
1 /*
2 * MOV decoder.
3 * Copyright (c) 2001 Fabrice Bellard.
4 *
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.
9 *
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.
14 *
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
18 */
19
20 #include <limits.h>
21
22 //#define DEBUG
23
24 #include "avformat.h"
25 #include "avi.h"
26 #include "mov.h"
27
28 #ifdef CONFIG_ZLIB
29 #include <zlib.h>
30 #endif
31
32 /*
33 * First version by Francois Revol revol@free.fr
34 * Seek function by Gael Chardon gael.dev@4now.net
35 *
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
48 *
49 * Funny I didn't know about http://sourceforge.net/projects/qt-ffmpeg/
50 * when coding this :) (it's a writer anyway)
51 *
52 * Reference documents:
53 * http://www.geocities.com/xhelmboyx/quicktime/formats/qtm-layout.txt
54 * Apple:
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 :))
58 */
59
60 #include "qtpalette.h"
61
62
63 #undef NDEBUG
64 #include <assert.h>
65
66 /* Allows seeking */
67 #define MOV_SEEK
68
69 /* http://gpac.sourceforge.net/tutorial/mediatypes.htm */
70 const CodecTag ff_mov_obj_type[] = {
71 { CODEC_ID_MPEG4 , 32 },
72 { CODEC_ID_H264 , 33 },
73 { CODEC_ID_AAC , 64 },
74 { CODEC_ID_MPEG2VIDEO, 96 }, /* MPEG2 Simple */
75 { CODEC_ID_MPEG2VIDEO, 97 }, /* MPEG2 Main */
76 { CODEC_ID_MPEG2VIDEO, 98 }, /* MPEG2 SNR */
77 { CODEC_ID_MPEG2VIDEO, 99 }, /* MPEG2 Spatial */
78 { CODEC_ID_MPEG2VIDEO, 100 }, /* MPEG2 High */
79 { CODEC_ID_MPEG2VIDEO, 101 }, /* MPEG2 422 */
80 { CODEC_ID_AAC , 102 }, /* MPEG2 AAC Main */
81 { CODEC_ID_AAC , 103 }, /* MPEG2 AAC Low */
82 { CODEC_ID_AAC , 104 }, /* MPEG2 AAC SSR */
83 { CODEC_ID_MP3 , 105 },
84 { CODEC_ID_MPEG1VIDEO, 106 },
85 { CODEC_ID_MP2 , 107 },
86 { CODEC_ID_MJPEG , 108 },
87 { CODEC_ID_PCM_S16LE , 224 },
88 { CODEC_ID_VORBIS , 221 },
89 { CODEC_ID_AC3 , 226 },
90 { CODEC_ID_PCM_ALAW , 227 },
91 { CODEC_ID_PCM_MULAW , 228 },
92 { CODEC_ID_PCM_S16BE , 230 },
93 { CODEC_ID_H263 , 242 },
94 { CODEC_ID_H261 , 243 },
95 { 0, 0 },
96 };
97
98 static const CodecTag mov_video_tags[] = {
99 /* { CODEC_ID_, MKTAG('c', 'v', 'i', 'd') }, *//* Cinepak */
100 /* { CODEC_ID_H263, MKTAG('r', 'a', 'w', ' ') }, *//* Uncompressed RGB */
101 /* { CODEC_ID_H263, MKTAG('Y', 'u', 'v', '2') }, *//* Uncompressed YUV422 */
102 /* { CODEC_ID_RAWVIDEO, MKTAG('A', 'V', 'U', 'I') }, *//* YUV with alpha-channel (AVID Uncompressed) */
103 /* Graphics */
104 /* Animation */
105 /* Apple video */
106 /* Kodak Photo CD */
107 { CODEC_ID_MJPEG, MKTAG('j', 'p', 'e', 'g') }, /* PhotoJPEG */
108 { CODEC_ID_MPEG1VIDEO, MKTAG('m', 'p', 'e', 'g') }, /* MPEG */
109 { CODEC_ID_MJPEG, MKTAG('m', 'j', 'p', 'a') }, /* Motion-JPEG (format A) */
110 { CODEC_ID_MJPEGB, MKTAG('m', 'j', 'p', 'b') }, /* Motion-JPEG (format B) */
111 { CODEC_ID_MJPEG, MKTAG('A', 'V', 'D', 'J') }, /* MJPEG with alpha-channel (AVID JFIF meridien compressed) */
112 /* { CODEC_ID_MJPEG, MKTAG('A', 'V', 'R', 'n') }, *//* MJPEG with alpha-channel (AVID ABVB/Truevision NuVista) */
113 /* { CODEC_ID_GIF, MKTAG('g', 'i', 'f', ' ') }, *//* embedded gif files as frames (usually one "click to play movie" frame) */
114 /* Sorenson video */
115 { CODEC_ID_SVQ1, MKTAG('S', 'V', 'Q', '1') }, /* Sorenson Video v1 */
116 { CODEC_ID_SVQ1, MKTAG('s', 'v', 'q', '1') }, /* Sorenson Video v1 */
117 { CODEC_ID_SVQ1, MKTAG('s', 'v', 'q', 'i') }, /* Sorenson Video v1 (from QT specs)*/
118 { CODEC_ID_SVQ3, MKTAG('S', 'V', 'Q', '3') }, /* Sorenson Video v3 */
119 { CODEC_ID_MPEG4, MKTAG('m', 'p', '4', 'v') },
120 { CODEC_ID_MPEG4, MKTAG('D', 'I', 'V', 'X') }, /* OpenDiVX *//* sample files at http://heroinewarrior.com/xmovie.php3 use this tag */
121 { CODEC_ID_MPEG4, MKTAG('X', 'V', 'I', 'D') },
122 { CODEC_ID_MPEG4, MKTAG('3', 'I', 'V', '2') }, /* experimental: 3IVX files before ivx D4 4.5.1 */
123 /* { CODEC_ID_, MKTAG('I', 'V', '5', '0') }, *//* Indeo 5.0 */
124 { CODEC_ID_H263, MKTAG('h', '2', '6', '3') }, /* H263 */
125 { CODEC_ID_H263, MKTAG('s', '2', '6', '3') }, /* H263 ?? works */
126 { CODEC_ID_DVVIDEO, MKTAG('d', 'v', 'c', ' ') }, /* DV NTSC */
127 { CODEC_ID_DVVIDEO, MKTAG('d', 'v', 'c', 'p') }, /* DV PAL */
128 /* { CODEC_ID_DVVIDEO, MKTAG('A', 'V', 'd', 'v') }, *//* AVID dv */
129 { CODEC_ID_VP3, MKTAG('V', 'P', '3', '1') }, /* On2 VP3 */
130 { CODEC_ID_RPZA, MKTAG('r', 'p', 'z', 'a') }, /* Apple Video (RPZA) */
131 { CODEC_ID_CINEPAK, MKTAG('c', 'v', 'i', 'd') }, /* Cinepak */
132 { CODEC_ID_8BPS, MKTAG('8', 'B', 'P', 'S') }, /* Planar RGB (8BPS) */
133 { CODEC_ID_SMC, MKTAG('s', 'm', 'c', ' ') }, /* Apple Graphics (SMC) */
134 { CODEC_ID_QTRLE, MKTAG('r', 'l', 'e', ' ') }, /* Apple Animation (RLE) */
135 { CODEC_ID_QDRAW, MKTAG('q', 'd', 'r', 'w') }, /* QuickDraw */
136 { CODEC_ID_H264, MKTAG('a', 'v', 'c', '1') }, /* AVC-1/H.264 */
137 { CODEC_ID_MPEG2VIDEO, MKTAG('h', 'd', 'v', '2') }, /* MPEG2 produced by Sony HD camera */
138 { CODEC_ID_MPEG2VIDEO, MKTAG('h', 'd', 'v', '3') }, /* HDV produced by FCP */
139 { CODEC_ID_MPEG2VIDEO, MKTAG('m', 'x', '5', 'n') }, /* MPEG2 IMX NTSC 525/60 50mb/s produced by FCP */
140 { CODEC_ID_MPEG2VIDEO, MKTAG('m', 'x', '5', 'p') }, /* MPEG2 IMX PAL 625/50 50mb/s produced by FCP */
141 { CODEC_ID_MPEG2VIDEO, MKTAG('m', 'x', '3', 'n') }, /* MPEG2 IMX NTSC 525/60 30mb/s produced by FCP */
142 { CODEC_ID_MPEG2VIDEO, MKTAG('m', 'x', '3', 'p') }, /* MPEG2 IMX PAL 625/50 30mb/s produced by FCP */
143 { CODEC_ID_DVVIDEO, MKTAG('d', 'v', 'p', 'p') }, /* DVCPRO PAL produced by FCP */
144 //{ CODEC_ID_DVVIDEO, MKTAG('d', 'v', 'h', '5') }, /* DVCPRO HD 50i produced by FCP */
145 //{ CODEC_ID_DVVIDEO, MKTAG('d', 'v', 'h', '6') }, /* DVCPRO HD 60i produced by FCP */
146 { CODEC_ID_DVVIDEO, MKTAG('d', 'v', '5', 'p') }, /* DVCPRO50 PAL produced by FCP */
147 { CODEC_ID_DVVIDEO, MKTAG('d', 'v', '5', 'n') }, /* DVCPRO50 NTSC produced by FCP */
148 { CODEC_ID_DVVIDEO, MKTAG('A', 'V', 'd', 'v') }, /* AVID DV */
149 //{ CODEC_ID_JPEG2000, MKTAG('m', 'j', 'p', '2') }, /* JPEG 2000 produced by FCP */
150 { CODEC_ID_RAWVIDEO, MKTAG('2', 'v', 'u', 'y') }, /* UNCOMPRESSED 8BIT 4:2:2 */
151 { CODEC_ID_NONE, 0 },
152 };
153
154 static const CodecTag mov_audio_tags[] = {
155 { CODEC_ID_PCM_S32BE, MKTAG('i', 'n', '3', '2') },
156 { CODEC_ID_PCM_S24BE, MKTAG('i', 'n', '2', '4') },
157 /* { CODEC_ID_PCM_S16BE, MKTAG('N', 'O', 'N', 'E') }, *//* uncompressed */
158 { CODEC_ID_PCM_S16BE, MKTAG('t', 'w', 'o', 's') }, /* 16 bits */
159 /* { CODEC_ID_PCM_S8, MKTAG('t', 'w', 'o', 's') },*/ /* 8 bits */
160 { CODEC_ID_PCM_U8, MKTAG('r', 'a', 'w', ' ') }, /* 8 bits unsigned */
161 { CODEC_ID_PCM_S16LE, MKTAG('s', 'o', 'w', 't') }, /* */
162 { CODEC_ID_PCM_MULAW, MKTAG('u', 'l', 'a', 'w') }, /* */
163 { CODEC_ID_PCM_ALAW, MKTAG('a', 'l', 'a', 'w') }, /* */
164 { CODEC_ID_ADPCM_IMA_QT, MKTAG('i', 'm', 'a', '4') }, /* IMA-4 ADPCM */
165 { CODEC_ID_MACE3, MKTAG('M', 'A', 'C', '3') }, /* Macintosh Audio Compression and Expansion 3:1 */
166 { CODEC_ID_MACE6, MKTAG('M', 'A', 'C', '6') }, /* Macintosh Audio Compression and Expansion 6:1 */
167
168 { CODEC_ID_MP2, MKTAG('.', 'm', 'p', '3') }, /* MPEG layer 3 */ /* sample files at http://www.3ivx.com/showcase.html use this tag */
169 { CODEC_ID_MP2, 0x6D730055 }, /* MPEG layer 3 */
170 { CODEC_ID_MP2, 0x5500736D }, /* MPEG layer 3 *//* XXX: check endianness */
171 /* { CODEC_ID_OGG_VORBIS, MKTAG('O', 'g', 'g', 'S') }, *//* sample files at http://heroinewarrior.com/xmovie.php3 use this tag */
172 /* MP4 tags */
173 { CODEC_ID_AAC, MKTAG('m', 'p', '4', 'a') }, /* MPEG-4 AAC */
174 /* The standard for mpeg4 audio is still not normalised AFAIK anyway */
175 { CODEC_ID_AMR_NB, MKTAG('s', 'a', 'm', 'r') }, /* AMR-NB 3gp */
176 { CODEC_ID_AMR_WB, MKTAG('s', 'a', 'w', 'b') }, /* AMR-WB 3gp */
177 { CODEC_ID_AC3, MKTAG('m', 's', 0x20, 0x00) }, /* Dolby AC-3 */
178 { CODEC_ID_ALAC,MKTAG('a', 'l', 'a', 'c') }, /* Apple Lossless */
179 { CODEC_ID_QDM2,MKTAG('Q', 'D', 'M', '2') }, /* QDM2 */
180 { CODEC_ID_NONE, 0 },
181 };
182
183 /* map numeric codes from mdhd atom to ISO 639 */
184 /* cf. QTFileFormat.pdf p253, qtff.pdf p205 */
185 /* http://developer.apple.com/documentation/mac/Text/Text-368.html */
186 /* deprecated by putting the code as 3*5bit ascii */
187 static const char *mov_mdhd_language_map[] = {
188 /* 0-9 */
189 "eng", "fra", "ger", "ita", "dut", "sve", "spa", "dan", "por", "nor",
190 "heb", "jpn", "ara", "fin", "gre", "ice", "mlt", "tur", "hr "/*scr*/, "chi"/*ace?*/,
191 "urd", "hin", "tha", "kor", "lit", "pol", "hun", "est", "lav", NULL,
192 "fo ", NULL, "rus", "chi", NULL, "iri", "alb", "ron", "ces", "slk",
193 "slv", "yid", "sr ", "mac", "bul", "ukr", "bel", "uzb", "kaz", "aze",
194 /*?*/
195 "aze", "arm", "geo", "mol", "kir", "tgk", "tuk", "mon", NULL, "pus",
196 "kur", "kas", "snd", "tib", "nep", "san", "mar", "ben", "asm", "guj",
197 "pa ", "ori", "mal", "kan", "tam", "tel", NULL, "bur", "khm", "lao",
198 /* roman? arabic? */
199 "vie", "ind", "tgl", "may", "may", "amh", "tir", "orm", "som", "swa",
200 /*==rundi?*/
201 NULL, "run", NULL, "mlg", "epo", NULL, NULL, NULL, NULL, NULL,
202 /* 100 */
203 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
204 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
205 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, "wel", "baq",
206 "cat", "lat", "que", "grn", "aym", "tat", "uig", "dzo", "jav"
207 };
208
209 /* the QuickTime file format is quite convoluted...
210 * it has lots of index tables, each indexing something in another one...
211 * Here we just use what is needed to read the chunks
212 */
213
214 typedef struct MOV_sample_to_chunk_tbl {
215 long first;
216 long count;
217 long id;
218 } MOV_sample_to_chunk_tbl;
219
220 typedef struct {
221 uint32_t type;
222 int64_t offset;
223 int64_t size; /* total size (excluding the size and type fields) */
224 } MOV_atom_t;
225
226 typedef struct {
227 int seed;
228 int flags;
229 int size;
230 void* clrs;
231 } MOV_ctab_t;
232
233 typedef struct {
234 uint8_t version;
235 uint32_t flags; // 24bit
236
237 /* 0x03 ESDescrTag */
238 uint16_t es_id;
239 #define MP4ODescrTag 0x01
240 #define MP4IODescrTag 0x02
241 #define MP4ESDescrTag 0x03
242 #define MP4DecConfigDescrTag 0x04
243 #define MP4DecSpecificDescrTag 0x05
244 #define MP4SLConfigDescrTag 0x06
245 #define MP4ContentIdDescrTag 0x07
246 #define MP4SupplContentIdDescrTag 0x08
247 #define MP4IPIPtrDescrTag 0x09
248 #define MP4IPMPPtrDescrTag 0x0A
249 #define MP4IPMPDescrTag 0x0B
250 #define MP4RegistrationDescrTag 0x0D
251 #define MP4ESIDIncDescrTag 0x0E
252 #define MP4ESIDRefDescrTag 0x0F
253 #define MP4FileIODescrTag 0x10
254 #define MP4FileODescrTag 0x11
255 #define MP4ExtProfileLevelDescrTag 0x13
256 #define MP4ExtDescrTagsStart 0x80
257 #define MP4ExtDescrTagsEnd 0xFE
258 uint8_t stream_priority;
259
260 /* 0x04 DecConfigDescrTag */
261 uint8_t object_type_id;
262 uint8_t stream_type;
263 /* XXX: really streamType is
264 * only 6bit, followed by:
265 * 1bit upStream
266 * 1bit reserved
267 */
268 uint32_t buffer_size_db; // 24
269 uint32_t max_bitrate;
270 uint32_t avg_bitrate;
271
272 /* 0x05 DecSpecificDescrTag */
273 uint8_t decoder_cfg_len;
274 uint8_t *decoder_cfg;
275
276 /* 0x06 SLConfigDescrTag */
277 uint8_t sl_config_len;
278 uint8_t *sl_config;
279 } MOV_esds_t;
280
281 struct MOVParseTableEntry;
282
283 typedef struct MOVStreamContext {
284 int ffindex; /* the ffmpeg stream id */
285 long next_chunk;
286 long chunk_count;
287 int64_t *chunk_offsets;
288 int stts_count;
289 Time2Sample *stts_data;
290 int ctts_count;
291 Time2Sample *ctts_data;
292 int edit_count; /* number of 'edit' (elst atom) */
293 long sample_to_chunk_sz;
294 MOV_sample_to_chunk_tbl *sample_to_chunk;
295 long sample_to_chunk_index;
296 int sample_to_time_index;
297 long sample_to_time_sample;
298 uint64_t sample_to_time_time;
299 int sample_to_ctime_index;
300 int sample_to_ctime_sample;
301 long sample_size;
302 long sample_count;
303 long *sample_sizes;
304 long keyframe_count;
305 long *keyframes;
306 int time_scale;
307 int time_rate;
308 long current_sample;
309 long left_in_chunk; /* how many samples before next chunk */
310 MOV_esds_t esds;
311 } MOVStreamContext;
312
313 typedef struct MOVContext {
314 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) */
315 AVFormatContext *fc;
316 int time_scale;
317 int64_t duration; /* duration of the longest track */
318 int found_moov; /* when both 'moov' and 'mdat' sections has been found */
319 int found_mdat; /* we suppose we have enough data to read the file */
320 int64_t mdat_size;
321 int64_t mdat_offset;
322 int ni; ///< non interleaved mode
323 int total_streams;
324 /* some streams listed here aren't presented to the ffmpeg API, since they aren't either video nor audio
325 * but we need the info to be able to skip data from those streams in the 'mdat' section
326 */
327 MOVStreamContext *streams[MAX_STREAMS];
328
329 int64_t next_chunk_offset;
330 MOVStreamContext *partial; /* != 0 : there is still to read in the current chunk */
331 int ctab_size;
332 MOV_ctab_t **ctab; /* color tables */
333 const struct MOVParseTableEntry *parse_table; /* could be eventually used to change the table */
334 /* NOTE: for recursion save to/ restore from local variable! */
335
336 AVPaletteControl palette_control;
337 } MOVContext;
338
339
340 /* XXX: it's the first time I make a recursive parser I think... sorry if it's ugly :P */
341
342 /* those functions parse an atom */
343 /* return code:
344 1: found what I wanted, exit
345 0: continue to parse next atom
346 -1: error occured, exit
347 */
348 typedef int (*mov_parse_function)(MOVContext *ctx, ByteIOContext *pb, MOV_atom_t atom);
349
350 /* links atom IDs to parse functions */
351 typedef struct MOVParseTableEntry {
352 uint32_t type;
353 mov_parse_function func;
354 } MOVParseTableEntry;
355
356 static int ff_mov_lang_to_iso639(int code, char *to)
357 {
358 int i;
359 /* is it the mangled iso code? */
360 /* see http://www.geocities.com/xhelmboyx/quicktime/formats/mp4-layout.txt */
361 if (code > 138) {
362 for (i = 2; i >= 0; i--) {
363 to[i] = 0x60 + (code & 0x1f);
364 code >>= 5;
365 }
366 return 1;
367 }
368 /* old fashion apple lang code */
369 if (code >= (sizeof(mov_mdhd_language_map)/sizeof(char *)))
370 return 0;
371 if (!mov_mdhd_language_map[code])
372 return 0;
373 strncpy(to, mov_mdhd_language_map[code], 4);
374 return 1;
375 }
376
377 int ff_mov_iso639_to_lang(const char *lang, int mp4)
378 {
379 int i, code = 0;
380
381 /* old way, only for QT? */
382 for (i = 0; !mp4 && (i < (sizeof(mov_mdhd_language_map)/sizeof(char *))); i++) {
383 if (mov_mdhd_language_map[i] && !strcmp(lang, mov_mdhd_language_map[i]))
384 return i;
385 }
386 /* XXX:can we do that in mov too? */
387 if (!mp4)
388 return 0;
389 /* handle undefined as such */
390 if (lang[0] == '\0')
391 lang = "und";
392 /* 5bit ascii */
393 for (i = 0; i < 3; i++) {
394 unsigned char c = (unsigned char)lang[i];
395 if (c < 0x60)
396 return 0;
397 if (c > 0x60 + 0x1f)
398 return 0;
399 code <<= 5;
400 code |= (c - 0x60);
401 }
402 return code;
403 }
404
405 static int mov_read_leaf(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
406 {
407 if (atom.size>1)
408 url_fskip(pb, atom.size);
409 /* url_seek(pb, atom_offset+atom.size, SEEK_SET); */
410 return 0;
411 }
412
413 static int mov_read_default(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
414 {
415 int64_t total_size = 0;
416 MOV_atom_t a;
417 int i;
418 int err = 0;
419
420 a.offset = atom.offset;
421
422 if (atom.size < 0)
423 atom.size = 0x7fffffffffffffffLL;
424 while(((total_size + 8) < atom.size) && !url_feof(pb) && !err) {
425 a.size = atom.size;
426 a.type=0L;
427 if(atom.size >= 8) {
428 a.size = get_be32(pb);
429 a.type = get_le32(pb);
430 }
431 total_size += 8;
432 a.offset += 8;
433 dprintf("type: %08x %.4s sz: %"PRIx64" %"PRIx64" %"PRIx64"\n", a.type, (char*)&a.type, a.size, atom.size, total_size);
434 if (a.size == 1) { /* 64 bit extended size */
435 a.size = get_be64(pb) - 8;
436 a.offset += 8;
437 total_size += 8;
438 }
439 if (a.size == 0) {
440 a.size = atom.size - total_size;
441 if (a.size <= 8)
442 break;
443 }
444 for (i = 0; c->parse_table[i].type != 0L
445 && c->parse_table[i].type != a.type; i++)
446 /* empty */;
447
448 a.size -= 8;
449
450 if(a.size < 0)
451 break;
452
453 if (c->parse_table[i].type == 0) { /* skip leaf atoms data */
454 url_fskip(pb, a.size);
455 } else {
456 offset_t start_pos = url_ftell(pb);
457 int64_t left;
458 err = (c->parse_table[i].func)(c, pb, a);
459 left = a.size - url_ftell(pb) + start_pos;
460 if (left > 0) /* skip garbage at atom end */
461 url_fskip(pb, left);
462 }
463
464 a.offset += a.size;
465 total_size += a.size;
466 }
467
468 if (!err && total_size < atom.size && atom.size < 0x7ffff) {
469 url_fskip(pb, atom.size - total_size);
470 }
471
472 return err;
473 }
474
475 static int mov_read_ctab(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
476 {
477 #if 1
478 url_fskip(pb, atom.size); // for now
479 #else
480 VERY VERY BROKEN, NEVER execute this, needs rewrite
481 unsigned int len;
482 MOV_ctab_t *t;
483 c->ctab = av_realloc(c->ctab, ++c->ctab_size);
484 t = c->ctab[c->ctab_size];
485 t->seed = get_be32(pb);
486 t->flags = get_be16(pb);
487 t->size = get_be16(pb) + 1;
488 len = 2 * t->size * 4;
489 if (len > 0) {
490 t->clrs = av_malloc(len); // 16bit A R G B
491 if (t->clrs)
492 get_buffer(pb, t->clrs, len);
493 }
494 #endif
495
496 return 0;
497 }
498
499 static int mov_read_hdlr(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
500 {
501 AVStream *st = c->fc->streams[c->fc->nb_streams-1];
502 int len = 0;
503 uint32_t type;
504 uint32_t ctype;
505
506 get_byte(pb); /* version */
507 get_byte(pb); get_byte(pb); get_byte(pb); /* flags */
508
509 /* component type */
510 ctype = get_le32(pb);
511 type = get_le32(pb); /* component subtype */
512
513 dprintf("ctype= %c%c%c%c (0x%08lx)\n", *((char *)&ctype), ((char *)&ctype)[1], ((char *)&ctype)[2], ((char *)&ctype)[3], (long) ctype);
514 dprintf("stype= %c%c%c%c\n", *((char *)&type), ((char *)&type)[1], ((char *)&type)[2], ((char *)&type)[3]);
515 if(ctype == MKTAG('m', 'h', 'l', 'r')) /* MOV */
516 c->mp4 = 0;
517 else if(ctype == 0)
518 c->mp4 = 1;
519 if(type == MKTAG('v', 'i', 'd', 'e'))
520 st->codec->codec_type = CODEC_TYPE_VIDEO;
521 else if(type == MKTAG('s', 'o', 'u', 'n'))
522 st->codec->codec_type = CODEC_TYPE_AUDIO;
523 get_be32(pb); /* component manufacture */
524 get_be32(pb); /* component flags */
525 get_be32(pb); /* component flags mask */
526
527 if(atom.size <= 24)
528 return 0; /* nothing left to read */
529 /* XXX: MP4 uses a C string, not a pascal one */
530 /* component name */
531
532 if(c->mp4) {
533 /* .mp4: C string */
534 while(get_byte(pb) && (++len < (atom.size - 24)));
535 } else {
536 /* .mov: PASCAL string */
537 len = get_byte(pb);
538 url_fskip(pb, len);
539 }
540
541 url_fskip(pb, atom.size - (url_ftell(pb) - atom.offset));
542 return 0;
543 }
544
545 static int mov_mp4_read_descr_len(ByteIOContext *pb)
546 {
547 int len = 0;
548 int count = 4;
549 while (count--) {
550 int c = get_byte(pb);
551 len = (len << 7) | (c & 0x7f);
552 if (!(c & 0x80))
553 break;
554 }
555 return len;
556 }
557
558 static int mov_mp4_read_descr(ByteIOContext *pb, int *tag)
559 {
560 int len;
561 *tag = get_byte(pb);
562 len = mov_mp4_read_descr_len(pb);
563 dprintf("MPEG4 description: tag=0x%02x len=%d\n", *tag, len);
564 return len;
565 }
566
567 static int mov_read_esds(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
568 {
569 AVStream *st = c->fc->streams[c->fc->nb_streams-1];
570 MOVStreamContext *sc = (MOVStreamContext *)st->priv_data;
571 int tag, len;
572
573 /* Well, broken but suffisant for some MP4 streams */
574 get_be32(pb); /* version + flags */
575 len = mov_mp4_read_descr(pb, &tag);
576 if (tag == MP4ESDescrTag) {
577 get_be16(pb); /* ID */
578 get_byte(pb); /* priority */
579 } else
580 get_be16(pb); /* ID */
581
582 len = mov_mp4_read_descr(pb, &tag);
583 if (tag == MP4DecConfigDescrTag) {
584 sc->esds.object_type_id = get_byte(pb);
585 sc->esds.stream_type = get_byte(pb);
586 sc->esds.buffer_size_db = get_be24(pb);
587 sc->esds.max_bitrate = get_be32(pb);
588 sc->esds.avg_bitrate = get_be32(pb);
589
590 st->codec->codec_id= codec_get_id(ff_mov_obj_type, sc->esds.object_type_id);
591 len = mov_mp4_read_descr(pb, &tag);
592 if (tag == MP4DecSpecificDescrTag) {
593 dprintf("Specific MPEG4 header len=%d\n", len);
594 st->codec->extradata = (uint8_t*) av_mallocz(len + FF_INPUT_BUFFER_PADDING_SIZE);
595 if (st->codec->extradata) {
596 get_buffer(pb, st->codec->extradata, len);
597 st->codec->extradata_size = len;
598 /* from mplayer */
599 if ((*(uint8_t *)st->codec->extradata >> 3) == 29) {
600 st->codec->codec_id = CODEC_ID_MP3ON4;
601 }
602 }
603 }
604 }
605 return 0;
606 }
607
608 /* this atom contains actual media data */
609 static int mov_read_mdat(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
610 {
611 if(atom.size == 0) /* wrong one (MP4) */
612 return 0;
613 c->found_mdat=1;
614 c->mdat_offset = atom.offset;
615 c->mdat_size = atom.size;
616 if(c->found_moov)
617 return 1; /* found both, just go */
618 url_fskip(pb, atom.size);
619 return 0; /* now go for moov */
620 }
621
622 static int mov_read_ftyp(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
623 {
624 uint32_t type = get_le32(pb);
625
626 /* from mplayer */
627 switch (type) {
628 case MKTAG('i', 's', 'o', 'm'):
629 case MKTAG('m', 'p', '4', '1'):
630 case MKTAG('m', 'p', '4', '2'):
631 case MKTAG('3', 'g', 'p', '1'):
632 case MKTAG('3', 'g', 'p', '2'):
633 case MKTAG('3', 'g', '2', 'a'):
634 case MKTAG('3', 'g', 'p', '3'):
635 case MKTAG('3', 'g', 'p', '4'):
636 case MKTAG('3', 'g', 'p', '5'):
637 case MKTAG('m', 'm', 'p', '4'): /* Mobile MP4 */
638 case MKTAG('M', '4', 'A', ' '): /* Apple iTunes AAC-LC Audio */
639 case MKTAG('M', '4', 'P', ' '): /* Apple iTunes AAC-LC Protected Audio */
640 case MKTAG('m', 'j', 'p', '2'): /* Motion Jpeg 2000 */
641 c->mp4 = 1;
642 case MKTAG('q', 't', ' ', ' '):
643 default:
644 av_log(c->fc, AV_LOG_DEBUG, "ISO: File Type Major Brand: %.4s\n",(char *)&type);
645 }
646 get_be32(pb); /* minor version */
647 url_fskip(pb, atom.size - 8);
648 return 0;
649 }
650
651 /* this atom should contain all header atoms */
652 static int mov_read_moov(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
653 {
654 int err;
655
656 err = mov_read_default(c, pb, atom);
657 /* we parsed the 'moov' atom, we can terminate the parsing as soon as we find the 'mdat' */
658 /* so we don't parse the whole file if over a network */
659 c->found_moov=1;
660 if(c->found_mdat)
661 return 1; /* found both, just go */
662 return 0; /* now go for mdat */
663 }
664
665
666 static int mov_read_mdhd(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
667 {
668 AVStream *st = c->fc->streams[c->fc->nb_streams-1];
669 MOVStreamContext *sc = (MOVStreamContext *)st->priv_data;
670 int version = get_byte(pb);
671 int lang;
672
673 if (version > 1)
674 return 1; /* unsupported */
675
676 get_byte(pb); get_byte(pb);
677 get_byte(pb); /* flags */
678
679 if (version == 1) {
680 get_be64(pb);
681 get_be64(pb);
682 } else {
683 get_be32(pb); /* creation time */
684 get_be32(pb); /* modification time */
685 }
686
687 sc->time_scale = get_be32(pb);
688 st->duration = (version == 1) ? get_be64(pb) : get_be32(pb); /* duration */
689
690 lang = get_be16(pb); /* language */
691 ff_mov_lang_to_iso639(lang, st->language);
692 get_be16(pb); /* quality */
693
694 return 0;
695 }
696
697 static int mov_read_mvhd(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
698 {
699 int version = get_byte(pb); /* version */
700 get_byte(pb); get_byte(pb); get_byte(pb); /* flags */
701
702 if (version == 1) {
703 get_be64(pb);
704 get_be64(pb);
705 } else {
706 get_be32(pb); /* creation time */
707 get_be32(pb); /* modification time */
708 }
709 c->time_scale = get_be32(pb); /* time scale */
710 #ifdef DEBUG
711 av_log(NULL, AV_LOG_DEBUG, "time scale = %i\n", c->time_scale);
712 #endif
713 c->duration = (version == 1) ? get_be64(pb) : get_be32(pb); /* duration */
714 get_be32(pb); /* preferred scale */
715
716 get_be16(pb); /* preferred volume */
717
718 url_fskip(pb, 10); /* reserved */
719
720 url_fskip(pb, 36); /* display matrix */
721
722 get_be32(pb); /* preview time */
723 get_be32(pb); /* preview duration */
724 get_be32(pb); /* poster time */
725 get_be32(pb); /* selection time */
726 get_be32(pb); /* selection duration */
727 get_be32(pb); /* current time */
728 get_be32(pb); /* next track ID */
729
730 return 0;
731 }
732
733 static int mov_read_smi(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
734 {
735 AVStream *st = c->fc->streams[c->fc->nb_streams-1];
736
737 if((uint64_t)atom.size > (1<<30))
738 return -1;
739
740 // currently SVQ3 decoder expect full STSD header - so let's fake it
741 // this should be fixed and just SMI header should be passed
742 av_free(st->codec->extradata);
743 st->codec->extradata_size = 0x5a + atom.size;
744 st->codec->extradata = (uint8_t*) av_mallocz(st->codec->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE);
745
746 if (st->codec->extradata) {
747 strcpy(st->codec->extradata, "SVQ3"); // fake
748 get_buffer(pb, st->codec->extradata + 0x5a, atom.size);
749 dprintf("Reading SMI %"PRId64" %s\n", atom.size, (char*)st->codec->extradata + 0x5a);
750 } else
751 url_fskip(pb, atom.size);
752
753 return 0;
754 }
755
756 static int mov_read_enda(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
757 {
758 AVStream *st = c->fc->streams[c->fc->nb_streams-1];
759 int little_endian = get_be16(pb);
760
761 if (little_endian) {
762 switch (st->codec->codec_id) {
763 case CODEC_ID_PCM_S24BE:
764 st->codec->codec_id = CODEC_ID_PCM_S24LE;
765 break;
766 case CODEC_ID_PCM_S32BE:
767 st->codec->codec_id = CODEC_ID_PCM_S32LE;
768 break;
769 default:
770 break;
771 }
772 }
773 return 0;
774 }
775
776 static int mov_read_alac(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
777 {
778 AVStream *st = c->fc->streams[c->fc->nb_streams-1];
779
780 // currently ALAC decoder expect full atom header - so let's fake it
781 // this should be fixed and just ALAC header should be passed
782
783 av_free(st->codec->extradata);
784 st->codec->extradata_size = 36;
785 st->codec->extradata = (uint8_t*) av_mallocz(st->codec->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE);
786
787 if (st->codec->extradata) {
788 strcpy(st->codec->extradata + 4, "alac"); // fake
789 get_buffer(pb, st->codec->extradata + 8, 36 - 8);
790 dprintf("Reading alac %d %s\n", st->codec->extradata_size, (char*)st->codec->extradata);
791 } else
792 url_fskip(pb, atom.size);
793 return 0;
794 }
795
796 static int mov_read_wave(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
797 {
798 AVStream *st = c->fc->streams[c->fc->nb_streams-1];
799
800 if((uint64_t)atom.size > (1<<30))
801 return -1;
802
803 if (st->codec->codec_id == CODEC_ID_QDM2) {
804 // pass all frma atom to codec, needed at least for QDM2
805 av_free(st->codec->extradata);
806 st->codec->extradata_size = atom.size;
807 st->codec->extradata = (uint8_t*) av_mallocz(st->codec->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE);
808
809 if (st->codec->extradata) {
810 get_buffer(pb, st->codec->extradata, atom.size);
811 } else
812 url_fskip(pb, atom.size);
813 } else if (atom.size > 8) { /* to read frma, esds atoms */
814 mov_read_default(c, pb, atom);
815 } else
816 url_fskip(pb, atom.size);
817 return 0;
818 }
819
820 static int mov_read_jp2h(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
821 {
822 AVStream *st = c->fc->streams[c->fc->nb_streams-1];
823
824 if((uint64_t)atom.size > (1<<30))
825 return -1;
826
827 av_free(st->codec->extradata);
828
829 st->codec->extradata_size = atom.size + 8;
830 st->codec->extradata = (uint8_t*) av_mallocz(st->codec->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE);
831
832 /* pass all jp2h atom to codec */
833 if (st->codec->extradata) {
834 strcpy(st->codec->extradata + 4, "jp2h");
835 get_buffer(pb, st->codec->extradata + 8, atom.size);
836 } else
837 url_fskip(pb, atom.size);
838 return 0;
839 }
840
841 static int mov_read_avcC(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
842 {
843 AVStream *st = c->fc->streams[c->fc->nb_streams-1];
844
845 if((uint64_t)atom.size > (1<<30))
846 return -1;
847
848 av_free(st->codec->extradata);
849
850 st->codec->extradata_size = atom.size;
851 st->codec->extradata = (uint8_t*) av_mallocz(st->codec->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE);
852
853 if (st->codec->extradata) {
854 get_buffer(pb, st->codec->extradata, atom.size);
855 } else
856 url_fskip(pb, atom.size);
857
858 return 0;
859 }
860
861 static int mov_read_stco(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
862 {
863 AVStream *st = c->fc->streams[c->fc->nb_streams-1];
864 MOVStreamContext *sc = (MOVStreamContext *)st->priv_data;
865 unsigned int i, entries;
866
867 get_byte(pb); /* version */
868 get_byte(pb); get_byte(pb); get_byte(pb); /* flags */
869
870 entries = get_be32(pb);
871
872 if(entries >= UINT_MAX/sizeof(int64_t))
873 return -1;
874
875 sc->chunk_count = entries;
876 sc->chunk_offsets = (int64_t*) av_malloc(entries * sizeof(int64_t));
877 if (!sc->chunk_offsets)
878 return -1;
879 if (atom.type == MKTAG('s', 't', 'c', 'o')) {
880 for(i=0; i<entries; i++) {
881 sc->chunk_offsets[i] = get_be32(pb);
882 }
883 } else if (atom.type == MKTAG('c', 'o', '6', '4')) {
884 for(i=0; i<entries; i++) {
885 sc->chunk_offsets[i] = get_be64(pb);
886 }
887 } else
888 return -1;
889
890 for(i=0; i<c->fc->nb_streams; i++){
891 MOVStreamContext *sc2 = (MOVStreamContext *)c->fc->streams[i]->priv_data;
892 if(sc2 && sc2->chunk_offsets){
893 int64_t first= sc2->chunk_offsets[0];
894 int64_t last= sc2->chunk_offsets[sc2->chunk_count-1];
895 if(first >= sc->chunk_offsets[entries-1] || last <= sc->chunk_offsets[0])
896 c->ni=1;
897 }
898 }
899 return 0;
900 }
901
902 static int mov_read_stsd(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
903 {
904 AVStream *st = c->fc->streams[c->fc->nb_streams-1];
905 MOVStreamContext *sc = (MOVStreamContext *)st->priv_data;
906 int entries, frames_per_sample;
907 uint32_t format;
908 uint8_t codec_name[32];
909
910 /* for palette traversal */
911 int color_depth;
912 int color_start;
913 int color_count;
914 int color_end;
915 int color_index;
916 int color_dec;
917 int color_greyscale;
918 unsigned char *color_table;
919 int j;
920 unsigned char r, g, b;
921
922 get_byte(pb); /* version */
923 get_byte(pb); get_byte(pb); get_byte(pb); /* flags */
924
925 entries = get_be32(pb);
926
927 while(entries--) { //Parsing Sample description table
928 enum CodecID id;
929 MOV_atom_t a = { 0, 0, 0 };
930 offset_t start_pos = url_ftell(pb);
931 int size = get_be32(pb); /* size */
932 format = get_le32(pb); /* data format */
933
934 get_be32(pb); /* reserved */
935 get_be16(pb); /* reserved */
936 get_be16(pb); /* index */
937
938 st->codec->codec_tag = format;
939 id = codec_get_id(mov_audio_tags, format);
940 if (id > 0) {
941 st->codec->codec_type = CODEC_TYPE_AUDIO;
942 } else if (format && format != MKTAG('m', 'p', '4', 's')) { /* skip old asf mpeg4 tag */
943 id = codec_get_id(mov_video_tags, format);
944 if (id <= 0)
945 id = codec_get_id(codec_bmp_tags, format);
946 if (id > 0)
947 st->codec->codec_type = CODEC_TYPE_VIDEO;
948 }
949
950 dprintf("size=%d 4CC= %c%c%c%c codec_type=%d\n",
951 size,
952 (format >> 0) & 0xff, (format >> 8) & 0xff, (format >> 16) & 0xff, (format >> 24) & 0xff,
953 st->codec->codec_type);
954
955 if(st->codec->codec_type==CODEC_TYPE_VIDEO) {
956 st->codec->codec_id = id;
957 get_be16(pb); /* version */
958 get_be16(pb); /* revision level */
959 get_be32(pb); /* vendor */
960 get_be32(pb); /* temporal quality */
961 get_be32(pb); /* spacial quality */
962
963 st->codec->width = get_be16(pb); /* width */
964 st->codec->height = get_be16(pb); /* height */
965
966 get_be32(pb); /* horiz resolution */
967 get_be32(pb); /* vert resolution */
968 get_be32(pb); /* data size, always 0 */
969 frames_per_sample = get_be16(pb); /* frames per samples */
970 #ifdef DEBUG
971 av_log(NULL, AV_LOG_DEBUG, "frames/samples = %d\n", frames_per_sample);
972 #endif
973 get_buffer(pb, codec_name, 32); /* codec name, pascal string (FIXME: true for mp4?) */
974 if (codec_name[0] <= 31) {
975 memcpy(st->codec->codec_name, &codec_name[1],codec_name[0]);
976 st->codec->codec_name[codec_name[0]] = 0;
977 }
978
979 st->codec->bits_per_sample = get_be16(pb); /* depth */
980 st->codec->color_table_id = get_be16(pb); /* colortable id */
981
982 /* These are set in mov_read_stts and might already be set!
983 st->codec->time_base.den = 25;
984 st->codec->time_base.num = 1;
985 */
986
987 /* figure out the palette situation */
988 color_depth = st->codec->bits_per_sample & 0x1F;
989 color_greyscale = st->codec->bits_per_sample & 0x20;
990
991 /* if the depth is 2, 4, or 8 bpp, file is palettized */
992 if ((color_depth == 2) || (color_depth == 4) ||
993 (color_depth == 8)) {
994
995 if (color_greyscale) {
996
997 /* compute the greyscale palette */
998 color_count = 1 << color_depth;
999 color_index = 255;
1000 color_dec = 256 / (color_count - 1);
1001 for (j = 0; j < color_count; j++) {
1002 r = g = b = color_index;
1003 c->palette_control.palette[j] =
1004 (r << 16) | (g << 8) | (b);
1005 color_index -= color_dec;
1006 if (color_index < 0)
1007 color_index = 0;
1008 }
1009
1010 } else if (st->codec->color_table_id & 0x08) {
1011
1012 /* if flag bit 3 is set, use the default palette */
1013 color_count = 1 << color_depth;
1014 if (color_depth == 2)
1015 color_table = ff_qt_default_palette_4;
1016 else if (color_depth == 4)
1017 color_table = ff_qt_default_palette_16;
1018 else
1019 color_table = ff_qt_default_palette_256;
1020
1021 for (j = 0; j < color_count; j++) {
1022 r = color_table[j * 4 + 0];
1023 g = color_table[j * 4 + 1];
1024 b = color_table[j * 4 + 2];
1025 c->palette_control.palette[j] =
1026 (r << 16) | (g << 8) | (b);
1027 }
1028
1029 } else {
1030
1031 /* load the palette from the file */
1032 color_start = get_be32(pb);
1033 color_count = get_be16(pb);
1034 color_end = get_be16(pb);
1035 for (j = color_start; j <= color_end; j++) {
1036 /* each R, G, or B component is 16 bits;
1037 * only use the top 8 bits; skip alpha bytes
1038 * up front */
1039 get_byte(pb);
1040 get_byte(pb);
1041 r = get_byte(pb);
1042 get_byte(pb);
1043 g = get_byte(pb);
1044 get_byte(pb);
1045 b = get_byte(pb);
1046 get_byte(pb);
1047 c->palette_control.palette[j] =
1048 (r << 16) | (g << 8) | (b);
1049 }
1050 }
1051
1052 st->codec->palctrl = &c->palette_control;
1053 st->codec->palctrl->palette_changed = 1;
1054 } else
1055 st->codec->palctrl = NULL;
1056 } else if(st->codec->codec_type==CODEC_TYPE_AUDIO) {
1057 uint16_t version = get_be16(pb);
1058
1059 st->codec->codec_id = id;
1060 get_be16(pb); /* revision level */
1061 get_be32(pb); /* vendor */
1062
1063 st->codec->channels = get_be16(pb); /* channel count */
1064 st->codec->bits_per_sample = get_be16(pb); /* sample size */
1065 /* do we need to force to 16 for AMR ? */
1066
1067 /* handle specific s8 codec */
1068 get_be16(pb); /* compression id = 0*/
1069 get_be16(pb); /* packet size = 0 */
1070
1071 st->codec->sample_rate = ((get_be32(pb) >> 16));
1072
1073 switch (st->codec->codec_id) {
1074 case CODEC_ID_PCM_S16LE:
1075 case CODEC_ID_PCM_S16BE:
1076 if (st->codec->bits_per_sample == 8)
1077 st->codec->codec_id = CODEC_ID_PCM_S8;
1078 st->codec->bit_rate = st->codec->sample_rate * 8;
1079 break;
1080 case CODEC_ID_PCM_U8:
1081 if (st->codec->bits_per_sample == 16)
1082 st->codec->codec_id = CODEC_ID_PCM_S16BE;
1083 st->codec->bit_rate = st->codec->sample_rate * 8;
1084 break;
1085 case CODEC_ID_AMR_WB:
1086 st->codec->sample_rate = 16000; /* should really we ? */
1087 st->codec->channels=1; /* really needed */
1088 break;
1089 case CODEC_ID_AMR_NB:
1090 st->codec->sample_rate = 8000; /* should really we ? */
1091 st->codec->channels=1; /* really needed */
1092 break;
1093 default:
1094 break;
1095 }
1096
1097 //Read QT version 1 fields. In version 0 theese dont exist
1098 dprintf("version =%d mp4=%d\n",version,c->mp4);
1099 if(version==1) {
1100 get_be32(pb); /* samples per packet */
1101 get_be32(pb); /* bytes per packet */
1102 get_be32(pb); /* bytes per frame */
1103 get_be32(pb); /* bytes per sample */
1104 } else if(version==2) {
1105 get_be32(pb); /* sizeof struct only */
1106 st->codec->sample_rate = av_int2dbl(get_be64(pb)); /* float 64 */
1107 st->codec->channels = get_be32(pb);
1108 get_be32(pb); /* always 0x7F000000 */
1109 get_be32(pb); /* bits per channel if sound is uncompressed */
1110 get_be32(pb); /* lcpm format specific flag */
1111 get_be32(pb); /* bytes per audio packet if constant */
1112 get_be32(pb); /* lpcm frames per audio packet if constant */
1113 }
1114 } else {
1115 /* other codec type, just skip (rtp, mp4s, tmcd ...) */
1116 url_fskip(pb, size - (url_ftell(pb) - start_pos));
1117 }
1118 /* this will read extra atoms at the end (wave, alac, damr, avcC, SMI ...) */
1119 a.size = size - (url_ftell(pb) - start_pos);
1120 if (a.size > 8)
1121 mov_read_default(c, pb, a);
1122 else if (a.size > 0)
1123 url_fskip(pb, a.size);
1124 }
1125
1126 if(st->codec->codec_type==CODEC_TYPE_AUDIO && st->codec->sample_rate==0 && sc->time_scale>1) {
1127 st->codec->sample_rate= sc->time_scale;
1128 }
1129
1130 switch (st->codec->codec_id) {
1131 #ifdef CONFIG_FAAD
1132 case CODEC_ID_AAC:
1133 #endif
1134 #ifdef CONFIG_VORBIS_DECODER
1135 case CODEC_ID_VORBIS:
1136 #endif
1137 case CODEC_ID_MP3ON4:
1138 st->codec->sample_rate= 0; /* let decoder init parameters properly */
1139 break;
1140 default:
1141 break;
1142 }
1143
1144 return 0;
1145 }
1146
1147 static int mov_read_stsc(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
1148 {
1149 AVStream *st = c->fc->streams[c->fc->nb_streams-1];
1150 MOVStreamContext *sc = (MOVStreamContext *)st->priv_data;
1151 unsigned int i, entries;
1152
1153 get_byte(pb); /* version */
1154 get_byte(pb); get_byte(pb); get_byte(pb); /* flags */
1155
1156 entries = get_be32(pb);
1157
1158 if(entries >= UINT_MAX / sizeof(MOV_sample_to_chunk_tbl))
1159 return -1;
1160
1161 #ifdef DEBUG
1162 av_log(NULL, AV_LOG_DEBUG, "track[%i].stsc.entries = %i\n", c->fc->nb_streams-1, entries);
1163 #endif
1164 sc->sample_to_chunk_sz = entries;
1165 sc->sample_to_chunk = (MOV_sample_to_chunk_tbl*) av_malloc(entries * sizeof(MOV_sample_to_chunk_tbl));
1166 if (!sc->sample_to_chunk)
1167 return -1;
1168 for(i=0; i<entries; i++) {
1169 sc->sample_to_chunk[i].first = get_be32(pb);
1170 sc->sample_to_chunk[i].count = get_be32(pb);
1171 sc->sample_to_chunk[i].id = get_be32(pb);
1172 }
1173 return 0;
1174 }
1175
1176 static int mov_read_stss(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
1177 {
1178 AVStream *st = c->fc->streams[c->fc->nb_streams-1];
1179 MOVStreamContext *sc = (MOVStreamContext *)st->priv_data;
1180 unsigned int i, entries;
1181
1182 get_byte(pb); /* version */
1183 get_byte(pb); get_byte(pb); get_byte(pb); /* flags */
1184
1185 entries = get_be32(pb);
1186
1187 if(entries >= UINT_MAX / sizeof(long))
1188 return -1;
1189
1190 sc->keyframe_count = entries;
1191 #ifdef DEBUG
1192 av_log(NULL, AV_LOG_DEBUG, "keyframe_count = %ld\n", sc->keyframe_count);
1193 #endif
1194 sc->keyframes = (long*) av_malloc(entries * sizeof(long));
1195 if (!sc->keyframes)
1196 return -1;
1197 for(i=0; i<entries; i++) {
1198 sc->keyframes[i] = get_be32(pb);
1199 #ifdef DEBUG
1200 /* av_log(NULL, AV_LOG_DEBUG, "keyframes[]=%ld\n", sc->keyframes[i]); */
1201 #endif
1202 }
1203 return 0;
1204 }
1205
1206 static int mov_read_stsz(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
1207 {
1208 AVStream *st = c->fc->streams[c->fc->nb_streams-1];
1209 MOVStreamContext *sc = (MOVStreamContext *)st->priv_data;
1210 unsigned int i, entries;
1211
1212 get_byte(pb); /* version */
1213 get_byte(pb); get_byte(pb); get_byte(pb); /* flags */
1214
1215 sc->sample_size = get_be32(pb);
1216 entries = get_be32(pb);
1217 if(entries >= UINT_MAX / sizeof(long))
1218 return -1;
1219
1220 sc->sample_count = entries;
1221 #ifdef DEBUG
1222 av_log(NULL, AV_LOG_DEBUG, "sample_size = %ld sample_count = %ld\n", sc->sample_size, sc->sample_count);
1223 #endif
1224 if(sc->sample_size) {
1225 /* override sample size for uncompressed sound */
1226 switch (st->codec->codec_id) {
1227 case CODEC_ID_PCM_S32BE:
1228 case CODEC_ID_PCM_S32LE:
1229 sc->sample_size = 4 * st->codec->channels;
1230 break;
1231 case CODEC_ID_PCM_S24BE:
1232 case CODEC_ID_PCM_S24LE:
1233 sc->sample_size = 3 * st->codec->channels;
1234 break;
1235 case CODEC_ID_PCM_S16BE:
1236 case CODEC_ID_PCM_S16LE:
1237 sc->sample_size = 2 * st->codec->channels;
1238 break;
1239 case CODEC_ID_PCM_MULAW:
1240 case CODEC_ID_PCM_ALAW:
1241 case CODEC_ID_PCM_S8:
1242 case CODEC_ID_PCM_U8:
1243 sc->sample_size = 1 * st->codec->channels;
1244 break;
1245 default:
1246 break;
1247 }
1248 assert(sc->sample_size);
1249 return 0; /* there isn't any table following */
1250 }
1251 sc->sample_sizes = (long*) av_malloc(entries * sizeof(long));
1252 if (!sc->sample_sizes)
1253 return -1;
1254 for(i=0; i<entries; i++) {
1255 sc->sample_sizes[i] = get_be32(pb);
1256 #ifdef DEBUG
1257 av_log(NULL, AV_LOG_DEBUG, "sample_sizes[]=%ld\n", sc->sample_sizes[i]);
1258 #endif
1259 }
1260 return 0;
1261 }
1262
1263 static int mov_read_stts(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
1264 {
1265 AVStream *st = c->fc->streams[c->fc->nb_streams-1];
1266 MOVStreamContext *sc = (MOVStreamContext *)st->priv_data;
1267 unsigned int i, entries;
1268 int64_t duration=0;
1269 int64_t total_sample_count=0;
1270
1271 get_byte(pb); /* version */
1272 get_byte(pb); get_byte(pb); get_byte(pb); /* flags */
1273 entries = get_be32(pb);
1274 if(entries >= UINT_MAX / sizeof(Time2Sample))
1275 return -1;
1276
1277 sc->stts_count = entries;
1278 sc->stts_data = av_malloc(entries * sizeof(Time2Sample));
1279
1280 #ifdef DEBUG
1281 av_log(NULL, AV_LOG_DEBUG, "track[%i].stts.entries = %i\n", c->fc->nb_streams-1, entries);
1282 #endif
1283
1284 sc->time_rate=0;
1285
1286 for(i=0; i<entries; i++) {
1287 int sample_duration;
1288 int sample_count;
1289
1290 sample_count=get_be32(pb);
1291 sample_duration = get_be32(pb);
1292 sc->stts_data[i].count= sample_count;
1293 sc->stts_data[i].duration= sample_duration;
1294
1295 sc->time_rate= ff_gcd(sc->time_rate, sample_duration);
1296
1297 dprintf("sample_count=%d, sample_duration=%d\n",sample_count,sample_duration);
1298
1299 duration+=(int64_t)sample_duration*sample_count;
1300 total_sample_count+=sample_count;
1301 }
1302
1303 st->nb_frames= total_sample_count;
1304 if(duration)
1305 st->duration= duration;
1306 return 0;
1307 }
1308
1309 static int mov_read_ctts(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
1310 {
1311 AVStream *st = c->fc->streams[c->fc->nb_streams-1];
1312 MOVStreamContext *sc = (MOVStreamContext *)st->priv_data;
1313 unsigned int i, entries;
1314
1315 get_byte(pb); /* version */
1316 get_byte(pb); get_byte(pb); get_byte(pb); /* flags */
1317 entries = get_be32(pb);
1318 if(entries >= UINT_MAX / sizeof(Time2Sample))
1319 return -1;
1320
1321 sc->ctts_count = entries;
1322 sc->ctts_data = av_malloc(entries * sizeof(Time2Sample));
1323
1324 dprintf("track[%i].ctts.entries = %i\n", c->fc->nb_streams-1, entries);
1325
1326 for(i=0; i<entries; i++) {
1327 int count =get_be32(pb);
1328 int duration =get_be32(pb);
1329
1330 if (duration < 0) {
1331 av_log(c->fc, AV_LOG_ERROR, "negative ctts, ignoring\n");
1332 sc->ctts_count = 0;
1333 url_fskip(pb, 8 * (entries - i - 1));
1334 break;
1335 }
1336 sc->ctts_data[i].count = count;
1337 sc->ctts_data[i].duration= duration;
1338
1339 sc->time_rate= ff_gcd(sc->time_rate, duration);
1340 }
1341 return 0;
1342 }
1343
1344 static int mov_read_trak(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
1345 {
1346 AVStream *st;
1347 MOVStreamContext *sc;
1348
1349 st = av_new_stream(c->fc, c->fc->nb_streams);
1350 if (!st) return -2;
1351 sc = (MOVStreamContext*) av_mallocz(sizeof(MOVStreamContext));
1352 if (!sc) {
1353 av_free(st);
1354 return -1;
1355 }
1356
1357 sc->sample_to_chunk_index = -1;
1358 st->priv_data = sc;
1359 st->codec->codec_type = CODEC_TYPE_DATA;
1360 st->start_time = 0; /* XXX: check */
1361 c->streams[c->fc->nb_streams-1] = sc;
1362
1363 return mov_read_default(c, pb, atom);
1364 }
1365
1366 static int mov_read_tkhd(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
1367 {
1368 AVStream *st = c->fc->streams[c->fc->nb_streams-1];
1369 int version = get_byte(pb);
1370
1371 get_byte(pb); get_byte(pb);
1372 get_byte(pb); /* flags */
1373 /*
1374 MOV_TRACK_ENABLED 0x0001
1375 MOV_TRACK_IN_MOVIE 0x0002
1376 MOV_TRACK_IN_PREVIEW 0x0004
1377 MOV_TRACK_IN_POSTER 0x0008
1378 */
1379
1380 if (version == 1) {
1381 get_be64(pb);
1382 get_be64(pb);
1383 } else {
1384 get_be32(pb); /* creation time */
1385 get_be32(pb); /* modification time */
1386 }
1387 st->id = (int)get_be32(pb); /* track id (NOT 0 !)*/
1388 get_be32(pb); /* reserved */
1389 st->start_time = 0; /* check */
1390 (version == 1) ? get_be64(pb) : get_be32(pb); /* highlevel (considering edits) duration in movie timebase */
1391 get_be32(pb); /* reserved */
1392 get_be32(pb); /* reserved */
1393
1394 get_be16(pb); /* layer */
1395 get_be16(pb); /* alternate group */
1396 get_be16(pb); /* volume */
1397 get_be16(pb); /* reserved */
1398
1399 url_fskip(pb, 36); /* display matrix */
1400
1401 /* those are fixed-point */
1402 get_be32(pb); /* track width */
1403 get_be32(pb); /* track height */
1404
1405 return 0;
1406 }
1407
1408 /* this atom should be null (from specs), but some buggy files put the 'moov' atom inside it... */
1409 /* like the files created with Adobe Premiere 5.0, for samples see */
1410 /* http://graphics.tudelft.nl/~wouter/publications/soundtests/ */
1411 static int mov_read_wide(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
1412 {
1413 int err;
1414
1415 if (atom.size < 8)
1416 return 0; /* continue */
1417 if (get_be32(pb) != 0) { /* 0 sized mdat atom... use the 'wide' atom size */
1418 url_fskip(pb, atom.size - 4);
1419 return 0;
1420 }
1421 atom.type = get_le32(pb);
1422 atom.offset += 8;
1423 atom.size -= 8;
1424 if (atom.type != MKTAG('m', 'd', 'a', 't')) {
1425 url_fskip(pb, atom.size);
1426 return 0;
1427 }
1428 err = mov_read_mdat(c, pb, atom);
1429 return err;
1430 }
1431
1432
1433 #ifdef CONFIG_ZLIB
1434 static int null_read_packet(void *opaque, uint8_t *buf, int buf_size)
1435 {
1436 return -1;
1437 }
1438
1439 static int mov_read_cmov(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
1440 {
1441 ByteIOContext ctx;
1442 uint8_t *cmov_data;
1443 uint8_t *moov_data; /* uncompressed data */
1444 long cmov_len, moov_len;
1445 int ret;
1446
1447 get_be32(pb); /* dcom atom */
1448 if (get_le32(pb) != MKTAG( 'd', 'c', 'o', 'm' ))
1449 return -1;
1450 if (get_le32(pb) != MKTAG( 'z', 'l', 'i', 'b' )) {
1451 av_log(NULL, AV_LOG_ERROR, "unknown compression for cmov atom !");
1452 return -1;
1453 }
1454 get_be32(pb); /* cmvd atom */
1455 if (get_le32(pb) != MKTAG( 'c', 'm', 'v', 'd' ))
1456 return -1;
1457 moov_len = get_be32(pb); /* uncompressed size */
1458 cmov_len = atom.size - 6 * 4;
1459
1460 cmov_data = (uint8_t *) av_malloc(cmov_len);
1461 if (!cmov_data)
1462 return -1;
1463 moov_data = (uint8_t *) av_malloc(moov_len);
1464 if (!moov_data) {
1465 av_free(cmov_data);
1466 return -1;
1467 }
1468 get_buffer(pb, cmov_data, cmov_len);
1469 if(uncompress (moov_data, (uLongf *) &moov_len, (const Bytef *)cmov_data, cmov_len) != Z_OK)
1470 return -1;
1471 if(init_put_byte(&ctx, moov_data, moov_len, 0, NULL, null_read_packet, NULL, NULL) != 0)
1472 return -1;
1473 ctx.buf_end = ctx.buffer + moov_len;
1474 atom.type = MKTAG( 'm', 'o', 'o', 'v' );
1475 atom.offset = 0;
1476 atom.size = moov_len;
1477 #ifdef DEBUG
1478 // { int fd = open("/tmp/uncompheader.mov", O_WRONLY | O_CREAT); write(fd, moov_data, moov_len); close(fd); }
1479 #endif
1480 ret = mov_read_default(c, &ctx, atom);
1481 av_free(moov_data);
1482 av_free(cmov_data);
1483
1484 return ret;
1485 }
1486 #endif
1487
1488 /* edit list atom */
1489 static int mov_read_elst(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
1490 {
1491 int i, edit_count;
1492
1493 get_byte(pb); /* version */
1494 get_byte(pb); get_byte(pb); get_byte(pb); /* flags */
1495 edit_count= c->streams[c->fc->nb_streams-1]->edit_count = get_be32(pb); /* entries */
1496
1497 for(i=0; i<edit_count; i++){
1498 get_be32(pb); /* Track duration */
1499 get_be32(pb); /* Media time */
1500 get_be32(pb); /* Media rate */
1501 }
1502 dprintf("track[%i].edit_count = %i\n", c->fc->nb_streams-1, c->streams[c->fc->nb_streams-1]->edit_count);
1503 return 0;
1504 }
1505
1506 static const MOVParseTableEntry mov_default_parse_table[] = {
1507 /* mp4 atoms */
1508 { MKTAG( 'c', 'o', '6', '4' ), mov_read_stco },
1509 { MKTAG( 'c', 'p', 'r', 't' ), mov_read_default },
1510 { MKTAG( 'c', 'r', 'h', 'd' ), mov_read_default },
1511 { MKTAG( 'c', 't', 't', 's' ), mov_read_ctts }, /* composition time to sample */
1512 { MKTAG( 'd', 'i', 'n', 'f' ), mov_read_default }, /* data information */
1513 { MKTAG( 'd', 'p', 'n', 'd' ), mov_read_leaf },
1514 { MKTAG( 'd', 'r', 'e', 'f' ), mov_read_leaf },
1515 { MKTAG( 'e', 'd', 't', 's' ), mov_read_default },
1516 { MKTAG( 'e', 'l', 's', 't' ), mov_read_elst },
1517 { MKTAG( 'e', 'n', 'd', 'a' ), mov_read_enda },
1518 { MKTAG( 'f', 'r', 'e', 'e' ), mov_read_leaf },
1519 { MKTAG( 'f', 't', 'y', 'p' ), mov_read_ftyp },
1520 { MKTAG( 'h', 'd', 'l', 'r' ), mov_read_hdlr },
1521 { MKTAG( 'h', 'i', 'n', 't' ), mov_read_leaf },
1522 { MKTAG( 'h', 'm', 'h', 'd' ), mov_read_leaf },
1523 { MKTAG( 'i', 'o', 'd', 's' ), mov_read_leaf },
1524 { MKTAG( 'j', 'p', '2', 'h' ), mov_read_jp2h },
1525 { MKTAG( 'm', 'd', 'a', 't' ), mov_read_mdat },
1526 { MKTAG( 'm', 'd', 'h', 'd' ), mov_read_mdhd },
1527 { MKTAG( 'm', 'd', 'i', 'a' ), mov_read_default },
1528 { MKTAG( 'm', 'i', 'n', 'f' ), mov_read_default },
1529 { MKTAG( 'm', 'o', 'o', 'v' ), mov_read_moov },
1530 { MKTAG( 'm', 'p', '4', 'a' ), mov_read_default },
1531 { MKTAG( 'm', 'p', '4', 's' ), mov_read_default },
1532 { MKTAG( 'm', 'p', '4', 'v' ), mov_read_default },
1533 { MKTAG( 'm', 'p', 'o', 'd' ), mov_read_leaf },
1534 { MKTAG( 'm', 'v', 'h', 'd' ), mov_read_mvhd },
1535 { MKTAG( 'n', 'm', 'h', 'd' ), mov_read_leaf },
1536 { MKTAG( 'o', 'd', 'h', 'd' ), mov_read_default },
1537 { MKTAG( 's', 'd', 'h', 'd' ), mov_read_default },
1538 { MKTAG( 's', 'k', 'i', 'p' ), mov_read_leaf },
1539 { MKTAG( 's', 'm', 'h', 'd' ), mov_read_leaf }, /* sound media info header */
1540 { MKTAG( 'S', 'M', 'I', ' ' ), mov_read_smi }, /* Sorenson extension ??? */
1541 { MKTAG( 'a', 'l', 'a', 'c' ), mov_read_alac }, /* alac specific atom */
1542 { MKTAG( 'a', 'v', 'c', 'C' ), mov_read_avcC },
1543 { MKTAG( 's', 't', 'b', 'l' ), mov_read_default },
1544 { MKTAG( 's', 't', 'c', 'o' ), mov_read_stco },
1545 { MKTAG( 's', 't', 'd', 'p' ), mov_read_default },
1546 { MKTAG( 's', 't', 's', 'c' ), mov_read_stsc },
1547 { MKTAG( 's', 't', 's', 'd' ), mov_read_stsd }, /* sample description */
1548 { MKTAG( 's', 't', 's', 'h' ), mov_read_default },
1549 { MKTAG( 's', 't', 's', 's' ), mov_read_stss }, /* sync sample */
1550 { MKTAG( 's', 't', 's', 'z' ), mov_read_stsz }, /* sample size */
1551 { MKTAG( 's', 't', 't', 's' ), mov_read_stts },
1552 { MKTAG( 't', 'k', 'h', 'd' ), mov_read_tkhd }, /* track header */
1553 { MKTAG( 't', 'r', 'a', 'k' ), mov_read_trak },
1554 { MKTAG( 't', 'r', 'e', 'f' ), mov_read_default }, /* not really */
1555 { MKTAG( 'u', 'd', 't', 'a' ), mov_read_leaf },
1556 { MKTAG( 'u', 'r', 'l', ' ' ), mov_read_leaf },
1557 { MKTAG( 'u', 'r', 'n', ' ' ), mov_read_leaf },
1558 { MKTAG( 'u', 'u', 'i', 'd' ), mov_read_leaf },
1559 { MKTAG( 'v', 'm', 'h', 'd' ), mov_read_leaf }, /* video media info header */
1560 { MKTAG( 'w', 'a', 'v', 'e' ), mov_read_wave },
1561 /* extra mp4 */
1562 { MKTAG( 'M', 'D', 'E', 'S' ), mov_read_leaf },
1563 /* QT atoms */
1564 { MKTAG( 'c', 'h', 'a', 'p' ), mov_read_leaf },
1565 { MKTAG( 'c', 'l', 'i', 'p' ), mov_read_default },
1566 { MKTAG( 'c', 'r', 'g', 'n' ), mov_read_leaf },
1567 { MKTAG( 'c', 't', 'a', 'b' ), mov_read_ctab },
1568 { MKTAG( 'e', 's', 'd', 's' ), mov_read_esds },
1569 { MKTAG( 'k', 'm', 'a', 't' ), mov_read_leaf },
1570 { MKTAG( 'm', 'a', 't', 't' ), mov_read_default },
1571 { MKTAG( 'r', 'd', 'r', 'f' ), mov_read_leaf },
1572 { MKTAG( 'r', 'm', 'd', 'a' ), mov_read_default },
1573 { MKTAG( 'r', 'm', 'd', 'r' ), mov_read_leaf },
1574 { MKTAG( 'r', 'm', 'r', 'a' ), mov_read_default },
1575 { MKTAG( 's', 'c', 'p', 't' ), mov_read_leaf },
1576 { MKTAG( 's', 's', 'r', 'c' ), mov_read_leaf },
1577 { MKTAG( 's', 'y', 'n', 'c' ), mov_read_leaf },
1578 { MKTAG( 't', 'c', 'm', 'd' ), mov_read_leaf },
1579 { MKTAG( 'w', 'i', 'd', 'e' ), mov_read_wide }, /* place holder */
1580 //{ MKTAG( 'r', 'm', 'q', 'u' ), mov_read_leaf },
1581 #ifdef CONFIG_ZLIB
1582 { MKTAG( 'c', 'm', 'o', 'v' ), mov_read_cmov },
1583 #else
1584 { MKTAG( 'c', 'm', 'o', 'v' ), mov_read_leaf },
1585 #endif
1586 { 0L, mov_read_leaf }
1587 };
1588
1589 static void mov_free_stream_context(MOVStreamContext *sc)
1590 {
1591 if(sc) {
1592 av_freep(&sc->chunk_offsets);
1593 av_freep(&sc->sample_to_chunk);
1594 av_freep(&sc->sample_sizes);
1595 av_freep(&sc->keyframes);
1596 av_freep(&sc->stts_data);
1597 av_freep(&sc->ctts_data);
1598 av_freep(&sc);
1599 }
1600 }
1601
1602 static inline uint32_t mov_to_tag(uint8_t *buf)
1603 {
1604 return MKTAG(buf[0], buf[1], buf[2], buf[3]);
1605 }
1606
1607 static inline uint32_t to_be32(uint8_t *buf)
1608 {
1609 return (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3];
1610 }
1611
1612 /* XXX: is it sufficient ? */
1613 static int mov_probe(AVProbeData *p)
1614 {
1615 unsigned int offset;
1616 uint32_t tag;
1617 int score = 0;
1618
1619 /* check file header */
1620 if (p->buf_size <= 12)
1621 return 0;
1622 offset = 0;
1623 for(;;) {
1624 /* ignore invalid offset */
1625 if ((offset + 8) > (unsigned int)p->buf_size)
1626 return score;
1627 tag = mov_to_tag(p->buf + offset + 4);
1628 switch(tag) {
1629 /* check for obvious tags */
1630 case MKTAG( 'j', 'P', ' ', ' ' ): /* jpeg 2000 signature */
1631 case MKTAG( 'm', 'o', 'o', 'v' ):
1632 case MKTAG( 'm', 'd', 'a', 't' ):
1633 case MKTAG( 'p', 'n', 'o', 't' ): /* detect movs with preview pics like ew.mov and april.mov */
1634 case MKTAG( 'u', 'd', 't', 'a' ): /* Packet Video PVAuthor adds this and a lot of more junk */
1635 return AVPROBE_SCORE_MAX;
1636 /* those are more common words, so rate then a bit less */
1637 case MKTAG( 'w', 'i', 'd', 'e' ):
1638 case MKTAG( 'f', 'r', 'e', 'e' ):
1639 case MKTAG( 'j', 'u', 'n', 'k' ):
1640 case MKTAG( 'p', 'i', 'c', 't' ):
1641 return AVPROBE_SCORE_MAX - 5;
1642 case MKTAG( 'f', 't', 'y', 'p' ):
1643 case MKTAG( 's', 'k', 'i', 'p' ):
1644 case MKTAG( 'u', 'u', 'i', 'd' ):
1645 offset = to_be32(p->buf+offset) + offset;
1646 /* if we only find those cause probedata is too small at least rate them */
1647 score = AVPROBE_SCORE_MAX - 50;
1648 break;
1649 default:
1650 /* unrecognized tag */
1651 return score;
1652 }
1653 }
1654 return score;
1655 }
1656
1657 static int mov_read_header(AVFormatContext *s, AVFormatParameters *ap)
1658 {
1659 MOVContext *mov = (MOVContext *) s->priv_data;
1660 ByteIOContext *pb = &s->pb;
1661 int i, err;
1662 MOV_atom_t atom = { 0, 0, 0 };
1663
1664 mov->fc = s;
1665 mov->parse_table = mov_default_parse_table;
1666
1667 if(!url_is_streamed(pb)) /* .mov and .mp4 aren't streamable anyway (only progressive download if moov is before mdat) */
1668 atom.size = url_fsize(pb);
1669 else
1670 atom.size = 0x7FFFFFFFFFFFFFFFLL;
1671
1672 /* check MOV header */
1673 err = mov_read_default(mov, pb, atom);
1674 if (err<0 || (!mov->found_moov && !mov->found_mdat)) {
1675 av_log(s, AV_LOG_ERROR, "mov: header not found !!! (err:%d, moov:%d, mdat:%d) pos:%"PRId64"\n",
1676 err, mov->found_moov, mov->found_mdat, url_ftell(pb));
1677 return -1;
1678 }
1679 dprintf("on_parse_exit_offset=%d\n", (int) url_ftell(pb));
1680
1681 /* some cleanup : make sure we are on the mdat atom */
1682 if(!url_is_streamed(pb) && (url_ftell(pb) != mov->mdat_offset))
1683 url_fseek(pb, mov->mdat_offset, SEEK_SET);
1684
1685 mov->next_chunk_offset = mov->mdat_offset; /* initialise reading */
1686 mov->total_streams = s->nb_streams;
1687
1688 for(i=0; i<mov->total_streams; i++) {
1689 MOVStreamContext *sc = mov->streams[i];
1690
1691 if(!sc->time_rate)
1692 sc->time_rate=1;
1693 if(!sc->time_scale)
1694 sc->time_scale= mov->time_scale;
1695 av_set_pts_info(s->streams[i], 64, sc->time_rate, sc->time_scale);
1696
1697 if(s->streams[i]->duration != AV_NOPTS_VALUE){
1698 assert(s->streams[i]->duration % sc->time_rate == 0);
1699 s->streams[i]->duration /= sc->time_rate;
1700 }
1701 sc->ffindex = i;
1702 }
1703
1704 return 0;
1705 }
1706
1707 /* Yes, this is ugly... I didn't write the specs of QT :p */
1708 /* XXX:remove useless commented code sometime */
1709 static int mov_read_packet(AVFormatContext *s, AVPacket *pkt)
1710 {
1711 MOVContext *mov = (MOVContext *) s->priv_data;
1712 MOVStreamContext *sc;
1713 AVStream *st;
1714 int64_t offset = INT64_MAX;
1715 int64_t best_dts = INT64_MAX;
1716 int i, a, b, m;
1717 int next_sample= -99;
1718 int size;
1719 int idx;
1720 int ret;
1721 size = 0x0FFFFFFF;
1722
1723 if (mov->partial) {
1724 sc = mov->partial;
1725 idx = sc->sample_to_chunk_index;
1726
1727 if (idx < 0) return 0;
1728 dprintf("sc[ffid %d]->sample_size = %ld\n", sc->ffindex, sc->sample_size);
1729 //size = sc->sample_sizes[sc->current_sample];
1730 // that ain't working...
1731 //size = (sc->sample_size)?sc->sample_size:sc->sample_sizes[sc->current_sample];
1732 size = (sc->sample_size > 1)?sc->sample_size:sc->sample_sizes[sc->current_sample];
1733
1734 next_sample= sc->current_sample+1;
1735
1736 sc->left_in_chunk--;
1737
1738 if (sc->left_in_chunk <= 0)
1739 mov->partial = 0;
1740 offset = mov->next_chunk_offset;
1741 /* extract the sample */
1742
1743 goto readchunk;
1744 }
1745
1746 again:
1747 sc = 0;
1748 if(offset == INT64_MAX)
1749 best_dts= INT64_MAX;
1750 for(i=0; i<mov->total_streams; i++) {
1751 MOVStreamContext *msc = mov->streams[i];
1752
1753 if ((msc->next_chunk < msc->chunk_count) && msc->next_chunk >= 0){
1754 if (msc->sample_to_time_index < msc->stts_count && mov->ni) {
1755 int64_t dts;
1756 int index= msc->sample_to_time_index;
1757 int sample= msc->sample_to_time_sample;
1758 int time= msc->sample_to_time_time;
1759 int duration = msc->stts_data[index].duration;
1760 int count = msc->stts_data[index].count;
1761 if (sample + count <= msc->current_sample) {
1762 sample += count;
1763 time += count*duration;
1764 index ++;
1765 duration = msc->stts_data[index].duration;
1766 }
1767 dts = time + (msc->current_sample - sample) * (int64_t)duration;
1768 dts = av_rescale(dts, AV_TIME_BASE, msc->time_scale);
1769 dprintf("stream: %d dts: %"PRId64" best_dts: %"PRId64" offset: %"PRId64"\n", i, dts, best_dts, offset);
1770 if(dts < best_dts){
1771 best_dts= dts;
1772 sc = msc;
1773 offset = msc->chunk_offsets[msc->next_chunk];
1774 }
1775 }else{
1776 if ((msc->chunk_offsets[msc->next_chunk] < offset)) {
1777 sc = msc;
1778 offset = msc->chunk_offsets[msc->next_chunk];
1779 }
1780 }
1781 }
1782 }
1783 if (!sc || offset==INT64_MAX)
1784 return -1;
1785
1786 sc->next_chunk++;
1787
1788 if(mov->next_chunk_offset < offset) { /* some meta data */
1789 url_fskip(&s->pb, (offset - mov->next_chunk_offset));
1790 mov->next_chunk_offset = offset;
1791 }
1792
1793 if(s->streams[sc->ffindex]->discard >= AVDISCARD_ALL) {
1794 url_fskip(&s->pb, (offset - mov->next_chunk_offset));
1795 mov->next_chunk_offset = offset;
1796 offset = INT64_MAX;
1797 goto again;
1798 }
1799
1800 idx = sc->sample_to_chunk_index;
1801 if (idx + 1 < sc->sample_to_chunk_sz && sc->next_chunk >= sc->sample_to_chunk[idx + 1].first)
1802 idx++;
1803 sc->sample_to_chunk_index = idx;
1804 /* split chunks into samples */
1805 if (sc->sample_size == 0 || sc->sample_size > 100) {
1806 if (idx >= 0 && sc->sample_to_chunk[idx].count != 1) {
1807 mov->partial = sc;
1808 /* we'll have to get those samples before next chunk */
1809 sc->left_in_chunk = sc->sample_to_chunk[idx].count - 1;
1810 }
1811 size = (sc->sample_size > 1)?sc->sample_size:sc->sample_sizes[sc->current_sample];
1812 next_sample= sc->current_sample+1;
1813 }else{
1814 int adjusted= 0;
1815 /* get the chunk size... */
1816 for(i=0; i<mov->total_streams; i++) {
1817 MOVStreamContext *msc = mov->streams[i];
1818 if ((msc->next_chunk < msc->chunk_count)
1819 && msc->chunk_offsets[msc->next_chunk] - offset < size
1820 && msc->chunk_offsets[msc->next_chunk] > offset)
1821 size = msc->chunk_offsets[msc->next_chunk] - offset;
1822 }
1823 //Make sure that size is according to sample_size (Needed by .mov files
1824 //created on a Minolta Dimage Xi where audio chunks contains waste data in the end)
1825 //needed for 'raw '
1826 //sample_size is already adjusted in read_stsz
1827 adjusted= sc->sample_to_chunk[idx].count * sc->sample_size;
1828 if (adjusted < size) {
1829 dprintf("adjusted %d, size %d, sample count %ld\n", adjusted, size, sc->sample_to_chunk[idx].count);
1830 size = adjusted;
1831 }
1832 if(idx < sc->sample_to_chunk_sz){
1833 next_sample= sc->current_sample + sc->sample_to_chunk[idx].count;
1834 }else
1835 next_sample= sc->current_sample;
1836 }
1837
1838 readchunk:
1839 dprintf("chunk: %"PRId64" -> %"PRId64" (%i)\n", offset, offset + size, size);
1840 if(size == 0x0FFFFFFF)
1841 size = mov->mdat_size + mov->mdat_offset - offset;
1842 if(size < 0)
1843 return -1;
1844 if(size == 0)
1845 return -1;
1846 ret = url_fseek(&s->pb, offset, SEEK_SET);
1847 if (ret < 0)
1848 return ret;
1849 av_get_packet(&s->pb, pkt, size);
1850 pkt->stream_index = sc->ffindex;
1851
1852 // If the keyframes table exists, mark any samples that are in the table as key frames.
1853 // If no table exists, treat very sample as a key frame.
1854 if (sc->keyframe_count) {
1855 a = 0;
1856 b = sc->keyframe_count - 1;
1857
1858 while (a < b) {
1859 m = (a + b + 1) >> 1;
1860 if (sc->keyframes[m] > sc->current_sample) {
1861 b = m - 1;
1862 } else {
1863 a = m;
1864 }
1865 }
1866
1867 if (sc->keyframes[a] == sc->current_sample)
1868 pkt->flags |= PKT_FLAG_KEY;
1869 }
1870 else
1871 pkt->flags |= PKT_FLAG_KEY;
1872
1873 mov->next_chunk_offset = offset + size;
1874
1875 /* find the corresponding dts */
1876 if (sc && sc->sample_to_time_index < sc->stts_count && pkt) {
1877 unsigned int count;
1878 uint64_t dts, pts;
1879 unsigned int duration = sc->stts_data[sc->sample_to_time_index].duration;
1880 count = sc->stts_data[sc->sample_to_time_index].count;
1881 if ((sc->sample_to_time_sample + count) <= sc->current_sample) {
1882 sc->sample_to_time_sample += count;
1883 sc->sample_to_time_time += count*duration;
1884 sc->sample_to_time_index ++;
1885 duration = sc->stts_data[sc->sample_to_time_index].duration;
1886 }
1887 dts = sc->sample_to_time_time + (sc->current_sample - sc->sample_to_time_sample) * (int64_t)duration;
1888 /* find the corresponding pts */
1889 if (sc->sample_to_ctime_index < sc->ctts_count) {
1890 int duration = sc->ctts_data[sc->sample_to_ctime_index].duration;
1891 int count = sc->ctts_data[sc->sample_to_ctime_index].count;
1892
1893 if ((sc->sample_to_ctime_sample + count) <= sc->current_sample) {
1894 sc->sample_to_ctime_sample += count;
1895 sc->sample_to_ctime_index ++;
1896 duration = sc->ctts_data[sc->sample_to_ctime_index].duration;
1897 }
1898 pts = dts + duration;
1899 }else
1900 pts = dts;
1901
1902 st= s->streams[ sc->ffindex ];
1903 assert(pts % st->time_base.num == 0);
1904 assert(dts % st->time_base.num == 0);
1905
1906 pkt->pts = pts / st->time_base.num;
1907 pkt->dts = dts / st->time_base.num;
1908 dprintf("stream #%d smp #%ld dts = %"PRId64" pts = %"PRId64" (smp:%ld time:%"PRId64" idx:%d ent:%d count:%d dur:%d)\n"
1909 , pkt->stream_index, sc->current_sample-1, pkt->dts, pkt->pts
1910 , sc->sample_to_time_sample
1911 , sc->sample_to_time_time
1912 , sc->sample_to_time_index
1913 , sc->stts_count
1914 , count
1915 , duration);
1916 }
1917
1918 assert(next_sample>=0);
1919 sc->current_sample= next_sample;
1920
1921 return 0;
1922 }
1923
1924 #if defined(MOV_SEEK)
1925 /**
1926 * Seek method based on the one described in the Appendix C of QTFileFormat.pdf
1927 */
1928 static int mov_read_seek(AVFormatContext *s, int stream_index, int64_t sample_time, int flags)
1929 {
1930 MOVContext* mov = (MOVContext *) s->priv_data;
1931 MOVStreamContext* sc;
1932 int32_t i, a, b, m;
1933 int64_t start_time;
1934 int32_t seek_sample, sample;
1935 int32_t duration;
1936 int32_t count;
1937 int32_t chunk;
1938 int32_t left_in_chunk;
1939 int64_t chunk_file_offset;
1940 int64_t sample_file_offset;
1941 int32_t first_chunk_sample;
1942 int32_t sample_to_chunk_idx;
1943 int sample_to_time_index;
1944 long sample_to_time_sample = 0;
1945 uint64_t sample_to_time_time = 0;
1946 int mov_idx;
1947
1948 // Find the corresponding mov stream
1949 for (mov_idx = 0; mov_idx < mov->total_streams; mov_idx++)
1950 if (mov->streams[mov_idx]->ffindex == stream_index)
1951 break;
1952 if (mov_idx == mov->total_streams) {
1953 av_log(s, AV_LOG_ERROR, "mov: requested stream was not found in mov streams (idx=%i)\n", stream_index);
1954 return -1;
1955 }
1956 sc = mov->streams[mov_idx];
1957
1958 sample_time *= s->streams[stream_index]->time_base.num;
1959
1960 // Step 1. Find the edit that contains the requested time (elst)
1961 if (sc->edit_count && 0) {
1962 // FIXME should handle edit list
1963 av_log(s, AV_LOG_ERROR, "mov: does not handle seeking in files that contain edit list (c:%d)\n", sc->edit_count);
1964 return -1;
1965 }
1966
1967 // Step 2. Find the corresponding sample using the Time-to-sample atom (stts) */
1968 dprintf("Searching for time %li in stream #%i (time_scale=%i)\n", (long)sample_time, mov_idx, sc->time_scale);
1969 start_time = 0; // FIXME use elst atom
1970 sample = 1; // sample are 0 based in table
1971
1972 for (i = 0; i < sc->stts_count; i++) {
1973 count = sc->stts_data[i].count;
1974 duration = sc->stts_data[i].duration;
1975 if ((start_time + count*duration) > sample_time) {
1976 sample_to_time_time = start_time;
1977 sample_to_time_index = i;
1978 sample_to_time_sample = sample;
1979 sample += (sample_time - start_time) / duration;
1980 break;
1981 }
1982 sample += count;
1983 start_time += count * duration;
1984 }
1985 sample_to_time_time = start_time;
1986 sample_to_time_index = i;
1987 /* NOTE: despite what qt doc say, the dt value (Display Time in qt vocabulary) computed with the stts atom
1988 is a decoding time stamp (dts) not a presentation time stamp. And as usual dts != pts for stream with b frames */
1989
1990 dprintf("Found time %li at sample #%u\n", (long)sample_time, sample);
1991 if (sample > sc->sample_count) {
1992 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);
1993 return -1;
1994 }
1995
1996 // Step 3. Find the prior sync. sample using the Sync sample atom (stss)
1997 if (sc->keyframe_count) {
1998 a = 0;
1999 b = sc->keyframe_count - 1;
2000 while (a < b) {
2001 m = (a + b + 1) >> 1;
2002 if (sc->keyframes[m] > sample) {
2003 b = m - 1;
2004 } else {
2005 a = m;
2006 }
2007 }
2008 // for low latency prob: always use the previous keyframe, just uncomment the next line
2009 // if (a) a--;
2010 seek_sample = sc->keyframes[a];
2011 }
2012 else
2013 seek_sample = sample; // else all samples are key frames
2014 dprintf("Found nearest keyframe at sample #%i \n", seek_sample);
2015
2016 // Step 4. Find the chunk of the sample using the Sample-to-chunk-atom (stsc)
2017 for (first_chunk_sample = 1, i = 0; i < (sc->sample_to_chunk_sz - 1); i++) {
2018 b = (sc->sample_to_chunk[i + 1].first - sc->sample_to_chunk[i].first) * sc->sample_to_chunk[i].count;
2019 if (seek_sample >= first_chunk_sample && seek_sample < (first_chunk_sample + b))
2020 break;
2021 first_chunk_sample += b;
2022 }
2023 chunk = sc->sample_to_chunk[i].first + (seek_sample - first_chunk_sample) / sc->sample_to_chunk[i].count;
2024 left_in_chunk = sc->sample_to_chunk[i].count - (seek_sample - first_chunk_sample) % sc->sample_to_chunk[i].count;
2025 first_chunk_sample += ((seek_sample - first_chunk_sample) / sc->sample_to_chunk[i].count) * sc->sample_to_chunk[i].count;
2026 sample_to_chunk_idx = i;
2027 dprintf("Sample was found in chunk #%i at sample offset %i (idx %i)\n", chunk, seek_sample - first_chunk_sample, sample_to_chunk_idx);
2028
2029 // Step 5. Find the offset of the chunk using the chunk offset atom
2030 if (!sc->chunk_offsets) {
2031 av_log(s, AV_LOG_ERROR, "mov: no chunk offset atom, unable to seek\n");
2032 return -1;
2033 }
2034 if (chunk > sc->chunk_count) {
2035 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);
2036 return -1;
2037 }
2038 chunk_file_offset = sc->chunk_offsets[chunk - 1];
2039 dprintf("Chunk file offset is #%"PRIu64"\n", chunk_file_offset);
2040
2041 // Step 6. Find the byte offset within the chunk using the sample size atom
2042 sample_file_offset = chunk_file_offset;
2043 if (sc->sample_size)
2044 sample_file_offset += (seek_sample - first_chunk_sample) * sc->sample_size;
2045 else {
2046 for (i = 0; i < (seek_sample - first_chunk_sample); i++) {
2047 sample_file_offset += sc->sample_sizes[first_chunk_sample + i - 1];
2048 }
2049 }
2050 dprintf("Sample file offset is #%"PRIu64"\n", sample_file_offset);
2051
2052 // Step 6. Update the parser
2053 mov->partial = sc;
2054 mov->next_chunk_offset = sample_file_offset;
2055 // Update current stream state
2056 sc->current_sample = seek_sample - 1; // zero based
2057 sc->left_in_chunk = left_in_chunk;
2058 sc->next_chunk = chunk; // +1 -1 (zero based)
2059 sc->sample_to_chunk_index = sample_to_chunk_idx;
2060
2061 // Update other streams
2062 for (i = 0; i<mov->total_streams; i++) {
2063 MOVStreamContext *msc;
2064 if (i == mov_idx) continue;
2065 // Find the nearest 'next' chunk
2066 msc = mov->streams[i];
2067 a = 0;
2068 b = msc->chunk_count - 1;
2069 while (a < b) {
2070 m = (a + b + 1) >> 1;
2071 if (msc->chunk_offsets[m] > chunk_file_offset) {
2072 b = m - 1;
2073 } else {
2074 a = m;
2075 }
2076 }
2077 msc->next_chunk = a;
2078 if (msc->chunk_offsets[a] < chunk_file_offset && a < (msc->chunk_count-1))
2079 msc->next_chunk ++;
2080 dprintf("Nearest next chunk for stream #%i is #%li @%"PRId64"\n", i, msc->next_chunk+1, msc->chunk_offsets[msc->next_chunk]);
2081
2082 // Compute sample count and index in the sample_to_chunk table (what a pity)
2083 msc->sample_to_chunk_index = 0;
2084 msc->current_sample = 0;
2085 for(; msc->sample_to_chunk_index < (msc->sample_to_chunk_sz - 1)
2086 && msc->sample_to_chunk[msc->sample_to_chunk_index + 1].first <= (1 + msc->next_chunk); msc->sample_to_chunk_index++) {
2087 msc->current_sample += (msc->sample_to_chunk[msc->sample_to_chunk_index + 1].first - msc->sample_to_chunk[msc->sample_to_chunk_index].first) \
2088 * msc->sample_to_chunk[msc->sample_to_chunk_index].count;
2089 }
2090 msc->current_sample += (msc->next_chunk - (msc->sample_to_chunk[msc->sample_to_chunk_index].first - 1)) * msc->sample_to_chunk[msc->sample_to_chunk_index].count;
2091 msc->left_in_chunk = msc->sample_to_chunk[msc->sample_to_chunk_index].count - 1;
2092 // Find corresponding position in stts (used later to compute dts)
2093 sample = 0;
2094 start_time = 0;
2095 for (msc->sample_to_time_index = 0; msc->sample_to_time_index < msc->stts_count; msc->sample_to_time_index++) {
2096 count = msc->stts_data[msc->sample_to_time_index].count;
2097 duration = msc->stts_data[msc->sample_to_time_index].duration;
2098 if ((sample + count - 1) > msc->current_sample) {
2099 msc->sample_to_time_time = start_time;
2100 msc->sample_to_time_sample = sample;
2101 break;
2102 }
2103 sample += count;
2104 start_time += count * duration;
2105 }
2106 sample = 0;
2107 for (msc->sample_to_ctime_index = 0; msc->sample_to_ctime_index < msc->ctts_count; msc->sample_to_ctime_index++) {
2108 count = msc->ctts_data[msc->sample_to_ctime_index].count;
2109 duration = msc->ctts_data[msc->sample_to_ctime_index].duration;
2110 if ((sample + count - 1) > msc->current_sample) {
2111 msc->sample_to_ctime_sample = sample;
2112 break;
2113 }
2114 sample += count;
2115 }
2116 dprintf("Next Sample for stream #%i is #%li @%li\n", i, msc->current_sample + 1, msc->sample_to_chunk_index + 1);
2117 }
2118 return 0;
2119 }
2120 #endif
2121
2122 static int mov_read_close(AVFormatContext *s)
2123 {
2124 int i;
2125 MOVContext *mov = (MOVContext *) s->priv_data;
2126 for(i=0; i<mov->total_streams; i++)
2127 mov_free_stream_context(mov->streams[i]);
2128 /* free color tabs */
2129 for(i=0; i<mov->ctab_size; i++)
2130 av_freep(&mov->ctab[i]);
2131 av_freep(&mov->ctab);
2132 return 0;
2133 }
2134
2135 static AVInputFormat mov_iformat = {
2136 "mov,mp4,m4a,3gp,3g2,mj2",
2137 "QuickTime/MPEG4/Motion JPEG 2000 format",
2138 sizeof(MOVContext),
2139 mov_probe,
2140 mov_read_header,
2141 mov_read_packet,
2142 mov_read_close,
2143 #if defined(MOV_SEEK)
2144 mov_read_seek,
2145 #endif
2146 };
2147
2148 int mov_init(void)
2149 {
2150 av_register_input_format(&mov_iformat);
2151 return 0;
2152 }