1 /* GStreamer unit tests for concat
2 *
3 * Copyright (C) 2014 Sebastian Dröge <sebastian@centricular.com>
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 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 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20
21 #ifdef HAVE_CONFIG_H
22 # include <config.h>
23 #endif
24
25 #include <gst/check/gstcheck.h>
26
27 #define N_BUFFERS 10
28 static gboolean got_eos;
29 static guint buffer_count;
30 static GstSegment current_segment;
31 static guint64 current_bytes;
32
33 static GstFlowReturn
output_chain_time(GstPad * pad,GstObject * parent,GstBuffer * buffer)34 output_chain_time (GstPad * pad, GstObject * parent, GstBuffer * buffer)
35 {
36 GstClockTime timestamp;
37 guint8 b;
38
39 timestamp = GST_BUFFER_TIMESTAMP (buffer);
40 fail_unless_equals_int64 (timestamp,
41 (buffer_count % N_BUFFERS) * 25 * GST_MSECOND);
42 timestamp =
43 gst_segment_to_stream_time (¤t_segment, GST_FORMAT_TIME, timestamp);
44 fail_unless_equals_int64 (timestamp,
45 (buffer_count % N_BUFFERS) * 25 * GST_MSECOND);
46
47 timestamp = GST_BUFFER_TIMESTAMP (buffer);
48 timestamp =
49 gst_segment_to_running_time (¤t_segment, GST_FORMAT_TIME,
50 timestamp);
51 fail_unless_equals_int64 (timestamp, buffer_count * 25 * GST_MSECOND);
52
53 gst_buffer_extract (buffer, 0, &b, 1);
54 fail_unless_equals_int (b, buffer_count % N_BUFFERS);
55
56 buffer_count++;
57 gst_buffer_unref (buffer);
58 return GST_FLOW_OK;
59 }
60
61 static gboolean
output_event_time(GstPad * pad,GstObject * parent,GstEvent * event)62 output_event_time (GstPad * pad, GstObject * parent, GstEvent * event)
63 {
64 switch (GST_EVENT_TYPE (event)) {
65 case GST_EVENT_FLUSH_STOP:
66 gst_segment_init (¤t_segment, GST_FORMAT_UNDEFINED);
67 break;
68 case GST_EVENT_SEGMENT:
69 gst_event_copy_segment (event, ¤t_segment);
70 break;
71 case GST_EVENT_EOS:
72 got_eos = TRUE;
73 break;
74 default:
75 break;
76 }
77
78 gst_event_unref (event);
79 return TRUE;
80 }
81
82 static gpointer
push_buffers_time(gpointer data)83 push_buffers_time (gpointer data)
84 {
85 GstSegment segment;
86 GstPad *pad = data;
87 gint i;
88 GstClockTime timestamp = 0;
89
90 gst_pad_send_event (pad, gst_event_new_stream_start ("test"));
91 gst_segment_init (&segment, GST_FORMAT_TIME);
92 gst_pad_send_event (pad, gst_event_new_segment (&segment));
93
94 for (i = 0; i < N_BUFFERS; i++) {
95 GstBuffer *buf = gst_buffer_new_and_alloc (1000);
96
97 gst_buffer_memset (buf, 0, i, 1);
98
99 GST_BUFFER_TIMESTAMP (buf) = timestamp;
100 timestamp += 25 * GST_MSECOND;
101 GST_BUFFER_DURATION (buf) = timestamp - GST_BUFFER_TIMESTAMP (buf);
102
103 fail_unless (gst_pad_chain (pad, buf) == GST_FLOW_OK);
104 }
105 gst_pad_send_event (pad, gst_event_new_eos ());
106
107 return NULL;
108 }
109
GST_START_TEST(test_concat_simple_time)110 GST_START_TEST (test_concat_simple_time)
111 {
112 GstElement *concat;
113 GstPad *sink1, *sink2, *sink3, *src, *output_sink;
114 GThread *thread1, *thread2, *thread3;
115
116 got_eos = FALSE;
117 buffer_count = 0;
118 gst_segment_init (¤t_segment, GST_FORMAT_UNDEFINED);
119
120 concat = gst_element_factory_make ("concat", NULL);
121 fail_unless (concat != NULL);
122
123 sink1 = gst_element_get_request_pad (concat, "sink_%u");
124 fail_unless (sink1 != NULL);
125
126 sink2 = gst_element_get_request_pad (concat, "sink_%u");
127 fail_unless (sink2 != NULL);
128
129 sink3 = gst_element_get_request_pad (concat, "sink_%u");
130 fail_unless (sink3 != NULL);
131
132 src = gst_element_get_static_pad (concat, "src");
133 output_sink = gst_pad_new ("sink", GST_PAD_SINK);
134 fail_unless (output_sink != NULL);
135 fail_unless (gst_pad_link (src, output_sink) == GST_PAD_LINK_OK);
136
137 gst_pad_set_chain_function (output_sink, output_chain_time);
138 gst_pad_set_event_function (output_sink, output_event_time);
139
140 gst_pad_set_active (output_sink, TRUE);
141 fail_unless (gst_element_set_state (concat,
142 GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS);
143
144 thread1 = g_thread_new ("thread1", (GThreadFunc) push_buffers_time, sink1);
145 thread2 = g_thread_new ("thread2", (GThreadFunc) push_buffers_time, sink2);
146 thread3 = g_thread_new ("thread3", (GThreadFunc) push_buffers_time, sink3);
147
148 g_thread_join (thread1);
149 g_thread_join (thread2);
150 g_thread_join (thread3);
151
152 fail_unless (got_eos);
153 fail_unless_equals_int (buffer_count, 3 * N_BUFFERS);
154
155 gst_element_set_state (concat, GST_STATE_NULL);
156 gst_pad_unlink (src, output_sink);
157 gst_object_unref (src);
158 gst_element_release_request_pad (concat, sink1);
159 gst_object_unref (sink1);
160 gst_element_release_request_pad (concat, sink2);
161 gst_object_unref (sink2);
162 gst_element_release_request_pad (concat, sink3);
163 gst_object_unref (sink3);
164 gst_pad_set_active (output_sink, FALSE);
165 gst_object_unref (output_sink);
166 gst_object_unref (concat);
167 }
168
169 GST_END_TEST;
170
171 static GstFlowReturn
output_chain_bytes(GstPad * pad,GstObject * parent,GstBuffer * buffer)172 output_chain_bytes (GstPad * pad, GstObject * parent, GstBuffer * buffer)
173 {
174 guint8 b;
175
176 fail_unless (current_bytes >= current_segment.start);
177 fail_unless_equals_int64 (current_segment.start,
178 (buffer_count / N_BUFFERS) * 1000 * N_BUFFERS);
179
180 gst_buffer_extract (buffer, 0, &b, 1);
181 fail_unless_equals_int (b, buffer_count % N_BUFFERS);
182
183 current_bytes += gst_buffer_get_size (buffer), buffer_count++;
184 gst_buffer_unref (buffer);
185 return GST_FLOW_OK;
186 }
187
188 static gboolean
output_event_bytes(GstPad * pad,GstObject * parent,GstEvent * event)189 output_event_bytes (GstPad * pad, GstObject * parent, GstEvent * event)
190 {
191 switch (GST_EVENT_TYPE (event)) {
192 case GST_EVENT_FLUSH_STOP:
193 gst_segment_init (¤t_segment, GST_FORMAT_UNDEFINED);
194 break;
195 case GST_EVENT_SEGMENT:
196 gst_event_copy_segment (event, ¤t_segment);
197 break;
198 case GST_EVENT_EOS:
199 got_eos = TRUE;
200 break;
201 default:
202 break;
203 }
204
205 gst_event_unref (event);
206 return TRUE;
207 }
208
209 static gpointer
push_buffers_bytes(gpointer data)210 push_buffers_bytes (gpointer data)
211 {
212 GstSegment segment;
213 GstPad *pad = data;
214 gint i;
215
216 gst_pad_send_event (pad, gst_event_new_stream_start ("test"));
217 gst_segment_init (&segment, GST_FORMAT_BYTES);
218 gst_pad_send_event (pad, gst_event_new_segment (&segment));
219
220 for (i = 0; i < N_BUFFERS; i++) {
221 GstBuffer *buf = gst_buffer_new_and_alloc (1000);
222 gst_buffer_memset (buf, 0, i, 1);
223
224 fail_unless (gst_pad_chain (pad, buf) == GST_FLOW_OK);
225 }
226 gst_pad_send_event (pad, gst_event_new_eos ());
227
228 return NULL;
229 }
230
GST_START_TEST(test_concat_simple_bytes)231 GST_START_TEST (test_concat_simple_bytes)
232 {
233 GstElement *concat;
234 GstPad *sink1, *sink2, *sink3, *src, *output_sink;
235 GThread *thread1, *thread2, *thread3;
236
237 got_eos = FALSE;
238 buffer_count = 0;
239 current_bytes = 0;
240 gst_segment_init (¤t_segment, GST_FORMAT_UNDEFINED);
241
242 concat = gst_element_factory_make ("concat", NULL);
243 fail_unless (concat != NULL);
244
245 sink1 = gst_element_get_request_pad (concat, "sink_%u");
246 fail_unless (sink1 != NULL);
247
248 sink2 = gst_element_get_request_pad (concat, "sink_%u");
249 fail_unless (sink2 != NULL);
250
251 sink3 = gst_element_get_request_pad (concat, "sink_%u");
252 fail_unless (sink3 != NULL);
253
254 src = gst_element_get_static_pad (concat, "src");
255 output_sink = gst_pad_new ("sink", GST_PAD_SINK);
256 fail_unless (output_sink != NULL);
257 fail_unless (gst_pad_link (src, output_sink) == GST_PAD_LINK_OK);
258
259 gst_pad_set_chain_function (output_sink, output_chain_bytes);
260 gst_pad_set_event_function (output_sink, output_event_bytes);
261
262 gst_pad_set_active (output_sink, TRUE);
263 fail_unless (gst_element_set_state (concat,
264 GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS);
265
266 thread1 = g_thread_new ("thread1", (GThreadFunc) push_buffers_bytes, sink1);
267 thread2 = g_thread_new ("thread2", (GThreadFunc) push_buffers_bytes, sink2);
268 thread3 = g_thread_new ("thread3", (GThreadFunc) push_buffers_bytes, sink3);
269
270 g_thread_join (thread1);
271 g_thread_join (thread2);
272 g_thread_join (thread3);
273
274 fail_unless (got_eos);
275 fail_unless_equals_int (buffer_count, 3 * N_BUFFERS);
276 fail_unless_equals_int64 (current_bytes, 3 * N_BUFFERS * 1000);
277
278 gst_element_set_state (concat, GST_STATE_NULL);
279 gst_pad_unlink (src, output_sink);
280 gst_object_unref (src);
281 gst_element_release_request_pad (concat, sink1);
282 gst_object_unref (sink1);
283 gst_element_release_request_pad (concat, sink2);
284 gst_object_unref (sink2);
285 gst_element_release_request_pad (concat, sink3);
286 gst_object_unref (sink3);
287 gst_pad_set_active (output_sink, FALSE);
288 gst_object_unref (output_sink);
289 gst_object_unref (concat);
290 }
291
292 GST_END_TEST;
293
294 static Suite *
concat_suite(void)295 concat_suite (void)
296 {
297 Suite *s = suite_create ("concat");
298 TCase *tc_chain;
299
300 tc_chain = tcase_create ("concat");
301 tcase_add_test (tc_chain, test_concat_simple_time);
302 tcase_add_test (tc_chain, test_concat_simple_bytes);
303 suite_add_tcase (s, tc_chain);
304
305 return s;
306 }
307
308 GST_CHECK_MAIN (concat);
309