]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - glsdk/gstreamer0-10.git/blobdiff - gst/gstquery.c
add GstQueryBuffers query
[glsdk/gstreamer0-10.git] / gst / gstquery.c
index d698138269a875edb74b0796a9f2b0728b56dc0e..1d7f5f99b4e6a354e538ac3456d70e8941c5fb57 100644 (file)
  *                     to create queries, and to set and parse values in them.
  * @see_also: #GstPad, #GstElement
  *
- * GstQuery functions are used to register a new query types to the gstreamer
- * core.
- * Query types can be used to perform queries on pads and elements.
+ * 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.
  *
- * Queries can be created using the gst_query_new_xxx() functions.  
- * Query values can be set using gst_query_set_xxx(), and parsed using 
- * gst_query_parse_xxx() helpers.
+ * Queries can be created using the gst_query_new_*() functions.
+ * Query values can be set using gst_query_set_*(), and parsed using
+ * gst_query_parse_*() helpers.
+ *
+ * The following example shows how to query the duration of a pipeline:
+ *
+ * <example>
+ *  <title>Query duration on a pipeline</title>
+ *  <programlisting>
+ *  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, &amp;duration);
+ *    g_print ("duration = %"GST_TIME_FORMAT, GST_TIME_ARGS (duration));
+ *  }
+ *  else {
+ *    g_print ("duration query failed...");
+ *  }
+ *  gst_query_unref (query);
+ *  </programlisting>
+ * </example>
+ *
+ * Last reviewed on 2006-02-14 (0.10.4)
  */
-#include <string.h>
 
 #include "gst_private.h"
+#include "gstinfo.h"
 #include "gstquery.h"
 #include "gstvalue.h"
 #include "gstenumtypes.h"
+#include "gstquark.h"
+#include "gsturi.h"
 
 GST_DEBUG_CATEGORY_STATIC (gst_query_debug);
 #define GST_CAT_DEFAULT gst_query_debug
 
-static void gst_query_init (GTypeInstance * instance, gpointer g_class);
-static void gst_query_class_init (gpointer g_class, gpointer class_data);
 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},
@@ -67,7 +93,11 @@ static GstQueryTypeDefinition standard_definitions[] = {
   {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},
-  {0, NULL, NULL, 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_BUFFERS, "buffers", "Minimum buffer requirements", 0},
+  {GST_QUERY_NONE, NULL, NULL, 0}
 };
 
 void
@@ -87,7 +117,7 @@ _gst_query_initialize (void)
 
   while (standards->nick) {
     standards->quark = g_quark_from_static_string (standards->nick);
-    g_hash_table_insert (_nick_to_query, standards->nick, standards);
+    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);
 
@@ -97,7 +127,7 @@ _gst_query_initialize (void)
   }
   g_static_mutex_unlock (&mutex);
 
-  gst_query_get_type ();
+  g_type_class_ref (gst_query_get_type ());
 }
 
 /**
@@ -136,41 +166,22 @@ gst_query_type_to_quark (GstQueryType query)
   return def->quark;
 }
 
-GType
-gst_query_get_type (void)
+G_DEFINE_TYPE (GstQuery, gst_query, GST_TYPE_MINI_OBJECT);
+
+static void
+gst_query_class_init (GstQueryClass * klass)
 {
-  static GType _gst_query_type;
+  parent_class = g_type_class_peek_parent (klass);
 
-  if (G_UNLIKELY (_gst_query_type == 0)) {
-    static const GTypeInfo query_info = {
-      sizeof (GstQueryClass),
-      NULL,
-      NULL,
-      gst_query_class_init,
-      NULL,
-      NULL,
-      sizeof (GstQuery),
-      0,
-      gst_query_init,
-      NULL
-    };
+  klass->mini_object_class.copy = (GstMiniObjectCopyFunction) _gst_query_copy;
+  klass->mini_object_class.finalize =
+      (GstMiniObjectFinalizeFunction) gst_query_finalize;
 
-    _gst_query_type = g_type_register_static (GST_TYPE_MINI_OBJECT,
-        "GstQuery", &query_info, 0);
-  }
-  return _gst_query_type;
 }
 
 static void
-gst_query_class_init (gpointer g_class, gpointer class_data)
+gst_query_init (GstQuery * query)
 {
-  GstQueryClass *query_class = GST_QUERY_CLASS (g_class);
-
-  query_class->mini_object_class.copy =
-      (GstMiniObjectCopyFunction) _gst_query_copy;
-  query_class->mini_object_class.finalize =
-      (GstMiniObjectFinalizeFunction) gst_query_finalize;
-
 }
 
 static void
@@ -182,12 +193,8 @@ gst_query_finalize (GstQuery * query)
     gst_structure_set_parent_refcount (query->structure, NULL);
     gst_structure_free (query->structure);
   }
-}
-
-static void
-gst_query_init (GTypeInstance * instance, gpointer g_class)
-{
 
+/*   GST_MINI_OBJECT_CLASS (parent_class)->finalize (GST_MINI_OBJECT (query)); */
 }
 
 static GstQuery *
