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