tracerutils: allow casting parameters types
[platform/upstream/gstreamer.git] / subprojects / gstreamer / gst / gststreams.c
1 /* GStreamer
2  *
3  * Copyright (C) 2015 Centricular Ltd
4  *  @author: Edward Hervey <edward@centricular.com>
5  *  @author: Jan Schmidt <jan@centricular.com>
6  *
7  * gststreams.c: GstStream and GstStreamCollection object and methods
8  *
9  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Library General Public
11  * License as published by the Free Software Foundation; either
12  * version 2 of the License, or (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Library General Public License for more details.
18  *
19  * You should have received a copy of the GNU Library General Public
20  * License along with this library; if not, write to the
21  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
22  * Boston, MA 02110-1301, USA.
23  *
24  * MT safe.
25  */
26
27 /**
28  * SECTION:gststreams
29  * @title: GstStreams
30  * @short_description: Base class for stream objects
31  *
32  * A #GstStream is a high-level object defining a stream of data which is, or
33  * can be, present in a #GstPipeline.
34  *
35  * It is defined by a unique identifier, a "Stream ID". A #GstStream does not
36  * automatically imply the stream is present within a pipeline or element.
37  *
38  * Any element that can introduce new streams in a pipeline should create the
39  * appropriate #GstStream object, and can convey that object via the
40  * %GST_EVENT_STREAM_START event and/or the #GstStreamCollection.
41  *
42  * Elements that do not modify the nature of the stream can add extra information
43  * on it (such as enrich the #GstCaps, or #GstTagList). This is typically done
44  * by parsing elements.
45  *
46  * Since: 1.10
47  */
48
49 #include "gst_private.h"
50
51 #include "gstenumtypes.h"
52 #include "gstevent.h"
53 #include "gststreams.h"
54
55 GST_DEBUG_CATEGORY_STATIC (streams_debug);
56 #define GST_CAT_DEFAULT streams_debug
57
58 struct _GstStreamPrivate
59 {
60   GstStreamFlags flags;
61   GstStreamType type;
62   GstTagList *tags;
63   GstCaps *caps;
64 };
65
66 /* stream signals and properties */
67 enum
68 {
69   LAST_SIGNAL
70 };
71
72 enum
73 {
74   PROP_0,
75   PROP_STREAM_ID,
76   PROP_STREAM_FLAGS,
77   PROP_STREAM_TYPE,
78   PROP_TAGS,
79   PROP_CAPS,
80   PROP_LAST
81 };
82
83 static GParamSpec *gst_stream_pspecs[PROP_LAST] = { 0 };
84
85 #if 0
86 static guint gst_stream_signals[LAST_SIGNAL] = { 0 };
87 #endif
88
89 static void gst_stream_finalize (GObject * object);
90
91 static void gst_stream_set_property (GObject * object, guint prop_id,
92     const GValue * value, GParamSpec * pspec);
93 static void gst_stream_get_property (GObject * object, guint prop_id,
94     GValue * value, GParamSpec * pspec);
95
96 #define _do_init                                \
97 { \
98   GST_DEBUG_CATEGORY_INIT (streams_debug, "streams", GST_DEBUG_BOLD, \
99       "debugging info for the stream and stream collection objects"); \
100   \
101 }
102
103 #define gst_stream_parent_class parent_class
104 G_DEFINE_TYPE_WITH_CODE (GstStream, gst_stream, GST_TYPE_OBJECT,
105     G_ADD_PRIVATE (GstStream) _do_init);
106
107 static void
108 gst_stream_class_init (GstStreamClass * klass)
109 {
110   GObjectClass *gobject_class;
111
112   gobject_class = (GObjectClass *) klass;
113
114   gobject_class->set_property = gst_stream_set_property;
115   gobject_class->get_property = gst_stream_get_property;
116
117   /**
118    * GstStream:stream-id:
119    *
120    * The unique identifier of the #GstStream. Can only be set at construction
121    * time.
122    */
123   g_object_class_install_property (gobject_class, PROP_STREAM_ID,
124       g_param_spec_string ("stream-id", "Stream ID",
125           "The stream ID of the stream",
126           NULL,
127           G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
128
129   /**
130    * GstStream:flags:
131    *
132    * The #GstStreamFlags of the #GstStream. Can only be set at construction time.
133    **/
134   gst_stream_pspecs[PROP_STREAM_FLAGS] =
135       g_param_spec_flags ("stream-flags", "Stream Flags", "The stream flags",
136       GST_TYPE_STREAM_FLAGS, GST_STREAM_FLAG_NONE,
137       G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS);
138   g_object_class_install_property (gobject_class, PROP_STREAM_FLAGS,
139       gst_stream_pspecs[PROP_STREAM_FLAGS]);
140
141   /**
142    * GstStream:stream-type:
143    *
144    * The #GstStreamType of the #GstStream. Can only be set at construction time.
145    **/
146   gst_stream_pspecs[PROP_STREAM_TYPE] =
147       g_param_spec_flags ("stream-type", "Stream Type", "The type of stream",
148       GST_TYPE_STREAM_TYPE, GST_STREAM_TYPE_UNKNOWN,
149       G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS);
150   g_object_class_install_property (gobject_class, PROP_STREAM_TYPE,
151       gst_stream_pspecs[PROP_STREAM_TYPE]);
152
153   /**
154    * GstStream:caps:
155    *
156    * The #GstCaps of the #GstStream.
157    **/
158   gst_stream_pspecs[PROP_CAPS] =
159       g_param_spec_boxed ("caps", "Caps", "The caps of the stream",
160       GST_TYPE_CAPS, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
161   g_object_class_install_property (gobject_class, PROP_CAPS,
162       gst_stream_pspecs[PROP_CAPS]);
163
164   /**
165    * GstStream:tags:
166    *
167    * The #GstTagList of the #GstStream.
168    **/
169   gst_stream_pspecs[PROP_TAGS] =
170       g_param_spec_boxed ("tags", "Tags", "The tags of the stream",
171       GST_TYPE_TAG_LIST, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
172   g_object_class_install_property (gobject_class, PROP_TAGS,
173       gst_stream_pspecs[PROP_TAGS]);
174
175   gobject_class->finalize = gst_stream_finalize;
176 }
177
178 static void
179 gst_stream_init (GstStream * stream)
180 {
181   stream->priv = gst_stream_get_instance_private (stream);
182   stream->priv->type = GST_STREAM_TYPE_UNKNOWN;
183 }
184
185 static void
186 gst_stream_finalize (GObject * object)
187 {
188   GstStream *stream = GST_STREAM_CAST (object);
189
190   gst_mini_object_replace ((GstMiniObject **) & stream->priv->tags,
191       (GstMiniObject *) NULL);
192   gst_caps_replace (&stream->priv->caps, NULL);
193   g_free ((gchar *) stream->stream_id);
194   stream->stream_id = NULL;
195
196   G_OBJECT_CLASS (parent_class)->finalize (object);
197 }
198
199 /**
200  * gst_stream_new:
201  * @stream_id: (allow-none): the id for the new stream. If %NULL,
202  * a new one will be automatically generated
203  * @caps: (allow-none) (transfer none): the #GstCaps of the stream
204  * @type: the #GstStreamType of the stream
205  * @flags: the #GstStreamFlags of the stream
206  *
207  * Create a new #GstStream for the given @stream_id, @caps, @type
208  * and @flags
209  *
210  * Returns: (transfer full): The new #GstStream
211  *
212  * Since: 1.10
213  */
214 GstStream *
215 gst_stream_new (const gchar * stream_id, GstCaps * caps, GstStreamType type,
216     GstStreamFlags flags)
217 {
218   GstStream *stream;
219
220   stream = g_object_new (GST_TYPE_STREAM, "stream-id", stream_id, "caps", caps,
221       "stream-type", type, "stream-flags", flags, NULL);
222
223   /* Clear floating flag */
224   gst_object_ref_sink (stream);
225
226   return stream;
227 }
228
229 static void
230 gst_stream_set_stream_id (GstStream * stream, const gchar * stream_id)
231 {
232   g_return_if_fail (GST_IS_STREAM (stream));
233
234   GST_OBJECT_LOCK (stream);
235   g_assert (stream->stream_id == NULL);
236   if (stream_id) {
237     stream->stream_id = g_strdup (stream_id);
238   } else {
239     /* Create a random stream_id if NULL */
240     stream->stream_id =
241         g_strdup_printf ("%08x%08x%08x%08x", g_random_int (), g_random_int (),
242         g_random_int (), g_random_int ());
243   }
244
245   /* We hold the object lock, replace directly */
246   g_free (GST_OBJECT_NAME (stream));
247   GST_OBJECT_NAME (stream) = g_strdup (stream->stream_id);
248
249   GST_OBJECT_UNLOCK (stream);
250
251   if (!stream_id)
252     GST_FIXME_OBJECT (stream, "Created random stream-id, consider "
253         "implementing a deterministic way of creating a stream-id");
254 }
255
256 /**
257  * gst_stream_get_stream_id:
258  * @stream: a #GstStream
259  *
260  * Returns the stream ID of @stream.
261  *
262  * Returns: (transfer none) (nullable): the stream ID of @stream. Only valid
263  * during the lifetime of @stream.
264  *
265  * Since: 1.10
266  */
267 const gchar *
268 gst_stream_get_stream_id (GstStream * stream)
269 {
270   g_return_val_if_fail (GST_IS_STREAM (stream), NULL);
271
272   return stream->stream_id;
273 }
274
275 /**
276  * gst_stream_set_stream_flags:
277  * @stream: a #GstStream
278  * @flags: the flags to set on @stream
279  *
280  * Set the @flags for the @stream.
281  *
282  * Since: 1.10
283  */
284 void
285 gst_stream_set_stream_flags (GstStream * stream, GstStreamFlags flags)
286 {
287   g_return_if_fail (GST_IS_STREAM (stream));
288
289   GST_OBJECT_LOCK (stream);
290   stream->priv->flags = flags;
291   GST_OBJECT_UNLOCK (stream);
292
293   g_object_notify_by_pspec (G_OBJECT (stream),
294       gst_stream_pspecs[PROP_STREAM_FLAGS]);
295 }
296
297 /**
298  * gst_stream_get_stream_flags:
299  * @stream: a #GstStream
300  *
301  * Retrieve the current stream flags for @stream
302  *
303  * Returns: The #GstStreamFlags for @stream
304  *
305  * Since: 1.10
306  */
307 GstStreamFlags
308 gst_stream_get_stream_flags (GstStream * stream)
309 {
310   GstStreamFlags res;
311
312   g_return_val_if_fail (GST_IS_STREAM (stream), GST_STREAM_FLAG_NONE);
313
314   GST_OBJECT_LOCK (stream);
315   res = stream->priv->flags;
316   GST_OBJECT_UNLOCK (stream);
317
318   return res;
319 }
320
321 /**
322  * gst_stream_set_stream_type:
323  * @stream: a #GstStream
324  * @stream_type: the type to set on @stream
325  *
326  * Set the stream type of @stream
327  *
328  * Since: 1.10
329  */
330 void
331 gst_stream_set_stream_type (GstStream * stream, GstStreamType stream_type)
332 {
333   g_return_if_fail (GST_IS_STREAM (stream));
334
335   GST_OBJECT_LOCK (stream);
336   stream->priv->type = stream_type;
337   GST_OBJECT_UNLOCK (stream);
338
339   g_object_notify_by_pspec (G_OBJECT (stream),
340       gst_stream_pspecs[PROP_STREAM_TYPE]);
341 }
342
343 /**
344  * gst_stream_get_stream_type:
345  * @stream: a #GstStream
346  *
347  * Retrieve the stream type for @stream
348  *
349  * Returns: The #GstStreamType for @stream
350  *
351  * Since: 1.10
352  */
353 GstStreamType
354 gst_stream_get_stream_type (GstStream * stream)
355 {
356   GstStreamType res;
357
358   g_return_val_if_fail (GST_IS_STREAM (stream), GST_STREAM_TYPE_UNKNOWN);
359
360   GST_OBJECT_LOCK (stream);
361   res = stream->priv->type;
362   GST_OBJECT_UNLOCK (stream);
363
364   return res;
365 }
366
367 /**
368  * gst_stream_set_tags:
369  * @stream: a #GstStream
370  * @tags: (transfer none) (allow-none): a #GstTagList
371  *
372  * Set the tags for the #GstStream
373  *
374  * Since: 1.10
375  */
376 void
377 gst_stream_set_tags (GstStream * stream, GstTagList * tags)
378 {
379   gboolean notify = FALSE;
380
381   g_return_if_fail (GST_IS_STREAM (stream));
382
383   GST_OBJECT_LOCK (stream);
384   if (stream->priv->tags == NULL || tags == NULL
385       || !gst_tag_list_is_equal (stream->priv->tags, tags)) {
386     gst_mini_object_replace ((GstMiniObject **) & stream->priv->tags,
387         (GstMiniObject *) tags);
388     notify = TRUE;
389   }
390   GST_OBJECT_UNLOCK (stream);
391
392   if (notify)
393     g_object_notify_by_pspec (G_OBJECT (stream), gst_stream_pspecs[PROP_TAGS]);
394 }
395
396 /**
397  * gst_stream_get_tags:
398  * @stream: a #GstStream
399  *
400  * Retrieve the tags for @stream, if any
401  *
402  * Returns: (transfer full) (nullable): The #GstTagList for @stream
403  *
404  * Since: 1.10
405  */
406 GstTagList *
407 gst_stream_get_tags (GstStream * stream)
408 {
409   GstTagList *res = NULL;
410
411   g_return_val_if_fail (GST_IS_STREAM (stream), NULL);
412
413   GST_OBJECT_LOCK (stream);
414   if (stream->priv->tags)
415     res = gst_tag_list_ref (stream->priv->tags);
416   GST_OBJECT_UNLOCK (stream);
417
418   return res;
419 }
420
421 /**
422  * gst_stream_set_caps:
423  * @stream: a #GstStream
424  * @caps: (transfer none) (allow-none): a #GstCaps
425  *
426  * Set the caps for the #GstStream
427  *
428  * Since: 1.10
429  */
430 void
431 gst_stream_set_caps (GstStream * stream, GstCaps * caps)
432 {
433   gboolean notify = FALSE;
434
435   g_return_if_fail (GST_IS_STREAM (stream));
436
437   GST_OBJECT_LOCK (stream);
438   if (stream->priv->caps == NULL || (caps
439           && !gst_caps_is_equal (stream->priv->caps, caps))) {
440     gst_caps_replace (&stream->priv->caps, caps);
441     notify = TRUE;
442   }
443   GST_OBJECT_UNLOCK (stream);
444
445   if (notify)
446     g_object_notify_by_pspec (G_OBJECT (stream), gst_stream_pspecs[PROP_CAPS]);
447 }
448
449
450 /**
451  * gst_stream_get_caps:
452  * @stream: a #GstStream
453  *
454  * Retrieve the caps for @stream, if any
455  *
456  * Returns: (transfer full) (nullable): The #GstCaps for @stream
457  *
458  * Since: 1.10
459  */
460 GstCaps *
461 gst_stream_get_caps (GstStream * stream)
462 {
463   GstCaps *res = NULL;
464
465   g_return_val_if_fail (GST_IS_STREAM (stream), NULL);
466
467   GST_OBJECT_LOCK (stream);
468   if (stream->priv->caps)
469     res = gst_caps_ref (stream->priv->caps);
470   GST_OBJECT_UNLOCK (stream);
471
472   return res;
473 }
474
475 static void
476 gst_stream_set_property (GObject * object, guint prop_id,
477     const GValue * value, GParamSpec * pspec)
478 {
479   GstStream *stream;
480
481   stream = GST_STREAM_CAST (object);
482
483   switch (prop_id) {
484     case PROP_STREAM_ID:
485       gst_stream_set_stream_id (stream, g_value_get_string (value));
486       break;
487     case PROP_STREAM_FLAGS:
488       GST_OBJECT_LOCK (stream);
489       stream->priv->flags = g_value_get_flags (value);
490       GST_OBJECT_UNLOCK (stream);
491       break;
492     case PROP_STREAM_TYPE:
493       GST_OBJECT_LOCK (stream);
494       stream->priv->type = g_value_get_flags (value);
495       GST_OBJECT_UNLOCK (stream);
496       break;
497     case PROP_TAGS:
498       GST_OBJECT_LOCK (stream);
499       gst_mini_object_replace ((GstMiniObject **) & stream->priv->tags,
500           (GstMiniObject *) g_value_get_boxed (value));
501       GST_OBJECT_UNLOCK (stream);
502       break;
503     case PROP_CAPS:
504       GST_OBJECT_LOCK (stream);
505       gst_mini_object_replace ((GstMiniObject **) & stream->priv->caps,
506           (GstMiniObject *) g_value_get_boxed (value));
507       GST_OBJECT_UNLOCK (stream);
508       break;
509     default:
510       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
511       break;
512   }
513 }
514
515 static void
516 gst_stream_get_property (GObject * object, guint prop_id,
517     GValue * value, GParamSpec * pspec)
518 {
519   GstStream *stream;
520
521   stream = GST_STREAM_CAST (object);
522
523   switch (prop_id) {
524     case PROP_STREAM_ID:
525       g_value_set_string (value, gst_stream_get_stream_id (stream));
526       break;
527     case PROP_STREAM_FLAGS:
528       g_value_set_flags (value, gst_stream_get_stream_flags (stream));
529       break;
530     case PROP_STREAM_TYPE:
531       g_value_set_flags (value, gst_stream_get_stream_type (stream));
532       break;
533     case PROP_TAGS:
534       g_value_take_boxed (value, gst_stream_get_tags (stream));
535       break;
536     case PROP_CAPS:
537       g_value_take_boxed (value, gst_stream_get_caps (stream));
538       break;
539     default:
540       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
541       break;
542   }
543 }
544
545 /**
546  * gst_stream_type_get_name:
547  * @stype: a #GstStreamType
548  *
549  * Get a descriptive string for a given #GstStreamType
550  *
551  * Returns: A string describing the stream type
552  *
553  * Since: 1.10
554  */
555 const gchar *
556 gst_stream_type_get_name (GstStreamType stype)
557 {
558   switch (stype) {
559     case GST_STREAM_TYPE_UNKNOWN:
560       return "unknown";
561     case GST_STREAM_TYPE_AUDIO:
562       return "audio";
563     case GST_STREAM_TYPE_VIDEO:
564       return "video";
565     case GST_STREAM_TYPE_CONTAINER:
566       return "container";
567     case GST_STREAM_TYPE_TEXT:
568       return "text";
569     default:{
570       gchar str[32] = { 0, };
571
572 #define _GST_STREAM_TYPE_ALL          \
573         (GST_STREAM_TYPE_AUDIO        \
574          | GST_STREAM_TYPE_VIDEO      \
575          | GST_STREAM_TYPE_CONTAINER  \
576          | GST_STREAM_TYPE_TEXT)
577
578       if ((stype & (~_GST_STREAM_TYPE_ALL)) != 0)
579         break;
580
581       if ((stype & GST_STREAM_TYPE_CONTAINER) != 0)
582         g_strlcat (str, "+container", sizeof (str));
583       if ((stype & GST_STREAM_TYPE_VIDEO) != 0)
584         g_strlcat (str, "+video", sizeof (str));
585       if ((stype & GST_STREAM_TYPE_AUDIO) != 0)
586         g_strlcat (str, "+audio", sizeof (str));
587       if ((stype & GST_STREAM_TYPE_TEXT) != 0)
588         g_strlcat (str, "+text", sizeof (str));
589
590       g_assert (str[0] != '\0');
591
592       return g_intern_string (str + 1);
593     }
594   }
595
596   g_return_val_if_reached ("invalid");
597 }