Translation system changes part 2: replace macros by strings
[mplayer/glamo.git] / libmpdemux / demux_mpg.c
blob620b44598c581074ba735f170acd191ca2334ce7
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 demux_flush(demuxer);
163 return pts;
166 /// Open an mpg physical stream
167 static demuxer_t* demux_mpg_open(demuxer_t* demuxer) {
168 stream_t *s = demuxer->stream;
169 mpg_demuxer_t* mpg_d;
171 if (!ds_fill_buffer(demuxer->video)) return 0;
172 mpg_d = calloc(1,sizeof(mpg_demuxer_t));
173 if(mpg_d)
175 demuxer->priv = mpg_d;
176 mpg_d->last_pts = -1.0;
177 mpg_d->first_pts = -1.0;
179 //if seeking is allowed set has_valid_timestamps if appropriate
180 if(demuxer->seekable
181 && (demuxer->stream->type == STREAMTYPE_FILE
182 || demuxer->stream->type == STREAMTYPE_VCD)
183 && demuxer->movi_start != demuxer-> movi_end
186 //We seek to the beginning of the stream, to somewhere in the
187 //middle, and to the end of the stream, while remembering the pts
188 //at each of the three positions. With these pts, we check whether
189 //or not the pts are "linear enough" to justify seeking by the pts
190 //of the stream
192 //The position where the stream is now
193 off_t pos = stream_tell(s);
194 float first_pts = read_first_mpeg_pts_at_position(demuxer, demuxer->movi_start);
195 if(first_pts != -1.0)
197 float middle_pts = read_first_mpeg_pts_at_position(demuxer, (demuxer->movi_end + demuxer->movi_start)/2);
198 if(middle_pts != -1.0)
200 float final_pts = read_first_mpeg_pts_at_position(demuxer, demuxer->movi_end - TIMESTAMP_PROBE_LEN);
201 if(final_pts != -1.0)
203 // found proper first, middle, and final pts.
204 float proportion = (middle_pts-first_pts==0) ? -1 : (final_pts-middle_pts)/(middle_pts-first_pts);
205 // if they are linear enough set has_valid_timestamps
206 if((0.5 < proportion) && (proportion < 2))
208 mpg_d->first_pts = first_pts;
209 mpg_d->first_to_final_pts_len = final_pts - first_pts;
210 mpg_d->has_valid_timestamps = 1;
216 //Cleaning up from seeking in stream
217 demuxer->stream->eof=0;
218 demuxer->video->eof=0;
219 demuxer->audio->eof=0;
221 stream_seek(s,pos);
222 ds_fill_buffer(demuxer->video);
223 } // if ( demuxer->seekable )
224 } // if ( mpg_d )
225 return demuxer;
228 static void demux_close_mpg(demuxer_t* demuxer) {
229 mpg_demuxer_t* mpg_d = demuxer->priv;
230 if (mpg_d) free(mpg_d);
234 static unsigned long long read_mpeg_timestamp(stream_t *s,int c){
235 unsigned int d,e;
236 unsigned long long pts;
237 d=stream_read_word(s);
238 e=stream_read_word(s);
239 if( ((c&1)!=1) || ((d&1)!=1) || ((e&1)!=1) ){
240 ++mpeg_pts_error;
241 return 0; // invalid pts
243 pts=(((uint64_t)((c>>1)&7))<<30)|((d>>1)<<15)|(e>>1);
244 mp_dbg(MSGT_DEMUX,MSGL_DBG3," pts {%"PRIu64"}",pts);
245 return pts;
248 static void new_audio_stream(demuxer_t *demux, int aid){
249 if(!demux->a_streams[aid]){
250 mpg_demuxer_t *mpg_d=(mpg_demuxer_t*)demux->priv;
251 sh_audio_t* sh_a;
252 new_sh_audio(demux,aid);
253 sh_a = (sh_audio_t*)demux->a_streams[aid];
254 switch(aid & 0xE0){ // 1110 0000 b (high 3 bit: type low 5: id)
255 case 0x00: sh_a->format=0x50;break; // mpeg
256 case 0xA0: sh_a->format=0x10001;break; // dvd pcm
257 case 0x80: if((aid & 0xF8) == 0x88) sh_a->format=0x2001;//dts
258 else sh_a->format=0x2000;break; // ac3
260 //evo files
261 if((aid & 0xC0) == 0xC0) sh_a->format=0x2000;
262 else if(aid >= 0x98 && aid <= 0x9f) sh_a->format=0x2001;
263 if (mpg_d) mpg_d->a_stream_ids[mpg_d->num_a_streams++] = aid;
265 if(demux->audio->id==-1) demux->audio->id=aid;
268 static int demux_mpg_read_packet(demuxer_t *demux,int id){
269 int d;
270 int len;
271 int set_pts=0; // !=0 iff pts has been set to a proper value
272 unsigned char c=0;
273 unsigned long long pts=0;
274 unsigned long long dts=0;
275 int l;
276 int pes_ext2_subid=-1;
277 double stream_pts = MP_NOPTS_VALUE;
278 demux_stream_t *ds=NULL;
279 demux_packet_t* dp;
280 mpg_demuxer_t *priv = (mpg_demuxer_t *) demux->priv;
282 mp_dbg(MSGT_DEMUX,MSGL_DBG3,"demux_read_packet: %X\n",id);
284 // if(id==0x1F0){
285 // demux->synced=0; // force resync after 0x1F0
286 // return -1;
289 // if(id==0x1BA) packet_start_pos=stream_tell(demux->stream);
290 if((id<0x1BC || id>=0x1F0) && id != 0x1FD) return -1;
291 if(id==0x1BE) return -1; // padding stream
292 if(id==0x1BF) return -1; // private2
294 len=stream_read_word(demux->stream);
295 mp_dbg(MSGT_DEMUX,MSGL_DBG3,"PACKET len=%d",len);
296 // if(len==62480){ demux->synced=0;return -1;} /* :) */
297 if(len==0 || len>MAX_PS_PACKETSIZE){
298 mp_dbg(MSGT_DEMUX,MSGL_DBG2,"Invalid PS packet len: %d\n",len);
299 return -2; // invalid packet !!!!!!
302 mpeg_pts_error=0;
304 if(id==0x1BC) {
305 parse_psm(demux, len);
306 return 0;
309 while(len>0){ // Skip stuFFing bytes
310 c=stream_read_char(demux->stream);
311 --len;
312 if(c!=0xFF)break;
314 if((c>>6)==1){ // Read (skip) STD scale & size value
315 // printf(" STD_scale=%d",(c>>5)&1);
316 d=((c&0x1F)<<8)|stream_read_char(demux->stream);
317 len-=2;
318 // printf(" STD_size=%d",d);
319 c=stream_read_char(demux->stream);
321 // Read System-1 stream timestamps:
322 if((c>>4)==2){
323 pts=read_mpeg_timestamp(demux->stream,c);
324 set_pts=1;
325 len-=4;
326 } else
327 if((c>>4)==3){
328 pts=read_mpeg_timestamp(demux->stream,c);
329 c=stream_read_char(demux->stream);
330 if((c>>4)!=1) pts=0; //printf("{ERROR4}");
331 else set_pts = 1;
332 dts=read_mpeg_timestamp(demux->stream,c);
333 len-=4+1+4;
334 } else
335 if((c>>6)==2){
336 int pts_flags;
337 int hdrlen;
338 int parse_ext2;
339 // System-2 (.VOB) stream:
340 c=stream_read_char(demux->stream);
341 pts_flags=c>>6;
342 parse_ext2 = (id == 0x1FD) && ((c & 0x3F) == 1);
343 c=stream_read_char(demux->stream);
344 hdrlen=c;
345 len-=2;
346 mp_dbg(MSGT_DEMUX,MSGL_DBG3," hdrlen=%d (len=%d)",hdrlen,len);
347 if(hdrlen>len){ mp_msg(MSGT_DEMUX,MSGL_V,"demux_mpg: invalid header length \n"); return -1;}
348 if(pts_flags==2 && hdrlen>=5){
349 c=stream_read_char(demux->stream);
350 pts=read_mpeg_timestamp(demux->stream,c);
351 set_pts=1;
352 len-=5;hdrlen-=5;
353 } else
354 if(pts_flags==3 && hdrlen>=10){
355 c=stream_read_char(demux->stream);
356 pts=read_mpeg_timestamp(demux->stream,c);
357 set_pts=1;
358 c=stream_read_char(demux->stream);
359 dts=read_mpeg_timestamp(demux->stream,c);
360 len-=10;hdrlen-=10;
362 len-=hdrlen;
363 if(parse_ext2 && hdrlen>=3) {
364 c=stream_read_char(demux->stream);
365 hdrlen--;
367 if((c & 0x0F) != 0x0F) {
368 mp_msg(MSGT_DEMUX,MSGL_V,"demux_mpg: pes_extension_flag2 not set, discarding pes packet\n");
369 return -1;
371 if(c & 0x80) { //pes_private_data_flag
372 if(hdrlen<16) {
373 mp_msg(MSGT_DEMUX,MSGL_V,"demux_mpg: not enough pes_private_data bytes: %d < 16, discarding pes packet\n", hdrlen);
374 return -1;
376 stream_skip(demux->stream, 16);
377 hdrlen-=16;
379 if(c & 0x40) { //pack_header_field_flag
380 int l = stream_read_char(demux->stream);
381 if(l < 0) //couldn't read from the stream?
382 return -1;
383 hdrlen--;
384 if(l < 0 || hdrlen < l) {
385 mp_msg(MSGT_DEMUX,MSGL_V,"demux_mpg: not enough pack_header bytes: hdrlen: %d < skip: %d, discarding pes packet\n",
386 hdrlen, l);
387 return -1;
389 stream_skip(demux->stream, l);
390 hdrlen-=l;
392 if(c & 0x20) { //program_packet_sequence_counter_flag
393 if(hdrlen < 2) {
394 mp_msg(MSGT_DEMUX,MSGL_V,"demux_mpg: not enough program_packet bytes: hdrlen: %d, discarding pes packet\n", hdrlen);
395 return -1;
397 stream_skip(demux->stream, 2);
398 hdrlen-=2;
400 if(c & 0x10) {
401 //STD
402 stream_skip(demux->stream, 2);
403 hdrlen-=2;
405 c=stream_read_char(demux->stream); //pes_extension2 flag
406 hdrlen--;
407 if(c!=0x81) { mp_msg(MSGT_DEMUX,MSGL_V,"demux_mpg: unknown pes_extension2 format, len is > 1 \n"); return -1;}
408 c=stream_read_char(demux->stream); //pes_extension2 payload === substream id
409 hdrlen--;
410 if(c<0x55 || c>0x5F) { mp_msg(MSGT_DEMUX,MSGL_V,"demux_mpg: unknown vc1 substream_id: 0x%x \n", c); return -1;}
411 pes_ext2_subid=c;
413 if(hdrlen>0)
414 stream_skip(demux->stream,hdrlen); // skip header and stuffing bytes
416 if(id==0x1FD && pes_ext2_subid!=-1) {
417 //==== EVO VC1 STREAMS ===//
418 if(!demux->v_streams[pes_ext2_subid]) new_sh_video(demux,pes_ext2_subid);
419 if(demux->video->id==-1) demux->video->id=pes_ext2_subid;
420 if(demux->video->id==pes_ext2_subid){
421 ds=demux->video;
422 if(!ds->sh) ds->sh=demux->v_streams[pes_ext2_subid];
423 if(priv && ds->sh) {
424 sh_video_t *sh = (sh_video_t *)ds->sh;
425 sh->format = mmioFOURCC('W', 'V', 'C', '1');
429 //============== DVD Audio sub-stream ======================
430 if(id==0x1BD){
431 int aid, rawa52 = 0;
432 off_t tmppos;
433 unsigned int tmp;
435 tmppos = stream_tell(demux->stream);
436 tmp = stream_read_word(demux->stream);
437 stream_seek(demux->stream, tmppos);
438 /// vdr stores A52 without the 4 header bytes, so we have to check this condition first
439 if(tmp == 0x0B77) {
440 aid = 128;
441 rawa52 = 1;
443 else {
444 aid=stream_read_char(demux->stream);--len;
445 if(len<3) return -1; // invalid audio packet
448 // AID:
449 // 0x20..0x3F subtitle
450 // 0x80..0x87 and 0xC0..0xCF AC3 audio
451 // 0x88..0x8F and 0x98..0x9F DTS audio
452 // 0xA0..0xBF PCM audio
454 if((aid & 0xE0) == 0x20){
455 // subtitle:
456 aid&=0x1F;
458 if(!demux->s_streams[aid]){
459 sh_sub_t *sh = new_sh_sub(demux, aid);
460 if (sh) sh->type = 'v';
461 mp_msg(MSGT_DEMUX,MSGL_V,"==> Found subtitle: %d\n",aid);
464 if(demux->sub->id > -1)
465 demux->sub->id &= 0x1F;
466 if(!dvdsub_lang && demux->sub->id == -1)
467 demux->sub->id = aid;
468 if(demux->sub->id==aid){
469 ds=demux->sub;
471 } else if((aid >= 0x80 && aid <= 0x8F) || (aid >= 0x98 && aid <= 0xAF) || (aid >= 0xC0 && aid <= 0xCF)) {
473 // aid=128+(aid&0x7F);
474 // aid=0x80..0xBF
475 new_audio_stream(demux, aid);
476 if(demux->audio->id==aid){
477 int type;
478 ds=demux->audio;
479 if(!ds->sh) ds->sh=demux->a_streams[aid];
480 // READ Packet: Skip additional audio header data:
481 if(!rawa52) {
482 c=stream_read_char(demux->stream);//num of frames
483 type=stream_read_char(demux->stream);//startpos hi
484 type=(type<<8)|stream_read_char(demux->stream);//startpos lo
485 // printf("\r[%02X][%04X]",c,type);
486 len-=3;
488 if((aid&0xE0)==0xA0 && len>=3){
489 unsigned char* hdr;
490 // save audio header as codecdata!
491 if(!((sh_audio_t*)(ds->sh))->codecdata_len){
492 ((sh_audio_t*)(ds->sh))->codecdata=malloc(3);
493 ((sh_audio_t*)(ds->sh))->codecdata_len=3;
495 hdr=((sh_audio_t*)(ds->sh))->codecdata;
496 // read LPCM header:
497 // emphasis[1], mute[1], rvd[1], frame number[5]:
498 hdr[0]=stream_read_char(demux->stream);
499 // printf(" [%01X:%02d]",c>>5,c&31);
500 // quantization[2],freq[2],rvd[1],channels[3]
501 hdr[1]=stream_read_char(demux->stream);
502 // printf("[%01X:%01X] ",c>>4,c&15);
503 // dynamic range control (0x80=off):
504 hdr[2]=stream_read_char(demux->stream);
505 // printf("[%02X] ",c);
506 len-=3;
507 if(len<=0) mp_msg(MSGT_DEMUX,MSGL_V,"End of packet while searching for PCM header\n");
509 // printf(" \n");
510 } // if(demux->audio->id==aid)
512 } else mp_msg(MSGT_DEMUX,MSGL_V,"Unknown 0x1BD substream: 0x%02X \n",aid);
513 } //if(id==0x1BD)
514 } else {
515 if(c!=0x0f){
516 mp_msg(MSGT_DEMUX,MSGL_V," {ERROR5,c=%d} \n",c);
517 return -1; // invalid packet !!!!!!
520 if(mpeg_pts_error) mp_msg(MSGT_DEMUX,MSGL_V," {PTS_err:%d} \n",mpeg_pts_error);
521 mp_dbg(MSGT_DEMUX,MSGL_DBG3," => len=%d\n",len);
523 // if(len<=0 || len>MAX_PS_PACKETSIZE) return -1; // Invalid packet size
524 if(len<=0 || len>MAX_PS_PACKETSIZE){
525 mp_dbg(MSGT_DEMUX,MSGL_DBG2,"Invalid PS data len: %d\n",len);
526 return -1; // invalid packet !!!!!!
529 if(id>=0x1C0 && id<=0x1DF){
530 // mpeg audio
531 int aid=id-0x1C0;
532 new_audio_stream(demux, aid);
533 if(demux->audio->id==aid){
534 ds=demux->audio;
535 if(!ds->sh) ds->sh=demux->a_streams[aid];
536 if(priv && ds->sh) {
537 sh_audio_t *sh = (sh_audio_t *)ds->sh;
538 if(priv->es_map[id - 0x1B0])
539 sh->format = priv->es_map[id - 0x1B0];
540 mp_dbg(MSGT_DEMUX,MSGL_DBG2,"ASSIGNED TO STREAM %d CODEC %x\n", id, priv->es_map[id - 0x1B0]);
543 } else
544 if(id>=0x1E0 && id<=0x1EF){
545 // mpeg video
546 int aid=id-0x1E0;
547 if(!demux->v_streams[aid]) new_sh_video(demux,aid);
548 if(demux->video->id==-1) demux->video->id=aid;
549 if(demux->video->id==aid){
550 ds=demux->video;
551 if(!ds->sh) ds->sh=demux->v_streams[aid];
552 if(priv && ds->sh) {
553 sh_video_t *sh = (sh_video_t *)ds->sh;
554 if(priv->es_map[id - 0x1B0]) {
555 sh->format = priv->es_map[id - 0x1B0];
556 mp_dbg(MSGT_DEMUX,MSGL_DBG2,"ASSIGNED TO STREAM %d CODEC %x\n", id, priv->es_map[id - 0x1B0]);
562 if(ds){
563 mp_dbg(MSGT_DEMUX,MSGL_DBG2,"DEMUX_MPG: Read %d data bytes from packet %04X\n",len,id);
564 // printf("packet start = 0x%X \n",stream_tell(demux->stream)-packet_start_pos);
566 dp=new_demux_packet(len);
567 if(!dp) {
568 mp_dbg(MSGT_DEMUX,MSGL_ERR,"DEMUX_MPG ERROR: couldn't create demux_packet(%d bytes)\n",len);
569 stream_skip(demux->stream,len);
570 return 0;
572 l = stream_read(demux->stream,dp->buffer,len);
573 if(l<len)
574 resize_demux_packet(dp, l);
575 len = l;
576 if(set_pts)
577 dp->pts=pts/90000.0f;
578 dp->pos=demux->filepos;
580 workaround:
581 set dp->stream_pts only when feeding the video stream, or strangely interleaved files
582 (such as SWIII) will show strange alternations in the stream time, wildly going
583 back and forth
585 if(ds == demux->video && stream_control(demux->stream, STREAM_CTRL_GET_CURRENT_TIME,(void *)&stream_pts)!=STREAM_UNSUPPORTED)
586 dp->stream_pts = stream_pts;
587 ds_add_packet(ds,dp);
588 if (demux->priv && set_pts) ((mpg_demuxer_t*)demux->priv)->last_pts = pts/90000.0f;
589 // if(ds==demux->sub) parse_dvdsub(ds->last->buffer,ds->last->len);
590 return 1;
592 mp_dbg(MSGT_DEMUX,MSGL_DBG2,"DEMUX_MPG: Skipping %d data bytes from packet %04X\n",len,id);
593 if(len<=2356) stream_skip(demux->stream,len);
594 return 0;
597 static int num_elementary_packets100=0;
598 static int num_elementary_packets101=0;
599 static int num_elementary_packets12x=0;
600 static int num_elementary_packets1B6=0;
601 static int num_elementary_packetsPES=0;
602 static int num_mpeg12_startcode=0;
603 static int num_h264_slice=0; //combined slice
604 static int num_h264_dpa=0; //DPA Slice
605 static int num_h264_dpb=0; //DPB Slice
606 static int num_h264_dpc=0; //DPC Slice
607 static int num_h264_idr=0; //IDR Slice
608 static int num_h264_sps=0;
609 static int num_h264_pps=0;
611 static int num_mp3audio_packets=0;
613 static void clear_stats(void)
615 num_elementary_packets100=0;
616 num_elementary_packets101=0;
617 num_elementary_packets1B6=0;
618 num_elementary_packets12x=0;
619 num_elementary_packetsPES=0;
620 num_mpeg12_startcode=0;
621 num_h264_slice=0; //combined slice
622 num_h264_dpa=0; //DPA Slice
623 num_h264_dpb=0; //DPB Slice
624 num_h264_dpc=0; //DPC Slice
625 num_h264_idr=0; //IDR Slice
626 num_h264_sps=0;
627 num_h264_pps=0;
628 num_mp3audio_packets=0;
631 //assumes demuxer->synced < 2
632 static inline void update_stats(int head)
634 if(head==0x1B6) ++num_elementary_packets1B6;
635 else if(head==0x1B3 || head==0x1B8) ++num_mpeg12_startcode;
636 else if(head==0x100) ++num_elementary_packets100;
637 else if(head==0x101) ++num_elementary_packets101;
638 else if(head==0x1BD || (0x1C0<=head && head<=0x1EF))
639 num_elementary_packetsPES++;
640 else if(head>=0x120 && head<=0x12F) ++num_elementary_packets12x;
641 if(head>=0x100 && head<0x1B0)
643 if((head&~0x60) == 0x101) ++num_h264_slice;
644 else if((head&~0x60) == 0x102) ++num_h264_dpa;
645 else if((head&~0x60) == 0x103) ++num_h264_dpb;
646 else if((head&~0x60) == 0x104) ++num_h264_dpc;
647 else if((head&~0x60) == 0x105 && head != 0x105) ++num_h264_idr;
648 else if((head&~0x60) == 0x107 && head != 0x107) ++num_h264_sps;
649 else if((head&~0x60) == 0x108 && head != 0x108) ++num_h264_pps;
653 static int demux_mpg_probe(demuxer_t *demuxer) {
654 int pes=1;
655 int tmp;
656 off_t tmppos;
657 int file_format = DEMUXER_TYPE_UNKNOWN;
659 tmppos=stream_tell(demuxer->stream);
660 tmp=stream_read_dword(demuxer->stream);
661 if(tmp==0x1E0 || tmp==0x1C0) {
662 tmp=stream_read_word(demuxer->stream);
663 if(tmp>1 && tmp<=2048) pes=0; // demuxer->synced=3; // PES...
665 stream_seek(demuxer->stream,tmppos);
667 clear_stats();
669 if(demux_mpg_open(demuxer))
670 file_format=DEMUXER_TYPE_MPEG_PS;
671 else {
672 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",
673 num_elementary_packets100,num_elementary_packets101,
674 num_elementary_packets1B6,num_elementary_packets12x,
675 num_h264_slice, num_h264_dpa,
676 num_h264_dpb, num_h264_dpc=0,
677 num_h264_idr, num_h264_sps=0,
678 num_h264_pps,
679 num_elementary_packetsPES,num_mp3audio_packets, demuxer->synced);
681 //MPEG packet stats: p100: 458 p101: 458 PES: 0 MP3: 1103 (.m2v)
682 if(num_mp3audio_packets>50 && num_mp3audio_packets>2*num_elementary_packets100
683 && abs(num_elementary_packets100-num_elementary_packets101)>2)
684 return file_format;
686 // some hack to get meaningfull error messages to our unhappy users:
687 if(num_mpeg12_startcode>=2 && num_elementary_packets100>=2 && num_elementary_packets101>=2 &&
688 abs(num_elementary_packets101+8-num_elementary_packets100)<16) {
689 if(num_elementary_packetsPES>=4 && num_elementary_packetsPES>=num_elementary_packets100-4) {
690 return file_format;
692 file_format=DEMUXER_TYPE_MPEG_ES; // <-- hack is here :)
693 } else
694 // fuzzy mpeg4-es detection. do NOT enable without heavy testing of mpeg formats detection!
695 if(num_elementary_packets1B6>3 && num_elementary_packets12x>=1 &&
696 num_elementary_packetsPES==0 && num_elementary_packets100<=num_elementary_packets12x &&
697 demuxer->synced<2) {
698 file_format=DEMUXER_TYPE_MPEG4_ES;
699 } else
700 // fuzzy h264-es detection. do NOT enable without heavy testing of mpeg formats detection!
701 if((num_h264_slice>3 || (num_h264_dpa>3 && num_h264_dpb>3 && num_h264_dpc>3)) &&
702 /* FIXME num_h264_sps>=1 && */ num_h264_pps>=1 && num_h264_idr>=1 &&
703 num_elementary_packets1B6==0 && num_elementary_packetsPES==0 &&
704 demuxer->synced<2) {
705 file_format=DEMUXER_TYPE_H264_ES;
706 } else
708 if(demuxer->synced==2)
709 mp_tmsg(MSGT_DEMUXER,MSGL_ERR,"MPEG: " "Missing video stream!? Contact the author, it may be a bug :(\n");
710 else
711 mp_tmsg(MSGT_DEMUXER,MSGL_V,"Not MPEG System Stream format... (maybe Transport Stream?)\n");
714 //FIXME this shouldn't be necessary
715 stream_seek(demuxer->stream,tmppos);
716 return file_format;
719 static int demux_mpg_es_fill_buffer(demuxer_t *demux, demux_stream_t *ds){
720 // Elementary video stream
721 if(demux->stream->eof) return 0;
722 demux->filepos=stream_tell(demux->stream);
723 ds_read_packet(demux->video,demux->stream,STREAM_BUFFER_SIZE,0,demux->filepos,0);
724 return 1;
728 * \brief discard until 0x100 header and return a filled buffer
729 * \param b buffer-end pointer
730 * \param pos current pos in stream, negative since b points to end of buffer
731 * \param s stream to read from
732 * \return new position, differs from original pos when eof hit and thus
733 * b was modified to point to the new end of buffer
735 static int find_end(unsigned char **b, int pos, stream_t *s) {
736 register int state = 0xffffffff;
737 unsigned char *buf = *b;
738 int start = pos;
739 int read, unused;
740 // search already read part
741 while (state != 0x100 && pos) {
742 state = state << 8 | buf[pos++];
744 // continue search in stream
745 while (state != 0x100) {
746 register int c = stream_read_char(s);
747 if (c < 0) break;
748 state = state << 8 | c;
750 // modify previous header (from 0x1bc or 0x1bf to 0x100)
751 buf[start++] = 0;
752 // copy remaining buffer part to current pos
753 memmove(&buf[start], &buf[pos], -pos);
754 unused = start + -pos; // -unused bytes in buffer
755 read = stream_read(s, &buf[unused], -unused);
756 unused += read;
757 // fix buffer so it ends at pos == 0 (eof case)
758 *b = &buf[unused];
759 start -= unused;
760 return start;
764 * This format usually uses an insane bitrate, which makes this function
765 * performance-critical!
766 * Be sure to benchmark any changes with different compiler versions.
768 static int demux_mpg_gxf_fill_buffer(demuxer_t *demux, demux_stream_t *ds) {
769 demux_packet_t *pack;
770 int len;
771 demux->filepos = stream_tell(demux->stream);
772 pack = new_demux_packet(STREAM_BUFFER_SIZE);
773 len = stream_read(demux->stream, pack->buffer, STREAM_BUFFER_SIZE);
774 if (len <= 0)
776 free_demux_packet(pack);
777 return 0;
780 register uint32_t state = (uint32_t)demux->priv;
781 register int pos = -len;
782 unsigned char *buf = &pack->buffer[len];
783 do {
784 state = state << 8 | buf[pos];
785 if (unlikely((state | 3) == 0x1bf))
786 pos = find_end(&buf, pos, demux->stream);
787 } while (++pos < 0);
788 demux->priv = (void *)state;
789 len = buf - pack->buffer;
791 if (len < STREAM_BUFFER_SIZE)
792 resize_demux_packet(pack, len);
793 ds_add_packet(ds, pack);
794 return 1;
797 static int demux_mpg_fill_buffer(demuxer_t *demux, demux_stream_t *ds){
798 unsigned int head=0;
799 int skipped=0;
800 int max_packs=256; // 512kbyte
801 int ret=0;
803 // System stream
805 demux->filepos=stream_tell(demux->stream);
806 #if 1
807 //lame workaround: this is needed to show the progress bar when playing dvdnav://
808 //(ths poor guy doesn't know teh length of the stream at startup)
809 demux->movi_end = demux->stream->end_pos;
810 #endif
811 head=stream_read_dword(demux->stream);
812 if((head&0xFFFFFF00)!=0x100){
813 // sync...
814 demux->filepos-=skipped;
815 while(1){
816 int c=stream_read_char(demux->stream);
817 if(c<0) break; //EOF
818 head<<=8;
819 if(head!=0x100){
820 head|=c;
821 if(mp_check_mp3_header(head)) ++num_mp3audio_packets;
822 ++skipped; //++demux->filepos;
823 continue;
825 head|=c;
826 break;
828 demux->filepos+=skipped;
830 if(stream_eof(demux->stream)) break;
831 // sure: head=0x000001XX
832 mp_dbg(MSGT_DEMUX,MSGL_DBG4,"*** head=0x%X\n",head);
833 if(demux->synced==0){
834 if(head==0x1BA) demux->synced=1; //else
835 // if(head==0x1BD || (head>=0x1C0 && head<=0x1EF)) demux->synced=3; // PES?
836 } else
837 if(demux->synced==1){
838 if(head==0x1BB || head==0x1BD || (head>=0x1C0 && head<=0x1EF)){
839 demux->synced=2;
840 mp_msg(MSGT_DEMUX,MSGL_V,"system stream synced at 0x%"PRIX64" (%"PRId64")!\n",(int64_t)demux->filepos,(int64_t)demux->filepos);
841 num_elementary_packets100=0; // requires for re-sync!
842 num_elementary_packets101=0; // requires for re-sync!
843 } else demux->synced=0;
844 } // else
845 if(demux->synced>=2){
846 ret=demux_mpg_read_packet(demux,head);
847 if(!ret)
848 if(--max_packs==0){
849 demux->stream->eof=1;
850 mp_tmsg(MSGT_DEMUX,MSGL_ERR,"demux: File doesn't contain the selected audio or video stream.\n");
851 return 0;
853 if(demux->synced==3) demux->synced=(ret==1)?2:0; // PES detect
854 } else {
855 update_stats(head);
856 if(head>=0x100 && head<0x1B0)
857 mp_msg(MSGT_DEMUX,MSGL_DBG3,"Opps... elementary video packet found: %03X\n",head);
858 else if((head>=0x1C0 && head<0x1F0) || head==0x1BD)
859 mp_msg(MSGT_DEMUX,MSGL_DBG3,"Opps... PES packet found: %03X\n",head);
861 if(((num_elementary_packets100>50 && num_elementary_packets101>50) ||
862 (num_elementary_packetsPES>50)) && skipped>4000000){
863 mp_msg(MSGT_DEMUX,MSGL_V,"sync_mpeg_ps: seems to be ES/PES stream...\n");
864 demux->stream->eof=1;
865 break;
867 if(num_mp3audio_packets>100 && num_elementary_packets100<10){
868 mp_msg(MSGT_DEMUX,MSGL_V,"sync_mpeg_ps: seems to be MP3 stream...\n");
869 demux->stream->eof=1;
870 break;
873 } while(ret!=1);
874 mp_dbg(MSGT_DEMUX,MSGL_DBG2,"demux: %d bad bytes skipped\n",skipped);
875 if(demux->stream->eof){
876 mp_msg(MSGT_DEMUX,MSGL_V,"MPEG Stream reached EOF\n");
877 return 0;
879 return 1;
882 void skip_audio_frame(sh_audio_t *sh_audio);
884 static void demux_seek_mpg(demuxer_t *demuxer,float rel_seek_secs,float audio_delay, int flags){
885 demux_stream_t *d_audio=demuxer->audio;
886 demux_stream_t *d_video=demuxer->video;
887 sh_audio_t *sh_audio=d_audio->sh;
888 sh_video_t *sh_video=d_video->sh;
889 mpg_demuxer_t *mpg_d=(mpg_demuxer_t*)demuxer->priv;
890 int precision = 1;
891 float oldpts = 0;
892 off_t oldpos = demuxer->filepos;
893 float newpts = 0;
894 off_t newpos = (flags & SEEK_ABSOLUTE) ? demuxer->movi_start : oldpos;
896 if(mpg_d)
897 oldpts = mpg_d->last_pts;
898 newpts = (flags & SEEK_ABSOLUTE) ? 0.0 : oldpts;
899 //================= seek in MPEG ==========================
900 //calculate the pts to seek to
901 if(flags & SEEK_FACTOR) {
902 if (mpg_d && mpg_d->first_to_final_pts_len > 0.0)
903 newpts += mpg_d->first_to_final_pts_len * rel_seek_secs;
904 else
905 newpts += rel_seek_secs * (demuxer->movi_end - demuxer->movi_start) * oldpts / oldpos;
906 } else
907 newpts += rel_seek_secs;
908 if (newpts < 0) newpts = 0;
910 if(flags&SEEK_FACTOR){
911 // float seek 0..1
912 newpos+=(demuxer->movi_end-demuxer->movi_start)*rel_seek_secs;
913 } else {
914 // time seek (secs)
915 if (mpg_d && mpg_d->has_valid_timestamps) {
916 if (mpg_d->first_to_final_pts_len > 0.0)
917 newpos += rel_seek_secs * (demuxer->movi_end - demuxer->movi_start) / mpg_d->first_to_final_pts_len;
918 else if (oldpts > 0.0)
919 newpos += rel_seek_secs * (oldpos - demuxer->movi_start) / oldpts;
920 } else if(!sh_video || !sh_video->i_bps) // unspecified or VBR
921 newpos+=2324*75*rel_seek_secs; // 174.3 kbyte/sec
922 else
923 newpos+=sh_video->i_bps*rel_seek_secs;
926 while (1) {
927 if(newpos<demuxer->movi_start){
928 if(demuxer->stream->type!=STREAMTYPE_VCD) demuxer->movi_start=0; // for VCD
929 if(newpos<demuxer->movi_start) newpos=demuxer->movi_start;
932 stream_seek(demuxer->stream,newpos);
934 // re-sync video:
935 videobuf_code_len=0; // reset ES stream buffer
937 ds_fill_buffer(d_video);
938 if(sh_audio){
939 ds_fill_buffer(d_audio);
942 while(1){
943 int i;
944 if(sh_audio && !d_audio->eof && d_video->pts && d_audio->pts){
945 float a_pts=d_audio->pts;
946 a_pts+=(ds_tell_pts(d_audio)-sh_audio->a_in_buffer_len)/(float)sh_audio->i_bps;
947 if(d_video->pts>a_pts){
948 skip_audio_frame(sh_audio); // sync audio
949 continue;
952 if(!sh_video) break;
953 i=sync_video_packet(d_video);
954 if(sh_video->format == mmioFOURCC('W', 'V', 'C', '1')) {
955 if(i==0x10E || i==0x10F) //entry point or sequence header
956 break;
957 } else
958 if(sh_video->format == 0x10000004) { //mpeg4
959 if(i==0x1B6) { //vop (frame) startcode
960 int pos = videobuf_len;
961 if(!read_video_packet(d_video)) break; // EOF
962 if((videobuffer[pos+4] & 0x3F) == 0) break; //I-frame
964 } else if(sh_video->format == 0x10000005){ //h264
965 if((i & ~0x60) == 0x105) break;
966 } else { //default mpeg1/2
967 if(i==0x1B3 || i==0x1B8) break; // found it!
969 if(!i || !skip_video_packet(d_video)) break; // EOF?
971 if(!mpg_d)
972 break;
973 if (!precision || abs(newpts - mpg_d->last_pts) < 0.5 || (mpg_d->last_pts == oldpts)) break;
974 if ((newpos - oldpos) * (mpg_d->last_pts - oldpts) < 0) { // invalid timestamps
975 mpg_d->has_valid_timestamps = 0;
976 break;
978 precision--;
979 //prepare another seek because we are off by more than 0.5s
980 if(mpg_d) {
981 newpos += (newpts - mpg_d->last_pts) * (newpos - oldpos) / (mpg_d->last_pts - oldpts);
982 demux_flush(demuxer);
983 demuxer->stream->eof=0; // clear eof flag
984 d_video->eof=0;
985 d_audio->eof=0;
990 static int demux_mpg_control(demuxer_t *demuxer,int cmd, void *arg){
991 mpg_demuxer_t *mpg_d=(mpg_demuxer_t*)demuxer->priv;
993 switch(cmd) {
994 case DEMUXER_CTRL_GET_TIME_LENGTH:
995 if(stream_control(demuxer->stream, STREAM_CTRL_GET_TIME_LENGTH, arg) != STREAM_UNSUPPORTED) {
996 mp_msg(MSGT_DEMUXER,MSGL_DBG2,"\r\nDEMUX_MPG_CTRL, (%.3lf)\r\n", *((double*)arg));
997 return DEMUXER_CTRL_GUESS;
999 if (mpg_d && mpg_d->has_valid_timestamps) {
1000 *((double *)arg)=(double)mpg_d->first_to_final_pts_len;
1001 return DEMUXER_CTRL_OK;
1003 return DEMUXER_CTRL_DONTKNOW;
1005 case DEMUXER_CTRL_GET_PERCENT_POS:
1006 if (mpg_d && mpg_d->has_valid_timestamps && mpg_d->first_to_final_pts_len > 0.0) {
1007 *((int *)arg)=(int)(100 * (mpg_d->last_pts-mpg_d->first_pts) / mpg_d->first_to_final_pts_len);
1008 return DEMUXER_CTRL_OK;
1010 return DEMUXER_CTRL_DONTKNOW;
1012 case DEMUXER_CTRL_SWITCH_AUDIO:
1013 if(! (mpg_d && mpg_d->num_a_streams > 1 && demuxer->audio && demuxer->audio->sh))
1014 return DEMUXER_CTRL_NOTIMPL;
1015 else {
1016 demux_stream_t *d_audio = demuxer->audio;
1017 sh_audio_t *sh_audio = d_audio->sh;
1018 sh_audio_t *sh_a = sh_audio;
1019 int i;
1020 if(!sh_audio)
1021 return DEMUXER_CTRL_NOTIMPL;
1022 if (*((int*)arg) < 0)
1024 for (i = 0; i < mpg_d->num_a_streams; i++) {
1025 if (d_audio->id == mpg_d->a_stream_ids[i]) break;
1027 i = (i+1) % mpg_d->num_a_streams;
1028 sh_a = (sh_audio_t*)demuxer->a_streams[mpg_d->a_stream_ids[i]];
1030 else {
1031 for (i = 0; i < mpg_d->num_a_streams; i++)
1032 if (*((int*)arg) == mpg_d->a_stream_ids[i]) break;
1033 if (i < mpg_d->num_a_streams)
1034 sh_a = (sh_audio_t*)demuxer->a_streams[*((int*)arg)];
1036 if (i < mpg_d->num_a_streams && d_audio->id != mpg_d->a_stream_ids[i]) {
1037 d_audio->id = mpg_d->a_stream_ids[i];
1038 d_audio->sh = sh_a;
1039 ds_free_packs(d_audio);
1042 *((int*)arg) = demuxer->audio->id;
1043 return DEMUXER_CTRL_OK;
1045 default:
1046 return DEMUXER_CTRL_NOTIMPL;
1051 static int demux_mpg_pes_probe(demuxer_t *demuxer) {
1052 demuxer->synced = 3;
1053 return (demux_mpg_probe(demuxer) == DEMUXER_TYPE_MPEG_PS) ? DEMUXER_TYPE_MPEG_PES : 0;
1057 static demuxer_t* demux_mpg_es_open(demuxer_t* demuxer)
1059 sh_video_t *sh_video=NULL;
1061 demuxer->audio->sh = NULL; // ES streams has no audio channel
1062 demuxer->video->sh = new_sh_video(demuxer,0); // create dummy video stream header, id=0
1063 sh_video=demuxer->video->sh;sh_video->ds=demuxer->video;
1065 return demuxer;
1068 static demuxer_t *demux_mpg_gxf_open(demuxer_t *demuxer) {
1069 demuxer->audio->sh = NULL;
1070 demuxer->video->sh = new_sh_video(demuxer,0);
1071 ((sh_video_t *)demuxer->video->sh)->ds = demuxer->video;
1072 demuxer->priv = (void *) 0xffffffff;
1073 return demuxer;
1076 static demuxer_t* demux_mpg_ps_open(demuxer_t* demuxer)
1078 sh_audio_t *sh_audio=NULL;
1079 sh_video_t *sh_video=NULL;
1081 sh_video=demuxer->video->sh;sh_video->ds=demuxer->video;
1083 if(demuxer->audio->id!=-2) {
1084 if(!ds_fill_buffer(demuxer->audio)){
1085 mp_tmsg(MSGT_DEMUXER,MSGL_INFO,"MPEG: " "No audio stream found -> no sound.\n");
1086 demuxer->audio->sh=NULL;
1087 } else {
1088 sh_audio=demuxer->audio->sh;sh_audio->ds=demuxer->audio;
1092 if(!sh_video->format && ps_probe > 0) {
1093 int head;
1094 off_t pos = stream_tell(demuxer->stream);
1096 clear_stats();
1097 do {
1098 head=sync_video_packet(demuxer->video);
1099 if(!head) break;
1100 update_stats(head);
1101 skip_video_packet(demuxer->video);
1102 } while(stream_tell(demuxer->stream) < pos + ps_probe && !demuxer->stream->eof);
1104 ds_free_packs(demuxer->video);
1105 demuxer->stream->eof=0;
1106 stream_seek(demuxer->stream, pos);
1107 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",
1108 num_elementary_packets100, num_elementary_packets101,
1109 num_elementary_packets1B6, num_elementary_packets12x,
1110 num_h264_slice, num_h264_dpa, num_h264_dpb, num_h264_dpc,
1111 num_h264_idr, num_h264_sps, num_h264_pps);
1113 if(num_elementary_packets1B6>3 && num_elementary_packets12x>=1 &&
1114 num_elementary_packets100<=num_elementary_packets12x)
1115 sh_video->format = 0x10000004;
1116 else if((num_h264_slice>3 || (num_h264_dpa>3 && num_h264_dpb>3 && num_h264_dpc>3)) &&
1117 num_h264_sps>=1 && num_h264_pps>=1 && num_h264_idr>=1 &&
1118 num_elementary_packets1B6==0)
1119 sh_video->format = 0x10000005;
1120 else sh_video->format = 0x10000002;
1123 return demuxer;
1127 const demuxer_desc_t demuxer_desc_mpeg_ps = {
1128 "MPEG PS demuxer",
1129 "mpegps",
1130 "MPEG-PS",
1131 "Arpi?",
1132 "Mpeg",
1133 DEMUXER_TYPE_MPEG_PS,
1134 0, // unsafe autodetect
1135 demux_mpg_probe,
1136 demux_mpg_fill_buffer,
1137 demux_mpg_ps_open,
1138 demux_close_mpg,
1139 demux_seek_mpg,
1140 demux_mpg_control,
1144 const demuxer_desc_t demuxer_desc_mpeg_pes = {
1145 "MPEG PES demuxer",
1146 "mpegpes",
1147 "MPEG-PES",
1148 "Arpi?",
1149 "Mpeg",
1150 DEMUXER_TYPE_MPEG_PES,
1151 0, // unsafe autodetect
1152 demux_mpg_pes_probe,
1153 demux_mpg_fill_buffer,
1154 demux_mpg_ps_open,
1155 demux_close_mpg,
1156 demux_seek_mpg,
1157 demux_mpg_control,
1161 const demuxer_desc_t demuxer_desc_mpeg_gxf = {
1162 "MPEG ES in GXF demuxer",
1163 "mpeggxf",
1164 "MPEG-ES in GXF",
1165 "Reimar Doeffinger",
1166 "Mpeg",
1167 DEMUXER_TYPE_MPEG_GXF,
1168 0, // hack autodetection
1169 NULL,
1170 demux_mpg_gxf_fill_buffer,
1171 demux_mpg_gxf_open,
1172 NULL,
1173 NULL,
1174 NULL
1177 const demuxer_desc_t demuxer_desc_mpeg_es = {
1178 "MPEG ES demuxer",
1179 "mpeges",
1180 "MPEG-ES",
1181 "Arpi?",
1182 "Mpeg",
1183 DEMUXER_TYPE_MPEG_ES,
1184 0, // hack autodetection
1185 NULL,
1186 demux_mpg_es_fill_buffer,
1187 demux_mpg_es_open,
1188 demux_close_mpg,
1189 demux_seek_mpg,
1190 demux_mpg_control,
1194 const demuxer_desc_t demuxer_desc_mpeg4_es = {
1195 "MPEG4 ES demuxer",
1196 "mpeg4es",
1197 "MPEG-ES",
1198 "Arpi?",
1199 "Mpeg",
1200 DEMUXER_TYPE_MPEG4_ES,
1201 0, // hack autodetection
1202 NULL,
1203 demux_mpg_es_fill_buffer,
1204 demux_mpg_es_open,
1205 demux_close_mpg,
1206 demux_seek_mpg,
1207 demux_mpg_control,
1211 const demuxer_desc_t demuxer_desc_h264_es = {
1212 "H.264 ES demuxer",
1213 "h264es",
1214 "H264-ES",
1215 "Arpi?",
1216 "Mpeg",
1217 DEMUXER_TYPE_H264_ES,
1218 0, // hack autodetection
1219 NULL,
1220 demux_mpg_es_fill_buffer,
1221 demux_mpg_es_open,
1222 demux_close_mpg,
1223 demux_seek_mpg,
1224 demux_mpg_control,