Port gtk-doc comments to their equivalent markdown syntax
[platform/upstream/gstreamer.git] / libs / gst / check / gstbufferstraw.c
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., 51 Franklin St, Fifth Floor,
20  * Boston, MA 02110-1301, USA.
21  */
22
23 /**
24  * SECTION:gstcheckbufferstraw
25  * @title: GstBufferStraw
26  * @short_description: Buffer interception code for GStreamer unit tests
27  *
28  * These macros and functions are for internal use of the unit tests found
29  * inside the 'check' directories of various GStreamer packages.
30  */
31
32 #include "gstbufferstraw.h"
33
34 static GCond cond;
35 static GMutex lock;
36 static GstBuffer *buf = NULL;
37 static gulong id;
38
39 /* called for every buffer.  Waits until the global "buf" variable is unset,
40  * then sets it to the buffer received, and signals. */
41 static GstPadProbeReturn
42 buffer_probe (GstPad * pad, GstPadProbeInfo * info, gpointer unused)
43 {
44   GstBuffer *buffer = GST_PAD_PROBE_INFO_BUFFER (info);
45
46   g_mutex_lock (&lock);
47
48   while (buf != NULL)
49     g_cond_wait (&cond, &lock);
50
51   /* increase the refcount because we store it globally for others to use */
52   buf = gst_buffer_ref (buffer);
53
54   g_cond_signal (&cond);
55
56   g_mutex_unlock (&lock);
57
58   return GST_PAD_PROBE_OK;
59 }
60
61 /**
62  * gst_buffer_straw_start_pipeline:
63  * @bin: the pipeline to run
64  * @pad: a pad on an element in @bin
65  *
66  * Sets up a pipeline for buffer sucking. This will allow you to call
67  * gst_buffer_straw_get_buffer() to access buffers as they pass over @pad.
68  *
69  * This function is normally used in unit tests that want to verify that a
70  * particular element is outputting correct buffers. For example, you would make
71  * a pipeline via gst_parse_launch(), pull out the pad you want to monitor, then
72  * call gst_buffer_straw_get_buffer() to get the buffers that pass through @pad.
73  * The pipeline will block until you have sucked off the buffers.
74  *
75  * This function will set the state of @bin to PLAYING; to clean up, be sure to
76  * call gst_buffer_straw_stop_pipeline().
77  *
78  * Note that you may not start two buffer straws at the same time. This function
79  * is intended for unit tests, not general API use. In fact it calls fail_if
80  * from libcheck, so you cannot use it outside unit tests.
81  */
82 void
83 gst_buffer_straw_start_pipeline (GstElement * bin, GstPad * pad)
84 {
85   GstStateChangeReturn ret;
86
87   id = gst_pad_add_probe (pad, GST_PAD_PROBE_TYPE_BUFFER,
88       buffer_probe, NULL, NULL);
89
90   ret = gst_element_set_state (bin, GST_STATE_PLAYING);
91   fail_if (ret == GST_STATE_CHANGE_FAILURE, "Could not start test pipeline");
92   if (ret == GST_STATE_CHANGE_ASYNC) {
93     ret = gst_element_get_state (bin, NULL, NULL, GST_CLOCK_TIME_NONE);
94     fail_if (ret != GST_STATE_CHANGE_SUCCESS, "Could not start test pipeline");
95   }
96 }
97
98 /**
99  * gst_buffer_straw_get_buffer:
100  * @bin: the pipeline previously started via gst_buffer_straw_start_pipeline()
101  * @pad: the pad previously passed to gst_buffer_straw_start_pipeline()
102  *
103  * Get one buffer from @pad. Implemented via buffer probes. This function will
104  * block until the pipeline passes a buffer over @pad, so for robust behavior
105  * in unit tests, you need to use check's timeout to fail out in the case that a
106  * buffer never arrives.
107  *
108  * You must have previously called gst_buffer_straw_start_pipeline() on
109  * @pipeline and @pad.
110  *
111  * Returns: the captured #GstBuffer.
112  */
113 GstBuffer *
114 gst_buffer_straw_get_buffer (GstElement * bin, GstPad * pad)
115 {
116   GstBuffer *ret;
117
118   g_mutex_lock (&lock);
119
120   while (buf == NULL)
121     g_cond_wait (&cond, &lock);
122
123   ret = buf;
124   buf = NULL;
125
126   g_cond_signal (&cond);
127
128   g_mutex_unlock (&lock);
129
130   return ret;
131 }
132
133 /**
134  * gst_buffer_straw_stop_pipeline:
135  * @bin: the pipeline previously started via gst_buffer_straw_start_pipeline()
136  * @pad: the pad previously passed to gst_buffer_straw_start_pipeline()
137  *
138  * Set @bin to #GST_STATE_NULL and release resource allocated in
139  * gst_buffer_straw_start_pipeline().
140  *
141  * You must have previously called gst_buffer_straw_start_pipeline() on
142  * @pipeline and @pad.
143  */
144 void
145 gst_buffer_straw_stop_pipeline (GstElement * bin, GstPad * pad)
146 {
147   GstStateChangeReturn ret;
148
149   g_mutex_lock (&lock);
150   if (buf)
151     gst_buffer_unref (buf);
152   buf = NULL;
153   gst_pad_remove_probe (pad, (guint) id);
154   id = 0;
155   g_cond_signal (&cond);
156   g_mutex_unlock (&lock);
157
158   ret = gst_element_set_state (bin, GST_STATE_NULL);
159   fail_if (ret == GST_STATE_CHANGE_FAILURE, "Could not stop test pipeline");
160   if (ret == GST_STATE_CHANGE_ASYNC) {
161     ret = gst_element_get_state (bin, NULL, NULL, GST_CLOCK_TIME_NONE);
162     fail_if (ret != GST_STATE_CHANGE_SUCCESS, "Could not stop test pipeline");
163   }
164
165   g_mutex_lock (&lock);
166   if (buf)
167     gst_buffer_unref (buf);
168   buf = NULL;
169   g_mutex_unlock (&lock);
170 }