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 #define GST_ALPHA_LOCK(alpha) G_STMT_START { \
149 GST_LOG_OBJECT (alpha, "Locking alpha from thread %p", g_thread_self ()); \
150 g_static_mutex_lock (&alpha->lock); \
151 GST_LOG_OBJECT (alpha, "Locked alpha from thread %p", g_thread_self ()); \
154 #define GST_ALPHA_UNLOCK(alpha) G_STMT_START { \
155 GST_LOG_OBJECT (alpha, "Unlocking alpha from thread %p", g_thread_self ()); \
156 g_static_mutex_unlock (&alpha->lock); \
159 static gboolean gst_alpha_get_unit_size (GstBaseTransform * btrans,
160 GstCaps * caps, gsize * size);
161 static GstCaps *gst_alpha_transform_caps (GstBaseTransform * btrans,
162 GstPadDirection direction, GstCaps * caps, GstCaps * filter);
163 static gboolean gst_alpha_set_caps (GstBaseTransform * btrans,
164 GstCaps * incaps, GstCaps * outcaps);
165 static GstFlowReturn gst_alpha_transform (GstBaseTransform * btrans,
166 GstBuffer * in, GstBuffer * out);
167 static void gst_alpha_before_transform (GstBaseTransform * btrans,
170 static void gst_alpha_init_params (GstAlpha * alpha);
171 static gboolean gst_alpha_set_process_function (GstAlpha * alpha);
173 static void gst_alpha_set_property (GObject * object, guint prop_id,
174 const GValue * value, GParamSpec * pspec);
175 static void gst_alpha_get_property (GObject * object, guint prop_id,
176 GValue * value, GParamSpec * pspec);
177 static void gst_alpha_finalize (GObject * object);
179 #define gst_alpha_parent_class parent_class
180 G_DEFINE_TYPE (GstAlpha, gst_alpha, GST_TYPE_VIDEO_FILTER);
182 #define GST_TYPE_ALPHA_METHOD (gst_alpha_method_get_type())
184 gst_alpha_method_get_type (void)
186 static GType alpha_method_type = 0;
187 static const GEnumValue alpha_method[] = {
188 {ALPHA_METHOD_SET, "Set/adjust alpha channel", "set"},
189 {ALPHA_METHOD_GREEN, "Chroma Key green", "green"},
190 {ALPHA_METHOD_BLUE, "Chroma Key blue", "blue"},
191 {ALPHA_METHOD_CUSTOM, "Chroma Key on target_r/g/b", "custom"},
195 if (!alpha_method_type) {
196 alpha_method_type = g_enum_register_static ("GstAlphaMethod", alpha_method);
198 return alpha_method_type;
202 gst_alpha_class_init (GstAlphaClass * klass)
204 GObjectClass *gobject_class = (GObjectClass *) klass;
205 GstElementClass *gstelement_class = (GstElementClass *) klass;
206 GstBaseTransformClass *btrans_class = (GstBaseTransformClass *) klass;
208 GST_DEBUG_CATEGORY_INIT (gst_alpha_debug, "alpha", 0,
209 "alpha - Element for adding alpha channel to streams");
211 gobject_class->set_property = gst_alpha_set_property;
212 gobject_class->get_property = gst_alpha_get_property;
213 gobject_class->finalize = gst_alpha_finalize;
215 g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_METHOD,
216 g_param_spec_enum ("method", "Method",
217 "How the alpha channels should be created", GST_TYPE_ALPHA_METHOD,
218 DEFAULT_METHOD, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
219 g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_ALPHA,
220 g_param_spec_double ("alpha", "Alpha", "The value for the alpha channel",
221 0.0, 1.0, DEFAULT_ALPHA,
222 G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
223 g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_TARGET_R,
224 g_param_spec_uint ("target-r", "Target Red", "The Red target", 0, 255,
226 G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
227 g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_TARGET_G,
228 g_param_spec_uint ("target-g", "Target Green", "The Green target", 0, 255,
230 G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
231 g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_TARGET_B,
232 g_param_spec_uint ("target-b", "Target Blue", "The Blue target", 0, 255,
234 G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
235 g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_ANGLE,
236 g_param_spec_float ("angle", "Angle", "Size of the colorcube to change",
237 0.0, 90.0, DEFAULT_ANGLE,
238 G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
239 g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_NOISE_LEVEL,
240 g_param_spec_float ("noise-level", "Noise Level", "Size of noise radius",
241 0.0, 64.0, DEFAULT_NOISE_LEVEL,
242 G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
243 g_object_class_install_property (G_OBJECT_CLASS (klass),
244 PROP_BLACK_SENSITIVITY, g_param_spec_uint ("black-sensitivity",
245 "Black Sensitivity", "Sensitivity to dark colors", 0, 128,
246 DEFAULT_BLACK_SENSITIVITY,
247 G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
248 g_object_class_install_property (G_OBJECT_CLASS (klass),
249 PROP_WHITE_SENSITIVITY, g_param_spec_uint ("white-sensitivity",
250 "Sensitivity", "Sensitivity to bright colors", 0, 128,
251 DEFAULT_WHITE_SENSITIVITY,
252 G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
253 g_object_class_install_property (G_OBJECT_CLASS (klass),
254 PROP_PREFER_PASSTHROUGH, g_param_spec_boolean ("prefer-passthrough",
255 "Prefer Passthrough",
256 "Don't do any processing for alpha=1.0 if possible",
257 DEFAULT_PREFER_PASSTHROUGH,
258 G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
260 gst_element_class_set_details_simple (gstelement_class, "Alpha filter",
261 "Filter/Effect/Video",
262 "Adds an alpha channel to video - uniform or via chroma-keying",
263 "Wim Taymans <wim.taymans@gmail.com>\n"
264 "Edward Hervey <edward.hervey@collabora.co.uk>\n"
265 "Jan Schmidt <thaytan@noraisin.net>");
267 gst_element_class_add_pad_template (gstelement_class,
268 gst_static_pad_template_get (&gst_alpha_sink_template));
269 gst_element_class_add_pad_template (gstelement_class,
270 gst_static_pad_template_get (&gst_alpha_src_template));
272 btrans_class->transform = GST_DEBUG_FUNCPTR (gst_alpha_transform);
273 btrans_class->before_transform =
274 GST_DEBUG_FUNCPTR (gst_alpha_before_transform);
275 btrans_class->get_unit_size = GST_DEBUG_FUNCPTR (gst_alpha_get_unit_size);
276 btrans_class->transform_caps = GST_DEBUG_FUNCPTR (gst_alpha_transform_caps);
277 btrans_class->set_caps = GST_DEBUG_FUNCPTR (gst_alpha_set_caps);
281 gst_alpha_init (GstAlpha * alpha)
283 alpha->alpha = DEFAULT_ALPHA;
284 alpha->method = DEFAULT_METHOD;
285 alpha->target_r = DEFAULT_TARGET_R;
286 alpha->target_g = DEFAULT_TARGET_G;
287 alpha->target_b = DEFAULT_TARGET_B;
288 alpha->angle = DEFAULT_ANGLE;
289 alpha->noise_level = DEFAULT_NOISE_LEVEL;
290 alpha->black_sensitivity = DEFAULT_BLACK_SENSITIVITY;
291 alpha->white_sensitivity = DEFAULT_WHITE_SENSITIVITY;
293 g_static_mutex_init (&alpha->lock);
297 gst_alpha_finalize (GObject * object)
299 GstAlpha *alpha = GST_ALPHA (object);
301 g_static_mutex_free (&alpha->lock);
303 G_OBJECT_CLASS (parent_class)->finalize (object);
307 gst_alpha_set_property (GObject * object, guint prop_id,
308 const GValue * value, GParamSpec * pspec)
310 GstAlpha *alpha = GST_ALPHA (object);
311 gboolean reconfigure = FALSE;
313 GST_ALPHA_LOCK (alpha);
316 gint method = g_value_get_enum (value);
318 reconfigure = (method != alpha->method) && (method == ALPHA_METHOD_SET
319 || alpha->method == ALPHA_METHOD_SET) && (alpha->alpha == 1.0)
320 && (alpha->prefer_passthrough);
321 alpha->method = method;
323 switch (alpha->method) {
324 case ALPHA_METHOD_GREEN:
326 alpha->target_g = 255;
329 case ALPHA_METHOD_BLUE:
332 alpha->target_b = 255;
337 gst_alpha_set_process_function (alpha);
338 gst_alpha_init_params (alpha);
342 gdouble a = g_value_get_double (value);
344 reconfigure = (a != alpha->alpha) && (a == 1.0 || alpha->alpha == 1.0)
345 && (alpha->method == ALPHA_METHOD_SET) && (alpha->prefer_passthrough);
350 alpha->target_r = g_value_get_uint (value);
351 gst_alpha_init_params (alpha);
354 alpha->target_g = g_value_get_uint (value);
355 gst_alpha_init_params (alpha);
358 alpha->target_b = g_value_get_uint (value);
359 gst_alpha_init_params (alpha);
362 alpha->angle = g_value_get_float (value);
363 gst_alpha_init_params (alpha);
365 case PROP_NOISE_LEVEL:
366 alpha->noise_level = g_value_get_float (value);
367 gst_alpha_init_params (alpha);
369 case PROP_BLACK_SENSITIVITY:
370 alpha->black_sensitivity = g_value_get_uint (value);
372 case PROP_WHITE_SENSITIVITY:
373 alpha->white_sensitivity = g_value_get_uint (value);
375 case PROP_PREFER_PASSTHROUGH:{
376 gboolean prefer_passthrough = g_value_get_boolean (value);
378 reconfigure = ((! !prefer_passthrough) != (! !alpha->prefer_passthrough))
379 && (alpha->method == ALPHA_METHOD_SET) && (alpha->alpha == 1.0);
380 alpha->prefer_passthrough = prefer_passthrough;
384 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
389 gst_base_transform_reconfigure (GST_BASE_TRANSFORM_CAST (alpha));
391 GST_ALPHA_UNLOCK (alpha);
395 gst_alpha_get_property (GObject * object, guint prop_id, GValue * value,
398 GstAlpha *alpha = GST_ALPHA (object);
402 g_value_set_enum (value, alpha->method);
405 g_value_set_double (value, alpha->alpha);
408 g_value_set_uint (value, alpha->target_r);
411 g_value_set_uint (value, alpha->target_g);
414 g_value_set_uint (value, alpha->target_b);
417 g_value_set_float (value, alpha->angle);
419 case PROP_NOISE_LEVEL:
420 g_value_set_float (value, alpha->noise_level);
422 case PROP_BLACK_SENSITIVITY:
423 g_value_set_uint (value, alpha->black_sensitivity);
425 case PROP_WHITE_SENSITIVITY:
426 g_value_set_uint (value, alpha->white_sensitivity);
428 case PROP_PREFER_PASSTHROUGH:
429 g_value_set_boolean (value, alpha->prefer_passthrough);
432 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
438 gst_alpha_get_unit_size (GstBaseTransform * btrans,
439 GstCaps * caps, gsize * size)
443 if (!gst_video_info_from_caps (&info, caps))
448 GST_DEBUG_OBJECT (btrans, "unit size = %d for format %s w %d height %d",
449 *size, GST_VIDEO_INFO_NAME (&info), GST_VIDEO_INFO_WIDTH (&info),
450 GST_VIDEO_INFO_HEIGHT (&info));
456 gst_alpha_transform_caps (GstBaseTransform * btrans,
457 GstPadDirection direction, GstCaps * caps, GstCaps * filter)
459 GstAlpha *alpha = GST_ALPHA (btrans);
460 GstCaps *ret, *tmp, *tmp2;
461 GstStructure *structure;
464 tmp = gst_caps_new_empty ();
466 GST_ALPHA_LOCK (alpha);
467 for (i = 0; i < gst_caps_get_size (caps); i++) {
468 structure = gst_structure_copy (gst_caps_get_structure (caps, i));
470 gst_structure_remove_field (structure, "format");
471 gst_structure_remove_field (structure, "color-matrix");
472 gst_structure_remove_field (structure, "chroma-site");
474 gst_caps_append_structure (tmp, structure);
477 if (direction == GST_PAD_SINK) {
478 tmp2 = gst_static_caps_get (&gst_alpha_alpha_caps);
479 ret = gst_caps_intersect (tmp, tmp2);
480 gst_caps_unref (tmp);
481 gst_caps_unref (tmp2);
485 if (alpha->prefer_passthrough && alpha->method == ALPHA_METHOD_SET
486 && alpha->alpha == 1.0) {
487 ret = gst_caps_copy (caps);
488 gst_caps_append (ret, tmp);
499 GST_DEBUG_OBJECT (alpha,
500 "Transformed %" GST_PTR_FORMAT " -> %" GST_PTR_FORMAT, caps, ret);
503 GstCaps *intersection;
505 GST_DEBUG_OBJECT (alpha, "Using filter caps %" GST_PTR_FORMAT, filter);
507 gst_caps_intersect_full (filter, ret, GST_CAPS_INTERSECT_FIRST);
508 gst_caps_unref (ret);
510 GST_DEBUG_OBJECT (alpha, "Intersection %" GST_PTR_FORMAT, ret);
514 GST_ALPHA_UNLOCK (alpha);
520 gst_alpha_set_caps (GstBaseTransform * btrans,
521 GstCaps * incaps, GstCaps * outcaps)
523 GstAlpha *alpha = GST_ALPHA (btrans);
524 GstVideoInfo in_info, out_info;
525 gboolean passthrough;
527 if (!gst_video_info_from_caps (&in_info, incaps) ||
528 !gst_video_info_from_caps (&out_info, outcaps))
531 GST_ALPHA_LOCK (alpha);
533 alpha->in_sdtv = in_info.colorimetry.matrix = GST_VIDEO_COLOR_MATRIX_BT601;
534 alpha->out_sdtv = out_info.colorimetry.matrix = GST_VIDEO_COLOR_MATRIX_BT601;
536 passthrough = alpha->prefer_passthrough &&
537 GST_VIDEO_INFO_FORMAT (&in_info) == GST_VIDEO_INFO_FORMAT (&out_info)
538 && alpha->in_sdtv == alpha->out_sdtv && alpha->method == ALPHA_METHOD_SET
539 && alpha->alpha == 1.0;
541 GST_DEBUG_OBJECT (alpha,
542 "Setting caps %" GST_PTR_FORMAT " -> %" GST_PTR_FORMAT
543 " (passthrough: %d)", incaps, outcaps, passthrough);
544 gst_base_transform_set_passthrough (btrans, passthrough);
546 alpha->in_info = in_info;
547 alpha->out_info = out_info;
549 if (!gst_alpha_set_process_function (alpha) && !passthrough)
552 gst_alpha_init_params (alpha);
554 GST_ALPHA_UNLOCK (alpha);
561 GST_WARNING_OBJECT (alpha,
562 "Failed to parse caps %" GST_PTR_FORMAT " -> %" GST_PTR_FORMAT, incaps,
568 GST_WARNING_OBJECT (alpha,
569 "No processing function for this caps and no passthrough mode");
570 GST_ALPHA_UNLOCK (alpha);
575 /* based on http://www.cs.utah.edu/~michael/chroma/
578 chroma_keying_yuv (gint a, gint * y, gint * u,
579 gint * v, gint cr, gint cb, gint smin, gint smax, guint8 accept_angle_tg,
580 guint8 accept_angle_ctg, guint8 one_over_kc, guint8 kfgy_scale, gint8 kg,
588 /* too dark or too bright, keep alpha */
589 if (*y < smin || *y > smax)
592 /* Convert foreground to XZ coords where X direction is defined by
594 tmp = ((*u) * cb + (*v) * cr) >> 7;
595 x = CLAMP (tmp, -128, 127);
596 tmp = ((*v) * cb - (*u) * cr) >> 7;
597 z = CLAMP (tmp, -128, 127);
599 /* WARNING: accept angle should never be set greater than "somewhat less
600 than 90 degrees" to avoid dealing with negative/infinite tg. In reality,
601 80 degrees should be enough if foreground is reasonable. If this seems
602 to be a problem, go to alternative ways of checking point position
603 (scalar product or line equations). This angle should not be too small
604 either to avoid infinite ctg (used to suppress foreground without use of
607 tmp = (x * accept_angle_tg) >> 4;
608 tmp = MIN (tmp, 127);
611 /* keep foreground Kfg = 0 */
614 /* Compute Kfg (implicitly) and Kbg, suppress foreground in XZ coord
616 tmp = (z * accept_angle_ctg) >> 4;
617 tmp = CLAMP (tmp, -128, 127);
622 tmp1 = MAX (tmp1, 0);
623 b_alpha = (tmp1 * one_over_kc) / 2;
624 b_alpha = 255 - CLAMP (b_alpha, 0, 255);
625 b_alpha = (a * b_alpha) >> 8;
627 tmp = (tmp1 * kfgy_scale) >> 4;
628 tmp1 = MIN (tmp, 255);
630 *y = (*y < tmp1) ? 0 : *y - tmp1;
632 /* Convert suppressed foreground back to CbCr */
633 tmp = (x1 * cb - y1 * cr) >> 7;
634 *u = CLAMP (tmp, -128, 127);
636 tmp = (x1 * cr + y1 * cb) >> 7;
637 *v = CLAMP (tmp, -128, 127);
639 /* Deal with noise. For now, a circle around the key color with
640 radius of noise_level treated as exact key color. Introduces
643 tmp = z * z + (x - kg) * (x - kg);
644 tmp = MIN (tmp, 0xffff);
646 if (tmp < noise_level2)
652 #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)
655 gst_alpha_set_argb_ayuv (const GstVideoFrame * in_frame,
656 GstVideoFrame * out_frame, GstAlpha * alpha)
658 gint s_alpha = CLAMP ((gint) (alpha->alpha * 256), 0, 256);
667 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
668 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
670 width = GST_VIDEO_FRAME_WIDTH (in_frame);
671 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
673 o[0] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 3);
674 o[1] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 0);
675 o[2] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 1);
676 o[3] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 2);
679 alpha->out_sdtv ? cog_rgb_to_ycbcr_matrix_8bit_sdtv :
680 cog_rgb_to_ycbcr_matrix_8bit_hdtv, 12 * sizeof (gint));
682 for (i = 0; i < height; i++) {
683 for (j = 0; j < width; j++) {
684 dest[0] = (src[o[0]] * s_alpha) >> 8;
686 y = APPLY_MATRIX (matrix, 0, src[o[1]], src[o[2]], src[o[3]]);
687 u = APPLY_MATRIX (matrix, 1, src[o[1]], src[o[2]], src[o[3]]);
688 v = APPLY_MATRIX (matrix, 2, src[o[1]], src[o[2]], src[o[3]]);
701 gst_alpha_chroma_key_argb_ayuv (const GstVideoFrame * in_frame,
702 GstVideoFrame * out_frame, GstAlpha * alpha)
711 gint pa = CLAMP ((gint) (alpha->alpha * 256), 0, 256);
712 gint8 cb = alpha->cb, cr = alpha->cr;
713 gint8 kg = alpha->kg;
714 guint8 accept_angle_tg = alpha->accept_angle_tg;
715 guint8 accept_angle_ctg = alpha->accept_angle_ctg;
716 guint8 one_over_kc = alpha->one_over_kc;
717 guint8 kfgy_scale = alpha->kfgy_scale;
718 guint noise_level2 = alpha->noise_level2;
722 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
723 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
725 width = GST_VIDEO_FRAME_WIDTH (in_frame);
726 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
728 o[0] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 3);
729 o[1] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 0);
730 o[2] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 1);
731 o[3] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 2);
733 smin = 128 - alpha->black_sensitivity;
734 smax = 128 + alpha->white_sensitivity;
737 alpha->out_sdtv ? cog_rgb_to_ycbcr_matrix_8bit_sdtv :
738 cog_rgb_to_ycbcr_matrix_8bit_hdtv, 12 * sizeof (gint));
740 for (i = 0; i < height; i++) {
741 for (j = 0; j < width; j++) {
742 a = (src[o[0]] * pa) >> 8;
747 y = APPLY_MATRIX (matrix, 0, r, g, b);
748 u = APPLY_MATRIX (matrix, 1, r, g, b) - 128;
749 v = APPLY_MATRIX (matrix, 2, r, g, b) - 128;
751 a = chroma_keying_yuv (a, &y, &u, &v, cr, cb,
752 smin, smax, accept_angle_tg, accept_angle_ctg,
753 one_over_kc, kfgy_scale, kg, noise_level2);
770 gst_alpha_set_argb_argb (const GstVideoFrame * in_frame,
771 GstVideoFrame * out_frame, GstAlpha * alpha)
776 gint s_alpha = CLAMP ((gint) (alpha->alpha * 256), 0, 256);
780 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
781 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
783 width = GST_VIDEO_FRAME_WIDTH (in_frame);
784 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
786 p[0] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 3);
787 p[1] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 0);
788 p[2] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 1);
789 p[3] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 2);
791 o[0] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 3);
792 o[1] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 0);
793 o[2] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 1);
794 o[3] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 2);
796 for (i = 0; i < height; i++) {
797 for (j = 0; j < width; j++) {
798 dest[p[0]] = (src[o[0]] * s_alpha) >> 8;
800 dest[p[1]] = src[o[1]];
801 dest[p[2]] = src[o[2]];
802 dest[p[3]] = src[o[3]];
811 gst_alpha_chroma_key_argb_argb (const GstVideoFrame * in_frame,
812 GstVideoFrame * out_frame, GstAlpha * alpha)
821 gint pa = CLAMP ((gint) (alpha->alpha * 256), 0, 256);
822 gint8 cb = alpha->cb, cr = alpha->cr;
823 gint8 kg = alpha->kg;
824 guint8 accept_angle_tg = alpha->accept_angle_tg;
825 guint8 accept_angle_ctg = alpha->accept_angle_ctg;
826 guint8 one_over_kc = alpha->one_over_kc;
827 guint8 kfgy_scale = alpha->kfgy_scale;
828 guint noise_level2 = alpha->noise_level2;
829 gint matrix[12], matrix2[12];
832 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
833 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
835 width = GST_VIDEO_FRAME_WIDTH (in_frame);
836 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
838 p[0] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 3);
839 p[1] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 0);
840 p[2] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 1);
841 p[3] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 2);
843 o[0] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 3);
844 o[1] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 0);
845 o[2] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 1);
846 o[3] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 2);
848 smin = 128 - alpha->black_sensitivity;
849 smax = 128 + alpha->white_sensitivity;
851 memcpy (matrix, cog_rgb_to_ycbcr_matrix_8bit_sdtv, 12 * sizeof (gint));
852 memcpy (matrix2, cog_ycbcr_to_rgb_matrix_8bit_sdtv, 12 * sizeof (gint));
854 for (i = 0; i < height; i++) {
855 for (j = 0; j < width; j++) {
856 a = (src[o[0]] * pa) >> 8;
861 y = APPLY_MATRIX (matrix, 0, r, g, b);
862 u = APPLY_MATRIX (matrix, 1, r, g, b) - 128;
863 v = APPLY_MATRIX (matrix, 2, r, g, b) - 128;
865 a = chroma_keying_yuv (a, &y, &u, &v, cr, cb,
866 smin, smax, accept_angle_tg, accept_angle_ctg,
867 one_over_kc, kfgy_scale, kg, noise_level2);
872 r = APPLY_MATRIX (matrix2, 0, y, u, v);
873 g = APPLY_MATRIX (matrix2, 1, y, u, v);
874 b = APPLY_MATRIX (matrix2, 2, y, u, v);
877 dest[p[1]] = CLAMP (r, 0, 255);
878 dest[p[2]] = CLAMP (g, 0, 255);
879 dest[p[3]] = CLAMP (b, 0, 255);
888 gst_alpha_set_ayuv_argb (const GstVideoFrame * in_frame,
889 GstVideoFrame * out_frame, GstAlpha * alpha)
894 gint s_alpha = CLAMP ((gint) (alpha->alpha * 256), 0, 256);
900 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
901 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
903 width = GST_VIDEO_FRAME_WIDTH (in_frame);
904 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
906 p[0] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 3);
907 p[1] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 0);
908 p[2] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 1);
909 p[3] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 2);
912 alpha->in_sdtv ? cog_ycbcr_to_rgb_matrix_8bit_sdtv :
913 cog_ycbcr_to_rgb_matrix_8bit_hdtv, 12 * sizeof (gint));
915 for (y = 0; y < height; y++) {
916 for (x = 0; x < width; x++) {
917 dest[p[0]] = (src[0] * s_alpha) >> 8;
919 r = APPLY_MATRIX (matrix, 0, src[1], src[2], src[3]);
920 g = APPLY_MATRIX (matrix, 1, src[1], src[2], src[3]);
921 b = APPLY_MATRIX (matrix, 2, src[1], src[2], src[3]);
923 dest[p[1]] = CLAMP (r, 0, 255);
924 dest[p[2]] = CLAMP (g, 0, 255);
925 dest[p[3]] = CLAMP (b, 0, 255);
934 gst_alpha_chroma_key_ayuv_argb (const GstVideoFrame * in_frame,
935 GstVideoFrame * out_frame, GstAlpha * alpha)
944 gint pa = CLAMP ((gint) (alpha->alpha * 256), 0, 256);
945 gint8 cb = alpha->cb, cr = alpha->cr;
946 gint8 kg = alpha->kg;
947 guint8 accept_angle_tg = alpha->accept_angle_tg;
948 guint8 accept_angle_ctg = alpha->accept_angle_ctg;
949 guint8 one_over_kc = alpha->one_over_kc;
950 guint8 kfgy_scale = alpha->kfgy_scale;
951 guint noise_level2 = alpha->noise_level2;
955 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
956 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
958 width = GST_VIDEO_FRAME_WIDTH (in_frame);
959 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
961 p[0] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 3);
962 p[1] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 0);
963 p[2] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 1);
964 p[3] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 2);
966 smin = 128 - alpha->black_sensitivity;
967 smax = 128 + alpha->white_sensitivity;
970 alpha->in_sdtv ? cog_ycbcr_to_rgb_matrix_8bit_sdtv :
971 cog_ycbcr_to_rgb_matrix_8bit_hdtv, 12 * sizeof (gint));
973 for (i = 0; i < height; i++) {
974 for (j = 0; j < width; j++) {
975 a = (src[0] * pa) >> 8;
980 a = chroma_keying_yuv (a, &y, &u, &v, cr, cb,
981 smin, smax, accept_angle_tg, accept_angle_ctg,
982 one_over_kc, kfgy_scale, kg, noise_level2);
987 r = APPLY_MATRIX (matrix, 0, y, u, v);
988 g = APPLY_MATRIX (matrix, 1, y, u, v);
989 b = APPLY_MATRIX (matrix, 2, y, u, v);
992 dest[p[1]] = CLAMP (r, 0, 255);
993 dest[p[2]] = CLAMP (g, 0, 255);
994 dest[p[3]] = CLAMP (b, 0, 255);
1003 gst_alpha_set_ayuv_ayuv (const GstVideoFrame * in_frame,
1004 GstVideoFrame * out_frame, GstAlpha * alpha)
1009 gint s_alpha = CLAMP ((gint) (alpha->alpha * 256), 0, 256);
1012 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
1013 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
1015 width = GST_VIDEO_FRAME_WIDTH (in_frame);
1016 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
1018 if (alpha->in_sdtv == alpha->out_sdtv) {
1019 for (y = 0; y < height; y++) {
1020 for (x = 0; x < width; x++) {
1021 dest[0] = (src[0] * s_alpha) >> 8;
1034 alpha->out_sdtv ? cog_ycbcr_hdtv_to_ycbcr_sdtv_matrix_8bit :
1035 cog_ycbcr_sdtv_to_ycbcr_hdtv_matrix_8bit, 12 * sizeof (gint));
1037 for (y = 0; y < height; y++) {
1038 for (x = 0; x < width; x++) {
1039 dest[0] = (src[0] * s_alpha) >> 8;
1040 dest[1] = APPLY_MATRIX (matrix, 0, src[1], src[2], src[3]);
1041 dest[2] = APPLY_MATRIX (matrix, 1, src[1], src[2], src[3]);
1042 dest[3] = APPLY_MATRIX (matrix, 2, src[1], src[2], src[3]);
1052 gst_alpha_chroma_key_ayuv_ayuv (const GstVideoFrame * in_frame,
1053 GstVideoFrame * out_frame, GstAlpha * alpha)
1061 gint pa = CLAMP ((gint) (alpha->alpha * 256), 0, 256);
1062 gint8 cb = alpha->cb, cr = alpha->cr;
1063 gint8 kg = alpha->kg;
1064 guint8 accept_angle_tg = alpha->accept_angle_tg;
1065 guint8 accept_angle_ctg = alpha->accept_angle_ctg;
1066 guint8 one_over_kc = alpha->one_over_kc;
1067 guint8 kfgy_scale = alpha->kfgy_scale;
1068 guint noise_level2 = alpha->noise_level2;
1070 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
1071 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
1073 width = GST_VIDEO_FRAME_WIDTH (in_frame);
1074 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
1076 smin = 128 - alpha->black_sensitivity;
1077 smax = 128 + alpha->white_sensitivity;
1079 if (alpha->in_sdtv == alpha->out_sdtv) {
1080 for (i = 0; i < height; i++) {
1081 for (j = 0; j < width; j++) {
1082 a = (src[0] * pa) >> 8;
1087 a = chroma_keying_yuv (a, &y, &u, &v, cr, cb,
1088 smin, smax, accept_angle_tg, accept_angle_ctg,
1089 one_over_kc, kfgy_scale, kg, noise_level2);
1107 alpha->out_sdtv ? cog_ycbcr_hdtv_to_ycbcr_sdtv_matrix_8bit :
1108 cog_ycbcr_sdtv_to_ycbcr_hdtv_matrix_8bit, 12 * sizeof (gint));
1110 for (i = 0; i < height; i++) {
1111 for (j = 0; j < width; j++) {
1112 a = (src[0] * pa) >> 8;
1113 y = APPLY_MATRIX (matrix, 0, src[1], src[2], src[3]);
1114 u = APPLY_MATRIX (matrix, 1, src[1], src[2], src[3]) - 128;
1115 v = APPLY_MATRIX (matrix, 2, src[1], src[2], src[3]) - 128;
1117 a = chroma_keying_yuv (a, &y, &u, &v, cr, cb,
1118 smin, smax, accept_angle_tg, accept_angle_ctg,
1119 one_over_kc, kfgy_scale, kg, noise_level2);
1137 gst_alpha_set_rgb_ayuv (const GstVideoFrame * in_frame,
1138 GstVideoFrame * out_frame, GstAlpha * alpha)
1143 gint s_alpha = CLAMP ((gint) (alpha->alpha * 255), 0, 255);
1150 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
1151 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
1153 width = GST_VIDEO_FRAME_WIDTH (in_frame);
1154 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
1156 bpp = GST_VIDEO_FRAME_COMP_PSTRIDE (in_frame, 0);
1157 o[0] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 0);
1158 o[1] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 1);
1159 o[2] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 2);
1162 alpha->out_sdtv ? cog_rgb_to_ycbcr_matrix_8bit_sdtv :
1163 cog_rgb_to_ycbcr_matrix_8bit_hdtv, 12 * sizeof (gint));
1165 for (i = 0; i < height; i++) {
1166 for (j = 0; j < width; j++) {
1169 y = APPLY_MATRIX (matrix, 0, src[o[0]], src[o[1]], src[o[2]]);
1170 u = APPLY_MATRIX (matrix, 1, src[o[0]], src[o[1]], src[o[2]]);
1171 v = APPLY_MATRIX (matrix, 2, src[o[0]], src[o[1]], src[o[2]]);
1184 gst_alpha_chroma_key_rgb_ayuv (const GstVideoFrame * in_frame,
1185 GstVideoFrame * out_frame, GstAlpha * alpha)
1194 gint pa = CLAMP ((gint) (alpha->alpha * 255), 0, 255);
1195 gint8 cb = alpha->cb, cr = alpha->cr;
1196 gint8 kg = alpha->kg;
1197 guint8 accept_angle_tg = alpha->accept_angle_tg;
1198 guint8 accept_angle_ctg = alpha->accept_angle_ctg;
1199 guint8 one_over_kc = alpha->one_over_kc;
1200 guint8 kfgy_scale = alpha->kfgy_scale;
1201 guint noise_level2 = alpha->noise_level2;
1206 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
1207 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
1209 width = GST_VIDEO_FRAME_WIDTH (in_frame);
1210 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
1212 bpp = GST_VIDEO_FRAME_COMP_PSTRIDE (in_frame, 0);
1214 o[0] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 0);
1215 o[1] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 1);
1216 o[2] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 2);
1218 smin = 128 - alpha->black_sensitivity;
1219 smax = 128 + alpha->white_sensitivity;
1222 alpha->out_sdtv ? cog_rgb_to_ycbcr_matrix_8bit_sdtv :
1223 cog_rgb_to_ycbcr_matrix_8bit_hdtv, 12 * sizeof (gint));
1225 for (i = 0; i < height; i++) {
1226 for (j = 0; j < width; j++) {
1232 y = APPLY_MATRIX (matrix, 0, r, g, b);
1233 u = APPLY_MATRIX (matrix, 1, r, g, b) - 128;
1234 v = APPLY_MATRIX (matrix, 2, r, g, b) - 128;
1236 a = chroma_keying_yuv (a, &y, &u, &v, cr, cb,
1237 smin, smax, accept_angle_tg, accept_angle_ctg,
1238 one_over_kc, kfgy_scale, kg, noise_level2);
1255 gst_alpha_set_rgb_argb (const GstVideoFrame * in_frame,
1256 GstVideoFrame * out_frame, GstAlpha * alpha)
1261 gint s_alpha = CLAMP ((gint) (alpha->alpha * 255), 0, 255);
1266 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
1267 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
1269 width = GST_VIDEO_FRAME_WIDTH (in_frame);
1270 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
1272 bpp = GST_VIDEO_FRAME_COMP_PSTRIDE (in_frame, 0);
1274 o[0] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 0);
1275 o[1] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 1);
1276 o[2] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 2);
1278 p[0] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 3);
1279 p[1] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 0);
1280 p[2] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 1);
1281 p[3] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 2);
1283 for (i = 0; i < height; i++) {
1284 for (j = 0; j < width; j++) {
1285 dest[p[0]] = s_alpha;
1287 dest[p[1]] = src[o[0]];
1288 dest[p[2]] = src[o[1]];
1289 dest[p[3]] = src[o[2]];
1298 gst_alpha_chroma_key_rgb_argb (const GstVideoFrame * in_frame,
1299 GstVideoFrame * out_frame, GstAlpha * alpha)
1308 gint pa = CLAMP ((gint) (alpha->alpha * 255), 0, 255);
1309 gint8 cb = alpha->cb, cr = alpha->cr;
1310 gint8 kg = alpha->kg;
1311 guint8 accept_angle_tg = alpha->accept_angle_tg;
1312 guint8 accept_angle_ctg = alpha->accept_angle_ctg;
1313 guint8 one_over_kc = alpha->one_over_kc;
1314 guint8 kfgy_scale = alpha->kfgy_scale;
1315 guint noise_level2 = alpha->noise_level2;
1316 gint matrix[12], matrix2[12];
1320 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
1321 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
1323 width = GST_VIDEO_FRAME_WIDTH (in_frame);
1324 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
1326 bpp = GST_VIDEO_FRAME_COMP_PSTRIDE (in_frame, 0);
1328 o[0] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 0);
1329 o[1] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 1);
1330 o[2] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 2);
1332 p[0] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 3);
1333 p[1] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 0);
1334 p[2] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 1);
1335 p[3] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 2);
1337 smin = 128 - alpha->black_sensitivity;
1338 smax = 128 + alpha->white_sensitivity;
1340 memcpy (matrix, cog_rgb_to_ycbcr_matrix_8bit_sdtv, 12 * sizeof (gint));
1341 memcpy (matrix2, cog_ycbcr_to_rgb_matrix_8bit_sdtv, 12 * sizeof (gint));
1343 for (i = 0; i < height; i++) {
1344 for (j = 0; j < width; j++) {
1350 y = APPLY_MATRIX (matrix, 0, r, g, b);
1351 u = APPLY_MATRIX (matrix, 1, r, g, b) - 128;
1352 v = APPLY_MATRIX (matrix, 2, r, g, b) - 128;
1354 a = chroma_keying_yuv (a, &y, &u, &v, cr, cb,
1355 smin, smax, accept_angle_tg, accept_angle_ctg,
1356 one_over_kc, kfgy_scale, kg, noise_level2);
1361 r = APPLY_MATRIX (matrix2, 0, y, u, v);
1362 g = APPLY_MATRIX (matrix2, 1, y, u, v);
1363 b = APPLY_MATRIX (matrix2, 2, y, u, v);
1366 dest[p[1]] = CLAMP (r, 0, 255);
1367 dest[p[2]] = CLAMP (g, 0, 255);
1368 dest[p[3]] = CLAMP (b, 0, 255);
1377 gst_alpha_set_planar_yuv_ayuv (const GstVideoFrame * in_frame,
1378 GstVideoFrame * out_frame, GstAlpha * alpha)
1383 gint b_alpha = CLAMP ((gint) (alpha->alpha * 255), 0, 255);
1384 const guint8 *srcY, *srcY_tmp;
1385 const guint8 *srcU, *srcU_tmp;
1386 const guint8 *srcV, *srcV_tmp;
1388 gint y_stride, uv_stride;
1389 gint v_subs, h_subs;
1391 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
1392 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
1394 width = GST_VIDEO_FRAME_WIDTH (in_frame);
1395 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
1397 y_stride = GST_VIDEO_FRAME_COMP_STRIDE (in_frame, 0);
1398 uv_stride = GST_VIDEO_FRAME_COMP_STRIDE (in_frame, 1);
1400 srcY_tmp = srcY = src;
1401 srcU_tmp = srcU = src + GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 1);
1402 srcV_tmp = srcV = src + GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 2);
1404 switch (GST_VIDEO_FRAME_FORMAT (in_frame)) {
1405 case GST_VIDEO_FORMAT_I420:
1406 case GST_VIDEO_FORMAT_YV12:
1407 v_subs = h_subs = 2;
1409 case GST_VIDEO_FORMAT_Y444:
1410 v_subs = h_subs = 1;
1412 case GST_VIDEO_FORMAT_Y42B:
1416 case GST_VIDEO_FORMAT_Y41B:
1421 g_assert_not_reached ();
1425 if (alpha->in_sdtv == alpha->out_sdtv) {
1426 for (i = 0; i < height; i++) {
1427 for (j = 0; j < width; j++) {
1435 if ((j + 1) % h_subs == 0) {
1441 srcY_tmp = srcY = srcY_tmp + y_stride;
1442 if ((i + 1) % v_subs == 0) {
1443 srcU_tmp = srcU = srcU_tmp + uv_stride;
1444 srcV_tmp = srcV = srcV_tmp + uv_stride;
1455 alpha->out_sdtv ? cog_ycbcr_hdtv_to_ycbcr_sdtv_matrix_8bit :
1456 cog_ycbcr_sdtv_to_ycbcr_hdtv_matrix_8bit, 12 * sizeof (gint));
1458 for (i = 0; i < height; i++) {
1459 for (j = 0; j < width; j++) {
1466 dest[1] = APPLY_MATRIX (matrix, 0, y, u, v);
1467 dest[2] = APPLY_MATRIX (matrix, 1, y, u, v);
1468 dest[3] = APPLY_MATRIX (matrix, 2, y, u, v);
1472 if ((j + 1) % h_subs == 0) {
1478 srcY_tmp = srcY = srcY_tmp + y_stride;
1479 if ((i + 1) % v_subs == 0) {
1480 srcU_tmp = srcU = srcU_tmp + uv_stride;
1481 srcV_tmp = srcV = srcV_tmp + uv_stride;
1491 gst_alpha_chroma_key_planar_yuv_ayuv (const GstVideoFrame * in_frame,
1492 GstVideoFrame * out_frame, GstAlpha * alpha)
1497 gint b_alpha = CLAMP ((gint) (alpha->alpha * 255), 0, 255);
1498 const guint8 *srcY, *srcY_tmp;
1499 const guint8 *srcU, *srcU_tmp;
1500 const guint8 *srcV, *srcV_tmp;
1503 gint y_stride, uv_stride;
1504 gint v_subs, h_subs;
1505 gint smin = 128 - alpha->black_sensitivity;
1506 gint smax = 128 + alpha->white_sensitivity;
1507 gint8 cb = alpha->cb, cr = alpha->cr;
1508 gint8 kg = alpha->kg;
1509 guint8 accept_angle_tg = alpha->accept_angle_tg;
1510 guint8 accept_angle_ctg = alpha->accept_angle_ctg;
1511 guint8 one_over_kc = alpha->one_over_kc;
1512 guint8 kfgy_scale = alpha->kfgy_scale;
1513 guint noise_level2 = alpha->noise_level2;
1515 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
1516 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
1518 width = GST_VIDEO_FRAME_WIDTH (in_frame);
1519 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
1521 y_stride = GST_VIDEO_FRAME_COMP_STRIDE (in_frame, 0);
1522 uv_stride = GST_VIDEO_FRAME_COMP_STRIDE (in_frame, 1);
1524 srcY_tmp = srcY = src;
1525 srcU_tmp = srcU = src + GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 1);
1526 srcV_tmp = srcV = src + GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 2);
1528 switch (GST_VIDEO_FRAME_FORMAT (in_frame)) {
1529 case GST_VIDEO_FORMAT_I420:
1530 case GST_VIDEO_FORMAT_YV12:
1531 v_subs = h_subs = 2;
1533 case GST_VIDEO_FORMAT_Y444:
1534 v_subs = h_subs = 1;
1536 case GST_VIDEO_FORMAT_Y42B:
1540 case GST_VIDEO_FORMAT_Y41B:
1545 g_assert_not_reached ();
1549 if (alpha->in_sdtv == alpha->out_sdtv) {
1550 for (i = 0; i < height; i++) {
1551 for (j = 0; j < width; j++) {
1557 a = chroma_keying_yuv (a, &y, &u, &v, cr, cb, smin,
1558 smax, accept_angle_tg, accept_angle_ctg,
1559 one_over_kc, kfgy_scale, kg, noise_level2);
1571 if ((j + 1) % h_subs == 0) {
1577 srcY_tmp = srcY = srcY_tmp + y_stride;
1578 if ((i + 1) % v_subs == 0) {
1579 srcU_tmp = srcU = srcU_tmp + uv_stride;
1580 srcV_tmp = srcV = srcV_tmp + uv_stride;
1590 alpha->out_sdtv ? cog_ycbcr_hdtv_to_ycbcr_sdtv_matrix_8bit :
1591 cog_ycbcr_sdtv_to_ycbcr_hdtv_matrix_8bit, 12 * sizeof (gint));
1593 for (i = 0; i < height; i++) {
1594 for (j = 0; j < width; j++) {
1596 y = APPLY_MATRIX (matrix, 0, srcY[0], srcU[0], srcV[0]);
1597 u = APPLY_MATRIX (matrix, 1, srcY[0], srcU[0], srcV[0]) - 128;
1598 v = APPLY_MATRIX (matrix, 2, srcY[0], srcU[0], srcV[0]) - 128;
1600 a = chroma_keying_yuv (a, &y, &u, &v, cr, cb, smin,
1601 smax, accept_angle_tg, accept_angle_ctg,
1602 one_over_kc, kfgy_scale, kg, noise_level2);
1611 if ((j + 1) % h_subs == 0) {
1617 srcY_tmp = srcY = srcY_tmp + y_stride;
1618 if ((i + 1) % v_subs == 0) {
1619 srcU_tmp = srcU = srcU_tmp + uv_stride;
1620 srcV_tmp = srcV = srcV_tmp + uv_stride;
1630 gst_alpha_set_planar_yuv_argb (const GstVideoFrame * in_frame,
1631 GstVideoFrame * out_frame, GstAlpha * alpha)
1636 gint b_alpha = CLAMP ((gint) (alpha->alpha * 255), 0, 255);
1637 const guint8 *srcY, *srcY_tmp;
1638 const guint8 *srcU, *srcU_tmp;
1639 const guint8 *srcV, *srcV_tmp;
1641 gint y_stride, uv_stride;
1642 gint v_subs, h_subs;
1648 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
1649 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
1651 width = GST_VIDEO_FRAME_WIDTH (in_frame);
1652 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
1654 p[0] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 3);
1655 p[1] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 0);
1656 p[2] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 1);
1657 p[3] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 2);
1659 y_stride = GST_VIDEO_FRAME_COMP_STRIDE (in_frame, 0);
1660 uv_stride = GST_VIDEO_FRAME_COMP_STRIDE (in_frame, 1);
1662 srcY_tmp = srcY = src;
1663 srcU_tmp = srcU = src + GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 1);
1664 srcV_tmp = srcV = src + GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 2);
1666 switch (GST_VIDEO_FRAME_FORMAT (in_frame)) {
1667 case GST_VIDEO_FORMAT_I420:
1668 case GST_VIDEO_FORMAT_YV12:
1669 v_subs = h_subs = 2;
1671 case GST_VIDEO_FORMAT_Y444:
1672 v_subs = h_subs = 1;
1674 case GST_VIDEO_FORMAT_Y42B:
1678 case GST_VIDEO_FORMAT_Y41B:
1683 g_assert_not_reached ();
1688 alpha->in_sdtv ? cog_ycbcr_to_rgb_matrix_8bit_sdtv :
1689 cog_ycbcr_to_rgb_matrix_8bit_hdtv, 12 * sizeof (gint));
1691 for (i = 0; i < height; i++) {
1692 for (j = 0; j < width; j++) {
1699 r = APPLY_MATRIX (matrix, 0, y, u, v);
1700 g = APPLY_MATRIX (matrix, 1, y, u, v);
1701 b = APPLY_MATRIX (matrix, 2, y, u, v);
1702 dest[p[1]] = CLAMP (r, 0, 255);
1703 dest[p[2]] = CLAMP (g, 0, 255);
1704 dest[p[3]] = CLAMP (b, 0, 255);
1708 if ((j + 1) % h_subs == 0) {
1714 srcY_tmp = srcY = srcY_tmp + y_stride;
1715 if ((i + 1) % v_subs == 0) {
1716 srcU_tmp = srcU = srcU_tmp + uv_stride;
1717 srcV_tmp = srcV = srcV_tmp + uv_stride;
1726 gst_alpha_chroma_key_planar_yuv_argb (const GstVideoFrame * in_frame,
1727 GstVideoFrame * out_frame, GstAlpha * alpha)
1732 gint b_alpha = CLAMP ((gint) (alpha->alpha * 255), 0, 255);
1733 const guint8 *srcY, *srcY_tmp;
1734 const guint8 *srcU, *srcU_tmp;
1735 const guint8 *srcV, *srcV_tmp;
1739 gint y_stride, uv_stride;
1740 gint v_subs, h_subs;
1741 gint smin = 128 - alpha->black_sensitivity;
1742 gint smax = 128 + alpha->white_sensitivity;
1743 gint8 cb = alpha->cb, cr = alpha->cr;
1744 gint8 kg = alpha->kg;
1745 guint8 accept_angle_tg = alpha->accept_angle_tg;
1746 guint8 accept_angle_ctg = alpha->accept_angle_ctg;
1747 guint8 one_over_kc = alpha->one_over_kc;
1748 guint8 kfgy_scale = alpha->kfgy_scale;
1749 guint noise_level2 = alpha->noise_level2;
1753 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
1754 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
1756 width = GST_VIDEO_FRAME_WIDTH (in_frame);
1757 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
1759 p[0] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 3);
1760 p[1] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 0);
1761 p[2] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 1);
1762 p[3] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 2);
1764 y_stride = GST_VIDEO_FRAME_COMP_STRIDE (in_frame, 0);
1765 uv_stride = GST_VIDEO_FRAME_COMP_STRIDE (in_frame, 1);
1767 srcY_tmp = srcY = src;
1768 srcU_tmp = srcU = src + GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 1);
1769 srcV_tmp = srcV = src + GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 2);
1771 switch (GST_VIDEO_FRAME_FORMAT (in_frame)) {
1772 case GST_VIDEO_FORMAT_I420:
1773 case GST_VIDEO_FORMAT_YV12:
1774 v_subs = h_subs = 2;
1776 case GST_VIDEO_FORMAT_Y444:
1777 v_subs = h_subs = 1;
1779 case GST_VIDEO_FORMAT_Y42B:
1783 case GST_VIDEO_FORMAT_Y41B:
1788 g_assert_not_reached ();
1793 alpha->in_sdtv ? cog_ycbcr_to_rgb_matrix_8bit_sdtv :
1794 cog_ycbcr_to_rgb_matrix_8bit_hdtv, 12 * sizeof (gint));
1796 for (i = 0; i < height; i++) {
1797 for (j = 0; j < width; j++) {
1803 a = chroma_keying_yuv (a, &y, &u, &v, cr, cb, smin,
1804 smax, accept_angle_tg, accept_angle_ctg,
1805 one_over_kc, kfgy_scale, kg, noise_level2);
1811 r = APPLY_MATRIX (matrix, 0, y, u, v);
1812 g = APPLY_MATRIX (matrix, 1, y, u, v);
1813 b = APPLY_MATRIX (matrix, 2, y, u, v);
1814 dest[p[1]] = CLAMP (r, 0, 255);
1815 dest[p[2]] = CLAMP (g, 0, 255);
1816 dest[p[3]] = CLAMP (b, 0, 255);
1820 if ((j + 1) % h_subs == 0) {
1826 srcY_tmp = srcY = srcY_tmp + y_stride;
1827 if ((i + 1) % v_subs == 0) {
1828 srcU_tmp = srcU = srcU_tmp + uv_stride;
1829 srcV_tmp = srcV = srcV_tmp + uv_stride;
1838 gst_alpha_set_packed_422_ayuv (const GstVideoFrame * in_frame,
1839 GstVideoFrame * out_frame, GstAlpha * alpha)
1844 gint s_alpha = CLAMP ((gint) (alpha->alpha * 255), 0, 255);
1847 gint p[4]; /* Y U Y V */
1849 const guint8 *src_tmp;
1851 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
1852 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
1854 width = GST_VIDEO_FRAME_WIDTH (in_frame);
1855 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
1857 src_stride = GST_VIDEO_FRAME_COMP_STRIDE (in_frame, 0);
1859 p[0] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 0);
1861 p[1] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 1);
1862 p[3] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 2);
1864 if (alpha->in_sdtv != alpha->out_sdtv) {
1868 alpha->in_sdtv ? cog_ycbcr_sdtv_to_ycbcr_hdtv_matrix_8bit :
1869 cog_ycbcr_hdtv_to_ycbcr_sdtv_matrix_8bit, 12 * sizeof (gint));
1871 for (i = 0; i < height; i++) {
1874 for (j = 0; j < width - 1; j += 2) {
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]]);
1886 y = APPLY_MATRIX (matrix, 0, src[p[2]], src[p[1]], src[p[3]]);
1887 u = APPLY_MATRIX (matrix, 1, src[p[2]], src[p[1]], src[p[3]]);
1888 v = APPLY_MATRIX (matrix, 2, src[p[2]], src[p[1]], src[p[3]]);
1898 if (j == width - 1) {
1901 y = APPLY_MATRIX (matrix, 0, src[p[0]], src[p[1]], src[p[3]]);
1902 u = APPLY_MATRIX (matrix, 1, src[p[0]], src[p[1]], src[p[3]]);
1903 v = APPLY_MATRIX (matrix, 2, src[p[0]], src[p[1]], src[p[3]]);
1912 src = src_tmp + src_stride;
1915 for (i = 0; i < height; i++) {
1918 for (j = 0; j < width - 1; j += 2) {
1940 if (j == width - 1) {
1954 src = src_tmp + src_stride;
1960 gst_alpha_chroma_key_packed_422_ayuv (const GstVideoFrame * in_frame,
1961 GstVideoFrame * out_frame, GstAlpha * alpha)
1969 gint pa = CLAMP ((gint) (alpha->alpha * 255), 0, 255);
1970 gint8 cb = alpha->cb, cr = alpha->cr;
1971 gint8 kg = alpha->kg;
1972 guint8 accept_angle_tg = alpha->accept_angle_tg;
1973 guint8 accept_angle_ctg = alpha->accept_angle_ctg;
1974 guint8 one_over_kc = alpha->one_over_kc;
1975 guint8 kfgy_scale = alpha->kfgy_scale;
1976 guint noise_level2 = alpha->noise_level2;
1977 gint p[4]; /* Y U Y V */
1979 const guint8 *src_tmp;
1981 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
1982 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
1984 width = GST_VIDEO_FRAME_WIDTH (in_frame);
1985 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
1987 src_stride = GST_VIDEO_FRAME_COMP_STRIDE (in_frame, 0);
1989 p[0] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 0);
1991 p[1] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 1);
1992 p[3] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 2);
1994 smin = 128 - alpha->black_sensitivity;
1995 smax = 128 + alpha->white_sensitivity;
1997 if (alpha->in_sdtv != alpha->out_sdtv) {
2001 alpha->in_sdtv ? cog_ycbcr_sdtv_to_ycbcr_hdtv_matrix_8bit :
2002 cog_ycbcr_hdtv_to_ycbcr_sdtv_matrix_8bit, 12 * sizeof (gint));
2004 for (i = 0; i < height; i++) {
2007 for (j = 0; j < width - 1; j += 2) {
2008 y = APPLY_MATRIX (matrix, 0, src[p[0]], src[p[1]], src[p[3]]);
2009 u = APPLY_MATRIX (matrix, 1, src[p[0]], src[p[1]], src[p[3]]) - 128;
2010 v = APPLY_MATRIX (matrix, 2, src[p[0]], src[p[1]], src[p[3]]) - 128;
2012 a = chroma_keying_yuv (pa, &y, &u, &v, cr, cb,
2013 smin, smax, accept_angle_tg, accept_angle_ctg,
2014 one_over_kc, kfgy_scale, kg, noise_level2);
2021 y = APPLY_MATRIX (matrix, 0, src[p[2]], src[p[1]], src[p[3]]);
2022 u = APPLY_MATRIX (matrix, 1, src[p[2]], src[p[1]], src[p[3]]) - 128;
2023 v = APPLY_MATRIX (matrix, 2, src[p[2]], src[p[1]], src[p[3]]) - 128;
2025 a = chroma_keying_yuv (pa, &y, &u, &v, cr, cb,
2026 smin, smax, accept_angle_tg, accept_angle_ctg,
2027 one_over_kc, kfgy_scale, kg, noise_level2);
2038 if (j == width - 1) {
2039 y = APPLY_MATRIX (matrix, 0, src[p[0]], src[p[1]], src[p[3]]);
2040 u = APPLY_MATRIX (matrix, 1, src[p[0]], src[p[1]], src[p[3]]) - 128;
2041 v = APPLY_MATRIX (matrix, 2, src[p[0]], src[p[1]], 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);
2055 src = src_tmp + src_stride;
2058 for (i = 0; i < height; i++) {
2061 for (j = 0; j < width - 1; j += 2) {
2063 u = src[p[1]] - 128;
2064 v = src[p[3]] - 128;
2066 a = chroma_keying_yuv (pa, &y, &u, &v, cr, cb,
2067 smin, smax, accept_angle_tg, accept_angle_ctg,
2068 one_over_kc, kfgy_scale, kg, noise_level2);
2076 u = src[p[1]] - 128;
2077 v = src[p[3]] - 128;
2079 a = chroma_keying_yuv (pa, &y, &u, &v, cr, cb,
2080 smin, smax, accept_angle_tg, accept_angle_ctg,
2081 one_over_kc, kfgy_scale, kg, noise_level2);
2092 if (j == width - 1) {
2094 u = src[p[1]] - 128;
2095 v = src[p[3]] - 128;
2097 a = chroma_keying_yuv (pa, &y, &u, &v, cr, cb,
2098 smin, smax, accept_angle_tg, accept_angle_ctg,
2099 one_over_kc, kfgy_scale, kg, noise_level2);
2109 src = src_tmp + src_stride;
2115 gst_alpha_set_packed_422_argb (const GstVideoFrame * in_frame,
2116 GstVideoFrame * out_frame, GstAlpha * alpha)
2121 gint s_alpha = CLAMP ((gint) (alpha->alpha * 255), 0, 255);
2125 const guint8 *src_tmp;
2129 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
2130 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
2132 width = GST_VIDEO_FRAME_WIDTH (in_frame);
2133 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
2135 src_stride = GST_VIDEO_FRAME_COMP_STRIDE (in_frame, 0);
2137 o[0] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 0);
2139 o[1] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 1);
2140 o[3] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 2);
2142 p[0] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 3);
2143 p[1] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 0);
2144 p[2] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 1);
2145 p[3] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 2);
2148 alpha->in_sdtv ? cog_ycbcr_to_rgb_matrix_8bit_sdtv :
2149 cog_ycbcr_to_rgb_matrix_8bit_hdtv, 12 * sizeof (gint));
2151 for (i = 0; i < height; i++) {
2154 for (j = 0; j < width - 1; j += 2) {
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);
2164 r = APPLY_MATRIX (matrix, 0, src[o[2]], src[o[1]], src[o[3]]);
2165 g = APPLY_MATRIX (matrix, 1, src[o[2]], src[o[1]], src[o[3]]);
2166 b = APPLY_MATRIX (matrix, 2, src[o[2]], src[o[1]], src[o[3]]);
2168 dest[4 + p[0]] = s_alpha;
2169 dest[4 + p[1]] = CLAMP (r, 0, 255);
2170 dest[4 + p[2]] = CLAMP (g, 0, 255);
2171 dest[4 + p[3]] = CLAMP (b, 0, 255);
2177 if (j == width - 1) {
2178 r = APPLY_MATRIX (matrix, 0, src[o[0]], src[o[1]], src[o[3]]);
2179 g = APPLY_MATRIX (matrix, 1, src[o[0]], src[o[1]], src[o[3]]);
2180 b = APPLY_MATRIX (matrix, 2, src[o[0]], src[o[1]], src[o[3]]);
2182 dest[p[0]] = s_alpha;
2183 dest[p[1]] = CLAMP (r, 0, 255);
2184 dest[p[2]] = CLAMP (g, 0, 255);
2185 dest[p[3]] = CLAMP (b, 0, 255);
2190 src = src_tmp + src_stride;
2195 gst_alpha_chroma_key_packed_422_argb (const GstVideoFrame * in_frame,
2196 GstVideoFrame * out_frame, GstAlpha * alpha)
2205 gint pa = CLAMP ((gint) (alpha->alpha * 255), 0, 255);
2206 gint8 cb = alpha->cb, cr = alpha->cr;
2207 gint8 kg = alpha->kg;
2208 guint8 accept_angle_tg = alpha->accept_angle_tg;
2209 guint8 accept_angle_ctg = alpha->accept_angle_ctg;
2210 guint8 one_over_kc = alpha->one_over_kc;
2211 guint8 kfgy_scale = alpha->kfgy_scale;
2212 guint noise_level2 = alpha->noise_level2;
2215 const guint8 *src_tmp;
2218 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
2219 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
2221 width = GST_VIDEO_FRAME_WIDTH (in_frame);
2222 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
2224 src_stride = GST_VIDEO_FRAME_COMP_STRIDE (in_frame, 0);
2226 o[0] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 0);
2228 o[1] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 1);
2229 o[3] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 2);
2231 p[0] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 3);
2232 p[1] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 0);
2233 p[2] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 1);
2234 p[3] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 2);
2237 alpha->in_sdtv ? cog_ycbcr_to_rgb_matrix_8bit_sdtv :
2238 cog_ycbcr_to_rgb_matrix_8bit_hdtv, 12 * sizeof (gint));
2240 smin = 128 - alpha->black_sensitivity;
2241 smax = 128 + alpha->white_sensitivity;
2243 for (i = 0; i < height; i++) {
2246 for (j = 0; j < width - 1; j += 2) {
2248 u = src[o[1]] - 128;
2249 v = src[o[3]] - 128;
2251 a = chroma_keying_yuv (pa, &y, &u, &v, cr, cb,
2252 smin, smax, accept_angle_tg, accept_angle_ctg,
2253 one_over_kc, kfgy_scale, kg, noise_level2);
2257 r = APPLY_MATRIX (matrix, 0, y, u, v);
2258 g = APPLY_MATRIX (matrix, 1, y, u, v);
2259 b = APPLY_MATRIX (matrix, 2, y, u, v);
2262 dest[p[1]] = CLAMP (r, 0, 255);
2263 dest[p[2]] = CLAMP (g, 0, 255);
2264 dest[p[3]] = CLAMP (b, 0, 255);
2267 u = src[o[1]] - 128;
2268 v = src[o[3]] - 128;
2270 a = chroma_keying_yuv (pa, &y, &u, &v, cr, cb,
2271 smin, smax, accept_angle_tg, accept_angle_ctg,
2272 one_over_kc, kfgy_scale, kg, noise_level2);
2276 r = APPLY_MATRIX (matrix, 0, y, u, v);
2277 g = APPLY_MATRIX (matrix, 1, y, u, v);
2278 b = APPLY_MATRIX (matrix, 2, y, u, v);
2281 dest[4 + p[1]] = CLAMP (r, 0, 255);
2282 dest[4 + p[2]] = CLAMP (g, 0, 255);
2283 dest[4 + p[3]] = CLAMP (b, 0, 255);
2289 if (j == width - 1) {
2291 u = src[o[1]] - 128;
2292 v = src[o[3]] - 128;
2294 a = chroma_keying_yuv (pa, &y, &u, &v, cr, cb,
2295 smin, smax, accept_angle_tg, accept_angle_ctg,
2296 one_over_kc, kfgy_scale, kg, noise_level2);
2300 r = APPLY_MATRIX (matrix, 0, y, u, v);
2301 g = APPLY_MATRIX (matrix, 1, y, u, v);
2302 b = APPLY_MATRIX (matrix, 2, y, u, v);
2305 dest[p[1]] = CLAMP (r, 0, 255);
2306 dest[p[2]] = CLAMP (g, 0, 255);
2307 dest[p[3]] = CLAMP (b, 0, 255);
2312 src = src_tmp + src_stride;
2316 /* Protected with the alpha lock */
2318 gst_alpha_init_params (GstAlpha * alpha)
2324 const GstVideoFormatInfo *in_info, *out_info;
2327 in_info = alpha->in_info.finfo;
2328 out_info = alpha->out_info.finfo;
2330 /* RGB->RGB: convert to SDTV YUV, chroma keying, convert back
2331 * YUV->RGB: chroma keying, convert to RGB
2332 * RGB->YUV: convert to YUV, chroma keying
2333 * YUV->YUV: convert matrix, chroma keying
2335 if (GST_VIDEO_FORMAT_INFO_IS_RGB (in_info)
2336 && GST_VIDEO_FORMAT_INFO_IS_RGB (out_info))
2337 matrix = cog_rgb_to_ycbcr_matrix_8bit_sdtv;
2338 else if (GST_VIDEO_FORMAT_INFO_IS_YUV (in_info)
2339 && GST_VIDEO_FORMAT_INFO_IS_RGB (out_info))
2341 (alpha->in_sdtv) ? cog_rgb_to_ycbcr_matrix_8bit_sdtv :
2342 cog_rgb_to_ycbcr_matrix_8bit_hdtv;
2343 else if (GST_VIDEO_FORMAT_INFO_IS_RGB (in_info)
2344 && GST_VIDEO_FORMAT_INFO_IS_YUV (out_info))
2346 (alpha->out_sdtv) ? cog_rgb_to_ycbcr_matrix_8bit_sdtv :
2347 cog_rgb_to_ycbcr_matrix_8bit_hdtv;
2348 else /* yuv -> yuv */
2350 (alpha->out_sdtv) ? cog_rgb_to_ycbcr_matrix_8bit_sdtv :
2351 cog_rgb_to_ycbcr_matrix_8bit_hdtv;
2353 y = (matrix[0] * ((gint) alpha->target_r) +
2354 matrix[1] * ((gint) alpha->target_g) +
2355 matrix[2] * ((gint) alpha->target_b) + matrix[3]) >> 8;
2356 /* Cb,Cr without offset here because the chroma keying
2357 * works with them being in range [-128,127]
2360 (matrix[4] * ((gint) alpha->target_r) +
2361 matrix[5] * ((gint) alpha->target_g) +
2362 matrix[6] * ((gint) alpha->target_b)) >> 8;
2364 (matrix[8] * ((gint) alpha->target_r) +
2365 matrix[9] * ((gint) alpha->target_g) +
2366 matrix[10] * ((gint) alpha->target_b)) >> 8;
2368 kgl = sqrt (tmp1 * tmp1 + tmp2 * tmp2);
2369 alpha->cb = 127 * (tmp1 / kgl);
2370 alpha->cr = 127 * (tmp2 / kgl);
2372 tmp = 15 * tan (M_PI * alpha->angle / 180);
2373 tmp = MIN (tmp, 255);
2374 alpha->accept_angle_tg = tmp;
2375 tmp = 15 / tan (M_PI * alpha->angle / 180);
2376 tmp = MIN (tmp, 255);
2377 alpha->accept_angle_ctg = tmp;
2379 alpha->one_over_kc = 255 * 2 * tmp - 255;
2381 tmp = MIN (tmp, 255);
2382 alpha->kfgy_scale = tmp;
2383 alpha->kg = MIN (kgl, 127);
2385 alpha->noise_level2 = alpha->noise_level * alpha->noise_level;
2388 /* Protected with the alpha lock */
2390 gst_alpha_set_process_function (GstAlpha * alpha)
2392 alpha->process = NULL;
2394 switch (alpha->method) {
2395 case ALPHA_METHOD_SET:
2396 switch (GST_VIDEO_INFO_FORMAT (&alpha->out_info)) {
2397 case GST_VIDEO_FORMAT_AYUV:
2398 switch (GST_VIDEO_INFO_FORMAT (&alpha->in_info)) {
2399 case GST_VIDEO_FORMAT_AYUV:
2400 alpha->process = gst_alpha_set_ayuv_ayuv;
2402 case GST_VIDEO_FORMAT_Y444:
2403 case GST_VIDEO_FORMAT_Y42B:
2404 case GST_VIDEO_FORMAT_I420:
2405 case GST_VIDEO_FORMAT_YV12:
2406 case GST_VIDEO_FORMAT_Y41B:
2407 alpha->process = gst_alpha_set_planar_yuv_ayuv;
2409 case GST_VIDEO_FORMAT_YUY2:
2410 case GST_VIDEO_FORMAT_YVYU:
2411 case GST_VIDEO_FORMAT_UYVY:
2412 alpha->process = gst_alpha_set_packed_422_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 alpha->process = gst_alpha_set_argb_ayuv;
2420 case GST_VIDEO_FORMAT_xRGB:
2421 case GST_VIDEO_FORMAT_xBGR:
2422 case GST_VIDEO_FORMAT_RGBx:
2423 case GST_VIDEO_FORMAT_BGRx:
2424 case GST_VIDEO_FORMAT_RGB:
2425 case GST_VIDEO_FORMAT_BGR:
2426 alpha->process = gst_alpha_set_rgb_ayuv;
2432 case GST_VIDEO_FORMAT_ARGB:
2433 case GST_VIDEO_FORMAT_ABGR:
2434 case GST_VIDEO_FORMAT_RGBA:
2435 case GST_VIDEO_FORMAT_BGRA:
2436 switch (GST_VIDEO_INFO_FORMAT (&alpha->in_info)) {
2437 case GST_VIDEO_FORMAT_AYUV:
2438 alpha->process = gst_alpha_set_ayuv_argb;
2440 case GST_VIDEO_FORMAT_Y444:
2441 case GST_VIDEO_FORMAT_Y42B:
2442 case GST_VIDEO_FORMAT_I420:
2443 case GST_VIDEO_FORMAT_YV12:
2444 case GST_VIDEO_FORMAT_Y41B:
2445 alpha->process = gst_alpha_set_planar_yuv_argb;
2447 case GST_VIDEO_FORMAT_YUY2:
2448 case GST_VIDEO_FORMAT_YVYU:
2449 case GST_VIDEO_FORMAT_UYVY:
2450 alpha->process = gst_alpha_set_packed_422_argb;
2452 case GST_VIDEO_FORMAT_ARGB:
2453 case GST_VIDEO_FORMAT_ABGR:
2454 case GST_VIDEO_FORMAT_RGBA:
2455 case GST_VIDEO_FORMAT_BGRA:
2456 alpha->process = gst_alpha_set_argb_argb;
2458 case GST_VIDEO_FORMAT_xRGB:
2459 case GST_VIDEO_FORMAT_xBGR:
2460 case GST_VIDEO_FORMAT_RGBx:
2461 case GST_VIDEO_FORMAT_BGRx:
2462 case GST_VIDEO_FORMAT_RGB:
2463 case GST_VIDEO_FORMAT_BGR:
2464 alpha->process = gst_alpha_set_rgb_argb;
2475 case ALPHA_METHOD_GREEN:
2476 case ALPHA_METHOD_BLUE:
2477 case ALPHA_METHOD_CUSTOM:
2478 switch (GST_VIDEO_INFO_FORMAT (&alpha->out_info)) {
2479 case GST_VIDEO_FORMAT_AYUV:
2480 switch (GST_VIDEO_INFO_FORMAT (&alpha->in_info)) {
2481 case GST_VIDEO_FORMAT_AYUV:
2482 alpha->process = gst_alpha_chroma_key_ayuv_ayuv;
2484 case GST_VIDEO_FORMAT_Y444:
2485 case GST_VIDEO_FORMAT_Y42B:
2486 case GST_VIDEO_FORMAT_I420:
2487 case GST_VIDEO_FORMAT_YV12:
2488 case GST_VIDEO_FORMAT_Y41B:
2489 alpha->process = gst_alpha_chroma_key_planar_yuv_ayuv;
2491 case GST_VIDEO_FORMAT_YUY2:
2492 case GST_VIDEO_FORMAT_YVYU:
2493 case GST_VIDEO_FORMAT_UYVY:
2494 alpha->process = gst_alpha_chroma_key_packed_422_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 alpha->process = gst_alpha_chroma_key_argb_ayuv;
2502 case GST_VIDEO_FORMAT_xRGB:
2503 case GST_VIDEO_FORMAT_xBGR:
2504 case GST_VIDEO_FORMAT_RGBx:
2505 case GST_VIDEO_FORMAT_BGRx:
2506 case GST_VIDEO_FORMAT_RGB:
2507 case GST_VIDEO_FORMAT_BGR:
2508 alpha->process = gst_alpha_chroma_key_rgb_ayuv;
2514 case GST_VIDEO_FORMAT_ARGB:
2515 case GST_VIDEO_FORMAT_ABGR:
2516 case GST_VIDEO_FORMAT_RGBA:
2517 case GST_VIDEO_FORMAT_BGRA:
2518 switch (GST_VIDEO_INFO_FORMAT (&alpha->in_info)) {
2519 case GST_VIDEO_FORMAT_AYUV:
2520 alpha->process = gst_alpha_chroma_key_ayuv_argb;
2522 case GST_VIDEO_FORMAT_Y444:
2523 case GST_VIDEO_FORMAT_Y42B:
2524 case GST_VIDEO_FORMAT_I420:
2525 case GST_VIDEO_FORMAT_YV12:
2526 case GST_VIDEO_FORMAT_Y41B:
2527 alpha->process = gst_alpha_chroma_key_planar_yuv_argb;
2529 case GST_VIDEO_FORMAT_YUY2:
2530 case GST_VIDEO_FORMAT_YVYU:
2531 case GST_VIDEO_FORMAT_UYVY:
2532 alpha->process = gst_alpha_chroma_key_packed_422_argb;
2534 case GST_VIDEO_FORMAT_ARGB:
2535 case GST_VIDEO_FORMAT_ABGR:
2536 case GST_VIDEO_FORMAT_RGBA:
2537 case GST_VIDEO_FORMAT_BGRA:
2538 alpha->process = gst_alpha_chroma_key_argb_argb;
2540 case GST_VIDEO_FORMAT_xRGB:
2541 case GST_VIDEO_FORMAT_xBGR:
2542 case GST_VIDEO_FORMAT_RGBx:
2543 case GST_VIDEO_FORMAT_BGRx:
2544 case GST_VIDEO_FORMAT_RGB:
2545 case GST_VIDEO_FORMAT_BGR:
2546 alpha->process = gst_alpha_chroma_key_rgb_argb;
2560 return alpha->process != NULL;
2564 gst_alpha_before_transform (GstBaseTransform * btrans, GstBuffer * buf)
2566 GstAlpha *alpha = GST_ALPHA (btrans);
2567 GstClockTime timestamp;
2569 timestamp = gst_segment_to_stream_time (&btrans->segment, GST_FORMAT_TIME,
2570 GST_BUFFER_TIMESTAMP (buf));
2571 GST_LOG ("Got stream time of %" GST_TIME_FORMAT, GST_TIME_ARGS (timestamp));
2572 if (GST_CLOCK_TIME_IS_VALID (timestamp))
2573 gst_object_sync_values (GST_OBJECT (alpha), timestamp);
2576 static GstFlowReturn
2577 gst_alpha_transform (GstBaseTransform * btrans, GstBuffer * in, GstBuffer * out)
2579 GstAlpha *alpha = GST_ALPHA (btrans);
2580 GstVideoFrame in_frame, out_frame;
2582 GST_ALPHA_LOCK (alpha);
2584 if (G_UNLIKELY (!alpha->process))
2585 goto not_negotiated;
2587 if (!gst_video_frame_map (&in_frame, &alpha->in_info, in, GST_MAP_READ))
2590 if (!gst_video_frame_map (&out_frame, &alpha->out_info, out, GST_MAP_WRITE))
2593 alpha->process (&in_frame, &out_frame, alpha);
2595 gst_video_frame_unmap (&out_frame);
2596 gst_video_frame_unmap (&in_frame);
2598 GST_ALPHA_UNLOCK (alpha);
2605 GST_ERROR_OBJECT (alpha, "Not negotiated yet");
2606 GST_ALPHA_UNLOCK (alpha);
2607 return GST_FLOW_NOT_NEGOTIATED;
2611 GST_ERROR_OBJECT (alpha, "Invalid input frame");
2612 GST_ALPHA_UNLOCK (alpha);
2617 GST_ERROR_OBJECT (alpha, "Invalid output frame");
2618 gst_video_frame_unmap (&in_frame);
2619 GST_ALPHA_UNLOCK (alpha);
2625 plugin_init (GstPlugin * plugin)
2627 return gst_element_register (plugin, "alpha", GST_RANK_NONE, GST_TYPE_ALPHA);
2630 GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
2633 "adds an alpha channel to video - constant or via chroma-keying",
2634 plugin_init, VERSION, GST_LICENSE, GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN)