events: Implement the stream-group-done event
authorJan Schmidt <jan@centricular.com>
Mon, 14 Mar 2016 03:20:42 +0000 (14:20 +1100)
committerJan Schmidt <jan@centricular.com>
Mon, 25 Jul 2016 10:22:20 +0000 (20:22 +1000)
A new event which precedes EOS in situations where we
need downstream to unblock any pads waiting on a stream
before we can send EOS. E.g, decodebin draining a chain
so it can switch pads.

https://bugzilla.gnome.org/show_bug.cgi?id=768995

docs/gst/gstreamer-sections.txt
gst/gstevent.c
gst/gstevent.h
gst/gstpad.c
gst/gstquark.c
gst/gstquark.h
tests/check/gst/gstevent.c
win32/common/libgstreamer.def

index f8f8a0f..13bba4a 100644 (file)
@@ -1183,6 +1183,9 @@ gst_event_parse_select_streams
 
 gst_event_new_stream_collection
 gst_event_parse_stream_collection
+
+gst_event_new_stream_group_done
+gst_event_parse_stream_group_done
 <SUBSECTION Standard>
 GstEventClass
 GST_EVENT
index 71e1884..e691dfb 100644 (file)
@@ -130,6 +130,7 @@ static GstEventQuarks event_quarks[] = {
   {GST_EVENT_CUSTOM_DOWNSTREAM_STICKY, "custom-downstream-sticky", 0},
   {GST_EVENT_CUSTOM_BOTH, "custom-both", 0},
   {GST_EVENT_CUSTOM_BOTH_OOB, "custom-both-oob", 0},
+  {GST_EVENT_STREAM_GROUP_DONE, "stream-group-done", 0},
 
   {0, NULL, 0}
 };
