X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=gst%2Fgstelement.c;h=25870f59d81294a7c3686b93b4ea1e01e7a1f495;hb=e10266e3f3cf9b05b69198b1ac6faa9a62840e30;hp=222292c9b9bec1ebba7a097274c500104f42a8df;hpb=13754e87fcf595bb87513413aec04b0db558028a;p=platform%2Fupstream%2Fgstreamer.git diff --git a/gst/gstelement.c b/gst/gstelement.c index 222292c..25870f5 100644 --- a/gst/gstelement.c +++ b/gst/gstelement.c @@ -16,8 +16,8 @@ * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. */ /** @@ -34,7 +34,7 @@ * 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. @@ -43,8 +43,7 @@ * * 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_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. @@ -65,18 +64,16 @@ * 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 + * 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 2009-05-29 (0.10.24) */ #include "gst_private.h" @@ -88,13 +85,18 @@ #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 "gstquark.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 @@ -129,6 +131,8 @@ static GstStateChangeReturn gst_element_set_state_func (GstElement * element, 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_post_message_default (GstElement * element, + GstMessage * message); static gboolean gst_element_default_send_event (GstElement * element, GstEvent * event); @@ -198,7 +202,7 @@ gst_element_class_init (GstElementClass * klass) 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 @@ -209,7 +213,7 @@ gst_element_class_init (GstElementClass * klass) 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 @@ -221,7 +225,7 @@ gst_element_class_init (GstElementClass * klass) 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; @@ -234,6 +238,7 @@ gst_element_class_init (GstElementClass * klass) klass->query = GST_DEBUG_FUNCPTR (gst_element_default_query); 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->elementfactory = NULL; } @@ -266,8 +271,8 @@ gst_element_base_class_init (gpointer g_class) element_class->elementfactory = g_type_get_qdata (G_TYPE_FROM_CLASS (element_class), __gst_elementclass_factory); - GST_DEBUG ("type %s : factory %p", G_OBJECT_CLASS_NAME (element_class), - element_class->elementfactory); + GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "type %s : factory %p", + G_OBJECT_CLASS_NAME (element_class), element_class->elementfactory); } static void @@ -290,8 +295,8 @@ gst_element_init (GstElement * element) 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); } /** @@ -300,10 +305,10 @@ gst_element_init (GstElement * element) * @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. @@ -315,66 +320,21 @@ gst_element_release_request_pad (GstElement * element, GstPad * pad) 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); /* if the element implements a custom release function we call that, else we * simply remove the pad from the element */ if (oclass->release_pad) - (oclass->release_pad) (element, pad); + oclass->release_pad (element, pad); else gst_element_remove_pad (element, pad); } /** - * 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 * @@ -546,8 +506,6 @@ gst_element_get_base_time (GstElement * element) * pipelines, and you can also ensure that the pipelines have the same clock. * * MT safe. - * - * Since: 0.10.24 */ void gst_element_set_start_time (GstElement * element, GstClockTime time) @@ -579,8 +537,6 @@ gst_element_set_start_time (GstElement * element, GstClockTime time) * MT safe. * * Returns: the start time of the element. - * - * Since: 0.10.24 */ GstClockTime gst_element_get_start_time (GstElement * element) @@ -596,28 +552,7 @@ gst_element_get_start_time (GstElement * element) 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. @@ -668,6 +603,7 @@ gst_element_get_index (GstElement * element) return result; } +#endif /** * gst_element_add_pad: @@ -706,6 +642,7 @@ gst_element_add_pad (GstElement * element, GstPad * 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 */ @@ -735,17 +672,17 @@ gst_element_add_pad (GstElement * element, GstPad * pad) /* add it to the list */ switch (gst_pad_get_direction (pad)) { case GST_PAD_SRC: - element->srcpads = g_list_prepend (element->srcpads, pad); + element->srcpads = g_list_append (element->srcpads, pad); element->numsrcpads++; break; case GST_PAD_SINK: - element->sinkpads = g_list_prepend (element->sinkpads, pad); + element->sinkpads = g_list_append (element->sinkpads, pad); element->numsinkpads++; break; default: goto no_direction; } - element->pads = g_list_prepend (element->pads, pad); + element->pads = g_list_append (element->pads, pad); element->numpads++; element->pads_cookie++; GST_OBJECT_UNLOCK (element); @@ -788,14 +725,14 @@ no_direction: /** * gst_element_remove_pad: * @element: a #GstElement to remove pad from. - * @pad: (transfer none): the #GstPad to remove from the element. + * @pad: (transfer full): the #GstPad to remove from the element. * * Removes @pad from @element. @pad will be destroyed if it has not been * referenced elsewhere using gst_object_unparent(). * * 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 @@ -858,6 +795,7 @@ gst_element_remove_pad (GstElement * element, GstPad * pad) break; } element->pads = g_list_remove (element->pads, pad); + GST_OBJECT_FLAG_UNSET (pad, GST_PAD_FLAG_NEED_PARENT); element->numpads--; element->pads_cookie++; GST_OBJECT_UNLOCK (element); @@ -1147,8 +1085,6 @@ gst_element_get_request_pad (GstElement * element, const gchar * name) * * Returns: (transfer full): requested #GstPad if found, otherwise %NULL. * Release after usage. - * - * Since: 0.10.32 */ GstPad * gst_element_request_pad (GstElement * element, @@ -1156,6 +1092,7 @@ gst_element_request_pad (GstElement * element, { g_return_val_if_fail (GST_IS_ELEMENT (element), NULL); g_return_val_if_fail (templ != NULL, NULL); + g_return_val_if_fail (templ->presence == GST_PAD_REQUEST, NULL); return _gst_element_request_pad (element, templ, name, caps); } @@ -1182,8 +1119,10 @@ gst_element_iterate_pad_list (GstElement * element, GList ** padlist) * be freed after usage. Also more specialized iterators exists such as * gst_element_iterate_src_pads() or gst_element_iterate_sink_pads(). * - * Returns: (transfer full): the #GstIterator of #GstPad. Unref each pad - * after use. + * The order of pads returned by the iterator will be the order in which + * the pads were added to the element. + * + * Returns: (transfer full): the #GstIterator of #GstPad. * * MT safe. */ @@ -1201,8 +1140,10 @@ gst_element_iterate_pads (GstElement * element) * * Retrieves an iterator of @element's source pads. * - * Returns: (transfer full): the #GstIterator of #GstPad. Unref each pad - * after use. + * The order of pads returned by the iterator will be the order in which + * the pads were added to the element. + * + * Returns: (transfer full): the #GstIterator of #GstPad. * * MT safe. */ @@ -1220,8 +1161,10 @@ gst_element_iterate_src_pads (GstElement * element) * * Retrieves an iterator of @element's sink pads. * - * Returns: (transfer full): the #GstIterator of #GstPad. Unref each pad - * after use. + * The order of pads returned by the iterator will be the order in which + * the pads were added to the element. + * + * Returns: (transfer full): the #GstIterator of #GstPad. * * MT safe. */ @@ -1267,7 +1210,7 @@ gst_element_class_add_pad_template (GstElementClass * klass, } /* 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++; @@ -1294,6 +1237,34 @@ gst_element_class_add_metadata (GstElementClass * klass, } /** + * gst_element_class_add_static_metadata: + * @klass: class to set metadata for + * @key: the key to set + * @value: the value to set + * + * Set @key with @value as metadata in @klass. + * + * Same as gst_element_class_add_metadata(), but @value must be a static string + * or an inlined string, as it will not be copied. (GStreamer plugins will + * be made resident once loaded, so this function can be used even from + * dynamically loaded plugins.) + */ +void +gst_element_class_add_static_metadata (GstElementClass * klass, + const gchar * key, const gchar * value) +{ + GValue val = G_VALUE_INIT; + + g_return_if_fail (GST_IS_ELEMENT_CLASS (klass)); + g_return_if_fail (key != NULL); + g_return_if_fail (value != NULL); + + g_value_init (&val, G_TYPE_STRING); + g_value_set_static_string (&val, value); + gst_structure_take_value ((GstStructure *) klass->metadata, key, &val); +} + +/** * gst_element_class_set_metadata: * @klass: class to set metadata for * @longname: The long English name of the element. E.g. "File Sink" @@ -1314,12 +1285,66 @@ gst_element_class_set_metadata (GstElementClass * klass, const gchar * description, const gchar * author) { g_return_if_fail (GST_IS_ELEMENT_CLASS (klass)); + g_return_if_fail (longname != NULL && *longname != '\0'); + g_return_if_fail (classification != NULL && *classification != '\0'); + g_return_if_fail (description != NULL && *description != '\0'); + g_return_if_fail (author != NULL && *author != '\0'); - gst_structure_set ((GstStructure *) klass->metadata, - GST_ELEMENT_METADATA_LONGNAME, G_TYPE_STRING, longname, - GST_ELEMENT_METADATA_KLASS, G_TYPE_STRING, classification, - GST_ELEMENT_METADATA_DESCRIPTION, G_TYPE_STRING, description, - GST_ELEMENT_METADATA_AUTHOR, G_TYPE_STRING, author, NULL); + gst_structure_id_set ((GstStructure *) klass->metadata, + GST_QUARK (ELEMENT_METADATA_LONGNAME), G_TYPE_STRING, longname, + GST_QUARK (ELEMENT_METADATA_KLASS), G_TYPE_STRING, classification, + GST_QUARK (ELEMENT_METADATA_DESCRIPTION), G_TYPE_STRING, description, + GST_QUARK (ELEMENT_METADATA_AUTHOR), G_TYPE_STRING, author, NULL); +} + +/** + * gst_element_class_set_static_metadata: + * @klass: class to set metadata for + * @longname: The long English name of the element. E.g. "File Sink" + * @classification: String describing the type of element, as an unordered list + * separated with slashes ('/'). See draft-klass.txt of the design docs + * for more details and common types. E.g: "Sink/File" + * @description: Sentence describing the purpose of the element. + * E.g: "Write stream to a file" + * @author: Name and contact details of the author(s). Use \n to separate + * multiple author metadata. E.g: "Joe Bloggs <joe.blogs at foo.com>" + * + * Sets the detailed information for a #GstElementClass. + * This function is for use in _class_init functions only. + * + * Same as gst_element_class_set_metadata(), but @longname, @classification, + * @description, and @author must be static strings or inlined strings, as + * they will not be copied. (GStreamer plugins will be made resident once + * loaded, so this function can be used even from dynamically loaded plugins.) + */ +void +gst_element_class_set_static_metadata (GstElementClass * klass, + const gchar * longname, const gchar * classification, + const gchar * description, const gchar * author) +{ + GstStructure *s = (GstStructure *) klass->metadata; + GValue val = G_VALUE_INIT; + + g_return_if_fail (GST_IS_ELEMENT_CLASS (klass)); + g_return_if_fail (longname != NULL && *longname != '\0'); + g_return_if_fail (classification != NULL && *classification != '\0'); + g_return_if_fail (description != NULL && *description != '\0'); + g_return_if_fail (author != NULL && *author != '\0'); + + g_value_init (&val, G_TYPE_STRING); + + g_value_set_static_string (&val, longname); + gst_structure_id_set_value (s, GST_QUARK (ELEMENT_METADATA_LONGNAME), &val); + + g_value_set_static_string (&val, classification); + gst_structure_id_set_value (s, GST_QUARK (ELEMENT_METADATA_KLASS), &val); + + g_value_set_static_string (&val, description); + gst_structure_id_set_value (s, GST_QUARK (ELEMENT_METADATA_DESCRIPTION), + &val); + + g_value_set_static_string (&val, author); + gst_structure_id_take_value (s, GST_QUARK (ELEMENT_METADATA_AUTHOR), &val); } /** @@ -1508,12 +1533,13 @@ gst_element_default_send_event (GstElement * element, GstEvent * event) * 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. * - * 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. * - * Returns: %TRUE if the event was handled. - * * MT safe. + * + * Returns: %TRUE if the event was handled. Events that trigger a preroll (such + * as flushing seeks and steps) will emit %GST_MESSAGE_ASYNC_DONE. */ gboolean gst_element_send_event (GstElement * element, GstEvent * event) @@ -1543,8 +1569,8 @@ gst_element_send_event (GstElement * element, GstEvent * event) * @rate: The new playback rate * @format: The format of the seek values * @flags: The optional seek flags. - * @cur_type: The type and flags for the new current position - * @cur: The value of the new current position + * @start_type: The type and flags for the new start position + * @start: The value of the new start position * @stop_type: The type and flags for the new stop position * @stop: The value of the new stop position * @@ -1552,13 +1578,14 @@ gst_element_send_event (GstElement * element, GstEvent * event) * the parameters. The seek event is sent to the element using * gst_element_send_event(). * - * Returns: %TRUE if the event was handled. - * * MT safe. + * + * Returns: %TRUE if the event was handled. Flushing seeks will trigger a + * preroll, which will emit %GST_MESSAGE_ASYNC_DONE. */ gboolean gst_element_seek (GstElement * element, gdouble rate, GstFormat format, - GstSeekFlags flags, GstSeekType cur_type, gint64 cur, + GstSeekFlags flags, GstSeekType start_type, gint64 start, GstSeekType stop_type, gint64 stop) { GstEvent *event; @@ -1567,7 +1594,8 @@ gst_element_seek (GstElement * element, gdouble rate, GstFormat format, g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE); event = - gst_event_new_seek (rate, format, flags, cur_type, cur, stop_type, stop); + gst_event_new_seek (rate, format, flags, start_type, start, stop_type, + stop); result = gst_element_send_event (element, event); return result; @@ -1613,45 +1641,30 @@ gst_element_default_query (GstElement * element, GstQuery * query) * * 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; g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE); g_return_val_if_fail (query != NULL, FALSE); - oclass = GST_ELEMENT_GET_CLASS (element); - - 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); + return klass->query (element, query); } - return result; + + return FALSE; } -/** - * gst_element_post_message: - * @element: a #GstElement posting the message - * @message: (transfer full): a #GstMessage to post - * - * Post a message on the element's #GstBus. This function takes ownership of the - * message; if you want to access the message after this call, you should add an - * additional reference before calling. - * - * Returns: %TRUE if the message was successfully posted. The function returns - * %FALSE if the element did not have a bus. - * - * MT safe. - */ -gboolean -gst_element_post_message (GstElement * element, GstMessage * message) +static gboolean +gst_element_post_message_default (GstElement * element, GstMessage * message) { GstBus *bus; gboolean result = FALSE; @@ -1687,6 +1700,35 @@ no_bus: } /** + * gst_element_post_message: + * @element: a #GstElement posting the message + * @message: (transfer full): a #GstMessage to post + * + * Post a message on the element's #GstBus. This function takes ownership of the + * message; if you want to access the message after this call, you should add an + * additional reference before calling. + * + * Returns: %TRUE if the message was successfully posted. The function returns + * %FALSE if the element did not have a bus. + * + * MT safe. + */ +gboolean +gst_element_post_message (GstElement * element, GstMessage * message) +{ + GstElementClass *klass; + + g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE); + g_return_val_if_fail (message != NULL, FALSE); + + klass = GST_ELEMENT_GET_CLASS (element); + if (klass->post_message) + return klass->post_message (element, message); + + return FALSE; +} + +/** * _gst_element_error_printf: * @format: the printf-like format to use, or %NULL * @@ -1702,6 +1744,7 @@ _gst_element_error_printf (const gchar * format, ...) { va_list args; gchar *buffer; + int len; if (format == NULL) return NULL; @@ -1709,8 +1752,14 @@ _gst_element_error_printf (const gchar * format, ...) 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; } @@ -1824,7 +1873,7 @@ void gst_element_message_full * * 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) @@ -1834,7 +1883,7 @@ gst_element_is_locked_state (GstElement * element) 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; @@ -1843,14 +1892,14 @@ 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 @@ -1861,7 +1910,7 @@ gst_element_set_locked_state (GstElement * element, gboolean locked_state) 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; @@ -1869,11 +1918,11 @@ gst_element_set_locked_state (GstElement * element, gboolean locked_state) 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); @@ -1895,9 +1944,9 @@ was_ok: * @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. */ @@ -1985,22 +2034,9 @@ gst_element_get_state_func (GstElement * element, 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; @@ -2008,7 +2044,17 @@ gst_element_get_state_func (GstElement * element, "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; @@ -2387,7 +2433,8 @@ only_async_start: * element will perform the remainder of the state change asynchronously in * another thread. * An application can use gst_element_get_state() to wait for the completion - * of the state change or it can wait for a state change message on the bus. + * of the state change or it can wait for a %GST_MESSAGE_ASYNC_DONE or + * %GST_MESSAGE_STATE_CHANGED on the bus. * * State changes to %GST_STATE_READY or %GST_STATE_NULL never return * #GST_STATE_CHANGE_ASYNC. @@ -2688,7 +2735,7 @@ gst_element_pads_activate (GstElement * element, gboolean active) gboolean res; GST_CAT_DEBUG_OBJECT (GST_CAT_ELEMENT_PADS, element, - "pads_activate with active %d", active); + "%s pads", active ? "activate" : "deactivate"); iter = gst_element_iterate_src_pads (element); res = @@ -2707,7 +2754,7 @@ gst_element_pads_activate (GstElement * element, gboolean active) goto sink_failed; GST_CAT_DEBUG_OBJECT (GST_CAT_ELEMENT_PADS, element, - "pads_activate successful"); + "pad %sactivation successful", active ? "" : "de"); return TRUE; @@ -2715,7 +2762,7 @@ gst_element_pads_activate (GstElement * element, gboolean active) src_failed: { GST_CAT_DEBUG_OBJECT (GST_CAT_ELEMENT_PADS, element, - "source pads_activate failed"); + "pad %sactivation failed", active ? "" : "de"); return FALSE; } sink_failed: @@ -2816,22 +2863,46 @@ gst_element_dispose (GObject * object) GstElement *element = GST_ELEMENT_CAST (object); GstClock **clock_p; GstBus **bus_p; + GstElementClass *oclass; + GList *walk; + + oclass = GST_ELEMENT_GET_CLASS (element); GST_CAT_INFO_OBJECT (GST_CAT_REFCOUNTING, element, "dispose"); if (GST_STATE (element) != GST_STATE_NULL) goto not_null; - GST_CAT_DEBUG_OBJECT (GST_CAT_ELEMENT_PADS, element, - "removing %d pads", g_list_length (element->pads)); - /* first we break all our links with the outside */ - while (element->pads && element->pads->data) { - /* don't call _remove_pad with NULL */ - gst_element_remove_pad (element, GST_PAD_CAST (element->pads->data)); + /* start by releasing all request pads, this might also remove some dynamic + * pads */ + walk = element->pads; + while (walk) { + GstPad *pad = GST_PAD_CAST (walk->data); + + walk = walk->next; + + if (oclass->release_pad && GST_PAD_PAD_TEMPLATE (pad) && + GST_PAD_TEMPLATE_PRESENCE (GST_PAD_PAD_TEMPLATE (pad)) + == GST_PAD_REQUEST) { + GST_CAT_DEBUG_OBJECT (GST_CAT_ELEMENT_PADS, element, + "removing request pad %s:%s", GST_DEBUG_PAD_NAME (pad)); + oclass->release_pad (element, pad); + + /* in case the release_pad function removed the next pad too */ + if (walk && g_list_position (element->pads, walk) == -1) + walk = element->pads; + } } - if (G_UNLIKELY (element->pads != NULL)) { - g_critical ("could not remove pads from element %s", - GST_STR_NULL (GST_OBJECT_NAME (object))); + /* remove the remaining pads */ + while (element->pads) { + GstPad *pad = GST_PAD_CAST (element->pads->data); + GST_CAT_DEBUG_OBJECT (GST_CAT_ELEMENT_PADS, element, + "removing pad %s:%s", GST_DEBUG_PAD_NAME (pad)); + if (!gst_element_remove_pad (element, pad)) { + /* only happens when someone unparented our pad.. */ + g_critical ("failed to remove pad %s:%s", GST_DEBUG_PAD_NAME (pad)); + break; + } } GST_OBJECT_LOCK (element); @@ -2852,7 +2923,7 @@ not_null: { 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" @@ -2874,8 +2945,8 @@ gst_element_finalize (GObject * object) 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"); @@ -2948,3 +3019,29 @@ gst_element_get_bus (GstElement * element) return result; } + +/** + * gst_element_set_context: + * @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. + * + * MT safe. + */ +void +gst_element_set_context (GstElement * element, GstContext * context) +{ + GstElementClass *oclass; + + g_return_if_fail (GST_IS_ELEMENT (element)); + + oclass = GST_ELEMENT_GET_CLASS (element); + + GST_CAT_DEBUG_OBJECT (GST_CAT_CONTEXT, element, + "set context %p %" GST_PTR_FORMAT, context, + gst_context_get_structure (context)); + + if (oclass->set_context) + oclass->set_context (element, context); +}