1 /* gstgoom.c: implementation of goom drawing element
2 * Copyright (C) <2001> Richard Boulton <richard@tartarus.org>
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.
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.
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., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
23 #include "goom_core.h"
25 #define GST_TYPE_GOOM (gst_goom_get_type())
26 #define GST_GOOM(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_GOOM,GstGOOM))
27 #define GST_GOOM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_GOOM,GstGOOM))
28 #define GST_IS_GOOM(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_GOOM))
29 #define GST_IS_GOOM_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_GOOM))
31 typedef struct _GstGOOM GstGOOM;
32 typedef struct _GstGOOMClass GstGOOMClass;
38 GstPad *sinkpad,*srcpad;
39 GstBufferPool *peerpool;
41 /* the timestamp of the next frame */
43 gint16 datain[2][512];
49 gboolean first_buffer;
52 struct _GstGOOMClass {
53 GstElementClass parent_class;
56 GType gst_goom_get_type(void);
59 /* elementfactory information */
60 static GstElementDetails gst_goom_details = {
62 "Filter/Visualization",
63 "Takes frames of data and outputs video frames using the GOOM filter",
65 "Wim Taymans <wim.taymans@chello.be>",
69 /* signals and args */
83 GST_PADTEMPLATE_FACTORY (src_template,
90 "format", GST_PROPS_FOURCC (GST_STR_FOURCC ("RGB ")),
91 "bpp", GST_PROPS_INT (32),
92 "depth", GST_PROPS_INT (32),
93 "endianness", GST_PROPS_INT (G_BYTE_ORDER),
94 "red_mask", GST_PROPS_INT (0xff0000),
95 "green_mask", GST_PROPS_INT (0xff00),
96 "blue_mask", GST_PROPS_INT (0xff),
97 "width", GST_PROPS_INT_RANGE (16, 4096),
98 "height", GST_PROPS_INT_RANGE (16, 4096)
102 GST_PADTEMPLATE_FACTORY (sink_template,
103 "sink", /* the name of the pads */
104 GST_PAD_SINK, /* type of the pad */
105 GST_PAD_ALWAYS, /* ALWAYS/SOMETIMES */
107 "goomsink", /* the name of the caps */
108 "audio/raw", /* the mime type of the caps */
109 /* Properties follow: */
110 "format", GST_PROPS_STRING ("int"),
111 "law", GST_PROPS_INT (0),
112 "endianness", GST_PROPS_INT (G_BYTE_ORDER),
113 "signed", GST_PROPS_BOOLEAN (TRUE),
114 "width", GST_PROPS_INT (16),
115 "depth", GST_PROPS_INT (16),
116 "rate", GST_PROPS_INT_RANGE (8000, 96000),
117 "channels", GST_PROPS_INT (1)
122 static void gst_goom_class_init (GstGOOMClass *klass);
123 static void gst_goom_init (GstGOOM *goom);
125 static void gst_goom_set_property (GObject *object, guint prop_id,
126 const GValue *value, GParamSpec *pspec);
127 static void gst_goom_get_property (GObject *object, guint prop_id,
128 GValue *value, GParamSpec *pspec);
130 static void gst_goom_chain (GstPad *pad, GstBuffer *buf);
132 static GstPadConnectReturn
133 gst_goom_sinkconnect (GstPad *pad, GstCaps *caps);
135 static GstElementClass *parent_class = NULL;
138 gst_goom_get_type (void)
140 static GType type = 0;
143 static const GTypeInfo info = {
144 sizeof (GstGOOMClass),
147 (GClassInitFunc) gst_goom_class_init,
152 (GInstanceInitFunc) gst_goom_init,
154 type = g_type_register_static (GST_TYPE_ELEMENT, "GstGOOM", &info, 0);
160 gst_goom_class_init(GstGOOMClass *klass)
162 GObjectClass *gobject_class;
163 GstElementClass *gstelement_class;
165 gobject_class = (GObjectClass*) klass;
166 gstelement_class = (GstElementClass*) klass;
168 parent_class = g_type_class_ref (GST_TYPE_ELEMENT);
170 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_WIDTH,
171 g_param_spec_int ("width","Width","The Width",
172 0, 2048, 320, G_PARAM_READWRITE));
173 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_HEIGHT,
174 g_param_spec_int ("height","Height","The height",
175 0, 2048, 320, G_PARAM_READWRITE));
176 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_FPS,
177 g_param_spec_int ("fps","FPS","Frames per second",
178 1, 100, 25, G_PARAM_READWRITE));
180 gobject_class->set_property = gst_goom_set_property;
181 gobject_class->get_property = gst_goom_get_property;
185 gst_goom_init (GstGOOM *goom)
187 /* create the sink and src pads */
188 goom->sinkpad = gst_pad_new_from_template (
189 GST_PADTEMPLATE_GET (sink_template ), "sink");
190 goom->srcpad = gst_pad_new_from_template (
191 GST_PADTEMPLATE_GET (src_template ), "src");
192 gst_element_add_pad (GST_ELEMENT (goom), goom->sinkpad);
193 gst_element_add_pad (GST_ELEMENT (goom), goom->srcpad);
195 gst_pad_set_chain_function (goom->sinkpad, gst_goom_chain);
196 gst_pad_set_connect_function (goom->sinkpad, gst_goom_sinkconnect);
199 goom->peerpool = NULL;
201 /* reset the initial video state */
202 goom->first_buffer = TRUE;
205 goom->fps = 25; /* desired frame rate */
209 static GstPadConnectReturn
210 gst_goom_sinkconnect (GstPad *pad, GstCaps *caps)
213 goom = GST_GOOM (gst_pad_get_parent (pad));
215 if (!GST_CAPS_IS_FIXED (caps)) {
216 return GST_PAD_CONNECT_DELAYED;
219 return GST_PAD_CONNECT_OK;
223 gst_goom_chain (GstPad *pad, GstBuffer *bufin)
231 goom = GST_GOOM (gst_pad_get_parent (pad));
233 GST_DEBUG (0, "GOOM: chainfunc called");
235 samples_in = GST_BUFFER_SIZE (bufin) / sizeof (gint16);
237 GST_DEBUG (0, "input buffer has %d samples", samples_in);
239 if (GST_BUFFER_TIMESTAMP (bufin) < goom->next_time || samples_in < 1024) {
240 gst_buffer_unref (bufin);
244 data = (gint16 *) GST_BUFFER_DATA (bufin);
245 for (i=0; i < 512; i++) {
246 goom->datain[0][i] = *data++;
247 goom->datain[1][i] = *data++;
250 if (goom->first_buffer) {
253 goom_init (goom->width, goom->height);
255 GST_DEBUG (0, "making new pad");
257 caps = GST_CAPS_NEW (
260 "format", GST_PROPS_FOURCC (GST_STR_FOURCC ("RGB ")),
261 "bpp", GST_PROPS_INT (32),
262 "depth", GST_PROPS_INT (32),
263 "endianness", GST_PROPS_INT (G_BYTE_ORDER),
264 "red_mask", GST_PROPS_INT (0xff0000),
265 "green_mask", GST_PROPS_INT (0x00ff00),
266 "blue_mask", GST_PROPS_INT (0x0000ff),
267 "width", GST_PROPS_INT (goom->width),
268 "height", GST_PROPS_INT (goom->height)
271 if (!gst_pad_try_set_caps (goom->srcpad, caps)) {
272 gst_element_error (GST_ELEMENT (goom), "could not set caps");
275 goom->first_buffer = FALSE;
278 bufout = gst_buffer_new ();
279 GST_BUFFER_SIZE (bufout) = goom->width * goom->height * 4;
280 GST_BUFFER_DATA (bufout) = (guchar *) goom_update (goom->datain);
281 GST_BUFFER_TIMESTAMP (bufout) = goom->next_time;
282 GST_BUFFER_FLAG_SET (bufout, GST_BUFFER_DONTFREE);
284 goom->next_time += 1000000LL / goom->fps;
286 gst_pad_push (goom->srcpad, bufout);
288 gst_buffer_unref (bufin);
290 GST_DEBUG (0, "GOOM: exiting chainfunc");
295 gst_goom_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
299 /* it's not null if we got it, but it might not be ours */
300 g_return_if_fail (GST_IS_GOOM (object));
301 goom = GST_GOOM (object);
305 goom->width = g_value_get_int (value);
308 goom->height = g_value_get_int (value);
311 goom->fps = g_value_get_int (value);
319 gst_goom_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
323 /* it's not null if we got it, but it might not be ours */
324 g_return_if_fail (GST_IS_GOOM (object));
325 goom = GST_GOOM (object);
329 g_value_set_int (value, goom->width);
332 g_value_set_int (value, goom->height);
335 g_value_set_int (value, goom->fps);
343 plugin_init (GModule *module, GstPlugin *plugin)
345 GstElementFactory *factory;
347 /* create an elementfactory for the goom element */
348 factory = gst_elementfactory_new("goom",GST_TYPE_GOOM,
350 g_return_val_if_fail(factory != NULL, FALSE);
352 gst_elementfactory_add_padtemplate (factory, GST_PADTEMPLATE_GET (src_template));
353 gst_elementfactory_add_padtemplate (factory, GST_PADTEMPLATE_GET (sink_template));
355 gst_plugin_add_feature (plugin, GST_PLUGIN_FEATURE (factory));
360 GstPluginDesc plugin_desc = {