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