[gst-cvs] CVS: gstreamer/plugins/mpeg2/parse mpeg2parse.c,1.37,1.38

Wim Taymans wtay at users.sourceforge.net
Fri Oct 26 12:45:08 PDT 2001


Update of /cvsroot/gstreamer/gstreamer/plugins/mpeg2/parse
In directory usw-pr-cvs1:/tmp/cvs-serv13299/parse

Modified Files:
	mpeg2parse.c 
Log Message:
Added mpeg1 caps to the demuxer and the mpeg decoder as they can handle them
fine.
Added more refined state/error management in the mpeg demuxer.


Index: mpeg2parse.c
===================================================================
RCS file: /cvsroot/gstreamer/gstreamer/plugins/mpeg2/parse/mpeg2parse.c,v
retrieving revision 1.37
retrieving revision 1.38
diff -u -d -r1.37 -r1.38
--- mpeg2parse.c	2001/10/23 19:50:41	1.37
+++ mpeg2parse.c	2001/10/26 19:44:47	1.38
@@ -41,9 +41,16 @@
 enum {
   ARG_0,
   ARG_BIT_RATE,
+  ARG_MPEG2,
   /* FILL ME */
 };
 
+typedef enum {
+  PARSE_STATE_ERROR 	= 0,
+  PARSE_STATE_OK  	= 1,
+  PARSE_STATE_EVENT	= 2,
+} Mpeg2ParseState;
+
 GST_PADTEMPLATE_FACTORY (sink_factory,
   "sink",
   GST_PAD_SINK,
@@ -51,7 +58,7 @@
   GST_CAPS_NEW (
     "mpeg2parse_sink",
     "video/mpeg",
-      "mpegversion",  GST_PROPS_INT (2),
+      "mpegversion",  GST_PROPS_INT_RANGE (1, 2),
       "systemstream", GST_PROPS_BOOLEAN (TRUE)
   )
 );
@@ -67,18 +74,32 @@
   )
 );
 
-GST_PADTEMPLATE_FACTORY (video_factory,
+GST_PADTEMPLATE_FACTORY (video_mpeg1_factory,
   "video_[0-15]",
   GST_PAD_SRC,
   GST_PAD_SOMETIMES,
   GST_CAPS_NEW (
-    "mpeg2parse_video",
+    "mpeg2parse_video_mpeg1",
+    "video/mpeg",
+      //"mpegversion",  GST_PROPS_INT_RANGE (1),
+      "mpegversion",  GST_PROPS_INT (1),
+      "systemstream",  GST_PROPS_BOOLEAN (FALSE)
+  )
+);
+
+GST_PADTEMPLATE_FACTORY (video_mpeg2_factory,
+  "video_[0-15]",
+  GST_PAD_SRC,
+  GST_PAD_SOMETIMES,
+  GST_CAPS_NEW (
+    "mpeg2parse_video_mpeg2",
     "video/mpeg",
       "mpegversion",  GST_PROPS_INT (2),
       "systemstream",  GST_PROPS_BOOLEAN (FALSE)
   )
 );
 
+
 GST_PADTEMPLATE_FACTORY (private1_factory,
   "private_stream_1.[0-7]",
   GST_PAD_SRC,
@@ -155,7 +176,10 @@
 
   g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_BIT_RATE,
     g_param_spec_uint("bit_rate","bit_rate","bit_rate",
-                     0,G_MAXUINT,0,G_PARAM_READABLE)); // CHECKME
+                      0, G_MAXUINT, 0, G_PARAM_READABLE));
+  g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_MPEG2,
+    g_param_spec_boolean ("mpeg2", "mpeg2", "is this an mpeg2 stream",
+                          FALSE, G_PARAM_READABLE));
 
   gobject_class->get_property = gst_mpeg2parse_get_property;
 
@@ -206,7 +230,7 @@
 /* This checks for and parses the pack header.  If at any point something
    looks odd (marker bits not correct), it will return FALSE and not set
    the values in the mpeg2parse structure. */
-static inline gboolean
+static inline Mpeg2ParseState
 parse_packhead (Mpeg2Parse * mpeg2parse)
 {
   gint length = 8;
@@ -216,7 +240,7 @@
 
   buf = gst_bytestream_peek_bytes (mpeg2parse->bs, length);
   if (!buf)
-    return FALSE;
+    return PARSE_STATE_EVENT;
 
   GST_DEBUG (0, "code %02x\n", *buf);
 
@@ -227,7 +251,7 @@
     length += 2;
     buf = gst_bytestream_peek_bytes (mpeg2parse->bs, length);
     if (!buf)
-      return FALSE;
+      return PARSE_STATE_EVENT;
     buf += 3;
   }
   else {
@@ -244,11 +268,11 @@
 	     ((float) (mpeg2parse->bit_rate * 50)) / 1000000);
 
   if (!gst_bytestream_flush (mpeg2parse->bs, length))
