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,
449 "unit size = %" G_GSIZE_FORMAT " for format %s w %d height %d", *size,
450 GST_VIDEO_INFO_NAME (&info), GST_VIDEO_INFO_WIDTH (&info),
451 GST_VIDEO_INFO_HEIGHT (&info));
457 gst_alpha_transform_caps (GstBaseTransform * btrans,
458 GstPadDirection direction, GstCaps * caps, GstCaps * filter)
460 GstAlpha *alpha = GST_ALPHA (btrans);
461 GstCaps *ret, *tmp, *tmp2;
462 GstStructure *structure;
465 tmp = gst_caps_new_empty ();
467 GST_ALPHA_LOCK (alpha);
468 for (i = 0; i < gst_caps_get_size (caps); i++) {
469 structure = gst_structure_copy (gst_caps_get_structure (caps, i));
471 gst_structure_remove_field (structure, "format");
472 gst_structure_remove_field (structure, "color-matrix");
473 gst_structure_remove_field (structure, "chroma-site");
475 gst_caps_append_structure (tmp, structure);
478 if (direction == GST_PAD_SINK) {
479 tmp2 = gst_static_caps_get (&gst_alpha_alpha_caps);
480 ret = gst_caps_intersect (tmp, tmp2);
481 gst_caps_unref (tmp);
482 gst_caps_unref (tmp2);
486 if (alpha->prefer_passthrough && alpha->method == ALPHA_METHOD_SET
487 && alpha->alpha == 1.0) {
488 ret = gst_caps_copy (caps);
489 gst_caps_append (ret, tmp);
500 GST_DEBUG_OBJECT (alpha,
501 "Transformed %" GST_PTR_FORMAT " -> %" GST_PTR_FORMAT, caps, ret);
504 GstCaps *intersection;
506 GST_DEBUG_OBJECT (alpha, "Using filter caps %" GST_PTR_FORMAT, filter);
508 gst_caps_intersect_full (filter, ret, GST_CAPS_INTERSECT_FIRST);
509 gst_caps_unref (ret);
511 GST_DEBUG_OBJECT (alpha, "Intersection %" GST_PTR_FORMAT, ret);
515 GST_ALPHA_UNLOCK (alpha);
521 gst_alpha_set_caps (GstBaseTransform * btrans,
522 GstCaps * incaps, GstCaps * outcaps)
524 GstAlpha *alpha = GST_ALPHA (btrans);
525 GstVideoInfo in_info, out_info;
526 gboolean passthrough;
528 if (!gst_video_info_from_caps (&in_info, incaps) ||
529 !gst_video_info_from_caps (&out_info, outcaps))
532 GST_ALPHA_LOCK (alpha);
534 alpha->in_sdtv = in_info.colorimetry.matrix = GST_VIDEO_COLOR_MATRIX_BT601;
535 alpha->out_sdtv = out_info.colorimetry.matrix = GST_VIDEO_COLOR_MATRIX_BT601;
537 passthrough = alpha->prefer_passthrough &&
538 GST_VIDEO_INFO_FORMAT (&in_info) == GST_VIDEO_INFO_FORMAT (&out_info)
539 && alpha->in_sdtv == alpha->out_sdtv && alpha->method == ALPHA_METHOD_SET
540 && alpha->alpha == 1.0;
542 GST_DEBUG_OBJECT (alpha,
543 "Setting caps %" GST_PTR_FORMAT " -> %" GST_PTR_FORMAT
544 " (passthrough: %d)", incaps, outcaps, passthrough);
545 gst_base_transform_set_passthrough (btrans, passthrough);
547 alpha->in_info = in_info;
548 alpha->out_info = out_info;
550 if (!gst_alpha_set_process_function (alpha) && !passthrough)
553 gst_alpha_init_params (alpha);
555 GST_ALPHA_UNLOCK (alpha);
562 GST_WARNING_OBJECT (alpha,
563 "Failed to parse caps %" GST_PTR_FORMAT " -> %" GST_PTR_FORMAT, incaps,
569 GST_WARNING_OBJECT (alpha,
570 "No processing function for this caps and no passthrough mode");
571 GST_ALPHA_UNLOCK (alpha);
576 /* based on http://www.cs.utah.edu/~michael/chroma/
579 chroma_keying_yuv (gint a, gint * y, gint * u,
580 gint * v, gint cr, gint cb, gint smin, gint smax, guint8 accept_angle_tg,
581 guint8 accept_angle_ctg, guint8 one_over_kc, guint8 kfgy_scale, gint8 kg,
589 /* too dark or too bright, keep alpha */
590 if (*y < smin || *y > smax)
593 /* Convert foreground to XZ coords where X direction is defined by
595 tmp = ((*u) * cb + (*v) * cr) >> 7;
596 x = CLAMP (tmp, -128, 127);
597 tmp = ((*v) * cb - (*u) * cr) >> 7;
598 z = CLAMP (tmp, -128, 127);
600 /* WARNING: accept angle should never be set greater than "somewhat less
601 than 90 degrees" to avoid dealing with negative/infinite tg. In reality,
602 80 degrees should be enough if foreground is reasonable. If this seems
603 to be a problem, go to alternative ways of checking point position
604 (scalar product or line equations). This angle should not be too small
605 either to avoid infinite ctg (used to suppress foreground without use of
608 tmp = (x * accept_angle_tg) >> 4;
609 tmp = MIN (tmp, 127);
612 /* keep foreground Kfg = 0 */
615 /* Compute Kfg (implicitly) and Kbg, suppress foreground in XZ coord
617 tmp = (z * accept_angle_ctg) >> 4;
618 tmp = CLAMP (tmp, -128, 127);
623 tmp1 = MAX (tmp1, 0);
624 b_alpha = (tmp1 * one_over_kc) / 2;
625 b_alpha = 255 - CLAMP (b_alpha, 0, 255);
626 b_alpha = (a * b_alpha) >> 8;
628 tmp = (tmp1 * kfgy_scale) >> 4;
629 tmp1 = MIN (tmp, 255);
631 *y = (*y < tmp1) ? 0 : *y - tmp1;
633 /* Convert suppressed foreground back to CbCr */
634 tmp = (x1 * cb - y1 * cr) >> 7;
635 *u = CLAMP (tmp, -128, 127);
637 tmp = (x1 * cr + y1 * cb) >> 7;
638 *v = CLAMP (tmp, -128, 127);
640 /* Deal with noise. For now, a circle around the key color with
641 radius of noise_level treated as exact key color. Introduces
644 tmp = z * z + (x - kg) * (x - kg);
645 tmp = MIN (tmp, 0xffff);
647 if (tmp < noise_level2)
653 #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)
656 gst_alpha_set_argb_ayuv (const GstVideoFrame * in_frame,
657 GstVideoFrame * out_frame, GstAlpha * alpha)
659 gint s_alpha = CLAMP ((gint) (alpha->alpha * 256), 0, 256);
668 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
669 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
671 width = GST_VIDEO_FRAME_WIDTH (in_frame);
672 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
674 o[0] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 3);
675 o[1] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 0);
676 o[2] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 1);
677 o[3] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 2);
680 alpha->out_sdtv ? cog_rgb_to_ycbcr_matrix_8bit_sdtv :
681 cog_rgb_to_ycbcr_matrix_8bit_hdtv, 12 * sizeof (gint));
683 for (i = 0; i < height; i++) {
684 for (j = 0; j < width; j++) {
685 dest[0] = (src[o[0]] * s_alpha) >> 8;
687 y = APPLY_MATRIX (matrix, 0, src[o[1]], src[o[2]], src[o[3]]);
688 u = APPLY_MATRIX (matrix, 1, src[o[1]], src[o[2]], src[o[3]]);
689 v = APPLY_MATRIX (matrix, 2, src[o[1]], src[o[2]], src[o[3]]);
702 gst_alpha_chroma_key_argb_ayuv (const GstVideoFrame * in_frame,
703 GstVideoFrame * out_frame, GstAlpha * alpha)
712 gint pa = CLAMP ((gint) (alpha->alpha * 256), 0, 256);
713 gint8 cb = alpha->cb, cr = alpha->cr;
714 gint8 kg = alpha->kg;
715 guint8 accept_angle_tg = alpha->accept_angle_tg;
716 guint8 accept_angle_ctg = alpha->accept_angle_ctg;
717 guint8 one_over_kc = alpha->one_over_kc;
718 guint8 kfgy_scale = alpha->kfgy_scale;
719 guint noise_level2 = alpha->noise_level2;
723 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
724 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
726 width = GST_VIDEO_FRAME_WIDTH (in_frame);
727 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
729 o[0] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 3);
730 o[1] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 0);
731 o[2] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 1);
732 o[3] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 2);
734 smin = 128 - alpha->black_sensitivity;
735 smax = 128 + alpha->white_sensitivity;
738 alpha->out_sdtv ? cog_rgb_to_ycbcr_matrix_8bit_sdtv :
739 cog_rgb_to_ycbcr_matrix_8bit_hdtv, 12 * sizeof (gint));
741 for (i = 0; i < height; i++) {
742 for (j = 0; j < width; j++) {
743 a = (src[o[0]] * pa) >> 8;
748 y = APPLY_MATRIX (matrix, 0, r, g, b);
749 u = APPLY_MATRIX (matrix, 1, r, g, b) - 128;
750 v = APPLY_MATRIX (matrix, 2, r, g, b) - 128;
752 a = chroma_keying_yuv (a, &y, &u, &v, cr, cb,
753 smin, smax, accept_angle_tg, accept_angle_ctg,
754 one_over_kc, kfgy_scale, kg, noise_level2);
771 gst_alpha_set_argb_argb (const GstVideoFrame * in_frame,
772 GstVideoFrame * out_frame, GstAlpha * alpha)
777 gint s_alpha = CLAMP ((gint) (alpha->alpha * 256), 0, 256);
781 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
782 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
784 width = GST_VIDEO_FRAME_WIDTH (in_frame);
785 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
787 p[0] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 3);
788 p[1] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 0);
789 p[2] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 1);
790 p[3] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 2);
792 o[0] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 3);
793 o[1] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 0);
794 o[2] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 1);
795 o[3] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 2);
797 for (i = 0; i < height; i++) {
798 for (j = 0; j < width; j++) {
799 dest[p[0]] = (src[o[0]] * s_alpha) >> 8;
801 dest[p[1]] = src[o[1]];
802 dest[p[2]] = src[o[2]];
803 dest[p[3]] = src[o[3]];
812 gst_alpha_chroma_key_argb_argb (const GstVideoFrame * in_frame,
813 GstVideoFrame * out_frame, GstAlpha * alpha)
822 gint pa = CLAMP ((gint) (alpha->alpha * 256), 0, 256);
823 gint8 cb = alpha->cb, cr = alpha->cr;
824 gint8 kg = alpha->kg;
825 guint8 accept_angle_tg = alpha->accept_angle_tg;
826 guint8 accept_angle_ctg = alpha->accept_angle_ctg;
827 guint8 one_over_kc = alpha->one_over_kc;
828 guint8 kfgy_scale = alpha->kfgy_scale;
829 guint noise_level2 = alpha->noise_level2;
830 gint matrix[12], matrix2[12];
833 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
834 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
836 width = GST_VIDEO_FRAME_WIDTH (in_frame);
837 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
839 p[0] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 3);
840 p[1] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 0);
841 p[2] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 1);
842 p[3] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 2);
844 o[0] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 3);
845 o[1] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 0);
846 o[2] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 1);
847 o[3] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 2);
849 smin = 128 - alpha->black_sensitivity;
850 smax = 128 + alpha->white_sensitivity;
852 memcpy (matrix, cog_rgb_to_ycbcr_matrix_8bit_sdtv, 12 * sizeof (gint));
853 memcpy (matrix2, cog_ycbcr_to_rgb_matrix_8bit_sdtv, 12 * sizeof (gint));
855 for (i = 0; i < height; i++) {
856 for (j = 0; j < width; j++) {
857 a = (src[o[0]] * pa) >> 8;
862 y = APPLY_MATRIX (matrix, 0, r, g, b);
863 u = APPLY_MATRIX (matrix, 1, r, g, b) - 128;
864 v = APPLY_MATRIX (matrix, 2, r, g, b) - 128;
866 a = chroma_keying_yuv (a, &y, &u, &v, cr, cb,
867 smin, smax, accept_angle_tg, accept_angle_ctg,
868 one_over_kc, kfgy_scale, kg, noise_level2);
873 r = APPLY_MATRIX (matrix2, 0, y, u, v);
874 g = APPLY_MATRIX (matrix2, 1, y, u, v);
875 b = APPLY_MATRIX (matrix2, 2, y, u, v);
878 dest[p[1]] = CLAMP (r, 0, 255);
879 dest[p[2]] = CLAMP (g, 0, 255);
880 dest[p[3]] = CLAMP (b, 0, 255);
889 gst_alpha_set_ayuv_argb (const GstVideoFrame * in_frame,
890 GstVideoFrame * out_frame, GstAlpha * alpha)
895 gint s_alpha = CLAMP ((gint) (alpha->alpha * 256), 0, 256);
901 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
902 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
904 width = GST_VIDEO_FRAME_WIDTH (in_frame);
905 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
907 p[0] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 3);
908 p[1] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 0);
909 p[2] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 1);
910 p[3] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 2);
913 alpha->in_sdtv ? cog_ycbcr_to_rgb_matrix_8bit_sdtv :
914 cog_ycbcr_to_rgb_matrix_8bit_hdtv, 12 * sizeof (gint));
916 for (y = 0; y < height; y++) {
917 for (x = 0; x < width; x++) {
918 dest[p[0]] = (src[0] * s_alpha) >> 8;
920 r = APPLY_MATRIX (matrix, 0, src[1], src[2], src[3]);
921 g = APPLY_MATRIX (matrix, 1, src[1], src[2], src[3]);
922 b = APPLY_MATRIX (matrix, 2, src[1], src[2], src[3]);
924 dest[p[1]] = CLAMP (r, 0, 255);
925 dest[p[2]] = CLAMP (g, 0, 255);
926 dest[p[3]] = CLAMP (b, 0, 255);
935 gst_alpha_chroma_key_ayuv_argb (const GstVideoFrame * in_frame,
936 GstVideoFrame * out_frame, GstAlpha * alpha)
945 gint pa = CLAMP ((gint) (alpha->alpha * 256), 0, 256);
946 gint8 cb = alpha->cb, cr = alpha->cr;
947 gint8 kg = alpha->kg;
948 guint8 accept_angle_tg = alpha->accept_angle_tg;
949 guint8 accept_angle_ctg = alpha->accept_angle_ctg;
950 guint8 one_over_kc = alpha->one_over_kc;
951 guint8 kfgy_scale = alpha->kfgy_scale;
952 guint noise_level2 = alpha->noise_level2;
956 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
957 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
959 width = GST_VIDEO_FRAME_WIDTH (in_frame);
960 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
962 p[0] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 3);
963 p[1] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 0);
964 p[2] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 1);
965 p[3] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 2);
967 smin = 128 - alpha->black_sensitivity;
968 smax = 128 + alpha->white_sensitivity;
971 alpha->in_sdtv ? cog_ycbcr_to_rgb_matrix_8bit_sdtv :
972 cog_ycbcr_to_rgb_matrix_8bit_hdtv, 12 * sizeof (gint));
974 for (i = 0; i < height; i++) {
975 for (j = 0; j < width; j++) {
976 a = (src[0] * pa) >> 8;
981 a = chroma_keying_yuv (a, &y, &u, &v, cr, cb,
982 smin, smax, accept_angle_tg, accept_angle_ctg,
983 one_over_kc, kfgy_scale, kg, noise_level2);
988 r = APPLY_MATRIX (matrix, 0, y, u, v);
989 g = APPLY_MATRIX (matrix, 1, y, u, v);
990 b = APPLY_MATRIX (matrix, 2, y, u, v);
993 dest[p[1]] = CLAMP (r, 0, 255);
994 dest[p[2]] = CLAMP (g, 0, 255);
995 dest[p[3]] = CLAMP (b, 0, 255);
1004 gst_alpha_set_ayuv_ayuv (const GstVideoFrame * in_frame,
1005 GstVideoFrame * out_frame, GstAlpha * alpha)
1010 gint s_alpha = CLAMP ((gint) (alpha->alpha * 256), 0, 256);
1013 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
1014 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
1016 width = GST_VIDEO_FRAME_WIDTH (in_frame);
1017 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
1019 if (alpha->in_sdtv == alpha->out_sdtv) {
1020 for (y = 0; y < height; y++) {
1021 for (x = 0; x < width; x++) {
1022 dest[0] = (src[0] * s_alpha) >> 8;
1035 alpha->out_sdtv ? cog_ycbcr_hdtv_to_ycbcr_sdtv_matrix_8bit :
1036 cog_ycbcr_sdtv_to_ycbcr_hdtv_matrix_8bit, 12 * sizeof (gint));
1038 for (y = 0; y < height; y++) {
1039 for (x = 0; x < width; x++) {
1040 dest[0] = (src[0] * s_alpha) >> 8;
1041 dest[1] = APPLY_MATRIX (matrix, 0, src[1], src[2], src[3]);
1042 dest[2] = APPLY_MATRIX (matrix, 1, src[1], src[2], src[3]);
1043 dest[3] = APPLY_MATRIX (matrix, 2, src[1], src[2], src[3]);
1053 gst_alpha_chroma_key_ayuv_ayuv (const GstVideoFrame * in_frame,
1054 GstVideoFrame * out_frame, GstAlpha * alpha)
1062 gint pa = CLAMP ((gint) (alpha->alpha * 256), 0, 256);
1063 gint8 cb = alpha->cb, cr = alpha->cr;
1064 gint8 kg = alpha->kg;
1065 guint8 accept_angle_tg = alpha->accept_angle_tg;
1066 guint8 accept_angle_ctg = alpha->accept_angle_ctg;
1067 guint8 one_over_kc = alpha->one_over_kc;
1068 guint8 kfgy_scale = alpha->kfgy_scale;
1069 guint noise_level2 = alpha->noise_level2;
1071 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
1072 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
1074 width = GST_VIDEO_FRAME_WIDTH (in_frame);
1075 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
1077 smin = 128 - alpha->black_sensitivity;
1078 smax = 128 + alpha->white_sensitivity;
1080 if (alpha->in_sdtv == alpha->out_sdtv) {
1081 for (i = 0; i < height; i++) {
1082 for (j = 0; j < width; j++) {
1083 a = (src[0] * pa) >> 8;
1088 a = chroma_keying_yuv (a, &y, &u, &v, cr, cb,
1089 smin, smax, accept_angle_tg, accept_angle_ctg,
1090 one_over_kc, kfgy_scale, kg, noise_level2);
1108 alpha->out_sdtv ? cog_ycbcr_hdtv_to_ycbcr_sdtv_matrix_8bit :
1109 cog_ycbcr_sdtv_to_ycbcr_hdtv_matrix_8bit, 12 * sizeof (gint));
1111 for (i = 0; i < height; i++) {
1112 for (j = 0; j < width; j++) {
1113 a = (src[0] * pa) >> 8;
1114 y = APPLY_MATRIX (matrix, 0, src[1], src[2], src[3]);
1115 u = APPLY_MATRIX (matrix, 1, src[1], src[2], src[3]) - 128;
1116 v = APPLY_MATRIX (matrix, 2, src[1], src[2], src[3]) - 128;
1118 a = chroma_keying_yuv (a, &y, &u, &v, cr, cb,
1119 smin, smax, accept_angle_tg, accept_angle_ctg,
1120 one_over_kc, kfgy_scale, kg, noise_level2);
1138 gst_alpha_set_rgb_ayuv (const GstVideoFrame * in_frame,
1139 GstVideoFrame * out_frame, GstAlpha * alpha)
1144 gint s_alpha = CLAMP ((gint) (alpha->alpha * 255), 0, 255);
1151 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
1152 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
1154 width = GST_VIDEO_FRAME_WIDTH (in_frame);
1155 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
1157 bpp = GST_VIDEO_FRAME_COMP_PSTRIDE (in_frame, 0);
1158 o[0] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 0);
1159 o[1] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 1);
1160 o[2] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 2);
1163 alpha->out_sdtv ? cog_rgb_to_ycbcr_matrix_8bit_sdtv :
1164 cog_rgb_to_ycbcr_matrix_8bit_hdtv, 12 * sizeof (gint));
1166 for (i = 0; i < height; i++) {
1167 for (j = 0; j < width; j++) {
1170 y = APPLY_MATRIX (matrix, 0, src[o[0]], src[o[1]], src[o[2]]);
1171 u = APPLY_MATRIX (matrix, 1, src[o[0]], src[o[1]], src[o[2]]);
1172 v = APPLY_MATRIX (matrix, 2, src[o[0]], src[o[1]], src[o[2]]);
1185 gst_alpha_chroma_key_rgb_ayuv (const GstVideoFrame * in_frame,
1186 GstVideoFrame * out_frame, GstAlpha * alpha)
1195 gint pa = CLAMP ((gint) (alpha->alpha * 255), 0, 255);
1196 gint8 cb = alpha->cb, cr = alpha->cr;
1197 gint8 kg = alpha->kg;
1198 guint8 accept_angle_tg = alpha->accept_angle_tg;
1199 guint8 accept_angle_ctg = alpha->accept_angle_ctg;
1200 guint8 one_over_kc = alpha->one_over_kc;
1201 guint8 kfgy_scale = alpha->kfgy_scale;
1202 guint noise_level2 = alpha->noise_level2;
1207 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
1208 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
1210 width = GST_VIDEO_FRAME_WIDTH (in_frame);
1211 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
1213 bpp = GST_VIDEO_FRAME_COMP_PSTRIDE (in_frame, 0);
1215 o[0] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 0);
1216 o[1] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 1);
1217 o[2] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 2);
1219 smin = 128 - alpha->black_sensitivity;
1220 smax = 128 + alpha->white_sensitivity;
1223 alpha->out_sdtv ? cog_rgb_to_ycbcr_matrix_8bit_sdtv :
1224 cog_rgb_to_ycbcr_matrix_8bit_hdtv, 12 * sizeof (gint));
1226 for (i = 0; i < height; i++) {
1227 for (j = 0; j < width; j++) {
1233 y = APPLY_MATRIX (matrix, 0, r, g, b);
1234 u = APPLY_MATRIX (matrix, 1, r, g, b) - 128;
1235 v = APPLY_MATRIX (matrix, 2, r, g, b) - 128;
1237 a = chroma_keying_yuv (a, &y, &u, &v, cr, cb,
1238 smin, smax, accept_angle_tg, accept_angle_ctg,
1239 one_over_kc, kfgy_scale, kg, noise_level2);
1256 gst_alpha_set_rgb_argb (const GstVideoFrame * in_frame,
1257 GstVideoFrame * out_frame, GstAlpha * alpha)
1262 gint s_alpha = CLAMP ((gint) (alpha->alpha * 255), 0, 255);
1267 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
1268 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
1270 width = GST_VIDEO_FRAME_WIDTH (in_frame);
1271 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
1273 bpp = GST_VIDEO_FRAME_COMP_PSTRIDE (in_frame, 0);
1275 o[0] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 0);
1276 o[1] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 1);
1277 o[2] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 2);
1279 p[0] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 3);
1280 p[1] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 0);
1281 p[2] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 1);
1282 p[3] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 2);
1284 for (i = 0; i < height; i++) {
1285 for (j = 0; j < width; j++) {
1286 dest[p[0]] = s_alpha;
1288 dest[p[1]] = src[o[0]];
1289 dest[p[2]] = src[o[1]];
1290 dest[p[3]] = src[o[2]];
1299 gst_alpha_chroma_key_rgb_argb (const GstVideoFrame * in_frame,
1300 GstVideoFrame * out_frame, GstAlpha * alpha)
1309 gint pa = CLAMP ((gint) (alpha->alpha * 255), 0, 255);
1310 gint8 cb = alpha->cb, cr = alpha->cr;
1311 gint8 kg = alpha->kg;
1312 guint8 accept_angle_tg = alpha->accept_angle_tg;
1313 guint8 accept_angle_ctg = alpha->accept_angle_ctg;
1314 guint8 one_over_kc = alpha->one_over_kc;
1315 guint8 kfgy_scale = alpha->kfgy_scale;
1316 guint noise_level2 = alpha->noise_level2;
1317 gint matrix[12], matrix2[12];
1321 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
1322 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
1324 width = GST_VIDEO_FRAME_WIDTH (in_frame);
1325 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
1327 bpp = GST_VIDEO_FRAME_COMP_PSTRIDE (in_frame, 0);
1329 o[0] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 0);
1330 o[1] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 1);
1331 o[2] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 2);
1333 p[0] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 3);
1334 p[1] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 0);
1335 p[2] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 1);
1336 p[3] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 2);
1338 smin = 128 - alpha->black_sensitivity;
1339 smax = 128 + alpha->white_sensitivity;
1341 memcpy (matrix, cog_rgb_to_ycbcr_matrix_8bit_sdtv, 12 * sizeof (gint));
1342 memcpy (matrix2, cog_ycbcr_to_rgb_matrix_8bit_sdtv, 12 * sizeof (gint));
1344 for (i = 0; i < height; i++) {
1345 for (j = 0; j < width; j++) {
1351 y = APPLY_MATRIX (matrix, 0, r, g, b);
1352 u = APPLY_MATRIX (matrix, 1, r, g, b) - 128;
1353 v = APPLY_MATRIX (matrix, 2, r, g, b) - 128;
1355 a = chroma_keying_yuv (a, &y, &u, &v, cr, cb,
1356 smin, smax, accept_angle_tg, accept_angle_ctg,
1357 one_over_kc, kfgy_scale, kg, noise_level2);
1362 r = APPLY_MATRIX (matrix2, 0, y, u, v);
1363 g = APPLY_MATRIX (matrix2, 1, y, u, v);
1364 b = APPLY_MATRIX (matrix2, 2, y, u, v);
1367 dest[p[1]] = CLAMP (r, 0, 255);
1368 dest[p[2]] = CLAMP (g, 0, 255);
1369 dest[p[3]] = CLAMP (b, 0, 255);
1378 gst_alpha_set_planar_yuv_ayuv (const GstVideoFrame * in_frame,
1379 GstVideoFrame * out_frame, GstAlpha * alpha)
1384 gint b_alpha = CLAMP ((gint) (alpha->alpha * 255), 0, 255);
1385 const guint8 *srcY, *srcY_tmp;
1386 const guint8 *srcU, *srcU_tmp;
1387 const guint8 *srcV, *srcV_tmp;
1389 gint y_stride, uv_stride;
1390 gint v_subs, h_subs;
1392 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
1393 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
1395 width = GST_VIDEO_FRAME_WIDTH (in_frame);
1396 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
1398 y_stride = GST_VIDEO_FRAME_COMP_STRIDE (in_frame, 0);
1399 uv_stride = GST_VIDEO_FRAME_COMP_STRIDE (in_frame, 1);
1401 srcY_tmp = srcY = src;
1402 srcU_tmp = srcU = src + GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 1);
1403 srcV_tmp = srcV = src + GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 2);
1405 switch (GST_VIDEO_FRAME_FORMAT (in_frame)) {
1406 case GST_VIDEO_FORMAT_I420:
1407 case GST_VIDEO_FORMAT_YV12:
1408 v_subs = h_subs = 2;
1410 case GST_VIDEO_FORMAT_Y444:
1411 v_subs = h_subs = 1;
1413 case GST_VIDEO_FORMAT_Y42B:
1417 case GST_VIDEO_FORMAT_Y41B:
1422 g_assert_not_reached ();
1426 if (alpha->in_sdtv == alpha->out_sdtv) {
1427 for (i = 0; i < height; i++) {
1428 for (j = 0; j < width; j++) {
1436 if ((j + 1) % h_subs == 0) {
1442 srcY_tmp = srcY = srcY_tmp + y_stride;
1443 if ((i + 1) % v_subs == 0) {
1444 srcU_tmp = srcU = srcU_tmp + uv_stride;
1445 srcV_tmp = srcV = srcV_tmp + uv_stride;
1456 alpha->out_sdtv ? cog_ycbcr_hdtv_to_ycbcr_sdtv_matrix_8bit :
1457 cog_ycbcr_sdtv_to_ycbcr_hdtv_matrix_8bit, 12 * sizeof (gint));
1459 for (i = 0; i < height; i++) {
1460 for (j = 0; j < width; j++) {
1467 dest[1] = APPLY_MATRIX (matrix, 0, y, u, v);
1468 dest[2] = APPLY_MATRIX (matrix, 1, y, u, v);
1469 dest[3] = APPLY_MATRIX (matrix, 2, y, u, v);
1473 if ((j + 1) % h_subs == 0) {
1479 srcY_tmp = srcY = srcY_tmp + y_stride;
1480 if ((i + 1) % v_subs == 0) {
1481 srcU_tmp = srcU = srcU_tmp + uv_stride;
1482 srcV_tmp = srcV = srcV_tmp + uv_stride;
1492 gst_alpha_chroma_key_planar_yuv_ayuv (const GstVideoFrame * in_frame,
1493 GstVideoFrame * out_frame, GstAlpha * alpha)
1498 gint b_alpha = CLAMP ((gint) (alpha->alpha * 255), 0, 255);
1499 const guint8 *srcY, *srcY_tmp;
1500 const guint8 *srcU, *srcU_tmp;
1501 const guint8 *srcV, *srcV_tmp;
1504 gint y_stride, uv_stride;
1505 gint v_subs, h_subs;
1506 gint smin = 128 - alpha->black_sensitivity;
1507 gint smax = 128 + alpha->white_sensitivity;
1508 gint8 cb = alpha->cb, cr = alpha->cr;
1509 gint8 kg = alpha->kg;
1510 guint8 accept_angle_tg = alpha->accept_angle_tg;
1511 guint8 accept_angle_ctg = alpha->accept_angle_ctg;
1512 guint8 one_over_kc = alpha->one_over_kc;
1513 guint8 kfgy_scale = alpha->kfgy_scale;
1514 guint noise_level2 = alpha->noise_level2;
1516 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
1517 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
1519 width = GST_VIDEO_FRAME_WIDTH (in_frame);
1520 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
1522 y_stride = GST_VIDEO_FRAME_COMP_STRIDE (in_frame, 0);
1523 uv_stride = GST_VIDEO_FRAME_COMP_STRIDE (in_frame, 1);
1525 srcY_tmp = srcY = src;
1526 srcU_tmp = srcU = src + GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 1);
1527 srcV_tmp = srcV = src + GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 2);
1529 switch (GST_VIDEO_FRAME_FORMAT (in_frame)) {
1530 case GST_VIDEO_FORMAT_I420:
1531 case GST_VIDEO_FORMAT_YV12:
1532 v_subs = h_subs = 2;
1534 case GST_VIDEO_FORMAT_Y444:
1535 v_subs = h_subs = 1;
1537 case GST_VIDEO_FORMAT_Y42B:
1541 case GST_VIDEO_FORMAT_Y41B:
1546 g_assert_not_reached ();
1550 if (alpha->in_sdtv == alpha->out_sdtv) {
1551 for (i = 0; i < height; i++) {
1552 for (j = 0; j < width; j++) {
1558 a = chroma_keying_yuv (a, &y, &u, &v, cr, cb, smin,
1559 smax, accept_angle_tg, accept_angle_ctg,
1560 one_over_kc, kfgy_scale, kg, noise_level2);
1572 if ((j + 1) % h_subs == 0) {
1578 srcY_tmp = srcY = srcY_tmp + y_stride;
1579 if ((i + 1) % v_subs == 0) {
1580 srcU_tmp = srcU = srcU_tmp + uv_stride;
1581 srcV_tmp = srcV = srcV_tmp + uv_stride;
1591 alpha->out_sdtv ? cog_ycbcr_hdtv_to_ycbcr_sdtv_matrix_8bit :
1592 cog_ycbcr_sdtv_to_ycbcr_hdtv_matrix_8bit, 12 * sizeof (gint));
1594 for (i = 0; i < height; i++) {
1595 for (j = 0; j < width; j++) {
1597 y = APPLY_MATRIX (matrix, 0, srcY[0], srcU[0], srcV[0]);
1598 u = APPLY_MATRIX (matrix, 1, srcY[0], srcU[0], srcV[0]) - 128;
1599 v = APPLY_MATRIX (matrix, 2, srcY[0], srcU[0], srcV[0]) - 128;
1601 a = chroma_keying_yuv (a, &y, &u, &v, cr, cb, smin,
1602 smax, accept_angle_tg, accept_angle_ctg,
1603 one_over_kc, kfgy_scale, kg, noise_level2);
1612 if ((j + 1) % h_subs == 0) {
1618 srcY_tmp = srcY = srcY_tmp + y_stride;
1619 if ((i + 1) % v_subs == 0) {
1620 srcU_tmp = srcU = srcU_tmp + uv_stride;
1621 srcV_tmp = srcV = srcV_tmp + uv_stride;
1631 gst_alpha_set_planar_yuv_argb (const GstVideoFrame * in_frame,
1632 GstVideoFrame * out_frame, GstAlpha * alpha)
1637 gint b_alpha = CLAMP ((gint) (alpha->alpha * 255), 0, 255);
1638 const guint8 *srcY, *srcY_tmp;
1639 const guint8 *srcU, *srcU_tmp;
1640 const guint8 *srcV, *srcV_tmp;
1642 gint y_stride, uv_stride;
1643 gint v_subs, h_subs;
1649 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
1650 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
1652 width = GST_VIDEO_FRAME_WIDTH (in_frame);
1653 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
1655 p[0] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 3);
1656 p[1] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 0);
1657 p[2] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 1);
1658 p[3] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 2);
1660 y_stride = GST_VIDEO_FRAME_COMP_STRIDE (in_frame, 0);
1661 uv_stride = GST_VIDEO_FRAME_COMP_STRIDE (in_frame, 1);
1663 srcY_tmp = srcY = src;
1664 srcU_tmp = srcU = src + GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 1);
1665 srcV_tmp = srcV = src + GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 2);
1667 switch (GST_VIDEO_FRAME_FORMAT (in_frame)) {
1668 case GST_VIDEO_FORMAT_I420:
1669 case GST_VIDEO_FORMAT_YV12:
1670 v_subs = h_subs = 2;
1672 case GST_VIDEO_FORMAT_Y444:
1673 v_subs = h_subs = 1;
1675 case GST_VIDEO_FORMAT_Y42B:
1679 case GST_VIDEO_FORMAT_Y41B:
1684 g_assert_not_reached ();
1689 alpha->in_sdtv ? cog_ycbcr_to_rgb_matrix_8bit_sdtv :
1690 cog_ycbcr_to_rgb_matrix_8bit_hdtv, 12 * sizeof (gint));
1692 for (i = 0; i < height; i++) {
1693 for (j = 0; j < width; j++) {
1700 r = APPLY_MATRIX (matrix, 0, y, u, v);
1701 g = APPLY_MATRIX (matrix, 1, y, u, v);
1702 b = APPLY_MATRIX (matrix, 2, y, u, v);
1703 dest[p[1]] = CLAMP (r, 0, 255);
1704 dest[p[2]] = CLAMP (g, 0, 255);
1705 dest[p[3]] = CLAMP (b, 0, 255);
1709 if ((j + 1) % h_subs == 0) {
1715 srcY_tmp = srcY = srcY_tmp + y_stride;
1716 if ((i + 1) % v_subs == 0) {
1717 srcU_tmp = srcU = srcU_tmp + uv_stride;
1718 srcV_tmp = srcV = srcV_tmp + uv_stride;
1727 gst_alpha_chroma_key_planar_yuv_argb (const GstVideoFrame * in_frame,
1728 GstVideoFrame * out_frame, GstAlpha * alpha)
1733 gint b_alpha = CLAMP ((gint) (alpha->alpha * 255), 0, 255);
1734 const guint8 *srcY, *srcY_tmp;
1735 const guint8 *srcU, *srcU_tmp;
1736 const guint8 *srcV, *srcV_tmp;
1740 gint y_stride, uv_stride;
1741 gint v_subs, h_subs;
1742 gint smin = 128 - alpha->black_sensitivity;
1743 gint smax = 128 + alpha->white_sensitivity;
1744 gint8 cb = alpha->cb, cr = alpha->cr;
1745 gint8 kg = alpha->kg;
1746 guint8 accept_angle_tg = alpha->accept_angle_tg;
1747 guint8 accept_angle_ctg = alpha->accept_angle_ctg;
1748 guint8 one_over_kc = alpha->one_over_kc;
1749 guint8 kfgy_scale = alpha->kfgy_scale;
1750 guint noise_level2 = alpha->noise_level2;
1754 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
1755 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
1757 width = GST_VIDEO_FRAME_WIDTH (in_frame);
1758 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
1760 p[0] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 3);
1761 p[1] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 0);
1762 p[2] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 1);
1763 p[3] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 2);
1765 y_stride = GST_VIDEO_FRAME_COMP_STRIDE (in_frame, 0);
1766 uv_stride = GST_VIDEO_FRAME_COMP_STRIDE (in_frame, 1);
1768 srcY_tmp = srcY = src;
1769 srcU_tmp = srcU = src + GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 1);
1770 srcV_tmp = srcV = src + GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 2);
1772 switch (GST_VIDEO_FRAME_FORMAT (in_frame)) {
1773 case GST_VIDEO_FORMAT_I420:
1774 case GST_VIDEO_FORMAT_YV12:
1775 v_subs = h_subs = 2;
1777 case GST_VIDEO_FORMAT_Y444:
1778 v_subs = h_subs = 1;
1780 case GST_VIDEO_FORMAT_Y42B:
1784 case GST_VIDEO_FORMAT_Y41B:
1789 g_assert_not_reached ();
1794 alpha->in_sdtv ? cog_ycbcr_to_rgb_matrix_8bit_sdtv :
1795 cog_ycbcr_to_rgb_matrix_8bit_hdtv, 12 * sizeof (gint));
1797 for (i = 0; i < height; i++) {
1798 for (j = 0; j < width; j++) {
1804 a = chroma_keying_yuv (a, &y, &u, &v, cr, cb, smin,
1805 smax, accept_angle_tg, accept_angle_ctg,
1806 one_over_kc, kfgy_scale, kg, noise_level2);
1812 r = APPLY_MATRIX (matrix, 0, y, u, v);
1813 g = APPLY_MATRIX (matrix, 1, y, u, v);
1814 b = APPLY_MATRIX (matrix, 2, y, u, v);
1815 dest[p[1]] = CLAMP (r, 0, 255);
1816 dest[p[2]] = CLAMP (g, 0, 255);
1817 dest[p[3]] = CLAMP (b, 0, 255);
1821 if ((j + 1) % h_subs == 0) {
1827 srcY_tmp = srcY = srcY_tmp + y_stride;
1828 if ((i + 1) % v_subs == 0) {
1829 srcU_tmp = srcU = srcU_tmp + uv_stride;
1830 srcV_tmp = srcV = srcV_tmp + uv_stride;
1839 gst_alpha_set_packed_422_ayuv (const GstVideoFrame * in_frame,
1840 GstVideoFrame * out_frame, GstAlpha * alpha)
1845 gint s_alpha = CLAMP ((gint) (alpha->alpha * 255), 0, 255);
1848 gint p[4]; /* Y U Y V */
1850 const guint8 *src_tmp;
1852 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
1853 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
1855 width = GST_VIDEO_FRAME_WIDTH (in_frame);
1856 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
1858 src_stride = GST_VIDEO_FRAME_COMP_STRIDE (in_frame, 0);
1860 p[0] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 0);
1862 p[1] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 1);
1863 p[3] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 2);
1865 if (alpha->in_sdtv != alpha->out_sdtv) {
1869 alpha->in_sdtv ? cog_ycbcr_sdtv_to_ycbcr_hdtv_matrix_8bit :
1870 cog_ycbcr_hdtv_to_ycbcr_sdtv_matrix_8bit, 12 * sizeof (gint));
1872 for (i = 0; i < height; i++) {
1875 for (j = 0; j < width - 1; j += 2) {
1879 y = APPLY_MATRIX (matrix, 0, src[p[0]], src[p[1]], src[p[3]]);
1880 u = APPLY_MATRIX (matrix, 1, src[p[0]], src[p[1]], src[p[3]]);
1881 v = APPLY_MATRIX (matrix, 2, src[p[0]], src[p[1]], src[p[3]]);
1887 y = APPLY_MATRIX (matrix, 0, src[p[2]], src[p[1]], src[p[3]]);
1888 u = APPLY_MATRIX (matrix, 1, src[p[2]], src[p[1]], src[p[3]]);
1889 v = APPLY_MATRIX (matrix, 2, src[p[2]], src[p[1]], src[p[3]]);
1899 if (j == width - 1) {
1902 y = APPLY_MATRIX (matrix, 0, src[p[0]], src[p[1]], src[p[3]]);
1903 u = APPLY_MATRIX (matrix, 1, src[p[0]], src[p[1]], src[p[3]]);
1904 v = APPLY_MATRIX (matrix, 2, src[p[0]], src[p[1]], src[p[3]]);
1913 src = src_tmp + src_stride;
1916 for (i = 0; i < height; i++) {
1919 for (j = 0; j < width - 1; j += 2) {
1941 if (j == width - 1) {
1955 src = src_tmp + src_stride;
1961 gst_alpha_chroma_key_packed_422_ayuv (const GstVideoFrame * in_frame,
1962 GstVideoFrame * out_frame, GstAlpha * alpha)
1970 gint pa = CLAMP ((gint) (alpha->alpha * 255), 0, 255);
1971 gint8 cb = alpha->cb, cr = alpha->cr;
1972 gint8 kg = alpha->kg;
1973 guint8 accept_angle_tg = alpha->accept_angle_tg;
1974 guint8 accept_angle_ctg = alpha->accept_angle_ctg;
1975 guint8 one_over_kc = alpha->one_over_kc;
1976 guint8 kfgy_scale = alpha->kfgy_scale;
1977 guint noise_level2 = alpha->noise_level2;
1978 gint p[4]; /* Y U Y V */
1980 const guint8 *src_tmp;
1982 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
1983 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
1985 width = GST_VIDEO_FRAME_WIDTH (in_frame);
1986 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
1988 src_stride = GST_VIDEO_FRAME_COMP_STRIDE (in_frame, 0);
1990 p[0] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 0);
1992 p[1] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 1);
1993 p[3] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 2);
1995 smin = 128 - alpha->black_sensitivity;
1996 smax = 128 + alpha->white_sensitivity;
1998 if (alpha->in_sdtv != alpha->out_sdtv) {
2002 alpha->in_sdtv ? cog_ycbcr_sdtv_to_ycbcr_hdtv_matrix_8bit :
2003 cog_ycbcr_hdtv_to_ycbcr_sdtv_matrix_8bit, 12 * sizeof (gint));
2005 for (i = 0; i < height; i++) {
2008 for (j = 0; j < width - 1; j += 2) {
2009 y = APPLY_MATRIX (matrix, 0, src[p[0]], src[p[1]], src[p[3]]);
2010 u = APPLY_MATRIX (matrix, 1, src[p[0]], src[p[1]], src[p[3]]) - 128;
2011 v = APPLY_MATRIX (matrix, 2, src[p[0]], src[p[1]], src[p[3]]) - 128;
2013 a = chroma_keying_yuv (pa, &y, &u, &v, cr, cb,
2014 smin, smax, accept_angle_tg, accept_angle_ctg,
2015 one_over_kc, kfgy_scale, kg, noise_level2);
2022 y = APPLY_MATRIX (matrix, 0, src[p[2]], src[p[1]], src[p[3]]);
2023 u = APPLY_MATRIX (matrix, 1, src[p[2]], src[p[1]], src[p[3]]) - 128;
2024 v = APPLY_MATRIX (matrix, 2, src[p[2]], src[p[1]], src[p[3]]) - 128;
2026 a = chroma_keying_yuv (pa, &y, &u, &v, cr, cb,
2027 smin, smax, accept_angle_tg, accept_angle_ctg,
2028 one_over_kc, kfgy_scale, kg, noise_level2);
2039 if (j == width - 1) {
2040 y = APPLY_MATRIX (matrix, 0, src[p[0]], src[p[1]], src[p[3]]);
2041 u = APPLY_MATRIX (matrix, 1, src[p[0]], src[p[1]], src[p[3]]) - 128;
2042 v = APPLY_MATRIX (matrix, 2, src[p[0]], src[p[1]], src[p[3]]) - 128;
2044 a = chroma_keying_yuv (pa, &y, &u, &v, cr, cb,
2045 smin, smax, accept_angle_tg, accept_angle_ctg,
2046 one_over_kc, kfgy_scale, kg, noise_level2);
2056 src = src_tmp + src_stride;
2059 for (i = 0; i < height; i++) {
2062 for (j = 0; j < width - 1; j += 2) {
2064 u = src[p[1]] - 128;
2065 v = src[p[3]] - 128;
2067 a = chroma_keying_yuv (pa, &y, &u, &v, cr, cb,
2068 smin, smax, accept_angle_tg, accept_angle_ctg,
2069 one_over_kc, kfgy_scale, kg, noise_level2);
2077 u = src[p[1]] - 128;
2078 v = src[p[3]] - 128;
2080 a = chroma_keying_yuv (pa, &y, &u, &v, cr, cb,
2081 smin, smax, accept_angle_tg, accept_angle_ctg,
2082 one_over_kc, kfgy_scale, kg, noise_level2);
2093 if (j == width - 1) {
2095 u = src[p[1]] - 128;
2096 v = src[p[3]] - 128;
2098 a = chroma_keying_yuv (pa, &y, &u, &v, cr, cb,
2099 smin, smax, accept_angle_tg, accept_angle_ctg,
2100 one_over_kc, kfgy_scale, kg, noise_level2);
2110 src = src_tmp + src_stride;
2116 gst_alpha_set_packed_422_argb (const GstVideoFrame * in_frame,
2117 GstVideoFrame * out_frame, GstAlpha * alpha)
2122 gint s_alpha = CLAMP ((gint) (alpha->alpha * 255), 0, 255);
2126 const guint8 *src_tmp;
2130 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
2131 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
2133 width = GST_VIDEO_FRAME_WIDTH (in_frame);
2134 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
2136 src_stride = GST_VIDEO_FRAME_COMP_STRIDE (in_frame, 0);
2138 o[0] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 0);
2140 o[1] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 1);
2141 o[3] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 2);
2143 p[0] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 3);
2144 p[1] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 0);
2145 p[2] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 1);
2146 p[3] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 2);
2149 alpha->in_sdtv ? cog_ycbcr_to_rgb_matrix_8bit_sdtv :
2150 cog_ycbcr_to_rgb_matrix_8bit_hdtv, 12 * sizeof (gint));
2152 for (i = 0; i < height; i++) {
2155 for (j = 0; j < width - 1; j += 2) {
2156 r = APPLY_MATRIX (matrix, 0, src[o[0]], src[o[1]], src[o[3]]);
2157 g = APPLY_MATRIX (matrix, 1, src[o[0]], src[o[1]], src[o[3]]);
2158 b = APPLY_MATRIX (matrix, 2, src[o[0]], src[o[1]], src[o[3]]);
2160 dest[p[0]] = s_alpha;
2161 dest[p[1]] = CLAMP (r, 0, 255);
2162 dest[p[2]] = CLAMP (g, 0, 255);
2163 dest[p[3]] = CLAMP (b, 0, 255);
2165 r = APPLY_MATRIX (matrix, 0, src[o[2]], src[o[1]], src[o[3]]);
2166 g = APPLY_MATRIX (matrix, 1, src[o[2]], src[o[1]], src[o[3]]);
2167 b = APPLY_MATRIX (matrix, 2, src[o[2]], src[o[1]], src[o[3]]);
2169 dest[4 + p[0]] = s_alpha;
2170 dest[4 + p[1]] = CLAMP (r, 0, 255);
2171 dest[4 + p[2]] = CLAMP (g, 0, 255);
2172 dest[4 + p[3]] = CLAMP (b, 0, 255);
2178 if (j == width - 1) {
2179 r = APPLY_MATRIX (matrix, 0, src[o[0]], src[o[1]], src[o[3]]);
2180 g = APPLY_MATRIX (matrix, 1, src[o[0]], src[o[1]], src[o[3]]);
2181 b = APPLY_MATRIX (matrix, 2, src[o[0]], src[o[1]], src[o[3]]);
2183 dest[p[0]] = s_alpha;
2184 dest[p[1]] = CLAMP (r, 0, 255);
2185 dest[p[2]] = CLAMP (g, 0, 255);
2186 dest[p[3]] = CLAMP (b, 0, 255);
2191 src = src_tmp + src_stride;
2196 gst_alpha_chroma_key_packed_422_argb (const GstVideoFrame * in_frame,
2197 GstVideoFrame * out_frame, GstAlpha * alpha)
2206 gint pa = CLAMP ((gint) (alpha->alpha * 255), 0, 255);
2207 gint8 cb = alpha->cb, cr = alpha->cr;
2208 gint8 kg = alpha->kg;
2209 guint8 accept_angle_tg = alpha->accept_angle_tg;
2210 guint8 accept_angle_ctg = alpha->accept_angle_ctg;
2211 guint8 one_over_kc = alpha->one_over_kc;
2212 guint8 kfgy_scale = alpha->kfgy_scale;
2213 guint noise_level2 = alpha->noise_level2;
2216 const guint8 *src_tmp;
2219 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
2220 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
2222 width = GST_VIDEO_FRAME_WIDTH (in_frame);
2223 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
2225 src_stride = GST_VIDEO_FRAME_COMP_STRIDE (in_frame, 0);
2227 o[0] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 0);
2229 o[1] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 1);
2230 o[3] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 2);
2232 p[0] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 3);
2233 p[1] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 0);
2234 p[2] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 1);
2235 p[3] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 2);
2238 alpha->in_sdtv ? cog_ycbcr_to_rgb_matrix_8bit_sdtv :
2239 cog_ycbcr_to_rgb_matrix_8bit_hdtv, 12 * sizeof (gint));
2241 smin = 128 - alpha->black_sensitivity;
2242 smax = 128 + alpha->white_sensitivity;
2244 for (i = 0; i < height; i++) {
2247 for (j = 0; j < width - 1; j += 2) {
2249 u = src[o[1]] - 128;
2250 v = src[o[3]] - 128;
2252 a = chroma_keying_yuv (pa, &y, &u, &v, cr, cb,
2253 smin, smax, accept_angle_tg, accept_angle_ctg,
2254 one_over_kc, kfgy_scale, kg, noise_level2);
2258 r = APPLY_MATRIX (matrix, 0, y, u, v);
2259 g = APPLY_MATRIX (matrix, 1, y, u, v);
2260 b = APPLY_MATRIX (matrix, 2, y, u, v);
2263 dest[p[1]] = CLAMP (r, 0, 255);
2264 dest[p[2]] = CLAMP (g, 0, 255);
2265 dest[p[3]] = CLAMP (b, 0, 255);
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[4 + p[1]] = CLAMP (r, 0, 255);
2283 dest[4 + p[2]] = CLAMP (g, 0, 255);
2284 dest[4 + p[3]] = CLAMP (b, 0, 255);
2290 if (j == width - 1) {
2292 u = src[o[1]] - 128;
2293 v = src[o[3]] - 128;
2295 a = chroma_keying_yuv (pa, &y, &u, &v, cr, cb,
2296 smin, smax, accept_angle_tg, accept_angle_ctg,
2297 one_over_kc, kfgy_scale, kg, noise_level2);
2301 r = APPLY_MATRIX (matrix, 0, y, u, v);
2302 g = APPLY_MATRIX (matrix, 1, y, u, v);
2303 b = APPLY_MATRIX (matrix, 2, y, u, v);
2306 dest[p[1]] = CLAMP (r, 0, 255);
2307 dest[p[2]] = CLAMP (g, 0, 255);
2308 dest[p[3]] = CLAMP (b, 0, 255);
2313 src = src_tmp + src_stride;
2317 /* Protected with the alpha lock */
2319 gst_alpha_init_params (GstAlpha * alpha)
2325 const GstVideoFormatInfo *in_info, *out_info;
2328 in_info = alpha->in_info.finfo;
2329 out_info = alpha->out_info.finfo;
2331 /* RGB->RGB: convert to SDTV YUV, chroma keying, convert back
2332 * YUV->RGB: chroma keying, convert to RGB
2333 * RGB->YUV: convert to YUV, chroma keying
2334 * YUV->YUV: convert matrix, chroma keying
2336 if (GST_VIDEO_FORMAT_INFO_IS_RGB (in_info)
2337 && GST_VIDEO_FORMAT_INFO_IS_RGB (out_info))
2338 matrix = cog_rgb_to_ycbcr_matrix_8bit_sdtv;
2339 else if (GST_VIDEO_FORMAT_INFO_IS_YUV (in_info)
2340 && GST_VIDEO_FORMAT_INFO_IS_RGB (out_info))
2342 (alpha->in_sdtv) ? cog_rgb_to_ycbcr_matrix_8bit_sdtv :
2343 cog_rgb_to_ycbcr_matrix_8bit_hdtv;
2344 else if (GST_VIDEO_FORMAT_INFO_IS_RGB (in_info)
2345 && GST_VIDEO_FORMAT_INFO_IS_YUV (out_info))
2347 (alpha->out_sdtv) ? cog_rgb_to_ycbcr_matrix_8bit_sdtv :
2348 cog_rgb_to_ycbcr_matrix_8bit_hdtv;
2349 else /* yuv -> yuv */
2351 (alpha->out_sdtv) ? cog_rgb_to_ycbcr_matrix_8bit_sdtv :
2352 cog_rgb_to_ycbcr_matrix_8bit_hdtv;
2354 y = (matrix[0] * ((gint) alpha->target_r) +
2355 matrix[1] * ((gint) alpha->target_g) +
2356 matrix[2] * ((gint) alpha->target_b) + matrix[3]) >> 8;
2357 /* Cb,Cr without offset here because the chroma keying
2358 * works with them being in range [-128,127]
2361 (matrix[4] * ((gint) alpha->target_r) +
2362 matrix[5] * ((gint) alpha->target_g) +
2363 matrix[6] * ((gint) alpha->target_b)) >> 8;
2365 (matrix[8] * ((gint) alpha->target_r) +
2366 matrix[9] * ((gint) alpha->target_g) +
2367 matrix[10] * ((gint) alpha->target_b)) >> 8;
2369 kgl = sqrt (tmp1 * tmp1 + tmp2 * tmp2);
2370 alpha->cb = 127 * (tmp1 / kgl);
2371 alpha->cr = 127 * (tmp2 / kgl);
2373 tmp = 15 * tan (M_PI * alpha->angle / 180);
2374 tmp = MIN (tmp, 255);
2375 alpha->accept_angle_tg = tmp;
2376 tmp = 15 / tan (M_PI * alpha->angle / 180);
2377 tmp = MIN (tmp, 255);
2378 alpha->accept_angle_ctg = tmp;
2380 alpha->one_over_kc = 255 * 2 * tmp - 255;
2382 tmp = MIN (tmp, 255);
2383 alpha->kfgy_scale = tmp;
2384 alpha->kg = MIN (kgl, 127);
2386 alpha->noise_level2 = alpha->noise_level * alpha->noise_level;
2389 /* Protected with the alpha lock */
2391 gst_alpha_set_process_function (GstAlpha * alpha)
2393 alpha->process = NULL;
2395 switch (alpha->method) {
2396 case ALPHA_METHOD_SET:
2397 switch (GST_VIDEO_INFO_FORMAT (&alpha->out_info)) {
2398 case GST_VIDEO_FORMAT_AYUV:
2399 switch (GST_VIDEO_INFO_FORMAT (&alpha->in_info)) {
2400 case GST_VIDEO_FORMAT_AYUV:
2401 alpha->process = gst_alpha_set_ayuv_ayuv;
2403 case GST_VIDEO_FORMAT_Y444:
2404 case GST_VIDEO_FORMAT_Y42B:
2405 case GST_VIDEO_FORMAT_I420:
2406 case GST_VIDEO_FORMAT_YV12:
2407 case GST_VIDEO_FORMAT_Y41B:
2408 alpha->process = gst_alpha_set_planar_yuv_ayuv;
2410 case GST_VIDEO_FORMAT_YUY2:
2411 case GST_VIDEO_FORMAT_YVYU:
2412 case GST_VIDEO_FORMAT_UYVY:
2413 alpha->process = gst_alpha_set_packed_422_ayuv;
2415 case GST_VIDEO_FORMAT_ARGB:
2416 case GST_VIDEO_FORMAT_ABGR:
2417 case GST_VIDEO_FORMAT_RGBA:
2418 case GST_VIDEO_FORMAT_BGRA:
2419 alpha->process = gst_alpha_set_argb_ayuv;
2421 case GST_VIDEO_FORMAT_xRGB:
2422 case GST_VIDEO_FORMAT_xBGR:
2423 case GST_VIDEO_FORMAT_RGBx:
2424 case GST_VIDEO_FORMAT_BGRx:
2425 case GST_VIDEO_FORMAT_RGB:
2426 case GST_VIDEO_FORMAT_BGR:
2427 alpha->process = gst_alpha_set_rgb_ayuv;
2433 case GST_VIDEO_FORMAT_ARGB:
2434 case GST_VIDEO_FORMAT_ABGR:
2435 case GST_VIDEO_FORMAT_RGBA:
2436 case GST_VIDEO_FORMAT_BGRA:
2437 switch (GST_VIDEO_INFO_FORMAT (&alpha->in_info)) {
2438 case GST_VIDEO_FORMAT_AYUV:
2439 alpha->process = gst_alpha_set_ayuv_argb;
2441 case GST_VIDEO_FORMAT_Y444:
2442 case GST_VIDEO_FORMAT_Y42B:
2443 case GST_VIDEO_FORMAT_I420:
2444 case GST_VIDEO_FORMAT_YV12:
2445 case GST_VIDEO_FORMAT_Y41B:
2446 alpha->process = gst_alpha_set_planar_yuv_argb;
2448 case GST_VIDEO_FORMAT_YUY2:
2449 case GST_VIDEO_FORMAT_YVYU:
2450 case GST_VIDEO_FORMAT_UYVY:
2451 alpha->process = gst_alpha_set_packed_422_argb;
2453 case GST_VIDEO_FORMAT_ARGB:
2454 case GST_VIDEO_FORMAT_ABGR:
2455 case GST_VIDEO_FORMAT_RGBA:
2456 case GST_VIDEO_FORMAT_BGRA:
2457 alpha->process = gst_alpha_set_argb_argb;
2459 case GST_VIDEO_FORMAT_xRGB:
2460 case GST_VIDEO_FORMAT_xBGR:
2461 case GST_VIDEO_FORMAT_RGBx:
2462 case GST_VIDEO_FORMAT_BGRx:
2463 case GST_VIDEO_FORMAT_RGB:
2464 case GST_VIDEO_FORMAT_BGR:
2465 alpha->process = gst_alpha_set_rgb_argb;
2476 case ALPHA_METHOD_GREEN:
2477 case ALPHA_METHOD_BLUE:
2478 case ALPHA_METHOD_CUSTOM:
2479 switch (GST_VIDEO_INFO_FORMAT (&alpha->out_info)) {
2480 case GST_VIDEO_FORMAT_AYUV:
2481 switch (GST_VIDEO_INFO_FORMAT (&alpha->in_info)) {
2482 case GST_VIDEO_FORMAT_AYUV:
2483 alpha->process = gst_alpha_chroma_key_ayuv_ayuv;
2485 case GST_VIDEO_FORMAT_Y444:
2486 case GST_VIDEO_FORMAT_Y42B:
2487 case GST_VIDEO_FORMAT_I420:
2488 case GST_VIDEO_FORMAT_YV12:
2489 case GST_VIDEO_FORMAT_Y41B:
2490 alpha->process = gst_alpha_chroma_key_planar_yuv_ayuv;
2492 case GST_VIDEO_FORMAT_YUY2:
2493 case GST_VIDEO_FORMAT_YVYU:
2494 case GST_VIDEO_FORMAT_UYVY:
2495 alpha->process = gst_alpha_chroma_key_packed_422_ayuv;
2497 case GST_VIDEO_FORMAT_ARGB:
2498 case GST_VIDEO_FORMAT_ABGR:
2499 case GST_VIDEO_FORMAT_RGBA:
2500 case GST_VIDEO_FORMAT_BGRA:
2501 alpha->process = gst_alpha_chroma_key_argb_ayuv;
2503 case GST_VIDEO_FORMAT_xRGB:
2504 case GST_VIDEO_FORMAT_xBGR:
2505 case GST_VIDEO_FORMAT_RGBx:
2506 case GST_VIDEO_FORMAT_BGRx:
2507 case GST_VIDEO_FORMAT_RGB:
2508 case GST_VIDEO_FORMAT_BGR:
2509 alpha->process = gst_alpha_chroma_key_rgb_ayuv;
2515 case GST_VIDEO_FORMAT_ARGB:
2516 case GST_VIDEO_FORMAT_ABGR:
2517 case GST_VIDEO_FORMAT_RGBA:
2518 case GST_VIDEO_FORMAT_BGRA:
2519 switch (GST_VIDEO_INFO_FORMAT (&alpha->in_info)) {
2520 case GST_VIDEO_FORMAT_AYUV:
2521 alpha->process = gst_alpha_chroma_key_ayuv_argb;
2523 case GST_VIDEO_FORMAT_Y444:
2524 case GST_VIDEO_FORMAT_Y42B:
2525 case GST_VIDEO_FORMAT_I420:
2526 case GST_VIDEO_FORMAT_YV12:
2527 case GST_VIDEO_FORMAT_Y41B:
2528 alpha->process = gst_alpha_chroma_key_planar_yuv_argb;
2530 case GST_VIDEO_FORMAT_YUY2:
2531 case GST_VIDEO_FORMAT_YVYU:
2532 case GST_VIDEO_FORMAT_UYVY:
2533 alpha->process = gst_alpha_chroma_key_packed_422_argb;
2535 case GST_VIDEO_FORMAT_ARGB:
2536 case GST_VIDEO_FORMAT_ABGR:
2537 case GST_VIDEO_FORMAT_RGBA:
2538 case GST_VIDEO_FORMAT_BGRA:
2539 alpha->process = gst_alpha_chroma_key_argb_argb;
2541 case GST_VIDEO_FORMAT_xRGB:
2542 case GST_VIDEO_FORMAT_xBGR:
2543 case GST_VIDEO_FORMAT_RGBx:
2544 case GST_VIDEO_FORMAT_BGRx:
2545 case GST_VIDEO_FORMAT_RGB:
2546 case GST_VIDEO_FORMAT_BGR:
2547 alpha->process = gst_alpha_chroma_key_rgb_argb;
2561 return alpha->process != NULL;
2565 gst_alpha_before_transform (GstBaseTransform * btrans, GstBuffer * buf)
2567 GstAlpha *alpha = GST_ALPHA (btrans);
2568 GstClockTime timestamp;
2570 timestamp = gst_segment_to_stream_time (&btrans->segment, GST_FORMAT_TIME,
2571 GST_BUFFER_TIMESTAMP (buf));
2572 GST_LOG ("Got stream time of %" GST_TIME_FORMAT, GST_TIME_ARGS (timestamp));
2573 if (GST_CLOCK_TIME_IS_VALID (timestamp))
2574 gst_object_sync_values (GST_OBJECT (alpha), timestamp);
2577 static GstFlowReturn
2578 gst_alpha_transform (GstBaseTransform * btrans, GstBuffer * in, GstBuffer * out)
2580 GstAlpha *alpha = GST_ALPHA (btrans);
2581 GstVideoFrame in_frame, out_frame;
2583 GST_ALPHA_LOCK (alpha);
2585 if (G_UNLIKELY (!alpha->process))
2586 goto not_negotiated;
2588 if (!gst_video_frame_map (&in_frame, &alpha->in_info, in, GST_MAP_READ))
2591 if (!gst_video_frame_map (&out_frame, &alpha->out_info, out, GST_MAP_WRITE))
2594 alpha->process (&in_frame, &out_frame, alpha);
2596 gst_video_frame_unmap (&out_frame);
2597 gst_video_frame_unmap (&in_frame);
2599 GST_ALPHA_UNLOCK (alpha);
2606 GST_ERROR_OBJECT (alpha, "Not negotiated yet");
2607 GST_ALPHA_UNLOCK (alpha);
2608 return GST_FLOW_NOT_NEGOTIATED;
2612 GST_ERROR_OBJECT (alpha, "Invalid input frame");
2613 GST_ALPHA_UNLOCK (alpha);
2618 GST_ERROR_OBJECT (alpha, "Invalid output frame");
2619 gst_video_frame_unmap (&in_frame);
2620 GST_ALPHA_UNLOCK (alpha);
2626 plugin_init (GstPlugin * plugin)
2628 return gst_element_register (plugin, "alpha", GST_RANK_NONE, GST_TYPE_ALPHA);
2631 GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
2634 "adds an alpha channel to video - constant or via chroma-keying",
2635 plugin_init, VERSION, GST_LICENSE, GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN)