mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-02-02 20:42:30 +00:00
message: Add redirect message
Redirection messages are already used in fragmented sources and in uridecodebin, so it makes sense to introduce these as an official message type. https://bugzilla.gnome.org/show_bug.cgi?id=631673
This commit is contained in:
parent
4981e09bc7
commit
eead9cf827
7 changed files with 367 additions and 2 deletions
|
@ -1678,6 +1678,11 @@ gst_message_streams_selected_add
|
|||
gst_message_streams_selected_get_size
|
||||
gst_message_streams_selected_get_stream
|
||||
|
||||
gst_message_new_redirect
|
||||
gst_message_add_redirect_entry
|
||||
gst_message_parse_redirect_entry
|
||||
gst_message_get_num_redirect_entries
|
||||
|
||||
<SUBSECTION Standard>
|
||||
GstMessageClass
|
||||
GST_MESSAGE
|
||||
|
|
241
gst/gstmessage.c
241
gst/gstmessage.c
|
@ -109,6 +109,7 @@ static GstMessageQuarks message_quarks[] = {
|
|||
{GST_MESSAGE_PROPERTY_NOTIFY, "property-notify", 0},
|
||||
{GST_MESSAGE_STREAM_COLLECTION, "stream-collection", 0},
|
||||
{GST_MESSAGE_STREAMS_SELECTED, "streams-selected", 0},
|
||||
{GST_MESSAGE_REDIRECT, "redirect", 0},
|
||||
{0, NULL, 0}
|
||||
};
|
||||
|
||||
|
@ -2914,3 +2915,243 @@ gst_message_parse_streams_selected (GstMessage * message,
|
|||
gst_structure_id_get (GST_MESSAGE_STRUCTURE (message),
|
||||
GST_QUARK (COLLECTION), GST_TYPE_STREAM_COLLECTION, collection, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_message_new_redirect:
|
||||
* @src: The #GstObject whose property changed (may or may not be a #GstElement)
|
||||
* @location: (transfer none): location string for the new entry
|
||||
* @tag_list: (transfer full) (allow-none): tag list for the new entry
|
||||
* @entry_struct: (transfer full) (allow-none): structure for the new entry
|
||||
*
|
||||
* Creates a new redirect message and adds a new entry to it. Redirect messages
|
||||
* are posted when an element detects that the actual data has to be retrieved
|
||||
* from a different location. This is useful if such a redirection cannot be
|
||||
* handled inside a source element, for example when HTTP 302/303 redirects
|
||||
* return a non-HTTP URL.
|
||||
*
|
||||
* The redirect message can hold multiple entries. The first one is added
|
||||
* when the redirect message is created, with the given location, tag_list,
|
||||
* entry_struct arguments. Use gst_message_add_redirect_entry() to add more
|
||||
* entries.
|
||||
*
|
||||
* Each entry has a location, a tag list, and a structure. All of these are
|
||||
* optional. The tag list and structure are useful for additional metadata,
|
||||
* such as bitrate statistics for the given location.
|
||||
*
|
||||
* By default, message recipients should treat entries in the order they are
|
||||
* stored. The recipient should therefore try entry #0 first, and if this
|
||||
* entry is not acceptable or working, try entry #1 etc. Senders must make
|
||||
* sure that they add entries in this order. However, recipients are free to
|
||||
* ignore the order and pick an entry that is "best" for them. One example
|
||||
* would be a recipient that scans the entries for the one with the highest
|
||||
* bitrate tag.
|
||||
*
|
||||
* The specified location string is copied. However, ownership over the tag
|
||||
* list and structure are transferred to the message.
|
||||
*
|
||||
* Returns: a newly allocated #GstMessage
|
||||
*
|
||||
* Since: 1.10
|
||||
*/
|
||||
GstMessage *
|
||||
gst_message_new_redirect (GstObject * src, const gchar * location,
|
||||
GstTagList * tag_list, const GstStructure * entry_struct)
|
||||
{
|
||||
GstStructure *structure;
|
||||
GstMessage *message;
|
||||
GValue entry_locations_gvalue = G_VALUE_INIT;
|
||||
GValue entry_taglists_gvalue = G_VALUE_INIT;
|
||||
GValue entry_structures_gvalue = G_VALUE_INIT;
|
||||
|
||||
g_return_val_if_fail (location != NULL, NULL);
|
||||
|
||||
g_value_init (&entry_locations_gvalue, GST_TYPE_LIST);
|
||||
g_value_init (&entry_taglists_gvalue, GST_TYPE_LIST);
|
||||
g_value_init (&entry_structures_gvalue, GST_TYPE_LIST);
|
||||
|
||||
structure = gst_structure_new_id_empty (GST_QUARK (MESSAGE_REDIRECT));
|
||||
gst_structure_id_take_value (structure, GST_QUARK (REDIRECT_ENTRY_LOCATIONS),
|
||||
&entry_locations_gvalue);
|
||||
gst_structure_id_take_value (structure, GST_QUARK (REDIRECT_ENTRY_TAGLISTS),
|
||||
&entry_taglists_gvalue);
|
||||
gst_structure_id_take_value (structure, GST_QUARK (REDIRECT_ENTRY_STRUCTURES),
|
||||
&entry_structures_gvalue);
|
||||
|
||||
message = gst_message_new_custom (GST_MESSAGE_REDIRECT, src, structure);
|
||||
g_assert (message != NULL);
|
||||
|
||||
gst_message_add_redirect_entry (message, location, tag_list, entry_struct);
|
||||
|
||||
return message;
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_message_add_redirect_entry:
|
||||
* @message: a #GstMessage of type %GST_MESSAGE_REDIRECT
|
||||
* @location: (transfer none): location string for the new entry
|
||||
* @tag_list: (transfer full) (allow-none): tag list for the new entry
|
||||
* @entry_struct: (transfer full) (allow-none): structure for the new entry
|
||||
*
|
||||
* Creates and appends a new entry.
|
||||
*
|
||||
* The specified location string is copied. However, ownership over the tag
|
||||
* list and structure are transferred to the message.
|
||||
*
|
||||
* Since: 1.10
|
||||
*/
|
||||
void
|
||||
gst_message_add_redirect_entry (GstMessage * message, const gchar * location,
|
||||
GstTagList * tag_list, const GstStructure * entry_struct)
|
||||
{
|
||||
GValue val = G_VALUE_INIT;
|
||||
GstStructure *structure;
|
||||
GValue *entry_locations_gvalue;
|
||||
GValue *entry_taglists_gvalue;
|
||||
GValue *entry_structures_gvalue;
|
||||
|
||||
g_return_if_fail (location != NULL);
|
||||
g_return_if_fail (GST_IS_MESSAGE (message));
|
||||
g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_REDIRECT);
|
||||
|
||||
structure = GST_MESSAGE_STRUCTURE (message);
|
||||
|
||||
entry_locations_gvalue =
|
||||
(GValue *) gst_structure_id_get_value (structure,
|
||||
GST_QUARK (REDIRECT_ENTRY_LOCATIONS));
|
||||
g_return_if_fail (GST_VALUE_HOLDS_LIST (entry_locations_gvalue));
|
||||
entry_taglists_gvalue =
|
||||
(GValue *) gst_structure_id_get_value (structure,
|
||||
GST_QUARK (REDIRECT_ENTRY_TAGLISTS));
|
||||
g_return_if_fail (GST_VALUE_HOLDS_LIST (entry_taglists_gvalue));
|
||||
entry_structures_gvalue =
|
||||
(GValue *) gst_structure_id_get_value (structure,
|
||||
GST_QUARK (REDIRECT_ENTRY_STRUCTURES));
|
||||
g_return_if_fail (GST_VALUE_HOLDS_LIST (entry_structures_gvalue));
|
||||
|
||||
g_value_init (&val, G_TYPE_STRING);
|
||||
if (location)
|
||||
g_value_set_string (&val, location);
|
||||
gst_value_list_append_and_take_value (entry_locations_gvalue, &val);
|
||||
|
||||
g_value_init (&val, GST_TYPE_TAG_LIST);
|
||||
if (tag_list)
|
||||
g_value_take_boxed (&val, tag_list);
|
||||
gst_value_list_append_and_take_value (entry_taglists_gvalue, &val);
|
||||
|
||||
g_value_init (&val, GST_TYPE_STRUCTURE);
|
||||
if (entry_struct)
|
||||
g_value_take_boxed (&val, entry_struct);
|
||||
gst_value_list_append_and_take_value (entry_structures_gvalue, &val);
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_message_parse_redirect_entry:
|
||||
* @message: a #GstMessage of type %GST_MESSAGE_REDIRECT
|
||||
* @entry_index: index of the entry to parse
|
||||
* @location: (out) (transfer none) (allow-none): return location for
|
||||
* the pointer to the entry's location string, or %NULL
|
||||
* @tag_list: (out) (transfer none) (allow-none): return location for
|
||||
* the pointer to the entry's tag list, or %NULL
|
||||
* @entry_struct: (out) (transfer none) (allow-none): return location
|
||||
* for the pointer to the entry's structure, or %NULL
|
||||
*
|
||||
* Parses the location and/or structure from the entry with the given index.
|
||||
* The index must be between 0 and gst_message_get_num_redirect_entries() - 1.
|
||||
* Returned pointers are valid for as long as this message exists.
|
||||
*
|
||||
* Since: 1.10
|
||||
*/
|
||||
void
|
||||
gst_message_parse_redirect_entry (GstMessage * message, gsize entry_index,
|
||||
const gchar ** location, GstTagList ** tag_list,
|
||||
const GstStructure ** entry_struct)
|
||||
{
|
||||
const GValue *val;
|
||||
GstStructure *structure;
|
||||
const GValue *entry_locations_gvalue;
|
||||
const GValue *entry_taglists_gvalue;
|
||||
const GValue *entry_structures_gvalue;
|
||||
|
||||
g_return_if_fail (GST_IS_MESSAGE (message));
|
||||
g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_REDIRECT);
|
||||
|
||||
if (G_UNLIKELY (!location && !tag_list && !entry_struct))
|
||||
return;
|
||||
|
||||
structure = GST_MESSAGE_STRUCTURE (message);
|
||||
|
||||
entry_locations_gvalue =
|
||||
gst_structure_id_get_value (structure,
|
||||
GST_QUARK (REDIRECT_ENTRY_LOCATIONS));
|
||||
g_return_if_fail (GST_VALUE_HOLDS_LIST (entry_locations_gvalue));
|
||||
entry_taglists_gvalue =
|
||||
gst_structure_id_get_value (structure,
|
||||
GST_QUARK (REDIRECT_ENTRY_TAGLISTS));
|
||||
g_return_if_fail (GST_VALUE_HOLDS_LIST (entry_taglists_gvalue));
|
||||
entry_structures_gvalue =
|
||||
gst_structure_id_get_value (structure,
|
||||
GST_QUARK (REDIRECT_ENTRY_STRUCTURES));
|
||||
g_return_if_fail (GST_VALUE_HOLDS_LIST (entry_structures_gvalue));
|
||||
|
||||
if (location) {
|
||||
val = gst_value_list_get_value (entry_locations_gvalue, entry_index);
|
||||
g_return_if_fail (val != NULL);
|
||||
*location = g_value_get_string (val);
|
||||
}
|
||||
|
||||
if (tag_list) {
|
||||
val = gst_value_list_get_value (entry_taglists_gvalue, entry_index);
|
||||
g_return_if_fail (val != NULL);
|
||||
*tag_list = (GstTagList *) g_value_get_boxed (val);
|
||||
}
|
||||
|
||||
if (entry_struct) {
|
||||
val = gst_value_list_get_value (entry_structures_gvalue, entry_index);
|
||||
g_return_if_fail (val != NULL);
|
||||
*entry_struct = (const GstStructure *) g_value_get_boxed (val);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_message_get_num_redirect_entries:
|
||||
* @message: a #GstMessage of type %GST_MESSAGE_REDIRECT
|
||||
*
|
||||
* Returns: the number of entries stored in the message
|
||||
*
|
||||
* Since: 1.10
|
||||
*/
|
||||
gsize
|
||||
gst_message_get_num_redirect_entries (GstMessage * message)
|
||||
{
|
||||
GstStructure *structure;
|
||||
const GValue *entry_locations_gvalue;
|
||||
const GValue *entry_taglists_gvalue;
|
||||
const GValue *entry_structures_gvalue;
|
||||
gsize size;
|
||||
|
||||
g_return_val_if_fail (GST_IS_MESSAGE (message), 0);
|
||||
g_return_val_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_REDIRECT, 0);
|
||||
|
||||
structure = GST_MESSAGE_STRUCTURE (message);
|
||||
|
||||
entry_locations_gvalue =
|
||||
gst_structure_id_get_value (structure,
|
||||
GST_QUARK (REDIRECT_ENTRY_LOCATIONS));
|
||||
g_return_val_if_fail (GST_VALUE_HOLDS_LIST (entry_locations_gvalue), 0);
|
||||
entry_taglists_gvalue =
|
||||
gst_structure_id_get_value (structure,
|
||||
GST_QUARK (REDIRECT_ENTRY_TAGLISTS));
|
||||
g_return_val_if_fail (GST_VALUE_HOLDS_LIST (entry_taglists_gvalue), 0);
|
||||
entry_structures_gvalue =
|
||||
gst_structure_id_get_value (structure,
|
||||
GST_QUARK (REDIRECT_ENTRY_STRUCTURES));
|
||||
g_return_val_if_fail (GST_VALUE_HOLDS_LIST (entry_structures_gvalue), 0);
|
||||
|
||||
size = gst_value_list_get_size (entry_locations_gvalue);
|
||||
|
||||
g_return_val_if_fail ((size ==
|
||||
gst_value_list_get_size (entry_structures_gvalue))
|
||||
&& (size == gst_value_list_get_size (entry_taglists_gvalue)), 0);
|
||||
|
||||
return size;
|
||||
}
|
||||
|
|
|
@ -114,6 +114,9 @@ typedef struct _GstMessage GstMessage;
|
|||
* is available (Since 1.10)
|
||||
* @GST_MESSAGE_STREAMS_SELECTED: Message indicating the active selection of
|
||||
* #GstStreams has changed (Since 1.10)
|
||||
* @GST_MESSAGE_REDIRECT: Message indicating to request the application to
|
||||
* try to play the given URL(s). Useful if for example a HTTP 302/303
|
||||
* response is received with a non-HTTP URL inside. (Since 1.10)
|
||||
* @GST_MESSAGE_ANY: mask for all of the above messages.
|
||||
*
|
||||
* The different message types that are available.
|
||||
|
@ -165,6 +168,7 @@ typedef enum
|
|||
GST_MESSAGE_PROPERTY_NOTIFY = GST_MESSAGE_EXTENDED + 3,
|
||||
GST_MESSAGE_STREAM_COLLECTION = GST_MESSAGE_EXTENDED + 4,
|
||||
GST_MESSAGE_STREAMS_SELECTED = GST_MESSAGE_EXTENDED + 5,
|
||||
GST_MESSAGE_REDIRECT = GST_MESSAGE_EXTENDED + 6,
|
||||
GST_MESSAGE_ANY = (gint) (0xffffffff)
|
||||
} GstMessageType;
|
||||
|
||||
|
@ -623,6 +627,12 @@ void gst_message_parse_streams_selected (GstMessage * message, GstStr
|
|||
guint gst_message_streams_selected_get_size (GstMessage * message);
|
||||
GstStream *gst_message_streams_selected_get_stream (GstMessage *message, guint idx);
|
||||
|
||||
/* REDIRECT */
|
||||
GstMessage * gst_message_new_redirect (GstObject * src, const gchar * location, GstTagList * tag_list, const GstStructure * entry_struct) G_GNUC_MALLOC;
|
||||
void gst_message_add_redirect_entry (GstMessage * message, const gchar * location, GstTagList * tag_list, const GstStructure * entry_struct);
|
||||
void gst_message_parse_redirect_entry (GstMessage * message, gsize entry_index, const gchar ** location, GstTagList ** tag_list, const GstStructure ** entry_struct);
|
||||
gsize gst_message_get_num_redirect_entries (GstMessage * message);
|
||||
|
||||
#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstMessage, gst_message_unref)
|
||||
#endif
|
||||
|
|
|
@ -73,7 +73,8 @@ static const gchar *_quark_strings[] = {
|
|||
"uri-redirection-permanent", "GstMessagePropertyNotify", "property-name",
|
||||
"property-value", "streams", "GstEventSelectStreams",
|
||||
"GstMessageStreamCollection", "collection", "stream", "stream-collection",
|
||||
"GstMessageStreamsSelected"
|
||||
"GstMessageStreamsSelected", "GstMessageRedirect", "redirect-entry-locations",
|
||||
"redirect-entry-taglists", "redirect-entry-structures"
|
||||
};
|
||||
|
||||
GQuark _priv_gst_quark_table[GST_QUARK_MAX];
|
||||
|
|
|
@ -212,7 +212,11 @@ typedef enum _GstQuarkId
|
|||
GST_QUARK_STREAM = 181,
|
||||
GST_QUARK_EVENT_STREAM_COLLECTION = 182,
|
||||
GST_QUARK_MESSAGE_STREAMS_SELECTED = 183,
|
||||
GST_QUARK_MAX = 184
|
||||
GST_QUARK_MESSAGE_REDIRECT = 184,
|
||||
GST_QUARK_REDIRECT_ENTRY_LOCATIONS = 185,
|
||||
GST_QUARK_REDIRECT_ENTRY_TAGLISTS = 186,
|
||||
GST_QUARK_REDIRECT_ENTRY_STRUCTURES = 187,
|
||||
GST_QUARK_MAX = 188
|
||||
} GstQuarkId;
|
||||
|
||||
extern GQuark _priv_gst_quark_table[GST_QUARK_MAX];
|
||||
|
|
|
@ -501,6 +501,106 @@ GST_START_TEST (test_parsing)
|
|||
gst_caps_unref (caps1);
|
||||
gst_caps_unref (caps2);
|
||||
}
|
||||
/* GST_MESSAGE_REDIRECT */
|
||||
{
|
||||
const gchar *parsed_location;
|
||||
GstTagList *parsed_tag_list;
|
||||
const GstStructure *parsed_structure;
|
||||
const gchar *test_location = "some-location";
|
||||
const gchar *test_struct_name = "test-struct";
|
||||
const gchar *test_value_name = "foo";
|
||||
const gint test_value = 12345;
|
||||
const guint test_bitrate = 120000;
|
||||
gint value;
|
||||
guint bitrate;
|
||||
GstTagList *test_tag_list;
|
||||
GstStructure *test_structure;
|
||||
|
||||
test_structure =
|
||||
gst_structure_new (test_struct_name, test_value_name, G_TYPE_INT,
|
||||
test_value, NULL);
|
||||
|
||||
/* Create a test tag list. It is ref'd before adding an entry to be able
|
||||
* to test that new_redirect takes ownership */
|
||||
test_tag_list = gst_tag_list_new (GST_TAG_BITRATE, test_bitrate, NULL);
|
||||
|
||||
/* Create the message and add the first entry, which only has a location
|
||||
* and a tag list */
|
||||
gst_tag_list_ref (test_tag_list);
|
||||
message =
|
||||
gst_message_new_redirect (NULL, test_location, test_tag_list, NULL);
|
||||
fail_if (message == NULL);
|
||||
fail_unless (GST_MESSAGE_TYPE (message) == GST_MESSAGE_REDIRECT);
|
||||
fail_unless (GST_MESSAGE_SRC (message) == NULL);
|
||||
|
||||
/* Add the second entry, which only has a location and a structure */
|
||||
gst_message_add_redirect_entry (message, test_location, NULL,
|
||||
gst_structure_copy (test_structure));
|
||||
|
||||
/* Add the third entry, which has a location, a taglist, and a structure */
|
||||
gst_tag_list_ref (test_tag_list);
|
||||
gst_message_add_redirect_entry (message, test_location, test_tag_list,
|
||||
gst_structure_copy (test_structure));
|
||||
|
||||
fail_unless (gst_message_get_num_redirect_entries (message) == 3);
|
||||
|
||||
/* Check that the location of the first entry is correct and that the
|
||||
* structure pointer is set to NULL */
|
||||
parsed_location = NULL;
|
||||
parsed_tag_list = NULL;
|
||||
parsed_structure = (const GstStructure *) 0x1;
|
||||
gst_message_parse_redirect_entry (message, 0, &parsed_location,
|
||||
&parsed_tag_list, &parsed_structure);
|
||||
fail_unless (parsed_location != NULL);
|
||||
fail_unless (parsed_tag_list != NULL);
|
||||
fail_unless (parsed_structure == NULL);
|
||||
fail_unless (!strcmp (parsed_location, test_location));
|
||||
fail_unless (gst_tag_list_get_uint (parsed_tag_list, GST_TAG_BITRATE,
|
||||
&bitrate) && (bitrate == test_bitrate));
|
||||
|
||||
/* Check that the structure of the second entry is correct and that the
|
||||
* tag list pointer is set to NULL */
|
||||
parsed_location = NULL;
|
||||
parsed_tag_list = (GstTagList *) 0x1;
|
||||
parsed_structure = NULL;
|
||||
gst_message_parse_redirect_entry (message, 1, &parsed_location,
|
||||
&parsed_tag_list, &parsed_structure);
|
||||
fail_unless (parsed_location != NULL);
|
||||
fail_unless (parsed_tag_list == NULL);
|
||||
fail_unless (parsed_structure != NULL);
|
||||
fail_unless (!strcmp (parsed_location, test_location));
|
||||
fail_unless (!strcmp (gst_structure_get_name (parsed_structure),
|
||||
test_struct_name));
|
||||
fail_unless (gst_structure_get_int (parsed_structure, test_value_name,
|
||||
&value) && (value == test_value));
|
||||
|
||||
/* Check that the location, tag list, and structure pointers of the
|
||||
* third entry are correct */
|
||||
parsed_location = NULL;
|
||||
parsed_tag_list = NULL;
|
||||
parsed_structure = NULL;
|
||||
gst_message_parse_redirect_entry (message, 2, &parsed_location,
|
||||
&parsed_tag_list, &parsed_structure);
|
||||
fail_unless (parsed_location != NULL);
|
||||
fail_unless (parsed_tag_list != NULL);
|
||||
fail_unless (parsed_structure != NULL);
|
||||
fail_unless (!strcmp (parsed_location, test_location));
|
||||
fail_unless (!strcmp (gst_structure_get_name (parsed_structure),
|
||||
test_struct_name));
|
||||
fail_unless (gst_tag_list_get_uint (parsed_tag_list, GST_TAG_BITRATE,
|
||||
&bitrate) && (bitrate == test_bitrate));
|
||||
fail_unless (gst_structure_get_int (parsed_structure, test_value_name,
|
||||
&value) && (value == test_value));
|
||||
|
||||
gst_message_unref (message);
|
||||
|
||||
/* Since the message takes ownership over the tag list, its refcount
|
||||
* must have been decreased after each added entry */
|
||||
fail_unless_equals_int (GST_MINI_OBJECT_REFCOUNT_VALUE (test_tag_list), 1);
|
||||
|
||||
gst_structure_free (test_structure);
|
||||
gst_tag_list_unref (test_tag_list);
|
||||
}
|
||||
}
|
||||
|
||||
GST_END_TEST;
|
||||
|
|
|
@ -700,6 +700,8 @@ EXPORTS
|
|||
gst_memory_resize
|
||||
gst_memory_share
|
||||
gst_memory_unmap
|
||||
gst_message_add_redirect_entry
|
||||
gst_message_get_num_redirect_entries
|
||||
gst_message_get_seqnum
|
||||
gst_message_get_stream_status_object
|
||||
gst_message_get_structure
|
||||
|
@ -728,6 +730,7 @@ EXPORTS
|
|||
gst_message_new_progress
|
||||
gst_message_new_property_notify
|
||||
gst_message_new_qos
|
||||
gst_message_new_redirect
|
||||
gst_message_new_request_state
|
||||
gst_message_new_reset_time
|
||||
gst_message_new_segment_done
|
||||
|
@ -765,6 +768,7 @@ EXPORTS
|
|||
gst_message_parse_qos
|
||||
gst_message_parse_qos_stats
|
||||
gst_message_parse_qos_values
|
||||
gst_message_parse_redirect_entry
|
||||
gst_message_parse_request_state
|
||||
gst_message_parse_reset_time
|
||||
gst_message_parse_segment_done
|
||||
|
|
Loading…
Reference in a new issue