Mercurial > libavformat.hg
annotate mov.c @ 3754:8d267b43eaba libavformat
Move malloc() down until after all initializations, so that the resource is
only allocated if initialization worked. This means that on failure, we
don't have to deallocate it.
author | rbultje |
---|---|
date | Sat, 23 Aug 2008 18:46:30 +0000 |
parents | 772eba9f4b30 |
children | 27537074f2a9 |
rev | line source |
---|---|
1845 | 1 /* |
2 * MOV demuxer | |
3 * Copyright (c) 2001 Fabrice Bellard. | |
4 * | |
5 * This file is part of FFmpeg. | |
6 * | |
7 * FFmpeg is free software; you can redistribute it and/or | |
8 * modify it under the terms of the GNU Lesser General Public | |
9 * License as published by the Free Software Foundation; either | |
10 * version 2.1 of the License, or (at your option) any later version. | |
11 * | |
12 * FFmpeg is distributed in the hope that it will be useful, | |
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
15 * Lesser General Public License for more details. | |
16 * | |
17 * You should have received a copy of the GNU Lesser General Public | |
18 * License along with FFmpeg; if not, write to the Free Software | |
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |
20 */ | |
21 | |
22 #include <limits.h> | |
23 | |
24 //#define DEBUG | |
25 | |
26 #include "avformat.h" | |
27 #include "riff.h" | |
28 #include "isom.h" | |
29 #include "dv.h" | |
3286 | 30 #include "libavcodec/mpeg4audio.h" |
31 #include "libavcodec/mpegaudiodata.h" | |
1845 | 32 |
33 #ifdef CONFIG_ZLIB | |
34 #include <zlib.h> | |
35 #endif | |
36 | |
37 /* | |
38 * First version by Francois Revol revol@free.fr | |
39 * Seek function by Gael Chardon gael.dev@4now.net | |
40 * | |
41 * Features and limitations: | |
42 * - reads most of the QT files I have (at least the structure), | |
43 * Sample QuickTime files with mp3 audio can be found at: http://www.3ivx.com/showcase.html | |
44 * - the code is quite ugly... maybe I won't do it recursive next time :-) | |
45 * | |
46 * Funny I didn't know about http://sourceforge.net/projects/qt-ffmpeg/ | |
47 * when coding this :) (it's a writer anyway) | |
48 * | |
49 * Reference documents: | |
50 * http://www.geocities.com/xhelmboyx/quicktime/formats/qtm-layout.txt | |
51 * Apple: | |
52 * http://developer.apple.com/documentation/QuickTime/QTFF/ | |
53 * http://developer.apple.com/documentation/QuickTime/QTFF/qtff.pdf | |
54 * QuickTime is a trademark of Apple (AFAIK :)) | |
55 */ | |
56 | |
57 #include "qtpalette.h" | |
58 | |
59 | |
60 #undef NDEBUG | |
61 #include <assert.h> | |
62 | |
63 /* the QuickTime file format is quite convoluted... | |
64 * it has lots of index tables, each indexing something in another one... | |
65 * Here we just use what is needed to read the chunks | |
66 */ | |
67 | |
2045
aa5e56700fdf
cosmectics, use consistant and homogeneous type names for atoms
bcoudurier
parents:
2044
diff
changeset
|
68 typedef struct { |
2030 | 69 int first; |
70 int count; | |
71 int id; | |
2045
aa5e56700fdf
cosmectics, use consistant and homogeneous type names for atoms
bcoudurier
parents:
2044
diff
changeset
|
72 } MOV_stsc_t; |
1845 | 73 |
74 typedef struct { | |
75 uint32_t type; | |
3085
bae59276377f
support mov reference files, ref.mov/ref.m2v/ref.wav and detect BrianCox.mov
bcoudurier
parents:
3084
diff
changeset
|
76 char *path; |
bae59276377f
support mov reference files, ref.mov/ref.m2v/ref.wav and detect BrianCox.mov
bcoudurier
parents:
3084
diff
changeset
|
77 } MOV_dref_t; |
bae59276377f
support mov reference files, ref.mov/ref.m2v/ref.wav and detect BrianCox.mov
bcoudurier
parents:
3084
diff
changeset
|
78 |
bae59276377f
support mov reference files, ref.mov/ref.m2v/ref.wav and detect BrianCox.mov
bcoudurier
parents:
3084
diff
changeset
|
79 typedef struct { |
bae59276377f
support mov reference files, ref.mov/ref.m2v/ref.wav and detect BrianCox.mov
bcoudurier
parents:
3084
diff
changeset
|
80 uint32_t type; |
1845 | 81 int64_t offset; |
82 int64_t size; /* total size (excluding the size and type fields) */ | |
83 } MOV_atom_t; | |
84 | |
85 struct MOVParseTableEntry; | |
86 | |
3169 | 87 typedef struct { |
88 unsigned track_id; | |
89 uint64_t base_data_offset; | |
90 uint64_t moof_offset; | |
91 unsigned stsd_id; | |
92 unsigned duration; | |
93 unsigned size; | |
94 unsigned flags; | |
95 } MOVFragment; | |
96 | |
97 typedef struct { | |
98 unsigned track_id; | |
99 unsigned stsd_id; | |
100 unsigned duration; | |
101 unsigned size; | |
102 unsigned flags; | |
103 } MOVTrackExt; | |
104 | |
1845 | 105 typedef struct MOVStreamContext { |
3085
bae59276377f
support mov reference files, ref.mov/ref.m2v/ref.wav and detect BrianCox.mov
bcoudurier
parents:
3084
diff
changeset
|
106 ByteIOContext *pb; |
1845 | 107 int ffindex; /* the ffmpeg stream id */ |
2030 | 108 int next_chunk; |
1845 | 109 unsigned int chunk_count; |
110 int64_t *chunk_offsets; | |
111 unsigned int stts_count; | |
2045
aa5e56700fdf
cosmectics, use consistant and homogeneous type names for atoms
bcoudurier
parents:
2044
diff
changeset
|
112 MOV_stts_t *stts_data; |
1845 | 113 unsigned int ctts_count; |
2045
aa5e56700fdf
cosmectics, use consistant and homogeneous type names for atoms
bcoudurier
parents:
2044
diff
changeset
|
114 MOV_stts_t *ctts_data; |
1845 | 115 unsigned int edit_count; /* number of 'edit' (elst atom) */ |
116 unsigned int sample_to_chunk_sz; | |
2045
aa5e56700fdf
cosmectics, use consistant and homogeneous type names for atoms
bcoudurier
parents:
2044
diff
changeset
|
117 MOV_stsc_t *sample_to_chunk; |
1845 | 118 int sample_to_ctime_index; |
119 int sample_to_ctime_sample; | |
120 unsigned int sample_size; | |
121 unsigned int sample_count; | |
2030 | 122 int *sample_sizes; |
1845 | 123 unsigned int keyframe_count; |
2030 | 124 int *keyframes; |
1845 | 125 int time_scale; |
126 int time_rate; | |
2030 | 127 int current_sample; |
1940
1a7f66384792
cosmetics, sample_size_v1 -> bytes_per_frame / samples_per_frame
bcoudurier
parents:
1939
diff
changeset
|
128 unsigned int bytes_per_frame; |
1a7f66384792
cosmetics, sample_size_v1 -> bytes_per_frame / samples_per_frame
bcoudurier
parents:
1939
diff
changeset
|
129 unsigned int samples_per_frame; |
1845 | 130 int dv_audio_container; |
3299
80a497804aa8
demux all stsd ids if codec is the same, fix premature_mov_ending.mov, closes #451
bcoudurier
parents:
3286
diff
changeset
|
131 int pseudo_stream_id; ///< -1 means demux all ids |
3029
10abe8748ec2
use correct demux mechanism when audio compression id is -2, dv audio does not matter, demux partially qt_dv_pal_test.mov which does NOT use cid -2
bcoudurier
parents:
3027
diff
changeset
|
132 int16_t audio_cid; ///< stsd audio compression id |
3085
bae59276377f
support mov reference files, ref.mov/ref.m2v/ref.wav and detect BrianCox.mov
bcoudurier
parents:
3084
diff
changeset
|
133 unsigned drefs_count; |
bae59276377f
support mov reference files, ref.mov/ref.m2v/ref.wav and detect BrianCox.mov
bcoudurier
parents:
3084
diff
changeset
|
134 MOV_dref_t *drefs; |
bae59276377f
support mov reference files, ref.mov/ref.m2v/ref.wav and detect BrianCox.mov
bcoudurier
parents:
3084
diff
changeset
|
135 int dref_id; |
1845 | 136 } MOVStreamContext; |
137 | |
138 typedef struct MOVContext { | |
139 AVFormatContext *fc; | |
140 int time_scale; | |
141 int64_t duration; /* duration of the longest track */ | |
142 int found_moov; /* when both 'moov' and 'mdat' sections has been found */ | |
143 int found_mdat; /* we suppose we have enough data to read the file */ | |
144 AVPaletteControl palette_control; | |
145 DVDemuxContext *dv_demux; | |
146 AVFormatContext *dv_fctx; | |
147 int isom; /* 1 if file is ISO Media (mp4/3gp) */ | |
3169 | 148 MOVFragment fragment; ///< current fragment in moof atom |
149 MOVTrackExt *trex_data; | |
150 unsigned trex_count; | |
1845 | 151 } MOVContext; |
152 | |
153 | |
154 /* XXX: it's the first time I make a recursive parser I think... sorry if it's ugly :P */ | |
155 | |
156 /* those functions parse an atom */ | |
157 /* return code: | |
3160 | 158 0: continue to parse next atom |
3175 | 159 <0: error occurred, exit |
3160 | 160 */ |
1845 | 161 /* links atom IDs to parse functions */ |
162 typedef struct MOVParseTableEntry { | |
163 uint32_t type; | |
2822
bdb887c3e9e9
cosmetics: func -> parse, remove useless parenthesis
bcoudurier
parents:
2821
diff
changeset
|
164 int (*parse)(MOVContext *ctx, ByteIOContext *pb, MOV_atom_t atom); |
1845 | 165 } MOVParseTableEntry; |
166 | |
2820
95ce00ad6f3e
save pointer to parse table, it is unlikely to change
bcoudurier
parents:
2819
diff
changeset
|
167 static const MOVParseTableEntry mov_default_parse_table[]; |
95ce00ad6f3e
save pointer to parse table, it is unlikely to change
bcoudurier
parents:
2819
diff
changeset
|
168 |
1845 | 169 static int mov_read_default(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom) |
170 { | |
171 int64_t total_size = 0; | |
172 MOV_atom_t a; | |
173 int i; | |
174 int err = 0; | |
175 | |
176 a.offset = atom.offset; | |
177 | |
178 if (atom.size < 0) | |
2026 | 179 atom.size = INT64_MAX; |
1845 | 180 while(((total_size + 8) < atom.size) && !url_feof(pb) && !err) { |
181 a.size = atom.size; | |
2826 | 182 a.type=0; |
1845 | 183 if(atom.size >= 8) { |
184 a.size = get_be32(pb); | |
185 a.type = get_le32(pb); | |
186 } | |
187 total_size += 8; | |
188 a.offset += 8; | |
2902 | 189 dprintf(c->fc, "type: %08x %.4s sz: %"PRIx64" %"PRIx64" %"PRIx64"\n", |
190 a.type, (char*)&a.type, a.size, atom.size, total_size); | |
1845 | 191 if (a.size == 1) { /* 64 bit extended size */ |
192 a.size = get_be64(pb) - 8; | |
193 a.offset += 8; | |
194 total_size += 8; | |
195 } | |
196 if (a.size == 0) { | |
197 a.size = atom.size - total_size; | |
198 if (a.size <= 8) | |
199 break; | |
200 } | |
1964
4571a481081d
move atom size check before parsing function search
bcoudurier
parents:
1963
diff
changeset
|
201 a.size -= 8; |
2660
022174d849d5
fix issue 225, instead of stoping when wrong atom size is found,
bcoudurier
parents:
2589
diff
changeset
|
202 if(a.size < 0) |
1964
4571a481081d
move atom size check before parsing function search
bcoudurier
parents:
1963
diff
changeset
|
203 break; |
2665 | 204 a.size = FFMIN(a.size, atom.size - total_size); |
1964
4571a481081d
move atom size check before parsing function search
bcoudurier
parents:
1963
diff
changeset
|
205 |
2826 | 206 for (i = 0; mov_default_parse_table[i].type != 0 |
2820
95ce00ad6f3e
save pointer to parse table, it is unlikely to change
bcoudurier
parents:
2819
diff
changeset
|
207 && mov_default_parse_table[i].type != a.type; i++) |
1845 | 208 /* empty */; |
209 | |
2820
95ce00ad6f3e
save pointer to parse table, it is unlikely to change
bcoudurier
parents:
2819
diff
changeset
|
210 if (mov_default_parse_table[i].type == 0) { /* skip leaf atoms data */ |
1845 | 211 url_fskip(pb, a.size); |
212 } else { | |
213 offset_t start_pos = url_ftell(pb); | |
214 int64_t left; | |
2822
bdb887c3e9e9
cosmetics: func -> parse, remove useless parenthesis
bcoudurier
parents:
2821
diff
changeset
|
215 err = mov_default_parse_table[i].parse(c, pb, a); |
3166
c082ee7573b2
simplify, and only stop parsing when non streamable
bcoudurier
parents:
3164
diff
changeset
|
216 if (url_is_streamed(pb) && c->found_moov && c->found_mdat) |
2817 | 217 break; |
1845 | 218 left = a.size - url_ftell(pb) + start_pos; |
219 if (left > 0) /* skip garbage at atom end */ | |
220 url_fskip(pb, left); | |
221 } | |
222 | |
223 a.offset += a.size; | |
224 total_size += a.size; | |
225 } | |
226 | |
3181 | 227 if (!err && total_size < atom.size && atom.size < 0x7ffff) |
1845 | 228 url_fskip(pb, atom.size - total_size); |
229 | |
230 return err; | |
231 } | |
232 | |
3085
bae59276377f
support mov reference files, ref.mov/ref.m2v/ref.wav and detect BrianCox.mov
bcoudurier
parents:
3084
diff
changeset
|
233 static int mov_read_dref(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom) |
bae59276377f
support mov reference files, ref.mov/ref.m2v/ref.wav and detect BrianCox.mov
bcoudurier
parents:
3084
diff
changeset
|
234 { |
bae59276377f
support mov reference files, ref.mov/ref.m2v/ref.wav and detect BrianCox.mov
bcoudurier
parents:
3084
diff
changeset
|
235 AVStream *st = c->fc->streams[c->fc->nb_streams-1]; |
bae59276377f
support mov reference files, ref.mov/ref.m2v/ref.wav and detect BrianCox.mov
bcoudurier
parents:
3084
diff
changeset
|
236 MOVStreamContext *sc = st->priv_data; |
bae59276377f
support mov reference files, ref.mov/ref.m2v/ref.wav and detect BrianCox.mov
bcoudurier
parents:
3084
diff
changeset
|
237 int entries, i, j; |
bae59276377f
support mov reference files, ref.mov/ref.m2v/ref.wav and detect BrianCox.mov
bcoudurier
parents:
3084
diff
changeset
|
238 |
bae59276377f
support mov reference files, ref.mov/ref.m2v/ref.wav and detect BrianCox.mov
bcoudurier
parents:
3084
diff
changeset
|
239 get_be32(pb); // version + flags |
bae59276377f
support mov reference files, ref.mov/ref.m2v/ref.wav and detect BrianCox.mov
bcoudurier
parents:
3084
diff
changeset
|
240 entries = get_be32(pb); |
bae59276377f
support mov reference files, ref.mov/ref.m2v/ref.wav and detect BrianCox.mov
bcoudurier
parents:
3084
diff
changeset
|
241 if (entries >= UINT_MAX / sizeof(*sc->drefs)) |
bae59276377f
support mov reference files, ref.mov/ref.m2v/ref.wav and detect BrianCox.mov
bcoudurier
parents:
3084
diff
changeset
|
242 return -1; |
bae59276377f
support mov reference files, ref.mov/ref.m2v/ref.wav and detect BrianCox.mov
bcoudurier
parents:
3084
diff
changeset
|
243 sc->drefs_count = entries; |
bae59276377f
support mov reference files, ref.mov/ref.m2v/ref.wav and detect BrianCox.mov
bcoudurier
parents:
3084
diff
changeset
|
244 sc->drefs = av_mallocz(entries * sizeof(*sc->drefs)); |
bae59276377f
support mov reference files, ref.mov/ref.m2v/ref.wav and detect BrianCox.mov
bcoudurier
parents:
3084
diff
changeset
|
245 |
bae59276377f
support mov reference files, ref.mov/ref.m2v/ref.wav and detect BrianCox.mov
bcoudurier
parents:
3084
diff
changeset
|
246 for (i = 0; i < sc->drefs_count; i++) { |
bae59276377f
support mov reference files, ref.mov/ref.m2v/ref.wav and detect BrianCox.mov
bcoudurier
parents:
3084
diff
changeset
|
247 MOV_dref_t *dref = &sc->drefs[i]; |
bae59276377f
support mov reference files, ref.mov/ref.m2v/ref.wav and detect BrianCox.mov
bcoudurier
parents:
3084
diff
changeset
|
248 uint32_t size = get_be32(pb); |
bae59276377f
support mov reference files, ref.mov/ref.m2v/ref.wav and detect BrianCox.mov
bcoudurier
parents:
3084
diff
changeset
|
249 offset_t next = url_ftell(pb) + size - 4; |
bae59276377f
support mov reference files, ref.mov/ref.m2v/ref.wav and detect BrianCox.mov
bcoudurier
parents:
3084
diff
changeset
|
250 |
bae59276377f
support mov reference files, ref.mov/ref.m2v/ref.wav and detect BrianCox.mov
bcoudurier
parents:
3084
diff
changeset
|
251 dref->type = get_le32(pb); |
bae59276377f
support mov reference files, ref.mov/ref.m2v/ref.wav and detect BrianCox.mov
bcoudurier
parents:
3084
diff
changeset
|
252 get_be32(pb); // version + flags |
bae59276377f
support mov reference files, ref.mov/ref.m2v/ref.wav and detect BrianCox.mov
bcoudurier
parents:
3084
diff
changeset
|
253 dprintf(c->fc, "type %.4s size %d\n", (char*)&dref->type, size); |
bae59276377f
support mov reference files, ref.mov/ref.m2v/ref.wav and detect BrianCox.mov
bcoudurier
parents:
3084
diff
changeset
|
254 |
bae59276377f
support mov reference files, ref.mov/ref.m2v/ref.wav and detect BrianCox.mov
bcoudurier
parents:
3084
diff
changeset
|
255 if (dref->type == MKTAG('a','l','i','s') && size > 150) { |
bae59276377f
support mov reference files, ref.mov/ref.m2v/ref.wav and detect BrianCox.mov
bcoudurier
parents:
3084
diff
changeset
|
256 /* macintosh alias record */ |
bae59276377f
support mov reference files, ref.mov/ref.m2v/ref.wav and detect BrianCox.mov
bcoudurier
parents:
3084
diff
changeset
|
257 uint16_t volume_len, len; |
bae59276377f
support mov reference files, ref.mov/ref.m2v/ref.wav and detect BrianCox.mov
bcoudurier
parents:
3084
diff
changeset
|
258 char volume[28]; |
bae59276377f
support mov reference files, ref.mov/ref.m2v/ref.wav and detect BrianCox.mov
bcoudurier
parents:
3084
diff
changeset
|
259 int16_t type; |
bae59276377f
support mov reference files, ref.mov/ref.m2v/ref.wav and detect BrianCox.mov
bcoudurier
parents:
3084
diff
changeset
|
260 |
bae59276377f
support mov reference files, ref.mov/ref.m2v/ref.wav and detect BrianCox.mov
bcoudurier
parents:
3084
diff
changeset
|
261 url_fskip(pb, 10); |
bae59276377f
support mov reference files, ref.mov/ref.m2v/ref.wav and detect BrianCox.mov
bcoudurier
parents:
3084
diff
changeset
|
262 |
bae59276377f
support mov reference files, ref.mov/ref.m2v/ref.wav and detect BrianCox.mov
bcoudurier
parents:
3084
diff
changeset
|
263 volume_len = get_byte(pb); |
bae59276377f
support mov reference files, ref.mov/ref.m2v/ref.wav and detect BrianCox.mov
bcoudurier
parents:
3084
diff
changeset
|
264 volume_len = FFMIN(volume_len, 27); |
bae59276377f
support mov reference files, ref.mov/ref.m2v/ref.wav and detect BrianCox.mov
bcoudurier
parents:
3084
diff
changeset
|
265 get_buffer(pb, volume, 27); |
bae59276377f
support mov reference files, ref.mov/ref.m2v/ref.wav and detect BrianCox.mov
bcoudurier
parents:
3084
diff
changeset
|
266 volume[volume_len] = 0; |
bae59276377f
support mov reference files, ref.mov/ref.m2v/ref.wav and detect BrianCox.mov
bcoudurier
parents:
3084
diff
changeset
|
267 av_log(c->fc, AV_LOG_DEBUG, "volume %s, len %d\n", volume, volume_len); |
bae59276377f
support mov reference files, ref.mov/ref.m2v/ref.wav and detect BrianCox.mov
bcoudurier
parents:
3084
diff
changeset
|
268 |
bae59276377f
support mov reference files, ref.mov/ref.m2v/ref.wav and detect BrianCox.mov
bcoudurier
parents:
3084
diff
changeset
|
269 url_fskip(pb, 112); |
bae59276377f
support mov reference files, ref.mov/ref.m2v/ref.wav and detect BrianCox.mov
bcoudurier
parents:
3084
diff
changeset
|
270 |
bae59276377f
support mov reference files, ref.mov/ref.m2v/ref.wav and detect BrianCox.mov
bcoudurier
parents:
3084
diff
changeset
|
271 for (type = 0; type != -1 && url_ftell(pb) < next; ) { |
bae59276377f
support mov reference files, ref.mov/ref.m2v/ref.wav and detect BrianCox.mov
bcoudurier
parents:
3084
diff
changeset
|
272 type = get_be16(pb); |
bae59276377f
support mov reference files, ref.mov/ref.m2v/ref.wav and detect BrianCox.mov
bcoudurier
parents:
3084
diff
changeset
|
273 len = get_be16(pb); |
bae59276377f
support mov reference files, ref.mov/ref.m2v/ref.wav and detect BrianCox.mov
bcoudurier
parents:
3084
diff
changeset
|
274 av_log(c->fc, AV_LOG_DEBUG, "type %d, len %d\n", type, len); |
bae59276377f
support mov reference files, ref.mov/ref.m2v/ref.wav and detect BrianCox.mov
bcoudurier
parents:
3084
diff
changeset
|
275 if (len&1) |
bae59276377f
support mov reference files, ref.mov/ref.m2v/ref.wav and detect BrianCox.mov
bcoudurier
parents:
3084
diff
changeset
|
276 len += 1; |
bae59276377f
support mov reference files, ref.mov/ref.m2v/ref.wav and detect BrianCox.mov
bcoudurier
parents:
3084
diff
changeset
|
277 if (type == 2) { // absolute path |
3092 | 278 av_free(dref->path); |
3085
bae59276377f
support mov reference files, ref.mov/ref.m2v/ref.wav and detect BrianCox.mov
bcoudurier
parents:
3084
diff
changeset
|
279 dref->path = av_mallocz(len+1); |
3091 | 280 if (!dref->path) |
281 return AVERROR(ENOMEM); | |
3085
bae59276377f
support mov reference files, ref.mov/ref.m2v/ref.wav and detect BrianCox.mov
bcoudurier
parents:
3084
diff
changeset
|
282 get_buffer(pb, dref->path, len); |
3090 | 283 if (len > volume_len && !strncmp(dref->path, volume, volume_len)) { |
3085
bae59276377f
support mov reference files, ref.mov/ref.m2v/ref.wav and detect BrianCox.mov
bcoudurier
parents:
3084
diff
changeset
|
284 len -= volume_len; |
bae59276377f
support mov reference files, ref.mov/ref.m2v/ref.wav and detect BrianCox.mov
bcoudurier
parents:
3084
diff
changeset
|
285 memmove(dref->path, dref->path+volume_len, len); |
bae59276377f
support mov reference files, ref.mov/ref.m2v/ref.wav and detect BrianCox.mov
bcoudurier
parents:
3084
diff
changeset
|
286 dref->path[len] = 0; |
bae59276377f
support mov reference files, ref.mov/ref.m2v/ref.wav and detect BrianCox.mov
bcoudurier
parents:
3084
diff
changeset
|
287 } |
bae59276377f
support mov reference files, ref.mov/ref.m2v/ref.wav and detect BrianCox.mov
bcoudurier
parents:
3084
diff
changeset
|
288 for (j = 0; j < len; j++) |
bae59276377f
support mov reference files, ref.mov/ref.m2v/ref.wav and detect BrianCox.mov
bcoudurier
parents:
3084
diff
changeset
|
289 if (dref->path[j] == ':') |
bae59276377f
support mov reference files, ref.mov/ref.m2v/ref.wav and detect BrianCox.mov
bcoudurier
parents:
3084
diff
changeset
|
290 dref->path[j] = '/'; |
bae59276377f
support mov reference files, ref.mov/ref.m2v/ref.wav and detect BrianCox.mov
bcoudurier
parents:
3084
diff
changeset
|
291 av_log(c->fc, AV_LOG_DEBUG, "path %s\n", dref->path); |
bae59276377f
support mov reference files, ref.mov/ref.m2v/ref.wav and detect BrianCox.mov
bcoudurier
parents:
3084
diff
changeset
|
292 } else |
bae59276377f
support mov reference files, ref.mov/ref.m2v/ref.wav and detect BrianCox.mov
bcoudurier
parents:
3084
diff
changeset
|
293 url_fskip(pb, len); |
bae59276377f
support mov reference files, ref.mov/ref.m2v/ref.wav and detect BrianCox.mov
bcoudurier
parents:
3084
diff
changeset
|
294 } |
bae59276377f
support mov reference files, ref.mov/ref.m2v/ref.wav and detect BrianCox.mov
bcoudurier
parents:
3084
diff
changeset
|
295 } |
bae59276377f
support mov reference files, ref.mov/ref.m2v/ref.wav and detect BrianCox.mov
bcoudurier
parents:
3084
diff
changeset
|
296 url_fseek(pb, next, SEEK_SET); |
bae59276377f
support mov reference files, ref.mov/ref.m2v/ref.wav and detect BrianCox.mov
bcoudurier
parents:
3084
diff
changeset
|
297 } |
bae59276377f
support mov reference files, ref.mov/ref.m2v/ref.wav and detect BrianCox.mov
bcoudurier
parents:
3084
diff
changeset
|
298 return 0; |
bae59276377f
support mov reference files, ref.mov/ref.m2v/ref.wav and detect BrianCox.mov
bcoudurier
parents:
3084
diff
changeset
|
299 } |
bae59276377f
support mov reference files, ref.mov/ref.m2v/ref.wav and detect BrianCox.mov
bcoudurier
parents:
3084
diff
changeset
|
300 |
1845 | 301 static int mov_read_hdlr(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom) |
302 { | |
303 AVStream *st = c->fc->streams[c->fc->nb_streams-1]; | |
304 uint32_t type; | |
305 uint32_t ctype; | |
306 | |
307 get_byte(pb); /* version */ | |
3145 | 308 get_be24(pb); /* flags */ |
1845 | 309 |
310 /* component type */ | |
311 ctype = get_le32(pb); | |
312 type = get_le32(pb); /* component subtype */ | |
313 | |
2902 | 314 dprintf(c->fc, "ctype= %c%c%c%c (0x%08x)\n", *((char *)&ctype), ((char *)&ctype)[1], |
315 ((char *)&ctype)[2], ((char *)&ctype)[3], (int) ctype); | |
316 dprintf(c->fc, "stype= %c%c%c%c\n", | |
317 *((char *)&type), ((char *)&type)[1], ((char *)&type)[2], ((char *)&type)[3]); | |
1845 | 318 if(!ctype) |
319 c->isom = 1; | |
3254 | 320 if (type == MKTAG('v','i','d','e')) |
1845 | 321 st->codec->codec_type = CODEC_TYPE_VIDEO; |
3253 | 322 else if(type == MKTAG('s','o','u','n')) |
1845 | 323 st->codec->codec_type = CODEC_TYPE_AUDIO; |
3253 | 324 else if(type == MKTAG('m','1','a',' ')) |
1845 | 325 st->codec->codec_id = CODEC_ID_MP2; |
3253 | 326 else if(type == MKTAG('s','u','b','p')) { |
1845 | 327 st->codec->codec_type = CODEC_TYPE_SUBTITLE; |
328 } | |
329 get_be32(pb); /* component manufacture */ | |
330 get_be32(pb); /* component flags */ | |
331 get_be32(pb); /* component flags mask */ | |
332 | |
333 if(atom.size <= 24) | |
334 return 0; /* nothing left to read */ | |
335 | |
336 url_fskip(pb, atom.size - (url_ftell(pb) - atom.offset)); | |
337 return 0; | |
338 } | |
339 | |
2029 | 340 static int mp4_read_descr_len(ByteIOContext *pb) |
1845 | 341 { |
342 int len = 0; | |
343 int count = 4; | |
344 while (count--) { | |
345 int c = get_byte(pb); | |
346 len = (len << 7) | (c & 0x7f); | |
347 if (!(c & 0x80)) | |
348 break; | |
349 } | |
350 return len; | |
351 } | |
352 | |
2029 | 353 static int mp4_read_descr(MOVContext *c, ByteIOContext *pb, int *tag) |
1845 | 354 { |
355 int len; | |
356 *tag = get_byte(pb); | |
2029 | 357 len = mp4_read_descr_len(pb); |
1907 | 358 dprintf(c->fc, "MPEG4 description: tag=0x%02x len=%d\n", *tag, len); |
1845 | 359 return len; |
360 } | |
361 | |
2028 | 362 #define MP4ESDescrTag 0x03 |
363 #define MP4DecConfigDescrTag 0x04 | |
364 #define MP4DecSpecificDescrTag 0x05 | |
365 | |
3261
bf5f112efcff
parse mpeg4audio config to correctly detect mp3on4, fix iso mp3on4 reference files
bcoudurier
parents:
3260
diff
changeset
|
366 static const AVCodecTag mp4_audio_types[] = { |
bf5f112efcff
parse mpeg4audio config to correctly detect mp3on4, fix iso mp3on4 reference files
bcoudurier
parents:
3260
diff
changeset
|
367 { CODEC_ID_MP3ON4, 29 }, /* old mp3on4 draft */ |
bf5f112efcff
parse mpeg4audio config to correctly detect mp3on4, fix iso mp3on4 reference files
bcoudurier
parents:
3260
diff
changeset
|
368 { CODEC_ID_MP3ON4, 32 }, /* layer 1 */ |
bf5f112efcff
parse mpeg4audio config to correctly detect mp3on4, fix iso mp3on4 reference files
bcoudurier
parents:
3260
diff
changeset
|
369 { CODEC_ID_MP3ON4, 33 }, /* layer 2 */ |
bf5f112efcff
parse mpeg4audio config to correctly detect mp3on4, fix iso mp3on4 reference files
bcoudurier
parents:
3260
diff
changeset
|
370 { CODEC_ID_MP3ON4, 34 }, /* layer 3 */ |
bf5f112efcff
parse mpeg4audio config to correctly detect mp3on4, fix iso mp3on4 reference files
bcoudurier
parents:
3260
diff
changeset
|
371 { CODEC_ID_NONE, 0 }, |
bf5f112efcff
parse mpeg4audio config to correctly detect mp3on4, fix iso mp3on4 reference files
bcoudurier
parents:
3260
diff
changeset
|
372 }; |
bf5f112efcff
parse mpeg4audio config to correctly detect mp3on4, fix iso mp3on4 reference files
bcoudurier
parents:
3260
diff
changeset
|
373 |
1845 | 374 static int mov_read_esds(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom) |
375 { | |
376 AVStream *st = c->fc->streams[c->fc->nb_streams-1]; | |
377 int tag, len; | |
378 | |
379 get_be32(pb); /* version + flags */ | |
2029 | 380 len = mp4_read_descr(c, pb, &tag); |
1845 | 381 if (tag == MP4ESDescrTag) { |
382 get_be16(pb); /* ID */ | |
383 get_byte(pb); /* priority */ | |
384 } else | |
385 get_be16(pb); /* ID */ | |
386 | |
2029 | 387 len = mp4_read_descr(c, pb, &tag); |
1845 | 388 if (tag == MP4DecConfigDescrTag) { |
2028 | 389 int object_type_id = get_byte(pb); |
390 get_byte(pb); /* stream type */ | |
391 get_be24(pb); /* buffer size db */ | |
392 get_be32(pb); /* max bitrate */ | |
393 get_be32(pb); /* avg bitrate */ | |
1845 | 394 |
2028 | 395 st->codec->codec_id= codec_get_id(ff_mp4_obj_type, object_type_id); |
396 dprintf(c->fc, "esds object type id %d\n", object_type_id); | |
2029 | 397 len = mp4_read_descr(c, pb, &tag); |
1845 | 398 if (tag == MP4DecSpecificDescrTag) { |
1907 | 399 dprintf(c->fc, "Specific MPEG4 header len=%d\n", len); |
3078 | 400 if((uint64_t)len > (1<<30)) |
401 return -1; | |
1845 | 402 st->codec->extradata = av_mallocz(len + FF_INPUT_BUFFER_PADDING_SIZE); |
3076 | 403 if (!st->codec->extradata) |
404 return AVERROR(ENOMEM); | |
3077 | 405 get_buffer(pb, st->codec->extradata, len); |
406 st->codec->extradata_size = len; | |
3261
bf5f112efcff
parse mpeg4audio config to correctly detect mp3on4, fix iso mp3on4 reference files
bcoudurier
parents:
3260
diff
changeset
|
407 if (st->codec->codec_id == CODEC_ID_AAC) { |
bf5f112efcff
parse mpeg4audio config to correctly detect mp3on4, fix iso mp3on4 reference files
bcoudurier
parents:
3260
diff
changeset
|
408 MPEG4AudioConfig cfg; |
bf5f112efcff
parse mpeg4audio config to correctly detect mp3on4, fix iso mp3on4 reference files
bcoudurier
parents:
3260
diff
changeset
|
409 ff_mpeg4audio_get_config(&cfg, st->codec->extradata, |
bf5f112efcff
parse mpeg4audio config to correctly detect mp3on4, fix iso mp3on4 reference files
bcoudurier
parents:
3260
diff
changeset
|
410 st->codec->extradata_size); |
3362
0dfa207c5d69
aac chan config is 0 if bitstream contains program_config_element
bcoudurier
parents:
3313
diff
changeset
|
411 if (cfg.chan_config > 7) |
3262
07299732f3b8
set channels and sample rate from mpeg4audio config
bcoudurier
parents:
3261
diff
changeset
|
412 return -1; |
07299732f3b8
set channels and sample rate from mpeg4audio config
bcoudurier
parents:
3261
diff
changeset
|
413 st->codec->channels = ff_mpeg4audio_channels[cfg.chan_config]; |
07299732f3b8
set channels and sample rate from mpeg4audio config
bcoudurier
parents:
3261
diff
changeset
|
414 if (cfg.object_type == 29 && cfg.sampling_index < 3) // old mp3on4 |
07299732f3b8
set channels and sample rate from mpeg4audio config
bcoudurier
parents:
3261
diff
changeset
|
415 st->codec->sample_rate = ff_mpa_freq_tab[cfg.sampling_index]; |
07299732f3b8
set channels and sample rate from mpeg4audio config
bcoudurier
parents:
3261
diff
changeset
|
416 else |
07299732f3b8
set channels and sample rate from mpeg4audio config
bcoudurier
parents:
3261
diff
changeset
|
417 st->codec->sample_rate = cfg.sample_rate; // ext sample rate ? |
07299732f3b8
set channels and sample rate from mpeg4audio config
bcoudurier
parents:
3261
diff
changeset
|
418 dprintf(c->fc, "mp4a config channels %d obj %d ext obj %d " |
07299732f3b8
set channels and sample rate from mpeg4audio config
bcoudurier
parents:
3261
diff
changeset
|
419 "sample rate %d ext sample rate %d\n", st->codec->channels, |
07299732f3b8
set channels and sample rate from mpeg4audio config
bcoudurier
parents:
3261
diff
changeset
|
420 cfg.object_type, cfg.ext_object_type, |
07299732f3b8
set channels and sample rate from mpeg4audio config
bcoudurier
parents:
3261
diff
changeset
|
421 cfg.sample_rate, cfg.ext_sample_rate); |
3261
bf5f112efcff
parse mpeg4audio config to correctly detect mp3on4, fix iso mp3on4 reference files
bcoudurier
parents:
3260
diff
changeset
|
422 if (!(st->codec->codec_id = codec_get_id(mp4_audio_types, |
bf5f112efcff
parse mpeg4audio config to correctly detect mp3on4, fix iso mp3on4 reference files
bcoudurier
parents:
3260
diff
changeset
|
423 cfg.object_type))) |
bf5f112efcff
parse mpeg4audio config to correctly detect mp3on4, fix iso mp3on4 reference files
bcoudurier
parents:
3260
diff
changeset
|
424 st->codec->codec_id = CODEC_ID_AAC; |
3077 | 425 } |
1845 | 426 } |
427 } | |
428 return 0; | |
429 } | |
430 | |
431 /* this atom contains actual media data */ | |
432 static int mov_read_mdat(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom) | |
433 { | |
434 if(atom.size == 0) /* wrong one (MP4) */ | |
435 return 0; | |
436 c->found_mdat=1; | |
437 return 0; /* now go for moov */ | |
438 } | |
439 | |
440 static int mov_read_ftyp(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom) | |
441 { | |
442 uint32_t type = get_le32(pb); | |
443 | |
444 if (type != MKTAG('q','t',' ',' ')) | |
445 c->isom = 1; | |
446 av_log(c->fc, AV_LOG_DEBUG, "ISO: File Type Major Brand: %.4s\n",(char *)&type); | |
447 get_be32(pb); /* minor version */ | |
448 url_fskip(pb, atom.size - 8); | |
449 return 0; | |
450 } | |
451 | |
452 /* this atom should contain all header atoms */ | |
453 static int mov_read_moov(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom) | |
454 { | |
2806
1ce39cda4a59
check mov_read_default return value where appropriate, patch by takis, fix issue 285
bcoudurier
parents:
2794
diff
changeset
|
455 if (mov_read_default(c, pb, atom) < 0) |
1ce39cda4a59
check mov_read_default return value where appropriate, patch by takis, fix issue 285
bcoudurier
parents:
2794
diff
changeset
|
456 return -1; |
1845 | 457 /* we parsed the 'moov' atom, we can terminate the parsing as soon as we find the 'mdat' */ |
458 /* so we don't parse the whole file if over a network */ | |
459 c->found_moov=1; | |
460 return 0; /* now go for mdat */ | |
461 } | |
462 | |
3169 | 463 static int mov_read_moof(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom) |
464 { | |
465 c->fragment.moof_offset = url_ftell(pb) - 8; | |
466 dprintf(c->fc, "moof offset %llx\n", c->fragment.moof_offset); | |
467 return mov_read_default(c, pb, atom); | |
468 } | |
1845 | 469 |
470 static int mov_read_mdhd(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom) | |
471 { | |
472 AVStream *st = c->fc->streams[c->fc->nb_streams-1]; | |
2006 | 473 MOVStreamContext *sc = st->priv_data; |
1845 | 474 int version = get_byte(pb); |
475 int lang; | |
476 | |
477 if (version > 1) | |
3259 | 478 return -1; /* unsupported */ |
1845 | 479 |
3145 | 480 get_be24(pb); /* flags */ |
1845 | 481 if (version == 1) { |
482 get_be64(pb); | |
483 get_be64(pb); | |
484 } else { | |
485 get_be32(pb); /* creation time */ | |
486 get_be32(pb); /* modification time */ | |
487 } | |
488 | |
489 sc->time_scale = get_be32(pb); | |
490 st->duration = (version == 1) ? get_be64(pb) : get_be32(pb); /* duration */ | |
491 | |
492 lang = get_be16(pb); /* language */ | |
493 ff_mov_lang_to_iso639(lang, st->language); | |
494 get_be16(pb); /* quality */ | |
495 | |
496 return 0; | |
497 } | |
498 | |
499 static int mov_read_mvhd(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom) | |
500 { | |
501 int version = get_byte(pb); /* version */ | |
3145 | 502 get_be24(pb); /* flags */ |
1845 | 503 |
504 if (version == 1) { | |
505 get_be64(pb); | |
506 get_be64(pb); | |
507 } else { | |
508 get_be32(pb); /* creation time */ | |
509 get_be32(pb); /* modification time */ | |
510 } | |
511 c->time_scale = get_be32(pb); /* time scale */ | |
2044 | 512 |
513 dprintf(c->fc, "time scale = %i\n", c->time_scale); | |
514 | |
1845 | 515 c->duration = (version == 1) ? get_be64(pb) : get_be32(pb); /* duration */ |
516 get_be32(pb); /* preferred scale */ | |
517 | |
518 get_be16(pb); /* preferred volume */ | |
519 | |
520 url_fskip(pb, 10); /* reserved */ | |
521 | |
522 url_fskip(pb, 36); /* display matrix */ | |
523 | |
524 get_be32(pb); /* preview time */ | |
525 get_be32(pb); /* preview duration */ | |
526 get_be32(pb); /* poster time */ | |
527 get_be32(pb); /* selection time */ | |
528 get_be32(pb); /* selection duration */ | |
529 get_be32(pb); /* current time */ | |
530 get_be32(pb); /* next track ID */ | |
531 | |
532 return 0; | |
533 } | |
534 | |
535 static int mov_read_smi(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom) | |
536 { | |
537 AVStream *st = c->fc->streams[c->fc->nb_streams-1]; | |
538 | |
539 if((uint64_t)atom.size > (1<<30)) | |
540 return -1; | |
541 | |
542 // currently SVQ3 decoder expect full STSD header - so let's fake it | |
543 // this should be fixed and just SMI header should be passed | |
544 av_free(st->codec->extradata); | |
3076 | 545 st->codec->extradata = av_mallocz(atom.size + 0x5a + FF_INPUT_BUFFER_PADDING_SIZE); |
546 if (!st->codec->extradata) | |
547 return AVERROR(ENOMEM); | |
3077 | 548 st->codec->extradata_size = 0x5a + atom.size; |
549 memcpy(st->codec->extradata, "SVQ3", 4); // fake | |
550 get_buffer(pb, st->codec->extradata + 0x5a, atom.size); | |
551 dprintf(c->fc, "Reading SMI %"PRId64" %s\n", atom.size, st->codec->extradata + 0x5a); | |
1845 | 552 return 0; |
553 } | |
554 | |
555 static int mov_read_enda(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom) | |
556 { | |
557 AVStream *st = c->fc->streams[c->fc->nb_streams-1]; | |
558 int little_endian = get_be16(pb); | |
559 | |
560 if (little_endian) { | |
561 switch (st->codec->codec_id) { | |
562 case CODEC_ID_PCM_S24BE: | |
563 st->codec->codec_id = CODEC_ID_PCM_S24LE; | |
564 break; | |
565 case CODEC_ID_PCM_S32BE: | |
566 st->codec->codec_id = CODEC_ID_PCM_S32LE; | |
567 break; | |
3738
0c46eb1cd9b3
Make MOV demuxer handle F32BE, F32LE, F64BE and F64LE PCM audio.
pross
parents:
3626
diff
changeset
|
568 case CODEC_ID_PCM_F32BE: |
0c46eb1cd9b3
Make MOV demuxer handle F32BE, F32LE, F64BE and F64LE PCM audio.
pross
parents:
3626
diff
changeset
|
569 st->codec->codec_id = CODEC_ID_PCM_F32LE; |
0c46eb1cd9b3
Make MOV demuxer handle F32BE, F32LE, F64BE and F64LE PCM audio.
pross
parents:
3626
diff
changeset
|
570 break; |
0c46eb1cd9b3
Make MOV demuxer handle F32BE, F32LE, F64BE and F64LE PCM audio.
pross
parents:
3626
diff
changeset
|
571 case CODEC_ID_PCM_F64BE: |
0c46eb1cd9b3
Make MOV demuxer handle F32BE, F32LE, F64BE and F64LE PCM audio.
pross
parents:
3626
diff
changeset
|
572 st->codec->codec_id = CODEC_ID_PCM_F64LE; |
0c46eb1cd9b3
Make MOV demuxer handle F32BE, F32LE, F64BE and F64LE PCM audio.
pross
parents:
3626
diff
changeset
|
573 break; |
1845 | 574 default: |
575 break; | |
576 } | |
577 } | |
578 return 0; | |
579 } | |
580 | |
581 /* FIXME modify qdm2/svq3/h264 decoders to take full atom as extradata */ | |
582 static int mov_read_extradata(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom) | |
583 { | |
584 AVStream *st = c->fc->streams[c->fc->nb_streams-1]; | |
2589
960795567b33
append extradata atoms when parsing, fix OLOCOONS_O3.mov
bcoudurier
parents:
2547
diff
changeset
|
585 uint64_t size= (uint64_t)st->codec->extradata_size + atom.size + 8 + FF_INPUT_BUFFER_PADDING_SIZE; |
960795567b33
append extradata atoms when parsing, fix OLOCOONS_O3.mov
bcoudurier
parents:
2547
diff
changeset
|
586 uint8_t *buf; |
960795567b33
append extradata atoms when parsing, fix OLOCOONS_O3.mov
bcoudurier
parents:
2547
diff
changeset
|
587 if(size > INT_MAX || (uint64_t)atom.size > INT_MAX) |
960795567b33
append extradata atoms when parsing, fix OLOCOONS_O3.mov
bcoudurier
parents:
2547
diff
changeset
|
588 return -1; |
960795567b33
append extradata atoms when parsing, fix OLOCOONS_O3.mov
bcoudurier
parents:
2547
diff
changeset
|
589 buf= av_realloc(st->codec->extradata, size); |
960795567b33
append extradata atoms when parsing, fix OLOCOONS_O3.mov
bcoudurier
parents:
2547
diff
changeset
|
590 if(!buf) |
1845 | 591 return -1; |
2589
960795567b33
append extradata atoms when parsing, fix OLOCOONS_O3.mov
bcoudurier
parents:
2547
diff
changeset
|
592 st->codec->extradata= buf; |
960795567b33
append extradata atoms when parsing, fix OLOCOONS_O3.mov
bcoudurier
parents:
2547
diff
changeset
|
593 buf+= st->codec->extradata_size; |
960795567b33
append extradata atoms when parsing, fix OLOCOONS_O3.mov
bcoudurier
parents:
2547
diff
changeset
|
594 st->codec->extradata_size= size - FF_INPUT_BUFFER_PADDING_SIZE; |
960795567b33
append extradata atoms when parsing, fix OLOCOONS_O3.mov
bcoudurier
parents:
2547
diff
changeset
|
595 AV_WB32( buf , atom.size + 8); |
960795567b33
append extradata atoms when parsing, fix OLOCOONS_O3.mov
bcoudurier
parents:
2547
diff
changeset
|
596 AV_WL32( buf + 4, atom.type); |
960795567b33
append extradata atoms when parsing, fix OLOCOONS_O3.mov
bcoudurier
parents:
2547
diff
changeset
|
597 get_buffer(pb, buf + 8, atom.size); |
1845 | 598 return 0; |
599 } | |
600 | |
601 static int mov_read_wave(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom) | |
602 { | |
603 AVStream *st = c->fc->streams[c->fc->nb_streams-1]; | |
604 | |
605 if((uint64_t)atom.size > (1<<30)) | |
606 return -1; | |
607 | |
608 if (st->codec->codec_id == CODEC_ID_QDM2) { | |
609 // pass all frma atom to codec, needed at least for QDM2 | |
610 av_free(st->codec->extradata); | |
3076 | 611 st->codec->extradata = av_mallocz(atom.size + FF_INPUT_BUFFER_PADDING_SIZE); |
612 if (!st->codec->extradata) | |
613 return AVERROR(ENOMEM); | |
1845 | 614 st->codec->extradata_size = atom.size; |
3076 | 615 get_buffer(pb, st->codec->extradata, atom.size); |
1845 | 616 } else if (atom.size > 8) { /* to read frma, esds atoms */ |
2806
1ce39cda4a59
check mov_read_default return value where appropriate, patch by takis, fix issue 285
bcoudurier
parents:
2794
diff
changeset
|
617 if (mov_read_default(c, pb, atom) < 0) |
1ce39cda4a59
check mov_read_default return value where appropriate, patch by takis, fix issue 285
bcoudurier
parents:
2794
diff
changeset
|
618 return -1; |
1845 | 619 } else |
620 url_fskip(pb, atom.size); | |
621 return 0; | |
622 } | |
623 | |
2837
1caef0e2fb46
supports glbl atom containing generic extradata for all codecs
bcoudurier
parents:
2826
diff
changeset
|
624 /** |
1caef0e2fb46
supports glbl atom containing generic extradata for all codecs
bcoudurier
parents:
2826
diff
changeset
|
625 * This function reads atom content and puts data in extradata without tag |
1caef0e2fb46
supports glbl atom containing generic extradata for all codecs
bcoudurier
parents:
2826
diff
changeset
|
626 * nor size unlike mov_read_extradata. |
1caef0e2fb46
supports glbl atom containing generic extradata for all codecs
bcoudurier
parents:
2826
diff
changeset
|
627 */ |
1caef0e2fb46
supports glbl atom containing generic extradata for all codecs
bcoudurier
parents:
2826
diff
changeset
|
628 static int mov_read_glbl(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom) |
1845 | 629 { |
630 AVStream *st = c->fc->streams[c->fc->nb_streams-1]; | |
631 | |
632 if((uint64_t)atom.size > (1<<30)) | |
633 return -1; | |
634 | |
635 av_free(st->codec->extradata); | |
3076 | 636 st->codec->extradata = av_mallocz(atom.size + FF_INPUT_BUFFER_PADDING_SIZE); |
637 if (!st->codec->extradata) | |
638 return AVERROR(ENOMEM); | |
1845 | 639 st->codec->extradata_size = atom.size; |
3076 | 640 get_buffer(pb, st->codec->extradata, atom.size); |
1845 | 641 return 0; |
642 } | |
643 | |
644 static int mov_read_stco(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom) | |
645 { | |
646 AVStream *st = c->fc->streams[c->fc->nb_streams-1]; | |
2006 | 647 MOVStreamContext *sc = st->priv_data; |
1845 | 648 unsigned int i, entries; |
649 | |
650 get_byte(pb); /* version */ | |
3145 | 651 get_be24(pb); /* flags */ |
1845 | 652 |
653 entries = get_be32(pb); | |
654 | |
655 if(entries >= UINT_MAX/sizeof(int64_t)) | |
656 return -1; | |
657 | |
658 sc->chunk_count = entries; | |
659 sc->chunk_offsets = av_malloc(entries * sizeof(int64_t)); | |
660 if (!sc->chunk_offsets) | |
661 return -1; | |
3254 | 662 if (atom.type == MKTAG('s','t','c','o')) |
663 for(i=0; i<entries; i++) | |
1845 | 664 sc->chunk_offsets[i] = get_be32(pb); |
3254 | 665 else if (atom.type == MKTAG('c','o','6','4')) |
666 for(i=0; i<entries; i++) | |
1845 | 667 sc->chunk_offsets[i] = get_be64(pb); |
3254 | 668 else |
1845 | 669 return -1; |
670 | |
671 return 0; | |
672 } | |
673 | |
3625 | 674 /** |
675 * Compute codec id for 'lpcm' tag. | |
676 * See CoreAudioTypes and AudioStreamBasicDescription at Apple. | |
677 */ | |
678 static int mov_get_lpcm_codec_id(int bps, int flags) | |
679 { | |
680 if (flags & 1) { // floating point | |
681 if (flags & 2) { // big endian | |
682 if (bps == 32) return CODEC_ID_PCM_F32BE; | |
3751 | 683 else if (bps == 64) return CODEC_ID_PCM_F64BE; |
3625 | 684 } else { |
3751 | 685 if (bps == 32) return CODEC_ID_PCM_F32LE; |
686 else if (bps == 64) return CODEC_ID_PCM_F64LE; | |
3625 | 687 } |
688 } else { | |
689 if (flags & 2) { | |
690 if (bps == 8) | |
691 // signed integer | |
692 if (flags & 4) return CODEC_ID_PCM_S8; | |
693 else return CODEC_ID_PCM_U8; | |
694 else if (bps == 16) return CODEC_ID_PCM_S16BE; | |
695 else if (bps == 24) return CODEC_ID_PCM_S24BE; | |
696 else if (bps == 32) return CODEC_ID_PCM_S32BE; | |
697 } else { | |
698 if (bps == 8) | |
699 if (flags & 4) return CODEC_ID_PCM_S8; | |
700 else return CODEC_ID_PCM_U8; | |
3626 | 701 else if (bps == 16) return CODEC_ID_PCM_S16LE; |
3625 | 702 else if (bps == 24) return CODEC_ID_PCM_S24LE; |
703 else if (bps == 32) return CODEC_ID_PCM_S32LE; | |
704 } | |
705 } | |
706 return 0; | |
707 } | |
708 | |
1845 | 709 static int mov_read_stsd(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom) |
710 { | |
711 AVStream *st = c->fc->streams[c->fc->nb_streams-1]; | |
2006 | 712 MOVStreamContext *sc = st->priv_data; |
3263 | 713 int j, entries, pseudo_stream_id; |
1845 | 714 |
715 get_byte(pb); /* version */ | |
3145 | 716 get_be24(pb); /* flags */ |
1845 | 717 |
718 entries = get_be32(pb); | |
719 | |
3167 | 720 for(pseudo_stream_id=0; pseudo_stream_id<entries; pseudo_stream_id++) { |
721 //Parsing Sample description table | |
1845 | 722 enum CodecID id; |
3085
bae59276377f
support mov reference files, ref.mov/ref.m2v/ref.wav and detect BrianCox.mov
bcoudurier
parents:
3084
diff
changeset
|
723 int dref_id; |
1845 | 724 MOV_atom_t a = { 0, 0, 0 }; |
725 offset_t start_pos = url_ftell(pb); | |
726 int size = get_be32(pb); /* size */ | |
3263 | 727 uint32_t format = get_le32(pb); /* data format */ |
1845 | 728 |
729 get_be32(pb); /* reserved */ | |
730 get_be16(pb); /* reserved */ | |
3085
bae59276377f
support mov reference files, ref.mov/ref.m2v/ref.wav and detect BrianCox.mov
bcoudurier
parents:
3084
diff
changeset
|
731 dref_id = get_be16(pb); |
1845 | 732 |
3022
800db1ceafc6
Allow the user to select which codec out of several in stsd he wants.
michael
parents:
2974
diff
changeset
|
733 if (st->codec->codec_tag && |
3299
80a497804aa8
demux all stsd ids if codec is the same, fix premature_mov_ending.mov, closes #451
bcoudurier
parents:
3286
diff
changeset
|
734 st->codec->codec_tag != format && |
3022
800db1ceafc6
Allow the user to select which codec out of several in stsd he wants.
michael
parents:
2974
diff
changeset
|
735 (c->fc->video_codec_id ? codec_get_id(codec_movvideo_tags, format) != c->fc->video_codec_id |
3253 | 736 : st->codec->codec_tag != MKTAG('j','p','e','g')) |
3022
800db1ceafc6
Allow the user to select which codec out of several in stsd he wants.
michael
parents:
2974
diff
changeset
|
737 ){ |
3135 | 738 /* Multiple fourcc, we skip JPEG. This is not correct, we should |
739 * export it as a separate AVStream but this needs a few changes | |
740 * in the MOV demuxer, patch welcome. */ | |
3300 | 741 av_log(c->fc, AV_LOG_WARNING, "multiple fourcc not supported\n"); |
1845 | 742 url_fskip(pb, size - (url_ftell(pb) - start_pos)); |
743 continue; | |
744 } | |
3299
80a497804aa8
demux all stsd ids if codec is the same, fix premature_mov_ending.mov, closes #451
bcoudurier
parents:
3286
diff
changeset
|
745 sc->pseudo_stream_id = st->codec->codec_tag ? -1 : pseudo_stream_id; |
3085
bae59276377f
support mov reference files, ref.mov/ref.m2v/ref.wav and detect BrianCox.mov
bcoudurier
parents:
3084
diff
changeset
|
746 sc->dref_id= dref_id; |
1845 | 747 |
748 st->codec->codec_tag = format; | |
1847
922180a45610
recommit of the change below after reverting earlier cosmetic-functional mix
michael
parents:
1846
diff
changeset
|
749 id = codec_get_id(codec_movaudio_tags, format); |
3253 | 750 if (id<=0 && (format&0xFFFF) == 'm'+('s'<<8)) |
2298 | 751 id = codec_get_id(codec_wav_tags, bswap_32(format)&0xFFFF); |
752 | |
1845 | 753 if (st->codec->codec_type != CODEC_TYPE_VIDEO && id > 0) { |
754 st->codec->codec_type = CODEC_TYPE_AUDIO; | |
755 } else if (st->codec->codec_type != CODEC_TYPE_AUDIO && /* do not overwrite codec type */ | |
3253 | 756 format && format != MKTAG('m','p','4','s')) { /* skip old asf mpeg4 tag */ |
1847
922180a45610
recommit of the change below after reverting earlier cosmetic-functional mix
michael
parents:
1846
diff
changeset
|
757 id = codec_get_id(codec_movvideo_tags, format); |
1845 | 758 if (id <= 0) |
759 id = codec_get_id(codec_bmp_tags, format); | |
760 if (id > 0) | |
761 st->codec->codec_type = CODEC_TYPE_VIDEO; | |
2969 | 762 else if(st->codec->codec_type == CODEC_TYPE_DATA){ |
763 id = codec_get_id(ff_codec_movsubtitle_tags, format); | |
764 if(id > 0) | |
765 st->codec->codec_type = CODEC_TYPE_SUBTITLE; | |
766 } | |
1845 | 767 } |
768 | |
2902 | 769 dprintf(c->fc, "size=%d 4CC= %c%c%c%c codec_type=%d\n", size, |
770 (format >> 0) & 0xff, (format >> 8) & 0xff, (format >> 16) & 0xff, | |
771 (format >> 24) & 0xff, st->codec->codec_type); | |
1845 | 772 |
773 if(st->codec->codec_type==CODEC_TYPE_VIDEO) { | |
3263 | 774 uint8_t codec_name[32]; |
775 unsigned int color_depth; | |
776 int color_greyscale; | |
777 | |
1845 | 778 st->codec->codec_id = id; |
779 get_be16(pb); /* version */ | |
780 get_be16(pb); /* revision level */ | |
781 get_be32(pb); /* vendor */ | |
782 get_be32(pb); /* temporal quality */ | |
2730 | 783 get_be32(pb); /* spatial quality */ |
1845 | 784 |
785 st->codec->width = get_be16(pb); /* width */ | |
786 st->codec->height = get_be16(pb); /* height */ | |
787 | |
788 get_be32(pb); /* horiz resolution */ | |
789 get_be32(pb); /* vert resolution */ | |
790 get_be32(pb); /* data size, always 0 */ | |
3264 | 791 get_be16(pb); /* frames per samples */ |
2044 | 792 |
3265 | 793 get_buffer(pb, codec_name, 32); /* codec name, pascal string */ |
1845 | 794 if (codec_name[0] <= 31) { |
795 memcpy(st->codec->codec_name, &codec_name[1],codec_name[0]); | |
796 st->codec->codec_name[codec_name[0]] = 0; | |
797 } | |
798 | |
799 st->codec->bits_per_sample = get_be16(pb); /* depth */ | |
800 st->codec->color_table_id = get_be16(pb); /* colortable id */ | |
3095
da04b574d131
set codec bps to grayscale bits, fix 256grey.mov
bcoudurier
parents:
3093
diff
changeset
|
801 dprintf(c->fc, "depth %d, ctab id %d\n", |
da04b574d131
set codec bps to grayscale bits, fix 256grey.mov
bcoudurier
parents:
3093
diff
changeset
|
802 st->codec->bits_per_sample, st->codec->color_table_id); |
1845 | 803 /* figure out the palette situation */ |
804 color_depth = st->codec->bits_per_sample & 0x1F; | |
805 color_greyscale = st->codec->bits_per_sample & 0x20; | |
806 | |
807 /* if the depth is 2, 4, or 8 bpp, file is palettized */ | |
808 if ((color_depth == 2) || (color_depth == 4) || | |
809 (color_depth == 8)) { | |
3257 | 810 /* for palette traversal */ |
811 unsigned int color_start, color_count, color_end; | |
812 unsigned char r, g, b; | |
813 | |
1845 | 814 if (color_greyscale) { |
3257 | 815 int color_index, color_dec; |
1845 | 816 /* compute the greyscale palette */ |
3095
da04b574d131
set codec bps to grayscale bits, fix 256grey.mov
bcoudurier
parents:
3093
diff
changeset
|
817 st->codec->bits_per_sample = color_depth; |
1845 | 818 color_count = 1 << color_depth; |
819 color_index = 255; | |
820 color_dec = 256 / (color_count - 1); | |
821 for (j = 0; j < color_count; j++) { | |
822 r = g = b = color_index; | |
823 c->palette_control.palette[j] = | |
824 (r << 16) | (g << 8) | (b); | |
825 color_index -= color_dec; | |
826 if (color_index < 0) | |
827 color_index = 0; | |
828 } | |
3179
5f56b694f9bf
according to specs, only color table id set to 0, have it in stsd, fix 4colors.mov
bcoudurier
parents:
3178
diff
changeset
|
829 } else if (st->codec->color_table_id) { |
3257 | 830 const uint8_t *color_table; |
1845 | 831 /* if flag bit 3 is set, use the default palette */ |
832 color_count = 1 << color_depth; | |
833 if (color_depth == 2) | |
834 color_table = ff_qt_default_palette_4; | |
835 else if (color_depth == 4) | |
836 color_table = ff_qt_default_palette_16; | |
837 else | |
838 color_table = ff_qt_default_palette_256; | |
839 | |
840 for (j = 0; j < color_count; j++) { | |
841 r = color_table[j * 4 + 0]; | |
842 g = color_table[j * 4 + 1]; | |
843 b = color_table[j * 4 + 2]; | |
844 c->palette_control.palette[j] = | |
845 (r << 16) | (g << 8) | (b); | |
846 } | |
847 } else { | |
848 /* load the palette from the file */ | |
849 color_start = get_be32(pb); | |
850 color_count = get_be16(pb); | |
851 color_end = get_be16(pb); | |
2809
17086a526938
Check sanity in the palette loading operation. The addresses a potential security risk in
melanson
parents:
2807
diff
changeset
|
852 if ((color_start <= 255) && |
17086a526938
Check sanity in the palette loading operation. The addresses a potential security risk in
melanson
parents:
2807
diff
changeset
|
853 (color_end <= 255)) { |
2810 | 854 for (j = color_start; j <= color_end; j++) { |
855 /* each R, G, or B component is 16 bits; | |
856 * only use the top 8 bits; skip alpha bytes | |
857 * up front */ | |
858 get_byte(pb); | |
859 get_byte(pb); | |
860 r = get_byte(pb); | |
861 get_byte(pb); | |
862 g = get_byte(pb); | |
863 get_byte(pb); | |
864 b = get_byte(pb); | |
865 get_byte(pb); | |
866 c->palette_control.palette[j] = | |
867 (r << 16) | (g << 8) | (b); | |
2809
17086a526938
Check sanity in the palette loading operation. The addresses a potential security risk in
melanson
parents:
2807
diff
changeset
|
868 } |
1845 | 869 } |
870 } | |
871 st->codec->palctrl = &c->palette_control; | |
872 st->codec->palctrl->palette_changed = 1; | |
873 } else | |
874 st->codec->palctrl = NULL; | |
875 } else if(st->codec->codec_type==CODEC_TYPE_AUDIO) { | |
3622 | 876 int bits_per_sample, flags; |
1845 | 877 uint16_t version = get_be16(pb); |
878 | |
879 st->codec->codec_id = id; | |
880 get_be16(pb); /* revision level */ | |
881 get_be32(pb); /* vendor */ | |
882 | |
883 st->codec->channels = get_be16(pb); /* channel count */ | |
1907 | 884 dprintf(c->fc, "audio channels %d\n", st->codec->channels); |
1845 | 885 st->codec->bits_per_sample = get_be16(pb); /* sample size */ |
886 | |
3029
10abe8748ec2
use correct demux mechanism when audio compression id is -2, dv audio does not matter, demux partially qt_dv_pal_test.mov which does NOT use cid -2
bcoudurier
parents:
3027
diff
changeset
|
887 sc->audio_cid = get_be16(pb); |
1845 | 888 get_be16(pb); /* packet size = 0 */ |
889 | |
890 st->codec->sample_rate = ((get_be32(pb) >> 16)); | |
891 | |
3619
bd4b7c8fec83
move version specific parsing code before codec specific code, will be needed
bcoudurier
parents:
3615
diff
changeset
|
892 //Read QT version 1 fields. In version 0 these do not exist. |
bd4b7c8fec83
move version specific parsing code before codec specific code, will be needed
bcoudurier
parents:
3615
diff
changeset
|
893 dprintf(c->fc, "version =%d, isom =%d\n",version,c->isom); |
bd4b7c8fec83
move version specific parsing code before codec specific code, will be needed
bcoudurier
parents:
3615
diff
changeset
|
894 if(!c->isom) { |
bd4b7c8fec83
move version specific parsing code before codec specific code, will be needed
bcoudurier
parents:
3615
diff
changeset
|
895 if(version==1) { |
bd4b7c8fec83
move version specific parsing code before codec specific code, will be needed
bcoudurier
parents:
3615
diff
changeset
|
896 sc->samples_per_frame = get_be32(pb); |
bd4b7c8fec83
move version specific parsing code before codec specific code, will be needed
bcoudurier
parents:
3615
diff
changeset
|
897 get_be32(pb); /* bytes per packet */ |
bd4b7c8fec83
move version specific parsing code before codec specific code, will be needed
bcoudurier
parents:
3615
diff
changeset
|
898 sc->bytes_per_frame = get_be32(pb); |
bd4b7c8fec83
move version specific parsing code before codec specific code, will be needed
bcoudurier
parents:
3615
diff
changeset
|
899 get_be32(pb); /* bytes per sample */ |
bd4b7c8fec83
move version specific parsing code before codec specific code, will be needed
bcoudurier
parents:
3615
diff
changeset
|
900 } else if(version==2) { |
bd4b7c8fec83
move version specific parsing code before codec specific code, will be needed
bcoudurier
parents:
3615
diff
changeset
|
901 get_be32(pb); /* sizeof struct only */ |
bd4b7c8fec83
move version specific parsing code before codec specific code, will be needed
bcoudurier
parents:
3615
diff
changeset
|
902 st->codec->sample_rate = av_int2dbl(get_be64(pb)); /* float 64 */ |
bd4b7c8fec83
move version specific parsing code before codec specific code, will be needed
bcoudurier
parents:
3615
diff
changeset
|
903 st->codec->channels = get_be32(pb); |
bd4b7c8fec83
move version specific parsing code before codec specific code, will be needed
bcoudurier
parents:
3615
diff
changeset
|
904 get_be32(pb); /* always 0x7F000000 */ |
3620 | 905 st->codec->bits_per_sample = get_be32(pb); /* bits per channel if sound is uncompressed */ |
3622 | 906 flags = get_be32(pb); /* lcpm format specific flag */ |
3620 | 907 sc->bytes_per_frame = get_be32(pb); /* bytes per audio packet if constant */ |
908 sc->samples_per_frame = get_be32(pb); /* lpcm frames per audio packet if constant */ | |
3625 | 909 if (format == MKTAG('l','p','c','m')) |
910 st->codec->codec_id = mov_get_lpcm_codec_id(st->codec->bits_per_sample, flags); | |
3619
bd4b7c8fec83
move version specific parsing code before codec specific code, will be needed
bcoudurier
parents:
3615
diff
changeset
|
911 } |
bd4b7c8fec83
move version specific parsing code before codec specific code, will be needed
bcoudurier
parents:
3615
diff
changeset
|
912 } |
bd4b7c8fec83
move version specific parsing code before codec specific code, will be needed
bcoudurier
parents:
3615
diff
changeset
|
913 |
1845 | 914 switch (st->codec->codec_id) { |
915 case CODEC_ID_PCM_S8: | |
916 case CODEC_ID_PCM_U8: | |
917 if (st->codec->bits_per_sample == 16) | |
918 st->codec->codec_id = CODEC_ID_PCM_S16BE; | |
919 break; | |
920 case CODEC_ID_PCM_S16LE: | |
921 case CODEC_ID_PCM_S16BE: | |
922 if (st->codec->bits_per_sample == 8) | |
923 st->codec->codec_id = CODEC_ID_PCM_S8; | |
924 else if (st->codec->bits_per_sample == 24) | |
3621
0415fc41780a
keep original codec/fourcc endianness, fix XDCAMHD.mov
bcoudurier
parents:
3620
diff
changeset
|
925 st->codec->codec_id = |
0415fc41780a
keep original codec/fourcc endianness, fix XDCAMHD.mov
bcoudurier
parents:
3620
diff
changeset
|
926 st->codec->codec_id == CODEC_ID_PCM_S16BE ? |
0415fc41780a
keep original codec/fourcc endianness, fix XDCAMHD.mov
bcoudurier
parents:
3620
diff
changeset
|
927 CODEC_ID_PCM_S24BE : CODEC_ID_PCM_S24LE; |
1845 | 928 break; |
3036
62181fbfc128
remove messy and not always correct chunk size workaround, use correct values instead
bcoudurier
parents:
3034
diff
changeset
|
929 /* set values for old format before stsd version 1 appeared */ |
62181fbfc128
remove messy and not always correct chunk size workaround, use correct values instead
bcoudurier
parents:
3034
diff
changeset
|
930 case CODEC_ID_MACE3: |
62181fbfc128
remove messy and not always correct chunk size workaround, use correct values instead
bcoudurier
parents:
3034
diff
changeset
|
931 sc->samples_per_frame = 6; |
62181fbfc128
remove messy and not always correct chunk size workaround, use correct values instead
bcoudurier
parents:
3034
diff
changeset
|
932 sc->bytes_per_frame = 2*st->codec->channels; |
62181fbfc128
remove messy and not always correct chunk size workaround, use correct values instead
bcoudurier
parents:
3034
diff
changeset
|
933 break; |
62181fbfc128
remove messy and not always correct chunk size workaround, use correct values instead
bcoudurier
parents:
3034
diff
changeset
|
934 case CODEC_ID_MACE6: |
62181fbfc128
remove messy and not always correct chunk size workaround, use correct values instead
bcoudurier
parents:
3034
diff
changeset
|
935 sc->samples_per_frame = 6; |
62181fbfc128
remove messy and not always correct chunk size workaround, use correct values instead
bcoudurier
parents:
3034
diff
changeset
|
936 sc->bytes_per_frame = 1*st->codec->channels; |
62181fbfc128
remove messy and not always correct chunk size workaround, use correct values instead
bcoudurier
parents:
3034
diff
changeset
|
937 break; |
62181fbfc128
remove messy and not always correct chunk size workaround, use correct values instead
bcoudurier
parents:
3034
diff
changeset
|
938 case CODEC_ID_ADPCM_IMA_QT: |
62181fbfc128
remove messy and not always correct chunk size workaround, use correct values instead
bcoudurier
parents:
3034
diff
changeset
|
939 sc->samples_per_frame = 64; |
62181fbfc128
remove messy and not always correct chunk size workaround, use correct values instead
bcoudurier
parents:
3034
diff
changeset
|
940 sc->bytes_per_frame = 34*st->codec->channels; |
62181fbfc128
remove messy and not always correct chunk size workaround, use correct values instead
bcoudurier
parents:
3034
diff
changeset
|
941 break; |
3252
f4fcd39c5d7f
set gsm default frame size and bytes per frame, needed by old qt format, fix sample-gsm-8000.mov
bcoudurier
parents:
3245
diff
changeset
|
942 case CODEC_ID_GSM: |
f4fcd39c5d7f
set gsm default frame size and bytes per frame, needed by old qt format, fix sample-gsm-8000.mov
bcoudurier
parents:
3245
diff
changeset
|
943 sc->samples_per_frame = 160; |
f4fcd39c5d7f
set gsm default frame size and bytes per frame, needed by old qt format, fix sample-gsm-8000.mov
bcoudurier
parents:
3245
diff
changeset
|
944 sc->bytes_per_frame = 33; |
f4fcd39c5d7f
set gsm default frame size and bytes per frame, needed by old qt format, fix sample-gsm-8000.mov
bcoudurier
parents:
3245
diff
changeset
|
945 break; |
1845 | 946 default: |
947 break; | |
948 } | |
949 | |
950 bits_per_sample = av_get_bits_per_sample(st->codec->codec_id); | |
951 if (bits_per_sample) { | |
952 st->codec->bits_per_sample = bits_per_sample; | |
953 sc->sample_size = (bits_per_sample >> 3) * st->codec->channels; | |
954 } | |
2972
bc330130bdce
Set subtitle codec id correctly, i hope this does not break anything.
michael
parents:
2970
diff
changeset
|
955 } else if(st->codec->codec_type==CODEC_TYPE_SUBTITLE){ |
bc330130bdce
Set subtitle codec id correctly, i hope this does not break anything.
michael
parents:
2970
diff
changeset
|
956 st->codec->codec_id= id; |
1845 | 957 } else { |
958 /* other codec type, just skip (rtp, mp4s, tmcd ...) */ | |
959 url_fskip(pb, size - (url_ftell(pb) - start_pos)); | |
960 } | |
961 /* this will read extra atoms at the end (wave, alac, damr, avcC, SMI ...) */ | |
962 a.size = size - (url_ftell(pb) - start_pos); | |
2806
1ce39cda4a59
check mov_read_default return value where appropriate, patch by takis, fix issue 285
bcoudurier
parents:
2794
diff
changeset
|
963 if (a.size > 8) { |
1ce39cda4a59
check mov_read_default return value where appropriate, patch by takis, fix issue 285
bcoudurier
parents:
2794
diff
changeset
|
964 if (mov_read_default(c, pb, a) < 0) |
1ce39cda4a59
check mov_read_default return value where appropriate, patch by takis, fix issue 285
bcoudurier
parents:
2794
diff
changeset
|
965 return -1; |
1ce39cda4a59
check mov_read_default return value where appropriate, patch by takis, fix issue 285
bcoudurier
parents:
2794
diff
changeset
|
966 } else if (a.size > 0) |
1845 | 967 url_fskip(pb, a.size); |
968 } | |
969 | |
3084 | 970 if(st->codec->codec_type==CODEC_TYPE_AUDIO && st->codec->sample_rate==0 && sc->time_scale>1) |
1845 | 971 st->codec->sample_rate= sc->time_scale; |
972 | |
973 /* special codec parameters handling */ | |
974 switch (st->codec->codec_id) { | |
975 #ifdef CONFIG_DV_DEMUXER | |
976 case CODEC_ID_DVAUDIO: | |
977 c->dv_fctx = av_alloc_format_context(); | |
978 c->dv_demux = dv_init_demux(c->dv_fctx); | |
979 if (!c->dv_demux) { | |
980 av_log(c->fc, AV_LOG_ERROR, "dv demux context init error\n"); | |
981 return -1; | |
982 } | |
983 sc->dv_audio_container = 1; | |
984 st->codec->codec_id = CODEC_ID_PCM_S16LE; | |
985 break; | |
986 #endif | |
987 /* no ifdef since parameters are always those */ | |
988 case CODEC_ID_AMR_WB: | |
989 st->codec->sample_rate= 16000; | |
990 st->codec->channels= 1; /* really needed */ | |
991 break; | |
3245
9f25267bee44
demux qcelp, so this can work with soc decoder and stream copy
bcoudurier
parents:
3242
diff
changeset
|
992 case CODEC_ID_QCELP: |
3256
b09eff5b0e89
parser should not be needed anymore, merge cases and set frame size for amr too
bcoudurier
parents:
3255
diff
changeset
|
993 case CODEC_ID_AMR_NB: |
3258 | 994 st->codec->frame_size= sc->samples_per_frame; |
1845 | 995 st->codec->sample_rate= 8000; |
996 st->codec->channels= 1; /* really needed */ | |
997 break; | |
998 case CODEC_ID_MP2: | |
1953
edfd6b33d1f6
activate parser on MP3 id, fix [A-Destiny]_Konjiki_no_Gash_Bell_-_65_[71EE362C].mp4
bcoudurier
parents:
1950
diff
changeset
|
999 case CODEC_ID_MP3: |
1845 | 1000 st->codec->codec_type = CODEC_TYPE_AUDIO; /* force type after stsd for m1a hdlr */ |
2023 | 1001 st->need_parsing = AVSTREAM_PARSE_FULL; |
1845 | 1002 break; |
3187 | 1003 case CODEC_ID_GSM: |
2299
fe59c768ecf7
set block align to stsd audio v2 bytes per frame for adpcm ms and ima wav, fix surge-2-16-L-ms11.mov and surge-2-16-L-ms02.mov
bcoudurier
parents:
2298
diff
changeset
|
1004 case CODEC_ID_ADPCM_MS: |
fe59c768ecf7
set block align to stsd audio v2 bytes per frame for adpcm ms and ima wav, fix surge-2-16-L-ms11.mov and surge-2-16-L-ms02.mov
bcoudurier
parents:
2298
diff
changeset
|
1005 case CODEC_ID_ADPCM_IMA_WAV: |
fe59c768ecf7
set block align to stsd audio v2 bytes per frame for adpcm ms and ima wav, fix surge-2-16-L-ms11.mov and surge-2-16-L-ms02.mov
bcoudurier
parents:
2298
diff
changeset
|
1006 st->codec->block_align = sc->bytes_per_frame; |
fe59c768ecf7
set block align to stsd audio v2 bytes per frame for adpcm ms and ima wav, fix surge-2-16-L-ms11.mov and surge-2-16-L-ms02.mov
bcoudurier
parents:
2298
diff
changeset
|
1007 break; |
3242 | 1008 case CODEC_ID_ALAC: |
1009 if (st->codec->extradata_size == 36) | |
1010 st->codec->frame_size = AV_RB32((st->codec->extradata+12)); | |
1011 break; | |
1845 | 1012 default: |
1013 break; | |
1014 } | |
1015 | |
1016 return 0; | |
1017 } | |
1018 | |
1019 static int mov_read_stsc(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom) | |
1020 { | |
1021 AVStream *st = c->fc->streams[c->fc->nb_streams-1]; | |
2006 | 1022 MOVStreamContext *sc = st->priv_data; |
1845 | 1023 unsigned int i, entries; |
1024 | |
1025 get_byte(pb); /* version */ | |
3145 | 1026 get_be24(pb); /* flags */ |
1845 | 1027 |
1028 entries = get_be32(pb); | |
1029 | |
2045
aa5e56700fdf
cosmectics, use consistant and homogeneous type names for atoms
bcoudurier
parents:
2044
diff
changeset
|
1030 if(entries >= UINT_MAX / sizeof(MOV_stsc_t)) |
1845 | 1031 return -1; |
1032 | |
2044 | 1033 dprintf(c->fc, "track[%i].stsc.entries = %i\n", c->fc->nb_streams-1, entries); |
1034 | |
1845 | 1035 sc->sample_to_chunk_sz = entries; |
2045
aa5e56700fdf
cosmectics, use consistant and homogeneous type names for atoms
bcoudurier
parents:
2044
diff
changeset
|
1036 sc->sample_to_chunk = av_malloc(entries * sizeof(MOV_stsc_t)); |
1845 | 1037 if (!sc->sample_to_chunk) |
1038 return -1; | |
1039 for(i=0; i<entries; i++) { | |
1040 sc->sample_to_chunk[i].first = get_be32(pb); | |
1041 sc->sample_to_chunk[i].count = get_be32(pb); | |
1042 sc->sample_to_chunk[i].id = get_be32(pb); | |
1043 } | |
1044 return 0; | |
1045 } | |
1046 | |
1047 static int mov_read_stss(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom) | |
1048 { | |
1049 AVStream *st = c->fc->streams[c->fc->nb_streams-1]; | |
2006 | 1050 MOVStreamContext *sc = st->priv_data; |
1845 | 1051 unsigned int i, entries; |
1052 | |
1053 get_byte(pb); /* version */ | |
3145 | 1054 get_be24(pb); /* flags */ |
1845 | 1055 |
1056 entries = get_be32(pb); | |
1057 | |
2030 | 1058 if(entries >= UINT_MAX / sizeof(int)) |
1845 | 1059 return -1; |
1060 | |
1061 sc->keyframe_count = entries; | |
2044 | 1062 |
1063 dprintf(c->fc, "keyframe_count = %d\n", sc->keyframe_count); | |
1064 | |
2030 | 1065 sc->keyframes = av_malloc(entries * sizeof(int)); |
1845 | 1066 if (!sc->keyframes) |
1067 return -1; | |
1068 for(i=0; i<entries; i++) { | |
1069 sc->keyframes[i] = get_be32(pb); | |
2044 | 1070 //dprintf(c->fc, "keyframes[]=%d\n", sc->keyframes[i]); |
1845 | 1071 } |
1072 return 0; | |
1073 } | |
1074 | |
1075 static int mov_read_stsz(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom) | |
1076 { | |
1077 AVStream *st = c->fc->streams[c->fc->nb_streams-1]; | |
2006 | 1078 MOVStreamContext *sc = st->priv_data; |
1845 | 1079 unsigned int i, entries, sample_size; |
1080 | |
1081 get_byte(pb); /* version */ | |
3145 | 1082 get_be24(pb); /* flags */ |
1845 | 1083 |
1084 sample_size = get_be32(pb); | |
1085 if (!sc->sample_size) /* do not overwrite value computed in stsd */ | |
1086 sc->sample_size = sample_size; | |
1087 entries = get_be32(pb); | |
2030 | 1088 if(entries >= UINT_MAX / sizeof(int)) |
1845 | 1089 return -1; |
1090 | |
1091 sc->sample_count = entries; | |
1092 if (sample_size) | |
1093 return 0; | |
1094 | |
2044 | 1095 dprintf(c->fc, "sample_size = %d sample_count = %d\n", sc->sample_size, sc->sample_count); |
1096 | |
2030 | 1097 sc->sample_sizes = av_malloc(entries * sizeof(int)); |
1845 | 1098 if (!sc->sample_sizes) |
1099 return -1; | |
3156
487b1979f195
remove useless debug print since now mov_build_index will do
bcoudurier
parents:
3155
diff
changeset
|
1100 for(i=0; i<entries; i++) |
1845 | 1101 sc->sample_sizes[i] = get_be32(pb); |
1102 return 0; | |
1103 } | |
1104 | |
1105 static int mov_read_stts(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom) | |
1106 { | |
1107 AVStream *st = c->fc->streams[c->fc->nb_streams-1]; | |
2006 | 1108 MOVStreamContext *sc = st->priv_data; |
1845 | 1109 unsigned int i, entries; |
1110 int64_t duration=0; | |
1111 int64_t total_sample_count=0; | |
1112 | |
1113 get_byte(pb); /* version */ | |
3145 | 1114 get_be24(pb); /* flags */ |
1845 | 1115 entries = get_be32(pb); |
2045
aa5e56700fdf
cosmectics, use consistant and homogeneous type names for atoms
bcoudurier
parents:
2044
diff
changeset
|
1116 if(entries >= UINT_MAX / sizeof(MOV_stts_t)) |
1845 | 1117 return -1; |
1118 | |
1119 sc->stts_count = entries; | |
2045
aa5e56700fdf
cosmectics, use consistant and homogeneous type names for atoms
bcoudurier
parents:
2044
diff
changeset
|
1120 sc->stts_data = av_malloc(entries * sizeof(MOV_stts_t)); |
2807
5bf4b9df2794
return error if malloc failed, found by takis, fix issue 286
bcoudurier
parents:
2806
diff
changeset
|
1121 if (!sc->stts_data) |
5bf4b9df2794
return error if malloc failed, found by takis, fix issue 286
bcoudurier
parents:
2806
diff
changeset
|
1122 return -1; |
2044 | 1123 dprintf(c->fc, "track[%i].stts.entries = %i\n", c->fc->nb_streams-1, entries); |
1845 | 1124 |
1125 sc->time_rate=0; | |
1126 | |
1127 for(i=0; i<entries; i++) { | |
1128 int sample_duration; | |
1129 int sample_count; | |
1130 | |
1131 sample_count=get_be32(pb); | |
1132 sample_duration = get_be32(pb); | |
1133 sc->stts_data[i].count= sample_count; | |
1134 sc->stts_data[i].duration= sample_duration; | |
1135 | |
1136 sc->time_rate= ff_gcd(sc->time_rate, sample_duration); | |
1137 | |
1907 | 1138 dprintf(c->fc, "sample_count=%d, sample_duration=%d\n",sample_count,sample_duration); |
1845 | 1139 |
1140 duration+=(int64_t)sample_duration*sample_count; | |
1141 total_sample_count+=sample_count; | |
1142 } | |
1143 | |
1144 st->nb_frames= total_sample_count; | |
1145 if(duration) | |
1146 st->duration= duration; | |
1147 return 0; | |
1148 } | |
1149 | |
1150 static int mov_read_ctts(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom) | |
1151 { | |
1152 AVStream *st = c->fc->streams[c->fc->nb_streams-1]; | |
2006 | 1153 MOVStreamContext *sc = st->priv_data; |
1845 | 1154 unsigned int i, entries; |
1155 | |
1156 get_byte(pb); /* version */ | |
3145 | 1157 get_be24(pb); /* flags */ |
1845 | 1158 entries = get_be32(pb); |
2045
aa5e56700fdf
cosmectics, use consistant and homogeneous type names for atoms
bcoudurier
parents:
2044
diff
changeset
|
1159 if(entries >= UINT_MAX / sizeof(MOV_stts_t)) |
1845 | 1160 return -1; |
1161 | |
1162 sc->ctts_count = entries; | |
2045
aa5e56700fdf
cosmectics, use consistant and homogeneous type names for atoms
bcoudurier
parents:
2044
diff
changeset
|
1163 sc->ctts_data = av_malloc(entries * sizeof(MOV_stts_t)); |
2807
5bf4b9df2794
return error if malloc failed, found by takis, fix issue 286
bcoudurier
parents:
2806
diff
changeset
|
1164 if (!sc->ctts_data) |
5bf4b9df2794
return error if malloc failed, found by takis, fix issue 286
bcoudurier
parents:
2806
diff
changeset
|
1165 return -1; |
1907 | 1166 dprintf(c->fc, "track[%i].ctts.entries = %i\n", c->fc->nb_streams-1, entries); |
1845 | 1167 |
1168 for(i=0; i<entries; i++) { | |
1169 int count =get_be32(pb); | |
1170 int duration =get_be32(pb); | |
1171 | |
1172 if (duration < 0) { | |
3615
f3db1276dc02
downgrade mov negative ctts log message to warning, patch by Art Clarke, aclarke at vlideshow dot com
bcoudurier
parents:
3595
diff
changeset
|
1173 av_log(c->fc, AV_LOG_WARNING, "negative ctts, ignoring\n"); |
1845 | 1174 sc->ctts_count = 0; |
1175 url_fskip(pb, 8 * (entries - i - 1)); | |
1176 break; | |
1177 } | |
1178 sc->ctts_data[i].count = count; | |
1179 sc->ctts_data[i].duration= duration; | |
1180 | |
1181 sc->time_rate= ff_gcd(sc->time_rate, duration); | |
1182 } | |
1183 return 0; | |
1184 } | |
1185 | |
3154
01f6f3c905db
move mov_build_index before mov_read_trak to avoid useless declaration
bcoudurier
parents:
3153
diff
changeset
|
1186 static void mov_build_index(MOVContext *mov, AVStream *st) |
01f6f3c905db
move mov_build_index before mov_read_trak to avoid useless declaration
bcoudurier
parents:
3153
diff
changeset
|
1187 { |
01f6f3c905db
move mov_build_index before mov_read_trak to avoid useless declaration
bcoudurier
parents:
3153
diff
changeset
|
1188 MOVStreamContext *sc = st->priv_data; |
01f6f3c905db
move mov_build_index before mov_read_trak to avoid useless declaration
bcoudurier
parents:
3153
diff
changeset
|
1189 offset_t current_offset; |
01f6f3c905db
move mov_build_index before mov_read_trak to avoid useless declaration
bcoudurier
parents:
3153
diff
changeset
|
1190 int64_t current_dts = 0; |
01f6f3c905db
move mov_build_index before mov_read_trak to avoid useless declaration
bcoudurier
parents:
3153
diff
changeset
|
1191 unsigned int stts_index = 0; |
01f6f3c905db
move mov_build_index before mov_read_trak to avoid useless declaration
bcoudurier
parents:
3153
diff
changeset
|
1192 unsigned int stsc_index = 0; |
01f6f3c905db
move mov_build_index before mov_read_trak to avoid useless declaration
bcoudurier
parents:
3153
diff
changeset
|
1193 unsigned int stss_index = 0; |
01f6f3c905db
move mov_build_index before mov_read_trak to avoid useless declaration
bcoudurier
parents:
3153
diff
changeset
|
1194 unsigned int i, j; |
01f6f3c905db
move mov_build_index before mov_read_trak to avoid useless declaration
bcoudurier
parents:
3153
diff
changeset
|
1195 |
3178
73b7ef886091
Only use chunk demuxing for old uncompressed audio mechanism specified by stts.
bcoudurier
parents:
3175
diff
changeset
|
1196 /* only use old uncompressed audio chunk demuxing when stts specifies it */ |
73b7ef886091
Only use chunk demuxing for old uncompressed audio mechanism specified by stts.
bcoudurier
parents:
3175
diff
changeset
|
1197 if (!(st->codec->codec_type == CODEC_TYPE_AUDIO && |
73b7ef886091
Only use chunk demuxing for old uncompressed audio mechanism specified by stts.
bcoudurier
parents:
3175
diff
changeset
|
1198 sc->stts_count == 1 && sc->stts_data[0].duration == 1)) { |
3154
01f6f3c905db
move mov_build_index before mov_read_trak to avoid useless declaration
bcoudurier
parents:
3153
diff
changeset
|
1199 unsigned int current_sample = 0; |
01f6f3c905db
move mov_build_index before mov_read_trak to avoid useless declaration
bcoudurier
parents:
3153
diff
changeset
|
1200 unsigned int stts_sample = 0; |
01f6f3c905db
move mov_build_index before mov_read_trak to avoid useless declaration
bcoudurier
parents:
3153
diff
changeset
|
1201 unsigned int keyframe, sample_size; |
01f6f3c905db
move mov_build_index before mov_read_trak to avoid useless declaration
bcoudurier
parents:
3153
diff
changeset
|
1202 unsigned int distance = 0; |
01f6f3c905db
move mov_build_index before mov_read_trak to avoid useless declaration
bcoudurier
parents:
3153
diff
changeset
|
1203 int key_off = sc->keyframes && sc->keyframes[0] == 1; |
01f6f3c905db
move mov_build_index before mov_read_trak to avoid useless declaration
bcoudurier
parents:
3153
diff
changeset
|
1204 |
01f6f3c905db
move mov_build_index before mov_read_trak to avoid useless declaration
bcoudurier
parents:
3153
diff
changeset
|
1205 st->nb_frames = sc->sample_count; |
01f6f3c905db
move mov_build_index before mov_read_trak to avoid useless declaration
bcoudurier
parents:
3153
diff
changeset
|
1206 for (i = 0; i < sc->chunk_count; i++) { |
01f6f3c905db
move mov_build_index before mov_read_trak to avoid useless declaration
bcoudurier
parents:
3153
diff
changeset
|
1207 current_offset = sc->chunk_offsets[i]; |
01f6f3c905db
move mov_build_index before mov_read_trak to avoid useless declaration
bcoudurier
parents:
3153
diff
changeset
|
1208 if (stsc_index + 1 < sc->sample_to_chunk_sz && |
01f6f3c905db
move mov_build_index before mov_read_trak to avoid useless declaration
bcoudurier
parents:
3153
diff
changeset
|
1209 i + 1 == sc->sample_to_chunk[stsc_index + 1].first) |
01f6f3c905db
move mov_build_index before mov_read_trak to avoid useless declaration
bcoudurier
parents:
3153
diff
changeset
|
1210 stsc_index++; |
01f6f3c905db
move mov_build_index before mov_read_trak to avoid useless declaration
bcoudurier
parents:
3153
diff
changeset
|
1211 for (j = 0; j < sc->sample_to_chunk[stsc_index].count; j++) { |
01f6f3c905db
move mov_build_index before mov_read_trak to avoid useless declaration
bcoudurier
parents:
3153
diff
changeset
|
1212 if (current_sample >= sc->sample_count) { |
01f6f3c905db
move mov_build_index before mov_read_trak to avoid useless declaration
bcoudurier
parents:
3153
diff
changeset
|
1213 av_log(mov->fc, AV_LOG_ERROR, "wrong sample count\n"); |
01f6f3c905db
move mov_build_index before mov_read_trak to avoid useless declaration
bcoudurier
parents:
3153
diff
changeset
|
1214 goto out; |
01f6f3c905db
move mov_build_index before mov_read_trak to avoid useless declaration
bcoudurier
parents:
3153
diff
changeset
|
1215 } |
01f6f3c905db
move mov_build_index before mov_read_trak to avoid useless declaration
bcoudurier
parents:
3153
diff
changeset
|
1216 keyframe = !sc->keyframe_count || current_sample+key_off == sc->keyframes[stss_index]; |
01f6f3c905db
move mov_build_index before mov_read_trak to avoid useless declaration
bcoudurier
parents:
3153
diff
changeset
|
1217 if (keyframe) { |
01f6f3c905db
move mov_build_index before mov_read_trak to avoid useless declaration
bcoudurier
parents:
3153
diff
changeset
|
1218 distance = 0; |
01f6f3c905db
move mov_build_index before mov_read_trak to avoid useless declaration
bcoudurier
parents:
3153
diff
changeset
|
1219 if (stss_index + 1 < sc->keyframe_count) |
01f6f3c905db
move mov_build_index before mov_read_trak to avoid useless declaration
bcoudurier
parents:
3153
diff
changeset
|
1220 stss_index++; |
01f6f3c905db
move mov_build_index before mov_read_trak to avoid useless declaration
bcoudurier
parents:
3153
diff
changeset
|
1221 } |
01f6f3c905db
move mov_build_index before mov_read_trak to avoid useless declaration
bcoudurier
parents:
3153
diff
changeset
|
1222 sample_size = sc->sample_size > 0 ? sc->sample_size : sc->sample_sizes[current_sample]; |
3299
80a497804aa8
demux all stsd ids if codec is the same, fix premature_mov_ending.mov, closes #451
bcoudurier
parents:
3286
diff
changeset
|
1223 if(sc->pseudo_stream_id == -1 || |
3301
11b6da5ffe78
only print debug info when sample is actually added
bcoudurier
parents:
3300
diff
changeset
|
1224 sc->sample_to_chunk[stsc_index].id - 1 == sc->pseudo_stream_id) { |
3154
01f6f3c905db
move mov_build_index before mov_read_trak to avoid useless declaration
bcoudurier
parents:
3153
diff
changeset
|
1225 av_add_index_entry(st, current_offset, current_dts, sample_size, distance, |
01f6f3c905db
move mov_build_index before mov_read_trak to avoid useless declaration
bcoudurier
parents:
3153
diff
changeset
|
1226 keyframe ? AVINDEX_KEYFRAME : 0); |
3301
11b6da5ffe78
only print debug info when sample is actually added
bcoudurier
parents:
3300
diff
changeset
|
1227 dprintf(mov->fc, "AVIndex stream %d, sample %d, offset %"PRIx64", dts %"PRId64", " |
11b6da5ffe78
only print debug info when sample is actually added
bcoudurier
parents:
3300
diff
changeset
|
1228 "size %d, distance %d, keyframe %d\n", st->index, current_sample, |
11b6da5ffe78
only print debug info when sample is actually added
bcoudurier
parents:
3300
diff
changeset
|
1229 current_offset, current_dts, sample_size, distance, keyframe); |
11b6da5ffe78
only print debug info when sample is actually added
bcoudurier
parents:
3300
diff
changeset
|
1230 } |
3154
01f6f3c905db
move mov_build_index before mov_read_trak to avoid useless declaration
bcoudurier
parents:
3153
diff
changeset
|
1231 current_offset += sample_size; |
01f6f3c905db
move mov_build_index before mov_read_trak to avoid useless declaration
bcoudurier
parents:
3153
diff
changeset
|
1232 assert(sc->stts_data[stts_index].duration % sc->time_rate == 0); |
01f6f3c905db
move mov_build_index before mov_read_trak to avoid useless declaration
bcoudurier
parents:
3153
diff
changeset
|
1233 current_dts += sc->stts_data[stts_index].duration / sc->time_rate; |
01f6f3c905db
move mov_build_index before mov_read_trak to avoid useless declaration
bcoudurier
parents:
3153
diff
changeset
|
1234 distance++; |
01f6f3c905db
move mov_build_index before mov_read_trak to avoid useless declaration
bcoudurier
parents:
3153
diff
changeset
|
1235 stts_sample++; |
01f6f3c905db
move mov_build_index before mov_read_trak to avoid useless declaration
bcoudurier
parents:
3153
diff
changeset
|
1236 current_sample++; |
01f6f3c905db
move mov_build_index before mov_read_trak to avoid useless declaration
bcoudurier
parents:
3153
diff
changeset
|
1237 if (stts_index + 1 < sc->stts_count && stts_sample == sc->stts_data[stts_index].count) { |
01f6f3c905db
move mov_build_index before mov_read_trak to avoid useless declaration
bcoudurier
parents:
3153
diff
changeset
|
1238 stts_sample = 0; |
01f6f3c905db
move mov_build_index before mov_read_trak to avoid useless declaration
bcoudurier
parents:
3153
diff
changeset
|
1239 stts_index++; |
01f6f3c905db
move mov_build_index before mov_read_trak to avoid useless declaration
bcoudurier
parents:
3153
diff
changeset
|
1240 } |
01f6f3c905db
move mov_build_index before mov_read_trak to avoid useless declaration
bcoudurier
parents:
3153
diff
changeset
|
1241 } |
01f6f3c905db
move mov_build_index before mov_read_trak to avoid useless declaration
bcoudurier
parents:
3153
diff
changeset
|
1242 } |
01f6f3c905db
move mov_build_index before mov_read_trak to avoid useless declaration
bcoudurier
parents:
3153
diff
changeset
|
1243 } else { /* read whole chunk */ |
01f6f3c905db
move mov_build_index before mov_read_trak to avoid useless declaration
bcoudurier
parents:
3153
diff
changeset
|
1244 unsigned int chunk_samples, chunk_size, chunk_duration; |
01f6f3c905db
move mov_build_index before mov_read_trak to avoid useless declaration
bcoudurier
parents:
3153
diff
changeset
|
1245 unsigned int frames = 1; |
01f6f3c905db
move mov_build_index before mov_read_trak to avoid useless declaration
bcoudurier
parents:
3153
diff
changeset
|
1246 for (i = 0; i < sc->chunk_count; i++) { |
01f6f3c905db
move mov_build_index before mov_read_trak to avoid useless declaration
bcoudurier
parents:
3153
diff
changeset
|
1247 current_offset = sc->chunk_offsets[i]; |
01f6f3c905db
move mov_build_index before mov_read_trak to avoid useless declaration
bcoudurier
parents:
3153
diff
changeset
|
1248 if (stsc_index + 1 < sc->sample_to_chunk_sz && |
01f6f3c905db
move mov_build_index before mov_read_trak to avoid useless declaration
bcoudurier
parents:
3153
diff
changeset
|
1249 i + 1 == sc->sample_to_chunk[stsc_index + 1].first) |
01f6f3c905db
move mov_build_index before mov_read_trak to avoid useless declaration
bcoudurier
parents:
3153
diff
changeset
|
1250 stsc_index++; |
01f6f3c905db
move mov_build_index before mov_read_trak to avoid useless declaration
bcoudurier
parents:
3153
diff
changeset
|
1251 chunk_samples = sc->sample_to_chunk[stsc_index].count; |
01f6f3c905db
move mov_build_index before mov_read_trak to avoid useless declaration
bcoudurier
parents:
3153
diff
changeset
|
1252 /* get chunk size, beware of alaw/ulaw/mace */ |
01f6f3c905db
move mov_build_index before mov_read_trak to avoid useless declaration
bcoudurier
parents:
3153
diff
changeset
|
1253 if (sc->samples_per_frame > 0 && |
01f6f3c905db
move mov_build_index before mov_read_trak to avoid useless declaration
bcoudurier
parents:
3153
diff
changeset
|
1254 (chunk_samples * sc->bytes_per_frame % sc->samples_per_frame == 0)) { |
3255 | 1255 if (sc->samples_per_frame < 160) |
3154
01f6f3c905db
move mov_build_index before mov_read_trak to avoid useless declaration
bcoudurier
parents:
3153
diff
changeset
|
1256 chunk_size = chunk_samples * sc->bytes_per_frame / sc->samples_per_frame; |
01f6f3c905db
move mov_build_index before mov_read_trak to avoid useless declaration
bcoudurier
parents:
3153
diff
changeset
|
1257 else { |
01f6f3c905db
move mov_build_index before mov_read_trak to avoid useless declaration
bcoudurier
parents:
3153
diff
changeset
|
1258 chunk_size = sc->bytes_per_frame; |
01f6f3c905db
move mov_build_index before mov_read_trak to avoid useless declaration
bcoudurier
parents:
3153
diff
changeset
|
1259 frames = chunk_samples / sc->samples_per_frame; |
01f6f3c905db
move mov_build_index before mov_read_trak to avoid useless declaration
bcoudurier
parents:
3153
diff
changeset
|
1260 chunk_samples = sc->samples_per_frame; |
01f6f3c905db
move mov_build_index before mov_read_trak to avoid useless declaration
bcoudurier
parents:
3153
diff
changeset
|
1261 } |
3173
cb3eb255f80d
sample size to 1 might happen for data, fix GMCMidiaASX.mov, fallback is better than failing
bcoudurier
parents:
3170
diff
changeset
|
1262 } else |
3154
01f6f3c905db
move mov_build_index before mov_read_trak to avoid useless declaration
bcoudurier
parents:
3153
diff
changeset
|
1263 chunk_size = chunk_samples * sc->sample_size; |
01f6f3c905db
move mov_build_index before mov_read_trak to avoid useless declaration
bcoudurier
parents:
3153
diff
changeset
|
1264 for (j = 0; j < frames; j++) { |
01f6f3c905db
move mov_build_index before mov_read_trak to avoid useless declaration
bcoudurier
parents:
3153
diff
changeset
|
1265 av_add_index_entry(st, current_offset, current_dts, chunk_size, 0, AVINDEX_KEYFRAME); |
01f6f3c905db
move mov_build_index before mov_read_trak to avoid useless declaration
bcoudurier
parents:
3153
diff
changeset
|
1266 /* get chunk duration */ |
01f6f3c905db
move mov_build_index before mov_read_trak to avoid useless declaration
bcoudurier
parents:
3153
diff
changeset
|
1267 chunk_duration = 0; |
01f6f3c905db
move mov_build_index before mov_read_trak to avoid useless declaration
bcoudurier
parents:
3153
diff
changeset
|
1268 while (chunk_samples > 0) { |
01f6f3c905db
move mov_build_index before mov_read_trak to avoid useless declaration
bcoudurier
parents:
3153
diff
changeset
|
1269 if (chunk_samples < sc->stts_data[stts_index].count) { |
01f6f3c905db
move mov_build_index before mov_read_trak to avoid useless declaration
bcoudurier
parents:
3153
diff
changeset
|
1270 chunk_duration += sc->stts_data[stts_index].duration * chunk_samples; |
01f6f3c905db
move mov_build_index before mov_read_trak to avoid useless declaration
bcoudurier
parents:
3153
diff
changeset
|
1271 sc->stts_data[stts_index].count -= chunk_samples; |
01f6f3c905db
move mov_build_index before mov_read_trak to avoid useless declaration
bcoudurier
parents:
3153
diff
changeset
|
1272 break; |
01f6f3c905db
move mov_build_index before mov_read_trak to avoid useless declaration
bcoudurier
parents:
3153
diff
changeset
|
1273 } else { |
01f6f3c905db
move mov_build_index before mov_read_trak to avoid useless declaration
bcoudurier
parents:
3153
diff
changeset
|
1274 chunk_duration += sc->stts_data[stts_index].duration * chunk_samples; |
01f6f3c905db
move mov_build_index before mov_read_trak to avoid useless declaration
bcoudurier
parents:
3153
diff
changeset
|
1275 chunk_samples -= sc->stts_data[stts_index].count; |
01f6f3c905db
move mov_build_index before mov_read_trak to avoid useless declaration
bcoudurier
parents:
3153
diff
changeset
|
1276 if (stts_index + 1 < sc->stts_count) |
01f6f3c905db
move mov_build_index before mov_read_trak to avoid useless declaration
bcoudurier
parents:
3153
diff
changeset
|
1277 stts_index++; |
01f6f3c905db
move mov_build_index before mov_read_trak to avoid useless declaration
bcoudurier
parents:
3153
diff
changeset
|
1278 } |
01f6f3c905db
move mov_build_index before mov_read_trak to avoid useless declaration
bcoudurier
parents:
3153
diff
changeset
|
1279 } |
01f6f3c905db
move mov_build_index before mov_read_trak to avoid useless declaration
bcoudurier
parents:
3153
diff
changeset
|
1280 current_offset += sc->bytes_per_frame; |
3167 | 1281 dprintf(mov->fc, "AVIndex stream %d, chunk %d, offset %"PRIx64", dts %"PRId64", " |
1282 "size %d, duration %d\n", st->index, i, current_offset, current_dts, | |
1283 chunk_size, chunk_duration); | |
3154
01f6f3c905db
move mov_build_index before mov_read_trak to avoid useless declaration
bcoudurier
parents:
3153
diff
changeset
|
1284 assert(chunk_duration % sc->time_rate == 0); |
01f6f3c905db
move mov_build_index before mov_read_trak to avoid useless declaration
bcoudurier
parents:
3153
diff
changeset
|
1285 current_dts += chunk_duration / sc->time_rate; |
01f6f3c905db
move mov_build_index before mov_read_trak to avoid useless declaration
bcoudurier
parents:
3153
diff
changeset
|
1286 } |
01f6f3c905db
move mov_build_index before mov_read_trak to avoid useless declaration
bcoudurier
parents:
3153
diff
changeset
|
1287 } |
01f6f3c905db
move mov_build_index before mov_read_trak to avoid useless declaration
bcoudurier
parents:
3153
diff
changeset
|
1288 } |
01f6f3c905db
move mov_build_index before mov_read_trak to avoid useless declaration
bcoudurier
parents:
3153
diff
changeset
|
1289 out: |
01f6f3c905db
move mov_build_index before mov_read_trak to avoid useless declaration
bcoudurier
parents:
3153
diff
changeset
|
1290 /* adjust sample count to avindex entries */ |
01f6f3c905db
move mov_build_index before mov_read_trak to avoid useless declaration
bcoudurier
parents:
3153
diff
changeset
|
1291 sc->sample_count = st->nb_index_entries; |
01f6f3c905db
move mov_build_index before mov_read_trak to avoid useless declaration
bcoudurier
parents:
3153
diff
changeset
|
1292 } |
3153
4ded3fdf5c7c
move specific end treatment when trak is detected, will be needed for fragments
bcoudurier
parents:
3145
diff
changeset
|
1293 |
1845 | 1294 static int mov_read_trak(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom) |
1295 { | |
1296 AVStream *st; | |
1297 MOVStreamContext *sc; | |
3153
4ded3fdf5c7c
move specific end treatment when trak is detected, will be needed for fragments
bcoudurier
parents:
3145
diff
changeset
|
1298 int ret; |
1845 | 1299 |
1300 st = av_new_stream(c->fc, c->fc->nb_streams); | |
3162 | 1301 if (!st) return AVERROR(ENOMEM); |
1845 | 1302 sc = av_mallocz(sizeof(MOVStreamContext)); |
3161
60be75aa8c47
cannot free AVStream like this, and return ENOMEM
bcoudurier
parents:
3160
diff
changeset
|
1303 if (!sc) return AVERROR(ENOMEM); |
1845 | 1304 |
1305 st->priv_data = sc; | |
1306 st->codec->codec_type = CODEC_TYPE_DATA; | |
1307 st->start_time = 0; /* XXX: check */ | |
1308 | |
3153
4ded3fdf5c7c
move specific end treatment when trak is detected, will be needed for fragments
bcoudurier
parents:
3145
diff
changeset
|
1309 if ((ret = mov_read_default(c, pb, atom)) < 0) |
4ded3fdf5c7c
move specific end treatment when trak is detected, will be needed for fragments
bcoudurier
parents:
3145
diff
changeset
|
1310 return ret; |
4ded3fdf5c7c
move specific end treatment when trak is detected, will be needed for fragments
bcoudurier
parents:
3145
diff
changeset
|
1311 |
4ded3fdf5c7c
move specific end treatment when trak is detected, will be needed for fragments
bcoudurier
parents:
3145
diff
changeset
|
1312 /* sanity checks */ |
3191
68c7fd8c44ca
support mp4 fragmented files without any samples in the moov atom
bcoudurier
parents:
3190
diff
changeset
|
1313 if(sc->chunk_count && (!sc->stts_count || !sc->sample_to_chunk_sz || |
68c7fd8c44ca
support mp4 fragmented files without any samples in the moov atom
bcoudurier
parents:
3190
diff
changeset
|
1314 (!sc->sample_size && !sc->sample_count))){ |
3180 | 1315 av_log(c->fc, AV_LOG_ERROR, "stream %d, missing mandatory atoms, broken header\n", |
1316 st->index); | |
3153
4ded3fdf5c7c
move specific end treatment when trak is detected, will be needed for fragments
bcoudurier
parents:
3145
diff
changeset
|
1317 sc->sample_count = 0; //ignore track |
4ded3fdf5c7c
move specific end treatment when trak is detected, will be needed for fragments
bcoudurier
parents:
3145
diff
changeset
|
1318 return 0; |
4ded3fdf5c7c
move specific end treatment when trak is detected, will be needed for fragments
bcoudurier
parents:
3145
diff
changeset
|
1319 } |
4ded3fdf5c7c
move specific end treatment when trak is detected, will be needed for fragments
bcoudurier
parents:
3145
diff
changeset
|
1320 if(!sc->time_rate) |
4ded3fdf5c7c
move specific end treatment when trak is detected, will be needed for fragments
bcoudurier
parents:
3145
diff
changeset
|
1321 sc->time_rate=1; |
4ded3fdf5c7c
move specific end treatment when trak is detected, will be needed for fragments
bcoudurier
parents:
3145
diff
changeset
|
1322 if(!sc->time_scale) |
4ded3fdf5c7c
move specific end treatment when trak is detected, will be needed for fragments
bcoudurier
parents:
3145
diff
changeset
|
1323 sc->time_scale= c->time_scale; |
4ded3fdf5c7c
move specific end treatment when trak is detected, will be needed for fragments
bcoudurier
parents:
3145
diff
changeset
|
1324 av_set_pts_info(st, 64, sc->time_rate, sc->time_scale); |
4ded3fdf5c7c
move specific end treatment when trak is detected, will be needed for fragments
bcoudurier
parents:
3145
diff
changeset
|
1325 |
3245
9f25267bee44
demux qcelp, so this can work with soc decoder and stream copy
bcoudurier
parents:
3242
diff
changeset
|
1326 if (st->codec->codec_type == CODEC_TYPE_AUDIO && |
9f25267bee44
demux qcelp, so this can work with soc decoder and stream copy
bcoudurier
parents:
3242
diff
changeset
|
1327 !st->codec->frame_size && sc->stts_count == 1) |
3153
4ded3fdf5c7c
move specific end treatment when trak is detected, will be needed for fragments
bcoudurier
parents:
3145
diff
changeset
|
1328 st->codec->frame_size = av_rescale(sc->time_rate, st->codec->sample_rate, sc->time_scale); |
4ded3fdf5c7c
move specific end treatment when trak is detected, will be needed for fragments
bcoudurier
parents:
3145
diff
changeset
|
1329 |
4ded3fdf5c7c
move specific end treatment when trak is detected, will be needed for fragments
bcoudurier
parents:
3145
diff
changeset
|
1330 if(st->duration != AV_NOPTS_VALUE){ |
4ded3fdf5c7c
move specific end treatment when trak is detected, will be needed for fragments
bcoudurier
parents:
3145
diff
changeset
|
1331 assert(st->duration % sc->time_rate == 0); |
4ded3fdf5c7c
move specific end treatment when trak is detected, will be needed for fragments
bcoudurier
parents:
3145
diff
changeset
|
1332 st->duration /= sc->time_rate; |
4ded3fdf5c7c
move specific end treatment when trak is detected, will be needed for fragments
bcoudurier
parents:
3145
diff
changeset
|
1333 } |
4ded3fdf5c7c
move specific end treatment when trak is detected, will be needed for fragments
bcoudurier
parents:
3145
diff
changeset
|
1334 sc->ffindex = st->index; |
4ded3fdf5c7c
move specific end treatment when trak is detected, will be needed for fragments
bcoudurier
parents:
3145
diff
changeset
|
1335 mov_build_index(c, st); |
4ded3fdf5c7c
move specific end treatment when trak is detected, will be needed for fragments
bcoudurier
parents:
3145
diff
changeset
|
1336 |
4ded3fdf5c7c
move specific end treatment when trak is detected, will be needed for fragments
bcoudurier
parents:
3145
diff
changeset
|
1337 if (sc->dref_id-1 < sc->drefs_count && sc->drefs[sc->dref_id-1].path) { |
4ded3fdf5c7c
move specific end treatment when trak is detected, will be needed for fragments
bcoudurier
parents:
3145
diff
changeset
|
1338 if (url_fopen(&sc->pb, sc->drefs[sc->dref_id-1].path, URL_RDONLY) < 0) |
3182 | 1339 av_log(c->fc, AV_LOG_ERROR, "stream %d, error opening file %s: %s\n", |
1340 st->index, sc->drefs[sc->dref_id-1].path, strerror(errno)); | |
3153
4ded3fdf5c7c
move specific end treatment when trak is detected, will be needed for fragments
bcoudurier
parents:
3145
diff
changeset
|
1341 } else |
4ded3fdf5c7c
move specific end treatment when trak is detected, will be needed for fragments
bcoudurier
parents:
3145
diff
changeset
|
1342 sc->pb = c->fc->pb; |
4ded3fdf5c7c
move specific end treatment when trak is detected, will be needed for fragments
bcoudurier
parents:
3145
diff
changeset
|
1343 |
4ded3fdf5c7c
move specific end treatment when trak is detected, will be needed for fragments
bcoudurier
parents:
3145
diff
changeset
|
1344 switch (st->codec->codec_id) { |
4ded3fdf5c7c
move specific end treatment when trak is detected, will be needed for fragments
bcoudurier
parents:
3145
diff
changeset
|
1345 #ifdef CONFIG_H261_DECODER |
4ded3fdf5c7c
move specific end treatment when trak is detected, will be needed for fragments
bcoudurier
parents:
3145
diff
changeset
|
1346 case CODEC_ID_H261: |
4ded3fdf5c7c
move specific end treatment when trak is detected, will be needed for fragments
bcoudurier
parents:
3145
diff
changeset
|
1347 #endif |
4ded3fdf5c7c
move specific end treatment when trak is detected, will be needed for fragments
bcoudurier
parents:
3145
diff
changeset
|
1348 #ifdef CONFIG_H263_DECODER |
4ded3fdf5c7c
move specific end treatment when trak is detected, will be needed for fragments
bcoudurier
parents:
3145
diff
changeset
|
1349 case CODEC_ID_H263: |
4ded3fdf5c7c
move specific end treatment when trak is detected, will be needed for fragments
bcoudurier
parents:
3145
diff
changeset
|
1350 #endif |
4ded3fdf5c7c
move specific end treatment when trak is detected, will be needed for fragments
bcoudurier
parents:
3145
diff
changeset
|
1351 #ifdef CONFIG_MPEG4_DECODER |
4ded3fdf5c7c
move specific end treatment when trak is detected, will be needed for fragments
bcoudurier
parents:
3145
diff
changeset
|
1352 case CODEC_ID_MPEG4: |
4ded3fdf5c7c
move specific end treatment when trak is detected, will be needed for fragments
bcoudurier
parents:
3145
diff
changeset
|
1353 #endif |
4ded3fdf5c7c
move specific end treatment when trak is detected, will be needed for fragments
bcoudurier
parents:
3145
diff
changeset
|
1354 st->codec->width= 0; /* let decoder init width/height */ |
4ded3fdf5c7c
move specific end treatment when trak is detected, will be needed for fragments
bcoudurier
parents:
3145
diff
changeset
|
1355 st->codec->height= 0; |
4ded3fdf5c7c
move specific end treatment when trak is detected, will be needed for fragments
bcoudurier
parents:
3145
diff
changeset
|
1356 break; |
4ded3fdf5c7c
move specific end treatment when trak is detected, will be needed for fragments
bcoudurier
parents:
3145
diff
changeset
|
1357 #ifdef CONFIG_VORBIS_DECODER |
4ded3fdf5c7c
move specific end treatment when trak is detected, will be needed for fragments
bcoudurier
parents:
3145
diff
changeset
|
1358 case CODEC_ID_VORBIS: |
4ded3fdf5c7c
move specific end treatment when trak is detected, will be needed for fragments
bcoudurier
parents:
3145
diff
changeset
|
1359 #endif |
4ded3fdf5c7c
move specific end treatment when trak is detected, will be needed for fragments
bcoudurier
parents:
3145
diff
changeset
|
1360 st->codec->sample_rate= 0; /* let decoder init parameters properly */ |
4ded3fdf5c7c
move specific end treatment when trak is detected, will be needed for fragments
bcoudurier
parents:
3145
diff
changeset
|
1361 break; |
4ded3fdf5c7c
move specific end treatment when trak is detected, will be needed for fragments
bcoudurier
parents:
3145
diff
changeset
|
1362 } |
3155 | 1363 |
1364 /* Do not need those anymore. */ | |
1365 av_freep(&sc->chunk_offsets); | |
1366 av_freep(&sc->sample_to_chunk); | |
1367 av_freep(&sc->sample_sizes); | |
1368 av_freep(&sc->keyframes); | |
1369 av_freep(&sc->stts_data); | |
1370 | |
3153
4ded3fdf5c7c
move specific end treatment when trak is detected, will be needed for fragments
bcoudurier
parents:
3145
diff
changeset
|
1371 return 0; |
1845 | 1372 } |
1373 | |
2296
0cfc556604e3
fill title, author, copyright and comment fields by parsing udta atom
benoit
parents:
2164
diff
changeset
|
1374 static void mov_parse_udta_string(ByteIOContext *pb, char *str, int size) |
0cfc556604e3
fill title, author, copyright and comment fields by parsing udta atom
benoit
parents:
2164
diff
changeset
|
1375 { |
0cfc556604e3
fill title, author, copyright and comment fields by parsing udta atom
benoit
parents:
2164
diff
changeset
|
1376 uint16_t str_size = get_be16(pb); /* string length */; |
0cfc556604e3
fill title, author, copyright and comment fields by parsing udta atom
benoit
parents:
2164
diff
changeset
|
1377 |
0cfc556604e3
fill title, author, copyright and comment fields by parsing udta atom
benoit
parents:
2164
diff
changeset
|
1378 get_be16(pb); /* skip language */ |
0cfc556604e3
fill title, author, copyright and comment fields by parsing udta atom
benoit
parents:
2164
diff
changeset
|
1379 get_buffer(pb, str, FFMIN(size, str_size)); |
0cfc556604e3
fill title, author, copyright and comment fields by parsing udta atom
benoit
parents:
2164
diff
changeset
|
1380 } |
0cfc556604e3
fill title, author, copyright and comment fields by parsing udta atom
benoit
parents:
2164
diff
changeset
|
1381 |
0cfc556604e3
fill title, author, copyright and comment fields by parsing udta atom
benoit
parents:
2164
diff
changeset
|
1382 static int mov_read_udta(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom) |
0cfc556604e3
fill title, author, copyright and comment fields by parsing udta atom
benoit
parents:
2164
diff
changeset
|
1383 { |
0cfc556604e3
fill title, author, copyright and comment fields by parsing udta atom
benoit
parents:
2164
diff
changeset
|
1384 uint64_t end = url_ftell(pb) + atom.size; |
0cfc556604e3
fill title, author, copyright and comment fields by parsing udta atom
benoit
parents:
2164
diff
changeset
|
1385 |
0cfc556604e3
fill title, author, copyright and comment fields by parsing udta atom
benoit
parents:
2164
diff
changeset
|
1386 while (url_ftell(pb) + 8 < end) { |
0cfc556604e3
fill title, author, copyright and comment fields by parsing udta atom
benoit
parents:
2164
diff
changeset
|
1387 uint32_t tag_size = get_be32(pb); |
0cfc556604e3
fill title, author, copyright and comment fields by parsing udta atom
benoit
parents:
2164
diff
changeset
|
1388 uint32_t tag = get_le32(pb); |
0cfc556604e3
fill title, author, copyright and comment fields by parsing udta atom
benoit
parents:
2164
diff
changeset
|
1389 uint64_t next = url_ftell(pb) + tag_size - 8; |
0cfc556604e3
fill title, author, copyright and comment fields by parsing udta atom
benoit
parents:
2164
diff
changeset
|
1390 |
2547
92bf4673d050
stop parsing udta if size is wrong/garbage, fix issue 154, fix RQ004F14.MOV
bcoudurier
parents:
2299
diff
changeset
|
1391 if (next > end) // stop if tag_size is wrong |
92bf4673d050
stop parsing udta if size is wrong/garbage, fix issue 154, fix RQ004F14.MOV
bcoudurier
parents:
2299
diff
changeset
|
1392 break; |
92bf4673d050
stop parsing udta if size is wrong/garbage, fix issue 154, fix RQ004F14.MOV
bcoudurier
parents:
2299
diff
changeset
|
1393 |
2296
0cfc556604e3
fill title, author, copyright and comment fields by parsing udta atom
benoit
parents:
2164
diff
changeset
|
1394 switch (tag) { |
0cfc556604e3
fill title, author, copyright and comment fields by parsing udta atom
benoit
parents:
2164
diff
changeset
|
1395 case MKTAG(0xa9,'n','a','m'): |
0cfc556604e3
fill title, author, copyright and comment fields by parsing udta atom
benoit
parents:
2164
diff
changeset
|
1396 mov_parse_udta_string(pb, c->fc->title, sizeof(c->fc->title)); |
0cfc556604e3
fill title, author, copyright and comment fields by parsing udta atom
benoit
parents:
2164
diff
changeset
|
1397 break; |
0cfc556604e3
fill title, author, copyright and comment fields by parsing udta atom
benoit
parents:
2164
diff
changeset
|
1398 case MKTAG(0xa9,'w','r','t'): |
0cfc556604e3
fill title, author, copyright and comment fields by parsing udta atom
benoit
parents:
2164
diff
changeset
|
1399 mov_parse_udta_string(pb, c->fc->author, sizeof(c->fc->author)); |
0cfc556604e3
fill title, author, copyright and comment fields by parsing udta atom
benoit
parents:
2164
diff
changeset
|
1400 break; |
0cfc556604e3
fill title, author, copyright and comment fields by parsing udta atom
benoit
parents:
2164
diff
changeset
|
1401 case MKTAG(0xa9,'c','p','y'): |
0cfc556604e3
fill title, author, copyright and comment fields by parsing udta atom
benoit
parents:
2164
diff
changeset
|
1402 mov_parse_udta_string(pb, c->fc->copyright, sizeof(c->fc->copyright)); |
0cfc556604e3
fill title, author, copyright and comment fields by parsing udta atom
benoit
parents:
2164
diff
changeset
|
1403 break; |
0cfc556604e3
fill title, author, copyright and comment fields by parsing udta atom
benoit
parents:
2164
diff
changeset
|
1404 case MKTAG(0xa9,'i','n','f'): |
0cfc556604e3
fill title, author, copyright and comment fields by parsing udta atom
benoit
parents:
2164
diff
changeset
|
1405 mov_parse_udta_string(pb, c->fc->comment, sizeof(c->fc->comment)); |
0cfc556604e3
fill title, author, copyright and comment fields by parsing udta atom
benoit
parents:
2164
diff
changeset
|
1406 break; |
0cfc556604e3
fill title, author, copyright and comment fields by parsing udta atom
benoit
parents:
2164
diff
changeset
|
1407 default: |
0cfc556604e3
fill title, author, copyright and comment fields by parsing udta atom
benoit
parents:
2164
diff
changeset
|
1408 break; |
0cfc556604e3
fill title, author, copyright and comment fields by parsing udta atom
benoit
parents:
2164
diff
changeset
|
1409 } |
0cfc556604e3
fill title, author, copyright and comment fields by parsing udta atom
benoit
parents:
2164
diff
changeset
|
1410 |
0cfc556604e3
fill title, author, copyright and comment fields by parsing udta atom
benoit
parents:
2164
diff
changeset
|
1411 url_fseek(pb, next, SEEK_SET); |
0cfc556604e3
fill title, author, copyright and comment fields by parsing udta atom
benoit
parents:
2164
diff
changeset
|
1412 } |
0cfc556604e3
fill title, author, copyright and comment fields by parsing udta atom
benoit
parents:
2164
diff
changeset
|
1413 |
0cfc556604e3
fill title, author, copyright and comment fields by parsing udta atom
benoit
parents:
2164
diff
changeset
|
1414 return 0; |
0cfc556604e3
fill title, author, copyright and comment fields by parsing udta atom
benoit
parents:
2164
diff
changeset
|
1415 } |
0cfc556604e3
fill title, author, copyright and comment fields by parsing udta atom
benoit
parents:
2164
diff
changeset
|
1416 |
1845 | 1417 static int mov_read_tkhd(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom) |
1418 { | |
3595 | 1419 int i; |
1420 int width; | |
1421 int height; | |
1422 int64_t disp_transform[2]; | |
1423 int display_matrix[3][2]; | |
1845 | 1424 AVStream *st = c->fc->streams[c->fc->nb_streams-1]; |
1425 int version = get_byte(pb); | |
1426 | |
3145 | 1427 get_be24(pb); /* flags */ |
1845 | 1428 /* |
1429 MOV_TRACK_ENABLED 0x0001 | |
1430 MOV_TRACK_IN_MOVIE 0x0002 | |
1431 MOV_TRACK_IN_PREVIEW 0x0004 | |
1432 MOV_TRACK_IN_POSTER 0x0008 | |
1433 */ | |
1434 | |
1435 if (version == 1) { | |
1436 get_be64(pb); | |
1437 get_be64(pb); | |
1438 } else { | |
1439 get_be32(pb); /* creation time */ | |
1440 get_be32(pb); /* modification time */ | |
1441 } | |
1442 st->id = (int)get_be32(pb); /* track id (NOT 0 !)*/ | |
1443 get_be32(pb); /* reserved */ | |
1444 st->start_time = 0; /* check */ | |
3167 | 1445 /* highlevel (considering edits) duration in movie timebase */ |
1446 (version == 1) ? get_be64(pb) : get_be32(pb); | |
1845 | 1447 get_be32(pb); /* reserved */ |
1448 get_be32(pb); /* reserved */ | |
1449 | |
1450 get_be16(pb); /* layer */ | |
1451 get_be16(pb); /* alternate group */ | |
1452 get_be16(pb); /* volume */ | |
1453 get_be16(pb); /* reserved */ | |
1454 | |
3595 | 1455 //read in the display matrix (outlined in ISO 14496-12, Section 6.2.2) |
1456 // they're kept in fixed point format through all calculations | |
1457 // ignore u,v,z b/c we don't need the scale factor to calc aspect ratio | |
1458 for (i = 0; i < 3; i++) { | |
1459 display_matrix[i][0] = get_be32(pb); // 16.16 fixed point | |
1460 display_matrix[i][1] = get_be32(pb); // 16.16 fixed point | |
1461 get_be32(pb); // 2.30 fixed point (not used) | |
1462 } | |
1463 | |
1464 width = get_be32(pb); // 16.16 fixed point track width | |
1465 height = get_be32(pb); // 16.16 fixed point track height | |
1845 | 1466 |
3595 | 1467 //transform the display width/height according to the matrix |
1468 // skip this if the display matrix is the default identity matrix | |
1469 // to keep the same scale, use [width height 1<<16] | |
1470 if (width && height && | |
1471 (display_matrix[0][0] != 65536 || display_matrix[0][1] || | |
1472 display_matrix[1][0] || display_matrix[1][1] != 65536 || | |
1473 display_matrix[2][0] || display_matrix[2][1])) { | |
1474 for (i = 0; i < 2; i++) | |
1475 disp_transform[i] = | |
1476 (int64_t) width * display_matrix[0][i] + | |
1477 (int64_t) height * display_matrix[1][i] + | |
1478 ((int64_t) display_matrix[2][i] << 16); | |
1845 | 1479 |
3595 | 1480 //sample aspect ratio is new width/height divided by old width/height |
1481 st->codec->sample_aspect_ratio = av_d2q( | |
1482 ((double) disp_transform[0] * height) / | |
1483 ((double) disp_transform[1] * width), INT_MAX); | |
1484 } | |
1845 | 1485 return 0; |
1486 } | |
1487 | |
3169 | 1488 static int mov_read_tfhd(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom) |
1489 { | |
1490 MOVFragment *frag = &c->fragment; | |
1491 MOVTrackExt *trex = NULL; | |
1492 int flags, track_id, i; | |
1493 | |
1494 get_byte(pb); /* version */ | |
1495 flags = get_be24(pb); | |
1496 | |
1497 track_id = get_be32(pb); | |
1498 if (!track_id || track_id > c->fc->nb_streams) | |
1499 return -1; | |
1500 frag->track_id = track_id; | |
1501 for (i = 0; i < c->trex_count; i++) | |
1502 if (c->trex_data[i].track_id == frag->track_id) { | |
1503 trex = &c->trex_data[i]; | |
1504 break; | |
1505 } | |
1506 if (!trex) { | |
1507 av_log(c->fc, AV_LOG_ERROR, "could not find corresponding trex\n"); | |
1508 return -1; | |
1509 } | |
1510 | |
1511 if (flags & 0x01) frag->base_data_offset = get_be64(pb); | |
1512 else frag->base_data_offset = frag->moof_offset; | |
1513 if (flags & 0x02) frag->stsd_id = get_be32(pb); | |
1514 else frag->stsd_id = trex->stsd_id; | |
1515 | |
1516 frag->duration = flags & 0x08 ? get_be32(pb) : trex->duration; | |
1517 frag->size = flags & 0x10 ? get_be32(pb) : trex->size; | |
1518 frag->flags = flags & 0x20 ? get_be32(pb) : trex->flags; | |
1519 dprintf(c->fc, "frag flags 0x%x\n", frag->flags); | |
1520 return 0; | |
1521 } | |
1522 | |
1523 static int mov_read_trex(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom) | |
1524 { | |
1525 MOVTrackExt *trex; | |
1526 | |
1527 if ((uint64_t)c->trex_count+1 >= UINT_MAX / sizeof(*c->trex_data)) | |
1528 return -1; | |
1529 c->trex_data = av_realloc(c->trex_data, (c->trex_count+1)*sizeof(*c->trex_data)); | |
1530 if (!c->trex_data) | |
1531 return AVERROR(ENOMEM); | |
1532 trex = &c->trex_data[c->trex_count++]; | |
1533 get_byte(pb); /* version */ | |
1534 get_be24(pb); /* flags */ | |
1535 trex->track_id = get_be32(pb); | |
1536 trex->stsd_id = get_be32(pb); | |
1537 trex->duration = get_be32(pb); | |
1538 trex->size = get_be32(pb); | |
1539 trex->flags = get_be32(pb); | |
1540 return 0; | |
1541 } | |
1542 | |
1543 static int mov_read_trun(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom) | |
1544 { | |
1545 MOVFragment *frag = &c->fragment; | |
3190 | 1546 AVStream *st; |
1547 MOVStreamContext *sc; | |
3169 | 1548 uint64_t offset; |
1549 int64_t dts; | |
1550 int data_offset = 0; | |
1551 unsigned entries, first_sample_flags = frag->flags; | |
1552 int flags, distance, i; | |
1553 | |
3190 | 1554 if (!frag->track_id || frag->track_id > c->fc->nb_streams) |
1555 return -1; | |
1556 st = c->fc->streams[frag->track_id-1]; | |
1557 sc = st->priv_data; | |
3169 | 1558 if (sc->pseudo_stream_id+1 != frag->stsd_id) |
1559 return 0; | |
1560 get_byte(pb); /* version */ | |
1561 flags = get_be24(pb); | |
1562 entries = get_be32(pb); | |
1563 dprintf(c->fc, "flags 0x%x entries %d\n", flags, entries); | |
1564 if (flags & 0x001) data_offset = get_be32(pb); | |
1565 if (flags & 0x004) first_sample_flags = get_be32(pb); | |
1566 if (flags & 0x800) { | |
1567 if ((uint64_t)entries+sc->ctts_count >= UINT_MAX/sizeof(*sc->ctts_data)) | |
1568 return -1; | |
1569 sc->ctts_data = av_realloc(sc->ctts_data, | |
1570 (entries+sc->ctts_count)*sizeof(*sc->ctts_data)); | |
1571 if (!sc->ctts_data) | |
1572 return AVERROR(ENOMEM); | |
1573 } | |
1574 dts = st->duration; | |
1575 offset = frag->base_data_offset + data_offset; | |
1576 distance = 0; | |
1577 dprintf(c->fc, "first sample flags 0x%x\n", first_sample_flags); | |
1578 for (i = 0; i < entries; i++) { | |
1579 unsigned sample_size = frag->size; | |
1580 int sample_flags = i ? frag->flags : first_sample_flags; | |
1581 unsigned sample_duration = frag->duration; | |
1582 int keyframe; | |
1583 | |
1584 if (flags & 0x100) sample_duration = get_be32(pb); | |
1585 if (flags & 0x200) sample_size = get_be32(pb); | |
1586 if (flags & 0x400) sample_flags = get_be32(pb); | |
1587 if (flags & 0x800) { | |
1588 sc->ctts_data[sc->ctts_count].count = 1; | |
1589 sc->ctts_data[sc->ctts_count].duration = get_be32(pb); | |
1590 sc->ctts_count++; | |
1591 } | |
1592 if ((keyframe = st->codec->codec_type == CODEC_TYPE_AUDIO || | |
1593 (flags & 0x004 && !i && !sample_flags) || sample_flags & 0x2000000)) | |
1594 distance = 0; | |
1595 av_add_index_entry(st, offset, dts, sample_size, distance, | |
1596 keyframe ? AVINDEX_KEYFRAME : 0); | |
1597 dprintf(c->fc, "AVIndex stream %d, sample %d, offset %"PRIx64", dts %"PRId64", " | |
1598 "size %d, distance %d, keyframe %d\n", st->index, sc->sample_count+i, | |
1599 offset, dts, sample_size, distance, keyframe); | |
1600 distance++; | |
1601 assert(sample_duration % sc->time_rate == 0); | |
1602 dts += sample_duration / sc->time_rate; | |
1603 offset += sample_size; | |
1604 } | |
1605 frag->moof_offset = offset; | |
1606 sc->sample_count = st->nb_index_entries; | |
1607 st->duration = dts; | |
1608 return 0; | |
1609 } | |
1610 | |
1845 | 1611 /* this atom should be null (from specs), but some buggy files put the 'moov' atom inside it... */ |
1612 /* like the files created with Adobe Premiere 5.0, for samples see */ | |
1613 /* http://graphics.tudelft.nl/~wouter/publications/soundtests/ */ | |
1614 static int mov_read_wide(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom) | |
1615 { | |
1616 int err; | |
1617 | |
1618 if (atom.size < 8) | |
1619 return 0; /* continue */ | |
1620 if (get_be32(pb) != 0) { /* 0 sized mdat atom... use the 'wide' atom size */ | |
1621 url_fskip(pb, atom.size - 4); | |
1622 return 0; | |
1623 } | |
1624 atom.type = get_le32(pb); | |
1625 atom.offset += 8; | |
1626 atom.size -= 8; | |
3253 | 1627 if (atom.type != MKTAG('m','d','a','t')) { |
1845 | 1628 url_fskip(pb, atom.size); |
1629 return 0; | |
1630 } | |
1631 err = mov_read_mdat(c, pb, atom); | |
1632 return err; | |
1633 } | |
1634 | |
1635 static int mov_read_cmov(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom) | |
1636 { | |
1637 #ifdef CONFIG_ZLIB | |
1638 ByteIOContext ctx; | |
1639 uint8_t *cmov_data; | |
1640 uint8_t *moov_data; /* uncompressed data */ | |
1641 long cmov_len, moov_len; | |
3313
8e83e0b76105
free moov and cmov when error occurs, fix memleak, patch by Albert Astals Cid, aastals at tv-wan dot es
bcoudurier
parents:
3301
diff
changeset
|
1642 int ret = -1; |
1845 | 1643 |
1644 get_be32(pb); /* dcom atom */ | |
3253 | 1645 if (get_le32(pb) != MKTAG('d','c','o','m')) |
1845 | 1646 return -1; |
3253 | 1647 if (get_le32(pb) != MKTAG('z','l','i','b')) { |
1845 | 1648 av_log(NULL, AV_LOG_ERROR, "unknown compression for cmov atom !"); |
1649 return -1; | |
1650 } | |
1651 get_be32(pb); /* cmvd atom */ | |
3253 | 1652 if (get_le32(pb) != MKTAG('c','m','v','d')) |
1845 | 1653 return -1; |
1654 moov_len = get_be32(pb); /* uncompressed size */ | |
1655 cmov_len = atom.size - 6 * 4; | |
1656 | |
1657 cmov_data = av_malloc(cmov_len); | |
1658 if (!cmov_data) | |
1659 return -1; | |
1660 moov_data = av_malloc(moov_len); | |
1661 if (!moov_data) { | |
1662 av_free(cmov_data); | |
1663 return -1; | |
1664 } | |
1665 get_buffer(pb, cmov_data, cmov_len); | |
1666 if(uncompress (moov_data, (uLongf *) &moov_len, (const Bytef *)cmov_data, cmov_len) != Z_OK) | |
3313
8e83e0b76105
free moov and cmov when error occurs, fix memleak, patch by Albert Astals Cid, aastals at tv-wan dot es
bcoudurier
parents:
3301
diff
changeset
|
1667 goto free_and_return; |
1845 | 1668 if(init_put_byte(&ctx, moov_data, moov_len, 0, NULL, NULL, NULL, NULL) != 0) |
3313
8e83e0b76105
free moov and cmov when error occurs, fix memleak, patch by Albert Astals Cid, aastals at tv-wan dot es
bcoudurier
parents:
3301
diff
changeset
|
1669 goto free_and_return; |
3253 | 1670 atom.type = MKTAG('m','o','o','v'); |
1845 | 1671 atom.offset = 0; |
1672 atom.size = moov_len; | |
1673 #ifdef DEBUG | |
1674 // { int fd = open("/tmp/uncompheader.mov", O_WRONLY | O_CREAT); write(fd, moov_data, moov_len); close(fd); } | |
1675 #endif | |
1676 ret = mov_read_default(c, &ctx, atom); | |
3313
8e83e0b76105
free moov and cmov when error occurs, fix memleak, patch by Albert Astals Cid, aastals at tv-wan dot es
bcoudurier
parents:
3301
diff
changeset
|
1677 free_and_return: |
1845 | 1678 av_free(moov_data); |
1679 av_free(cmov_data); | |
1680 return ret; | |
1681 #else | |
1682 av_log(c->fc, AV_LOG_ERROR, "this file requires zlib support compiled in\n"); | |
1683 return -1; | |
1684 #endif | |
1685 } | |
1686 | |
1687 /* edit list atom */ | |
1688 static int mov_read_elst(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom) | |
1689 { | |
2824
ecbfaa8712a1
do not retain useless pointers to avstream priv_data, use it directly
bcoudurier
parents:
2823
diff
changeset
|
1690 MOVStreamContext *sc = c->fc->streams[c->fc->nb_streams-1]->priv_data; |
1845 | 1691 int i, edit_count; |
1692 | |
1693 get_byte(pb); /* version */ | |
3145 | 1694 get_be24(pb); /* flags */ |
2824
ecbfaa8712a1
do not retain useless pointers to avstream priv_data, use it directly
bcoudurier
parents:
2823
diff
changeset
|
1695 edit_count= sc->edit_count = get_be32(pb); /* entries */ |
1845 | 1696 |
1697 for(i=0; i<edit_count; i++){ | |
3038
db12cabbe337
warn use if edit list is not starting at 0, a/v desync might occur
bcoudurier
parents:
3037
diff
changeset
|
1698 int time; |
1845 | 1699 get_be32(pb); /* Track duration */ |
3038
db12cabbe337
warn use if edit list is not starting at 0, a/v desync might occur
bcoudurier
parents:
3037
diff
changeset
|
1700 time = get_be32(pb); /* Media time */ |
1845 | 1701 get_be32(pb); /* Media rate */ |
3038
db12cabbe337
warn use if edit list is not starting at 0, a/v desync might occur
bcoudurier
parents:
3037
diff
changeset
|
1702 if (time != 0) |
db12cabbe337
warn use if edit list is not starting at 0, a/v desync might occur
bcoudurier
parents:
3037
diff
changeset
|
1703 av_log(c->fc, AV_LOG_WARNING, "edit list not starting at 0, " |
db12cabbe337
warn use if edit list is not starting at 0, a/v desync might occur
bcoudurier
parents:
3037
diff
changeset
|
1704 "a/v desync might occur, patch welcome\n"); |
1845 | 1705 } |
2824
ecbfaa8712a1
do not retain useless pointers to avstream priv_data, use it directly
bcoudurier
parents:
2823
diff
changeset
|
1706 dprintf(c->fc, "track[%i].edit_count = %i\n", c->fc->nb_streams-1, sc->edit_count); |
1845 | 1707 return 0; |
1708 } | |
1709 | |
1710 static const MOVParseTableEntry mov_default_parse_table[] = { | |
3496
cdbf302a3c00
chinese avs demuxing support, demux AVSFileFormat.mp4
bcoudurier
parents:
3487
diff
changeset
|
1711 { MKTAG('a','v','s','s'), mov_read_extradata }, |
3253 | 1712 { MKTAG('c','o','6','4'), mov_read_stco }, |
1713 { MKTAG('c','t','t','s'), mov_read_ctts }, /* composition time to sample */ | |
1714 { MKTAG('d','i','n','f'), mov_read_default }, | |
1715 { MKTAG('d','r','e','f'), mov_read_dref }, | |
1716 { MKTAG('e','d','t','s'), mov_read_default }, | |
1717 { MKTAG('e','l','s','t'), mov_read_elst }, | |
1718 { MKTAG('e','n','d','a'), mov_read_enda }, | |
1719 { MKTAG('f','i','e','l'), mov_read_extradata }, | |
1720 { MKTAG('f','t','y','p'), mov_read_ftyp }, | |
1721 { MKTAG('g','l','b','l'), mov_read_glbl }, | |
1722 { MKTAG('h','d','l','r'), mov_read_hdlr }, | |
1723 { MKTAG('j','p','2','h'), mov_read_extradata }, | |
1724 { MKTAG('m','d','a','t'), mov_read_mdat }, | |
1725 { MKTAG('m','d','h','d'), mov_read_mdhd }, | |
1726 { MKTAG('m','d','i','a'), mov_read_default }, | |
1727 { MKTAG('m','i','n','f'), mov_read_default }, | |
1728 { MKTAG('m','o','o','f'), mov_read_moof }, | |
1729 { MKTAG('m','o','o','v'), mov_read_moov }, | |
1730 { MKTAG('m','v','e','x'), mov_read_default }, | |
1731 { MKTAG('m','v','h','d'), mov_read_mvhd }, | |
1732 { MKTAG('S','M','I',' '), mov_read_smi }, /* Sorenson extension ??? */ | |
1733 { MKTAG('a','l','a','c'), mov_read_extradata }, /* alac specific atom */ | |
1734 { MKTAG('a','v','c','C'), mov_read_glbl }, | |
1735 { MKTAG('s','t','b','l'), mov_read_default }, | |
1736 { MKTAG('s','t','c','o'), mov_read_stco }, | |
1737 { MKTAG('s','t','s','c'), mov_read_stsc }, | |
1738 { MKTAG('s','t','s','d'), mov_read_stsd }, /* sample description */ | |
1739 { MKTAG('s','t','s','s'), mov_read_stss }, /* sync sample */ | |
1740 { MKTAG('s','t','s','z'), mov_read_stsz }, /* sample size */ | |
1741 { MKTAG('s','t','t','s'), mov_read_stts }, | |
1742 { MKTAG('t','k','h','d'), mov_read_tkhd }, /* track header */ | |
1743 { MKTAG('t','f','h','d'), mov_read_tfhd }, /* track fragment header */ | |
1744 { MKTAG('t','r','a','k'), mov_read_trak }, | |
1745 { MKTAG('t','r','a','f'), mov_read_default }, | |
1746 { MKTAG('t','r','e','x'), mov_read_trex }, | |
1747 { MKTAG('t','r','u','n'), mov_read_trun }, | |
1748 { MKTAG('u','d','t','a'), mov_read_udta }, | |
1749 { MKTAG('w','a','v','e'), mov_read_wave }, | |
1750 { MKTAG('e','s','d','s'), mov_read_esds }, | |
1751 { MKTAG('w','i','d','e'), mov_read_wide }, /* place holder */ | |
1752 { MKTAG('c','m','o','v'), mov_read_cmov }, | |
2826 | 1753 { 0, NULL } |
1845 | 1754 }; |
1755 | |
1756 static int mov_probe(AVProbeData *p) | |
1757 { | |
1758 unsigned int offset; | |
1759 uint32_t tag; | |
1760 int score = 0; | |
1761 | |
1762 /* check file header */ | |
1763 offset = 0; | |
1764 for(;;) { | |
1765 /* ignore invalid offset */ | |
1766 if ((offset + 8) > (unsigned int)p->buf_size) | |
1767 return score; | |
1768 tag = AV_RL32(p->buf + offset + 4); | |
1769 switch(tag) { | |
1770 /* check for obvious tags */ | |
3253 | 1771 case MKTAG('j','P',' ',' '): /* jpeg 2000 signature */ |
1772 case MKTAG('m','o','o','v'): | |
1773 case MKTAG('m','d','a','t'): | |
1774 case MKTAG('p','n','o','t'): /* detect movs with preview pics like ew.mov and april.mov */ | |
1775 case MKTAG('u','d','t','a'): /* Packet Video PVAuthor adds this and a lot of more junk */ | |
3587
7d5480d3989d
Return max score when ftyp atom is encountered.
bcoudurier
parents:
3496
diff
changeset
|
1776 case MKTAG('f','t','y','p'): |
1845 | 1777 return AVPROBE_SCORE_MAX; |
1778 /* those are more common words, so rate then a bit less */ | |
3253 | 1779 case MKTAG('e','d','i','w'): /* xdcam files have reverted first tags */ |
1780 case MKTAG('w','i','d','e'): | |
1781 case MKTAG('f','r','e','e'): | |
1782 case MKTAG('j','u','n','k'): | |
1783 case MKTAG('p','i','c','t'): | |
1845 | 1784 return AVPROBE_SCORE_MAX - 5; |
3588 | 1785 case MKTAG(0x82,0x82,0x7f,0x7d): |
3253 | 1786 case MKTAG('s','k','i','p'): |
1787 case MKTAG('u','u','i','d'): | |
1788 case MKTAG('p','r','f','l'): | |
1845 | 1789 offset = AV_RB32(p->buf+offset) + offset; |
1790 /* if we only find those cause probedata is too small at least rate them */ | |
1791 score = AVPROBE_SCORE_MAX - 50; | |
1792 break; | |
1793 default: | |
1794 /* unrecognized tag */ | |
1795 return score; | |
1796 } | |
1797 } | |
1798 return score; | |
1799 } | |
1800 | |
1801 static int mov_read_header(AVFormatContext *s, AVFormatParameters *ap) | |
1802 { | |
2006 | 1803 MOVContext *mov = s->priv_data; |
2771
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2730
diff
changeset
|
1804 ByteIOContext *pb = s->pb; |
3155 | 1805 int err; |
1845 | 1806 MOV_atom_t atom = { 0, 0, 0 }; |
1807 | |
1808 mov->fc = s; | |
3167 | 1809 /* .mov and .mp4 aren't streamable anyway (only progressive download if moov is before mdat) */ |
1810 if(!url_is_streamed(pb)) | |
1845 | 1811 atom.size = url_fsize(pb); |
1812 else | |
2026 | 1813 atom.size = INT64_MAX; |
1845 | 1814 |
1815 /* check MOV header */ | |
3204 | 1816 if ((err = mov_read_default(mov, pb, atom)) < 0) { |
1817 av_log(s, AV_LOG_ERROR, "error reading header: %d\n", err); | |
1818 return err; | |
1819 } | |
1820 if (!mov->found_moov) { | |
1821 av_log(s, AV_LOG_ERROR, "moov atom not found\n"); | |
1845 | 1822 return -1; |
1823 } | |
3205 | 1824 dprintf(mov->fc, "on_parse_exit_offset=%lld\n", url_ftell(pb)); |
1845 | 1825 |
1826 return 0; | |
1827 } | |
1828 | |
1829 static int mov_read_packet(AVFormatContext *s, AVPacket *pkt) | |
1830 { | |
1831 MOVContext *mov = s->priv_data; | |
1832 MOVStreamContext *sc = 0; | |
1833 AVIndexEntry *sample = 0; | |
1834 int64_t best_dts = INT64_MAX; | |
1835 int i; | |
3170 | 1836 retry: |
2823 | 1837 for (i = 0; i < s->nb_streams; i++) { |
2824
ecbfaa8712a1
do not retain useless pointers to avstream priv_data, use it directly
bcoudurier
parents:
2823
diff
changeset
|
1838 AVStream *st = s->streams[i]; |
ecbfaa8712a1
do not retain useless pointers to avstream priv_data, use it directly
bcoudurier
parents:
2823
diff
changeset
|
1839 MOVStreamContext *msc = st->priv_data; |
3085
bae59276377f
support mov reference files, ref.mov/ref.m2v/ref.wav and detect BrianCox.mov
bcoudurier
parents:
3084
diff
changeset
|
1840 if (st->discard != AVDISCARD_ALL && msc->pb && msc->current_sample < msc->sample_count) { |
2824
ecbfaa8712a1
do not retain useless pointers to avstream priv_data, use it directly
bcoudurier
parents:
2823
diff
changeset
|
1841 AVIndexEntry *current_sample = &st->index_entries[msc->current_sample]; |
2902 | 1842 int64_t dts = av_rescale(current_sample->timestamp * (int64_t)msc->time_rate, |
1843 AV_TIME_BASE, msc->time_scale); | |
2030 | 1844 dprintf(s, "stream %d, sample %d, dts %"PRId64"\n", i, msc->current_sample, dts); |
2817 | 1845 if (!sample || (url_is_streamed(s->pb) && current_sample->pos < sample->pos) || |
1846 (!url_is_streamed(s->pb) && | |
3085
bae59276377f
support mov reference files, ref.mov/ref.m2v/ref.wav and detect BrianCox.mov
bcoudurier
parents:
3084
diff
changeset
|
1847 ((msc->pb != s->pb && dts < best_dts) || (msc->pb == s->pb && |
2817 | 1848 ((FFABS(best_dts - dts) <= AV_TIME_BASE && current_sample->pos < sample->pos) || |
3085
bae59276377f
support mov reference files, ref.mov/ref.m2v/ref.wav and detect BrianCox.mov
bcoudurier
parents:
3084
diff
changeset
|
1849 (FFABS(best_dts - dts) > AV_TIME_BASE && dts < best_dts)))))) { |
1845 | 1850 sample = current_sample; |
1851 best_dts = dts; | |
1852 sc = msc; | |
1853 } | |
1854 } | |
1855 } | |
3170 | 1856 if (!sample) { |
1857 mov->found_mdat = 0; | |
1858 if (!url_is_streamed(s->pb) || | |
1859 mov_read_default(mov, s->pb, (MOV_atom_t){ 0, 0, INT64_MAX }) < 0 || | |
1860 url_feof(s->pb)) | |
1861 return -1; | |
1862 dprintf(s, "read fragments, offset 0x%llx\n", url_ftell(s->pb)); | |
1863 goto retry; | |
1864 } | |
1845 | 1865 /* must be done just before reading, to avoid infinite loop on sample */ |
1866 sc->current_sample++; | |
3085
bae59276377f
support mov reference files, ref.mov/ref.m2v/ref.wav and detect BrianCox.mov
bcoudurier
parents:
3084
diff
changeset
|
1867 if (url_fseek(sc->pb, sample->pos, SEEK_SET) != sample->pos) { |
2902 | 1868 av_log(mov->fc, AV_LOG_ERROR, "stream %d, offset 0x%"PRIx64": partial file\n", |
1869 sc->ffindex, sample->pos); | |
1845 | 1870 return -1; |
1871 } | |
3085
bae59276377f
support mov reference files, ref.mov/ref.m2v/ref.wav and detect BrianCox.mov
bcoudurier
parents:
3084
diff
changeset
|
1872 av_get_packet(sc->pb, pkt, sample->size); |
1845 | 1873 #ifdef CONFIG_DV_DEMUXER |
3027 | 1874 if (mov->dv_demux && sc->dv_audio_container) { |
1875 dv_produce_packet(mov->dv_demux, pkt, pkt->data, pkt->size); | |
1876 av_free(pkt->data); | |
3034 | 1877 pkt->size = 0; |
1878 if (dv_get_packet(mov->dv_demux, pkt) < 0) | |
1879 return -1; | |
3027 | 1880 } |
1845 | 1881 #endif |
1882 pkt->stream_index = sc->ffindex; | |
1883 pkt->dts = sample->timestamp; | |
1884 if (sc->ctts_data) { | |
1885 assert(sc->ctts_data[sc->sample_to_ctime_index].duration % sc->time_rate == 0); | |
1886 pkt->pts = pkt->dts + sc->ctts_data[sc->sample_to_ctime_index].duration / sc->time_rate; | |
1887 /* update ctts context */ | |
1888 sc->sample_to_ctime_sample++; | |
2902 | 1889 if (sc->sample_to_ctime_index < sc->ctts_count && |
1890 sc->ctts_data[sc->sample_to_ctime_index].count == sc->sample_to_ctime_sample) { | |
1845 | 1891 sc->sample_to_ctime_index++; |
1892 sc->sample_to_ctime_sample = 0; | |
1893 } | |
1894 } else { | |
3267 | 1895 AVStream *st = s->streams[sc->ffindex]; |
1896 int64_t next_dts = (sc->current_sample < sc->sample_count) ? | |
1897 st->index_entries[sc->current_sample].timestamp : st->duration; | |
1898 pkt->duration = next_dts - pkt->dts; | |
1845 | 1899 pkt->pts = pkt->dts; |
1900 } | |
1901 pkt->flags |= sample->flags & AVINDEX_KEYFRAME ? PKT_FLAG_KEY : 0; | |
1902 pkt->pos = sample->pos; | |
2902 | 1903 dprintf(s, "stream %d, pts %"PRId64", dts %"PRId64", pos 0x%"PRIx64", duration %d\n", |
1904 pkt->stream_index, pkt->pts, pkt->dts, pkt->pos, pkt->duration); | |
1845 | 1905 return 0; |
1906 } | |
1907 | |
1908 static int mov_seek_stream(AVStream *st, int64_t timestamp, int flags) | |
1909 { | |
1910 MOVStreamContext *sc = st->priv_data; | |
1911 int sample, time_sample; | |
1912 int i; | |
1913 | |
1914 sample = av_index_search_timestamp(st, timestamp, flags); | |
1907 | 1915 dprintf(st->codec, "stream %d, timestamp %"PRId64", sample %d\n", st->index, timestamp, sample); |
1845 | 1916 if (sample < 0) /* not sure what to do */ |
1917 return -1; | |
1918 sc->current_sample = sample; | |
2030 | 1919 dprintf(st->codec, "stream %d, found sample %d\n", st->index, sc->current_sample); |
1845 | 1920 /* adjust ctts index */ |
1921 if (sc->ctts_data) { | |
1922 time_sample = 0; | |
1923 for (i = 0; i < sc->ctts_count; i++) { | |
2083
2c3887f02739
fix ctts index computation when seeking, check must be done against next ctts sample, thanks to Uoti
bcoudurier
parents:
2046
diff
changeset
|
1924 int next = time_sample + sc->ctts_data[i].count; |
2c3887f02739
fix ctts index computation when seeking, check must be done against next ctts sample, thanks to Uoti
bcoudurier
parents:
2046
diff
changeset
|
1925 if (next > sc->current_sample) { |
1845 | 1926 sc->sample_to_ctime_index = i; |
2083
2c3887f02739
fix ctts index computation when seeking, check must be done against next ctts sample, thanks to Uoti
bcoudurier
parents:
2046
diff
changeset
|
1927 sc->sample_to_ctime_sample = sc->current_sample - time_sample; |
1845 | 1928 break; |
1929 } | |
2083
2c3887f02739
fix ctts index computation when seeking, check must be done against next ctts sample, thanks to Uoti
bcoudurier
parents:
2046
diff
changeset
|
1930 time_sample = next; |
1845 | 1931 } |
1932 } | |
1933 return sample; | |
1934 } | |
1935 | |
1936 static int mov_read_seek(AVFormatContext *s, int stream_index, int64_t sample_time, int flags) | |
1937 { | |
1938 AVStream *st; | |
1939 int64_t seek_timestamp, timestamp; | |
1940 int sample; | |
1941 int i; | |
1942 | |
1943 if (stream_index >= s->nb_streams) | |
1944 return -1; | |
1945 | |
1946 st = s->streams[stream_index]; | |
1947 sample = mov_seek_stream(st, sample_time, flags); | |
1948 if (sample < 0) | |
1949 return -1; | |
1950 | |
1951 /* adjust seek timestamp to found sample timestamp */ | |
1952 seek_timestamp = st->index_entries[sample].timestamp; | |
1953 | |
1954 for (i = 0; i < s->nb_streams; i++) { | |
1955 st = s->streams[i]; | |
1956 if (stream_index == i || st->discard == AVDISCARD_ALL) | |
1957 continue; | |
1958 | |
1959 timestamp = av_rescale_q(seek_timestamp, s->streams[stream_index]->time_base, st->time_base); | |
1960 mov_seek_stream(st, timestamp, flags); | |
1961 } | |
1962 return 0; | |
1963 } | |
1964 | |
1965 static int mov_read_close(AVFormatContext *s) | |
1966 { | |
3085
bae59276377f
support mov reference files, ref.mov/ref.m2v/ref.wav and detect BrianCox.mov
bcoudurier
parents:
3084
diff
changeset
|
1967 int i, j; |
2006 | 1968 MOVContext *mov = s->priv_data; |
2823 | 1969 for(i=0; i<s->nb_streams; i++) { |
2824
ecbfaa8712a1
do not retain useless pointers to avstream priv_data, use it directly
bcoudurier
parents:
2823
diff
changeset
|
1970 MOVStreamContext *sc = s->streams[i]->priv_data; |
ecbfaa8712a1
do not retain useless pointers to avstream priv_data, use it directly
bcoudurier
parents:
2823
diff
changeset
|
1971 av_freep(&sc->ctts_data); |
3085
bae59276377f
support mov reference files, ref.mov/ref.m2v/ref.wav and detect BrianCox.mov
bcoudurier
parents:
3084
diff
changeset
|
1972 for (j=0; j<sc->drefs_count; j++) |
bae59276377f
support mov reference files, ref.mov/ref.m2v/ref.wav and detect BrianCox.mov
bcoudurier
parents:
3084
diff
changeset
|
1973 av_freep(&sc->drefs[j].path); |
bae59276377f
support mov reference files, ref.mov/ref.m2v/ref.wav and detect BrianCox.mov
bcoudurier
parents:
3084
diff
changeset
|
1974 av_freep(&sc->drefs); |
bae59276377f
support mov reference files, ref.mov/ref.m2v/ref.wav and detect BrianCox.mov
bcoudurier
parents:
3084
diff
changeset
|
1975 if (sc->pb && sc->pb != s->pb) |
bae59276377f
support mov reference files, ref.mov/ref.m2v/ref.wav and detect BrianCox.mov
bcoudurier
parents:
3084
diff
changeset
|
1976 url_fclose(sc->pb); |
2084 | 1977 } |
1845 | 1978 if(mov->dv_demux){ |
1979 for(i=0; i<mov->dv_fctx->nb_streams; i++){ | |
1980 av_freep(&mov->dv_fctx->streams[i]->codec); | |
1981 av_freep(&mov->dv_fctx->streams[i]); | |
1982 } | |
1983 av_freep(&mov->dv_fctx); | |
1984 av_freep(&mov->dv_demux); | |
1985 } | |
3169 | 1986 av_freep(&mov->trex_data); |
1845 | 1987 return 0; |
1988 } | |
1989 | |
1990 AVInputFormat mov_demuxer = { | |
1991 "mov,mp4,m4a,3gp,3g2,mj2", | |
3424
7a0230981402
Make long_names in lavf/lavdev optional depending on CONFIG_SMALL.
diego
parents:
3362
diff
changeset
|
1992 NULL_IF_CONFIG_SMALL("QuickTime/MPEG-4/Motion JPEG 2000 format"), |
1845 | 1993 sizeof(MOVContext), |
1994 mov_probe, | |
1995 mov_read_header, | |
1996 mov_read_packet, | |
1997 mov_read_close, | |
1998 mov_read_seek, | |
1999 }; |