@@ -227,21 +234,21 @@ gst_query_type_register (const gchar * nick, const gchar * description)
   GstQueryTypeDefinition *query;
   GstQueryType lookup;
 
-  g_return_val_if_fail (nick != NULL, 0);
-  g_return_val_if_fail (description != NULL, 0);
+  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_new0 (GstQueryTypeDefinition, 1);
-  query->value = _n_values;
+  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, query->nick, query);
+  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);
@@ -265,7 +272,7 @@ gst_query_type_get_by_nick (const gchar * nick)
 {
   GstQueryTypeDefinition *query;
 
-  g_return_val_if_fail (nick != NULL, 0);
+  g_return_val_if_fail (nick != NULL, GST_QUERY_NONE);
 
   g_static_mutex_lock (&mutex);
   query = g_hash_table_lookup (_nick_to_query, nick);
@@ -325,10 +332,12 @@ gst_query_type_get_details (GstQueryType type)
 /**
  * gst_query_type_iterate_definitions:
  *
- * Get a #GstIterator of all the registered query types. The definitions 
+ * Get a #GstIterator of all the registered query types. The definitions
  * iterated over are read only.
  *
- * Returns: A #GstIterator of #GstQueryTypeDefinition.
+ * Free-function: gst_iterator_free
+ *
+ * Returns: (transfer full): a #GstIterator of #GstQueryTypeDefinition.
  */
 GstIterator *
 gst_query_type_iterate_definitions (void)
@@ -352,7 +361,7 @@ gst_query_new (GstQueryType type, GstStructure * structure)
 
   query = (GstQuery *) gst_mini_object_new (GST_TYPE_QUERY);
 
-  GST_DEBUG ("creating new query %p %d", query, type);
+  GST_DEBUG ("creating new query %p %s", query, gst_query_type_get_name (type));
 
   query->type = type;
 
@@ -375,7 +384,9 @@ gst_query_new (GstQueryType type, GstStructure * structure)
  * when done with it. A position query is used to query the current position
  * of playback in the streams, in some format.
  *
- * Returns: A #GstQuery
+ * Free-function: gst_query_unref
+ *
+ * Returns: (transfer full): a new #GstQuery
  */
 GstQuery *
 gst_query_new_position (GstFormat format)
@@ -383,9 +394,10 @@ gst_query_new_position (GstFormat format)
   GstQuery *query;
   GstStructure *structure;
 
-  structure = gst_structure_new ("GstQueryPosition",
-      "format", GST_TYPE_FORMAT, format,
-      "cur", G_TYPE_INT64, (gint64) - 1, NULL);
+  structure = gst_structure_id_new (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);
 
   return query;
@@ -402,20 +414,19 @@ gst_query_new_position (GstFormat format)
 void
 gst_query_set_position (GstQuery * query, GstFormat format, gint64 cur)
 {
-  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, NULL);
+  gst_structure_id_set (query->structure,
+      GST_QUARK (FORMAT), GST_TYPE_FORMAT, format,
+      GST_QUARK (CURRENT), G_TYPE_INT64, cur, NULL);
 }
 
 /**
  * gst_query_parse_position:
  * @query: a #GstQuery
- * @format: the storage for the #GstFormat of the position values (may be NULL)
- * @cur: the storage for the current position (may be NULL)
+ * @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)
  *
  * Parse a position query, writing the format into @format, and the position
  * into @cur, if the respective parameters are non-NULL.
@@ -427,11 +438,14 @@ gst_query_parse_position (GstQuery * query, GstFormat * format, gint64 * cur)
 
   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_POSITION);
 
-  structure = gst_query_get_structure (query);
+  structure = query->structure;
   if (format)
-    *format = g_value_get_enum (gst_structure_get_value (structure, "format"));
+    *format =
+        (GstFormat) g_value_get_enum (gst_structure_id_get_value (structure,
+            GST_QUARK (FORMAT)));
   if (cur)
-    *cur = g_value_get_int64 (gst_structure_get_value (structure, "cur"));
+    *cur = g_value_get_int64 (gst_structure_id_get_value (structure,
+            GST_QUARK (CURRENT)));
 }
 
 
@@ -439,11 +453,13 @@ gst_query_parse_position (GstQuery * query, GstFormat * format, gint64 * cur)
  * gst_query_new_duration:
  * @format: the #GstFormat for this duration query
  *
- * Constructs a new stream duration query object to query in the given format. 
+ * Constructs a new stream duration query object to query in the given format.
  * Use gst_query_unref() when done with it. A duration query will give the
  * total length of the stream.
  *
- * Returns: A #GstQuery
+ * Free-function: gst_query_unref
+ *
+ * Returns: (transfer full): a new #GstQuery
  */
 GstQuery *
 gst_query_new_duration (GstFormat format)
@@ -451,9 +467,10 @@ gst_query_new_duration (GstFormat format)
   GstQuery *query;
   GstStructure *structure;
 
-  structure = gst_structure_new ("GstQueryDuration",
-      "format", GST_TYPE_FORMAT, format,
-      "duration", G_TYPE_INT64, (gint64) - 1, NULL);
+  structure = gst_structure_id_new (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);
 
   return query;
