• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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