2 * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
3 * Copyright (C) <2007> Wim Taymans <wim.taymans@collabora.co.uk>
4 * Copyright (C) <2007> Edward Hervey <edward.hervey@collabora.co.uk>
5 * Copyright (C) <2007> Jan Schmidt <thaytan@noraisin.net>
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Library General Public License for more details.
17 * You should have received a copy of the GNU Library General Public
18 * License along with this library; if not, write to the
19 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 * Boston, MA 02111-1307, USA.
24 * SECTION:element-alpha
26 * The alpha element adds an alpha channel to a video stream. The values
27 * of the alpha channel can be either be set to a constant or can be
28 * dynamically calculated via chroma keying, e.g. blue can be set as
29 * the transparent color.
33 * gst-launch videotestsrc pattern=smpte75 ! alpha method=green ! \
34 * videomixer name=mixer ! videoconvert ! autovideosink \
35 * videotestsrc pattern=snow ! mixer.
36 * ]| This pipeline adds a alpha channel to the SMPTE color bars
37 * with green as the transparent color and mixes the output with
38 * a snow video stream.
53 #define M_PI 3.14159265358979323846
56 /* Generated by -bad/ext/cog/generate_tables */
57 static const int cog_ycbcr_to_rgb_matrix_8bit_hdtv[] = {
59 298, -55, -136, 19681,
63 static const int cog_ycbcr_to_rgb_matrix_8bit_sdtv[] = {
65 298, -100, -208, 34707,
69 static const gint cog_rgb_to_ycbcr_matrix_8bit_hdtv[] = {
72 112, -102, -10, 32768,
75 static const gint cog_rgb_to_ycbcr_matrix_8bit_sdtv[] = {
81 static const gint cog_ycbcr_sdtv_to_ycbcr_hdtv_matrix_8bit[] = {
87 static const gint cog_ycbcr_hdtv_to_ycbcr_sdtv_matrix_8bit[] = {
93 /* Alpha signals and args */
100 #define DEFAULT_METHOD ALPHA_METHOD_SET
101 #define DEFAULT_ALPHA 1.0
102 #define DEFAULT_TARGET_R 0
103 #define DEFAULT_TARGET_G 255
104 #define DEFAULT_TARGET_B 0
105 #define DEFAULT_ANGLE 20.0
106 #define DEFAULT_NOISE_LEVEL 2.0
107 #define DEFAULT_BLACK_SENSITIVITY 100
108 #define DEFAULT_WHITE_SENSITIVITY 100
109 #define DEFAULT_PREFER_PASSTHROUGH FALSE
121 PROP_BLACK_SENSITIVITY,
122 PROP_WHITE_SENSITIVITY,
123 PROP_PREFER_PASSTHROUGH,
127 static GstStaticPadTemplate gst_alpha_src_template =
128 GST_STATIC_PAD_TEMPLATE ("src",
131 GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE ("{ AYUV, "
132 "ARGB, BGRA, ABGR, RGBA, Y444, xRGB, BGRx, xBGR, "
133 "RGBx, RGB, BGR, Y42B, YUY2, YVYU, UYVY, I420, YV12, Y41B } "))
136 static GstStaticPadTemplate gst_alpha_sink_template =
137 GST_STATIC_PAD_TEMPLATE ("sink",
140 GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE ("{ AYUV, "
141 "ARGB, BGRA, ABGR, RGBA, Y444, xRGB, BGRx, xBGR, "
142 "RGBx, RGB, BGR, Y42B, YUY2, YVYU, UYVY, I420, YV12, " "Y41B } "))
145 static GstStaticCaps gst_alpha_alpha_caps =
146 GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE ("{ AYUV, ARGB, BGRA, ABGR, RGBA }"));
148 /* FIXME: why do we need our own lock for this? */
149 #if !GLIB_CHECK_VERSION (2, 31, 0)
150 #define GST_ALPHA_LOCK(alpha) G_STMT_START { \
151 GST_LOG_OBJECT (alpha, "Locking alpha from thread %p", g_thread_self ()); \
152 g_static_mutex_lock (&alpha->lock); \
153 GST_LOG_OBJECT (alpha, "Locked alpha from thread %p", g_thread_self ()); \
156 #define GST_ALPHA_UNLOCK(alpha) G_STMT_START { \
157 GST_LOG_OBJECT (alpha, "Unlocking alpha from thread %p", g_thread_self ()); \
158 g_static_mutex_unlock (&alpha->lock); \
161 #define GST_ALPHA_LOCK(alpha) G_STMT_START { \
162 GST_LOG_OBJECT (alpha, "Locking alpha from thread %p", g_thread_self ()); \
163 g_mutex_lock (&alpha->lock); \
164 GST_LOG_OBJECT (alpha, "Locked alpha from thread %p", g_thread_self ()); \
167 #define GST_ALPHA_UNLOCK(alpha) G_STMT_START { \
168 GST_LOG_OBJECT (alpha, "Unlocking alpha from thread %p", g_thread_self ()); \
169 g_mutex_unlock (&alpha->lock); \
173 static GstCaps *gst_alpha_transform_caps (GstBaseTransform * btrans,
174 GstPadDirection direction, GstCaps * caps, GstCaps * filter);
175 static void gst_alpha_before_transform (GstBaseTransform * btrans,
178 static gboolean gst_alpha_set_info (GstVideoFilter * filter,
179 GstCaps * incaps, GstVideoInfo * in_info, GstCaps * outcaps,
180 GstVideoInfo * out_info);
181 static GstFlowReturn gst_alpha_transform_frame (GstVideoFilter * filter,
182 GstVideoFrame * in_frame, GstVideoFrame * out_frame);
184 static void gst_alpha_init_params_full (GstAlpha * alpha,
185 const GstVideoFormatInfo * in_info, const GstVideoFormatInfo * out_info);
186 static void gst_alpha_init_params (GstAlpha * alpha);
187 static gboolean gst_alpha_set_process_function (GstAlpha * alpha);
188 static gboolean gst_alpha_set_process_function_full (GstAlpha * alpha,
189 GstVideoInfo * in_info, GstVideoInfo * out_info);
191 static void gst_alpha_set_property (GObject * object, guint prop_id,
192 const GValue * value, GParamSpec * pspec);
193 static void gst_alpha_get_property (GObject * object, guint prop_id,
194 GValue * value, GParamSpec * pspec);
195 static void gst_alpha_finalize (GObject * object);
197 #define gst_alpha_parent_class parent_class
198 G_DEFINE_TYPE (GstAlpha, gst_alpha, GST_TYPE_VIDEO_FILTER);
200 #define GST_TYPE_ALPHA_METHOD (gst_alpha_method_get_type())
202 gst_alpha_method_get_type (void)
204 static GType alpha_method_type = 0;
205 static const GEnumValue alpha_method[] = {
206 {ALPHA_METHOD_SET, "Set/adjust alpha channel", "set"},
207 {ALPHA_METHOD_GREEN, "Chroma Key green", "green"},
208 {ALPHA_METHOD_BLUE, "Chroma Key blue", "blue"},
209 {ALPHA_METHOD_CUSTOM, "Chroma Key on target_r/g/b", "custom"},
213 if (!alpha_method_type) {
214 alpha_method_type = g_enum_register_static ("GstAlphaMethod", alpha_method);
216 return alpha_method_type;
220 gst_alpha_class_init (GstAlphaClass * klass)
222 GObjectClass *gobject_class = (GObjectClass *) klass;
223 GstElementClass *gstelement_class = (GstElementClass *) klass;
224 GstBaseTransformClass *btrans_class = (GstBaseTransformClass *) klass;
225 GstVideoFilterClass *vfilter_class = (GstVideoFilterClass *) klass;
227 GST_DEBUG_CATEGORY_INIT (gst_alpha_debug, "alpha", 0,
228 "alpha - Element for adding alpha channel to streams");
230 gobject_class->set_property = gst_alpha_set_property;
231 gobject_class->get_property = gst_alpha_get_property;
232 gobject_class->finalize = gst_alpha_finalize;
234 g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_METHOD,
235 g_param_spec_enum ("method", "Method",
236 "How the alpha channels should be created", GST_TYPE_ALPHA_METHOD,
237 DEFAULT_METHOD, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
238 g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_ALPHA,
239 g_param_spec_double ("alpha", "Alpha", "The value for the alpha channel",
240 0.0, 1.0, DEFAULT_ALPHA,
241 G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
242 g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_TARGET_R,
243 g_param_spec_uint ("target-r", "Target Red", "The Red target", 0, 255,
245 G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
246 g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_TARGET_G,
247 g_param_spec_uint ("target-g", "Target Green", "The Green target", 0, 255,
249 G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
250 g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_TARGET_B,
251 g_param_spec_uint ("target-b", "Target Blue", "The Blue target", 0, 255,
253 G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
254 g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_ANGLE,
255 g_param_spec_float ("angle", "Angle", "Size of the colorcube to change",
256 0.0, 90.0, DEFAULT_ANGLE,
257 G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
258 g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_NOISE_LEVEL,
259 g_param_spec_float ("noise-level", "Noise Level", "Size of noise radius",
260 0.0, 64.0, DEFAULT_NOISE_LEVEL,
261 G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
262 g_object_class_install_property (G_OBJECT_CLASS (klass),
263 PROP_BLACK_SENSITIVITY, g_param_spec_uint ("black-sensitivity",
264 "Black Sensitivity", "Sensitivity to dark colors", 0, 128,
265 DEFAULT_BLACK_SENSITIVITY,
266 G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
267 g_object_class_install_property (G_OBJECT_CLASS (klass),
268 PROP_WHITE_SENSITIVITY, g_param_spec_uint ("white-sensitivity",
269 "Sensitivity", "Sensitivity to bright colors", 0, 128,
270 DEFAULT_WHITE_SENSITIVITY,
271 G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
272 g_object_class_install_property (G_OBJECT_CLASS (klass),
273 PROP_PREFER_PASSTHROUGH, g_param_spec_boolean ("prefer-passthrough",
274 "Prefer Passthrough",
275 "Don't do any processing for alpha=1.0 if possible",
276 DEFAULT_PREFER_PASSTHROUGH,
277 G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
279 gst_element_class_set_details_simple (gstelement_class, "Alpha filter",
280 "Filter/Effect/Video",
281 "Adds an alpha channel to video - uniform or via chroma-keying",
282 "Wim Taymans <wim.taymans@gmail.com>\n"
283 "Edward Hervey <edward.hervey@collabora.co.uk>\n"
284 "Jan Schmidt <thaytan@noraisin.net>");
286 gst_element_class_add_pad_template (gstelement_class,
287 gst_static_pad_template_get (&gst_alpha_sink_template));
288 gst_element_class_add_pad_template (gstelement_class,
289 gst_static_pad_template_get (&gst_alpha_src_template));
291 btrans_class->before_transform =
292 GST_DEBUG_FUNCPTR (gst_alpha_before_transform);
293 btrans_class->transform_caps = GST_DEBUG_FUNCPTR (gst_alpha_transform_caps);
295 vfilter_class->set_info = GST_DEBUG_FUNCPTR (gst_alpha_set_info);
296 vfilter_class->transform_frame =
297 GST_DEBUG_FUNCPTR (gst_alpha_transform_frame);
301 gst_alpha_init (GstAlpha * alpha)
303 alpha->alpha = DEFAULT_ALPHA;
304 alpha->method = DEFAULT_METHOD;
305 alpha->target_r = DEFAULT_TARGET_R;
306 alpha->target_g = DEFAULT_TARGET_G;
307 alpha->target_b = DEFAULT_TARGET_B;
308 alpha->angle = DEFAULT_ANGLE;
309 alpha->noise_level = DEFAULT_NOISE_LEVEL;
310 alpha->black_sensitivity = DEFAULT_BLACK_SENSITIVITY;
311 alpha->white_sensitivity = DEFAULT_WHITE_SENSITIVITY;
313 #if !GLIB_CHECK_VERSION (2, 31, 0)
314 g_static_mutex_init (&alpha->lock);
316 g_mutex_init (&alpha->lock);
321 gst_alpha_finalize (GObject * object)
323 GstAlpha *alpha = GST_ALPHA (object);
325 #if !GLIB_CHECK_VERSION (2, 31, 0)
326 g_static_mutex_free (&alpha->lock);
328 g_mutex_clear (&alpha->lock);
331 G_OBJECT_CLASS (parent_class)->finalize (object);
335 gst_alpha_set_property (GObject * object, guint prop_id,
336 const GValue * value, GParamSpec * pspec)
338 GstAlpha *alpha = GST_ALPHA (object);
339 gboolean reconfigure = FALSE;
341 GST_ALPHA_LOCK (alpha);
344 gint method = g_value_get_enum (value);
346 reconfigure = (method != alpha->method) && (method == ALPHA_METHOD_SET
347 || alpha->method == ALPHA_METHOD_SET) && (alpha->alpha == 1.0)
348 && (alpha->prefer_passthrough);
349 alpha->method = method;
351 switch (alpha->method) {
352 case ALPHA_METHOD_GREEN:
354 alpha->target_g = 255;
357 case ALPHA_METHOD_BLUE:
360 alpha->target_b = 255;
365 gst_alpha_set_process_function (alpha);
366 gst_alpha_init_params (alpha);
370 gdouble a = g_value_get_double (value);
372 reconfigure = (a != alpha->alpha) && (a == 1.0 || alpha->alpha == 1.0)
373 && (alpha->method == ALPHA_METHOD_SET) && (alpha->prefer_passthrough);
378 alpha->target_r = g_value_get_uint (value);
379 gst_alpha_init_params (alpha);
382 alpha->target_g = g_value_get_uint (value);
383 gst_alpha_init_params (alpha);
386 alpha->target_b = g_value_get_uint (value);
387 gst_alpha_init_params (alpha);
390 alpha->angle = g_value_get_float (value);
391 gst_alpha_init_params (alpha);
393 case PROP_NOISE_LEVEL:
394 alpha->noise_level = g_value_get_float (value);
395 gst_alpha_init_params (alpha);
397 case PROP_BLACK_SENSITIVITY:
398 alpha->black_sensitivity = g_value_get_uint (value);
400 case PROP_WHITE_SENSITIVITY:
401 alpha->white_sensitivity = g_value_get_uint (value);
403 case PROP_PREFER_PASSTHROUGH:{
404 gboolean prefer_passthrough = g_value_get_boolean (value);
406 reconfigure = ((! !prefer_passthrough) != (! !alpha->prefer_passthrough))
407 && (alpha->method == ALPHA_METHOD_SET) && (alpha->alpha == 1.0);
408 alpha->prefer_passthrough = prefer_passthrough;
412 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
417 gst_base_transform_reconfigure (GST_BASE_TRANSFORM_CAST (alpha));
419 GST_ALPHA_UNLOCK (alpha);
423 gst_alpha_get_property (GObject * object, guint prop_id, GValue * value,
426 GstAlpha *alpha = GST_ALPHA (object);
430 g_value_set_enum (value, alpha->method);
433 g_value_set_double (value, alpha->alpha);
436 g_value_set_uint (value, alpha->target_r);
439 g_value_set_uint (value, alpha->target_g);
442 g_value_set_uint (value, alpha->target_b);
445 g_value_set_float (value, alpha->angle);
447 case PROP_NOISE_LEVEL:
448 g_value_set_float (value, alpha->noise_level);
450 case PROP_BLACK_SENSITIVITY:
451 g_value_set_uint (value, alpha->black_sensitivity);
453 case PROP_WHITE_SENSITIVITY:
454 g_value_set_uint (value, alpha->white_sensitivity);
456 case PROP_PREFER_PASSTHROUGH:
457 g_value_set_boolean (value, alpha->prefer_passthrough);
460 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
466 gst_alpha_transform_caps (GstBaseTransform * btrans,
467 GstPadDirection direction, GstCaps * caps, GstCaps * filter)
469 GstAlpha *alpha = GST_ALPHA (btrans);
470 GstCaps *ret, *tmp, *tmp2;
471 GstStructure *structure;
474 tmp = gst_caps_new_empty ();
476 GST_ALPHA_LOCK (alpha);
477 for (i = 0; i < gst_caps_get_size (caps); i++) {
478 structure = gst_structure_copy (gst_caps_get_structure (caps, i));
480 gst_structure_remove_field (structure, "format");
481 gst_structure_remove_field (structure, "color-matrix");
482 gst_structure_remove_field (structure, "chroma-site");
484 gst_caps_append_structure (tmp, structure);
487 if (direction == GST_PAD_SINK) {
488 tmp2 = gst_static_caps_get (&gst_alpha_alpha_caps);
489 ret = gst_caps_intersect (tmp, tmp2);
490 gst_caps_unref (tmp);
491 gst_caps_unref (tmp2);
495 if (alpha->prefer_passthrough && alpha->method == ALPHA_METHOD_SET
496 && alpha->alpha == 1.0) {
497 ret = gst_caps_copy (caps);
498 gst_caps_append (ret, tmp);
509 GST_DEBUG_OBJECT (alpha,
510 "Transformed %" GST_PTR_FORMAT " -> %" GST_PTR_FORMAT, caps, ret);
513 GstCaps *intersection;
515 GST_DEBUG_OBJECT (alpha, "Using filter caps %" GST_PTR_FORMAT, filter);
517 gst_caps_intersect_full (filter, ret, GST_CAPS_INTERSECT_FIRST);
518 gst_caps_unref (ret);
520 GST_DEBUG_OBJECT (alpha, "Intersection %" GST_PTR_FORMAT, ret);
524 GST_ALPHA_UNLOCK (alpha);
530 gst_alpha_set_info (GstVideoFilter * filter,
531 GstCaps * incaps, GstVideoInfo * in_info, GstCaps * outcaps,
532 GstVideoInfo * out_info)
534 GstAlpha *alpha = GST_ALPHA (filter);
535 gboolean passthrough;
537 GST_ALPHA_LOCK (alpha);
539 alpha->in_sdtv = in_info->colorimetry.matrix = GST_VIDEO_COLOR_MATRIX_BT601;
540 alpha->out_sdtv = out_info->colorimetry.matrix = GST_VIDEO_COLOR_MATRIX_BT601;
542 passthrough = alpha->prefer_passthrough &&
543 GST_VIDEO_INFO_FORMAT (in_info) == GST_VIDEO_INFO_FORMAT (out_info)
544 && alpha->in_sdtv == alpha->out_sdtv && alpha->method == ALPHA_METHOD_SET
545 && alpha->alpha == 1.0;
547 GST_DEBUG_OBJECT (alpha,
548 "Setting caps %" GST_PTR_FORMAT " -> %" GST_PTR_FORMAT
549 " (passthrough: %d)", incaps, outcaps, passthrough);
550 gst_base_transform_set_passthrough (GST_BASE_TRANSFORM_CAST (filter),
553 if (!gst_alpha_set_process_function_full (alpha, in_info, out_info)
557 gst_alpha_init_params_full (alpha, in_info->finfo, out_info->finfo);
559 GST_ALPHA_UNLOCK (alpha);
566 GST_WARNING_OBJECT (alpha,
567 "No processing function for this caps and no passthrough mode");
568 GST_ALPHA_UNLOCK (alpha);
573 /* based on http://www.cs.utah.edu/~michael/chroma/
576 chroma_keying_yuv (gint a, gint * y, gint * u,
577 gint * v, gint cr, gint cb, gint smin, gint smax, guint8 accept_angle_tg,
578 guint8 accept_angle_ctg, guint8 one_over_kc, guint8 kfgy_scale, gint8 kg,
586 /* too dark or too bright, keep alpha */
587 if (*y < smin || *y > smax)
590 /* Convert foreground to XZ coords where X direction is defined by
592 tmp = ((*u) * cb + (*v) * cr) >> 7;
593 x = CLAMP (tmp, -128, 127);
594 tmp = ((*v) * cb - (*u) * cr) >> 7;
595 z = CLAMP (tmp, -128, 127);
597 /* WARNING: accept angle should never be set greater than "somewhat less
598 than 90 degrees" to avoid dealing with negative/infinite tg. In reality,
599 80 degrees should be enough if foreground is reasonable. If this seems
600 to be a problem, go to alternative ways of checking point position
601 (scalar product or line equations). This angle should not be too small
602 either to avoid infinite ctg (used to suppress foreground without use of
605 tmp = (x * accept_angle_tg) >> 4;
606 tmp = MIN (tmp, 127);
609 /* keep foreground Kfg = 0 */
612 /* Compute Kfg (implicitly) and Kbg, suppress foreground in XZ coord
614 tmp = (z * accept_angle_ctg) >> 4;
615 tmp = CLAMP (tmp, -128, 127);
620 tmp1 = MAX (tmp1, 0);
621 b_alpha = (tmp1 * one_over_kc) / 2;
622 b_alpha = 255 - CLAMP (b_alpha, 0, 255);
623 b_alpha = (a * b_alpha) >> 8;
625 tmp = (tmp1 * kfgy_scale) >> 4;
626 tmp1 = MIN (tmp, 255);
628 *y = (*y < tmp1) ? 0 : *y - tmp1;
630 /* Convert suppressed foreground back to CbCr */
631 tmp = (x1 * cb - y1 * cr) >> 7;
632 *u = CLAMP (tmp, -128, 127);
634 tmp = (x1 * cr + y1 * cb) >> 7;
635 *v = CLAMP (tmp, -128, 127);
637 /* Deal with noise. For now, a circle around the key color with
638 radius of noise_level treated as exact key color. Introduces
641 tmp = z * z + (x - kg) * (x - kg);
642 tmp = MIN (tmp, 0xffff);
644 if (tmp < noise_level2)
650 #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)
653 gst_alpha_set_argb_ayuv (const GstVideoFrame * in_frame,
654 GstVideoFrame * out_frame, GstAlpha * alpha)
656 gint s_alpha = CLAMP ((gint) (alpha->alpha * 256), 0, 256);
665 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
666 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
668 width = GST_VIDEO_FRAME_WIDTH (in_frame);
669 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
671 o[0] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 3);
672 o[1] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 0);
673 o[2] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 1);
674 o[3] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 2);
677 alpha->out_sdtv ? cog_rgb_to_ycbcr_matrix_8bit_sdtv :
678 cog_rgb_to_ycbcr_matrix_8bit_hdtv, 12 * sizeof (gint));
680 for (i = 0; i < height; i++) {
681 for (j = 0; j < width; j++) {
682 dest[0] = (src[o[0]] * s_alpha) >> 8;
684 y = APPLY_MATRIX (matrix, 0, src[o[1]], src[o[2]], src[o[3]]);
685 u = APPLY_MATRIX (matrix, 1, src[o[1]], src[o[2]], src[o[3]]);
686 v = APPLY_MATRIX (matrix, 2, src[o[1]], src[o[2]], src[o[3]]);
699 gst_alpha_chroma_key_argb_ayuv (const GstVideoFrame * in_frame,
700 GstVideoFrame * out_frame, GstAlpha * alpha)
709 gint pa = CLAMP ((gint) (alpha->alpha * 256), 0, 256);
710 gint8 cb = alpha->cb, cr = alpha->cr;
711 gint8 kg = alpha->kg;
712 guint8 accept_angle_tg = alpha->accept_angle_tg;
713 guint8 accept_angle_ctg = alpha->accept_angle_ctg;
714 guint8 one_over_kc = alpha->one_over_kc;
715 guint8 kfgy_scale = alpha->kfgy_scale;
716 guint noise_level2 = alpha->noise_level2;
720 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
721 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
723 width = GST_VIDEO_FRAME_WIDTH (in_frame);
724 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
726 o[0] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 3);
727 o[1] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 0);
728 o[2] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 1);
729 o[3] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 2);
731 smin = 128 - alpha->black_sensitivity;
732 smax = 128 + alpha->white_sensitivity;
735 alpha->out_sdtv ? cog_rgb_to_ycbcr_matrix_8bit_sdtv :
736 cog_rgb_to_ycbcr_matrix_8bit_hdtv, 12 * sizeof (gint));
738 for (i = 0; i < height; i++) {
739 for (j = 0; j < width; j++) {
740 a = (src[o[0]] * pa) >> 8;
745 y = APPLY_MATRIX (matrix, 0, r, g, b);
746 u = APPLY_MATRIX (matrix, 1, r, g, b) - 128;
747 v = APPLY_MATRIX (matrix, 2, r, g, b) - 128;
749 a = chroma_keying_yuv (a, &y, &u, &v, cr, cb,
750 smin, smax, accept_angle_tg, accept_angle_ctg,
751 one_over_kc, kfgy_scale, kg, noise_level2);
768 gst_alpha_set_argb_argb (const GstVideoFrame * in_frame,
769 GstVideoFrame * out_frame, GstAlpha * alpha)
774 gint s_alpha = CLAMP ((gint) (alpha->alpha * 256), 0, 256);
778 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
779 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
781 width = GST_VIDEO_FRAME_WIDTH (in_frame);
782 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
784 p[0] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 3);
785 p[1] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 0);
786 p[2] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 1);
787 p[3] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 2);
789 o[0] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 3);
790 o[1] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 0);
791 o[2] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 1);
792 o[3] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 2);
794 for (i = 0; i < height; i++) {
795 for (j = 0; j < width; j++) {
796 dest[p[0]] = (src[o[0]] * s_alpha) >> 8;
798 dest[p[1]] = src[o[1]];
799 dest[p[2]] = src[o[2]];
800 dest[p[3]] = src[o[3]];
809 gst_alpha_chroma_key_argb_argb (const GstVideoFrame * in_frame,
810 GstVideoFrame * out_frame, GstAlpha * alpha)
819 gint pa = CLAMP ((gint) (alpha->alpha * 256), 0, 256);
820 gint8 cb = alpha->cb, cr = alpha->cr;
821 gint8 kg = alpha->kg;
822 guint8 accept_angle_tg = alpha->accept_angle_tg;
823 guint8 accept_angle_ctg = alpha->accept_angle_ctg;
824 guint8 one_over_kc = alpha->one_over_kc;
825 guint8 kfgy_scale = alpha->kfgy_scale;
826 guint noise_level2 = alpha->noise_level2;
827 gint matrix[12], matrix2[12];
830 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
831 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
833 width = GST_VIDEO_FRAME_WIDTH (in_frame);
834 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
836 p[0] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 3);
837 p[1] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 0);
838 p[2] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 1);
839 p[3] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 2);
841 o[0] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 3);
842 o[1] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 0);
843 o[2] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 1);
844 o[3] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 2);
846 smin = 128 - alpha->black_sensitivity;
847 smax = 128 + alpha->white_sensitivity;
849 memcpy (matrix, cog_rgb_to_ycbcr_matrix_8bit_sdtv, 12 * sizeof (gint));
850 memcpy (matrix2, cog_ycbcr_to_rgb_matrix_8bit_sdtv, 12 * sizeof (gint));
852 for (i = 0; i < height; i++) {
853 for (j = 0; j < width; j++) {
854 a = (src[o[0]] * pa) >> 8;
859 y = APPLY_MATRIX (matrix, 0, r, g, b);
860 u = APPLY_MATRIX (matrix, 1, r, g, b) - 128;
861 v = APPLY_MATRIX (matrix, 2, r, g, b) - 128;
863 a = chroma_keying_yuv (a, &y, &u, &v, cr, cb,
864 smin, smax, accept_angle_tg, accept_angle_ctg,
865 one_over_kc, kfgy_scale, kg, noise_level2);
870 r = APPLY_MATRIX (matrix2, 0, y, u, v);
871 g = APPLY_MATRIX (matrix2, 1, y, u, v);
872 b = APPLY_MATRIX (matrix2, 2, y, u, v);
875 dest[p[1]] = CLAMP (r, 0, 255);
876 dest[p[2]] = CLAMP (g, 0, 255);
877 dest[p[3]] = CLAMP (b, 0, 255);
886 gst_alpha_set_ayuv_argb (const GstVideoFrame * in_frame,
887 GstVideoFrame * out_frame, GstAlpha * alpha)
892 gint s_alpha = CLAMP ((gint) (alpha->alpha * 256), 0, 256);
898 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
899 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
901 width = GST_VIDEO_FRAME_WIDTH (in_frame);
902 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
904 p[0] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 3);
905 p[1] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 0);
906 p[2] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 1);
907 p[3] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 2);
910 alpha->in_sdtv ? cog_ycbcr_to_rgb_matrix_8bit_sdtv :
911 cog_ycbcr_to_rgb_matrix_8bit_hdtv, 12 * sizeof (gint));
913 for (y = 0; y < height; y++) {
914 for (x = 0; x < width; x++) {
915 dest[p[0]] = (src[0] * s_alpha) >> 8;
917 r = APPLY_MATRIX (matrix, 0, src[1], src[2], src[3]);
918 g = APPLY_MATRIX (matrix, 1, src[1], src[2], src[3]);
919 b = APPLY_MATRIX (matrix, 2, src[1], src[2], src[3]);
921 dest[p[1]] = CLAMP (r, 0, 255);
922 dest[p[2]] = CLAMP (g, 0, 255);
923 dest[p[3]] = CLAMP (b, 0, 255);
932 gst_alpha_chroma_key_ayuv_argb (const GstVideoFrame * in_frame,
933 GstVideoFrame * out_frame, GstAlpha * alpha)
942 gint pa = CLAMP ((gint) (alpha->alpha * 256), 0, 256);
943 gint8 cb = alpha->cb, cr = alpha->cr;
944 gint8 kg = alpha->kg;
945 guint8 accept_angle_tg = alpha->accept_angle_tg;
946 guint8 accept_angle_ctg = alpha->accept_angle_ctg;
947 guint8 one_over_kc = alpha->one_over_kc;
948 guint8 kfgy_scale = alpha->kfgy_scale;
949 guint noise_level2 = alpha->noise_level2;
953 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
954 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
956 width = GST_VIDEO_FRAME_WIDTH (in_frame);
957 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
959 p[0] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 3);
960 p[1] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 0);
961 p[2] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 1);
962 p[3] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 2);
964 smin = 128 - alpha->black_sensitivity;
965 smax = 128 + alpha->white_sensitivity;
968 alpha->in_sdtv ? cog_ycbcr_to_rgb_matrix_8bit_sdtv :
969 cog_ycbcr_to_rgb_matrix_8bit_hdtv, 12 * sizeof (gint));
971 for (i = 0; i < height; i++) {
972 for (j = 0; j < width; j++) {
973 a = (src[0] * pa) >> 8;
978 a = chroma_keying_yuv (a, &y, &u, &v, cr, cb,
979 smin, smax, accept_angle_tg, accept_angle_ctg,
980 one_over_kc, kfgy_scale, kg, noise_level2);
985 r = APPLY_MATRIX (matrix, 0, y, u, v);
986 g = APPLY_MATRIX (matrix, 1, y, u, v);
987 b = APPLY_MATRIX (matrix, 2, y, u, v);
990 dest[p[1]] = CLAMP (r, 0, 255);
991 dest[p[2]] = CLAMP (g, 0, 255);
992 dest[p[3]] = CLAMP (b, 0, 255);
1001 gst_alpha_set_ayuv_ayuv (const GstVideoFrame * in_frame,
1002 GstVideoFrame * out_frame, GstAlpha * alpha)
1007 gint s_alpha = CLAMP ((gint) (alpha->alpha * 256), 0, 256);
1010 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
1011 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
1013 width = GST_VIDEO_FRAME_WIDTH (in_frame);
1014 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
1016 if (alpha->in_sdtv == alpha->out_sdtv) {
1017 for (y = 0; y < height; y++) {
1018 for (x = 0; x < width; x++) {
1019 dest[0] = (src[0] * s_alpha) >> 8;
1032 alpha->out_sdtv ? cog_ycbcr_hdtv_to_ycbcr_sdtv_matrix_8bit :
1033 cog_ycbcr_sdtv_to_ycbcr_hdtv_matrix_8bit, 12 * sizeof (gint));
1035 for (y = 0; y < height; y++) {
1036 for (x = 0; x < width; x++) {
1037 dest[0] = (src[0] * s_alpha) >> 8;
1038 dest[1] = APPLY_MATRIX (matrix, 0, src[1], src[2], src[3]);
1039 dest[2] = APPLY_MATRIX (matrix, 1, src[1], src[2], src[3]);
1040 dest[3] = APPLY_MATRIX (matrix, 2, src[1], src[2], src[3]);
1050 gst_alpha_chroma_key_ayuv_ayuv (const GstVideoFrame * in_frame,
1051 GstVideoFrame * out_frame, GstAlpha * alpha)
1059 gint pa = CLAMP ((gint) (alpha->alpha * 256), 0, 256);
1060 gint8 cb = alpha->cb, cr = alpha->cr;
1061 gint8 kg = alpha->kg;
1062 guint8 accept_angle_tg = alpha->accept_angle_tg;
1063 guint8 accept_angle_ctg = alpha->accept_angle_ctg;
1064 guint8 one_over_kc = alpha->one_over_kc;
1065 guint8 kfgy_scale = alpha->kfgy_scale;
1066 guint noise_level2 = alpha->noise_level2;
1068 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
1069 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
1071 width = GST_VIDEO_FRAME_WIDTH (in_frame);
1072 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
1074 smin = 128 - alpha->black_sensitivity;
1075 smax = 128 + alpha->white_sensitivity;
1077 if (alpha->in_sdtv == alpha->out_sdtv) {
1078 for (i = 0; i < height; i++) {
1079 for (j = 0; j < width; j++) {
1080 a = (src[0] * pa) >> 8;
1085 a = chroma_keying_yuv (a, &y, &u, &v, cr, cb,
1086 smin, smax, accept_angle_tg, accept_angle_ctg,
1087 one_over_kc, kfgy_scale, kg, noise_level2);
1105 alpha->out_sdtv ? cog_ycbcr_hdtv_to_ycbcr_sdtv_matrix_8bit :
1106 cog_ycbcr_sdtv_to_ycbcr_hdtv_matrix_8bit, 12 * sizeof (gint));
1108 for (i = 0; i < height; i++) {
1109 for (j = 0; j < width; j++) {
1110 a = (src[0] * pa) >> 8;
1111 y = APPLY_MATRIX (matrix, 0, src[1], src[2], src[3]);
1112 u = APPLY_MATRIX (matrix, 1, src[1], src[2], src[3]) - 128;
1113 v = APPLY_MATRIX (matrix, 2, src[1], src[2], src[3]) - 128;
1115 a = chroma_keying_yuv (a, &y, &u, &v, cr, cb,
1116 smin, smax, accept_angle_tg, accept_angle_ctg,
1117 one_over_kc, kfgy_scale, kg, noise_level2);
1135 gst_alpha_set_rgb_ayuv (const GstVideoFrame * in_frame,
1136 GstVideoFrame * out_frame, GstAlpha * alpha)
1141 gint s_alpha = CLAMP ((gint) (alpha->alpha * 255), 0, 255);
1148 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
1149 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
1151 width = GST_VIDEO_FRAME_WIDTH (in_frame);
1152 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
1154 bpp = GST_VIDEO_FRAME_COMP_PSTRIDE (in_frame, 0);
1155 o[0] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 0);
1156 o[1] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 1);
1157 o[2] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 2);
1160 alpha->out_sdtv ? cog_rgb_to_ycbcr_matrix_8bit_sdtv :
1161 cog_rgb_to_ycbcr_matrix_8bit_hdtv, 12 * sizeof (gint));
1163 for (i = 0; i < height; i++) {
1164 for (j = 0; j < width; j++) {
1167 y = APPLY_MATRIX (matrix, 0, src[o[0]], src[o[1]], src[o[2]]);
1168 u = APPLY_MATRIX (matrix, 1, src[o[0]], src[o[1]], src[o[2]]);
1169 v = APPLY_MATRIX (matrix, 2, src[o[0]], src[o[1]], src[o[2]]);
1182 gst_alpha_chroma_key_rgb_ayuv (const GstVideoFrame * in_frame,
1183 GstVideoFrame * out_frame, GstAlpha * alpha)
1192 gint pa = CLAMP ((gint) (alpha->alpha * 255), 0, 255);
1193 gint8 cb = alpha->cb, cr = alpha->cr;
1194 gint8 kg = alpha->kg;
1195 guint8 accept_angle_tg = alpha->accept_angle_tg;
1196 guint8 accept_angle_ctg = alpha->accept_angle_ctg;
1197 guint8 one_over_kc = alpha->one_over_kc;
1198 guint8 kfgy_scale = alpha->kfgy_scale;
1199 guint noise_level2 = alpha->noise_level2;
1204 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
1205 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
1207 width = GST_VIDEO_FRAME_WIDTH (in_frame);
1208 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
1210 bpp = GST_VIDEO_FRAME_COMP_PSTRIDE (in_frame, 0);
1212 o[0] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 0);
1213 o[1] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 1);
1214 o[2] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 2);
1216 smin = 128 - alpha->black_sensitivity;
1217 smax = 128 + alpha->white_sensitivity;
1220 alpha->out_sdtv ? cog_rgb_to_ycbcr_matrix_8bit_sdtv :
1221 cog_rgb_to_ycbcr_matrix_8bit_hdtv, 12 * sizeof (gint));
1223 for (i = 0; i < height; i++) {
1224 for (j = 0; j < width; j++) {
1230 y = APPLY_MATRIX (matrix, 0, r, g, b);
1231 u = APPLY_MATRIX (matrix, 1, r, g, b) - 128;
1232 v = APPLY_MATRIX (matrix, 2, r, g, b) - 128;
1234 a = chroma_keying_yuv (a, &y, &u, &v, cr, cb,
1235 smin, smax, accept_angle_tg, accept_angle_ctg,
1236 one_over_kc, kfgy_scale, kg, noise_level2);
1253 gst_alpha_set_rgb_argb (const GstVideoFrame * in_frame,
1254 GstVideoFrame * out_frame, GstAlpha * alpha)
1259 gint s_alpha = CLAMP ((gint) (alpha->alpha * 255), 0, 255);
1264 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
1265 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
1267 width = GST_VIDEO_FRAME_WIDTH (in_frame);
1268 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
1270 bpp = GST_VIDEO_FRAME_COMP_PSTRIDE (in_frame, 0);
1272 o[0] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 0);
1273 o[1] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 1);
1274 o[2] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 2);
1276 p[0] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 3);
1277 p[1] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 0);
1278 p[2] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 1);
1279 p[3] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 2);
1281 for (i = 0; i < height; i++) {
1282 for (j = 0; j < width; j++) {
1283 dest[p[0]] = s_alpha;
1285 dest[p[1]] = src[o[0]];
1286 dest[p[2]] = src[o[1]];
1287 dest[p[3]] = src[o[2]];
1296 gst_alpha_chroma_key_rgb_argb (const GstVideoFrame * in_frame,
1297 GstVideoFrame * out_frame, GstAlpha * alpha)
1306 gint pa = CLAMP ((gint) (alpha->alpha * 255), 0, 255);
1307 gint8 cb = alpha->cb, cr = alpha->cr;
1308 gint8 kg = alpha->kg;
1309 guint8 accept_angle_tg = alpha->accept_angle_tg;
1310 guint8 accept_angle_ctg = alpha->accept_angle_ctg;
1311 guint8 one_over_kc = alpha->one_over_kc;
1312 guint8 kfgy_scale = alpha->kfgy_scale;
1313 guint noise_level2 = alpha->noise_level2;
1314 gint matrix[12], matrix2[12];
1318 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
1319 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
1321 width = GST_VIDEO_FRAME_WIDTH (in_frame);
1322 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
1324 bpp = GST_VIDEO_FRAME_COMP_PSTRIDE (in_frame, 0);
1326 o[0] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 0);
1327 o[1] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 1);
1328 o[2] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 2);
1330 p[0] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 3);
1331 p[1] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 0);
1332 p[2] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 1);
1333 p[3] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 2);
1335 smin = 128 - alpha->black_sensitivity;
1336 smax = 128 + alpha->white_sensitivity;
1338 memcpy (matrix, cog_rgb_to_ycbcr_matrix_8bit_sdtv, 12 * sizeof (gint));
1339 memcpy (matrix2, cog_ycbcr_to_rgb_matrix_8bit_sdtv, 12 * sizeof (gint));
1341 for (i = 0; i < height; i++) {
1342 for (j = 0; j < width; j++) {
1348 y = APPLY_MATRIX (matrix, 0, r, g, b);
1349 u = APPLY_MATRIX (matrix, 1, r, g, b) - 128;
1350 v = APPLY_MATRIX (matrix, 2, r, g, b) - 128;
1352 a = chroma_keying_yuv (a, &y, &u, &v, cr, cb,
1353 smin, smax, accept_angle_tg, accept_angle_ctg,
1354 one_over_kc, kfgy_scale, kg, noise_level2);
1359 r = APPLY_MATRIX (matrix2, 0, y, u, v);
1360 g = APPLY_MATRIX (matrix2, 1, y, u, v);
1361 b = APPLY_MATRIX (matrix2, 2, y, u, v);
1364 dest[p[1]] = CLAMP (r, 0, 255);
1365 dest[p[2]] = CLAMP (g, 0, 255);
1366 dest[p[3]] = CLAMP (b, 0, 255);
1375 gst_alpha_set_planar_yuv_ayuv (const GstVideoFrame * in_frame,
1376 GstVideoFrame * out_frame, GstAlpha * alpha)
1381 gint b_alpha = CLAMP ((gint) (alpha->alpha * 255), 0, 255);
1382 const guint8 *srcY, *srcY_tmp;
1383 const guint8 *srcU, *srcU_tmp;
1384 const guint8 *srcV, *srcV_tmp;
1386 gint y_stride, uv_stride;
1387 gint v_subs, h_subs;
1389 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
1390 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
1392 width = GST_VIDEO_FRAME_WIDTH (in_frame);
1393 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
1395 y_stride = GST_VIDEO_FRAME_COMP_STRIDE (in_frame, 0);
1396 uv_stride = GST_VIDEO_FRAME_COMP_STRIDE (in_frame, 1);
1398 srcY_tmp = srcY = src;
1399 srcU_tmp = srcU = src + GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 1);
1400 srcV_tmp = srcV = src + GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 2);
1402 switch (GST_VIDEO_FRAME_FORMAT (in_frame)) {
1403 case GST_VIDEO_FORMAT_I420:
1404 case GST_VIDEO_FORMAT_YV12:
1405 v_subs = h_subs = 2;
1407 case GST_VIDEO_FORMAT_Y444:
1408 v_subs = h_subs = 1;
1410 case GST_VIDEO_FORMAT_Y42B:
1414 case GST_VIDEO_FORMAT_Y41B:
1419 g_assert_not_reached ();
1423 if (alpha->in_sdtv == alpha->out_sdtv) {
1424 for (i = 0; i < height; i++) {
1425 for (j = 0; j < width; j++) {
1433 if ((j + 1) % h_subs == 0) {
1439 srcY_tmp = srcY = srcY_tmp + y_stride;
1440 if ((i + 1) % v_subs == 0) {
1441 srcU_tmp = srcU = srcU_tmp + uv_stride;
1442 srcV_tmp = srcV = srcV_tmp + uv_stride;
1453 alpha->out_sdtv ? cog_ycbcr_hdtv_to_ycbcr_sdtv_matrix_8bit :
1454 cog_ycbcr_sdtv_to_ycbcr_hdtv_matrix_8bit, 12 * sizeof (gint));
1456 for (i = 0; i < height; i++) {
1457 for (j = 0; j < width; j++) {
1464 dest[1] = APPLY_MATRIX (matrix, 0, y, u, v);
1465 dest[2] = APPLY_MATRIX (matrix, 1, y, u, v);
1466 dest[3] = APPLY_MATRIX (matrix, 2, y, u, v);
1470 if ((j + 1) % h_subs == 0) {
1476 srcY_tmp = srcY = srcY_tmp + y_stride;
1477 if ((i + 1) % v_subs == 0) {
1478 srcU_tmp = srcU = srcU_tmp + uv_stride;
1479 srcV_tmp = srcV = srcV_tmp + uv_stride;
1489 gst_alpha_chroma_key_planar_yuv_ayuv (const GstVideoFrame * in_frame,
1490 GstVideoFrame * out_frame, GstAlpha * alpha)
1495 gint b_alpha = CLAMP ((gint) (alpha->alpha * 255), 0, 255);
1496 const guint8 *srcY, *srcY_tmp;
1497 const guint8 *srcU, *srcU_tmp;
1498 const guint8 *srcV, *srcV_tmp;
1501 gint y_stride, uv_stride;
1502 gint v_subs, h_subs;
1503 gint smin = 128 - alpha->black_sensitivity;
1504 gint smax = 128 + alpha->white_sensitivity;
1505 gint8 cb = alpha->cb, cr = alpha->cr;
1506 gint8 kg = alpha->kg;
1507 guint8 accept_angle_tg = alpha->accept_angle_tg;
1508 guint8 accept_angle_ctg = alpha->accept_angle_ctg;
1509 guint8 one_over_kc = alpha->one_over_kc;
1510 guint8 kfgy_scale = alpha->kfgy_scale;
1511 guint noise_level2 = alpha->noise_level2;
1513 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
1514 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
1516 width = GST_VIDEO_FRAME_WIDTH (in_frame);
1517 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
1519 y_stride = GST_VIDEO_FRAME_COMP_STRIDE (in_frame, 0);
1520 uv_stride = GST_VIDEO_FRAME_COMP_STRIDE (in_frame, 1);
1522 srcY_tmp = srcY = src;
1523 srcU_tmp = srcU = src + GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 1);
1524 srcV_tmp = srcV = src + GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 2);
1526 switch (GST_VIDEO_FRAME_FORMAT (in_frame)) {
1527 case GST_VIDEO_FORMAT_I420:
1528 case GST_VIDEO_FORMAT_YV12:
1529 v_subs = h_subs = 2;
1531 case GST_VIDEO_FORMAT_Y444:
1532 v_subs = h_subs = 1;
1534 case GST_VIDEO_FORMAT_Y42B:
1538 case GST_VIDEO_FORMAT_Y41B:
1543 g_assert_not_reached ();
1547 if (alpha->in_sdtv == alpha->out_sdtv) {
1548 for (i = 0; i < height; i++) {
1549 for (j = 0; j < width; j++) {
1555 a = chroma_keying_yuv (a, &y, &u, &v, cr, cb, smin,
1556 smax, accept_angle_tg, accept_angle_ctg,
1557 one_over_kc, kfgy_scale, kg, noise_level2);
1569 if ((j + 1) % h_subs == 0) {
1575 srcY_tmp = srcY = srcY_tmp + y_stride;
1576 if ((i + 1) % v_subs == 0) {
1577 srcU_tmp = srcU = srcU_tmp + uv_stride;
1578 srcV_tmp = srcV = srcV_tmp + uv_stride;
1588 alpha->out_sdtv ? cog_ycbcr_hdtv_to_ycbcr_sdtv_matrix_8bit :
1589 cog_ycbcr_sdtv_to_ycbcr_hdtv_matrix_8bit, 12 * sizeof (gint));
1591 for (i = 0; i < height; i++) {
1592 for (j = 0; j < width; j++) {
1594 y = APPLY_MATRIX (matrix, 0, srcY[0], srcU[0], srcV[0]);
1595 u = APPLY_MATRIX (matrix, 1, srcY[0], srcU[0], srcV[0]) - 128;
1596 v = APPLY_MATRIX (matrix, 2, srcY[0], srcU[0], srcV[0]) - 128;
1598 a = chroma_keying_yuv (a, &y, &u, &v, cr, cb, smin,
1599 smax, accept_angle_tg, accept_angle_ctg,
1600 one_over_kc, kfgy_scale, kg, noise_level2);
1609 if ((j + 1) % h_subs == 0) {
1615 srcY_tmp = srcY = srcY_tmp + y_stride;
1616 if ((i + 1) % v_subs == 0) {
1617 srcU_tmp = srcU = srcU_tmp + uv_stride;
1618 srcV_tmp = srcV = srcV_tmp + uv_stride;
1628 gst_alpha_set_planar_yuv_argb (const GstVideoFrame * in_frame,
1629 GstVideoFrame * out_frame, GstAlpha * alpha)
1634 gint b_alpha = CLAMP ((gint) (alpha->alpha * 255), 0, 255);
1635 const guint8 *srcY, *srcY_tmp;
1636 const guint8 *srcU, *srcU_tmp;
1637 const guint8 *srcV, *srcV_tmp;
1639 gint y_stride, uv_stride;
1640 gint v_subs, h_subs;
1646 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
1647 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
1649 width = GST_VIDEO_FRAME_WIDTH (in_frame);
1650 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
1652 p[0] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 3);
1653 p[1] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 0);
1654 p[2] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 1);
1655 p[3] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 2);
1657 y_stride = GST_VIDEO_FRAME_COMP_STRIDE (in_frame, 0);
1658 uv_stride = GST_VIDEO_FRAME_COMP_STRIDE (in_frame, 1);
1660 srcY_tmp = srcY = src;
1661 srcU_tmp = srcU = src + GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 1);
1662 srcV_tmp = srcV = src + GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 2);
1664 switch (GST_VIDEO_FRAME_FORMAT (in_frame)) {
1665 case GST_VIDEO_FORMAT_I420:
1666 case GST_VIDEO_FORMAT_YV12:
1667 v_subs = h_subs = 2;
1669 case GST_VIDEO_FORMAT_Y444:
1670 v_subs = h_subs = 1;
1672 case GST_VIDEO_FORMAT_Y42B:
1676 case GST_VIDEO_FORMAT_Y41B:
1681 g_assert_not_reached ();
1686 alpha->in_sdtv ? cog_ycbcr_to_rgb_matrix_8bit_sdtv :
1687 cog_ycbcr_to_rgb_matrix_8bit_hdtv, 12 * sizeof (gint));
1689 for (i = 0; i < height; i++) {
1690 for (j = 0; j < width; j++) {
1697 r = APPLY_MATRIX (matrix, 0, y, u, v);
1698 g = APPLY_MATRIX (matrix, 1, y, u, v);
1699 b = APPLY_MATRIX (matrix, 2, y, u, v);
1700 dest[p[1]] = CLAMP (r, 0, 255);
1701 dest[p[2]] = CLAMP (g, 0, 255);
1702 dest[p[3]] = CLAMP (b, 0, 255);
1706 if ((j + 1) % h_subs == 0) {
1712 srcY_tmp = srcY = srcY_tmp + y_stride;
1713 if ((i + 1) % v_subs == 0) {
1714 srcU_tmp = srcU = srcU_tmp + uv_stride;
1715 srcV_tmp = srcV = srcV_tmp + uv_stride;
1724 gst_alpha_chroma_key_planar_yuv_argb (const GstVideoFrame * in_frame,
1725 GstVideoFrame * out_frame, GstAlpha * alpha)
1730 gint b_alpha = CLAMP ((gint) (alpha->alpha * 255), 0, 255);
1731 const guint8 *srcY, *srcY_tmp;
1732 const guint8 *srcU, *srcU_tmp;
1733 const guint8 *srcV, *srcV_tmp;
1737 gint y_stride, uv_stride;
1738 gint v_subs, h_subs;
1739 gint smin = 128 - alpha->black_sensitivity;
1740 gint smax = 128 + alpha->white_sensitivity;
1741 gint8 cb = alpha->cb, cr = alpha->cr;
1742 gint8 kg = alpha->kg;
1743 guint8 accept_angle_tg = alpha->accept_angle_tg;
1744 guint8 accept_angle_ctg = alpha->accept_angle_ctg;
1745 guint8 one_over_kc = alpha->one_over_kc;
1746 guint8 kfgy_scale = alpha->kfgy_scale;
1747 guint noise_level2 = alpha->noise_level2;
1751 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
1752 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
1754 width = GST_VIDEO_FRAME_WIDTH (in_frame);
1755 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
1757 p[0] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 3);
1758 p[1] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 0);
1759 p[2] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 1);
1760 p[3] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 2);
1762 y_stride = GST_VIDEO_FRAME_COMP_STRIDE (in_frame, 0);
1763 uv_stride = GST_VIDEO_FRAME_COMP_STRIDE (in_frame, 1);
1765 srcY_tmp = srcY = src;
1766 srcU_tmp = srcU = src + GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 1);
1767 srcV_tmp = srcV = src + GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 2);
1769 switch (GST_VIDEO_FRAME_FORMAT (in_frame)) {
1770 case GST_VIDEO_FORMAT_I420:
1771 case GST_VIDEO_FORMAT_YV12:
1772 v_subs = h_subs = 2;
1774 case GST_VIDEO_FORMAT_Y444:
1775 v_subs = h_subs = 1;
1777 case GST_VIDEO_FORMAT_Y42B:
1781 case GST_VIDEO_FORMAT_Y41B:
1786 g_assert_not_reached ();
1791 alpha->in_sdtv ? cog_ycbcr_to_rgb_matrix_8bit_sdtv :
1792 cog_ycbcr_to_rgb_matrix_8bit_hdtv, 12 * sizeof (gint));
1794 for (i = 0; i < height; i++) {
1795 for (j = 0; j < width; j++) {
1801 a = chroma_keying_yuv (a, &y, &u, &v, cr, cb, smin,
1802 smax, accept_angle_tg, accept_angle_ctg,
1803 one_over_kc, kfgy_scale, kg, noise_level2);
1809 r = APPLY_MATRIX (matrix, 0, y, u, v);
1810 g = APPLY_MATRIX (matrix, 1, y, u, v);
1811 b = APPLY_MATRIX (matrix, 2, y, u, v);
1812 dest[p[1]] = CLAMP (r, 0, 255);
1813 dest[p[2]] = CLAMP (g, 0, 255);
1814 dest[p[3]] = CLAMP (b, 0, 255);
1818 if ((j + 1) % h_subs == 0) {
1824 srcY_tmp = srcY = srcY_tmp + y_stride;
1825 if ((i + 1) % v_subs == 0) {
1826 srcU_tmp = srcU = srcU_tmp + uv_stride;
1827 srcV_tmp = srcV = srcV_tmp + uv_stride;
1836 gst_alpha_set_packed_422_ayuv (const GstVideoFrame * in_frame,
1837 GstVideoFrame * out_frame, GstAlpha * alpha)
1842 gint s_alpha = CLAMP ((gint) (alpha->alpha * 255), 0, 255);
1845 gint p[4]; /* Y U Y V */
1847 const guint8 *src_tmp;
1849 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
1850 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
1852 width = GST_VIDEO_FRAME_WIDTH (in_frame);
1853 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
1855 src_stride = GST_VIDEO_FRAME_COMP_STRIDE (in_frame, 0);
1857 p[0] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 0);
1859 p[1] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 1);
1860 p[3] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 2);
1862 if (alpha->in_sdtv != alpha->out_sdtv) {
1866 alpha->in_sdtv ? cog_ycbcr_sdtv_to_ycbcr_hdtv_matrix_8bit :
1867 cog_ycbcr_hdtv_to_ycbcr_sdtv_matrix_8bit, 12 * sizeof (gint));
1869 for (i = 0; i < height; i++) {
1872 for (j = 0; j < width - 1; j += 2) {
1876 y = APPLY_MATRIX (matrix, 0, src[p[0]], src[p[1]], src[p[3]]);
1877 u = APPLY_MATRIX (matrix, 1, src[p[0]], src[p[1]], src[p[3]]);
1878 v = APPLY_MATRIX (matrix, 2, src[p[0]], src[p[1]], src[p[3]]);
1884 y = APPLY_MATRIX (matrix, 0, src[p[2]], src[p[1]], src[p[3]]);
1885 u = APPLY_MATRIX (matrix, 1, src[p[2]], src[p[1]], src[p[3]]);
1886 v = APPLY_MATRIX (matrix, 2, src[p[2]], src[p[1]], src[p[3]]);
1896 if (j == width - 1) {
1899 y = APPLY_MATRIX (matrix, 0, src[p[0]], src[p[1]], src[p[3]]);
1900 u = APPLY_MATRIX (matrix, 1, src[p[0]], src[p[1]], src[p[3]]);
1901 v = APPLY_MATRIX (matrix, 2, src[p[0]], src[p[1]], src[p[3]]);
1910 src = src_tmp + src_stride;
1913 for (i = 0; i < height; i++) {
1916 for (j = 0; j < width - 1; j += 2) {
1938 if (j == width - 1) {
1952 src = src_tmp + src_stride;
1958 gst_alpha_chroma_key_packed_422_ayuv (const GstVideoFrame * in_frame,
1959 GstVideoFrame * out_frame, GstAlpha * alpha)
1967 gint pa = CLAMP ((gint) (alpha->alpha * 255), 0, 255);
1968 gint8 cb = alpha->cb, cr = alpha->cr;
1969 gint8 kg = alpha->kg;
1970 guint8 accept_angle_tg = alpha->accept_angle_tg;
1971 guint8 accept_angle_ctg = alpha->accept_angle_ctg;
1972 guint8 one_over_kc = alpha->one_over_kc;
1973 guint8 kfgy_scale = alpha->kfgy_scale;
1974 guint noise_level2 = alpha->noise_level2;
1975 gint p[4]; /* Y U Y V */
1977 const guint8 *src_tmp;
1979 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
1980 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
1982 width = GST_VIDEO_FRAME_WIDTH (in_frame);
1983 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
1985 src_stride = GST_VIDEO_FRAME_COMP_STRIDE (in_frame, 0);
1987 p[0] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 0);
1989 p[1] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 1);
1990 p[3] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 2);
1992 smin = 128 - alpha->black_sensitivity;
1993 smax = 128 + alpha->white_sensitivity;
1995 if (alpha->in_sdtv != alpha->out_sdtv) {
1999 alpha->in_sdtv ? cog_ycbcr_sdtv_to_ycbcr_hdtv_matrix_8bit :
2000 cog_ycbcr_hdtv_to_ycbcr_sdtv_matrix_8bit, 12 * sizeof (gint));
2002 for (i = 0; i < height; i++) {
2005 for (j = 0; j < width - 1; j += 2) {
2006 y = APPLY_MATRIX (matrix, 0, src[p[0]], src[p[1]], src[p[3]]);
2007 u = APPLY_MATRIX (matrix, 1, src[p[0]], src[p[1]], src[p[3]]) - 128;
2008 v = APPLY_MATRIX (matrix, 2, src[p[0]], src[p[1]], src[p[3]]) - 128;
2010 a = chroma_keying_yuv (pa, &y, &u, &v, cr, cb,
2011 smin, smax, accept_angle_tg, accept_angle_ctg,
2012 one_over_kc, kfgy_scale, kg, noise_level2);
2019 y = APPLY_MATRIX (matrix, 0, src[p[2]], src[p[1]], src[p[3]]);
2020 u = APPLY_MATRIX (matrix, 1, src[p[2]], src[p[1]], src[p[3]]) - 128;
2021 v = APPLY_MATRIX (matrix, 2, src[p[2]], src[p[1]], src[p[3]]) - 128;
2023 a = chroma_keying_yuv (pa, &y, &u, &v, cr, cb,
2024 smin, smax, accept_angle_tg, accept_angle_ctg,
2025 one_over_kc, kfgy_scale, kg, noise_level2);
2036 if (j == width - 1) {
2037 y = APPLY_MATRIX (matrix, 0, src[p[0]], src[p[1]], src[p[3]]);
2038 u = APPLY_MATRIX (matrix, 1, src[p[0]], src[p[1]], src[p[3]]) - 128;
2039 v = APPLY_MATRIX (matrix, 2, src[p[0]], src[p[1]], src[p[3]]) - 128;
2041 a = chroma_keying_yuv (pa, &y, &u, &v, cr, cb,
2042 smin, smax, accept_angle_tg, accept_angle_ctg,
2043 one_over_kc, kfgy_scale, kg, noise_level2);
2053 src = src_tmp + src_stride;
2056 for (i = 0; i < height; i++) {
2059 for (j = 0; j < width - 1; j += 2) {
2061 u = src[p[1]] - 128;
2062 v = src[p[3]] - 128;
2064 a = chroma_keying_yuv (pa, &y, &u, &v, cr, cb,
2065 smin, smax, accept_angle_tg, accept_angle_ctg,
2066 one_over_kc, kfgy_scale, kg, noise_level2);
2074 u = src[p[1]] - 128;
2075 v = src[p[3]] - 128;
2077 a = chroma_keying_yuv (pa, &y, &u, &v, cr, cb,
2078 smin, smax, accept_angle_tg, accept_angle_ctg,
2079 one_over_kc, kfgy_scale, kg, noise_level2);
2090 if (j == width - 1) {
2092 u = src[p[1]] - 128;
2093 v = src[p[3]] - 128;
2095 a = chroma_keying_yuv (pa, &y, &u, &v, cr, cb,
2096 smin, smax, accept_angle_tg, accept_angle_ctg,
2097 one_over_kc, kfgy_scale, kg, noise_level2);
2107 src = src_tmp + src_stride;
2113 gst_alpha_set_packed_422_argb (const GstVideoFrame * in_frame,
2114 GstVideoFrame * out_frame, GstAlpha * alpha)
2119 gint s_alpha = CLAMP ((gint) (alpha->alpha * 255), 0, 255);
2123 const guint8 *src_tmp;
2127 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
2128 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
2130 width = GST_VIDEO_FRAME_WIDTH (in_frame);
2131 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
2133 src_stride = GST_VIDEO_FRAME_COMP_STRIDE (in_frame, 0);
2135 o[0] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 0);
2137 o[1] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 1);
2138 o[3] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 2);
2140 p[0] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 3);
2141 p[1] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 0);
2142 p[2] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 1);
2143 p[3] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 2);
2146 alpha->in_sdtv ? cog_ycbcr_to_rgb_matrix_8bit_sdtv :
2147 cog_ycbcr_to_rgb_matrix_8bit_hdtv, 12 * sizeof (gint));
2149 for (i = 0; i < height; i++) {
2152 for (j = 0; j < width - 1; j += 2) {
2153 r = APPLY_MATRIX (matrix, 0, src[o[0]], src[o[1]], src[o[3]]);
2154 g = APPLY_MATRIX (matrix, 1, src[o[0]], src[o[1]], src[o[3]]);
2155 b = APPLY_MATRIX (matrix, 2, src[o[0]], src[o[1]], src[o[3]]);
2157 dest[p[0]] = s_alpha;
2158 dest[p[1]] = CLAMP (r, 0, 255);
2159 dest[p[2]] = CLAMP (g, 0, 255);
2160 dest[p[3]] = CLAMP (b, 0, 255);
2162 r = APPLY_MATRIX (matrix, 0, src[o[2]], src[o[1]], src[o[3]]);
2163 g = APPLY_MATRIX (matrix, 1, src[o[2]], src[o[1]], src[o[3]]);
2164 b = APPLY_MATRIX (matrix, 2, src[o[2]], src[o[1]], src[o[3]]);
2166 dest[4 + p[0]] = s_alpha;
2167 dest[4 + p[1]] = CLAMP (r, 0, 255);
2168 dest[4 + p[2]] = CLAMP (g, 0, 255);
2169 dest[4 + p[3]] = CLAMP (b, 0, 255);
2175 if (j == width - 1) {
2176 r = APPLY_MATRIX (matrix, 0, src[o[0]], src[o[1]], src[o[3]]);
2177 g = APPLY_MATRIX (matrix, 1, src[o[0]], src[o[1]], src[o[3]]);
2178 b = APPLY_MATRIX (matrix, 2, src[o[0]], src[o[1]], src[o[3]]);
2180 dest[p[0]] = s_alpha;
2181 dest[p[1]] = CLAMP (r, 0, 255);
2182 dest[p[2]] = CLAMP (g, 0, 255);
2183 dest[p[3]] = CLAMP (b, 0, 255);
2188 src = src_tmp + src_stride;
2193 gst_alpha_chroma_key_packed_422_argb (const GstVideoFrame * in_frame,
2194 GstVideoFrame * out_frame, GstAlpha * alpha)
2203 gint pa = CLAMP ((gint) (alpha->alpha * 255), 0, 255);
2204 gint8 cb = alpha->cb, cr = alpha->cr;
2205 gint8 kg = alpha->kg;
2206 guint8 accept_angle_tg = alpha->accept_angle_tg;
2207 guint8 accept_angle_ctg = alpha->accept_angle_ctg;
2208 guint8 one_over_kc = alpha->one_over_kc;
2209 guint8 kfgy_scale = alpha->kfgy_scale;
2210 guint noise_level2 = alpha->noise_level2;
2213 const guint8 *src_tmp;
2216 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
2217 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
2219 width = GST_VIDEO_FRAME_WIDTH (in_frame);
2220 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
2222 src_stride = GST_VIDEO_FRAME_COMP_STRIDE (in_frame, 0);
2224 o[0] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 0);
2226 o[1] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 1);
2227 o[3] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 2);
2229 p[0] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 3);
2230 p[1] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 0);
2231 p[2] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 1);
2232 p[3] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 2);
2235 alpha->in_sdtv ? cog_ycbcr_to_rgb_matrix_8bit_sdtv :
2236 cog_ycbcr_to_rgb_matrix_8bit_hdtv, 12 * sizeof (gint));
2238 smin = 128 - alpha->black_sensitivity;
2239 smax = 128 + alpha->white_sensitivity;
2241 for (i = 0; i < height; i++) {
2244 for (j = 0; j < width - 1; j += 2) {
2246 u = src[o[1]] - 128;
2247 v = src[o[3]] - 128;
2249 a = chroma_keying_yuv (pa, &y, &u, &v, cr, cb,
2250 smin, smax, accept_angle_tg, accept_angle_ctg,
2251 one_over_kc, kfgy_scale, kg, noise_level2);
2255 r = APPLY_MATRIX (matrix, 0, y, u, v);
2256 g = APPLY_MATRIX (matrix, 1, y, u, v);
2257 b = APPLY_MATRIX (matrix, 2, y, u, v);
2260 dest[p[1]] = CLAMP (r, 0, 255);
2261 dest[p[2]] = CLAMP (g, 0, 255);
2262 dest[p[3]] = CLAMP (b, 0, 255);
2265 u = src[o[1]] - 128;
2266 v = src[o[3]] - 128;
2268 a = chroma_keying_yuv (pa, &y, &u, &v, cr, cb,
2269 smin, smax, accept_angle_tg, accept_angle_ctg,
2270 one_over_kc, kfgy_scale, kg, noise_level2);
2274 r = APPLY_MATRIX (matrix, 0, y, u, v);
2275 g = APPLY_MATRIX (matrix, 1, y, u, v);
2276 b = APPLY_MATRIX (matrix, 2, y, u, v);
2279 dest[4 + p[1]] = CLAMP (r, 0, 255);
2280 dest[4 + p[2]] = CLAMP (g, 0, 255);
2281 dest[4 + p[3]] = CLAMP (b, 0, 255);
2287 if (j == width - 1) {
2289 u = src[o[1]] - 128;
2290 v = src[o[3]] - 128;
2292 a = chroma_keying_yuv (pa, &y, &u, &v, cr, cb,
2293 smin, smax, accept_angle_tg, accept_angle_ctg,
2294 one_over_kc, kfgy_scale, kg, noise_level2);
2298 r = APPLY_MATRIX (matrix, 0, y, u, v);
2299 g = APPLY_MATRIX (matrix, 1, y, u, v);
2300 b = APPLY_MATRIX (matrix, 2, y, u, v);
2303 dest[p[1]] = CLAMP (r, 0, 255);
2304 dest[p[2]] = CLAMP (g, 0, 255);
2305 dest[p[3]] = CLAMP (b, 0, 255);
2310 src = src_tmp + src_stride;
2314 /* Protected with the alpha lock */
2316 gst_alpha_init_params_full (GstAlpha * alpha,
2317 const GstVideoFormatInfo * in_info, const GstVideoFormatInfo * out_info)
2325 /* RGB->RGB: convert to SDTV YUV, chroma keying, convert back
2326 * YUV->RGB: chroma keying, convert to RGB
2327 * RGB->YUV: convert to YUV, chroma keying
2328 * YUV->YUV: convert matrix, chroma keying
2330 if (GST_VIDEO_FORMAT_INFO_IS_RGB (in_info)
2331 && GST_VIDEO_FORMAT_INFO_IS_RGB (out_info))
2332 matrix = cog_rgb_to_ycbcr_matrix_8bit_sdtv;
2333 else if (GST_VIDEO_FORMAT_INFO_IS_YUV (in_info)
2334 && GST_VIDEO_FORMAT_INFO_IS_RGB (out_info))
2336 (alpha->in_sdtv) ? cog_rgb_to_ycbcr_matrix_8bit_sdtv :
2337 cog_rgb_to_ycbcr_matrix_8bit_hdtv;
2338 else if (GST_VIDEO_FORMAT_INFO_IS_RGB (in_info)
2339 && GST_VIDEO_FORMAT_INFO_IS_YUV (out_info))
2341 (alpha->out_sdtv) ? cog_rgb_to_ycbcr_matrix_8bit_sdtv :
2342 cog_rgb_to_ycbcr_matrix_8bit_hdtv;
2343 else /* yuv -> yuv */
2345 (alpha->out_sdtv) ? cog_rgb_to_ycbcr_matrix_8bit_sdtv :
2346 cog_rgb_to_ycbcr_matrix_8bit_hdtv;
2348 y = (matrix[0] * ((gint) alpha->target_r) +
2349 matrix[1] * ((gint) alpha->target_g) +
2350 matrix[2] * ((gint) alpha->target_b) + matrix[3]) >> 8;
2351 /* Cb,Cr without offset here because the chroma keying
2352 * works with them being in range [-128,127]
2355 (matrix[4] * ((gint) alpha->target_r) +
2356 matrix[5] * ((gint) alpha->target_g) +
2357 matrix[6] * ((gint) alpha->target_b)) >> 8;
2359 (matrix[8] * ((gint) alpha->target_r) +
2360 matrix[9] * ((gint) alpha->target_g) +
2361 matrix[10] * ((gint) alpha->target_b)) >> 8;
2363 kgl = sqrt (tmp1 * tmp1 + tmp2 * tmp2);
2364 alpha->cb = 127 * (tmp1 / kgl);
2365 alpha->cr = 127 * (tmp2 / kgl);
2367 tmp = 15 * tan (M_PI * alpha->angle / 180);
2368 tmp = MIN (tmp, 255);
2369 alpha->accept_angle_tg = tmp;
2370 tmp = 15 / tan (M_PI * alpha->angle / 180);
2371 tmp = MIN (tmp, 255);
2372 alpha->accept_angle_ctg = tmp;
2374 alpha->one_over_kc = 255 * 2 * tmp - 255;
2376 tmp = MIN (tmp, 255);
2377 alpha->kfgy_scale = tmp;
2378 alpha->kg = MIN (kgl, 127);
2380 alpha->noise_level2 = alpha->noise_level * alpha->noise_level;
2384 gst_alpha_init_params (GstAlpha * alpha)
2386 gst_alpha_init_params_full (alpha, GST_VIDEO_FILTER (alpha)->in_info.finfo,
2387 GST_VIDEO_FILTER (alpha)->out_info.finfo);
2390 /* Protected with the alpha lock */
2392 gst_alpha_set_process_function_full (GstAlpha * alpha, GstVideoInfo * in_info,
2393 GstVideoInfo * out_info)
2395 alpha->process = NULL;
2397 switch (alpha->method) {
2398 case ALPHA_METHOD_SET:
2399 switch (GST_VIDEO_INFO_FORMAT (out_info)) {
2400 case GST_VIDEO_FORMAT_AYUV:
2401 switch (GST_VIDEO_INFO_FORMAT (in_info)) {
2402 case GST_VIDEO_FORMAT_AYUV:
2403 alpha->process = gst_alpha_set_ayuv_ayuv;
2405 case GST_VIDEO_FORMAT_Y444:
2406 case GST_VIDEO_FORMAT_Y42B:
2407 case GST_VIDEO_FORMAT_I420:
2408 case GST_VIDEO_FORMAT_YV12:
2409 case GST_VIDEO_FORMAT_Y41B:
2410 alpha->process = gst_alpha_set_planar_yuv_ayuv;
2412 case GST_VIDEO_FORMAT_YUY2:
2413 case GST_VIDEO_FORMAT_YVYU:
2414 case GST_VIDEO_FORMAT_UYVY:
2415 alpha->process = gst_alpha_set_packed_422_ayuv;
2417 case GST_VIDEO_FORMAT_ARGB:
2418 case GST_VIDEO_FORMAT_ABGR:
2419 case GST_VIDEO_FORMAT_RGBA:
2420 case GST_VIDEO_FORMAT_BGRA:
2421 alpha->process = gst_alpha_set_argb_ayuv;
2423 case GST_VIDEO_FORMAT_xRGB:
2424 case GST_VIDEO_FORMAT_xBGR:
2425 case GST_VIDEO_FORMAT_RGBx:
2426 case GST_VIDEO_FORMAT_BGRx:
2427 case GST_VIDEO_FORMAT_RGB:
2428 case GST_VIDEO_FORMAT_BGR:
2429 alpha->process = gst_alpha_set_rgb_ayuv;
2435 case GST_VIDEO_FORMAT_ARGB:
2436 case GST_VIDEO_FORMAT_ABGR:
2437 case GST_VIDEO_FORMAT_RGBA:
2438 case GST_VIDEO_FORMAT_BGRA:
2439 switch (GST_VIDEO_INFO_FORMAT (in_info)) {
2440 case GST_VIDEO_FORMAT_AYUV:
2441 alpha->process = gst_alpha_set_ayuv_argb;
2443 case GST_VIDEO_FORMAT_Y444:
2444 case GST_VIDEO_FORMAT_Y42B:
2445 case GST_VIDEO_FORMAT_I420:
2446 case GST_VIDEO_FORMAT_YV12:
2447 case GST_VIDEO_FORMAT_Y41B:
2448 alpha->process = gst_alpha_set_planar_yuv_argb;
2450 case GST_VIDEO_FORMAT_YUY2:
2451 case GST_VIDEO_FORMAT_YVYU:
2452 case GST_VIDEO_FORMAT_UYVY:
2453 alpha->process = gst_alpha_set_packed_422_argb;
2455 case GST_VIDEO_FORMAT_ARGB:
2456 case GST_VIDEO_FORMAT_ABGR:
2457 case GST_VIDEO_FORMAT_RGBA:
2458 case GST_VIDEO_FORMAT_BGRA:
2459 alpha->process = gst_alpha_set_argb_argb;
2461 case GST_VIDEO_FORMAT_xRGB:
2462 case GST_VIDEO_FORMAT_xBGR:
2463 case GST_VIDEO_FORMAT_RGBx:
2464 case GST_VIDEO_FORMAT_BGRx:
2465 case GST_VIDEO_FORMAT_RGB:
2466 case GST_VIDEO_FORMAT_BGR:
2467 alpha->process = gst_alpha_set_rgb_argb;
2478 case ALPHA_METHOD_GREEN:
2479 case ALPHA_METHOD_BLUE:
2480 case ALPHA_METHOD_CUSTOM:
2481 switch (GST_VIDEO_INFO_FORMAT (out_info)) {
2482 case GST_VIDEO_FORMAT_AYUV:
2483 switch (GST_VIDEO_INFO_FORMAT (in_info)) {
2484 case GST_VIDEO_FORMAT_AYUV:
2485 alpha->process = gst_alpha_chroma_key_ayuv_ayuv;
2487 case GST_VIDEO_FORMAT_Y444:
2488 case GST_VIDEO_FORMAT_Y42B:
2489 case GST_VIDEO_FORMAT_I420:
2490 case GST_VIDEO_FORMAT_YV12:
2491 case GST_VIDEO_FORMAT_Y41B:
2492 alpha->process = gst_alpha_chroma_key_planar_yuv_ayuv;
2494 case GST_VIDEO_FORMAT_YUY2:
2495 case GST_VIDEO_FORMAT_YVYU:
2496 case GST_VIDEO_FORMAT_UYVY:
2497 alpha->process = gst_alpha_chroma_key_packed_422_ayuv;
2499 case GST_VIDEO_FORMAT_ARGB:
2500 case GST_VIDEO_FORMAT_ABGR:
2501 case GST_VIDEO_FORMAT_RGBA:
2502 case GST_VIDEO_FORMAT_BGRA:
2503 alpha->process = gst_alpha_chroma_key_argb_ayuv;
2505 case GST_VIDEO_FORMAT_xRGB:
2506 case GST_VIDEO_FORMAT_xBGR:
2507 case GST_VIDEO_FORMAT_RGBx:
2508 case GST_VIDEO_FORMAT_BGRx:
2509 case GST_VIDEO_FORMAT_RGB:
2510 case GST_VIDEO_FORMAT_BGR:
2511 alpha->process = gst_alpha_chroma_key_rgb_ayuv;
2517 case GST_VIDEO_FORMAT_ARGB:
2518 case GST_VIDEO_FORMAT_ABGR:
2519 case GST_VIDEO_FORMAT_RGBA:
2520 case GST_VIDEO_FORMAT_BGRA:
2521 switch (GST_VIDEO_INFO_FORMAT (in_info)) {
2522 case GST_VIDEO_FORMAT_AYUV:
2523 alpha->process = gst_alpha_chroma_key_ayuv_argb;
2525 case GST_VIDEO_FORMAT_Y444:
2526 case GST_VIDEO_FORMAT_Y42B:
2527 case GST_VIDEO_FORMAT_I420:
2528 case GST_VIDEO_FORMAT_YV12:
2529 case GST_VIDEO_FORMAT_Y41B:
2530 alpha->process = gst_alpha_chroma_key_planar_yuv_argb;
2532 case GST_VIDEO_FORMAT_YUY2:
2533 case GST_VIDEO_FORMAT_YVYU:
2534 case GST_VIDEO_FORMAT_UYVY:
2535 alpha->process = gst_alpha_chroma_key_packed_422_argb;
2537 case GST_VIDEO_FORMAT_ARGB:
2538 case GST_VIDEO_FORMAT_ABGR:
2539 case GST_VIDEO_FORMAT_RGBA:
2540 case GST_VIDEO_FORMAT_BGRA:
2541 alpha->process = gst_alpha_chroma_key_argb_argb;
2543 case GST_VIDEO_FORMAT_xRGB:
2544 case GST_VIDEO_FORMAT_xBGR:
2545 case GST_VIDEO_FORMAT_RGBx:
2546 case GST_VIDEO_FORMAT_BGRx:
2547 case GST_VIDEO_FORMAT_RGB:
2548 case GST_VIDEO_FORMAT_BGR:
2549 alpha->process = gst_alpha_chroma_key_rgb_argb;
2563 return alpha->process != NULL;
2567 gst_alpha_set_process_function (GstAlpha * alpha)
2569 return gst_alpha_set_process_function_full (alpha,
2570 &GST_VIDEO_FILTER_CAST (alpha)->in_info,
2571 &GST_VIDEO_FILTER_CAST (alpha)->out_info);
2575 gst_alpha_before_transform (GstBaseTransform * btrans, GstBuffer * buf)
2577 GstAlpha *alpha = GST_ALPHA (btrans);
2578 GstClockTime timestamp;
2580 timestamp = gst_segment_to_stream_time (&btrans->segment, GST_FORMAT_TIME,
2581 GST_BUFFER_TIMESTAMP (buf));
2582 GST_LOG ("Got stream time of %" GST_TIME_FORMAT, GST_TIME_ARGS (timestamp));
2583 if (GST_CLOCK_TIME_IS_VALID (timestamp))
2584 gst_object_sync_values (GST_OBJECT (alpha), timestamp);
2587 static GstFlowReturn
2588 gst_alpha_transform_frame (GstVideoFilter * filter, GstVideoFrame * in_frame,
2589 GstVideoFrame * out_frame)
2591 GstAlpha *alpha = GST_ALPHA (filter);
2593 GST_ALPHA_LOCK (alpha);
2595 if (G_UNLIKELY (!alpha->process))
2596 goto not_negotiated;
2598 alpha->process (in_frame, out_frame, alpha);
2600 GST_ALPHA_UNLOCK (alpha);
2607 GST_ERROR_OBJECT (alpha, "Not negotiated yet");
2608 GST_ALPHA_UNLOCK (alpha);
2609 return GST_FLOW_NOT_NEGOTIATED;
2614 plugin_init (GstPlugin * plugin)
2616 return gst_element_register (plugin, "alpha", GST_RANK_NONE, GST_TYPE_ALPHA);
2619 GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
2622 "adds an alpha channel to video - constant or via chroma-keying",
2623 plugin_init, VERSION, GST_LICENSE, GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN)