summaryrefslogtreecommitdiff
path: root/gst/coloreffects
diff options
context:
space:
mode:
authorFilippo Argiolas <filippo.argiolas@gmail.com>2010-08-03 14:39:22 +0200
committerSebastian Dröge <sebastian.droege@collabora.co.uk>2010-08-04 10:05:35 +0200
commit74de641ca4db01d96ddc7db37cfda99f0c16d2d2 (patch)
tree914152fad41684ce228e5d1c73f15fb2f1410ca3 /gst/coloreffects
parent79c343badee269afc423a2c08e99de97eeeb1c0b (diff)
downloadgstreamer-plugins-bad-74de641ca4db01d96ddc7db37cfda99f0c16d2d2.tar.gz
coloreffects: add ayuv support
Currently implemented switching from yuv to rgb, looking up rgb from the table in the usual way, getting back to yuv. With luma lookup presets (sepia, heat, xray) a color space conversion is saved directly looking up rgb for a given Y and converting to yuv. Probably this latter step can even be made faster precalculating a luma to yuv table in an outer loop. https://bugzilla.gnome.org/show_bug.cgi?id=625817
Diffstat (limited to 'gst/coloreffects')
-rw-r--r--gst/coloreffects/gstcoloreffects.c212
-rw-r--r--gst/coloreffects/gstcoloreffects.h2
2 files changed, 172 insertions, 42 deletions
diff --git a/gst/coloreffects/gstcoloreffects.c b/gst/coloreffects/gstcoloreffects.c
index 2d2e237d3..2cbd29870 100644
--- a/gst/coloreffects/gstcoloreffects.c
+++ b/gst/coloreffects/gstcoloreffects.c
@@ -55,7 +55,8 @@ GST_BOILERPLATE (GstColorEffects, gst_color_effects, GstVideoFilter,
GST_VIDEO_CAPS_ABGR ";" GST_VIDEO_CAPS_RGBA ";"\
GST_VIDEO_CAPS_xRGB ";" GST_VIDEO_CAPS_RGBx ";"\
GST_VIDEO_CAPS_xBGR ";" GST_VIDEO_CAPS_BGRx ";"\
- GST_VIDEO_CAPS_RGB ";" GST_VIDEO_CAPS_BGR ";"
+ GST_VIDEO_CAPS_RGB ";" GST_VIDEO_CAPS_BGR ";" \
+ GST_VIDEO_CAPS_YUV ("AYUV") ";"
static GstStaticPadTemplate gst_color_effects_src_template =
GST_STATIC_PAD_TEMPLATE ("src",
@@ -251,58 +252,30 @@ static const guint8 xpro_table[768] =
"\376\365\377\377\365\377\377\366\377\377\366\377\377\366\377\377\367\377"
"\377\367\377\377\367\377\377\370";
-static gboolean
-gst_color_effects_set_caps (GstBaseTransform * btrans, GstCaps * incaps,
- GstCaps * outcaps)
-{
- GstColorEffects *filter = GST_COLOR_EFFECTS (btrans);
-
- GST_DEBUG_OBJECT (filter,
- "in %" GST_PTR_FORMAT " out %" GST_PTR_FORMAT, incaps, outcaps);
-
- if (!gst_video_format_parse_caps (incaps, &filter->format,
- &filter->width, &filter->height))
- goto invalid_caps;
-
- GST_OBJECT_LOCK (filter);
-
- filter->size =
- gst_video_format_get_size (filter->format, filter->width, filter->height);
-
- GST_OBJECT_UNLOCK (filter);
+static const int cog_ycbcr_to_rgb_matrix_8bit_sdtv[] = {
+ 298, 0, 409, -57068,
+ 298, -100, -208, 34707,
+ 298, 516, 0, -70870,
+};
- return TRUE;
+static const gint cog_rgb_to_ycbcr_matrix_8bit_sdtv[] = {
+ 66, 129, 25, 4096,
+ -38, -74, 112, 32768,
+ 112, -94, -18, 32768,
+};
-invalid_caps:
- GST_ERROR_OBJECT (filter, "Invalid caps: %" GST_PTR_FORMAT, incaps);
- return FALSE;
-}
+#define APPLY_MATRIX(m,o,v1,v2,v3) ((m[o*4] * v1 + m[o*4+1] * v2 + m[o*4+2] * v3 + m[o*4+3]) >> 8)
-static GstFlowReturn
-gst_color_effects_transform_ip (GstBaseTransform * trans, GstBuffer * out)
+static void
+gst_color_effects_transform_rgb (GstColorEffects * filter, guint8 * data)
{
- GstColorEffects *filter = GST_COLOR_EFFECTS (trans);
- guint8 *data;
gint i, j;
- gint size;
gint width, height;
gint pixel_stride, row_stride, row_wrap;
guint32 r, g, b;
guint32 luma;
gint offsets[3];
- data = GST_BUFFER_DATA (out);
- size = GST_BUFFER_SIZE (out);
-
- if (size != filter->size)
- goto wrong_size;
-
- /* do nothing if there is no table ("none" preset) */
- if (filter->table == NULL)
- return GST_FLOW_OK;
-
- GST_OBJECT_LOCK (filter);
-
/* videoformat fun copied from videobalance */
offsets[0] = gst_video_format_get_component_offset (filter->format, 0,
@@ -352,7 +325,159 @@ gst_color_effects_transform_ip (GstBaseTransform * trans, GstBuffer * out)
}
data += row_wrap;
}
+}
+
+static void
+gst_color_effects_transform_ayuv (GstColorEffects * filter, guint8 * data)
+{
+ gint i, j;
+ gint width, height;
+ gint pixel_stride, row_stride, row_wrap;
+ gint r, g, b;
+ gint y, u, v;
+ gint offsets[3];
+
+ /* videoformat fun copied from videobalance */
+
+ offsets[0] = gst_video_format_get_component_offset (filter->format, 0,
+ filter->width, filter->height);
+ offsets[1] = gst_video_format_get_component_offset (filter->format, 1,
+ filter->width, filter->height);
+ offsets[2] = gst_video_format_get_component_offset (filter->format, 2,
+ filter->width, filter->height);
+
+ width =
+ gst_video_format_get_component_width (filter->format, 0, filter->width);
+ height =
+ gst_video_format_get_component_height (filter->format, 0, filter->height);
+ row_stride =
+ gst_video_format_get_row_stride (filter->format, 0, filter->width);
+ pixel_stride = gst_video_format_get_pixel_stride (filter->format, 0);
+ row_wrap = row_stride - pixel_stride * width;
+
+ for (i = 0; i < height; i++) {
+ for (j = 0; j < width; j++) {
+ y = data[offsets[0]];
+ u = data[offsets[1]];
+ v = data[offsets[2]];
+ if (filter->map_luma) {
+ /* map luma to lookup table */
+ /* src.luma |-> table[luma].rgb */
+ y *= 3;
+ r = filter->table[y];
+ g = filter->table[y + 1];
+ b = filter->table[y + 2];
+
+ y = APPLY_MATRIX (cog_rgb_to_ycbcr_matrix_8bit_sdtv, 0, r, g, b);
+ u = APPLY_MATRIX (cog_rgb_to_ycbcr_matrix_8bit_sdtv, 1, r, g, b);
+ v = APPLY_MATRIX (cog_rgb_to_ycbcr_matrix_8bit_sdtv, 2, r, g, b);
+
+ data[offsets[0]] = CLAMP (y, 0, 255);
+ data[offsets[1]] = CLAMP (u, 0, 255);
+ data[offsets[2]] = CLAMP (v, 0, 255);
+ } else {
+ r = APPLY_MATRIX (cog_ycbcr_to_rgb_matrix_8bit_sdtv, 0, y, u, v);
+ g = APPLY_MATRIX (cog_ycbcr_to_rgb_matrix_8bit_sdtv, 1, y, u, v);
+ b = APPLY_MATRIX (cog_ycbcr_to_rgb_matrix_8bit_sdtv, 2, y, u, v);
+
+ r = CLAMP (r, 0, 255);
+ g = CLAMP (g, 0, 255);
+ b = CLAMP (b, 0, 255);
+
+ /* map each color component to the correspondent lut color */
+ /* src.r |-> table[r].r */
+ /* src.g |-> table[g].g */
+ /* src.b |-> table[b].b */
+ r = filter->table[r * 3];
+ g = filter->table[g * 3 + 1];
+ b = filter->table[b * 3 + 2];
+
+ y = APPLY_MATRIX (cog_rgb_to_ycbcr_matrix_8bit_sdtv, 0, r, g, b);
+ u = APPLY_MATRIX (cog_rgb_to_ycbcr_matrix_8bit_sdtv, 1, r, g, b);
+ v = APPLY_MATRIX (cog_rgb_to_ycbcr_matrix_8bit_sdtv, 2, r, g, b);
+
+ data[offsets[0]] = CLAMP (y, 0, 255);
+ data[offsets[1]] = CLAMP (u, 0, 255);
+ data[offsets[2]] = CLAMP (v, 0, 255);
+ }
+ data += pixel_stride;
+ }
+ data += row_wrap;
+ }
+}
+
+static gboolean
+gst_color_effects_set_caps (GstBaseTransform * btrans, GstCaps * incaps,
+ GstCaps * outcaps)
+{
+ GstColorEffects *filter = GST_COLOR_EFFECTS (btrans);
+
+ GST_DEBUG_OBJECT (filter,
+ "in %" GST_PTR_FORMAT " out %" GST_PTR_FORMAT, incaps, outcaps);
+
+ filter->process = NULL;
+
+ if (!gst_video_format_parse_caps (incaps, &filter->format,
+ &filter->width, &filter->height))
+ goto invalid_caps;
+
+ GST_OBJECT_LOCK (filter);
+
+ filter->size =
+ gst_video_format_get_size (filter->format, filter->width, filter->height);
+
+ switch (filter->format) {
+ case GST_VIDEO_FORMAT_AYUV:
+ filter->process = gst_color_effects_transform_ayuv;
+ break;
+ case GST_VIDEO_FORMAT_ARGB:
+ case GST_VIDEO_FORMAT_ABGR:
+ case GST_VIDEO_FORMAT_RGBA:
+ case GST_VIDEO_FORMAT_BGRA:
+ case GST_VIDEO_FORMAT_xRGB:
+ case GST_VIDEO_FORMAT_xBGR:
+ case GST_VIDEO_FORMAT_RGBx:
+ case GST_VIDEO_FORMAT_BGRx:
+ case GST_VIDEO_FORMAT_RGB:
+ case GST_VIDEO_FORMAT_BGR:
+ filter->process = gst_color_effects_transform_rgb;
+ break;
+ default:
+ break;
+ }
+
+ GST_OBJECT_UNLOCK (filter);
+
+ return filter->process != NULL;
+
+invalid_caps:
+ GST_ERROR_OBJECT (filter, "Invalid caps: %" GST_PTR_FORMAT, incaps);
+ return FALSE;
+}
+
+static GstFlowReturn
+gst_color_effects_transform_ip (GstBaseTransform * trans, GstBuffer * out)
+{
+ GstColorEffects *filter = GST_COLOR_EFFECTS (trans);
+ guint8 *data;
+ gint size;
+
+ if (!filter->process)
+ goto not_negotiated;
+
+ data = GST_BUFFER_DATA (out);
+ size = GST_BUFFER_SIZE (out);
+
+ if (size != filter->size)
+ goto wrong_size;
+
+ /* do nothing if there is no table ("none" preset) */
+ if (filter->table == NULL)
+ return GST_FLOW_OK;
+
+ GST_OBJECT_LOCK (filter);
+ filter->process (filter, data);
GST_OBJECT_UNLOCK (filter);
return GST_FLOW_OK;
@@ -363,6 +488,9 @@ wrong_size:
(NULL), ("Invalid buffer size %d, expected %d", size, filter->size));
return GST_FLOW_ERROR;
}
+not_negotiated:
+ GST_ERROR_OBJECT (filter, "Not negotiated yet");
+ return GST_FLOW_NOT_NEGOTIATED;
}
static void
diff --git a/gst/coloreffects/gstcoloreffects.h b/gst/coloreffects/gstcoloreffects.h
index 05df30bde..b549ff1d4 100644
--- a/gst/coloreffects/gstcoloreffects.h
+++ b/gst/coloreffects/gstcoloreffects.h
@@ -76,6 +76,8 @@ struct _GstColorEffects
gint width;
gint height;
gint size;
+
+ void (*process) (GstColorEffects *filter, guint8 *data);
};
struct _GstColorEffectsClass