2 * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
3 * Copyright (C) <2007> Wim Taymans <wim.taymans@collabora.co.uk>
4 * Copyright (C) <2007> Edward Hervey <edward.hervey@collabora.co.uk>
5 * Copyright (C) <2007> Jan Schmidt <thaytan@noraisin.net>
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Library General Public License for more details.
17 * You should have received a copy of the GNU Library General Public
18 * License along with this library; if not, write to the
19 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
20 * Boston, MA 02110-1301, USA.
24 * SECTION:element-alpha
26 * The alpha element adds an alpha channel to a video stream. The values
27 * of the alpha channel can be either be set to a constant or can be
28 * dynamically calculated via chroma keying, e.g. blue can be set as
29 * the transparent color.
33 * gst-launch-1.0 videotestsrc pattern=smpte75 ! alpha method=green ! \
34 * videomixer name=mixer ! videoconvert ! autovideosink \
35 * videotestsrc pattern=snow ! mixer.
36 * ]| This pipeline adds a alpha channel to the SMPTE color bars
37 * with green as the transparent color and mixes the output with
38 * a snow video stream.
53 #define M_PI 3.14159265358979323846
56 /* Generated by -bad/ext/cog/generate_tables */
57 static const int cog_ycbcr_to_rgb_matrix_8bit_hdtv[] = {
59 298, -55, -136, 19681,
63 static const int cog_ycbcr_to_rgb_matrix_8bit_sdtv[] = {
65 298, -100, -208, 34707,
69 static const gint cog_rgb_to_ycbcr_matrix_8bit_hdtv[] = {
72 112, -102, -10, 32768,
75 static const gint cog_rgb_to_ycbcr_matrix_8bit_sdtv[] = {
81 static const gint cog_ycbcr_sdtv_to_ycbcr_hdtv_matrix_8bit[] = {
87 static const gint cog_ycbcr_hdtv_to_ycbcr_sdtv_matrix_8bit[] = {
93 /* Alpha signals and args */
100 #define DEFAULT_METHOD ALPHA_METHOD_SET
101 #define DEFAULT_ALPHA 1.0
102 #define DEFAULT_TARGET_R 0
103 #define DEFAULT_TARGET_G 255
104 #define DEFAULT_TARGET_B 0
105 #define DEFAULT_ANGLE 20.0
106 #define DEFAULT_NOISE_LEVEL 2.0
107 #define DEFAULT_BLACK_SENSITIVITY 100
108 #define DEFAULT_WHITE_SENSITIVITY 100
109 #define DEFAULT_PREFER_PASSTHROUGH FALSE
121 PROP_BLACK_SENSITIVITY,
122 PROP_WHITE_SENSITIVITY,
123 PROP_PREFER_PASSTHROUGH
126 static GstStaticPadTemplate gst_alpha_src_template =
127 GST_STATIC_PAD_TEMPLATE ("src",
130 GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE ("{ AYUV, "
131 "ARGB, BGRA, ABGR, RGBA, Y444, xRGB, BGRx, xBGR, "
132 "RGBx, RGB, BGR, Y42B, YUY2, YVYU, UYVY, I420, YV12, Y41B } "))
135 static GstStaticPadTemplate gst_alpha_sink_template =
136 GST_STATIC_PAD_TEMPLATE ("sink",
139 GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE ("{ AYUV, "
140 "ARGB, BGRA, ABGR, RGBA, Y444, xRGB, BGRx, xBGR, "
141 "RGBx, RGB, BGR, Y42B, YUY2, YVYU, UYVY, I420, YV12, " "Y41B } "))
144 static GstStaticCaps gst_alpha_alpha_caps =
145 GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE ("{ AYUV, ARGB, BGRA, ABGR, RGBA }"));
147 /* FIXME: why do we need our own lock for this? */
148 #define GST_ALPHA_LOCK(alpha) G_STMT_START { \
149 GST_LOG_OBJECT (alpha, "Locking alpha from thread %p", g_thread_self ()); \
150 g_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_mutex_unlock (&alpha->lock); \
159 static GstCaps *gst_alpha_transform_caps (GstBaseTransform * btrans,
160 GstPadDirection direction, GstCaps * caps, GstCaps * filter);
161 static void gst_alpha_before_transform (GstBaseTransform * btrans,
164 static gboolean gst_alpha_set_info (GstVideoFilter * filter,
165 GstCaps * incaps, GstVideoInfo * in_info, GstCaps * outcaps,
166 GstVideoInfo * out_info);
167 static GstFlowReturn gst_alpha_transform_frame (GstVideoFilter * filter,
168 GstVideoFrame * in_frame, GstVideoFrame * out_frame);
170 static void gst_alpha_init_params_full (GstAlpha * alpha,
171 const GstVideoFormatInfo * in_info, const GstVideoFormatInfo * out_info);
172 static void gst_alpha_init_params (GstAlpha * alpha);
173 static void gst_alpha_set_process_function (GstAlpha * alpha);
174 static gboolean gst_alpha_set_process_function_full (GstAlpha * alpha,
175 GstVideoInfo * in_info, GstVideoInfo * out_info);
177 static void gst_alpha_set_property (GObject * object, guint prop_id,
178 const GValue * value, GParamSpec * pspec);
179 static void gst_alpha_get_property (GObject * object, guint prop_id,
180 GValue * value, GParamSpec * pspec);
181 static void gst_alpha_finalize (GObject * object);
183 #define gst_alpha_parent_class parent_class
184 G_DEFINE_TYPE (GstAlpha, gst_alpha, GST_TYPE_VIDEO_FILTER);
186 #define GST_TYPE_ALPHA_METHOD (gst_alpha_method_get_type())
188 gst_alpha_method_get_type (void)
190 static GType alpha_method_type = 0;
191 static const GEnumValue alpha_method[] = {
192 {ALPHA_METHOD_SET, "Set/adjust alpha channel", "set"},
193 {ALPHA_METHOD_GREEN, "Chroma Key on pure green", "green"},
194 {ALPHA_METHOD_BLUE, "Chroma Key on pure blue", "blue"},
195 {ALPHA_METHOD_CUSTOM, "Chroma Key on custom RGB values", "custom"},
199 if (!alpha_method_type) {
200 alpha_method_type = g_enum_register_static ("GstAlphaMethod", alpha_method);
202 return alpha_method_type;
206 gst_alpha_class_init (GstAlphaClass * klass)
208 GObjectClass *gobject_class = (GObjectClass *) klass;
209 GstElementClass *gstelement_class = (GstElementClass *) klass;
210 GstBaseTransformClass *btrans_class = (GstBaseTransformClass *) klass;
211 GstVideoFilterClass *vfilter_class = (GstVideoFilterClass *) klass;
213 GST_DEBUG_CATEGORY_INIT (gst_alpha_debug, "alpha", 0,
214 "alpha - Element for adding alpha channel to streams");
216 gobject_class->set_property = gst_alpha_set_property;
217 gobject_class->get_property = gst_alpha_get_property;
218 gobject_class->finalize = gst_alpha_finalize;
220 g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_METHOD,
221 g_param_spec_enum ("method", "Method",
222 "How the alpha channels should be created", GST_TYPE_ALPHA_METHOD,
223 DEFAULT_METHOD, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
224 g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_ALPHA,
225 g_param_spec_double ("alpha", "Alpha", "The value for the alpha channel",
226 0.0, 1.0, DEFAULT_ALPHA,
227 G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
228 g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_TARGET_R,
229 g_param_spec_uint ("target-r", "Target Red",
230 "The red color value for custom RGB chroma keying", 0, 255,
232 G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
233 g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_TARGET_G,
234 g_param_spec_uint ("target-g", "Target Green",
235 "The green color value for custom RGB chroma keying", 0, 255,
237 G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
238 g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_TARGET_B,
239 g_param_spec_uint ("target-b", "Target Blue",
240 "The blue color value for custom RGB chroma keying", 0, 255,
242 G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
243 g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_ANGLE,
244 g_param_spec_float ("angle", "Angle", "Size of the colorcube to change",
245 0.0, 90.0, DEFAULT_ANGLE,
246 G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
247 g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_NOISE_LEVEL,
248 g_param_spec_float ("noise-level", "Noise Level", "Size of noise radius",
249 0.0, 64.0, DEFAULT_NOISE_LEVEL,
250 G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
251 g_object_class_install_property (G_OBJECT_CLASS (klass),
252 PROP_BLACK_SENSITIVITY, g_param_spec_uint ("black-sensitivity",
253 "Black Sensitivity", "Sensitivity to dark colors", 0, 128,
254 DEFAULT_BLACK_SENSITIVITY,
255 G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
256 g_object_class_install_property (G_OBJECT_CLASS (klass),
257 PROP_WHITE_SENSITIVITY, g_param_spec_uint ("white-sensitivity",
258 "White Sensitivity", "Sensitivity to bright colors", 0, 128,
259 DEFAULT_WHITE_SENSITIVITY,
260 G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
261 g_object_class_install_property (G_OBJECT_CLASS (klass),
262 PROP_PREFER_PASSTHROUGH, g_param_spec_boolean ("prefer-passthrough",
263 "Prefer Passthrough",
264 "Don't do any processing for alpha=1.0 if possible",
265 DEFAULT_PREFER_PASSTHROUGH,
266 G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
268 gst_element_class_set_static_metadata (gstelement_class, "Alpha filter",
269 "Filter/Effect/Video",
270 "Adds an alpha channel to video - uniform or via chroma-keying",
271 "Wim Taymans <wim.taymans@gmail.com>\n"
272 "Edward Hervey <edward.hervey@collabora.co.uk>\n"
273 "Jan Schmidt <thaytan@noraisin.net>");
275 gst_element_class_add_pad_template (gstelement_class,
276 gst_static_pad_template_get (&gst_alpha_sink_template));
277 gst_element_class_add_pad_template (gstelement_class,
278 gst_static_pad_template_get (&gst_alpha_src_template));
280 btrans_class->before_transform =
281 GST_DEBUG_FUNCPTR (gst_alpha_before_transform);
282 btrans_class->transform_caps = GST_DEBUG_FUNCPTR (gst_alpha_transform_caps);
284 vfilter_class->set_info = GST_DEBUG_FUNCPTR (gst_alpha_set_info);
285 vfilter_class->transform_frame =
286 GST_DEBUG_FUNCPTR (gst_alpha_transform_frame);
290 gst_alpha_init (GstAlpha * alpha)
292 alpha->alpha = DEFAULT_ALPHA;
293 alpha->method = DEFAULT_METHOD;
294 alpha->target_r = DEFAULT_TARGET_R;
295 alpha->target_g = DEFAULT_TARGET_G;
296 alpha->target_b = DEFAULT_TARGET_B;
297 alpha->angle = DEFAULT_ANGLE;
298 alpha->noise_level = DEFAULT_NOISE_LEVEL;
299 alpha->black_sensitivity = DEFAULT_BLACK_SENSITIVITY;
300 alpha->white_sensitivity = DEFAULT_WHITE_SENSITIVITY;
302 g_mutex_init (&alpha->lock);
306 gst_alpha_finalize (GObject * object)
308 GstAlpha *alpha = GST_ALPHA (object);
310 g_mutex_clear (&alpha->lock);
312 G_OBJECT_CLASS (parent_class)->finalize (object);
316 gst_alpha_set_property (GObject * object, guint prop_id,
317 const GValue * value, GParamSpec * pspec)
319 GstAlpha *alpha = GST_ALPHA (object);
320 gboolean reconfigure = FALSE;
322 GST_ALPHA_LOCK (alpha);
325 gint method = g_value_get_enum (value);
327 reconfigure = (method != alpha->method) && (method == ALPHA_METHOD_SET
328 || alpha->method == ALPHA_METHOD_SET) && (alpha->alpha == 1.0)
329 && (alpha->prefer_passthrough);
330 alpha->method = method;
332 gst_alpha_set_process_function (alpha);
333 gst_alpha_init_params (alpha);
337 gdouble a = g_value_get_double (value);
339 reconfigure = (a != alpha->alpha) && (a == 1.0 || alpha->alpha == 1.0)
340 && (alpha->method == ALPHA_METHOD_SET) && (alpha->prefer_passthrough);
345 alpha->target_r = g_value_get_uint (value);
346 gst_alpha_init_params (alpha);
349 alpha->target_g = g_value_get_uint (value);
350 gst_alpha_init_params (alpha);
353 alpha->target_b = g_value_get_uint (value);
354 gst_alpha_init_params (alpha);
357 alpha->angle = g_value_get_float (value);
358 gst_alpha_init_params (alpha);
360 case PROP_NOISE_LEVEL:
361 alpha->noise_level = g_value_get_float (value);
362 gst_alpha_init_params (alpha);
364 case PROP_BLACK_SENSITIVITY:
365 alpha->black_sensitivity = g_value_get_uint (value);
367 case PROP_WHITE_SENSITIVITY:
368 alpha->white_sensitivity = g_value_get_uint (value);
370 case PROP_PREFER_PASSTHROUGH:{
371 gboolean prefer_passthrough = g_value_get_boolean (value);
373 reconfigure = ((! !prefer_passthrough) != (! !alpha->prefer_passthrough))
374 && (alpha->method == ALPHA_METHOD_SET) && (alpha->alpha == 1.0);
375 alpha->prefer_passthrough = prefer_passthrough;
379 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
384 gst_base_transform_reconfigure_src (GST_BASE_TRANSFORM_CAST (alpha));
386 GST_ALPHA_UNLOCK (alpha);
390 gst_alpha_get_property (GObject * object, guint prop_id, GValue * value,
393 GstAlpha *alpha = GST_ALPHA (object);
397 g_value_set_enum (value, alpha->method);
400 g_value_set_double (value, alpha->alpha);
403 g_value_set_uint (value, alpha->target_r);
406 g_value_set_uint (value, alpha->target_g);
409 g_value_set_uint (value, alpha->target_b);
412 g_value_set_float (value, alpha->angle);
414 case PROP_NOISE_LEVEL:
415 g_value_set_float (value, alpha->noise_level);
417 case PROP_BLACK_SENSITIVITY:
418 g_value_set_uint (value, alpha->black_sensitivity);
420 case PROP_WHITE_SENSITIVITY:
421 g_value_set_uint (value, alpha->white_sensitivity);
423 case PROP_PREFER_PASSTHROUGH:
424 g_value_set_boolean (value, alpha->prefer_passthrough);
427 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
433 gst_alpha_transform_caps (GstBaseTransform * btrans,
434 GstPadDirection direction, GstCaps * caps, GstCaps * filter)
436 GstAlpha *alpha = GST_ALPHA (btrans);
437 GstCaps *ret, *tmp, *tmp2;
438 GstStructure *structure;
441 tmp = gst_caps_new_empty ();
443 GST_ALPHA_LOCK (alpha);
444 for (i = 0; i < gst_caps_get_size (caps); i++) {
445 structure = gst_structure_copy (gst_caps_get_structure (caps, i));
447 gst_structure_remove_field (structure, "format");
448 gst_structure_remove_field (structure, "colorimetry");
449 gst_structure_remove_field (structure, "chroma-site");
451 gst_caps_append_structure (tmp, structure);
454 if (direction == GST_PAD_SINK) {
455 tmp2 = gst_static_caps_get (&gst_alpha_alpha_caps);
456 ret = gst_caps_intersect (tmp, tmp2);
457 gst_caps_unref (tmp);
458 gst_caps_unref (tmp2);
462 if (alpha->prefer_passthrough && alpha->method == ALPHA_METHOD_SET
463 && alpha->alpha == 1.0) {
464 ret = gst_caps_copy (caps);
465 gst_caps_append (ret, tmp);
476 GST_DEBUG_OBJECT (alpha,
477 "Transformed %" GST_PTR_FORMAT " -> %" GST_PTR_FORMAT, caps, ret);
480 GstCaps *intersection;
482 GST_DEBUG_OBJECT (alpha, "Using filter caps %" GST_PTR_FORMAT, filter);
484 gst_caps_intersect_full (filter, ret, GST_CAPS_INTERSECT_FIRST);
485 gst_caps_unref (ret);
487 GST_DEBUG_OBJECT (alpha, "Intersection %" GST_PTR_FORMAT, ret);
491 GST_ALPHA_UNLOCK (alpha);
497 gst_alpha_set_info (GstVideoFilter * filter,
498 GstCaps * incaps, GstVideoInfo * in_info, GstCaps * outcaps,
499 GstVideoInfo * out_info)
501 GstAlpha *alpha = GST_ALPHA (filter);
502 gboolean passthrough;
504 GST_ALPHA_LOCK (alpha);
506 alpha->in_sdtv = in_info->colorimetry.matrix == GST_VIDEO_COLOR_MATRIX_BT601;
508 out_info->colorimetry.matrix == GST_VIDEO_COLOR_MATRIX_BT601;
510 passthrough = alpha->prefer_passthrough &&
511 GST_VIDEO_INFO_FORMAT (in_info) == GST_VIDEO_INFO_FORMAT (out_info)
512 && alpha->in_sdtv == alpha->out_sdtv && alpha->method == ALPHA_METHOD_SET
513 && alpha->alpha == 1.0;
515 GST_DEBUG_OBJECT (alpha,
516 "Setting caps %" GST_PTR_FORMAT " -> %" GST_PTR_FORMAT
517 " (passthrough: %d)", incaps, outcaps, passthrough);
518 gst_base_transform_set_passthrough (GST_BASE_TRANSFORM_CAST (filter),
521 if (!gst_alpha_set_process_function_full (alpha, in_info, out_info)
525 gst_alpha_init_params_full (alpha, in_info->finfo, out_info->finfo);
527 GST_ALPHA_UNLOCK (alpha);
534 GST_WARNING_OBJECT (alpha,
535 "No processing function for this caps and no passthrough mode");
536 GST_ALPHA_UNLOCK (alpha);
541 /* based on http://www.cs.utah.edu/~michael/chroma/
544 chroma_keying_yuv (gint a, gint * y, gint * u,
545 gint * v, gint cr, gint cb, gint smin, gint smax, guint8 accept_angle_tg,
546 guint8 accept_angle_ctg, guint8 one_over_kc, guint8 kfgy_scale, gint8 kg,
554 /* too dark or too bright, keep alpha */
555 if (*y < smin || *y > smax)
558 /* Convert foreground to XZ coords where X direction is defined by
560 tmp = ((*u) * cb + (*v) * cr) >> 7;
561 x = CLAMP (tmp, -128, 127);
562 tmp = ((*v) * cb - (*u) * cr) >> 7;
563 z = CLAMP (tmp, -128, 127);
565 /* WARNING: accept angle should never be set greater than "somewhat less
566 than 90 degrees" to avoid dealing with negative/infinite tg. In reality,
567 80 degrees should be enough if foreground is reasonable. If this seems
568 to be a problem, go to alternative ways of checking point position
569 (scalar product or line equations). This angle should not be too small
570 either to avoid infinite ctg (used to suppress foreground without use of
573 tmp = (x * accept_angle_tg) >> 4;
574 tmp = MIN (tmp, 127);
577 /* keep foreground Kfg = 0 */
580 /* Compute Kfg (implicitly) and Kbg, suppress foreground in XZ coord
582 tmp = (z * accept_angle_ctg) >> 4;
583 tmp = CLAMP (tmp, -128, 127);
588 tmp1 = MAX (tmp1, 0);
589 b_alpha = (tmp1 * one_over_kc) / 2;
590 b_alpha = 255 - CLAMP (b_alpha, 0, 255);
591 b_alpha = (a * b_alpha) >> 8;
593 tmp = (tmp1 * kfgy_scale) >> 4;
594 tmp1 = MIN (tmp, 255);
596 *y = (*y < tmp1) ? 0 : *y - tmp1;
598 /* Convert suppressed foreground back to CbCr */
599 tmp = (x1 * cb - y1 * cr) >> 7;
600 *u = CLAMP (tmp, -128, 127);
602 tmp = (x1 * cr + y1 * cb) >> 7;
603 *v = CLAMP (tmp, -128, 127);
605 /* Deal with noise. For now, a circle around the key color with
606 radius of noise_level treated as exact key color. Introduces
609 tmp = z * z + (x - kg) * (x - kg);
610 tmp = MIN (tmp, 0xffff);
612 if (tmp < noise_level2)
618 #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)
621 gst_alpha_set_argb_ayuv (const GstVideoFrame * in_frame,
622 GstVideoFrame * out_frame, GstAlpha * alpha)
624 gint s_alpha = CLAMP ((gint) (alpha->alpha * 256), 0, 256);
633 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
634 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
636 width = GST_VIDEO_FRAME_WIDTH (in_frame);
637 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
639 o[0] = GST_VIDEO_FRAME_COMP_POFFSET (in_frame, 3);
640 o[1] = GST_VIDEO_FRAME_COMP_POFFSET (in_frame, 0);
641 o[2] = GST_VIDEO_FRAME_COMP_POFFSET (in_frame, 1);
642 o[3] = GST_VIDEO_FRAME_COMP_POFFSET (in_frame, 2);
645 alpha->out_sdtv ? cog_rgb_to_ycbcr_matrix_8bit_sdtv :
646 cog_rgb_to_ycbcr_matrix_8bit_hdtv, 12 * sizeof (gint));
648 for (i = 0; i < height; i++) {
649 for (j = 0; j < width; j++) {
650 dest[0] = (src[o[0]] * s_alpha) >> 8;
652 y = APPLY_MATRIX (matrix, 0, src[o[1]], src[o[2]], src[o[3]]);
653 u = APPLY_MATRIX (matrix, 1, src[o[1]], src[o[2]], src[o[3]]);
654 v = APPLY_MATRIX (matrix, 2, src[o[1]], src[o[2]], src[o[3]]);
667 gst_alpha_chroma_key_argb_ayuv (const GstVideoFrame * in_frame,
668 GstVideoFrame * out_frame, GstAlpha * alpha)
677 gint pa = CLAMP ((gint) (alpha->alpha * 256), 0, 256);
678 gint8 cb = alpha->cb, cr = alpha->cr;
679 gint8 kg = alpha->kg;
680 guint8 accept_angle_tg = alpha->accept_angle_tg;
681 guint8 accept_angle_ctg = alpha->accept_angle_ctg;
682 guint8 one_over_kc = alpha->one_over_kc;
683 guint8 kfgy_scale = alpha->kfgy_scale;
684 guint noise_level2 = alpha->noise_level2;
688 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
689 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
691 width = GST_VIDEO_FRAME_WIDTH (in_frame);
692 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
694 o[0] = GST_VIDEO_FRAME_COMP_POFFSET (in_frame, 3);
695 o[1] = GST_VIDEO_FRAME_COMP_POFFSET (in_frame, 0);
696 o[2] = GST_VIDEO_FRAME_COMP_POFFSET (in_frame, 1);
697 o[3] = GST_VIDEO_FRAME_COMP_POFFSET (in_frame, 2);
699 smin = 128 - alpha->black_sensitivity;
700 smax = 128 + alpha->white_sensitivity;
703 alpha->out_sdtv ? cog_rgb_to_ycbcr_matrix_8bit_sdtv :
704 cog_rgb_to_ycbcr_matrix_8bit_hdtv, 12 * sizeof (gint));
706 for (i = 0; i < height; i++) {
707 for (j = 0; j < width; j++) {
708 a = (src[o[0]] * pa) >> 8;
713 y = APPLY_MATRIX (matrix, 0, r, g, b);
714 u = APPLY_MATRIX (matrix, 1, r, g, b) - 128;
715 v = APPLY_MATRIX (matrix, 2, r, g, b) - 128;
717 a = chroma_keying_yuv (a, &y, &u, &v, cr, cb,
718 smin, smax, accept_angle_tg, accept_angle_ctg,
719 one_over_kc, kfgy_scale, kg, noise_level2);
736 gst_alpha_set_argb_argb (const GstVideoFrame * in_frame,
737 GstVideoFrame * out_frame, GstAlpha * alpha)
742 gint s_alpha = CLAMP ((gint) (alpha->alpha * 256), 0, 256);
746 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
747 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
749 width = GST_VIDEO_FRAME_WIDTH (in_frame);
750 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
752 p[0] = GST_VIDEO_FRAME_COMP_POFFSET (out_frame, 3);
753 p[1] = GST_VIDEO_FRAME_COMP_POFFSET (out_frame, 0);
754 p[2] = GST_VIDEO_FRAME_COMP_POFFSET (out_frame, 1);
755 p[3] = GST_VIDEO_FRAME_COMP_POFFSET (out_frame, 2);
757 o[0] = GST_VIDEO_FRAME_COMP_POFFSET (in_frame, 3);
758 o[1] = GST_VIDEO_FRAME_COMP_POFFSET (in_frame, 0);
759 o[2] = GST_VIDEO_FRAME_COMP_POFFSET (in_frame, 1);
760 o[3] = GST_VIDEO_FRAME_COMP_POFFSET (in_frame, 2);
762 for (i = 0; i < height; i++) {
763 for (j = 0; j < width; j++) {
764 dest[p[0]] = (src[o[0]] * s_alpha) >> 8;
766 dest[p[1]] = src[o[1]];
767 dest[p[2]] = src[o[2]];
768 dest[p[3]] = src[o[3]];
777 gst_alpha_chroma_key_argb_argb (const GstVideoFrame * in_frame,
778 GstVideoFrame * out_frame, GstAlpha * alpha)
787 gint pa = CLAMP ((gint) (alpha->alpha * 256), 0, 256);
788 gint8 cb = alpha->cb, cr = alpha->cr;
789 gint8 kg = alpha->kg;
790 guint8 accept_angle_tg = alpha->accept_angle_tg;
791 guint8 accept_angle_ctg = alpha->accept_angle_ctg;
792 guint8 one_over_kc = alpha->one_over_kc;
793 guint8 kfgy_scale = alpha->kfgy_scale;
794 guint noise_level2 = alpha->noise_level2;
795 gint matrix[12], matrix2[12];
798 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
799 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
801 width = GST_VIDEO_FRAME_WIDTH (in_frame);
802 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
804 p[0] = GST_VIDEO_FRAME_COMP_POFFSET (out_frame, 3);
805 p[1] = GST_VIDEO_FRAME_COMP_POFFSET (out_frame, 0);
806 p[2] = GST_VIDEO_FRAME_COMP_POFFSET (out_frame, 1);
807 p[3] = GST_VIDEO_FRAME_COMP_POFFSET (out_frame, 2);
809 o[0] = GST_VIDEO_FRAME_COMP_POFFSET (in_frame, 3);
810 o[1] = GST_VIDEO_FRAME_COMP_POFFSET (in_frame, 0);
811 o[2] = GST_VIDEO_FRAME_COMP_POFFSET (in_frame, 1);
812 o[3] = GST_VIDEO_FRAME_COMP_POFFSET (in_frame, 2);
814 smin = 128 - alpha->black_sensitivity;
815 smax = 128 + alpha->white_sensitivity;
817 memcpy (matrix, cog_rgb_to_ycbcr_matrix_8bit_sdtv, 12 * sizeof (gint));
818 memcpy (matrix2, cog_ycbcr_to_rgb_matrix_8bit_sdtv, 12 * sizeof (gint));
820 for (i = 0; i < height; i++) {
821 for (j = 0; j < width; j++) {
822 a = (src[o[0]] * pa) >> 8;
827 y = APPLY_MATRIX (matrix, 0, r, g, b);
828 u = APPLY_MATRIX (matrix, 1, r, g, b) - 128;
829 v = APPLY_MATRIX (matrix, 2, r, g, b) - 128;
831 a = chroma_keying_yuv (a, &y, &u, &v, cr, cb,
832 smin, smax, accept_angle_tg, accept_angle_ctg,
833 one_over_kc, kfgy_scale, kg, noise_level2);
838 r = APPLY_MATRIX (matrix2, 0, y, u, v);
839 g = APPLY_MATRIX (matrix2, 1, y, u, v);
840 b = APPLY_MATRIX (matrix2, 2, y, u, v);
843 dest[p[1]] = CLAMP (r, 0, 255);
844 dest[p[2]] = CLAMP (g, 0, 255);
845 dest[p[3]] = CLAMP (b, 0, 255);
854 gst_alpha_set_ayuv_argb (const GstVideoFrame * in_frame,
855 GstVideoFrame * out_frame, GstAlpha * alpha)
860 gint s_alpha = CLAMP ((gint) (alpha->alpha * 256), 0, 256);
866 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
867 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
869 width = GST_VIDEO_FRAME_WIDTH (in_frame);
870 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
872 p[0] = GST_VIDEO_FRAME_COMP_POFFSET (out_frame, 3);
873 p[1] = GST_VIDEO_FRAME_COMP_POFFSET (out_frame, 0);
874 p[2] = GST_VIDEO_FRAME_COMP_POFFSET (out_frame, 1);
875 p[3] = GST_VIDEO_FRAME_COMP_POFFSET (out_frame, 2);
878 alpha->in_sdtv ? cog_ycbcr_to_rgb_matrix_8bit_sdtv :
879 cog_ycbcr_to_rgb_matrix_8bit_hdtv, 12 * sizeof (gint));
881 for (y = 0; y < height; y++) {
882 for (x = 0; x < width; x++) {
883 dest[p[0]] = (src[0] * s_alpha) >> 8;
885 r = APPLY_MATRIX (matrix, 0, src[1], src[2], src[3]);
886 g = APPLY_MATRIX (matrix, 1, src[1], src[2], src[3]);
887 b = APPLY_MATRIX (matrix, 2, src[1], src[2], src[3]);
889 dest[p[1]] = CLAMP (r, 0, 255);
890 dest[p[2]] = CLAMP (g, 0, 255);
891 dest[p[3]] = CLAMP (b, 0, 255);
900 gst_alpha_chroma_key_ayuv_argb (const GstVideoFrame * in_frame,
901 GstVideoFrame * out_frame, GstAlpha * alpha)
910 gint pa = CLAMP ((gint) (alpha->alpha * 256), 0, 256);
911 gint8 cb = alpha->cb, cr = alpha->cr;
912 gint8 kg = alpha->kg;
913 guint8 accept_angle_tg = alpha->accept_angle_tg;
914 guint8 accept_angle_ctg = alpha->accept_angle_ctg;
915 guint8 one_over_kc = alpha->one_over_kc;
916 guint8 kfgy_scale = alpha->kfgy_scale;
917 guint noise_level2 = alpha->noise_level2;
921 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
922 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
924 width = GST_VIDEO_FRAME_WIDTH (in_frame);
925 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
927 p[0] = GST_VIDEO_FRAME_COMP_POFFSET (out_frame, 3);
928 p[1] = GST_VIDEO_FRAME_COMP_POFFSET (out_frame, 0);
929 p[2] = GST_VIDEO_FRAME_COMP_POFFSET (out_frame, 1);
930 p[3] = GST_VIDEO_FRAME_COMP_POFFSET (out_frame, 2);
932 smin = 128 - alpha->black_sensitivity;
933 smax = 128 + alpha->white_sensitivity;
936 alpha->in_sdtv ? cog_ycbcr_to_rgb_matrix_8bit_sdtv :
937 cog_ycbcr_to_rgb_matrix_8bit_hdtv, 12 * sizeof (gint));
939 for (i = 0; i < height; i++) {
940 for (j = 0; j < width; j++) {
941 a = (src[0] * pa) >> 8;
946 a = chroma_keying_yuv (a, &y, &u, &v, cr, cb,
947 smin, smax, accept_angle_tg, accept_angle_ctg,
948 one_over_kc, kfgy_scale, kg, noise_level2);
953 r = APPLY_MATRIX (matrix, 0, y, u, v);
954 g = APPLY_MATRIX (matrix, 1, y, u, v);
955 b = APPLY_MATRIX (matrix, 2, y, u, v);
958 dest[p[1]] = CLAMP (r, 0, 255);
959 dest[p[2]] = CLAMP (g, 0, 255);
960 dest[p[3]] = CLAMP (b, 0, 255);
969 gst_alpha_set_ayuv_ayuv (const GstVideoFrame * in_frame,
970 GstVideoFrame * out_frame, GstAlpha * alpha)
975 gint s_alpha = CLAMP ((gint) (alpha->alpha * 256), 0, 256);
978 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
979 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
981 width = GST_VIDEO_FRAME_WIDTH (in_frame);
982 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
984 if (alpha->in_sdtv == alpha->out_sdtv) {
985 for (y = 0; y < height; y++) {
986 for (x = 0; x < width; x++) {
987 dest[0] = (src[0] * s_alpha) >> 8;
1000 alpha->out_sdtv ? cog_ycbcr_hdtv_to_ycbcr_sdtv_matrix_8bit :
1001 cog_ycbcr_sdtv_to_ycbcr_hdtv_matrix_8bit, 12 * sizeof (gint));
1003 for (y = 0; y < height; y++) {
1004 for (x = 0; x < width; x++) {
1005 dest[0] = (src[0] * s_alpha) >> 8;
1006 dest[1] = APPLY_MATRIX (matrix, 0, src[1], src[2], src[3]);
1007 dest[2] = APPLY_MATRIX (matrix, 1, src[1], src[2], src[3]);
1008 dest[3] = APPLY_MATRIX (matrix, 2, src[1], src[2], src[3]);
1018 gst_alpha_chroma_key_ayuv_ayuv (const GstVideoFrame * in_frame,
1019 GstVideoFrame * out_frame, GstAlpha * alpha)
1027 gint pa = CLAMP ((gint) (alpha->alpha * 256), 0, 256);
1028 gint8 cb = alpha->cb, cr = alpha->cr;
1029 gint8 kg = alpha->kg;
1030 guint8 accept_angle_tg = alpha->accept_angle_tg;
1031 guint8 accept_angle_ctg = alpha->accept_angle_ctg;
1032 guint8 one_over_kc = alpha->one_over_kc;
1033 guint8 kfgy_scale = alpha->kfgy_scale;
1034 guint noise_level2 = alpha->noise_level2;
1036 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
1037 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
1039 width = GST_VIDEO_FRAME_WIDTH (in_frame);
1040 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
1042 smin = 128 - alpha->black_sensitivity;
1043 smax = 128 + alpha->white_sensitivity;
1045 if (alpha->in_sdtv == alpha->out_sdtv) {
1046 for (i = 0; i < height; i++) {
1047 for (j = 0; j < width; j++) {
1048 a = (src[0] * pa) >> 8;
1053 a = chroma_keying_yuv (a, &y, &u, &v, cr, cb,
1054 smin, smax, accept_angle_tg, accept_angle_ctg,
1055 one_over_kc, kfgy_scale, kg, noise_level2);
1073 alpha->out_sdtv ? cog_ycbcr_hdtv_to_ycbcr_sdtv_matrix_8bit :
1074 cog_ycbcr_sdtv_to_ycbcr_hdtv_matrix_8bit, 12 * sizeof (gint));
1076 for (i = 0; i < height; i++) {
1077 for (j = 0; j < width; j++) {
1078 a = (src[0] * pa) >> 8;
1079 y = APPLY_MATRIX (matrix, 0, src[1], src[2], src[3]);
1080 u = APPLY_MATRIX (matrix, 1, src[1], src[2], src[3]) - 128;
1081 v = APPLY_MATRIX (matrix, 2, src[1], src[2], src[3]) - 128;
1083 a = chroma_keying_yuv (a, &y, &u, &v, cr, cb,
1084 smin, smax, accept_angle_tg, accept_angle_ctg,
1085 one_over_kc, kfgy_scale, kg, noise_level2);
1103 gst_alpha_set_rgb_ayuv (const GstVideoFrame * in_frame,
1104 GstVideoFrame * out_frame, GstAlpha * alpha)
1109 gint s_alpha = CLAMP ((gint) (alpha->alpha * 255), 0, 255);
1116 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
1117 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
1119 width = GST_VIDEO_FRAME_WIDTH (in_frame);
1120 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
1122 bpp = GST_VIDEO_FRAME_COMP_PSTRIDE (in_frame, 0);
1123 o[0] = GST_VIDEO_FRAME_COMP_POFFSET (in_frame, 0);
1124 o[1] = GST_VIDEO_FRAME_COMP_POFFSET (in_frame, 1);
1125 o[2] = GST_VIDEO_FRAME_COMP_POFFSET (in_frame, 2);
1128 alpha->out_sdtv ? cog_rgb_to_ycbcr_matrix_8bit_sdtv :
1129 cog_rgb_to_ycbcr_matrix_8bit_hdtv, 12 * sizeof (gint));
1131 for (i = 0; i < height; i++) {
1132 for (j = 0; j < width; j++) {
1135 y = APPLY_MATRIX (matrix, 0, src[o[0]], src[o[1]], src[o[2]]);
1136 u = APPLY_MATRIX (matrix, 1, src[o[0]], src[o[1]], src[o[2]]);
1137 v = APPLY_MATRIX (matrix, 2, src[o[0]], src[o[1]], src[o[2]]);
1150 gst_alpha_chroma_key_rgb_ayuv (const GstVideoFrame * in_frame,
1151 GstVideoFrame * out_frame, GstAlpha * alpha)
1160 gint pa = CLAMP ((gint) (alpha->alpha * 255), 0, 255);
1161 gint8 cb = alpha->cb, cr = alpha->cr;
1162 gint8 kg = alpha->kg;
1163 guint8 accept_angle_tg = alpha->accept_angle_tg;
1164 guint8 accept_angle_ctg = alpha->accept_angle_ctg;
1165 guint8 one_over_kc = alpha->one_over_kc;
1166 guint8 kfgy_scale = alpha->kfgy_scale;
1167 guint noise_level2 = alpha->noise_level2;
1172 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
1173 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
1175 width = GST_VIDEO_FRAME_WIDTH (in_frame);
1176 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
1178 bpp = GST_VIDEO_FRAME_COMP_PSTRIDE (in_frame, 0);
1180 o[0] = GST_VIDEO_FRAME_COMP_POFFSET (in_frame, 0);
1181 o[1] = GST_VIDEO_FRAME_COMP_POFFSET (in_frame, 1);
1182 o[2] = GST_VIDEO_FRAME_COMP_POFFSET (in_frame, 2);
1184 smin = 128 - alpha->black_sensitivity;
1185 smax = 128 + alpha->white_sensitivity;
1188 alpha->out_sdtv ? cog_rgb_to_ycbcr_matrix_8bit_sdtv :
1189 cog_rgb_to_ycbcr_matrix_8bit_hdtv, 12 * sizeof (gint));
1191 for (i = 0; i < height; i++) {
1192 for (j = 0; j < width; j++) {
1198 y = APPLY_MATRIX (matrix, 0, r, g, b);
1199 u = APPLY_MATRIX (matrix, 1, r, g, b) - 128;
1200 v = APPLY_MATRIX (matrix, 2, r, g, b) - 128;
1202 a = chroma_keying_yuv (a, &y, &u, &v, cr, cb,
1203 smin, smax, accept_angle_tg, accept_angle_ctg,
1204 one_over_kc, kfgy_scale, kg, noise_level2);
1221 gst_alpha_set_rgb_argb (const GstVideoFrame * in_frame,
1222 GstVideoFrame * out_frame, GstAlpha * alpha)
1227 gint s_alpha = CLAMP ((gint) (alpha->alpha * 255), 0, 255);
1232 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
1233 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
1235 width = GST_VIDEO_FRAME_WIDTH (in_frame);
1236 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
1238 bpp = GST_VIDEO_FRAME_COMP_PSTRIDE (in_frame, 0);
1240 o[0] = GST_VIDEO_FRAME_COMP_POFFSET (in_frame, 0);
1241 o[1] = GST_VIDEO_FRAME_COMP_POFFSET (in_frame, 1);
1242 o[2] = GST_VIDEO_FRAME_COMP_POFFSET (in_frame, 2);
1244 p[0] = GST_VIDEO_FRAME_COMP_POFFSET (out_frame, 3);
1245 p[1] = GST_VIDEO_FRAME_COMP_POFFSET (out_frame, 0);
1246 p[2] = GST_VIDEO_FRAME_COMP_POFFSET (out_frame, 1);
1247 p[3] = GST_VIDEO_FRAME_COMP_POFFSET (out_frame, 2);
1249 for (i = 0; i < height; i++) {
1250 for (j = 0; j < width; j++) {
1251 dest[p[0]] = s_alpha;
1253 dest[p[1]] = src[o[0]];
1254 dest[p[2]] = src[o[1]];
1255 dest[p[3]] = src[o[2]];
1264 gst_alpha_chroma_key_rgb_argb (const GstVideoFrame * in_frame,
1265 GstVideoFrame * out_frame, GstAlpha * alpha)
1274 gint pa = CLAMP ((gint) (alpha->alpha * 255), 0, 255);
1275 gint8 cb = alpha->cb, cr = alpha->cr;
1276 gint8 kg = alpha->kg;
1277 guint8 accept_angle_tg = alpha->accept_angle_tg;
1278 guint8 accept_angle_ctg = alpha->accept_angle_ctg;
1279 guint8 one_over_kc = alpha->one_over_kc;
1280 guint8 kfgy_scale = alpha->kfgy_scale;
1281 guint noise_level2 = alpha->noise_level2;
1282 gint matrix[12], matrix2[12];
1286 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
1287 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
1289 width = GST_VIDEO_FRAME_WIDTH (in_frame);
1290 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
1292 bpp = GST_VIDEO_FRAME_COMP_PSTRIDE (in_frame, 0);
1294 o[0] = GST_VIDEO_FRAME_COMP_POFFSET (in_frame, 0);
1295 o[1] = GST_VIDEO_FRAME_COMP_POFFSET (in_frame, 1);
1296 o[2] = GST_VIDEO_FRAME_COMP_POFFSET (in_frame, 2);
1298 p[0] = GST_VIDEO_FRAME_COMP_POFFSET (out_frame, 3);
1299 p[1] = GST_VIDEO_FRAME_COMP_POFFSET (out_frame, 0);
1300 p[2] = GST_VIDEO_FRAME_COMP_POFFSET (out_frame, 1);
1301 p[3] = GST_VIDEO_FRAME_COMP_POFFSET (out_frame, 2);
1303 smin = 128 - alpha->black_sensitivity;
1304 smax = 128 + alpha->white_sensitivity;
1306 memcpy (matrix, cog_rgb_to_ycbcr_matrix_8bit_sdtv, 12 * sizeof (gint));
1307 memcpy (matrix2, cog_ycbcr_to_rgb_matrix_8bit_sdtv, 12 * sizeof (gint));
1309 for (i = 0; i < height; i++) {
1310 for (j = 0; j < width; j++) {
1316 y = APPLY_MATRIX (matrix, 0, r, g, b);
1317 u = APPLY_MATRIX (matrix, 1, r, g, b) - 128;
1318 v = APPLY_MATRIX (matrix, 2, r, g, b) - 128;
1320 a = chroma_keying_yuv (a, &y, &u, &v, cr, cb,
1321 smin, smax, accept_angle_tg, accept_angle_ctg,
1322 one_over_kc, kfgy_scale, kg, noise_level2);
1327 r = APPLY_MATRIX (matrix2, 0, y, u, v);
1328 g = APPLY_MATRIX (matrix2, 1, y, u, v);
1329 b = APPLY_MATRIX (matrix2, 2, y, u, v);
1332 dest[p[1]] = CLAMP (r, 0, 255);
1333 dest[p[2]] = CLAMP (g, 0, 255);
1334 dest[p[3]] = CLAMP (b, 0, 255);
1343 gst_alpha_set_planar_yuv_ayuv (const GstVideoFrame * in_frame,
1344 GstVideoFrame * out_frame, GstAlpha * alpha)
1348 gint b_alpha = CLAMP ((gint) (alpha->alpha * 255), 0, 255);
1349 const guint8 *srcY, *srcY_tmp;
1350 const guint8 *srcU, *srcU_tmp;
1351 const guint8 *srcV, *srcV_tmp;
1353 gint y_stride, uv_stride;
1354 gint v_subs, h_subs;
1356 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
1358 width = GST_VIDEO_FRAME_WIDTH (in_frame);
1359 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
1361 y_stride = GST_VIDEO_FRAME_COMP_STRIDE (in_frame, 0);
1362 uv_stride = GST_VIDEO_FRAME_COMP_STRIDE (in_frame, 1);
1364 srcY_tmp = srcY = GST_VIDEO_FRAME_COMP_DATA (in_frame, 0);
1365 srcU_tmp = srcU = GST_VIDEO_FRAME_COMP_DATA (in_frame, 1);
1366 srcV_tmp = srcV = GST_VIDEO_FRAME_COMP_DATA (in_frame, 2);
1368 switch (GST_VIDEO_FRAME_FORMAT (in_frame)) {
1369 case GST_VIDEO_FORMAT_I420:
1370 case GST_VIDEO_FORMAT_YV12:
1371 v_subs = h_subs = 2;
1373 case GST_VIDEO_FORMAT_Y444:
1374 v_subs = h_subs = 1;
1376 case GST_VIDEO_FORMAT_Y42B:
1380 case GST_VIDEO_FORMAT_Y41B:
1385 g_assert_not_reached ();
1389 if (alpha->in_sdtv == alpha->out_sdtv) {
1390 for (i = 0; i < height; i++) {
1391 for (j = 0; j < width; j++) {
1399 if ((j + 1) % h_subs == 0) {
1405 srcY_tmp = srcY = srcY_tmp + y_stride;
1406 if ((i + 1) % v_subs == 0) {
1407 srcU_tmp = srcU = srcU_tmp + uv_stride;
1408 srcV_tmp = srcV = srcV_tmp + uv_stride;
1419 alpha->out_sdtv ? cog_ycbcr_hdtv_to_ycbcr_sdtv_matrix_8bit :
1420 cog_ycbcr_sdtv_to_ycbcr_hdtv_matrix_8bit, 12 * sizeof (gint));
1422 for (i = 0; i < height; i++) {
1423 for (j = 0; j < width; j++) {
1430 dest[1] = APPLY_MATRIX (matrix, 0, y, u, v);
1431 dest[2] = APPLY_MATRIX (matrix, 1, y, u, v);
1432 dest[3] = APPLY_MATRIX (matrix, 2, y, u, v);
1436 if ((j + 1) % h_subs == 0) {
1442 srcY_tmp = srcY = srcY_tmp + y_stride;
1443 if ((i + 1) % v_subs == 0) {
1444 srcU_tmp = srcU = srcU_tmp + uv_stride;
1445 srcV_tmp = srcV = srcV_tmp + uv_stride;
1455 gst_alpha_chroma_key_planar_yuv_ayuv (const GstVideoFrame * in_frame,
1456 GstVideoFrame * out_frame, GstAlpha * alpha)
1460 gint b_alpha = CLAMP ((gint) (alpha->alpha * 255), 0, 255);
1461 const guint8 *srcY, *srcY_tmp;
1462 const guint8 *srcU, *srcU_tmp;
1463 const guint8 *srcV, *srcV_tmp;
1466 gint y_stride, uv_stride;
1467 gint v_subs, h_subs;
1468 gint smin = 128 - alpha->black_sensitivity;
1469 gint smax = 128 + alpha->white_sensitivity;
1470 gint8 cb = alpha->cb, cr = alpha->cr;
1471 gint8 kg = alpha->kg;
1472 guint8 accept_angle_tg = alpha->accept_angle_tg;
1473 guint8 accept_angle_ctg = alpha->accept_angle_ctg;
1474 guint8 one_over_kc = alpha->one_over_kc;
1475 guint8 kfgy_scale = alpha->kfgy_scale;
1476 guint noise_level2 = alpha->noise_level2;
1478 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
1480 width = GST_VIDEO_FRAME_WIDTH (in_frame);
1481 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
1483 y_stride = GST_VIDEO_FRAME_COMP_STRIDE (in_frame, 0);
1484 uv_stride = GST_VIDEO_FRAME_COMP_STRIDE (in_frame, 1);
1486 srcY_tmp = srcY = GST_VIDEO_FRAME_COMP_DATA (in_frame, 0);
1487 srcU_tmp = srcU = GST_VIDEO_FRAME_COMP_DATA (in_frame, 1);
1488 srcV_tmp = srcV = GST_VIDEO_FRAME_COMP_DATA (in_frame, 2);
1490 switch (GST_VIDEO_FRAME_FORMAT (in_frame)) {
1491 case GST_VIDEO_FORMAT_I420:
1492 case GST_VIDEO_FORMAT_YV12:
1493 v_subs = h_subs = 2;
1495 case GST_VIDEO_FORMAT_Y444:
1496 v_subs = h_subs = 1;
1498 case GST_VIDEO_FORMAT_Y42B:
1502 case GST_VIDEO_FORMAT_Y41B:
1507 g_assert_not_reached ();
1511 if (alpha->in_sdtv == alpha->out_sdtv) {
1512 for (i = 0; i < height; i++) {
1513 for (j = 0; j < width; j++) {
1519 a = chroma_keying_yuv (a, &y, &u, &v, cr, cb, smin,
1520 smax, accept_angle_tg, accept_angle_ctg,
1521 one_over_kc, kfgy_scale, kg, noise_level2);
1533 if ((j + 1) % h_subs == 0) {
1539 srcY_tmp = srcY = srcY_tmp + y_stride;
1540 if ((i + 1) % v_subs == 0) {
1541 srcU_tmp = srcU = srcU_tmp + uv_stride;
1542 srcV_tmp = srcV = srcV_tmp + uv_stride;
1552 alpha->out_sdtv ? cog_ycbcr_hdtv_to_ycbcr_sdtv_matrix_8bit :
1553 cog_ycbcr_sdtv_to_ycbcr_hdtv_matrix_8bit, 12 * sizeof (gint));
1555 for (i = 0; i < height; i++) {
1556 for (j = 0; j < width; j++) {
1558 y = APPLY_MATRIX (matrix, 0, srcY[0], srcU[0], srcV[0]);
1559 u = APPLY_MATRIX (matrix, 1, srcY[0], srcU[0], srcV[0]) - 128;
1560 v = APPLY_MATRIX (matrix, 2, srcY[0], srcU[0], srcV[0]) - 128;
1562 a = chroma_keying_yuv (a, &y, &u, &v, cr, cb, smin,
1563 smax, accept_angle_tg, accept_angle_ctg,
1564 one_over_kc, kfgy_scale, kg, noise_level2);
1573 if ((j + 1) % h_subs == 0) {
1579 srcY_tmp = srcY = srcY_tmp + y_stride;
1580 if ((i + 1) % v_subs == 0) {
1581 srcU_tmp = srcU = srcU_tmp + uv_stride;
1582 srcV_tmp = srcV = srcV_tmp + uv_stride;
1592 gst_alpha_set_planar_yuv_argb (const GstVideoFrame * in_frame,
1593 GstVideoFrame * out_frame, GstAlpha * alpha)
1597 gint b_alpha = CLAMP ((gint) (alpha->alpha * 255), 0, 255);
1598 const guint8 *srcY, *srcY_tmp;
1599 const guint8 *srcU, *srcU_tmp;
1600 const guint8 *srcV, *srcV_tmp;
1602 gint y_stride, uv_stride;
1603 gint v_subs, h_subs;
1609 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
1611 width = GST_VIDEO_FRAME_WIDTH (in_frame);
1612 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
1614 p[0] = GST_VIDEO_FRAME_COMP_POFFSET (out_frame, 3);
1615 p[1] = GST_VIDEO_FRAME_COMP_POFFSET (out_frame, 0);
1616 p[2] = GST_VIDEO_FRAME_COMP_POFFSET (out_frame, 1);
1617 p[3] = GST_VIDEO_FRAME_COMP_POFFSET (out_frame, 2);
1619 y_stride = GST_VIDEO_FRAME_COMP_STRIDE (in_frame, 0);
1620 uv_stride = GST_VIDEO_FRAME_COMP_STRIDE (in_frame, 1);
1622 srcY_tmp = srcY = GST_VIDEO_FRAME_COMP_DATA (in_frame, 0);
1623 srcU_tmp = srcU = GST_VIDEO_FRAME_COMP_DATA (in_frame, 1);
1624 srcV_tmp = srcV = GST_VIDEO_FRAME_COMP_DATA (in_frame, 2);
1626 switch (GST_VIDEO_FRAME_FORMAT (in_frame)) {
1627 case GST_VIDEO_FORMAT_I420:
1628 case GST_VIDEO_FORMAT_YV12:
1629 v_subs = h_subs = 2;
1631 case GST_VIDEO_FORMAT_Y444:
1632 v_subs = h_subs = 1;
1634 case GST_VIDEO_FORMAT_Y42B:
1638 case GST_VIDEO_FORMAT_Y41B:
1643 g_assert_not_reached ();
1648 alpha->in_sdtv ? cog_ycbcr_to_rgb_matrix_8bit_sdtv :
1649 cog_ycbcr_to_rgb_matrix_8bit_hdtv, 12 * sizeof (gint));
1651 for (i = 0; i < height; i++) {
1652 for (j = 0; j < width; j++) {
1659 r = APPLY_MATRIX (matrix, 0, y, u, v);
1660 g = APPLY_MATRIX (matrix, 1, y, u, v);
1661 b = APPLY_MATRIX (matrix, 2, y, u, v);
1662 dest[p[1]] = CLAMP (r, 0, 255);
1663 dest[p[2]] = CLAMP (g, 0, 255);
1664 dest[p[3]] = CLAMP (b, 0, 255);
1668 if ((j + 1) % h_subs == 0) {
1674 srcY_tmp = srcY = srcY_tmp + y_stride;
1675 if ((i + 1) % v_subs == 0) {
1676 srcU_tmp = srcU = srcU_tmp + uv_stride;
1677 srcV_tmp = srcV = srcV_tmp + uv_stride;
1686 gst_alpha_chroma_key_planar_yuv_argb (const GstVideoFrame * in_frame,
1687 GstVideoFrame * out_frame, GstAlpha * alpha)
1691 gint b_alpha = CLAMP ((gint) (alpha->alpha * 255), 0, 255);
1692 const guint8 *srcY, *srcY_tmp;
1693 const guint8 *srcU, *srcU_tmp;
1694 const guint8 *srcV, *srcV_tmp;
1698 gint y_stride, uv_stride;
1699 gint v_subs, h_subs;
1700 gint smin = 128 - alpha->black_sensitivity;
1701 gint smax = 128 + alpha->white_sensitivity;
1702 gint8 cb = alpha->cb, cr = alpha->cr;
1703 gint8 kg = alpha->kg;
1704 guint8 accept_angle_tg = alpha->accept_angle_tg;
1705 guint8 accept_angle_ctg = alpha->accept_angle_ctg;
1706 guint8 one_over_kc = alpha->one_over_kc;
1707 guint8 kfgy_scale = alpha->kfgy_scale;
1708 guint noise_level2 = alpha->noise_level2;
1712 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
1714 width = GST_VIDEO_FRAME_WIDTH (in_frame);
1715 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
1717 p[0] = GST_VIDEO_FRAME_COMP_POFFSET (out_frame, 3);
1718 p[1] = GST_VIDEO_FRAME_COMP_POFFSET (out_frame, 0);
1719 p[2] = GST_VIDEO_FRAME_COMP_POFFSET (out_frame, 1);
1720 p[3] = GST_VIDEO_FRAME_COMP_POFFSET (out_frame, 2);
1722 y_stride = GST_VIDEO_FRAME_COMP_STRIDE (in_frame, 0);
1723 uv_stride = GST_VIDEO_FRAME_COMP_STRIDE (in_frame, 1);
1725 srcY_tmp = srcY = GST_VIDEO_FRAME_COMP_DATA (in_frame, 0);
1726 srcU_tmp = srcU = GST_VIDEO_FRAME_COMP_DATA (in_frame, 1);
1727 srcV_tmp = srcV = GST_VIDEO_FRAME_COMP_DATA (in_frame, 2);
1729 switch (GST_VIDEO_FRAME_FORMAT (in_frame)) {
1730 case GST_VIDEO_FORMAT_I420:
1731 case GST_VIDEO_FORMAT_YV12:
1732 v_subs = h_subs = 2;
1734 case GST_VIDEO_FORMAT_Y444:
1735 v_subs = h_subs = 1;
1737 case GST_VIDEO_FORMAT_Y42B:
1741 case GST_VIDEO_FORMAT_Y41B:
1746 g_assert_not_reached ();
1751 alpha->in_sdtv ? cog_ycbcr_to_rgb_matrix_8bit_sdtv :
1752 cog_ycbcr_to_rgb_matrix_8bit_hdtv, 12 * sizeof (gint));
1754 for (i = 0; i < height; i++) {
1755 for (j = 0; j < width; j++) {
1761 a = chroma_keying_yuv (a, &y, &u, &v, cr, cb, smin,
1762 smax, accept_angle_tg, accept_angle_ctg,
1763 one_over_kc, kfgy_scale, kg, noise_level2);
1769 r = APPLY_MATRIX (matrix, 0, y, u, v);
1770 g = APPLY_MATRIX (matrix, 1, y, u, v);
1771 b = APPLY_MATRIX (matrix, 2, y, u, v);
1772 dest[p[1]] = CLAMP (r, 0, 255);
1773 dest[p[2]] = CLAMP (g, 0, 255);
1774 dest[p[3]] = CLAMP (b, 0, 255);
1778 if ((j + 1) % h_subs == 0) {
1784 srcY_tmp = srcY = srcY_tmp + y_stride;
1785 if ((i + 1) % v_subs == 0) {
1786 srcU_tmp = srcU = srcU_tmp + uv_stride;
1787 srcV_tmp = srcV = srcV_tmp + uv_stride;
1796 gst_alpha_set_packed_422_ayuv (const GstVideoFrame * in_frame,
1797 GstVideoFrame * out_frame, GstAlpha * alpha)
1802 gint s_alpha = CLAMP ((gint) (alpha->alpha * 255), 0, 255);
1805 gint p[4]; /* Y U Y V */
1807 const guint8 *src_tmp;
1809 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
1810 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
1812 width = GST_VIDEO_FRAME_WIDTH (in_frame);
1813 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
1815 src_stride = GST_VIDEO_FRAME_COMP_STRIDE (in_frame, 0);
1817 p[0] = GST_VIDEO_FRAME_COMP_POFFSET (in_frame, 0);
1819 p[1] = GST_VIDEO_FRAME_COMP_POFFSET (in_frame, 1);
1820 p[3] = GST_VIDEO_FRAME_COMP_POFFSET (in_frame, 2);
1822 if (alpha->in_sdtv != alpha->out_sdtv) {
1826 alpha->in_sdtv ? cog_ycbcr_sdtv_to_ycbcr_hdtv_matrix_8bit :
1827 cog_ycbcr_hdtv_to_ycbcr_sdtv_matrix_8bit, 12 * sizeof (gint));
1829 for (i = 0; i < height; i++) {
1832 for (j = 0; j < width - 1; j += 2) {
1836 y = APPLY_MATRIX (matrix, 0, src[p[0]], src[p[1]], src[p[3]]);
1837 u = APPLY_MATRIX (matrix, 1, src[p[0]], src[p[1]], src[p[3]]);
1838 v = APPLY_MATRIX (matrix, 2, src[p[0]], src[p[1]], src[p[3]]);
1844 y = APPLY_MATRIX (matrix, 0, src[p[2]], src[p[1]], src[p[3]]);
1845 u = APPLY_MATRIX (matrix, 1, src[p[2]], src[p[1]], src[p[3]]);
1846 v = APPLY_MATRIX (matrix, 2, src[p[2]], src[p[1]], src[p[3]]);
1856 if (j == width - 1) {
1859 y = APPLY_MATRIX (matrix, 0, src[p[0]], src[p[1]], src[p[3]]);
1860 u = APPLY_MATRIX (matrix, 1, src[p[0]], src[p[1]], src[p[3]]);
1861 v = APPLY_MATRIX (matrix, 2, src[p[0]], src[p[1]], src[p[3]]);
1870 src = src_tmp + src_stride;
1873 for (i = 0; i < height; i++) {
1876 for (j = 0; j < width - 1; j += 2) {
1898 if (j == width - 1) {
1912 src = src_tmp + src_stride;
1918 gst_alpha_chroma_key_packed_422_ayuv (const GstVideoFrame * in_frame,
1919 GstVideoFrame * out_frame, GstAlpha * alpha)
1927 gint pa = CLAMP ((gint) (alpha->alpha * 255), 0, 255);
1928 gint8 cb = alpha->cb, cr = alpha->cr;
1929 gint8 kg = alpha->kg;
1930 guint8 accept_angle_tg = alpha->accept_angle_tg;
1931 guint8 accept_angle_ctg = alpha->accept_angle_ctg;
1932 guint8 one_over_kc = alpha->one_over_kc;
1933 guint8 kfgy_scale = alpha->kfgy_scale;
1934 guint noise_level2 = alpha->noise_level2;
1935 gint p[4]; /* Y U Y V */
1937 const guint8 *src_tmp;
1939 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
1940 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
1942 width = GST_VIDEO_FRAME_WIDTH (in_frame);
1943 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
1945 src_stride = GST_VIDEO_FRAME_COMP_STRIDE (in_frame, 0);
1947 p[0] = GST_VIDEO_FRAME_COMP_POFFSET (in_frame, 0);
1949 p[1] = GST_VIDEO_FRAME_COMP_POFFSET (in_frame, 1);
1950 p[3] = GST_VIDEO_FRAME_COMP_POFFSET (in_frame, 2);
1952 smin = 128 - alpha->black_sensitivity;
1953 smax = 128 + alpha->white_sensitivity;
1955 if (alpha->in_sdtv != alpha->out_sdtv) {
1959 alpha->in_sdtv ? cog_ycbcr_sdtv_to_ycbcr_hdtv_matrix_8bit :
1960 cog_ycbcr_hdtv_to_ycbcr_sdtv_matrix_8bit, 12 * sizeof (gint));
1962 for (i = 0; i < height; i++) {
1965 for (j = 0; j < width - 1; j += 2) {
1966 y = APPLY_MATRIX (matrix, 0, src[p[0]], src[p[1]], src[p[3]]);
1967 u = APPLY_MATRIX (matrix, 1, src[p[0]], src[p[1]], src[p[3]]) - 128;
1968 v = APPLY_MATRIX (matrix, 2, src[p[0]], src[p[1]], src[p[3]]) - 128;
1970 a = chroma_keying_yuv (pa, &y, &u, &v, cr, cb,
1971 smin, smax, accept_angle_tg, accept_angle_ctg,
1972 one_over_kc, kfgy_scale, kg, noise_level2);
1979 y = APPLY_MATRIX (matrix, 0, src[p[2]], src[p[1]], src[p[3]]);
1980 u = APPLY_MATRIX (matrix, 1, src[p[2]], src[p[1]], src[p[3]]) - 128;
1981 v = APPLY_MATRIX (matrix, 2, src[p[2]], src[p[1]], src[p[3]]) - 128;
1983 a = chroma_keying_yuv (pa, &y, &u, &v, cr, cb,
1984 smin, smax, accept_angle_tg, accept_angle_ctg,
1985 one_over_kc, kfgy_scale, kg, noise_level2);
1996 if (j == width - 1) {
1997 y = APPLY_MATRIX (matrix, 0, src[p[0]], src[p[1]], src[p[3]]);
1998 u = APPLY_MATRIX (matrix, 1, src[p[0]], src[p[1]], src[p[3]]) - 128;
1999 v = APPLY_MATRIX (matrix, 2, src[p[0]], src[p[1]], src[p[3]]) - 128;
2001 a = chroma_keying_yuv (pa, &y, &u, &v, cr, cb,
2002 smin, smax, accept_angle_tg, accept_angle_ctg,
2003 one_over_kc, kfgy_scale, kg, noise_level2);
2013 src = src_tmp + src_stride;
2016 for (i = 0; i < height; i++) {
2019 for (j = 0; j < width - 1; j += 2) {
2021 u = src[p[1]] - 128;
2022 v = src[p[3]] - 128;
2024 a = chroma_keying_yuv (pa, &y, &u, &v, cr, cb,
2025 smin, smax, accept_angle_tg, accept_angle_ctg,
2026 one_over_kc, kfgy_scale, kg, noise_level2);
2034 u = src[p[1]] - 128;
2035 v = src[p[3]] - 128;
2037 a = chroma_keying_yuv (pa, &y, &u, &v, cr, cb,
2038 smin, smax, accept_angle_tg, accept_angle_ctg,
2039 one_over_kc, kfgy_scale, kg, noise_level2);
2050 if (j == width - 1) {
2052 u = src[p[1]] - 128;
2053 v = src[p[3]] - 128;
2055 a = chroma_keying_yuv (pa, &y, &u, &v, cr, cb,
2056 smin, smax, accept_angle_tg, accept_angle_ctg,
2057 one_over_kc, kfgy_scale, kg, noise_level2);
2067 src = src_tmp + src_stride;
2073 gst_alpha_set_packed_422_argb (const GstVideoFrame * in_frame,
2074 GstVideoFrame * out_frame, GstAlpha * alpha)
2079 gint s_alpha = CLAMP ((gint) (alpha->alpha * 255), 0, 255);
2083 const guint8 *src_tmp;
2087 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
2088 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
2090 width = GST_VIDEO_FRAME_WIDTH (in_frame);
2091 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
2093 src_stride = GST_VIDEO_FRAME_COMP_STRIDE (in_frame, 0);
2095 o[0] = GST_VIDEO_FRAME_COMP_POFFSET (in_frame, 0);
2097 o[1] = GST_VIDEO_FRAME_COMP_POFFSET (in_frame, 1);
2098 o[3] = GST_VIDEO_FRAME_COMP_POFFSET (in_frame, 2);
2100 p[0] = GST_VIDEO_FRAME_COMP_POFFSET (out_frame, 3);
2101 p[1] = GST_VIDEO_FRAME_COMP_POFFSET (out_frame, 0);
2102 p[2] = GST_VIDEO_FRAME_COMP_POFFSET (out_frame, 1);
2103 p[3] = GST_VIDEO_FRAME_COMP_POFFSET (out_frame, 2);
2106 alpha->in_sdtv ? cog_ycbcr_to_rgb_matrix_8bit_sdtv :
2107 cog_ycbcr_to_rgb_matrix_8bit_hdtv, 12 * sizeof (gint));
2109 for (i = 0; i < height; i++) {
2112 for (j = 0; j < width - 1; j += 2) {
2113 r = APPLY_MATRIX (matrix, 0, src[o[0]], src[o[1]], src[o[3]]);
2114 g = APPLY_MATRIX (matrix, 1, src[o[0]], src[o[1]], src[o[3]]);
2115 b = APPLY_MATRIX (matrix, 2, src[o[0]], src[o[1]], src[o[3]]);
2117 dest[p[0]] = s_alpha;
2118 dest[p[1]] = CLAMP (r, 0, 255);
2119 dest[p[2]] = CLAMP (g, 0, 255);
2120 dest[p[3]] = CLAMP (b, 0, 255);
2122 r = APPLY_MATRIX (matrix, 0, src[o[2]], src[o[1]], src[o[3]]);
2123 g = APPLY_MATRIX (matrix, 1, src[o[2]], src[o[1]], src[o[3]]);
2124 b = APPLY_MATRIX (matrix, 2, src[o[2]], src[o[1]], src[o[3]]);
2126 dest[4 + p[0]] = s_alpha;
2127 dest[4 + p[1]] = CLAMP (r, 0, 255);
2128 dest[4 + p[2]] = CLAMP (g, 0, 255);
2129 dest[4 + p[3]] = CLAMP (b, 0, 255);
2135 if (j == width - 1) {
2136 r = APPLY_MATRIX (matrix, 0, src[o[0]], src[o[1]], src[o[3]]);
2137 g = APPLY_MATRIX (matrix, 1, src[o[0]], src[o[1]], src[o[3]]);
2138 b = APPLY_MATRIX (matrix, 2, src[o[0]], src[o[1]], src[o[3]]);
2140 dest[p[0]] = s_alpha;
2141 dest[p[1]] = CLAMP (r, 0, 255);
2142 dest[p[2]] = CLAMP (g, 0, 255);
2143 dest[p[3]] = CLAMP (b, 0, 255);
2148 src = src_tmp + src_stride;
2153 gst_alpha_chroma_key_packed_422_argb (const GstVideoFrame * in_frame,
2154 GstVideoFrame * out_frame, GstAlpha * alpha)
2163 gint pa = CLAMP ((gint) (alpha->alpha * 255), 0, 255);
2164 gint8 cb = alpha->cb, cr = alpha->cr;
2165 gint8 kg = alpha->kg;
2166 guint8 accept_angle_tg = alpha->accept_angle_tg;
2167 guint8 accept_angle_ctg = alpha->accept_angle_ctg;
2168 guint8 one_over_kc = alpha->one_over_kc;
2169 guint8 kfgy_scale = alpha->kfgy_scale;
2170 guint noise_level2 = alpha->noise_level2;
2173 const guint8 *src_tmp;
2176 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
2177 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
2179 width = GST_VIDEO_FRAME_WIDTH (in_frame);
2180 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
2182 src_stride = GST_VIDEO_FRAME_COMP_STRIDE (in_frame, 0);
2184 o[0] = GST_VIDEO_FRAME_COMP_POFFSET (in_frame, 0);
2186 o[1] = GST_VIDEO_FRAME_COMP_POFFSET (in_frame, 1);
2187 o[3] = GST_VIDEO_FRAME_COMP_POFFSET (in_frame, 2);
2189 p[0] = GST_VIDEO_FRAME_COMP_POFFSET (out_frame, 3);
2190 p[1] = GST_VIDEO_FRAME_COMP_POFFSET (out_frame, 0);
2191 p[2] = GST_VIDEO_FRAME_COMP_POFFSET (out_frame, 1);
2192 p[3] = GST_VIDEO_FRAME_COMP_POFFSET (out_frame, 2);
2195 alpha->in_sdtv ? cog_ycbcr_to_rgb_matrix_8bit_sdtv :
2196 cog_ycbcr_to_rgb_matrix_8bit_hdtv, 12 * sizeof (gint));
2198 smin = 128 - alpha->black_sensitivity;
2199 smax = 128 + alpha->white_sensitivity;
2201 for (i = 0; i < height; i++) {
2204 for (j = 0; j < width - 1; j += 2) {
2206 u = src[o[1]] - 128;
2207 v = src[o[3]] - 128;
2209 a = chroma_keying_yuv (pa, &y, &u, &v, cr, cb,
2210 smin, smax, accept_angle_tg, accept_angle_ctg,
2211 one_over_kc, kfgy_scale, kg, noise_level2);
2215 r = APPLY_MATRIX (matrix, 0, y, u, v);
2216 g = APPLY_MATRIX (matrix, 1, y, u, v);
2217 b = APPLY_MATRIX (matrix, 2, y, u, v);
2220 dest[p[1]] = CLAMP (r, 0, 255);
2221 dest[p[2]] = CLAMP (g, 0, 255);
2222 dest[p[3]] = CLAMP (b, 0, 255);
2225 u = src[o[1]] - 128;
2226 v = src[o[3]] - 128;
2228 a = chroma_keying_yuv (pa, &y, &u, &v, cr, cb,
2229 smin, smax, accept_angle_tg, accept_angle_ctg,
2230 one_over_kc, kfgy_scale, kg, noise_level2);
2234 r = APPLY_MATRIX (matrix, 0, y, u, v);
2235 g = APPLY_MATRIX (matrix, 1, y, u, v);
2236 b = APPLY_MATRIX (matrix, 2, y, u, v);
2239 dest[4 + p[1]] = CLAMP (r, 0, 255);
2240 dest[4 + p[2]] = CLAMP (g, 0, 255);
2241 dest[4 + p[3]] = CLAMP (b, 0, 255);
2247 if (j == width - 1) {
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);
2270 src = src_tmp + src_stride;
2274 /* Protected with the alpha lock */
2276 gst_alpha_init_params_full (GstAlpha * alpha,
2277 const GstVideoFormatInfo * in_info, const GstVideoFormatInfo * out_info)
2283 guint target_r = alpha->target_r;
2284 guint target_g = alpha->target_g;
2285 guint target_b = alpha->target_b;
2288 switch (alpha->method) {
2289 case ALPHA_METHOD_GREEN:
2294 case ALPHA_METHOD_BLUE:
2303 /* RGB->RGB: convert to SDTV YUV, chroma keying, convert back
2304 * YUV->RGB: chroma keying, convert to RGB
2305 * RGB->YUV: convert to YUV, chroma keying
2306 * YUV->YUV: convert matrix, chroma keying
2308 if (GST_VIDEO_FORMAT_INFO_IS_RGB (in_info)
2309 && GST_VIDEO_FORMAT_INFO_IS_RGB (out_info))
2310 matrix = cog_rgb_to_ycbcr_matrix_8bit_sdtv;
2311 else if (GST_VIDEO_FORMAT_INFO_IS_YUV (in_info)
2312 && GST_VIDEO_FORMAT_INFO_IS_RGB (out_info))
2314 (alpha->in_sdtv) ? cog_rgb_to_ycbcr_matrix_8bit_sdtv :
2315 cog_rgb_to_ycbcr_matrix_8bit_hdtv;
2316 else if (GST_VIDEO_FORMAT_INFO_IS_RGB (in_info)
2317 && GST_VIDEO_FORMAT_INFO_IS_YUV (out_info))
2319 (alpha->out_sdtv) ? cog_rgb_to_ycbcr_matrix_8bit_sdtv :
2320 cog_rgb_to_ycbcr_matrix_8bit_hdtv;
2321 else /* yuv -> yuv */
2323 (alpha->out_sdtv) ? cog_rgb_to_ycbcr_matrix_8bit_sdtv :
2324 cog_rgb_to_ycbcr_matrix_8bit_hdtv;
2326 y = (matrix[0] * ((gint) target_r) +
2327 matrix[1] * ((gint) target_g) +
2328 matrix[2] * ((gint) target_b) + matrix[3]) >> 8;
2329 /* Cb,Cr without offset here because the chroma keying
2330 * works with them being in range [-128,127]
2333 (matrix[4] * ((gint) target_r) +
2334 matrix[5] * ((gint) target_g) + matrix[6] * ((gint) target_b)) >> 8;
2336 (matrix[8] * ((gint) target_r) +
2337 matrix[9] * ((gint) target_g) + matrix[10] * ((gint) target_b)) >> 8;
2339 kgl = sqrt (tmp1 * tmp1 + tmp2 * tmp2);
2340 alpha->cb = 127 * (tmp1 / kgl);
2341 alpha->cr = 127 * (tmp2 / kgl);
2343 tmp = 15 * tan (M_PI * alpha->angle / 180);
2344 tmp = MIN (tmp, 255);
2345 alpha->accept_angle_tg = tmp;
2346 tmp = 15 / tan (M_PI * alpha->angle / 180);
2347 tmp = MIN (tmp, 255);
2348 alpha->accept_angle_ctg = tmp;
2350 alpha->one_over_kc = 255 * 2 * tmp - 255;
2352 tmp = MIN (tmp, 255);
2353 alpha->kfgy_scale = tmp;
2354 alpha->kg = MIN (kgl, 127);
2356 alpha->noise_level2 = alpha->noise_level * alpha->noise_level;
2360 gst_alpha_init_params (GstAlpha * alpha)
2362 const GstVideoFormatInfo *finfo_in, *finfo_out;
2364 finfo_in = GST_VIDEO_FILTER (alpha)->in_info.finfo;
2365 finfo_out = GST_VIDEO_FILTER (alpha)->out_info.finfo;
2367 if (finfo_in != NULL && finfo_out != NULL) {
2368 gst_alpha_init_params_full (alpha, finfo_in, finfo_out);
2370 GST_DEBUG_OBJECT (alpha, "video formats not set yet");
2374 /* Protected with the alpha lock */
2376 gst_alpha_set_process_function_full (GstAlpha * alpha, GstVideoInfo * in_info,
2377 GstVideoInfo * out_info)
2379 alpha->process = NULL;
2381 switch (alpha->method) {
2382 case ALPHA_METHOD_SET:
2383 switch (GST_VIDEO_INFO_FORMAT (out_info)) {
2384 case GST_VIDEO_FORMAT_AYUV:
2385 switch (GST_VIDEO_INFO_FORMAT (in_info)) {
2386 case GST_VIDEO_FORMAT_AYUV:
2387 alpha->process = gst_alpha_set_ayuv_ayuv;
2389 case GST_VIDEO_FORMAT_Y444:
2390 case GST_VIDEO_FORMAT_Y42B:
2391 case GST_VIDEO_FORMAT_I420:
2392 case GST_VIDEO_FORMAT_YV12:
2393 case GST_VIDEO_FORMAT_Y41B:
2394 alpha->process = gst_alpha_set_planar_yuv_ayuv;
2396 case GST_VIDEO_FORMAT_YUY2:
2397 case GST_VIDEO_FORMAT_YVYU:
2398 case GST_VIDEO_FORMAT_UYVY:
2399 alpha->process = gst_alpha_set_packed_422_ayuv;
2401 case GST_VIDEO_FORMAT_ARGB:
2402 case GST_VIDEO_FORMAT_ABGR:
2403 case GST_VIDEO_FORMAT_RGBA:
2404 case GST_VIDEO_FORMAT_BGRA:
2405 alpha->process = gst_alpha_set_argb_ayuv;
2407 case GST_VIDEO_FORMAT_xRGB:
2408 case GST_VIDEO_FORMAT_xBGR:
2409 case GST_VIDEO_FORMAT_RGBx:
2410 case GST_VIDEO_FORMAT_BGRx:
2411 case GST_VIDEO_FORMAT_RGB:
2412 case GST_VIDEO_FORMAT_BGR:
2413 alpha->process = gst_alpha_set_rgb_ayuv;
2419 case GST_VIDEO_FORMAT_ARGB:
2420 case GST_VIDEO_FORMAT_ABGR:
2421 case GST_VIDEO_FORMAT_RGBA:
2422 case GST_VIDEO_FORMAT_BGRA:
2423 switch (GST_VIDEO_INFO_FORMAT (in_info)) {
2424 case GST_VIDEO_FORMAT_AYUV:
2425 alpha->process = gst_alpha_set_ayuv_argb;
2427 case GST_VIDEO_FORMAT_Y444:
2428 case GST_VIDEO_FORMAT_Y42B:
2429 case GST_VIDEO_FORMAT_I420:
2430 case GST_VIDEO_FORMAT_YV12:
2431 case GST_VIDEO_FORMAT_Y41B:
2432 alpha->process = gst_alpha_set_planar_yuv_argb;
2434 case GST_VIDEO_FORMAT_YUY2:
2435 case GST_VIDEO_FORMAT_YVYU:
2436 case GST_VIDEO_FORMAT_UYVY:
2437 alpha->process = gst_alpha_set_packed_422_argb;
2439 case GST_VIDEO_FORMAT_ARGB:
2440 case GST_VIDEO_FORMAT_ABGR:
2441 case GST_VIDEO_FORMAT_RGBA:
2442 case GST_VIDEO_FORMAT_BGRA:
2443 alpha->process = gst_alpha_set_argb_argb;
2445 case GST_VIDEO_FORMAT_xRGB:
2446 case GST_VIDEO_FORMAT_xBGR:
2447 case GST_VIDEO_FORMAT_RGBx:
2448 case GST_VIDEO_FORMAT_BGRx:
2449 case GST_VIDEO_FORMAT_RGB:
2450 case GST_VIDEO_FORMAT_BGR:
2451 alpha->process = gst_alpha_set_rgb_argb;
2461 case ALPHA_METHOD_GREEN:
2462 case ALPHA_METHOD_BLUE:
2463 case ALPHA_METHOD_CUSTOM:
2464 switch (GST_VIDEO_INFO_FORMAT (out_info)) {
2465 case GST_VIDEO_FORMAT_AYUV:
2466 switch (GST_VIDEO_INFO_FORMAT (in_info)) {
2467 case GST_VIDEO_FORMAT_AYUV:
2468 alpha->process = gst_alpha_chroma_key_ayuv_ayuv;
2470 case GST_VIDEO_FORMAT_Y444:
2471 case GST_VIDEO_FORMAT_Y42B:
2472 case GST_VIDEO_FORMAT_I420:
2473 case GST_VIDEO_FORMAT_YV12:
2474 case GST_VIDEO_FORMAT_Y41B:
2475 alpha->process = gst_alpha_chroma_key_planar_yuv_ayuv;
2477 case GST_VIDEO_FORMAT_YUY2:
2478 case GST_VIDEO_FORMAT_YVYU:
2479 case GST_VIDEO_FORMAT_UYVY:
2480 alpha->process = gst_alpha_chroma_key_packed_422_ayuv;
2482 case GST_VIDEO_FORMAT_ARGB:
2483 case GST_VIDEO_FORMAT_ABGR:
2484 case GST_VIDEO_FORMAT_RGBA:
2485 case GST_VIDEO_FORMAT_BGRA:
2486 alpha->process = gst_alpha_chroma_key_argb_ayuv;
2488 case GST_VIDEO_FORMAT_xRGB:
2489 case GST_VIDEO_FORMAT_xBGR:
2490 case GST_VIDEO_FORMAT_RGBx:
2491 case GST_VIDEO_FORMAT_BGRx:
2492 case GST_VIDEO_FORMAT_RGB:
2493 case GST_VIDEO_FORMAT_BGR:
2494 alpha->process = gst_alpha_chroma_key_rgb_ayuv;
2500 case GST_VIDEO_FORMAT_ARGB:
2501 case GST_VIDEO_FORMAT_ABGR:
2502 case GST_VIDEO_FORMAT_RGBA:
2503 case GST_VIDEO_FORMAT_BGRA:
2504 switch (GST_VIDEO_INFO_FORMAT (in_info)) {
2505 case GST_VIDEO_FORMAT_AYUV:
2506 alpha->process = gst_alpha_chroma_key_ayuv_argb;
2508 case GST_VIDEO_FORMAT_Y444:
2509 case GST_VIDEO_FORMAT_Y42B:
2510 case GST_VIDEO_FORMAT_I420:
2511 case GST_VIDEO_FORMAT_YV12:
2512 case GST_VIDEO_FORMAT_Y41B:
2513 alpha->process = gst_alpha_chroma_key_planar_yuv_argb;
2515 case GST_VIDEO_FORMAT_YUY2:
2516 case GST_VIDEO_FORMAT_YVYU:
2517 case GST_VIDEO_FORMAT_UYVY:
2518 alpha->process = gst_alpha_chroma_key_packed_422_argb;
2520 case GST_VIDEO_FORMAT_ARGB:
2521 case GST_VIDEO_FORMAT_ABGR:
2522 case GST_VIDEO_FORMAT_RGBA:
2523 case GST_VIDEO_FORMAT_BGRA:
2524 alpha->process = gst_alpha_chroma_key_argb_argb;
2526 case GST_VIDEO_FORMAT_xRGB:
2527 case GST_VIDEO_FORMAT_xBGR:
2528 case GST_VIDEO_FORMAT_RGBx:
2529 case GST_VIDEO_FORMAT_BGRx:
2530 case GST_VIDEO_FORMAT_RGB:
2531 case GST_VIDEO_FORMAT_BGR:
2532 alpha->process = gst_alpha_chroma_key_rgb_argb;
2545 return alpha->process != NULL;
2549 gst_alpha_set_process_function (GstAlpha * alpha)
2551 GstVideoInfo *info_in, *info_out;
2553 info_in = &GST_VIDEO_FILTER (alpha)->in_info;
2554 info_out = &GST_VIDEO_FILTER (alpha)->out_info;
2556 if (info_in->finfo != NULL && info_out->finfo != NULL) {
2557 gst_alpha_set_process_function_full (alpha, info_in, info_out);
2559 GST_DEBUG_OBJECT (alpha, "video formats not set yet");
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_frame (GstVideoFilter * filter, GstVideoFrame * in_frame,
2578 GstVideoFrame * out_frame)
2580 GstAlpha *alpha = GST_ALPHA (filter);
2582 GST_ALPHA_LOCK (alpha);
2584 if (G_UNLIKELY (!alpha->process))
2585 goto not_negotiated;
2587 alpha->process (in_frame, out_frame, alpha);
2589 GST_ALPHA_UNLOCK (alpha);
2596 GST_ERROR_OBJECT (alpha, "Not negotiated yet");
2597 GST_ALPHA_UNLOCK (alpha);
2598 return GST_FLOW_NOT_NEGOTIATED;
2603 plugin_init (GstPlugin * plugin)
2605 return gst_element_register (plugin, "alpha", GST_RANK_NONE, GST_TYPE_ALPHA);
2608 GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
2611 "adds an alpha channel to video - constant or via chroma-keying",
2612 plugin_init, VERSION, GST_LICENSE, GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN)