mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-01-14 03:15:47 +00:00
event: Add new stream-id field to the stream-start event
This is supposed to allow uniquely identifying a single stream.
This commit is contained in:
parent
ea761a24b4
commit
41954ff8cd
7 changed files with 222 additions and 5 deletions
|
@ -974,6 +974,7 @@ gst_event_new_gap
|
|||
gst_event_parse_gap
|
||||
|
||||
gst_event_new_stream_start
|
||||
gst_event_parse_stream_start
|
||||
|
||||
gst_event_new_segment
|
||||
gst_event_parse_segment
|
||||
|
@ -1786,6 +1787,8 @@ gst_pad_iterate_internal_links_default
|
|||
gst_pad_set_element_private
|
||||
gst_pad_get_element_private
|
||||
|
||||
gst_pad_create_stream_id
|
||||
|
||||
GstPadForwardFunction
|
||||
gst_pad_forward
|
||||
<SUBSECTION Core>
|
||||
|
|
|
@ -1593,6 +1593,7 @@ gst_event_parse_sink_message (GstEvent * event, GstMessage ** msg)
|
|||
|
||||
/**
|
||||
* gst_event_new_stream_start:
|
||||
* @stream_id: Identifier for this stream
|
||||
*
|
||||
* Create a new STREAM_START event. The stream start event can only
|
||||
* travel downstream synchronized with the buffer flow. It is expected
|
||||
|
@ -1605,12 +1606,48 @@ gst_event_parse_sink_message (GstEvent * event, GstMessage ** msg)
|
|||
* combining multiple streams must ensure that this event is only forwarded
|
||||
* downstream once and not for every single input stream.
|
||||
*
|
||||
* The @stream_id should be a unique string that consists of the upstream
|
||||
* stream-id, / as separator and a unique stream-id for this specific
|
||||
* stream. A new stream-id should only be created for a stream if the upstream
|
||||
* stream is split into (potentially) multiple new streams, e.g. in a demuxer,
|
||||
* but not for every single element in the pipeline.
|
||||
* gst_util_create_stream_id() can be used to create a stream-id.
|
||||
*
|
||||
* Returns: (transfer full): the new STREAM_START event.
|
||||
*/
|
||||
GstEvent *
|
||||
gst_event_new_stream_start (void)
|
||||
gst_event_new_stream_start (const gchar * stream_id)
|
||||
{
|
||||
return gst_event_new_custom (GST_EVENT_STREAM_START, NULL);
|
||||
GstStructure *s;
|
||||
|
||||
g_return_val_if_fail (stream_id != NULL, NULL);
|
||||
|
||||
s = gst_structure_new_id (GST_QUARK (EVENT_STREAM_START),
|
||||
GST_QUARK (STREAM_ID), G_TYPE_STRING, stream_id, NULL);
|
||||
|
||||
return gst_event_new_custom (GST_EVENT_STREAM_START, s);
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_event_parse_stream_start:
|
||||
* @event: a stream-start event.
|
||||
* @stream_id: (out): pointer to store the stream-id
|
||||
*
|
||||
* Parse a stream-id @event and store the result in the given @stream_id location.
|
||||
*/
|
||||
void
|
||||
gst_event_parse_stream_start (GstEvent * event, const gchar ** stream_id)
|
||||
{
|
||||
const GstStructure *structure;
|
||||
|
||||
g_return_if_fail (event != NULL);
|
||||
g_return_if_fail (GST_EVENT_TYPE (event) == GST_EVENT_STREAM_START);
|
||||
|
||||
structure = gst_event_get_structure (event);
|
||||
|
||||
if (stream_id)
|
||||
gst_structure_id_get (structure,
|
||||
GST_QUARK (STREAM_ID), G_TYPE_STRING, stream_id, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -472,7 +472,8 @@ guint32 gst_event_get_seqnum (GstEvent *event);
|
|||
void gst_event_set_seqnum (GstEvent *event, guint32 seqnum);
|
||||
|
||||
/* Stream start event */
|
||||
GstEvent * gst_event_new_stream_start (void) G_GNUC_MALLOC;
|
||||
GstEvent * gst_event_new_stream_start (const gchar *stream_id) G_GNUC_MALLOC;
|
||||
void gst_event_parse_stream_start (GstEvent *event, const gchar **stream_id);
|
||||
|
||||
/* flush events */
|
||||
GstEvent * gst_event_new_flush_start (void) G_GNUC_MALLOC;
|
||||
|
|
|
@ -64,7 +64,8 @@ static const gchar *_quark_strings[] = {
|
|||
"uid", "tags", "sub-entries", "info", "GstMessageTag", "GstEventTag",
|
||||
"GstMessageResetTime",
|
||||
"GstMessageToc", "GstEventTocGlobal", "GstEventTocCurrent",
|
||||
"GstEventSegmentDone"
|
||||
"GstEventSegmentDone",
|
||||
"GstEventStreamStart", "stream-id"
|
||||
};
|
||||
|
||||
GQuark _priv_gst_quark_table[GST_QUARK_MAX];
|
||||
|
|
|
@ -186,7 +186,9 @@ typedef enum _GstQuarkId
|
|||
GST_QUARK_EVENT_TOC_GLOBAL = 157,
|
||||
GST_QUARK_EVENT_TOC_CURRENT = 158,
|
||||
GST_QUARK_EVENT_SEGMENT_DONE = 159,
|
||||
GST_QUARK_MAX = 160
|
||||
GST_QUARK_EVENT_STREAM_START = 160,
|
||||
GST_QUARK_STREAM_ID = 161,
|
||||
GST_QUARK_MAX = 162
|
||||
} GstQuarkId;
|
||||
|
||||
extern GQuark _priv_gst_quark_table[GST_QUARK_MAX];
|
||||
|
|
169
gst/gstutils.c
169
gst/gstutils.c
|
@ -3535,3 +3535,172 @@ gst_util_fraction_compare (gint a_n, gint a_d, gint b_n, gint b_d)
|
|||
/* Should not happen because a_d and b_d are not 0 */
|
||||
g_return_val_if_reached (0);
|
||||
}
|
||||
|
||||
/** gst_pad_create_stream_id:
|
||||
* @pad: A source #GstPad
|
||||
* @parent: Parent #GstElement of @pad
|
||||
* @stream_id: (allow-none): The stream-id
|
||||
* @var_args: parameters for the @stream_id format string
|
||||
*
|
||||
* Creates a stream-id for the source #GstPad @pad by combining the
|
||||
* upstream information with the optional @stream_id of the stream
|
||||
* of @pad. @pad must have a parent #GstElement and which must have zero
|
||||
* or one sinkpad. @stream_id can only be %NULL if the parent element
|
||||
* of @pad has only a single source pad.
|
||||
*
|
||||
* This function generates an unique stream-id by getting the upstream
|
||||
* stream-start event stream ID and appending @stream_id to it. If the
|
||||
* element has no sinkpad it will generate an upstream stream-id by
|
||||
* doing an URI query on the element and in the worst case just uses
|
||||
* a random number. Source elements that don't implement the URI
|
||||
* handler interface should ideally generate a unique, deterministic
|
||||
* stream-id manually instead.
|
||||
*
|
||||
* Returns: A stream-id for @pad. g_free() after usage.
|
||||
*/
|
||||
gchar *
|
||||
gst_pad_create_stream_id_printf_valist (GstPad * pad, GstElement * parent,
|
||||
const gchar * stream_id, va_list var_args)
|
||||
{
|
||||
GstEvent *upstream_event;
|
||||
gchar *upstream_stream_id = NULL, *new_stream_id;
|
||||
GstPad *sinkpad;
|
||||
|
||||
g_return_val_if_fail (GST_IS_PAD (pad), NULL);
|
||||
g_return_val_if_fail (GST_PAD_IS_SRC (pad), NULL);
|
||||
g_return_val_if_fail (GST_IS_ELEMENT (parent), NULL);
|
||||
|
||||
g_return_val_if_fail (parent->numsinkpads <= 1, NULL);
|
||||
|
||||
/* If the element has multiple source pads it must
|
||||
* provide a stream-id for every source pad, otherwise
|
||||
* all source pads will have the same and are not
|
||||
* distinguishable */
|
||||
g_return_val_if_fail (parent->numsrcpads == 1 || stream_id, NULL);
|
||||
|
||||
/* First try to get the upstream stream-start stream-id from the sinkpad.
|
||||
* This will only work for non-source elements */
|
||||
sinkpad = gst_element_get_static_pad (parent, "sink");
|
||||
if (sinkpad) {
|
||||
upstream_event =
|
||||
gst_pad_get_sticky_event (sinkpad, GST_EVENT_STREAM_START, 0);
|
||||
if (upstream_event) {
|
||||
const gchar *tmp;
|
||||
|
||||
gst_event_parse_stream_start (upstream_event, &tmp);
|
||||
if (tmp)
|
||||
upstream_stream_id = g_strdup (tmp);
|
||||
gst_event_unref (upstream_event);
|
||||
}
|
||||
gst_object_unref (sinkpad);
|
||||
}
|
||||
|
||||
/* The only case where we don't have an upstream start-start event
|
||||
* here is for source elements */
|
||||
if (!upstream_stream_id) {
|
||||
GstQuery *query;
|
||||
|
||||
/* Try to generate one from the URI query and
|
||||
* if it fails take a random number instead */
|
||||
query = gst_query_new_uri ();
|
||||
if (gst_element_query (parent, query)) {
|
||||
GChecksum *cs;
|
||||
gchar *uri;
|
||||
|
||||
gst_query_parse_uri (query, &uri);
|
||||
|
||||
/* And then generate an SHA256 sum of the URI */
|
||||
cs = g_checksum_new (G_CHECKSUM_SHA256);
|
||||
g_checksum_update (cs, (const guchar *) uri, strlen (uri));
|
||||
g_free (uri);
|
||||
upstream_stream_id = g_strdup (g_checksum_get_string (cs));
|
||||
g_checksum_free (cs);
|
||||
} else {
|
||||
/* Just get some random number if the URI query fails */
|
||||
GST_WARNING_OBJECT (pad, "Creating random stream-id, consider "
|
||||
"implementing a deterministic way of creating a stream-id");
|
||||
upstream_stream_id =
|
||||
g_strdup_printf ("%08x%08x%08x%08x", g_random_int (), g_random_int (),
|
||||
g_random_int (), g_random_int ());
|
||||
}
|
||||
|
||||
gst_query_unref (query);
|
||||
}
|
||||
|
||||
if (stream_id) {
|
||||
gchar *expanded = g_strdup_vprintf (stream_id, var_args);
|
||||
new_stream_id = g_strconcat (upstream_stream_id, "/", expanded, NULL);
|
||||
g_free (expanded);
|
||||
} else {
|
||||
new_stream_id = g_strdup (upstream_stream_id);
|
||||
}
|
||||
|
||||
g_free (upstream_stream_id);
|
||||
|
||||
return new_stream_id;
|
||||
}
|
||||
|
||||
/** gst_pad_create_stream_id:
|
||||
* @pad: A source #GstPad
|
||||
* @parent: Parent #GstElement of @pad
|
||||
* @stream_id: (allow-none): The stream-id
|
||||
* @...: parameters for the @stream_id format string
|
||||
*
|
||||
* Creates a stream-id for the source #GstPad @pad by combining the
|
||||
* upstream information with the optional @stream_id of the stream
|
||||
* of @pad. @pad must have a parent #GstElement and which must have zero
|
||||
* or one sinkpad. @stream_id can only be %NULL if the parent element
|
||||
* of @pad has only a single source pad.
|
||||
*
|
||||
* This function generates an unique stream-id by getting the upstream
|
||||
* stream-start event stream ID and appending @stream_id to it. If the
|
||||
* element has no sinkpad it will generate an upstream stream-id by
|
||||
* doing an URI query on the element and in the worst case just uses
|
||||
* a random number. Source elements that don't implement the URI
|
||||
* handler interface should ideally generate a unique, deterministic
|
||||
* stream-id manually instead.
|
||||
*
|
||||
* Returns: A stream-id for @pad. g_free() after usage.
|
||||
*/
|
||||
gchar *
|
||||
gst_pad_create_stream_id_printf (GstPad * pad, GstElement * parent,
|
||||
const gchar * stream_id, ...)
|
||||
{
|
||||
va_list var_args;
|
||||
gchar *new_stream_id;
|
||||
|
||||
va_start (var_args, stream_id);
|
||||
new_stream_id =
|
||||
gst_pad_create_stream_id_printf_valist (pad, parent, stream_id, var_args);
|
||||
va_end (var_args);
|
||||
|
||||
return new_stream_id;
|
||||
}
|
||||
|
||||
/** gst_pad_create_stream_id:
|
||||
* @pad: A source #GstPad
|
||||
* @parent: Parent #GstElement of @pad
|
||||
* @stream_id: (allow-none): The stream-id
|
||||
*
|
||||
* Creates a stream-id for the source #GstPad @pad by combining the
|
||||
* upstream information with the optional @stream_id of the stream
|
||||
* of @pad. @pad must have a parent #GstElement and which must have zero
|
||||
* or one sinkpad. @stream_id can only be %NULL if the parent element
|
||||
* of @pad has only a single source pad.
|
||||
*
|
||||
* This function generates an unique stream-id by getting the upstream
|
||||
* stream-start event stream ID and appending @stream_id to it. If the
|
||||
* element has no sinkpad it will generate an upstream stream-id by
|
||||
* doing an URI query on the element and in the worst case just uses
|
||||
* a random number. Source elements that don't implement the URI
|
||||
* handler interface should ideally generate a unique, deterministic
|
||||
* stream-id manually instead.
|
||||
*
|
||||
* Returns: A stream-id for @pad. g_free() after usage.
|
||||
*/
|
||||
gchar *
|
||||
gst_pad_create_stream_id (GstPad * pad, GstElement * parent,
|
||||
const gchar * stream_id)
|
||||
{
|
||||
return gst_pad_create_stream_id_printf (pad, parent, stream_id, NULL);
|
||||
}
|
||||
|
|
|
@ -888,6 +888,10 @@ gboolean gst_pad_peer_query_convert (GstPad *pad, GstFormat
|
|||
GstCaps * gst_pad_peer_query_caps (GstPad * pad, GstCaps *filter);
|
||||
gboolean gst_pad_peer_query_accept_caps (GstPad * pad, GstCaps *caps);
|
||||
|
||||
gchar * gst_pad_create_stream_id (GstPad * pad, GstElement * parent, const gchar *stream_id);
|
||||
gchar * gst_pad_create_stream_id_printf (GstPad * pad, GstElement * parent, const gchar *stream_id, ...);
|
||||
gchar * gst_pad_create_stream_id_printf_valist (GstPad * pad, GstElement * parent, const gchar *stream_id, va_list var_args);
|
||||
|
||||
/* bin functions */
|
||||
void gst_bin_add_many (GstBin *bin, GstElement *element_1, ...) G_GNUC_NULL_TERMINATED;
|
||||
void gst_bin_remove_many (GstBin *bin, GstElement *element_1, ...) G_GNUC_NULL_TERMINATED;
|
||||
|
|
Loading…
Reference in a new issue