diff options
Diffstat (limited to 'gst/gstpad.c')
-rw-r--r-- | gst/gstpad.c | 982 |
1 files changed, 121 insertions, 861 deletions
diff --git a/gst/gstpad.c b/gst/gstpad.c index d479fcf6ae..b0acac4f4a 100644 --- a/gst/gstpad.c +++ b/gst/gstpad.c @@ -163,8 +163,7 @@ enum enum { REAL_ARG_0, - REAL_ARG_CAPS, - REAL_ARG_ACTIVE + REAL_ARG_CAPS /* FILL ME */ }; @@ -232,9 +231,6 @@ gst_real_pad_class_init (GstRealPadClass * klass) gst_marshal_BOXED__BOXED, GST_TYPE_CAPS, 1, GST_TYPE_CAPS | G_SIGNAL_TYPE_STATIC_SCOPE); - g_object_class_install_property (G_OBJECT_CLASS (klass), REAL_ARG_ACTIVE, - g_param_spec_boolean ("active", "Active", "Whether the pad is active.", - TRUE, G_PARAM_READWRITE)); g_object_class_install_property (G_OBJECT_CLASS (klass), REAL_ARG_CAPS, g_param_spec_boxed ("caps", "Caps", "The capabilities of the pad", GST_TYPE_CAPS, G_PARAM_READABLE)); @@ -261,31 +257,11 @@ static void gst_real_pad_init (GstRealPad * pad) { pad->direction = GST_PAD_UNKNOWN; - pad->peer = NULL; - pad->chainfunc = NULL; - pad->getfunc = NULL; - - pad->chainhandler = NULL; - pad->gethandler = NULL; - - pad->ghostpads = NULL; - pad->caps = NULL; - - pad->linkfunc = NULL; - pad->getcapsfunc = NULL; - - pad->eventfunc = gst_pad_event_default; + pad->eventhandler = gst_pad_event_default; pad->convertfunc = gst_pad_convert_default; pad->queryfunc = gst_pad_query_default; pad->intlinkfunc = gst_pad_get_internal_links_default; - - pad->eventmaskfunc = gst_pad_get_event_masks_default; - pad->formatsfunc = gst_pad_get_formats_default; - pad->querytypefunc = gst_pad_get_query_types_default; - - GST_FLAG_SET (pad, GST_PAD_DISABLED); - GST_FLAG_UNSET (pad, GST_PAD_NEGOTIATING); } static void @@ -295,9 +271,6 @@ gst_real_pad_set_property (GObject * object, guint prop_id, g_return_if_fail (GST_IS_PAD (object)); switch (prop_id) { - case REAL_ARG_ACTIVE: - gst_pad_set_active (GST_PAD (object), g_value_get_boolean (value)); - break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -311,9 +284,6 @@ gst_real_pad_get_property (GObject * object, guint prop_id, g_return_if_fail (GST_IS_PAD (object)); switch (prop_id) { - case REAL_ARG_ACTIVE: - g_value_set_boolean (value, !GST_FLAG_IS_SET (object, GST_PAD_DISABLED)); - break; case REAL_ARG_CAPS: g_value_set_boxed (value, GST_PAD_CAPS (GST_REAL_PAD (object))); break; @@ -323,6 +293,44 @@ gst_real_pad_get_property (GObject * object, guint prop_id, } } +/** + * gst_pad_push: + * @pad: a source #GstPad. + * @data: the #GstData to push. + * + * Pushes a buffer or an event to the peer of @pad. @pad must be negotiated. + * May only be called by @pad's parent and only if the parent has the + * GST_ELEMENT_PUSHING flag set. + */ +void +gst_pad_push (GstPad * pad, GstData * data) +{ + GstElement *parent; + GstScheduler *sched; + + g_return_if_fail (GST_IS_REAL_PAD (pad)); + g_return_if_fail (GST_PAD_IS_SRC (pad)); + g_return_if_fail (data != NULL); + + parent = gst_pad_get_parent (pad); + g_return_if_fail (GST_IS_ELEMENT (parent)); + g_return_if_fail (GST_ELEMENT_IS_PUSHING (parent)); + //DEBUG_DATA (pad, data, "gst_pad_push"); + + if (!gst_pad_is_negotiated (pad)) { + g_warning ("pushing data on non-negotiated pad %s:%s, not allowed.", + GST_DEBUG_PAD_NAME (pad)); + gst_data_unref (data); + return; + } + + GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, "pushing"); + + sched = GST_ELEMENT_SCHED (parent); + g_return_if_fail (sched); + gst_scheduler_pad_push (sched, GST_REAL_PAD (pad), data); +} + /* FIXME-0.9: Replace these custom functions with proper inheritance via _init functions and object properties */ /** @@ -433,111 +441,59 @@ gst_pad_get_direction (GstPad * pad) } /** - * gst_pad_set_active: + * gst_real_pad_set_active: * @pad: the #GstPad to activate or deactivate. * @active: TRUE to activate the pad. * * Activates or deactivates the given pad. */ void -gst_pad_set_active (GstPad * pad, gboolean active) +gst_real_pad_set_active (GstRealPad * pad, gboolean active) { - GstRealPad *realpad; - gboolean old; - GstPadLink *link; - - g_return_if_fail (GST_IS_PAD (pad)); - - old = GST_PAD_IS_ACTIVE (pad); - - if (old == active) - return; - - realpad = GST_PAD_REALIZE (pad); - - if (active) { - GST_CAT_DEBUG (GST_CAT_PADS, "activating pad %s:%s", - GST_DEBUG_PAD_NAME (realpad)); - GST_FLAG_UNSET (realpad, GST_PAD_DISABLED); - } else { - GST_CAT_DEBUG (GST_CAT_PADS, "de-activating pad %s:%s", - GST_DEBUG_PAD_NAME (realpad)); - GST_FLAG_SET (realpad, GST_PAD_DISABLED); - } - link = GST_RPAD_LINK (realpad); - if (link) { - if (link->temp_store) { - GST_CAT_INFO (GST_CAT_PADS, - "deleting cached data %p from bufpen of pad %s:%s", link->temp_store, - GST_DEBUG_PAD_NAME (realpad)); - gst_data_unref (link->temp_store); - link->temp_store = NULL; - } - } + g_return_if_fail (GST_IS_REAL_PAD (pad)); - g_object_notify (G_OBJECT (realpad), "active"); + g_return_if_fail (pad->action != NULL); + gst_action_set_active (pad->action, active); } /** - * gst_pad_set_active_recursive: - * @pad: the #GstPad to activate or deactivate. - * @active: TRUE to activate the pad. + * gst_real_pad_is_active: + * @pad: the #GstPad to query * - * Activates or deactivates the given pad and all internally linked - * pads upstream until it finds an element with multiple source pads. + * Query if a pad is active + * + * Returns: TRUE if the pad is active. */ -void -gst_pad_set_active_recursive (GstPad * pad, gboolean active) +gboolean +gst_real_pad_is_active (GstRealPad * pad) { - GstElement *parent; - const GList *int_links; - - g_return_if_fail (GST_IS_PAD (pad)); - g_return_if_fail (GST_PAD_IS_SRC (pad)); - - GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad, - "Recursively %s pad %s:%s", active ? "activating" : "deactivating", - GST_DEBUG_PAD_NAME (pad)); - - gst_pad_set_active (pad, active); - - /* If we have more than one sourcepad, then the other pads should - * possibly be kept active. FIXME: maybe we should recurse - * activation if any one pad is active and recurse deactivation - * if no single pad is active? */ - parent = gst_pad_get_parent (pad); - if (!parent || parent->numsrcpads > 1) - return; + g_return_val_if_fail (GST_IS_REAL_PAD (pad), FALSE); - for (int_links = gst_pad_get_internal_links (pad); - int_links; int_links = g_list_next (int_links)) { - GstPad *sinkpad = GST_PAD (int_links->data); - GstPad *peer = GST_PAD_PEER (sinkpad); - - GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, sinkpad, - "Recursing %s on pad %s:%s", - active ? "activation" : "deactivation", GST_DEBUG_PAD_NAME (sinkpad)); + if (pad->action == NULL) + return FALSE; - gst_pad_set_active (sinkpad, active); - if (peer) - gst_pad_set_active_recursive (peer, active); - } + return gst_action_is_active (pad->action); } /** - * gst_pad_is_active: - * @pad: the #GstPad to query - * - * Query if a pad is active - * - * Returns: TRUE if the pad is active. - */ -gboolean -gst_pad_is_active (GstPad * pad) + * gst_real_pad_set_initially_active: + * @pad: a #GstPad + * @active: whether the pad should be initially active or not + * + * Sets if the pad should be initially active. This sets the pad's action to + * initially active. See gst_action_set_initially_active() for details. The + * default behaviour is that sink pads are initially active while source pads + * are not, since this works for most general purpose elements. Other elements, + * most likely sources, will need to call this function on its pads. + * <note>The pad must have an action handler set when calling this function.</note> + **/ +void +gst_real_pad_set_initially_active (GstRealPad * pad, gboolean active) { - g_return_val_if_fail (GST_IS_PAD (pad), FALSE); + g_return_if_fail (GST_IS_REAL_PAD (pad)); - return !GST_FLAG_IS_SET (pad, GST_PAD_DISABLED); + g_return_if_fail (pad->action != NULL); + gst_action_set_initially_active (pad->action, active); } /** @@ -575,46 +531,6 @@ gst_pad_get_name (GstPad * pad) } /** - * gst_pad_set_chain_function: - * @pad: a real sink #GstPad. - * @chain: the #GstPadChainFunction to set. - * - * Sets the given chain function for the pad. The chain function is called to - * process a #GstData input buffer. - */ -void -gst_pad_set_chain_function (GstPad * pad, GstPadChainFunction chain) -{ - g_return_if_fail (GST_IS_REAL_PAD (pad)); - g_return_if_fail (GST_RPAD_DIRECTION (pad) == GST_PAD_SINK); - - GST_RPAD_CHAINFUNC (pad) = chain; - GST_CAT_DEBUG (GST_CAT_PADS, "chainfunc for %s:%s set to %s", - GST_DEBUG_PAD_NAME (pad), GST_DEBUG_FUNCPTR_NAME (chain)); -} - -/** - * gst_pad_set_get_function: - * @pad: a real source #GstPad. - * @get: the #GstPadGetFunction to set. - * - * Sets the given get function for the pad. The get function is called to - * produce a new #GstData to start the processing pipeline. Get functions cannot - * return %NULL. - */ -void -gst_pad_set_get_function (GstPad * pad, GstPadGetFunction get) -{ - g_return_if_fail (GST_IS_REAL_PAD (pad)); - g_return_if_fail (GST_RPAD_DIRECTION (pad) == GST_PAD_SRC); - - GST_RPAD_GETFUNC (pad) = get; - - GST_CAT_DEBUG (GST_CAT_PADS, "getfunc for %s:%s set to %s", - GST_DEBUG_PAD_NAME (pad), GST_DEBUG_FUNCPTR_NAME (get)); -} - -/** * gst_pad_set_event_function: * @pad: a real source #GstPad. * @event: the #GstPadEventFunction to set. @@ -624,91 +540,19 @@ gst_pad_set_get_function (GstPad * pad, GstPadGetFunction get) void gst_pad_set_event_function (GstPad * pad, GstPadEventFunction event) { + GstRealPad *real; + g_return_if_fail (GST_IS_REAL_PAD (pad)); g_return_if_fail (GST_RPAD_DIRECTION (pad) == GST_PAD_SRC); - GST_RPAD_EVENTFUNC (pad) = event; + real = GST_REAL_PAD (pad); + real->eventhandler = event; GST_CAT_DEBUG (GST_CAT_PADS, "eventfunc for %s:%s set to %s", GST_DEBUG_PAD_NAME (pad), GST_DEBUG_FUNCPTR_NAME (event)); } /** - * gst_pad_set_event_mask_function: - * @pad: a real #GstPad of either direction. - * @mask_func: the #GstPadEventMaskFunction to set. - * - * Sets the given event mask function for the pad. - */ -void -gst_pad_set_event_mask_function (GstPad * pad, - GstPadEventMaskFunction mask_func) -{ - g_return_if_fail (GST_IS_REAL_PAD (pad)); - - GST_RPAD_EVENTMASKFUNC (pad) = mask_func; - - GST_CAT_DEBUG (GST_CAT_PADS, "eventmaskfunc for %s:%s set to %s", - GST_DEBUG_PAD_NAME (pad), GST_DEBUG_FUNCPTR_NAME (mask_func)); -} - -/** - * gst_pad_get_event_masks: - * @pad: a #GstPad. - * - * Gets the array of eventmasks from the given pad. - * - * Returns: a zero-terminated array of #GstEventMask, or NULL if the pad does - * not have an event mask function. - */ -const GstEventMask * -gst_pad_get_event_masks (GstPad * pad) -{ - GstRealPad *rpad; - - g_return_val_if_fail (GST_IS_PAD (pad), NULL); - - rpad = GST_PAD_REALIZE (pad); - - g_return_val_if_fail (rpad, NULL); - - if (GST_RPAD_EVENTMASKFUNC (rpad)) - return GST_RPAD_EVENTMASKFUNC (rpad) (GST_PAD (pad)); - - return NULL; -} - -static gboolean -gst_pad_get_event_masks_dispatcher (GstPad * pad, const GstEventMask ** data) -{ - *data = gst_pad_get_event_masks (pad); - - return TRUE; -} - -/** - * gst_pad_get_event_masks_default: - * @pad: a #GstPad. - * - * Invokes the default event masks dispatcher on the pad. - * - * Returns: a zero-terminated array of #GstEventMask, or NULL if none of the - * internally-linked pads have an event mask function. - */ -const GstEventMask * -gst_pad_get_event_masks_default (GstPad * pad) -{ - GstEventMask *result = NULL; - - g_return_val_if_fail (GST_IS_PAD (pad), NULL); - - gst_pad_dispatcher (pad, (GstPadDispatcherFunction) - gst_pad_get_event_masks_dispatcher, &result); - - return result; -} - -/** * gst_pad_set_convert_function: * @pad: a real #GstPad of either direction. * @convert: the #GstPadConvertFunction to set. @@ -745,82 +589,6 @@ gst_pad_set_query_function (GstPad * pad, GstPadQueryFunction query) } /** - * gst_pad_set_query_type_function: - * @pad: a real #GstPad of either direction. - * @type_func: the #GstPadQueryTypeFunction to set. - * - * Set the given query type function for the pad. - */ -void -gst_pad_set_query_type_function (GstPad * pad, - GstPadQueryTypeFunction type_func) -{ - g_return_if_fail (GST_IS_REAL_PAD (pad)); - - GST_RPAD_QUERYTYPEFUNC (pad) = type_func; - - GST_CAT_DEBUG (GST_CAT_PADS, "querytypefunc for %s:%s set to %s", - GST_DEBUG_PAD_NAME (pad), GST_DEBUG_FUNCPTR_NAME (type_func)); -} - -/** - * gst_pad_get_query_types: - * @pad: a #GstPad. - * - * Get an array of supported queries that can be performed - * on this pad. - * - * Returns: a zero-terminated array of #GstQueryType. - */ -const GstQueryType * -gst_pad_get_query_types (GstPad * pad) -{ - GstRealPad *rpad; - - g_return_val_if_fail (GST_IS_PAD (pad), NULL); - - rpad = GST_PAD_REALIZE (pad); - - g_return_val_if_fail (rpad, NULL); - - if (GST_RPAD_QUERYTYPEFUNC (rpad)) - return GST_RPAD_QUERYTYPEFUNC (rpad) (GST_PAD (pad)); - - return NULL; -} - -static gboolean -gst_pad_get_query_types_dispatcher (GstPad * pad, const GstQueryType ** data) -{ - *data = gst_pad_get_query_types (pad); - - return TRUE; -} - -/** - * gst_pad_get_query_types_default: - * @pad: a #GstPad. - * - * Invoke the default dispatcher for the query types on - * the pad. - * - * Returns: an zero-terminated array of #GstQueryType, or NULL if none of the - * internally-linked pads has a query types function. - */ -const GstQueryType * -gst_pad_get_query_types_default (GstPad * pad) -{ - GstQueryType *result = NULL; - - g_return_val_if_fail (GST_IS_PAD (pad), NULL); - - gst_pad_dispatcher (pad, (GstPadDispatcherFunction) - gst_pad_get_query_types_dispatcher, &result); - - return result; -} - -/** * gst_pad_set_internal_link_function: * @pad: a real #GstPad of either direction. * @intlink: the #GstPadIntLinkFunction to set. @@ -838,23 +606,6 @@ gst_pad_set_internal_link_function (GstPad * pad, GstPadIntLinkFunction intlink) } /** - * gst_pad_set_formats_function: - * @pad: a real #GstPad of either direction. - * @formats: the #GstPadFormatsFunction to set. - * - * Sets the given formats function for the pad. - */ -void -gst_pad_set_formats_function (GstPad * pad, GstPadFormatsFunction formats) -{ - g_return_if_fail (GST_IS_REAL_PAD (pad)); - - GST_RPAD_FORMATSFUNC (pad) = formats; - GST_CAT_DEBUG (GST_CAT_PADS, "formats function for %s:%s set to %s", - GST_DEBUG_PAD_NAME (pad), GST_DEBUG_FUNCPTR_NAME (formats)); -} - -/** * gst_pad_set_link_function: * @pad: a real #GstPad. * @link: the #GstPadLinkFunction to set. @@ -1092,18 +843,12 @@ static gboolean gst_pad_check_schedulers (GstRealPad * realsrc, GstRealPad * realsink) { GstScheduler *src_sched, *sink_sched; - gint num_decoupled = 0; src_sched = gst_pad_get_scheduler (GST_PAD (realsrc)); sink_sched = gst_pad_get_scheduler (GST_PAD (realsink)); if (src_sched && sink_sched) { - if (GST_FLAG_IS_SET (GST_PAD_PARENT (realsrc), GST_ELEMENT_DECOUPLED)) - num_decoupled++; - if (GST_FLAG_IS_SET (GST_PAD_PARENT (realsink), GST_ELEMENT_DECOUPLED)) - num_decoupled++; - - if (src_sched != sink_sched && num_decoupled != 1) { + if (src_sched != sink_sched) { return FALSE; } } @@ -2014,18 +1759,8 @@ gst_pad_get_scheduler (GstPad * pad) g_return_val_if_fail (GST_IS_PAD (pad), NULL); parent = gst_pad_get_parent (pad); - if (parent) { - if (GST_FLAG_IS_SET (parent, GST_ELEMENT_DECOUPLED)) { - GstRealPad *peer = GST_RPAD_PEER (pad); - - if (peer) { - scheduler = - gst_element_get_scheduler (gst_pad_get_parent (GST_PAD (peer))); - } - } else { - scheduler = gst_element_get_scheduler (parent); - } - } + if (parent) + scheduler = gst_element_get_scheduler (parent); return scheduler; } @@ -3079,6 +2814,11 @@ gst_real_pad_dispose (GObject * object) gst_element_remove_pad (GST_ELEMENT (GST_OBJECT_PARENT (pad)), pad); } + if (GST_REAL_PAD (pad)->action) { + gst_action_free (GST_REAL_PAD (pad)->action); + GST_REAL_PAD (pad)->action = NULL; + } + if (GST_RPAD_EXPLICIT_CAPS (pad)) { GST_ERROR_OBJECT (pad, "still explicit caps %" GST_PTR_FORMAT " set", GST_RPAD_EXPLICIT_CAPS (pad)); @@ -3088,6 +2828,43 @@ gst_real_pad_dispose (GObject * object) G_OBJECT_CLASS (real_pad_parent_class)->dispose (object); } +void +gst_src_pad_set_action_handler (GstPad * pad, GstActionSrcPadFunc func) +{ + GstRealPad *real; + + g_return_if_fail (GST_IS_REAL_PAD (pad)); + g_return_if_fail (func != NULL); + + real = GST_REAL_PAD (pad); + if (!real->action) { + /* actions may only be set (not reset) before being added to an element */ + g_return_if_fail (GST_OBJECT_PARENT (pad) == NULL); + real->action = gst_action_new (GST_ACTION_SRC_PAD); + real->action->any.initially_active = FALSE; + real->action->srcpad.pad = GST_REAL_PAD (pad); + } + real->action->srcpad.release = func; +} + +void +gst_sink_pad_set_action_handler (GstPad * pad, GstActionSinkPadFunc func) +{ + GstRealPad *real; + + g_return_if_fail (GST_IS_REAL_PAD (pad)); + g_return_if_fail (func != NULL); + + real = GST_REAL_PAD (pad); + if (!real->action) { + /* actions may only be set (not reset) before being added to an element */ + g_return_if_fail (GST_OBJECT_PARENT (pad) == NULL); + real->action = gst_action_new (GST_ACTION_SINK_PAD); + real->action->any.initially_active = TRUE; + real->action->sinkpad.pad = GST_REAL_PAD (pad); + } + real->action->sinkpad.release = func; +} #ifndef GST_DISABLE_LOADSAVE /* FIXME: why isn't this on a GstElement ? */ @@ -3228,388 +3005,6 @@ gst_ghost_pad_save_thyself (GstPad * pad, xmlNodePtr parent) } #endif /* GST_DISABLE_LOADSAVE */ -static GstData * -_invent_event (GstPad * pad, GstBuffer * buffer) -{ - GstEvent *event; - GstEventType event_type; - guint64 offset; - - if (GST_BUFFER_OFFSET_IS_VALID (buffer)) - event_type = GST_FORMAT_DEFAULT; - else - event_type = GST_FORMAT_UNDEFINED; - - offset = GST_BUFFER_OFFSET (buffer); - - if (GST_BUFFER_TIMESTAMP_IS_VALID (buffer)) { - GstClockTime timestamp = GST_BUFFER_TIMESTAMP (buffer); - - event = gst_event_new_discontinuous (TRUE, - GST_FORMAT_TIME, timestamp, event_type, offset, GST_FORMAT_UNDEFINED); - GST_CAT_WARNING (GST_CAT_SCHEDULING, - "needed to invent a DISCONT %p (time %" G_GUINT64_FORMAT - ") for %s:%s => %s:%s", event, timestamp, - GST_DEBUG_PAD_NAME (GST_PAD_PEER (pad)), GST_DEBUG_PAD_NAME (pad)); - } else { - event = gst_event_new_discontinuous (TRUE, - event_type, offset, GST_FORMAT_UNDEFINED); - GST_CAT_WARNING (GST_CAT_SCHEDULING, - "needed to invent a DISCONT %p (no time) for %s:%s => %s:%s", event, - GST_DEBUG_PAD_NAME (GST_PAD_PEER (pad)), GST_DEBUG_PAD_NAME (pad)); - } - - return GST_DATA (event); -} - -/** - * gst_pad_push: - * @pad: a source #GstPad. - * @data: the #GstData to push. - * - * Pushes a buffer or an event to the peer of @pad. @pad must be linked. May - * only be called by @pad's parent. - */ -void -gst_pad_push (GstPad * pad, GstData * data) -{ - GstRealPad *peer; - - g_return_if_fail (GST_IS_PAD (pad)); - g_return_if_fail (GST_PAD_DIRECTION (pad) == GST_PAD_SRC); - g_return_if_fail (!GST_FLAG_IS_SET (GST_PAD_REALIZE (pad), - GST_RPAD_IN_GETFUNC)); - g_return_if_fail (data != NULL); - - DEBUG_DATA (pad, data, "gst_pad_push"); - - if (!GST_PAD_IS_LINKED (pad)) { - GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, - "not pushing data %p as pad is unconnected", data); - gst_data_unref (data); - return; - } - - if (GST_IS_BUFFER (data) && !gst_pad_is_negotiated (pad)) { - g_warning ("pushing data on non-negotiated pad %s:%s, not allowed.", - GST_DEBUG_PAD_NAME (pad)); - gst_data_unref (data); - return; - } - - GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, "pushing"); - peer = GST_RPAD_PEER (pad); - - if (!peer) { - g_warning ("push on pad %s:%s but it is unlinked", - GST_DEBUG_PAD_NAME (pad)); - } else { - if (!GST_IS_EVENT (data) && !GST_PAD_IS_ACTIVE (peer)) { - g_warning ("push on peer of pad %s:%s but peer is not active", - GST_DEBUG_PAD_NAME (pad)); - return; - } - - if (peer->chainhandler) { - if (data) { - GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, - "calling chainhandler &%s of peer pad %s:%s", - GST_DEBUG_FUNCPTR_NAME (peer->chainhandler), - GST_DEBUG_PAD_NAME (GST_PAD (peer))); - (peer->chainhandler) (GST_PAD (peer), data); - return; - } else { - g_warning ("trying to push a NULL buffer on pad %s:%s", - GST_DEBUG_PAD_NAME (peer)); - return; - } - } else { - g_warning ("internal error: push on pad %s:%s but it has no chainhandler", - GST_DEBUG_PAD_NAME (peer)); - } - } - /* clean up the mess here */ - if (data != NULL) - gst_data_unref (data); -} - -/** - * gst_pad_pull: - * @pad: a sink #GstPad. - * - * Pulls an event or a buffer from the peer pad. May only be called by @pad's - * parent. - * - * Returns: a new #GstData from the peer pad. - */ -GstData * -gst_pad_pull (GstPad * pad) -{ - GstRealPad *peer; - GstData *data; - - g_return_val_if_fail (GST_PAD_DIRECTION (pad) == GST_PAD_SINK, - GST_DATA (gst_event_new (GST_EVENT_INTERRUPT))); - g_return_val_if_fail (!GST_FLAG_IS_SET (GST_PAD_REALIZE (pad), - GST_RPAD_IN_CHAINFUNC), - GST_DATA (gst_event_new (GST_EVENT_INTERRUPT))); - - peer = GST_RPAD_PEER (pad); - - if (!peer) { - GST_ELEMENT_ERROR (GST_PAD_PARENT (pad), CORE, PAD, (NULL), - ("pull on pad %s:%s but it was unlinked", GST_DEBUG_PAD_NAME (pad))); - } else { - if (peer->gethandler) { - GstPadLink *link = GST_RPAD_LINK (pad); - - GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, - "calling gethandler %s of peer pad %s:%s", - GST_DEBUG_FUNCPTR_NAME (peer->gethandler), GST_DEBUG_PAD_NAME (peer)); - - if (link->temp_store) { - g_assert (link->engaged); - GST_DEBUG ("moving temp_store %p to data", link->temp_store); - data = link->temp_store; - link->temp_store = NULL; - } else { - data = (peer->gethandler) (GST_PAD (peer)); - /* refetch - we might have been relinked */ - link = GST_RPAD_LINK (pad); - peer = GST_RPAD_PEER (pad); - if (!peer) { - /* Our peer disa-peer-ed ;) */ - goto int_out; - } - } - - if (data) { - if (!link->engaged) { - g_assert (link->temp_store == NULL); - if (GST_IS_BUFFER (data)) { - GST_DEBUG ("moving data buffer %p back to temp_store", data); - link->temp_store = data; - link->engaged = TRUE; - data = _invent_event (pad, GST_BUFFER (data)); - } else if (GST_IS_EVENT (data) && - GST_EVENT_TYPE (data) == GST_EVENT_DISCONTINUOUS && - GST_EVENT_DISCONT_NEW_MEDIA (data)) { - link->engaged = TRUE; - GST_CAT_LOG (GST_CAT_SCHEDULING, - "link engaged by discont event %p for pad %s:%s", data, - GST_DEBUG_PAD_NAME (pad)); - } - } - DEBUG_DATA (pad, data, "gst_pad_pull returned"); - return data; - } - - /* no null buffers allowed */ - GST_ELEMENT_ERROR (GST_PAD_PARENT (pad), CORE, PAD, (NULL), - ("NULL buffer during pull on %s:%s", GST_DEBUG_PAD_NAME (pad))); - } else { - GST_ELEMENT_ERROR (GST_PAD_PARENT (pad), CORE, PAD, (NULL), - ("pull on pad %s:%s but the peer pad %s:%s has no gethandler", - GST_DEBUG_PAD_NAME (pad), GST_DEBUG_PAD_NAME (peer))); - } - } - -int_out: - data = GST_DATA (gst_event_new (GST_EVENT_INTERRUPT)); - DEBUG_DATA (pad, data, "gst_pad_pull returning INTERRUPT"); - return data; -} - -GstData * -gst_pad_collect_array (GstScheduler * scheduler, GstPad ** selected, - GstPad ** padlist) -{ - GstSchedulerClass *klass = GST_SCHEDULER_GET_CLASS (scheduler); - - if (!GST_FLAG_IS_SET (scheduler, GST_SCHEDULER_FLAG_NEW_API) || - !klass->pad_select) { - /* better randomness? */ - if (selected) - *selected = padlist[0]; - return gst_pad_pull (padlist[0]); - } else { - GstPad *select; - - return klass->pad_select (scheduler, selected ? selected : &select, - padlist); - } -} - -/** - * gst_pad_collectv: - * @selected: set to the pad the buffer comes from if not NULL - * @padlist: a #GList of sink pads. - * - * Waits for a buffer on any of the list of pads. Each #GstPad in @padlist must - * belong to the same element and be owned by the caller. - * - * Returns: the #GstData that was available - */ -GstData * -gst_pad_collectv (GstPad ** selected, const GList * padlist) -{ - /* need to use alloca here because we must not leak data */ - GstPad **pads; - GstPad *test; - GstElement *element = NULL; - int i = 0; - - g_return_val_if_fail (padlist != NULL, NULL); - pads = g_alloca (sizeof (gpointer) * (g_list_length ((GList *) padlist) + 1)); - for (; padlist; padlist = g_list_next (padlist)) { - test = GST_PAD (padlist->data); - g_return_val_if_fail (GST_IS_PAD (test), NULL); - g_return_val_if_fail (GST_PAD_IS_SINK (test), NULL); - if (element) { - g_return_val_if_fail (element == gst_pad_get_parent (test), NULL); - } else { - element = gst_pad_get_parent (test); - } - pads[i++] = test; - } - pads[i] = NULL; - - return gst_pad_collect_array (GST_ELEMENT_SCHED (element), selected, pads); -} - -/** - * gst_pad_collect: - * @selected: set to the pad the buffer comes from if not NULL - * @pad: first pad - * @...: more sink pads. - * - * Waits for a buffer on the given set of pads. - * - * Returns: the #GstData that was available. - */ -GstData * -gst_pad_collect (GstPad ** selected, GstPad * pad, ...) -{ - GstData *result; - va_list var_args; - - g_return_val_if_fail (GST_IS_PAD (pad), NULL); - - va_start (var_args, pad); - - result = gst_pad_collect_valist (selected, pad, var_args); - - va_end (var_args); - - return result; -} - -/** - * gst_pad_collect_valist: - * @selected: set to the pad the buffer comes from if not NULL - * @pad: first pad - * @...: more sink pads. - * - * Waits for a buffer on the given set of pads. - * - * Returns: the #GstData that was available. - */ -GstData * -gst_pad_collect_valist (GstPad ** selected, GstPad * pad, va_list var_args) -{ - GstPad **padlist; - GstElement *element = NULL; - gint i = 0, maxlength; - - g_return_val_if_fail (GST_IS_PAD (pad), NULL); - - element = gst_pad_get_parent (pad); - maxlength = element->numsinkpads; - /* can we make this list a bit smaller than this upper limit? */ - padlist = g_alloca (sizeof (gpointer) * (maxlength + 1)); - while (pad) { - g_return_val_if_fail (i < maxlength, NULL); - g_return_val_if_fail (element == gst_pad_get_parent (pad), NULL); - padlist[i++] = pad; - pad = va_arg (var_args, GstPad *); - } - padlist[i] = NULL; - return gst_pad_collect_array (GST_ELEMENT_SCHED (element), selected, padlist); -} - -/** - * gst_pad_selectv: - * @padlist: a #GList of sink pads. - * - * Waits for a buffer on any of the list of pads. Each #GstPad in @padlist must - * be owned by the calling code. - * - * Returns: the #GstPad that has a buffer available. - * Use #gst_pad_pull() to get the buffer. - */ -GstPad * -gst_pad_selectv (GList * padlist) -{ - return NULL; -} - -/** - * gst_pad_select_valist: - * @pad: a first #GstPad to perform the select on. - * @varargs: A va_list of more pads to select on. - * - * Waits for a buffer on the given set of pads. - * - * Returns: the #GstPad that has a buffer available. - * Use #gst_pad_pull() to get the buffer. - */ -GstPad * -gst_pad_select_valist (GstPad * pad, va_list var_args) -{ - GstPad *result; - GList *padlist = NULL; - - if (pad == NULL) - return NULL; - - while (pad) { - padlist = g_list_prepend (padlist, pad); - pad = va_arg (var_args, GstPad *); - } - result = gst_pad_selectv (padlist); - g_list_free (padlist); - - return result; -} - -/** - * gst_pad_select: - * @pad: a first sink #GstPad to perform the select on. - * @...: A NULL-terminated list of more pads to select on. - * - * Waits for a buffer on the given set of pads. - * - * Returns: the #GstPad that has a buffer available. - * Use #gst_pad_pull() to get the buffer. - */ -GstPad * -gst_pad_select (GstPad * pad, ...) -{ - GstPad *result; - va_list var_args; - - if (pad == NULL) - return NULL; - - va_start (var_args, pad); - - result = gst_pad_select_valist (pad, var_args); - - va_end (var_args); - - return result; -} - /************************************************************************ * * templates @@ -4405,138 +3800,3 @@ gst_pad_query (GstPad * pad, GstQueryType type, return FALSE; } - -static gboolean -gst_pad_get_formats_dispatcher (GstPad * pad, const GstFormat ** data) -{ - *data = gst_pad_get_formats (pad); - - return TRUE; -} - -/** - * gst_pad_get_formats_default: - * @pad: a #GstPad to query - * - * Invoke the default format dispatcher for the pad. - * - * Returns: An array of GstFormats ended with a 0 value. - */ -const GstFormat * -gst_pad_get_formats_default (GstPad * pad) -{ - GstFormat *result = NULL; - - g_return_val_if_fail (GST_IS_PAD (pad), NULL); - - gst_pad_dispatcher (pad, (GstPadDispatcherFunction) - gst_pad_get_formats_dispatcher, &result); - - return result; -} - -/** - * gst_pad_get_formats: - * @pad: a #GstPad to query - * - * Gets the list of supported formats from the pad. - * - * Returns: An array of GstFormats ended with a 0 value. - */ -const GstFormat * -gst_pad_get_formats (GstPad * pad) -{ - GstRealPad *rpad; - - g_return_val_if_fail (GST_IS_PAD (pad), NULL); - - rpad = GST_PAD_REALIZE (pad); - - if (GST_RPAD_FORMATSFUNC (rpad)) - return GST_RPAD_FORMATSFUNC (rpad) (GST_PAD (pad)); - - return NULL; -} - -#define CALL_CHAINFUNC(pad, data) G_STMT_START {\ - GstData *__temp = (data); \ - DEBUG_DATA (pad, __temp, "calling chain function with "); \ - if (GST_IS_EVENT (__temp) && \ - !GST_FLAG_IS_SET (gst_pad_get_parent (pad), GST_ELEMENT_EVENT_AWARE)) { \ - gst_pad_send_event (pad, GST_EVENT (__temp)); \ - } else { \ - GST_FLAG_SET (pad, GST_RPAD_IN_CHAINFUNC); \ - GST_RPAD_CHAINFUNC (pad) (pad, __temp); \ - GST_FLAG_UNSET (pad, GST_RPAD_IN_CHAINFUNC); \ - } \ -}G_STMT_END -/** - * gst_pad_call_chain_function: - * @pad: sink pad to call chain function on - * @data: data to call the chain function with - * - * Calls the chain function of the given pad while making sure the internal - * consistency is kept. Use this function inside schedulers instead of calling - * the chain function yourself. - */ -void -gst_pad_call_chain_function (GstPad * pad, GstData * data) -{ - GstPadLink *link; - - g_return_if_fail (GST_IS_REAL_PAD (pad)); - g_return_if_fail (GST_PAD_IS_SINK (pad)); - g_return_if_fail (data != NULL); - g_return_if_fail (GST_RPAD_CHAINFUNC (pad) != NULL); - g_return_if_fail (GST_RPAD_LINK (pad) != NULL); - - link = GST_RPAD_LINK (pad); - if (!link->engaged) { - g_assert (link->temp_store == NULL); - if (GST_IS_BUFFER (data)) { - GST_DEBUG ("moving data buffer %p back to temp_store", data); - link->temp_store = data; - link->engaged = TRUE; - CALL_CHAINFUNC (pad, _invent_event (pad, GST_BUFFER (data))); - link = GST_RPAD_LINK (pad); - if (link->temp_store == NULL) /* happens after relinking in chainfunc */ - return; - g_assert (link->temp_store == data); - link->temp_store = NULL; - } else if (GST_IS_EVENT (data) && - GST_EVENT_TYPE (data) == GST_EVENT_DISCONTINUOUS && - GST_EVENT_DISCONT_NEW_MEDIA (data)) { - link->engaged = TRUE; - GST_CAT_LOG (GST_CAT_SCHEDULING, - "link engaged by discont event %p for pad %s:%s", data, - GST_DEBUG_PAD_NAME (pad)); - } - } - CALL_CHAINFUNC (pad, data); -} - -/** - * gst_pad_call_get_function: - * @pad: sink pad to call chain function on - * - * Calls the get function of the given pad while making sure the internal - * consistency is kept. Use this function inside schedulers instead of calling - * the get function yourself. - * - * Returns: the data provided by the pad or NULL if no data was available. - */ -GstData * -gst_pad_call_get_function (GstPad * pad) -{ - GstData *data; - - g_return_val_if_fail (GST_IS_REAL_PAD (pad), NULL); - g_return_val_if_fail (GST_PAD_IS_SRC (pad), NULL); - g_return_val_if_fail (GST_RPAD_GETFUNC (pad) != NULL, NULL); - - GST_FLAG_SET (pad, GST_RPAD_IN_GETFUNC); - data = GST_RPAD_GETFUNC (pad) (pad); - GST_FLAG_UNSET (pad, GST_RPAD_IN_GETFUNC); - DEBUG_DATA (pad, data, "getfunction returned"); - return data; -} |