pad: Implement GstPadEventFullFunction
authorEdward Hervey <bilboed@bilboed.com>
Thu, 12 Nov 2015 16:15:37 +0000 (17:15 +0100)
committerEdward Hervey <bilboed@bilboed.com>
Wed, 2 Dec 2015 15:04:03 +0000 (16:04 +0100)
API: GstPadEventFullFunction

Returns a GstFlowReturn, allows asynchronous elements to properly
propagate flow returns

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

gst/gstpad.c
gst/gstpad.h
plugins/elements/gstmultiqueue.c
plugins/elements/gstqueue.c
win32/common/libgstreamer.def

index 34dafe5..aed3af7 100644 (file)
@@ -1826,6 +1826,51 @@ gst_pad_set_event_function_full (GstPad * pad, GstPadEventFunction event,
       GST_DEBUG_FUNCPTR_NAME (event));
 }
 
+static gboolean
+event_wrap (GstPad * pad, GstObject * object, GstEvent * event)
+{
+  GstFlowReturn ret;
+
+  ret = GST_PAD_EVENTFULLFUNC (pad) (pad, object, event);
+  if (ret == GST_FLOW_OK)
+    return TRUE;
+  return FALSE;
+}
+
+/**
+ * gst_pad_set_event_full_function:
+ * @p: a #GstPad of either direction.
+ * @f: the #GstPadEventFullFunction to set.
+ *
+ * Calls gst_pad_set_event_full_function_full() with %NULL for the user_data and
+ * notify.
+ */
+/**
+ * gst_pad_set_event_full_function_full:
+ * @pad: a #GstPad of either direction.
+ * @event: the #GstPadEventFullFunction to set.
+ * @user_data: user_data passed to @notify
+ * @notify: notify called when @event will not be used anymore.
+ *
+ * Sets the given event handler for the pad.
+ */
+void
+gst_pad_set_event_full_function_full (GstPad * pad,
+    GstPadEventFullFunction event, gpointer user_data, GDestroyNotify notify)
+{
+  g_return_if_fail (GST_IS_PAD (pad));
+
+  if (pad->eventnotify)
+    pad->eventnotify (pad->eventdata);
+  GST_PAD_EVENTFULLFUNC (pad) = event;
+  GST_PAD_EVENTFUNC (pad) = event_wrap;
+  pad->eventdata = user_data;
+  pad->eventnotify = notify;
+
+  GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad, "eventfullfunc for set to %s",
+      GST_DEBUG_FUNCPTR_NAME (event));
+}
+
 /**
  * gst_pad_set_query_function:
  * @p: a #GstPad of either direction.
@@ -5389,6 +5434,7 @@ gst_pad_send_event_unchecked (GstPad * pad, GstEvent * event,
   GstEventType event_type;
   gboolean serialized, need_unlock = FALSE, sticky;
   GstPadEventFunction eventfunc;
+  GstPadEventFullFunction eventfullfunc = NULL;
   GstObject *parent;
 
   GST_OBJECT_LOCK (pad);
@@ -5486,7 +5532,9 @@ gst_pad_send_event_unchecked (GstPad * pad, GstEvent * event,
 
   PROBE_PUSH (pad, type | GST_PAD_PROBE_TYPE_PUSH, event, probe_stopped);
 
-  if (G_UNLIKELY ((eventfunc = GST_PAD_EVENTFUNC (pad)) == NULL))
+  eventfullfunc = GST_PAD_EVENTFULLFUNC (pad);
+  eventfunc = GST_PAD_EVENTFUNC (pad);
+  if (G_UNLIKELY (eventfunc == NULL && eventfullfunc == NULL))
     goto no_function;
 
   ACQUIRE_PARENT (pad, parent, no_parent);
@@ -5499,7 +5547,9 @@ gst_pad_send_event_unchecked (GstPad * pad, GstEvent * event,
   if (sticky)
     gst_event_ref (event);
 
-  if (eventfunc (pad, parent, event)) {
+  if (eventfullfunc) {
+    ret = eventfullfunc (pad, parent, event);
+  } else if (eventfunc (pad, parent, event)) {
     ret = GST_FLOW_OK;
   } else {
     /* something went wrong */
