• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 (&current_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 (&current_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 (&current_segment, GST_FORMAT_UNDEFINED);
67       break;
68     case GST_EVENT_SEGMENT:
69       gst_event_copy_segment (event, &current_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 (&current_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 (&current_segment, GST_FORMAT_UNDEFINED);
194       break;
195     case GST_EVENT_SEGMENT:
196       gst_event_copy_segment (event, &current_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 (&current_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