Revert "gst/parse: define pure-parser depending on bison version"
[platform/upstream/gstreamer.git] / gst / gstquery.c
index 53b4cf9..1a82747 100644 (file)
  *
  * 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.
+ * @title: GstQuery
+ * @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.
  * 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)
- */
-
-
-/* FIXME 0.11: suppress warnings for deprecated API such as GValueArray
- * with newer GLib versions (>= 2.31.0) */
-#define GLIB_DISABLE_DEPRECATION_WARNINGS
+ * |[<!-- language="C" -->
+ *   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);
+ * ]|
+ */
+
 
 #include "gst_private.h"
 #include "gstinfo.h"
 #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}
+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},
+  {GST_QUERY_BITRATE, "bitrate", 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);
+#ifdef USE_POISONING
+  memset (query, 0xff, sizeof (GstQueryImpl));
+#endif
 
-  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;
 }
 
 /**
@@ -389,7 +226,7 @@ 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.
  *
- * Free-function: gst_query_unref
+ * Free-function: gst_query_unref()
  *
  * Returns: (transfer full): a new #GstQuery
  */
@@ -399,11 +236,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 +256,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 +273,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 +286,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,
@@ -462,7 +305,7 @@ gst_query_parse_position (GstQuery * query, GstFormat * format, gint64 * cur)
  * Use gst_query_unref() when done with it. A duration query will give the
  * total length of the stream.
  *
- * Free-function: gst_query_unref
+ * Free-function: gst_query_unref()
  *
  * Returns: (transfer full): a new #GstQuery
  */
@@ -472,11 +315,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 +335,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 +350,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 +364,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,
@@ -535,11 +382,9 @@ gst_query_parse_duration (GstQuery * query, GstFormat * format,
  * by sinks to compensate for additional latency introduced by elements in the
  * pipeline.
  *
- * Free-function: gst_query_unref
+ * Free-function: gst_query_unref()
  *
  * Returns: (transfer full): a #GstQuery
- *
- * Since: 0.10.12
  */
 GstQuery *
 gst_query_new_latency (void)
@@ -547,12 +392,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);
+      GST_QUARK (MAX_LATENCY), G_TYPE_UINT64, GST_CLOCK_TIME_NONE, NULL);
 
-  query = gst_query_new (GST_QUERY_LATENCY, structure);
+  query = gst_query_new_custom (GST_QUERY_LATENCY, structure);
 
   return query;
 }
@@ -561,20 +406,22 @@ 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);
+  g_return_if_fail (GST_CLOCK_TIME_IS_VALID (min_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 +430,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 +444,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,
@@ -622,7 +467,7 @@ gst_query_parse_latency (GstQuery * query, gboolean * live,
  * when done with it. A convert query is used to ask for a conversion between
  * one format and another.
  *
- * Free-function: gst_query_unref
+ * Free-function: gst_query_unref()
  *
  * Returns: (transfer full): a #GstQuery
  */
@@ -633,13 +478,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 +503,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 +519,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 +537,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,
@@ -714,7 +562,7 @@ 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.
  *
- * Free-function: gst_query_unref
+ * Free-function: gst_query_unref()
  *
  * Returns: (transfer full): a new #GstQuery
  */
@@ -724,13 +572,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 +607,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 +622,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 +641,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,24 +658,49 @@ 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
+ * Free-function: gst_query_unref()
  *
- * Returns: (transfer full): a new #GstQuery
+ * Returns: (transfer full) (nullable): 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);
 
-  return gst_query_new (type, structure);
+  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;
+  }
+
+  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;
+  }
 }
 
 /**
@@ -833,16 +709,47 @@ gst_query_new_application (GstQueryType type, GstStructure * structure)
  *
  * Get the structure of a query.
  *
+ * Returns: (transfer none) (nullable): the #GstStructure of the query. The
+ *     structure is still owned by the query and will therefore be freed when the
+ *     query is unreffed.
+ */
+const GstStructure *
+gst_query_get_structure (GstQuery * query)
+{
+  g_return_val_if_fail (GST_IS_QUERY (query), NULL);
+
+  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_get_structure (GstQuery * query)
+gst_query_writable_structure (GstQuery * query)
 {
+  GstStructure *structure;
+
   g_return_val_if_fail (GST_IS_QUERY (query), NULL);
+  g_return_val_if_fail (gst_query_is_writable (query), NULL);
+
+  structure = GST_QUERY_STRUCTURE (query);
 
-  return query->structure;
+  if (structure == NULL) {
+    structure =
+        gst_structure_new_id_empty (gst_query_type_to_quark (GST_QUERY_TYPE
+            (query)));
+    gst_structure_set_parent_refcount (structure, &query->mini_object.refcount);
+    GST_QUERY_STRUCTURE (query) = structure;
+  }
+  return structure;
 }
 
 /**
@@ -852,7 +759,7 @@ gst_query_get_structure (GstQuery * query)
  * Constructs a new query object for querying seeking properties of
  * the stream.
  *
- * Free-function: gst_query_unref
+ * Free-function: gst_query_unref()
  *
  * Returns: (transfer full): a new #GstQuery
  */
@@ -862,13 +769,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 +794,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 +811,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 +828,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,17 +844,40 @@ 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:
  *
  * Constructs a new query object for querying formats of
  * the stream.
  *
- * Free-function: gst_query_unref
+ * Free-function: gst_query_unref()
  *
  * Returns: (transfer full): a new #GstQuery
- *
- * Since: 0.10.4
  */
 GstQuery *
 gst_query_new_formats (void)
@@ -951,8 +885,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 +917,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 +930,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 +946,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 +953,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 +995,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
+ * @nth: the nth format to retrieve.
+ * @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 +1029,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 +1047,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 +1059,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 +1120,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 +1144,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 +1210,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 +1228,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 +1245,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 +1262,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;
 }
 
 
@@ -1436,11 +1367,9 @@ gst_query_parse_nth_buffering_range (GstQuery * query, guint index,
  * 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
+ * Free-function: gst_query_unref()
  *
  * Returns: (transfer full): a new #GstQuery
- *
- * Since: 0.10.22
  */
 GstQuery *
 gst_query_new_uri (void)
@@ -1448,10 +1377,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 +1391,1339 @@ 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.
+ *
+ * Pool details can be retrieved using gst_query_get_n_allocation_pools() and
+ * gst_query_parse_nth_allocation_pool().
+ */
+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: (transfer none) (allow-none): the #GstBufferPool
+ * @size: the buffer 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));
+
+  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 buffer 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: (transfer none) (allow-none): the #GstBufferPool
+ * @size: the buffer 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 parameters
+ *
+ * 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 parameters
+ * 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: (out) (allow-none): 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;
+
+  g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_ACCEPT_CAPS);
+
+  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;
 
-  structure = gst_query_get_structure (query);
+  g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_CAPS);
+  g_return_if_fail (gst_query_is_writable (query));
 
-  g_return_if_fail (structure != NULL);
+  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;
+
+  g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_CONTEXT);
+
+  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;
+}
+
+/**
+ * gst_query_new_bitrate:
+ *
+ * Constructs a new query object for querying the bitrate.
+ *
+ * Free-function: gst_query_unref()
+ *
+ * Returns: (transfer full): a new #GstQuery
+ *
+ * Since: 1.16
+ */
+GstQuery *
+gst_query_new_bitrate (void)
+{
+  GstQuery *query;
+  GstStructure *structure;
+
+  structure = gst_structure_new_id_empty (GST_QUARK (QUERY_BITRATE));
+  query = gst_query_new_custom (GST_QUERY_BITRATE, structure);
+
+  return query;
+}
+
+/**
+ * gst_query_set_bitrate:
+ * @query: a GST_QUERY_BITRATE type #GstQuery
+ * @nominal_bitrate: the nominal bitrate in bits per second
+ *
+ * Set the results of a bitrate query.  The nominal bitrate is the average
+ * bitrate expected over the length of the stream as advertised in file
+ * headers (or similar).
+ *
+ * Since: 1.16
+ */
+void
+gst_query_set_bitrate (GstQuery * query, guint nominal_bitrate)
+{
+  GstStructure *s;
+
+  g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_BITRATE);
+
+  s = GST_QUERY_STRUCTURE (query);
+
+  gst_structure_id_set (s,
+      GST_QUARK (NOMINAL_BITRATE), G_TYPE_UINT, nominal_bitrate, NULL);
+}
+
+/**
+ * gst_query_parse_bitrate:
+ * @query: a GST_QUERY_BITRATE type #GstQuery
+ * @nominal_bitrate: (out) (allow-none): The resulting bitrate in bits per second
+ *
+ * Get the results of a bitrate query. See also gst_query_set_bitrate().
+ *
+ * Since: 1.16
+ */
+void
+gst_query_parse_bitrate (GstQuery * query, guint * nominal_bitrate)
+{
+  GstStructure *structure;
+  const GValue *value;
 
-  if (toc != NULL)
-    *toc = _gst_toc_from_structure (structure);
+  g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_BITRATE);
 
-  if (extend_uid != NULL)
-    *extend_uid = _gst_toc_structure_get_extend_uid (structure);
+  structure = GST_QUERY_STRUCTURE (query);
+
+  if (nominal_bitrate) {
+    value = gst_structure_id_get_value (structure, GST_QUARK (NOMINAL_BITRATE));
+    *nominal_bitrate = g_value_get_uint (value);
+  }
 }