*
* 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_\%u".
+ * gst_element_request_pad() with a #GstPadTemplate.
* An iterator of all pads can be retrieved with gst_element_iterate_pads().
*
* Elements can be linked through their pads.
* #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
+ * Note that clock selection 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 2012-03-28 (0.11.3)
*/
#include "gst_private.h"
#include "gstutils.h"
#include "gstinfo.h"
#include "gstquark.h"
+#include "gsttracerutils.h"
#include "gstvalue.h"
#include "gst-i18n-lib.h"
#include "glib-compat-private.h"
+#ifndef GST_DISABLE_GST_DEBUG
+#include "printf/printf.h"
+#endif
+
/* Element signals and args */
enum
{
static void gst_element_base_class_init (gpointer g_class);
static void gst_element_base_class_finalize (gpointer g_class);
+static void gst_element_constructed (GObject * object);
static void gst_element_dispose (GObject * object);
static void gst_element_finalize (GObject * object);
static void gst_element_set_bus_func (GstElement * element, GstBus * bus);
static gboolean gst_element_post_message_default (GstElement * element,
GstMessage * message);
-
+static void gst_element_set_context_default (GstElement * element,
+ GstContext * context);
static gboolean gst_element_default_send_event (GstElement * element,
GstEvent * event);
gobject_class->dispose = gst_element_dispose;
gobject_class->finalize = gst_element_finalize;
+ gobject_class->constructed = gst_element_constructed;
klass->change_state = GST_DEBUG_FUNCPTR (gst_element_change_state_func);
klass->set_state = GST_DEBUG_FUNCPTR (gst_element_set_state_func);
klass->send_event = GST_DEBUG_FUNCPTR (gst_element_default_send_event);
klass->numpadtemplates = 0;
klass->post_message = GST_DEBUG_FUNCPTR (gst_element_post_message_default);
+ klass->set_context = GST_DEBUG_FUNCPTR (gst_element_set_context_default);
klass->elementfactory = NULL;
}
g_cond_init (&element->state_cond);
}
+static void
+gst_element_constructed (GObject * object)
+{
+ GST_TRACER_ELEMENT_NEW (GST_ELEMENT_CAST (object));
+ G_OBJECT_CLASS (parent_class)->constructed (object);
+}
+
/**
* gst_element_release_request_pad:
* @element: a #GstElement to release the request pad of.
* @pad: the #GstPad to release.
*
* Makes the element free the previously requested pad as obtained
- * with gst_element_get_request_pad().
+ * with gst_element_request_pad().
*
* This does not unref the pad. If the pad was created by using
- * gst_element_get_request_pad(), gst_element_release_request_pad() needs to be
+ * gst_element_request_pad(), gst_element_release_request_pad() needs to be
* followed by gst_object_unref() to free the @pad.
*
* MT safe.
* <note>An element is only required to provide a clock in the PAUSED
* state. Some elements can provide a clock in other states.</note>
*
- * Returns: (transfer full): the GstClock provided by the element or %NULL
- * if no clock could be provided. Unref after usage.
+ * Returns: (transfer full) (nullable): the GstClock provided by the
+ * element or %NULL if no clock could be provided. Unref after usage.
*
* MT safe.
*/
* Gets the currently configured clock of the element. This is the clock as was
* last set with gst_element_set_clock().
*
+ * Elements in a pipeline will only have their clock set when the
+ * pipeline is in the PLAYING state.
+ *
* Returns: (transfer full): the #GstClock of the element. unref after usage.
*
* MT safe.
*
* Gets the index from the element.
*
- * Returns: (transfer full): a #GstIndex or %NULL when no index was set on the
- * element. unref after usage.
+ * Returns: (transfer full) (nullable): a #GstIndex or %NULL when no
+ * index was set on the element. unref after usage.
*
* MT safe.
*/
gst_element_add_pad (GstElement * element, GstPad * pad)
{
gchar *pad_name;
- gboolean flushing;
+ gboolean active;
g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
pad_name = g_strdup (GST_PAD_NAME (pad));
GST_CAT_INFO_OBJECT (GST_CAT_ELEMENT_PADS, element, "adding pad '%s'",
GST_STR_NULL (pad_name));
- flushing = GST_PAD_IS_FLUSHING (pad);
+ active = GST_PAD_IS_ACTIVE (pad);
GST_OBJECT_FLAG_SET (pad, GST_PAD_FLAG_NEED_PARENT);
GST_OBJECT_UNLOCK (pad);
GST_OBJECT_CAST (element))))
goto had_parent;
- /* check for flushing pads */
- if (flushing && (GST_STATE (element) > GST_STATE_READY ||
+ /* check for active pads */
+ if (!active && (GST_STATE (element) > GST_STATE_READY ||
GST_STATE_NEXT (element) == GST_STATE_PAUSED)) {
- g_warning ("adding flushing pad '%s' to running element '%s', you need to "
+ g_warning ("adding inactive pad '%s' to running element '%s', you need to "
"use gst_pad_set_active(pad,TRUE) before adding it.",
GST_STR_NULL (pad_name), GST_ELEMENT_NAME (element));
- /* unset flushing */
- GST_OBJECT_LOCK (pad);
- GST_PAD_UNSET_FLUSHING (pad);
- GST_OBJECT_UNLOCK (pad);
+ gst_pad_set_active (pad, TRUE);
}
g_free (pad_name);
/* emit the PAD_ADDED signal */
g_signal_emit (element, gst_element_signals[PAD_ADDED], 0, pad);
-
+ GST_TRACER_ELEMENT_ADD_PAD (element, pad);
return TRUE;
/* ERROR cases */
*
* This function is used by plugin developers and should not be used
* by applications. Pads that were dynamically requested from elements
- * with gst_element_get_request_pad() should be released with the
+ * with gst_element_request_pad() should be released with the
* gst_element_release_request_pad() function instead.
*
* Pads are not automatically deactivated so elements should perform the needed
/* emit the PAD_REMOVED signal before unparenting and losing the last ref. */
g_signal_emit (element, gst_element_signals[PAD_REMOVED], 0, pad);
-
+ GST_TRACER_ELEMENT_REMOVE_PAD (element, pad);
gst_object_unparent (GST_OBJECT_CAST (pad));
return TRUE;
* Retrieves a pad from @element by name. This version only retrieves
* already-existing (i.e. 'static') pads.
*
- * Returns: (transfer full): the requested #GstPad if found, otherwise %NULL.
- * unref after usage.
+ * Returns: (transfer full) (nullable): the requested #GstPad if
+ * found, otherwise %NULL. unref after usage.
*
* MT safe.
*/
pad = gst_element_get_static_pad (element, name);
if (pad) {
gst_object_unref (pad);
- /* FIXME 0.11: Change this to g_return_val_if_fail() */
+ /* FIXME 2.0: Change this to g_return_val_if_fail() */
g_critical ("Element %s already has a pad named %s, the behaviour of "
" gst_element_get_request_pad() for existing pads is undefined!",
GST_ELEMENT_NAME (element), name);
* retrieves request pads. The pad should be released with
* gst_element_release_request_pad().
*
- * This method is slow and will be deprecated in the future. New code should
- * use gst_element_request_pad() with the requested template.
+ * This method is slower than manually getting the pad template and calling
+ * gst_element_request_pad() if the pads should have a specific name (e.g.
+ * @name is "src_1" instead of "src_\%u").
*
- * Returns: (transfer full): requested #GstPad if found, otherwise %NULL.
- * Release after usage.
+ * Returns: (transfer full) (nullable): requested #GstPad if found,
+ * otherwise %NULL. Release after usage.
*/
GstPad *
gst_element_get_request_pad (GstElement * element, const gchar * name)
}
/**
- * gst_element_request_pad:
+ * gst_element_request_pad: (virtual request_new_pad)
* @element: a #GstElement to find a request pad of.
* @templ: a #GstPadTemplate of which we want a pad of.
* @name: (transfer none) (allow-none): the name of the request #GstPad
*
* The pad should be released with gst_element_release_request_pad().
*
- * Returns: (transfer full): requested #GstPad if found, otherwise %NULL.
- * Release after usage.
+ * Returns: (transfer full) (nullable): requested #GstPad if found,
+ * otherwise %NULL. Release after usage.
*/
GstPad *
gst_element_request_pad (GstElement * element,
* that has subclasses, make sure to pass the g_class parameter of the
* #GInstanceInitFunc here.</note>
*
- * Returns: (transfer none): the #GstPadTemplate with the given name, or %NULL
- * if none was found. No unreferencing is necessary.
+ * Returns: (transfer none) (nullable): the #GstPadTemplate with the
+ * given name, or %NULL if none was found. No unreferencing is
+ * necessary.
*/
GstPadTemplate *
gst_element_class_get_pad_template (GstElementClass *
GstPad *pad;
pad = GST_EVENT_IS_DOWNSTREAM (event) ?
- gst_element_get_random_pad (element, TRUE, GST_PAD_SRC) :
- gst_element_get_random_pad (element, TRUE, GST_PAD_SINK);
+ gst_element_get_random_pad (element, TRUE, GST_PAD_SINK) :
+ gst_element_get_random_pad (element, TRUE, GST_PAD_SRC);
if (pad) {
GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS,
(GST_PAD_DIRECTION (pad) == GST_PAD_SRC ? "src" : "sink"),
GST_DEBUG_PAD_NAME (pad));
- result = gst_pad_push_event (pad, event);
+ result = gst_pad_send_event (pad, event);
gst_object_unref (pad);
} else {
GST_CAT_INFO (GST_CAT_ELEMENT_PADS, "can't send %s event on element %s",
*
* Sends an event to an element. If the element doesn't implement an
* event handler, the event will be pushed on a random linked sink pad for
- * upstream events or a random linked source pad for downstream events.
+ * downstream events or a random linked source pad for upstream events.
*
- * This function takes owership of the provided event so you should
+ * This function takes ownership of the provided event so you should
* gst_event_ref() it if you want to reuse the event after this call.
*
* MT safe.
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 {
+ gst_event_unref (event);
}
GST_STATE_UNLOCK (element);
*
* Please note that some queries might need a running pipeline to work.
*
- * Returns: TRUE if the query could be performed.
+ * Returns: %TRUE if the query could be performed.
*
* MT safe.
*/
gboolean
gst_element_query (GstElement * element, GstQuery * query)
{
- GstElementClass *oclass;
- gboolean result = FALSE;
+ GstElementClass *klass;
+ gboolean res = FALSE;
g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
g_return_val_if_fail (query != NULL, FALSE);
- oclass = GST_ELEMENT_GET_CLASS (element);
+ GST_TRACER_ELEMENT_QUERY_PRE (element, query);
- if (oclass->query) {
+ klass = GST_ELEMENT_GET_CLASS (element);
+ if (klass->query) {
GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "send query on element %s",
GST_ELEMENT_NAME (element));
- result = oclass->query (element, query);
+ res = klass->query (element, query);
}
- return result;
+
+ GST_TRACER_ELEMENT_QUERY_POST (element, query, res);
+ return res;
}
static gboolean
gst_element_post_message (GstElement * element, GstMessage * message)
{
GstElementClass *klass;
+ gboolean res = FALSE;
g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
+ g_return_val_if_fail (message != NULL, FALSE);
+
+ GST_TRACER_ELEMENT_POST_MESSAGE_PRE (element, message);
klass = GST_ELEMENT_GET_CLASS (element);
if (klass->post_message)
- return klass->post_message (element, message);
+ res = klass->post_message (element, message);
+ else
+ gst_message_unref (message);
- return FALSE;
+ GST_TRACER_ELEMENT_POST_MESSAGE_POST (element, res);
+ return res;
}
/**
* _gst_element_error_printf:
- * @format: the printf-like format to use, or %NULL
+ * @format: (allow-none): the printf-like format to use, or %NULL
*
* This function is only used internally by the gst_element_error() macro.
*
- * Returns: (transfer full): a newly allocated string, or %NULL if the format
- * was %NULL or ""
+ * Returns: (transfer full) (nullable): a newly allocated string, or
+ * %NULL if the format was %NULL or ""
*
* MT safe.
*/
{
va_list args;
gchar *buffer;
+ int len;
if (format == NULL)
return NULL;
return NULL;
va_start (args, format);
- buffer = g_strdup_vprintf (format, args);
+
+ len = __gst_vasprintf (&buffer, format, args);
+
va_end (args);
+
+ if (len < 0)
+ buffer = NULL;
+
return buffer;
}
*
* MT safe.
*
- * Returns: TRUE, if the element's state is locked.
+ * Returns: %TRUE, if the element's state is locked.
*/
gboolean
gst_element_is_locked_state (GstElement * element)
/**
* gst_element_set_locked_state:
* @element: a #GstElement
- * @locked_state: TRUE to lock the element's state
+ * @locked_state: %TRUE to lock the element's state
*
* Locks the state of an element, so state changes of the parent don't affect
* this element anymore.
*
* MT safe.
*
- * Returns: TRUE if the state was changed, FALSE if bad parameters were given
+ * Returns: %TRUE if the state was changed, %FALSE if bad parameters were given
* or the elements state-locking needed no change.
*/
gboolean
* @element: a #GstElement.
*
* Tries to change the state of the element to the same as its parent.
- * If this function returns FALSE, the state of element is undefined.
+ * If this function returns %FALSE, the state of element is undefined.
*
- * Returns: TRUE, if the element's state could be synced to the parent's state.
+ * Returns: %TRUE, if the element's state could be synced to the parent's state.
*
* MT safe.
*/
oclass = GST_ELEMENT_GET_CLASS (element);
+ GST_TRACER_ELEMENT_CHANGE_STATE_PRE (element, transition);
+
/* call the state change function so it can set the state */
if (oclass->change_state)
ret = (oclass->change_state) (element, transition);
else
ret = GST_STATE_CHANGE_FAILURE;
+ GST_TRACER_ELEMENT_CHANGE_STATE_POST (element, transition, ret);
+
switch (ret) {
case GST_STATE_CHANGE_FAILURE:
GST_CAT_INFO_OBJECT (GST_CAT_STATES, element,
}
/* gst_iterator_fold functions for pads_activate
- * Stop the iterator if activating one pad failed. */
+ * Stop the iterator if activating one pad failed, but only if that pad
+ * has not been removed from the element. */
static gboolean
activate_pads (const GValue * vpad, GValue * ret, gboolean * active)
{
GstPad *pad = g_value_get_object (vpad);
gboolean cont = TRUE;
- if (!(cont = gst_pad_set_active (pad, *active)))
- g_value_set_boolean (ret, FALSE);
+ if (!gst_pad_set_active (pad, *active)) {
+ if (GST_PAD_PARENT (pad) != NULL) {
+ cont = FALSE;
+ g_value_set_boolean (ret, FALSE);
+ }
+ }
return cont;
}
case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
break;
case GST_STATE_CHANGE_PAUSED_TO_READY:
- case GST_STATE_CHANGE_READY_TO_NULL:
+ case GST_STATE_CHANGE_READY_TO_NULL:{
+ GList *l;
+
/* deactivate pads in both cases, since they are activated on
ready->paused but the element might not have made it to paused */
if (!gst_element_pads_activate (element, FALSE)) {
result = GST_STATE_CHANGE_FAILURE;
}
+
+ /* Remove all non-persistent contexts */
+ GST_OBJECT_LOCK (element);
+ for (l = element->contexts; l;) {
+ GstContext *context = l->data;
+
+ if (!gst_context_is_persistent (context)) {
+ GList *next;
+
+ gst_context_unref (context);
+ next = l->next;
+ element->contexts = g_list_delete_link (element->contexts, l);
+ l = next;
+ } else {
+ l = l->next;
+ }
+ }
+ GST_OBJECT_UNLOCK (element);
break;
+ }
default:
/* this will catch real but unhandled state changes;
* can only be caused by:
bus_p = &element->bus;
gst_object_replace ((GstObject **) clock_p, NULL);
gst_object_replace ((GstObject **) bus_p, NULL);
+ g_list_free_full (element->contexts, (GDestroyNotify) gst_context_unref);
GST_OBJECT_UNLOCK (element);
GST_CAT_INFO_OBJECT (GST_CAT_REFCOUNTING, element, "parent class dispose");
return result;
}
+static void
+gst_element_set_context_default (GstElement * element, GstContext * context)
+{
+ const gchar *context_type;
+ GList *l;
+
+ GST_OBJECT_LOCK (element);
+ context_type = gst_context_get_context_type (context);
+ for (l = element->contexts; l; l = l->next) {
+ GstContext *tmp = l->data;
+ const gchar *tmp_type = gst_context_get_context_type (tmp);
+
+ /* Always store newest context but never replace
+ * a persistent one by a non-persistent one */
+ if (strcmp (context_type, tmp_type) == 0 &&
+ (gst_context_is_persistent (context) ||
+ !gst_context_is_persistent (tmp))) {
+ gst_context_replace ((GstContext **) & l->data, context);
+ break;
+ }
+ }
+ /* Not found? Add */
+ if (l == NULL) {
+ element->contexts =
+ g_list_prepend (element->contexts, gst_context_ref (context));
+ }
+ GST_OBJECT_UNLOCK (element);
+}
+
/**
* gst_element_set_context:
- * @element: a #GstElement to set the bus of.
+ * @element: a #GstElement to set the context of.
* @context: (transfer none): the #GstContext to set.
*
* Sets the context of the element. Increases the refcount of the context.
if (oclass->set_context)
oclass->set_context (element, context);
}
+
+/**
+ * gst_element_get_contexts:
+ * @element: a #GstElement to set the context of.
+ *
+ * Gets the contexts set on the element.
+ *
+ * MT safe.
+ *
+ * Returns: (element-type Gst.Context) (transfer full): List of #GstContext
+ *
+ * Since: 1.8
+ */
+GList *
+gst_element_get_contexts (GstElement * element)
+{
+ GList *ret;
+
+ g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
+
+ GST_OBJECT_LOCK (element);
+ ret = g_list_copy_deep (element->contexts, (GCopyFunc) gst_context_ref, NULL);
+ GST_OBJECT_UNLOCK (element);
+
+ return ret;
+}
+
+static gint
+_match_context_type (GstContext * c1, const gchar * context_type)
+{
+ const gchar *c1_type;
+
+ c1_type = gst_context_get_context_type (c1);
+
+ return g_strcmp0 (c1_type, context_type);
+}
+
+/**
+ * gst_element_get_context_unlocked:
+ * @element: a #GstElement to get the context of.
+ * @context_type: a name of a context to retrieve
+ *
+ * Gets the context with @context_type set on the element or NULL.
+ *
+ * Returns: (transfer full): A #GstContext or NULL
+ *
+ * Since: 1.8
+ */
+GstContext *
+gst_element_get_context_unlocked (GstElement * element,
+ const gchar * context_type)
+{
+ GstContext *ret = NULL;
+ GList *node;
+
+ g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
+
+ node =
+ g_list_find_custom (element->contexts, context_type,
+ (GCompareFunc) _match_context_type);
+ if (node && node->data)
+ ret = gst_context_ref (node->data);
+
+ return ret;
+}
+
+/**
+ * gst_element_get_context:
+ * @element: a #GstElement to get the context of.
+ * @context_type: a name of a context to retrieve
+ *
+ * Gets the context with @context_type set on the element or NULL.
+ *
+ * MT safe.
+ *
+ * Returns: (transfer full): A #GstContext or NULL
+ *
+ * Since: 1.8
+ */
+GstContext *
+gst_element_get_context (GstElement * element, const gchar * context_type)
+{
+ GstContext *ret = NULL;
+
+ g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
+
+ GST_OBJECT_LOCK (element);
+ ret = gst_element_get_context_unlocked (element, context_type);
+ GST_OBJECT_UNLOCK (element);
+
+ return ret;
+}