@@ -470,21 +487,19 @@ gst_query_new_duration (GstFormat format)
 void
 gst_query_set_duration (GstQuery * query, GstFormat format, gint64 duration)
 {
-  GstStructure *structure;
-
   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_DURATION);
 
-  structure = gst_query_get_structure (query);
-  gst_structure_set (structure,
-      "format", GST_TYPE_FORMAT, format,
-      "duration", G_TYPE_INT64, duration, NULL);
+  gst_structure_id_set (query->structure,
+      GST_QUARK (FORMAT), GST_TYPE_FORMAT, format,
+      GST_QUARK (DURATION), G_TYPE_INT64, duration, NULL);
 }
 
 /**
  * gst_query_parse_duration:
  * @query: a #GstQuery
- * @format: the storage for the #GstFormat of the duration value, or NULL.
- * @duration: the storage for the total duration, or NULL.
+ * @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.
  *
  * 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.
@@ -497,12 +512,99 @@ gst_query_parse_duration (GstQuery * query, GstFormat * format,
 
   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_DURATION);
 
-  structure = gst_query_get_structure (query);
+  structure = query->structure;
   if (format)
-    *format = g_value_get_enum (gst_structure_get_value (structure, "format"));
+    *format =
+        (GstFormat) g_value_get_enum (gst_structure_id_get_value (structure,
+            GST_QUARK (FORMAT)));
   if (duration)
-    *duration =
-        g_value_get_int64 (gst_structure_get_value (structure, "duration"));
+    *duration = g_value_get_int64 (gst_structure_id_get_value (structure,
+            GST_QUARK (DURATION)));
+}
+
+/**
+ * gst_query_new_latency:
+ *
+ * Constructs a new latency query object.
+ * Use gst_query_unref() when done with it. A latency query is usually performed
+ * by sinks to compensate for additional latency introduced by elements in the
+ * pipeline.
+ *
+ * Free-function: gst_query_unref
+ *
+ * Returns: (transfer full): a #GstQuery
+ *
+ * Since: 0.10.12
+ */
+GstQuery *
+gst_query_new_latency (void)
+{
+  GstQuery *query;
+  GstStructure *structure;
+
+  structure = gst_structure_id_new (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);
+
+  return query;
+}
+
+/**
+ * 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
+ *
+ * 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)
+{
+  g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_LATENCY);
+
+  gst_structure_id_set (query->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);
+}
+
+/**
+ * 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
+ *
+ * Parse a latency query answer.
+ *
+ * Since: 0.10.12
+ */
+void
+gst_query_parse_latency (GstQuery * query, gboolean * live,
+    GstClockTime * min_latency, GstClockTime * max_latency)
+{
+  GstStructure *structure;
+
+  g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_LATENCY);
+
+  structure = query->structure;
+  if (live)
+    *live =
+        g_value_get_boolean (gst_structure_id_get_value (structure,
+            GST_QUARK (LIVE)));
+  if (min_latency)
+    *min_latency = g_value_get_uint64 (gst_structure_id_get_value (structure,
+            GST_QUARK (MIN_LATENCY)));
+  if (max_latency)
+    *max_latency = g_value_get_uint64 (gst_structure_id_get_value (structure,
+            GST_QUARK (MAX_LATENCY)));
 }
 
 /**
@@ -515,7 +617,9 @@ gst_query_parse_duration (GstQuery * query, GstFormat * format,
  * when done with it. A convert query is used to ask for a conversion between
  * one format and another.
  *
- * Returns: A #GstQuery
+ * Free-function: gst_query_unref
+ *
+ * Returns: (transfer full): a #GstQuery
  */
 GstQuery *
 gst_query_new_convert (GstFormat src_format, gint64 value,
@@ -524,13 +628,12 @@ gst_query_new_convert (GstFormat src_format, gint64 value,
   GstQuery *query;
   GstStructure *structure;
 
-  g_return_val_if_fail (value >= 0, NULL);
+  structure = gst_structure_id_new (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);
 
-  structure = gst_structure_new ("GstQueryConvert",
-      "src_format", GST_TYPE_FORMAT, src_format,
-      "src_value", G_TYPE_INT64, value,
-      "dest_format", GST_TYPE_FORMAT, dest_format,
-      "dest_value", G_TYPE_INT64, (gint64) - 1, NULL);
   query = gst_query_new (GST_QUERY_CONVERT, structure);
 
   return query;
@@ -550,25 +653,25 @@ void
 gst_query_set_convert (GstQuery * query, GstFormat src_format, gint64 src_value,
     GstFormat dest_format, gint64 dest_value)
 {
-  GstStructure *structure;
-
   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_CONVERT);
 
-  structure = gst_query_get_structure (query);
-  gst_structure_set (structure,
-      "src_format", GST_TYPE_FORMAT, src_format,
-      "src_value", G_TYPE_INT64, src_value,
-      "dest_format", GST_TYPE_FORMAT, dest_format,
-      "dest_value", G_TYPE_INT64, dest_value, NULL);
+  gst_structure_id_set (query->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,
+      GST_QUARK (DEST_VALUE), G_TYPE_INT64, dest_value, NULL);
 }
 
 /**
  * gst_query_parse_convert:
  * @query: a #GstQuery
- * @src_format: the storage for the #GstFormat of the source value, or NULL
- * @src_value: the storage for the source value, or NULL
- * @dest_format: the storage for the #GstFormat of the destination value, or NULL
- * @dest_value: the storage for the destination value, or NULL
+ * @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
+ * @dest_format: (out) (allow-none): the storage for the #GstFormat of the
+ *     destination value, or NULL
+ * @dest_value: (out) (allow-none): the storage for the destination value,
+ *     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.
@@ -581,19 +684,21 @@ gst_query_parse_convert (GstQuery * query, GstFormat * src_format,
 
   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_CONVERT);
 
-  structure = gst_query_get_structure (query);
+  structure = query->structure;
   if (src_format)
     *src_format =
-        g_value_get_enum (gst_structure_get_value (structure, "src_format"));
+        (GstFormat) g_value_get_enum (gst_structure_id_get_value (structure,
+            GST_QUARK (SRC_FORMAT)));
   if (src_value)
-    *src_value =
-        g_value_get_int64 (gst_structure_get_value (structure, "src_value"));
+    *src_value = g_value_get_int64 (gst_structure_id_get_value (structure,
+            GST_QUARK (SRC_VALUE)));
   if (dest_format)
     *dest_format =
-        g_value_get_enum (gst_structure_get_value (structure, "dest_format"));
+        (GstFormat) g_value_get_enum (gst_structure_id_get_value (structure,
+            GST_QUARK (DEST_FORMAT)));
   if (dest_value)
-    *dest_value =
-        g_value_get_int64 (gst_structure_get_value (structure, "dest_value"));
+    *dest_value = g_value_get_int64 (gst_structure_id_get_value (structure,
+            GST_QUARK (DEST_VALUE)));
 }
 
 /**
@@ -604,7 +709,9 @@ gst_query_parse_convert (GstQuery * query, GstFormat * src_format,
  * when done with it. A segment query is used to discover information about the
  * currently configured segment for playback.
  *
- * Returns: a #GstQuery
+ * Free-function: gst_query_unref
+ *
+ * Returns: (transfer full): a new #GstQuery
  */
 GstQuery *
 gst_query_new_segment (GstFormat format)
@@ -612,8 +719,12 @@ gst_query_new_segment (GstFormat format)
   GstQuery *query;
   GstStructure *structure;
 
-  structure = gst_structure_new ("GstQuerySegment",
-      "format", GST_TYPE_FORMAT, format, NULL);
+  structure = gst_structure_id_new (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);
 
   return query;
@@ -627,34 +738,44 @@ gst_query_new_segment (GstFormat format)
  * @start_value: the start value
  * @stop_value: the stop value
  *
- * Answer a segment query by setting the requested values.
+ * Answer a segment query by setting the requested values. The normal
+ * playback segment of a pipeline is 0 to duration at the default rate of
+ * 1.0. If a seek was performed on the pipeline to play a different
+ * segment, this query will return the range specified in the last seek.
+ *
+ * @start_value and @stop_value will respectively contain the configured
+ * playback range start and stop values expressed in @format.
+ * The values are always between 0 and the duration of the media and
+ * @start_value <= @stop_value. @rate will contain the playback rate. For
+ * negative rates, playback will actually happen from @stop_value to
+ * @start_value.
  */
 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);
 
