test: rtpbin_buffer_list: check if the chain_list function has been called
[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., 51 Franklin St, Fifth Floor,
40  * Boston, MA 02110-1301, USA.
41  */
42
43 /**
44  * SECTION:element-revtv
45  *
46  * RevTV acts like a video waveform monitor for each line of video
47  * processed. This creates a pseudo 3D effect based on the brightness
48  * of the video along each line.
49  *
50  * <refsect2>
51  * <title>Example launch line</title>
52  * |[
53  * gst-launch-1.0 -v videotestsrc ! revtv ! videoconvert ! autovideosink
54  * ]| This pipeline shows the effect of revtv on a test stream.
55  * </refsect2>
56  */
57
58 #ifdef HAVE_CONFIG_H
59 #include "config.h"
60 #endif
61
62 #include <math.h>
63 #include <string.h>
64
65 #include "gstrev.h"
66
67 #define THE_COLOR 0xffffffff
68
69 enum
70 {
71   PROP_0,
72   PROP_DELAY,
73   PROP_LINESPACE,
74   PROP_GAIN
75 };
76
77 #define gst_revtv_parent_class parent_class
78 G_DEFINE_TYPE (GstRevTV, gst_revtv, GST_TYPE_VIDEO_FILTER);
79
80 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
81 #define CAPS_STR GST_VIDEO_CAPS_MAKE ("{ BGRx, RGBx }")
82 #else
83 #define CAPS_STR GST_VIDEO_CAPS_MAKE ("{ xBGR, xRGB }")
84 #endif
85
86 static GstStaticPadTemplate gst_revtv_src_template =
87 GST_STATIC_PAD_TEMPLATE ("src",
88     GST_PAD_SRC,
89     GST_PAD_ALWAYS,
90     GST_STATIC_CAPS (CAPS_STR)
91     );
92
93 static GstStaticPadTemplate gst_revtv_sink_template =
94 GST_STATIC_PAD_TEMPLATE ("sink",
95     GST_PAD_SINK,
96     GST_PAD_ALWAYS,
97     GST_STATIC_CAPS (CAPS_STR)
98     );
99
100 static GstFlowReturn
101 gst_revtv_transform_frame (GstVideoFilter * vfilter, GstVideoFrame * in_frame,
102     GstVideoFrame * out_frame)
103 {
104   GstRevTV *filter = GST_REVTV (vfilter);
105   guint32 *src, *dest;
106   gint width, height, sstride, dstride;
107   guint32 *nsrc;
108   gint y, x, R, G, B, yval;
109   gint linespace, vscale;
110   GstClockTime timestamp, stream_time;
111
112   timestamp = GST_BUFFER_TIMESTAMP (in_frame->buffer);
113   stream_time =
114       gst_segment_to_stream_time (&GST_BASE_TRANSFORM (vfilter)->segment,
115       GST_FORMAT_TIME, timestamp);
116
117   GST_DEBUG_OBJECT (filter, "sync to %" GST_TIME_FORMAT,
118       GST_TIME_ARGS (timestamp));
119
120   if (GST_CLOCK_TIME_IS_VALID (stream_time))
121     gst_object_sync_values (GST_OBJECT (filter), stream_time);
122
123   src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
124   sstride = GST_VIDEO_FRAME_PLANE_STRIDE (in_frame, 0);
125   dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
126   dstride = GST_VIDEO_FRAME_PLANE_STRIDE (out_frame, 0);
127
128   width = GST_VIDEO_FRAME_WIDTH (in_frame);
129   height = GST_VIDEO_FRAME_HEIGHT (in_frame);
130
131   /* Clear everything to black */
132   memset (dest, 0, dstride * height);
133
134   GST_OBJECT_LOCK (filter);
135   linespace = filter->linespace;
136   vscale = filter->vscale;
137
138   /* draw the offset lines */
139   for (y = 0; y < height; y += linespace) {
140     for (x = 0; x <= width; x++) {
141       nsrc = src + (y * sstride / 4) + x;
142
143       /* Calc Y Value for curpix */
144       R = ((*nsrc) & 0xff0000) >> (16 - 1);
145       G = ((*nsrc) & 0xff00) >> (8 - 2);
146       B = (*nsrc) & 0xff;
147
148       yval = y - ((short) (R + G + B) / vscale);
149
150       if (yval > 0) {
151         dest[x + (yval * dstride / 4)] = THE_COLOR;
152       }
153     }
154   }
155   GST_OBJECT_UNLOCK (filter);
156
157   return GST_FLOW_OK;
158 }
159
160 static void
161 gst_revtv_set_property (GObject * object, guint prop_id, const GValue * value,
162     GParamSpec * pspec)
163 {
164   GstRevTV *filter = GST_REVTV (object);
165
166   GST_OBJECT_LOCK (filter);
167   switch (prop_id) {
168     case PROP_DELAY:
169       filter->vgrabtime = g_value_get_int (value);
170       break;
171     case PROP_LINESPACE:
172       filter->linespace = g_value_get_int (value);
173       break;
174     case PROP_GAIN:
175       filter->vscale = g_value_get_int (value);
176       break;
177     default:
178       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
179       break;
180   }
181   GST_OBJECT_UNLOCK (filter);
182 }
183
184 static void
185 gst_revtv_get_property (GObject * object, guint prop_id, GValue * value,
186     GParamSpec * pspec)
187 {
188   GstRevTV *filter = GST_REVTV (object);
189
190   switch (prop_id) {
191     case PROP_DELAY:
192       g_value_set_int (value, filter->vgrabtime);
193       break;
194     case PROP_LINESPACE:
195       g_value_set_int (value, filter->linespace);
196       break;
197     case PROP_GAIN:
198       g_value_set_int (value, filter->vscale);
199       break;
200     default:
201       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
202       break;
203   }
204 }
205
206 static void
207 gst_revtv_class_init (GstRevTVClass * klass)
208 {
209   GObjectClass *gobject_class = (GObjectClass *) klass;
210   GstElementClass *gstelement_class = (GstElementClass *) klass;
211   GstVideoFilterClass *vfilter_class = (GstVideoFilterClass *) klass;
212
213   gobject_class->set_property = gst_revtv_set_property;
214   gobject_class->get_property = gst_revtv_get_property;
215
216   g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_DELAY,
217       g_param_spec_int ("delay", "Delay", "Delay in frames between updates",
218           1, 100, 1,
219           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | GST_PARAM_CONTROLLABLE));
220   g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_LINESPACE,
221       g_param_spec_int ("linespace", "Linespace", "Control line spacing", 1,
222           100, 6,
223           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | GST_PARAM_CONTROLLABLE));
224   g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_GAIN,
225       g_param_spec_int ("gain", "Gain", "Control gain", 1, 200, 50,
226           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | GST_PARAM_CONTROLLABLE));
227
228   gst_element_class_set_static_metadata (gstelement_class, "RevTV effect",
229       "Filter/Effect/Video",
230       "A video waveform monitor for each line of video processed",
231       "Wim Taymans <wim.taymans@gmail.be>");
232
233   gst_element_class_add_static_pad_template (gstelement_class,
234       &gst_revtv_sink_template);
235   gst_element_class_add_static_pad_template (gstelement_class,
236       &gst_revtv_src_template);
237
238   vfilter_class->transform_frame =
239       GST_DEBUG_FUNCPTR (gst_revtv_transform_frame);
240 }
241
242 static void
243 gst_revtv_init (GstRevTV * restv)
244 {
245   restv->vgrabtime = 1;
246   restv->vgrab = 0;
247   restv->linespace = 6;
248   restv->vscale = 50;
249 }