mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-15 22:01:27 +00:00
dash: Store entire ContentProtection node in protection event data
Some manifests use the ContentProtection node to store additional information such as the license server url. Our MPD parser used to process the ContentProtection node, extracting Playready PSSH boxes. However for other DRM systems, only the `value` attribute was passed down to the protection event, so for example, Widevine data was not parsed at all and "Widevine" was passed to the event, which is not very useful for decryptors that require a PSSH init data. Parsing should now be done by decryptors which will receive the entire ContentProtection XML node as a string. This gives more "freedom" to the decryptor which can then detect and parse custom nodes as well. Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-bad/-/merge_requests/2400>
This commit is contained in:
parent
ff0e42eb30
commit
bc09d8cc66
2 changed files with 74 additions and 29 deletions
|
@ -503,35 +503,14 @@ error:
|
||||||
static void
|
static void
|
||||||
gst_mpdparser_parse_content_protection_node (GList ** list, xmlNode * a_node)
|
gst_mpdparser_parse_content_protection_node (GList ** list, xmlNode * a_node)
|
||||||
{
|
{
|
||||||
gchar *value = NULL;
|
GstMPDDescriptorTypeNode *new_descriptor;
|
||||||
if (gst_xml_helper_get_prop_string (a_node, "value", &value)) {
|
new_descriptor = gst_mpd_descriptor_type_node_new ((const gchar *)
|
||||||
if (!g_strcmp0 (value, "MSPR 2.0")) {
|
a_node->name);
|
||||||
xmlNode *cur_node;
|
*list = g_list_append (*list, new_descriptor);
|
||||||
for (cur_node = a_node->children; cur_node; cur_node = cur_node->next) {
|
|
||||||
if (cur_node->type == XML_ELEMENT_NODE) {
|
|
||||||
if (xmlStrcmp (cur_node->name, (xmlChar *) "pro") == 0) {
|
|
||||||
GstMPDDescriptorTypeNode *new_descriptor;
|
|
||||||
new_descriptor = gst_mpd_descriptor_type_node_new ((const gchar *)
|
|
||||||
cur_node->name);
|
|
||||||
*list = g_list_append (*list, new_descriptor);
|
|
||||||
|
|
||||||
gst_xml_helper_get_prop_string_stripped (a_node, "schemeIdUri",
|
gst_xml_helper_get_prop_string_stripped (a_node, "schemeIdUri",
|
||||||
&new_descriptor->schemeIdUri);
|
&new_descriptor->schemeIdUri);
|
||||||
|
gst_xml_helper_get_node_as_string (a_node, &new_descriptor->value);
|
||||||
gst_xml_helper_get_node_content (cur_node, &new_descriptor->value);
|
|
||||||
goto beach;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
gst_mpdparser_parse_descriptor_type (list, a_node);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
gst_mpdparser_parse_descriptor_type (list, a_node);
|
|
||||||
}
|
|
||||||
beach:
|
|
||||||
if (value)
|
|
||||||
g_free (value);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
|
@ -1392,6 +1392,7 @@ GST_START_TEST
|
||||||
|
|
||||||
gboolean ret;
|
gboolean ret;
|
||||||
GstMPDClient *mpdclient = gst_mpd_client_new ();
|
GstMPDClient *mpdclient = gst_mpd_client_new ();
|
||||||
|
gchar *str;
|
||||||
|
|
||||||
ret = gst_mpd_client_parse (mpdclient, xml, (gint) strlen (xml));
|
ret = gst_mpd_client_parse (mpdclient, xml, (gint) strlen (xml));
|
||||||
assert_equals_int (ret, TRUE);
|
assert_equals_int (ret, TRUE);
|
||||||
|
@ -1402,13 +1403,76 @@ GST_START_TEST
|
||||||
contentProtection =
|
contentProtection =
|
||||||
(GstMPDDescriptorTypeNode *) representationBase->ContentProtection->data;
|
(GstMPDDescriptorTypeNode *) representationBase->ContentProtection->data;
|
||||||
assert_equals_string (contentProtection->schemeIdUri, "TestSchemeIdUri");
|
assert_equals_string (contentProtection->schemeIdUri, "TestSchemeIdUri");
|
||||||
assert_equals_string (contentProtection->value, "TestValue");
|
|
||||||
|
/* We can't do a simple compare of value (which should be an XML dump
|
||||||
|
of the ContentProtection element), because the whitespace
|
||||||
|
formatting from xmlDump might differ between versions of libxml */
|
||||||
|
str = strstr (contentProtection->value, "<ContentProtection");
|
||||||
|
fail_if (str == NULL);
|
||||||
|
str = strstr (contentProtection->value, "value=\"TestValue\"");
|
||||||
|
fail_if (str == NULL);
|
||||||
|
str = strstr (contentProtection->value, "</ContentProtection>");
|
||||||
|
fail_if (str == NULL);
|
||||||
|
|
||||||
gst_mpd_client_free (mpdclient);
|
gst_mpd_client_free (mpdclient);
|
||||||
}
|
}
|
||||||
|
|
||||||
GST_END_TEST;
|
GST_END_TEST;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Test parsing Period AdaptationSet RepresentationBase ContentProtection
|
||||||
|
* with custom ContentProtection content.
|
||||||
|
*/
|
||||||
|
GST_START_TEST
|
||||||
|
(dash_mpdparser_period_adaptationSet_representationBase_contentProtection_with_content)
|
||||||
|
{
|
||||||
|
GstMPDPeriodNode *periodNode;
|
||||||
|
GstMPDAdaptationSetNode *adaptationSet;
|
||||||
|
GstMPDRepresentationBaseNode *representationBase;
|
||||||
|
GstMPDDescriptorTypeNode *contentProtection;
|
||||||
|
const gchar *xml =
|
||||||
|
"<?xml version=\"1.0\"?>"
|
||||||
|
"<MPD xmlns=\"urn:mpeg:dash:schema:mpd:2011\""
|
||||||
|
" profiles=\"urn:mpeg:dash:profile:isoff-main:2011\">"
|
||||||
|
" customns=\"foo\""
|
||||||
|
" <Period>"
|
||||||
|
" <AdaptationSet>"
|
||||||
|
" <ContentProtection schemeIdUri=\"TestSchemeIdUri\">"
|
||||||
|
" <customns:bar>Hello world</customns:bar>"
|
||||||
|
" </ContentProtection></AdaptationSet></Period></MPD>";
|
||||||
|
|
||||||
|
gboolean ret;
|
||||||
|
GstMPDClient *mpdclient = gst_mpd_client_new ();
|
||||||
|
gchar *str;
|
||||||
|
|
||||||
|
ret = gst_mpd_client_parse (mpdclient, xml, (gint) strlen (xml));
|
||||||
|
assert_equals_int (ret, TRUE);
|
||||||
|
|
||||||
|
periodNode = (GstMPDPeriodNode *) mpdclient->mpd_root_node->Periods->data;
|
||||||
|
adaptationSet = (GstMPDAdaptationSetNode *) periodNode->AdaptationSets->data;
|
||||||
|
representationBase = GST_MPD_REPRESENTATION_BASE_NODE (adaptationSet);
|
||||||
|
contentProtection =
|
||||||
|
(GstMPDDescriptorTypeNode *) representationBase->ContentProtection->data;
|
||||||
|
assert_equals_string (contentProtection->schemeIdUri, "TestSchemeIdUri");
|
||||||
|
|
||||||
|
/* We can't do a simple compare of value (which should be an XML dump
|
||||||
|
of the ContentProtection element), because the whitespace
|
||||||
|
formatting from xmlDump might differ between versions of libxml */
|
||||||
|
str = strstr (contentProtection->value, "<ContentProtection");
|
||||||
|
fail_if (str == NULL);
|
||||||
|
str =
|
||||||
|
strstr (contentProtection->value,
|
||||||
|
"<customns:bar>Hello world</customns:bar>");
|
||||||
|
fail_if (str == NULL);
|
||||||
|
str = strstr (contentProtection->value, "</ContentProtection>");
|
||||||
|
fail_if (str == NULL);
|
||||||
|
|
||||||
|
gst_mpd_client_free (mpdclient);
|
||||||
|
}
|
||||||
|
|
||||||
|
GST_END_TEST;
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Test parsing ContentProtection element that has no value attribute
|
* Test parsing ContentProtection element that has no value attribute
|
||||||
*/
|
*/
|
||||||
|
@ -6388,6 +6452,8 @@ dash_suite (void)
|
||||||
tcase_add_test (tc_simpleMPD, dash_mpdparser_contentProtection_no_value);
|
tcase_add_test (tc_simpleMPD, dash_mpdparser_contentProtection_no_value);
|
||||||
tcase_add_test (tc_simpleMPD,
|
tcase_add_test (tc_simpleMPD,
|
||||||
dash_mpdparser_contentProtection_no_value_no_encoding);
|
dash_mpdparser_contentProtection_no_value_no_encoding);
|
||||||
|
tcase_add_test (tc_simpleMPD,
|
||||||
|
dash_mpdparser_period_adaptationSet_representationBase_contentProtection_with_content);
|
||||||
tcase_add_test (tc_simpleMPD,
|
tcase_add_test (tc_simpleMPD,
|
||||||
dash_mpdparser_period_adaptationSet_accessibility);
|
dash_mpdparser_period_adaptationSet_accessibility);
|
||||||
tcase_add_test (tc_simpleMPD, dash_mpdparser_period_adaptationSet_role);
|
tcase_add_test (tc_simpleMPD, dash_mpdparser_period_adaptationSet_role);
|
||||||
|
|
Loading…
Reference in a new issue