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