diff -r 567bb019e3e3 -r 7e817e7e631c gstreamer_core/gst/gstghostpad.c --- a/gstreamer_core/gst/gstghostpad.c Tue Aug 31 15:30:33 2010 +0300 +++ b/gstreamer_core/gst/gstghostpad.c Wed Sep 01 12:16:41 2010 +0100 @@ -56,24 +56,43 @@ #define GST_CAT_DEFAULT GST_CAT_PADS +#define GST_TYPE_PROXY_PAD (gst_proxy_pad_get_type ()) +#define GST_IS_PROXY_PAD(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_PROXY_PAD)) +#define GST_IS_PROXY_PAD_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_PROXY_PAD)) +#define GST_PROXY_PAD(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_PROXY_PAD, GstProxyPad)) +#define GST_PROXY_PAD_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_PROXY_PAD, GstProxyPadClass)) #define GST_PROXY_PAD_CAST(obj) ((GstProxyPad *)obj) -#define GST_PROXY_PAD_PRIVATE(obj) (GST_PROXY_PAD_CAST (obj)->priv) -#define GST_PROXY_PAD_TARGET(pad) (GST_PROXY_PAD_PRIVATE (pad)->target) -#define GST_PROXY_PAD_INTERNAL(pad) (GST_PROXY_PAD_PRIVATE (pad)->internal) -#define GST_PROXY_PAD_RETARGET(pad) (GST_PROXY_PAD_PRIVATE (pad)->retarget) -#define GST_PROXY_GET_LOCK(pad) (GST_PROXY_PAD_PRIVATE (pad)->proxy_lock) + +#define GST_PROXY_PAD_TARGET(pad) (GST_PROXY_PAD_CAST (pad)->target) +#define GST_PROXY_PAD_INTERNAL(pad) (GST_PROXY_PAD_CAST (pad)->internal) + +typedef struct _GstProxyPad GstProxyPad; +typedef struct _GstProxyPadClass GstProxyPadClass; + +#define GST_PROXY_GET_LOCK(pad) (GST_PROXY_PAD_CAST (pad)->proxy_lock) #define GST_PROXY_LOCK(pad) (g_mutex_lock (GST_PROXY_GET_LOCK (pad))) #define GST_PROXY_UNLOCK(pad) (g_mutex_unlock (GST_PROXY_GET_LOCK (pad))) -struct _GstProxyPadPrivate +struct _GstProxyPad { + GstPad pad; + /* with PROXY_LOCK */ GMutex *proxy_lock; GstPad *target; GstPad *internal; - gboolean retarget; }; +struct _GstProxyPadClass +{ + GstPadClass parent_class; + + /*< private > */ + gpointer _gst_reserved[1]; +}; + +static GType gst_proxy_pad_get_type (void); + G_DEFINE_TYPE (GstProxyPad, gst_proxy_pad, GST_TYPE_PAD); static GstPad *gst_proxy_pad_get_target (GstPad * pad); @@ -86,17 +105,12 @@ xmlNodePtr parent); #endif -static void on_src_target_notify (GstPad * target, - GParamSpec * unused, GstGhostPad * pad); - static void gst_proxy_pad_class_init (GstProxyPadClass * klass) { GObjectClass *gobject_class = (GObjectClass *) klass; - g_type_class_add_private (klass, sizeof (GstProxyPadPrivate)); - gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_proxy_pad_dispose); gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_proxy_pad_finalize); @@ -148,14 +162,14 @@ return res; } -static GstIterator * -gst_proxy_pad_do_iterate_internal_links (GstPad * pad) +static GList * +gst_proxy_pad_do_internal_link (GstPad * pad) { - GstIterator *res = NULL; + GList *res = NULL; GstPad *target = gst_proxy_pad_get_target (pad); if (target) { - res = gst_pad_iterate_internal_links (target); + res = gst_pad_get_internal_links (target); gst_object_unref (target); } @@ -186,17 +200,6 @@ } static GstFlowReturn -gst_proxy_pad_do_chain_list (GstPad * pad, GstBufferList * list) -{ - GstFlowReturn res; - GstPad *internal = GST_PROXY_PAD_INTERNAL (pad); - - res = gst_pad_push_list (internal, list); - - return res; -} - -static GstFlowReturn gst_proxy_pad_do_getrange (GstPad * pad, guint64 offset, guint size, GstBuffer ** buffer) { @@ -231,8 +234,7 @@ res = gst_pad_get_caps (target); gst_object_unref (target); - GST_DEBUG_OBJECT (pad, "get caps of target %s:%s : %" GST_PTR_FORMAT, - GST_DEBUG_PAD_NAME (target), res); + GST_DEBUG_OBJECT (pad, "get caps of target: %" GST_PTR_FORMAT, res); /* filter against the template */ if (templ && res) { @@ -329,9 +331,9 @@ GST_LOG_OBJECT (pad, "clearing target"); /* clear old target */ - if ((oldtarget = GST_PROXY_PAD_TARGET (pad))) + if ((oldtarget = GST_PROXY_PAD_TARGET (pad))) { gst_object_unref (oldtarget); - + } /* set and ref new target if any */ if (target) GST_PROXY_PAD_TARGET (pad) = gst_object_ref (target); @@ -376,24 +378,6 @@ } static void -gst_proxy_pad_do_unlink (GstPad * pad) -{ - GstPad *internal; - - /* don't do anything if this unlink resulted from retargeting the pad - * controlled by the ghostpad. We only want to invalidate the target pad when - * the element suddently unlinked with our internal pad. */ - if (GST_PROXY_PAD_RETARGET (pad)) - return; - - internal = GST_PROXY_PAD_INTERNAL (pad); - - GST_DEBUG_OBJECT (pad, "pad is unlinked"); - - gst_proxy_pad_set_target (internal, NULL); -} - -static void gst_proxy_pad_dispose (GObject * object) { GstPad *pad = GST_PAD (object); @@ -416,8 +400,8 @@ { GstProxyPad *pad = GST_PROXY_PAD (object); - g_mutex_free (GST_PROXY_GET_LOCK (pad)); - GST_PROXY_GET_LOCK (pad) = NULL; + g_mutex_free (pad->proxy_lock); + pad->proxy_lock = NULL; G_OBJECT_CLASS (gst_proxy_pad_parent_class)->finalize (object); } @@ -427,16 +411,14 @@ { GstPad *pad = (GstPad *) ppad; - GST_PROXY_PAD_PRIVATE (ppad) = G_TYPE_INSTANCE_GET_PRIVATE (ppad, - GST_TYPE_PROXY_PAD, GstProxyPadPrivate); - GST_PROXY_GET_LOCK (pad) = g_mutex_new (); + ppad->proxy_lock = g_mutex_new (); gst_pad_set_query_type_function (pad, GST_DEBUG_FUNCPTR (gst_proxy_pad_do_query_type)); gst_pad_set_event_function (pad, GST_DEBUG_FUNCPTR (gst_proxy_pad_do_event)); gst_pad_set_query_function (pad, GST_DEBUG_FUNCPTR (gst_proxy_pad_do_query)); - gst_pad_set_iterate_internal_links_function (pad, - GST_DEBUG_FUNCPTR (gst_proxy_pad_do_iterate_internal_links)); + gst_pad_set_internal_link_function (pad, + GST_DEBUG_FUNCPTR (gst_proxy_pad_do_internal_link)); gst_pad_set_getcaps_function (pad, GST_DEBUG_FUNCPTR (gst_proxy_pad_do_getcaps)); @@ -446,8 +428,6 @@ GST_DEBUG_FUNCPTR (gst_proxy_pad_do_fixatecaps)); gst_pad_set_setcaps_function (pad, GST_DEBUG_FUNCPTR (gst_proxy_pad_do_setcaps)); - gst_pad_set_unlink_function (pad, - GST_DEBUG_FUNCPTR (gst_proxy_pad_do_unlink)); } #ifndef GST_DISABLE_LOADSAVE @@ -510,16 +490,26 @@ */ -#define GST_GHOST_PAD_PRIVATE(obj) (GST_GHOST_PAD_CAST (obj)->priv) +struct _GstGhostPad +{ + GstProxyPad pad; -struct _GstGhostPadPrivate -{ /* with PROXY_LOCK */ gulong notify_id; - gboolean constructed; + /*< private > */ + gpointer _gst_reserved[GST_PADDING]; }; +struct _GstGhostPadClass +{ + GstProxyPadClass parent_class; + + /*< private > */ + gpointer _gst_reserved[GST_PADDING]; +}; + + G_DEFINE_TYPE (GstGhostPad, gst_ghost_pad, GST_TYPE_PROXY_PAD); static void gst_ghost_pad_dispose (GObject * object); @@ -529,8 +519,6 @@ { GObjectClass *gobject_class = (GObjectClass *) klass; - g_type_class_add_private (klass, sizeof (GstGhostPadPrivate)); - gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_ghost_pad_dispose); } @@ -674,74 +662,44 @@ static void gst_ghost_pad_do_unlink (GstPad * pad) { + GstPad *target; GstPad *internal; + target = gst_proxy_pad_get_target (pad); internal = GST_PROXY_PAD_INTERNAL (pad); GST_DEBUG_OBJECT (pad, "unlinking ghostpad"); /* The target of the internal pad is no longer valid */ gst_proxy_pad_set_target (internal, NULL); + + if (target) { + if (GST_PAD_UNLINKFUNC (target)) + GST_PAD_UNLINKFUNC (target) (target); + + gst_object_unref (target); + } } static void on_int_notify (GstPad * internal, GParamSpec * unused, GstGhostPad * pad) { GstCaps *caps; - gboolean changed; g_object_get (internal, "caps", &caps, NULL); GST_OBJECT_LOCK (pad); - changed = (GST_PAD_CAPS (pad) != caps); - if (changed) - gst_caps_replace (&(GST_PAD_CAPS (pad)), caps); + gst_caps_replace (&(GST_PAD_CAPS (pad)), caps); GST_OBJECT_UNLOCK (pad); - if (changed) - g_object_notify (G_OBJECT (pad), "caps"); - + g_object_notify (G_OBJECT (pad), "caps"); if (caps) gst_caps_unref (caps); } static void -on_src_target_notify (GstPad * target, GParamSpec * unused, GstGhostPad * pad) -{ - GstCaps *caps; - gboolean changed; - - g_object_get (target, "caps", &caps, NULL); - - GST_OBJECT_LOCK (pad); - changed = (GST_PAD_CAPS (pad) != caps); - gst_caps_replace (&(GST_PAD_CAPS (pad)), caps); - GST_OBJECT_UNLOCK (pad); - - if (changed) - g_object_notify (G_OBJECT (pad), "caps"); - - if (caps) - gst_caps_unref (caps); -} - -static gboolean -gst_ghost_pad_do_setcaps (GstPad * pad, GstCaps * caps) -{ - if (GST_PAD_DIRECTION (pad) == GST_PAD_SRC) - return TRUE; - - return gst_proxy_pad_do_setcaps (pad, caps); -} - -static void gst_ghost_pad_init (GstGhostPad * pad) { - GST_GHOST_PAD_PRIVATE (pad) = G_TYPE_INSTANCE_GET_PRIVATE (pad, - GST_TYPE_GHOST_PAD, GstGhostPadPrivate); - - gst_pad_set_setcaps_function (GST_PAD_CAST (pad), - GST_DEBUG_FUNCPTR (gst_ghost_pad_do_setcaps)); gst_pad_set_activatepull_function (GST_PAD_CAST (pad), GST_DEBUG_FUNCPTR (gst_ghost_pad_do_activate_pull)); gst_pad_set_activatepush_function (GST_PAD_CAST (pad), @@ -753,109 +711,85 @@ { GstPad *pad; GstPad *internal; - GstPad *peer; + GstPad *intpeer; pad = GST_PAD (object); GST_DEBUG_OBJECT (pad, "dispose"); - gst_ghost_pad_set_target (GST_GHOST_PAD (pad), NULL); - - /* Unlink here so that gst_pad_dispose doesn't. That would lead to a call to - * gst_ghost_pad_do_unlink when the ghost pad is in an inconsistent state */ - peer = gst_pad_get_peer (pad); - if (peer) { - if (GST_PAD_IS_SRC (pad)) - gst_pad_unlink (pad, peer); - else - gst_pad_unlink (peer, pad); - - gst_object_unref (peer); - } - GST_PROXY_LOCK (pad); internal = GST_PROXY_PAD_INTERNAL (pad); gst_pad_set_activatepull_function (internal, NULL); gst_pad_set_activatepush_function (internal, NULL); - g_signal_handler_disconnect (internal, - GST_GHOST_PAD_PRIVATE (pad)->notify_id); + g_signal_handler_disconnect (internal, GST_GHOST_PAD_CAST (pad)->notify_id); + + intpeer = gst_pad_get_peer (internal); + if (intpeer) { + if (GST_PAD_IS_SRC (internal)) + gst_pad_unlink (internal, intpeer); + else + gst_pad_unlink (intpeer, internal); + + gst_object_unref (intpeer); + } + + GST_PROXY_PAD_INTERNAL (internal) = NULL; /* disposes of the internal pad, since the ghostpad is the only possible object * that has a refcount on the internal pad. */ gst_object_unparent (GST_OBJECT_CAST (internal)); - GST_PROXY_PAD_INTERNAL (pad) = NULL; GST_PROXY_UNLOCK (pad); G_OBJECT_CLASS (gst_ghost_pad_parent_class)->dispose (object); } -/** - * gst_ghost_pad_construct: - * @gpad: the newly allocated ghost pad - * - * Finish initialization of a newly allocated ghost pad. - * - * This function is most useful in language bindings and when subclassing - * #GstGhostPad; plugin and application developers normally will not call this - * function. Call this function directly after a call to g_object_new - * (GST_TYPE_GHOST_PAD, "direction", @dir, ..., NULL). - * - * Returns: %TRUE if the construction succeeds, %FALSE otherwise. - * - * Since: 0.10.22 - */ -#ifdef __SYMBIAN32__ -EXPORT_C -#endif +static GstPad * +gst_ghost_pad_new_full (const gchar * name, GstPadDirection dir, + GstPadTemplate * templ) +{ + GstPad *ret; + GstPad *internal; + GstPadDirection otherdir; -gboolean -gst_ghost_pad_construct (GstGhostPad * gpad) -{ - GstPadDirection dir, otherdir; - GstPadTemplate *templ; - GstPad *pad, *internal; + g_return_val_if_fail (dir != GST_PAD_UNKNOWN, NULL); - g_return_val_if_fail (GST_IS_GHOST_PAD (gpad), FALSE); - g_return_val_if_fail (GST_GHOST_PAD_PRIVATE (gpad)->constructed == FALSE, - FALSE); - - g_object_get (gpad, "direction", &dir, "template", &templ, NULL); - - g_return_val_if_fail (dir != GST_PAD_UNKNOWN, FALSE); - - pad = GST_PAD (gpad); + /* OBJECT CREATION */ + if (templ) { + ret = g_object_new (GST_TYPE_GHOST_PAD, "name", name, + "direction", dir, "template", templ, NULL); + } else { + ret = g_object_new (GST_TYPE_GHOST_PAD, "name", name, + "direction", dir, NULL); + } /* Set directional padfunctions for ghostpad */ if (dir == GST_PAD_SINK) { - gst_pad_set_bufferalloc_function (pad, + gst_pad_set_bufferalloc_function (ret, GST_DEBUG_FUNCPTR (gst_proxy_pad_do_bufferalloc)); - gst_pad_set_chain_function (pad, + gst_pad_set_chain_function (ret, GST_DEBUG_FUNCPTR (gst_proxy_pad_do_chain)); - gst_pad_set_chain_list_function (pad, - GST_DEBUG_FUNCPTR (gst_proxy_pad_do_chain_list)); } else { - gst_pad_set_getrange_function (pad, + gst_pad_set_getrange_function (ret, GST_DEBUG_FUNCPTR (gst_proxy_pad_do_getrange)); - gst_pad_set_checkgetrange_function (pad, + gst_pad_set_checkgetrange_function (ret, GST_DEBUG_FUNCPTR (gst_proxy_pad_do_checkgetrange)); } /* link/unlink functions */ - gst_pad_set_link_function (pad, GST_DEBUG_FUNCPTR (gst_ghost_pad_do_link)); - gst_pad_set_unlink_function (pad, + gst_pad_set_link_function (ret, GST_DEBUG_FUNCPTR (gst_ghost_pad_do_link)); + gst_pad_set_unlink_function (ret, GST_DEBUG_FUNCPTR (gst_ghost_pad_do_unlink)); + /* INTERNAL PAD, it always exists and is child of the ghostpad */ otherdir = (dir == GST_PAD_SRC) ? GST_PAD_SINK : GST_PAD_SRC; if (templ) { internal = g_object_new (GST_TYPE_PROXY_PAD, "name", NULL, "direction", otherdir, "template", templ, NULL); - /* release ref obtained via g_object_get */ - gst_object_unref (templ); } else { internal = g_object_new (GST_TYPE_PROXY_PAD, "name", NULL, @@ -869,8 +803,6 @@ GST_DEBUG_FUNCPTR (gst_proxy_pad_do_bufferalloc)); gst_pad_set_chain_function (internal, GST_DEBUG_FUNCPTR (gst_proxy_pad_do_chain)); - gst_pad_set_chain_list_function (internal, - GST_DEBUG_FUNCPTR (gst_proxy_pad_do_chain_list)); } else { gst_pad_set_getrange_function (internal, GST_DEBUG_FUNCPTR (gst_proxy_pad_do_getrange)); @@ -878,11 +810,11 @@ GST_DEBUG_FUNCPTR (gst_proxy_pad_do_checkgetrange)); } - GST_PROXY_LOCK (pad); + GST_PROXY_LOCK (ret); /* now make the ghostpad a parent of the internal pad */ if (!gst_object_set_parent (GST_OBJECT_CAST (internal), - GST_OBJECT_CAST (pad))) + GST_OBJECT_CAST (ret))) goto parent_failed; /* The ghostpad is the parent of the internal pad and is the only object that @@ -893,17 +825,17 @@ * it's refcount on the internal pad in the dispose method by un-parenting it. * This is why we don't take extra refcounts in the assignments below */ - GST_PROXY_PAD_INTERNAL (pad) = internal; - GST_PROXY_PAD_INTERNAL (internal) = pad; + GST_PROXY_PAD_INTERNAL (ret) = internal; + GST_PROXY_PAD_INTERNAL (internal) = ret; /* could be more general here, iterating over all writable properties... * taking the short road for now tho */ - GST_GHOST_PAD_PRIVATE (pad)->notify_id = + GST_GHOST_PAD_CAST (ret)->notify_id = g_signal_connect (internal, "notify::caps", G_CALLBACK (on_int_notify), - pad); + ret); /* call function to init values of the pad caps */ - on_int_notify (internal, NULL, GST_GHOST_PAD_CAST (pad)); + on_int_notify (internal, NULL, GST_GHOST_PAD_CAST (ret)); /* special activation functions for the internal pad */ gst_pad_set_activatepull_function (internal, @@ -911,52 +843,24 @@ gst_pad_set_activatepush_function (internal, GST_DEBUG_FUNCPTR (gst_ghost_pad_internal_do_activate_push)); - GST_PROXY_UNLOCK (pad); + GST_PROXY_UNLOCK (ret); - GST_GHOST_PAD_PRIVATE (gpad)->constructed = TRUE; - return TRUE; + return ret; /* ERRORS */ parent_failed: { - GST_WARNING_OBJECT (gpad, "Could not set internal pad %s:%s", + GST_WARNING_OBJECT (ret, "Could not set internal pad %s:%s", GST_DEBUG_PAD_NAME (internal)); g_critical ("Could not set internal pad %s:%s", GST_DEBUG_PAD_NAME (internal)); - GST_PROXY_UNLOCK (pad); + GST_PROXY_UNLOCK (ret); + gst_object_unref (ret); gst_object_unref (internal); - return FALSE; + return NULL; } } -static GstPad * -gst_ghost_pad_new_full (const gchar * name, GstPadDirection dir, - GstPadTemplate * templ) -{ - GstGhostPad *ret; - - g_return_val_if_fail (dir != GST_PAD_UNKNOWN, NULL); - - /* OBJECT CREATION */ - if (templ) { - ret = g_object_new (GST_TYPE_GHOST_PAD, "name", name, - "direction", dir, "template", templ, NULL); - } else { - ret = g_object_new (GST_TYPE_GHOST_PAD, "name", name, - "direction", dir, NULL); - } - - if (!gst_ghost_pad_construct (ret)) - goto construct_failed; - - return GST_PAD (ret); - -construct_failed: - /* already logged */ - gst_object_unref (ret); - return NULL; -} - /** * gst_ghost_pad_new_no_target: * @name: the name of the new pad, or NULL to assign a default name. @@ -1145,8 +1049,7 @@ * @newtarget: the new pad target * * Set the new target of the ghostpad @gpad. Any existing target - * is unlinked and links to the new target are established. if @newtarget is - * NULL the target will be cleared. + * is unlinked and links to the new target are established. * * Returns: TRUE if the new target could be set. This function can return FALSE * when the internal pads could not be linked. @@ -1167,39 +1070,23 @@ GST_PROXY_LOCK (gpad); internal = GST_PROXY_PAD_INTERNAL (gpad); - g_assert (internal); - if (newtarget) - GST_DEBUG_OBJECT (gpad, "set target %s:%s", GST_DEBUG_PAD_NAME (newtarget)); - else - GST_DEBUG_OBJECT (gpad, "clearing target"); + GST_DEBUG_OBJECT (gpad, "set target %s:%s", GST_DEBUG_PAD_NAME (newtarget)); /* clear old target */ if ((oldtarget = GST_PROXY_PAD_TARGET (gpad))) { - if (GST_PAD_IS_SRC (oldtarget)) { - g_signal_handlers_disconnect_by_func (oldtarget, - (gpointer) on_src_target_notify, gpad); + /* if we have an internal pad, unlink */ + if (internal) { + if (GST_PAD_IS_SRC (internal)) + gst_pad_unlink (internal, oldtarget); + else + gst_pad_unlink (oldtarget, internal); } - - GST_PROXY_PAD_RETARGET (internal) = TRUE; - - /* unlink internal pad */ - if (GST_PAD_IS_SRC (internal)) - gst_pad_unlink (internal, oldtarget); - else - gst_pad_unlink (oldtarget, internal); - - GST_PROXY_PAD_RETARGET (internal) = FALSE; } result = gst_proxy_pad_set_target_unlocked (GST_PAD_CAST (gpad), newtarget); if (result && newtarget) { - if (GST_PAD_IS_SRC (newtarget)) { - g_signal_connect (newtarget, "notify::caps", - G_CALLBACK (on_src_target_notify), gpad); - } - /* and link to internal pad */ GST_DEBUG_OBJECT (gpad, "connecting internal pad to target");