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