-  structure = gst_query_get_structure (query);
-  gst_structure_set (structure,
-      "rate", G_TYPE_DOUBLE, rate,
-      "format", GST_TYPE_FORMAT, format,
-      "start_value", G_TYPE_INT64, start_value,
-      "stop_value", G_TYPE_INT64, stop_value, NULL);
+  gst_structure_id_set (query->structure,
+      GST_QUARK (RATE), G_TYPE_DOUBLE, rate,
+      GST_QUARK (FORMAT), GST_TYPE_FORMAT, format,
+      GST_QUARK (START_VALUE), G_TYPE_INT64, start_value,
+      GST_QUARK (STOP_VALUE), G_TYPE_INT64, stop_value, NULL);
 }
 
 /**
  * gst_query_parse_segment:
  * @query: a #GstQuery
- * @rate: the storage for the rate of the segment, or NULL
- * @format: the storage for the #GstFormat of the values, or NULL
- * @start_value: the storage for the start value, or NULL
- * @stop_value: the storage for the stop value, 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
  *
- * Parse a segment query answer. Any of @rate, @format, @start_value, and 
+ * 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.
+ *
+ * See gst_query_set_segment() for an explanation of the function arguments.
  */
 void
 gst_query_parse_segment (GstQuery * query, gdouble * rate, GstFormat * format,
@@ -664,17 +785,20 @@ gst_query_parse_segment (GstQuery * query, gdouble * rate, GstFormat * format,
 
   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_SEGMENT);
 
-  structure = gst_query_get_structure (query);
+  structure = query->structure;
   if (rate)
-    *rate = g_value_get_double (gst_structure_get_value (structure, "rate"));
+    *rate = g_value_get_double (gst_structure_id_get_value (structure,
+            GST_QUARK (RATE)));
   if (format)
-    *format = g_value_get_enum (gst_structure_get_value (structure, "format"));
+    *format =
+        (GstFormat) g_value_get_enum (gst_structure_id_get_value (structure,
+            GST_QUARK (FORMAT)));
   if (start_value)
-    *start_value =
-        g_value_get_int64 (gst_structure_get_value (structure, "start_value"));
+    *start_value = g_value_get_int64 (gst_structure_id_get_value (structure,
+            GST_QUARK (START_VALUE)));
   if (stop_value)
-    *stop_value =
-        g_value_get_int64 (gst_structure_get_value (structure, "stop_value"));
+    *stop_value = g_value_get_int64 (gst_structure_id_get_value (structure,
+            GST_QUARK (STOP_VALUE)));
 }
 
 /**
@@ -685,7 +809,9 @@ gst_query_parse_segment (GstQuery * query, gdouble * rate, GstFormat * format,
  * Constructs a new custom application query object. Use gst_query_unref()
  * when done with it.
  *
- * Returns: a #GstQuery
+ * Free-function: gst_query_unref
+ *
+ * Returns: (transfer full): a new #GstQuery
  */
 GstQuery *
 gst_query_new_application (GstQueryType type, GstStructure * structure)
