Mercurial > libavformat.hg
annotate mpeg.c @ 2715:c15be6c85ab4 libavformat
Add some explanatory comments.
author | diego |
---|---|
date | Wed, 07 Nov 2007 22:02:02 +0000 |
parents | 26a111e617a8 |
children | 1bbb4fa1cdcd |
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 | |
2697
afbdd52324e3
fix misdetection of mp3could_not_find_codec_parameters.mp3
michael
parents:
2695
diff
changeset
|
47 static int check_pes(uint8_t *p, uint8_t *end){ |
afbdd52324e3
fix misdetection of mp3could_not_find_codec_parameters.mp3
michael
parents:
2695
diff
changeset
|
48 int pes1; |
afbdd52324e3
fix misdetection of mp3could_not_find_codec_parameters.mp3
michael
parents:
2695
diff
changeset
|
49 int pes2= (p[3] & 0xC0) == 0x80 |
afbdd52324e3
fix misdetection of mp3could_not_find_codec_parameters.mp3
michael
parents:
2695
diff
changeset
|
50 && (p[4] & 0xC0) != 0x40 |
afbdd52324e3
fix misdetection of mp3could_not_find_codec_parameters.mp3
michael
parents:
2695
diff
changeset
|
51 &&((p[4] & 0xC0) == 0x00 || (p[4]&0xC0)>>2 == (p[6]&0xF0)); |
afbdd52324e3
fix misdetection of mp3could_not_find_codec_parameters.mp3
michael
parents:
2695
diff
changeset
|
52 |
afbdd52324e3
fix misdetection of mp3could_not_find_codec_parameters.mp3
michael
parents:
2695
diff
changeset
|
53 for(p+=3; p<end && *p == 0xFF; p++); |
afbdd52324e3
fix misdetection of mp3could_not_find_codec_parameters.mp3
michael
parents:
2695
diff
changeset
|
54 if((*p&0xC0) == 0x40) p+=2; |
afbdd52324e3
fix misdetection of mp3could_not_find_codec_parameters.mp3
michael
parents:
2695
diff
changeset
|
55 if((*p&0xF0) == 0x20){ |
afbdd52324e3
fix misdetection of mp3could_not_find_codec_parameters.mp3
michael
parents:
2695
diff
changeset
|
56 pes1= p[0]&p[2]&p[4]&1; |
afbdd52324e3
fix misdetection of mp3could_not_find_codec_parameters.mp3
michael
parents:
2695
diff
changeset
|
57 p+=5; |
afbdd52324e3
fix misdetection of mp3could_not_find_codec_parameters.mp3
michael
parents:
2695
diff
changeset
|
58 }else if((*p&0xF0) == 0x30){ |
afbdd52324e3
fix misdetection of mp3could_not_find_codec_parameters.mp3
michael
parents:
2695
diff
changeset
|
59 pes1= p[0]&p[2]&p[4]&p[5]&p[7]&p[9]&1; |
afbdd52324e3
fix misdetection of mp3could_not_find_codec_parameters.mp3
michael
parents:
2695
diff
changeset
|
60 p+=10; |
afbdd52324e3
fix misdetection of mp3could_not_find_codec_parameters.mp3
michael
parents:
2695
diff
changeset
|
61 }else |
afbdd52324e3
fix misdetection of mp3could_not_find_codec_parameters.mp3
michael
parents:
2695
diff
changeset
|
62 pes1 = *p == 0x0F; |
afbdd52324e3
fix misdetection of mp3could_not_find_codec_parameters.mp3
michael
parents:
2695
diff
changeset
|
63 |
afbdd52324e3
fix misdetection of mp3could_not_find_codec_parameters.mp3
michael
parents:
2695
diff
changeset
|
64 return pes1||pes2; |
afbdd52324e3
fix misdetection of mp3could_not_find_codec_parameters.mp3
michael
parents:
2695
diff
changeset
|
65 } |
afbdd52324e3
fix misdetection of mp3could_not_find_codec_parameters.mp3
michael
parents:
2695
diff
changeset
|
66 |
0 | 67 static int mpegps_probe(AVProbeData *p) |
68 { | |
936 | 69 uint32_t code= -1; |
1138
36ce24677f96
detect MPEG PES streams as MPEG PS; the PS demuxer will cope
mru
parents:
1126
diff
changeset
|
70 int sys=0, pspack=0, priv1=0, vid=0, audio=0; |
539 | 71 int i; |
1257 | 72 int score=0; |
49 | 73 |
1284 | 74 score = cdxa_probe(p); |
75 if (score > 0) return score; | |
76 | |
77 /* Search for MPEG stream */ | |
936 | 78 for(i=0; i<p->buf_size; i++){ |
79 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
|
80 if ((code & 0xffffff00) == 0x100) { |
2698 | 81 int pes= check_pes(p->buf+i, p->buf+p->buf_size); |
2697
afbdd52324e3
fix misdetection of mp3could_not_find_codec_parameters.mp3
michael
parents:
2695
diff
changeset
|
82 |
1140
2cfb5e02b299
detect audio-only program streams and broken files made by VDR
mru
parents:
1138
diff
changeset
|
83 if(code == SYSTEM_HEADER_START_CODE) sys++; |
2cfb5e02b299
detect audio-only program streams and broken files made by VDR
mru
parents:
1138
diff
changeset
|
84 else if(code == PRIVATE_STREAM_1) priv1++; |
2cfb5e02b299
detect audio-only program streams and broken files made by VDR
mru
parents:
1138
diff
changeset
|
85 else if(code == PACK_START_CODE) pspack++; |
2697
afbdd52324e3
fix misdetection of mp3could_not_find_codec_parameters.mp3
michael
parents:
2695
diff
changeset
|
86 else if((code & 0xf0) == VIDEO_ID && pes) vid++; |
afbdd52324e3
fix misdetection of mp3could_not_find_codec_parameters.mp3
michael
parents:
2695
diff
changeset
|
87 else if((code & 0xe0) == AUDIO_ID && pes) audio++; |
165
e4d2f704bf80
- Looks a tiny bit harder in mpegps_probe() for a valid start code. This is
michaelni
parents:
65
diff
changeset
|
88 } |
0 | 89 } |
1257 | 90 |
91 if(vid || audio) /* invalid VDR files nd short PES streams */ | |
92 score= AVPROBE_SCORE_MAX/4; | |
93 | |
2311 | 94 //av_log(NULL, AV_LOG_ERROR, "%d %d %d %d %d len:%d\n", sys, priv1, pspack,vid, audio, p->buf_size); |
936 | 95 if(sys && sys*9 <= pspack*10) |
96 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
|
97 if((priv1 || vid || audio) && (priv1+vid+audio)*9 <= pspack*10) |
940 | 98 return AVPROBE_SCORE_MAX/2+2; // +1 for .mpg |
2312 | 99 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
|
100 return AVPROBE_SCORE_MAX/2+2; |
1257 | 101 |
102 //02-Penguin.flac has sys:0 priv1:0 pspack:0 vid:0 audio:1 | |
103 return score; | |
0 | 104 } |
105 | |
106 | |
107 typedef struct MpegDemuxContext { | |
1332 | 108 int32_t header_state; |
722 | 109 unsigned char psm_es_type[256]; |
0 | 110 } MpegDemuxContext; |
111 | |
310 | 112 static int mpegps_read_header(AVFormatContext *s, |
113 AVFormatParameters *ap) | |
114 { | |
115 MpegDemuxContext *m = s->priv_data; | |
116 m->header_state = 0xff; | |
117 s->ctx_flags |= AVFMTCTX_NOHEADER; | |
118 | |
119 /* no need to do more */ | |
120 return 0; | |
121 } | |
122 | |
123 static int64_t get_pts(ByteIOContext *pb, int c) | |
124 { | |
125 int64_t pts; | |
126 int val; | |
127 | |
128 if (c < 0) | |
129 c = get_byte(pb); | |
130 pts = (int64_t)((c >> 1) & 0x07) << 30; | |
131 val = get_be16(pb); | |
132 pts |= (int64_t)(val >> 1) << 15; | |
133 val = get_be16(pb); | |
134 pts |= (int64_t)(val >> 1); | |
135 return pts; | |
136 } | |
137 | |
885 | 138 static int find_next_start_code(ByteIOContext *pb, int *size_ptr, |
1332 | 139 int32_t *header_state) |
0 | 140 { |
141 unsigned int state, v; | |
142 int val, n; | |
143 | |
144 state = *header_state; | |
145 n = *size_ptr; | |
146 while (n > 0) { | |
147 if (url_feof(pb)) | |
148 break; | |
149 v = get_byte(pb); | |
150 n--; | |
151 if (state == 0x000001) { | |
152 state = ((state << 8) | v) & 0xffffff; | |
153 val = state; | |
154 goto found; | |
155 } | |
156 state = ((state << 8) | v) & 0xffffff; | |
157 } | |
158 val = -1; | |
159 found: | |
160 *header_state = state; | |
161 *size_ptr = n; | |
162 return val; | |
163 } | |
164 | |
683
095009fc2f35
kill warnings patch by (M«©ns Rullg«©rd <mru inprovide com>)
michael
parents:
674
diff
changeset
|
165 #if 0 /* unused, remove? */ |
310 | 166 /* XXX: optimize */ |
167 static int find_prev_start_code(ByteIOContext *pb, int *size_ptr) | |
0 | 168 { |
310 | 169 int64_t pos, pos_start; |
170 int max_size, start_code; | |
171 | |
172 max_size = *size_ptr; | |
173 pos_start = url_ftell(pb); | |
174 | |
175 /* in order to go faster, we fill the buffer */ | |
176 pos = pos_start - 16386; | |
177 if (pos < 0) | |
178 pos = 0; | |
179 url_fseek(pb, pos, SEEK_SET); | |
180 get_byte(pb); | |
293
62cec412a186
make AVFMT_NOHEADER flag dynamic - added av_open_input_stream()
bellard
parents:
291
diff
changeset
|
181 |
310 | 182 pos = pos_start; |
183 for(;;) { | |
184 pos--; | |
185 if (pos < 0 || (pos_start - pos) >= max_size) { | |
186 start_code = -1; | |
187 goto the_end; | |
188 } | |
189 url_fseek(pb, pos, SEEK_SET); | |
190 start_code = get_be32(pb); | |
191 if ((start_code & 0xffffff00) == 0x100) | |
192 break; | |
193 } | |
194 the_end: | |
195 *size_ptr = pos_start - pos; | |
196 return start_code; | |
0 | 197 } |
683
095009fc2f35
kill warnings patch by (M«©ns Rullg«©rd <mru inprovide com>)
michael
parents:
674
diff
changeset
|
198 #endif |
0 | 199 |
722 | 200 /** |
201 * Extracts stream types from a program stream map | |
202 * According to ISO/IEC 13818-1 ('MPEG-2 Systems') table 2-35 | |
885 | 203 * |
722 | 204 * @return number of bytes occupied by PSM in the bitstream |
205 */ | |
206 static long mpegps_psm_parse(MpegDemuxContext *m, ByteIOContext *pb) | |
207 { | |
208 int psm_length, ps_info_length, es_map_length; | |
209 | |
210 psm_length = get_be16(pb); | |
211 get_byte(pb); | |
212 get_byte(pb); | |
213 ps_info_length = get_be16(pb); | |
214 | |
215 /* skip program_stream_info */ | |
216 url_fskip(pb, ps_info_length); | |
217 es_map_length = get_be16(pb); | |
218 | |
219 /* at least one es available? */ | |
220 while (es_map_length >= 4){ | |
221 unsigned char type = get_byte(pb); | |
222 unsigned char es_id = get_byte(pb); | |
223 uint16_t es_info_length = get_be16(pb); | |
224 /* remember mapping from stream id to stream type */ | |
225 m->psm_es_type[es_id] = type; | |
226 /* skip program_stream_info */ | |
227 url_fskip(pb, es_info_length); | |
228 es_map_length -= 4 + es_info_length; | |
229 } | |
230 get_be32(pb); /* crc32 */ | |
231 return 2 + psm_length; | |
232 } | |
233 | |
885 | 234 /* read the next PES header. Return its position in ppos |
310 | 235 (if not NULL), and its start code, pts and dts. |
236 */ | |
237 static int mpegps_read_pes_header(AVFormatContext *s, | |
885 | 238 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
|
239 int64_t *ppts, int64_t *pdts) |
0 | 240 { |
241 MpegDemuxContext *m = s->priv_data; | |
310 | 242 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
|
243 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
|
244 int64_t pts, dts; |
5e7460a2f209
seperate redo (we dont handle this possibly valid packet) from
michael
parents:
1443
diff
changeset
|
245 int64_t last_sync= url_ftell(&s->pb); |
0 | 246 |
1664
5e7460a2f209
seperate redo (we dont handle this possibly valid packet) from
michael
parents:
1443
diff
changeset
|
247 error_redo: |
5e7460a2f209
seperate redo (we dont handle this possibly valid packet) from
michael
parents:
1443
diff
changeset
|
248 url_fseek(&s->pb, last_sync, SEEK_SET); |
0 | 249 redo: |
310 | 250 /* next start code (should be immediately after) */ |
251 m->header_state = 0xff; | |
252 size = MAX_SYNC_SIZE; | |
253 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
|
254 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
|
255 //printf("startcode=%x pos=0x%"PRIx64"\n", startcode, url_ftell(&s->pb)); |
0 | 256 if (startcode < 0) |
2274
b21c2af60bc9
Replace all occurrences of AVERROR_IO with AVERROR(EIO).
takis
parents:
2177
diff
changeset
|
257 return AVERROR(EIO); |
0 | 258 if (startcode == PACK_START_CODE) |
259 goto redo; | |
260 if (startcode == SYSTEM_HEADER_START_CODE) | |
261 goto redo; | |
262 if (startcode == PADDING_STREAM || | |
263 startcode == PRIVATE_STREAM_2) { | |
264 /* skip them */ | |
265 len = get_be16(&s->pb); | |
266 url_fskip(&s->pb, len); | |
267 goto redo; | |
268 } | |
722 | 269 if (startcode == PROGRAM_STREAM_MAP) { |
270 mpegps_psm_parse(m, &s->pb); | |
271 goto redo; | |
272 } | |
885 | 273 |
0 | 274 /* find matching stream */ |
275 if (!((startcode >= 0x1c0 && startcode <= 0x1df) || | |
276 (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
|
277 (startcode == 0x1bd) || (startcode == 0x1fd))) |
0 | 278 goto redo; |
310 | 279 if (ppos) { |
280 *ppos = url_ftell(&s->pb) - 4; | |
281 } | |
0 | 282 len = get_be16(&s->pb); |
1666 | 283 pts = |
0 | 284 dts = AV_NOPTS_VALUE; |
285 /* stuffing */ | |
286 for(;;) { | |
310 | 287 if (len < 1) |
1664
5e7460a2f209
seperate redo (we dont handle this possibly valid packet) from
michael
parents:
1443
diff
changeset
|
288 goto error_redo; |
0 | 289 c = get_byte(&s->pb); |
290 len--; | |
291 /* XXX: for mpeg1, should test only bit 7 */ | |
885 | 292 if (c != 0xff) |
0 | 293 break; |
294 } | |
295 if ((c & 0xc0) == 0x40) { | |
296 /* buffer scale & size */ | |
297 get_byte(&s->pb); | |
298 c = get_byte(&s->pb); | |
299 len -= 2; | |
300 } | |
1667 | 301 if ((c & 0xe0) == 0x20) { |
310 | 302 dts = pts = get_pts(&s->pb, c); |
0 | 303 len -= 4; |
1667 | 304 if (c & 0x10){ |
305 dts = get_pts(&s->pb, -1); | |
306 len -= 5; | |
307 } | |
0 | 308 } else if ((c & 0xc0) == 0x80) { |
309 /* mpeg 2 PES */ | |
1126 | 310 #if 0 /* some streams have this field set for no apparent reason */ |
0 | 311 if ((c & 0x30) != 0) { |
310 | 312 /* Encrypted multiplex not handled */ |
313 goto redo; | |
0 | 314 } |
1126 | 315 #endif |
0 | 316 flags = get_byte(&s->pb); |
317 header_len = get_byte(&s->pb); | |
318 len -= 2; | |
319 if (header_len > len) | |
1664
5e7460a2f209
seperate redo (we dont handle this possibly valid packet) from
michael
parents:
1443
diff
changeset
|
320 goto error_redo; |
1668 | 321 len -= header_len; |
1667 | 322 if (flags & 0x80) { |
310 | 323 dts = pts = get_pts(&s->pb, -1); |
0 | 324 header_len -= 5; |
1667 | 325 if (flags & 0x40) { |
326 dts = get_pts(&s->pb, -1); | |
327 header_len -= 5; | |
328 } | |
0 | 329 } |
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
|
330 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
|
331 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
|
332 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
|
333 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
|
334 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
|
335 } |
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
|
336 /* 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
|
337 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
|
338 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
|
339 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
|
340 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
|
341 |
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
|
342 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
|
343 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
|
344 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
|
345 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
|
346 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
|
347 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
|
348 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
|
349 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
|
350 } |
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 } |
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
|
352 } |
1668 | 353 if(header_len < 0) |
354 goto error_redo; | |
355 url_fskip(&s->pb, header_len); | |
0 | 356 } |
447
94aa265c18b9
Mpeg start codes patch by ("Dmitry Borisov" <jbors at mail dot ru>)
michael
parents:
437
diff
changeset
|
357 else if( c!= 0xf ) |
94aa265c18b9
Mpeg start codes patch by ("Dmitry Borisov" <jbors at mail dot ru>)
michael
parents:
437
diff
changeset
|
358 goto redo; |
94aa265c18b9
Mpeg start codes patch by ("Dmitry Borisov" <jbors at mail dot ru>)
michael
parents:
437
diff
changeset
|
359 |
722 | 360 if (startcode == PRIVATE_STREAM_1 && !m->psm_es_type[startcode & 0xff]) { |
0 | 361 startcode = get_byte(&s->pb); |
362 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
|
363 if (startcode >= 0x80 && startcode <= 0xcf) { |
0 | 364 /* audio: skip header */ |
365 get_byte(&s->pb); | |
366 get_byte(&s->pb); | |
367 get_byte(&s->pb); | |
368 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
|
369 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
|
370 /* 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
|
371 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
|
372 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
|
373 } |
0 | 374 } |
375 } | |
1665 | 376 if(len<0) |
377 goto error_redo; | |
346
e154eb1b7149
caching of timestamps for mpeg-ps so seeking is faster
michael
parents:
337
diff
changeset
|
378 if(dts != AV_NOPTS_VALUE && ppos){ |
e154eb1b7149
caching of timestamps for mpeg-ps so seeking is faster
michael
parents:
337
diff
changeset
|
379 int i; |
e154eb1b7149
caching of timestamps for mpeg-ps so seeking is faster
michael
parents:
337
diff
changeset
|
380 for(i=0; i<s->nb_streams; i++){ |
e154eb1b7149
caching of timestamps for mpeg-ps so seeking is faster
michael
parents:
337
diff
changeset
|
381 if(startcode == s->streams[i]->id) { |
979 | 382 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
|
383 } |
e154eb1b7149
caching of timestamps for mpeg-ps so seeking is faster
michael
parents:
337
diff
changeset
|
384 } |
e154eb1b7149
caching of timestamps for mpeg-ps so seeking is faster
michael
parents:
337
diff
changeset
|
385 } |
885 | 386 |
310 | 387 *pstart_code = startcode; |
388 *ppts = pts; | |
389 *pdts = dts; | |
390 return len; | |
391 } | |
392 | |
393 static int mpegps_read_packet(AVFormatContext *s, | |
394 AVPacket *pkt) | |
395 { | |
722 | 396 MpegDemuxContext *m = s->priv_data; |
310 | 397 AVStream *st; |
722 | 398 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
|
399 int64_t pts, dts, dummy_pos; //dummy_pos is needed for the index building to work |
310 | 400 |
401 redo: | |
437
50bae308f71e
moving nearly identical binary search code from nut/mpeg/asf to utils.c
michael
parents:
396
diff
changeset
|
402 len = mpegps_read_pes_header(s, &dummy_pos, &startcode, &pts, &dts); |
310 | 403 if (len < 0) |
404 return len; | |
885 | 405 |
0 | 406 /* now find stream */ |
407 for(i=0;i<s->nb_streams;i++) { | |
408 st = s->streams[i]; | |
409 if (st->id == startcode) | |
410 goto found; | |
411 } | |
722 | 412 |
413 es_type = m->psm_es_type[startcode & 0xff]; | |
414 if(es_type > 0){ | |
415 if(es_type == STREAM_TYPE_VIDEO_MPEG1){ | |
416 codec_id = CODEC_ID_MPEG2VIDEO; | |
417 type = CODEC_TYPE_VIDEO; | |
418 } else if(es_type == STREAM_TYPE_VIDEO_MPEG2){ | |
419 codec_id = CODEC_ID_MPEG2VIDEO; | |
420 type = CODEC_TYPE_VIDEO; | |
421 } else if(es_type == STREAM_TYPE_AUDIO_MPEG1 || | |
422 es_type == STREAM_TYPE_AUDIO_MPEG2){ | |
423 codec_id = CODEC_ID_MP3; | |
424 type = CODEC_TYPE_AUDIO; | |
425 } else if(es_type == STREAM_TYPE_AUDIO_AAC){ | |
426 codec_id = CODEC_ID_AAC; | |
427 type = CODEC_TYPE_AUDIO; | |
428 } else if(es_type == STREAM_TYPE_VIDEO_MPEG4){ | |
429 codec_id = CODEC_ID_MPEG4; | |
430 type = CODEC_TYPE_VIDEO; | |
431 } else if(es_type == STREAM_TYPE_VIDEO_H264){ | |
432 codec_id = CODEC_ID_H264; | |
433 type = CODEC_TYPE_VIDEO; | |
434 } else if(es_type == STREAM_TYPE_AUDIO_AC3){ | |
435 codec_id = CODEC_ID_AC3; | |
436 type = CODEC_TYPE_AUDIO; | |
437 } else { | |
438 goto skip; | |
439 } | |
440 } else if (startcode >= 0x1e0 && startcode <= 0x1ef) { | |
1146 | 441 static const unsigned char avs_seqh[4] = { 0, 0, 1, 0xb0 }; |
442 unsigned char buf[8]; | |
443 get_buffer(&s->pb, buf, 8); | |
444 url_fseek(&s->pb, -8, SEEK_CUR); | |
445 if(!memcmp(buf, avs_seqh, 4) && (buf[6] != 0 || buf[7] != 1)) | |
446 codec_id = CODEC_ID_CAVS; | |
447 else | |
448 codec_id = CODEC_ID_MPEG2VIDEO; | |
0 | 449 type = CODEC_TYPE_VIDEO; |
450 } else if (startcode >= 0x1c0 && startcode <= 0x1df) { | |
451 type = CODEC_TYPE_AUDIO; | |
2695 | 452 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
|
453 } else if (startcode >= 0x80 && startcode <= 0x87) { |
0 | 454 type = CODEC_TYPE_AUDIO; |
455 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
|
456 } 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
|
457 ||( 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
|
458 /* 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
|
459 type = CODEC_TYPE_AUDIO; |
112057e05179
libdts support by (Benjamin Zores <ben at geexbox dot org>)
michael
parents:
483
diff
changeset
|
460 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
|
461 } else if (startcode >= 0xa0 && startcode <= 0xaf) { |
41 | 462 type = CODEC_TYPE_AUDIO; |
463 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
|
464 } 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
|
465 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
|
466 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
|
467 } 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
|
468 /* 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
|
469 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
|
470 codec_id = CODEC_ID_AC3; |
783
2e8b5a7d7e02
DVD subtitle parsing - show mpeg component IDs by default
bellard
parents:
767
diff
changeset
|
471 } else if (startcode >= 0x20 && startcode <= 0x3f) { |
2e8b5a7d7e02
DVD subtitle parsing - show mpeg component IDs by default
bellard
parents:
767
diff
changeset
|
472 type = CODEC_TYPE_SUBTITLE; |
2e8b5a7d7e02
DVD subtitle parsing - show mpeg component IDs by default
bellard
parents:
767
diff
changeset
|
473 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
|
474 } 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
|
475 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
|
476 codec_id = CODEC_ID_VC1; |
0 | 477 } else { |
478 skip: | |
479 /* skip packet */ | |
480 url_fskip(&s->pb, len); | |
481 goto redo; | |
482 } | |
483 /* no stream found: add a new stream */ | |
484 st = av_new_stream(s, startcode); | |
885 | 485 if (!st) |
0 | 486 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
|
487 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
|
488 st->codec->codec_id = codec_id; |
310 | 489 if (codec_id != CODEC_ID_PCM_S16BE) |
2023 | 490 st->need_parsing = AVSTREAM_PARSE_FULL; |
0 | 491 found: |
708 | 492 if(st->discard >= AVDISCARD_ALL) |
652 | 493 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
|
494 if (startcode >= 0xa0 && startcode <= 0xaf) { |
41 | 495 int b1, freq; |
496 | |
497 /* for LPCM, we just skip the header and consider it is raw | |
498 audio data */ | |
499 if (len <= 3) | |
500 goto skip; | |
501 get_byte(&s->pb); /* emphasis (1), muse(1), reserved(1), frame number(5) */ | |
502 b1 = get_byte(&s->pb); /* quant (2), freq(2), reserved(1), channels(3) */ | |
503 get_byte(&s->pb); /* dynamic range control (0x80 = off) */ | |
504 len -= 3; | |
505 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
|
506 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
|
507 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
|
508 st->codec->bit_rate = st->codec->channels * st->codec->sample_rate * 2; |
41 | 509 } |
0 | 510 av_new_packet(pkt, len); |
511 get_buffer(&s->pb, pkt->data, pkt->size); | |
512 pkt->pts = pts; | |
310 | 513 pkt->dts = dts; |
0 | 514 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
|
515 #if 0 |
652 | 516 av_log(s, AV_LOG_DEBUG, "%d: pts=%0.3f dts=%0.3f size=%d\n", |
517 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
|
518 #endif |
482 | 519 |
0 | 520 return 0; |
521 } | |
522 | |
523 static int mpegps_read_close(AVFormatContext *s) | |
524 { | |
525 return 0; | |
526 } | |
527 | |
885 | 528 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
|
529 int64_t *ppos, int64_t pos_limit) |
310 | 530 { |
531 int len, startcode; | |
532 int64_t pos, pts, dts; | |
533 | |
534 pos = *ppos; | |
535 #ifdef DEBUG_SEEK | |
1443
404048ea11bc
Replace most of the %lld and %llx by their (cleaner) PRI*64 counterparts.
diego
parents:
1415
diff
changeset
|
536 printf("read_dts: pos=0x%"PRIx64" next=%d -> ", pos, find_next); |
310 | 537 #endif |
538 url_fseek(&s->pb, pos, SEEK_SET); | |
539 for(;;) { | |
437
50bae308f71e
moving nearly identical binary search code from nut/mpeg/asf to utils.c
michael
parents:
396
diff
changeset
|
540 len = mpegps_read_pes_header(s, &pos, &startcode, &pts, &dts); |
310 | 541 if (len < 0) { |
542 #ifdef DEBUG_SEEK | |
543 printf("none (ret=%d)\n", len); | |
544 #endif | |
545 return AV_NOPTS_VALUE; | |
546 } | |
885 | 547 if (startcode == s->streams[stream_index]->id && |
310 | 548 dts != AV_NOPTS_VALUE) { |
549 break; | |
550 } | |
437
50bae308f71e
moving nearly identical binary search code from nut/mpeg/asf to utils.c
michael
parents:
396
diff
changeset
|
551 url_fskip(&s->pb, len); |
310 | 552 } |
553 #ifdef DEBUG_SEEK | |
1443
404048ea11bc
Replace most of the %lld and %llx by their (cleaner) PRI*64 counterparts.
diego
parents:
1415
diff
changeset
|
554 printf("pos=0x%"PRIx64" dts=0x%"PRIx64" %0.3f\n", pos, dts, dts / 90000.0); |
310 | 555 #endif |
556 *ppos = pos; | |
463
696f41bc8784
store index for seeking in the native timebase of each stream
michael
parents:
452
diff
changeset
|
557 return dts; |
310 | 558 } |
559 | |
1167 | 560 AVInputFormat mpegps_demuxer = { |
0 | 561 "mpeg", |
562 "MPEG PS format", | |
563 sizeof(MpegDemuxContext), | |
564 mpegps_probe, | |
565 mpegps_read_header, | |
566 mpegps_read_packet, | |
567 mpegps_read_close, | |
437
50bae308f71e
moving nearly identical binary search code from nut/mpeg/asf to utils.c
michael
parents:
396
diff
changeset
|
568 NULL, //mpegps_read_seek, |
50bae308f71e
moving nearly identical binary search code from nut/mpeg/asf to utils.c
michael
parents:
396
diff
changeset
|
569 mpegps_read_dts, |
783
2e8b5a7d7e02
DVD subtitle parsing - show mpeg component IDs by default
bellard
parents:
767
diff
changeset
|
570 .flags = AVFMT_SHOW_IDS, |
0 | 571 }; |