1 /* A set of utility functions that are common between elements 2 * based upon GstAdaptiveDemux 3 * 4 * Copyright (c) <2015> YouView TV Ltd 5 * 6 * This library is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU Library General Public 8 * License as published by the Free Software Foundation; either 9 * version 2 of the License, or (at your option) any later version. 10 * 11 * This library is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * Library General Public License for more details. 15 * 16 * You should have received a copy of the GNU Library General Public 17 * License along with this library; if not, write to the 18 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, 19 * Boston, MA 02110-1301, USA. 20 */ 21 22 #ifndef __GST_ADAPTIVE_DEMUX_COMMON_TEST_H__ 23 #define __GST_ADAPTIVE_DEMUX_COMMON_TEST_H__ 24 25 #include <gst/gst.h> 26 #include "adaptive_demux_engine.h" 27 28 G_BEGIN_DECLS 29 30 #define GST_TYPE_ADAPTIVE_DEMUX_TEST_CASE \ 31 (gst_adaptive_demux_test_case_get_type()) 32 #define GST_ADAPTIVE_DEMUX_TEST_CASE(obj) \ 33 (G_TYPE_CHECK_INSTANCE_CAST((obj), GST_TYPE_ADAPTIVE_DEMUX_TEST_CASE, GstAdaptiveDemuxTestCase)) 34 #define GST_ADAPTIVE_DEMUX_TEST_CASE_CLASS(klass) \ 35 (G_TYPE_CHECK_CLASS_CAST((klass), GST_TYPE_ADAPTIVE_DEMUX_TEST_CASE, GstAdaptiveDemuxTestCaseClass)) 36 #define GST_ADAPTIVE_DEMUX_TEST_CASE_GET_CLASS(obj) \ 37 (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_ADAPTIVE_DEMUX_TEST_CASE, GstAdaptiveDemuxTestCaseClass)) 38 #define GST_IS_ADAPTIVE_DEMUX_TEST_CASE(obj) \ 39 (G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_TYPE_ADAPTIVE_DEMUX_TEST_CASE)) 40 #define GST_IS_ADAPTIVE_DEMUX_TEST_CASE_CLASS(klass) \ 41 (G_TYPE_CHECK_CLASS_TYPE((klass), GST_TYPE_ADAPTIVE_DEMUX_TEST_CASE)) 42 43 /** 44 * TestTaskState: 45 * The seek test uses a separate task to perform the seek operation. 46 * After starting the task, the caller blocks until the seek task 47 * flushes the AppSink and changes the GstFakeSoupHTTPSrc element state from 48 * PLAYING to PAUSED. 49 * When that event is detected, the caller is allowed to resume. 50 * Any data that will be sent to AppSink after resume will be rejected because 51 * AppSink is in flushing mode. 52 */ 53 typedef enum 54 { 55 TEST_TASK_STATE_NOT_STARTED, 56 TEST_TASK_STATE_WAITING_FOR_TESTSRC_STATE_CHANGE, 57 TEST_TASK_STATE_EXITING, 58 } TestTaskState; 59 60 /** 61 * GstAdaptiveDemuxTestExpectedOutput: 62 * Structure used to store output stream related data. 63 * It is used by the test during output validation. 64 * The fields are set by the testcase function prior 65 * to starting the test. 66 */ 67 typedef struct _GstAdaptiveDemuxTestExpectedOutput 68 { 69 /* the name of the demux src pad generating this stream */ 70 const char *name; 71 /* the expected size on this stream */ 72 guint64 expected_size; 73 /* the expected data on this stream (optional) */ 74 const guint8* expected_data; 75 76 GstSegment post_seek_segment; 77 gboolean segment_verification_needed; 78 } GstAdaptiveDemuxTestExpectedOutput; 79 80 typedef struct _GstAdaptiveDemuxTestCaseClass 81 { 82 GObjectClass parent_class; 83 } GstAdaptiveDemuxTestCaseClass; 84 85 typedef struct _GstAdaptiveDemuxTestCase 86 { 87 GObject parent; 88 89 /* output data used to validate the test 90 * list of GstAdaptiveDemuxTestExpectedOutput, one entry per stream 91 */ 92 GList *output_streams; /*GList<GstAdaptiveDemuxTestExpectedOutput>*/ 93 94 /* the number of streams that finished. 95 * Main thread will stop the pipeline when all streams are finished 96 * (i.e. count_of_finished_streams == g_list_length(output_streams) ) 97 */ 98 guint count_of_finished_streams; 99 100 /* taskTesk... is a set of variables that can be used by a test 101 * that needs to perform operations from another thread 102 * For example, it is used by the seek test to perform the seek 103 * operation 104 */ 105 GstTask *test_task; 106 GRecMutex test_task_lock; 107 TestTaskState test_task_state; 108 GMutex test_task_state_lock; 109 GCond test_task_state_cond; 110 111 /* seek test will wait for this amount of bytes to be sent by 112 * demux to AppSink before triggering a seek request 113 */ 114 guint64 threshold_for_seek; 115 GstEvent *seek_event; 116 gboolean seeked; 117 118 gpointer signal_context; 119 } GstAdaptiveDemuxTestCase; 120 121 /* high-level unit test functions */ 122 123 /** 124 * gst_adaptive_demux_test_setup: 125 * Causes the test HTTP src element to be registered 126 */ 127 void gst_adaptive_demux_test_setup (void); 128 129 void gst_adaptive_demux_test_teardown (void); 130 131 GType gst_adaptive_demux_test_case_get_type (void); 132 133 /** 134 * gst_adaptive_demux_test_case_new: creates new #GstAdaptiveDemuxTestCase 135 * object. Use #g_object_unref to free. 136 */ 137 GstAdaptiveDemuxTestCase * gst_adaptive_demux_test_case_new (void) G_GNUC_MALLOC; 138 139 /** 140 * gst_adaptive_demux_test_seek: test that element supports seeking 141 * @element_name: The name of the demux element (e.g. "dashdemux") 142 * @manifest_uri: The URI of the manifest to load 143 * @testData: The #GstAdaptiveDemuxTestCase that the test expects the 144 * demux element to produce. 145 * 146 * Creates a pipeline and starts it. Once data is flowing, request a 147 * seek to almost the start of the stream. 148 */ 149 void gst_adaptive_demux_test_seek (const gchar * element_name, 150 const gchar * manifest_uri, 151 GstAdaptiveDemuxTestCase *testData); 152 153 /* Utility functions for use within a unit test */ 154 155 /** 156 * gst_adaptive_demux_test_unexpected_eos: 157 * @engine: The #GstAdaptiveDemuxTestEngine that caused this callback 158 * @stream: The #GstAdaptiveDemuxTestOutputStream that caused this callback 159 * @user_data: A pointer to a #GstAdaptiveDemuxTestCase object 160 * 161 * This function can be used as an EOS callback by tests that don't expect 162 * AppSink to receive EOS. 163 */ 164 void 165 gst_adaptive_demux_test_unexpected_eos (GstAdaptiveDemuxTestEngine * 166 engine, GstAdaptiveDemuxTestOutputStream * stream, gpointer user_data); 167 168 /** 169 * gst_adaptive_demux_test_check_size_of_received_data: 170 * @engine: The #GstAdaptiveDemuxTestEngine that caused this callback 171 * @stream: The #GstAdaptiveDemuxTestOutputStream that caused this callback 172 * @user_data: A pointer to a #GstAdaptiveDemuxTestCase object 173 * 174 * This function can be used as an EOS callback to check that the 175 * size of received data equals expected_size. It should be used with 176 * a test that expects the entire file to be downloaded. 177 */ 178 void gst_adaptive_demux_test_check_size_of_received_data( 179 GstAdaptiveDemuxTestEngine *engine, 180 GstAdaptiveDemuxTestOutputStream * stream, gpointer user_data); 181 182 /** 183 * gst_adaptive_demux_test_download_error_size_of_received_data: 184 * @engine: The #GstAdaptiveDemuxTestEngine that caused this callback 185 * @stream: The #GstAdaptiveDemuxTestOutputStream that caused this callback 186 * @user_data: A pointer to a #GstAdaptiveDemuxTestCase object 187 * 188 * This function can be used as an EOS callback to check that the 189 * size of received data is >0 && <expected_size. It should be used with 190 * a test that does not expect the entire file to be downloaded. 191 */ 192 void gst_adaptive_demux_test_download_error_size_of_received_data ( 193 GstAdaptiveDemuxTestEngine *engine, 194 GstAdaptiveDemuxTestOutputStream * stream, gpointer user_data); 195 196 /** 197 * gst_adaptive_demux_test_check_received_data: 198 * @engine: The #GstAdaptiveDemuxTestEngine that caused this callback 199 * @stream: The #GstAdaptiveDemuxTestOutputStream that caused this callback 200 * @buffer: The #GstBuffer containing the data to check 201 * @user_data: A pointer to a #GstAdaptiveDemuxTestCase object 202 * Returns: TRUE if buffer contains the expected data. 203 * 204 * This function can be used as an appSinkGotData callback, to check 205 * that the contents of the received data matches the expected data 206 */ 207 gboolean gst_adaptive_demux_test_check_received_data ( 208 GstAdaptiveDemuxTestEngine *engine, 209 GstAdaptiveDemuxTestOutputStream * stream, 210 GstBuffer * buffer, 211 gpointer user_data); 212 213 /** 214 * gst_adaptive_demux_test_find_test_data_by_stream: 215 * @testData: The #GstAdaptiveDemuxTestCase object that contains the 216 * output_streams list to search 217 * @stream: the #GstAdaptiveDemuxTestOutputStream to search for 218 * @index: (out) (allow none) the index of the entry in output_streams 219 * Returns: The #GstAdaptiveDemuxTestExpectedOutput that matches @stream, or 220 * %NULL if not found 221 * 222 * Search the list of output test data for the entry that matches stream. 223 */ 224 GstAdaptiveDemuxTestExpectedOutput * gst_adaptive_demux_test_find_test_data_by_stream ( 225 GstAdaptiveDemuxTestCase * testData, 226 GstAdaptiveDemuxTestOutputStream * stream, 227 guint * index); 228 229 G_END_DECLS 230 #endif /* __GST_ADAPTIVE_DEMUX_COMMON_TEST_H__ */ 231