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.
25 #include <gst/video/video.h>
26 #include "goom_core.h"
28 #define GST_TYPE_GOOM (gst_goom_get_type())
29 #define GST_GOOM(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_GOOM,GstGOOM))
30 #define GST_GOOM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_GOOM,GstGOOM))
31 #define GST_IS_GOOM(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_GOOM))
32 #define GST_IS_GOOM_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_GOOM))
34 typedef struct _GstGOOM GstGOOM;
35 typedef struct _GstGOOMClass GstGOOMClass;
41 GstPad *sinkpad,*srcpad;
43 /* the timestamp of the next frame */
45 gint16 datain[2][512];
52 gboolean srcnegotiated;
55 struct _GstGOOMClass {
56 GstElementClass parent_class;
59 GType gst_goom_get_type(void);
62 /* elementfactory information */
63 static GstElementDetails gst_goom_details = {
67 "Takes frames of data and outputs video frames using the GOOM filter",
69 "Wim Taymans <wim.taymans@chello.be>",
73 /* signals and args */
84 GST_PAD_TEMPLATE_FACTORY (src_template,
91 GST_VIDEO_RGB_PAD_TEMPLATE_PROPS_32
95 GST_PAD_TEMPLATE_FACTORY (sink_template,
96 "sink", /* the name of the pads */
97 GST_PAD_SINK, /* type of the pad */
98 GST_PAD_ALWAYS, /* ALWAYS/SOMETIMES */
100 "goomsink", /* the name of the caps */
101 "audio/x-raw-int", /* the mime type of the caps */
102 /* Properties follow: */
103 "endianness", GST_PROPS_INT (G_BYTE_ORDER),
104 "signed", GST_PROPS_BOOLEAN (TRUE),
105 "width", GST_PROPS_INT (16),
106 "depth", GST_PROPS_INT (16),
107 "rate", GST_PROPS_INT_RANGE (8000, 96000),
108 "channels", GST_PROPS_INT_RANGE (1, 2)
113 static void gst_goom_class_init (GstGOOMClass *klass);
114 static void gst_goom_init (GstGOOM *goom);
115 static void gst_goom_dispose (GObject *object);
117 static GstElementStateReturn
118 gst_goom_change_state (GstElement *element);
120 static void gst_goom_chain (GstPad *pad, GstBuffer *buf);
122 static GstPadLinkReturn gst_goom_sinkconnect (GstPad *pad, GstCaps *caps);
123 static GstPadLinkReturn gst_goom_srcconnect (GstPad *pad, GstCaps *caps);
125 static GstElementClass *parent_class = NULL;
128 gst_goom_get_type (void)
130 static GType type = 0;
133 static const GTypeInfo info = {
134 sizeof (GstGOOMClass),
137 (GClassInitFunc) gst_goom_class_init,
142 (GInstanceInitFunc) gst_goom_init,
144 type = g_type_register_static (GST_TYPE_ELEMENT, "GstGOOM", &info, 0);
150 gst_goom_class_init(GstGOOMClass *klass)
152 GObjectClass *gobject_class;
153 GstElementClass *gstelement_class;
155 gobject_class = (GObjectClass*) klass;
156 gstelement_class = (GstElementClass*) klass;
158 parent_class = g_type_class_ref (GST_TYPE_ELEMENT);
160 gobject_class->dispose = gst_goom_dispose;
162 gstelement_class->change_state = gst_goom_change_state;
166 gst_goom_init (GstGOOM *goom)
168 /* create the sink and src pads */
169 goom->sinkpad = gst_pad_new_from_template (
170 GST_PAD_TEMPLATE_GET (sink_template ), "sink");
171 goom->srcpad = gst_pad_new_from_template (
172 GST_PAD_TEMPLATE_GET (src_template ), "src");
173 gst_element_add_pad (GST_ELEMENT (goom), goom->sinkpad);
174 gst_element_add_pad (GST_ELEMENT (goom), goom->srcpad);
176 GST_FLAG_SET (goom, GST_ELEMENT_EVENT_AWARE);
178 gst_pad_set_chain_function (goom->sinkpad, gst_goom_chain);
179 gst_pad_set_link_function (goom->sinkpad, gst_goom_sinkconnect);
181 gst_pad_set_link_function (goom->srcpad, gst_goom_srcconnect);
185 goom->fps = 25.; /* desired frame rate */
187 /* set to something */
192 gst_goom_dispose (GObject *object)
196 G_OBJECT_CLASS (parent_class)->dispose (object);
199 static GstPadLinkReturn
200 gst_goom_sinkconnect (GstPad *pad, GstCaps *caps)
203 goom = GST_GOOM (gst_pad_get_parent (pad));
205 if (!GST_CAPS_IS_FIXED (caps)) {
206 return GST_PAD_LINK_DELAYED;
209 gst_caps_get_int (caps, "channels", &goom->channels);
211 return GST_PAD_LINK_OK;
214 static GstPadLinkReturn
215 gst_goom_srcconnect (GstPad *pad, GstCaps *caps)
218 goom = GST_GOOM (gst_pad_get_parent (pad));
220 if (!GST_CAPS_IS_FIXED (caps)) {
221 return GST_PAD_LINK_DELAYED;
224 if (gst_caps_has_property_typed (caps, "width", GST_PROPS_INT_TYPE)) {
225 gst_caps_get_int (caps, "width", &goom->width);
227 if (gst_caps_has_property_typed (caps, "height", GST_PROPS_INT_TYPE)) {
228 gst_caps_get_int (caps, "height", &goom->height);
230 if (gst_caps_has_property_typed (caps, "framerate", GST_PROPS_FLOAT_TYPE)) {
231 gst_caps_get_float (caps, "framerate", &goom->fps);
234 goom_set_resolution (goom->width, goom->height);
235 goom->srcnegotiated = TRUE;
237 return GST_PAD_LINK_OK;
241 gst_goom_negotiate_default (GstGOOM *goom)
245 caps = GST_CAPS_NEW (
248 "format", GST_PROPS_FOURCC (GST_STR_FOURCC ("RGB ")),
249 "bpp", GST_PROPS_INT (32),
250 "depth", GST_PROPS_INT (32),
251 "endianness", GST_PROPS_INT (G_BYTE_ORDER),
252 "red_mask", GST_PROPS_INT (0xff0000),
253 "green_mask", GST_PROPS_INT (0x00ff00),
254 "blue_mask", GST_PROPS_INT (0x0000ff),
255 "width", GST_PROPS_INT (goom->width),
256 "height", GST_PROPS_INT (goom->height),
257 "framerate", GST_PROPS_FLOAT (goom->fps)
260 if (gst_pad_try_set_caps (goom->srcpad, caps) <= 0) {
264 goom_set_resolution (goom->width, goom->height);
265 goom->srcnegotiated = TRUE;
271 gst_goom_chain (GstPad *pad, GstBuffer *bufin)
279 goom = GST_GOOM (gst_pad_get_parent (pad));
281 GST_DEBUG ("GOOM: chainfunc called");
283 if (GST_IS_EVENT (bufin)) {
284 GstEvent *event = GST_EVENT (bufin);
286 switch (GST_EVENT_TYPE (event)) {
287 case GST_EVENT_DISCONTINUOUS:
291 gst_event_discont_get_value (event, GST_FORMAT_TIME, &value);
293 goom->next_time = value;
296 gst_pad_event_default (pad, event);
302 if (goom->channels == 0) {
303 gst_element_error (GST_ELEMENT (goom), "sink format not negotiated");
307 if (!GST_PAD_IS_USABLE (goom->srcpad))
310 if (!goom->srcnegotiated) {
311 if (!gst_goom_negotiate_default (goom)) {
312 gst_element_error (GST_ELEMENT (goom), "could not negotiate src format");
317 samples_in = GST_BUFFER_SIZE (bufin) / (sizeof (gint16) * goom->channels);
319 GST_DEBUG ("input buffer has %d samples", samples_in);
321 if (GST_BUFFER_TIMESTAMP (bufin) < goom->next_time || samples_in < 512) {
325 data = (gint16 *) GST_BUFFER_DATA (bufin);
326 if (goom->channels == 2) {
327 for (i=0; i < 512; i++) {
328 goom->datain[0][i] = *data++;
329 goom->datain[1][i] = *data++;
333 for (i=0; i < 512; i++) {
334 goom->datain[0][i] = *data;
335 goom->datain[1][i] = *data++;
339 bufout = gst_buffer_new ();
340 GST_BUFFER_SIZE (bufout) = goom->width * goom->height * 4;
341 GST_BUFFER_DATA (bufout) = (guchar *) goom_update (goom->datain);
342 GST_BUFFER_TIMESTAMP (bufout) = goom->next_time;
343 GST_BUFFER_FLAG_SET (bufout, GST_BUFFER_DONTFREE);
345 goom->next_time += GST_SECOND / goom->fps;
347 gst_pad_push (goom->srcpad, bufout);
350 gst_buffer_unref (bufin);
352 GST_DEBUG ("GOOM: exiting chainfunc");
355 static GstElementStateReturn
356 gst_goom_change_state (GstElement *element)
358 GstGOOM *goom = GST_GOOM (element);
360 switch (GST_STATE_TRANSITION (element)) {
361 case GST_STATE_NULL_TO_READY:
363 case GST_STATE_READY_TO_NULL:
365 case GST_STATE_READY_TO_PAUSED:
367 goom->srcnegotiated = FALSE;
370 case GST_STATE_PAUSED_TO_READY:
376 if (GST_ELEMENT_CLASS (parent_class)->change_state)
377 return GST_ELEMENT_CLASS (parent_class)->change_state (element);
379 return GST_STATE_SUCCESS;
383 plugin_init (GModule *module, GstPlugin *plugin)
385 GstElementFactory *factory;
387 /* create an elementfactory for the goom element */
388 factory = gst_element_factory_new("goom",GST_TYPE_GOOM,
390 g_return_val_if_fail(factory != NULL, FALSE);
392 gst_element_factory_add_pad_template (factory, GST_PAD_TEMPLATE_GET (src_template));
393 gst_element_factory_add_pad_template (factory, GST_PAD_TEMPLATE_GET (sink_template));
395 gst_plugin_add_feature (plugin, GST_PLUGIN_FEATURE (factory));
400 GstPluginDesc plugin_desc = {