options: Make dynamic dup hack work with new options
[mplayer.git] / libmpdemux / demux_mpg.c
blob3ebec07a8e219ff62c73970cd1c82ad011b2ec0b
1 // MPG/VOB file parser for DEMUXER v2.5 by A'rpi/ESP-team
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <unistd.h>
6 #include <math.h>
8 #include "config.h"
9 #include "mp_msg.h"
10 #include "help_mp.h"
12 #include "stream/stream.h"
13 #include "demuxer.h"
14 #include "parse_es.h"
15 #include "stheader.h"
16 #include "mp3_hdr.h"
18 //#define MAX_PS_PACKETSIZE 2048
19 #define MAX_PS_PACKETSIZE (224*1024)
21 #define UNKNOWN 0
22 #define VIDEO_MPEG1 0x10000001
23 #define VIDEO_MPEG2 0x10000002
24 #define VIDEO_MPEG4 0x10000004
25 #define VIDEO_H264 0x10000005
26 #define AUDIO_MP2 0x50
27 #define AUDIO_A52 0x2000
28 #define AUDIO_LPCM_BE 0x10001
29 #define AUDIO_AAC mmioFOURCC('M', 'P', '4', 'A')
31 typedef struct mpg_demuxer {
32 float last_pts;
33 float first_pts; // first pts found in stream
34 float first_to_final_pts_len; // difference between final pts and first pts
35 int has_valid_timestamps; // !=0 iff time stamps look linear
36 // (not necessarily starting with 0)
37 unsigned int es_map[0x40]; //es map of stream types (associated to the pes id) from 0xb0 to 0xef
38 int num_a_streams;
39 int a_stream_ids[MAX_A_STREAMS];
40 } mpg_demuxer_t;
42 extern char* dvdsub_lang;
43 static int mpeg_pts_error=0;
44 off_t ps_probe = 0;
46 static int parse_psm(demuxer_t *demux, int len) {
47 unsigned char c, id, type;
48 unsigned int plen, prog_len, es_map_len;
49 mpg_demuxer_t *priv = (mpg_demuxer_t *) demux->priv;
51 mp_dbg(MSGT_DEMUX,MSGL_V, "PARSE_PSM, len=%d\n", len);
52 if(! len || len > 1018)
53 return 0;
55 c = stream_read_char(demux->stream);
56 if(! (c & 0x80)) {
57 stream_skip(demux->stream, len - 1); //not yet valid, discard
58 return 0;
60 stream_skip(demux->stream, 1);
61 prog_len = stream_read_word(demux->stream); //length of program descriptors
62 stream_skip(demux->stream, prog_len); //.. that we ignore
63 es_map_len = stream_read_word(demux->stream); //length of elementary streams map
64 es_map_len = FFMIN(es_map_len, len - prog_len - 8); //sanity check
65 while(es_map_len > 0) {
66 type = stream_read_char(demux->stream);
67 id = stream_read_char(demux->stream);
68 if(id >= 0xB0 && id <= 0xEF && priv) {
69 int idoffset = id - 0xB0;
70 switch(type) {
71 case 0x1:
72 priv->es_map[idoffset] = VIDEO_MPEG1;
73 break;
74 case 0x2:
75 priv->es_map[idoffset] = VIDEO_MPEG2;
76 break;
77 case 0x3:
78 case 0x4:
79 priv->es_map[idoffset] = AUDIO_MP2;
80 break;
81 case 0x0f:
82 case 0x11:
83 priv->es_map[idoffset] = AUDIO_AAC;
84 break;
85 case 0x10:
86 priv->es_map[idoffset] = VIDEO_MPEG4;
87 break;
88 case 0x1b:
89 priv->es_map[idoffset] = VIDEO_H264;
90 break;
91 case 0x81:
92 priv->es_map[idoffset] = AUDIO_A52;
93 break;
95 mp_dbg(MSGT_DEMUX,MSGL_V, "PSM ES, id=0x%x, type=%x, stype: %x\n", id, type, priv->es_map[idoffset]);
97 plen = stream_read_word(demux->stream); //length of elementary stream descriptors
98 plen = FFMIN(plen, es_map_len); //sanity check
99 stream_skip(demux->stream, plen); //skip descriptors for now
100 es_map_len -= 4 + plen;
102 stream_skip(demux->stream, 4); //skip crc32
103 return 1;
106 // 500000 is a wild guess
107 #define TIMESTAMP_PROBE_LEN 500000
109 //MAX_PTS_DIFF_FOR_CONSECUTIVE denotes the maximum difference
110 //between two pts to consider them consecutive
111 //1.0 is a wild guess
112 #define MAX_PTS_DIFF_FOR_CONSECUTIVE 1.0
114 //returns the first pts found within TIME_STAMP_PROBE_LEN bytes after stream_pos in demuxer's stream.
115 //if no pts is found or an error occurs, -1.0 is returned.
116 //Packs are freed.
117 static float read_first_mpeg_pts_at_position(demuxer_t* demuxer, off_t stream_pos)
119 stream_t *s = demuxer->stream;
120 mpg_demuxer_t *mpg_d = demuxer->priv;
121 float pts = -1.0; //the pts to return;
122 float found_pts1; //the most recently found pts
123 float found_pts2; //the pts found before found_pts1
124 float found_pts3; //the pts found before found_pts2
125 int found = 0;
127 if(!mpg_d || stream_pos < 0)
128 return pts;
130 found_pts3 = found_pts2 = found_pts1 = mpg_d->last_pts;
131 stream_seek(s, stream_pos);
133 //We look for pts.
134 //However, we do not stop at the first found one, as timestamps may reset
135 //Therefore, we seek until we found three consecutive
136 //pts within MAX_PTS_DIFF_FOR_CONSECUTIVE.
138 while(found<3 && !s->eof
139 && (fabsf(found_pts2-found_pts1) < MAX_PTS_DIFF_FOR_CONSECUTIVE)
140 && (fabsf(found_pts3-found_pts2) < MAX_PTS_DIFF_FOR_CONSECUTIVE)
141 && (stream_tell(s) < stream_pos + TIMESTAMP_PROBE_LEN)
142 && ds_fill_buffer(demuxer->video))
144 if(mpg_d->last_pts != found_pts1)
146 if(!found)
147 found_pts3 = found_pts2 = found_pts1 = mpg_d->last_pts; //the most recently found pts
148 else
150 found_pts3 = found_pts2;
151 found_pts2 = found_pts1;
152 found_pts1 = mpg_d->last_pts;
154 found++;
158 if(found == 3) pts = found_pts3;
160 //clean up from searching of first pts;
161 ds_free_packs(demuxer->audio);
162 ds_free_packs(demuxer->video);
163 ds_free_packs(demuxer->sub);
165 return pts;
168 /// Open an mpg physical stream
169 static demuxer_t* demux_mpg_open(demuxer_t* demuxer) {
170 stream_t *s = demuxer->stream;
171 mpg_demuxer_t* mpg_d;
173 if (!ds_fill_buffer(demuxer->video)) return 0;
174 mpg_d = calloc(1,sizeof(mpg_demuxer_t));
175 if(mpg_d)
177 demuxer->priv = mpg_d;
178 mpg_d->last_pts = -1.0;
179 mpg_d->first_pts = -1.0;
181 //if seeking is allowed set has_valid_timestamps if appropriate
182 if(demuxer->seekable
183 && (demuxer->stream->type == STREAMTYPE_FILE
184 || demuxer->stream->type == STREAMTYPE_VCD)
185 && demuxer->movi_start != demuxer-> movi_end
188 //We seek to the beginning of the stream, to somewhere in the
189 //middle, and to the end of the stream, while remembering the pts
190 //at each of the three positions. With these pts, we check whether
191 //or not the pts are "linear enough" to justify seeking by the pts
192 //of the stream
194 //The position where the stream is now
195 off_t pos = stream_tell(s);
196 float first_pts = read_first_mpeg_pts_at_position(demuxer, demuxer->movi_start);
197 if(first_pts != -1.0)
199 float middle_pts = read_first_mpeg_pts_at_position(demuxer, (demuxer->movi_end + demuxer->movi_start)/2);
200 if(middle_pts != -1.0)
202 float final_pts = read_first_mpeg_pts_at_position(demuxer, demuxer->movi_end - TIMESTAMP_PROBE_LEN);
203 if(final_pts != -1.0)
205 // found proper first, middle, and final pts.
206 float proportion = (middle_pts-first_pts==0) ? -1 : (final_pts-middle_pts)/(middle_pts-first_pts);
207 // if they are linear enough set has_valid_timestamps
208 if((0.5 < proportion) && (proportion < 2))
210 mpg_d->first_pts = first_pts;
211 mpg_d->first_to_final_pts_len = final_pts - first_pts;
212 mpg_d->has_valid_timestamps = 1;
218 //Cleaning up from seeking in stream
219 demuxer->stream->eof=0;
220 demuxer->video->eof=0;
221 demuxer->audio->eof=0;
223 stream_seek(s,pos);
224 ds_fill_buffer(demuxer->video);
225 } // if ( demuxer->seekable )
226 } // if ( mpg_d )
227 return demuxer;
230 static void demux_close_mpg(demuxer_t* demuxer) {
231 mpg_demuxer_t* mpg_d = demuxer->priv;
232 if (mpg_d) free(mpg_d);
236 static unsigned long long read_mpeg_timestamp(stream_t *s,int c){
237 unsigned int d,e;
238 unsigned long long pts;
239 d=stream_read_word(s);
240 e=stream_read_word(s);
241 if( ((c&1)!=1) || ((d&1)!=1) || ((e&1)!=1) ){
242 ++mpeg_pts_error;
243 return 0; // invalid pts
245 pts=(((uint64_t)((c>>1)&7))<<30)|((d>>1)<<15)|(e>>1);
246 mp_dbg(MSGT_DEMUX,MSGL_DBG3," pts {%"PRIu64"}",pts);
247 return pts;
250 static void new_audio_stream(demuxer_t *demux, int aid){
251 if(!demux->a_streams[aid]){
252 mpg_demuxer_t *mpg_d=(mpg_demuxer_t*)demux->priv;
253 sh_audio_t* sh_a;
254 new_sh_audio(demux,aid);
255 sh_a = (sh_audio_t*)demux->a_streams[aid];
256 switch(aid & 0xE0){ // 1110 0000 b (high 3 bit: type low 5: id)
257 case 0x00: sh_a->format=0x50;break; // mpeg
258 case 0xA0: sh_a->format=0x10001;break; // dvd pcm
259 case 0x80: if((aid & 0xF8) == 0x88) sh_a->format=0x2001;//dts
260 else sh_a->format=0x2000;break; // ac3
262 //evo files
263 if((aid & 0xC0) == 0xC0) sh_a->format=0x2000;
264 else if(aid >= 0x98 && aid <= 0x9f) sh_a->format=0x2001;
265 if (mpg_d) mpg_d->a_stream_ids[mpg_d->num_a_streams++] = aid;
267 if(demux->audio->id==-1) demux->audio->id=aid;
270 static int demux_mpg_read_packet(demuxer_t *demux,int id){
271 int d;
272 int len;
273 int set_pts=0; // !=0 iff pts has been set to a proper value
274 unsigned char c=0;
275 unsigned long long pts=0;
276 unsigned long long dts=0;
277 int l;
278 int pes_ext2_subid=-1;
279 double stream_pts = MP_NOPTS_VALUE;
280 demux_stream_t *ds=NULL;
281 demux_packet_t* dp;
282 mpg_demuxer_t *priv = (mpg_demuxer_t *) demux->priv;
284 mp_dbg(MSGT_DEMUX,MSGL_DBG3,"demux_read_packet: %X\n",id);
286 // if(id==0x1F0){
287 // demux->synced=0; // force resync after 0x1F0
288 // return -1;
291 // if(id==0x1BA) packet_start_pos=stream_tell(demux->stream);
292 if((id<0x1BC || id>=0x1F0) && id != 0x1FD) return -1;
293 if(id==0x1BE) return -1; // padding stream
294 if(id==0x1BF) return -1; // private2
296 len=stream_read_word(demux->stream);
297 mp_dbg(MSGT_DEMUX,MSGL_DBG3,"PACKET len=%d",len);
298 // if(len==62480){ demux->synced=0;return -1;} /* :) */
299 if(len==0 || len>MAX_PS_PACKETSIZE){
300 mp_dbg(MSGT_DEMUX,MSGL_DBG2,"Invalid PS packet len: %d\n",len);
301 return -2; // invalid packet !!!!!!
304 mpeg_pts_error=0;
306 if(id==0x1BC) {
307 parse_psm(demux, len);
308 return 0;
311 while(len>0){ // Skip stuFFing bytes
312 c=stream_read_char(demux->stream);
313 --len;
314 if(c!=0xFF)break;
316 if((c>>6)==1){ // Read (skip) STD scale & size value
317 // printf(" STD_scale=%d",(c>>5)&1);
318 d=((c&0x1F)<<8)|stream_read_char(demux->stream);
319 len-=2;
320 // printf(" STD_size=%d",d);
321 c=stream_read_char(demux->stream);
323 // Read System-1 stream timestamps:
324 if((c>>4)==2){
325 pts=read_mpeg_timestamp(demux->stream,c);
326 set_pts=1;
327 len-=4;
328 } else
329 if((c>>4)==3){
330 pts=read_mpeg_timestamp(demux->stream,c);
331 c=stream_read_char(demux->stream);
332 if((c>>4)!=1) pts=0; //printf("{ERROR4}");
333 else set_pts = 1;
334 dts=read_mpeg_timestamp(demux->stream,c);
335 len-=4+1+4;
336 } else
337 if((c>>6)==2){
338 int pts_flags;
339 int hdrlen;
340 int parse_ext2;
341 // System-2 (.VOB) stream:
342 c=stream_read_char(demux->stream);
343 pts_flags=c>>6;
344 parse_ext2 = (id == 0x1FD) && ((c & 0x3F) == 1);
345 c=stream_read_char(demux->stream);
346 hdrlen=c;
347 len-=2;
348 mp_dbg(MSGT_DEMUX,MSGL_DBG3," hdrlen=%d (len=%d)",hdrlen,len);
349 if(hdrlen>len){ mp_msg(MSGT_DEMUX,MSGL_V,"demux_mpg: invalid header length \n"); return -1;}
350 if(pts_flags==2 && hdrlen>=5){
351 c=stream_read_char(demux->stream);
352 pts=read_mpeg_timestamp(demux->stream,c);
353 set_pts=1;
354 len-=5;hdrlen-=5;
355 } else
356 if(pts_flags==3 && hdrlen>=10){
357 c=stream_read_char(demux->stream);
358 pts=read_mpeg_timestamp(demux->stream,c);
359 set_pts=1;
360 c=stream_read_char(demux->stream);
361 dts=read_mpeg_timestamp(demux->stream,c);
362 len-=10;hdrlen-=10;
364 len-=hdrlen;
365 if(parse_ext2 && hdrlen>=3) {
366 c=stream_read_char(demux->stream);
367 hdrlen--;
369 if((c & 0x0F) != 0x0F) {
370 mp_msg(MSGT_DEMUX,MSGL_V,"demux_mpg: pes_extension_flag2 not set, discarding pes packet\n");
371 return -1;
373 if(c & 0x80) { //pes_private_data_flag
374 if(hdrlen<16) {
375 mp_msg(MSGT_DEMUX,MSGL_V,"demux_mpg: not enough pes_private_data bytes: %d < 16, discarding pes packet\n", hdrlen);
376 return -1;
378 stream_skip(demux->stream, 16);
379 hdrlen-=16;
381 if(c & 0x40) { //pack_header_field_flag
382 int l = stream_read_char(demux->stream);
383 if(l < 0) //couldn't read from the stream?
384 return -1;
385 hdrlen--;
386 if(l < 0 || hdrlen < l) {
387 mp_msg(MSGT_DEMUX,MSGL_V,"demux_mpg: not enough pack_header bytes: hdrlen: %d < skip: %d, discarding pes packet\n",
388 hdrlen, l);
389 return -1;
391 stream_skip(demux->stream, l);
392 hdrlen-=l;
394 if(c & 0x20) { //program_packet_sequence_counter_flag
395 if(hdrlen < 2) {
396 mp_msg(MSGT_DEMUX,MSGL_V,"demux_mpg: not enough program_packet bytes: hdrlen: %d, discarding pes packet\n", hdrlen);
397 return -1;
399 stream_skip(demux->stream, 2);
400 hdrlen-=2;
402 if(c & 0x10) {
403 //STD
404 stream_skip(demux->stream, 2);
405 hdrlen-=2;
407 c=stream_read_char(demux->stream); //pes_extension2 flag
408 hdrlen--;
409 if(c!=0x81) { mp_msg(MSGT_DEMUX,MSGL_V,"demux_mpg: unknown pes_extension2 format, len is > 1 \n"); return -1;}
410 c=stream_read_char(demux->stream); //pes_extension2 payload === substream id
411 hdrlen--;
412 if(c<0x55 || c>0x5F) { mp_msg(MSGT_DEMUX,MSGL_V,"demux_mpg: unknown vc1 substream_id: 0x%x \n", c); return -1;}
413 pes_ext2_subid=c;
415 if(hdrlen>0)
416 stream_skip(demux->stream,hdrlen); // skip header and stuffing bytes
418 if(id==0x1FD && pes_ext2_subid!=-1) {
419 //==== EVO VC1 STREAMS ===//
420 if(!demux->v_streams[pes_ext2_subid]) new_sh_video(demux,pes_ext2_subid);
421 if(demux->video->id==-1) demux->video->id=pes_ext2_subid;
422 if(demux->video->id==pes_ext2_subid){
423 ds=demux->video;
424 if(!ds->sh) ds->sh=demux->v_streams[pes_ext2_subid];
425 if(priv && ds->sh) {
426 sh_video_t *sh = (sh_video_t *)ds->sh;
427 sh->format = mmioFOURCC('W', 'V', 'C', '1');
431 //============== DVD Audio sub-stream ======================
432 if(id==0x1BD){
433 int aid, rawa52 = 0;
434 off_t tmppos;
435 unsigned int tmp;
437 tmppos = stream_tell(demux->stream);
438 tmp = stream_read_word(demux->stream);
439 stream_seek(demux->stream, tmppos);
440 /// vdr stores A52 without the 4 header bytes, so we have to check this condition first
441 if(tmp == 0x0B77) {
442 aid = 128;
443 rawa52 = 1;
445 else {
446 aid=stream_read_char(demux->stream);--len;
447 if(len<3) return -1; // invalid audio packet
450 // AID:
451 // 0x20..0x3F subtitle
452 // 0x80..0x87 and 0xC0..0xCF AC3 audio
453 // 0x88..0x8F and 0x98..0x9F DTS audio
454 // 0xA0..0xBF PCM audio
456 if((aid & 0xE0) == 0x20){
457 // subtitle:
458 aid&=0x1F;
460 if(!demux->s_streams[aid]){
461 sh_sub_t *sh = new_sh_sub(demux, aid);
462 if (sh) sh->type = 'v';
463 mp_msg(MSGT_DEMUX,MSGL_V,"==> Found subtitle: %d\n",aid);
466 if(demux->sub->id > -1)
467 demux->sub->id &= 0x1F;
468 if(!dvdsub_lang && demux->sub->id == -1)
469 demux->sub->id = aid;
470 if(demux->sub->id==aid){
471 ds=demux->sub;
473 } else if((aid >= 0x80 && aid <= 0x8F) || (aid >= 0x98 && aid <= 0xAF) || (aid >= 0xC0 && aid <= 0xCF)) {
475 // aid=128+(aid&0x7F);
476 // aid=0x80..0xBF
477 new_audio_stream(demux, aid);
478 if(demux->audio->id==aid){
479 int type;
480 ds=demux->audio;
481 if(!ds->sh) ds->sh=demux->a_streams[aid];
482 // READ Packet: Skip additional audio header data:
483 if(!rawa52) {
484 c=stream_read_char(demux->stream);//num of frames
485 type=stream_read_char(demux->stream);//startpos hi
486 type=(type<<8)|stream_read_char(demux->stream);//startpos lo
487 // printf("\r[%02X][%04X]",c,type);
488 len-=3;
490 if((aid&0xE0)==0xA0 && len>=3){
491 unsigned char* hdr;
492 // save audio header as codecdata!
493 if(!((sh_audio_t*)(ds->sh))->codecdata_len){
494 ((sh_audio_t*)(ds->sh))->codecdata=malloc(3);
495 ((sh_audio_t*)(ds->sh))->codecdata_len=3;
497 hdr=((sh_audio_t*)(ds->sh))->codecdata;
498 // read LPCM header:
499 // emphasis[1], mute[1], rvd[1], frame number[5]:
500 hdr[0]=stream_read_char(demux->stream);
501 // printf(" [%01X:%02d]",c>>5,c&31);
502 // quantization[2],freq[2],rvd[1],channels[3]
503 hdr[1]=stream_read_char(demux->stream);
504 // printf("[%01X:%01X] ",c>>4,c&15);
505 // dynamic range control (0x80=off):
506 hdr[2]=stream_read_char(demux->stream);
507 // printf("[%02X] ",c);
508 len-=3;
509 if(len<=0) mp_msg(MSGT_DEMUX,MSGL_V,"End of packet while searching for PCM header\n");
511 // printf(" \n");
512 } // if(demux->audio->id==aid)
514 } else mp_msg(MSGT_DEMUX,MSGL_V,"Unknown 0x1BD substream: 0x%02X \n",aid);
515 } //if(id==0x1BD)
516 } else {
517 if(c!=0x0f){
518 mp_msg(MSGT_DEMUX,MSGL_V," {ERROR5,c=%d} \n",c);
519 return -1; // invalid packet !!!!!!
522 if(mpeg_pts_error) mp_msg(MSGT_DEMUX,MSGL_V," {PTS_err:%d} \n",mpeg_pts_error);
523 mp_dbg(MSGT_DEMUX,MSGL_DBG3," => len=%d\n",len);
525 // if(len<=0 || len>MAX_PS_PACKETSIZE) return -1; // Invalid packet size
526 if(len<=0 || len>MAX_PS_PACKETSIZE){
527 mp_dbg(MSGT_DEMUX,MSGL_DBG2,"Invalid PS data len: %d\n",len);
528 return -1; // invalid packet !!!!!!
531 if(id>=0x1C0 && id<=0x1DF){
532 // mpeg audio
533 int aid=id-0x1C0;
534 new_audio_stream(demux, aid);
535 if(demux->audio->id==aid){
536 ds=demux->audio;
537 if(!ds->sh) ds->sh=demux->a_streams[aid];
538 if(priv && ds->sh) {
539 sh_audio_t *sh = (sh_audio_t *)ds->sh;
540 if(priv->es_map[id - 0x1B0])
541 sh->format = priv->es_map[id - 0x1B0];
542 mp_dbg(MSGT_DEMUX,MSGL_DBG2,"ASSIGNED TO STREAM %d CODEC %x\n", id, priv->es_map[id - 0x1B0]);
545 } else
546 if(id>=0x1E0 && id<=0x1EF){
547 // mpeg video
548 int aid=id-0x1E0;
549 if(!demux->v_streams[aid]) new_sh_video(demux,aid);
550 if(demux->video->id==-1) demux->video->id=aid;
551 if(demux->video->id==aid){
552 ds=demux->video;
553 if(!ds->sh) ds->sh=demux->v_streams[aid];
554 if(priv && ds->sh) {
555 sh_video_t *sh = (sh_video_t *)ds->sh;
556 if(priv->es_map[id - 0x1B0]) {
557 sh->format = priv->es_map[id - 0x1B0];
558 mp_dbg(MSGT_DEMUX,MSGL_DBG2,"ASSIGNED TO STREAM %d CODEC %x\n", id, priv->es_map[id - 0x1B0]);
564 if(ds){
565 mp_dbg(MSGT_DEMUX,MSGL_DBG2,"DEMUX_MPG: Read %d data bytes from packet %04X\n",len,id);
566 // printf("packet start = 0x%X \n",stream_tell(demux->stream)-packet_start_pos);
568 dp=new_demux_packet(len);
569 if(!dp) {
570 mp_dbg(MSGT_DEMUX,MSGL_ERR,"DEMUX_MPG ERROR: couldn't create demux_packet(%d bytes)\n",len);
571 stream_skip(demux->stream,len);
572 return 0;
574 l = stream_read(demux->stream,dp->buffer,len);
575 if(l<len)
576 resize_demux_packet(dp, l);
577 len = l;
578 if(set_pts)
579 dp->pts=pts/90000.0f;
580 dp->pos=demux->filepos;
582 workaround:
583 set dp->stream_pts only when feeding the video stream, or strangely interleaved files
584 (such as SWIII) will show strange alternations in the stream time, wildly going
585 back and forth
587 if(ds == demux->video && stream_control(demux->stream, STREAM_CTRL_GET_CURRENT_TIME,(void *)&stream_pts)!=STREAM_UNSUPPORTED)
588 dp->stream_pts = stream_pts;
589 ds_add_packet(ds,dp);
590 if (demux->priv && set_pts) ((mpg_demuxer_t*)demux->priv)->last_pts = pts/90000.0f;
591 // if(ds==demux->sub) parse_dvdsub(ds->last->buffer,ds->last->len);
592 return 1;
594 mp_dbg(MSGT_DEMUX,MSGL_DBG2,"DEMUX_MPG: Skipping %d data bytes from packet %04X\n",len,id);
595 if(len<=2356) stream_skip(demux->stream,len);
596 return 0;
599 static int num_elementary_packets100=0;
600 static int num_elementary_packets101=0;
601 static int num_elementary_packets12x=0;
602 static int num_elementary_packets1B6=0;
603 static int num_elementary_packetsPES=0;
604 static int num_mpeg12_startcode=0;
605 static int num_h264_slice=0; //combined slice
606 static int num_h264_dpa=0; //DPA Slice
607 static int num_h264_dpb=0; //DPB Slice
608 static int num_h264_dpc=0; //DPC Slice
609 static int num_h264_idr=0; //IDR Slice
610 static int num_h264_sps=0;
611 static int num_h264_pps=0;
613 static int num_mp3audio_packets=0;
615 static void clear_stats(void)
617 num_elementary_packets100=0;
618 num_elementary_packets101=0;
619 num_elementary_packets1B6=0;
620 num_elementary_packets12x=0;
621 num_elementary_packetsPES=0;
622 num_mpeg12_startcode=0;
623 num_h264_slice=0; //combined slice
624 num_h264_dpa=0; //DPA Slice
625 num_h264_dpb=0; //DPB Slice
626 num_h264_dpc=0; //DPC Slice
627 num_h264_idr=0; //IDR Slice
628 num_h264_sps=0;
629 num_h264_pps=0;
630 num_mp3audio_packets=0;
633 //assumes demuxer->synced < 2
634 static inline void update_stats(int head)
636 if(head==0x1B6) ++num_elementary_packets1B6;
637 else if(head==0x1B3 || head==0x1B8) ++num_mpeg12_startcode;
638 else if(head==0x100) ++num_elementary_packets100;
639 else if(head==0x101) ++num_elementary_packets101;
640 else if(head==0x1BD || (0x1C0<=head && head<=0x1EF))
641 num_elementary_packetsPES++;
642 else if(head>=0x120 && head<=0x12F) ++num_elementary_packets12x;
643 if(head>=0x100 && head<0x1B0)
645 if((head&~0x60) == 0x101) ++num_h264_slice;
646 else if((head&~0x60) == 0x102) ++num_h264_dpa;
647 else if((head&~0x60) == 0x103) ++num_h264_dpb;
648 else if((head&~0x60) == 0x104) ++num_h264_dpc;
649 else if((head&~0x60) == 0x105 && head != 0x105) ++num_h264_idr;
650 else if((head&~0x60) == 0x107 && head != 0x107) ++num_h264_sps;
651 else if((head&~0x60) == 0x108 && head != 0x108) ++num_h264_pps;
655 static int demux_mpg_probe(demuxer_t *demuxer) {
656 int pes=1;
657 int tmp;
658 off_t tmppos;
659 int file_format = DEMUXER_TYPE_UNKNOWN;
661 tmppos=stream_tell(demuxer->stream);
662 tmp=stream_read_dword(demuxer->stream);
663 if(tmp==0x1E0 || tmp==0x1C0) {
664 tmp=stream_read_word(demuxer->stream);
665 if(tmp>1 && tmp<=2048) pes=0; // demuxer->synced=3; // PES...
667 stream_seek(demuxer->stream,tmppos);
669 clear_stats();
671 if(demux_mpg_open(demuxer))
672 file_format=DEMUXER_TYPE_MPEG_PS;
673 else {
674 mp_msg(MSGT_DEMUX,MSGL_V,"MPEG packet stats: p100: %d p101: %d p1B6: %d p12x: %d sli: %d a: %d b: %d c: %d idr: %d sps: %d pps: %d PES: %d MP3: %d, synced: %d\n",
675 num_elementary_packets100,num_elementary_packets101,
676 num_elementary_packets1B6,num_elementary_packets12x,
677 num_h264_slice, num_h264_dpa,
678 num_h264_dpb, num_h264_dpc=0,
679 num_h264_idr, num_h264_sps=0,
680 num_h264_pps,
681 num_elementary_packetsPES,num_mp3audio_packets, demuxer->synced);
683 //MPEG packet stats: p100: 458 p101: 458 PES: 0 MP3: 1103 (.m2v)
684 if(num_mp3audio_packets>50 && num_mp3audio_packets>2*num_elementary_packets100
685 && abs(num_elementary_packets100-num_elementary_packets101)>2)
686 return file_format;
688 // some hack to get meaningfull error messages to our unhappy users:
689 if(num_mpeg12_startcode>=2 && num_elementary_packets100>=2 && num_elementary_packets101>=2 &&
690 abs(num_elementary_packets101+8-num_elementary_packets100)<16) {
691 if(num_elementary_packetsPES>=4 && num_elementary_packetsPES>=num_elementary_packets100-4) {
692 return file_format;
694 file_format=DEMUXER_TYPE_MPEG_ES; // <-- hack is here :)
695 } else
696 // fuzzy mpeg4-es detection. do NOT enable without heavy testing of mpeg formats detection!
697 if(num_elementary_packets1B6>3 && num_elementary_packets12x>=1 &&
698 num_elementary_packetsPES==0 && num_elementary_packets100<=num_elementary_packets12x &&
699 demuxer->synced<2) {
700 file_format=DEMUXER_TYPE_MPEG4_ES;
701 } else
702 // fuzzy h264-es detection. do NOT enable without heavy testing of mpeg formats detection!
703 if((num_h264_slice>3 || (num_h264_dpa>3 && num_h264_dpb>3 && num_h264_dpc>3)) &&
704 /* FIXME num_h264_sps>=1 && */ num_h264_pps>=1 && num_h264_idr>=1 &&
705 num_elementary_packets1B6==0 && num_elementary_packetsPES==0 &&
706 demuxer->synced<2) {
707 file_format=DEMUXER_TYPE_H264_ES;
708 } else
710 if(demuxer->synced==2)
711 mp_msg(MSGT_DEMUXER,MSGL_ERR,"MPEG: " MSGTR_MissingVideoStreamBug);
712 else
713 mp_msg(MSGT_DEMUXER,MSGL_V,MSGTR_NotSystemStream);
716 //FIXME this shouldn't be necessary
717 stream_seek(demuxer->stream,tmppos);
718 return file_format;
721 static int demux_mpg_es_fill_buffer(demuxer_t *demux, demux_stream_t *ds){
722 // Elementary video stream
723 if(demux->stream->eof) return 0;
724 demux->filepos=stream_tell(demux->stream);
725 ds_read_packet(demux->video,demux->stream,STREAM_BUFFER_SIZE,0,demux->filepos,0);
726 return 1;
730 * \brief discard until 0x100 header and return a filled buffer
731 * \param b buffer-end pointer
732 * \param pos current pos in stream, negative since b points to end of buffer
733 * \param s stream to read from
734 * \return new position, differs from original pos when eof hit and thus
735 * b was modified to point to the new end of buffer
737 static int find_end(unsigned char **b, int pos, stream_t *s) {
738 register int state = 0xffffffff;
739 unsigned char *buf = *b;
740 int start = pos;
741 int read, unused;
742 // search already read part
743 while (state != 0x100 && pos) {
744 state = state << 8 | buf[pos++];
746 // continue search in stream
747 while (state != 0x100) {
748 register int c = stream_read_char(s);
749 if (c < 0) break;
750 state = state << 8 | c;
752 // modify previous header (from 0x1bc or 0x1bf to 0x100)
753 buf[start++] = 0;
754 // copy remaining buffer part to current pos
755 memmove(&buf[start], &buf[pos], -pos);
756 unused = start + -pos; // -unused bytes in buffer
757 read = stream_read(s, &buf[unused], -unused);
758 unused += read;
759 // fix buffer so it ends at pos == 0 (eof case)
760 *b = &buf[unused];
761 start -= unused;
762 return start;
766 * This format usually uses an insane bitrate, which makes this function
767 * performance-critical!
768 * Be sure to benchmark any changes with different compiler versions.
770 static int demux_mpg_gxf_fill_buffer(demuxer_t *demux, demux_stream_t *ds) {
771 demux_packet_t *pack;
772 int len;
773 demux->filepos = stream_tell(demux->stream);
774 pack = new_demux_packet(STREAM_BUFFER_SIZE);
775 len = stream_read(demux->stream, pack->buffer, STREAM_BUFFER_SIZE);
776 if (len <= 0)
778 free_demux_packet(pack);
779 return 0;
782 register uint32_t state = (uint32_t)demux->priv;
783 register int pos = -len;
784 unsigned char *buf = &pack->buffer[len];
785 do {
786 state = state << 8 | buf[pos];
787 if (unlikely((state | 3) == 0x1bf))
788 pos = find_end(&buf, pos, demux->stream);
789 } while (++pos < 0);
790 demux->priv = (void *)state;
791 len = buf - pack->buffer;
793 if (len < STREAM_BUFFER_SIZE)
794 resize_demux_packet(pack, len);
795 ds_add_packet(ds, pack);
796 return 1;
799 int demux_mpg_fill_buffer(demuxer_t *demux, demux_stream_t *ds){
800 unsigned int head=0;
801 int skipped=0;
802 int max_packs=256; // 512kbyte
803 int ret=0;
805 // System stream
807 demux->filepos=stream_tell(demux->stream);
808 #if 1
809 //lame workaround: this is needed to show the progress bar when playing dvdnav://
810 //(ths poor guy doesn't know teh length of the stream at startup)
811 demux->movi_end = demux->stream->end_pos;
812 #endif
813 head=stream_read_dword(demux->stream);
814 if((head&0xFFFFFF00)!=0x100){
815 // sync...
816 demux->filepos-=skipped;
817 while(1){
818 int c=stream_read_char(demux->stream);
819 if(c<0) break; //EOF
820 head<<=8;
821 if(head!=0x100){
822 head|=c;
823 if(mp_check_mp3_header(head)) ++num_mp3audio_packets;
824 ++skipped; //++demux->filepos;
825 continue;
827 head|=c;
828 break;
830 demux->filepos+=skipped;
832 if(stream_eof(demux->stream)) break;
833 // sure: head=0x000001XX
834 mp_dbg(MSGT_DEMUX,MSGL_DBG4,"*** head=0x%X\n",head);
835 if(demux->synced==0){
836 if(head==0x1BA) demux->synced=1; //else
837 // if(head==0x1BD || (head>=0x1C0 && head<=0x1EF)) demux->synced=3; // PES?
838 } else
839 if(demux->synced==1){
840 if(head==0x1BB || head==0x1BD || (head>=0x1C0 && head<=0x1EF)){
841 demux->synced=2;
842 mp_msg(MSGT_DEMUX,MSGL_V,"system stream synced at 0x%"PRIX64" (%"PRId64")!\n",(int64_t)demux->filepos,(int64_t)demux->filepos);
843 num_elementary_packets100=0; // requires for re-sync!
844 num_elementary_packets101=0; // requires for re-sync!
845 } else demux->synced=0;
846 } // else
847 if(demux->synced>=2){
848 ret=demux_mpg_read_packet(demux,head);
849 if(!ret)
850 if(--max_packs==0){
851 demux->stream->eof=1;
852 mp_msg(MSGT_DEMUX,MSGL_ERR,MSGTR_DoesntContainSelectedStream);
853 return 0;
855 if(demux->synced==3) demux->synced=(ret==1)?2:0; // PES detect
856 } else {
857 update_stats(head);
858 if(head>=0x100 && head<0x1B0)
859 mp_msg(MSGT_DEMUX,MSGL_DBG3,"Opps... elementary video packet found: %03X\n",head);
860 else if((head>=0x1C0 && head<0x1F0) || head==0x1BD)
861 mp_msg(MSGT_DEMUX,MSGL_DBG3,"Opps... PES packet found: %03X\n",head);
863 if(((num_elementary_packets100>50 && num_elementary_packets101>50) ||
864 (num_elementary_packetsPES>50)) && skipped>4000000){
865 mp_msg(MSGT_DEMUX,MSGL_V,"sync_mpeg_ps: seems to be ES/PES stream...\n");
866 demux->stream->eof=1;
867 break;
869 if(num_mp3audio_packets>100 && num_elementary_packets100<10){
870 mp_msg(MSGT_DEMUX,MSGL_V,"sync_mpeg_ps: seems to be MP3 stream...\n");
871 demux->stream->eof=1;
872 break;
875 } while(ret!=1);
876 mp_dbg(MSGT_DEMUX,MSGL_DBG2,"demux: %d bad bytes skipped\n",skipped);
877 if(demux->stream->eof){
878 mp_msg(MSGT_DEMUX,MSGL_V,"MPEG Stream reached EOF\n");
879 return 0;
881 return 1;
884 extern void skip_audio_frame(sh_audio_t *sh_audio);
886 void demux_seek_mpg(demuxer_t *demuxer,float rel_seek_secs,float audio_delay, int flags){
887 demux_stream_t *d_audio=demuxer->audio;
888 demux_stream_t *d_video=demuxer->video;
889 sh_audio_t *sh_audio=d_audio->sh;
890 sh_video_t *sh_video=d_video->sh;
891 mpg_demuxer_t *mpg_d=(mpg_demuxer_t*)demuxer->priv;
892 int precision = 1;
893 float oldpts = 0;
894 off_t oldpos = demuxer->filepos;
895 float newpts = 0;
896 off_t newpos = (flags & SEEK_ABSOLUTE) ? demuxer->movi_start : oldpos;
898 if(mpg_d)
899 oldpts = mpg_d->last_pts;
900 newpts = (flags & SEEK_ABSOLUTE) ? 0.0 : oldpts;
901 //================= seek in MPEG ==========================
902 //calculate the pts to seek to
903 if(flags & SEEK_FACTOR) {
904 if (mpg_d && mpg_d->first_to_final_pts_len > 0.0)
905 newpts += mpg_d->first_to_final_pts_len * rel_seek_secs;
906 else
907 newpts += rel_seek_secs * (demuxer->movi_end - demuxer->movi_start) * oldpts / oldpos;
908 } else
909 newpts += rel_seek_secs;
910 if (newpts < 0) newpts = 0;
912 if(flags&SEEK_FACTOR){
913 // float seek 0..1
914 newpos+=(demuxer->movi_end-demuxer->movi_start)*rel_seek_secs;
915 } else {
916 // time seek (secs)
917 if (mpg_d && mpg_d->has_valid_timestamps) {
918 if (mpg_d->first_to_final_pts_len > 0.0)
919 newpos += rel_seek_secs * (demuxer->movi_end - demuxer->movi_start) / mpg_d->first_to_final_pts_len;
920 else if (oldpts > 0.0)
921 newpos += rel_seek_secs * (oldpos - demuxer->movi_start) / oldpts;
922 } else if(!sh_video || !sh_video->i_bps) // unspecified or VBR
923 newpos+=2324*75*rel_seek_secs; // 174.3 kbyte/sec
924 else
925 newpos+=sh_video->i_bps*rel_seek_secs;
928 while (1) {
929 if(newpos<demuxer->movi_start){
930 if(demuxer->stream->type!=STREAMTYPE_VCD) demuxer->movi_start=0; // for VCD
931 if(newpos<demuxer->movi_start) newpos=demuxer->movi_start;
934 stream_seek(demuxer->stream,newpos);
936 // re-sync video:
937 videobuf_code_len=0; // reset ES stream buffer
939 ds_fill_buffer(d_video);
940 if(sh_audio){
941 ds_fill_buffer(d_audio);
944 while(1){
945 int i;
946 if(sh_audio && !d_audio->eof && d_video->pts && d_audio->pts){
947 float a_pts=d_audio->pts;
948 a_pts+=(ds_tell_pts(d_audio)-sh_audio->a_in_buffer_len)/(float)sh_audio->i_bps;
949 if(d_video->pts>a_pts){
950 skip_audio_frame(sh_audio); // sync audio
951 continue;
954 if(!sh_video) break;
955 i=sync_video_packet(d_video);
956 if(sh_video->format == mmioFOURCC('W', 'V', 'C', '1')) {
957 if(i==0x10E || i==0x10F) //entry point or sequence header
958 break;
959 } else
960 if(sh_video->format == 0x10000004) { //mpeg4
961 if(i==0x1B6) { //vop (frame) startcode
962 int pos = videobuf_len;
963 if(!read_video_packet(d_video)) break; // EOF
964 if((videobuffer[pos+4] & 0x3F) == 0) break; //I-frame
966 } else if(sh_video->format == 0x10000005){ //h264
967 if((i & ~0x60) == 0x105) break;
968 } else { //default mpeg1/2
969 if(i==0x1B3 || i==0x1B8) break; // found it!
971 if(!i || !skip_video_packet(d_video)) break; // EOF?
973 if(!mpg_d)
974 break;
975 if (!precision || abs(newpts - mpg_d->last_pts) < 0.5 || (mpg_d->last_pts == oldpts)) break;
976 if ((newpos - oldpos) * (mpg_d->last_pts - oldpts) < 0) { // invalid timestamps
977 mpg_d->has_valid_timestamps = 0;
978 break;
980 precision--;
981 //prepare another seek because we are off by more than 0.5s
982 if(mpg_d) {
983 newpos += (newpts - mpg_d->last_pts) * (newpos - oldpos) / (mpg_d->last_pts - oldpts);
984 ds_free_packs(d_audio);
985 ds_free_packs(d_video);
986 ds_free_packs(demuxer->sub);
987 demuxer->stream->eof=0; // clear eof flag
988 d_video->eof=0;
989 d_audio->eof=0;
994 int demux_mpg_control(demuxer_t *demuxer,int cmd, void *arg){
995 mpg_demuxer_t *mpg_d=(mpg_demuxer_t*)demuxer->priv;
997 switch(cmd) {
998 case DEMUXER_CTRL_GET_TIME_LENGTH:
999 if(stream_control(demuxer->stream, STREAM_CTRL_GET_TIME_LENGTH, arg) != STREAM_UNSUPPORTED) {
1000 mp_msg(MSGT_DEMUXER,MSGL_DBG2,"\r\nDEMUX_MPG_CTRL, (%.3lf)\r\n", *((double*)arg));
1001 return DEMUXER_CTRL_GUESS;
1003 if (mpg_d && mpg_d->has_valid_timestamps) {
1004 *((double *)arg)=(double)mpg_d->first_to_final_pts_len;
1005 return DEMUXER_CTRL_OK;
1007 return DEMUXER_CTRL_DONTKNOW;
1009 case DEMUXER_CTRL_GET_PERCENT_POS:
1010 if (mpg_d && mpg_d->has_valid_timestamps && mpg_d->first_to_final_pts_len > 0.0) {
1011 *((int *)arg)=(int)(100 * (mpg_d->last_pts-mpg_d->first_pts) / mpg_d->first_to_final_pts_len);
1012 return DEMUXER_CTRL_OK;
1014 return DEMUXER_CTRL_DONTKNOW;
1016 case DEMUXER_CTRL_SWITCH_AUDIO:
1017 if(! (mpg_d && mpg_d->num_a_streams > 1 && demuxer->audio && demuxer->audio->sh))
1018 return DEMUXER_CTRL_NOTIMPL;
1019 else {
1020 demux_stream_t *d_audio = demuxer->audio;
1021 sh_audio_t *sh_audio = d_audio->sh;
1022 sh_audio_t *sh_a = sh_audio;
1023 int i;
1024 if(!sh_audio)
1025 return DEMUXER_CTRL_NOTIMPL;
1026 if (*((int*)arg) < 0)
1028 for (i = 0; i < mpg_d->num_a_streams; i++) {
1029 if (d_audio->id == mpg_d->a_stream_ids[i]) break;
1031 i = (i+1) % mpg_d->num_a_streams;
1032 sh_a = (sh_audio_t*)demuxer->a_streams[mpg_d->a_stream_ids[i]];
1034 else {
1035 for (i = 0; i < mpg_d->num_a_streams; i++)
1036 if (*((int*)arg) == mpg_d->a_stream_ids[i]) break;
1037 if (i < mpg_d->num_a_streams)
1038 sh_a = (sh_audio_t*)demuxer->a_streams[*((int*)arg)];
1040 if (i < mpg_d->num_a_streams && d_audio->id != mpg_d->a_stream_ids[i]) {
1041 d_audio->id = mpg_d->a_stream_ids[i];
1042 d_audio->sh = sh_a;
1043 ds_free_packs(d_audio);
1046 *((int*)arg) = demuxer->audio->id;
1047 return DEMUXER_CTRL_OK;
1049 default:
1050 return DEMUXER_CTRL_NOTIMPL;
1055 static int demux_mpg_pes_probe(demuxer_t *demuxer) {
1056 demuxer->synced = 3;
1057 return (demux_mpg_probe(demuxer) == DEMUXER_TYPE_MPEG_PS) ? DEMUXER_TYPE_MPEG_PES : 0;
1061 static demuxer_t* demux_mpg_es_open(demuxer_t* demuxer)
1063 sh_video_t *sh_video=NULL;
1065 demuxer->audio->sh = NULL; // ES streams has no audio channel
1066 demuxer->video->sh = new_sh_video(demuxer,0); // create dummy video stream header, id=0
1067 sh_video=demuxer->video->sh;sh_video->ds=demuxer->video;
1069 return demuxer;
1072 static demuxer_t *demux_mpg_gxf_open(demuxer_t *demuxer) {
1073 demuxer->audio->sh = NULL;
1074 demuxer->video->sh = new_sh_video(demuxer,0);
1075 ((sh_video_t *)demuxer->video->sh)->ds = demuxer->video;
1076 demuxer->priv = (void *) 0xffffffff;
1077 return demuxer;
1080 static demuxer_t* demux_mpg_ps_open(demuxer_t* demuxer)
1082 sh_audio_t *sh_audio=NULL;
1083 sh_video_t *sh_video=NULL;
1085 sh_video=demuxer->video->sh;sh_video->ds=demuxer->video;
1087 if(demuxer->audio->id!=-2) {
1088 if(!ds_fill_buffer(demuxer->audio)){
1089 mp_msg(MSGT_DEMUXER,MSGL_INFO,"MPEG: " MSGTR_MissingAudioStream);
1090 demuxer->audio->sh=NULL;
1091 } else {
1092 sh_audio=demuxer->audio->sh;sh_audio->ds=demuxer->audio;
1096 if(!sh_video->format && ps_probe > 0) {
1097 int head;
1098 off_t pos = stream_tell(demuxer->stream);
1100 clear_stats();
1101 do {
1102 head=sync_video_packet(demuxer->video);
1103 if(!head) break;
1104 update_stats(head);
1105 skip_video_packet(demuxer->video);
1106 } while(stream_tell(demuxer->stream) < pos + ps_probe && !demuxer->stream->eof);
1108 ds_free_packs(demuxer->video);
1109 demuxer->stream->eof=0;
1110 stream_seek(demuxer->stream, pos);
1111 mp_msg(MSGT_DEMUX,MSGL_INFO,"MPEG packet stats: p100: %d p101: %d p1B6: %d p12x: %d sli: %d a: %d b: %d c: %d idr: %d sps: %d pps: %d\n",
1112 num_elementary_packets100, num_elementary_packets101,
1113 num_elementary_packets1B6, num_elementary_packets12x,
1114 num_h264_slice, num_h264_dpa, num_h264_dpb, num_h264_dpc,
1115 num_h264_idr, num_h264_sps, num_h264_pps);
1117 if(num_elementary_packets1B6>3 && num_elementary_packets12x>=1 &&
1118 num_elementary_packets100<=num_elementary_packets12x)
1119 sh_video->format = 0x10000004;
1120 else if((num_h264_slice>3 || (num_h264_dpa>3 && num_h264_dpb>3 && num_h264_dpc>3)) &&
1121 num_h264_sps>=1 && num_h264_pps>=1 && num_h264_idr>=1 &&
1122 num_elementary_packets1B6==0)
1123 sh_video->format = 0x10000005;
1124 else sh_video->format = 0x10000002;
1127 return demuxer;
1131 const demuxer_desc_t demuxer_desc_mpeg_ps = {
1132 "MPEG PS demuxer",
1133 "mpegps",
1134 "MPEG-PS",
1135 "Arpi?",
1136 "Mpeg",
1137 DEMUXER_TYPE_MPEG_PS,
1138 0, // unsafe autodetect
1139 demux_mpg_probe,
1140 demux_mpg_fill_buffer,
1141 demux_mpg_ps_open,
1142 demux_close_mpg,
1143 demux_seek_mpg,
1144 demux_mpg_control,
1148 const demuxer_desc_t demuxer_desc_mpeg_pes = {
1149 "MPEG PES demuxer",
1150 "mpegpes",
1151 "MPEG-PES",
1152 "Arpi?",
1153 "Mpeg",
1154 DEMUXER_TYPE_MPEG_PES,
1155 0, // unsafe autodetect
1156 demux_mpg_pes_probe,
1157 demux_mpg_fill_buffer,
1158 demux_mpg_ps_open,
1159 demux_close_mpg,
1160 demux_seek_mpg,
1161 demux_mpg_control,
1165 const demuxer_desc_t demuxer_desc_mpeg_gxf = {
1166 "MPEG ES in GXF demuxer",
1167 "mpeggxf",
1168 "MPEG-ES in GXF",
1169 "Reimar Doeffinger",
1170 "Mpeg",
1171 DEMUXER_TYPE_MPEG_GXF,
1172 0, // hack autodetection
1173 NULL,
1174 demux_mpg_gxf_fill_buffer,
1175 demux_mpg_gxf_open,
1176 NULL,
1177 NULL,
1178 NULL
1181 const demuxer_desc_t demuxer_desc_mpeg_es = {
1182 "MPEG ES demuxer",
1183 "mpeges",
1184 "MPEG-ES",
1185 "Arpi?",
1186 "Mpeg",
1187 DEMUXER_TYPE_MPEG_ES,
1188 0, // hack autodetection
1189 NULL,
1190 demux_mpg_es_fill_buffer,
1191 demux_mpg_es_open,
1192 demux_close_mpg,
1193 demux_seek_mpg,
1194 demux_mpg_control,
1198 const demuxer_desc_t demuxer_desc_mpeg4_es = {
1199 "MPEG4 ES demuxer",
1200 "mpeg4es",
1201 "MPEG-ES",
1202 "Arpi?",
1203 "Mpeg",
1204 DEMUXER_TYPE_MPEG4_ES,
1205 0, // hack autodetection
1206 NULL,
1207 demux_mpg_es_fill_buffer,
1208 demux_mpg_es_open,
1209 demux_close_mpg,
1210 demux_seek_mpg,
1211 demux_mpg_control,
1215 const demuxer_desc_t demuxer_desc_h264_es = {
1216 "H.264 ES demuxer",
1217 "h264es",
1218 "H264-ES",
1219 "Arpi?",
1220 "Mpeg",
1221 DEMUXER_TYPE_H264_ES,
1222 0, // hack autodetection
1223 NULL,
1224 demux_mpg_es_fill_buffer,
1225 demux_mpg_es_open,
1226 demux_close_mpg,
1227 demux_seek_mpg,
1228 demux_mpg_control,