mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-24 17:20:36 +00:00
[MOVED FROM BAD 03/29] shapewipe: Add border property to allow smooth borders
...and use a border of 0.01 in the example application.
This commit is contained in:
parent
b7f83c6b80
commit
c0f9553707
3 changed files with 41 additions and 6 deletions
|
@ -57,7 +57,8 @@ static GstCaps *gst_shape_wipe_src_getcaps (GstPad * pad);
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
PROP_0,
|
PROP_0,
|
||||||
PROP_POSITION
|
PROP_POSITION,
|
||||||
|
PROP_BORDER
|
||||||
};
|
};
|
||||||
|
|
||||||
static GstStaticPadTemplate video_sink_pad_template =
|
static GstStaticPadTemplate video_sink_pad_template =
|
||||||
|
@ -121,6 +122,10 @@ gst_shape_wipe_class_init (GstShapeWipeClass * klass)
|
||||||
g_param_spec_float ("position", "Position", "Position of the mask",
|
g_param_spec_float ("position", "Position", "Position of the mask",
|
||||||
0.0, 1.0, 0.0,
|
0.0, 1.0, 0.0,
|
||||||
G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE));
|
G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE));
|
||||||
|
g_object_class_install_property (gobject_class, PROP_BORDER,
|
||||||
|
g_param_spec_float ("border", "Border", "Border of the mask",
|
||||||
|
0.0, 1.0, 0.0,
|
||||||
|
G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE));
|
||||||
|
|
||||||
gstelement_class->change_state =
|
gstelement_class->change_state =
|
||||||
GST_DEBUG_FUNCPTR (gst_shape_wipe_change_state);
|
GST_DEBUG_FUNCPTR (gst_shape_wipe_change_state);
|
||||||
|
@ -176,6 +181,9 @@ gst_shape_wipe_get_property (GObject * object, guint prop_id,
|
||||||
case PROP_POSITION:
|
case PROP_POSITION:
|
||||||
g_value_set_float (value, self->mask_position);
|
g_value_set_float (value, self->mask_position);
|
||||||
break;
|
break;
|
||||||
|
case PROP_BORDER:
|
||||||
|
g_value_set_float (value, self->mask_border);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
break;
|
break;
|
||||||
|
@ -192,6 +200,9 @@ gst_shape_wipe_set_property (GObject * object, guint prop_id,
|
||||||
case PROP_POSITION:
|
case PROP_POSITION:
|
||||||
self->mask_position = g_value_get_float (value);
|
self->mask_position = g_value_get_float (value);
|
||||||
break;
|
break;
|
||||||
|
case PROP_BORDER:
|
||||||
|
self->mask_border = g_value_get_float (value);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
break;
|
break;
|
||||||
|
@ -227,6 +238,7 @@ gst_shape_wipe_reset (GstShapeWipe * self)
|
||||||
|
|
||||||
self->width = self->height = 0;
|
self->width = self->height = 0;
|
||||||
self->mask_position = 0.0;
|
self->mask_position = 0.0;
|
||||||
|
self->mask_border = 0.0;
|
||||||
self->mask_bpp = 0;
|
self->mask_bpp = 0;
|
||||||
|
|
||||||
gst_segment_init (&self->segment, GST_FORMAT_TIME);
|
gst_segment_init (&self->segment, GST_FORMAT_TIME);
|
||||||
|
@ -544,19 +556,30 @@ gst_shape_wipe_blend_16 (GstShapeWipe * self, GstBuffer * inbuf,
|
||||||
guint i, j;
|
guint i, j;
|
||||||
guint mask_increment = GST_ROUND_UP_2 (self->width) - self->width;
|
guint mask_increment = GST_ROUND_UP_2 (self->width) - self->width;
|
||||||
gfloat position = self->mask_position;
|
gfloat position = self->mask_position;
|
||||||
|
gfloat low = MAX (0.0, position - self->mask_border);
|
||||||
|
gfloat high = MIN (1.0, position + self->mask_border);
|
||||||
|
|
||||||
for (i = 0; i < self->height; i++) {
|
for (i = 0; i < self->height; i++) {
|
||||||
for (j = 0; j < self->width; j++) {
|
for (j = 0; j < self->width; j++) {
|
||||||
if (*mask / 65535.0 < position) {
|
gfloat in = *mask / 65535.0;
|
||||||
|
|
||||||
|
if (in <= low) {
|
||||||
output[0] = 0x00; /* A */
|
output[0] = 0x00; /* A */
|
||||||
output[1] = 0x00; /* Y */
|
output[1] = 0x00; /* Y */
|
||||||
output[2] = 0x80; /* U */
|
output[2] = 0x80; /* U */
|
||||||
output[3] = 0x80; /* V */
|
output[3] = 0x80; /* V */
|
||||||
} else {
|
} else if (in >= high) {
|
||||||
output[0] = 0xff; /* A */
|
output[0] = 0xff; /* A */
|
||||||
output[1] = input[1]; /* Y */
|
output[1] = input[1]; /* Y */
|
||||||
output[2] = input[2]; /* U */
|
output[2] = input[2]; /* U */
|
||||||
output[3] = input[3]; /* V */
|
output[3] = input[3]; /* V */
|
||||||
|
} else {
|
||||||
|
gfloat val = 255 * ((in - low) / (high - low));
|
||||||
|
|
||||||
|
output[0] = CLAMP (val, 0, 255); /* A */
|
||||||
|
output[1] = input[1]; /* Y */
|
||||||
|
output[2] = input[2]; /* U */
|
||||||
|
output[3] = input[3]; /* V */
|
||||||
}
|
}
|
||||||
|
|
||||||
mask++;
|
mask++;
|
||||||
|
@ -579,19 +602,30 @@ gst_shape_wipe_blend_8 (GstShapeWipe * self, GstBuffer * inbuf,
|
||||||
guint i, j;
|
guint i, j;
|
||||||
guint mask_increment = GST_ROUND_UP_4 (self->width) - self->width;
|
guint mask_increment = GST_ROUND_UP_4 (self->width) - self->width;
|
||||||
gfloat position = self->mask_position;
|
gfloat position = self->mask_position;
|
||||||
|
gfloat low = MAX (0.0, position - self->mask_border);
|
||||||
|
gfloat high = MIN (1.0, position + self->mask_border);
|
||||||
|
|
||||||
for (i = 0; i < self->height; i++) {
|
for (i = 0; i < self->height; i++) {
|
||||||
for (j = 0; j < self->width; j++) {
|
for (j = 0; j < self->width; j++) {
|
||||||
if (*mask / 255.0 < position) {
|
gfloat in = *mask / 255.0;
|
||||||
|
|
||||||
|
if (in <= low) {
|
||||||
output[0] = 0x00; /* A */
|
output[0] = 0x00; /* A */
|
||||||
output[1] = 0x00; /* Y */
|
output[1] = 0x00; /* Y */
|
||||||
output[2] = 0x80; /* U */
|
output[2] = 0x80; /* U */
|
||||||
output[3] = 0x80; /* V */
|
output[3] = 0x80; /* V */
|
||||||
} else {
|
} else if (in >= high) {
|
||||||
output[0] = 0xff; /* A */
|
output[0] = 0xff; /* A */
|
||||||
output[1] = input[1]; /* Y */
|
output[1] = input[1]; /* Y */
|
||||||
output[2] = input[2]; /* U */
|
output[2] = input[2]; /* U */
|
||||||
output[3] = input[3]; /* V */
|
output[3] = input[3]; /* V */
|
||||||
|
} else {
|
||||||
|
gfloat val = 255 * ((in - low) / (high - low));
|
||||||
|
|
||||||
|
output[0] = CLAMP (val, 0, 255); /* A */
|
||||||
|
output[1] = input[1]; /* Y */
|
||||||
|
output[2] = input[2]; /* U */
|
||||||
|
output[3] = input[3]; /* V */
|
||||||
}
|
}
|
||||||
|
|
||||||
mask++;
|
mask++;
|
||||||
|
|
|
@ -54,6 +54,7 @@ struct _GstShapeWipe
|
||||||
|
|
||||||
GstBuffer *mask;
|
GstBuffer *mask;
|
||||||
gfloat mask_position;
|
gfloat mask_position;
|
||||||
|
gfloat mask_border;
|
||||||
GMutex *mask_mutex;
|
GMutex *mask_mutex;
|
||||||
GCond *mask_cond;
|
GCond *mask_cond;
|
||||||
gint mask_bpp;
|
gint mask_bpp;
|
||||||
|
|
|
@ -67,7 +67,7 @@ main (gint argc, gchar ** argv)
|
||||||
|
|
||||||
pipeline_string =
|
pipeline_string =
|
||||||
g_strdup_printf
|
g_strdup_printf
|
||||||
("videotestsrc ! video/x-raw-yuv,width=640,height=480 ! shapewipe name=shape ! videomixer name=mixer ! ffmpegcolorspace ! autovideosink filesrc location=%s ! typefind ! decodebin2 ! ffmpegcolorspace ! videoscale ! queue ! shape.mask_sink videotestsrc pattern=snow ! video/x-raw-yuv,width=640,height=480 ! queue ! mixer.",
|
("videotestsrc ! video/x-raw-yuv,width=640,height=480 ! shapewipe name=shape border=0.01 ! videomixer name=mixer ! ffmpegcolorspace ! autovideosink filesrc location=%s ! typefind ! decodebin2 ! ffmpegcolorspace ! videoscale ! queue ! shape.mask_sink videotestsrc pattern=snow ! video/x-raw-yuv,width=640,height=480 ! queue ! mixer.",
|
||||||
argv[1]);
|
argv[1]);
|
||||||
|
|
||||||
pipeline = gst_parse_launch (pipeline_string, NULL);
|
pipeline = gst_parse_launch (pipeline_string, NULL);
|
||||||
|
|
Loading…
Reference in a new issue