diff options
author | Florin Apostol <florin.apostol@oregan.net> | 2015-06-05 17:20:20 +0100 |
---|---|---|
committer | Thiago Santos <thiagoss@osg.samsung.com> | 2015-06-08 13:17:49 -0300 |
commit | 8b18be5bfb7544915cb55b031a7b77787f64e3a2 (patch) | |
tree | fc765e41aabbf08fec514a0d9c8a725bb39461ab | |
parent | 7b8d819d186156f35ec67c47b6d42cd72685d6c2 (diff) | |
download | gstreamer-plugins-bad-8b18be5bfb7544915cb55b031a7b77787f64e3a2.tar.gz |
tests: dashdemux: add unit tests for checking the parsing of MPD element
Create a dash test target and add unit tests that check the parsing of
attributes of the MPD element and the following child elements:
- baseURL
- program information
- location
- metrics
These tests check the compliance of parts of the MPD parser in the
dashdemux element against the DASH specification [1].
[1] http://standards.iso.org/ittf/PubliclyAvailableStandards/c065274_ISO_IEC_23009-1_2014_Electronic_inserts.zip
http://standards.iso.org/ittf/PubliclyAvailableStandards/c065274_ISO_IEC_23009-1_2014.zip
https://bugzilla.gnome.org/show_bug.cgi?id=750390
-rw-r--r-- | tests/check/Makefile.am | 11 | ||||
-rw-r--r-- | tests/check/elements/.gitignore | 1 | ||||
-rw-r--r-- | tests/check/elements/dash_mpd.c | 454 |
3 files changed, 466 insertions, 0 deletions
diff --git a/tests/check/Makefile.am b/tests/check/Makefile.am index 04e5d5df8..e51bb0360 100644 --- a/tests/check/Makefile.am +++ b/tests/check/Makefile.am @@ -40,6 +40,12 @@ else check_assrender = endif +if USE_DASH +check_dash = elements/dash_mpd +else +check_dash = +endif + if USE_FAAC check_faac = elements/faac else @@ -222,6 +228,7 @@ noinst_PROGRAMS = \ check_PROGRAMS = \ generic/states \ $(check_assrender) \ + $(check_dash) \ $(check_faac) \ $(check_faad) \ $(check_voaacenc) \ @@ -428,6 +435,10 @@ elements_mpg123audiodec_LDADD = \ elements_uvch264demux_CFLAGS = -DUVCH264DEMUX_DATADIR="$(srcdir)/elements/uvch264demux_data" \ $(AM_CFLAGS) +elements_dash_mpd_CFLAGS = $(AM_CFLAGS) $(LIBXML2_CFLAGS) +elements_dash_mpd_LDADD = $(LDADD) $(LIBXML2_LIBS) +elements_dash_mpd_SOURCES = elements/dash_mpd.c + pipelines_streamheader_CFLAGS = $(GIO_CFLAGS) $(AM_CFLAGS) pipelines_streamheader_LDADD = $(GIO_LIBS) $(LDADD) diff --git a/tests/check/elements/.gitignore b/tests/check/elements/.gitignore index 1c5d0a924..4fe8ea386 100644 --- a/tests/check/elements/.gitignore +++ b/tests/check/elements/.gitignore @@ -15,6 +15,7 @@ curlftpsink curlsftpsink curlhttpsink curlsmtpsink +dash_mpd dataurisrc faac faad diff --git a/tests/check/elements/dash_mpd.c b/tests/check/elements/dash_mpd.c new file mode 100644 index 000000000..a30baf4c0 --- /dev/null +++ b/tests/check/elements/dash_mpd.c @@ -0,0 +1,454 @@ +/* GStreamer unit test for MPEG-DASH + * + * Copyright (c) <2015> YouView TV Ltd + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include "../../ext/dash/gstmpdparser.c" +#undef GST_CAT_DEFAULT + +#include <gst/check/gstcheck.h> + +GST_DEBUG_CATEGORY (gst_dash_demux_debug); + +/* + * compute the number of milliseconds contained in a duration value specified by + * year, month, day, hour, minute, second, millisecond + * + * This function must use the same conversion algorithm implemented in + * gst_mpdparser_get_xml_prop_duration from gstmpdparser.c file. + */ +static gint64 +duration_to_ms (guint year, guint month, guint day, guint hour, guint minute, + guint second, guint millisecond) +{ + gint64 days = (gint64) year * 365 + month * 30 + day; + gint64 hours = days * 24 + hour; + gint64 minutes = hours * 60 + minute; + gint64 seconds = minutes * 60 + second; + gint64 ms = seconds * 1000 + millisecond; + return ms; +} + +/* + * Test to ensure a simple mpd file successfully parses. + * + */ +GST_START_TEST (dash_mpdparser_validsimplempd) +{ + const gchar *xml = + "<?xml version=\"1.0\"?>" + "<MPD xmlns=\"urn:mpeg:dash:schema:mpd:2011\"" + " profiles=\"urn:mpeg:dash:profile:isoff-main:2011\"> </MPD>"; + + gboolean ret; + GstMpdClient *mpdclient = gst_mpd_client_new (); + + ret = gst_mpd_parse (mpdclient, xml, strlen (xml)); + + assert_equals_int (ret, TRUE); + /* check that unset elements with default values are properly configured */ + assert_equals_int (mpdclient->mpd_node->type, GST_MPD_FILE_TYPE_STATIC); + + gst_mpd_client_free (mpdclient); +} + +GST_END_TEST; + +/* + * Test parsing the MPD attributes. + * + */ +GST_START_TEST (dash_mpdparser_mpd) +{ + GstDateTime *availabilityStartTime; + GstDateTime *availabilityEndTime; + const gchar *xml = + "<?xml version=\"1.0\"?>" + "<MPD xmlns=\"urn:mpeg:dash:schema:mpd:2011\"" + " profiles=\"urn:mpeg:dash:profile:isoff-main:2011\"" + " id=\"testId\"" + " type=\"static\"" + " availabilityStartTime=\"2015-03-24T1:10:50\"" + " availabilityEndTime=\"2015-03-24T1:10:50\"" + " mediaPresentationDuration=\"P0Y1M2DT12H10M20.5S\"" + " minimumUpdatePeriod=\"P0Y1M2DT12H10M20.5S\"" + " minBufferTime=\"P0Y1M2DT12H10M20.5S\"" + " timeShiftBufferDepth=\"P0Y1M2DT12H10M20.5S\"" + " suggestedPresentationDelay=\"P0Y1M2DT12H10M20.5S\"" + " maxSegmentDuration=\"P0Y1M2DT12H10M20.5S\"" + " maxSubsegmentDuration=\"P0Y1M2DT12H10M20.5S\"></MPD>"; + + gboolean ret; + GstMpdClient *mpdclient = gst_mpd_client_new (); + + ret = gst_mpd_parse (mpdclient, xml, strlen (xml)); + + assert_equals_int (ret, TRUE); + + assert_equals_string (mpdclient->mpd_node->id, "testId"); + + assert_equals_int (mpdclient->mpd_node->type, GST_MPD_FILE_TYPE_STATIC); + + availabilityStartTime = mpdclient->mpd_node->availabilityStartTime; + assert_equals_int (gst_date_time_get_year (availabilityStartTime), 2015); + assert_equals_int (gst_date_time_get_month (availabilityStartTime), 3); + assert_equals_int (gst_date_time_get_day (availabilityStartTime), 24); + assert_equals_int (gst_date_time_get_hour (availabilityStartTime), 1); + assert_equals_int (gst_date_time_get_minute (availabilityStartTime), 10); + assert_equals_int (gst_date_time_get_second (availabilityStartTime), 50); + + availabilityEndTime = mpdclient->mpd_node->availabilityEndTime; + assert_equals_int (gst_date_time_get_year (availabilityEndTime), 2015); + assert_equals_int (gst_date_time_get_month (availabilityEndTime), 3); + assert_equals_int (gst_date_time_get_day (availabilityEndTime), 24); + assert_equals_int (gst_date_time_get_hour (availabilityEndTime), 1); + assert_equals_int (gst_date_time_get_minute (availabilityEndTime), 10); + assert_equals_int (gst_date_time_get_second (availabilityEndTime), 50); + + assert_equals_int64 (mpdclient->mpd_node->mediaPresentationDuration, + duration_to_ms (0, 1, 2, 12, 10, 20, 500)); + + assert_equals_int64 (mpdclient->mpd_node->minimumUpdatePeriod, + duration_to_ms (0, 1, 2, 12, 10, 20, 500)); + + assert_equals_int64 (mpdclient->mpd_node->minBufferTime, + duration_to_ms (0, 1, 2, 12, 10, 20, 500)); + + assert_equals_int64 (mpdclient->mpd_node->timeShiftBufferDepth, + duration_to_ms (0, 1, 2, 12, 10, 20, 500)); + + assert_equals_int64 (mpdclient->mpd_node->suggestedPresentationDelay, + duration_to_ms (0, 1, 2, 12, 10, 20, 500)); + + assert_equals_int64 (mpdclient->mpd_node->maxSegmentDuration, + duration_to_ms (0, 1, 2, 12, 10, 20, 500)); + + assert_equals_int64 (mpdclient->mpd_node->maxSubsegmentDuration, + duration_to_ms (0, 1, 2, 12, 10, 20, 500)); + + gst_mpd_client_free (mpdclient); +} + +GST_END_TEST; + +/* + * Test parsing the ProgramInformation attributes + * + */ +GST_START_TEST (dash_mpdparser_program_information) +{ + GstProgramInformationNode *program; + const gchar *xml = + "<?xml version=\"1.0\"?>" + "<MPD xmlns=\"urn:mpeg:dash:schema:mpd:2011\"" + " profiles=\"urn:mpeg:dash:profile:isoff-main:2011\">" + "<ProgramInformation lang=\"en\"" + " moreInformationURL=\"TestMoreInformationUrl\">" + "<Title>TestTitle</Title>" + "<Source>TestSource</Source>" + "<Copyright>TestCopyright</Copyright> </ProgramInformation> </MPD>"; + + gboolean ret; + GstMpdClient *mpdclient = gst_mpd_client_new (); + + ret = gst_mpd_parse (mpdclient, xml, strlen (xml)); + + assert_equals_int (ret, TRUE); + program = + (GstProgramInformationNode *) mpdclient->mpd_node->ProgramInfo->data; + assert_equals_string (program->lang, "en"); + assert_equals_string (program->moreInformationURL, "TestMoreInformationUrl"); + assert_equals_string (program->Title, "TestTitle"); + assert_equals_string (program->Source, "TestSource"); + assert_equals_string (program->Copyright, "TestCopyright"); + + gst_mpd_client_free (mpdclient); +} + +GST_END_TEST; + +/* + * Test parsing the BaseURL attributes + * + */ +GST_START_TEST (dash_mpdparser_base_URL) +{ + GstBaseURL *baseURL; + const gchar *xml = + "<?xml version=\"1.0\"?>" + "<MPD xmlns=\"urn:mpeg:dash:schema:mpd:2011\"" + " profiles=\"urn:mpeg:dash:profile:isoff-main:2011\">" + "<BaseURL serviceLocation=\"TestServiceLocation\"" + " byteRange=\"TestByteRange\">TestBaseURL</BaseURL></MPD>"; + + gboolean ret; + GstMpdClient *mpdclient = gst_mpd_client_new (); + + ret = gst_mpd_parse (mpdclient, xml, strlen (xml)); + + assert_equals_int (ret, TRUE); + baseURL = (GstBaseURL *) mpdclient->mpd_node->BaseURLs->data; + assert_equals_string (baseURL->baseURL, "TestBaseURL"); + assert_equals_string (baseURL->serviceLocation, "TestServiceLocation"); + assert_equals_string (baseURL->byteRange, "TestByteRange"); + + gst_mpd_client_free (mpdclient); +} + +GST_END_TEST; + +/* + * Test parsing the location attributes + * + */ +GST_START_TEST (dash_mpdparser_location) +{ + const gchar *location; + const gchar *xml = + "<?xml version=\"1.0\"?>" + "<MPD xmlns=\"urn:mpeg:dash:schema:mpd:2011\"" + " profiles=\"urn:mpeg:dash:profile:isoff-main:2011\">" + "<Location>TestLocation</Location></MPD>"; + + gboolean ret; + GstMpdClient *mpdclient = gst_mpd_client_new (); + + ret = gst_mpd_parse (mpdclient, xml, strlen (xml)); + + assert_equals_int (ret, TRUE); + location = (gchar *) mpdclient->mpd_node->Locations->data; + assert_equals_string (location, "TestLocation"); + + gst_mpd_client_free (mpdclient); +} + +GST_END_TEST; + +/* + * Test parsing metrics attributes + * + */ +GST_START_TEST (dash_mpdparser_metrics) +{ + GstMetricsNode *metricsNode; + const gchar *xml = + "<?xml version=\"1.0\"?>" + "<MPD xmlns=\"urn:mpeg:dash:schema:mpd:2011\"" + " profiles=\"urn:mpeg:dash:profile:isoff-main:2011\">" + "<Metrics metrics=\"TestMetric\"></Metrics></MPD>"; + + gboolean ret; + GstMpdClient *mpdclient = gst_mpd_client_new (); + + ret = gst_mpd_parse (mpdclient, xml, strlen (xml)); + + assert_equals_int (ret, TRUE); + metricsNode = (GstMetricsNode *) mpdclient->mpd_node->Metrics->data; + assert_equals_string (metricsNode->metrics, "TestMetric"); + gst_mpd_client_free (mpdclient); +} + +GST_END_TEST; + +/* + * Test parsing metrics range attributes + * + */ +GST_START_TEST (dash_mpdparser_metrics_range) +{ + GstMetricsNode *metricsNode; + GstMetricsRangeNode *metricsRangeNode; + const gchar *xml = + "<?xml version=\"1.0\"?>" + "<MPD xmlns=\"urn:mpeg:dash:schema:mpd:2011\"" + " profiles=\"urn:mpeg:dash:profile:isoff-main:2011\">" + "<Metrics><Range starttime=\"P0Y1M2DT12H10M20.5S\"" + " duration=\"P0Y1M2DT12H10M20.1234567S\"></Range></Metrics></MPD>"; + + gboolean ret; + GstMpdClient *mpdclient = gst_mpd_client_new (); + + ret = gst_mpd_parse (mpdclient, xml, strlen (xml)); + + assert_equals_int (ret, TRUE); + metricsNode = (GstMetricsNode *) mpdclient->mpd_node->Metrics->data; + assert_equals_pointer (metricsNode->metrics, NULL); + metricsRangeNode = (GstMetricsRangeNode *) metricsNode->MetricsRanges->data; + assert_equals_int64 (metricsRangeNode->starttime, + duration_to_ms (0, 1, 2, 12, 10, 20, 500)); + assert_equals_int64 (metricsRangeNode->duration, + duration_to_ms (0, 1, 2, 12, 10, 20, 123)); + + gst_mpd_client_free (mpdclient); +} + +GST_END_TEST; + +/* + * Test parsing metrics reporting attributes + * + */ +GST_START_TEST (dash_mpdparser_metrics_reporting) +{ + GstMetricsNode *metricsNode; + const gchar *xml = + "<?xml version=\"1.0\"?>" + "<MPD xmlns=\"urn:mpeg:dash:schema:mpd:2011\"" + " profiles=\"urn:mpeg:dash:profile:isoff-main:2011\">" + "<Metrics><Reporting></Reporting></Metrics></MPD>"; + + gboolean ret; + GstMpdClient *mpdclient = gst_mpd_client_new (); + + ret = gst_mpd_parse (mpdclient, xml, strlen (xml)); + + assert_equals_int (ret, TRUE); + metricsNode = (GstMetricsNode *) mpdclient->mpd_node->Metrics->data; + assert_equals_pointer (metricsNode->metrics, NULL); + + gst_mpd_client_free (mpdclient); +} + +GST_END_TEST; + +/* + * Test parsing the type property: value "dynamic" + * + */ +GST_START_TEST (dash_mpdparser_type_dynamic) +{ + const gchar *xml = + "<?xml version=\"1.0\"?>" + "<MPD type=\"dynamic\" xmlns=\"urn:mpeg:dash:schema:mpd:2011\"" + " profiles=\"urn:mpeg:dash:profile:isoff-main:2011\"> </MPD>"; + + gboolean ret; + GstMpdClient *mpdclient = gst_mpd_client_new (); + + ret = gst_mpd_parse (mpdclient, xml, strlen (xml)); + + assert_equals_int (ret, TRUE); + assert_equals_int (mpdclient->mpd_node->type, GST_MPD_FILE_TYPE_DYNAMIC); + + gst_mpd_client_free (mpdclient); +} + +GST_END_TEST; + +/* + * Test parsing empty xml string + * + */ +GST_START_TEST (dash_mpdparser_missing_xml) +{ + const gchar *xml = ""; + + gboolean ret; + GstMpdClient *mpdclient = gst_mpd_client_new (); + + ret = gst_mpd_parse (mpdclient, xml, strlen (xml)); + + assert_equals_int (ret, FALSE); + + gst_mpd_client_free (mpdclient); +} + +GST_END_TEST; + +/* + * Test parsing an xml with no mpd tag + * + */ +GST_START_TEST (dash_mpdparser_missing_mpd) +{ + const gchar *xml = "<?xml version=\"1.0\"?>"; + + gboolean ret; + GstMpdClient *mpdclient = gst_mpd_client_new (); + + ret = gst_mpd_parse (mpdclient, xml, strlen (xml)); + + assert_equals_int (ret, FALSE); + + gst_mpd_client_free (mpdclient); +} + +GST_END_TEST; + +/* + * Test parsing an MPD with a wrong end tag + */ +GST_START_TEST (dash_mpdparser_no_end_tag) +{ + const gchar *xml = + "<?xml version=\"1.0\"?>" + "<MPD xmlns=\"urn:mpeg:dash:schema:mpd:2011\"" + " profiles=\"urn:mpeg:dash:profile:isoff-main:2011\"> </NPD>"; + + gboolean ret; + GstMpdClient *mpdclient = gst_mpd_client_new (); + + ret = gst_mpd_parse (mpdclient, xml, strlen (xml)); + + assert_equals_int (ret, FALSE); + + gst_mpd_client_free (mpdclient); +} + +GST_END_TEST; + +/* + * create a test suite containing all dash testcases + */ +static Suite * +dash_suite (void) +{ + Suite *s = suite_create ("dash"); + TCase *tc_simpleMPD = tcase_create ("simpleMPD"); + TCase *tc_negativeTests = tcase_create ("negativeTests"); + + GST_DEBUG_CATEGORY_INIT (gst_dash_demux_debug, "gst_dash_demux_debug", 0, + "mpeg dash tests"); + + /* test parsing the simplest possible mpd */ + tcase_add_test (tc_simpleMPD, dash_mpdparser_validsimplempd); + + /* tests parsing attributes from each element type */ + tcase_add_test (tc_simpleMPD, dash_mpdparser_mpd); + tcase_add_test (tc_simpleMPD, dash_mpdparser_program_information); + tcase_add_test (tc_simpleMPD, dash_mpdparser_base_URL); + tcase_add_test (tc_simpleMPD, dash_mpdparser_location); + tcase_add_test (tc_simpleMPD, dash_mpdparser_metrics); + tcase_add_test (tc_simpleMPD, dash_mpdparser_metrics_range); + tcase_add_test (tc_simpleMPD, dash_mpdparser_metrics_reporting); + + /* tests checking other possible values for attributes */ + tcase_add_test (tc_simpleMPD, dash_mpdparser_type_dynamic); + + /* tests checking the parsing of missing/incomplete attributes of xml */ + tcase_add_test (tc_negativeTests, dash_mpdparser_missing_xml); + tcase_add_test (tc_negativeTests, dash_mpdparser_missing_mpd); + tcase_add_test (tc_negativeTests, dash_mpdparser_no_end_tag); + + suite_add_tcase (s, tc_simpleMPD); + suite_add_tcase (s, tc_negativeTests); + + return s; +} + +GST_CHECK_MAIN (dash); |