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 <gst/check/gstcheck.h>
22 #include "adaptive_demux_common.h"
23
24 #define DEMUX_ELEMENT_NAME "dashdemux"
25
26 #define COPY_OUTPUT_TEST_DATA(outputTestData,testData) do { \
27 guint otdPos, otdLen = sizeof((outputTestData)) / sizeof((outputTestData)[0]); \
28 for(otdPos=0; otdPos<otdLen; ++otdPos){ \
29 GST_ADAPTIVE_DEMUX_TEST_CASE (testData)->output_streams = g_list_append (GST_ADAPTIVE_DEMUX_TEST_CASE (testData)->output_streams, &(outputTestData)[otdPos]); \
30 } \
31 } while(0)
32
33 typedef struct _GstDashDemuxTestInputData
34 {
35 const gchar *uri;
36 const guint8 *payload;
37 guint64 size;
38 } GstDashDemuxTestInputData;
39
40 typedef struct _GstTestHTTPSrcTestData
41 {
42 const GstDashDemuxTestInputData *input;
43 GstStructure *data;
44 } GstTestHTTPSrcTestData;
45
46 typedef struct _GstDashDemuxTestCase
47 {
48 GstAdaptiveDemuxTestCase parent;
49
50 /* the number of Protection Events sent to each pad */
51 GstStructure *countContentProtectionEvents;
52 } GstDashDemuxTestCase;
53
54 GType gst_dash_demux_test_case_get_type (void);
55 static void gst_dash_demux_test_case_dispose (GObject * object);
56 static void gst_dash_demux_test_case_finalize (GObject * object);
57 static void gst_dash_demux_test_case_clear (GstDashDemuxTestCase * test_case);
58
59 static GstDashDemuxTestCase *
60 gst_dash_demux_test_case_new (void)
61 G_GNUC_MALLOC;
62
63 #define GST_TYPE_DASH_DEMUX_TEST_CASE \
64 (gst_dash_demux_test_case_get_type())
65 #define GST_DASH_DEMUX_TEST_CASE(obj) \
66 (G_TYPE_CHECK_INSTANCE_CAST((obj), GST_TYPE_DASH_DEMUX_TEST_CASE, GstDashDemuxTestCase))
67 #define GST_DASH_DEMUX_TEST_CASE_CLASS(klass) \
68 (G_TYPE_CHECK_CLASS_CAST((klass), GST_TYPE_DASH_DEMUX_TEST_CASE, GstDashDemuxTestCaseClass))
69 #define GST_DASH_DEMUX_TEST_CASE_GET_CLASS(obj) \
70 (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_DASH_DEMUX_TEST_CASE, GstDashDemuxTestCaseClass))
71 #define GST_IS_DASH_DEMUX_TEST_CASE(obj) \
72 (G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_TYPE_DASH_DEMUX_TEST_CASE))
73 #define GST_IS_DASH_DEMUX_TEST_CASE_CLASS(klass) \
74 (G_TYPE_CHECK_CLASS_TYPE((klass), GST_TYPE_DASH_DEMUX_TEST_CASE))
75
gst_dash_demux_test_case_new(void)76 static GstDashDemuxTestCase *gst_dash_demux_test_case_new (void)
77 {
78 return g_object_new (GST_TYPE_DASH_DEMUX_TEST_CASE, NULL);
79 }
80
81 typedef struct _GstDashDemuxTestCaseClass
82 {
83 GstAdaptiveDemuxTestCaseClass parent_class;
84 } GstDashDemuxTestCaseClass;
85
86 #define gst_dash_demux_test_case_parent_class parent_class
87
88 G_DEFINE_TYPE (GstDashDemuxTestCase, gst_dash_demux_test_case,
89 GST_TYPE_ADAPTIVE_DEMUX_TEST_CASE);
90
91 static void
gst_dash_demux_test_case_class_init(GstDashDemuxTestCaseClass * klass)92 gst_dash_demux_test_case_class_init (GstDashDemuxTestCaseClass * klass)
93 {
94 GObjectClass *object = G_OBJECT_CLASS (klass);
95
96 object->dispose = gst_dash_demux_test_case_dispose;
97 object->finalize = gst_dash_demux_test_case_finalize;
98 }
99
100 static void
gst_dash_demux_test_case_init(GstDashDemuxTestCase * test_case)101 gst_dash_demux_test_case_init (GstDashDemuxTestCase * test_case)
102 {
103 test_case->countContentProtectionEvents = NULL;
104 gst_dash_demux_test_case_clear (test_case);
105 }
106
107 static void
gst_dash_demux_test_case_clear(GstDashDemuxTestCase * test_case)108 gst_dash_demux_test_case_clear (GstDashDemuxTestCase * test_case)
109 {
110 if (test_case->countContentProtectionEvents) {
111 gst_structure_free (test_case->countContentProtectionEvents);
112 test_case->countContentProtectionEvents = NULL;
113 }
114 }
115
116 static void
gst_dash_demux_test_case_dispose(GObject * object)117 gst_dash_demux_test_case_dispose (GObject * object)
118 {
119 GstDashDemuxTestCase *testData = GST_DASH_DEMUX_TEST_CASE (object);
120
121 gst_dash_demux_test_case_clear (testData);
122
123 G_OBJECT_CLASS (parent_class)->dispose (object);
124 }
125
126 static void
gst_dash_demux_test_case_finalize(GObject * object)127 gst_dash_demux_test_case_finalize (GObject * object)
128 {
129 /*GstDashDemuxTestCase *testData = GST_DASH_DEMUX_TEST_CASE (object); */
130
131 G_OBJECT_CLASS (parent_class)->finalize (object);
132 }
133
134 static gboolean
gst_dashdemux_http_src_start(GstTestHTTPSrc * src,const gchar * uri,GstTestHTTPSrcInput * input_data,gpointer user_data)135 gst_dashdemux_http_src_start (GstTestHTTPSrc * src,
136 const gchar * uri, GstTestHTTPSrcInput * input_data, gpointer user_data)
137 {
138 const GstTestHTTPSrcTestData *test_case =
139 (const GstTestHTTPSrcTestData *) user_data;
140 guint i;
141
142 for (i = 0; test_case->input[i].uri; ++i) {
143 if (g_strcmp0 (test_case->input[i].uri, uri) == 0) {
144 input_data->context = (gpointer) & test_case->input[i];
145 input_data->size = test_case->input[i].size;
146 if (test_case->input[i].size == 0)
147 input_data->size = strlen ((gchar *) test_case->input[i].payload);
148 return TRUE;
149 }
150 }
151 return FALSE;
152 }
153
154 static GstFlowReturn
gst_dashdemux_http_src_create(GstTestHTTPSrc * src,guint64 offset,guint length,GstBuffer ** retbuf,gpointer context,gpointer user_data)155 gst_dashdemux_http_src_create (GstTestHTTPSrc * src,
156 guint64 offset,
157 guint length, GstBuffer ** retbuf, gpointer context, gpointer user_data)
158 {
159 const GstDashDemuxTestInputData *input =
160 (const GstDashDemuxTestInputData *) context;
161 GstBuffer *buf;
162
163 buf = gst_buffer_new_allocate (NULL, length, NULL);
164 fail_if (buf == NULL, "Not enough memory to allocate buffer");
165
166 if (input->payload) {
167 gst_buffer_fill (buf, 0, input->payload + offset, length);
168 } else {
169 GstMapInfo info;
170 guint pattern;
171 guint64 i;
172
173 pattern = offset - offset % sizeof (pattern);
174
175 gst_buffer_map (buf, &info, GST_MAP_WRITE);
176 for (i = 0; i < length; ++i) {
177 gchar pattern_byte_to_write = (offset + i) % sizeof (pattern);
178 if (pattern_byte_to_write == 0) {
179 pattern = offset + i;
180 }
181 info.data[i] = (pattern >> (pattern_byte_to_write * 8)) & 0xFF;
182 }
183 gst_buffer_unmap (buf, &info);
184 }
185 *retbuf = buf;
186 return GST_FLOW_OK;
187 }
188
189 /******************** Test specific code starts here **************************/
190
191 /*
192 * Test an mpd with an audio and a video stream
193 *
194 */
GST_START_TEST(simpleTest)195 GST_START_TEST (simpleTest)
196 {
197 const gchar *mpd =
198 "<?xml version=\"1.0\" encoding=\"utf-8\"?>"
199 "<MPD xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""
200 " xmlns=\"urn:mpeg:DASH:schema:MPD:2011\""
201 " xsi:schemaLocation=\"urn:mpeg:DASH:schema:MPD:2011 DASH-MPD.xsd\""
202 " profiles=\"urn:mpeg:dash:profile:isoff-on-demand:2011\""
203 " type=\"static\""
204 " minBufferTime=\"PT1.500S\""
205 " mediaPresentationDuration=\"PT135.743S\">"
206 " <Period>"
207 " <AdaptationSet mimeType=\"audio/webm\""
208 " subsegmentAlignment=\"true\">"
209 " <Representation id=\"171\""
210 " codecs=\"vorbis\""
211 " audioSamplingRate=\"44100\""
212 " startWithSAP=\"1\""
213 " bandwidth=\"129553\">"
214 " <AudioChannelConfiguration"
215 " schemeIdUri=\"urn:mpeg:dash:23003:3:audio_channel_configuration:2011\""
216 " value=\"2\" />"
217 " <BaseURL>audio.webm</BaseURL>"
218 " <SegmentBase indexRange=\"4452-4686\""
219 " indexRangeExact=\"true\">"
220 " <Initialization range=\"0-4451\" />"
221 " </SegmentBase>"
222 " </Representation>"
223 " </AdaptationSet>"
224 " <AdaptationSet mimeType=\"video/webm\""
225 " subsegmentAlignment=\"true\">"
226 " <Representation id=\"242\""
227 " codecs=\"vp9\""
228 " width=\"426\""
229 " height=\"240\""
230 " startWithSAP=\"1\""
231 " bandwidth=\"490208\">"
232 " <BaseURL>video.webm</BaseURL>"
233 " <SegmentBase indexRange=\"234-682\""
234 " indexRangeExact=\"true\">"
235 " <Initialization range=\"0-233\" />"
236 " </SegmentBase>"
237 " </Representation></AdaptationSet></Period></MPD>";
238
239 GstDashDemuxTestInputData inputTestData[] = {
240 {"http://unit.test/test.mpd", (guint8 *) mpd, 0},
241 {"http://unit.test/audio.webm", NULL, 5000},
242 {"http://unit.test/video.webm", NULL, 9000},
243 {NULL, NULL, 0},
244 };
245 GstAdaptiveDemuxTestExpectedOutput outputTestData[] = {
246 {"audio_00", 5000, NULL},
247 {"video_00", 9000, NULL}
248 };
249 GstTestHTTPSrcCallbacks http_src_callbacks = { 0 };
250 GstTestHTTPSrcTestData http_src_test_data = { 0 };
251 GstAdaptiveDemuxTestCallbacks test_callbacks = { 0 };
252 GstDashDemuxTestCase *testData;
253
254 http_src_callbacks.src_start = gst_dashdemux_http_src_start;
255 http_src_callbacks.src_create = gst_dashdemux_http_src_create;
256 http_src_test_data.input = inputTestData;
257 gst_test_http_src_install_callbacks (&http_src_callbacks,
258 &http_src_test_data);
259
260 test_callbacks.appsink_received_data =
261 gst_adaptive_demux_test_check_received_data;
262 test_callbacks.appsink_eos =
263 gst_adaptive_demux_test_check_size_of_received_data;
264
265 testData = gst_dash_demux_test_case_new ();
266 COPY_OUTPUT_TEST_DATA (outputTestData, testData);
267
268 gst_adaptive_demux_test_run (DEMUX_ELEMENT_NAME, "http://unit.test/test.mpd",
269 &test_callbacks, testData);
270
271 g_object_unref (testData);
272 if (http_src_test_data.data)
273 gst_structure_free (http_src_test_data.data);
274 }
275
276 GST_END_TEST;
277
278 /*
279 * Test an mpd with 2 periods
280 *
281 */
GST_START_TEST(testTwoPeriods)282 GST_START_TEST (testTwoPeriods)
283 {
284 const gchar *mpd =
285 "<?xml version=\"1.0\" encoding=\"utf-8\"?>"
286 "<MPD xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""
287 " xmlns=\"urn:mpeg:DASH:schema:MPD:2011\""
288 " xsi:schemaLocation=\"urn:mpeg:DASH:schema:MPD:2011 DASH-MPD.xsd\""
289 " profiles=\"urn:mpeg:dash:profile:isoff-on-demand:2011\""
290 " type=\"static\""
291 " minBufferTime=\"PT1.500S\""
292 " mediaPresentationDuration=\"PT300S\">"
293 " <Period id=\"Period0\" duration=\"PT0.1S\">"
294 " <AdaptationSet mimeType=\"audio/webm\""
295 " subsegmentAlignment=\"true\">"
296 " <Representation id=\"171\""
297 " codecs=\"vorbis\""
298 " audioSamplingRate=\"44100\""
299 " startWithSAP=\"1\""
300 " bandwidth=\"129553\">"
301 " <AudioChannelConfiguration"
302 " schemeIdUri=\"urn:mpeg:dash:23003:3:audio_channel_configuration:2011\""
303 " value=\"2\" />"
304 " <BaseURL>audio1.webm</BaseURL>"
305 " <SegmentBase indexRange=\"4452-4686\""
306 " indexRangeExact=\"true\">"
307 " <Initialization range=\"0-4451\" />"
308 " </SegmentBase>"
309 " </Representation>"
310 " </AdaptationSet>"
311 " <AdaptationSet mimeType=\"video/webm\""
312 " subsegmentAlignment=\"true\">"
313 " <Representation id=\"242\""
314 " codecs=\"vp9\""
315 " width=\"426\""
316 " height=\"240\""
317 " startWithSAP=\"1\""
318 " bandwidth=\"490208\">"
319 " <BaseURL>video1.webm</BaseURL>"
320 " <SegmentBase indexRange=\"234-682\""
321 " indexRangeExact=\"true\">"
322 " <Initialization range=\"0-233\" />"
323 " </SegmentBase>"
324 " </Representation>"
325 " </AdaptationSet>"
326 " </Period>"
327 " <Period>"
328 " <AdaptationSet mimeType=\"audio/webm\""
329 " subsegmentAlignment=\"true\">"
330 " <Representation id=\"171\""
331 " codecs=\"vorbis\""
332 " audioSamplingRate=\"44100\""
333 " startWithSAP=\"1\""
334 " bandwidth=\"129553\">"
335 " <AudioChannelConfiguration"
336 " schemeIdUri=\"urn:mpeg:dash:23003:3:audio_channel_configuration:2011\""
337 " value=\"2\" />"
338 " <BaseURL>audio2.webm</BaseURL>"
339 " <SegmentBase indexRange=\"4452-4686\""
340 " indexRangeExact=\"true\">"
341 " <Initialization range=\"0-4451\" />"
342 " </SegmentBase>"
343 " </Representation>"
344 " </AdaptationSet>"
345 " <AdaptationSet mimeType=\"video/webm\""
346 " subsegmentAlignment=\"true\">"
347 " <Representation id=\"242\""
348 " codecs=\"vp9\""
349 " width=\"426\""
350 " height=\"240\""
351 " startWithSAP=\"1\""
352 " bandwidth=\"490208\">"
353 " <BaseURL>video2.webm</BaseURL>"
354 " <SegmentBase indexRange=\"234-682\""
355 " indexRangeExact=\"true\">"
356 " <Initialization range=\"0-233\" />"
357 " </SegmentBase>"
358 " </Representation></AdaptationSet></Period></MPD>";
359
360 GstDashDemuxTestInputData inputTestData[] = {
361 {"http://unit.test/test.mpd", (guint8 *) mpd, 0},
362 {"http://unit.test/audio1.webm", NULL, 5001},
363 {"http://unit.test/video1.webm", NULL, 9001},
364 {"http://unit.test/audio2.webm", NULL, 5002},
365 {"http://unit.test/video2.webm", NULL, 9002},
366 {NULL, NULL, 0},
367 };
368 GstAdaptiveDemuxTestExpectedOutput outputTestData[] = {
369 {"audio_00", 5001, NULL},
370 {"video_00", 9001, NULL},
371 {"audio_01", 5002, NULL},
372 {"video_01", 9002, NULL},
373 };
374 GstTestHTTPSrcCallbacks http_src_callbacks = { 0 };
375 GstTestHTTPSrcTestData http_src_test_data = { 0 };
376 GstAdaptiveDemuxTestCallbacks test_callbacks = { 0 };
377 GstDashDemuxTestCase *testData;
378
379 http_src_callbacks.src_start = gst_dashdemux_http_src_start;
380 http_src_callbacks.src_create = gst_dashdemux_http_src_create;
381 http_src_test_data.input = inputTestData;
382 gst_test_http_src_install_callbacks (&http_src_callbacks,
383 &http_src_test_data);
384
385 test_callbacks.appsink_received_data =
386 gst_adaptive_demux_test_check_received_data;
387 test_callbacks.appsink_eos =
388 gst_adaptive_demux_test_check_size_of_received_data;
389
390 testData = gst_dash_demux_test_case_new ();
391 COPY_OUTPUT_TEST_DATA (outputTestData, testData);
392
393 gst_adaptive_demux_test_run (DEMUX_ELEMENT_NAME,
394 "http://unit.test/test.mpd", &test_callbacks, testData);
395
396 g_object_unref (testData);
397 if (http_src_test_data.data)
398 gst_structure_free (http_src_test_data.data);
399 }
400
401 GST_END_TEST;
402
403 /* test setting a property on an object */
404 #define test_int_prop(object, name, value) \
405 do \
406 { \
407 int val = value; \
408 int val_after; \
409 g_object_set (object, name, val, NULL); \
410 g_object_get (object, name, &val_after, NULL); \
411 fail_unless (val_after == val, "property check failed for %s: set to %d, but got %d", \
412 name, val, val_after); \
413 } while (0)
414
415 #define test_float_prop(object, name, value) \
416 do \
417 { \
418 float val = value; \
419 float val_after; \
420 g_object_set (object, name, val, NULL); \
421 g_object_get (object, name, &val_after, NULL); \
422 fail_unless (val_after == val, "property check failed for %s: set to %f, but got %f", \
423 name, val, val_after); \
424 } while (0)
425
426 /* test setting an invalid value for a property on an object.
427 * Expect an assert and the property to remain unchanged
428 */
429 #define test_invalid_int_prop(object, name, value) \
430 do \
431 { \
432 int val_before; \
433 int val_after; \
434 int val = value; \
435 g_object_get (object, name, &val_before, NULL); \
436 ASSERT_WARNING (g_object_set (object, name, val, NULL)); \
437 g_object_get (object, name, &val_after, NULL); \
438 fail_unless (val_after == val_before, "property check failed for %s: before %d, after %d", \
439 name, val_before, val_after); \
440 } while (0)
441
442 #define test_invalid_float_prop(object, name, value) \
443 do \
444 { \
445 float val_before; \
446 float val_after; \
447 float val = value; \
448 g_object_get (object, name, &val_before, NULL); \
449 ASSERT_WARNING (g_object_set (object, name, val, NULL)); \
450 g_object_get (object, name, &val_after, NULL); \
451 fail_unless (val_after == val_before, "property check failed for %s: before %f, after %f", \
452 name, val_before, val_after); \
453 } while (0)
454
455 static void
setAndTestDashParams(GstAdaptiveDemuxTestEngine * engine,gpointer user_data)456 setAndTestDashParams (GstAdaptiveDemuxTestEngine * engine, gpointer user_data)
457 {
458 /* GstDashDemuxTestCase * testData = (GstDashDemuxTestCase*)user_data; */
459 GObject *dashdemux = G_OBJECT (engine->demux);
460
461 test_int_prop (dashdemux, "connection-speed", 1000);
462 test_invalid_int_prop (dashdemux, "connection-speed", 4294967 + 1);
463
464 test_float_prop (dashdemux, "bitrate-limit", 1);
465 test_invalid_float_prop (dashdemux, "bitrate-limit", 2.1);
466
467 test_int_prop (dashdemux, "max-buffering-time", 15);
468 test_invalid_int_prop (dashdemux, "max-buffering-time", 1);
469
470 test_float_prop (dashdemux, "bandwidth-usage", 0.5);
471 test_invalid_float_prop (dashdemux, "bandwidth-usage", 2);
472
473 test_int_prop (dashdemux, "max-bitrate", 1000);
474 test_invalid_int_prop (dashdemux, "max-bitrate", 10);
475 }
476
477 /*
478 * Test setting parameters
479 *
480 */
GST_START_TEST(testParameters)481 GST_START_TEST (testParameters)
482 {
483 const gchar *mpd =
484 "<?xml version=\"1.0\" encoding=\"utf-8\"?>"
485 "<MPD xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""
486 " xmlns=\"urn:mpeg:DASH:schema:MPD:2011\""
487 " xsi:schemaLocation=\"urn:mpeg:DASH:schema:MPD:2011 DASH-MPD.xsd\""
488 " profiles=\"urn:mpeg:dash:profile:isoff-on-demand:2011\""
489 " type=\"static\""
490 " minBufferTime=\"PT1.500S\""
491 " mediaPresentationDuration=\"PT135.743S\">"
492 " <Period>"
493 " <AdaptationSet mimeType=\"audio/webm\""
494 " subsegmentAlignment=\"true\">"
495 " <Representation id=\"171\""
496 " codecs=\"vorbis\""
497 " audioSamplingRate=\"44100\""
498 " startWithSAP=\"1\""
499 " bandwidth=\"129553\">"
500 " <AudioChannelConfiguration"
501 " schemeIdUri=\"urn:mpeg:dash:23003:3:audio_channel_configuration:2011\""
502 " value=\"2\" />"
503 " <BaseURL>audio.webm</BaseURL>"
504 " <SegmentBase indexRange=\"4452-4686\""
505 " indexRangeExact=\"true\">"
506 " <Initialization range=\"0-4451\" />"
507 " </SegmentBase>"
508 " </Representation></AdaptationSet></Period></MPD>";
509
510 GstDashDemuxTestInputData inputTestData[] = {
511 {"http://unit.test/test.mpd", (guint8 *) mpd, 0},
512 {"http://unit.test/audio.webm", NULL, 5000},
513 {NULL, NULL, 0},
514 };
515 GstAdaptiveDemuxTestExpectedOutput outputTestData[] = {
516 {"audio_00", 5000, NULL},
517 };
518 GstTestHTTPSrcCallbacks http_src_callbacks = { 0 };
519 GstTestHTTPSrcTestData http_src_test_data = { 0 };
520 GstAdaptiveDemuxTestCallbacks test_callbacks = { 0 };
521 GstDashDemuxTestCase *testData;
522
523 http_src_callbacks.src_start = gst_dashdemux_http_src_start;
524 http_src_callbacks.src_create = gst_dashdemux_http_src_create;
525 http_src_test_data.input = inputTestData;
526 gst_test_http_src_install_callbacks (&http_src_callbacks,
527 &http_src_test_data);
528
529 test_callbacks.pre_test = setAndTestDashParams;
530 test_callbacks.appsink_received_data =
531 gst_adaptive_demux_test_check_received_data;
532 test_callbacks.appsink_eos =
533 gst_adaptive_demux_test_check_size_of_received_data;
534
535 testData = gst_dash_demux_test_case_new ();
536 COPY_OUTPUT_TEST_DATA (outputTestData, testData);
537
538 gst_adaptive_demux_test_run (DEMUX_ELEMENT_NAME, "http://unit.test/test.mpd",
539 &test_callbacks, testData);
540
541 g_object_unref (testData);
542 if (http_src_test_data.data)
543 gst_structure_free (http_src_test_data.data);
544 }
545
546 GST_END_TEST;
547
548 /*
549 * Test seeking
550 *
551 */
GST_START_TEST(testSeek)552 GST_START_TEST (testSeek)
553 {
554 const gchar *mpd =
555 "<?xml version=\"1.0\" encoding=\"utf-8\"?>"
556 "<MPD xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""
557 " xmlns=\"urn:mpeg:DASH:schema:MPD:2011\""
558 " xsi:schemaLocation=\"urn:mpeg:DASH:schema:MPD:2011 DASH-MPD.xsd\""
559 " profiles=\"urn:mpeg:dash:profile:isoff-on-demand:2011\""
560 " type=\"static\""
561 " minBufferTime=\"PT1.500S\""
562 " mediaPresentationDuration=\"PT135.743S\">"
563 " <Period>"
564 " <AdaptationSet mimeType=\"audio/webm\""
565 " subsegmentAlignment=\"true\">"
566 " <Representation id=\"171\""
567 " codecs=\"vorbis\""
568 " audioSamplingRate=\"44100\""
569 " startWithSAP=\"1\""
570 " bandwidth=\"129553\">"
571 " <AudioChannelConfiguration"
572 " schemeIdUri=\"urn:mpeg:dash:23003:3:audio_channel_configuration:2011\""
573 " value=\"2\" />"
574 " <BaseURL>audio.webm</BaseURL>"
575 " <SegmentBase indexRange=\"4452-4686\""
576 " indexRangeExact=\"true\">"
577 " <Initialization range=\"0-4451\" />"
578 " </SegmentBase>"
579 " </Representation></AdaptationSet></Period></MPD>";
580
581 GstDashDemuxTestInputData inputTestData[] = {
582 {"http://unit.test/test.mpd", (guint8 *) mpd, 0},
583 {"http://unit.test/audio.webm", NULL, 10000},
584 {NULL, NULL, 0},
585 };
586 GstAdaptiveDemuxTestExpectedOutput outputTestData[] = {
587 {"audio_00", 10000, NULL},
588 };
589 GstTestHTTPSrcCallbacks http_src_callbacks = { 0 };
590 GstTestHTTPSrcTestData http_src_test_data = { 0 };
591 GstDashDemuxTestCase *testData;
592
593 http_src_callbacks.src_start = gst_dashdemux_http_src_start;
594 http_src_callbacks.src_create = gst_dashdemux_http_src_create;
595 http_src_test_data.input = inputTestData;
596 gst_test_http_src_install_callbacks (&http_src_callbacks,
597 &http_src_test_data);
598
599 testData = gst_dash_demux_test_case_new ();
600 COPY_OUTPUT_TEST_DATA (outputTestData, testData);
601
602 /* media segment starts at 4687
603 * Issue a seek request after media segment has started to be downloaded
604 * on the first pad listed in GstAdaptiveDemuxTestOutputStreamData and the
605 * first chunk of at least one byte has already arrived in AppSink
606 */
607 GST_ADAPTIVE_DEMUX_TEST_CASE (testData)->threshold_for_seek = 4687 + 1;
608
609 /* seek to 5ms.
610 * Because there is only one fragment, we expect the whole file to be
611 * downloaded again
612 */
613 GST_ADAPTIVE_DEMUX_TEST_CASE (testData)->seek_event =
614 gst_event_new_seek (1.0, GST_FORMAT_TIME,
615 GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_KEY_UNIT, GST_SEEK_TYPE_SET,
616 5 * GST_MSECOND, GST_SEEK_TYPE_NONE, 0);
617
618 gst_adaptive_demux_test_seek (DEMUX_ELEMENT_NAME,
619 "http://unit.test/test.mpd", GST_ADAPTIVE_DEMUX_TEST_CASE (testData));
620
621 g_object_unref (testData);
622 if (http_src_test_data.data)
623 gst_structure_free (http_src_test_data.data);
624 }
625
626 GST_END_TEST;
627
628
629 #define SEGMENT_SIZE 10000
630 static void
run_seek_position_test(gdouble rate,GstSeekType start_type,guint64 seek_start,GstSeekType stop_type,guint64 seek_stop,GstSeekFlags flags,guint64 segment_start,guint64 segment_stop,gint segments,gint seek_threshold_bytes)631 run_seek_position_test (gdouble rate, GstSeekType start_type,
632 guint64 seek_start, GstSeekType stop_type, guint64 seek_stop,
633 GstSeekFlags flags, guint64 segment_start, guint64 segment_stop,
634 gint segments, gint seek_threshold_bytes)
635 {
636 const gchar *mpd =
637 "<?xml version=\"1.0\" encoding=\"utf-8\"?>"
638 "<MPD xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""
639 " xmlns=\"urn:mpeg:DASH:schema:MPD:2011\""
640 " xsi:schemaLocation=\"urn:mpeg:DASH:schema:MPD:2011 DASH-MPD.xsd\""
641 " profiles=\"urn:mpeg:dash:profile:isoff-on-demand:2011\""
642 " type=\"static\""
643 " minBufferTime=\"PT1.500S\""
644 " mediaPresentationDuration=\"PT135.743S\">"
645 " <Period>"
646 " <AdaptationSet "
647 " mimeType=\"audio/mp4\" minBandwidth=\"128000\" "
648 " maxBandwidth=\"128000\" segmentAlignment=\"true\">"
649 " <SegmentTemplate timescale=\"48000\" "
650 " initialization=\"init-$RepresentationID$.mp4\" "
651 " media=\"$RepresentationID$-$Number$.mp4\" "
652 " startNumber=\"1\">"
653 " <SegmentTimeline>"
654 " <S t=\"0\" d=\"48000\" /> "
655 " <S d=\"48000\" /> "
656 " <S d=\"48000\" /> "
657 " <S d=\"48000\" /> "
658 " </SegmentTimeline>"
659 " </SegmentTemplate>"
660 " <Representation id=\"audio\" bandwidth=\"128000\" "
661 " codecs=\"mp4a.40.2\" audioSamplingRate=\"48000\"> "
662 " <AudioChannelConfiguration "
663 " schemeIdUri=\"urn:mpeg:dash:23003:3:audio_channel_configuration:2011\""
664 " value=\"2\"> "
665 " </AudioChannelConfiguration> "
666 " </Representation></AdaptationSet></Period></MPD>";
667
668 GstDashDemuxTestInputData inputTestData[] = {
669 {"http://unit.test/test.mpd", (guint8 *) mpd, 0},
670 {"http://unit.test/init-audio.mp4", NULL, 10000},
671 {"http://unit.test/audio-1.mp4", NULL, 10000},
672 {"http://unit.test/audio-2.mp4", NULL, 10000},
673 {"http://unit.test/audio-3.mp4", NULL, 10000},
674 {"http://unit.test/audio-4.mp4", NULL, 10000},
675 {NULL, NULL, 0},
676 };
677 GstTestHTTPSrcCallbacks http_src_callbacks = { 0 };
678 GstTestHTTPSrcTestData http_src_test_data = { 0 };
679 GstAdaptiveDemuxTestExpectedOutput outputTestData[] = {
680 /* 1 from the init segment */
681 {"audio_00", (segments ? 1 + segments : 0) * 10000, NULL},
682 };
683 GstDashDemuxTestCase *testData;
684
685 http_src_callbacks.src_start = gst_dashdemux_http_src_start;
686 http_src_callbacks.src_create = gst_dashdemux_http_src_create;
687 http_src_test_data.input = inputTestData;
688 gst_test_http_src_install_callbacks (&http_src_callbacks,
689 &http_src_test_data);
690
691 testData = gst_dash_demux_test_case_new ();
692 COPY_OUTPUT_TEST_DATA (outputTestData, testData);
693
694 /* media segment starts at 4687
695 * Issue a seek request after media segment has started to be downloaded
696 * on the first pad listed in GstAdaptiveDemuxTestOutputStreamData and the
697 * first chunk of at least one byte has already arrived in AppSink
698 */
699 if (seek_threshold_bytes)
700 GST_ADAPTIVE_DEMUX_TEST_CASE (testData)->threshold_for_seek =
701 seek_threshold_bytes;
702 else
703 GST_ADAPTIVE_DEMUX_TEST_CASE (testData)->threshold_for_seek = 4687 + 1;
704
705 /* FIXME hack to avoid having a 0 seqnum */
706 gst_util_seqnum_next ();
707
708 /* seek to 5ms.
709 * Because there is only one fragment, we expect the whole file to be
710 * downloaded again
711 */
712 GST_ADAPTIVE_DEMUX_TEST_CASE (testData)->seek_event =
713 gst_event_new_seek (rate, GST_FORMAT_TIME, flags, start_type,
714 seek_start, stop_type, seek_stop);
715
716 gst_adaptive_demux_test_seek (DEMUX_ELEMENT_NAME,
717 "http://unit.test/test.mpd", GST_ADAPTIVE_DEMUX_TEST_CASE (testData));
718
719 g_object_unref (testData);
720 if (http_src_test_data.data)
721 gst_structure_free (http_src_test_data.data);
722 }
723
GST_START_TEST(testSeekKeyUnitPosition)724 GST_START_TEST (testSeekKeyUnitPosition)
725 {
726 /* Seek to 1.5s with key unit, it should go back to 1.0s. 3 segments will be
727 * pushed */
728 run_seek_position_test (1.0, GST_SEEK_TYPE_SET, 1500 * GST_MSECOND,
729 GST_SEEK_TYPE_NONE, 0, GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_KEY_UNIT,
730 1000 * GST_MSECOND, -1, 3, 0);
731 }
732
733 GST_END_TEST;
734
735
GST_START_TEST(testSeekUpdateStopPosition)736 GST_START_TEST (testSeekUpdateStopPosition)
737 {
738 run_seek_position_test (1.0, GST_SEEK_TYPE_NONE, 1500 * GST_MSECOND,
739 GST_SEEK_TYPE_SET, 3000 * GST_MSECOND, 0, 0, 3000 * GST_MSECOND, 3, 0);
740 }
741
742 GST_END_TEST;
743
GST_START_TEST(testSeekPosition)744 GST_START_TEST (testSeekPosition)
745 {
746 /* Seek to 1.5s without key unit, it should keep the 1.5s, but still push
747 * from the 1st segment, so 3 segments will be
748 * pushed */
749 run_seek_position_test (1.0, GST_SEEK_TYPE_SET, 1500 * GST_MSECOND,
750 GST_SEEK_TYPE_NONE, 0, GST_SEEK_FLAG_FLUSH, 1500 * GST_MSECOND, -1, 3, 0);
751 }
752
753 GST_END_TEST;
754
GST_START_TEST(testSeekSnapBeforePosition)755 GST_START_TEST (testSeekSnapBeforePosition)
756 {
757 /* Seek to 1.5s, snap before, it go to 1s */
758 run_seek_position_test (1.0, GST_SEEK_TYPE_SET, 1500 * GST_MSECOND,
759 GST_SEEK_TYPE_NONE, 0,
760 GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_KEY_UNIT | GST_SEEK_FLAG_SNAP_BEFORE,
761 1000 * GST_MSECOND, -1, 3, 0);
762 }
763
764 GST_END_TEST;
765
766
GST_START_TEST(testSeekSnapAfterPosition)767 GST_START_TEST (testSeekSnapAfterPosition)
768 {
769 /* Seek to 1.5s with snap after, it should move to 2s */
770 run_seek_position_test (1.0, GST_SEEK_TYPE_SET, 1500 * GST_MSECOND,
771 GST_SEEK_TYPE_NONE, 0,
772 GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_KEY_UNIT | GST_SEEK_FLAG_SNAP_AFTER,
773 2000 * GST_MSECOND, -1, 2, 0);
774 }
775
776 GST_END_TEST;
777
778
GST_START_TEST(testSeekSnapBeforeSamePosition)779 GST_START_TEST (testSeekSnapBeforeSamePosition)
780 {
781 /* Snap seek without position */
782 run_seek_position_test (1.0, GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE,
783 GST_SEEK_TYPE_NONE, 0,
784 GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_KEY_UNIT | GST_SEEK_FLAG_SNAP_BEFORE,
785 2 * GST_MSECOND, -1, 2, SEGMENT_SIZE * 3 + 1);
786 }
787
788 GST_END_TEST;
789
790
GST_START_TEST(testSeekSnapAfterSamePosition)791 GST_START_TEST (testSeekSnapAfterSamePosition)
792 {
793 /* Snap seek without position */
794 run_seek_position_test (1.0, GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE,
795 GST_SEEK_TYPE_NONE, 0,
796 GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_KEY_UNIT | GST_SEEK_FLAG_SNAP_AFTER,
797 3 * GST_MSECOND, -1, 1, SEGMENT_SIZE * 3 + 1);
798 }
799
800 GST_END_TEST;
801
802
803
GST_START_TEST(testReverseSeekSnapBeforePosition)804 GST_START_TEST (testReverseSeekSnapBeforePosition)
805 {
806 run_seek_position_test (-1.0, GST_SEEK_TYPE_SET, 1000 * GST_MSECOND,
807 GST_SEEK_TYPE_SET, 2500 * GST_MSECOND,
808 GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_KEY_UNIT | GST_SEEK_FLAG_SNAP_BEFORE,
809 1000 * GST_MSECOND, 3000 * GST_MSECOND, 2, 0);
810 }
811
812 GST_END_TEST;
813
814
GST_START_TEST(testReverseSeekSnapAfterPosition)815 GST_START_TEST (testReverseSeekSnapAfterPosition)
816 {
817 run_seek_position_test (-1.0, GST_SEEK_TYPE_SET, 1000 * GST_MSECOND,
818 GST_SEEK_TYPE_SET, 2500 * GST_MSECOND,
819 GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_KEY_UNIT | GST_SEEK_FLAG_SNAP_AFTER,
820 1000 * GST_MSECOND, 2000 * GST_MSECOND, 1, 0);
821 }
822
823 GST_END_TEST;
824
825 static void
testDownloadErrorMessageCallback(GstAdaptiveDemuxTestEngine * engine,GstMessage * msg,gpointer user_data)826 testDownloadErrorMessageCallback (GstAdaptiveDemuxTestEngine * engine,
827 GstMessage * msg, gpointer user_data)
828 {
829 GError *err = NULL;
830 gchar *dbg_info = NULL;
831
832 fail_unless (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_ERROR);
833 gst_message_parse_error (msg, &err, &dbg_info);
834 GST_DEBUG ("Error from element %s : %s\n",
835 GST_OBJECT_NAME (msg->src), err->message);
836 fail_unless_equals_string (GST_OBJECT_NAME (msg->src), DEMUX_ELEMENT_NAME);
837 g_error_free (err);
838 g_free (dbg_info);
839 g_main_loop_quit (engine->loop);
840 }
841
842 /*
843 * Test error case of failing to download a segment
844 */
GST_START_TEST(testDownloadError)845 GST_START_TEST (testDownloadError)
846 {
847 const gchar *mpd =
848 "<?xml version=\"1.0\" encoding=\"utf-8\"?>"
849 "<MPD xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""
850 " xmlns=\"urn:mpeg:DASH:schema:MPD:2011\""
851 " xsi:schemaLocation=\"urn:mpeg:DASH:schema:MPD:2011 DASH-MPD.xsd\""
852 " profiles=\"urn:mpeg:dash:profile:isoff-on-demand:2011\""
853 " type=\"static\""
854 " minBufferTime=\"PT1.500S\""
855 " mediaPresentationDuration=\"PT0.5S\">"
856 " <Period>"
857 " <AdaptationSet mimeType=\"audio/webm\""
858 " subsegmentAlignment=\"true\">"
859 " <Representation id=\"171\""
860 " codecs=\"vorbis\""
861 " audioSamplingRate=\"44100\""
862 " startWithSAP=\"1\""
863 " bandwidth=\"129553\">"
864 " <AudioChannelConfiguration"
865 " schemeIdUri=\"urn:mpeg:dash:23003:3:audio_channel_configuration:2011\""
866 " value=\"2\" />"
867 " <BaseURL>audio_file_not_available.webm</BaseURL>"
868 " <SegmentBase indexRange=\"4452-4686\""
869 " indexRangeExact=\"true\">"
870 " <Initialization range=\"0-4451\" />"
871 " </SegmentBase>"
872 " </Representation></AdaptationSet></Period></MPD>";
873
874 GstDashDemuxTestInputData inputTestData[] = {
875 {"http://unit.test/test.mpd", (guint8 *) mpd, 0},
876 {NULL, NULL, 0},
877 };
878 GstAdaptiveDemuxTestExpectedOutput outputTestData[] = {
879 {"audio_00", 0, NULL},
880 };
881 GstTestHTTPSrcCallbacks http_src_callbacks = { 0 };
882 GstTestHTTPSrcTestData http_src_test_data = { 0 };
883 GstAdaptiveDemuxTestCallbacks test_callbacks = { 0 };
884 GstDashDemuxTestCase *testData;
885
886 http_src_callbacks.src_start = gst_dashdemux_http_src_start;
887 http_src_callbacks.src_create = gst_dashdemux_http_src_create;
888 http_src_test_data.input = inputTestData;
889 gst_test_http_src_install_callbacks (&http_src_callbacks,
890 &http_src_test_data);
891
892 test_callbacks.appsink_received_data =
893 gst_adaptive_demux_test_check_received_data;
894 test_callbacks.bus_error_message = testDownloadErrorMessageCallback;
895 test_callbacks.appsink_eos = gst_adaptive_demux_test_unexpected_eos;
896
897 testData = gst_dash_demux_test_case_new ();
898 COPY_OUTPUT_TEST_DATA (outputTestData, testData);
899
900 gst_adaptive_demux_test_run (DEMUX_ELEMENT_NAME, "http://unit.test/test.mpd",
901 &test_callbacks, testData);
902
903 g_object_unref (testData);
904 if (http_src_test_data.data)
905 gst_structure_free (http_src_test_data.data);
906 }
907
908 GST_END_TEST;
909
910 static GstFlowReturn
test_fragment_download_error_src_create(GstTestHTTPSrc * src,guint64 offset,guint length,GstBuffer ** retbuf,gpointer context,gpointer user_data)911 test_fragment_download_error_src_create (GstTestHTTPSrc * src,
912 guint64 offset,
913 guint length, GstBuffer ** retbuf, gpointer context, gpointer user_data)
914 {
915 const GstDashDemuxTestInputData *input =
916 (const GstDashDemuxTestInputData *) context;
917 const GstTestHTTPSrcTestData *http_src_test_data =
918 (const GstTestHTTPSrcTestData *) user_data;
919 guint64 threshold_for_trigger;
920
921 fail_unless (input != NULL);
922 gst_structure_get_uint64 (http_src_test_data->data, "threshold_for_trigger",
923 &threshold_for_trigger);
924
925 if (!g_str_has_suffix (input->uri, ".mpd") && offset >= threshold_for_trigger) {
926 GST_DEBUG ("network_error %s %" G_GUINT64_FORMAT " @ %" G_GUINT64_FORMAT,
927 input->uri, offset, threshold_for_trigger);
928 GST_ELEMENT_ERROR (src, RESOURCE, READ,
929 (("A network error occurred, or the server closed the connection unexpectedly.")), ("A network error occurred, or the server closed the connection unexpectedly."));
930 return GST_FLOW_ERROR;
931 }
932 return gst_dashdemux_http_src_create (src, offset, length, retbuf, context,
933 user_data);
934 }
935
936 /*
937 * Test header download error
938 * Let the adaptive demux download a few bytes, then instruct the
939 * GstTestHTTPSrc element to generate an error while the fragment header
940 * is still being downloaded.
941 */
GST_START_TEST(testHeaderDownloadError)942 GST_START_TEST (testHeaderDownloadError)
943 {
944 const gchar *mpd =
945 "<?xml version=\"1.0\" encoding=\"utf-8\"?>"
946 "<MPD xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""
947 " xmlns=\"urn:mpeg:DASH:schema:MPD:2011\""
948 " xsi:schemaLocation=\"urn:mpeg:DASH:schema:MPD:2011 DASH-MPD.xsd\""
949 " profiles=\"urn:mpeg:dash:profile:isoff-on-demand:2011\""
950 " type=\"static\""
951 " minBufferTime=\"PT1.500S\""
952 " mediaPresentationDuration=\"PT0.5S\">"
953 " <Period>"
954 " <AdaptationSet mimeType=\"audio/webm\""
955 " subsegmentAlignment=\"true\">"
956 " <Representation id=\"171\""
957 " codecs=\"vorbis\""
958 " audioSamplingRate=\"44100\""
959 " startWithSAP=\"1\""
960 " bandwidth=\"129553\">"
961 " <AudioChannelConfiguration"
962 " schemeIdUri=\"urn:mpeg:dash:23003:3:audio_channel_configuration:2011\""
963 " value=\"2\" />"
964 " <BaseURL>audio.webm</BaseURL>"
965 " <SegmentBase indexRange=\"4452-4686\""
966 " indexRangeExact=\"true\">"
967 " <Initialization range=\"0-4451\" />"
968 " </SegmentBase>"
969 " </Representation></AdaptationSet></Period></MPD>";
970
971 /* generate error while the headers are still being downloaded
972 * threshold_for_trigger must be less than the size of headers
973 * (initialization + index) which is 4687.
974 */
975 guint64 threshold_for_trigger = 2000;
976
977 GstDashDemuxTestInputData inputTestData[] = {
978 {"http://unit.test/test.mpd", (guint8 *) mpd, 0},
979 {"http://unit.test/audio.webm", NULL, 5000},
980 {NULL, NULL, 0},
981 };
982 GstAdaptiveDemuxTestExpectedOutput outputTestData[] = {
983 /* adaptive demux tries for 4 times (MAX_DOWNLOAD_ERROR_COUNT + 1) before giving up */
984 {"audio_00", threshold_for_trigger * 4, NULL},
985 };
986 GstTestHTTPSrcCallbacks http_src_callbacks = { 0 };
987 GstTestHTTPSrcTestData http_src_test_data = { 0 };
988 GstAdaptiveDemuxTestCallbacks test_callbacks = { 0 };
989 GstDashDemuxTestCase *testData;
990
991 http_src_callbacks.src_start = gst_dashdemux_http_src_start;
992 http_src_callbacks.src_create = test_fragment_download_error_src_create;
993 http_src_test_data.data = gst_structure_new_empty (__FUNCTION__);
994 gst_structure_set (http_src_test_data.data, "threshold_for_trigger",
995 G_TYPE_UINT64, threshold_for_trigger, NULL);
996 http_src_test_data.input = inputTestData;
997 gst_test_http_src_install_callbacks (&http_src_callbacks,
998 &http_src_test_data);
999
1000 test_callbacks.appsink_received_data =
1001 gst_adaptive_demux_test_check_received_data;
1002 test_callbacks.appsink_eos = gst_adaptive_demux_test_unexpected_eos;
1003 test_callbacks.bus_error_message = testDownloadErrorMessageCallback;
1004
1005 testData = gst_dash_demux_test_case_new ();
1006 COPY_OUTPUT_TEST_DATA (outputTestData, testData);
1007
1008 /* download in chunks of threshold_for_trigger size.
1009 * This means the first chunk will succeed, the second will generate
1010 * error because we already exceeded threshold_for_trigger bytes.
1011 */
1012 gst_test_http_src_set_default_blocksize (threshold_for_trigger);
1013
1014 gst_adaptive_demux_test_run (DEMUX_ELEMENT_NAME,
1015 "http://unit.test/test.mpd", &test_callbacks, testData);
1016
1017 g_object_unref (testData);
1018 if (http_src_test_data.data)
1019 gst_structure_free (http_src_test_data.data);
1020 }
1021
1022 GST_END_TEST;
1023
1024 /*
1025 * Test media download error on the last media fragment.
1026 * Let the adaptive demux download a few bytes, then instruct the
1027 * GstTestHTTPSrc element to generate an error while the last media fragment
1028 * is being downloaded.
1029 * Adaptive demux will not retry downloading the last media fragment. It will
1030 * be considered eos.
1031 */
GST_START_TEST(testMediaDownloadErrorLastFragment)1032 GST_START_TEST (testMediaDownloadErrorLastFragment)
1033 {
1034 const gchar *mpd =
1035 "<?xml version=\"1.0\" encoding=\"utf-8\"?>"
1036 "<MPD xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""
1037 " xmlns=\"urn:mpeg:DASH:schema:MPD:2011\""
1038 " xsi:schemaLocation=\"urn:mpeg:DASH:schema:MPD:2011 DASH-MPD.xsd\""
1039 " profiles=\"urn:mpeg:dash:profile:isoff-on-demand:2011\""
1040 " type=\"static\""
1041 " minBufferTime=\"PT1.500S\""
1042 " mediaPresentationDuration=\"PT0.5S\">"
1043 " <Period>"
1044 " <AdaptationSet mimeType=\"audio/webm\""
1045 " subsegmentAlignment=\"true\">"
1046 " <Representation id=\"171\""
1047 " codecs=\"vorbis\""
1048 " audioSamplingRate=\"44100\""
1049 " startWithSAP=\"1\""
1050 " bandwidth=\"129553\">"
1051 " <AudioChannelConfiguration"
1052 " schemeIdUri=\"urn:mpeg:dash:23003:3:audio_channel_configuration:2011\""
1053 " value=\"2\" />"
1054 " <BaseURL>audio.webm</BaseURL>"
1055 " <SegmentBase indexRange=\"4452-4686\""
1056 " indexRangeExact=\"true\">"
1057 " <Initialization range=\"0-4451\" />"
1058 " </SegmentBase>"
1059 " </Representation></AdaptationSet></Period></MPD>";
1060
1061 /* generate error on the first media fragment */
1062 guint64 threshold_for_trigger = 4687;
1063
1064 GstDashDemuxTestInputData inputTestData[] = {
1065 {"http://unit.test/test.mpd", (guint8 *) mpd, 0},
1066 {"http://unit.test/audio.webm", NULL, 5000},
1067 {NULL, NULL, 0},
1068 };
1069 GstAdaptiveDemuxTestExpectedOutput outputTestData[] = {
1070 /* adaptive demux will not retry because this is the last fragment */
1071 {"audio_00", threshold_for_trigger, NULL},
1072 };
1073 GstTestHTTPSrcCallbacks http_src_callbacks = { 0 };
1074 GstTestHTTPSrcTestData http_src_test_data = { 0 };
1075 GstAdaptiveDemuxTestCallbacks test_callbacks = { 0 };
1076 GstDashDemuxTestCase *testData;
1077
1078 http_src_callbacks.src_start = gst_dashdemux_http_src_start;
1079 http_src_callbacks.src_create = test_fragment_download_error_src_create;
1080 http_src_test_data.data = gst_structure_new_empty (__FUNCTION__);
1081 gst_structure_set (http_src_test_data.data, "threshold_for_trigger",
1082 G_TYPE_UINT64, threshold_for_trigger, NULL);
1083 http_src_test_data.input = inputTestData;
1084 gst_test_http_src_install_callbacks (&http_src_callbacks,
1085 &http_src_test_data);
1086
1087 test_callbacks.appsink_received_data =
1088 gst_adaptive_demux_test_check_received_data;
1089 test_callbacks.appsink_eos =
1090 gst_adaptive_demux_test_check_size_of_received_data;
1091
1092 testData = gst_dash_demux_test_case_new ();
1093 COPY_OUTPUT_TEST_DATA (outputTestData, testData);
1094
1095 gst_adaptive_demux_test_run (DEMUX_ELEMENT_NAME,
1096 "http://unit.test/test.mpd", &test_callbacks, testData);
1097
1098 g_object_unref (testData);
1099 if (http_src_test_data.data)
1100 gst_structure_free (http_src_test_data.data);
1101 }
1102
1103 GST_END_TEST;
1104
1105 /*
1106 * Test media download error on a media fragment which is not the last one.
1107 * Let the adaptive demux download a few bytes, then instruct the
1108 * GstTestHTTPSrc element to generate an error while a media fragment
1109 * is being downloaded.
1110 */
GST_START_TEST(testMediaDownloadErrorMiddleFragment)1111 GST_START_TEST (testMediaDownloadErrorMiddleFragment)
1112 {
1113 const gchar *mpd =
1114 "<?xml version=\"1.0\" encoding=\"utf-8\"?>"
1115 "<MPD xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""
1116 " xmlns=\"urn:mpeg:DASH:schema:MPD:2011\""
1117 " xsi:schemaLocation=\"urn:mpeg:DASH:schema:MPD:2011 DASH-MPD.xsd\""
1118 " profiles=\"urn:mpeg:dash:profile:isoff-on-demand:2011\""
1119 " type=\"static\""
1120 " minBufferTime=\"PT1.500S\""
1121 " mediaPresentationDuration=\"PT10S\">"
1122 " <Period>"
1123 " <AdaptationSet mimeType=\"audio/webm\""
1124 " subsegmentAlignment=\"true\">"
1125 " <Representation id=\"171\""
1126 " codecs=\"vorbis\""
1127 " audioSamplingRate=\"44100\""
1128 " startWithSAP=\"1\""
1129 " bandwidth=\"129553\">"
1130 " <AudioChannelConfiguration"
1131 " schemeIdUri=\"urn:mpeg:dash:23003:3:audio_channel_configuration:2011\""
1132 " value=\"2\" />"
1133 " <BaseURL>audio.webm</BaseURL>"
1134 " <SegmentList duration=\"1\">"
1135 " <SegmentURL indexRange=\"1-10\""
1136 " mediaRange=\"11-30\">"
1137 " </SegmentURL>"
1138 " <SegmentURL indexRange=\"31-60\""
1139 " mediaRange=\"61-100\">"
1140 " </SegmentURL>"
1141 " <SegmentURL indexRange=\"101-150\""
1142 " mediaRange=\"151-210\">"
1143 " </SegmentURL>"
1144 " </SegmentList>"
1145 " </Representation></AdaptationSet></Period></MPD>";
1146
1147 /* generate error on the second media fragment */
1148 guint64 threshold_for_trigger = 31;
1149
1150 GstDashDemuxTestInputData inputTestData[] = {
1151 {"http://unit.test/test.mpd", (guint8 *) mpd, 0},
1152 {"http://unit.test/audio.webm", NULL, 5000},
1153 {NULL, NULL, 0},
1154 };
1155 GstAdaptiveDemuxTestExpectedOutput outputTestData[] = {
1156 /* adaptive demux will download only the first media fragment */
1157 {"audio_00", 20, NULL},
1158 };
1159 GstTestHTTPSrcCallbacks http_src_callbacks = { 0 };
1160 GstTestHTTPSrcTestData http_src_test_data = { 0 };
1161 GstAdaptiveDemuxTestCallbacks test_callbacks = { 0 };
1162 GstDashDemuxTestCase *testData;
1163
1164 http_src_callbacks.src_start = gst_dashdemux_http_src_start;
1165 http_src_callbacks.src_create = test_fragment_download_error_src_create;
1166 http_src_test_data.data = gst_structure_new_empty (__FUNCTION__);
1167 gst_structure_set (http_src_test_data.data, "threshold_for_trigger",
1168 G_TYPE_UINT64, threshold_for_trigger, NULL);
1169 http_src_test_data.input = inputTestData;
1170 gst_test_http_src_install_callbacks (&http_src_callbacks,
1171 &http_src_test_data);
1172
1173 test_callbacks.appsink_received_data =
1174 gst_adaptive_demux_test_check_received_data;
1175 test_callbacks.appsink_eos = gst_adaptive_demux_test_unexpected_eos;
1176 test_callbacks.bus_error_message = testDownloadErrorMessageCallback;
1177
1178 testData = gst_dash_demux_test_case_new ();
1179 COPY_OUTPUT_TEST_DATA (outputTestData, testData);
1180
1181 gst_adaptive_demux_test_run (DEMUX_ELEMENT_NAME,
1182 "http://unit.test/test.mpd", &test_callbacks, testData);
1183
1184 g_object_unref (testData);
1185 if (http_src_test_data.data)
1186 gst_structure_free (http_src_test_data.data);
1187 }
1188
1189 GST_END_TEST;
1190
1191 /* generate queries to adaptive demux */
1192 static gboolean
testQueryCheckDataReceived(GstAdaptiveDemuxTestEngine * engine,GstAdaptiveDemuxTestOutputStream * stream,GstBuffer * buffer,gpointer user_data)1193 testQueryCheckDataReceived (GstAdaptiveDemuxTestEngine * engine,
1194 GstAdaptiveDemuxTestOutputStream * stream,
1195 GstBuffer * buffer, gpointer user_data)
1196 {
1197 GList *pads;
1198 GstPad *pad;
1199 GstQuery *query;
1200 gboolean ret;
1201 gint64 duration;
1202 gboolean seekable;
1203 gint64 segment_start;
1204 gint64 segment_end;
1205 gboolean live;
1206 GstClockTime min_latency;
1207 GstClockTime max_latency;
1208 gchar *uri;
1209 gchar *redirect_uri;
1210 gboolean redirect_permanent;
1211
1212 pads = GST_ELEMENT_PADS (stream->appsink);
1213
1214 /* AppSink should have only 1 pad */
1215 fail_unless (pads != NULL);
1216 fail_unless (g_list_length (pads) == 1);
1217 pad = GST_PAD (pads->data);
1218
1219 /* duration query */
1220 query = gst_query_new_duration (GST_FORMAT_TIME);
1221 ret = gst_pad_peer_query (pad, query);
1222 fail_unless (ret == TRUE);
1223 gst_query_parse_duration (query, NULL, &duration);
1224 /* mediaPresentationDuration=\"PT135.743S\" */
1225 fail_unless (duration == 135743 * GST_MSECOND);
1226 gst_query_unref (query);
1227
1228 /* seek query */
1229 query = gst_query_new_seeking (GST_FORMAT_TIME);
1230 ret = gst_pad_peer_query (pad, query);
1231 fail_unless (ret == TRUE);
1232 gst_query_parse_seeking (query, NULL, &seekable, &segment_start,
1233 &segment_end);
1234 fail_unless (seekable == TRUE);
1235 fail_unless (segment_start == 0);
1236 fail_unless (segment_end == duration);
1237 gst_query_unref (query);
1238
1239 /* latency query */
1240 query = gst_query_new_latency ();
1241 ret = gst_pad_peer_query (pad, query);
1242 fail_unless (ret == TRUE);
1243 gst_query_parse_latency (query, &live, &min_latency, &max_latency);
1244 fail_unless (live == FALSE);
1245 fail_unless (min_latency == 0);
1246 fail_unless (max_latency == -1);
1247 gst_query_unref (query);
1248
1249 /* uri query */
1250 query = gst_query_new_uri ();
1251 ret = gst_pad_peer_query (pad, query);
1252 fail_unless (ret == TRUE);
1253 gst_query_parse_uri (query, &uri);
1254 gst_query_parse_uri_redirection (query, &redirect_uri);
1255 gst_query_parse_uri_redirection_permanent (query, &redirect_permanent);
1256 fail_unless (g_strcmp0 (uri, "http://unit.test/test.mpd") == 0);
1257 /* adaptive demux does not reply with redirect information */
1258 fail_unless (redirect_uri == NULL);
1259 fail_unless (redirect_permanent == FALSE);
1260 g_free (uri);
1261 g_free (redirect_uri);
1262 gst_query_unref (query);
1263
1264 return gst_adaptive_demux_test_check_received_data (engine,
1265 stream, buffer, user_data);
1266 }
1267
1268 /*
1269 * Test queries
1270 *
1271 */
GST_START_TEST(testQuery)1272 GST_START_TEST (testQuery)
1273 {
1274 const gchar *mpd =
1275 "<?xml version=\"1.0\" encoding=\"utf-8\"?>"
1276 "<MPD xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""
1277 " xmlns=\"urn:mpeg:DASH:schema:MPD:2011\""
1278 " xsi:schemaLocation=\"urn:mpeg:DASH:schema:MPD:2011 DASH-MPD.xsd\""
1279 " profiles=\"urn:mpeg:dash:profile:isoff-on-demand:2011\""
1280 " type=\"static\""
1281 " minBufferTime=\"PT1.500S\""
1282 " mediaPresentationDuration=\"PT135.743S\">"
1283 " <Period>"
1284 " <AdaptationSet mimeType=\"audio/webm\""
1285 " subsegmentAlignment=\"true\">"
1286 " <Representation id=\"171\""
1287 " codecs=\"vorbis\""
1288 " audioSamplingRate=\"44100\""
1289 " startWithSAP=\"1\""
1290 " bandwidth=\"129553\">"
1291 " <AudioChannelConfiguration"
1292 " schemeIdUri=\"urn:mpeg:dash:23003:3:audio_channel_configuration:2011\""
1293 " value=\"2\" />"
1294 " <BaseURL>audio.webm</BaseURL>"
1295 " <SegmentBase indexRange=\"4452-4686\""
1296 " indexRangeExact=\"true\">"
1297 " <Initialization range=\"0-4451\" />"
1298 " </SegmentBase>"
1299 " </Representation></AdaptationSet></Period></MPD>";
1300
1301 GstDashDemuxTestInputData inputTestData[] = {
1302 {"http://unit.test/test.mpd", (guint8 *) mpd, 0},
1303 {"http://unit.test/audio.webm", NULL, 5000},
1304 {NULL, NULL, 0},
1305 };
1306 GstAdaptiveDemuxTestExpectedOutput outputTestData[] = {
1307 {"audio_00", 5000, NULL},
1308 };
1309 GstTestHTTPSrcCallbacks http_src_callbacks = { 0 };
1310 GstTestHTTPSrcTestData http_src_test_data = { 0 };
1311 GstAdaptiveDemuxTestCallbacks test_callbacks = { 0 };
1312 GstDashDemuxTestCase *testData;
1313
1314 http_src_callbacks.src_start = gst_dashdemux_http_src_start;
1315 http_src_callbacks.src_create = gst_dashdemux_http_src_create;
1316 http_src_test_data.input = inputTestData;
1317 gst_test_http_src_install_callbacks (&http_src_callbacks,
1318 &http_src_test_data);
1319
1320 test_callbacks.appsink_received_data = testQueryCheckDataReceived;
1321 test_callbacks.appsink_eos =
1322 gst_adaptive_demux_test_check_size_of_received_data;
1323
1324 testData = gst_dash_demux_test_case_new ();
1325 COPY_OUTPUT_TEST_DATA (outputTestData, testData);
1326
1327 gst_adaptive_demux_test_run (DEMUX_ELEMENT_NAME,
1328 "http://unit.test/test.mpd", &test_callbacks, testData);
1329
1330 g_object_unref (testData);
1331 if (http_src_test_data.data)
1332 gst_structure_free (http_src_test_data.data);
1333 }
1334
1335 GST_END_TEST;
1336
1337 static gboolean
testContentProtectionDashdemuxSendsEvent(GstAdaptiveDemuxTestEngine * engine,GstAdaptiveDemuxTestOutputStream * stream,GstEvent * event,gpointer user_data)1338 testContentProtectionDashdemuxSendsEvent (GstAdaptiveDemuxTestEngine * engine,
1339 GstAdaptiveDemuxTestOutputStream * stream,
1340 GstEvent * event, gpointer user_data)
1341 {
1342 GstDashDemuxTestCase *test_case = GST_DASH_DEMUX_TEST_CASE (user_data);
1343 const gchar *system_id;
1344 GstBuffer *data;
1345 const gchar *origin;
1346 GstMapInfo info;
1347 gchar *value;
1348 gchar *name;
1349 guint event_count = 0;
1350
1351 GST_DEBUG ("received event %s", GST_EVENT_TYPE_NAME (event));
1352
1353 if (GST_EVENT_TYPE (event) != GST_EVENT_PROTECTION) {
1354 return TRUE;
1355 }
1356
1357 /* we expect content protection events only on video pad */
1358 name = gst_pad_get_name (stream->pad);
1359 fail_unless (g_strcmp0 (name, "video_00") == 0);
1360 gst_event_parse_protection (event, &system_id, &data, &origin);
1361
1362 gst_buffer_map (data, &info, GST_MAP_READ);
1363
1364 value = g_malloc (info.size + 1);
1365 strncpy (value, (gchar *) info.data, info.size);
1366 value[info.size] = 0;
1367 gst_buffer_unmap (data, &info);
1368
1369 if (g_strcmp0 (system_id, "11111111-AAAA-BBBB-CCCC-123456789ABC") == 0) {
1370 fail_unless (g_strcmp0 (origin, "dash/mpd") == 0);
1371 fail_unless (g_strcmp0 (value, "test value") == 0);
1372 } else if (g_strcmp0 (system_id, "5e629af5-38da-4063-8977-97ffbd9902d4") == 0) {
1373 const gchar *str;
1374
1375 fail_unless (g_strcmp0 (origin, "dash/mpd") == 0);
1376
1377 /* We can't do a simple compare of value (which should be an XML dump
1378 of the ContentProtection element), because the whitespace
1379 formatting from xmlDump might differ between versions of libxml */
1380 str = strstr (value, "<ContentProtection");
1381 fail_if (str == NULL);
1382 str = strstr (value, "<mas:MarlinContentIds>");
1383 fail_if (str == NULL);
1384 str = strstr (value, "<mas:MarlinContentId>");
1385 fail_if (str == NULL);
1386 str = strstr (value, "urn:marlin:kid:02020202020202020202020202020202");
1387 fail_if (str == NULL);
1388 str = strstr (value, "</ContentProtection>");
1389 fail_if (str == NULL);
1390 } else if (g_strcmp0 (system_id, "9a04f079-9840-4286-ab92-e65be0885f95") == 0) {
1391 fail_unless (g_strcmp0 (origin, "dash/mpd") == 0);
1392 fail_unless (g_strcmp0 (value, "dGVzdA==") == 0);
1393 } else {
1394 fail ("unexpected content protection event '%s'", system_id);
1395 }
1396
1397 g_free (value);
1398
1399 fail_if (test_case->countContentProtectionEvents == NULL);
1400 gst_structure_get_uint (test_case->countContentProtectionEvents, name,
1401 &event_count);
1402 event_count++;
1403 gst_structure_set (test_case->countContentProtectionEvents, name, G_TYPE_UINT,
1404 event_count, NULL);
1405
1406 g_free (name);
1407 return TRUE;
1408 }
1409
1410 /*
1411 * Test content protection
1412 * Configure 3 content protection sources:
1413 * - a uuid scheme/value pair
1414 * - a non uuid scheme/value pair (dash recognises only uuid schemes)
1415 * - a complex uuid scheme, with trailing spaces and capital letters in scheme uri
1416 * Only the uuid scheme will be recognised. We expect to receive 2 content
1417 * protection events
1418 */
GST_START_TEST(testContentProtection)1419 GST_START_TEST (testContentProtection)
1420 {
1421 const gchar *mpd =
1422 "<?xml version=\"1.0\" encoding=\"utf-8\"?>"
1423 "<MPD xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""
1424 " xmlns=\"urn:mpeg:DASH:schema:MPD:2011\""
1425 " xmlns:mspr=\"urn:microsoft:playready\""
1426 " xsi:schemaLocation=\"urn:mpeg:DASH:schema:MPD:2011 DASH-MPD.xsd\""
1427 " profiles=\"urn:mpeg:dash:profile:isoff-on-demand:2011\""
1428 " type=\"static\""
1429 " minBufferTime=\"PT1.500S\""
1430 " mediaPresentationDuration=\"PT135.743S\">"
1431 " <Period>"
1432 " <AdaptationSet mimeType=\"audio/webm\""
1433 " subsegmentAlignment=\"true\">"
1434 " <Representation id=\"171\""
1435 " codecs=\"vorbis\""
1436 " audioSamplingRate=\"44100\""
1437 " startWithSAP=\"1\""
1438 " bandwidth=\"129553\">"
1439 " <AudioChannelConfiguration"
1440 " schemeIdUri=\"urn:mpeg:dash:23003:3:audio_channel_configuration:2011\""
1441 " value=\"2\" />"
1442 " <BaseURL>audio.webm</BaseURL>"
1443 " <SegmentBase indexRange=\"4452-4686\""
1444 " indexRangeExact=\"true\">"
1445 " <Initialization range=\"0-4451\" />"
1446 " </SegmentBase>"
1447 " </Representation>"
1448 " </AdaptationSet>"
1449 " <AdaptationSet mimeType=\"video/webm\""
1450 " subsegmentAlignment=\"true\">"
1451 " <ContentProtection schemeIdUri=\"urn:uuid:11111111-AAAA-BBBB-CCCC-123456789ABC\" value=\"test value\"/>"
1452 " <ContentProtection schemeIdUri=\"urn:mpeg:dash:mp4protection:2011\" value=\"cenc\"/>"
1453 " <ContentProtection schemeIdUri=\" URN:UUID:5e629af5-38da-4063-8977-97ffbd9902d4\" xmlns:mas=\"urn:marlin:mas:1-0:services:schemas:mpd\">"
1454 " <mas:MarlinContentIds>"
1455 " <mas:MarlinContentId>urn:marlin:kid:02020202020202020202020202020202</mas:MarlinContentId>"
1456 " </mas:MarlinContentIds>"
1457 " </ContentProtection>"
1458 " <ContentProtection schemeIdUri=\"urn:uuid:9a04f079-9840-4286-ab92-e65be0885f95\" value=\"MSPR 2.0\">"
1459 " <mspr:pro>dGVzdA==</mspr:pro>"
1460 " </ContentProtection>"
1461 " <Representation id=\"242\""
1462 " codecs=\"vp9\""
1463 " width=\"426\""
1464 " height=\"240\""
1465 " startWithSAP=\"1\""
1466 " bandwidth=\"490208\">"
1467 " <BaseURL>video.webm</BaseURL>"
1468 " <SegmentBase indexRange=\"234-682\""
1469 " indexRangeExact=\"true\">"
1470 " <Initialization range=\"0-233\" />"
1471 " </SegmentBase>"
1472 " </Representation></AdaptationSet></Period></MPD>";
1473
1474 GstDashDemuxTestInputData inputTestData[] = {
1475 {"http://unit.test/test.mpd", (guint8 *) mpd, 0},
1476 {"http://unit.test/audio.webm", NULL, 5000},
1477 {"http://unit.test/video.webm", NULL, 9000},
1478 {NULL, NULL, 0},
1479 };
1480 GstAdaptiveDemuxTestExpectedOutput outputTestData[] = {
1481 {"audio_00", 5000, NULL},
1482 {"video_00", 9000, NULL},
1483 };
1484 GstTestHTTPSrcCallbacks http_src_callbacks = { 0 };
1485 GstTestHTTPSrcTestData http_src_test_data = { 0 };
1486 GstAdaptiveDemuxTestCallbacks test_callbacks = { 0 };
1487 GstDashDemuxTestCase *testData;
1488 guint event_count = 0;
1489
1490 http_src_callbacks.src_start = gst_dashdemux_http_src_start;
1491 http_src_callbacks.src_create = gst_dashdemux_http_src_create;
1492 http_src_test_data.input = inputTestData;
1493 gst_test_http_src_install_callbacks (&http_src_callbacks,
1494 &http_src_test_data);
1495
1496 test_callbacks.appsink_received_data =
1497 gst_adaptive_demux_test_check_received_data;
1498 test_callbacks.appsink_eos =
1499 gst_adaptive_demux_test_check_size_of_received_data;
1500 test_callbacks.demux_sent_event = testContentProtectionDashdemuxSendsEvent;
1501
1502 testData = gst_dash_demux_test_case_new ();
1503 COPY_OUTPUT_TEST_DATA (outputTestData, testData);
1504 testData->countContentProtectionEvents =
1505 gst_structure_new_empty ("countContentProtectionEvents");
1506 gst_adaptive_demux_test_run (DEMUX_ELEMENT_NAME, "http://unit.test/test.mpd",
1507 &test_callbacks, testData);
1508
1509 fail_unless (gst_structure_has_field_typed
1510 (testData->countContentProtectionEvents, "video_00", G_TYPE_UINT));
1511
1512 gst_structure_get_uint (testData->countContentProtectionEvents, "video_00",
1513 &event_count);
1514 fail_unless (event_count == 3);
1515
1516 g_object_unref (testData);
1517 if (http_src_test_data.data)
1518 gst_structure_free (http_src_test_data.data);
1519 }
1520
1521 GST_END_TEST;
1522
1523 static Suite *
dash_demux_suite(void)1524 dash_demux_suite (void)
1525 {
1526 Suite *s = suite_create ("dash_demux");
1527 TCase *tc_basicTest = tcase_create ("basicTest");
1528
1529 tcase_add_test (tc_basicTest, simpleTest);
1530 tcase_add_test (tc_basicTest, testTwoPeriods);
1531 tcase_add_test (tc_basicTest, testParameters);
1532 tcase_add_test (tc_basicTest, testSeek);
1533 tcase_add_test (tc_basicTest, testSeekKeyUnitPosition);
1534 tcase_add_test (tc_basicTest, testSeekPosition);
1535 tcase_add_test (tc_basicTest, testSeekUpdateStopPosition);
1536 tcase_add_test (tc_basicTest, testSeekSnapBeforePosition);
1537 tcase_add_test (tc_basicTest, testSeekSnapAfterPosition);
1538 tcase_add_test (tc_basicTest, testSeekSnapBeforeSamePosition);
1539 tcase_add_test (tc_basicTest, testSeekSnapAfterSamePosition);
1540 tcase_add_test (tc_basicTest, testReverseSeekSnapBeforePosition);
1541 tcase_add_test (tc_basicTest, testReverseSeekSnapAfterPosition);
1542 tcase_add_test (tc_basicTest, testDownloadError);
1543 tcase_add_test (tc_basicTest, testHeaderDownloadError);
1544 tcase_add_test (tc_basicTest, testMediaDownloadErrorLastFragment);
1545 tcase_add_test (tc_basicTest, testMediaDownloadErrorMiddleFragment);
1546 tcase_add_test (tc_basicTest, testQuery);
1547 tcase_add_test (tc_basicTest, testContentProtection);
1548
1549 tcase_add_unchecked_fixture (tc_basicTest, gst_adaptive_demux_test_setup,
1550 gst_adaptive_demux_test_teardown);
1551
1552 suite_add_tcase (s, tc_basicTest);
1553
1554 return s;
1555 }
1556
1557 GST_CHECK_MAIN (dash_demux);
1558