1 /* GStreamer
2 *
3 * unit test for mxfdemux
4 *
5 * Copyright (C) <2008> Sebastian Dröge <sebastian.droege@collabora.co.uk>
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Library General Public License for more details.
16 *
17 * You should have received a copy of the GNU Library General Public
18 * License along with this library; if not, write to the
19 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
20 * Boston, MA 02110-1301, USA.
21 */
22
23 #include <gst/check/gstcheck.h>
24 #include <string.h>
25 #include "mxfdemux.h"
26
27 static GstPad *mysrcpad, *mysinkpad;
28 static GMainLoop *loop = NULL;
29 static gboolean have_eos = FALSE;
30 static gboolean have_data = FALSE;
31
32 static GstStaticPadTemplate mysrctemplate =
33 GST_STATIC_PAD_TEMPLATE ("src", GST_PAD_SRC, GST_PAD_ALWAYS,
34 GST_STATIC_CAPS ("application/mxf"));
35
36 static GstStaticPadTemplate mysinktemplate =
37 GST_STATIC_PAD_TEMPLATE ("sink", GST_PAD_SINK, GST_PAD_ALWAYS,
38 GST_STATIC_CAPS_ANY);
39
40 static void
_pad_added(GstElement * element,GstPad * pad,gpointer user_data)41 _pad_added (GstElement * element, GstPad * pad, gpointer user_data)
42 {
43 gchar *name = gst_pad_get_name (pad);
44
45 fail_unless_equals_string (name, "track_2");
46 fail_unless (gst_pad_link (pad, mysinkpad) == GST_PAD_LINK_OK);
47
48 g_free (name);
49 }
50
51 static void
_sink_check_caps(GstPad * pad,GstCaps * caps)52 _sink_check_caps (GstPad * pad, GstCaps * caps)
53 {
54 GstCaps *tcaps = gst_caps_new_simple ("audio/x-raw",
55 "rate", G_TYPE_INT, 11025,
56 "channels", G_TYPE_INT, 1,
57 "format", G_TYPE_STRING, "U8",
58 "layout", G_TYPE_STRING, "interleaved",
59 NULL);
60
61 fail_unless (gst_caps_is_always_compatible (caps, tcaps));
62 gst_caps_unref (tcaps);
63 }
64
65 static GstFlowReturn
_sink_chain(GstPad * pad,GstObject * parent,GstBuffer * buffer)66 _sink_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer)
67 {
68 fail_unless_equals_int (gst_buffer_get_size (buffer), sizeof (mxf_essence));
69 fail_unless (gst_buffer_memcmp (buffer, 0, mxf_essence,
70 sizeof (mxf_essence)) == 0);
71
72 fail_unless (GST_BUFFER_TIMESTAMP (buffer) == 0);
73 fail_unless (GST_BUFFER_DURATION (buffer) == 200 * GST_MSECOND);
74
75 gst_buffer_unref (buffer);
76
77 have_data = TRUE;
78 return GST_FLOW_OK;
79 }
80
81 static gboolean
_sink_event(GstPad * pad,GstObject * parent,GstEvent * event)82 _sink_event (GstPad * pad, GstObject * parent, GstEvent * event)
83 {
84 GST_INFO_OBJECT (pad, "got %s event %p: %" GST_PTR_FORMAT,
85 GST_EVENT_TYPE_NAME (event), event, event);
86
87 switch (GST_EVENT_TYPE (event)) {
88 case GST_EVENT_EOS:
89 if (loop) {
90 while (!g_main_loop_is_running (loop));
91 }
92
93 have_eos = TRUE;
94 if (loop)
95 g_main_loop_quit (loop);
96 break;
97 case GST_EVENT_CAPS:
98 {
99 GstCaps *caps;
100
101 gst_event_parse_caps (event, &caps);
102 _sink_check_caps (pad, caps);
103 break;
104 }
105 default:
106 break;
107 }
108
109 gst_event_unref (event);
110
111 return TRUE;
112 }
113
114 static GstPad *
_create_sink_pad(void)115 _create_sink_pad (void)
116 {
117 mysinkpad = gst_pad_new_from_static_template (&mysinktemplate, "sink");
118
119 gst_pad_set_chain_function (mysinkpad, _sink_chain);
120 gst_pad_set_event_function (mysinkpad, _sink_event);
121
122 return mysinkpad;
123 }
124
125 static GstPad *
_create_src_pad_push(void)126 _create_src_pad_push (void)
127 {
128 mysrcpad = gst_pad_new_from_static_template (&mysrctemplate, "src");
129
130 return mysrcpad;
131 }
132
133 static GstFlowReturn
_src_getrange(GstPad * pad,GstObject * parent,guint64 offset,guint length,GstBuffer ** buffer)134 _src_getrange (GstPad * pad, GstObject * parent, guint64 offset, guint length,
135 GstBuffer ** buffer)
136 {
137 if (offset + length > sizeof (mxf_file))
138 return GST_FLOW_EOS;
139
140 *buffer = gst_buffer_new_wrapped_full (GST_MEMORY_FLAG_READONLY,
141 (guint8 *) (mxf_file + offset), length, 0, length, NULL, NULL);
142
143 return GST_FLOW_OK;
144 }
145
146 static gboolean
_src_query(GstPad * pad,GstObject * parent,GstQuery * query)147 _src_query (GstPad * pad, GstObject * parent, GstQuery * query)
148 {
149 gboolean res = FALSE;
150
151 switch (GST_QUERY_TYPE (query)) {
152 case GST_QUERY_DURATION:{
153 GstFormat fmt;
154
155 gst_query_parse_duration (query, &fmt, NULL);
156 if (fmt != GST_FORMAT_BYTES)
157 break;
158
159 gst_query_set_duration (query, fmt, sizeof (mxf_file));
160 res = TRUE;
161 break;
162 }
163 case GST_QUERY_SCHEDULING:{
164 gst_query_set_scheduling (query, GST_SCHEDULING_FLAG_SEEKABLE, 1, -1, 0);
165 gst_query_add_scheduling_mode (query, GST_PAD_MODE_PULL);
166 res = TRUE;
167 break;
168 }
169 default:
170 GST_DEBUG_OBJECT (pad, "unhandled %s query", GST_QUERY_TYPE_NAME (query));
171 break;
172 }
173
174 return res;
175 }
176
177 static GstPad *
_create_src_pad_pull(void)178 _create_src_pad_pull (void)
179 {
180 mysrcpad = gst_pad_new_from_static_template (&mysrctemplate, "src");
181 gst_pad_set_getrange_function (mysrcpad, _src_getrange);
182 gst_pad_set_query_function (mysrcpad, _src_query);
183
184 return mysrcpad;
185 }
186
GST_START_TEST(test_pull)187 GST_START_TEST (test_pull)
188 {
189 GstStateChangeReturn sret;
190 GstElement *mxfdemux;
191 GstPad *sinkpad;
192
193 have_eos = FALSE;
194 have_data = FALSE;
195 loop = g_main_loop_new (NULL, FALSE);
196
197 mxfdemux = gst_element_factory_make ("mxfdemux", NULL);
198 fail_unless (mxfdemux != NULL);
199 g_signal_connect (mxfdemux, "pad-added", G_CALLBACK (_pad_added), NULL);
200 sinkpad = gst_element_get_static_pad (mxfdemux, "sink");
201 fail_unless (sinkpad != NULL);
202
203 mysinkpad = _create_sink_pad ();
204 fail_unless (mysinkpad != NULL);
205 mysrcpad = _create_src_pad_pull ();
206 fail_unless (mysrcpad != NULL);
207
208 fail_unless (gst_pad_link (mysrcpad, sinkpad) == GST_PAD_LINK_OK);
209 gst_object_unref (sinkpad);
210
211 gst_pad_set_active (mysinkpad, TRUE);
212 gst_pad_set_active (mysrcpad, TRUE);
213
214 GST_INFO ("Setting to PLAYING");
215 sret = gst_element_set_state (mxfdemux, GST_STATE_PLAYING);
216 fail_unless_equals_int (sret, GST_STATE_CHANGE_SUCCESS);
217
218 g_main_loop_run (loop);
219 fail_unless (have_eos == TRUE);
220 fail_unless (have_data == TRUE);
221
222 gst_element_set_state (mxfdemux, GST_STATE_NULL);
223 gst_pad_set_active (mysinkpad, FALSE);
224 gst_pad_set_active (mysrcpad, FALSE);
225
226 gst_object_unref (mxfdemux);
227 gst_object_unref (mysinkpad);
228 gst_object_unref (mysrcpad);
229 g_main_loop_unref (loop);
230 loop = NULL;
231 }
232
233 GST_END_TEST;
234
GST_START_TEST(test_push)235 GST_START_TEST (test_push)
236 {
237 GstElement *mxfdemux;
238 GstBuffer *buffer;
239 GstPad *sinkpad;
240 GstCaps *caps;
241
242 have_data = FALSE;
243 have_eos = FALSE;
244
245 mxfdemux = gst_element_factory_make ("mxfdemux", NULL);
246 fail_unless (mxfdemux != NULL);
247 g_signal_connect (mxfdemux, "pad-added", G_CALLBACK (_pad_added), NULL);
248 sinkpad = gst_element_get_static_pad (mxfdemux, "sink");
249 fail_unless (sinkpad != NULL);
250
251 buffer =
252 gst_buffer_new_wrapped_full (GST_MEMORY_FLAG_READONLY,
253 (guint8 *) mxf_file, sizeof (mxf_file), 0, sizeof (mxf_file), NULL, NULL);
254 GST_BUFFER_OFFSET (buffer) = 0;
255
256 mysinkpad = _create_sink_pad ();
257 fail_unless (mysinkpad != NULL);
258 mysrcpad = _create_src_pad_push ();
259 fail_unless (mysrcpad != NULL);
260
261 fail_unless (gst_pad_link (mysrcpad, sinkpad) == GST_PAD_LINK_OK);
262 gst_object_unref (sinkpad);
263
264 gst_pad_set_active (mysinkpad, TRUE);
265 gst_pad_set_active (mysrcpad, TRUE);
266
267 caps = gst_caps_new_empty_simple ("application/mxf");
268 gst_check_setup_events (mysrcpad, mxfdemux, caps, GST_FORMAT_BYTES);
269 gst_caps_unref (caps);
270
271 gst_element_set_state (mxfdemux, GST_STATE_PLAYING);
272
273 fail_unless (gst_pad_push (mysrcpad, buffer) == GST_FLOW_OK);
274 fail_unless (gst_pad_push_event (mysrcpad, gst_event_new_eos ()));
275
276 fail_unless (have_eos == TRUE);
277 fail_unless (have_data == TRUE);
278
279 gst_element_set_state (mxfdemux, GST_STATE_NULL);
280 gst_pad_set_active (mysinkpad, FALSE);
281 gst_pad_set_active (mysrcpad, FALSE);
282
283 gst_object_unref (mxfdemux);
284 gst_object_unref (mysinkpad);
285 gst_object_unref (mysrcpad);
286 }
287
288 GST_END_TEST;
289
290 static Suite *
mxfdemux_suite(void)291 mxfdemux_suite (void)
292 {
293 Suite *s = suite_create ("mxfdemux");
294 TCase *tc_chain = tcase_create ("general");
295
296 /* FIXME: remove again once ported */
297 if (!gst_registry_check_feature_version (gst_registry_get (), "mxfdemux", 1,
298 0, 0))
299 return s;
300
301 suite_add_tcase (s, tc_chain);
302 tcase_set_timeout (tc_chain, 180);
303 tcase_add_test (tc_chain, test_pull);
304 tcase_add_test (tc_chain, test_push);
305
306 return s;
307 }
308
309 GST_CHECK_MAIN (mxfdemux);
310