@@ -653,6 +654,57 @@ gst_event_parse_select_streams (GstEvent * event, GList ** streams)
 
 
 /**
+ * gst_event_new_stream_group_done:
+ * @group_id: the group id of the stream group which is ending
+ *
+ * Create a new Stream Group Done event. The stream-group-done event can
+ * only travel downstream synchronized with the buffer flow. Elements
+ * that receive the event on a pad should handle it mostly like EOS,
+ * and emit any data or pending buffers that would depend on more data
+ * arriving and unblock, since there won't be any more data.
+ *
+ * This event is followed by EOS at some point in the future, and is
+ * generally used when switching pads - to unblock downstream so that
+ * new pads can be exposed before sending EOS on the existing pads.
+ *
+ * Returns: (transfer full): the new stream-group-done event.
+ *
+ * Since: 1.10
+ */
+GstEvent *
+gst_event_new_stream_group_done (guint group_id)
+{
+  GstStructure *s;
+
+  s = gst_structure_new_id (GST_QUARK (EVENT_STREAM_GROUP_DONE),
+      GST_QUARK (GROUP_ID), G_TYPE_UINT, group_id, NULL);
+
+  return gst_event_new_custom (GST_EVENT_STREAM_GROUP_DONE, s);
+}
+
+/**
+ * gst_event_parse_stream_group_done:
+ * @event: a stream-group-done event.
+ * @group_id: (out): address of variable to store the group id into
+ *
+ * Parse a stream-group-done @event and store the result in the given
+ * @group_id location.
+ *
+ * Since: 1.10
+ */
+void
+gst_event_parse_stream_group_done (GstEvent * event, guint * group_id)
+{
+  g_return_if_fail (event != NULL);
+  g_return_if_fail (GST_EVENT_TYPE (event) == GST_EVENT_STREAM_GROUP_DONE);
+
+  if (group_id) {
+    gst_structure_id_get (GST_EVENT_STRUCTURE (event),
+        GST_QUARK (GROUP_ID), G_TYPE_UINT, group_id, NULL);
+  }
+}
+
+/**
  * gst_event_new_eos:
  *
  * Create a new EOS event. The eos event can only travel downstream
index faf0014..e7dbb25 100644 (file)
@@ -95,6 +95,9 @@ typedef enum {
  * @GST_EVENT_SINK_MESSAGE: An event that sinks turn into a message. Used to
  *                          send messages that should be emitted in sync with
  *                          rendering.
+ * @GST_EVENT_STREAM_GROUP_DONE: Indicates that there is no more data for
+ *                 the stream group ID in the message. Sent before EOS
+ *                 in some instances and should be handled mostly the same. (Since 1.10)
  * @GST_EVENT_EOS: End-Of-Stream. No more data is to be expected to follow
  *                 without either a STREAM_START event, or a FLUSH_STOP and a SEGMENT
  *                 event.
@@ -151,6 +154,7 @@ typedef enum {
   GST_EVENT_TAG                   = GST_EVENT_MAKE_TYPE (80, FLAG(DOWNSTREAM) | FLAG(SERIALIZED) | FLAG(STICKY) | FLAG(STICKY_MULTI)),
   GST_EVENT_BUFFERSIZE            = GST_EVENT_MAKE_TYPE (90, FLAG(DOWNSTREAM) | FLAG(SERIALIZED) | FLAG(STICKY)),
   GST_EVENT_SINK_MESSAGE          = GST_EVENT_MAKE_TYPE (100, FLAG(DOWNSTREAM) | FLAG(SERIALIZED) | FLAG(STICKY) | FLAG(STICKY_MULTI)),
+  GST_EVENT_STREAM_GROUP_DONE     = GST_EVENT_MAKE_TYPE (105, FLAG(DOWNSTREAM) | FLAG(SERIALIZED) | FLAG(STICKY)),
   GST_EVENT_EOS                   = GST_EVENT_MAKE_TYPE (110, FLAG(DOWNSTREAM) | FLAG(SERIALIZED) | FLAG(STICKY)),
   GST_EVENT_TOC                   = GST_EVENT_MAKE_TYPE (120, FLAG(DOWNSTREAM) | FLAG(SERIALIZED) | FLAG(STICKY) | FLAG(STICKY_MULTI)),
   GST_EVENT_PROTECTION            = GST_EVENT_MAKE_TYPE (130, FLAG (DOWNSTREAM) | FLAG (SERIALIZED) | FLAG (STICKY) | FLAG (STICKY_MULTI)),
@@ -496,6 +500,10 @@ void            gst_event_parse_stream_collection (GstEvent *event, GstStreamCol
 GstEvent *      gst_event_new_select_streams    (GList *streams);
 void            gst_event_parse_select_streams  (GstEvent *event, GList **streams);
 
+/* stream-group-done event */
+GstEvent *      gst_event_new_stream_group_done (const guint group_id) G_GNUC_MALLOC;
+void            gst_event_parse_stream_group_done (GstEvent *event, guint *group_id);
+
 /* EOS event */
 GstEvent *      gst_event_new_eos               (void) G_GNUC_MALLOC;
 
index 3f5afd6..cd9fff1 100644 (file)
@@ -5035,8 +5035,9 @@ store_sticky_event (GstPad * pad, GstEvent * event)
   /* Unset the EOS flag when received STREAM_START event, so pad can
    * store sticky event and then push it later */
   if (type == GST_EVENT_STREAM_START) {
-    GST_LOG_OBJECT (pad, "Removing pending EOS events");
+    GST_LOG_OBJECT (pad, "Removing pending EOS and StreamGroupDone events");
     remove_event_by_type (pad, GST_EVENT_EOS);
+    remove_event_by_type (pad, GST_EVENT_STREAM_GROUP_DONE);
     GST_OBJECT_FLAG_UNSET (pad, GST_PAD_FLAG_EOS);
   }
 