@@ -702,8 +828,9 @@ gst_query_new_application (GstQueryType type, GstStructure * structure)
  *
  * Get the structure of a query.
  *
- * Returns: The #GstStructure of the query. The structure is still owned
- * by the query and will therefore be freed when the query is unreffed.
+ * 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_get_structure (GstQuery * query)
@@ -714,13 +841,15 @@ gst_query_get_structure (GstQuery * query)
 }
 
 /**
- * gst_query_new_seeking (GstFormat *format)
+ * gst_query_new_seeking:
  * @format: the default #GstFormat for the new query
  *
  * Constructs a new query object for querying seeking properties of
- * the stream. 
+ * the stream.
  *
- * Returns: A #GstQuery
+ * Free-function: gst_query_unref
+ *
+ * Returns: (transfer full): a new #GstQuery
  */
 GstQuery *
 gst_query_new_seeking (GstFormat format)
@@ -728,11 +857,12 @@ gst_query_new_seeking (GstFormat format)
   GstQuery *query;
   GstStructure *structure;
 
-  structure = gst_structure_new ("GstQuerySeeking",
-      "format", GST_TYPE_FORMAT, format,
-      "seekable", G_TYPE_BOOLEAN, FALSE,
-      "segment-start", G_TYPE_INT64, (gint64) - 1,
-      "segment-end", G_TYPE_INT64, (gint64) - 1, NULL);
+  structure = gst_structure_id_new (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);
 
   return query;
@@ -752,27 +882,25 @@ 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);
+  gst_structure_id_set (query->structure,
+      GST_QUARK (FORMAT), GST_TYPE_FORMAT, format,
+      GST_QUARK (SEEKABLE), G_TYPE_BOOLEAN, seekable,
+      GST_QUARK (SEGMENT_START), G_TYPE_INT64, segment_start,
+      GST_QUARK (SEGMENT_END), G_TYPE_INT64, segment_end, NULL);
 }
 
 /**
  * gst_query_parse_seeking:
  * @query: a GST_QUERY_SEEKING type query #GstQuery
- * @format: the format to set for the @segment_start and @segment_end values
- * @seekable: the seekable flag to set
- * @segment_start: the segment_start to set
- * @segment_end: the segment_end to set
+ * @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
  *
- * Parse a seeking query, writing the format into @format, and 
+ * Parse a seeking query, writing the format into @format, and
  * other results into the passed parameters, if the respective parameters
  * are non-NULL
  */
@@ -784,28 +912,31 @@ gst_query_parse_seeking (GstQuery * query, GstFormat * format,
 
   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_SEEKING);
 
-  structure = gst_query_get_structure (query);
+  structure = query->structure;
   if (format)
-    *format = g_value_get_enum (gst_structure_get_value (structure, "format"));
+    *format =
+        (GstFormat) g_value_get_enum (gst_structure_id_get_value (structure,
+            GST_QUARK (FORMAT)));
   if (seekable)
-    *seekable =
-        g_value_get_boolean (gst_structure_get_value (structure, "seekable"));
+    *seekable = g_value_get_boolean (gst_structure_id_get_value (structure,
+            GST_QUARK (SEEKABLE)));
   if (segment_start)
-    *segment_start =
-        g_value_get_int64 (gst_structure_get_value (structure,
-            "segment-start"));
+    *segment_start = g_value_get_int64 (gst_structure_id_get_value (structure,
+            GST_QUARK (SEGMENT_START)));
   if (segment_end)
-    *segment_end =
-        g_value_get_int64 (gst_structure_get_value (structure, "segment-end"));
+    *segment_end = g_value_get_int64 (gst_structure_id_get_value (structure,
+            GST_QUARK (SEGMENT_END)));
 }
 
 /**
  * gst_query_new_formats:
  *
  * Constructs a new query object for querying formats of
- * the stream. 
+ * the stream.
  *
- * Returns: A #GstQuery
+ * Free-function: gst_query_unref
+ *
+ * Returns: (transfer full): a new #GstQuery
  *
  * Since: 0.10.4
  */