-    return FALSE;
+    return PARSE_STATE_EVENT;
 
-  return TRUE;
+  return PARSE_STATE_OK;
 }
-static inline gboolean
+static inline Mpeg2ParseState
 parse_syshead (Mpeg2Parse * mpeg2parse)
 {
   guint16 header_length;
@@ -259,13 +283,13 @@
 
   buf = gst_bytestream_peek_bytes (bs, 2);
   if (!buf)
-    return FALSE;
+    return PARSE_STATE_EVENT;
 
   header_length = GUINT16_FROM_BE (*(guint16 *) buf);
   GST_DEBUG (0, "mpeg2parse: header_length %d\n", header_length);
   buf = gst_bytestream_peek_bytes (bs, 2 + header_length);
   if (!buf)
-    return FALSE;
+    return PARSE_STATE_EVENT;
   buf += 2;
 
   // marker:1==1 ! rate_bound:22 | marker:1==1
@@ -300,14 +324,14 @@
       stream_id = *buf++;
       if (!(stream_id & 0x80)) {
 	GST_DEBUG (0, "mpeg2parse::parse_syshead: error in system header length\n");
-	return FALSE;
+	return PARSE_STATE_ERROR;
       }
 
       // check marker bits
       if ((*buf & 0xC0) != 0xC0) {
 	GST_DEBUG (0,
 		   "mpeg2parse::parse_syshead: expecting placeholder bit values '11' after stream id\n");
-	return FALSE;
+	return PARSE_STATE_ERROR;
       }
 
       STD_buffer_bound_scale = *buf & 0x20;
@@ -345,7 +369,12 @@
 	name = g_strdup_printf ("video_%02d", stream_id & 0x0F);
 	stream_num = stream_id & 0x0F;
 	outpad = &mpeg2parse->video_pad[stream_num];
-	newtemp = GST_PADTEMPLATE_GET (video_factory);
+        if (!mpeg2parse->MPEG2) {
+          newtemp = GST_PADTEMPLATE_GET (video_mpeg1_factory);
+	}
+	else {
+	  newtemp = GST_PADTEMPLATE_GET (video_mpeg2_factory);
+	}
       }
 
       GST_DEBUG (0, "mpeg2parse::parse_syshead: stream ID 0x%02X (%s)\n", stream_id, name);
@@ -357,7 +386,7 @@
       // this should trigger the NEW_PAD signal, which should be caught by
       // the app and used to attach to desired streams.
       if (outpad && *outpad == NULL) {
-	(*outpad) = gst_pad_new_from_template (newtemp, name);
+	*outpad = gst_pad_new_from_template (newtemp, name);
 	gst_pad_set_caps (*outpad, gst_pad_get_padtemplate_caps (*outpad));
 	gst_element_add_pad (GST_ELEMENT (mpeg2parse), (*outpad));
       }
@@ -379,12 +408,12 @@
 
   // return total number of bytes used in this chunk
   if (!gst_bytestream_flush (bs, 2 + header_length))
-    return FALSE;
+    return PARSE_STATE_EVENT;
 
-  return TRUE;
+  return PARSE_STATE_OK;
 }
 
-static gboolean
+static Mpeg2ParseState
 parse_packet (Mpeg2Parse *mpeg2parse)
 {
   guint8 id = mpeg2parse->id;
@@ -408,7 +437,7 @@
 
   buf = gst_bytestream_peek_bytes (bs, 2);
   if (!buf)
-    return FALSE;
+    return PARSE_STATE_EVENT;
 
   // start parsing
   packet_length = GUINT16_FROM_BE (*((guint16 *)buf));
@@ -416,7 +445,7 @@
   GST_DEBUG (0,"mpeg2parse: got packet_length %d\n",packet_length);
   basebuf = buf = gst_bytestream_peek_bytes (bs, 2 + packet_length);
   if (!buf)
-    return FALSE;
+    return PARSE_STATE_EVENT;
   buf += 2;
   headerlen = 2;
 
@@ -547,29 +576,30 @@
     // if this is part of the buffer, create a subbuffer
     GST_DEBUG (0,"mpeg2parse::parse_packet: creating subbuffer len %d\n", datalen);
     if (!gst_bytestream_flush (bs, headerlen))
-      return FALSE;
+      return PARSE_STATE_EVENT;
 
     outbuf = gst_bytestream_read (bs, datalen);
     if (!outbuf)
-      return FALSE;
+      return PARSE_STATE_EVENT;
 
     GST_DEBUG (0,"mpeg2parse::parse_packet: pushing buffer of len %d id %d\n", datalen, id);
     GST_BUFFER_OFFSET(outbuf) = outoffset;
     GST_BUFFER_TIMESTAMP(outbuf) = (mpeg2parse->last_pts*1000000LL)/90000LL;
     gst_pad_push((*outpad),outbuf);
 
-    return TRUE;
+    return PARSE_STATE_OK;
   }
-  else
-    return gst_bytestream_flush (bs, 2 + packet_length);
+  else {
+    return (gst_bytestream_flush (bs, 2 + packet_length) ? PARSE_STATE_OK : PARSE_STATE_EVENT);
+  }
 
 error:
   gst_bytestream_flush (bs, 2 + packet_length);
 
-  return FALSE;
+  return PARSE_STATE_ERROR;
 }
 
-static inline gboolean
+static inline Mpeg2ParseState
 parse_pes (Mpeg2Parse *mpeg2parse)
 {
   guint8 id;
@@ -592,7 +622,7 @@
 
   buf = gst_bytestream_peek_bytes (bs, 2);
   if (!buf)
-    return FALSE;
+    return PARSE_STATE_EVENT;
 
   // start parsing
   packet_length = GUINT16_FROM_BE (*((guint16 *)buf));
@@ -600,7 +630,7 @@
   GST_DEBUG (0,"mpeg2parse: got packet_length %d\n",packet_length);
   basebuf = buf = gst_bytestream_peek_bytes (bs, 2 + packet_length);
   if (!buf)
-    return FALSE;
+    return PARSE_STATE_EVENT;
   buf += 2;
 
   // we don't operate on: program_stream_map, padding_stream,
@@ -613,7 +643,7 @@
     guchar flags2 = *buf++;
 
     if ((flags1 & 0xC0) != 0x80) {
-      return FALSE;
+      return PARSE_STATE_ERROR;
     }
 
     header_data_length = *buf++;
@@ -704,7 +734,7 @@
 
   // if we don't know what it is, bail
   if (outpad == NULL)
-    return gst_bytestream_flush (bs, 2 + packet_length);
+    return (gst_bytestream_flush (bs, 2 + packet_length) ? PARSE_STATE_OK : PARSE_STATE_EVENT);
 
   // create the pad and add it if we don't already have one.
   // this should trigger the NEW_PAD signal, which should be caught by
@@ -736,7 +766,7 @@
     }
     else if ((id >= 0xE0) && (id <= 0xEF)) {
       name = g_strdup_printf("video_%d",id - 0xE0);
-      newtemp = GST_PADTEMPLATE_GET (video_factory);
+      newtemp = GST_PADTEMPLATE_GET (video_mpeg2_factory);
     }
     else {
       name = g_strdup_printf("unknown");
@@ -760,11 +790,11 @@
     // if this is part of the buffer, create a subbuffer
     GST_DEBUG (0,"mpeg2parse: creating subbuffer len %d\n", datalen);
     if (!gst_bytestream_flush (bs, headerlen))
-      return FALSE;
+      return PARSE_STATE_EVENT;
 
     outbuf = gst_bytestream_read (bs, datalen);
     if (!outbuf)
-      return FALSE;
+      return PARSE_STATE_EVENT;
 
     GST_BUFFER_OFFSET(outbuf) = outoffset;
     GST_BUFFER_TIMESTAMP(outbuf) = (mpeg2parse->last_pts*1000000LL)/90000LL;
@@ -773,11 +803,11 @@
   }
   else {
     if (!gst_bytestream_flush (bs, 2 + packet_length))
-      return FALSE;
+      return PARSE_STATE_EVENT;
   }
 
   // return total number of bytes
-  return TRUE;
+  return PARSE_STATE_OK;
 }
 
 // FIXME mmx-ify me