index 5f93112..539dcfb 100644 (file)
@@ -362,6 +362,26 @@ typedef GstFlowReturn              (*GstPadGetRangeFunction)       (GstPad *pad, GstObject *parent
 typedef gboolean               (*GstPadEventFunction)          (GstPad *pad, GstObject *parent,
                                                                  GstEvent *event);
 
+/**
+ * GstPadEventFullFunction:
+ * @pad: the #GstPad to handle the event.
+ * @parent: (allow-none): the parent of @pad. If the #GST_PAD_FLAG_NEED_PARENT
+ *          flag is set, @parent is guaranteed to be not-%NULL and remain valid
+ *          during the execution of this function.
+ * @event: (transfer full): the #GstEvent to handle.
+ *
+ * Function signature to handle an event for the pad.
+ *
+ * This variant is for specific elements that will take into account the
+ * last downstream flow return (from a pad push), in which case they can
+ * return it.
+ *
+ * Returns: %GST_FLOW_OK if the event was handled properly, or any other
+ * #GstFlowReturn dependent on downstream state.
+ */
+typedef GstFlowReturn          (*GstPadEventFullFunction)      (GstPad *pad, GstObject *parent,
+                                                                 GstEvent *event);
+
 
 /* internal links */
 /**
@@ -756,6 +776,7 @@ struct _GstPad {
     gpointer _gst_reserved[GST_PADDING];
     struct {
       GstFlowReturn last_flowret;
+      GstPadEventFullFunction eventfullfunc;
     } abi;
   } ABI;
 };
@@ -881,6 +902,17 @@ struct _GstPadClass {
  */
 #define GST_PAD_EVENTFUNC(pad)         (GST_PAD_CAST(pad)->eventfunc)
 /**
+ * GST_PAD_EVENTFULLFUNC:
+ * @pad: a #GstPad
+ *
+ * Get the #GstPadEventFullFunction from the given @pad, which
+ * is the function that handles events on the pad. You can
+ * use this to set your own event handling function on a pad
+ * after you create it.  If your element derives from a base
+ * class, use the base class's virtual functions instead.
+ */
+#define GST_PAD_EVENTFULLFUNC(pad)     (GST_PAD_CAST(pad)->ABI.abi.eventfullfunc)
+/**
  * GST_PAD_QUERYFUNC:
  * @pad: a #GstPad
  *
@@ -1306,6 +1338,10 @@ void                     gst_pad_set_event_function_full         (GstPad *pad,
                                                                  GstPadEventFunction event,
                                                                  gpointer user_data,
                                                                  GDestroyNotify notify);
+void                   gst_pad_set_event_full_function_full    (GstPad *pad,
+                                                                 GstPadEventFullFunction event,
+                                                                 gpointer user_data,
+                                                                 GDestroyNotify notify);
 
 #define gst_pad_set_activate_function(p,f)      gst_pad_set_activate_function_full((p),(f),NULL,NULL)
 #define gst_pad_set_activatemode_function(p,f)  gst_pad_set_activatemode_function_full((p),(f),NULL,NULL)
@@ -1313,6 +1349,7 @@ void                      gst_pad_set_event_function_full         (GstPad *pad,
 #define gst_pad_set_chain_list_function(p,f)    gst_pad_set_chain_list_function_full((p),(f),NULL,NULL)
 #define gst_pad_set_getrange_function(p,f)      gst_pad_set_getrange_function_full((p),(f),NULL,NULL)
 #define gst_pad_set_event_function(p,f)         gst_pad_set_event_function_full((p),(f),NULL,NULL)
+#define gst_pad_set_event_full_function(p,f)    gst_pad_set_event_full_function_full((p),(f),NULL,NULL)
 
 /* pad links */
 void                   gst_pad_set_link_function_full          (GstPad *pad,
index db9f445..d98bd6d 100644 (file)
@@ -1941,14 +1941,15 @@ gst_multi_queue_sink_activate_mode (GstPad * pad, GstObject * parent,
   return res;
 }
 
-static gboolean
+static GstFlowReturn
 gst_multi_queue_sink_event (GstPad * pad, GstObject * parent, GstEvent * event)
 {
   GstSingleQueue *sq;
   GstMultiQueue *mq;
   guint32 curid;
   GstMultiQueueItem *item;
-  gboolean res;
+  gboolean res = TRUE;
+  GstFlowReturn flowret = GST_FLOW_OK;
   GstEventType type;
   GstEvent *sref = NULL;
 
@@ -2088,8 +2089,17 @@ gst_multi_queue_sink_event (GstPad * pad, GstObject * parent, GstEvent * event)
     default:
       break;
   }
+
 done:
-  return res;
+  if (res == FALSE) {
+    if (GST_EVENT_TYPE (event) == GST_EVENT_CAPS)
+      flowret = GST_FLOW_NOT_NEGOTIATED;
+    else
+      flowret = GST_FLOW_ERROR;
+  }
+  GST_DEBUG_OBJECT (mq, "SingleQueue %d : returning %s", sq->id,
+      gst_flow_get_name (flowret));
+  return flowret;
 
 flushing:
   {
@@ -2098,14 +2108,14 @@ flushing:
     if (sref)
       gst_event_unref (sref);
     gst_multi_queue_item_destroy (item);
-    goto done;
+    return sq->srcresult;
   }
 was_eos:
   {
-    GST_DEBUG_OBJECT (mq, "we are EOS, dropping event, return FALSE");
+    GST_DEBUG_OBJECT (mq, "we are EOS, dropping event, return GST_FLOW_EOS");
     gst_event_unref (event);
     res = FALSE;
-    goto done;
+    return GST_FLOW_EOS;
   }
 }
 
@@ -2676,7 +2686,7 @@ gst_single_queue_new (GstMultiQueue * mqueue, guint id)
       GST_DEBUG_FUNCPTR (gst_multi_queue_chain));
   gst_pad_set_activatemode_function (sq->sinkpad,
       GST_DEBUG_FUNCPTR (gst_multi_queue_sink_activate_mode));
