[gst-devel] event handling for mpeg2 plugins

vishnu at pobox.com vishnu at pobox.com
Mon Oct 22 15:36:02 CEST 2001


The attached patch allows me to seek around an mpeg2 program stream.  It
seems to work pretty well.

-- 
Victory to the Divine Mother!!   ... after all,
  http://sahajayoga.org                http://why-compete.org
-------------- next part --------------
? stamp-h1
Index: gst/gstpad.c
===================================================================
RCS file: /cvsroot/gstreamer/gstreamer/gst/gstpad.c,v
retrieving revision 1.118
diff -u -p -r1.118 gstpad.c
--- gst/gstpad.c	2001/10/21 18:00:31	1.118
+++ gst/gstpad.c	2001/10/22 22:32:50
@@ -1982,13 +1982,15 @@ gst_pad_event_default(GstPad *pad, GstEv
  *
  * Send the event to the pad.
  *
- * Returns: TRUe if the event was handled.
+ * Returns: TRUE if the event was handled.
  */
 gboolean
 gst_pad_send_event (GstPad *pad, GstEvent *event)
 {
   gboolean handled = FALSE;
 
+  g_return_val_if_fail (event, FALSE);
+
   GST_DEBUG (GST_CAT_EVENT, "have event %d on pad %s:%s\n",
 		  GST_EVENT_TYPE (event), GST_DEBUG_PAD_NAME (pad));
 
@@ -2002,5 +2004,7 @@ gst_pad_send_event (GstPad *pad, GstEven
     GST_DEBUG(GST_CAT_EVENT, "would proceed with default behavior here\n");
     //gst_pad_event_default (pad, event);
   }
+
+  return handled;
 }
 
Index: libs/bytestream/gstbytestream.c
===================================================================
RCS file: /cvsroot/gstreamer/gstreamer/libs/bytestream/gstbytestream.c,v
retrieving revision 1.4
diff -u -p -r1.4 gstbytestream.c
--- libs/bytestream/gstbytestream.c	2001/10/22 19:00:52	1.4
+++ libs/bytestream/gstbytestream.c	2001/10/22 22:32:51
@@ -407,6 +407,21 @@ gst_bytestream_read (GstByteStream * bs,
   return buf;
 }
 
+
+/**
+ * gst_bytestream_get_status
+ * @bs: a bytestream
+ * @avail_out: total number of bytes buffered
+ * @event_out: an event
+ *
+ * When an event occurs, the bytestream will return NULL.  You must
+ * retrieve the event using this API before reading more bytes from
+ * the stream.
+ *
+ * It is possible for the bytestream to return NULL due to running
+ * out of buffers, however, this indicates a bug because an EOS
+ * event should have been sent.
+ */
 void
 gst_bytestream_get_status (GstByteStream *bs,
 			   guint32 *avail_out,
Index: plugins/a52dec/gsta52dec.c
===================================================================
RCS file: /cvsroot/gstreamer/gstreamer/plugins/a52dec/gsta52dec.c,v
retrieving revision 1.8
diff -u -p -r1.8 gsta52dec.c
--- plugins/a52dec/gsta52dec.c	2001/10/17 10:21:25	1.8
+++ plugins/a52dec/gsta52dec.c	2001/10/22 22:32:51
@@ -356,6 +356,7 @@ gst_a52dec_loop (GstElement *element)
   int stream_channels;
   a52_state_t *state;
   GstBuffer *buf;
+  gboolean got_event = FALSE;
 
   g_return_if_fail (element != NULL);
   g_return_if_fail (GST_IS_A52DEC (element));
@@ -370,17 +371,50 @@ gst_a52dec_loop (GstElement *element)
   state = g_new(a52_state_t, 1);
 
   do {
+    if (got_event)
+      {
+	guint32 remaining;
+	GstEvent *event;
+
+	got_event = FALSE;
+	gst_bytestream_get_status (a52dec->bs, &remaining, &event);
+	
+	switch (GST_EVENT_TYPE (event)) {
+	case GST_EVENT_DISCONTINUOUS:
+	  gst_bytestream_flush_fast (a52dec->bs, remaining);
+	  break;
+	
+	case GST_EVENT_EOS:
+	  gst_element_set_state (GST_ELEMENT (a52dec), GST_STATE_PAUSED);
+	  break;
+
+	default:
+	  g_warning ("Don't know how to cope with event type %d",
+		     GST_EVENT_TYPE (event));
+	  break;
+	}
+
+	gst_event_free (event);
+      }
+
     // find and read header
-    do {
+    while (1) {
       data = gst_bytestream_peek_bytes(a52dec->bs, 7);
       if (!data)
-	continue;
+	{
+	  got_event = TRUE;
+	  break;
+	}
       length = a52_syncinfo(data, &flags, &sample_rate, &bit_rate);
       if (length == 0) {
         // slide window to next 7 bytes
-        gst_bytestream_flush(a52dec->bs, 1);
+        gst_bytestream_flush_fast (a52dec->bs, 1);
       }
-    } while (length == 0);
+      else
+	break;
+    }
+    if (got_event)
+      continue;
 
     //fprintf(stderr, "sync sr:%d->%d br:%d->%d f:%d->%d\n", a52dec->sample_rate, sample_rate, a52dec->bit_rate, bit_rate, a52dec->flags, flags);
     // check if params have changed since last call
@@ -404,7 +438,10 @@ gst_a52dec_loop (GstElement *element)
     // read the header + rest of frame
     buf = gst_bytestream_read(a52dec->bs, length);
     if (!buf)
-      continue;
+      {
+	got_event = TRUE;
+	continue;
+      }
     data = GST_BUFFER_DATA(buf);
 
     // process
Index: plugins/mpeg2/mpeg2dec/gstmpeg2dec.c
===================================================================
RCS file: /cvsroot/gstreamer/gstreamer/plugins/mpeg2/mpeg2dec/gstmpeg2dec.c,v
retrieving revision 1.24
diff -u -p -r1.24 gstmpeg2dec.c
--- plugins/mpeg2/mpeg2dec/gstmpeg2dec.c	2001/10/17 10:21:25	1.24
+++ plugins/mpeg2/mpeg2dec/gstmpeg2dec.c	2001/10/22 22:32:51
@@ -396,6 +396,11 @@ gst_mpeg2dec_loop (GstElement *element)
 	restart = 1;
 	break;
 	
+      case GST_EVENT_EOS:
+	gst_element_set_state (GST_ELEMENT (mpeg2dec), GST_STATE_PAUSED);
+	restart = 1;   // we should get stuck in gst_pad_pull
+	break;
+
       default:
 	g_warning ("Ignoring unknown event %d", ev->type);
 	break;
Index: plugins/mpeg2/parse/mpeg2parse.c
===================================================================
RCS file: /cvsroot/gstreamer/gstreamer/plugins/mpeg2/parse/mpeg2parse.c,v
retrieving revision 1.36
diff -u -p -r1.36 mpeg2parse.c
--- plugins/mpeg2/parse/mpeg2parse.c	2001/10/17 10:21:25	1.36
+++ plugins/mpeg2/parse/mpeg2parse.c	2001/10/22 22:32:51
@@ -826,6 +826,13 @@ _queue_discontinuous (GstPad *pad, gpoin
 }
 
 static void
+_queue_eos (GstPad *pad, gpointer ign)
+{
+  // ugh, GstBuffer cast is wrong here
+  gst_pad_push (pad, (GstBuffer*) gst_event_new (GST_EVENT_EOS));
+}
+
+static void
 _forall_pads (Mpeg2Parse *mpeg2parse, GFunc fun, gpointer user_data)
 {
   GstPad *pad;
@@ -874,21 +881,21 @@ gst_mpeg2parse_loop (GstElement *element
   }
 
   do {
-    gboolean discont = FALSE;
+    gboolean got_event = FALSE;
 
     if (!find_start_code (mpeg2parse))
-      discont = TRUE;
+      got_event = TRUE;
     else {
       GST_DEBUG (0, "mpeg2parse: have chunk 0x%02X\n",mpeg2parse->id);
       switch (mpeg2parse->id) {
       case 0xBA:
 	if (!parse_packhead (mpeg2parse))
-	  discont = TRUE;
+	  got_event = TRUE;
 	break;
 	
       case 0xBB:
 	if (!parse_syshead (mpeg2parse))
-	  discont = TRUE;
+	  got_event = TRUE;
 	break;
 	
       default:
@@ -899,22 +906,48 @@ gst_mpeg2parse_loop (GstElement *element
 	  if (mpeg2parse->MPEG2) 
 	    {
 	      if (!parse_pes (mpeg2parse))
-		discont = TRUE;
+		got_event = TRUE;
 	    }
 	  else
 	    {
 	      if (!parse_packet (mpeg2parse))
-		discont = TRUE;
+		got_event = TRUE;
 	    }
 	}
       }
     }
 
-    if (discont)
-      _forall_pads (mpeg2parse, (GFunc) _queue_discontinuous, NULL);
+    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;
+
+	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;
+	}
 
-  } while (!GST_ELEMENT_IS_COTHREAD_STOPPING(element));
+	gst_event_free (event);
+      }
 
+  } while (!GST_ELEMENT_IS_COTHREAD_STOPPING(element));
 }
 
 static void


More information about the gstreamer-devel mailing list