More G_OBJECT macro fixing.
[platform/upstream/gstreamer.git] / gst / effectv / gstwarp.c
1 /* GStreamer
2  * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
3  * Copyright (C) <2003> David Schleef <ds@schleef.org>
4  *
5  * EffecTV - Realtime Digital Video Effector
6  * Copyright (C) 2001 FUKUCHI Kentarou
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Library General Public
10  * License as published by the Free Software Foundation; either
11  * version 2 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Library General Public License for more details.
17  *
18  * You should have received a copy of the GNU Library General Public
19  * License along with this library; if not, write to the
20  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21  * Boston, MA 02111-1307, USA.
22  */
23
24 /*
25  * This file was (probably) generated from gstvideotemplate.c,
26  * gstvideotemplate.c,v 1.11 2004/01/07 08:56:45 ds Exp 
27  */
28
29 /* From main.c of warp-1.1:
30  *
31  *      Simple DirectMedia Layer demo
32  *      Realtime picture 'gooing'
33  *      by sam lantinga slouken@devolution.com
34  */
35
36 #ifdef HAVE_CONFIG_H
37 #include "config.h"
38 #endif
39
40 #include <gst/video/gstvideofilter.h>
41
42 #include <string.h>
43 #include <math.h>
44
45 #include <gst/video/video.h>
46
47 #ifndef M_PI
48 #define M_PI    3.14159265358979323846
49 #endif
50
51 #define GST_TYPE_WARPTV \
52   (gst_warptv_get_type())
53 #define GST_WARPTV(obj) \
54   (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_WARPTV,GstWarpTV))
55 #define GST_WARPTV_CLASS(klass) \
56   (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_WARPTV,GstWarpTVClass))
57 #define GST_IS_WARPTV(obj) \
58   (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_WARPTV))
59 #define GST_IS_WARPTV_CLASS(klass) \
60   (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_WARPTV))
61
62 typedef struct _GstWarpTV GstWarpTV;
63 typedef struct _GstWarpTVClass GstWarpTVClass;
64
65 struct _GstWarpTV
66 {
67   GstVideoFilter videofilter;
68
69   gint width, height;
70   gint *offstable;
71   gint32 *disttable;
72   gint32 ctable[1024];
73   gint32 sintable[1024 + 256];
74   gint tval;
75 };
76
77 struct _GstWarpTVClass
78 {
79   GstVideoFilterClass parent_class;
80 };
81
82 GType gst_warptv_get_type (void);
83
84 static void initSinTable (GstWarpTV * filter);
85 static void initOffsTable (GstWarpTV * filter);
86 static void initDistTable (GstWarpTV * filter);
87
88 static const GstElementDetails warptv_details =
89 GST_ELEMENT_DETAILS ("WarpTV effect",
90     "Filter/Effect/Video",
91     "WarpTV does realtime goo'ing of the video input",
92     "Sam Lantinga <slouken@devolution.com>");
93
94 static GstStaticPadTemplate gst_warptv_src_template =
95     GST_STATIC_PAD_TEMPLATE ("src",
96     GST_PAD_SRC,
97     GST_PAD_ALWAYS,
98     GST_STATIC_CAPS (GST_VIDEO_CAPS_RGBx ";" GST_VIDEO_CAPS_xRGB ";"
99         GST_VIDEO_CAPS_BGRx ";" GST_VIDEO_CAPS_xBGR)
100     );
101
102 static GstStaticPadTemplate gst_warptv_sink_template =
103     GST_STATIC_PAD_TEMPLATE ("sink",
104     GST_PAD_SINK,
105     GST_PAD_ALWAYS,
106     GST_STATIC_CAPS (GST_VIDEO_CAPS_RGBx ";" GST_VIDEO_CAPS_xRGB ";"
107         GST_VIDEO_CAPS_BGRx ";" GST_VIDEO_CAPS_xBGR)
108     );
109
110 static GstVideoFilterClass *parent_class = NULL;
111
112 static gboolean
113 gst_warptv_set_caps (GstBaseTransform * btrans, GstCaps * incaps,
114     GstCaps * outcaps)
115 {
116   GstWarpTV *filter = GST_WARPTV (btrans);
117   GstStructure *structure;
118   gboolean ret = FALSE;
119
120   structure = gst_caps_get_structure (incaps, 0);
121
122   if (gst_structure_get_int (structure, "width", &filter->width) &&
123       gst_structure_get_int (structure, "height", &filter->height)) {
124     g_free (filter->disttable);
125     g_free (filter->offstable);
126
127     filter->offstable = g_malloc (filter->height * sizeof (guint32));
128     filter->disttable =
129         g_malloc (filter->width * filter->height * sizeof (guint32));
130
131     initSinTable (filter);
132     initOffsTable (filter);
133     initDistTable (filter);
134     ret = TRUE;
135   }
136
137   return ret;
138 }
139
140 static gboolean
141 gst_warptv_get_unit_size (GstBaseTransform * btrans, GstCaps * caps,
142     guint * size)
143 {
144   GstWarpTV *filter;
145   GstStructure *structure;
146   gboolean ret = FALSE;
147   gint width, height;
148
149   filter = GST_WARPTV (btrans);
150
151   structure = gst_caps_get_structure (caps, 0);
152
153   if (gst_structure_get_int (structure, "width", &width) &&
154       gst_structure_get_int (structure, "height", &height)) {
155     *size = width * height * 32 / 8;
156     ret = TRUE;
157     GST_DEBUG_OBJECT (filter, "our frame size is %d bytes (%dx%d)", *size,
158         width, height);
159   }
160
161   return ret;
162 }
163
164 static void
165 initSinTable (GstWarpTV * filter)
166 {
167   gint32 *tptr, *tsinptr;
168   double i;
169
170   tsinptr = tptr = filter->sintable;
171
172   for (i = 0; i < 1024; i++)
173     *tptr++ = (int) (sin (i * M_PI / 512) * 32767);
174
175   for (i = 0; i < 256; i++)
176     *tptr++ = *tsinptr++;
177 }
178
179 static void
180 initOffsTable (GstWarpTV * filter)
181 {
182   int y;
183
184   for (y = 0; y < filter->height; y++) {
185     filter->offstable[y] = y * filter->width;
186   }
187 }
188
189 static void
190 initDistTable (GstWarpTV * filter)
191 {
192   gint32 halfw, halfh, *distptr;
193
194 #ifdef PS2
195   float x, y, m;
196 #else
197   double x, y, m;
198 #endif
199
200   halfw = filter->width >> 1;
201   halfh = filter->height >> 1;
202
203   distptr = filter->disttable;
204
205   m = sqrt ((double) (halfw * halfw + halfh * halfh));
206
207   for (y = -halfh; y < halfh; y++)
208     for (x = -halfw; x < halfw; x++)
209 #ifdef PS2
210       *distptr++ = ((int) ((sqrtf (x * x + y * y) * 511.9999) / m)) << 1;
211 #else
212       *distptr++ = ((int) ((sqrt (x * x + y * y) * 511.9999) / m)) << 1;
213 #endif
214 }
215
216 static GstFlowReturn
217 gst_warptv_transform (GstBaseTransform * trans, GstBuffer * in, GstBuffer * out)
218 {
219   GstWarpTV *warptv = GST_WARPTV (trans);
220   int width = warptv->width;
221   int height = warptv->height;
222   guint32 *src = (guint32 *) GST_BUFFER_DATA (in);
223   guint32 *dest = (guint32 *) GST_BUFFER_DATA (out);
224   gint xw, yw, cw;
225   gint32 c, i, x, y, dx, dy, maxx, maxy;
226   gint32 skip, *ctptr, *distptr;
227   gint32 *sintable, *ctable;
228   GstFlowReturn ret = GST_FLOW_OK;
229
230   gst_buffer_stamp (out, in);
231
232   xw = (gint) (sin ((warptv->tval + 100) * M_PI / 128) * 30);
233   yw = (gint) (sin ((warptv->tval) * M_PI / 256) * -35);
234   cw = (gint) (sin ((warptv->tval - 70) * M_PI / 64) * 50);
235   xw += (gint) (sin ((warptv->tval - 10) * M_PI / 512) * 40);
236   yw += (gint) (sin ((warptv->tval + 30) * M_PI / 512) * 40);
237
238   ctptr = warptv->ctable;
239   distptr = warptv->disttable;
240   sintable = warptv->sintable;
241   ctable = warptv->ctable;
242
243   skip = 0;                     /* video_width*sizeof(RGB32)/4 - video_width;; */
244   c = 0;
245
246   for (x = 0; x < 512; x++) {
247     i = (c >> 3) & 0x3FE;
248     *ctptr++ = ((sintable[i] * yw) >> 15);
249     *ctptr++ = ((sintable[i + 256] * xw) >> 15);
250     c += cw;
251   }
252   maxx = width - 2;
253   maxy = height - 2;
254
255   for (y = 0; y < height - 1; y++) {
256     for (x = 0; x < width; x++) {
257       i = *distptr++;
258       dx = ctable[i + 1] + x;
259       dy = ctable[i] + y;
260
261       if (dx < 0)
262         dx = 0;
263       else if (dx > maxx)
264         dx = maxx;
265
266       if (dy < 0)
267         dy = 0;
268       else if (dy > maxy)
269         dy = maxy;
270       *dest++ = src[warptv->offstable[dy] + dx];
271     }
272     dest += skip;
273   }
274
275   warptv->tval = (warptv->tval + 1) & 511;
276
277   return ret;
278 }
279
280 static void
281 gst_warptv_base_init (gpointer g_class)
282 {
283   GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
284
285   gst_element_class_set_details (element_class, &warptv_details);
286
287   gst_element_class_add_pad_template (element_class,
288       gst_static_pad_template_get (&gst_warptv_sink_template));
289   gst_element_class_add_pad_template (element_class,
290       gst_static_pad_template_get (&gst_warptv_src_template));
291 }
292
293 static void
294 gst_warptv_class_init (gpointer klass, gpointer class_data)
295 {
296   GObjectClass *gobject_class;
297   GstElementClass *element_class;
298   GstBaseTransformClass *trans_class;
299
300   gobject_class = (GObjectClass *) klass;
301   element_class = (GstElementClass *) klass;
302   trans_class = (GstBaseTransformClass *) klass;
303
304   parent_class = g_type_class_peek_parent (klass);
305
306   trans_class->set_caps = GST_DEBUG_FUNCPTR (gst_warptv_set_caps);
307   trans_class->get_unit_size = GST_DEBUG_FUNCPTR (gst_warptv_get_unit_size);
308   trans_class->transform = GST_DEBUG_FUNCPTR (gst_warptv_transform);
309 }
310
311 static void
312 gst_warptv_init (GTypeInstance * instance, gpointer g_class)
313 {
314 }
315
316 GType
317 gst_warptv_get_type (void)
318 {
319   static GType warptv_type = 0;
320
321   if (!warptv_type) {
322     static const GTypeInfo warptv_info = {
323       sizeof (GstWarpTVClass),
324       gst_warptv_base_init,
325       NULL,
326       gst_warptv_class_init,
327       NULL,
328       NULL,
329       sizeof (GstWarpTV),
330       0,
331       gst_warptv_init,
332     };
333
334     warptv_type = g_type_register_static (GST_TYPE_VIDEO_FILTER,
335         "GstWarpTV", &warptv_info, 0);
336   }
337   return warptv_type;
338 }