2015-10-09 13:10:52 +00:00
/* GStreamer unit test for MPEG-DASH
*
* Copyright ( c ) < 2015 > YouView TV Ltd
*
* This library is free software ; you can redistribute it and / or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation ; either
* version 2 of the License , or ( at your option ) any later version .
*
* This library is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the GNU
* Library General Public License for more details .
*
* You should have received a copy of the GNU Library General Public
* License along with this library ; if not , write to the
* Free Software Foundation , Inc . , 51 Franklin St , Fifth Floor ,
* Boston , MA 02110 - 1301 , USA .
*/
# include <gst/check/gstcheck.h>
2015-11-10 13:13:35 +00:00
# include "adaptive_demux_common.h"
2015-10-09 13:10:52 +00:00
2015-11-10 13:13:35 +00:00
# define DEMUX_ELEMENT_NAME "dashdemux"
2015-10-09 13:10:52 +00:00
2015-11-10 13:13:35 +00:00
# define COPY_OUTPUT_TEST_DATA(outputTestData,testData) do { \
guint otdPos , otdLen = sizeof ( ( outputTestData ) ) / sizeof ( ( outputTestData ) [ 0 ] ) ; \
for ( otdPos = 0 ; otdPos < otdLen ; + + otdPos ) { \
2016-02-16 14:24:26 +00:00
GST_ADAPTIVE_DEMUX_TEST_CASE ( testData ) - > output_streams = g_list_append ( GST_ADAPTIVE_DEMUX_TEST_CASE ( testData ) - > output_streams , & ( outputTestData ) [ otdPos ] ) ; \
2015-11-10 13:13:35 +00:00
} \
} while ( 0 )
2015-10-09 13:10:52 +00:00
2015-11-10 13:13:35 +00:00
typedef struct _GstDashDemuxTestInputData
2015-10-09 13:10:52 +00:00
{
2015-11-10 13:13:35 +00:00
const gchar * uri ;
const guint8 * payload ;
guint64 size ;
} GstDashDemuxTestInputData ;
2015-10-09 13:10:52 +00:00
2016-02-16 14:24:09 +00:00
typedef struct _GstTestHTTPSrcTestData
{
const GstDashDemuxTestInputData * input ;
GstStructure * data ;
} GstTestHTTPSrcTestData ;
2016-02-16 14:24:26 +00:00
typedef struct _GstDashDemuxTestCase
{
GstAdaptiveDemuxTestCase parent ;
2016-02-16 11:37:44 +00:00
/* the number of Protection Events sent to each pad */
GstStructure * countContentProtectionEvents ;
2016-02-16 14:24:26 +00:00
} GstDashDemuxTestCase ;
GType gst_dash_demux_test_case_get_type ( void ) ;
static void gst_dash_demux_test_case_dispose ( GObject * object ) ;
static void gst_dash_demux_test_case_finalize ( GObject * object ) ;
static void gst_dash_demux_test_case_clear ( GstDashDemuxTestCase * test_case ) ;
static GstDashDemuxTestCase *
gst_dash_demux_test_case_new ( void )
G_GNUC_MALLOC ;
# define GST_TYPE_DASH_DEMUX_TEST_CASE \
( gst_dash_demux_test_case_get_type ( ) )
# define GST_DASH_DEMUX_TEST_CASE(obj) \
( G_TYPE_CHECK_INSTANCE_CAST ( ( obj ) , GST_TYPE_DASH_DEMUX_TEST_CASE , GstDashDemuxTestCase ) )
# define GST_DASH_DEMUX_TEST_CASE_CLASS(klass) \
( G_TYPE_CHECK_CLASS_CAST ( ( klass ) , GST_TYPE_DASH_DEMUX_TEST_CASE , GstDashDemuxTestCaseClass ) )
# define GST_DASH_DEMUX_TEST_CASE_GET_CLASS(obj) \
( G_TYPE_INSTANCE_GET_CLASS ( ( obj ) , GST_TYPE_DASH_DEMUX_TEST_CASE , GstDashDemuxTestCaseClass ) )
# define GST_IS_DASH_DEMUX_TEST_CASE(obj) \
( G_TYPE_CHECK_INSTANCE_TYPE ( ( obj ) , GST_TYPE_DASH_DEMUX_TEST_CASE ) )
# define GST_IS_DASH_DEMUX_TEST_CASE_CLASS(klass) \
( G_TYPE_CHECK_CLASS_TYPE ( ( klass ) , GST_TYPE_DASH_DEMUX_TEST_CASE ) )
static GstDashDemuxTestCase * gst_dash_demux_test_case_new ( void )
{
return g_object_newv ( GST_TYPE_DASH_DEMUX_TEST_CASE , 0 , NULL ) ;
}
typedef struct _GstDashDemuxTestCaseClass
{
GstAdaptiveDemuxTestCaseClass parent_class ;
} GstDashDemuxTestCaseClass ;
# define gst_dash_demux_test_case_parent_class parent_class
G_DEFINE_TYPE ( GstDashDemuxTestCase , gst_dash_demux_test_case ,
GST_TYPE_ADAPTIVE_DEMUX_TEST_CASE ) ;
static void
gst_dash_demux_test_case_class_init ( GstDashDemuxTestCaseClass * klass )
{
GObjectClass * object = G_OBJECT_CLASS ( klass ) ;
object - > dispose = gst_dash_demux_test_case_dispose ;
object - > finalize = gst_dash_demux_test_case_finalize ;
}
static void
gst_dash_demux_test_case_init ( GstDashDemuxTestCase * test_case )
{
2016-02-16 11:37:44 +00:00
test_case - > countContentProtectionEvents = NULL ;
2016-02-16 14:24:26 +00:00
gst_dash_demux_test_case_clear ( test_case ) ;
}
static void
gst_dash_demux_test_case_clear ( GstDashDemuxTestCase * test_case )
{
2016-02-16 11:37:44 +00:00
if ( test_case - > countContentProtectionEvents ) {
gst_structure_free ( test_case - > countContentProtectionEvents ) ;
test_case - > countContentProtectionEvents = NULL ;
}
2016-02-16 14:24:26 +00:00
}
static void
gst_dash_demux_test_case_dispose ( GObject * object )
{
GstDashDemuxTestCase * testData = GST_DASH_DEMUX_TEST_CASE ( object ) ;
gst_dash_demux_test_case_clear ( testData ) ;
G_OBJECT_CLASS ( parent_class ) - > dispose ( object ) ;
}
static void
gst_dash_demux_test_case_finalize ( GObject * object )
{
/*GstDashDemuxTestCase *testData = GST_DASH_DEMUX_TEST_CASE (object); */
G_OBJECT_CLASS ( parent_class ) - > finalize ( object ) ;
}
2015-11-10 13:13:35 +00:00
static gboolean
gst_dashdemux_http_src_start ( GstTestHTTPSrc * src ,
const gchar * uri , GstTestHTTPSrcInput * input_data , gpointer user_data )
{
2016-02-16 14:24:09 +00:00
const GstTestHTTPSrcTestData * test_case =
( const GstTestHTTPSrcTestData * ) user_data ;
for ( guint i = 0 ; test_case - > input [ i ] . uri ; + + i ) {
if ( g_strcmp0 ( test_case - > input [ i ] . uri , uri ) = = 0 ) {
input_data - > context = ( gpointer ) & test_case - > input [ i ] ;
input_data - > size = test_case - > input [ i ] . size ;
if ( test_case - > input [ i ] . size = = 0 )
input_data - > size = strlen ( ( gchar * ) test_case - > input [ i ] . payload ) ;
2015-11-10 13:13:35 +00:00
return TRUE ;
2015-10-09 13:10:52 +00:00
}
}
2015-11-10 13:13:35 +00:00
return FALSE ;
2015-10-09 13:10:52 +00:00
}
static GstFlowReturn
2015-11-10 13:13:35 +00:00
gst_dashdemux_http_src_create ( GstTestHTTPSrc * src ,
guint64 offset ,
guint length , GstBuffer * * retbuf , gpointer context , gpointer user_data )
2015-10-09 13:10:52 +00:00
{
2015-11-10 13:13:35 +00:00
const GstDashDemuxTestInputData * input =
( const GstDashDemuxTestInputData * ) context ;
GstBuffer * buf ;
2015-10-20 14:46:36 +00:00
2015-11-10 13:13:35 +00:00
buf = gst_buffer_new_allocate ( NULL , length , NULL ) ;
fail_if ( buf = = NULL , " Not enough memory to allocate buffer " ) ;
2015-10-09 13:10:52 +00:00
2015-11-10 13:13:35 +00:00
if ( input - > payload ) {
gst_buffer_fill ( buf , 0 , input - > payload + offset , length ) ;
2015-10-09 13:10:52 +00:00
} else {
2015-11-10 13:13:35 +00:00
GstMapInfo info ;
guint pattern ;
2015-10-20 14:46:36 +00:00
2015-11-10 13:13:35 +00:00
pattern = offset - offset % sizeof ( pattern ) ;
2015-10-09 13:10:52 +00:00
2015-11-10 13:13:35 +00:00
gst_buffer_map ( buf , & info , GST_MAP_WRITE ) ;
for ( guint64 i = 0 ; i < length ; + + i ) {
gchar pattern_byte_to_write = ( offset + i ) % sizeof ( pattern ) ;
if ( pattern_byte_to_write = = 0 ) {
pattern = offset + i ;
}
info . data [ i ] = ( pattern > > ( pattern_byte_to_write * 8 ) ) & 0xFF ;
2015-10-09 13:10:52 +00:00
}
2015-11-10 13:13:35 +00:00
gst_buffer_unmap ( buf , & info ) ;
2015-10-09 13:10:52 +00:00
}
2015-11-10 13:13:35 +00:00
* retbuf = buf ;
return GST_FLOW_OK ;
2015-10-09 13:10:52 +00:00
}
2015-11-10 13:13:35 +00:00
/******************** Test specific code starts here **************************/
2015-10-09 13:10:52 +00:00
/*
* Test an mpd with an audio and a video stream
*
*/
GST_START_TEST ( simpleTest )
{
const gchar * mpd =
" <?xml version= \" 1.0 \" encoding= \" utf-8 \" ?> "
" <MPD xmlns:xsi= \" http://www.w3.org/2001/XMLSchema-instance \" "
" xmlns= \" urn:mpeg:DASH:schema:MPD:2011 \" "
" xsi:schemaLocation= \" urn:mpeg:DASH:schema:MPD:2011 DASH-MPD.xsd \" "
" profiles= \" urn:mpeg:dash:profile:isoff-on-demand:2011 \" "
" type= \" static \" "
" minBufferTime= \" PT1.500S \" "
" mediaPresentationDuration= \" PT135.743S \" > "
" <Period> "
" <AdaptationSet mimeType= \" audio/webm \" "
" subsegmentAlignment= \" true \" > "
" <Representation id= \" 171 \" "
" codecs= \" vorbis \" "
" audioSamplingRate= \" 44100 \" "
" startWithSAP= \" 1 \" "
" bandwidth= \" 129553 \" > "
" <AudioChannelConfiguration "
" schemeIdUri= \" urn:mpeg:dash:23003:3:audio_channel_configuration:2011 \" "
" value= \" 2 \" /> "
" <BaseURL>audio.webm</BaseURL> "
" <SegmentBase indexRange= \" 4452-4686 \" "
" indexRangeExact= \" true \" > "
" <Initialization range= \" 0-4451 \" /> "
" </SegmentBase> "
" </Representation> "
" </AdaptationSet> "
" <AdaptationSet mimeType= \" video/webm \" "
" subsegmentAlignment= \" true \" > "
" <Representation id= \" 242 \" "
" codecs= \" vp9 \" "
" width= \" 426 \" "
" height= \" 240 \" "
" startWithSAP= \" 1 \" "
" bandwidth= \" 490208 \" > "
" <BaseURL>video.webm</BaseURL> "
" <SegmentBase indexRange= \" 234-682 \" "
" indexRangeExact= \" true \" > "
" <Initialization range= \" 0-233 \" /> "
" </SegmentBase> "
" </Representation></AdaptationSet></Period></MPD> " ;
2016-02-16 14:24:09 +00:00
2015-11-10 13:13:35 +00:00
GstDashDemuxTestInputData inputTestData [ ] = {
{ " http://unit.test/test.mpd " , ( guint8 * ) mpd , 0 } ,
2015-10-09 13:10:52 +00:00
{ " http://unit.test/audio.webm " , NULL , 5000 } ,
{ " http://unit.test/video.webm " , NULL , 9000 } ,
{ NULL , NULL , 0 } ,
} ;
2015-11-10 13:13:35 +00:00
GstAdaptiveDemuxTestExpectedOutput outputTestData [ ] = {
2015-10-09 13:10:52 +00:00
{ " audio_00 " , 5000 , NULL } ,
2015-11-10 13:13:35 +00:00
{ " video_00 " , 9000 , NULL }
2015-10-09 13:10:52 +00:00
} ;
2016-02-16 14:24:09 +00:00
GstTestHTTPSrcCallbacks http_src_callbacks = { 0 } ;
GstTestHTTPSrcTestData http_src_test_data = { 0 } ;
2015-11-10 13:13:35 +00:00
GstAdaptiveDemuxTestCallbacks test_callbacks = { 0 } ;
2016-02-16 14:24:26 +00:00
GstDashDemuxTestCase * testData ;
2015-10-09 13:10:52 +00:00
2015-11-10 13:13:35 +00:00
http_src_callbacks . src_start = gst_dashdemux_http_src_start ;
http_src_callbacks . src_create = gst_dashdemux_http_src_create ;
2016-02-16 14:24:09 +00:00
http_src_test_data . input = inputTestData ;
gst_test_http_src_install_callbacks ( & http_src_callbacks ,
& http_src_test_data ) ;
2015-10-09 13:10:52 +00:00
2015-11-10 13:13:35 +00:00
test_callbacks . appsink_received_data =
gst_adaptive_demux_test_check_received_data ;
test_callbacks . appsink_eos =
gst_adaptive_demux_test_check_size_of_received_data ;
2016-02-16 14:24:26 +00:00
testData = gst_dash_demux_test_case_new ( ) ;
2016-02-16 14:24:09 +00:00
COPY_OUTPUT_TEST_DATA ( outputTestData , testData ) ;
2015-11-10 13:13:35 +00:00
gst_adaptive_demux_test_run ( DEMUX_ELEMENT_NAME , " http://unit.test/test.mpd " ,
& test_callbacks , testData ) ;
2016-02-16 14:24:09 +00:00
2015-11-10 13:13:35 +00:00
g_object_unref ( testData ) ;
2016-02-16 14:24:09 +00:00
if ( http_src_test_data . data )
gst_structure_free ( http_src_test_data . data ) ;
2015-10-09 13:10:52 +00:00
}
GST_END_TEST ;
/*
* Test an mpd with 2 periods
*
*/
GST_START_TEST ( testTwoPeriods )
{
const gchar * mpd =
" <?xml version= \" 1.0 \" encoding= \" utf-8 \" ?> "
" <MPD xmlns:xsi= \" http://www.w3.org/2001/XMLSchema-instance \" "
" xmlns= \" urn:mpeg:DASH:schema:MPD:2011 \" "
" xsi:schemaLocation= \" urn:mpeg:DASH:schema:MPD:2011 DASH-MPD.xsd \" "
" profiles= \" urn:mpeg:dash:profile:isoff-on-demand:2011 \" "
" type= \" static \" "
" minBufferTime= \" PT1.500S \" "
" mediaPresentationDuration= \" PT300S \" > "
" <Period id= \" Period0 \" duration= \" PT0.1S \" > "
" <AdaptationSet mimeType= \" audio/webm \" "
" subsegmentAlignment= \" true \" > "
" <Representation id= \" 171 \" "
" codecs= \" vorbis \" "
" audioSamplingRate= \" 44100 \" "
" startWithSAP= \" 1 \" "
" bandwidth= \" 129553 \" > "
" <AudioChannelConfiguration "
" schemeIdUri= \" urn:mpeg:dash:23003:3:audio_channel_configuration:2011 \" "
" value= \" 2 \" /> "
" <BaseURL>audio1.webm</BaseURL> "
" <SegmentBase indexRange= \" 4452-4686 \" "
" indexRangeExact= \" true \" > "
" <Initialization range= \" 0-4451 \" /> "
" </SegmentBase> "
" </Representation> "
" </AdaptationSet> "
" <AdaptationSet mimeType= \" video/webm \" "
" subsegmentAlignment= \" true \" > "
" <Representation id= \" 242 \" "
" codecs= \" vp9 \" "
" width= \" 426 \" "
" height= \" 240 \" "
" startWithSAP= \" 1 \" "
" bandwidth= \" 490208 \" > "
" <BaseURL>video1.webm</BaseURL> "
" <SegmentBase indexRange= \" 234-682 \" "
" indexRangeExact= \" true \" > "
" <Initialization range= \" 0-233 \" /> "
" </SegmentBase> "
" </Representation> "
" </AdaptationSet> "
" </Period> "
" <Period> "
" <AdaptationSet mimeType= \" audio/webm \" "
" subsegmentAlignment= \" true \" > "
" <Representation id= \" 171 \" "
" codecs= \" vorbis \" "
" audioSamplingRate= \" 44100 \" "
" startWithSAP= \" 1 \" "
" bandwidth= \" 129553 \" > "
" <AudioChannelConfiguration "
" schemeIdUri= \" urn:mpeg:dash:23003:3:audio_channel_configuration:2011 \" "
" value= \" 2 \" /> "
" <BaseURL>audio2.webm</BaseURL> "
" <SegmentBase indexRange= \" 4452-4686 \" "
" indexRangeExact= \" true \" > "
" <Initialization range= \" 0-4451 \" /> "
" </SegmentBase> "
" </Representation> "
" </AdaptationSet> "
" <AdaptationSet mimeType= \" video/webm \" "
" subsegmentAlignment= \" true \" > "
" <Representation id= \" 242 \" "
" codecs= \" vp9 \" "
" width= \" 426 \" "
" height= \" 240 \" "
" startWithSAP= \" 1 \" "
" bandwidth= \" 490208 \" > "
" <BaseURL>video2.webm</BaseURL> "
" <SegmentBase indexRange= \" 234-682 \" "
" indexRangeExact= \" true \" > "
" <Initialization range= \" 0-233 \" /> "
" </SegmentBase> "
" </Representation></AdaptationSet></Period></MPD> " ;
2015-11-10 13:13:35 +00:00
GstDashDemuxTestInputData inputTestData [ ] = {
{ " http://unit.test/test.mpd " , ( guint8 * ) mpd , 0 } ,
2015-10-09 13:10:52 +00:00
{ " http://unit.test/audio1.webm " , NULL , 5001 } ,
{ " http://unit.test/video1.webm " , NULL , 9001 } ,
{ " http://unit.test/audio2.webm " , NULL , 5002 } ,
{ " http://unit.test/video2.webm " , NULL , 9002 } ,
{ NULL , NULL , 0 } ,
} ;
2015-11-10 13:13:35 +00:00
GstAdaptiveDemuxTestExpectedOutput outputTestData [ ] = {
2015-10-09 13:10:52 +00:00
{ " audio_00 " , 5001 , NULL } ,
{ " video_00 " , 9001 , NULL } ,
{ " audio_01 " , 5002 , NULL } ,
{ " video_01 " , 9002 , NULL } ,
} ;
2016-02-16 14:24:09 +00:00
GstTestHTTPSrcCallbacks http_src_callbacks = { 0 } ;
GstTestHTTPSrcTestData http_src_test_data = { 0 } ;
2015-11-10 13:13:35 +00:00
GstAdaptiveDemuxTestCallbacks test_callbacks = { 0 } ;
2016-02-16 14:24:26 +00:00
GstDashDemuxTestCase * testData ;
2015-10-09 13:10:52 +00:00
2015-11-10 13:13:35 +00:00
http_src_callbacks . src_start = gst_dashdemux_http_src_start ;
http_src_callbacks . src_create = gst_dashdemux_http_src_create ;
2016-02-16 14:24:09 +00:00
http_src_test_data . input = inputTestData ;
gst_test_http_src_install_callbacks ( & http_src_callbacks ,
& http_src_test_data ) ;
2015-11-10 13:13:35 +00:00
test_callbacks . appsink_received_data =
gst_adaptive_demux_test_check_received_data ;
test_callbacks . appsink_eos =
gst_adaptive_demux_test_check_size_of_received_data ;
2015-10-09 13:10:52 +00:00
2016-02-16 14:24:26 +00:00
testData = gst_dash_demux_test_case_new ( ) ;
2016-02-16 14:24:09 +00:00
COPY_OUTPUT_TEST_DATA ( outputTestData , testData ) ;
2015-11-10 13:13:35 +00:00
gst_adaptive_demux_test_run ( DEMUX_ELEMENT_NAME ,
" http://unit.test/test.mpd " , & test_callbacks , testData ) ;
2016-02-16 14:24:09 +00:00
2016-02-16 13:55:54 +00:00
g_object_unref ( testData ) ;
2016-02-16 14:24:09 +00:00
if ( http_src_test_data . data )
gst_structure_free ( http_src_test_data . data ) ;
2015-10-09 13:10:52 +00:00
}
GST_END_TEST ;
/* test setting a property on an object */
# define test_int_prop(object, name, value) \
do \
{ \
int val = value ; \
int val_after ; \
g_object_set ( object , name , val , NULL ) ; \
g_object_get ( object , name , & val_after , NULL ) ; \
fail_unless ( val_after = = val , " property check failed for %s: set to %d, but got %d " , \
name , val , val_after ) ; \
} while ( 0 )
# define test_float_prop(object, name, value) \
do \
{ \
float val = value ; \
float val_after ; \
g_object_set ( object , name , val , NULL ) ; \
g_object_get ( object , name , & val_after , NULL ) ; \
fail_unless ( val_after = = val , " property check failed for %s: set to %f, but got %f " , \
name , val , val_after ) ; \
} while ( 0 )
/* test setting an invalid value for a property on an object.
* Expect an assert and the property to remain unchanged
*/
# define test_invalid_int_prop(object, name, value) \
do \
{ \
int val_before ; \
int val_after ; \
int val = value ; \
g_object_get ( object , name , & val_before , NULL ) ; \
ASSERT_WARNING ( g_object_set ( object , name , val , NULL ) ) ; \
g_object_get ( object , name , & val_after , NULL ) ; \
fail_unless ( val_after = = val_before , " property check failed for %s: before %d, after %d " , \
name , val_before , val_after ) ; \
} while ( 0 )
# define test_invalid_float_prop(object, name, value) \
do \
{ \
float val_before ; \
float val_after ; \
float val = value ; \
g_object_get ( object , name , & val_before , NULL ) ; \
ASSERT_WARNING ( g_object_set ( object , name , val , NULL ) ) ; \
g_object_get ( object , name , & val_after , NULL ) ; \
fail_unless ( val_after = = val_before , " property check failed for %s: before %f, after %f " , \
name , val_before , val_after ) ; \
} while ( 0 )
static void
2015-11-10 13:13:35 +00:00
setAndTestDashParams ( GstAdaptiveDemuxTestEngine * engine , gpointer user_data )
2015-10-09 13:10:52 +00:00
{
2016-02-16 14:24:26 +00:00
/* GstDashDemuxTestCase * testData = (GstDashDemuxTestCase*)user_data; */
2015-11-10 13:13:35 +00:00
GObject * dashdemux = G_OBJECT ( engine - > demux ) ;
2015-10-09 13:10:52 +00:00
2015-11-10 13:13:35 +00:00
test_int_prop ( dashdemux , " connection-speed " , 1000 ) ;
test_invalid_int_prop ( dashdemux , " connection-speed " , 4294967 + 1 ) ;
2015-10-09 13:10:52 +00:00
2015-11-10 13:13:35 +00:00
test_float_prop ( dashdemux , " bitrate-limit " , 1 ) ;
test_invalid_float_prop ( dashdemux , " bitrate-limit " , 2.1 ) ;
2015-10-09 13:10:52 +00:00
2015-11-10 13:13:35 +00:00
test_int_prop ( dashdemux , " max-buffering-time " , 15 ) ;
test_invalid_int_prop ( dashdemux , " max-buffering-time " , 1 ) ;
2015-10-09 13:10:52 +00:00
2015-11-10 13:13:35 +00:00
test_float_prop ( dashdemux , " bandwidth-usage " , 0.5 ) ;
test_invalid_float_prop ( dashdemux , " bandwidth-usage " , 2 ) ;
2015-10-09 13:10:52 +00:00
2015-11-10 13:13:35 +00:00
test_int_prop ( dashdemux , " max-bitrate " , 1000 ) ;
test_invalid_int_prop ( dashdemux , " max-bitrate " , 10 ) ;
2015-10-09 13:10:52 +00:00
}
/*
* Test setting parameters
*
*/
GST_START_TEST ( testParameters )
{
const gchar * mpd =
" <?xml version= \" 1.0 \" encoding= \" utf-8 \" ?> "
" <MPD xmlns:xsi= \" http://www.w3.org/2001/XMLSchema-instance \" "
" xmlns= \" urn:mpeg:DASH:schema:MPD:2011 \" "
" xsi:schemaLocation= \" urn:mpeg:DASH:schema:MPD:2011 DASH-MPD.xsd \" "
" profiles= \" urn:mpeg:dash:profile:isoff-on-demand:2011 \" "
" type= \" static \" "
" minBufferTime= \" PT1.500S \" "
" mediaPresentationDuration= \" PT135.743S \" > "
" <Period> "
" <AdaptationSet mimeType= \" audio/webm \" "
" subsegmentAlignment= \" true \" > "
" <Representation id= \" 171 \" "
" codecs= \" vorbis \" "
" audioSamplingRate= \" 44100 \" "
" startWithSAP= \" 1 \" "
" bandwidth= \" 129553 \" > "
" <AudioChannelConfiguration "
" schemeIdUri= \" urn:mpeg:dash:23003:3:audio_channel_configuration:2011 \" "
" value= \" 2 \" /> "
" <BaseURL>audio.webm</BaseURL> "
" <SegmentBase indexRange= \" 4452-4686 \" "
" indexRangeExact= \" true \" > "
" <Initialization range= \" 0-4451 \" /> "
" </SegmentBase> "
" </Representation></AdaptationSet></Period></MPD> " ;
2015-11-10 13:13:35 +00:00
GstDashDemuxTestInputData inputTestData [ ] = {
{ " http://unit.test/test.mpd " , ( guint8 * ) mpd , 0 } ,
2015-10-09 13:10:52 +00:00
{ " http://unit.test/audio.webm " , NULL , 5000 } ,
{ NULL , NULL , 0 } ,
} ;
2015-11-10 13:13:35 +00:00
GstAdaptiveDemuxTestExpectedOutput outputTestData [ ] = {
2015-10-09 13:10:52 +00:00
{ " audio_00 " , 5000 , NULL } ,
} ;
2016-02-16 14:24:09 +00:00
GstTestHTTPSrcCallbacks http_src_callbacks = { 0 } ;
GstTestHTTPSrcTestData http_src_test_data = { 0 } ;
2015-11-10 13:13:35 +00:00
GstAdaptiveDemuxTestCallbacks test_callbacks = { 0 } ;
2016-02-16 14:24:26 +00:00
GstDashDemuxTestCase * testData ;
2015-10-09 13:10:52 +00:00
2015-11-10 13:13:35 +00:00
http_src_callbacks . src_start = gst_dashdemux_http_src_start ;
http_src_callbacks . src_create = gst_dashdemux_http_src_create ;
2016-02-16 14:24:09 +00:00
http_src_test_data . input = inputTestData ;
gst_test_http_src_install_callbacks ( & http_src_callbacks ,
& http_src_test_data ) ;
2015-11-10 13:13:35 +00:00
test_callbacks . pre_test = setAndTestDashParams ;
test_callbacks . appsink_received_data =
gst_adaptive_demux_test_check_received_data ;
test_callbacks . appsink_eos =
gst_adaptive_demux_test_check_size_of_received_data ;
2015-10-09 13:10:52 +00:00
2016-02-16 14:24:26 +00:00
testData = gst_dash_demux_test_case_new ( ) ;
2016-02-16 14:24:09 +00:00
COPY_OUTPUT_TEST_DATA ( outputTestData , testData ) ;
2015-11-10 13:13:35 +00:00
gst_adaptive_demux_test_run ( DEMUX_ELEMENT_NAME , " http://unit.test/test.mpd " ,
& test_callbacks , testData ) ;
2016-02-16 14:24:09 +00:00
2016-02-16 13:55:54 +00:00
g_object_unref ( testData ) ;
2016-02-16 14:24:09 +00:00
if ( http_src_test_data . data )
gst_structure_free ( http_src_test_data . data ) ;
2015-10-09 13:10:52 +00:00
}
GST_END_TEST ;
/*
* Test seeking
*
*/
GST_START_TEST ( testSeek )
{
const gchar * mpd =
" <?xml version= \" 1.0 \" encoding= \" utf-8 \" ?> "
" <MPD xmlns:xsi= \" http://www.w3.org/2001/XMLSchema-instance \" "
" xmlns= \" urn:mpeg:DASH:schema:MPD:2011 \" "
" xsi:schemaLocation= \" urn:mpeg:DASH:schema:MPD:2011 DASH-MPD.xsd \" "
" profiles= \" urn:mpeg:dash:profile:isoff-on-demand:2011 \" "
" type= \" static \" "
" minBufferTime= \" PT1.500S \" "
" mediaPresentationDuration= \" PT135.743S \" > "
" <Period> "
" <AdaptationSet mimeType= \" audio/webm \" "
" subsegmentAlignment= \" true \" > "
" <Representation id= \" 171 \" "
" codecs= \" vorbis \" "
" audioSamplingRate= \" 44100 \" "
" startWithSAP= \" 1 \" "
" bandwidth= \" 129553 \" > "
" <AudioChannelConfiguration "
" schemeIdUri= \" urn:mpeg:dash:23003:3:audio_channel_configuration:2011 \" "
" value= \" 2 \" /> "
" <BaseURL>audio.webm</BaseURL> "
" <SegmentBase indexRange= \" 4452-4686 \" "
" indexRangeExact= \" true \" > "
" <Initialization range= \" 0-4451 \" /> "
" </SegmentBase> "
" </Representation></AdaptationSet></Period></MPD> " ;
2016-02-16 14:24:09 +00:00
2015-11-10 13:13:35 +00:00
GstDashDemuxTestInputData inputTestData [ ] = {
{ " http://unit.test/test.mpd " , ( guint8 * ) mpd , 0 } ,
2015-10-09 13:10:52 +00:00
{ " http://unit.test/audio.webm " , NULL , 10000 } ,
{ NULL , NULL , 0 } ,
} ;
2015-11-10 13:13:35 +00:00
GstAdaptiveDemuxTestExpectedOutput outputTestData [ ] = {
2015-10-09 13:10:52 +00:00
{ " audio_00 " , 10000 , NULL } ,
} ;
2016-02-16 14:24:09 +00:00
GstTestHTTPSrcCallbacks http_src_callbacks = { 0 } ;
GstTestHTTPSrcTestData http_src_test_data = { 0 } ;
2016-02-16 14:24:26 +00:00
GstDashDemuxTestCase * testData ;
2015-10-09 13:10:52 +00:00
2015-11-10 13:13:35 +00:00
http_src_callbacks . src_start = gst_dashdemux_http_src_start ;
http_src_callbacks . src_create = gst_dashdemux_http_src_create ;
2016-02-16 14:24:09 +00:00
http_src_test_data . input = inputTestData ;
gst_test_http_src_install_callbacks ( & http_src_callbacks ,
& http_src_test_data ) ;
2016-02-16 14:24:26 +00:00
testData = gst_dash_demux_test_case_new ( ) ;
2015-11-10 13:13:35 +00:00
COPY_OUTPUT_TEST_DATA ( outputTestData , testData ) ;
2015-10-16 16:10:11 +00:00
2015-11-10 13:13:35 +00:00
/* media segment starts at 4687
* Issue a seek request after media segment has started to be downloaded
* on the first pad listed in GstAdaptiveDemuxTestOutputStreamData and the
* first chunk of at least one byte has already arrived in AppSink
*/
2016-02-16 14:24:26 +00:00
GST_ADAPTIVE_DEMUX_TEST_CASE ( testData ) - > threshold_for_seek = 4687 + 1 ;
2015-10-16 16:10:11 +00:00
2015-12-23 18:25:29 +00:00
/* seek to 5ms.
* Because there is only one fragment , we expect the whole file to be
* downloaded again
*/
2016-02-16 14:24:26 +00:00
GST_ADAPTIVE_DEMUX_TEST_CASE ( testData ) - > seek_event =
2015-12-23 18:25:29 +00:00
gst_event_new_seek ( 1.0 , GST_FORMAT_TIME ,
GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_KEY_UNIT , GST_SEEK_TYPE_SET ,
5 * GST_MSECOND , GST_SEEK_TYPE_NONE , 0 ) ;
2015-11-10 13:13:35 +00:00
gst_adaptive_demux_test_seek ( DEMUX_ELEMENT_NAME ,
2016-02-16 14:24:26 +00:00
" http://unit.test/test.mpd " , GST_ADAPTIVE_DEMUX_TEST_CASE ( testData ) ) ;
2016-02-16 14:24:09 +00:00
2016-02-16 13:55:54 +00:00
g_object_unref ( testData ) ;
2016-02-16 14:24:09 +00:00
if ( http_src_test_data . data )
gst_structure_free ( http_src_test_data . data ) ;
2015-10-16 16:10:11 +00:00
}
GST_END_TEST ;
2016-01-05 20:41:23 +00:00
2016-02-26 21:17:37 +00:00
# define SEGMENT_SIZE 10000
2016-01-05 20:41:23 +00:00
static void
2016-01-27 02:15:10 +00:00
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 ,
2016-02-26 21:17:37 +00:00
gint segments , gint seek_threshold_bytes )
2016-01-05 20:41:23 +00:00
{
const gchar * mpd =
" <?xml version= \" 1.0 \" encoding= \" utf-8 \" ?> "
" <MPD xmlns:xsi= \" http://www.w3.org/2001/XMLSchema-instance \" "
" xmlns= \" urn:mpeg:DASH:schema:MPD:2011 \" "
" xsi:schemaLocation= \" urn:mpeg:DASH:schema:MPD:2011 DASH-MPD.xsd \" "
" profiles= \" urn:mpeg:dash:profile:isoff-on-demand:2011 \" "
" type= \" static \" "
" minBufferTime= \" PT1.500S \" "
" mediaPresentationDuration= \" PT135.743S \" > "
" <Period> "
" <AdaptationSet "
" mimeType= \" audio/mp4 \" minBandwidth= \" 128000 \" "
" maxBandwidth= \" 128000 \" segmentAlignment= \" true \" > "
" <SegmentTemplate timescale= \" 48000 \" "
" initialization= \" init-$RepresentationID$.mp4 \" "
" media= \" $RepresentationID$-$Number$.mp4 \" "
" startNumber= \" 1 \" > "
" <SegmentTimeline> "
" <S t= \" 0 \" d= \" 48000 \" /> "
" <S d= \" 48000 \" /> "
" <S d= \" 48000 \" /> "
" <S d= \" 48000 \" /> "
" </SegmentTimeline> "
" </SegmentTemplate> "
" <Representation id= \" audio \" bandwidth= \" 128000 \" "
" codecs= \" mp4a.40.2 \" audioSamplingRate= \" 48000 \" > "
" <AudioChannelConfiguration "
" schemeIdUri= \" urn:mpeg:dash:23003:3:audio_channel_configuration:2011 \" "
" value= \" 2 \" > "
" </AudioChannelConfiguration> "
" </Representation></AdaptationSet></Period></MPD> " ;
2016-02-16 14:24:09 +00:00
2016-01-05 20:41:23 +00:00
GstDashDemuxTestInputData inputTestData [ ] = {
{ " http://unit.test/test.mpd " , ( guint8 * ) mpd , 0 } ,
{ " http://unit.test/init-audio.mp4 " , NULL , 10000 } ,
{ " http://unit.test/audio-1.mp4 " , NULL , 10000 } ,
{ " http://unit.test/audio-2.mp4 " , NULL , 10000 } ,
{ " http://unit.test/audio-3.mp4 " , NULL , 10000 } ,
{ " http://unit.test/audio-4.mp4 " , NULL , 10000 } ,
{ NULL , NULL , 0 } ,
} ;
GstTestHTTPSrcCallbacks http_src_callbacks = { 0 } ;
2016-02-16 14:24:09 +00:00
GstTestHTTPSrcTestData http_src_test_data = { 0 } ;
2016-01-05 20:41:23 +00:00
GstAdaptiveDemuxTestExpectedOutput outputTestData [ ] = {
/* 1 from the init segment */
2016-02-26 21:17:37 +00:00
{ " audio_00 " , ( segments ? 1 + segments : 0 ) * 10000 , NULL } ,
2016-01-05 20:41:23 +00:00
} ;
2016-02-16 14:24:26 +00:00
GstDashDemuxTestCase * testData ;
2016-01-05 20:41:23 +00:00
http_src_callbacks . src_start = gst_dashdemux_http_src_start ;
http_src_callbacks . src_create = gst_dashdemux_http_src_create ;
2016-02-16 14:24:09 +00:00
http_src_test_data . input = inputTestData ;
gst_test_http_src_install_callbacks ( & http_src_callbacks ,
& http_src_test_data ) ;
2016-02-16 14:24:26 +00:00
testData = gst_dash_demux_test_case_new ( ) ;
2016-01-05 20:41:23 +00:00
COPY_OUTPUT_TEST_DATA ( outputTestData , testData ) ;
/* media segment starts at 4687
* Issue a seek request after media segment has started to be downloaded
* on the first pad listed in GstAdaptiveDemuxTestOutputStreamData and the
* first chunk of at least one byte has already arrived in AppSink
*/
2016-02-26 21:17:37 +00:00
if ( seek_threshold_bytes )
2016-02-16 11:37:44 +00:00
GST_ADAPTIVE_DEMUX_TEST_CASE ( testData ) - > threshold_for_seek =
seek_threshold_bytes ;
2016-02-26 21:17:37 +00:00
else
2016-02-16 14:24:26 +00:00
GST_ADAPTIVE_DEMUX_TEST_CASE ( testData ) - > threshold_for_seek = 4687 + 1 ;
2016-01-05 20:41:23 +00:00
/* FIXME hack to avoid having a 0 seqnum */
gst_util_seqnum_next ( ) ;
/* seek to 5ms.
* Because there is only one fragment , we expect the whole file to be
* downloaded again
*/
2016-02-16 14:24:26 +00:00
GST_ADAPTIVE_DEMUX_TEST_CASE ( testData ) - > seek_event =
2016-01-27 02:15:10 +00:00
gst_event_new_seek ( rate , GST_FORMAT_TIME , flags , start_type ,
2016-01-05 20:41:23 +00:00
seek_start , stop_type , seek_stop ) ;
gst_adaptive_demux_test_seek ( DEMUX_ELEMENT_NAME ,
2016-02-16 14:24:26 +00:00
" http://unit.test/test.mpd " , GST_ADAPTIVE_DEMUX_TEST_CASE ( testData ) ) ;
2016-02-16 14:24:09 +00:00
2016-02-16 13:55:54 +00:00
g_object_unref ( testData ) ;
2016-02-16 14:24:09 +00:00
if ( http_src_test_data . data )
gst_structure_free ( http_src_test_data . data ) ;
2016-01-05 20:41:23 +00:00
}
GST_START_TEST ( testSeekKeyUnitPosition )
{
/* Seek to 1.5s with key unit, it should go back to 1.0s. 3 segments will be
* pushed */
2016-01-27 02:15:10 +00:00
run_seek_position_test ( 1.0 , GST_SEEK_TYPE_SET , 1500 * GST_MSECOND ,
GST_SEEK_TYPE_NONE , 0 , GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_KEY_UNIT ,
2016-02-26 21:17:37 +00:00
1000 * GST_MSECOND , - 1 , 3 , 0 ) ;
2016-01-27 02:15:10 +00:00
}
GST_END_TEST ;
GST_START_TEST ( testSeekUpdateStopPosition )
{
run_seek_position_test ( 1.0 , GST_SEEK_TYPE_NONE , 1500 * GST_MSECOND ,
2016-02-26 21:17:37 +00:00
GST_SEEK_TYPE_SET , 3000 * GST_MSECOND , 0 , 0 , 3000 * GST_MSECOND , 3 , 0 ) ;
2016-01-05 20:41:23 +00:00
}
GST_END_TEST ;
GST_START_TEST ( testSeekPosition )
{
/* Seek to 1.5s without key unit, it should keep the 1.5s, but still push
* from the 1 st segment , so 3 segments will be
* pushed */
2016-01-27 02:15:10 +00:00
run_seek_position_test ( 1.0 , GST_SEEK_TYPE_SET , 1500 * GST_MSECOND ,
2016-02-26 21:17:37 +00:00
GST_SEEK_TYPE_NONE , 0 , GST_SEEK_FLAG_FLUSH , 1500 * GST_MSECOND , - 1 , 3 , 0 ) ;
2016-01-05 20:41:23 +00:00
}
GST_END_TEST ;
2016-01-27 13:48:53 +00:00
GST_START_TEST ( testSeekSnapBeforePosition )
{
/* Seek to 1.5s, snap before, it go to 1s */
run_seek_position_test ( 1.0 , GST_SEEK_TYPE_SET , 1500 * GST_MSECOND ,
GST_SEEK_TYPE_NONE , 0 , GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_SNAP_BEFORE ,
2016-02-26 21:17:37 +00:00
1000 * GST_MSECOND , - 1 , 3 , 0 ) ;
2016-01-27 13:48:53 +00:00
}
GST_END_TEST ;
GST_START_TEST ( testSeekSnapAfterPosition )
{
/* Seek to 1.5s with snap after, it should move to 2s */
run_seek_position_test ( 1.0 , GST_SEEK_TYPE_SET , 1500 * GST_MSECOND ,
GST_SEEK_TYPE_NONE , 0 , GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_SNAP_AFTER ,
2016-02-26 21:17:37 +00:00
2000 * GST_MSECOND , - 1 , 2 , 0 ) ;
}
GST_END_TEST ;
GST_START_TEST ( testSeekSnapBeforeSamePosition )
{
/* Snap seek without position */
run_seek_position_test ( 1.0 , GST_SEEK_TYPE_NONE , GST_CLOCK_TIME_NONE ,
GST_SEEK_TYPE_NONE , 0 , GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_SNAP_BEFORE ,
2 * GST_MSECOND , - 1 , 2 , SEGMENT_SIZE * 3 + 1 ) ;
}
GST_END_TEST ;
GST_START_TEST ( testSeekSnapAfterSamePosition )
{
/* Snap seek without position */
run_seek_position_test ( 1.0 , GST_SEEK_TYPE_NONE , GST_CLOCK_TIME_NONE ,
GST_SEEK_TYPE_NONE , 0 , GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_SNAP_AFTER ,
3 * GST_MSECOND , - 1 , 1 , SEGMENT_SIZE * 3 + 1 ) ;
2016-01-27 13:48:53 +00:00
}
GST_END_TEST ;
2016-02-26 21:17:37 +00:00
2016-01-27 13:48:53 +00:00
GST_START_TEST ( testReverseSeekSnapBeforePosition )
{
run_seek_position_test ( - 1.0 , GST_SEEK_TYPE_SET , 1000 * GST_MSECOND ,
GST_SEEK_TYPE_SET , 2500 * GST_MSECOND ,
GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_SNAP_BEFORE , 1000 * GST_MSECOND ,
2016-02-26 21:17:37 +00:00
3000 * GST_MSECOND , 2 , 0 ) ;
2016-01-27 13:48:53 +00:00
}
GST_END_TEST ;
GST_START_TEST ( testReverseSeekSnapAfterPosition )
{
run_seek_position_test ( - 1.0 , GST_SEEK_TYPE_SET , 1000 * GST_MSECOND ,
GST_SEEK_TYPE_SET , 2500 * GST_MSECOND ,
GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_SNAP_AFTER , 1000 * GST_MSECOND ,
2016-02-26 21:17:37 +00:00
2000 * GST_MSECOND , 1 , 0 ) ;
2016-01-27 13:48:53 +00:00
}
GST_END_TEST ;
2015-11-10 13:13:35 +00:00
static void
testDownloadErrorMessageCallback ( GstAdaptiveDemuxTestEngine * engine ,
GstMessage * msg , gpointer user_data )
2015-10-20 16:21:00 +00:00
{
2015-11-10 13:13:35 +00:00
GError * err = NULL ;
gchar * dbg_info = NULL ;
2015-10-20 16:21:00 +00:00
2015-11-10 13:13:35 +00:00
fail_unless ( GST_MESSAGE_TYPE ( msg ) = = GST_MESSAGE_ERROR ) ;
gst_message_parse_error ( msg , & err , & dbg_info ) ;
GST_DEBUG ( " Error from element %s : %s \n " ,
GST_OBJECT_NAME ( msg - > src ) , err - > message ) ;
fail_unless_equals_string ( GST_OBJECT_NAME ( msg - > src ) , DEMUX_ELEMENT_NAME ) ;
g_error_free ( err ) ;
g_free ( dbg_info ) ;
g_main_loop_quit ( engine - > loop ) ;
2015-10-20 16:21:00 +00:00
}
/*
2015-11-10 13:13:35 +00:00
* Test error case of failing to download a segment
2015-10-20 16:21:00 +00:00
*/
2015-11-10 13:13:35 +00:00
GST_START_TEST ( testDownloadError )
2015-10-20 16:21:00 +00:00
{
const gchar * mpd =
" <?xml version= \" 1.0 \" encoding= \" utf-8 \" ?> "
" <MPD xmlns:xsi= \" http://www.w3.org/2001/XMLSchema-instance \" "
" xmlns= \" urn:mpeg:DASH:schema:MPD:2011 \" "
" xsi:schemaLocation= \" urn:mpeg:DASH:schema:MPD:2011 DASH-MPD.xsd \" "
" profiles= \" urn:mpeg:dash:profile:isoff-on-demand:2011 \" "
" type= \" static \" "
" minBufferTime= \" PT1.500S \" "
" mediaPresentationDuration= \" PT0.5S \" > "
" <Period> "
" <AdaptationSet mimeType= \" audio/webm \" "
" subsegmentAlignment= \" true \" > "
" <Representation id= \" 171 \" "
" codecs= \" vorbis \" "
" audioSamplingRate= \" 44100 \" "
" startWithSAP= \" 1 \" "
" bandwidth= \" 129553 \" > "
" <AudioChannelConfiguration "
" schemeIdUri= \" urn:mpeg:dash:23003:3:audio_channel_configuration:2011 \" "
" value= \" 2 \" /> "
2015-11-10 13:13:35 +00:00
" <BaseURL>audio_file_not_available.webm</BaseURL> "
2015-10-20 16:21:00 +00:00
" <SegmentBase indexRange= \" 4452-4686 \" "
" indexRangeExact= \" true \" > "
" <Initialization range= \" 0-4451 \" /> "
" </SegmentBase> "
" </Representation></AdaptationSet></Period></MPD> " ;
2015-11-10 13:13:35 +00:00
GstDashDemuxTestInputData inputTestData [ ] = {
{ " http://unit.test/test.mpd " , ( guint8 * ) mpd , 0 } ,
2015-10-20 16:21:00 +00:00
{ NULL , NULL , 0 } ,
} ;
2015-11-10 13:13:35 +00:00
GstAdaptiveDemuxTestExpectedOutput outputTestData [ ] = {
{ " audio_00 " , 0 , NULL } ,
2015-10-20 16:21:00 +00:00
} ;
2016-02-16 14:24:09 +00:00
GstTestHTTPSrcCallbacks http_src_callbacks = { 0 } ;
GstTestHTTPSrcTestData http_src_test_data = { 0 } ;
2015-11-10 13:13:35 +00:00
GstAdaptiveDemuxTestCallbacks test_callbacks = { 0 } ;
2016-02-16 14:24:26 +00:00
GstDashDemuxTestCase * testData ;
2015-10-20 16:21:00 +00:00
2015-11-10 13:13:35 +00:00
http_src_callbacks . src_start = gst_dashdemux_http_src_start ;
http_src_callbacks . src_create = gst_dashdemux_http_src_create ;
2016-02-16 14:24:09 +00:00
http_src_test_data . input = inputTestData ;
gst_test_http_src_install_callbacks ( & http_src_callbacks ,
& http_src_test_data ) ;
2015-11-10 13:13:35 +00:00
test_callbacks . appsink_received_data =
gst_adaptive_demux_test_check_received_data ;
test_callbacks . bus_error_message = testDownloadErrorMessageCallback ;
2016-02-16 14:25:32 +00:00
test_callbacks . appsink_eos = gst_adaptive_demux_test_unexpected_eos ;
2015-10-20 16:21:00 +00:00
2016-02-16 14:24:26 +00:00
testData = gst_dash_demux_test_case_new ( ) ;
2016-02-16 14:24:09 +00:00
COPY_OUTPUT_TEST_DATA ( outputTestData , testData ) ;
2015-11-10 13:13:35 +00:00
gst_adaptive_demux_test_run ( DEMUX_ELEMENT_NAME , " http://unit.test/test.mpd " ,
& test_callbacks , testData ) ;
2016-02-16 14:24:09 +00:00
2016-02-16 13:55:54 +00:00
g_object_unref ( testData ) ;
2016-02-16 14:24:09 +00:00
if ( http_src_test_data . data )
gst_structure_free ( http_src_test_data . data ) ;
2015-10-20 16:21:00 +00:00
}
GST_END_TEST ;
2016-02-16 14:24:49 +00:00
static GstFlowReturn
test_fragment_download_error_src_create ( GstTestHTTPSrc * src ,
guint64 offset ,
guint length , GstBuffer * * retbuf , gpointer context , gpointer user_data )
2015-10-16 15:20:34 +00:00
{
2016-02-16 14:24:49 +00:00
const GstDashDemuxTestInputData * input =
( const GstDashDemuxTestInputData * ) context ;
const GstTestHTTPSrcTestData * http_src_test_data =
( const GstTestHTTPSrcTestData * ) user_data ;
guint64 threshold_for_trigger ;
2015-10-16 15:20:34 +00:00
2016-02-16 14:24:49 +00:00
fail_unless ( input ! = NULL ) ;
gst_structure_get_uint64 ( http_src_test_data - > data , " threshold_for_trigger " ,
& threshold_for_trigger ) ;
2015-10-16 15:20:34 +00:00
2016-02-16 14:25:32 +00:00
if ( ! g_str_has_suffix ( input - > uri , " .mpd " ) & & offset > = threshold_for_trigger ) {
2016-02-16 14:24:49 +00:00
GST_DEBUG ( " network_error %s % " G_GUINT64_FORMAT " @ % " G_GUINT64_FORMAT ,
input - > uri , offset , threshold_for_trigger ) ;
GST_ELEMENT_ERROR ( src , RESOURCE , READ ,
( ( " A network error occurred, or the server closed the connection unexpectedly. " ) ) , ( " A network error occurred, or the server closed the connection unexpectedly. " ) ) ;
return GST_FLOW_ERROR ;
}
return gst_dashdemux_http_src_create ( src , offset , length , retbuf , context ,
user_data ) ;
}
2015-10-16 15:20:34 +00:00
2016-02-16 14:25:45 +00:00
/*
* Test header download error
* Let the adaptive demux download a few bytes , then instruct the
* GstTestHTTPSrc element to generate an error while the fragment header
* is still being downloaded .
*/
GST_START_TEST ( testHeaderDownloadError )
{
const gchar * mpd =
" <?xml version= \" 1.0 \" encoding= \" utf-8 \" ?> "
" <MPD xmlns:xsi= \" http://www.w3.org/2001/XMLSchema-instance \" "
" xmlns= \" urn:mpeg:DASH:schema:MPD:2011 \" "
" xsi:schemaLocation= \" urn:mpeg:DASH:schema:MPD:2011 DASH-MPD.xsd \" "
" profiles= \" urn:mpeg:dash:profile:isoff-on-demand:2011 \" "
" type= \" static \" "
" minBufferTime= \" PT1.500S \" "
" mediaPresentationDuration= \" PT0.5S \" > "
" <Period> "
" <AdaptationSet mimeType= \" audio/webm \" "
" subsegmentAlignment= \" true \" > "
" <Representation id= \" 171 \" "
" codecs= \" vorbis \" "
" audioSamplingRate= \" 44100 \" "
" startWithSAP= \" 1 \" "
" bandwidth= \" 129553 \" > "
" <AudioChannelConfiguration "
" schemeIdUri= \" urn:mpeg:dash:23003:3:audio_channel_configuration:2011 \" "
" value= \" 2 \" /> "
" <BaseURL>audio.webm</BaseURL> "
" <SegmentBase indexRange= \" 4452-4686 \" "
" indexRangeExact= \" true \" > "
" <Initialization range= \" 0-4451 \" /> "
" </SegmentBase> "
" </Representation></AdaptationSet></Period></MPD> " ;
/* generate error while the headers are still being downloaded
* threshold_for_trigger must be less than the size of headers
* ( initialization + index ) which is 4687.
*/
guint64 threshold_for_trigger = 2000 ;
GstDashDemuxTestInputData inputTestData [ ] = {
{ " http://unit.test/test.mpd " , ( guint8 * ) mpd , 0 } ,
{ " http://unit.test/audio.webm " , NULL , 5000 } ,
{ NULL , NULL , 0 } ,
} ;
GstAdaptiveDemuxTestExpectedOutput outputTestData [ ] = {
/* adaptive demux tries for 4 times (MAX_DOWNLOAD_ERROR_COUNT + 1) before giving up */
{ " audio_00 " , threshold_for_trigger * 4 , NULL } ,
} ;
GstTestHTTPSrcCallbacks http_src_callbacks = { 0 } ;
GstTestHTTPSrcTestData http_src_test_data = { 0 } ;
GstAdaptiveDemuxTestCallbacks test_callbacks = { 0 } ;
GstDashDemuxTestCase * testData ;
http_src_callbacks . src_start = gst_dashdemux_http_src_start ;
http_src_callbacks . src_create = test_fragment_download_error_src_create ;
http_src_test_data . data = gst_structure_new_empty ( __FUNCTION__ ) ;
gst_structure_set ( http_src_test_data . data , " threshold_for_trigger " ,
G_TYPE_UINT64 , threshold_for_trigger , NULL ) ;
http_src_test_data . input = inputTestData ;
gst_test_http_src_install_callbacks ( & http_src_callbacks ,
& http_src_test_data ) ;
test_callbacks . appsink_received_data =
gst_adaptive_demux_test_check_received_data ;
test_callbacks . appsink_eos = gst_adaptive_demux_test_unexpected_eos ;
test_callbacks . bus_error_message = testDownloadErrorMessageCallback ;
testData = gst_dash_demux_test_case_new ( ) ;
COPY_OUTPUT_TEST_DATA ( outputTestData , testData ) ;
/* download in chunks of threshold_for_trigger size.
* This means the first chunk will succeed , the second will generate
* error because we already exceeded threshold_for_trigger bytes .
*/
gst_test_http_src_set_default_blocksize ( threshold_for_trigger ) ;
gst_adaptive_demux_test_run ( DEMUX_ELEMENT_NAME ,
" http://unit.test/test.mpd " , & test_callbacks , testData ) ;
g_object_unref ( testData ) ;
if ( http_src_test_data . data )
gst_structure_free ( http_src_test_data . data ) ;
}
GST_END_TEST ;
2015-10-16 15:20:34 +00:00
/*
2016-02-16 14:25:32 +00:00
* Test media download error on the last media fragment .
2016-02-16 14:24:49 +00:00
* Let the adaptive demux download a few bytes , then instruct the
2016-02-16 14:25:32 +00:00
* GstTestHTTPSrc element to generate an error while the last media fragment
* is being downloaded .
* Adaptive demux will not retry downloading the last media fragment . It will
* be considered eos .
2015-10-16 15:20:34 +00:00
*/
2016-02-16 14:25:32 +00:00
GST_START_TEST ( testMediaDownloadErrorLastFragment )
2015-10-16 15:20:34 +00:00
{
const gchar * mpd =
" <?xml version= \" 1.0 \" encoding= \" utf-8 \" ?> "
" <MPD xmlns:xsi= \" http://www.w3.org/2001/XMLSchema-instance \" "
" xmlns= \" urn:mpeg:DASH:schema:MPD:2011 \" "
" xsi:schemaLocation= \" urn:mpeg:DASH:schema:MPD:2011 DASH-MPD.xsd \" "
" profiles= \" urn:mpeg:dash:profile:isoff-on-demand:2011 \" "
" type= \" static \" "
" minBufferTime= \" PT1.500S \" "
2016-02-16 14:24:49 +00:00
" mediaPresentationDuration= \" PT0.5S \" > "
2015-10-16 15:20:34 +00:00
" <Period> "
" <AdaptationSet mimeType= \" audio/webm \" "
" subsegmentAlignment= \" true \" > "
" <Representation id= \" 171 \" "
" codecs= \" vorbis \" "
" audioSamplingRate= \" 44100 \" "
" startWithSAP= \" 1 \" "
" bandwidth= \" 129553 \" > "
" <AudioChannelConfiguration "
" schemeIdUri= \" urn:mpeg:dash:23003:3:audio_channel_configuration:2011 \" "
" value= \" 2 \" /> "
" <BaseURL>audio.webm</BaseURL> "
" <SegmentBase indexRange= \" 4452-4686 \" "
" indexRangeExact= \" true \" > "
" <Initialization range= \" 0-4451 \" /> "
" </SegmentBase> "
" </Representation></AdaptationSet></Period></MPD> " ;
2016-02-16 14:24:09 +00:00
2016-02-16 14:25:32 +00:00
/* generate error on the first media fragment */
guint64 threshold_for_trigger = 4687 ;
2015-11-10 13:13:35 +00:00
GstDashDemuxTestInputData inputTestData [ ] = {
{ " http://unit.test/test.mpd " , ( guint8 * ) mpd , 0 } ,
2015-10-16 15:20:34 +00:00
{ " http://unit.test/audio.webm " , NULL , 5000 } ,
{ NULL , NULL , 0 } ,
} ;
2015-11-10 13:13:35 +00:00
GstAdaptiveDemuxTestExpectedOutput outputTestData [ ] = {
2016-02-16 14:25:32 +00:00
/* adaptive demux will not retry because this is the last fragment */
{ " audio_00 " , threshold_for_trigger , NULL } ,
2015-11-10 13:13:35 +00:00
} ;
2016-02-16 14:24:09 +00:00
GstTestHTTPSrcCallbacks http_src_callbacks = { 0 } ;
GstTestHTTPSrcTestData http_src_test_data = { 0 } ;
2015-11-10 13:13:35 +00:00
GstAdaptiveDemuxTestCallbacks test_callbacks = { 0 } ;
2016-02-16 14:24:26 +00:00
GstDashDemuxTestCase * testData ;
2015-10-16 15:20:34 +00:00
2015-11-10 13:13:35 +00:00
http_src_callbacks . src_start = gst_dashdemux_http_src_start ;
2016-02-16 14:24:49 +00:00
http_src_callbacks . src_create = test_fragment_download_error_src_create ;
http_src_test_data . data = gst_structure_new_empty ( __FUNCTION__ ) ;
gst_structure_set ( http_src_test_data . data , " threshold_for_trigger " ,
G_TYPE_UINT64 , threshold_for_trigger , NULL ) ;
2016-02-16 14:24:09 +00:00
http_src_test_data . input = inputTestData ;
gst_test_http_src_install_callbacks ( & http_src_callbacks ,
& http_src_test_data ) ;
2016-02-16 14:24:49 +00:00
test_callbacks . appsink_received_data =
gst_adaptive_demux_test_check_received_data ;
2016-02-16 14:25:32 +00:00
test_callbacks . appsink_eos =
gst_adaptive_demux_test_check_size_of_received_data ;
2015-11-10 13:13:35 +00:00
2016-02-16 14:24:26 +00:00
testData = gst_dash_demux_test_case_new ( ) ;
2016-02-16 14:24:09 +00:00
COPY_OUTPUT_TEST_DATA ( outputTestData , testData ) ;
2015-11-10 13:13:35 +00:00
gst_adaptive_demux_test_run ( DEMUX_ELEMENT_NAME ,
" http://unit.test/test.mpd " , & test_callbacks , testData ) ;
2016-02-16 14:24:09 +00:00
2016-02-16 13:55:54 +00:00
g_object_unref ( testData ) ;
2016-02-16 14:24:09 +00:00
if ( http_src_test_data . data )
gst_structure_free ( http_src_test_data . data ) ;
2015-11-10 13:13:35 +00:00
}
GST_END_TEST ;
2016-02-16 14:26:05 +00:00
/*
* Test media download error on a media fragment which is not the last one .
* Let the adaptive demux download a few bytes , then instruct the
* GstTestHTTPSrc element to generate an error while a media fragment
* is being downloaded .
*/
GST_START_TEST ( testMediaDownloadErrorMiddleFragment )
{
const gchar * mpd =
" <?xml version= \" 1.0 \" encoding= \" utf-8 \" ?> "
" <MPD xmlns:xsi= \" http://www.w3.org/2001/XMLSchema-instance \" "
" xmlns= \" urn:mpeg:DASH:schema:MPD:2011 \" "
" xsi:schemaLocation= \" urn:mpeg:DASH:schema:MPD:2011 DASH-MPD.xsd \" "
" profiles= \" urn:mpeg:dash:profile:isoff-on-demand:2011 \" "
" type= \" static \" "
" minBufferTime= \" PT1.500S \" "
" mediaPresentationDuration= \" PT10S \" > "
" <Period> "
" <AdaptationSet mimeType= \" audio/webm \" "
" subsegmentAlignment= \" true \" > "
" <Representation id= \" 171 \" "
" codecs= \" vorbis \" "
" audioSamplingRate= \" 44100 \" "
" startWithSAP= \" 1 \" "
" bandwidth= \" 129553 \" > "
" <AudioChannelConfiguration "
" schemeIdUri= \" urn:mpeg:dash:23003:3:audio_channel_configuration:2011 \" "
" value= \" 2 \" /> "
" <BaseURL>audio.webm</BaseURL> "
" <SegmentList duration= \" 1 \" > "
" <SegmentURL indexRange= \" 1-10 \" "
" mediaRange= \" 11-30 \" > "
" </SegmentURL> "
" <SegmentURL indexRange= \" 31-60 \" "
" mediaRange= \" 61-100 \" > "
" </SegmentURL> "
" <SegmentURL indexRange= \" 101-150 \" "
" mediaRange= \" 151-210 \" > "
" </SegmentURL> "
" </SegmentList> "
" </Representation></AdaptationSet></Period></MPD> " ;
/* generate error on the second media fragment */
guint64 threshold_for_trigger = 31 ;
GstDashDemuxTestInputData inputTestData [ ] = {
{ " http://unit.test/test.mpd " , ( guint8 * ) mpd , 0 } ,
{ " http://unit.test/audio.webm " , NULL , 5000 } ,
{ NULL , NULL , 0 } ,
} ;
GstAdaptiveDemuxTestExpectedOutput outputTestData [ ] = {
/* adaptive demux will download only the first media fragment */
{ " audio_00 " , 20 , NULL } ,
} ;
GstTestHTTPSrcCallbacks http_src_callbacks = { 0 } ;
GstTestHTTPSrcTestData http_src_test_data = { 0 } ;
GstAdaptiveDemuxTestCallbacks test_callbacks = { 0 } ;
GstDashDemuxTestCase * testData ;
http_src_callbacks . src_start = gst_dashdemux_http_src_start ;
http_src_callbacks . src_create = test_fragment_download_error_src_create ;
http_src_test_data . data = gst_structure_new_empty ( __FUNCTION__ ) ;
gst_structure_set ( http_src_test_data . data , " threshold_for_trigger " ,
G_TYPE_UINT64 , threshold_for_trigger , NULL ) ;
http_src_test_data . input = inputTestData ;
gst_test_http_src_install_callbacks ( & http_src_callbacks ,
& http_src_test_data ) ;
test_callbacks . appsink_received_data =
gst_adaptive_demux_test_check_received_data ;
test_callbacks . appsink_eos = gst_adaptive_demux_test_unexpected_eos ;
test_callbacks . bus_error_message = testDownloadErrorMessageCallback ;
testData = gst_dash_demux_test_case_new ( ) ;
COPY_OUTPUT_TEST_DATA ( outputTestData , testData ) ;
gst_adaptive_demux_test_run ( DEMUX_ELEMENT_NAME ,
" http://unit.test/test.mpd " , & test_callbacks , testData ) ;
g_object_unref ( testData ) ;
if ( http_src_test_data . data )
gst_structure_free ( http_src_test_data . data ) ;
}
GST_END_TEST ;
2016-02-16 14:24:49 +00:00
/* generate queries to adaptive demux */
static gboolean
testQueryCheckDataReceived ( GstAdaptiveDemuxTestEngine * engine ,
GstAdaptiveDemuxTestOutputStream * stream ,
GstBuffer * buffer , gpointer user_data )
2015-11-10 13:13:35 +00:00
{
2016-02-16 14:24:49 +00:00
GList * pads ;
GstPad * pad ;
GstQuery * query ;
gboolean ret ;
gint64 duration ;
gboolean seekable ;
gint64 segment_start ;
gint64 segment_end ;
2016-02-16 14:25:04 +00:00
gboolean live ;
GstClockTime min_latency ;
GstClockTime max_latency ;
2016-02-16 14:24:49 +00:00
gchar * uri ;
gchar * redirect_uri ;
gboolean redirect_permanent ;
2016-02-16 14:24:09 +00:00
2016-02-16 14:24:49 +00:00
pads = GST_ELEMENT_PADS ( stream - > appsink ) ;
2016-02-16 14:24:09 +00:00
2016-02-16 14:24:49 +00:00
/* AppSink should have only 1 pad */
fail_unless ( pads ! = NULL ) ;
fail_unless ( g_list_length ( pads ) = = 1 ) ;
pad = GST_PAD ( pads - > data ) ;
2015-11-10 13:13:35 +00:00
2016-02-16 14:25:04 +00:00
/* duration query */
2016-02-16 14:24:49 +00:00
query = gst_query_new_duration ( GST_FORMAT_TIME ) ;
ret = gst_pad_peer_query ( pad , query ) ;
fail_unless ( ret = = TRUE ) ;
gst_query_parse_duration ( query , NULL , & duration ) ;
2016-02-16 14:25:04 +00:00
/* mediaPresentationDuration=\"PT135.743S\" */
2016-02-16 14:24:49 +00:00
fail_unless ( duration = = 135743 * GST_MSECOND ) ;
gst_query_unref ( query ) ;
2015-11-10 13:13:35 +00:00
2016-02-16 14:25:04 +00:00
/* seek query */
2016-02-16 14:24:49 +00:00
query = gst_query_new_seeking ( GST_FORMAT_TIME ) ;
ret = gst_pad_peer_query ( pad , query ) ;
fail_unless ( ret = = TRUE ) ;
gst_query_parse_seeking ( query , NULL , & seekable , & segment_start ,
& segment_end ) ;
fail_unless ( seekable = = TRUE ) ;
fail_unless ( segment_start = = 0 ) ;
fail_unless ( segment_end = = duration ) ;
gst_query_unref ( query ) ;
2015-11-10 13:13:35 +00:00
2016-02-16 14:25:04 +00:00
/* latency query */
query = gst_query_new_latency ( ) ;
ret = gst_pad_peer_query ( pad , query ) ;
fail_unless ( ret = = TRUE ) ;
gst_query_parse_latency ( query , & live , & min_latency , & max_latency ) ;
fail_unless ( live = = FALSE ) ;
fail_unless ( min_latency = = 0 ) ;
fail_unless ( max_latency = = - 1 ) ;
gst_query_unref ( query ) ;
/* uri query */
2016-02-16 14:24:49 +00:00
query = gst_query_new_uri ( ) ;
ret = gst_pad_peer_query ( pad , query ) ;
fail_unless ( ret = = TRUE ) ;
gst_query_parse_uri ( query , & uri ) ;
gst_query_parse_uri_redirection ( query , & redirect_uri ) ;
gst_query_parse_uri_redirection_permanent ( query , & redirect_permanent ) ;
2016-02-16 14:25:04 +00:00
fail_unless ( g_strcmp0 ( uri , " http://unit.test/test.mpd " ) = = 0 ) ;
2016-02-16 14:24:49 +00:00
/* adaptive demux does not reply with redirect information */
fail_unless ( redirect_uri = = NULL ) ;
fail_unless ( redirect_permanent = = FALSE ) ;
g_free ( uri ) ;
g_free ( redirect_uri ) ;
gst_query_unref ( query ) ;
2015-11-10 13:13:35 +00:00
2016-02-16 14:24:49 +00:00
return gst_adaptive_demux_test_check_received_data ( engine ,
stream , buffer , user_data ) ;
2015-11-10 13:13:35 +00:00
}
/*
2016-02-16 14:24:49 +00:00
* Test queries
*
2015-11-10 13:13:35 +00:00
*/
2016-02-16 14:24:49 +00:00
GST_START_TEST ( testQuery )
2015-11-10 13:13:35 +00:00
{
const gchar * mpd =
" <?xml version= \" 1.0 \" encoding= \" utf-8 \" ?> "
" <MPD xmlns:xsi= \" http://www.w3.org/2001/XMLSchema-instance \" "
" xmlns= \" urn:mpeg:DASH:schema:MPD:2011 \" "
" xsi:schemaLocation= \" urn:mpeg:DASH:schema:MPD:2011 DASH-MPD.xsd \" "
" profiles= \" urn:mpeg:dash:profile:isoff-on-demand:2011 \" "
" type= \" static \" "
" minBufferTime= \" PT1.500S \" "
2016-02-16 14:24:49 +00:00
" mediaPresentationDuration= \" PT135.743S \" > "
2015-11-10 13:13:35 +00:00
" <Period> "
" <AdaptationSet mimeType= \" audio/webm \" "
" subsegmentAlignment= \" true \" > "
" <Representation id= \" 171 \" "
" codecs= \" vorbis \" "
" audioSamplingRate= \" 44100 \" "
" startWithSAP= \" 1 \" "
" bandwidth= \" 129553 \" > "
" <AudioChannelConfiguration "
" schemeIdUri= \" urn:mpeg:dash:23003:3:audio_channel_configuration:2011 \" "
" value= \" 2 \" /> "
" <BaseURL>audio.webm</BaseURL> "
" <SegmentBase indexRange= \" 4452-4686 \" "
" indexRangeExact= \" true \" > "
" <Initialization range= \" 0-4451 \" /> "
" </SegmentBase> "
" </Representation></AdaptationSet></Period></MPD> " ;
GstDashDemuxTestInputData inputTestData [ ] = {
{ " http://unit.test/test.mpd " , ( guint8 * ) mpd , 0 } ,
{ " http://unit.test/audio.webm " , NULL , 5000 } ,
{ NULL , NULL , 0 } ,
} ;
GstAdaptiveDemuxTestExpectedOutput outputTestData [ ] = {
2015-10-16 15:20:34 +00:00
{ " audio_00 " , 5000 , NULL } ,
} ;
2016-02-16 14:24:09 +00:00
GstTestHTTPSrcCallbacks http_src_callbacks = { 0 } ;
GstTestHTTPSrcTestData http_src_test_data = { 0 } ;
2015-11-10 13:13:35 +00:00
GstAdaptiveDemuxTestCallbacks test_callbacks = { 0 } ;
2016-02-16 14:24:26 +00:00
GstDashDemuxTestCase * testData ;
2015-11-10 13:13:35 +00:00
http_src_callbacks . src_start = gst_dashdemux_http_src_start ;
2016-02-16 14:24:49 +00:00
http_src_callbacks . src_create = gst_dashdemux_http_src_create ;
2016-02-16 14:24:09 +00:00
http_src_test_data . input = inputTestData ;
gst_test_http_src_install_callbacks ( & http_src_callbacks ,
& http_src_test_data ) ;
2016-02-16 14:24:49 +00:00
test_callbacks . appsink_received_data = testQueryCheckDataReceived ;
test_callbacks . appsink_eos =
gst_adaptive_demux_test_check_size_of_received_data ;
2015-10-16 15:20:34 +00:00
2016-02-16 14:24:26 +00:00
testData = gst_dash_demux_test_case_new ( ) ;
2016-02-16 14:24:09 +00:00
COPY_OUTPUT_TEST_DATA ( outputTestData , testData ) ;
2015-11-10 13:13:35 +00:00
gst_adaptive_demux_test_run ( DEMUX_ELEMENT_NAME ,
" http://unit.test/test.mpd " , & test_callbacks , testData ) ;
2016-02-16 14:24:09 +00:00
2016-02-16 13:55:54 +00:00
g_object_unref ( testData ) ;
2016-02-16 14:24:09 +00:00
if ( http_src_test_data . data )
gst_structure_free ( http_src_test_data . data ) ;
2015-10-16 15:20:34 +00:00
}
GST_END_TEST ;
2016-02-16 11:37:44 +00:00
static gboolean
testContentProtectionDashdemuxSendsEvent ( GstAdaptiveDemuxTestEngine * engine ,
GstAdaptiveDemuxTestOutputStream * stream ,
GstEvent * event , gpointer user_data )
{
GstDashDemuxTestCase * test_case = GST_DASH_DEMUX_TEST_CASE ( user_data ) ;
const gchar * system_id ;
GstBuffer * data ;
const gchar * origin ;
GstMapInfo info ;
gchar * value ;
gchar * name ;
guint event_count = 0 ;
GST_DEBUG ( " received event %s " , GST_EVENT_TYPE_NAME ( event ) ) ;
if ( GST_EVENT_TYPE ( event ) ! = GST_EVENT_PROTECTION ) {
return TRUE ;
}
/* we expect content protection events only on video pad */
name = gst_pad_get_name ( stream - > pad ) ;
fail_unless ( g_strcmp0 ( name , " video_00 " ) = = 0 ) ;
gst_event_parse_protection ( event , & system_id , & data , & origin ) ;
gst_buffer_map ( data , & info , GST_MAP_READ ) ;
value = g_malloc ( info . size + 1 ) ;
strncpy ( value , ( gchar * ) info . data , info . size ) ;
value [ info . size ] = 0 ;
gst_buffer_unmap ( data , & info ) ;
if ( g_strcmp0 ( system_id , " 11111111-AAAA-BBBB-CCCC-123456789ABC " ) = = 0 ) {
fail_unless ( g_strcmp0 ( origin , " dash/mpd " ) = = 0 ) ;
fail_unless ( g_strcmp0 ( value , " test value " ) = = 0 ) ;
} else if ( g_strcmp0 ( system_id , " 5e629af5-38da-4063-8977-97ffbd9902d4 " ) = = 0 ) {
const gchar * str ;
fail_unless ( g_strcmp0 ( origin , " dash/mpd " ) = = 0 ) ;
/* We can't do a simple compare of value (which should be an XML dump
of the ContentProtection element ) , because the whitespace
formatting from xmlDump might differ between versions of libxml */
str = strstr ( value , " <ContentProtection " ) ;
fail_if ( str = = NULL ) ;
str = strstr ( value , " <mas:MarlinContentIds> " ) ;
fail_if ( str = = NULL ) ;
str = strstr ( value , " <mas:MarlinContentId> " ) ;
fail_if ( str = = NULL ) ;
str = strstr ( value , " urn:marlin:kid:02020202020202020202020202020202 " ) ;
fail_if ( str = = NULL ) ;
str = strstr ( value , " </ContentProtection> " ) ;
fail_if ( str = = NULL ) ;
2016-11-04 08:56:33 +00:00
} else if ( g_strcmp0 ( system_id , " 9a04f079-9840-4286-ab92-e65be0885f95 " ) = = 0 ) {
fail_unless ( g_strcmp0 ( origin , " dash/mpd " ) = = 0 ) ;
2016-11-14 10:08:24 +00:00
fail_unless ( g_strcmp0 ( value , " dGVzdA== " ) = = 0 ) ;
2016-02-16 11:37:44 +00:00
} else {
fail ( " unexpected content protection event '%s' " , system_id ) ;
}
g_free ( value ) ;
fail_if ( test_case - > countContentProtectionEvents = = NULL ) ;
gst_structure_get_uint ( test_case - > countContentProtectionEvents , name ,
& event_count ) ;
event_count + + ;
gst_structure_set ( test_case - > countContentProtectionEvents , name , G_TYPE_UINT ,
event_count , NULL ) ;
g_free ( name ) ;
return TRUE ;
}
/*
* Test content protection
* Configure 3 content protection sources :
* - a uuid scheme / value pair
* - a non uuid scheme / value pair ( dash recognises only uuid schemes )
* - a complex uuid scheme , with trailing spaces and capital letters in scheme uri
* Only the uuid scheme will be recognised . We expect to receive 2 content
* protection events
*/
GST_START_TEST ( testContentProtection )
{
const gchar * mpd =
" <?xml version= \" 1.0 \" encoding= \" utf-8 \" ?> "
" <MPD xmlns:xsi= \" http://www.w3.org/2001/XMLSchema-instance \" "
" xmlns= \" urn:mpeg:DASH:schema:MPD:2011 \" "
2016-11-04 08:56:33 +00:00
" xmlns:mspr= \" urn:microsoft:playready \" "
2016-02-16 11:37:44 +00:00
" xsi:schemaLocation= \" urn:mpeg:DASH:schema:MPD:2011 DASH-MPD.xsd \" "
" profiles= \" urn:mpeg:dash:profile:isoff-on-demand:2011 \" "
" type= \" static \" "
" minBufferTime= \" PT1.500S \" "
" mediaPresentationDuration= \" PT135.743S \" > "
" <Period> "
" <AdaptationSet mimeType= \" audio/webm \" "
" subsegmentAlignment= \" true \" > "
" <Representation id= \" 171 \" "
" codecs= \" vorbis \" "
" audioSamplingRate= \" 44100 \" "
" startWithSAP= \" 1 \" "
" bandwidth= \" 129553 \" > "
" <AudioChannelConfiguration "
" schemeIdUri= \" urn:mpeg:dash:23003:3:audio_channel_configuration:2011 \" "
" value= \" 2 \" /> "
" <BaseURL>audio.webm</BaseURL> "
" <SegmentBase indexRange= \" 4452-4686 \" "
" indexRangeExact= \" true \" > "
" <Initialization range= \" 0-4451 \" /> "
" </SegmentBase> "
" </Representation> "
" </AdaptationSet> "
" <AdaptationSet mimeType= \" video/webm \" "
" subsegmentAlignment= \" true \" > "
" <ContentProtection schemeIdUri= \" urn:uuid:11111111-AAAA-BBBB-CCCC-123456789ABC \" value= \" test value \" /> "
" <ContentProtection schemeIdUri= \" urn:mpeg:dash:mp4protection:2011 \" value= \" cenc \" /> "
" <ContentProtection schemeIdUri= \" URN:UUID:5e629af5-38da-4063-8977-97ffbd9902d4 \" xmlns:mas= \" urn:marlin:mas:1-0:services:schemas:mpd \" > "
" <mas:MarlinContentIds> "
" <mas:MarlinContentId>urn:marlin:kid:02020202020202020202020202020202</mas:MarlinContentId> "
" </mas:MarlinContentIds> "
" </ContentProtection> "
2016-11-04 08:56:33 +00:00
" <ContentProtection schemeIdUri= \" urn:uuid:9a04f079-9840-4286-ab92-e65be0885f95 \" value= \" MSPR 2.0 \" > "
" <mspr:pro>dGVzdA==</mspr:pro> "
" </ContentProtection> "
2016-02-16 11:37:44 +00:00
" <Representation id= \" 242 \" "
" codecs= \" vp9 \" "
" width= \" 426 \" "
" height= \" 240 \" "
" startWithSAP= \" 1 \" "
" bandwidth= \" 490208 \" > "
" <BaseURL>video.webm</BaseURL> "
" <SegmentBase indexRange= \" 234-682 \" "
" indexRangeExact= \" true \" > "
" <Initialization range= \" 0-233 \" /> "
" </SegmentBase> "
" </Representation></AdaptationSet></Period></MPD> " ;
GstDashDemuxTestInputData inputTestData [ ] = {
{ " http://unit.test/test.mpd " , ( guint8 * ) mpd , 0 } ,
{ " http://unit.test/audio.webm " , NULL , 5000 } ,
{ " http://unit.test/video.webm " , NULL , 9000 } ,
{ NULL , NULL , 0 } ,
} ;
GstAdaptiveDemuxTestExpectedOutput outputTestData [ ] = {
{ " audio_00 " , 5000 , NULL } ,
{ " video_00 " , 9000 , NULL } ,
} ;
GstTestHTTPSrcCallbacks http_src_callbacks = { 0 } ;
GstTestHTTPSrcTestData http_src_test_data = { 0 } ;
GstAdaptiveDemuxTestCallbacks test_callbacks = { 0 } ;
GstDashDemuxTestCase * testData ;
guint event_count = 0 ;
http_src_callbacks . src_start = gst_dashdemux_http_src_start ;
http_src_callbacks . src_create = gst_dashdemux_http_src_create ;
http_src_test_data . input = inputTestData ;
gst_test_http_src_install_callbacks ( & http_src_callbacks ,
& http_src_test_data ) ;
test_callbacks . appsink_received_data =
gst_adaptive_demux_test_check_received_data ;
test_callbacks . appsink_eos =
gst_adaptive_demux_test_check_size_of_received_data ;
test_callbacks . demux_sent_event = testContentProtectionDashdemuxSendsEvent ;
testData = gst_dash_demux_test_case_new ( ) ;
COPY_OUTPUT_TEST_DATA ( outputTestData , testData ) ;
testData - > countContentProtectionEvents =
gst_structure_new_empty ( " countContentProtectionEvents " ) ;
gst_adaptive_demux_test_run ( DEMUX_ELEMENT_NAME , " http://unit.test/test.mpd " ,
& test_callbacks , testData ) ;
fail_unless ( gst_structure_has_field_typed
( testData - > countContentProtectionEvents , " video_00 " , G_TYPE_UINT ) ) ;
gst_structure_get_uint ( testData - > countContentProtectionEvents , " video_00 " ,
& event_count ) ;
2016-11-04 08:56:33 +00:00
fail_unless ( event_count = = 3 ) ;
2016-02-16 11:37:44 +00:00
g_object_unref ( testData ) ;
if ( http_src_test_data . data )
gst_structure_free ( http_src_test_data . data ) ;
}
GST_END_TEST ;
2015-10-09 13:10:52 +00:00
static Suite *
dash_demux_suite ( void )
{
Suite * s = suite_create ( " dash_demux " ) ;
TCase * tc_basicTest = tcase_create ( " basicTest " ) ;
tcase_add_test ( tc_basicTest , simpleTest ) ;
tcase_add_test ( tc_basicTest , testTwoPeriods ) ;
tcase_add_test ( tc_basicTest , testParameters ) ;
tcase_add_test ( tc_basicTest , testSeek ) ;
2016-01-05 20:41:23 +00:00
tcase_add_test ( tc_basicTest , testSeekKeyUnitPosition ) ;
tcase_add_test ( tc_basicTest , testSeekPosition ) ;
2016-01-27 02:15:10 +00:00
tcase_add_test ( tc_basicTest , testSeekUpdateStopPosition ) ;
2016-01-27 13:48:53 +00:00
tcase_add_test ( tc_basicTest , testSeekSnapBeforePosition ) ;
tcase_add_test ( tc_basicTest , testSeekSnapAfterPosition ) ;
2016-02-26 21:17:37 +00:00
tcase_add_test ( tc_basicTest , testSeekSnapBeforeSamePosition ) ;
tcase_add_test ( tc_basicTest , testSeekSnapAfterSamePosition ) ;
2016-01-27 13:48:53 +00:00
tcase_add_test ( tc_basicTest , testReverseSeekSnapBeforePosition ) ;
tcase_add_test ( tc_basicTest , testReverseSeekSnapAfterPosition ) ;
2015-10-16 16:10:11 +00:00
tcase_add_test ( tc_basicTest , testDownloadError ) ;
2016-02-16 14:25:45 +00:00
tcase_add_test ( tc_basicTest , testHeaderDownloadError ) ;
2016-02-16 14:25:32 +00:00
tcase_add_test ( tc_basicTest , testMediaDownloadErrorLastFragment ) ;
2016-02-16 14:26:05 +00:00
tcase_add_test ( tc_basicTest , testMediaDownloadErrorMiddleFragment ) ;
2015-10-16 15:20:34 +00:00
tcase_add_test ( tc_basicTest , testQuery ) ;
2016-02-16 11:37:44 +00:00
tcase_add_test ( tc_basicTest , testContentProtection ) ;
2015-10-09 13:10:52 +00:00
2015-11-10 13:13:35 +00:00
tcase_add_unchecked_fixture ( tc_basicTest , gst_adaptive_demux_test_setup ,
gst_adaptive_demux_test_teardown ) ;
2015-10-09 13:10:52 +00:00
suite_add_tcase ( s , tc_basicTest ) ;
return s ;
}
GST_CHECK_MAIN ( dash_demux ) ;