2 * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
5 * Copyright (C) 2001 FUKUCHI Kentarou
7 * EffecTV is free software. * This library is free software;
8 * 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.
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.
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.
28 #include <gst/video/gstvideofilter.h>
32 #include <gst/video/video.h>
34 #define GST_TYPE_EDGETV \
35 (gst_edgetv_get_type())
36 #define GST_EDGETV(obj) \
37 (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_EDGETV,GstEdgeTV))
38 #define GST_EDGETV_CLASS(klass) \
39 (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_EDGETV,GstEdgeTVClass))
40 #define GST_IS_EDGETV(obj) \
41 (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_EDGETV))
42 #define GST_IS_EDGETV_CLASS(obj) \
43 (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_EDGETV))
45 typedef struct _GstEdgeTV GstEdgeTV;
46 typedef struct _GstEdgeTVClass GstEdgeTVClass;
50 GstVideoFilter videofilter;
53 gint map_width, map_height;
55 gint video_width_margin;
58 struct _GstEdgeTVClass
60 GstVideoFilterClass parent_class;
63 GType gst_edgetv_get_type (void);
65 static const GstElementDetails gst_edgetv_details =
66 GST_ELEMENT_DETAILS ("EdgeTV effect",
67 "Filter/Effect/Video",
68 "Apply edge detect on video",
69 "Wim Taymans <wim.taymans@chello.be>");
71 static GstStaticPadTemplate gst_edgetv_src_template =
72 GST_STATIC_PAD_TEMPLATE ("src",
75 GST_STATIC_CAPS (GST_VIDEO_CAPS_BGRx)
78 static GstStaticPadTemplate gst_edgetv_sink_template =
79 GST_STATIC_PAD_TEMPLATE ("sink",
82 GST_STATIC_CAPS (GST_VIDEO_CAPS_BGRx)
85 static GstVideoFilterClass *parent_class = NULL;
88 gst_edgetv_set_caps (GstBaseTransform * btrans, GstCaps * incaps,
91 GstEdgeTV *edgetv = GST_EDGETV (btrans);
92 GstStructure *structure;
95 structure = gst_caps_get_structure (incaps, 0);
97 if (gst_structure_get_int (structure, "width", &edgetv->width) &&
98 gst_structure_get_int (structure, "height", &edgetv->height)) {
99 edgetv->map_width = edgetv->width / 4;
100 edgetv->map_height = edgetv->height / 4;
101 edgetv->video_width_margin = edgetv->width % 4;
103 g_free (edgetv->map);
105 (guint32 *) g_malloc (edgetv->map_width * edgetv->map_height *
106 sizeof (guint32) * 2);
107 memset (edgetv->map, 0,
108 edgetv->map_width * edgetv->map_height * sizeof (guint32) * 2);
116 gst_edgetv_get_unit_size (GstBaseTransform * btrans, GstCaps * caps,
120 GstStructure *structure;
121 gboolean ret = FALSE;
124 filter = GST_EDGETV (btrans);
126 structure = gst_caps_get_structure (caps, 0);
128 if (gst_structure_get_int (structure, "width", &width) &&
129 gst_structure_get_int (structure, "height", &height)) {
130 *size = width * height * 32 / 8;
132 GST_DEBUG_OBJECT (filter, "our frame size is %d bytes (%dx%d)", *size,
140 gst_edgetv_transform (GstBaseTransform * trans, GstBuffer * in, GstBuffer * out)
146 guint32 v0, v1, v2, v3;
147 GstFlowReturn ret = GST_FLOW_OK;
149 filter = GST_EDGETV (trans);
151 gst_buffer_stamp (out, in);
153 src = (guint32 *) GST_BUFFER_DATA (in);
154 dest = (guint32 *) GST_BUFFER_DATA (out);
156 src += filter->width * 4 + 4;
157 dest += filter->width * 4 + 4;
159 for (y = 1; y < filter->map_height - 1; y++) {
160 for (x = 1; x < filter->map_width - 1; x++) {
165 /* difference between the current pixel and right neighbor. */
166 r = ((p & 0xff0000) - (q & 0xff0000)) >> 16;
167 g = ((p & 0xff00) - (q & 0xff00)) >> 8;
168 b = (p & 0xff) - (q & 0xff);
172 r = r >> 5; /* To lack the lower bit for saturated addition, */
173 g = g >> 5; /* devide the value with 32, instead of 16. It is */
174 b = b >> 4; /* same as `v2 &= 0xfefeff' */
181 v2 = (r << 17) | (g << 9) | b;
183 /* difference between the current pixel and upper neighbor. */
184 q = *(src - filter->width * 4);
185 r = ((p & 0xff0000) - (q & 0xff0000)) >> 16;
186 g = ((p & 0xff00) - (q & 0xff00)) >> 8;
187 b = (p & 0xff) - (q & 0xff);
200 v3 = (r << 17) | (g << 9) | b;
202 v0 = filter->map[(y - 1) * filter->map_width * 2 + x * 2];
203 v1 = filter->map[y * filter->map_width * 2 + (x - 1) * 2 + 1];
204 filter->map[y * filter->map_width * 2 + x * 2] = v2;
205 filter->map[y * filter->map_width * 2 + x * 2 + 1] = v3;
208 dest[0] = r | (g - (g >> 8));
211 dest[1] = r | (g - (g >> 8));
216 dest[filter->width] = r | (g - (g >> 8));
219 dest[filter->width + 1] = r | (g - (g >> 8));
220 dest[filter->width + 2] = v3;
221 dest[filter->width + 3] = v3;
222 dest[filter->width * 2] = v2;
223 dest[filter->width * 2 + 1] = v2;
224 dest[filter->width * 3] = v2;
225 dest[filter->width * 3 + 1] = v2;
230 src += filter->width * 3 + 8 + filter->video_width_margin;
231 dest += filter->width * 3 + 8 + filter->video_width_margin;
238 gst_edgetv_base_init (gpointer g_class)
240 GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
242 gst_element_class_set_details (element_class, &gst_edgetv_details);
244 gst_element_class_add_pad_template (element_class,
245 gst_static_pad_template_get (&gst_edgetv_sink_template));
246 gst_element_class_add_pad_template (element_class,
247 gst_static_pad_template_get (&gst_edgetv_src_template));
251 gst_edgetv_class_init (gpointer klass, gpointer class_data)
253 GObjectClass *gobject_class;
254 GstElementClass *element_class;
255 GstBaseTransformClass *trans_class;
257 gobject_class = (GObjectClass *) klass;
258 element_class = (GstElementClass *) klass;
259 trans_class = (GstBaseTransformClass *) klass;
261 parent_class = g_type_class_peek_parent (klass);
263 trans_class->set_caps = GST_DEBUG_FUNCPTR (gst_edgetv_set_caps);
264 trans_class->get_unit_size = GST_DEBUG_FUNCPTR (gst_edgetv_get_unit_size);
265 trans_class->transform = GST_DEBUG_FUNCPTR (gst_edgetv_transform);
269 gst_edgetv_init (GTypeInstance * instance, gpointer g_class)
271 GstEdgeTV *edgetv = GST_EDGETV (instance);
277 gst_edgetv_get_type (void)
279 static GType edgetv_type = 0;
282 static const GTypeInfo edgetv_info = {
283 sizeof (GstEdgeTVClass),
284 gst_edgetv_base_init,
286 (GClassInitFunc) gst_edgetv_class_init,
291 (GInstanceInitFunc) gst_edgetv_init,
295 g_type_register_static (GST_TYPE_VIDEO_FILTER, "GstEdgeTV",