From: Sebastian Dröge Date: Sat, 17 Apr 2010 15:43:51 +0000 (+0200) Subject: smptealpha: Add support for all 4 ARGB formats X-Git-Tag: RELEASE-0.10.23~230 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=ae1783e5cd9c112fb631a38b16186e41f8abeed9;p=platform%2Fupstream%2Fgst-plugins-good.git smptealpha: Add support for all 4 ARGB formats ...without format conversion. --- diff --git a/gst/smpte/gstsmptealpha.c b/gst/smpte/gstsmptealpha.c index cd91e84..ebc2068 100644 --- a/gst/smpte/gstsmptealpha.c +++ b/gst/smpte/gstsmptealpha.c @@ -62,11 +62,12 @@ GST_DEBUG_CATEGORY_STATIC (gst_smpte_alpha_debug); #define GST_CAT_DEFAULT gst_smpte_alpha_debug static GstStaticPadTemplate gst_smpte_alpha_src_template = -GST_STATIC_PAD_TEMPLATE ("src", + GST_STATIC_PAD_TEMPLATE ("src", GST_PAD_SRC, GST_PAD_ALWAYS, - GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV ("AYUV") - ) + GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV ("AYUV") ";" + GST_VIDEO_CAPS_ARGB ";" GST_VIDEO_CAPS_BGRA ";" + GST_VIDEO_CAPS_RGBA ";" GST_VIDEO_CAPS_ARGB) ); static GstStaticPadTemplate gst_smpte_alpha_sink_template = @@ -74,7 +75,8 @@ static GstStaticPadTemplate gst_smpte_alpha_sink_template = GST_PAD_SINK, GST_PAD_ALWAYS, GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV ("I420") ";" GST_VIDEO_CAPS_YUV ("AYUV") - ) + ";" GST_VIDEO_CAPS_ARGB ";" GST_VIDEO_CAPS_BGRA ";" GST_VIDEO_CAPS_RGBA + ";" GST_VIDEO_CAPS_ARGB) ); /* SMPTE signals and properties */ @@ -147,14 +149,8 @@ static gboolean gst_smpte_alpha_get_unit_size (GstBaseTransform * btrans, GstCaps * caps, guint * size); static GstFlowReturn gst_smpte_alpha_transform (GstBaseTransform * trans, GstBuffer * in, GstBuffer * out); - -static void -gst_smpte_alpha_process_i420_ayuv (GstSMPTEAlpha * smpte, const guint8 * in, - guint8 * out, GstMask * mask, gint width, gint height, gint border, - gint pos); -static void gst_smpte_alpha_process_ayuv_ayuv (GstSMPTEAlpha * smpte, - const guint8 * in, guint8 * out, GstMask * mask, gint width, gint height, - gint border, gint pos); +static GstCaps *gst_smpte_alpha_transform_caps (GstBaseTransform * trans, + GstPadDirection direction, GstCaps * from); GST_BOILERPLATE (GstSMPTEAlpha, gst_smpte_alpha, GstVideoFilter, GST_TYPE_VIDEO_FILTER); @@ -212,6 +208,8 @@ gst_smpte_alpha_class_init (GstSMPTEAlphaClass * klass) trans_class->get_unit_size = GST_DEBUG_FUNCPTR (gst_smpte_alpha_get_unit_size); trans_class->transform = GST_DEBUG_FUNCPTR (gst_smpte_alpha_transform); + trans_class->transform_caps = + GST_DEBUG_FUNCPTR (gst_smpte_alpha_transform_caps); } static gboolean @@ -260,79 +258,6 @@ mask_failed: } } -static gboolean -gst_smpte_alpha_setcaps (GstBaseTransform * btrans, GstCaps * incaps, - GstCaps * outcaps) -{ - GstSMPTEAlpha *smpte = GST_SMPTE_ALPHA (btrans); - gboolean ret; - gint width, height; - - smpte->process = NULL; - - if (!gst_video_format_parse_caps (incaps, &smpte->in_format, &width, &height)) - goto invalid_caps; - if (!gst_video_format_parse_caps (outcaps, &smpte->out_format, &width, - &height)) - goto invalid_caps; - - /* try to update the mask now, this will also adjust the width/height on - * success */ - GST_OBJECT_LOCK (smpte); - ret = - gst_smpte_alpha_update_mask (smpte, smpte->type, smpte->invert, - smpte->depth, width, height); - GST_OBJECT_UNLOCK (smpte); - if (!ret) - goto mask_failed; - - switch (smpte->out_format) { - case GST_VIDEO_FORMAT_AYUV: - switch (smpte->in_format) { - case GST_VIDEO_FORMAT_AYUV: - smpte->process = gst_smpte_alpha_process_ayuv_ayuv; - break; - case GST_VIDEO_FORMAT_I420: - smpte->process = gst_smpte_alpha_process_i420_ayuv; - break; - default: - break; - } - break; - default: - break; - } - - return ret; - - /* ERRORS */ -invalid_caps: - { - GST_ERROR_OBJECT (smpte, "Invalid caps: %" GST_PTR_FORMAT, incaps); - return FALSE; - } -mask_failed: - { - GST_ERROR_OBJECT (smpte, "failed creating the mask"); - return FALSE; - } -} - -static gboolean -gst_smpte_alpha_get_unit_size (GstBaseTransform * btrans, GstCaps * caps, - guint * size) -{ - gint width, height; - GstVideoFormat format; - - if (!gst_video_format_parse_caps (caps, &format, &width, &height)) - return FALSE; - - *size = gst_video_format_get_size (format, width, height); - - return TRUE; -} - static void gst_smpte_alpha_init (GstSMPTEAlpha * smpte, GstSMPTEAlphaClass * klass) { @@ -343,16 +268,47 @@ gst_smpte_alpha_init (GstSMPTEAlpha * smpte, GstSMPTEAlphaClass * klass) smpte->invert = DEFAULT_PROP_INVERT; } -static void -gst_smpte_alpha_finalize (GstSMPTEAlpha * smpte) -{ - if (smpte->mask) - gst_mask_destroy (smpte->mask); - smpte->mask = NULL; - - G_OBJECT_CLASS (parent_class)->finalize ((GObject *) smpte); +#define CREATE_ARGB_FUNC(name, A, R, G, B) \ +static void \ +gst_smpte_alpha_process_##name##_##name (GstSMPTEAlpha * smpte, const guint8 * in, \ + guint8 * out, GstMask * mask, gint width, gint height, gint border, \ + gint pos) \ +{ \ + gint i, j; \ + const guint32 *maskp; \ + gint value; \ + gint min, max; \ + \ + if (border == 0) \ + border++; \ + \ + min = pos - border; \ + max = pos; \ + GST_DEBUG_OBJECT (smpte, "pos %d, min %d, max %d, border %d", pos, min, max, \ + border); \ + \ + maskp = mask->data; \ + \ + /* we basically copy the source to dest but we scale the alpha channel with \ + * the mask */ \ + for (i = 0; i < height; i++) { \ + for (j = 0; j < width; j++) { \ + value = *maskp++; \ + out[A] = (in[A] * ((CLAMP (value, min, max) - min) << 8) / border) >> 8; \ + out[R] = in[R]; \ + out[G] = in[G]; \ + out[B] = in[B]; \ + out += 4; \ + in += 4; \ + } \ + } \ } +CREATE_ARGB_FUNC (argb, 0, 1, 2, 3); +CREATE_ARGB_FUNC (bgra, 3, 2, 1, 0); +CREATE_ARGB_FUNC (abgr, 0, 3, 2, 1); +CREATE_ARGB_FUNC (rgba, 3, 0, 1, 2); + static void gst_smpte_alpha_process_ayuv_ayuv (GstSMPTEAlpha * smpte, const guint8 * in, guint8 * out, GstMask * mask, gint width, gint height, gint border, @@ -504,6 +460,162 @@ not_negotiated: } } +static GstCaps * +gst_smpte_alpha_transform_caps (GstBaseTransform * trans, + GstPadDirection direction, GstCaps * from) +{ + GstCaps *to = gst_caps_copy (from); + GstStructure *s; + + gst_caps_truncate (to); + s = gst_caps_get_structure (to, 0); + + if (gst_structure_has_name (s, "video/x-raw-yuv")) { + GValue list = { 0, }; + GValue val = { 0, }; + + gst_structure_remove_field (s, "format"); + + g_value_init (&list, GST_TYPE_LIST); + g_value_init (&val, GST_TYPE_FOURCC); + gst_value_set_fourcc (&val, GST_STR_FOURCC ("AYUV")); + gst_value_list_append_value (&list, &val); + g_value_reset (&val); + gst_value_set_fourcc (&val, GST_STR_FOURCC ("I420")); + gst_value_list_append_value (&list, &val); + g_value_reset (&val); + gst_value_set_fourcc (&val, GST_STR_FOURCC ("YV12")); + gst_value_list_append_value (&list, &val); + g_value_unset (&val); + gst_structure_set_value (s, "format", &list); + g_value_unset (&list); + } else if (!gst_structure_has_name (s, "video/x-raw-rgb")) { + gst_caps_unref (to); + to = gst_caps_new_empty (); + } + + return to; +} + +static gboolean +gst_smpte_alpha_setcaps (GstBaseTransform * btrans, GstCaps * incaps, + GstCaps * outcaps) +{ + GstSMPTEAlpha *smpte = GST_SMPTE_ALPHA (btrans); + gboolean ret; + gint width, height; + + smpte->process = NULL; + + if (!gst_video_format_parse_caps (incaps, &smpte->in_format, &width, &height)) + goto invalid_caps; + if (!gst_video_format_parse_caps (outcaps, &smpte->out_format, &width, + &height)) + goto invalid_caps; + + /* try to update the mask now, this will also adjust the width/height on + * success */ + GST_OBJECT_LOCK (smpte); + ret = + gst_smpte_alpha_update_mask (smpte, smpte->type, smpte->invert, + smpte->depth, width, height); + GST_OBJECT_UNLOCK (smpte); + if (!ret) + goto mask_failed; + + switch (smpte->out_format) { + case GST_VIDEO_FORMAT_AYUV: + switch (smpte->in_format) { + case GST_VIDEO_FORMAT_AYUV: + smpte->process = gst_smpte_alpha_process_ayuv_ayuv; + break; + case GST_VIDEO_FORMAT_I420: + smpte->process = gst_smpte_alpha_process_i420_ayuv; + break; + default: + break; + } + break; + case GST_VIDEO_FORMAT_ARGB: + switch (smpte->in_format) { + case GST_VIDEO_FORMAT_ARGB: + smpte->process = gst_smpte_alpha_process_argb_argb; + break; + default: + break; + } + break; + case GST_VIDEO_FORMAT_RGBA: + switch (smpte->in_format) { + case GST_VIDEO_FORMAT_RGBA: + smpte->process = gst_smpte_alpha_process_rgba_rgba; + break; + default: + break; + } + break; + case GST_VIDEO_FORMAT_ABGR: + switch (smpte->in_format) { + case GST_VIDEO_FORMAT_ABGR: + smpte->process = gst_smpte_alpha_process_abgr_abgr; + break; + default: + break; + } + break; + case GST_VIDEO_FORMAT_BGRA: + switch (smpte->in_format) { + case GST_VIDEO_FORMAT_BGRA: + smpte->process = gst_smpte_alpha_process_bgra_bgra; + break; + default: + break; + } + break; + default: + break; + } + + return ret; + + /* ERRORS */ +invalid_caps: + { + GST_ERROR_OBJECT (smpte, "Invalid caps: %" GST_PTR_FORMAT, incaps); + return FALSE; + } +mask_failed: + { + GST_ERROR_OBJECT (smpte, "failed creating the mask"); + return FALSE; + } +} + +static gboolean +gst_smpte_alpha_get_unit_size (GstBaseTransform * btrans, GstCaps * caps, + guint * size) +{ + gint width, height; + GstVideoFormat format; + + if (!gst_video_format_parse_caps (caps, &format, &width, &height)) + return FALSE; + + *size = gst_video_format_get_size (format, width, height); + + return TRUE; +} + +static void +gst_smpte_alpha_finalize (GstSMPTEAlpha * smpte) +{ + if (smpte->mask) + gst_mask_destroy (smpte->mask); + smpte->mask = NULL; + + G_OBJECT_CLASS (parent_class)->finalize ((GObject *) smpte); +} + static void gst_smpte_alpha_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec)