* core when using the appropriate locking. Do not use this in plug-ins or
* applications in order to retain ABI compatibility.
*
- * All elements have pads (of the type #GstPad). These pads link to pads on
+ * Elements can have pads (of the type #GstPad). These pads link to pads on
* other elements. #GstBuffer flow between these linked pads.
* A #GstElement has a #GList of #GstPad structures for all their input (or sink)
* and output (or source) pads.
* An existing pad of an element can be retrieved by name with
* gst_element_get_static_pad(). A new dynamic pad can be created using
* gst_element_request_pad() with a #GstPadTemplate or
- * gst_element_get_request_pad() with the template name such as "src_%d".
+ * gst_element_get_request_pad() with the template name such as "src_\%u".
* An iterator of all pads can be retrieved with gst_element_iterate_pads().
*
* Elements can be linked through their pads.
* You can get and set a #GstClock on an element using gst_element_get_clock()
* and gst_element_set_clock().
* Some elements can provide a clock for the pipeline if
- * gst_element_provides_clock() returns %TRUE. With the
+ * the #GST_ELEMENT_FLAG_PROVIDE_CLOCK flag is set. With the
* gst_element_provide_clock() method one can retrieve the clock provided by
* such an element.
- * Not all elements require a clock to operate correctly. If
- * gst_element_requires_clock() returns %TRUE, a clock should be set on the
+ * Not all elements require a clock to operate correctly. If the
+ * #GST_ELEMENT_FLAG_REQUIRE_CLOCK() flag is set, a clock should be set on the
* element with gst_element_set_clock().
*
* Note that clock slection and distribution is normally handled by the
* toplevel #GstPipeline so the clock functions are only to be used in very
* specific situations.
*
- * Last reviewed on 2009-05-29 (0.10.24)
+ * Last reviewed on 2012-03-28 (0.11.3)
*/
#include "gst_private.h"
#include "gstelementmetadata.h"
#include "gstenumtypes.h"
#include "gstbus.h"
-#include "gstmarshal.h"
#include "gsterror.h"
#include "gstevent.h"
#include "gstutils.h"
#include "gstinfo.h"
#include "gstvalue.h"
#include "gst-i18n-lib.h"
+#include "glib-compat-private.h"
/* Element signals and args */
enum
GstState * state, GstState * pending, GstClockTime timeout);
static GstStateChangeReturn gst_element_set_state_func (GstElement * element,
GstState state);
+static gboolean gst_element_set_clock_func (GstElement * element,
+ GstClock * clock);
static void gst_element_set_bus_func (GstElement * element, GstBus * bus);
static gboolean gst_element_default_send_event (GstElement * element,
static guint gst_element_signals[LAST_SIGNAL] = { 0 };
/* this is used in gstelementfactory.c:gst_element_register() */
-GQuark _gst_elementclass_factory = 0;
+GQuark __gst_elementclass_factory = 0;
GType
gst_element_get_type (void)
_type = g_type_register_static (GST_TYPE_OBJECT, "GstElement",
&element_info, G_TYPE_FLAG_ABSTRACT);
- _gst_elementclass_factory =
+ __gst_elementclass_factory =
g_quark_from_static_string ("GST_ELEMENTCLASS_FACTORY");
g_once_init_leave (&gst_element_type, _type);
}
gst_element_signals[PAD_ADDED] =
g_signal_new ("pad-added", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (GstElementClass, pad_added), NULL, NULL,
- gst_marshal_VOID__OBJECT, G_TYPE_NONE, 1, GST_TYPE_PAD);
+ g_cclosure_marshal_generic, G_TYPE_NONE, 1, GST_TYPE_PAD);
/**
* GstElement::pad-removed:
* @gstelement: the object which received the signal
gst_element_signals[PAD_REMOVED] =
g_signal_new ("pad-removed", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (GstElementClass, pad_removed), NULL, NULL,
- gst_marshal_VOID__OBJECT, G_TYPE_NONE, 1, GST_TYPE_PAD);
+ g_cclosure_marshal_generic, G_TYPE_NONE, 1, GST_TYPE_PAD);
/**
* GstElement::no-more-pads:
* @gstelement: the object which received the signal
gst_element_signals[NO_MORE_PADS] =
g_signal_new ("no-more-pads", G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstElementClass, no_more_pads), NULL,
- NULL, gst_marshal_VOID__VOID, G_TYPE_NONE, 0);
+ NULL, g_cclosure_marshal_generic, G_TYPE_NONE, 0);
gobject_class->dispose = gst_element_dispose;
gobject_class->finalize = gst_element_finalize;
klass->change_state = GST_DEBUG_FUNCPTR (gst_element_change_state_func);
klass->set_state = GST_DEBUG_FUNCPTR (gst_element_set_state_func);
klass->get_state = GST_DEBUG_FUNCPTR (gst_element_get_state_func);
+ klass->set_clock = GST_DEBUG_FUNCPTR (gst_element_set_clock_func);
klass->set_bus = GST_DEBUG_FUNCPTR (gst_element_set_bus_func);
klass->query = GST_DEBUG_FUNCPTR (gst_element_default_query);
klass->send_event = GST_DEBUG_FUNCPTR (gst_element_default_send_event);
* the details in class_init instead of base_init */
element_class->metadata =
element_class->metadata ? gst_structure_copy (element_class->metadata) :
- gst_structure_empty_new ("metadata");
+ gst_structure_new_empty ("metadata");
/* Copy the pad templates so elements inherit them
* from their base class but elements can add pad templates in class_init
/* set the factory, see gst_element_register() */
element_class->elementfactory =
g_type_get_qdata (G_TYPE_FROM_CLASS (element_class),
- _gst_elementclass_factory);
+ __gst_elementclass_factory);
GST_DEBUG ("type %s : factory %p", G_OBJECT_CLASS_NAME (element_class),
element_class->elementfactory);
}
GST_STATE_PENDING (element) = GST_STATE_VOID_PENDING;
GST_STATE_RETURN (element) = GST_STATE_CHANGE_SUCCESS;
- g_static_rec_mutex_init (&element->state_lock);
- element->state_cond = g_cond_new ();
+ g_rec_mutex_init (&element->state_lock);
+ g_cond_init (&element->state_cond);
}
/**
g_return_if_fail (GST_IS_ELEMENT (element));
g_return_if_fail (GST_IS_PAD (pad));
+ g_return_if_fail (GST_PAD_PAD_TEMPLATE (pad) == NULL ||
+ GST_PAD_TEMPLATE_PRESENCE (GST_PAD_PAD_TEMPLATE (pad)) ==
+ GST_PAD_REQUEST);
oclass = GST_ELEMENT_GET_CLASS (element);
}
/**
- * gst_element_requires_clock:
- * @element: a #GstElement to query
- *
- * Query if the element requires a clock.
- *
- * Returns: %TRUE if the element requires a clock
- *
- * MT safe.
- */
-gboolean
-gst_element_requires_clock (GstElement * element)
-{
- gboolean result;
-
- g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
-
- result = (GST_ELEMENT_GET_CLASS (element)->set_clock != NULL);
-
- return result;
-}
-
-/**
- * gst_element_provides_clock:
- * @element: a #GstElement to query
- *
- * Query if the element provides a clock. A #GstClock provided by an
- * element can be used as the global #GstClock for the pipeline.
- * An element that can provide a clock is only required to do so in the PAUSED
- * state, this means when it is fully negotiated and has allocated the resources
- * to operate the clock.
- *
- * Returns: %TRUE if the element provides a clock
- *
- * MT safe.
- */
-gboolean
-gst_element_provides_clock (GstElement * element)
-{
- gboolean result;
-
- g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
-
- result = (GST_ELEMENT_GET_CLASS (element)->provide_clock != NULL);
-
- return result;
-}
-
-/**
* gst_element_provide_clock:
* @element: a #GstElement to query
*
return result;
}
+static gboolean
+gst_element_set_clock_func (GstElement * element, GstClock * clock)
+{
+ GstClock **clock_p;
+
+ GST_OBJECT_LOCK (element);
+ clock_p = &element->clock;
+ gst_object_replace ((GstObject **) clock_p, (GstObject *) clock);
+ GST_OBJECT_UNLOCK (element);
+
+ return TRUE;
+}
+
/**
* gst_element_set_clock:
* @element: a #GstElement to set the clock for.
gst_element_set_clock (GstElement * element, GstClock * clock)
{
GstElementClass *oclass;
- gboolean res = TRUE;
- GstClock **clock_p;
+ gboolean res = FALSE;
g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
g_return_val_if_fail (clock == NULL || GST_IS_CLOCK (clock), FALSE);
if (oclass->set_clock)
res = oclass->set_clock (element, clock);
- if (res) {
- /* only update the clock pointer if the element accepted the clock */
- GST_OBJECT_LOCK (element);
- clock_p = &element->clock;
- gst_object_replace ((GstObject **) clock_p, (GstObject *) clock);
- GST_OBJECT_UNLOCK (element);
- }
return res;
}
return result;
}
-/**
- * gst_element_is_indexable:
- * @element: a #GstElement.
- *
- * Queries if the element can be indexed.
- *
- * Returns: TRUE if the element can be indexed.
- *
- * MT safe.
- */
-gboolean
-gst_element_is_indexable (GstElement * element)
-{
- gboolean result;
-
- g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
-
- result = (GST_ELEMENT_GET_CLASS (element)->set_index != NULL);
-
- return result;
-}
-
+#if 0
/**
* gst_element_set_index:
* @element: a #GstElement.
return result;
}
+#endif
/**
* gst_element_add_pad:
GST_CAT_INFO_OBJECT (GST_CAT_ELEMENT_PADS, element, "adding pad '%s'",
GST_STR_NULL (pad_name));
flushing = GST_PAD_IS_FLUSHING (pad);
+ GST_OBJECT_FLAG_SET (pad, GST_PAD_FLAG_NEED_PARENT);
GST_OBJECT_UNLOCK (pad);
/* then check to see if there's already a pad by that name here */
* @element: a #GstElement to find a request pad of.
* @name: the name of the request #GstPad to retrieve.
*
- * Retrieves a pad from the element by name (e.g. "src_%d"). This version only
+ * Retrieves a pad from the element by name (e.g. "src_\%d"). This version only
* retrieves request pads. The pad should be released with
* gst_element_release_request_pad().
*
* Pad templates can be looked up using
* gst_element_factory_get_static_pad_templates().
*
- * If the @caps are specified and the element implements thew new
- * request_new_pad_full virtual method, the element will use them to select
- * which pad to create.
- *
* The pad should be released with gst_element_release_request_pad().
*
* Returns: (transfer full): requested #GstPad if found, otherwise %NULL.
}
/* Take ownership of the floating ref */
- g_object_ref_sink (templ);
+ gst_object_ref_sink (templ);
klass->padtemplates = g_list_append (klass->padtemplates, templ);
klass->numpadtemplates++;
GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "send %s event on element %s",
GST_EVENT_TYPE_NAME (event), GST_ELEMENT_NAME (element));
result = oclass->send_event (element, event);
- } else {
- result = gst_element_default_send_event (element, event);
}
GST_STATE_UNLOCK (element);
return result;
}
-/**
- * gst_element_get_query_types:
- * @element: a #GstElement to query
- *
- * Get an array of query types from the element.
- * If the element doesn't implement a query types function,
- * the query will be forwarded to the peer of a random linked sink pad.
- *
- * Returns: An array of #GstQueryType elements that should not
- * be freed or modified.
- *
- * MT safe.
- */
-const GstQueryType *
-gst_element_get_query_types (GstElement * element)
-{
- GstElementClass *oclass;
- const GstQueryType *result = NULL;
-
- g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
-
- oclass = GST_ELEMENT_GET_CLASS (element);
-
- if (oclass->get_query_types) {
- result = oclass->get_query_types (element);
- } else {
- GstPad *pad = gst_element_get_random_pad (element, TRUE, GST_PAD_SINK);
-
- if (pad) {
- GstPad *peer = gst_pad_get_peer (pad);
-
- if (peer) {
- result = gst_pad_get_query_types (peer);
-
- gst_object_unref (peer);
- }
- gst_object_unref (pad);
- }
- }
- return result;
-}
-
static gboolean
gst_element_default_query (GstElement * element, GstQuery * query)
{
GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "send query on element %s",
GST_ELEMENT_NAME (element));
result = oclass->query (element, query);
- } else {
- result = gst_element_default_query (element, query);
}
return result;
}
g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
GST_OBJECT_LOCK (element);
- result = GST_OBJECT_FLAG_IS_SET (element, GST_ELEMENT_LOCKED_STATE);
+ result = GST_ELEMENT_IS_LOCKED_STATE (element);
GST_OBJECT_UNLOCK (element);
return result;
g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
GST_OBJECT_LOCK (element);
- old = GST_OBJECT_FLAG_IS_SET (element, GST_ELEMENT_LOCKED_STATE);
+ old = GST_ELEMENT_IS_LOCKED_STATE (element);
if (G_UNLIKELY (old == locked_state))
goto was_ok;
if (locked_state) {
GST_CAT_DEBUG (GST_CAT_STATES, "locking state of element %s",
GST_ELEMENT_NAME (element));
- GST_OBJECT_FLAG_SET (element, GST_ELEMENT_LOCKED_STATE);
+ GST_OBJECT_FLAG_SET (element, GST_ELEMENT_FLAG_LOCKED_STATE);
} else {
GST_CAT_DEBUG (GST_CAT_STATES, "unlocking state of element %s",
GST_ELEMENT_NAME (element));
- GST_OBJECT_FLAG_UNSET (element, GST_ELEMENT_LOCKED_STATE);
+ GST_OBJECT_FLAG_UNSET (element, GST_ELEMENT_FLAG_LOCKED_STATE);
}
GST_OBJECT_UNLOCK (element);
if (ret == GST_STATE_CHANGE_FAILURE)
goto done;
- /* we got no_preroll, report immediatly */
+ /* we got no_preroll, report immediately */
if (ret == GST_STATE_CHANGE_NO_PREROLL)
goto done;
old_pending = GST_STATE_PENDING (element);
if (old_pending != GST_STATE_VOID_PENDING) {
- GTimeVal *timeval, abstimeout;
+ gboolean signaled;
guint32 cookie;
- if (timeout != GST_CLOCK_TIME_NONE) {
- glong add = timeout / 1000;
-
- if (add == 0)
- goto done;
-
- /* make timeout absolute */
- g_get_current_time (&abstimeout);
- g_time_val_add (&abstimeout, add);
- timeval = &abstimeout;
- } else {
- timeval = NULL;
- }
/* get cookie to detect state changes during waiting */
cookie = element->state_cookie;
"waiting for element to commit state");
/* we have a pending state change, wait for it to complete */
- if (!GST_STATE_TIMED_WAIT (element, timeval)) {
+ if (timeout != GST_CLOCK_TIME_NONE) {
+ gint64 end_time;
+ /* make timeout absolute */
+ end_time = g_get_monotonic_time () + (timeout / 1000);
+ signaled = GST_STATE_WAIT_UNTIL (element, end_time);
+ } else {
+ GST_STATE_WAIT (element);
+ signaled = TRUE;
+ }
+
+ if (!signaled) {
GST_CAT_INFO_OBJECT (GST_CAT_STATES, element, "timed out");
/* timeout triggered */
ret = GST_STATE_CHANGE_ASYNC;
GstElement *element = GST_ELEMENT_CAST (object);
GstClock **clock_p;
GstBus **bus_p;
+ GstElementClass *oclass;
+
+ oclass = GST_ELEMENT_GET_CLASS (element);
GST_CAT_INFO_OBJECT (GST_CAT_REFCOUNTING, element, "dispose");
"removing %d pads", g_list_length (element->pads));
/* first we break all our links with the outside */
while (element->pads && element->pads->data) {
+ GstPad *pad = GST_PAD_CAST (element->pads->data);
+
/* don't call _remove_pad with NULL */
- gst_element_remove_pad (element, GST_PAD_CAST (element->pads->data));
+ if (oclass->release_pad && GST_PAD_PAD_TEMPLATE (pad) &&
+ GST_PAD_TEMPLATE_PRESENCE (GST_PAD_PAD_TEMPLATE (pad))
+ == GST_PAD_REQUEST)
+ (oclass->release_pad) (element, GST_PAD_CAST (element->pads->data));
+ else
+ gst_element_remove_pad (element, GST_PAD_CAST (element->pads->data));
}
if (G_UNLIKELY (element->pads != NULL)) {
g_critical ("could not remove pads from element %s",
{
gboolean is_locked;
- is_locked = GST_OBJECT_FLAG_IS_SET (element, GST_ELEMENT_LOCKED_STATE);
+ is_locked = GST_ELEMENT_IS_LOCKED_STATE (element);
g_critical
("\nTrying to dispose element %s, but it is in %s%s instead of the NULL"
" state.\n"
GST_CAT_INFO_OBJECT (GST_CAT_REFCOUNTING, element, "finalize");
- g_cond_free (element->state_cond);
- g_static_rec_mutex_free (&element->state_lock);
+ g_cond_clear (&element->state_cond);
+ g_rec_mutex_clear (&element->state_lock);
GST_CAT_INFO_OBJECT (GST_CAT_REFCOUNTING, element, "finalize parent");