1 /* GStreamer unit test for MPEG-DASH
2  *
3  * Copyright (c) <2015> YouView TV Ltd
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Library General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Library General Public License for more details.
14  *
15  * You should have received a copy of the GNU Library General Public
16  * License along with this library; if not, write to the
17  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
18  * Boston, MA 02110-1301, USA.
19  */
20 
21 #include "../../ext/dash/gstmpdparser.c"
22 #undef GST_CAT_DEFAULT
23 
24 #include <gst/check/gstcheck.h>
25 
26 GST_DEBUG_CATEGORY (gst_dash_demux_debug);
27 
28 /*
29  * compute the number of milliseconds contained in a duration value specified by
30  * year, month, day, hour, minute, second, millisecond
31  *
32  * This function must use the same conversion algorithm implemented in
33  * gst_mpdparser_get_xml_prop_duration from gstmpdparser.c file.
34  */
35 static guint64
duration_to_ms(guint year,guint month,guint day,guint hour,guint minute,guint second,guint millisecond)36 duration_to_ms (guint year, guint month, guint day, guint hour, guint minute,
37     guint second, guint millisecond)
38 {
39   guint64 days = (guint64) year * 365 + (guint64) month * 30 + day;
40   guint64 hours = days * 24 + hour;
41   guint64 minutes = hours * 60 + minute;
42   guint64 seconds = minutes * 60 + second;
43   guint64 ms = seconds * 1000 + millisecond;
44   return ms;
45 }
46 
47 static GstClockTime
duration_to_clocktime(guint year,guint month,guint day,guint hour,guint minute,guint second,guint millisecond)48 duration_to_clocktime (guint year, guint month, guint day, guint hour,
49     guint minute, guint second, guint millisecond)
50 {
51   return (GST_MSECOND * duration_to_ms (year, month, day, hour, minute, second,
52           millisecond));
53 }
54 
55 /*
56  * Test to ensure a simple mpd file successfully parses.
57  *
58  */
GST_START_TEST(dash_mpdparser_validsimplempd)59 GST_START_TEST (dash_mpdparser_validsimplempd)
60 {
61   const gchar *xml =
62       "<?xml version=\"1.0\"?>"
63       "<MPD xmlns=\"urn:mpeg:dash:schema:mpd:2011\""
64       "     profiles=\"urn:mpeg:dash:profile:isoff-main:2011\"> </MPD>";
65 
66   gboolean ret;
67   GstMpdClient *mpdclient = gst_mpd_client_new ();
68 
69   ret = gst_mpd_parse (mpdclient, xml, (gint) strlen (xml));
70   assert_equals_int (ret, TRUE);
71 
72   /* check that unset elements with default values are properly configured */
73   assert_equals_int (mpdclient->mpd_node->type, GST_MPD_FILE_TYPE_STATIC);
74 
75   gst_mpd_client_free (mpdclient);
76 }
77 
78 GST_END_TEST;
79 
80 /*
81  * Test parsing the MPD attributes.
82  *
83  */
GST_START_TEST(dash_mpdparser_mpd)84 GST_START_TEST (dash_mpdparser_mpd)
85 {
86   GstDateTime *availabilityStartTime;
87   GstDateTime *availabilityEndTime;
88   const gchar *xml =
89       "<?xml version=\"1.0\"?>"
90       "<MPD xmlns=\"urn:mpeg:dash:schema:mpd:2011\""
91       "     profiles=\"urn:mpeg:dash:profile:isoff-main:2011\""
92       "     schemaLocation=\"TestSchemaLocation\""
93       "     xmlns:xsi=\"TestNamespaceXSI\""
94       "     xmlns:ext=\"TestNamespaceEXT\""
95       "     id=\"testId\""
96       "     type=\"static\""
97       "     availabilityStartTime=\"2015-03-24T1:10:50\""
98       "     availabilityEndTime=\"2015-03-24T1:10:50.123456\""
99       "     mediaPresentationDuration=\"P0Y1M2DT12H10M20.5S\""
100       "     minimumUpdatePeriod=\"P0Y1M2DT12H10M20.5S\""
101       "     minBufferTime=\"P0Y1M2DT12H10M20.5S\""
102       "     timeShiftBufferDepth=\"P0Y1M2DT12H10M20.5S\""
103       "     suggestedPresentationDelay=\"P0Y1M2DT12H10M20.5S\""
104       "     maxSegmentDuration=\"P0Y1M2DT12H10M20.5S\""
105       "     maxSubsegmentDuration=\"P0Y1M2DT12H10M20.5S\"></MPD>";
106 
107   gboolean ret;
108   GstMpdClient *mpdclient = gst_mpd_client_new ();
109 
110   ret = gst_mpd_parse (mpdclient, xml, (gint) strlen (xml));
111   assert_equals_int (ret, TRUE);
112 
113   assert_equals_string (mpdclient->mpd_node->default_namespace,
114       "urn:mpeg:dash:schema:mpd:2011");
115   assert_equals_string (mpdclient->mpd_node->namespace_xsi, "TestNamespaceXSI");
116   assert_equals_string (mpdclient->mpd_node->namespace_ext, "TestNamespaceEXT");
117   assert_equals_string (mpdclient->mpd_node->schemaLocation,
118       "TestSchemaLocation");
119   assert_equals_string (mpdclient->mpd_node->id, "testId");
120 
121   assert_equals_int (mpdclient->mpd_node->type, GST_MPD_FILE_TYPE_STATIC);
122 
123   availabilityStartTime = mpdclient->mpd_node->availabilityStartTime;
124   assert_equals_int (gst_date_time_get_year (availabilityStartTime), 2015);
125   assert_equals_int (gst_date_time_get_month (availabilityStartTime), 3);
126   assert_equals_int (gst_date_time_get_day (availabilityStartTime), 24);
127   assert_equals_int (gst_date_time_get_hour (availabilityStartTime), 1);
128   assert_equals_int (gst_date_time_get_minute (availabilityStartTime), 10);
129   assert_equals_int (gst_date_time_get_second (availabilityStartTime), 50);
130   assert_equals_int (gst_date_time_get_microsecond (availabilityStartTime), 0);
131 
132   availabilityEndTime = mpdclient->mpd_node->availabilityEndTime;
133   assert_equals_int (gst_date_time_get_year (availabilityEndTime), 2015);
134   assert_equals_int (gst_date_time_get_month (availabilityEndTime), 3);
135   assert_equals_int (gst_date_time_get_day (availabilityEndTime), 24);
136   assert_equals_int (gst_date_time_get_hour (availabilityEndTime), 1);
137   assert_equals_int (gst_date_time_get_minute (availabilityEndTime), 10);
138   assert_equals_int (gst_date_time_get_second (availabilityEndTime), 50);
139   assert_equals_int (gst_date_time_get_microsecond (availabilityEndTime),
140       123456);
141 
142   assert_equals_uint64 (mpdclient->mpd_node->mediaPresentationDuration,
143       duration_to_ms (0, 1, 2, 12, 10, 20, 500));
144 
145   assert_equals_uint64 (mpdclient->mpd_node->minimumUpdatePeriod,
146       duration_to_ms (0, 1, 2, 12, 10, 20, 500));
147 
148   assert_equals_uint64 (mpdclient->mpd_node->minBufferTime,
149       duration_to_ms (0, 1, 2, 12, 10, 20, 500));
150 
151   assert_equals_uint64 (mpdclient->mpd_node->timeShiftBufferDepth,
152       duration_to_ms (0, 1, 2, 12, 10, 20, 500));
153 
154   assert_equals_uint64 (mpdclient->mpd_node->suggestedPresentationDelay,
155       duration_to_ms (0, 1, 2, 12, 10, 20, 500));
156 
157   assert_equals_uint64 (mpdclient->mpd_node->maxSegmentDuration,
158       duration_to_ms (0, 1, 2, 12, 10, 20, 500));
159 
160   assert_equals_uint64 (mpdclient->mpd_node->maxSubsegmentDuration,
161       duration_to_ms (0, 1, 2, 12, 10, 20, 500));
162 
163   gst_mpd_client_free (mpdclient);
164 }
165 
166 GST_END_TEST;
167 
168 /*
169  * Test parsing the ProgramInformation attributes
170  *
171  */
GST_START_TEST(dash_mpdparser_programInformation)172 GST_START_TEST (dash_mpdparser_programInformation)
173 {
174   GstProgramInformationNode *program;
175   const gchar *xml =
176       "<?xml version=\"1.0\"?>"
177       "<MPD xmlns=\"urn:mpeg:dash:schema:mpd:2011\""
178       "     profiles=\"urn:mpeg:dash:profile:isoff-main:2011\">"
179       "  <ProgramInformation lang=\"en\""
180       "                      moreInformationURL=\"TestMoreInformationUrl\">"
181       "    <Title>TestTitle</Title>"
182       "    <Source>TestSource</Source>"
183       "    <Copyright>TestCopyright</Copyright>"
184       "  </ProgramInformation> </MPD>";
185 
186   gboolean ret;
187   GstMpdClient *mpdclient = gst_mpd_client_new ();
188 
189   ret = gst_mpd_parse (mpdclient, xml, (gint) strlen (xml));
190   assert_equals_int (ret, TRUE);
191 
192   program =
193       (GstProgramInformationNode *) mpdclient->mpd_node->ProgramInfo->data;
194   assert_equals_string (program->lang, "en");
195   assert_equals_string (program->moreInformationURL, "TestMoreInformationUrl");
196   assert_equals_string (program->Title, "TestTitle");
197   assert_equals_string (program->Source, "TestSource");
198   assert_equals_string (program->Copyright, "TestCopyright");
199 
200   gst_mpd_client_free (mpdclient);
201 }
202 
203 GST_END_TEST;
204 
205 /*
206  * Test parsing the BaseURL attributes
207  *
208  */
GST_START_TEST(dash_mpdparser_baseURL)209 GST_START_TEST (dash_mpdparser_baseURL)
210 {
211   GstBaseURL *baseURL;
212   const gchar *xml =
213       "<?xml version=\"1.0\"?>"
214       "<MPD xmlns=\"urn:mpeg:dash:schema:mpd:2011\""
215       "     profiles=\"urn:mpeg:dash:profile:isoff-main:2011\">"
216       "  <BaseURL serviceLocation=\"TestServiceLocation\""
217       "     byteRange=\"TestByteRange\">TestBaseURL</BaseURL></MPD>";
218 
219   gboolean ret;
220   GstMpdClient *mpdclient = gst_mpd_client_new ();
221 
222   ret = gst_mpd_parse (mpdclient, xml, (gint) strlen (xml));
223   assert_equals_int (ret, TRUE);
224 
225   baseURL = (GstBaseURL *) mpdclient->mpd_node->BaseURLs->data;
226   assert_equals_string (baseURL->baseURL, "TestBaseURL");
227   assert_equals_string (baseURL->serviceLocation, "TestServiceLocation");
228   assert_equals_string (baseURL->byteRange, "TestByteRange");
229 
230   gst_mpd_client_free (mpdclient);
231 }
232 
233 GST_END_TEST;
234 
235 /*
236  * Test parsing the Location attributes
237  *
238  */
GST_START_TEST(dash_mpdparser_location)239 GST_START_TEST (dash_mpdparser_location)
240 {
241   const gchar *location;
242   const gchar *xml =
243       "<?xml version=\"1.0\"?>"
244       "<MPD xmlns=\"urn:mpeg:dash:schema:mpd:2011\""
245       "     profiles=\"urn:mpeg:dash:profile:isoff-main:2011\">"
246       "  <Location>TestLocation</Location></MPD>";
247 
248   gboolean ret;
249   GstMpdClient *mpdclient = gst_mpd_client_new ();
250 
251   ret = gst_mpd_parse (mpdclient, xml, (gint) strlen (xml));
252   assert_equals_int (ret, TRUE);
253 
254   location = (gchar *) mpdclient->mpd_node->Locations->data;
255   assert_equals_string (location, "TestLocation");
256 
257   gst_mpd_client_free (mpdclient);
258 }
259 
260 GST_END_TEST;
261 
262 /*
263  * Test parsing Metrics attributes
264  *
265  */
GST_START_TEST(dash_mpdparser_metrics)266 GST_START_TEST (dash_mpdparser_metrics)
267 {
268   GstMetricsNode *metricsNode;
269   const gchar *xml =
270       "<?xml version=\"1.0\"?>"
271       "<MPD xmlns=\"urn:mpeg:dash:schema:mpd:2011\""
272       "     profiles=\"urn:mpeg:dash:profile:isoff-main:2011\">"
273       "  <Metrics metrics=\"TestMetric\"></Metrics></MPD>";
274 
275   gboolean ret;
276   GstMpdClient *mpdclient = gst_mpd_client_new ();
277 
278   ret = gst_mpd_parse (mpdclient, xml, (gint) strlen (xml));
279   assert_equals_int (ret, TRUE);
280 
281   metricsNode = (GstMetricsNode *) mpdclient->mpd_node->Metrics->data;
282   assert_equals_string (metricsNode->metrics, "TestMetric");
283 
284   gst_mpd_client_free (mpdclient);
285 }
286 
287 GST_END_TEST;
288 
289 /*
290  * Test parsing Metrics Range attributes
291  *
292  */
GST_START_TEST(dash_mpdparser_metrics_range)293 GST_START_TEST (dash_mpdparser_metrics_range)
294 {
295   GstMetricsNode *metricsNode;
296   GstMetricsRangeNode *metricsRangeNode;
297   const gchar *xml =
298       "<?xml version=\"1.0\"?>"
299       "<MPD xmlns=\"urn:mpeg:dash:schema:mpd:2011\""
300       "     profiles=\"urn:mpeg:dash:profile:isoff-main:2011\">"
301       "  <Metrics>"
302       "    <Range starttime=\"P0Y1M2DT12H10M20.5S\""
303       "           duration=\"P0Y1M2DT12H10M20.1234567S\">"
304       "    </Range></Metrics></MPD>";
305 
306   gboolean ret;
307   GstMpdClient *mpdclient = gst_mpd_client_new ();
308 
309   ret = gst_mpd_parse (mpdclient, xml, (gint) strlen (xml));
310   assert_equals_int (ret, TRUE);
311 
312   metricsNode = (GstMetricsNode *) mpdclient->mpd_node->Metrics->data;
313   assert_equals_pointer (metricsNode->metrics, NULL);
314   metricsRangeNode = (GstMetricsRangeNode *) metricsNode->MetricsRanges->data;
315   assert_equals_uint64 (metricsRangeNode->starttime,
316       duration_to_ms (0, 1, 2, 12, 10, 20, 500));
317   assert_equals_uint64 (metricsRangeNode->duration,
318       duration_to_ms (0, 1, 2, 12, 10, 20, 123));
319 
320   gst_mpd_client_free (mpdclient);
321 }
322 
323 GST_END_TEST;
324 
325 /*
326  * Test parsing Metrics Reporting attributes
327  *
328  */
GST_START_TEST(dash_mpdparser_metrics_reporting)329 GST_START_TEST (dash_mpdparser_metrics_reporting)
330 {
331   GstMetricsNode *metricsNode;
332   const gchar *xml =
333       "<?xml version=\"1.0\"?>"
334       "<MPD xmlns=\"urn:mpeg:dash:schema:mpd:2011\""
335       "     profiles=\"urn:mpeg:dash:profile:isoff-main:2011\">"
336       "  <Metrics><Reporting></Reporting></Metrics></MPD>";
337 
338   gboolean ret;
339   GstMpdClient *mpdclient = gst_mpd_client_new ();
340 
341   ret = gst_mpd_parse (mpdclient, xml, (gint) strlen (xml));
342   assert_equals_int (ret, TRUE);
343 
344   metricsNode = (GstMetricsNode *) mpdclient->mpd_node->Metrics->data;
345   assert_equals_pointer (metricsNode->metrics, NULL);
346 
347   gst_mpd_client_free (mpdclient);
348 }
349 
350 GST_END_TEST;
351 
352 /*
353  * Test parsing Period attributes
354  *
355  */
GST_START_TEST(dash_mpdparser_period)356 GST_START_TEST (dash_mpdparser_period)
357 {
358   GstPeriodNode *periodNode;
359   const gchar *xml =
360       "<?xml version=\"1.0\"?>"
361       "<MPD xmlns=\"urn:mpeg:dash:schema:mpd:2011\""
362       "     profiles=\"urn:mpeg:dash:profile:isoff-main:2011\">"
363       "  <Period id=\"TestId\""
364       "          start=\"P0Y1M2DT12H10M20.1234567S\""
365       "          duration=\"P0Y1M2DT12H10M20.7654321S\""
366       "          bitstreamSwitching=\"true\"></Period></MPD>";
367 
368   gboolean ret;
369   GstMpdClient *mpdclient = gst_mpd_client_new ();
370 
371   ret = gst_mpd_parse (mpdclient, xml, (gint) strlen (xml));
372   assert_equals_int (ret, TRUE);
373 
374   periodNode = (GstPeriodNode *) mpdclient->mpd_node->Periods->data;
375   assert_equals_string (periodNode->id, "TestId");
376   assert_equals_uint64 (periodNode->start,
377       duration_to_ms (0, 1, 2, 12, 10, 20, 123));
378   assert_equals_uint64 (periodNode->duration,
379       duration_to_ms (0, 1, 2, 12, 10, 20, 765));
380   assert_equals_int (periodNode->bitstreamSwitching, 1);
381 
382   gst_mpd_client_free (mpdclient);
383 }
384 
385 GST_END_TEST;
386 
387 /*
388  * Test parsing Period baseURL attributes
389  *
390  */
GST_START_TEST(dash_mpdparser_period_baseURL)391 GST_START_TEST (dash_mpdparser_period_baseURL)
392 {
393   GstPeriodNode *periodNode;
394   GstBaseURL *baseURL;
395   const gchar *xml =
396       "<?xml version=\"1.0\"?>"
397       "<MPD xmlns=\"urn:mpeg:dash:schema:mpd:2011\""
398       "     profiles=\"urn:mpeg:dash:profile:isoff-main:2011\">"
399       "  <Period>"
400       "    <BaseURL serviceLocation=\"TestServiceLocation\""
401       "             byteRange=\"TestByteRange\">TestBaseURL</BaseURL>"
402       "  </Period></MPD>";
403 
404   gboolean ret;
405   GstMpdClient *mpdclient = gst_mpd_client_new ();
406 
407   ret = gst_mpd_parse (mpdclient, xml, (gint) strlen (xml));
408   assert_equals_int (ret, TRUE);
409 
410   periodNode = (GstPeriodNode *) mpdclient->mpd_node->Periods->data;
411   baseURL = (GstBaseURL *) periodNode->BaseURLs->data;
412   assert_equals_string (baseURL->baseURL, "TestBaseURL");
413   assert_equals_string (baseURL->serviceLocation, "TestServiceLocation");
414   assert_equals_string (baseURL->byteRange, "TestByteRange");
415 
416   gst_mpd_client_free (mpdclient);
417 }
418 
419 GST_END_TEST;
420 
421 /*
422  * Test parsing Period SegmentBase attributes
423  *
424  */
GST_START_TEST(dash_mpdparser_period_segmentBase)425 GST_START_TEST (dash_mpdparser_period_segmentBase)
426 {
427   GstPeriodNode *periodNode;
428   GstSegmentBaseType *segmentBase;
429   const gchar *xml =
430       "<?xml version=\"1.0\"?>"
431       "<MPD xmlns=\"urn:mpeg:dash:schema:mpd:2011\""
432       "     profiles=\"urn:mpeg:dash:profile:isoff-main:2011\">"
433       "  <Period>"
434       "    <SegmentBase timescale=\"123456\""
435       "                 presentationTimeOffset=\"123456789\""
436       "                 indexRange=\"100-200\""
437       "                 indexRangeExact=\"true\">"
438       "    </SegmentBase></Period></MPD>";
439 
440   gboolean ret;
441   GstMpdClient *mpdclient = gst_mpd_client_new ();
442 
443   ret = gst_mpd_parse (mpdclient, xml, (gint) strlen (xml));
444   assert_equals_int (ret, TRUE);
445 
446   periodNode = (GstPeriodNode *) mpdclient->mpd_node->Periods->data;
447   segmentBase = periodNode->SegmentBase;
448   assert_equals_uint64 (segmentBase->timescale, 123456);
449   assert_equals_uint64 (segmentBase->presentationTimeOffset, 123456789);
450   assert_equals_uint64 (segmentBase->indexRange->first_byte_pos, 100);
451   assert_equals_uint64 (segmentBase->indexRange->last_byte_pos, 200);
452   assert_equals_int (segmentBase->indexRangeExact, 1);
453 
454   gst_mpd_client_free (mpdclient);
455 }
456 
457 GST_END_TEST;
458 
459 /*
460  * Test parsing Period SegmentBase Initialization attributes
461  *
462  */
GST_START_TEST(dash_mpdparser_period_segmentBase_initialization)463 GST_START_TEST (dash_mpdparser_period_segmentBase_initialization)
464 {
465   GstPeriodNode *periodNode;
466   GstSegmentBaseType *segmentBase;
467   GstURLType *initialization;
468   const gchar *xml =
469       "<?xml version=\"1.0\"?>"
470       "<MPD xmlns=\"urn:mpeg:dash:schema:mpd:2011\""
471       "     profiles=\"urn:mpeg:dash:profile:isoff-main:2011\">"
472       "  <Period>"
473       "    <SegmentBase>"
474       "      <Initialisation sourceURL=\"TestSourceURL\""
475       "                      range=\"100-200\">"
476       "      </Initialisation></SegmentBase></Period></MPD>";
477 
478   gboolean ret;
479   GstMpdClient *mpdclient = gst_mpd_client_new ();
480 
481   ret = gst_mpd_parse (mpdclient, xml, (gint) strlen (xml));
482   assert_equals_int (ret, TRUE);
483 
484   periodNode = (GstPeriodNode *) mpdclient->mpd_node->Periods->data;
485   segmentBase = periodNode->SegmentBase;
486   initialization = segmentBase->Initialization;
487   assert_equals_string (initialization->sourceURL, "TestSourceURL");
488   assert_equals_uint64 (initialization->range->first_byte_pos, 100);
489   assert_equals_uint64 (initialization->range->last_byte_pos, 200);
490 
491   gst_mpd_client_free (mpdclient);
492 }
493 
494 GST_END_TEST;
495 
496 /*
497  * Test parsing Period SegmentBase RepresentationIndex attributes
498  *
499  */
GST_START_TEST(dash_mpdparser_period_segmentBase_representationIndex)500 GST_START_TEST (dash_mpdparser_period_segmentBase_representationIndex)
501 {
502   GstPeriodNode *periodNode;
503   GstSegmentBaseType *segmentBase;
504   GstURLType *representationIndex;
505   const gchar *xml =
506       "<?xml version=\"1.0\"?>"
507       "<MPD xmlns=\"urn:mpeg:dash:schema:mpd:2011\""
508       "     profiles=\"urn:mpeg:dash:profile:isoff-main:2011\">"
509       "  <Period>"
510       "    <SegmentBase>"
511       "      <RepresentationIndex sourceURL=\"TestSourceURL\""
512       "                           range=\"100-200\">"
513       "      </RepresentationIndex></SegmentBase></Period></MPD>";
514 
515   gboolean ret;
516   GstMpdClient *mpdclient = gst_mpd_client_new ();
517 
518   ret = gst_mpd_parse (mpdclient, xml, (gint) strlen (xml));
519   assert_equals_int (ret, TRUE);
520 
521   periodNode = (GstPeriodNode *) mpdclient->mpd_node->Periods->data;
522   segmentBase = periodNode->SegmentBase;
523   representationIndex = segmentBase->RepresentationIndex;
524   assert_equals_string (representationIndex->sourceURL, "TestSourceURL");
525   assert_equals_uint64 (representationIndex->range->first_byte_pos, 100);
526   assert_equals_uint64 (representationIndex->range->last_byte_pos, 200);
527 
528   gst_mpd_client_free (mpdclient);
529 }
530 
531 GST_END_TEST;
532 
533 /*
534  * Test parsing Period SegmentList attributes
535  *
536  */
GST_START_TEST(dash_mpdparser_period_segmentList)537 GST_START_TEST (dash_mpdparser_period_segmentList)
538 {
539   GstPeriodNode *periodNode;
540   GstSegmentListNode *segmentList;
541   const gchar *xml =
542       "<?xml version=\"1.0\"?>"
543       "<MPD xmlns=\"urn:mpeg:dash:schema:mpd:2011\""
544       "     profiles=\"urn:mpeg:dash:profile:isoff-main:2011\">"
545       "  <Period><SegmentList duration=\"1\"></SegmentList></Period></MPD>";
546 
547   gboolean ret;
548   GstMpdClient *mpdclient = gst_mpd_client_new ();
549 
550   ret = gst_mpd_parse (mpdclient, xml, (gint) strlen (xml));
551   assert_equals_int (ret, TRUE);
552 
553   periodNode = (GstPeriodNode *) mpdclient->mpd_node->Periods->data;
554   segmentList = periodNode->SegmentList;
555   fail_if (segmentList == NULL);
556 
557   gst_mpd_client_free (mpdclient);
558 }
559 
560 GST_END_TEST;
561 
562 /*
563  * Test parsing Period SegmentList MultipleSegmentBaseType attributes
564  *
565  */
GST_START_TEST(dash_mpdparser_period_segmentList_multipleSegmentBaseType)566 GST_START_TEST (dash_mpdparser_period_segmentList_multipleSegmentBaseType)
567 {
568   GstPeriodNode *periodNode;
569   GstSegmentListNode *segmentList;
570   GstMultSegmentBaseType *multSegBaseType;
571   const gchar *xml =
572       "<?xml version=\"1.0\"?>"
573       "<MPD xmlns=\"urn:mpeg:dash:schema:mpd:2011\""
574       "     profiles=\"urn:mpeg:dash:profile:isoff-main:2011\">"
575       "  <Period>"
576       "    <SegmentList duration=\"10\""
577       "                 startNumber=\"11\">"
578       "    </SegmentList></Period></MPD>";
579 
580   gboolean ret;
581   GstMpdClient *mpdclient = gst_mpd_client_new ();
582 
583   ret = gst_mpd_parse (mpdclient, xml, (gint) strlen (xml));
584   assert_equals_int (ret, TRUE);
585 
586   periodNode = (GstPeriodNode *) mpdclient->mpd_node->Periods->data;
587   segmentList = periodNode->SegmentList;
588   multSegBaseType = segmentList->MultSegBaseType;
589   assert_equals_uint64 (multSegBaseType->duration, 10);
590   assert_equals_uint64 (multSegBaseType->startNumber, 11);
591 
592   gst_mpd_client_free (mpdclient);
593 }
594 
595 GST_END_TEST;
596 
597 /*
598  * Test parsing Period SegmentList MultipleSegmentBaseType SegmentBaseType
599  * attributes
600  */
GST_START_TEST(dash_mpdparser_period_segmentList_multipleSegmentBaseType_segmentBaseType)601 GST_START_TEST
602     (dash_mpdparser_period_segmentList_multipleSegmentBaseType_segmentBaseType)
603 {
604   GstPeriodNode *periodNode;
605   GstSegmentListNode *segmentList;
606   GstMultSegmentBaseType *multSegBaseType;
607   GstSegmentBaseType *segBaseType;
608   const gchar *xml =
609       "<?xml version=\"1.0\"?>"
610       "<MPD xmlns=\"urn:mpeg:dash:schema:mpd:2011\""
611       "     profiles=\"urn:mpeg:dash:profile:isoff-main:2011\">"
612       "  <Period>"
613       "    <SegmentList timescale=\"10\""
614       "                 duration=\"1\""
615       "                 presentationTimeOffset=\"11\""
616       "                 indexRange=\"20-21\""
617       "                 indexRangeExact=\"false\">"
618       "    </SegmentList></Period></MPD>";
619 
620   gboolean ret;
621   GstMpdClient *mpdclient = gst_mpd_client_new ();
622 
623   ret = gst_mpd_parse (mpdclient, xml, (gint) strlen (xml));
624   assert_equals_int (ret, TRUE);
625 
626   periodNode = (GstPeriodNode *) mpdclient->mpd_node->Periods->data;
627   segmentList = periodNode->SegmentList;
628   multSegBaseType = segmentList->MultSegBaseType;
629   segBaseType = multSegBaseType->SegBaseType;
630   assert_equals_uint64 (segBaseType->timescale, 10);
631   assert_equals_uint64 (segBaseType->presentationTimeOffset, 11);
632   assert_equals_uint64 (segBaseType->indexRange->first_byte_pos, 20);
633   assert_equals_uint64 (segBaseType->indexRange->last_byte_pos, 21);
634   assert_equals_int (segBaseType->indexRangeExact, FALSE);
635 
636   gst_mpd_client_free (mpdclient);
637 }
638 
639 GST_END_TEST;
640 
641 /*
642  * Test parsing Period SegmentList MultipleSegmentBaseType SegmentTimeline
643  * attributes
644  */
GST_START_TEST(dash_mpdparser_period_segmentList_multipleSegmentBaseType_segmentTimeline)645 GST_START_TEST
646     (dash_mpdparser_period_segmentList_multipleSegmentBaseType_segmentTimeline)
647 {
648   GstPeriodNode *periodNode;
649   GstSegmentListNode *segmentList;
650   GstMultSegmentBaseType *multSegBaseType;
651   GstSegmentTimelineNode *segmentTimeline;
652   const gchar *xml =
653       "<?xml version=\"1.0\"?>"
654       "<MPD xmlns=\"urn:mpeg:dash:schema:mpd:2011\""
655       "     profiles=\"urn:mpeg:dash:profile:isoff-main:2011\">"
656       "  <Period>"
657       "    <SegmentList>"
658       "      <SegmentTimeline>"
659       "      </SegmentTimeline></SegmentList></Period></MPD>";
660 
661   gboolean ret;
662   GstMpdClient *mpdclient = gst_mpd_client_new ();
663 
664   ret = gst_mpd_parse (mpdclient, xml, (gint) strlen (xml));
665   assert_equals_int (ret, TRUE);
666 
667   periodNode = (GstPeriodNode *) mpdclient->mpd_node->Periods->data;
668   segmentList = periodNode->SegmentList;
669   multSegBaseType = segmentList->MultSegBaseType;
670   segmentTimeline = multSegBaseType->SegmentTimeline;
671   fail_if (segmentTimeline == NULL);
672 
673   gst_mpd_client_free (mpdclient);
674 }
675 
676 GST_END_TEST;
677 
678 /*
679  * Test parsing Period SegmentList MultipleSegmentBaseType SegmentTimeline S
680  * attributes
681  */
GST_START_TEST(dash_mpdparser_period_segmentList_multipleSegmentBaseType_segmentTimeline_s)682 GST_START_TEST
683     (dash_mpdparser_period_segmentList_multipleSegmentBaseType_segmentTimeline_s)
684 {
685   GstPeriodNode *periodNode;
686   GstSegmentListNode *segmentList;
687   GstMultSegmentBaseType *multSegBaseType;
688   GstSegmentTimelineNode *segmentTimeline;
689   GstSNode *sNode;
690   const gchar *xml =
691       "<?xml version=\"1.0\"?>"
692       "<MPD xmlns=\"urn:mpeg:dash:schema:mpd:2011\""
693       "     profiles=\"urn:mpeg:dash:profile:isoff-main:2011\">"
694       "  <Period>"
695       "    <SegmentList>"
696       "      <SegmentTimeline>"
697       "        <S t=\"1\" d=\"2\" r=\"3\">"
698       "        </S></SegmentTimeline></SegmentList></Period></MPD>";
699 
700   gboolean ret;
701   GstMpdClient *mpdclient = gst_mpd_client_new ();
702 
703   ret = gst_mpd_parse (mpdclient, xml, (gint) strlen (xml));
704   assert_equals_int (ret, TRUE);
705 
706   periodNode = (GstPeriodNode *) mpdclient->mpd_node->Periods->data;
707   segmentList = periodNode->SegmentList;
708   multSegBaseType = segmentList->MultSegBaseType;
709   segmentTimeline = multSegBaseType->SegmentTimeline;
710   sNode = (GstSNode *) g_queue_peek_head (&segmentTimeline->S);
711   assert_equals_uint64 (sNode->t, 1);
712   assert_equals_uint64 (sNode->d, 2);
713   assert_equals_uint64 (sNode->r, 3);
714 
715   gst_mpd_client_free (mpdclient);
716 }
717 
718 GST_END_TEST;
719 
720 /*
721  * Test parsing Period SegmentList MultipleSegmentBaseType BitstreamSwitching
722  * attributes
723  */
GST_START_TEST(dash_mpdparser_period_segmentList_multipleSegmentBaseType_bitstreamSwitching)724 GST_START_TEST
725     (dash_mpdparser_period_segmentList_multipleSegmentBaseType_bitstreamSwitching)
726 {
727   GstPeriodNode *periodNode;
728   GstSegmentListNode *segmentList;
729   GstMultSegmentBaseType *multSegBaseType;
730   GstURLType *bitstreamSwitching;
731   const gchar *xml =
732       "<?xml version=\"1.0\"?>"
733       "<MPD xmlns=\"urn:mpeg:dash:schema:mpd:2011\""
734       "     profiles=\"urn:mpeg:dash:profile:isoff-main:2011\">"
735       "  <Period>"
736       "    <SegmentList duration=\"0\">"
737       "      <BitstreamSwitching sourceURL=\"TestSourceURL\""
738       "                          range=\"100-200\">"
739       "      </BitstreamSwitching></SegmentList></Period></MPD>";
740 
741   gboolean ret;
742   GstMpdClient *mpdclient = gst_mpd_client_new ();
743 
744   ret = gst_mpd_parse (mpdclient, xml, (gint) strlen (xml));
745   assert_equals_int (ret, TRUE);
746 
747   periodNode = (GstPeriodNode *) mpdclient->mpd_node->Periods->data;
748   segmentList = periodNode->SegmentList;
749   multSegBaseType = segmentList->MultSegBaseType;
750   bitstreamSwitching = multSegBaseType->BitstreamSwitching;
751   assert_equals_string (bitstreamSwitching->sourceURL, "TestSourceURL");
752   assert_equals_uint64 (bitstreamSwitching->range->first_byte_pos, 100);
753   assert_equals_uint64 (bitstreamSwitching->range->last_byte_pos, 200);
754 
755   gst_mpd_client_free (mpdclient);
756 }
757 
758 GST_END_TEST;
759 
760 /*
761  * Test parsing Period SegmentList SegmentURL attributes
762  *
763  */
GST_START_TEST(dash_mpdparser_period_segmentList_segmentURL)764 GST_START_TEST (dash_mpdparser_period_segmentList_segmentURL)
765 {
766   GstPeriodNode *periodNode;
767   GstSegmentListNode *segmentList;
768   GstSegmentURLNode *segmentURL;
769   const gchar *xml =
770       "<?xml version=\"1.0\"?>"
771       "<MPD xmlns=\"urn:mpeg:dash:schema:mpd:2011\""
772       "     profiles=\"urn:mpeg:dash:profile:isoff-main:2011\">"
773       "  <Period>"
774       "    <SegmentList duration=\"1\">"
775       "      <SegmentURL media=\"TestMedia\""
776       "                  mediaRange=\"100-200\""
777       "                  index=\"TestIndex\""
778       "                  indexRange=\"300-400\">"
779       "      </SegmentURL></SegmentList></Period></MPD>";
780 
781   gboolean ret;
782   GstMpdClient *mpdclient = gst_mpd_client_new ();
783 
784   ret = gst_mpd_parse (mpdclient, xml, (gint) strlen (xml));
785   assert_equals_int (ret, TRUE);
786 
787   periodNode = (GstPeriodNode *) mpdclient->mpd_node->Periods->data;
788   segmentList = periodNode->SegmentList;
789   segmentURL = (GstSegmentURLNode *) segmentList->SegmentURL->data;
790   assert_equals_string (segmentURL->media, "TestMedia");
791   assert_equals_uint64 (segmentURL->mediaRange->first_byte_pos, 100);
792   assert_equals_uint64 (segmentURL->mediaRange->last_byte_pos, 200);
793   assert_equals_string (segmentURL->index, "TestIndex");
794   assert_equals_uint64 (segmentURL->indexRange->first_byte_pos, 300);
795   assert_equals_uint64 (segmentURL->indexRange->last_byte_pos, 400);
796 
797   gst_mpd_client_free (mpdclient);
798 }
799 
800 GST_END_TEST;
801 
802 /*
803  * Test parsing Period SegmentTemplate attributes
804  *
805  */
GST_START_TEST(dash_mpdparser_period_segmentTemplate)806 GST_START_TEST (dash_mpdparser_period_segmentTemplate)
807 {
808   GstPeriodNode *periodNode;
809   GstSegmentTemplateNode *segmentTemplate;
810   const gchar *xml =
811       "<?xml version=\"1.0\"?>"
812       "<MPD xmlns=\"urn:mpeg:dash:schema:mpd:2011\""
813       "     profiles=\"urn:mpeg:dash:profile:isoff-main:2011\">"
814       "  <Period>"
815       "    <SegmentTemplate media=\"TestMedia\""
816       "                     duration=\"0\""
817       "                     index=\"TestIndex\""
818       "                     initialization=\"TestInitialization\""
819       "                     bitstreamSwitching=\"TestBitstreamSwitching\">"
820       "    </SegmentTemplate></Period></MPD>";
821 
822   gboolean ret;
823   GstMpdClient *mpdclient = gst_mpd_client_new ();
824 
825   ret = gst_mpd_parse (mpdclient, xml, (gint) strlen (xml));
826   assert_equals_int (ret, TRUE);
827 
828   periodNode = (GstPeriodNode *) mpdclient->mpd_node->Periods->data;
829   segmentTemplate = periodNode->SegmentTemplate;
830   assert_equals_string (segmentTemplate->media, "TestMedia");
831   assert_equals_string (segmentTemplate->index, "TestIndex");
832   assert_equals_string (segmentTemplate->initialization, "TestInitialization");
833   assert_equals_string (segmentTemplate->bitstreamSwitching,
834       "TestBitstreamSwitching");
835 
836   gst_mpd_client_free (mpdclient);
837 }
838 
839 GST_END_TEST;
840 
841 /*
842  * Test parsing Period SegmentTemplate MultipleSegmentBaseType attributes
843  *
844  */
GST_START_TEST(dash_mpdparser_period_segmentTemplate_multipleSegmentBaseType)845 GST_START_TEST (dash_mpdparser_period_segmentTemplate_multipleSegmentBaseType)
846 {
847   GstPeriodNode *periodNode;
848   GstSegmentTemplateNode *segmentTemplate;
849   GstMultSegmentBaseType *multSegBaseType;
850   const gchar *xml =
851       "<?xml version=\"1.0\"?>"
852       "<MPD xmlns=\"urn:mpeg:dash:schema:mpd:2011\""
853       "     profiles=\"urn:mpeg:dash:profile:isoff-main:2011\">"
854       "  <Period>"
855       "    <SegmentTemplate duration=\"10\""
856       "                     startNumber=\"11\">"
857       "    </SegmentTemplate></Period></MPD>";
858 
859   gboolean ret;
860   GstMpdClient *mpdclient = gst_mpd_client_new ();
861 
862   ret = gst_mpd_parse (mpdclient, xml, (gint) strlen (xml));
863   assert_equals_int (ret, TRUE);
864 
865   periodNode = (GstPeriodNode *) mpdclient->mpd_node->Periods->data;
866   segmentTemplate = periodNode->SegmentTemplate;
867   multSegBaseType = segmentTemplate->MultSegBaseType;
868   assert_equals_uint64 (multSegBaseType->duration, 10);
869   assert_equals_uint64 (multSegBaseType->startNumber, 11);
870 
871   gst_mpd_client_free (mpdclient);
872 }
873 
874 GST_END_TEST;
875 
876 /*
877  * Test parsing Period SegmentTemplate MultipleSegmentBaseType SegmentBaseType
878  * attributes
879  */
GST_START_TEST(dash_mpdparser_period_segmentTemplate_multipleSegmentBaseType_segmentBaseType)880 GST_START_TEST
881     (dash_mpdparser_period_segmentTemplate_multipleSegmentBaseType_segmentBaseType)
882 {
883   GstPeriodNode *periodNode;
884   GstSegmentTemplateNode *segmentTemplate;
885   GstMultSegmentBaseType *multSegBaseType;
886   GstSegmentBaseType *segBaseType;
887   const gchar *xml =
888       "<?xml version=\"1.0\"?>"
889       "<MPD xmlns=\"urn:mpeg:dash:schema:mpd:2011\""
890       "     profiles=\"urn:mpeg:dash:profile:isoff-main:2011\">"
891       "  <Period>"
892       "    <SegmentTemplate timescale=\"123456\""
893       "                     duration=\"1\""
894       "                     presentationTimeOffset=\"123456789\""
895       "                     indexRange=\"100-200\""
896       "                     indexRangeExact=\"true\">"
897       "    </SegmentTemplate></Period></MPD>";
898 
899   gboolean ret;
900   GstMpdClient *mpdclient = gst_mpd_client_new ();
901 
902   ret = gst_mpd_parse (mpdclient, xml, (gint) strlen (xml));
903   assert_equals_int (ret, TRUE);
904 
905   periodNode = (GstPeriodNode *) mpdclient->mpd_node->Periods->data;
906   segmentTemplate = periodNode->SegmentTemplate;
907   multSegBaseType = segmentTemplate->MultSegBaseType;
908   segBaseType = multSegBaseType->SegBaseType;
909   assert_equals_uint64 (segBaseType->timescale, 123456);
910   assert_equals_uint64 (segBaseType->presentationTimeOffset, 123456789);
911   assert_equals_uint64 (segBaseType->indexRange->first_byte_pos, 100);
912   assert_equals_uint64 (segBaseType->indexRange->last_byte_pos, 200);
913   assert_equals_int (segBaseType->indexRangeExact, TRUE);
914 
915   gst_mpd_client_free (mpdclient);
916 }
917 
918 GST_END_TEST;
919 
920 /*
921  * Test parsing Period SegmentTemplate MultipleSegmentBaseType SegmentTimeline
922  * attributes
923  */
GST_START_TEST(dash_mpdparser_period_segmentTemplate_multipleSegmentBaseType_segmentTimeline)924 GST_START_TEST
925     (dash_mpdparser_period_segmentTemplate_multipleSegmentBaseType_segmentTimeline)
926 {
927   GstPeriodNode *periodNode;
928   GstSegmentTemplateNode *segmentTemplate;
929   GstMultSegmentBaseType *multSegBaseType;
930   GstSegmentTimelineNode *segmentTimeline;
931   const gchar *xml =
932       "<?xml version=\"1.0\"?>"
933       "<MPD xmlns=\"urn:mpeg:dash:schema:mpd:2011\""
934       "     profiles=\"urn:mpeg:dash:profile:isoff-main:2011\">"
935       "  <Period>"
936       "    <SegmentTemplate>"
937       "      <SegmentTimeline>"
938       "      </SegmentTimeline></SegmentTemplate></Period></MPD>";
939 
940   gboolean ret;
941   GstMpdClient *mpdclient = gst_mpd_client_new ();
942 
943   ret = gst_mpd_parse (mpdclient, xml, (gint) strlen (xml));
944   assert_equals_int (ret, TRUE);
945 
946   periodNode = (GstPeriodNode *) mpdclient->mpd_node->Periods->data;
947   segmentTemplate = periodNode->SegmentTemplate;
948   multSegBaseType = segmentTemplate->MultSegBaseType;
949   segmentTimeline = (GstSegmentTimelineNode *) multSegBaseType->SegmentTimeline;
950   fail_if (segmentTimeline == NULL);
951 
952   gst_mpd_client_free (mpdclient);
953 }
954 
955 GST_END_TEST;
956 
957 /*
958  * Test parsing Period SegmentTemplate MultipleSegmentBaseType SegmentTimeline
959  * S attributes
960  */
GST_START_TEST(dash_mpdparser_period_segmentTemplate_multipleSegmentBaseType_segmentTimeline_s)961 GST_START_TEST
962     (dash_mpdparser_period_segmentTemplate_multipleSegmentBaseType_segmentTimeline_s)
963 {
964   GstPeriodNode *periodNode;
965   GstSegmentTemplateNode *segmentTemplate;
966   GstMultSegmentBaseType *multSegBaseType;
967   GstSegmentTimelineNode *segmentTimeline;
968   GstSNode *sNode;
969   const gchar *xml =
970       "<?xml version=\"1.0\"?>"
971       "<MPD xmlns=\"urn:mpeg:dash:schema:mpd:2011\""
972       "     profiles=\"urn:mpeg:dash:profile:isoff-main:2011\">"
973       "  <Period>"
974       "    <SegmentTemplate>"
975       "      <SegmentTimeline>"
976       "        <S t=\"1\" d=\"2\" r=\"3\">"
977       "        </S></SegmentTimeline></SegmentTemplate></Period></MPD>";
978 
979   gboolean ret;
980   GstMpdClient *mpdclient = gst_mpd_client_new ();
981 
982   ret = gst_mpd_parse (mpdclient, xml, (gint) strlen (xml));
983   assert_equals_int (ret, TRUE);
984 
985   periodNode = (GstPeriodNode *) mpdclient->mpd_node->Periods->data;
986   segmentTemplate = periodNode->SegmentTemplate;
987   multSegBaseType = segmentTemplate->MultSegBaseType;
988   segmentTimeline = (GstSegmentTimelineNode *) multSegBaseType->SegmentTimeline;
989   sNode = (GstSNode *) g_queue_peek_head (&segmentTimeline->S);
990   assert_equals_uint64 (sNode->t, 1);
991   assert_equals_uint64 (sNode->d, 2);
992   assert_equals_uint64 (sNode->r, 3);
993 
994   gst_mpd_client_free (mpdclient);
995 }
996 
997 GST_END_TEST;
998 
999 /*
1000  * Test parsing Period SegmentTemplate MultipleSegmentBaseType
1001  * BitstreamSwitching attributes
1002  */
GST_START_TEST(dash_mpdparser_period_segmentTemplate_multipleSegmentBaseType_bitstreamSwitching)1003 GST_START_TEST
1004     (dash_mpdparser_period_segmentTemplate_multipleSegmentBaseType_bitstreamSwitching)
1005 {
1006   GstPeriodNode *periodNode;
1007   GstSegmentTemplateNode *segmentTemplate;
1008   GstMultSegmentBaseType *multSegBaseType;
1009   GstURLType *bitstreamSwitching;
1010   const gchar *xml =
1011       "<?xml version=\"1.0\"?>"
1012       "<MPD xmlns=\"urn:mpeg:dash:schema:mpd:2011\""
1013       "     profiles=\"urn:mpeg:dash:profile:isoff-main:2011\">"
1014       "  <Period>"
1015       "    <SegmentTemplate duration=\"1\">"
1016       "      <BitstreamSwitching sourceURL=\"TestSourceURL\""
1017       "                          range=\"100-200\">"
1018       "      </BitstreamSwitching></SegmentTemplate></Period></MPD>";
1019 
1020   gboolean ret;
1021   GstMpdClient *mpdclient = gst_mpd_client_new ();
1022 
1023   ret = gst_mpd_parse (mpdclient, xml, (gint) strlen (xml));
1024   assert_equals_int (ret, TRUE);
1025 
1026   periodNode = (GstPeriodNode *) mpdclient->mpd_node->Periods->data;
1027   segmentTemplate = periodNode->SegmentTemplate;
1028   multSegBaseType = segmentTemplate->MultSegBaseType;
1029   bitstreamSwitching = multSegBaseType->BitstreamSwitching;
1030   assert_equals_string (bitstreamSwitching->sourceURL, "TestSourceURL");
1031   assert_equals_uint64 (bitstreamSwitching->range->first_byte_pos, 100);
1032   assert_equals_uint64 (bitstreamSwitching->range->last_byte_pos, 200);
1033 
1034   gst_mpd_client_free (mpdclient);
1035 }
1036 
1037 GST_END_TEST;
1038 
1039 /*
1040  * Test parsing Period AdaptationSet attributes
1041  *
1042  */
GST_START_TEST(dash_mpdparser_period_adaptationSet)1043 GST_START_TEST (dash_mpdparser_period_adaptationSet)
1044 {
1045   GstPeriodNode *periodNode;
1046   GstAdaptationSetNode *adaptationSet;
1047   const gchar *xml =
1048       "<?xml version=\"1.0\"?>"
1049       "<MPD xmlns=\"urn:mpeg:dash:schema:mpd:2011\""
1050       "     profiles=\"urn:mpeg:dash:profile:isoff-main:2011\">"
1051       "  <Period>"
1052       "    <AdaptationSet id=\"7\""
1053       "                   group=\"8\""
1054       "                   lang=\"en\""
1055       "                   contentType=\"TestContentType\""
1056       "                   par=\"4:3\""
1057       "                   minBandwidth=\"100\""
1058       "                   maxBandwidth=\"200\""
1059       "                   minWidth=\"1000\""
1060       "                   maxWidth=\"2000\""
1061       "                   minHeight=\"1100\""
1062       "                   maxHeight=\"2100\""
1063       "                   minFrameRate=\"25/123\""
1064       "                   maxFrameRate=\"26\""
1065       "                   segmentAlignment=\"2\""
1066       "                   subsegmentAlignment=\"false\""
1067       "                   subsegmentStartsWithSAP=\"6\""
1068       "                   bitstreamSwitching=\"false\">"
1069       "    </AdaptationSet></Period></MPD>";
1070 
1071   gboolean ret;
1072   GstMpdClient *mpdclient = gst_mpd_client_new ();
1073 
1074   ret = gst_mpd_parse (mpdclient, xml, (gint) strlen (xml));
1075   assert_equals_int (ret, TRUE);
1076 
1077   periodNode = (GstPeriodNode *) mpdclient->mpd_node->Periods->data;
1078   adaptationSet = (GstAdaptationSetNode *) periodNode->AdaptationSets->data;
1079   assert_equals_uint64 (adaptationSet->id, 7);
1080   assert_equals_uint64 (adaptationSet->group, 8);
1081   assert_equals_string (adaptationSet->lang, "en");
1082   assert_equals_string (adaptationSet->contentType, "TestContentType");
1083   assert_equals_uint64 (adaptationSet->par->num, 4);
1084   assert_equals_uint64 (adaptationSet->par->den, 3);
1085   assert_equals_uint64 (adaptationSet->minBandwidth, 100);
1086   assert_equals_uint64 (adaptationSet->maxBandwidth, 200);
1087   assert_equals_uint64 (adaptationSet->minWidth, 1000);
1088   assert_equals_uint64 (adaptationSet->maxWidth, 2000);
1089   assert_equals_uint64 (adaptationSet->minHeight, 1100);
1090   assert_equals_uint64 (adaptationSet->maxHeight, 2100);
1091   assert_equals_uint64 (adaptationSet->RepresentationBase->minFrameRate->num,
1092       25);
1093   assert_equals_uint64 (adaptationSet->RepresentationBase->minFrameRate->den,
1094       123);
1095   assert_equals_uint64 (adaptationSet->RepresentationBase->maxFrameRate->num,
1096       26);
1097   assert_equals_uint64 (adaptationSet->RepresentationBase->maxFrameRate->den,
1098       1);
1099   assert_equals_int (adaptationSet->segmentAlignment->flag, 1);
1100   assert_equals_uint64 (adaptationSet->segmentAlignment->value, 2);
1101   assert_equals_int (adaptationSet->subsegmentAlignment->flag, 0);
1102   assert_equals_uint64 (adaptationSet->subsegmentAlignment->value, 0);
1103   assert_equals_int (adaptationSet->subsegmentStartsWithSAP, 6);
1104   assert_equals_int (adaptationSet->bitstreamSwitching, 0);
1105 
1106   gst_mpd_client_free (mpdclient);
1107 }
1108 
1109 GST_END_TEST;
1110 
1111 /*
1112  * Test parsing Period AdaptationSet RepresentationBase attributes
1113  *
1114  */
GST_START_TEST(dash_mpdparser_period_adaptationSet_representationBase)1115 GST_START_TEST (dash_mpdparser_period_adaptationSet_representationBase)
1116 {
1117   GstPeriodNode *periodNode;
1118   GstAdaptationSetNode *adaptationSet;
1119   GstRepresentationBaseType *representationBase;
1120   const gchar *xml =
1121       "<?xml version=\"1.0\"?>"
1122       "<MPD xmlns=\"urn:mpeg:dash:schema:mpd:2011\""
1123       "     profiles=\"urn:mpeg:dash:profile:isoff-main:2011\">"
1124       "  <Period>"
1125       "    <AdaptationSet profiles=\"TestProfiles\""
1126       "                   width=\"100\""
1127       "                   height=\"200\""
1128       "                   sar=\"10:20\""
1129       "                   frameRate=\"30/40\""
1130       "                   audioSamplingRate=\"TestAudioSamplingRate\""
1131       "                   mimeType=\"TestMimeType\""
1132       "                   segmentProfiles=\"TestSegmentProfiles\""
1133       "                   codecs=\"TestCodecs\""
1134       "                   maximumSAPPeriod=\"3.4\""
1135       "                   startWithSAP=\"0\""
1136       "                   maxPlayoutRate=\"1.2\""
1137       "                   codingDependency=\"false\""
1138       "                   scanType=\"progressive\">"
1139       "    </AdaptationSet></Period></MPD>";
1140 
1141   gboolean ret;
1142   GstMpdClient *mpdclient = gst_mpd_client_new ();
1143 
1144   ret = gst_mpd_parse (mpdclient, xml, (gint) strlen (xml));
1145   assert_equals_int (ret, TRUE);
1146 
1147   periodNode = (GstPeriodNode *) mpdclient->mpd_node->Periods->data;
1148   adaptationSet = (GstAdaptationSetNode *) periodNode->AdaptationSets->data;
1149   representationBase = adaptationSet->RepresentationBase;
1150   assert_equals_string (representationBase->profiles, "TestProfiles");
1151   assert_equals_uint64 (representationBase->width, 100);
1152   assert_equals_uint64 (representationBase->height, 200);
1153   assert_equals_uint64 (representationBase->sar->num, 10);
1154   assert_equals_uint64 (representationBase->sar->den, 20);
1155   assert_equals_uint64 (representationBase->frameRate->num, 30);
1156   assert_equals_uint64 (representationBase->frameRate->den, 40);
1157   assert_equals_string (representationBase->audioSamplingRate,
1158       "TestAudioSamplingRate");
1159   assert_equals_string (representationBase->mimeType, "TestMimeType");
1160   assert_equals_string (representationBase->segmentProfiles,
1161       "TestSegmentProfiles");
1162   assert_equals_string (representationBase->codecs, "TestCodecs");
1163   assert_equals_float (representationBase->maximumSAPPeriod, 3.4);
1164   assert_equals_int (representationBase->startWithSAP, GST_SAP_TYPE_0);
1165   assert_equals_float (representationBase->maxPlayoutRate, 1.2);
1166   assert_equals_float (representationBase->codingDependency, 0);
1167   assert_equals_string (representationBase->scanType, "progressive");
1168 
1169   gst_mpd_client_free (mpdclient);
1170 }
1171 
1172 GST_END_TEST;
1173 
1174 /*
1175  * Test parsing Period AdaptationSet RepresentationBase FramePacking attributes
1176  *
1177  */
GST_START_TEST(dash_mpdparser_period_adaptationSet_representationBase_framePacking)1178 GST_START_TEST
1179     (dash_mpdparser_period_adaptationSet_representationBase_framePacking) {
1180   GstPeriodNode *periodNode;
1181   GstAdaptationSetNode *adaptationSet;
1182   GstRepresentationBaseType *representationBase;
1183   GstDescriptorType *framePacking;
1184   const gchar *xml =
1185       "<?xml version=\"1.0\"?>"
1186       "<MPD xmlns=\"urn:mpeg:dash:schema:mpd:2011\""
1187       "     profiles=\"urn:mpeg:dash:profile:isoff-main:2011\">"
1188       "  <Period>"
1189       "    <AdaptationSet>"
1190       "      <FramePacking schemeIdUri=\"TestSchemeIdUri\""
1191       "                    value=\"TestValue\">"
1192       "      </FramePacking></AdaptationSet></Period></MPD>";
1193 
1194   gboolean ret;
1195   GstMpdClient *mpdclient = gst_mpd_client_new ();
1196 
1197   ret = gst_mpd_parse (mpdclient, xml, (gint) strlen (xml));
1198   assert_equals_int (ret, TRUE);
1199 
1200   periodNode = (GstPeriodNode *) mpdclient->mpd_node->Periods->data;
1201   adaptationSet = (GstAdaptationSetNode *) periodNode->AdaptationSets->data;
1202   representationBase = adaptationSet->RepresentationBase;
1203   framePacking = (GstDescriptorType *) representationBase->FramePacking->data;
1204   assert_equals_string (framePacking->schemeIdUri, "TestSchemeIdUri");
1205   assert_equals_string (framePacking->value, "TestValue");
1206 
1207   gst_mpd_client_free (mpdclient);
1208 }
1209 
1210 GST_END_TEST;
1211 
1212 /*
1213  * Test parsing Period AdaptationSet RepresentationBase
1214  * AudioChannelConfiguration attributes
1215  */
GST_START_TEST(dash_mpdparser_period_adaptationSet_representationBase_audioChannelConfiguration)1216 GST_START_TEST
1217     (dash_mpdparser_period_adaptationSet_representationBase_audioChannelConfiguration)
1218 {
1219   GstPeriodNode *periodNode;
1220   GstAdaptationSetNode *adaptationSet;
1221   GstRepresentationBaseType *representationBase;
1222   GstDescriptorType *audioChannelConfiguration;
1223   const gchar *xml =
1224       "<?xml version=\"1.0\"?>"
1225       "<MPD xmlns=\"urn:mpeg:dash:schema:mpd:2011\""
1226       "     profiles=\"urn:mpeg:dash:profile:isoff-main:2011\">"
1227       "  <Period>"
1228       "    <AdaptationSet>"
1229       "      <AudioChannelConfiguration schemeIdUri=\"TestSchemeIdUri\""
1230       "                                 value=\"TestValue\">"
1231       "      </AudioChannelConfiguration></AdaptationSet></Period></MPD>";
1232 
1233   gboolean ret;
1234   GstMpdClient *mpdclient = gst_mpd_client_new ();
1235 
1236   ret = gst_mpd_parse (mpdclient, xml, (gint) strlen (xml));
1237   assert_equals_int (ret, TRUE);
1238 
1239   periodNode = (GstPeriodNode *) mpdclient->mpd_node->Periods->data;
1240   adaptationSet = (GstAdaptationSetNode *) periodNode->AdaptationSets->data;
1241   representationBase = adaptationSet->RepresentationBase;
1242   audioChannelConfiguration =
1243       (GstDescriptorType *) representationBase->AudioChannelConfiguration->data;
1244   assert_equals_string (audioChannelConfiguration->schemeIdUri,
1245       "TestSchemeIdUri");
1246   assert_equals_string (audioChannelConfiguration->value, "TestValue");
1247 
1248   gst_mpd_client_free (mpdclient);
1249 }
1250 
1251 GST_END_TEST;
1252 
1253 /*
1254  * Test parsing Period AdaptationSet RepresentationBase ContentProtection
1255  * attributes
1256  */
GST_START_TEST(dash_mpdparser_period_adaptationSet_representationBase_contentProtection)1257 GST_START_TEST
1258     (dash_mpdparser_period_adaptationSet_representationBase_contentProtection) {
1259   GstPeriodNode *periodNode;
1260   GstAdaptationSetNode *adaptationSet;
1261   GstRepresentationBaseType *representationBase;
1262   GstDescriptorType *contentProtection;
1263   const gchar *xml =
1264       "<?xml version=\"1.0\"?>"
1265       "<MPD xmlns=\"urn:mpeg:dash:schema:mpd:2011\""
1266       "     profiles=\"urn:mpeg:dash:profile:isoff-main:2011\">"
1267       "  <Period>"
1268       "    <AdaptationSet>"
1269       "      <ContentProtection schemeIdUri=\"TestSchemeIdUri\""
1270       "                         value=\"TestValue\">"
1271       "      </ContentProtection></AdaptationSet></Period></MPD>";
1272 
1273   gboolean ret;
1274   GstMpdClient *mpdclient = gst_mpd_client_new ();
1275 
1276   ret = gst_mpd_parse (mpdclient, xml, (gint) strlen (xml));
1277   assert_equals_int (ret, TRUE);
1278 
1279   periodNode = (GstPeriodNode *) mpdclient->mpd_node->Periods->data;
1280   adaptationSet = (GstAdaptationSetNode *) periodNode->AdaptationSets->data;
1281   representationBase = adaptationSet->RepresentationBase;
1282   contentProtection =
1283       (GstDescriptorType *) representationBase->ContentProtection->data;
1284   assert_equals_string (contentProtection->schemeIdUri, "TestSchemeIdUri");
1285   assert_equals_string (contentProtection->value, "TestValue");
1286 
1287   gst_mpd_client_free (mpdclient);
1288 }
1289 
1290 GST_END_TEST;
1291 
1292 /*
1293  * Test parsing ContentProtection element that has no value attribute
1294  */
GST_START_TEST(dash_mpdparser_contentProtection_no_value)1295 GST_START_TEST (dash_mpdparser_contentProtection_no_value)
1296 {
1297   GstPeriodNode *periodNode;
1298   GstAdaptationSetNode *adaptationSet;
1299   GstRepresentationBaseType *representationBase;
1300   GstDescriptorType *contentProtection;
1301   const gchar *xml =
1302       "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
1303       "<MPD xmlns=\"urn:mpeg:dash:schema:mpd:2011\""
1304       "     xmlns:mspr=\"urn:microsoft:playready\""
1305       "     profiles=\"urn:mpeg:dash:profile:isoff-main:2011\">"
1306       "  <Period>"
1307       "    <AdaptationSet>"
1308       "      <ContentProtection schemeIdUri=\"urn:mpeg:dash:mp4protection:2011\" value=\"cenc\"/>"
1309       "      <ContentProtection xmlns:mas=\"urn:marlin:mas:1-0:services:schemas:mpd\" schemeIdUri=\"urn:uuid:5e629af5-38da-4063-8977-97ffbd9902d4\">"
1310       "	      <mas:MarlinContentIds>"
1311       "	        <mas:MarlinContentId>urn:marlin:kid:02020202020202020202020202020202</mas:MarlinContentId>"
1312       "       </mas:MarlinContentIds>"
1313       "      </ContentProtection>"
1314       "      <ContentProtection schemeIdUri=\"urn:uuid:9a04f079-9840-4286-ab92-e65be0885f95\" value=\"MSPR 2.0\">"
1315       "        <mspr:pro>dGVzdA==</mspr:pro>"
1316       "     </ContentProtection>" "</AdaptationSet></Period></MPD>";
1317 
1318   gboolean ret;
1319   GstMpdClient *mpdclient = gst_mpd_client_new ();
1320   gchar *str;
1321 
1322   ret = gst_mpd_parse (mpdclient, xml, (gint) strlen (xml));
1323   assert_equals_int (ret, TRUE);
1324 
1325   periodNode = (GstPeriodNode *) mpdclient->mpd_node->Periods->data;
1326   adaptationSet = (GstAdaptationSetNode *) periodNode->AdaptationSets->data;
1327   representationBase = adaptationSet->RepresentationBase;
1328   assert_equals_int (g_list_length (representationBase->ContentProtection), 3);
1329   contentProtection =
1330       (GstDescriptorType *) g_list_nth (representationBase->ContentProtection,
1331       1)->data;
1332   assert_equals_string (contentProtection->schemeIdUri,
1333       "urn:uuid:5e629af5-38da-4063-8977-97ffbd9902d4");
1334   fail_if (contentProtection->value == NULL);
1335   /* We can't do a simple compare of value (which should be an XML dump
1336      of the ContentProtection element), because the whitespace
1337      formatting from xmlDump might differ between versions of libxml */
1338   str = strstr (contentProtection->value, "<ContentProtection");
1339   fail_if (str == NULL);
1340   str = strstr (contentProtection->value, "<mas:MarlinContentIds>");
1341   fail_if (str == NULL);
1342   str = strstr (contentProtection->value, "<mas:MarlinContentId>");
1343   fail_if (str == NULL);
1344   str =
1345       strstr (contentProtection->value,
1346       "urn:marlin:kid:02020202020202020202020202020202");
1347   fail_if (str == NULL);
1348   str = strstr (contentProtection->value, "</ContentProtection>");
1349   fail_if (str == NULL);
1350   gst_mpd_client_free (mpdclient);
1351 }
1352 
1353 GST_END_TEST;
1354 
1355 /*
1356  * Test parsing ContentProtection element that has no value attribute
1357  * nor an XML encoding
1358  */
GST_START_TEST(dash_mpdparser_contentProtection_no_value_no_encoding)1359 GST_START_TEST (dash_mpdparser_contentProtection_no_value_no_encoding)
1360 {
1361   GstPeriodNode *periodNode;
1362   GstAdaptationSetNode *adaptationSet;
1363   GstRepresentationBaseType *representationBase;
1364   GstDescriptorType *contentProtection;
1365   const gchar *xml =
1366       "<?xml version=\"1.0\"?>"
1367       "<MPD xmlns=\"urn:mpeg:dash:schema:mpd:2011\""
1368       "     profiles=\"urn:mpeg:dash:profile:isoff-main:2011\">"
1369       "  <Period>"
1370       "    <AdaptationSet>"
1371       "      <ContentProtection schemeIdUri=\"urn:mpeg:dash:mp4protection:2011\" value=\"cenc\"/>"
1372       "      <ContentProtection xmlns:mas=\"urn:marlin:mas:1-0:services:schemas:mpd\" schemeIdUri=\"urn:uuid:5e629af5-38da-4063-8977-97ffbd9902d4\">"
1373       "	      <mas:MarlinContentIds>"
1374       "	        <mas:MarlinContentId>urn:marlin:kid:02020202020202020202020202020202</mas:MarlinContentId>"
1375       "       </mas:MarlinContentIds>"
1376       "     </ContentProtection>" "</AdaptationSet></Period></MPD>";
1377 
1378   gboolean ret;
1379   GstMpdClient *mpdclient = gst_mpd_client_new ();
1380 
1381   ret = gst_mpd_parse (mpdclient, xml, (gint) strlen (xml));
1382   assert_equals_int (ret, TRUE);
1383 
1384   periodNode = (GstPeriodNode *) mpdclient->mpd_node->Periods->data;
1385   adaptationSet = (GstAdaptationSetNode *) periodNode->AdaptationSets->data;
1386   representationBase = adaptationSet->RepresentationBase;
1387   assert_equals_int (g_list_length (representationBase->ContentProtection), 2);
1388   contentProtection =
1389       (GstDescriptorType *) g_list_nth (representationBase->ContentProtection,
1390       1)->data;
1391   assert_equals_string (contentProtection->schemeIdUri,
1392       "urn:uuid:5e629af5-38da-4063-8977-97ffbd9902d4");
1393   fail_if (contentProtection->value == NULL);
1394   gst_mpd_client_free (mpdclient);
1395 }
1396 
1397 GST_END_TEST;
1398 
1399 /*
1400  * Test parsing Period AdaptationSet Accessibility attributes
1401  *
1402  */
GST_START_TEST(dash_mpdparser_period_adaptationSet_accessibility)1403 GST_START_TEST (dash_mpdparser_period_adaptationSet_accessibility)
1404 {
1405   GstPeriodNode *periodNode;
1406   GstAdaptationSetNode *adaptationSet;
1407   GstDescriptorType *accessibility;
1408   const gchar *xml =
1409       "<?xml version=\"1.0\"?>"
1410       "<MPD xmlns=\"urn:mpeg:dash:schema:mpd:2011\""
1411       "     profiles=\"urn:mpeg:dash:profile:isoff-main:2011\">"
1412       "  <Period>"
1413       "    <AdaptationSet>"
1414       "      <Accessibility schemeIdUri=\"TestSchemeIdUri\""
1415       "                     value=\"TestValue\">"
1416       "      </Accessibility></AdaptationSet></Period></MPD>";
1417 
1418   gboolean ret;
1419   GstMpdClient *mpdclient = gst_mpd_client_new ();
1420 
1421   ret = gst_mpd_parse (mpdclient, xml, (gint) strlen (xml));
1422   assert_equals_int (ret, TRUE);
1423 
1424   periodNode = (GstPeriodNode *) mpdclient->mpd_node->Periods->data;
1425   adaptationSet = (GstAdaptationSetNode *) periodNode->AdaptationSets->data;
1426   accessibility = (GstDescriptorType *) adaptationSet->Accessibility->data;
1427   assert_equals_string (accessibility->schemeIdUri, "TestSchemeIdUri");
1428   assert_equals_string (accessibility->value, "TestValue");
1429 
1430   gst_mpd_client_free (mpdclient);
1431 }
1432 
1433 GST_END_TEST;
1434 
1435 /*
1436  * Test parsing Period AdaptationSet Role attributes
1437  *
1438  */
GST_START_TEST(dash_mpdparser_period_adaptationSet_role)1439 GST_START_TEST (dash_mpdparser_period_adaptationSet_role)
1440 {
1441   GstPeriodNode *periodNode;
1442   GstAdaptationSetNode *adaptationSet;
1443   GstDescriptorType *role;
1444   const gchar *xml =
1445       "<?xml version=\"1.0\"?>"
1446       "<MPD xmlns=\"urn:mpeg:dash:schema:mpd:2011\""
1447       "     profiles=\"urn:mpeg:dash:profile:isoff-main:2011\">"
1448       "  <Period>"
1449       "    <AdaptationSet>"
1450       "      <Role schemeIdUri=\"TestSchemeIdUri\""
1451       "            value=\"TestValue\">"
1452       "      </Role></AdaptationSet></Period></MPD>";
1453 
1454   gboolean ret;
1455   GstMpdClient *mpdclient = gst_mpd_client_new ();
1456 
1457   ret = gst_mpd_parse (mpdclient, xml, (gint) strlen (xml));
1458   assert_equals_int (ret, TRUE);
1459 
1460   periodNode = (GstPeriodNode *) mpdclient->mpd_node->Periods->data;
1461   adaptationSet = (GstAdaptationSetNode *) periodNode->AdaptationSets->data;
1462   role = (GstDescriptorType *) adaptationSet->Role->data;
1463   assert_equals_string (role->schemeIdUri, "TestSchemeIdUri");
1464   assert_equals_string (role->value, "TestValue");
1465 
1466   gst_mpd_client_free (mpdclient);
1467 }
1468 
1469 GST_END_TEST;
1470 
1471 /*
1472  * Test parsing Period AdaptationSet Rating attributes
1473  *
1474  */
GST_START_TEST(dash_mpdparser_period_adaptationSet_rating)1475 GST_START_TEST (dash_mpdparser_period_adaptationSet_rating)
1476 {
1477   GstPeriodNode *periodNode;
1478   GstAdaptationSetNode *adaptationSet;
1479   GstDescriptorType *rating;
1480   const gchar *xml =
1481       "<?xml version=\"1.0\"?>"
1482       "<MPD xmlns=\"urn:mpeg:dash:schema:mpd:2011\""
1483       "     profiles=\"urn:mpeg:dash:profile:isoff-main:2011\">"
1484       "  <Period>"
1485       "    <AdaptationSet>"
1486       "      <Rating schemeIdUri=\"TestSchemeIdUri\""
1487       "              value=\"TestValue\">"
1488       "      </Rating></AdaptationSet></Period></MPD>";
1489 
1490   gboolean ret;
1491   GstMpdClient *mpdclient = gst_mpd_client_new ();
1492 
1493   ret = gst_mpd_parse (mpdclient, xml, (gint) strlen (xml));
1494   assert_equals_int (ret, TRUE);
1495 
1496   periodNode = (GstPeriodNode *) mpdclient->mpd_node->Periods->data;
1497   adaptationSet = (GstAdaptationSetNode *) periodNode->AdaptationSets->data;
1498   rating = (GstDescriptorType *) adaptationSet->Rating->data;
1499   assert_equals_string (rating->schemeIdUri, "TestSchemeIdUri");
1500   assert_equals_string (rating->value, "TestValue");
1501 
1502   gst_mpd_client_free (mpdclient);
1503 }
1504 
1505 GST_END_TEST;
1506 
1507 /*
1508  * Test parsing Period AdaptationSet Viewpoint attributes
1509  *
1510  */
GST_START_TEST(dash_mpdparser_period_adaptationSet_viewpoint)1511 GST_START_TEST (dash_mpdparser_period_adaptationSet_viewpoint)
1512 {
1513   GstPeriodNode *periodNode;
1514   GstAdaptationSetNode *adaptationSet;
1515   GstDescriptorType *viewpoint;
1516   const gchar *xml =
1517       "<?xml version=\"1.0\"?>"
1518       "<MPD xmlns=\"urn:mpeg:dash:schema:mpd:2011\""
1519       "     profiles=\"urn:mpeg:dash:profile:isoff-main:2011\">"
1520       "  <Period>"
1521       "    <AdaptationSet>"
1522       "      <Viewpoint schemeIdUri=\"TestSchemeIdUri\""
1523       "                 value=\"TestValue\">"
1524       "      </Viewpoint></AdaptationSet></Period></MPD>";
1525 
1526   gboolean ret;
1527   GstMpdClient *mpdclient = gst_mpd_client_new ();
1528 
1529   ret = gst_mpd_parse (mpdclient, xml, (gint) strlen (xml));
1530   assert_equals_int (ret, TRUE);
1531 
1532   periodNode = (GstPeriodNode *) mpdclient->mpd_node->Periods->data;
1533   adaptationSet = (GstAdaptationSetNode *) periodNode->AdaptationSets->data;
1534   viewpoint = (GstDescriptorType *) adaptationSet->Viewpoint->data;
1535   assert_equals_string (viewpoint->schemeIdUri, "TestSchemeIdUri");
1536   assert_equals_string (viewpoint->value, "TestValue");
1537 
1538   gst_mpd_client_free (mpdclient);
1539 }
1540 
1541 GST_END_TEST;
1542 
1543 /*
1544  * Test parsing Period AdaptationSet ContentComponent attributes
1545  *
1546  */
GST_START_TEST(dash_mpdparser_period_adaptationSet_contentComponent)1547 GST_START_TEST (dash_mpdparser_period_adaptationSet_contentComponent)
1548 {
1549   GstPeriodNode *periodNode;
1550   GstAdaptationSetNode *adaptationSet;
1551   GstContentComponentNode *contentComponent;
1552   const gchar *xml =
1553       "<?xml version=\"1.0\"?>"
1554       "<MPD xmlns=\"urn:mpeg:dash:schema:mpd:2011\""
1555       "     profiles=\"urn:mpeg:dash:profile:isoff-main:2011\">"
1556       "  <Period>"
1557       "    <AdaptationSet>"
1558       "      <ContentComponent id=\"1\""
1559       "                        lang=\"en\""
1560       "                        contentType=\"TestContentType\""
1561       "                        par=\"10:20\">"
1562       "      </ContentComponent></AdaptationSet></Period></MPD>";
1563 
1564   gboolean ret;
1565   GstMpdClient *mpdclient = gst_mpd_client_new ();
1566 
1567   ret = gst_mpd_parse (mpdclient, xml, (gint) strlen (xml));
1568   assert_equals_int (ret, TRUE);
1569 
1570   periodNode = (GstPeriodNode *) mpdclient->mpd_node->Periods->data;
1571   adaptationSet = (GstAdaptationSetNode *) periodNode->AdaptationSets->data;
1572   contentComponent = (GstContentComponentNode *)
1573       adaptationSet->ContentComponents->data;
1574   assert_equals_uint64 (contentComponent->id, 1);
1575   assert_equals_string (contentComponent->lang, "en");
1576   assert_equals_string (contentComponent->contentType, "TestContentType");
1577   assert_equals_uint64 (contentComponent->par->num, 10);
1578   assert_equals_uint64 (contentComponent->par->den, 20);
1579 
1580   gst_mpd_client_free (mpdclient);
1581 }
1582 
1583 GST_END_TEST;
1584 
1585 /*
1586  * Test parsing Period AdaptationSet ContentComponent Accessibility attributes
1587  *
1588  */
GST_START_TEST(dash_mpdparser_period_adaptationSet_contentComponent_accessibility)1589 GST_START_TEST
1590     (dash_mpdparser_period_adaptationSet_contentComponent_accessibility) {
1591   GstPeriodNode *periodNode;
1592   GstAdaptationSetNode *adaptationSet;
1593   GstContentComponentNode *contentComponent;
1594   GstDescriptorType *accessibility;
1595   const gchar *xml =
1596       "<?xml version=\"1.0\"?>"
1597       "<MPD xmlns=\"urn:mpeg:dash:schema:mpd:2011\""
1598       "     profiles=\"urn:mpeg:dash:profile:isoff-main:2011\">"
1599       "  <Period>"
1600       "    <AdaptationSet>"
1601       "      <ContentComponent>"
1602       "        <Accessibility schemeIdUri=\"TestSchemeIdUri\""
1603       "                       value=\"TestValue\">"
1604       "        </Accessibility>"
1605       "      </ContentComponent></AdaptationSet></Period></MPD>";
1606 
1607   gboolean ret;
1608   GstMpdClient *mpdclient = gst_mpd_client_new ();
1609 
1610   ret = gst_mpd_parse (mpdclient, xml, (gint) strlen (xml));
1611   assert_equals_int (ret, TRUE);
1612 
1613   periodNode = (GstPeriodNode *) mpdclient->mpd_node->Periods->data;
1614   adaptationSet = (GstAdaptationSetNode *) periodNode->AdaptationSets->data;
1615   contentComponent = (GstContentComponentNode *)
1616       adaptationSet->ContentComponents->data;
1617   accessibility = (GstDescriptorType *) contentComponent->Accessibility->data;
1618   assert_equals_string (accessibility->schemeIdUri, "TestSchemeIdUri");
1619   assert_equals_string (accessibility->value, "TestValue");
1620 
1621   gst_mpd_client_free (mpdclient);
1622 }
1623 
1624 GST_END_TEST;
1625 
1626 /*
1627  * Test parsing Period AdaptationSet ContentComponent Role attributes
1628  *
1629  */
GST_START_TEST(dash_mpdparser_period_adaptationSet_contentComponent_role)1630 GST_START_TEST (dash_mpdparser_period_adaptationSet_contentComponent_role)
1631 {
1632   GstPeriodNode *periodNode;
1633   GstAdaptationSetNode *adaptationSet;
1634   GstContentComponentNode *contentComponent;
1635   GstDescriptorType *role;
1636   const gchar *xml =
1637       "<?xml version=\"1.0\"?>"
1638       "<MPD xmlns=\"urn:mpeg:dash:schema:mpd:2011\""
1639       "     profiles=\"urn:mpeg:dash:profile:isoff-main:2011\">"
1640       "  <Period>"
1641       "    <AdaptationSet>"
1642       "      <ContentComponent>"
1643       "        <Role schemeIdUri=\"TestSchemeIdUri\""
1644       "              value=\"TestValue\">"
1645       "        </Role></ContentComponent></AdaptationSet></Period></MPD>";
1646 
1647   gboolean ret;
1648   GstMpdClient *mpdclient = gst_mpd_client_new ();
1649 
1650   ret = gst_mpd_parse (mpdclient, xml, (gint) strlen (xml));
1651   assert_equals_int (ret, TRUE);
1652 
1653   periodNode = (GstPeriodNode *) mpdclient->mpd_node->Periods->data;
1654   adaptationSet = (GstAdaptationSetNode *) periodNode->AdaptationSets->data;
1655   contentComponent = (GstContentComponentNode *)
1656       adaptationSet->ContentComponents->data;
1657   role = (GstDescriptorType *) contentComponent->Role->data;
1658   assert_equals_string (role->schemeIdUri, "TestSchemeIdUri");
1659   assert_equals_string (role->value, "TestValue");
1660 
1661   gst_mpd_client_free (mpdclient);
1662 }
1663 
1664 GST_END_TEST;
1665 
1666 /*
1667  * Test parsing Period AdaptationSet ContentComponent Rating attributes
1668  *
1669  */
GST_START_TEST(dash_mpdparser_period_adaptationSet_contentComponent_rating)1670 GST_START_TEST (dash_mpdparser_period_adaptationSet_contentComponent_rating)
1671 {
1672   GstPeriodNode *periodNode;
1673   GstAdaptationSetNode *adaptationSet;
1674   GstContentComponentNode *contentComponent;
1675   GstDescriptorType *rating;
1676   const gchar *xml =
1677       "<?xml version=\"1.0\"?>"
1678       "<MPD xmlns=\"urn:mpeg:dash:schema:mpd:2011\""
1679       "     profiles=\"urn:mpeg:dash:profile:isoff-main:2011\">"
1680       "  <Period>"
1681       "    <AdaptationSet>"
1682       "      <ContentComponent>"
1683       "        <Rating schemeIdUri=\"TestSchemeIdUri\""
1684       "                value=\"TestValue\">"
1685       "        </Rating>"
1686       "      </ContentComponent></AdaptationSet></Period></MPD>";
1687 
1688   gboolean ret;
1689   GstMpdClient *mpdclient = gst_mpd_client_new ();
1690 
1691   ret = gst_mpd_parse (mpdclient, xml, (gint) strlen (xml));
1692   assert_equals_int (ret, TRUE);
1693 
1694   periodNode = (GstPeriodNode *) mpdclient->mpd_node->Periods->data;
1695   adaptationSet = (GstAdaptationSetNode *) periodNode->AdaptationSets->data;
1696   contentComponent = (GstContentComponentNode *)
1697       adaptationSet->ContentComponents->data;
1698   rating = (GstDescriptorType *) contentComponent->Rating->data;
1699   assert_equals_string (rating->schemeIdUri, "TestSchemeIdUri");
1700   assert_equals_string (rating->value, "TestValue");
1701 
1702   gst_mpd_client_free (mpdclient);
1703 }
1704 
1705 GST_END_TEST;
1706 
1707 /*
1708  * Test parsing Period AdaptationSet ContentComponent Viewpoint attributes
1709  *
1710  */
GST_START_TEST(dash_mpdparser_period_adaptationSet_contentComponent_viewpoint)1711 GST_START_TEST (dash_mpdparser_period_adaptationSet_contentComponent_viewpoint)
1712 {
1713   GstPeriodNode *periodNode;
1714   GstAdaptationSetNode *adaptationSet;
1715   GstContentComponentNode *contentComponent;
1716   GstDescriptorType *viewpoint;
1717   const gchar *xml =
1718       "<?xml version=\"1.0\"?>"
1719       "<MPD xmlns=\"urn:mpeg:dash:schema:mpd:2011\""
1720       "     profiles=\"urn:mpeg:dash:profile:isoff-main:2011\">"
1721       "  <Period>"
1722       "    <AdaptationSet>"
1723       "      <ContentComponent>"
1724       "        <Viewpoint schemeIdUri=\"TestSchemeIdUri\""
1725       "                   value=\"TestValue\">"
1726       "        </Viewpoint>"
1727       "      </ContentComponent></AdaptationSet></Period></MPD>";
1728 
1729   gboolean ret;
1730   GstMpdClient *mpdclient = gst_mpd_client_new ();
1731 
1732   ret = gst_mpd_parse (mpdclient, xml, (gint) strlen (xml));
1733   assert_equals_int (ret, TRUE);
1734 
1735   periodNode = (GstPeriodNode *) mpdclient->mpd_node->Periods->data;
1736   adaptationSet = (GstAdaptationSetNode *) periodNode->AdaptationSets->data;
1737   contentComponent = (GstContentComponentNode *)
1738       adaptationSet->ContentComponents->data;
1739   viewpoint = (GstDescriptorType *) contentComponent->Viewpoint->data;
1740   assert_equals_string (viewpoint->schemeIdUri, "TestSchemeIdUri");
1741   assert_equals_string (viewpoint->value, "TestValue");
1742 
1743   gst_mpd_client_free (mpdclient);
1744 }
1745 
1746 GST_END_TEST;
1747 
1748 /*
1749  * Test parsing Period AdaptationSet BaseURL attributes
1750  *
1751  */
GST_START_TEST(dash_mpdparser_period_adaptationSet_baseURL)1752 GST_START_TEST (dash_mpdparser_period_adaptationSet_baseURL)
1753 {
1754   GstPeriodNode *periodNode;
1755   GstAdaptationSetNode *adaptationSet;
1756   GstBaseURL *baseURL;
1757   const gchar *xml =
1758       "<?xml version=\"1.0\"?>"
1759       "<MPD xmlns=\"urn:mpeg:dash:schema:mpd:2011\""
1760       "     profiles=\"urn:mpeg:dash:profile:isoff-main:2011\">"
1761       "  <Period>"
1762       "    <AdaptationSet>"
1763       "      <BaseURL serviceLocation=\"TestServiceLocation\""
1764       "               byteRange=\"TestByteRange\">TestBaseURL</BaseURL>"
1765       "    </AdaptationSet></Period></MPD>";
1766 
1767   gboolean ret;
1768   GstMpdClient *mpdclient = gst_mpd_client_new ();
1769 
1770   ret = gst_mpd_parse (mpdclient, xml, (gint) strlen (xml));
1771   assert_equals_int (ret, TRUE);
1772 
1773   periodNode = (GstPeriodNode *) mpdclient->mpd_node->Periods->data;
1774   adaptationSet = (GstAdaptationSetNode *) periodNode->AdaptationSets->data;
1775   baseURL = (GstBaseURL *) adaptationSet->BaseURLs->data;
1776   assert_equals_string (baseURL->baseURL, "TestBaseURL");
1777   assert_equals_string (baseURL->serviceLocation, "TestServiceLocation");
1778   assert_equals_string (baseURL->byteRange, "TestByteRange");
1779 
1780   gst_mpd_client_free (mpdclient);
1781 }
1782 
1783 GST_END_TEST;
1784 
1785 /*
1786  * Test parsing Period AdaptationSet SegmentBase attributes
1787  *
1788  */
GST_START_TEST(dash_mpdparser_period_adaptationSet_segmentBase)1789 GST_START_TEST (dash_mpdparser_period_adaptationSet_segmentBase)
1790 {
1791   GstPeriodNode *periodNode;
1792   GstAdaptationSetNode *adaptationSet;
1793   GstSegmentBaseType *segmentBase;
1794   const gchar *xml =
1795       "<?xml version=\"1.0\"?>"
1796       "<MPD xmlns=\"urn:mpeg:dash:schema:mpd:2011\""
1797       "     profiles=\"urn:mpeg:dash:profile:isoff-main:2011\">"
1798       "  <Period>"
1799       "    <AdaptationSet>"
1800       "      <SegmentBase timescale=\"123456\""
1801       "                   presentationTimeOffset=\"123456789\""
1802       "                   indexRange=\"100-200\""
1803       "                   indexRangeExact=\"true\">"
1804       "      </SegmentBase></AdaptationSet></Period></MPD>";
1805 
1806   gboolean ret;
1807   GstMpdClient *mpdclient = gst_mpd_client_new ();
1808 
1809   ret = gst_mpd_parse (mpdclient, xml, (gint) strlen (xml));
1810   assert_equals_int (ret, TRUE);
1811 
1812   periodNode = (GstPeriodNode *) mpdclient->mpd_node->Periods->data;
1813   adaptationSet = (GstAdaptationSetNode *) periodNode->AdaptationSets->data;
1814   segmentBase = adaptationSet->SegmentBase;
1815   assert_equals_uint64 (segmentBase->timescale, 123456);
1816   assert_equals_uint64 (segmentBase->presentationTimeOffset, 123456789);
1817   assert_equals_uint64 (segmentBase->indexRange->first_byte_pos, 100);
1818   assert_equals_uint64 (segmentBase->indexRange->last_byte_pos, 200);
1819   assert_equals_int (segmentBase->indexRangeExact, TRUE);
1820 
1821   gst_mpd_client_free (mpdclient);
1822 }
1823 
1824 GST_END_TEST;
1825 
1826 /*
1827  * Test parsing Period AdaptationSet SegmentBase Initialization attributes
1828  *
1829  */
GST_START_TEST(dash_mpdparser_period_adaptationSet_segmentBase_initialization)1830 GST_START_TEST (dash_mpdparser_period_adaptationSet_segmentBase_initialization)
1831 {
1832   GstPeriodNode *periodNode;
1833   GstAdaptationSetNode *adaptationSet;
1834   GstSegmentBaseType *segmentBase;
1835   GstURLType *initialization;
1836   const gchar *xml =
1837       "<?xml version=\"1.0\"?>"
1838       "<MPD xmlns=\"urn:mpeg:dash:schema:mpd:2011\""
1839       "     profiles=\"urn:mpeg:dash:profile:isoff-main:2011\">"
1840       "  <Period>"
1841       "    <AdaptationSet>"
1842       "      <SegmentBase>"
1843       "        <Initialisation sourceURL=\"TestSourceURL\""
1844       "                        range=\"100-200\">"
1845       "        </Initialisation></SegmentBase></AdaptationSet></Period></MPD>";
1846 
1847   gboolean ret;
1848   GstMpdClient *mpdclient = gst_mpd_client_new ();
1849 
1850   ret = gst_mpd_parse (mpdclient, xml, (gint) strlen (xml));
1851   assert_equals_int (ret, TRUE);
1852 
1853   periodNode = (GstPeriodNode *) mpdclient->mpd_node->Periods->data;
1854   adaptationSet = (GstAdaptationSetNode *) periodNode->AdaptationSets->data;
1855   segmentBase = adaptationSet->SegmentBase;
1856   initialization = segmentBase->Initialization;
1857   assert_equals_string (initialization->sourceURL, "TestSourceURL");
1858   assert_equals_uint64 (initialization->range->first_byte_pos, 100);
1859   assert_equals_uint64 (initialization->range->last_byte_pos, 200);
1860 
1861   gst_mpd_client_free (mpdclient);
1862 }
1863 
1864 GST_END_TEST;
1865 
1866 /*
1867  * Test parsing Period AdaptationSet SegmentBase RepresentationIndex attributes
1868  *
1869  */
GST_START_TEST(dash_mpdparser_period_adaptationSet_segmentBase_representationIndex)1870 GST_START_TEST
1871     (dash_mpdparser_period_adaptationSet_segmentBase_representationIndex) {
1872   GstPeriodNode *periodNode;
1873   GstAdaptationSetNode *adaptationSet;
1874   GstSegmentBaseType *segmentBase;
1875   GstURLType *representationIndex;
1876   const gchar *xml =
1877       "<?xml version=\"1.0\"?>"
1878       "<MPD xmlns=\"urn:mpeg:dash:schema:mpd:2011\""
1879       "     profiles=\"urn:mpeg:dash:profile:isoff-main:2011\">"
1880       "  <Period>"
1881       "    <AdaptationSet>"
1882       "      <SegmentBase>"
1883       "        <RepresentationIndex sourceURL=\"TestSourceURL\""
1884       "                             range=\"100-200\">"
1885       "        </RepresentationIndex>"
1886       "      </SegmentBase></AdaptationSet></Period></MPD>";
1887 
1888   gboolean ret;
1889   GstMpdClient *mpdclient = gst_mpd_client_new ();
1890 
1891   ret = gst_mpd_parse (mpdclient, xml, (gint) strlen (xml));
1892   assert_equals_int (ret, TRUE);
1893 
1894   periodNode = (GstPeriodNode *) mpdclient->mpd_node->Periods->data;
1895   adaptationSet = (GstAdaptationSetNode *) periodNode->AdaptationSets->data;
1896   segmentBase = adaptationSet->SegmentBase;
1897   representationIndex = segmentBase->RepresentationIndex;
1898   assert_equals_string (representationIndex->sourceURL, "TestSourceURL");
1899   assert_equals_uint64 (representationIndex->range->first_byte_pos, 100);
1900   assert_equals_uint64 (representationIndex->range->last_byte_pos, 200);
1901 
1902   gst_mpd_client_free (mpdclient);
1903 }
1904 
1905 GST_END_TEST;
1906 
1907 /*
1908  * Test parsing Period AdaptationSet SegmentList attributes
1909  *
1910  */
GST_START_TEST(dash_mpdparser_period_adaptationSet_segmentList)1911 GST_START_TEST (dash_mpdparser_period_adaptationSet_segmentList)
1912 {
1913   GstPeriodNode *periodNode;
1914   GstAdaptationSetNode *adaptationSet;
1915   GstSegmentListNode *segmentList;
1916   const gchar *xml =
1917       "<?xml version=\"1.0\"?>"
1918       "<MPD xmlns=\"urn:mpeg:dash:schema:mpd:2011\""
1919       "     profiles=\"urn:mpeg:dash:profile:isoff-main:2011\">"
1920       "  <Period>"
1921       "    <AdaptationSet>"
1922       "      <SegmentList duration=\"1\"></SegmentList></AdaptationSet></Period></MPD>";
1923 
1924   gboolean ret;
1925   GstMpdClient *mpdclient = gst_mpd_client_new ();
1926 
1927   ret = gst_mpd_parse (mpdclient, xml, (gint) strlen (xml));
1928   assert_equals_int (ret, TRUE);
1929 
1930   periodNode = (GstPeriodNode *) mpdclient->mpd_node->Periods->data;
1931   adaptationSet = (GstAdaptationSetNode *) periodNode->AdaptationSets->data;
1932   segmentList = adaptationSet->SegmentList;
1933   fail_if (segmentList == NULL);
1934 
1935   gst_mpd_client_free (mpdclient);
1936 }
1937 
1938 GST_END_TEST;
1939 
1940 /*
1941  * Test parsing Period AdaptationSet SegmentTemplate attributes
1942  *
1943  */
GST_START_TEST(dash_mpdparser_period_adaptationSet_segmentTemplate)1944 GST_START_TEST (dash_mpdparser_period_adaptationSet_segmentTemplate)
1945 {
1946   GstPeriodNode *periodNode;
1947   GstAdaptationSetNode *adaptationSet;
1948   GstSegmentTemplateNode *segmentTemplate;
1949   const gchar *xml =
1950       "<?xml version=\"1.0\"?>"
1951       "<MPD xmlns=\"urn:mpeg:dash:schema:mpd:2011\""
1952       "     profiles=\"urn:mpeg:dash:profile:isoff-main:2011\">"
1953       "  <Period>"
1954       "    <AdaptationSet>"
1955       "      <SegmentTemplate media=\"TestMedia\""
1956       "                       duration=\"1\""
1957       "                       index=\"TestIndex\""
1958       "                       initialization=\"TestInitialization\""
1959       "                       bitstreamSwitching=\"TestBitstreamSwitching\">"
1960       "      </SegmentTemplate></AdaptationSet></Period></MPD>";
1961 
1962   gboolean ret;
1963   GstMpdClient *mpdclient = gst_mpd_client_new ();
1964 
1965   ret = gst_mpd_parse (mpdclient, xml, (gint) strlen (xml));
1966   assert_equals_int (ret, TRUE);
1967 
1968   periodNode = (GstPeriodNode *) mpdclient->mpd_node->Periods->data;
1969   adaptationSet = (GstAdaptationSetNode *) periodNode->AdaptationSets->data;
1970   segmentTemplate = adaptationSet->SegmentTemplate;
1971   assert_equals_string (segmentTemplate->media, "TestMedia");
1972   assert_equals_string (segmentTemplate->index, "TestIndex");
1973   assert_equals_string (segmentTemplate->initialization, "TestInitialization");
1974   assert_equals_string (segmentTemplate->bitstreamSwitching,
1975       "TestBitstreamSwitching");
1976 
1977   gst_mpd_client_free (mpdclient);
1978 }
1979 
1980 GST_END_TEST;
1981 
1982 
GST_START_TEST(dash_mpdparser_period_adaptationSet_representation_segmentTemplate_inherit)1983 GST_START_TEST
1984     (dash_mpdparser_period_adaptationSet_representation_segmentTemplate_inherit)
1985 {
1986   GstPeriodNode *periodNode;
1987   GstAdaptationSetNode *adaptationSet;
1988   GstRepresentationNode *representation;
1989   GstSegmentTemplateNode *segmentTemplate;
1990   const gchar *xml =
1991       "<?xml version=\"1.0\"?>"
1992       "<MPD xmlns=\"urn:mpeg:dash:schema:mpd:2011\""
1993       "     profiles=\"urn:mpeg:dash:profile:isoff-main:2011\">"
1994       "  <Period>"
1995       "    <SegmentTemplate media=\"ParentMedia\" duration=\"1\" "
1996       "                     initialization=\"ParentInitialization\">"
1997       "    </SegmentTemplate>"
1998       "    <AdaptationSet>"
1999       "      <Representation id=\"1\" bandwidth=\"5000\">"
2000       "      <SegmentTemplate media=\"TestMedia\""
2001       "                       index=\"TestIndex\""
2002       "                       bitstreamSwitching=\"TestBitstreamSwitching\">"
2003       "      </SegmentTemplate></Representation></AdaptationSet></Period></MPD>";
2004 
2005   gboolean ret;
2006   GstMpdClient *mpdclient = gst_mpd_client_new ();
2007 
2008   ret = gst_mpd_parse (mpdclient, xml, (gint) strlen (xml));
2009   assert_equals_int (ret, TRUE);
2010 
2011   periodNode = (GstPeriodNode *) mpdclient->mpd_node->Periods->data;
2012   adaptationSet = (GstAdaptationSetNode *) periodNode->AdaptationSets->data;
2013   representation =
2014       (GstRepresentationNode *) adaptationSet->Representations->data;
2015   segmentTemplate = representation->SegmentTemplate;
2016   assert_equals_string (segmentTemplate->media, "TestMedia");
2017   assert_equals_string (segmentTemplate->index, "TestIndex");
2018   assert_equals_string (segmentTemplate->initialization,
2019       "ParentInitialization");
2020   assert_equals_string (segmentTemplate->bitstreamSwitching,
2021       "TestBitstreamSwitching");
2022 
2023   gst_mpd_client_free (mpdclient);
2024 }
2025 
2026 GST_END_TEST;
2027 
GST_START_TEST(dash_mpdparser_period_adaptationSet_representation_segmentBase_inherit)2028 GST_START_TEST
2029     (dash_mpdparser_period_adaptationSet_representation_segmentBase_inherit) {
2030   GstPeriodNode *periodNode;
2031   GstAdaptationSetNode *adaptationSet;
2032   GstRepresentationNode *representation;
2033   GstSegmentBaseType *segmentBase;
2034   const gchar *xml =
2035       "<?xml version=\"1.0\"?>"
2036       "<MPD xmlns=\"urn:mpeg:dash:schema:mpd:2011\""
2037       "     profiles=\"urn:mpeg:dash:profile:isoff-main:2011\">"
2038       "  <Period>"
2039       "    <SegmentBase timescale=\"123456\""
2040       "                 presentationTimeOffset=\"123456789\""
2041       "                 indexRange=\"100-200\""
2042       "                 indexRangeExact=\"true\">"
2043       "      <Initialisation sourceURL=\"TestSourceURL\""
2044       "                      range=\"100-200\" />"
2045       "    </SegmentBase>"
2046       "    <AdaptationSet>"
2047       "      <Representation id=\"1\" bandwidth=\"5000\">"
2048       "      <SegmentBase>"
2049       "      </SegmentBase></Representation></AdaptationSet></Period></MPD>";
2050 
2051   gboolean ret;
2052   GstMpdClient *mpdclient = gst_mpd_client_new ();
2053 
2054   ret = gst_mpd_parse (mpdclient, xml, (gint) strlen (xml));
2055   assert_equals_int (ret, TRUE);
2056 
2057   periodNode = (GstPeriodNode *) mpdclient->mpd_node->Periods->data;
2058   adaptationSet = (GstAdaptationSetNode *) periodNode->AdaptationSets->data;
2059   representation =
2060       (GstRepresentationNode *) adaptationSet->Representations->data;
2061   segmentBase = representation->SegmentBase;
2062   assert_equals_int (segmentBase->timescale, 123456);
2063 
2064   gst_mpd_client_free (mpdclient);
2065 }
2066 
2067 GST_END_TEST;
2068 
2069 /*
2070  * Test parsing Period AdaptationSet SegmentTemplate attributes with
2071  * inheritance
2072  */
GST_START_TEST(dash_mpdparser_adapt_repr_segmentTemplate_inherit)2073 GST_START_TEST (dash_mpdparser_adapt_repr_segmentTemplate_inherit)
2074 {
2075   GstPeriodNode *periodNode;
2076   GstAdaptationSetNode *adaptationSet;
2077   GstSegmentTemplateNode *segmentTemplate;
2078   GstRepresentationNode *representation;
2079   GstMultSegmentBaseType *multSegBaseType;
2080   GstSegmentBaseType *segBaseType;
2081   const gchar *xml =
2082       "<?xml version=\"1.0\"?>"
2083       "<MPD xmlns=\"urn:mpeg:dash:schema:mpd:2011\""
2084       "     profiles=\"urn:mpeg:dash:profile:isoff-main:2011\">"
2085       "  <Period duration=\"PT0H5M0.000S\">"
2086       "    <AdaptationSet maxWidth=\"1280\" maxHeight=\"720\" maxFrameRate=\"50\">"
2087       "      <SegmentTemplate initialization=\"set1_init.mp4\"/>"
2088       "      <Representation id=\"1\" mimeType=\"video/mp4\" codecs=\"avc1.640020\" "
2089       "          width=\"1280\" height=\"720\" frameRate=\"50\" bandwidth=\"30000\">"
2090       "        <SegmentTemplate timescale=\"12800\" media=\"track1_$Number$.m4s\" startNumber=\"1\" duration=\"25600\"/>"
2091       "  </Representation></AdaptationSet></Period></MPD>";
2092 
2093   gboolean ret;
2094   GstMpdClient *mpdclient = gst_mpd_client_new ();
2095 
2096   ret = gst_mpd_parse (mpdclient, xml, (gint) strlen (xml));
2097   assert_equals_int (ret, TRUE);
2098 
2099   periodNode = (GstPeriodNode *) mpdclient->mpd_node->Periods->data;
2100   adaptationSet = (GstAdaptationSetNode *) periodNode->AdaptationSets->data;
2101   representation = (GstRepresentationNode *)
2102       adaptationSet->Representations->data;
2103   segmentTemplate = representation->SegmentTemplate;
2104   fail_if (segmentTemplate == NULL);
2105   multSegBaseType = segmentTemplate->MultSegBaseType;
2106   segBaseType = multSegBaseType->SegBaseType;
2107 
2108   assert_equals_uint64 (segBaseType->timescale, 12800);
2109   assert_equals_uint64 (multSegBaseType->duration, 25600);
2110   assert_equals_uint64 (multSegBaseType->startNumber, 1);
2111   assert_equals_string (segmentTemplate->media, "track1_$Number$.m4s");
2112   assert_equals_string (segmentTemplate->initialization, "set1_init.mp4");
2113 
2114   gst_mpd_client_free (mpdclient);
2115 }
2116 
2117 GST_END_TEST;
2118 /*
2119  * Test parsing Period AdaptationSet SegmentTemplate attributes with
2120  * inheritance
2121  */
GST_START_TEST(dash_mpdparser_period_adaptationSet_segmentTemplate_inherit)2122 GST_START_TEST (dash_mpdparser_period_adaptationSet_segmentTemplate_inherit)
2123 {
2124   GstPeriodNode *periodNode;
2125   GstAdaptationSetNode *adaptationSet;
2126   GstSegmentTemplateNode *segmentTemplate;
2127   const gchar *xml =
2128       "<?xml version=\"1.0\"?>"
2129       "<MPD xmlns=\"urn:mpeg:dash:schema:mpd:2011\""
2130       "     profiles=\"urn:mpeg:dash:profile:isoff-main:2011\">"
2131       "  <Period>"
2132       "    <SegmentTemplate media=\"ParentMedia\" duration=\"1\" "
2133       "                     initialization=\"ParentInitialization\">"
2134       "    </SegmentTemplate>"
2135       "    <AdaptationSet>"
2136       "      <SegmentTemplate media=\"TestMedia\""
2137       "                       duration=\"1\""
2138       "                       index=\"TestIndex\""
2139       "                       bitstreamSwitching=\"TestBitstreamSwitching\">"
2140       "      </SegmentTemplate></AdaptationSet></Period></MPD>";
2141 
2142   gboolean ret;
2143   GstMpdClient *mpdclient = gst_mpd_client_new ();
2144 
2145   ret = gst_mpd_parse (mpdclient, xml, (gint) strlen (xml));
2146   assert_equals_int (ret, TRUE);
2147 
2148   periodNode = (GstPeriodNode *) mpdclient->mpd_node->Periods->data;
2149   adaptationSet = (GstAdaptationSetNode *) periodNode->AdaptationSets->data;
2150   segmentTemplate = adaptationSet->SegmentTemplate;
2151   assert_equals_string (segmentTemplate->media, "TestMedia");
2152   assert_equals_string (segmentTemplate->index, "TestIndex");
2153   assert_equals_string (segmentTemplate->initialization,
2154       "ParentInitialization");
2155   assert_equals_string (segmentTemplate->bitstreamSwitching,
2156       "TestBitstreamSwitching");
2157 
2158   gst_mpd_client_free (mpdclient);
2159 }
2160 
2161 GST_END_TEST;
2162 
2163 /*
2164  * Test parsing Period AdaptationSet Representation attributes
2165  *
2166  */
GST_START_TEST(dash_mpdparser_period_adaptationSet_representation)2167 GST_START_TEST (dash_mpdparser_period_adaptationSet_representation)
2168 {
2169   GstPeriodNode *periodNode;
2170   GstAdaptationSetNode *adaptationSet;
2171   GstRepresentationNode *representation;
2172   const gchar *xml =
2173       "<?xml version=\"1.0\"?>"
2174       "<MPD xmlns=\"urn:mpeg:dash:schema:mpd:2011\""
2175       "     profiles=\"urn:mpeg:dash:profile:isoff-main:2011\">"
2176       "  <Period>"
2177       "    <AdaptationSet>"
2178       "      <Representation id=\"Test_Id\""
2179       "                      bandwidth=\"100\""
2180       "                      qualityRanking=\"200\""
2181       "                      dependencyId=\"one two three\""
2182       "                      mediaStreamStructureId=\"\">"
2183       "      </Representation></AdaptationSet></Period></MPD>";
2184 
2185   gboolean ret;
2186   GstMpdClient *mpdclient = gst_mpd_client_new ();
2187 
2188   ret = gst_mpd_parse (mpdclient, xml, (gint) strlen (xml));
2189   assert_equals_int (ret, TRUE);
2190 
2191   periodNode = (GstPeriodNode *) mpdclient->mpd_node->Periods->data;
2192   adaptationSet = (GstAdaptationSetNode *) periodNode->AdaptationSets->data;
2193   representation = (GstRepresentationNode *)
2194       adaptationSet->Representations->data;
2195   assert_equals_string (representation->id, "Test_Id");
2196   assert_equals_uint64 (representation->bandwidth, 100);
2197   assert_equals_uint64 (representation->qualityRanking, 200);
2198   assert_equals_string (representation->dependencyId[0], "one");
2199   assert_equals_string (representation->dependencyId[1], "two");
2200   assert_equals_string (representation->dependencyId[2], "three");
2201   assert_equals_pointer (representation->dependencyId[3], NULL);
2202   assert_equals_pointer (representation->mediaStreamStructureId[0], NULL);
2203 
2204   gst_mpd_client_free (mpdclient);
2205 }
2206 
2207 GST_END_TEST;
2208 
2209 /*
2210  * Test parsing Period AdaptationSet Representation RepresentationBaseType attributes
2211  *
2212  */
GST_START_TEST(dash_mpdparser_period_adaptationSet_representation_representationBase)2213 GST_START_TEST
2214     (dash_mpdparser_period_adaptationSet_representation_representationBase) {
2215   GstPeriodNode *periodNode;
2216   GstAdaptationSetNode *adaptationSet;
2217   GstRepresentationNode *representation;
2218   GstRepresentationBaseType *representationBase;
2219   const gchar *xml =
2220       "<?xml version=\"1.0\"?>"
2221       "<MPD xmlns=\"urn:mpeg:dash:schema:mpd:2011\""
2222       "     profiles=\"urn:mpeg:dash:profile:isoff-main:2011\">"
2223       "  <Period>"
2224       "    <AdaptationSet>"
2225       "      <Representation id=\"1\" bandwidth=\"250000\">"
2226       "      </Representation></AdaptationSet></Period></MPD>";
2227 
2228   gboolean ret;
2229   GstMpdClient *mpdclient = gst_mpd_client_new ();
2230 
2231   ret = gst_mpd_parse (mpdclient, xml, (gint) strlen (xml));
2232   assert_equals_int (ret, TRUE);
2233 
2234   periodNode = (GstPeriodNode *) mpdclient->mpd_node->Periods->data;
2235   adaptationSet = (GstAdaptationSetNode *) periodNode->AdaptationSets->data;
2236   representation = (GstRepresentationNode *)
2237       adaptationSet->Representations->data;
2238   representationBase = (GstRepresentationBaseType *)
2239       representation->RepresentationBase;
2240   fail_if (representationBase == NULL);
2241 
2242   gst_mpd_client_free (mpdclient);
2243 }
2244 
2245 GST_END_TEST;
2246 
2247 /*
2248  * Test parsing Period AdaptationSet Representation BaseURL attributes
2249  *
2250  */
GST_START_TEST(dash_mpdparser_period_adaptationSet_representation_baseURL)2251 GST_START_TEST (dash_mpdparser_period_adaptationSet_representation_baseURL)
2252 {
2253   GstPeriodNode *periodNode;
2254   GstAdaptationSetNode *adaptationSet;
2255   GstRepresentationNode *representation;
2256   GstBaseURL *baseURL;
2257   const gchar *xml =
2258       "<?xml version=\"1.0\"?>"
2259       "<MPD xmlns=\"urn:mpeg:dash:schema:mpd:2011\""
2260       "     profiles=\"urn:mpeg:dash:profile:isoff-main:2011\">"
2261       "  <Period>"
2262       "    <AdaptationSet>"
2263       "      <Representation id=\"1\" bandwidth=\"250000\">"
2264       "        <BaseURL serviceLocation=\"TestServiceLocation\""
2265       "                 byteRange=\"TestByteRange\">TestBaseURL</BaseURL>"
2266       "      </Representation></AdaptationSet></Period></MPD>";
2267 
2268   gboolean ret;
2269   GstMpdClient *mpdclient = gst_mpd_client_new ();
2270 
2271   ret = gst_mpd_parse (mpdclient, xml, (gint) strlen (xml));
2272   assert_equals_int (ret, TRUE);
2273 
2274   periodNode = (GstPeriodNode *) mpdclient->mpd_node->Periods->data;
2275   adaptationSet = (GstAdaptationSetNode *) periodNode->AdaptationSets->data;
2276   representation = (GstRepresentationNode *)
2277       adaptationSet->Representations->data;
2278   baseURL = (GstBaseURL *) representation->BaseURLs->data;
2279   assert_equals_string (baseURL->baseURL, "TestBaseURL");
2280   assert_equals_string (baseURL->serviceLocation, "TestServiceLocation");
2281   assert_equals_string (baseURL->byteRange, "TestByteRange");
2282 
2283   gst_mpd_client_free (mpdclient);
2284 }
2285 
2286 GST_END_TEST;
2287 
2288 /*
2289  * Test parsing Period AdaptationSet Representation SubRepresentation attributes
2290  *
2291  */
GST_START_TEST(dash_mpdparser_period_adaptationSet_representation_subRepresentation)2292 GST_START_TEST
2293     (dash_mpdparser_period_adaptationSet_representation_subRepresentation) {
2294   GstPeriodNode *periodNode;
2295   GstAdaptationSetNode *adaptationSet;
2296   GstRepresentationNode *representation;
2297   GstSubRepresentationNode *subRepresentation;
2298   const gchar *xml =
2299       "<?xml version=\"1.0\"?>"
2300       "<MPD xmlns=\"urn:mpeg:dash:schema:mpd:2011\""
2301       "     profiles=\"urn:mpeg:dash:profile:isoff-main:2011\">"
2302       "  <Period>"
2303       "    <AdaptationSet>"
2304       "      <Representation id=\"1\" bandwidth=\"250000\">"
2305       "        <SubRepresentation level=\"100\""
2306       "                           dependencyLevel=\"1 2 3\""
2307       "                           bandwidth=\"200\""
2308       "                           contentComponent=\"content1 content2\">"
2309       "        </SubRepresentation>"
2310       "      </Representation></AdaptationSet></Period></MPD>";
2311 
2312   gboolean ret;
2313   GstMpdClient *mpdclient = gst_mpd_client_new ();
2314 
2315   ret = gst_mpd_parse (mpdclient, xml, (gint) strlen (xml));
2316   assert_equals_int (ret, TRUE);
2317 
2318   periodNode = (GstPeriodNode *) mpdclient->mpd_node->Periods->data;
2319   adaptationSet = (GstAdaptationSetNode *) periodNode->AdaptationSets->data;
2320   representation = (GstRepresentationNode *)
2321       adaptationSet->Representations->data;
2322   subRepresentation = (GstSubRepresentationNode *)
2323       representation->SubRepresentations->data;
2324   assert_equals_uint64 (subRepresentation->level, 100);
2325   assert_equals_uint64 (subRepresentation->size, 3);
2326   assert_equals_uint64 (subRepresentation->dependencyLevel[0], 1);
2327   assert_equals_uint64 (subRepresentation->dependencyLevel[1], 2);
2328   assert_equals_uint64 (subRepresentation->dependencyLevel[2], 3);
2329   assert_equals_uint64 (subRepresentation->bandwidth, 200);
2330   assert_equals_string (subRepresentation->contentComponent[0], "content1");
2331   assert_equals_string (subRepresentation->contentComponent[1], "content2");
2332   assert_equals_pointer (subRepresentation->contentComponent[2], NULL);
2333 
2334   gst_mpd_client_free (mpdclient);
2335 }
2336 
2337 GST_END_TEST;
2338 
2339 /*
2340  * Test parsing Period AdaptationSet Representation SubRepresentation
2341  * RepresentationBase attributes
2342  */
GST_START_TEST(dash_mpdparser_period_adaptationSet_representation_subRepresentation_representationBase)2343 GST_START_TEST
2344     (dash_mpdparser_period_adaptationSet_representation_subRepresentation_representationBase)
2345 {
2346   GstPeriodNode *periodNode;
2347   GstAdaptationSetNode *adaptationSet;
2348   GstRepresentationNode *representation;
2349   GstSubRepresentationNode *subRepresentation;
2350   GstRepresentationBaseType *representationBase;
2351   const gchar *xml =
2352       "<?xml version=\"1.0\"?>"
2353       "<MPD xmlns=\"urn:mpeg:dash:schema:mpd:2011\""
2354       "     profiles=\"urn:mpeg:dash:profile:isoff-main:2011\">"
2355       "  <Period>"
2356       "    <AdaptationSet>"
2357       "      <Representation id=\"1\" bandwidth=\"250000\">"
2358       "        <SubRepresentation>"
2359       "        </SubRepresentation>"
2360       "      </Representation></AdaptationSet></Period></MPD>";
2361 
2362   gboolean ret;
2363   GstMpdClient *mpdclient = gst_mpd_client_new ();
2364 
2365   ret = gst_mpd_parse (mpdclient, xml, (gint) strlen (xml));
2366   assert_equals_int (ret, TRUE);
2367 
2368   periodNode = (GstPeriodNode *) mpdclient->mpd_node->Periods->data;
2369   adaptationSet = (GstAdaptationSetNode *) periodNode->AdaptationSets->data;
2370   representation = (GstRepresentationNode *)
2371       adaptationSet->Representations->data;
2372   subRepresentation = (GstSubRepresentationNode *)
2373       representation->SubRepresentations->data;
2374   representationBase = (GstRepresentationBaseType *)
2375       subRepresentation->RepresentationBase;
2376   fail_if (representationBase == NULL);
2377 
2378   gst_mpd_client_free (mpdclient);
2379 }
2380 
2381 GST_END_TEST;
2382 
2383 /*
2384  * Test parsing Period AdaptationSet Representation SegmentBase attributes
2385  *
2386  */
GST_START_TEST(dash_mpdparser_period_adaptationSet_representation_segmentBase)2387 GST_START_TEST (dash_mpdparser_period_adaptationSet_representation_segmentBase)
2388 {
2389   GstPeriodNode *periodNode;
2390   GstAdaptationSetNode *adaptationSet;
2391   GstRepresentationNode *representation;
2392   GstSegmentBaseType *segmentBase;
2393   const gchar *xml =
2394       "<?xml version=\"1.0\"?>"
2395       "<MPD xmlns=\"urn:mpeg:dash:schema:mpd:2011\""
2396       "     profiles=\"urn:mpeg:dash:profile:isoff-main:2011\">"
2397       "  <Period>"
2398       "    <AdaptationSet>"
2399       "      <Representation id=\"1\" bandwidth=\"250000\">"
2400       "        <SegmentBase>"
2401       "        </SegmentBase>"
2402       "      </Representation></AdaptationSet></Period></MPD>";
2403 
2404   gboolean ret;
2405   GstMpdClient *mpdclient = gst_mpd_client_new ();
2406 
2407   ret = gst_mpd_parse (mpdclient, xml, (gint) strlen (xml));
2408   assert_equals_int (ret, TRUE);
2409 
2410   periodNode = (GstPeriodNode *) mpdclient->mpd_node->Periods->data;
2411   adaptationSet = (GstAdaptationSetNode *) periodNode->AdaptationSets->data;
2412   representation = (GstRepresentationNode *)
2413       adaptationSet->Representations->data;
2414   segmentBase = representation->SegmentBase;
2415   fail_if (segmentBase == NULL);
2416 
2417   gst_mpd_client_free (mpdclient);
2418 }
2419 
2420 GST_END_TEST;
2421 
2422 /*
2423  * Test parsing Period AdaptationSet Representation SegmentList attributes
2424  *
2425  */
GST_START_TEST(dash_mpdparser_period_adaptationSet_representation_segmentList)2426 GST_START_TEST (dash_mpdparser_period_adaptationSet_representation_segmentList)
2427 {
2428   GstPeriodNode *periodNode;
2429   GstAdaptationSetNode *adaptationSet;
2430   GstRepresentationNode *representation;
2431   GstSegmentListNode *segmentList;
2432   const gchar *xml =
2433       "<?xml version=\"1.0\"?>"
2434       "<MPD xmlns=\"urn:mpeg:dash:schema:mpd:2011\""
2435       "     profiles=\"urn:mpeg:dash:profile:isoff-main:2011\">"
2436       "  <Period>"
2437       "    <AdaptationSet>"
2438       "      <Representation id=\"1\" bandwidth=\"250000\">"
2439       "        <SegmentList duration=\"1\">"
2440       "        </SegmentList>"
2441       "      </Representation></AdaptationSet></Period></MPD>";
2442 
2443   gboolean ret;
2444   GstMpdClient *mpdclient = gst_mpd_client_new ();
2445 
2446   ret = gst_mpd_parse (mpdclient, xml, (gint) strlen (xml));
2447   assert_equals_int (ret, TRUE);
2448 
2449   periodNode = (GstPeriodNode *) mpdclient->mpd_node->Periods->data;
2450   adaptationSet = (GstAdaptationSetNode *) periodNode->AdaptationSets->data;
2451   representation = (GstRepresentationNode *)
2452       adaptationSet->Representations->data;
2453   segmentList = representation->SegmentList;
2454   fail_if (segmentList == NULL);
2455 
2456   gst_mpd_client_free (mpdclient);
2457 }
2458 
2459 GST_END_TEST;
2460 
2461 /*
2462  * Test parsing Period AdaptationSet Representation SegmentTemplate attributes
2463  *
2464  */
GST_START_TEST(dash_mpdparser_period_adaptationSet_representation_segmentTemplate)2465 GST_START_TEST
2466     (dash_mpdparser_period_adaptationSet_representation_segmentTemplate) {
2467   GstPeriodNode *periodNode;
2468   GstAdaptationSetNode *adaptationSet;
2469   GstRepresentationNode *representation;
2470   GstSegmentTemplateNode *segmentTemplate;
2471   const gchar *xml =
2472       "<?xml version=\"1.0\"?>"
2473       "<MPD xmlns=\"urn:mpeg:dash:schema:mpd:2011\""
2474       "     profiles=\"urn:mpeg:dash:profile:isoff-main:2011\">"
2475       "  <Period>"
2476       "    <AdaptationSet>"
2477       "      <Representation id=\"1\" bandwidth=\"250000\">"
2478       "        <SegmentTemplate duration=\"1\">"
2479       "        </SegmentTemplate>"
2480       "      </Representation></AdaptationSet></Period></MPD>";
2481 
2482   gboolean ret;
2483   GstMpdClient *mpdclient = gst_mpd_client_new ();
2484 
2485   ret = gst_mpd_parse (mpdclient, xml, (gint) strlen (xml));
2486   assert_equals_int (ret, TRUE);
2487 
2488   periodNode = (GstPeriodNode *) mpdclient->mpd_node->Periods->data;
2489   adaptationSet = (GstAdaptationSetNode *) periodNode->AdaptationSets->data;
2490   representation = (GstRepresentationNode *)
2491       adaptationSet->Representations->data;
2492   segmentTemplate = representation->SegmentTemplate;
2493   fail_if (segmentTemplate == NULL);
2494 
2495   gst_mpd_client_free (mpdclient);
2496 }
2497 
2498 GST_END_TEST;
2499 
2500 /*
2501  * Test parsing Period Subset attributes
2502  *
2503  */
GST_START_TEST(dash_mpdparser_period_subset)2504 GST_START_TEST (dash_mpdparser_period_subset)
2505 {
2506   GstPeriodNode *periodNode;
2507   GstSubsetNode *subset;
2508   const gchar *xml =
2509       "<?xml version=\"1.0\"?>"
2510       "<MPD xmlns=\"urn:mpeg:dash:schema:mpd:2011\""
2511       "     profiles=\"urn:mpeg:dash:profile:isoff-main:2011\">"
2512       "  <Period><Subset contains=\"1 2 3\"></Subset></Period></MPD>";
2513 
2514   gboolean ret;
2515   GstMpdClient *mpdclient = gst_mpd_client_new ();
2516 
2517   ret = gst_mpd_parse (mpdclient, xml, (gint) strlen (xml));
2518   assert_equals_int (ret, TRUE);
2519 
2520   periodNode = (GstPeriodNode *) mpdclient->mpd_node->Periods->data;
2521   subset = (GstSubsetNode *) periodNode->Subsets->data;
2522   assert_equals_uint64 (subset->size, 3);
2523   assert_equals_uint64 (subset->contains[0], 1);
2524   assert_equals_uint64 (subset->contains[1], 2);
2525   assert_equals_uint64 (subset->contains[2], 3);
2526 
2527   gst_mpd_client_free (mpdclient);
2528 }
2529 
2530 GST_END_TEST;
2531 
2532 /*
2533  * Test parsing UTCTiming elements
2534  *
2535  */
GST_START_TEST(dash_mpdparser_utctiming)2536 GST_START_TEST (dash_mpdparser_utctiming)
2537 {
2538   const gchar *xml =
2539       "<?xml version=\"1.0\"?>"
2540       "<MPD xmlns=\"urn:mpeg:dash:schema:mpd:2011\""
2541       " profiles=\"urn:mpeg:dash:profile:isoff-main:2011\">"
2542       "<UTCTiming schemeIdUri=\"urn:mpeg:dash:utc:http-xsdate:2014\" value=\"http://time.akamai.com/?iso http://example.time/xsdate\"/>"
2543       "<UTCTiming schemeIdUri=\"urn:mpeg:dash:utc:direct:2014\" value=\"2002-05-30T09:30:10Z \"/>"
2544       "<UTCTiming schemeIdUri=\"urn:mpeg:dash:utc:ntp:2014\" value=\"0.europe.pool.ntp.org 1.europe.pool.ntp.org 2.europe.pool.ntp.org 3.europe.pool.ntp.org\"/>"
2545       "</MPD>";
2546   gboolean ret;
2547   GstMpdClient *mpdclient = gst_mpd_client_new ();
2548   GstMPDUTCTimingType selected_method;
2549   gchar **urls;
2550 
2551   ret = gst_mpd_parse (mpdclient, xml, (gint) strlen (xml));
2552 
2553   assert_equals_int (ret, TRUE);
2554   fail_if (mpdclient->mpd_node == NULL);
2555   fail_if (mpdclient->mpd_node->UTCTiming == NULL);
2556   assert_equals_int (g_list_length (mpdclient->mpd_node->UTCTiming), 3);
2557   urls =
2558       gst_mpd_client_get_utc_timing_sources (mpdclient,
2559       GST_MPD_UTCTIMING_TYPE_HTTP_XSDATE, &selected_method);
2560   fail_if (urls == NULL);
2561   assert_equals_int (selected_method, GST_MPD_UTCTIMING_TYPE_HTTP_XSDATE);
2562   assert_equals_int (g_strv_length (urls), 2);
2563   assert_equals_string (urls[0], "http://time.akamai.com/?iso");
2564   assert_equals_string (urls[1], "http://example.time/xsdate");
2565   urls =
2566       gst_mpd_client_get_utc_timing_sources (mpdclient,
2567       GST_MPD_UTCTIMING_TYPE_HTTP_XSDATE | GST_MPD_UTCTIMING_TYPE_HTTP_ISO,
2568       &selected_method);
2569   fail_if (urls == NULL);
2570   assert_equals_int (selected_method, GST_MPD_UTCTIMING_TYPE_HTTP_XSDATE);
2571   urls =
2572       gst_mpd_client_get_utc_timing_sources (mpdclient,
2573       GST_MPD_UTCTIMING_TYPE_DIRECT, NULL);
2574   fail_if (urls == NULL);
2575   assert_equals_int (g_strv_length (urls), 1);
2576   assert_equals_string (urls[0], "2002-05-30T09:30:10Z ");
2577   urls =
2578       gst_mpd_client_get_utc_timing_sources (mpdclient,
2579       GST_MPD_UTCTIMING_TYPE_HTTP_XSDATE | GST_MPD_UTCTIMING_TYPE_DIRECT,
2580       &selected_method);
2581   fail_if (urls == NULL);
2582   assert_equals_int (selected_method, GST_MPD_UTCTIMING_TYPE_HTTP_XSDATE);
2583   urls =
2584       gst_mpd_client_get_utc_timing_sources (mpdclient,
2585       GST_MPD_UTCTIMING_TYPE_NTP, &selected_method);
2586   fail_if (urls == NULL);
2587   assert_equals_int (selected_method, GST_MPD_UTCTIMING_TYPE_NTP);
2588   assert_equals_int (g_strv_length (urls), 4);
2589   assert_equals_string (urls[0], "0.europe.pool.ntp.org");
2590   assert_equals_string (urls[1], "1.europe.pool.ntp.org");
2591   assert_equals_string (urls[2], "2.europe.pool.ntp.org");
2592   assert_equals_string (urls[3], "3.europe.pool.ntp.org");
2593   gst_mpd_client_free (mpdclient);
2594 }
2595 
2596 GST_END_TEST;
2597 
2598 /*
2599  * Test parsing invalid UTCTiming values:
2600  * - elements with no schemeIdUri property should be rejected
2601  * - elements with no value property should be rejected
2602  * - elements with unrecognised UTCTiming scheme should be rejected
2603  * - elements with empty values should be rejected
2604  *
2605  */
GST_START_TEST(dash_mpdparser_utctiming_invalid_value)2606 GST_START_TEST (dash_mpdparser_utctiming_invalid_value)
2607 {
2608   const gchar *xml =
2609       "<?xml version=\"1.0\"?>"
2610       "<MPD xmlns=\"urn:mpeg:dash:schema:mpd:2011\""
2611       " profiles=\"urn:mpeg:dash:profile:isoff-main:2011\">"
2612       "<UTCTiming invalid_schemeIdUri=\"dummy.uri.scheme\" value=\"dummy value\"/>"
2613       "<UTCTiming schemeIdUri=\"urn:mpeg:dash:utc:ntp:2014\" invalid_value=\"dummy value\"/>"
2614       "<UTCTiming schemeIdUri=\"dummy.uri.scheme\" value=\"dummy value\"/>"
2615       "<UTCTiming schemeIdUri=\"urn:mpeg:dash:utc:ntp:2014\" value=\"\"/>"
2616       "</MPD>";
2617   gboolean ret;
2618   GstMpdClient *mpdclient = gst_mpd_client_new ();
2619 
2620   ret = gst_mpd_parse (mpdclient, xml, (gint) strlen (xml));
2621 
2622   assert_equals_int (ret, TRUE);
2623   fail_if (mpdclient->mpd_node == NULL);
2624   fail_if (mpdclient->mpd_node->UTCTiming != NULL);
2625   gst_mpd_client_free (mpdclient);
2626 }
2627 
2628 GST_END_TEST;
2629 
2630 /*
2631  * Test parsing the type property: value "dynamic"
2632  *
2633  */
GST_START_TEST(dash_mpdparser_type_dynamic)2634 GST_START_TEST (dash_mpdparser_type_dynamic)
2635 {
2636   gboolean isLive;
2637 
2638   const gchar *xml =
2639       "<?xml version=\"1.0\"?>"
2640       "<MPD type=\"dynamic\" xmlns=\"urn:mpeg:dash:schema:mpd:2011\""
2641       "     profiles=\"urn:mpeg:dash:profile:isoff-main:2011\"> </MPD>";
2642 
2643   gboolean ret;
2644   GstMpdClient *mpdclient = gst_mpd_client_new ();
2645 
2646   ret = gst_mpd_parse (mpdclient, xml, (gint) strlen (xml));
2647   assert_equals_int (ret, TRUE);
2648 
2649   isLive = gst_mpd_client_is_live (mpdclient);
2650   assert_equals_int (isLive, 1);
2651 
2652   gst_mpd_client_free (mpdclient);
2653 }
2654 
2655 GST_END_TEST;
2656 
2657 /*
2658  * Validate gst_mpdparser_build_URL_from_template function
2659  *
2660  */
GST_START_TEST(dash_mpdparser_template_parsing)2661 GST_START_TEST (dash_mpdparser_template_parsing)
2662 {
2663   const gchar *id = "TestId";
2664   guint number = 7;
2665   guint bandwidth = 2500;
2666   guint64 time = 100;
2667   gchar *result;
2668 
2669   struct TestUrl
2670   {
2671     const gchar *urlTemplate;
2672     const gchar *expectedResponse;
2673   };
2674 
2675   /* various test scenarios to attempt */
2676   struct TestUrl testUrl[] = {
2677     {"", NULL},                 /* empty string for template */
2678     {"$$", "$"},                /* escaped $ */
2679     {"Number", "Number"},       /* string similar with an identifier, but without $ */
2680     {"Number$Number$", "Number7"},      /* Number identifier */
2681     {"Number$Number$$$", "Number7$"},   /* Number identifier followed by $$ */
2682     {"Number$Number$Number$Number$", "Number7Number7"}, /* series of "Number" string and Number identifier */
2683     {"Representation$RepresentationID$", "RepresentationTestId"},       /* RepresentationID identifier */
2684     {"TestMedia$Bandwidth$$$test", "TestMedia2500$test"},       /* Bandwidth identifier */
2685     {"TestMedia$Time$", "TestMedia100"},        /* Time identifier */
2686     {"TestMedia$Time", NULL},   /* Identifier not finished with $ */
2687     {"Time$Time%d$", NULL},     /* usage of %d (no width) */
2688     {"Time$Time%0d$", "Time100"},       /* usage of format smaller than number of digits */
2689     {"Time$Time%01d$", "Time100"},      /* usage of format smaller than number of digits */
2690     {"Time$Time%05d$", "Time00100"},    /* usage of format bigger than number of digits */
2691     {"Time$Time%05dtest$", "Time00100test"},    /* usage extra text in format */
2692     {"Time$Time%3d$", NULL},    /* incorrect format: width does not start with 0 */
2693     {"Time$Time%0-4d$", NULL},  /* incorrect format: width is not a number */
2694     {"Time$Time%0$", NULL},     /* incorrect format: no d, x or u */
2695     {"Time$Time1%01d$", NULL},  /* incorrect format: does not start with % after identifier */
2696     {"$Bandwidth%/init.mp4v", NULL},    /* incorrect identifier: not finished with $ */
2697     {"$Number%/$Time$.mp4v", NULL},     /* incorrect number of $ separators */
2698     {"$RepresentationID1$", NULL},      /* incorrect identifier */
2699     {"$Bandwidth1$", NULL},     /* incorrect identifier */
2700     {"$Number1$", NULL},        /* incorrect identifier */
2701     {"$RepresentationID%01d$", NULL},   /* incorrect format: RepresentationID does not support formatting */
2702     {"Time$Time%05u$", NULL},   /* %u format */
2703     {"Time$Time%05x$", NULL},   /* %x format */
2704     {"Time$Time%05utest$", NULL},       /* %u format followed by text */
2705     {"Time$Time%05xtest$", NULL},       /* %x format followed by text */
2706     {"Time$Time%05xtest%$", NULL},      /* second % character in format */
2707   };
2708 
2709   guint count = sizeof (testUrl) / sizeof (testUrl[0]);
2710   gint i;
2711 
2712   for (i = 0; i < count; i++) {
2713     result =
2714         gst_mpdparser_build_URL_from_template (testUrl[i].urlTemplate, id,
2715         number, bandwidth, time);
2716     assert_equals_string (result, testUrl[i].expectedResponse);
2717     g_free (result);
2718   }
2719 }
2720 
2721 GST_END_TEST;
2722 
2723 /*
2724  * Test handling isoff ondemand profile
2725  *
2726  */
GST_START_TEST(dash_mpdparser_isoff_ondemand_profile)2727 GST_START_TEST (dash_mpdparser_isoff_ondemand_profile)
2728 {
2729   gboolean hasOnDemandProfile;
2730 
2731   const gchar *xml =
2732       "<?xml version=\"1.0\"?>"
2733       "<MPD xmlns=\"urn:mpeg:dash:schema:mpd:2011\""
2734       "     profiles=\"urn:mpeg:dash:profile:isoff-on-demand:2011\"></MPD>";
2735 
2736   gboolean ret;
2737   GstMpdClient *mpdclient = gst_mpd_client_new ();
2738 
2739   ret = gst_mpd_parse (mpdclient, xml, (gint) strlen (xml));
2740   assert_equals_int (ret, TRUE);
2741 
2742   hasOnDemandProfile = gst_mpd_client_has_isoff_ondemand_profile (mpdclient);
2743   assert_equals_int (hasOnDemandProfile, 1);
2744 
2745   gst_mpd_client_free (mpdclient);
2746 }
2747 
2748 GST_END_TEST;
2749 
2750 /*
2751  * Test handling GstDateTime
2752  *
2753  */
GST_START_TEST(dash_mpdparser_GstDateTime)2754 GST_START_TEST (dash_mpdparser_GstDateTime)
2755 {
2756   gint64 delta;
2757   GstDateTime *time1;
2758   GstDateTime *time2;
2759   GstDateTime *time3;
2760   GDateTime *g_time2;
2761   GDateTime *g_time3;
2762 
2763   time1 = gst_date_time_new_from_iso8601_string ("2012-06-23T23:30:59Z");
2764   time2 = gst_date_time_new_from_iso8601_string ("2012-06-23T23:31:00Z");
2765 
2766   delta = gst_mpd_client_calculate_time_difference (time1, time2);
2767   assert_equals_int64 (delta, 1 * GST_SECOND);
2768 
2769   time3 =
2770       gst_mpd_client_add_time_difference (time1, GST_TIME_AS_USECONDS (delta));
2771 
2772   /* convert to GDateTime in order to compare time2 and time 3 */
2773   g_time2 = gst_date_time_to_g_date_time (time2);
2774   g_time3 = gst_date_time_to_g_date_time (time3);
2775   fail_if (g_date_time_compare (g_time2, g_time3) != 0);
2776 
2777   gst_date_time_unref (time1);
2778   gst_date_time_unref (time2);
2779   gst_date_time_unref (time3);
2780   g_date_time_unref (g_time2);
2781   g_date_time_unref (g_time3);
2782 }
2783 
2784 GST_END_TEST;
2785 
2786 /*
2787  * Test bitstreamSwitching inheritance from Period to AdaptationSet
2788  *
2789  * Description of bistreamSwitching attribute in Period:
2790  * "When set to ‘true’, this is equivalent as if the
2791  * AdaptationSet@bitstreamSwitching for each Adaptation Set contained in this
2792  * Period is set to 'true'. In this case, the AdaptationSet@bitstreamSwitching
2793  * attribute shall not be set to 'false' for any Adaptation Set in this Period"
2794  *
2795  */
GST_START_TEST(dash_mpdparser_bitstreamSwitching_inheritance)2796 GST_START_TEST (dash_mpdparser_bitstreamSwitching_inheritance)
2797 {
2798   GList *adaptationSets;
2799   GstAdaptationSetNode *adapt_set;
2800   guint activeStreams;
2801   GstActiveStream *activeStream;
2802   GstCaps *caps;
2803   GstStructure *s;
2804   gboolean bitstreamSwitchingFlag;
2805 
2806   const gchar *xml =
2807       "<?xml version=\"1.0\"?>"
2808       "<MPD xmlns=\"urn:mpeg:dash:schema:mpd:2011\""
2809       "     profiles=\"urn:mpeg:dash:profile:isoff-main:2011\">"
2810       "  <Period id=\"Period0\""
2811       "          duration=\"P0Y0M1DT1H1M1S\""
2812       "          bitstreamSwitching=\"true\">"
2813       "    <AdaptationSet id=\"1\""
2814       "                   mimeType=\"video/mp4\">"
2815       "      <Representation id=\"1\" bandwidth=\"250000\">"
2816       "      </Representation>"
2817       "    </AdaptationSet>"
2818       "    <AdaptationSet id=\"2\""
2819       "                   mimeType=\"audio\""
2820       "                   bitstreamSwitching=\"false\">"
2821       "      <Representation id=\"2\" bandwidth=\"250000\">"
2822       "      </Representation></AdaptationSet></Period></MPD>";
2823 
2824   gboolean ret;
2825   GstMpdClient *mpdclient = gst_mpd_client_new ();
2826 
2827   ret = gst_mpd_parse (mpdclient, xml, (gint) strlen (xml));
2828   assert_equals_int (ret, TRUE);
2829 
2830   /* process the xml data */
2831   ret = gst_mpd_client_setup_media_presentation (mpdclient, GST_CLOCK_TIME_NONE,
2832       -1, NULL);
2833   assert_equals_int (ret, TRUE);
2834 
2835   /* get the list of adaptation sets of the first period */
2836   adaptationSets = gst_mpd_client_get_adaptation_sets (mpdclient);
2837   fail_if (adaptationSets == NULL);
2838 
2839   /* setup streaming from the first adaptation set */
2840   adapt_set = (GstAdaptationSetNode *) g_list_nth_data (adaptationSets, 0);
2841   fail_if (adapt_set == NULL);
2842   ret = gst_mpd_client_setup_streaming (mpdclient, adapt_set);
2843   assert_equals_int (ret, TRUE);
2844 
2845   /* setup streaming from the second adaptation set */
2846   adapt_set = (GstAdaptationSetNode *) g_list_nth_data (adaptationSets, 1);
2847   fail_if (adapt_set == NULL);
2848   ret = gst_mpd_client_setup_streaming (mpdclient, adapt_set);
2849   assert_equals_int (ret, TRUE);
2850 
2851   /* 2 active streams */
2852   activeStreams = gst_mpdparser_get_nb_active_stream (mpdclient);
2853   assert_equals_int (activeStreams, 2);
2854 
2855   /* get details of the first active stream */
2856   activeStream = gst_mpdparser_get_active_stream_by_index (mpdclient, 0);
2857   fail_if (activeStream == NULL);
2858 
2859   assert_equals_int (activeStream->mimeType, GST_STREAM_VIDEO);
2860   caps = gst_mpd_client_get_stream_caps (activeStream);
2861   fail_unless (caps != NULL);
2862   s = gst_caps_get_structure (caps, 0);
2863   assert_equals_string (gst_structure_get_name (s), "video/quicktime");
2864   gst_caps_unref (caps);
2865 
2866   /* inherited from Period's bitstreamSwitching */
2867   bitstreamSwitchingFlag =
2868       gst_mpd_client_get_bitstream_switching_flag (activeStream);
2869   assert_equals_int (bitstreamSwitchingFlag, TRUE);
2870 
2871   /* get details of the second active stream */
2872   activeStream = gst_mpdparser_get_active_stream_by_index (mpdclient, 1);
2873   fail_if (activeStream == NULL);
2874 
2875   assert_equals_int (activeStream->mimeType, GST_STREAM_AUDIO);
2876   caps = gst_mpd_client_get_stream_caps (activeStream);
2877   fail_unless (caps != NULL);
2878   s = gst_caps_get_structure (caps, 0);
2879   assert_equals_string (gst_structure_get_name (s), "audio");
2880   gst_caps_unref (caps);
2881 
2882   /* set to FALSE in our example, but overwritten to TRUE by Period's
2883    * bitstreamSwitching
2884    */
2885   bitstreamSwitchingFlag =
2886       gst_mpd_client_get_bitstream_switching_flag (activeStream);
2887   assert_equals_int (bitstreamSwitchingFlag, TRUE);
2888 
2889   gst_mpd_client_free (mpdclient);
2890 }
2891 
2892 GST_END_TEST;
2893 
2894 /*
2895  * Test various duration formats
2896  */
GST_START_TEST(dash_mpdparser_various_duration_formats)2897 GST_START_TEST (dash_mpdparser_various_duration_formats)
2898 {
2899   GstPeriodNode *periodNode;
2900   const gchar *xml =
2901       "<?xml version=\"1.0\"?>"
2902       "<MPD xmlns=\"urn:mpeg:dash:schema:mpd:2011\""
2903       "     profiles=\"urn:mpeg:dash:profile:isoff-main:2011\""
2904       "     availabilityStartTime=\"2015-03-24T0:0:0\""
2905       "     mediaPresentationDuration=\"P100Y\">"
2906       "  <Period id=\"Period0\" start=\"PT1S\"></Period>"
2907       "  <Period id=\"Period1\" start=\"PT1.5S\"></Period>"
2908       "  <Period id=\"Period2\" start=\"PT1,7S\"></Period>"
2909       "  <Period id=\"Period3\" start=\"PT1M\"></Period>"
2910       "  <Period id=\"Period4\" start=\"PT1H\"></Period>"
2911       "  <Period id=\"Period5\" start=\"P1D\"></Period>"
2912       "  <Period id=\"Period6\" start=\"P1M\"></Period>"
2913       "  <Period id=\"Period7\" start=\"P1Y\"></Period></MPD>";
2914 
2915   gboolean ret;
2916   GstMpdClient *mpdclient = gst_mpd_client_new ();
2917 
2918   ret = gst_mpd_parse (mpdclient, xml, (gint) strlen (xml));
2919   assert_equals_int (ret, TRUE);
2920 
2921   ret =
2922       gst_mpd_client_setup_media_presentation (mpdclient, GST_CLOCK_TIME_NONE,
2923       -1, NULL);
2924   assert_equals_int (ret, TRUE);
2925 
2926   periodNode =
2927       (GstPeriodNode *) g_list_nth_data (mpdclient->mpd_node->Periods, 0);
2928   assert_equals_string (periodNode->id, "Period0");
2929   assert_equals_uint64 (periodNode->start,
2930       duration_to_ms (0, 0, 0, 0, 0, 1, 0));
2931 
2932   periodNode =
2933       (GstPeriodNode *) g_list_nth_data (mpdclient->mpd_node->Periods, 1);
2934   assert_equals_string (periodNode->id, "Period1");
2935   assert_equals_uint64 (periodNode->start,
2936       duration_to_ms (0, 0, 0, 0, 0, 1, 500));
2937 
2938   periodNode =
2939       (GstPeriodNode *) g_list_nth_data (mpdclient->mpd_node->Periods, 2);
2940   assert_equals_string (periodNode->id, "Period2");
2941   assert_equals_uint64 (periodNode->start,
2942       duration_to_ms (0, 0, 0, 0, 0, 1, 700));
2943 
2944   periodNode =
2945       (GstPeriodNode *) g_list_nth_data (mpdclient->mpd_node->Periods, 3);
2946   assert_equals_string (periodNode->id, "Period3");
2947   assert_equals_uint64 (periodNode->start,
2948       duration_to_ms (0, 0, 0, 0, 1, 0, 0));
2949 
2950   periodNode =
2951       (GstPeriodNode *) g_list_nth_data (mpdclient->mpd_node->Periods, 4);
2952   assert_equals_string (periodNode->id, "Period4");
2953   assert_equals_uint64 (periodNode->start,
2954       duration_to_ms (0, 0, 0, 1, 0, 0, 0));
2955 
2956   periodNode =
2957       (GstPeriodNode *) g_list_nth_data (mpdclient->mpd_node->Periods, 5);
2958   assert_equals_string (periodNode->id, "Period5");
2959   assert_equals_uint64 (periodNode->start,
2960       duration_to_ms (0, 0, 1, 0, 0, 0, 0));
2961 
2962   periodNode =
2963       (GstPeriodNode *) g_list_nth_data (mpdclient->mpd_node->Periods, 6);
2964   assert_equals_string (periodNode->id, "Period6");
2965   assert_equals_uint64 (periodNode->start,
2966       duration_to_ms (0, 1, 0, 0, 0, 0, 0));
2967 
2968   periodNode =
2969       (GstPeriodNode *) g_list_nth_data (mpdclient->mpd_node->Periods, 7);
2970   assert_equals_string (periodNode->id, "Period7");
2971   assert_equals_uint64 (periodNode->start,
2972       duration_to_ms (1, 0, 0, 0, 0, 0, 0));
2973 
2974   gst_mpd_client_free (mpdclient);
2975 }
2976 
2977 GST_END_TEST;
2978 
2979 /*
2980  * Test media presentation setup
2981  *
2982  */
GST_START_TEST(dash_mpdparser_setup_media_presentation)2983 GST_START_TEST (dash_mpdparser_setup_media_presentation)
2984 {
2985   const gchar *xml =
2986       "<?xml version=\"1.0\"?>"
2987       "<MPD xmlns=\"urn:mpeg:dash:schema:mpd:2011\""
2988       "     profiles=\"urn:mpeg:dash:profile:isoff-main:2011\">"
2989       "  <Period id=\"Period0\""
2990       "          duration=\"P0Y0M1DT1H1M1S\"></Period></MPD>";
2991 
2992   gboolean ret;
2993   GstMpdClient *mpdclient = gst_mpd_client_new ();
2994 
2995   ret = gst_mpd_parse (mpdclient, xml, (gint) strlen (xml));
2996   assert_equals_int (ret, TRUE);
2997 
2998   /* process the xml data */
2999   ret =
3000       gst_mpd_client_setup_media_presentation (mpdclient, GST_CLOCK_TIME_NONE,
3001       -1, NULL);
3002   assert_equals_int (ret, TRUE);
3003 
3004   gst_mpd_client_free (mpdclient);
3005 }
3006 
3007 GST_END_TEST;
3008 
3009 /*
3010  * Test setting a stream
3011  *
3012  */
GST_START_TEST(dash_mpdparser_setup_streaming)3013 GST_START_TEST (dash_mpdparser_setup_streaming)
3014 {
3015   GList *adaptationSets;
3016   GstAdaptationSetNode *adapt_set;
3017 
3018   const gchar *xml =
3019       "<?xml version=\"1.0\"?>"
3020       "<MPD xmlns=\"urn:mpeg:dash:schema:mpd:2011\""
3021       "     profiles=\"urn:mpeg:dash:profile:isoff-main:2011\">"
3022       "  <Period id=\"Period0\""
3023       "          duration=\"P0Y0M1DT1H1M1S\">"
3024       "    <AdaptationSet id=\"1\""
3025       "                   mimeType=\"video/mp4\">"
3026       "      <Representation id=\"1\" bandwidth=\"250000\">"
3027       "      </Representation></AdaptationSet></Period></MPD>";
3028 
3029   gboolean ret;
3030   GstMpdClient *mpdclient = gst_mpd_client_new ();
3031 
3032   ret = gst_mpd_parse (mpdclient, xml, (gint) strlen (xml));
3033   assert_equals_int (ret, TRUE);
3034 
3035   /* process the xml data */
3036   ret =
3037       gst_mpd_client_setup_media_presentation (mpdclient, GST_CLOCK_TIME_NONE,
3038       -1, NULL);
3039   assert_equals_int (ret, TRUE);
3040 
3041   /* get the first adaptation set of the first period */
3042   adaptationSets = gst_mpd_client_get_adaptation_sets (mpdclient);
3043   fail_if (adaptationSets == NULL);
3044   adapt_set = (GstAdaptationSetNode *) adaptationSets->data;
3045   fail_if (adapt_set == NULL);
3046 
3047   /* setup streaming from the adaptation set */
3048   ret = gst_mpd_client_setup_streaming (mpdclient, adapt_set);
3049   assert_equals_int (ret, TRUE);
3050 
3051   gst_mpd_client_free (mpdclient);
3052 }
3053 
3054 GST_END_TEST;
3055 
3056 /*
3057  * Test handling Period selection
3058  *
3059  */
GST_START_TEST(dash_mpdparser_period_selection)3060 GST_START_TEST (dash_mpdparser_period_selection)
3061 {
3062   const gchar *periodName;
3063   guint periodIndex;
3064 
3065   const gchar *xml =
3066       "<?xml version=\"1.0\"?>"
3067       "<MPD xmlns=\"urn:mpeg:dash:schema:mpd:2011\""
3068       "     profiles=\"urn:mpeg:dash:profile:isoff-main:2011\""
3069       "     mediaPresentationDuration=\"P0Y0M1DT1H4M3S\">"
3070       "  <Period id=\"Period0\" duration=\"P0Y0M1DT1H1M1S\"></Period>"
3071       "  <Period id=\"Period1\"></Period>"
3072       "  <Period id=\"Period2\" start=\"P0Y0M1DT1H3M3S\"></Period></MPD>";
3073 
3074   gboolean ret;
3075   GstMpdClient *mpdclient = gst_mpd_client_new ();
3076 
3077   ret = gst_mpd_parse (mpdclient, xml, (gint) strlen (xml));
3078   assert_equals_int (ret, TRUE);
3079 
3080   /* period_idx should be 0 and we should have no active periods */
3081   assert_equals_uint64 (mpdclient->period_idx, 0);
3082   fail_unless (mpdclient->periods == NULL);
3083 
3084   /* process the xml data */
3085   ret =
3086       gst_mpd_client_setup_media_presentation (mpdclient, GST_CLOCK_TIME_NONE,
3087       -1, NULL);
3088   assert_equals_int (ret, TRUE);
3089 
3090   /* check the periods */
3091   fail_unless (mpdclient->periods != NULL);
3092   periodName = gst_mpd_client_get_period_id (mpdclient);
3093   assert_equals_string (periodName, "Period0");
3094 
3095   ret = gst_mpd_client_set_period_index (mpdclient, 1);
3096   assert_equals_int (ret, TRUE);
3097   periodName = gst_mpd_client_get_period_id (mpdclient);
3098   assert_equals_string (periodName, "Period1");
3099 
3100   ret = gst_mpd_client_set_period_index (mpdclient, 2);
3101   assert_equals_int (ret, TRUE);
3102   periodName = gst_mpd_client_get_period_id (mpdclient);
3103   assert_equals_string (periodName, "Period2");
3104 
3105   ret = gst_mpd_client_has_next_period (mpdclient);
3106   assert_equals_int (ret, FALSE);
3107   ret = gst_mpd_client_has_previous_period (mpdclient);
3108   assert_equals_int (ret, TRUE);
3109 
3110   ret = gst_mpd_client_set_period_index (mpdclient, 0);
3111   assert_equals_int (ret, TRUE);
3112   ret = gst_mpd_client_has_next_period (mpdclient);
3113   assert_equals_int (ret, TRUE);
3114   ret = gst_mpd_client_has_previous_period (mpdclient);
3115   assert_equals_int (ret, FALSE);
3116 
3117   ret = gst_mpd_client_set_period_id (mpdclient, "Period1");
3118   assert_equals_int (ret, TRUE);
3119   periodIndex = gst_mpd_client_get_period_index (mpdclient);
3120   assert_equals_uint64 (periodIndex, 1);
3121 
3122   gst_mpd_client_free (mpdclient);
3123 }
3124 
3125 GST_END_TEST;
3126 
3127 /*
3128  * Test handling Period selection based on time
3129  *
3130  */
GST_START_TEST(dash_mpdparser_get_period_at_time)3131 GST_START_TEST (dash_mpdparser_get_period_at_time)
3132 {
3133   guint periodIndex;
3134   GstDateTime *time;
3135 
3136   const gchar *xml =
3137       "<?xml version=\"1.0\"?>"
3138       "<MPD xmlns=\"urn:mpeg:dash:schema:mpd:2011\""
3139       "     profiles=\"urn:mpeg:dash:profile:isoff-main:2011\""
3140       "     availabilityStartTime=\"2015-03-24T0:0:0\""
3141       "     mediaPresentationDuration=\"P0Y0M1DT1H4M3S\">"
3142       "  <Period id=\"Period0\" duration=\"P0Y0M1DT1H1M1S\"></Period>"
3143       "  <Period id=\"Period1\"></Period>"
3144       "  <Period id=\"Period2\" start=\"P0Y0M1DT1H3M3S\"></Period></MPD>";
3145 
3146   gboolean ret;
3147   GstMpdClient *mpdclient = gst_mpd_client_new ();
3148 
3149   ret = gst_mpd_parse (mpdclient, xml, (gint) strlen (xml));
3150   assert_equals_int (ret, TRUE);
3151 
3152   /* process the xml data */
3153   ret =
3154       gst_mpd_client_setup_media_presentation (mpdclient, GST_CLOCK_TIME_NONE,
3155       -1, NULL);
3156   assert_equals_int (ret, TRUE);
3157 
3158   /* request period for a time before availabilityStartTime, expect period index 0 */
3159   time = gst_date_time_new_from_iso8601_string ("2015-03-23T23:30:59Z");
3160   periodIndex = gst_mpd_client_get_period_index_at_time (mpdclient, time);
3161   gst_date_time_unref (time);
3162   assert_equals_int (periodIndex, 0);
3163 
3164   /* request period for a time from period 0 */
3165   time = gst_date_time_new_from_iso8601_string ("2015-03-24T23:30:59Z");
3166   periodIndex = gst_mpd_client_get_period_index_at_time (mpdclient, time);
3167   gst_date_time_unref (time);
3168   assert_equals_int (periodIndex, 0);
3169 
3170   /* request period for a time from period 1 */
3171   time = gst_date_time_new_from_iso8601_string ("2015-03-25T1:1:1Z");
3172   periodIndex = gst_mpd_client_get_period_index_at_time (mpdclient, time);
3173   gst_date_time_unref (time);
3174   assert_equals_int (periodIndex, 1);
3175 
3176   /* request period for a time from period 2 */
3177   time = gst_date_time_new_from_iso8601_string ("2015-03-25T1:3:3Z");
3178   periodIndex = gst_mpd_client_get_period_index_at_time (mpdclient, time);
3179   gst_date_time_unref (time);
3180   assert_equals_int (periodIndex, 2);
3181 
3182   /* request period for a time after mediaPresentationDuration, expect period index G_MAXUINT */
3183   time = gst_date_time_new_from_iso8601_string ("2015-03-25T1:4:3Z");
3184   periodIndex = gst_mpd_client_get_period_index_at_time (mpdclient, time);
3185   gst_date_time_unref (time);
3186   assert_equals_int (periodIndex, G_MAXUINT);
3187 
3188   gst_mpd_client_free (mpdclient);
3189 }
3190 
3191 GST_END_TEST;
3192 
3193 /*
3194  * Test handling Adaptation sets
3195  *
3196  */
GST_START_TEST(dash_mpdparser_adaptationSet_handling)3197 GST_START_TEST (dash_mpdparser_adaptationSet_handling)
3198 {
3199   const gchar *periodName;
3200   guint adaptation_sets_count;
3201   GList *adaptationSets, *it;
3202   guint count = 0;
3203 
3204   const gchar *xml =
3205       "<?xml version=\"1.0\"?>"
3206       "<MPD xmlns=\"urn:mpeg:dash:schema:mpd:2011\""
3207       "     profiles=\"urn:mpeg:dash:profile:isoff-main:2011\">"
3208       "  <Period id=\"Period0\" duration=\"P0Y0M1DT1H1M1S\">"
3209       "    <AdaptationSet id=\"1\"></AdaptationSet>"
3210       "  </Period>"
3211       "  <Period id=\"Period1\" duration=\"P0Y0M1DT1H1M1S\">"
3212       "    <AdaptationSet id=\"10\"></AdaptationSet>"
3213       "    <AdaptationSet id=\"11\"></AdaptationSet></Period></MPD>";
3214 
3215   gboolean ret;
3216   GstMpdClient *mpdclient = gst_mpd_client_new ();
3217 
3218   ret = gst_mpd_parse (mpdclient, xml, (gint) strlen (xml));
3219   assert_equals_int (ret, TRUE);
3220 
3221   /* process the xml data */
3222   ret =
3223       gst_mpd_client_setup_media_presentation (mpdclient, GST_CLOCK_TIME_NONE,
3224       -1, NULL);
3225   assert_equals_int (ret, TRUE);
3226 
3227   /* period0 has 1 adaptation set */
3228   fail_unless (mpdclient->periods != NULL);
3229   periodName = gst_mpd_client_get_period_id (mpdclient);
3230   assert_equals_string (periodName, "Period0");
3231   adaptation_sets_count = gst_mpdparser_get_nb_adaptationSet (mpdclient);
3232   assert_equals_int (adaptation_sets_count, 1);
3233 
3234   /* period1 has 2 adaptation set */
3235   ret = gst_mpd_client_set_period_id (mpdclient, "Period1");
3236   assert_equals_int (ret, TRUE);
3237   adaptation_sets_count = gst_mpdparser_get_nb_adaptationSet (mpdclient);
3238   assert_equals_int (adaptation_sets_count, 2);
3239 
3240   /* check the id for the 2 adaptation sets from period 1 */
3241   adaptationSets = gst_mpd_client_get_adaptation_sets (mpdclient);
3242   fail_if (adaptationSets == NULL);
3243 
3244   for (it = adaptationSets; it; it = g_list_next (it)) {
3245     GstAdaptationSetNode *adapt_set;
3246     adapt_set = (GstAdaptationSetNode *) it->data;
3247     fail_if (adapt_set == NULL);
3248 
3249     assert_equals_int (adapt_set->id, 10 + count);
3250     count++;
3251   }
3252 
3253   gst_mpd_client_free (mpdclient);
3254 }
3255 
3256 GST_END_TEST;
3257 
3258 /*
3259  * Test handling Representation selection
3260  *
3261  */
GST_START_TEST(dash_mpdparser_representation_selection)3262 GST_START_TEST (dash_mpdparser_representation_selection)
3263 {
3264   GList *adaptationSets;
3265   GstAdaptationSetNode *adaptationSetNode;
3266   GList *representations;
3267   gint represendationIndex;
3268 
3269   const gchar *xml =
3270       "<?xml version=\"1.0\"?>"
3271       "<MPD xmlns=\"urn:mpeg:dash:schema:mpd:2011\""
3272       "     profiles=\"urn:mpeg:dash:profile:isoff-main:2011\">"
3273       "  <Period id=\"Period0\" duration=\"P0Y0M1DT1H1M1S\">"
3274       "    <AdaptationSet id=\"1\" mimeType=\"video/mp4\">"
3275       "      <Representation id=\"v0\" bandwidth=\"500000\"></Representation>"
3276       "      <Representation id=\"v1\" bandwidth=\"250000\"></Representation>"
3277       "    </AdaptationSet></Period></MPD>";
3278 
3279   gboolean ret;
3280   GstMpdClient *mpdclient = gst_mpd_client_new ();
3281 
3282   ret = gst_mpd_parse (mpdclient, xml, (gint) strlen (xml));
3283   assert_equals_int (ret, TRUE);
3284 
3285   /* process the xml data */
3286   ret =
3287       gst_mpd_client_setup_media_presentation (mpdclient, GST_CLOCK_TIME_NONE,
3288       -1, NULL);
3289   assert_equals_int (ret, TRUE);
3290 
3291   adaptationSets = gst_mpd_client_get_adaptation_sets (mpdclient);
3292   fail_if (adaptationSets == NULL);
3293 
3294   adaptationSetNode = adaptationSets->data;
3295   fail_if (adaptationSetNode == NULL);
3296   assert_equals_int (adaptationSetNode->id, 1);
3297 
3298   representations = adaptationSetNode->Representations;
3299   fail_if (representations == NULL);
3300 
3301   represendationIndex =
3302       gst_mpdparser_get_rep_idx_with_min_bandwidth (representations);
3303   assert_equals_int (represendationIndex, 1);
3304 
3305   represendationIndex =
3306       gst_mpdparser_get_rep_idx_with_max_bandwidth (representations, 0, 0, 0, 0,
3307       1);
3308   assert_equals_int (represendationIndex, 1);
3309 
3310   represendationIndex =
3311       gst_mpdparser_get_rep_idx_with_max_bandwidth (representations, 100000, 0,
3312       0, 0, 1);
3313   assert_equals_int (represendationIndex, -1);
3314 
3315   represendationIndex =
3316       gst_mpdparser_get_rep_idx_with_max_bandwidth (representations, 300000, 0,
3317       0, 0, 1);
3318   assert_equals_int (represendationIndex, 1);
3319 
3320   represendationIndex =
3321       gst_mpdparser_get_rep_idx_with_max_bandwidth (representations, 500000, 0,
3322       0, 0, 1);
3323   assert_equals_int (represendationIndex, 0);
3324 
3325   gst_mpd_client_free (mpdclient);
3326 }
3327 
3328 GST_END_TEST;
3329 
3330 /*
3331  * Test handling Active stream selection
3332  *
3333  */
GST_START_TEST(dash_mpdparser_activeStream_selection)3334 GST_START_TEST (dash_mpdparser_activeStream_selection)
3335 {
3336   GList *adaptationSets;
3337   GstAdaptationSetNode *adapt_set;
3338   guint activeStreams;
3339   GstActiveStream *activeStream;
3340 
3341   const gchar *xml =
3342       "<?xml version=\"1.0\"?>"
3343       "<MPD xmlns=\"urn:mpeg:dash:schema:mpd:2011\""
3344       "     profiles=\"urn:mpeg:dash:profile:isoff-main:2011\">"
3345       "  <Period id=\"Period0\" duration=\"P0Y0M1DT1H1M1S\">"
3346       "    <AdaptationSet id=\"1\" mimeType=\"video/mp4\">"
3347       "      <Representation id=\"1\" bandwidth=\"250000\">"
3348       "      </Representation>"
3349       "    </AdaptationSet>"
3350       "    <AdaptationSet id=\"2\" mimeType=\"audio\">"
3351       "      <Representation id=\"2\" bandwidth=\"250000\">"
3352       "      </Representation>"
3353       "    </AdaptationSet>"
3354       "    <AdaptationSet id=\"3\" mimeType=\"application\">"
3355       "      <Representation id=\"3\" bandwidth=\"250000\">"
3356       "      </Representation></AdaptationSet></Period></MPD>";
3357 
3358   gboolean ret;
3359   GstMpdClient *mpdclient = gst_mpd_client_new ();
3360 
3361   ret = gst_mpd_parse (mpdclient, xml, (gint) strlen (xml));
3362   assert_equals_int (ret, TRUE);
3363 
3364   /* process the xml data */
3365   ret =
3366       gst_mpd_client_setup_media_presentation (mpdclient, GST_CLOCK_TIME_NONE,
3367       -1, NULL);
3368   assert_equals_int (ret, TRUE);
3369 
3370   /* get the list of adaptation sets of the first period */
3371   adaptationSets = gst_mpd_client_get_adaptation_sets (mpdclient);
3372   fail_if (adaptationSets == NULL);
3373 
3374   /* no active streams yet */
3375   activeStreams = gst_mpdparser_get_nb_active_stream (mpdclient);
3376   assert_equals_int (activeStreams, 0);
3377 
3378   /* setup streaming from the first adaptation set */
3379   adapt_set = (GstAdaptationSetNode *) g_list_nth_data (adaptationSets, 0);
3380   fail_if (adapt_set == NULL);
3381   ret = gst_mpd_client_setup_streaming (mpdclient, adapt_set);
3382   assert_equals_int (ret, TRUE);
3383 
3384   /* 1 active streams */
3385   activeStreams = gst_mpdparser_get_nb_active_stream (mpdclient);
3386   assert_equals_int (activeStreams, 1);
3387 
3388   /* setup streaming from the second adaptation set */
3389   adapt_set = (GstAdaptationSetNode *) g_list_nth_data (adaptationSets, 1);
3390   fail_if (adapt_set == NULL);
3391   ret = gst_mpd_client_setup_streaming (mpdclient, adapt_set);
3392   assert_equals_int (ret, TRUE);
3393 
3394   /* 2 active streams */
3395   activeStreams = gst_mpdparser_get_nb_active_stream (mpdclient);
3396   assert_equals_int (activeStreams, 2);
3397 
3398   /* setup streaming from the third adaptation set */
3399   adapt_set = (GstAdaptationSetNode *) g_list_nth_data (adaptationSets, 2);
3400   fail_if (adapt_set == NULL);
3401   ret = gst_mpd_client_setup_streaming (mpdclient, adapt_set);
3402   assert_equals_int (ret, TRUE);
3403 
3404   /* 3 active streams */
3405   activeStreams = gst_mpdparser_get_nb_active_stream (mpdclient);
3406   assert_equals_int (activeStreams, 3);
3407 
3408   /* get details of the first active stream */
3409   activeStream = gst_mpdparser_get_active_stream_by_index (mpdclient, 0);
3410   fail_if (activeStream == NULL);
3411   assert_equals_int (activeStream->mimeType, GST_STREAM_VIDEO);
3412 
3413   /* get details of the second active stream */
3414   activeStream = gst_mpdparser_get_active_stream_by_index (mpdclient, 1);
3415   fail_if (activeStream == NULL);
3416   assert_equals_int (activeStream->mimeType, GST_STREAM_AUDIO);
3417 
3418   /* get details of the third active stream */
3419   activeStream = gst_mpdparser_get_active_stream_by_index (mpdclient, 2);
3420   fail_if (activeStream == NULL);
3421   assert_equals_int (activeStream->mimeType, GST_STREAM_APPLICATION);
3422 
3423   gst_mpd_client_free (mpdclient);
3424 }
3425 
3426 GST_END_TEST;
3427 
3428 /*
3429  * Test getting Active stream parameters
3430  *
3431  */
GST_START_TEST(dash_mpdparser_activeStream_parameters)3432 GST_START_TEST (dash_mpdparser_activeStream_parameters)
3433 {
3434   GList *adaptationSets;
3435   GstAdaptationSetNode *adapt_set;
3436   guint activeStreams;
3437   GstActiveStream *activeStream;
3438   GstCaps *caps;
3439   GstStructure *s;
3440   gboolean bitstreamSwitchingFlag;
3441   guint videoStreamWidth;
3442   guint videoStreamHeight;
3443   guint audioStreamRate;
3444   guint audioChannelsCount;
3445 
3446   const gchar *xml =
3447       "<?xml version=\"1.0\"?>"
3448       "<MPD xmlns=\"urn:mpeg:dash:schema:mpd:2011\""
3449       "     profiles=\"urn:mpeg:dash:profile:isoff-main:2011\">"
3450       "  <Period id=\"Period0\""
3451       "          duration=\"P0Y0M1DT1H1M1S\">"
3452       "    <AdaptationSet id=\"1\""
3453       "                   mimeType=\"video/mp4\""
3454       "                   width=\"320\""
3455       "                   height=\"240\""
3456       "                   bitstreamSwitching=\"true\""
3457       "                   audioSamplingRate=\"48000\">"
3458       "      <Representation id=\"1\" bandwidth=\"250000\">"
3459       "      </Representation></AdaptationSet></Period></MPD>";
3460 
3461   gboolean ret;
3462   GstMpdClient *mpdclient = gst_mpd_client_new ();
3463 
3464   ret = gst_mpd_parse (mpdclient, xml, (gint) strlen (xml));
3465   assert_equals_int (ret, TRUE);
3466 
3467   /* process the xml data */
3468   ret =
3469       gst_mpd_client_setup_media_presentation (mpdclient, GST_CLOCK_TIME_NONE,
3470       -1, NULL);
3471   assert_equals_int (ret, TRUE);
3472 
3473   /* get the list of adaptation sets of the first period */
3474   adaptationSets = gst_mpd_client_get_adaptation_sets (mpdclient);
3475   fail_if (adaptationSets == NULL);
3476 
3477   /* setup streaming from the first adaptation set */
3478   adapt_set = (GstAdaptationSetNode *) g_list_nth_data (adaptationSets, 0);
3479   fail_if (adapt_set == NULL);
3480   ret = gst_mpd_client_setup_streaming (mpdclient, adapt_set);
3481   assert_equals_int (ret, TRUE);
3482 
3483   /* 1 active streams */
3484   activeStreams = gst_mpdparser_get_nb_active_stream (mpdclient);
3485   assert_equals_int (activeStreams, 1);
3486 
3487   /* get details of the first active stream */
3488   activeStream = gst_mpdparser_get_active_stream_by_index (mpdclient, 0);
3489   fail_if (activeStream == NULL);
3490 
3491   assert_equals_int (activeStream->mimeType, GST_STREAM_VIDEO);
3492   caps = gst_mpd_client_get_stream_caps (activeStream);
3493   fail_unless (caps != NULL);
3494   s = gst_caps_get_structure (caps, 0);
3495   assert_equals_string (gst_structure_get_name (s), "video/quicktime");
3496   gst_caps_unref (caps);
3497 
3498   bitstreamSwitchingFlag =
3499       gst_mpd_client_get_bitstream_switching_flag (activeStream);
3500   assert_equals_int (bitstreamSwitchingFlag, 1);
3501 
3502   videoStreamWidth = gst_mpd_client_get_video_stream_width (activeStream);
3503   assert_equals_int (videoStreamWidth, 320);
3504 
3505   videoStreamHeight = gst_mpd_client_get_video_stream_height (activeStream);
3506   assert_equals_int (videoStreamHeight, 240);
3507 
3508   audioStreamRate = gst_mpd_client_get_audio_stream_rate (activeStream);
3509   assert_equals_int (audioStreamRate, 48000);
3510 
3511   audioChannelsCount =
3512       gst_mpd_client_get_audio_stream_num_channels (activeStream);
3513   assert_equals_int (audioChannelsCount, 0);
3514 
3515   gst_mpd_client_free (mpdclient);
3516 }
3517 
3518 GST_END_TEST;
3519 
3520 /*
3521  * Test getting number and list of audio languages
3522  *
3523  */
GST_START_TEST(dash_mpdparser_get_audio_languages)3524 GST_START_TEST (dash_mpdparser_get_audio_languages)
3525 {
3526   GList *adaptationSets;
3527   GstAdaptationSetNode *adapt_set;
3528   guint activeStreams;
3529   guint adaptationSetsCount;
3530   GList *languages = NULL;
3531   guint languagesCount;
3532 
3533   const gchar *xml =
3534       "<?xml version=\"1.0\"?>"
3535       "<MPD xmlns=\"urn:mpeg:dash:schema:mpd:2011\""
3536       "     profiles=\"urn:mpeg:dash:profile:isoff-main:2011\">"
3537       "  <Period id=\"Period0\" duration=\"P0Y0M1DT1H1M1S\">"
3538       "    <AdaptationSet id=\"1\" mimeType=\"audio\" lang=\"en\">"
3539       "      <Representation id=\"1\" bandwidth=\"250000\">"
3540       "      </Representation>"
3541       "    </AdaptationSet>"
3542       "    <AdaptationSet id=\"2\" mimeType=\"video/mp4\">"
3543       "      <Representation id=\"2\" bandwidth=\"250000\">"
3544       "      </Representation>"
3545       "    </AdaptationSet>"
3546       "    <AdaptationSet id=\"3\" mimeType=\"audio\" lang=\"fr\">"
3547       "      <Representation id=\"3\" bandwidth=\"250000\">"
3548       "      </Representation></AdaptationSet></Period></MPD>";
3549 
3550   gboolean ret;
3551   GstMpdClient *mpdclient = gst_mpd_client_new ();
3552   gint i;
3553 
3554   ret = gst_mpd_parse (mpdclient, xml, (gint) strlen (xml));
3555   assert_equals_int (ret, TRUE);
3556 
3557   /* process the xml data */
3558   ret =
3559       gst_mpd_client_setup_media_presentation (mpdclient, GST_CLOCK_TIME_NONE,
3560       -1, NULL);
3561   assert_equals_int (ret, TRUE);
3562 
3563   /* get the list of adaptation sets of the first period */
3564   adaptationSets = gst_mpd_client_get_adaptation_sets (mpdclient);
3565   fail_if (adaptationSets == NULL);
3566 
3567   /* setup streaming from all adaptation sets */
3568   adaptationSetsCount = gst_mpdparser_get_nb_adaptationSet (mpdclient);
3569   for (i = 0; i < adaptationSetsCount; i++) {
3570     adapt_set = (GstAdaptationSetNode *) g_list_nth_data (adaptationSets, i);
3571     fail_if (adapt_set == NULL);
3572     ret = gst_mpd_client_setup_streaming (mpdclient, adapt_set);
3573     assert_equals_int (ret, TRUE);
3574   }
3575   activeStreams = gst_mpdparser_get_nb_active_stream (mpdclient);
3576   assert_equals_int (activeStreams, adaptationSetsCount);
3577 
3578   languagesCount =
3579       gst_mpdparser_get_list_and_nb_of_audio_language (mpdclient, &languages);
3580   assert_equals_int (languagesCount, 2);
3581   assert_equals_string ((gchar *) g_list_nth_data (languages, 0), "en");
3582   assert_equals_string ((gchar *) g_list_nth_data (languages, 1), "fr");
3583 
3584   g_list_free (languages);
3585 
3586   gst_mpd_client_free (mpdclient);
3587 }
3588 
3589 GST_END_TEST;
3590 
3591 /*
3592  * Tests getting the base URL
3593  *
3594  */
3595 static GstMpdClient *
setup_mpd_client(const gchar * xml)3596 setup_mpd_client (const gchar * xml)
3597 {
3598   GList *adaptationSets;
3599   GstAdaptationSetNode *adapt_set;
3600   guint activeStreams;
3601   guint adaptationSetsCount;
3602   gboolean ret;
3603   GstMpdClient *mpdclient = gst_mpd_client_new ();
3604   gint i;
3605 
3606   ret = gst_mpd_parse (mpdclient, xml, (gint) strlen (xml));
3607   assert_equals_int (ret, TRUE);
3608 
3609   /* process the xml data */
3610   ret =
3611       gst_mpd_client_setup_media_presentation (mpdclient, GST_CLOCK_TIME_NONE,
3612       -1, NULL);
3613   assert_equals_int (ret, TRUE);
3614 
3615   /* get the list of adaptation sets of the first period */
3616   adaptationSets = gst_mpd_client_get_adaptation_sets (mpdclient);
3617   fail_if (adaptationSets == NULL);
3618 
3619   /* setup streaming from all adaptation sets */
3620   adaptationSetsCount = gst_mpdparser_get_nb_adaptationSet (mpdclient);
3621   for (i = 0; i < adaptationSetsCount; i++) {
3622     adapt_set = (GstAdaptationSetNode *) g_list_nth_data (adaptationSets, i);
3623     fail_if (adapt_set == NULL);
3624     ret = gst_mpd_client_setup_streaming (mpdclient, adapt_set);
3625     assert_equals_int (ret, TRUE);
3626   }
3627   activeStreams = gst_mpdparser_get_nb_active_stream (mpdclient);
3628   assert_equals_int (activeStreams, adaptationSetsCount);
3629 
3630   return mpdclient;
3631 }
3632 
GST_START_TEST(dash_mpdparser_get_baseURL1)3633 GST_START_TEST (dash_mpdparser_get_baseURL1)
3634 {
3635   const gchar *baseURL;
3636   const gchar *xml =
3637       "<?xml version=\"1.0\"?>"
3638       "<MPD xmlns=\"urn:mpeg:dash:schema:mpd:2011\""
3639       "     profiles=\"urn:mpeg:dash:profile:isoff-main:2011\">"
3640       "  <BaseURL>http://example.com/</BaseURL>"
3641       "  <Period id=\"Period0\" duration=\"P0Y0M1DT1H1M1S\">"
3642       "    <AdaptationSet id=\"1\" mimeType=\"audio\" lang=\"en\">"
3643       "      <Representation id=\"1\" bandwidth=\"250000\">"
3644       "      </Representation></AdaptationSet></Period></MPD>";
3645 
3646   GstMpdClient *mpdclient = setup_mpd_client (xml);
3647 
3648   baseURL = gst_mpdparser_get_baseURL (mpdclient, 0);
3649   fail_if (baseURL == NULL);
3650   assert_equals_string (baseURL, "http://example.com/");
3651 
3652   gst_mpd_client_free (mpdclient);
3653 }
3654 
3655 GST_END_TEST;
3656 
3657 
GST_START_TEST(dash_mpdparser_get_baseURL2)3658 GST_START_TEST (dash_mpdparser_get_baseURL2)
3659 {
3660   const gchar *baseURL;
3661   const gchar *xml =
3662       "<?xml version=\"1.0\"?>"
3663       "<MPD xmlns=\"urn:mpeg:dash:schema:mpd:2011\""
3664       "     profiles=\"urn:mpeg:dash:profile:isoff-main:2011\">"
3665       "  <BaseURL>mpd_base_url/</BaseURL>"
3666       "  <Period id=\"Period0\" duration=\"P0Y0M1DT1H1M1S\">"
3667       "    <BaseURL> /period_base_url/</BaseURL>"
3668       "    <AdaptationSet id=\"1\" mimeType=\"audio\" lang=\"en\">"
3669       "      <BaseURL>adaptation_base_url</BaseURL>"
3670       "      <Representation id=\"1\" bandwidth=\"250000\">"
3671       "        <BaseURL>representation_base_url</BaseURL>"
3672       "      </Representation></AdaptationSet></Period></MPD>";
3673 
3674   GstMpdClient *mpdclient = setup_mpd_client (xml);
3675 
3676   /* test baseURL. Its value should be computed like this:
3677    *  - start with xml url (null)
3678    *  - set it to the value from MPD's BaseURL element: "mpd_base_url/"
3679    *  - update the value with BaseURL element from Period. Because Period's
3680    * baseURL is absolute (starts with /) it will overwrite the current value
3681    * for baseURL. So, baseURL becomes "/period_base_url/"
3682    *  - update the value with BaseURL element from AdaptationSet. Because this
3683    * is a relative url, it will update the current value. baseURL becomes
3684    * "/period_base_url/adaptation_base_url"
3685    *  - update the value with BaseURL element from Representation. Because this
3686    * is a relative url, it will update the current value. Because the current
3687    * value does not end in /, everything after the last / will be overwritten.
3688    * baseURL becomes "/period_base_url/representation_base_url"
3689    */
3690   baseURL = gst_mpdparser_get_baseURL (mpdclient, 0);
3691   fail_if (baseURL == NULL);
3692   assert_equals_string (baseURL, "/period_base_url/representation_base_url");
3693 
3694   gst_mpd_client_free (mpdclient);
3695 }
3696 
3697 GST_END_TEST;
3698 
3699 
GST_START_TEST(dash_mpdparser_get_baseURL3)3700 GST_START_TEST (dash_mpdparser_get_baseURL3)
3701 {
3702   const gchar *baseURL;
3703   const gchar *xml =
3704       "<?xml version=\"1.0\"?>"
3705       "<MPD xmlns=\"urn:mpeg:dash:schema:mpd:2011\""
3706       "     profiles=\"urn:mpeg:dash:profile:isoff-main:2011\">"
3707       "  <BaseURL>mpd_base_url/</BaseURL>"
3708       "  <Period id=\"Period0\" duration=\"P0Y0M1DT1H1M1S\">"
3709       "    <BaseURL> /period_base_url/</BaseURL>"
3710       "    <AdaptationSet id=\"1\" mimeType=\"audio\" lang=\"en\">"
3711       "      <BaseURL>adaptation_base_url</BaseURL>"
3712       "      <Representation id=\"1\" bandwidth=\"250000\">"
3713       "        <BaseURL>/representation_base_url</BaseURL>"
3714       "      </Representation></AdaptationSet></Period></MPD>";
3715 
3716   GstMpdClient *mpdclient = setup_mpd_client (xml);
3717 
3718   /* test baseURL. Its value should be computed like this:
3719    *  - start with xml url (null)
3720    *  - set it to the value from MPD's BaseURL element: "mpd_base_url/"
3721    *  - update the value with BaseURL element from Period. Because Period's
3722    * baseURL is absolute (starts with /) it will overwrite the current value
3723    * for baseURL. So, baseURL becomes "/period_base_url/"
3724    *  - update the value with BaseURL element from AdaptationSet. Because this
3725    * is a relative url, it will update the current value. baseURL becomes
3726    * "/period_base_url/adaptation_base_url"
3727    *  - update the value with BaseURL element from Representation. Because this
3728    * is an absolute url, it will replace everything again"
3729    */
3730   baseURL = gst_mpdparser_get_baseURL (mpdclient, 0);
3731   fail_if (baseURL == NULL);
3732   assert_equals_string (baseURL, "/representation_base_url");
3733 
3734   gst_mpd_client_free (mpdclient);
3735 }
3736 
3737 GST_END_TEST;
3738 
3739 
GST_START_TEST(dash_mpdparser_get_baseURL4)3740 GST_START_TEST (dash_mpdparser_get_baseURL4)
3741 {
3742   const gchar *baseURL;
3743   const gchar *xml =
3744       "<?xml version=\"1.0\"?>"
3745       "<MPD xmlns=\"urn:mpeg:dash:schema:mpd:2011\""
3746       "     profiles=\"urn:mpeg:dash:profile:isoff-main:2011\">"
3747       "  <BaseURL>mpd_base_url/</BaseURL>"
3748       "  <Period id=\"Period0\" duration=\"P0Y0M1DT1H1M1S\">"
3749       "    <BaseURL> /period_base_url/</BaseURL>"
3750       "    <AdaptationSet id=\"1\" mimeType=\"audio\" lang=\"en\">"
3751       "      <BaseURL>adaptation_base_url/</BaseURL>"
3752       "      <Representation id=\"1\" bandwidth=\"250000\">"
3753       "        <BaseURL>representation_base_url/</BaseURL>"
3754       "      </Representation></AdaptationSet></Period></MPD>";
3755 
3756   GstMpdClient *mpdclient = setup_mpd_client (xml);
3757 
3758   /* test baseURL. Its value should be computed like this:
3759    *  - start with xml url (null)
3760    *  - set it to the value from MPD's BaseURL element: "mpd_base_url/"
3761    *  - update the value with BaseURL element from Period. Because Period's
3762    * baseURL is absolute (starts with /) it will overwrite the current value
3763    * for baseURL. So, baseURL becomes "/period_base_url/"
3764    *  - update the value with BaseURL element from AdaptationSet. Because this
3765    * is a relative url, it will update the current value. baseURL becomes
3766    * "/period_base_url/adaptation_base_url/"
3767    *  - update the value with BaseURL element from Representation. Because this
3768    * is an relative url, it will update the current value."
3769    */
3770   baseURL = gst_mpdparser_get_baseURL (mpdclient, 0);
3771   fail_if (baseURL == NULL);
3772   assert_equals_string (baseURL,
3773       "/period_base_url/adaptation_base_url/representation_base_url/");
3774 
3775   gst_mpd_client_free (mpdclient);
3776 }
3777 
3778 GST_END_TEST;
3779 
3780 /* test multiple BaseUrl entries per section */
GST_START_TEST(dash_mpdparser_get_baseURL5)3781 GST_START_TEST (dash_mpdparser_get_baseURL5)
3782 {
3783   GstPeriodNode *periodNode;
3784   GstAdaptationSetNode *adaptationSet;
3785   GstRepresentationNode *representation;
3786   const gchar *baseURL;
3787   GstBaseURL *gstBaseURL;
3788 
3789   const gchar *xml =
3790       "<?xml version=\"1.0\"?>"
3791       "<MPD xmlns=\"urn:mpeg:dash:schema:mpd:2011\""
3792       "     profiles=\"urn:mpeg:dash:profile:isoff-main:2011\">"
3793       "  <BaseURL>/mpd_base_url1/</BaseURL>"
3794       "  <BaseURL>/mpd_base_url2/</BaseURL>"
3795       "  <Period id=\"Period0\" duration=\"P0Y0M1DT1H1M1S\">"
3796       "    <BaseURL> period_base_url1/</BaseURL>"
3797       "    <BaseURL> period_base_url2/</BaseURL>"
3798       "    <BaseURL> period_base_url3/</BaseURL>"
3799       "    <AdaptationSet id=\"1\" mimeType=\"audio\" lang=\"en\">"
3800       "      <BaseURL>adaptation_base_url1/</BaseURL>"
3801       "      <BaseURL>adaptation_base_url2/</BaseURL>"
3802       "      <BaseURL>adaptation_base_url3/</BaseURL>"
3803       "      <BaseURL>adaptation_base_url4/</BaseURL>"
3804       "      <Representation id=\"1\" bandwidth=\"250000\">"
3805       "        <BaseURL>representation_base_url1/</BaseURL>"
3806       "        <BaseURL>representation_base_url2/</BaseURL>"
3807       "        <BaseURL>representation_base_url3/</BaseURL>"
3808       "        <BaseURL>representation_base_url4/</BaseURL>"
3809       "        <BaseURL>representation_base_url5/</BaseURL>"
3810       "      </Representation></AdaptationSet></Period></MPD>";
3811 
3812   GstMpdClient *mpdclient = setup_mpd_client (xml);
3813 
3814   assert_equals_int (g_list_length (mpdclient->mpd_node->BaseURLs), 2);
3815   gstBaseURL = g_list_nth_data (mpdclient->mpd_node->BaseURLs, 0);
3816   assert_equals_string (gstBaseURL->baseURL, "/mpd_base_url1/");
3817   gstBaseURL = g_list_nth_data (mpdclient->mpd_node->BaseURLs, 1);
3818   assert_equals_string (gstBaseURL->baseURL, "/mpd_base_url2/");
3819 
3820   periodNode = (GstPeriodNode *) mpdclient->mpd_node->Periods->data;
3821   assert_equals_int (g_list_length (periodNode->BaseURLs), 3);
3822   gstBaseURL = g_list_nth_data (periodNode->BaseURLs, 0);
3823   assert_equals_string (gstBaseURL->baseURL, " period_base_url1/");
3824   gstBaseURL = g_list_nth_data (periodNode->BaseURLs, 1);
3825   assert_equals_string (gstBaseURL->baseURL, " period_base_url2/");
3826   gstBaseURL = g_list_nth_data (periodNode->BaseURLs, 2);
3827   assert_equals_string (gstBaseURL->baseURL, " period_base_url3/");
3828 
3829   adaptationSet = (GstAdaptationSetNode *) periodNode->AdaptationSets->data;
3830   assert_equals_int (g_list_length (adaptationSet->BaseURLs), 4);
3831   gstBaseURL = g_list_nth_data (adaptationSet->BaseURLs, 0);
3832   assert_equals_string (gstBaseURL->baseURL, "adaptation_base_url1/");
3833   gstBaseURL = g_list_nth_data (adaptationSet->BaseURLs, 1);
3834   assert_equals_string (gstBaseURL->baseURL, "adaptation_base_url2/");
3835   gstBaseURL = g_list_nth_data (adaptationSet->BaseURLs, 2);
3836   assert_equals_string (gstBaseURL->baseURL, "adaptation_base_url3/");
3837   gstBaseURL = g_list_nth_data (adaptationSet->BaseURLs, 3);
3838   assert_equals_string (gstBaseURL->baseURL, "adaptation_base_url4/");
3839 
3840   representation = (GstRepresentationNode *)
3841       adaptationSet->Representations->data;
3842   assert_equals_int (g_list_length (representation->BaseURLs), 5);
3843   gstBaseURL = g_list_nth_data (representation->BaseURLs, 0);
3844   assert_equals_string (gstBaseURL->baseURL, "representation_base_url1/");
3845   gstBaseURL = g_list_nth_data (representation->BaseURLs, 1);
3846   assert_equals_string (gstBaseURL->baseURL, "representation_base_url2/");
3847   gstBaseURL = g_list_nth_data (representation->BaseURLs, 2);
3848   assert_equals_string (gstBaseURL->baseURL, "representation_base_url3/");
3849   gstBaseURL = g_list_nth_data (representation->BaseURLs, 3);
3850   assert_equals_string (gstBaseURL->baseURL, "representation_base_url4/");
3851   gstBaseURL = g_list_nth_data (representation->BaseURLs, 4);
3852   assert_equals_string (gstBaseURL->baseURL, "representation_base_url5/");
3853 
3854   /* test baseURL. Its value should be computed like this:
3855    *  - start with xml url (null)
3856    *  - set it to the value from MPD's BaseURL element: "/mpd_base_url1/"
3857    *  - update the value with BaseURL element from Period. Because this
3858    * is a relative url, it will update the current value. baseURL becomes
3859    * "/mpd_base_url1/period_base_url1/"
3860    *  - update the value with BaseURL element from AdaptationSet. Because this
3861    * is a relative url, it will update the current value. baseURL becomes
3862    * "/mpd_base_url1/period_base_url1/adaptation_base_url1/"
3863    *  - update the value with BaseURL element from Representation. Because this
3864    * is an relative url, it will update the current value."
3865    */
3866   baseURL = gst_mpdparser_get_baseURL (mpdclient, 0);
3867   fail_if (baseURL == NULL);
3868   assert_equals_string (baseURL,
3869       "/mpd_base_url1/period_base_url1/adaptation_base_url1/representation_base_url1/");
3870 
3871   gst_mpd_client_free (mpdclient);
3872 }
3873 
3874 GST_END_TEST;
3875 
3876 /* test no BaseURL */
GST_START_TEST(dash_mpdparser_get_baseURL6)3877 GST_START_TEST (dash_mpdparser_get_baseURL6)
3878 {
3879   const gchar *baseURL;
3880   const gchar *xml =
3881       "<?xml version=\"1.0\"?>"
3882       "<MPD xmlns=\"urn:mpeg:dash:schema:mpd:2011\""
3883       "     profiles=\"urn:mpeg:dash:profile:isoff-main:2011\">"
3884       "  <Period id=\"Period0\" duration=\"P0Y0M1DT1H1M1S\">"
3885       "    <AdaptationSet id=\"1\" mimeType=\"audio\" lang=\"en\">"
3886       "      <Representation id=\"1\" bandwidth=\"250000\">"
3887       "      </Representation></AdaptationSet></Period></MPD>";
3888 
3889   GstMpdClient *mpdclient = setup_mpd_client (xml);
3890 
3891   baseURL = gst_mpdparser_get_baseURL (mpdclient, 0);
3892   fail_if (baseURL == NULL);
3893   assert_equals_string (baseURL, "");
3894 
3895   gst_mpd_client_free (mpdclient);
3896 }
3897 
3898 GST_END_TEST;
3899 
3900 /* BaseURL: test that the path is made absolute (a / is prepended if needed */
GST_START_TEST(dash_mpdparser_get_baseURL7)3901 GST_START_TEST (dash_mpdparser_get_baseURL7)
3902 {
3903   const gchar *baseURL;
3904   const gchar *xml =
3905       "<?xml version=\"1.0\"?>"
3906       "<MPD xmlns=\"urn:mpeg:dash:schema:mpd:2011\""
3907       "     profiles=\"urn:mpeg:dash:profile:isoff-main:2011\">"
3908       "  <BaseURL>x/example.com/</BaseURL>"
3909       "  <Period id=\"Period0\" duration=\"P0Y0M1DT1H1M1S\">"
3910       "    <AdaptationSet id=\"1\" mimeType=\"audio\" lang=\"en\">"
3911       "      <Representation id=\"1\" bandwidth=\"250000\">"
3912       "      </Representation></AdaptationSet></Period></MPD>";
3913 
3914   GstMpdClient *mpdclient;
3915 
3916   mpdclient = setup_mpd_client (xml);
3917 
3918   baseURL = gst_mpdparser_get_baseURL (mpdclient, 0);
3919   fail_if (baseURL == NULL);
3920   assert_equals_string (baseURL, "/x/example.com/");
3921 
3922   gst_mpd_client_free (mpdclient);
3923 }
3924 
3925 GST_END_TEST;
3926 
3927 /* BaseURL: test that a / is not prepended if the string contains ':'
3928  * This tests uris with schema present */
GST_START_TEST(dash_mpdparser_get_baseURL8)3929 GST_START_TEST (dash_mpdparser_get_baseURL8)
3930 {
3931   const gchar *baseURL;
3932   const gchar *xml =
3933       "<?xml version=\"1.0\"?>"
3934       "<MPD xmlns=\"urn:mpeg:dash:schema:mpd:2011\""
3935       "     profiles=\"urn:mpeg:dash:profile:isoff-main:2011\">"
3936       "  <BaseURL>x:y/example.com/</BaseURL>"
3937       "  <Period id=\"Period0\" duration=\"P0Y0M1DT1H1M1S\">"
3938       "    <AdaptationSet id=\"1\" mimeType=\"audio\" lang=\"en\">"
3939       "      <Representation id=\"1\" bandwidth=\"250000\">"
3940       "      </Representation></AdaptationSet></Period></MPD>";
3941 
3942   GstMpdClient *mpdclient = setup_mpd_client (xml);
3943 
3944   baseURL = gst_mpdparser_get_baseURL (mpdclient, 0);
3945   fail_if (baseURL == NULL);
3946   assert_equals_string (baseURL, "x:y/example.com/");
3947 
3948   gst_mpd_client_free (mpdclient);
3949 }
3950 
3951 GST_END_TEST;
3952 
3953 /*
3954  * Test getting mediaPresentationDuration
3955  *
3956  */
GST_START_TEST(dash_mpdparser_get_mediaPresentationDuration)3957 GST_START_TEST (dash_mpdparser_get_mediaPresentationDuration)
3958 {
3959   GstClockTime mediaPresentationDuration;
3960 
3961   const gchar *xml =
3962       "<?xml version=\"1.0\"?>"
3963       "<MPD xmlns=\"urn:mpeg:dash:schema:mpd:2011\""
3964       "     profiles=\"urn:mpeg:dash:profile:isoff-main:2011\""
3965       "     mediaPresentationDuration=\"P0Y0M0DT0H0M3S\"></MPD>";
3966 
3967   gboolean ret;
3968   GstMpdClient *mpdclient = gst_mpd_client_new ();
3969 
3970   ret = gst_mpd_parse (mpdclient, xml, (gint) strlen (xml));
3971   assert_equals_int (ret, TRUE);
3972 
3973   mediaPresentationDuration =
3974       gst_mpd_client_get_media_presentation_duration (mpdclient);
3975   assert_equals_uint64 (mediaPresentationDuration, 3000000000);
3976 
3977   gst_mpd_client_free (mpdclient);
3978 }
3979 
3980 GST_END_TEST;
3981 
3982 /*
3983  * Test getting streamPresentationOffset
3984  *
3985  */
GST_START_TEST(dash_mpdparser_get_streamPresentationOffset)3986 GST_START_TEST (dash_mpdparser_get_streamPresentationOffset)
3987 {
3988   GList *adaptationSets;
3989   GstAdaptationSetNode *adapt_set;
3990   GstClockTime offset;
3991   const gchar *xml =
3992       "<?xml version=\"1.0\"?>"
3993       "<MPD xmlns=\"urn:mpeg:dash:schema:mpd:2011\""
3994       "     profiles=\"urn:mpeg:dash:profile:isoff-main:2011\""
3995       "     mediaPresentationDuration=\"P0Y0M0DT3H3M30S\">"
3996       "  <Period>"
3997       "    <AdaptationSet mimeType=\"video/mp4\">"
3998       "      <SegmentBase timescale=\"1000\" presentationTimeOffset=\"3000\">"
3999       "      </SegmentBase>"
4000       "      <Representation id=\"1\" bandwidth=\"250000\">"
4001       "      </Representation></AdaptationSet></Period></MPD>";
4002 
4003   gboolean ret;
4004   GstMpdClient *mpdclient = gst_mpd_client_new ();
4005 
4006   ret = gst_mpd_parse (mpdclient, xml, (gint) strlen (xml));
4007   assert_equals_int (ret, TRUE);
4008 
4009   /* process the xml data */
4010   ret =
4011       gst_mpd_client_setup_media_presentation (mpdclient, GST_CLOCK_TIME_NONE,
4012       -1, NULL);
4013   assert_equals_int (ret, TRUE);
4014 
4015   /* get the list of adaptation sets of the first period */
4016   adaptationSets = gst_mpd_client_get_adaptation_sets (mpdclient);
4017   fail_if (adaptationSets == NULL);
4018 
4019   /* setup streaming from the first adaptation set */
4020   adapt_set = (GstAdaptationSetNode *) g_list_nth_data (adaptationSets, 0);
4021   fail_if (adapt_set == NULL);
4022   ret = gst_mpd_client_setup_streaming (mpdclient, adapt_set);
4023   assert_equals_int (ret, TRUE);
4024 
4025   /* test the stream presentation time offset */
4026   offset = gst_mpd_parser_get_stream_presentation_offset (mpdclient, 0);
4027   /* seems to be set only for template segments, so here it is 0 */
4028   assert_equals_int (offset, 0);
4029 
4030   gst_mpd_client_free (mpdclient);
4031 }
4032 
4033 GST_END_TEST;
4034 
4035 /*
4036  * Test handling segments
4037  *
4038  */
GST_START_TEST(dash_mpdparser_segments)4039 GST_START_TEST (dash_mpdparser_segments)
4040 {
4041   GList *adaptationSets;
4042   GstAdaptationSetNode *adapt_set;
4043   gboolean hasNextSegment;
4044   GstActiveStream *activeStream;
4045   GstFlowReturn flow;
4046   GstDateTime *segmentAvailability;
4047   GstDateTime *gst_time;
4048   GDateTime *g_time;
4049 
4050   const gchar *xml =
4051       "<?xml version=\"1.0\"?>"
4052       "<MPD xmlns=\"urn:mpeg:dash:schema:mpd:2011\""
4053       "     type=\"dynamic\""
4054       "     profiles=\"urn:mpeg:dash:profile:isoff-main:2011\""
4055       "     availabilityStartTime=\"2015-03-24T0:0:0\""
4056       "     mediaPresentationDuration=\"P0Y0M0DT3H3M30S\">"
4057       "  <Period id=\"Period0\" start=\"P0Y0M0DT0H0M10S\">"
4058       "    <AdaptationSet mimeType=\"video/mp4\">"
4059       "      <Representation id=\"1\" bandwidth=\"250000\">"
4060       "        <SegmentList duration=\"45\">"
4061       "          <SegmentURL media=\"TestMedia1\""
4062       "                      mediaRange=\"10-20\""
4063       "                      index=\"TestIndex1\""
4064       "                      indexRange=\"30-40\">"
4065       "          </SegmentURL>"
4066       "          <SegmentURL media=\"TestMedia2\""
4067       "                      mediaRange=\"20-30\""
4068       "                      index=\"TestIndex2\""
4069       "                      indexRange=\"40-50\">"
4070       "          </SegmentURL>"
4071       "        </SegmentList>"
4072       "      </Representation></AdaptationSet></Period></MPD>";
4073 
4074   gboolean ret;
4075   GstMpdClient *mpdclient = gst_mpd_client_new ();
4076 
4077   ret = gst_mpd_parse (mpdclient, xml, (gint) strlen (xml));
4078   assert_equals_int (ret, TRUE);
4079 
4080   /* process the xml data */
4081   ret =
4082       gst_mpd_client_setup_media_presentation (mpdclient, GST_CLOCK_TIME_NONE,
4083       -1, NULL);
4084   assert_equals_int (ret, TRUE);
4085 
4086   /* get the list of adaptation sets of the first period */
4087   adaptationSets = gst_mpd_client_get_adaptation_sets (mpdclient);
4088   fail_if (adaptationSets == NULL);
4089 
4090   /* setup streaming from the first adaptation set */
4091   adapt_set = (GstAdaptationSetNode *) g_list_nth_data (adaptationSets, 0);
4092   fail_if (adapt_set == NULL);
4093   ret = gst_mpd_client_setup_streaming (mpdclient, adapt_set);
4094   assert_equals_int (ret, TRUE);
4095 
4096   activeStream = gst_mpdparser_get_active_stream_by_index (mpdclient, 0);
4097   fail_if (activeStream == NULL);
4098 
4099   /* segment_index 0, segment_count 2.
4100    * Has next segment and can advance to next segment
4101    */
4102   hasNextSegment =
4103       gst_mpd_client_has_next_segment (mpdclient, activeStream, TRUE);
4104   assert_equals_int (hasNextSegment, 1);
4105   flow = gst_mpd_client_advance_segment (mpdclient, activeStream, TRUE);
4106   assert_equals_int (flow, GST_FLOW_OK);
4107 
4108   /* segment_index 1, segment_count 2.
4109    * Does not have next segment and can not advance to next segment
4110    */
4111   hasNextSegment =
4112       gst_mpd_client_has_next_segment (mpdclient, activeStream, TRUE);
4113   assert_equals_int (hasNextSegment, 0);
4114   flow = gst_mpd_client_advance_segment (mpdclient, activeStream, TRUE);
4115   assert_equals_int (flow, GST_FLOW_EOS);
4116 
4117   /* go to first segment */
4118   gst_mpd_client_seek_to_first_segment (mpdclient);
4119 
4120   /* segment_index 0, segment_count 2.
4121    * Has next segment and can advance to next segment
4122    */
4123   hasNextSegment =
4124       gst_mpd_client_has_next_segment (mpdclient, activeStream, TRUE);
4125   assert_equals_int (hasNextSegment, 1);
4126   flow = gst_mpd_client_advance_segment (mpdclient, activeStream, TRUE);
4127   assert_equals_int (flow, GST_FLOW_OK);
4128 
4129   /* segment_index 1, segment_count 2
4130    * Does not have next segment
4131    */
4132   hasNextSegment =
4133       gst_mpd_client_has_next_segment (mpdclient, activeStream, TRUE);
4134   assert_equals_int (hasNextSegment, 0);
4135 
4136   /* segment index is still 1 */
4137   hasNextSegment =
4138       gst_mpd_client_has_next_segment (mpdclient, activeStream, TRUE);
4139   assert_equals_int (hasNextSegment, 0);
4140 
4141   /* each segment has a duration of 0 hours, 0 min 45 seconds
4142    * segment index is 1.
4143    * Start time is at the beginning of segment 1, so 1 * segment_duration = 1 * 45s
4144    * Availability start time is at the end of the segment, so we add duration (45s)
4145    * We also add period start time (10s)
4146    * So, availability start time for segment 1 is: 10 (period start) +
4147    * 45 (segment start) + 45 (duration) = 1'40s
4148    */
4149   segmentAvailability =
4150       gst_mpd_client_get_next_segment_availability_start_time (mpdclient,
4151       activeStream);
4152   assert_equals_int (gst_date_time_get_year (segmentAvailability), 2015);
4153   assert_equals_int (gst_date_time_get_month (segmentAvailability), 3);
4154   assert_equals_int (gst_date_time_get_day (segmentAvailability), 24);
4155   assert_equals_int (gst_date_time_get_hour (segmentAvailability), 0);
4156   assert_equals_int (gst_date_time_get_minute (segmentAvailability), 1);
4157   assert_equals_int (gst_date_time_get_second (segmentAvailability), 40);
4158   gst_date_time_unref (segmentAvailability);
4159 
4160   /* seek to time */
4161   gst_time = gst_date_time_new_from_iso8601_string ("2015-03-24T0:0:20Z");
4162   g_time = gst_date_time_to_g_date_time (gst_time);
4163   ret = gst_mpd_client_seek_to_time (mpdclient, g_time);
4164   assert_equals_int (ret, 1);
4165   gst_date_time_unref (gst_time);
4166   g_date_time_unref (g_time);
4167 
4168   /* segment index is now 0 */
4169   hasNextSegment =
4170       gst_mpd_client_has_next_segment (mpdclient, activeStream, TRUE);
4171   assert_equals_int (hasNextSegment, 1);
4172 
4173   gst_mpd_client_free (mpdclient);
4174 }
4175 
4176 GST_END_TEST;
4177 
4178 /*
4179  * Test handling headers
4180  *
4181  */
GST_START_TEST(dash_mpdparser_headers)4182 GST_START_TEST (dash_mpdparser_headers)
4183 {
4184   GList *adaptationSets;
4185   GstAdaptationSetNode *adapt_set;
4186   gchar *uri;
4187   gint64 range_start;
4188   gint64 range_end;
4189 
4190   const gchar *xml =
4191       "<?xml version=\"1.0\"?>"
4192       "<MPD xmlns=\"urn:mpeg:dash:schema:mpd:2011\""
4193       "     type=\"dynamic\""
4194       "     profiles=\"urn:mpeg:dash:profile:isoff-main:2011\""
4195       "     availabilityStartTime=\"2015-03-24T0:0:0\""
4196       "     mediaPresentationDuration=\"P0Y0M0DT3H3M30S\">"
4197       "  <Period id=\"Period0\">"
4198       "    <AdaptationSet mimeType=\"video/mp4\">"
4199       "      <Representation id=\"1\" bandwidth=\"250000\">"
4200       "        <SegmentBase indexRange=\"10-20\">"
4201       "          <Initialization sourceURL=\"TestSourceUrl\""
4202       "                          range=\"100-200\">"
4203       "          </Initialization>"
4204       "          <RepresentationIndex sourceURL=\"TestSourceIndex\">"
4205       "          </RepresentationIndex>"
4206       "        </SegmentBase>"
4207       "      </Representation></AdaptationSet></Period></MPD>";
4208 
4209   gboolean ret;
4210   GstMpdClient *mpdclient = gst_mpd_client_new ();
4211 
4212   ret = gst_mpd_parse (mpdclient, xml, (gint) strlen (xml));
4213   assert_equals_int (ret, TRUE);
4214 
4215   /* process the xml data */
4216   ret =
4217       gst_mpd_client_setup_media_presentation (mpdclient, GST_CLOCK_TIME_NONE,
4218       -1, NULL);
4219   assert_equals_int (ret, TRUE);
4220 
4221   /* get the list of adaptation sets of the first period */
4222   adaptationSets = gst_mpd_client_get_adaptation_sets (mpdclient);
4223   fail_if (adaptationSets == NULL);
4224 
4225   /* setup streaming from the first adaptation set */
4226   adapt_set = (GstAdaptationSetNode *) g_list_nth_data (adaptationSets, 0);
4227   fail_if (adapt_set == NULL);
4228   ret = gst_mpd_client_setup_streaming (mpdclient, adapt_set);
4229   assert_equals_int (ret, TRUE);
4230 
4231   /* get segment url and range from segment Initialization */
4232   ret =
4233       gst_mpd_client_get_next_header (mpdclient, &uri, 0, &range_start,
4234       &range_end);
4235   assert_equals_int (ret, TRUE);
4236   assert_equals_string (uri, "TestSourceUrl");
4237   assert_equals_int64 (range_start, 100);
4238   assert_equals_int64 (range_end, 200);
4239   g_free (uri);
4240 
4241   /* get segment url and range from segment indexRange */
4242   ret =
4243       gst_mpd_client_get_next_header_index (mpdclient, &uri, 0, &range_start,
4244       &range_end);
4245   assert_equals_int (ret, TRUE);
4246   assert_equals_string (uri, "TestSourceIndex");
4247   assert_equals_int64 (range_start, 10);
4248   assert_equals_int64 (range_end, 20);
4249   g_free (uri);
4250 
4251   gst_mpd_client_free (mpdclient);
4252 }
4253 
4254 GST_END_TEST;
4255 
4256 /*
4257  * Test handling fragments
4258  *
4259  */
GST_START_TEST(dash_mpdparser_fragments)4260 GST_START_TEST (dash_mpdparser_fragments)
4261 {
4262   GList *adaptationSets;
4263   GstAdaptationSetNode *adapt_set;
4264   GstMediaFragmentInfo fragment;
4265   GstActiveStream *activeStream;
4266   GstClockTime nextFragmentDuration;
4267   GstClockTime nextFragmentTimestamp;
4268   GstClockTime nextFragmentTimestampEnd;
4269   GstClockTime periodStartTime;
4270   GstClockTime expectedDuration;
4271   GstClockTime expectedTimestamp;
4272   GstClockTime expectedTimestampEnd;
4273 
4274   const gchar *xml =
4275       "<?xml version=\"1.0\"?>"
4276       "<MPD xmlns=\"urn:mpeg:dash:schema:mpd:2011\""
4277       "     profiles=\"urn:mpeg:dash:profile:isoff-main:2011\""
4278       "     availabilityStartTime=\"2015-03-24T0:0:0\""
4279       "     mediaPresentationDuration=\"P0Y0M0DT3H3M30S\">"
4280       "  <Period id=\"Period0\" start=\"P0Y0M0DT0H0M10S\">"
4281       "    <AdaptationSet mimeType=\"video/mp4\">"
4282       "      <Representation id=\"1\" bandwidth=\"250000\">"
4283       "      </Representation></AdaptationSet></Period></MPD>";
4284 
4285   gboolean ret;
4286   GstMpdClient *mpdclient = gst_mpd_client_new ();
4287 
4288   ret = gst_mpd_parse (mpdclient, xml, (gint) strlen (xml));
4289   assert_equals_int (ret, TRUE);
4290 
4291   /* process the xml data */
4292   ret =
4293       gst_mpd_client_setup_media_presentation (mpdclient, GST_CLOCK_TIME_NONE,
4294       -1, NULL);
4295   assert_equals_int (ret, TRUE);
4296 
4297   /* get the list of adaptation sets of the first period */
4298   adaptationSets = gst_mpd_client_get_adaptation_sets (mpdclient);
4299   fail_if (adaptationSets == NULL);
4300 
4301   /* setup streaming from the first adaptation set */
4302   adapt_set = (GstAdaptationSetNode *) g_list_nth_data (adaptationSets, 0);
4303   fail_if (adapt_set == NULL);
4304   ret = gst_mpd_client_setup_streaming (mpdclient, adapt_set);
4305   assert_equals_int (ret, TRUE);
4306   activeStream = gst_mpdparser_get_active_stream_by_index (mpdclient, 0);
4307   fail_if (activeStream == NULL);
4308 
4309   /* expected duration of the next fragment */
4310   expectedDuration = duration_to_ms (0, 0, 0, 3, 3, 20, 0);
4311   expectedTimestamp = duration_to_ms (0, 0, 0, 0, 0, 0, 0);
4312   expectedTimestampEnd = duration_to_ms (0, 0, 0, 3, 3, 20, 0);
4313 
4314   ret = gst_mpd_client_get_next_fragment (mpdclient, 0, &fragment);
4315   assert_equals_int (ret, TRUE);
4316   assert_equals_string (fragment.uri, "");
4317   assert_equals_int64 (fragment.range_start, 0);
4318   assert_equals_int64 (fragment.range_end, -1);
4319   assert_equals_uint64 (fragment.duration, expectedDuration * GST_MSECOND);
4320   assert_equals_uint64 (fragment.timestamp, expectedTimestamp * GST_MSECOND);
4321   gst_media_fragment_info_clear (&fragment);
4322 
4323   periodStartTime = gst_mpd_parser_get_period_start_time (mpdclient);
4324   assert_equals_uint64 (periodStartTime, 10 * GST_SECOND);
4325 
4326   nextFragmentDuration =
4327       gst_mpd_client_get_next_fragment_duration (mpdclient, activeStream);
4328   assert_equals_uint64 (nextFragmentDuration, expectedDuration * GST_MSECOND);
4329 
4330   ret =
4331       gst_mpd_client_get_next_fragment_timestamp (mpdclient, 0,
4332       &nextFragmentTimestamp);
4333   assert_equals_int (ret, TRUE);
4334   assert_equals_uint64 (nextFragmentTimestamp, expectedTimestamp * GST_MSECOND);
4335 
4336   ret =
4337       gst_mpd_client_get_last_fragment_timestamp_end (mpdclient, 0,
4338       &nextFragmentTimestampEnd);
4339   assert_equals_int (ret, TRUE);
4340   assert_equals_uint64 (nextFragmentTimestampEnd,
4341       expectedTimestampEnd * GST_MSECOND);
4342 
4343   gst_mpd_client_free (mpdclient);
4344 }
4345 
4346 GST_END_TEST;
4347 
4348 /*
4349  * Test inheriting segmentBase from parent
4350  *
4351  */
GST_START_TEST(dash_mpdparser_inherited_segmentBase)4352 GST_START_TEST (dash_mpdparser_inherited_segmentBase)
4353 {
4354   GstPeriodNode *periodNode;
4355   GstSegmentBaseType *segmentBase;
4356   GstAdaptationSetNode *adaptationSet;
4357   GstRepresentationNode *representation;
4358   const gchar *xml =
4359       "<?xml version=\"1.0\"?>"
4360       "<MPD xmlns=\"urn:mpeg:dash:schema:mpd:2011\""
4361       "     profiles=\"urn:mpeg:dash:profile:isoff-main:2011\">"
4362       "  <Period>"
4363       "    <AdaptationSet>"
4364       "      <SegmentBase timescale=\"100\">"
4365       "      </SegmentBase>"
4366       "      <Representation id=\"1\" bandwidth=\"250000\">"
4367       "        <SegmentBase timescale=\"200\">"
4368       "        </SegmentBase>"
4369       "      </Representation></AdaptationSet></Period></MPD>";
4370 
4371   gboolean ret;
4372   GstMpdClient *mpdclient = gst_mpd_client_new ();
4373 
4374   ret = gst_mpd_parse (mpdclient, xml, (gint) strlen (xml));
4375   assert_equals_int (ret, TRUE);
4376 
4377   periodNode = (GstPeriodNode *) mpdclient->mpd_node->Periods->data;
4378   adaptationSet = (GstAdaptationSetNode *) periodNode->AdaptationSets->data;
4379   representation = (GstRepresentationNode *)
4380       adaptationSet->Representations->data;
4381 
4382   /* test segment base from adaptation set */
4383   segmentBase = adaptationSet->SegmentBase;
4384   assert_equals_uint64 (segmentBase->timescale, 100);
4385 
4386   /* test segment base from representation */
4387   segmentBase = representation->SegmentBase;
4388   assert_equals_uint64 (segmentBase->timescale, 200);
4389 
4390   gst_mpd_client_free (mpdclient);
4391 }
4392 
4393 GST_END_TEST;
4394 
4395 /*
4396  * Test inheriting segmentURL from parent
4397  *
4398  */
GST_START_TEST(dash_mpdparser_inherited_segmentURL)4399 GST_START_TEST (dash_mpdparser_inherited_segmentURL)
4400 {
4401   GList *adaptationSets;
4402   GstAdaptationSetNode *adapt_set;
4403   GstActiveStream *activeStream;
4404   GstMediaFragmentInfo fragment;
4405   GstClockTime expectedDuration;
4406   GstClockTime expectedTimestamp;
4407   GstFlowReturn flow;
4408 
4409   const gchar *xml =
4410       "<?xml version=\"1.0\"?>"
4411       "<MPD xmlns=\"urn:mpeg:dash:schema:mpd:2011\""
4412       "     profiles=\"urn:mpeg:dash:profile:isoff-main:2011\""
4413       "     availabilityStartTime=\"2015-03-24T0:0:0\""
4414       "     mediaPresentationDuration=\"P0Y0M0DT3H3M30S\">"
4415       "  <Period start=\"P0Y0M0DT0H0M10S\">"
4416       "    <AdaptationSet mimeType=\"video/mp4\">"
4417       "      <SegmentList duration=\"100\">"
4418       "        <SegmentURL media=\"TestMediaAdaptation\""
4419       "                    mediaRange=\"10-20\""
4420       "                    index=\"TestIndexAdaptation\""
4421       "                    indexRange=\"30-40\">"
4422       "        </SegmentURL>"
4423       "      </SegmentList>"
4424       "      <Representation id=\"1\" bandwidth=\"250000\">"
4425       "        <SegmentList duration=\"110\">"
4426       "          <SegmentURL media=\"TestMediaRep\""
4427       "                      mediaRange=\"100-200\""
4428       "                      index=\"TestIndexRep\""
4429       "                      indexRange=\"300-400\">"
4430       "          </SegmentURL>"
4431       "        </SegmentList>"
4432       "      </Representation></AdaptationSet></Period></MPD>";
4433 
4434   gboolean ret;
4435   GstMpdClient *mpdclient = gst_mpd_client_new ();
4436 
4437   ret = gst_mpd_parse (mpdclient, xml, (gint) strlen (xml));
4438   assert_equals_int (ret, TRUE);
4439 
4440   /* process the xml data */
4441   ret =
4442       gst_mpd_client_setup_media_presentation (mpdclient, GST_CLOCK_TIME_NONE,
4443       -1, NULL);
4444   assert_equals_int (ret, TRUE);
4445 
4446   /* get the list of adaptation sets of the first period */
4447   adaptationSets = gst_mpd_client_get_adaptation_sets (mpdclient);
4448   fail_if (adaptationSets == NULL);
4449 
4450   /* setup streaming from the first adaptation set */
4451   adapt_set = (GstAdaptationSetNode *) g_list_nth_data (adaptationSets, 0);
4452   fail_if (adapt_set == NULL);
4453   ret = gst_mpd_client_setup_streaming (mpdclient, adapt_set);
4454   assert_equals_int (ret, TRUE);
4455 
4456   activeStream = gst_mpdparser_get_active_stream_by_index (mpdclient, 0);
4457   fail_if (activeStream == NULL);
4458 
4459   /* expected duration of the next fragment
4460    * Segment duration was set to 100 in AdaptationSet and to 110 in Representation
4461    * We expect duration to be 110
4462    */
4463   expectedDuration = duration_to_ms (0, 0, 0, 0, 0, 110, 0);
4464   expectedTimestamp = duration_to_ms (0, 0, 0, 0, 0, 0, 0);
4465 
4466   /* the representation contains 1 segment (the one from Representation) */
4467 
4468   /* check first segment */
4469   ret = gst_mpd_client_get_next_fragment (mpdclient, 0, &fragment);
4470   assert_equals_int (ret, TRUE);
4471   assert_equals_string (fragment.uri, "/TestMediaRep");
4472   assert_equals_int64 (fragment.range_start, 100);
4473   assert_equals_int64 (fragment.range_end, 200);
4474   assert_equals_string (fragment.index_uri, "/TestIndexRep");
4475   assert_equals_int64 (fragment.index_range_start, 300);
4476   assert_equals_int64 (fragment.index_range_end, 400);
4477   assert_equals_uint64 (fragment.duration, expectedDuration * GST_MSECOND);
4478   assert_equals_uint64 (fragment.timestamp, expectedTimestamp * GST_MSECOND);
4479   gst_media_fragment_info_clear (&fragment);
4480 
4481   /* try to advance to next segment. Should fail */
4482   flow = gst_mpd_client_advance_segment (mpdclient, activeStream, TRUE);
4483   assert_equals_int (flow, GST_FLOW_EOS);
4484 
4485   gst_mpd_client_free (mpdclient);
4486 }
4487 
4488 GST_END_TEST;
4489 
4490 /*
4491  * Test segment list
4492  *
4493  */
GST_START_TEST(dash_mpdparser_segment_list)4494 GST_START_TEST (dash_mpdparser_segment_list)
4495 {
4496   GList *adaptationSets;
4497   GstAdaptationSetNode *adapt_set;
4498   GstActiveStream *activeStream;
4499   GstMediaFragmentInfo fragment;
4500   GstClockTime expectedDuration;
4501   GstClockTime expectedTimestamp;
4502   const gchar *xml =
4503       "<?xml version=\"1.0\"?>"
4504       "<MPD xmlns=\"urn:mpeg:dash:schema:mpd:2011\""
4505       "     profiles=\"urn:mpeg:dash:profile:isoff-main:2011\""
4506       "     availabilityStartTime=\"2015-03-24T0:0:0\""
4507       "     mediaPresentationDuration=\"P0Y0M0DT3H3M30S\">"
4508       "  <Period start=\"P0Y0M0DT0H0M10S\">"
4509       "    <AdaptationSet mimeType=\"video/mp4\">"
4510       "      <Representation id=\"1\" bandwidth=\"250000\">"
4511       "        <SegmentList duration=\"12000\">"
4512       "          <SegmentURL media=\"TestMedia\""
4513       "                      mediaRange=\"100-200\""
4514       "                      index=\"TestIndex\""
4515       "                      indexRange=\"300-400\">"
4516       "          </SegmentURL>"
4517       "        </SegmentList>"
4518       "      </Representation></AdaptationSet></Period></MPD>";
4519 
4520   gboolean ret;
4521   GstMpdClient *mpdclient = gst_mpd_client_new ();
4522 
4523   ret = gst_mpd_parse (mpdclient, xml, (gint) strlen (xml));
4524   assert_equals_int (ret, TRUE);
4525 
4526   /* process the xml data */
4527   ret =
4528       gst_mpd_client_setup_media_presentation (mpdclient, GST_CLOCK_TIME_NONE,
4529       -1, NULL);
4530   assert_equals_int (ret, TRUE);
4531 
4532   /* get the list of adaptation sets of the first period */
4533   adaptationSets = gst_mpd_client_get_adaptation_sets (mpdclient);
4534   fail_if (adaptationSets == NULL);
4535 
4536   /* setup streaming from the first adaptation set */
4537   adapt_set = (GstAdaptationSetNode *) g_list_nth_data (adaptationSets, 0);
4538   fail_if (adapt_set == NULL);
4539   ret = gst_mpd_client_setup_streaming (mpdclient, adapt_set);
4540   assert_equals_int (ret, TRUE);
4541 
4542   activeStream = gst_mpdparser_get_active_stream_by_index (mpdclient, 0);
4543   fail_if (activeStream == NULL);
4544 
4545   /* expected duration of the next fragment
4546    * Segment duration was set larger than period duration (12000 vs 11000).
4547    * We expect it to be limited to period duration.
4548    */
4549   expectedDuration = duration_to_ms (0, 0, 0, 3, 3, 20, 0);
4550   expectedTimestamp = duration_to_ms (0, 0, 0, 0, 0, 0, 0);
4551 
4552   ret = gst_mpd_client_get_next_fragment (mpdclient, 0, &fragment);
4553   assert_equals_int (ret, TRUE);
4554   assert_equals_string (fragment.uri, "/TestMedia");
4555   assert_equals_int64 (fragment.range_start, 100);
4556   assert_equals_int64 (fragment.range_end, 200);
4557   assert_equals_string (fragment.index_uri, "/TestIndex");
4558   assert_equals_int64 (fragment.index_range_start, 300);
4559   assert_equals_int64 (fragment.index_range_end, 400);
4560   assert_equals_uint64 (fragment.duration, expectedDuration * GST_MSECOND);
4561   assert_equals_uint64 (fragment.timestamp, expectedTimestamp * GST_MSECOND);
4562 
4563   gst_media_fragment_info_clear (&fragment);
4564 
4565   gst_mpd_client_free (mpdclient);
4566 }
4567 
4568 GST_END_TEST;
4569 
4570 /*
4571  * Test segment template
4572  *
4573  */
GST_START_TEST(dash_mpdparser_segment_template)4574 GST_START_TEST (dash_mpdparser_segment_template)
4575 {
4576   GList *adaptationSets;
4577   GstAdaptationSetNode *adapt_set;
4578   GstActiveStream *activeStream;
4579   GstMediaFragmentInfo fragment;
4580   GstClockTime expectedDuration;
4581   GstClockTime expectedTimestamp;
4582   GstClockTime periodStartTime;
4583   GstClockTime offset;
4584   GstClockTime lastFragmentTimestampEnd;
4585   const gchar *xml =
4586       "<?xml version=\"1.0\"?>"
4587       "<MPD xmlns=\"urn:mpeg:dash:schema:mpd:2011\""
4588       "     profiles=\"urn:mpeg:dash:profile:isoff-main:2011\""
4589       "     availabilityStartTime=\"2015-03-24T0:0:0\""
4590       "     mediaPresentationDuration=\"P0Y0M0DT3H3M30S\">"
4591       "  <Period start=\"P0Y0M0DT0H0M10S\">"
4592       "    <AdaptationSet mimeType=\"video/mp4\">"
4593       "      <Representation id=\"repId\" bandwidth=\"250000\">"
4594       "        <SegmentTemplate duration=\"12000\""
4595       "                         presentationTimeOffset=\"15\""
4596       "                         media=\"TestMedia_rep=$RepresentationID$number=$Number$bandwidth=$Bandwidth$time=$Time$\""
4597       "                         index=\"TestIndex\">"
4598       "        </SegmentTemplate>"
4599       "      </Representation></AdaptationSet></Period></MPD>";
4600 
4601   gboolean ret;
4602   GstMpdClient *mpdclient = gst_mpd_client_new ();
4603 
4604   ret = gst_mpd_parse (mpdclient, xml, (gint) strlen (xml));
4605   assert_equals_int (ret, TRUE);
4606 
4607   /* process the xml data */
4608   ret =
4609       gst_mpd_client_setup_media_presentation (mpdclient, GST_CLOCK_TIME_NONE,
4610       -1, NULL);
4611   assert_equals_int (ret, TRUE);
4612 
4613   /* get the list of adaptation sets of the first period */
4614   adaptationSets = gst_mpd_client_get_adaptation_sets (mpdclient);
4615   fail_if (adaptationSets == NULL);
4616 
4617   /* setup streaming from the first adaptation set */
4618   adapt_set = (GstAdaptationSetNode *) g_list_nth_data (adaptationSets, 0);
4619   fail_if (adapt_set == NULL);
4620   ret = gst_mpd_client_setup_streaming (mpdclient, adapt_set);
4621   assert_equals_int (ret, TRUE);
4622 
4623   activeStream = gst_mpdparser_get_active_stream_by_index (mpdclient, 0);
4624   fail_if (activeStream == NULL);
4625 
4626   /* expected duration of the next fragment
4627    * Segment duration was set larger than period duration (12000 vs 11000).
4628    * We expect it to not be limited to period duration.
4629    */
4630   expectedDuration = duration_to_ms (0, 0, 0, 0, 0, 12000, 0);
4631 
4632   /* while the period starts at 10ms, the fragment timestamp is supposed to be
4633    * 0ms. timestamps are starting from 0 at every period, and only the overall
4634    * composition of periods should consider the period start timestamp. In
4635    * dashdemux this is done by mapping the 0 fragment timestamp to a stream
4636    * time equal to the period start time.
4637    */
4638   expectedTimestamp = duration_to_ms (0, 0, 0, 0, 0, 0, 0);
4639 
4640   ret = gst_mpd_client_get_next_fragment (mpdclient, 0, &fragment);
4641   assert_equals_int (ret, TRUE);
4642   assert_equals_string (fragment.uri,
4643       "/TestMedia_rep=repIdnumber=1bandwidth=250000time=0");
4644   assert_equals_int64 (fragment.range_start, 0);
4645   assert_equals_int64 (fragment.range_end, -1);
4646   assert_equals_string (fragment.index_uri, "/TestIndex");
4647   assert_equals_int64 (fragment.index_range_start, 0);
4648   assert_equals_int64 (fragment.index_range_end, -1);
4649   assert_equals_uint64 (fragment.duration, expectedDuration * GST_MSECOND);
4650   assert_equals_uint64 (fragment.timestamp, expectedTimestamp * GST_MSECOND);
4651 
4652   periodStartTime = gst_mpd_parser_get_period_start_time (mpdclient);
4653   assert_equals_uint64 (periodStartTime, 10 * GST_SECOND);
4654 
4655   offset = gst_mpd_parser_get_stream_presentation_offset (mpdclient, 0);
4656   assert_equals_uint64 (offset, 15 * GST_SECOND);
4657 
4658   gst_media_fragment_info_clear (&fragment);
4659 
4660   /*
4661    * Period starts at 10s.
4662    * MPD has a duration of 3h3m30s, so period duration is 3h3m20s.
4663    * We expect the last fragment to end at period start + period duration: 3h3m30s
4664    */
4665   expectedTimestamp = duration_to_ms (0, 0, 0, 3, 3, 30, 0);
4666   gst_mpd_client_get_last_fragment_timestamp_end (mpdclient, 0,
4667       &lastFragmentTimestampEnd);
4668   assert_equals_uint64 (lastFragmentTimestampEnd,
4669       expectedTimestamp * GST_MSECOND);
4670 
4671   gst_mpd_client_free (mpdclient);
4672 }
4673 
4674 GST_END_TEST;
4675 
4676 /*
4677  * Test segment timeline
4678  *
4679  */
GST_START_TEST(dash_mpdparser_segment_timeline)4680 GST_START_TEST (dash_mpdparser_segment_timeline)
4681 {
4682   GList *adaptationSets;
4683   GstAdaptationSetNode *adapt_set;
4684   GstActiveStream *activeStream;
4685   GstMediaFragmentInfo fragment;
4686   GstClockTime expectedDuration;
4687   GstClockTime expectedTimestamp;
4688   GstFlowReturn flow;
4689   GstDateTime *segmentAvailability;
4690 
4691   const gchar *xml =
4692       "<?xml version=\"1.0\"?>"
4693       "<MPD xmlns=\"urn:mpeg:dash:schema:mpd:2011\""
4694       "     profiles=\"urn:mpeg:dash:profile:isoff-main:2011\""
4695       "     availabilityStartTime=\"2015-03-24T0:0:0\""
4696       "     mediaPresentationDuration=\"P0Y0M0DT3H3M30S\">"
4697       "  <Period start=\"P0Y0M0DT0H0M10S\">"
4698       "    <AdaptationSet mimeType=\"video/mp4\">"
4699       "      <SegmentList>"
4700       "        <SegmentTimeline>"
4701       "          <S t=\"10\"  d=\"20\" r=\"30\"></S>"
4702       "        </SegmentTimeline>"
4703       "      </SegmentList>"
4704       "      <Representation id=\"1\" bandwidth=\"250000\">"
4705       "        <SegmentList>"
4706       "          <SegmentTimeline>"
4707       "            <S t=\"3\"  d=\"2\" r=\"1\"></S>"
4708       "            <S t=\"10\" d=\"3\" r=\"0\"></S>"
4709       "          </SegmentTimeline>"
4710       "          <SegmentURL media=\"TestMedia0\""
4711       "                      index=\"TestIndex0\">"
4712       "          </SegmentURL>"
4713       "          <SegmentURL media=\"TestMedia1\""
4714       "                      index=\"TestIndex1\">"
4715       "          </SegmentURL>"
4716       "        </SegmentList>"
4717       "      </Representation></AdaptationSet></Period></MPD>";
4718 
4719   gboolean ret;
4720   GstMpdClient *mpdclient = gst_mpd_client_new ();
4721 
4722   ret = gst_mpd_parse (mpdclient, xml, (gint) strlen (xml));
4723   assert_equals_int (ret, TRUE);
4724 
4725   /* process the xml data */
4726   ret =
4727       gst_mpd_client_setup_media_presentation (mpdclient, GST_CLOCK_TIME_NONE,
4728       -1, NULL);
4729   assert_equals_int (ret, TRUE);
4730 
4731   /* get the list of adaptation sets of the first period */
4732   adaptationSets = gst_mpd_client_get_adaptation_sets (mpdclient);
4733   fail_if (adaptationSets == NULL);
4734 
4735   /* setup streaming from the first adaptation set */
4736   adapt_set = (GstAdaptationSetNode *) g_list_nth_data (adaptationSets, 0);
4737   fail_if (adapt_set == NULL);
4738   ret = gst_mpd_client_setup_streaming (mpdclient, adapt_set);
4739   assert_equals_int (ret, TRUE);
4740 
4741   activeStream = gst_mpdparser_get_active_stream_by_index (mpdclient, 0);
4742   fail_if (activeStream == NULL);
4743 
4744   /* expected duration of the next fragment */
4745   expectedDuration = duration_to_ms (0, 0, 0, 0, 0, 2, 0);
4746   expectedTimestamp = duration_to_ms (0, 0, 0, 0, 0, 3, 0);
4747 
4748   ret = gst_mpd_client_get_next_fragment (mpdclient, 0, &fragment);
4749   assert_equals_int (ret, TRUE);
4750   assert_equals_string (fragment.uri, "/TestMedia0");
4751   assert_equals_string (fragment.index_uri, "/TestIndex0");
4752   assert_equals_uint64 (fragment.duration, expectedDuration * GST_MSECOND);
4753   assert_equals_uint64 (fragment.timestamp, expectedTimestamp * GST_MSECOND);
4754   gst_media_fragment_info_clear (&fragment);
4755 
4756   /* first segment starts at 3s and has a duration of 2s.
4757    * We also add period start time (10s) so we expect a segment availability
4758    * start time of 15s
4759    */
4760   segmentAvailability =
4761       gst_mpd_client_get_next_segment_availability_start_time (mpdclient,
4762       activeStream);
4763   fail_unless (segmentAvailability != NULL);
4764   assert_equals_int (gst_date_time_get_year (segmentAvailability), 2015);
4765   assert_equals_int (gst_date_time_get_month (segmentAvailability), 3);
4766   assert_equals_int (gst_date_time_get_day (segmentAvailability), 24);
4767   assert_equals_int (gst_date_time_get_hour (segmentAvailability), 0);
4768   assert_equals_int (gst_date_time_get_minute (segmentAvailability), 0);
4769   assert_equals_int (gst_date_time_get_second (segmentAvailability), 15);
4770   gst_date_time_unref (segmentAvailability);
4771 
4772   /* advance to next segment */
4773   flow = gst_mpd_client_advance_segment (mpdclient, activeStream, TRUE);
4774   assert_equals_int (flow, GST_FLOW_OK);
4775 
4776   /* second segment starts after first ends */
4777   expectedTimestamp = expectedTimestamp + expectedDuration;
4778 
4779   /* check second segment.
4780    * It is a repeat of first segmentURL, because "r" in SegmentTimeline is 1
4781    */
4782   ret = gst_mpd_client_get_next_fragment (mpdclient, 0, &fragment);
4783   assert_equals_int (ret, TRUE);
4784   assert_equals_string (fragment.uri, "/TestMedia0");
4785   assert_equals_string (fragment.index_uri, "/TestIndex0");
4786   assert_equals_uint64 (fragment.duration, expectedDuration * GST_MSECOND);
4787   assert_equals_uint64 (fragment.timestamp, expectedTimestamp * GST_MSECOND);
4788   gst_media_fragment_info_clear (&fragment);
4789 
4790   /* first segment starts at 3s and has a duration of 2s.
4791    * Second segment starts when the first ends (5s) and has a duration of 2s,
4792    * so it ends at 7s.
4793    * We also add period start time (10s) so we expect a segment availability
4794    * start time of 17s
4795    */
4796   segmentAvailability =
4797       gst_mpd_client_get_next_segment_availability_start_time (mpdclient,
4798       activeStream);
4799   fail_unless (segmentAvailability != NULL);
4800   assert_equals_int (gst_date_time_get_year (segmentAvailability), 2015);
4801   assert_equals_int (gst_date_time_get_month (segmentAvailability), 3);
4802   assert_equals_int (gst_date_time_get_day (segmentAvailability), 24);
4803   assert_equals_int (gst_date_time_get_hour (segmentAvailability), 0);
4804   assert_equals_int (gst_date_time_get_minute (segmentAvailability), 0);
4805   assert_equals_int (gst_date_time_get_second (segmentAvailability), 17);
4806   gst_date_time_unref (segmentAvailability);
4807 
4808   /* advance to next segment */
4809   flow = gst_mpd_client_advance_segment (mpdclient, activeStream, TRUE);
4810   assert_equals_int (flow, GST_FLOW_OK);
4811 
4812   /* third segment has a small gap after the second ends  (t=10) */
4813   expectedDuration = duration_to_ms (0, 0, 0, 0, 0, 3, 0);
4814   expectedTimestamp = duration_to_ms (0, 0, 0, 0, 0, 10, 0);
4815 
4816   /* check third segment */
4817   ret = gst_mpd_client_get_next_fragment (mpdclient, 0, &fragment);
4818   assert_equals_int (ret, TRUE);
4819   assert_equals_string (fragment.uri, "/TestMedia1");
4820   assert_equals_string (fragment.index_uri, "/TestIndex1");
4821   assert_equals_uint64 (fragment.duration, expectedDuration * GST_MSECOND);
4822   assert_equals_uint64 (fragment.timestamp, expectedTimestamp * GST_MSECOND);
4823   gst_media_fragment_info_clear (&fragment);
4824 
4825   /* Third segment starts at 10s and has a duration of 3s so it ends at 13s.
4826    * We also add period start time (10s) so we expect a segment availability
4827    * start time of 23s
4828    */
4829   segmentAvailability =
4830       gst_mpd_client_get_next_segment_availability_start_time (mpdclient,
4831       activeStream);
4832   fail_unless (segmentAvailability != NULL);
4833   assert_equals_int (gst_date_time_get_year (segmentAvailability), 2015);
4834   assert_equals_int (gst_date_time_get_month (segmentAvailability), 3);
4835   assert_equals_int (gst_date_time_get_day (segmentAvailability), 24);
4836   assert_equals_int (gst_date_time_get_hour (segmentAvailability), 0);
4837   assert_equals_int (gst_date_time_get_minute (segmentAvailability), 0);
4838   assert_equals_int (gst_date_time_get_second (segmentAvailability), 23);
4839   gst_date_time_unref (segmentAvailability);
4840 
4841   gst_mpd_client_free (mpdclient);
4842 }
4843 
4844 GST_END_TEST;
4845 
4846 /*
4847  * Test SegmentList with multiple inherited segmentURLs
4848  *
4849  */
GST_START_TEST(dash_mpdparser_multiple_inherited_segmentURL)4850 GST_START_TEST (dash_mpdparser_multiple_inherited_segmentURL)
4851 {
4852   GList *adaptationSets;
4853   GstAdaptationSetNode *adapt_set;
4854   GstActiveStream *activeStream;
4855   GstMediaFragmentInfo fragment;
4856   GstClockTime expectedDuration;
4857   GstClockTime expectedTimestamp;
4858   GstFlowReturn flow;
4859 
4860   /*
4861    * Period duration is 30 seconds
4862    * Period start is 10 seconds. Thus, period duration is 20 seconds.
4863    *
4864    * There are 2 segments in the AdaptationSet segment list and 2 in the
4865    * Representation's segment list.
4866    * Segment duration is 5s for the Adaptation segments and 8s for
4867    * Representation segments.
4868    * Separately, each segment list (duration 2*5=10 or 2*8=16) fits comfortably
4869    * in the Period's 20s duration.
4870    *
4871    * We expect the Representation segments to overwrite the AdaptationSet segments.
4872    */
4873   const gchar *xml =
4874       "<?xml version=\"1.0\"?>"
4875       "<MPD xmlns=\"urn:mpeg:dash:schema:mpd:2011\""
4876       " profiles=\"urn:mpeg:dash:profile:isoff-main:2011\""
4877       " availabilityStartTime=\"2015-03-24T0:0:0\""
4878       " mediaPresentationDuration=\"P0Y0M0DT0H0M30S\">"
4879       "<Period start=\"P0Y0M0DT0H0M10S\">"
4880       "  <AdaptationSet mimeType=\"video/mp4\">"
4881       "    <SegmentList duration=\"5\">"
4882       "      <SegmentURL"
4883       "         media=\"TestMedia0\" mediaRange=\"10-20\""
4884       "         index=\"TestIndex0\" indexRange=\"100-200\""
4885       "      ></SegmentURL>"
4886       "      <SegmentURL"
4887       "         media=\"TestMedia1\" mediaRange=\"20-30\""
4888       "         index=\"TestIndex1\" indexRange=\"200-300\""
4889       "      ></SegmentURL>"
4890       "    </SegmentList>"
4891       "    <Representation id=\"1\" bandwidth=\"250000\">"
4892       "      <SegmentList duration=\"8\">"
4893       "        <SegmentURL"
4894       "           media=\"TestMedia2\" mediaRange=\"30-40\""
4895       "           index=\"TestIndex2\" indexRange=\"300-400\""
4896       "        ></SegmentURL>"
4897       "        <SegmentURL"
4898       "           media=\"TestMedia3\" mediaRange=\"40-50\""
4899       "           index=\"TestIndex3\" indexRange=\"400-500\""
4900       "        ></SegmentURL>"
4901       "      </SegmentList>"
4902       "    </Representation></AdaptationSet></Period></MPD>";
4903 
4904   gboolean ret;
4905   GstMpdClient *mpdclient = gst_mpd_client_new ();
4906 
4907   ret = gst_mpd_parse (mpdclient, xml, (gint) strlen (xml));
4908   assert_equals_int (ret, TRUE);
4909 
4910   /* process the xml data */
4911   ret = gst_mpd_client_setup_media_presentation (mpdclient, GST_CLOCK_TIME_NONE,
4912       -1, NULL);
4913   assert_equals_int (ret, TRUE);
4914 
4915   /* get the list of adaptation sets of the first period */
4916   adaptationSets = gst_mpd_client_get_adaptation_sets (mpdclient);
4917   fail_if (adaptationSets == NULL);
4918 
4919   /* setup streaming from the first adaptation set */
4920   adapt_set = (GstAdaptationSetNode *) g_list_nth_data (adaptationSets, 0);
4921   fail_if (adapt_set == NULL);
4922   ret = gst_mpd_client_setup_streaming (mpdclient, adapt_set);
4923   assert_equals_int (ret, TRUE);
4924 
4925   activeStream = gst_mpdparser_get_active_stream_by_index (mpdclient, 0);
4926   fail_if (activeStream == NULL);
4927 
4928   expectedDuration = duration_to_ms (0, 0, 0, 0, 0, 8, 0);
4929   expectedTimestamp = duration_to_ms (0, 0, 0, 0, 0, 0, 0);
4930 
4931   /* the representation contains 2 segments defined in the Representation
4932    *
4933    * Both will have the duration specified in the Representation (8)
4934    */
4935 
4936   /* check first segment */
4937   ret = gst_mpd_client_get_next_fragment (mpdclient, 0, &fragment);
4938   assert_equals_int (ret, TRUE);
4939   assert_equals_string (fragment.uri, "/TestMedia2");
4940   assert_equals_int64 (fragment.range_start, 30);
4941   assert_equals_int64 (fragment.range_end, 40);
4942   assert_equals_string (fragment.index_uri, "/TestIndex2");
4943   assert_equals_int64 (fragment.index_range_start, 300);
4944   assert_equals_int64 (fragment.index_range_end, 400);
4945   assert_equals_uint64 (fragment.duration, expectedDuration * GST_MSECOND);
4946   assert_equals_uint64 (fragment.timestamp, expectedTimestamp * GST_MSECOND);
4947   gst_media_fragment_info_clear (&fragment);
4948 
4949   /* advance to next segment */
4950   flow = gst_mpd_client_advance_segment (mpdclient, activeStream, TRUE);
4951   assert_equals_int (flow, GST_FLOW_OK);
4952 
4953   /* second segment starts after previous ends */
4954   expectedTimestamp = expectedTimestamp + expectedDuration;
4955 
4956   /* check second segment */
4957   ret = gst_mpd_client_get_next_fragment (mpdclient, 0, &fragment);
4958   assert_equals_int (ret, TRUE);
4959   assert_equals_string (fragment.uri, "/TestMedia3");
4960   assert_equals_int64 (fragment.range_start, 40);
4961   assert_equals_int64 (fragment.range_end, 50);
4962   assert_equals_string (fragment.index_uri, "/TestIndex3");
4963   assert_equals_int64 (fragment.index_range_start, 400);
4964   assert_equals_int64 (fragment.index_range_end, 500);
4965   assert_equals_uint64 (fragment.duration, expectedDuration * GST_MSECOND);
4966   assert_equals_uint64 (fragment.timestamp, expectedTimestamp * GST_MSECOND);
4967   gst_media_fragment_info_clear (&fragment);
4968 
4969   /* try to advance to the next segment. There isn't any, so it should fail */
4970   flow = gst_mpd_client_advance_segment (mpdclient, activeStream, TRUE);
4971   assert_equals_int (flow, GST_FLOW_EOS);
4972 
4973   gst_mpd_client_free (mpdclient);
4974 }
4975 
4976 GST_END_TEST;
4977 
4978 /*
4979  * Test SegmentList with multiple segmentURL
4980  *
4981  */
GST_START_TEST(dash_mpdparser_multipleSegmentURL)4982 GST_START_TEST (dash_mpdparser_multipleSegmentURL)
4983 {
4984   GList *adaptationSets;
4985   GstAdaptationSetNode *adapt_set;
4986   GstActiveStream *activeStream;
4987   GstMediaFragmentInfo fragment;
4988   GstClockTime expectedDuration;
4989   GstClockTime expectedTimestamp;
4990   GstFlowReturn flow;
4991 
4992   /*
4993    * Period duration is 30 seconds
4994    * Period start is 10 seconds. Thus, period duration is 20 seconds.
4995    *
4996    * Segment duration is 25 seconds. There are 2 segments in the list.
4997    * We expect first segment to have a duration of 20 seconds (limited by the period)
4998    * and the second segment to not exist.
4999    */
5000   const gchar *xml =
5001       "<?xml version=\"1.0\"?>"
5002       "<MPD xmlns=\"urn:mpeg:dash:schema:mpd:2011\""
5003       " profiles=\"urn:mpeg:dash:profile:isoff-main:2011\""
5004       " availabilityStartTime=\"2015-03-24T0:0:0\""
5005       " mediaPresentationDuration=\"P0Y0M0DT0H0M30S\">"
5006       "<Period start=\"P0Y0M0DT0H0M10S\">"
5007       "  <AdaptationSet mimeType=\"video/mp4\">"
5008       "    <Representation id=\"1\" bandwidth=\"250000\">"
5009       "      <SegmentList duration=\"25\">"
5010       "        <SegmentURL"
5011       "           media=\"TestMedia0\" mediaRange=\"10-20\""
5012       "           index=\"TestIndex0\" indexRange=\"100-200\""
5013       "        ></SegmentURL>"
5014       "        <SegmentURL"
5015       "           media=\"TestMedia1\" mediaRange=\"20-30\""
5016       "           index=\"TestIndex1\" indexRange=\"200-300\""
5017       "        ></SegmentURL>"
5018       "      </SegmentList>"
5019       "    </Representation></AdaptationSet></Period></MPD>";
5020 
5021   gboolean ret;
5022   GstMpdClient *mpdclient = gst_mpd_client_new ();
5023 
5024   ret = gst_mpd_parse (mpdclient, xml, (gint) strlen (xml));
5025   assert_equals_int (ret, TRUE);
5026 
5027   /* process the xml data */
5028   ret =
5029       gst_mpd_client_setup_media_presentation (mpdclient, GST_CLOCK_TIME_NONE,
5030       -1, NULL);
5031   assert_equals_int (ret, TRUE);
5032 
5033   /* get the list of adaptation sets of the first period */
5034   adaptationSets = gst_mpd_client_get_adaptation_sets (mpdclient);
5035   fail_if (adaptationSets == NULL);
5036 
5037   /* setup streaming from the first adaptation set */
5038   adapt_set = (GstAdaptationSetNode *) g_list_nth_data (adaptationSets, 0);
5039   fail_if (adapt_set == NULL);
5040   ret = gst_mpd_client_setup_streaming (mpdclient, adapt_set);
5041   assert_equals_int (ret, TRUE);
5042 
5043   activeStream = gst_mpdparser_get_active_stream_by_index (mpdclient, 0);
5044   fail_if (activeStream == NULL);
5045 
5046   expectedDuration = duration_to_ms (0, 0, 0, 0, 0, 20, 0);
5047   expectedTimestamp = duration_to_ms (0, 0, 0, 0, 0, 0, 0);
5048 
5049   /* the representation contains 2 segments. The first is partially
5050    * clipped, and the second entirely (and thus discarded).
5051    */
5052 
5053   /* check first segment */
5054   ret = gst_mpd_client_get_next_fragment (mpdclient, 0, &fragment);
5055   assert_equals_int (ret, TRUE);
5056   assert_equals_string (fragment.uri, "/TestMedia0");
5057   assert_equals_int64 (fragment.range_start, 10);
5058   assert_equals_int64 (fragment.range_end, 20);
5059   assert_equals_string (fragment.index_uri, "/TestIndex0");
5060   assert_equals_int64 (fragment.index_range_start, 100);
5061   assert_equals_int64 (fragment.index_range_end, 200);
5062   assert_equals_uint64 (fragment.duration, expectedDuration * GST_MSECOND);
5063   assert_equals_uint64 (fragment.timestamp, expectedTimestamp * GST_MSECOND);
5064   gst_media_fragment_info_clear (&fragment);
5065 
5066   /* advance to next segment */
5067   flow = gst_mpd_client_advance_segment (mpdclient, activeStream, TRUE);
5068   assert_equals_int (flow, GST_FLOW_EOS);
5069 
5070   gst_mpd_client_free (mpdclient);
5071 }
5072 
5073 GST_END_TEST;
5074 
5075 /*
5076  * Test parsing empty xml string
5077  *
5078  */
GST_START_TEST(dash_mpdparser_missing_xml)5079 GST_START_TEST (dash_mpdparser_missing_xml)
5080 {
5081   const gchar *xml = "";
5082 
5083   gboolean ret;
5084   GstMpdClient *mpdclient = gst_mpd_client_new ();
5085 
5086   ret = gst_mpd_parse (mpdclient, xml, (gint) strlen (xml));
5087   assert_equals_int (ret, FALSE);
5088 
5089   gst_mpd_client_free (mpdclient);
5090 }
5091 
5092 GST_END_TEST;
5093 
5094 /*
5095  * Test parsing an xml with no mpd tag
5096  *
5097  */
GST_START_TEST(dash_mpdparser_missing_mpd)5098 GST_START_TEST (dash_mpdparser_missing_mpd)
5099 {
5100   const gchar *xml = "<?xml version=\"1.0\"?>";
5101 
5102   gboolean ret;
5103   GstMpdClient *mpdclient = gst_mpd_client_new ();
5104 
5105   ret = gst_mpd_parse (mpdclient, xml, (gint) strlen (xml));
5106   assert_equals_int (ret, FALSE);
5107 
5108   gst_mpd_client_free (mpdclient);
5109 }
5110 
5111 GST_END_TEST;
5112 
5113 /*
5114  * Test parsing an MPD with a wrong end tag
5115  */
GST_START_TEST(dash_mpdparser_no_end_tag)5116 GST_START_TEST (dash_mpdparser_no_end_tag)
5117 {
5118   const gchar *xml =
5119       "<?xml version=\"1.0\"?>"
5120       "<MPD xmlns=\"urn:mpeg:dash:schema:mpd:2011\""
5121       "     profiles=\"urn:mpeg:dash:profile:isoff-main:2011\"> </NPD>";
5122 
5123   gboolean ret;
5124   GstMpdClient *mpdclient = gst_mpd_client_new ();
5125 
5126   ret = gst_mpd_parse (mpdclient, xml, (gint) strlen (xml));
5127   assert_equals_int (ret, FALSE);
5128 
5129   gst_mpd_client_free (mpdclient);
5130 }
5131 
5132 GST_END_TEST;
5133 
5134 /*
5135  * Test parsing an MPD with no default namespace
5136  */
GST_START_TEST(dash_mpdparser_no_default_namespace)5137 GST_START_TEST (dash_mpdparser_no_default_namespace)
5138 {
5139   const gchar *xml =
5140       "<?xml version=\"1.0\"?>"
5141       "<MPD profiles=\"urn:mpeg:dash:profile:isoff-main:2011\"></MPD>";
5142 
5143   gboolean ret;
5144   GstMpdClient *mpdclient = gst_mpd_client_new ();
5145 
5146   ret = gst_mpd_parse (mpdclient, xml, strlen (xml));
5147   assert_equals_int (ret, TRUE);
5148 
5149   gst_mpd_client_free (mpdclient);
5150 }
5151 
5152 GST_END_TEST;
5153 
5154 /*
5155  * Test handling wrong period duration during attempts to
5156  * infer a period duration from the start time of the next period
5157  */
GST_START_TEST(dash_mpdparser_wrong_period_duration_inferred_from_next_period)5158 GST_START_TEST (dash_mpdparser_wrong_period_duration_inferred_from_next_period)
5159 {
5160   const gchar *periodName;
5161 
5162   const gchar *xml =
5163       "<?xml version=\"1.0\"?>"
5164       "<MPD xmlns=\"urn:mpeg:dash:schema:mpd:2011\""
5165       "     profiles=\"urn:mpeg:dash:profile:isoff-main:2011\""
5166       "     availabilityStartTime=\"2015-03-24T0:0:0\""
5167       "     mediaPresentationDuration=\"P0Y0M0DT3H3M30S\">"
5168       "  <Period id=\"Period0\" duration=\"P0Y0M0DT1H1M0S\"></Period>"
5169       "  <Period id=\"Period1\"></Period>"
5170       "  <Period id=\"Period2\" start=\"P0Y0M0DT0H0M10S\"></Period></MPD>";
5171 
5172   gboolean ret;
5173   GstMpdClient *mpdclient = gst_mpd_client_new ();
5174 
5175   ret = gst_mpd_parse (mpdclient, xml, (gint) strlen (xml));
5176   assert_equals_int (ret, TRUE);
5177 
5178   /* period_idx should be 0 and we should have no active periods */
5179   assert_equals_uint64 (mpdclient->period_idx, 0);
5180   fail_unless (mpdclient->periods == NULL);
5181 
5182   /* process the xml data */
5183   ret =
5184       gst_mpd_client_setup_media_presentation (mpdclient, GST_CLOCK_TIME_NONE,
5185       -1, NULL);
5186   assert_equals_int (ret, TRUE);
5187 
5188   /* Period0 should be present */
5189   fail_unless (mpdclient->periods != NULL);
5190   periodName = gst_mpd_client_get_period_id (mpdclient);
5191   assert_equals_string (periodName, "Period0");
5192 
5193   /* Period1 should not be present due to wrong duration */
5194   ret = gst_mpd_client_set_period_index (mpdclient, 1);
5195   assert_equals_int (ret, FALSE);
5196 
5197   gst_mpd_client_free (mpdclient);
5198 }
5199 
5200 GST_END_TEST;
5201 
5202 /*
5203  * Test handling wrong period duration during attempts to
5204  * infer a period duration from the mediaPresentationDuration
5205  */
GST_START_TEST(dash_mpdparser_wrong_period_duration_inferred_from_next_mediaPresentationDuration)5206 GST_START_TEST
5207     (dash_mpdparser_wrong_period_duration_inferred_from_next_mediaPresentationDuration)
5208 {
5209   const gchar *xml =
5210       "<?xml version=\"1.0\"?>"
5211       "<MPD xmlns=\"urn:mpeg:dash:schema:mpd:2011\""
5212       "     profiles=\"urn:mpeg:dash:profile:isoff-main:2011\""
5213       "     availabilityStartTime=\"2015-03-24T0:0:0\""
5214       "     mediaPresentationDuration=\"P0Y0M0DT3H3M30S\">"
5215       "  <Period id=\"Period0\" start=\"P0Y0M0DT4H0M0S\"></Period></MPD>";
5216 
5217   gboolean ret;
5218   GstMpdClient *mpdclient = gst_mpd_client_new ();
5219 
5220   ret = gst_mpd_parse (mpdclient, xml, (gint) strlen (xml));
5221   assert_equals_int (ret, TRUE);
5222 
5223   /* period_idx should be 0 and we should have no active periods */
5224   assert_equals_uint64 (mpdclient->period_idx, 0);
5225   fail_unless (mpdclient->periods == NULL);
5226 
5227   /* process the xml data
5228    * should fail due to wrong duration in Period0 (start > mediaPresentationDuration)
5229    */
5230   ret =
5231       gst_mpd_client_setup_media_presentation (mpdclient, GST_CLOCK_TIME_NONE,
5232       -1, NULL);
5233   assert_equals_int (ret, FALSE);
5234 
5235   gst_mpd_client_free (mpdclient);
5236 }
5237 
5238 GST_END_TEST;
5239 
GST_START_TEST(dash_mpdparser_whitespace_strings)5240 GST_START_TEST (dash_mpdparser_whitespace_strings)
5241 {
5242   fail_unless (gst_mpdparser_validate_no_whitespace ("") == TRUE);
5243   fail_unless (gst_mpdparser_validate_no_whitespace ("/") == TRUE);
5244   fail_unless (gst_mpdparser_validate_no_whitespace (" ") == FALSE);
5245   fail_unless (gst_mpdparser_validate_no_whitespace ("aaaaaaaa ") == FALSE);
5246   fail_unless (gst_mpdparser_validate_no_whitespace ("a\ta") == FALSE);
5247   fail_unless (gst_mpdparser_validate_no_whitespace ("a\ra") == FALSE);
5248   fail_unless (gst_mpdparser_validate_no_whitespace ("a\na") == FALSE);
5249 }
5250 
5251 GST_END_TEST;
5252 
GST_START_TEST(dash_mpdparser_rfc1738_strings)5253 GST_START_TEST (dash_mpdparser_rfc1738_strings)
5254 {
5255   fail_unless (gst_mpdparser_validate_rfc1738_url ("/") == TRUE);
5256   fail_unless (gst_mpdparser_validate_rfc1738_url (" ") == FALSE);
5257   fail_unless (gst_mpdparser_validate_rfc1738_url ("aaaaaaaa ") == FALSE);
5258 
5259   fail_unless (gst_mpdparser_validate_rfc1738_url ("") == TRUE);
5260   fail_unless (gst_mpdparser_validate_rfc1738_url ("a") == TRUE);
5261   fail_unless (gst_mpdparser_validate_rfc1738_url
5262       (";:@&=aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ0123456789$-_.+!*'(),%AA")
5263       == TRUE);
5264   fail_unless (gst_mpdparser_validate_rfc1738_url
5265       (";:@&=aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ0123456789$-_.+!*'(),/%AA")
5266       == TRUE);
5267   fail_unless (gst_mpdparser_validate_rfc1738_url
5268       (";:@&=aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ0123456789$-_.+!*'(),% ")
5269       == FALSE);
5270   fail_unless (gst_mpdparser_validate_rfc1738_url ("%AA") == TRUE);
5271   fail_unless (gst_mpdparser_validate_rfc1738_url ("%A") == FALSE);
5272   fail_unless (gst_mpdparser_validate_rfc1738_url ("%") == FALSE);
5273   fail_unless (gst_mpdparser_validate_rfc1738_url ("%XA") == FALSE);
5274   fail_unless (gst_mpdparser_validate_rfc1738_url ("%AX") == FALSE);
5275   fail_unless (gst_mpdparser_validate_rfc1738_url ("%XX") == FALSE);
5276   fail_unless (gst_mpdparser_validate_rfc1738_url ("\001") == FALSE);
5277 }
5278 
5279 GST_END_TEST;
5280 
5281 /*
5282  * Test negative period duration
5283  */
GST_START_TEST(dash_mpdparser_negative_period_duration)5284 GST_START_TEST (dash_mpdparser_negative_period_duration)
5285 {
5286   const gchar *xml =
5287       "<?xml version=\"1.0\"?>"
5288       "<MPD xmlns=\"urn:mpeg:dash:schema:mpd:2011\""
5289       "     profiles=\"urn:mpeg:dash:profile:isoff-main:2011\""
5290       "     availabilityStartTime=\"2015-03-24T0:0:0\""
5291       "     mediaPresentationDuration=\"P0Y0M0DT3H3M30S\">"
5292       "  <Period id=\"Period0\""
5293       "          start=\"P0Y0M0DT1H0M0S\""
5294       "          duration=\"-PT10S\">"
5295       "  </Period><Period id=\"Period1\"></Period></MPD>";
5296 
5297   gboolean ret;
5298   GstMpdClient *mpdclient = gst_mpd_client_new ();
5299 
5300   ret = gst_mpd_parse (mpdclient, xml, (gint) strlen (xml));
5301   assert_equals_int (ret, TRUE);
5302 
5303   /* process the xml data
5304    * should fail due to negative duration of Period0
5305    */
5306   ret = gst_mpd_client_setup_media_presentation (mpdclient, GST_CLOCK_TIME_NONE,
5307       -1, NULL);
5308   assert_equals_int (ret, FALSE);
5309 
5310   gst_mpd_client_free (mpdclient);
5311 }
5312 
5313 GST_END_TEST;
5314 
5315 /*
5316  * Test parsing negative values from attributes that should be unsigned
5317  *
5318  */
GST_START_TEST(dash_mpdparser_read_unsigned_from_negative_values)5319 GST_START_TEST (dash_mpdparser_read_unsigned_from_negative_values)
5320 {
5321   GstPeriodNode *periodNode;
5322   GstSegmentBaseType *segmentBase;
5323   GstAdaptationSetNode *adaptationSet;
5324   GstRepresentationNode *representation;
5325   GstSubRepresentationNode *subRepresentation;
5326 
5327   const gchar *xml =
5328       "<?xml version=\"1.0\"?>"
5329       "<MPD xmlns=\"urn:mpeg:dash:schema:mpd:2011\""
5330       "     profiles=\"urn:mpeg:dash:profile:isoff-main:2011\""
5331       "     availabilityStartTime=\"2015--1-13T12:25:37\">"
5332       "  <Period start=\"-P-2015Y\" duration=\"-P-5M\">"
5333       "    <SegmentBase presentationTimeOffset=\"-10\""
5334       "                 timescale=\"-5\""
5335       "                 indexRange=\"1--10\">"
5336       "    </SegmentBase>"
5337       "    <AdaptationSet par=\"-1:7\""
5338       "                   minFrameRate=\" -1\""
5339       "                   segmentAlignment=\"-4\">"
5340       "      <Representation id=\"1\" bandwidth=\"250000\">"
5341       "        <SubRepresentation dependencyLevel=\"1 -2 3\">"
5342       "        </SubRepresentation>"
5343       "      </Representation></AdaptationSet></Period></MPD>";
5344 
5345   gboolean ret;
5346   GstMpdClient *mpdclient = gst_mpd_client_new ();
5347 
5348   ret = gst_mpd_parse (mpdclient, xml, (gint) strlen (xml));
5349   assert_equals_int (ret, TRUE);
5350 
5351   periodNode = (GstPeriodNode *) mpdclient->mpd_node->Periods->data;
5352   segmentBase = periodNode->SegmentBase;
5353   adaptationSet = (GstAdaptationSetNode *) periodNode->AdaptationSets->data;
5354   representation = (GstRepresentationNode *)
5355       adaptationSet->Representations->data;
5356   subRepresentation = (GstSubRepresentationNode *)
5357       representation->SubRepresentations->data;
5358 
5359   /* availabilityStartTime parsing should fail */
5360   fail_if (mpdclient->mpd_node->availabilityStartTime != NULL);
5361 
5362   /* Period start parsing should fail */
5363   assert_equals_int64 (periodNode->start, -1);
5364 
5365   /* Period duration parsing should fail */
5366   assert_equals_int64 (periodNode->duration, -1);
5367 
5368   /* expect negative value to be rejected and presentationTimeOffset to be 0 */
5369   assert_equals_uint64 (segmentBase->presentationTimeOffset, 0);
5370   assert_equals_uint64 (segmentBase->timescale, 1);
5371   fail_if (segmentBase->indexRange != NULL);
5372 
5373   /* par ratio parsing should fail */
5374   fail_if (adaptationSet->par != NULL);
5375 
5376   /* minFrameRate parsing should fail */
5377   fail_if (adaptationSet->RepresentationBase->minFrameRate != NULL);
5378 
5379   /* segmentAlignment parsing should fail */
5380   fail_if (adaptationSet->segmentAlignment != NULL);
5381 
5382   /* dependency level parsing should fail */
5383   fail_if (subRepresentation->dependencyLevel != NULL);
5384 
5385   gst_mpd_client_free (mpdclient);
5386 }
5387 
5388 GST_END_TEST;
5389 
5390 /*
5391  * Test negative mediaPresentationDuration duration
5392  */
GST_START_TEST(dash_mpdparser_negative_mediaPresentationDuration)5393 GST_START_TEST (dash_mpdparser_negative_mediaPresentationDuration)
5394 {
5395   const gchar *xml =
5396       "<?xml version=\"1.0\"?>"
5397       "<MPD xmlns=\"urn:mpeg:dash:schema:mpd:2011\""
5398       "     profiles=\"urn:mpeg:dash:profile:isoff-main:2011\""
5399       "     availabilityStartTime=\"2015-03-24T0:0:0\""
5400       "     mediaPresentationDuration=\"-P0Y0M0DT3H3M30S\">"
5401       "  <Period id=\"Period0\" start=\"P0Y0M0DT1H0M0S\"></Period></MPD>";
5402 
5403   gboolean ret;
5404   GstMpdClient *mpdclient = gst_mpd_client_new ();
5405 
5406   ret = gst_mpd_parse (mpdclient, xml, (gint) strlen (xml));
5407   assert_equals_int (ret, TRUE);
5408 
5409   /* process the xml data
5410    * should fail due to negative duration of mediaPresentationDuration
5411    */
5412   ret = gst_mpd_client_setup_media_presentation (mpdclient, GST_CLOCK_TIME_NONE,
5413       -1, NULL);
5414   assert_equals_int (ret, FALSE);
5415 
5416   gst_mpd_client_free (mpdclient);
5417 }
5418 
5419 GST_END_TEST;
5420 
5421 /*
5422  * Test parsing an MPD with no profiles
5423  */
GST_START_TEST(dash_mpdparser_no_profiles)5424 GST_START_TEST (dash_mpdparser_no_profiles)
5425 {
5426   const gchar *xml =
5427       "<?xml version=\"1.0\"?>"
5428       "<MPD xmlns=\"urn:mpeg:dash:schema:mpd:2011\"></MPD>";
5429 
5430   gboolean ret;
5431   GstMpdClient *mpdclient = gst_mpd_client_new ();
5432 
5433   ret = gst_mpd_parse (mpdclient, xml, strlen (xml));
5434 
5435   assert_equals_int (ret, TRUE);
5436 
5437   gst_mpd_client_free (mpdclient);
5438 }
5439 
5440 GST_END_TEST;
5441 
5442 /*
5443  * Test S node list greater than SegmentURL list
5444  *
5445  */
GST_START_TEST(dash_mpdparser_unmatched_segmentTimeline_segmentURL)5446 GST_START_TEST (dash_mpdparser_unmatched_segmentTimeline_segmentURL)
5447 {
5448   GList *adaptationSets;
5449   GstAdaptationSetNode *adapt_set;
5450 
5451   const gchar *xml =
5452       "<?xml version=\"1.0\"?>"
5453       "<MPD xmlns=\"urn:mpeg:dash:schema:mpd:2011\""
5454       "     profiles=\"urn:mpeg:dash:profile:isoff-main:2011\""
5455       "     availabilityStartTime=\"2015-03-24T0:0:0\""
5456       "     mediaPresentationDuration=\"P0Y0M0DT3H3M30S\">"
5457       "  <Period start=\"P0Y0M0DT0H0M10S\">"
5458       "    <AdaptationSet mimeType=\"video/mp4\">"
5459       "      <Representation id=\"1\" bandwidth=\"250000\">"
5460       "        <SegmentList>"
5461       "          <SegmentTimeline>"
5462       "            <S t=\"3\"  d=\"2\" r=\"1\"></S>"
5463       "            <S t=\"10\" d=\"3\" r=\"0\"></S>"
5464       "          </SegmentTimeline>"
5465       "          <SegmentURL media=\"TestMedia0\""
5466       "                      index=\"TestIndex0\">"
5467       "          </SegmentURL>"
5468       "        </SegmentList>"
5469       "      </Representation></AdaptationSet></Period></MPD>";
5470 
5471   gboolean ret;
5472   GstMpdClient *mpdclient = gst_mpd_client_new ();
5473 
5474   ret = gst_mpd_parse (mpdclient, xml, (gint) strlen (xml));
5475   assert_equals_int (ret, TRUE);
5476 
5477   /* process the xml data */
5478   ret = gst_mpd_client_setup_media_presentation (mpdclient, GST_CLOCK_TIME_NONE,
5479       -1, NULL);
5480   assert_equals_int (ret, TRUE);
5481 
5482   /* get the list of adaptation sets of the first period */
5483   adaptationSets = gst_mpd_client_get_adaptation_sets (mpdclient);
5484   fail_if (adaptationSets == NULL);
5485 
5486   adapt_set = (GstAdaptationSetNode *) g_list_nth_data (adaptationSets, 0);
5487   fail_if (adapt_set == NULL);
5488 
5489   /* setup streaming from the first adaptation set.
5490    * Should fail because the second S node does not have a  matching
5491    * SegmentURL node
5492    */
5493   ret = gst_mpd_client_setup_streaming (mpdclient, adapt_set);
5494   assert_equals_int (ret, FALSE);
5495 
5496   gst_mpd_client_free (mpdclient);
5497 }
5498 
5499 GST_END_TEST;
5500 
5501 /*
5502  * Test parsing of the default presentation delay property
5503  */
GST_START_TEST(dash_mpdparser_default_presentation_delay)5504 GST_START_TEST (dash_mpdparser_default_presentation_delay)
5505 {
5506   const gchar *xml =
5507       "<?xml version=\"1.0\"?>"
5508       "<MPD xmlns=\"urn:mpeg:dash:schema:mpd:2011\""
5509       "     profiles=\"urn:mpeg:dash:profile:isoff-main:2011\""
5510       "     maxSegmentDuration=\"PT2S\">"
5511       "  <Period id=\"Period0\" start=\"P0S\"></Period></MPD>";
5512 
5513   gboolean ret;
5514   GstMpdClient *mpdclient = gst_mpd_client_new ();
5515   gint64 value;
5516 
5517   ret = gst_mpd_parse (mpdclient, xml, (gint) strlen (xml));
5518   assert_equals_int (ret, TRUE);
5519   value = gst_mpd_client_parse_default_presentation_delay (mpdclient, "5s");
5520   assert_equals_int64 (value, 5000);
5521   value = gst_mpd_client_parse_default_presentation_delay (mpdclient, "5S");
5522   assert_equals_int64 (value, 5000);
5523   value =
5524       gst_mpd_client_parse_default_presentation_delay (mpdclient, "5 seconds");
5525   assert_equals_int64 (value, 5000);
5526   value = gst_mpd_client_parse_default_presentation_delay (mpdclient, "2500ms");
5527   assert_equals_int64 (value, 2500);
5528   value = gst_mpd_client_parse_default_presentation_delay (mpdclient, "3f");
5529   assert_equals_int64 (value, 6000);
5530   value = gst_mpd_client_parse_default_presentation_delay (mpdclient, "3F");
5531   assert_equals_int64 (value, 6000);
5532   value = gst_mpd_client_parse_default_presentation_delay (mpdclient, "");
5533   assert_equals_int64 (value, 0);
5534   value = gst_mpd_client_parse_default_presentation_delay (mpdclient, "10");
5535   assert_equals_int64 (value, 0);
5536   value =
5537       gst_mpd_client_parse_default_presentation_delay (mpdclient,
5538       "not a number");
5539   assert_equals_int64 (value, 0);
5540 
5541   gst_mpd_client_free (mpdclient);
5542 }
5543 
5544 GST_END_TEST;
5545 
GST_START_TEST(dash_mpdparser_duration)5546 GST_START_TEST (dash_mpdparser_duration)
5547 {
5548   guint64 v;
5549 
5550   fail_unless (gst_mpdparser_parse_duration ("", &v) == FALSE);
5551   fail_unless (gst_mpdparser_parse_duration (" ", &v) == FALSE);
5552   fail_unless (gst_mpdparser_parse_duration ("0", &v) == FALSE);
5553   fail_unless (gst_mpdparser_parse_duration ("D-1", &v) == FALSE);
5554   fail_unless (gst_mpdparser_parse_duration ("T", &v) == FALSE);
5555 
5556   fail_unless (gst_mpdparser_parse_duration ("P", &v) == TRUE);
5557   fail_unless (gst_mpdparser_parse_duration ("PT", &v) == TRUE);
5558   fail_unless (gst_mpdparser_parse_duration ("PX", &v) == FALSE);
5559   fail_unless (gst_mpdparser_parse_duration ("PPT", &v) == FALSE);
5560   fail_unless (gst_mpdparser_parse_duration ("PTT", &v) == FALSE);
5561 
5562   fail_unless (gst_mpdparser_parse_duration ("P1D", &v) == TRUE);
5563   fail_unless (gst_mpdparser_parse_duration ("P1D1D", &v) == FALSE);
5564   fail_unless (gst_mpdparser_parse_duration ("P1D1M", &v) == FALSE);
5565   fail_unless (gst_mpdparser_parse_duration ("P1M1D", &v) == TRUE);
5566   fail_unless (gst_mpdparser_parse_duration ("P1M1D1M", &v) == FALSE);
5567   fail_unless (gst_mpdparser_parse_duration ("P1M1D1D", &v) == FALSE);
5568 
5569   fail_unless (gst_mpdparser_parse_duration ("P0M0D", &v) == TRUE);
5570   fail_unless (gst_mpdparser_parse_duration ("P-1M", &v) == FALSE);
5571   fail_unless (gst_mpdparser_parse_duration ("P15M", &v) == FALSE);
5572   fail_unless (gst_mpdparser_parse_duration ("P-1D", &v) == FALSE);
5573   fail_unless (gst_mpdparser_parse_duration ("P35D", &v) == FALSE);
5574   fail_unless (gst_mpdparser_parse_duration ("P-1Y", &v) == FALSE);
5575   fail_unless (gst_mpdparser_parse_duration ("PT-1H", &v) == FALSE);
5576   fail_unless (gst_mpdparser_parse_duration ("PT25H", &v) == FALSE);
5577   fail_unless (gst_mpdparser_parse_duration ("PT-1M", &v) == FALSE);
5578   fail_unless (gst_mpdparser_parse_duration ("PT65M", &v) == FALSE);
5579   fail_unless (gst_mpdparser_parse_duration ("PT-1S", &v) == FALSE);
5580   /* seconds are allowed to be larger than 60 */
5581   fail_unless (gst_mpdparser_parse_duration ("PT65S", &v) == TRUE);
5582 
5583   fail_unless (gst_mpdparser_parse_duration ("PT1.1H", &v) == FALSE);
5584   fail_unless (gst_mpdparser_parse_duration ("PT1-1H", &v) == FALSE);
5585   fail_unless (gst_mpdparser_parse_duration ("PT1-H", &v) == FALSE);
5586   fail_unless (gst_mpdparser_parse_duration ("PT-H", &v) == FALSE);
5587   fail_unless (gst_mpdparser_parse_duration ("PTH", &v) == FALSE);
5588   fail_unless (gst_mpdparser_parse_duration ("PT0", &v) == FALSE);
5589   fail_unless (gst_mpdparser_parse_duration ("PT1.1S", &v) == TRUE);
5590   fail_unless (gst_mpdparser_parse_duration ("PT1.1.1S", &v) == FALSE);
5591 
5592   fail_unless (gst_mpdparser_parse_duration ("P585Y", &v) == FALSE);
5593   fail_unless (gst_mpdparser_parse_duration ("P584Y", &v) == TRUE);
5594 
5595   fail_unless (gst_mpdparser_parse_duration (" P10DT8H", &v) == TRUE);
5596   fail_unless (gst_mpdparser_parse_duration ("P10D T8H", &v) == FALSE);
5597   fail_unless (gst_mpdparser_parse_duration ("P10DT8H ", &v) == TRUE);
5598 }
5599 
5600 GST_END_TEST;
5601 
5602 /*
5603  * Test that the maximum_segment_duration correctly implements the
5604  * rules in the DASH specification
5605  */
GST_START_TEST(dash_mpdparser_maximum_segment_duration)5606 GST_START_TEST (dash_mpdparser_maximum_segment_duration)
5607 {
5608   const gchar *xml_template =
5609       "<?xml version=\"1.0\"?>"
5610       "<MPD xmlns=\"urn:mpeg:dash:schema:mpd:2011\""
5611       "     profiles=\"urn:mpeg:dash:profile:isoff-main:2011\""
5612       "     availabilityStartTime=\"2015-03-24T0:0:0\""
5613       "     %s "
5614       "     mediaPresentationDuration=\"P100Y\">"
5615       "  <Period id=\"Period0\" start=\"PT0S\">"
5616       "    <AdaptationSet mimeType=\"video/mp4\" >"
5617       "      <SegmentTemplate timescale=\"90000\" initialization=\"$RepresentationID$/Header.m4s\" media=\"$RepresentationID$/$Number$.m4s\" duration=\"360000\" />"
5618       "      <Representation id=\"video1\" width=\"576\" height=\"324\" frameRate=\"25\" sar=\"1:1\" bandwidth=\"900000\" codecs=\"avc1.4D401E\"/>"
5619       "    </AdaptationSet>"
5620       "      <AdaptationSet mimeType=\"audio/mp4\" >"
5621       "        <SegmentTemplate timescale=\"90000\" initialization=\"$RepresentationID$/Header.m4s\" media=\"$RepresentationID$/$Number$.m4s\" duration=\"340000\" />"
5622       "        <Representation id=\"audio1\" audioSamplingRate=\"22050\" bandwidth=\"29600\" codecs=\"mp4a.40.2\">"
5623       "        <AudioChannelConfiguration schemeIdUri=\"urn:mpeg:dash:23003:3:audio_channel_configuration:2011\" value=\"2\"/>"
5624       "      </Representation>" "    </AdaptationSet>" "  </Period></MPD>";
5625   gboolean ret;
5626   GstMpdClient *mpdclient;
5627   gchar *xml;
5628   GstClockTime dur;
5629   GList *adapt_sets, *iter;
5630 
5631   xml = g_strdup_printf (xml_template, "maxSegmentDuration=\"PT4.5S\"");
5632   mpdclient = gst_mpd_client_new ();
5633   ret = gst_mpd_parse (mpdclient, xml, (gint) strlen (xml));
5634   g_free (xml);
5635   assert_equals_int (ret, TRUE);
5636 
5637   assert_equals_uint64 (mpdclient->mpd_node->maxSegmentDuration,
5638       duration_to_ms (0, 0, 0, 0, 0, 4, 500));
5639   dur = gst_mpd_client_get_maximum_segment_duration (mpdclient);
5640   assert_equals_uint64 (dur, duration_to_clocktime (0, 0, 0, 0, 0, 4, 500));
5641   gst_mpd_client_free (mpdclient);
5642 
5643   /* now parse without the maxSegmentDuration attribute, to check that
5644      gst_mpd_client_get_maximum_segment_duration uses the maximum
5645      duration of any segment
5646    */
5647   xml = g_strdup_printf (xml_template, "");
5648   mpdclient = gst_mpd_client_new ();
5649   ret = gst_mpd_parse (mpdclient, xml, (gint) strlen (xml));
5650   g_free (xml);
5651   assert_equals_int (ret, TRUE);
5652   ret =
5653       gst_mpd_client_setup_media_presentation (mpdclient, GST_CLOCK_TIME_NONE,
5654       -1, NULL);
5655   assert_equals_int (ret, TRUE);
5656   adapt_sets = gst_mpd_client_get_adaptation_sets (mpdclient);
5657   for (iter = adapt_sets; iter; iter = g_list_next (iter)) {
5658     GstAdaptationSetNode *adapt_set_node = iter->data;
5659 
5660     ret = gst_mpd_client_setup_streaming (mpdclient, adapt_set_node);
5661     assert_equals_int (ret, TRUE);
5662   }
5663   dur = gst_mpd_client_get_maximum_segment_duration (mpdclient);
5664   assert_equals_uint64 (dur, duration_to_clocktime (0, 0, 0, 0, 0, 4, 0));
5665   gst_mpd_client_free (mpdclient);
5666 }
5667 
5668 GST_END_TEST;
5669 
5670 /*
5671  * Test parsing of Perioud using @xlink:href attribute
5672  */
5673 
5674 #define STRINGIFY_(x) #x
5675 #define STRINGIFY(x) STRINGIFY_ (x)
5676 #define REMOTEDIR STRINGIFY (DASH_MPD_DATADIR)
5677 #define XLINK_SINGLE_PERIOD_FILENAME REMOTEDIR "/xlink_single_period.period"
5678 #define XLINK_DOUBLE_PERIOD_FILENAME REMOTEDIR "/xlink_double_period.period"
5679 
GST_START_TEST(dash_mpdparser_xlink_period)5680 GST_START_TEST (dash_mpdparser_xlink_period)
5681 {
5682   GstPeriodNode *periodNode;
5683   GstUriDownloader *downloader;
5684   GstMpdClient *mpdclient;
5685   GList *period_list, *iter;
5686   gboolean ret;
5687   gchar *xml_joined, *file_uri_single_period, *file_uri_double_period;
5688   const gchar *xml_frag_start =
5689       "<?xml version=\"1.0\"?>"
5690       "<MPD xmlns=\"urn:mpeg:dash:schema:mpd:2011\""
5691       "     profiles=\"urn:mpeg:dash:profile:isoff-main:2011\">"
5692       "  <Period id=\"Period0\" duration=\"PT5S\"></Period>";
5693 
5694   const gchar *xml_uri_front = "  <Period xlink:href=\"";
5695 
5696   const gchar *xml_uri_rear =
5697       "\""
5698       "          xlink:actuate=\"onRequest\""
5699       "          xmlns:xlink=\"http://www.w3.org/1999/xlink\"></Period>";
5700 
5701   const gchar *xml_frag_end = "</MPD>";
5702 
5703   /* XLINK_ONE_PERIOD_FILENAME
5704    *
5705    * <Period id="xlink-single-period-Period1" duration="PT10S" xmlns="urn:mpeg:dash:schema:mpd:2011"></Period>
5706    */
5707 
5708   /* XLINK_TWO_PERIODS_FILENAME
5709    *
5710    * <Period id="xlink-double-period-Period1" duration="PT10S" xmlns="urn:mpeg:dash:schema:mpd:2011"></Period>
5711    * <Period id="xlink-double-period-Period2" duration="PT20S" xmlns="urn:mpeg:dash:schema:mpd:2011"></Period>
5712    */
5713 
5714 
5715   mpdclient = gst_mpd_client_new ();
5716   downloader = gst_uri_downloader_new ();
5717 
5718   gst_mpd_client_set_uri_downloader (mpdclient, downloader);
5719 
5720   file_uri_single_period =
5721       gst_filename_to_uri (XLINK_SINGLE_PERIOD_FILENAME, NULL);
5722   file_uri_double_period =
5723       gst_filename_to_uri (XLINK_DOUBLE_PERIOD_FILENAME, NULL);
5724 
5725   /* constructs inital mpd using external xml uri */
5726   /* For invalid URI, mpdparser should be ignore it */
5727   xml_joined = g_strjoin ("", xml_frag_start,
5728       xml_uri_front, "http://404/ERROR/XML.period", xml_uri_rear,
5729       xml_uri_front, (const char *) file_uri_single_period, xml_uri_rear,
5730       xml_uri_front, (const char *) file_uri_double_period, xml_uri_rear,
5731       xml_frag_end, NULL);
5732 
5733   ret = gst_mpd_parse (mpdclient, xml_joined, (gint) strlen (xml_joined));
5734   assert_equals_int (ret, TRUE);
5735 
5736   period_list = mpdclient->mpd_node->Periods;
5737   /* only count periods on initial mpd (external xml does not parsed yet) */
5738   assert_equals_int (g_list_length (period_list), 4);
5739 
5740   /* process the xml data */
5741   ret = gst_mpd_client_setup_media_presentation (mpdclient, GST_CLOCK_TIME_NONE,
5742       -1, NULL);
5743   assert_equals_int (ret, TRUE);
5744 
5745   period_list = mpdclient->mpd_node->Periods;
5746   assert_equals_int (g_list_length (period_list), 4);
5747 
5748   iter = period_list;
5749   periodNode = (GstPeriodNode *) iter->data;
5750   assert_equals_string (periodNode->id, "Period0");
5751 
5752   iter = iter->next;
5753   periodNode = (GstPeriodNode *) iter->data;
5754   assert_equals_string (periodNode->id, "xlink-single-period-Period1");
5755 
5756   iter = iter->next;
5757   periodNode = (GstPeriodNode *) iter->data;
5758   assert_equals_string (periodNode->id, "xlink-double-period-Period1");
5759 
5760   iter = iter->next;
5761   periodNode = (GstPeriodNode *) iter->data;
5762   assert_equals_string (periodNode->id, "xlink-double-period-Period2");
5763 
5764   gst_mpd_client_free (mpdclient);
5765   g_object_unref (downloader);
5766   g_free (file_uri_single_period);
5767   g_free (file_uri_double_period);
5768   g_free (xml_joined);
5769 }
5770 
5771 GST_END_TEST;
5772 
5773 
5774 /*
5775  * Test parsing xsd:datetime with timezoneoffset.
5776  *
5777  */
GST_START_TEST(dash_mpdparser_datetime_with_tz_offset)5778 GST_START_TEST (dash_mpdparser_datetime_with_tz_offset)
5779 {
5780   GstDateTime *availabilityStartTime;
5781   GstDateTime *availabilityEndTime;
5782   const gchar *xml =
5783       "<?xml version=\"1.0\"?>"
5784       "<MPD xmlns=\"urn:mpeg:dash:schema:mpd:2011\""
5785       "     profiles=\"urn:mpeg:dash:profile:isoff-main:2011\""
5786       "     schemaLocation=\"TestSchemaLocation\""
5787       "     xmlns:xsi=\"TestNamespaceXSI\""
5788       "     xmlns:ext=\"TestNamespaceEXT\""
5789       "     id=\"testId\""
5790       "     type=\"static\""
5791       "     availabilityStartTime=\"2015-03-24T1:10:50+08:00\""
5792       "     availabilityEndTime=\"2015-03-24T1:10:50.123456-04:30\""
5793       "     mediaPresentationDuration=\"P0Y1M2DT12H10M20.5S\""
5794       "     minimumUpdatePeriod=\"P0Y1M2DT12H10M20.5S\""
5795       "     minBufferTime=\"P0Y1M2DT12H10M20.5S\""
5796       "     timeShiftBufferDepth=\"P0Y1M2DT12H10M20.5S\""
5797       "     suggestedPresentationDelay=\"P0Y1M2DT12H10M20.5S\""
5798       "     maxSegmentDuration=\"P0Y1M2DT12H10M20.5S\""
5799       "     maxSubsegmentDuration=\"P0Y1M2DT12H10M20.5S\"></MPD>";
5800 
5801   gboolean ret;
5802   GstMpdClient *mpdclient = gst_mpd_client_new ();
5803 
5804   ret = gst_mpd_parse (mpdclient, xml, (gint) strlen (xml));
5805   assert_equals_int (ret, TRUE);
5806 
5807   availabilityStartTime = mpdclient->mpd_node->availabilityStartTime;
5808   assert_equals_int (gst_date_time_get_year (availabilityStartTime), 2015);
5809   assert_equals_int (gst_date_time_get_month (availabilityStartTime), 3);
5810   assert_equals_int (gst_date_time_get_day (availabilityStartTime), 24);
5811   assert_equals_int (gst_date_time_get_hour (availabilityStartTime), 1);
5812   assert_equals_int (gst_date_time_get_minute (availabilityStartTime), 10);
5813   assert_equals_int (gst_date_time_get_second (availabilityStartTime), 50);
5814   assert_equals_int (gst_date_time_get_microsecond (availabilityStartTime), 0);
5815   assert_equals_float (gst_date_time_get_time_zone_offset
5816       (availabilityStartTime), 8.0);
5817 
5818   availabilityEndTime = mpdclient->mpd_node->availabilityEndTime;
5819   assert_equals_int (gst_date_time_get_year (availabilityEndTime), 2015);
5820   assert_equals_int (gst_date_time_get_month (availabilityEndTime), 3);
5821   assert_equals_int (gst_date_time_get_day (availabilityEndTime), 24);
5822   assert_equals_int (gst_date_time_get_hour (availabilityEndTime), 1);
5823   assert_equals_int (gst_date_time_get_minute (availabilityEndTime), 10);
5824   assert_equals_int (gst_date_time_get_second (availabilityEndTime), 50);
5825   assert_equals_int (gst_date_time_get_microsecond (availabilityEndTime),
5826       123456);
5827   assert_equals_float (gst_date_time_get_time_zone_offset (availabilityEndTime),
5828       -4.5);
5829 
5830   gst_mpd_client_free (mpdclient);
5831 }
5832 
5833 GST_END_TEST;
5834 
5835 
5836 
5837 /*
5838  * create a test suite containing all dash testcases
5839  */
5840 static Suite *
dash_suite(void)5841 dash_suite (void)
5842 {
5843   Suite *s = suite_create ("dash");
5844   TCase *tc_simpleMPD = tcase_create ("simpleMPD");
5845   TCase *tc_complexMPD = tcase_create ("complexMPD");
5846   TCase *tc_negativeTests = tcase_create ("negativeTests");
5847   TCase *tc_stringTests = tcase_create ("stringTests");
5848   TCase *tc_duration = tcase_create ("duration");
5849 
5850   GST_DEBUG_CATEGORY_INIT (gst_dash_demux_debug, "gst_dash_demux_debug", 0,
5851       "mpeg dash tests");
5852 
5853   /* test parsing the simplest possible mpd */
5854   tcase_add_test (tc_simpleMPD, dash_mpdparser_validsimplempd);
5855 
5856   /* tests parsing attributes from each element type */
5857   tcase_add_test (tc_simpleMPD, dash_mpdparser_mpd);
5858   tcase_add_test (tc_simpleMPD, dash_mpdparser_datetime_with_tz_offset);
5859   tcase_add_test (tc_simpleMPD, dash_mpdparser_programInformation);
5860   tcase_add_test (tc_simpleMPD, dash_mpdparser_baseURL);
5861   tcase_add_test (tc_simpleMPD, dash_mpdparser_location);
5862   tcase_add_test (tc_simpleMPD, dash_mpdparser_metrics);
5863   tcase_add_test (tc_simpleMPD, dash_mpdparser_metrics_range);
5864   tcase_add_test (tc_simpleMPD, dash_mpdparser_metrics_reporting);
5865   tcase_add_test (tc_simpleMPD, dash_mpdparser_period);
5866   tcase_add_test (tc_simpleMPD, dash_mpdparser_period_baseURL);
5867   tcase_add_test (tc_simpleMPD, dash_mpdparser_period_segmentBase);
5868   tcase_add_test (tc_simpleMPD,
5869       dash_mpdparser_period_segmentBase_initialization);
5870   tcase_add_test (tc_simpleMPD,
5871       dash_mpdparser_period_segmentBase_representationIndex);
5872   tcase_add_test (tc_simpleMPD, dash_mpdparser_period_segmentList);
5873   tcase_add_test (tc_simpleMPD,
5874       dash_mpdparser_period_segmentList_multipleSegmentBaseType);
5875   tcase_add_test (tc_simpleMPD,
5876       dash_mpdparser_period_segmentList_multipleSegmentBaseType_segmentBaseType);
5877   tcase_add_test (tc_simpleMPD,
5878       dash_mpdparser_period_segmentList_multipleSegmentBaseType_segmentTimeline);
5879   tcase_add_test (tc_simpleMPD,
5880       dash_mpdparser_period_segmentList_multipleSegmentBaseType_segmentTimeline_s);
5881   tcase_add_test (tc_simpleMPD,
5882       dash_mpdparser_period_segmentList_multipleSegmentBaseType_bitstreamSwitching);
5883   tcase_add_test (tc_simpleMPD, dash_mpdparser_period_segmentList_segmentURL);
5884   tcase_add_test (tc_simpleMPD, dash_mpdparser_period_segmentTemplate);
5885   tcase_add_test (tc_simpleMPD,
5886       dash_mpdparser_period_segmentTemplate_multipleSegmentBaseType);
5887   tcase_add_test (tc_simpleMPD,
5888       dash_mpdparser_period_segmentTemplate_multipleSegmentBaseType_segmentBaseType);
5889   tcase_add_test (tc_simpleMPD,
5890       dash_mpdparser_period_segmentTemplate_multipleSegmentBaseType_segmentTimeline);
5891   tcase_add_test (tc_simpleMPD,
5892       dash_mpdparser_period_segmentTemplate_multipleSegmentBaseType_segmentTimeline_s);
5893   tcase_add_test (tc_simpleMPD,
5894       dash_mpdparser_period_segmentTemplate_multipleSegmentBaseType_bitstreamSwitching);
5895   tcase_add_test (tc_simpleMPD, dash_mpdparser_period_adaptationSet);
5896   tcase_add_test (tc_simpleMPD,
5897       dash_mpdparser_period_adaptationSet_representationBase);
5898   tcase_add_test (tc_simpleMPD,
5899       dash_mpdparser_period_adaptationSet_representationBase_framePacking);
5900   tcase_add_test (tc_simpleMPD,
5901       dash_mpdparser_adapt_repr_segmentTemplate_inherit);
5902   tcase_add_test (tc_simpleMPD,
5903       dash_mpdparser_period_adaptationSet_representationBase_audioChannelConfiguration);
5904   tcase_add_test (tc_simpleMPD,
5905       dash_mpdparser_period_adaptationSet_representationBase_contentProtection);
5906   tcase_add_test (tc_simpleMPD, dash_mpdparser_contentProtection_no_value);
5907   tcase_add_test (tc_simpleMPD,
5908       dash_mpdparser_contentProtection_no_value_no_encoding);
5909   tcase_add_test (tc_simpleMPD,
5910       dash_mpdparser_period_adaptationSet_accessibility);
5911   tcase_add_test (tc_simpleMPD, dash_mpdparser_period_adaptationSet_role);
5912   tcase_add_test (tc_simpleMPD, dash_mpdparser_period_adaptationSet_rating);
5913   tcase_add_test (tc_simpleMPD, dash_mpdparser_period_adaptationSet_viewpoint);
5914   tcase_add_test (tc_simpleMPD,
5915       dash_mpdparser_period_adaptationSet_contentComponent);
5916   tcase_add_test (tc_simpleMPD,
5917       dash_mpdparser_period_adaptationSet_contentComponent_accessibility);
5918   tcase_add_test (tc_simpleMPD,
5919       dash_mpdparser_period_adaptationSet_contentComponent_role);
5920   tcase_add_test (tc_simpleMPD,
5921       dash_mpdparser_period_adaptationSet_contentComponent_rating);
5922   tcase_add_test (tc_simpleMPD,
5923       dash_mpdparser_period_adaptationSet_contentComponent_viewpoint);
5924   tcase_add_test (tc_simpleMPD, dash_mpdparser_period_adaptationSet_baseURL);
5925   tcase_add_test (tc_simpleMPD,
5926       dash_mpdparser_period_adaptationSet_segmentBase);
5927   tcase_add_test (tc_simpleMPD,
5928       dash_mpdparser_period_adaptationSet_segmentBase_initialization);
5929   tcase_add_test (tc_simpleMPD,
5930       dash_mpdparser_period_adaptationSet_segmentBase_representationIndex);
5931   tcase_add_test (tc_simpleMPD,
5932       dash_mpdparser_period_adaptationSet_segmentList);
5933   tcase_add_test (tc_simpleMPD,
5934       dash_mpdparser_period_adaptationSet_segmentTemplate);
5935   tcase_add_test (tc_simpleMPD,
5936       dash_mpdparser_period_adaptationSet_segmentTemplate_inherit);
5937   tcase_add_test (tc_simpleMPD,
5938       dash_mpdparser_period_adaptationSet_representation);
5939   tcase_add_test (tc_simpleMPD,
5940       dash_mpdparser_period_adaptationSet_representation_representationBase);
5941   tcase_add_test (tc_simpleMPD,
5942       dash_mpdparser_period_adaptationSet_representation_baseURL);
5943   tcase_add_test (tc_simpleMPD,
5944       dash_mpdparser_period_adaptationSet_representation_subRepresentation);
5945   tcase_add_test (tc_simpleMPD,
5946       dash_mpdparser_period_adaptationSet_representation_subRepresentation_representationBase);
5947   tcase_add_test (tc_simpleMPD,
5948       dash_mpdparser_period_adaptationSet_representation_segmentBase);
5949   tcase_add_test (tc_simpleMPD,
5950       dash_mpdparser_period_adaptationSet_representation_segmentList);
5951   tcase_add_test (tc_simpleMPD,
5952       dash_mpdparser_period_adaptationSet_representation_segmentTemplate);
5953   tcase_add_test (tc_simpleMPD,
5954       dash_mpdparser_period_adaptationSet_representation_segmentTemplate_inherit);
5955   tcase_add_test (tc_simpleMPD,
5956       dash_mpdparser_period_adaptationSet_representation_segmentBase_inherit);
5957   tcase_add_test (tc_simpleMPD, dash_mpdparser_period_subset);
5958   tcase_add_test (tc_simpleMPD, dash_mpdparser_utctiming);
5959   tcase_add_test (tc_simpleMPD, dash_mpdparser_utctiming_invalid_value);
5960 
5961   /* tests checking other possible values for attributes */
5962   tcase_add_test (tc_simpleMPD, dash_mpdparser_type_dynamic);
5963   tcase_add_test (tc_simpleMPD, dash_mpdparser_template_parsing);
5964   tcase_add_test (tc_simpleMPD, dash_mpdparser_isoff_ondemand_profile);
5965   tcase_add_test (tc_simpleMPD, dash_mpdparser_GstDateTime);
5966   tcase_add_test (tc_simpleMPD, dash_mpdparser_bitstreamSwitching_inheritance);
5967   tcase_add_test (tc_simpleMPD, dash_mpdparser_various_duration_formats);
5968   tcase_add_test (tc_simpleMPD, dash_mpdparser_default_presentation_delay);
5969 
5970   /* tests checking xlink attributes */
5971   tcase_add_test (tc_simpleMPD, dash_mpdparser_xlink_period);
5972 
5973   /* tests checking the MPD management
5974    * (eg. setting active streams, obtaining attributes values)
5975    */
5976   tcase_add_test (tc_complexMPD, dash_mpdparser_setup_media_presentation);
5977   tcase_add_test (tc_complexMPD, dash_mpdparser_setup_streaming);
5978   tcase_add_test (tc_complexMPD, dash_mpdparser_period_selection);
5979   tcase_add_test (tc_complexMPD, dash_mpdparser_get_period_at_time);
5980   tcase_add_test (tc_complexMPD, dash_mpdparser_adaptationSet_handling);
5981   tcase_add_test (tc_complexMPD, dash_mpdparser_representation_selection);
5982   tcase_add_test (tc_complexMPD, dash_mpdparser_multipleSegmentURL);
5983   tcase_add_test (tc_complexMPD, dash_mpdparser_activeStream_selection);
5984   tcase_add_test (tc_complexMPD, dash_mpdparser_activeStream_parameters);
5985   tcase_add_test (tc_complexMPD, dash_mpdparser_get_audio_languages);
5986   tcase_add_test (tc_complexMPD, dash_mpdparser_get_baseURL1);
5987   tcase_add_test (tc_complexMPD, dash_mpdparser_get_baseURL2);
5988   tcase_add_test (tc_complexMPD, dash_mpdparser_get_baseURL3);
5989   tcase_add_test (tc_complexMPD, dash_mpdparser_get_baseURL4);
5990   tcase_add_test (tc_complexMPD, dash_mpdparser_get_baseURL5);
5991   tcase_add_test (tc_complexMPD, dash_mpdparser_get_baseURL6);
5992   tcase_add_test (tc_complexMPD, dash_mpdparser_get_baseURL7);
5993   tcase_add_test (tc_complexMPD, dash_mpdparser_get_baseURL8);
5994   tcase_add_test (tc_complexMPD, dash_mpdparser_get_mediaPresentationDuration);
5995   tcase_add_test (tc_complexMPD, dash_mpdparser_get_streamPresentationOffset);
5996   tcase_add_test (tc_complexMPD, dash_mpdparser_segments);
5997   tcase_add_test (tc_complexMPD, dash_mpdparser_headers);
5998   tcase_add_test (tc_complexMPD, dash_mpdparser_fragments);
5999   tcase_add_test (tc_complexMPD, dash_mpdparser_inherited_segmentBase);
6000   tcase_add_test (tc_complexMPD, dash_mpdparser_inherited_segmentURL);
6001   tcase_add_test (tc_complexMPD, dash_mpdparser_segment_list);
6002   tcase_add_test (tc_complexMPD, dash_mpdparser_segment_template);
6003   tcase_add_test (tc_complexMPD, dash_mpdparser_segment_timeline);
6004   tcase_add_test (tc_complexMPD, dash_mpdparser_multiple_inherited_segmentURL);
6005 
6006   /* tests checking the parsing of missing/incomplete attributes of xml */
6007   tcase_add_test (tc_negativeTests, dash_mpdparser_missing_xml);
6008   tcase_add_test (tc_negativeTests, dash_mpdparser_missing_mpd);
6009   tcase_add_test (tc_negativeTests, dash_mpdparser_no_end_tag);
6010   tcase_add_test (tc_negativeTests, dash_mpdparser_no_profiles);
6011   tcase_add_test (tc_negativeTests, dash_mpdparser_no_default_namespace);
6012   tcase_add_test (tc_negativeTests,
6013       dash_mpdparser_wrong_period_duration_inferred_from_next_period);
6014   tcase_add_test (tc_negativeTests,
6015       dash_mpdparser_wrong_period_duration_inferred_from_next_mediaPresentationDuration);
6016   tcase_add_test (tc_negativeTests, dash_mpdparser_negative_period_duration);
6017   tcase_add_test (tc_negativeTests,
6018       dash_mpdparser_read_unsigned_from_negative_values);
6019   tcase_add_test (tc_negativeTests,
6020       dash_mpdparser_negative_mediaPresentationDuration);
6021   tcase_add_test (tc_negativeTests,
6022       dash_mpdparser_unmatched_segmentTimeline_segmentURL);
6023 
6024   tcase_add_test (tc_stringTests, dash_mpdparser_whitespace_strings);
6025   tcase_add_test (tc_stringTests, dash_mpdparser_rfc1738_strings);
6026 
6027   tcase_add_test (tc_duration, dash_mpdparser_duration);
6028   tcase_add_test (tc_duration, dash_mpdparser_maximum_segment_duration);
6029 
6030   suite_add_tcase (s, tc_simpleMPD);
6031   suite_add_tcase (s, tc_complexMPD);
6032   suite_add_tcase (s, tc_negativeTests);
6033   suite_add_tcase (s, tc_stringTests);
6034   suite_add_tcase (s, tc_duration);
6035 
6036   return s;
6037 }
6038 
6039 GST_CHECK_MAIN (dash);
6040