@@ -5202,6 +5203,7 @@ gst_pad_push_event_unchecked (GstPad * pad, GstEvent * event,
       /* Remove sticky EOS events */
       GST_LOG_OBJECT (pad, "Removing pending EOS events");
       remove_event_by_type (pad, GST_EVENT_EOS);
+      remove_event_by_type (pad, GST_EVENT_STREAM_GROUP_DONE);
       remove_event_by_type (pad, GST_EVENT_SEGMENT);
       GST_OBJECT_FLAG_UNSET (pad, GST_PAD_FLAG_EOS);
       pad->ABI.abi.last_flowret = GST_FLOW_OK;
@@ -5526,6 +5528,7 @@ gst_pad_send_event_unchecked (GstPad * pad, GstEvent * event,
       /* Remove pending EOS events */
       GST_LOG_OBJECT (pad, "Removing pending EOS and SEGMENT events");
       remove_event_by_type (pad, GST_EVENT_EOS);
+      remove_event_by_type (pad, GST_EVENT_STREAM_GROUP_DONE);
       remove_event_by_type (pad, GST_EVENT_SEGMENT);
       GST_OBJECT_FLAG_UNSET (pad, GST_PAD_FLAG_EOS);
       pad->ABI.abi.last_flowret = GST_FLOW_OK;
@@ -5553,6 +5556,7 @@ gst_pad_send_event_unchecked (GstPad * pad, GstEvent * event,
           /* Remove sticky EOS events */
           GST_LOG_OBJECT (pad, "Removing pending EOS events");
           remove_event_by_type (pad, GST_EVENT_EOS);
+          remove_event_by_type (pad, GST_EVENT_STREAM_GROUP_DONE);
           GST_OBJECT_FLAG_UNSET (pad, GST_PAD_FLAG_EOS);
           break;
         default:
index c2a204d..4500cc6 100644 (file)
@@ -74,7 +74,8 @@ static const gchar *_quark_strings[] = {
   "property-value", "streams", "GstEventSelectStreams",
   "GstMessageStreamCollection", "collection", "stream", "stream-collection",
   "GstMessageStreamsSelected", "GstMessageRedirect", "redirect-entry-locations",
-  "redirect-entry-taglists", "redirect-entry-structures"
+  "redirect-entry-taglists", "redirect-entry-structures",
+  "GstEventStreamGroupDone"
 };
 
 GQuark _priv_gst_quark_table[GST_QUARK_MAX];
index fda5deb..e41466b 100644 (file)
@@ -216,7 +216,8 @@ typedef enum _GstQuarkId
   GST_QUARK_REDIRECT_ENTRY_LOCATIONS = 185,
   GST_QUARK_REDIRECT_ENTRY_TAGLISTS = 186,
   GST_QUARK_REDIRECT_ENTRY_STRUCTURES = 187,
-  GST_QUARK_MAX = 188
+  GST_QUARK_EVENT_STREAM_GROUP_DONE = 188,
+  GST_QUARK_MAX = 189
 } GstQuarkId;
 
 extern GQuark _priv_gst_quark_table[GST_QUARK_MAX];
index ebb836c..5e93b5d 100644 (file)
@@ -52,6 +52,7 @@ GST_START_TEST (create_events)
     fail_unless (reset_time == TRUE);
     gst_event_unref (event);
   }
+
   /* SELECT_STREAMS */
   {
     GList *streams = NULL;
@@ -77,6 +78,22 @@ GST_START_TEST (create_events)
     g_list_free (streams);
     g_list_free_full (res, g_free);
   }
+
+  /* STREAM_GROUP_DONE */
+  {
+    guint group_id = 0;
+
+    event = gst_event_new_stream_group_done (0x42);
+    fail_if (event == NULL);
+    fail_unless (GST_EVENT_TYPE (event) == GST_EVENT_STREAM_GROUP_DONE);
+    fail_if (GST_EVENT_IS_UPSTREAM (event));
+    fail_unless (GST_EVENT_IS_DOWNSTREAM (event));
+    fail_unless (GST_EVENT_IS_SERIALIZED (event));
+    gst_event_parse_stream_group_done (event, &group_id);
+    fail_unless (group_id == 0x42);
+    gst_event_unref (event);
+  }
+
   /* EOS */
   {
     event = gst_event_new_eos ();
index ef9e8da..279451e 100644 (file)
@@ -594,6 +594,7 @@ EXPORTS
        gst_event_new_sink_message
        gst_event_new_step
        gst_event_new_stream_collection
+       gst_event_new_stream_group_done
        gst_event_new_stream_start
        gst_event_new_tag
        gst_event_new_toc
@@ -615,6 +616,7 @@ EXPORTS
        gst_event_parse_stream
        gst_event_parse_stream_collection
        gst_event_parse_stream_flags
+       gst_event_parse_stream_group_done
        gst_event_parse_stream_start
        gst_event_parse_tag
        gst_event_parse_toc