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