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