tests/check/: use the new macro
[platform/upstream/gstreamer.git] / tests / check / elements / fakesink.c
1 /* GStreamer
2  *
3  * unit test for fakesink
4  *
5  * Copyright (C) <2005> Thomas Vander Stichele <thomas at apestaart dot org>
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., 59 Temple Place - Suite 330,
20  * Boston, MA 02111-1307, USA.
21  */
22
23 #include <unistd.h>
24
25 #include <gst/check/gstcheck.h>
26
27 typedef struct
28 {
29   GstPad *pad;
30   GstBuffer *buffer;
31   GThread *thread;
32   GstFlowReturn ret;
33 } ChainData;
34
35 static gpointer
36 chain_async_buffer (gpointer data)
37 {
38   ChainData *chain_data = (ChainData *) data;
39
40   chain_data->ret = gst_pad_chain (chain_data->pad, chain_data->buffer);
41
42   return chain_data;
43 }
44
45 static ChainData *
46 chain_async (GstPad * pad, GstBuffer * buffer)
47 {
48   GThread *thread;
49   ChainData *chain_data;
50   GError *error = NULL;
51
52   chain_data = g_new (ChainData, 1);
53   chain_data->pad = pad;
54   chain_data->buffer = buffer;
55   chain_data->ret = GST_FLOW_ERROR;
56
57   thread = g_thread_create (chain_async_buffer, chain_data, TRUE, &error);
58   if (error != NULL) {
59     g_warning ("could not create thread reason: %s", error->message);
60     g_free (chain_data);
61     return NULL;
62   }
63   chain_data->thread = thread;
64
65   return chain_data;
66 }
67
68 static GstFlowReturn
69 chain_async_return (ChainData * data)
70 {
71   GstFlowReturn ret;
72
73   g_thread_join (data->thread);
74   ret = data->ret;
75   g_free (data);
76
77   return ret;
78 }
79
80 GST_START_TEST (test_clipping)
81 {
82   GstElement *sink;
83   GstPad *sinkpad;
84   GstStateChangeReturn ret;
85
86   /* create sink */
87   sink = gst_element_factory_make ("fakesink", "sink");
88   fail_if (sink == NULL);
89
90   sinkpad = gst_element_get_pad (sink, "sink");
91   fail_if (sinkpad == NULL);
92
93   /* make element ready to accept data */
94   ret = gst_element_set_state (sink, GST_STATE_PAUSED);
95   fail_unless (ret == GST_STATE_CHANGE_ASYNC);
96
97   /* send segment */
98   {
99     GstEvent *segment;
100     gboolean eret;
101
102     GST_DEBUG ("sending segment");
103     segment = gst_event_new_new_segment (FALSE,
104         1.0, GST_FORMAT_TIME, 1 * GST_SECOND, 5 * GST_SECOND, 1 * GST_SECOND);
105
106     eret = gst_pad_send_event (sinkpad, segment);
107     fail_if (eret == FALSE);
108   }
109
110   /* new segment should not have finished preroll */
111   ret = gst_element_get_state (sink, NULL, NULL, 0);
112   fail_unless (ret == GST_STATE_CHANGE_ASYNC);
113
114   /* send buffer that should be dropped */
115   {
116     GstBuffer *buffer;
117     GstFlowReturn fret;
118
119     buffer = gst_buffer_new ();
120     GST_BUFFER_TIMESTAMP (buffer) = 0;
121     GST_BUFFER_DURATION (buffer) = 1 * GST_MSECOND;
122
123     GST_DEBUG ("sending buffer to be dropped");
124     fret = gst_pad_chain (sinkpad, buffer);
125     fail_if (fret != GST_FLOW_OK);
126   }
127   /* dropped buffer should not have finished preroll */
128   ret = gst_element_get_state (sink, NULL, NULL, 0);
129   fail_unless (ret == GST_STATE_CHANGE_ASYNC);
130
131   /* send buffer that should be dropped */
132   {
133     GstBuffer *buffer;
134     GstFlowReturn fret;
135
136     buffer = gst_buffer_new ();
137     GST_BUFFER_TIMESTAMP (buffer) = 5 * GST_SECOND;
138     GST_BUFFER_DURATION (buffer) = 1 * GST_MSECOND;
139
140     GST_DEBUG ("sending buffer to be dropped");
141     fret = gst_pad_chain (sinkpad, buffer);
142     fail_if (fret != GST_FLOW_OK);
143   }
144   /* dropped buffer should not have finished preroll */
145   ret = gst_element_get_state (sink, NULL, NULL, 0);
146   fail_unless (ret == GST_STATE_CHANGE_ASYNC);
147
148   /* send buffer that should block and finish preroll */
149   {
150     GstBuffer *buffer;
151     GstFlowReturn fret;
152     ChainData *data;
153     GstState current, pending;
154
155     buffer = gst_buffer_new ();
156     GST_BUFFER_TIMESTAMP (buffer) = 1 * GST_SECOND;
157     GST_BUFFER_DURATION (buffer) = 1 * GST_MSECOND;
158
159     GST_DEBUG ("sending buffer to finish preroll");
160     data = chain_async (sinkpad, buffer);
161     fail_if (data == NULL);
162
163     /* state should now eventually change to PAUSED */
164     ret = gst_element_get_state (sink, &current, &pending, GST_CLOCK_TIME_NONE);
165     fail_unless (ret == GST_STATE_CHANGE_SUCCESS);
166     fail_unless (current == GST_STATE_PAUSED);
167     fail_unless (pending == GST_STATE_VOID_PENDING);
168
169     /* playing should render the buffer */
170     ret = gst_element_set_state (sink, GST_STATE_PLAYING);
171     fail_unless (ret == GST_STATE_CHANGE_SUCCESS);
172
173     /* and we should get a success return value */
174     fret = chain_async_return (data);
175     fail_if (fret != GST_FLOW_OK);
176   }
177
178   /* send some buffer that will be dropped or clipped, this can 
179    * only be observed in the debug log. */
180   {
181     GstBuffer *buffer;
182     GstFlowReturn fret;
183
184     buffer = gst_buffer_new ();
185     GST_BUFFER_TIMESTAMP (buffer) = 6 * GST_SECOND;
186     GST_BUFFER_DURATION (buffer) = 1 * GST_MSECOND;
187
188     /* should be dropped */
189     GST_DEBUG ("sending buffer to drop");
190     fret = gst_pad_chain (sinkpad, buffer);
191     fail_if (fret != GST_FLOW_OK);
192
193     buffer = gst_buffer_new ();
194     GST_BUFFER_TIMESTAMP (buffer) = 0 * GST_SECOND;
195     GST_BUFFER_DURATION (buffer) = 2 * GST_SECOND;
196
197     /* should be clipped */
198     GST_DEBUG ("sending buffer to clip");
199     fret = gst_pad_chain (sinkpad, buffer);
200     fail_if (fret != GST_FLOW_OK);
201
202     buffer = gst_buffer_new ();
203     GST_BUFFER_TIMESTAMP (buffer) = 4 * GST_SECOND;
204     GST_BUFFER_DURATION (buffer) = 2 * GST_SECOND;
205
206     /* should be clipped */
207     GST_DEBUG ("sending buffer to clip");
208     fret = gst_pad_chain (sinkpad, buffer);
209     fail_if (fret != GST_FLOW_OK);
210   }
211
212   gst_element_set_state (sink, GST_STATE_NULL);
213   gst_element_get_state (sink, NULL, NULL, GST_CLOCK_TIME_NONE);
214   gst_object_unref (sinkpad);
215   gst_object_unref (sink);
216 }
217
218 GST_END_TEST;
219
220 GST_START_TEST (test_preroll_sync)
221 {
222   GstElement *pipeline, *sink;
223   GstPad *sinkpad;
224   GstStateChangeReturn ret;
225
226   /* create sink */
227   pipeline = gst_pipeline_new ("pipeline");
228   fail_if (pipeline == NULL);
229
230   sink = gst_element_factory_make ("fakesink", "sink");
231   fail_if (sink == NULL);
232   g_object_set (G_OBJECT (sink), "sync", TRUE, NULL);
233
234   gst_bin_add (GST_BIN (pipeline), sink);
235
236   sinkpad = gst_element_get_pad (sink, "sink");
237   fail_if (sinkpad == NULL);
238
239   /* make pipeline and element ready to accept data */
240   ret = gst_element_set_state (pipeline, GST_STATE_PAUSED);
241   fail_unless (ret == GST_STATE_CHANGE_ASYNC);
242
243   /* send segment */
244   {
245     GstEvent *segment;
246     gboolean eret;
247
248     GST_DEBUG ("sending segment");
249     segment = gst_event_new_new_segment (FALSE,
250         1.0, GST_FORMAT_TIME, 0 * GST_SECOND, 2 * GST_SECOND, 0 * GST_SECOND);
251
252     eret = gst_pad_send_event (sinkpad, segment);
253     fail_if (eret == FALSE);
254   }
255
256   /* send buffer that should block and finish preroll */
257   {
258     GstBuffer *buffer;
259     GstFlowReturn fret;
260     ChainData *data;
261     GstState current, pending;
262
263     buffer = gst_buffer_new ();
264     GST_BUFFER_TIMESTAMP (buffer) = 1 * GST_SECOND;
265     GST_BUFFER_DURATION (buffer) = 1 * GST_SECOND;
266
267     GST_DEBUG ("sending buffer to finish preroll");
268     data = chain_async (sinkpad, buffer);
269     fail_if (data == NULL);
270
271     /* state should now eventually change to PAUSED */
272     ret =
273         gst_element_get_state (pipeline, &current, &pending,
274         GST_CLOCK_TIME_NONE);
275     fail_unless (ret == GST_STATE_CHANGE_SUCCESS);
276     fail_unless (current == GST_STATE_PAUSED);
277     fail_unless (pending == GST_STATE_VOID_PENDING);
278
279     /* playing should render the buffer */
280     ret = gst_element_set_state (pipeline, GST_STATE_PLAYING);
281     fail_unless (ret == GST_STATE_CHANGE_SUCCESS);
282
283     /* and we should get a success return value */
284     fret = chain_async_return (data);
285     fail_if (fret != GST_FLOW_OK);
286   }
287   gst_element_set_state (pipeline, GST_STATE_NULL);
288   gst_element_get_state (pipeline, NULL, NULL, GST_CLOCK_TIME_NONE);
289   gst_object_unref (sinkpad);
290   gst_object_unref (pipeline);
291 }
292
293 GST_END_TEST;
294
295 Suite *
296 fakesink_suite (void)
297 {
298   Suite *s = suite_create ("fakesink");
299   TCase *tc_chain = tcase_create ("general");
300
301   suite_add_tcase (s, tc_chain);
302   tcase_add_test (tc_chain, test_clipping);
303   tcase_add_test (tc_chain, test_preroll_sync);
304
305   return s;
306 }
307
308 GST_CHECK_MAIN (fakesink);