diff options
-rw-r--r-- | libmpdemux/demux_mpg.c | 96 | ||||
-rw-r--r-- | libmpdemux/video.c | 20 |
2 files changed, 109 insertions, 7 deletions
diff --git a/libmpdemux/demux_mpg.c b/libmpdemux/demux_mpg.c index dbfa43a5e4..ffab3b1fca 100644 --- a/libmpdemux/demux_mpg.c +++ b/libmpdemux/demux_mpg.c @@ -17,14 +17,85 @@ //#define MAX_PS_PACKETSIZE 2048 #define MAX_PS_PACKETSIZE (224*1024) +#define UNKNOWN 0 +#define VIDEO_MPEG1 0x10000001 +#define VIDEO_MPEG2 0x10000002 +#define VIDEO_MPEG4 0x10000004 +#define VIDEO_H264 0x10000005 +#define AUDIO_MP2 0x50 +#define AUDIO_A52 0x2000 +#define AUDIO_LPCM_BE 0x10001 +#define AUDIO_AAC mmioFOURCC('M', 'P', '4', 'A') + typedef struct mpg_demuxer { float last_pts; float final_pts; int has_valid_timestamps; + unsigned int es_map[0x40]; //es map of stream types (associated to the pes id) from 0xb0 to 0xef } mpg_demuxer_t; static int mpeg_pts_error=0; +static int parse_psm(demuxer_t *demux, int len) { + unsigned char c, id, type; + unsigned int plen, prog_len, es_map_len; + mpg_demuxer_t *priv = (mpg_demuxer_t *) demux->priv; + + mp_dbg(MSGT_DEMUX,MSGL_V, "PARSE_PSM, len=%d\n", len); + if(! len) + return 0; + + c = stream_read_char(demux->stream); + if(! (c & 0x80)) { + stream_skip(demux->stream, len - 1); //not yet valid, discard + return 0; + } + stream_skip(demux->stream, 1); + prog_len = stream_read_word(demux->stream); //length of program descriptors + stream_skip(demux->stream, prog_len); //.. that we ignore + es_map_len = stream_read_word(demux->stream); //length of elementary streams map + es_map_len = min(es_map_len, len - prog_len - 8); //sanity check + while(es_map_len > 0) { + type = stream_read_char(demux->stream); + id = stream_read_char(demux->stream); + if(id >= 0xB0 && id <= 0xEF && priv) { + int idoffset = id - 0xB0; + switch(type) { + case 0x1: + priv->es_map[idoffset] = VIDEO_MPEG1; + break; + case 0x2: + priv->es_map[idoffset] = VIDEO_MPEG2; + break; + case 0x3: + case 0x4: + priv->es_map[idoffset] = AUDIO_MP2; + break; + case 0x0f: + case 0x11: + priv->es_map[idoffset] = AUDIO_AAC; + break; + case 0x10: + priv->es_map[idoffset] = VIDEO_MPEG4; + break; + case 0x1b: + priv->es_map[idoffset] = VIDEO_H264; + break; + case 0x81: + priv->es_map[idoffset] = AUDIO_A52; + break; + } + mp_dbg(MSGT_DEMUX,MSGL_V, "PSM ES, id=0x%x, type=%x, stype: %x\n", id, type, priv->es_map[idoffset]); + } + plen = stream_read_word(demux->stream); //length of elementary stream descriptors + plen = min(plen, es_map_len); //sanity check + stream_skip(demux->stream, plen); //skip descriptors for now + es_map_len -= 4 + plen; + } + stream_skip(demux->stream, 4); //skip crc32 + return 1; +} + /// Open an mpg physical stream int demux_mpg_open(demuxer_t* demuxer) { stream_t *s = demuxer->stream; @@ -90,6 +161,7 @@ static int demux_mpg_read_packet(demuxer_t *demux,int id){ unsigned int pts=0; unsigned int dts=0; demux_stream_t *ds=NULL; + mpg_demuxer_t *priv = (mpg_demuxer_t *) demux->priv; mp_dbg(MSGT_DEMUX,MSGL_DBG3,"demux_read_packet: %X\n",id); @@ -113,6 +185,11 @@ static int demux_mpg_read_packet(demuxer_t *demux,int id){ mpeg_pts_error=0; + if(id==0x1BC) { + parse_psm(demux, len); + return 0; + } + while(len>0){ // Skip stuFFing bytes c=stream_read_char(demux->stream);--len; if(c!=0xFF)break; @@ -255,6 +332,12 @@ static int demux_mpg_read_packet(demuxer_t *demux,int id){ if(demux->audio->id==aid){ ds=demux->audio; if(!ds->sh) ds->sh=demux->a_streams[aid]; + if(priv && ds->sh) { + sh_audio_t *sh = (sh_audio_t *)ds->sh; + if(priv->es_map[id - 0x1B0]) + sh->format = priv->es_map[id - 0x1B0]; + mp_dbg(MSGT_DEMUX,MSGL_DBG2,"ASSIGNED TO STREAM %d CODEC %x\n", id, priv->es_map[id - 0x1B0]); + } } } else if(id>=0x1E0 && id<=0x1EF){ @@ -265,6 +348,13 @@ static int demux_mpg_read_packet(demuxer_t *demux,int id){ if(demux->video->id==aid){ ds=demux->video; if(!ds->sh) ds->sh=demux->v_streams[aid]; + if(priv && ds->sh) { + sh_video_t *sh = (sh_video_t *)ds->sh; + if(priv->es_map[id - 0x1B0]) { + sh->format = priv->es_map[id - 0x1B0]; + mp_dbg(MSGT_DEMUX,MSGL_DBG2,"ASSIGNED TO STREAM %d CODEC %x\n", id, priv->es_map[id - 0x1B0]); + } + } } } @@ -479,7 +569,11 @@ void demux_seek_mpg(demuxer_t *demuxer,float rel_seek_secs,int flags){ } i=sync_video_packet(d_video); if(sh_video->format == 0x10000004) { //mpeg4 - if(i==0x1B6) break; //vop (frame) startcode + if(i==0x1B6) { //vop (frame) startcode + int pos = videobuf_len; + if(!read_video_packet(d_video)) break; // EOF + if((videobuffer[pos+4] & 0x3F) == 0) break; //I-frame + } } else if(sh_video->format == 0x10000005){ //h264 if((i & ~0x60) == 0x101 || (i & ~0x60) == 0x102 || (i & ~0x60) == 0x105) break; } else { //default mpeg1/2 diff --git a/libmpdemux/video.c b/libmpdemux/video.c index 5b98af0de9..693dab2e94 100644 --- a/libmpdemux/video.c +++ b/libmpdemux/video.c @@ -46,7 +46,7 @@ enum { if((d_video->demuxer->file_format == DEMUXER_TYPE_PVA) || (d_video->demuxer->file_format == DEMUXER_TYPE_MPEG_ES) || - (d_video->demuxer->file_format == DEMUXER_TYPE_MPEG_PS) || + (d_video->demuxer->file_format == DEMUXER_TYPE_MPEG_PS && ((! sh_video->format) || (sh_video->format==0x10000001) || (sh_video->format==0x10000002))) || (d_video->demuxer->file_format == DEMUXER_TYPE_MPEG_TY) || (d_video->demuxer->file_format == DEMUXER_TYPE_MPEG_TS && ((sh_video->format==0x10000001) || (sh_video->format==0x10000002))) #ifdef STREAMING_LIVE_DOT_COM @@ -55,11 +55,13 @@ if((d_video->demuxer->file_format == DEMUXER_TYPE_PVA) || ) video_codec = VIDEO_MPEG12; else if((d_video->demuxer->file_format == DEMUXER_TYPE_MPEG4_ES) || - ((d_video->demuxer->file_format == DEMUXER_TYPE_MPEG_TS) && (sh_video->format==0x10000004)) + ((d_video->demuxer->file_format == DEMUXER_TYPE_MPEG_TS) && (sh_video->format==0x10000004)) || + ((d_video->demuxer->file_format == DEMUXER_TYPE_MPEG_PS) && (sh_video->format==0x10000004)) ) video_codec = VIDEO_MPEG4; else if((d_video->demuxer->file_format == DEMUXER_TYPE_H264_ES) || - ((d_video->demuxer->file_format == DEMUXER_TYPE_MPEG_TS) && (sh_video->format==0x10000005)) + ((d_video->demuxer->file_format == DEMUXER_TYPE_MPEG_TS) && (sh_video->format==0x10000005)) || + ((d_video->demuxer->file_format == DEMUXER_TYPE_MPEG_PS) && (sh_video->format==0x10000005)) ) video_codec = VIDEO_H264; else @@ -400,7 +402,8 @@ int video_read_frame(sh_video_t* sh_video,float* frame_time_ptr,unsigned char** *start=NULL; - if(demuxer->file_format==DEMUXER_TYPE_MPEG_ES || demuxer->file_format==DEMUXER_TYPE_MPEG_PS + if(demuxer->file_format==DEMUXER_TYPE_MPEG_ES || + (demuxer->file_format==DEMUXER_TYPE_MPEG_PS && ((! sh_video->format) || (sh_video->format==0x10000001) || (sh_video->format==0x10000002))) || demuxer->file_format==DEMUXER_TYPE_PVA || ((demuxer->file_format==DEMUXER_TYPE_MPEG_TS) && ((sh_video->format==0x10000001) || (sh_video->format==0x10000002))) || demuxer->file_format==DEMUXER_TYPE_MPEG_TY @@ -493,17 +496,22 @@ int video_read_frame(sh_video_t* sh_video,float* frame_time_ptr,unsigned char** telecine=1; } - } else if((demuxer->file_format==DEMUXER_TYPE_MPEG4_ES) || ((demuxer->file_format==DEMUXER_TYPE_MPEG_TS) && (sh_video->format==0x10000004))){ + } else if((demuxer->file_format==DEMUXER_TYPE_MPEG4_ES) || ((demuxer->file_format==DEMUXER_TYPE_MPEG_TS) && (sh_video->format==0x10000004)) || + ((demuxer->file_format==DEMUXER_TYPE_MPEG_PS) && (sh_video->format==0x10000004)) + ){ // while(videobuf_len<VIDEOBUFFER_SIZE-MAX_VIDEO_PACKET_SIZE){ int i=sync_video_packet(d_video); + if(!i) return -1; if(!read_video_packet(d_video)) return -1; // EOF if(i==0x1B6) break; } *start=videobuffer; in_size=videobuf_len; videobuf_len=0; - } else if(demuxer->file_format==DEMUXER_TYPE_H264_ES || ((demuxer->file_format==DEMUXER_TYPE_MPEG_TS) && (sh_video->format==0x10000005))){ + } else if(demuxer->file_format==DEMUXER_TYPE_H264_ES || ((demuxer->file_format==DEMUXER_TYPE_MPEG_TS) && (sh_video->format==0x10000005)) || + ((demuxer->file_format==DEMUXER_TYPE_MPEG_PS) && (sh_video->format==0x10000005)) + ){ // while(videobuf_len<VIDEOBUFFER_SIZE-MAX_VIDEO_PACKET_SIZE){ int i=sync_video_packet(d_video); |