static GstFlowReturn gst_pad_chain_list_default (GstPad * pad,
GstObject * parent, GstBufferList * list);
+static GstFlowReturn gst_pad_send_event_unchecked (GstPad * pad,
+ GstEvent * event, GstPadProbeType type);
+static GstFlowReturn gst_pad_push_event_unchecked (GstPad * pad,
+ GstEvent * event, GstPadProbeType type, gboolean * stored);
+
static guint gst_pad_signals[LAST_SIGNAL] = { 0 };
static GParamSpec *pspec_caps = NULL;
static GstFlowQuarks flow_quarks[] = {
{GST_FLOW_CUSTOM_SUCCESS, "custom-success", 0},
- {GST_FLOW_RESEND, "resend", 0},
{GST_FLOW_OK, "ok", 0},
{GST_FLOW_NOT_LINKED, "not-linked", 0},
- {GST_FLOW_WRONG_STATE, "wrong-state", 0},
+ {GST_FLOW_FLUSHING, "flushing", 0},
{GST_FLOW_EOS, "eos", 0},
{GST_FLOW_NOT_NEGOTIATED, "not-negotiated", 0},
{GST_FLOW_ERROR, "error", 0},
GST_PAD_SET_FLUSHING (pad);
- g_static_rec_mutex_init (&pad->stream_rec_lock);
+ g_rec_mutex_init (&pad->stream_rec_lock);
- pad->block_cond = g_cond_new ();
+ g_cond_init (&pad->block_cond);
g_hook_list_init (&pad->probes, sizeof (GstProbe));
- pad->priv->events = g_array_sized_new (FALSE, TRUE,
- sizeof (PadEvent), GST_EVENT_MAX_STICKY);
+ pad->priv->events = g_array_sized_new (FALSE, TRUE, sizeof (PadEvent), 16);
}
/* called when setting the pad inactive. It removes all sticky events from
}
if (pad->activatenotify)
- pad->activatenotify (pad);
+ pad->activatenotify (pad->activatedata);
if (pad->activatemodenotify)
- pad->activatemodenotify (pad);
+ pad->activatemodenotify (pad->activatemodedata);
if (pad->linknotify)
- pad->linknotify (pad);
+ pad->linknotify (pad->linkdata);
if (pad->unlinknotify)
- pad->unlinknotify (pad);
+ pad->unlinknotify (pad->unlinkdata);
if (pad->chainnotify)
- pad->chainnotify (pad);
+ pad->chainnotify (pad->chaindata);
if (pad->chainlistnotify)
- pad->chainlistnotify (pad);
+ pad->chainlistnotify (pad->chainlistdata);
if (pad->getrangenotify)
- pad->getrangenotify (pad);
+ pad->getrangenotify (pad->getrangedata);
if (pad->eventnotify)
- pad->eventnotify (pad);
+ pad->eventnotify (pad->eventdata);
if (pad->querynotify)
- pad->querynotify (pad);
+ pad->querynotify (pad->querydata);
if (pad->iterintlinknotify)
- pad->iterintlinknotify (pad);
+ pad->iterintlinknotify (pad->iterintlinkdata);
- g_static_rec_mutex_free (&pad->stream_rec_lock);
- g_cond_free (pad->block_cond);
+ g_rec_mutex_clear (&pad->stream_rec_lock);
+ g_cond_clear (&pad->block_cond);
g_array_free (pad->priv->events, TRUE);
G_OBJECT_CLASS (parent_class)->finalize (object);
* will be assigned.
* This function makes a copy of the name so you can safely free the name.
*
- * Returns: (transfer full): a new #GstPad, or NULL in case of an error.
+ * Returns: (transfer floating): a new #GstPad, or NULL in case of an error.
*
* MT safe.
*/
"pad is in use, delay idle callback");
GST_OBJECT_UNLOCK (pad);
} else {
- GstPadProbeInfo info = { GST_PAD_PROBE_TYPE_IDLE, };
+ GstPadProbeInfo info = { GST_PAD_PROBE_TYPE_IDLE, res, };
/* the pad is idle now, we can signal the idle callback now */
GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad,
* gst_pad_set_activate_function_full:
* @pad: a #GstPad.
* @activate: the #GstPadActivateFunction to set.
+ * @user_data: user_data passed to @notify
* @notify: notify called when @activate will not be used anymore.
*
* Sets the given activate function for @pad. The activate function will
*/
void
gst_pad_set_activate_function_full (GstPad * pad,
- GstPadActivateFunction activate, GDestroyNotify notify)
+ GstPadActivateFunction activate, gpointer user_data, GDestroyNotify notify)
{
g_return_if_fail (GST_IS_PAD (pad));
if (pad->activatenotify)
- pad->activatenotify (pad);
+ pad->activatenotify (pad->activatedata);
GST_PAD_ACTIVATEFUNC (pad) = activate;
+ pad->activatedata = user_data;
pad->activatenotify = notify;
GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad, "activatefunc set to %s",
* gst_pad_set_activatemode_function_full:
* @pad: a #GstPad.
* @activatemode: the #GstPadActivateModeFunction to set.
+ * @user_data: user_data passed to @notify
* @notify: notify called when @activatemode will not be used anymore.
*
* Sets the given activate_mode function for the pad. An activate_mode function
*/
void
gst_pad_set_activatemode_function_full (GstPad * pad,
- GstPadActivateModeFunction activatemode, GDestroyNotify notify)
+ GstPadActivateModeFunction activatemode, gpointer user_data,
+ GDestroyNotify notify)
{
g_return_if_fail (GST_IS_PAD (pad));
if (pad->activatemodenotify)
- pad->activatemodenotify (pad);
+ pad->activatemodenotify (pad->activatemodedata);
GST_PAD_ACTIVATEMODEFUNC (pad) = activatemode;
+ pad->activatemodedata = user_data;
pad->activatemodenotify = notify;
GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad, "activatemodefunc set to %s",
* gst_pad_set_chain_function_full:
* @pad: a sink #GstPad.
* @chain: the #GstPadChainFunction to set.
+ * @user_data: user_data passed to @notify
* @notify: notify called when @chain will not be used anymore.
*
* Sets the given chain function for the pad. The chain function is called to
*/
void
gst_pad_set_chain_function_full (GstPad * pad, GstPadChainFunction chain,
- GDestroyNotify notify)
+ gpointer user_data, GDestroyNotify notify)
{
g_return_if_fail (GST_IS_PAD (pad));
g_return_if_fail (GST_PAD_IS_SINK (pad));
if (pad->chainnotify)
- pad->chainnotify (pad);
+ pad->chainnotify (pad->chaindata);
GST_PAD_CHAINFUNC (pad) = chain;
+ pad->chaindata = user_data;
pad->chainnotify = notify;
GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad, "chainfunc set to %s",
* gst_pad_set_chain_list_function_full:
* @pad: a sink #GstPad.
* @chainlist: the #GstPadChainListFunction to set.
+ * @user_data: user_data passed to @notify
* @notify: notify called when @chainlist will not be used anymore.
*
* Sets the given chain list function for the pad. The chainlist function is
*/
void
gst_pad_set_chain_list_function_full (GstPad * pad,
- GstPadChainListFunction chainlist, GDestroyNotify notify)
+ GstPadChainListFunction chainlist, gpointer user_data,
+ GDestroyNotify notify)
{
g_return_if_fail (GST_IS_PAD (pad));
g_return_if_fail (GST_PAD_IS_SINK (pad));
if (pad->chainlistnotify)
- pad->chainlistnotify (pad);
+ pad->chainlistnotify (pad->chainlistdata);
GST_PAD_CHAINLISTFUNC (pad) = chainlist;
+ pad->chainlistdata = user_data;
pad->chainlistnotify = notify;
GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad, "chainlistfunc set to %s",
* gst_pad_set_getrange_function_full:
* @pad: a source #GstPad.
* @get: the #GstPadGetRangeFunction to set.
+ * @user_data: user_data passed to @notify
* @notify: notify called when @get will not be used anymore.
*
* Sets the given getrange function for the pad. The getrange function is
*/
void
gst_pad_set_getrange_function_full (GstPad * pad, GstPadGetRangeFunction get,
- GDestroyNotify notify)
+ gpointer user_data, GDestroyNotify notify)
{
g_return_if_fail (GST_IS_PAD (pad));
g_return_if_fail (GST_PAD_IS_SRC (pad));
if (pad->getrangenotify)
- pad->getrangenotify (pad);
+ pad->getrangenotify (pad->getrangedata);
GST_PAD_GETRANGEFUNC (pad) = get;
+ pad->getrangedata = user_data;
pad->getrangenotify = notify;
GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad, "getrangefunc set to %s",
* gst_pad_set_event_function_full:
* @pad: a #GstPad of either direction.
* @event: the #GstPadEventFunction 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_function_full (GstPad * pad, GstPadEventFunction event,
- GDestroyNotify notify)
+ gpointer user_data, GDestroyNotify notify)
{
g_return_if_fail (GST_IS_PAD (pad));
if (pad->eventnotify)
- pad->eventnotify (pad);
+ pad->eventnotify (pad->eventdata);
GST_PAD_EVENTFUNC (pad) = event;
+ pad->eventdata = user_data;
pad->eventnotify = notify;
GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad, "eventfunc for set to %s",
* gst_pad_set_query_function_full:
* @pad: a #GstPad of either direction.
* @query: the #GstPadQueryFunction to set.
+ * @user_data: user_data passed to @notify
* @notify: notify called when @query will not be used anymore.
*
* Set the given query function for the pad.
*/
void
gst_pad_set_query_function_full (GstPad * pad, GstPadQueryFunction query,
- GDestroyNotify notify)
+ gpointer user_data, GDestroyNotify notify)
{
g_return_if_fail (GST_IS_PAD (pad));
if (pad->querynotify)
- pad->querynotify (pad);
+ pad->querynotify (pad->querydata);
GST_PAD_QUERYFUNC (pad) = query;
+ pad->querydata = user_data;
pad->querynotify = notify;
GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad, "queryfunc set to %s",
* gst_pad_set_iterate_internal_links_function_full:
* @pad: a #GstPad of either direction.
* @iterintlink: the #GstPadIterIntLinkFunction to set.
+ * @user_data: user_data passed to @notify
* @notify: notify called when @iterintlink will not be used anymore.
*
* Sets the given internal link iterator function for the pad.
*/
void
gst_pad_set_iterate_internal_links_function_full (GstPad * pad,
- GstPadIterIntLinkFunction iterintlink, GDestroyNotify notify)
+ GstPadIterIntLinkFunction iterintlink, gpointer user_data,
+ GDestroyNotify notify)
{
g_return_if_fail (GST_IS_PAD (pad));
if (pad->iterintlinknotify)
- pad->iterintlinknotify (pad);
+ pad->iterintlinknotify (pad->iterintlinkdata);
GST_PAD_ITERINTLINKFUNC (pad) = iterintlink;
+ pad->iterintlinkdata = user_data;
pad->iterintlinknotify = notify;
GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad, "internal link iterator set to %s",
* gst_pad_set_link_function_full:
* @pad: a #GstPad.
* @link: the #GstPadLinkFunction to set.
+ * @user_data: user_data passed to @notify
* @notify: notify called when @link will not be used anymore.
*
* Sets the given link function for the pad. It will be called when
*/
void
gst_pad_set_link_function_full (GstPad * pad, GstPadLinkFunction link,
- GDestroyNotify notify)
+ gpointer user_data, GDestroyNotify notify)
{
g_return_if_fail (GST_IS_PAD (pad));
if (pad->linknotify)
- pad->linknotify (pad);
+ pad->linknotify (pad->linkdata);
GST_PAD_LINKFUNC (pad) = link;
+ pad->linkdata = user_data;
pad->linknotify = notify;
GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad, "linkfunc set to %s",
* gst_pad_set_unlink_function_full:
* @pad: a #GstPad.
* @unlink: the #GstPadUnlinkFunction to set.
+ * @user_data: user_data passed to @notify
* @notify: notify called when @unlink will not be used anymore.
*
* Sets the given unlink function for the pad. It will be called
*/
void
gst_pad_set_unlink_function_full (GstPad * pad, GstPadUnlinkFunction unlink,
- GDestroyNotify notify)
+ gpointer user_data, GDestroyNotify notify)
{
g_return_if_fail (GST_IS_PAD (pad));
if (pad->unlinknotify)
- pad->unlinknotify (pad);
+ pad->unlinknotify (pad->unlinkdata);
GST_PAD_UNLINKFUNC (pad) = unlink;
+ pad->unlinkdata = user_data;
pad->unlinknotify = notify;
GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad, "unlinkfunc set to %s",
intpad = g_value_get_object (&item);
/* if already pushed, skip. FIXME, find something faster to tag pads */
- if (g_list_find (pushed_pads, intpad)) {
+ if (intpad == NULL || g_list_find (pushed_pads, intpad)) {
g_value_reset (&item);
break;
}
}
}
+ GST_CAT_DEBUG_OBJECT (GST_CAT_PERFORMANCE, pad,
+ "fallback ACCEPT_CAPS query, consider implementing a specialized version");
+
allowed = gst_pad_query_caps (pad, NULL);
gst_query_parse_accept_caps (query, &caps);
gboolean
gst_pad_query_default (GstPad * pad, GstObject * parent, GstQuery * query)
{
- gboolean forward = TRUE, ret = FALSE;
+ gboolean forward, ret = FALSE;
switch (GST_QUERY_TYPE (query)) {
case GST_QUERY_SCHEDULING:
forward = FALSE;
break;
+ case GST_QUERY_ALLOCATION:
+ forward = GST_PAD_IS_PROXY_ALLOCATION (pad);
+ break;
case GST_QUERY_ACCEPT_CAPS:
ret = gst_pad_query_accept_caps_default (pad, query);
forward = FALSE;
case GST_QUERY_JITTER:
case GST_QUERY_RATE:
case GST_QUERY_CONVERT:
- case GST_QUERY_ALLOCATION:
default:
+ forward = TRUE;
break;
}
GstPadProbeCallback callback;
GstPadProbeReturn ret;
- GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad,
- "hook %lu, cookie %u checking", hook->hook_id, PROBE_COOKIE (hook));
-
/* if we have called this callback, do nothing */
if (PROBE_COOKIE (hook) == data->cookie) {
GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad,
if ((type & GST_PAD_PROBE_TYPE_BLOCKING) &&
(flags & GST_PAD_PROBE_TYPE_BLOCKING & type) == 0)
goto no_match;
+ /* only probes that have GST_PAD_PROBE_TYPE_EVENT_FLUSH set */
+ if ((type & GST_PAD_PROBE_TYPE_EVENT_FLUSH) &&
+ (flags & GST_PAD_PROBE_TYPE_EVENT_FLUSH & type) == 0)
+ goto no_match;
GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad,
- "hook %lu with flags 0x%08x matches", hook->hook_id, flags);
+ "hook %lu, cookie %u with flags 0x%08x matches", hook->hook_id,
+ PROBE_COOKIE (hook), flags);
callback = (GstPadProbeCallback) hook->func;
if (callback == NULL)
return;
+ info->id = hook->hook_id;
+
GST_OBJECT_UNLOCK (pad);
ret = callback (pad, info, hook->data);
no_match:
{
GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad,
- "hook %lu with flags 0x%08x does not match %08x", hook->hook_id,
- flags, info->type);
+ "hook %lu, cookie %u with flags 0x%08x does not match %08x",
+ hook->hook_id, PROBE_COOKIE (hook), flags, info->type);
return;
}
}
G_STMT_START { \
if (G_UNLIKELY (pad->num_probes)) { \
/* we start with passing NULL as the data item */ \
- GstPadProbeInfo info = { mask, NULL, offs, size }; \
+ GstPadProbeInfo info = { mask, 0, NULL, offs, size }; \
ret = do_probe_callbacks (pad, &info, defaultval); \
/* store the possibly updated data item */ \
data = GST_PAD_PROBE_INFO_DATA (&info); \
G_STMT_START { \
if (G_UNLIKELY (pad->num_probes)) { \
/* pass NULL as the data item */ \
- GstPadProbeInfo info = { mask, NULL, 0, 0 }; \
+ GstPadProbeInfo info = { mask, 0, NULL, 0, 0 }; \
ret = do_probe_callbacks (pad, &info, defaultval); \
if (G_UNLIKELY (ret != defaultval && ret != GST_FLOW_OK)) \
goto label; \
#define PROBE_FULL(pad,mask,data,offs,size,label,defaultval) \
G_STMT_START { \
if (G_UNLIKELY (pad->num_probes)) { \
- GstPadProbeInfo info = { mask, data, offs, size }; \
+ GstPadProbeInfo info = { mask, 0, data, offs, size }; \
ret = do_probe_callbacks (pad, &info, defaultval); \
data = GST_PAD_PROBE_INFO_DATA (&info); \
if (G_UNLIKELY (ret != defaultval && ret != GST_FLOW_OK)) \
flushing:
{
GST_DEBUG_OBJECT (pad, "pad is flushing");
- return GST_FLOW_WRONG_STATE;
+ return GST_FLOW_FLUSHING;
}
dropped:
{
static gboolean
push_sticky (GstPad * pad, PadEvent * ev, gpointer user_data)
{
- gboolean res;
GstFlowReturn *data = user_data;
+ gboolean stored;
if (ev->received) {
GST_DEBUG_OBJECT (pad, "event %s was already received",
}
GST_OBJECT_UNLOCK (pad);
- res = gst_pad_push_event (pad, gst_event_ref (ev->event));
+ *data = gst_pad_push_event_unchecked (pad, gst_event_ref (ev->event),
+ GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM, &stored);
GST_OBJECT_LOCK (pad);
- if (!res)
- *data = GST_FLOW_ERROR;
-
- return res;
+ return *data == GST_FLOW_OK;
}
/* this is the chain function that does not perform the additional argument
if (G_UNLIKELY (GST_PAD_IS_FLUSHING (pad)))
goto flushing;
+ if (G_UNLIKELY (GST_PAD_MODE (pad) != GST_PAD_MODE_PUSH))
+ goto wrong_mode;
+
PROBE_PUSH (pad, type | GST_PAD_PROBE_TYPE_BLOCK, data, probe_stopped);
PROBE_PUSH (pad, type, data, probe_stopped);
GST_OBJECT_UNLOCK (pad);
GST_PAD_STREAM_UNLOCK (pad);
gst_mini_object_unref (GST_MINI_OBJECT_CAST (data));
- return GST_FLOW_WRONG_STATE;
+ return GST_FLOW_FLUSHING;
+ }
+wrong_mode:
+ {
+ GST_ELEMENT_ERROR (GST_PAD_PARENT (pad), CORE, PAD, (NULL),
+ ("chain on pad %s:%s but it was not in push mode",
+ GST_DEBUG_PAD_NAME (pad)));
+ GST_OBJECT_UNLOCK (pad);
+ GST_PAD_STREAM_UNLOCK (pad);
+ gst_mini_object_unref (GST_MINI_OBJECT_CAST (data));
+ return GST_FLOW_ERROR;
}
probe_stopped:
{
no_function:
{
gst_mini_object_unref (GST_MINI_OBJECT_CAST (data));
- GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad,
- "pushing, but not chainhandler");
GST_ELEMENT_ERROR (parent, CORE, PAD, (NULL),
- ("push on pad %s:%s but it has no chainfunction",
+ ("chain on pad %s:%s but it has no chainfunction",
GST_DEBUG_PAD_NAME (pad)));
GST_PAD_STREAM_UNLOCK (pad);
return GST_FLOW_NOT_SUPPORTED;
*
* Chain a buffer to @pad.
*
- * The function returns #GST_FLOW_WRONG_STATE if the pad was flushing.
+ * The function returns #GST_FLOW_FLUSHING if the pad was flushing.
*
* If the buffer type is not acceptable for @pad (as negotiated with a
* preceeding GST_EVENT_CAPS event), this function returns
*
* Chain a bufferlist to @pad.
*
- * The function returns #GST_FLOW_WRONG_STATE if the pad was flushing.
+ * The function returns #GST_FLOW_FLUSHING if the pad was flushing.
*
* If @pad was not negotiated properly with a CAPS event, this function
* returns #GST_FLOW_NOT_NEGOTIATED.
if (G_UNLIKELY (GST_PAD_IS_FLUSHING (pad)))
goto flushing;
+ if (G_UNLIKELY (GST_PAD_MODE (pad) != GST_PAD_MODE_PUSH))
+ goto wrong_mode;
+
if (G_UNLIKELY (GST_PAD_HAS_PENDING_EVENTS (pad))) {
GST_OBJECT_FLAG_UNSET (pad, GST_PAD_FLAG_PENDING_EVENTS);
"pushing, but pad was flushing");
GST_OBJECT_UNLOCK (pad);
gst_mini_object_unref (GST_MINI_OBJECT_CAST (data));
- return GST_FLOW_WRONG_STATE;
+ return GST_FLOW_FLUSHING;
+ }
+wrong_mode:
+ {
+ GST_ELEMENT_ERROR (GST_PAD_PARENT (pad), CORE, PAD, (NULL),
+ ("pushing on pad %s:%s but it was not activated in push mode",
+ GST_DEBUG_PAD_NAME (pad)));
+ GST_OBJECT_UNLOCK (pad);
+ gst_mini_object_unref (GST_MINI_OBJECT_CAST (data));
+ return GST_FLOW_ERROR;
}
events_error:
{
- GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, "error pushing events");
+ GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad,
+ "error pushing events, return %s", gst_flow_get_name (ret));
GST_OBJECT_UNLOCK (pad);
gst_mini_object_unref (GST_MINI_OBJECT_CAST (data));
return ret;
if (G_UNLIKELY (GST_PAD_IS_FLUSHING (pad)))
goto flushing;
+ if (G_UNLIKELY (GST_PAD_MODE (pad) != GST_PAD_MODE_PULL))
+ goto wrong_mode;
+
if (G_UNLIKELY (GST_PAD_HAS_PENDING_EVENTS (pad))) {
GST_OBJECT_FLAG_UNSET (pad, GST_PAD_FLAG_PENDING_EVENTS);
"getrange, but pad was flushing");
GST_OBJECT_UNLOCK (pad);
GST_PAD_STREAM_UNLOCK (pad);
- return GST_FLOW_WRONG_STATE;
+ return GST_FLOW_FLUSHING;
+ }
+wrong_mode:
+ {
+ GST_ELEMENT_ERROR (GST_PAD_PARENT (pad), CORE, PAD, (NULL),
+ ("getrange on pad %s:%s but it was not activated in pull mode",
+ GST_DEBUG_PAD_NAME (pad)));
+ GST_OBJECT_UNLOCK (pad);
+ GST_PAD_STREAM_UNLOCK (pad);
+ return GST_FLOW_ERROR;
}
events_error:
{
GST_DEBUG_OBJECT (pad, "no parent");
GST_OBJECT_UNLOCK (pad);
GST_PAD_STREAM_UNLOCK (pad);
- return GST_FLOW_WRONG_STATE;
+ return GST_FLOW_FLUSHING;
}
no_function:
{
* @buffer: (out callee-allocates): a pointer to hold the #GstBuffer,
* returns #GST_FLOW_ERROR if %NULL.
*
- * When @pad is flushing this function returns #GST_FLOW_WRONG_STATE
+ * When @pad is flushing this function returns #GST_FLOW_FLUSHING
* immediately and @buffer is %NULL.
*
* Calls the getrange function of @pad, see #GstPadGetRangeFunction for a
if (G_UNLIKELY (GST_PAD_IS_FLUSHING (pad)))
goto flushing;
+ if (G_UNLIKELY (GST_PAD_MODE (pad) != GST_PAD_MODE_PULL))
+ goto wrong_mode;
+
/* when one of the probes returns a buffer, probed_data will be called and we
* skip calling the peer getrange function */
PROBE_PRE_PULL (pad, GST_PAD_PROBE_TYPE_PULL | GST_PAD_PROBE_TYPE_BLOCK,
GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad,
"pullrange, but pad was flushing");
GST_OBJECT_UNLOCK (pad);
- return GST_FLOW_WRONG_STATE;
+ return GST_FLOW_FLUSHING;
+ }
+wrong_mode:
+ {
+ GST_ELEMENT_ERROR (GST_PAD_PARENT (pad), CORE, PAD, (NULL),
+ ("gpulltange on pad %s:%s but it was not activated in pull mode",
+ GST_DEBUG_PAD_NAME (pad)));
+ GST_OBJECT_UNLOCK (pad);
+ return GST_FLOW_ERROR;
}
pre_probe_stopped:
{
return res;
}
-/**
- * gst_pad_push_event:
- * @pad: a #GstPad to push the event to.
- * @event: (transfer full): the #GstEvent to send to the pad.
- *
- * Sends the event to the peer of the given pad. This function is
- * mainly used by elements to send events to their peer
- * elements.
- *
- * This function takes owership of the provided event so you should
- * gst_event_ref() it if you want to reuse the event after this call.
- *
- * Returns: TRUE if the event was handled.
- *
- * MT safe.
- */
-gboolean
-gst_pad_push_event (GstPad * pad, GstEvent * event)
+static GstFlowReturn
+gst_pad_push_event_unchecked (GstPad * pad, GstEvent * event,
+ GstPadProbeType type, gboolean * stored)
{
GstFlowReturn ret;
GstPad *peerpad;
- gboolean result;
- gboolean stored = FALSE;
- GstPadProbeType type;
+ GstEventType event_type;
gboolean sticky;
- g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
- g_return_val_if_fail (event != NULL, FALSE);
- g_return_val_if_fail (GST_IS_EVENT (event), FALSE);
-
- if (GST_PAD_IS_SRC (pad)) {
- if (G_UNLIKELY (!GST_EVENT_IS_DOWNSTREAM (event)))
- goto wrong_direction;
- sticky = GST_EVENT_IS_STICKY (event);
- type = GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM;
- } else if (GST_PAD_IS_SINK (pad)) {
- if (G_UNLIKELY (!GST_EVENT_IS_UPSTREAM (event)))
- goto wrong_direction;
- /* events pushed on sinkpad never are sticky */
- sticky = FALSE;
- type = GST_PAD_PROBE_TYPE_EVENT_UPSTREAM;
- } else
- goto unknown_direction;
+ sticky = GST_EVENT_IS_STICKY (event);
GST_OBJECT_LOCK (pad);
/* Two checks to be made:
* . (un)set the FLUSHING flag for flushing events,
* . handle pad blocking */
- switch (GST_EVENT_TYPE (event)) {
+ event_type = GST_EVENT_TYPE (event);
+ *stored = FALSE;
+ switch (event_type) {
case GST_EVENT_FLUSH_START:
GST_PAD_SET_FLUSHING (pad);
- if (G_UNLIKELY (GST_PAD_IS_BLOCKED (pad))) {
- /* flush start will have set the FLUSHING flag and will then
- * unlock all threads doing a GCond wait on the blocking pad. This
- * will typically unblock the STREAMING thread blocked on a pad. */
- GST_LOG_OBJECT (pad, "Pad is blocked, not forwarding flush-start, "
- "doing block signal.");
- GST_PAD_BLOCK_BROADCAST (pad);
- goto flushed;
- }
+ GST_PAD_BLOCK_BROADCAST (pad);
+ type |= GST_PAD_PROBE_TYPE_EVENT_FLUSH;
break;
case GST_EVENT_FLUSH_STOP:
GST_PAD_UNSET_FLUSHING (pad);
GST_LOG_OBJECT (pad, "Removing pending EOS events");
remove_event_by_type (pad, GST_EVENT_EOS);
- if (G_UNLIKELY (GST_PAD_IS_BLOCKED (pad))) {
- GST_LOG_OBJECT (pad, "Pad is blocked, not forwarding flush-stop");
- goto flushed;
- }
+ type |= GST_PAD_PROBE_TYPE_EVENT_FLUSH;
break;
default:
{
GST_DEBUG_OBJECT (pad, "event %s updated",
GST_EVENT_TYPE_NAME (event));
}
- stored = TRUE;
+ *stored = TRUE;
}
switch (GST_EVENT_TYPE (event)) {
GST_LOG_OBJECT (pad, "sending event %p (%s) to peerpad %" GST_PTR_FORMAT,
event, GST_EVENT_TYPE_NAME (event), peerpad);
- result = gst_pad_send_event (peerpad, event);
+ ret = gst_pad_send_event_unchecked (peerpad, event, type);
/* Note: we gave away ownership of the event at this point but we can still
* print the old pointer */
GST_LOG_OBJECT (pad,
- "sent event %p to peerpad %" GST_PTR_FORMAT ", result %d", event, peerpad,
- result);
+ "sent event %p to peerpad %" GST_PTR_FORMAT ", ret %s", event, peerpad,
+ gst_flow_get_name (ret));
gst_object_unref (peerpad);
GST_OBJECT_LOCK (pad);
if (sticky) {
- if (result) {
+ if (ret == GST_FLOW_OK) {
PadEvent *ev;
if ((ev = find_event (pad, event)))
if (pad->priv->using == 0) {
/* pad is not active anymore, trigger idle callbacks */
PROBE_NO_DATA (pad, GST_PAD_PROBE_TYPE_PUSH | GST_PAD_PROBE_TYPE_IDLE,
- idle_probe_stopped, GST_FLOW_OK);
+ idle_probe_stopped, ret);
}
GST_OBJECT_UNLOCK (pad);
- return result | stored;
+ return ret;
/* ERROR handling */
-wrong_direction:
- {
- g_warning ("pad %s:%s pushing %s event in wrong direction",
- GST_DEBUG_PAD_NAME (pad), GST_EVENT_TYPE_NAME (event));
- gst_event_unref (event);
- return FALSE;
- }
-unknown_direction:
- {
- g_warning ("pad %s:%s has invalid direction", GST_DEBUG_PAD_NAME (pad));
- gst_event_unref (event);
- return FALSE;
- }
flushed:
{
GST_DEBUG_OBJECT (pad, "We're flushing");
GST_OBJECT_UNLOCK (pad);
gst_event_unref (event);
- return stored;
+ return GST_FLOW_FLUSHING;
}
probe_stopped:
{
- GST_DEBUG_OBJECT (pad, "Probe returned %s", gst_flow_get_name (ret));
GST_OBJECT_FLAG_SET (pad, GST_PAD_FLAG_PENDING_EVENTS);
GST_OBJECT_UNLOCK (pad);
gst_event_unref (event);
- return stored;
+
+ switch (ret) {
+ case GST_FLOW_CUSTOM_SUCCESS:
+ GST_DEBUG_OBJECT (pad, "dropped event");
+ ret = GST_FLOW_OK;
+ break;
+ default:
+ GST_DEBUG_OBJECT (pad, "en error occured %s", gst_flow_get_name (ret));
+ break;
+ }
+ return ret;
+ }
+not_linked:
+ {
+ GST_DEBUG_OBJECT (pad, "Dropping event because pad is not linked");
+ GST_OBJECT_FLAG_SET (pad, GST_PAD_FLAG_PENDING_EVENTS);
+ GST_OBJECT_UNLOCK (pad);
+ gst_event_unref (event);
+ return sticky ? GST_FLOW_OK : GST_FLOW_NOT_LINKED;
}
idle_probe_stopped:
{
GST_DEBUG_OBJECT (pad, "Idle probe returned %s", gst_flow_get_name (ret));
GST_OBJECT_UNLOCK (pad);
+ return ret;
+ }
+}
+
+/**
+ * gst_pad_push_event:
+ * @pad: a #GstPad to push the event to.
+ * @event: (transfer full): the #GstEvent to send to the pad.
+ *
+ * Sends the event to the peer of the given pad. This function is
+ * mainly used by elements to send events to their peer
+ * elements.
+ *
+ * This function takes owership of the provided event so you should
+ * gst_event_ref() it if you want to reuse the event after this call.
+ *
+ * Returns: TRUE if the event was handled.
+ *
+ * MT safe.
+ */
+gboolean
+gst_pad_push_event (GstPad * pad, GstEvent * event)
+{
+ gboolean res;
+ GstPadProbeType type;
+ gboolean stored;
+
+ g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
+ g_return_val_if_fail (event != NULL, FALSE);
+ g_return_val_if_fail (GST_IS_EVENT (event), FALSE);
+
+ if (GST_PAD_IS_SRC (pad)) {
+ if (G_UNLIKELY (!GST_EVENT_IS_DOWNSTREAM (event)))
+ goto wrong_direction;
+ type = GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM;
+ } else if (GST_PAD_IS_SINK (pad)) {
+ if (G_UNLIKELY (!GST_EVENT_IS_UPSTREAM (event)))
+ goto wrong_direction;
+ /* events pushed on sinkpad never are sticky */
+ type = GST_PAD_PROBE_TYPE_EVENT_UPSTREAM;
+ } else
+ goto unknown_direction;
+
+ if (gst_pad_push_event_unchecked (pad, event, type, &stored) != GST_FLOW_OK)
+ res = stored ? TRUE : FALSE;
+ else
+ res = TRUE;
+
+ return res;
+
+ /* ERROR handling */
+wrong_direction:
+ {
+ g_warning ("pad %s:%s pushing %s event in wrong direction",
+ GST_DEBUG_PAD_NAME (pad), GST_EVENT_TYPE_NAME (event));
gst_event_unref (event);
- return stored;
+ return FALSE;
}
-not_linked:
+unknown_direction:
{
- GST_DEBUG_OBJECT (pad, "Dropping event because pad is not linked");
- GST_OBJECT_FLAG_SET (pad, GST_PAD_FLAG_PENDING_EVENTS);
- GST_OBJECT_UNLOCK (pad);
+ g_warning ("pad %s:%s has invalid direction", GST_DEBUG_PAD_NAME (pad));
gst_event_unref (event);
- return stored;
+ return FALSE;
}
}
gst_caps_unref (templ);
GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, pad,
"caps %" GST_PTR_FORMAT " not accepted", caps);
+ GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, pad,
+ "no intersection with template %" GST_PTR_FORMAT, templ);
return GST_FLOW_NOT_NEGOTIATED;
}
}
-/**
- * gst_pad_send_event:
- * @pad: a #GstPad to send the event to.
- * @event: (transfer full): the #GstEvent to send to the pad.
- *
- * Sends the event to the pad. This function can be used
- * by applications to send events in the pipeline.
- *
- * If @pad is a source pad, @event should be an upstream event. If @pad is a
- * sink pad, @event should be a downstream event. For example, you would not
- * send a #GST_EVENT_EOS on a src pad; EOS events only propagate downstream.
- * Furthermore, some downstream events have to be serialized with data flow,
- * like EOS, while some can travel out-of-band, like #GST_EVENT_FLUSH_START. If
- * the event needs to be serialized with data flow, this function will take the
- * pad's stream lock while calling its event function.
- *
- * To find out whether an event type is upstream, downstream, or downstream and
- * serialized, see #GstEventTypeFlags, gst_event_type_get_flags(),
- * #GST_EVENT_IS_UPSTREAM, #GST_EVENT_IS_DOWNSTREAM, and
- * #GST_EVENT_IS_SERIALIZED. Note that in practice that an application or
- * plugin doesn't need to bother itself with this information; the core handles
- * all necessary locks and checks.
- *
- * This function takes owership of the provided event so you should
- * gst_event_ref() it if you want to reuse the event after this call.
- *
- * Returns: TRUE if the event was handled.
- */
-gboolean
-gst_pad_send_event (GstPad * pad, GstEvent * event)
+static GstFlowReturn
+gst_pad_send_event_unchecked (GstPad * pad, GstEvent * event,
+ GstPadProbeType type)
{
GstFlowReturn ret;
- gboolean result = FALSE;
+ GstEventType event_type;
gboolean serialized, need_unlock = FALSE, sticky;
GstPadEventFunction eventfunc;
GstObject *parent;
- GstPadProbeType type;
-
- g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
- g_return_val_if_fail (event != NULL, FALSE);
-
- if (GST_PAD_IS_SINK (pad)) {
- if (G_UNLIKELY (!GST_EVENT_IS_DOWNSTREAM (event)))
- goto wrong_direction;
- serialized = GST_EVENT_IS_SERIALIZED (event);
- sticky = GST_EVENT_IS_STICKY (event);
- type = GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM;
- } else if (GST_PAD_IS_SRC (pad)) {
- if (G_UNLIKELY (!GST_EVENT_IS_UPSTREAM (event)))
- goto wrong_direction;
- /* events on srcpad never are serialized and sticky */
- serialized = sticky = FALSE;
- type = GST_PAD_PROBE_TYPE_EVENT_UPSTREAM;
- } else
- goto unknown_direction;
GST_OBJECT_LOCK (pad);
- switch (GST_EVENT_TYPE (event)) {
+ if (GST_PAD_IS_SINK (pad))
+ serialized = GST_EVENT_IS_SERIALIZED (event);
+ else
+ serialized = FALSE;
+ sticky = GST_EVENT_IS_STICKY (event);
+ event_type = GST_EVENT_TYPE (event);
+ switch (event_type) {
case GST_EVENT_FLUSH_START:
GST_CAT_DEBUG_OBJECT (GST_CAT_EVENT, pad,
"have event type %d (FLUSH_START)", GST_EVENT_TYPE (event));
if (GST_PAD_IS_SRC (pad))
GST_OBJECT_FLAG_SET (pad, GST_PAD_FLAG_NEED_RECONFIGURE);
default:
- GST_CAT_DEBUG_OBJECT (GST_CAT_EVENT, pad, "have event type %s",
- GST_EVENT_TYPE_NAME (event));
+ GST_CAT_DEBUG_OBJECT (GST_CAT_EVENT, pad,
+ "have event type %" GST_PTR_FORMAT, event);
if (G_UNLIKELY (GST_PAD_IS_FLUSHING (pad)))
goto flushing;
ACQUIRE_PARENT (pad, parent, no_parent);
GST_OBJECT_UNLOCK (pad);
- if (G_UNLIKELY (pre_eventfunc_check (pad, event) != GST_FLOW_OK))
+ ret = pre_eventfunc_check (pad, event);
+ if (G_UNLIKELY (ret != GST_FLOW_OK))
goto precheck_failed;
if (sticky)
gst_event_ref (event);
- result = eventfunc (pad, parent, event);
-
+ if (eventfunc (pad, parent, event)) {
+ ret = GST_FLOW_OK;
+ } else {
+ /* something went wrong */
+ switch (event_type) {
+ case GST_EVENT_CAPS:
+ ret = GST_FLOW_NOT_NEGOTIATED;
+ break;
+ default:
+ ret = GST_FLOW_ERROR;
+ break;
+ }
+ }
RELEASE_PARENT (parent);
+ GST_DEBUG_OBJECT (pad, "sent event, ret %s", gst_flow_get_name (ret));
+
if (sticky) {
- if (result)
+ if (ret == GST_FLOW_OK) {
/* after the event function accepted the event, we can store the sticky
* event on the pad */
gst_pad_store_sticky_event (pad, event, FALSE);
-
+ }
gst_event_unref (event);
}
if (need_unlock)
GST_PAD_STREAM_UNLOCK (pad);
- GST_DEBUG_OBJECT (pad, "sent event, result %d", result);
-
- return result;
+ return ret;
/* ERROR handling */
-wrong_direction:
+flushing:
{
- g_warning ("pad %s:%s sending %s event in wrong direction",
- GST_DEBUG_PAD_NAME (pad), GST_EVENT_TYPE_NAME (event));
+ GST_OBJECT_UNLOCK (pad);
+ if (need_unlock)
+ GST_PAD_STREAM_UNLOCK (pad);
+ GST_CAT_INFO_OBJECT (GST_CAT_EVENT, pad,
+ "Received event on flushing pad. Discarding");
gst_event_unref (event);
- return FALSE;
+ return GST_FLOW_FLUSHING;
}
-unknown_direction:
+probe_stopped:
{
- g_warning ("pad %s:%s has invalid direction", GST_DEBUG_PAD_NAME (pad));
+ GST_OBJECT_UNLOCK (pad);
+ if (need_unlock)
+ GST_PAD_STREAM_UNLOCK (pad);
gst_event_unref (event);
- return FALSE;
+
+ switch (ret) {
+ case GST_FLOW_CUSTOM_SUCCESS:
+ GST_DEBUG_OBJECT (pad, "dropped event");
+ ret = GST_FLOW_OK;
+ break;
+ default:
+ GST_DEBUG_OBJECT (pad, "en error occured %s", gst_flow_get_name (ret));
+ break;
+ }
+ return ret;
}
no_function:
{
if (need_unlock)
GST_PAD_STREAM_UNLOCK (pad);
gst_event_unref (event);
- return FALSE;
- }
-precheck_failed:
- {
- GST_DEBUG_OBJECT (pad, "pre event check failed");
- RELEASE_PARENT (parent);
- if (need_unlock)
- GST_PAD_STREAM_UNLOCK (pad);
- gst_event_unref (event);
- return FALSE;
+ return GST_FLOW_NOT_SUPPORTED;
}
no_parent:
{
if (need_unlock)
GST_PAD_STREAM_UNLOCK (pad);
gst_event_unref (event);
- return FALSE;
+ return GST_FLOW_FLUSHING;
}
-flushing:
+precheck_failed:
{
- GST_OBJECT_UNLOCK (pad);
+ GST_DEBUG_OBJECT (pad, "pre event check failed");
+ RELEASE_PARENT (parent);
if (need_unlock)
GST_PAD_STREAM_UNLOCK (pad);
- GST_CAT_INFO_OBJECT (GST_CAT_EVENT, pad,
- "Received event on flushing pad. Discarding");
+ gst_event_unref (event);
+ return ret;
+ }
+}
+
+/**
+ * gst_pad_send_event:
+ * @pad: a #GstPad to send the event to.
+ * @event: (transfer full): the #GstEvent to send to the pad.
+ *
+ * Sends the event to the pad. This function can be used
+ * by applications to send events in the pipeline.
+ *
+ * If @pad is a source pad, @event should be an upstream event. If @pad is a
+ * sink pad, @event should be a downstream event. For example, you would not
+ * send a #GST_EVENT_EOS on a src pad; EOS events only propagate downstream.
+ * Furthermore, some downstream events have to be serialized with data flow,
+ * like EOS, while some can travel out-of-band, like #GST_EVENT_FLUSH_START. If
+ * the event needs to be serialized with data flow, this function will take the
+ * pad's stream lock while calling its event function.
+ *
+ * To find out whether an event type is upstream, downstream, or downstream and
+ * serialized, see #GstEventTypeFlags, gst_event_type_get_flags(),
+ * #GST_EVENT_IS_UPSTREAM, #GST_EVENT_IS_DOWNSTREAM, and
+ * #GST_EVENT_IS_SERIALIZED. Note that in practice that an application or
+ * plugin doesn't need to bother itself with this information; the core handles
+ * all necessary locks and checks.
+ *
+ * This function takes owership of the provided event so you should
+ * gst_event_ref() it if you want to reuse the event after this call.
+ *
+ * Returns: TRUE if the event was handled.
+ */
+gboolean
+gst_pad_send_event (GstPad * pad, GstEvent * event)
+{
+ gboolean result;
+ GstPadProbeType type;
+
+ g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
+ g_return_val_if_fail (event != NULL, FALSE);
+
+ if (GST_PAD_IS_SINK (pad)) {
+ if (G_UNLIKELY (!GST_EVENT_IS_DOWNSTREAM (event)))
+ goto wrong_direction;
+ type = GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM;
+ } else if (GST_PAD_IS_SRC (pad)) {
+ if (G_UNLIKELY (!GST_EVENT_IS_UPSTREAM (event)))
+ goto wrong_direction;
+ type = GST_PAD_PROBE_TYPE_EVENT_UPSTREAM;
+ } else
+ goto unknown_direction;
+
+ if (gst_pad_send_event_unchecked (pad, event, type) != GST_FLOW_OK)
+ result = FALSE;
+ else
+ result = TRUE;
+
+ return result;
+
+ /* ERROR handling */
+wrong_direction:
+ {
+ g_warning ("pad %s:%s sending %s event in wrong direction",
+ GST_DEBUG_PAD_NAME (pad), GST_EVENT_TYPE_NAME (event));
gst_event_unref (event);
return FALSE;
}
-probe_stopped:
+unknown_direction:
{
- GST_DEBUG_OBJECT (pad, "probe returned %s", gst_flow_get_name (ret));
- GST_OBJECT_UNLOCK (pad);
- if (need_unlock)
- GST_PAD_STREAM_UNLOCK (pad);
+ g_warning ("pad %s:%s has invalid direction", GST_DEBUG_PAD_NAME (pad));
gst_event_unref (event);
return FALSE;
}