1089ed90113b9c8f5b7276d86d485353da89dd58
1 /* GStreamer
2 *
3 * unit testing helper lib
4 *
5 * Copyright (C) 2006 Andy Wingo <wingo at pobox.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., 59 Temple Place - Suite 330,
20 * Boston, MA 02111-1307, USA.
21 */
23 /**
24 * SECTION:gstcheckbufferstraw
25 * @short_description: Buffer interception code for GStreamer unit tests
26 *
27 * These macros and functions are for internal use of the unit tests found
28 * inside the 'check' directories of various GStreamer packages.
29 */
31 #include "gstbufferstraw.h"
33 static GCond *cond = NULL;
34 static GMutex *lock = NULL;
35 static GstBuffer *buf = NULL;
36 static gulong id;
38 /* called for every buffer. Waits until the global "buf" variable is unset,
39 * then sets it to the buffer received, and signals. */
40 static gboolean
41 buffer_probe (GstPad * pad, GstBuffer * buffer, gpointer unused)
42 {
43 g_mutex_lock (lock);
45 while (buf != NULL)
46 g_cond_wait (cond, lock);
48 /* increase the refcount because we store it globally for others to use */
49 buf = gst_buffer_ref (buffer);
51 g_cond_signal (cond);
53 g_mutex_unlock (lock);
55 return TRUE;
56 }
58 /**
59 * gst_buffer_straw_start_pipeline:
60 * @bin: the pipeline to run
61 * @pad: a pad on an element in @bin
62 *
63 * Sets up a pipeline for buffer sucking. This will allow you to call
64 * gst_buffer_straw_get_buffer() to access buffers as they pass over @pad.
65 *
66 * This function is normally used in unit tests that want to verify that a
67 * particular element is outputting correct buffers. For example, you would make
68 * a pipeline via gst_parse_launch(), pull out the pad you want to monitor, then
69 * call gst_buffer_straw_get_buffer() to get the buffers that pass through @pad.
70 * The pipeline will block until you have sucked off the buffers.
71 *
72 * This function will set the state of @bin to PLAYING; to clean up, be sure to
73 * call gst_buffer_straw_stop_pipeline().
74 *
75 * Note that you may not start two buffer straws at the same time. This function
76 * is intended for unit tests, not general API use. In fact it calls fail_if
77 * from libcheck, so you cannot use it outside unit tests.
78 */
79 void
80 gst_buffer_straw_start_pipeline (GstElement * bin, GstPad * pad)
81 {
82 GstStateChangeReturn ret;
84 id = gst_pad_add_buffer_probe (pad, G_CALLBACK (buffer_probe), NULL);
86 cond = g_cond_new ();
87 lock = g_mutex_new ();
89 ret = gst_element_set_state (bin, GST_STATE_PLAYING);
90 fail_if (ret == GST_STATE_CHANGE_FAILURE, "Could not start test pipeline");
91 if (ret == GST_STATE_CHANGE_ASYNC) {
92 ret = gst_element_get_state (bin, NULL, NULL, GST_CLOCK_TIME_NONE);
93 fail_if (ret != GST_STATE_CHANGE_SUCCESS, "Could not start test pipeline");
94 }
95 }
97 /**
98 * gst_buffer_straw_get_buffer:
99 * @bin: the pipeline previously started via gst_buffer_straw_start_pipeline()
100 * @pad: the pad previously passed to gst_buffer_straw_start_pipeline()
101 *
102 * Get one buffer from @pad. Implemented via buffer probes. This function will
103 * block until the pipeline passes a buffer over @pad, so for robust behavior
104 * in unit tests, you need to use check's timeout to fail out in the case that a
105 * buffer never arrives.
106 *
107 * You must have previously called gst_buffer_straw_start_pipeline() on
108 * @pipeline and @pad.
109 *
110 * Returns: the captured #GstBuffer.
111 */
112 GstBuffer *
113 gst_buffer_straw_get_buffer (GstElement * bin, GstPad * pad)
114 {
115 GstBuffer *ret;
117 g_mutex_lock (lock);
119 while (buf == NULL)
120 g_cond_wait (cond, lock);
122 ret = buf;
123 buf = NULL;
125 g_cond_signal (cond);
127 g_mutex_unlock (lock);
129 return ret;
130 }
132 /**
133 * gst_buffer_straw_stop_pipeline:
134 * @bin: the pipeline previously started via gst_buffer_straw_start_pipeline()
135 * @pad: the pad previously passed to gst_buffer_straw_start_pipeline()
136 *
137 * Set @bin to #GST_STATE_NULL and release resource allocated in
138 * gst_buffer_straw_start_pipeline().
139 *
140 * You must have previously called gst_buffer_straw_start_pipeline() on
141 * @pipeline and @pad.
142 */
143 void
144 gst_buffer_straw_stop_pipeline (GstElement * bin, GstPad * pad)
145 {
146 GstStateChangeReturn ret;
148 g_mutex_lock (lock);
149 if (buf)
150 gst_buffer_unref (buf);
151 buf = NULL;
152 gst_pad_remove_buffer_probe (pad, (guint) id);
153 id = 0;
154 g_cond_signal (cond);
155 g_mutex_unlock (lock);
157 ret = gst_element_set_state (bin, GST_STATE_NULL);
158 fail_if (ret == GST_STATE_CHANGE_FAILURE, "Could not stop test pipeline");
159 if (ret == GST_STATE_CHANGE_ASYNC) {
160 ret = gst_element_get_state (bin, NULL, NULL, GST_CLOCK_TIME_NONE);
161 fail_if (ret != GST_STATE_CHANGE_SUCCESS, "Could not stop test pipeline");
162 }
164 g_mutex_lock (lock);
165 if (buf)
166 gst_buffer_unref (buf);
167 buf = NULL;
168 g_mutex_unlock (lock);
170 g_mutex_free (lock);
171 g_cond_free (cond);
173 lock = NULL;
174 cond = NULL;
175 }