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