Initialize Tizen 2.3
[framework/multimedia/gst-plugins-base0.10.git] / mobile / tests / check / elements / appsink.c
1 /* GStreamer
2  *
3  * Copyright (C) 2009, Axis Communications AB, LUND, SWEDEN
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Library General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Library General Public License for more details.
14  *
15  * You should have received a copy of the GNU Library General Public
16  * License along with this library; if not, write to the
17  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18  * Boston, MA 02111-1307, USA.
19  */
20
21 #include <gst/check/gstcheck.h>
22 #include <gst/app/gstappsink.h>
23
24 gint global_testdata;
25
26 static GstPad *mysrcpad;
27
28 static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src",
29     GST_PAD_SRC,
30     GST_PAD_ALWAYS,
31     GST_STATIC_CAPS ("application/x-gst-check")
32     );
33
34 static GstElement *
35 setup_appsink (void)
36 {
37   GstElement *appsink;
38
39   GST_DEBUG ("setup_appsink");
40   appsink = gst_check_setup_element ("appsink");
41   mysrcpad = gst_check_setup_src_pad (appsink, &srctemplate, NULL);
42
43   return appsink;
44 }
45
46 static void
47 cleanup_appsink (GstElement * appsink)
48 {
49   GST_DEBUG ("cleanup_appsink");
50
51   gst_check_teardown_src_pad (appsink);
52   gst_check_teardown_element (appsink);
53 }
54
55 /* This function does an operation to it's indata argument and returns it.
56  * The exact operation performed doesn't matter. Currently it multiplies with
57  * two, but it could do anything. The idea is to use the function to verify
58  * that the code calling it gets run. */
59 static gint
60 operate_on_data (gint indata)
61 {
62   return indata * 2;
63 }
64
65 static GstFlowReturn
66 callback_function (GstAppSink * appsink, gpointer callback_data)
67 {
68   global_testdata = operate_on_data (*((gint *) callback_data));
69
70   return GST_FLOW_OK;
71 }
72
73 static void
74 notify_function (gpointer callback_data)
75 {
76   global_testdata = operate_on_data (*((gint *) callback_data));
77 }
78
79 GST_START_TEST (test_non_clients)
80 {
81   GstElement *sink;
82   GstBuffer *buffer;
83   GstCaps *caps;
84
85   sink = setup_appsink ();
86
87   ASSERT_SET_STATE (sink, GST_STATE_PLAYING, GST_STATE_CHANGE_ASYNC);
88
89   caps = gst_caps_from_string ("application/x-gst-check");
90   buffer = gst_buffer_new_and_alloc (4);
91   gst_buffer_set_caps (buffer, caps);
92   gst_caps_unref (caps);
93   fail_unless (gst_pad_push (mysrcpad, buffer) == GST_FLOW_OK);
94
95   GST_DEBUG ("cleaning up appsink");
96   ASSERT_SET_STATE (sink, GST_STATE_NULL, GST_STATE_CHANGE_SUCCESS);
97   cleanup_appsink (sink);
98 }
99
100 GST_END_TEST;
101
102 /* Verifies that the handoff callback gets run one time when passing a buffer */
103 GST_START_TEST (test_handoff_callback)
104 {
105   GstElement *sink;
106   GstBuffer *buffer;
107   GstCaps *caps;
108   gint testdata;
109   GstAppSinkCallbacks callbacks = { NULL };
110
111   sink = setup_appsink ();
112
113   global_testdata = 0;
114   testdata = 5;                 /* Arbitrary value */
115
116   callbacks.new_buffer = callback_function;
117
118   gst_app_sink_set_callbacks (GST_APP_SINK (sink), &callbacks, &testdata, NULL);
119
120   ASSERT_SET_STATE (sink, GST_STATE_PLAYING, GST_STATE_CHANGE_ASYNC);
121
122   caps = gst_caps_from_string ("application/x-gst-check");
123   buffer = gst_buffer_new_and_alloc (4);
124   gst_buffer_set_caps (buffer, caps);
125   gst_caps_unref (caps);
126   /* Pushing a buffer should run our callback */
127   fail_unless (gst_pad_push (mysrcpad, buffer) == GST_FLOW_OK);
128
129   testdata = operate_on_data (testdata);
130
131   /* If both test_data & global_testdata have been operated on, we're happy. */
132   fail_unless (testdata == global_testdata);
133
134   GST_DEBUG ("cleaning up appsink");
135   ASSERT_SET_STATE (sink, GST_STATE_NULL, GST_STATE_CHANGE_SUCCESS);
136   cleanup_appsink (sink);
137 }
138
139 GST_END_TEST;
140
141 /* Verifies that the notify function gets executed when the sink is destroyed */
142 GST_START_TEST (test_notify0)
143 {
144   GstElement *sink;
145   gint testdata;
146   GstAppSinkCallbacks callbacks = { NULL };
147
148   sink = gst_element_factory_make ("appsink", NULL);
149
150   global_testdata = 0;
151   testdata = 17;                /* Arbitrary value */
152
153   gst_app_sink_set_callbacks (GST_APP_SINK (sink), &callbacks,
154       &testdata, (*notify_function));
155
156   GST_DEBUG ("cleaning up appsink");
157   /* Destroying sink should call our notify_function */
158   gst_object_unref (sink);
159
160   testdata = operate_on_data (testdata);
161
162   /* If both test_data & global_testdata have been operated on, we're happy. */
163   fail_unless (testdata == global_testdata);
164 }
165
166 GST_END_TEST;
167
168
169 /* Verifies that the notify function gets executed when
170  * gst_app_sink_set_callbacks () gets called */
171 GST_START_TEST (test_notify1)
172 {
173   GstElement *sink;
174   gint testdata;
175   GstAppSinkCallbacks callbacks = { NULL };
176
177   sink = gst_element_factory_make ("appsink", NULL);
178
179   global_testdata = 0;
180   testdata = 42;                /* Arbitrary value */
181
182   gst_app_sink_set_callbacks (GST_APP_SINK (sink), &callbacks,
183       &testdata, (*notify_function));
184   /* Setting new callbacks should trigger the destroy of the old data */
185   gst_app_sink_set_callbacks (GST_APP_SINK (sink), &callbacks, &testdata, NULL);
186
187   testdata = operate_on_data (testdata);
188
189   /* If both test_data & global_testdata have been operated on, we're happy. */
190   fail_unless (testdata == global_testdata);
191
192   GST_DEBUG ("cleaning up appsink");
193   gst_object_unref (sink);
194 }
195
196 GST_END_TEST;
197
198 static GstBufferList *mylist;
199 static GstCaps *mycaps;
200
201 static GstBufferList *
202 create_buffer_list (void)
203 {
204   GstBufferListIterator *it;
205   GstBuffer *buffer;
206
207   mylist = gst_buffer_list_new ();
208   fail_if (mylist == NULL);
209
210   mycaps = gst_caps_from_string ("application/x-gst-check");
211   fail_if (mycaps == NULL);
212
213   it = gst_buffer_list_iterate (mylist);
214   fail_if (it == NULL);
215
216   gst_buffer_list_iterator_add_group (it);
217
218   buffer = gst_buffer_new_and_alloc (sizeof (gint));
219   *(gint *) GST_BUFFER_DATA (buffer) = 1;
220   gst_buffer_set_caps (buffer, mycaps);
221   gst_buffer_list_iterator_add (it, buffer);
222
223   gst_buffer_list_iterator_add_group (it);
224
225   buffer = gst_buffer_new_and_alloc (sizeof (gint));
226   *(gint *) GST_BUFFER_DATA (buffer) = 2;
227   gst_buffer_set_caps (buffer, mycaps);
228   gst_buffer_list_iterator_add (it, buffer);
229
230   buffer = gst_buffer_new_and_alloc (sizeof (gint));
231   *(gint *) GST_BUFFER_DATA (buffer) = 4;
232   gst_buffer_set_caps (buffer, mycaps);
233   gst_buffer_list_iterator_add (it, buffer);
234
235   gst_buffer_list_iterator_free (it);
236
237   return mylist;
238 }
239
240 static void
241 check_buffer_list (GstBufferList * list)
242 {
243   GstBufferListIterator *it;
244   GstBuffer *buf;
245   GstCaps *caps;
246
247   fail_unless (list == mylist);
248   fail_unless (gst_buffer_list_n_groups (list) == 2);
249
250   it = gst_buffer_list_iterate (list);
251   fail_if (it == NULL);
252
253   fail_unless (gst_buffer_list_iterator_next_group (it));
254   fail_unless (gst_buffer_list_iterator_n_buffers (it) == 1);
255   buf = gst_buffer_list_iterator_next (it);
256   fail_if (buf == NULL);
257   fail_unless (*(gint *) GST_BUFFER_DATA (buf) == 1);
258   caps = gst_buffer_get_caps (buf);
259   fail_unless (caps == mycaps);
260   fail_unless (gst_caps_is_equal (caps, mycaps));
261   gst_caps_unref (caps);
262
263   fail_unless (gst_buffer_list_iterator_next_group (it));
264   fail_unless (gst_buffer_list_iterator_n_buffers (it) == 2);
265   buf = gst_buffer_list_iterator_next (it);
266   fail_if (buf == NULL);
267   fail_unless (*(gint *) GST_BUFFER_DATA (buf) == 2);
268   caps = gst_buffer_get_caps (buf);
269   fail_unless (caps == mycaps);
270   gst_caps_unref (caps);
271
272   buf = gst_buffer_list_iterator_next (it);
273   fail_if (buf == NULL);
274   fail_unless (*(gint *) GST_BUFFER_DATA (buf) == 4);
275   caps = gst_buffer_get_caps (buf);
276   fail_unless (caps == mycaps);
277   gst_caps_unref (caps);
278
279   gst_buffer_list_iterator_free (it);
280 }
281
282 static GstFlowReturn
283 callback_function_buffer_list (GstAppSink * appsink, gpointer callback_data)
284 {
285   GstBufferList *list;
286
287   list = gst_app_sink_pull_buffer_list (appsink);
288   fail_unless (GST_IS_BUFFER_LIST (list));
289
290   check_buffer_list (list);
291
292   gst_buffer_list_unref (list);
293
294   return GST_FLOW_OK;
295 }
296
297 GST_START_TEST (test_buffer_list)
298 {
299   GstElement *sink;
300   GstBufferList *list;
301   GstAppSinkCallbacks callbacks = { NULL };
302
303   sink = setup_appsink ();
304
305   callbacks.new_buffer_list = callback_function_buffer_list;
306
307   gst_app_sink_set_callbacks (GST_APP_SINK (sink), &callbacks, NULL, NULL);
308
309   ASSERT_SET_STATE (sink, GST_STATE_PLAYING, GST_STATE_CHANGE_ASYNC);
310
311   list = create_buffer_list ();
312   fail_unless (gst_pad_push_list (mysrcpad, list) == GST_FLOW_OK);
313
314   ASSERT_SET_STATE (sink, GST_STATE_NULL, GST_STATE_CHANGE_SUCCESS);
315   cleanup_appsink (sink);
316 }
317
318 GST_END_TEST;
319
320 static GstFlowReturn
321 callback_function_buffer (GstAppSink * appsink, gpointer p_counter)
322 {
323   GstBuffer *buf;
324   gint *p_int_counter = p_counter;
325
326   buf = gst_app_sink_pull_buffer (appsink);
327   fail_unless (GST_IS_BUFFER (buf));
328
329   /* buffer list has 3 buffers in two groups */
330   switch (*p_int_counter) {
331     case 0:
332       fail_unless_equals_int (GST_BUFFER_SIZE (buf), sizeof (gint));
333       fail_unless_equals_int ((((gint *) GST_BUFFER_DATA (buf))[0]), 1);
334       break;
335     case 1:
336       fail_unless_equals_int (GST_BUFFER_SIZE (buf), 2 * sizeof (gint));
337       fail_unless_equals_int ((((gint *) GST_BUFFER_DATA (buf))[0]), 2);
338       fail_unless_equals_int ((((gint *) GST_BUFFER_DATA (buf))[1]), 4);
339       break;
340     default:
341       g_warn_if_reached ();
342       break;
343   }
344
345   gst_buffer_unref (buf);
346
347   *p_int_counter += 1;
348
349   return GST_FLOW_OK;
350 }
351
352 GST_START_TEST (test_buffer_list_fallback)
353 {
354   GstElement *sink;
355   GstBufferList *list;
356   GstAppSinkCallbacks callbacks = { NULL };
357   gint counter = 0;
358
359   sink = setup_appsink ();
360
361   callbacks.new_buffer = callback_function_buffer;
362
363   gst_app_sink_set_callbacks (GST_APP_SINK (sink), &callbacks, &counter, NULL);
364
365   ASSERT_SET_STATE (sink, GST_STATE_PLAYING, GST_STATE_CHANGE_ASYNC);
366
367   list = create_buffer_list ();
368   fail_unless (gst_pad_push_list (mysrcpad, list) == GST_FLOW_OK);
369
370   fail_unless_equals_int (counter, 2);
371
372   ASSERT_SET_STATE (sink, GST_STATE_NULL, GST_STATE_CHANGE_SUCCESS);
373   cleanup_appsink (sink);
374 }
375
376 GST_END_TEST;
377
378 GST_START_TEST (test_buffer_list_fallback_signal)
379 {
380   GstElement *sink;
381   GstBufferList *list;
382   gint counter = 0;
383
384   sink = setup_appsink ();
385
386   /* C calling convention to the rescue.. */
387   g_signal_connect (sink, "new-buffer", G_CALLBACK (callback_function_buffer),
388       &counter);
389
390   g_object_set (sink, "emit-signals", TRUE, NULL);
391
392   ASSERT_SET_STATE (sink, GST_STATE_PLAYING, GST_STATE_CHANGE_ASYNC);
393
394   list = create_buffer_list ();
395   fail_unless (gst_pad_push_list (mysrcpad, list) == GST_FLOW_OK);
396
397   fail_unless_equals_int (counter, 2);
398
399   ASSERT_SET_STATE (sink, GST_STATE_NULL, GST_STATE_CHANGE_SUCCESS);
400   cleanup_appsink (sink);
401 }
402
403 GST_END_TEST;
404
405 static Suite *
406 appsink_suite (void)
407 {
408   Suite *s = suite_create ("appsink");
409   TCase *tc_chain = tcase_create ("general");
410
411   suite_add_tcase (s, tc_chain);
412   tcase_add_test (tc_chain, test_non_clients);
413   tcase_add_test (tc_chain, test_handoff_callback);
414   tcase_add_test (tc_chain, test_notify0);
415   tcase_add_test (tc_chain, test_notify1);
416   tcase_add_test (tc_chain, test_buffer_list);
417   tcase_add_test (tc_chain, test_buffer_list_fallback);
418   tcase_add_test (tc_chain, test_buffer_list_fallback_signal);
419
420   return s;
421 }
422
423 GST_CHECK_MAIN (appsink);