changeset 14923:658fc109eefc

added support for other codecs (mpeg4/h264/aac) in mpeg-ps parsing the PSM
author nicodvb
date Sun, 06 Mar 2005 21:10:01 +0000
parents ed06939c5217
children 7f386d84805f
files libmpdemux/demux_mpg.c libmpdemux/video.c
diffstat 2 files changed, 109 insertions(+), 7 deletions(-) [+]
line wrap: on
line diff
--- a/libmpdemux/demux_mpg.c	Sun Mar 06 17:55:31 2005 +0000
+++ b/libmpdemux/demux_mpg.c	Sun Mar 06 21:10:01 2005 +0000
@@ -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 @@
   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 @@
 
   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 @@
     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 @@
     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 @@
           }
           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
--- a/libmpdemux/video.c	Sun Mar 06 17:55:31 2005 +0000
+++ b/libmpdemux/video.c	Sun Mar 06 21:10:01 2005 +0000
@@ -46,7 +46,7 @@
 
 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 @@
   )
     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 @@
     
     *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 @@
 	    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);