• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* GStreamer
2  * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
3  *                    2000 Wim Taymans <wim.taymans@chello.be>
4  *                    2005 Wim Taymans <wim@fluendo.com>
5  *
6  * gstquery.c: GstQueryType registration and Query parsing/creation
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Library General Public
10  * License as published by the Free Software Foundation; either
11  * version 2 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Library General Public License for more details.
17  *
18  * You should have received a copy of the GNU Library General Public
19  * License along with this library; if not, write to the
20  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
21  * Boston, MA 02110-1301, USA.
22  */
23 
24 /**
25  * SECTION:gstquery
26  * @title: GstQuery
27  * @short_description: Provide functions to create queries, and to set and parse
28  *                     values in them.
29  * @see_also: #GstPad, #GstElement
30  *
31  * Queries can be performed on pads (gst_pad_query()) and elements
32  * (gst_element_query()). Please note that some queries might need a running
33  * pipeline to work.
34  *
35  * Queries can be created using the gst_query_new_*() functions.
36  * Query values can be set using gst_query_set_*(), and parsed using
37  * gst_query_parse_*() helpers.
38  *
39  * The following example shows how to query the duration of a pipeline:
40  * |[<!-- language="C" -->
41  *   GstQuery *query;
42  *   gboolean res;
43  *   query = gst_query_new_duration (GST_FORMAT_TIME);
44  *   res = gst_element_query (pipeline, query);
45  *   if (res) {
46  *     gint64 duration;
47  *     gst_query_parse_duration (query, NULL, &duration);
48  *     g_print ("duration = %"GST_TIME_FORMAT, GST_TIME_ARGS (duration));
49  *   } else {
50  *     g_print ("duration query failed...");
51  *   }
52  *   gst_query_unref (query);
53  * ]|
54  */
55 
56 #define GST_DISABLE_MINIOBJECT_INLINE_FUNCTIONS
57 #include "gst_private.h"
58 #include "gstinfo.h"
59 #include "gstquery.h"
60 #include "gstvalue.h"
61 #include "gstenumtypes.h"
62 #include "gstquark.h"
63 #include "gsturi.h"
64 #include "gstbufferpool.h"
65 
66 GST_DEBUG_CATEGORY_STATIC (gst_query_debug);
67 #define GST_CAT_DEFAULT gst_query_debug
68 
69 GType _gst_query_type = 0;
70 
71 typedef struct
72 {
73   GstQuery query;
74 
75   GstStructure *structure;
76 } GstQueryImpl;
77 
78 #define GST_QUERY_STRUCTURE(q)  (((GstQueryImpl *)(q))->structure)
79 
80 
81 typedef struct
82 {
83   const gint type;
84   const gchar *name;
85   GQuark quark;
86 } GstQueryQuarks;
87 
88 static GstQueryQuarks query_quarks[] = {
89   {GST_QUERY_UNKNOWN, "unknown", 0},
90   {GST_QUERY_POSITION, "position", 0},
91   {GST_QUERY_DURATION, "duration", 0},
92   {GST_QUERY_LATENCY, "latency", 0},
93   {GST_QUERY_JITTER, "jitter", 0},
94   {GST_QUERY_RATE, "rate", 0},
95   {GST_QUERY_SEEKING, "seeking", 0},
96   {GST_QUERY_SEGMENT, "segment", 0},
97   {GST_QUERY_CONVERT, "convert", 0},
98   {GST_QUERY_FORMATS, "formats", 0},
99   {GST_QUERY_BUFFERING, "buffering", 0},
100   {GST_QUERY_CUSTOM, "custom", 0},
101   {GST_QUERY_URI, "uri", 0},
102   {GST_QUERY_ALLOCATION, "allocation", 0},
103   {GST_QUERY_SCHEDULING, "scheduling", 0},
104   {GST_QUERY_ACCEPT_CAPS, "accept-caps", 0},
105   {GST_QUERY_CAPS, "caps", 0},
106   {GST_QUERY_DRAIN, "drain", 0},
107   {GST_QUERY_CONTEXT, "context", 0},
108   {GST_QUERY_BITRATE, "bitrate", 0},
109 
110   {0, NULL, 0}
111 };
112 
113 GST_DEFINE_MINI_OBJECT_TYPE (GstQuery, gst_query);
114 
115 void
_priv_gst_query_initialize(void)116 _priv_gst_query_initialize (void)
117 {
118   gint i;
119 
120   _gst_query_type = gst_query_get_type ();
121 
122   GST_DEBUG_CATEGORY_INIT (gst_query_debug, "query", 0, "query system");
123 
124   for (i = 0; query_quarks[i].name; i++) {
125     query_quarks[i].quark = g_quark_from_static_string (query_quarks[i].name);
126   }
127 }
128 
129 /**
130  * gst_query_type_get_name:
131  * @type: the query type
132  *
133  * Get a printable name for the given query type. Do not modify or free.
134  *
135  * Returns: a reference to the static name of the query.
136  */
137 const gchar *
gst_query_type_get_name(GstQueryType type)138 gst_query_type_get_name (GstQueryType type)
139 {
140   gint i;
141 
142   for (i = 0; query_quarks[i].name; i++) {
143     if (type == query_quarks[i].type)
144       return query_quarks[i].name;
145   }
146   return "unknown";
147 }
148 
149 /**
150  * gst_query_type_to_quark:
151  * @type: the query type
152  *
153  * Get the unique quark for the given query type.
154  *
155  * Returns: the quark associated with the query type
156  */
157 GQuark
gst_query_type_to_quark(GstQueryType type)158 gst_query_type_to_quark (GstQueryType type)
159 {
160   gint i;
161 
162   for (i = 0; query_quarks[i].name; i++) {
163     if (type == query_quarks[i].type)
164       return query_quarks[i].quark;
165   }
166   return 0;
167 }
168 
169 /**
170  * gst_query_type_get_flags:
171  * @type: a #GstQueryType
172  *
173  * Gets the #GstQueryTypeFlags associated with @type.
174  *
175  * Returns: a #GstQueryTypeFlags.
176  */
177 GstQueryTypeFlags
gst_query_type_get_flags(GstQueryType type)178 gst_query_type_get_flags (GstQueryType type)
179 {
180   GstQueryTypeFlags ret;
181 
182   ret = type & ((1 << GST_QUERY_NUM_SHIFT) - 1);
183 
184   return ret;
185 }
186 
187 static void
_gst_query_free(GstQuery * query)188 _gst_query_free (GstQuery * query)
189 {
190   GstStructure *s;
191 
192   g_return_if_fail (query != NULL);
193 
194   s = GST_QUERY_STRUCTURE (query);
195   if (s) {
196     gst_structure_set_parent_refcount (s, NULL);
197     gst_structure_free (s);
198   }
199 #ifdef USE_POISONING
200   memset (query, 0xff, sizeof (GstQueryImpl));
201 #endif
202 
203   g_slice_free1 (sizeof (GstQueryImpl), query);
204 }
205 
206 static GstQuery *
_gst_query_copy(GstQuery * query)207 _gst_query_copy (GstQuery * query)
208 {
209   GstQuery *copy;
210   GstStructure *s;
211 
212   s = GST_QUERY_STRUCTURE (query);
213   if (s) {
214     s = gst_structure_copy (s);
215   }
216   copy = gst_query_new_custom (query->type, s);
217 
218   return copy;
219 }
220 
221 /**
222  * gst_query_new_position:
223  * @format: the default #GstFormat for the new query
224  *
225  * Constructs a new query stream position query object. Use gst_query_unref()
226  * when done with it. A position query is used to query the current position
227  * of playback in the streams, in some format.
228  *
229  * Free-function: gst_query_unref()
230  *
231  * Returns: (transfer full): a new #GstQuery
232  */
233 GstQuery *
gst_query_new_position(GstFormat format)234 gst_query_new_position (GstFormat format)
235 {
236   GstQuery *query;
237   GstStructure *structure;
238 
239   structure = gst_structure_new_id (GST_QUARK (QUERY_POSITION),
240       GST_QUARK (FORMAT), GST_TYPE_FORMAT, format,
241       GST_QUARK (CURRENT), G_TYPE_INT64, G_GINT64_CONSTANT (-1), NULL);
242 
243   query = gst_query_new_custom (GST_QUERY_POSITION, structure);
244 
245   return query;
246 }
247 
248 /**
249  * gst_query_set_position:
250  * @query: a #GstQuery with query type GST_QUERY_POSITION
251  * @format: the requested #GstFormat
252  * @cur: the position to set
253  *
254  * Answer a position query by setting the requested value in the given format.
255  */
256 void
gst_query_set_position(GstQuery * query,GstFormat format,gint64 cur)257 gst_query_set_position (GstQuery * query, GstFormat format, gint64 cur)
258 {
259   GstStructure *s;
260 
261   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_POSITION);
262 
263   s = GST_QUERY_STRUCTURE (query);
264   g_return_if_fail (format == g_value_get_enum (gst_structure_id_get_value (s,
265               GST_QUARK (FORMAT))));
266 
267   gst_structure_id_set (s,
268       GST_QUARK (FORMAT), GST_TYPE_FORMAT, format,
269       GST_QUARK (CURRENT), G_TYPE_INT64, cur, NULL);
270 }
271 
272 /**
273  * gst_query_parse_position:
274  * @query: a #GstQuery
275  * @format: (out) (allow-none): the storage for the #GstFormat of the
276  *     position values (may be %NULL)
277  * @cur: (out) (allow-none): the storage for the current position (may be %NULL)
278  *
279  * Parse a position query, writing the format into @format, and the position
280  * into @cur, if the respective parameters are non-%NULL.
281  */
282 void
gst_query_parse_position(GstQuery * query,GstFormat * format,gint64 * cur)283 gst_query_parse_position (GstQuery * query, GstFormat * format, gint64 * cur)
284 {
285   GstStructure *structure;
286 
287   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_POSITION);
288 
289   structure = GST_QUERY_STRUCTURE (query);
290   if (format)
291     *format =
292         (GstFormat) g_value_get_enum (gst_structure_id_get_value (structure,
293             GST_QUARK (FORMAT)));
294   if (cur)
295     *cur = g_value_get_int64 (gst_structure_id_get_value (structure,
296             GST_QUARK (CURRENT)));
297 }
298 
299 
300 /**
301  * gst_query_new_duration:
302  * @format: the #GstFormat for this duration query
303  *
304  * Constructs a new stream duration query object to query in the given format.
305  * Use gst_query_unref() when done with it. A duration query will give the
306  * total length of the stream.
307  *
308  * Free-function: gst_query_unref()
309  *
310  * Returns: (transfer full): a new #GstQuery
311  */
312 GstQuery *
gst_query_new_duration(GstFormat format)313 gst_query_new_duration (GstFormat format)
314 {
315   GstQuery *query;
316   GstStructure *structure;
317 
318   structure = gst_structure_new_id (GST_QUARK (QUERY_DURATION),
319       GST_QUARK (FORMAT), GST_TYPE_FORMAT, format,
320       GST_QUARK (DURATION), G_TYPE_INT64, G_GINT64_CONSTANT (-1), NULL);
321 
322   query = gst_query_new_custom (GST_QUERY_DURATION, structure);
323 
324   return query;
325 }
326 
327 /**
328  * gst_query_set_duration:
329  * @query: a #GstQuery
330  * @format: the #GstFormat for the duration
331  * @duration: the duration of the stream
332  *
333  * Answer a duration query by setting the requested value in the given format.
334  */
335 void
gst_query_set_duration(GstQuery * query,GstFormat format,gint64 duration)336 gst_query_set_duration (GstQuery * query, GstFormat format, gint64 duration)
337 {
338   GstStructure *s;
339 
340   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_DURATION);
341 
342   s = GST_QUERY_STRUCTURE (query);
343   g_return_if_fail (format == g_value_get_enum (gst_structure_id_get_value (s,
344               GST_QUARK (FORMAT))));
345   gst_structure_id_set (s, GST_QUARK (FORMAT), GST_TYPE_FORMAT, format,
346       GST_QUARK (DURATION), G_TYPE_INT64, duration, NULL);
347 }
348 
349 /**
350  * gst_query_parse_duration:
351  * @query: a #GstQuery
352  * @format: (out) (allow-none): the storage for the #GstFormat of the duration
353  *     value, or %NULL.
354  * @duration: (out) (allow-none): the storage for the total duration, or %NULL.
355  *
356  * Parse a duration query answer. Write the format of the duration into @format,
357  * and the value into @duration, if the respective variables are non-%NULL.
358  */
359 void
gst_query_parse_duration(GstQuery * query,GstFormat * format,gint64 * duration)360 gst_query_parse_duration (GstQuery * query, GstFormat * format,
361     gint64 * duration)
362 {
363   GstStructure *structure;
364 
365   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_DURATION);
366 
367   structure = GST_QUERY_STRUCTURE (query);
368   if (format)
369     *format =
370         (GstFormat) g_value_get_enum (gst_structure_id_get_value (structure,
371             GST_QUARK (FORMAT)));
372   if (duration)
373     *duration = g_value_get_int64 (gst_structure_id_get_value (structure,
374             GST_QUARK (DURATION)));
375 }
376 
377 /**
378  * gst_query_new_latency:
379  *
380  * Constructs a new latency query object.
381  * Use gst_query_unref() when done with it. A latency query is usually performed
382  * by sinks to compensate for additional latency introduced by elements in the
383  * pipeline.
384  *
385  * Free-function: gst_query_unref()
386  *
387  * Returns: (transfer full): a #GstQuery
388  */
389 GstQuery *
gst_query_new_latency(void)390 gst_query_new_latency (void)
391 {
392   GstQuery *query;
393   GstStructure *structure;
394 
395   structure = gst_structure_new_id (GST_QUARK (QUERY_LATENCY),
396       GST_QUARK (LIVE), G_TYPE_BOOLEAN, FALSE,
397       GST_QUARK (MIN_LATENCY), G_TYPE_UINT64, G_GUINT64_CONSTANT (0),
398       GST_QUARK (MAX_LATENCY), G_TYPE_UINT64, GST_CLOCK_TIME_NONE, NULL);
399 
400   query = gst_query_new_custom (GST_QUERY_LATENCY, structure);
401 
402   return query;
403 }
404 
405 /**
406  * gst_query_set_latency:
407  * @query: a #GstQuery
408  * @live: if there is a live element upstream
409  * @min_latency: the minimal latency of the upstream elements
410  * @max_latency: the maximal latency of the upstream elements
411  *
412  * Answer a latency query by setting the requested values in the given format.
413  */
414 void
gst_query_set_latency(GstQuery * query,gboolean live,GstClockTime min_latency,GstClockTime max_latency)415 gst_query_set_latency (GstQuery * query, gboolean live,
416     GstClockTime min_latency, GstClockTime max_latency)
417 {
418   GstStructure *structure;
419 
420   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_LATENCY);
421   g_return_if_fail (GST_CLOCK_TIME_IS_VALID (min_latency));
422 
423   structure = GST_QUERY_STRUCTURE (query);
424   gst_structure_id_set (structure,
425       GST_QUARK (LIVE), G_TYPE_BOOLEAN, live,
426       GST_QUARK (MIN_LATENCY), G_TYPE_UINT64, min_latency,
427       GST_QUARK (MAX_LATENCY), G_TYPE_UINT64, max_latency, NULL);
428 }
429 
430 /**
431  * gst_query_parse_latency:
432  * @query: a #GstQuery
433  * @live: (out) (allow-none): storage for live or %NULL
434  * @min_latency: (out) (allow-none): the storage for the min latency or %NULL
435  * @max_latency: (out) (allow-none): the storage for the max latency or %NULL
436  *
437  * Parse a latency query answer.
438  */
439 void
gst_query_parse_latency(GstQuery * query,gboolean * live,GstClockTime * min_latency,GstClockTime * max_latency)440 gst_query_parse_latency (GstQuery * query, gboolean * live,
441     GstClockTime * min_latency, GstClockTime * max_latency)
442 {
443   GstStructure *structure;
444 
445   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_LATENCY);
446 
447   structure = GST_QUERY_STRUCTURE (query);
448   if (live)
449     *live =
450         g_value_get_boolean (gst_structure_id_get_value (structure,
451             GST_QUARK (LIVE)));
452   if (min_latency)
453     *min_latency = g_value_get_uint64 (gst_structure_id_get_value (structure,
454             GST_QUARK (MIN_LATENCY)));
455   if (max_latency)
456     *max_latency = g_value_get_uint64 (gst_structure_id_get_value (structure,
457             GST_QUARK (MAX_LATENCY)));
458 }
459 
460 /**
461  * gst_query_new_convert:
462  * @src_format: the source #GstFormat for the new query
463  * @value: the value to convert
464  * @dest_format: the target #GstFormat
465  *
466  * Constructs a new convert query object. Use gst_query_unref()
467  * when done with it. A convert query is used to ask for a conversion between
468  * one format and another.
469  *
470  * Free-function: gst_query_unref()
471  *
472  * Returns: (transfer full): a #GstQuery
473  */
474 GstQuery *
gst_query_new_convert(GstFormat src_format,gint64 value,GstFormat dest_format)475 gst_query_new_convert (GstFormat src_format, gint64 value,
476     GstFormat dest_format)
477 {
478   GstQuery *query;
479   GstStructure *structure;
480 
481   structure = gst_structure_new_id (GST_QUARK (QUERY_CONVERT),
482       GST_QUARK (SRC_FORMAT), GST_TYPE_FORMAT, src_format,
483       GST_QUARK (SRC_VALUE), G_TYPE_INT64, value,
484       GST_QUARK (DEST_FORMAT), GST_TYPE_FORMAT, dest_format,
485       GST_QUARK (DEST_VALUE), G_TYPE_INT64, G_GINT64_CONSTANT (-1), NULL);
486 
487   query = gst_query_new_custom (GST_QUERY_CONVERT, structure);
488 
489   return query;
490 }
491 
492 /**
493  * gst_query_set_convert:
494  * @query: a #GstQuery
495  * @src_format: the source #GstFormat
496  * @src_value: the source value
497  * @dest_format: the destination #GstFormat
498  * @dest_value: the destination value
499  *
500  * Answer a convert query by setting the requested values.
501  */
502 void
gst_query_set_convert(GstQuery * query,GstFormat src_format,gint64 src_value,GstFormat dest_format,gint64 dest_value)503 gst_query_set_convert (GstQuery * query, GstFormat src_format, gint64 src_value,
504     GstFormat dest_format, gint64 dest_value)
505 {
506   GstStructure *structure;
507 
508   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_CONVERT);
509 
510   structure = GST_QUERY_STRUCTURE (query);
511   gst_structure_id_set (structure,
512       GST_QUARK (SRC_FORMAT), GST_TYPE_FORMAT, src_format,
513       GST_QUARK (SRC_VALUE), G_TYPE_INT64, src_value,
514       GST_QUARK (DEST_FORMAT), GST_TYPE_FORMAT, dest_format,
515       GST_QUARK (DEST_VALUE), G_TYPE_INT64, dest_value, NULL);
516 }
517 
518 /**
519  * gst_query_parse_convert:
520  * @query: a #GstQuery
521  * @src_format: (out) (allow-none): the storage for the #GstFormat of the
522  *     source value, or %NULL
523  * @src_value: (out) (allow-none): the storage for the source value, or %NULL
524  * @dest_format: (out) (allow-none): the storage for the #GstFormat of the
525  *     destination value, or %NULL
526  * @dest_value: (out) (allow-none): the storage for the destination value,
527  *     or %NULL
528  *
529  * Parse a convert query answer. Any of @src_format, @src_value, @dest_format,
530  * and @dest_value may be %NULL, in which case that value is omitted.
531  */
532 void
gst_query_parse_convert(GstQuery * query,GstFormat * src_format,gint64 * src_value,GstFormat * dest_format,gint64 * dest_value)533 gst_query_parse_convert (GstQuery * query, GstFormat * src_format,
534     gint64 * src_value, GstFormat * dest_format, gint64 * dest_value)
535 {
536   GstStructure *structure;
537 
538   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_CONVERT);
539 
540   structure = GST_QUERY_STRUCTURE (query);
541   if (src_format)
542     *src_format =
543         (GstFormat) g_value_get_enum (gst_structure_id_get_value (structure,
544             GST_QUARK (SRC_FORMAT)));
545   if (src_value)
546     *src_value = g_value_get_int64 (gst_structure_id_get_value (structure,
547             GST_QUARK (SRC_VALUE)));
548   if (dest_format)
549     *dest_format =
550         (GstFormat) g_value_get_enum (gst_structure_id_get_value (structure,
551             GST_QUARK (DEST_FORMAT)));
552   if (dest_value)
553     *dest_value = g_value_get_int64 (gst_structure_id_get_value (structure,
554             GST_QUARK (DEST_VALUE)));
555 }
556 
557 /**
558  * gst_query_new_segment:
559  * @format: the #GstFormat for the new query
560  *
561  * Constructs a new segment query object. Use gst_query_unref()
562  * when done with it. A segment query is used to discover information about the
563  * currently configured segment for playback.
564  *
565  * Free-function: gst_query_unref()
566  *
567  * Returns: (transfer full): a new #GstQuery
568  */
569 GstQuery *
gst_query_new_segment(GstFormat format)570 gst_query_new_segment (GstFormat format)
571 {
572   GstQuery *query;
573   GstStructure *structure;
574 
575   structure = gst_structure_new_id (GST_QUARK (QUERY_SEGMENT),
576       GST_QUARK (RATE), G_TYPE_DOUBLE, (gdouble) 0.0,
577       GST_QUARK (FORMAT), GST_TYPE_FORMAT, format,
578       GST_QUARK (START_VALUE), G_TYPE_INT64, G_GINT64_CONSTANT (-1),
579       GST_QUARK (STOP_VALUE), G_TYPE_INT64, G_GINT64_CONSTANT (-1), NULL);
580 
581   query = gst_query_new_custom (GST_QUERY_SEGMENT, structure);
582 
583   return query;
584 }
585 
586 /**
587  * gst_query_set_segment:
588  * @query: a #GstQuery
589  * @rate: the rate of the segment
590  * @format: the #GstFormat of the segment values (@start_value and @stop_value)
591  * @start_value: the start value
592  * @stop_value: the stop value
593  *
594  * Answer a segment query by setting the requested values. The normal
595  * playback segment of a pipeline is 0 to duration at the default rate of
596  * 1.0. If a seek was performed on the pipeline to play a different
597  * segment, this query will return the range specified in the last seek.
598  *
599  * @start_value and @stop_value will respectively contain the configured
600  * playback range start and stop values expressed in @format.
601  * The values are always between 0 and the duration of the media and
602  * @start_value <= @stop_value. @rate will contain the playback rate. For
603  * negative rates, playback will actually happen from @stop_value to
604  * @start_value.
605  */
606 void
gst_query_set_segment(GstQuery * query,gdouble rate,GstFormat format,gint64 start_value,gint64 stop_value)607 gst_query_set_segment (GstQuery * query, gdouble rate, GstFormat format,
608     gint64 start_value, gint64 stop_value)
609 {
610   GstStructure *structure;
611 
612   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_SEGMENT);
613 
614   structure = GST_QUERY_STRUCTURE (query);
615   gst_structure_id_set (structure,
616       GST_QUARK (RATE), G_TYPE_DOUBLE, rate,
617       GST_QUARK (FORMAT), GST_TYPE_FORMAT, format,
618       GST_QUARK (START_VALUE), G_TYPE_INT64, start_value,
619       GST_QUARK (STOP_VALUE), G_TYPE_INT64, stop_value, NULL);
620 }
621 
622 /**
623  * gst_query_parse_segment:
624  * @query: a #GstQuery
625  * @rate: (out) (allow-none): the storage for the rate of the segment, or %NULL
626  * @format: (out) (allow-none): the storage for the #GstFormat of the values,
627  *     or %NULL
628  * @start_value: (out) (allow-none): the storage for the start value, or %NULL
629  * @stop_value: (out) (allow-none): the storage for the stop value, or %NULL
630  *
631  * Parse a segment query answer. Any of @rate, @format, @start_value, and
632  * @stop_value may be %NULL, which will cause this value to be omitted.
633  *
634  * See gst_query_set_segment() for an explanation of the function arguments.
635  */
636 void
gst_query_parse_segment(GstQuery * query,gdouble * rate,GstFormat * format,gint64 * start_value,gint64 * stop_value)637 gst_query_parse_segment (GstQuery * query, gdouble * rate, GstFormat * format,
638     gint64 * start_value, gint64 * stop_value)
639 {
640   GstStructure *structure;
641 
642   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_SEGMENT);
643 
644   structure = GST_QUERY_STRUCTURE (query);
645   if (rate)
646     *rate = g_value_get_double (gst_structure_id_get_value (structure,
647             GST_QUARK (RATE)));
648   if (format)
649     *format =
650         (GstFormat) g_value_get_enum (gst_structure_id_get_value (structure,
651             GST_QUARK (FORMAT)));
652   if (start_value)
653     *start_value = g_value_get_int64 (gst_structure_id_get_value (structure,
654             GST_QUARK (START_VALUE)));
655   if (stop_value)
656     *stop_value = g_value_get_int64 (gst_structure_id_get_value (structure,
657             GST_QUARK (STOP_VALUE)));
658 }
659 
660 /**
661  * gst_query_new_custom:
662  * @type: the query type
663  * @structure: (allow-none) (transfer full): a structure for the query
664  *
665  * Constructs a new custom query object. Use gst_query_unref()
666  * when done with it.
667  *
668  * Free-function: gst_query_unref()
669  *
670  * Returns: (transfer full) (nullable): a new #GstQuery
671  */
672 GstQuery *
gst_query_new_custom(GstQueryType type,GstStructure * structure)673 gst_query_new_custom (GstQueryType type, GstStructure * structure)
674 {
675   GstQueryImpl *query;
676 
677   query = g_slice_new0 (GstQueryImpl);
678 
679   GST_DEBUG ("creating new query %p %s", query, gst_query_type_get_name (type));
680 
681   if (structure) {
682     /* structure must not have a parent */
683     if (!gst_structure_set_parent_refcount (structure,
684             &query->query.mini_object.refcount))
685       goto had_parent;
686   }
687 
688   gst_mini_object_init (GST_MINI_OBJECT_CAST (query), 0, _gst_query_type,
689       (GstMiniObjectCopyFunction) _gst_query_copy, NULL,
690       (GstMiniObjectFreeFunction) _gst_query_free);
691 
692   GST_QUERY_TYPE (query) = type;
693   GST_QUERY_STRUCTURE (query) = structure;
694 
695   return GST_QUERY_CAST (query);
696 
697   /* ERRORS */
698 had_parent:
699   {
700     g_slice_free1 (sizeof (GstQueryImpl), query);
701     g_warning ("structure is already owned by another object");
702     return NULL;
703   }
704 }
705 
706 /**
707  * gst_query_get_structure:
708  * @query: a #GstQuery
709  *
710  * Get the structure of a query.
711  *
712  * Returns: (transfer none) (nullable): the #GstStructure of the query. The
713  *     structure is still owned by the query and will therefore be freed when the
714  *     query is unreffed.
715  */
716 const GstStructure *
gst_query_get_structure(GstQuery * query)717 gst_query_get_structure (GstQuery * query)
718 {
719   g_return_val_if_fail (GST_IS_QUERY (query), NULL);
720 
721   return GST_QUERY_STRUCTURE (query);
722 }
723 
724 /**
725  * gst_query_writable_structure:
726  * @query: a #GstQuery
727  *
728  * Get the structure of a query. This method should be called with a writable
729  * @query so that the returned structure is guaranteed to be writable.
730  *
731  * Returns: (transfer none): the #GstStructure of the query. The structure is
732  *     still owned by the query and will therefore be freed when the query
733  *     is unreffed.
734  */
735 GstStructure *
gst_query_writable_structure(GstQuery * query)736 gst_query_writable_structure (GstQuery * query)
737 {
738   GstStructure *structure;
739 
740   g_return_val_if_fail (GST_IS_QUERY (query), NULL);
741   g_return_val_if_fail (gst_query_is_writable (query), NULL);
742 
743   structure = GST_QUERY_STRUCTURE (query);
744 
745   if (structure == NULL) {
746     structure =
747         gst_structure_new_id_empty (gst_query_type_to_quark (GST_QUERY_TYPE
748             (query)));
749     gst_structure_set_parent_refcount (structure, &query->mini_object.refcount);
750     GST_QUERY_STRUCTURE (query) = structure;
751   }
752   return structure;
753 }
754 
755 /**
756  * gst_query_new_seeking:
757  * @format: the default #GstFormat for the new query
758  *
759  * Constructs a new query object for querying seeking properties of
760  * the stream.
761  *
762  * Free-function: gst_query_unref()
763  *
764  * Returns: (transfer full): a new #GstQuery
765  */
766 GstQuery *
gst_query_new_seeking(GstFormat format)767 gst_query_new_seeking (GstFormat format)
768 {
769   GstQuery *query;
770   GstStructure *structure;
771 
772   structure = gst_structure_new_id (GST_QUARK (QUERY_SEEKING),
773       GST_QUARK (FORMAT), GST_TYPE_FORMAT, format,
774       GST_QUARK (SEEKABLE), G_TYPE_BOOLEAN, FALSE,
775       GST_QUARK (SEGMENT_START), G_TYPE_INT64, G_GINT64_CONSTANT (-1),
776       GST_QUARK (SEGMENT_END), G_TYPE_INT64, G_GINT64_CONSTANT (-1), NULL);
777 
778   query = gst_query_new_custom (GST_QUERY_SEEKING, structure);
779 
780   return query;
781 }
782 
783 /**
784  * gst_query_set_seeking:
785  * @query: a #GstQuery
786  * @format: the format to set for the @segment_start and @segment_end values
787  * @seekable: the seekable flag to set
788  * @segment_start: the segment_start to set
789  * @segment_end: the segment_end to set
790  *
791  * Set the seeking query result fields in @query.
792  */
793 void
gst_query_set_seeking(GstQuery * query,GstFormat format,gboolean seekable,gint64 segment_start,gint64 segment_end)794 gst_query_set_seeking (GstQuery * query, GstFormat format,
795     gboolean seekable, gint64 segment_start, gint64 segment_end)
796 {
797   GstStructure *structure;
798 
799   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_SEEKING);
800   g_return_if_fail (gst_query_is_writable (query));
801 
802   structure = GST_QUERY_STRUCTURE (query);
803   gst_structure_id_set (structure,
804       GST_QUARK (FORMAT), GST_TYPE_FORMAT, format,
805       GST_QUARK (SEEKABLE), G_TYPE_BOOLEAN, seekable,
806       GST_QUARK (SEGMENT_START), G_TYPE_INT64, segment_start,
807       GST_QUARK (SEGMENT_END), G_TYPE_INT64, segment_end, NULL);
808 }
809 
810 /**
811  * gst_query_parse_seeking:
812  * @query: a GST_QUERY_SEEKING type query #GstQuery
813  * @format: (out) (allow-none): the format to set for the @segment_start
814  *     and @segment_end values, or %NULL
815  * @seekable: (out) (allow-none): the seekable flag to set, or %NULL
816  * @segment_start: (out) (allow-none): the segment_start to set, or %NULL
817  * @segment_end: (out) (allow-none): the segment_end to set, or %NULL
818  *
819  * Parse a seeking query, writing the format into @format, and
820  * other results into the passed parameters, if the respective parameters
821  * are non-%NULL
822  */
823 void
gst_query_parse_seeking(GstQuery * query,GstFormat * format,gboolean * seekable,gint64 * segment_start,gint64 * segment_end)824 gst_query_parse_seeking (GstQuery * query, GstFormat * format,
825     gboolean * seekable, gint64 * segment_start, gint64 * segment_end)
826 {
827   GstStructure *structure;
828 
829   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_SEEKING);
830 
831   structure = GST_QUERY_STRUCTURE (query);
832   if (format)
833     *format =
834         (GstFormat) g_value_get_enum (gst_structure_id_get_value (structure,
835             GST_QUARK (FORMAT)));
836   if (seekable)
837     *seekable = g_value_get_boolean (gst_structure_id_get_value (structure,
838             GST_QUARK (SEEKABLE)));
839   if (segment_start)
840     *segment_start = g_value_get_int64 (gst_structure_id_get_value (structure,
841             GST_QUARK (SEGMENT_START)));
842   if (segment_end)
843     *segment_end = g_value_get_int64 (gst_structure_id_get_value (structure,
844             GST_QUARK (SEGMENT_END)));
845 }
846 
847 static GArray *
ensure_array(GstStructure * s,GQuark quark,gsize element_size,GDestroyNotify clear_func)848 ensure_array (GstStructure * s, GQuark quark, gsize element_size,
849     GDestroyNotify clear_func)
850 {
851   GArray *array;
852   const GValue *value;
853 
854   value = gst_structure_id_get_value (s, quark);
855   if (value) {
856     array = (GArray *) g_value_get_boxed (value);
857   } else {
858     GValue new_array_val = { 0, };
859 
860     array = g_array_new (FALSE, TRUE, element_size);
861     if (clear_func)
862       g_array_set_clear_func (array, clear_func);
863 
864     g_value_init (&new_array_val, G_TYPE_ARRAY);
865     g_value_take_boxed (&new_array_val, array);
866 
867     gst_structure_id_take_value (s, quark, &new_array_val);
868   }
869   return array;
870 }
871 
872 /**
873  * gst_query_new_formats:
874  *
875  * Constructs a new query object for querying formats of
876  * the stream.
877  *
878  * Free-function: gst_query_unref()
879  *
880  * Returns: (transfer full): a new #GstQuery
881  */
882 GstQuery *
gst_query_new_formats(void)883 gst_query_new_formats (void)
884 {
885   GstQuery *query;
886   GstStructure *structure;
887 
888   structure = gst_structure_new_id_empty (GST_QUARK (QUERY_FORMATS));
889   query = gst_query_new_custom (GST_QUERY_FORMATS, structure);
890 
891   return query;
892 }
893 
894 static void
gst_query_list_add_format(GValue * list,GstFormat format)895 gst_query_list_add_format (GValue * list, GstFormat format)
896 {
897   GValue item = { 0, };
898 
899   g_value_init (&item, GST_TYPE_FORMAT);
900   g_value_set_enum (&item, format);
901   gst_value_list_append_value (list, &item);
902   g_value_unset (&item);
903 }
904 
905 /**
906  * gst_query_set_formats:
907  * @query: a #GstQuery
908  * @n_formats: the number of formats to set.
909  * @...: A number of @GstFormats equal to @n_formats.
910  *
911  * Set the formats query result fields in @query. The number of formats passed
912  * must be equal to @n_formats.
913  */
914 void
gst_query_set_formats(GstQuery * query,gint n_formats,...)915 gst_query_set_formats (GstQuery * query, gint n_formats, ...)
916 {
917   va_list ap;
918   GValue list = { 0, };
919   gint i;
920   GstStructure *structure;
921 
922   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_FORMATS);
923   g_return_if_fail (gst_query_is_writable (query));
924 
925   g_value_init (&list, GST_TYPE_LIST);
926 
927   va_start (ap, n_formats);
928   for (i = 0; i < n_formats; i++) {
929     gst_query_list_add_format (&list, va_arg (ap, GstFormat));
930   }
931   va_end (ap);
932 
933   structure = GST_QUERY_STRUCTURE (query);
934   gst_structure_set_value (structure, "formats", &list);
935 
936   g_value_unset (&list);
937 
938 }
939 
940 /**
941  * gst_query_set_formatsv:
942  * @query: a #GstQuery
943  * @n_formats: the number of formats to set.
944  * @formats: (in) (array length=n_formats): an array containing @n_formats
945  *     @GstFormat values.
946  *
947  * Set the formats query result fields in @query. The number of formats passed
948  * in the @formats array must be equal to @n_formats.
949  */
950 void
gst_query_set_formatsv(GstQuery * query,gint n_formats,const GstFormat * formats)951 gst_query_set_formatsv (GstQuery * query, gint n_formats,
952     const GstFormat * formats)
953 {
954   GValue list = { 0, };
955   gint i;
956   GstStructure *structure;
957 
958   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_FORMATS);
959   g_return_if_fail (gst_query_is_writable (query));
960 
961   g_value_init (&list, GST_TYPE_LIST);
962   for (i = 0; i < n_formats; i++) {
963     gst_query_list_add_format (&list, formats[i]);
964   }
965   structure = GST_QUERY_STRUCTURE (query);
966   gst_structure_set_value (structure, "formats", &list);
967 
968   g_value_unset (&list);
969 }
970 
971 /**
972  * gst_query_parse_n_formats:
973  * @query: a #GstQuery
974  * @n_formats: (out) (allow-none): the number of formats in this query.
975  *
976  * Parse the number of formats in the formats @query.
977  */
978 void
gst_query_parse_n_formats(GstQuery * query,guint * n_formats)979 gst_query_parse_n_formats (GstQuery * query, guint * n_formats)
980 {
981   GstStructure *structure;
982 
983   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_FORMATS);
984 
985   if (n_formats) {
986     const GValue *list;
987 
988     structure = GST_QUERY_STRUCTURE (query);
989     list = gst_structure_get_value (structure, "formats");
990     if (list == NULL)
991       *n_formats = 0;
992     else
993       *n_formats = gst_value_list_get_size (list);
994   }
995 }
996 
997 /**
998  * gst_query_parse_nth_format:
999  * @query: a #GstQuery
1000  * @nth: the nth format to retrieve.
1001  * @format: (out) (allow-none): a pointer to store the nth format
1002  *
1003  * Parse the format query and retrieve the @nth format from it into
1004  * @format. If the list contains less elements than @nth, @format will be
1005  * set to GST_FORMAT_UNDEFINED.
1006  */
1007 void
gst_query_parse_nth_format(GstQuery * query,guint nth,GstFormat * format)1008 gst_query_parse_nth_format (GstQuery * query, guint nth, GstFormat * format)
1009 {
1010   GstStructure *structure;
1011 
1012   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_FORMATS);
1013 
1014   if (format) {
1015     const GValue *list;
1016 
1017     structure = GST_QUERY_STRUCTURE (query);
1018     list = gst_structure_get_value (structure, "formats");
1019     if (list == NULL) {
1020       *format = GST_FORMAT_UNDEFINED;
1021     } else {
1022       if (nth < gst_value_list_get_size (list)) {
1023         *format =
1024             (GstFormat) g_value_get_enum (gst_value_list_get_value (list, nth));
1025       } else
1026         *format = GST_FORMAT_UNDEFINED;
1027     }
1028   }
1029 }
1030 
1031 /**
1032  * gst_query_new_buffering:
1033  * @format: the default #GstFormat for the new query
1034  *
1035  * Constructs a new query object for querying the buffering status of
1036  * a stream.
1037  *
1038  * Free-function: gst_query_unref()
1039  *
1040  * Returns: (transfer full): a new #GstQuery
1041  */
1042 GstQuery *
gst_query_new_buffering(GstFormat format)1043 gst_query_new_buffering (GstFormat format)
1044 {
1045   GstQuery *query;
1046   GstStructure *structure;
1047 
1048   /* by default, we configure the answer as no buffering with a 100% buffering
1049    * progress */
1050   structure = gst_structure_new_id (GST_QUARK (QUERY_BUFFERING),
1051       GST_QUARK (BUSY), G_TYPE_BOOLEAN, FALSE,
1052       GST_QUARK (BUFFER_PERCENT), G_TYPE_INT, 100,
1053       GST_QUARK (BUFFERING_MODE), GST_TYPE_BUFFERING_MODE, GST_BUFFERING_STREAM,
1054       GST_QUARK (AVG_IN_RATE), G_TYPE_INT, -1,
1055       GST_QUARK (AVG_OUT_RATE), G_TYPE_INT, -1,
1056       GST_QUARK (BUFFERING_LEFT), G_TYPE_INT64, G_GINT64_CONSTANT (0),
1057       GST_QUARK (ESTIMATED_TOTAL), G_TYPE_INT64, G_GINT64_CONSTANT (-1),
1058       GST_QUARK (FORMAT), GST_TYPE_FORMAT, format,
1059       GST_QUARK (START_VALUE), G_TYPE_INT64, G_GINT64_CONSTANT (-1),
1060       GST_QUARK (STOP_VALUE), G_TYPE_INT64, G_GINT64_CONSTANT (-1), NULL);
1061 
1062   query = gst_query_new_custom (GST_QUERY_BUFFERING, structure);
1063 
1064   return query;
1065 }
1066 
1067 /**
1068  * gst_query_set_buffering_percent:
1069  * @query: A valid #GstQuery of type GST_QUERY_BUFFERING.
1070  * @busy: if buffering is busy
1071  * @percent: a buffering percent
1072  *
1073  * Set the percentage of buffered data. This is a value between 0 and 100.
1074  * The @busy indicator is %TRUE when the buffering is in progress.
1075  */
1076 void
gst_query_set_buffering_percent(GstQuery * query,gboolean busy,gint percent)1077 gst_query_set_buffering_percent (GstQuery * query, gboolean busy, gint percent)
1078 {
1079   GstStructure *structure;
1080 
1081   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_BUFFERING);
1082   g_return_if_fail (gst_query_is_writable (query));
1083   g_return_if_fail (percent >= 0 && percent <= 100);
1084 
1085   structure = GST_QUERY_STRUCTURE (query);
1086   gst_structure_id_set (structure,
1087       GST_QUARK (BUSY), G_TYPE_BOOLEAN, busy,
1088       GST_QUARK (BUFFER_PERCENT), G_TYPE_INT, percent, NULL);
1089 }
1090 
1091 /**
1092  * gst_query_parse_buffering_percent:
1093  * @query: A valid #GstQuery of type GST_QUERY_BUFFERING.
1094  * @busy: (out) (allow-none): if buffering is busy, or %NULL
1095  * @percent: (out) (allow-none): a buffering percent, or %NULL
1096  *
1097  * Get the percentage of buffered data. This is a value between 0 and 100.
1098  * The @busy indicator is %TRUE when the buffering is in progress.
1099  */
1100 void
gst_query_parse_buffering_percent(GstQuery * query,gboolean * busy,gint * percent)1101 gst_query_parse_buffering_percent (GstQuery * query, gboolean * busy,
1102     gint * percent)
1103 {
1104   GstStructure *structure;
1105 
1106   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_BUFFERING);
1107 
1108   structure = GST_QUERY_STRUCTURE (query);
1109   if (busy)
1110     *busy = g_value_get_boolean (gst_structure_id_get_value (structure,
1111             GST_QUARK (BUSY)));
1112   if (percent)
1113     *percent = g_value_get_int (gst_structure_id_get_value (structure,
1114             GST_QUARK (BUFFER_PERCENT)));
1115 }
1116 
1117 /**
1118  * gst_query_set_buffering_stats:
1119  * @query: A valid #GstQuery of type GST_QUERY_BUFFERING.
1120  * @mode: a buffering mode
1121  * @avg_in: the average input rate
1122  * @avg_out: the average output rate
1123  * @buffering_left: amount of buffering time left in milliseconds
1124  *
1125  * Configures the buffering stats values in @query.
1126  */
1127 void
gst_query_set_buffering_stats(GstQuery * query,GstBufferingMode mode,gint avg_in,gint avg_out,gint64 buffering_left)1128 gst_query_set_buffering_stats (GstQuery * query, GstBufferingMode mode,
1129     gint avg_in, gint avg_out, gint64 buffering_left)
1130 {
1131   GstStructure *structure;
1132 
1133   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_BUFFERING);
1134   g_return_if_fail (gst_query_is_writable (query));
1135 
1136   structure = GST_QUERY_STRUCTURE (query);
1137   gst_structure_id_set (structure,
1138       GST_QUARK (BUFFERING_MODE), GST_TYPE_BUFFERING_MODE, mode,
1139       GST_QUARK (AVG_IN_RATE), G_TYPE_INT, avg_in,
1140       GST_QUARK (AVG_OUT_RATE), G_TYPE_INT, avg_out,
1141       GST_QUARK (BUFFERING_LEFT), G_TYPE_INT64, buffering_left, NULL);
1142 }
1143 
1144 /**
1145  * gst_query_parse_buffering_stats:
1146  * @query: A valid #GstQuery of type GST_QUERY_BUFFERING.
1147  * @mode: (out) (allow-none): a buffering mode, or %NULL
1148  * @avg_in: (out) (allow-none): the average input rate, or %NULL
1149  * @avg_out: (out) (allow-none): the average output rat, or %NULL
1150  * @buffering_left: (out) (allow-none): amount of buffering time left in
1151  *     milliseconds, or %NULL
1152  *
1153  * Extracts the buffering stats values from @query.
1154  */
1155 void
gst_query_parse_buffering_stats(GstQuery * query,GstBufferingMode * mode,gint * avg_in,gint * avg_out,gint64 * buffering_left)1156 gst_query_parse_buffering_stats (GstQuery * query,
1157     GstBufferingMode * mode, gint * avg_in, gint * avg_out,
1158     gint64 * buffering_left)
1159 {
1160   GstStructure *structure;
1161 
1162   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_BUFFERING);
1163 
1164   structure = GST_QUERY_STRUCTURE (query);
1165   if (mode)
1166     *mode = (GstBufferingMode)
1167         g_value_get_enum (gst_structure_id_get_value (structure,
1168             GST_QUARK (BUFFERING_MODE)));
1169   if (avg_in)
1170     *avg_in = g_value_get_int (gst_structure_id_get_value (structure,
1171             GST_QUARK (AVG_IN_RATE)));
1172   if (avg_out)
1173     *avg_out = g_value_get_int (gst_structure_id_get_value (structure,
1174             GST_QUARK (AVG_OUT_RATE)));
1175   if (buffering_left)
1176     *buffering_left =
1177         g_value_get_int64 (gst_structure_id_get_value (structure,
1178             GST_QUARK (BUFFERING_LEFT)));
1179 }
1180 
1181 /**
1182  * gst_query_set_buffering_range:
1183  * @query: a #GstQuery
1184  * @format: the format to set for the @start and @stop values
1185  * @start: the start to set
1186  * @stop: the stop to set
1187  * @estimated_total: estimated total amount of download time remaining in
1188  *     milliseconds
1189  *
1190  * Set the available query result fields in @query.
1191  */
1192 void
gst_query_set_buffering_range(GstQuery * query,GstFormat format,gint64 start,gint64 stop,gint64 estimated_total)1193 gst_query_set_buffering_range (GstQuery * query, GstFormat format,
1194     gint64 start, gint64 stop, gint64 estimated_total)
1195 {
1196   GstStructure *structure;
1197 
1198   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_BUFFERING);
1199   g_return_if_fail (gst_query_is_writable (query));
1200 
1201   structure = GST_QUERY_STRUCTURE (query);
1202   gst_structure_id_set (structure,
1203       GST_QUARK (FORMAT), GST_TYPE_FORMAT, format,
1204       GST_QUARK (START_VALUE), G_TYPE_INT64, start,
1205       GST_QUARK (STOP_VALUE), G_TYPE_INT64, stop,
1206       GST_QUARK (ESTIMATED_TOTAL), G_TYPE_INT64, estimated_total, NULL);
1207 }
1208 
1209 /**
1210  * gst_query_parse_buffering_range:
1211  * @query: a GST_QUERY_BUFFERING type query #GstQuery
1212  * @format: (out) (allow-none): the format to set for the @segment_start
1213  *     and @segment_end values, or %NULL
1214  * @start: (out) (allow-none): the start to set, or %NULL
1215  * @stop: (out) (allow-none): the stop to set, or %NULL
1216  * @estimated_total: (out) (allow-none): estimated total amount of download
1217  *     time remaining in milliseconds, or %NULL
1218  *
1219  * Parse an available query, writing the format into @format, and
1220  * other results into the passed parameters, if the respective parameters
1221  * are non-%NULL
1222  */
1223 void
gst_query_parse_buffering_range(GstQuery * query,GstFormat * format,gint64 * start,gint64 * stop,gint64 * estimated_total)1224 gst_query_parse_buffering_range (GstQuery * query, GstFormat * format,
1225     gint64 * start, gint64 * stop, gint64 * estimated_total)
1226 {
1227   GstStructure *structure;
1228 
1229   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_BUFFERING);
1230 
1231   structure = GST_QUERY_STRUCTURE (query);
1232   if (format)
1233     *format =
1234         (GstFormat) g_value_get_enum (gst_structure_id_get_value (structure,
1235             GST_QUARK (FORMAT)));
1236   if (start)
1237     *start = g_value_get_int64 (gst_structure_id_get_value (structure,
1238             GST_QUARK (START_VALUE)));
1239   if (stop)
1240     *stop = g_value_get_int64 (gst_structure_id_get_value (structure,
1241             GST_QUARK (STOP_VALUE)));
1242   if (estimated_total)
1243     *estimated_total =
1244         g_value_get_int64 (gst_structure_id_get_value (structure,
1245             GST_QUARK (ESTIMATED_TOTAL)));
1246 }
1247 
1248 /* GstQueryBufferingRange: internal struct for GArray */
1249 typedef struct
1250 {
1251   gint64 start;
1252   gint64 stop;
1253 } GstQueryBufferingRange;
1254 
1255 /**
1256  * gst_query_add_buffering_range:
1257  * @query: a GST_QUERY_BUFFERING type query #GstQuery
1258  * @start: start position of the range
1259  * @stop: stop position of the range
1260  *
1261  * Set the buffering-ranges array field in @query. The current last
1262  * start position of the array should be inferior to @start.
1263  *
1264  * Returns: a #gboolean indicating if the range was added or not.
1265  */
1266 gboolean
gst_query_add_buffering_range(GstQuery * query,gint64 start,gint64 stop)1267 gst_query_add_buffering_range (GstQuery * query, gint64 start, gint64 stop)
1268 {
1269   GstQueryBufferingRange range;
1270   GstStructure *structure;
1271   GArray *array;
1272 
1273   g_return_val_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_BUFFERING, FALSE);
1274   g_return_val_if_fail (gst_query_is_writable (query), FALSE);
1275 
1276   if (G_UNLIKELY (start >= stop))
1277     return FALSE;
1278 
1279   structure = GST_QUERY_STRUCTURE (query);
1280   array = ensure_array (structure, GST_QUARK (BUFFERING_RANGES),
1281       sizeof (GstQueryBufferingRange), NULL);
1282 
1283   if (array->len > 1) {
1284     GstQueryBufferingRange *last;
1285 
1286     last = &g_array_index (array, GstQueryBufferingRange, array->len - 1);
1287 
1288     if (G_UNLIKELY (start <= last->start))
1289       return FALSE;
1290   }
1291 
1292   range.start = start;
1293   range.stop = stop;
1294   g_array_append_val (array, range);
1295 
1296   return TRUE;
1297 }
1298 
1299 /**
1300  * gst_query_get_n_buffering_ranges:
1301  * @query: a GST_QUERY_BUFFERING type query #GstQuery
1302  *
1303  * Retrieve the number of values currently stored in the
1304  * buffered-ranges array of the query's structure.
1305  *
1306  * Returns: the range array size as a #guint.
1307  */
1308 guint
gst_query_get_n_buffering_ranges(GstQuery * query)1309 gst_query_get_n_buffering_ranges (GstQuery * query)
1310 {
1311   GstStructure *structure;
1312   GArray *array;
1313 
1314   g_return_val_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_BUFFERING, 0);
1315 
1316   structure = GST_QUERY_STRUCTURE (query);
1317   array = ensure_array (structure, GST_QUARK (BUFFERING_RANGES),
1318       sizeof (GstQueryBufferingRange), NULL);
1319 
1320   return array->len;
1321 }
1322 
1323 
1324 /**
1325  * gst_query_parse_nth_buffering_range:
1326  * @query: a GST_QUERY_BUFFERING type query #GstQuery
1327  * @index: position in the buffered-ranges array to read
1328  * @start: (out) (allow-none): the start position to set, or %NULL
1329  * @stop: (out) (allow-none): the stop position to set, or %NULL
1330  *
1331  * Parse an available query and get the start and stop values stored
1332  * at the @index of the buffered ranges array.
1333  *
1334  * Returns: a #gboolean indicating if the parsing succeeded.
1335  */
1336 gboolean
gst_query_parse_nth_buffering_range(GstQuery * query,guint index,gint64 * start,gint64 * stop)1337 gst_query_parse_nth_buffering_range (GstQuery * query, guint index,
1338     gint64 * start, gint64 * stop)
1339 {
1340   GstQueryBufferingRange *range;
1341   GstStructure *structure;
1342   GArray *array;
1343 
1344   g_return_val_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_BUFFERING, FALSE);
1345 
1346   structure = GST_QUERY_STRUCTURE (query);
1347 
1348   array = ensure_array (structure, GST_QUARK (BUFFERING_RANGES),
1349       sizeof (GstQueryBufferingRange), NULL);
1350   g_return_val_if_fail (index < array->len, FALSE);
1351 
1352   range = &g_array_index (array, GstQueryBufferingRange, index);
1353 
1354   if (start)
1355     *start = range->start;
1356   if (stop)
1357     *stop = range->stop;
1358 
1359   return TRUE;
1360 }
1361 
1362 
1363 /**
1364  * gst_query_new_uri:
1365  *
1366  * Constructs a new query URI query object. Use gst_query_unref()
1367  * when done with it. An URI query is used to query the current URI
1368  * that is used by the source or sink.
1369  *
1370  * Free-function: gst_query_unref()
1371  *
1372  * Returns: (transfer full): a new #GstQuery
1373  */
1374 GstQuery *
gst_query_new_uri(void)1375 gst_query_new_uri (void)
1376 {
1377   GstQuery *query;
1378   GstStructure *structure;
1379 
1380   structure = gst_structure_new_id (GST_QUARK (QUERY_URI),
1381       GST_QUARK (URI), G_TYPE_STRING, NULL, NULL);
1382 
1383   query = gst_query_new_custom (GST_QUERY_URI, structure);
1384 
1385   return query;
1386 }
1387 
1388 /**
1389  * gst_query_set_uri:
1390  * @query: a #GstQuery with query type GST_QUERY_URI
1391  * @uri: the URI to set
1392  *
1393  * Answer a URI query by setting the requested URI.
1394  */
1395 void
gst_query_set_uri(GstQuery * query,const gchar * uri)1396 gst_query_set_uri (GstQuery * query, const gchar * uri)
1397 {
1398   GstStructure *structure;
1399 
1400   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_URI);
1401   g_return_if_fail (gst_query_is_writable (query));
1402   g_return_if_fail (gst_uri_is_valid (uri));
1403 
1404   structure = GST_QUERY_STRUCTURE (query);
1405   gst_structure_id_set (structure, GST_QUARK (URI), G_TYPE_STRING, uri, NULL);
1406 }
1407 
1408 /**
1409  * gst_query_parse_uri:
1410  * @query: a #GstQuery
1411  * @uri: (out) (transfer full) (allow-none): the storage for the current URI
1412  *     (may be %NULL)
1413  *
1414  * Parse an URI query, writing the URI into @uri as a newly
1415  * allocated string, if the respective parameters are non-%NULL.
1416  * Free the string with g_free() after usage.
1417  */
1418 void
gst_query_parse_uri(GstQuery * query,gchar ** uri)1419 gst_query_parse_uri (GstQuery * query, gchar ** uri)
1420 {
1421   GstStructure *structure;
1422 
1423   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_URI);
1424 
1425   structure = GST_QUERY_STRUCTURE (query);
1426   if (uri)
1427     *uri = g_value_dup_string (gst_structure_id_get_value (structure,
1428             GST_QUARK (URI)));
1429 }
1430 
1431 /**
1432  * gst_query_set_uri_redirection:
1433  * @query: a #GstQuery with query type GST_QUERY_URI
1434  * @uri: the URI to set
1435  *
1436  * Answer a URI query by setting the requested URI redirection.
1437  *
1438  * Since: 1.2
1439  */
1440 void
gst_query_set_uri_redirection(GstQuery * query,const gchar * uri)1441 gst_query_set_uri_redirection (GstQuery * query, const gchar * uri)
1442 {
1443   GstStructure *structure;
1444 
1445   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_URI);
1446   g_return_if_fail (gst_query_is_writable (query));
1447   g_return_if_fail (gst_uri_is_valid (uri));
1448 
1449   structure = GST_QUERY_STRUCTURE (query);
1450   gst_structure_id_set (structure, GST_QUARK (URI_REDIRECTION),
1451       G_TYPE_STRING, uri, NULL);
1452 }
1453 
1454 /**
1455  * gst_query_parse_uri_redirection:
1456  * @query: a #GstQuery
1457  * @uri: (out) (transfer full) (allow-none): the storage for the redirect URI
1458  *     (may be %NULL)
1459  *
1460  * Parse an URI query, writing the URI into @uri as a newly
1461  * allocated string, if the respective parameters are non-%NULL.
1462  * Free the string with g_free() after usage.
1463  *
1464  * Since: 1.2
1465  */
1466 void
gst_query_parse_uri_redirection(GstQuery * query,gchar ** uri)1467 gst_query_parse_uri_redirection (GstQuery * query, gchar ** uri)
1468 {
1469   GstStructure *structure;
1470 
1471   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_URI);
1472 
1473   structure = GST_QUERY_STRUCTURE (query);
1474   if (uri) {
1475     if (!gst_structure_id_get (structure, GST_QUARK (URI_REDIRECTION),
1476             G_TYPE_STRING, uri, NULL))
1477       *uri = NULL;
1478   }
1479 }
1480 
1481 /**
1482  * gst_query_set_uri_redirection_permanent:
1483  * @query: a #GstQuery with query type %GST_QUERY_URI
1484  * @permanent: whether the redirect is permanent or not
1485  *
1486  * Answer a URI query by setting the requested URI redirection
1487  * to permanent or not.
1488  *
1489  * Since: 1.4
1490  */
1491 void
gst_query_set_uri_redirection_permanent(GstQuery * query,gboolean permanent)1492 gst_query_set_uri_redirection_permanent (GstQuery * query, gboolean permanent)
1493 {
1494   GstStructure *structure;
1495 
1496   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_URI);
1497   g_return_if_fail (gst_query_is_writable (query));
1498 
1499   structure = GST_QUERY_STRUCTURE (query);
1500   gst_structure_id_set (structure, GST_QUARK (URI_REDIRECTION_PERMANENT),
1501       G_TYPE_BOOLEAN, permanent, NULL);
1502 }
1503 
1504 /**
1505  * gst_query_parse_uri_redirection_permanent:
1506  * @query: a #GstQuery
1507  * @permanent: (out) (allow-none): if the URI redirection is permanent
1508  *     (may be %NULL)
1509  *
1510  * Parse an URI query, and set @permanent to %TRUE if there is a redirection
1511  * and it should be considered permanent. If a redirection is permanent,
1512  * applications should update their internal storage of the URI, otherwise
1513  * they should make all future requests to the original URI.
1514  *
1515  * Since: 1.4
1516  */
1517 void
gst_query_parse_uri_redirection_permanent(GstQuery * query,gboolean * permanent)1518 gst_query_parse_uri_redirection_permanent (GstQuery * query,
1519     gboolean * permanent)
1520 {
1521   GstStructure *structure;
1522 
1523   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_URI);
1524 
1525   structure = GST_QUERY_STRUCTURE (query);
1526   if (permanent) {
1527     if (!gst_structure_id_get (structure, GST_QUARK (URI_REDIRECTION_PERMANENT),
1528             G_TYPE_BOOLEAN, permanent, NULL))
1529       *permanent = FALSE;
1530   }
1531 }
1532 
1533 /**
1534  * gst_query_new_allocation:
1535  * @caps: the negotiated caps
1536  * @need_pool: return a pool
1537  *
1538  * Constructs a new query object for querying the allocation properties.
1539  *
1540  * Free-function: gst_query_unref()
1541  *
1542  * Returns: (transfer full): a new #GstQuery
1543  */
1544 GstQuery *
gst_query_new_allocation(GstCaps * caps,gboolean need_pool)1545 gst_query_new_allocation (GstCaps * caps, gboolean need_pool)
1546 {
1547   GstQuery *query;
1548   GstStructure *structure;
1549 
1550   structure = gst_structure_new_id (GST_QUARK (QUERY_ALLOCATION),
1551       GST_QUARK (CAPS), GST_TYPE_CAPS, caps,
1552       GST_QUARK (NEED_POOL), G_TYPE_BOOLEAN, need_pool, NULL);
1553 
1554   query = gst_query_new_custom (GST_QUERY_ALLOCATION, structure);
1555 
1556   return query;
1557 }
1558 
1559 /**
1560  * gst_query_parse_allocation:
1561  * @query: a #GstQuery
1562  * @caps: (out) (transfer none) (allow-none): The #GstCaps
1563  * @need_pool: (out) (allow-none): Whether a #GstBufferPool is needed
1564  *
1565  * Parse an allocation query, writing the requested caps in @caps and
1566  * whether a pool is needed in @need_pool, if the respective parameters
1567  * are non-%NULL.
1568  *
1569  * Pool details can be retrieved using gst_query_get_n_allocation_pools() and
1570  * gst_query_parse_nth_allocation_pool().
1571  */
1572 void
gst_query_parse_allocation(GstQuery * query,GstCaps ** caps,gboolean * need_pool)1573 gst_query_parse_allocation (GstQuery * query, GstCaps ** caps,
1574     gboolean * need_pool)
1575 {
1576   GstStructure *structure;
1577 
1578   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_ALLOCATION);
1579 
1580   structure = GST_QUERY_STRUCTURE (query);
1581   if (caps) {
1582     *caps = g_value_get_boxed (gst_structure_id_get_value (structure,
1583             GST_QUARK (CAPS)));
1584   }
1585   gst_structure_id_get (structure,
1586       GST_QUARK (NEED_POOL), G_TYPE_BOOLEAN, need_pool, NULL);
1587 }
1588 
1589 typedef struct
1590 {
1591   GstBufferPool *pool;
1592   guint size;
1593   guint min_buffers;
1594   guint max_buffers;
1595 } AllocationPool;
1596 
1597 static void
allocation_pool_free(AllocationPool * ap)1598 allocation_pool_free (AllocationPool * ap)
1599 {
1600   if (ap->pool)
1601     gst_object_unref (ap->pool);
1602 }
1603 
1604 /**
1605  * gst_query_add_allocation_pool:
1606  * @query: A valid #GstQuery of type GST_QUERY_ALLOCATION.
1607  * @pool: (transfer none) (allow-none): the #GstBufferPool
1608  * @size: the buffer size
1609  * @min_buffers: the min buffers
1610  * @max_buffers: the max buffers
1611  *
1612  * Set the pool parameters in @query.
1613  */
1614 void
gst_query_add_allocation_pool(GstQuery * query,GstBufferPool * pool,guint size,guint min_buffers,guint max_buffers)1615 gst_query_add_allocation_pool (GstQuery * query, GstBufferPool * pool,
1616     guint size, guint min_buffers, guint max_buffers)
1617 {
1618   GArray *array;
1619   GstStructure *structure;
1620   AllocationPool ap;
1621 
1622   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_ALLOCATION);
1623   g_return_if_fail (gst_query_is_writable (query));
1624 
1625   structure = GST_QUERY_STRUCTURE (query);
1626   array = ensure_array (structure, GST_QUARK (POOL),
1627       sizeof (AllocationPool), (GDestroyNotify) allocation_pool_free);
1628 
1629   if ((ap.pool = pool))
1630     gst_object_ref (pool);
1631   ap.size = size;
1632   ap.min_buffers = min_buffers;
1633   ap.max_buffers = max_buffers;
1634 
1635   g_array_append_val (array, ap);
1636 }
1637 
1638 /**
1639  * gst_query_get_n_allocation_pools:
1640  * @query: a GST_QUERY_ALLOCATION type query #GstQuery
1641  *
1642  * Retrieve the number of values currently stored in the
1643  * pool array of the query's structure.
1644  *
1645  * Returns: the pool array size as a #guint.
1646  */
1647 guint
gst_query_get_n_allocation_pools(GstQuery * query)1648 gst_query_get_n_allocation_pools (GstQuery * query)
1649 {
1650   GArray *array;
1651   GstStructure *structure;
1652 
1653   g_return_val_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_ALLOCATION, 0);
1654 
1655   structure = GST_QUERY_STRUCTURE (query);
1656   array = ensure_array (structure, GST_QUARK (POOL),
1657       sizeof (AllocationPool), (GDestroyNotify) allocation_pool_free);
1658 
1659   return array->len;
1660 }
1661 
1662 /**
1663  * gst_query_parse_nth_allocation_pool:
1664  * @query: A valid #GstQuery of type GST_QUERY_ALLOCATION.
1665  * @index: index to parse
1666  * @pool: (out) (allow-none) (transfer full): the #GstBufferPool
1667  * @size: (out) (allow-none): the buffer size
1668  * @min_buffers: (out) (allow-none): the min buffers
1669  * @max_buffers: (out) (allow-none): the max buffers
1670  *
1671  * Get the pool parameters in @query.
1672  *
1673  * Unref @pool with gst_object_unref() when it's not needed any more.
1674  */
1675 void
gst_query_parse_nth_allocation_pool(GstQuery * query,guint index,GstBufferPool ** pool,guint * size,guint * min_buffers,guint * max_buffers)1676 gst_query_parse_nth_allocation_pool (GstQuery * query, guint index,
1677     GstBufferPool ** pool, guint * size, guint * min_buffers,
1678     guint * max_buffers)
1679 {
1680   GArray *array;
1681   GstStructure *structure;
1682   AllocationPool *ap;
1683 
1684   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_ALLOCATION);
1685 
1686   structure = GST_QUERY_STRUCTURE (query);
1687   array = ensure_array (structure, GST_QUARK (POOL),
1688       sizeof (AllocationPool), (GDestroyNotify) allocation_pool_free);
1689   g_return_if_fail (index < array->len);
1690 
1691   ap = &g_array_index (array, AllocationPool, index);
1692 
1693   if (pool)
1694     if ((*pool = ap->pool))
1695       gst_object_ref (*pool);
1696   if (size)
1697     *size = ap->size;
1698   if (min_buffers)
1699     *min_buffers = ap->min_buffers;
1700   if (max_buffers)
1701     *max_buffers = ap->max_buffers;
1702 }
1703 
1704 /**
1705  * gst_query_set_nth_allocation_pool:
1706  * @index: index to modify
1707  * @query: A valid #GstQuery of type GST_QUERY_ALLOCATION.
1708  * @pool: (transfer none) (allow-none): the #GstBufferPool
1709  * @size: the buffer size
1710  * @min_buffers: the min buffers
1711  * @max_buffers: the max buffers
1712  *
1713  * Set the pool parameters in @query.
1714  */
1715 void
gst_query_set_nth_allocation_pool(GstQuery * query,guint index,GstBufferPool * pool,guint size,guint min_buffers,guint max_buffers)1716 gst_query_set_nth_allocation_pool (GstQuery * query, guint index,
1717     GstBufferPool * pool, guint size, guint min_buffers, guint max_buffers)
1718 {
1719   GArray *array;
1720   GstStructure *structure;
1721   AllocationPool *oldap, ap;
1722 
1723   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_ALLOCATION);
1724 
1725   structure = GST_QUERY_STRUCTURE (query);
1726   array = ensure_array (structure, GST_QUARK (POOL),
1727       sizeof (AllocationPool), (GDestroyNotify) allocation_pool_free);
1728   g_return_if_fail (index < array->len);
1729 
1730   oldap = &g_array_index (array, AllocationPool, index);
1731   allocation_pool_free (oldap);
1732 
1733   if ((ap.pool = pool))
1734     gst_object_ref (pool);
1735   ap.size = size;
1736   ap.min_buffers = min_buffers;
1737   ap.max_buffers = max_buffers;
1738   g_array_index (array, AllocationPool, index) = ap;
1739 }
1740 
1741 /**
1742  * gst_query_remove_nth_allocation_pool:
1743  * @query: a GST_QUERY_ALLOCATION type query #GstQuery
1744  * @index: position in the allocation pool array to remove
1745  *
1746  * Remove the allocation pool at @index of the allocation pool array.
1747  *
1748  * Since: 1.2
1749  */
1750 void
gst_query_remove_nth_allocation_pool(GstQuery * query,guint index)1751 gst_query_remove_nth_allocation_pool (GstQuery * query, guint index)
1752 {
1753   GArray *array;
1754   GstStructure *structure;
1755 
1756   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_ALLOCATION);
1757   g_return_if_fail (gst_query_is_writable (query));
1758 
1759   structure = GST_QUERY_STRUCTURE (query);
1760   array =
1761       ensure_array (structure, GST_QUARK (POOL), sizeof (AllocationPool),
1762       (GDestroyNotify) allocation_pool_free);
1763   g_return_if_fail (index < array->len);
1764 
1765   g_array_remove_index (array, index);
1766 }
1767 
1768 typedef struct
1769 {
1770   GType api;
1771   GstStructure *params;
1772 } AllocationMeta;
1773 
1774 static void
allocation_meta_free(AllocationMeta * am)1775 allocation_meta_free (AllocationMeta * am)
1776 {
1777   if (am->params)
1778     gst_structure_free (am->params);
1779 }
1780 
1781 /**
1782  * gst_query_add_allocation_meta:
1783  * @query: a GST_QUERY_ALLOCATION type query #GstQuery
1784  * @api: the metadata API
1785  * @params: (transfer none) (allow-none): API specific parameters
1786  *
1787  * Add @api with @params as one of the supported metadata API to @query.
1788  */
1789 void
gst_query_add_allocation_meta(GstQuery * query,GType api,const GstStructure * params)1790 gst_query_add_allocation_meta (GstQuery * query, GType api,
1791     const GstStructure * params)
1792 {
1793   GArray *array;
1794   GstStructure *structure;
1795   AllocationMeta am;
1796 
1797   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_ALLOCATION);
1798   g_return_if_fail (api != 0);
1799   g_return_if_fail (gst_query_is_writable (query));
1800 
1801   structure = GST_QUERY_STRUCTURE (query);
1802   array =
1803       ensure_array (structure, GST_QUARK (META), sizeof (AllocationMeta),
1804       (GDestroyNotify) allocation_meta_free);
1805 
1806   am.api = api;
1807   am.params = (params ? gst_structure_copy (params) : NULL);
1808 
1809   g_array_append_val (array, am);
1810 }
1811 
1812 /**
1813  * gst_query_get_n_allocation_metas:
1814  * @query: a GST_QUERY_ALLOCATION type query #GstQuery
1815  *
1816  * Retrieve the number of values currently stored in the
1817  * meta API array of the query's structure.
1818  *
1819  * Returns: the metadata API array size as a #guint.
1820  */
1821 guint
gst_query_get_n_allocation_metas(GstQuery * query)1822 gst_query_get_n_allocation_metas (GstQuery * query)
1823 {
1824   GArray *array;
1825   GstStructure *structure;
1826 
1827   g_return_val_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_ALLOCATION, 0);
1828 
1829   structure = GST_QUERY_STRUCTURE (query);
1830   array =
1831       ensure_array (structure, GST_QUARK (META), sizeof (AllocationMeta),
1832       (GDestroyNotify) allocation_meta_free);
1833 
1834   return array->len;
1835 }
1836 
1837 /**
1838  * gst_query_parse_nth_allocation_meta:
1839  * @query: a GST_QUERY_ALLOCATION type query #GstQuery
1840  * @index: position in the metadata API array to read
1841  * @params: (out) (transfer none) (allow-none): API specific parameters
1842  *
1843  * Parse an available query and get the metadata API
1844  * at @index of the metadata API array.
1845  *
1846  * Returns: a #GType of the metadata API at @index.
1847  */
1848 GType
gst_query_parse_nth_allocation_meta(GstQuery * query,guint index,const GstStructure ** params)1849 gst_query_parse_nth_allocation_meta (GstQuery * query, guint index,
1850     const GstStructure ** params)
1851 {
1852   GArray *array;
1853   GstStructure *structure;
1854   AllocationMeta *am;
1855 
1856   g_return_val_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_ALLOCATION, 0);
1857 
1858   structure = GST_QUERY_STRUCTURE (query);
1859   array =
1860       ensure_array (structure, GST_QUARK (META), sizeof (AllocationMeta),
1861       (GDestroyNotify) allocation_meta_free);
1862 
1863   g_return_val_if_fail (index < array->len, 0);
1864 
1865   am = &g_array_index (array, AllocationMeta, index);
1866 
1867   if (params)
1868     *params = am->params;
1869 
1870   return am->api;
1871 }
1872 
1873 /**
1874  * gst_query_remove_nth_allocation_meta:
1875  * @query: a GST_QUERY_ALLOCATION type query #GstQuery
1876  * @index: position in the metadata API array to remove
1877  *
1878  * Remove the metadata API at @index of the metadata API array.
1879  */
1880 void
gst_query_remove_nth_allocation_meta(GstQuery * query,guint index)1881 gst_query_remove_nth_allocation_meta (GstQuery * query, guint index)
1882 {
1883   GArray *array;
1884   GstStructure *structure;
1885 
1886   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_ALLOCATION);
1887   g_return_if_fail (gst_query_is_writable (query));
1888 
1889   structure = GST_QUERY_STRUCTURE (query);
1890   array =
1891       ensure_array (structure, GST_QUARK (META), sizeof (AllocationMeta),
1892       (GDestroyNotify) allocation_meta_free);
1893   g_return_if_fail (index < array->len);
1894 
1895   g_array_remove_index (array, index);
1896 }
1897 
1898 /**
1899  * gst_query_find_allocation_meta:
1900  * @query: a GST_QUERY_ALLOCATION type query #GstQuery
1901  * @api: the metadata API
1902  * @index: (out) (transfer none) (allow-none): the index
1903  *
1904  * Check if @query has metadata @api set. When this function returns %TRUE,
1905  * @index will contain the index where the requested API and the parameters
1906  * can be found.
1907  *
1908  * Returns: %TRUE when @api is in the list of metadata.
1909  */
1910 gboolean
gst_query_find_allocation_meta(GstQuery * query,GType api,guint * index)1911 gst_query_find_allocation_meta (GstQuery * query, GType api, guint * index)
1912 {
1913   GArray *array;
1914   GstStructure *structure;
1915   guint i, len;
1916 
1917   g_return_val_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_ALLOCATION, FALSE);
1918   g_return_val_if_fail (api != 0, FALSE);
1919 
1920   structure = GST_QUERY_STRUCTURE (query);
1921   array =
1922       ensure_array (structure, GST_QUARK (META), sizeof (AllocationMeta),
1923       (GDestroyNotify) allocation_meta_free);
1924 
1925   len = array->len;
1926   for (i = 0; i < len; i++) {
1927     AllocationMeta *am = &g_array_index (array, AllocationMeta, i);
1928     if (am->api == api) {
1929       if (index)
1930         *index = i;
1931       return TRUE;
1932     }
1933   }
1934   return FALSE;
1935 }
1936 
1937 typedef struct
1938 {
1939   GstAllocator *allocator;
1940   GstAllocationParams params;
1941 } AllocationParam;
1942 
1943 static void
allocation_param_free(AllocationParam * ap)1944 allocation_param_free (AllocationParam * ap)
1945 {
1946   if (ap->allocator)
1947     gst_object_unref (ap->allocator);
1948 }
1949 
1950 /**
1951  * gst_query_add_allocation_param:
1952  * @query: a GST_QUERY_ALLOCATION type query #GstQuery
1953  * @allocator: (transfer none) (allow-none): the memory allocator
1954  * @params: (transfer none) (allow-none): a #GstAllocationParams
1955  *
1956  * Add @allocator and its @params as a supported memory allocator.
1957  */
1958 void
gst_query_add_allocation_param(GstQuery * query,GstAllocator * allocator,const GstAllocationParams * params)1959 gst_query_add_allocation_param (GstQuery * query, GstAllocator * allocator,
1960     const GstAllocationParams * params)
1961 {
1962   GArray *array;
1963   GstStructure *structure;
1964   AllocationParam ap;
1965 
1966   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_ALLOCATION);
1967   g_return_if_fail (gst_query_is_writable (query));
1968   g_return_if_fail (allocator != NULL || params != NULL);
1969 
1970   structure = GST_QUERY_STRUCTURE (query);
1971   array = ensure_array (structure, GST_QUARK (ALLOCATOR),
1972       sizeof (AllocationParam), (GDestroyNotify) allocation_param_free);
1973 
1974   if ((ap.allocator = allocator))
1975     gst_object_ref (allocator);
1976   if (params)
1977     ap.params = *params;
1978   else
1979     gst_allocation_params_init (&ap.params);
1980 
1981   g_array_append_val (array, ap);
1982 }
1983 
1984 /**
1985  * gst_query_get_n_allocation_params:
1986  * @query: a GST_QUERY_ALLOCATION type query #GstQuery
1987  *
1988  * Retrieve the number of values currently stored in the
1989  * allocator params array of the query's structure.
1990  *
1991  * If no memory allocator is specified, the downstream element can handle
1992  * the default memory allocator. The first memory allocator in the query
1993  * should be generic and allow mapping to system memory, all following
1994  * allocators should be ordered by preference with the preferred one first.
1995  *
1996  * Returns: the allocator array size as a #guint.
1997  */
1998 guint
gst_query_get_n_allocation_params(GstQuery * query)1999 gst_query_get_n_allocation_params (GstQuery * query)
2000 {
2001   GArray *array;
2002   GstStructure *structure;
2003 
2004   g_return_val_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_ALLOCATION, 0);
2005 
2006   structure = GST_QUERY_STRUCTURE (query);
2007   array = ensure_array (structure, GST_QUARK (ALLOCATOR),
2008       sizeof (AllocationParam), (GDestroyNotify) allocation_param_free);
2009 
2010   return array->len;
2011 }
2012 
2013 /**
2014  * gst_query_parse_nth_allocation_param:
2015  * @query: a GST_QUERY_ALLOCATION type query #GstQuery
2016  * @index: position in the allocator array to read
2017  * @allocator: (out) (transfer full) (allow-none): variable to hold the result
2018  * @params: (out) (allow-none): parameters for the allocator
2019  *
2020  * Parse an available query and get the allocator and its params
2021  * at @index of the allocator array.
2022  */
2023 void
gst_query_parse_nth_allocation_param(GstQuery * query,guint index,GstAllocator ** allocator,GstAllocationParams * params)2024 gst_query_parse_nth_allocation_param (GstQuery * query, guint index,
2025     GstAllocator ** allocator, GstAllocationParams * params)
2026 {
2027   GArray *array;
2028   GstStructure *structure;
2029   AllocationParam *ap;
2030 
2031   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_ALLOCATION);
2032 
2033   structure = GST_QUERY_STRUCTURE (query);
2034   array = ensure_array (structure, GST_QUARK (ALLOCATOR),
2035       sizeof (AllocationParam), (GDestroyNotify) allocation_param_free);
2036   g_return_if_fail (index < array->len);
2037 
2038   ap = &g_array_index (array, AllocationParam, index);
2039 
2040   if (allocator)
2041     if ((*allocator = ap->allocator))
2042       gst_object_ref (*allocator);
2043   if (params)
2044     *params = ap->params;
2045 }
2046 
2047 /**
2048  * gst_query_set_nth_allocation_param:
2049  * @query: a GST_QUERY_ALLOCATION type query #GstQuery
2050  * @index: position in the allocator array to set
2051  * @allocator: (transfer none) (allow-none): new allocator to set
2052  * @params: (transfer none) (allow-none): parameters for the allocator
2053  *
2054  * Parse an available query and get the allocator and its params
2055  * at @index of the allocator array.
2056  */
2057 void
gst_query_set_nth_allocation_param(GstQuery * query,guint index,GstAllocator * allocator,const GstAllocationParams * params)2058 gst_query_set_nth_allocation_param (GstQuery * query, guint index,
2059     GstAllocator * allocator, const GstAllocationParams * params)
2060 {
2061   GArray *array;
2062   GstStructure *structure;
2063   AllocationParam *old, ap;
2064 
2065   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_ALLOCATION);
2066 
2067   structure = GST_QUERY_STRUCTURE (query);
2068   array = ensure_array (structure, GST_QUARK (ALLOCATOR),
2069       sizeof (AllocationParam), (GDestroyNotify) allocation_param_free);
2070   g_return_if_fail (index < array->len);
2071 
2072   old = &g_array_index (array, AllocationParam, index);
2073   allocation_param_free (old);
2074 
2075   if ((ap.allocator = allocator))
2076     gst_object_ref (allocator);
2077   if (params)
2078     ap.params = *params;
2079   else
2080     gst_allocation_params_init (&ap.params);
2081 
2082   g_array_index (array, AllocationParam, index) = ap;
2083 }
2084 
2085 /**
2086  * gst_query_remove_nth_allocation_param:
2087  * @query: a GST_QUERY_ALLOCATION type query #GstQuery
2088  * @index: position in the allocation param array to remove
2089  *
2090  * Remove the allocation param at @index of the allocation param array.
2091  *
2092  * Since: 1.2
2093  */
2094 void
gst_query_remove_nth_allocation_param(GstQuery * query,guint index)2095 gst_query_remove_nth_allocation_param (GstQuery * query, guint index)
2096 {
2097   GArray *array;
2098   GstStructure *structure;
2099 
2100   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_ALLOCATION);
2101   g_return_if_fail (gst_query_is_writable (query));
2102 
2103   structure = GST_QUERY_STRUCTURE (query);
2104   array =
2105       ensure_array (structure, GST_QUARK (ALLOCATOR), sizeof (AllocationParam),
2106       (GDestroyNotify) allocation_param_free);
2107   g_return_if_fail (index < array->len);
2108 
2109   g_array_remove_index (array, index);
2110 }
2111 
2112 /**
2113  * gst_query_new_scheduling:
2114  *
2115  * Constructs a new query object for querying the scheduling properties.
2116  *
2117  * Free-function: gst_query_unref()
2118  *
2119  * Returns: (transfer full): a new #GstQuery
2120  */
2121 GstQuery *
gst_query_new_scheduling(void)2122 gst_query_new_scheduling (void)
2123 {
2124   GstQuery *query;
2125   GstStructure *structure;
2126 
2127   structure = gst_structure_new_id (GST_QUARK (QUERY_SCHEDULING),
2128       GST_QUARK (FLAGS), GST_TYPE_SCHEDULING_FLAGS, 0,
2129       GST_QUARK (MINSIZE), G_TYPE_INT, 1,
2130       GST_QUARK (MAXSIZE), G_TYPE_INT, -1,
2131       GST_QUARK (ALIGN), G_TYPE_INT, 0, NULL);
2132   query = gst_query_new_custom (GST_QUERY_SCHEDULING, structure);
2133 
2134   return query;
2135 }
2136 
2137 /**
2138  * gst_query_set_scheduling:
2139  * @query: A valid #GstQuery of type GST_QUERY_SCHEDULING.
2140  * @flags: #GstSchedulingFlags
2141  * @minsize: the suggested minimum size of pull requests
2142  * @maxsize: the suggested maximum size of pull requests
2143  * @align: the suggested alignment of pull requests
2144  *
2145  * Set the scheduling properties.
2146  */
2147 void
gst_query_set_scheduling(GstQuery * query,GstSchedulingFlags flags,gint minsize,gint maxsize,gint align)2148 gst_query_set_scheduling (GstQuery * query, GstSchedulingFlags flags,
2149     gint minsize, gint maxsize, gint align)
2150 {
2151   GstStructure *structure;
2152 
2153   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_SCHEDULING);
2154   g_return_if_fail (gst_query_is_writable (query));
2155 
2156   structure = GST_QUERY_STRUCTURE (query);
2157   gst_structure_id_set (structure,
2158       GST_QUARK (FLAGS), GST_TYPE_SCHEDULING_FLAGS, flags,
2159       GST_QUARK (MINSIZE), G_TYPE_INT, minsize,
2160       GST_QUARK (MAXSIZE), G_TYPE_INT, maxsize,
2161       GST_QUARK (ALIGN), G_TYPE_INT, align, NULL);
2162 }
2163 
2164 /**
2165  * gst_query_parse_scheduling:
2166  * @query: A valid #GstQuery of type GST_QUERY_SCHEDULING.
2167  * @flags: (out) (allow-none): #GstSchedulingFlags
2168  * @minsize: (out) (allow-none): the suggested minimum size of pull requests
2169  * @maxsize: (out) (allow-none): the suggested maximum size of pull requests:
2170  * @align: (out) (allow-none): the suggested alignment of pull requests
2171  *
2172  * Set the scheduling properties.
2173  */
2174 void
gst_query_parse_scheduling(GstQuery * query,GstSchedulingFlags * flags,gint * minsize,gint * maxsize,gint * align)2175 gst_query_parse_scheduling (GstQuery * query, GstSchedulingFlags * flags,
2176     gint * minsize, gint * maxsize, gint * align)
2177 {
2178   GstStructure *structure;
2179 
2180   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_SCHEDULING);
2181 
2182   structure = GST_QUERY_STRUCTURE (query);
2183   gst_structure_id_get (structure,
2184       GST_QUARK (FLAGS), GST_TYPE_SCHEDULING_FLAGS, flags,
2185       GST_QUARK (MINSIZE), G_TYPE_INT, minsize,
2186       GST_QUARK (MAXSIZE), G_TYPE_INT, maxsize,
2187       GST_QUARK (ALIGN), G_TYPE_INT, align, NULL);
2188 }
2189 
2190 /**
2191  * gst_query_add_scheduling_mode:
2192  * @query: a GST_QUERY_SCHEDULING type query #GstQuery
2193  * @mode: a #GstPadMode
2194  *
2195  * Add @mode as one of the supported scheduling modes to @query.
2196  */
2197 void
gst_query_add_scheduling_mode(GstQuery * query,GstPadMode mode)2198 gst_query_add_scheduling_mode (GstQuery * query, GstPadMode mode)
2199 {
2200   GstStructure *structure;
2201   GArray *array;
2202 
2203   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_SCHEDULING);
2204   g_return_if_fail (gst_query_is_writable (query));
2205 
2206   structure = GST_QUERY_STRUCTURE (query);
2207   array =
2208       ensure_array (structure, GST_QUARK (MODES), sizeof (GstPadMode), NULL);
2209 
2210   g_array_append_val (array, mode);
2211 }
2212 
2213 /**
2214  * gst_query_get_n_scheduling_modes:
2215  * @query: a GST_QUERY_SCHEDULING type query #GstQuery
2216  *
2217  * Retrieve the number of values currently stored in the
2218  * scheduling mode array of the query's structure.
2219  *
2220  * Returns: the scheduling mode array size as a #guint.
2221  */
2222 guint
gst_query_get_n_scheduling_modes(GstQuery * query)2223 gst_query_get_n_scheduling_modes (GstQuery * query)
2224 {
2225   GArray *array;
2226   GstStructure *structure;
2227 
2228   g_return_val_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_SCHEDULING, 0);
2229 
2230   structure = GST_QUERY_STRUCTURE (query);
2231   array =
2232       ensure_array (structure, GST_QUARK (MODES), sizeof (GstPadMode), NULL);
2233 
2234   return array->len;
2235 }
2236 
2237 /**
2238  * gst_query_parse_nth_scheduling_mode:
2239  * @query: a GST_QUERY_SCHEDULING type query #GstQuery
2240  * @index: position in the scheduling modes array to read
2241  *
2242  * Parse an available query and get the scheduling mode
2243  * at @index of the scheduling modes array.
2244  *
2245  * Returns: a #GstPadMode of the scheduling mode at @index.
2246  */
2247 GstPadMode
gst_query_parse_nth_scheduling_mode(GstQuery * query,guint index)2248 gst_query_parse_nth_scheduling_mode (GstQuery * query, guint index)
2249 {
2250   GstStructure *structure;
2251   GArray *array;
2252 
2253   g_return_val_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_SCHEDULING,
2254       GST_PAD_MODE_NONE);
2255 
2256   structure = GST_QUERY_STRUCTURE (query);
2257   array =
2258       ensure_array (structure, GST_QUARK (MODES), sizeof (GstPadMode), NULL);
2259   g_return_val_if_fail (index < array->len, GST_PAD_MODE_NONE);
2260 
2261   return g_array_index (array, GstPadMode, index);
2262 }
2263 
2264 /**
2265  * gst_query_has_scheduling_mode:
2266  * @query: a GST_QUERY_SCHEDULING type query #GstQuery
2267  * @mode: the scheduling mode
2268  *
2269  * Check if @query has scheduling mode set.
2270  *
2271  * > When checking if upstream supports pull mode, it is usually not
2272  * > enough to just check for GST_PAD_MODE_PULL with this function, you
2273  * > also want to check whether the scheduling flags returned by
2274  * > gst_query_parse_scheduling() have the seeking flag set (meaning
2275  * > random access is supported, not only sequential pulls).
2276  *
2277  * Returns: %TRUE when @mode is in the list of scheduling modes.
2278  */
2279 gboolean
gst_query_has_scheduling_mode(GstQuery * query,GstPadMode mode)2280 gst_query_has_scheduling_mode (GstQuery * query, GstPadMode mode)
2281 {
2282   GstStructure *structure;
2283   GArray *array;
2284   guint i, len;
2285 
2286   g_return_val_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_SCHEDULING, FALSE);
2287 
2288   structure = GST_QUERY_STRUCTURE (query);
2289   array =
2290       ensure_array (structure, GST_QUARK (MODES), sizeof (GstPadMode), NULL);
2291 
2292   len = array->len;
2293   for (i = 0; i < len; i++) {
2294     if (mode == g_array_index (array, GstPadMode, i))
2295       return TRUE;
2296   }
2297   return FALSE;
2298 }
2299 
2300 /**
2301  * gst_query_has_scheduling_mode_with_flags:
2302  * @query: a GST_QUERY_SCHEDULING type query #GstQuery
2303  * @mode: the scheduling mode
2304  * @flags: #GstSchedulingFlags
2305  *
2306  * Check if @query has scheduling mode set and @flags is set in
2307  * query scheduling flags.
2308  *
2309  * Returns: %TRUE when @mode is in the list of scheduling modes
2310  *    and @flags are compatible with query flags.
2311  */
2312 gboolean
gst_query_has_scheduling_mode_with_flags(GstQuery * query,GstPadMode mode,GstSchedulingFlags flags)2313 gst_query_has_scheduling_mode_with_flags (GstQuery * query, GstPadMode mode,
2314     GstSchedulingFlags flags)
2315 {
2316   GstSchedulingFlags sched_flags;
2317 
2318   g_return_val_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_SCHEDULING, FALSE);
2319 
2320   gst_query_parse_scheduling (query, &sched_flags, NULL, NULL, NULL);
2321 
2322   return ((flags & sched_flags) == flags) &&
2323       gst_query_has_scheduling_mode (query, mode);
2324 }
2325 
2326 /**
2327  * gst_query_new_accept_caps:
2328  * @caps: a fixed #GstCaps
2329  *
2330  * Constructs a new query object for querying if @caps are accepted.
2331  *
2332  * Free-function: gst_query_unref()
2333  *
2334  * Returns: (transfer full): a new #GstQuery
2335  */
2336 GstQuery *
gst_query_new_accept_caps(GstCaps * caps)2337 gst_query_new_accept_caps (GstCaps * caps)
2338 {
2339   GstQuery *query;
2340   GstStructure *structure;
2341 
2342   g_return_val_if_fail (gst_caps_is_fixed (caps), NULL);
2343 
2344   structure = gst_structure_new_id (GST_QUARK (QUERY_ACCEPT_CAPS),
2345       GST_QUARK (CAPS), GST_TYPE_CAPS, caps,
2346       GST_QUARK (RESULT), G_TYPE_BOOLEAN, FALSE, NULL);
2347   query = gst_query_new_custom (GST_QUERY_ACCEPT_CAPS, structure);
2348 
2349   return query;
2350 }
2351 
2352 /**
2353  * gst_query_parse_accept_caps:
2354  * @query: The query to parse
2355  * @caps: (out) (transfer none): A pointer to the caps
2356  *
2357  * Get the caps from @query. The caps remains valid as long as @query remains
2358  * valid.
2359  */
2360 void
gst_query_parse_accept_caps(GstQuery * query,GstCaps ** caps)2361 gst_query_parse_accept_caps (GstQuery * query, GstCaps ** caps)
2362 {
2363   GstStructure *structure;
2364 
2365   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_ACCEPT_CAPS);
2366   g_return_if_fail (caps != NULL);
2367 
2368   structure = GST_QUERY_STRUCTURE (query);
2369   *caps = g_value_get_boxed (gst_structure_id_get_value (structure,
2370           GST_QUARK (CAPS)));
2371 }
2372 
2373 /**
2374  * gst_query_set_accept_caps_result:
2375  * @query: a GST_QUERY_ACCEPT_CAPS type query #GstQuery
2376  * @result: the result to set
2377  *
2378  * Set @result as the result for the @query.
2379  */
2380 void
gst_query_set_accept_caps_result(GstQuery * query,gboolean result)2381 gst_query_set_accept_caps_result (GstQuery * query, gboolean result)
2382 {
2383   GstStructure *structure;
2384 
2385   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_ACCEPT_CAPS);
2386   g_return_if_fail (gst_query_is_writable (query));
2387 
2388   structure = GST_QUERY_STRUCTURE (query);
2389   gst_structure_id_set (structure,
2390       GST_QUARK (RESULT), G_TYPE_BOOLEAN, result, NULL);
2391 }
2392 
2393 /**
2394  * gst_query_parse_accept_caps_result:
2395  * @query: a GST_QUERY_ACCEPT_CAPS type query #GstQuery
2396  * @result: (out) (allow-none): location for the result
2397  *
2398  * Parse the result from @query and store in @result.
2399  */
2400 void
gst_query_parse_accept_caps_result(GstQuery * query,gboolean * result)2401 gst_query_parse_accept_caps_result (GstQuery * query, gboolean * result)
2402 {
2403   GstStructure *structure;
2404 
2405   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_ACCEPT_CAPS);
2406 
2407   structure = GST_QUERY_STRUCTURE (query);
2408   gst_structure_id_get (structure,
2409       GST_QUARK (RESULT), G_TYPE_BOOLEAN, result, NULL);
2410 }
2411 
2412 /**
2413  * gst_query_new_caps:
2414  * @filter: a filter
2415  *
2416  * Constructs a new query object for querying the caps.
2417  *
2418  * The CAPS query should return the allowable caps for a pad in the context
2419  * of the element's state, its link to other elements, and the devices or files
2420  * it has opened. These caps must be a subset of the pad template caps. In the
2421  * NULL state with no links, the CAPS query should ideally return the same caps
2422  * as the pad template. In rare circumstances, an object property can affect
2423  * the caps returned by the CAPS query, but this is discouraged.
2424  *
2425  * For most filters, the caps returned by CAPS query is directly affected by the
2426  * allowed caps on other pads. For demuxers and decoders, the caps returned by
2427  * the srcpad's getcaps function is directly related to the stream data. Again,
2428  * the CAPS query should return the most specific caps it reasonably can, since this
2429  * helps with autoplugging.
2430  *
2431  * The @filter is used to restrict the result caps, only the caps matching
2432  * @filter should be returned from the CAPS query. Specifying a filter might
2433  * greatly reduce the amount of processing an element needs to do.
2434  *
2435  * Free-function: gst_query_unref()
2436  *
2437  * Returns: (transfer full): a new #GstQuery
2438  */
2439 GstQuery *
gst_query_new_caps(GstCaps * filter)2440 gst_query_new_caps (GstCaps * filter)
2441 {
2442   GstQuery *query;
2443   GstStructure *structure;
2444 
2445   structure = gst_structure_new_id (GST_QUARK (QUERY_CAPS),
2446       GST_QUARK (FILTER), GST_TYPE_CAPS, filter,
2447       GST_QUARK (CAPS), GST_TYPE_CAPS, NULL, NULL);
2448   query = gst_query_new_custom (GST_QUERY_CAPS, structure);
2449 
2450   return query;
2451 }
2452 
2453 /**
2454  * gst_query_parse_caps:
2455  * @query: The query to parse
2456  * @filter: (out) (transfer none): A pointer to the caps filter
2457  *
2458  * Get the filter from the caps @query. The caps remains valid as long as
2459  * @query remains valid.
2460  */
2461 void
gst_query_parse_caps(GstQuery * query,GstCaps ** filter)2462 gst_query_parse_caps (GstQuery * query, GstCaps ** filter)
2463 {
2464   GstStructure *structure;
2465 
2466   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_CAPS);
2467   g_return_if_fail (filter != NULL);
2468 
2469   structure = GST_QUERY_STRUCTURE (query);
2470   *filter = g_value_get_boxed (gst_structure_id_get_value (structure,
2471           GST_QUARK (FILTER)));
2472 }
2473 
2474 /**
2475  * gst_query_set_caps_result:
2476  * @query: The query to use
2477  * @caps: (in): A pointer to the caps
2478  *
2479  * Set the @caps result in @query.
2480  */
2481 void
gst_query_set_caps_result(GstQuery * query,GstCaps * caps)2482 gst_query_set_caps_result (GstQuery * query, GstCaps * caps)
2483 {
2484   GstStructure *structure;
2485 
2486   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_CAPS);
2487   g_return_if_fail (gst_query_is_writable (query));
2488 
2489   structure = GST_QUERY_STRUCTURE (query);
2490   gst_structure_id_set (structure, GST_QUARK (CAPS), GST_TYPE_CAPS, caps, NULL);
2491 }
2492 
2493 /**
2494  * gst_query_parse_caps_result:
2495  * @query: The query to parse
2496  * @caps: (out) (transfer none): A pointer to the caps
2497  *
2498  * Get the caps result from @query. The caps remains valid as long as
2499  * @query remains valid.
2500  */
2501 void
gst_query_parse_caps_result(GstQuery * query,GstCaps ** caps)2502 gst_query_parse_caps_result (GstQuery * query, GstCaps ** caps)
2503 {
2504   GstStructure *structure;
2505 
2506   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_CAPS);
2507   g_return_if_fail (caps != NULL);
2508 
2509   structure = GST_QUERY_STRUCTURE (query);
2510   *caps = g_value_get_boxed (gst_structure_id_get_value (structure,
2511           GST_QUARK (CAPS)));
2512 }
2513 
2514 #if 0
2515 void
2516 gst_query_intersect_caps_result (GstQuery * query, GstCaps * filter,
2517     GstCapsIntersectMode mode)
2518 {
2519   GstCaps *res, *caps = NULL;
2520 
2521   gst_query_parse_caps_result (query, &caps);
2522   res = gst_caps_intersect_full (filter, caps, GST_CAPS_INTERSECT_FIRST);
2523   gst_query_set_caps_result (query, res);
2524   gst_caps_unref (res);
2525 }
2526 #endif
2527 
2528 /**
2529  * gst_query_new_drain:
2530  *
2531  * Constructs a new query object for querying the drain state.
2532  *
2533  * Free-function: gst_query_unref()
2534  *
2535  * Returns: (transfer full): a new #GstQuery
2536  */
2537 GstQuery *
gst_query_new_drain(void)2538 gst_query_new_drain (void)
2539 {
2540   GstQuery *query;
2541   GstStructure *structure;
2542 
2543   structure = gst_structure_new_id_empty (GST_QUARK (QUERY_DRAIN));
2544   query = gst_query_new_custom (GST_QUERY_DRAIN, structure);
2545 
2546   return query;
2547 }
2548 
2549 /**
2550  * gst_query_new_context:
2551  * @context_type: Context type to query
2552  *
2553  * Constructs a new query object for querying the pipeline-local context.
2554  *
2555  * Free-function: gst_query_unref()
2556  *
2557  * Returns: (transfer full): a new #GstQuery
2558  *
2559  * Since: 1.2
2560  */
2561 GstQuery *
gst_query_new_context(const gchar * context_type)2562 gst_query_new_context (const gchar * context_type)
2563 {
2564   GstQuery *query;
2565   GstStructure *structure;
2566 
2567   g_return_val_if_fail (context_type != NULL, NULL);
2568 
2569   structure = gst_structure_new_id (GST_QUARK (QUERY_CONTEXT),
2570       GST_QUARK (CONTEXT_TYPE), G_TYPE_STRING, context_type, NULL);
2571   query = gst_query_new_custom (GST_QUERY_CONTEXT, structure);
2572 
2573   return query;
2574 }
2575 
2576 /**
2577  * gst_query_set_context:
2578  * @query: a #GstQuery with query type GST_QUERY_CONTEXT
2579  * @context: the requested #GstContext
2580  *
2581  * Answer a context query by setting the requested context.
2582  *
2583  * Since: 1.2
2584  */
2585 void
gst_query_set_context(GstQuery * query,GstContext * context)2586 gst_query_set_context (GstQuery * query, GstContext * context)
2587 {
2588   GstStructure *s;
2589   const gchar *context_type;
2590 
2591   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_CONTEXT);
2592 
2593   gst_query_parse_context_type (query, &context_type);
2594   g_return_if_fail (strcmp (gst_context_get_context_type (context),
2595           context_type) == 0);
2596 
2597   s = GST_QUERY_STRUCTURE (query);
2598 
2599   gst_structure_id_set (s,
2600       GST_QUARK (CONTEXT), GST_TYPE_CONTEXT, context, NULL);
2601 }
2602 
2603 /**
2604  * gst_query_parse_context:
2605  * @query: The query to parse
2606  * @context: (out) (transfer none): A pointer to store the #GstContext
2607  *
2608  * Get the context from the context @query. The context remains valid as long as
2609  * @query remains valid.
2610  *
2611  * Since: 1.2
2612  */
2613 void
gst_query_parse_context(GstQuery * query,GstContext ** context)2614 gst_query_parse_context (GstQuery * query, GstContext ** context)
2615 {
2616   GstStructure *structure;
2617   const GValue *v;
2618 
2619   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_CONTEXT);
2620   g_return_if_fail (context != NULL);
2621 
2622   structure = GST_QUERY_STRUCTURE (query);
2623   v = gst_structure_id_get_value (structure, GST_QUARK (CONTEXT));
2624   if (v)
2625     *context = g_value_get_boxed (v);
2626   else
2627     *context = NULL;
2628 }
2629 
2630 /**
2631  * gst_query_parse_context_type:
2632  * @query: a GST_QUERY_CONTEXT type query
2633  * @context_type: (out) (transfer none) (allow-none): the context type, or %NULL
2634  *
2635  * Parse a context type from an existing GST_QUERY_CONTEXT query.
2636  *
2637  * Returns: a #gboolean indicating if the parsing succeeded.
2638  *
2639  * Since: 1.2
2640  */
2641 gboolean
gst_query_parse_context_type(GstQuery * query,const gchar ** context_type)2642 gst_query_parse_context_type (GstQuery * query, const gchar ** context_type)
2643 {
2644   GstStructure *structure;
2645   const GValue *value;
2646 
2647   g_return_val_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_CONTEXT, FALSE);
2648 
2649   structure = GST_QUERY_STRUCTURE (query);
2650 
2651   if (context_type) {
2652     value = gst_structure_id_get_value (structure, GST_QUARK (CONTEXT_TYPE));
2653     *context_type = g_value_get_string (value);
2654   }
2655 
2656   return TRUE;
2657 }
2658 
2659 /**
2660  * gst_query_new_bitrate:
2661  *
2662  * Constructs a new query object for querying the bitrate.
2663  *
2664  * Free-function: gst_query_unref()
2665  *
2666  * Returns: (transfer full): a new #GstQuery
2667  *
2668  * Since: 1.16
2669  */
2670 GstQuery *
gst_query_new_bitrate(void)2671 gst_query_new_bitrate (void)
2672 {
2673   GstQuery *query;
2674   GstStructure *structure;
2675 
2676   structure = gst_structure_new_id_empty (GST_QUARK (QUERY_BITRATE));
2677   query = gst_query_new_custom (GST_QUERY_BITRATE, structure);
2678 
2679   return query;
2680 }
2681 
2682 /**
2683  * gst_query_set_bitrate:
2684  * @query: a GST_QUERY_BITRATE type #GstQuery
2685  * @nominal_bitrate: the nominal bitrate in bits per second
2686  *
2687  * Set the results of a bitrate query.  The nominal bitrate is the average
2688  * bitrate expected over the length of the stream as advertised in file
2689  * headers (or similar).
2690  *
2691  * Since: 1.16
2692  */
2693 void
gst_query_set_bitrate(GstQuery * query,guint nominal_bitrate)2694 gst_query_set_bitrate (GstQuery * query, guint nominal_bitrate)
2695 {
2696   GstStructure *s;
2697 
2698   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_BITRATE);
2699 
2700   s = GST_QUERY_STRUCTURE (query);
2701 
2702   gst_structure_id_set (s,
2703       GST_QUARK (NOMINAL_BITRATE), G_TYPE_UINT, nominal_bitrate, NULL);
2704 }
2705 
2706 /**
2707  * gst_query_parse_bitrate:
2708  * @query: a GST_QUERY_BITRATE type #GstQuery
2709  * @nominal_bitrate: (out) (allow-none): The resulting bitrate in bits per second
2710  *
2711  * Get the results of a bitrate query. See also gst_query_set_bitrate().
2712  *
2713  * Since: 1.16
2714  */
2715 void
gst_query_parse_bitrate(GstQuery * query,guint * nominal_bitrate)2716 gst_query_parse_bitrate (GstQuery * query, guint * nominal_bitrate)
2717 {
2718   GstStructure *structure;
2719   const GValue *value;
2720 
2721   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_BITRATE);
2722 
2723   structure = GST_QUERY_STRUCTURE (query);
2724 
2725   if (nominal_bitrate) {
2726     value = gst_structure_id_get_value (structure, GST_QUARK (NOMINAL_BITRATE));
2727     *nominal_bitrate = g_value_get_uint (value);
2728   }
2729 }
2730 
2731 /**
2732  * gst_query_ref:
2733  * @q: a #GstQuery to increase the refcount of.
2734  *
2735  * Increases the refcount of the given query by one.
2736  *
2737  * Returns: @q
2738  */
2739 GstQuery *
gst_query_ref(GstQuery * q)2740 gst_query_ref (GstQuery * q)
2741 {
2742   return GST_QUERY_CAST (gst_mini_object_ref (GST_MINI_OBJECT_CAST (q)));
2743 }
2744 
2745 /**
2746  * gst_query_unref: (skip)
2747  * @q: a #GstQuery to decrease the refcount of.
2748  *
2749  * Decreases the refcount of the query. If the refcount reaches 0, the query
2750  * will be freed.
2751  */
2752 void
gst_query_unref(GstQuery * q)2753 gst_query_unref (GstQuery * q)
2754 {
2755   gst_mini_object_unref (GST_MINI_OBJECT_CAST (q));
2756 }
2757 
2758 /**
2759  * gst_clear_query: (skip)
2760  * @query_ptr: a pointer to a #GstQuery reference
2761  *
2762  * Clears a reference to a #GstQuery.
2763  *
2764  * @query_ptr must not be %NULL.
2765  *
2766  * If the reference is %NULL then this function does nothing. Otherwise, the
2767  * reference count of the query is decreased and the pointer is set to %NULL.
2768  *
2769  * Since: 1.16
2770  */
2771 void
gst_clear_query(GstQuery ** query_ptr)2772 gst_clear_query (GstQuery ** query_ptr)
2773 {
2774   gst_clear_mini_object ((GstMiniObject **) query_ptr);
2775 }
2776 
2777 /**
2778  * gst_query_copy: (skip)
2779  * @q: a #GstQuery to copy.
2780  *
2781  * Copies the given query using the copy function of the parent #GstStructure.
2782  *
2783  * Free-function: gst_query_unref
2784  *
2785  * Returns: (transfer full): a new copy of @q.
2786  */
2787 GstQuery *
gst_query_copy(const GstQuery * q)2788 gst_query_copy (const GstQuery * q)
2789 {
2790   return GST_QUERY_CAST (gst_mini_object_copy (GST_MINI_OBJECT_CONST_CAST (q)));
2791 }
2792 
2793 /**
2794  * gst_query_replace: (skip)
2795  * @old_query: (inout) (transfer full) (nullable): pointer to a pointer to a
2796  *     #GstQuery to be replaced.
2797  * @new_query: (allow-none) (transfer none): pointer to a #GstQuery that will
2798  *     replace the query pointed to by @old_query.
2799  *
2800  * Modifies a pointer to a #GstQuery to point to a different #GstQuery. The
2801  * modification is done atomically (so this is useful for ensuring thread safety
2802  * in some cases), and the reference counts are updated appropriately (the old
2803  * query is unreffed, the new one is reffed).
2804  *
2805  * Either @new_query or the #GstQuery pointed to by @old_query may be %NULL.
2806  *
2807  * Returns: %TRUE if @new_query was different from @old_query
2808  */
2809 gboolean
gst_query_replace(GstQuery ** old_query,GstQuery * new_query)2810 gst_query_replace (GstQuery ** old_query, GstQuery * new_query)
2811 {
2812   return gst_mini_object_replace ((GstMiniObject **) old_query,
2813       (GstMiniObject *) new_query);
2814 }
2815 
2816 /**
2817  * gst_query_take:
2818  * @old_query: (inout) (transfer full) (nullable): pointer to a
2819  *     pointer to a #GstQuery to be stolen.
2820  * @new_query: (allow-none) (transfer full): pointer to a #GstQuery that will
2821  *     replace the query pointed to by @old_query.
2822  *
2823  * Modifies a pointer to a #GstQuery to point to a different #GstQuery. This
2824  * function is similar to gst_query_replace() except that it takes ownership of
2825  * @new_query.
2826  *
2827  * Either @new_query or the #GstQuery pointed to by @old_query may be %NULL.
2828  *
2829  * Returns: %TRUE if @new_query was different from @old_query
2830  *
2831  * Since: 1.16
2832  */
2833 gboolean
gst_query_take(GstQuery ** old_query,GstQuery * new_query)2834 gst_query_take (GstQuery ** old_query, GstQuery * new_query)
2835 {
2836   return gst_mini_object_take ((GstMiniObject **) old_query,
2837       (GstMiniObject *) new_query);
2838 }
2839