gstreamer/gst/effectv/gstedge.c
Julien Moutte 2ea4f5b3c9 VideoFilter inherits from
Original commit message from CVS:
2005-11-23  Julien MOUTTE  <julien@moutte.net>

* ext/cairo/gsttimeoverlay.c:
(gst_timeoverlay_update_font_height),
(gst_timeoverlay_set_caps), (gst_timeoverlay_get_unit_size),
(gst_timeoverlay_transform), (gst_timeoverlay_base_init),
(gst_timeoverlay_class_init), (gst_timeoverlay_init),
(gst_timeoverlay_get_type):
* ext/cairo/gsttimeoverlay.h:
* gst/debug/Makefile.am:
* gst/debug/gstnavigationtest.c:
(gst_navigationtest_handle_src_event),
(gst_navigationtest_get_unit_size),
(gst_navigationtest_set_caps),
(gst_navigationtest_transform),
(gst_navigationtest_change_state),
(gst_navigationtest_base_init), (gst_navigationtest_class_init),
(gst_navigationtest_init), (gst_navigationtest_get_type),
(plugin_init):
* gst/debug/gstnavigationtest.h:
* gst/effectv/Makefile.am:
* gst/effectv/gstaging.c: (gst_agingtv_set_caps),
(gst_agingtv_get_unit_size), (gst_agingtv_transform),
(gst_agingtv_base_init), (gst_agingtv_class_init),
(gst_agingtv_init), (gst_agingtv_get_type):
* gst/effectv/gstdice.c: (gst_dicetv_set_caps),
(gst_dicetv_get_unit_size), (gst_dicetv_transform),
(gst_dicetv_base_init), (gst_dicetv_class_init),
(gst_dicetv_init),
(gst_dicetv_get_type):
* gst/effectv/gstedge.c: (gst_edgetv_set_caps),
(gst_edgetv_get_unit_size), (gst_edgetv_transform),
(gst_edgetv_base_init), (gst_edgetv_class_init),
(gst_edgetv_init),
(gst_edgetv_get_type):
* gst/effectv/gsteffectv.c:
* gst/effectv/gsteffectv.h:
* gst/effectv/gstquark.c: (gst_quarktv_set_caps),
(gst_quarktv_get_unit_size), (fastrand),
(gst_quarktv_transform),
(gst_quarktv_change_state), (gst_quarktv_base_init),
(gst_quarktv_class_init), (gst_quarktv_init),
(gst_quarktv_get_type):
* gst/effectv/gstrev.c: (gst_revtv_set_caps),
(gst_revtv_get_unit_size), (gst_revtv_transform),
(gst_revtv_base_init), (gst_revtv_class_init), (gst_revtv_init),
(gst_revtv_get_type):
* gst/effectv/gstshagadelic.c: (gst_shagadelictv_set_caps),
(gst_shagadelictv_get_unit_size), (gst_shagadelictv_transform),
(gst_shagadelictv_base_init), (gst_shagadelictv_class_init),
(gst_shagadelictv_init), (gst_shagadelictv_get_type):
* gst/effectv/gstvertigo.c: (gst_vertigotv_set_caps),
(gst_vertigotv_get_unit_size), (gst_vertigotv_transform),
(gst_vertigotv_base_init), (gst_vertigotv_class_init),
(gst_vertigotv_init), (gst_vertigotv_get_type):
* gst/effectv/gstwarp.c: (gst_warptv_set_caps),
(gst_warptv_get_unit_size), (gst_warptv_transform),
(gst_warptv_base_init), (gst_warptv_class_init),
(gst_warptv_init),
(gst_warptv_get_type):
* gst/videofilter/Makefile.am:
* gst/videofilter/gstvideobalance.c:
* gst/videofilter/gstvideobalance.h:
* gst/videofilter/gstvideofilter.c: (gst_videofilter_get_type),
(gst_videofilter_class_init), (gst_videofilter_init):
* gst/videofilter/gstvideofilter.h:
* gst/videofilter/gstvideoflip.c: (gst_videoflip_set_caps),
(gst_videoflip_transform_caps), (gst_videoflip_get_unit_size),
(gst_videoflip_flip), (gst_videoflip_transform),
(gst_videoflip_handle_src_event), (gst_videoflip_set_property),
(gst_videoflip_base_init), (gst_videoflip_class_init),
(gst_videoflip_init), (plugin_init), (gst_videoflip_get_type):
* gst/videofilter/gstvideoflip.h: VideoFilter inherits from
BaseTransform, it's just a place holder for now and every video
effect plugin has been ported to use BaseTransform features
directly. QuarkTV was fixed too (was broken), navigationtest
works
and best for the end, videoflip converts navigation events
depending
on flip method ! Fixes #320953
2005-11-23 15:50:51 +00:00

