Mercurial > libavformat.hg
annotate mpeg.c @ 2595:f9cfd91f344a libavformat
fix buffer overread with invalid Vorbis header
author | mru |
---|---|
date | Wed, 10 Oct 2007 22:59:31 +0000 |
parents | a8122196ad95 |
children | bb2ba011f1e1 |
rev | line source |
---|---|
0 | 1 /* |
2176
50322a49fa2b
split mpeg ps and variants muxer and demuxer, I'll clean more in a few minutes, lpcm freq tab is left static const in mpeg.h for now until we have more code in common
bcoudurier
parents:
2164
diff
changeset
|
2 * MPEG1/2 demuxer |
0 | 3 * Copyright (c) 2000, 2001, 2002 Fabrice Bellard. |
4 * | |
1358
0899bfe4105c
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
1332
diff
changeset
|
5 * This file is part of FFmpeg. |
0899bfe4105c
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
1332
diff
changeset
|
6 * |
0899bfe4105c
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
1332
diff
changeset
|
7 * FFmpeg is free software; you can redistribute it and/or |
0 | 8 * modify it under the terms of the GNU Lesser General Public |
9 * License as published by the Free Software Foundation; either | |
1358
0899bfe4105c
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
1332
diff
changeset
|
10 * version 2.1 of the License, or (at your option) any later version. |
0 | 11 * |
1358
0899bfe4105c
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
1332
diff
changeset
|
12 * FFmpeg is distributed in the hope that it will be useful, |
0 | 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
15 * Lesser General Public License for more details. | |
16 * | |
17 * You should have received a copy of the GNU Lesser General Public | |
1358
0899bfe4105c
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
1332
diff
changeset
|
18 * License along with FFmpeg; if not, write to the Free Software |
896
edbe5c3717f9
Update licensing information: The FSF changed postal address.
diego
parents:
885
diff
changeset
|
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
0 | 20 */ |
2176
50322a49fa2b
split mpeg ps and variants muxer and demuxer, I'll clean more in a few minutes, lpcm freq tab is left static const in mpeg.h for now until we have more code in common
bcoudurier
parents:
2164
diff
changeset
|
21 |
0 | 22 #include "avformat.h" |
2176
50322a49fa2b
split mpeg ps and variants muxer and demuxer, I'll clean more in a few minutes, lpcm freq tab is left static const in mpeg.h for now until we have more code in common
bcoudurier
parents:
2164
diff
changeset
|
23 #include "mpeg.h" |
0 | 24 |
310 | 25 //#define DEBUG_SEEK |
0 | 26 |
346
e154eb1b7149
caching of timestamps for mpeg-ps so seeking is faster
michael
parents:
337
diff
changeset
|
27 #undef NDEBUG |
e154eb1b7149
caching of timestamps for mpeg-ps so seeking is faster
michael
parents:
337
diff
changeset
|
28 #include <assert.h> |
e154eb1b7149
caching of timestamps for mpeg-ps so seeking is faster
michael
parents:
337
diff
changeset
|
29 |
0 | 30 /*********************************************/ |
31 /* demux code */ | |
32 | |
33 #define MAX_SYNC_SIZE 100000 | |
34 | |
1284 | 35 static int cdxa_probe(AVProbeData *p) |
36 { | |
37 /* check file header */ | |
38 if (p->buf[0] == 'R' && p->buf[1] == 'I' && | |
39 p->buf[2] == 'F' && p->buf[3] == 'F' && | |
40 p->buf[8] == 'C' && p->buf[9] == 'D' && | |
41 p->buf[10] == 'X' && p->buf[11] == 'A') | |
42 return AVPROBE_SCORE_MAX; | |
43 else | |
44 return 0; | |
45 } | |
46 | |
0 | 47 static int mpegps_probe(AVProbeData *p) |
48 { | |
936 | 49 uint32_t code= -1; |
1138
36ce24677f96
detect MPEG PES streams as MPEG PS; the PS demuxer will cope
mru
parents:
1126
diff
changeset
|
50 int sys=0, pspack=0, priv1=0, vid=0, audio=0; |
539 | 51 int i; |
1257 | 52 int score=0; |
49 | 53 |
1284 | 54 score = cdxa_probe(p); |
55 if (score > 0) return score; | |
56 | |
57 /* Search for MPEG stream */ | |
936 | 58 for(i=0; i<p->buf_size; i++){ |
59 code = (code<<8) + p->buf[i]; | |
165
e4d2f704bf80
- Looks a tiny bit harder in mpegps_probe() for a valid start code. This is
michaelni
parents:
65
diff
changeset
|
60 if ((code & 0xffffff00) == 0x100) { |
1140
2cfb5e02b299
detect audio-only program streams and broken files made by VDR
mru
parents:
1138
diff
changeset
|
61 if(code == SYSTEM_HEADER_START_CODE) sys++; |
2cfb5e02b299
detect audio-only program streams and broken files made by VDR
mru
parents:
1138
diff
changeset
|
62 else if(code == PRIVATE_STREAM_1) priv1++; |
2cfb5e02b299
detect audio-only program streams and broken files made by VDR
mru
parents:
1138
diff
changeset
|
63 else if(code == PACK_START_CODE) pspack++; |
2cfb5e02b299
detect audio-only program streams and broken files made by VDR
mru
parents:
1138
diff
changeset
|
64 else if((code & 0xf0) == VIDEO_ID) vid++; |
2cfb5e02b299
detect audio-only program streams and broken files made by VDR
mru
parents:
1138
diff
changeset
|
65 else if((code & 0xe0) == AUDIO_ID) audio++; |
165
e4d2f704bf80
- Looks a tiny bit harder in mpegps_probe() for a valid start code. This is
michaelni
parents:
65
diff
changeset
|
66 } |
0 | 67 } |
1257 | 68 |
69 if(vid || audio) /* invalid VDR files nd short PES streams */ | |
70 score= AVPROBE_SCORE_MAX/4; | |
71 | |
2311 | 72 //av_log(NULL, AV_LOG_ERROR, "%d %d %d %d %d len:%d\n", sys, priv1, pspack,vid, audio, p->buf_size); |
936 | 73 if(sys && sys*9 <= pspack*10) |
74 return AVPROBE_SCORE_MAX/2+2; // +1 for .mpg | |
1140
2cfb5e02b299
detect audio-only program streams and broken files made by VDR
mru
parents:
1138
diff
changeset
|
75 if((priv1 || vid || audio) && (priv1+vid+audio)*9 <= pspack*10) |
940 | 76 return AVPROBE_SCORE_MAX/2+2; // +1 for .mpg |
2312 | 77 if((!!vid ^ !!audio) && (audio+vid > 1) && !sys && !pspack && p->buf_size>2048) /* PES stream */ |
1140
2cfb5e02b299
detect audio-only program streams and broken files made by VDR
mru
parents:
1138
diff
changeset
|
78 return AVPROBE_SCORE_MAX/2+2; |
1257 | 79 |
80 //02-Penguin.flac has sys:0 priv1:0 pspack:0 vid:0 audio:1 | |
81 return score; | |
0 | 82 } |
83 | |
84 | |
85 typedef struct MpegDemuxContext { | |
1332 | 86 int32_t header_state; |
722 | 87 unsigned char psm_es_type[256]; |
0 | 88 } MpegDemuxContext; |
89 | |
310 | 90 static int mpegps_read_header(AVFormatContext *s, |
91 AVFormatParameters *ap) | |
92 { | |
93 MpegDemuxContext *m = s->priv_data; | |
94 m->header_state = 0xff; | |
95 s->ctx_flags |= AVFMTCTX_NOHEADER; | |
96 | |
97 /* no need to do more */ | |
98 return 0; | |
99 } | |
100 | |
101 static int64_t get_pts(ByteIOContext *pb, int c) | |
102 { | |
103 int64_t pts; | |
104 int val; | |
105 | |
106 if (c < 0) | |
107 c = get_byte(pb); | |
108 pts = (int64_t)((c >> 1) & 0x07) << 30; | |
109 val = get_be16(pb); | |
110 pts |= (int64_t)(val >> 1) << 15; | |
111 val = get_be16(pb); | |
112 pts |= (int64_t)(val >> 1); | |
113 return pts; | |
114 } | |
115 | |
885 | 116 static int find_next_start_code(ByteIOContext *pb, int *size_ptr, |
1332 | 117 int32_t *header_state) |
0 | 118 { |
119 unsigned int state, v; | |
120 int val, n; | |
121 | |
122 state = *header_state; | |
123 n = *size_ptr; | |
124 while (n > 0) { | |
125 if (url_feof(pb)) | |
126 break; | |
127 v = get_byte(pb); | |
128 n--; | |
129 if (state == 0x000001) { | |
130 state = ((state << 8) | v) & 0xffffff; | |
131 val = state; | |
132 goto found; | |
133 } | |
134 state = ((state << 8) | v) & 0xffffff; | |
135 } | |
136 val = -1; | |
137 found: | |
138 *header_state = state; | |
139 *size_ptr = n; | |
140 return val; | |
141 } | |
142 | |
683
095009fc2f35
kill warnings patch by (M«©ns Rullg«©rd <mru inprovide com>)
michael
parents:
674
diff
changeset
|
143 #if 0 /* unused, remove? */ |
310 | 144 /* XXX: optimize */ |
145 static int find_prev_start_code(ByteIOContext *pb, int *size_ptr) | |
0 | 146 { |
310 | 147 int64_t pos, pos_start; |
148 int max_size, start_code; | |
149 | |
150 max_size = *size_ptr; | |
151 pos_start = url_ftell(pb); | |
152 | |
153 /* in order to go faster, we fill the buffer */ | |
154 pos = pos_start - 16386; | |
155 if (pos < 0) | |
156 pos = 0; | |
157 url_fseek(pb, pos, SEEK_SET); | |
158 get_byte(pb); | |
293
62cec412a186
make AVFMT_NOHEADER flag dynamic - added av_open_input_stream()
bellard
parents:
291
diff
changeset
|
159 |
310 | 160 pos = pos_start; |
161 for(;;) { | |
162 pos--; | |
163 if (pos < 0 || (pos_start - pos) >= max_size) { | |
164 start_code = -1; | |
165 goto the_end; | |
166 } | |
167 url_fseek(pb, pos, SEEK_SET); | |
168 start_code = get_be32(pb); | |
169 if ((start_code & 0xffffff00) == 0x100) | |
170 break; | |
171 } | |
172 the_end: | |
173 *size_ptr = pos_start - pos; | |
174 return start_code; | |
0 | 175 } |
683
095009fc2f35
kill warnings patch by (M«©ns Rullg«©rd <mru inprovide com>)
michael
parents:
674
diff
changeset
|
176 #endif |
0 | 177 |
722 | 178 /** |
179 * Extracts stream types from a program stream map | |
180 * According to ISO/IEC 13818-1 ('MPEG-2 Systems') table 2-35 | |
885 | 181 * |
722 | 182 * @return number of bytes occupied by PSM in the bitstream |
183 */ | |
184 static long mpegps_psm_parse(MpegDemuxContext *m, ByteIOContext *pb) | |
185 { | |
186 int psm_length, ps_info_length, es_map_length; | |
187 | |
188 psm_length = get_be16(pb); | |
189 get_byte(pb); | |
190 get_byte(pb); | |
191 ps_info_length = get_be16(pb); | |
192 | |
193 /* skip program_stream_info */ | |
194 url_fskip(pb, ps_info_length); | |
195 es_map_length = get_be16(pb); | |
196 | |
197 /* at least one es available? */ | |
198 while (es_map_length >= 4){ | |
199 unsigned char type = get_byte(pb); | |
200 unsigned char es_id = get_byte(pb); | |
201 uint16_t es_info_length = get_be16(pb); | |
202 /* remember mapping from stream id to stream type */ | |
203 m->psm_es_type[es_id] = type; | |
204 /* skip program_stream_info */ | |
205 url_fskip(pb, es_info_length); | |
206 es_map_length -= 4 + es_info_length; | |
207 } | |
208 get_be32(pb); /* crc32 */ | |
209 return 2 + psm_length; | |
210 } | |
211 | |
885 | 212 /* read the next PES header. Return its position in ppos |
310 | 213 (if not NULL), and its start code, pts and dts. |
214 */ | |
215 static int mpegps_read_pes_header(AVFormatContext *s, | |
885 | 216 int64_t *ppos, int *pstart_code, |
437
50bae308f71e
moving nearly identical binary search code from nut/mpeg/asf to utils.c
michael
parents:
396
diff
changeset
|
217 int64_t *ppts, int64_t *pdts) |
0 | 218 { |
219 MpegDemuxContext *m = s->priv_data; | |
310 | 220 int len, size, startcode, c, flags, header_len; |
1759
9eaf71a70ac1
Revised patch for HD DVD .EVO demuxing by (Ian Caulfield <lowercase name seperated by . place at here gmail place a dot here com>)
michael
parents:
1668
diff
changeset
|
221 int pes_ext, ext2_len, id_ext, skip; |
1664
5e7460a2f209
seperate redo (we dont handle this possibly valid packet) from
michael
parents:
1443
diff
changeset
|
222 int64_t pts, dts; |
5e7460a2f209
seperate redo (we dont handle this possibly valid packet) from
michael
parents:
1443
diff
changeset
|
223 int64_t last_sync= url_ftell(&s->pb); |
0 | 224 |
1664
5e7460a2f209
seperate redo (we dont handle this possibly valid packet) from
michael
parents:
1443
diff
changeset
|
225 error_redo: |
5e7460a2f209
seperate redo (we dont handle this possibly valid packet) from
michael
parents:
1443
diff
changeset
|
226 url_fseek(&s->pb, last_sync, SEEK_SET); |
0 | 227 redo: |
310 | 228 /* next start code (should be immediately after) */ |
229 m->header_state = 0xff; | |
230 size = MAX_SYNC_SIZE; | |
231 startcode = find_next_start_code(&s->pb, &size, &m->header_state); | |
1664
5e7460a2f209
seperate redo (we dont handle this possibly valid packet) from
michael
parents:
1443
diff
changeset
|
232 last_sync = url_ftell(&s->pb); |
1443
404048ea11bc
Replace most of the %lld and %llx by their (cleaner) PRI*64 counterparts.
diego
parents:
1415
diff
changeset
|
233 //printf("startcode=%x pos=0x%"PRIx64"\n", startcode, url_ftell(&s->pb)); |
0 | 234 if (startcode < 0) |
2274
b21c2af60bc9
Replace all occurrences of AVERROR_IO with AVERROR(EIO).
takis
parents:
2177
diff
changeset
|
235 return AVERROR(EIO); |
0 | 236 if (startcode == PACK_START_CODE) |
237 goto redo; | |
238 if (startcode == SYSTEM_HEADER_START_CODE) | |
239 goto redo; | |
240 if (startcode == PADDING_STREAM || | |
241 startcode == PRIVATE_STREAM_2) { | |
242 /* skip them */ | |
243 len = get_be16(&s->pb); | |
244 url_fskip(&s->pb, len); | |
245 goto redo; | |
246 } | |
722 | 247 if (startcode == PROGRAM_STREAM_MAP) { |
248 mpegps_psm_parse(m, &s->pb); | |
249 goto redo; | |
250 } | |
885 | 251 |
0 | 252 /* find matching stream */ |
253 if (!((startcode >= 0x1c0 && startcode <= 0x1df) || | |
254 (startcode >= 0x1e0 && startcode <= 0x1ef) || | |
1759
9eaf71a70ac1
Revised patch for HD DVD .EVO demuxing by (Ian Caulfield <lowercase name seperated by . place at here gmail place a dot here com>)
michael
parents:
1668
diff
changeset
|
255 (startcode == 0x1bd) || (startcode == 0x1fd))) |
0 | 256 goto redo; |
310 | 257 if (ppos) { |
258 *ppos = url_ftell(&s->pb) - 4; | |
259 } | |
0 | 260 len = get_be16(&s->pb); |
1666 | 261 pts = |
0 | 262 dts = AV_NOPTS_VALUE; |
263 /* stuffing */ | |
264 for(;;) { | |
310 | 265 if (len < 1) |
1664
5e7460a2f209
seperate redo (we dont handle this possibly valid packet) from
michael
parents:
1443
diff
changeset
|
266 goto error_redo; |
0 | 267 c = get_byte(&s->pb); |
268 len--; | |
269 /* XXX: for mpeg1, should test only bit 7 */ | |
885 | 270 if (c != 0xff) |
0 | 271 break; |
272 } | |
273 if ((c & 0xc0) == 0x40) { | |
274 /* buffer scale & size */ | |
275 get_byte(&s->pb); | |
276 c = get_byte(&s->pb); | |
277 len -= 2; | |
278 } | |
1667 | 279 if ((c & 0xe0) == 0x20) { |
310 | 280 dts = pts = get_pts(&s->pb, c); |
0 | 281 len -= 4; |
1667 | 282 if (c & 0x10){ |
283 dts = get_pts(&s->pb, -1); | |
284 len -= 5; | |
285 } | |
0 | 286 } else if ((c & 0xc0) == 0x80) { |
287 /* mpeg 2 PES */ | |
1126 | 288 #if 0 /* some streams have this field set for no apparent reason */ |
0 | 289 if ((c & 0x30) != 0) { |
310 | 290 /* Encrypted multiplex not handled */ |
291 goto redo; | |
0 | 292 } |
1126 | 293 #endif |
0 | 294 flags = get_byte(&s->pb); |
295 header_len = get_byte(&s->pb); | |
296 len -= 2; | |
297 if (header_len > len) | |
1664
5e7460a2f209
seperate redo (we dont handle this possibly valid packet) from
michael
parents:
1443
diff
changeset
|
298 goto error_redo; |
1668 | 299 len -= header_len; |
1667 | 300 if (flags & 0x80) { |
310 | 301 dts = pts = get_pts(&s->pb, -1); |
0 | 302 header_len -= 5; |
1667 | 303 if (flags & 0x40) { |
304 dts = get_pts(&s->pb, -1); | |
305 header_len -= 5; | |
306 } | |
0 | 307 } |
1759
9eaf71a70ac1
Revised patch for HD DVD .EVO demuxing by (Ian Caulfield <lowercase name seperated by . place at here gmail place a dot here com>)
michael
parents:
1668
diff
changeset
|
308 if (flags & 0x01) { /* PES extension */ |
9eaf71a70ac1
Revised patch for HD DVD .EVO demuxing by (Ian Caulfield <lowercase name seperated by . place at here gmail place a dot here com>)
michael
parents:
1668
diff
changeset
|
309 pes_ext = get_byte(&s->pb); |
9eaf71a70ac1
Revised patch for HD DVD .EVO demuxing by (Ian Caulfield <lowercase name seperated by . place at here gmail place a dot here com>)
michael
parents:
1668
diff
changeset
|
310 header_len--; |
9eaf71a70ac1
Revised patch for HD DVD .EVO demuxing by (Ian Caulfield <lowercase name seperated by . place at here gmail place a dot here com>)
michael
parents:
1668
diff
changeset
|
311 if (pes_ext & 0x40) { /* pack header - should be zero in PS */ |
9eaf71a70ac1
Revised patch for HD DVD .EVO demuxing by (Ian Caulfield <lowercase name seperated by . place at here gmail place a dot here com>)
michael
parents:
1668
diff
changeset
|
312 goto error_redo; |
9eaf71a70ac1
Revised patch for HD DVD .EVO demuxing by (Ian Caulfield <lowercase name seperated by . place at here gmail place a dot here com>)
michael
parents:
1668
diff
changeset
|
313 } |
9eaf71a70ac1
Revised patch for HD DVD .EVO demuxing by (Ian Caulfield <lowercase name seperated by . place at here gmail place a dot here com>)
michael
parents:
1668
diff
changeset
|
314 /* Skip PES private data, program packet sequence counter and P-STD buffer */ |
9eaf71a70ac1
Revised patch for HD DVD .EVO demuxing by (Ian Caulfield <lowercase name seperated by . place at here gmail place a dot here com>)
michael
parents:
1668
diff
changeset
|
315 skip = (pes_ext >> 4) & 0xb; |
9eaf71a70ac1
Revised patch for HD DVD .EVO demuxing by (Ian Caulfield <lowercase name seperated by . place at here gmail place a dot here com>)
michael
parents:
1668
diff
changeset
|
316 skip += skip & 0x9; |
9eaf71a70ac1
Revised patch for HD DVD .EVO demuxing by (Ian Caulfield <lowercase name seperated by . place at here gmail place a dot here com>)
michael
parents:
1668
diff
changeset
|
317 url_fskip(&s->pb, skip); |
9eaf71a70ac1
Revised patch for HD DVD .EVO demuxing by (Ian Caulfield <lowercase name seperated by . place at here gmail place a dot here com>)
michael
parents:
1668
diff
changeset
|
318 header_len -= skip; |
9eaf71a70ac1
Revised patch for HD DVD .EVO demuxing by (Ian Caulfield <lowercase name seperated by . place at here gmail place a dot here com>)
michael
parents:
1668
diff
changeset
|
319 |
9eaf71a70ac1
Revised patch for HD DVD .EVO demuxing by (Ian Caulfield <lowercase name seperated by . place at here gmail place a dot here com>)
michael
parents:
1668
diff
changeset
|
320 if (pes_ext & 0x01) { /* PES extension 2 */ |
9eaf71a70ac1
Revised patch for HD DVD .EVO demuxing by (Ian Caulfield <lowercase name seperated by . place at here gmail place a dot here com>)
michael
parents:
1668
diff
changeset
|
321 ext2_len = get_byte(&s->pb); |
9eaf71a70ac1
Revised patch for HD DVD .EVO demuxing by (Ian Caulfield <lowercase name seperated by . place at here gmail place a dot here com>)
michael
parents:
1668
diff
changeset
|
322 header_len--; |
9eaf71a70ac1
Revised patch for HD DVD .EVO demuxing by (Ian Caulfield <lowercase name seperated by . place at here gmail place a dot here com>)
michael
parents:
1668
diff
changeset
|
323 if ((ext2_len & 0x7f) > 0) { |
9eaf71a70ac1
Revised patch for HD DVD .EVO demuxing by (Ian Caulfield <lowercase name seperated by . place at here gmail place a dot here com>)
michael
parents:
1668
diff
changeset
|
324 id_ext = get_byte(&s->pb); |
9eaf71a70ac1
Revised patch for HD DVD .EVO demuxing by (Ian Caulfield <lowercase name seperated by . place at here gmail place a dot here com>)
michael
parents:
1668
diff
changeset
|
325 if ((id_ext & 0x80) == 0) |
9eaf71a70ac1
Revised patch for HD DVD .EVO demuxing by (Ian Caulfield <lowercase name seperated by . place at here gmail place a dot here com>)
michael
parents:
1668
diff
changeset
|
326 startcode = ((startcode & 0xff) << 8) | id_ext; |
9eaf71a70ac1
Revised patch for HD DVD .EVO demuxing by (Ian Caulfield <lowercase name seperated by . place at here gmail place a dot here com>)
michael
parents:
1668
diff
changeset
|
327 header_len--; |
9eaf71a70ac1
Revised patch for HD DVD .EVO demuxing by (Ian Caulfield <lowercase name seperated by . place at here gmail place a dot here com>)
michael
parents:
1668
diff
changeset
|
328 } |
9eaf71a70ac1
Revised patch for HD DVD .EVO demuxing by (Ian Caulfield <lowercase name seperated by . place at here gmail place a dot here com>)
michael
parents:
1668
diff
changeset
|
329 } |
9eaf71a70ac1
Revised patch for HD DVD .EVO demuxing by (Ian Caulfield <lowercase name seperated by . place at here gmail place a dot here com>)
michael
parents:
1668
diff
changeset
|
330 } |
1668 | 331 if(header_len < 0) |
332 goto error_redo; | |
333 url_fskip(&s->pb, header_len); | |
0 | 334 } |
447
94aa265c18b9
Mpeg start codes patch by ("Dmitry Borisov" <jbors at mail dot ru>)
michael
parents:
437
diff
changeset
|
335 else if( c!= 0xf ) |
94aa265c18b9
Mpeg start codes patch by ("Dmitry Borisov" <jbors at mail dot ru>)
michael
parents:
437
diff
changeset
|
336 goto redo; |
94aa265c18b9
Mpeg start codes patch by ("Dmitry Borisov" <jbors at mail dot ru>)
michael
parents:
437
diff
changeset
|
337 |
722 | 338 if (startcode == PRIVATE_STREAM_1 && !m->psm_es_type[startcode & 0xff]) { |
0 | 339 startcode = get_byte(&s->pb); |
340 len--; | |
1759
9eaf71a70ac1
Revised patch for HD DVD .EVO demuxing by (Ian Caulfield <lowercase name seperated by . place at here gmail place a dot here com>)
michael
parents:
1668
diff
changeset
|
341 if (startcode >= 0x80 && startcode <= 0xcf) { |
0 | 342 /* audio: skip header */ |
343 get_byte(&s->pb); | |
344 get_byte(&s->pb); | |
345 get_byte(&s->pb); | |
346 len -= 3; | |
1759
9eaf71a70ac1
Revised patch for HD DVD .EVO demuxing by (Ian Caulfield <lowercase name seperated by . place at here gmail place a dot here com>)
michael
parents:
1668
diff
changeset
|
347 if (startcode >= 0xb0 && startcode <= 0xbf) { |
9eaf71a70ac1
Revised patch for HD DVD .EVO demuxing by (Ian Caulfield <lowercase name seperated by . place at here gmail place a dot here com>)
michael
parents:
1668
diff
changeset
|
348 /* MLP/TrueHD audio has a 4-byte header */ |
9eaf71a70ac1
Revised patch for HD DVD .EVO demuxing by (Ian Caulfield <lowercase name seperated by . place at here gmail place a dot here com>)
michael
parents:
1668
diff
changeset
|
349 get_byte(&s->pb); |
9eaf71a70ac1
Revised patch for HD DVD .EVO demuxing by (Ian Caulfield <lowercase name seperated by . place at here gmail place a dot here com>)
michael
parents:
1668
diff
changeset
|
350 len--; |
9eaf71a70ac1
Revised patch for HD DVD .EVO demuxing by (Ian Caulfield <lowercase name seperated by . place at here gmail place a dot here com>)
michael
parents:
1668
diff
changeset
|
351 } |
0 | 352 } |
353 } | |
1665 | 354 if(len<0) |
355 goto error_redo; | |
346
e154eb1b7149
caching of timestamps for mpeg-ps so seeking is faster
michael
parents:
337
diff
changeset
|
356 if(dts != AV_NOPTS_VALUE && ppos){ |
e154eb1b7149
caching of timestamps for mpeg-ps so seeking is faster
michael
parents:
337
diff
changeset
|
357 int i; |
e154eb1b7149
caching of timestamps for mpeg-ps so seeking is faster
michael
parents:
337
diff
changeset
|
358 for(i=0; i<s->nb_streams; i++){ |
e154eb1b7149
caching of timestamps for mpeg-ps so seeking is faster
michael
parents:
337
diff
changeset
|
359 if(startcode == s->streams[i]->id) { |
979 | 360 av_add_index_entry(s->streams[i], *ppos, dts, 0, 0, AVINDEX_KEYFRAME /* FIXME keyframe? */); |
346
e154eb1b7149
caching of timestamps for mpeg-ps so seeking is faster
michael
parents:
337
diff
changeset
|
361 } |
e154eb1b7149
caching of timestamps for mpeg-ps so seeking is faster
michael
parents:
337
diff
changeset
|
362 } |
e154eb1b7149
caching of timestamps for mpeg-ps so seeking is faster
michael
parents:
337
diff
changeset
|
363 } |
885 | 364 |
310 | 365 *pstart_code = startcode; |
366 *ppts = pts; | |
367 *pdts = dts; | |
368 return len; | |
369 } | |
370 | |
371 static int mpegps_read_packet(AVFormatContext *s, | |
372 AVPacket *pkt) | |
373 { | |
722 | 374 MpegDemuxContext *m = s->priv_data; |
310 | 375 AVStream *st; |
722 | 376 int len, startcode, i, type, codec_id = 0, es_type; |
346
e154eb1b7149
caching of timestamps for mpeg-ps so seeking is faster
michael
parents:
337
diff
changeset
|
377 int64_t pts, dts, dummy_pos; //dummy_pos is needed for the index building to work |
310 | 378 |
379 redo: | |
437
50bae308f71e
moving nearly identical binary search code from nut/mpeg/asf to utils.c
michael
parents:
396
diff
changeset
|
380 len = mpegps_read_pes_header(s, &dummy_pos, &startcode, &pts, &dts); |
310 | 381 if (len < 0) |
382 return len; | |
885 | 383 |
0 | 384 /* now find stream */ |
385 for(i=0;i<s->nb_streams;i++) { | |
386 st = s->streams[i]; | |
387 if (st->id == startcode) | |
388 goto found; | |
389 } | |
722 | 390 |
391 es_type = m->psm_es_type[startcode & 0xff]; | |
392 if(es_type > 0){ | |
393 if(es_type == STREAM_TYPE_VIDEO_MPEG1){ | |
394 codec_id = CODEC_ID_MPEG2VIDEO; | |
395 type = CODEC_TYPE_VIDEO; | |
396 } else if(es_type == STREAM_TYPE_VIDEO_MPEG2){ | |
397 codec_id = CODEC_ID_MPEG2VIDEO; | |
398 type = CODEC_TYPE_VIDEO; | |
399 } else if(es_type == STREAM_TYPE_AUDIO_MPEG1 || | |
400 es_type == STREAM_TYPE_AUDIO_MPEG2){ | |
401 codec_id = CODEC_ID_MP3; | |
402 type = CODEC_TYPE_AUDIO; | |
403 } else if(es_type == STREAM_TYPE_AUDIO_AAC){ | |
404 codec_id = CODEC_ID_AAC; | |
405 type = CODEC_TYPE_AUDIO; | |
406 } else if(es_type == STREAM_TYPE_VIDEO_MPEG4){ | |
407 codec_id = CODEC_ID_MPEG4; | |
408 type = CODEC_TYPE_VIDEO; | |
409 } else if(es_type == STREAM_TYPE_VIDEO_H264){ | |
410 codec_id = CODEC_ID_H264; | |
411 type = CODEC_TYPE_VIDEO; | |
412 } else if(es_type == STREAM_TYPE_AUDIO_AC3){ | |
413 codec_id = CODEC_ID_AC3; | |
414 type = CODEC_TYPE_AUDIO; | |
415 } else { | |
416 goto skip; | |
417 } | |
418 } else if (startcode >= 0x1e0 && startcode <= 0x1ef) { | |
1146 | 419 static const unsigned char avs_seqh[4] = { 0, 0, 1, 0xb0 }; |
420 unsigned char buf[8]; | |
421 get_buffer(&s->pb, buf, 8); | |
422 url_fseek(&s->pb, -8, SEEK_CUR); | |
423 if(!memcmp(buf, avs_seqh, 4) && (buf[6] != 0 || buf[7] != 1)) | |
424 codec_id = CODEC_ID_CAVS; | |
425 else | |
426 codec_id = CODEC_ID_MPEG2VIDEO; | |
0 | 427 type = CODEC_TYPE_VIDEO; |
428 } else if (startcode >= 0x1c0 && startcode <= 0x1df) { | |
429 type = CODEC_TYPE_AUDIO; | |
430 codec_id = CODEC_ID_MP2; | |
767
cbfea73709bd
fix ac3 and dts detection (patch by Joakim Plate <joakim.plate at ecce.se>)
mru
parents:
722
diff
changeset
|
431 } else if (startcode >= 0x80 && startcode <= 0x87) { |
0 | 432 type = CODEC_TYPE_AUDIO; |
433 codec_id = CODEC_ID_AC3; | |
1759
9eaf71a70ac1
Revised patch for HD DVD .EVO demuxing by (Ian Caulfield <lowercase name seperated by . place at here gmail place a dot here com>)
michael
parents:
1668
diff
changeset
|
434 } else if ((startcode >= 0x88 && startcode <= 0x8f) |
9eaf71a70ac1
Revised patch for HD DVD .EVO demuxing by (Ian Caulfield <lowercase name seperated by . place at here gmail place a dot here com>)
michael
parents:
1668
diff
changeset
|
435 ||( startcode >= 0x98 && startcode <= 0x9f)) { |
9eaf71a70ac1
Revised patch for HD DVD .EVO demuxing by (Ian Caulfield <lowercase name seperated by . place at here gmail place a dot here com>)
michael
parents:
1668
diff
changeset
|
436 /* 0x90 - 0x97 is reserved for SDDS in DVD specs */ |
496
112057e05179
libdts support by (Benjamin Zores <ben at geexbox dot org>)
michael
parents:
483
diff
changeset
|
437 type = CODEC_TYPE_AUDIO; |
112057e05179
libdts support by (Benjamin Zores <ben at geexbox dot org>)
michael
parents:
483
diff
changeset
|
438 codec_id = CODEC_ID_DTS; |
1759
9eaf71a70ac1
Revised patch for HD DVD .EVO demuxing by (Ian Caulfield <lowercase name seperated by . place at here gmail place a dot here com>)
michael
parents:
1668
diff
changeset
|
439 } else if (startcode >= 0xa0 && startcode <= 0xaf) { |
41 | 440 type = CODEC_TYPE_AUDIO; |
441 codec_id = CODEC_ID_PCM_S16BE; | |
1759
9eaf71a70ac1
Revised patch for HD DVD .EVO demuxing by (Ian Caulfield <lowercase name seperated by . place at here gmail place a dot here com>)
michael
parents:
1668
diff
changeset
|
442 } else if (startcode >= 0xb0 && startcode <= 0xbf) { |
9eaf71a70ac1
Revised patch for HD DVD .EVO demuxing by (Ian Caulfield <lowercase name seperated by . place at here gmail place a dot here com>)
michael
parents:
1668
diff
changeset
|
443 type = CODEC_TYPE_AUDIO; |
9eaf71a70ac1
Revised patch for HD DVD .EVO demuxing by (Ian Caulfield <lowercase name seperated by . place at here gmail place a dot here com>)
michael
parents:
1668
diff
changeset
|
444 codec_id = CODEC_ID_MLP; |
9eaf71a70ac1
Revised patch for HD DVD .EVO demuxing by (Ian Caulfield <lowercase name seperated by . place at here gmail place a dot here com>)
michael
parents:
1668
diff
changeset
|
445 } else if (startcode >= 0xc0 && startcode <= 0xcf) { |
9eaf71a70ac1
Revised patch for HD DVD .EVO demuxing by (Ian Caulfield <lowercase name seperated by . place at here gmail place a dot here com>)
michael
parents:
1668
diff
changeset
|
446 /* Used for both AC-3 and E-AC-3 in EVOB files */ |
9eaf71a70ac1
Revised patch for HD DVD .EVO demuxing by (Ian Caulfield <lowercase name seperated by . place at here gmail place a dot here com>)
michael
parents:
1668
diff
changeset
|
447 type = CODEC_TYPE_AUDIO; |
9eaf71a70ac1
Revised patch for HD DVD .EVO demuxing by (Ian Caulfield <lowercase name seperated by . place at here gmail place a dot here com>)
michael
parents:
1668
diff
changeset
|
448 codec_id = CODEC_ID_AC3; |
783
2e8b5a7d7e02
DVD subtitle parsing - show mpeg component IDs by default
bellard
parents:
767
diff
changeset
|
449 } else if (startcode >= 0x20 && startcode <= 0x3f) { |
2e8b5a7d7e02
DVD subtitle parsing - show mpeg component IDs by default
bellard
parents:
767
diff
changeset
|
450 type = CODEC_TYPE_SUBTITLE; |
2e8b5a7d7e02
DVD subtitle parsing - show mpeg component IDs by default
bellard
parents:
767
diff
changeset
|
451 codec_id = CODEC_ID_DVD_SUBTITLE; |
1759
9eaf71a70ac1
Revised patch for HD DVD .EVO demuxing by (Ian Caulfield <lowercase name seperated by . place at here gmail place a dot here com>)
michael
parents:
1668
diff
changeset
|
452 } else if (startcode >= 0xfd55 && startcode <= 0xfd5f) { |
9eaf71a70ac1
Revised patch for HD DVD .EVO demuxing by (Ian Caulfield <lowercase name seperated by . place at here gmail place a dot here com>)
michael
parents:
1668
diff
changeset
|
453 type = CODEC_TYPE_VIDEO; |
9eaf71a70ac1
Revised patch for HD DVD .EVO demuxing by (Ian Caulfield <lowercase name seperated by . place at here gmail place a dot here com>)
michael
parents:
1668
diff
changeset
|
454 codec_id = CODEC_ID_VC1; |
0 | 455 } else { |
456 skip: | |
457 /* skip packet */ | |
458 url_fskip(&s->pb, len); | |
459 goto redo; | |
460 } | |
461 /* no stream found: add a new stream */ | |
462 st = av_new_stream(s, startcode); | |
885 | 463 if (!st) |
0 | 464 goto skip; |
820
feca73904e67
changing AVCodecContext codec -> *codec in AVStream so additions to AVCodecContext dont randomize AVStream and break binary compatibility
michael
parents:
789
diff
changeset
|
465 st->codec->codec_type = type; |
feca73904e67
changing AVCodecContext codec -> *codec in AVStream so additions to AVCodecContext dont randomize AVStream and break binary compatibility
michael
parents:
789
diff
changeset
|
466 st->codec->codec_id = codec_id; |
310 | 467 if (codec_id != CODEC_ID_PCM_S16BE) |
2023 | 468 st->need_parsing = AVSTREAM_PARSE_FULL; |
0 | 469 found: |
708 | 470 if(st->discard >= AVDISCARD_ALL) |
652 | 471 goto skip; |
1759
9eaf71a70ac1
Revised patch for HD DVD .EVO demuxing by (Ian Caulfield <lowercase name seperated by . place at here gmail place a dot here com>)
michael
parents:
1668
diff
changeset
|
472 if (startcode >= 0xa0 && startcode <= 0xaf) { |
41 | 473 int b1, freq; |
474 | |
475 /* for LPCM, we just skip the header and consider it is raw | |
476 audio data */ | |
477 if (len <= 3) | |
478 goto skip; | |
479 get_byte(&s->pb); /* emphasis (1), muse(1), reserved(1), frame number(5) */ | |
480 b1 = get_byte(&s->pb); /* quant (2), freq(2), reserved(1), channels(3) */ | |
481 get_byte(&s->pb); /* dynamic range control (0x80 = off) */ | |
482 len -= 3; | |
483 freq = (b1 >> 4) & 3; | |
820
feca73904e67
changing AVCodecContext codec -> *codec in AVStream so additions to AVCodecContext dont randomize AVStream and break binary compatibility
michael
parents:
789
diff
changeset
|
484 st->codec->sample_rate = lpcm_freq_tab[freq]; |
feca73904e67
changing AVCodecContext codec -> *codec in AVStream so additions to AVCodecContext dont randomize AVStream and break binary compatibility
michael
parents:
789
diff
changeset
|
485 st->codec->channels = 1 + (b1 & 7); |
feca73904e67
changing AVCodecContext codec -> *codec in AVStream so additions to AVCodecContext dont randomize AVStream and break binary compatibility
michael
parents:
789
diff
changeset
|
486 st->codec->bit_rate = st->codec->channels * st->codec->sample_rate * 2; |
41 | 487 } |
0 | 488 av_new_packet(pkt, len); |
489 get_buffer(&s->pb, pkt->data, pkt->size); | |
490 pkt->pts = pts; | |
310 | 491 pkt->dts = dts; |
0 | 492 pkt->stream_index = st->index; |
331
4530681af424
suppress PTS in packets when not needed (slightly smaller files), fixed PTS generation in some cases, added provision for DTS generation, slightly better SCR generation (initial patch by Michel Bardiaux)
bellard
parents:
310
diff
changeset
|
493 #if 0 |
652 | 494 av_log(s, AV_LOG_DEBUG, "%d: pts=%0.3f dts=%0.3f size=%d\n", |
495 pkt->stream_index, pkt->pts / 90000.0, pkt->dts / 90000.0, pkt->size); | |
331
4530681af424
suppress PTS in packets when not needed (slightly smaller files), fixed PTS generation in some cases, added provision for DTS generation, slightly better SCR generation (initial patch by Michel Bardiaux)
bellard
parents:
310
diff
changeset
|
496 #endif |
482 | 497 |
0 | 498 return 0; |
499 } | |
500 | |
501 static int mpegps_read_close(AVFormatContext *s) | |
502 { | |
503 return 0; | |
504 } | |
505 | |
885 | 506 static int64_t mpegps_read_dts(AVFormatContext *s, int stream_index, |
437
50bae308f71e
moving nearly identical binary search code from nut/mpeg/asf to utils.c
michael
parents:
396
diff
changeset
|
507 int64_t *ppos, int64_t pos_limit) |
310 | 508 { |
509 int len, startcode; | |
510 int64_t pos, pts, dts; | |
511 | |
512 pos = *ppos; | |
513 #ifdef DEBUG_SEEK | |
1443
404048ea11bc
Replace most of the %lld and %llx by their (cleaner) PRI*64 counterparts.
diego
parents:
1415
diff
changeset
|
514 printf("read_dts: pos=0x%"PRIx64" next=%d -> ", pos, find_next); |
310 | 515 #endif |
516 url_fseek(&s->pb, pos, SEEK_SET); | |
517 for(;;) { | |
437
50bae308f71e
moving nearly identical binary search code from nut/mpeg/asf to utils.c
michael
parents:
396
diff
changeset
|
518 len = mpegps_read_pes_header(s, &pos, &startcode, &pts, &dts); |
310 | 519 if (len < 0) { |
520 #ifdef DEBUG_SEEK | |
521 printf("none (ret=%d)\n", len); | |
522 #endif | |
523 return AV_NOPTS_VALUE; | |
524 } | |
885 | 525 if (startcode == s->streams[stream_index]->id && |
310 | 526 dts != AV_NOPTS_VALUE) { |
527 break; | |
528 } | |
437
50bae308f71e
moving nearly identical binary search code from nut/mpeg/asf to utils.c
michael
parents:
396
diff
changeset
|
529 url_fskip(&s->pb, len); |
310 | 530 } |
531 #ifdef DEBUG_SEEK | |
1443
404048ea11bc
Replace most of the %lld and %llx by their (cleaner) PRI*64 counterparts.
diego
parents:
1415
diff
changeset
|
532 printf("pos=0x%"PRIx64" dts=0x%"PRIx64" %0.3f\n", pos, dts, dts / 90000.0); |
310 | 533 #endif |
534 *ppos = pos; | |
463
696f41bc8784
store index for seeking in the native timebase of each stream
michael
parents:
452
diff
changeset
|
535 return dts; |
310 | 536 } |
537 | |
1167 | 538 AVInputFormat mpegps_demuxer = { |
0 | 539 "mpeg", |
540 "MPEG PS format", | |
541 sizeof(MpegDemuxContext), | |
542 mpegps_probe, | |
543 mpegps_read_header, | |
544 mpegps_read_packet, | |
545 mpegps_read_close, | |
437
50bae308f71e
moving nearly identical binary search code from nut/mpeg/asf to utils.c
michael
parents:
396
diff
changeset
|
546 NULL, //mpegps_read_seek, |
50bae308f71e
moving nearly identical binary search code from nut/mpeg/asf to utils.c
michael
parents:
396
diff
changeset
|
547 mpegps_read_dts, |
783
2e8b5a7d7e02
DVD subtitle parsing - show mpeg component IDs by default
bellard
parents:
767
diff
changeset
|
548 .flags = AVFMT_SHOW_IDS, |
0 | 549 }; |