close #333784 unref the result of gst_pad_get_parent() by: Christophe Fergeau.
[platform/upstream/gstreamer.git] / gst / debug / negotiation.c
1 /*
2  * GStreamer
3  * Copyright (C) 1999-2001 Erik Walthinsen <omega@cse.ogi.edu>
4  * Copyright (C) 2002 David A. Schleef <ds@schleef.org>
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Library General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Library General Public License for more details.
15  *
16  * You should have received a copy of the GNU Library General Public
17  * License along with this library; if not, write to the
18  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19  * Boston, MA 02111-1307, USA.
20  */
21
22 #ifdef HAVE_CONFIG_H
23 #include "config.h"
24 #endif
25 #include <gst/gst.h>
26
27 #include <string.h>
28 #include <unistd.h>
29 #include <sys/mman.h>
30
31
32 #define GST_TYPE_NEGOTIATION \
33   (gst_gst_negotiation_get_type())
34 #define GST_NEGOTIATION(obj) \
35   (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_NEGOTIATION,GstNegotiation))
36 #define GST_NEGOTIATION_CLASS(klass) \
37   (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_NEGOTIATION,GstNegotiation))
38 #define GST_IS_NEGOTIATION(obj) \
39   (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_NEGOTIATION))
40 #define GST_IS_NEGOTIATION_CLASS(obj) \
41   (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_NEGOTIATION))
42
43 typedef struct _GstNegotiation GstNegotiation;
44 typedef struct _GstNegotiationClass GstNegotiationClass;
45
46 struct _GstNegotiation
47 {
48   GstElement element;
49
50   GstPad *sinkpad, *srcpad;
51
52   GstCaps *caps;
53 };
54
55 struct _GstNegotiationClass
56 {
57   GstElementClass parent_class;
58 };
59
60 GType gst_gst_negotiation_get_type (void);
61
62
63 static GstElementDetails plugin_details = {
64   "Negotiation",
65   "Testing",
66   "This element acts like identity, except that one can control how "
67       "negotiation works",
68   "David A. Schleef <ds@schleef.org>",
69 };
70
71 /* Filter signals and args */
72 enum
73 {
74   /* FILL ME */
75   LAST_SIGNAL
76 };
77
78 enum
79 {
80   ARG_0,
81   ARG_ALLOWED_CAPS
82 };
83
84 static GstStaticPadTemplate gst_negotiation_sink_factory =
85 GST_STATIC_PAD_TEMPLATE ("sink",
86     GST_PAD_SINK,
87     GST_PAD_ALWAYS,
88     GST_STATIC_CAPS_ANY);
89
90 static GstStaticPadTemplate gst_negotiation_src_factory =
91 GST_STATIC_PAD_TEMPLATE ("src",
92     GST_PAD_SRC,
93     GST_PAD_ALWAYS,
94     GST_STATIC_CAPS_ANY);
95
96 static void gst_negotiation_base_init (gpointer g_class);
97 static void gst_negotiation_class_init (GstNegotiationClass * klass);
98 static void gst_negotiation_init (GstNegotiation * filter);
99
100 static GstCaps *gst_negotiation_getcaps (GstPad * pad);
101 static GstPadLinkReturn gst_negotiation_pad_link (GstPad * pad,
102     const GstCaps * caps);
103
104 static void gst_negotiation_set_property (GObject * object, guint prop_id,
105     const GValue * value, GParamSpec * pspec);
106 static void gst_negotiation_get_property (GObject * object, guint prop_id,
107     GValue * value, GParamSpec * pspec);
108
109 static void gst_negotiation_update_caps (GstNegotiation * negotiation);
110 static void gst_negotiation_chain (GstPad * pad, GstData * _data);
111
112 static GstElementClass *parent_class = NULL;
113
114 typedef struct _GstFencedBuffer GstFencedBuffer;
115 struct _GstFencedBuffer
116 {
117   GstBuffer buffer;
118   void *region;
119   unsigned int length;
120 };
121
122 GType
123 gst_gst_negotiation_get_type (void)
124 {
125   static GType plugin_type = 0;
126
127   if (!plugin_type) {
128     static const GTypeInfo plugin_info = {
129       sizeof (GstNegotiationClass),
130       gst_negotiation_base_init,
131       NULL,
132       (GClassInitFunc) gst_negotiation_class_init,
133       NULL,
134       NULL,
135       sizeof (GstNegotiation),
136       0,
137       (GInstanceInitFunc) gst_negotiation_init,
138     };
139
140     plugin_type = g_type_register_static (GST_TYPE_ELEMENT,
141         "GstNegotiation", &plugin_info, 0);
142   }
143   return plugin_type;
144 }
145
146 static void
147 gst_negotiation_base_init (gpointer g_class)
148 {
149   GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
150
151   gst_element_class_add_pad_template (element_class,
152       gst_static_pad_template_get (&gst_negotiation_sink_factory));
153   gst_element_class_add_pad_template (element_class,
154       gst_static_pad_template_get (&gst_negotiation_src_factory));
155   gst_element_class_set_details (element_class, &plugin_details);
156 }
157
158 static void
159 gst_negotiation_class_init (GstNegotiationClass * klass)
160 {
161   GObjectClass *gobject_class;
162   GstElementClass *gstelement_class;
163
164   gobject_class = (GObjectClass *) klass;
165   gstelement_class = (GstElementClass *) klass;
166
167   parent_class = g_type_class_ref (GST_TYPE_ELEMENT);
168
169   gobject_class->set_property = gst_negotiation_set_property;
170   gobject_class->get_property = gst_negotiation_get_property;
171
172   g_object_class_install_property (gobject_class, ARG_ALLOWED_CAPS,
173       g_param_spec_boxed ("allowed-caps", "Caps",
174           "The range of formats allowed by " "this element's peers",
175           GST_TYPE_CAPS, G_PARAM_READABLE));
176 }
177
178 static void
179 gst_negotiation_init (GstNegotiation * filter)
180 {
181   filter->sinkpad =
182       gst_pad_new_from_template (gst_static_pad_template_get
183       (&gst_negotiation_sink_factory), "sink");
184   gst_pad_set_getcaps_function (filter->sinkpad, gst_negotiation_getcaps);
185   gst_pad_set_link_function (filter->sinkpad, gst_negotiation_pad_link);
186   filter->srcpad =
187       gst_pad_new_from_template (gst_static_pad_template_get
188       (&gst_negotiation_src_factory), "src");
189   gst_pad_set_getcaps_function (filter->srcpad, gst_negotiation_getcaps);
190   gst_pad_set_link_function (filter->srcpad, gst_negotiation_pad_link);
191
192   gst_element_add_pad (GST_ELEMENT (filter), filter->sinkpad);
193   gst_element_add_pad (GST_ELEMENT (filter), filter->srcpad);
194   gst_pad_set_chain_function (filter->sinkpad, gst_negotiation_chain);
195 }
196
197 static GstCaps *
198 gst_negotiation_getcaps (GstPad * pad)
199 {
200   GstNegotiation *negotiation = GST_NEGOTIATION (gst_pad_get_parent (pad));
201   GstPad *otherpad;
202   GstCaps *caps;
203
204   otherpad = (pad == negotiation->sinkpad) ? negotiation->srcpad :
205       negotiation->sinkpad;
206
207   caps = gst_pad_get_allowed_caps (otherpad);
208
209   GST_ERROR ("getcaps called on %" GST_PTR_FORMAT ", returning %"
210       GST_PTR_FORMAT, pad, caps);
211
212   gst_negotiation_update_caps (negotiation);
213   gst_object_unref (negotiation);
214
215   return caps;
216 }
217
218 static GstPadLinkReturn
219 gst_negotiation_pad_link (GstPad * pad, const GstCaps * caps)
220 {
221   GstNegotiation *negotiation = GST_NEGOTIATION (gst_pad_get_parent (pad));
222   GstPad *otherpad;
223   GstPadLinkReturn ret;
224
225   otherpad = (pad == negotiation->sinkpad) ? negotiation->srcpad :
226       negotiation->sinkpad;
227
228   ret = gst_pad_try_set_caps (otherpad, caps);
229
230   GST_ERROR ("pad_link called on %" GST_PTR_FORMAT " with caps %"
231       GST_PTR_FORMAT ", returning %d", pad, caps, ret);
232   gst_object_unref (negotiation);
233
234   return ret;
235 }
236
237 static void
238 gst_negotiation_update_caps (GstNegotiation * negotiation)
239 {
240   GstCaps *srccaps;
241   GstCaps *sinkcaps;
242   GstCaps *icaps;
243
244   srccaps = gst_pad_get_allowed_caps (negotiation->srcpad);
245   sinkcaps = gst_pad_get_allowed_caps (negotiation->sinkpad);
246
247   icaps = gst_caps_intersect (srccaps, sinkcaps);
248   gst_caps_free (srccaps);
249   gst_caps_free (sinkcaps);
250
251   gst_caps_replace (&negotiation->caps, icaps);
252   g_object_notify (G_OBJECT (negotiation), "allowed-caps");
253   g_print ("notify %s", gst_caps_to_string (icaps));
254 }
255
256 static void
257 gst_negotiation_chain (GstPad * pad, GstData * _data)
258 {
259   GstNegotiation *negotiation = GST_NEGOTIATION (gst_pad_get_parent (pad));
260
261   gst_pad_push (negotiation->srcpad, _data);
262   gst_object_unref (negotiation);
263 }
264
265 static void
266 gst_negotiation_set_property (GObject * object, guint prop_id,
267     const GValue * value, GParamSpec * pspec)
268 {
269   GstNegotiation *filter;
270
271   g_return_if_fail (GST_IS_NEGOTIATION (object));
272   filter = GST_NEGOTIATION (object);
273
274   switch (prop_id) {
275     default:
276       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
277       break;
278   }
279 }
280
281 static void
282 gst_negotiation_get_property (GObject * object, guint prop_id,
283     GValue * value, GParamSpec * pspec)
284 {
285   GstNegotiation *filter;
286
287   g_return_if_fail (GST_IS_NEGOTIATION (object));
288   filter = GST_NEGOTIATION (object);
289
290   switch (prop_id) {
291     case ARG_ALLOWED_CAPS:
292       g_value_set_boxed (value, filter->caps);
293       break;
294     default:
295       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
296       break;
297   }
298 }
299
300 gboolean
301 gst_negotiation_plugin_init (GstPlugin * plugin)
302 {
303   if (!gst_element_register (plugin, "negotiation", GST_RANK_NONE,
304           GST_TYPE_NEGOTIATION))
305     return FALSE;
306
307   return TRUE;
308 }