From 8df6cd7243a593bfae5f1d85f1283e815eabd176 Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Mon, 9 May 2005 10:53:13 +0000 Subject: [PATCH] Remove old query functions. Ported old code. Original commit message from CVS: Remove old query functions. Ported old code. Added position/convert helper functions to gstutils. Reordered gstpad.c code, grouping relevant things. Remove gst_message_new(), always need to speficy a specific message. --- ChangeLog | 57 + docs/design/draft-push-pull.txt | 26 +- gst/base/gstbasesrc.c | 16 +- gst/elements/gstfilesink.c | 10 +- gst/elements/gsttypefindelement.c | 78 +- gst/gstelement.c | 157 +-- gst/gstelement.h | 60 +- gst/gstmessage.c | 2 +- gst/gstmessage.h | 1 - gst/gstpad.c | 2224 ++++++++++++++------------------- gst/gstpad.h | 88 +- gst/gstquery.c | 110 +- gst/gstquery.h | 16 + gst/gstqueryutils.c | 53 - gst/gstqueryutils.h | 6 - gst/gstqueue.c | 46 +- gst/gstutils.c | 120 ++ gst/gstutils.h | 15 +- libs/gst/base/gstbasesrc.c | 16 +- plugins/elements/gstfilesink.c | 10 +- plugins/elements/gstqueue.c | 46 +- plugins/elements/gsttypefindelement.c | 78 +- tools/gst-inspect.c | 15 +- tools/gst-xmlinspect.c | 19 +- 24 files changed, 1519 insertions(+), 1750 deletions(-) diff --git a/ChangeLog b/ChangeLog index f661d61..aa23ce1 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,60 @@ +2005-05-09 Wim Taymans + + * docs/design/draft-push-pull.txt: + * gst/base/gstbasesrc.c: (gst_basesrc_init), (gst_basesrc_query): + * gst/elements/gstfilesink.c: (gst_filesink_init), + (gst_filesink_query): + * gst/elements/gsttypefindelement.c: (gst_type_find_element_init), + (gst_type_find_handle_src_query), (find_element_get_length): + * gst/gstelement.c: (gst_element_seek), (gst_element_query): + * gst/gstelement.h: + * gst/gstmessage.c: + * gst/gstmessage.h: + * gst/gstpad.c: (gst_real_pad_init), (gst_pad_get_query_types), + (gst_real_pad_get_caps_unlocked), + (gst_pad_get_internal_links_default), (gst_pad_get_internal_links), + (gst_pad_event_default_dispatch), (gst_pad_event_default), + (gst_pad_dispatcher), (gst_pad_query), (gst_pad_query_default), + (gst_real_pad_dispose), (gst_real_pad_finalize), + (gst_pad_load_and_link), (gst_pad_save_thyself), + (gst_ghost_pad_save_thyself), (handle_pad_block), (gst_pad_push), + (gst_pad_check_pull_range), (gst_pad_pull_range), + (gst_pad_template_get_type), (gst_pad_template_class_init), + (gst_pad_template_init), (gst_pad_template_dispose), + (name_is_valid), (gst_static_pad_template_get), + (gst_pad_template_new), (gst_static_pad_template_get_caps), + (gst_pad_template_get_caps), (gst_pad_set_element_private), + (gst_pad_get_element_private), (gst_pad_start_task), + (gst_pad_pause_task), (gst_pad_stop_task), + (gst_ghost_pad_get_type), (gst_ghost_pad_class_init), + (gst_ghost_pad_init), (gst_ghost_pad_dispose), + (gst_ghost_pad_set_property), (gst_ghost_pad_get_property), + (gst_ghost_pad_new): + * gst/gstpad.h: + * gst/gstquery.c: (_gst_query_initialize), (gst_query_new), + (gst_query_new_position), (gst_query_set_position), + (gst_query_parse_position), (gst_query_new_convert), + (gst_query_set_convert), (gst_query_parse_convert): + * gst/gstquery.h: + * gst/gstqueryutils.c: + * gst/gstqueryutils.h: + * gst/gstqueue.c: (gst_queue_init), (gst_queue_getcaps), + (gst_queue_bufferalloc), (gst_queue_handle_sink_event), + (gst_queue_handle_src_query): + * gst/gstutils.c: (gst_element_get_compatible_pad_template), + (gst_element_query_position), (gst_element_query_convert), + (intersect_caps_func), (gst_pad_query_position), + (gst_pad_query_convert): + * gst/gstutils.h: + * tools/gst-inspect.c: (print_pad_info): + * tools/gst-xmlinspect.c: (print_element_info): + Remove old query functions. Ported old code. + Added position/convert helper functions to gstutils. + Reordered gstpad.c code, grouping relevant things. + Remove gst_message_new(), always need to speficy a specific + message. + + 2005-05-09 Andy Wingo * gst/gstiterator.h: Add some includes. diff --git a/docs/design/draft-push-pull.txt b/docs/design/draft-push-pull.txt index fbcbee7..e56ce5f 100644 --- a/docs/design/draft-push-pull.txt +++ b/docs/design/draft-push-pull.txt @@ -80,9 +80,31 @@ Proposition: decision. - - +Things to query: + + - pad can do real random access (downstream peer can ask for offset != -1) + - min offset + - suggest sequential access + - max offset + - align: all offsets should be aligned with this value. + - pad can give ranges from A to B length (peer can ask for A <= length <= B) + - min length + - suggested length + - max length + +Use cases: + + - An audio source can provide random access to the samples queued in its + DMA buffer, it however suggests sequential access method. + An audio source can provide a random number of samples but prefers + reading from the hardware using a fixed segment size. + + - A caching network source would suggest sequential access but is seekable + in the cached region. Applications can query for the already downloaded + portion and update the GUI, a seek can be done in that area. + - a live video source can only provide buffers sequentialy. It exposes + offsets as -1. lengths are also -1. diff --git a/gst/base/gstbasesrc.c b/gst/base/gstbasesrc.c index 5031568..2d7b966 100644 --- a/gst/base/gstbasesrc.c +++ b/gst/base/gstbasesrc.c @@ -89,9 +89,11 @@ static void gst_basesrc_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec); static gboolean gst_basesrc_event_handler (GstPad * pad, GstEvent * event); -static gboolean gst_basesrc_query2 (GstPad * pad, GstQuery * query); +static gboolean gst_basesrc_query (GstPad * pad, GstQuery * query); +#if 0 static const GstEventMask *gst_basesrc_get_event_mask (GstPad * pad); +#endif static gboolean gst_basesrc_unlock (GstBaseSrc * basesrc); static gboolean gst_basesrc_get_size (GstBaseSrc * basesrc, guint64 * size); @@ -158,9 +160,7 @@ gst_basesrc_init (GstBaseSrc * basesrc, gpointer g_class) gst_pad_set_activate_function (pad, gst_basesrc_activate); gst_pad_set_event_function (pad, gst_basesrc_event_handler); - gst_pad_set_event_mask_function (pad, gst_basesrc_get_event_mask); - - gst_pad_set_query2_function (pad, gst_basesrc_query2); + gst_pad_set_query_function (pad, gst_basesrc_query); gst_pad_set_checkgetrange_function (pad, gst_basesrc_check_get_range); @@ -193,7 +193,7 @@ gst_basesrc_set_dataflow_funcs (GstBaseSrc * this) } static gboolean -gst_basesrc_query2 (GstPad * pad, GstQuery * query) +gst_basesrc_query (GstPad * pad, GstQuery * query) { gboolean b; guint64 ui64; @@ -207,7 +207,7 @@ gst_basesrc_query2 (GstPad * pad, GstQuery * query) { GstFormat format; - gst_query_parse_position_query (query, &format); + gst_query_parse_position (query, &format, NULL, NULL); switch (format) { case GST_FORMAT_DEFAULT: case GST_FORMAT_BYTES: @@ -243,10 +243,11 @@ gst_basesrc_query2 (GstPad * pad, GstQuery * query) case GST_QUERY_RATE: case GST_QUERY_CONVERT: default: - return gst_pad_query2_default (pad, query); + return gst_pad_query_default (pad, query); } } +#if 0 static const GstEventMask * gst_basesrc_get_event_mask (GstPad * pad) { @@ -260,6 +261,7 @@ gst_basesrc_get_event_mask (GstPad * pad) }; return masks; } +#endif static gboolean gst_basesrc_do_seek (GstBaseSrc * src, GstEvent * event) diff --git a/gst/elements/gstfilesink.c b/gst/elements/gstfilesink.c index c0da0e3..cc44e97 100644 --- a/gst/elements/gstfilesink.c +++ b/gst/elements/gstfilesink.c @@ -80,7 +80,7 @@ static gboolean gst_filesink_event (GstBaseSink * sink, GstEvent * event); static GstFlowReturn gst_filesink_render (GstBaseSink * sink, GstBuffer * buffer); -static gboolean gst_filesink_query2 (GstPad * pad, GstQuery * query); +static gboolean gst_filesink_query (GstPad * pad, GstQuery * query); static void gst_filesink_uri_handler_init (gpointer g_iface, gpointer iface_data); @@ -144,7 +144,7 @@ gst_filesink_init (GstFileSink * filesink) pad = GST_BASESINK_PAD (filesink); - gst_pad_set_query2_function (pad, gst_filesink_query2); + gst_pad_set_query_function (pad, gst_filesink_query); filesink->filename = NULL; filesink->file = NULL; @@ -255,7 +255,7 @@ gst_filesink_close_file (GstFileSink * sink) } static gboolean -gst_filesink_query2 (GstPad * pad, GstQuery * query) +gst_filesink_query (GstPad * pad, GstQuery * query) { GstFileSink *self; GstFormat format; @@ -264,7 +264,7 @@ gst_filesink_query2 (GstPad * pad, GstQuery * query) switch (GST_QUERY_TYPE (query)) { case GST_QUERY_POSITION: - gst_query_parse_position_query (query, &format); + gst_query_parse_position (query, &format, NULL, NULL); switch (format) { case GST_FORMAT_DEFAULT: case GST_FORMAT_BYTES: @@ -280,7 +280,7 @@ gst_filesink_query2 (GstPad * pad, GstQuery * query) return TRUE; default: - return gst_pad_query2_default (pad, query); + return gst_pad_query_default (pad, query); } } diff --git a/gst/elements/gsttypefindelement.c b/gst/elements/gsttypefindelement.c index 994e04f..5aeece8 100644 --- a/gst/elements/gsttypefindelement.c +++ b/gst/elements/gsttypefindelement.c @@ -115,11 +115,13 @@ static void gst_type_find_element_set_property (GObject * object, static void gst_type_find_element_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec); +#if 0 static const GstEventMask *gst_type_find_element_src_event_mask (GstPad * pad); +#endif + static gboolean gst_type_find_element_src_event (GstPad * pad, GstEvent * event); -static gboolean gst_type_find_handle_src_query (GstPad * pad, - GstQueryType type, GstFormat * fmt, gint64 * value); +static gboolean gst_type_find_handle_src_query (GstPad * pad, GstQuery * query); static GstFlowReturn push_buffer_store (GstTypeFindElement * typefind); static gboolean gst_type_find_element_handle_event (GstPad * pad, @@ -219,8 +221,6 @@ gst_type_find_element_init (GstTypeFindElement * typefind) gst_type_find_element_checkgetrange); gst_pad_set_getrange_function (typefind->src, gst_type_find_element_getrange); gst_pad_set_event_function (typefind->src, gst_type_find_element_src_event); - gst_pad_set_event_mask_function (typefind->src, - gst_type_find_element_src_event_mask); gst_pad_set_query_function (typefind->src, GST_DEBUG_FUNCPTR (gst_type_find_handle_src_query)); gst_pad_use_fixed_caps (typefind->src); @@ -295,32 +295,48 @@ gst_type_find_element_get_property (GObject * object, guint prop_id, } static gboolean -gst_type_find_handle_src_query (GstPad * pad, - GstQueryType type, GstFormat * fmt, gint64 * value) +gst_type_find_handle_src_query (GstPad * pad, GstQuery * query) { - GstTypeFindElement *typefind = - GST_TYPE_FIND_ELEMENT (gst_pad_get_parent (pad)); + GstTypeFindElement *typefind; gboolean res; - res = gst_pad_query (GST_PAD_PEER (typefind->sink), type, fmt, value); + typefind = GST_TYPE_FIND_ELEMENT (GST_PAD_PARENT (pad)); + + res = gst_pad_query (GST_PAD_PEER (typefind->sink), query); if (!res) return FALSE; - if (type == GST_QUERY_POSITION && typefind->store != NULL) { - /* FIXME: this code assumes that there's no discont in the queue */ - switch (*fmt) { - case GST_FORMAT_BYTES: - *value -= gst_buffer_store_get_size (typefind->store, 0); - break; - default: - /* FIXME */ - break; + switch (GST_QUERY_TYPE (query)) { + case GST_QUERY_POSITION: + { + gint64 peer_pos, peer_total; + GstFormat format; + + if (typefind->store == NULL) + return TRUE; + + gst_query_parse_position (query, &format, &peer_pos, &peer_total); + + /* FIXME: this code assumes that there's no discont in the queue */ + switch (format) { + case GST_FORMAT_BYTES: + peer_pos -= gst_buffer_store_get_size (typefind->store, 0); + break; + default: + /* FIXME */ + break; + } + gst_query_set_position (query, format, peer_pos, peer_total); + break; } + default: + break; } return TRUE; } +#if 0 static const GstEventMask * gst_type_find_element_src_event_mask (GstPad * pad) { @@ -334,6 +350,7 @@ gst_type_find_element_src_event_mask (GstPad * pad) return mask; } +#endif static gboolean gst_type_find_element_src_event (GstPad * pad, GstEvent * event) @@ -462,24 +479,29 @@ find_element_get_length (gpointer data) return 0; } if (entry->self->stream_length == 0) { - typefind->stream_length_available = - gst_pad_query (GST_PAD_PEER (entry->self->sink), GST_QUERY_TOTAL, - &format, (gint64 *) & entry->self->stream_length); - if (format != GST_FORMAT_BYTES) + if (!gst_pad_query_position (GST_PAD_PEER (entry->self->sink), &format, + NULL, (gint64 *) & entry->self->stream_length)) + goto no_length; + + if (format != GST_FORMAT_BYTES) { typefind->stream_length_available = FALSE; - if (!typefind->stream_length_available) { - GST_DEBUG_OBJECT (entry->self, - "'%s' called get_length () but it's not available", - GST_PLUGIN_FEATURE_NAME (entry->factory)); - return 0; + entry->self->stream_length = 0; } else { GST_DEBUG_OBJECT (entry->self, "'%s' called get_length () and it's %" G_GUINT64_FORMAT " bytes", GST_PLUGIN_FEATURE_NAME (entry->factory), entry->self->stream_length); } } - return entry->self->stream_length; + +no_length: + { + typefind->stream_length_available = FALSE; + GST_DEBUG_OBJECT (entry->self, + "'%s' called get_length () but it's not available", + GST_PLUGIN_FEATURE_NAME (entry->factory)); + return 0; + } } static gboolean diff --git a/gst/gstelement.c b/gst/gstelement.c index 28ffe83..0523f4f 100644 --- a/gst/gstelement.c +++ b/gst/gstelement.c @@ -1050,48 +1050,6 @@ wrong_direction: } /** - * gst_element_get_event_masks: - * @element: a #GstElement to query - * - * Get an array of event masks from the element. - * If the element doesn't implement an event masks function, - * the query will be forwarded to a random linked sink pad. - * - * Returns: An array of #GstEventMask elements. The array - * cannot be modified or freed. - * - * MT safe. - */ -const GstEventMask * -gst_element_get_event_masks (GstElement * element) -{ - GstElementClass *oclass; - const GstEventMask *result = NULL; - - g_return_val_if_fail (GST_IS_ELEMENT (element), NULL); - - oclass = GST_ELEMENT_GET_CLASS (element); - - if (oclass->get_event_masks) { - result = oclass->get_event_masks (element); - } else { - GstPad *pad = gst_element_get_random_pad (element, GST_PAD_SINK); - - if (pad) { - GstPad *peer = gst_pad_get_peer (pad); - - if (peer) { - result = gst_pad_get_event_masks (peer); - gst_object_unref (GST_OBJECT (peer)); - } - gst_object_unref (GST_OBJECT (pad)); - } - } - - return result; -} - -/** * gst_element_send_event: * @element: a #GstElement to send the event to. * @event: the #GstEvent to send to the element. @@ -1156,9 +1114,12 @@ gst_element_send_event (GstElement * element, GstEvent * event) gboolean gst_element_seek (GstElement * element, GstSeekType seek_type, guint64 offset) { - GstEvent *event = gst_event_new_seek (seek_type, offset); + GstEvent *event; gboolean result; + g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE); + + event = gst_event_new_seek (seek_type, offset); result = gst_element_send_event (element, event); return result; @@ -1224,25 +1185,23 @@ gst_element_get_query_types (GstElement * element) * MT safe. */ gboolean -gst_element_query (GstElement * element, GstQueryType type, - GstFormat * format, gint64 * value) +gst_element_query (GstElement * element, GstQuery * query) { GstElementClass *oclass; gboolean result = FALSE; g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE); - g_return_val_if_fail (format != NULL, FALSE); - g_return_val_if_fail (value != NULL, FALSE); + g_return_val_if_fail (query != NULL, FALSE); oclass = GST_ELEMENT_GET_CLASS (element); if (oclass->query) { - result = oclass->query (element, type, format, value); + result = oclass->query (element, query); } else { GstPad *pad = gst_element_get_random_pad (element, GST_PAD_SRC); if (pad) { - result = gst_pad_query (pad, type, format, value); + result = gst_pad_query (pad, query); gst_object_unref (GST_OBJECT (pad)); } else { @@ -1251,7 +1210,7 @@ gst_element_query (GstElement * element, GstQueryType type, GstPad *peer = gst_pad_get_peer (pad); if (peer) { - result = gst_pad_query (peer, type, format, value); + result = gst_pad_query (peer, query); gst_object_unref (GST_OBJECT (peer)); } @@ -1263,104 +1222,6 @@ gst_element_query (GstElement * element, GstQueryType type, } /** - * gst_element_get_formats: - * @element: a #GstElement to query - * - * Get an array of formats from the element. - * If the element doesn't implement a formats function, - * the query will be forwarded to a random sink pad. - * - * Returns: An array of #GstFormat elements. - * - * MT safe. - */ -const GstFormat * -gst_element_get_formats (GstElement * element) -{ - GstElementClass *oclass; - const GstFormat *result = NULL; - - g_return_val_if_fail (GST_IS_ELEMENT (element), NULL); - - oclass = GST_ELEMENT_GET_CLASS (element); - - if (oclass->get_formats) { - result = oclass->get_formats (element); - } else { - GstPad *pad = gst_element_get_random_pad (element, GST_PAD_SINK); - - if (pad) { - GstPad *peer = gst_pad_get_peer (pad); - - if (peer) { - result = gst_pad_get_formats (peer); - - gst_object_unref (GST_OBJECT (peer)); - } - gst_object_unref (GST_OBJECT (pad)); - } - } - - return result; -} - -/** - * gst_element_convert: - * @element: a #GstElement to invoke the converter on. - * @src_format: the source #GstFormat. - * @src_value: the source value. - * @dest_format: a pointer to the destination #GstFormat. - * @dest_value: a pointer to the destination value. - * - * Invokes a conversion on the element. - * If the element doesn't implement a convert function, - * the query will be forwarded to a random sink pad. - * - * Returns: TRUE if the conversion could be performed. - * - * MT safe. - */ -gboolean -gst_element_convert (GstElement * element, - GstFormat src_format, gint64 src_value, - GstFormat * dest_format, gint64 * dest_value) -{ - GstElementClass *oclass; - gboolean result = FALSE; - - g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE); - g_return_val_if_fail (dest_format != NULL, FALSE); - g_return_val_if_fail (dest_value != NULL, FALSE); - - if (src_format == *dest_format) { - *dest_value = src_value; - return TRUE; - } - - oclass = GST_ELEMENT_GET_CLASS (element); - - if (oclass->convert) { - result = oclass->convert (element, - src_format, src_value, dest_format, dest_value); - } else { - GstPad *pad = gst_element_get_random_pad (element, GST_PAD_SINK); - - if (pad) { - GstPad *peer = gst_pad_get_peer (pad); - - if (peer) { - result = gst_pad_convert (peer, - src_format, src_value, dest_format, dest_value); - - gst_object_unref (GST_OBJECT (peer)); - } - gst_object_unref (GST_OBJECT (pad)); - } - } - return result; -} - -/** * gst_element_post_message: * @element: a #GstElement posting the message * @message: a #GstMessage to post diff --git a/gst/gstelement.h b/gst/gstelement.h index 6e3c137..be4e9f0 100644 --- a/gst/gstelement.h +++ b/gst/gstelement.h @@ -249,13 +249,13 @@ struct _GstElementClass void (*release_pad) (GstElement *element, GstPad *pad); /* state changes */ - GstElementStateReturn (*get_state) (GstElement * element, GstElementState * state, - GstElementState * pending, GTimeVal * timeout); + GstElementStateReturn (*get_state) (GstElement * element, GstElementState * state, + GstElementState * pending, GTimeVal * timeout); GstElementStateReturn (*change_state) (GstElement *element); /* manager */ - void (*set_manager) (GstElement * element, GstPipeline * pipeline); - void (*set_bus) (GstElement * element, GstBus * bus); + void (*set_manager) (GstElement * element, GstPipeline * pipeline); + void (*set_bus) (GstElement * element, GstBus * bus); void (*set_scheduler) (GstElement *element, GstScheduler *scheduler); /* set/get clocks */ @@ -266,16 +266,11 @@ struct _GstElementClass GstIndex* (*get_index) (GstElement *element); void (*set_index) (GstElement *element, GstIndex *index); - /* query/convert/events functions */ - const GstEventMask* (*get_event_masks) (GstElement *element); + /* query functions */ gboolean (*send_event) (GstElement *element, GstEvent *event); - const GstFormat* (*get_formats) (GstElement *element); - gboolean (*convert) (GstElement *element, - GstFormat src_format, gint64 src_value, - GstFormat *dest_format, gint64 *dest_value); + const GstQueryType* (*get_query_types) (GstElement *element); - gboolean (*query) (GstElement *element, GstQueryType type, - GstFormat *format, gint64 *value); + gboolean (*query) (GstElement *element, GstQuery *query); /*< private >*/ gpointer _gst_reserved[GST_PADDING]; @@ -309,10 +304,10 @@ void gst_element_set_index (GstElement *element, GstIndex *index); GstIndex* gst_element_get_index (GstElement *element); /* manager and tasks */ -void gst_element_set_manager (GstElement * element, GstPipeline * pipeline); -GstPipeline *gst_element_get_manager (GstElement * element); -void gst_element_set_bus (GstElement * element, GstBus * bus); -GstBus *gst_element_get_bus (GstElement * element); +void gst_element_set_manager (GstElement * element, GstPipeline * pipeline); +GstPipeline * gst_element_get_manager (GstElement * element); +void gst_element_set_bus (GstElement * element, GstBus * bus); +GstBus * gst_element_get_bus (GstElement * element); void gst_element_set_scheduler (GstElement *element, GstScheduler *sched); GstScheduler* gst_element_get_scheduler (GstElement *element); @@ -330,44 +325,37 @@ void gst_element_release_request_pad (GstElement *element, GstPad *pad); GstIterator * gst_element_iterate_pads (GstElement * element); /* event/query/format stuff */ -G_CONST_RETURN GstEventMask* - gst_element_get_event_masks (GstElement *element); gboolean gst_element_send_event (GstElement *element, GstEvent *event); gboolean gst_element_seek (GstElement *element, GstSeekType seek_type, guint64 offset); G_CONST_RETURN GstQueryType* gst_element_get_query_types (GstElement *element); -gboolean gst_element_query (GstElement *element, GstQueryType type, - GstFormat *format, gint64 *value); -G_CONST_RETURN GstFormat* - gst_element_get_formats (GstElement *element); -gboolean gst_element_convert (GstElement *element, - GstFormat src_format, gint64 src_value, - GstFormat *dest_format, gint64 *dest_value); +gboolean gst_element_query (GstElement *element, GstQuery *query); /* messages */ -gboolean gst_element_post_message (GstElement * element, GstMessage * message); +gboolean gst_element_post_message (GstElement * element, GstMessage * message); /* error handling */ gchar * _gst_element_error_printf (const gchar *format, ...); -void gst_element_message_full (GstElement * element, GstMessageType type, - GQuark domain, gint code, gchar * text, gchar * debug, const gchar * file, - const gchar * function, gint line); +void gst_element_message_full (GstElement * element, GstMessageType type, + GQuark domain, gint code, gchar * text, + gchar * debug, const gchar * file, + const gchar * function, gint line); /* state management */ gboolean gst_element_is_locked_state (GstElement *element); gboolean gst_element_set_locked_state (GstElement *element, gboolean locked_state); gboolean gst_element_sync_state_with_parent (GstElement *element); -GstElementStateReturn gst_element_get_state (GstElement * element, - GstElementState * state, - GstElementState * pending, - GTimeVal * timeout); +GstElementStateReturn gst_element_get_state (GstElement * element, + GstElementState * state, + GstElementState * pending, + GTimeVal * timeout); GstElementStateReturn gst_element_set_state (GstElement *element, GstElementState state); -void gst_element_abort_state (GstElement * element); -void gst_element_commit_state (GstElement * element); -void gst_element_lost_state (GstElement * element); +void gst_element_abort_state (GstElement * element); +void gst_element_commit_state (GstElement * element); +void gst_element_lost_state (GstElement * element); /* factory management */ GstElementFactory* gst_element_get_factory (GstElement *element); diff --git a/gst/gstmessage.c b/gst/gstmessage.c index bc459eb..ab887a8 100644 --- a/gst/gstmessage.c +++ b/gst/gstmessage.c @@ -128,7 +128,7 @@ gst_message_get_type (void) * * MT safe. */ -GstMessage * +static GstMessage * gst_message_new (GstMessageType type, GstObject * src) { GstMessage *message; diff --git a/gst/gstmessage.h b/gst/gstmessage.h index 286682a..91a5743 100644 --- a/gst/gstmessage.h +++ b/gst/gstmessage.h @@ -111,7 +111,6 @@ struct _GstMessage void _gst_message_initialize (void); GType gst_message_get_type (void); -GstMessage * gst_message_new (GstMessageType type, GstObject * src); /* refcounting */ #define gst_message_ref(msg) GST_MESSAGE (gst_data_ref (GST_DATA (msg))) diff --git a/gst/gstpad.c b/gst/gstpad.c index cc63fca..8981c38 100644 --- a/gst/gstpad.c +++ b/gst/gstpad.c @@ -247,16 +247,10 @@ gst_real_pad_init (GstRealPad * pad) pad->getcapsfunc = NULL; pad->eventfunc = gst_pad_event_default; - pad->convertfunc = gst_pad_convert_default; + pad->querytypefunc = gst_pad_get_query_types_default; pad->queryfunc = gst_pad_query_default; pad->intlinkfunc = gst_pad_get_internal_links_default; - pad->query2func = gst_pad_query2_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_UNSET (pad, GST_PAD_ACTIVE); pad->preroll_lock = g_mutex_new (); @@ -879,99 +873,6 @@ gst_pad_set_event_function (GstPad * pad, GstPadEventFunction 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. - * - * Sets the given convert function for the pad. - */ -void -gst_pad_set_convert_function (GstPad * pad, GstPadConvertFunction convert) -{ - g_return_if_fail (GST_IS_REAL_PAD (pad)); - - GST_RPAD_CONVERTFUNC (pad) = convert; - - GST_CAT_DEBUG (GST_CAT_PADS, "convertfunc for %s:%s set to %s", - GST_DEBUG_PAD_NAME (pad), GST_DEBUG_FUNCPTR_NAME (convert)); -} - -/** * gst_pad_set_query_function: * @pad: a real #GstPad of either direction. * @query: the #GstPadQueryFunction to set. @@ -990,24 +891,6 @@ gst_pad_set_query_function (GstPad * pad, GstPadQueryFunction query) } /** - * gst_pad_set_query2_function: - * @pad: a real #GstPad of either direction. - * @query: the #GstPadQueryFunction to set. - * - * Set the given query function for the pad. - */ -void -gst_pad_set_query2_function (GstPad * pad, GstPadQuery2Function query) -{ - g_return_if_fail (GST_IS_REAL_PAD (pad)); - - GST_RPAD_QUERY2FUNC (pad) = query; - - GST_CAT_DEBUG (GST_CAT_PADS, "query2func for %s:%s set to %s", - GST_DEBUG_PAD_NAME (pad), GST_DEBUG_FUNCPTR_NAME (query)); -} - -/** * gst_pad_set_query_type_function: * @pad: a real #GstPad of either direction. * @type_func: the #GstPadQueryTypeFunction to set. @@ -1039,6 +922,7 @@ const GstQueryType * gst_pad_get_query_types (GstPad * pad) { GstRealPad *rpad; + GstPadQueryTypeFunction func; g_return_val_if_fail (GST_IS_PAD (pad), NULL); @@ -1046,10 +930,15 @@ gst_pad_get_query_types (GstPad * pad) g_return_val_if_fail (rpad, NULL); - if (GST_RPAD_QUERYTYPEFUNC (rpad)) - return GST_RPAD_QUERYTYPEFUNC (rpad) (GST_PAD (pad)); + if (G_UNLIKELY ((func = GST_RPAD_QUERYTYPEFUNC (rpad)) == NULL)) + goto no_func; + + return func (GST_PAD (rpad)); - return NULL; +no_func: + { + return NULL; + } } static gboolean @@ -1101,23 +990,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. @@ -1622,6 +1494,8 @@ gst_pad_set_pad_template (GstPad * pad, GstPadTemplate * templ) * * Returns: the #GstPadTemplate from which this pad was instantiated, or %NULL * if this pad has no template. + * + * FIXME: currently returns an unrefcounted padtemplate. */ GstPadTemplate * gst_pad_get_pad_template (GstPad * pad) @@ -1641,7 +1515,7 @@ gst_pad_get_pad_template (GstPad * pad) * returned, as opposed to #gst_pad_get_parent(). * Unref the object after use. * - * Returns: the parent #GstElement. + * Returns: the parent #GstElement. unref after usage. * * MT safe. */ @@ -1717,7 +1591,7 @@ gst_real_pad_get_caps_unlocked (GstRealPad * realpad) GST_FLAG_UNSET (realpad, GST_PAD_IN_GETCAPS); if (result == NULL) { - g_critical ("pad %s:%s returned NULL caps from getcaps function\n", + g_critical ("pad %s:%s returned NULL caps from getcaps function", GST_DEBUG_PAD_NAME (realpad)); } else { #ifndef G_DISABLE_ASSERT @@ -2408,1140 +2282,801 @@ not_negotiated: } } -static void -gst_real_pad_dispose (GObject * object) +/** + * gst_pad_get_internal_links_default: + * @pad: the #GstPad to get the internal links of. + * + * Gets a list of pads to which the given pad is linked to + * inside of the parent element. + * This is the default handler, and thus returns a list of all of the + * pads inside the parent element with opposite direction. + * The caller must free this list after use. + * + * Returns: a newly allocated #GList of pads. + * + * Not MT safe. + */ +GList * +gst_pad_get_internal_links_default (GstPad * pad) { - GstPad *pad; + GList *res = NULL; + GstElement *parent; + GList *parent_pads; + GstPadDirection direction; GstRealPad *rpad; - pad = GST_PAD (object); - rpad = GST_REAL_PAD (object); - - /* No linked pad can ever be disposed. - * It has to have a parent to be linked - * and a parent would hold a reference */ - /* FIXME: what about if g_object_dispose is explicitly called on the pad? Is - that legal? otherwise we could assert GST_OBJECT_PARENT (pad) == NULL as - well... */ - g_assert (GST_PAD_PEER (pad) == NULL); - - GST_CAT_DEBUG (GST_CAT_REFCOUNTING, "dispose %s:%s", - GST_DEBUG_PAD_NAME (pad)); - - /* we destroy the ghostpads, because they are nothing without the real pad */ - if (rpad->ghostpads) { - GList *orig, *ghostpads; + g_return_val_if_fail (GST_IS_PAD (pad), NULL); - orig = ghostpads = g_list_copy (rpad->ghostpads); + rpad = GST_PAD_REALIZE (pad); + direction = rpad->direction; - while (ghostpads) { - GstPad *ghostpad = GST_PAD (ghostpads->data); + parent = GST_PAD_PARENT (rpad); + parent_pads = parent->pads; - if (GST_IS_ELEMENT (GST_OBJECT_PARENT (ghostpad))) { - GstElement *parent = GST_ELEMENT (GST_OBJECT_PARENT (ghostpad)); + while (parent_pads) { + GstRealPad *parent_pad = GST_PAD_REALIZE (parent_pads->data); - GST_CAT_DEBUG (GST_CAT_REFCOUNTING, - "removing ghost pad from element '%s'", GST_OBJECT_NAME (parent)); - gst_element_remove_pad (parent, ghostpad); - } else { - /* handle the case where we have some floating ghost pad that was never - added to an element */ - g_object_set (ghostpad, "real-pad", NULL, NULL); - } - ghostpads = g_list_next (ghostpads); + if (parent_pad->direction != direction) { + res = g_list_prepend (res, parent_pad); } - g_list_free (orig); - /* as the ghost pads are removed, they remove themselves from ->ghostpads. - So it should be empty now. Let's assert that. */ - g_assert (rpad->ghostpads == NULL); - } - /* clear the caps */ - gst_caps_replace (&GST_RPAD_CAPS (pad), NULL); - - if (GST_IS_ELEMENT (GST_OBJECT_PARENT (pad))) { - GST_CAT_DEBUG (GST_CAT_REFCOUNTING, "removing pad from element '%s'", - GST_OBJECT_NAME (GST_OBJECT (GST_ELEMENT (GST_OBJECT_PARENT (pad))))); - - gst_element_remove_pad (GST_ELEMENT (GST_OBJECT_PARENT (pad)), pad); + parent_pads = g_list_next (parent_pads); } - G_OBJECT_CLASS (real_pad_parent_class)->dispose (object); + return res; } -static void -gst_real_pad_finalize (GObject * object) +/** + * gst_pad_get_internal_links: + * @pad: the #GstPad to get the internal links of. + * + * Gets a list of pads to which the given pad is linked to + * inside of the parent element. + * The caller must free this list after use. + * + * Returns: a newly allocated #GList of pads. + * + * Not MT safe. + */ +GList * +gst_pad_get_internal_links (GstPad * pad) { + GList *res = NULL; GstRealPad *rpad; - rpad = GST_REAL_PAD (object); + g_return_val_if_fail (GST_IS_PAD (pad), NULL); - if (rpad->stream_rec_lock) { - g_static_rec_mutex_free (rpad->stream_rec_lock); - rpad->stream_rec_lock = NULL; - } - if (rpad->preroll_lock) { - g_mutex_free (rpad->preroll_lock); - g_cond_free (rpad->preroll_cond); - rpad->preroll_lock = NULL; - rpad->preroll_cond = NULL; - } - if (rpad->block_cond) { - g_cond_free (rpad->block_cond); - rpad->block_cond = NULL; - } + rpad = GST_PAD_REALIZE (pad); - G_OBJECT_CLASS (real_pad_parent_class)->finalize (object); + if (GST_RPAD_INTLINKFUNC (rpad)) + res = GST_RPAD_INTLINKFUNC (rpad) (GST_PAD_CAST (rpad)); + + return res; } -#ifndef GST_DISABLE_LOADSAVE -/* FIXME: why isn't this on a GstElement ? */ -/** - * gst_pad_load_and_link: - * @self: an #xmlNodePtr to read the description from. - * @parent: the #GstObject element that owns the pad. - * - * Reads the pad definition from the XML node and links the given pad - * in the element to a pad of an element up in the hierarchy. - */ -void -gst_pad_load_and_link (xmlNodePtr self, GstObject * parent) +static gboolean +gst_pad_event_default_dispatch (GstPad * pad, GstEvent * event) { - xmlNodePtr field = self->xmlChildrenNode; - GstPad *pad = NULL, *targetpad; - gchar *peer = NULL; - gchar **split; - GstElement *target; - GstObject *grandparent; - gchar *name = NULL; - - while (field) { - if (!strcmp ((char *) field->name, "name")) { - name = (gchar *) xmlNodeGetContent (field); - pad = gst_element_get_pad (GST_ELEMENT (parent), name); - g_free (name); - } else if (!strcmp ((char *) field->name, "peer")) { - peer = (gchar *) xmlNodeGetContent (field); - } - field = field->next; - } - g_return_if_fail (pad != NULL); + GList *orig, *pads; + gboolean result; - if (peer == NULL) - return; + GST_INFO_OBJECT (pad, "Sending event %p to all internally linked pads", + event); - split = g_strsplit (peer, ".", 2); + result = (GST_PAD_DIRECTION (pad) == GST_PAD_SINK); - if (split[0] == NULL || split[1] == NULL) { - GST_CAT_DEBUG (GST_CAT_XML, - "Could not parse peer '%s' for pad %s:%s, leaving unlinked", - peer, GST_DEBUG_PAD_NAME (pad)); + orig = pads = gst_pad_get_internal_links (pad); - g_free (peer); - return; - } - g_free (peer); - - g_return_if_fail (split[0] != NULL); - g_return_if_fail (split[1] != NULL); - - grandparent = gst_object_get_parent (parent); - - if (grandparent && GST_IS_BIN (grandparent)) { - target = gst_bin_get_by_name_recurse_up (GST_BIN (grandparent), split[0]); - } else - goto cleanup; - - if (target == NULL) - goto cleanup; + while (pads) { + GstPad *eventpad = GST_PAD (pads->data); - targetpad = gst_element_get_pad (target, split[1]); + pads = g_list_next (pads); - if (targetpad == NULL) - goto cleanup; + /* for all of the internally-linked pads that are actually linked */ + if (GST_PAD_IS_LINKED (eventpad)) { + if (GST_PAD_DIRECTION (eventpad) == GST_PAD_SRC) { + /* for each pad we send to, we should ref the event; it's up + * to downstream to unref again when handled. */ + GST_LOG_OBJECT (pad, "Reffing and sending event %p to %s:%s", event, + GST_DEBUG_PAD_NAME (eventpad)); + gst_event_ref (event); + gst_pad_push_event (eventpad, event); + } else { + /* we only send the event on one pad, multi-sinkpad elements + * should implement a handler */ + GST_LOG_OBJECT (pad, "sending event %p to one sink pad %s:%s", event, + GST_DEBUG_PAD_NAME (eventpad)); + result = gst_pad_push_event (eventpad, event); + goto done; + } + } + } + /* we handled the incoming event so we unref once */ + GST_LOG_OBJECT (pad, "handled event %p, unreffing", event); + gst_event_unref (event); - gst_pad_link (pad, targetpad); +done: + g_list_free (orig); -cleanup: - g_strfreev (split); + return result; } /** - * gst_pad_save_thyself: - * @pad: a #GstPad to save. - * @parent: the parent #xmlNodePtr to save the description in. + * gst_pad_event_default: + * @pad: a #GstPad to call the default event handler on. + * @event: the #GstEvent to handle. * - * Saves the pad into an xml representation. + * Invokes the default event handler for the given pad. End-of-stream and + * discontinuity events are handled specially, and then the event is sent to all + * pads internally linked to @pad. Note that if there are many possible sink + * pads that are internally linked to @pad, only one will be sent an event. + * Multi-sinkpad elements should implement custom event handlers. * - * Returns: the #xmlNodePtr representation of the pad. + * Returns: TRUE if the event was sent succesfully. */ -static xmlNodePtr -gst_pad_save_thyself (GstObject * object, xmlNodePtr parent) +gboolean +gst_pad_event_default (GstPad * pad, GstEvent * event) { - GstRealPad *realpad; - GstPad *peer; - - g_return_val_if_fail (GST_IS_REAL_PAD (object), NULL); - - realpad = GST_REAL_PAD (object); + g_return_val_if_fail (GST_IS_PAD (pad), FALSE); + g_return_val_if_fail (event != NULL, FALSE); - xmlNewChild (parent, NULL, (xmlChar *) "name", - (xmlChar *) GST_PAD_NAME (realpad)); - if (GST_RPAD_PEER (realpad) != NULL) { - gchar *content; + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_EOS: + { + GstRealPad *rpad = GST_PAD_REALIZE (pad); - peer = GST_PAD (GST_RPAD_PEER (realpad)); - /* first check to see if the peer's parent's parent is the same */ - /* we just save it off */ - content = g_strdup_printf ("%s.%s", - GST_OBJECT_NAME (GST_PAD_PARENT (peer)), GST_PAD_NAME (peer)); - xmlNewChild (parent, NULL, (xmlChar *) "peer", (xmlChar *) content); - g_free (content); - } else - xmlNewChild (parent, NULL, (xmlChar *) "peer", NULL); + if (GST_RPAD_TASK (rpad)) { + GST_DEBUG_OBJECT (rpad, "pausing task because of eos"); + gst_task_pause (GST_RPAD_TASK (rpad)); + } + } + default: + break; + } - return parent; + return gst_pad_event_default_dispatch (pad, event); } /** - * gst_ghost_pad_save_thyself: - * @pad: a ghost #GstPad to save. - * @parent: the parent #xmlNodePtr to save the description in. + * gst_pad_dispatcher: + * @pad: a #GstPad to dispatch. + * @dispatch: the #GstDispatcherFunction to call. + * @data: gpointer user data passed to the dispatcher function. * - * Saves the ghost pad into an xml representation. + * Invokes the given dispatcher function on all pads that are + * internally linked to the given pad. + * The GstPadDispatcherFunction should return TRUE when no further pads + * need to be processed. * - * Returns: the #xmlNodePtr representation of the pad. + * Returns: TRUE if one of the dispatcher functions returned TRUE. */ -xmlNodePtr -gst_ghost_pad_save_thyself (GstPad * pad, xmlNodePtr parent) +gboolean +gst_pad_dispatcher (GstPad * pad, GstPadDispatcherFunction dispatch, + gpointer data) { - xmlNodePtr self; - - g_return_val_if_fail (GST_IS_GHOST_PAD (pad), NULL); - - self = xmlNewChild (parent, NULL, (xmlChar *) "ghostpad", NULL); - xmlNewChild (self, NULL, (xmlChar *) "name", (xmlChar *) GST_PAD_NAME (pad)); - xmlNewChild (self, NULL, (xmlChar *) "parent", - (xmlChar *) GST_OBJECT_NAME (GST_PAD_PARENT (pad))); - - /* FIXME FIXME FIXME! */ - - return self; -} -#endif /* GST_DISABLE_LOADSAVE */ + gboolean res = FALSE; + GList *int_pads, *orig; -/* - * should be called with pad lock held - * - * MT safe. - */ -static void -handle_pad_block (GstRealPad * pad) -{ - GstPadBlockCallback callback; - gpointer user_data; + g_return_val_if_fail (GST_IS_PAD (pad), FALSE); + g_return_val_if_fail (dispatch != NULL, FALSE); - GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, - "signal block taken on pad %s:%s", GST_DEBUG_PAD_NAME (pad)); + orig = int_pads = gst_pad_get_internal_links (pad); - /* need to grab extra ref for the callbacks */ - gst_object_ref (GST_OBJECT (pad)); + while (int_pads) { + GstRealPad *int_rpad = GST_PAD_REALIZE (int_pads->data); + GstRealPad *int_peer = GST_RPAD_PEER (int_rpad); - callback = pad->block_callback; - if (callback) { - user_data = pad->block_data; - GST_UNLOCK (pad); - callback (GST_PAD_CAST (pad), TRUE, user_data); - GST_LOCK (pad); - } else { - GST_PAD_BLOCK_SIGNAL (pad); + if (int_peer) { + res = dispatch (GST_PAD (int_peer), data); + if (res) + break; + } + int_pads = g_list_next (int_pads); } - while (GST_RPAD_IS_BLOCKED (pad)) - GST_PAD_BLOCK_WAIT (pad); - - GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, "got unblocked"); - - callback = pad->block_callback; - if (callback) { - user_data = pad->block_data; - GST_UNLOCK (pad); - callback (GST_PAD_CAST (pad), FALSE, user_data); - GST_LOCK (pad); - } else { - GST_PAD_BLOCK_SIGNAL (pad); - } + g_list_free (orig); - gst_object_unref (GST_OBJECT (pad)); + return res; } /** - * gst_pad_push: - * @pad: a source #GstPad. - * @buffer: the #GstBuffer to push. + * gst_pad_query: + * @pad: a #GstPad to invoke the default query on. + * @query: the #GstQuery to perform. * - * Pushes a buffer to the peer of @pad. @pad must be linked. + * Dispatches a query to a pad. The query should have been allocated by the + * caller via one of the type-specific allocation functions in gstquery.h. The + * element is responsible for filling the query with an appropriate response, + * which should then be parsed with a type-specific query parsing function. * - * Returns: a #GstFlowReturn from the peer pad. + * Again, the caller is responsible for both the allocation and deallocation of + * the query structure. * - * MT safe. + * Returns: TRUE if the query could be performed. */ -GstFlowReturn -gst_pad_push (GstPad * pad, GstBuffer * buffer) +gboolean +gst_pad_query (GstPad * pad, GstQuery * query) { - GstRealPad *peer; - GstFlowReturn ret; - GstPadChainFunction chainfunc; - GstCaps *caps; - gboolean caps_changed; - - g_return_val_if_fail (GST_IS_REAL_PAD (pad), GST_FLOW_ERROR); - g_return_val_if_fail (GST_RPAD_DIRECTION (pad) == GST_PAD_SRC, - GST_FLOW_ERROR); - g_return_val_if_fail (buffer != NULL, GST_FLOW_ERROR); - g_return_val_if_fail (GST_IS_BUFFER (buffer), GST_FLOW_ERROR); + GstRealPad *rpad; + GstPadQueryFunction func; + g_return_val_if_fail (GST_IS_PAD (pad), FALSE); + g_return_val_if_fail (GST_IS_QUERY (query), FALSE); - GST_LOCK (pad); - while (G_UNLIKELY (GST_RPAD_IS_BLOCKED (pad))) - handle_pad_block (GST_REAL_PAD_CAST (pad)); + rpad = GST_PAD_REALIZE (pad); - if (G_UNLIKELY ((peer = GST_RPAD_PEER (pad)) == NULL)) - goto not_linked; + g_return_val_if_fail (rpad, FALSE); - if (G_UNLIKELY (!GST_RPAD_IS_ACTIVE (peer))) - goto not_active; + GST_DEBUG ("sending query %p to pad %s:%s", query, GST_DEBUG_PAD_NAME (pad)); - if (G_UNLIKELY (GST_RPAD_IS_FLUSHING (peer))) - goto flushing; + if ((func = GST_RPAD_QUERYFUNC (rpad)) == NULL) + goto no_func; - gst_object_ref (GST_OBJECT_CAST (peer)); - GST_UNLOCK (pad); + return func (GST_PAD_CAST (rpad), query); - /* FIXME, move capnego this into a base class? */ - caps = GST_BUFFER_CAPS (buffer); - caps_changed = caps && caps != GST_RPAD_CAPS (peer); - GST_DEBUG ("caps changed %d %" GST_PTR_FORMAT "\n", caps_changed, caps); - /* we got a new datatype on the peer pad, see if it can handle it */ - if (G_UNLIKELY (caps_changed)) { - if (G_UNLIKELY (!gst_pad_configure_sink (GST_PAD_CAST (peer), caps))) - goto not_negotiated; +no_func: + { + GST_DEBUG ("pad had no query function"); + return FALSE; } +} - /* NOTE: we read the peer chainfunc unlocked. - * we cannot hold the lock for the peer so we might send - * the data to the wrong function. This is not really a - * problem since functions are assigned at creation time - * and don't change that often... */ - if (G_UNLIKELY ((chainfunc = peer->chainfunc) == NULL)) - goto no_function; - - GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, - "calling chainfunction &%s of peer pad %s:%s", - GST_DEBUG_FUNCPTR_NAME (chainfunc), GST_DEBUG_PAD_NAME (peer)); - - ret = chainfunc (GST_PAD_CAST (peer), buffer); - - gst_object_unref (GST_OBJECT_CAST (peer)); - - return ret; - - /* ERROR recovery here */ -not_linked: - { - GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, - "pushing, but it was not linked"); - GST_UNLOCK (pad); - return GST_FLOW_NOT_CONNECTED; - } -not_active: - { - GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, - "pushing, but it was inactive"); - GST_UNLOCK (pad); - return GST_FLOW_WRONG_STATE; - } -flushing: - { - GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, - "pushing, but pad was flushing"); - GST_UNLOCK (pad); - return GST_FLOW_UNEXPECTED; - } -not_negotiated: - { - GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, - "pushing buffer but peer did not accept"); - return GST_FLOW_NOT_NEGOTIATED; - } -no_function: - { - GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, - "pushing, but not chainhandler"); - GST_ELEMENT_ERROR (GST_PAD_PARENT (pad), CORE, PAD, (NULL), - ("push on pad %s:%s but the peer pad %s:%s has no chainfunction", - GST_DEBUG_PAD_NAME (pad), GST_DEBUG_PAD_NAME (peer))); - gst_object_unref (GST_OBJECT (peer)); - return GST_FLOW_ERROR; - } -} - -/** - * gst_pad_check_pull_range: - * @pad: a sink #GstRealPad. - * - * Checks if a #gst_pad_pull_range() can be performed on the peer - * source pad. This function is used by plugins that want to check - * if they can use random access on the peer source pad. - * - * The peer sourcepad can implement a custom #GstPadCheckGetRangeFunction - * if it needs to perform some logic to determine if pull_range is - * possible. - * - * Returns: a gboolean with the result. - * - * MT safe. - */ gboolean -gst_pad_check_pull_range (GstPad * pad) +gst_pad_query_default (GstPad * pad, GstQuery * query) { - GstRealPad *peer; - gboolean ret; - GstPadCheckGetRangeFunction checkgetrangefunc; - - g_return_val_if_fail (GST_IS_REAL_PAD (pad), FALSE); - - GST_LOCK (pad); - if (GST_RPAD_DIRECTION (pad) != GST_PAD_SINK) - goto wrong_direction; - - if (G_UNLIKELY ((peer = GST_RPAD_PEER (pad)) == NULL)) - goto not_connected; - - gst_object_ref (GST_OBJECT_CAST (peer)); - GST_UNLOCK (pad); - - /* see note in above function */ - if (G_LIKELY ((checkgetrangefunc = peer->checkgetrangefunc) == NULL)) { - ret = GST_RPAD_GETRANGEFUNC (peer) != NULL; - } else { - GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, - "calling checkgetrangefunc %s of peer pad %s:%s", - GST_DEBUG_FUNCPTR_NAME (checkgetrangefunc), GST_DEBUG_PAD_NAME (peer)); - - ret = checkgetrangefunc (GST_PAD_CAST (peer)); - } - - gst_object_unref (GST_OBJECT_CAST (peer)); - - return ret; - - /* ERROR recovery here */ -wrong_direction: - { - GST_UNLOCK (pad); - return FALSE; - } -not_connected: - { - GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, - "checking pull range, but it was not linked"); - GST_UNLOCK (pad); - return FALSE; + switch (GST_QUERY_TYPE (query)) { + case GST_QUERY_POSITION: + case GST_QUERY_SEEKING: + case GST_QUERY_FORMATS: + case GST_QUERY_LATENCY: + case GST_QUERY_JITTER: + case GST_QUERY_RATE: + case GST_QUERY_CONVERT: + default: + return gst_pad_dispatcher + (pad, (GstPadDispatcherFunction) gst_pad_query, query); } } -/** - * gst_pad_pull_range: - * @pad: a sink #GstPad. - * @buffer: a pointer to hold the #GstBuffer. - * @offset: The start offset of the buffer - * @length: The length of the buffer - * - * Pulls a buffer from the peer pad. @pad must be linked. - * - * Returns: a #GstFlowReturn from the peer pad. - * - * MT safe. - */ -GstFlowReturn -gst_pad_pull_range (GstPad * pad, guint64 offset, guint size, - GstBuffer ** buffer) +static void +gst_real_pad_dispose (GObject * object) { - GstRealPad *peer; - GstFlowReturn ret; - GstPadGetRangeFunction getrangefunc; - - g_return_val_if_fail (GST_IS_REAL_PAD (pad), GST_FLOW_ERROR); - g_return_val_if_fail (GST_RPAD_DIRECTION (pad) == GST_PAD_SINK, - GST_FLOW_ERROR); - g_return_val_if_fail (buffer != NULL, GST_FLOW_ERROR); - - GST_LOCK (pad); - - while (G_UNLIKELY (GST_RPAD_IS_BLOCKED (pad))) - handle_pad_block (GST_REAL_PAD_CAST (pad)); - - if (G_UNLIKELY ((peer = GST_RPAD_PEER (pad)) == NULL)) - goto not_connected; - - if (G_UNLIKELY (!GST_RPAD_IS_ACTIVE (peer))) - goto not_active; + GstPad *pad; + GstRealPad *rpad; - if (G_UNLIKELY (GST_RPAD_IS_FLUSHING (peer))) - goto flushing; + pad = GST_PAD (object); + rpad = GST_REAL_PAD (object); - gst_object_ref (GST_OBJECT_CAST (peer)); - GST_UNLOCK (pad); + /* No linked pad can ever be disposed. + * It has to have a parent to be linked + * and a parent would hold a reference */ + /* FIXME: what about if g_object_dispose is explicitly called on the pad? Is + that legal? otherwise we could assert GST_OBJECT_PARENT (pad) == NULL as + well... */ + g_assert (GST_PAD_PEER (pad) == NULL); - /* see note in above function */ - if (G_UNLIKELY ((getrangefunc = peer->getrangefunc) == NULL)) - goto no_function; + GST_CAT_DEBUG (GST_CAT_REFCOUNTING, "dispose %s:%s", + GST_DEBUG_PAD_NAME (pad)); - GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, - "calling getrangefunc %s of peer pad %s:%s, offset %" - G_GUINT64_FORMAT ", size %u", - GST_DEBUG_FUNCPTR_NAME (getrangefunc), GST_DEBUG_PAD_NAME (peer), - offset, size); + /* we destroy the ghostpads, because they are nothing without the real pad */ + if (rpad->ghostpads) { + GList *orig, *ghostpads; - ret = getrangefunc (GST_PAD_CAST (peer), offset, size, buffer); + orig = ghostpads = g_list_copy (rpad->ghostpads); - gst_object_unref (GST_OBJECT_CAST (peer)); + while (ghostpads) { + GstPad *ghostpad = GST_PAD (ghostpads->data); - return ret; + if (GST_IS_ELEMENT (GST_OBJECT_PARENT (ghostpad))) { + GstElement *parent = GST_ELEMENT (GST_OBJECT_PARENT (ghostpad)); - /* ERROR recovery here */ -not_connected: - { - GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, - "pulling range, but it was not linked"); - GST_UNLOCK (pad); - return GST_FLOW_NOT_CONNECTED; - } -not_active: - { - GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, - "pulling range, but it was inactive"); - GST_UNLOCK (pad); - return GST_FLOW_WRONG_STATE; - } -flushing: - { - GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, - "pulling range, but pad was flushing"); - GST_UNLOCK (pad); - return GST_FLOW_UNEXPECTED; - } -no_function: - { - GST_ELEMENT_ERROR (GST_PAD_PARENT (pad), CORE, PAD, (NULL), - ("pullrange on pad %s:%s but the peer pad %s:%s has no getrangefunction", - GST_DEBUG_PAD_NAME (pad), GST_DEBUG_PAD_NAME (peer))); - gst_object_unref (GST_OBJECT (peer)); - return GST_FLOW_ERROR; + GST_CAT_DEBUG (GST_CAT_REFCOUNTING, + "removing ghost pad from element '%s'", GST_OBJECT_NAME (parent)); + gst_element_remove_pad (parent, ghostpad); + } else { + /* handle the case where we have some floating ghost pad that was never + added to an element */ + g_object_set (ghostpad, "real-pad", NULL, NULL); + } + ghostpads = g_list_next (ghostpads); + } + g_list_free (orig); + /* as the ghost pads are removed, they remove themselves from ->ghostpads. + So it should be empty now. Let's assert that. */ + g_assert (rpad->ghostpads == NULL); } -} - -/************************************************************************ - * - * templates - * - */ -static void gst_pad_template_class_init (GstPadTemplateClass * klass); -static void gst_pad_template_init (GstPadTemplate * templ); -static void gst_pad_template_dispose (GObject * object); -GType -gst_pad_template_get_type (void) -{ - static GType padtemplate_type = 0; + /* clear the caps */ + gst_caps_replace (&GST_RPAD_CAPS (pad), NULL); - if (!padtemplate_type) { - static const GTypeInfo padtemplate_info = { - sizeof (GstPadTemplateClass), NULL, NULL, - (GClassInitFunc) gst_pad_template_class_init, NULL, NULL, - sizeof (GstPadTemplate), - 0, - (GInstanceInitFunc) gst_pad_template_init, NULL - }; + if (GST_IS_ELEMENT (GST_OBJECT_PARENT (pad))) { + GST_CAT_DEBUG (GST_CAT_REFCOUNTING, "removing pad from element '%s'", + GST_OBJECT_NAME (GST_OBJECT (GST_ELEMENT (GST_OBJECT_PARENT (pad))))); - padtemplate_type = - g_type_register_static (GST_TYPE_OBJECT, "GstPadTemplate", - &padtemplate_info, 0); + gst_element_remove_pad (GST_ELEMENT (GST_OBJECT_PARENT (pad)), pad); } - return padtemplate_type; -} -static void -gst_pad_template_class_init (GstPadTemplateClass * klass) -{ - GObjectClass *gobject_class; - GstObjectClass *gstobject_class; - - gobject_class = (GObjectClass *) klass; - gstobject_class = (GstObjectClass *) klass; - - padtemplate_parent_class = g_type_class_ref (GST_TYPE_OBJECT); - - gst_pad_template_signals[TEMPL_PAD_CREATED] = - g_signal_new ("pad-created", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (GstPadTemplateClass, pad_created), - NULL, NULL, gst_marshal_VOID__OBJECT, G_TYPE_NONE, 1, GST_TYPE_PAD); - - gobject_class->dispose = gst_pad_template_dispose; - - gstobject_class->path_string_separator = "*"; + G_OBJECT_CLASS (real_pad_parent_class)->dispose (object); } static void -gst_pad_template_init (GstPadTemplate * templ) +gst_real_pad_finalize (GObject * object) { -} + GstRealPad *rpad; -static void -gst_pad_template_dispose (GObject * object) -{ - GstPadTemplate *templ = GST_PAD_TEMPLATE (object); + rpad = GST_REAL_PAD (object); - g_free (GST_PAD_TEMPLATE_NAME_TEMPLATE (templ)); - if (GST_PAD_TEMPLATE_CAPS (templ)) { - gst_caps_unref (GST_PAD_TEMPLATE_CAPS (templ)); + if (rpad->stream_rec_lock) { + g_static_rec_mutex_free (rpad->stream_rec_lock); + rpad->stream_rec_lock = NULL; } - - G_OBJECT_CLASS (padtemplate_parent_class)->dispose (object); -} - -/* ALWAYS padtemplates cannot have conversion specifications, it doesn't make - * sense. - * SOMETIMES padtemplates can do whatever they want, they are provided by the - * element. - * REQUEST padtemplates can be reverse-parsed (the user asks for 'sink1', the - * 'sink%d' template is automatically selected), so we need to restrict their - * naming. - */ -static gboolean -name_is_valid (const gchar * name, GstPadPresence presence) -{ - const gchar *str; - - if (presence == GST_PAD_ALWAYS) { - if (strchr (name, '%')) { - g_warning ("invalid name template %s: conversion specifications are not" - " allowed for GST_PAD_ALWAYS padtemplates", name); - return FALSE; - } - } else if (presence == GST_PAD_REQUEST) { - if ((str = strchr (name, '%')) && strchr (str + 1, '%')) { - g_warning ("invalid name template %s: only one conversion specification" - " allowed in GST_PAD_REQUEST padtemplate", name); - return FALSE; - } - if (str && (*(str + 1) != 's' && *(str + 1) != 'd')) { - g_warning ("invalid name template %s: conversion specification must be of" - " type '%%d' or '%%s' for GST_PAD_REQUEST padtemplate", name); - return FALSE; - } - if (str && (*(str + 2) != '\0')) { - g_warning ("invalid name template %s: conversion specification must" - " appear at the end of the GST_PAD_REQUEST padtemplate name", name); - return FALSE; - } + if (rpad->preroll_lock) { + g_mutex_free (rpad->preroll_lock); + g_cond_free (rpad->preroll_cond); + rpad->preroll_lock = NULL; + rpad->preroll_cond = NULL; + } + if (rpad->block_cond) { + g_cond_free (rpad->block_cond); + rpad->block_cond = NULL; } - return TRUE; + G_OBJECT_CLASS (real_pad_parent_class)->finalize (object); } + +#ifndef GST_DISABLE_LOADSAVE +/* FIXME: why isn't this on a GstElement ? */ /** - * gst_static_pad_template_get: - * @pad_template: the static pad template - * - * Converts a #GstStaticPadTemplate into a #GstPadTemplate. + * gst_pad_load_and_link: + * @self: an #xmlNodePtr to read the description from. + * @parent: the #GstObject element that owns the pad. * - * Returns: a new #GstPadTemplate. + * Reads the pad definition from the XML node and links the given pad + * in the element to a pad of an element up in the hierarchy. */ -GstPadTemplate * -gst_static_pad_template_get (GstStaticPadTemplate * pad_template) +void +gst_pad_load_and_link (xmlNodePtr self, GstObject * parent) { - GstPadTemplate *new; - - if (!name_is_valid (pad_template->name_template, pad_template->presence)) - return NULL; - - new = g_object_new (gst_pad_template_get_type (), - "name", pad_template->name_template, NULL); - - GST_PAD_TEMPLATE_NAME_TEMPLATE (new) = g_strdup (pad_template->name_template); - GST_PAD_TEMPLATE_DIRECTION (new) = pad_template->direction; - GST_PAD_TEMPLATE_PRESENCE (new) = pad_template->presence; + xmlNodePtr field = self->xmlChildrenNode; + GstPad *pad = NULL, *targetpad; + gchar *peer = NULL; + gchar **split; + GstElement *target; + GstObject *grandparent; + gchar *name = NULL; - GST_PAD_TEMPLATE_CAPS (new) = - gst_caps_copy (gst_static_caps_get (&pad_template->static_caps)); + while (field) { + if (!strcmp ((char *) field->name, "name")) { + name = (gchar *) xmlNodeGetContent (field); + pad = gst_element_get_pad (GST_ELEMENT (parent), name); + g_free (name); + } else if (!strcmp ((char *) field->name, "peer")) { + peer = (gchar *) xmlNodeGetContent (field); + } + field = field->next; + } + g_return_if_fail (pad != NULL); - return new; -} + if (peer == NULL) + return; -/** - * gst_pad_template_new: - * @name_template: the name template. - * @direction: the #GstPadDirection of the template. - * @presence: the #GstPadPresence of the pad. - * @caps: a #GstCaps set for the template. The caps are taken ownership of. - * - * Creates a new pad template with a name according to the given template - * and with the given arguments. This functions takes ownership of the provided - * caps, so be sure to not use them afterwards. - * - * Returns: a new #GstPadTemplate. - */ -GstPadTemplate * -gst_pad_template_new (const gchar * name_template, - GstPadDirection direction, GstPadPresence presence, GstCaps * caps) -{ - GstPadTemplate *new; + split = g_strsplit (peer, ".", 2); - g_return_val_if_fail (name_template != NULL, NULL); - g_return_val_if_fail (caps != NULL, NULL); - g_return_val_if_fail (direction == GST_PAD_SRC - || direction == GST_PAD_SINK, NULL); - g_return_val_if_fail (presence == GST_PAD_ALWAYS - || presence == GST_PAD_SOMETIMES || presence == GST_PAD_REQUEST, NULL); + if (split[0] == NULL || split[1] == NULL) { + GST_CAT_DEBUG (GST_CAT_XML, + "Could not parse peer '%s' for pad %s:%s, leaving unlinked", + peer, GST_DEBUG_PAD_NAME (pad)); - if (!name_is_valid (name_template, presence)) - return NULL; + g_free (peer); + return; + } + g_free (peer); - new = g_object_new (gst_pad_template_get_type (), - "name", name_template, NULL); + g_return_if_fail (split[0] != NULL); + g_return_if_fail (split[1] != NULL); - GST_PAD_TEMPLATE_NAME_TEMPLATE (new) = g_strdup (name_template); - GST_PAD_TEMPLATE_DIRECTION (new) = direction; - GST_PAD_TEMPLATE_PRESENCE (new) = presence; - GST_PAD_TEMPLATE_CAPS (new) = caps; + grandparent = gst_object_get_parent (parent); - return new; -} + if (grandparent && GST_IS_BIN (grandparent)) { + target = gst_bin_get_by_name_recurse_up (GST_BIN (grandparent), split[0]); + } else + goto cleanup; -/** - * gst_static_pad_template_get_caps: - * @templ: a #GstStaticPadTemplate to get capabilities of. - * - * Gets the capabilities of the static pad template. - * - * Returns: the #GstCaps of the static pad template. If you need to keep a - * reference to the caps, take a ref (see gst_caps_ref ()). - */ -GstCaps * -gst_static_pad_template_get_caps (GstStaticPadTemplate * templ) -{ - g_return_val_if_fail (templ, NULL); + if (target == NULL) + goto cleanup; - return (GstCaps *) gst_static_caps_get (&templ->static_caps); -} + targetpad = gst_element_get_pad (target, split[1]); -/** - * gst_pad_template_get_caps: - * @templ: a #GstPadTemplate to get capabilities of. - * - * Gets the capabilities of the pad template. - * - * Returns: the #GstCaps of the pad template. If you need to keep a reference to - * the caps, take a ref (see gst_caps_ref ()). - */ -GstCaps * -gst_pad_template_get_caps (GstPadTemplate * templ) -{ - g_return_val_if_fail (GST_IS_PAD_TEMPLATE (templ), NULL); + if (targetpad == NULL) + goto cleanup; - return GST_PAD_TEMPLATE_CAPS (templ); -} + gst_pad_link (pad, targetpad); -/** - * gst_pad_set_element_private: - * @pad: the #GstPad to set the private data of. - * @priv: The private data to attach to the pad. - * - * Set the given private data gpointer on the pad. - * This function can only be used by the element that owns the pad. - */ -void -gst_pad_set_element_private (GstPad * pad, gpointer priv) -{ - pad->element_private = priv; +cleanup: + g_strfreev (split); } /** - * gst_pad_get_element_private: - * @pad: the #GstPad to get the private data of. + * gst_pad_save_thyself: + * @pad: a #GstPad to save. + * @parent: the parent #xmlNodePtr to save the description in. * - * Gets the private data of a pad. + * Saves the pad into an xml representation. * - * Returns: a #gpointer to the private data. + * Returns: the #xmlNodePtr representation of the pad. */ -gpointer -gst_pad_get_element_private (GstPad * pad) -{ - return pad->element_private; -} - -gboolean -gst_pad_start_task (GstPad * pad) -{ - g_warning ("implement gst_pad_start_task()"); - return FALSE; -} - -gboolean -gst_pad_pause_task (GstPad * pad) -{ - g_warning ("implement gst_pad_pause_task()"); - return FALSE; -} - -gboolean -gst_pad_stop_task (GstPad * pad) +static xmlNodePtr +gst_pad_save_thyself (GstObject * object, xmlNodePtr parent) { - g_warning ("implement gst_pad_stop_task()"); - return FALSE; -} - - -/***** ghost pads *****/ -GType _gst_ghost_pad_type = 0; + GstRealPad *realpad; + GstPad *peer; -static void gst_ghost_pad_class_init (GstGhostPadClass * klass); -static void gst_ghost_pad_init (GstGhostPad * pad); -static void gst_ghost_pad_dispose (GObject * object); -static void gst_ghost_pad_get_property (GObject * object, guint prop_id, - GValue * value, GParamSpec * pspec); -static void gst_ghost_pad_set_property (GObject * object, guint prop_id, - const GValue * value, GParamSpec * pspec); + g_return_val_if_fail (GST_IS_REAL_PAD (object), NULL); -static GstPad *ghost_pad_parent_class = NULL; + realpad = GST_REAL_PAD (object); -/* static guint gst_ghost_pad_signals[LAST_SIGNAL] = { 0 }; */ -enum -{ - GPAD_ARG_0, - GPAD_ARG_REAL_PAD - /* fill me */ -}; + xmlNewChild (parent, NULL, (xmlChar *) "name", + (xmlChar *) GST_PAD_NAME (realpad)); + if (GST_RPAD_PEER (realpad) != NULL) { + gchar *content; -GType -gst_ghost_pad_get_type (void) -{ - if (!_gst_ghost_pad_type) { - static const GTypeInfo pad_info = { - sizeof (GstGhostPadClass), NULL, NULL, - (GClassInitFunc) gst_ghost_pad_class_init, NULL, NULL, - sizeof (GstGhostPad), - 0, - (GInstanceInitFunc) gst_ghost_pad_init, - NULL - }; + peer = GST_PAD (GST_RPAD_PEER (realpad)); + /* first check to see if the peer's parent's parent is the same */ + /* we just save it off */ + content = g_strdup_printf ("%s.%s", + GST_OBJECT_NAME (GST_PAD_PARENT (peer)), GST_PAD_NAME (peer)); + xmlNewChild (parent, NULL, (xmlChar *) "peer", (xmlChar *) content); + g_free (content); + } else + xmlNewChild (parent, NULL, (xmlChar *) "peer", NULL); - _gst_ghost_pad_type = g_type_register_static (GST_TYPE_PAD, "GstGhostPad", - &pad_info, 0); - } - return _gst_ghost_pad_type; + return parent; } -static void -gst_ghost_pad_class_init (GstGhostPadClass * klass) +/** + * gst_ghost_pad_save_thyself: + * @pad: a ghost #GstPad to save. + * @parent: the parent #xmlNodePtr to save the description in. + * + * Saves the ghost pad into an xml representation. + * + * Returns: the #xmlNodePtr representation of the pad. + */ +xmlNodePtr +gst_ghost_pad_save_thyself (GstPad * pad, xmlNodePtr parent) { - GObjectClass *gobject_class; - - gobject_class = (GObjectClass *) klass; + xmlNodePtr self; - ghost_pad_parent_class = g_type_class_ref (GST_TYPE_PAD); + g_return_val_if_fail (GST_IS_GHOST_PAD (pad), NULL); - gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_ghost_pad_dispose); - gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_ghost_pad_set_property); - gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_ghost_pad_get_property); + self = xmlNewChild (parent, NULL, (xmlChar *) "ghostpad", NULL); + xmlNewChild (self, NULL, (xmlChar *) "name", (xmlChar *) GST_PAD_NAME (pad)); + xmlNewChild (self, NULL, (xmlChar *) "parent", + (xmlChar *) GST_OBJECT_NAME (GST_PAD_PARENT (pad))); - g_object_class_install_property (gobject_class, GPAD_ARG_REAL_PAD, - g_param_spec_object ("real-pad", "Real pad", - "The real pad for the ghost pad", GST_TYPE_PAD, G_PARAM_READWRITE)); -} + /* FIXME FIXME FIXME! */ -static void -gst_ghost_pad_init (GstGhostPad * pad) -{ - /* zeroed by glib */ + return self; } +#endif /* GST_DISABLE_LOADSAVE */ +/* + * should be called with pad lock held + * + * MT safe. + */ static void -gst_ghost_pad_dispose (GObject * object) +handle_pad_block (GstRealPad * pad) { - g_object_set (object, "real-pad", NULL, NULL); + GstPadBlockCallback callback; + gpointer user_data; - G_OBJECT_CLASS (ghost_pad_parent_class)->dispose (object); -} + GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, + "signal block taken on pad %s:%s", GST_DEBUG_PAD_NAME (pad)); -static void -gst_ghost_pad_set_property (GObject * object, guint prop_id, - const GValue * value, GParamSpec * pspec) -{ - GstPad *ghostpad = (GstPad *) object; - GstPad *oldrealpad = (GstPad *) GST_GPAD_REALPAD (ghostpad); - GstPad *realpad = NULL; + /* need to grab extra ref for the callbacks */ + gst_object_ref (GST_OBJECT (pad)); - switch (prop_id) { - case GPAD_ARG_REAL_PAD: - realpad = g_value_get_object (value); + callback = pad->block_callback; + if (callback) { + user_data = pad->block_data; + GST_UNLOCK (pad); + callback (GST_PAD_CAST (pad), TRUE, user_data); + GST_LOCK (pad); + } else { + GST_PAD_BLOCK_SIGNAL (pad); + } - if (oldrealpad) { - if (realpad == oldrealpad) - return; - else - gst_pad_remove_ghost_pad (oldrealpad, ghostpad); - } + while (GST_RPAD_IS_BLOCKED (pad)) + GST_PAD_BLOCK_WAIT (pad); - if (realpad) - gst_pad_add_ghost_pad (realpad, ghostpad); - break; + GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, "got unblocked"); - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; + callback = pad->block_callback; + if (callback) { + user_data = pad->block_data; + GST_UNLOCK (pad); + callback (GST_PAD_CAST (pad), FALSE, user_data); + GST_LOCK (pad); + } else { + GST_PAD_BLOCK_SIGNAL (pad); } + + gst_object_unref (GST_OBJECT (pad)); } -static void -gst_ghost_pad_get_property (GObject * object, guint prop_id, - GValue * value, GParamSpec * pspec) -{ - switch (prop_id) { - case GPAD_ARG_REAL_PAD: - g_value_set_object (value, GST_GPAD_REALPAD (object)); - break; +/********************************************************************** + * Data passing functions + */ - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} /** - * gst_ghost_pad_new: - * @name: the name of the new ghost pad. - * @pad: the #GstPad to create a ghost pad for. + * gst_pad_push: + * @pad: a source #GstPad. + * @buffer: the #GstBuffer to push. * - * Creates a new ghost pad associated with @pad, and named @name. If @name is - * %NULL, a guaranteed unique name (across all ghost pads) will be assigned. + * Pushes a buffer to the peer of @pad. @pad must be linked. * - * Returns: a new ghost #GstPad, or %NULL in case of an error. + * Returns: a #GstFlowReturn from the peer pad. + * + * MT safe. */ -GstPad * -gst_ghost_pad_new (const gchar * name, GstPad * pad) +GstFlowReturn +gst_pad_push (GstPad * pad, GstBuffer * buffer) { - GstPad *gpad; + GstRealPad *peer; + GstFlowReturn ret; + GstPadChainFunction chainfunc; + GstCaps *caps; + gboolean caps_changed; - g_return_val_if_fail (GST_IS_PAD (pad), NULL); + g_return_val_if_fail (GST_IS_REAL_PAD (pad), GST_FLOW_ERROR); + g_return_val_if_fail (GST_RPAD_DIRECTION (pad) == GST_PAD_SRC, + GST_FLOW_ERROR); + g_return_val_if_fail (buffer != NULL, GST_FLOW_ERROR); + g_return_val_if_fail (GST_IS_BUFFER (buffer), GST_FLOW_ERROR); - gpad = g_object_new (GST_TYPE_GHOST_PAD, "name", name, "real-pad", pad, NULL); - GST_CAT_DEBUG (GST_CAT_PADS, "created ghost pad \"%s\" for pad %s:%s", - GST_OBJECT_NAME (gpad), GST_DEBUG_PAD_NAME (pad)); + GST_LOCK (pad); + while (G_UNLIKELY (GST_RPAD_IS_BLOCKED (pad))) + handle_pad_block (GST_REAL_PAD_CAST (pad)); + + if (G_UNLIKELY ((peer = GST_RPAD_PEER (pad)) == NULL)) + goto not_linked; + + if (G_UNLIKELY (!GST_RPAD_IS_ACTIVE (peer))) + goto not_active; + + if (G_UNLIKELY (GST_RPAD_IS_FLUSHING (peer))) + goto flushing; - return gpad; -} + gst_object_ref (GST_OBJECT_CAST (peer)); + GST_UNLOCK (pad); -/** - * gst_pad_get_internal_links_default: - * @pad: the #GstPad to get the internal links of. - * - * Gets a list of pads to which the given pad is linked to - * inside of the parent element. - * This is the default handler, and thus returns a list of all of the - * pads inside the parent element with opposite direction. - * The caller must free this list after use. - * - * Returns: a newly allocated #GList of pads. - * - * Not MT safe. - */ -GList * -gst_pad_get_internal_links_default (GstPad * pad) -{ - GList *res = NULL; - GstElement *parent; - GList *parent_pads; - GstPadDirection direction; - GstRealPad *rpad; + /* FIXME, move capnego this into a base class? */ + caps = GST_BUFFER_CAPS (buffer); + caps_changed = caps && caps != GST_RPAD_CAPS (peer); + GST_DEBUG ("caps changed %d %" GST_PTR_FORMAT, caps_changed, caps); + /* we got a new datatype on the peer pad, see if it can handle it */ + if (G_UNLIKELY (caps_changed)) { + if (G_UNLIKELY (!gst_pad_configure_sink (GST_PAD_CAST (peer), caps))) + goto not_negotiated; + } - g_return_val_if_fail (GST_IS_PAD (pad), NULL); + /* NOTE: we read the peer chainfunc unlocked. + * we cannot hold the lock for the peer so we might send + * the data to the wrong function. This is not really a + * problem since functions are assigned at creation time + * and don't change that often... */ + if (G_UNLIKELY ((chainfunc = peer->chainfunc) == NULL)) + goto no_function; - rpad = GST_PAD_REALIZE (pad); - direction = rpad->direction; + GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, + "calling chainfunction &%s of peer pad %s:%s", + GST_DEBUG_FUNCPTR_NAME (chainfunc), GST_DEBUG_PAD_NAME (peer)); - parent = GST_PAD_PARENT (rpad); - parent_pads = parent->pads; + ret = chainfunc (GST_PAD_CAST (peer), buffer); - while (parent_pads) { - GstRealPad *parent_pad = GST_PAD_REALIZE (parent_pads->data); + gst_object_unref (GST_OBJECT_CAST (peer)); - if (parent_pad->direction != direction) { - res = g_list_prepend (res, parent_pad); - } + return ret; - parent_pads = g_list_next (parent_pads); + /* ERROR recovery here */ +not_linked: + { + GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, + "pushing, but it was not linked"); + GST_UNLOCK (pad); + return GST_FLOW_NOT_CONNECTED; + } +not_active: + { + GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, + "pushing, but it was inactive"); + GST_UNLOCK (pad); + return GST_FLOW_WRONG_STATE; + } +flushing: + { + GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, + "pushing, but pad was flushing"); + GST_UNLOCK (pad); + return GST_FLOW_UNEXPECTED; + } +not_negotiated: + { + GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, + "pushing buffer but peer did not accept"); + return GST_FLOW_NOT_NEGOTIATED; + } +no_function: + { + GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, + "pushing, but not chainhandler"); + GST_ELEMENT_ERROR (GST_PAD_PARENT (pad), CORE, PAD, (NULL), + ("push on pad %s:%s but the peer pad %s:%s has no chainfunction", + GST_DEBUG_PAD_NAME (pad), GST_DEBUG_PAD_NAME (peer))); + gst_object_unref (GST_OBJECT (peer)); + return GST_FLOW_ERROR; } - - return res; } /** - * gst_pad_get_internal_links: - * @pad: the #GstPad to get the internal links of. + * gst_pad_check_pull_range: + * @pad: a sink #GstRealPad. * - * Gets a list of pads to which the given pad is linked to - * inside of the parent element. - * The caller must free this list after use. + * Checks if a #gst_pad_pull_range() can be performed on the peer + * source pad. This function is used by plugins that want to check + * if they can use random access on the peer source pad. * - * Returns: a newly allocated #GList of pads. + * The peer sourcepad can implement a custom #GstPadCheckGetRangeFunction + * if it needs to perform some logic to determine if pull_range is + * possible. * - * Not MT safe. + * Returns: a gboolean with the result. + * + * MT safe. */ -GList * -gst_pad_get_internal_links (GstPad * pad) +gboolean +gst_pad_check_pull_range (GstPad * pad) { - GList *res = NULL; - GstRealPad *rpad; - - g_return_val_if_fail (GST_IS_PAD (pad), NULL); - - rpad = GST_PAD_REALIZE (pad); - - if (GST_RPAD_INTLINKFUNC (rpad)) - res = GST_RPAD_INTLINKFUNC (rpad) (GST_PAD_CAST (rpad)); + GstRealPad *peer; + gboolean ret; + GstPadCheckGetRangeFunction checkgetrangefunc; - return res; -} + g_return_val_if_fail (GST_IS_REAL_PAD (pad), FALSE); + GST_LOCK (pad); + if (GST_RPAD_DIRECTION (pad) != GST_PAD_SINK) + goto wrong_direction; -static gboolean -gst_pad_event_default_dispatch (GstPad * pad, GstEvent * event) -{ - GList *orig, *pads; - gboolean result; + if (G_UNLIKELY ((peer = GST_RPAD_PEER (pad)) == NULL)) + goto not_connected; - GST_INFO_OBJECT (pad, "Sending event %p to all internally linked pads", - event); + gst_object_ref (GST_OBJECT_CAST (peer)); + GST_UNLOCK (pad); - result = (GST_PAD_DIRECTION (pad) == GST_PAD_SINK); + /* see note in above function */ + if (G_LIKELY ((checkgetrangefunc = peer->checkgetrangefunc) == NULL)) { + ret = GST_RPAD_GETRANGEFUNC (peer) != NULL; + } else { + GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, + "calling checkgetrangefunc %s of peer pad %s:%s", + GST_DEBUG_FUNCPTR_NAME (checkgetrangefunc), GST_DEBUG_PAD_NAME (peer)); - orig = pads = gst_pad_get_internal_links (pad); + ret = checkgetrangefunc (GST_PAD_CAST (peer)); + } - while (pads) { - GstPad *eventpad = GST_PAD (pads->data); + gst_object_unref (GST_OBJECT_CAST (peer)); - pads = g_list_next (pads); + return ret; - /* for all of the internally-linked pads that are actually linked */ - if (GST_PAD_IS_LINKED (eventpad)) { - if (GST_PAD_DIRECTION (eventpad) == GST_PAD_SRC) { - /* for each pad we send to, we should ref the event; it's up - * to downstream to unref again when handled. */ - GST_LOG_OBJECT (pad, "Reffing and sending event %p to %s:%s", event, - GST_DEBUG_PAD_NAME (eventpad)); - gst_event_ref (event); - gst_pad_push_event (eventpad, event); - } else { - /* we only send the event on one pad, multi-sinkpad elements - * should implement a handler */ - GST_LOG_OBJECT (pad, "sending event %p to one sink pad %s:%s", event, - GST_DEBUG_PAD_NAME (eventpad)); - result = gst_pad_push_event (eventpad, event); - goto done; - } - } + /* ERROR recovery here */ +wrong_direction: + { + GST_UNLOCK (pad); + return FALSE; + } +not_connected: + { + GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, + "checking pull range, but it was not linked"); + GST_UNLOCK (pad); + return FALSE; } - /* we handled the incoming event so we unref once */ - GST_LOG_OBJECT (pad, "handled event %p, unreffing", event); - gst_event_unref (event); - -done: - g_list_free (orig); - - return result; } /** - * gst_pad_event_default: - * @pad: a #GstPad to call the default event handler on. - * @event: the #GstEvent to handle. + * gst_pad_pull_range: + * @pad: a sink #GstPad. + * @buffer: a pointer to hold the #GstBuffer. + * @offset: The start offset of the buffer + * @length: The length of the buffer * - * Invokes the default event handler for the given pad. End-of-stream and - * discontinuity events are handled specially, and then the event is sent to all - * pads internally linked to @pad. Note that if there are many possible sink - * pads that are internally linked to @pad, only one will be sent an event. - * Multi-sinkpad elements should implement custom event handlers. + * Pulls a buffer from the peer pad. @pad must be linked. * - * Returns: TRUE if the event was sent succesfully. + * Returns: a #GstFlowReturn from the peer pad. + * + * MT safe. */ -gboolean -gst_pad_event_default (GstPad * pad, GstEvent * event) +GstFlowReturn +gst_pad_pull_range (GstPad * pad, guint64 offset, guint size, + GstBuffer ** buffer) { - g_return_val_if_fail (GST_IS_PAD (pad), FALSE); - g_return_val_if_fail (event != NULL, FALSE); + GstRealPad *peer; + GstFlowReturn ret; + GstPadGetRangeFunction getrangefunc; - switch (GST_EVENT_TYPE (event)) { - case GST_EVENT_EOS: - { - GstRealPad *rpad = GST_PAD_REALIZE (pad); + g_return_val_if_fail (GST_IS_REAL_PAD (pad), GST_FLOW_ERROR); + g_return_val_if_fail (GST_RPAD_DIRECTION (pad) == GST_PAD_SINK, + GST_FLOW_ERROR); + g_return_val_if_fail (buffer != NULL, GST_FLOW_ERROR); - if (GST_RPAD_TASK (rpad)) { - GST_DEBUG_OBJECT (rpad, "pausing task because of eos"); - gst_task_pause (GST_RPAD_TASK (rpad)); - } - } - default: - break; - } + GST_LOCK (pad); + + while (G_UNLIKELY (GST_RPAD_IS_BLOCKED (pad))) + handle_pad_block (GST_REAL_PAD_CAST (pad)); - return gst_pad_event_default_dispatch (pad, event); -} + if (G_UNLIKELY ((peer = GST_RPAD_PEER (pad)) == NULL)) + goto not_connected; -/** - * gst_pad_dispatcher: - * @pad: a #GstPad to dispatch. - * @dispatch: the #GstDispatcherFunction to call. - * @data: gpointer user data passed to the dispatcher function. - * - * Invokes the given dispatcher function on all pads that are - * internally linked to the given pad. - * The GstPadDispatcherFunction should return TRUE when no further pads - * need to be processed. - * - * Returns: TRUE if one of the dispatcher functions returned TRUE. - */ -gboolean -gst_pad_dispatcher (GstPad * pad, GstPadDispatcherFunction dispatch, - gpointer data) -{ - gboolean res = FALSE; - GList *int_pads, *orig; + if (G_UNLIKELY (!GST_RPAD_IS_ACTIVE (peer))) + goto not_active; - g_return_val_if_fail (GST_IS_PAD (pad), FALSE); - g_return_val_if_fail (dispatch != NULL, FALSE); + if (G_UNLIKELY (GST_RPAD_IS_FLUSHING (peer))) + goto flushing; - orig = int_pads = gst_pad_get_internal_links (pad); + gst_object_ref (GST_OBJECT_CAST (peer)); + GST_UNLOCK (pad); - while (int_pads) { - GstRealPad *int_rpad = GST_PAD_REALIZE (int_pads->data); - GstRealPad *int_peer = GST_RPAD_PEER (int_rpad); + /* see note in above function */ + if (G_UNLIKELY ((getrangefunc = peer->getrangefunc) == NULL)) + goto no_function; - if (int_peer) { - res = dispatch (GST_PAD (int_peer), data); - if (res) - break; - } - int_pads = g_list_next (int_pads); - } + GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, + "calling getrangefunc %s of peer pad %s:%s, offset %" + G_GUINT64_FORMAT ", size %u", + GST_DEBUG_FUNCPTR_NAME (getrangefunc), GST_DEBUG_PAD_NAME (peer), + offset, size); - g_list_free (orig); + ret = getrangefunc (GST_PAD_CAST (peer), offset, size, buffer); - return res; + gst_object_unref (GST_OBJECT_CAST (peer)); + + return ret; + + /* ERROR recovery here */ +not_connected: + { + GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, + "pulling range, but it was not linked"); + GST_UNLOCK (pad); + return GST_FLOW_NOT_CONNECTED; + } +not_active: + { + GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, + "pulling range, but it was inactive"); + GST_UNLOCK (pad); + return GST_FLOW_WRONG_STATE; + } +flushing: + { + GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, + "pulling range, but pad was flushing"); + GST_UNLOCK (pad); + return GST_FLOW_UNEXPECTED; + } +no_function: + { + GST_ELEMENT_ERROR (GST_PAD_PARENT (pad), CORE, PAD, (NULL), + ("pullrange on pad %s:%s but the peer pad %s:%s has no getrangefunction", + GST_DEBUG_PAD_NAME (pad), GST_DEBUG_PAD_NAME (peer))); + gst_object_unref (GST_OBJECT (peer)); + return GST_FLOW_ERROR; + } } /** @@ -3646,304 +3181,405 @@ no_function: } } -typedef struct -{ - GstFormat src_format; - gint64 src_value; - GstFormat *dest_format; - gint64 *dest_value; -} -GstPadConvertData; +/************************************************************************ + * + * templates + * + */ +static void gst_pad_template_class_init (GstPadTemplateClass * klass); +static void gst_pad_template_init (GstPadTemplate * templ); +static void gst_pad_template_dispose (GObject * object); + +GType +gst_pad_template_get_type (void) +{ + static GType padtemplate_type = 0; + + if (!padtemplate_type) { + static const GTypeInfo padtemplate_info = { + sizeof (GstPadTemplateClass), NULL, NULL, + (GClassInitFunc) gst_pad_template_class_init, NULL, NULL, + sizeof (GstPadTemplate), + 0, + (GInstanceInitFunc) gst_pad_template_init, NULL + }; + + padtemplate_type = + g_type_register_static (GST_TYPE_OBJECT, "GstPadTemplate", + &padtemplate_info, 0); + } + return padtemplate_type; +} + +static void +gst_pad_template_class_init (GstPadTemplateClass * klass) +{ + GObjectClass *gobject_class; + GstObjectClass *gstobject_class; + + gobject_class = (GObjectClass *) klass; + gstobject_class = (GstObjectClass *) klass; + + padtemplate_parent_class = g_type_class_ref (GST_TYPE_OBJECT); + + gst_pad_template_signals[TEMPL_PAD_CREATED] = + g_signal_new ("pad-created", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GstPadTemplateClass, pad_created), + NULL, NULL, gst_marshal_VOID__OBJECT, G_TYPE_NONE, 1, GST_TYPE_PAD); + + gobject_class->dispose = gst_pad_template_dispose; + + gstobject_class->path_string_separator = "*"; +} + +static void +gst_pad_template_init (GstPadTemplate * templ) +{ +} + +static void +gst_pad_template_dispose (GObject * object) +{ + GstPadTemplate *templ = GST_PAD_TEMPLATE (object); + + g_free (GST_PAD_TEMPLATE_NAME_TEMPLATE (templ)); + if (GST_PAD_TEMPLATE_CAPS (templ)) { + gst_caps_unref (GST_PAD_TEMPLATE_CAPS (templ)); + } + + G_OBJECT_CLASS (padtemplate_parent_class)->dispose (object); +} + +/* ALWAYS padtemplates cannot have conversion specifications, it doesn't make + * sense. + * SOMETIMES padtemplates can do whatever they want, they are provided by the + * element. + * REQUEST padtemplates can be reverse-parsed (the user asks for 'sink1', the + * 'sink%d' template is automatically selected), so we need to restrict their + * naming. + */ +static gboolean +name_is_valid (const gchar * name, GstPadPresence presence) +{ + const gchar *str; + + if (presence == GST_PAD_ALWAYS) { + if (strchr (name, '%')) { + g_warning ("invalid name template %s: conversion specifications are not" + " allowed for GST_PAD_ALWAYS padtemplates", name); + return FALSE; + } + } else if (presence == GST_PAD_REQUEST) { + if ((str = strchr (name, '%')) && strchr (str + 1, '%')) { + g_warning ("invalid name template %s: only one conversion specification" + " allowed in GST_PAD_REQUEST padtemplate", name); + return FALSE; + } + if (str && (*(str + 1) != 's' && *(str + 1) != 'd')) { + g_warning ("invalid name template %s: conversion specification must be of" + " type '%%d' or '%%s' for GST_PAD_REQUEST padtemplate", name); + return FALSE; + } + if (str && (*(str + 2) != '\0')) { + g_warning ("invalid name template %s: conversion specification must" + " appear at the end of the GST_PAD_REQUEST padtemplate name", name); + return FALSE; + } + } + + return TRUE; +} + +/** + * gst_static_pad_template_get: + * @pad_template: the static pad template + * + * Converts a #GstStaticPadTemplate into a #GstPadTemplate. + * + * Returns: a new #GstPadTemplate. + */ +GstPadTemplate * +gst_static_pad_template_get (GstStaticPadTemplate * pad_template) +{ + GstPadTemplate *new; + + if (!name_is_valid (pad_template->name_template, pad_template->presence)) + return NULL; + + new = g_object_new (gst_pad_template_get_type (), + "name", pad_template->name_template, NULL); + + GST_PAD_TEMPLATE_NAME_TEMPLATE (new) = g_strdup (pad_template->name_template); + GST_PAD_TEMPLATE_DIRECTION (new) = pad_template->direction; + GST_PAD_TEMPLATE_PRESENCE (new) = pad_template->presence; + + GST_PAD_TEMPLATE_CAPS (new) = + gst_caps_copy (gst_static_caps_get (&pad_template->static_caps)); + + return new; +} + +/** + * gst_pad_template_new: + * @name_template: the name template. + * @direction: the #GstPadDirection of the template. + * @presence: the #GstPadPresence of the pad. + * @caps: a #GstCaps set for the template. The caps are taken ownership of. + * + * Creates a new pad template with a name according to the given template + * and with the given arguments. This functions takes ownership of the provided + * caps, so be sure to not use them afterwards. + * + * Returns: a new #GstPadTemplate. + */ +GstPadTemplate * +gst_pad_template_new (const gchar * name_template, + GstPadDirection direction, GstPadPresence presence, GstCaps * caps) +{ + GstPadTemplate *new; + + g_return_val_if_fail (name_template != NULL, NULL); + g_return_val_if_fail (caps != NULL, NULL); + g_return_val_if_fail (direction == GST_PAD_SRC + || direction == GST_PAD_SINK, NULL); + g_return_val_if_fail (presence == GST_PAD_ALWAYS + || presence == GST_PAD_SOMETIMES || presence == GST_PAD_REQUEST, NULL); + + if (!name_is_valid (name_template, presence)) + return NULL; + + new = g_object_new (gst_pad_template_get_type (), + "name", name_template, NULL); + + GST_PAD_TEMPLATE_NAME_TEMPLATE (new) = g_strdup (name_template); + GST_PAD_TEMPLATE_DIRECTION (new) = direction; + GST_PAD_TEMPLATE_PRESENCE (new) = presence; + GST_PAD_TEMPLATE_CAPS (new) = caps; -static gboolean -gst_pad_convert_dispatcher (GstPad * pad, GstPadConvertData * data) -{ - return gst_pad_convert (pad, data->src_format, data->src_value, - data->dest_format, data->dest_value); + return new; } /** - * gst_pad_convert_default: - * @pad: a #GstPad to invoke the default converter on. - * @src_format: the source #GstFormat. - * @src_value: the source value. - * @dest_format: a pointer to the destination #GstFormat. - * @dest_value: a pointer to the destination value. + * gst_static_pad_template_get_caps: + * @templ: a #GstStaticPadTemplate to get capabilities of. * - * Invokes the default converter on a pad. - * This will forward the call to the pad obtained - * using the internal link of - * the element. + * Gets the capabilities of the static pad template. * - * Returns: TRUE if the conversion could be performed. + * Returns: the #GstCaps of the static pad template. If you need to keep a + * reference to the caps, take a ref (see gst_caps_ref ()). */ -gboolean -gst_pad_convert_default (GstPad * pad, - GstFormat src_format, gint64 src_value, - GstFormat * dest_format, gint64 * dest_value) +GstCaps * +gst_static_pad_template_get_caps (GstStaticPadTemplate * templ) { - GstPadConvertData data; - - g_return_val_if_fail (GST_IS_PAD (pad), FALSE); - g_return_val_if_fail (dest_format != NULL, FALSE); - g_return_val_if_fail (dest_value != NULL, FALSE); - - data.src_format = src_format; - data.src_value = src_value; - data.dest_format = dest_format; - data.dest_value = dest_value; + g_return_val_if_fail (templ, NULL); - return gst_pad_dispatcher (pad, (GstPadDispatcherFunction) - gst_pad_convert_dispatcher, &data); + return (GstCaps *) gst_static_caps_get (&templ->static_caps); } /** - * gst_pad_convert: - * @pad: a #GstPad to invoke the default converter on. - * @src_format: the source #GstFormat. - * @src_value: the source value. - * @dest_format: a pointer to the destination #GstFormat. - * @dest_value: a pointer to the destination value. + * gst_pad_template_get_caps: + * @templ: a #GstPadTemplate to get capabilities of. * - * Invokes a conversion on the pad. + * Gets the capabilities of the pad template. * - * Returns: TRUE if the conversion could be performed. + * Returns: the #GstCaps of the pad template. If you need to keep a reference to + * the caps, take a ref (see gst_caps_ref ()). */ -gboolean -gst_pad_convert (GstPad * pad, - GstFormat src_format, gint64 src_value, - GstFormat * dest_format, gint64 * dest_value) -{ - GstRealPad *rpad; - - g_return_val_if_fail (GST_IS_PAD (pad), FALSE); - g_return_val_if_fail (dest_format != NULL, FALSE); - g_return_val_if_fail (dest_value != NULL, FALSE); - - if (src_format == *dest_format) { - *dest_value = src_value; - return TRUE; - } - - rpad = GST_PAD_REALIZE (pad); - - if (GST_RPAD_CONVERTFUNC (rpad)) { - return GST_RPAD_CONVERTFUNC (rpad) (GST_PAD (rpad), src_format, - src_value, dest_format, dest_value); - } - - return FALSE; -} - -typedef struct +GstCaps * +gst_pad_template_get_caps (GstPadTemplate * templ) { - GstQueryType type; - GstFormat *format; - gint64 *value; -} -GstPadQueryData; + g_return_val_if_fail (GST_IS_PAD_TEMPLATE (templ), NULL); -static gboolean -gst_pad_query_dispatcher (GstPad * pad, GstPadQueryData * data) -{ - return gst_pad_query (pad, data->type, data->format, data->value); + return GST_PAD_TEMPLATE_CAPS (templ); } /** - * gst_pad_query_default: - * @pad: a #GstPad to invoke the default query on. - * @type: the #GstQueryType of the query to perform. - * @format: a pointer to the #GstFormat of the result. - * @value: a pointer to the result. - * - * Invokes the default query function on a pad. + * gst_pad_set_element_private: + * @pad: the #GstPad to set the private data of. + * @priv: The private data to attach to the pad. * - * Returns: TRUE if the query could be performed. + * Set the given private data gpointer on the pad. + * This function can only be used by the element that owns the pad. */ -gboolean -gst_pad_query_default (GstPad * pad, GstQueryType type, - GstFormat * format, gint64 * value) +void +gst_pad_set_element_private (GstPad * pad, gpointer priv) { - GstPadQueryData data; - - g_return_val_if_fail (GST_IS_PAD (pad), FALSE); - g_return_val_if_fail (format != NULL, FALSE); - g_return_val_if_fail (value != NULL, FALSE); - - data.type = type; - data.format = format; - data.value = value; - - return gst_pad_dispatcher (pad, (GstPadDispatcherFunction) - gst_pad_query_dispatcher, &data); + pad->element_private = priv; } /** - * gst_pad_query: - * @pad: a #GstPad to invoke the default query on. - * @type: the #GstQueryType of the query to perform. - * @format: a pointer to the #GstFormat asked for. - * On return contains the #GstFormat used. - * @value: a pointer to the result. + * gst_pad_get_element_private: + * @pad: the #GstPad to get the private data of. * - * Queries a pad for one of the available properties. The format will be - * adjusted to the actual format used when specifying formats such as - * GST_FORMAT_DEFAULT. - * FIXME: Tell if the format can be adjusted when specifying a definite format. + * Gets the private data of a pad. * - * Returns: TRUE if the query could be performed. + * Returns: a #gpointer to the private data. */ -gboolean -gst_pad_query (GstPad * pad, GstQueryType type, - GstFormat * format, gint64 * value) +gpointer +gst_pad_get_element_private (GstPad * pad) { - GstRealPad *rpad; - - g_return_val_if_fail (GST_IS_PAD (pad), FALSE); - g_return_val_if_fail (format != NULL, FALSE); - g_return_val_if_fail (value != NULL, FALSE); - - rpad = GST_PAD_REALIZE (pad); - - g_return_val_if_fail (rpad, FALSE); + return pad->element_private; +} - if (GST_RPAD_QUERYFUNC (rpad)) - return GST_RPAD_QUERYFUNC (rpad) (GST_PAD_CAST (rpad), type, format, value); +gboolean +gst_pad_start_task (GstPad * pad) +{ + g_warning ("implement gst_pad_start_task()"); + return FALSE; +} +gboolean +gst_pad_pause_task (GstPad * pad) +{ + g_warning ("implement gst_pad_pause_task()"); return FALSE; } -/** - * gst_pad_query2: - * @pad: a #GstPad to invoke the default query on. - * @query: the #GstQuery to perform. - * - * Dispatches a query to a pad. The query should have been allocated by the - * caller via one of the type-specific allocation functions in gstquery.h. The - * element is responsible for filling the query with an appropriate response, - * which should then be parsed with a type-specific query parsing function. - * - * Again, the caller is responsible for both the allocation and deallocation of - * the query structure. - * - * Returns: TRUE if the query could be performed. - */ gboolean -gst_pad_query2 (GstPad * pad, GstQuery * query) +gst_pad_stop_task (GstPad * pad) { - GstRealPad *rpad; + g_warning ("implement gst_pad_stop_task()"); + return FALSE; +} - g_return_val_if_fail (GST_IS_PAD (pad), FALSE); - g_return_val_if_fail (GST_IS_QUERY (query), FALSE); - rpad = GST_PAD_REALIZE (pad); +/***** ghost pads *****/ +GType _gst_ghost_pad_type = 0; - g_return_val_if_fail (rpad, FALSE); +static void gst_ghost_pad_class_init (GstGhostPadClass * klass); +static void gst_ghost_pad_init (GstGhostPad * pad); +static void gst_ghost_pad_dispose (GObject * object); +static void gst_ghost_pad_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec); +static void gst_ghost_pad_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec); - if (GST_RPAD_QUERY2FUNC (rpad)) - return GST_RPAD_QUERY2FUNC (rpad) (GST_PAD_CAST (rpad), query); +static GstPad *ghost_pad_parent_class = NULL; - return FALSE; -} +/* static guint gst_ghost_pad_signals[LAST_SIGNAL] = { 0 }; */ +enum +{ + GPAD_ARG_0, + GPAD_ARG_REAL_PAD + /* fill me */ +}; -gboolean -gst_pad_query2_default (GstPad * pad, GstQuery * query) +GType +gst_ghost_pad_get_type (void) { - switch (GST_QUERY_TYPE (query)) { - case GST_QUERY_POSITION: - case GST_QUERY_SEEKING: - case GST_QUERY_FORMATS: - case GST_QUERY_LATENCY: - case GST_QUERY_JITTER: - case GST_QUERY_RATE: - case GST_QUERY_CONVERT: - default: - return gst_pad_dispatcher - (pad, (GstPadDispatcherFunction) gst_pad_query2, query); + if (!_gst_ghost_pad_type) { + static const GTypeInfo pad_info = { + sizeof (GstGhostPadClass), NULL, NULL, + (GClassInitFunc) gst_ghost_pad_class_init, NULL, NULL, + sizeof (GstGhostPad), + 0, + (GInstanceInitFunc) gst_ghost_pad_init, + NULL + }; + + _gst_ghost_pad_type = g_type_register_static (GST_TYPE_PAD, "GstGhostPad", + &pad_info, 0); } + return _gst_ghost_pad_type; } -/** - * gst_pad_query_position: - * @pad: a #GstPad to invoke the default query on. - * @format: a pointer to the #GstFormat asked for. - * On return contains the #GstFormat used. - * @cur: A location in which to store the current position, or NULL. - * @end: A location in which to store the end position (length), or NULL. - * - * Queries a pad for the stream position and length. - * - * Returns: TRUE if the query could be performed. - */ -gboolean -gst_pad_query_position (GstPad * pad, GstFormat * format, gint64 * cur, - gint64 * end) +static void +gst_ghost_pad_class_init (GstGhostPadClass * klass) { - GstQuery *query; - gboolean ret; + GObjectClass *gobject_class; - g_return_val_if_fail (GST_IS_PAD (pad), FALSE); - g_return_val_if_fail (format != NULL, FALSE); + gobject_class = (GObjectClass *) klass; - query = gst_query_new_position (*format); - ret = gst_pad_query2 (pad, query); + ghost_pad_parent_class = g_type_class_ref (GST_TYPE_PAD); - if (ret) - gst_query_parse_position_response (query, format, cur, end); + gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_ghost_pad_dispose); + gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_ghost_pad_set_property); + gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_ghost_pad_get_property); - gst_query_unref (query); + g_object_class_install_property (gobject_class, GPAD_ARG_REAL_PAD, + g_param_spec_object ("real-pad", "Real pad", + "The real pad for the ghost pad", GST_TYPE_PAD, G_PARAM_READWRITE)); +} - return ret; +static void +gst_ghost_pad_init (GstGhostPad * pad) +{ + /* zeroed by glib */ } -static gboolean -gst_pad_get_formats_dispatcher (GstPad * pad, const GstFormat ** data) +static void +gst_ghost_pad_dispose (GObject * object) { - *data = gst_pad_get_formats (pad); + g_object_set (object, "real-pad", NULL, NULL); - return TRUE; + G_OBJECT_CLASS (ghost_pad_parent_class)->dispose (object); } -/** - * 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) +static void +gst_ghost_pad_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) { - GstFormat *result = NULL; + GstPad *ghostpad = (GstPad *) object; + GstPad *oldrealpad = (GstPad *) GST_GPAD_REALPAD (ghostpad); + GstPad *realpad = NULL; - g_return_val_if_fail (GST_IS_PAD (pad), NULL); + switch (prop_id) { + case GPAD_ARG_REAL_PAD: + realpad = g_value_get_object (value); - gst_pad_dispatcher (pad, (GstPadDispatcherFunction) - gst_pad_get_formats_dispatcher, &result); + if (oldrealpad) { + if (realpad == oldrealpad) + return; + else + gst_pad_remove_ghost_pad (oldrealpad, ghostpad); + } - return result; + if (realpad) + gst_pad_add_ghost_pad (realpad, ghostpad); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_ghost_pad_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec) +{ + switch (prop_id) { + case GPAD_ARG_REAL_PAD: + g_value_set_object (value, GST_GPAD_REALPAD (object)); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } } /** - * gst_pad_get_formats: - * @pad: a #GstPad to query + * gst_ghost_pad_new: + * @name: the name of the new ghost pad. + * @pad: the #GstPad to create a ghost pad for. * - * Gets the list of supported formats from the pad. + * Creates a new ghost pad associated with @pad, and named @name. If @name is + * %NULL, a guaranteed unique name (across all ghost pads) will be assigned. * - * Returns: An array of GstFormats ended with a 0 value. + * Returns: a new ghost #GstPad, or %NULL in case of an error. */ -const GstFormat * -gst_pad_get_formats (GstPad * pad) +GstPad * +gst_ghost_pad_new (const gchar * name, GstPad * pad) { - GstRealPad *rpad; + GstPad *gpad; g_return_val_if_fail (GST_IS_PAD (pad), NULL); - rpad = GST_PAD_REALIZE (pad); + gpad = g_object_new (GST_TYPE_GHOST_PAD, "name", name, "real-pad", pad, NULL); - if (GST_RPAD_FORMATSFUNC (rpad)) - return GST_RPAD_FORMATSFUNC (rpad) (GST_PAD (pad)); + GST_CAT_DEBUG (GST_CAT_PADS, "created ghost pad \"%s\" for pad %s:%s", + GST_OBJECT_NAME (gpad), GST_DEBUG_PAD_NAME (pad)); - return NULL; + return gpad; } diff --git a/gst/gstpad.h b/gst/gstpad.h index b560b80..d8fcd9f 100644 --- a/gst/gstpad.h +++ b/gst/gstpad.h @@ -135,26 +135,21 @@ typedef enum { typedef gboolean (*GstPadActivateFunction) (GstPad *pad, GstActivateMode mode); /* data passing */ -typedef void (*GstPadLoopFunction) (GstPad *pad); typedef GstFlowReturn (*GstPadChainFunction) (GstPad *pad, GstBuffer *buffer); typedef GstFlowReturn (*GstPadGetRangeFunction) (GstPad *pad, guint64 offset, guint length, GstBuffer **buffer); -typedef gboolean (*GstPadCheckGetRangeFunction) (GstPad *pad); typedef gboolean (*GstPadEventFunction) (GstPad *pad, GstEvent *event); -/* old, deprecated convert/query/format functions */ -typedef gboolean (*GstPadConvertFunction) (GstPad *pad, - GstFormat src_format, gint64 src_value, - GstFormat *dest_format, gint64 *dest_value); -typedef gboolean (*GstPadQueryFunction) (GstPad *pad, GstQueryType type, - GstFormat *format, gint64 *value); +/* deprecate me, check range should use seeking query, loop function is internal */ +typedef gboolean (*GstPadCheckGetRangeFunction) (GstPad *pad); +typedef void (*GstPadLoopFunction) (GstPad *pad); + +/* internal links */ typedef GList* (*GstPadIntLinkFunction) (GstPad *pad); -typedef const GstFormat* (*GstPadFormatsFunction) (GstPad *pad); -typedef const GstEventMask* (*GstPadEventMaskFunction) (GstPad *pad); -typedef const GstQueryType* (*GstPadQueryTypeFunction) (GstPad *pad); /* generic query function */ -typedef gboolean (*GstPadQuery2Function) (GstPad *pad, GstQuery *query); +typedef const GstQueryType* (*GstPadQueryTypeFunction) (GstPad *pad); +typedef gboolean (*GstPadQueryFunction) (GstPad *pad, GstQuery *query); /* linking */ typedef GstPadLinkReturn (*GstPadLinkFunction) (GstPad *pad, GstPad *peer); @@ -247,29 +242,23 @@ struct _GstRealPad { GstPadGetRangeFunction getrangefunc; GstPadEventFunction eventfunc; - GstPadEventMaskFunction eventmaskfunc; - /* ghostpads */ GList *ghostpads; guint32 ghostpads_cookie; - /* old, deprecated query/convert/formats functions */ - GstPadConvertFunction convertfunc; - GstPadQueryFunction queryfunc; - GstPadFormatsFunction formatsfunc; + /* generic query method */ GstPadQueryTypeFunction querytypefunc; + GstPadQueryFunction queryfunc; + + /* internal links */ GstPadIntLinkFunction intlinkfunc; GstPadBufferAllocFunction bufferallocfunc; GstProbeDispatcher probedisp; - /* generic query method */ - GstPadQuery2Function query2func; - /*< private >*/ - /* fixme: bring back to gst_padding when old query functions go away */ - gpointer _gst_reserved[GST_PADDING - 1]; + gpointer _gst_reserved[GST_PADDING]; }; struct _GstRealPadClass { @@ -315,13 +304,9 @@ struct _GstGhostPadClass { #define GST_RPAD_CHECKGETRANGEFUNC(pad) (GST_REAL_PAD_CAST(pad)->checkgetrangefunc) #define GST_RPAD_GETRANGEFUNC(pad) (GST_REAL_PAD_CAST(pad)->getrangefunc) #define GST_RPAD_EVENTFUNC(pad) (GST_REAL_PAD_CAST(pad)->eventfunc) -#define GST_RPAD_CONVERTFUNC(pad) (GST_REAL_PAD_CAST(pad)->convertfunc) +#define GST_RPAD_QUERYTYPEFUNC(pad) (GST_REAL_PAD_CAST(pad)->querytypefunc) #define GST_RPAD_QUERYFUNC(pad) (GST_REAL_PAD_CAST(pad)->queryfunc) #define GST_RPAD_INTLINKFUNC(pad) (GST_REAL_PAD_CAST(pad)->intlinkfunc) -#define GST_RPAD_FORMATSFUNC(pad) (GST_REAL_PAD_CAST(pad)->formatsfunc) -#define GST_RPAD_QUERYTYPEFUNC(pad) (GST_REAL_PAD_CAST(pad)->querytypefunc) -#define GST_RPAD_EVENTMASKFUNC(pad) (GST_REAL_PAD_CAST(pad)->eventmaskfunc) -#define GST_RPAD_QUERY2FUNC(pad) (GST_REAL_PAD_CAST(pad)->query2func) #define GST_RPAD_PEER(pad) (GST_REAL_PAD_CAST(pad)->peer) #define GST_RPAD_LINKFUNC(pad) (GST_REAL_PAD_CAST(pad)->linkfunc) @@ -379,11 +364,10 @@ struct _GstGhostPadClass { #define GST_PAD_IS_LINKED(pad) (GST_RPAD_IS_LINKED(GST_PAD_REALIZE(pad))) #define GST_PAD_IS_ACTIVE(pad) (GST_RPAD_IS_ACTIVE(GST_PAD_REALIZE(pad))) #define GST_PAD_IS_BLOCKED(pad) (GST_RPAD_IS_BLOCKED(GST_PAD_REALIZE(pad))) -#define GST_PAD_IS_NEGOTIATING(pad) (GST_RPAD_IS_NEGOTIATING(GST_PAD_REALIZE(pad))) +#define GST_PAD_IS_FLUSHING(pad) (GST_RPAD_IS_FLUSHING(GST_PAD_REALIZE(pad))) #define GST_PAD_IS_IN_GETCAPS(pad) (GST_RPAD_IS_IN_GETCAPS(GST_PAD_REALIZE(pad))) #define GST_PAD_IS_IN_SETCAPS(pad) (GST_RPAD_IS_IN_SETCAPS(GST_PAD_REALIZE(pad))) #define GST_PAD_IS_USABLE(pad) (GST_RPAD_IS_USABLE(GST_PAD_REALIZE(pad))) -#define GST_PAD_CAN_PULL(pad) (GST_RPAD_CAN_PULL(GST_PAD_REALIZE(pad))) #define GST_PAD_IS_SRC(pad) (GST_RPAD_IS_SRC(GST_PAD_REALIZE(pad))) #define GST_PAD_IS_SINK(pad) (GST_RPAD_IS_SINK(GST_PAD_REALIZE(pad))) @@ -492,11 +476,6 @@ void gst_pad_set_chain_function (GstPad *pad, GstPadChainFunction chain); void gst_pad_set_getrange_function (GstPad *pad, GstPadGetRangeFunction get); void gst_pad_set_checkgetrange_function (GstPad *pad, GstPadCheckGetRangeFunction check); void gst_pad_set_event_function (GstPad *pad, GstPadEventFunction event); -void gst_pad_set_event_mask_function (GstPad *pad, GstPadEventMaskFunction mask_func); -G_CONST_RETURN GstEventMask* - gst_pad_get_event_masks (GstPad *pad); -G_CONST_RETURN GstEventMask* - gst_pad_get_event_masks_default (GstPad *pad); /* pad links */ void gst_pad_set_link_function (GstPad *pad, GstPadLinkFunction link); @@ -544,44 +523,21 @@ gboolean gst_pad_start_task (GstPad *pad); gboolean gst_pad_pause_task (GstPad *pad); gboolean gst_pad_stop_task (GstPad *pad); -/* convert/query/format functions */ -void gst_pad_set_formats_function (GstPad *pad, - GstPadFormatsFunction formats); -G_CONST_RETURN GstFormat* - gst_pad_get_formats (GstPad *pad); -G_CONST_RETURN GstFormat* - gst_pad_get_formats_default (GstPad *pad); - -void gst_pad_set_convert_function (GstPad *pad, GstPadConvertFunction convert); -gboolean gst_pad_convert (GstPad *pad, - GstFormat src_format, gint64 src_value, - GstFormat *dest_format, gint64 *dest_value); -gboolean gst_pad_convert_default (GstPad *pad, - GstFormat src_format, gint64 src_value, - GstFormat *dest_format, gint64 *dest_value); +/* internal links */ +void gst_pad_set_internal_link_function (GstPad *pad, GstPadIntLinkFunction intlink); +GList* gst_pad_get_internal_links (GstPad *pad); +GList* gst_pad_get_internal_links_default (GstPad *pad); -void gst_pad_set_query_function (GstPad *pad, GstPadQueryFunction query); +/* generic query function */ void gst_pad_set_query_type_function (GstPad *pad, GstPadQueryTypeFunction type_func); G_CONST_RETURN GstQueryType* gst_pad_get_query_types (GstPad *pad); G_CONST_RETURN GstQueryType* gst_pad_get_query_types_default (GstPad *pad); -gboolean gst_pad_query (GstPad *pad, GstQueryType type, - GstFormat *format, gint64 *value); -gboolean gst_pad_query_default (GstPad *pad, GstQueryType type, - GstFormat *format, gint64 *value); -void gst_pad_set_internal_link_function (GstPad *pad, GstPadIntLinkFunction intlink); -GList* gst_pad_get_internal_links (GstPad *pad); -GList* gst_pad_get_internal_links_default (GstPad *pad); - -gboolean gst_pad_query2 (GstPad *pad, GstQuery *query); -void gst_pad_set_query2_function (GstPad *pad, GstPadQuery2Function query); -gboolean gst_pad_query2_default (GstPad *pad, GstQuery *query); - -/* util query functions */ -gboolean gst_pad_query_position (GstPad *pad, GstFormat *format, - gint64 *cur, gint64 *end); +gboolean gst_pad_query (GstPad *pad, GstQuery *query); +void gst_pad_set_query_function (GstPad *pad, GstPadQueryFunction query); +gboolean gst_pad_query_default (GstPad *pad, GstQuery *query); /* misc helper functions */ gboolean gst_pad_dispatcher (GstPad *pad, GstPadDispatcherFunction dispatch, diff --git a/gst/gstquery.c b/gst/gstquery.c index 5f02fe4..9b57fb3 100644 --- a/gst/gstquery.c +++ b/gst/gstquery.c @@ -26,12 +26,14 @@ #include "gst_private.h" #include "gstquery.h" #include "gstmemchunk.h" +#include "gstenumtypes.h" #include "gstdata_private.h" +GST_DEBUG_CATEGORY_STATIC (gst_query_debug); +#define GST_CAT_DEFAULT gst_query_debug GType _gst_query_type; - static GStaticMutex mutex = G_STATIC_MUTEX_INIT; static GList *_gst_queries = NULL; static GHashTable *_nick_to_query = NULL; @@ -61,6 +63,8 @@ _gst_query_initialize (void) GST_CAT_INFO (GST_CAT_GST_INIT, "init queries"); + GST_DEBUG_CATEGORY_INIT (gst_query_debug, "query", 0, "query system"); + g_static_mutex_lock (&mutex); if (_nick_to_query == NULL) { _nick_to_query = g_hash_table_new (g_str_hash, g_str_equal); @@ -279,12 +283,116 @@ gst_query_new (GstQueryType type, GstStructure * structure) query->structure = structure; gst_structure_set_parent_refcount (query->structure, &GST_DATA_REFCOUNT (query)); + } else { + query->structure = NULL; } return query; } GstQuery * +gst_query_new_position (GstFormat format) +{ + GstQuery *query; + GstStructure *structure; + + structure = gst_structure_new ("GstQueryPosition", + "format", GST_TYPE_FORMAT, format, + "cur", G_TYPE_INT64, (gint64) - 1, + "end", G_TYPE_INT64, (gint64) - 1, NULL); + query = gst_query_new (GST_QUERY_POSITION, structure); + + return query; +} + +void +gst_query_set_position (GstQuery * query, GstFormat format, + gint64 cur, gint64 end) +{ + GstStructure *structure; + + g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_POSITION); + + structure = gst_query_get_structure (query); + gst_structure_set (structure, + "format", GST_TYPE_FORMAT, format, + "cur", G_TYPE_INT64, cur, "end", G_TYPE_INT64, end, NULL); +} + +void +gst_query_parse_position (GstQuery * query, GstFormat * format, + gint64 * cur, gint64 * end) +{ + GstStructure *structure; + + g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_POSITION); + + structure = gst_query_get_structure (query); + if (format) + *format = g_value_get_enum (gst_structure_get_value (structure, "format")); + if (cur) + *cur = g_value_get_int64 (gst_structure_get_value (structure, "cur")); + if (end) + *end = g_value_get_int64 (gst_structure_get_value (structure, "end")); +} + +GstQuery * +gst_query_new_convert (GstFormat src_fmt, gint64 value, GstFormat dest_fmt) +{ + GstQuery *query; + GstStructure *structure; + + structure = gst_structure_new ("GstQueryConvert", + "src_format", GST_TYPE_FORMAT, src_fmt, + "src_value", G_TYPE_INT64, value, + "dest_format", GST_TYPE_FORMAT, dest_fmt, + "dest_value", G_TYPE_INT64, (gint64) - 1, NULL); + query = gst_query_new (GST_QUERY_CONVERT, structure); + + return query; +} + +void +gst_query_set_convert (GstQuery * query, GstFormat src_format, gint64 src_value, + GstFormat dest_format, gint64 dest_value) +{ + GstStructure *structure; + + g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_CONVERT); + + structure = gst_query_get_structure (query); + gst_structure_set (structure, + "src_format", GST_TYPE_FORMAT, src_format, + "src_value", G_TYPE_INT64, src_value, + "dest_format", GST_TYPE_FORMAT, dest_format, + "dest_value", G_TYPE_INT64, dest_value, NULL); +} + +void +gst_query_parse_convert (GstQuery * query, GstFormat * src_format, + gint64 * src_value, GstFormat * dest_format, gint64 * dest_value) +{ + GstStructure *structure; + + g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_CONVERT); + + structure = gst_query_get_structure (query); + if (src_format) + *src_format = + g_value_get_enum (gst_structure_get_value (structure, "src_format")); + if (src_value) + *src_value = + g_value_get_int64 (gst_structure_get_value (structure, "src_value")); + if (dest_format) + *dest_format = + g_value_get_enum (gst_structure_get_value (structure, "dest_format")); + if (dest_value) + *dest_value = + g_value_get_int64 (gst_structure_get_value (structure, "dest_value")); +} + + +GstQuery * gst_query_new_application (GstQueryType type, GstStructure * structure) { g_return_val_if_fail (gst_query_type_get_details (type) != NULL, NULL); diff --git a/gst/gstquery.h b/gst/gstquery.h index 70d49e8..3501c47 100644 --- a/gst/gstquery.h +++ b/gst/gstquery.h @@ -30,6 +30,7 @@ #include #include #include +#include G_BEGIN_DECLS @@ -129,9 +130,24 @@ GstIterator* gst_query_type_iterate_definitions (void); #define gst_query_copy(msg) GST_QUERY (gst_data_copy (GST_DATA (msg))) #define gst_query_copy_on_write(msg) GST_QUERY (gst_data_copy_on_write (GST_DATA (msg))) +/* position query */ +GstQuery* gst_query_new_position (GstFormat format); +void gst_query_set_position (GstQuery *query, GstFormat format, + gint64 cur, gint64 end); +void gst_query_parse_position (GstQuery *query, GstFormat *format, + gint64 *cur, gint64 *end); +/* convert query */ +GstQuery* gst_query_new_convert (GstFormat src_fmt, gint64 value, GstFormat dest_fmt); +void gst_query_set_convert (GstQuery *query, GstFormat src_format, gint64 src_value, + GstFormat dest_format, gint64 dest_value); +void gst_query_parse_convert (GstQuery *query, GstFormat *src_format, gint64 *src_value, + GstFormat *dest_format, gint64 *dest_value); + +/* application specific query */ GstQuery * gst_query_new_application (GstQueryType type, GstStructure *structure); + GstStructure * gst_query_get_structure (GstQuery *query); /* hmm */ diff --git a/gst/gstqueryutils.c b/gst/gstqueryutils.c index 25a39f5..b2ad663 100644 --- a/gst/gstqueryutils.c +++ b/gst/gstqueryutils.c @@ -29,59 +29,6 @@ /* some macros are just waiting to be defined here */ - -GstQuery * -gst_query_new_position (GstFormat format) -{ - GstStructure *structure = gst_structure_new ("query", - "format", GST_TYPE_FORMAT, format, NULL); - - return gst_query_new_application (GST_QUERY_POSITION, structure); -} - -void -gst_query_set_position (GstQuery * query, GstFormat format, gint64 cur, - gint64 end) -{ - GstStructure *structure; - - g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_POSITION); - - structure = gst_query_get_structure (query); - gst_structure_set (structure, - "format", GST_TYPE_FORMAT, format, - "cur", G_TYPE_INT64, cur, "end", G_TYPE_INT64, end, NULL); -} - -void -gst_query_parse_position_query (GstQuery * query, GstFormat * format) -{ - GstStructure *structure; - - g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_POSITION); - - structure = gst_query_get_structure (query); - if (format) - *format = g_value_get_enum (gst_structure_get_value (structure, "format")); -} - -void -gst_query_parse_position_response (GstQuery * query, GstFormat * format, - gint64 * cur, gint64 * end) -{ - GstStructure *structure; - - g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_POSITION); - - structure = gst_query_get_structure (query); - if (format) - *format = g_value_get_enum (gst_structure_get_value (structure, "format")); - if (cur) - *cur = g_value_get_int64 (gst_structure_get_value (structure, "cur")); - if (end) - *end = g_value_get_int64 (gst_structure_get_value (structure, "end")); -} - void gst_query_parse_seeking_query (GstQuery * query, GstFormat * format) { diff --git a/gst/gstqueryutils.h b/gst/gstqueryutils.h index d59a804..d72c165 100644 --- a/gst/gstqueryutils.h +++ b/gst/gstqueryutils.h @@ -26,12 +26,6 @@ #include -GstQuery* gst_query_new_position (GstFormat format); -void gst_query_set_position (GstQuery *query, GstFormat format, - gint64 cur, gint64 end); -void gst_query_parse_position_query (GstQuery *query, GstFormat *format); -void gst_query_parse_position_response (GstQuery *query, GstFormat *format, - gint64 *cur, gint64 *end); void gst_query_parse_seeking_query (GstQuery *query, GstFormat *format); void gst_query_set_seeking (GstQuery *query, GstFormat format, gboolean seekable, gint64 segment_start, diff --git a/gst/gstqueue.c b/gst/gstqueue.c index 0596538..aa2b905 100644 --- a/gst/gstqueue.c +++ b/gst/gstqueue.c @@ -133,8 +133,7 @@ static void gst_queue_loop (GstPad * pad); static gboolean gst_queue_handle_sink_event (GstPad * pad, GstEvent * event); static gboolean gst_queue_handle_src_event (GstPad * pad, GstEvent * event); -static gboolean gst_queue_handle_src_query (GstPad * pad, - GstQueryType type, GstFormat * fmt, gint64 * value); +static gboolean gst_queue_handle_src_query (GstPad * pad, GstQuery * query); static GstCaps *gst_queue_getcaps (GstPad * pad); static GstPadLinkReturn gst_queue_link_sink (GstPad * pad, GstPad * peer); @@ -811,29 +810,42 @@ gst_queue_handle_src_event (GstPad * pad, GstEvent * event) } static gboolean -gst_queue_handle_src_query (GstPad * pad, - GstQueryType type, GstFormat * fmt, gint64 * value) +gst_queue_handle_src_query (GstPad * pad, GstQuery * query) { GstQueue *queue = GST_QUEUE (GST_PAD_PARENT (pad)); if (!GST_PAD_PEER (queue->sinkpad)) return FALSE; - if (!gst_pad_query (GST_PAD_PEER (queue->sinkpad), type, fmt, value)) + if (!gst_pad_query (GST_PAD_PEER (queue->sinkpad), query)) return FALSE; - if (type == GST_QUERY_POSITION) { - /* FIXME: this code assumes that there's no discont in the queue */ - switch (*fmt) { - case GST_FORMAT_BYTES: - *value -= queue->cur_level.bytes; - break; - case GST_FORMAT_TIME: - *value -= queue->cur_level.time; - break; - default: - /* FIXME */ - break; + switch (GST_QUERY_TYPE (query)) { + case GST_QUERY_POSITION: + { + gint64 peer_pos, peer_total; + GstFormat format; + + /* get peer position */ + gst_query_parse_position (query, &format, &peer_pos, &peer_total); + + /* FIXME: this code assumes that there's no discont in the queue */ + switch (format) { + case GST_FORMAT_BYTES: + peer_pos -= queue->cur_level.bytes; + break; + case GST_FORMAT_TIME: + peer_pos -= queue->cur_level.time; + break; + default: + /* FIXME */ + break; + } + /* set updated positions */ + gst_query_set_position (query, format, peer_pos, peer_total); + break; } + default: + break; } return TRUE; diff --git a/gst/gstutils.c b/gst/gstutils.c index 0345bf4..e02ac8e 100644 --- a/gst/gstutils.c +++ b/gst/gstutils.c @@ -1155,6 +1155,55 @@ gst_element_unlink (GstElement * src, GstElement * dest) } } +gboolean +gst_element_query_position (GstElement * element, GstFormat * format, + gint64 * cur, gint64 * end) +{ + GstQuery *query; + gboolean ret; + + g_return_val_if_fail (GST_IS_PAD (element), FALSE); + g_return_val_if_fail (format != NULL, FALSE); + + query = gst_query_new_position (*format); + ret = gst_element_query (element, query); + + if (ret) + gst_query_parse_position (query, format, cur, end); + + gst_query_unref (query); + + return ret; +} + +gboolean +gst_element_query_convert (GstElement * element, GstFormat src_format, + gint64 src_val, GstFormat * dest_fmt, gint64 * dest_val) +{ + GstQuery *query; + gboolean ret; + + g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE); + g_return_val_if_fail (dest_fmt != NULL, FALSE); + g_return_val_if_fail (dest_val != NULL, FALSE); + + if (*dest_fmt == src_format) { + *dest_val = src_val; + return TRUE; + } + + query = gst_query_new_convert (src_format, src_val, *dest_fmt); + ret = gst_element_query (element, query); + + if (ret) + gst_query_parse_convert (query, NULL, NULL, dest_fmt, dest_val); + + gst_query_unref (query); + + return ret; +} + + /** * gst_pad_can_link: * @srcpad: the source #GstPad to link. @@ -1675,6 +1724,77 @@ gst_pad_proxy_setcaps (GstPad * pad, GstCaps * caps) return g_value_get_boolean (&ret); } +/** + * gst_pad_query_position: + * @pad: a #GstPad to invoke the position query on. + * @format: a pointer to the #GstFormat asked for. + * On return contains the #GstFormat used. + * @cur: A location in which to store the current position, or NULL. + * @end: A location in which to store the end position (length), or NULL. + * + * Queries a pad for the stream position and length. + * + * Returns: TRUE if the query could be performed. + */ +gboolean +gst_pad_query_position (GstPad * pad, GstFormat * format, gint64 * cur, + gint64 * end) +{ + GstQuery *query; + gboolean ret; + + g_return_val_if_fail (GST_IS_PAD (pad), FALSE); + g_return_val_if_fail (format != NULL, FALSE); + + query = gst_query_new_position (*format); + ret = gst_pad_query (pad, query); + + if (ret) + gst_query_parse_position (query, format, cur, end); + + gst_query_unref (query); + + return ret; +} + +/** + * gst_pad_query_convert: + * @pad: a #GstPad to invoke the convert query on. + * @src_format: a #GstFormat to convert from. + * @src_val: a value to convert. + * @dest_format: a pointer to the #GstFormat to convert to. + * @dest_val: a pointer to the result. + * + * Queries a pad to convert @src_val in @src_format to @dest_format. + * + * Returns: TRUE if the query could be performed. + */ +gboolean +gst_pad_query_convert (GstPad * pad, GstFormat src_format, gint64 src_val, + GstFormat * dest_fmt, gint64 * dest_val) +{ + GstQuery *query; + gboolean ret; + + g_return_val_if_fail (GST_IS_PAD (pad), FALSE); + g_return_val_if_fail (dest_fmt != NULL, FALSE); + g_return_val_if_fail (dest_val != NULL, FALSE); + + if (*dest_fmt == src_format) { + *dest_val = src_val; + return TRUE; + } + + query = gst_query_new_convert (src_format, src_val, *dest_fmt); + ret = gst_pad_query (pad, query); + + if (ret) + gst_query_parse_convert (query, NULL, NULL, dest_fmt, dest_val); + + gst_query_unref (query); + + return ret; +} /** * gst_atomic_int_set: diff --git a/gst/gstutils.h b/gst/gstutils.h index d5b17ca..a278517 100644 --- a/gst/gstutils.h +++ b/gst/gstutils.h @@ -251,10 +251,15 @@ gboolean gst_element_link_pads (GstElement *src, const gchar *srcpadn GstElement *dest, const gchar *destpadname); void gst_element_unlink_pads (GstElement *src, const gchar *srcpadname, GstElement *dest, const gchar *destpadname); +/* util query functions */ +gboolean gst_element_query_position (GstElement *element, GstFormat *format, + gint64 *cur, gint64 *end); +gboolean gst_element_query_convert (GstElement *element, GstFormat src_format, gint64 src_val, + GstFormat *dest_fmt, gint64 *dest_val); /* element class functions */ -void gst_element_class_install_std_props (GstElementClass * klass, - const gchar * first_name, ...); +void gst_element_class_install_std_props (GstElementClass * klass, + const gchar * first_name, ...); /* pad functions */ gboolean gst_pad_can_link (GstPad *srcpad, GstPad *sinkpad); @@ -264,6 +269,12 @@ GstCaps* gst_pad_get_fixed_caps_func (GstPad *pad); GstCaps* gst_pad_proxy_getcaps (GstPad * pad); gboolean gst_pad_proxy_setcaps (GstPad * pad, GstCaps * caps); +/* util query functions */ +gboolean gst_pad_query_position (GstPad *pad, GstFormat *format, + gint64 *cur, gint64 *end); +gboolean gst_pad_query_convert (GstPad *pad, GstFormat src_format, gint64 src_val, + GstFormat *dest_fmt, gint64 *dest_val); + /* bin functions */ void gst_bin_add_many (GstBin *bin, GstElement *element_1, ...); void gst_bin_remove_many (GstBin *bin, GstElement *element_1, ...); diff --git a/libs/gst/base/gstbasesrc.c b/libs/gst/base/gstbasesrc.c index 5031568..2d7b966 100644 --- a/libs/gst/base/gstbasesrc.c +++ b/libs/gst/base/gstbasesrc.c @@ -89,9 +89,11 @@ static void gst_basesrc_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec); static gboolean gst_basesrc_event_handler (GstPad * pad, GstEvent * event); -static gboolean gst_basesrc_query2 (GstPad * pad, GstQuery * query); +static gboolean gst_basesrc_query (GstPad * pad, GstQuery * query); +#if 0 static const GstEventMask *gst_basesrc_get_event_mask (GstPad * pad); +#endif static gboolean gst_basesrc_unlock (GstBaseSrc * basesrc); static gboolean gst_basesrc_get_size (GstBaseSrc * basesrc, guint64 * size); @@ -158,9 +160,7 @@ gst_basesrc_init (GstBaseSrc * basesrc, gpointer g_class) gst_pad_set_activate_function (pad, gst_basesrc_activate); gst_pad_set_event_function (pad, gst_basesrc_event_handler); - gst_pad_set_event_mask_function (pad, gst_basesrc_get_event_mask); - - gst_pad_set_query2_function (pad, gst_basesrc_query2); + gst_pad_set_query_function (pad, gst_basesrc_query); gst_pad_set_checkgetrange_function (pad, gst_basesrc_check_get_range); @@ -193,7 +193,7 @@ gst_basesrc_set_dataflow_funcs (GstBaseSrc * this) } static gboolean -gst_basesrc_query2 (GstPad * pad, GstQuery * query) +gst_basesrc_query (GstPad * pad, GstQuery * query) { gboolean b; guint64 ui64; @@ -207,7 +207,7 @@ gst_basesrc_query2 (GstPad * pad, GstQuery * query) { GstFormat format; - gst_query_parse_position_query (query, &format); + gst_query_parse_position (query, &format, NULL, NULL); switch (format) { case GST_FORMAT_DEFAULT: case GST_FORMAT_BYTES: @@ -243,10 +243,11 @@ gst_basesrc_query2 (GstPad * pad, GstQuery * query) case GST_QUERY_RATE: case GST_QUERY_CONVERT: default: - return gst_pad_query2_default (pad, query); + return gst_pad_query_default (pad, query); } } +#if 0 static const GstEventMask * gst_basesrc_get_event_mask (GstPad * pad) { @@ -260,6 +261,7 @@ gst_basesrc_get_event_mask (GstPad * pad) }; return masks; } +#endif static gboolean gst_basesrc_do_seek (GstBaseSrc * src, GstEvent * event) diff --git a/plugins/elements/gstfilesink.c b/plugins/elements/gstfilesink.c index c0da0e3..cc44e97 100644 --- a/plugins/elements/gstfilesink.c +++ b/plugins/elements/gstfilesink.c @@ -80,7 +80,7 @@ static gboolean gst_filesink_event (GstBaseSink * sink, GstEvent * event); static GstFlowReturn gst_filesink_render (GstBaseSink * sink, GstBuffer * buffer); -static gboolean gst_filesink_query2 (GstPad * pad, GstQuery * query); +static gboolean gst_filesink_query (GstPad * pad, GstQuery * query); static void gst_filesink_uri_handler_init (gpointer g_iface, gpointer iface_data); @@ -144,7 +144,7 @@ gst_filesink_init (GstFileSink * filesink) pad = GST_BASESINK_PAD (filesink); - gst_pad_set_query2_function (pad, gst_filesink_query2); + gst_pad_set_query_function (pad, gst_filesink_query); filesink->filename = NULL; filesink->file = NULL; @@ -255,7 +255,7 @@ gst_filesink_close_file (GstFileSink * sink) } static gboolean -gst_filesink_query2 (GstPad * pad, GstQuery * query) +gst_filesink_query (GstPad * pad, GstQuery * query) { GstFileSink *self; GstFormat format; @@ -264,7 +264,7 @@ gst_filesink_query2 (GstPad * pad, GstQuery * query) switch (GST_QUERY_TYPE (query)) { case GST_QUERY_POSITION: - gst_query_parse_position_query (query, &format); + gst_query_parse_position (query, &format, NULL, NULL); switch (format) { case GST_FORMAT_DEFAULT: case GST_FORMAT_BYTES: @@ -280,7 +280,7 @@ gst_filesink_query2 (GstPad * pad, GstQuery * query) return TRUE; default: - return gst_pad_query2_default (pad, query); + return gst_pad_query_default (pad, query); } } diff --git a/plugins/elements/gstqueue.c b/plugins/elements/gstqueue.c index 0596538..aa2b905 100644 --- a/plugins/elements/gstqueue.c +++ b/plugins/elements/gstqueue.c @@ -133,8 +133,7 @@ static void gst_queue_loop (GstPad * pad); static gboolean gst_queue_handle_sink_event (GstPad * pad, GstEvent * event); static gboolean gst_queue_handle_src_event (GstPad * pad, GstEvent * event); -static gboolean gst_queue_handle_src_query (GstPad * pad, - GstQueryType type, GstFormat * fmt, gint64 * value); +static gboolean gst_queue_handle_src_query (GstPad * pad, GstQuery * query); static GstCaps *gst_queue_getcaps (GstPad * pad); static GstPadLinkReturn gst_queue_link_sink (GstPad * pad, GstPad * peer); @@ -811,29 +810,42 @@ gst_queue_handle_src_event (GstPad * pad, GstEvent * event) } static gboolean -gst_queue_handle_src_query (GstPad * pad, - GstQueryType type, GstFormat * fmt, gint64 * value) +gst_queue_handle_src_query (GstPad * pad, GstQuery * query) { GstQueue *queue = GST_QUEUE (GST_PAD_PARENT (pad)); if (!GST_PAD_PEER (queue->sinkpad)) return FALSE; - if (!gst_pad_query (GST_PAD_PEER (queue->sinkpad), type, fmt, value)) + if (!gst_pad_query (GST_PAD_PEER (queue->sinkpad), query)) return FALSE; - if (type == GST_QUERY_POSITION) { - /* FIXME: this code assumes that there's no discont in the queue */ - switch (*fmt) { - case GST_FORMAT_BYTES: - *value -= queue->cur_level.bytes; - break; - case GST_FORMAT_TIME: - *value -= queue->cur_level.time; - break; - default: - /* FIXME */ - break; + switch (GST_QUERY_TYPE (query)) { + case GST_QUERY_POSITION: + { + gint64 peer_pos, peer_total; + GstFormat format; + + /* get peer position */ + gst_query_parse_position (query, &format, &peer_pos, &peer_total); + + /* FIXME: this code assumes that there's no discont in the queue */ + switch (format) { + case GST_FORMAT_BYTES: + peer_pos -= queue->cur_level.bytes; + break; + case GST_FORMAT_TIME: + peer_pos -= queue->cur_level.time; + break; + default: + /* FIXME */ + break; + } + /* set updated positions */ + gst_query_set_position (query, format, peer_pos, peer_total); + break; } + default: + break; } return TRUE; diff --git a/plugins/elements/gsttypefindelement.c b/plugins/elements/gsttypefindelement.c index 994e04f..5aeece8 100644 --- a/plugins/elements/gsttypefindelement.c +++ b/plugins/elements/gsttypefindelement.c @@ -115,11 +115,13 @@ static void gst_type_find_element_set_property (GObject * object, static void gst_type_find_element_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec); +#if 0 static const GstEventMask *gst_type_find_element_src_event_mask (GstPad * pad); +#endif + static gboolean gst_type_find_element_src_event (GstPad * pad, GstEvent * event); -static gboolean gst_type_find_handle_src_query (GstPad * pad, - GstQueryType type, GstFormat * fmt, gint64 * value); +static gboolean gst_type_find_handle_src_query (GstPad * pad, GstQuery * query); static GstFlowReturn push_buffer_store (GstTypeFindElement * typefind); static gboolean gst_type_find_element_handle_event (GstPad * pad, @@ -219,8 +221,6 @@ gst_type_find_element_init (GstTypeFindElement * typefind) gst_type_find_element_checkgetrange); gst_pad_set_getrange_function (typefind->src, gst_type_find_element_getrange); gst_pad_set_event_function (typefind->src, gst_type_find_element_src_event); - gst_pad_set_event_mask_function (typefind->src, - gst_type_find_element_src_event_mask); gst_pad_set_query_function (typefind->src, GST_DEBUG_FUNCPTR (gst_type_find_handle_src_query)); gst_pad_use_fixed_caps (typefind->src); @@ -295,32 +295,48 @@ gst_type_find_element_get_property (GObject * object, guint prop_id, } static gboolean -gst_type_find_handle_src_query (GstPad * pad, - GstQueryType type, GstFormat * fmt, gint64 * value) +gst_type_find_handle_src_query (GstPad * pad, GstQuery * query) { - GstTypeFindElement *typefind = - GST_TYPE_FIND_ELEMENT (gst_pad_get_parent (pad)); + GstTypeFindElement *typefind; gboolean res; - res = gst_pad_query (GST_PAD_PEER (typefind->sink), type, fmt, value); + typefind = GST_TYPE_FIND_ELEMENT (GST_PAD_PARENT (pad)); + + res = gst_pad_query (GST_PAD_PEER (typefind->sink), query); if (!res) return FALSE; - if (type == GST_QUERY_POSITION && typefind->store != NULL) { - /* FIXME: this code assumes that there's no discont in the queue */ - switch (*fmt) { - case GST_FORMAT_BYTES: - *value -= gst_buffer_store_get_size (typefind->store, 0); - break; - default: - /* FIXME */ - break; + switch (GST_QUERY_TYPE (query)) { + case GST_QUERY_POSITION: + { + gint64 peer_pos, peer_total; + GstFormat format; + + if (typefind->store == NULL) + return TRUE; + + gst_query_parse_position (query, &format, &peer_pos, &peer_total); + + /* FIXME: this code assumes that there's no discont in the queue */ + switch (format) { + case GST_FORMAT_BYTES: + peer_pos -= gst_buffer_store_get_size (typefind->store, 0); + break; + default: + /* FIXME */ + break; + } + gst_query_set_position (query, format, peer_pos, peer_total); + break; } + default: + break; } return TRUE; } +#if 0 static const GstEventMask * gst_type_find_element_src_event_mask (GstPad * pad) { @@ -334,6 +350,7 @@ gst_type_find_element_src_event_mask (GstPad * pad) return mask; } +#endif static gboolean gst_type_find_element_src_event (GstPad * pad, GstEvent * event) @@ -462,24 +479,29 @@ find_element_get_length (gpointer data) return 0; } if (entry->self->stream_length == 0) { - typefind->stream_length_available = - gst_pad_query (GST_PAD_PEER (entry->self->sink), GST_QUERY_TOTAL, - &format, (gint64 *) & entry->self->stream_length); - if (format != GST_FORMAT_BYTES) + if (!gst_pad_query_position (GST_PAD_PEER (entry->self->sink), &format, + NULL, (gint64 *) & entry->self->stream_length)) + goto no_length; + + if (format != GST_FORMAT_BYTES) { typefind->stream_length_available = FALSE; - if (!typefind->stream_length_available) { - GST_DEBUG_OBJECT (entry->self, - "'%s' called get_length () but it's not available", - GST_PLUGIN_FEATURE_NAME (entry->factory)); - return 0; + entry->self->stream_length = 0; } else { GST_DEBUG_OBJECT (entry->self, "'%s' called get_length () and it's %" G_GUINT64_FORMAT " bytes", GST_PLUGIN_FEATURE_NAME (entry->factory), entry->self->stream_length); } } - return entry->self->stream_length; + +no_length: + { + typefind->stream_length_available = FALSE; + GST_DEBUG_OBJECT (entry->self, + "'%s' called get_length () but it's not available", + GST_PLUGIN_FEATURE_NAME (entry->factory)); + return 0; + } } static gboolean diff --git a/tools/gst-inspect.c b/tools/gst-inspect.c index 67b25d6..e0aca2e 100644 --- a/tools/gst-inspect.c +++ b/tools/gst-inspect.c @@ -87,6 +87,7 @@ print_caps (const GstCaps * caps, const gchar * pfx) } } +#if 0 static void print_formats (const GstFormat * formats) { @@ -103,6 +104,7 @@ print_formats (const GstFormat * formats) formats++; } } +#endif static void print_query_types (const GstQueryType * types) @@ -122,6 +124,7 @@ print_query_types (const GstQueryType * types) } #ifndef GST_DISABLE_ENUMTYPES +#if 0 static void print_event_masks (const GstEventMask * masks) { @@ -169,6 +172,7 @@ print_event_masks (const GstEventMask * masks) masks++; } } +#endif #else static void print_event_masks (const GstEventMask * masks) @@ -631,20 +635,9 @@ print_pad_info (GstElement * element) if (realpad->getrangefunc) n_print (" Has getrangefunc(): %s\n", GST_DEBUG_FUNCPTR_NAME (realpad->getrangefunc)); - if (realpad->formatsfunc != gst_pad_get_formats_default) { - n_print (" Supports seeking/conversion/query formats:\n"); - print_formats (gst_pad_get_formats (GST_PAD (realpad))); - } - if (realpad->convertfunc != gst_pad_convert_default) - n_print (" Has custom convertfunc(): %s\n", - GST_DEBUG_FUNCPTR_NAME (realpad->convertfunc)); if (realpad->eventfunc != gst_pad_event_default) n_print (" Has custom eventfunc(): %s\n", GST_DEBUG_FUNCPTR_NAME (realpad->eventfunc)); - if (realpad->eventmaskfunc != gst_pad_get_event_masks_default) { - n_print (" Provides event masks:\n"); - print_event_masks (gst_pad_get_event_masks (GST_PAD (realpad))); - } if (realpad->queryfunc != gst_pad_query_default) n_print (" Has custom queryfunc(): %s\n", GST_DEBUG_FUNCPTR_NAME (realpad->queryfunc)); diff --git a/tools/gst-xmlinspect.c b/tools/gst-xmlinspect.c index fd478a6..2548437 100644 --- a/tools/gst-xmlinspect.c +++ b/tools/gst-xmlinspect.c @@ -73,6 +73,7 @@ print_caps (const GstCaps * caps, gint pfx) g_free (s); } +#if 0 static void print_formats (const GstFormat * formats, gint pfx) { @@ -89,6 +90,7 @@ print_formats (const GstFormat * formats, gint pfx) formats++; } } +#endif static void print_query_types (const GstQueryType * types, gint pfx) @@ -107,6 +109,7 @@ print_query_types (const GstQueryType * types, gint pfx) } } +#if 0 static void print_event_masks (const GstEventMask * masks, gint pfx) { @@ -156,6 +159,7 @@ print_event_masks (const GstEventMask * masks, gint pfx) } #endif } +#endif static void output_hierarchy (GType type, gint level, gint * maxlevel) @@ -606,24 +610,9 @@ print_element_info (GstElementFactory * factory) if (realpad->getrangefunc) PUT_STRING (4, "", GST_DEBUG_FUNCPTR_NAME (realpad->getrangefunc)); - if (realpad->formatsfunc != gst_pad_get_formats_default) { - PUT_STRING (4, "", - GST_DEBUG_FUNCPTR_NAME (realpad->formatsfunc)); - print_formats (gst_pad_get_formats (GST_PAD (realpad)), 5); - PUT_END_TAG (4, "formats-function"); - } - if (realpad->convertfunc != gst_pad_convert_default) - PUT_STRING (4, "", - GST_DEBUG_FUNCPTR_NAME (realpad->convertfunc)); if (realpad->eventfunc != gst_pad_event_default) PUT_STRING (4, "", GST_DEBUG_FUNCPTR_NAME (realpad->eventfunc)); - if (realpad->eventmaskfunc != gst_pad_get_event_masks_default) { - PUT_STRING (4, "", - GST_DEBUG_FUNCPTR_NAME (realpad->eventmaskfunc)); - print_event_masks (gst_pad_get_event_masks (GST_PAD (realpad)), 5); - PUT_END_TAG (4, "event-mask-func"); - } if (realpad->queryfunc != gst_pad_query_default) PUT_STRING (4, "", GST_DEBUG_FUNCPTR_NAME (realpad->queryfunc)); -- 2.7.4