X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=gst%2Fgstquery.c;h=076b8dca9cdba7c12a74850c6e1dccdc68123876;hb=e10266e3f3cf9b05b69198b1ac6faa9a62840e30;hp=53b4cf9571ea01149305fc9c6e641826acbac07b;hpb=105330784c357df741152b0d10e466216bf359e4;p=platform%2Fupstream%2Fgstreamer.git diff --git a/gst/gstquery.c b/gst/gstquery.c index 53b4cf9..076b8dc 100644 --- a/gst/gstquery.c +++ b/gst/gstquery.c @@ -17,18 +17,16 @@ * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. */ /** * SECTION:gstquery - * @short_description: Dynamically register new query types. Provide functions - * to create queries, and to set and parse values in them. + * @short_description: Provide functions to create queries, and to set and parse + * values in them. * @see_also: #GstPad, #GstElement * - * GstQuery functions are used to register new query types to the gstreamer - * core and use them. * Queries can be performed on pads (gst_pad_query()) and elements * (gst_element_query()). Please note that some queries might need a running * pipeline to work. @@ -38,33 +36,22 @@ * gst_query_parse_*() helpers. * * The following example shows how to query the duration of a pipeline: - * - * - * Query duration on a pipeline - * - * GstQuery *query; - * gboolean res; - * query = gst_query_new_duration (GST_FORMAT_TIME); - * res = gst_element_query (pipeline, query); - * if (res) { - * gint64 duration; - * gst_query_parse_duration (query, NULL, &duration); - * g_print ("duration = %"GST_TIME_FORMAT, GST_TIME_ARGS (duration)); - * } - * else { - * g_print ("duration query failed..."); - * } - * gst_query_unref (query); - * - * - * - * Last reviewed on 2006-02-14 (0.10.4) - */ - - -/* FIXME 0.11: suppress warnings for deprecated API such as GValueArray - * with newer GLib versions (>= 2.31.0) */ -#define GLIB_DISABLE_DEPRECATION_WARNINGS + * |[ + * GstQuery *query; + * gboolean res; + * query = gst_query_new_duration (GST_FORMAT_TIME); + * res = gst_element_query (pipeline, query); + * if (res) { + * gint64 duration; + * gst_query_parse_duration (query, NULL, &duration); + * g_print ("duration = %"GST_TIME_FORMAT, GST_TIME_ARGS (duration)); + * } else { + * g_print ("duration query failed..."); + * } + * gst_query_unref (query); + * ]| + */ + #include "gst_private.h" #include "gstinfo.h" @@ -73,312 +60,157 @@ #include "gstenumtypes.h" #include "gstquark.h" #include "gsturi.h" +#include "gstbufferpool.h" GST_DEBUG_CATEGORY_STATIC (gst_query_debug); #define GST_CAT_DEFAULT gst_query_debug -static void gst_query_finalize (GstQuery * query); -static GstQuery *_gst_query_copy (GstQuery * query); - -static GStaticMutex mutex = G_STATIC_MUTEX_INIT; -static GList *_gst_queries = NULL; -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 GstMiniObjectClass *parent_class = NULL; - -static GstQueryTypeDefinition standard_definitions[] = { - {GST_QUERY_POSITION, "position", "Current position", 0}, - {GST_QUERY_DURATION, "duration", "Total duration", 0}, - {GST_QUERY_LATENCY, "latency", "Latency", 0}, - {GST_QUERY_JITTER, "jitter", "Jitter", 0}, - {GST_QUERY_RATE, "rate", "Configured rate 1000000 = 1", 0}, - {GST_QUERY_SEEKING, "seeking", "Seeking capabilities and parameters", 0}, - {GST_QUERY_SEGMENT, "segment", "currently configured segment", 0}, - {GST_QUERY_CONVERT, "convert", "Converting between formats", 0}, - {GST_QUERY_FORMATS, "formats", "Supported formats for conversion", 0}, - {GST_QUERY_BUFFERING, "buffering", "Buffering status", 0}, - {GST_QUERY_CUSTOM, "custom", "Custom query", 0}, - {GST_QUERY_URI, "uri", "URI of the source or sink", 0}, - {GST_QUERY_TOC, "toc", "Full table of contents", 0}, - {GST_QUERY_NONE, NULL, NULL, 0} +static GType _gst_query_type = 0; + +typedef struct +{ + GstQuery query; + + GstStructure *structure; +} GstQueryImpl; + +#define GST_QUERY_STRUCTURE(q) (((GstQueryImpl *)(q))->structure) + + +typedef struct +{ + const gint type; + const gchar *name; + GQuark quark; +} GstQueryQuarks; + +static GstQueryQuarks query_quarks[] = { + {GST_QUERY_UNKNOWN, "unknown", 0}, + {GST_QUERY_POSITION, "position", 0}, + {GST_QUERY_DURATION, "duration", 0}, + {GST_QUERY_LATENCY, "latency", 0}, + {GST_QUERY_JITTER, "jitter", 0}, + {GST_QUERY_RATE, "rate", 0}, + {GST_QUERY_SEEKING, "seeking", 0}, + {GST_QUERY_SEGMENT, "segment", 0}, + {GST_QUERY_CONVERT, "convert", 0}, + {GST_QUERY_FORMATS, "formats", 0}, + {GST_QUERY_BUFFERING, "buffering", 0}, + {GST_QUERY_CUSTOM, "custom", 0}, + {GST_QUERY_URI, "uri", 0}, + {GST_QUERY_ALLOCATION, "allocation", 0}, + {GST_QUERY_SCHEDULING, "scheduling", 0}, + {GST_QUERY_ACCEPT_CAPS, "accept-caps", 0}, + {GST_QUERY_CAPS, "caps", 0}, + {GST_QUERY_DRAIN, "drain", 0}, + {GST_QUERY_CONTEXT, "context", 0}, + + {0, NULL, 0} }; +GST_DEFINE_MINI_OBJECT_TYPE (GstQuery, gst_query); + void -_gst_query_initialize (void) +_priv_gst_query_initialize (void) { - GstQueryTypeDefinition *standards = standard_definitions; + gint i; - GST_CAT_INFO (GST_CAT_GST_INIT, "init queries"); + _gst_query_type = gst_query_get_type (); 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); - _query_type_to_nick = g_hash_table_new (NULL, NULL); - } - - while (standards->nick) { - standards->quark = g_quark_from_static_string (standards->nick); - g_hash_table_insert (_nick_to_query, (gpointer) standards->nick, standards); - g_hash_table_insert (_query_type_to_nick, - GINT_TO_POINTER (standards->value), standards); - - _gst_queries = g_list_append (_gst_queries, standards); - standards++; - _n_values++; + for (i = 0; query_quarks[i].name; i++) { + query_quarks[i].quark = g_quark_from_static_string (query_quarks[i].name); } - g_static_mutex_unlock (&mutex); - - g_type_class_ref (gst_query_get_type ()); } /** * gst_query_type_get_name: - * @query: the query type + * @type: the query type * * Get a printable name for the given query type. Do not modify or free. * * Returns: a reference to the static name of the query. */ const gchar * -gst_query_type_get_name (GstQueryType query) +gst_query_type_get_name (GstQueryType type) { - const GstQueryTypeDefinition *def; - - def = gst_query_type_get_details (query); + gint i; - return def->nick; + for (i = 0; query_quarks[i].name; i++) { + if (type == query_quarks[i].type) + return query_quarks[i].name; + } + return "unknown"; } /** * gst_query_type_to_quark: - * @query: the query type + * @type: the query type * * Get the unique quark for the given query type. * * Returns: the quark associated with the query type */ GQuark -gst_query_type_to_quark (GstQueryType query) -{ - const GstQueryTypeDefinition *def; - - def = gst_query_type_get_details (query); - - return def->quark; -} - -G_DEFINE_TYPE (GstQuery, gst_query, GST_TYPE_MINI_OBJECT); - -static void -gst_query_class_init (GstQueryClass * klass) -{ - parent_class = g_type_class_peek_parent (klass); - - klass->mini_object_class.copy = (GstMiniObjectCopyFunction) _gst_query_copy; - klass->mini_object_class.finalize = - (GstMiniObjectFinalizeFunction) gst_query_finalize; - -} - -static void -gst_query_init (GstQuery * query) -{ -} - -static void -gst_query_finalize (GstQuery * query) -{ - g_return_if_fail (query != NULL); - - if (query->structure) { - gst_structure_set_parent_refcount (query->structure, NULL); - gst_structure_free (query->structure); - } - -/* GST_MINI_OBJECT_CLASS (parent_class)->finalize (GST_MINI_OBJECT (query)); */ -} - -static GstQuery * -_gst_query_copy (GstQuery * query) +gst_query_type_to_quark (GstQueryType type) { - GstQuery *copy; - - copy = (GstQuery *) gst_mini_object_new (GST_TYPE_QUERY); - - copy->type = query->type; + gint i; - if (query->structure) { - copy->structure = gst_structure_copy (query->structure); - gst_structure_set_parent_refcount (copy->structure, - &query->mini_object.refcount); + for (i = 0; query_quarks[i].name; i++) { + if (type == query_quarks[i].type) + return query_quarks[i].quark; } - - return copy; -} - - - -/** - * gst_query_type_register: - * @nick: The nick of the new query - * @description: The description of the new query - * - * Create a new GstQueryType based on the nick or return an - * already registered query with that nick - * - * Returns: A new GstQueryType or an already registered query - * with the same nick. - */ -GstQueryType -gst_query_type_register (const gchar * nick, const gchar * description) -{ - GstQueryTypeDefinition *query; - GstQueryType lookup; - - g_return_val_if_fail (nick != NULL, GST_QUERY_NONE); - g_return_val_if_fail (description != NULL, GST_QUERY_NONE); - - lookup = gst_query_type_get_by_nick (nick); - if (lookup != GST_QUERY_NONE) - return lookup; - - query = g_slice_new (GstQueryTypeDefinition); - query->value = (GstQueryType) _n_values; - query->nick = g_strdup (nick); - query->description = g_strdup (description); - query->quark = g_quark_from_static_string (query->nick); - - g_static_mutex_lock (&mutex); - g_hash_table_insert (_nick_to_query, (gpointer) query->nick, query); - g_hash_table_insert (_query_type_to_nick, GINT_TO_POINTER (query->value), - query); - _gst_queries = g_list_append (_gst_queries, query); - _n_values++; - g_static_mutex_unlock (&mutex); - - return query->value; + return 0; } /** - * gst_query_type_get_by_nick: - * @nick: The nick of the query + * gst_query_type_get_flags: + * @type: a #GstQueryType * - * Get the query type registered with @nick. + * Gets the #GstQueryTypeFlags associated with @type. * - * Returns: The query registered with @nick or #GST_QUERY_NONE - * if the query was not registered. + * Returns: a #GstQueryTypeFlags. */ -GstQueryType -gst_query_type_get_by_nick (const gchar * nick) +GstQueryTypeFlags +gst_query_type_get_flags (GstQueryType type) { - GstQueryTypeDefinition *query; - - g_return_val_if_fail (nick != NULL, GST_QUERY_NONE); + GstQueryTypeFlags ret; - g_static_mutex_lock (&mutex); - query = g_hash_table_lookup (_nick_to_query, nick); - g_static_mutex_unlock (&mutex); + ret = type & ((1 << GST_QUERY_NUM_SHIFT) - 1); - if (query != NULL) - return query->value; - else - return GST_QUERY_NONE; + return ret; } -/** - * gst_query_types_contains: - * @types: The query array to search - * @type: the #GstQueryType to find - * - * See if the given #GstQueryType is inside the @types query types array. - * - * Returns: TRUE if the type is found inside the array - */ -gboolean -gst_query_types_contains (const GstQueryType * types, GstQueryType type) +static void +_gst_query_free (GstQuery * query) { - if (!types) - return FALSE; + GstStructure *s; - while (*types) { - if (*types == type) - return TRUE; + g_return_if_fail (query != NULL); - types++; + s = GST_QUERY_STRUCTURE (query); + if (s) { + gst_structure_set_parent_refcount (s, NULL); + gst_structure_free (s); } - return FALSE; -} - - -/** - * gst_query_type_get_details: - * @type: a #GstQueryType - * - * Get details about the given #GstQueryType. - * - * Returns: The #GstQueryTypeDefinition for @type or NULL on failure. - */ -const GstQueryTypeDefinition * -gst_query_type_get_details (GstQueryType type) -{ - const GstQueryTypeDefinition *result; - - g_static_mutex_lock (&mutex); - result = g_hash_table_lookup (_query_type_to_nick, GINT_TO_POINTER (type)); - g_static_mutex_unlock (&mutex); - - return result; -} - -/** - * gst_query_type_iterate_definitions: - * - * Get a #GstIterator of all the registered query types. The definitions - * iterated over are read only. - * - * Free-function: gst_iterator_free - * - * Returns: (transfer full): a #GstIterator of #GstQueryTypeDefinition. - */ -GstIterator * -gst_query_type_iterate_definitions (void) -{ - GstIterator *result; - - g_static_mutex_lock (&mutex); - /* FIXME: register a boxed type for GstQueryTypeDefinition */ - result = gst_iterator_new_list (G_TYPE_POINTER, - g_static_mutex_get_mutex (&mutex), &_n_values, &_gst_queries, - NULL, NULL, NULL); - g_static_mutex_unlock (&mutex); - return result; + g_slice_free1 (sizeof (GstQueryImpl), query); } static GstQuery * -gst_query_new (GstQueryType type, GstStructure * structure) +_gst_query_copy (GstQuery * query) { - GstQuery *query; - - query = (GstQuery *) gst_mini_object_new (GST_TYPE_QUERY); - - GST_DEBUG ("creating new query %p %s", query, gst_query_type_get_name (type)); - - query->type = type; + GstQuery *copy; + GstStructure *s; - if (structure) { - query->structure = structure; - gst_structure_set_parent_refcount (query->structure, - &query->mini_object.refcount); - } else { - query->structure = NULL; + s = GST_QUERY_STRUCTURE (query); + if (s) { + s = gst_structure_copy (s); } + copy = gst_query_new_custom (query->type, s); - return query; + return copy; } /** @@ -399,11 +231,11 @@ gst_query_new_position (GstFormat format) GstQuery *query; GstStructure *structure; - structure = gst_structure_id_new (GST_QUARK (QUERY_POSITION), + structure = gst_structure_new_id (GST_QUARK (QUERY_POSITION), GST_QUARK (FORMAT), GST_TYPE_FORMAT, format, GST_QUARK (CURRENT), G_TYPE_INT64, G_GINT64_CONSTANT (-1), NULL); - query = gst_query_new (GST_QUERY_POSITION, structure); + query = gst_query_new_custom (GST_QUERY_POSITION, structure); return query; } @@ -419,9 +251,15 @@ gst_query_new_position (GstFormat format) void gst_query_set_position (GstQuery * query, GstFormat format, gint64 cur) { + GstStructure *s; + g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_POSITION); - gst_structure_id_set (query->structure, + s = GST_QUERY_STRUCTURE (query); + g_return_if_fail (format == g_value_get_enum (gst_structure_id_get_value (s, + GST_QUARK (FORMAT)))); + + gst_structure_id_set (s, GST_QUARK (FORMAT), GST_TYPE_FORMAT, format, GST_QUARK (CURRENT), G_TYPE_INT64, cur, NULL); } @@ -430,11 +268,11 @@ gst_query_set_position (GstQuery * query, GstFormat format, gint64 cur) * gst_query_parse_position: * @query: a #GstQuery * @format: (out) (allow-none): the storage for the #GstFormat of the - * position values (may be NULL) - * @cur: (out) (allow-none): the storage for the current position (may be NULL) + * position values (may be %NULL) + * @cur: (out) (allow-none): the storage for the current position (may be %NULL) * * Parse a position query, writing the format into @format, and the position - * into @cur, if the respective parameters are non-NULL. + * into @cur, if the respective parameters are non-%NULL. */ void gst_query_parse_position (GstQuery * query, GstFormat * format, gint64 * cur) @@ -443,7 +281,7 @@ gst_query_parse_position (GstQuery * query, GstFormat * format, gint64 * cur) g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_POSITION); - structure = query->structure; + structure = GST_QUERY_STRUCTURE (query); if (format) *format = (GstFormat) g_value_get_enum (gst_structure_id_get_value (structure, @@ -472,11 +310,11 @@ gst_query_new_duration (GstFormat format) GstQuery *query; GstStructure *structure; - structure = gst_structure_id_new (GST_QUARK (QUERY_DURATION), + structure = gst_structure_new_id (GST_QUARK (QUERY_DURATION), GST_QUARK (FORMAT), GST_TYPE_FORMAT, format, GST_QUARK (DURATION), G_TYPE_INT64, G_GINT64_CONSTANT (-1), NULL); - query = gst_query_new (GST_QUERY_DURATION, structure); + query = gst_query_new_custom (GST_QUERY_DURATION, structure); return query; } @@ -492,10 +330,14 @@ gst_query_new_duration (GstFormat format) void gst_query_set_duration (GstQuery * query, GstFormat format, gint64 duration) { + GstStructure *s; + g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_DURATION); - gst_structure_id_set (query->structure, - GST_QUARK (FORMAT), GST_TYPE_FORMAT, format, + s = GST_QUERY_STRUCTURE (query); + g_return_if_fail (format == g_value_get_enum (gst_structure_id_get_value (s, + GST_QUARK (FORMAT)))); + gst_structure_id_set (s, GST_QUARK (FORMAT), GST_TYPE_FORMAT, format, GST_QUARK (DURATION), G_TYPE_INT64, duration, NULL); } @@ -503,11 +345,11 @@ gst_query_set_duration (GstQuery * query, GstFormat format, gint64 duration) * gst_query_parse_duration: * @query: a #GstQuery * @format: (out) (allow-none): the storage for the #GstFormat of the duration - * value, or NULL. - * @duration: (out) (allow-none): the storage for the total duration, or NULL. + * value, or %NULL. + * @duration: (out) (allow-none): the storage for the total duration, or %NULL. * * Parse a duration query answer. Write the format of the duration into @format, - * and the value into @duration, if the respective variables are non-NULL. + * and the value into @duration, if the respective variables are non-%NULL. */ void gst_query_parse_duration (GstQuery * query, GstFormat * format, @@ -517,7 +359,7 @@ gst_query_parse_duration (GstQuery * query, GstFormat * format, g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_DURATION); - structure = query->structure; + structure = GST_QUERY_STRUCTURE (query); if (format) *format = (GstFormat) g_value_get_enum (gst_structure_id_get_value (structure, @@ -538,8 +380,6 @@ gst_query_parse_duration (GstQuery * query, GstFormat * format, * Free-function: gst_query_unref * * Returns: (transfer full): a #GstQuery - * - * Since: 0.10.12 */ GstQuery * gst_query_new_latency (void) @@ -547,12 +387,12 @@ gst_query_new_latency (void) GstQuery *query; GstStructure *structure; - structure = gst_structure_id_new (GST_QUARK (QUERY_LATENCY), + structure = gst_structure_new_id (GST_QUARK (QUERY_LATENCY), GST_QUARK (LIVE), G_TYPE_BOOLEAN, FALSE, GST_QUARK (MIN_LATENCY), G_TYPE_UINT64, G_GUINT64_CONSTANT (0), GST_QUARK (MAX_LATENCY), G_TYPE_UINT64, G_GUINT64_CONSTANT (-1), NULL); - query = gst_query_new (GST_QUERY_LATENCY, structure); + query = gst_query_new_custom (GST_QUERY_LATENCY, structure); return query; } @@ -561,20 +401,21 @@ gst_query_new_latency (void) * gst_query_set_latency: * @query: a #GstQuery * @live: if there is a live element upstream - * @min_latency: the minimal latency of the live element - * @max_latency: the maximal latency of the live element + * @min_latency: the minimal latency of the upstream elements + * @max_latency: the maximal latency of the upstream elements * * Answer a latency query by setting the requested values in the given format. - * - * Since: 0.10.12 */ void gst_query_set_latency (GstQuery * query, gboolean live, GstClockTime min_latency, GstClockTime max_latency) { + GstStructure *structure; + g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_LATENCY); - gst_structure_id_set (query->structure, + structure = GST_QUERY_STRUCTURE (query); + gst_structure_id_set (structure, GST_QUARK (LIVE), G_TYPE_BOOLEAN, live, GST_QUARK (MIN_LATENCY), G_TYPE_UINT64, min_latency, GST_QUARK (MAX_LATENCY), G_TYPE_UINT64, max_latency, NULL); @@ -583,13 +424,11 @@ gst_query_set_latency (GstQuery * query, gboolean live, /** * gst_query_parse_latency: * @query: a #GstQuery - * @live: (out) (allow-none): storage for live or NULL - * @min_latency: (out) (allow-none): the storage for the min latency or NULL - * @max_latency: (out) (allow-none): the storage for the max latency or NULL + * @live: (out) (allow-none): storage for live or %NULL + * @min_latency: (out) (allow-none): the storage for the min latency or %NULL + * @max_latency: (out) (allow-none): the storage for the max latency or %NULL * * Parse a latency query answer. - * - * Since: 0.10.12 */ void gst_query_parse_latency (GstQuery * query, gboolean * live, @@ -599,7 +438,7 @@ gst_query_parse_latency (GstQuery * query, gboolean * live, g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_LATENCY); - structure = query->structure; + structure = GST_QUERY_STRUCTURE (query); if (live) *live = g_value_get_boolean (gst_structure_id_get_value (structure, @@ -633,13 +472,13 @@ gst_query_new_convert (GstFormat src_format, gint64 value, GstQuery *query; GstStructure *structure; - structure = gst_structure_id_new (GST_QUARK (QUERY_CONVERT), + structure = gst_structure_new_id (GST_QUARK (QUERY_CONVERT), GST_QUARK (SRC_FORMAT), GST_TYPE_FORMAT, src_format, GST_QUARK (SRC_VALUE), G_TYPE_INT64, value, GST_QUARK (DEST_FORMAT), GST_TYPE_FORMAT, dest_format, GST_QUARK (DEST_VALUE), G_TYPE_INT64, G_GINT64_CONSTANT (-1), NULL); - query = gst_query_new (GST_QUERY_CONVERT, structure); + query = gst_query_new_custom (GST_QUERY_CONVERT, structure); return query; } @@ -658,9 +497,12 @@ 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); - gst_structure_id_set (query->structure, + structure = GST_QUERY_STRUCTURE (query); + gst_structure_id_set (structure, GST_QUARK (SRC_FORMAT), GST_TYPE_FORMAT, src_format, GST_QUARK (SRC_VALUE), G_TYPE_INT64, src_value, GST_QUARK (DEST_FORMAT), GST_TYPE_FORMAT, dest_format, @@ -671,15 +513,15 @@ gst_query_set_convert (GstQuery * query, GstFormat src_format, gint64 src_value, * gst_query_parse_convert: * @query: a #GstQuery * @src_format: (out) (allow-none): the storage for the #GstFormat of the - * source value, or NULL - * @src_value: (out) (allow-none): the storage for the source value, or NULL + * source value, or %NULL + * @src_value: (out) (allow-none): the storage for the source value, or %NULL * @dest_format: (out) (allow-none): the storage for the #GstFormat of the - * destination value, or NULL + * destination value, or %NULL * @dest_value: (out) (allow-none): the storage for the destination value, - * or NULL + * or %NULL * * Parse a convert query answer. Any of @src_format, @src_value, @dest_format, - * and @dest_value may be NULL, in which case that value is omitted. + * and @dest_value may be %NULL, in which case that value is omitted. */ void gst_query_parse_convert (GstQuery * query, GstFormat * src_format, @@ -689,7 +531,7 @@ gst_query_parse_convert (GstQuery * query, GstFormat * src_format, g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_CONVERT); - structure = query->structure; + structure = GST_QUERY_STRUCTURE (query); if (src_format) *src_format = (GstFormat) g_value_get_enum (gst_structure_id_get_value (structure, @@ -724,13 +566,13 @@ gst_query_new_segment (GstFormat format) GstQuery *query; GstStructure *structure; - structure = gst_structure_id_new (GST_QUARK (QUERY_SEGMENT), + structure = gst_structure_new_id (GST_QUARK (QUERY_SEGMENT), GST_QUARK (RATE), G_TYPE_DOUBLE, (gdouble) 0.0, GST_QUARK (FORMAT), GST_TYPE_FORMAT, format, GST_QUARK (START_VALUE), G_TYPE_INT64, G_GINT64_CONSTANT (-1), GST_QUARK (STOP_VALUE), G_TYPE_INT64, G_GINT64_CONSTANT (-1), NULL); - query = gst_query_new (GST_QUERY_SEGMENT, structure); + query = gst_query_new_custom (GST_QUERY_SEGMENT, structure); return query; } @@ -759,9 +601,12 @@ void gst_query_set_segment (GstQuery * query, gdouble rate, GstFormat format, gint64 start_value, gint64 stop_value) { + GstStructure *structure; + g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_SEGMENT); - gst_structure_id_set (query->structure, + structure = GST_QUERY_STRUCTURE (query); + gst_structure_id_set (structure, GST_QUARK (RATE), G_TYPE_DOUBLE, rate, GST_QUARK (FORMAT), GST_TYPE_FORMAT, format, GST_QUARK (START_VALUE), G_TYPE_INT64, start_value, @@ -771,14 +616,14 @@ gst_query_set_segment (GstQuery * query, gdouble rate, GstFormat format, /** * gst_query_parse_segment: * @query: a #GstQuery - * @rate: (out) (allow-none): the storage for the rate of the segment, or NULL + * @rate: (out) (allow-none): the storage for the rate of the segment, or %NULL * @format: (out) (allow-none): the storage for the #GstFormat of the values, - * or NULL - * @start_value: (out) (allow-none): the storage for the start value, or NULL - * @stop_value: (out) (allow-none): the storage for the stop value, or NULL + * or %NULL + * @start_value: (out) (allow-none): the storage for the start value, or %NULL + * @stop_value: (out) (allow-none): the storage for the stop value, or %NULL * * Parse a segment query answer. Any of @rate, @format, @start_value, and - * @stop_value may be NULL, which will cause this value to be omitted. + * @stop_value may be %NULL, which will cause this value to be omitted. * * See gst_query_set_segment() for an explanation of the function arguments. */ @@ -790,7 +635,7 @@ gst_query_parse_segment (GstQuery * query, gdouble * rate, GstFormat * format, g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_SEGMENT); - structure = query->structure; + structure = GST_QUERY_STRUCTURE (query); if (rate) *rate = g_value_get_double (gst_structure_id_get_value (structure, GST_QUARK (RATE))); @@ -807,11 +652,11 @@ gst_query_parse_segment (GstQuery * query, gdouble * rate, GstFormat * format, } /** - * gst_query_new_application: + * gst_query_new_custom: * @type: the query type - * @structure: a structure for the query + * @structure: (allow-none) (transfer full): a structure for the query * - * Constructs a new custom application query object. Use gst_query_unref() + * Constructs a new custom query object. Use gst_query_unref() * when done with it. * * Free-function: gst_query_unref @@ -819,12 +664,37 @@ gst_query_parse_segment (GstQuery * query, gdouble * rate, GstFormat * format, * Returns: (transfer full): a new #GstQuery */ GstQuery * -gst_query_new_application (GstQueryType type, GstStructure * structure) +gst_query_new_custom (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); + GstQueryImpl *query; + + query = g_slice_new0 (GstQueryImpl); + + GST_DEBUG ("creating new query %p %s", query, gst_query_type_get_name (type)); + + if (structure) { + /* structure must not have a parent */ + if (!gst_structure_set_parent_refcount (structure, + &query->query.mini_object.refcount)) + goto had_parent; + } - return gst_query_new (type, structure); + gst_mini_object_init (GST_MINI_OBJECT_CAST (query), 0, _gst_query_type, + (GstMiniObjectCopyFunction) _gst_query_copy, NULL, + (GstMiniObjectFreeFunction) _gst_query_free); + + GST_QUERY_TYPE (query) = type; + GST_QUERY_STRUCTURE (query) = structure; + + return GST_QUERY_CAST (query); + + /* ERRORS */ +had_parent: + { + g_slice_free1 (sizeof (GstQueryImpl), query); + g_warning ("structure is already owned by another object"); + return NULL; + } } /** @@ -837,12 +707,32 @@ gst_query_new_application (GstQueryType type, GstStructure * structure) * still owned by the query and will therefore be freed when the query * is unreffed. */ -GstStructure * +const GstStructure * gst_query_get_structure (GstQuery * query) { g_return_val_if_fail (GST_IS_QUERY (query), NULL); - return query->structure; + return GST_QUERY_STRUCTURE (query); +} + +/** + * gst_query_writable_structure: + * @query: a #GstQuery + * + * Get the structure of a query. This method should be called with a writable + * @query so that the returned structure is guaranteed to be writable. + * + * Returns: (transfer none): the #GstStructure of the query. The structure is + * still owned by the query and will therefore be freed when the query + * is unreffed. + */ +GstStructure * +gst_query_writable_structure (GstQuery * query) +{ + g_return_val_if_fail (GST_IS_QUERY (query), NULL); + g_return_val_if_fail (gst_query_is_writable (query), NULL); + + return GST_QUERY_STRUCTURE (query); } /** @@ -862,13 +752,13 @@ gst_query_new_seeking (GstFormat format) GstQuery *query; GstStructure *structure; - structure = gst_structure_id_new (GST_QUARK (QUERY_SEEKING), + structure = gst_structure_new_id (GST_QUARK (QUERY_SEEKING), GST_QUARK (FORMAT), GST_TYPE_FORMAT, format, GST_QUARK (SEEKABLE), G_TYPE_BOOLEAN, FALSE, GST_QUARK (SEGMENT_START), G_TYPE_INT64, G_GINT64_CONSTANT (-1), GST_QUARK (SEGMENT_END), G_TYPE_INT64, G_GINT64_CONSTANT (-1), NULL); - query = gst_query_new (GST_QUERY_SEEKING, structure); + query = gst_query_new_custom (GST_QUERY_SEEKING, structure); return query; } @@ -887,9 +777,13 @@ 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); + g_return_if_fail (gst_query_is_writable (query)); - gst_structure_id_set (query->structure, + structure = GST_QUERY_STRUCTURE (query); + gst_structure_id_set (structure, GST_QUARK (FORMAT), GST_TYPE_FORMAT, format, GST_QUARK (SEEKABLE), G_TYPE_BOOLEAN, seekable, GST_QUARK (SEGMENT_START), G_TYPE_INT64, segment_start, @@ -900,14 +794,14 @@ gst_query_set_seeking (GstQuery * query, GstFormat format, * gst_query_parse_seeking: * @query: a GST_QUERY_SEEKING type query #GstQuery * @format: (out) (allow-none): the format to set for the @segment_start - * and @segment_end values, or NULL - * @seekable: (out) (allow-none): the seekable flag to set, or NULL - * @segment_start: (out) (allow-none): the segment_start to set, or NULL - * @segment_end: (out) (allow-none): the segment_end to set, or NULL + * and @segment_end values, or %NULL + * @seekable: (out) (allow-none): the seekable flag to set, or %NULL + * @segment_start: (out) (allow-none): the segment_start to set, or %NULL + * @segment_end: (out) (allow-none): the segment_end to set, or %NULL * * Parse a seeking query, writing the format into @format, and * other results into the passed parameters, if the respective parameters - * are non-NULL + * are non-%NULL */ void gst_query_parse_seeking (GstQuery * query, GstFormat * format, @@ -917,7 +811,7 @@ gst_query_parse_seeking (GstQuery * query, GstFormat * format, g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_SEEKING); - structure = query->structure; + structure = GST_QUERY_STRUCTURE (query); if (format) *format = (GstFormat) g_value_get_enum (gst_structure_id_get_value (structure, @@ -933,6 +827,31 @@ gst_query_parse_seeking (GstQuery * query, GstFormat * format, GST_QUARK (SEGMENT_END))); } +static GArray * +ensure_array (GstStructure * s, GQuark quark, gsize element_size, + GDestroyNotify clear_func) +{ + GArray *array; + const GValue *value; + + value = gst_structure_id_get_value (s, quark); + if (value) { + array = (GArray *) g_value_get_boxed (value); + } else { + GValue new_array_val = { 0, }; + + array = g_array_new (FALSE, TRUE, element_size); + if (clear_func) + g_array_set_clear_func (array, clear_func); + + g_value_init (&new_array_val, G_TYPE_ARRAY); + g_value_take_boxed (&new_array_val, array); + + gst_structure_id_take_value (s, quark, &new_array_val); + } + return array; +} + /** * gst_query_new_formats: * @@ -942,8 +861,6 @@ gst_query_parse_seeking (GstQuery * query, GstFormat * format, * Free-function: gst_query_unref * * Returns: (transfer full): a new #GstQuery - * - * Since: 0.10.4 */ GstQuery * gst_query_new_formats (void) @@ -951,8 +868,8 @@ gst_query_new_formats (void) GstQuery *query; GstStructure *structure; - structure = gst_structure_id_empty_new (GST_QUARK (QUERY_FORMATS)); - query = gst_query_new (GST_QUERY_FORMATS, structure); + structure = gst_structure_new_id_empty (GST_QUARK (QUERY_FORMATS)); + query = gst_query_new_custom (GST_QUERY_FORMATS, structure); return query; } @@ -983,8 +900,10 @@ gst_query_set_formats (GstQuery * query, gint n_formats, ...) va_list ap; GValue list = { 0, }; gint i; + GstStructure *structure; g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_FORMATS); + g_return_if_fail (gst_query_is_writable (query)); g_value_init (&list, GST_TYPE_LIST); @@ -994,7 +913,8 @@ gst_query_set_formats (GstQuery * query, gint n_formats, ...) } va_end (ap); - gst_structure_set_value (query->structure, "formats", &list); + structure = GST_QUERY_STRUCTURE (query); + gst_structure_set_value (structure, "formats", &list); g_value_unset (&list); @@ -1009,8 +929,6 @@ gst_query_set_formats (GstQuery * query, gint n_formats, ...) * * Set the formats query result fields in @query. The number of formats passed * in the @formats array must be equal to @n_formats. - * - * Since: 0.10.4 */ void gst_query_set_formatsv (GstQuery * query, gint n_formats, @@ -1018,36 +936,40 @@ gst_query_set_formatsv (GstQuery * query, gint n_formats, { GValue list = { 0, }; gint i; + GstStructure *structure; g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_FORMATS); + g_return_if_fail (gst_query_is_writable (query)); g_value_init (&list, GST_TYPE_LIST); for (i = 0; i < n_formats; i++) { gst_query_list_add_format (&list, formats[i]); } - gst_structure_set_value (query->structure, "formats", &list); + structure = GST_QUERY_STRUCTURE (query); + gst_structure_set_value (structure, "formats", &list); g_value_unset (&list); } /** - * gst_query_parse_formats_length: + * gst_query_parse_n_formats: * @query: a #GstQuery - * @n_formats: (out): the number of formats in this query. + * @n_formats: (out) (allow-none): the number of formats in this query. * * Parse the number of formats in the formats @query. - * - * Since: 0.10.4 */ void -gst_query_parse_formats_length (GstQuery * query, guint * n_formats) +gst_query_parse_n_formats (GstQuery * query, guint * n_formats) { + GstStructure *structure; + g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_FORMATS); if (n_formats) { const GValue *list; - list = gst_structure_get_value (query->structure, "formats"); + structure = GST_QUERY_STRUCTURE (query); + list = gst_structure_get_value (structure, "formats"); if (list == NULL) *n_formats = 0; else @@ -1056,26 +978,27 @@ gst_query_parse_formats_length (GstQuery * query, guint * n_formats) } /** - * gst_query_parse_formats_nth: + * gst_query_parse_nth_format: * @query: a #GstQuery * @nth: (out): the nth format to retrieve. - * @format: (out): a pointer to store the nth format + * @format: (out) (allow-none): a pointer to store the nth format * * Parse the format query and retrieve the @nth format from it into * @format. If the list contains less elements than @nth, @format will be * set to GST_FORMAT_UNDEFINED. - * - * Since: 0.10.4 */ void -gst_query_parse_formats_nth (GstQuery * query, guint nth, GstFormat * format) +gst_query_parse_nth_format (GstQuery * query, guint nth, GstFormat * format) { + GstStructure *structure; + g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_FORMATS); if (format) { const GValue *list; - list = gst_structure_get_value (query->structure, "formats"); + structure = GST_QUERY_STRUCTURE (query); + list = gst_structure_get_value (structure, "formats"); if (list == NULL) { *format = GST_FORMAT_UNDEFINED; } else { @@ -1089,17 +1012,15 @@ gst_query_parse_formats_nth (GstQuery * query, guint nth, GstFormat * format) } /** - * gst_query_new_buffering + * gst_query_new_buffering: * @format: the default #GstFormat for the new query * * Constructs a new query object for querying the buffering status of * a stream. * - * Free-function: gst_query_new + * Free-function: gst_query_unref * * Returns: (transfer full): a new #GstQuery - * - * Since: 0.10.20 */ GstQuery * gst_query_new_buffering (GstFormat format) @@ -1109,7 +1030,7 @@ gst_query_new_buffering (GstFormat format) /* by default, we configure the answer as no buffering with a 100% buffering * progress */ - structure = gst_structure_id_new (GST_QUARK (QUERY_BUFFERING), + structure = gst_structure_new_id (GST_QUARK (QUERY_BUFFERING), GST_QUARK (BUSY), G_TYPE_BOOLEAN, FALSE, GST_QUARK (BUFFER_PERCENT), G_TYPE_INT, 100, GST_QUARK (BUFFERING_MODE), GST_TYPE_BUFFERING_MODE, GST_BUFFERING_STREAM, @@ -1121,55 +1042,58 @@ gst_query_new_buffering (GstFormat format) GST_QUARK (START_VALUE), G_TYPE_INT64, G_GINT64_CONSTANT (-1), GST_QUARK (STOP_VALUE), G_TYPE_INT64, G_GINT64_CONSTANT (-1), NULL); - query = gst_query_new (GST_QUERY_BUFFERING, structure); + query = gst_query_new_custom (GST_QUERY_BUFFERING, structure); return query; } /** - * gst_query_set_buffering_percent + * gst_query_set_buffering_percent: * @query: A valid #GstQuery of type GST_QUERY_BUFFERING. * @busy: if buffering is busy * @percent: a buffering percent * * Set the percentage of buffered data. This is a value between 0 and 100. * The @busy indicator is %TRUE when the buffering is in progress. - * - * Since: 0.10.20 */ void gst_query_set_buffering_percent (GstQuery * query, gboolean busy, gint percent) { + GstStructure *structure; + g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_BUFFERING); + g_return_if_fail (gst_query_is_writable (query)); g_return_if_fail (percent >= 0 && percent <= 100); - gst_structure_id_set (query->structure, + structure = GST_QUERY_STRUCTURE (query); + gst_structure_id_set (structure, GST_QUARK (BUSY), G_TYPE_BOOLEAN, busy, GST_QUARK (BUFFER_PERCENT), G_TYPE_INT, percent, NULL); } /** - * gst_query_parse_buffering_percent + * gst_query_parse_buffering_percent: * @query: A valid #GstQuery of type GST_QUERY_BUFFERING. - * @busy: (out) (allow-none): if buffering is busy, or NULL - * @percent: (out) (allow-none): a buffering percent, or NULL + * @busy: (out) (allow-none): if buffering is busy, or %NULL + * @percent: (out) (allow-none): a buffering percent, or %NULL * * Get the percentage of buffered data. This is a value between 0 and 100. * The @busy indicator is %TRUE when the buffering is in progress. - * - * Since: 0.10.20 */ void gst_query_parse_buffering_percent (GstQuery * query, gboolean * busy, gint * percent) { + GstStructure *structure; + g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_BUFFERING); + structure = GST_QUERY_STRUCTURE (query); if (busy) - *busy = g_value_get_boolean (gst_structure_id_get_value (query->structure, + *busy = g_value_get_boolean (gst_structure_id_get_value (structure, GST_QUARK (BUSY))); if (percent) - *percent = g_value_get_int (gst_structure_id_get_value (query->structure, + *percent = g_value_get_int (gst_structure_id_get_value (structure, GST_QUARK (BUFFER_PERCENT))); } @@ -1179,19 +1103,21 @@ gst_query_parse_buffering_percent (GstQuery * query, gboolean * busy, * @mode: a buffering mode * @avg_in: the average input rate * @avg_out: the average output rate - * @buffering_left: amount of buffering time left + * @buffering_left: amount of buffering time left in milliseconds * * Configures the buffering stats values in @query. - * - * Since: 0.10.20 */ void gst_query_set_buffering_stats (GstQuery * query, GstBufferingMode mode, gint avg_in, gint avg_out, gint64 buffering_left) { + GstStructure *structure; + g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_BUFFERING); + g_return_if_fail (gst_query_is_writable (query)); - gst_structure_id_set (query->structure, + structure = GST_QUERY_STRUCTURE (query); + gst_structure_id_set (structure, GST_QUARK (BUFFERING_MODE), GST_TYPE_BUFFERING_MODE, mode, GST_QUARK (AVG_IN_RATE), G_TYPE_INT, avg_in, GST_QUARK (AVG_OUT_RATE), G_TYPE_INT, avg_out, @@ -1201,58 +1127,62 @@ gst_query_set_buffering_stats (GstQuery * query, GstBufferingMode mode, /** * gst_query_parse_buffering_stats: * @query: A valid #GstQuery of type GST_QUERY_BUFFERING. - * @mode: (out) (allow-none): a buffering mode, or NULL - * @avg_in: (out) (allow-none): the average input rate, or NULL - * @avg_out: (out) (allow-none): the average output rat, or NULLe - * @buffering_left: (out) (allow-none): amount of buffering time left, or NULL + * @mode: (out) (allow-none): a buffering mode, or %NULL + * @avg_in: (out) (allow-none): the average input rate, or %NULL + * @avg_out: (out) (allow-none): the average output rat, or %NULL + * @buffering_left: (out) (allow-none): amount of buffering time left in + * milliseconds, or %NULL * * Extracts the buffering stats values from @query. - * - * Since: 0.10.20 */ void gst_query_parse_buffering_stats (GstQuery * query, GstBufferingMode * mode, gint * avg_in, gint * avg_out, gint64 * buffering_left) { + GstStructure *structure; + g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_BUFFERING); + structure = GST_QUERY_STRUCTURE (query); if (mode) *mode = (GstBufferingMode) - g_value_get_enum (gst_structure_id_get_value (query->structure, + g_value_get_enum (gst_structure_id_get_value (structure, GST_QUARK (BUFFERING_MODE))); if (avg_in) - *avg_in = g_value_get_int (gst_structure_id_get_value (query->structure, + *avg_in = g_value_get_int (gst_structure_id_get_value (structure, GST_QUARK (AVG_IN_RATE))); if (avg_out) - *avg_out = g_value_get_int (gst_structure_id_get_value (query->structure, + *avg_out = g_value_get_int (gst_structure_id_get_value (structure, GST_QUARK (AVG_OUT_RATE))); if (buffering_left) *buffering_left = - g_value_get_int64 (gst_structure_id_get_value (query->structure, + g_value_get_int64 (gst_structure_id_get_value (structure, GST_QUARK (BUFFERING_LEFT))); } - /** * gst_query_set_buffering_range: * @query: a #GstQuery * @format: the format to set for the @start and @stop values * @start: the start to set * @stop: the stop to set - * @estimated_total: estimated total amount of download time + * @estimated_total: estimated total amount of download time remaining in + * milliseconds * * Set the available query result fields in @query. - * - * Since: 0.10.20 */ void gst_query_set_buffering_range (GstQuery * query, GstFormat format, gint64 start, gint64 stop, gint64 estimated_total) { + GstStructure *structure; + g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_BUFFERING); + g_return_if_fail (gst_query_is_writable (query)); - gst_structure_id_set (query->structure, + structure = GST_QUERY_STRUCTURE (query); + gst_structure_id_set (structure, GST_QUARK (FORMAT), GST_TYPE_FORMAT, format, GST_QUARK (START_VALUE), G_TYPE_INT64, start, GST_QUARK (STOP_VALUE), G_TYPE_INT64, stop, @@ -1263,17 +1193,15 @@ gst_query_set_buffering_range (GstQuery * query, GstFormat format, * gst_query_parse_buffering_range: * @query: a GST_QUERY_BUFFERING type query #GstQuery * @format: (out) (allow-none): the format to set for the @segment_start - * and @segment_end values, or NULL - * @start: (out) (allow-none): the start to set, or NULL - * @stop: (out) (allow-none): the stop to set, or NULL + * and @segment_end values, or %NULL + * @start: (out) (allow-none): the start to set, or %NULL + * @stop: (out) (allow-none): the stop to set, or %NULL * @estimated_total: (out) (allow-none): estimated total amount of download - * time, or NULL + * time remaining in milliseconds, or %NULL * * Parse an available query, writing the format into @format, and * other results into the passed parameters, if the respective parameters - * are non-NULL - * - * Since: 0.10.20 + * are non-%NULL */ void gst_query_parse_buffering_range (GstQuery * query, GstFormat * format, @@ -1283,7 +1211,7 @@ gst_query_parse_buffering_range (GstQuery * query, GstFormat * format, g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_BUFFERING); - structure = query->structure; + structure = GST_QUERY_STRUCTURE (query); if (format) *format = (GstFormat) g_value_get_enum (gst_structure_id_get_value (structure, @@ -1300,8 +1228,15 @@ gst_query_parse_buffering_range (GstQuery * query, GstFormat * format, GST_QUARK (ESTIMATED_TOTAL))); } +/* GstQueryBufferingRange: internal struct for GArray */ +typedef struct +{ + gint64 start; + gint64 stop; +} GstQueryBufferingRange; + /** - * gst_query_add_buffering_range + * gst_query_add_buffering_range: * @query: a GST_QUERY_BUFFERING type query #GstQuery * @start: start position of the range * @stop: stop position of the range @@ -1310,122 +1245,101 @@ gst_query_parse_buffering_range (GstQuery * query, GstFormat * format, * start position of the array should be inferior to @start. * * Returns: a #gboolean indicating if the range was added or not. - * - * Since: 0.10.31 */ gboolean gst_query_add_buffering_range (GstQuery * query, gint64 start, gint64 stop) { - GValueArray *array; - GValue *last_array_value; - const GValue *value; - GValue range_value = { 0 }; + GstQueryBufferingRange range; + GstStructure *structure; + GArray *array; g_return_val_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_BUFFERING, FALSE); + g_return_val_if_fail (gst_query_is_writable (query), FALSE); if (G_UNLIKELY (start >= stop)) return FALSE; - value = - gst_structure_id_get_value (query->structure, - GST_QUARK (BUFFERING_RANGES)); - if (value) { - array = (GValueArray *) g_value_get_boxed (value); - last_array_value = g_value_array_get_nth (array, array->n_values - 1); - if (G_UNLIKELY (start <= gst_value_get_int64_range_min (last_array_value))) - return FALSE; - } else { - GValue new_array_val = { 0, }; + structure = GST_QUERY_STRUCTURE (query); + array = ensure_array (structure, GST_QUARK (BUFFERING_RANGES), + sizeof (GstQueryBufferingRange), NULL); - array = g_value_array_new (0); + if (array->len > 1) { + GstQueryBufferingRange *last; - g_value_init (&new_array_val, G_TYPE_VALUE_ARRAY); - g_value_take_boxed (&new_array_val, array); + last = &g_array_index (array, GstQueryBufferingRange, array->len - 1); - /* set the value array only once, so we then modify (append to) the - * existing value array owned by the GstStructure / the field's GValue */ - gst_structure_id_take_value (query->structure, GST_QUARK (BUFFERING_RANGES), - &new_array_val); + if (G_UNLIKELY (start <= last->start)) + return FALSE; } - g_value_init (&range_value, GST_TYPE_INT64_RANGE); - gst_value_set_int64_range (&range_value, start, stop); - g_value_array_append (array, &range_value); - /* skip the g_value_unset(&range_value) here, we know it's not needed */ + range.start = start; + range.stop = stop; + g_array_append_val (array, range); return TRUE; } /** - * gst_query_get_n_buffering_ranges + * gst_query_get_n_buffering_ranges: * @query: a GST_QUERY_BUFFERING type query #GstQuery * * Retrieve the number of values currently stored in the * buffered-ranges array of the query's structure. * * Returns: the range array size as a #guint. - * - * Since: 0.10.31 */ guint gst_query_get_n_buffering_ranges (GstQuery * query) { - GValueArray *array; - const GValue *value; - guint size = 0; + GstStructure *structure; + GArray *array; g_return_val_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_BUFFERING, 0); - value = - gst_structure_id_get_value (query->structure, - GST_QUARK (BUFFERING_RANGES)); - if (value) { - array = (GValueArray *) g_value_get_boxed (value); - size = array->n_values; - } - return size; + structure = GST_QUERY_STRUCTURE (query); + array = ensure_array (structure, GST_QUARK (BUFFERING_RANGES), + sizeof (GstQueryBufferingRange), NULL); + + return array->len; } /** - * gst_query_parse_nth_buffering_range + * gst_query_parse_nth_buffering_range: * @query: a GST_QUERY_BUFFERING type query #GstQuery * @index: position in the buffered-ranges array to read - * @start: (out) (allow-none): the start position to set, or NULL - * @stop: (out) (allow-none): the stop position to set, or NULL + * @start: (out) (allow-none): the start position to set, or %NULL + * @stop: (out) (allow-none): the stop position to set, or %NULL * * Parse an available query and get the start and stop values stored * at the @index of the buffered ranges array. * * Returns: a #gboolean indicating if the parsing succeeded. - * - * Since: 0.10.31 */ gboolean gst_query_parse_nth_buffering_range (GstQuery * query, guint index, gint64 * start, gint64 * stop) { - const GValue *value; - GValueArray *ranges; - GValue *range_value; - gboolean ret = FALSE; - - g_return_val_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_BUFFERING, ret); - - value = - gst_structure_id_get_value (query->structure, - GST_QUARK (BUFFERING_RANGES)); - ranges = (GValueArray *) g_value_get_boxed (value); - range_value = g_value_array_get_nth (ranges, index); - if (range_value) { - if (start) - *start = gst_value_get_int64_range_min (range_value); - if (stop) - *stop = gst_value_get_int64_range_max (range_value); - ret = TRUE; - } + GstQueryBufferingRange *range; + GstStructure *structure; + GArray *array; - return ret; + g_return_val_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_BUFFERING, FALSE); + + structure = GST_QUERY_STRUCTURE (query); + + array = ensure_array (structure, GST_QUARK (BUFFERING_RANGES), + sizeof (GstQueryBufferingRange), NULL); + g_return_val_if_fail (index < array->len, FALSE); + + range = &g_array_index (array, GstQueryBufferingRange, index); + + if (start) + *start = range->start; + if (stop) + *stop = range->stop; + + return TRUE; } @@ -1439,8 +1353,6 @@ gst_query_parse_nth_buffering_range (GstQuery * query, guint index, * Free-function: gst_query_unref * * Returns: (transfer full): a new #GstQuery - * - * Since: 0.10.22 */ GstQuery * gst_query_new_uri (void) @@ -1448,10 +1360,10 @@ gst_query_new_uri (void) GstQuery *query; GstStructure *structure; - structure = gst_structure_id_new (GST_QUARK (QUERY_URI), + structure = gst_structure_new_id (GST_QUARK (QUERY_URI), GST_QUARK (URI), G_TYPE_STRING, NULL, NULL); - query = gst_query_new (GST_QUERY_URI, structure); + query = gst_query_new_custom (GST_QUERY_URI, structure); return query; } @@ -1462,128 +1374,1270 @@ gst_query_new_uri (void) * @uri: the URI to set * * Answer a URI query by setting the requested URI. - * - * Since: 0.10.22 */ void gst_query_set_uri (GstQuery * query, const gchar * uri) { + GstStructure *structure; + g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_URI); + g_return_if_fail (gst_query_is_writable (query)); g_return_if_fail (gst_uri_is_valid (uri)); - gst_structure_id_set (query->structure, GST_QUARK (URI), G_TYPE_STRING, uri, - NULL); + structure = GST_QUERY_STRUCTURE (query); + gst_structure_id_set (structure, GST_QUARK (URI), G_TYPE_STRING, uri, NULL); } /** * gst_query_parse_uri: * @query: a #GstQuery - * @uri: (out callee-allocates) (allow-none): the storage for the current URI - * (may be NULL) + * @uri: (out) (transfer full) (allow-none): the storage for the current URI + * (may be %NULL) * * Parse an URI query, writing the URI into @uri as a newly - * allocated string, if the respective parameters are non-NULL. + * allocated string, if the respective parameters are non-%NULL. * Free the string with g_free() after usage. - * - * Since: 0.10.22 */ void gst_query_parse_uri (GstQuery * query, gchar ** uri) { + GstStructure *structure; + g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_URI); + structure = GST_QUERY_STRUCTURE (query); if (uri) - *uri = g_value_dup_string (gst_structure_id_get_value (query->structure, + *uri = g_value_dup_string (gst_structure_id_get_value (structure, GST_QUARK (URI))); } /** - * gst_query_new_toc: - * - * Constructs a new query TOC query object. Use gst_query_unref() - * when done with it. A TOC query is used to query the full TOC with - * the UID marker for TOC extending (to insert some new entries). + * gst_query_set_uri_redirection: + * @query: a #GstQuery with query type GST_QUERY_URI + * @uri: the URI to set * - * Returns: A #GstQuery. + * Answer a URI query by setting the requested URI redirection. * - * Since: 0.10.37 + * Since: 1.2 */ -GstQuery * -gst_query_new_toc (void) +void +gst_query_set_uri_redirection (GstQuery * query, const gchar * uri) { - GstQuery *query; + GstStructure *structure; - query = gst_query_new (GST_QUERY_TOC, NULL); + g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_URI); + g_return_if_fail (gst_query_is_writable (query)); + g_return_if_fail (gst_uri_is_valid (uri)); - return query; + structure = GST_QUERY_STRUCTURE (query); + gst_structure_id_set (structure, GST_QUARK (URI_REDIRECTION), + G_TYPE_STRING, uri, NULL); } /** - * gst_query_set_toc: - * @query: a #GstQuery with query type GST_QUERY_TOC. - * @toc: the GstToc to set. - * @extend_uid: UID which can be used for TOC extending (may be NULL), - * 0 means root TOC level. + * gst_query_parse_uri_redirection: + * @query: a #GstQuery + * @uri: (out) (transfer full) (allow-none): the storage for the redirect URI + * (may be %NULL) * - * Answer a TOC query by setting appropriate #GstToc structure. + * Parse an URI query, writing the URI into @uri as a newly + * allocated string, if the respective parameters are non-%NULL. + * Free the string with g_free() after usage. * - * Since: 0.10.37 + * Since: 1.2 */ void -gst_query_set_toc (GstQuery * query, GstToc * toc, const gchar * extend_uid) +gst_query_parse_uri_redirection (GstQuery * query, gchar ** uri) { GstStructure *structure; - g_return_if_fail (query != NULL); - g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_TOC); - g_return_if_fail (toc != NULL); - - structure = _gst_toc_to_structure (toc); - - g_return_if_fail (structure != NULL); - - /* that shouldn't be happen in normal usage */ - if (query->structure != NULL) - gst_structure_free (query->structure); - - if (extend_uid != NULL) - _gst_toc_structure_set_extend_uid (structure, extend_uid); + g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_URI); - query->structure = structure; - gst_structure_set_parent_refcount (query->structure, - &(query->mini_object.refcount)); + structure = GST_QUERY_STRUCTURE (query); + if (uri) { + if (!gst_structure_id_get (structure, GST_QUARK (URI_REDIRECTION), + G_TYPE_STRING, uri, NULL)) + *uri = NULL; + } } /** - * gst_query_parse_toc: - * @query: a #GstQuery. - * @toc: (out): the storage for the received TOC (may be NULL). - * @extend_uid: (out): the storage for the received extend UID marker (may be NULL), - * 0 means root TOC level. + * gst_query_set_uri_redirection_permanent: + * @query: a #GstQuery with query type GST_QUERY_URI + * @permanent: whether the redirect is permanent or not * - * Parse a TOC query, writing the TOC into @toc as a newly - * allocated #GstToc and extend UID into @extend_uid, if the respective parameters - * are non-NULL. Use @extend_uid value to insert new entries into the TOC (@extend_uid will - * act as root entry for newly inserted entries). - * Free @toc with gst_toc_free() and @extend_uid with g_free() after usage. + * Answer a URI query by setting the requested URI redirection + * to permanent or not. * - * Since: 0.10.37 + * Since: 1.4 */ void -gst_query_parse_toc (GstQuery * query, GstToc ** toc, gchar ** extend_uid) +gst_query_set_uri_redirection_permanent (GstQuery * query, gboolean permanent) { - const GstStructure *structure; + GstStructure *structure; - g_return_if_fail (query != NULL); - g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_TOC); + g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_URI); + g_return_if_fail (gst_query_is_writable (query)); + + structure = GST_QUERY_STRUCTURE (query); + gst_structure_id_set (structure, GST_QUARK (URI_REDIRECTION_PERMANENT), + G_TYPE_BOOLEAN, permanent, NULL); +} + +/** + * gst_query_parse_uri_redirection_permanent: + * @query: a #GstQuery + * @permanent: (out) (allow-none): if the URI redirection is permanent + * (may be %NULL) + * + * Parse an URI query, and set @permanent to %TRUE if there is a redirection + * and it should be considered permanent. If a redirection is permanent, + * applications should update their internal storage of the URI, otherwise + * they should make all future requests to the original URI. + * + * Since: 1.4 + */ +void +gst_query_parse_uri_redirection_permanent (GstQuery * query, + gboolean * permanent) +{ + GstStructure *structure; + + g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_URI); + + structure = GST_QUERY_STRUCTURE (query); + if (permanent) { + if (!gst_structure_id_get (structure, GST_QUARK (URI_REDIRECTION_PERMANENT), + G_TYPE_BOOLEAN, permanent, NULL)) + *permanent = FALSE; + } +} + +/** + * gst_query_new_allocation: + * @caps: the negotiated caps + * @need_pool: return a pool + * + * Constructs a new query object for querying the allocation properties. + * + * Free-function: gst_query_unref + * + * Returns: (transfer full): a new #GstQuery + */ +GstQuery * +gst_query_new_allocation (GstCaps * caps, gboolean need_pool) +{ + GstQuery *query; + GstStructure *structure; + + structure = gst_structure_new_id (GST_QUARK (QUERY_ALLOCATION), + GST_QUARK (CAPS), GST_TYPE_CAPS, caps, + GST_QUARK (NEED_POOL), G_TYPE_BOOLEAN, need_pool, NULL); + + query = gst_query_new_custom (GST_QUERY_ALLOCATION, structure); + + return query; +} + +/** + * gst_query_parse_allocation: + * @query: a #GstQuery + * @caps: (out) (transfer none) (allow-none): The #GstCaps + * @need_pool: (out) (allow-none): Whether a #GstBufferPool is needed + * + * Parse an allocation query, writing the requested caps in @caps and + * whether a pool is needed in @need_pool, if the respective parameters + * are non-%NULL. + */ +void +gst_query_parse_allocation (GstQuery * query, GstCaps ** caps, + gboolean * need_pool) +{ + GstStructure *structure; + + g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_ALLOCATION); + + structure = GST_QUERY_STRUCTURE (query); + if (caps) { + *caps = g_value_get_boxed (gst_structure_id_get_value (structure, + GST_QUARK (CAPS))); + } + gst_structure_id_get (structure, + GST_QUARK (NEED_POOL), G_TYPE_BOOLEAN, need_pool, NULL); +} + +typedef struct +{ + GstBufferPool *pool; + guint size; + guint min_buffers; + guint max_buffers; +} AllocationPool; + +static void +allocation_pool_free (AllocationPool * ap) +{ + if (ap->pool) + gst_object_unref (ap->pool); +} + +/** + * gst_query_add_allocation_pool: + * @query: A valid #GstQuery of type GST_QUERY_ALLOCATION. + * @pool: the #GstBufferPool + * @size: the size + * @min_buffers: the min buffers + * @max_buffers: the max buffers + * + * Set the pool parameters in @query. + */ +void +gst_query_add_allocation_pool (GstQuery * query, GstBufferPool * pool, + guint size, guint min_buffers, guint max_buffers) +{ + GArray *array; + GstStructure *structure; + AllocationPool ap; + + g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_ALLOCATION); + g_return_if_fail (gst_query_is_writable (query)); + g_return_if_fail (size != 0); + + structure = GST_QUERY_STRUCTURE (query); + array = ensure_array (structure, GST_QUARK (POOL), + sizeof (AllocationPool), (GDestroyNotify) allocation_pool_free); + + if ((ap.pool = pool)) + gst_object_ref (pool); + ap.size = size; + ap.min_buffers = min_buffers; + ap.max_buffers = max_buffers; + + g_array_append_val (array, ap); +} + + +/** + * gst_query_get_n_allocation_pools: + * @query: a GST_QUERY_ALLOCATION type query #GstQuery + * + * Retrieve the number of values currently stored in the + * pool array of the query's structure. + * + * Returns: the pool array size as a #guint. + */ +guint +gst_query_get_n_allocation_pools (GstQuery * query) +{ + GArray *array; + GstStructure *structure; + + g_return_val_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_ALLOCATION, 0); + + structure = GST_QUERY_STRUCTURE (query); + array = ensure_array (structure, GST_QUARK (POOL), + sizeof (AllocationPool), (GDestroyNotify) allocation_pool_free); + + return array->len; +} + +/** + * gst_query_parse_nth_allocation_pool: + * @query: A valid #GstQuery of type GST_QUERY_ALLOCATION. + * @index: index to parse + * @pool: (out) (allow-none) (transfer full): the #GstBufferPool + * @size: (out) (allow-none): the size + * @min_buffers: (out) (allow-none): the min buffers + * @max_buffers: (out) (allow-none): the max buffers + * + * Get the pool parameters in @query. + * + * Unref @pool with gst_object_unref() when it's not needed any more. + */ +void +gst_query_parse_nth_allocation_pool (GstQuery * query, guint index, + GstBufferPool ** pool, guint * size, guint * min_buffers, + guint * max_buffers) +{ + GArray *array; + GstStructure *structure; + AllocationPool *ap; + + g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_ALLOCATION); + + structure = GST_QUERY_STRUCTURE (query); + array = ensure_array (structure, GST_QUARK (POOL), + sizeof (AllocationPool), (GDestroyNotify) allocation_pool_free); + g_return_if_fail (index < array->len); + + ap = &g_array_index (array, AllocationPool, index); + + if (pool) + if ((*pool = ap->pool)) + gst_object_ref (*pool); + if (size) + *size = ap->size; + if (min_buffers) + *min_buffers = ap->min_buffers; + if (max_buffers) + *max_buffers = ap->max_buffers; +} + +/** + * gst_query_set_nth_allocation_pool: + * @index: index to modify + * @query: A valid #GstQuery of type GST_QUERY_ALLOCATION. + * @pool: the #GstBufferPool + * @size: the size + * @min_buffers: the min buffers + * @max_buffers: the max buffers + * + * Set the pool parameters in @query. + */ +void +gst_query_set_nth_allocation_pool (GstQuery * query, guint index, + GstBufferPool * pool, guint size, guint min_buffers, guint max_buffers) +{ + GArray *array; + GstStructure *structure; + AllocationPool *oldap, ap; + + g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_ALLOCATION); + + structure = GST_QUERY_STRUCTURE (query); + array = ensure_array (structure, GST_QUARK (POOL), + sizeof (AllocationPool), (GDestroyNotify) allocation_pool_free); + g_return_if_fail (index < array->len); + + oldap = &g_array_index (array, AllocationPool, index); + allocation_pool_free (oldap); + + if ((ap.pool = pool)) + gst_object_ref (pool); + ap.size = size; + ap.min_buffers = min_buffers; + ap.max_buffers = max_buffers; + g_array_index (array, AllocationPool, index) = ap; +} + +/** + * gst_query_remove_nth_allocation_pool: + * @query: a GST_QUERY_ALLOCATION type query #GstQuery + * @index: position in the allocation pool array to remove + * + * Remove the allocation pool at @index of the allocation pool array. + * + * Since: 1.2 + */ +void +gst_query_remove_nth_allocation_pool (GstQuery * query, guint index) +{ + GArray *array; + GstStructure *structure; + + g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_ALLOCATION); + g_return_if_fail (gst_query_is_writable (query)); + + structure = GST_QUERY_STRUCTURE (query); + array = + ensure_array (structure, GST_QUARK (POOL), sizeof (AllocationPool), + (GDestroyNotify) allocation_pool_free); + g_return_if_fail (index < array->len); + + g_array_remove_index (array, index); +} + +typedef struct +{ + GType api; + GstStructure *params; +} AllocationMeta; + +static void +allocation_meta_free (AllocationMeta * am) +{ + if (am->params) + gst_structure_free (am->params); +} + +/** + * gst_query_add_allocation_meta: + * @query: a GST_QUERY_ALLOCATION type query #GstQuery + * @api: the metadata API + * @params: (transfer none) (allow-none): API specific parameters + * + * Add @api with @params as one of the supported metadata API to @query. + */ +void +gst_query_add_allocation_meta (GstQuery * query, GType api, + const GstStructure * params) +{ + GArray *array; + GstStructure *structure; + AllocationMeta am; + + g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_ALLOCATION); + g_return_if_fail (api != 0); + g_return_if_fail (gst_query_is_writable (query)); + + structure = GST_QUERY_STRUCTURE (query); + array = + ensure_array (structure, GST_QUARK (META), sizeof (AllocationMeta), + (GDestroyNotify) allocation_meta_free); + + am.api = api; + am.params = (params ? gst_structure_copy (params) : NULL); + + g_array_append_val (array, am); +} + +/** + * gst_query_get_n_allocation_metas: + * @query: a GST_QUERY_ALLOCATION type query #GstQuery + * + * Retrieve the number of values currently stored in the + * meta API array of the query's structure. + * + * Returns: the metadata API array size as a #guint. + */ +guint +gst_query_get_n_allocation_metas (GstQuery * query) +{ + GArray *array; + GstStructure *structure; + + g_return_val_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_ALLOCATION, 0); + + structure = GST_QUERY_STRUCTURE (query); + array = + ensure_array (structure, GST_QUARK (META), sizeof (AllocationMeta), + (GDestroyNotify) allocation_meta_free); + + return array->len; +} + +/** + * gst_query_parse_nth_allocation_meta: + * @query: a GST_QUERY_ALLOCATION type query #GstQuery + * @index: position in the metadata API array to read + * @params: (out) (transfer none) (allow-none): API specific flags + * + * Parse an available query and get the metadata API + * at @index of the metadata API array. + * + * Returns: a #GType of the metadata API at @index. + */ +GType +gst_query_parse_nth_allocation_meta (GstQuery * query, guint index, + const GstStructure ** params) +{ + GArray *array; + GstStructure *structure; + AllocationMeta *am; + + g_return_val_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_ALLOCATION, 0); + + structure = GST_QUERY_STRUCTURE (query); + array = + ensure_array (structure, GST_QUARK (META), sizeof (AllocationMeta), + (GDestroyNotify) allocation_meta_free); + + g_return_val_if_fail (index < array->len, 0); + + am = &g_array_index (array, AllocationMeta, index); + + if (params) + *params = am->params; + + return am->api; +} + +/** + * gst_query_remove_nth_allocation_meta: + * @query: a GST_QUERY_ALLOCATION type query #GstQuery + * @index: position in the metadata API array to remove + * + * Remove the metadata API at @index of the metadata API array. + */ +void +gst_query_remove_nth_allocation_meta (GstQuery * query, guint index) +{ + GArray *array; + GstStructure *structure; + + g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_ALLOCATION); + g_return_if_fail (gst_query_is_writable (query)); + + structure = GST_QUERY_STRUCTURE (query); + array = + ensure_array (structure, GST_QUARK (META), sizeof (AllocationMeta), + (GDestroyNotify) allocation_meta_free); + g_return_if_fail (index < array->len); + + g_array_remove_index (array, index); +} + +/** + * gst_query_find_allocation_meta: + * @query: a GST_QUERY_ALLOCATION type query #GstQuery + * @api: the metadata API + * @index: (out) (transfer none) (allow-none): the index + * + * Check if @query has metadata @api set. When this function returns %TRUE, + * @index will contain the index where the requested API and the flags can be + * found. + * + * Returns: %TRUE when @api is in the list of metadata. + */ +gboolean +gst_query_find_allocation_meta (GstQuery * query, GType api, guint * index) +{ + GArray *array; + GstStructure *structure; + guint i, len; + + g_return_val_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_ALLOCATION, FALSE); + g_return_val_if_fail (api != 0, FALSE); + + structure = GST_QUERY_STRUCTURE (query); + array = + ensure_array (structure, GST_QUARK (META), sizeof (AllocationMeta), + (GDestroyNotify) allocation_meta_free); + + len = array->len; + for (i = 0; i < len; i++) { + AllocationMeta *am = &g_array_index (array, AllocationMeta, i); + if (am->api == api) { + if (index) + *index = i; + return TRUE; + } + } + return FALSE; +} + +typedef struct +{ + GstAllocator *allocator; + GstAllocationParams params; +} AllocationParam; + +static void +allocation_param_free (AllocationParam * ap) +{ + if (ap->allocator) + gst_object_unref (ap->allocator); +} + +/** + * gst_query_add_allocation_param: + * @query: a GST_QUERY_ALLOCATION type query #GstQuery + * @allocator: (transfer none) (allow-none): the memory allocator + * @params: (transfer none) (allow-none): a #GstAllocationParams + * + * Add @allocator and its @params as a supported memory allocator. + */ +void +gst_query_add_allocation_param (GstQuery * query, GstAllocator * allocator, + const GstAllocationParams * params) +{ + GArray *array; + GstStructure *structure; + AllocationParam ap; + + g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_ALLOCATION); + g_return_if_fail (gst_query_is_writable (query)); + g_return_if_fail (allocator != NULL || params != NULL); + + structure = GST_QUERY_STRUCTURE (query); + array = ensure_array (structure, GST_QUARK (ALLOCATOR), + sizeof (AllocationParam), (GDestroyNotify) allocation_param_free); + + if ((ap.allocator = allocator)) + gst_object_ref (allocator); + if (params) + ap.params = *params; + else + gst_allocation_params_init (&ap.params); + + g_array_append_val (array, ap); +} + +/** + * gst_query_get_n_allocation_params: + * @query: a GST_QUERY_ALLOCATION type query #GstQuery + * + * Retrieve the number of values currently stored in the + * allocator params array of the query's structure. + * + * If no memory allocator is specified, the downstream element can handle + * the default memory allocator. The first memory allocator in the query + * should be generic and allow mapping to system memory, all following + * allocators should be ordered by preference with the preferred one first. + * + * Returns: the allocator array size as a #guint. + */ +guint +gst_query_get_n_allocation_params (GstQuery * query) +{ + GArray *array; + GstStructure *structure; + + g_return_val_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_ALLOCATION, 0); + + structure = GST_QUERY_STRUCTURE (query); + array = ensure_array (structure, GST_QUARK (ALLOCATOR), + sizeof (AllocationParam), (GDestroyNotify) allocation_param_free); + + return array->len; +} + +/** + * gst_query_parse_nth_allocation_param: + * @query: a GST_QUERY_ALLOCATION type query #GstQuery + * @index: position in the allocator array to read + * @allocator: (out) (transfer full) (allow-none): variable to hold the result + * @params: (out) (allow-none): parameters for the allocator + * + * Parse an available query and get the allocator and its params + * at @index of the allocator array. + */ +void +gst_query_parse_nth_allocation_param (GstQuery * query, guint index, + GstAllocator ** allocator, GstAllocationParams * params) +{ + GArray *array; + GstStructure *structure; + AllocationParam *ap; + + g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_ALLOCATION); + + structure = GST_QUERY_STRUCTURE (query); + array = ensure_array (structure, GST_QUARK (ALLOCATOR), + sizeof (AllocationParam), (GDestroyNotify) allocation_param_free); + g_return_if_fail (index < array->len); + + ap = &g_array_index (array, AllocationParam, index); + + if (allocator) + if ((*allocator = ap->allocator)) + gst_object_ref (*allocator); + if (params) + *params = ap->params; +} + +/** + * gst_query_set_nth_allocation_param: + * @query: a GST_QUERY_ALLOCATION type query #GstQuery + * @index: position in the allocator array to set + * @allocator: (transfer none) (allow-none): new allocator to set + * @params: (transfer none) (allow-none): parameters for the allocator + * + * Parse an available query and get the allocator and its params + * at @index of the allocator array. + */ +void +gst_query_set_nth_allocation_param (GstQuery * query, guint index, + GstAllocator * allocator, const GstAllocationParams * params) +{ + GArray *array; + GstStructure *structure; + AllocationParam *old, ap; + + g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_ALLOCATION); + + structure = GST_QUERY_STRUCTURE (query); + array = ensure_array (structure, GST_QUARK (ALLOCATOR), + sizeof (AllocationParam), (GDestroyNotify) allocation_param_free); + g_return_if_fail (index < array->len); + + old = &g_array_index (array, AllocationParam, index); + allocation_param_free (old); + + if ((ap.allocator = allocator)) + gst_object_ref (allocator); + if (params) + ap.params = *params; + else + gst_allocation_params_init (&ap.params); + + g_array_index (array, AllocationParam, index) = ap; +} + +/** + * gst_query_remove_nth_allocation_param: + * @query: a GST_QUERY_ALLOCATION type query #GstQuery + * @index: position in the allocation param array to remove + * + * Remove the allocation param at @index of the allocation param array. + * + * Since: 1.2 + */ +void +gst_query_remove_nth_allocation_param (GstQuery * query, guint index) +{ + GArray *array; + GstStructure *structure; + + g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_ALLOCATION); + g_return_if_fail (gst_query_is_writable (query)); + + structure = GST_QUERY_STRUCTURE (query); + array = + ensure_array (structure, GST_QUARK (ALLOCATOR), sizeof (AllocationParam), + (GDestroyNotify) allocation_param_free); + g_return_if_fail (index < array->len); + + g_array_remove_index (array, index); +} + +/** + * gst_query_new_scheduling: + * + * Constructs a new query object for querying the scheduling properties. + * + * Free-function: gst_query_unref + * + * Returns: (transfer full): a new #GstQuery + */ +GstQuery * +gst_query_new_scheduling (void) +{ + GstQuery *query; + GstStructure *structure; + + structure = gst_structure_new_id (GST_QUARK (QUERY_SCHEDULING), + GST_QUARK (FLAGS), GST_TYPE_SCHEDULING_FLAGS, 0, + GST_QUARK (MINSIZE), G_TYPE_INT, 1, + GST_QUARK (MAXSIZE), G_TYPE_INT, -1, + GST_QUARK (ALIGN), G_TYPE_INT, 0, NULL); + query = gst_query_new_custom (GST_QUERY_SCHEDULING, structure); + + return query; +} + +/** + * gst_query_set_scheduling: + * @query: A valid #GstQuery of type GST_QUERY_SCHEDULING. + * @flags: #GstSchedulingFlags + * @minsize: the suggested minimum size of pull requests + * @maxsize: the suggested maximum size of pull requests + * @align: the suggested alignment of pull requests + * + * Set the scheduling properties. + */ +void +gst_query_set_scheduling (GstQuery * query, GstSchedulingFlags flags, + gint minsize, gint maxsize, gint align) +{ + GstStructure *structure; + + g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_SCHEDULING); + g_return_if_fail (gst_query_is_writable (query)); + + structure = GST_QUERY_STRUCTURE (query); + gst_structure_id_set (structure, + GST_QUARK (FLAGS), GST_TYPE_SCHEDULING_FLAGS, flags, + GST_QUARK (MINSIZE), G_TYPE_INT, minsize, + GST_QUARK (MAXSIZE), G_TYPE_INT, maxsize, + GST_QUARK (ALIGN), G_TYPE_INT, align, NULL); +} + +/** + * gst_query_parse_scheduling: + * @query: A valid #GstQuery of type GST_QUERY_SCHEDULING. + * @flags: (out) (allow-none): #GstSchedulingFlags + * @minsize: (out) (allow-none): the suggested minimum size of pull requests + * @maxsize: (out) (allow-none): the suggested maximum size of pull requests: + * @align: (out) (allow-none): the suggested alignment of pull requests + * + * Set the scheduling properties. + */ +void +gst_query_parse_scheduling (GstQuery * query, GstSchedulingFlags * flags, + gint * minsize, gint * maxsize, gint * align) +{ + GstStructure *structure; + + g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_SCHEDULING); + + structure = GST_QUERY_STRUCTURE (query); + gst_structure_id_get (structure, + GST_QUARK (FLAGS), GST_TYPE_SCHEDULING_FLAGS, flags, + GST_QUARK (MINSIZE), G_TYPE_INT, minsize, + GST_QUARK (MAXSIZE), G_TYPE_INT, maxsize, + GST_QUARK (ALIGN), G_TYPE_INT, align, NULL); +} + +/** + * gst_query_add_scheduling_mode: + * @query: a GST_QUERY_SCHEDULING type query #GstQuery + * @mode: a #GstPadMode + * + * Add @mode as one of the supported scheduling modes to @query. + */ +void +gst_query_add_scheduling_mode (GstQuery * query, GstPadMode mode) +{ + GstStructure *structure; + GArray *array; + + g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_SCHEDULING); + g_return_if_fail (gst_query_is_writable (query)); + + structure = GST_QUERY_STRUCTURE (query); + array = + ensure_array (structure, GST_QUARK (MODES), sizeof (GstPadMode), NULL); + + g_array_append_val (array, mode); +} + +/** + * gst_query_get_n_scheduling_modes: + * @query: a GST_QUERY_SCHEDULING type query #GstQuery + * + * Retrieve the number of values currently stored in the + * scheduling mode array of the query's structure. + * + * Returns: the scheduling mode array size as a #guint. + */ +guint +gst_query_get_n_scheduling_modes (GstQuery * query) +{ + GArray *array; + GstStructure *structure; + + g_return_val_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_SCHEDULING, 0); + + structure = GST_QUERY_STRUCTURE (query); + array = + ensure_array (structure, GST_QUARK (MODES), sizeof (GstPadMode), NULL); + + return array->len; +} + +/** + * gst_query_parse_nth_scheduling_mode: + * @query: a GST_QUERY_SCHEDULING type query #GstQuery + * @index: position in the scheduling modes array to read + * + * Parse an available query and get the scheduling mode + * at @index of the scheduling modes array. + * + * Returns: a #GstPadMode of the scheduling mode at @index. + */ +GstPadMode +gst_query_parse_nth_scheduling_mode (GstQuery * query, guint index) +{ + GstStructure *structure; + GArray *array; + + g_return_val_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_SCHEDULING, + GST_PAD_MODE_NONE); + + structure = GST_QUERY_STRUCTURE (query); + array = + ensure_array (structure, GST_QUARK (MODES), sizeof (GstPadMode), NULL); + g_return_val_if_fail (index < array->len, GST_PAD_MODE_NONE); + + return g_array_index (array, GstPadMode, index); +} + +/** + * gst_query_has_scheduling_mode: + * @query: a GST_QUERY_SCHEDULING type query #GstQuery + * @mode: the scheduling mode + * + * Check if @query has scheduling mode set. + * + * + * + * When checking if upstream supports pull mode, it is usually not + * enough to just check for GST_PAD_MODE_PULL with this function, you + * also want to check whether the scheduling flags returned by + * gst_query_parse_scheduling() have the seeking flag set (meaning + * random access is supported, not only sequential pulls). + * + * + * + * Returns: %TRUE when @mode is in the list of scheduling modes. + */ +gboolean +gst_query_has_scheduling_mode (GstQuery * query, GstPadMode mode) +{ + GstStructure *structure; + GArray *array; + guint i, len; + + g_return_val_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_SCHEDULING, FALSE); + + structure = GST_QUERY_STRUCTURE (query); + array = + ensure_array (structure, GST_QUARK (MODES), sizeof (GstPadMode), NULL); + + len = array->len; + for (i = 0; i < len; i++) { + if (mode == g_array_index (array, GstPadMode, i)) + return TRUE; + } + return FALSE; +} + +/** + * gst_query_has_scheduling_mode_with_flags: + * @query: a GST_QUERY_SCHEDULING type query #GstQuery + * @mode: the scheduling mode + * @flags: #GstSchedulingFlags + * + * Check if @query has scheduling mode set and @flags is set in + * query scheduling flags. + * + * Returns: %TRUE when @mode is in the list of scheduling modes + * and @flags are compatible with query flags. + */ +gboolean +gst_query_has_scheduling_mode_with_flags (GstQuery * query, GstPadMode mode, + GstSchedulingFlags flags) +{ + GstSchedulingFlags sched_flags; + + g_return_val_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_SCHEDULING, FALSE); + + gst_query_parse_scheduling (query, &sched_flags, NULL, NULL, NULL); + + return ((flags & sched_flags) == flags) && + gst_query_has_scheduling_mode (query, mode); +} + +/** + * gst_query_new_accept_caps: + * @caps: a fixed #GstCaps + * + * Constructs a new query object for querying if @caps are accepted. + * + * Free-function: gst_query_unref + * + * Returns: (transfer full): a new #GstQuery + */ +GstQuery * +gst_query_new_accept_caps (GstCaps * caps) +{ + GstQuery *query; + GstStructure *structure; + + g_return_val_if_fail (gst_caps_is_fixed (caps), NULL); + + structure = gst_structure_new_id (GST_QUARK (QUERY_ACCEPT_CAPS), + GST_QUARK (CAPS), GST_TYPE_CAPS, caps, + GST_QUARK (RESULT), G_TYPE_BOOLEAN, FALSE, NULL); + query = gst_query_new_custom (GST_QUERY_ACCEPT_CAPS, structure); + + return query; +} + +/** + * gst_query_parse_accept_caps: + * @query: The query to parse + * @caps: (out) (transfer none): A pointer to the caps + * + * Get the caps from @query. The caps remains valid as long as @query remains + * valid. + */ +void +gst_query_parse_accept_caps (GstQuery * query, GstCaps ** caps) +{ + GstStructure *structure; + + g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_ACCEPT_CAPS); + g_return_if_fail (caps != NULL); + + structure = GST_QUERY_STRUCTURE (query); + *caps = g_value_get_boxed (gst_structure_id_get_value (structure, + GST_QUARK (CAPS))); +} + +/** + * gst_query_set_accept_caps_result: + * @query: a GST_QUERY_ACCEPT_CAPS type query #GstQuery + * @result: the result to set + * + * Set @result as the result for the @query. + */ +void +gst_query_set_accept_caps_result (GstQuery * query, gboolean result) +{ + GstStructure *structure; + + g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_ACCEPT_CAPS); + g_return_if_fail (gst_query_is_writable (query)); + + structure = GST_QUERY_STRUCTURE (query); + gst_structure_id_set (structure, + GST_QUARK (RESULT), G_TYPE_BOOLEAN, result, NULL); +} + +/** + * gst_query_parse_accept_caps_result: + * @query: a GST_QUERY_ACCEPT_CAPS type query #GstQuery + * @result: location for the result + * + * Parse the result from @query and store in @result. + */ +void +gst_query_parse_accept_caps_result (GstQuery * query, gboolean * result) +{ + GstStructure *structure; - structure = gst_query_get_structure (query); + g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_ACCEPT_CAPS); - g_return_if_fail (structure != NULL); + structure = GST_QUERY_STRUCTURE (query); + gst_structure_id_get (structure, + GST_QUARK (RESULT), G_TYPE_BOOLEAN, result, NULL); +} + +/** + * gst_query_new_caps: + * @filter: a filter + * + * Constructs a new query object for querying the caps. + * + * The CAPS query should return the allowable caps for a pad in the context + * of the element's state, its link to other elements, and the devices or files + * it has opened. These caps must be a subset of the pad template caps. In the + * NULL state with no links, the CAPS query should ideally return the same caps + * as the pad template. In rare circumstances, an object property can affect + * the caps returned by the CAPS query, but this is discouraged. + * + * For most filters, the caps returned by CAPS query is directly affected by the + * allowed caps on other pads. For demuxers and decoders, the caps returned by + * the srcpad's getcaps function is directly related to the stream data. Again, + * the CAPS query should return the most specific caps it reasonably can, since this + * helps with autoplugging. + * + * The @filter is used to restrict the result caps, only the caps matching + * @filter should be returned from the CAPS query. Specifying a filter might + * greatly reduce the amount of processing an element needs to do. + * + * Free-function: gst_query_unref + * + * Returns: (transfer full): a new #GstQuery + */ +GstQuery * +gst_query_new_caps (GstCaps * filter) +{ + GstQuery *query; + GstStructure *structure; + + structure = gst_structure_new_id (GST_QUARK (QUERY_CAPS), + GST_QUARK (FILTER), GST_TYPE_CAPS, filter, + GST_QUARK (CAPS), GST_TYPE_CAPS, NULL, NULL); + query = gst_query_new_custom (GST_QUERY_CAPS, structure); + + return query; +} + +/** + * gst_query_parse_caps: + * @query: The query to parse + * @filter: (out) (transfer none): A pointer to the caps filter + * + * Get the filter from the caps @query. The caps remains valid as long as + * @query remains valid. + */ +void +gst_query_parse_caps (GstQuery * query, GstCaps ** filter) +{ + GstStructure *structure; + + g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_CAPS); + g_return_if_fail (filter != NULL); + + structure = GST_QUERY_STRUCTURE (query); + *filter = g_value_get_boxed (gst_structure_id_get_value (structure, + GST_QUARK (FILTER))); +} + +/** + * gst_query_set_caps_result: + * @query: The query to use + * @caps: (in): A pointer to the caps + * + * Set the @caps result in @query. + */ +void +gst_query_set_caps_result (GstQuery * query, GstCaps * caps) +{ + GstStructure *structure; + + g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_CAPS); + g_return_if_fail (gst_query_is_writable (query)); + + structure = GST_QUERY_STRUCTURE (query); + gst_structure_id_set (structure, GST_QUARK (CAPS), GST_TYPE_CAPS, caps, NULL); +} + +/** + * gst_query_parse_caps_result: + * @query: The query to parse + * @caps: (out) (transfer none): A pointer to the caps + * + * Get the caps result from @query. The caps remains valid as long as + * @query remains valid. + */ +void +gst_query_parse_caps_result (GstQuery * query, GstCaps ** caps) +{ + GstStructure *structure; + + g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_CAPS); + g_return_if_fail (caps != NULL); + + structure = GST_QUERY_STRUCTURE (query); + *caps = g_value_get_boxed (gst_structure_id_get_value (structure, + GST_QUARK (CAPS))); +} + +#if 0 +void +gst_query_intersect_caps_result (GstQuery * query, GstCaps * filter, + GstCapsIntersectMode mode) +{ + GstCaps *res, *caps = NULL; + + gst_query_parse_caps_result (query, &caps); + res = gst_caps_intersect_full (filter, caps, GST_CAPS_INTERSECT_FIRST); + gst_query_set_caps_result (query, res); + gst_caps_unref (res); +} +#endif + +/** + * gst_query_new_drain: + * + * Constructs a new query object for querying the drain state. + * + * Free-function: gst_query_unref + * + * Returns: (transfer full): a new #GstQuery + */ +GstQuery * +gst_query_new_drain (void) +{ + GstQuery *query; + GstStructure *structure; + + structure = gst_structure_new_id_empty (GST_QUARK (QUERY_DRAIN)); + query = gst_query_new_custom (GST_QUERY_DRAIN, structure); + + return query; +} + +/** + * gst_query_new_context: + * @context_type: Context type to query + * + * Constructs a new query object for querying the pipeline-local context. + * + * Free-function: gst_query_unref + * + * Returns: (transfer full): a new #GstQuery + * + * Since: 1.2 + */ +GstQuery * +gst_query_new_context (const gchar * context_type) +{ + GstQuery *query; + GstStructure *structure; + + g_return_val_if_fail (context_type != NULL, NULL); + + structure = gst_structure_new_id (GST_QUARK (QUERY_CONTEXT), + GST_QUARK (CONTEXT_TYPE), G_TYPE_STRING, context_type, NULL); + query = gst_query_new_custom (GST_QUERY_CONTEXT, structure); + + return query; +} + +/** + * gst_query_set_context: + * @query: a #GstQuery with query type GST_QUERY_CONTEXT + * @context: the requested #GstContext + * + * Answer a context query by setting the requested context. + * + * Since: 1.2 + */ +void +gst_query_set_context (GstQuery * query, GstContext * context) +{ + GstStructure *s; + const gchar *context_type; - if (toc != NULL) - *toc = _gst_toc_from_structure (structure); + g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_CONTEXT); - if (extend_uid != NULL) - *extend_uid = _gst_toc_structure_get_extend_uid (structure); + gst_query_parse_context_type (query, &context_type); + g_return_if_fail (strcmp (gst_context_get_context_type (context), + context_type) == 0); + + s = GST_QUERY_STRUCTURE (query); + + gst_structure_id_set (s, + GST_QUARK (CONTEXT), GST_TYPE_CONTEXT, context, NULL); +} + +/** + * gst_query_parse_context: + * @query: The query to parse + * @context: (out) (transfer none): A pointer to store the #GstContext + * + * Get the context from the context @query. The context remains valid as long as + * @query remains valid. + * + * Since: 1.2 + */ +void +gst_query_parse_context (GstQuery * query, GstContext ** context) +{ + GstStructure *structure; + const GValue *v; + + g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_CONTEXT); + g_return_if_fail (context != NULL); + + structure = GST_QUERY_STRUCTURE (query); + v = gst_structure_id_get_value (structure, GST_QUARK (CONTEXT)); + if (v) + *context = g_value_get_boxed (v); + else + *context = NULL; +} + +/** + * gst_query_parse_context_type: + * @query: a GST_QUERY_CONTEXT type query + * @context_type: (out) (transfer none) (allow-none): the context type, or %NULL + * + * Parse a context type from an existing GST_QUERY_CONTEXT query. + * + * Returns: a #gboolean indicating if the parsing succeeded. + * + * Since: 1.2 + */ +gboolean +gst_query_parse_context_type (GstQuery * query, const gchar ** context_type) +{ + GstStructure *structure; + const GValue *value; + + g_return_val_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_CONTEXT, FALSE); + + structure = GST_QUERY_STRUCTURE (query); + + if (context_type) { + value = gst_structure_id_get_value (structure, GST_QUARK (CONTEXT_TYPE)); + *context_type = g_value_get_string (value); + } + + return TRUE; }