From 8970bda4baa0d1bad389c84853066c6458ed7c22 Mon Sep 17 00:00:00 2001 From: Andy Wingo Date: Fri, 6 May 2005 21:41:22 +0000 Subject: [PATCH] gst/gstquery.h Original commit message from CVS: 2005-05-06 Andy Wingo * gst/gstquery.h * gst/gstquery.c (_gst_query_initialize): Extend GstQuery from GstData, init a memchunk. (standard_definitions): Add a few query types, deprecate a few. (gst_query_get_type): New proc. (_gst_query_copy, _gst_query_free, gst_query_new): GstData implementation. (gst_query_new_application, gst_query_get_structure): New public procs. * docs/design/draft-query.txt: Removed LINKS from the query types, because all the rest can be dispatched to other pads -- seemed ugly to have a query that couldn't be dispatched. internal_links is fine as a pad method. * gst/gstpad.h: Add query2 as a pad method, add the new functions in gstpad.c, but maintain binary compatibility for the moment. Will fix before 0.9 is out. * gst/gstqueryutils.c: * gst/gstqueryutils.h: New files, implement 3 methods for each query type: parse_query, parse_response, and set. Probably need an allocator as well. * gst/gst.h: Add gstquery.h and gstqueryutils.h to the list. * gst/elements/gstfilesink.c (gst_filesink_query2): * gst/base/gstbasesrc.c (gst_basesrc_query2): Replace old query, query_types, and formats methods. * gst/gstpad.c (gst_pad_query2, gst_pad_query2_default) (gst_pad_set_query2_function): New functions. (gst_real_pad_init): Set query2_default as the default query2 function. Basically just dispatches to internally linked pads. Needs review! * gst/gstdata_private.h (_GST_DATA_INIT): Set data->refcount to 1 without using the atomic operations. Only one thread can possibly be accessing the data at this point. Changed so as to avoid gst_atomic operations. --- ChangeLog | 44 +++++++++++ docs/design/draft-query.txt | 4 - docs/gst/tmpl/gstquery.sgml | 3 + gst/base/gstbasesrc.c | 115 +++++++++++---------------- gst/elements/gstfilesink.c | 72 ++++++----------- gst/gst.c | 2 +- gst/gst.h | 2 + gst/gstdata_private.h | 2 +- gst/gstpad.c | 70 +++++++++++++++++ gst/gstpad.h | 18 ++++- gst/gstquery.c | 111 +++++++++++++++++++++++++- gst/gstquery.h | 69 ++++++++++++++--- gst/gstqueryutils.c | 138 +++++++++++++++++++++++++++++++++ gst/gstqueryutils.h | 39 ++++++++++ libs/gst/base/gstbasesrc.c | 115 +++++++++++---------------- plugins/elements/gstfilesink.c | 72 ++++++----------- 16 files changed, 613 insertions(+), 263 deletions(-) create mode 100644 gst/gstqueryutils.c create mode 100644 gst/gstqueryutils.h diff --git a/ChangeLog b/ChangeLog index 394a597f4e..2024f31981 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,47 @@ +2005-05-06 Andy Wingo + + * gst/gstquery.h + * gst/gstquery.c (_gst_query_initialize): Extend GstQuery from + GstData, init a memchunk. + (standard_definitions): Add a few query types, deprecate a few. + (gst_query_get_type): New proc. + (_gst_query_copy, _gst_query_free, gst_query_new): GstData + implementation. + (gst_query_new_application, gst_query_get_structure): New public + procs. + + * docs/design/draft-query.txt: Removed LINKS from the query types, + because all the rest can be dispatched to other pads -- seemed + ugly to have a query that couldn't be dispatched. internal_links + is fine as a pad method. + + * gst/gstpad.h: Add query2 as a pad method, add the new functions + in gstpad.c, but maintain binary compatibility for the moment. + Will fix before 0.9 is out. + + * gst/gstqueryutils.c: + * gst/gstqueryutils.h: New files, implement 3 methods for each + query type: parse_query, parse_response, and set. Probably need an + allocator as well. + + * gst/gst.h: Add gstquery.h and gstqueryutils.h to the list. + + * gst/elements/gstfilesink.c (gst_filesink_query2): + * gst/base/gstbasesrc.c (gst_basesrc_query2): Replace old query, + query_types, and formats methods. + + * gst/gstpad.c (gst_pad_query2, gst_pad_query2_default) + (gst_pad_set_query2_function): New functions. + (gst_real_pad_init): Set query2_default as the default query2 + function. Basically just dispatches to internally linked pads. + + Needs review! + + * gst/gstdata_private.h (_GST_DATA_INIT): Set data->refcount to 1 + without using the atomic operations. Only one thread can possibly + be accessing the data at this point. Changed so as to avoid + gst_atomic operations. + 2005-05-06 Wim Taymans * gst/gstpad.c: (gst_pad_alloc_buffer), (gst_pad_push): diff --git a/docs/design/draft-query.txt b/docs/design/draft-query.txt index 7a4f81ea39..c7dcb48a8d 100644 --- a/docs/design/draft-query.txt +++ b/docs/design/draft-query.txt @@ -83,10 +83,6 @@ Proposed types - return list of supported formats. - - GST_QUERY_LINKS: - - - return list of internal link pads. - Also???? - GST_QUERY_CAPS: diff --git a/docs/gst/tmpl/gstquery.sgml b/docs/gst/tmpl/gstquery.sgml index 24d7577f0c..4d8e1b27a6 100644 --- a/docs/gst/tmpl/gstquery.sgml +++ b/docs/gst/tmpl/gstquery.sgml @@ -28,6 +28,9 @@ Standard predefined Query types @GST_QUERY_START: start of configured segment @GST_QUERY_SEGMENT_END: end of configured segment @GST_QUERY_RATE: current rate of the stream +@GST_QUERY_SEEKING: +@GST_QUERY_CONVERT: +@GST_QUERY_FORMATS: diff --git a/gst/base/gstbasesrc.c b/gst/base/gstbasesrc.c index e9ff0faede..503156870e 100644 --- a/gst/base/gstbasesrc.c +++ b/gst/base/gstbasesrc.c @@ -88,11 +88,10 @@ static void gst_basesrc_set_property (GObject * object, guint prop_id, 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 const GstEventMask *gst_basesrc_get_event_mask (GstPad * pad); -static const GstQueryType *gst_basesrc_get_query_types (GstPad * pad); -static gboolean gst_basesrc_query (GstPad * pad, GstQueryType type, - GstFormat * format, gint64 * value); -static const GstFormat *gst_basesrc_get_formats (GstPad * pad); static gboolean gst_basesrc_unlock (GstBaseSrc * basesrc); static gboolean gst_basesrc_get_size (GstBaseSrc * basesrc, guint64 * size); @@ -160,10 +159,11 @@ 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_query_function (pad, gst_basesrc_query); - gst_pad_set_query_type_function (pad, gst_basesrc_get_query_types); - gst_pad_set_formats_function (pad, gst_basesrc_get_formats); + + gst_pad_set_query2_function (pad, gst_basesrc_query2); + gst_pad_set_checkgetrange_function (pad, gst_basesrc_check_get_range); + /* hold ref to pad */ basesrc->srcpad = pad; gst_element_add_pad (GST_ELEMENT (basesrc), pad); @@ -192,84 +192,59 @@ gst_basesrc_set_dataflow_funcs (GstBaseSrc * this) gst_pad_set_getrange_function (this->srcpad, NULL); } -static const GstFormat * -gst_basesrc_get_formats (GstPad * pad) -{ - static const GstFormat formats[] = { - GST_FORMAT_DEFAULT, - GST_FORMAT_BYTES, - 0, - }; - - return formats; -} - -static const GstQueryType * -gst_basesrc_get_query_types (GstPad * pad) -{ - static const GstQueryType types[] = { - GST_QUERY_TOTAL, - GST_QUERY_POSITION, - GST_QUERY_START, - GST_QUERY_SEGMENT_END, - 0, - }; - - return types; -} - static gboolean -gst_basesrc_query (GstPad * pad, GstQueryType type, - GstFormat * format, gint64 * value) +gst_basesrc_query2 (GstPad * pad, GstQuery * query) { - GstBaseSrc *src = GST_BASESRC (GST_PAD_PARENT (pad)); - - if (*format == GST_FORMAT_DEFAULT) - *format = GST_FORMAT_BYTES; + gboolean b; + guint64 ui64; + gint64 i64; + GstBaseSrc *src; - switch (type) { - case GST_QUERY_TOTAL: - switch (*format) { - case GST_FORMAT_BYTES: - { - gboolean ret; + src = GST_BASESRC (GST_PAD_PARENT (pad)); - ret = gst_basesrc_get_size (src, (guint64 *) value); - GST_DEBUG ("getting length %d %lld", ret, *value); - return ret; - } - case GST_FORMAT_PERCENT: - *value = GST_FORMAT_PERCENT_MAX; - return TRUE; - default: - return FALSE; - } - break; + switch (GST_QUERY_TYPE (query)) { case GST_QUERY_POSITION: - switch (*format) { + { + GstFormat format; + + gst_query_parse_position_query (query, &format); + switch (format) { + case GST_FORMAT_DEFAULT: case GST_FORMAT_BYTES: - *value = src->offset; - break; + b = gst_basesrc_get_size (src, &ui64); + /* better to make get_size take an int64 */ + i64 = b ? (gint64) ui64 : -1; + gst_query_set_position (query, GST_FORMAT_BYTES, src->offset, i64); + return TRUE; case GST_FORMAT_PERCENT: - /* fixme */ - if (!gst_basesrc_get_size (src, (guint64 *) value)) - return FALSE; - *value = src->offset * GST_FORMAT_PERCENT_MAX / *value; + b = gst_basesrc_get_size (src, &ui64); + i64 = GST_FORMAT_PERCENT_MAX; + i64 *= b ? (src->offset / (gdouble) ui64) : 1.0; + gst_query_set_position (query, GST_FORMAT_PERCENT, + i64, GST_FORMAT_PERCENT_MAX); return TRUE; default: return FALSE; } - break; - case GST_QUERY_START: - *value = src->segment_start; + } + + case GST_QUERY_SEEKING: + gst_query_set_seeking (query, GST_FORMAT_BYTES, + src->seekable, src->segment_start, src->segment_end); return TRUE; - case GST_QUERY_SEGMENT_END: - *value = src->segment_end; + + case GST_QUERY_FORMATS: + gst_query_set_formats (query, 3, GST_FORMAT_DEFAULT, + GST_FORMAT_BYTES, GST_FORMAT_PERCENT); return TRUE; + + case GST_QUERY_LATENCY: + case GST_QUERY_JITTER: + case GST_QUERY_RATE: + case GST_QUERY_CONVERT: default: - return FALSE; + return gst_pad_query2_default (pad, query); } - return FALSE; } static const GstEventMask * diff --git a/gst/elements/gstfilesink.c b/gst/elements/gstfilesink.c index 162f649dda..c0da0e3632 100644 --- a/gst/elements/gstfilesink.c +++ b/gst/elements/gstfilesink.c @@ -66,29 +66,6 @@ enum ARG_LOCATION }; -static const GstFormat * -gst_filesink_get_formats (GstPad * pad) -{ - static const GstFormat formats[] = { - GST_FORMAT_BYTES, - 0, - }; - - return formats; -} - -static const GstQueryType * -gst_filesink_get_query_types (GstPad * pad) -{ - static const GstQueryType types[] = { - GST_QUERY_TOTAL, - GST_QUERY_POSITION, - 0 - }; - - return types; -} - static void gst_filesink_dispose (GObject * object); static void gst_filesink_set_property (GObject * object, guint prop_id, @@ -103,8 +80,7 @@ static gboolean gst_filesink_event (GstBaseSink * sink, GstEvent * event); static GstFlowReturn gst_filesink_render (GstBaseSink * sink, GstBuffer * buffer); -static gboolean gst_filesink_pad_query (GstPad * pad, GstQueryType type, - GstFormat * format, gint64 * value); +static gboolean gst_filesink_query2 (GstPad * pad, GstQuery * query); static void gst_filesink_uri_handler_init (gpointer g_iface, gpointer iface_data); @@ -141,6 +117,7 @@ gst_filesink_base_init (gpointer g_class) gst_static_pad_template_get (&sinktemplate)); gst_element_class_set_details (gstelement_class, &gst_filesink_details); } + static void gst_filesink_class_init (GstFileSinkClass * klass) { @@ -159,6 +136,7 @@ gst_filesink_class_init (GstFileSinkClass * klass) gstbasesink_class->render = GST_DEBUG_FUNCPTR (gst_filesink_render); gstbasesink_class->event = GST_DEBUG_FUNCPTR (gst_filesink_event); } + static void gst_filesink_init (GstFileSink * filesink) { @@ -166,13 +144,12 @@ gst_filesink_init (GstFileSink * filesink) pad = GST_BASESINK_PAD (filesink); - gst_pad_set_query_function (pad, gst_filesink_pad_query); - gst_pad_set_query_type_function (pad, gst_filesink_get_query_types); - gst_pad_set_formats_function (pad, gst_filesink_get_formats); + gst_pad_set_query2_function (pad, gst_filesink_query2); filesink->filename = NULL; filesink->file = NULL; } + static void gst_filesink_dispose (GObject * object) { @@ -278,36 +255,33 @@ gst_filesink_close_file (GstFileSink * sink) } static gboolean -gst_filesink_pad_query (GstPad * pad, GstQueryType type, - GstFormat * format, gint64 * value) +gst_filesink_query2 (GstPad * pad, GstQuery * query) { - GstFileSink *sink = GST_FILESINK (GST_PAD_PARENT (pad)); + GstFileSink *self; + GstFormat format; - switch (type) { - case GST_QUERY_TOTAL: - switch (*format) { - case GST_FORMAT_BYTES: - *value = sink->data_written; /* FIXME - doesn't the kernel provide - such a function? */ - break; - default: - return FALSE; - } - break; + self = GST_FILESINK (GST_PAD_PARENT (pad)); + + switch (GST_QUERY_TYPE (query)) { case GST_QUERY_POSITION: - switch (*format) { + gst_query_parse_position_query (query, &format); + switch (format) { + case GST_FORMAT_DEFAULT: case GST_FORMAT_BYTES: - *value = ftell (sink->file); - break; + gst_query_set_position (query, GST_FORMAT_BYTES, + self->data_written, self->data_written); + return TRUE; default: return FALSE; } - break; + + case GST_QUERY_FORMATS: + gst_query_set_formats (query, 2, GST_FORMAT_DEFAULT, GST_FORMAT_BYTES); + return TRUE; + default: - return FALSE; + return gst_pad_query2_default (pad, query); } - - return TRUE; } /* handle events (search) */ diff --git a/gst/gst.c b/gst/gst.c index 86092b7023..b1f7ffad63 100644 --- a/gst/gst.c +++ b/gst/gst.c @@ -582,7 +582,7 @@ init_post (void) g_log_set_handler (g_log_domain_gstreamer, llf, debug_log_handler, NULL); _gst_format_initialize (); - _gst_query_type_initialize (); + _gst_query_initialize (); gst_object_get_type (); gst_probe_get_type (); gst_pad_get_type (); diff --git a/gst/gst.h b/gst/gst.h index fe6540cbf9..04318684d7 100644 --- a/gst/gst.h +++ b/gst/gst.h @@ -48,6 +48,8 @@ #include #include #include +#include +#include #include #include #include diff --git a/gst/gstdata_private.h b/gst/gstdata_private.h index 4786fec8ae..7f5f55ab8c 100644 --- a/gst/gstdata_private.h +++ b/gst/gstdata_private.h @@ -22,7 +22,7 @@ #define _GST_DATA_INIT(data, ptype, pflags, pfree, pcopy) \ G_STMT_START { \ - gst_atomic_int_set (&(data)->refcount, 1); \ + (data)->refcount = 1; \ (data)->type = ptype; \ (data)->flags = pflags; \ (data)->free = pfree; \ diff --git a/gst/gstpad.c b/gst/gstpad.c index bbc8a58088..92ee6e067c 100644 --- a/gst/gstpad.c +++ b/gst/gstpad.c @@ -251,6 +251,8 @@ gst_real_pad_init (GstRealPad * pad) 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; @@ -987,6 +989,24 @@ gst_pad_set_query_function (GstPad * pad, GstPadQueryFunction query) GST_DEBUG_PAD_NAME (pad), GST_DEBUG_FUNCPTR_NAME (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. @@ -3793,6 +3813,56 @@ gst_pad_query (GstPad * pad, GstQueryType type, 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) +{ + GstRealPad *rpad; + + 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); + + g_return_val_if_fail (rpad, FALSE); + + if (GST_RPAD_QUERY2FUNC (rpad)) + return GST_RPAD_QUERY2FUNC (rpad) (GST_PAD_CAST (rpad), query); + + return FALSE; +} + +gboolean +gst_pad_query2_default (GstPad * pad, GstQuery * query) +{ + 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); + } +} + static gboolean gst_pad_get_formats_dispatcher (GstPad * pad, const GstFormat ** data) { diff --git a/gst/gstpad.h b/gst/gstpad.h index 3b5cf2e37e..02cfeeba97 100644 --- a/gst/gstpad.h +++ b/gst/gstpad.h @@ -141,7 +141,7 @@ typedef GstFlowReturn (*GstPadGetRangeFunction) (GstPad *pad, guint64 offset, typedef gboolean (*GstPadCheckGetRangeFunction) (GstPad *pad); typedef gboolean (*GstPadEventFunction) (GstPad *pad, GstEvent *event); -/* convert/query/format functions */ +/* old, deprecated convert/query/format functions */ typedef gboolean (*GstPadConvertFunction) (GstPad *pad, GstFormat src_format, gint64 src_value, GstFormat *dest_format, gint64 *dest_value); @@ -152,6 +152,9 @@ 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); + /* linking */ typedef GstPadLinkReturn (*GstPadLinkFunction) (GstPad *pad, GstPad *peer); typedef void (*GstPadUnlinkFunction) (GstPad *pad); @@ -249,7 +252,7 @@ struct _GstRealPad { GList *ghostpads; guint32 ghostpads_cookie; - /* query/convert/formats functions */ + /* old, deprecated query/convert/formats functions */ GstPadConvertFunction convertfunc; GstPadQueryFunction queryfunc; GstPadFormatsFunction formatsfunc; @@ -260,8 +263,12 @@ struct _GstRealPad { GstProbeDispatcher probedisp; + /* generic query method */ + GstPadQuery2Function query2func; + /*< private >*/ - gpointer _gst_reserved[GST_PADDING]; + /* fixme: bring back to gst_padding when old query functions go away */ + gpointer _gst_reserved[GST_PADDING - 1]; }; struct _GstRealPadClass { @@ -313,6 +320,7 @@ struct _GstGhostPadClass { #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) @@ -566,6 +574,10 @@ void gst_pad_set_internal_link_function (GstPad *pad, GstPadIntLinkFunction in 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); + /* misc helper functions */ gboolean gst_pad_dispatcher (GstPad *pad, GstPadDispatcherFunction dispatch, gpointer data); diff --git a/gst/gstquery.c b/gst/gstquery.c index ffb64498bf..5f02fe4f9a 100644 --- a/gst/gstquery.c +++ b/gst/gstquery.c @@ -25,6 +25,12 @@ #include "gst_private.h" #include "gstquery.h" +#include "gstmemchunk.h" +#include "gstdata_private.h" + + +GType _gst_query_type; + static GStaticMutex mutex = G_STATIC_MUTEX_INIT; static GList *_gst_queries = NULL; @@ -32,22 +38,29 @@ static GHashTable *_nick_to_query = NULL; static GHashTable *_query_type_to_nick = NULL; static guint32 _n_values = 1; /* we start from 1 because 0 reserved for NONE */ +static GstMemChunk *chunk; + static GstQueryTypeDefinition standard_definitions[] = { - {GST_QUERY_TOTAL, "total", "Total length"}, + {GST_QUERY_TOTAL, "total", "Total length"}, /* deprecated */ {GST_QUERY_POSITION, "position", "Current Position"}, {GST_QUERY_LATENCY, "latency", "Latency"}, {GST_QUERY_JITTER, "jitter", "Jitter"}, - {GST_QUERY_START, "start", "Start position of stream"}, - {GST_QUERY_SEGMENT_END, "segment_end", "End position of the stream"}, + {GST_QUERY_START, "start", "Start position of stream"}, /* deprecated */ + {GST_QUERY_SEGMENT_END, "segment_end", "End position of the stream"}, /* dep */ {GST_QUERY_RATE, "rate", "Configured rate 1000000 = 1"}, + {GST_QUERY_SEEKING, "seeking", "Seeking capabilities and parameters"}, + {GST_QUERY_CONVERT, "convert", "Converting between formats"}, {0, NULL, NULL} }; + void -_gst_query_type_initialize (void) +_gst_query_initialize (void) { GstQueryTypeDefinition *standards = standard_definitions; + GST_CAT_INFO (GST_CAT_GST_INIT, "init queries"); + g_static_mutex_lock (&mutex); if (_nick_to_query == NULL) { _nick_to_query = g_hash_table_new (g_str_hash, g_str_equal); @@ -64,6 +77,13 @@ _gst_query_type_initialize (void) _n_values++; } g_static_mutex_unlock (&mutex); + + /* register the type */ + _gst_query_type = g_boxed_type_register_static ("GstQuery", + (GBoxedCopyFunc) gst_data_copy, (GBoxedFreeFunc) gst_data_unref); + + chunk = gst_mem_chunk_new ("GstQueryChunk", sizeof (GstQuery), + sizeof (GstQuery) * 20, 0); } /** @@ -197,3 +217,86 @@ gst_query_type_iterate_definitions (void) return result; } + +GType +gst_query_get_type (void) +{ + return _gst_query_type; +} + +static GstQuery * +_gst_query_copy (GstQuery * query) +{ + GstQuery *copy; + + GST_LOG ("copy query %p", query); + + copy = gst_mem_chunk_alloc (chunk); + + memcpy (copy, query, sizeof (GstQuery)); + + if (query->structure) { + copy->structure = gst_structure_copy (query->structure); + gst_structure_set_parent_refcount (copy->structure, + &GST_DATA_REFCOUNT (query)); + } + + return copy; +} + +static void +_gst_query_free (GstQuery * query) +{ + GST_LOG ("freeing query %p", query); + + if (query->structure) { + gst_structure_set_parent_refcount (query->structure, NULL); + gst_structure_free (query->structure); + } + + _GST_DATA_DISPOSE (GST_DATA (query)); + gst_mem_chunk_free (chunk, query); +} + +static GstQuery * +gst_query_new (GstQueryType type, GstStructure * structure) +{ + GstQuery *query; + + query = gst_mem_chunk_alloc0 (chunk); + + GST_DEBUG ("creating new query %p %d", query, type); + + _GST_DATA_INIT (GST_DATA (query), + _gst_query_type, + 0, + (GstDataFreeFunction) _gst_query_free, + (GstDataCopyFunction) _gst_query_copy); + + GST_QUERY_TYPE (query) = type; + + if (structure) { + query->structure = structure; + gst_structure_set_parent_refcount (query->structure, + &GST_DATA_REFCOUNT (query)); + } + + return query; +} + +GstQuery * +gst_query_new_application (GstQueryType type, GstStructure * structure) +{ + g_return_val_if_fail (gst_query_type_get_details (type) != NULL, NULL); + g_return_val_if_fail (structure != NULL, NULL); + + return gst_query_new (type, structure); +} + +GstStructure * +gst_query_get_structure (GstQuery * query) +{ + g_return_val_if_fail (GST_IS_QUERY (query), NULL); + + return query->structure; +} diff --git a/gst/gstquery.h b/gst/gstquery.h index 3b6ae641aa..70d49e86a7 100644 --- a/gst/gstquery.h +++ b/gst/gstquery.h @@ -28,24 +28,30 @@ #include #include +#include +#include G_BEGIN_DECLS typedef enum { GST_QUERY_NONE = 0, - GST_QUERY_TOTAL, + GST_QUERY_TOTAL, /* deprecated, use POSITION */ GST_QUERY_POSITION, GST_QUERY_LATENCY, - GST_QUERY_JITTER, - GST_QUERY_START, - GST_QUERY_SEGMENT_END, - GST_QUERY_RATE + GST_QUERY_JITTER, /* not in draft-query, necessary? */ + GST_QUERY_START, /* deprecated, use SEEKING */ + GST_QUERY_SEGMENT_END, /* deprecated, use SEEKING */ + GST_QUERY_RATE, /* not in draft-query, necessary? */ + GST_QUERY_SEEKING, + GST_QUERY_CONVERT, + GST_QUERY_FORMATS } GstQueryType; /* rate is relative to 1000000 */ #define GST_QUERY_TYPE_RATE_DEN G_GINT64_CONSTANT (1000000) typedef struct _GstQueryTypeDefinition GstQueryTypeDefinition; +typedef struct _GstQuery GstQuery; struct _GstQueryTypeDefinition { @@ -78,20 +84,59 @@ functionname (type object) \ } #endif -void _gst_query_type_initialize (void); +GST_EXPORT GType _gst_query_type; + +#define GST_TYPE_QUERY (_gst_query_type) +#define GST_QUERY(query) ((GstQuery*)(query)) +#define GST_IS_QUERY(query) (GST_DATA_TYPE(query) == GST_TYPE_QUERY) +#define GST_QUERY_TYPE(query) (((GstQuery*)(query))->type) + +struct _GstQuery +{ + GstData data; + + /*< public > */ + GstQueryType type; + + GstStructure *structure; + + /*< private > */ + gpointer _gst_reserved[GST_PADDING]; +}; + +void _gst_query_initialize (void); +GType gst_query_get_type (void); /* register a new query */ -GstQueryType gst_query_type_register (const gchar *nick, - const gchar *description); -GstQueryType gst_query_type_get_by_nick (const gchar *nick); +GstQueryType gst_query_type_register (const gchar *nick, + const gchar *description); +GstQueryType gst_query_type_get_by_nick (const gchar *nick); /* check if a query is in an array of querys */ -gboolean gst_query_types_contains (const GstQueryType *types, GstQueryType type); +gboolean gst_query_types_contains (const GstQueryType *types, + GstQueryType type); /* query for query details */ G_CONST_RETURN GstQueryTypeDefinition* - gst_query_type_get_details (GstQueryType type); -GstIterator* gst_query_type_iterate_definitions (void); + gst_query_type_get_details (GstQueryType type); +GstIterator* gst_query_type_iterate_definitions (void); + +/* refcounting */ +#define gst_query_ref(msg) GST_QUERY (gst_data_ref (GST_DATA (msg))) +#define gst_query_ref_by_count(msg,c) GST_QUERY (gst_data_ref_by_count (GST_DATA (msg), (c))) +#define gst_query_unref(msg) gst_data_unref (GST_DATA (msg)) +/* copy query */ +#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))) + +GstQuery * gst_query_new_application (GstQueryType type, + GstStructure *structure); + +GstStructure * gst_query_get_structure (GstQuery *query); + +/* hmm */ +#define GST_QUERY_POSITION_GET_FORMAT(q) \ + (gst_structure_get_int ((q)->structure, "format")) G_END_DECLS diff --git a/gst/gstqueryutils.c b/gst/gstqueryutils.c new file mode 100644 index 0000000000..b10645854f --- /dev/null +++ b/gst/gstqueryutils.c @@ -0,0 +1,138 @@ +/* GStreamer + * Copyright (C) 2005 Andy Wingo + * + * gstqueryutils.c: Utility functions for creating and parsing GstQueries. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + + +#include + +#include "gstqueryutils.h" + +/* some macros are just waiting to be defined here */ + + +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); + *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); + *format = g_value_get_enum (gst_structure_get_value (structure, "format")); + *cur = g_value_get_int64 (gst_structure_get_value (structure, "cur")); + *end = g_value_get_int64 (gst_structure_get_value (structure, "end")); +} + +void +gst_query_parse_seeking_query (GstQuery * query, GstFormat * format) +{ + GstStructure *structure; + + g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_SEEKING); + + structure = gst_query_get_structure (query); + *format = g_value_get_enum (gst_structure_get_value (structure, "format")); +} + +void +gst_query_set_seeking (GstQuery * query, GstFormat format, + gboolean seekable, gint64 segment_start, gint64 segment_end) +{ + GstStructure *structure; + + g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_SEEKING); + + structure = gst_query_get_structure (query); + gst_structure_set (structure, + "format", GST_TYPE_FORMAT, format, + "seekable", G_TYPE_BOOLEAN, seekable, + "segment-start", G_TYPE_INT64, segment_start, + "segment-end", G_TYPE_INT64, segment_end, NULL); +} + +void +gst_query_parse_seeking_response (GstQuery * query, GstFormat * format, + gboolean * seekable, gint64 * segment_start, gint64 * segment_end) +{ + GstStructure *structure; + + g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_SEEKING); + + structure = gst_query_get_structure (query); + *format = g_value_get_enum (gst_structure_get_value (structure, "format")); + *seekable = g_value_get_boolean (gst_structure_get_value + (structure, "seekable")); + *segment_start = g_value_get_int64 (gst_structure_get_value + (structure, "segment-start")); + *segment_end = g_value_get_int64 (gst_structure_get_value + (structure, "segment-end")); +} + +void +gst_query_set_formats (GstQuery * query, gint n_formats, ...) +{ + va_list ap; + GValue list = { 0, }; + GValue item = { 0, }; + GstStructure *structure; + gint i; + + g_value_init (&list, GST_TYPE_LIST); + + va_start (ap, n_formats); + + for (i = 0; i < n_formats; i++) { + g_value_init (&item, GST_TYPE_FORMAT); + g_value_set_enum (&item, va_arg (ap, GstFormat)); + gst_value_list_append_value (&list, &item); + g_value_unset (&item); + } + + va_end (ap); + + structure = gst_query_get_structure (query); + gst_structure_set_value (structure, "formats", &list); +} diff --git a/gst/gstqueryutils.h b/gst/gstqueryutils.h new file mode 100644 index 0000000000..3486d7219b --- /dev/null +++ b/gst/gstqueryutils.h @@ -0,0 +1,39 @@ +/* GStreamer + * Copyright (C) 2005 Andy Wingo + * + * gstqueryutils.c: Utility functions for creating and parsing GstQueries. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + + +#include + + +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, + gint64 segment_end); +void gst_query_parse_seeking_response (GstQuery *query, GstFormat *format, + gboolean *seekable, + gint64 *segment_start, + gint64 *segment_end); +void gst_query_set_formats (GstQuery *query, gint n_formats, ...); diff --git a/libs/gst/base/gstbasesrc.c b/libs/gst/base/gstbasesrc.c index e9ff0faede..503156870e 100644 --- a/libs/gst/base/gstbasesrc.c +++ b/libs/gst/base/gstbasesrc.c @@ -88,11 +88,10 @@ static void gst_basesrc_set_property (GObject * object, guint prop_id, 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 const GstEventMask *gst_basesrc_get_event_mask (GstPad * pad); -static const GstQueryType *gst_basesrc_get_query_types (GstPad * pad); -static gboolean gst_basesrc_query (GstPad * pad, GstQueryType type, - GstFormat * format, gint64 * value); -static const GstFormat *gst_basesrc_get_formats (GstPad * pad); static gboolean gst_basesrc_unlock (GstBaseSrc * basesrc); static gboolean gst_basesrc_get_size (GstBaseSrc * basesrc, guint64 * size); @@ -160,10 +159,11 @@ 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_query_function (pad, gst_basesrc_query); - gst_pad_set_query_type_function (pad, gst_basesrc_get_query_types); - gst_pad_set_formats_function (pad, gst_basesrc_get_formats); + + gst_pad_set_query2_function (pad, gst_basesrc_query2); + gst_pad_set_checkgetrange_function (pad, gst_basesrc_check_get_range); + /* hold ref to pad */ basesrc->srcpad = pad; gst_element_add_pad (GST_ELEMENT (basesrc), pad); @@ -192,84 +192,59 @@ gst_basesrc_set_dataflow_funcs (GstBaseSrc * this) gst_pad_set_getrange_function (this->srcpad, NULL); } -static const GstFormat * -gst_basesrc_get_formats (GstPad * pad) -{ - static const GstFormat formats[] = { - GST_FORMAT_DEFAULT, - GST_FORMAT_BYTES, - 0, - }; - - return formats; -} - -static const GstQueryType * -gst_basesrc_get_query_types (GstPad * pad) -{ - static const GstQueryType types[] = { - GST_QUERY_TOTAL, - GST_QUERY_POSITION, - GST_QUERY_START, - GST_QUERY_SEGMENT_END, - 0, - }; - - return types; -} - static gboolean -gst_basesrc_query (GstPad * pad, GstQueryType type, - GstFormat * format, gint64 * value) +gst_basesrc_query2 (GstPad * pad, GstQuery * query) { - GstBaseSrc *src = GST_BASESRC (GST_PAD_PARENT (pad)); - - if (*format == GST_FORMAT_DEFAULT) - *format = GST_FORMAT_BYTES; + gboolean b; + guint64 ui64; + gint64 i64; + GstBaseSrc *src; - switch (type) { - case GST_QUERY_TOTAL: - switch (*format) { - case GST_FORMAT_BYTES: - { - gboolean ret; + src = GST_BASESRC (GST_PAD_PARENT (pad)); - ret = gst_basesrc_get_size (src, (guint64 *) value); - GST_DEBUG ("getting length %d %lld", ret, *value); - return ret; - } - case GST_FORMAT_PERCENT: - *value = GST_FORMAT_PERCENT_MAX; - return TRUE; - default: - return FALSE; - } - break; + switch (GST_QUERY_TYPE (query)) { case GST_QUERY_POSITION: - switch (*format) { + { + GstFormat format; + + gst_query_parse_position_query (query, &format); + switch (format) { + case GST_FORMAT_DEFAULT: case GST_FORMAT_BYTES: - *value = src->offset; - break; + b = gst_basesrc_get_size (src, &ui64); + /* better to make get_size take an int64 */ + i64 = b ? (gint64) ui64 : -1; + gst_query_set_position (query, GST_FORMAT_BYTES, src->offset, i64); + return TRUE; case GST_FORMAT_PERCENT: - /* fixme */ - if (!gst_basesrc_get_size (src, (guint64 *) value)) - return FALSE; - *value = src->offset * GST_FORMAT_PERCENT_MAX / *value; + b = gst_basesrc_get_size (src, &ui64); + i64 = GST_FORMAT_PERCENT_MAX; + i64 *= b ? (src->offset / (gdouble) ui64) : 1.0; + gst_query_set_position (query, GST_FORMAT_PERCENT, + i64, GST_FORMAT_PERCENT_MAX); return TRUE; default: return FALSE; } - break; - case GST_QUERY_START: - *value = src->segment_start; + } + + case GST_QUERY_SEEKING: + gst_query_set_seeking (query, GST_FORMAT_BYTES, + src->seekable, src->segment_start, src->segment_end); return TRUE; - case GST_QUERY_SEGMENT_END: - *value = src->segment_end; + + case GST_QUERY_FORMATS: + gst_query_set_formats (query, 3, GST_FORMAT_DEFAULT, + GST_FORMAT_BYTES, GST_FORMAT_PERCENT); return TRUE; + + case GST_QUERY_LATENCY: + case GST_QUERY_JITTER: + case GST_QUERY_RATE: + case GST_QUERY_CONVERT: default: - return FALSE; + return gst_pad_query2_default (pad, query); } - return FALSE; } static const GstEventMask * diff --git a/plugins/elements/gstfilesink.c b/plugins/elements/gstfilesink.c index 162f649dda..c0da0e3632 100644 --- a/plugins/elements/gstfilesink.c +++ b/plugins/elements/gstfilesink.c @@ -66,29 +66,6 @@ enum ARG_LOCATION }; -static const GstFormat * -gst_filesink_get_formats (GstPad * pad) -{ - static const GstFormat formats[] = { - GST_FORMAT_BYTES, - 0, - }; - - return formats; -} - -static const GstQueryType * -gst_filesink_get_query_types (GstPad * pad) -{ - static const GstQueryType types[] = { - GST_QUERY_TOTAL, - GST_QUERY_POSITION, - 0 - }; - - return types; -} - static void gst_filesink_dispose (GObject * object); static void gst_filesink_set_property (GObject * object, guint prop_id, @@ -103,8 +80,7 @@ static gboolean gst_filesink_event (GstBaseSink * sink, GstEvent * event); static GstFlowReturn gst_filesink_render (GstBaseSink * sink, GstBuffer * buffer); -static gboolean gst_filesink_pad_query (GstPad * pad, GstQueryType type, - GstFormat * format, gint64 * value); +static gboolean gst_filesink_query2 (GstPad * pad, GstQuery * query); static void gst_filesink_uri_handler_init (gpointer g_iface, gpointer iface_data); @@ -141,6 +117,7 @@ gst_filesink_base_init (gpointer g_class) gst_static_pad_template_get (&sinktemplate)); gst_element_class_set_details (gstelement_class, &gst_filesink_details); } + static void gst_filesink_class_init (GstFileSinkClass * klass) { @@ -159,6 +136,7 @@ gst_filesink_class_init (GstFileSinkClass * klass) gstbasesink_class->render = GST_DEBUG_FUNCPTR (gst_filesink_render); gstbasesink_class->event = GST_DEBUG_FUNCPTR (gst_filesink_event); } + static void gst_filesink_init (GstFileSink * filesink) { @@ -166,13 +144,12 @@ gst_filesink_init (GstFileSink * filesink) pad = GST_BASESINK_PAD (filesink); - gst_pad_set_query_function (pad, gst_filesink_pad_query); - gst_pad_set_query_type_function (pad, gst_filesink_get_query_types); - gst_pad_set_formats_function (pad, gst_filesink_get_formats); + gst_pad_set_query2_function (pad, gst_filesink_query2); filesink->filename = NULL; filesink->file = NULL; } + static void gst_filesink_dispose (GObject * object) { @@ -278,36 +255,33 @@ gst_filesink_close_file (GstFileSink * sink) } static gboolean -gst_filesink_pad_query (GstPad * pad, GstQueryType type, - GstFormat * format, gint64 * value) +gst_filesink_query2 (GstPad * pad, GstQuery * query) { - GstFileSink *sink = GST_FILESINK (GST_PAD_PARENT (pad)); + GstFileSink *self; + GstFormat format; - switch (type) { - case GST_QUERY_TOTAL: - switch (*format) { - case GST_FORMAT_BYTES: - *value = sink->data_written; /* FIXME - doesn't the kernel provide - such a function? */ - break; - default: - return FALSE; - } - break; + self = GST_FILESINK (GST_PAD_PARENT (pad)); + + switch (GST_QUERY_TYPE (query)) { case GST_QUERY_POSITION: - switch (*format) { + gst_query_parse_position_query (query, &format); + switch (format) { + case GST_FORMAT_DEFAULT: case GST_FORMAT_BYTES: - *value = ftell (sink->file); - break; + gst_query_set_position (query, GST_FORMAT_BYTES, + self->data_written, self->data_written); + return TRUE; default: return FALSE; } - break; + + case GST_QUERY_FORMATS: + gst_query_set_formats (query, 2, GST_FORMAT_DEFAULT, GST_FORMAT_BYTES); + return TRUE; + default: - return FALSE; + return gst_pad_query2_default (pad, query); } - - return TRUE; } /* handle events (search) */ -- 2.34.1