@@ -888,65 +918,56 @@
     else {
       GST_DEBUG (0, "mpeg2parse: have chunk 0x%02X\n",mpeg2parse->id);
       switch (mpeg2parse->id) {
-      case 0xBA:
-	if (!parse_packhead (mpeg2parse))
-	  got_event = TRUE;
-	break;
-	
-      case 0xBB:
-	if (!parse_syshead (mpeg2parse))
-	  got_event = TRUE;
-	break;
-	
-      default:
-	if (mpeg2parse->MPEG2 && ((mpeg2parse->id < 0xBD) || (mpeg2parse->id > 0xFE))) {
-	  g_warning ("mpeg2parse: ******** unknown id 0x%02X",mpeg2parse->id);
-	}
-	else {
-	  if (mpeg2parse->MPEG2) 
-	    {
-	      if (!parse_pes (mpeg2parse))
+        case 0xBA:
+	  if (parse_packhead (mpeg2parse) == PARSE_STATE_EVENT)
+	    got_event = TRUE;
+	  break;
+        case 0xBB:
+	  if (parse_syshead (mpeg2parse) == PARSE_STATE_EVENT)
+	    got_event = TRUE;
+	  break;
+        default:
+	  if (mpeg2parse->MPEG2 && ((mpeg2parse->id < 0xBD) || (mpeg2parse->id > 0xFE))) {
+	    g_warning ("mpeg2parse: ******** unknown id 0x%02X",mpeg2parse->id);
+	  }
+	  else {
+	    if (mpeg2parse->MPEG2) {
+	      if (parse_pes (mpeg2parse) == PARSE_STATE_EVENT)
 		got_event = TRUE;
 	    }
-	  else
-	    {
-	      if (!parse_packet (mpeg2parse))
+	    else {
+	      if (parse_packet (mpeg2parse) == PARSE_STATE_EVENT)
 		got_event = TRUE;
 	    }
-	}
+	  }
       }
     }
 
-    if (got_event)
-      {
-	guint32 remaining;
-	GstEvent *event;
-	gint etype;
-
-	gst_bytestream_get_status (mpeg2parse->bs, &remaining, &event);
-	etype = event? GST_EVENT_TYPE (event) : GST_EVENT_EOS;
+    if (got_event) {
+      guint32 remaining;
+      GstEvent *event;
+      gint etype;
 
-	switch (etype) {
+      gst_bytestream_get_status (mpeg2parse->bs, &remaining, &event);
+      etype = event? GST_EVENT_TYPE (event) : GST_EVENT_EOS;
 
+      switch (etype) {
 	case GST_EVENT_DISCONTINUOUS:
 	  gst_bytestream_flush_fast (mpeg2parse->bs, remaining);
 	  _forall_pads (mpeg2parse, (GFunc) _queue_discontinuous, NULL);
 	  break;
-
 	case GST_EVENT_EOS:
 	  gst_element_set_state (GST_ELEMENT (mpeg2parse), GST_STATE_PAUSED);
 	  _forall_pads (mpeg2parse, (GFunc) _queue_eos, NULL);
 	  break;
-
 	default:
 	  g_warning ("Don't know how to cope with event type %d",
 		     GST_EVENT_TYPE (event));
 	  break;
-	}
-
-	gst_event_free (event);
       }
 
+      gst_event_free (event);
+    }
   } while (!GST_ELEMENT_IS_COTHREAD_STOPPING(element));
 }
 
@@ -956,18 +977,18 @@
   Mpeg2Parse *mpeg2parse;
 
   /* it's not null if we got it, but it might not be ours */
-
   mpeg2parse = GST_MPEG2PARSE(object);
 
   switch (prop_id) {
-    case ARG_BIT_RATE: {
-      g_value_set_uint (value, mpeg2parse->bit_rate*316); // hu?
+    case ARG_BIT_RATE: 
+      g_value_set_uint (value, mpeg2parse->bit_rate * 316); // hu?
       break;
-    }
-    default: {
+    case ARG_MPEG2:
+      g_value_set_boolean (value, mpeg2parse->MPEG2);
+      break;
+    default: 
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
-    }
   }
 }
 
@@ -990,7 +1011,8 @@
 
   gst_elementfactory_add_padtemplate (factory, GST_PADTEMPLATE_GET (sink_factory));
   gst_elementfactory_add_padtemplate (factory, GST_PADTEMPLATE_GET (audio_factory));
-  gst_elementfactory_add_padtemplate (factory, GST_PADTEMPLATE_GET (video_factory));
+  gst_elementfactory_add_padtemplate (factory, GST_PADTEMPLATE_GET (video_mpeg1_factory));
+  gst_elementfactory_add_padtemplate (factory, GST_PADTEMPLATE_GET (video_mpeg2_factory));
   gst_elementfactory_add_padtemplate (factory, GST_PADTEMPLATE_GET (private1_factory));
   gst_elementfactory_add_padtemplate (factory, GST_PADTEMPLATE_GET (private2_factory));
   gst_elementfactory_add_padtemplate (factory, GST_PADTEMPLATE_GET (subtitle_factory));





More information about the Gstreamer-commits mailing list