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., 51 Franklin St, Fifth Floor,
20 * Boston, MA 02110-1301, 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-1.0 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 #define GST_ALPHA_LOCK(alpha) G_STMT_START { \
150 GST_LOG_OBJECT (alpha, "Locking alpha from thread %p", g_thread_self ()); \
151 g_mutex_lock (&alpha->lock); \
152 GST_LOG_OBJECT (alpha, "Locked alpha from thread %p", g_thread_self ()); \
155 #define GST_ALPHA_UNLOCK(alpha) G_STMT_START { \
156 GST_LOG_OBJECT (alpha, "Unlocking alpha from thread %p", g_thread_self ()); \
157 g_mutex_unlock (&alpha->lock); \
160 static GstCaps *gst_alpha_transform_caps (GstBaseTransform * btrans,
161 GstPadDirection direction, GstCaps * caps, GstCaps * filter);
162 static void gst_alpha_before_transform (GstBaseTransform * btrans,
165 static gboolean gst_alpha_set_info (GstVideoFilter * filter,
166 GstCaps * incaps, GstVideoInfo * in_info, GstCaps * outcaps,
167 GstVideoInfo * out_info);
168 static GstFlowReturn gst_alpha_transform_frame (GstVideoFilter * filter,
169 GstVideoFrame * in_frame, GstVideoFrame * out_frame);
171 static void gst_alpha_init_params_full (GstAlpha * alpha,
172 const GstVideoFormatInfo * in_info, const GstVideoFormatInfo * out_info);
173 static void gst_alpha_init_params (GstAlpha * alpha);
174 static void gst_alpha_set_process_function (GstAlpha * alpha);
175 static gboolean gst_alpha_set_process_function_full (GstAlpha * alpha,
176 GstVideoInfo * in_info, GstVideoInfo * out_info);
178 static void gst_alpha_set_property (GObject * object, guint prop_id,
179 const GValue * value, GParamSpec * pspec);
180 static void gst_alpha_get_property (GObject * object, guint prop_id,
181 GValue * value, GParamSpec * pspec);
182 static void gst_alpha_finalize (GObject * object);
184 #define gst_alpha_parent_class parent_class
185 G_DEFINE_TYPE (GstAlpha, gst_alpha, GST_TYPE_VIDEO_FILTER);
187 #define GST_TYPE_ALPHA_METHOD (gst_alpha_method_get_type())
189 gst_alpha_method_get_type (void)
191 static GType alpha_method_type = 0;
192 static const GEnumValue alpha_method[] = {
193 {ALPHA_METHOD_SET, "Set/adjust alpha channel", "set"},
194 {ALPHA_METHOD_GREEN, "Chroma Key green", "green"},
195 {ALPHA_METHOD_BLUE, "Chroma Key blue", "blue"},
196 {ALPHA_METHOD_CUSTOM, "Chroma Key on target_r/g/b", "custom"},
200 if (!alpha_method_type) {
201 alpha_method_type = g_enum_register_static ("GstAlphaMethod", alpha_method);
203 return alpha_method_type;
207 gst_alpha_class_init (GstAlphaClass * klass)
209 GObjectClass *gobject_class = (GObjectClass *) klass;
210 GstElementClass *gstelement_class = (GstElementClass *) klass;
211 GstBaseTransformClass *btrans_class = (GstBaseTransformClass *) klass;
212 GstVideoFilterClass *vfilter_class = (GstVideoFilterClass *) klass;
214 GST_DEBUG_CATEGORY_INIT (gst_alpha_debug, "alpha", 0,
215 "alpha - Element for adding alpha channel to streams");
217 gobject_class->set_property = gst_alpha_set_property;
218 gobject_class->get_property = gst_alpha_get_property;
219 gobject_class->finalize = gst_alpha_finalize;
221 g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_METHOD,
222 g_param_spec_enum ("method", "Method",
223 "How the alpha channels should be created", GST_TYPE_ALPHA_METHOD,
224 DEFAULT_METHOD, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
225 g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_ALPHA,
226 g_param_spec_double ("alpha", "Alpha", "The value for the alpha channel",
227 0.0, 1.0, DEFAULT_ALPHA,
228 G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
229 g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_TARGET_R,
230 g_param_spec_uint ("target-r", "Target Red", "The Red target", 0, 255,
232 G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
233 g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_TARGET_G,
234 g_param_spec_uint ("target-g", "Target Green", "The Green target", 0, 255,
236 G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
237 g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_TARGET_B,
238 g_param_spec_uint ("target-b", "Target Blue", "The Blue target", 0, 255,
240 G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
241 g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_ANGLE,
242 g_param_spec_float ("angle", "Angle", "Size of the colorcube to change",
243 0.0, 90.0, DEFAULT_ANGLE,
244 G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
245 g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_NOISE_LEVEL,
246 g_param_spec_float ("noise-level", "Noise Level", "Size of noise radius",
247 0.0, 64.0, DEFAULT_NOISE_LEVEL,
248 G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
249 g_object_class_install_property (G_OBJECT_CLASS (klass),
250 PROP_BLACK_SENSITIVITY, g_param_spec_uint ("black-sensitivity",
251 "Black Sensitivity", "Sensitivity to dark colors", 0, 128,
252 DEFAULT_BLACK_SENSITIVITY,
253 G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
254 g_object_class_install_property (G_OBJECT_CLASS (klass),
255 PROP_WHITE_SENSITIVITY, g_param_spec_uint ("white-sensitivity",
256 "Sensitivity", "Sensitivity to bright colors", 0, 128,
257 DEFAULT_WHITE_SENSITIVITY,
258 G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
259 g_object_class_install_property (G_OBJECT_CLASS (klass),
260 PROP_PREFER_PASSTHROUGH, g_param_spec_boolean ("prefer-passthrough",
261 "Prefer Passthrough",
262 "Don't do any processing for alpha=1.0 if possible",
263 DEFAULT_PREFER_PASSTHROUGH,
264 G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
266 gst_element_class_set_static_metadata (gstelement_class, "Alpha filter",
267 "Filter/Effect/Video",
268 "Adds an alpha channel to video - uniform or via chroma-keying",
269 "Wim Taymans <wim.taymans@gmail.com>\n"
270 "Edward Hervey <edward.hervey@collabora.co.uk>\n"
271 "Jan Schmidt <thaytan@noraisin.net>");
273 gst_element_class_add_pad_template (gstelement_class,
274 gst_static_pad_template_get (&gst_alpha_sink_template));
275 gst_element_class_add_pad_template (gstelement_class,
276 gst_static_pad_template_get (&gst_alpha_src_template));
278 btrans_class->before_transform =
279 GST_DEBUG_FUNCPTR (gst_alpha_before_transform);
280 btrans_class->transform_caps = GST_DEBUG_FUNCPTR (gst_alpha_transform_caps);
282 vfilter_class->set_info = GST_DEBUG_FUNCPTR (gst_alpha_set_info);
283 vfilter_class->transform_frame =
284 GST_DEBUG_FUNCPTR (gst_alpha_transform_frame);
288 gst_alpha_init (GstAlpha * alpha)
290 alpha->alpha = DEFAULT_ALPHA;
291 alpha->method = DEFAULT_METHOD;
292 alpha->target_r = DEFAULT_TARGET_R;
293 alpha->target_g = DEFAULT_TARGET_G;
294 alpha->target_b = DEFAULT_TARGET_B;
295 alpha->angle = DEFAULT_ANGLE;
296 alpha->noise_level = DEFAULT_NOISE_LEVEL;
297 alpha->black_sensitivity = DEFAULT_BLACK_SENSITIVITY;
298 alpha->white_sensitivity = DEFAULT_WHITE_SENSITIVITY;
300 g_mutex_init (&alpha->lock);
304 gst_alpha_finalize (GObject * object)
306 GstAlpha *alpha = GST_ALPHA (object);
308 g_mutex_clear (&alpha->lock);
310 G_OBJECT_CLASS (parent_class)->finalize (object);
314 gst_alpha_set_property (GObject * object, guint prop_id,
315 const GValue * value, GParamSpec * pspec)
317 GstAlpha *alpha = GST_ALPHA (object);
318 gboolean reconfigure = FALSE;
320 GST_ALPHA_LOCK (alpha);
323 gint method = g_value_get_enum (value);
325 reconfigure = (method != alpha->method) && (method == ALPHA_METHOD_SET
326 || alpha->method == ALPHA_METHOD_SET) && (alpha->alpha == 1.0)
327 && (alpha->prefer_passthrough);
328 alpha->method = method;
330 gst_alpha_set_process_function (alpha);
331 gst_alpha_init_params (alpha);
335 gdouble a = g_value_get_double (value);
337 reconfigure = (a != alpha->alpha) && (a == 1.0 || alpha->alpha == 1.0)
338 && (alpha->method == ALPHA_METHOD_SET) && (alpha->prefer_passthrough);
343 alpha->target_r = g_value_get_uint (value);
344 gst_alpha_init_params (alpha);
347 alpha->target_g = g_value_get_uint (value);
348 gst_alpha_init_params (alpha);
351 alpha->target_b = g_value_get_uint (value);
352 gst_alpha_init_params (alpha);
355 alpha->angle = g_value_get_float (value);
356 gst_alpha_init_params (alpha);
358 case PROP_NOISE_LEVEL:
359 alpha->noise_level = g_value_get_float (value);
360 gst_alpha_init_params (alpha);
362 case PROP_BLACK_SENSITIVITY:
363 alpha->black_sensitivity = g_value_get_uint (value);
365 case PROP_WHITE_SENSITIVITY:
366 alpha->white_sensitivity = g_value_get_uint (value);
368 case PROP_PREFER_PASSTHROUGH:{
369 gboolean prefer_passthrough = g_value_get_boolean (value);
371 reconfigure = ((! !prefer_passthrough) != (! !alpha->prefer_passthrough))
372 && (alpha->method == ALPHA_METHOD_SET) && (alpha->alpha == 1.0);
373 alpha->prefer_passthrough = prefer_passthrough;
377 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
382 gst_base_transform_reconfigure_src (GST_BASE_TRANSFORM_CAST (alpha));
384 GST_ALPHA_UNLOCK (alpha);
388 gst_alpha_get_property (GObject * object, guint prop_id, GValue * value,
391 GstAlpha *alpha = GST_ALPHA (object);
395 g_value_set_enum (value, alpha->method);
398 g_value_set_double (value, alpha->alpha);
401 g_value_set_uint (value, alpha->target_r);
404 g_value_set_uint (value, alpha->target_g);
407 g_value_set_uint (value, alpha->target_b);
410 g_value_set_float (value, alpha->angle);
412 case PROP_NOISE_LEVEL:
413 g_value_set_float (value, alpha->noise_level);
415 case PROP_BLACK_SENSITIVITY:
416 g_value_set_uint (value, alpha->black_sensitivity);
418 case PROP_WHITE_SENSITIVITY:
419 g_value_set_uint (value, alpha->white_sensitivity);
421 case PROP_PREFER_PASSTHROUGH:
422 g_value_set_boolean (value, alpha->prefer_passthrough);
425 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
431 gst_alpha_transform_caps (GstBaseTransform * btrans,
432 GstPadDirection direction, GstCaps * caps, GstCaps * filter)
434 GstAlpha *alpha = GST_ALPHA (btrans);
435 GstCaps *ret, *tmp, *tmp2;
436 GstStructure *structure;
439 tmp = gst_caps_new_empty ();
441 GST_ALPHA_LOCK (alpha);
442 for (i = 0; i < gst_caps_get_size (caps); i++) {
443 structure = gst_structure_copy (gst_caps_get_structure (caps, i));
445 gst_structure_remove_field (structure, "format");
446 gst_structure_remove_field (structure, "colorimetry");
447 gst_structure_remove_field (structure, "chroma-site");
449 gst_caps_append_structure (tmp, structure);
452 if (direction == GST_PAD_SINK) {
453 tmp2 = gst_static_caps_get (&gst_alpha_alpha_caps);
454 ret = gst_caps_intersect (tmp, tmp2);
455 gst_caps_unref (tmp);
456 gst_caps_unref (tmp2);
460 if (alpha->prefer_passthrough && alpha->method == ALPHA_METHOD_SET
461 && alpha->alpha == 1.0) {
462 ret = gst_caps_copy (caps);
463 gst_caps_append (ret, tmp);
474 GST_DEBUG_OBJECT (alpha,
475 "Transformed %" GST_PTR_FORMAT " -> %" GST_PTR_FORMAT, caps, ret);
478 GstCaps *intersection;
480 GST_DEBUG_OBJECT (alpha, "Using filter caps %" GST_PTR_FORMAT, filter);
482 gst_caps_intersect_full (filter, ret, GST_CAPS_INTERSECT_FIRST);
483 gst_caps_unref (ret);
485 GST_DEBUG_OBJECT (alpha, "Intersection %" GST_PTR_FORMAT, ret);
489 GST_ALPHA_UNLOCK (alpha);
495 gst_alpha_set_info (GstVideoFilter * filter,
496 GstCaps * incaps, GstVideoInfo * in_info, GstCaps * outcaps,
497 GstVideoInfo * out_info)
499 GstAlpha *alpha = GST_ALPHA (filter);
500 gboolean passthrough;
502 GST_ALPHA_LOCK (alpha);
504 alpha->in_sdtv = in_info->colorimetry.matrix == GST_VIDEO_COLOR_MATRIX_BT601;
506 out_info->colorimetry.matrix == GST_VIDEO_COLOR_MATRIX_BT601;
508 passthrough = alpha->prefer_passthrough &&
509 GST_VIDEO_INFO_FORMAT (in_info) == GST_VIDEO_INFO_FORMAT (out_info)
510 && alpha->in_sdtv == alpha->out_sdtv && alpha->method == ALPHA_METHOD_SET
511 && alpha->alpha == 1.0;
513 GST_DEBUG_OBJECT (alpha,
514 "Setting caps %" GST_PTR_FORMAT " -> %" GST_PTR_FORMAT
515 " (passthrough: %d)", incaps, outcaps, passthrough);
516 gst_base_transform_set_passthrough (GST_BASE_TRANSFORM_CAST (filter),
519 if (!gst_alpha_set_process_function_full (alpha, in_info, out_info)
523 gst_alpha_init_params_full (alpha, in_info->finfo, out_info->finfo);
525 GST_ALPHA_UNLOCK (alpha);
532 GST_WARNING_OBJECT (alpha,
533 "No processing function for this caps and no passthrough mode");
534 GST_ALPHA_UNLOCK (alpha);
539 /* based on http://www.cs.utah.edu/~michael/chroma/
542 chroma_keying_yuv (gint a, gint * y, gint * u,
543 gint * v, gint cr, gint cb, gint smin, gint smax, guint8 accept_angle_tg,
544 guint8 accept_angle_ctg, guint8 one_over_kc, guint8 kfgy_scale, gint8 kg,
552 /* too dark or too bright, keep alpha */
553 if (*y < smin || *y > smax)
556 /* Convert foreground to XZ coords where X direction is defined by
558 tmp = ((*u) * cb + (*v) * cr) >> 7;
559 x = CLAMP (tmp, -128, 127);
560 tmp = ((*v) * cb - (*u) * cr) >> 7;
561 z = CLAMP (tmp, -128, 127);
563 /* WARNING: accept angle should never be set greater than "somewhat less
564 than 90 degrees" to avoid dealing with negative/infinite tg. In reality,
565 80 degrees should be enough if foreground is reasonable. If this seems
566 to be a problem, go to alternative ways of checking point position
567 (scalar product or line equations). This angle should not be too small
568 either to avoid infinite ctg (used to suppress foreground without use of
571 tmp = (x * accept_angle_tg) >> 4;
572 tmp = MIN (tmp, 127);
575 /* keep foreground Kfg = 0 */
578 /* Compute Kfg (implicitly) and Kbg, suppress foreground in XZ coord
580 tmp = (z * accept_angle_ctg) >> 4;
581 tmp = CLAMP (tmp, -128, 127);
586 tmp1 = MAX (tmp1, 0);
587 b_alpha = (tmp1 * one_over_kc) / 2;
588 b_alpha = 255 - CLAMP (b_alpha, 0, 255);
589 b_alpha = (a * b_alpha) >> 8;
591 tmp = (tmp1 * kfgy_scale) >> 4;
592 tmp1 = MIN (tmp, 255);
594 *y = (*y < tmp1) ? 0 : *y - tmp1;
596 /* Convert suppressed foreground back to CbCr */
597 tmp = (x1 * cb - y1 * cr) >> 7;
598 *u = CLAMP (tmp, -128, 127);
600 tmp = (x1 * cr + y1 * cb) >> 7;
601 *v = CLAMP (tmp, -128, 127);
603 /* Deal with noise. For now, a circle around the key color with
604 radius of noise_level treated as exact key color. Introduces
607 tmp = z * z + (x - kg) * (x - kg);
608 tmp = MIN (tmp, 0xffff);
610 if (tmp < noise_level2)
616 #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)
619 gst_alpha_set_argb_ayuv (const GstVideoFrame * in_frame,
620 GstVideoFrame * out_frame, GstAlpha * alpha)
622 gint s_alpha = CLAMP ((gint) (alpha->alpha * 256), 0, 256);
631 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
632 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
634 width = GST_VIDEO_FRAME_WIDTH (in_frame);
635 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
637 o[0] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 3);
638 o[1] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 0);
639 o[2] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 1);
640 o[3] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 2);
643 alpha->out_sdtv ? cog_rgb_to_ycbcr_matrix_8bit_sdtv :
644 cog_rgb_to_ycbcr_matrix_8bit_hdtv, 12 * sizeof (gint));
646 for (i = 0; i < height; i++) {
647 for (j = 0; j < width; j++) {
648 dest[0] = (src[o[0]] * s_alpha) >> 8;
650 y = APPLY_MATRIX (matrix, 0, src[o[1]], src[o[2]], src[o[3]]);
651 u = APPLY_MATRIX (matrix, 1, src[o[1]], src[o[2]], src[o[3]]);
652 v = APPLY_MATRIX (matrix, 2, src[o[1]], src[o[2]], src[o[3]]);
665 gst_alpha_chroma_key_argb_ayuv (const GstVideoFrame * in_frame,
666 GstVideoFrame * out_frame, GstAlpha * alpha)
675 gint pa = CLAMP ((gint) (alpha->alpha * 256), 0, 256);
676 gint8 cb = alpha->cb, cr = alpha->cr;
677 gint8 kg = alpha->kg;
678 guint8 accept_angle_tg = alpha->accept_angle_tg;
679 guint8 accept_angle_ctg = alpha->accept_angle_ctg;
680 guint8 one_over_kc = alpha->one_over_kc;
681 guint8 kfgy_scale = alpha->kfgy_scale;
682 guint noise_level2 = alpha->noise_level2;
686 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
687 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
689 width = GST_VIDEO_FRAME_WIDTH (in_frame);
690 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
692 o[0] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 3);
693 o[1] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 0);
694 o[2] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 1);
695 o[3] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 2);
697 smin = 128 - alpha->black_sensitivity;
698 smax = 128 + alpha->white_sensitivity;
701 alpha->out_sdtv ? cog_rgb_to_ycbcr_matrix_8bit_sdtv :
702 cog_rgb_to_ycbcr_matrix_8bit_hdtv, 12 * sizeof (gint));
704 for (i = 0; i < height; i++) {
705 for (j = 0; j < width; j++) {
706 a = (src[o[0]] * pa) >> 8;
711 y = APPLY_MATRIX (matrix, 0, r, g, b);
712 u = APPLY_MATRIX (matrix, 1, r, g, b) - 128;
713 v = APPLY_MATRIX (matrix, 2, r, g, b) - 128;
715 a = chroma_keying_yuv (a, &y, &u, &v, cr, cb,
716 smin, smax, accept_angle_tg, accept_angle_ctg,
717 one_over_kc, kfgy_scale, kg, noise_level2);
734 gst_alpha_set_argb_argb (const GstVideoFrame * in_frame,
735 GstVideoFrame * out_frame, GstAlpha * alpha)
740 gint s_alpha = CLAMP ((gint) (alpha->alpha * 256), 0, 256);
744 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
745 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
747 width = GST_VIDEO_FRAME_WIDTH (in_frame);
748 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
750 p[0] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 3);
751 p[1] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 0);
752 p[2] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 1);
753 p[3] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 2);
755 o[0] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 3);
756 o[1] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 0);
757 o[2] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 1);
758 o[3] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 2);
760 for (i = 0; i < height; i++) {
761 for (j = 0; j < width; j++) {
762 dest[p[0]] = (src[o[0]] * s_alpha) >> 8;
764 dest[p[1]] = src[o[1]];
765 dest[p[2]] = src[o[2]];
766 dest[p[3]] = src[o[3]];
775 gst_alpha_chroma_key_argb_argb (const GstVideoFrame * in_frame,
776 GstVideoFrame * out_frame, GstAlpha * alpha)
785 gint pa = CLAMP ((gint) (alpha->alpha * 256), 0, 256);
786 gint8 cb = alpha->cb, cr = alpha->cr;
787 gint8 kg = alpha->kg;
788 guint8 accept_angle_tg = alpha->accept_angle_tg;
789 guint8 accept_angle_ctg = alpha->accept_angle_ctg;
790 guint8 one_over_kc = alpha->one_over_kc;
791 guint8 kfgy_scale = alpha->kfgy_scale;
792 guint noise_level2 = alpha->noise_level2;
793 gint matrix[12], matrix2[12];
796 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
797 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
799 width = GST_VIDEO_FRAME_WIDTH (in_frame);
800 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
802 p[0] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 3);
803 p[1] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 0);
804 p[2] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 1);
805 p[3] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 2);
807 o[0] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 3);
808 o[1] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 0);
809 o[2] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 1);
810 o[3] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 2);
812 smin = 128 - alpha->black_sensitivity;
813 smax = 128 + alpha->white_sensitivity;
815 memcpy (matrix, cog_rgb_to_ycbcr_matrix_8bit_sdtv, 12 * sizeof (gint));
816 memcpy (matrix2, cog_ycbcr_to_rgb_matrix_8bit_sdtv, 12 * sizeof (gint));
818 for (i = 0; i < height; i++) {
819 for (j = 0; j < width; j++) {
820 a = (src[o[0]] * pa) >> 8;
825 y = APPLY_MATRIX (matrix, 0, r, g, b);
826 u = APPLY_MATRIX (matrix, 1, r, g, b) - 128;
827 v = APPLY_MATRIX (matrix, 2, r, g, b) - 128;
829 a = chroma_keying_yuv (a, &y, &u, &v, cr, cb,
830 smin, smax, accept_angle_tg, accept_angle_ctg,
831 one_over_kc, kfgy_scale, kg, noise_level2);
836 r = APPLY_MATRIX (matrix2, 0, y, u, v);
837 g = APPLY_MATRIX (matrix2, 1, y, u, v);
838 b = APPLY_MATRIX (matrix2, 2, y, u, v);
841 dest[p[1]] = CLAMP (r, 0, 255);
842 dest[p[2]] = CLAMP (g, 0, 255);
843 dest[p[3]] = CLAMP (b, 0, 255);
852 gst_alpha_set_ayuv_argb (const GstVideoFrame * in_frame,
853 GstVideoFrame * out_frame, GstAlpha * alpha)
858 gint s_alpha = CLAMP ((gint) (alpha->alpha * 256), 0, 256);
864 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
865 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
867 width = GST_VIDEO_FRAME_WIDTH (in_frame);
868 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
870 p[0] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 3);
871 p[1] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 0);
872 p[2] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 1);
873 p[3] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 2);
876 alpha->in_sdtv ? cog_ycbcr_to_rgb_matrix_8bit_sdtv :
877 cog_ycbcr_to_rgb_matrix_8bit_hdtv, 12 * sizeof (gint));
879 for (y = 0; y < height; y++) {
880 for (x = 0; x < width; x++) {
881 dest[p[0]] = (src[0] * s_alpha) >> 8;
883 r = APPLY_MATRIX (matrix, 0, src[1], src[2], src[3]);
884 g = APPLY_MATRIX (matrix, 1, src[1], src[2], src[3]);
885 b = APPLY_MATRIX (matrix, 2, src[1], src[2], src[3]);
887 dest[p[1]] = CLAMP (r, 0, 255);
888 dest[p[2]] = CLAMP (g, 0, 255);
889 dest[p[3]] = CLAMP (b, 0, 255);
898 gst_alpha_chroma_key_ayuv_argb (const GstVideoFrame * in_frame,
899 GstVideoFrame * out_frame, GstAlpha * alpha)
908 gint pa = CLAMP ((gint) (alpha->alpha * 256), 0, 256);
909 gint8 cb = alpha->cb, cr = alpha->cr;
910 gint8 kg = alpha->kg;
911 guint8 accept_angle_tg = alpha->accept_angle_tg;
912 guint8 accept_angle_ctg = alpha->accept_angle_ctg;
913 guint8 one_over_kc = alpha->one_over_kc;
914 guint8 kfgy_scale = alpha->kfgy_scale;
915 guint noise_level2 = alpha->noise_level2;
919 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
920 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
922 width = GST_VIDEO_FRAME_WIDTH (in_frame);
923 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
925 p[0] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 3);
926 p[1] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 0);
927 p[2] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 1);
928 p[3] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 2);
930 smin = 128 - alpha->black_sensitivity;
931 smax = 128 + alpha->white_sensitivity;
934 alpha->in_sdtv ? cog_ycbcr_to_rgb_matrix_8bit_sdtv :
935 cog_ycbcr_to_rgb_matrix_8bit_hdtv, 12 * sizeof (gint));
937 for (i = 0; i < height; i++) {
938 for (j = 0; j < width; j++) {
939 a = (src[0] * pa) >> 8;
944 a = chroma_keying_yuv (a, &y, &u, &v, cr, cb,
945 smin, smax, accept_angle_tg, accept_angle_ctg,
946 one_over_kc, kfgy_scale, kg, noise_level2);
951 r = APPLY_MATRIX (matrix, 0, y, u, v);
952 g = APPLY_MATRIX (matrix, 1, y, u, v);
953 b = APPLY_MATRIX (matrix, 2, y, u, v);
956 dest[p[1]] = CLAMP (r, 0, 255);
957 dest[p[2]] = CLAMP (g, 0, 255);
958 dest[p[3]] = CLAMP (b, 0, 255);
967 gst_alpha_set_ayuv_ayuv (const GstVideoFrame * in_frame,
968 GstVideoFrame * out_frame, GstAlpha * alpha)
973 gint s_alpha = CLAMP ((gint) (alpha->alpha * 256), 0, 256);
976 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
977 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
979 width = GST_VIDEO_FRAME_WIDTH (in_frame);
980 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
982 if (alpha->in_sdtv == alpha->out_sdtv) {
983 for (y = 0; y < height; y++) {
984 for (x = 0; x < width; x++) {
985 dest[0] = (src[0] * s_alpha) >> 8;
998 alpha->out_sdtv ? cog_ycbcr_hdtv_to_ycbcr_sdtv_matrix_8bit :
999 cog_ycbcr_sdtv_to_ycbcr_hdtv_matrix_8bit, 12 * sizeof (gint));
1001 for (y = 0; y < height; y++) {
1002 for (x = 0; x < width; x++) {
1003 dest[0] = (src[0] * s_alpha) >> 8;
1004 dest[1] = APPLY_MATRIX (matrix, 0, src[1], src[2], src[3]);
1005 dest[2] = APPLY_MATRIX (matrix, 1, src[1], src[2], src[3]);
1006 dest[3] = APPLY_MATRIX (matrix, 2, src[1], src[2], src[3]);
1016 gst_alpha_chroma_key_ayuv_ayuv (const GstVideoFrame * in_frame,
1017 GstVideoFrame * out_frame, GstAlpha * alpha)
1025 gint pa = CLAMP ((gint) (alpha->alpha * 256), 0, 256);
1026 gint8 cb = alpha->cb, cr = alpha->cr;
1027 gint8 kg = alpha->kg;
1028 guint8 accept_angle_tg = alpha->accept_angle_tg;
1029 guint8 accept_angle_ctg = alpha->accept_angle_ctg;
1030 guint8 one_over_kc = alpha->one_over_kc;
1031 guint8 kfgy_scale = alpha->kfgy_scale;
1032 guint noise_level2 = alpha->noise_level2;
1034 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
1035 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
1037 width = GST_VIDEO_FRAME_WIDTH (in_frame);
1038 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
1040 smin = 128 - alpha->black_sensitivity;
1041 smax = 128 + alpha->white_sensitivity;
1043 if (alpha->in_sdtv == alpha->out_sdtv) {
1044 for (i = 0; i < height; i++) {
1045 for (j = 0; j < width; j++) {
1046 a = (src[0] * pa) >> 8;
1051 a = chroma_keying_yuv (a, &y, &u, &v, cr, cb,
1052 smin, smax, accept_angle_tg, accept_angle_ctg,
1053 one_over_kc, kfgy_scale, kg, noise_level2);
1071 alpha->out_sdtv ? cog_ycbcr_hdtv_to_ycbcr_sdtv_matrix_8bit :
1072 cog_ycbcr_sdtv_to_ycbcr_hdtv_matrix_8bit, 12 * sizeof (gint));
1074 for (i = 0; i < height; i++) {
1075 for (j = 0; j < width; j++) {
1076 a = (src[0] * pa) >> 8;
1077 y = APPLY_MATRIX (matrix, 0, src[1], src[2], src[3]);
1078 u = APPLY_MATRIX (matrix, 1, src[1], src[2], src[3]) - 128;
1079 v = APPLY_MATRIX (matrix, 2, src[1], src[2], src[3]) - 128;
1081 a = chroma_keying_yuv (a, &y, &u, &v, cr, cb,
1082 smin, smax, accept_angle_tg, accept_angle_ctg,
1083 one_over_kc, kfgy_scale, kg, noise_level2);
1101 gst_alpha_set_rgb_ayuv (const GstVideoFrame * in_frame,
1102 GstVideoFrame * out_frame, GstAlpha * alpha)
1107 gint s_alpha = CLAMP ((gint) (alpha->alpha * 255), 0, 255);
1114 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
1115 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
1117 width = GST_VIDEO_FRAME_WIDTH (in_frame);
1118 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
1120 bpp = GST_VIDEO_FRAME_COMP_PSTRIDE (in_frame, 0);
1121 o[0] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 0);
1122 o[1] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 1);
1123 o[2] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 2);
1126 alpha->out_sdtv ? cog_rgb_to_ycbcr_matrix_8bit_sdtv :
1127 cog_rgb_to_ycbcr_matrix_8bit_hdtv, 12 * sizeof (gint));
1129 for (i = 0; i < height; i++) {
1130 for (j = 0; j < width; j++) {
1133 y = APPLY_MATRIX (matrix, 0, src[o[0]], src[o[1]], src[o[2]]);
1134 u = APPLY_MATRIX (matrix, 1, src[o[0]], src[o[1]], src[o[2]]);
1135 v = APPLY_MATRIX (matrix, 2, src[o[0]], src[o[1]], src[o[2]]);
1148 gst_alpha_chroma_key_rgb_ayuv (const GstVideoFrame * in_frame,
1149 GstVideoFrame * out_frame, GstAlpha * alpha)
1158 gint pa = CLAMP ((gint) (alpha->alpha * 255), 0, 255);
1159 gint8 cb = alpha->cb, cr = alpha->cr;
1160 gint8 kg = alpha->kg;
1161 guint8 accept_angle_tg = alpha->accept_angle_tg;
1162 guint8 accept_angle_ctg = alpha->accept_angle_ctg;
1163 guint8 one_over_kc = alpha->one_over_kc;
1164 guint8 kfgy_scale = alpha->kfgy_scale;
1165 guint noise_level2 = alpha->noise_level2;
1170 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
1171 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
1173 width = GST_VIDEO_FRAME_WIDTH (in_frame);
1174 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
1176 bpp = GST_VIDEO_FRAME_COMP_PSTRIDE (in_frame, 0);
1178 o[0] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 0);
1179 o[1] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 1);
1180 o[2] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 2);
1182 smin = 128 - alpha->black_sensitivity;
1183 smax = 128 + alpha->white_sensitivity;
1186 alpha->out_sdtv ? cog_rgb_to_ycbcr_matrix_8bit_sdtv :
1187 cog_rgb_to_ycbcr_matrix_8bit_hdtv, 12 * sizeof (gint));
1189 for (i = 0; i < height; i++) {
1190 for (j = 0; j < width; j++) {
1196 y = APPLY_MATRIX (matrix, 0, r, g, b);
1197 u = APPLY_MATRIX (matrix, 1, r, g, b) - 128;
1198 v = APPLY_MATRIX (matrix, 2, r, g, b) - 128;
1200 a = chroma_keying_yuv (a, &y, &u, &v, cr, cb,
1201 smin, smax, accept_angle_tg, accept_angle_ctg,
1202 one_over_kc, kfgy_scale, kg, noise_level2);
1219 gst_alpha_set_rgb_argb (const GstVideoFrame * in_frame,
1220 GstVideoFrame * out_frame, GstAlpha * alpha)
1225 gint s_alpha = CLAMP ((gint) (alpha->alpha * 255), 0, 255);
1230 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
1231 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
1233 width = GST_VIDEO_FRAME_WIDTH (in_frame);
1234 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
1236 bpp = GST_VIDEO_FRAME_COMP_PSTRIDE (in_frame, 0);
1238 o[0] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 0);
1239 o[1] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 1);
1240 o[2] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 2);
1242 p[0] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 3);
1243 p[1] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 0);
1244 p[2] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 1);
1245 p[3] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 2);
1247 for (i = 0; i < height; i++) {
1248 for (j = 0; j < width; j++) {
1249 dest[p[0]] = s_alpha;
1251 dest[p[1]] = src[o[0]];
1252 dest[p[2]] = src[o[1]];
1253 dest[p[3]] = src[o[2]];
1262 gst_alpha_chroma_key_rgb_argb (const GstVideoFrame * in_frame,
1263 GstVideoFrame * out_frame, GstAlpha * alpha)
1272 gint pa = CLAMP ((gint) (alpha->alpha * 255), 0, 255);
1273 gint8 cb = alpha->cb, cr = alpha->cr;
1274 gint8 kg = alpha->kg;
1275 guint8 accept_angle_tg = alpha->accept_angle_tg;
1276 guint8 accept_angle_ctg = alpha->accept_angle_ctg;
1277 guint8 one_over_kc = alpha->one_over_kc;
1278 guint8 kfgy_scale = alpha->kfgy_scale;
1279 guint noise_level2 = alpha->noise_level2;
1280 gint matrix[12], matrix2[12];
1284 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
1285 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
1287 width = GST_VIDEO_FRAME_WIDTH (in_frame);
1288 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
1290 bpp = GST_VIDEO_FRAME_COMP_PSTRIDE (in_frame, 0);
1292 o[0] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 0);
1293 o[1] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 1);
1294 o[2] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 2);
1296 p[0] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 3);
1297 p[1] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 0);
1298 p[2] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 1);
1299 p[3] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 2);
1301 smin = 128 - alpha->black_sensitivity;
1302 smax = 128 + alpha->white_sensitivity;
1304 memcpy (matrix, cog_rgb_to_ycbcr_matrix_8bit_sdtv, 12 * sizeof (gint));
1305 memcpy (matrix2, cog_ycbcr_to_rgb_matrix_8bit_sdtv, 12 * sizeof (gint));
1307 for (i = 0; i < height; i++) {
1308 for (j = 0; j < width; j++) {
1314 y = APPLY_MATRIX (matrix, 0, r, g, b);
1315 u = APPLY_MATRIX (matrix, 1, r, g, b) - 128;
1316 v = APPLY_MATRIX (matrix, 2, r, g, b) - 128;
1318 a = chroma_keying_yuv (a, &y, &u, &v, cr, cb,
1319 smin, smax, accept_angle_tg, accept_angle_ctg,
1320 one_over_kc, kfgy_scale, kg, noise_level2);
1325 r = APPLY_MATRIX (matrix2, 0, y, u, v);
1326 g = APPLY_MATRIX (matrix2, 1, y, u, v);
1327 b = APPLY_MATRIX (matrix2, 2, y, u, v);
1330 dest[p[1]] = CLAMP (r, 0, 255);
1331 dest[p[2]] = CLAMP (g, 0, 255);
1332 dest[p[3]] = CLAMP (b, 0, 255);
1341 gst_alpha_set_planar_yuv_ayuv (const GstVideoFrame * in_frame,
1342 GstVideoFrame * out_frame, GstAlpha * alpha)
1347 gint b_alpha = CLAMP ((gint) (alpha->alpha * 255), 0, 255);
1348 const guint8 *srcY, *srcY_tmp;
1349 const guint8 *srcU, *srcU_tmp;
1350 const guint8 *srcV, *srcV_tmp;
1352 gint y_stride, uv_stride;
1353 gint v_subs, h_subs;
1355 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
1356 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
1358 width = GST_VIDEO_FRAME_WIDTH (in_frame);
1359 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
1361 y_stride = GST_VIDEO_FRAME_COMP_STRIDE (in_frame, 0);
1362 uv_stride = GST_VIDEO_FRAME_COMP_STRIDE (in_frame, 1);
1364 srcY_tmp = srcY = src;
1365 srcU_tmp = srcU = src + GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 1);
1366 srcV_tmp = srcV = src + GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 2);
1368 switch (GST_VIDEO_FRAME_FORMAT (in_frame)) {
1369 case GST_VIDEO_FORMAT_I420:
1370 case GST_VIDEO_FORMAT_YV12:
1371 v_subs = h_subs = 2;
1373 case GST_VIDEO_FORMAT_Y444:
1374 v_subs = h_subs = 1;
1376 case GST_VIDEO_FORMAT_Y42B:
1380 case GST_VIDEO_FORMAT_Y41B:
1385 g_assert_not_reached ();
1389 if (alpha->in_sdtv == alpha->out_sdtv) {
1390 for (i = 0; i < height; i++) {
1391 for (j = 0; j < width; j++) {
1399 if ((j + 1) % h_subs == 0) {
1405 srcY_tmp = srcY = srcY_tmp + y_stride;
1406 if ((i + 1) % v_subs == 0) {
1407 srcU_tmp = srcU = srcU_tmp + uv_stride;
1408 srcV_tmp = srcV = srcV_tmp + uv_stride;
1419 alpha->out_sdtv ? cog_ycbcr_hdtv_to_ycbcr_sdtv_matrix_8bit :
1420 cog_ycbcr_sdtv_to_ycbcr_hdtv_matrix_8bit, 12 * sizeof (gint));
1422 for (i = 0; i < height; i++) {
1423 for (j = 0; j < width; j++) {
1430 dest[1] = APPLY_MATRIX (matrix, 0, y, u, v);
1431 dest[2] = APPLY_MATRIX (matrix, 1, y, u, v);
1432 dest[3] = APPLY_MATRIX (matrix, 2, y, u, v);
1436 if ((j + 1) % h_subs == 0) {
1442 srcY_tmp = srcY = srcY_tmp + y_stride;
1443 if ((i + 1) % v_subs == 0) {
1444 srcU_tmp = srcU = srcU_tmp + uv_stride;
1445 srcV_tmp = srcV = srcV_tmp + uv_stride;
1455 gst_alpha_chroma_key_planar_yuv_ayuv (const GstVideoFrame * in_frame,
1456 GstVideoFrame * out_frame, GstAlpha * alpha)
1461 gint b_alpha = CLAMP ((gint) (alpha->alpha * 255), 0, 255);
1462 const guint8 *srcY, *srcY_tmp;
1463 const guint8 *srcU, *srcU_tmp;
1464 const guint8 *srcV, *srcV_tmp;
1467 gint y_stride, uv_stride;
1468 gint v_subs, h_subs;
1469 gint smin = 128 - alpha->black_sensitivity;
1470 gint smax = 128 + alpha->white_sensitivity;
1471 gint8 cb = alpha->cb, cr = alpha->cr;
1472 gint8 kg = alpha->kg;
1473 guint8 accept_angle_tg = alpha->accept_angle_tg;
1474 guint8 accept_angle_ctg = alpha->accept_angle_ctg;
1475 guint8 one_over_kc = alpha->one_over_kc;
1476 guint8 kfgy_scale = alpha->kfgy_scale;
1477 guint noise_level2 = alpha->noise_level2;
1479 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
1480 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
1482 width = GST_VIDEO_FRAME_WIDTH (in_frame);
1483 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
1485 y_stride = GST_VIDEO_FRAME_COMP_STRIDE (in_frame, 0);
1486 uv_stride = GST_VIDEO_FRAME_COMP_STRIDE (in_frame, 1);
1488 srcY_tmp = srcY = src;
1489 srcU_tmp = srcU = src + GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 1);
1490 srcV_tmp = srcV = src + GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 2);
1492 switch (GST_VIDEO_FRAME_FORMAT (in_frame)) {
1493 case GST_VIDEO_FORMAT_I420:
1494 case GST_VIDEO_FORMAT_YV12:
1495 v_subs = h_subs = 2;
1497 case GST_VIDEO_FORMAT_Y444:
1498 v_subs = h_subs = 1;
1500 case GST_VIDEO_FORMAT_Y42B:
1504 case GST_VIDEO_FORMAT_Y41B:
1509 g_assert_not_reached ();
1513 if (alpha->in_sdtv == alpha->out_sdtv) {
1514 for (i = 0; i < height; i++) {
1515 for (j = 0; j < width; j++) {
1521 a = chroma_keying_yuv (a, &y, &u, &v, cr, cb, smin,
1522 smax, accept_angle_tg, accept_angle_ctg,
1523 one_over_kc, kfgy_scale, kg, noise_level2);
1535 if ((j + 1) % h_subs == 0) {
1541 srcY_tmp = srcY = srcY_tmp + y_stride;
1542 if ((i + 1) % v_subs == 0) {
1543 srcU_tmp = srcU = srcU_tmp + uv_stride;
1544 srcV_tmp = srcV = srcV_tmp + uv_stride;
1554 alpha->out_sdtv ? cog_ycbcr_hdtv_to_ycbcr_sdtv_matrix_8bit :
1555 cog_ycbcr_sdtv_to_ycbcr_hdtv_matrix_8bit, 12 * sizeof (gint));
1557 for (i = 0; i < height; i++) {
1558 for (j = 0; j < width; j++) {
1560 y = APPLY_MATRIX (matrix, 0, srcY[0], srcU[0], srcV[0]);
1561 u = APPLY_MATRIX (matrix, 1, srcY[0], srcU[0], srcV[0]) - 128;
1562 v = APPLY_MATRIX (matrix, 2, srcY[0], srcU[0], srcV[0]) - 128;
1564 a = chroma_keying_yuv (a, &y, &u, &v, cr, cb, smin,
1565 smax, accept_angle_tg, accept_angle_ctg,
1566 one_over_kc, kfgy_scale, kg, noise_level2);
1575 if ((j + 1) % h_subs == 0) {
1581 srcY_tmp = srcY = srcY_tmp + y_stride;
1582 if ((i + 1) % v_subs == 0) {
1583 srcU_tmp = srcU = srcU_tmp + uv_stride;
1584 srcV_tmp = srcV = srcV_tmp + uv_stride;
1594 gst_alpha_set_planar_yuv_argb (const GstVideoFrame * in_frame,
1595 GstVideoFrame * out_frame, GstAlpha * alpha)
1600 gint b_alpha = CLAMP ((gint) (alpha->alpha * 255), 0, 255);
1601 const guint8 *srcY, *srcY_tmp;
1602 const guint8 *srcU, *srcU_tmp;
1603 const guint8 *srcV, *srcV_tmp;
1605 gint y_stride, uv_stride;
1606 gint v_subs, h_subs;
1612 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
1613 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
1615 width = GST_VIDEO_FRAME_WIDTH (in_frame);
1616 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
1618 p[0] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 3);
1619 p[1] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 0);
1620 p[2] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 1);
1621 p[3] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 2);
1623 y_stride = GST_VIDEO_FRAME_COMP_STRIDE (in_frame, 0);
1624 uv_stride = GST_VIDEO_FRAME_COMP_STRIDE (in_frame, 1);
1626 srcY_tmp = srcY = src;
1627 srcU_tmp = srcU = src + GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 1);
1628 srcV_tmp = srcV = src + GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 2);
1630 switch (GST_VIDEO_FRAME_FORMAT (in_frame)) {
1631 case GST_VIDEO_FORMAT_I420:
1632 case GST_VIDEO_FORMAT_YV12:
1633 v_subs = h_subs = 2;
1635 case GST_VIDEO_FORMAT_Y444:
1636 v_subs = h_subs = 1;
1638 case GST_VIDEO_FORMAT_Y42B:
1642 case GST_VIDEO_FORMAT_Y41B:
1647 g_assert_not_reached ();
1652 alpha->in_sdtv ? cog_ycbcr_to_rgb_matrix_8bit_sdtv :
1653 cog_ycbcr_to_rgb_matrix_8bit_hdtv, 12 * sizeof (gint));
1655 for (i = 0; i < height; i++) {
1656 for (j = 0; j < width; j++) {
1663 r = APPLY_MATRIX (matrix, 0, y, u, v);
1664 g = APPLY_MATRIX (matrix, 1, y, u, v);
1665 b = APPLY_MATRIX (matrix, 2, y, u, v);
1666 dest[p[1]] = CLAMP (r, 0, 255);
1667 dest[p[2]] = CLAMP (g, 0, 255);
1668 dest[p[3]] = CLAMP (b, 0, 255);
1672 if ((j + 1) % h_subs == 0) {
1678 srcY_tmp = srcY = srcY_tmp + y_stride;
1679 if ((i + 1) % v_subs == 0) {
1680 srcU_tmp = srcU = srcU_tmp + uv_stride;
1681 srcV_tmp = srcV = srcV_tmp + uv_stride;
1690 gst_alpha_chroma_key_planar_yuv_argb (const GstVideoFrame * in_frame,
1691 GstVideoFrame * out_frame, GstAlpha * alpha)
1696 gint b_alpha = CLAMP ((gint) (alpha->alpha * 255), 0, 255);
1697 const guint8 *srcY, *srcY_tmp;
1698 const guint8 *srcU, *srcU_tmp;
1699 const guint8 *srcV, *srcV_tmp;
1703 gint y_stride, uv_stride;
1704 gint v_subs, h_subs;
1705 gint smin = 128 - alpha->black_sensitivity;
1706 gint smax = 128 + alpha->white_sensitivity;
1707 gint8 cb = alpha->cb, cr = alpha->cr;
1708 gint8 kg = alpha->kg;
1709 guint8 accept_angle_tg = alpha->accept_angle_tg;
1710 guint8 accept_angle_ctg = alpha->accept_angle_ctg;
1711 guint8 one_over_kc = alpha->one_over_kc;
1712 guint8 kfgy_scale = alpha->kfgy_scale;
1713 guint noise_level2 = alpha->noise_level2;
1717 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
1718 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
1720 width = GST_VIDEO_FRAME_WIDTH (in_frame);
1721 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
1723 p[0] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 3);
1724 p[1] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 0);
1725 p[2] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 1);
1726 p[3] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 2);
1728 y_stride = GST_VIDEO_FRAME_COMP_STRIDE (in_frame, 0);
1729 uv_stride = GST_VIDEO_FRAME_COMP_STRIDE (in_frame, 1);
1731 srcY_tmp = srcY = src;
1732 srcU_tmp = srcU = src + GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 1);
1733 srcV_tmp = srcV = src + GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 2);
1735 switch (GST_VIDEO_FRAME_FORMAT (in_frame)) {
1736 case GST_VIDEO_FORMAT_I420:
1737 case GST_VIDEO_FORMAT_YV12:
1738 v_subs = h_subs = 2;
1740 case GST_VIDEO_FORMAT_Y444:
1741 v_subs = h_subs = 1;
1743 case GST_VIDEO_FORMAT_Y42B:
1747 case GST_VIDEO_FORMAT_Y41B:
1752 g_assert_not_reached ();
1757 alpha->in_sdtv ? cog_ycbcr_to_rgb_matrix_8bit_sdtv :
1758 cog_ycbcr_to_rgb_matrix_8bit_hdtv, 12 * sizeof (gint));
1760 for (i = 0; i < height; i++) {
1761 for (j = 0; j < width; j++) {
1767 a = chroma_keying_yuv (a, &y, &u, &v, cr, cb, smin,
1768 smax, accept_angle_tg, accept_angle_ctg,
1769 one_over_kc, kfgy_scale, kg, noise_level2);
1775 r = APPLY_MATRIX (matrix, 0, y, u, v);
1776 g = APPLY_MATRIX (matrix, 1, y, u, v);
1777 b = APPLY_MATRIX (matrix, 2, y, u, v);
1778 dest[p[1]] = CLAMP (r, 0, 255);
1779 dest[p[2]] = CLAMP (g, 0, 255);
1780 dest[p[3]] = CLAMP (b, 0, 255);
1784 if ((j + 1) % h_subs == 0) {
1790 srcY_tmp = srcY = srcY_tmp + y_stride;
1791 if ((i + 1) % v_subs == 0) {
1792 srcU_tmp = srcU = srcU_tmp + uv_stride;
1793 srcV_tmp = srcV = srcV_tmp + uv_stride;
1802 gst_alpha_set_packed_422_ayuv (const GstVideoFrame * in_frame,
1803 GstVideoFrame * out_frame, GstAlpha * alpha)
1808 gint s_alpha = CLAMP ((gint) (alpha->alpha * 255), 0, 255);
1811 gint p[4]; /* Y U Y V */
1813 const guint8 *src_tmp;
1815 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
1816 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
1818 width = GST_VIDEO_FRAME_WIDTH (in_frame);
1819 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
1821 src_stride = GST_VIDEO_FRAME_COMP_STRIDE (in_frame, 0);
1823 p[0] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 0);
1825 p[1] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 1);
1826 p[3] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 2);
1828 if (alpha->in_sdtv != alpha->out_sdtv) {
1832 alpha->in_sdtv ? cog_ycbcr_sdtv_to_ycbcr_hdtv_matrix_8bit :
1833 cog_ycbcr_hdtv_to_ycbcr_sdtv_matrix_8bit, 12 * sizeof (gint));
1835 for (i = 0; i < height; i++) {
1838 for (j = 0; j < width - 1; j += 2) {
1842 y = APPLY_MATRIX (matrix, 0, src[p[0]], src[p[1]], src[p[3]]);
1843 u = APPLY_MATRIX (matrix, 1, src[p[0]], src[p[1]], src[p[3]]);
1844 v = APPLY_MATRIX (matrix, 2, src[p[0]], src[p[1]], src[p[3]]);
1850 y = APPLY_MATRIX (matrix, 0, src[p[2]], src[p[1]], src[p[3]]);
1851 u = APPLY_MATRIX (matrix, 1, src[p[2]], src[p[1]], src[p[3]]);
1852 v = APPLY_MATRIX (matrix, 2, src[p[2]], src[p[1]], src[p[3]]);
1862 if (j == width - 1) {
1865 y = APPLY_MATRIX (matrix, 0, src[p[0]], src[p[1]], src[p[3]]);
1866 u = APPLY_MATRIX (matrix, 1, src[p[0]], src[p[1]], src[p[3]]);
1867 v = APPLY_MATRIX (matrix, 2, src[p[0]], src[p[1]], src[p[3]]);
1876 src = src_tmp + src_stride;
1879 for (i = 0; i < height; i++) {
1882 for (j = 0; j < width - 1; j += 2) {
1904 if (j == width - 1) {
1918 src = src_tmp + src_stride;
1924 gst_alpha_chroma_key_packed_422_ayuv (const GstVideoFrame * in_frame,
1925 GstVideoFrame * out_frame, GstAlpha * alpha)
1933 gint pa = CLAMP ((gint) (alpha->alpha * 255), 0, 255);
1934 gint8 cb = alpha->cb, cr = alpha->cr;
1935 gint8 kg = alpha->kg;
1936 guint8 accept_angle_tg = alpha->accept_angle_tg;
1937 guint8 accept_angle_ctg = alpha->accept_angle_ctg;
1938 guint8 one_over_kc = alpha->one_over_kc;
1939 guint8 kfgy_scale = alpha->kfgy_scale;
1940 guint noise_level2 = alpha->noise_level2;
1941 gint p[4]; /* Y U Y V */
1943 const guint8 *src_tmp;
1945 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
1946 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
1948 width = GST_VIDEO_FRAME_WIDTH (in_frame);
1949 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
1951 src_stride = GST_VIDEO_FRAME_COMP_STRIDE (in_frame, 0);
1953 p[0] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 0);
1955 p[1] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 1);
1956 p[3] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 2);
1958 smin = 128 - alpha->black_sensitivity;
1959 smax = 128 + alpha->white_sensitivity;
1961 if (alpha->in_sdtv != alpha->out_sdtv) {
1965 alpha->in_sdtv ? cog_ycbcr_sdtv_to_ycbcr_hdtv_matrix_8bit :
1966 cog_ycbcr_hdtv_to_ycbcr_sdtv_matrix_8bit, 12 * sizeof (gint));
1968 for (i = 0; i < height; i++) {
1971 for (j = 0; j < width - 1; j += 2) {
1972 y = APPLY_MATRIX (matrix, 0, src[p[0]], src[p[1]], src[p[3]]);
1973 u = APPLY_MATRIX (matrix, 1, src[p[0]], src[p[1]], src[p[3]]) - 128;
1974 v = APPLY_MATRIX (matrix, 2, src[p[0]], src[p[1]], src[p[3]]) - 128;
1976 a = chroma_keying_yuv (pa, &y, &u, &v, cr, cb,
1977 smin, smax, accept_angle_tg, accept_angle_ctg,
1978 one_over_kc, kfgy_scale, kg, noise_level2);
1985 y = APPLY_MATRIX (matrix, 0, src[p[2]], src[p[1]], src[p[3]]);
1986 u = APPLY_MATRIX (matrix, 1, src[p[2]], src[p[1]], src[p[3]]) - 128;
1987 v = APPLY_MATRIX (matrix, 2, src[p[2]], src[p[1]], src[p[3]]) - 128;
1989 a = chroma_keying_yuv (pa, &y, &u, &v, cr, cb,
1990 smin, smax, accept_angle_tg, accept_angle_ctg,
1991 one_over_kc, kfgy_scale, kg, noise_level2);
2002 if (j == width - 1) {
2003 y = APPLY_MATRIX (matrix, 0, src[p[0]], src[p[1]], src[p[3]]);
2004 u = APPLY_MATRIX (matrix, 1, src[p[0]], src[p[1]], src[p[3]]) - 128;
2005 v = APPLY_MATRIX (matrix, 2, src[p[0]], src[p[1]], src[p[3]]) - 128;
2007 a = chroma_keying_yuv (pa, &y, &u, &v, cr, cb,
2008 smin, smax, accept_angle_tg, accept_angle_ctg,
2009 one_over_kc, kfgy_scale, kg, noise_level2);
2019 src = src_tmp + src_stride;
2022 for (i = 0; i < height; i++) {
2025 for (j = 0; j < width - 1; j += 2) {
2027 u = src[p[1]] - 128;
2028 v = src[p[3]] - 128;
2030 a = chroma_keying_yuv (pa, &y, &u, &v, cr, cb,
2031 smin, smax, accept_angle_tg, accept_angle_ctg,
2032 one_over_kc, kfgy_scale, kg, noise_level2);
2040 u = src[p[1]] - 128;
2041 v = src[p[3]] - 128;
2043 a = chroma_keying_yuv (pa, &y, &u, &v, cr, cb,
2044 smin, smax, accept_angle_tg, accept_angle_ctg,
2045 one_over_kc, kfgy_scale, kg, noise_level2);
2056 if (j == width - 1) {
2058 u = src[p[1]] - 128;
2059 v = src[p[3]] - 128;
2061 a = chroma_keying_yuv (pa, &y, &u, &v, cr, cb,
2062 smin, smax, accept_angle_tg, accept_angle_ctg,
2063 one_over_kc, kfgy_scale, kg, noise_level2);
2073 src = src_tmp + src_stride;
2079 gst_alpha_set_packed_422_argb (const GstVideoFrame * in_frame,
2080 GstVideoFrame * out_frame, GstAlpha * alpha)
2085 gint s_alpha = CLAMP ((gint) (alpha->alpha * 255), 0, 255);
2089 const guint8 *src_tmp;
2093 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
2094 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
2096 width = GST_VIDEO_FRAME_WIDTH (in_frame);
2097 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
2099 src_stride = GST_VIDEO_FRAME_COMP_STRIDE (in_frame, 0);
2101 o[0] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 0);
2103 o[1] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 1);
2104 o[3] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 2);
2106 p[0] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 3);
2107 p[1] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 0);
2108 p[2] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 1);
2109 p[3] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 2);
2112 alpha->in_sdtv ? cog_ycbcr_to_rgb_matrix_8bit_sdtv :
2113 cog_ycbcr_to_rgb_matrix_8bit_hdtv, 12 * sizeof (gint));
2115 for (i = 0; i < height; i++) {
2118 for (j = 0; j < width - 1; j += 2) {
2119 r = APPLY_MATRIX (matrix, 0, src[o[0]], src[o[1]], src[o[3]]);
2120 g = APPLY_MATRIX (matrix, 1, src[o[0]], src[o[1]], src[o[3]]);
2121 b = APPLY_MATRIX (matrix, 2, src[o[0]], src[o[1]], src[o[3]]);
2123 dest[p[0]] = s_alpha;
2124 dest[p[1]] = CLAMP (r, 0, 255);
2125 dest[p[2]] = CLAMP (g, 0, 255);
2126 dest[p[3]] = CLAMP (b, 0, 255);
2128 r = APPLY_MATRIX (matrix, 0, src[o[2]], src[o[1]], src[o[3]]);
2129 g = APPLY_MATRIX (matrix, 1, src[o[2]], src[o[1]], src[o[3]]);
2130 b = APPLY_MATRIX (matrix, 2, src[o[2]], src[o[1]], src[o[3]]);
2132 dest[4 + p[0]] = s_alpha;
2133 dest[4 + p[1]] = CLAMP (r, 0, 255);
2134 dest[4 + p[2]] = CLAMP (g, 0, 255);
2135 dest[4 + p[3]] = CLAMP (b, 0, 255);
2141 if (j == width - 1) {
2142 r = APPLY_MATRIX (matrix, 0, src[o[0]], src[o[1]], src[o[3]]);
2143 g = APPLY_MATRIX (matrix, 1, src[o[0]], src[o[1]], src[o[3]]);
2144 b = APPLY_MATRIX (matrix, 2, src[o[0]], src[o[1]], src[o[3]]);
2146 dest[p[0]] = s_alpha;
2147 dest[p[1]] = CLAMP (r, 0, 255);
2148 dest[p[2]] = CLAMP (g, 0, 255);
2149 dest[p[3]] = CLAMP (b, 0, 255);
2154 src = src_tmp + src_stride;
2159 gst_alpha_chroma_key_packed_422_argb (const GstVideoFrame * in_frame,
2160 GstVideoFrame * out_frame, GstAlpha * alpha)
2169 gint pa = CLAMP ((gint) (alpha->alpha * 255), 0, 255);
2170 gint8 cb = alpha->cb, cr = alpha->cr;
2171 gint8 kg = alpha->kg;
2172 guint8 accept_angle_tg = alpha->accept_angle_tg;
2173 guint8 accept_angle_ctg = alpha->accept_angle_ctg;
2174 guint8 one_over_kc = alpha->one_over_kc;
2175 guint8 kfgy_scale = alpha->kfgy_scale;
2176 guint noise_level2 = alpha->noise_level2;
2179 const guint8 *src_tmp;
2182 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
2183 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
2185 width = GST_VIDEO_FRAME_WIDTH (in_frame);
2186 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
2188 src_stride = GST_VIDEO_FRAME_COMP_STRIDE (in_frame, 0);
2190 o[0] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 0);
2192 o[1] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 1);
2193 o[3] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 2);
2195 p[0] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 3);
2196 p[1] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 0);
2197 p[2] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 1);
2198 p[3] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 2);
2201 alpha->in_sdtv ? cog_ycbcr_to_rgb_matrix_8bit_sdtv :
2202 cog_ycbcr_to_rgb_matrix_8bit_hdtv, 12 * sizeof (gint));
2204 smin = 128 - alpha->black_sensitivity;
2205 smax = 128 + alpha->white_sensitivity;
2207 for (i = 0; i < height; i++) {
2210 for (j = 0; j < width - 1; j += 2) {
2212 u = src[o[1]] - 128;
2213 v = src[o[3]] - 128;
2215 a = chroma_keying_yuv (pa, &y, &u, &v, cr, cb,
2216 smin, smax, accept_angle_tg, accept_angle_ctg,
2217 one_over_kc, kfgy_scale, kg, noise_level2);
2221 r = APPLY_MATRIX (matrix, 0, y, u, v);
2222 g = APPLY_MATRIX (matrix, 1, y, u, v);
2223 b = APPLY_MATRIX (matrix, 2, y, u, v);
2226 dest[p[1]] = CLAMP (r, 0, 255);
2227 dest[p[2]] = CLAMP (g, 0, 255);
2228 dest[p[3]] = CLAMP (b, 0, 255);
2231 u = src[o[1]] - 128;
2232 v = src[o[3]] - 128;
2234 a = chroma_keying_yuv (pa, &y, &u, &v, cr, cb,
2235 smin, smax, accept_angle_tg, accept_angle_ctg,
2236 one_over_kc, kfgy_scale, kg, noise_level2);
2240 r = APPLY_MATRIX (matrix, 0, y, u, v);
2241 g = APPLY_MATRIX (matrix, 1, y, u, v);
2242 b = APPLY_MATRIX (matrix, 2, y, u, v);
2245 dest[4 + p[1]] = CLAMP (r, 0, 255);
2246 dest[4 + p[2]] = CLAMP (g, 0, 255);
2247 dest[4 + p[3]] = CLAMP (b, 0, 255);
2253 if (j == width - 1) {
2255 u = src[o[1]] - 128;
2256 v = src[o[3]] - 128;
2258 a = chroma_keying_yuv (pa, &y, &u, &v, cr, cb,
2259 smin, smax, accept_angle_tg, accept_angle_ctg,
2260 one_over_kc, kfgy_scale, kg, noise_level2);
2264 r = APPLY_MATRIX (matrix, 0, y, u, v);
2265 g = APPLY_MATRIX (matrix, 1, y, u, v);
2266 b = APPLY_MATRIX (matrix, 2, y, u, v);
2269 dest[p[1]] = CLAMP (r, 0, 255);
2270 dest[p[2]] = CLAMP (g, 0, 255);
2271 dest[p[3]] = CLAMP (b, 0, 255);
2276 src = src_tmp + src_stride;
2280 /* Protected with the alpha lock */
2282 gst_alpha_init_params_full (GstAlpha * alpha,
2283 const GstVideoFormatInfo * in_info, const GstVideoFormatInfo * out_info)
2289 guint target_r = alpha->target_r;
2290 guint target_g = alpha->target_g;
2291 guint target_b = alpha->target_b;
2294 switch (alpha->method) {
2295 case ALPHA_METHOD_GREEN:
2300 case ALPHA_METHOD_BLUE:
2309 /* RGB->RGB: convert to SDTV YUV, chroma keying, convert back
2310 * YUV->RGB: chroma keying, convert to RGB
2311 * RGB->YUV: convert to YUV, chroma keying
2312 * YUV->YUV: convert matrix, chroma keying
2314 if (GST_VIDEO_FORMAT_INFO_IS_RGB (in_info)
2315 && GST_VIDEO_FORMAT_INFO_IS_RGB (out_info))
2316 matrix = cog_rgb_to_ycbcr_matrix_8bit_sdtv;
2317 else if (GST_VIDEO_FORMAT_INFO_IS_YUV (in_info)
2318 && GST_VIDEO_FORMAT_INFO_IS_RGB (out_info))
2320 (alpha->in_sdtv) ? cog_rgb_to_ycbcr_matrix_8bit_sdtv :
2321 cog_rgb_to_ycbcr_matrix_8bit_hdtv;
2322 else if (GST_VIDEO_FORMAT_INFO_IS_RGB (in_info)
2323 && GST_VIDEO_FORMAT_INFO_IS_YUV (out_info))
2325 (alpha->out_sdtv) ? cog_rgb_to_ycbcr_matrix_8bit_sdtv :
2326 cog_rgb_to_ycbcr_matrix_8bit_hdtv;
2327 else /* yuv -> yuv */
2329 (alpha->out_sdtv) ? cog_rgb_to_ycbcr_matrix_8bit_sdtv :
2330 cog_rgb_to_ycbcr_matrix_8bit_hdtv;
2332 y = (matrix[0] * ((gint) target_r) +
2333 matrix[1] * ((gint) target_g) +
2334 matrix[2] * ((gint) target_b) + matrix[3]) >> 8;
2335 /* Cb,Cr without offset here because the chroma keying
2336 * works with them being in range [-128,127]
2339 (matrix[4] * ((gint) target_r) +
2340 matrix[5] * ((gint) target_g) + matrix[6] * ((gint) target_b)) >> 8;
2342 (matrix[8] * ((gint) target_r) +
2343 matrix[9] * ((gint) target_g) + matrix[10] * ((gint) target_b)) >> 8;
2345 kgl = sqrt (tmp1 * tmp1 + tmp2 * tmp2);
2346 alpha->cb = 127 * (tmp1 / kgl);
2347 alpha->cr = 127 * (tmp2 / kgl);
2349 tmp = 15 * tan (M_PI * alpha->angle / 180);
2350 tmp = MIN (tmp, 255);
2351 alpha->accept_angle_tg = tmp;
2352 tmp = 15 / tan (M_PI * alpha->angle / 180);
2353 tmp = MIN (tmp, 255);
2354 alpha->accept_angle_ctg = tmp;
2356 alpha->one_over_kc = 255 * 2 * tmp - 255;
2358 tmp = MIN (tmp, 255);
2359 alpha->kfgy_scale = tmp;
2360 alpha->kg = MIN (kgl, 127);
2362 alpha->noise_level2 = alpha->noise_level * alpha->noise_level;
2366 gst_alpha_init_params (GstAlpha * alpha)
2368 const GstVideoFormatInfo *finfo_in, *finfo_out;
2370 finfo_in = GST_VIDEO_FILTER (alpha)->in_info.finfo;
2371 finfo_out = GST_VIDEO_FILTER (alpha)->out_info.finfo;
2373 if (finfo_in != NULL && finfo_out != NULL) {
2374 gst_alpha_init_params_full (alpha, finfo_in, finfo_out);
2376 GST_DEBUG_OBJECT (alpha, "video formats not set yet");
2380 /* Protected with the alpha lock */
2382 gst_alpha_set_process_function_full (GstAlpha * alpha, GstVideoInfo * in_info,
2383 GstVideoInfo * out_info)
2385 alpha->process = NULL;
2387 switch (alpha->method) {
2388 case ALPHA_METHOD_SET:
2389 switch (GST_VIDEO_INFO_FORMAT (out_info)) {
2390 case GST_VIDEO_FORMAT_AYUV:
2391 switch (GST_VIDEO_INFO_FORMAT (in_info)) {
2392 case GST_VIDEO_FORMAT_AYUV:
2393 alpha->process = gst_alpha_set_ayuv_ayuv;
2395 case GST_VIDEO_FORMAT_Y444:
2396 case GST_VIDEO_FORMAT_Y42B:
2397 case GST_VIDEO_FORMAT_I420:
2398 case GST_VIDEO_FORMAT_YV12:
2399 case GST_VIDEO_FORMAT_Y41B:
2400 alpha->process = gst_alpha_set_planar_yuv_ayuv;
2402 case GST_VIDEO_FORMAT_YUY2:
2403 case GST_VIDEO_FORMAT_YVYU:
2404 case GST_VIDEO_FORMAT_UYVY:
2405 alpha->process = gst_alpha_set_packed_422_ayuv;
2407 case GST_VIDEO_FORMAT_ARGB:
2408 case GST_VIDEO_FORMAT_ABGR:
2409 case GST_VIDEO_FORMAT_RGBA:
2410 case GST_VIDEO_FORMAT_BGRA:
2411 alpha->process = gst_alpha_set_argb_ayuv;
2413 case GST_VIDEO_FORMAT_xRGB:
2414 case GST_VIDEO_FORMAT_xBGR:
2415 case GST_VIDEO_FORMAT_RGBx:
2416 case GST_VIDEO_FORMAT_BGRx:
2417 case GST_VIDEO_FORMAT_RGB:
2418 case GST_VIDEO_FORMAT_BGR:
2419 alpha->process = gst_alpha_set_rgb_ayuv;
2425 case GST_VIDEO_FORMAT_ARGB:
2426 case GST_VIDEO_FORMAT_ABGR:
2427 case GST_VIDEO_FORMAT_RGBA:
2428 case GST_VIDEO_FORMAT_BGRA:
2429 switch (GST_VIDEO_INFO_FORMAT (in_info)) {
2430 case GST_VIDEO_FORMAT_AYUV:
2431 alpha->process = gst_alpha_set_ayuv_argb;
2433 case GST_VIDEO_FORMAT_Y444:
2434 case GST_VIDEO_FORMAT_Y42B:
2435 case GST_VIDEO_FORMAT_I420:
2436 case GST_VIDEO_FORMAT_YV12:
2437 case GST_VIDEO_FORMAT_Y41B:
2438 alpha->process = gst_alpha_set_planar_yuv_argb;
2440 case GST_VIDEO_FORMAT_YUY2:
2441 case GST_VIDEO_FORMAT_YVYU:
2442 case GST_VIDEO_FORMAT_UYVY:
2443 alpha->process = gst_alpha_set_packed_422_argb;
2445 case GST_VIDEO_FORMAT_ARGB:
2446 case GST_VIDEO_FORMAT_ABGR:
2447 case GST_VIDEO_FORMAT_RGBA:
2448 case GST_VIDEO_FORMAT_BGRA:
2449 alpha->process = gst_alpha_set_argb_argb;
2451 case GST_VIDEO_FORMAT_xRGB:
2452 case GST_VIDEO_FORMAT_xBGR:
2453 case GST_VIDEO_FORMAT_RGBx:
2454 case GST_VIDEO_FORMAT_BGRx:
2455 case GST_VIDEO_FORMAT_RGB:
2456 case GST_VIDEO_FORMAT_BGR:
2457 alpha->process = gst_alpha_set_rgb_argb;
2468 case ALPHA_METHOD_GREEN:
2469 case ALPHA_METHOD_BLUE:
2470 case ALPHA_METHOD_CUSTOM:
2471 switch (GST_VIDEO_INFO_FORMAT (out_info)) {
2472 case GST_VIDEO_FORMAT_AYUV:
2473 switch (GST_VIDEO_INFO_FORMAT (in_info)) {
2474 case GST_VIDEO_FORMAT_AYUV:
2475 alpha->process = gst_alpha_chroma_key_ayuv_ayuv;
2477 case GST_VIDEO_FORMAT_Y444:
2478 case GST_VIDEO_FORMAT_Y42B:
2479 case GST_VIDEO_FORMAT_I420:
2480 case GST_VIDEO_FORMAT_YV12:
2481 case GST_VIDEO_FORMAT_Y41B:
2482 alpha->process = gst_alpha_chroma_key_planar_yuv_ayuv;
2484 case GST_VIDEO_FORMAT_YUY2:
2485 case GST_VIDEO_FORMAT_YVYU:
2486 case GST_VIDEO_FORMAT_UYVY:
2487 alpha->process = gst_alpha_chroma_key_packed_422_ayuv;
2489 case GST_VIDEO_FORMAT_ARGB:
2490 case GST_VIDEO_FORMAT_ABGR:
2491 case GST_VIDEO_FORMAT_RGBA:
2492 case GST_VIDEO_FORMAT_BGRA:
2493 alpha->process = gst_alpha_chroma_key_argb_ayuv;
2495 case GST_VIDEO_FORMAT_xRGB:
2496 case GST_VIDEO_FORMAT_xBGR:
2497 case GST_VIDEO_FORMAT_RGBx:
2498 case GST_VIDEO_FORMAT_BGRx:
2499 case GST_VIDEO_FORMAT_RGB:
2500 case GST_VIDEO_FORMAT_BGR:
2501 alpha->process = gst_alpha_chroma_key_rgb_ayuv;
2507 case GST_VIDEO_FORMAT_ARGB:
2508 case GST_VIDEO_FORMAT_ABGR:
2509 case GST_VIDEO_FORMAT_RGBA:
2510 case GST_VIDEO_FORMAT_BGRA:
2511 switch (GST_VIDEO_INFO_FORMAT (in_info)) {
2512 case GST_VIDEO_FORMAT_AYUV:
2513 alpha->process = gst_alpha_chroma_key_ayuv_argb;
2515 case GST_VIDEO_FORMAT_Y444:
2516 case GST_VIDEO_FORMAT_Y42B:
2517 case GST_VIDEO_FORMAT_I420:
2518 case GST_VIDEO_FORMAT_YV12:
2519 case GST_VIDEO_FORMAT_Y41B:
2520 alpha->process = gst_alpha_chroma_key_planar_yuv_argb;
2522 case GST_VIDEO_FORMAT_YUY2:
2523 case GST_VIDEO_FORMAT_YVYU:
2524 case GST_VIDEO_FORMAT_UYVY:
2525 alpha->process = gst_alpha_chroma_key_packed_422_argb;
2527 case GST_VIDEO_FORMAT_ARGB:
2528 case GST_VIDEO_FORMAT_ABGR:
2529 case GST_VIDEO_FORMAT_RGBA:
2530 case GST_VIDEO_FORMAT_BGRA:
2531 alpha->process = gst_alpha_chroma_key_argb_argb;
2533 case GST_VIDEO_FORMAT_xRGB:
2534 case GST_VIDEO_FORMAT_xBGR:
2535 case GST_VIDEO_FORMAT_RGBx:
2536 case GST_VIDEO_FORMAT_BGRx:
2537 case GST_VIDEO_FORMAT_RGB:
2538 case GST_VIDEO_FORMAT_BGR:
2539 alpha->process = gst_alpha_chroma_key_rgb_argb;
2553 return alpha->process != NULL;
2557 gst_alpha_set_process_function (GstAlpha * alpha)
2559 GstVideoInfo *info_in, *info_out;
2561 info_in = &GST_VIDEO_FILTER (alpha)->in_info;
2562 info_out = &GST_VIDEO_FILTER (alpha)->out_info;
2564 if (info_in->finfo != NULL && info_out->finfo != NULL) {
2565 gst_alpha_set_process_function_full (alpha, info_in, info_out);
2567 GST_DEBUG_OBJECT (alpha, "video formats not set yet");
2572 gst_alpha_before_transform (GstBaseTransform * btrans, GstBuffer * buf)
2574 GstAlpha *alpha = GST_ALPHA (btrans);
2575 GstClockTime timestamp;
2577 timestamp = gst_segment_to_stream_time (&btrans->segment, GST_FORMAT_TIME,
2578 GST_BUFFER_TIMESTAMP (buf));
2579 GST_LOG ("Got stream time of %" GST_TIME_FORMAT, GST_TIME_ARGS (timestamp));
2580 if (GST_CLOCK_TIME_IS_VALID (timestamp))
2581 gst_object_sync_values (GST_OBJECT (alpha), timestamp);
2584 static GstFlowReturn
2585 gst_alpha_transform_frame (GstVideoFilter * filter, GstVideoFrame * in_frame,
2586 GstVideoFrame * out_frame)
2588 GstAlpha *alpha = GST_ALPHA (filter);
2590 GST_ALPHA_LOCK (alpha);
2592 if (G_UNLIKELY (!alpha->process))
2593 goto not_negotiated;
2595 alpha->process (in_frame, out_frame, alpha);
2597 GST_ALPHA_UNLOCK (alpha);
2604 GST_ERROR_OBJECT (alpha, "Not negotiated yet");
2605 GST_ALPHA_UNLOCK (alpha);
2606 return GST_FLOW_NOT_NEGOTIATED;
2611 plugin_init (GstPlugin * plugin)
2613 return gst_element_register (plugin, "alpha", GST_RANK_NONE, GST_TYPE_ALPHA);
2616 GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
2619 "adds an alpha channel to video - constant or via chroma-keying",
2620 plugin_init, VERSION, GST_LICENSE, GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN)