diff options
Diffstat (limited to 'wearable/gst/alpha/gstalpha.c')
-rw-r--r-- | wearable/gst/alpha/gstalpha.c | 2654 |
1 files changed, 0 insertions, 2654 deletions
diff --git a/wearable/gst/alpha/gstalpha.c b/wearable/gst/alpha/gstalpha.c deleted file mode 100644 index f4d0cce..0000000 --- a/wearable/gst/alpha/gstalpha.c +++ /dev/null @@ -1,2654 +0,0 @@ -/* GStreamer - * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu> - * Copyright (C) <2007> Wim Taymans <wim.taymans@collabora.co.uk> - * Copyright (C) <2007> Edward Hervey <edward.hervey@collabora.co.uk> - * Copyright (C) <2007> Jan Schmidt <thaytan@noraisin.net> - * - * 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-alpha - * - * The alpha element adds an alpha channel to a video stream. The values - * of the alpha channel can be either be set to a constant or can be - * dynamically calculated via chroma keying, e.g. blue can be set as - * the transparent color. - * - * Sample pipeline: - * |[ - * gst-launch videotestsrc pattern=smpte75 ! alpha method=green ! \ - * videomixer name=mixer ! ffmpegcolorspace ! autovideosink \ - * videotestsrc pattern=snow ! mixer. - * ]| This pipeline adds a alpha channel to the SMPTE color bars - * with green as the transparent color and mixes the output with - * a snow video stream. - */ - - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "gstalpha.h" - -#include <stdlib.h> -#include <string.h> -#include <math.h> - -#ifndef M_PI -#define M_PI 3.14159265358979323846 -#endif - -/* Generated by -bad/ext/cog/generate_tables */ -static const int cog_ycbcr_to_rgb_matrix_8bit_hdtv[] = { - 298, 0, 459, -63514, - 298, -55, -136, 19681, - 298, 541, 0, -73988, -}; - -static const int cog_ycbcr_to_rgb_matrix_8bit_sdtv[] = { - 298, 0, 409, -57068, - 298, -100, -208, 34707, - 298, 516, 0, -70870, -}; - -static const gint cog_rgb_to_ycbcr_matrix_8bit_hdtv[] = { - 47, 157, 16, 4096, - -26, -87, 112, 32768, - 112, -102, -10, 32768, -}; - -static const gint cog_rgb_to_ycbcr_matrix_8bit_sdtv[] = { - 66, 129, 25, 4096, - -38, -74, 112, 32768, - 112, -94, -18, 32768, -}; - -static const gint cog_ycbcr_sdtv_to_ycbcr_hdtv_matrix_8bit[] = { - 256, -30, -53, 10600, - 0, 261, 29, -4367, - 0, 19, 262, -3289, -}; - -static const gint cog_ycbcr_hdtv_to_ycbcr_sdtv_matrix_8bit[] = { - 256, 25, 49, -9536, - 0, 253, -28, 3958, - 0, -19, 252, 2918, -}; - -/* Alpha signals and args */ -enum -{ - /* FILL ME */ - LAST_SIGNAL -}; - -#define DEFAULT_METHOD ALPHA_METHOD_SET -#define DEFAULT_ALPHA 1.0 -#define DEFAULT_TARGET_R 0 -#define DEFAULT_TARGET_G 255 -#define DEFAULT_TARGET_B 0 -#define DEFAULT_ANGLE 20.0 -#define DEFAULT_NOISE_LEVEL 2.0 -#define DEFAULT_BLACK_SENSITIVITY 100 -#define DEFAULT_WHITE_SENSITIVITY 100 -#define DEFAULT_PREFER_PASSTHROUGH FALSE - -enum -{ - PROP_0, - PROP_METHOD, - PROP_ALPHA, - PROP_TARGET_R, - PROP_TARGET_G, - PROP_TARGET_B, - PROP_ANGLE, - PROP_NOISE_LEVEL, - PROP_BLACK_SENSITIVITY, - PROP_WHITE_SENSITIVITY, - PROP_PREFER_PASSTHROUGH, - PROP_LAST -}; - -static GstStaticPadTemplate gst_alpha_src_template = - GST_STATIC_PAD_TEMPLATE ("src", - GST_PAD_SRC, - GST_PAD_ALWAYS, - GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV ("AYUV") ";" - GST_VIDEO_CAPS_ARGB ";" GST_VIDEO_CAPS_BGRA ";" - GST_VIDEO_CAPS_ABGR ";" GST_VIDEO_CAPS_RGBA - ";" GST_VIDEO_CAPS_YUV ("Y444") - ";" GST_VIDEO_CAPS_xRGB ";" GST_VIDEO_CAPS_BGRx ";" GST_VIDEO_CAPS_xBGR - ";" GST_VIDEO_CAPS_RGBx ";" GST_VIDEO_CAPS_RGB ";" GST_VIDEO_CAPS_BGR - ";" GST_VIDEO_CAPS_YUV ("Y42B") ";" GST_VIDEO_CAPS_YUV ("YUY2") - ";" GST_VIDEO_CAPS_YUV ("YVYU") ";" GST_VIDEO_CAPS_YUV ("UYVY") - ";" GST_VIDEO_CAPS_YUV ("I420") ";" GST_VIDEO_CAPS_YUV ("YV12") - ";" GST_VIDEO_CAPS_YUV ("Y41B")) - ); - -static GstStaticPadTemplate gst_alpha_sink_template = - GST_STATIC_PAD_TEMPLATE ("sink", - GST_PAD_SINK, - GST_PAD_ALWAYS, - GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV ("AYUV") - ";" GST_VIDEO_CAPS_ARGB ";" GST_VIDEO_CAPS_BGRA ";" GST_VIDEO_CAPS_ABGR - ";" GST_VIDEO_CAPS_RGBA ";" GST_VIDEO_CAPS_YUV ("Y444") - ";" GST_VIDEO_CAPS_xRGB ";" GST_VIDEO_CAPS_BGRx ";" GST_VIDEO_CAPS_xBGR - ";" GST_VIDEO_CAPS_RGBx ";" GST_VIDEO_CAPS_RGB ";" GST_VIDEO_CAPS_BGR - ";" GST_VIDEO_CAPS_YUV ("Y42B") ";" GST_VIDEO_CAPS_YUV ("YUY2") - ";" GST_VIDEO_CAPS_YUV ("YVYU") ";" GST_VIDEO_CAPS_YUV ("UYVY") - ";" GST_VIDEO_CAPS_YUV ("I420") ";" GST_VIDEO_CAPS_YUV ("YV12") - ";" GST_VIDEO_CAPS_YUV ("Y41B") - ) - ); - -static GstStaticCaps gst_alpha_alpha_caps = - GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV ("AYUV") - ";" GST_VIDEO_CAPS_ARGB ";" GST_VIDEO_CAPS_BGRA ";" GST_VIDEO_CAPS_ABGR ";" - GST_VIDEO_CAPS_RGBA); - -/* FIXME: why do we need our own lock for this? */ -#if !GLIB_CHECK_VERSION (2, 31, 0) -#define GST_ALPHA_LOCK(alpha) G_STMT_START { \ - GST_LOG_OBJECT (alpha, "Locking alpha from thread %p", g_thread_self ()); \ - g_static_mutex_lock (&alpha->lock); \ - GST_LOG_OBJECT (alpha, "Locked alpha from thread %p", g_thread_self ()); \ -} G_STMT_END - -#define GST_ALPHA_UNLOCK(alpha) G_STMT_START { \ - GST_LOG_OBJECT (alpha, "Unlocking alpha from thread %p", g_thread_self ()); \ - g_static_mutex_unlock (&alpha->lock); \ -} G_STMT_END -#else -#define GST_ALPHA_LOCK(alpha) G_STMT_START { \ - GST_LOG_OBJECT (alpha, "Locking alpha from thread %p", g_thread_self ()); \ - g_mutex_lock (&alpha->lock); \ - GST_LOG_OBJECT (alpha, "Locked alpha from thread %p", g_thread_self ()); \ -} G_STMT_END - -#define GST_ALPHA_UNLOCK(alpha) G_STMT_START { \ - GST_LOG_OBJECT (alpha, "Unlocking alpha from thread %p", g_thread_self ()); \ - g_mutex_unlock (&alpha->lock); \ -} G_STMT_END -#endif - -static gboolean gst_alpha_start (GstBaseTransform * trans); -static gboolean gst_alpha_get_unit_size (GstBaseTransform * btrans, - GstCaps * caps, guint * size); -static GstCaps *gst_alpha_transform_caps (GstBaseTransform * btrans, - GstPadDirection direction, GstCaps * caps); -static gboolean gst_alpha_set_caps (GstBaseTransform * btrans, - GstCaps * incaps, GstCaps * outcaps); -static GstFlowReturn gst_alpha_transform (GstBaseTransform * btrans, - GstBuffer * in, GstBuffer * out); -static void gst_alpha_before_transform (GstBaseTransform * btrans, - GstBuffer * buf); - -static void gst_alpha_init_params (GstAlpha * alpha); -static gboolean gst_alpha_set_process_function (GstAlpha * alpha); - -static void gst_alpha_set_property (GObject * object, guint prop_id, - const GValue * value, GParamSpec * pspec); -static void gst_alpha_get_property (GObject * object, guint prop_id, - GValue * value, GParamSpec * pspec); -static void gst_alpha_finalize (GObject * object); - -GST_BOILERPLATE (GstAlpha, gst_alpha, GstVideoFilter, GST_TYPE_VIDEO_FILTER); - -#define GST_TYPE_ALPHA_METHOD (gst_alpha_method_get_type()) -static GType -gst_alpha_method_get_type (void) -{ - static GType alpha_method_type = 0; - static const GEnumValue alpha_method[] = { - {ALPHA_METHOD_SET, "Set/adjust alpha channel", "set"}, - {ALPHA_METHOD_GREEN, "Chroma Key green", "green"}, - {ALPHA_METHOD_BLUE, "Chroma Key blue", "blue"}, - {ALPHA_METHOD_CUSTOM, "Chroma Key on target_r/g/b", "custom"}, - {0, NULL, NULL}, - }; - - if (!alpha_method_type) { - alpha_method_type = g_enum_register_static ("GstAlphaMethod", alpha_method); - } - return alpha_method_type; -} - -static void -gst_alpha_base_init (gpointer g_class) -{ - GstElementClass *element_class = GST_ELEMENT_CLASS (g_class); - - gst_element_class_set_details_simple (element_class, "Alpha filter", - "Filter/Effect/Video", - "Adds an alpha channel to video - uniform or via chroma-keying", - "Wim Taymans <wim@fluendo.com>\n" - "Edward Hervey <edward.hervey@collabora.co.uk>\n" - "Jan Schmidt <thaytan@noraisin.net>"); - - gst_element_class_add_static_pad_template (element_class, - &gst_alpha_sink_template); - gst_element_class_add_static_pad_template (element_class, - &gst_alpha_src_template); - - GST_DEBUG_CATEGORY_INIT (gst_alpha_debug, "alpha", 0, - "alpha - Element for adding alpha channel to streams"); -} - -static void -gst_alpha_class_init (GstAlphaClass * klass) -{ - GObjectClass *gobject_class = (GObjectClass *) klass; - GstBaseTransformClass *btrans_class = (GstBaseTransformClass *) klass; - - gobject_class->set_property = gst_alpha_set_property; - gobject_class->get_property = gst_alpha_get_property; - gobject_class->finalize = gst_alpha_finalize; - - g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_METHOD, - g_param_spec_enum ("method", "Method", - "How the alpha channels should be created", GST_TYPE_ALPHA_METHOD, - DEFAULT_METHOD, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_ALPHA, - g_param_spec_double ("alpha", "Alpha", "The value for the alpha channel", - 0.0, 1.0, DEFAULT_ALPHA, - G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS)); - g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_TARGET_R, - g_param_spec_uint ("target-r", "Target Red", "The Red target", 0, 255, - DEFAULT_TARGET_R, - G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS)); - g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_TARGET_G, - g_param_spec_uint ("target-g", "Target Green", "The Green target", 0, 255, - DEFAULT_TARGET_G, - G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS)); - g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_TARGET_B, - g_param_spec_uint ("target-b", "Target Blue", "The Blue target", 0, 255, - DEFAULT_TARGET_B, - G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS)); - g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_ANGLE, - g_param_spec_float ("angle", "Angle", "Size of the colorcube to change", - 0.0, 90.0, DEFAULT_ANGLE, - G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS)); - g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_NOISE_LEVEL, - g_param_spec_float ("noise-level", "Noise Level", "Size of noise radius", - 0.0, 64.0, DEFAULT_NOISE_LEVEL, - G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS)); - g_object_class_install_property (G_OBJECT_CLASS (klass), - PROP_BLACK_SENSITIVITY, g_param_spec_uint ("black-sensitivity", - "Black Sensitivity", "Sensitivity to dark colors", 0, 128, - DEFAULT_BLACK_SENSITIVITY, - G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS)); - g_object_class_install_property (G_OBJECT_CLASS (klass), - PROP_WHITE_SENSITIVITY, g_param_spec_uint ("white-sensitivity", - "Sensitivity", "Sensitivity to bright colors", 0, 128, - DEFAULT_WHITE_SENSITIVITY, - G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS)); - g_object_class_install_property (G_OBJECT_CLASS (klass), - PROP_PREFER_PASSTHROUGH, g_param_spec_boolean ("prefer-passthrough", - "Prefer Passthrough", - "Don't do any processing for alpha=1.0 if possible", - DEFAULT_PREFER_PASSTHROUGH, - G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS)); - - btrans_class->start = GST_DEBUG_FUNCPTR (gst_alpha_start); - btrans_class->transform = GST_DEBUG_FUNCPTR (gst_alpha_transform); - btrans_class->before_transform = - GST_DEBUG_FUNCPTR (gst_alpha_before_transform); - btrans_class->get_unit_size = GST_DEBUG_FUNCPTR (gst_alpha_get_unit_size); - btrans_class->transform_caps = GST_DEBUG_FUNCPTR (gst_alpha_transform_caps); - btrans_class->set_caps = GST_DEBUG_FUNCPTR (gst_alpha_set_caps); -} - -static void -gst_alpha_init (GstAlpha * alpha, GstAlphaClass * klass) -{ - alpha->alpha = DEFAULT_ALPHA; - alpha->method = DEFAULT_METHOD; - alpha->target_r = DEFAULT_TARGET_R; - alpha->target_g = DEFAULT_TARGET_G; - alpha->target_b = DEFAULT_TARGET_B; - alpha->angle = DEFAULT_ANGLE; - alpha->noise_level = DEFAULT_NOISE_LEVEL; - alpha->black_sensitivity = DEFAULT_BLACK_SENSITIVITY; - alpha->white_sensitivity = DEFAULT_WHITE_SENSITIVITY; - -#if !GLIB_CHECK_VERSION (2, 31, 0) - g_static_mutex_init (&alpha->lock); -#else - g_mutex_init (&alpha->lock); -#endif -} - -static void -gst_alpha_finalize (GObject * object) -{ - GstAlpha *alpha = GST_ALPHA (object); - -#if !GLIB_CHECK_VERSION (2, 31, 0) - g_static_mutex_free (&alpha->lock); -#else - g_mutex_clear (&alpha->lock); -#endif - - G_OBJECT_CLASS (parent_class)->finalize (object); -} - -static void -gst_alpha_set_property (GObject * object, guint prop_id, - const GValue * value, GParamSpec * pspec) -{ - GstAlpha *alpha = GST_ALPHA (object); - gboolean reconfigure = FALSE; - - GST_ALPHA_LOCK (alpha); - switch (prop_id) { - case PROP_METHOD:{ - gint method = g_value_get_enum (value); - - reconfigure = (method != alpha->method) && (method == ALPHA_METHOD_SET - || alpha->method == ALPHA_METHOD_SET) && (alpha->alpha == 1.0) - && (alpha->prefer_passthrough); - alpha->method = method; - - switch (alpha->method) { - case ALPHA_METHOD_GREEN: - alpha->target_r = 0; - alpha->target_g = 255; - alpha->target_b = 0; - break; - case ALPHA_METHOD_BLUE: - alpha->target_r = 0; - alpha->target_g = 0; - alpha->target_b = 255; - break; - default: - break; - } - gst_alpha_set_process_function (alpha); - gst_alpha_init_params (alpha); - break; - } - case PROP_ALPHA:{ - gdouble a = g_value_get_double (value); - - reconfigure = (a != alpha->alpha) && (a == 1.0 || alpha->alpha == 1.0) - && (alpha->method == ALPHA_METHOD_SET) && (alpha->prefer_passthrough); - alpha->alpha = a; - break; - } - case PROP_TARGET_R: - alpha->target_r = g_value_get_uint (value); - gst_alpha_init_params (alpha); - break; - case PROP_TARGET_G: - alpha->target_g = g_value_get_uint (value); - gst_alpha_init_params (alpha); - break; - case PROP_TARGET_B: - alpha->target_b = g_value_get_uint (value); - gst_alpha_init_params (alpha); - break; - case PROP_ANGLE: - alpha->angle = g_value_get_float (value); - gst_alpha_init_params (alpha); - break; - case PROP_NOISE_LEVEL: - alpha->noise_level = g_value_get_float (value); - gst_alpha_init_params (alpha); - break; - case PROP_BLACK_SENSITIVITY: - alpha->black_sensitivity = g_value_get_uint (value); - break; - case PROP_WHITE_SENSITIVITY: - alpha->white_sensitivity = g_value_get_uint (value); - break; - case PROP_PREFER_PASSTHROUGH:{ - gboolean prefer_passthrough = g_value_get_boolean (value); - - reconfigure = ((! !prefer_passthrough) != (! !alpha->prefer_passthrough)) - && (alpha->method == ALPHA_METHOD_SET) && (alpha->alpha == 1.0); - alpha->prefer_passthrough = prefer_passthrough; - break; - } - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } - - if (reconfigure) - gst_base_transform_reconfigure (GST_BASE_TRANSFORM_CAST (alpha)); - - GST_ALPHA_UNLOCK (alpha); -} - -static void -gst_alpha_get_property (GObject * object, guint prop_id, GValue * value, - GParamSpec * pspec) -{ - GstAlpha *alpha = GST_ALPHA (object); - - switch (prop_id) { - case PROP_METHOD: - g_value_set_enum (value, alpha->method); - break; - case PROP_ALPHA: - g_value_set_double (value, alpha->alpha); - break; - case PROP_TARGET_R: - g_value_set_uint (value, alpha->target_r); - break; - case PROP_TARGET_G: - g_value_set_uint (value, alpha->target_g); - break; - case PROP_TARGET_B: - g_value_set_uint (value, alpha->target_b); - break; - case PROP_ANGLE: - g_value_set_float (value, alpha->angle); - break; - case PROP_NOISE_LEVEL: - g_value_set_float (value, alpha->noise_level); - break; - case PROP_BLACK_SENSITIVITY: - g_value_set_uint (value, alpha->black_sensitivity); - break; - case PROP_WHITE_SENSITIVITY: - g_value_set_uint (value, alpha->white_sensitivity); - break; - case PROP_PREFER_PASSTHROUGH: - g_value_set_boolean (value, alpha->prefer_passthrough); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static gboolean -gst_alpha_get_unit_size (GstBaseTransform * btrans, - GstCaps * caps, guint * size) -{ - GstVideoFormat format; - gint width, height; - - if (!gst_video_format_parse_caps (caps, &format, &width, &height)) - return FALSE; - - *size = gst_video_format_get_size (format, width, height); - - GST_DEBUG_OBJECT (btrans, "unit size = %d for format %d w %d height %d", - *size, format, width, height); - - return TRUE; -} - -static GstCaps * -gst_alpha_transform_caps (GstBaseTransform * btrans, - GstPadDirection direction, GstCaps * caps) -{ - GstAlpha *alpha = GST_ALPHA (btrans); - GstCaps *ret, *tmp, *tmp2; - GstStructure *structure; - gint i; - - tmp = gst_caps_new_empty (); - - GST_ALPHA_LOCK (alpha); - for (i = 0; i < gst_caps_get_size (caps); i++) { - structure = gst_structure_copy (gst_caps_get_structure (caps, i)); - - gst_structure_remove_field (structure, "format"); - gst_structure_remove_field (structure, "endianness"); - gst_structure_remove_field (structure, "depth"); - gst_structure_remove_field (structure, "bpp"); - gst_structure_remove_field (structure, "red_mask"); - gst_structure_remove_field (structure, "green_mask"); - gst_structure_remove_field (structure, "blue_mask"); - gst_structure_remove_field (structure, "alpha_mask"); - gst_structure_remove_field (structure, "color-matrix"); - gst_structure_remove_field (structure, "chroma-site"); - - gst_structure_set_name (structure, "video/x-raw-yuv"); - gst_caps_append_structure (tmp, gst_structure_copy (structure)); - gst_structure_set_name (structure, "video/x-raw-rgb"); - gst_caps_append_structure (tmp, structure); - } - - if (direction == GST_PAD_SINK) { - tmp2 = gst_static_caps_get (&gst_alpha_alpha_caps); - ret = gst_caps_intersect (tmp, tmp2); - gst_caps_unref (tmp); - gst_caps_unref (tmp2); - tmp = ret; - ret = NULL; - - if (alpha->prefer_passthrough && alpha->method == ALPHA_METHOD_SET - && alpha->alpha == 1.0) { - ret = gst_caps_copy (caps); - gst_caps_append (ret, tmp); - tmp = NULL; - } else { - ret = tmp; - tmp = NULL; - } - } else { - ret = tmp; - tmp = NULL; - } - - GST_DEBUG_OBJECT (alpha, - "Transformed %" GST_PTR_FORMAT " -> %" GST_PTR_FORMAT, caps, ret); - - GST_ALPHA_UNLOCK (alpha); - - return ret; -} - -static gboolean -gst_alpha_set_caps (GstBaseTransform * btrans, - GstCaps * incaps, GstCaps * outcaps) -{ - GstAlpha *alpha = GST_ALPHA (btrans); - const gchar *matrix; - gboolean passthrough; - - GST_ALPHA_LOCK (alpha); - - if (!gst_video_format_parse_caps (incaps, &alpha->in_format, - &alpha->width, &alpha->height) || - !gst_video_format_parse_caps (outcaps, &alpha->out_format, - &alpha->width, &alpha->height)) { - GST_WARNING_OBJECT (alpha, - "Failed to parse caps %" GST_PTR_FORMAT " -> %" GST_PTR_FORMAT, incaps, - outcaps); - GST_ALPHA_UNLOCK (alpha); - return FALSE; - } - - matrix = gst_video_parse_caps_color_matrix (incaps); - alpha->in_sdtv = matrix ? g_str_equal (matrix, "sdtv") : TRUE; - - matrix = gst_video_parse_caps_color_matrix (outcaps); - alpha->out_sdtv = matrix ? g_str_equal (matrix, "sdtv") : TRUE; - - passthrough = alpha->prefer_passthrough && - alpha->in_format == alpha->out_format && alpha->in_sdtv == alpha->out_sdtv - && alpha->method == ALPHA_METHOD_SET && alpha->alpha == 1.0; - - GST_DEBUG_OBJECT (alpha, - "Setting caps %" GST_PTR_FORMAT " -> %" GST_PTR_FORMAT - " (passthrough: %d)", incaps, outcaps, passthrough); - gst_base_transform_set_passthrough (btrans, passthrough); - - if (!gst_alpha_set_process_function (alpha) && !passthrough) { - GST_WARNING_OBJECT (alpha, - "No processing function for this caps and no passthrough mode"); - GST_ALPHA_UNLOCK (alpha); - return FALSE; - } - - gst_alpha_init_params (alpha); - - GST_ALPHA_UNLOCK (alpha); - - return TRUE; -} - -/* based on http://www.cs.utah.edu/~michael/chroma/ - */ -static inline gint -chroma_keying_yuv (gint a, gint * y, gint * u, - gint * v, gint cr, gint cb, gint smin, gint smax, guint8 accept_angle_tg, - guint8 accept_angle_ctg, guint8 one_over_kc, guint8 kfgy_scale, gint8 kg, - guint noise_level2) -{ - gint tmp, tmp1; - gint x1, y1; - gint x, z; - gint b_alpha; - - /* too dark or too bright, keep alpha */ - if (*y < smin || *y > smax) - return a; - - /* Convert foreground to XZ coords where X direction is defined by - the key color */ - tmp = ((*u) * cb + (*v) * cr) >> 7; - x = CLAMP (tmp, -128, 127); - tmp = ((*v) * cb - (*u) * cr) >> 7; - z = CLAMP (tmp, -128, 127); - - /* WARNING: accept angle should never be set greater than "somewhat less - than 90 degrees" to avoid dealing with negative/infinite tg. In reality, - 80 degrees should be enough if foreground is reasonable. If this seems - to be a problem, go to alternative ways of checking point position - (scalar product or line equations). This angle should not be too small - either to avoid infinite ctg (used to suppress foreground without use of - division) */ - - tmp = (x * accept_angle_tg) >> 4; - tmp = MIN (tmp, 127); - - if (abs (z) > tmp) { - /* keep foreground Kfg = 0 */ - return a; - } - /* Compute Kfg (implicitly) and Kbg, suppress foreground in XZ coord - according to Kfg */ - tmp = (z * accept_angle_ctg) >> 4; - tmp = CLAMP (tmp, -128, 127); - x1 = abs (tmp); - y1 = z; - - tmp1 = x - x1; - tmp1 = MAX (tmp1, 0); - b_alpha = (tmp1 * one_over_kc) / 2; - b_alpha = 255 - CLAMP (b_alpha, 0, 255); - b_alpha = (a * b_alpha) >> 8; - - tmp = (tmp1 * kfgy_scale) >> 4; - tmp1 = MIN (tmp, 255); - - *y = (*y < tmp1) ? 0 : *y - tmp1; - - /* Convert suppressed foreground back to CbCr */ - tmp = (x1 * cb - y1 * cr) >> 7; - *u = CLAMP (tmp, -128, 127); - - tmp = (x1 * cr + y1 * cb) >> 7; - *v = CLAMP (tmp, -128, 127); - - /* Deal with noise. For now, a circle around the key color with - radius of noise_level treated as exact key color. Introduces - sharp transitions. - */ - tmp = z * z + (x - kg) * (x - kg); - tmp = MIN (tmp, 0xffff); - - if (tmp < noise_level2) - b_alpha = 0; - - return b_alpha; -} - -#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 void -gst_alpha_set_argb_ayuv (const guint8 * src, guint8 * dest, gint width, - gint height, GstAlpha * alpha) -{ - gint s_alpha = CLAMP ((gint) (alpha->alpha * 256), 0, 256); - gint i, j; - gint matrix[12]; - gint y, u, v; - gint o[4]; - - o[0] = - gst_video_format_get_component_offset (alpha->in_format, 3, width, - height); - o[1] = - gst_video_format_get_component_offset (alpha->in_format, 0, width, - height); - o[2] = - gst_video_format_get_component_offset (alpha->in_format, 1, width, - height); - o[3] = - gst_video_format_get_component_offset (alpha->in_format, 2, width, - height); - - memcpy (matrix, - alpha->out_sdtv ? cog_rgb_to_ycbcr_matrix_8bit_sdtv : - cog_rgb_to_ycbcr_matrix_8bit_hdtv, 12 * sizeof (gint)); - - for (i = 0; i < height; i++) { - for (j = 0; j < width; j++) { - dest[0] = (src[o[0]] * s_alpha) >> 8; - - y = APPLY_MATRIX (matrix, 0, src[o[1]], src[o[2]], src[o[3]]); - u = APPLY_MATRIX (matrix, 1, src[o[1]], src[o[2]], src[o[3]]); - v = APPLY_MATRIX (matrix, 2, src[o[1]], src[o[2]], src[o[3]]); - - dest[1] = y; - dest[2] = u; - dest[3] = v; - - dest += 4; - src += 4; - } - } -} - -static void -gst_alpha_chroma_key_argb_ayuv (const guint8 * src, guint8 * dest, gint width, - gint height, GstAlpha * alpha) -{ - gint i, j; - gint a, y, u, v; - gint r, g, b; - gint smin, smax; - gint pa = CLAMP ((gint) (alpha->alpha * 256), 0, 256); - gint8 cb = alpha->cb, cr = alpha->cr; - gint8 kg = alpha->kg; - guint8 accept_angle_tg = alpha->accept_angle_tg; - guint8 accept_angle_ctg = alpha->accept_angle_ctg; - guint8 one_over_kc = alpha->one_over_kc; - guint8 kfgy_scale = alpha->kfgy_scale; - guint noise_level2 = alpha->noise_level2; - gint matrix[12]; - gint o[4]; - - o[0] = - gst_video_format_get_component_offset (alpha->in_format, 3, width, - height); - o[1] = - gst_video_format_get_component_offset (alpha->in_format, 0, width, - height); - o[2] = - gst_video_format_get_component_offset (alpha->in_format, 1, width, - height); - o[3] = - gst_video_format_get_component_offset (alpha->in_format, 2, width, - height); - - smin = 128 - alpha->black_sensitivity; - smax = 128 + alpha->white_sensitivity; - - memcpy (matrix, - alpha->out_sdtv ? cog_rgb_to_ycbcr_matrix_8bit_sdtv : - cog_rgb_to_ycbcr_matrix_8bit_hdtv, 12 * sizeof (gint)); - - for (i = 0; i < height; i++) { - for (j = 0; j < width; j++) { - a = (src[o[0]] * pa) >> 8; - r = src[o[1]]; - g = src[o[2]]; - b = src[o[3]]; - - y = APPLY_MATRIX (matrix, 0, r, g, b); - u = APPLY_MATRIX (matrix, 1, r, g, b) - 128; - v = APPLY_MATRIX (matrix, 2, r, g, b) - 128; - - a = chroma_keying_yuv (a, &y, &u, &v, cr, cb, - smin, smax, accept_angle_tg, accept_angle_ctg, - one_over_kc, kfgy_scale, kg, noise_level2); - - u += 128; - v += 128; - - dest[0] = a; - dest[1] = y; - dest[2] = u; - dest[3] = v; - - src += 4; - dest += 4; - } - } -} - -static void -gst_alpha_set_argb_argb (const guint8 * src, guint8 * dest, gint width, - gint height, GstAlpha * alpha) -{ - gint s_alpha = CLAMP ((gint) (alpha->alpha * 256), 0, 256); - gint i, j; - gint p[4], o[4]; - - p[0] = - gst_video_format_get_component_offset (alpha->out_format, 3, width, - height); - p[1] = - gst_video_format_get_component_offset (alpha->out_format, 0, width, - height); - p[2] = - gst_video_format_get_component_offset (alpha->out_format, 1, width, - height); - p[3] = - gst_video_format_get_component_offset (alpha->out_format, 2, width, - height); - - o[0] = - gst_video_format_get_component_offset (alpha->in_format, 3, width, - height); - o[1] = - gst_video_format_get_component_offset (alpha->in_format, 0, width, - height); - o[2] = - gst_video_format_get_component_offset (alpha->in_format, 1, width, - height); - o[3] = - gst_video_format_get_component_offset (alpha->in_format, 2, width, - height); - - for (i = 0; i < height; i++) { - for (j = 0; j < width; j++) { - dest[p[0]] = (src[o[0]] * s_alpha) >> 8; - - dest[p[1]] = src[o[1]]; - dest[p[2]] = src[o[2]]; - dest[p[3]] = src[o[3]]; - - dest += 4; - src += 4; - } - } -} - -static void -gst_alpha_chroma_key_argb_argb (const guint8 * src, guint8 * dest, gint width, - gint height, GstAlpha * alpha) -{ - gint i, j; - gint a, y, u, v; - gint r, g, b; - gint smin, smax; - gint pa = CLAMP ((gint) (alpha->alpha * 256), 0, 256); - gint8 cb = alpha->cb, cr = alpha->cr; - gint8 kg = alpha->kg; - guint8 accept_angle_tg = alpha->accept_angle_tg; - guint8 accept_angle_ctg = alpha->accept_angle_ctg; - guint8 one_over_kc = alpha->one_over_kc; - guint8 kfgy_scale = alpha->kfgy_scale; - guint noise_level2 = alpha->noise_level2; - gint matrix[12], matrix2[12]; - gint p[4], o[4]; - - p[0] = - gst_video_format_get_component_offset (alpha->out_format, 3, width, - height); - p[1] = - gst_video_format_get_component_offset (alpha->out_format, 0, width, - height); - p[2] = - gst_video_format_get_component_offset (alpha->out_format, 1, width, - height); - p[3] = - gst_video_format_get_component_offset (alpha->out_format, 2, width, - height); - - o[0] = - gst_video_format_get_component_offset (alpha->in_format, 3, width, - height); - o[1] = - gst_video_format_get_component_offset (alpha->in_format, 0, width, - height); - o[2] = - gst_video_format_get_component_offset (alpha->in_format, 1, width, - height); - o[3] = - gst_video_format_get_component_offset (alpha->in_format, 2, width, - height); - - smin = 128 - alpha->black_sensitivity; - smax = 128 + alpha->white_sensitivity; - - memcpy (matrix, cog_rgb_to_ycbcr_matrix_8bit_sdtv, 12 * sizeof (gint)); - memcpy (matrix2, cog_ycbcr_to_rgb_matrix_8bit_sdtv, 12 * sizeof (gint)); - - for (i = 0; i < height; i++) { - for (j = 0; j < width; j++) { - a = (src[o[0]] * pa) >> 8; - r = src[o[1]]; - g = src[o[2]]; - b = src[o[3]]; - - y = APPLY_MATRIX (matrix, 0, r, g, b); - u = APPLY_MATRIX (matrix, 1, r, g, b) - 128; - v = APPLY_MATRIX (matrix, 2, r, g, b) - 128; - - a = chroma_keying_yuv (a, &y, &u, &v, cr, cb, - smin, smax, accept_angle_tg, accept_angle_ctg, - one_over_kc, kfgy_scale, kg, noise_level2); - - u += 128; - v += 128; - - r = APPLY_MATRIX (matrix2, 0, y, u, v); - g = APPLY_MATRIX (matrix2, 1, y, u, v); - b = APPLY_MATRIX (matrix2, 2, y, u, v); - - dest[p[0]] = a; - dest[p[1]] = CLAMP (r, 0, 255); - dest[p[2]] = CLAMP (g, 0, 255); - dest[p[3]] = CLAMP (b, 0, 255); - - src += 4; - dest += 4; - } - } -} - -static void -gst_alpha_set_ayuv_argb (const guint8 * src, guint8 * dest, gint width, - gint height, GstAlpha * alpha) -{ - gint s_alpha = CLAMP ((gint) (alpha->alpha * 256), 0, 256); - gint y, x; - gint matrix[12]; - gint r, g, b; - gint p[4]; - - p[0] = - gst_video_format_get_component_offset (alpha->out_format, 3, width, - height); - p[1] = - gst_video_format_get_component_offset (alpha->out_format, 0, width, - height); - p[2] = - gst_video_format_get_component_offset (alpha->out_format, 1, width, - height); - p[3] = - gst_video_format_get_component_offset (alpha->out_format, 2, width, - height); - - memcpy (matrix, - alpha->in_sdtv ? cog_ycbcr_to_rgb_matrix_8bit_sdtv : - cog_ycbcr_to_rgb_matrix_8bit_hdtv, 12 * sizeof (gint)); - - for (y = 0; y < height; y++) { - for (x = 0; x < width; x++) { - dest[p[0]] = (src[0] * s_alpha) >> 8; - - r = APPLY_MATRIX (matrix, 0, src[1], src[2], src[3]); - g = APPLY_MATRIX (matrix, 1, src[1], src[2], src[3]); - b = APPLY_MATRIX (matrix, 2, src[1], src[2], src[3]); - - dest[p[1]] = CLAMP (r, 0, 255); - dest[p[2]] = CLAMP (g, 0, 255); - dest[p[3]] = CLAMP (b, 0, 255); - - dest += 4; - src += 4; - } - } -} - -static void -gst_alpha_chroma_key_ayuv_argb (const guint8 * src, guint8 * dest, gint width, - gint height, GstAlpha * alpha) -{ - gint i, j; - gint a, y, u, v; - gint r, g, b; - gint smin, smax; - gint pa = CLAMP ((gint) (alpha->alpha * 256), 0, 256); - gint8 cb = alpha->cb, cr = alpha->cr; - gint8 kg = alpha->kg; - guint8 accept_angle_tg = alpha->accept_angle_tg; - guint8 accept_angle_ctg = alpha->accept_angle_ctg; - guint8 one_over_kc = alpha->one_over_kc; - guint8 kfgy_scale = alpha->kfgy_scale; - guint noise_level2 = alpha->noise_level2; - gint matrix[12]; - gint p[4]; - - p[0] = - gst_video_format_get_component_offset (alpha->out_format, 3, width, - height); - p[1] = - gst_video_format_get_component_offset (alpha->out_format, 0, width, - height); - p[2] = - gst_video_format_get_component_offset (alpha->out_format, 1, width, - height); - p[3] = - gst_video_format_get_component_offset (alpha->out_format, 2, width, - height); - - smin = 128 - alpha->black_sensitivity; - smax = 128 + alpha->white_sensitivity; - - memcpy (matrix, - alpha->in_sdtv ? cog_ycbcr_to_rgb_matrix_8bit_sdtv : - cog_ycbcr_to_rgb_matrix_8bit_hdtv, 12 * sizeof (gint)); - - for (i = 0; i < height; i++) { - for (j = 0; j < width; j++) { - a = (src[0] * pa) >> 8; - y = src[1]; - u = src[2] - 128; - v = src[3] - 128; - - a = chroma_keying_yuv (a, &y, &u, &v, cr, cb, - smin, smax, accept_angle_tg, accept_angle_ctg, - one_over_kc, kfgy_scale, kg, noise_level2); - - u += 128; - v += 128; - - r = APPLY_MATRIX (matrix, 0, y, u, v); - g = APPLY_MATRIX (matrix, 1, y, u, v); - b = APPLY_MATRIX (matrix, 2, y, u, v); - - dest[p[0]] = a; - dest[p[1]] = CLAMP (r, 0, 255); - dest[p[2]] = CLAMP (g, 0, 255); - dest[p[3]] = CLAMP (b, 0, 255); - - src += 4; - dest += 4; - } - } -} - -static void -gst_alpha_set_ayuv_ayuv (const guint8 * src, guint8 * dest, gint width, - gint height, GstAlpha * alpha) -{ - gint s_alpha = CLAMP ((gint) (alpha->alpha * 256), 0, 256); - gint y, x; - - if (alpha->in_sdtv == alpha->out_sdtv) { - for (y = 0; y < height; y++) { - for (x = 0; x < width; x++) { - dest[0] = (src[0] * s_alpha) >> 8; - dest[1] = src[1]; - dest[2] = src[2]; - dest[3] = src[3]; - - dest += 4; - src += 4; - } - } - } else { - gint matrix[12]; - - memcpy (matrix, - alpha->out_sdtv ? cog_ycbcr_hdtv_to_ycbcr_sdtv_matrix_8bit : - cog_ycbcr_sdtv_to_ycbcr_hdtv_matrix_8bit, 12 * sizeof (gint)); - - for (y = 0; y < height; y++) { - for (x = 0; x < width; x++) { - dest[0] = (src[0] * s_alpha) >> 8; - dest[1] = APPLY_MATRIX (matrix, 0, src[1], src[2], src[3]); - dest[2] = APPLY_MATRIX (matrix, 1, src[1], src[2], src[3]); - dest[3] = APPLY_MATRIX (matrix, 2, src[1], src[2], src[3]); - - dest += 4; - src += 4; - } - } - } -} - -static void -gst_alpha_chroma_key_ayuv_ayuv (const guint8 * src, guint8 * dest, - gint width, gint height, GstAlpha * alpha) -{ - gint i, j; - gint a, y, u, v; - gint smin, smax; - gint pa = CLAMP ((gint) (alpha->alpha * 256), 0, 256); - gint8 cb = alpha->cb, cr = alpha->cr; - gint8 kg = alpha->kg; - guint8 accept_angle_tg = alpha->accept_angle_tg; - guint8 accept_angle_ctg = alpha->accept_angle_ctg; - guint8 one_over_kc = alpha->one_over_kc; - guint8 kfgy_scale = alpha->kfgy_scale; - guint noise_level2 = alpha->noise_level2; - - smin = 128 - alpha->black_sensitivity; - smax = 128 + alpha->white_sensitivity; - - if (alpha->in_sdtv == alpha->out_sdtv) { - for (i = 0; i < height; i++) { - for (j = 0; j < width; j++) { - a = (src[0] * pa) >> 8; - y = src[1]; - u = src[2] - 128; - v = src[3] - 128; - - a = chroma_keying_yuv (a, &y, &u, &v, cr, cb, - smin, smax, accept_angle_tg, accept_angle_ctg, - one_over_kc, kfgy_scale, kg, noise_level2); - - u += 128; - v += 128; - - dest[0] = a; - dest[1] = y; - dest[2] = u; - dest[3] = v; - - src += 4; - dest += 4; - } - } - } else { - gint matrix[12]; - - memcpy (matrix, - alpha->out_sdtv ? cog_ycbcr_hdtv_to_ycbcr_sdtv_matrix_8bit : - cog_ycbcr_sdtv_to_ycbcr_hdtv_matrix_8bit, 12 * sizeof (gint)); - - for (i = 0; i < height; i++) { - for (j = 0; j < width; j++) { - a = (src[0] * pa) >> 8; - y = APPLY_MATRIX (matrix, 0, src[1], src[2], src[3]); - u = APPLY_MATRIX (matrix, 1, src[1], src[2], src[3]) - 128; - v = APPLY_MATRIX (matrix, 2, src[1], src[2], src[3]) - 128; - - a = chroma_keying_yuv (a, &y, &u, &v, cr, cb, - smin, smax, accept_angle_tg, accept_angle_ctg, - one_over_kc, kfgy_scale, kg, noise_level2); - - u += 128; - v += 128; - - dest[0] = a; - dest[1] = y; - dest[2] = u; - dest[3] = v; - - src += 4; - dest += 4; - } - } - } -} - -static void -gst_alpha_set_rgb_ayuv (const guint8 * src, guint8 * dest, gint width, - gint height, GstAlpha * alpha) -{ - gint s_alpha = CLAMP ((gint) (alpha->alpha * 255), 0, 255); - gint i, j; - gint matrix[12]; - gint y, u, v; - gint o[3]; - gint bpp; - - bpp = gst_video_format_get_pixel_stride (alpha->in_format, 0); - - o[0] = - gst_video_format_get_component_offset (alpha->in_format, 0, width, - height); - o[1] = - gst_video_format_get_component_offset (alpha->in_format, 1, width, - height); - o[2] = - gst_video_format_get_component_offset (alpha->in_format, 2, width, - height); - - memcpy (matrix, - alpha->out_sdtv ? cog_rgb_to_ycbcr_matrix_8bit_sdtv : - cog_rgb_to_ycbcr_matrix_8bit_hdtv, 12 * sizeof (gint)); - - for (i = 0; i < height; i++) { - for (j = 0; j < width; j++) { - dest[0] = s_alpha; - - y = APPLY_MATRIX (matrix, 0, src[o[0]], src[o[1]], src[o[2]]); - u = APPLY_MATRIX (matrix, 1, src[o[0]], src[o[1]], src[o[2]]); - v = APPLY_MATRIX (matrix, 2, src[o[0]], src[o[1]], src[o[2]]); - - dest[1] = y; - dest[2] = u; - dest[3] = v; - - dest += 4; - src += bpp; - } - } -} - -static void -gst_alpha_chroma_key_rgb_ayuv (const guint8 * src, guint8 * dest, gint width, - gint height, GstAlpha * alpha) -{ - gint i, j; - gint a, y, u, v; - gint r, g, b; - gint smin, smax; - gint pa = CLAMP ((gint) (alpha->alpha * 255), 0, 255); - gint8 cb = alpha->cb, cr = alpha->cr; - gint8 kg = alpha->kg; - guint8 accept_angle_tg = alpha->accept_angle_tg; - guint8 accept_angle_ctg = alpha->accept_angle_ctg; - guint8 one_over_kc = alpha->one_over_kc; - guint8 kfgy_scale = alpha->kfgy_scale; - guint noise_level2 = alpha->noise_level2; - gint matrix[12]; - gint o[3]; - gint bpp; - - bpp = gst_video_format_get_pixel_stride (alpha->in_format, 0); - - o[0] = - gst_video_format_get_component_offset (alpha->in_format, 0, width, - height); - o[1] = - gst_video_format_get_component_offset (alpha->in_format, 1, width, - height); - o[2] = - gst_video_format_get_component_offset (alpha->in_format, 2, width, - height); - - smin = 128 - alpha->black_sensitivity; - smax = 128 + alpha->white_sensitivity; - - memcpy (matrix, - alpha->out_sdtv ? cog_rgb_to_ycbcr_matrix_8bit_sdtv : - cog_rgb_to_ycbcr_matrix_8bit_hdtv, 12 * sizeof (gint)); - - for (i = 0; i < height; i++) { - for (j = 0; j < width; j++) { - a = pa; - r = src[o[0]]; - g = src[o[1]]; - b = src[o[2]]; - - y = APPLY_MATRIX (matrix, 0, r, g, b); - u = APPLY_MATRIX (matrix, 1, r, g, b) - 128; - v = APPLY_MATRIX (matrix, 2, r, g, b) - 128; - - a = chroma_keying_yuv (a, &y, &u, &v, cr, cb, - smin, smax, accept_angle_tg, accept_angle_ctg, - one_over_kc, kfgy_scale, kg, noise_level2); - - u += 128; - v += 128; - - dest[0] = a; - dest[1] = y; - dest[2] = u; - dest[3] = v; - - src += bpp; - dest += 4; - } - } -} - -static void -gst_alpha_set_rgb_argb (const guint8 * src, guint8 * dest, gint width, - gint height, GstAlpha * alpha) -{ - gint s_alpha = CLAMP ((gint) (alpha->alpha * 255), 0, 255); - gint i, j; - gint p[4], o[3]; - gint bpp; - - bpp = gst_video_format_get_pixel_stride (alpha->in_format, 0); - - o[0] = - gst_video_format_get_component_offset (alpha->in_format, 0, width, - height); - o[1] = - gst_video_format_get_component_offset (alpha->in_format, 1, width, - height); - o[2] = - gst_video_format_get_component_offset (alpha->in_format, 2, width, - height); - - p[0] = - gst_video_format_get_component_offset (alpha->out_format, 3, width, - height); - p[1] = - gst_video_format_get_component_offset (alpha->out_format, 0, width, - height); - p[2] = - gst_video_format_get_component_offset (alpha->out_format, 1, width, - height); - p[3] = - gst_video_format_get_component_offset (alpha->out_format, 2, width, - height); - - for (i = 0; i < height; i++) { - for (j = 0; j < width; j++) { - dest[p[0]] = s_alpha; - - dest[p[1]] = src[o[0]]; - dest[p[2]] = src[o[1]]; - dest[p[3]] = src[o[2]]; - - dest += 4; - src += bpp; - } - } -} - -static void -gst_alpha_chroma_key_rgb_argb (const guint8 * src, guint8 * dest, gint width, - gint height, GstAlpha * alpha) -{ - gint i, j; - gint a, y, u, v; - gint r, g, b; - gint smin, smax; - gint pa = CLAMP ((gint) (alpha->alpha * 255), 0, 255); - gint8 cb = alpha->cb, cr = alpha->cr; - gint8 kg = alpha->kg; - guint8 accept_angle_tg = alpha->accept_angle_tg; - guint8 accept_angle_ctg = alpha->accept_angle_ctg; - guint8 one_over_kc = alpha->one_over_kc; - guint8 kfgy_scale = alpha->kfgy_scale; - guint noise_level2 = alpha->noise_level2; - gint matrix[12], matrix2[12]; - gint p[4], o[3]; - gint bpp; - - bpp = gst_video_format_get_pixel_stride (alpha->in_format, 0); - - o[0] = - gst_video_format_get_component_offset (alpha->in_format, 0, width, - height); - o[1] = - gst_video_format_get_component_offset (alpha->in_format, 1, width, - height); - o[2] = - gst_video_format_get_component_offset (alpha->in_format, 2, width, - height); - - p[0] = - gst_video_format_get_component_offset (alpha->out_format, 3, width, - height); - p[1] = - gst_video_format_get_component_offset (alpha->out_format, 0, width, - height); - p[2] = - gst_video_format_get_component_offset (alpha->out_format, 1, width, - height); - p[3] = - gst_video_format_get_component_offset (alpha->out_format, 2, width, - height); - - smin = 128 - alpha->black_sensitivity; - smax = 128 + alpha->white_sensitivity; - - memcpy (matrix, cog_rgb_to_ycbcr_matrix_8bit_sdtv, 12 * sizeof (gint)); - memcpy (matrix2, cog_ycbcr_to_rgb_matrix_8bit_sdtv, 12 * sizeof (gint)); - - for (i = 0; i < height; i++) { - for (j = 0; j < width; j++) { - a = pa; - r = src[o[0]]; - g = src[o[1]]; - b = src[o[2]]; - - y = APPLY_MATRIX (matrix, 0, r, g, b); - u = APPLY_MATRIX (matrix, 1, r, g, b) - 128; - v = APPLY_MATRIX (matrix, 2, r, g, b) - 128; - - a = chroma_keying_yuv (a, &y, &u, &v, cr, cb, - smin, smax, accept_angle_tg, accept_angle_ctg, - one_over_kc, kfgy_scale, kg, noise_level2); - - u += 128; - v += 128; - - r = APPLY_MATRIX (matrix2, 0, y, u, v); - g = APPLY_MATRIX (matrix2, 1, y, u, v); - b = APPLY_MATRIX (matrix2, 2, y, u, v); - - dest[p[0]] = a; - dest[p[1]] = CLAMP (r, 0, 255); - dest[p[2]] = CLAMP (g, 0, 255); - dest[p[3]] = CLAMP (b, 0, 255); - - src += bpp; - dest += 4; - } - } -} - -static void -gst_alpha_set_planar_yuv_ayuv (const guint8 * src, guint8 * dest, gint width, - gint height, GstAlpha * alpha) -{ - gint b_alpha = CLAMP ((gint) (alpha->alpha * 255), 0, 255); - const guint8 *srcY, *srcY_tmp; - const guint8 *srcU, *srcU_tmp; - const guint8 *srcV, *srcV_tmp; - gint i, j; - gint y_stride, uv_stride; - gint v_subs, h_subs; - - y_stride = gst_video_format_get_row_stride (alpha->in_format, 0, width); - uv_stride = gst_video_format_get_row_stride (alpha->in_format, 1, width); - - srcY_tmp = srcY = src; - srcU_tmp = srcU = - src + gst_video_format_get_component_offset (alpha->in_format, 1, width, - height); - srcV_tmp = srcV = - src + gst_video_format_get_component_offset (alpha->in_format, 2, width, - height); - - switch (alpha->in_format) { - case GST_VIDEO_FORMAT_I420: - case GST_VIDEO_FORMAT_YV12: - v_subs = h_subs = 2; - break; - case GST_VIDEO_FORMAT_Y444: - v_subs = h_subs = 1; - break; - case GST_VIDEO_FORMAT_Y42B: - v_subs = 1; - h_subs = 2; - break; - case GST_VIDEO_FORMAT_Y41B: - v_subs = 1; - h_subs = 4; - break; - default: - g_assert_not_reached (); - return; - } - - if (alpha->in_sdtv == alpha->out_sdtv) { - for (i = 0; i < height; i++) { - for (j = 0; j < width; j++) { - dest[0] = b_alpha; - dest[1] = srcY[0]; - dest[2] = srcU[0]; - dest[3] = srcV[0]; - - dest += 4; - srcY++; - if ((j + 1) % h_subs == 0) { - srcU++; - srcV++; - } - } - - srcY_tmp = srcY = srcY_tmp + y_stride; - if ((i + 1) % v_subs == 0) { - srcU_tmp = srcU = srcU_tmp + uv_stride; - srcV_tmp = srcV = srcV_tmp + uv_stride; - } else { - srcU = srcU_tmp; - srcV = srcV_tmp; - } - } - } else { - gint matrix[12]; - gint a, y, u, v; - - memcpy (matrix, - alpha->out_sdtv ? cog_ycbcr_hdtv_to_ycbcr_sdtv_matrix_8bit : - cog_ycbcr_sdtv_to_ycbcr_hdtv_matrix_8bit, 12 * sizeof (gint)); - - for (i = 0; i < height; i++) { - for (j = 0; j < width; j++) { - a = b_alpha; - y = srcY[0]; - u = srcU[0]; - v = srcV[0]; - - dest[0] = a; - dest[1] = APPLY_MATRIX (matrix, 0, y, u, v); - dest[2] = APPLY_MATRIX (matrix, 1, y, u, v); - dest[3] = APPLY_MATRIX (matrix, 2, y, u, v); - - dest += 4; - srcY++; - if ((j + 1) % h_subs == 0) { - srcU++; - srcV++; - } - } - - srcY_tmp = srcY = srcY_tmp + y_stride; - if ((i + 1) % v_subs == 0) { - srcU_tmp = srcU = srcU_tmp + uv_stride; - srcV_tmp = srcV = srcV_tmp + uv_stride; - } else { - srcU = srcU_tmp; - srcV = srcV_tmp; - } - } - } -} - -static void -gst_alpha_chroma_key_planar_yuv_ayuv (const guint8 * src, guint8 * dest, - gint width, gint height, GstAlpha * alpha) -{ - gint b_alpha = CLAMP ((gint) (alpha->alpha * 255), 0, 255); - const guint8 *srcY, *srcY_tmp; - const guint8 *srcU, *srcU_tmp; - const guint8 *srcV, *srcV_tmp; - gint i, j; - gint a, y, u, v; - gint y_stride, uv_stride; - gint v_subs, h_subs; - gint smin = 128 - alpha->black_sensitivity; - gint smax = 128 + alpha->white_sensitivity; - gint8 cb = alpha->cb, cr = alpha->cr; - gint8 kg = alpha->kg; - guint8 accept_angle_tg = alpha->accept_angle_tg; - guint8 accept_angle_ctg = alpha->accept_angle_ctg; - guint8 one_over_kc = alpha->one_over_kc; - guint8 kfgy_scale = alpha->kfgy_scale; - guint noise_level2 = alpha->noise_level2; - - y_stride = gst_video_format_get_row_stride (alpha->in_format, 0, width); - uv_stride = gst_video_format_get_row_stride (alpha->in_format, 1, width); - - srcY_tmp = srcY = src; - srcU_tmp = srcU = - src + gst_video_format_get_component_offset (alpha->in_format, 1, width, - height); - srcV_tmp = srcV = - src + gst_video_format_get_component_offset (alpha->in_format, 2, width, - height); - - switch (alpha->in_format) { - case GST_VIDEO_FORMAT_I420: - case GST_VIDEO_FORMAT_YV12: - v_subs = h_subs = 2; - break; - case GST_VIDEO_FORMAT_Y444: - v_subs = h_subs = 1; - break; - case GST_VIDEO_FORMAT_Y42B: - v_subs = 1; - h_subs = 2; - break; - case GST_VIDEO_FORMAT_Y41B: - v_subs = 1; - h_subs = 4; - break; - default: - g_assert_not_reached (); - return; - } - - if (alpha->in_sdtv == alpha->out_sdtv) { - for (i = 0; i < height; i++) { - for (j = 0; j < width; j++) { - a = b_alpha; - y = srcY[0]; - u = srcU[0] - 128; - v = srcV[0] - 128; - - a = chroma_keying_yuv (a, &y, &u, &v, cr, cb, smin, - smax, accept_angle_tg, accept_angle_ctg, - one_over_kc, kfgy_scale, kg, noise_level2); - - u += 128; - v += 128; - - dest[0] = a; - dest[1] = y; - dest[2] = u; - dest[3] = v; - - dest += 4; - srcY++; - if ((j + 1) % h_subs == 0) { - srcU++; - srcV++; - } - } - - srcY_tmp = srcY = srcY_tmp + y_stride; - if ((i + 1) % v_subs == 0) { - srcU_tmp = srcU = srcU_tmp + uv_stride; - srcV_tmp = srcV = srcV_tmp + uv_stride; - } else { - srcU = srcU_tmp; - srcV = srcV_tmp; - } - } - } else { - gint matrix[12]; - - memcpy (matrix, - alpha->out_sdtv ? cog_ycbcr_hdtv_to_ycbcr_sdtv_matrix_8bit : - cog_ycbcr_sdtv_to_ycbcr_hdtv_matrix_8bit, 12 * sizeof (gint)); - - for (i = 0; i < height; i++) { - for (j = 0; j < width; j++) { - a = b_alpha; - y = APPLY_MATRIX (matrix, 0, srcY[0], srcU[0], srcV[0]); - u = APPLY_MATRIX (matrix, 1, srcY[0], srcU[0], srcV[0]) - 128; - v = APPLY_MATRIX (matrix, 2, srcY[0], srcU[0], srcV[0]) - 128; - - a = chroma_keying_yuv (a, &y, &u, &v, cr, cb, smin, - smax, accept_angle_tg, accept_angle_ctg, - one_over_kc, kfgy_scale, kg, noise_level2); - - dest[0] = a; - dest[1] = y; - dest[2] = u + 128; - dest[3] = v + 128; - - dest += 4; - srcY++; - if ((j + 1) % h_subs == 0) { - srcU++; - srcV++; - } - } - - srcY_tmp = srcY = srcY_tmp + y_stride; - if ((i + 1) % v_subs == 0) { - srcU_tmp = srcU = srcU_tmp + uv_stride; - srcV_tmp = srcV = srcV_tmp + uv_stride; - } else { - srcU = srcU_tmp; - srcV = srcV_tmp; - } - } - } -} - -static void -gst_alpha_set_planar_yuv_argb (const guint8 * src, guint8 * dest, gint width, - gint height, GstAlpha * alpha) -{ - gint b_alpha = CLAMP ((gint) (alpha->alpha * 255), 0, 255); - const guint8 *srcY, *srcY_tmp; - const guint8 *srcU, *srcU_tmp; - const guint8 *srcV, *srcV_tmp; - gint i, j; - gint y_stride, uv_stride; - gint v_subs, h_subs; - gint matrix[12]; - gint a, y, u, v; - gint r, g, b; - gint p[4]; - - p[0] = - gst_video_format_get_component_offset (alpha->out_format, 3, width, - height); - p[1] = - gst_video_format_get_component_offset (alpha->out_format, 0, width, - height); - p[2] = - gst_video_format_get_component_offset (alpha->out_format, 1, width, - height); - p[3] = - gst_video_format_get_component_offset (alpha->out_format, 2, width, - height); - - y_stride = gst_video_format_get_row_stride (alpha->in_format, 0, width); - uv_stride = gst_video_format_get_row_stride (alpha->in_format, 1, width); - - srcY_tmp = srcY = src; - srcU_tmp = srcU = - src + gst_video_format_get_component_offset (alpha->in_format, 1, width, - height); - srcV_tmp = srcV = - src + gst_video_format_get_component_offset (alpha->in_format, 2, width, - height); - - switch (alpha->in_format) { - case GST_VIDEO_FORMAT_I420: - case GST_VIDEO_FORMAT_YV12: - v_subs = h_subs = 2; - break; - case GST_VIDEO_FORMAT_Y444: - v_subs = h_subs = 1; - break; - case GST_VIDEO_FORMAT_Y42B: - v_subs = 1; - h_subs = 2; - break; - case GST_VIDEO_FORMAT_Y41B: - v_subs = 1; - h_subs = 4; - break; - default: - g_assert_not_reached (); - return; - } - - memcpy (matrix, - alpha->in_sdtv ? cog_ycbcr_to_rgb_matrix_8bit_sdtv : - cog_ycbcr_to_rgb_matrix_8bit_hdtv, 12 * sizeof (gint)); - - for (i = 0; i < height; i++) { - for (j = 0; j < width; j++) { - a = b_alpha; - y = srcY[0]; - u = srcU[0]; - v = srcV[0]; - - dest[p[0]] = a; - r = APPLY_MATRIX (matrix, 0, y, u, v); - g = APPLY_MATRIX (matrix, 1, y, u, v); - b = APPLY_MATRIX (matrix, 2, y, u, v); - dest[p[1]] = CLAMP (r, 0, 255); - dest[p[2]] = CLAMP (g, 0, 255); - dest[p[3]] = CLAMP (b, 0, 255); - - dest += 4; - srcY++; - if ((j + 1) % h_subs == 0) { - srcU++; - srcV++; - } - } - - srcY_tmp = srcY = srcY_tmp + y_stride; - if ((i + 1) % v_subs == 0) { - srcU_tmp = srcU = srcU_tmp + uv_stride; - srcV_tmp = srcV = srcV_tmp + uv_stride; - } else { - srcU = srcU_tmp; - srcV = srcV_tmp; - } - } -} - -static void -gst_alpha_chroma_key_planar_yuv_argb (const guint8 * src, guint8 * dest, - gint width, gint height, GstAlpha * alpha) -{ - gint b_alpha = CLAMP ((gint) (alpha->alpha * 255), 0, 255); - const guint8 *srcY, *srcY_tmp; - const guint8 *srcU, *srcU_tmp; - const guint8 *srcV, *srcV_tmp; - gint i, j; - gint a, y, u, v; - gint r, g, b; - gint y_stride, uv_stride; - gint v_subs, h_subs; - gint smin = 128 - alpha->black_sensitivity; - gint smax = 128 + alpha->white_sensitivity; - gint8 cb = alpha->cb, cr = alpha->cr; - gint8 kg = alpha->kg; - guint8 accept_angle_tg = alpha->accept_angle_tg; - guint8 accept_angle_ctg = alpha->accept_angle_ctg; - guint8 one_over_kc = alpha->one_over_kc; - guint8 kfgy_scale = alpha->kfgy_scale; - guint noise_level2 = alpha->noise_level2; - gint matrix[12]; - gint p[4]; - - p[0] = - gst_video_format_get_component_offset (alpha->out_format, 3, width, - height); - p[1] = - gst_video_format_get_component_offset (alpha->out_format, 0, width, - height); - p[2] = - gst_video_format_get_component_offset (alpha->out_format, 1, width, - height); - p[3] = - gst_video_format_get_component_offset (alpha->out_format, 2, width, - height); - - y_stride = gst_video_format_get_row_stride (alpha->in_format, 0, width); - uv_stride = gst_video_format_get_row_stride (alpha->in_format, 1, width); - - srcY_tmp = srcY = src; - srcU_tmp = srcU = - src + gst_video_format_get_component_offset (alpha->in_format, 1, width, - height); - srcV_tmp = srcV = - src + gst_video_format_get_component_offset (alpha->in_format, 2, width, - height); - - switch (alpha->in_format) { - case GST_VIDEO_FORMAT_I420: - case GST_VIDEO_FORMAT_YV12: - v_subs = h_subs = 2; - break; - case GST_VIDEO_FORMAT_Y444: - v_subs = h_subs = 1; - break; - case GST_VIDEO_FORMAT_Y42B: - v_subs = 1; - h_subs = 2; - break; - case GST_VIDEO_FORMAT_Y41B: - v_subs = 1; - h_subs = 4; - break; - default: - g_assert_not_reached (); - return; - } - - memcpy (matrix, - alpha->in_sdtv ? cog_ycbcr_to_rgb_matrix_8bit_sdtv : - cog_ycbcr_to_rgb_matrix_8bit_hdtv, 12 * sizeof (gint)); - - for (i = 0; i < height; i++) { - for (j = 0; j < width; j++) { - a = b_alpha; - y = srcY[0]; - u = srcU[0] - 128; - v = srcV[0] - 128; - - a = chroma_keying_yuv (a, &y, &u, &v, cr, cb, smin, - smax, accept_angle_tg, accept_angle_ctg, - one_over_kc, kfgy_scale, kg, noise_level2); - - u += 128; - v += 128; - - dest[p[0]] = a; - r = APPLY_MATRIX (matrix, 0, y, u, v); - g = APPLY_MATRIX (matrix, 1, y, u, v); - b = APPLY_MATRIX (matrix, 2, y, u, v); - dest[p[1]] = CLAMP (r, 0, 255); - dest[p[2]] = CLAMP (g, 0, 255); - dest[p[3]] = CLAMP (b, 0, 255); - - dest += 4; - srcY++; - if ((j + 1) % h_subs == 0) { - srcU++; - srcV++; - } - } - - srcY_tmp = srcY = srcY_tmp + y_stride; - if ((i + 1) % v_subs == 0) { - srcU_tmp = srcU = srcU_tmp + uv_stride; - srcV_tmp = srcV = srcV_tmp + uv_stride; - } else { - srcU = srcU_tmp; - srcV = srcV_tmp; - } - } -} - -static void -gst_alpha_set_packed_422_ayuv (const guint8 * src, guint8 * dest, gint width, - gint height, GstAlpha * alpha) -{ - gint s_alpha = CLAMP ((gint) (alpha->alpha * 255), 0, 255); - gint i, j; - gint y, u, v; - gint p[4]; /* Y U Y V */ - gint src_stride; - const guint8 *src_tmp; - - src_stride = gst_video_format_get_row_stride (alpha->in_format, 0, width); - - p[0] = - gst_video_format_get_component_offset (alpha->in_format, 0, width, - height); - p[2] = p[0] + 2; - p[1] = - gst_video_format_get_component_offset (alpha->in_format, 1, width, - height); - p[3] = - gst_video_format_get_component_offset (alpha->in_format, 2, width, - height); - - if (alpha->in_sdtv != alpha->out_sdtv) { - gint matrix[12]; - - memcpy (matrix, - alpha->in_sdtv ? cog_ycbcr_sdtv_to_ycbcr_hdtv_matrix_8bit : - cog_ycbcr_hdtv_to_ycbcr_sdtv_matrix_8bit, 12 * sizeof (gint)); - - for (i = 0; i < height; i++) { - src_tmp = src; - - for (j = 0; j < width - 1; j += 2) { - dest[0] = s_alpha; - dest[4] = s_alpha; - - y = APPLY_MATRIX (matrix, 0, src[p[0]], src[p[1]], src[p[3]]); - u = APPLY_MATRIX (matrix, 1, src[p[0]], src[p[1]], src[p[3]]); - v = APPLY_MATRIX (matrix, 2, src[p[0]], src[p[1]], src[p[3]]); - - dest[1] = y; - dest[2] = u; - dest[3] = v; - - y = APPLY_MATRIX (matrix, 0, src[p[2]], src[p[1]], src[p[3]]); - u = APPLY_MATRIX (matrix, 1, src[p[2]], src[p[1]], src[p[3]]); - v = APPLY_MATRIX (matrix, 2, src[p[2]], src[p[1]], src[p[3]]); - - dest[5] = y; - dest[6] = u; - dest[7] = v; - - dest += 8; - src += 4; - } - - if (j == width - 1) { - dest[0] = s_alpha; - - y = APPLY_MATRIX (matrix, 0, src[p[0]], src[p[1]], src[p[3]]); - u = APPLY_MATRIX (matrix, 1, src[p[0]], src[p[1]], src[p[3]]); - v = APPLY_MATRIX (matrix, 2, src[p[0]], src[p[1]], src[p[3]]); - - dest[1] = y; - dest[2] = u; - dest[3] = v; - - dest += 4; - } - - src = src_tmp + src_stride; - } - } else { - for (i = 0; i < height; i++) { - src_tmp = src; - - for (j = 0; j < width - 1; j += 2) { - dest[0] = s_alpha; - dest[4] = s_alpha; - - y = src[p[0]]; - u = src[p[1]]; - v = src[p[3]];; - - dest[1] = y; - dest[2] = u; - dest[3] = v; - - y = src[p[2]]; - - dest[5] = y; - dest[6] = u; - dest[7] = v; - - dest += 8; - src += 4; - } - - if (j == width - 1) { - dest[0] = s_alpha; - - y = src[p[0]]; - u = src[p[1]]; - v = src[p[3]];; - - dest[1] = y; - dest[2] = u; - dest[3] = v; - - dest += 4; - } - - src = src_tmp + src_stride; - } - } -} - -static void -gst_alpha_chroma_key_packed_422_ayuv (const guint8 * src, guint8 * dest, - gint width, gint height, GstAlpha * alpha) -{ - gint i, j; - gint a, y, u, v; - gint smin, smax; - gint pa = CLAMP ((gint) (alpha->alpha * 255), 0, 255); - gint8 cb = alpha->cb, cr = alpha->cr; - gint8 kg = alpha->kg; - guint8 accept_angle_tg = alpha->accept_angle_tg; - guint8 accept_angle_ctg = alpha->accept_angle_ctg; - guint8 one_over_kc = alpha->one_over_kc; - guint8 kfgy_scale = alpha->kfgy_scale; - guint noise_level2 = alpha->noise_level2; - gint p[4]; /* Y U Y V */ - gint src_stride; - const guint8 *src_tmp; - - src_stride = gst_video_format_get_row_stride (alpha->in_format, 0, width); - - p[0] = - gst_video_format_get_component_offset (alpha->in_format, 0, width, - height); - p[2] = p[0] + 2; - p[1] = - gst_video_format_get_component_offset (alpha->in_format, 1, width, - height); - p[3] = - gst_video_format_get_component_offset (alpha->in_format, 2, width, - height); - - smin = 128 - alpha->black_sensitivity; - smax = 128 + alpha->white_sensitivity; - - if (alpha->in_sdtv != alpha->out_sdtv) { - gint matrix[12]; - - memcpy (matrix, - alpha->in_sdtv ? cog_ycbcr_sdtv_to_ycbcr_hdtv_matrix_8bit : - cog_ycbcr_hdtv_to_ycbcr_sdtv_matrix_8bit, 12 * sizeof (gint)); - - for (i = 0; i < height; i++) { - src_tmp = src; - - for (j = 0; j < width - 1; j += 2) { - y = APPLY_MATRIX (matrix, 0, src[p[0]], src[p[1]], src[p[3]]); - u = APPLY_MATRIX (matrix, 1, src[p[0]], src[p[1]], src[p[3]]) - 128; - v = APPLY_MATRIX (matrix, 2, src[p[0]], src[p[1]], src[p[3]]) - 128; - - a = chroma_keying_yuv (pa, &y, &u, &v, cr, cb, - smin, smax, accept_angle_tg, accept_angle_ctg, - one_over_kc, kfgy_scale, kg, noise_level2); - - dest[0] = a; - dest[1] = y; - dest[2] = u + 128; - dest[3] = v + 128; - - y = APPLY_MATRIX (matrix, 0, src[p[2]], src[p[1]], src[p[3]]); - u = APPLY_MATRIX (matrix, 1, src[p[2]], src[p[1]], src[p[3]]) - 128; - v = APPLY_MATRIX (matrix, 2, src[p[2]], src[p[1]], src[p[3]]) - 128; - - a = chroma_keying_yuv (pa, &y, &u, &v, cr, cb, - smin, smax, accept_angle_tg, accept_angle_ctg, - one_over_kc, kfgy_scale, kg, noise_level2); - - dest[4] = a; - dest[5] = y; - dest[6] = u + 128; - dest[7] = v + 128; - - dest += 8; - src += 4; - } - - if (j == width - 1) { - y = APPLY_MATRIX (matrix, 0, src[p[0]], src[p[1]], src[p[3]]); - u = APPLY_MATRIX (matrix, 1, src[p[0]], src[p[1]], src[p[3]]) - 128; - v = APPLY_MATRIX (matrix, 2, src[p[0]], src[p[1]], src[p[3]]) - 128; - - a = chroma_keying_yuv (pa, &y, &u, &v, cr, cb, - smin, smax, accept_angle_tg, accept_angle_ctg, - one_over_kc, kfgy_scale, kg, noise_level2); - - dest[0] = a; - dest[1] = y; - dest[2] = u + 128; - dest[3] = v + 128; - - dest += 4; - } - - src = src_tmp + src_stride; - } - } else { - for (i = 0; i < height; i++) { - src_tmp = src; - - for (j = 0; j < width - 1; j += 2) { - y = src[p[0]]; - u = src[p[1]] - 128; - v = src[p[3]] - 128; - - a = chroma_keying_yuv (pa, &y, &u, &v, cr, cb, - smin, smax, accept_angle_tg, accept_angle_ctg, - one_over_kc, kfgy_scale, kg, noise_level2); - - dest[0] = a; - dest[1] = y; - dest[2] = u + 128; - dest[3] = v + 128; - - y = src[p[2]]; - u = src[p[1]] - 128; - v = src[p[3]] - 128; - - a = chroma_keying_yuv (pa, &y, &u, &v, cr, cb, - smin, smax, accept_angle_tg, accept_angle_ctg, - one_over_kc, kfgy_scale, kg, noise_level2); - - dest[4] = a; - dest[5] = y; - dest[6] = u + 128; - dest[7] = v + 128; - - dest += 8; - src += 4; - } - - if (j == width - 1) { - y = src[p[0]]; - u = src[p[1]] - 128; - v = src[p[3]] - 128; - - a = chroma_keying_yuv (pa, &y, &u, &v, cr, cb, - smin, smax, accept_angle_tg, accept_angle_ctg, - one_over_kc, kfgy_scale, kg, noise_level2); - - dest[0] = a; - dest[1] = y; - dest[2] = u + 128; - dest[3] = v + 128; - - dest += 4; - } - - src = src_tmp + src_stride; - } - } -} - -static void -gst_alpha_set_packed_422_argb (const guint8 * src, guint8 * dest, gint width, - gint height, GstAlpha * alpha) -{ - gint s_alpha = CLAMP ((gint) (alpha->alpha * 255), 0, 255); - gint i, j; - gint p[4], o[4]; - gint src_stride; - const guint8 *src_tmp; - gint matrix[12]; - gint r, g, b; - - src_stride = gst_video_format_get_row_stride (alpha->in_format, 0, width); - - o[0] = - gst_video_format_get_component_offset (alpha->in_format, 0, width, - height); - o[2] = o[0] + 2; - o[1] = - gst_video_format_get_component_offset (alpha->in_format, 1, width, - height); - o[3] = - gst_video_format_get_component_offset (alpha->in_format, 2, width, - height); - - p[0] = - gst_video_format_get_component_offset (alpha->out_format, 3, width, - height); - p[1] = - gst_video_format_get_component_offset (alpha->out_format, 0, width, - height); - p[2] = - gst_video_format_get_component_offset (alpha->out_format, 1, width, - height); - p[3] = - gst_video_format_get_component_offset (alpha->out_format, 2, width, - height); - - memcpy (matrix, - alpha->in_sdtv ? cog_ycbcr_to_rgb_matrix_8bit_sdtv : - cog_ycbcr_to_rgb_matrix_8bit_hdtv, 12 * sizeof (gint)); - - for (i = 0; i < height; i++) { - src_tmp = src; - - for (j = 0; j < width - 1; j += 2) { - r = APPLY_MATRIX (matrix, 0, src[o[0]], src[o[1]], src[o[3]]); - g = APPLY_MATRIX (matrix, 1, src[o[0]], src[o[1]], src[o[3]]); - b = APPLY_MATRIX (matrix, 2, src[o[0]], src[o[1]], src[o[3]]); - - dest[p[0]] = s_alpha; - dest[p[1]] = CLAMP (r, 0, 255); - dest[p[2]] = CLAMP (g, 0, 255); - dest[p[3]] = CLAMP (b, 0, 255); - - r = APPLY_MATRIX (matrix, 0, src[o[2]], src[o[1]], src[o[3]]); - g = APPLY_MATRIX (matrix, 1, src[o[2]], src[o[1]], src[o[3]]); - b = APPLY_MATRIX (matrix, 2, src[o[2]], src[o[1]], src[o[3]]); - - dest[4 + p[0]] = s_alpha; - dest[4 + p[1]] = CLAMP (r, 0, 255); - dest[4 + p[2]] = CLAMP (g, 0, 255); - dest[4 + p[3]] = CLAMP (b, 0, 255); - - dest += 8; - src += 4; - } - - if (j == width - 1) { - r = APPLY_MATRIX (matrix, 0, src[o[0]], src[o[1]], src[o[3]]); - g = APPLY_MATRIX (matrix, 1, src[o[0]], src[o[1]], src[o[3]]); - b = APPLY_MATRIX (matrix, 2, src[o[0]], src[o[1]], src[o[3]]); - - dest[p[0]] = s_alpha; - dest[p[1]] = CLAMP (r, 0, 255); - dest[p[2]] = CLAMP (g, 0, 255); - dest[p[3]] = CLAMP (b, 0, 255); - - dest += 4; - } - - src = src_tmp + src_stride; - } -} - -static void -gst_alpha_chroma_key_packed_422_argb (const guint8 * src, guint8 * dest, - gint width, gint height, GstAlpha * alpha) -{ - gint i, j; - gint a, y, u, v; - gint r, g, b; - gint smin, smax; - gint pa = CLAMP ((gint) (alpha->alpha * 255), 0, 255); - gint8 cb = alpha->cb, cr = alpha->cr; - gint8 kg = alpha->kg; - guint8 accept_angle_tg = alpha->accept_angle_tg; - guint8 accept_angle_ctg = alpha->accept_angle_ctg; - guint8 one_over_kc = alpha->one_over_kc; - guint8 kfgy_scale = alpha->kfgy_scale; - guint noise_level2 = alpha->noise_level2; - gint p[4], o[4]; - gint src_stride; - const guint8 *src_tmp; - gint matrix[12]; - - src_stride = gst_video_format_get_row_stride (alpha->in_format, 0, width); - - o[0] = - gst_video_format_get_component_offset (alpha->in_format, 0, width, - height); - o[2] = o[0] + 2; - o[1] = - gst_video_format_get_component_offset (alpha->in_format, 1, width, - height); - o[3] = - gst_video_format_get_component_offset (alpha->in_format, 2, width, - height); - - p[0] = - gst_video_format_get_component_offset (alpha->out_format, 3, width, - height); - p[1] = - gst_video_format_get_component_offset (alpha->out_format, 0, width, - height); - p[2] = - gst_video_format_get_component_offset (alpha->out_format, 1, width, - height); - p[3] = - gst_video_format_get_component_offset (alpha->out_format, 2, width, - height); - - memcpy (matrix, - alpha->in_sdtv ? cog_ycbcr_to_rgb_matrix_8bit_sdtv : - cog_ycbcr_to_rgb_matrix_8bit_hdtv, 12 * sizeof (gint)); - - smin = 128 - alpha->black_sensitivity; - smax = 128 + alpha->white_sensitivity; - - for (i = 0; i < height; i++) { - src_tmp = src; - - for (j = 0; j < width - 1; j += 2) { - y = src[o[0]]; - u = src[o[1]] - 128; - v = src[o[3]] - 128; - - a = chroma_keying_yuv (pa, &y, &u, &v, cr, cb, - smin, smax, accept_angle_tg, accept_angle_ctg, - one_over_kc, kfgy_scale, kg, noise_level2); - u += 128; - v += 128; - - r = APPLY_MATRIX (matrix, 0, y, u, v); - g = APPLY_MATRIX (matrix, 1, y, u, v); - b = APPLY_MATRIX (matrix, 2, y, u, v); - - dest[p[0]] = a; - dest[p[1]] = CLAMP (r, 0, 255); - dest[p[2]] = CLAMP (g, 0, 255); - dest[p[3]] = CLAMP (b, 0, 255); - - y = src[o[2]]; - u = src[o[1]] - 128; - v = src[o[3]] - 128; - - a = chroma_keying_yuv (pa, &y, &u, &v, cr, cb, - smin, smax, accept_angle_tg, accept_angle_ctg, - one_over_kc, kfgy_scale, kg, noise_level2); - u += 128; - v += 128; - - r = APPLY_MATRIX (matrix, 0, y, u, v); - g = APPLY_MATRIX (matrix, 1, y, u, v); - b = APPLY_MATRIX (matrix, 2, y, u, v); - - dest[4 + p[0]] = a; - dest[4 + p[1]] = CLAMP (r, 0, 255); - dest[4 + p[2]] = CLAMP (g, 0, 255); - dest[4 + p[3]] = CLAMP (b, 0, 255); - - dest += 8; - src += 4; - } - - if (j == width - 1) { - y = src[o[0]]; - u = src[o[1]] - 128; - v = src[o[3]] - 128; - - a = chroma_keying_yuv (pa, &y, &u, &v, cr, cb, - smin, smax, accept_angle_tg, accept_angle_ctg, - one_over_kc, kfgy_scale, kg, noise_level2); - u += 128; - v += 128; - - r = APPLY_MATRIX (matrix, 0, y, u, v); - g = APPLY_MATRIX (matrix, 1, y, u, v); - b = APPLY_MATRIX (matrix, 2, y, u, v); - - dest[p[0]] = a; - dest[p[1]] = CLAMP (r, 0, 255); - dest[p[2]] = CLAMP (g, 0, 255); - dest[p[3]] = CLAMP (b, 0, 255); - - dest += 4; - } - - src = src_tmp + src_stride; - } -} - -/* Protected with the alpha lock */ -static void -gst_alpha_init_params (GstAlpha * alpha) -{ - gfloat kgl; - gfloat tmp; - gfloat tmp1, tmp2; - gfloat y; - const gint *matrix; - - /* RGB->RGB: convert to SDTV YUV, chroma keying, convert back - * YUV->RGB: chroma keying, convert to RGB - * RGB->YUV: convert to YUV, chroma keying - * YUV->YUV: convert matrix, chroma keying - */ - if (gst_video_format_is_rgb (alpha->in_format) - && gst_video_format_is_rgb (alpha->out_format)) - matrix = cog_rgb_to_ycbcr_matrix_8bit_sdtv; - else if (gst_video_format_is_yuv (alpha->in_format) - && gst_video_format_is_rgb (alpha->out_format)) - matrix = - (alpha->in_sdtv) ? cog_rgb_to_ycbcr_matrix_8bit_sdtv : - cog_rgb_to_ycbcr_matrix_8bit_hdtv; - else if (gst_video_format_is_rgb (alpha->in_format) - && gst_video_format_is_yuv (alpha->out_format)) - matrix = - (alpha->out_sdtv) ? cog_rgb_to_ycbcr_matrix_8bit_sdtv : - cog_rgb_to_ycbcr_matrix_8bit_hdtv; - else /* yuv -> yuv */ - matrix = - (alpha->out_sdtv) ? cog_rgb_to_ycbcr_matrix_8bit_sdtv : - cog_rgb_to_ycbcr_matrix_8bit_hdtv; - - y = (matrix[0] * ((gint) alpha->target_r) + - matrix[1] * ((gint) alpha->target_g) + - matrix[2] * ((gint) alpha->target_b) + matrix[3]) >> 8; - /* Cb,Cr without offset here because the chroma keying - * works with them being in range [-128,127] - */ - tmp1 = - (matrix[4] * ((gint) alpha->target_r) + - matrix[5] * ((gint) alpha->target_g) + - matrix[6] * ((gint) alpha->target_b)) >> 8; - tmp2 = - (matrix[8] * ((gint) alpha->target_r) + - matrix[9] * ((gint) alpha->target_g) + - matrix[10] * ((gint) alpha->target_b)) >> 8; - - kgl = sqrt (tmp1 * tmp1 + tmp2 * tmp2); - alpha->cb = 127 * (tmp1 / kgl); - alpha->cr = 127 * (tmp2 / kgl); - - tmp = 15 * tan (M_PI * alpha->angle / 180); - tmp = MIN (tmp, 255); - alpha->accept_angle_tg = tmp; - tmp = 15 / tan (M_PI * alpha->angle / 180); - tmp = MIN (tmp, 255); - alpha->accept_angle_ctg = tmp; - tmp = 1 / (kgl); - alpha->one_over_kc = 255 * 2 * tmp - 255; - tmp = 15 * y / kgl; - tmp = MIN (tmp, 255); - alpha->kfgy_scale = tmp; - alpha->kg = MIN (kgl, 127); - - alpha->noise_level2 = alpha->noise_level * alpha->noise_level; -} - -/* Protected with the alpha lock */ -static gboolean -gst_alpha_set_process_function (GstAlpha * alpha) -{ - alpha->process = NULL; - - switch (alpha->method) { - case ALPHA_METHOD_SET: - switch (alpha->out_format) { - case GST_VIDEO_FORMAT_AYUV: - switch (alpha->in_format) { - case GST_VIDEO_FORMAT_AYUV: - alpha->process = gst_alpha_set_ayuv_ayuv; - break; - case GST_VIDEO_FORMAT_Y444: - case GST_VIDEO_FORMAT_Y42B: - case GST_VIDEO_FORMAT_I420: - case GST_VIDEO_FORMAT_YV12: - case GST_VIDEO_FORMAT_Y41B: - alpha->process = gst_alpha_set_planar_yuv_ayuv; - break; - case GST_VIDEO_FORMAT_YUY2: - case GST_VIDEO_FORMAT_YVYU: - case GST_VIDEO_FORMAT_UYVY: - alpha->process = gst_alpha_set_packed_422_ayuv; - break; - case GST_VIDEO_FORMAT_ARGB: - case GST_VIDEO_FORMAT_ABGR: - case GST_VIDEO_FORMAT_RGBA: - case GST_VIDEO_FORMAT_BGRA: - alpha->process = gst_alpha_set_argb_ayuv; - break; - 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: - alpha->process = gst_alpha_set_rgb_ayuv; - break; - default: - break; - } - break; - case GST_VIDEO_FORMAT_ARGB: - case GST_VIDEO_FORMAT_ABGR: - case GST_VIDEO_FORMAT_RGBA: - case GST_VIDEO_FORMAT_BGRA: - switch (alpha->in_format) { - case GST_VIDEO_FORMAT_AYUV: - alpha->process = gst_alpha_set_ayuv_argb; - break; - case GST_VIDEO_FORMAT_Y444: - case GST_VIDEO_FORMAT_Y42B: - case GST_VIDEO_FORMAT_I420: - case GST_VIDEO_FORMAT_YV12: - case GST_VIDEO_FORMAT_Y41B: - alpha->process = gst_alpha_set_planar_yuv_argb; - break; - case GST_VIDEO_FORMAT_YUY2: - case GST_VIDEO_FORMAT_YVYU: - case GST_VIDEO_FORMAT_UYVY: - alpha->process = gst_alpha_set_packed_422_argb; - break; - case GST_VIDEO_FORMAT_ARGB: - case GST_VIDEO_FORMAT_ABGR: - case GST_VIDEO_FORMAT_RGBA: - case GST_VIDEO_FORMAT_BGRA: - alpha->process = gst_alpha_set_argb_argb; - break; - 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: - alpha->process = gst_alpha_set_rgb_argb; - break; - default: - break; - } - break; - break; - default: - break; - } - break; - case ALPHA_METHOD_GREEN: - case ALPHA_METHOD_BLUE: - case ALPHA_METHOD_CUSTOM: - switch (alpha->out_format) { - case GST_VIDEO_FORMAT_AYUV: - switch (alpha->in_format) { - case GST_VIDEO_FORMAT_AYUV: - alpha->process = gst_alpha_chroma_key_ayuv_ayuv; - break; - case GST_VIDEO_FORMAT_Y444: - case GST_VIDEO_FORMAT_Y42B: - case GST_VIDEO_FORMAT_I420: - case GST_VIDEO_FORMAT_YV12: - case GST_VIDEO_FORMAT_Y41B: - alpha->process = gst_alpha_chroma_key_planar_yuv_ayuv; - break; - case GST_VIDEO_FORMAT_YUY2: - case GST_VIDEO_FORMAT_YVYU: - case GST_VIDEO_FORMAT_UYVY: - alpha->process = gst_alpha_chroma_key_packed_422_ayuv; - break; - case GST_VIDEO_FORMAT_ARGB: - case GST_VIDEO_FORMAT_ABGR: - case GST_VIDEO_FORMAT_RGBA: - case GST_VIDEO_FORMAT_BGRA: - alpha->process = gst_alpha_chroma_key_argb_ayuv; - break; - 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: - alpha->process = gst_alpha_chroma_key_rgb_ayuv; - break; - default: - break; - } - break; - case GST_VIDEO_FORMAT_ARGB: - case GST_VIDEO_FORMAT_ABGR: - case GST_VIDEO_FORMAT_RGBA: - case GST_VIDEO_FORMAT_BGRA: - switch (alpha->in_format) { - case GST_VIDEO_FORMAT_AYUV: - alpha->process = gst_alpha_chroma_key_ayuv_argb; - break; - case GST_VIDEO_FORMAT_Y444: - case GST_VIDEO_FORMAT_Y42B: - case GST_VIDEO_FORMAT_I420: - case GST_VIDEO_FORMAT_YV12: - case GST_VIDEO_FORMAT_Y41B: - alpha->process = gst_alpha_chroma_key_planar_yuv_argb; - break; - case GST_VIDEO_FORMAT_YUY2: - case GST_VIDEO_FORMAT_YVYU: - case GST_VIDEO_FORMAT_UYVY: - alpha->process = gst_alpha_chroma_key_packed_422_argb; - break; - case GST_VIDEO_FORMAT_ARGB: - case GST_VIDEO_FORMAT_ABGR: - case GST_VIDEO_FORMAT_RGBA: - case GST_VIDEO_FORMAT_BGRA: - alpha->process = gst_alpha_chroma_key_argb_argb; - break; - 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: - alpha->process = gst_alpha_chroma_key_rgb_argb; - break; - default: - break; - } - break; - break; - default: - break; - } - break; - default: - break; - } - return alpha->process != NULL; -} - -static gboolean -gst_alpha_start (GstBaseTransform * btrans) -{ - GstAlpha *alpha = GST_ALPHA (btrans); - - GST_ALPHA_LOCK (alpha); - gst_alpha_init_params (alpha); - GST_ALPHA_UNLOCK (alpha); - - return TRUE; -} - -static void -gst_alpha_before_transform (GstBaseTransform * btrans, GstBuffer * buf) -{ - GstAlpha *alpha = GST_ALPHA (btrans); - GstClockTime timestamp; - - timestamp = gst_segment_to_stream_time (&btrans->segment, GST_FORMAT_TIME, - GST_BUFFER_TIMESTAMP (buf)); - GST_LOG ("Got stream time of %" GST_TIME_FORMAT, GST_TIME_ARGS (timestamp)); - if (GST_CLOCK_TIME_IS_VALID (timestamp)) - gst_object_sync_values (G_OBJECT (alpha), timestamp); -} - -static GstFlowReturn -gst_alpha_transform (GstBaseTransform * btrans, GstBuffer * in, GstBuffer * out) -{ - GstAlpha *alpha = GST_ALPHA (btrans); - gint width, height; - - GST_ALPHA_LOCK (alpha); - - if (G_UNLIKELY (!alpha->process)) { - GST_ERROR_OBJECT (alpha, "Not negotiated yet"); - GST_ALPHA_UNLOCK (alpha); - return GST_FLOW_NOT_NEGOTIATED; - } - - width = alpha->width; - height = alpha->height; - - alpha->process (GST_BUFFER_DATA (in), - GST_BUFFER_DATA (out), width, height, alpha); - - GST_ALPHA_UNLOCK (alpha); - - return GST_FLOW_OK; -} - -static gboolean -plugin_init (GstPlugin * plugin) -{ - gst_controller_init (NULL, NULL); - - return gst_element_register (plugin, "alpha", GST_RANK_NONE, GST_TYPE_ALPHA); -} - -GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, - GST_VERSION_MINOR, - "alpha", - "adds an alpha channel to video - constant or via chroma-keying", - plugin_init, VERSION, GST_LICENSE, GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN) |