mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-27 12:11:13 +00:00
effectv: Add rippletv element
This produces a water ripple effect on the video input, based on motion or a rain drop algorithm. Kindly relicensed to LGPL2+ by Kentaro Fukuchi <fukuchi@megaui.net>. Fixes bug #588695.
This commit is contained in:
parent
433255304e
commit
2abd58de9d
4 changed files with 701 additions and 2 deletions
|
@ -3,7 +3,7 @@ plugin_LTLIBRARIES = libgsteffectv.la
|
||||||
libgsteffectv_la_SOURCES = \
|
libgsteffectv_la_SOURCES = \
|
||||||
gsteffectv.c gstedge.c gstaging.c gstdice.c gstwarp.c \
|
gsteffectv.c gstedge.c gstaging.c gstdice.c gstwarp.c \
|
||||||
gstshagadelic.c gstvertigo.c gstrev.c gstquark.c gstop.c \
|
gstshagadelic.c gstvertigo.c gstrev.c gstquark.c gstop.c \
|
||||||
gstradioac.c gststreak.c
|
gstradioac.c gststreak.c gstripple.c
|
||||||
libgsteffectv_la_CFLAGS = \
|
libgsteffectv_la_CFLAGS = \
|
||||||
$(GST_PLUGINS_BASE_CFLAGS) \
|
$(GST_PLUGINS_BASE_CFLAGS) \
|
||||||
$(GST_CONTROLLER_CFLAGS) \
|
$(GST_CONTROLLER_CFLAGS) \
|
||||||
|
@ -21,4 +21,4 @@ libgsteffectv_la_LIBTOOLFLAGS = --tag=disable-static
|
||||||
|
|
||||||
noinst_HEADERS = gsteffectv.h gstaging.h gstdice.h gstedge.h \
|
noinst_HEADERS = gsteffectv.h gstaging.h gstdice.h gstedge.h \
|
||||||
gstquark.h gstrev.h gstshagadelic.h gstvertigo.h gstwarp.h gstop.h \
|
gstquark.h gstrev.h gstshagadelic.h gstvertigo.h gstwarp.h gstop.h \
|
||||||
gstradioac.h gststreak.h
|
gstradioac.h gststreak.h gstripple.h
|
||||||
|
|
|
@ -37,6 +37,7 @@
|
||||||
#include "gstop.h"
|
#include "gstop.h"
|
||||||
#include "gstradioac.h"
|
#include "gstradioac.h"
|
||||||
#include "gststreak.h"
|
#include "gststreak.h"
|
||||||
|
#include "gstripple.h"
|
||||||
|
|
||||||
struct _elements_entry
|
struct _elements_entry
|
||||||
{
|
{
|
||||||
|
@ -56,6 +57,7 @@ static const struct _elements_entry _elements[] = {
|
||||||
{"optv", gst_optv_get_type},
|
{"optv", gst_optv_get_type},
|
||||||
{"radioactv", gst_radioactv_get_type},
|
{"radioactv", gst_radioactv_get_type},
|
||||||
{"streaktv", gst_streaktv_get_type},
|
{"streaktv", gst_streaktv_get_type},
|
||||||
|
{"rippletv", gst_rippletv_get_type},
|
||||||
{NULL, 0},
|
{NULL, 0},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
610
gst/effectv/gstripple.c
Normal file
610
gst/effectv/gstripple.c
Normal file
|
@ -0,0 +1,610 @@
|
||||||
|
/* GStreamer
|
||||||
|
* Copyright (C) <2009> Sebastian Dröge <sebastian.droege@collabora.co.uk>
|
||||||
|
*
|
||||||
|
* EffecTV - Realtime Digital Video Effector
|
||||||
|
* Copyright (C) 2001-2006 FUKUCHI Kentaro
|
||||||
|
*
|
||||||
|
* RippleTV - Water ripple effect.
|
||||||
|
* Copyright (C) 2001-2002 FUKUCHI Kentaro
|
||||||
|
*
|
||||||
|
* This combines the RippleTV and BaltanTV effects, which are
|
||||||
|
* very similar. BaltanTV is used if the feedback property is set
|
||||||
|
* to TRUE, otherwise RippleTV is used.
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SECTION:element-rippletv
|
||||||
|
*
|
||||||
|
* RippleTV does ripple mark effect on the video input. The ripple is caused
|
||||||
|
* by motion or random rain drops.
|
||||||
|
*
|
||||||
|
* <refsect2>
|
||||||
|
* <title>Example launch line</title>
|
||||||
|
* |[
|
||||||
|
* gst-launch -v videotestsrc ! rippletv ! ffmpegcolorspace ! autovideosink
|
||||||
|
* ]| This pipeline shows the effect of rippletv on a test stream.
|
||||||
|
* </refsect2>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include "config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <math.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "gstripple.h"
|
||||||
|
#include "gsteffectv.h"
|
||||||
|
|
||||||
|
#include <gst/video/video.h>
|
||||||
|
|
||||||
|
#define DEFAULT_MODE 0
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
PROP_0,
|
||||||
|
PROP_RESET,
|
||||||
|
PROP_MODE
|
||||||
|
};
|
||||||
|
|
||||||
|
static gint sqrtable[256];
|
||||||
|
|
||||||
|
#define GST_TYPE_RIPPLETV_MODE (gst_rippletv_mode_get_type())
|
||||||
|
static GType
|
||||||
|
gst_rippletv_mode_get_type (void)
|
||||||
|
{
|
||||||
|
static GType type = 0;
|
||||||
|
|
||||||
|
static const GEnumValue enumvalue[] = {
|
||||||
|
{0, "Motion Detection", "motion-detection"},
|
||||||
|
{1, "Rain", "rain"},
|
||||||
|
{0, NULL, NULL},
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!type) {
|
||||||
|
type = g_enum_register_static ("GstRippleTVMode", enumvalue);
|
||||||
|
}
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
GST_BOILERPLATE (GstRippleTV, gst_rippletv, GstVideoFilter,
|
||||||
|
GST_TYPE_VIDEO_FILTER);
|
||||||
|
|
||||||
|
static GstStaticPadTemplate gst_rippletv_src_template =
|
||||||
|
GST_STATIC_PAD_TEMPLATE ("src",
|
||||||
|
GST_PAD_SRC,
|
||||||
|
GST_PAD_ALWAYS,
|
||||||
|
GST_STATIC_CAPS (GST_VIDEO_CAPS_BGRx "; " GST_VIDEO_CAPS_RGBx ";"
|
||||||
|
GST_VIDEO_CAPS_xBGR "; " GST_VIDEO_CAPS_xRGB)
|
||||||
|
);
|
||||||
|
|
||||||
|
static GstStaticPadTemplate gst_rippletv_sink_template =
|
||||||
|
GST_STATIC_PAD_TEMPLATE ("sink",
|
||||||
|
GST_PAD_SINK,
|
||||||
|
GST_PAD_ALWAYS,
|
||||||
|
GST_STATIC_CAPS (GST_VIDEO_CAPS_BGRx "; " GST_VIDEO_CAPS_RGBx ";"
|
||||||
|
GST_VIDEO_CAPS_xBGR "; " GST_VIDEO_CAPS_xRGB)
|
||||||
|
);
|
||||||
|
|
||||||
|
static const gint point = 16;
|
||||||
|
static const gint impact = 2;
|
||||||
|
static const gint decay = 8;
|
||||||
|
static const gint loopnum = 2;
|
||||||
|
|
||||||
|
static void
|
||||||
|
setTable (void)
|
||||||
|
{
|
||||||
|
gint i;
|
||||||
|
|
||||||
|
for (i = 0; i < 128; i++) {
|
||||||
|
sqrtable[i] = i * i;
|
||||||
|
}
|
||||||
|
for (i = 1; i <= 128; i++) {
|
||||||
|
sqrtable[256 - i] = -i * i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
image_bgset_y (guint32 * src, gint16 * background, gint video_area)
|
||||||
|
{
|
||||||
|
gint i;
|
||||||
|
gint R, G, B;
|
||||||
|
guint32 *p;
|
||||||
|
gint16 *q;
|
||||||
|
|
||||||
|
p = src;
|
||||||
|
q = background;
|
||||||
|
for (i = 0; i < video_area; i++) {
|
||||||
|
R = ((*p) & 0xff0000) >> (16 - 1);
|
||||||
|
G = ((*p) & 0xff00) >> (8 - 2);
|
||||||
|
B = (*p) & 0xff;
|
||||||
|
*q = (gint16) (R + G + B);
|
||||||
|
p++;
|
||||||
|
q++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static gint
|
||||||
|
setBackground (GstRippleTV * filter, guint32 * src)
|
||||||
|
{
|
||||||
|
image_bgset_y (src, filter->background, filter->width * filter->height);
|
||||||
|
filter->bg_is_set = TRUE;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
image_bgsubtract_update_y (guint32 * src, gint16 * background, guint8 * diff,
|
||||||
|
gint video_area)
|
||||||
|
{
|
||||||
|
gint i;
|
||||||
|
gint R, G, B;
|
||||||
|
guint32 *p;
|
||||||
|
gint16 *q;
|
||||||
|
guint8 *r;
|
||||||
|
gint v;
|
||||||
|
|
||||||
|
p = src;
|
||||||
|
q = background;
|
||||||
|
r = diff;
|
||||||
|
for (i = 0; i < video_area; i++) {
|
||||||
|
R = ((*p) & 0xff0000) >> (16 - 1);
|
||||||
|
G = ((*p) & 0xff00) >> (8 - 2);
|
||||||
|
B = (*p) & 0xff;
|
||||||
|
v = (R + G + B) - (gint) (*q);
|
||||||
|
*q = (gint16) (R + G + B);
|
||||||
|
*r = ((v + 70 * 7) >> 24) | ((70 * 7 - v) >> 24);
|
||||||
|
|
||||||
|
p++;
|
||||||
|
q++;
|
||||||
|
r++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
motiondetect (GstRippleTV * filter, guint32 * src)
|
||||||
|
{
|
||||||
|
guint8 *diff = filter->diff;
|
||||||
|
gint width = filter->width;
|
||||||
|
gint *p, *q;
|
||||||
|
gint x, y, h;
|
||||||
|
|
||||||
|
if (!filter->bg_is_set)
|
||||||
|
setBackground (filter, src);
|
||||||
|
|
||||||
|
image_bgsubtract_update_y (src, filter->background, filter->diff,
|
||||||
|
filter->width * filter->height);
|
||||||
|
p = filter->map1 + filter->map_w + 1;
|
||||||
|
q = filter->map2 + filter->map_w + 1;
|
||||||
|
diff += filter->width + 2;
|
||||||
|
|
||||||
|
for (y = filter->map_h - 2; y > 0; y--) {
|
||||||
|
for (x = filter->map_w - 2; x > 0; x--) {
|
||||||
|
h = (gint) * diff + (gint) * (diff + 1) + (gint) * (diff + width) +
|
||||||
|
(gint) * (diff + width + 1);
|
||||||
|
if (h > 0) {
|
||||||
|
*p = h << (point + impact - 8);
|
||||||
|
*q = *p;
|
||||||
|
}
|
||||||
|
p++;
|
||||||
|
q++;
|
||||||
|
diff += 2;
|
||||||
|
}
|
||||||
|
diff += width + 2;
|
||||||
|
p += 2;
|
||||||
|
q += 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
drop (gint power, gint * map1, gint * map2, gint map_w, gint map_h)
|
||||||
|
{
|
||||||
|
gint x, y;
|
||||||
|
gint *p, *q;
|
||||||
|
|
||||||
|
x = fastrand () % (map_w - 4) + 2;
|
||||||
|
y = fastrand () % (map_h - 4) + 2;
|
||||||
|
p = map1 + y * map_w + x;
|
||||||
|
q = map2 + y * map_w + x;
|
||||||
|
*p = power;
|
||||||
|
*q = power;
|
||||||
|
*(p - map_w) = *(p - 1) = *(p + 1) = *(p + map_w) = power / 2;
|
||||||
|
*(p - map_w - 1) = *(p - map_w + 1) = *(p + map_w - 1) = *(p + map_w + 1) =
|
||||||
|
power / 4;
|
||||||
|
*(q - map_w) = *(q - 1) = *(q + 1) = *(q + map_w) = power / 2;
|
||||||
|
*(q - map_w - 1) = *(q - map_w + 1) = *(q + map_w - 1) = *(p + map_w + 1) =
|
||||||
|
power / 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
raindrop (GstRippleTV * filter)
|
||||||
|
{
|
||||||
|
gint i;
|
||||||
|
|
||||||
|
if (filter->period == 0) {
|
||||||
|
switch (filter->rain_stat) {
|
||||||
|
case 0:
|
||||||
|
filter->period = (fastrand () >> 23) + 100;
|
||||||
|
filter->drop_prob = 0;
|
||||||
|
filter->drop_prob_increment = 0x00ffffff / filter->period;
|
||||||
|
filter->drop_power = (-(fastrand () >> 28) - 2) << point;
|
||||||
|
filter->drops_per_frame_max = 2 << (fastrand () >> 30); // 2,4,8 or 16
|
||||||
|
filter->rain_stat = 1;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
filter->drop_prob = 0x00ffffff;
|
||||||
|
filter->drops_per_frame = 1;
|
||||||
|
filter->drop_prob_increment = 1;
|
||||||
|
filter->period = (filter->drops_per_frame_max - 1) * 16;
|
||||||
|
filter->rain_stat = 2;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
filter->period = (fastrand () >> 22) + 1000;
|
||||||
|
filter->drop_prob_increment = 0;
|
||||||
|
filter->rain_stat = 3;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
filter->period = (filter->drops_per_frame_max - 1) * 16;
|
||||||
|
filter->drop_prob_increment = -1;
|
||||||
|
filter->rain_stat = 4;
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
filter->period = (fastrand () >> 24) + 60;
|
||||||
|
filter->drop_prob_increment = -(filter->drop_prob / filter->period);
|
||||||
|
filter->rain_stat = 5;
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
default:
|
||||||
|
filter->period = (fastrand () >> 23) + 500;
|
||||||
|
filter->drop_prob = 0;
|
||||||
|
filter->rain_stat = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
switch (filter->rain_stat) {
|
||||||
|
default:
|
||||||
|
case 0:
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
case 5:
|
||||||
|
if ((fastrand () >> 8) < filter->drop_prob) {
|
||||||
|
drop (filter->drop_power, filter->map1, filter->map2, filter->map_w,
|
||||||
|
filter->map_h);
|
||||||
|
}
|
||||||
|
filter->drop_prob += filter->drop_prob_increment;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
case 3:
|
||||||
|
case 4:
|
||||||
|
for (i = filter->drops_per_frame / 16; i > 0; i--) {
|
||||||
|
drop (filter->drop_power, filter->map1, filter->map2, filter->map_w,
|
||||||
|
filter->map_h);
|
||||||
|
}
|
||||||
|
filter->drops_per_frame += filter->drop_prob_increment;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
filter->period--;
|
||||||
|
}
|
||||||
|
|
||||||
|
static GstFlowReturn
|
||||||
|
gst_rippletv_transform (GstBaseTransform * trans, GstBuffer * in,
|
||||||
|
GstBuffer * out)
|
||||||
|
{
|
||||||
|
GstRippleTV *filter = GST_RIPPLETV (trans);
|
||||||
|
guint32 *src, *dest;
|
||||||
|
GstFlowReturn ret = GST_FLOW_OK;
|
||||||
|
gint x, y, i;
|
||||||
|
gint dx, dy;
|
||||||
|
gint h, v;
|
||||||
|
gint width, height;
|
||||||
|
gint *p, *q, *r;
|
||||||
|
gint8 *vp;
|
||||||
|
|
||||||
|
src = (guint32 *) GST_BUFFER_DATA (in);
|
||||||
|
dest = (guint32 *) GST_BUFFER_DATA (out);
|
||||||
|
|
||||||
|
/* impact from the motion or rain drop */
|
||||||
|
if (filter->mode)
|
||||||
|
raindrop (filter);
|
||||||
|
else
|
||||||
|
motiondetect (filter, src);
|
||||||
|
|
||||||
|
/* simulate surface wave */
|
||||||
|
width = filter->map_w;
|
||||||
|
height = filter->map_h;
|
||||||
|
|
||||||
|
/* This function is called only 30 times per second. To increase a speed
|
||||||
|
* of wave, iterates this loop several times. */
|
||||||
|
for (i = loopnum; i > 0; i--) {
|
||||||
|
/* wave simulation */
|
||||||
|
p = filter->map1 + width + 1;
|
||||||
|
q = filter->map2 + width + 1;
|
||||||
|
r = filter->map3 + width + 1;
|
||||||
|
for (y = height - 2; y > 0; y--) {
|
||||||
|
for (x = width - 2; x > 0; x--) {
|
||||||
|
h = *(p - width - 1) + *(p - width + 1) + *(p + width - 1) + *(p +
|
||||||
|
width + 1)
|
||||||
|
+ *(p - width) + *(p - 1) + *(p + 1) + *(p + width) - (*p) * 9;
|
||||||
|
h = h >> 3;
|
||||||
|
v = *p - *q;
|
||||||
|
v += h - (v >> decay);
|
||||||
|
*r = v + *p;
|
||||||
|
p++;
|
||||||
|
q++;
|
||||||
|
r++;
|
||||||
|
}
|
||||||
|
p += 2;
|
||||||
|
q += 2;
|
||||||
|
r += 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* low pass filter */
|
||||||
|
p = filter->map3 + width + 1;
|
||||||
|
q = filter->map2 + width + 1;
|
||||||
|
for (y = height - 2; y > 0; y--) {
|
||||||
|
for (x = width - 2; x > 0; x--) {
|
||||||
|
h = *(p - width) + *(p - 1) + *(p + 1) + *(p + width) + (*p) * 60;
|
||||||
|
*q = h >> 6;
|
||||||
|
p++;
|
||||||
|
q++;
|
||||||
|
}
|
||||||
|
p += 2;
|
||||||
|
q += 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
p = filter->map1;
|
||||||
|
filter->map1 = filter->map2;
|
||||||
|
filter->map2 = p;
|
||||||
|
}
|
||||||
|
|
||||||
|
vp = filter->vtable;
|
||||||
|
p = filter->map1;
|
||||||
|
for (y = height - 1; y > 0; y--) {
|
||||||
|
for (x = width - 1; x > 0; x--) {
|
||||||
|
/* difference of the height between two voxel. They are twiced to
|
||||||
|
* emphasise the wave. */
|
||||||
|
vp[0] = sqrtable[((p[0] - p[1]) >> (point - 1)) & 0xff];
|
||||||
|
vp[1] = sqrtable[((p[0] - p[width]) >> (point - 1)) & 0xff];
|
||||||
|
p++;
|
||||||
|
vp += 2;
|
||||||
|
}
|
||||||
|
p++;
|
||||||
|
vp += 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
height = filter->height;
|
||||||
|
width = filter->width;
|
||||||
|
vp = filter->vtable;
|
||||||
|
|
||||||
|
/* draw refracted image. The vector table is stretched. */
|
||||||
|
for (y = 0; y < height; y += 2) {
|
||||||
|
for (x = 0; x < width; x += 2) {
|
||||||
|
h = (gint) vp[0];
|
||||||
|
v = (gint) vp[1];
|
||||||
|
dx = x + h;
|
||||||
|
dy = y + v;
|
||||||
|
if (dx < 0)
|
||||||
|
dx = 0;
|
||||||
|
if (dy < 0)
|
||||||
|
dy = 0;
|
||||||
|
if (dx >= width)
|
||||||
|
dx = width - 1;
|
||||||
|
if (dy >= height)
|
||||||
|
dy = height - 1;
|
||||||
|
dest[0] = src[dy * width + dx];
|
||||||
|
|
||||||
|
i = dx;
|
||||||
|
|
||||||
|
dx = x + 1 + (h + (gint) vp[2]) / 2;
|
||||||
|
if (dx < 0)
|
||||||
|
dx = 0;
|
||||||
|
if (dx >= width)
|
||||||
|
dx = width - 1;
|
||||||
|
dest[1] = src[dy * width + dx];
|
||||||
|
|
||||||
|
dy = y + 1 + (v + (gint) vp[filter->map_w * 2 + 1]) / 2;
|
||||||
|
if (dy < 0)
|
||||||
|
dy = 0;
|
||||||
|
if (dy >= height)
|
||||||
|
dy = height - 1;
|
||||||
|
dest[width] = src[dy * width + i];
|
||||||
|
|
||||||
|
dest[width + 1] = src[dy * width + dx];
|
||||||
|
dest += 2;
|
||||||
|
vp += 2;
|
||||||
|
}
|
||||||
|
dest += filter->width;
|
||||||
|
vp += 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gst_rippletv_set_caps (GstBaseTransform * btrans, GstCaps * incaps,
|
||||||
|
GstCaps * outcaps)
|
||||||
|
{
|
||||||
|
GstRippleTV *filter = GST_RIPPLETV (btrans);
|
||||||
|
GstStructure *structure;
|
||||||
|
gboolean ret = FALSE;
|
||||||
|
|
||||||
|
structure = gst_caps_get_structure (incaps, 0);
|
||||||
|
|
||||||
|
if (gst_structure_get_int (structure, "width", &filter->width) &&
|
||||||
|
gst_structure_get_int (structure, "height", &filter->height)) {
|
||||||
|
|
||||||
|
filter->map_h = filter->height / 2 + 1;
|
||||||
|
filter->map_w = filter->width / 2 + 1;
|
||||||
|
|
||||||
|
if (filter->map)
|
||||||
|
g_free (filter->map);
|
||||||
|
filter->map = g_new0 (gint, filter->map_h * filter->map_w * 3);
|
||||||
|
|
||||||
|
filter->map1 = filter->map;
|
||||||
|
filter->map2 = filter->map + filter->map_w * filter->map_h;
|
||||||
|
filter->map3 = filter->map + filter->map_w * filter->map_h * 2;
|
||||||
|
|
||||||
|
if (filter->vtable)
|
||||||
|
g_free (filter->vtable);
|
||||||
|
filter->vtable = g_new0 (gint8, filter->map_h * filter->map_w * 2);
|
||||||
|
|
||||||
|
if (filter->background)
|
||||||
|
g_free (filter->background);
|
||||||
|
filter->background = g_new0 (gint16, filter->width * filter->height);
|
||||||
|
|
||||||
|
if (filter->diff)
|
||||||
|
g_free (filter->diff);
|
||||||
|
filter->diff = g_new0 (guint8, filter->width * filter->height);
|
||||||
|
|
||||||
|
ret = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gst_rippletv_start (GstBaseTransform * trans)
|
||||||
|
{
|
||||||
|
GstRippleTV *filter = GST_RIPPLETV (trans);
|
||||||
|
|
||||||
|
filter->bg_is_set = FALSE;
|
||||||
|
|
||||||
|
filter->period = 0;
|
||||||
|
filter->rain_stat = 0;
|
||||||
|
filter->drop_prob = 0;
|
||||||
|
filter->drop_prob_increment = 0;
|
||||||
|
filter->drops_per_frame_max = 0;
|
||||||
|
filter->drops_per_frame = 0;
|
||||||
|
filter->drop_power = 0;
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_rippletv_finalize (GObject * object)
|
||||||
|
{
|
||||||
|
GstRippleTV *filter = GST_RIPPLETV (object);
|
||||||
|
|
||||||
|
if (filter->map)
|
||||||
|
g_free (filter->map);
|
||||||
|
filter->map = NULL;
|
||||||
|
|
||||||
|
if (filter->vtable)
|
||||||
|
g_free (filter->vtable);
|
||||||
|
filter->vtable = NULL;
|
||||||
|
|
||||||
|
if (filter->background)
|
||||||
|
g_free (filter->background);
|
||||||
|
filter->background = NULL;
|
||||||
|
|
||||||
|
if (filter->diff)
|
||||||
|
g_free (filter->diff);
|
||||||
|
filter->diff = NULL;
|
||||||
|
|
||||||
|
G_OBJECT_CLASS (parent_class)->finalize (object);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_rippletv_set_property (GObject * object, guint prop_id,
|
||||||
|
const GValue * value, GParamSpec * pspec)
|
||||||
|
{
|
||||||
|
GstRippleTV *filter = GST_RIPPLETV (object);
|
||||||
|
|
||||||
|
switch (prop_id) {
|
||||||
|
case PROP_RESET:{
|
||||||
|
memset (filter->map, 0,
|
||||||
|
filter->map_h * filter->map_w * 2 * sizeof (gint));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case PROP_MODE:
|
||||||
|
filter->mode = g_value_get_enum (value);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_rippletv_get_property (GObject * object, guint prop_id, GValue * value,
|
||||||
|
GParamSpec * pspec)
|
||||||
|
{
|
||||||
|
GstRippleTV *filter = GST_RIPPLETV (object);
|
||||||
|
|
||||||
|
switch (prop_id) {
|
||||||
|
case PROP_MODE:
|
||||||
|
g_value_set_enum (value, filter->mode);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_rippletv_base_init (gpointer g_class)
|
||||||
|
{
|
||||||
|
GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
|
||||||
|
|
||||||
|
gst_element_class_set_details_simple (element_class, "RippleTV effect",
|
||||||
|
"Filter/Effect/Video",
|
||||||
|
"RippleTV does ripple mark effect on the video input",
|
||||||
|
"FUKUCHI, Kentarou <fukuchi@users.sourceforge.net>, "
|
||||||
|
"Sebastian Dröge <sebastian.droege@collabora.co.uk>");
|
||||||
|
|
||||||
|
gst_element_class_add_pad_template (element_class,
|
||||||
|
gst_static_pad_template_get (&gst_rippletv_sink_template));
|
||||||
|
gst_element_class_add_pad_template (element_class,
|
||||||
|
gst_static_pad_template_get (&gst_rippletv_src_template));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_rippletv_class_init (GstRippleTVClass * klass)
|
||||||
|
{
|
||||||
|
GObjectClass *gobject_class = (GObjectClass *) klass;
|
||||||
|
GstBaseTransformClass *trans_class = (GstBaseTransformClass *) klass;
|
||||||
|
|
||||||
|
gobject_class->set_property = gst_rippletv_set_property;
|
||||||
|
gobject_class->get_property = gst_rippletv_get_property;
|
||||||
|
|
||||||
|
gobject_class->finalize = gst_rippletv_finalize;
|
||||||
|
|
||||||
|
g_object_class_install_property (gobject_class, PROP_RESET,
|
||||||
|
g_param_spec_boolean ("reset", "Reset",
|
||||||
|
"Reset all current ripples", FALSE,
|
||||||
|
G_PARAM_WRITABLE | G_PARAM_STATIC_STRINGS));
|
||||||
|
|
||||||
|
g_object_class_install_property (gobject_class, PROP_MODE,
|
||||||
|
g_param_spec_enum ("mode", "Mode",
|
||||||
|
"Mode", GST_TYPE_RIPPLETV_MODE, DEFAULT_MODE,
|
||||||
|
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||||
|
|
||||||
|
trans_class->set_caps = GST_DEBUG_FUNCPTR (gst_rippletv_set_caps);
|
||||||
|
trans_class->transform = GST_DEBUG_FUNCPTR (gst_rippletv_transform);
|
||||||
|
trans_class->start = GST_DEBUG_FUNCPTR (gst_rippletv_start);
|
||||||
|
|
||||||
|
setTable ();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_rippletv_init (GstRippleTV * filter, GstRippleTVClass * klass)
|
||||||
|
{
|
||||||
|
filter->mode = DEFAULT_MODE;
|
||||||
|
}
|
87
gst/effectv/gstripple.h
Normal file
87
gst/effectv/gstripple.h
Normal file
|
@ -0,0 +1,87 @@
|
||||||
|
/* GStreamer
|
||||||
|
* Copyright (C) <2009> Sebastian Dröge <sebastian.droege@collabora.co.uk>
|
||||||
|
*
|
||||||
|
* EffecTV - Realtime Digital Video Effector
|
||||||
|
* Copyright (C) 2001-2006 FUKUCHI Kentaro
|
||||||
|
*
|
||||||
|
* RippleTV - Water ripple effect.
|
||||||
|
* Copyright (C) 2001-2002 FUKUCHI Kentaro
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __GST_RIPPLE_H__
|
||||||
|
#define __GST_RIPPLE_H__
|
||||||
|
|
||||||
|
#include <gst/gst.h>
|
||||||
|
|
||||||
|
#include <gst/video/gstvideofilter.h>
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
#define GST_TYPE_RIPPLETV \
|
||||||
|
(gst_rippletv_get_type())
|
||||||
|
#define GST_RIPPLETV(obj) \
|
||||||
|
(G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_RIPPLETV,GstRippleTV))
|
||||||
|
#define GST_RIPPLETV_CLASS(klass) \
|
||||||
|
(G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_RIPPLETV,GstRippleTVClass))
|
||||||
|
#define GST_IS_RIPPLETV(obj) \
|
||||||
|
(G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_RIPPLETV))
|
||||||
|
#define GST_IS_RIPPLETV_CLASS(klass) \
|
||||||
|
(G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_RIPPLETV))
|
||||||
|
|
||||||
|
typedef struct _GstRippleTV GstRippleTV;
|
||||||
|
typedef struct _GstRippleTVClass GstRippleTVClass;
|
||||||
|
|
||||||
|
struct _GstRippleTV
|
||||||
|
{
|
||||||
|
GstVideoFilter element;
|
||||||
|
|
||||||
|
/* < private > */
|
||||||
|
gint width, height;
|
||||||
|
|
||||||
|
gint mode;
|
||||||
|
|
||||||
|
gint16 *background;
|
||||||
|
guint8 *diff;
|
||||||
|
|
||||||
|
gint *map, *map1, *map2, *map3;
|
||||||
|
gint map_h, map_w;
|
||||||
|
|
||||||
|
gint8 *vtable;
|
||||||
|
|
||||||
|
gboolean bg_is_set;
|
||||||
|
|
||||||
|
gint period;
|
||||||
|
gint rain_stat;
|
||||||
|
guint drop_prob;
|
||||||
|
gint drop_prob_increment;
|
||||||
|
gint drops_per_frame_max;
|
||||||
|
gint drops_per_frame;
|
||||||
|
gint drop_power;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _GstRippleTVClass
|
||||||
|
{
|
||||||
|
GstVideoFilterClass parent_class;
|
||||||
|
};
|
||||||
|
|
||||||
|
GType gst_rippletv_get_type (void);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* __GST_RIPPLE_H__ */
|
Loading…
Reference in a new issue