X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=gst%2Fgstpad.c;h=d2c3f0cda338953c875178aa1ac297e956250d89;hb=7b359c1d4a6b4ad95e095b3dbad5fbef1574741d;hp=4d51fcd2fa974ea2caa93a95cc05c753417727aa;hpb=f6f5451caf2e90ef64f9965c1ac32ddd0cbe190c;p=platform%2Fupstream%2Fgstreamer.git diff --git a/gst/gstpad.c b/gst/gstpad.c index 4d51fcd..d2c3f0c 100644 --- a/gst/gstpad.c +++ b/gst/gstpad.c @@ -21,6 +21,7 @@ */ /** * SECTION:gstpad + * @title: GstPad * @short_description: Object contained by elements that allows links to * other elements * @see_also: #GstPadTemplate, #GstElement, #GstEvent, #GstQuery, #GstBuffer @@ -94,6 +95,7 @@ #include "gstutils.h" #include "gstinfo.h" #include "gsterror.h" +#include "gsttracerutils.h" #include "gstvalue.h" #include "glib-compat-private.h" @@ -122,6 +124,8 @@ enum #define GST_PAD_GET_PRIVATE(obj) \ (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GST_TYPE_PAD, GstPadPrivate)) +#define _PAD_PROBE_TYPE_ALL_BOTH_AND_FLUSH (GST_PAD_PROBE_TYPE_ALL_BOTH | GST_PAD_PROBE_TYPE_EVENT_FLUSH) + /* we have a pending and an active event on the pad. On source pads only the * active event is used. On sinkpads, events are copied to the pending entry and * moved to the active event when the eventfunc returned %TRUE. */ @@ -185,6 +189,9 @@ static GstFlowReturn gst_pad_send_event_unchecked (GstPad * pad, static GstFlowReturn gst_pad_push_event_unchecked (GstPad * pad, GstEvent * event, GstPadProbeType type); +static gboolean activate_mode_internal (GstPad * pad, GstObject * parent, + GstPadMode mode, gboolean active); + static guint gst_pad_signals[LAST_SIGNAL] = { 0 }; static GParamSpec *pspec_caps = NULL; @@ -637,8 +644,8 @@ _apply_pad_offset (GstPad * pad, GstEvent * event, gboolean upstream) { gint64 offset; - GST_DEBUG_OBJECT (pad, "apply pad offset %" GST_TIME_FORMAT, - GST_TIME_ARGS (pad->offset)); + GST_DEBUG_OBJECT (pad, "apply pad offset %" GST_STIME_FORMAT, + GST_STIME_ARGS (pad->offset)); if (GST_EVENT_TYPE (event) == GST_EVENT_SEGMENT) { GstSegment segment; @@ -693,7 +700,7 @@ gst_pad_dispose (GObject * object) GstPad *pad = GST_PAD_CAST (object); GstPad *peer; - GST_CAT_DEBUG_OBJECT (GST_CAT_REFCOUNTING, pad, "dispose"); + GST_CAT_DEBUG_OBJECT (GST_CAT_REFCOUNTING, pad, "%p dispose", pad); /* unlink the peer pad */ if ((peer = gst_pad_get_peer (pad))) { @@ -923,7 +930,9 @@ gst_pad_get_direction (GstPad * pad) static gboolean gst_pad_activate_default (GstPad * pad, GstObject * parent) { - return gst_pad_activate_mode (pad, GST_PAD_MODE_PUSH, TRUE); + g_return_val_if_fail (GST_IS_PAD (pad), FALSE); + + return activate_mode_internal (pad, parent, GST_PAD_MODE_PUSH, TRUE); } /** @@ -1068,7 +1077,7 @@ gst_pad_set_active (GstPad * pad, gboolean active) } else { GST_DEBUG_OBJECT (pad, "deactivating pad from %s mode", gst_pad_mode_get_name (old)); - ret = gst_pad_activate_mode (pad, old, FALSE); + ret = activate_mode_internal (pad, parent, old, FALSE); if (ret) pad->ABI.abi.last_flowret = GST_FLOW_FLUSHING; } @@ -1102,36 +1111,18 @@ failed: } } -/** - * gst_pad_activate_mode: - * @pad: the #GstPad to activate or deactivate. - * @mode: the requested activation mode - * @active: whether or not the pad should be active. - * - * Activates or deactivates the given pad in @mode via dispatching to the - * pad's activatemodefunc. For use from within pad activation functions only. - * - * If you don't know what this is, you probably don't want to call it. - * - * Returns: %TRUE if the operation was successful. - * - * MT safe. - */ -gboolean -gst_pad_activate_mode (GstPad * pad, GstPadMode mode, gboolean active) +static gboolean +activate_mode_internal (GstPad * pad, GstObject * parent, GstPadMode mode, + gboolean active) { gboolean res = FALSE; - GstObject *parent; GstPadMode old, new; GstPadDirection dir; GstPad *peer; - g_return_val_if_fail (GST_IS_PAD (pad), FALSE); - GST_OBJECT_LOCK (pad); old = GST_PAD_MODE (pad); dir = GST_PAD_DIRECTION (pad); - ACQUIRE_PARENT (pad, parent, no_parent); GST_OBJECT_UNLOCK (pad); new = active ? mode : GST_PAD_MODE_NONE; @@ -1145,8 +1136,9 @@ gst_pad_activate_mode (GstPad * pad, GstPadMode mode, gboolean active) GST_DEBUG_OBJECT (pad, "deactivating pad from %s mode", gst_pad_mode_get_name (old)); - if (G_UNLIKELY (!gst_pad_activate_mode (pad, old, FALSE))) + if (G_UNLIKELY (!activate_mode_internal (pad, parent, old, FALSE))) goto deactivate_failed; + old = GST_PAD_MODE_NONE; } switch (mode) { @@ -1208,16 +1200,8 @@ exit_success: } exit: - RELEASE_PARENT (parent); - return res; -no_parent: - { - GST_DEBUG_OBJECT (pad, "no parent"); - GST_OBJECT_UNLOCK (pad); - return FALSE; - } was_ok: { GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad, "already %s in %s mode", @@ -1260,6 +1244,47 @@ failure: } /** + * gst_pad_activate_mode: + * @pad: the #GstPad to activate or deactivate. + * @mode: the requested activation mode + * @active: whether or not the pad should be active. + * + * Activates or deactivates the given pad in @mode via dispatching to the + * pad's activatemodefunc. For use from within pad activation functions only. + * + * If you don't know what this is, you probably don't want to call it. + * + * Returns: %TRUE if the operation was successful. + * + * MT safe. + */ +gboolean +gst_pad_activate_mode (GstPad * pad, GstPadMode mode, gboolean active) +{ + GstObject *parent; + gboolean res; + + g_return_val_if_fail (GST_IS_PAD (pad), FALSE); + + GST_OBJECT_LOCK (pad); + ACQUIRE_PARENT (pad, parent, no_parent); + GST_OBJECT_UNLOCK (pad); + + res = activate_mode_internal (pad, parent, mode, active); + + RELEASE_PARENT (parent); + + return res; + +no_parent: + { + GST_WARNING_OBJECT (pad, "no parent"); + GST_OBJECT_UNLOCK (pad); + return FALSE; + } +} + +/** * gst_pad_is_active: * @pad: the #GstPad to query * @@ -1323,6 +1348,13 @@ cleanup_hook (GstPad * pad, GHook * hook) * Be notified of different states of pads. The provided callback is called for * every state that matches @mask. * + * Probes are called in groups: First GST_PAD_PROBE_TYPE_BLOCK probes are + * called, then others, then finally GST_PAD_PROBE_TYPE_IDLE. The only + * exception here are GST_PAD_PROBE_TYPE_IDLE probes that are called + * immediately if the pad is already idle while calling gst_pad_add_probe(). + * In each of the groups, probes are called in the order in which they were + * added. + * * Returns: an id or 0 if no probe is pending. The id can be used to remove the * probe with gst_pad_remove_probe(). When using GST_PAD_PROBE_TYPE_IDLE it can * happen that the probe can be run immediately and if the probe returns @@ -1351,7 +1383,7 @@ gst_pad_add_probe (GstPad * pad, GstPadProbeType mask, /* when no contraints are given for the types, assume all types are * acceptable */ - if ((mask & GST_PAD_PROBE_TYPE_ALL_BOTH) == 0) + if ((mask & _PAD_PROBE_TYPE_ALL_BOTH_AND_FLUSH) == 0) mask |= GST_PAD_PROBE_TYPE_ALL_BOTH; if ((mask & GST_PAD_PROBE_TYPE_SCHEDULING) == 0) mask |= GST_PAD_PROBE_TYPE_SCHEDULING; @@ -1364,7 +1396,7 @@ gst_pad_add_probe (GstPad * pad, GstPadProbeType mask, PROBE_COOKIE (hook) = (pad->priv->probe_cookie - 1); /* add the probe */ - g_hook_prepend (&pad->probes, hook); + g_hook_append (&pad->probes, hook); pad->num_probes++; /* incremenent cookie so that the new hook get's called */ pad->priv->probe_list_cookie++; @@ -1818,6 +1850,53 @@ 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. + * + * Since: 1.8 + */ +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. @@ -1986,6 +2065,8 @@ gst_pad_unlink (GstPad * srcpad, GstPad * sinkpad) g_return_val_if_fail (GST_IS_PAD (sinkpad), FALSE); g_return_val_if_fail (GST_PAD_IS_SINK (sinkpad), FALSE); + GST_TRACER_PAD_UNLINK_PRE (srcpad, sinkpad); + GST_CAT_INFO (GST_CAT_ELEMENT_PADS, "unlinking %s:%s(%p) and %s:%s(%p)", GST_DEBUG_PAD_NAME (srcpad), srcpad, GST_DEBUG_PAD_NAME (sinkpad), sinkpad); @@ -2053,6 +2134,7 @@ done: GST_STRUCTURE_CHANGE_TYPE_PAD_UNLINK, parent, FALSE)); gst_object_unref (parent); } + GST_TRACER_PAD_UNLINK_POST (srcpad, sinkpad, result); return result; /* ERRORS */ @@ -2362,6 +2444,8 @@ gst_pad_link_full (GstPad * srcpad, GstPad * sinkpad, GstPadLinkCheck flags) g_return_val_if_fail (GST_PAD_IS_SINK (sinkpad), GST_PAD_LINK_WRONG_DIRECTION); + GST_TRACER_PAD_LINK_PRE (srcpad, sinkpad); + /* Notify the parent early. See gst_pad_unlink for details. */ if (G_LIKELY ((parent = GST_ELEMENT_CAST (gst_pad_get_parent (srcpad))))) { if (G_LIKELY (GST_IS_ELEMENT (parent))) { @@ -2439,7 +2523,8 @@ gst_pad_link_full (GstPad * srcpad, GstPad * sinkpad, GstPadLinkCheck flags) GST_CAT_INFO (GST_CAT_PADS, "linked %s:%s and %s:%s, successful", GST_DEBUG_PAD_NAME (srcpad), GST_DEBUG_PAD_NAME (sinkpad)); - gst_pad_send_event (srcpad, gst_event_new_reconfigure ()); + if (!(flags & GST_PAD_LINK_CHECK_NO_RECONFIGURE)) + gst_pad_send_event (srcpad, gst_event_new_reconfigure ()); done: if (G_LIKELY (parent)) { @@ -2449,6 +2534,7 @@ done: gst_object_unref (parent); } + GST_TRACER_PAD_LINK_POST (srcpad, sinkpad, result); return result; /* ERRORS */ @@ -2568,7 +2654,8 @@ gst_pad_has_current_caps (GstPad * pad) * Gets the capabilities currently configured on @pad with the last * #GST_EVENT_CAPS event. * - * Returns: the current caps of the pad with incremented ref-count. + * Returns: (transfer full) (nullable): the current caps of the pad with + * incremented ref-count or %NULL when pad has no caps. Unref after usage. */ GstCaps * gst_pad_get_current_caps (GstPad * pad) @@ -2671,16 +2758,25 @@ gst_pad_get_allowed_caps (GstPad * pad) /* Query peer caps */ query = gst_query_new_caps (mycaps); - gst_pad_peer_query (pad, query); + if (!gst_pad_peer_query (pad, query)) { + GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, pad, "Caps query failed"); + goto end; + } + gst_query_parse_caps_result (query, &caps); + if (caps == NULL) { + g_warn_if_fail (caps != NULL); + goto end; + } gst_caps_ref (caps); - gst_query_unref (query); - - gst_caps_unref (mycaps); GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, pad, "allowed caps %" GST_PTR_FORMAT, caps); +end: + gst_query_unref (query); + gst_caps_unref (mycaps); + return caps; no_peer: @@ -2965,7 +3061,7 @@ static gboolean gst_pad_query_accept_caps_default (GstPad * pad, GstQuery * query) { /* get the caps and see if it intersects to something not empty */ - GstCaps *caps, *allowed; + GstCaps *caps, *allowed = NULL; gboolean result; GST_DEBUG_OBJECT (pad, "query accept-caps %" GST_PTR_FORMAT, query); @@ -2973,19 +3069,23 @@ gst_pad_query_accept_caps_default (GstPad * pad, GstQuery * query) /* first forward the query to internally linked pads when we are dealing with * a PROXY CAPS */ if (GST_PAD_IS_PROXY_CAPS (pad)) { - if ((result = gst_pad_proxy_query_accept_caps (pad, query))) { + result = gst_pad_proxy_query_accept_caps (pad, query); + if (result) + allowed = gst_pad_get_pad_template_caps (pad); + else goto done; - } } - GST_CAT_DEBUG_OBJECT (GST_CAT_PERFORMANCE, pad, - "fallback ACCEPT_CAPS query, consider implementing a specialized version"); - gst_query_parse_accept_caps (query, &caps); - if (GST_PAD_IS_ACCEPT_TEMPLATE (pad)) - allowed = gst_pad_get_pad_template_caps (pad); - else - allowed = gst_pad_query_caps (pad, caps); + if (!allowed) { + if (GST_PAD_IS_ACCEPT_TEMPLATE (pad)) { + allowed = gst_pad_get_pad_template_caps (pad); + } else { + GST_CAT_DEBUG_OBJECT (GST_CAT_PERFORMANCE, pad, + "fallback ACCEPT_CAPS query, consider implementing a specialized version"); + allowed = gst_pad_query_caps (pad, caps); + } + } if (allowed) { if (GST_PAD_IS_ACCEPT_INTERSECT (pad)) { @@ -3084,6 +3184,7 @@ done: /* Default latency implementation */ typedef struct { + guint count; gboolean live; GstClockTime min, max; } LatencyFoldData; @@ -3115,7 +3216,8 @@ query_latency_default_fold (const GValue * item, GValue * ret, GST_LOG_OBJECT (pad, "got latency live:%s min:%" G_GINT64_FORMAT " max:%" G_GINT64_FORMAT, live ? "true" : "false", min, max); - if (live) { + /* FIXME : Why do we only take values into account if it's live ? */ + if (live || fold_data->count == 0) { if (min > fold_data->min) fold_data->min = min; @@ -3124,8 +3226,9 @@ query_latency_default_fold (const GValue * item, GValue * ret, else if (max < fold_data->max) fold_data->max = max; - fold_data->live = TRUE; + fold_data->live = live; } + fold_data->count += 1; } else if (peer) { GST_DEBUG_OBJECT (pad, "latency query failed"); g_value_set_boolean (ret, FALSE); @@ -3156,6 +3259,7 @@ gst_pad_query_latency_default (GstPad * pad, GstQuery * query) g_value_init (&ret, G_TYPE_BOOLEAN); retry: + fold_data.count = 0; fold_data.live = FALSE; fold_data.min = 0; fold_data.max = GST_CLOCK_TIME_NONE; @@ -3317,13 +3421,25 @@ probe_hook_marshal (GHook * hook, ProbeMarshall * data) type = info->type; original_data = info->data; - /* one of the data types for non-idle probes */ - if ((type & GST_PAD_PROBE_TYPE_IDLE) == 0 - && (flags & GST_PAD_PROBE_TYPE_ALL_BOTH & type) == 0) - goto no_match; /* one of the scheduling types */ if ((flags & GST_PAD_PROBE_TYPE_SCHEDULING & type) == 0) goto no_match; + + if (type & GST_PAD_PROBE_TYPE_PUSH) { + /* one of the data types for non-idle probes */ + if ((type & GST_PAD_PROBE_TYPE_IDLE) == 0 + && (flags & _PAD_PROBE_TYPE_ALL_BOTH_AND_FLUSH & type) == 0) + goto no_match; + } else if (type & GST_PAD_PROBE_TYPE_PULL) { + /* one of the data types for non-idle probes */ + if ((type & GST_PAD_PROBE_TYPE_BLOCKING) == 0 + && (flags & _PAD_PROBE_TYPE_ALL_BOTH_AND_FLUSH & type) == 0) + goto no_match; + } else { + /* Type must have PULL or PUSH probe types */ + g_assert_not_reached (); + } + /* one of the blocking types must match */ if ((type & GST_PAD_PROBE_TYPE_BLOCKING) && (flags & GST_PAD_PROBE_TYPE_BLOCKING & type) == 0) @@ -3640,7 +3756,8 @@ gst_pad_set_offset (GstPad * pad, gint64 offset) goto done; pad->offset = offset; - GST_DEBUG_OBJECT (pad, "changed offset to %" G_GINT64_FORMAT, offset); + GST_DEBUG_OBJECT (pad, "changed offset to %" GST_STIME_FORMAT, + GST_STIME_ARGS (offset)); /* resend all sticky events with updated offset on next buffer push */ events_foreach (pad, mark_event_not_received, NULL); @@ -3713,11 +3830,12 @@ push_sticky (GstPad * pad, PadEvent * ev, gpointer user_data) break; case GST_FLOW_NOT_LINKED: /* not linked is not a problem, we are sticky so the event will be - * sent later but only for non-EOS events */ + * rescheduled to be sent later on re-link, but only for non-EOS events */ GST_DEBUG_OBJECT (pad, "pad was not linked, mark pending"); - if (GST_EVENT_TYPE (event) != GST_EVENT_EOS) + if (GST_EVENT_TYPE (event) != GST_EVENT_EOS) { data->ret = GST_FLOW_OK; - GST_OBJECT_FLAG_SET (pad, GST_PAD_FLAG_PENDING_EVENTS); + ev->received = TRUE; + } break; default: GST_DEBUG_OBJECT (pad, "result %s, mark pending events", @@ -3812,6 +3930,7 @@ gst_pad_query (GstPad * pad, GstQuery * query) GST_DEBUG_OBJECT (pad, "doing query %p (%s)", query, GST_QUERY_TYPE_NAME (query)); + GST_TRACER_PAD_QUERY_PRE (pad, query); serialized = GST_QUERY_IS_SERIALIZED (query); if (G_UNLIKELY (serialized)) @@ -3834,6 +3953,7 @@ gst_pad_query (GstPad * pad, GstQuery * query) GST_DEBUG_OBJECT (pad, "sent query %p (%s), result %d", query, GST_QUERY_TYPE_NAME (query), res); + GST_TRACER_PAD_QUERY_POST (pad, query, res); if (res != TRUE) goto query_failed; @@ -4043,7 +4163,7 @@ gst_pad_chain_data_unchecked (GstPad * pad, GstPadProbeType type, void *data) if (G_UNLIKELY (GST_PAD_MODE (pad) != GST_PAD_MODE_PUSH)) goto wrong_mode; -#ifndef G_DISABLE_ASSERT +#ifdef GST_ENABLE_EXTRA_CHECKS if (G_UNLIKELY (pad->priv->last_cookie != pad->priv->events_cookie)) { if (!find_event_by_type (pad, GST_EVENT_STREAM_START, 0)) { g_warning (G_STRLOC @@ -4296,7 +4416,7 @@ gst_pad_push_data (GstPad * pad, GstPadProbeType type, void *data) if (G_UNLIKELY (GST_PAD_MODE (pad) != GST_PAD_MODE_PUSH)) goto wrong_mode; -#ifndef G_DISABLE_ASSERT +#ifdef GST_ENABLE_EXTRA_CHECKS if (G_UNLIKELY (pad->priv->last_cookie != pad->priv->events_cookie)) { if (!find_event_by_type (pad, GST_EVENT_STREAM_START, 0)) { g_warning (G_STRLOC @@ -4446,12 +4566,17 @@ not_linked: GstFlowReturn gst_pad_push (GstPad * pad, GstBuffer * buffer) { + GstFlowReturn res; + g_return_val_if_fail (GST_IS_PAD (pad), GST_FLOW_ERROR); g_return_val_if_fail (GST_PAD_IS_SRC (pad), GST_FLOW_ERROR); g_return_val_if_fail (GST_IS_BUFFER (buffer), GST_FLOW_ERROR); - return gst_pad_push_data (pad, + GST_TRACER_PAD_PUSH_PRE (pad, buffer); + res = gst_pad_push_data (pad, GST_PAD_PROBE_TYPE_BUFFER | GST_PAD_PROBE_TYPE_PUSH, buffer); + GST_TRACER_PAD_PUSH_POST (pad, res); + return res; } /** @@ -4481,12 +4606,17 @@ gst_pad_push (GstPad * pad, GstBuffer * buffer) GstFlowReturn gst_pad_push_list (GstPad * pad, GstBufferList * list) { + GstFlowReturn res; + g_return_val_if_fail (GST_IS_PAD (pad), GST_FLOW_ERROR); g_return_val_if_fail (GST_PAD_IS_SRC (pad), GST_FLOW_ERROR); g_return_val_if_fail (GST_IS_BUFFER_LIST (list), GST_FLOW_ERROR); - return gst_pad_push_data (pad, + GST_TRACER_PAD_PUSH_LIST_PRE (pad, list); + res = gst_pad_push_data (pad, GST_PAD_PROBE_TYPE_BUFFER_LIST | GST_PAD_PROBE_TYPE_PUSH, list); + GST_TRACER_PAD_PUSH_LIST_POST (pad, res); + return res; } static GstFlowReturn @@ -4750,6 +4880,8 @@ gst_pad_pull_range (GstPad * pad, guint64 offset, guint size, g_return_val_if_fail (*buffer == NULL || (GST_IS_BUFFER (*buffer) && gst_buffer_get_size (*buffer) >= size), GST_FLOW_ERROR); + GST_TRACER_PAD_PULL_RANGE_PRE (pad, offset, size); + GST_OBJECT_LOCK (pad); if (G_UNLIKELY (GST_PAD_IS_FLUSHING (pad))) goto flushing; @@ -4796,6 +4928,7 @@ probed_data: *buffer = res_buf; + GST_TRACER_PAD_PULL_RANGE_POST (pad, *buffer, ret); return ret; /* ERROR recovery here */ @@ -4805,7 +4938,8 @@ flushing: "pullrange, but pad was flushing"); pad->ABI.abi.last_flowret = GST_FLOW_FLUSHING; GST_OBJECT_UNLOCK (pad); - return GST_FLOW_FLUSHING; + ret = GST_FLOW_FLUSHING; + goto done; } wrong_mode: { @@ -4813,7 +4947,8 @@ wrong_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_ERROR; + goto done; } probe_stopped: { @@ -4834,7 +4969,7 @@ probe_stopped: } pad->ABI.abi.last_flowret = ret; GST_OBJECT_UNLOCK (pad); - return ret; + goto done; } not_linked: { @@ -4842,7 +4977,8 @@ not_linked: "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; + ret = GST_FLOW_NOT_LINKED; + goto done; } pull_range_failed: { @@ -4851,7 +4987,7 @@ pull_range_failed: GST_CAT_LEVEL_LOG (GST_CAT_SCHEDULING, (ret >= GST_FLOW_EOS) ? GST_LEVEL_INFO : GST_LEVEL_WARNING, pad, "pullrange failed, flow: %s", gst_flow_get_name (ret)); - return ret; + goto done; } probe_stopped_unref: { @@ -4867,8 +5003,11 @@ probe_stopped_unref: if (*buffer == NULL) gst_buffer_unref (res_buf); - return ret; + goto done; } +done: + GST_TRACER_PAD_PULL_RANGE_POST (pad, NULL, ret); + return ret; } /* must be called with pad object lock */ @@ -4896,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); } @@ -4993,7 +5133,7 @@ eos: /** * gst_pad_store_sticky_event: * @pad: a #GstPad - * @event: a #GstEvent + * @event: (transfer none): a #GstEvent * * Store the sticky @event on @pad * @@ -5063,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; @@ -5217,6 +5358,8 @@ gst_pad_push_event (GstPad * pad, GstEvent * event) g_return_val_if_fail (GST_IS_PAD (pad), FALSE); g_return_val_if_fail (GST_IS_EVENT (event), FALSE); + GST_TRACER_PAD_PUSH_EVENT_PRE (pad, event); + if (GST_PAD_IS_SRC (pad)) { if (G_UNLIKELY (!GST_EVENT_IS_DOWNSTREAM (event))) goto wrong_direction; @@ -5271,6 +5414,7 @@ gst_pad_push_event (GstPad * pad, GstEvent * event) } GST_OBJECT_UNLOCK (pad); + GST_TRACER_PAD_PUSH_EVENT_POST (pad, res); return res; /* ERROR handling */ @@ -5279,28 +5423,31 @@ 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; + goto done; } unknown_direction: { g_warning ("pad %s:%s has invalid direction", GST_DEBUG_PAD_NAME (pad)); gst_event_unref (event); - return FALSE; + goto done; } flushed: { GST_DEBUG_OBJECT (pad, "We're flushing"); GST_OBJECT_UNLOCK (pad); gst_event_unref (event); - return FALSE; + goto done; } eos: { GST_DEBUG_OBJECT (pad, "We're EOS"); GST_OBJECT_UNLOCK (pad); gst_event_unref (event); - return FALSE; + goto done; } +done: + GST_TRACER_PAD_PUSH_EVENT_POST (pad, FALSE); + return FALSE; } /* Check if we can call the event function with the given event */ @@ -5341,6 +5488,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); @@ -5380,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; @@ -5407,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: @@ -5438,7 +5588,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); @@ -5451,7 +5603,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 */ @@ -5920,6 +6074,42 @@ no_task: } /** + * gst_pad_get_task_state: + * @pad: the #GstPad to get task state from + * + * Get @pad task state. If no task is currently + * set, #GST_TASK_STOPPED is returned. + * + * Returns: The current state of @pad's task. + * + * Since: 1.12 + */ +GstTaskState +gst_pad_get_task_state (GstPad * pad) +{ + GstTask *task; + GstTaskState res; + + g_return_val_if_fail (GST_IS_PAD (pad), GST_TASK_STOPPED); + + GST_OBJECT_LOCK (pad); + task = GST_PAD_TASK (pad); + if (task == NULL) + goto no_task; + res = gst_task_get_state (task); + GST_OBJECT_UNLOCK (pad); + + return res; + +no_task: + { + GST_DEBUG_OBJECT (pad, "pad has no task"); + GST_OBJECT_UNLOCK (pad); + return GST_TASK_STOPPED; + } +} + +/** * gst_pad_stop_task: * @pad: the #GstPad to stop the task of * @@ -6042,7 +6232,7 @@ gst_pad_probe_info_get_buffer (GstPadProbeInfo * info) * gst_pad_probe_info_get_buffer_list: * @info: a #GstPadProbeInfo * - * Returns: (transfer none): The #GstBufferlist from the probe + * Returns: (transfer none): The #GstBufferList from the probe */ GstBufferList *