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.
29 * @short_description: Base class for stream objects
31 * A #GstStream is a high-level object defining a stream of data which is, or
32 * can be, present in a #GstPipeline.
34 * It is defined by a unique identifier, a "Stream ID". A #GstStream does not
35 * automatically imply the stream is present within a pipeline or element.
37 * Any element that can introduce new streams in a pipeline should create the
38 * appropriate #GstStream object, and can convey that object via the
39 * %GST_EVENT_STREAM_START event and/or the #GstStreamCollection.
41 * Elements that do not modify the nature of the stream can add extra information
42 * on it (such as enrich the #GstCaps, or #GstTagList). This is typically done
43 * by parsing elements.
48 #include "gst_private.h"
50 #include "gstenumtypes.h"
52 #include "gststreams.h"
54 GST_DEBUG_CATEGORY_STATIC (streams_debug);
55 #define GST_CAT_DEFAULT streams_debug
57 #define GST_STREAM_GET_PRIVATE(obj) \
58 (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GST_TYPE_STREAM, GstStreamPrivate))
60 struct _GstStreamPrivate
68 /* stream signals and properties */
85 static GParamSpec *gst_stream_pspecs[PROP_LAST] = { 0 };
88 static guint gst_stream_signals[LAST_SIGNAL] = { 0 };
91 static void gst_stream_finalize (GObject * object);
93 static void gst_stream_set_property (GObject * object, guint prop_id,
94 const GValue * value, GParamSpec * pspec);
95 static void gst_stream_get_property (GObject * object, guint prop_id,
96 GValue * value, GParamSpec * pspec);
100 GST_DEBUG_CATEGORY_INIT (streams_debug, "streams", GST_DEBUG_BOLD, \
101 "debugging info for the stream and stream collection objects"); \
105 #define gst_stream_parent_class parent_class
106 G_DEFINE_TYPE_WITH_CODE (GstStream, gst_stream, GST_TYPE_OBJECT, _do_init);
109 gst_stream_class_init (GstStreamClass * klass)
111 GObjectClass *gobject_class;
113 gobject_class = (GObjectClass *) klass;
115 g_type_class_add_private (klass, sizeof (GstStreamPrivate));
117 gobject_class->set_property = gst_stream_set_property;
118 gobject_class->get_property = gst_stream_get_property;
121 * GstStream:stream-id:
123 * The unique identifier of the #GstStream. Can only be set at construction
126 g_object_class_install_property (gobject_class, PROP_STREAM_ID,
127 g_param_spec_string ("stream-id", "Stream ID",
128 "The stream ID of the stream",
130 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
135 * The #GstStreamFlags of the #GstStream. Can only be set at construction time.
137 gst_stream_pspecs[PROP_STREAM_FLAGS] =
138 g_param_spec_flags ("stream-flags", "Stream Flags", "The stream flags",
139 GST_TYPE_STREAM_FLAGS, GST_STREAM_FLAG_NONE,
140 G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS);
141 g_object_class_install_property (gobject_class, PROP_STREAM_FLAGS,
142 gst_stream_pspecs[PROP_STREAM_FLAGS]);
145 * GstStream:stream-type:
147 * The #GstStreamType of the #GstStream. Can only be set at construction time.
149 gst_stream_pspecs[PROP_STREAM_TYPE] =
150 g_param_spec_flags ("stream-type", "Stream Type", "The type of stream",
151 GST_TYPE_STREAM_TYPE, GST_STREAM_TYPE_UNKNOWN,
152 G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS);
153 g_object_class_install_property (gobject_class, PROP_STREAM_TYPE,
154 gst_stream_pspecs[PROP_STREAM_TYPE]);
159 * The #GstCaps of the #GstStream.
161 gst_stream_pspecs[PROP_CAPS] =
162 g_param_spec_boxed ("caps", "Caps", "The caps of the stream",
163 GST_TYPE_CAPS, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
164 g_object_class_install_property (gobject_class, PROP_CAPS,
165 gst_stream_pspecs[PROP_CAPS]);
170 * The #GstTagList of the #GstStream.
172 gst_stream_pspecs[PROP_TAGS] =
173 g_param_spec_boxed ("tags", "Tags", "The tags of the stream",
174 GST_TYPE_TAG_LIST, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
175 g_object_class_install_property (gobject_class, PROP_TAGS,
176 gst_stream_pspecs[PROP_TAGS]);
178 gobject_class->finalize = gst_stream_finalize;
182 gst_stream_init (GstStream * stream)
184 stream->priv = GST_STREAM_GET_PRIVATE (stream);
185 stream->priv->type = GST_STREAM_TYPE_UNKNOWN;
189 gst_stream_finalize (GObject * object)
191 GstStream *stream = GST_STREAM_CAST (object);
193 gst_mini_object_replace ((GstMiniObject **) & stream->priv->tags,
194 (GstMiniObject *) NULL);
195 gst_caps_replace (&stream->priv->caps, NULL);
196 g_free ((gchar *) stream->stream_id);
198 G_OBJECT_CLASS (parent_class)->finalize (object);
203 * @stream_id: (allow-none): the id for the new stream. If %NULL,
204 * a new one will be automatically generated
205 * @caps: (allow-none) (transfer none): the #GstCaps of the stream
206 * @type: the #GstStreamType of the stream
207 * @flags: the #GstStreamFlags of the stream
209 * Create a new #GstStream for the given @stream_id, @caps, @type
212 * Returns: The new #GstStream
217 gst_stream_new (const gchar * stream_id, GstCaps * caps, GstStreamType type,
218 GstStreamFlags flags)
220 return g_object_new (GST_TYPE_STREAM, "stream-id", stream_id, "caps", caps,
221 "stream-type", type, "stream-flags", flags, NULL);
225 gst_stream_set_stream_id (GstStream * stream, const gchar * stream_id)
227 GST_OBJECT_LOCK (stream);
228 g_assert (stream->stream_id == NULL);
230 stream->stream_id = g_strdup (stream_id);
232 /* Create a randoom stream_id if NULL */
233 GST_FIXME_OBJECT (stream, "Creating random stream-id, consider "
234 "implementing a deterministic way of creating a stream-id");
236 g_strdup_printf ("%08x%08x%08x%08x", g_random_int (), g_random_int (),
237 g_random_int (), g_random_int ());
240 GST_OBJECT_UNLOCK (stream);
244 * gst_stream_get_stream_id:
245 * @stream: a #GstStream
247 * Returns the stream ID of @stream.
249 * Returns: (transfer none) (nullable): the stream ID of @stream. Only valid
250 * during the lifetime of @stream.
255 gst_stream_get_stream_id (GstStream * stream)
257 return stream->stream_id;
261 * gst_stream_set_stream_flags:
262 * @stream: a #GstStream
263 * @flags: the flags to set on @stream
265 * Set the @flags for the @stream.
270 gst_stream_set_stream_flags (GstStream * stream, GstStreamFlags flags)
272 GST_OBJECT_LOCK (stream);
273 stream->priv->flags = flags;
274 GST_OBJECT_UNLOCK (stream);
276 g_object_notify_by_pspec (G_OBJECT (stream),
277 gst_stream_pspecs[PROP_STREAM_FLAGS]);
281 * gst_stream_get_stream_flags:
282 * @stream: a #GstStream
284 * Retrieve the current stream flags for @stream
286 * Returns: The #GstStreamFlags for @stream
291 gst_stream_get_stream_flags (GstStream * stream)
295 GST_OBJECT_LOCK (stream);
296 res = stream->priv->flags;
297 GST_OBJECT_UNLOCK (stream);
303 * gst_stream_set_stream_type:
304 * @stream: a #GstStream
305 * @stream_type: the type to set on @stream
307 * Set the stream type of @stream
312 gst_stream_set_stream_type (GstStream * stream, GstStreamType stream_type)
314 GST_OBJECT_LOCK (stream);
315 stream->priv->type = stream_type;
316 GST_OBJECT_UNLOCK (stream);
318 g_object_notify_by_pspec (G_OBJECT (stream),
319 gst_stream_pspecs[PROP_STREAM_TYPE]);
323 * gst_stream_get_stream_type:
324 * @stream: a #GstStream
326 * Retrieve the stream type for @stream
328 * Returns: The #GstStreamType for @stream
333 gst_stream_get_stream_type (GstStream * stream)
337 GST_OBJECT_LOCK (stream);
338 res = stream->priv->type;
339 GST_OBJECT_UNLOCK (stream);
345 * gst_stream_set_tags:
346 * @stream: a #GstStream
347 * @tags: (transfer none) (allow-none): a #GstTagList
349 * Set the tags for the #GstStream
354 gst_stream_set_tags (GstStream * stream, GstTagList * tags)
356 gboolean notify = FALSE;
358 GST_OBJECT_LOCK (stream);
359 if (stream->priv->tags == NULL || tags == NULL
360 || !gst_tag_list_is_equal (stream->priv->tags, tags)) {
361 gst_mini_object_replace ((GstMiniObject **) & stream->priv->tags,
362 (GstMiniObject *) tags);
365 GST_OBJECT_UNLOCK (stream);
368 g_object_notify_by_pspec (G_OBJECT (stream), gst_stream_pspecs[PROP_TAGS]);
372 * gst_stream_get_tags:
373 * @stream: a #GstStream
375 * Retrieve the tags for @stream, if any
377 * Returns: (transfer full) (nullable): The #GstTagList for @stream
382 gst_stream_get_tags (GstStream * stream)
384 GstTagList *res = NULL;
386 GST_OBJECT_LOCK (stream);
387 if (stream->priv->tags)
388 res = gst_tag_list_ref (stream->priv->tags);
389 GST_OBJECT_UNLOCK (stream);
395 * gst_stream_set_caps:
396 * @stream: a #GstStream
397 * @caps: (transfer none) (allow-none): a #GstCaps
399 * Set the caps for the #GstStream
404 gst_stream_set_caps (GstStream * stream, GstCaps * caps)
406 gboolean notify = FALSE;
408 GST_OBJECT_LOCK (stream);
409 if (stream->priv->caps == NULL || (caps
410 && !gst_caps_is_equal (stream->priv->caps, caps))) {
411 gst_caps_replace (&stream->priv->caps, caps);
414 GST_OBJECT_UNLOCK (stream);
417 g_object_notify_by_pspec (G_OBJECT (stream), gst_stream_pspecs[PROP_CAPS]);
422 * gst_stream_get_caps:
423 * @stream: a #GstStream
425 * Retrieve the caps for @stream, if any
427 * Returns: (transfer full) (nullable): The #GstCaps for @stream
432 gst_stream_get_caps (GstStream * stream)
436 GST_OBJECT_LOCK (stream);
437 if (stream->priv->caps)
438 res = gst_caps_ref (stream->priv->caps);
439 GST_OBJECT_UNLOCK (stream);
445 gst_stream_set_property (GObject * object, guint prop_id,
446 const GValue * value, GParamSpec * pspec)
450 stream = GST_STREAM_CAST (object);
454 gst_stream_set_stream_id (stream, g_value_get_string (value));
456 case PROP_STREAM_FLAGS:
457 GST_OBJECT_LOCK (stream);
458 stream->priv->flags = g_value_get_flags (value);
459 GST_OBJECT_UNLOCK (stream);
461 case PROP_STREAM_TYPE:
462 GST_OBJECT_LOCK (stream);
463 stream->priv->type = g_value_get_flags (value);
464 GST_OBJECT_UNLOCK (stream);
467 GST_OBJECT_LOCK (stream);
468 gst_mini_object_replace ((GstMiniObject **) & stream->priv->tags,
469 (GstMiniObject *) g_value_get_boxed (value));
470 GST_OBJECT_UNLOCK (stream);
473 GST_OBJECT_LOCK (stream);
474 gst_mini_object_replace ((GstMiniObject **) & stream->priv->caps,
475 (GstMiniObject *) g_value_get_boxed (value));
476 GST_OBJECT_UNLOCK (stream);
479 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
485 gst_stream_get_property (GObject * object, guint prop_id,
486 GValue * value, GParamSpec * pspec)
490 stream = GST_STREAM_CAST (object);
494 g_value_set_string (value, gst_stream_get_stream_id (stream));
496 case PROP_STREAM_FLAGS:
497 g_value_set_flags (value, gst_stream_get_stream_flags (stream));
499 case PROP_STREAM_TYPE:
500 g_value_set_flags (value, gst_stream_get_stream_type (stream));
503 g_value_take_boxed (value, gst_stream_get_tags (stream));
506 g_value_take_boxed (value, gst_stream_get_caps (stream));
509 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
515 * gst_stream_type_get_name:
516 * @stype: a #GstStreamType
518 * Get a descriptive string for a given #GstStreamType
520 * Returns: A string describing the stream type
525 gst_stream_type_get_name (GstStreamType stype)
527 /* FIXME : Make this more flexible */
529 case GST_STREAM_TYPE_UNKNOWN:
531 case GST_STREAM_TYPE_AUDIO:
533 case GST_STREAM_TYPE_VIDEO:
535 case GST_STREAM_TYPE_CONTAINER:
537 case GST_STREAM_TYPE_TEXT: