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 GstElementDetails gst_edgetv_details = GST_ELEMENT_DETAILS ("EdgeTV",
66 "Filter/Effect/Video",
67 "Apply edge detect on video",
68 "Wim Taymans <wim.taymans@chello.be>");
70 static GstStaticPadTemplate gst_edgetv_src_template =
71 GST_STATIC_PAD_TEMPLATE ("src",
74 GST_STATIC_CAPS (GST_VIDEO_CAPS_BGRx)
77 static GstStaticPadTemplate gst_edgetv_sink_template =
78 GST_STATIC_PAD_TEMPLATE ("sink",
81 GST_STATIC_CAPS (GST_VIDEO_CAPS_BGRx)
84 static GstVideoFilterClass *parent_class = NULL;
87 gst_edgetv_set_caps (GstBaseTransform * btrans, GstCaps * incaps,
90 GstEdgeTV *edgetv = GST_EDGETV (btrans);
91 GstStructure *structure;
94 structure = gst_caps_get_structure (incaps, 0);
96 if (gst_structure_get_int (structure, "width", &edgetv->width) &&
97 gst_structure_get_int (structure, "height", &edgetv->height)) {
98 edgetv->map_width = edgetv->width / 4;
99 edgetv->map_height = edgetv->height / 4;
100 edgetv->video_width_margin = edgetv->width % 4;
102 g_free (edgetv->map);
104 (guint32 *) g_malloc (edgetv->map_width * edgetv->map_height *
105 sizeof (guint32) * 2);
106 memset (edgetv->map, 0,
107 edgetv->map_width * edgetv->map_height * sizeof (guint32) * 2);
115 gst_edgetv_get_unit_size (GstBaseTransform * btrans, GstCaps * caps,
119 GstStructure *structure;
120 gboolean ret = FALSE;
123 filter = GST_EDGETV (btrans);
125 structure = gst_caps_get_structure (caps, 0);
127 if (gst_structure_get_int (structure, "width", &width) &&
128 gst_structure_get_int (structure, "height", &height)) {
129 *size = width * height * 32 / 8;
131 GST_DEBUG_OBJECT (filter, "our frame size is %d bytes (%dx%d)", *size,
139 gst_edgetv_transform (GstBaseTransform * trans, GstBuffer * in, GstBuffer * out)
145 guint32 v0, v1, v2, v3;
146 GstFlowReturn ret = GST_FLOW_OK;
148 filter = GST_EDGETV (trans);
150 gst_buffer_stamp (out, in);
152 src = (guint32 *) GST_BUFFER_DATA (in);
153 dest = (guint32 *) GST_BUFFER_DATA (out);
155 src += filter->width * 4 + 4;
156 dest += filter->width * 4 + 4;
158 for (y = 1; y < filter->map_height - 1; y++) {
159 for (x = 1; x < filter->map_width - 1; x++) {
164 /* difference between the current pixel and right neighbor. */
165 r = ((p & 0xff0000) - (q & 0xff0000)) >> 16;
166 g = ((p & 0xff00) - (q & 0xff00)) >> 8;
167 b = (p & 0xff) - (q & 0xff);
171 r = r >> 5; /* To lack the lower bit for saturated addition, */
172 g = g >> 5; /* devide the value with 32, instead of 16. It is */
173 b = b >> 4; /* same as `v2 &= 0xfefeff' */
180 v2 = (r << 17) | (g << 9) | b;
182 /* difference between the current pixel and upper neighbor. */
183 q = *(src - filter->width * 4);
184 r = ((p & 0xff0000) - (q & 0xff0000)) >> 16;
185 g = ((p & 0xff00) - (q & 0xff00)) >> 8;
186 b = (p & 0xff) - (q & 0xff);
199 v3 = (r << 17) | (g << 9) | b;
201 v0 = filter->map[(y - 1) * filter->map_width * 2 + x * 2];
202 v1 = filter->map[y * filter->map_width * 2 + (x - 1) * 2 + 1];
203 filter->map[y * filter->map_width * 2 + x * 2] = v2;
204 filter->map[y * filter->map_width * 2 + x * 2 + 1] = v3;
207 dest[0] = r | (g - (g >> 8));
210 dest[1] = r | (g - (g >> 8));
215 dest[filter->width] = r | (g - (g >> 8));
218 dest[filter->width + 1] = r | (g - (g >> 8));
219 dest[filter->width + 2] = v3;
220 dest[filter->width + 3] = v3;
221 dest[filter->width * 2] = v2;
222 dest[filter->width * 2 + 1] = v2;
223 dest[filter->width * 3] = v2;
224 dest[filter->width * 3 + 1] = v2;
229 src += filter->width * 3 + 8 + filter->video_width_margin;
230 dest += filter->width * 3 + 8 + filter->video_width_margin;
237 gst_edgetv_base_init (gpointer g_class)
239 GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
241 gst_element_class_set_details (element_class, &gst_edgetv_details);
243 gst_element_class_add_pad_template (element_class,
244 gst_static_pad_template_get (&gst_edgetv_sink_template));
245 gst_element_class_add_pad_template (element_class,
246 gst_static_pad_template_get (&gst_edgetv_src_template));
250 gst_edgetv_class_init (gpointer klass, gpointer class_data)
252 GObjectClass *gobject_class;
253 GstElementClass *element_class;
254 GstBaseTransformClass *trans_class;
256 gobject_class = (GObjectClass *) klass;
257 element_class = (GstElementClass *) klass;
258 trans_class = (GstBaseTransformClass *) klass;
260 parent_class = g_type_class_peek_parent (klass);
262 trans_class->set_caps = GST_DEBUG_FUNCPTR (gst_edgetv_set_caps);
263 trans_class->get_unit_size = GST_DEBUG_FUNCPTR (gst_edgetv_get_unit_size);
264 trans_class->transform = GST_DEBUG_FUNCPTR (gst_edgetv_transform);
268 gst_edgetv_init (GTypeInstance * instance, gpointer g_class)
270 GstEdgeTV *edgetv = GST_EDGETV (instance);
276 gst_edgetv_get_type (void)
278 static GType edgetv_type = 0;
281 static const GTypeInfo edgetv_info = {
282 sizeof (GstEdgeTVClass),
283 gst_edgetv_base_init,
285 (GClassInitFunc) gst_edgetv_class_init,
290 (GInstanceInitFunc) gst_edgetv_init,
294 g_type_register_static (GST_TYPE_VIDEO_FILTER, "GstEdgeTV",