298 lines
8 KiB
C

/* GStreamer
* Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
*
* EffecTV:
* Copyright (C) 2001 FUKUCHI Kentarou
*
* EffecTV is free software. * This library is free software;
* you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <gstvideofilter.h>
#include <string.h>
#include <gst/video/video.h>
#define GST_TYPE_EDGETV \
(gst_edgetv_get_type())
#define GST_EDGETV(obj) \
(G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_EDGETV,GstEdgeTV))
#define GST_EDGETV_CLASS(klass) \
(G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_EDGETV,GstEdgeTVClass))
#define GST_IS_EDGETV(obj) \
(G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_EDGETV))
#define GST_IS_EDGETV_CLASS(obj) \
(G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_EDGETV))
typedef struct _GstEdgeTV GstEdgeTV;
typedef struct _GstEdgeTVClass GstEdgeTVClass;
struct _GstEdgeTV
{
GstVideofilter videofilter;
gint width, height;
gint map_width, map_height;
guint32 *map;
gint video_width_margin;
};
struct _GstEdgeTVClass
{
GstVideofilterClass parent_class;
};
GType gst_edgetv_get_type (void);
static GstElementDetails gst_edgetv_details = GST_ELEMENT_DETAILS ("EdgeTV",
"Filter/Effect/Video",
"Apply edge detect on video",
"Wim Taymans <wim.taymans@chello.be>");
static GstStaticPadTemplate gst_edgetv_src_template =
GST_STATIC_PAD_TEMPLATE ("src",
GST_PAD_SRC,
GST_PAD_ALWAYS,
GST_STATIC_CAPS (GST_VIDEO_CAPS_BGRx)
);
static GstStaticPadTemplate gst_edgetv_sink_template =
GST_STATIC_PAD_TEMPLATE ("sink",
GST_PAD_SINK,
GST_PAD_ALWAYS,
GST_STATIC_CAPS (GST_VIDEO_CAPS_BGRx)
);
static GstVideofilterClass *parent_class = NULL;
static gboolean
gst_edgetv_set_caps (GstBaseTransform * btrans, GstCaps * incaps,
GstCaps * outcaps)
{
GstEdgeTV *edgetv = GST_EDGETV (btrans);
GstStructure *structure;
gboolean ret = FALSE;
structure = gst_caps_get_structure (incaps, 0);
if (gst_structure_get_int (structure, "width", &edgetv->width) &&
gst_structure_get_int (structure, "height", &edgetv->height)) {
edgetv->map_width = edgetv->width / 4;
edgetv->map_height = edgetv->height / 4;
edgetv->video_width_margin = edgetv->width % 4;
g_free (edgetv->map);
edgetv->map =
(guint32 *) g_malloc (edgetv->map_width * edgetv->map_height *
sizeof (guint32) * 2);
memset (edgetv->map, 0,
edgetv->map_width * edgetv->map_height * sizeof (guint32) * 2);
ret = TRUE;
}
return ret;
}
static gboolean
gst_edgetv_get_unit_size (GstBaseTransform * btrans, GstCaps * caps,
guint * size)
{
GstEdgeTV *filter;
GstStructure *structure;
gboolean ret = FALSE;
gint width, height;
filter = GST_EDGETV (btrans);
structure = gst_caps_get_structure (caps, 0);
if (gst_structure_get_int (structure, "width", &width) &&
gst_structure_get_int (structure, "height", &height)) {
*size = width * height * 32 / 8;
ret = TRUE;
GST_DEBUG_OBJECT (filter, "our frame size is %d bytes (%dx%d)", *size,
width, height);
}
return ret;
}
static GstFlowReturn
gst_edgetv_transform (GstBaseTransform * trans, GstBuffer * in, GstBuffer * out)
{
GstEdgeTV *filter;
gint x, y, r, g, b;
guint32 *src, *dest;
guint32 p, q;
guint32 v0, v1, v2, v3;
GstFlowReturn ret = GST_FLOW_OK;
filter = GST_EDGETV (trans);
gst_buffer_stamp (out, in);
src = (guint32 *) GST_BUFFER_DATA (in);
dest = (guint32 *) GST_BUFFER_DATA (out);
src += filter->width * 4 + 4;
dest += filter->width * 4 + 4;
for (y = 1; y < filter->map_height - 1; y++) {
for (x = 1; x < filter->map_width - 1; x++) {
p = *src;
q = *(src - 4);
/* difference between the current pixel and right neighbor. */
r = ((p & 0xff0000) - (q & 0xff0000)) >> 16;
g = ((p & 0xff00) - (q & 0xff00)) >> 8;
b = (p & 0xff) - (q & 0xff);
r *= r;
g *= g;
b *= b;
r = r >> 5; /* To lack the lower bit for saturated addition, */
g = g >> 5; /* devide the value with 32, instead of 16. It is */
b = b >> 4; /* same as `v2 &= 0xfefeff' */
if (r > 127)
r = 127;
if (g > 127)
g = 127;
if (b > 255)
b = 255;
v2 = (r << 17) | (g << 9) | b;
/* difference between the current pixel and upper neighbor. */
q = *(src - filter->width * 4);
r = ((p & 0xff0000) - (q & 0xff0000)) >> 16;
g = ((p & 0xff00) - (q & 0xff00)) >> 8;
b = (p & 0xff) - (q & 0xff);
r *= r;
g *= g;
b *= b;
r = r >> 5;
g = g >> 5;
b = b >> 4;
if (r > 127)
r = 127;
if (g > 127)
g = 127;
if (b > 255)
b = 255;
v3 = (r << 17) | (g << 9) | b;
v0 = filter->map[(y - 1) * filter->map_width * 2 + x * 2];
v1 = filter->map[y * filter->map_width * 2 + (x - 1) * 2 + 1];
filter->map[y * filter->map_width * 2 + x * 2] = v2;
filter->map[y * filter->map_width * 2 + x * 2 + 1] = v3;
r = v0 + v1;
g = r & 0x01010100;
dest[0] = r | (g - (g >> 8));
r = v0 + v3;
g = r & 0x01010100;
dest[1] = r | (g - (g >> 8));
dest[2] = v3;
dest[3] = v3;
r = v2 + v1;
g = r & 0x01010100;
dest[filter->width] = r | (g - (g >> 8));
r = v2 + v3;
g = r & 0x01010100;
dest[filter->width + 1] = r | (g - (g >> 8));
dest[filter->width + 2] = v3;
dest[filter->width + 3] = v3;
dest[filter->width * 2] = v2;
dest[filter->width * 2 + 1] = v2;
dest[filter->width * 3] = v2;
dest[filter->width * 3 + 1] = v2;
src += 4;
dest += 4;
}
src += filter->width * 3 + 8 + filter->video_width_margin;
dest += filter->width * 3 + 8 + filter->video_width_margin;
}
return ret;
}
static void
gst_edgetv_base_init (gpointer g_class)
{
GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
gst_element_class_set_details (element_class, &gst_edgetv_details);
gst_element_class_add_pad_template (element_class,
gst_static_pad_template_get (&gst_edgetv_sink_template));
gst_element_class_add_pad_template (element_class,
gst_static_pad_template_get (&gst_edgetv_src_template));
}
static void
gst_edgetv_class_init (gpointer klass, gpointer class_data)
{
GObjectClass *gobject_class;
GstElementClass *element_class;
GstBaseTransformClass *trans_class;
gobject_class = (GObjectClass *) klass;
element_class = (GstElementClass *) klass;
trans_class = (GstBaseTransformClass *) klass;
parent_class = g_type_class_peek_parent (klass);
trans_class->set_caps = GST_DEBUG_FUNCPTR (gst_edgetv_set_caps);
trans_class->get_unit_size = GST_DEBUG_FUNCPTR (gst_edgetv_get_unit_size);
trans_class->transform = GST_DEBUG_FUNCPTR (gst_edgetv_transform);
}
static void
gst_edgetv_init (GTypeInstance * instance, gpointer g_class)
{
GstEdgeTV *edgetv = GST_EDGETV (instance);
edgetv->map = NULL;
}
GType
gst_edgetv_get_type (void)
{
static GType edgetv_type = 0;
if (!edgetv_type) {
static const GTypeInfo edgetv_info = {
sizeof (GstEdgeTVClass),
gst_edgetv_base_init,
NULL,
(GClassInitFunc) gst_edgetv_class_init,
NULL,
NULL,
sizeof (GstEdgeTV),
0,
(GInstanceInitFunc) gst_edgetv_init,
};
edgetv_type =
g_type_register_static (GST_TYPE_VIDEOFILTER, "GstEdgeTV", &edgetv_info,
0);
}
return edgetv_type;
}