@@ -815,7 +946,7 @@ gst_query_new_formats (void)
   GstQuery *query;
   GstStructure *structure;
 
-  structure = gst_structure_new ("GstQueryFormats", NULL);
+  structure = gst_structure_id_empty_new (GST_QUARK (QUERY_FORMATS));
   query = gst_query_new (GST_QUERY_FORMATS, structure);
 
   return query;
@@ -846,7 +977,6 @@ gst_query_set_formats (GstQuery * query, gint n_formats, ...)
 {
   va_list ap;
   GValue list = { 0, };
-  GstStructure *structure;
   gint i;
 
   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_FORMATS);
@@ -859,15 +989,18 @@ gst_query_set_formats (GstQuery * query, gint n_formats, ...)
   }
   va_end (ap);
 
-  structure = gst_query_get_structure (query);
-  gst_structure_set_value (structure, "formats", &list);
+  gst_structure_set_value (query->structure, "formats", &list);
+
+  g_value_unset (&list);
+
 }
 
 /**
  * gst_query_set_formatsv:
  * @query: a #GstQuery
  * @n_formats: the number of formats to set.
- * @formats: An array containing @n_formats @GstFormat values.
+ * @formats: (in) (array length=n_formats): an array containing @n_formats
+ *     @GstFormat values.
  *
  * Set the formats query result fields in @query. The number of formats passed
  * in the @formats array must be equal to @n_formats.
@@ -875,10 +1008,10 @@ gst_query_set_formats (GstQuery * query, gint n_formats, ...)
  * Since: 0.10.4
  */
 void
-gst_query_set_formatsv (GstQuery * query, gint n_formats, GstFormat * formats)
+gst_query_set_formatsv (GstQuery * query, gint n_formats,
+    const GstFormat * formats)
 {
   GValue list = { 0, };
-  GstStructure *structure;
   gint i;
 
   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_FORMATS);
@@ -887,31 +1020,29 @@ gst_query_set_formatsv (GstQuery * query, gint n_formats, GstFormat * formats)
   for (i = 0; i < n_formats; i++) {
     gst_query_list_add_format (&list, formats[i]);
   }
