1 /* GStreamer
2 *
3 * unit test for shm elements
4 * Copyright (C) 2013 Collabora Ltd
5 * @author: Olivier Crete <olivier.crete@collabora.com>
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., 51 Franklin St, Fifth Floor,
20 * Boston, MA 02110-1301, USA.
21 */
22
23 #ifdef HAVE_CONFIG_H
24 #include "config.h"
25 #endif
26
27 #include <gst/gst.h>
28 #include <gst/check/gstcheck.h>
29
30
31 static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink",
32 GST_PAD_SINK,
33 GST_PAD_ALWAYS,
34 GST_STATIC_CAPS_ANY);
35
36 static GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE ("src",
37 GST_PAD_SRC,
38 GST_PAD_ALWAYS,
39 GST_STATIC_CAPS_ANY);
40
41 GstElement *src, *sink;
42 GstPad *sinkpad, *srcpad;
43
44 static void
setup_shm(void)45 setup_shm (void)
46 {
47 gchar *socket_path = NULL;
48
49 sink = gst_check_setup_element ("shmsink");
50 src = gst_check_setup_element ("shmsrc");
51
52 srcpad = gst_check_setup_src_pad (sink, &src_template);
53 sinkpad = gst_check_setup_sink_pad (src, &sink_template);
54
55 g_object_set (sink, "socket-path", "shm-unit-test", NULL);
56
57 fail_unless (gst_element_set_state (sink, GST_STATE_PLAYING) ==
58 GST_STATE_CHANGE_ASYNC);
59
60 g_object_get (sink, "socket-path", &socket_path, NULL);
61 fail_unless (socket_path != NULL);
62 g_object_set (src, "socket-path", socket_path, NULL);
63 g_free (socket_path);
64
65 gst_pad_set_active (srcpad, TRUE);
66 gst_pad_set_active (sinkpad, TRUE);
67
68 fail_unless (gst_element_set_state (src, GST_STATE_PLAYING) ==
69 GST_STATE_CHANGE_SUCCESS);
70 }
71
72 static void
teardown_shm(void)73 teardown_shm (void)
74 {
75 fail_unless (gst_element_set_state (src, GST_STATE_NULL) ==
76 GST_STATE_CHANGE_SUCCESS);
77 gst_check_teardown_sink_pad (src);
78 gst_check_teardown_src_pad (sink);
79 gst_check_teardown_element (src);
80 gst_check_teardown_element (sink);
81 }
82
GST_START_TEST(test_shm_sysmem_alloc)83 GST_START_TEST (test_shm_sysmem_alloc)
84 {
85 GstBuffer *buf;
86 GstState state, pending;
87 GstSegment segment;
88
89 gst_pad_push_event (srcpad, gst_event_new_stream_start ("test"));
90 gst_segment_init (&segment, GST_FORMAT_BYTES);
91 gst_pad_push_event (srcpad, gst_event_new_segment (&segment));
92
93 buf = gst_buffer_new_allocate (NULL, 1000, NULL);
94
95 fail_unless (gst_pad_push (srcpad, buf) == GST_FLOW_OK);
96
97 fail_unless (gst_element_get_state (sink, &state, &pending,
98 GST_CLOCK_TIME_NONE) == GST_STATE_CHANGE_SUCCESS);
99 fail_unless (state == GST_STATE_PLAYING);
100 fail_unless (pending == GST_STATE_VOID_PENDING);
101
102 g_mutex_lock (&check_mutex);
103 while (buffers == NULL)
104 g_cond_wait (&check_cond, &check_mutex);
105 g_mutex_unlock (&check_mutex);
106 fail_unless (g_list_length (buffers) == 1);
107
108 buf = buffers->data;
109 fail_unless (gst_buffer_get_size (buf) == 1000);
110
111 gst_check_drop_buffers ();
112 teardown_shm ();
113 }
114
115 GST_END_TEST;
116
117
GST_START_TEST(test_shm_alloc)118 GST_START_TEST (test_shm_alloc)
119 {
120 GstBuffer *buf;
121 GstQuery *query;
122 GstCaps *caps = gst_caps_new_empty_simple ("application/x-test");
123 GstAllocator *alloc;
124 GstAllocationParams params;
125 guint size;
126 GstSegment segment;
127
128 gst_pad_push_event (srcpad, gst_event_new_stream_start ("test"));
129 gst_pad_push_event (srcpad, gst_event_new_caps (caps));
130 gst_segment_init (&segment, GST_FORMAT_BYTES);
131 gst_pad_push_event (srcpad, gst_event_new_segment (&segment));
132
133 query = gst_query_new_allocation (caps, FALSE);
134 gst_caps_unref (caps);
135
136 fail_unless (gst_pad_peer_query (srcpad, query));
137
138 fail_unless (gst_query_get_n_allocation_params (query) == 1);
139
140 gst_query_parse_nth_allocation_param (query, 0, &alloc, ¶ms);
141 fail_unless (alloc != NULL);
142 gst_query_unref (query);
143
144 g_object_get (sink, "shm-size", &size, NULL);
145
146 size -= params.align | gst_memory_alignment;
147
148 /* alloc buffer of max size, this way, it will block forever it a copy
149 * is made inside shmsink*/
150 buf = gst_buffer_new_allocate (alloc, size, ¶ms);
151
152 gst_object_unref (alloc);
153
154 fail_unless (gst_pad_push (srcpad, buf) == GST_FLOW_OK);
155
156
157 g_mutex_lock (&check_mutex);
158 while (buffers == NULL)
159 g_cond_wait (&check_cond, &check_mutex);
160 g_mutex_unlock (&check_mutex);
161 fail_unless (g_list_length (buffers) == 1);
162
163 buf = buffers->data;
164 fail_unless (gst_buffer_get_size (buf) == size);
165
166 gst_check_drop_buffers ();
167 teardown_shm ();
168 }
169
170 GST_END_TEST;
171
GST_START_TEST(test_shm_live)172 GST_START_TEST (test_shm_live)
173 {
174 GstElement *producer, *consumer;
175 GstElement *src, *sink;
176 gchar *socket_path = NULL;
177 GstStateChangeReturn state_res;
178 GstSample *sample = NULL;
179
180 src = gst_element_factory_make ("fakesrc", NULL);
181 g_object_set (src, "sizetype", 2, NULL);
182
183 sink = gst_element_factory_make ("shmsink", NULL);
184 g_object_set (sink, "socket-path", "shm-unit-test", "wait-for-connection",
185 FALSE, NULL);
186
187 producer = gst_pipeline_new ("producer-pipeline");
188 gst_bin_add_many (GST_BIN (producer), src, sink, NULL);
189 fail_unless (gst_element_link (src, sink));
190
191 state_res = gst_element_set_state (producer, GST_STATE_PLAYING);
192 fail_unless (state_res != GST_STATE_CHANGE_FAILURE);
193
194 g_object_get (sink, "socket-path", &socket_path, NULL);
195 fail_unless (socket_path != NULL);
196
197 src = gst_element_factory_make ("shmsrc", NULL);
198 sink = gst_element_factory_make ("appsink", NULL);
199 g_object_set (src, "is-live", TRUE, NULL);
200 g_object_set (sink, "async", FALSE, "enable-last-sample", FALSE, NULL);
201
202 consumer = gst_pipeline_new ("consumer-pipeline");
203 gst_bin_add_many (GST_BIN (consumer), src, sink, NULL);
204 fail_unless (gst_element_link (src, sink));
205
206 g_object_set (src, "socket-path", socket_path, NULL);
207
208 state_res = gst_element_set_state (consumer, GST_STATE_PLAYING);
209 fail_unless (state_res != GST_STATE_CHANGE_FAILURE);
210
211 /* wait for preroll */
212 state_res = gst_element_get_state (consumer, NULL, NULL, GST_CLOCK_TIME_NONE);
213 fail_unless (state_res == GST_STATE_CHANGE_SUCCESS);
214
215 g_signal_emit_by_name (sink, "pull-sample", &sample);
216 gst_sample_unref (sample);
217
218 state_res = gst_element_set_state (producer, GST_STATE_NULL);
219 fail_unless (state_res != GST_STATE_CHANGE_FAILURE);
220
221 state_res = gst_element_set_state (consumer, GST_STATE_NULL);
222 fail_unless (state_res != GST_STATE_CHANGE_FAILURE);
223
224 gst_object_unref (consumer);
225 gst_object_unref (producer);
226
227 g_free (socket_path);
228 }
229
230 GST_END_TEST;
231
232 static Suite *
shm_suite(void)233 shm_suite (void)
234 {
235 Suite *s = suite_create ("shm");
236 TCase *tc;
237
238 tc = tcase_create ("shm");
239 tcase_add_checked_fixture (tc, setup_shm, NULL);
240 tcase_add_test (tc, test_shm_sysmem_alloc);
241 tcase_add_test (tc, test_shm_alloc);
242 suite_add_tcase (s, tc);
243
244 tc = tcase_create ("shm2");
245 tcase_add_test (tc, test_shm_live);
246 suite_add_tcase (s, tc);
247
248 return s;
249 }
250
251
252 GST_CHECK_MAIN (shm);
253