3 * Copyright (C) 2015 Centricular Ltd
4 * @author: Edward Hervey <edward@centricular.com>
5 * @author: Jan Schmidt <jan@centricular.com>
7 * gststreams.c: GstStream and GstStreamCollection object and methods
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.
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.
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.
30 * @short_description: Base class for stream objects
32 * A #GstStream is a high-level object defining a stream of data which is, or
33 * can be, present in a #GstPipeline.
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.
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.
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.
49 #include "gst_private.h"
51 #include "gstenumtypes.h"
53 #include "gststreams.h"
55 GST_DEBUG_CATEGORY_STATIC (streams_debug);
56 #define GST_CAT_DEFAULT streams_debug
58 struct _GstStreamPrivate
66 /* stream signals and properties */
83 static GParamSpec *gst_stream_pspecs[PROP_LAST] = { 0 };
86 static guint gst_stream_signals[LAST_SIGNAL] = { 0 };
89 static void gst_stream_finalize (GObject * object);
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);
98 GST_DEBUG_CATEGORY_INIT (streams_debug, "streams", GST_DEBUG_BOLD, \
99 "debugging info for the stream and stream collection objects"); \
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);
108 gst_stream_class_init (GstStreamClass * klass)
110 GObjectClass *gobject_class;
112 gobject_class = (GObjectClass *) klass;
114 gobject_class->set_property = gst_stream_set_property;
115 gobject_class->get_property = gst_stream_get_property;
118 * GstStream:stream-id:
120 * The unique identifier of the #GstStream. Can only be set at construction
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",
127 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
132 * The #GstStreamFlags of the #GstStream. Can only be set at construction time.
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]);
142 * GstStream:stream-type:
144 * The #GstStreamType of the #GstStream. Can only be set at construction time.
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]);
156 * The #GstCaps of the #GstStream.
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]);
167 * The #GstTagList of the #GstStream.
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]);
175 gobject_class->finalize = gst_stream_finalize;
179 gst_stream_init (GstStream * stream)
181 stream->priv = gst_stream_get_instance_private (stream);
182 stream->priv->type = GST_STREAM_TYPE_UNKNOWN;
186 gst_stream_finalize (GObject * object)
188 GstStream *stream = GST_STREAM_CAST (object);
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;
196 G_OBJECT_CLASS (parent_class)->finalize (object);
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
207 * Create a new #GstStream for the given @stream_id, @caps, @type
210 * Returns: (transfer full): The new #GstStream
215 gst_stream_new (const gchar * stream_id, GstCaps * caps, GstStreamType type,
216 GstStreamFlags flags)
220 stream = g_object_new (GST_TYPE_STREAM, "stream-id", stream_id, "caps", caps,
221 "stream-type", type, "stream-flags", flags, NULL);
223 /* Clear floating flag */
224 gst_object_ref_sink (stream);
230 gst_stream_set_stream_id (GstStream * stream, const gchar * stream_id)
232 g_return_if_fail (GST_IS_STREAM (stream));
234 GST_OBJECT_LOCK (stream);
235 g_assert (stream->stream_id == NULL);
237 stream->stream_id = g_strdup (stream_id);
239 /* Create a random stream_id if NULL */
241 g_strdup_printf ("%08x%08x%08x%08x", g_random_int (), g_random_int (),
242 g_random_int (), g_random_int ());
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);
249 GST_OBJECT_UNLOCK (stream);
252 GST_FIXME_OBJECT (stream, "Created random stream-id, consider "
253 "implementing a deterministic way of creating a stream-id");
257 * gst_stream_get_stream_id:
258 * @stream: a #GstStream
260 * Returns the stream ID of @stream.
262 * Returns: (transfer none) (nullable): the stream ID of @stream. Only valid
263 * during the lifetime of @stream.
268 gst_stream_get_stream_id (GstStream * stream)
270 g_return_val_if_fail (GST_IS_STREAM (stream), NULL);
272 return stream->stream_id;
276 * gst_stream_set_stream_flags:
277 * @stream: a #GstStream
278 * @flags: the flags to set on @stream
280 * Set the @flags for the @stream.
285 gst_stream_set_stream_flags (GstStream * stream, GstStreamFlags flags)
287 g_return_if_fail (GST_IS_STREAM (stream));
289 GST_OBJECT_LOCK (stream);
290 stream->priv->flags = flags;
291 GST_OBJECT_UNLOCK (stream);
293 g_object_notify_by_pspec (G_OBJECT (stream),
294 gst_stream_pspecs[PROP_STREAM_FLAGS]);
298 * gst_stream_get_stream_flags:
299 * @stream: a #GstStream
301 * Retrieve the current stream flags for @stream
303 * Returns: The #GstStreamFlags for @stream
308 gst_stream_get_stream_flags (GstStream * stream)
312 g_return_val_if_fail (GST_IS_STREAM (stream), GST_STREAM_FLAG_NONE);
314 GST_OBJECT_LOCK (stream);
315 res = stream->priv->flags;
316 GST_OBJECT_UNLOCK (stream);
322 * gst_stream_set_stream_type:
323 * @stream: a #GstStream
324 * @stream_type: the type to set on @stream
326 * Set the stream type of @stream
331 gst_stream_set_stream_type (GstStream * stream, GstStreamType stream_type)
333 g_return_if_fail (GST_IS_STREAM (stream));
335 GST_OBJECT_LOCK (stream);
336 stream->priv->type = stream_type;
337 GST_OBJECT_UNLOCK (stream);
339 g_object_notify_by_pspec (G_OBJECT (stream),
340 gst_stream_pspecs[PROP_STREAM_TYPE]);
344 * gst_stream_get_stream_type:
345 * @stream: a #GstStream
347 * Retrieve the stream type for @stream
349 * Returns: The #GstStreamType for @stream
354 gst_stream_get_stream_type (GstStream * stream)
358 g_return_val_if_fail (GST_IS_STREAM (stream), GST_STREAM_TYPE_UNKNOWN);
360 GST_OBJECT_LOCK (stream);
361 res = stream->priv->type;
362 GST_OBJECT_UNLOCK (stream);
368 * gst_stream_set_tags:
369 * @stream: a #GstStream
370 * @tags: (transfer none) (allow-none): a #GstTagList
372 * Set the tags for the #GstStream
377 gst_stream_set_tags (GstStream * stream, GstTagList * tags)
379 gboolean notify = FALSE;
381 g_return_if_fail (GST_IS_STREAM (stream));
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);
390 GST_OBJECT_UNLOCK (stream);
393 g_object_notify_by_pspec (G_OBJECT (stream), gst_stream_pspecs[PROP_TAGS]);
397 * gst_stream_get_tags:
398 * @stream: a #GstStream
400 * Retrieve the tags for @stream, if any
402 * Returns: (transfer full) (nullable): The #GstTagList for @stream
407 gst_stream_get_tags (GstStream * stream)
409 GstTagList *res = NULL;
411 g_return_val_if_fail (GST_IS_STREAM (stream), NULL);
413 GST_OBJECT_LOCK (stream);
414 if (stream->priv->tags)
415 res = gst_tag_list_ref (stream->priv->tags);
416 GST_OBJECT_UNLOCK (stream);
422 * gst_stream_set_caps:
423 * @stream: a #GstStream
424 * @caps: (transfer none) (allow-none): a #GstCaps
426 * Set the caps for the #GstStream
431 gst_stream_set_caps (GstStream * stream, GstCaps * caps)
433 gboolean notify = FALSE;
435 g_return_if_fail (GST_IS_STREAM (stream));
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);
443 GST_OBJECT_UNLOCK (stream);
446 g_object_notify_by_pspec (G_OBJECT (stream), gst_stream_pspecs[PROP_CAPS]);
451 * gst_stream_get_caps:
452 * @stream: a #GstStream
454 * Retrieve the caps for @stream, if any
456 * Returns: (transfer full) (nullable): The #GstCaps for @stream
461 gst_stream_get_caps (GstStream * stream)
465 g_return_val_if_fail (GST_IS_STREAM (stream), NULL);
467 GST_OBJECT_LOCK (stream);
468 if (stream->priv->caps)
469 res = gst_caps_ref (stream->priv->caps);
470 GST_OBJECT_UNLOCK (stream);
476 gst_stream_set_property (GObject * object, guint prop_id,
477 const GValue * value, GParamSpec * pspec)
481 stream = GST_STREAM_CAST (object);
485 gst_stream_set_stream_id (stream, g_value_get_string (value));
487 case PROP_STREAM_FLAGS:
488 GST_OBJECT_LOCK (stream);
489 stream->priv->flags = g_value_get_flags (value);
490 GST_OBJECT_UNLOCK (stream);
492 case PROP_STREAM_TYPE:
493 GST_OBJECT_LOCK (stream);
494 stream->priv->type = g_value_get_flags (value);
495 GST_OBJECT_UNLOCK (stream);
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);
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);
510 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
516 gst_stream_get_property (GObject * object, guint prop_id,
517 GValue * value, GParamSpec * pspec)
521 stream = GST_STREAM_CAST (object);
525 g_value_set_string (value, gst_stream_get_stream_id (stream));
527 case PROP_STREAM_FLAGS:
528 g_value_set_flags (value, gst_stream_get_stream_flags (stream));
530 case PROP_STREAM_TYPE:
531 g_value_set_flags (value, gst_stream_get_stream_type (stream));
534 g_value_take_boxed (value, gst_stream_get_tags (stream));
537 g_value_take_boxed (value, gst_stream_get_caps (stream));
540 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
546 * gst_stream_type_get_name:
547 * @stype: a #GstStreamType
549 * Get a descriptive string for a given #GstStreamType
551 * Returns: A string describing the stream type
556 gst_stream_type_get_name (GstStreamType stype)
559 case GST_STREAM_TYPE_UNKNOWN:
561 case GST_STREAM_TYPE_AUDIO:
563 case GST_STREAM_TYPE_VIDEO:
565 case GST_STREAM_TYPE_CONTAINER:
567 case GST_STREAM_TYPE_TEXT:
570 gchar str[32] = { 0, };
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)
578 if ((stype & (~_GST_STREAM_TYPE_ALL)) != 0)
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));
590 g_assert (str[0] != '\0');
592 return g_intern_string (str + 1);
596 g_return_val_if_reached ("invalid");