1 /* GStreamer unit test for multifile plugin
2  *
3  * Copyright (C) 2007 David A. Schleef <ds@schleef.org>
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., 51 Franklin St, Fifth Floor,
18  * Boston, MA 02110-1301, USA.
19  */
20 
21 #ifdef HAVE_CONFIG_H
22 #  include "config.h"
23 #endif
24 
25 #include <glib/gstdio.h>
26 
27 #include <gst/check/gstcheck.h>
28 #include <gst/video/video.h>
29 #include <stdlib.h>
30 
31 static GList *mfs_messages = NULL;
32 
33 static void
mfs_check_next_message(const gchar * filename)34 mfs_check_next_message (const gchar * filename)
35 {
36   GstMessage *msg;
37   const gchar *msg_filename;
38   const GstStructure *structure;
39 
40   fail_unless (mfs_messages != NULL);
41 
42   msg = mfs_messages->data;
43   mfs_messages = g_list_delete_link (mfs_messages, mfs_messages);
44 
45   structure = gst_message_get_structure (msg);
46 
47   msg_filename = gst_structure_get_string (structure, "filename");
48 
49   fail_unless (strcmp (filename, msg_filename) == 0);
50 
51   gst_message_unref (msg);
52 }
53 
54 static void
run_pipeline(GstElement * pipeline)55 run_pipeline (GstElement * pipeline)
56 {
57   GstMessage *msg;
58   GstBus *bus;
59 
60   bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
61 
62   gst_element_set_state (pipeline, GST_STATE_PAUSED);
63   gst_element_get_state (pipeline, NULL, NULL, -1);
64   gst_element_set_state (pipeline, GST_STATE_PLAYING);
65 
66   while (1) {
67     msg =
68         gst_bus_timed_pop_filtered (bus, GST_CLOCK_TIME_NONE,
69         GST_MESSAGE_EOS | GST_MESSAGE_ERROR | GST_MESSAGE_ELEMENT);
70 
71     fail_unless (msg != NULL);
72     if (msg) {
73       if (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_ELEMENT) {
74         if (gst_message_has_name (msg, "GstMultiFileSink"))
75           mfs_messages = g_list_append (mfs_messages, msg);
76         else
77           gst_message_unref (msg);
78 
79         continue;
80       }
81 
82       fail_unless (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_EOS);
83       gst_message_unref (msg);
84     }
85     break;
86   }
87 
88   gst_object_unref (bus);
89   gst_element_set_state (pipeline, GST_STATE_NULL);
90 }
91 
GST_START_TEST(test_multifilesink_key_frame)92 GST_START_TEST (test_multifilesink_key_frame)
93 {
94   GstElement *pipeline;
95   GstElement *mfs;
96   int i;
97   const gchar *tmpdir;
98   gchar *my_tmpdir;
99   gchar *template;
100   gchar *mfs_pattern;
101 
102   tmpdir = g_get_tmp_dir ();
103   template = g_build_filename (tmpdir, "multifile-test-XXXXXX", NULL);
104   my_tmpdir = g_mkdtemp (template);
105   fail_if (my_tmpdir == NULL);
106 
107   pipeline =
108       gst_parse_launch
109       ("videotestsrc num-buffers=10 ! video/x-raw,format=(string)I420,width=320,height=240 ! multifilesink name=mfs",
110       NULL);
111   fail_if (pipeline == NULL);
112   mfs = gst_bin_get_by_name (GST_BIN (pipeline), "mfs");
113   fail_if (mfs == NULL);
114   mfs_pattern = g_build_filename (my_tmpdir, "%05d", NULL);
115   g_object_set (G_OBJECT (mfs), "location", mfs_pattern, "post-messages", TRUE,
116       NULL);
117   g_object_unref (mfs);
118   run_pipeline (pipeline);
119   gst_object_unref (pipeline);
120 
121   for (i = 0; i < 10; i++) {
122     char *s;
123 
124     s = g_strdup_printf (mfs_pattern, i);
125     fail_if (g_remove (s) != 0);
126 
127     mfs_check_next_message (s);
128 
129     g_free (s);
130   }
131   fail_if (g_remove (my_tmpdir) != 0);
132 
133   fail_unless (mfs_messages == NULL);
134   g_free (mfs_pattern);
135   g_free (my_tmpdir);
136 }
137 
138 GST_END_TEST;
139 
GST_START_TEST(test_multifilesink_max_files)140 GST_START_TEST (test_multifilesink_max_files)
141 {
142   GstElement *pipeline;
143   GstElement *mfs;
144   int i;
145   const gchar *tmpdir;
146   gchar *my_tmpdir;
147   gchar *template;
148   gchar *mfs_pattern;
149 
150   tmpdir = g_get_tmp_dir ();
151   template = g_build_filename (tmpdir, "multifile-test-XXXXXX", NULL);
152   my_tmpdir = g_mkdtemp (template);
153   fail_if (my_tmpdir == NULL);
154 
155   pipeline =
156       gst_parse_launch
157       ("videotestsrc num-buffers=10 ! video/x-raw,format=(string)I420,width=320,height=240 ! multifilesink name=mfs",
158       NULL);
159   fail_if (pipeline == NULL);
160   mfs = gst_bin_get_by_name (GST_BIN (pipeline), "mfs");
161   fail_if (mfs == NULL);
162   mfs_pattern = g_build_filename (my_tmpdir, "%05d", NULL);
163   g_object_set (G_OBJECT (mfs), "location", mfs_pattern, "max-files", 3, NULL);
164   g_object_unref (mfs);
165   run_pipeline (pipeline);
166   gst_object_unref (pipeline);
167 
168   for (i = 0; i < 7; i++) {
169     char *s;
170 
171     s = g_strdup_printf (mfs_pattern, i);
172     fail_unless (g_remove (s) != 0);
173     g_free (s);
174   }
175   for (i = 7; i < 10; i++) {
176     char *s;
177 
178     s = g_strdup_printf (mfs_pattern, i);
179     fail_if (g_remove (s) != 0);
180     g_free (s);
181   }
182   fail_if (g_remove (my_tmpdir) != 0);
183 
184   g_free (mfs_pattern);
185   g_free (my_tmpdir);
186 }
187 
188 GST_END_TEST;
189 
GST_START_TEST(test_multifilesink_key_unit)190 GST_START_TEST (test_multifilesink_key_unit)
191 {
192   GstElement *mfs;
193   int i;
194   const gchar *tmpdir;
195   gchar *my_tmpdir;
196   gchar *template;
197   gchar *mfs_pattern;
198   GstBuffer *buf;
199   GstPad *sink;
200   GstSegment segment;
201   GstBus *bus;
202 
203   tmpdir = g_get_tmp_dir ();
204   template = g_build_filename (tmpdir, "multifile-test-XXXXXX", NULL);
205   my_tmpdir = g_mkdtemp (template);
206   fail_if (my_tmpdir == NULL);
207 
208   mfs = gst_element_factory_make ("multifilesink", NULL);
209   fail_if (mfs == NULL);
210   mfs_pattern = g_build_filename (my_tmpdir, "%05d", NULL);
211   g_object_set (G_OBJECT (mfs), "location", mfs_pattern, "next-file", 3,
212       "post-messages", TRUE, NULL);
213   bus = gst_bus_new ();
214   gst_element_set_bus (mfs, bus);
215   fail_if (gst_element_set_state (mfs,
216           GST_STATE_PLAYING) == GST_STATE_CHANGE_FAILURE);
217 
218   sink = gst_element_get_static_pad (mfs, "sink");
219 
220   gst_pad_send_event (sink, gst_event_new_stream_start ("test"));
221   gst_segment_init (&segment, GST_FORMAT_TIME);
222   gst_pad_send_event (sink, gst_event_new_segment (&segment));
223 
224   buf = gst_buffer_new_and_alloc (4);
225 
226   gst_buffer_fill (buf, 0, "foo", 4);
227   fail_if (gst_pad_chain (sink, gst_buffer_copy (buf)) != GST_FLOW_OK);
228 
229   gst_buffer_fill (buf, 0, "bar", 4);
230   fail_if (gst_pad_chain (sink, gst_buffer_copy (buf)) != GST_FLOW_OK);
231 
232   fail_unless (gst_pad_send_event (sink,
233           gst_video_event_new_downstream_force_key_unit (GST_CLOCK_TIME_NONE,
234               GST_CLOCK_TIME_NONE, GST_CLOCK_TIME_NONE, TRUE, 1)));
235 
236   gst_buffer_fill (buf, 0, "baz", 4);
237   fail_if (gst_pad_chain (sink, buf) != GST_FLOW_OK);
238 
239   gst_pad_send_event (sink, gst_event_new_eos ());
240 
241   fail_if (gst_element_set_state (mfs,
242           GST_STATE_NULL) == GST_STATE_CHANGE_FAILURE);
243   gst_element_set_bus (mfs, NULL);
244 
245   for (i = 0; i < 2; i++) {
246     char *s;
247     GstMessage *msg;
248 
249     s = g_strdup_printf (mfs_pattern, i);
250     fail_if (g_remove (s) != 0);
251 
252     msg = gst_bus_pop_filtered (bus, GST_MESSAGE_ELEMENT);
253     fail_unless (msg != NULL);
254     fail_unless (gst_message_has_name (msg, "GstMultiFileSink"));
255     fail_unless (strcmp (s,
256             gst_structure_get_string (gst_message_get_structure (msg),
257                 "filename")) == 0);
258 
259     gst_message_unref (msg);
260     g_free (s);
261   }
262   fail_if (g_remove (my_tmpdir) != 0);
263 
264   gst_object_unref (bus);
265   g_free (mfs_pattern);
266   g_free (my_tmpdir);
267   gst_object_unref (sink);
268   gst_object_unref (mfs);
269 }
270 
271 GST_END_TEST;
272 
GST_START_TEST(test_multifilesrc)273 GST_START_TEST (test_multifilesrc)
274 {
275   GstElement *pipeline;
276   GstElement *mfs;
277   int i;
278   const gchar *tmpdir;
279   gchar *my_tmpdir;
280   gchar *template;
281   gchar *mfs_pattern;
282 
283   tmpdir = g_get_tmp_dir ();
284   template = g_build_filename (tmpdir, "multifile-test-XXXXXX", NULL);
285   my_tmpdir = g_mkdtemp (template);
286   fail_if (my_tmpdir == NULL);
287 
288   pipeline =
289       gst_parse_launch
290       ("videotestsrc num-buffers=10 ! video/x-raw,format=(string)I420,width=320,height=240 ! multifilesink name=mfs",
291       NULL);
292   fail_if (pipeline == NULL);
293   mfs = gst_bin_get_by_name (GST_BIN (pipeline), "mfs");
294   fail_if (mfs == NULL);
295   mfs_pattern = g_build_filename (my_tmpdir, "%05d", NULL);
296   g_object_set (G_OBJECT (mfs), "location", mfs_pattern, NULL);
297   g_free (mfs_pattern);
298   g_object_unref (mfs);
299   run_pipeline (pipeline);
300   gst_object_unref (pipeline);
301 
302   pipeline =
303       gst_parse_launch
304       ("multifilesrc ! video/x-raw,format=(string)I420,width=320,height=240,framerate=10/1 ! fakesink",
305       NULL);
306   fail_if (pipeline == NULL);
307   mfs = gst_bin_get_by_name (GST_BIN (pipeline), "multifilesrc0");
308   fail_if (mfs == NULL);
309   mfs_pattern = g_build_filename (my_tmpdir, "%05d", NULL);
310   g_object_set (G_OBJECT (mfs), "location", mfs_pattern, NULL);
311   g_object_unref (mfs);
312   run_pipeline (pipeline);
313   gst_object_unref (pipeline);
314 
315   for (i = 0; i < 10; i++) {
316     char *s;
317 
318     s = g_strdup_printf (mfs_pattern, i);
319     fail_if (g_remove (s) != 0);
320     g_free (s);
321   }
322   fail_if (g_remove (my_tmpdir) != 0);
323 
324   g_free (mfs_pattern);
325   g_free (my_tmpdir);
326 }
327 
328 GST_END_TEST;
329 
330 static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink",
331     GST_PAD_SINK,
332     GST_PAD_ALWAYS,
333     GST_STATIC_CAPS_ANY);
334 
335 /* make sure stop_index is honoured even if the next target file exists */
GST_START_TEST(test_multifilesrc_stop_index)336 GST_START_TEST (test_multifilesrc_stop_index)
337 {
338   GstElement *src;
339   GstEvent *event;
340   GstPad *sinkpad;
341   gchar *fn;
342 
343   src = gst_check_setup_element ("multifilesrc");
344   fail_unless (src != NULL);
345 
346   fn = g_build_filename (GST_TEST_FILES_PATH, "image.jpg", NULL);
347   g_object_set (src, "location", fn, NULL);
348   g_free (fn);
349 
350   g_object_set (src, "stop-index", 5, NULL);
351 
352   sinkpad = gst_check_setup_sink_pad_by_name (src, &sinktemplate, "src");
353   fail_unless (sinkpad != NULL);
354   gst_pad_set_active (sinkpad, TRUE);
355 
356   gst_element_set_state (src, GST_STATE_PLAYING);
357 
358   gst_element_get_state (src, NULL, NULL, -1);
359 
360   /* busy-loop for EOS */
361   do {
362     g_usleep (G_USEC_PER_SEC / 10);
363     event = gst_pad_get_sticky_event (sinkpad, GST_EVENT_EOS, 0);
364   } while (event == NULL);
365   gst_event_unref (event);
366 
367   /* Range appears to be [ start, stop ] */
368   fail_unless_equals_int (g_list_length (buffers), 5 + 1);
369 
370   gst_element_set_state (src, GST_STATE_NULL);
371 
372   gst_check_drop_buffers ();
373   gst_check_teardown_pad_by_name (src, "src");
374   gst_check_teardown_element (src);
375 }
376 
377 GST_END_TEST;
378 
379 
380 static Suite *
multifile_suite(void)381 multifile_suite (void)
382 {
383   Suite *s = suite_create ("multifile");
384   TCase *tc_chain = tcase_create ("general");
385 
386   suite_add_tcase (s, tc_chain);
387 
388   tcase_add_test (tc_chain, test_multifilesink_key_frame);
389   tcase_add_test (tc_chain, test_multifilesink_max_files);
390   tcase_add_test (tc_chain, test_multifilesink_key_unit);
391   tcase_add_test (tc_chain, test_multifilesrc);
392   tcase_add_test (tc_chain, test_multifilesrc_stop_index);
393 
394   return s;
395 }
396 
397 GST_CHECK_MAIN (multifile);
398