pad->priv->events = g_array_sized_new (FALSE, TRUE, sizeof (PadEvent), 16);
pad->priv->events_cookie = 0;
pad->priv->last_cookie = -1;
+ pad->ABI.abi.last_flowret = GST_FLOW_FLUSHING;
}
/* called when setting the pad inactive. It removes all sticky events from
GST_OBJECT_LOCK (pad);
GST_DEBUG_OBJECT (pad, "setting PAD_MODE NONE, set flushing");
GST_PAD_SET_FLUSHING (pad);
+ pad->ABI.abi.last_flowret = GST_FLOW_FLUSHING;
GST_PAD_MODE (pad) = new_mode;
/* unlock blocked pads so element can resume and stop */
GST_PAD_BLOCK_BROADCAST (pad);
GST_DEBUG_OBJECT (pad, "setting pad into %s mode, unset flushing",
gst_pad_mode_get_name (new_mode));
GST_PAD_UNSET_FLUSHING (pad);
+ pad->ABI.abi.last_flowret = GST_FLOW_OK;
GST_PAD_MODE (pad) = new_mode;
if (GST_PAD_IS_SINK (pad)) {
GstPad *peer;
if (old == GST_PAD_MODE_NONE) {
GST_DEBUG_OBJECT (pad, "activating pad from none");
ret = (GST_PAD_ACTIVATEFUNC (pad)) (pad, parent);
+ if (ret)
+ pad->ABI.abi.last_flowret = GST_FLOW_OK;
} else {
GST_DEBUG_OBJECT (pad, "pad was active in %s mode",
gst_pad_mode_get_name (old));
GST_DEBUG_OBJECT (pad, "deactivating pad from %s mode",
gst_pad_mode_get_name (old));
ret = gst_pad_activate_mode (pad, old, FALSE);
+ if (ret)
+ pad->ABI.abi.last_flowret = GST_FLOW_FLUSHING;
}
}
gst_object_unref (peer);
GST_OBJECT_LOCK (pad);
+ pad->ABI.abi.last_flowret = ret;
pad->priv->using--;
if (pad->priv->using == 0) {
/* pad is not active anymore, trigger idle callbacks */
{
GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad,
"pushing, but pad was flushing");
+ pad->ABI.abi.last_flowret = GST_FLOW_FLUSHING;
GST_OBJECT_UNLOCK (pad);
gst_mini_object_unref (GST_MINI_OBJECT_CAST (data));
return GST_FLOW_FLUSHING;
eos:
{
GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, "pushing, but pad was EOS");
+ pad->ABI.abi.last_flowret = GST_FLOW_EOS;
GST_OBJECT_UNLOCK (pad);
gst_mini_object_unref (GST_MINI_OBJECT_CAST (data));
return GST_FLOW_EOS;
{
g_critical ("pushing on pad %s:%s but it was not activated in push mode",
GST_DEBUG_PAD_NAME (pad));
+ pad->ABI.abi.last_flowret = GST_FLOW_ERROR;
GST_OBJECT_UNLOCK (pad);
gst_mini_object_unref (GST_MINI_OBJECT_CAST (data));
return GST_FLOW_ERROR;
{
GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad,
"error pushing events, return %s", gst_flow_get_name (ret));
+ pad->ABI.abi.last_flowret = ret;
GST_OBJECT_UNLOCK (pad);
gst_mini_object_unref (GST_MINI_OBJECT_CAST (data));
return ret;
probe_stopped:
{
GST_OBJECT_UNLOCK (pad);
+ pad->ABI.abi.last_flowret =
+ ret == GST_FLOW_CUSTOM_SUCCESS ? GST_FLOW_OK : ret;
gst_mini_object_unref (GST_MINI_OBJECT_CAST (data));
switch (ret) {
{
GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad,
"pushing, but it was not linked");
+ pad->ABI.abi.last_flowret = GST_FLOW_NOT_LINKED;
GST_OBJECT_UNLOCK (pad);
gst_mini_object_unref (GST_MINI_OBJECT_CAST (data));
return GST_FLOW_NOT_LINKED;
RELEASE_PARENT (parent);
+ GST_OBJECT_LOCK (pad);
if (G_UNLIKELY (ret != GST_FLOW_OK))
goto get_range_failed;
/* can only fire the signal if we have a valid buffer */
- GST_OBJECT_LOCK (pad);
probed_data:
PROBE_PULL (pad, GST_PAD_PROBE_TYPE_PULL | GST_PAD_PROBE_TYPE_BUFFER,
res_buf, offset, size, probe_stopped_unref);
+ pad->ABI.abi.last_flowret = ret;
GST_OBJECT_UNLOCK (pad);
GST_PAD_STREAM_UNLOCK (pad);
{
GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad,
"getrange, but pad was flushing");
+ pad->ABI.abi.last_flowret = GST_FLOW_FLUSHING;
GST_OBJECT_UNLOCK (pad);
GST_PAD_STREAM_UNLOCK (pad);
return GST_FLOW_FLUSHING;
{
g_critical ("getrange on pad %s:%s but it was not activated in pull mode",
GST_DEBUG_PAD_NAME (pad));
+ pad->ABI.abi.last_flowret = GST_FLOW_ERROR;
GST_OBJECT_UNLOCK (pad);
GST_PAD_STREAM_UNLOCK (pad);
return GST_FLOW_ERROR;
events_error:
{
GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, "error pushing events");
+ pad->ABI.abi.last_flowret = ret;
GST_OBJECT_UNLOCK (pad);
GST_PAD_STREAM_UNLOCK (pad);
return ret;
no_parent:
{
GST_DEBUG_OBJECT (pad, "no parent");
+ pad->ABI.abi.last_flowret = GST_FLOW_FLUSHING;
GST_OBJECT_UNLOCK (pad);
GST_PAD_STREAM_UNLOCK (pad);
return GST_FLOW_FLUSHING;
ret = GST_FLOW_EOS;
}
}
+ pad->ABI.abi.last_flowret = ret;
GST_OBJECT_UNLOCK (pad);
GST_PAD_STREAM_UNLOCK (pad);
/* if we drop here, it signals EOS */
if (ret == GST_FLOW_CUSTOM_SUCCESS)
ret = GST_FLOW_EOS;
+ pad->ABI.abi.last_flowret = ret;
GST_OBJECT_UNLOCK (pad);
GST_PAD_STREAM_UNLOCK (pad);
if (*buffer == NULL)
}
get_range_failed:
{
+ pad->ABI.abi.last_flowret = ret;
+ GST_OBJECT_UNLOCK (pad);
GST_PAD_STREAM_UNLOCK (pad);
GST_CAT_LEVEL_LOG (GST_CAT_SCHEDULING,
(ret >= GST_FLOW_EOS) ? GST_LEVEL_INFO : GST_LEVEL_WARNING,
GST_OBJECT_LOCK (pad);
pad->priv->using--;
+ pad->ABI.abi.last_flowret = ret;
if (pad->priv->using == 0) {
/* pad is not active anymore, trigger idle callbacks */
PROBE_NO_DATA (pad, GST_PAD_PROBE_TYPE_PULL | GST_PAD_PROBE_TYPE_IDLE,
{
GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad,
"pullrange, but pad was flushing");
+ pad->ABI.abi.last_flowret = GST_FLOW_FLUSHING;
GST_OBJECT_UNLOCK (pad);
return GST_FLOW_FLUSHING;
}
{
g_critical ("pullrange on pad %s:%s but it was not activated in pull mode",
GST_DEBUG_PAD_NAME (pad));
+ pad->ABI.abi.last_flowret = GST_FLOW_ERROR;
GST_OBJECT_UNLOCK (pad);
return GST_FLOW_ERROR;
}
ret = GST_FLOW_EOS;
}
}
+ pad->ABI.abi.last_flowret = ret;
GST_OBJECT_UNLOCK (pad);
return ret;
}
{
GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad,
"pulling range, but it was not linked");
+ pad->ABI.abi.last_flowret = GST_FLOW_NOT_LINKED;
GST_OBJECT_UNLOCK (pad);
return GST_FLOW_NOT_LINKED;
}
pull_range_failed:
{
+ pad->ABI.abi.last_flowret = ret;
GST_OBJECT_UNLOCK (pad);
GST_CAT_LEVEL_LOG (GST_CAT_SCHEDULING,
(ret >= GST_FLOW_EOS) ? GST_LEVEL_INFO : GST_LEVEL_WARNING,
{
GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad,
"post probe returned %s", gst_flow_get_name (ret));
- GST_OBJECT_UNLOCK (pad);
+
/* if we drop here, it signals EOS */
if (ret == GST_FLOW_CUSTOM_SUCCESS)
ret = GST_FLOW_EOS;
+
+ pad->ABI.abi.last_flowret = ret;
+ GST_OBJECT_UNLOCK (pad);
+
if (*buffer == NULL)
gst_buffer_unref (res_buf);
return ret;
break;
}
}
- if (type == GST_EVENT_EOS)
+ if (type == GST_EVENT_EOS) {
GST_OBJECT_FLAG_SET (pad, GST_PAD_FLAG_EOS);
+ pad->ABI.abi.last_flowret = GST_FLOW_EOS;
+ }
return GST_PAD_IS_FLUSHING (pad) ? GST_FLOW_FLUSHING : GST_FLOW_OK;
remove_event_by_type (pad, GST_EVENT_EOS);
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;
type |= GST_PAD_PROBE_TYPE_EVENT_FLUSH;
break;
remove_event_by_type (pad, GST_EVENT_EOS);
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;
GST_OBJECT_UNLOCK (pad);
/* grab stream lock */
return GST_PAD_PROBE_INFO_BUFFER_LIST (info);
}
+
+/**
+ * gst_pad_get_last_flowreturn:
+ * @pad: the #GstPad
+ *
+ * Gets the #GstFlowReturn return from the last data passed by this pad.
+ *
+ * Since: 1.4
+ */
+GstFlowReturn
+gst_pad_get_last_flow_return (GstPad * pad)
+{
+ GstFlowReturn ret;
+
+ GST_OBJECT_LOCK (pad);
+ ret = GST_PAD_LAST_FLOW_RETURN (pad);
+ GST_OBJECT_UNLOCK (pad);
+
+ return ret;
+}
GST_END_TEST;
+static GstFlowReturn next_return;
+
+static GstFlowReturn
+test_lastflow_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer)
+{
+ gst_buffer_unref (buffer);
+ return next_return;
+}
+
+GST_START_TEST (test_last_flow_return_push)
+{
+ GstPad *srcpad, *sinkpad;
+ GstSegment seg;
+
+ srcpad = gst_pad_new ("src", GST_PAD_SRC);
+ fail_unless (srcpad != NULL);
+ sinkpad = gst_pad_new ("sink", GST_PAD_SINK);
+ fail_unless (sinkpad != NULL);
+ gst_pad_set_chain_function (sinkpad, test_lastflow_chain);
+ gst_pad_link (srcpad, sinkpad);
+
+ /* initial value is flushing */
+ fail_unless (gst_pad_get_last_flow_return (srcpad) == GST_FLOW_FLUSHING);
+
+ /* when active it goes to ok */
+ gst_pad_set_active (srcpad, TRUE);
+ fail_unless (gst_pad_get_last_flow_return (srcpad) == GST_FLOW_OK);
+ gst_pad_set_active (sinkpad, TRUE);
+
+ /* startup events */
+ gst_pad_push_event (srcpad, gst_event_new_stream_start ("test"));
+ gst_segment_init (&seg, GST_FORMAT_TIME);
+ gst_pad_push_event (srcpad, gst_event_new_segment (&seg));
+
+
+ /* push Ok */
+ next_return = GST_FLOW_OK;
+ fail_unless (gst_pad_push (srcpad, gst_buffer_new ()) == GST_FLOW_OK);
+ fail_unless (gst_pad_get_last_flow_return (srcpad) == GST_FLOW_OK);
+
+ /* push not-linked */
+ next_return = GST_FLOW_NOT_LINKED;
+ fail_unless (gst_pad_push (srcpad, gst_buffer_new ()) == GST_FLOW_NOT_LINKED);
+ fail_unless (gst_pad_get_last_flow_return (srcpad) == GST_FLOW_NOT_LINKED);
+
+ /* push not-linked */
+ next_return = GST_FLOW_NOT_NEGOTIATED;
+ fail_unless (gst_pad_push (srcpad,
+ gst_buffer_new ()) == GST_FLOW_NOT_NEGOTIATED);
+ fail_unless (gst_pad_get_last_flow_return (srcpad) ==
+ GST_FLOW_NOT_NEGOTIATED);
+
+ /* push error */
+ next_return = GST_FLOW_ERROR;
+ fail_unless (gst_pad_push (srcpad, gst_buffer_new ()) == GST_FLOW_ERROR);
+ fail_unless (gst_pad_get_last_flow_return (srcpad) == GST_FLOW_ERROR);
+
+ /* back to ok */
+ next_return = GST_FLOW_OK;
+ fail_unless (gst_pad_push (srcpad, gst_buffer_new ()) == GST_FLOW_OK);
+ fail_unless (gst_pad_get_last_flow_return (srcpad) == GST_FLOW_OK);
+
+ /* unlinked push */
+ gst_pad_unlink (srcpad, sinkpad);
+ fail_unless (gst_pad_push (srcpad, gst_buffer_new ()) == GST_FLOW_NOT_LINKED);
+ fail_unless (gst_pad_get_last_flow_return (srcpad) == GST_FLOW_NOT_LINKED);
+
+ gst_pad_link (srcpad, sinkpad);
+ fail_unless (gst_pad_push_event (srcpad, gst_event_new_eos ()));
+ fail_unless (gst_pad_get_last_flow_return (srcpad) == GST_FLOW_EOS);
+
+ gst_object_unref (srcpad);
+ gst_object_unref (sinkpad);
+}
+
+GST_END_TEST;
+
+static GstFlowReturn
+test_lastflow_getrange (GstPad * pad, GstObject * parent, guint64 offset,
+ guint length, GstBuffer ** buf)
+{
+ if (next_return == GST_FLOW_OK)
+ *buf = gst_buffer_new ();
+ else
+ *buf = NULL;
+ return next_return;
+}
+
+static gboolean
+test_lastflow_activate_pull_func (GstPad * pad, GstObject * object)
+{
+ return gst_pad_activate_mode (pad, GST_PAD_MODE_PULL, TRUE);
+}
+
+GST_START_TEST (test_last_flow_return_pull)
+{
+ GstPad *srcpad, *sinkpad;
+ GstBuffer *buf = NULL;
+
+ srcpad = gst_pad_new ("src", GST_PAD_SRC);
+ fail_unless (srcpad != NULL);
+ sinkpad = gst_pad_new ("sink", GST_PAD_SINK);
+ fail_unless (sinkpad != NULL);
+ gst_pad_set_getrange_function (srcpad, test_lastflow_getrange);
+ gst_pad_set_activate_function (sinkpad, test_lastflow_activate_pull_func);
+ gst_pad_link (srcpad, sinkpad);
+
+ /* initial value is flushing */
+ fail_unless (gst_pad_get_last_flow_return (sinkpad) == GST_FLOW_FLUSHING);
+
+ /* when active it goes to ok */
+ gst_pad_set_active (sinkpad, TRUE);
+ fail_unless (gst_pad_get_last_flow_return (sinkpad) == GST_FLOW_OK);
+ gst_pad_set_active (srcpad, TRUE);
+
+ /* pull Ok */
+ next_return = GST_FLOW_OK;
+ fail_unless (gst_pad_pull_range (sinkpad, 0, 1, &buf) == GST_FLOW_OK);
+ fail_unless (gst_pad_get_last_flow_return (sinkpad) == GST_FLOW_OK);
+ gst_buffer_unref (buf);
+ buf = NULL;
+
+ /* pull not-linked */
+ next_return = GST_FLOW_NOT_LINKED;
+ fail_unless (gst_pad_pull_range (sinkpad, 0, 1, &buf) == GST_FLOW_NOT_LINKED);
+ fail_unless (gst_pad_get_last_flow_return (sinkpad) == GST_FLOW_NOT_LINKED);
+
+ /* pull error */
+ next_return = GST_FLOW_ERROR;
+ fail_unless (gst_pad_pull_range (sinkpad, 0, 1, &buf) == GST_FLOW_ERROR);
+ fail_unless (gst_pad_get_last_flow_return (sinkpad) == GST_FLOW_ERROR);
+
+ /* pull not-nego */
+ next_return = GST_FLOW_NOT_NEGOTIATED;
+ fail_unless (gst_pad_pull_range (sinkpad, 0, 1,
+ &buf) == GST_FLOW_NOT_NEGOTIATED);
+ fail_unless (gst_pad_get_last_flow_return (sinkpad) ==
+ GST_FLOW_NOT_NEGOTIATED);
+
+ /* pull ok again */
+ next_return = GST_FLOW_OK;
+ fail_unless (gst_pad_pull_range (sinkpad, 0, 1, &buf) == GST_FLOW_OK);
+ fail_unless (gst_pad_get_last_flow_return (sinkpad) == GST_FLOW_OK);
+ gst_buffer_unref (buf);
+ buf = NULL;
+
+ /* unlinked pads */
+ gst_pad_unlink (srcpad, sinkpad);
+ fail_unless (gst_pad_pull_range (sinkpad, 0, 1, &buf) == GST_FLOW_NOT_LINKED);
+ fail_unless (gst_pad_get_last_flow_return (sinkpad) == GST_FLOW_NOT_LINKED);
+
+ /* eos */
+ gst_pad_link (srcpad, sinkpad);
+ next_return = GST_FLOW_EOS;
+ fail_unless (gst_pad_pull_range (sinkpad, 0, 1, &buf) == GST_FLOW_EOS);
+ fail_unless (gst_pad_get_last_flow_return (sinkpad) == GST_FLOW_EOS);
+
+ gst_object_unref (srcpad);
+ gst_object_unref (sinkpad);
+}
+
+GST_END_TEST;
+
static Suite *
gst_pad_suite (void)
{
tcase_add_test (tc_chain, test_block_async_full_destroy_dispose);
tcase_add_test (tc_chain, test_block_async_replace_callback_no_flush);
tcase_add_test (tc_chain, test_sticky_events);
+ tcase_add_test (tc_chain, test_last_flow_return_push);
+ tcase_add_test (tc_chain, test_last_flow_return_pull);
return s;
}