2 * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
5 * Copyright (C) 2001 FUKUCHI Kentarou
7 * EffecTV - Realtime Digital Video Effector
8 * Copyright (C) 2001 FUKUCHI Kentarou
10 * revTV based on Rutt-Etra Video Synthesizer 1974?
12 * (c)2002 Ed Tannenbaum
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.
19 * Experimaental tapes were made with this system by Bill and
20 * Louise Etra and Woody and Steina Vasulka
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.
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.
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.
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.
47 #include <gst/video/gstvideofilter.h>
52 #include <gst/video/video.h>
54 #define GST_TYPE_REVTV \
55 (gst_revtv_get_type())
56 #define GST_REVTV(obj) \
57 (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_REVTV,GstRevTV))
58 #define GST_REVTV_CLASS(klass) \
59 (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_REVTV,GstRevTVClass))
60 #define GST_IS_REVTV(obj) \
61 (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_REVTV))
62 #define GST_IS_REVTV_CLASS(klass) \
63 (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_REVTV))
65 #define THE_COLOR 0xffffffff
67 typedef struct _GstRevTV GstRevTV;
68 typedef struct _GstRevTVClass GstRevTVClass;
72 GstVideoFilter videofilter;
83 GstVideoFilterClass parent_class;
94 GType gst_revtv_get_type (void);
96 static const GstElementDetails gst_revtv_details =
97 GST_ELEMENT_DETAILS ("RevTV effect",
98 "Filter/Effect/Video",
99 "A video waveform monitor for each line of video processed",
100 "Wim Taymans <wim.taymans@chello.be>");
102 static GstStaticPadTemplate gst_revtv_src_template =
103 GST_STATIC_PAD_TEMPLATE ("src",
106 GST_STATIC_CAPS (GST_VIDEO_CAPS_BGRx)
109 static GstStaticPadTemplate gst_revtv_sink_template =
110 GST_STATIC_PAD_TEMPLATE ("sink",
113 GST_STATIC_CAPS (GST_VIDEO_CAPS_BGRx)
116 static GstVideoFilterClass *parent_class = NULL;
119 gst_revtv_set_caps (GstBaseTransform * btrans, GstCaps * incaps,
122 GstRevTV *filter = GST_REVTV (btrans);
123 GstStructure *structure;
124 gboolean ret = FALSE;
126 structure = gst_caps_get_structure (incaps, 0);
128 if (gst_structure_get_int (structure, "width", &filter->width) &&
129 gst_structure_get_int (structure, "height", &filter->height)) {
137 gst_revtv_get_unit_size (GstBaseTransform * btrans, GstCaps * caps,
141 GstStructure *structure;
142 gboolean ret = FALSE;
145 filter = GST_REVTV (btrans);
147 structure = gst_caps_get_structure (caps, 0);
149 if (gst_structure_get_int (structure, "width", &width) &&
150 gst_structure_get_int (structure, "height", &height)) {
151 *size = width * height * 32 / 8;
153 GST_DEBUG_OBJECT (filter, "our frame size is %d bytes (%dx%d)", *size,
161 gst_revtv_transform (GstBaseTransform * trans, GstBuffer * in, GstBuffer * out)
167 gint y, x, R, G, B, yval;
168 GstFlowReturn ret = GST_FLOW_OK;
170 filter = GST_REVTV (trans);
172 gst_buffer_copy_metadata (out, in, GST_BUFFER_COPY_TIMESTAMPS);
174 src = (guint32 *) GST_BUFFER_DATA (in);
175 dest = (guint32 *) GST_BUFFER_DATA (out);
177 width = filter->width;
178 height = filter->height;
180 /* Clear everything to black */
181 memset (dest, 0, width * height * sizeof (guint32));
183 // draw the offset lines
184 for (y = 0; y < height; y += filter->linespace) {
185 for (x = 0; x <= width; x++) {
186 nsrc = src + (y * width) + x;
188 // Calc Y Value for curpix
189 R = ((*nsrc) & 0xff0000) >> (16 - 1);
190 G = ((*nsrc) & 0xff00) >> (8 - 2);
193 yval = y - ((short) (R + G + B) / filter->vscale);
196 dest[x + (yval * width)] = THE_COLOR;
205 gst_revtv_set_property (GObject * object, guint prop_id, const GValue * value,
210 g_return_if_fail (GST_IS_REVTV (object));
212 filter = GST_REVTV (object);
216 filter->vgrabtime = g_value_get_int (value);
219 filter->linespace = g_value_get_int (value);
222 filter->vscale = g_value_get_int (value);
230 gst_revtv_get_property (GObject * object, guint prop_id, GValue * value,
235 g_return_if_fail (GST_IS_REVTV (object));
237 filter = GST_REVTV (object);
241 g_value_set_int (value, filter->vgrabtime);
244 g_value_set_int (value, filter->linespace);
247 g_value_set_int (value, filter->vscale);
250 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
256 gst_revtv_base_init (gpointer g_class)
258 GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
260 gst_element_class_set_details (element_class, &gst_revtv_details);
262 gst_element_class_add_pad_template (element_class,
263 gst_static_pad_template_get (&gst_revtv_sink_template));
264 gst_element_class_add_pad_template (element_class,
265 gst_static_pad_template_get (&gst_revtv_src_template));
269 gst_revtv_class_init (gpointer klass, gpointer class_data)
271 GObjectClass *gobject_class;
272 GstBaseTransformClass *trans_class;
274 gobject_class = (GObjectClass *) klass;
275 trans_class = (GstBaseTransformClass *) klass;
277 parent_class = g_type_class_peek_parent (klass);
279 gobject_class->set_property = gst_revtv_set_property;
280 gobject_class->get_property = gst_revtv_get_property;
282 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_DELAY,
283 g_param_spec_int ("delay", "Delay", "Delay in frames between updates",
284 1, 100, 1, G_PARAM_READWRITE));
285 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_LINESPACE,
286 g_param_spec_int ("linespace", "Linespace", "Control line spacing",
287 1, 100, 6, G_PARAM_READWRITE));
288 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_GAIN,
289 g_param_spec_int ("gain", "Gain", "Control gain",
290 1, 200, 50, G_PARAM_READWRITE));
292 trans_class->set_caps = GST_DEBUG_FUNCPTR (gst_revtv_set_caps);
293 trans_class->get_unit_size = GST_DEBUG_FUNCPTR (gst_revtv_get_unit_size);
294 trans_class->transform = GST_DEBUG_FUNCPTR (gst_revtv_transform);
298 gst_revtv_init (GTypeInstance * instance, gpointer g_class)
300 GstRevTV *restv = GST_REVTV (instance);
302 restv->vgrabtime = 1;
304 restv->linespace = 6;
309 gst_revtv_get_type (void)
311 static GType revtv_type = 0;
314 static const GTypeInfo revtv_info = {
315 sizeof (GstRevTVClass),
318 (GClassInitFunc) gst_revtv_class_init,
323 (GInstanceInitFunc) gst_revtv_init,
327 g_type_register_static (GST_TYPE_VIDEO_FILTER, "GstRevTV", &revtv_info,