1 /* GStreamer
2 * Copyright (C) 2005 Andy Wingo <wingo@pobox.com>
3 *
4 * simple_launch_lines.c: Unit test for simple pipelines
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
23 #include <gst/check/gstcheck.h>
24
25
26 static GstElement *
setup_pipeline(const gchar * pipe_descr)27 setup_pipeline (const gchar * pipe_descr)
28 {
29 GstElement *pipeline;
30
31 pipeline = gst_parse_launch (pipe_descr, NULL);
32 fail_unless (GST_IS_PIPELINE (pipeline));
33 return pipeline;
34 }
35
36 /*
37 * run_pipeline:
38 * @pipe: the pipeline to run
39 * @desc: the description for use in messages
40 * @message_types: is a mask of expected message_types
41 * @tmessage: is the expected terminal message
42 *
43 * the poll call will time out after half a second.
44 */
45 static void
run_pipeline(GstElement * pipeline,const gchar * descr,GstMessageType message_types,GstMessageType tmessage)46 run_pipeline (GstElement * pipeline, const gchar * descr,
47 GstMessageType message_types, GstMessageType tmessage)
48 {
49 GstBus *bus;
50 GstMessageType rmessage;
51 GstStateChangeReturn ret;
52
53 fail_if (pipeline == NULL);
54 bus = gst_element_get_bus (pipeline);
55 fail_if (bus == NULL);
56
57 GST_DEBUG ("running pipeline %s", descr);
58
59 ret = gst_element_set_state (pipeline, GST_STATE_PLAYING);
60 ret = gst_element_get_state (pipeline, NULL, NULL, GST_CLOCK_TIME_NONE);
61
62 if (ret != GST_STATE_CHANGE_SUCCESS) {
63 GST_WARNING ("have failed state change %d", ret);
64 g_critical ("Couldn't set pipeline to PLAYING");
65 goto done;
66 }
67
68 while (1) {
69 GstMessage *message = gst_bus_poll (bus, GST_MESSAGE_ANY, GST_SECOND / 2);
70
71 if (message) {
72 rmessage = GST_MESSAGE_TYPE (message);
73 gst_message_unref (message);
74 } else {
75 rmessage = GST_MESSAGE_UNKNOWN;
76 }
77
78 if (rmessage == tmessage) {
79 break;
80 } else if (rmessage == GST_MESSAGE_UNKNOWN) {
81 g_critical ("Unexpected timeout in gst_bus_poll, looking for %d: %s",
82 tmessage, descr);
83 break;
84 } else if (rmessage & message_types) {
85 continue;
86 }
87 g_critical
88 ("Unexpected message received of type %d, '%s', looking for %d: %s",
89 rmessage, gst_message_type_get_name (rmessage), tmessage, descr);
90 }
91
92 done:
93 gst_element_set_state (pipeline, GST_STATE_NULL);
94 gst_object_unref (pipeline);
95 gst_object_unref (bus);
96 }
97
GST_START_TEST(test_2_elements)98 GST_START_TEST (test_2_elements)
99 {
100 const gchar *s;
101
102 s = "fakesrc can-activate-push=false ! fakesink can-activate-pull=true";
103 run_pipeline (setup_pipeline (s), s,
104 GST_MESSAGE_NEW_CLOCK | GST_MESSAGE_STATE_CHANGED |
105 GST_MESSAGE_STREAM_STATUS | GST_MESSAGE_ASYNC_DONE |
106 GST_MESSAGE_STREAM_START, GST_MESSAGE_UNKNOWN);
107
108 s = "fakesrc can-activate-push=true ! fakesink can-activate-pull=false";
109 run_pipeline (setup_pipeline (s), s,
110 GST_MESSAGE_NEW_CLOCK | GST_MESSAGE_STATE_CHANGED |
111 GST_MESSAGE_STREAM_STATUS | GST_MESSAGE_ASYNC_DONE |
112 GST_MESSAGE_STREAM_START, GST_MESSAGE_UNKNOWN);
113
114 s = "fakesrc can-activate-push=false num-buffers=10 ! fakesink can-activate-pull=true";
115 run_pipeline (setup_pipeline (s), s,
116 GST_MESSAGE_NEW_CLOCK | GST_MESSAGE_STATE_CHANGED |
117 GST_MESSAGE_STREAM_STATUS | GST_MESSAGE_ASYNC_DONE |
118 GST_MESSAGE_STREAM_START, GST_MESSAGE_EOS);
119
120 s = "fakesrc can-activate-push=true num-buffers=10 ! fakesink can-activate-pull=false";
121 run_pipeline (setup_pipeline (s), s,
122 GST_MESSAGE_NEW_CLOCK | GST_MESSAGE_STATE_CHANGED |
123 GST_MESSAGE_STREAM_STATUS | GST_MESSAGE_ASYNC_DONE |
124 GST_MESSAGE_STREAM_START, GST_MESSAGE_EOS);
125
126 s = "fakesrc can-activate-push=false ! fakesink can-activate-pull=false";
127 ASSERT_CRITICAL (run_pipeline (setup_pipeline (s), s,
128 GST_MESSAGE_NEW_CLOCK | GST_MESSAGE_STATE_CHANGED |
129 GST_MESSAGE_STREAM_STATUS | GST_MESSAGE_ASYNC_DONE |
130 GST_MESSAGE_STREAM_START, GST_MESSAGE_UNKNOWN));
131 }
132
133 GST_END_TEST;
134
135 static void
check_state_change_return(GstElement * pipeline,GstState state,GstStateChangeReturn immediate,GstStateChangeReturn final)136 check_state_change_return (GstElement * pipeline, GstState state,
137 GstStateChangeReturn immediate, GstStateChangeReturn final)
138 {
139 GstStateChangeReturn ret;
140
141 ret = gst_element_set_state (pipeline, state);
142 if (ret != immediate)
143 g_critical ("Unexpected set_state return ->%s: %d != %d",
144 gst_element_state_get_name (state), ret, immediate);
145 ret = gst_element_get_state (pipeline, NULL, NULL, GST_CLOCK_TIME_NONE);
146 if (ret != final)
147 g_critical ("Unexpected get_state return ->%s: %d != %d",
148 gst_element_state_get_name (state), ret, final);
149 }
150
151
GST_START_TEST(test_state_change_returns)152 GST_START_TEST (test_state_change_returns)
153 {
154 const gchar *s;
155 GstElement *pipeline;
156
157 s = "fakesrc can-activate-pull=false ! fakesink";
158 pipeline = gst_parse_launch (s, NULL);
159 fail_unless (GST_IS_PIPELINE (pipeline));
160 check_state_change_return (pipeline, GST_STATE_READY,
161 GST_STATE_CHANGE_SUCCESS, GST_STATE_CHANGE_SUCCESS);
162 check_state_change_return (pipeline, GST_STATE_PAUSED, GST_STATE_CHANGE_ASYNC,
163 GST_STATE_CHANGE_SUCCESS);
164 check_state_change_return (pipeline, GST_STATE_PLAYING,
165 GST_STATE_CHANGE_SUCCESS, GST_STATE_CHANGE_SUCCESS);
166 /* can't check PAUSED, it's not deterministic */
167 check_state_change_return (pipeline, GST_STATE_READY,
168 GST_STATE_CHANGE_SUCCESS, GST_STATE_CHANGE_SUCCESS);
169 check_state_change_return (pipeline, GST_STATE_NULL, GST_STATE_CHANGE_SUCCESS,
170 GST_STATE_CHANGE_SUCCESS);
171 gst_object_unref (pipeline);
172
173 s = "fakesrc can-activate-push=false ! fakesink can-activate-pull=true";
174 pipeline = gst_parse_launch (s, NULL);
175 fail_unless (GST_IS_PIPELINE (pipeline));
176 check_state_change_return (pipeline, GST_STATE_READY,
177 GST_STATE_CHANGE_SUCCESS, GST_STATE_CHANGE_SUCCESS);
178 check_state_change_return (pipeline, GST_STATE_PAUSED,
179 GST_STATE_CHANGE_ASYNC, GST_STATE_CHANGE_SUCCESS);
180 check_state_change_return (pipeline, GST_STATE_PLAYING,
181 GST_STATE_CHANGE_SUCCESS, GST_STATE_CHANGE_SUCCESS);
182 /* can't check PAUSED, it's not deterministic */
183 check_state_change_return (pipeline, GST_STATE_READY,
184 GST_STATE_CHANGE_SUCCESS, GST_STATE_CHANGE_SUCCESS);
185 check_state_change_return (pipeline, GST_STATE_NULL, GST_STATE_CHANGE_SUCCESS,
186 GST_STATE_CHANGE_SUCCESS);
187 gst_object_unref (pipeline);
188 }
189
190 GST_END_TEST;
191
192 G_GNUC_UNUSED
GST_START_TEST(test_tee)193 GST_START_TEST (test_tee)
194 {
195 const gchar *s;
196
197 s = "fakesrc can-activate-push=true ! tee ! fakesink can-activate-push=true";
198 run_pipeline (setup_pipeline (s), s,
199 GST_MESSAGE_NEW_CLOCK | GST_MESSAGE_STATE_CHANGED |
200 GST_MESSAGE_STREAM_START, GST_MESSAGE_UNKNOWN);
201
202 s = "fakesrc can-activate-push=true num-buffers=10 ! tee ! fakesink can-activate-push=true";
203 run_pipeline (setup_pipeline (s), s,
204 GST_MESSAGE_NEW_CLOCK | GST_MESSAGE_STATE_CHANGED |
205 GST_MESSAGE_STREAM_START, GST_MESSAGE_EOS);
206
207 s = "fakesrc can-activate-push=false can-activate-pull=true ! tee ! fakesink can-activate-pull=true";
208 ASSERT_CRITICAL (run_pipeline (setup_pipeline (s), s,
209 GST_MESSAGE_NEW_CLOCK | GST_MESSAGE_STATE_CHANGED |
210 GST_MESSAGE_STREAM_START, GST_MESSAGE_UNKNOWN));
211
212 s = "fakesrc can-activate-push=false can-activate-pull=true "
213 "! tee pull-mode=single ! fakesink can-activate-pull=true";
214 run_pipeline (setup_pipeline (s), s,
215 GST_MESSAGE_NEW_CLOCK | GST_MESSAGE_STATE_CHANGED |
216 GST_MESSAGE_STREAM_START, GST_MESSAGE_UNKNOWN);
217
218 s = "fakesrc can-activate-push=false can-activate-pull=true num-buffers=10 "
219 "! tee pull-mode=single ! fakesink can-activate-pull=true";
220 run_pipeline (setup_pipeline (s), s,
221 GST_MESSAGE_NEW_CLOCK | GST_MESSAGE_STATE_CHANGED |
222 GST_MESSAGE_STREAM_START, GST_MESSAGE_EOS);
223
224 s = "fakesrc can-activate-push=false can-activate-pull=true "
225 "! tee name=t pull-mode=single ! fakesink can-activate-pull=true "
226 "t. ! queue ! fakesink can-activate-pull=true can-activate-push=false";
227 ASSERT_CRITICAL (run_pipeline (setup_pipeline (s), s,
228 GST_MESSAGE_NEW_CLOCK | GST_MESSAGE_STATE_CHANGED |
229 GST_MESSAGE_STREAM_START, GST_MESSAGE_UNKNOWN));
230
231 s = "fakesrc can-activate-push=false can-activate-pull=true "
232 "! tee name=t pull-mode=single ! fakesink can-activate-pull=true "
233 "t. ! queue ! fakesink";
234 run_pipeline (setup_pipeline (s), s,
235 GST_MESSAGE_NEW_CLOCK | GST_MESSAGE_STATE_CHANGED |
236 GST_MESSAGE_STREAM_START, GST_MESSAGE_UNKNOWN);
237
238 s = "fakesrc can-activate-push=false can-activate-pull=true num-buffers=10 "
239 "! tee name=t pull-mode=single ! fakesink can-activate-pull=true "
240 "t. ! queue ! fakesink";
241 run_pipeline (setup_pipeline (s), s,
242 GST_MESSAGE_NEW_CLOCK | GST_MESSAGE_STATE_CHANGED |
243 GST_MESSAGE_STREAM_START, GST_MESSAGE_EOS);
244 }
245
246 GST_END_TEST;
247
248 static void
got_handoff(GstElement * sink,GstBuffer * buf,GstPad * pad,gpointer unused)249 got_handoff (GstElement * sink, GstBuffer * buf, GstPad * pad, gpointer unused)
250 {
251 gst_element_post_message
252 (sink, gst_message_new_application (NULL,
253 gst_structure_new_empty ("foo")));
254 }
255
GST_START_TEST(test_stop_from_app)256 GST_START_TEST (test_stop_from_app)
257 {
258 GstElement *fakesrc, *fakesink, *pipeline;
259 GstBus *bus;
260 GstStateChangeReturn ret;
261 GstMessageType rmessage;
262 GstMessage *message;
263
264 fakesrc = gst_element_factory_make ("fakesrc", NULL);
265 fakesink = gst_element_factory_make ("fakesink", NULL);
266 pipeline = gst_element_factory_make ("pipeline", NULL);
267
268 fail_unless (fakesrc && fakesink && pipeline);
269
270 gst_bin_add_many (GST_BIN (pipeline), fakesrc, fakesink, NULL);
271 fail_unless (gst_element_link (fakesrc, fakesink) != FALSE);
272
273 g_object_set (fakesink, "signal-handoffs", (gboolean) TRUE, NULL);
274 g_signal_connect (fakesink, "handoff", G_CALLBACK (got_handoff), NULL);
275
276 gst_element_set_state (pipeline, GST_STATE_PAUSED);
277 ret = gst_element_get_state (pipeline, NULL, NULL, 5 * GST_SECOND);
278 switch (ret) {
279 case GST_STATE_CHANGE_FAILURE:
280 g_error ("Failed to change state to PAUSED");
281 break;
282 case GST_STATE_CHANGE_ASYNC:
283 g_error ("Failed to change state to PAUSED within 5 seconds");
284 break;
285 default:
286 break;
287 }
288
289 gst_element_set_state (pipeline, GST_STATE_PLAYING);
290
291 bus = gst_element_get_bus (pipeline);
292 fail_if (bus == NULL);
293
294 /* will time out after half a second */
295 message = gst_bus_poll (bus, GST_MESSAGE_APPLICATION, GST_SECOND / 2);
296 if (message) {
297 rmessage = GST_MESSAGE_TYPE (message);
298 gst_message_unref (message);
299 } else {
300 rmessage = GST_MESSAGE_UNKNOWN;
301 }
302 fail_unless (rmessage == GST_MESSAGE_APPLICATION,
303 "polled message is not APPLICATION but %s",
304 gst_message_type_get_name (rmessage));
305
306 gst_element_set_state (pipeline, GST_STATE_NULL);
307 gst_object_unref (pipeline);
308 gst_object_unref (bus);
309 }
310
311 GST_END_TEST;
312
GST_START_TEST(test_typefind_force_sink_caps)313 GST_START_TEST (test_typefind_force_sink_caps)
314 {
315 const gchar *s;
316
317 s = "fakesrc can-activate-push=true num-buffers=5 ! "
318 "typefind force-caps=foo/x-bar ! fakesink can-activate-push=true";
319 ASSERT_CRITICAL (run_pipeline (setup_pipeline (s), s,
320 GST_MESSAGE_NEW_CLOCK | GST_MESSAGE_STATE_CHANGED |
321 GST_MESSAGE_STREAM_STATUS | GST_MESSAGE_ASYNC_DONE |
322 GST_MESSAGE_STREAM_START, GST_MESSAGE_UNKNOWN));
323 }
324
325 GST_END_TEST;
326
327 static Suite *
simple_launch_lines_suite(void)328 simple_launch_lines_suite (void)
329 {
330 Suite *s = suite_create ("Pipelines");
331 TCase *tc_chain = tcase_create ("linear");
332
333 /* time out after 20s, not the default 3 */
334 tcase_set_timeout (tc_chain, 0);
335
336 suite_add_tcase (s, tc_chain);
337 tcase_add_test (tc_chain, test_2_elements);
338 tcase_add_test (tc_chain, test_state_change_returns);
339 /* tcase_add_test (tc_chain, test_tee); FIXME */
340 tcase_add_test (tc_chain, test_stop_from_app);
341 tcase_add_test (tc_chain, test_typefind_force_sink_caps);
342
343 return s;
344 }
345
346 GST_CHECK_MAIN (simple_launch_lines);
347