• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* GStreamer
2  * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
3  *
4  * EffecTV:
5  * Copyright (C) 2001 FUKUCHI Kentarou
6  *
7  * Inspired by Adrian Likin's script for the GIMP.
8  * EffecTV is free software.  This library is free software;
9  * you can redistribute it and/or
10  *  modify it under the terms of the GNU Library General Public
11  * License as published by the Free Software Foundation; either
12  * version 2 of the License, or (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Library General Public License for more details.
18  *
19  * You should have received a copy of the GNU Library General Public
20  * License along with this library; if not, write to the
21  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
22  * Boston, MA 02110-1301, USA.
23  */
24 
25 /**
26  * SECTION:element-shagadelictv
27  * @title: shagadelictv
28  *
29  * Oh behave, ShagedelicTV makes images shagadelic!
30  *
31  * ## Example launch line
32  * |[
33  * gst-launch-1.0 -v videotestsrc ! shagadelictv ! videoconvert ! autovideosink
34  * ]| This pipeline shows the effect of shagadelictv on a test stream.
35  *
36  */
37 
38 #ifdef HAVE_CONFIG_H
39 #include "config.h"
40 #endif
41 
42 #include <math.h>
43 #include <string.h>
44 
45 #include "gstshagadelic.h"
46 #include "gsteffectv.h"
47 
48 #ifndef M_PI
49 #define M_PI  3.14159265358979323846
50 #endif
51 
52 #define gst_shagadelictv_parent_class parent_class
53 G_DEFINE_TYPE (GstShagadelicTV, gst_shagadelictv, GST_TYPE_VIDEO_FILTER);
54 GST_ELEMENT_REGISTER_DEFINE (shagadelictv, "shagadelictv",
55     GST_RANK_NONE, GST_TYPE_SHAGADELICTV);
56 
57 static void gst_shagadelic_initialize (GstShagadelicTV * filter,
58     GstVideoInfo * in_info);
59 
60 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
61 #define CAPS_STR GST_VIDEO_CAPS_MAKE ("BGRx")
62 #else
63 #define CAPS_STR GST_VIDEO_CAPS_MAKE ("xRGB")
64 #endif
65 
66 static GstStaticPadTemplate gst_shagadelictv_src_template =
67 GST_STATIC_PAD_TEMPLATE ("src",
68     GST_PAD_SRC,
69     GST_PAD_ALWAYS,
70     GST_STATIC_CAPS (CAPS_STR)
71     );
72 
73 static GstStaticPadTemplate gst_shagadelictv_sink_template =
74 GST_STATIC_PAD_TEMPLATE ("sink",
75     GST_PAD_SINK,
76     GST_PAD_ALWAYS,
77     GST_STATIC_CAPS (CAPS_STR)
78     );
79 
80 static gboolean
gst_shagadelictv_set_info(GstVideoFilter * vfilter,GstCaps * incaps,GstVideoInfo * in_info,GstCaps * outcaps,GstVideoInfo * out_info)81 gst_shagadelictv_set_info (GstVideoFilter * vfilter, GstCaps * incaps,
82     GstVideoInfo * in_info, GstCaps * outcaps, GstVideoInfo * out_info)
83 {
84   GstShagadelicTV *filter = GST_SHAGADELICTV (vfilter);
85   gint width, height, area;
86 
87   width = GST_VIDEO_INFO_WIDTH (in_info);
88   height = GST_VIDEO_INFO_HEIGHT (in_info);
89 
90   area = width * height;
91 
92   g_free (filter->ripple);
93   g_free (filter->spiral);
94   filter->ripple = (guint8 *) g_malloc (area * 4);
95   filter->spiral = (guint8 *) g_malloc (area);
96 
97   gst_shagadelic_initialize (filter, in_info);
98 
99   return TRUE;
100 }
101 
102 static void
gst_shagadelic_initialize(GstShagadelicTV * filter,GstVideoInfo * info)103 gst_shagadelic_initialize (GstShagadelicTV * filter, GstVideoInfo * info)
104 {
105   int i, x, y;
106 #ifdef PS2
107   float xx, yy;
108 #else
109   double xx, yy;
110 #endif
111   gint width, height;
112 
113   width = GST_VIDEO_INFO_WIDTH (info);
114   height = GST_VIDEO_INFO_HEIGHT (info);
115 
116   i = 0;
117   for (y = 0; y < height * 2; y++) {
118     yy = y - height;
119     yy *= yy;
120 
121     for (x = 0; x < width * 2; x++) {
122       xx = x - width;
123 #ifdef PS2
124       filter->ripple[i++] = ((unsigned int) (sqrtf (xx * xx + yy) * 8)) & 255;
125 #else
126       filter->ripple[i++] = ((unsigned int) (sqrt (xx * xx + yy) * 8)) & 255;
127 #endif
128     }
129   }
130 
131   i = 0;
132   for (y = 0; y < height; y++) {
133     yy = y - height / 2;
134 
135     for (x = 0; x < width; x++) {
136       xx = x - width / 2;
137 #ifdef PS2
138       filter->spiral[i++] = ((unsigned int)
139           ((atan2f (xx,
140                       yy) / ((float) M_PI) * 256 * 9) + (sqrtf (xx * xx +
141                       yy * yy) * 5))) & 255;
142 #else
143       filter->spiral[i++] = ((unsigned int)
144           ((atan2 (xx, yy) / M_PI * 256 * 9) + (sqrt (xx * xx +
145                       yy * yy) * 5))) & 255;
146 #endif
147 /* Here is another Swinger!
148  * ((atan2(xx, yy)/M_PI*256) + (sqrt(xx*xx+yy*yy)*10))&255;
149  */
150     }
151   }
152   filter->rx = fastrand () % width;
153   filter->ry = fastrand () % height;
154   filter->bx = fastrand () % width;
155   filter->by = fastrand () % height;
156   filter->rvx = -2;
157   filter->rvy = -2;
158   filter->bvx = 2;
159   filter->bvy = 2;
160   filter->phase = 0;
161 }
162 
163 static GstFlowReturn
gst_shagadelictv_transform_frame(GstVideoFilter * vfilter,GstVideoFrame * in_frame,GstVideoFrame * out_frame)164 gst_shagadelictv_transform_frame (GstVideoFilter * vfilter,
165     GstVideoFrame * in_frame, GstVideoFrame * out_frame)
166 {
167   GstShagadelicTV *filter = GST_SHAGADELICTV (vfilter);
168   guint32 *src, *dest;
169   gint x, y;
170   guint32 v;
171   guint8 r, g, b;
172   gint width, height;
173 
174   src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
175   dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
176 
177   width = GST_VIDEO_FRAME_WIDTH (in_frame);
178   height = GST_VIDEO_FRAME_HEIGHT (in_frame);
179 
180   for (y = 0; y < height; y++) {
181     for (x = 0; x < width; x++) {
182       v = *src++ | 0x1010100;
183       v = (v - 0x707060) & 0x1010100;
184       v -= v >> 8;
185 /* Try another Babe!
186  * v = *src++;
187  * *dest++ = v & ((r<<16)|(g<<8)|b);
188  */
189       r = ((gint8) (filter->ripple[(filter->ry + y) * width * 2 + filter->rx +
190                   x] + filter->phase * 2)) >> 7;
191       g = ((gint8) (filter->spiral[y * width + x] + filter->phase * 3)) >> 7;
192       b = ((gint8) (filter->ripple[(filter->by + y) * width * 2 + filter->bx +
193                   x] - filter->phase)) >> 7;
194       *dest++ = v & ((r << 16) | (g << 8) | b);
195     }
196   }
197 
198   filter->phase -= 8;
199   if ((filter->rx + filter->rvx) < 0 || (filter->rx + filter->rvx) >= width)
200     filter->rvx = -filter->rvx;
201   if ((filter->ry + filter->rvy) < 0 || (filter->ry + filter->rvy) >= height)
202     filter->rvy = -filter->rvy;
203   if ((filter->bx + filter->bvx) < 0 || (filter->bx + filter->bvx) >= width)
204     filter->bvx = -filter->bvx;
205   if ((filter->by + filter->bvy) < 0 || (filter->by + filter->bvy) >= height)
206     filter->bvy = -filter->bvy;
207   filter->rx += filter->rvx;
208   filter->ry += filter->rvy;
209   filter->bx += filter->bvx;
210   filter->by += filter->bvy;
211 
212   return GST_FLOW_OK;
213 }
214 
215 static void
gst_shagadelictv_finalize(GObject * object)216 gst_shagadelictv_finalize (GObject * object)
217 {
218   GstShagadelicTV *filter = GST_SHAGADELICTV (object);
219 
220   g_free (filter->ripple);
221   filter->ripple = NULL;
222 
223   g_free (filter->spiral);
224   filter->spiral = NULL;
225 
226   G_OBJECT_CLASS (parent_class)->finalize (object);
227 }
228 
229 static void
gst_shagadelictv_class_init(GstShagadelicTVClass * klass)230 gst_shagadelictv_class_init (GstShagadelicTVClass * klass)
231 {
232   GObjectClass *gobject_class = (GObjectClass *) klass;
233   GstElementClass *gstelement_class = (GstElementClass *) klass;
234   GstVideoFilterClass *vfilter_class = (GstVideoFilterClass *) klass;
235 
236   gobject_class->finalize = gst_shagadelictv_finalize;
237 
238   gst_element_class_set_static_metadata (gstelement_class, "ShagadelicTV",
239       "Filter/Effect/Video",
240       "Oh behave, ShagedelicTV makes images shagadelic!",
241       "Wim Taymans <wim.taymans@chello.be>");
242 
243   gst_element_class_add_static_pad_template (gstelement_class,
244       &gst_shagadelictv_sink_template);
245   gst_element_class_add_static_pad_template (gstelement_class,
246       &gst_shagadelictv_src_template);
247 
248   vfilter_class->set_info = GST_DEBUG_FUNCPTR (gst_shagadelictv_set_info);
249   vfilter_class->transform_frame =
250       GST_DEBUG_FUNCPTR (gst_shagadelictv_transform_frame);
251 }
252 
253 static void
gst_shagadelictv_init(GstShagadelicTV * filter)254 gst_shagadelictv_init (GstShagadelicTV * filter)
255 {
256   filter->ripple = NULL;
257   filter->spiral = NULL;
258 }
259