mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-03-09 13:21:16 +00:00
Original commit message from CVS: * ext/amrwb/gstamrwbdec.c: (gst_amrwbdec_class_init): * ext/amrwb/gstamrwbenc.c: (gst_amrwbenc_class_init): * ext/amrwb/gstamrwbparse.c: (gst_amrwbparse_class_init): * ext/arts/gst_arts.c: (gst_arts_class_init): * ext/artsd/gstartsdsink.c: (gst_artsdsink_class_init): * ext/audiofile/gstafsink.c: (gst_afsink_class_init): * ext/audiofile/gstafsrc.c: (gst_afsrc_class_init): * ext/audioresample/gstaudioresample.c: * ext/cdaudio/gstcdaudio.c: (gst_cdaudio_class_init): * ext/directfb/dfbvideosink.c: (gst_dfbvideosink_class_init): * ext/divx/gstdivxdec.c: (gst_divxdec_class_init): * ext/hermes/gsthermescolorspace.c: (gst_hermes_colorspace_class_init): * ext/ivorbis/vorbisfile.c: (gst_ivorbisfile_class_init): * ext/jack/gstjack.c: (gst_jack_class_init): * ext/jack/gstjackbin.c: (gst_jack_bin_class_init): * ext/lcs/gstcolorspace.c: (gst_colorspace_class_init): * ext/libfame/gstlibfame.c: (gst_fameenc_class_init): * ext/musicbrainz/gsttrm.c: (gst_musicbrainz_class_init): * ext/nas/nassink.c: (gst_nassink_class_init): * ext/shout/gstshout.c: (gst_icecastsend_class_init): * ext/snapshot/gstsnapshot.c: (gst_snapshot_class_init): * ext/sndfile/gstsf.c: (gst_sf_class_init): * ext/swfdec/gstswfdec.c: (gst_swfdecbuffer_class_init), (gst_swfdec_class_init): * ext/tarkin/gsttarkindec.c: (gst_tarkindec_class_init): * ext/tarkin/gsttarkinenc.c: (gst_tarkinenc_class_init): * gst/cdxaparse/gstcdxastrip.c: (gst_cdxastrip_class_init): * gst/chart/gstchart.c: (gst_chart_class_init): * gst/colorspace/gstcolorspace.c: (gst_colorspace_class_init): * gst/deinterlace/gstdeinterlace.c: (gst_deinterlace_class_init): * gst/festival/gstfestival.c: (gst_festival_class_init): * gst/filter/gstbpwsinc.c: (gst_bpwsinc_class_init): * gst/filter/gstiir.c: (gst_iir_class_init): * gst/filter/gstlpwsinc.c: (gst_lpwsinc_class_init): * gst/librfb/gstrfbsrc.c: (gst_rfbsrc_class_init): * gst/mixmatrix/mixmatrix.c: (gst_mixmatrix_class_init): * gst/mpeg1sys/gstmpeg1systemencode.c: (gst_system_encode_class_init): * gst/mpeg1videoparse/gstmp1videoparse.c: (gst_mp1videoparse_class_init): * gst/mpeg2sub/gstmpeg2subt.c: (gst_mpeg2subt_class_init): * gst/mpegaudioparse/gstmpegaudioparse.c: (gst_mp3parse_class_init): * gst/overlay/gstoverlay.c: (gst_overlay_class_init): * gst/passthrough/gstpassthrough.c: (passthrough_class_init): * gst/playondemand/gstplayondemand.c: (play_on_demand_class_init): * gst/rtjpeg/gstrtjpegdec.c: (gst_rtjpegdec_class_init): * gst/rtjpeg/gstrtjpegenc.c: (gst_rtjpegenc_class_init): * gst/smooth/gstsmooth.c: (gst_smooth_class_init): * gst/smoothwave/gstsmoothwave.c: (gst_smoothwave_class_init): * gst/spectrum/gstspectrum.c: (gst_spectrum_class_init): * gst/stereo/gststereo.c: (gst_stereo_class_init): * gst/switch/gstswitch.c: (gst_switch_class_init): * gst/tta/gstttadec.c: (gst_tta_dec_class_init): * gst/tta/gstttaparse.c: (gst_tta_parse_class_init): * gst/vbidec/gstvbidec.c: (gst_vbidec_class_init): * gst/videocrop/gstvideocrop.c: (gst_video_crop_class_init): * gst/virtualdub/gstxsharpen.c: (gst_xsharpen_class_init): * gst/y4m/gsty4mencode.c: (gst_y4mencode_class_init): * sys/cdrom/gstcdplayer.c: (cdplayer_class_init): * sys/directsound/gstdirectsoundsink.c: (gst_directsoundsink_class_init): * sys/dxr3/dxr3audiosink.c: (dxr3audiosink_class_init): * sys/dxr3/dxr3spusink.c: (dxr3spusink_class_init): * sys/dxr3/dxr3videosink.c: (dxr3videosink_class_init): * sys/qcam/gstqcamsrc.c: (gst_qcamsrc_class_init): * sys/v4l2/gstv4l2colorbalance.c: (gst_v4l2_color_balance_channel_class_init): * sys/v4l2/gstv4l2tuner.c: (gst_v4l2_tuner_channel_class_init), (gst_v4l2_tuner_norm_class_init): * sys/ximagesrc/ximagesrc.c: (gst_ximagesrc_class_init): Fix #337365 (g_type_class_ref <-> g_type_class_peek_parent)
436 lines
11 KiB
C
436 lines
11 KiB
C
/* GStreamer
|
|
* Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
|
|
*
|
|
* Filter:
|
|
* Copyright (C) 2000 Donald A. Graft
|
|
*
|
|
* 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 <string.h>
|
|
#include <gst/gst.h>
|
|
#include "gstvirtualdub.h"
|
|
|
|
#define GST_TYPE_XSHARPEN \
|
|
(gst_xsharpen_get_type())
|
|
#define GST_XSHARPEN(obj) \
|
|
(G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_XSHARPEN,GstXsharpen))
|
|
#define GST_XSHARPEN_CLASS(klass) \
|
|
(G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_ULAW,GstXsharpen))
|
|
#define GST_IS_XSHARPEN(obj) \
|
|
(G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_XSHARPEN))
|
|
#define GST_IS_XSHARPEN_CLASS(obj) \
|
|
(G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_XSHARPEN))
|
|
|
|
typedef struct _GstXsharpen GstXsharpen;
|
|
typedef struct _GstXsharpenClass GstXsharpenClass;
|
|
|
|
struct _GstXsharpen
|
|
{
|
|
GstElement element;
|
|
|
|
GstPad *sinkpad, *srcpad;
|
|
|
|
gint width, height;
|
|
gint strength, strengthinv, threshold;
|
|
gint srcpitch, dstpitch;
|
|
};
|
|
|
|
struct _GstXsharpenClass
|
|
{
|
|
GstElementClass parent_class;
|
|
};
|
|
|
|
GstElementDetails gst_xsharpen_details = GST_ELEMENT_DETAILS ("Sharpen",
|
|
"Filter/Video/Effect",
|
|
"LGPL",
|
|
"Apply a sharpen effect on video" VERSION,
|
|
"Jeremy SIMON <jsimon13@yahoo.fr>",
|
|
"(C) 2000 Donald Graft");
|
|
|
|
|
|
/* Filter signals and args */
|
|
enum
|
|
{
|
|
/* FILL ME */
|
|
ARG_STRENGTH,
|
|
ARG_THRESHOLD,
|
|
LAST_SIGNAL
|
|
};
|
|
|
|
enum
|
|
{
|
|
ARG_0
|
|
};
|
|
|
|
static void gst_xsharpen_class_init (GstXsharpenClass * klass);
|
|
static void gst_xsharpen_init (GstXsharpen * sharpen);
|
|
|
|
static void gst_xsharpen_set_property (GObject * object, guint prop_id,
|
|
const GValue * value, GParamSpec * pspec);
|
|
static void gst_xsharpen_get_property (GObject * object, guint prop_id,
|
|
GValue * value, GParamSpec * pspec);
|
|
|
|
static void gst_xsharpen_chain (GstPad * pad, GstData * _data);
|
|
|
|
static GstElementClass *parent_class = NULL;
|
|
|
|
GType
|
|
gst_xsharpen_get_type (void)
|
|
{
|
|
static GType xsharpen_type = 0;
|
|
|
|
if (!xsharpen_type) {
|
|
static const GTypeInfo xsharpen_info = {
|
|
sizeof (GstXsharpenClass), NULL,
|
|
NULL,
|
|
(GClassInitFunc) gst_xsharpen_class_init,
|
|
NULL,
|
|
NULL,
|
|
sizeof (GstXsharpen),
|
|
0,
|
|
(GInstanceInitFunc) gst_xsharpen_init,
|
|
};
|
|
|
|
xsharpen_type =
|
|
g_type_register_static (GST_TYPE_ELEMENT, "GstXsharpen", &xsharpen_info,
|
|
0);
|
|
}
|
|
return xsharpen_type;
|
|
}
|
|
|
|
static void
|
|
gst_xsharpen_class_init (GstXsharpenClass * klass)
|
|
{
|
|
GObjectClass *gobject_class;
|
|
GstElementClass *gstelement_class;
|
|
|
|
gobject_class = (GObjectClass *) klass;
|
|
gstelement_class = (GstElementClass *) klass;
|
|
|
|
parent_class = g_type_class_peek_parent (klass);
|
|
|
|
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_STRENGTH,
|
|
g_param_spec_int ("strength", "strength", "strength",
|
|
0, 255, 255, (GParamFlags) G_PARAM_READWRITE));
|
|
|
|
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_THRESHOLD,
|
|
g_param_spec_int ("threshold", "threshold", "threshold",
|
|
0, 255, 255, (GParamFlags) G_PARAM_READWRITE));
|
|
|
|
gobject_class->set_property = gst_xsharpen_set_property;
|
|
gobject_class->get_property = gst_xsharpen_get_property;
|
|
}
|
|
|
|
static GstPadLinkReturn
|
|
gst_xsharpen_sinkconnect (GstPad * pad, GstCaps * caps)
|
|
{
|
|
GstXsharpen *sharpen;
|
|
|
|
sharpen = GST_XSHARPEN (gst_pad_get_parent (pad));
|
|
|
|
if (!GST_CAPS_IS_FIXED (caps))
|
|
return GST_PAD_LINK_DELAYED;
|
|
|
|
gst_caps_get_int (caps, "width", &sharpen->width);
|
|
gst_caps_get_int (caps, "height", &sharpen->height);
|
|
|
|
sharpen->strengthinv = 255 - sharpen->strength;
|
|
|
|
sharpen->dstpitch = sharpen->srcpitch = sharpen->width * sizeof (Pixel32);
|
|
|
|
return gst_pad_try_set_caps (sharpen->srcpad, caps);
|
|
}
|
|
|
|
static void
|
|
gst_xsharpen_init (GstXsharpen * sharpen)
|
|
{
|
|
sharpen->sinkpad =
|
|
gst_pad_new_from_template (gst_virtualdub_sink_factory (), "sink");
|
|
gst_pad_set_chain_function (sharpen->sinkpad, gst_xsharpen_chain);
|
|
gst_pad_set_link_function (sharpen->sinkpad, gst_xsharpen_sinkconnect);
|
|
gst_element_add_pad (GST_ELEMENT (sharpen), sharpen->sinkpad);
|
|
|
|
sharpen->srcpad =
|
|
gst_pad_new_from_template (gst_virtualdub_src_factory (), "src");
|
|
gst_element_add_pad (GST_ELEMENT (sharpen), sharpen->srcpad);
|
|
}
|
|
|
|
static void
|
|
gst_xsharpen_chain (GstPad * pad, GstData * _data)
|
|
{
|
|
GstBuffer *buf = GST_BUFFER (_data);
|
|
GstXsharpen *xsharpen;
|
|
GstBuffer *outbuf;
|
|
gint x, y;
|
|
gint r, g, b, R, G, B;
|
|
Pixel32 p, min, max;
|
|
gint luma, lumac, lumamax, lumamin, mindiff, maxdiff;
|
|
Pixel32 *src_buf, *dst_buf, *src, *dst;
|
|
|
|
xsharpen = GST_XSHARPEN (gst_pad_get_parent (pad));
|
|
|
|
outbuf = gst_buffer_new ();
|
|
GST_BUFFER_SIZE (outbuf) =
|
|
(xsharpen->width * xsharpen->height * sizeof (Pixel32));
|
|
GST_BUFFER_DATA (outbuf) = g_malloc (GST_BUFFER_SIZE (outbuf));
|
|
|
|
GST_BUFFER_TIMESTAMP (outbuf) = GST_BUFFER_TIMESTAMP (buf);
|
|
|
|
src_buf = (Pixel32 *) GST_BUFFER_DATA (buf);
|
|
dst_buf = (Pixel32 *) GST_BUFFER_DATA (outbuf);
|
|
min = max = 0;
|
|
|
|
/* First copy through the four border lines. */
|
|
src = src_buf;
|
|
dst = dst_buf;
|
|
for (x = 0; x < xsharpen->width; x++) {
|
|
dst[x] = src[x];
|
|
}
|
|
|
|
src =
|
|
(Pixel *) ((char *) src_buf + (xsharpen->height -
|
|
1) * xsharpen->srcpitch);
|
|
dst =
|
|
(Pixel *) ((char *) dst_buf + (xsharpen->height -
|
|
1) * xsharpen->dstpitch);
|
|
|
|
for (x = 0; x < xsharpen->width; x++) {
|
|
dst[x] = src[x];
|
|
}
|
|
|
|
src = src_buf;
|
|
dst = dst_buf;
|
|
|
|
for (y = 0; y < xsharpen->height; y++) {
|
|
dst[0] = src[0];
|
|
dst[xsharpen->width - 1] = src[xsharpen->width - 1];
|
|
src = (Pixel *) ((char *) src + xsharpen->srcpitch);
|
|
dst = (Pixel *) ((char *) dst + xsharpen->dstpitch);
|
|
}
|
|
|
|
/* Now calculate and store the pixel luminances for the remaining pixels. */
|
|
src = src_buf;
|
|
for (y = 0; y < xsharpen->height; y++) {
|
|
for (x = 0; x < xsharpen->width; x++) {
|
|
r = (src[x] >> 16) & 0xff;
|
|
g = (src[x] >> 8) & 0xff;
|
|
b = src[x] & 0xff;
|
|
luma = (55 * r + 182 * g + 19 * b) >> 8;
|
|
src[x] &= 0x00ffffff;
|
|
src[x] |= (luma << 24);
|
|
}
|
|
src = (Pixel *) ((char *) src + xsharpen->srcpitch);
|
|
}
|
|
|
|
/* Finally run the 3x3 rank-order sharpening kernel over the pixels. */
|
|
src = (Pixel *) ((char *) src_buf + xsharpen->srcpitch);
|
|
dst = (Pixel *) ((char *) dst_buf + xsharpen->dstpitch);
|
|
|
|
for (y = 1; y < xsharpen->height - 1; y++) {
|
|
for (x = 1; x < xsharpen->width - 1; x++) {
|
|
/* Find the brightest and dimmest pixels in the 3x3 window
|
|
surrounding the current pixel. */
|
|
|
|
lumamax = -1;
|
|
lumamin = 1000;
|
|
|
|
p = ((Pixel32 *) ((char *) src - xsharpen->srcpitch))[x - 1];
|
|
luma = p >> 24;
|
|
if (luma > lumamax) {
|
|
lumamax = luma;
|
|
max = p;
|
|
}
|
|
if (luma < lumamin) {
|
|
lumamin = luma;
|
|
min = p;
|
|
}
|
|
|
|
p = ((Pixel32 *) ((char *) src - xsharpen->srcpitch))[x];
|
|
luma = p >> 24;
|
|
if (luma > lumamax) {
|
|
lumamax = luma;
|
|
max = p;
|
|
}
|
|
if (luma < lumamin) {
|
|
lumamin = luma;
|
|
min = p;
|
|
}
|
|
|
|
p = ((Pixel32 *) ((char *) src - xsharpen->srcpitch))[x + 1];
|
|
luma = p >> 24;
|
|
if (luma > lumamax) {
|
|
lumamax = luma;
|
|
max = p;
|
|
}
|
|
if (luma < lumamin) {
|
|
lumamin = luma;
|
|
min = p;
|
|
}
|
|
|
|
p = src[x - 1];
|
|
luma = p >> 24;
|
|
if (luma > lumamax) {
|
|
lumamax = luma;
|
|
max = p;
|
|
}
|
|
if (luma < lumamin) {
|
|
lumamin = luma;
|
|
min = p;
|
|
}
|
|
|
|
p = src[x];
|
|
lumac = luma = p >> 24;
|
|
if (luma > lumamax) {
|
|
lumamax = luma;
|
|
max = p;
|
|
}
|
|
if (luma < lumamin) {
|
|
lumamin = luma;
|
|
min = p;
|
|
}
|
|
|
|
p = src[x + 1];
|
|
luma = p >> 24;
|
|
if (luma > lumamax) {
|
|
lumamax = luma;
|
|
max = p;
|
|
}
|
|
if (luma < lumamin) {
|
|
lumamin = luma;
|
|
min = p;
|
|
}
|
|
|
|
p = ((Pixel32 *) ((char *) src + xsharpen->srcpitch))[x - 1];
|
|
luma = p >> 24;
|
|
if (luma > lumamax) {
|
|
lumamax = luma;
|
|
max = p;
|
|
}
|
|
if (luma < lumamin) {
|
|
lumamin = luma;
|
|
min = p;
|
|
}
|
|
|
|
p = ((Pixel32 *) ((char *) src + xsharpen->srcpitch))[x];
|
|
luma = p >> 24;
|
|
if (luma > lumamax) {
|
|
lumamax = luma;
|
|
max = p;
|
|
}
|
|
if (luma < lumamin) {
|
|
lumamin = luma;
|
|
min = p;
|
|
}
|
|
|
|
p = ((Pixel32 *) ((char *) src + xsharpen->srcpitch))[x + 1];
|
|
luma = p >> 24;
|
|
if (luma > lumamax) {
|
|
lumamax = luma;
|
|
max = p;
|
|
}
|
|
if (luma < lumamin) {
|
|
lumamin = luma;
|
|
min = p;
|
|
}
|
|
|
|
/* Determine whether the current pixel is closer to the
|
|
brightest or the dimmest pixel. Then compare the current
|
|
pixel to that closest pixel. If the difference is within
|
|
threshold, map the current pixel to the closest pixel;
|
|
otherwise pass it through. */
|
|
|
|
p = -1;
|
|
if (xsharpen->strength != 0) {
|
|
mindiff = lumac - lumamin;
|
|
maxdiff = lumamax - lumac;
|
|
if (mindiff > maxdiff) {
|
|
if (maxdiff < xsharpen->threshold) {
|
|
p = max;
|
|
}
|
|
} else {
|
|
if (mindiff < xsharpen->threshold) {
|
|
p = min;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (p == -1) {
|
|
dst[x] = src[x];
|
|
} else {
|
|
R = (src[x] >> 16) & 0xff;
|
|
G = (src[x] >> 8) & 0xff;
|
|
B = src[x] & 0xff;
|
|
r = (p >> 16) & 0xff;
|
|
g = (p >> 8) & 0xff;
|
|
b = p & 0xff;
|
|
r = (xsharpen->strength * r + xsharpen->strengthinv * R) / 255;
|
|
g = (xsharpen->strength * g + xsharpen->strengthinv * G) / 255;
|
|
b = (xsharpen->strength * b + xsharpen->strengthinv * B) / 255;
|
|
dst[x] = (r << 16) | (g << 8) | b;
|
|
}
|
|
}
|
|
src = (Pixel *) ((char *) src + xsharpen->srcpitch);
|
|
dst = (Pixel *) ((char *) dst + xsharpen->dstpitch);
|
|
}
|
|
|
|
gst_buffer_unref (buf);
|
|
|
|
gst_pad_push (xsharpen->srcpad, GST_DATA (outbuf));
|
|
}
|
|
|
|
static void
|
|
gst_xsharpen_set_property (GObject * object, guint prop_id,
|
|
const GValue * value, GParamSpec * pspec)
|
|
{
|
|
GstXsharpen *xsharpen;
|
|
|
|
g_return_if_fail (GST_IS_XSHARPEN (object));
|
|
|
|
xsharpen = GST_XSHARPEN (object);
|
|
|
|
switch (prop_id) {
|
|
case ARG_STRENGTH:
|
|
xsharpen->strength = g_value_get_int (value);
|
|
xsharpen->strengthinv = 255 - xsharpen->strength;
|
|
case ARG_THRESHOLD:
|
|
xsharpen->threshold = g_value_get_int (value);
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void
|
|
gst_xsharpen_get_property (GObject * object, guint prop_id, GValue * value,
|
|
GParamSpec * pspec)
|
|
{
|
|
GstXsharpen *xsharpen;
|
|
|
|
g_return_if_fail (GST_IS_XSHARPEN (object));
|
|
|
|
xsharpen = GST_XSHARPEN (object);
|
|
|
|
switch (prop_id) {
|
|
case ARG_STRENGTH:
|
|
g_value_set_int (value, xsharpen->strength);
|
|
break;
|
|
case ARG_THRESHOLD:
|
|
g_value_set_int (value, xsharpen->threshold);
|
|
break;
|
|
default:
|
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
|
break;
|
|
}
|
|
}
|