3 * Copyright (C) 2009, Axis Communications AB, LUND, SWEDEN
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.
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.
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.
21 #include <gst/check/gstcheck.h>
22 #include <gst/app/gstappsink.h>
26 static GstPad *mysrcpad;
28 static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src",
31 GST_STATIC_CAPS ("application/x-gst-check")
39 GST_DEBUG ("setup_appsink");
40 appsink = gst_check_setup_element ("appsink");
41 mysrcpad = gst_check_setup_src_pad (appsink, &srctemplate);
42 gst_pad_set_active (mysrcpad, TRUE);
48 cleanup_appsink (GstElement * appsink)
50 GST_DEBUG ("cleanup_appsink");
52 gst_check_teardown_src_pad (appsink);
53 gst_check_teardown_element (appsink);
56 /* This function does an operation to it's indata argument and returns it.
57 * The exact operation performed doesn't matter. Currently it multiplies with
58 * two, but it could do anything. The idea is to use the function to verify
59 * that the code calling it gets run. */
61 operate_on_data (gint indata)
67 callback_function (GstAppSink * appsink, gpointer callback_data)
69 global_testdata = operate_on_data (*((gint *) callback_data));
75 notify_function (gpointer callback_data)
77 global_testdata = operate_on_data (*((gint *) callback_data));
80 GST_START_TEST (test_non_clients)
86 sink = setup_appsink ();
88 ASSERT_SET_STATE (sink, GST_STATE_PLAYING, GST_STATE_CHANGE_ASYNC);
90 caps = gst_caps_from_string ("application/x-gst-check");
91 buffer = gst_buffer_new_and_alloc (4);
92 gst_pad_set_caps (mysrcpad, caps);
93 gst_caps_unref (caps);
94 fail_unless (gst_pad_push (mysrcpad, buffer) == GST_FLOW_OK);
96 GST_DEBUG ("cleaning up appsink");
97 ASSERT_SET_STATE (sink, GST_STATE_NULL, GST_STATE_CHANGE_SUCCESS);
98 cleanup_appsink (sink);
103 /* Verifies that the handoff callback gets run one time when passing a buffer */
104 GST_START_TEST (test_handoff_callback)
110 GstAppSinkCallbacks callbacks = { NULL };
112 sink = setup_appsink ();
115 testdata = 5; /* Arbitrary value */
117 callbacks.new_sample = callback_function;
119 gst_app_sink_set_callbacks (GST_APP_SINK (sink), &callbacks, &testdata, NULL);
121 ASSERT_SET_STATE (sink, GST_STATE_PLAYING, GST_STATE_CHANGE_ASYNC);
123 caps = gst_caps_from_string ("application/x-gst-check");
124 buffer = gst_buffer_new_and_alloc (4);
125 gst_pad_set_caps (mysrcpad, caps);
126 gst_caps_unref (caps);
127 /* Pushing a buffer should run our callback */
128 fail_unless (gst_pad_push (mysrcpad, buffer) == GST_FLOW_OK);
130 testdata = operate_on_data (testdata);
132 /* If both test_data & global_testdata have been operated on, we're happy. */
133 fail_unless (testdata == global_testdata);
135 GST_DEBUG ("cleaning up appsink");
136 ASSERT_SET_STATE (sink, GST_STATE_NULL, GST_STATE_CHANGE_SUCCESS);
137 cleanup_appsink (sink);
142 /* Verifies that the notify function gets executed when the sink is destroyed */
143 GST_START_TEST (test_notify0)
147 GstAppSinkCallbacks callbacks = { NULL };
149 sink = gst_element_factory_make ("appsink", NULL);
152 testdata = 17; /* Arbitrary value */
154 gst_app_sink_set_callbacks (GST_APP_SINK (sink), &callbacks,
155 &testdata, (*notify_function));
157 GST_DEBUG ("cleaning up appsink");
158 /* Destroying sink should call our notify_function */
159 gst_object_unref (sink);
161 testdata = operate_on_data (testdata);
163 /* If both test_data & global_testdata have been operated on, we're happy. */
164 fail_unless (testdata == global_testdata);
170 /* Verifies that the notify function gets executed when
171 * gst_app_sink_set_callbacks () gets called */
172 GST_START_TEST (test_notify1)
176 GstAppSinkCallbacks callbacks = { NULL };
178 sink = gst_element_factory_make ("appsink", NULL);
181 testdata = 42; /* Arbitrary value */
183 gst_app_sink_set_callbacks (GST_APP_SINK (sink), &callbacks,
184 &testdata, (*notify_function));
185 /* Setting new callbacks should trigger the destroy of the old data */
186 gst_app_sink_set_callbacks (GST_APP_SINK (sink), &callbacks, &testdata, NULL);
188 testdata = operate_on_data (testdata);
190 /* If both test_data & global_testdata have been operated on, we're happy. */
191 fail_unless (testdata == global_testdata);
193 GST_DEBUG ("cleaning up appsink");
194 gst_object_unref (sink);
199 static GstBufferList *mylist;
200 static GstCaps *mycaps;
202 static gint values[] = { 1, 2, 4 };
204 static GstBufferList *
205 create_buffer_list (void)
210 mylist = gst_buffer_list_new ();
211 fail_if (mylist == NULL);
213 mycaps = gst_caps_from_string ("application/x-gst-check");
214 fail_if (mycaps == NULL);
216 len = gst_buffer_list_length (mylist);
219 buffer = gst_buffer_new_and_alloc (sizeof (gint));
220 gst_buffer_fill (buffer, 0, &values[0], sizeof (gint));
221 gst_buffer_list_add (mylist, buffer);
223 buffer = gst_buffer_new_and_alloc (sizeof (gint));
224 gst_buffer_fill (buffer, 0, &values[1], sizeof (gint));
225 gst_buffer_list_add (mylist, buffer);
227 buffer = gst_buffer_new_and_alloc (sizeof (gint));
228 gst_buffer_fill (buffer, 0, &values[2], sizeof (gint));
229 gst_buffer_list_add (mylist, buffer);
231 gst_pad_set_caps (mysrcpad, mycaps);
232 gst_caps_unref (mycaps);
238 callback_function_sample (GstAppSink * appsink, gpointer p_counter)
242 gint *p_int_counter = p_counter;
244 sample = gst_app_sink_pull_sample (appsink);
245 buf = gst_sample_get_buffer (sample);
246 fail_unless (GST_IS_BUFFER (buf));
248 /* buffer list has 3 buffers in two groups */
249 switch (*p_int_counter) {
251 fail_unless_equals_int (gst_buffer_get_size (buf), sizeof (gint));
252 gst_check_buffer_data (buf, &values[0], sizeof (gint));
255 fail_unless_equals_int (gst_buffer_get_size (buf), sizeof (gint));
256 gst_check_buffer_data (buf, &values[1], sizeof (gint));
259 fail_unless_equals_int (gst_buffer_get_size (buf), sizeof (gint));
260 gst_check_buffer_data (buf, &values[2], sizeof (gint));
263 g_warn_if_reached ();
267 gst_sample_unref (sample);
274 GST_START_TEST (test_buffer_list_fallback)
278 GstAppSinkCallbacks callbacks = { NULL };
281 sink = setup_appsink ();
283 callbacks.new_sample = callback_function_sample;
285 gst_app_sink_set_callbacks (GST_APP_SINK (sink), &callbacks, &counter, NULL);
287 ASSERT_SET_STATE (sink, GST_STATE_PLAYING, GST_STATE_CHANGE_ASYNC);
289 list = create_buffer_list ();
290 fail_unless (gst_pad_push_list (mysrcpad, list) == GST_FLOW_OK);
292 fail_unless_equals_int (counter, 3);
294 ASSERT_SET_STATE (sink, GST_STATE_NULL, GST_STATE_CHANGE_SUCCESS);
295 cleanup_appsink (sink);
300 GST_START_TEST (test_buffer_list_fallback_signal)
306 sink = setup_appsink ();
308 /* C calling convention to the rescue.. */
309 g_signal_connect (sink, "new-sample", G_CALLBACK (callback_function_sample),
312 g_object_set (sink, "emit-signals", TRUE, NULL);
314 ASSERT_SET_STATE (sink, GST_STATE_PLAYING, GST_STATE_CHANGE_ASYNC);
316 list = create_buffer_list ();
317 fail_unless (gst_pad_push_list (mysrcpad, list) == GST_FLOW_OK);
319 fail_unless_equals_int (counter, 3);
321 ASSERT_SET_STATE (sink, GST_STATE_NULL, GST_STATE_CHANGE_SUCCESS);
322 cleanup_appsink (sink);
330 Suite *s = suite_create ("appsink");
331 TCase *tc_chain = tcase_create ("general");
333 suite_add_tcase (s, tc_chain);
334 tcase_add_test (tc_chain, test_non_clients);
335 tcase_add_test (tc_chain, test_handoff_callback);
336 tcase_add_test (tc_chain, test_notify0);
337 tcase_add_test (tc_chain, test_notify1);
338 tcase_add_test (tc_chain, test_buffer_list_fallback);
339 tcase_add_test (tc_chain, test_buffer_list_fallback_signal);
344 GST_CHECK_MAIN (appsink);