• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* GStreamer
2  *
3  * some unit tests for GstBaseTransform
4  *
5  * Copyright (C) 2008 Wim Taymans <wim.taymans@gmail.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 #ifdef HAVE_CONFIG_H
23 #include "config.h"
24 #endif
25 
26 #include <gst/base/gstbasetransform.h>
27 
28 typedef struct
29 {
30   GstPad *srcpad;
31   GstPad *sinkpad;
32   GList *events;
33   GList *buffers;
34   GstElement *trans;
35   GstBaseTransformClass *klass;
36 } TestTransData;
37 
38 static GstStaticPadTemplate gst_test_trans_src_template =
39 GST_STATIC_PAD_TEMPLATE ("src",
40     GST_PAD_SRC,
41     GST_PAD_ALWAYS,
42     GST_STATIC_CAPS ("foo/x-bar")
43     );
44 
45 static GstStaticPadTemplate gst_test_trans_sink_template =
46 GST_STATIC_PAD_TEMPLATE ("sink",
47     GST_PAD_SINK,
48     GST_PAD_ALWAYS,
49     GST_STATIC_CAPS ("foo/x-bar")
50     );
51 
52 typedef struct _GstTestTrans GstTestTrans;
53 typedef struct _GstTestTransClass GstTestTransClass;
54 
55 #define GST_TEST_TRANS(obj) ((GstTestTrans *)(obj))
56 
57 struct _GstTestTrans
58 {
59   GstBaseTransform element;
60 
61   TestTransData *data;
62 };
63 
64 struct _GstTestTransClass
65 {
66   GstBaseTransformClass parent_class;
67 };
68 
69 static GstFlowReturn (*klass_transform) (GstBaseTransform * trans,
70     GstBuffer * inbuf, GstBuffer * outbuf) = NULL;
71 static GstFlowReturn (*klass_transform_ip) (GstBaseTransform * trans,
72     GstBuffer * buf) = NULL;
73 static gboolean (*klass_set_caps) (GstBaseTransform * trans, GstCaps * incaps,
74     GstCaps * outcaps) = NULL;
75 static GstCaps *(*klass_transform_caps) (GstBaseTransform * trans,
76     GstPadDirection direction, GstCaps * caps, GstCaps * filter) = NULL;
77 static gboolean (*klass_transform_size) (GstBaseTransform * trans,
78     GstPadDirection direction, GstCaps * caps, gsize size, GstCaps * othercaps,
79     gsize * othersize) = NULL;
80 static gboolean klass_passthrough_on_same_caps = FALSE;
81 GstFlowReturn (*klass_submit_input_buffer) (GstBaseTransform * trans,
82     gboolean is_discont, GstBuffer * input) = NULL;
83 GstFlowReturn (*klass_generate_output) (GstBaseTransform * trans,
84     GstBuffer ** outbuf) = NULL;
85 
86 static GstStaticPadTemplate *sink_template = &gst_test_trans_sink_template;
87 static GstStaticPadTemplate *src_template = &gst_test_trans_src_template;
88 
89 static void
gst_test_trans_class_init(GstTestTransClass * klass)90 gst_test_trans_class_init (GstTestTransClass * klass)
91 {
92   GstElementClass *element_class;
93   GstBaseTransformClass *trans_class;
94 
95   element_class = (GstElementClass *) klass;
96   trans_class = (GstBaseTransformClass *) klass;
97 
98   gst_element_class_set_metadata (element_class, "TestTrans",
99       "Filter/Test", "Test transform", "Wim Taymans <wim.taymans@gmail.com>");
100 
101   gst_element_class_add_static_pad_template (element_class, sink_template);
102   gst_element_class_add_static_pad_template (element_class, src_template);
103 
104   GST_INFO ("setting up %s", g_type_name (((GTypeClass *) klass)->g_type));
105 
106   trans_class->passthrough_on_same_caps = klass_passthrough_on_same_caps;
107   if (klass_transform_ip != NULL)
108     trans_class->transform_ip = klass_transform_ip;
109   if (klass_transform != NULL)
110     trans_class->transform = klass_transform;
111   if (klass_transform_caps != NULL)
112     trans_class->transform_caps = klass_transform_caps;
113   if (klass_transform_size != NULL)
114     trans_class->transform_size = klass_transform_size;
115   if (klass_set_caps != NULL)
116     trans_class->set_caps = klass_set_caps;
117   if (klass_submit_input_buffer != NULL)
118     trans_class->submit_input_buffer = klass_submit_input_buffer;
119   if (klass_generate_output)
120     trans_class->generate_output = klass_generate_output;
121 }
122 
123 static void
gst_test_trans_init(GstTestTrans * this)124 gst_test_trans_init (GstTestTrans * this)
125 {
126 }
127 
128 static void
gst_test_trans_set_data(GstTestTrans * this,TestTransData * data)129 gst_test_trans_set_data (GstTestTrans * this, TestTransData * data)
130 {
131   this->data = data;
132 }
133 
134 static GstFlowReturn
result_sink_chain(GstPad * pad,GstObject * parent,GstBuffer * buffer)135 result_sink_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer)
136 {
137   TestTransData *data;
138 
139   data = gst_pad_get_element_private (pad);
140 
141   data->buffers = g_list_append (data->buffers, buffer);
142 
143   return GST_FLOW_OK;
144 }
145 
146 #if 0
147 static GstFlowReturn
148 result_buffer_alloc (GstPad * pad, guint64 offset, guint size, GstCaps * caps,
149     GstBuffer ** buf)
150 {
151   GstFlowReturn res;
152   TestTransData *data;
153 
154   data = gst_pad_get_element_private (pad);
155 
156   *buf = gst_buffer_new_and_alloc (size);
157   gst_buffer_set_caps (*buf, caps);
158   res = GST_FLOW_OK;
159 
160   return res;
161 }
162 #endif
163 
164 static TestTransData *
gst_test_trans_new(void)165 gst_test_trans_new (void)
166 {
167   TestTransData *res;
168   GstPad *tmp;
169   GstPadTemplate *templ;
170   GType type;
171 
172   /* we register a new sub-class for every test-run, so the class init
173    * function is called for every test run and can be set up properly
174    * even with CK_FORK=no */
175   {
176     static gint counter = 0;
177     gchar name[100];
178 
179     g_snprintf (name, sizeof (name), "GstTestTrans%d", ++counter);
180 
181     type = g_type_register_static_simple (GST_TYPE_BASE_TRANSFORM, name,
182         sizeof (GstTestTransClass), (GClassInitFunc) gst_test_trans_class_init,
183         sizeof (GstTestTrans), (GInstanceInitFunc) gst_test_trans_init, 0);
184   }
185 
186   res = g_new0 (TestTransData, 1);
187   res->trans = g_object_new (type, NULL);
188 
189   templ = gst_static_pad_template_get (sink_template);
190   templ->direction = GST_PAD_SRC;
191   res->srcpad = gst_pad_new_from_template (templ, "src");
192   gst_object_unref (templ);
193 
194   templ = gst_static_pad_template_get (src_template);
195   templ->direction = GST_PAD_SINK;
196   res->sinkpad = gst_pad_new_from_template (templ, "sink");
197   gst_object_unref (templ);
198 
199   res->klass = GST_BASE_TRANSFORM_GET_CLASS (res->trans);
200 
201   gst_test_trans_set_data (GST_TEST_TRANS (res->trans), res);
202   gst_pad_set_element_private (res->sinkpad, res);
203 
204   gst_pad_set_chain_function (res->sinkpad, result_sink_chain);
205 
206   tmp = gst_element_get_static_pad (res->trans, "sink");
207   gst_pad_link (res->srcpad, tmp);
208   gst_object_unref (tmp);
209 
210   tmp = gst_element_get_static_pad (res->trans, "src");
211   gst_pad_link (tmp, res->sinkpad);
212   gst_object_unref (tmp);
213 
214   gst_pad_set_active (res->sinkpad, TRUE);
215   gst_element_set_state (res->trans, GST_STATE_PAUSED);
216   gst_pad_set_active (res->srcpad, TRUE);
217 
218   gst_pad_push_event (res->srcpad, gst_event_new_stream_start ("test"));
219 
220   return res;
221 }
222 
223 static void
gst_test_trans_free(TestTransData * data)224 gst_test_trans_free (TestTransData * data)
225 {
226   GstPad *tmp;
227 
228   gst_pad_set_active (data->sinkpad, FALSE);
229   gst_element_set_state (data->trans, GST_STATE_NULL);
230   gst_pad_set_active (data->srcpad, FALSE);
231 
232   tmp = gst_element_get_static_pad (data->trans, "src");
233   gst_pad_unlink (tmp, data->sinkpad);
234   gst_object_unref (tmp);
235 
236   tmp = gst_element_get_static_pad (data->trans, "sink");
237   gst_pad_link (data->srcpad, tmp);
238   gst_object_unref (tmp);
239 
240   gst_object_unref (data->srcpad);
241   gst_object_unref (data->sinkpad);
242   gst_object_unref (data->trans);
243 
244   g_free (data);
245 }
246 
247 static GstFlowReturn
gst_test_trans_push(TestTransData * data,GstBuffer * buffer)248 gst_test_trans_push (TestTransData * data, GstBuffer * buffer)
249 {
250   GstFlowReturn ret;
251 
252   ret = gst_pad_push (data->srcpad, buffer);
253 
254   return ret;
255 }
256 
257 static GstBuffer *
gst_test_trans_pop(TestTransData * data)258 gst_test_trans_pop (TestTransData * data)
259 {
260   GstBuffer *ret;
261 
262   if (data->buffers) {
263     ret = data->buffers->data;
264     data->buffers = g_list_delete_link (data->buffers, data->buffers);
265   } else {
266     ret = NULL;
267   }
268   return ret;
269 }
270 
271 static gboolean
gst_test_trans_setcaps(TestTransData * data,GstCaps * caps)272 gst_test_trans_setcaps (TestTransData * data, GstCaps * caps)
273 {
274   return gst_pad_set_caps (data->srcpad, caps);
275 }
276 
277 static gboolean
gst_test_trans_push_segment(TestTransData * data)278 gst_test_trans_push_segment (TestTransData * data)
279 {
280   GstSegment segment;
281 
282   gst_segment_init (&segment, GST_FORMAT_TIME);
283 
284   return gst_pad_push_event (data->srcpad, gst_event_new_segment (&segment));
285 }
286