gst: Correctly annotate functions taking floating reference parameters and returning...
[platform/upstream/gstreamer.git] / 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 #define GST_STREAM_GET_PRIVATE(obj)  \
59    (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GST_TYPE_STREAM, GstStreamPrivate))
60
61 struct _GstStreamPrivate
62 {
63   GstStreamFlags flags;
64   GstStreamType type;
65   GstTagList *tags;
66   GstCaps *caps;
67 };
68
69 /* stream signals and properties */
70 enum
71 {
72   LAST_SIGNAL
73 };
74
75 enum
76 {
77   PROP_0,
78   PROP_STREAM_ID,
79   PROP_STREAM_FLAGS,
80   PROP_STREAM_TYPE,
81   PROP_TAGS,
82   PROP_CAPS,
83   PROP_LAST
84 };
85
86 static GParamSpec *gst_stream_pspecs[PROP_LAST] = { 0 };
87
88 #if 0
89 static guint gst_stream_signals[LAST_SIGNAL] = { 0 };
90 #endif
91
92 static void gst_stream_finalize (GObject * object);
93
94 static void gst_stream_set_property (GObject * object, guint prop_id,
95     const GValue * value, GParamSpec * pspec);
96 static void gst_stream_get_property (GObject * object, guint prop_id,
97     GValue * value, GParamSpec * pspec);
98
99 #define _do_init                                \
100 { \
101   GST_DEBUG_CATEGORY_INIT (streams_debug, "streams", GST_DEBUG_BOLD, \
102       "debugging info for the stream and stream collection objects"); \
103   \
104 }
105
106 #define gst_stream_parent_class parent_class
107 G_DEFINE_TYPE_WITH_CODE (GstStream, gst_stream, GST_TYPE_OBJECT, _do_init);
108
109 static void
110 gst_stream_class_init (GstStreamClass * klass)
111 {
112   GObjectClass *gobject_class;
113
114   gobject_class = (GObjectClass *) klass;
115
116   g_type_class_add_private (klass, sizeof (GstStreamPrivate));
117
118   gobject_class->set_property = gst_stream_set_property;
119   gobject_class->get_property = gst_stream_get_property;
120
121   /**
122    * GstStream:stream-id:
123    *
124    * The unique identifier of the #GstStream. Can only be set at construction
125    * time.
126    */
127   g_object_class_install_property (gobject_class, PROP_STREAM_ID,
128       g_param_spec_string ("stream-id", "Stream ID",
129           "The stream ID of the stream",
130           NULL,
131           G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
132
133   /**
134    * GstStream:flags:
135    *
136    * The #GstStreamFlags of the #GstStream. Can only be set at construction time.
137    **/
138   gst_stream_pspecs[PROP_STREAM_FLAGS] =
139       g_param_spec_flags ("stream-flags", "Stream Flags", "The stream flags",
140       GST_TYPE_STREAM_FLAGS, GST_STREAM_FLAG_NONE,
141       G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS);
142   g_object_class_install_property (gobject_class, PROP_STREAM_FLAGS,
143       gst_stream_pspecs[PROP_STREAM_FLAGS]);
144
145   /**
146    * GstStream:stream-type:
147    *
148    * The #GstStreamType of the #GstStream. Can only be set at construction time.
149    **/
150   gst_stream_pspecs[PROP_STREAM_TYPE] =
151       g_param_spec_flags ("stream-type", "Stream Type", "The type of stream",
152       GST_TYPE_STREAM_TYPE, GST_STREAM_TYPE_UNKNOWN,
153       G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS);
154   g_object_class_install_property (gobject_class, PROP_STREAM_TYPE,
155       gst_stream_pspecs[PROP_STREAM_TYPE]);
156
157   /**
158    * GstStream:caps:
159    *
160    * The #GstCaps of the #GstStream.
161    **/
162   gst_stream_pspecs[PROP_CAPS] =
163       g_param_spec_boxed ("caps", "Caps", "The caps of the stream",
164       GST_TYPE_CAPS, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
165   g_object_class_install_property (gobject_class, PROP_CAPS,
166       gst_stream_pspecs[PROP_CAPS]);
167
168   /**
169    * GstStream:tags:
170    *
171    * The #GstTagList of the #GstStream.
172    **/
173   gst_stream_pspecs[PROP_TAGS] =
174       g_param_spec_boxed ("tags", "Tags", "The tags of the stream",
175       GST_TYPE_TAG_LIST, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
176   g_object_class_install_property (gobject_class, PROP_TAGS,
177       gst_stream_pspecs[PROP_TAGS]);
178
179   gobject_class->finalize = gst_stream_finalize;
180 }
181
182 static void
183 gst_stream_init (GstStream * stream)
184 {
185   stream->priv = GST_STREAM_GET_PRIVATE (stream);
186   stream->priv->type = GST_STREAM_TYPE_UNKNOWN;
187 }
188
189 static void
190 gst_stream_finalize (GObject * object)
191 {
192   GstStream *stream = GST_STREAM_CAST (object);
193
194   gst_mini_object_replace ((GstMiniObject **) & stream->priv->tags,
195       (GstMiniObject *) NULL);
196   gst_caps_replace (&stream->priv->caps, NULL);
197   g_free ((gchar *) stream->stream_id);
198
199   G_OBJECT_CLASS (parent_class)->finalize (object);
200 }
201
202 /**
203  * gst_stream_new:
204  * @stream_id: (allow-none): the id for the new stream. If %NULL,
205  * a new one will be automatically generated
206  * @caps: (allow-none) (transfer none): the #GstCaps of the stream
207  * @type: the #GstStreamType of the stream
208  * @flags: the #GstStreamFlags of the stream
209  *
210  * Create a new #GstStream for the given @stream_id, @caps, @type
211  * and @flags
212  *
213  * Returns: (transfer floating): The new #GstStream
214  *
215  * Since: 1.10
216  */
217 GstStream *
218 gst_stream_new (const gchar * stream_id, GstCaps * caps, GstStreamType type,
219     GstStreamFlags flags)
220 {
221   return g_object_new (GST_TYPE_STREAM, "stream-id", stream_id, "caps", caps,
222       "stream-type", type, "stream-flags", flags, NULL);
223 }
224
225 static void
226 gst_stream_set_stream_id (GstStream * stream, const gchar * stream_id)
227 {
228   GST_OBJECT_LOCK (stream);
229   g_assert (stream->stream_id == NULL);
230   if (stream_id)
231     stream->stream_id = g_strdup (stream_id);
232   else {
233     /* Create a randoom stream_id if NULL */
234     GST_FIXME_OBJECT (stream, "Creating random stream-id, consider "
235         "implementing a deterministic way of creating a stream-id");
236     stream->stream_id =
237         g_strdup_printf ("%08x%08x%08x%08x", g_random_int (), g_random_int (),
238         g_random_int (), g_random_int ());
239   }
240
241   GST_OBJECT_UNLOCK (stream);
242 }
243
244 /**
245  * gst_stream_get_stream_id:
246  * @stream: a #GstStream
247  *
248  * Returns the stream ID of @stream.
249  *
250  * Returns: (transfer none) (nullable): the stream ID of @stream. Only valid
251  * during the lifetime of @stream.
252  *
253  * Since: 1.10
254  */
255 const gchar *
256 gst_stream_get_stream_id (GstStream * stream)
257 {
258   return stream->stream_id;
259 }
260
261 /**
262  * gst_stream_set_stream_flags:
263  * @stream: a #GstStream
264  * @flags: the flags to set on @stream
265  *
266  * Set the @flags for the @stream.
267  *
268  * Since: 1.10
269  */
270 void
271 gst_stream_set_stream_flags (GstStream * stream, GstStreamFlags flags)
272 {
273   GST_OBJECT_LOCK (stream);
274   stream->priv->flags = flags;
275   GST_OBJECT_UNLOCK (stream);
276
277   g_object_notify_by_pspec (G_OBJECT (stream),
278       gst_stream_pspecs[PROP_STREAM_FLAGS]);
279 }
280
281 /**
282  * gst_stream_get_stream_flags:
283  * @stream: a #GstStream
284  *
285  * Retrieve the current stream flags for @stream
286  *
287  * Returns: The #GstStreamFlags for @stream
288  *
289  * Since: 1.10
290  */
291 GstStreamFlags
292 gst_stream_get_stream_flags (GstStream * stream)
293 {
294   GstStreamFlags res;
295
296   GST_OBJECT_LOCK (stream);
297   res = stream->priv->flags;
298   GST_OBJECT_UNLOCK (stream);
299
300   return res;
301 }
302
303 /**
304  * gst_stream_set_stream_type:
305  * @stream: a #GstStream
306  * @stream_type: the type to set on @stream
307  *
308  * Set the stream type of @stream
309  *
310  * Since: 1.10
311  */
312 void
313 gst_stream_set_stream_type (GstStream * stream, GstStreamType stream_type)
314 {
315   GST_OBJECT_LOCK (stream);
316   stream->priv->type = stream_type;
317   GST_OBJECT_UNLOCK (stream);
318
319   g_object_notify_by_pspec (G_OBJECT (stream),
320       gst_stream_pspecs[PROP_STREAM_TYPE]);
321 }
322
323 /**
324  * gst_stream_get_stream_type:
325  * @stream: a #GstStream
326  *
327  * Retrieve the stream type for @stream
328  *
329  * Returns: The #GstStreamType for @stream
330  *
331  * Since: 1.10
332  */
333 GstStreamType
334 gst_stream_get_stream_type (GstStream * stream)
335 {
336   GstStreamType res;
337
338   GST_OBJECT_LOCK (stream);
339   res = stream->priv->type;
340   GST_OBJECT_UNLOCK (stream);
341
342   return res;
343 }
344
345 /**
346  * gst_stream_set_tags:
347  * @stream: a #GstStream
348  * @tags: (transfer none) (allow-none): a #GstTagList
349  *
350  * Set the tags for the #GstStream
351  *
352  * Since: 1.10
353  */
354 void
355 gst_stream_set_tags (GstStream * stream, GstTagList * tags)
356 {
357   gboolean notify = FALSE;
358
359   GST_OBJECT_LOCK (stream);
360   if (stream->priv->tags == NULL || tags == NULL
361       || !gst_tag_list_is_equal (stream->priv->tags, tags)) {
362     gst_mini_object_replace ((GstMiniObject **) & stream->priv->tags,
363         (GstMiniObject *) tags);
364     notify = TRUE;
365   }
366   GST_OBJECT_UNLOCK (stream);
367
368   if (notify)
369     g_object_notify_by_pspec (G_OBJECT (stream), gst_stream_pspecs[PROP_TAGS]);
370 }
371
372 /**
373  * gst_stream_get_tags:
374  * @stream: a #GstStream
375  *
376  * Retrieve the tags for @stream, if any
377  *
378  * Returns: (transfer full) (nullable): The #GstTagList for @stream
379  *
380  * Since: 1.10
381  */
382 GstTagList *
383 gst_stream_get_tags (GstStream * stream)
384 {
385   GstTagList *res = NULL;
386
387   GST_OBJECT_LOCK (stream);
388   if (stream->priv->tags)
389     res = gst_tag_list_ref (stream->priv->tags);
390   GST_OBJECT_UNLOCK (stream);
391
392   return res;
393 }
394
395 /**
396  * gst_stream_set_caps:
397  * @stream: a #GstStream
398  * @caps: (transfer none) (allow-none): a #GstCaps
399  *
400  * Set the caps for the #GstStream
401  *
402  * Since: 1.10
403  */
404 void
405 gst_stream_set_caps (GstStream * stream, GstCaps * caps)
406 {
407   gboolean notify = FALSE;
408
409   GST_OBJECT_LOCK (stream);
410   if (stream->priv->caps == NULL || (caps
411           && !gst_caps_is_equal (stream->priv->caps, caps))) {
412     gst_caps_replace (&stream->priv->caps, caps);
413     notify = TRUE;
414   }
415   GST_OBJECT_UNLOCK (stream);
416
417   if (notify)
418     g_object_notify_by_pspec (G_OBJECT (stream), gst_stream_pspecs[PROP_CAPS]);
419 }
420
421
422 /**
423  * gst_stream_get_caps:
424  * @stream: a #GstStream
425  *
426  * Retrieve the caps for @stream, if any
427  *
428  * Returns: (transfer full) (nullable): The #GstCaps for @stream
429  *
430  * Since: 1.10
431  */
432 GstCaps *
433 gst_stream_get_caps (GstStream * stream)
434 {
435   GstCaps *res = NULL;
436
437   GST_OBJECT_LOCK (stream);
438   if (stream->priv->caps)
439     res = gst_caps_ref (stream->priv->caps);
440   GST_OBJECT_UNLOCK (stream);
441
442   return res;
443 }
444
445 static void
446 gst_stream_set_property (GObject * object, guint prop_id,
447     const GValue * value, GParamSpec * pspec)
448 {
449   GstStream *stream;
450
451   stream = GST_STREAM_CAST (object);
452
453   switch (prop_id) {
454     case PROP_STREAM_ID:
455       gst_stream_set_stream_id (stream, g_value_get_string (value));
456       break;
457     case PROP_STREAM_FLAGS:
458       GST_OBJECT_LOCK (stream);
459       stream->priv->flags = g_value_get_flags (value);
460       GST_OBJECT_UNLOCK (stream);
461       break;
462     case PROP_STREAM_TYPE:
463       GST_OBJECT_LOCK (stream);
464       stream->priv->type = g_value_get_flags (value);
465       GST_OBJECT_UNLOCK (stream);
466       break;
467     case PROP_TAGS:
468       GST_OBJECT_LOCK (stream);
469       gst_mini_object_replace ((GstMiniObject **) & stream->priv->tags,
470           (GstMiniObject *) g_value_get_boxed (value));
471       GST_OBJECT_UNLOCK (stream);
472       break;
473     case PROP_CAPS:
474       GST_OBJECT_LOCK (stream);
475       gst_mini_object_replace ((GstMiniObject **) & stream->priv->caps,
476           (GstMiniObject *) g_value_get_boxed (value));
477       GST_OBJECT_UNLOCK (stream);
478       break;
479     default:
480       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
481       break;
482   }
483 }
484
485 static void
486 gst_stream_get_property (GObject * object, guint prop_id,
487     GValue * value, GParamSpec * pspec)
488 {
489   GstStream *stream;
490
491   stream = GST_STREAM_CAST (object);
492
493   switch (prop_id) {
494     case PROP_STREAM_ID:
495       g_value_set_string (value, gst_stream_get_stream_id (stream));
496       break;
497     case PROP_STREAM_FLAGS:
498       g_value_set_flags (value, gst_stream_get_stream_flags (stream));
499       break;
500     case PROP_STREAM_TYPE:
501       g_value_set_flags (value, gst_stream_get_stream_type (stream));
502       break;
503     case PROP_TAGS:
504       g_value_take_boxed (value, gst_stream_get_tags (stream));
505       break;
506     case PROP_CAPS:
507       g_value_take_boxed (value, gst_stream_get_caps (stream));
508       break;
509     default:
510       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
511       break;
512   }
513 }
514
515 /**
516  * gst_stream_type_get_name:
517  * @stype: a #GstStreamType
518  *
519  * Get a descriptive string for a given #GstStreamType
520  *
521  * Returns: A string describing the stream type
522  *
523  * Since: 1.10
524  */
525 const gchar *
526 gst_stream_type_get_name (GstStreamType stype)
527 {
528   /* FIXME : Make this more flexible */
529   switch (stype) {
530     case GST_STREAM_TYPE_UNKNOWN:
531       return "unknown";
532     case GST_STREAM_TYPE_AUDIO:
533       return "audio";
534     case GST_STREAM_TYPE_VIDEO:
535       return "video";
536     case GST_STREAM_TYPE_CONTAINER:
537       return "container";
538     case GST_STREAM_TYPE_TEXT:
539       return "text";
540     default:
541       return NULL;
542   }
543
544   return NULL;
545 }