/* FIXME, I think this function is used to work around bad behaviour * of elements that add pads to themselves without activating them. * * Must be called with PAD_LOCK. */ static void gst_collect_pads_set_flushing_unlocked (GstCollectPads * pads, gboolean flushing) { GSList *walk = NULL; GST_DEBUG ("Setting flushing (%d)", flushing); /* Update the pads flushing flag */ for (walk = pads->data; walk; walk = g_slist_next (walk)) { GstCollectData *cdata = walk->data; if (GST_IS_PAD (cdata->pad)) { GST_OBJECT_LOCK (cdata->pad); if (flushing) GST_PAD_SET_FLUSHING (cdata->pad); else GST_PAD_UNSET_FLUSHING (cdata->pad); cdata->abidata.ABI.flushing = flushing; gst_collect_pads_clear (pads, cdata); GST_OBJECT_UNLOCK (cdata->pad); } } /* Setting the pads to flushing means that we changed the values which * are 'protected' by the cookie. We therefore update it to force a * recalculation of the current pad status. */ pads->abidata.ABI.pad_cookie++; }
/** * progress_buffer_create_sourcepad() * */ static void progress_buffer_create_sourcepad(ProgressBuffer *element) { element->srcpad = gst_pad_new_from_template (gst_element_class_get_pad_template (GST_ELEMENT_GET_CLASS(element), "src"), "src"); gst_pad_set_activatemode_function (element->srcpad, GST_DEBUG_FUNCPTR(progress_buffer_activatemode)); gst_pad_set_event_function (element->srcpad, GST_DEBUG_FUNCPTR(progress_buffer_src_event)); gst_pad_set_getrange_function (element->srcpad, GST_DEBUG_FUNCPTR(progress_buffer_getrange)); GST_PAD_UNSET_FLUSHING(element->srcpad); // Add pad gst_element_add_pad (GST_ELEMENT (element), element->srcpad); // Activate pad gst_pad_set_active (element->srcpad, TRUE); // Send "no-more-pads" gst_element_no_more_pads(GST_ELEMENT (element)); }
/** * 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. */ gboolean gst_ghost_pad_construct (GstGhostPad * gpad) { GstPadDirection dir, otherdir; GstPadTemplate *templ; GstPad *pad, *internal; 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); /* Set directional padfunctions for ghostpad */ if (dir == GST_PAD_SINK) { gst_pad_set_chain_function (pad, gst_proxy_pad_chain_default); gst_pad_set_chain_list_function (pad, gst_proxy_pad_chain_list_default); } else { gst_pad_set_getrange_function (pad, gst_proxy_pad_getrange_default); } /* 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, "direction", otherdir, NULL); } GST_PAD_UNSET_FLUSHING (internal); /* Set directional padfunctions for internal pad */ if (dir == GST_PAD_SRC) { gst_pad_set_chain_function (internal, gst_proxy_pad_chain_default); gst_pad_set_chain_list_function (internal, gst_proxy_pad_chain_list_default); } else { gst_pad_set_getrange_function (internal, gst_proxy_pad_getrange_default); } GST_OBJECT_LOCK (pad); /* now make the ghostpad a parent of the internal pad */ if (!gst_object_set_parent (GST_OBJECT_CAST (internal), GST_OBJECT_CAST (pad))) goto parent_failed; /* The ghostpad is the parent of the internal pad and is the only object that * can have a refcount on the internal pad. * At this point, the GstGhostPad has a refcount of 1, and the internal pad has * a refcount of 1. * When the refcount of the GstGhostPad drops to 0, the ghostpad will dispose * its 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; /* special activation functions for the internal pad */ gst_pad_set_activatemode_function (internal, gst_ghost_pad_internal_activate_mode_default); GST_OBJECT_UNLOCK (pad); GST_GHOST_PAD_PRIVATE (gpad)->constructed = TRUE; return TRUE; /* ERRORS */ parent_failed: { GST_WARNING_OBJECT (gpad, "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_OBJECT_UNLOCK (pad); gst_object_unref (internal); return FALSE; } }
static GstPad * gst_ghost_pad_new_full (const gchar * name, GstPadDirection dir, GstPadTemplate * templ) { GstPad *ret; GstPad *internal; GstPadDirection otherdir; 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); } /* Set directional padfunctions for ghostpad */ if (dir == GST_PAD_SINK) { gst_pad_set_bufferalloc_function (ret, GST_DEBUG_FUNCPTR (gst_proxy_pad_do_bufferalloc)); gst_pad_set_chain_function (ret, GST_DEBUG_FUNCPTR (gst_proxy_pad_do_chain)); } else { gst_pad_set_getrange_function (ret, GST_DEBUG_FUNCPTR (gst_proxy_pad_do_getrange)); gst_pad_set_checkgetrange_function (ret, GST_DEBUG_FUNCPTR (gst_proxy_pad_do_checkgetrange)); } /* link/unlink functions */ 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); } else { internal = g_object_new (GST_TYPE_PROXY_PAD, "name", NULL, "direction", otherdir, NULL); } GST_PAD_UNSET_FLUSHING (internal); /* Set directional padfunctions for internal pad */ if (dir == GST_PAD_SRC) { gst_pad_set_bufferalloc_function (internal, GST_DEBUG_FUNCPTR (gst_proxy_pad_do_bufferalloc)); gst_pad_set_chain_function (internal, GST_DEBUG_FUNCPTR (gst_proxy_pad_do_chain)); } else { gst_pad_set_getrange_function (internal, GST_DEBUG_FUNCPTR (gst_proxy_pad_do_getrange)); gst_pad_set_checkgetrange_function (internal, GST_DEBUG_FUNCPTR (gst_proxy_pad_do_checkgetrange)); } 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 (ret))) goto parent_failed; /* The ghostpad is the parent of the internal pad and is the only object that * can have a refcount on the internal pad. * At this point, the GstGhostPad has a refcount of 1, and the internal pad has * a refcount of 1. * When the refcount of the GstGhostPad drops to 0, the ghostpad will dispose * 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 (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_CAST (ret)->notify_id = g_signal_connect (internal, "notify::caps", G_CALLBACK (on_int_notify), ret); /* call function to init values of the pad caps */ on_int_notify (internal, NULL, GST_GHOST_PAD_CAST (ret)); /* special activation functions for the internal pad */ gst_pad_set_activatepull_function (internal, GST_DEBUG_FUNCPTR (gst_ghost_pad_internal_do_activate_pull)); gst_pad_set_activatepush_function (internal, GST_DEBUG_FUNCPTR (gst_ghost_pad_internal_do_activate_push)); GST_PROXY_UNLOCK (ret); return ret; /* ERRORS */ parent_failed: { 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 (ret); gst_object_unref (ret); gst_object_unref (internal); return NULL; } }