-  structure = gst_query_get_structure (query);
-  gst_structure_set_value (structure, "formats", &list);
+  gst_structure_set_value (query->structure, "formats", &list);
+
+  g_value_unset (&list);
 }
 
 /**
  * gst_query_parse_formats_length:
  * @query: a #GstQuery
- * @n_formats: the number of formats in this query.
+ * @n_formats: (out): the number of formats in this query.
  *
- * Parse the number of formats in the formats @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)
 {
-  GstStructure *structure;
-
   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_FORMATS);
 
   if (n_formats) {
     const GValue *list;
 
-    structure = gst_query_get_structure (query);
-    list = gst_structure_get_value (structure, "formats");
+    list = gst_structure_get_value (query->structure, "formats");
     if (list == NULL)
       *n_formats = 0;
     else
@@ -922,10 +1053,10 @@ gst_query_parse_formats_length (GstQuery * query, guint * n_formats)
 /**
  * gst_query_parse_formats_nth:
  * @query: a #GstQuery
- * @nth: the nth format to retrieve.
- * @format: a pointer to store the nth format
+ * @nth: (out): the nth format to retrieve.
+ * @format: (out): a pointer to store the nth format
  *
- * Parse the format query and retrieve the @nth format from it into 
+ * 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.
  *
@@ -934,22 +1065,569 @@ gst_query_parse_formats_length (GstQuery * query, guint * n_formats)
 void
 gst_query_parse_formats_nth (GstQuery * query, guint nth, GstFormat * format)
 {
-  GstStructure *structure;
-
   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_FORMATS);
 
   if (format) {
     const GValue *list;
 
-    structure = gst_query_get_structure (query);
-    list = gst_structure_get_value (structure, "formats");
+    list = gst_structure_get_value (query->structure, "formats");
     if (list == NULL) {
       *format = GST_FORMAT_UNDEFINED;
     } else {
       if (nth < gst_value_list_get_size (list)) {
-        *format = g_value_get_enum (gst_value_list_get_value (list, nth));
+        *format =
+            (GstFormat) g_value_get_enum (gst_value_list_get_value (list, nth));
       } else
         *format = GST_FORMAT_UNDEFINED;
     }
   }
 }
+
+/**
+ * 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
+ *
+ * Returns: (transfer full): a new #GstQuery
+ *
+ * Since: 0.10.20
+ */
+GstQuery *
+gst_query_new_buffering (GstFormat format)
+{
+  GstQuery *query;
+  GstStructure *structure;
+
+  /* by default, we configure the answer as no buffering with a 100% buffering
+   * progress */
+  structure = gst_structure_id_new (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,
+      GST_QUARK (AVG_IN_RATE), G_TYPE_INT, -1,
+      GST_QUARK (AVG_OUT_RATE), G_TYPE_INT, -1,
+      GST_QUARK (BUFFERING_LEFT), G_TYPE_INT64, G_GINT64_CONSTANT (0),
+      GST_QUARK (ESTIMATED_TOTAL), G_TYPE_INT64, G_GINT64_CONSTANT (-1),
+      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_BUFFERING, structure);
+
+  return query;
+}
+
+/**
+ * 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)
+{
+  g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_BUFFERING);
+  g_return_if_fail (percent >= 0 && percent <= 100);
+
+  gst_structure_id_set (query->structure,
+      GST_QUARK (BUSY), G_TYPE_BOOLEAN, busy,
+      GST_QUARK (BUFFER_PERCENT), G_TYPE_INT, percent, NULL);
+}
+
+/**
+ * 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
+ *
+ * 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)
+{
+  g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_BUFFERING);
+
+  if (busy)
+    *busy = g_value_get_boolean (gst_structure_id_get_value (query->structure,
+            GST_QUARK (BUSY)));
+  if (percent)
+    *percent = g_value_get_int (gst_structure_id_get_value (query->structure,
+            GST_QUARK (BUFFER_PERCENT)));
+}
+
+/**
+ * gst_query_set_buffering_stats:
+ * @query: A valid #GstQuery of type GST_QUERY_BUFFERING.
+ * @mode: a buffering mode
+ * @avg_in: the average input rate
+ * @avg_out: the average output rate
+ * @buffering_left: amount of buffering time left
+ *
+ * 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)
+{
+  g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_BUFFERING);
+
+  gst_structure_id_set (query->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,
+      GST_QUARK (BUFFERING_LEFT), G_TYPE_INT64, buffering_left, NULL);
+}
+
+/**
+ * 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
+ *
+ * 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)
+{
+  g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_BUFFERING);
+
+  if (mode)
+    *mode = (GstBufferingMode)
+        g_value_get_enum (gst_structure_id_get_value (query->structure,
+            GST_QUARK (BUFFERING_MODE)));
+  if (avg_in)
+    *avg_in = g_value_get_int (gst_structure_id_get_value (query->structure,
+            GST_QUARK (AVG_IN_RATE)));
+  if (avg_out)
+    *avg_out = g_value_get_int (gst_structure_id_get_value (query->structure,
+            GST_QUARK (AVG_OUT_RATE)));
+  if (buffering_left)
+    *buffering_left =
+        g_value_get_int64 (gst_structure_id_get_value (query->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
+ *
+ * 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)
+{
+  g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_BUFFERING);
+
+  gst_structure_id_set (query->structure,
+      GST_QUARK (FORMAT), GST_TYPE_FORMAT, format,
+      GST_QUARK (START_VALUE), G_TYPE_INT64, start,
+      GST_QUARK (STOP_VALUE), G_TYPE_INT64, stop,
+      GST_QUARK (ESTIMATED_TOTAL), G_TYPE_INT64, estimated_total, NULL);
+}
+
+/**
+ * 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
+ * @estimated_total: (out) (allow-none): estimated total amount of download
+ *     time, 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
+ */
+void
+gst_query_parse_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);
+
+  structure = query->structure;
+  if (format)
+    *format =
+        (GstFormat) g_value_get_enum (gst_structure_id_get_value (structure,
+            GST_QUARK (FORMAT)));
+  if (start)
+    *start = g_value_get_int64 (gst_structure_id_get_value (structure,
+            GST_QUARK (START_VALUE)));
+  if (stop)
+    *stop = g_value_get_int64 (gst_structure_id_get_value (structure,
+            GST_QUARK (STOP_VALUE)));
+  if (estimated_total)
+    *estimated_total =
+        g_value_get_int64 (gst_structure_id_get_value (structure,
+            GST_QUARK (ESTIMATED_TOTAL)));
+}
+
+/**
+ * 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
+ *
+ * Set the buffering-ranges array field in @query. The current last
+ * 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 };
+
+  g_return_val_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_BUFFERING, 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, };
+
+    array = g_value_array_new (0);
+
+    g_value_init (&new_array_val, G_TYPE_VALUE_ARRAY);
+    g_value_take_boxed (&new_array_val, array);
+
+    /* 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);
+  }
+
+  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 */
+
+  return TRUE;
+}
+
+/**
+ * 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;
+
+  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;
+}
+
+
+/**
+ * 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
+ *
+ * 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;
+  }
+
+  return ret;
+}
+
+
+/**
+ * gst_query_new_uri:
+ *
+ * Constructs a new query URI query object. Use gst_query_unref()
+ * when done with it. An URI query is used to query the current URI
+ * that is used by the source or sink.
+ *
+ * Free-function: gst_query_unref
+ *
+ * Returns: (transfer full): a new #GstQuery
+ *
+ * Since: 0.10.22
+ */
+GstQuery *
+gst_query_new_uri (void)
+{
+  GstQuery *query;
+  GstStructure *structure;
+
+  structure = gst_structure_id_new (GST_QUARK (QUERY_URI),
+      GST_QUARK (URI), G_TYPE_STRING, NULL, NULL);
+
+  query = gst_query_new (GST_QUERY_URI, structure);
+
+  return query;
+}
+
+/**
+ * gst_query_set_uri:
+ * @query: a #GstQuery with query type GST_QUERY_URI
+ * @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)
+{
+  g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_URI);
+  g_return_if_fail (gst_uri_is_valid (uri));
+
+  gst_structure_id_set (query->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)
+ *
+ * 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.22
+ */
+void
+gst_query_parse_uri (GstQuery * query, gchar ** uri)
+{
+  g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_URI);
+
+  if (uri)
+    *uri = g_value_dup_string (gst_structure_id_get_value (query->structure,
+            GST_QUARK (URI)));
+}
+
+/**
+ * gst_query_new_buffers:
+ * @caps: the #GstCaps for the buffers that are going to be allocated
+ *
+ * Constructs a new buffer requirements query object to query buffer
+ * requirements for a particular caps.  Use gst_query_unref() when done
+ * with it.
+ *
+ * Returns: A #GstQuery
+ */
+GstQuery *
+gst_query_new_buffers (GstCaps * caps)
+{
+  GstQuery *query;
+  GstStructure *structure;
+
+  /* XXX could add size here, for linear (non YUV/RGB) buffers?  But I'm not
+   * entirely sure what is the use-case for that.. it should be easy enough
+   * to add more optional reply fields later
+   */
+  structure = gst_structure_id_new (GST_QUARK (QUERY_BUFFERS),
+      GST_QUARK (CAPS), GST_TYPE_CAPS, caps,
+      GST_QUARK (COUNT), G_TYPE_INT, -1,
+      GST_QUARK (WIDTH), G_TYPE_INT, -1,
+      GST_QUARK (HEIGHT), G_TYPE_INT, -1, NULL);
+
+  query = gst_query_new (GST_QUERY_BUFFERS, structure);
+
+  return query;
+}
+
+/**
+ * gst_query_set_buffers_count:
+ * @count: minimum number of buffers required
+ *
+ * Answer a buffers query by setting the minimum number of buffers required.
+ * If there is no minimum buffer count requirement, don't set this field in
+ * the query.
+ */
+void
+gst_query_set_buffers_count (GstQuery * query, gint count)
+{
+  GstStructure *structure;
+
+  g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_BUFFERS);
+
+  structure = gst_query_get_structure (query);
+  gst_structure_id_set (structure, GST_QUARK (COUNT), G_TYPE_INT, count, NULL);
+}
+
+/**
+ * gst_query_set_buffers_dimensions:
+ * @width: minimum buffer width
+ * @height: minimum buffer height
+ *
+ * Answer a buffers query by setting the minimum buffer dimensions required.
+ * If there is no minimum buffer dimensions (beyond the width/height specified
+ * in the #GstCaps), don't set this field in the query.
+ */
+void
+gst_query_set_buffers_dimensions (GstQuery * query, gint width, gint height)
+{
+  GstStructure *structure;
+
+  g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_BUFFERS);
+
+  structure = gst_query_get_structure (query);
+  gst_structure_id_set (structure,
+      GST_QUARK (WIDTH), G_TYPE_INT, width,
+      GST_QUARK (HEIGHT), G_TYPE_INT, height, NULL);
+}
+
+/**
+ * gst_query_parse_buffers_caps:
+ * @query: a #GstQuery
+ * @caps: the storage for the #GstCaps pointer, or NULL
+ *
+ * Parse a buffers query.
+ */
+void
+gst_query_parse_buffers_caps (GstQuery * query, const GstCaps ** caps)
+{
+  GstStructure *structure;
+
+  g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_BUFFERS);
+
+  structure = gst_query_get_structure (query);
+  if (caps)
+    *caps = gst_value_get_caps (gst_structure_id_get_value (structure,
+            GST_QUARK (CAPS)));
+}
+
+/**
+ * gst_query_parse_buffers_count:
+ * @query: a #GstQuery
+ * @count: the storage for minimum number of buffers, or NULL
+ *
+ * Parse a buffers query answer to see the minimum number of buffers
+ * required.  A returned value of -1 means there is no minimum requirement
+ */
+void
+gst_query_parse_buffers_count (GstQuery * query, gint * count)
+{
+  GstStructure *structure;
+
+  g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_BUFFERS);
+
+  structure = gst_query_get_structure (query);
+  if (count)
+    *count = g_value_get_int (gst_structure_id_get_value (structure,
+            GST_QUARK (COUNT)));
+}
+
+/**
+ * gst_query_parse_buffers_dimensions:
+ * @query: a #GstQuery
+ * @width: the storage for minimum width, or NULL
+ * @height: the storage for minimum height, or NULL
+ *
+ * Parse a buffers query answer to see the minimum buffer dimensions required.
+ * A returned value of -1 for either dimension means there is no minimum
+ * requirement in that axis
+ */
+void
+gst_query_parse_buffers_dimensions (GstQuery * query, gint * width,
+    gint * height)
+{
+  GstStructure *structure;
+
+  g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_BUFFERS);
+
+  structure = gst_query_get_structure (query);
+  if (width)
+    *width = g_value_get_int (gst_structure_id_get_value (structure,
+            GST_QUARK (WIDTH)));
+  if (height)
+    *height = g_value_get_int (gst_structure_id_get_value (structure,
+            GST_QUARK (HEIGHT)));
+}