summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSebastian Dröge <sebastian.droege@collabora.co.uk>2009-07-02 11:24:48 +0200
committerSebastian Dröge <sebastian.droege@collabora.co.uk>2009-07-02 11:27:31 +0200
commit8fade13db154dcf0b39cf5c15793d0f1f632f7ae (patch)
tree1baa771e93cf4646561dbc58af994d3e39f1e3d4
parentcf2b2b017f0995ecab2822804537f193835e35e9 (diff)
downloadgst-plugins-bad-8fade13db154dcf0b39cf5c15793d0f1f632f7ae.tar.gz
gst-plugins-bad-8fade13db154dcf0b39cf5c15793d0f1f632f7ae.tar.bz2
gst-plugins-bad-8fade13db154dcf0b39cf5c15793d0f1f632f7ae.zip
shapewipe: Add support for ARGB video input/output
-rw-r--r--gst/shapewipe/gstshapewipe.c279
-rw-r--r--gst/shapewipe/gstshapewipe.h1
2 files changed, 159 insertions, 121 deletions
diff --git a/gst/shapewipe/gstshapewipe.c b/gst/shapewipe/gstshapewipe.c
index 4029c494..655cfc50 100644
--- a/gst/shapewipe/gstshapewipe.c
+++ b/gst/shapewipe/gstshapewipe.c
@@ -93,10 +93,10 @@ enum
};
static GstStaticPadTemplate video_sink_pad_template =
-GST_STATIC_PAD_TEMPLATE ("video_sink",
+ GST_STATIC_PAD_TEMPLATE ("video_sink",
GST_PAD_SINK,
GST_PAD_ALWAYS,
- GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV ("AYUV")));
+ GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV ("AYUV") " ; " GST_VIDEO_CAPS_ARGB));
static GstStaticPadTemplate mask_sink_pad_template =
GST_STATIC_PAD_TEMPLATE ("mask_sink",
@@ -112,8 +112,8 @@ static GstStaticPadTemplate mask_sink_pad_template =
"height = " GST_VIDEO_SIZE_RANGE ", " "framerate = 0/1"));
static GstStaticPadTemplate src_pad_template =
-GST_STATIC_PAD_TEMPLATE ("src", GST_PAD_SRC, GST_PAD_ALWAYS,
- GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV ("AYUV")));
+ GST_STATIC_PAD_TEMPLATE ("src", GST_PAD_SRC, GST_PAD_ALWAYS,
+ GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV ("AYUV") " ; " GST_VIDEO_CAPS_ARGB));
GST_DEBUG_CATEGORY_STATIC (gst_shape_wipe_debug);
#define GST_CAT_DEFAULT gst_shape_wipe_debug
@@ -273,6 +273,7 @@ gst_shape_wipe_reset (GstShapeWipe * self)
g_cond_signal (self->mask_cond);
+ self->fmt = GST_VIDEO_FORMAT_UNKNOWN;
self->width = self->height = 0;
self->mask_position = 0.0;
self->mask_border = 0.0;
@@ -309,6 +310,7 @@ gst_shape_wipe_video_sink_setcaps (GstPad * pad, GstCaps * caps)
GstShapeWipe *self = GST_SHAPE_WIPE (gst_pad_get_parent (pad));
gboolean ret = TRUE;
GstStructure *s;
+ GstVideoFormat fmt;
gint width, height;
gint fps_n, fps_d;
@@ -316,13 +318,13 @@ gst_shape_wipe_video_sink_setcaps (GstPad * pad, GstCaps * caps)
s = gst_caps_get_structure (caps, 0);
- if (!gst_structure_get_int (s, "width", &width) ||
- !gst_structure_get_int (s, "height", &height) ||
+ if (!gst_video_format_parse_caps (caps, &fmt, &width, &height) ||
!gst_structure_get_fraction (s, "framerate", &fps_n, &fps_d)) {
ret = FALSE;
goto done;
}
+ self->fmt = fmt;
if (self->width != width || self->height != height) {
g_mutex_lock (self->mask_mutex);
self->width = width;
@@ -402,13 +404,20 @@ gst_shape_wipe_video_sink_getcaps (GstPad * pad)
n = gst_caps_get_size (tmp);
+ tmp2 = gst_caps_new_empty ();
for (i = 0; i < n; i++) {
GstStructure *s = gst_caps_get_structure (tmp, i);
+ GstStructure *c;
- gst_structure_remove_fields (s, "bpp", "depth", "endianness", "framerate",
+ gst_structure_remove_fields (s, "format", "bpp", "depth", "endianness",
+ "framerate", "red_mask", "green_mask", "blue_mask", "alpha_mask",
NULL);
gst_structure_set_name (s, "video/x-raw-yuv");
+ c = gst_structure_copy (s);
+ gst_structure_set_name (c, "video/x-raw-rgb");
+ gst_caps_append_structure (tmp2, c);
}
+ gst_caps_append (tmp, tmp2);
intersection = gst_caps_intersect (tmp, ret);
gst_caps_unref (tmp);
@@ -498,7 +507,9 @@ gst_shape_wipe_mask_sink_getcaps (GstPad * pad)
GstStructure *t;
gst_structure_set_name (s, "video/x-raw-gray");
- gst_structure_remove_fields (s, "format", "framerate", NULL);
+ gst_structure_remove_fields (s, "format", "framerate", "bpp", "depth",
+ "endianness", "framerate", "red_mask", "green_mask", "blue_mask",
+ "alpha_mask", NULL);
if (self->width && self->height)
gst_structure_set (s, "width", G_TYPE_INT, self->width, "height",
@@ -514,7 +525,7 @@ gst_shape_wipe_mask_sink_getcaps (GstPad * pad)
gst_caps_append_structure (tmp, t);
}
- gst_caps_merge (ret, tmp);
+ gst_caps_append (ret, tmp);
tmp = gst_pad_peer_get_caps (pad);
if (tmp) {
@@ -591,13 +602,20 @@ gst_shape_wipe_src_getcaps (GstPad * pad)
tmp = intersection;
n = gst_caps_get_size (tmp);
+ tmp2 = gst_caps_new_empty ();
for (i = 0; i < n; i++) {
GstStructure *s = gst_caps_get_structure (tmp, i);
+ GstStructure *c;
- gst_structure_remove_fields (s, "bpp", "depth", "endianness", "framerate",
+ gst_structure_remove_fields (s, "format", "bpp", "depth", "endianness",
+ "framerate", "red_mask", "green_mask", "blue_mask", "alpha_mask",
NULL);
gst_structure_set_name (s, "video/x-raw-yuv");
+ c = gst_structure_copy (s);
+
+ gst_caps_append_structure (tmp2, c);
}
+ gst_caps_append (tmp, tmp2);
intersection = gst_caps_intersect (tmp, ret);
gst_caps_unref (tmp);
@@ -729,118 +747,128 @@ gst_shape_wipe_do_qos (GstShapeWipe * self, GstClockTime timestamp)
return TRUE;
}
-static GstFlowReturn
-gst_shape_wipe_blend_16 (GstShapeWipe * self, GstBuffer * inbuf,
- GstBuffer * maskbuf, GstBuffer * outbuf)
-{
- const guint16 *mask = (const guint16 *) GST_BUFFER_DATA (maskbuf);
- const guint8 *input = (const guint8 *) GST_BUFFER_DATA (inbuf);
- guint8 *output = (guint8 *) GST_BUFFER_DATA (outbuf);
- guint i, j;
- guint mask_increment = GST_ROUND_UP_2 (self->width) - self->width;
- gfloat position = self->mask_position;
- gfloat low = position - (self->mask_border / 2.0f);
- gfloat high = position + (self->mask_border / 2.0f);
-
- if (low < 0.0f) {
- high = 0.0f;
- low = 0.0f;
- }
-
- if (high > 1.0f) {
- low = 1.0f;
- high = 1.0f;
- }
-
- for (i = 0; i < self->height; i++) {
- for (j = 0; j < self->width; j++) {
- gfloat in = *mask / 65536.0f;
-
- if (in < low) {
- output[0] = 0x00; /* A */
- output[1] = 0x00; /* Y */
- output[2] = 0x80; /* U */
- output[3] = 0x80; /* V */
- } else if (in >= high) {
- output[0] = 0xff; /* A */
- output[1] = input[1]; /* Y */
- output[2] = input[2]; /* U */
- output[3] = input[3]; /* V */
- } else {
- gfloat val = 255.0f * ((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++;
- input += 4;
- output += 4;
- }
- mask += mask_increment;
- }
-
- return GST_FLOW_OK;
+#define CREATE_AYUV_FUNCTIONS(depth, scale) \
+static GstFlowReturn \
+gst_shape_wipe_blend_ayuv_##depth (GstShapeWipe * self, GstBuffer * inbuf, \
+ GstBuffer * maskbuf, GstBuffer * outbuf) \
+{ \
+ const guint##depth *mask = (const guint##depth *) GST_BUFFER_DATA (maskbuf); \
+ const guint8 *input = (const guint8 *) GST_BUFFER_DATA (inbuf); \
+ guint8 *output = (guint8 *) GST_BUFFER_DATA (outbuf); \
+ guint i, j; \
+ guint mask_increment = ((depth == 16) ? GST_ROUND_UP_2 (self->width) : \
+ GST_ROUND_UP_4 (self->width)) - self->width; \
+ gfloat position = self->mask_position; \
+ gfloat low = position - (self->mask_border / 2.0f); \
+ gfloat high = position + (self->mask_border / 2.0f); \
+ \
+ if (low < 0.0f) { \
+ high = 0.0f; \
+ low = 0.0f; \
+ } \
+ \
+ if (high > 1.0f) { \
+ low = 1.0f; \
+ high = 1.0f; \
+ } \
+ \
+ for (i = 0; i < self->height; i++) { \
+ for (j = 0; j < self->width; j++) { \
+ gfloat in = *mask / scale; \
+ \
+ if (in < low) { \
+ output[0] = 0x00; /* A */ \
+ output[1] = 0x00; /* Y */ \
+ output[2] = 0x80; /* U */ \
+ output[3] = 0x80; /* V */ \
+ } else if (in >= high) { \
+ output[0] = 0xff; /* A */ \
+ output[1] = input[1]; /* Y */ \
+ output[2] = input[2]; /* U */ \
+ output[3] = input[3]; /* V */ \
+ } else { \
+ gfloat val = 255.0f * ((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++; \
+ input += 4; \
+ output += 4; \
+ } \
+ mask += mask_increment; \
+ } \
+ \
+ return GST_FLOW_OK; \
}
-static GstFlowReturn
-gst_shape_wipe_blend_8 (GstShapeWipe * self, GstBuffer * inbuf,
- GstBuffer * maskbuf, GstBuffer * outbuf)
-{
- const guint8 *mask = (const guint8 *) GST_BUFFER_DATA (maskbuf);
- const guint8 *input = (const guint8 *) GST_BUFFER_DATA (inbuf);
- guint8 *output = (guint8 *) GST_BUFFER_DATA (outbuf);
- guint i, j;
- guint mask_increment = GST_ROUND_UP_4 (self->width) - self->width;
- gfloat position = self->mask_position;
- gfloat low = position - (self->mask_border / 2.0f);
- gfloat high = position + (self->mask_border / 2.0f);
-
- if (low < 0.0f) {
- high = 0.0f;
- low = 0.0f;
- }
-
- if (high > 1.0f) {
- low = 1.0f;
- high = 1.0f;
- }
-
- for (i = 0; i < self->height; i++) {
- for (j = 0; j < self->width; j++) {
- gfloat in = *mask / 256.0f;
-
- if (in < low) {
- output[0] = 0x00; /* A */
- output[1] = 0x00; /* Y */
- output[2] = 0x80; /* U */
- output[3] = 0x80; /* V */
- } else if (in >= high) {
- output[0] = 0xff; /* A */
- output[1] = input[1]; /* Y */
- output[2] = input[2]; /* U */
- output[3] = input[3]; /* V */
- } else {
- gfloat val = 255.0f * ((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++;
- input += 4;
- output += 4;
- }
- mask += mask_increment;
- }
-
- return GST_FLOW_OK;
+CREATE_AYUV_FUNCTIONS (16, 65536.0f);
+CREATE_AYUV_FUNCTIONS (8, 256.0f);
+
+#define CREATE_ARGB_FUNCTIONS(depth, scale) \
+static GstFlowReturn \
+gst_shape_wipe_blend_argb_##depth (GstShapeWipe * self, GstBuffer * inbuf, \
+ GstBuffer * maskbuf, GstBuffer * outbuf) \
+{ \
+ const guint##depth *mask = (const guint##depth *) GST_BUFFER_DATA (maskbuf); \
+ const guint8 *input = (const guint8 *) GST_BUFFER_DATA (inbuf); \
+ guint8 *output = (guint8 *) GST_BUFFER_DATA (outbuf); \
+ guint i, j; \
+ guint mask_increment = ((depth == 16) ? GST_ROUND_UP_2 (self->width) : \
+ GST_ROUND_UP_4 (self->width)) - self->width; \
+ gfloat position = self->mask_position; \
+ gfloat low = position - (self->mask_border / 2.0f); \
+ gfloat high = position + (self->mask_border / 2.0f); \
+ \
+ if (low < 0.0f) { \
+ high = 0.0f; \
+ low = 0.0f; \
+ } \
+ \
+ if (high > 1.0f) { \
+ low = 1.0f; \
+ high = 1.0f; \
+ } \
+ \
+ for (i = 0; i < self->height; i++) { \
+ for (j = 0; j < self->width; j++) { \
+ gfloat in = *mask / scale; \
+ \
+ if (in < low) { \
+ output[0] = 0x00; /* A */ \
+ output[1] = 0x00; /* R */ \
+ output[2] = 0x00; /* G */ \
+ output[3] = 0x00; /* B */ \
+ } else if (in >= high) { \
+ output[0] = 0xff; /* A */ \
+ output[1] = input[1]; /* R */ \
+ output[2] = input[2]; /* G */ \
+ output[3] = input[3]; /* B */ \
+ } else { \
+ gfloat val = 255.0f * ((in - low) / (high - low)); \
+ \
+ output[0] = CLAMP (val, 0, 255); /* A */ \
+ output[1] = input[1]; /* R */ \
+ output[2] = input[2]; /* G */ \
+ output[3] = input[3]; /* B */ \
+ } \
+ \
+ mask++; \
+ input += 4; \
+ output += 4; \
+ } \
+ mask += mask_increment; \
+ } \
+ \
+ return GST_FLOW_OK; \
}
+CREATE_ARGB_FUNCTIONS (16, 65536.0f);
+CREATE_ARGB_FUNCTIONS (8, 256.0f);
+
static GstFlowReturn
gst_shape_wipe_video_sink_chain (GstPad * pad, GstBuffer * buffer)
{
@@ -850,6 +878,9 @@ gst_shape_wipe_video_sink_chain (GstPad * pad, GstBuffer * buffer)
GstClockTime timestamp;
gboolean new_outbuf = FALSE;
+ if (G_UNLIKELY (self->fmt == GST_VIDEO_FORMAT_UNKNOWN))
+ return GST_FLOW_NOT_NEGOTIATED;
+
timestamp = GST_BUFFER_TIMESTAMP (buffer);
timestamp =
gst_segment_to_stream_time (&self->segment, GST_FORMAT_TIME, timestamp);
@@ -898,10 +929,16 @@ gst_shape_wipe_video_sink_chain (GstPad * pad, GstBuffer * buffer)
outbuf = buffer;
}
- if (self->mask_bpp == 16)
- ret = gst_shape_wipe_blend_16 (self, buffer, mask, outbuf);
+ if (self->fmt == GST_VIDEO_FORMAT_AYUV && self->mask_bpp == 16)
+ ret = gst_shape_wipe_blend_ayuv_16 (self, buffer, mask, outbuf);
+ else if (self->fmt == GST_VIDEO_FORMAT_AYUV)
+ ret = gst_shape_wipe_blend_ayuv_8 (self, buffer, mask, outbuf);
+ else if (self->fmt == GST_VIDEO_FORMAT_ARGB && self->mask_bpp == 16)
+ ret = gst_shape_wipe_blend_argb_16 (self, buffer, mask, outbuf);
+ else if (self->fmt == GST_VIDEO_FORMAT_ARGB)
+ ret = gst_shape_wipe_blend_argb_8 (self, buffer, mask, outbuf);
else
- ret = gst_shape_wipe_blend_8 (self, buffer, mask, outbuf);
+ g_assert_not_reached ();
gst_buffer_unref (mask);
if (new_outbuf)
diff --git a/gst/shapewipe/gstshapewipe.h b/gst/shapewipe/gstshapewipe.h
index 2cc44831..f6196c69 100644
--- a/gst/shapewipe/gstshapewipe.h
+++ b/gst/shapewipe/gstshapewipe.h
@@ -59,6 +59,7 @@ struct _GstShapeWipe
GCond *mask_cond;
gint mask_bpp;
+ GstVideoFormat fmt;
gint width, height;
gdouble proportion;