From dc38e75d88bd8921895821f7afed01cab30e46c9 Mon Sep 17 00:00:00 2001 From: Edward Hervey Date: Mon, 17 May 2010 15:04:48 +0200 Subject: [PATCH] GstPad: Add GST_PAD_NEGOTIABLE GstPadFlag A pad is 'negotiable' when its container element is in a state greater than GST_STATE_READY API:gst_pad_is_negotiable API:gst_pad_set_negotiable API:GST_PAD_NEGOTIABLE https://bugzilla.gnome.org/show_bug.cgi?id=618644 --- docs/gst/gstreamer-sections.txt | 6 ++++ gst/gstelement.c | 60 ++++++++++++++++++++++++++++++++- gst/gstpad.c | 56 ++++++++++++++++++++++++++++++ gst/gstpad.h | 9 +++++ win32/common/libgstreamer.def | 2 ++ 5 files changed, 132 insertions(+), 1 deletion(-) diff --git a/docs/gst/gstreamer-sections.txt b/docs/gst/gstreamer-sections.txt index 79f6064178..fcd3b0f2bb 100644 --- a/docs/gst/gstreamer-sections.txt +++ b/docs/gst/gstreamer-sections.txt @@ -1372,6 +1372,9 @@ gst_pad_use_fixed_caps gst_pad_is_active +gst_pad_is_negotiable +gst_pad_set_negotiable + gst_pad_set_blocked gst_pad_set_blocked_async gst_pad_set_blocked_async_full @@ -1561,6 +1564,9 @@ GST_PAD_IS_BLOCKED GST_PAD_IS_BLOCKING GST_PAD_IS_IN_SETCAPS GST_PAD_SET_FLUSHING +GST_PAD_IS_NEGOTIABLE +GST_PAD_SET_NEGOTIABLE +GST_PAD_UNSET_NEGOTIABLE GST_PAD_TASK GST_PAD_UNSET_FLUSHING diff --git a/gst/gstelement.c b/gst/gstelement.c index 0db67a3fcf..e4e149b396 100644 --- a/gst/gstelement.c +++ b/gst/gstelement.c @@ -686,7 +686,7 @@ gboolean gst_element_add_pad (GstElement * element, GstPad * pad) { gchar *pad_name; - gboolean flushing; + gboolean flushing, negotiable; g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE); g_return_val_if_fail (GST_IS_PAD (pad), FALSE); @@ -697,6 +697,7 @@ gst_element_add_pad (GstElement * element, GstPad * pad) GST_CAT_INFO_OBJECT (GST_CAT_ELEMENT_PADS, element, "adding pad '%s'", GST_STR_NULL (pad_name)); flushing = GST_PAD_IS_FLUSHING (pad); + negotiable = GST_PAD_IS_NEGOTIABLE (pad); GST_OBJECT_UNLOCK (pad); /* then check to see if there's already a pad by that name here */ @@ -709,6 +710,14 @@ gst_element_add_pad (GstElement * element, GstPad * pad) GST_OBJECT_CAST (element)))) goto had_parent; + /* sync pad state with element */ + if (!negotiable && (GST_STATE (element) > GST_STATE_NULL || + GST_STATE_NEXT (element) == GST_STATE_READY)) { + GST_OBJECT_LOCK (pad); + GST_PAD_SET_NEGOTIABLE (pad); + GST_OBJECT_UNLOCK (pad); + } + /* check for flushing pads */ if (flushing && (GST_STATE (element) > GST_STATE_READY || GST_STATE_NEXT (element) == GST_STATE_PAUSED)) { @@ -2668,6 +2677,51 @@ done: return g_value_get_boolean (&ret); } +static gboolean +negotiable_pads (GstPad * pad, GValue * ret, gboolean * active) +{ + if (!gst_pad_set_negotiable (pad, *active)) + g_value_set_boolean (ret, FALSE); + + /* unref the object that was reffed for us by _fold */ + gst_object_unref (pad); + return TRUE; +} + +/* is called with STATE_LOCK */ +static gboolean +gst_element_pads_negotiable (GstElement * element, gboolean negotiable) +{ + GstIterator *iter; + gboolean res; + + GST_CAT_DEBUG_OBJECT (GST_CAT_ELEMENT_PADS, element, + "pads_negotiable with negotiable %d", negotiable); + + /* clear the caps on all pads, this should never fail */ + iter = gst_element_iterate_pads (element); + res = + iterator_activate_fold_with_resync (iter, + (GstIteratorFoldFunction) negotiable_pads, &negotiable); + gst_iterator_free (iter); + if (G_UNLIKELY (!res)) + goto negotiable_failed; + + GST_CAT_DEBUG_OBJECT (GST_CAT_ELEMENT_PADS, element, + "pads_negotiable successful"); + + return TRUE; + + /* ERRORS */ +negotiable_failed: + { + GST_CAT_DEBUG_OBJECT (GST_CAT_ELEMENT_PADS, element, + "failed to set pads to 'negotiable'"); + return FALSE; + } +} + + /* is called with STATE_LOCK * * Pads are activated from source pads to sinkpads. @@ -2758,6 +2812,9 @@ gst_element_change_state_func (GstElement * element, GstStateChange transition) switch (transition) { case GST_STATE_CHANGE_NULL_TO_READY: + if (!gst_element_pads_negotiable (element, TRUE)) { + result = GST_STATE_CHANGE_FAILURE; + } break; case GST_STATE_CHANGE_READY_TO_PAUSED: if (!gst_element_pads_activate (element, TRUE)) { @@ -2777,6 +2834,7 @@ gst_element_change_state_func (GstElement * element, GstStateChange transition) } else { gst_element_set_base_time (element, 0); } + gst_element_pads_negotiable (element, FALSE); /* In null state release the reference to the clock */ GST_OBJECT_LOCK (element); diff --git a/gst/gstpad.c b/gst/gstpad.c index 90c8577a90..5cd434fd29 100644 --- a/gst/gstpad.c +++ b/gst/gstpad.c @@ -983,6 +983,62 @@ gst_pad_is_active (GstPad * pad) return result; } +/** + * gst_pad_is_negotiable: + * @pad: the #GstPad to query + * + * Query if a pad is negotiable + * + * Returns: TRUE if the pad is negotiable. + * + * MT safe. + * + * Since: 0.10.30 + */ +gboolean +gst_pad_is_negotiable (GstPad * pad) +{ + gboolean result = FALSE; + + g_return_val_if_fail (GST_IS_PAD (pad), FALSE); + + GST_OBJECT_LOCK (pad); + result = GST_PAD_IS_NEGOTIABLE (pad); + GST_OBJECT_UNLOCK (pad); + + return result; +} + +/** + * gst_pad_set_negotiable: + * @pad: the #GstPad to set negotiable or not + * @negotiable: whether or not the pad should be set negotiable or not + * + * Sets a pad 'negotiable' if @negotiable is TRUE. A pad in that state will + * forward pad queries. Pads are set to negotiable by their container element in + * GST_STATE_READY and unset in GST_STATE_NULL. + * + * MT safe. + * + * Returns: #TRUE if the operation was successfull. + * + * Since: 0.10.30 + */ +gboolean +gst_pad_set_negotiable (GstPad * pad, gboolean negotiable) +{ + g_return_val_if_fail (GST_IS_PAD (pad), FALSE); + + GST_OBJECT_LOCK (pad); + if (negotiable) + GST_PAD_SET_NEGOTIABLE (pad); + else + GST_PAD_UNSET_NEGOTIABLE (pad); + GST_OBJECT_UNLOCK (pad); + + return TRUE; +} + /** * gst_pad_set_blocked_async_full: * @pad: the #GstPad to block or unblock diff --git a/gst/gstpad.h b/gst/gstpad.h index 56e4320b01..979dce9647 100644 --- a/gst/gstpad.h +++ b/gst/gstpad.h @@ -541,6 +541,7 @@ typedef enum { * @GST_PAD_IN_GETCAPS: GstPadGetCapsFunction() is running now * @GST_PAD_IN_SETCAPS: GstPadSetCapsFunction() is running now * @GST_PAD_BLOCKING: is pad currently blocking on a buffer or event + * @GST_PAD_NEGOTIABLE: can pad handle caps requests. Since 0.10.30 * @GST_PAD_FLAG_LAST: offset to define more flags * * Pad state flags @@ -551,6 +552,7 @@ typedef enum { GST_PAD_IN_GETCAPS = (GST_OBJECT_FLAG_LAST << 2), GST_PAD_IN_SETCAPS = (GST_OBJECT_FLAG_LAST << 3), GST_PAD_BLOCKING = (GST_OBJECT_FLAG_LAST << 4), + GST_PAD_NEGOTIABLE = (GST_OBJECT_FLAG_LAST << 5), /* padding */ GST_PAD_FLAG_LAST = (GST_OBJECT_FLAG_LAST << 8) } GstPadFlags; @@ -746,12 +748,16 @@ struct _GstPadClass { #define GST_PAD_IS_FLUSHING(pad) (GST_OBJECT_FLAG_IS_SET (pad, GST_PAD_FLUSHING)) #define GST_PAD_IS_IN_GETCAPS(pad) (GST_OBJECT_FLAG_IS_SET (pad, GST_PAD_IN_GETCAPS)) #define GST_PAD_IS_IN_SETCAPS(pad) (GST_OBJECT_FLAG_IS_SET (pad, GST_PAD_IN_SETCAPS)) +#define GST_PAD_IS_NEGOTIABLE(pad) (GST_OBJECT_FLAG_IS_SET (pad, GST_PAD_NEGOTIABLE)) #define GST_PAD_IS_SRC(pad) (GST_PAD_DIRECTION(pad) == GST_PAD_SRC) #define GST_PAD_IS_SINK(pad) (GST_PAD_DIRECTION(pad) == GST_PAD_SINK) #define GST_PAD_SET_FLUSHING(pad) (GST_OBJECT_FLAG_SET (pad, GST_PAD_FLUSHING)) #define GST_PAD_UNSET_FLUSHING(pad) (GST_OBJECT_FLAG_UNSET (pad, GST_PAD_FLUSHING)) +#define GST_PAD_SET_NEGOTIABLE(pad) (GST_OBJECT_FLAG_SET (pad, GST_PAD_NEGOTIABLE)) +#define GST_PAD_UNSET_NEGOTIABLE(pad) (GST_OBJECT_FLAG_UNSET (pad, GST_PAD_NEGOTIABLE)) + /** * GST_PAD_GET_STREAM_LOCK: * @pad: a #GstPad @@ -971,6 +977,9 @@ gboolean gst_pad_query_default (GstPad *pad, GstQuery *query); gboolean gst_pad_dispatcher (GstPad *pad, GstPadDispatcherFunction dispatch, gpointer data); +gboolean gst_pad_is_negotiable (GstPad *pad); +gboolean gst_pad_set_negotiable (GstPad *pad, gboolean negotiable); + #ifndef GST_DISABLE_LOADSAVE void gst_pad_load_and_link (xmlNodePtr self, GstObject *parent); #endif diff --git a/win32/common/libgstreamer.def b/win32/common/libgstreamer.def index 1146b2ae37..30e5496e7e 100644 --- a/win32/common/libgstreamer.def +++ b/win32/common/libgstreamer.def @@ -612,6 +612,7 @@ EXPORTS gst_pad_is_blocked gst_pad_is_blocking gst_pad_is_linked + gst_pad_is_negotiable gst_pad_iterate_internal_links gst_pad_iterate_internal_links_default gst_pad_link @@ -665,6 +666,7 @@ EXPORTS gst_pad_set_internal_link_function gst_pad_set_iterate_internal_links_function gst_pad_set_link_function + gst_pad_set_negotiable gst_pad_set_query_function gst_pad_set_query_type_function gst_pad_set_setcaps_function