Mercurial > libavformat.hg
annotate mov.c @ 3717:f65dc584662d libavformat
matroskadec: list some more ebml IDs found in the wild and that we ignore
This avoid printing some warnings about unknow IDs while we in fact know
the IDs but just want to knowingly ignore them.
author | aurel |
---|---|
date | Wed, 13 Aug 2008 21:15:15 +0000 |
parents | 3a7f7509bf3c |
children | 0c46eb1cd9b3 |
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; | |
568 default: | |
569 break; | |
570 } | |
571 } | |
572 return 0; | |
573 } | |
574 | |
575 /* FIXME modify qdm2/svq3/h264 decoders to take full atom as extradata */ | |
576 static int mov_read_extradata(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom) | |
577 { | |
578 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
|
579 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
|
580 uint8_t *buf; |
960795567b33
append extradata atoms when parsing, fix OLOCOONS_O3.mov
bcoudurier
parents:
2547
diff
changeset
|
581 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
|
582 return -1; |
960795567b33
append extradata atoms when parsing, fix OLOCOONS_O3.mov
bcoudurier
parents:
2547
diff
changeset
|
583 buf= av_realloc(st->codec->extradata, size); |
960795567b33
append extradata atoms when parsing, fix OLOCOONS_O3.mov
bcoudurier
parents:
2547
diff
changeset
|
584 if(!buf) |
1845 | 585 return -1; |
2589
960795567b33
append extradata atoms when parsing, fix OLOCOONS_O3.mov
bcoudurier
parents:
2547
diff
changeset
|
586 st->codec->extradata= buf; |
960795567b33
append extradata atoms when parsing, fix OLOCOONS_O3.mov
bcoudurier
parents:
2547
diff
changeset
|
587 buf+= st->codec->extradata_size; |
960795567b33
append extradata atoms when parsing, fix OLOCOONS_O3.mov
bcoudurier
parents:
2547
diff
changeset
|
588 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
|
589 AV_WB32( buf , atom.size + 8); |
960795567b33
append extradata atoms when parsing, fix OLOCOONS_O3.mov
bcoudurier
parents:
2547
diff
changeset
|
590 AV_WL32( buf + 4, atom.type); |
960795567b33
append extradata atoms when parsing, fix OLOCOONS_O3.mov
bcoudurier
parents:
2547
diff
changeset
|
591 get_buffer(pb, buf + 8, atom.size); |
1845 | 592 return 0; |
593 } | |
594 | |
595 static int mov_read_wave(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom) | |
596 { | |
597 AVStream *st = c->fc->streams[c->fc->nb_streams-1]; | |
598 | |
599 if((uint64_t)atom.size > (1<<30)) | |
600 return -1; | |
601 | |
602 if (st->codec->codec_id == CODEC_ID_QDM2) { | |
603 // pass all frma atom to codec, needed at least for QDM2 | |
604 av_free(st->codec->extradata); | |
3076 | 605 st->codec->extradata = av_mallocz(atom.size + FF_INPUT_BUFFER_PADDING_SIZE); |
606 if (!st->codec->extradata) | |
607 return AVERROR(ENOMEM); | |
1845 | 608 st->codec->extradata_size = atom.size; |
3076 | 609 get_buffer(pb, st->codec->extradata, atom.size); |
1845 | 610 } 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
|
611 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
|
612 return -1; |
1845 | 613 } else |
614 url_fskip(pb, atom.size); | |
615 return 0; | |
616 } | |
617 | |
2837
1caef0e2fb46
supports glbl atom containing generic extradata for all codecs
bcoudurier
parents:
2826
diff
changeset
|
618 /** |
1caef0e2fb46
supports glbl atom containing generic extradata for all codecs
bcoudurier
parents:
2826
diff
changeset
|
619 * 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
|
620 * nor size unlike mov_read_extradata. |
1caef0e2fb46
supports glbl atom containing generic extradata for all codecs
bcoudurier
parents:
2826
diff
changeset
|
621 */ |
1caef0e2fb46
supports glbl atom containing generic extradata for all codecs
bcoudurier
parents:
2826
diff
changeset
|
622 static int mov_read_glbl(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom) |
1845 | 623 { |
624 AVStream *st = c->fc->streams[c->fc->nb_streams-1]; | |
625 | |
626 if((uint64_t)atom.size > (1<<30)) | |
627 return -1; | |
628 | |
629 av_free(st->codec->extradata); | |
3076 | 630 st->codec->extradata = av_mallocz(atom.size + FF_INPUT_BUFFER_PADDING_SIZE); |
631 if (!st->codec->extradata) | |
632 return AVERROR(ENOMEM); | |
1845 | 633 st->codec->extradata_size = atom.size; |
3076 | 634 get_buffer(pb, st->codec->extradata, atom.size); |
1845 | 635 return 0; |
636 } | |
637 | |
638 static int mov_read_stco(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom) | |
639 { | |
640 AVStream *st = c->fc->streams[c->fc->nb_streams-1]; | |
2006 | 641 MOVStreamContext *sc = st->priv_data; |
1845 | 642 unsigned int i, entries; |
643 | |
644 get_byte(pb); /* version */ | |
3145 | 645 get_be24(pb); /* flags */ |
1845 | 646 |
647 entries = get_be32(pb); | |
648 | |
649 if(entries >= UINT_MAX/sizeof(int64_t)) | |
650 return -1; | |
651 | |
652 sc->chunk_count = entries; | |
653 sc->chunk_offsets = av_malloc(entries * sizeof(int64_t)); | |
654 if (!sc->chunk_offsets) | |
655 return -1; | |
3254 | 656 if (atom.type == MKTAG('s','t','c','o')) |
657 for(i=0; i<entries; i++) | |
1845 | 658 sc->chunk_offsets[i] = get_be32(pb); |
3254 | 659 else if (atom.type == MKTAG('c','o','6','4')) |
660 for(i=0; i<entries; i++) | |
1845 | 661 sc->chunk_offsets[i] = get_be64(pb); |
3254 | 662 else |
1845 | 663 return -1; |
664 | |
665 return 0; | |
666 } | |
667 | |
3625 | 668 /** |
669 * Compute codec id for 'lpcm' tag. | |
670 * See CoreAudioTypes and AudioStreamBasicDescription at Apple. | |
671 */ | |
672 static int mov_get_lpcm_codec_id(int bps, int flags) | |
673 { | |
674 if (flags & 1) { // floating point | |
675 if (flags & 2) { // big endian | |
676 if (bps == 32) return CODEC_ID_PCM_F32BE; | |
677 //else if (bps == 64) return CODEC_ID_PCM_F64BE; | |
678 } else { | |
679 //if (bps == 32) return CODEC_ID_PCM_F32LE; | |
680 //else if (bps == 64) return CODEC_ID_PCM_F64LE; | |
681 } | |
682 } else { | |
683 if (flags & 2) { | |
684 if (bps == 8) | |
685 // signed integer | |
686 if (flags & 4) return CODEC_ID_PCM_S8; | |
687 else return CODEC_ID_PCM_U8; | |
688 else if (bps == 16) return CODEC_ID_PCM_S16BE; | |
689 else if (bps == 24) return CODEC_ID_PCM_S24BE; | |
690 else if (bps == 32) return CODEC_ID_PCM_S32BE; | |
691 } else { | |
692 if (bps == 8) | |
693 if (flags & 4) return CODEC_ID_PCM_S8; | |
694 else return CODEC_ID_PCM_U8; | |
3626 | 695 else if (bps == 16) return CODEC_ID_PCM_S16LE; |
3625 | 696 else if (bps == 24) return CODEC_ID_PCM_S24LE; |
697 else if (bps == 32) return CODEC_ID_PCM_S32LE; | |
698 } | |
699 } | |
700 return 0; | |
701 } | |
702 | |
1845 | 703 static int mov_read_stsd(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom) |
704 { | |
705 AVStream *st = c->fc->streams[c->fc->nb_streams-1]; | |
2006 | 706 MOVStreamContext *sc = st->priv_data; |
3263 | 707 int j, entries, pseudo_stream_id; |
1845 | 708 |
709 get_byte(pb); /* version */ | |
3145 | 710 get_be24(pb); /* flags */ |
1845 | 711 |
712 entries = get_be32(pb); | |
713 | |
3167 | 714 for(pseudo_stream_id=0; pseudo_stream_id<entries; pseudo_stream_id++) { |
715 //Parsing Sample description table | |
1845 | 716 enum CodecID id; |
3085
bae59276377f
support mov reference files, ref.mov/ref.m2v/ref.wav and detect BrianCox.mov
bcoudurier
parents:
3084
diff
changeset
|
717 int dref_id; |
1845 | 718 MOV_atom_t a = { 0, 0, 0 }; |
719 offset_t start_pos = url_ftell(pb); | |
720 int size = get_be32(pb); /* size */ | |
3263 | 721 uint32_t format = get_le32(pb); /* data format */ |
1845 | 722 |
723 get_be32(pb); /* reserved */ | |
724 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
|
725 dref_id = get_be16(pb); |
1845 | 726 |
3022
800db1ceafc6
Allow the user to select which codec out of several in stsd he wants.
michael
parents:
2974
diff
changeset
|
727 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
|
728 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
|
729 (c->fc->video_codec_id ? codec_get_id(codec_movvideo_tags, format) != c->fc->video_codec_id |
3253 | 730 : 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
|
731 ){ |
3135 | 732 /* Multiple fourcc, we skip JPEG. This is not correct, we should |
733 * export it as a separate AVStream but this needs a few changes | |
734 * in the MOV demuxer, patch welcome. */ | |
3300 | 735 av_log(c->fc, AV_LOG_WARNING, "multiple fourcc not supported\n"); |
1845 | 736 url_fskip(pb, size - (url_ftell(pb) - start_pos)); |
737 continue; | |
738 } | |
3299
80a497804aa8
demux all stsd ids if codec is the same, fix premature_mov_ending.mov, closes #451
bcoudurier
parents:
3286
diff
changeset
|
739 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
|
740 sc->dref_id= dref_id; |
1845 | 741 |
742 st->codec->codec_tag = format; | |
1847
922180a45610
recommit of the change below after reverting earlier cosmetic-functional mix
michael
parents:
1846
diff
changeset
|
743 id = codec_get_id(codec_movaudio_tags, format); |
3253 | 744 if (id<=0 && (format&0xFFFF) == 'm'+('s'<<8)) |
2298 | 745 id = codec_get_id(codec_wav_tags, bswap_32(format)&0xFFFF); |
746 | |
1845 | 747 if (st->codec->codec_type != CODEC_TYPE_VIDEO && id > 0) { |
748 st->codec->codec_type = CODEC_TYPE_AUDIO; | |
749 } else if (st->codec->codec_type != CODEC_TYPE_AUDIO && /* do not overwrite codec type */ | |
3253 | 750 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
|
751 id = codec_get_id(codec_movvideo_tags, format); |
1845 | 752 if (id <= 0) |
753 id = codec_get_id(codec_bmp_tags, format); | |
754 if (id > 0) | |
755 st->codec->codec_type = CODEC_TYPE_VIDEO; | |
2969 | 756 else if(st->codec->codec_type == CODEC_TYPE_DATA){ |
757 id = codec_get_id(ff_codec_movsubtitle_tags, format); | |
758 if(id > 0) | |
759 st->codec->codec_type = CODEC_TYPE_SUBTITLE; | |
760 } | |
1845 | 761 } |
762 | |
2902 | 763 dprintf(c->fc, "size=%d 4CC= %c%c%c%c codec_type=%d\n", size, |
764 (format >> 0) & 0xff, (format >> 8) & 0xff, (format >> 16) & 0xff, | |
765 (format >> 24) & 0xff, st->codec->codec_type); | |
1845 | 766 |
767 if(st->codec->codec_type==CODEC_TYPE_VIDEO) { | |
3263 | 768 uint8_t codec_name[32]; |
769 unsigned int color_depth; | |
770 int color_greyscale; | |
771 | |
1845 | 772 st->codec->codec_id = id; |
773 get_be16(pb); /* version */ | |
774 get_be16(pb); /* revision level */ | |
775 get_be32(pb); /* vendor */ | |
776 get_be32(pb); /* temporal quality */ | |
2730 | 777 get_be32(pb); /* spatial quality */ |
1845 | 778 |
779 st->codec->width = get_be16(pb); /* width */ | |
780 st->codec->height = get_be16(pb); /* height */ | |
781 | |
782 get_be32(pb); /* horiz resolution */ | |
783 get_be32(pb); /* vert resolution */ | |
784 get_be32(pb); /* data size, always 0 */ | |
3264 | 785 get_be16(pb); /* frames per samples */ |
2044 | 786 |
3265 | 787 get_buffer(pb, codec_name, 32); /* codec name, pascal string */ |
1845 | 788 if (codec_name[0] <= 31) { |
789 memcpy(st->codec->codec_name, &codec_name[1],codec_name[0]); | |
790 st->codec->codec_name[codec_name[0]] = 0; | |
791 } | |
792 | |
793 st->codec->bits_per_sample = get_be16(pb); /* depth */ | |
794 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
|
795 dprintf(c->fc, "depth %d, ctab id %d\n", |
da04b574d131
set codec bps to grayscale bits, fix 256grey.mov
bcoudurier
parents:
3093
diff
changeset
|
796 st->codec->bits_per_sample, st->codec->color_table_id); |
1845 | 797 /* figure out the palette situation */ |
798 color_depth = st->codec->bits_per_sample & 0x1F; | |
799 color_greyscale = st->codec->bits_per_sample & 0x20; | |
800 | |
801 /* if the depth is 2, 4, or 8 bpp, file is palettized */ | |
802 if ((color_depth == 2) || (color_depth == 4) || | |
803 (color_depth == 8)) { | |
3257 | 804 /* for palette traversal */ |
805 unsigned int color_start, color_count, color_end; | |
806 unsigned char r, g, b; | |
807 | |
1845 | 808 if (color_greyscale) { |
3257 | 809 int color_index, color_dec; |
1845 | 810 /* compute the greyscale palette */ |
3095
da04b574d131
set codec bps to grayscale bits, fix 256grey.mov
bcoudurier
parents:
3093
diff
changeset
|
811 st->codec->bits_per_sample = color_depth; |
1845 | 812 color_count = 1 << color_depth; |
813 color_index = 255; | |
814 color_dec = 256 / (color_count - 1); | |
815 for (j = 0; j < color_count; j++) { | |
816 r = g = b = color_index; | |
817 c->palette_control.palette[j] = | |
818 (r << 16) | (g << 8) | (b); | |
819 color_index -= color_dec; | |
820 if (color_index < 0) | |
821 color_index = 0; | |
822 } | |
3179
5f56b694f9bf
according to specs, only color table id set to 0, have it in stsd, fix 4colors.mov
bcoudurier
parents:
3178
diff
changeset
|
823 } else if (st->codec->color_table_id) { |
3257 | 824 const uint8_t *color_table; |
1845 | 825 /* if flag bit 3 is set, use the default palette */ |
826 color_count = 1 << color_depth; | |
827 if (color_depth == 2) | |
828 color_table = ff_qt_default_palette_4; | |
829 else if (color_depth == 4) | |
830 color_table = ff_qt_default_palette_16; | |
831 else | |
832 color_table = ff_qt_default_palette_256; | |
833 | |
834 for (j = 0; j < color_count; j++) { | |
835 r = color_table[j * 4 + 0]; | |
836 g = color_table[j * 4 + 1]; | |
837 b = color_table[j * 4 + 2]; | |
838 c->palette_control.palette[j] = | |
839 (r << 16) | (g << 8) | (b); | |
840 } | |
841 } else { | |
842 /* load the palette from the file */ | |
843 color_start = get_be32(pb); | |
844 color_count = get_be16(pb); | |
845 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
|
846 if ((color_start <= 255) && |
17086a526938
Check sanity in the palette loading operation. The addresses a potential security risk in
melanson
parents:
2807
diff
changeset
|
847 (color_end <= 255)) { |
2810 | 848 for (j = color_start; j <= color_end; j++) { |
849 /* each R, G, or B component is 16 bits; | |
850 * only use the top 8 bits; skip alpha bytes | |
851 * up front */ | |
852 get_byte(pb); | |
853 get_byte(pb); | |
854 r = get_byte(pb); | |
855 get_byte(pb); | |
856 g = get_byte(pb); | |
857 get_byte(pb); | |
858 b = get_byte(pb); | |
859 get_byte(pb); | |
860 c->palette_control.palette[j] = | |
861 (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
|
862 } |
1845 | 863 } |
864 } | |
865 st->codec->palctrl = &c->palette_control; | |
866 st->codec->palctrl->palette_changed = 1; | |
867 } else | |
868 st->codec->palctrl = NULL; | |
869 } else if(st->codec->codec_type==CODEC_TYPE_AUDIO) { | |
3622 | 870 int bits_per_sample, flags; |
1845 | 871 uint16_t version = get_be16(pb); |
872 | |
873 st->codec->codec_id = id; | |
874 get_be16(pb); /* revision level */ | |
875 get_be32(pb); /* vendor */ | |
876 | |
877 st->codec->channels = get_be16(pb); /* channel count */ | |
1907 | 878 dprintf(c->fc, "audio channels %d\n", st->codec->channels); |
1845 | 879 st->codec->bits_per_sample = get_be16(pb); /* sample size */ |
880 | |
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
|
881 sc->audio_cid = get_be16(pb); |
1845 | 882 get_be16(pb); /* packet size = 0 */ |
883 | |
884 st->codec->sample_rate = ((get_be32(pb) >> 16)); | |
885 | |
3619
bd4b7c8fec83
move version specific parsing code before codec specific code, will be needed
bcoudurier
parents:
3615
diff
changeset
|
886 //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
|
887 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
|
888 if(!c->isom) { |
bd4b7c8fec83
move version specific parsing code before codec specific code, will be needed
bcoudurier
parents:
3615
diff
changeset
|
889 if(version==1) { |
bd4b7c8fec83
move version specific parsing code before codec specific code, will be needed
bcoudurier
parents:
3615
diff
changeset
|
890 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
|
891 get_be32(pb); /* bytes per packet */ |
bd4b7c8fec83
move version specific parsing code before codec specific code, will be needed
bcoudurier
parents:
3615
diff
changeset
|
892 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
|
893 get_be32(pb); /* bytes per sample */ |
bd4b7c8fec83
move version specific parsing code before codec specific code, will be needed
bcoudurier
parents:
3615
diff
changeset
|
894 } else if(version==2) { |
bd4b7c8fec83
move version specific parsing code before codec specific code, will be needed
bcoudurier
parents:
3615
diff
changeset
|
895 get_be32(pb); /* sizeof struct only */ |
bd4b7c8fec83
move version specific parsing code before codec specific code, will be needed
bcoudurier
parents:
3615
diff
changeset
|
896 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
|
897 st->codec->channels = get_be32(pb); |
bd4b7c8fec83
move version specific parsing code before codec specific code, will be needed
bcoudurier
parents:
3615
diff
changeset
|
898 get_be32(pb); /* always 0x7F000000 */ |
3620 | 899 st->codec->bits_per_sample = get_be32(pb); /* bits per channel if sound is uncompressed */ |
3622 | 900 flags = get_be32(pb); /* lcpm format specific flag */ |
3620 | 901 sc->bytes_per_frame = get_be32(pb); /* bytes per audio packet if constant */ |
902 sc->samples_per_frame = get_be32(pb); /* lpcm frames per audio packet if constant */ | |
3625 | 903 if (format == MKTAG('l','p','c','m')) |
904 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
|
905 } |
bd4b7c8fec83
move version specific parsing code before codec specific code, will be needed
bcoudurier
parents:
3615
diff
changeset
|
906 } |
bd4b7c8fec83
move version specific parsing code before codec specific code, will be needed
bcoudurier
parents:
3615
diff
changeset
|
907 |
1845 | 908 switch (st->codec->codec_id) { |
909 case CODEC_ID_PCM_S8: | |
910 case CODEC_ID_PCM_U8: | |
911 if (st->codec->bits_per_sample == 16) | |
912 st->codec->codec_id = CODEC_ID_PCM_S16BE; | |
913 break; | |
914 case CODEC_ID_PCM_S16LE: | |
915 case CODEC_ID_PCM_S16BE: | |
916 if (st->codec->bits_per_sample == 8) | |
917 st->codec->codec_id = CODEC_ID_PCM_S8; | |
918 else if (st->codec->bits_per_sample == 24) | |
3621
0415fc41780a
keep original codec/fourcc endianness, fix XDCAMHD.mov
bcoudurier
parents:
3620
diff
changeset
|
919 st->codec->codec_id = |
0415fc41780a
keep original codec/fourcc endianness, fix XDCAMHD.mov
bcoudurier
parents:
3620
diff
changeset
|
920 st->codec->codec_id == CODEC_ID_PCM_S16BE ? |
0415fc41780a
keep original codec/fourcc endianness, fix XDCAMHD.mov
bcoudurier
parents:
3620
diff
changeset
|
921 CODEC_ID_PCM_S24BE : CODEC_ID_PCM_S24LE; |
1845 | 922 break; |
3036
62181fbfc128
remove messy and not always correct chunk size workaround, use correct values instead
bcoudurier
parents:
3034
diff
changeset
|
923 /* 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
|
924 case CODEC_ID_MACE3: |
62181fbfc128
remove messy and not always correct chunk size workaround, use correct values instead
bcoudurier
parents:
3034
diff
changeset
|
925 sc->samples_per_frame = 6; |
62181fbfc128
remove messy and not always correct chunk size workaround, use correct values instead
bcoudurier
parents:
3034
diff
changeset
|
926 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
|
927 break; |
62181fbfc128
remove messy and not always correct chunk size workaround, use correct values instead
bcoudurier
parents:
3034
diff
changeset
|
928 case CODEC_ID_MACE6: |
62181fbfc128
remove messy and not always correct chunk size workaround, use correct values instead
bcoudurier
parents:
3034
diff
changeset
|
929 sc->samples_per_frame = 6; |
62181fbfc128
remove messy and not always correct chunk size workaround, use correct values instead
bcoudurier
parents:
3034
diff
changeset
|
930 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
|
931 break; |
62181fbfc128
remove messy and not always correct chunk size workaround, use correct values instead
bcoudurier
parents:
3034
diff
changeset
|
932 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
|
933 sc->samples_per_frame = 64; |
62181fbfc128
remove messy and not always correct chunk size workaround, use correct values instead
bcoudurier
parents:
3034
diff
changeset
|
934 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
|
935 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
|
936 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
|
937 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
|
938 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
|
939 break; |
1845 | 940 default: |
941 break; | |
942 } | |
943 | |
944 bits_per_sample = av_get_bits_per_sample(st->codec->codec_id); | |
945 if (bits_per_sample) { | |
946 st->codec->bits_per_sample = bits_per_sample; | |
947 sc->sample_size = (bits_per_sample >> 3) * st->codec->channels; | |
948 } | |
2972
bc330130bdce
Set subtitle codec id correctly, i hope this does not break anything.
michael
parents:
2970
diff
changeset
|
949 } 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
|
950 st->codec->codec_id= id; |
1845 | 951 } else { |
952 /* other codec type, just skip (rtp, mp4s, tmcd ...) */ | |
953 url_fskip(pb, size - (url_ftell(pb) - start_pos)); | |
954 } | |
955 /* this will read extra atoms at the end (wave, alac, damr, avcC, SMI ...) */ | |
956 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
|
957 if (a.size > 8) { |
1ce39cda4a59
check mov_read_default return value where appropriate, patch by takis, fix issue 285
bcoudurier
parents:
2794
diff
changeset
|
958 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
|
959 return -1; |
1ce39cda4a59
check mov_read_default return value where appropriate, patch by takis, fix issue 285
bcoudurier
parents:
2794
diff
changeset
|
960 } else if (a.size > 0) |
1845 | 961 url_fskip(pb, a.size); |
962 } | |
963 | |
3084 | 964 if(st->codec->codec_type==CODEC_TYPE_AUDIO && st->codec->sample_rate==0 && sc->time_scale>1) |
1845 | 965 st->codec->sample_rate= sc->time_scale; |
966 | |
967 /* special codec parameters handling */ | |
968 switch (st->codec->codec_id) { | |
969 #ifdef CONFIG_DV_DEMUXER | |
970 case CODEC_ID_DVAUDIO: | |
971 c->dv_fctx = av_alloc_format_context(); | |
972 c->dv_demux = dv_init_demux(c->dv_fctx); | |
973 if (!c->dv_demux) { | |
974 av_log(c->fc, AV_LOG_ERROR, "dv demux context init error\n"); | |
975 return -1; | |
976 } | |
977 sc->dv_audio_container = 1; | |
978 st->codec->codec_id = CODEC_ID_PCM_S16LE; | |
979 break; | |
980 #endif | |
981 /* no ifdef since parameters are always those */ | |
982 case CODEC_ID_AMR_WB: | |
983 st->codec->sample_rate= 16000; | |
984 st->codec->channels= 1; /* really needed */ | |
985 break; | |
3245
9f25267bee44
demux qcelp, so this can work with soc decoder and stream copy
bcoudurier
parents:
3242
diff
changeset
|
986 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
|
987 case CODEC_ID_AMR_NB: |
3258 | 988 st->codec->frame_size= sc->samples_per_frame; |
1845 | 989 st->codec->sample_rate= 8000; |
990 st->codec->channels= 1; /* really needed */ | |
991 break; | |
992 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
|
993 case CODEC_ID_MP3: |
1845 | 994 st->codec->codec_type = CODEC_TYPE_AUDIO; /* force type after stsd for m1a hdlr */ |
2023 | 995 st->need_parsing = AVSTREAM_PARSE_FULL; |
1845 | 996 break; |
3187 | 997 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
|
998 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
|
999 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
|
1000 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
|
1001 break; |
3242 | 1002 case CODEC_ID_ALAC: |
1003 if (st->codec->extradata_size == 36) | |
1004 st->codec->frame_size = AV_RB32((st->codec->extradata+12)); | |
1005 break; | |
1845 | 1006 default: |
1007 break; | |
1008 } | |
1009 | |
1010 return 0; | |
1011 } | |
1012 | |
1013 static int mov_read_stsc(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom) | |
1014 { | |
1015 AVStream *st = c->fc->streams[c->fc->nb_streams-1]; | |
2006 | 1016 MOVStreamContext *sc = st->priv_data; |
1845 | 1017 unsigned int i, entries; |
1018 | |
1019 get_byte(pb); /* version */ | |
3145 | 1020 get_be24(pb); /* flags */ |
1845 | 1021 |
1022 entries = get_be32(pb); | |
1023 | |
2045
aa5e56700fdf
cosmectics, use consistant and homogeneous type names for atoms
bcoudurier
parents:
2044
diff
changeset
|
1024 if(entries >= UINT_MAX / sizeof(MOV_stsc_t)) |
1845 | 1025 return -1; |
1026 | |
2044 | 1027 dprintf(c->fc, "track[%i].stsc.entries = %i\n", c->fc->nb_streams-1, entries); |
1028 | |
1845 | 1029 sc->sample_to_chunk_sz = entries; |
2045
aa5e56700fdf
cosmectics, use consistant and homogeneous type names for atoms
bcoudurier
parents:
2044
diff
changeset
|
1030 sc->sample_to_chunk = av_malloc(entries * sizeof(MOV_stsc_t)); |
1845 | 1031 if (!sc->sample_to_chunk) |
1032 return -1; | |
1033 for(i=0; i<entries; i++) { | |
1034 sc->sample_to_chunk[i].first = get_be32(pb); | |
1035 sc->sample_to_chunk[i].count = get_be32(pb); | |
1036 sc->sample_to_chunk[i].id = get_be32(pb); | |
1037 } | |
1038 return 0; | |
1039 } | |
1040 | |
1041 static int mov_read_stss(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom) | |
1042 { | |
1043 AVStream *st = c->fc->streams[c->fc->nb_streams-1]; | |
2006 | 1044 MOVStreamContext *sc = st->priv_data; |
1845 | 1045 unsigned int i, entries; |
1046 | |
1047 get_byte(pb); /* version */ | |
3145 | 1048 get_be24(pb); /* flags */ |
1845 | 1049 |
1050 entries = get_be32(pb); | |
1051 | |
2030 | 1052 if(entries >= UINT_MAX / sizeof(int)) |
1845 | 1053 return -1; |
1054 | |
1055 sc->keyframe_count = entries; | |
2044 | 1056 |
1057 dprintf(c->fc, "keyframe_count = %d\n", sc->keyframe_count); | |
1058 | |
2030 | 1059 sc->keyframes = av_malloc(entries * sizeof(int)); |
1845 | 1060 if (!sc->keyframes) |
1061 return -1; | |
1062 for(i=0; i<entries; i++) { | |
1063 sc->keyframes[i] = get_be32(pb); | |
2044 | 1064 //dprintf(c->fc, "keyframes[]=%d\n", sc->keyframes[i]); |
1845 | 1065 } |
1066 return 0; | |
1067 } | |
1068 | |
1069 static int mov_read_stsz(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom) | |
1070 { | |
1071 AVStream *st = c->fc->streams[c->fc->nb_streams-1]; | |
2006 | 1072 MOVStreamContext *sc = st->priv_data; |
1845 | 1073 unsigned int i, entries, sample_size; |
1074 | |
1075 get_byte(pb); /* version */ | |
3145 | 1076 get_be24(pb); /* flags */ |
1845 | 1077 |
1078 sample_size = get_be32(pb); | |
1079 if (!sc->sample_size) /* do not overwrite value computed in stsd */ | |
1080 sc->sample_size = sample_size; | |
1081 entries = get_be32(pb); | |
2030 | 1082 if(entries >= UINT_MAX / sizeof(int)) |
1845 | 1083 return -1; |
1084 | |
1085 sc->sample_count = entries; | |
1086 if (sample_size) | |
1087 return 0; | |
1088 | |
2044 | 1089 dprintf(c->fc, "sample_size = %d sample_count = %d\n", sc->sample_size, sc->sample_count); |
1090 | |
2030 | 1091 sc->sample_sizes = av_malloc(entries * sizeof(int)); |
1845 | 1092 if (!sc->sample_sizes) |
1093 return -1; | |
3156
487b1979f195
remove useless debug print since now mov_build_index will do
bcoudurier
parents:
3155
diff
changeset
|
1094 for(i=0; i<entries; i++) |
1845 | 1095 sc->sample_sizes[i] = get_be32(pb); |
1096 return 0; | |
1097 } | |
1098 | |
1099 static int mov_read_stts(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom) | |
1100 { | |
1101 AVStream *st = c->fc->streams[c->fc->nb_streams-1]; | |
2006 | 1102 MOVStreamContext *sc = st->priv_data; |
1845 | 1103 unsigned int i, entries; |
1104 int64_t duration=0; | |
1105 int64_t total_sample_count=0; | |
1106 | |
1107 get_byte(pb); /* version */ | |
3145 | 1108 get_be24(pb); /* flags */ |
1845 | 1109 entries = get_be32(pb); |
2045
aa5e56700fdf
cosmectics, use consistant and homogeneous type names for atoms
bcoudurier
parents:
2044
diff
changeset
|
1110 if(entries >= UINT_MAX / sizeof(MOV_stts_t)) |
1845 | 1111 return -1; |
1112 | |
1113 sc->stts_count = entries; | |
2045
aa5e56700fdf
cosmectics, use consistant and homogeneous type names for atoms
bcoudurier
parents:
2044
diff
changeset
|
1114 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
|
1115 if (!sc->stts_data) |
5bf4b9df2794
return error if malloc failed, found by takis, fix issue 286
bcoudurier
parents:
2806
diff
changeset
|
1116 return -1; |
2044 | 1117 dprintf(c->fc, "track[%i].stts.entries = %i\n", c->fc->nb_streams-1, entries); |
1845 | 1118 |
1119 sc->time_rate=0; | |
1120 | |
1121 for(i=0; i<entries; i++) { | |
1122 int sample_duration; | |
1123 int sample_count; | |
1124 | |
1125 sample_count=get_be32(pb); | |
1126 sample_duration = get_be32(pb); | |
1127 sc->stts_data[i].count= sample_count; | |
1128 sc->stts_data[i].duration= sample_duration; | |
1129 | |
1130 sc->time_rate= ff_gcd(sc->time_rate, sample_duration); | |
1131 | |
1907 | 1132 dprintf(c->fc, "sample_count=%d, sample_duration=%d\n",sample_count,sample_duration); |
1845 | 1133 |
1134 duration+=(int64_t)sample_duration*sample_count; | |
1135 total_sample_count+=sample_count; | |
1136 } | |
1137 | |
1138 st->nb_frames= total_sample_count; | |
1139 if(duration) | |
1140 st->duration= duration; | |
1141 return 0; | |
1142 } | |
1143 | |
1144 static int mov_read_ctts(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom) | |
1145 { | |
1146 AVStream *st = c->fc->streams[c->fc->nb_streams-1]; | |
2006 | 1147 MOVStreamContext *sc = st->priv_data; |
1845 | 1148 unsigned int i, entries; |
1149 | |
1150 get_byte(pb); /* version */ | |
3145 | 1151 get_be24(pb); /* flags */ |
1845 | 1152 entries = get_be32(pb); |
2045
aa5e56700fdf
cosmectics, use consistant and homogeneous type names for atoms
bcoudurier
parents:
2044
diff
changeset
|
1153 if(entries >= UINT_MAX / sizeof(MOV_stts_t)) |
1845 | 1154 return -1; |
1155 | |
1156 sc->ctts_count = entries; | |
2045
aa5e56700fdf
cosmectics, use consistant and homogeneous type names for atoms
bcoudurier
parents:
2044
diff
changeset
|
1157 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
|
1158 if (!sc->ctts_data) |
5bf4b9df2794
return error if malloc failed, found by takis, fix issue 286
bcoudurier
parents:
2806
diff
changeset
|
1159 return -1; |
1907 | 1160 dprintf(c->fc, "track[%i].ctts.entries = %i\n", c->fc->nb_streams-1, entries); |
1845 | 1161 |
1162 for(i=0; i<entries; i++) { | |
1163 int count =get_be32(pb); | |
1164 int duration =get_be32(pb); | |
1165 | |
1166 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
|
1167 av_log(c->fc, AV_LOG_WARNING, "negative ctts, ignoring\n"); |
1845 | 1168 sc->ctts_count = 0; |
1169 url_fskip(pb, 8 * (entries - i - 1)); | |
1170 break; | |
1171 } | |
1172 sc->ctts_data[i].count = count; | |
1173 sc->ctts_data[i].duration= duration; | |
1174 | |
1175 sc->time_rate= ff_gcd(sc->time_rate, duration); | |
1176 } | |
1177 return 0; | |
1178 } | |
1179 | |
3154
01f6f3c905db
move mov_build_index before mov_read_trak to avoid useless declaration
bcoudurier
parents:
3153
diff
changeset
|
1180 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
|
1181 { |
01f6f3c905db
move mov_build_index before mov_read_trak to avoid useless declaration
bcoudurier
parents:
3153
diff
changeset
|
1182 MOVStreamContext *sc = st->priv_data; |
01f6f3c905db
move mov_build_index before mov_read_trak to avoid useless declaration
bcoudurier
parents:
3153
diff
changeset
|
1183 offset_t current_offset; |
01f6f3c905db
move mov_build_index before mov_read_trak to avoid useless declaration
bcoudurier
parents:
3153
diff
changeset
|
1184 int64_t current_dts = 0; |
01f6f3c905db
move mov_build_index before mov_read_trak to avoid useless declaration
bcoudurier
parents:
3153
diff
changeset
|
1185 unsigned int stts_index = 0; |
01f6f3c905db
move mov_build_index before mov_read_trak to avoid useless declaration
bcoudurier
parents:
3153
diff
changeset
|
1186 unsigned int stsc_index = 0; |
01f6f3c905db
move mov_build_index before mov_read_trak to avoid useless declaration
bcoudurier
parents:
3153
diff
changeset
|
1187 unsigned int stss_index = 0; |
01f6f3c905db
move mov_build_index before mov_read_trak to avoid useless declaration
bcoudurier
parents:
3153
diff
changeset
|
1188 unsigned int i, j; |
01f6f3c905db
move mov_build_index before mov_read_trak to avoid useless declaration
bcoudurier
parents:
3153
diff
changeset
|
1189 |
3178
73b7ef886091
Only use chunk demuxing for old uncompressed audio mechanism specified by stts.
bcoudurier
parents:
3175
diff
changeset
|
1190 /* 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
|
1191 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
|
1192 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
|
1193 unsigned int current_sample = 0; |
01f6f3c905db
move mov_build_index before mov_read_trak to avoid useless declaration
bcoudurier
parents:
3153
diff
changeset
|
1194 unsigned int stts_sample = 0; |
01f6f3c905db
move mov_build_index before mov_read_trak to avoid useless declaration
bcoudurier
parents:
3153
diff
changeset
|
1195 unsigned int keyframe, sample_size; |
01f6f3c905db
move mov_build_index before mov_read_trak to avoid useless declaration
bcoudurier
parents:
3153
diff
changeset
|
1196 unsigned int distance = 0; |
01f6f3c905db
move mov_build_index before mov_read_trak to avoid useless declaration
bcoudurier
parents:
3153
diff
changeset
|
1197 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
|
1198 |
01f6f3c905db
move mov_build_index before mov_read_trak to avoid useless declaration
bcoudurier
parents:
3153
diff
changeset
|
1199 st->nb_frames = sc->sample_count; |
01f6f3c905db
move mov_build_index before mov_read_trak to avoid useless declaration
bcoudurier
parents:
3153
diff
changeset
|
1200 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
|
1201 current_offset = sc->chunk_offsets[i]; |
01f6f3c905db
move mov_build_index before mov_read_trak to avoid useless declaration
bcoudurier
parents:
3153
diff
changeset
|
1202 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
|
1203 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
|
1204 stsc_index++; |
01f6f3c905db
move mov_build_index before mov_read_trak to avoid useless declaration
bcoudurier
parents:
3153
diff
changeset
|
1205 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
|
1206 if (current_sample >= sc->sample_count) { |
01f6f3c905db
move mov_build_index before mov_read_trak to avoid useless declaration
bcoudurier
parents:
3153
diff
changeset
|
1207 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
|
1208 goto out; |
01f6f3c905db
move mov_build_index before mov_read_trak to avoid useless declaration
bcoudurier
parents:
3153
diff
changeset
|
1209 } |
01f6f3c905db
move mov_build_index before mov_read_trak to avoid useless declaration
bcoudurier
parents:
3153
diff
changeset
|
1210 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
|
1211 if (keyframe) { |
01f6f3c905db
move mov_build_index before mov_read_trak to avoid useless declaration
bcoudurier
parents:
3153
diff
changeset
|
1212 distance = 0; |
01f6f3c905db
move mov_build_index before mov_read_trak to avoid useless declaration
bcoudurier
parents:
3153
diff
changeset
|
1213 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
|
1214 stss_index++; |
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 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
|
1217 if(sc->pseudo_stream_id == -1 || |
3301
11b6da5ffe78
only print debug info when sample is actually added
bcoudurier
parents:
3300
diff
changeset
|
1218 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
|
1219 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
|
1220 keyframe ? AVINDEX_KEYFRAME : 0); |
3301
11b6da5ffe78
only print debug info when sample is actually added
bcoudurier
parents:
3300
diff
changeset
|
1221 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
|
1222 "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
|
1223 current_offset, current_dts, sample_size, distance, keyframe); |
11b6da5ffe78
only print debug info when sample is actually added
bcoudurier
parents:
3300
diff
changeset
|
1224 } |
3154
01f6f3c905db
move mov_build_index before mov_read_trak to avoid useless declaration
bcoudurier
parents:
3153
diff
changeset
|
1225 current_offset += sample_size; |
01f6f3c905db
move mov_build_index before mov_read_trak to avoid useless declaration
bcoudurier
parents:
3153
diff
changeset
|
1226 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
|
1227 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
|
1228 distance++; |
01f6f3c905db
move mov_build_index before mov_read_trak to avoid useless declaration
bcoudurier
parents:
3153
diff
changeset
|
1229 stts_sample++; |
01f6f3c905db
move mov_build_index before mov_read_trak to avoid useless declaration
bcoudurier
parents:
3153
diff
changeset
|
1230 current_sample++; |
01f6f3c905db
move mov_build_index before mov_read_trak to avoid useless declaration
bcoudurier
parents:
3153
diff
changeset
|
1231 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
|
1232 stts_sample = 0; |
01f6f3c905db
move mov_build_index before mov_read_trak to avoid useless declaration
bcoudurier
parents:
3153
diff
changeset
|
1233 stts_index++; |
01f6f3c905db
move mov_build_index before mov_read_trak to avoid useless declaration
bcoudurier
parents:
3153
diff
changeset
|
1234 } |
01f6f3c905db
move mov_build_index before mov_read_trak to avoid useless declaration
bcoudurier
parents:
3153
diff
changeset
|
1235 } |
01f6f3c905db
move mov_build_index before mov_read_trak to avoid useless declaration
bcoudurier
parents:
3153
diff
changeset
|
1236 } |
01f6f3c905db
move mov_build_index before mov_read_trak to avoid useless declaration
bcoudurier
parents:
3153
diff
changeset
|
1237 } else { /* read whole chunk */ |
01f6f3c905db
move mov_build_index before mov_read_trak to avoid useless declaration
bcoudurier
parents:
3153
diff
changeset
|
1238 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
|
1239 unsigned int frames = 1; |
01f6f3c905db
move mov_build_index before mov_read_trak to avoid useless declaration
bcoudurier
parents:
3153
diff
changeset
|
1240 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
|
1241 current_offset = sc->chunk_offsets[i]; |
01f6f3c905db
move mov_build_index before mov_read_trak to avoid useless declaration
bcoudurier
parents:
3153
diff
changeset
|
1242 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
|
1243 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
|
1244 stsc_index++; |
01f6f3c905db
move mov_build_index before mov_read_trak to avoid useless declaration
bcoudurier
parents:
3153
diff
changeset
|
1245 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
|
1246 /* 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
|
1247 if (sc->samples_per_frame > 0 && |
01f6f3c905db
move mov_build_index before mov_read_trak to avoid useless declaration
bcoudurier
parents:
3153
diff
changeset
|
1248 (chunk_samples * sc->bytes_per_frame % sc->samples_per_frame == 0)) { |
3255 | 1249 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
|
1250 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
|
1251 else { |
01f6f3c905db
move mov_build_index before mov_read_trak to avoid useless declaration
bcoudurier
parents:
3153
diff
changeset
|
1252 chunk_size = sc->bytes_per_frame; |
01f6f3c905db
move mov_build_index before mov_read_trak to avoid useless declaration
bcoudurier
parents:
3153
diff
changeset
|
1253 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
|
1254 chunk_samples = sc->samples_per_frame; |
01f6f3c905db
move mov_build_index before mov_read_trak to avoid useless declaration
bcoudurier
parents:
3153
diff
changeset
|
1255 } |
3173
cb3eb255f80d
sample size to 1 might happen for data, fix GMCMidiaASX.mov, fallback is better than failing
bcoudurier
parents:
3170
diff
changeset
|
1256 } else |
3154
01f6f3c905db
move mov_build_index before mov_read_trak to avoid useless declaration
bcoudurier
parents:
3153
diff
changeset
|
1257 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
|
1258 for (j = 0; j < frames; j++) { |
01f6f3c905db
move mov_build_index before mov_read_trak to avoid useless declaration
bcoudurier
parents:
3153
diff
changeset
|
1259 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
|
1260 /* get chunk duration */ |
01f6f3c905db
move mov_build_index before mov_read_trak to avoid useless declaration
bcoudurier
parents:
3153
diff
changeset
|
1261 chunk_duration = 0; |
01f6f3c905db
move mov_build_index before mov_read_trak to avoid useless declaration
bcoudurier
parents:
3153
diff
changeset
|
1262 while (chunk_samples > 0) { |
01f6f3c905db
move mov_build_index before mov_read_trak to avoid useless declaration
bcoudurier
parents:
3153
diff
changeset
|
1263 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
|
1264 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
|
1265 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
|
1266 break; |
01f6f3c905db
move mov_build_index before mov_read_trak to avoid useless declaration
bcoudurier
parents:
3153
diff
changeset
|
1267 } else { |
01f6f3c905db
move mov_build_index before mov_read_trak to avoid useless declaration
bcoudurier
parents:
3153
diff
changeset
|
1268 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
|
1269 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 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
|
1271 stts_index++; |
01f6f3c905db
move mov_build_index before mov_read_trak to avoid useless declaration
bcoudurier
parents:
3153
diff
changeset
|
1272 } |
01f6f3c905db
move mov_build_index before mov_read_trak to avoid useless declaration
bcoudurier
parents:
3153
diff
changeset
|
1273 } |
01f6f3c905db
move mov_build_index before mov_read_trak to avoid useless declaration
bcoudurier
parents:
3153
diff
changeset
|
1274 current_offset += sc->bytes_per_frame; |
3167 | 1275 dprintf(mov->fc, "AVIndex stream %d, chunk %d, offset %"PRIx64", dts %"PRId64", " |
1276 "size %d, duration %d\n", st->index, i, current_offset, current_dts, | |
1277 chunk_size, chunk_duration); | |
3154
01f6f3c905db
move mov_build_index before mov_read_trak to avoid useless declaration
bcoudurier
parents:
3153
diff
changeset
|
1278 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
|
1279 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
|
1280 } |
01f6f3c905db
move mov_build_index before mov_read_trak to avoid useless declaration
bcoudurier
parents:
3153
diff
changeset
|
1281 } |
01f6f3c905db
move mov_build_index before mov_read_trak to avoid useless declaration
bcoudurier
parents:
3153
diff
changeset
|
1282 } |
01f6f3c905db
move mov_build_index before mov_read_trak to avoid useless declaration
bcoudurier
parents:
3153
diff
changeset
|
1283 out: |
01f6f3c905db
move mov_build_index before mov_read_trak to avoid useless declaration
bcoudurier
parents:
3153
diff
changeset
|
1284 /* adjust sample count to avindex entries */ |
01f6f3c905db
move mov_build_index before mov_read_trak to avoid useless declaration
bcoudurier
parents:
3153
diff
changeset
|
1285 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
|
1286 } |
3153
4ded3fdf5c7c
move specific end treatment when trak is detected, will be needed for fragments
bcoudurier
parents:
3145
diff
changeset
|
1287 |
1845 | 1288 static int mov_read_trak(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom) |
1289 { | |
1290 AVStream *st; | |
1291 MOVStreamContext *sc; | |
3153
4ded3fdf5c7c
move specific end treatment when trak is detected, will be needed for fragments
bcoudurier
parents:
3145
diff
changeset
|
1292 int ret; |
1845 | 1293 |
1294 st = av_new_stream(c->fc, c->fc->nb_streams); | |
3162 | 1295 if (!st) return AVERROR(ENOMEM); |
1845 | 1296 sc = av_mallocz(sizeof(MOVStreamContext)); |
3161
60be75aa8c47
cannot free AVStream like this, and return ENOMEM
bcoudurier
parents:
3160
diff
changeset
|
1297 if (!sc) return AVERROR(ENOMEM); |
1845 | 1298 |
1299 st->priv_data = sc; | |
1300 st->codec->codec_type = CODEC_TYPE_DATA; | |
1301 st->start_time = 0; /* XXX: check */ | |
1302 | |
3153
4ded3fdf5c7c
move specific end treatment when trak is detected, will be needed for fragments
bcoudurier
parents:
3145
diff
changeset
|
1303 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
|
1304 return ret; |
4ded3fdf5c7c
move specific end treatment when trak is detected, will be needed for fragments
bcoudurier
parents:
3145
diff
changeset
|
1305 |
4ded3fdf5c7c
move specific end treatment when trak is detected, will be needed for fragments
bcoudurier
parents:
3145
diff
changeset
|
1306 /* sanity checks */ |
3191
68c7fd8c44ca
support mp4 fragmented files without any samples in the moov atom
bcoudurier
parents:
3190
diff
changeset
|
1307 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
|
1308 (!sc->sample_size && !sc->sample_count))){ |
3180 | 1309 av_log(c->fc, AV_LOG_ERROR, "stream %d, missing mandatory atoms, broken header\n", |
1310 st->index); | |
3153
4ded3fdf5c7c
move specific end treatment when trak is detected, will be needed for fragments
bcoudurier
parents:
3145
diff
changeset
|
1311 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
|
1312 return 0; |
4ded3fdf5c7c
move specific end treatment when trak is detected, will be needed for fragments
bcoudurier
parents:
3145
diff
changeset
|
1313 } |
4ded3fdf5c7c
move specific end treatment when trak is detected, will be needed for fragments
bcoudurier
parents:
3145
diff
changeset
|
1314 if(!sc->time_rate) |
4ded3fdf5c7c
move specific end treatment when trak is detected, will be needed for fragments
bcoudurier
parents:
3145
diff
changeset
|
1315 sc->time_rate=1; |
4ded3fdf5c7c
move specific end treatment when trak is detected, will be needed for fragments
bcoudurier
parents:
3145
diff
changeset
|
1316 if(!sc->time_scale) |
4ded3fdf5c7c
move specific end treatment when trak is detected, will be needed for fragments
bcoudurier
parents:
3145
diff
changeset
|
1317 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
|
1318 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
|
1319 |
3245
9f25267bee44
demux qcelp, so this can work with soc decoder and stream copy
bcoudurier
parents:
3242
diff
changeset
|
1320 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
|
1321 !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
|
1322 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
|
1323 |
4ded3fdf5c7c
move specific end treatment when trak is detected, will be needed for fragments
bcoudurier
parents:
3145
diff
changeset
|
1324 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
|
1325 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
|
1326 st->duration /= sc->time_rate; |
4ded3fdf5c7c
move specific end treatment when trak is detected, will be needed for fragments
bcoudurier
parents:
3145
diff
changeset
|
1327 } |
4ded3fdf5c7c
move specific end treatment when trak is detected, will be needed for fragments
bcoudurier
parents:
3145
diff
changeset
|
1328 sc->ffindex = st->index; |
4ded3fdf5c7c
move specific end treatment when trak is detected, will be needed for fragments
bcoudurier
parents:
3145
diff
changeset
|
1329 mov_build_index(c, st); |
4ded3fdf5c7c
move specific end treatment when trak is detected, will be needed for fragments
bcoudurier
parents:
3145
diff
changeset
|
1330 |
4ded3fdf5c7c
move specific end treatment when trak is detected, will be needed for fragments
bcoudurier
parents:
3145
diff
changeset
|
1331 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
|
1332 if (url_fopen(&sc->pb, sc->drefs[sc->dref_id-1].path, URL_RDONLY) < 0) |
3182 | 1333 av_log(c->fc, AV_LOG_ERROR, "stream %d, error opening file %s: %s\n", |
1334 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
|
1335 } else |
4ded3fdf5c7c
move specific end treatment when trak is detected, will be needed for fragments
bcoudurier
parents:
3145
diff
changeset
|
1336 sc->pb = c->fc->pb; |
4ded3fdf5c7c
move specific end treatment when trak is detected, will be needed for fragments
bcoudurier
parents:
3145
diff
changeset
|
1337 |
4ded3fdf5c7c
move specific end treatment when trak is detected, will be needed for fragments
bcoudurier
parents:
3145
diff
changeset
|
1338 switch (st->codec->codec_id) { |
4ded3fdf5c7c
move specific end treatment when trak is detected, will be needed for fragments
bcoudurier
parents:
3145
diff
changeset
|
1339 #ifdef CONFIG_H261_DECODER |
4ded3fdf5c7c
move specific end treatment when trak is detected, will be needed for fragments
bcoudurier
parents:
3145
diff
changeset
|
1340 case CODEC_ID_H261: |
4ded3fdf5c7c
move specific end treatment when trak is detected, will be needed for fragments
bcoudurier
parents:
3145
diff
changeset
|
1341 #endif |
4ded3fdf5c7c
move specific end treatment when trak is detected, will be needed for fragments
bcoudurier
parents:
3145
diff
changeset
|
1342 #ifdef CONFIG_H263_DECODER |
4ded3fdf5c7c
move specific end treatment when trak is detected, will be needed for fragments
bcoudurier
parents:
3145
diff
changeset
|
1343 case CODEC_ID_H263: |
4ded3fdf5c7c
move specific end treatment when trak is detected, will be needed for fragments
bcoudurier
parents:
3145
diff
changeset
|
1344 #endif |
4ded3fdf5c7c
move specific end treatment when trak is detected, will be needed for fragments
bcoudurier
parents:
3145
diff
changeset
|
1345 #ifdef CONFIG_MPEG4_DECODER |
4ded3fdf5c7c
move specific end treatment when trak is detected, will be needed for fragments
bcoudurier
parents:
3145
diff
changeset
|
1346 case CODEC_ID_MPEG4: |
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 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
|
1349 st->codec->height= 0; |
4ded3fdf5c7c
move specific end treatment when trak is detected, will be needed for fragments
bcoudurier
parents:
3145
diff
changeset
|
1350 break; |
4ded3fdf5c7c
move specific end treatment when trak is detected, will be needed for fragments
bcoudurier
parents:
3145
diff
changeset
|
1351 #ifdef CONFIG_VORBIS_DECODER |
4ded3fdf5c7c
move specific end treatment when trak is detected, will be needed for fragments
bcoudurier
parents:
3145
diff
changeset
|
1352 case CODEC_ID_VORBIS: |
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->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
|
1355 break; |
4ded3fdf5c7c
move specific end treatment when trak is detected, will be needed for fragments
bcoudurier
parents:
3145
diff
changeset
|
1356 } |
3155 | 1357 |
1358 /* Do not need those anymore. */ | |
1359 av_freep(&sc->chunk_offsets); | |
1360 av_freep(&sc->sample_to_chunk); | |
1361 av_freep(&sc->sample_sizes); | |
1362 av_freep(&sc->keyframes); | |
1363 av_freep(&sc->stts_data); | |
1364 | |
3153
4ded3fdf5c7c
move specific end treatment when trak is detected, will be needed for fragments
bcoudurier
parents:
3145
diff
changeset
|
1365 return 0; |
1845 | 1366 } |
1367 | |
2296
0cfc556604e3
fill title, author, copyright and comment fields by parsing udta atom
benoit
parents:
2164
diff
changeset
|
1368 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
|
1369 { |
0cfc556604e3
fill title, author, copyright and comment fields by parsing udta atom
benoit
parents:
2164
diff
changeset
|
1370 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
|
1371 |
0cfc556604e3
fill title, author, copyright and comment fields by parsing udta atom
benoit
parents:
2164
diff
changeset
|
1372 get_be16(pb); /* skip language */ |
0cfc556604e3
fill title, author, copyright and comment fields by parsing udta atom
benoit
parents:
2164
diff
changeset
|
1373 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
|
1374 } |
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 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
|
1377 { |
0cfc556604e3
fill title, author, copyright and comment fields by parsing udta atom
benoit
parents:
2164
diff
changeset
|
1378 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
|
1379 |
0cfc556604e3
fill title, author, copyright and comment fields by parsing udta atom
benoit
parents:
2164
diff
changeset
|
1380 while (url_ftell(pb) + 8 < end) { |
0cfc556604e3
fill title, author, copyright and comment fields by parsing udta atom
benoit
parents:
2164
diff
changeset
|
1381 uint32_t tag_size = get_be32(pb); |
0cfc556604e3
fill title, author, copyright and comment fields by parsing udta atom
benoit
parents:
2164
diff
changeset
|
1382 uint32_t tag = get_le32(pb); |
0cfc556604e3
fill title, author, copyright and comment fields by parsing udta atom
benoit
parents:
2164
diff
changeset
|
1383 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
|
1384 |
2547
92bf4673d050
stop parsing udta if size is wrong/garbage, fix issue 154, fix RQ004F14.MOV
bcoudurier
parents:
2299
diff
changeset
|
1385 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
|
1386 break; |
92bf4673d050
stop parsing udta if size is wrong/garbage, fix issue 154, fix RQ004F14.MOV
bcoudurier
parents:
2299
diff
changeset
|
1387 |
2296
0cfc556604e3
fill title, author, copyright and comment fields by parsing udta atom
benoit
parents:
2164
diff
changeset
|
1388 switch (tag) { |
0cfc556604e3
fill title, author, copyright and comment fields by parsing udta atom
benoit
parents:
2164
diff
changeset
|
1389 case MKTAG(0xa9,'n','a','m'): |
0cfc556604e3
fill title, author, copyright and comment fields by parsing udta atom
benoit
parents:
2164
diff
changeset
|
1390 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
|
1391 break; |
0cfc556604e3
fill title, author, copyright and comment fields by parsing udta atom
benoit
parents:
2164
diff
changeset
|
1392 case MKTAG(0xa9,'w','r','t'): |
0cfc556604e3
fill title, author, copyright and comment fields by parsing udta atom
benoit
parents:
2164
diff
changeset
|
1393 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
|
1394 break; |
0cfc556604e3
fill title, author, copyright and comment fields by parsing udta atom
benoit
parents:
2164
diff
changeset
|
1395 case MKTAG(0xa9,'c','p','y'): |
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->copyright, sizeof(c->fc->copyright)); |
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,'i','n','f'): |
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->comment, sizeof(c->fc->comment)); |
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 default: |
0cfc556604e3
fill title, author, copyright and comment fields by parsing udta atom
benoit
parents:
2164
diff
changeset
|
1402 break; |
0cfc556604e3
fill title, author, copyright and comment fields by parsing udta atom
benoit
parents:
2164
diff
changeset
|
1403 } |
0cfc556604e3
fill title, author, copyright and comment fields by parsing udta atom
benoit
parents:
2164
diff
changeset
|
1404 |
0cfc556604e3
fill title, author, copyright and comment fields by parsing udta atom
benoit
parents:
2164
diff
changeset
|
1405 url_fseek(pb, next, SEEK_SET); |
0cfc556604e3
fill title, author, copyright and comment fields by parsing udta atom
benoit
parents:
2164
diff
changeset
|
1406 } |
0cfc556604e3
fill title, author, copyright and comment fields by parsing udta atom
benoit
parents:
2164
diff
changeset
|
1407 |
0cfc556604e3
fill title, author, copyright and comment fields by parsing udta atom
benoit
parents:
2164
diff
changeset
|
1408 return 0; |
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 |
1845 | 1411 static int mov_read_tkhd(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom) |
1412 { | |
3595 | 1413 int i; |
1414 int width; | |
1415 int height; | |
1416 int64_t disp_transform[2]; | |
1417 int display_matrix[3][2]; | |
1845 | 1418 AVStream *st = c->fc->streams[c->fc->nb_streams-1]; |
1419 int version = get_byte(pb); | |
1420 | |
3145 | 1421 get_be24(pb); /* flags */ |
1845 | 1422 /* |
1423 MOV_TRACK_ENABLED 0x0001 | |
1424 MOV_TRACK_IN_MOVIE 0x0002 | |
1425 MOV_TRACK_IN_PREVIEW 0x0004 | |
1426 MOV_TRACK_IN_POSTER 0x0008 | |
1427 */ | |
1428 | |
1429 if (version == 1) { | |
1430 get_be64(pb); | |
1431 get_be64(pb); | |
1432 } else { | |
1433 get_be32(pb); /* creation time */ | |
1434 get_be32(pb); /* modification time */ | |
1435 } | |
1436 st->id = (int)get_be32(pb); /* track id (NOT 0 !)*/ | |
1437 get_be32(pb); /* reserved */ | |
1438 st->start_time = 0; /* check */ | |
3167 | 1439 /* highlevel (considering edits) duration in movie timebase */ |
1440 (version == 1) ? get_be64(pb) : get_be32(pb); | |
1845 | 1441 get_be32(pb); /* reserved */ |
1442 get_be32(pb); /* reserved */ | |
1443 | |
1444 get_be16(pb); /* layer */ | |
1445 get_be16(pb); /* alternate group */ | |
1446 get_be16(pb); /* volume */ | |
1447 get_be16(pb); /* reserved */ | |
1448 | |
3595 | 1449 //read in the display matrix (outlined in ISO 14496-12, Section 6.2.2) |
1450 // they're kept in fixed point format through all calculations | |
1451 // ignore u,v,z b/c we don't need the scale factor to calc aspect ratio | |
1452 for (i = 0; i < 3; i++) { | |
1453 display_matrix[i][0] = get_be32(pb); // 16.16 fixed point | |
1454 display_matrix[i][1] = get_be32(pb); // 16.16 fixed point | |
1455 get_be32(pb); // 2.30 fixed point (not used) | |
1456 } | |
1457 | |
1458 width = get_be32(pb); // 16.16 fixed point track width | |
1459 height = get_be32(pb); // 16.16 fixed point track height | |
1845 | 1460 |
3595 | 1461 //transform the display width/height according to the matrix |
1462 // skip this if the display matrix is the default identity matrix | |
1463 // to keep the same scale, use [width height 1<<16] | |
1464 if (width && height && | |
1465 (display_matrix[0][0] != 65536 || display_matrix[0][1] || | |
1466 display_matrix[1][0] || display_matrix[1][1] != 65536 || | |
1467 display_matrix[2][0] || display_matrix[2][1])) { | |
1468 for (i = 0; i < 2; i++) | |
1469 disp_transform[i] = | |
1470 (int64_t) width * display_matrix[0][i] + | |
1471 (int64_t) height * display_matrix[1][i] + | |
1472 ((int64_t) display_matrix[2][i] << 16); | |
1845 | 1473 |
3595 | 1474 //sample aspect ratio is new width/height divided by old width/height |
1475 st->codec->sample_aspect_ratio = av_d2q( | |
1476 ((double) disp_transform[0] * height) / | |
1477 ((double) disp_transform[1] * width), INT_MAX); | |
1478 } | |
1845 | 1479 return 0; |
1480 } | |
1481 | |
3169 | 1482 static int mov_read_tfhd(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom) |
1483 { | |
1484 MOVFragment *frag = &c->fragment; | |
1485 MOVTrackExt *trex = NULL; | |
1486 int flags, track_id, i; | |
1487 | |
1488 get_byte(pb); /* version */ | |
1489 flags = get_be24(pb); | |
1490 | |
1491 track_id = get_be32(pb); | |
1492 if (!track_id || track_id > c->fc->nb_streams) | |
1493 return -1; | |
1494 frag->track_id = track_id; | |
1495 for (i = 0; i < c->trex_count; i++) | |
1496 if (c->trex_data[i].track_id == frag->track_id) { | |
1497 trex = &c->trex_data[i]; | |
1498 break; | |
1499 } | |
1500 if (!trex) { | |
1501 av_log(c->fc, AV_LOG_ERROR, "could not find corresponding trex\n"); | |
1502 return -1; | |
1503 } | |
1504 | |
1505 if (flags & 0x01) frag->base_data_offset = get_be64(pb); | |
1506 else frag->base_data_offset = frag->moof_offset; | |
1507 if (flags & 0x02) frag->stsd_id = get_be32(pb); | |
1508 else frag->stsd_id = trex->stsd_id; | |
1509 | |
1510 frag->duration = flags & 0x08 ? get_be32(pb) : trex->duration; | |
1511 frag->size = flags & 0x10 ? get_be32(pb) : trex->size; | |
1512 frag->flags = flags & 0x20 ? get_be32(pb) : trex->flags; | |
1513 dprintf(c->fc, "frag flags 0x%x\n", frag->flags); | |
1514 return 0; | |
1515 } | |
1516 | |
1517 static int mov_read_trex(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom) | |
1518 { | |
1519 MOVTrackExt *trex; | |
1520 | |
1521 if ((uint64_t)c->trex_count+1 >= UINT_MAX / sizeof(*c->trex_data)) | |
1522 return -1; | |
1523 c->trex_data = av_realloc(c->trex_data, (c->trex_count+1)*sizeof(*c->trex_data)); | |
1524 if (!c->trex_data) | |
1525 return AVERROR(ENOMEM); | |
1526 trex = &c->trex_data[c->trex_count++]; | |
1527 get_byte(pb); /* version */ | |
1528 get_be24(pb); /* flags */ | |
1529 trex->track_id = get_be32(pb); | |
1530 trex->stsd_id = get_be32(pb); | |
1531 trex->duration = get_be32(pb); | |
1532 trex->size = get_be32(pb); | |
1533 trex->flags = get_be32(pb); | |
1534 return 0; | |
1535 } | |
1536 | |
1537 static int mov_read_trun(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom) | |
1538 { | |
1539 MOVFragment *frag = &c->fragment; | |
3190 | 1540 AVStream *st; |
1541 MOVStreamContext *sc; | |
3169 | 1542 uint64_t offset; |
1543 int64_t dts; | |
1544 int data_offset = 0; | |
1545 unsigned entries, first_sample_flags = frag->flags; | |
1546 int flags, distance, i; | |
1547 | |
3190 | 1548 if (!frag->track_id || frag->track_id > c->fc->nb_streams) |
1549 return -1; | |
1550 st = c->fc->streams[frag->track_id-1]; | |
1551 sc = st->priv_data; | |
3169 | 1552 if (sc->pseudo_stream_id+1 != frag->stsd_id) |
1553 return 0; | |
1554 get_byte(pb); /* version */ | |
1555 flags = get_be24(pb); | |
1556 entries = get_be32(pb); | |
1557 dprintf(c->fc, "flags 0x%x entries %d\n", flags, entries); | |
1558 if (flags & 0x001) data_offset = get_be32(pb); | |
1559 if (flags & 0x004) first_sample_flags = get_be32(pb); | |
1560 if (flags & 0x800) { | |
1561 if ((uint64_t)entries+sc->ctts_count >= UINT_MAX/sizeof(*sc->ctts_data)) | |
1562 return -1; | |
1563 sc->ctts_data = av_realloc(sc->ctts_data, | |
1564 (entries+sc->ctts_count)*sizeof(*sc->ctts_data)); | |
1565 if (!sc->ctts_data) | |
1566 return AVERROR(ENOMEM); | |
1567 } | |
1568 dts = st->duration; | |
1569 offset = frag->base_data_offset + data_offset; | |
1570 distance = 0; | |
1571 dprintf(c->fc, "first sample flags 0x%x\n", first_sample_flags); | |
1572 for (i = 0; i < entries; i++) { | |
1573 unsigned sample_size = frag->size; | |
1574 int sample_flags = i ? frag->flags : first_sample_flags; | |
1575 unsigned sample_duration = frag->duration; | |
1576 int keyframe; | |
1577 | |
1578 if (flags & 0x100) sample_duration = get_be32(pb); | |
1579 if (flags & 0x200) sample_size = get_be32(pb); | |
1580 if (flags & 0x400) sample_flags = get_be32(pb); | |
1581 if (flags & 0x800) { | |
1582 sc->ctts_data[sc->ctts_count].count = 1; | |
1583 sc->ctts_data[sc->ctts_count].duration = get_be32(pb); | |
1584 sc->ctts_count++; | |
1585 } | |
1586 if ((keyframe = st->codec->codec_type == CODEC_TYPE_AUDIO || | |
1587 (flags & 0x004 && !i && !sample_flags) || sample_flags & 0x2000000)) | |
1588 distance = 0; | |
1589 av_add_index_entry(st, offset, dts, sample_size, distance, | |
1590 keyframe ? AVINDEX_KEYFRAME : 0); | |
1591 dprintf(c->fc, "AVIndex stream %d, sample %d, offset %"PRIx64", dts %"PRId64", " | |
1592 "size %d, distance %d, keyframe %d\n", st->index, sc->sample_count+i, | |
1593 offset, dts, sample_size, distance, keyframe); | |
1594 distance++; | |
1595 assert(sample_duration % sc->time_rate == 0); | |
1596 dts += sample_duration / sc->time_rate; | |
1597 offset += sample_size; | |
1598 } | |
1599 frag->moof_offset = offset; | |
1600 sc->sample_count = st->nb_index_entries; | |
1601 st->duration = dts; | |
1602 return 0; | |
1603 } | |
1604 | |
1845 | 1605 /* this atom should be null (from specs), but some buggy files put the 'moov' atom inside it... */ |
1606 /* like the files created with Adobe Premiere 5.0, for samples see */ | |
1607 /* http://graphics.tudelft.nl/~wouter/publications/soundtests/ */ | |
1608 static int mov_read_wide(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom) | |
1609 { | |
1610 int err; | |
1611 | |
1612 if (atom.size < 8) | |
1613 return 0; /* continue */ | |
1614 if (get_be32(pb) != 0) { /* 0 sized mdat atom... use the 'wide' atom size */ | |
1615 url_fskip(pb, atom.size - 4); | |
1616 return 0; | |
1617 } | |
1618 atom.type = get_le32(pb); | |
1619 atom.offset += 8; | |
1620 atom.size -= 8; | |
3253 | 1621 if (atom.type != MKTAG('m','d','a','t')) { |
1845 | 1622 url_fskip(pb, atom.size); |
1623 return 0; | |
1624 } | |
1625 err = mov_read_mdat(c, pb, atom); | |
1626 return err; | |
1627 } | |
1628 | |
1629 static int mov_read_cmov(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom) | |
1630 { | |
1631 #ifdef CONFIG_ZLIB | |
1632 ByteIOContext ctx; | |
1633 uint8_t *cmov_data; | |
1634 uint8_t *moov_data; /* uncompressed data */ | |
1635 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
|
1636 int ret = -1; |
1845 | 1637 |
1638 get_be32(pb); /* dcom atom */ | |
3253 | 1639 if (get_le32(pb) != MKTAG('d','c','o','m')) |
1845 | 1640 return -1; |
3253 | 1641 if (get_le32(pb) != MKTAG('z','l','i','b')) { |
1845 | 1642 av_log(NULL, AV_LOG_ERROR, "unknown compression for cmov atom !"); |
1643 return -1; | |
1644 } | |
1645 get_be32(pb); /* cmvd atom */ | |
3253 | 1646 if (get_le32(pb) != MKTAG('c','m','v','d')) |
1845 | 1647 return -1; |
1648 moov_len = get_be32(pb); /* uncompressed size */ | |
1649 cmov_len = atom.size - 6 * 4; | |
1650 | |
1651 cmov_data = av_malloc(cmov_len); | |
1652 if (!cmov_data) | |
1653 return -1; | |
1654 moov_data = av_malloc(moov_len); | |
1655 if (!moov_data) { | |
1656 av_free(cmov_data); | |
1657 return -1; | |
1658 } | |
1659 get_buffer(pb, cmov_data, cmov_len); | |
1660 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
|
1661 goto free_and_return; |
1845 | 1662 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
|
1663 goto free_and_return; |
3253 | 1664 atom.type = MKTAG('m','o','o','v'); |
1845 | 1665 atom.offset = 0; |
1666 atom.size = moov_len; | |
1667 #ifdef DEBUG | |
1668 // { int fd = open("/tmp/uncompheader.mov", O_WRONLY | O_CREAT); write(fd, moov_data, moov_len); close(fd); } | |
1669 #endif | |
1670 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
|
1671 free_and_return: |
1845 | 1672 av_free(moov_data); |
1673 av_free(cmov_data); | |
1674 return ret; | |
1675 #else | |
1676 av_log(c->fc, AV_LOG_ERROR, "this file requires zlib support compiled in\n"); | |
1677 return -1; | |
1678 #endif | |
1679 } | |
1680 | |
1681 /* edit list atom */ | |
1682 static int mov_read_elst(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom) | |
1683 { | |
2824
ecbfaa8712a1
do not retain useless pointers to avstream priv_data, use it directly
bcoudurier
parents:
2823
diff
changeset
|
1684 MOVStreamContext *sc = c->fc->streams[c->fc->nb_streams-1]->priv_data; |
1845 | 1685 int i, edit_count; |
1686 | |
1687 get_byte(pb); /* version */ | |
3145 | 1688 get_be24(pb); /* flags */ |
2824
ecbfaa8712a1
do not retain useless pointers to avstream priv_data, use it directly
bcoudurier
parents:
2823
diff
changeset
|
1689 edit_count= sc->edit_count = get_be32(pb); /* entries */ |
1845 | 1690 |
1691 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
|
1692 int time; |
1845 | 1693 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
|
1694 time = get_be32(pb); /* Media time */ |
1845 | 1695 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
|
1696 if (time != 0) |
db12cabbe337
warn use if edit list is not starting at 0, a/v desync might occur
bcoudurier
parents:
3037
diff
changeset
|
1697 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
|
1698 "a/v desync might occur, patch welcome\n"); |
1845 | 1699 } |
2824
ecbfaa8712a1
do not retain useless pointers to avstream priv_data, use it directly
bcoudurier
parents:
2823
diff
changeset
|
1700 dprintf(c->fc, "track[%i].edit_count = %i\n", c->fc->nb_streams-1, sc->edit_count); |
1845 | 1701 return 0; |
1702 } | |
1703 | |
1704 static const MOVParseTableEntry mov_default_parse_table[] = { | |
3496
cdbf302a3c00
chinese avs demuxing support, demux AVSFileFormat.mp4
bcoudurier
parents:
3487
diff
changeset
|
1705 { MKTAG('a','v','s','s'), mov_read_extradata }, |
3253 | 1706 { MKTAG('c','o','6','4'), mov_read_stco }, |
1707 { MKTAG('c','t','t','s'), mov_read_ctts }, /* composition time to sample */ | |
1708 { MKTAG('d','i','n','f'), mov_read_default }, | |
1709 { MKTAG('d','r','e','f'), mov_read_dref }, | |
1710 { MKTAG('e','d','t','s'), mov_read_default }, | |
1711 { MKTAG('e','l','s','t'), mov_read_elst }, | |
1712 { MKTAG('e','n','d','a'), mov_read_enda }, | |
1713 { MKTAG('f','i','e','l'), mov_read_extradata }, | |
1714 { MKTAG('f','t','y','p'), mov_read_ftyp }, | |
1715 { MKTAG('g','l','b','l'), mov_read_glbl }, | |
1716 { MKTAG('h','d','l','r'), mov_read_hdlr }, | |
1717 { MKTAG('j','p','2','h'), mov_read_extradata }, | |
1718 { MKTAG('m','d','a','t'), mov_read_mdat }, | |
1719 { MKTAG('m','d','h','d'), mov_read_mdhd }, | |
1720 { MKTAG('m','d','i','a'), mov_read_default }, | |
1721 { MKTAG('m','i','n','f'), mov_read_default }, | |
1722 { MKTAG('m','o','o','f'), mov_read_moof }, | |
1723 { MKTAG('m','o','o','v'), mov_read_moov }, | |
1724 { MKTAG('m','v','e','x'), mov_read_default }, | |
1725 { MKTAG('m','v','h','d'), mov_read_mvhd }, | |
1726 { MKTAG('S','M','I',' '), mov_read_smi }, /* Sorenson extension ??? */ | |
1727 { MKTAG('a','l','a','c'), mov_read_extradata }, /* alac specific atom */ | |
1728 { MKTAG('a','v','c','C'), mov_read_glbl }, | |
1729 { MKTAG('s','t','b','l'), mov_read_default }, | |
1730 { MKTAG('s','t','c','o'), mov_read_stco }, | |
1731 { MKTAG('s','t','s','c'), mov_read_stsc }, | |
1732 { MKTAG('s','t','s','d'), mov_read_stsd }, /* sample description */ | |
1733 { MKTAG('s','t','s','s'), mov_read_stss }, /* sync sample */ | |
1734 { MKTAG('s','t','s','z'), mov_read_stsz }, /* sample size */ | |
1735 { MKTAG('s','t','t','s'), mov_read_stts }, | |
1736 { MKTAG('t','k','h','d'), mov_read_tkhd }, /* track header */ | |
1737 { MKTAG('t','f','h','d'), mov_read_tfhd }, /* track fragment header */ | |
1738 { MKTAG('t','r','a','k'), mov_read_trak }, | |
1739 { MKTAG('t','r','a','f'), mov_read_default }, | |
1740 { MKTAG('t','r','e','x'), mov_read_trex }, | |
1741 { MKTAG('t','r','u','n'), mov_read_trun }, | |
1742 { MKTAG('u','d','t','a'), mov_read_udta }, | |
1743 { MKTAG('w','a','v','e'), mov_read_wave }, | |
1744 { MKTAG('e','s','d','s'), mov_read_esds }, | |
1745 { MKTAG('w','i','d','e'), mov_read_wide }, /* place holder */ | |
1746 { MKTAG('c','m','o','v'), mov_read_cmov }, | |
2826 | 1747 { 0, NULL } |
1845 | 1748 }; |
1749 | |
1750 static int mov_probe(AVProbeData *p) | |
1751 { | |
1752 unsigned int offset; | |
1753 uint32_t tag; | |
1754 int score = 0; | |
1755 | |
1756 /* check file header */ | |
1757 offset = 0; | |
1758 for(;;) { | |
1759 /* ignore invalid offset */ | |
1760 if ((offset + 8) > (unsigned int)p->buf_size) | |
1761 return score; | |
1762 tag = AV_RL32(p->buf + offset + 4); | |
1763 switch(tag) { | |
1764 /* check for obvious tags */ | |
3253 | 1765 case MKTAG('j','P',' ',' '): /* jpeg 2000 signature */ |
1766 case MKTAG('m','o','o','v'): | |
1767 case MKTAG('m','d','a','t'): | |
1768 case MKTAG('p','n','o','t'): /* detect movs with preview pics like ew.mov and april.mov */ | |
1769 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
|
1770 case MKTAG('f','t','y','p'): |
1845 | 1771 return AVPROBE_SCORE_MAX; |
1772 /* those are more common words, so rate then a bit less */ | |
3253 | 1773 case MKTAG('e','d','i','w'): /* xdcam files have reverted first tags */ |
1774 case MKTAG('w','i','d','e'): | |
1775 case MKTAG('f','r','e','e'): | |
1776 case MKTAG('j','u','n','k'): | |
1777 case MKTAG('p','i','c','t'): | |
1845 | 1778 return AVPROBE_SCORE_MAX - 5; |
3588 | 1779 case MKTAG(0x82,0x82,0x7f,0x7d): |
3253 | 1780 case MKTAG('s','k','i','p'): |
1781 case MKTAG('u','u','i','d'): | |
1782 case MKTAG('p','r','f','l'): | |
1845 | 1783 offset = AV_RB32(p->buf+offset) + offset; |
1784 /* if we only find those cause probedata is too small at least rate them */ | |
1785 score = AVPROBE_SCORE_MAX - 50; | |
1786 break; | |
1787 default: | |
1788 /* unrecognized tag */ | |
1789 return score; | |
1790 } | |
1791 } | |
1792 return score; | |
1793 } | |
1794 | |
1795 static int mov_read_header(AVFormatContext *s, AVFormatParameters *ap) | |
1796 { | |
2006 | 1797 MOVContext *mov = s->priv_data; |
2771
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2730
diff
changeset
|
1798 ByteIOContext *pb = s->pb; |
3155 | 1799 int err; |
1845 | 1800 MOV_atom_t atom = { 0, 0, 0 }; |
1801 | |
1802 mov->fc = s; | |
3167 | 1803 /* .mov and .mp4 aren't streamable anyway (only progressive download if moov is before mdat) */ |
1804 if(!url_is_streamed(pb)) | |
1845 | 1805 atom.size = url_fsize(pb); |
1806 else | |
2026 | 1807 atom.size = INT64_MAX; |
1845 | 1808 |
1809 /* check MOV header */ | |
3204 | 1810 if ((err = mov_read_default(mov, pb, atom)) < 0) { |
1811 av_log(s, AV_LOG_ERROR, "error reading header: %d\n", err); | |
1812 return err; | |
1813 } | |
1814 if (!mov->found_moov) { | |
1815 av_log(s, AV_LOG_ERROR, "moov atom not found\n"); | |
1845 | 1816 return -1; |
1817 } | |
3205 | 1818 dprintf(mov->fc, "on_parse_exit_offset=%lld\n", url_ftell(pb)); |
1845 | 1819 |
1820 return 0; | |
1821 } | |
1822 | |
1823 static int mov_read_packet(AVFormatContext *s, AVPacket *pkt) | |
1824 { | |
1825 MOVContext *mov = s->priv_data; | |
1826 MOVStreamContext *sc = 0; | |
1827 AVIndexEntry *sample = 0; | |
1828 int64_t best_dts = INT64_MAX; | |
1829 int i; | |
3170 | 1830 retry: |
2823 | 1831 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
|
1832 AVStream *st = s->streams[i]; |
ecbfaa8712a1
do not retain useless pointers to avstream priv_data, use it directly
bcoudurier
parents:
2823
diff
changeset
|
1833 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
|
1834 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
|
1835 AVIndexEntry *current_sample = &st->index_entries[msc->current_sample]; |
2902 | 1836 int64_t dts = av_rescale(current_sample->timestamp * (int64_t)msc->time_rate, |
1837 AV_TIME_BASE, msc->time_scale); | |
2030 | 1838 dprintf(s, "stream %d, sample %d, dts %"PRId64"\n", i, msc->current_sample, dts); |
2817 | 1839 if (!sample || (url_is_streamed(s->pb) && current_sample->pos < sample->pos) || |
1840 (!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
|
1841 ((msc->pb != s->pb && dts < best_dts) || (msc->pb == s->pb && |
2817 | 1842 ((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
|
1843 (FFABS(best_dts - dts) > AV_TIME_BASE && dts < best_dts)))))) { |
1845 | 1844 sample = current_sample; |
1845 best_dts = dts; | |
1846 sc = msc; | |
1847 } | |
1848 } | |
1849 } | |
3170 | 1850 if (!sample) { |
1851 mov->found_mdat = 0; | |
1852 if (!url_is_streamed(s->pb) || | |
1853 mov_read_default(mov, s->pb, (MOV_atom_t){ 0, 0, INT64_MAX }) < 0 || | |
1854 url_feof(s->pb)) | |
1855 return -1; | |
1856 dprintf(s, "read fragments, offset 0x%llx\n", url_ftell(s->pb)); | |
1857 goto retry; | |
1858 } | |
1845 | 1859 /* must be done just before reading, to avoid infinite loop on sample */ |
1860 sc->current_sample++; | |
3085
bae59276377f
support mov reference files, ref.mov/ref.m2v/ref.wav and detect BrianCox.mov
bcoudurier
parents:
3084
diff
changeset
|
1861 if (url_fseek(sc->pb, sample->pos, SEEK_SET) != sample->pos) { |
2902 | 1862 av_log(mov->fc, AV_LOG_ERROR, "stream %d, offset 0x%"PRIx64": partial file\n", |
1863 sc->ffindex, sample->pos); | |
1845 | 1864 return -1; |
1865 } | |
3085
bae59276377f
support mov reference files, ref.mov/ref.m2v/ref.wav and detect BrianCox.mov
bcoudurier
parents:
3084
diff
changeset
|
1866 av_get_packet(sc->pb, pkt, sample->size); |
1845 | 1867 #ifdef CONFIG_DV_DEMUXER |
3027 | 1868 if (mov->dv_demux && sc->dv_audio_container) { |
1869 dv_produce_packet(mov->dv_demux, pkt, pkt->data, pkt->size); | |
1870 av_free(pkt->data); | |
3034 | 1871 pkt->size = 0; |
1872 if (dv_get_packet(mov->dv_demux, pkt) < 0) | |
1873 return -1; | |
3027 | 1874 } |
1845 | 1875 #endif |
1876 pkt->stream_index = sc->ffindex; | |
1877 pkt->dts = sample->timestamp; | |
1878 if (sc->ctts_data) { | |
1879 assert(sc->ctts_data[sc->sample_to_ctime_index].duration % sc->time_rate == 0); | |
1880 pkt->pts = pkt->dts + sc->ctts_data[sc->sample_to_ctime_index].duration / sc->time_rate; | |
1881 /* update ctts context */ | |
1882 sc->sample_to_ctime_sample++; | |
2902 | 1883 if (sc->sample_to_ctime_index < sc->ctts_count && |
1884 sc->ctts_data[sc->sample_to_ctime_index].count == sc->sample_to_ctime_sample) { | |
1845 | 1885 sc->sample_to_ctime_index++; |
1886 sc->sample_to_ctime_sample = 0; | |
1887 } | |
1888 } else { | |
3267 | 1889 AVStream *st = s->streams[sc->ffindex]; |
1890 int64_t next_dts = (sc->current_sample < sc->sample_count) ? | |
1891 st->index_entries[sc->current_sample].timestamp : st->duration; | |
1892 pkt->duration = next_dts - pkt->dts; | |
1845 | 1893 pkt->pts = pkt->dts; |
1894 } | |
1895 pkt->flags |= sample->flags & AVINDEX_KEYFRAME ? PKT_FLAG_KEY : 0; | |
1896 pkt->pos = sample->pos; | |
2902 | 1897 dprintf(s, "stream %d, pts %"PRId64", dts %"PRId64", pos 0x%"PRIx64", duration %d\n", |
1898 pkt->stream_index, pkt->pts, pkt->dts, pkt->pos, pkt->duration); | |
1845 | 1899 return 0; |
1900 } | |
1901 | |
1902 static int mov_seek_stream(AVStream *st, int64_t timestamp, int flags) | |
1903 { | |
1904 MOVStreamContext *sc = st->priv_data; | |
1905 int sample, time_sample; | |
1906 int i; | |
1907 | |
1908 sample = av_index_search_timestamp(st, timestamp, flags); | |
1907 | 1909 dprintf(st->codec, "stream %d, timestamp %"PRId64", sample %d\n", st->index, timestamp, sample); |
1845 | 1910 if (sample < 0) /* not sure what to do */ |
1911 return -1; | |
1912 sc->current_sample = sample; | |
2030 | 1913 dprintf(st->codec, "stream %d, found sample %d\n", st->index, sc->current_sample); |
1845 | 1914 /* adjust ctts index */ |
1915 if (sc->ctts_data) { | |
1916 time_sample = 0; | |
1917 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
|
1918 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
|
1919 if (next > sc->current_sample) { |
1845 | 1920 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
|
1921 sc->sample_to_ctime_sample = sc->current_sample - time_sample; |
1845 | 1922 break; |
1923 } | |
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 time_sample = next; |
1845 | 1925 } |
1926 } | |
1927 return sample; | |
1928 } | |
1929 | |
1930 static int mov_read_seek(AVFormatContext *s, int stream_index, int64_t sample_time, int flags) | |
1931 { | |
1932 AVStream *st; | |
1933 int64_t seek_timestamp, timestamp; | |
1934 int sample; | |
1935 int i; | |
1936 | |
1937 if (stream_index >= s->nb_streams) | |
1938 return -1; | |
1939 | |
1940 st = s->streams[stream_index]; | |
1941 sample = mov_seek_stream(st, sample_time, flags); | |
1942 if (sample < 0) | |
1943 return -1; | |
1944 | |
1945 /* adjust seek timestamp to found sample timestamp */ | |
1946 seek_timestamp = st->index_entries[sample].timestamp; | |
1947 | |
1948 for (i = 0; i < s->nb_streams; i++) { | |
1949 st = s->streams[i]; | |
1950 if (stream_index == i || st->discard == AVDISCARD_ALL) | |
1951 continue; | |
1952 | |
1953 timestamp = av_rescale_q(seek_timestamp, s->streams[stream_index]->time_base, st->time_base); | |
1954 mov_seek_stream(st, timestamp, flags); | |
1955 } | |
1956 return 0; | |
1957 } | |
1958 | |
1959 static int mov_read_close(AVFormatContext *s) | |
1960 { | |
3085
bae59276377f
support mov reference files, ref.mov/ref.m2v/ref.wav and detect BrianCox.mov
bcoudurier
parents:
3084
diff
changeset
|
1961 int i, j; |
2006 | 1962 MOVContext *mov = s->priv_data; |
2823 | 1963 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
|
1964 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
|
1965 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
|
1966 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
|
1967 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
|
1968 av_freep(&sc->drefs); |
bae59276377f
support mov reference files, ref.mov/ref.m2v/ref.wav and detect BrianCox.mov
bcoudurier
parents:
3084
diff
changeset
|
1969 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
|
1970 url_fclose(sc->pb); |
2084 | 1971 } |
1845 | 1972 if(mov->dv_demux){ |
1973 for(i=0; i<mov->dv_fctx->nb_streams; i++){ | |
1974 av_freep(&mov->dv_fctx->streams[i]->codec); | |
1975 av_freep(&mov->dv_fctx->streams[i]); | |
1976 } | |
1977 av_freep(&mov->dv_fctx); | |
1978 av_freep(&mov->dv_demux); | |
1979 } | |
3169 | 1980 av_freep(&mov->trex_data); |
1845 | 1981 return 0; |
1982 } | |
1983 | |
1984 AVInputFormat mov_demuxer = { | |
1985 "mov,mp4,m4a,3gp,3g2,mj2", | |
3424
7a0230981402
Make long_names in lavf/lavdev optional depending on CONFIG_SMALL.
diego
parents:
3362
diff
changeset
|
1986 NULL_IF_CONFIG_SMALL("QuickTime/MPEG-4/Motion JPEG 2000 format"), |
1845 | 1987 sizeof(MOVContext), |
1988 mov_probe, | |
1989 mov_read_header, | |
1990 mov_read_packet, | |
1991 mov_read_close, | |
1992 mov_read_seek, | |
1993 }; |