diff --git a/docs/gst/gstreamer-sections.txt b/docs/gst/gstreamer-sections.txt index 30150feac5..bccaac5985 100644 --- a/docs/gst/gstreamer-sections.txt +++ b/docs/gst/gstreamer-sections.txt @@ -3452,6 +3452,7 @@ gst_uri_query_has_key gst_uri_get_query_keys gst_uri_get_fragment gst_uri_set_fragment +gst_uri_get_media_fragment_table GST_IS_URI GST_TYPE_URI diff --git a/gst/gsturi.c b/gst/gsturi.c index d87d4dbfe2..cb0d01b9ec 100644 --- a/gst/gsturi.c +++ b/gst/gsturi.c @@ -2803,3 +2803,34 @@ gst_uri_set_fragment (GstUri * uri, const gchar * fragment) uri->fragment = g_strdup (fragment); return TRUE; } + +/** + * gst_uri_get_media_fragment_table: + * @uri: (nullable): The #GstUri to get the fragment table from. + * + * Get the media fragment table from the URI, as defined by "Media Fragments URI 1.0". + * Hash table returned by this API is a list of "key-value" pairs, and the each + * pair is generated by splitting "URI fragment" per "&" sub-delims, then "key" + * and "value" are splitted by "=" sub-delims. The "key" returned by this API may + * be undefined keyword by standard. + * A value may be %NULL to indicate that the key should appear in the fragment + * string in the URI, but does not have a value. Free the returned #GHashTable + * with #g_hash_table_unref() when it is no longer required. + * Modifying this hash table does not affect the fragment in the URI. + * + * See more about Media Fragments URI 1.0 (W3C) at https://www.w3.org/TR/media-frags/ + * + * Returns: (transfer full)(element-type gchar* gchar*): The fragment hash table + * from the URI. + * + * Since: 1.12 + */ +GHashTable * +gst_uri_get_media_fragment_table (const GstUri * uri) +{ + g_return_val_if_fail (uri == NULL || GST_IS_URI (uri), NULL); + + if (!uri->fragment) + return NULL; + return _gst_uri_string_to_table (uri->fragment, "&", "=", TRUE, TRUE); +} diff --git a/gst/gsturi.h b/gst/gsturi.h index 7e0f0b3a82..9a78fa3be0 100644 --- a/gst/gsturi.h +++ b/gst/gsturi.h @@ -250,6 +250,7 @@ const gchar * gst_uri_get_query_value (const GstUri * uri, GList * gst_uri_get_query_keys (const GstUri * uri); const gchar * gst_uri_get_fragment (const GstUri * uri); gboolean gst_uri_set_fragment (GstUri * uri, const gchar * fragment); +GHashTable * gst_uri_get_media_fragment_table (const GstUri * uri); /** * gst_uri_copy: diff --git a/tests/check/gst/gsturi.c b/tests/check/gst/gsturi.c index e7ce6dfd47..dbd1509b68 100644 --- a/tests/check/gst/gsturi.c +++ b/tests/check/gst/gsturi.c @@ -980,6 +980,80 @@ GST_START_TEST (test_url_get_set) GST_END_TEST; +GST_START_TEST (test_url_get_media_fragment_table) +{ + GstUri *url; + gchar *val; + GHashTable *table; + + /* Examples at https://www.w3.org/TR/media-frags/#processing-media-fragment-uri */ + + /* TEST "t=1" */ + url = gst_uri_from_string ("http://foo/var/file#t=1"); + table = gst_uri_get_media_fragment_table (url); + fail_unless (table); + fail_unless (g_hash_table_size (table) == 1); + fail_unless (g_hash_table_lookup_extended (table, "t", NULL, + (gpointer) & val)); + fail_unless_equals_string ("1", val); + g_hash_table_unref (table); + gst_uri_unref (url); + + /* NOTE: Media Fragments URI 1.0 (W3C) is saying that + * "Multiple occurrences of the same dimension: only the last valid occurrence + * of a dimension (e.g. t=10 in #t=2&t=10) is interpreted and all previous + * occurrences (valid or invalid) SHOULD be ignored by the user agent" + */ + /* TEST "t=1&t=2" */ + url = gst_uri_from_string ("http://foo/var/file#t=1&t=2"); + table = gst_uri_get_media_fragment_table (url); + fail_unless (table); + fail_unless (g_hash_table_size (table) == 1); + fail_unless (g_hash_table_lookup_extended (table, "t", NULL, + (gpointer) & val)); + fail_unless_equals_string ("2", val); + g_hash_table_unref (table); + gst_uri_unref (url); + + /* TEST "a=b=c" */ + url = gst_uri_from_string ("http://foo/var/file#a=b=c"); + table = gst_uri_get_media_fragment_table (url); + fail_unless (table); + fail_unless (g_hash_table_size (table) == 1); + fail_unless (g_hash_table_lookup_extended (table, "a", NULL, + (gpointer) & val)); + fail_unless_equals_string ("b=c", val); + g_hash_table_unref (table); + gst_uri_unref (url); + + /* TEST "a&b=c" */ + url = gst_uri_from_string ("http://foo/var/file#a&b=c"); + table = gst_uri_get_media_fragment_table (url); + fail_unless (table); + fail_unless (g_hash_table_size (table) == 2); + fail_unless (g_hash_table_lookup_extended (table, "a", NULL, + (gpointer) & val)); + fail_unless (val == NULL); + fail_unless (g_hash_table_lookup_extended (table, "b", NULL, + (gpointer) & val)); + fail_unless_equals_string ("c", val); + g_hash_table_unref (table); + gst_uri_unref (url); + + /* TEST "%74=%6ept%3A%310" */ + url = gst_uri_from_string ("http://foo/var/file#%74=%6ept%3A%310"); + table = gst_uri_get_media_fragment_table (url); + fail_unless (table); + fail_unless (g_hash_table_size (table) == 1); + fail_unless (g_hash_table_lookup_extended (table, "t", NULL, + (gpointer) & val)); + fail_unless_equals_string ("npt:10", val); + g_hash_table_unref (table); + gst_uri_unref (url); +} + +GST_END_TEST; + static Suite * gst_uri_suite (void) { @@ -1003,6 +1077,7 @@ gst_uri_suite (void) tcase_add_test (tc_chain, test_url_equality); tcase_add_test (tc_chain, test_url_constructors); tcase_add_test (tc_chain, test_url_get_set); + tcase_add_test (tc_chain, test_url_get_media_fragment_table); return s; } diff --git a/win32/common/libgstreamer.def b/win32/common/libgstreamer.def index f63ffee4be..9ecf089ca5 100644 --- a/win32/common/libgstreamer.def +++ b/win32/common/libgstreamer.def @@ -1493,6 +1493,7 @@ EXPORTS gst_uri_get_fragment gst_uri_get_host gst_uri_get_location + gst_uri_get_media_fragment_table gst_uri_get_path gst_uri_get_path_segments gst_uri_get_path_string