-  gst_pad_set_event_function (sq->sinkpad,
+  gst_pad_set_event_full_function (sq->sinkpad,
       GST_DEBUG_FUNCPTR (gst_multi_queue_sink_event));
   gst_pad_set_query_function (sq->sinkpad,
       GST_DEBUG_FUNCPTR (gst_multi_queue_sink_query));
index 44714e8..6d9810f 100644 (file)
@@ -200,8 +200,8 @@ static GstFlowReturn gst_queue_chain_list (GstPad * pad, GstObject * parent,
 static GstFlowReturn gst_queue_push_one (GstQueue * queue);
 static void gst_queue_loop (GstPad * pad);
 
-static gboolean gst_queue_handle_sink_event (GstPad * pad, GstObject * parent,
-    GstEvent * event);
+static GstFlowReturn gst_queue_handle_sink_event (GstPad * pad,
+    GstObject * parent, GstEvent * event);
 static gboolean gst_queue_handle_sink_query (GstPad * pad, GstObject * parent,
     GstQuery * query);
 
@@ -431,7 +431,7 @@ gst_queue_init (GstQueue * queue)
   gst_pad_set_chain_list_function (queue->sinkpad, gst_queue_chain_list);
   gst_pad_set_activatemode_function (queue->sinkpad,
       gst_queue_sink_activate_mode);
-  gst_pad_set_event_function (queue->sinkpad, gst_queue_handle_sink_event);
+  gst_pad_set_event_full_function (queue->sinkpad, gst_queue_handle_sink_event);
   gst_pad_set_query_function (queue->sinkpad, gst_queue_handle_sink_query);
   GST_PAD_SET_PROXY_CAPS (queue->sinkpad);
   gst_element_add_pad (GST_ELEMENT (queue), queue->sinkpad);
@@ -897,7 +897,7 @@ no_item:
   }
 }
 
-static gboolean
+static GstFlowReturn
 gst_queue_handle_sink_event (GstPad * pad, GstObject * parent, GstEvent * event)
 {
   gboolean ret = TRUE;
@@ -985,7 +985,12 @@ gst_queue_handle_sink_event (GstPad * pad, GstObject * parent, GstEvent * event)
       }
       break;
   }
-  return ret;
+  if (ret == FALSE) {
+    if (GST_EVENT_TYPE (event) == GST_EVENT_CAPS)
+      return GST_FLOW_NOT_NEGOTIATED;
+    return GST_FLOW_ERROR;
+  }
+  return GST_FLOW_OK;
 
   /* ERRORS */
 out_eos:
@@ -993,7 +998,7 @@ out_eos:
     GST_CAT_LOG_OBJECT (queue_dataflow, queue, "refusing event, we are EOS");
     GST_QUEUE_MUTEX_UNLOCK (queue);
     gst_event_unref (event);
-    return FALSE;
+    return GST_FLOW_EOS;
   }
 out_flow_error:
   {
@@ -1001,7 +1006,7 @@ out_flow_error:
         "refusing event, we have a downstream flow error: %s",
         gst_flow_get_name (queue->srcresult));
     gst_event_unref (event);
-    return FALSE;
+    return queue->srcresult;
   }
 }
 
index 10dad7a..ce553fa 100644 (file)
@@ -895,6 +895,7 @@ EXPORTS
        gst_pad_set_chain_function_full
        gst_pad_set_chain_list_function_full
        gst_pad_set_element_private
+       gst_pad_set_event_full_function_full
        gst_pad_set_event_function_full
        gst_pad_set_getrange_function_full
        gst_pad_set_iterate_internal_links_function_full