1 /* GStreamer
2 * Copyright (C) 2010 David Schleef <ds@schleef.org>
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
18 */
19
20
21 #ifdef HAVE_CONFIG_H
22 #include "config.h"
23 #endif
24
25 #include <gst/gst.h>
26 #include <gst/gst.h>
27 #include "gstdebugutilselements.h"
28 #include "gstcapsdebug.h"
29
30 GST_DEBUG_CATEGORY_STATIC (gst_caps_debug_debug);
31 #define GST_CAT_DEFAULT gst_caps_debug_debug
32
33 /* prototypes */
34
35
36 static void gst_caps_debug_dispose (GObject * object);
37 static void gst_caps_debug_finalize (GObject * object);
38
39 static GstFlowReturn gst_caps_debug_sink_chain (GstPad * pad,
40 GstBuffer * buffer);
41 static GstCaps *gst_caps_debug_getcaps (GstPad * pad);
42 static gboolean gst_caps_debug_acceptcaps (GstPad * pad, GstCaps * caps);
43 static GstFlowReturn gst_caps_debug_bufferalloc (GstPad * pad,
44 guint64 offset, guint size, GstCaps * caps, GstBuffer ** buf);
45
46 static GstStateChangeReturn
47 gst_caps_debug_change_state (GstElement * element, GstStateChange transition);
48
49 /* pad templates */
50
51 static GstStaticPadTemplate gst_caps_debug_sink_template =
52 GST_STATIC_PAD_TEMPLATE ("sink",
53 GST_PAD_SINK,
54 GST_PAD_ALWAYS,
55 GST_STATIC_CAPS_ANY);
56
57 static GstStaticPadTemplate gst_caps_debug_src_template =
58 GST_STATIC_PAD_TEMPLATE ("src",
59 GST_PAD_SRC,
60 GST_PAD_ALWAYS,
61 GST_STATIC_CAPS_ANY);
62
63 /* class initialization */
64
65 #define gst_caps_debug_parent_class parent_class
66 G_DEFINE_TYPE (GstCapsDebug, gst_caps_debug, GST_TYPE_ELEMENT);
67 GST_ELEMENT_REGISTER_DEFINE (capsdebug, "capsdebug",
68 GST_RANK_PRIMARY, gst_caps_debug_get_type ());
69
70 static void
gst_caps_debug_class_init(GstCapsDebugClass * klass)71 gst_caps_debug_class_init (GstCapsDebugClass * klass)
72 {
73 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
74 GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
75
76 gobject_class->dispose = gst_caps_debug_dispose;
77 gobject_class->finalize = gst_caps_debug_finalize;
78 element_class->change_state = GST_DEBUG_FUNCPTR (gst_caps_debug_change_state);
79
80 GST_DEBUG_CATEGORY_INIT (gst_caps_debug_debug, "capsdebug", 0,
81 "debug category for capsdebug element");
82
83 gst_element_class_add_static_pad_template (element_class,
84 &gst_caps_debug_src_template);
85 gst_element_class_add_static_pad_template (element_class,
86 &gst_caps_debug_sink_template);
87
88 gst_element_class_set_static_metadata (element_class, "Caps debug",
89 "Generic", "Debug caps negotiation", "David Schleef <ds@schleef.org>");
90 }
91
92 static void
gst_caps_debug_init(GstCapsDebug * capsdebug)93 gst_caps_debug_init (GstCapsDebug * capsdebug)
94 {
95
96 capsdebug->srcpad =
97 gst_pad_new_from_static_template (&gst_caps_debug_src_template, "src");
98 gst_pad_set_getcaps_function (capsdebug->srcpad,
99 GST_DEBUG_FUNCPTR (gst_caps_debug_getcaps));
100 gst_pad_set_acceptcaps_function (capsdebug->srcpad,
101 GST_DEBUG_FUNCPTR (gst_caps_debug_acceptcaps));
102 gst_element_add_pad (GST_ELEMENT (capsdebug), capsdebug->srcpad);
103
104 capsdebug->sinkpad =
105 gst_pad_new_from_static_template (&gst_caps_debug_sink_template, "sink");
106 gst_pad_set_chain_function (capsdebug->sinkpad,
107 GST_DEBUG_FUNCPTR (gst_caps_debug_sink_chain));
108 gst_pad_set_bufferalloc_function (capsdebug->sinkpad,
109 GST_DEBUG_FUNCPTR (gst_caps_debug_bufferalloc));
110 gst_pad_set_getcaps_function (capsdebug->sinkpad,
111 GST_DEBUG_FUNCPTR (gst_caps_debug_getcaps));
112 gst_pad_set_acceptcaps_function (capsdebug->sinkpad,
113 GST_DEBUG_FUNCPTR (gst_caps_debug_acceptcaps));
114 gst_element_add_pad (GST_ELEMENT (capsdebug), capsdebug->sinkpad);
115
116 }
117
118 void
gst_caps_debug_dispose(GObject * object)119 gst_caps_debug_dispose (GObject * object)
120 {
121 /* clean up as possible. may be called multiple times */
122
123 G_OBJECT_CLASS (parent_class)->dispose (object);
124 }
125
126 void
gst_caps_debug_finalize(GObject * object)127 gst_caps_debug_finalize (GObject * object)
128 {
129 /* clean up object here */
130
131 G_OBJECT_CLASS (parent_class)->finalize (object);
132 }
133
134
135
136 static GstStateChangeReturn
gst_caps_debug_change_state(GstElement * element,GstStateChange transition)137 gst_caps_debug_change_state (GstElement * element, GstStateChange transition)
138 {
139 GstStateChangeReturn ret;
140
141 ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
142
143 return ret;
144 }
145
146
147 static GstFlowReturn
gst_caps_debug_sink_chain(GstPad * pad,GstBuffer * buffer)148 gst_caps_debug_sink_chain (GstPad * pad, GstBuffer * buffer)
149 {
150 GstFlowReturn ret;
151 GstCapsDebug *capsdebug;
152
153 capsdebug = GST_CAPS_DEBUG (gst_pad_get_parent (pad));
154
155 ret = gst_pad_push (capsdebug->srcpad, buffer);
156
157 gst_object_unref (capsdebug);
158
159 return ret;
160 }
161
162 #define THISPAD ((pad == capsdebug->srcpad) ? "downstream" : "upstream")
163 #define OTHERPAD ((pad == capsdebug->srcpad) ? "upstream" : "downstream")
164
165 static GstCaps *
gst_caps_debug_getcaps(GstPad * pad)166 gst_caps_debug_getcaps (GstPad * pad)
167 {
168 GstCaps *caps;
169 GstCapsDebug *capsdebug;
170 gchar *s;
171 GstPad *otherpad;
172
173 capsdebug = GST_CAPS_DEBUG (gst_pad_get_parent (pad));
174 otherpad =
175 (pad == capsdebug->srcpad) ? capsdebug->sinkpad : capsdebug->srcpad;
176
177 GST_INFO ("%s called getcaps", THISPAD);
178
179 caps = gst_pad_peer_get_caps (otherpad);
180
181 s = gst_caps_to_string (caps);
182 GST_INFO ("%s returned %s", OTHERPAD, s);
183 g_free (s);
184
185 if (caps == NULL)
186 caps = gst_caps_new_any ();
187
188 gst_object_unref (capsdebug);
189
190 return caps;
191 }
192
193
194 static gboolean
gst_caps_debug_acceptcaps(GstPad * pad,GstCaps * caps)195 gst_caps_debug_acceptcaps (GstPad * pad, GstCaps * caps)
196 {
197 GstCapsDebug *capsdebug;
198 gchar *s;
199 gboolean ret;
200 GstPad *otherpad;
201
202 capsdebug = GST_CAPS_DEBUG (gst_pad_get_parent (pad));
203 otherpad =
204 (pad == capsdebug->srcpad) ? capsdebug->sinkpad : capsdebug->srcpad;
205
206 s = gst_caps_to_string (caps);
207 GST_INFO ("%s called acceptcaps with %s", THISPAD, s);
208 g_free (s);
209
210 ret = gst_pad_peer_accept_caps (otherpad, caps);
211
212 GST_INFO ("%s returned %s", OTHERPAD, ret ? "TRUE" : "FALSE");
213
214 gst_object_unref (capsdebug);
215
216 return ret;
217 }
218
219 static GstFlowReturn
gst_caps_debug_bufferalloc(GstPad * pad,guint64 offset,guint size,GstCaps * caps,GstBuffer ** buf)220 gst_caps_debug_bufferalloc (GstPad * pad, guint64 offset, guint size,
221 GstCaps * caps, GstBuffer ** buf)
222 {
223 GstCapsDebug *capsdebug;
224 gchar *s;
225 gchar *t;
226 GstFlowReturn ret;
227 GstPad *otherpad;
228 gboolean newcaps;
229
230 capsdebug = GST_CAPS_DEBUG (gst_pad_get_parent (pad));
231 otherpad =
232 (pad == capsdebug->srcpad) ? capsdebug->sinkpad : capsdebug->srcpad;
233
234 newcaps = (caps != GST_PAD_CAPS (pad));
235
236 if (newcaps) {
237 s = gst_caps_to_string (caps);
238 GST_INFO ("%s called bufferalloc with new caps, offset=%" G_GUINT64_FORMAT
239 " size=%d caps=%s", THISPAD, offset, size, s);
240 g_free (s);
241 }
242
243 ret = gst_pad_alloc_buffer_and_set_caps (otherpad, offset, size, caps, buf);
244
245 if (newcaps) {
246 GST_INFO ("%s returned %s", OTHERPAD, gst_flow_get_name (ret));
247 }
248 if (caps != GST_BUFFER_CAPS (*buf)) {
249 s = gst_caps_to_string (caps);
250 t = gst_caps_to_string (GST_BUFFER_CAPS (*buf));
251 GST_INFO
252 ("%s returned from bufferalloc with different caps, requested=%s returned=%s",
253 OTHERPAD, s, t);
254 g_free (s);
255 g_free (t);
256 }
257
258 gst_object_unref (capsdebug);
259
260 return ret;
261 }
262