5 * Copyright (C) <2007> Wim Taymans <wim dot taymans at gmail dot com>
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.
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.
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., 59 Temple Place - Suite 330,
20 * Boston, MA 02111-1307, USA.
24 #include <sys/types.h>
28 #include <gst/check/gstcheck.h>
31 handoff (GstElement * fakesink, GstBuffer * buf, GstPad * pad, guint * count)
36 /* construct fakesrc num-buffers=3 ! tee name=t ! queue ! fakesink t. ! queue !
37 * fakesink. Each fakesink should exactly receive 3 buffers.
39 GST_START_TEST (test_num_buffers)
41 #define NUM_SUBSTREAMS 15
43 GstElement *pipeline, *src, *tee;
44 GstElement *queues[NUM_SUBSTREAMS];
45 GstElement *sinks[NUM_SUBSTREAMS];
46 GstPad *req_pads[NUM_SUBSTREAMS];
47 guint counts[NUM_SUBSTREAMS];
52 pipeline = gst_pipeline_new ("pipeline");
53 src = gst_check_setup_element ("fakesrc");
54 g_object_set (src, "num-buffers", NUM_BUFFERS, NULL);
55 tee = gst_check_setup_element ("tee");
56 fail_unless (gst_bin_add (GST_BIN (pipeline), src));
57 fail_unless (gst_bin_add (GST_BIN (pipeline), tee));
58 fail_unless (gst_element_link (src, tee));
60 for (i = 0; i < NUM_SUBSTREAMS; ++i) {
66 queues[i] = gst_check_setup_element ("queue");
67 g_snprintf (name, 32, "queue%d", i);
68 gst_object_set_name (GST_OBJECT (queues[i]), name);
69 fail_unless (gst_bin_add (GST_BIN (pipeline), queues[i]));
71 sinks[i] = gst_check_setup_element ("fakesink");
72 g_snprintf (name, 32, "sink%d", i);
73 gst_object_set_name (GST_OBJECT (sinks[i]), name);
74 fail_unless (gst_bin_add (GST_BIN (pipeline), sinks[i]));
75 fail_unless (gst_element_link (queues[i], sinks[i]));
76 g_object_set (sinks[i], "signal-handoffs", TRUE, NULL);
77 g_signal_connect (sinks[i], "handoff", (GCallback) handoff, &counts[i]);
79 req_pads[i] = gst_element_get_request_pad (tee, "src%d");
80 fail_unless (req_pads[i] != NULL);
82 qpad = gst_element_get_pad (queues[i], "sink");
83 fail_unless_equals_int (gst_pad_link (req_pads[i], qpad), GST_PAD_LINK_OK);
84 gst_object_unref (qpad);
87 bus = gst_element_get_bus (pipeline);
88 fail_if (bus == NULL);
89 gst_element_set_state (pipeline, GST_STATE_PLAYING);
91 msg = gst_bus_poll (bus, GST_MESSAGE_EOS | GST_MESSAGE_ERROR, -1);
92 fail_if (GST_MESSAGE_TYPE (msg) != GST_MESSAGE_EOS);
93 gst_message_unref (msg);
95 for (i = 0; i < NUM_SUBSTREAMS; ++i) {
96 fail_unless_equals_int (counts[i], NUM_BUFFERS);
99 gst_element_set_state (pipeline, GST_STATE_NULL);
100 gst_object_unref (bus);
102 for (i = 0; i < NUM_SUBSTREAMS; ++i) {
103 gst_element_release_request_pad (tee, req_pads[i]);
104 gst_object_unref (req_pads[i]);
106 gst_object_unref (pipeline);
111 /* we use fakesrc ! tee ! fakesink and then randomly request/release and link
112 * some pads from tee. This should happily run without any errors. */
113 GST_START_TEST (test_stress)
115 GstElement *pipeline;
122 /* Pump 1000 buffers (10 bytes each) per second through tee for 5 secs */
123 desc = "fakesrc datarate=10000 sizemin=10 sizemax=10 num-buffers=5000 ! "
124 "video/x-raw-rgb,framerate=25/1 ! tee name=t ! "
125 "queue max-size-buffers=2 ! fakesink sync=true";
127 pipeline = gst_parse_launch (desc, NULL);
128 fail_if (pipeline == NULL);
130 tee = gst_bin_get_by_name (GST_BIN (pipeline), "t");
131 fail_if (tee == NULL);
133 /* bring the pipeline to PLAYING, then start switching */
134 bus = gst_element_get_bus (pipeline);
135 fail_if (bus == NULL);
136 gst_element_set_state (pipeline, GST_STATE_PLAYING);
137 /* Wait for the pipeline to hit playing so that parse_launch can do the
138 * initial link, otherwise we perform linking from multiple threads and cause
140 gst_element_get_state (pipeline, NULL, NULL, GST_CLOCK_TIME_NONE);
142 for (i = 0; i < 50000; i++) {
145 pad = gst_element_get_request_pad (tee, "src%d");
146 gst_element_release_request_pad (tee, pad);
147 gst_object_unref (pad);
149 if ((msg = gst_bus_poll (bus, GST_MESSAGE_EOS | GST_MESSAGE_ERROR, 0)))
153 /* now wait for completion or error */
155 msg = gst_bus_poll (bus, GST_MESSAGE_EOS | GST_MESSAGE_ERROR, -1);
156 fail_if (GST_MESSAGE_TYPE (msg) != GST_MESSAGE_EOS);
157 gst_message_unref (msg);
159 gst_element_set_state (pipeline, GST_STATE_NULL);
160 gst_object_unref (tee);
161 gst_object_unref (bus);
162 gst_object_unref (pipeline);
170 Suite *s = suite_create ("tee");
171 TCase *tc_chain = tcase_create ("general");
173 suite_add_tcase (s, tc_chain);
174 tcase_add_test (tc_chain, test_num_buffers);
175 tcase_add_test (tc_chain, test_stress);
180 GST_CHECK_MAIN (tee);