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 #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 gboolean 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_details_simple (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 switch (alpha->method) {
331 case ALPHA_METHOD_GREEN:
333 alpha->target_g = 255;
336 case ALPHA_METHOD_BLUE:
339 alpha->target_b = 255;
344 gst_alpha_set_process_function (alpha);
345 gst_alpha_init_params (alpha);
349 gdouble a = g_value_get_double (value);
351 reconfigure = (a != alpha->alpha) && (a == 1.0 || alpha->alpha == 1.0)
352 && (alpha->method == ALPHA_METHOD_SET) && (alpha->prefer_passthrough);
357 alpha->target_r = g_value_get_uint (value);
358 gst_alpha_init_params (alpha);
361 alpha->target_g = g_value_get_uint (value);
362 gst_alpha_init_params (alpha);
365 alpha->target_b = g_value_get_uint (value);
366 gst_alpha_init_params (alpha);
369 alpha->angle = g_value_get_float (value);
370 gst_alpha_init_params (alpha);
372 case PROP_NOISE_LEVEL:
373 alpha->noise_level = g_value_get_float (value);
374 gst_alpha_init_params (alpha);
376 case PROP_BLACK_SENSITIVITY:
377 alpha->black_sensitivity = g_value_get_uint (value);
379 case PROP_WHITE_SENSITIVITY:
380 alpha->white_sensitivity = g_value_get_uint (value);
382 case PROP_PREFER_PASSTHROUGH:{
383 gboolean prefer_passthrough = g_value_get_boolean (value);
385 reconfigure = ((! !prefer_passthrough) != (! !alpha->prefer_passthrough))
386 && (alpha->method == ALPHA_METHOD_SET) && (alpha->alpha == 1.0);
387 alpha->prefer_passthrough = prefer_passthrough;
391 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
396 gst_base_transform_reconfigure_src (GST_BASE_TRANSFORM_CAST (alpha));
398 GST_ALPHA_UNLOCK (alpha);
402 gst_alpha_get_property (GObject * object, guint prop_id, GValue * value,
405 GstAlpha *alpha = GST_ALPHA (object);
409 g_value_set_enum (value, alpha->method);
412 g_value_set_double (value, alpha->alpha);
415 g_value_set_uint (value, alpha->target_r);
418 g_value_set_uint (value, alpha->target_g);
421 g_value_set_uint (value, alpha->target_b);
424 g_value_set_float (value, alpha->angle);
426 case PROP_NOISE_LEVEL:
427 g_value_set_float (value, alpha->noise_level);
429 case PROP_BLACK_SENSITIVITY:
430 g_value_set_uint (value, alpha->black_sensitivity);
432 case PROP_WHITE_SENSITIVITY:
433 g_value_set_uint (value, alpha->white_sensitivity);
435 case PROP_PREFER_PASSTHROUGH:
436 g_value_set_boolean (value, alpha->prefer_passthrough);
439 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
445 gst_alpha_transform_caps (GstBaseTransform * btrans,
446 GstPadDirection direction, GstCaps * caps, GstCaps * filter)
448 GstAlpha *alpha = GST_ALPHA (btrans);
449 GstCaps *ret, *tmp, *tmp2;
450 GstStructure *structure;
453 tmp = gst_caps_new_empty ();
455 GST_ALPHA_LOCK (alpha);
456 for (i = 0; i < gst_caps_get_size (caps); i++) {
457 structure = gst_structure_copy (gst_caps_get_structure (caps, i));
459 gst_structure_remove_field (structure, "format");
460 gst_structure_remove_field (structure, "color-matrix");
461 gst_structure_remove_field (structure, "chroma-site");
463 gst_caps_append_structure (tmp, structure);
466 if (direction == GST_PAD_SINK) {
467 tmp2 = gst_static_caps_get (&gst_alpha_alpha_caps);
468 ret = gst_caps_intersect (tmp, tmp2);
469 gst_caps_unref (tmp);
470 gst_caps_unref (tmp2);
474 if (alpha->prefer_passthrough && alpha->method == ALPHA_METHOD_SET
475 && alpha->alpha == 1.0) {
476 ret = gst_caps_copy (caps);
477 gst_caps_append (ret, tmp);
488 GST_DEBUG_OBJECT (alpha,
489 "Transformed %" GST_PTR_FORMAT " -> %" GST_PTR_FORMAT, caps, ret);
492 GstCaps *intersection;
494 GST_DEBUG_OBJECT (alpha, "Using filter caps %" GST_PTR_FORMAT, filter);
496 gst_caps_intersect_full (filter, ret, GST_CAPS_INTERSECT_FIRST);
497 gst_caps_unref (ret);
499 GST_DEBUG_OBJECT (alpha, "Intersection %" GST_PTR_FORMAT, ret);
503 GST_ALPHA_UNLOCK (alpha);
509 gst_alpha_set_info (GstVideoFilter * filter,
510 GstCaps * incaps, GstVideoInfo * in_info, GstCaps * outcaps,
511 GstVideoInfo * out_info)
513 GstAlpha *alpha = GST_ALPHA (filter);
514 gboolean passthrough;
516 GST_ALPHA_LOCK (alpha);
518 alpha->in_sdtv = in_info->colorimetry.matrix = GST_VIDEO_COLOR_MATRIX_BT601;
519 alpha->out_sdtv = out_info->colorimetry.matrix = GST_VIDEO_COLOR_MATRIX_BT601;
521 passthrough = alpha->prefer_passthrough &&
522 GST_VIDEO_INFO_FORMAT (in_info) == GST_VIDEO_INFO_FORMAT (out_info)
523 && alpha->in_sdtv == alpha->out_sdtv && alpha->method == ALPHA_METHOD_SET
524 && alpha->alpha == 1.0;
526 GST_DEBUG_OBJECT (alpha,
527 "Setting caps %" GST_PTR_FORMAT " -> %" GST_PTR_FORMAT
528 " (passthrough: %d)", incaps, outcaps, passthrough);
529 gst_base_transform_set_passthrough (GST_BASE_TRANSFORM_CAST (filter),
532 if (!gst_alpha_set_process_function_full (alpha, in_info, out_info)
536 gst_alpha_init_params_full (alpha, in_info->finfo, out_info->finfo);
538 GST_ALPHA_UNLOCK (alpha);
545 GST_WARNING_OBJECT (alpha,
546 "No processing function for this caps and no passthrough mode");
547 GST_ALPHA_UNLOCK (alpha);
552 /* based on http://www.cs.utah.edu/~michael/chroma/
555 chroma_keying_yuv (gint a, gint * y, gint * u,
556 gint * v, gint cr, gint cb, gint smin, gint smax, guint8 accept_angle_tg,
557 guint8 accept_angle_ctg, guint8 one_over_kc, guint8 kfgy_scale, gint8 kg,
565 /* too dark or too bright, keep alpha */
566 if (*y < smin || *y > smax)
569 /* Convert foreground to XZ coords where X direction is defined by
571 tmp = ((*u) * cb + (*v) * cr) >> 7;
572 x = CLAMP (tmp, -128, 127);
573 tmp = ((*v) * cb - (*u) * cr) >> 7;
574 z = CLAMP (tmp, -128, 127);
576 /* WARNING: accept angle should never be set greater than "somewhat less
577 than 90 degrees" to avoid dealing with negative/infinite tg. In reality,
578 80 degrees should be enough if foreground is reasonable. If this seems
579 to be a problem, go to alternative ways of checking point position
580 (scalar product or line equations). This angle should not be too small
581 either to avoid infinite ctg (used to suppress foreground without use of
584 tmp = (x * accept_angle_tg) >> 4;
585 tmp = MIN (tmp, 127);
588 /* keep foreground Kfg = 0 */
591 /* Compute Kfg (implicitly) and Kbg, suppress foreground in XZ coord
593 tmp = (z * accept_angle_ctg) >> 4;
594 tmp = CLAMP (tmp, -128, 127);
599 tmp1 = MAX (tmp1, 0);
600 b_alpha = (tmp1 * one_over_kc) / 2;
601 b_alpha = 255 - CLAMP (b_alpha, 0, 255);
602 b_alpha = (a * b_alpha) >> 8;
604 tmp = (tmp1 * kfgy_scale) >> 4;
605 tmp1 = MIN (tmp, 255);
607 *y = (*y < tmp1) ? 0 : *y - tmp1;
609 /* Convert suppressed foreground back to CbCr */
610 tmp = (x1 * cb - y1 * cr) >> 7;
611 *u = CLAMP (tmp, -128, 127);
613 tmp = (x1 * cr + y1 * cb) >> 7;
614 *v = CLAMP (tmp, -128, 127);
616 /* Deal with noise. For now, a circle around the key color with
617 radius of noise_level treated as exact key color. Introduces
620 tmp = z * z + (x - kg) * (x - kg);
621 tmp = MIN (tmp, 0xffff);
623 if (tmp < noise_level2)
629 #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)
632 gst_alpha_set_argb_ayuv (const GstVideoFrame * in_frame,
633 GstVideoFrame * out_frame, GstAlpha * alpha)
635 gint s_alpha = CLAMP ((gint) (alpha->alpha * 256), 0, 256);
644 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
645 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
647 width = GST_VIDEO_FRAME_WIDTH (in_frame);
648 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
650 o[0] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 3);
651 o[1] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 0);
652 o[2] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 1);
653 o[3] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 2);
656 alpha->out_sdtv ? cog_rgb_to_ycbcr_matrix_8bit_sdtv :
657 cog_rgb_to_ycbcr_matrix_8bit_hdtv, 12 * sizeof (gint));
659 for (i = 0; i < height; i++) {
660 for (j = 0; j < width; j++) {
661 dest[0] = (src[o[0]] * s_alpha) >> 8;
663 y = APPLY_MATRIX (matrix, 0, src[o[1]], src[o[2]], src[o[3]]);
664 u = APPLY_MATRIX (matrix, 1, src[o[1]], src[o[2]], src[o[3]]);
665 v = APPLY_MATRIX (matrix, 2, src[o[1]], src[o[2]], src[o[3]]);
678 gst_alpha_chroma_key_argb_ayuv (const GstVideoFrame * in_frame,
679 GstVideoFrame * out_frame, GstAlpha * alpha)
688 gint pa = CLAMP ((gint) (alpha->alpha * 256), 0, 256);
689 gint8 cb = alpha->cb, cr = alpha->cr;
690 gint8 kg = alpha->kg;
691 guint8 accept_angle_tg = alpha->accept_angle_tg;
692 guint8 accept_angle_ctg = alpha->accept_angle_ctg;
693 guint8 one_over_kc = alpha->one_over_kc;
694 guint8 kfgy_scale = alpha->kfgy_scale;
695 guint noise_level2 = alpha->noise_level2;
699 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
700 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
702 width = GST_VIDEO_FRAME_WIDTH (in_frame);
703 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
705 o[0] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 3);
706 o[1] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 0);
707 o[2] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 1);
708 o[3] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 2);
710 smin = 128 - alpha->black_sensitivity;
711 smax = 128 + alpha->white_sensitivity;
714 alpha->out_sdtv ? cog_rgb_to_ycbcr_matrix_8bit_sdtv :
715 cog_rgb_to_ycbcr_matrix_8bit_hdtv, 12 * sizeof (gint));
717 for (i = 0; i < height; i++) {
718 for (j = 0; j < width; j++) {
719 a = (src[o[0]] * pa) >> 8;
724 y = APPLY_MATRIX (matrix, 0, r, g, b);
725 u = APPLY_MATRIX (matrix, 1, r, g, b) - 128;
726 v = APPLY_MATRIX (matrix, 2, r, g, b) - 128;
728 a = chroma_keying_yuv (a, &y, &u, &v, cr, cb,
729 smin, smax, accept_angle_tg, accept_angle_ctg,
730 one_over_kc, kfgy_scale, kg, noise_level2);
747 gst_alpha_set_argb_argb (const GstVideoFrame * in_frame,
748 GstVideoFrame * out_frame, GstAlpha * alpha)
753 gint s_alpha = CLAMP ((gint) (alpha->alpha * 256), 0, 256);
757 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
758 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
760 width = GST_VIDEO_FRAME_WIDTH (in_frame);
761 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
763 p[0] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 3);
764 p[1] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 0);
765 p[2] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 1);
766 p[3] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 2);
768 o[0] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 3);
769 o[1] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 0);
770 o[2] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 1);
771 o[3] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 2);
773 for (i = 0; i < height; i++) {
774 for (j = 0; j < width; j++) {
775 dest[p[0]] = (src[o[0]] * s_alpha) >> 8;
777 dest[p[1]] = src[o[1]];
778 dest[p[2]] = src[o[2]];
779 dest[p[3]] = src[o[3]];
788 gst_alpha_chroma_key_argb_argb (const GstVideoFrame * in_frame,
789 GstVideoFrame * out_frame, GstAlpha * alpha)
798 gint pa = CLAMP ((gint) (alpha->alpha * 256), 0, 256);
799 gint8 cb = alpha->cb, cr = alpha->cr;
800 gint8 kg = alpha->kg;
801 guint8 accept_angle_tg = alpha->accept_angle_tg;
802 guint8 accept_angle_ctg = alpha->accept_angle_ctg;
803 guint8 one_over_kc = alpha->one_over_kc;
804 guint8 kfgy_scale = alpha->kfgy_scale;
805 guint noise_level2 = alpha->noise_level2;
806 gint matrix[12], matrix2[12];
809 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
810 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
812 width = GST_VIDEO_FRAME_WIDTH (in_frame);
813 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
815 p[0] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 3);
816 p[1] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 0);
817 p[2] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 1);
818 p[3] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 2);
820 o[0] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 3);
821 o[1] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 0);
822 o[2] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 1);
823 o[3] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 2);
825 smin = 128 - alpha->black_sensitivity;
826 smax = 128 + alpha->white_sensitivity;
828 memcpy (matrix, cog_rgb_to_ycbcr_matrix_8bit_sdtv, 12 * sizeof (gint));
829 memcpy (matrix2, cog_ycbcr_to_rgb_matrix_8bit_sdtv, 12 * sizeof (gint));
831 for (i = 0; i < height; i++) {
832 for (j = 0; j < width; j++) {
833 a = (src[o[0]] * pa) >> 8;
838 y = APPLY_MATRIX (matrix, 0, r, g, b);
839 u = APPLY_MATRIX (matrix, 1, r, g, b) - 128;
840 v = APPLY_MATRIX (matrix, 2, r, g, b) - 128;
842 a = chroma_keying_yuv (a, &y, &u, &v, cr, cb,
843 smin, smax, accept_angle_tg, accept_angle_ctg,
844 one_over_kc, kfgy_scale, kg, noise_level2);
849 r = APPLY_MATRIX (matrix2, 0, y, u, v);
850 g = APPLY_MATRIX (matrix2, 1, y, u, v);
851 b = APPLY_MATRIX (matrix2, 2, y, u, v);
854 dest[p[1]] = CLAMP (r, 0, 255);
855 dest[p[2]] = CLAMP (g, 0, 255);
856 dest[p[3]] = CLAMP (b, 0, 255);
865 gst_alpha_set_ayuv_argb (const GstVideoFrame * in_frame,
866 GstVideoFrame * out_frame, GstAlpha * alpha)
871 gint s_alpha = CLAMP ((gint) (alpha->alpha * 256), 0, 256);
877 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
878 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
880 width = GST_VIDEO_FRAME_WIDTH (in_frame);
881 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
883 p[0] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 3);
884 p[1] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 0);
885 p[2] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 1);
886 p[3] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 2);
889 alpha->in_sdtv ? cog_ycbcr_to_rgb_matrix_8bit_sdtv :
890 cog_ycbcr_to_rgb_matrix_8bit_hdtv, 12 * sizeof (gint));
892 for (y = 0; y < height; y++) {
893 for (x = 0; x < width; x++) {
894 dest[p[0]] = (src[0] * s_alpha) >> 8;
896 r = APPLY_MATRIX (matrix, 0, src[1], src[2], src[3]);
897 g = APPLY_MATRIX (matrix, 1, src[1], src[2], src[3]);
898 b = APPLY_MATRIX (matrix, 2, src[1], src[2], src[3]);
900 dest[p[1]] = CLAMP (r, 0, 255);
901 dest[p[2]] = CLAMP (g, 0, 255);
902 dest[p[3]] = CLAMP (b, 0, 255);
911 gst_alpha_chroma_key_ayuv_argb (const GstVideoFrame * in_frame,
912 GstVideoFrame * out_frame, GstAlpha * alpha)
921 gint pa = CLAMP ((gint) (alpha->alpha * 256), 0, 256);
922 gint8 cb = alpha->cb, cr = alpha->cr;
923 gint8 kg = alpha->kg;
924 guint8 accept_angle_tg = alpha->accept_angle_tg;
925 guint8 accept_angle_ctg = alpha->accept_angle_ctg;
926 guint8 one_over_kc = alpha->one_over_kc;
927 guint8 kfgy_scale = alpha->kfgy_scale;
928 guint noise_level2 = alpha->noise_level2;
932 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
933 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
935 width = GST_VIDEO_FRAME_WIDTH (in_frame);
936 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
938 p[0] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 3);
939 p[1] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 0);
940 p[2] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 1);
941 p[3] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 2);
943 smin = 128 - alpha->black_sensitivity;
944 smax = 128 + alpha->white_sensitivity;
947 alpha->in_sdtv ? cog_ycbcr_to_rgb_matrix_8bit_sdtv :
948 cog_ycbcr_to_rgb_matrix_8bit_hdtv, 12 * sizeof (gint));
950 for (i = 0; i < height; i++) {
951 for (j = 0; j < width; j++) {
952 a = (src[0] * pa) >> 8;
957 a = chroma_keying_yuv (a, &y, &u, &v, cr, cb,
958 smin, smax, accept_angle_tg, accept_angle_ctg,
959 one_over_kc, kfgy_scale, kg, noise_level2);
964 r = APPLY_MATRIX (matrix, 0, y, u, v);
965 g = APPLY_MATRIX (matrix, 1, y, u, v);
966 b = APPLY_MATRIX (matrix, 2, y, u, v);
969 dest[p[1]] = CLAMP (r, 0, 255);
970 dest[p[2]] = CLAMP (g, 0, 255);
971 dest[p[3]] = CLAMP (b, 0, 255);
980 gst_alpha_set_ayuv_ayuv (const GstVideoFrame * in_frame,
981 GstVideoFrame * out_frame, GstAlpha * alpha)
986 gint s_alpha = CLAMP ((gint) (alpha->alpha * 256), 0, 256);
989 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
990 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
992 width = GST_VIDEO_FRAME_WIDTH (in_frame);
993 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
995 if (alpha->in_sdtv == alpha->out_sdtv) {
996 for (y = 0; y < height; y++) {
997 for (x = 0; x < width; x++) {
998 dest[0] = (src[0] * s_alpha) >> 8;
1011 alpha->out_sdtv ? cog_ycbcr_hdtv_to_ycbcr_sdtv_matrix_8bit :
1012 cog_ycbcr_sdtv_to_ycbcr_hdtv_matrix_8bit, 12 * sizeof (gint));
1014 for (y = 0; y < height; y++) {
1015 for (x = 0; x < width; x++) {
1016 dest[0] = (src[0] * s_alpha) >> 8;
1017 dest[1] = APPLY_MATRIX (matrix, 0, src[1], src[2], src[3]);
1018 dest[2] = APPLY_MATRIX (matrix, 1, src[1], src[2], src[3]);
1019 dest[3] = APPLY_MATRIX (matrix, 2, src[1], src[2], src[3]);
1029 gst_alpha_chroma_key_ayuv_ayuv (const GstVideoFrame * in_frame,
1030 GstVideoFrame * out_frame, GstAlpha * alpha)
1038 gint pa = CLAMP ((gint) (alpha->alpha * 256), 0, 256);
1039 gint8 cb = alpha->cb, cr = alpha->cr;
1040 gint8 kg = alpha->kg;
1041 guint8 accept_angle_tg = alpha->accept_angle_tg;
1042 guint8 accept_angle_ctg = alpha->accept_angle_ctg;
1043 guint8 one_over_kc = alpha->one_over_kc;
1044 guint8 kfgy_scale = alpha->kfgy_scale;
1045 guint noise_level2 = alpha->noise_level2;
1047 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
1048 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
1050 width = GST_VIDEO_FRAME_WIDTH (in_frame);
1051 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
1053 smin = 128 - alpha->black_sensitivity;
1054 smax = 128 + alpha->white_sensitivity;
1056 if (alpha->in_sdtv == alpha->out_sdtv) {
1057 for (i = 0; i < height; i++) {
1058 for (j = 0; j < width; j++) {
1059 a = (src[0] * pa) >> 8;
1064 a = chroma_keying_yuv (a, &y, &u, &v, cr, cb,
1065 smin, smax, accept_angle_tg, accept_angle_ctg,
1066 one_over_kc, kfgy_scale, kg, noise_level2);
1084 alpha->out_sdtv ? cog_ycbcr_hdtv_to_ycbcr_sdtv_matrix_8bit :
1085 cog_ycbcr_sdtv_to_ycbcr_hdtv_matrix_8bit, 12 * sizeof (gint));
1087 for (i = 0; i < height; i++) {
1088 for (j = 0; j < width; j++) {
1089 a = (src[0] * pa) >> 8;
1090 y = APPLY_MATRIX (matrix, 0, src[1], src[2], src[3]);
1091 u = APPLY_MATRIX (matrix, 1, src[1], src[2], src[3]) - 128;
1092 v = APPLY_MATRIX (matrix, 2, src[1], src[2], src[3]) - 128;
1094 a = chroma_keying_yuv (a, &y, &u, &v, cr, cb,
1095 smin, smax, accept_angle_tg, accept_angle_ctg,
1096 one_over_kc, kfgy_scale, kg, noise_level2);
1114 gst_alpha_set_rgb_ayuv (const GstVideoFrame * in_frame,
1115 GstVideoFrame * out_frame, GstAlpha * alpha)
1120 gint s_alpha = CLAMP ((gint) (alpha->alpha * 255), 0, 255);
1127 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
1128 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
1130 width = GST_VIDEO_FRAME_WIDTH (in_frame);
1131 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
1133 bpp = GST_VIDEO_FRAME_COMP_PSTRIDE (in_frame, 0);
1134 o[0] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 0);
1135 o[1] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 1);
1136 o[2] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 2);
1139 alpha->out_sdtv ? cog_rgb_to_ycbcr_matrix_8bit_sdtv :
1140 cog_rgb_to_ycbcr_matrix_8bit_hdtv, 12 * sizeof (gint));
1142 for (i = 0; i < height; i++) {
1143 for (j = 0; j < width; j++) {
1146 y = APPLY_MATRIX (matrix, 0, src[o[0]], src[o[1]], src[o[2]]);
1147 u = APPLY_MATRIX (matrix, 1, src[o[0]], src[o[1]], src[o[2]]);
1148 v = APPLY_MATRIX (matrix, 2, src[o[0]], src[o[1]], src[o[2]]);
1161 gst_alpha_chroma_key_rgb_ayuv (const GstVideoFrame * in_frame,
1162 GstVideoFrame * out_frame, GstAlpha * alpha)
1171 gint pa = CLAMP ((gint) (alpha->alpha * 255), 0, 255);
1172 gint8 cb = alpha->cb, cr = alpha->cr;
1173 gint8 kg = alpha->kg;
1174 guint8 accept_angle_tg = alpha->accept_angle_tg;
1175 guint8 accept_angle_ctg = alpha->accept_angle_ctg;
1176 guint8 one_over_kc = alpha->one_over_kc;
1177 guint8 kfgy_scale = alpha->kfgy_scale;
1178 guint noise_level2 = alpha->noise_level2;
1183 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
1184 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
1186 width = GST_VIDEO_FRAME_WIDTH (in_frame);
1187 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
1189 bpp = GST_VIDEO_FRAME_COMP_PSTRIDE (in_frame, 0);
1191 o[0] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 0);
1192 o[1] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 1);
1193 o[2] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 2);
1195 smin = 128 - alpha->black_sensitivity;
1196 smax = 128 + alpha->white_sensitivity;
1199 alpha->out_sdtv ? cog_rgb_to_ycbcr_matrix_8bit_sdtv :
1200 cog_rgb_to_ycbcr_matrix_8bit_hdtv, 12 * sizeof (gint));
1202 for (i = 0; i < height; i++) {
1203 for (j = 0; j < width; j++) {
1209 y = APPLY_MATRIX (matrix, 0, r, g, b);
1210 u = APPLY_MATRIX (matrix, 1, r, g, b) - 128;
1211 v = APPLY_MATRIX (matrix, 2, r, g, b) - 128;
1213 a = chroma_keying_yuv (a, &y, &u, &v, cr, cb,
1214 smin, smax, accept_angle_tg, accept_angle_ctg,
1215 one_over_kc, kfgy_scale, kg, noise_level2);
1232 gst_alpha_set_rgb_argb (const GstVideoFrame * in_frame,
1233 GstVideoFrame * out_frame, GstAlpha * alpha)
1238 gint s_alpha = CLAMP ((gint) (alpha->alpha * 255), 0, 255);
1243 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
1244 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
1246 width = GST_VIDEO_FRAME_WIDTH (in_frame);
1247 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
1249 bpp = GST_VIDEO_FRAME_COMP_PSTRIDE (in_frame, 0);
1251 o[0] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 0);
1252 o[1] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 1);
1253 o[2] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 2);
1255 p[0] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 3);
1256 p[1] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 0);
1257 p[2] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 1);
1258 p[3] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 2);
1260 for (i = 0; i < height; i++) {
1261 for (j = 0; j < width; j++) {
1262 dest[p[0]] = s_alpha;
1264 dest[p[1]] = src[o[0]];
1265 dest[p[2]] = src[o[1]];
1266 dest[p[3]] = src[o[2]];
1275 gst_alpha_chroma_key_rgb_argb (const GstVideoFrame * in_frame,
1276 GstVideoFrame * out_frame, GstAlpha * alpha)
1285 gint pa = CLAMP ((gint) (alpha->alpha * 255), 0, 255);
1286 gint8 cb = alpha->cb, cr = alpha->cr;
1287 gint8 kg = alpha->kg;
1288 guint8 accept_angle_tg = alpha->accept_angle_tg;
1289 guint8 accept_angle_ctg = alpha->accept_angle_ctg;
1290 guint8 one_over_kc = alpha->one_over_kc;
1291 guint8 kfgy_scale = alpha->kfgy_scale;
1292 guint noise_level2 = alpha->noise_level2;
1293 gint matrix[12], matrix2[12];
1297 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
1298 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
1300 width = GST_VIDEO_FRAME_WIDTH (in_frame);
1301 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
1303 bpp = GST_VIDEO_FRAME_COMP_PSTRIDE (in_frame, 0);
1305 o[0] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 0);
1306 o[1] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 1);
1307 o[2] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 2);
1309 p[0] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 3);
1310 p[1] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 0);
1311 p[2] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 1);
1312 p[3] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 2);
1314 smin = 128 - alpha->black_sensitivity;
1315 smax = 128 + alpha->white_sensitivity;
1317 memcpy (matrix, cog_rgb_to_ycbcr_matrix_8bit_sdtv, 12 * sizeof (gint));
1318 memcpy (matrix2, cog_ycbcr_to_rgb_matrix_8bit_sdtv, 12 * sizeof (gint));
1320 for (i = 0; i < height; i++) {
1321 for (j = 0; j < width; j++) {
1327 y = APPLY_MATRIX (matrix, 0, r, g, b);
1328 u = APPLY_MATRIX (matrix, 1, r, g, b) - 128;
1329 v = APPLY_MATRIX (matrix, 2, r, g, b) - 128;
1331 a = chroma_keying_yuv (a, &y, &u, &v, cr, cb,
1332 smin, smax, accept_angle_tg, accept_angle_ctg,
1333 one_over_kc, kfgy_scale, kg, noise_level2);
1338 r = APPLY_MATRIX (matrix2, 0, y, u, v);
1339 g = APPLY_MATRIX (matrix2, 1, y, u, v);
1340 b = APPLY_MATRIX (matrix2, 2, y, u, v);
1343 dest[p[1]] = CLAMP (r, 0, 255);
1344 dest[p[2]] = CLAMP (g, 0, 255);
1345 dest[p[3]] = CLAMP (b, 0, 255);
1354 gst_alpha_set_planar_yuv_ayuv (const GstVideoFrame * in_frame,
1355 GstVideoFrame * out_frame, GstAlpha * alpha)
1360 gint b_alpha = CLAMP ((gint) (alpha->alpha * 255), 0, 255);
1361 const guint8 *srcY, *srcY_tmp;
1362 const guint8 *srcU, *srcU_tmp;
1363 const guint8 *srcV, *srcV_tmp;
1365 gint y_stride, uv_stride;
1366 gint v_subs, h_subs;
1368 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
1369 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
1371 width = GST_VIDEO_FRAME_WIDTH (in_frame);
1372 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
1374 y_stride = GST_VIDEO_FRAME_COMP_STRIDE (in_frame, 0);
1375 uv_stride = GST_VIDEO_FRAME_COMP_STRIDE (in_frame, 1);
1377 srcY_tmp = srcY = src;
1378 srcU_tmp = srcU = src + GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 1);
1379 srcV_tmp = srcV = src + GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 2);
1381 switch (GST_VIDEO_FRAME_FORMAT (in_frame)) {
1382 case GST_VIDEO_FORMAT_I420:
1383 case GST_VIDEO_FORMAT_YV12:
1384 v_subs = h_subs = 2;
1386 case GST_VIDEO_FORMAT_Y444:
1387 v_subs = h_subs = 1;
1389 case GST_VIDEO_FORMAT_Y42B:
1393 case GST_VIDEO_FORMAT_Y41B:
1398 g_assert_not_reached ();
1402 if (alpha->in_sdtv == alpha->out_sdtv) {
1403 for (i = 0; i < height; i++) {
1404 for (j = 0; j < width; j++) {
1412 if ((j + 1) % h_subs == 0) {
1418 srcY_tmp = srcY = srcY_tmp + y_stride;
1419 if ((i + 1) % v_subs == 0) {
1420 srcU_tmp = srcU = srcU_tmp + uv_stride;
1421 srcV_tmp = srcV = srcV_tmp + uv_stride;
1432 alpha->out_sdtv ? cog_ycbcr_hdtv_to_ycbcr_sdtv_matrix_8bit :
1433 cog_ycbcr_sdtv_to_ycbcr_hdtv_matrix_8bit, 12 * sizeof (gint));
1435 for (i = 0; i < height; i++) {
1436 for (j = 0; j < width; j++) {
1443 dest[1] = APPLY_MATRIX (matrix, 0, y, u, v);
1444 dest[2] = APPLY_MATRIX (matrix, 1, y, u, v);
1445 dest[3] = APPLY_MATRIX (matrix, 2, y, u, v);
1449 if ((j + 1) % h_subs == 0) {
1455 srcY_tmp = srcY = srcY_tmp + y_stride;
1456 if ((i + 1) % v_subs == 0) {
1457 srcU_tmp = srcU = srcU_tmp + uv_stride;
1458 srcV_tmp = srcV = srcV_tmp + uv_stride;
1468 gst_alpha_chroma_key_planar_yuv_ayuv (const GstVideoFrame * in_frame,
1469 GstVideoFrame * out_frame, GstAlpha * alpha)
1474 gint b_alpha = CLAMP ((gint) (alpha->alpha * 255), 0, 255);
1475 const guint8 *srcY, *srcY_tmp;
1476 const guint8 *srcU, *srcU_tmp;
1477 const guint8 *srcV, *srcV_tmp;
1480 gint y_stride, uv_stride;
1481 gint v_subs, h_subs;
1482 gint smin = 128 - alpha->black_sensitivity;
1483 gint smax = 128 + alpha->white_sensitivity;
1484 gint8 cb = alpha->cb, cr = alpha->cr;
1485 gint8 kg = alpha->kg;
1486 guint8 accept_angle_tg = alpha->accept_angle_tg;
1487 guint8 accept_angle_ctg = alpha->accept_angle_ctg;
1488 guint8 one_over_kc = alpha->one_over_kc;
1489 guint8 kfgy_scale = alpha->kfgy_scale;
1490 guint noise_level2 = alpha->noise_level2;
1492 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
1493 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
1495 width = GST_VIDEO_FRAME_WIDTH (in_frame);
1496 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
1498 y_stride = GST_VIDEO_FRAME_COMP_STRIDE (in_frame, 0);
1499 uv_stride = GST_VIDEO_FRAME_COMP_STRIDE (in_frame, 1);
1501 srcY_tmp = srcY = src;
1502 srcU_tmp = srcU = src + GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 1);
1503 srcV_tmp = srcV = src + GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 2);
1505 switch (GST_VIDEO_FRAME_FORMAT (in_frame)) {
1506 case GST_VIDEO_FORMAT_I420:
1507 case GST_VIDEO_FORMAT_YV12:
1508 v_subs = h_subs = 2;
1510 case GST_VIDEO_FORMAT_Y444:
1511 v_subs = h_subs = 1;
1513 case GST_VIDEO_FORMAT_Y42B:
1517 case GST_VIDEO_FORMAT_Y41B:
1522 g_assert_not_reached ();
1526 if (alpha->in_sdtv == alpha->out_sdtv) {
1527 for (i = 0; i < height; i++) {
1528 for (j = 0; j < width; j++) {
1534 a = chroma_keying_yuv (a, &y, &u, &v, cr, cb, smin,
1535 smax, accept_angle_tg, accept_angle_ctg,
1536 one_over_kc, kfgy_scale, kg, noise_level2);
1548 if ((j + 1) % h_subs == 0) {
1554 srcY_tmp = srcY = srcY_tmp + y_stride;
1555 if ((i + 1) % v_subs == 0) {
1556 srcU_tmp = srcU = srcU_tmp + uv_stride;
1557 srcV_tmp = srcV = srcV_tmp + uv_stride;
1567 alpha->out_sdtv ? cog_ycbcr_hdtv_to_ycbcr_sdtv_matrix_8bit :
1568 cog_ycbcr_sdtv_to_ycbcr_hdtv_matrix_8bit, 12 * sizeof (gint));
1570 for (i = 0; i < height; i++) {
1571 for (j = 0; j < width; j++) {
1573 y = APPLY_MATRIX (matrix, 0, srcY[0], srcU[0], srcV[0]);
1574 u = APPLY_MATRIX (matrix, 1, srcY[0], srcU[0], srcV[0]) - 128;
1575 v = APPLY_MATRIX (matrix, 2, srcY[0], srcU[0], srcV[0]) - 128;
1577 a = chroma_keying_yuv (a, &y, &u, &v, cr, cb, smin,
1578 smax, accept_angle_tg, accept_angle_ctg,
1579 one_over_kc, kfgy_scale, kg, noise_level2);
1588 if ((j + 1) % h_subs == 0) {
1594 srcY_tmp = srcY = srcY_tmp + y_stride;
1595 if ((i + 1) % v_subs == 0) {
1596 srcU_tmp = srcU = srcU_tmp + uv_stride;
1597 srcV_tmp = srcV = srcV_tmp + uv_stride;
1607 gst_alpha_set_planar_yuv_argb (const GstVideoFrame * in_frame,
1608 GstVideoFrame * out_frame, GstAlpha * alpha)
1613 gint b_alpha = CLAMP ((gint) (alpha->alpha * 255), 0, 255);
1614 const guint8 *srcY, *srcY_tmp;
1615 const guint8 *srcU, *srcU_tmp;
1616 const guint8 *srcV, *srcV_tmp;
1618 gint y_stride, uv_stride;
1619 gint v_subs, h_subs;
1625 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
1626 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
1628 width = GST_VIDEO_FRAME_WIDTH (in_frame);
1629 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
1631 p[0] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 3);
1632 p[1] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 0);
1633 p[2] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 1);
1634 p[3] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 2);
1636 y_stride = GST_VIDEO_FRAME_COMP_STRIDE (in_frame, 0);
1637 uv_stride = GST_VIDEO_FRAME_COMP_STRIDE (in_frame, 1);
1639 srcY_tmp = srcY = src;
1640 srcU_tmp = srcU = src + GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 1);
1641 srcV_tmp = srcV = src + GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 2);
1643 switch (GST_VIDEO_FRAME_FORMAT (in_frame)) {
1644 case GST_VIDEO_FORMAT_I420:
1645 case GST_VIDEO_FORMAT_YV12:
1646 v_subs = h_subs = 2;
1648 case GST_VIDEO_FORMAT_Y444:
1649 v_subs = h_subs = 1;
1651 case GST_VIDEO_FORMAT_Y42B:
1655 case GST_VIDEO_FORMAT_Y41B:
1660 g_assert_not_reached ();
1665 alpha->in_sdtv ? cog_ycbcr_to_rgb_matrix_8bit_sdtv :
1666 cog_ycbcr_to_rgb_matrix_8bit_hdtv, 12 * sizeof (gint));
1668 for (i = 0; i < height; i++) {
1669 for (j = 0; j < width; j++) {
1676 r = APPLY_MATRIX (matrix, 0, y, u, v);
1677 g = APPLY_MATRIX (matrix, 1, y, u, v);
1678 b = APPLY_MATRIX (matrix, 2, y, u, v);
1679 dest[p[1]] = CLAMP (r, 0, 255);
1680 dest[p[2]] = CLAMP (g, 0, 255);
1681 dest[p[3]] = CLAMP (b, 0, 255);
1685 if ((j + 1) % h_subs == 0) {
1691 srcY_tmp = srcY = srcY_tmp + y_stride;
1692 if ((i + 1) % v_subs == 0) {
1693 srcU_tmp = srcU = srcU_tmp + uv_stride;
1694 srcV_tmp = srcV = srcV_tmp + uv_stride;
1703 gst_alpha_chroma_key_planar_yuv_argb (const GstVideoFrame * in_frame,
1704 GstVideoFrame * out_frame, GstAlpha * alpha)
1709 gint b_alpha = CLAMP ((gint) (alpha->alpha * 255), 0, 255);
1710 const guint8 *srcY, *srcY_tmp;
1711 const guint8 *srcU, *srcU_tmp;
1712 const guint8 *srcV, *srcV_tmp;
1716 gint y_stride, uv_stride;
1717 gint v_subs, h_subs;
1718 gint smin = 128 - alpha->black_sensitivity;
1719 gint smax = 128 + alpha->white_sensitivity;
1720 gint8 cb = alpha->cb, cr = alpha->cr;
1721 gint8 kg = alpha->kg;
1722 guint8 accept_angle_tg = alpha->accept_angle_tg;
1723 guint8 accept_angle_ctg = alpha->accept_angle_ctg;
1724 guint8 one_over_kc = alpha->one_over_kc;
1725 guint8 kfgy_scale = alpha->kfgy_scale;
1726 guint noise_level2 = alpha->noise_level2;
1730 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
1731 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
1733 width = GST_VIDEO_FRAME_WIDTH (in_frame);
1734 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
1736 p[0] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 3);
1737 p[1] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 0);
1738 p[2] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 1);
1739 p[3] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 2);
1741 y_stride = GST_VIDEO_FRAME_COMP_STRIDE (in_frame, 0);
1742 uv_stride = GST_VIDEO_FRAME_COMP_STRIDE (in_frame, 1);
1744 srcY_tmp = srcY = src;
1745 srcU_tmp = srcU = src + GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 1);
1746 srcV_tmp = srcV = src + GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 2);
1748 switch (GST_VIDEO_FRAME_FORMAT (in_frame)) {
1749 case GST_VIDEO_FORMAT_I420:
1750 case GST_VIDEO_FORMAT_YV12:
1751 v_subs = h_subs = 2;
1753 case GST_VIDEO_FORMAT_Y444:
1754 v_subs = h_subs = 1;
1756 case GST_VIDEO_FORMAT_Y42B:
1760 case GST_VIDEO_FORMAT_Y41B:
1765 g_assert_not_reached ();
1770 alpha->in_sdtv ? cog_ycbcr_to_rgb_matrix_8bit_sdtv :
1771 cog_ycbcr_to_rgb_matrix_8bit_hdtv, 12 * sizeof (gint));
1773 for (i = 0; i < height; i++) {
1774 for (j = 0; j < width; j++) {
1780 a = chroma_keying_yuv (a, &y, &u, &v, cr, cb, smin,
1781 smax, accept_angle_tg, accept_angle_ctg,
1782 one_over_kc, kfgy_scale, kg, noise_level2);
1788 r = APPLY_MATRIX (matrix, 0, y, u, v);
1789 g = APPLY_MATRIX (matrix, 1, y, u, v);
1790 b = APPLY_MATRIX (matrix, 2, y, u, v);
1791 dest[p[1]] = CLAMP (r, 0, 255);
1792 dest[p[2]] = CLAMP (g, 0, 255);
1793 dest[p[3]] = CLAMP (b, 0, 255);
1797 if ((j + 1) % h_subs == 0) {
1803 srcY_tmp = srcY = srcY_tmp + y_stride;
1804 if ((i + 1) % v_subs == 0) {
1805 srcU_tmp = srcU = srcU_tmp + uv_stride;
1806 srcV_tmp = srcV = srcV_tmp + uv_stride;
1815 gst_alpha_set_packed_422_ayuv (const GstVideoFrame * in_frame,
1816 GstVideoFrame * out_frame, GstAlpha * alpha)
1821 gint s_alpha = CLAMP ((gint) (alpha->alpha * 255), 0, 255);
1824 gint p[4]; /* Y U Y V */
1826 const guint8 *src_tmp;
1828 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
1829 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
1831 width = GST_VIDEO_FRAME_WIDTH (in_frame);
1832 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
1834 src_stride = GST_VIDEO_FRAME_COMP_STRIDE (in_frame, 0);
1836 p[0] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 0);
1838 p[1] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 1);
1839 p[3] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 2);
1841 if (alpha->in_sdtv != alpha->out_sdtv) {
1845 alpha->in_sdtv ? cog_ycbcr_sdtv_to_ycbcr_hdtv_matrix_8bit :
1846 cog_ycbcr_hdtv_to_ycbcr_sdtv_matrix_8bit, 12 * sizeof (gint));
1848 for (i = 0; i < height; i++) {
1851 for (j = 0; j < width - 1; j += 2) {
1855 y = APPLY_MATRIX (matrix, 0, src[p[0]], src[p[1]], src[p[3]]);
1856 u = APPLY_MATRIX (matrix, 1, src[p[0]], src[p[1]], src[p[3]]);
1857 v = APPLY_MATRIX (matrix, 2, src[p[0]], src[p[1]], src[p[3]]);
1863 y = APPLY_MATRIX (matrix, 0, src[p[2]], src[p[1]], src[p[3]]);
1864 u = APPLY_MATRIX (matrix, 1, src[p[2]], src[p[1]], src[p[3]]);
1865 v = APPLY_MATRIX (matrix, 2, src[p[2]], src[p[1]], src[p[3]]);
1875 if (j == width - 1) {
1878 y = APPLY_MATRIX (matrix, 0, src[p[0]], src[p[1]], src[p[3]]);
1879 u = APPLY_MATRIX (matrix, 1, src[p[0]], src[p[1]], src[p[3]]);
1880 v = APPLY_MATRIX (matrix, 2, src[p[0]], src[p[1]], src[p[3]]);
1889 src = src_tmp + src_stride;
1892 for (i = 0; i < height; i++) {
1895 for (j = 0; j < width - 1; j += 2) {
1917 if (j == width - 1) {
1931 src = src_tmp + src_stride;
1937 gst_alpha_chroma_key_packed_422_ayuv (const GstVideoFrame * in_frame,
1938 GstVideoFrame * out_frame, GstAlpha * alpha)
1946 gint pa = CLAMP ((gint) (alpha->alpha * 255), 0, 255);
1947 gint8 cb = alpha->cb, cr = alpha->cr;
1948 gint8 kg = alpha->kg;
1949 guint8 accept_angle_tg = alpha->accept_angle_tg;
1950 guint8 accept_angle_ctg = alpha->accept_angle_ctg;
1951 guint8 one_over_kc = alpha->one_over_kc;
1952 guint8 kfgy_scale = alpha->kfgy_scale;
1953 guint noise_level2 = alpha->noise_level2;
1954 gint p[4]; /* Y U Y V */
1956 const guint8 *src_tmp;
1958 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
1959 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
1961 width = GST_VIDEO_FRAME_WIDTH (in_frame);
1962 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
1964 src_stride = GST_VIDEO_FRAME_COMP_STRIDE (in_frame, 0);
1966 p[0] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 0);
1968 p[1] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 1);
1969 p[3] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 2);
1971 smin = 128 - alpha->black_sensitivity;
1972 smax = 128 + alpha->white_sensitivity;
1974 if (alpha->in_sdtv != alpha->out_sdtv) {
1978 alpha->in_sdtv ? cog_ycbcr_sdtv_to_ycbcr_hdtv_matrix_8bit :
1979 cog_ycbcr_hdtv_to_ycbcr_sdtv_matrix_8bit, 12 * sizeof (gint));
1981 for (i = 0; i < height; i++) {
1984 for (j = 0; j < width - 1; j += 2) {
1985 y = APPLY_MATRIX (matrix, 0, src[p[0]], src[p[1]], src[p[3]]);
1986 u = APPLY_MATRIX (matrix, 1, src[p[0]], src[p[1]], src[p[3]]) - 128;
1987 v = APPLY_MATRIX (matrix, 2, src[p[0]], 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);
1998 y = APPLY_MATRIX (matrix, 0, src[p[2]], src[p[1]], src[p[3]]);
1999 u = APPLY_MATRIX (matrix, 1, src[p[2]], src[p[1]], src[p[3]]) - 128;
2000 v = APPLY_MATRIX (matrix, 2, src[p[2]], src[p[1]], src[p[3]]) - 128;
2002 a = chroma_keying_yuv (pa, &y, &u, &v, cr, cb,
2003 smin, smax, accept_angle_tg, accept_angle_ctg,
2004 one_over_kc, kfgy_scale, kg, noise_level2);
2015 if (j == width - 1) {
2016 y = APPLY_MATRIX (matrix, 0, src[p[0]], src[p[1]], src[p[3]]);
2017 u = APPLY_MATRIX (matrix, 1, src[p[0]], src[p[1]], src[p[3]]) - 128;
2018 v = APPLY_MATRIX (matrix, 2, src[p[0]], src[p[1]], src[p[3]]) - 128;
2020 a = chroma_keying_yuv (pa, &y, &u, &v, cr, cb,
2021 smin, smax, accept_angle_tg, accept_angle_ctg,
2022 one_over_kc, kfgy_scale, kg, noise_level2);
2032 src = src_tmp + src_stride;
2035 for (i = 0; i < height; i++) {
2038 for (j = 0; j < width - 1; j += 2) {
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);
2053 u = src[p[1]] - 128;
2054 v = src[p[3]] - 128;
2056 a = chroma_keying_yuv (pa, &y, &u, &v, cr, cb,
2057 smin, smax, accept_angle_tg, accept_angle_ctg,
2058 one_over_kc, kfgy_scale, kg, noise_level2);
2069 if (j == width - 1) {
2071 u = src[p[1]] - 128;
2072 v = src[p[3]] - 128;
2074 a = chroma_keying_yuv (pa, &y, &u, &v, cr, cb,
2075 smin, smax, accept_angle_tg, accept_angle_ctg,
2076 one_over_kc, kfgy_scale, kg, noise_level2);
2086 src = src_tmp + src_stride;
2092 gst_alpha_set_packed_422_argb (const GstVideoFrame * in_frame,
2093 GstVideoFrame * out_frame, GstAlpha * alpha)
2098 gint s_alpha = CLAMP ((gint) (alpha->alpha * 255), 0, 255);
2102 const guint8 *src_tmp;
2106 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
2107 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
2109 width = GST_VIDEO_FRAME_WIDTH (in_frame);
2110 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
2112 src_stride = GST_VIDEO_FRAME_COMP_STRIDE (in_frame, 0);
2114 o[0] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 0);
2116 o[1] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 1);
2117 o[3] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 2);
2119 p[0] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 3);
2120 p[1] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 0);
2121 p[2] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 1);
2122 p[3] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 2);
2125 alpha->in_sdtv ? cog_ycbcr_to_rgb_matrix_8bit_sdtv :
2126 cog_ycbcr_to_rgb_matrix_8bit_hdtv, 12 * sizeof (gint));
2128 for (i = 0; i < height; i++) {
2131 for (j = 0; j < width - 1; j += 2) {
2132 r = APPLY_MATRIX (matrix, 0, src[o[0]], src[o[1]], src[o[3]]);
2133 g = APPLY_MATRIX (matrix, 1, src[o[0]], src[o[1]], src[o[3]]);
2134 b = APPLY_MATRIX (matrix, 2, src[o[0]], src[o[1]], src[o[3]]);
2136 dest[p[0]] = s_alpha;
2137 dest[p[1]] = CLAMP (r, 0, 255);
2138 dest[p[2]] = CLAMP (g, 0, 255);
2139 dest[p[3]] = CLAMP (b, 0, 255);
2141 r = APPLY_MATRIX (matrix, 0, src[o[2]], src[o[1]], src[o[3]]);
2142 g = APPLY_MATRIX (matrix, 1, src[o[2]], src[o[1]], src[o[3]]);
2143 b = APPLY_MATRIX (matrix, 2, src[o[2]], src[o[1]], src[o[3]]);
2145 dest[4 + p[0]] = s_alpha;
2146 dest[4 + p[1]] = CLAMP (r, 0, 255);
2147 dest[4 + p[2]] = CLAMP (g, 0, 255);
2148 dest[4 + p[3]] = CLAMP (b, 0, 255);
2154 if (j == width - 1) {
2155 r = APPLY_MATRIX (matrix, 0, src[o[0]], src[o[1]], src[o[3]]);
2156 g = APPLY_MATRIX (matrix, 1, src[o[0]], src[o[1]], src[o[3]]);
2157 b = APPLY_MATRIX (matrix, 2, src[o[0]], src[o[1]], src[o[3]]);
2159 dest[p[0]] = s_alpha;
2160 dest[p[1]] = CLAMP (r, 0, 255);
2161 dest[p[2]] = CLAMP (g, 0, 255);
2162 dest[p[3]] = CLAMP (b, 0, 255);
2167 src = src_tmp + src_stride;
2172 gst_alpha_chroma_key_packed_422_argb (const GstVideoFrame * in_frame,
2173 GstVideoFrame * out_frame, GstAlpha * alpha)
2182 gint pa = CLAMP ((gint) (alpha->alpha * 255), 0, 255);
2183 gint8 cb = alpha->cb, cr = alpha->cr;
2184 gint8 kg = alpha->kg;
2185 guint8 accept_angle_tg = alpha->accept_angle_tg;
2186 guint8 accept_angle_ctg = alpha->accept_angle_ctg;
2187 guint8 one_over_kc = alpha->one_over_kc;
2188 guint8 kfgy_scale = alpha->kfgy_scale;
2189 guint noise_level2 = alpha->noise_level2;
2192 const guint8 *src_tmp;
2195 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
2196 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
2198 width = GST_VIDEO_FRAME_WIDTH (in_frame);
2199 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
2201 src_stride = GST_VIDEO_FRAME_COMP_STRIDE (in_frame, 0);
2203 o[0] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 0);
2205 o[1] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 1);
2206 o[3] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 2);
2208 p[0] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 3);
2209 p[1] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 0);
2210 p[2] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 1);
2211 p[3] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 2);
2214 alpha->in_sdtv ? cog_ycbcr_to_rgb_matrix_8bit_sdtv :
2215 cog_ycbcr_to_rgb_matrix_8bit_hdtv, 12 * sizeof (gint));
2217 smin = 128 - alpha->black_sensitivity;
2218 smax = 128 + alpha->white_sensitivity;
2220 for (i = 0; i < height; i++) {
2223 for (j = 0; j < width - 1; j += 2) {
2225 u = src[o[1]] - 128;
2226 v = src[o[3]] - 128;
2228 a = chroma_keying_yuv (pa, &y, &u, &v, cr, cb,
2229 smin, smax, accept_angle_tg, accept_angle_ctg,
2230 one_over_kc, kfgy_scale, kg, noise_level2);
2234 r = APPLY_MATRIX (matrix, 0, y, u, v);
2235 g = APPLY_MATRIX (matrix, 1, y, u, v);
2236 b = APPLY_MATRIX (matrix, 2, y, u, v);
2239 dest[p[1]] = CLAMP (r, 0, 255);
2240 dest[p[2]] = CLAMP (g, 0, 255);
2241 dest[p[3]] = CLAMP (b, 0, 255);
2244 u = src[o[1]] - 128;
2245 v = src[o[3]] - 128;
2247 a = chroma_keying_yuv (pa, &y, &u, &v, cr, cb,
2248 smin, smax, accept_angle_tg, accept_angle_ctg,
2249 one_over_kc, kfgy_scale, kg, noise_level2);
2253 r = APPLY_MATRIX (matrix, 0, y, u, v);
2254 g = APPLY_MATRIX (matrix, 1, y, u, v);
2255 b = APPLY_MATRIX (matrix, 2, y, u, v);
2258 dest[4 + p[1]] = CLAMP (r, 0, 255);
2259 dest[4 + p[2]] = CLAMP (g, 0, 255);
2260 dest[4 + p[3]] = CLAMP (b, 0, 255);
2266 if (j == width - 1) {
2268 u = src[o[1]] - 128;
2269 v = src[o[3]] - 128;
2271 a = chroma_keying_yuv (pa, &y, &u, &v, cr, cb,
2272 smin, smax, accept_angle_tg, accept_angle_ctg,
2273 one_over_kc, kfgy_scale, kg, noise_level2);
2277 r = APPLY_MATRIX (matrix, 0, y, u, v);
2278 g = APPLY_MATRIX (matrix, 1, y, u, v);
2279 b = APPLY_MATRIX (matrix, 2, y, u, v);
2282 dest[p[1]] = CLAMP (r, 0, 255);
2283 dest[p[2]] = CLAMP (g, 0, 255);
2284 dest[p[3]] = CLAMP (b, 0, 255);
2289 src = src_tmp + src_stride;
2293 /* Protected with the alpha lock */
2295 gst_alpha_init_params_full (GstAlpha * alpha,
2296 const GstVideoFormatInfo * in_info, const GstVideoFormatInfo * out_info)
2304 /* RGB->RGB: convert to SDTV YUV, chroma keying, convert back
2305 * YUV->RGB: chroma keying, convert to RGB
2306 * RGB->YUV: convert to YUV, chroma keying
2307 * YUV->YUV: convert matrix, chroma keying
2309 if (GST_VIDEO_FORMAT_INFO_IS_RGB (in_info)
2310 && GST_VIDEO_FORMAT_INFO_IS_RGB (out_info))
2311 matrix = cog_rgb_to_ycbcr_matrix_8bit_sdtv;
2312 else if (GST_VIDEO_FORMAT_INFO_IS_YUV (in_info)
2313 && GST_VIDEO_FORMAT_INFO_IS_RGB (out_info))
2315 (alpha->in_sdtv) ? cog_rgb_to_ycbcr_matrix_8bit_sdtv :
2316 cog_rgb_to_ycbcr_matrix_8bit_hdtv;
2317 else if (GST_VIDEO_FORMAT_INFO_IS_RGB (in_info)
2318 && GST_VIDEO_FORMAT_INFO_IS_YUV (out_info))
2320 (alpha->out_sdtv) ? cog_rgb_to_ycbcr_matrix_8bit_sdtv :
2321 cog_rgb_to_ycbcr_matrix_8bit_hdtv;
2322 else /* yuv -> yuv */
2324 (alpha->out_sdtv) ? cog_rgb_to_ycbcr_matrix_8bit_sdtv :
2325 cog_rgb_to_ycbcr_matrix_8bit_hdtv;
2327 y = (matrix[0] * ((gint) alpha->target_r) +
2328 matrix[1] * ((gint) alpha->target_g) +
2329 matrix[2] * ((gint) alpha->target_b) + matrix[3]) >> 8;
2330 /* Cb,Cr without offset here because the chroma keying
2331 * works with them being in range [-128,127]
2334 (matrix[4] * ((gint) alpha->target_r) +
2335 matrix[5] * ((gint) alpha->target_g) +
2336 matrix[6] * ((gint) alpha->target_b)) >> 8;
2338 (matrix[8] * ((gint) alpha->target_r) +
2339 matrix[9] * ((gint) alpha->target_g) +
2340 matrix[10] * ((gint) alpha->target_b)) >> 8;
2342 kgl = sqrt (tmp1 * tmp1 + tmp2 * tmp2);
2343 alpha->cb = 127 * (tmp1 / kgl);
2344 alpha->cr = 127 * (tmp2 / kgl);
2346 tmp = 15 * tan (M_PI * alpha->angle / 180);
2347 tmp = MIN (tmp, 255);
2348 alpha->accept_angle_tg = tmp;
2349 tmp = 15 / tan (M_PI * alpha->angle / 180);
2350 tmp = MIN (tmp, 255);
2351 alpha->accept_angle_ctg = tmp;
2353 alpha->one_over_kc = 255 * 2 * tmp - 255;
2355 tmp = MIN (tmp, 255);
2356 alpha->kfgy_scale = tmp;
2357 alpha->kg = MIN (kgl, 127);
2359 alpha->noise_level2 = alpha->noise_level * alpha->noise_level;
2363 gst_alpha_init_params (GstAlpha * alpha)
2365 gst_alpha_init_params_full (alpha, GST_VIDEO_FILTER (alpha)->in_info.finfo,
2366 GST_VIDEO_FILTER (alpha)->out_info.finfo);
2369 /* Protected with the alpha lock */
2371 gst_alpha_set_process_function_full (GstAlpha * alpha, GstVideoInfo * in_info,
2372 GstVideoInfo * out_info)
2374 alpha->process = NULL;
2376 switch (alpha->method) {
2377 case ALPHA_METHOD_SET:
2378 switch (GST_VIDEO_INFO_FORMAT (out_info)) {
2379 case GST_VIDEO_FORMAT_AYUV:
2380 switch (GST_VIDEO_INFO_FORMAT (in_info)) {
2381 case GST_VIDEO_FORMAT_AYUV:
2382 alpha->process = gst_alpha_set_ayuv_ayuv;
2384 case GST_VIDEO_FORMAT_Y444:
2385 case GST_VIDEO_FORMAT_Y42B:
2386 case GST_VIDEO_FORMAT_I420:
2387 case GST_VIDEO_FORMAT_YV12:
2388 case GST_VIDEO_FORMAT_Y41B:
2389 alpha->process = gst_alpha_set_planar_yuv_ayuv;
2391 case GST_VIDEO_FORMAT_YUY2:
2392 case GST_VIDEO_FORMAT_YVYU:
2393 case GST_VIDEO_FORMAT_UYVY:
2394 alpha->process = gst_alpha_set_packed_422_ayuv;
2396 case GST_VIDEO_FORMAT_ARGB:
2397 case GST_VIDEO_FORMAT_ABGR:
2398 case GST_VIDEO_FORMAT_RGBA:
2399 case GST_VIDEO_FORMAT_BGRA:
2400 alpha->process = gst_alpha_set_argb_ayuv;
2402 case GST_VIDEO_FORMAT_xRGB:
2403 case GST_VIDEO_FORMAT_xBGR:
2404 case GST_VIDEO_FORMAT_RGBx:
2405 case GST_VIDEO_FORMAT_BGRx:
2406 case GST_VIDEO_FORMAT_RGB:
2407 case GST_VIDEO_FORMAT_BGR:
2408 alpha->process = gst_alpha_set_rgb_ayuv;
2414 case GST_VIDEO_FORMAT_ARGB:
2415 case GST_VIDEO_FORMAT_ABGR:
2416 case GST_VIDEO_FORMAT_RGBA:
2417 case GST_VIDEO_FORMAT_BGRA:
2418 switch (GST_VIDEO_INFO_FORMAT (in_info)) {
2419 case GST_VIDEO_FORMAT_AYUV:
2420 alpha->process = gst_alpha_set_ayuv_argb;
2422 case GST_VIDEO_FORMAT_Y444:
2423 case GST_VIDEO_FORMAT_Y42B:
2424 case GST_VIDEO_FORMAT_I420:
2425 case GST_VIDEO_FORMAT_YV12:
2426 case GST_VIDEO_FORMAT_Y41B:
2427 alpha->process = gst_alpha_set_planar_yuv_argb;
2429 case GST_VIDEO_FORMAT_YUY2:
2430 case GST_VIDEO_FORMAT_YVYU:
2431 case GST_VIDEO_FORMAT_UYVY:
2432 alpha->process = gst_alpha_set_packed_422_argb;
2434 case GST_VIDEO_FORMAT_ARGB:
2435 case GST_VIDEO_FORMAT_ABGR:
2436 case GST_VIDEO_FORMAT_RGBA:
2437 case GST_VIDEO_FORMAT_BGRA:
2438 alpha->process = gst_alpha_set_argb_argb;
2440 case GST_VIDEO_FORMAT_xRGB:
2441 case GST_VIDEO_FORMAT_xBGR:
2442 case GST_VIDEO_FORMAT_RGBx:
2443 case GST_VIDEO_FORMAT_BGRx:
2444 case GST_VIDEO_FORMAT_RGB:
2445 case GST_VIDEO_FORMAT_BGR:
2446 alpha->process = gst_alpha_set_rgb_argb;
2457 case ALPHA_METHOD_GREEN:
2458 case ALPHA_METHOD_BLUE:
2459 case ALPHA_METHOD_CUSTOM:
2460 switch (GST_VIDEO_INFO_FORMAT (out_info)) {
2461 case GST_VIDEO_FORMAT_AYUV:
2462 switch (GST_VIDEO_INFO_FORMAT (in_info)) {
2463 case GST_VIDEO_FORMAT_AYUV:
2464 alpha->process = gst_alpha_chroma_key_ayuv_ayuv;
2466 case GST_VIDEO_FORMAT_Y444:
2467 case GST_VIDEO_FORMAT_Y42B:
2468 case GST_VIDEO_FORMAT_I420:
2469 case GST_VIDEO_FORMAT_YV12:
2470 case GST_VIDEO_FORMAT_Y41B:
2471 alpha->process = gst_alpha_chroma_key_planar_yuv_ayuv;
2473 case GST_VIDEO_FORMAT_YUY2:
2474 case GST_VIDEO_FORMAT_YVYU:
2475 case GST_VIDEO_FORMAT_UYVY:
2476 alpha->process = gst_alpha_chroma_key_packed_422_ayuv;
2478 case GST_VIDEO_FORMAT_ARGB:
2479 case GST_VIDEO_FORMAT_ABGR:
2480 case GST_VIDEO_FORMAT_RGBA:
2481 case GST_VIDEO_FORMAT_BGRA:
2482 alpha->process = gst_alpha_chroma_key_argb_ayuv;
2484 case GST_VIDEO_FORMAT_xRGB:
2485 case GST_VIDEO_FORMAT_xBGR:
2486 case GST_VIDEO_FORMAT_RGBx:
2487 case GST_VIDEO_FORMAT_BGRx:
2488 case GST_VIDEO_FORMAT_RGB:
2489 case GST_VIDEO_FORMAT_BGR:
2490 alpha->process = gst_alpha_chroma_key_rgb_ayuv;
2496 case GST_VIDEO_FORMAT_ARGB:
2497 case GST_VIDEO_FORMAT_ABGR:
2498 case GST_VIDEO_FORMAT_RGBA:
2499 case GST_VIDEO_FORMAT_BGRA:
2500 switch (GST_VIDEO_INFO_FORMAT (in_info)) {
2501 case GST_VIDEO_FORMAT_AYUV:
2502 alpha->process = gst_alpha_chroma_key_ayuv_argb;
2504 case GST_VIDEO_FORMAT_Y444:
2505 case GST_VIDEO_FORMAT_Y42B:
2506 case GST_VIDEO_FORMAT_I420:
2507 case GST_VIDEO_FORMAT_YV12:
2508 case GST_VIDEO_FORMAT_Y41B:
2509 alpha->process = gst_alpha_chroma_key_planar_yuv_argb;
2511 case GST_VIDEO_FORMAT_YUY2:
2512 case GST_VIDEO_FORMAT_YVYU:
2513 case GST_VIDEO_FORMAT_UYVY:
2514 alpha->process = gst_alpha_chroma_key_packed_422_argb;
2516 case GST_VIDEO_FORMAT_ARGB:
2517 case GST_VIDEO_FORMAT_ABGR:
2518 case GST_VIDEO_FORMAT_RGBA:
2519 case GST_VIDEO_FORMAT_BGRA:
2520 alpha->process = gst_alpha_chroma_key_argb_argb;
2522 case GST_VIDEO_FORMAT_xRGB:
2523 case GST_VIDEO_FORMAT_xBGR:
2524 case GST_VIDEO_FORMAT_RGBx:
2525 case GST_VIDEO_FORMAT_BGRx:
2526 case GST_VIDEO_FORMAT_RGB:
2527 case GST_VIDEO_FORMAT_BGR:
2528 alpha->process = gst_alpha_chroma_key_rgb_argb;
2542 return alpha->process != NULL;
2546 gst_alpha_set_process_function (GstAlpha * alpha)
2548 return gst_alpha_set_process_function_full (alpha,
2549 &GST_VIDEO_FILTER_CAST (alpha)->in_info,
2550 &GST_VIDEO_FILTER_CAST (alpha)->out_info);
2554 gst_alpha_before_transform (GstBaseTransform * btrans, GstBuffer * buf)
2556 GstAlpha *alpha = GST_ALPHA (btrans);
2557 GstClockTime timestamp;
2559 timestamp = gst_segment_to_stream_time (&btrans->segment, GST_FORMAT_TIME,
2560 GST_BUFFER_TIMESTAMP (buf));
2561 GST_LOG ("Got stream time of %" GST_TIME_FORMAT, GST_TIME_ARGS (timestamp));
2562 if (GST_CLOCK_TIME_IS_VALID (timestamp))
2563 gst_object_sync_values (GST_OBJECT (alpha), timestamp);
2566 static GstFlowReturn
2567 gst_alpha_transform_frame (GstVideoFilter * filter, GstVideoFrame * in_frame,
2568 GstVideoFrame * out_frame)
2570 GstAlpha *alpha = GST_ALPHA (filter);
2572 GST_ALPHA_LOCK (alpha);
2574 if (G_UNLIKELY (!alpha->process))
2575 goto not_negotiated;
2577 alpha->process (in_frame, out_frame, alpha);
2579 GST_ALPHA_UNLOCK (alpha);
2586 GST_ERROR_OBJECT (alpha, "Not negotiated yet");
2587 GST_ALPHA_UNLOCK (alpha);
2588 return GST_FLOW_NOT_NEGOTIATED;
2593 plugin_init (GstPlugin * plugin)
2595 return gst_element_register (plugin, "alpha", GST_RANK_NONE, GST_TYPE_ALPHA);
2598 GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
2601 "adds an alpha channel to video - constant or via chroma-keying",
2602 plugin_init, VERSION, GST_LICENSE, GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN)