allocation: fix for vmethod changes
[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 /**
37  * SECTION:element-warptv
38  *
39  * WarpTV does realtime goo'ing of the video input.
40  *
41  * <refsect2>
42  * <title>Example launch line</title>
43  * |[
44  * gst-launch -v videotestsrc ! warptv ! videoconvert ! autovideosink
45  * ]| This pipeline shows the effect of warptv on a test stream.
46  * </refsect2>
47  */
48
49 #ifdef HAVE_CONFIG_H
50 #include "config.h"
51 #endif
52
53 #include <string.h>
54 #include <math.h>
55
56 #include "gstwarp.h"
57 #include <gst/video/gstmetavideo.h>
58 #include <gst/video/gstvideopool.h>
59
60 #ifndef M_PI
61 #define M_PI    3.14159265358979323846
62 #endif
63
64 #define gst_warptv_parent_class parent_class
65 G_DEFINE_TYPE (GstWarpTV, gst_warptv, GST_TYPE_VIDEO_FILTER);
66
67 static void initSinTable ();
68 static void initDistTable (GstWarpTV * filter, gint width, gint height);
69
70 static GstStaticPadTemplate gst_warptv_src_template =
71 GST_STATIC_PAD_TEMPLATE ("src",
72     GST_PAD_SRC,
73     GST_PAD_ALWAYS,
74     GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE ("{ RGBx, xRGB, BGRx, xBGR }"))
75     );
76
77 static GstStaticPadTemplate gst_warptv_sink_template =
78 GST_STATIC_PAD_TEMPLATE ("sink",
79     GST_PAD_SINK,
80     GST_PAD_ALWAYS,
81     GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE ("{ RGBx, xRGB, BGRx, xBGR }"))
82     );
83
84 static gboolean
85 gst_warptv_set_caps (GstBaseTransform * btrans, GstCaps * incaps,
86     GstCaps * outcaps)
87 {
88   GstWarpTV *filter = GST_WARPTV (btrans);
89   GstVideoInfo info;
90   gint width, height;
91
92   if (!gst_video_info_from_caps (&info, incaps))
93     goto invalid_caps;
94
95   filter->info = info;
96
97   width = GST_VIDEO_INFO_WIDTH (&info);
98   height = GST_VIDEO_INFO_HEIGHT (&info);
99
100   g_free (filter->disttable);
101   filter->disttable = g_malloc (width * height * sizeof (guint32));
102   initDistTable (filter, width, height);
103
104   return TRUE;
105
106   /* ERRORS */
107 invalid_caps:
108   {
109     GST_DEBUG_OBJECT (filter, "invalid caps received");
110     return FALSE;
111   }
112 }
113
114 static gint32 sintable[1024 + 256];
115
116 static void
117 initSinTable (void)
118 {
119   gint32 *tptr, *tsinptr;
120   gint i;
121
122   tsinptr = tptr = sintable;
123
124   for (i = 0; i < 1024; i++)
125     *tptr++ = (int) (sin (i * M_PI / 512) * 32767);
126
127   for (i = 0; i < 256; i++)
128     *tptr++ = *tsinptr++;
129 }
130
131 static void
132 initDistTable (GstWarpTV * filter, gint width, gint height)
133 {
134   gint32 halfw, halfh, *distptr;
135   gint x, y;
136 #ifdef PS2
137   float m;
138 #else
139   float m;
140 #endif
141
142   halfw = width >> 1;
143   halfh = height >> 1;
144
145   distptr = filter->disttable;
146
147   m = sqrt ((double) (halfw * halfw + halfh * halfh));
148
149   for (y = -halfh; y < halfh; y++)
150     for (x = -halfw; x < halfw; x++)
151 #ifdef PS2
152       *distptr++ = ((int) ((sqrtf (x * x + y * y) * 511.9999) / m)) << 1;
153 #else
154       *distptr++ = ((int) ((sqrt (x * x + y * y) * 511.9999) / m)) << 1;
155 #endif
156 }
157
158 static GstFlowReturn
159 gst_warptv_transform (GstBaseTransform * trans, GstBuffer * in, GstBuffer * out)
160 {
161   GstWarpTV *warptv = GST_WARPTV (trans);
162   gint width, height;
163   gint xw, yw, cw;
164   gint32 c, i, x, y, dx, dy, maxx, maxy;
165   gint32 *ctptr, *distptr;
166   gint32 *ctable;
167   guint32 *src, *dest;
168   gint sstride, dstride;
169   GstVideoFrame in_frame, out_frame;
170
171   gst_video_frame_map (&in_frame, &warptv->info, in, GST_MAP_READ);
172   gst_video_frame_map (&out_frame, &warptv->info, out, GST_MAP_WRITE);
173
174   src = GST_VIDEO_FRAME_PLANE_DATA (&in_frame, 0);
175   dest = GST_VIDEO_FRAME_PLANE_DATA (&out_frame, 0);
176
177   sstride = GST_VIDEO_FRAME_PLANE_STRIDE (&in_frame, 0) / 4;
178   dstride = GST_VIDEO_FRAME_PLANE_STRIDE (&out_frame, 0) / 4;
179
180   width = GST_VIDEO_FRAME_WIDTH (&in_frame);
181   height = GST_VIDEO_FRAME_HEIGHT (&in_frame);
182
183   GST_OBJECT_LOCK (warptv);
184   xw = (gint) (sin ((warptv->tval + 100) * M_PI / 128) * 30);
185   yw = (gint) (sin ((warptv->tval) * M_PI / 256) * -35);
186   cw = (gint) (sin ((warptv->tval - 70) * M_PI / 64) * 50);
187   xw += (gint) (sin ((warptv->tval - 10) * M_PI / 512) * 40);
188   yw += (gint) (sin ((warptv->tval + 30) * M_PI / 512) * 40);
189
190   ctptr = warptv->ctable;
191   distptr = warptv->disttable;
192   ctable = warptv->ctable;
193
194   c = 0;
195
196   for (x = 0; x < 512; x++) {
197     i = (c >> 3) & 0x3FE;
198     *ctptr++ = ((sintable[i] * yw) >> 15);
199     *ctptr++ = ((sintable[i + 256] * xw) >> 15);
200     c += cw;
201   }
202   maxx = width - 2;
203   maxy = height - 2;
204
205   for (y = 0; y < height - 1; y++) {
206     for (x = 0; x < width; x++) {
207       i = *distptr++;
208       dx = ctable[i + 1] + x;
209       dy = ctable[i] + y;
210
211       if (dx < 0)
212         dx = 0;
213       else if (dx > maxx)
214         dx = maxx;
215
216       if (dy < 0)
217         dy = 0;
218       else if (dy > maxy)
219         dy = maxy;
220
221       dest[x] = src[dy * sstride + dx];
222     }
223     dest += dstride;
224   }
225
226   warptv->tval = (warptv->tval + 1) & 511;
227   GST_OBJECT_UNLOCK (warptv);
228
229   gst_video_frame_unmap (&in_frame);
230   gst_video_frame_unmap (&out_frame);
231
232   return GST_FLOW_OK;
233 }
234
235 static gboolean
236 gst_warptv_start (GstBaseTransform * trans)
237 {
238   GstWarpTV *warptv = GST_WARPTV (trans);
239
240   warptv->tval = 0;
241
242   return TRUE;
243 }
244
245 static gboolean
246 gst_wraptv_decide_allocation (GstBaseTransform * trans, GstQuery * query)
247 {
248   GstBufferPool *pool = NULL;
249   guint size, min, max, prefix, alignment;
250
251   gst_query_parse_allocation_params (query, &size, &min, &max, &prefix,
252       &alignment, &pool);
253
254   if (pool) {
255     GstStructure *config;
256
257     config = gst_buffer_pool_get_config (pool);
258     gst_buffer_pool_config_add_option (config,
259         GST_BUFFER_POOL_OPTION_META_VIDEO);
260     gst_buffer_pool_set_config (pool, config);
261   }
262   return TRUE;
263 }
264
265 static void
266 gst_warptv_finalize (GObject * object)
267 {
268   GstWarpTV *warptv = GST_WARPTV (object);
269
270   g_free (warptv->disttable);
271   warptv->disttable = NULL;
272
273   G_OBJECT_CLASS (parent_class)->finalize (object);
274 }
275
276 static void
277 gst_warptv_class_init (GstWarpTVClass * klass)
278 {
279   GObjectClass *gobject_class = (GObjectClass *) klass;
280   GstElementClass *gstelement_class = (GstElementClass *) klass;
281   GstBaseTransformClass *trans_class = (GstBaseTransformClass *) klass;
282
283   gobject_class->finalize = gst_warptv_finalize;
284
285   gst_element_class_set_details_simple (gstelement_class, "WarpTV effect",
286       "Filter/Effect/Video",
287       "WarpTV does realtime goo'ing of the video input",
288       "Sam Lantinga <slouken@devolution.com>");
289
290   gst_element_class_add_pad_template (gstelement_class,
291       gst_static_pad_template_get (&gst_warptv_sink_template));
292   gst_element_class_add_pad_template (gstelement_class,
293       gst_static_pad_template_get (&gst_warptv_src_template));
294
295   trans_class->start = GST_DEBUG_FUNCPTR (gst_warptv_start);
296   trans_class->set_caps = GST_DEBUG_FUNCPTR (gst_warptv_set_caps);
297   trans_class->decide_allocation =
298       GST_DEBUG_FUNCPTR (gst_wraptv_decide_allocation);
299   trans_class->transform = GST_DEBUG_FUNCPTR (gst_warptv_transform);
300
301   initSinTable ();
302 }
303
304 static void
305 gst_warptv_init (GstWarpTV * warptv)
306 {
307   gst_pad_use_fixed_caps (GST_BASE_TRANSFORM_SRC_PAD (warptv));
308   gst_pad_use_fixed_caps (GST_BASE_TRANSFORM_SINK_PAD (warptv));
309 }