33e6bf8a64884bb7fb1f1b3ec05293d8af30bb2e
[platform/upstream/gst-plugins-good.git] / gst / effectv / gstrev.c
1 /* GStreamer
2  * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
3  *
4  * EffecTV:
5  * Copyright (C) 2001 FUKUCHI Kentarou
6  *
7  * EffecTV - Realtime Digital Video Effector
8  * Copyright (C) 2001 FUKUCHI Kentarou
9  *
10  * revTV based on Rutt-Etra Video Synthesizer 1974?
11
12  * (c)2002 Ed Tannenbaum
13  *
14  * This effect acts like a waveform monitor on each line.
15  * It was originally done by deflecting the electron beam on a monitor using
16  * additional electromagnets on the yoke of a b/w CRT. 
17  * Here it is emulated digitally.
18
19  * Experimaental tapes were made with this system by Bill and 
20  * Louise Etra and Woody and Steina Vasulka
21
22  * The line spacing can be controlled using the 1 and 2 Keys.
23  * The gain is controlled using the 3 and 4 keys.
24  * The update rate is controlled using the 0 and - keys.
25  
26  * EffecTV is free software. This library is free software;
27  * you can redistribute it and/or
28  * modify it under the terms of the GNU Library General Public
29  * License as published by the Free Software Foundation; either
30  * version 2 of the License, or (at your option) any later version.
31  *
32  * This library is distributed in the hope that it will be useful,
33  * but WITHOUT ANY WARRANTY; without even the implied warranty of
34  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
35  * Library General Public License for more details.
36  *
37  * You should have received a copy of the GNU Library General Public
38  * License along with this library; if not, write to the
39  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
40  * Boston, MA 02111-1307, USA.
41  */
42
43 #ifdef HAVE_CONFIG_H
44 #include "config.h"
45 #endif
46 #include <math.h>
47 #include <string.h>
48 #include <gst/gst.h>
49 #include <gstvideofilter.h>
50
51 #define GST_TYPE_REVTV \
52   (gst_revtv_get_type())
53 #define GST_REVTV(obj) \
54   (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_REVTV,GstRevTV))
55 #define GST_REVTV_CLASS(klass) \
56   (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_REVTV,GstRevTVClass))
57 #define GST_IS_REVTV(obj) \
58   (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_REVTV))
59 #define GST_IS_REVTV_CLASS(obj) \
60   (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_REVTV))
61
62 #define THE_COLOR 0xffffffff
63
64 typedef struct _GstRevTV GstRevTV;
65 typedef struct _GstRevTVClass GstRevTVClass;
66
67 struct _GstRevTV
68 {
69   GstVideofilter videofilter;
70
71   gint width, height;
72   gint vgrabtime;
73   gint vgrab;
74   gint linespace;
75   gint vscale;
76 };
77
78 struct _GstRevTVClass
79 {
80   GstVideofilterClass parent_class;
81
82   void (*reset) (GstElement *element);
83 };
84
85 /* Filter signals and args */
86 enum
87 {
88   /* FILL ME */
89   LAST_SIGNAL
90 };
91
92 enum
93 {
94   ARG_0,
95   ARG_DELAY,
96   ARG_LINESPACE,
97   ARG_GAIN,
98 };
99
100 static void     gst_revtv_base_init             (gpointer g_class);
101 static void     gst_revtv_class_init            (gpointer g_class, gpointer class_data);
102 static void     gst_revtv_init                  (GTypeInstance *instance, gpointer g_class);
103
104 static void     gst_revtv_set_property          (GObject * object, guint prop_id,
105                                                  const GValue * value, GParamSpec * pspec);
106 static void     gst_revtv_get_property          (GObject * object, guint prop_id,
107                                                  GValue * value, GParamSpec * pspec);
108 static void     gst_revtv_setup                 (GstVideofilter *videofilter);
109 static void     gst_revtv_rgb32                 (GstVideofilter *videofilter, void *d, void *s);
110
111 /* static guint gst_revtv_signals[LAST_SIGNAL] = { 0 }; */
112
113 GType gst_revtv_get_type (void)
114 {
115   static GType revtv_type = 0;
116
117   if (!revtv_type) {
118     static const GTypeInfo revtv_info = {
119       sizeof (GstRevTVClass), 
120       gst_revtv_base_init,
121       NULL,
122       (GClassInitFunc) gst_revtv_class_init,
123       NULL,
124       NULL,
125       sizeof (GstRevTV),
126       0,
127       (GInstanceInitFunc) gst_revtv_init,
128     };
129
130     revtv_type = g_type_register_static (GST_TYPE_VIDEOFILTER, "GstRevTV", &revtv_info, 0);
131   }
132   return revtv_type;
133 }
134
135 static GstVideofilterFormat gst_revtv_formats[] = {
136   { "RGB ", 32, gst_revtv_rgb32, 24, G_BIG_ENDIAN, 0x0000ff00, 0x00ff0000, 0xff000000 }
137 };
138
139 static void
140 gst_revtv_base_init (gpointer g_class)
141 {
142   /* elementfactory information */
143   static GstElementDetails gst_revtv_details = GST_ELEMENT_DETAILS (
144     "RevTV",
145     "Filter/Effect/Video",
146     "A video waveform monitor for each line of video processed",
147     "Wim Taymans <wim.taymans@chello.be>"
148   );
149
150   GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
151   GstVideofilterClass *videofilter_class = GST_VIDEOFILTER_CLASS (g_class);
152   int i;
153   
154   gst_element_class_set_details (element_class, &gst_revtv_details);
155
156   for(i=0; i < G_N_ELEMENTS(gst_revtv_formats); i++) {
157     gst_videofilter_class_add_format(videofilter_class,
158         gst_revtv_formats + i);
159   }
160
161   gst_videofilter_class_add_pad_templates (GST_VIDEOFILTER_CLASS (g_class));
162 }
163
164 static void
165 gst_revtv_class_init (gpointer klass, gpointer class_data)
166 {
167   GObjectClass *gobject_class;
168   GstVideofilterClass *videofilter_class;
169
170   gobject_class = G_OBJECT_CLASS (klass);
171   videofilter_class = GST_VIDEOFILTER_CLASS (klass);
172
173   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_DELAY,
174     g_param_spec_int ("delay","Delay","Delay in frames between updates",
175                         1, 100, 1, G_PARAM_READWRITE));
176   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_LINESPACE,
177     g_param_spec_int ("linespace","Linespace","Control line spacing",
178                         1, 100, 6, G_PARAM_READWRITE));
179   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_GAIN,
180     g_param_spec_int ("gain","Gain","Control gain",
181                         1, 200, 50, G_PARAM_READWRITE));
182
183   gobject_class->set_property = gst_revtv_set_property;
184   gobject_class->get_property = gst_revtv_get_property;
185
186   videofilter_class->setup = gst_revtv_setup;
187 }
188
189 static void
190 gst_revtv_init (GTypeInstance *instance, gpointer g_class)
191 {
192   GstRevTV *restv = GST_REVTV (instance);
193
194   restv->vgrabtime = 1;
195   restv->vgrab = 0;
196   restv->linespace = 6;
197   restv->vscale = 50;
198 }
199
200 static void
201 gst_revtv_setup (GstVideofilter *videofilter)
202 {
203   GstRevTV *revtv;
204
205   g_return_if_fail (GST_IS_REVTV (videofilter));
206   revtv = GST_REVTV (videofilter);
207
208   revtv->width = gst_videofilter_get_input_width (videofilter);
209   revtv->height = gst_videofilter_get_input_height (videofilter);
210 }
211
212 static void
213 gst_revtv_rgb32 (GstVideofilter *videofilter, void *d, void *s)
214 {
215   GstRevTV *filter;
216   guint32 *src, *dest;
217   gint width, height;
218   guint32 *nsrc;
219   gint y, x, R, G, B, yval;
220
221   filter = GST_REVTV (videofilter);
222
223   src = (guint32 *) s;
224   dest = (guint32 *) d;
225
226   width = filter->width;
227   height = filter->height;
228
229   /* Clear everything to black */
230   memset (dest, 0, width*height*sizeof(guint32));
231
232   // draw the offset lines
233   for (y = 0; y < height ; y += filter->linespace){
234     for (x = 0; x <= width; x++) {
235       nsrc = src + (y * width) + x;
236
237       // Calc Y Value for curpix
238       R = ((*nsrc) & 0xff0000) >> (16 - 1);
239       G = ((*nsrc) & 0xff00) >> (8 - 2);
240       B =  (*nsrc) & 0xff;
241
242       yval = y - ((short) (R + G + B) / filter->vscale) ;
243
244       if (yval > 0) {
245         dest[x + (yval * width)] = THE_COLOR;
246       }
247     }
248   }
249 }
250
251 static void
252 gst_revtv_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec)
253 {
254   GstRevTV *filter;
255
256   /* it's not null if we got it, but it might not be ours */
257   g_return_if_fail (GST_IS_REVTV (object));
258
259   filter = GST_REVTV (object);
260
261   switch (prop_id) {
262     case ARG_DELAY:
263       filter->vgrabtime = g_value_get_int (value);
264       break;
265     case ARG_LINESPACE:
266       filter->linespace = g_value_get_int (value);
267       break;
268     case ARG_GAIN:
269       filter->vscale = g_value_get_int (value);
270       break;
271     default:
272       break;
273   }
274 }
275
276 static void
277 gst_revtv_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec)
278 {
279   GstRevTV *filter;
280
281   /* it's not null if we got it, but it might not be ours */
282   g_return_if_fail (GST_IS_REVTV (object));
283
284   filter = GST_REVTV (object);
285
286   switch (prop_id) {
287     case ARG_DELAY:
288       g_value_set_int (value, filter->vgrabtime);
289       break;
290     case ARG_LINESPACE:
291       g_value_set_int (value, filter->linespace);
292       break;
293     case ARG_GAIN:
294       g_value_set_int (value, filter->vscale);
295       break;
296     default:
297       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
298       break;
299   }
300 }