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