2 * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
3 * Copyright (C) <2007> Wim Taymans <wim.taymans@collabora.co.uk>
4 * Copyright (C) <2007> Edward Hervey <edward.hervey@collabora.co.uk>
5 * Copyright (C) <2007> Jan Schmidt <thaytan@noraisin.net>
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Library General Public License for more details.
17 * You should have received a copy of the GNU Library General Public
18 * License along with this library; if not, write to the
19 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
20 * Boston, MA 02110-1301, USA.
24 * SECTION:element-alpha
26 * The alpha element adds an alpha channel to a video stream. The values
27 * of the alpha channel can be either be set to a constant or can be
28 * dynamically calculated via chroma keying, e.g. blue can be set as
29 * the transparent color.
33 * gst-launch-1.0 videotestsrc pattern=smpte75 ! alpha method=green ! \
34 * videomixer name=mixer ! videoconvert ! autovideosink \
35 * videotestsrc pattern=snow ! mixer.
36 * ]| This pipeline adds a alpha channel to the SMPTE color bars
37 * with green as the transparent color and mixes the output with
38 * a snow video stream.
53 #define M_PI 3.14159265358979323846
56 /* Generated by -bad/ext/cog/generate_tables */
57 static const int cog_ycbcr_to_rgb_matrix_8bit_hdtv[] = {
59 298, -55, -136, 19681,
63 static const int cog_ycbcr_to_rgb_matrix_8bit_sdtv[] = {
65 298, -100, -208, 34707,
69 static const gint cog_rgb_to_ycbcr_matrix_8bit_hdtv[] = {
72 112, -102, -10, 32768,
75 static const gint cog_rgb_to_ycbcr_matrix_8bit_sdtv[] = {
81 static const gint cog_ycbcr_sdtv_to_ycbcr_hdtv_matrix_8bit[] = {
87 static const gint cog_ycbcr_hdtv_to_ycbcr_sdtv_matrix_8bit[] = {
93 /* Alpha signals and args */
100 #define DEFAULT_METHOD ALPHA_METHOD_SET
101 #define DEFAULT_ALPHA 1.0
102 #define DEFAULT_TARGET_R 0
103 #define DEFAULT_TARGET_G 255
104 #define DEFAULT_TARGET_B 0
105 #define DEFAULT_ANGLE 20.0
106 #define DEFAULT_NOISE_LEVEL 2.0
107 #define DEFAULT_BLACK_SENSITIVITY 100
108 #define DEFAULT_WHITE_SENSITIVITY 100
109 #define DEFAULT_PREFER_PASSTHROUGH FALSE
121 PROP_BLACK_SENSITIVITY,
122 PROP_WHITE_SENSITIVITY,
123 PROP_PREFER_PASSTHROUGH,
127 static GstStaticPadTemplate gst_alpha_src_template =
128 GST_STATIC_PAD_TEMPLATE ("src",
131 GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE ("{ AYUV, "
132 "ARGB, BGRA, ABGR, RGBA, Y444, xRGB, BGRx, xBGR, "
133 "RGBx, RGB, BGR, Y42B, YUY2, YVYU, UYVY, I420, YV12, Y41B } "))
136 static GstStaticPadTemplate gst_alpha_sink_template =
137 GST_STATIC_PAD_TEMPLATE ("sink",
140 GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE ("{ AYUV, "
141 "ARGB, BGRA, ABGR, RGBA, Y444, xRGB, BGRx, xBGR, "
142 "RGBx, RGB, BGR, Y42B, YUY2, YVYU, UYVY, I420, YV12, " "Y41B } "))
145 static GstStaticCaps gst_alpha_alpha_caps =
146 GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE ("{ AYUV, ARGB, BGRA, ABGR, RGBA }"));
148 /* FIXME: why do we need our own lock for this? */
149 #define GST_ALPHA_LOCK(alpha) G_STMT_START { \
150 GST_LOG_OBJECT (alpha, "Locking alpha from thread %p", g_thread_self ()); \
151 g_mutex_lock (&alpha->lock); \
152 GST_LOG_OBJECT (alpha, "Locked alpha from thread %p", g_thread_self ()); \
155 #define GST_ALPHA_UNLOCK(alpha) G_STMT_START { \
156 GST_LOG_OBJECT (alpha, "Unlocking alpha from thread %p", g_thread_self ()); \
157 g_mutex_unlock (&alpha->lock); \
160 static GstCaps *gst_alpha_transform_caps (GstBaseTransform * btrans,
161 GstPadDirection direction, GstCaps * caps, GstCaps * filter);
162 static void gst_alpha_before_transform (GstBaseTransform * btrans,
165 static gboolean gst_alpha_set_info (GstVideoFilter * filter,
166 GstCaps * incaps, GstVideoInfo * in_info, GstCaps * outcaps,
167 GstVideoInfo * out_info);
168 static GstFlowReturn gst_alpha_transform_frame (GstVideoFilter * filter,
169 GstVideoFrame * in_frame, GstVideoFrame * out_frame);
171 static void gst_alpha_init_params_full (GstAlpha * alpha,
172 const GstVideoFormatInfo * in_info, const GstVideoFormatInfo * out_info);
173 static void gst_alpha_init_params (GstAlpha * alpha);
174 static void gst_alpha_set_process_function (GstAlpha * alpha);
175 static gboolean gst_alpha_set_process_function_full (GstAlpha * alpha,
176 GstVideoInfo * in_info, GstVideoInfo * out_info);
178 static void gst_alpha_set_property (GObject * object, guint prop_id,
179 const GValue * value, GParamSpec * pspec);
180 static void gst_alpha_get_property (GObject * object, guint prop_id,
181 GValue * value, GParamSpec * pspec);
182 static void gst_alpha_finalize (GObject * object);
184 #define gst_alpha_parent_class parent_class
185 G_DEFINE_TYPE (GstAlpha, gst_alpha, GST_TYPE_VIDEO_FILTER);
187 #define GST_TYPE_ALPHA_METHOD (gst_alpha_method_get_type())
189 gst_alpha_method_get_type (void)
191 static GType alpha_method_type = 0;
192 static const GEnumValue alpha_method[] = {
193 {ALPHA_METHOD_SET, "Set/adjust alpha channel", "set"},
194 {ALPHA_METHOD_GREEN, "Chroma Key on pure green", "green"},
195 {ALPHA_METHOD_BLUE, "Chroma Key on pure blue", "blue"},
196 {ALPHA_METHOD_CUSTOM, "Chroma Key on custom RGB values", "custom"},
200 if (!alpha_method_type) {
201 alpha_method_type = g_enum_register_static ("GstAlphaMethod", alpha_method);
203 return alpha_method_type;
207 gst_alpha_class_init (GstAlphaClass * klass)
209 GObjectClass *gobject_class = (GObjectClass *) klass;
210 GstElementClass *gstelement_class = (GstElementClass *) klass;
211 GstBaseTransformClass *btrans_class = (GstBaseTransformClass *) klass;
212 GstVideoFilterClass *vfilter_class = (GstVideoFilterClass *) klass;
214 GST_DEBUG_CATEGORY_INIT (gst_alpha_debug, "alpha", 0,
215 "alpha - Element for adding alpha channel to streams");
217 gobject_class->set_property = gst_alpha_set_property;
218 gobject_class->get_property = gst_alpha_get_property;
219 gobject_class->finalize = gst_alpha_finalize;
221 g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_METHOD,
222 g_param_spec_enum ("method", "Method",
223 "How the alpha channels should be created", GST_TYPE_ALPHA_METHOD,
224 DEFAULT_METHOD, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
225 g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_ALPHA,
226 g_param_spec_double ("alpha", "Alpha", "The value for the alpha channel",
227 0.0, 1.0, DEFAULT_ALPHA,
228 G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
229 g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_TARGET_R,
230 g_param_spec_uint ("target-r", "Target Red",
231 "The red color value for custom RGB chroma keying", 0, 255,
233 G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
234 g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_TARGET_G,
235 g_param_spec_uint ("target-g", "Target Green",
236 "The green color value for custom RGB chroma keying", 0, 255,
238 G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
239 g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_TARGET_B,
240 g_param_spec_uint ("target-b", "Target Blue",
241 "The blue color value for custom RGB chroma keying", 0, 255,
243 G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
244 g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_ANGLE,
245 g_param_spec_float ("angle", "Angle", "Size of the colorcube to change",
246 0.0, 90.0, DEFAULT_ANGLE,
247 G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
248 g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_NOISE_LEVEL,
249 g_param_spec_float ("noise-level", "Noise Level", "Size of noise radius",
250 0.0, 64.0, DEFAULT_NOISE_LEVEL,
251 G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
252 g_object_class_install_property (G_OBJECT_CLASS (klass),
253 PROP_BLACK_SENSITIVITY, g_param_spec_uint ("black-sensitivity",
254 "Black Sensitivity", "Sensitivity to dark colors", 0, 128,
255 DEFAULT_BLACK_SENSITIVITY,
256 G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
257 g_object_class_install_property (G_OBJECT_CLASS (klass),
258 PROP_WHITE_SENSITIVITY, g_param_spec_uint ("white-sensitivity",
259 "White Sensitivity", "Sensitivity to bright colors", 0, 128,
260 DEFAULT_WHITE_SENSITIVITY,
261 G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
262 g_object_class_install_property (G_OBJECT_CLASS (klass),
263 PROP_PREFER_PASSTHROUGH, g_param_spec_boolean ("prefer-passthrough",
264 "Prefer Passthrough",
265 "Don't do any processing for alpha=1.0 if possible",
266 DEFAULT_PREFER_PASSTHROUGH,
267 G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
269 gst_element_class_set_static_metadata (gstelement_class, "Alpha filter",
270 "Filter/Effect/Video",
271 "Adds an alpha channel to video - uniform or via chroma-keying",
272 "Wim Taymans <wim.taymans@gmail.com>\n"
273 "Edward Hervey <edward.hervey@collabora.co.uk>\n"
274 "Jan Schmidt <thaytan@noraisin.net>");
276 gst_element_class_add_pad_template (gstelement_class,
277 gst_static_pad_template_get (&gst_alpha_sink_template));
278 gst_element_class_add_pad_template (gstelement_class,
279 gst_static_pad_template_get (&gst_alpha_src_template));
281 btrans_class->before_transform =
282 GST_DEBUG_FUNCPTR (gst_alpha_before_transform);
283 btrans_class->transform_caps = GST_DEBUG_FUNCPTR (gst_alpha_transform_caps);
285 vfilter_class->set_info = GST_DEBUG_FUNCPTR (gst_alpha_set_info);
286 vfilter_class->transform_frame =
287 GST_DEBUG_FUNCPTR (gst_alpha_transform_frame);
291 gst_alpha_init (GstAlpha * alpha)
293 alpha->alpha = DEFAULT_ALPHA;
294 alpha->method = DEFAULT_METHOD;
295 alpha->target_r = DEFAULT_TARGET_R;
296 alpha->target_g = DEFAULT_TARGET_G;
297 alpha->target_b = DEFAULT_TARGET_B;
298 alpha->angle = DEFAULT_ANGLE;
299 alpha->noise_level = DEFAULT_NOISE_LEVEL;
300 alpha->black_sensitivity = DEFAULT_BLACK_SENSITIVITY;
301 alpha->white_sensitivity = DEFAULT_WHITE_SENSITIVITY;
303 g_mutex_init (&alpha->lock);
307 gst_alpha_finalize (GObject * object)
309 GstAlpha *alpha = GST_ALPHA (object);
311 g_mutex_clear (&alpha->lock);
313 G_OBJECT_CLASS (parent_class)->finalize (object);
317 gst_alpha_set_property (GObject * object, guint prop_id,
318 const GValue * value, GParamSpec * pspec)
320 GstAlpha *alpha = GST_ALPHA (object);
321 gboolean reconfigure = FALSE;
323 GST_ALPHA_LOCK (alpha);
326 gint method = g_value_get_enum (value);
328 reconfigure = (method != alpha->method) && (method == ALPHA_METHOD_SET
329 || alpha->method == ALPHA_METHOD_SET) && (alpha->alpha == 1.0)
330 && (alpha->prefer_passthrough);
331 alpha->method = method;
333 gst_alpha_set_process_function (alpha);
334 gst_alpha_init_params (alpha);
338 gdouble a = g_value_get_double (value);
340 reconfigure = (a != alpha->alpha) && (a == 1.0 || alpha->alpha == 1.0)
341 && (alpha->method == ALPHA_METHOD_SET) && (alpha->prefer_passthrough);
346 alpha->target_r = g_value_get_uint (value);
347 gst_alpha_init_params (alpha);
350 alpha->target_g = g_value_get_uint (value);
351 gst_alpha_init_params (alpha);
354 alpha->target_b = g_value_get_uint (value);
355 gst_alpha_init_params (alpha);
358 alpha->angle = g_value_get_float (value);
359 gst_alpha_init_params (alpha);
361 case PROP_NOISE_LEVEL:
362 alpha->noise_level = g_value_get_float (value);
363 gst_alpha_init_params (alpha);
365 case PROP_BLACK_SENSITIVITY:
366 alpha->black_sensitivity = g_value_get_uint (value);
368 case PROP_WHITE_SENSITIVITY:
369 alpha->white_sensitivity = g_value_get_uint (value);
371 case PROP_PREFER_PASSTHROUGH:{
372 gboolean prefer_passthrough = g_value_get_boolean (value);
374 reconfigure = ((! !prefer_passthrough) != (! !alpha->prefer_passthrough))
375 && (alpha->method == ALPHA_METHOD_SET) && (alpha->alpha == 1.0);
376 alpha->prefer_passthrough = prefer_passthrough;
380 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
385 gst_base_transform_reconfigure_src (GST_BASE_TRANSFORM_CAST (alpha));
387 GST_ALPHA_UNLOCK (alpha);
391 gst_alpha_get_property (GObject * object, guint prop_id, GValue * value,
394 GstAlpha *alpha = GST_ALPHA (object);
398 g_value_set_enum (value, alpha->method);
401 g_value_set_double (value, alpha->alpha);
404 g_value_set_uint (value, alpha->target_r);
407 g_value_set_uint (value, alpha->target_g);
410 g_value_set_uint (value, alpha->target_b);
413 g_value_set_float (value, alpha->angle);
415 case PROP_NOISE_LEVEL:
416 g_value_set_float (value, alpha->noise_level);
418 case PROP_BLACK_SENSITIVITY:
419 g_value_set_uint (value, alpha->black_sensitivity);
421 case PROP_WHITE_SENSITIVITY:
422 g_value_set_uint (value, alpha->white_sensitivity);
424 case PROP_PREFER_PASSTHROUGH:
425 g_value_set_boolean (value, alpha->prefer_passthrough);
428 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
434 gst_alpha_transform_caps (GstBaseTransform * btrans,
435 GstPadDirection direction, GstCaps * caps, GstCaps * filter)
437 GstAlpha *alpha = GST_ALPHA (btrans);
438 GstCaps *ret, *tmp, *tmp2;
439 GstStructure *structure;
442 tmp = gst_caps_new_empty ();
444 GST_ALPHA_LOCK (alpha);
445 for (i = 0; i < gst_caps_get_size (caps); i++) {
446 structure = gst_structure_copy (gst_caps_get_structure (caps, i));
448 gst_structure_remove_field (structure, "format");
449 gst_structure_remove_field (structure, "colorimetry");
450 gst_structure_remove_field (structure, "chroma-site");
452 gst_caps_append_structure (tmp, structure);
455 if (direction == GST_PAD_SINK) {
456 tmp2 = gst_static_caps_get (&gst_alpha_alpha_caps);
457 ret = gst_caps_intersect (tmp, tmp2);
458 gst_caps_unref (tmp);
459 gst_caps_unref (tmp2);
463 if (alpha->prefer_passthrough && alpha->method == ALPHA_METHOD_SET
464 && alpha->alpha == 1.0) {
465 ret = gst_caps_copy (caps);
466 gst_caps_append (ret, tmp);
477 GST_DEBUG_OBJECT (alpha,
478 "Transformed %" GST_PTR_FORMAT " -> %" GST_PTR_FORMAT, caps, ret);
481 GstCaps *intersection;
483 GST_DEBUG_OBJECT (alpha, "Using filter caps %" GST_PTR_FORMAT, filter);
485 gst_caps_intersect_full (filter, ret, GST_CAPS_INTERSECT_FIRST);
486 gst_caps_unref (ret);
488 GST_DEBUG_OBJECT (alpha, "Intersection %" GST_PTR_FORMAT, ret);
492 GST_ALPHA_UNLOCK (alpha);
498 gst_alpha_set_info (GstVideoFilter * filter,
499 GstCaps * incaps, GstVideoInfo * in_info, GstCaps * outcaps,
500 GstVideoInfo * out_info)
502 GstAlpha *alpha = GST_ALPHA (filter);
503 gboolean passthrough;
505 GST_ALPHA_LOCK (alpha);
507 alpha->in_sdtv = in_info->colorimetry.matrix == GST_VIDEO_COLOR_MATRIX_BT601;
509 out_info->colorimetry.matrix == GST_VIDEO_COLOR_MATRIX_BT601;
511 passthrough = alpha->prefer_passthrough &&
512 GST_VIDEO_INFO_FORMAT (in_info) == GST_VIDEO_INFO_FORMAT (out_info)
513 && alpha->in_sdtv == alpha->out_sdtv && alpha->method == ALPHA_METHOD_SET
514 && alpha->alpha == 1.0;
516 GST_DEBUG_OBJECT (alpha,
517 "Setting caps %" GST_PTR_FORMAT " -> %" GST_PTR_FORMAT
518 " (passthrough: %d)", incaps, outcaps, passthrough);
519 gst_base_transform_set_passthrough (GST_BASE_TRANSFORM_CAST (filter),
522 if (!gst_alpha_set_process_function_full (alpha, in_info, out_info)
526 gst_alpha_init_params_full (alpha, in_info->finfo, out_info->finfo);
528 GST_ALPHA_UNLOCK (alpha);
535 GST_WARNING_OBJECT (alpha,
536 "No processing function for this caps and no passthrough mode");
537 GST_ALPHA_UNLOCK (alpha);
542 /* based on http://www.cs.utah.edu/~michael/chroma/
545 chroma_keying_yuv (gint a, gint * y, gint * u,
546 gint * v, gint cr, gint cb, gint smin, gint smax, guint8 accept_angle_tg,
547 guint8 accept_angle_ctg, guint8 one_over_kc, guint8 kfgy_scale, gint8 kg,
555 /* too dark or too bright, keep alpha */
556 if (*y < smin || *y > smax)
559 /* Convert foreground to XZ coords where X direction is defined by
561 tmp = ((*u) * cb + (*v) * cr) >> 7;
562 x = CLAMP (tmp, -128, 127);
563 tmp = ((*v) * cb - (*u) * cr) >> 7;
564 z = CLAMP (tmp, -128, 127);
566 /* WARNING: accept angle should never be set greater than "somewhat less
567 than 90 degrees" to avoid dealing with negative/infinite tg. In reality,
568 80 degrees should be enough if foreground is reasonable. If this seems
569 to be a problem, go to alternative ways of checking point position
570 (scalar product or line equations). This angle should not be too small
571 either to avoid infinite ctg (used to suppress foreground without use of
574 tmp = (x * accept_angle_tg) >> 4;
575 tmp = MIN (tmp, 127);
578 /* keep foreground Kfg = 0 */
581 /* Compute Kfg (implicitly) and Kbg, suppress foreground in XZ coord
583 tmp = (z * accept_angle_ctg) >> 4;
584 tmp = CLAMP (tmp, -128, 127);
589 tmp1 = MAX (tmp1, 0);
590 b_alpha = (tmp1 * one_over_kc) / 2;
591 b_alpha = 255 - CLAMP (b_alpha, 0, 255);
592 b_alpha = (a * b_alpha) >> 8;
594 tmp = (tmp1 * kfgy_scale) >> 4;
595 tmp1 = MIN (tmp, 255);
597 *y = (*y < tmp1) ? 0 : *y - tmp1;
599 /* Convert suppressed foreground back to CbCr */
600 tmp = (x1 * cb - y1 * cr) >> 7;
601 *u = CLAMP (tmp, -128, 127);
603 tmp = (x1 * cr + y1 * cb) >> 7;
604 *v = CLAMP (tmp, -128, 127);
606 /* Deal with noise. For now, a circle around the key color with
607 radius of noise_level treated as exact key color. Introduces
610 tmp = z * z + (x - kg) * (x - kg);
611 tmp = MIN (tmp, 0xffff);
613 if (tmp < noise_level2)
619 #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)
622 gst_alpha_set_argb_ayuv (const GstVideoFrame * in_frame,
623 GstVideoFrame * out_frame, GstAlpha * alpha)
625 gint s_alpha = CLAMP ((gint) (alpha->alpha * 256), 0, 256);
634 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
635 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
637 width = GST_VIDEO_FRAME_WIDTH (in_frame);
638 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
640 o[0] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 3);
641 o[1] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 0);
642 o[2] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 1);
643 o[3] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 2);
646 alpha->out_sdtv ? cog_rgb_to_ycbcr_matrix_8bit_sdtv :
647 cog_rgb_to_ycbcr_matrix_8bit_hdtv, 12 * sizeof (gint));
649 for (i = 0; i < height; i++) {
650 for (j = 0; j < width; j++) {
651 dest[0] = (src[o[0]] * s_alpha) >> 8;
653 y = APPLY_MATRIX (matrix, 0, src[o[1]], src[o[2]], src[o[3]]);
654 u = APPLY_MATRIX (matrix, 1, src[o[1]], src[o[2]], src[o[3]]);
655 v = APPLY_MATRIX (matrix, 2, src[o[1]], src[o[2]], src[o[3]]);
668 gst_alpha_chroma_key_argb_ayuv (const GstVideoFrame * in_frame,
669 GstVideoFrame * out_frame, GstAlpha * alpha)
678 gint pa = CLAMP ((gint) (alpha->alpha * 256), 0, 256);
679 gint8 cb = alpha->cb, cr = alpha->cr;
680 gint8 kg = alpha->kg;
681 guint8 accept_angle_tg = alpha->accept_angle_tg;
682 guint8 accept_angle_ctg = alpha->accept_angle_ctg;
683 guint8 one_over_kc = alpha->one_over_kc;
684 guint8 kfgy_scale = alpha->kfgy_scale;
685 guint noise_level2 = alpha->noise_level2;
689 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
690 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
692 width = GST_VIDEO_FRAME_WIDTH (in_frame);
693 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
695 o[0] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 3);
696 o[1] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 0);
697 o[2] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 1);
698 o[3] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 2);
700 smin = 128 - alpha->black_sensitivity;
701 smax = 128 + alpha->white_sensitivity;
704 alpha->out_sdtv ? cog_rgb_to_ycbcr_matrix_8bit_sdtv :
705 cog_rgb_to_ycbcr_matrix_8bit_hdtv, 12 * sizeof (gint));
707 for (i = 0; i < height; i++) {
708 for (j = 0; j < width; j++) {
709 a = (src[o[0]] * pa) >> 8;
714 y = APPLY_MATRIX (matrix, 0, r, g, b);
715 u = APPLY_MATRIX (matrix, 1, r, g, b) - 128;
716 v = APPLY_MATRIX (matrix, 2, r, g, b) - 128;
718 a = chroma_keying_yuv (a, &y, &u, &v, cr, cb,
719 smin, smax, accept_angle_tg, accept_angle_ctg,
720 one_over_kc, kfgy_scale, kg, noise_level2);
737 gst_alpha_set_argb_argb (const GstVideoFrame * in_frame,
738 GstVideoFrame * out_frame, GstAlpha * alpha)
743 gint s_alpha = CLAMP ((gint) (alpha->alpha * 256), 0, 256);
747 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
748 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
750 width = GST_VIDEO_FRAME_WIDTH (in_frame);
751 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
753 p[0] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 3);
754 p[1] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 0);
755 p[2] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 1);
756 p[3] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 2);
758 o[0] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 3);
759 o[1] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 0);
760 o[2] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 1);
761 o[3] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 2);
763 for (i = 0; i < height; i++) {
764 for (j = 0; j < width; j++) {
765 dest[p[0]] = (src[o[0]] * s_alpha) >> 8;
767 dest[p[1]] = src[o[1]];
768 dest[p[2]] = src[o[2]];
769 dest[p[3]] = src[o[3]];
778 gst_alpha_chroma_key_argb_argb (const GstVideoFrame * in_frame,
779 GstVideoFrame * out_frame, GstAlpha * alpha)
788 gint pa = CLAMP ((gint) (alpha->alpha * 256), 0, 256);
789 gint8 cb = alpha->cb, cr = alpha->cr;
790 gint8 kg = alpha->kg;
791 guint8 accept_angle_tg = alpha->accept_angle_tg;
792 guint8 accept_angle_ctg = alpha->accept_angle_ctg;
793 guint8 one_over_kc = alpha->one_over_kc;
794 guint8 kfgy_scale = alpha->kfgy_scale;
795 guint noise_level2 = alpha->noise_level2;
796 gint matrix[12], matrix2[12];
799 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
800 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
802 width = GST_VIDEO_FRAME_WIDTH (in_frame);
803 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
805 p[0] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 3);
806 p[1] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 0);
807 p[2] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 1);
808 p[3] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 2);
810 o[0] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 3);
811 o[1] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 0);
812 o[2] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 1);
813 o[3] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 2);
815 smin = 128 - alpha->black_sensitivity;
816 smax = 128 + alpha->white_sensitivity;
818 memcpy (matrix, cog_rgb_to_ycbcr_matrix_8bit_sdtv, 12 * sizeof (gint));
819 memcpy (matrix2, cog_ycbcr_to_rgb_matrix_8bit_sdtv, 12 * sizeof (gint));
821 for (i = 0; i < height; i++) {
822 for (j = 0; j < width; j++) {
823 a = (src[o[0]] * pa) >> 8;
828 y = APPLY_MATRIX (matrix, 0, r, g, b);
829 u = APPLY_MATRIX (matrix, 1, r, g, b) - 128;
830 v = APPLY_MATRIX (matrix, 2, r, g, b) - 128;
832 a = chroma_keying_yuv (a, &y, &u, &v, cr, cb,
833 smin, smax, accept_angle_tg, accept_angle_ctg,
834 one_over_kc, kfgy_scale, kg, noise_level2);
839 r = APPLY_MATRIX (matrix2, 0, y, u, v);
840 g = APPLY_MATRIX (matrix2, 1, y, u, v);
841 b = APPLY_MATRIX (matrix2, 2, y, u, v);
844 dest[p[1]] = CLAMP (r, 0, 255);
845 dest[p[2]] = CLAMP (g, 0, 255);
846 dest[p[3]] = CLAMP (b, 0, 255);
855 gst_alpha_set_ayuv_argb (const GstVideoFrame * in_frame,
856 GstVideoFrame * out_frame, GstAlpha * alpha)
861 gint s_alpha = CLAMP ((gint) (alpha->alpha * 256), 0, 256);
867 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
868 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
870 width = GST_VIDEO_FRAME_WIDTH (in_frame);
871 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
873 p[0] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 3);
874 p[1] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 0);
875 p[2] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 1);
876 p[3] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 2);
879 alpha->in_sdtv ? cog_ycbcr_to_rgb_matrix_8bit_sdtv :
880 cog_ycbcr_to_rgb_matrix_8bit_hdtv, 12 * sizeof (gint));
882 for (y = 0; y < height; y++) {
883 for (x = 0; x < width; x++) {
884 dest[p[0]] = (src[0] * s_alpha) >> 8;
886 r = APPLY_MATRIX (matrix, 0, src[1], src[2], src[3]);
887 g = APPLY_MATRIX (matrix, 1, src[1], src[2], src[3]);
888 b = APPLY_MATRIX (matrix, 2, src[1], src[2], src[3]);
890 dest[p[1]] = CLAMP (r, 0, 255);
891 dest[p[2]] = CLAMP (g, 0, 255);
892 dest[p[3]] = CLAMP (b, 0, 255);
901 gst_alpha_chroma_key_ayuv_argb (const GstVideoFrame * in_frame,
902 GstVideoFrame * out_frame, GstAlpha * alpha)
911 gint pa = CLAMP ((gint) (alpha->alpha * 256), 0, 256);
912 gint8 cb = alpha->cb, cr = alpha->cr;
913 gint8 kg = alpha->kg;
914 guint8 accept_angle_tg = alpha->accept_angle_tg;
915 guint8 accept_angle_ctg = alpha->accept_angle_ctg;
916 guint8 one_over_kc = alpha->one_over_kc;
917 guint8 kfgy_scale = alpha->kfgy_scale;
918 guint noise_level2 = alpha->noise_level2;
922 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
923 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
925 width = GST_VIDEO_FRAME_WIDTH (in_frame);
926 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
928 p[0] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 3);
929 p[1] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 0);
930 p[2] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 1);
931 p[3] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 2);
933 smin = 128 - alpha->black_sensitivity;
934 smax = 128 + alpha->white_sensitivity;
937 alpha->in_sdtv ? cog_ycbcr_to_rgb_matrix_8bit_sdtv :
938 cog_ycbcr_to_rgb_matrix_8bit_hdtv, 12 * sizeof (gint));
940 for (i = 0; i < height; i++) {
941 for (j = 0; j < width; j++) {
942 a = (src[0] * pa) >> 8;
947 a = chroma_keying_yuv (a, &y, &u, &v, cr, cb,
948 smin, smax, accept_angle_tg, accept_angle_ctg,
949 one_over_kc, kfgy_scale, kg, noise_level2);
954 r = APPLY_MATRIX (matrix, 0, y, u, v);
955 g = APPLY_MATRIX (matrix, 1, y, u, v);
956 b = APPLY_MATRIX (matrix, 2, y, u, v);
959 dest[p[1]] = CLAMP (r, 0, 255);
960 dest[p[2]] = CLAMP (g, 0, 255);
961 dest[p[3]] = CLAMP (b, 0, 255);
970 gst_alpha_set_ayuv_ayuv (const GstVideoFrame * in_frame,
971 GstVideoFrame * out_frame, GstAlpha * alpha)
976 gint s_alpha = CLAMP ((gint) (alpha->alpha * 256), 0, 256);
979 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
980 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
982 width = GST_VIDEO_FRAME_WIDTH (in_frame);
983 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
985 if (alpha->in_sdtv == alpha->out_sdtv) {
986 for (y = 0; y < height; y++) {
987 for (x = 0; x < width; x++) {
988 dest[0] = (src[0] * s_alpha) >> 8;
1001 alpha->out_sdtv ? cog_ycbcr_hdtv_to_ycbcr_sdtv_matrix_8bit :
1002 cog_ycbcr_sdtv_to_ycbcr_hdtv_matrix_8bit, 12 * sizeof (gint));
1004 for (y = 0; y < height; y++) {
1005 for (x = 0; x < width; x++) {
1006 dest[0] = (src[0] * s_alpha) >> 8;
1007 dest[1] = APPLY_MATRIX (matrix, 0, src[1], src[2], src[3]);
1008 dest[2] = APPLY_MATRIX (matrix, 1, src[1], src[2], src[3]);
1009 dest[3] = APPLY_MATRIX (matrix, 2, src[1], src[2], src[3]);
1019 gst_alpha_chroma_key_ayuv_ayuv (const GstVideoFrame * in_frame,
1020 GstVideoFrame * out_frame, GstAlpha * alpha)
1028 gint pa = CLAMP ((gint) (alpha->alpha * 256), 0, 256);
1029 gint8 cb = alpha->cb, cr = alpha->cr;
1030 gint8 kg = alpha->kg;
1031 guint8 accept_angle_tg = alpha->accept_angle_tg;
1032 guint8 accept_angle_ctg = alpha->accept_angle_ctg;
1033 guint8 one_over_kc = alpha->one_over_kc;
1034 guint8 kfgy_scale = alpha->kfgy_scale;
1035 guint noise_level2 = alpha->noise_level2;
1037 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
1038 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
1040 width = GST_VIDEO_FRAME_WIDTH (in_frame);
1041 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
1043 smin = 128 - alpha->black_sensitivity;
1044 smax = 128 + alpha->white_sensitivity;
1046 if (alpha->in_sdtv == alpha->out_sdtv) {
1047 for (i = 0; i < height; i++) {
1048 for (j = 0; j < width; j++) {
1049 a = (src[0] * pa) >> 8;
1054 a = chroma_keying_yuv (a, &y, &u, &v, cr, cb,
1055 smin, smax, accept_angle_tg, accept_angle_ctg,
1056 one_over_kc, kfgy_scale, kg, noise_level2);
1074 alpha->out_sdtv ? cog_ycbcr_hdtv_to_ycbcr_sdtv_matrix_8bit :
1075 cog_ycbcr_sdtv_to_ycbcr_hdtv_matrix_8bit, 12 * sizeof (gint));
1077 for (i = 0; i < height; i++) {
1078 for (j = 0; j < width; j++) {
1079 a = (src[0] * pa) >> 8;
1080 y = APPLY_MATRIX (matrix, 0, src[1], src[2], src[3]);
1081 u = APPLY_MATRIX (matrix, 1, src[1], src[2], src[3]) - 128;
1082 v = APPLY_MATRIX (matrix, 2, src[1], src[2], src[3]) - 128;
1084 a = chroma_keying_yuv (a, &y, &u, &v, cr, cb,
1085 smin, smax, accept_angle_tg, accept_angle_ctg,
1086 one_over_kc, kfgy_scale, kg, noise_level2);
1104 gst_alpha_set_rgb_ayuv (const GstVideoFrame * in_frame,
1105 GstVideoFrame * out_frame, GstAlpha * alpha)
1110 gint s_alpha = CLAMP ((gint) (alpha->alpha * 255), 0, 255);
1117 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
1118 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
1120 width = GST_VIDEO_FRAME_WIDTH (in_frame);
1121 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
1123 bpp = GST_VIDEO_FRAME_COMP_PSTRIDE (in_frame, 0);
1124 o[0] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 0);
1125 o[1] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 1);
1126 o[2] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 2);
1129 alpha->out_sdtv ? cog_rgb_to_ycbcr_matrix_8bit_sdtv :
1130 cog_rgb_to_ycbcr_matrix_8bit_hdtv, 12 * sizeof (gint));
1132 for (i = 0; i < height; i++) {
1133 for (j = 0; j < width; j++) {
1136 y = APPLY_MATRIX (matrix, 0, src[o[0]], src[o[1]], src[o[2]]);
1137 u = APPLY_MATRIX (matrix, 1, src[o[0]], src[o[1]], src[o[2]]);
1138 v = APPLY_MATRIX (matrix, 2, src[o[0]], src[o[1]], src[o[2]]);
1151 gst_alpha_chroma_key_rgb_ayuv (const GstVideoFrame * in_frame,
1152 GstVideoFrame * out_frame, GstAlpha * alpha)
1161 gint pa = CLAMP ((gint) (alpha->alpha * 255), 0, 255);
1162 gint8 cb = alpha->cb, cr = alpha->cr;
1163 gint8 kg = alpha->kg;
1164 guint8 accept_angle_tg = alpha->accept_angle_tg;
1165 guint8 accept_angle_ctg = alpha->accept_angle_ctg;
1166 guint8 one_over_kc = alpha->one_over_kc;
1167 guint8 kfgy_scale = alpha->kfgy_scale;
1168 guint noise_level2 = alpha->noise_level2;
1173 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
1174 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
1176 width = GST_VIDEO_FRAME_WIDTH (in_frame);
1177 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
1179 bpp = GST_VIDEO_FRAME_COMP_PSTRIDE (in_frame, 0);
1181 o[0] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 0);
1182 o[1] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 1);
1183 o[2] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 2);
1185 smin = 128 - alpha->black_sensitivity;
1186 smax = 128 + alpha->white_sensitivity;
1189 alpha->out_sdtv ? cog_rgb_to_ycbcr_matrix_8bit_sdtv :
1190 cog_rgb_to_ycbcr_matrix_8bit_hdtv, 12 * sizeof (gint));
1192 for (i = 0; i < height; i++) {
1193 for (j = 0; j < width; j++) {
1199 y = APPLY_MATRIX (matrix, 0, r, g, b);
1200 u = APPLY_MATRIX (matrix, 1, r, g, b) - 128;
1201 v = APPLY_MATRIX (matrix, 2, r, g, b) - 128;
1203 a = chroma_keying_yuv (a, &y, &u, &v, cr, cb,
1204 smin, smax, accept_angle_tg, accept_angle_ctg,
1205 one_over_kc, kfgy_scale, kg, noise_level2);
1222 gst_alpha_set_rgb_argb (const GstVideoFrame * in_frame,
1223 GstVideoFrame * out_frame, GstAlpha * alpha)
1228 gint s_alpha = CLAMP ((gint) (alpha->alpha * 255), 0, 255);
1233 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
1234 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
1236 width = GST_VIDEO_FRAME_WIDTH (in_frame);
1237 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
1239 bpp = GST_VIDEO_FRAME_COMP_PSTRIDE (in_frame, 0);
1241 o[0] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 0);
1242 o[1] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 1);
1243 o[2] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 2);
1245 p[0] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 3);
1246 p[1] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 0);
1247 p[2] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 1);
1248 p[3] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 2);
1250 for (i = 0; i < height; i++) {
1251 for (j = 0; j < width; j++) {
1252 dest[p[0]] = s_alpha;
1254 dest[p[1]] = src[o[0]];
1255 dest[p[2]] = src[o[1]];
1256 dest[p[3]] = src[o[2]];
1265 gst_alpha_chroma_key_rgb_argb (const GstVideoFrame * in_frame,
1266 GstVideoFrame * out_frame, GstAlpha * alpha)
1275 gint pa = CLAMP ((gint) (alpha->alpha * 255), 0, 255);
1276 gint8 cb = alpha->cb, cr = alpha->cr;
1277 gint8 kg = alpha->kg;
1278 guint8 accept_angle_tg = alpha->accept_angle_tg;
1279 guint8 accept_angle_ctg = alpha->accept_angle_ctg;
1280 guint8 one_over_kc = alpha->one_over_kc;
1281 guint8 kfgy_scale = alpha->kfgy_scale;
1282 guint noise_level2 = alpha->noise_level2;
1283 gint matrix[12], matrix2[12];
1287 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
1288 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
1290 width = GST_VIDEO_FRAME_WIDTH (in_frame);
1291 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
1293 bpp = GST_VIDEO_FRAME_COMP_PSTRIDE (in_frame, 0);
1295 o[0] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 0);
1296 o[1] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 1);
1297 o[2] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 2);
1299 p[0] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 3);
1300 p[1] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 0);
1301 p[2] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 1);
1302 p[3] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 2);
1304 smin = 128 - alpha->black_sensitivity;
1305 smax = 128 + alpha->white_sensitivity;
1307 memcpy (matrix, cog_rgb_to_ycbcr_matrix_8bit_sdtv, 12 * sizeof (gint));
1308 memcpy (matrix2, cog_ycbcr_to_rgb_matrix_8bit_sdtv, 12 * sizeof (gint));
1310 for (i = 0; i < height; i++) {
1311 for (j = 0; j < width; j++) {
1317 y = APPLY_MATRIX (matrix, 0, r, g, b);
1318 u = APPLY_MATRIX (matrix, 1, r, g, b) - 128;
1319 v = APPLY_MATRIX (matrix, 2, r, g, b) - 128;
1321 a = chroma_keying_yuv (a, &y, &u, &v, cr, cb,
1322 smin, smax, accept_angle_tg, accept_angle_ctg,
1323 one_over_kc, kfgy_scale, kg, noise_level2);
1328 r = APPLY_MATRIX (matrix2, 0, y, u, v);
1329 g = APPLY_MATRIX (matrix2, 1, y, u, v);
1330 b = APPLY_MATRIX (matrix2, 2, y, u, v);
1333 dest[p[1]] = CLAMP (r, 0, 255);
1334 dest[p[2]] = CLAMP (g, 0, 255);
1335 dest[p[3]] = CLAMP (b, 0, 255);
1344 gst_alpha_set_planar_yuv_ayuv (const GstVideoFrame * in_frame,
1345 GstVideoFrame * out_frame, GstAlpha * alpha)
1350 gint b_alpha = CLAMP ((gint) (alpha->alpha * 255), 0, 255);
1351 const guint8 *srcY, *srcY_tmp;
1352 const guint8 *srcU, *srcU_tmp;
1353 const guint8 *srcV, *srcV_tmp;
1355 gint y_stride, uv_stride;
1356 gint v_subs, h_subs;
1358 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
1359 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
1361 width = GST_VIDEO_FRAME_WIDTH (in_frame);
1362 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
1364 y_stride = GST_VIDEO_FRAME_COMP_STRIDE (in_frame, 0);
1365 uv_stride = GST_VIDEO_FRAME_COMP_STRIDE (in_frame, 1);
1367 srcY_tmp = srcY = src;
1368 srcU_tmp = srcU = src + GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 1);
1369 srcV_tmp = srcV = src + GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 2);
1371 switch (GST_VIDEO_FRAME_FORMAT (in_frame)) {
1372 case GST_VIDEO_FORMAT_I420:
1373 case GST_VIDEO_FORMAT_YV12:
1374 v_subs = h_subs = 2;
1376 case GST_VIDEO_FORMAT_Y444:
1377 v_subs = h_subs = 1;
1379 case GST_VIDEO_FORMAT_Y42B:
1383 case GST_VIDEO_FORMAT_Y41B:
1388 g_assert_not_reached ();
1392 if (alpha->in_sdtv == alpha->out_sdtv) {
1393 for (i = 0; i < height; i++) {
1394 for (j = 0; j < width; j++) {
1402 if ((j + 1) % h_subs == 0) {
1408 srcY_tmp = srcY = srcY_tmp + y_stride;
1409 if ((i + 1) % v_subs == 0) {
1410 srcU_tmp = srcU = srcU_tmp + uv_stride;
1411 srcV_tmp = srcV = srcV_tmp + uv_stride;
1422 alpha->out_sdtv ? cog_ycbcr_hdtv_to_ycbcr_sdtv_matrix_8bit :
1423 cog_ycbcr_sdtv_to_ycbcr_hdtv_matrix_8bit, 12 * sizeof (gint));
1425 for (i = 0; i < height; i++) {
1426 for (j = 0; j < width; j++) {
1433 dest[1] = APPLY_MATRIX (matrix, 0, y, u, v);
1434 dest[2] = APPLY_MATRIX (matrix, 1, y, u, v);
1435 dest[3] = APPLY_MATRIX (matrix, 2, y, u, v);
1439 if ((j + 1) % h_subs == 0) {
1445 srcY_tmp = srcY = srcY_tmp + y_stride;
1446 if ((i + 1) % v_subs == 0) {
1447 srcU_tmp = srcU = srcU_tmp + uv_stride;
1448 srcV_tmp = srcV = srcV_tmp + uv_stride;
1458 gst_alpha_chroma_key_planar_yuv_ayuv (const GstVideoFrame * in_frame,
1459 GstVideoFrame * out_frame, GstAlpha * alpha)
1464 gint b_alpha = CLAMP ((gint) (alpha->alpha * 255), 0, 255);
1465 const guint8 *srcY, *srcY_tmp;
1466 const guint8 *srcU, *srcU_tmp;
1467 const guint8 *srcV, *srcV_tmp;
1470 gint y_stride, uv_stride;
1471 gint v_subs, h_subs;
1472 gint smin = 128 - alpha->black_sensitivity;
1473 gint smax = 128 + alpha->white_sensitivity;
1474 gint8 cb = alpha->cb, cr = alpha->cr;
1475 gint8 kg = alpha->kg;
1476 guint8 accept_angle_tg = alpha->accept_angle_tg;
1477 guint8 accept_angle_ctg = alpha->accept_angle_ctg;
1478 guint8 one_over_kc = alpha->one_over_kc;
1479 guint8 kfgy_scale = alpha->kfgy_scale;
1480 guint noise_level2 = alpha->noise_level2;
1482 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
1483 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
1485 width = GST_VIDEO_FRAME_WIDTH (in_frame);
1486 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
1488 y_stride = GST_VIDEO_FRAME_COMP_STRIDE (in_frame, 0);
1489 uv_stride = GST_VIDEO_FRAME_COMP_STRIDE (in_frame, 1);
1491 srcY_tmp = srcY = src;
1492 srcU_tmp = srcU = src + GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 1);
1493 srcV_tmp = srcV = src + GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 2);
1495 switch (GST_VIDEO_FRAME_FORMAT (in_frame)) {
1496 case GST_VIDEO_FORMAT_I420:
1497 case GST_VIDEO_FORMAT_YV12:
1498 v_subs = h_subs = 2;
1500 case GST_VIDEO_FORMAT_Y444:
1501 v_subs = h_subs = 1;
1503 case GST_VIDEO_FORMAT_Y42B:
1507 case GST_VIDEO_FORMAT_Y41B:
1512 g_assert_not_reached ();
1516 if (alpha->in_sdtv == alpha->out_sdtv) {
1517 for (i = 0; i < height; i++) {
1518 for (j = 0; j < width; j++) {
1524 a = chroma_keying_yuv (a, &y, &u, &v, cr, cb, smin,
1525 smax, accept_angle_tg, accept_angle_ctg,
1526 one_over_kc, kfgy_scale, kg, noise_level2);
1538 if ((j + 1) % h_subs == 0) {
1544 srcY_tmp = srcY = srcY_tmp + y_stride;
1545 if ((i + 1) % v_subs == 0) {
1546 srcU_tmp = srcU = srcU_tmp + uv_stride;
1547 srcV_tmp = srcV = srcV_tmp + uv_stride;
1557 alpha->out_sdtv ? cog_ycbcr_hdtv_to_ycbcr_sdtv_matrix_8bit :
1558 cog_ycbcr_sdtv_to_ycbcr_hdtv_matrix_8bit, 12 * sizeof (gint));
1560 for (i = 0; i < height; i++) {
1561 for (j = 0; j < width; j++) {
1563 y = APPLY_MATRIX (matrix, 0, srcY[0], srcU[0], srcV[0]);
1564 u = APPLY_MATRIX (matrix, 1, srcY[0], srcU[0], srcV[0]) - 128;
1565 v = APPLY_MATRIX (matrix, 2, srcY[0], srcU[0], srcV[0]) - 128;
1567 a = chroma_keying_yuv (a, &y, &u, &v, cr, cb, smin,
1568 smax, accept_angle_tg, accept_angle_ctg,
1569 one_over_kc, kfgy_scale, kg, noise_level2);
1578 if ((j + 1) % h_subs == 0) {
1584 srcY_tmp = srcY = srcY_tmp + y_stride;
1585 if ((i + 1) % v_subs == 0) {
1586 srcU_tmp = srcU = srcU_tmp + uv_stride;
1587 srcV_tmp = srcV = srcV_tmp + uv_stride;
1597 gst_alpha_set_planar_yuv_argb (const GstVideoFrame * in_frame,
1598 GstVideoFrame * out_frame, GstAlpha * alpha)
1603 gint b_alpha = CLAMP ((gint) (alpha->alpha * 255), 0, 255);
1604 const guint8 *srcY, *srcY_tmp;
1605 const guint8 *srcU, *srcU_tmp;
1606 const guint8 *srcV, *srcV_tmp;
1608 gint y_stride, uv_stride;
1609 gint v_subs, h_subs;
1615 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
1616 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
1618 width = GST_VIDEO_FRAME_WIDTH (in_frame);
1619 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
1621 p[0] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 3);
1622 p[1] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 0);
1623 p[2] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 1);
1624 p[3] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 2);
1626 y_stride = GST_VIDEO_FRAME_COMP_STRIDE (in_frame, 0);
1627 uv_stride = GST_VIDEO_FRAME_COMP_STRIDE (in_frame, 1);
1629 srcY_tmp = srcY = src;
1630 srcU_tmp = srcU = src + GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 1);
1631 srcV_tmp = srcV = src + GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 2);
1633 switch (GST_VIDEO_FRAME_FORMAT (in_frame)) {
1634 case GST_VIDEO_FORMAT_I420:
1635 case GST_VIDEO_FORMAT_YV12:
1636 v_subs = h_subs = 2;
1638 case GST_VIDEO_FORMAT_Y444:
1639 v_subs = h_subs = 1;
1641 case GST_VIDEO_FORMAT_Y42B:
1645 case GST_VIDEO_FORMAT_Y41B:
1650 g_assert_not_reached ();
1655 alpha->in_sdtv ? cog_ycbcr_to_rgb_matrix_8bit_sdtv :
1656 cog_ycbcr_to_rgb_matrix_8bit_hdtv, 12 * sizeof (gint));
1658 for (i = 0; i < height; i++) {
1659 for (j = 0; j < width; j++) {
1666 r = APPLY_MATRIX (matrix, 0, y, u, v);
1667 g = APPLY_MATRIX (matrix, 1, y, u, v);
1668 b = APPLY_MATRIX (matrix, 2, y, u, v);
1669 dest[p[1]] = CLAMP (r, 0, 255);
1670 dest[p[2]] = CLAMP (g, 0, 255);
1671 dest[p[3]] = CLAMP (b, 0, 255);
1675 if ((j + 1) % h_subs == 0) {
1681 srcY_tmp = srcY = srcY_tmp + y_stride;
1682 if ((i + 1) % v_subs == 0) {
1683 srcU_tmp = srcU = srcU_tmp + uv_stride;
1684 srcV_tmp = srcV = srcV_tmp + uv_stride;
1693 gst_alpha_chroma_key_planar_yuv_argb (const GstVideoFrame * in_frame,
1694 GstVideoFrame * out_frame, GstAlpha * alpha)
1699 gint b_alpha = CLAMP ((gint) (alpha->alpha * 255), 0, 255);
1700 const guint8 *srcY, *srcY_tmp;
1701 const guint8 *srcU, *srcU_tmp;
1702 const guint8 *srcV, *srcV_tmp;
1706 gint y_stride, uv_stride;
1707 gint v_subs, h_subs;
1708 gint smin = 128 - alpha->black_sensitivity;
1709 gint smax = 128 + alpha->white_sensitivity;
1710 gint8 cb = alpha->cb, cr = alpha->cr;
1711 gint8 kg = alpha->kg;
1712 guint8 accept_angle_tg = alpha->accept_angle_tg;
1713 guint8 accept_angle_ctg = alpha->accept_angle_ctg;
1714 guint8 one_over_kc = alpha->one_over_kc;
1715 guint8 kfgy_scale = alpha->kfgy_scale;
1716 guint noise_level2 = alpha->noise_level2;
1720 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
1721 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
1723 width = GST_VIDEO_FRAME_WIDTH (in_frame);
1724 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
1726 p[0] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 3);
1727 p[1] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 0);
1728 p[2] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 1);
1729 p[3] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 2);
1731 y_stride = GST_VIDEO_FRAME_COMP_STRIDE (in_frame, 0);
1732 uv_stride = GST_VIDEO_FRAME_COMP_STRIDE (in_frame, 1);
1734 srcY_tmp = srcY = src;
1735 srcU_tmp = srcU = src + GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 1);
1736 srcV_tmp = srcV = src + GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 2);
1738 switch (GST_VIDEO_FRAME_FORMAT (in_frame)) {
1739 case GST_VIDEO_FORMAT_I420:
1740 case GST_VIDEO_FORMAT_YV12:
1741 v_subs = h_subs = 2;
1743 case GST_VIDEO_FORMAT_Y444:
1744 v_subs = h_subs = 1;
1746 case GST_VIDEO_FORMAT_Y42B:
1750 case GST_VIDEO_FORMAT_Y41B:
1755 g_assert_not_reached ();
1760 alpha->in_sdtv ? cog_ycbcr_to_rgb_matrix_8bit_sdtv :
1761 cog_ycbcr_to_rgb_matrix_8bit_hdtv, 12 * sizeof (gint));
1763 for (i = 0; i < height; i++) {
1764 for (j = 0; j < width; j++) {
1770 a = chroma_keying_yuv (a, &y, &u, &v, cr, cb, smin,
1771 smax, accept_angle_tg, accept_angle_ctg,
1772 one_over_kc, kfgy_scale, kg, noise_level2);
1778 r = APPLY_MATRIX (matrix, 0, y, u, v);
1779 g = APPLY_MATRIX (matrix, 1, y, u, v);
1780 b = APPLY_MATRIX (matrix, 2, y, u, v);
1781 dest[p[1]] = CLAMP (r, 0, 255);
1782 dest[p[2]] = CLAMP (g, 0, 255);
1783 dest[p[3]] = CLAMP (b, 0, 255);
1787 if ((j + 1) % h_subs == 0) {
1793 srcY_tmp = srcY = srcY_tmp + y_stride;
1794 if ((i + 1) % v_subs == 0) {
1795 srcU_tmp = srcU = srcU_tmp + uv_stride;
1796 srcV_tmp = srcV = srcV_tmp + uv_stride;
1805 gst_alpha_set_packed_422_ayuv (const GstVideoFrame * in_frame,
1806 GstVideoFrame * out_frame, GstAlpha * alpha)
1811 gint s_alpha = CLAMP ((gint) (alpha->alpha * 255), 0, 255);
1814 gint p[4]; /* Y U Y V */
1816 const guint8 *src_tmp;
1818 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
1819 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
1821 width = GST_VIDEO_FRAME_WIDTH (in_frame);
1822 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
1824 src_stride = GST_VIDEO_FRAME_COMP_STRIDE (in_frame, 0);
1826 p[0] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 0);
1828 p[1] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 1);
1829 p[3] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 2);
1831 if (alpha->in_sdtv != alpha->out_sdtv) {
1835 alpha->in_sdtv ? cog_ycbcr_sdtv_to_ycbcr_hdtv_matrix_8bit :
1836 cog_ycbcr_hdtv_to_ycbcr_sdtv_matrix_8bit, 12 * sizeof (gint));
1838 for (i = 0; i < height; i++) {
1841 for (j = 0; j < width - 1; j += 2) {
1845 y = APPLY_MATRIX (matrix, 0, src[p[0]], src[p[1]], src[p[3]]);
1846 u = APPLY_MATRIX (matrix, 1, src[p[0]], src[p[1]], src[p[3]]);
1847 v = APPLY_MATRIX (matrix, 2, src[p[0]], src[p[1]], src[p[3]]);
1853 y = APPLY_MATRIX (matrix, 0, src[p[2]], src[p[1]], src[p[3]]);
1854 u = APPLY_MATRIX (matrix, 1, src[p[2]], src[p[1]], src[p[3]]);
1855 v = APPLY_MATRIX (matrix, 2, src[p[2]], src[p[1]], src[p[3]]);
1865 if (j == width - 1) {
1868 y = APPLY_MATRIX (matrix, 0, src[p[0]], src[p[1]], src[p[3]]);
1869 u = APPLY_MATRIX (matrix, 1, src[p[0]], src[p[1]], src[p[3]]);
1870 v = APPLY_MATRIX (matrix, 2, src[p[0]], src[p[1]], src[p[3]]);
1879 src = src_tmp + src_stride;
1882 for (i = 0; i < height; i++) {
1885 for (j = 0; j < width - 1; j += 2) {
1907 if (j == width - 1) {
1921 src = src_tmp + src_stride;
1927 gst_alpha_chroma_key_packed_422_ayuv (const GstVideoFrame * in_frame,
1928 GstVideoFrame * out_frame, GstAlpha * alpha)
1936 gint pa = CLAMP ((gint) (alpha->alpha * 255), 0, 255);
1937 gint8 cb = alpha->cb, cr = alpha->cr;
1938 gint8 kg = alpha->kg;
1939 guint8 accept_angle_tg = alpha->accept_angle_tg;
1940 guint8 accept_angle_ctg = alpha->accept_angle_ctg;
1941 guint8 one_over_kc = alpha->one_over_kc;
1942 guint8 kfgy_scale = alpha->kfgy_scale;
1943 guint noise_level2 = alpha->noise_level2;
1944 gint p[4]; /* Y U Y V */
1946 const guint8 *src_tmp;
1948 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
1949 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
1951 width = GST_VIDEO_FRAME_WIDTH (in_frame);
1952 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
1954 src_stride = GST_VIDEO_FRAME_COMP_STRIDE (in_frame, 0);
1956 p[0] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 0);
1958 p[1] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 1);
1959 p[3] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 2);
1961 smin = 128 - alpha->black_sensitivity;
1962 smax = 128 + alpha->white_sensitivity;
1964 if (alpha->in_sdtv != alpha->out_sdtv) {
1968 alpha->in_sdtv ? cog_ycbcr_sdtv_to_ycbcr_hdtv_matrix_8bit :
1969 cog_ycbcr_hdtv_to_ycbcr_sdtv_matrix_8bit, 12 * sizeof (gint));
1971 for (i = 0; i < height; i++) {
1974 for (j = 0; j < width - 1; j += 2) {
1975 y = APPLY_MATRIX (matrix, 0, src[p[0]], src[p[1]], src[p[3]]);
1976 u = APPLY_MATRIX (matrix, 1, src[p[0]], src[p[1]], src[p[3]]) - 128;
1977 v = APPLY_MATRIX (matrix, 2, src[p[0]], src[p[1]], src[p[3]]) - 128;
1979 a = chroma_keying_yuv (pa, &y, &u, &v, cr, cb,
1980 smin, smax, accept_angle_tg, accept_angle_ctg,
1981 one_over_kc, kfgy_scale, kg, noise_level2);
1988 y = APPLY_MATRIX (matrix, 0, src[p[2]], src[p[1]], src[p[3]]);
1989 u = APPLY_MATRIX (matrix, 1, src[p[2]], src[p[1]], src[p[3]]) - 128;
1990 v = APPLY_MATRIX (matrix, 2, src[p[2]], src[p[1]], src[p[3]]) - 128;
1992 a = chroma_keying_yuv (pa, &y, &u, &v, cr, cb,
1993 smin, smax, accept_angle_tg, accept_angle_ctg,
1994 one_over_kc, kfgy_scale, kg, noise_level2);
2005 if (j == width - 1) {
2006 y = APPLY_MATRIX (matrix, 0, src[p[0]], src[p[1]], src[p[3]]);
2007 u = APPLY_MATRIX (matrix, 1, src[p[0]], src[p[1]], src[p[3]]) - 128;
2008 v = APPLY_MATRIX (matrix, 2, src[p[0]], src[p[1]], src[p[3]]) - 128;
2010 a = chroma_keying_yuv (pa, &y, &u, &v, cr, cb,
2011 smin, smax, accept_angle_tg, accept_angle_ctg,
2012 one_over_kc, kfgy_scale, kg, noise_level2);
2022 src = src_tmp + src_stride;
2025 for (i = 0; i < height; i++) {
2028 for (j = 0; j < width - 1; j += 2) {
2030 u = src[p[1]] - 128;
2031 v = src[p[3]] - 128;
2033 a = chroma_keying_yuv (pa, &y, &u, &v, cr, cb,
2034 smin, smax, accept_angle_tg, accept_angle_ctg,
2035 one_over_kc, kfgy_scale, kg, noise_level2);
2043 u = src[p[1]] - 128;
2044 v = src[p[3]] - 128;
2046 a = chroma_keying_yuv (pa, &y, &u, &v, cr, cb,
2047 smin, smax, accept_angle_tg, accept_angle_ctg,
2048 one_over_kc, kfgy_scale, kg, noise_level2);
2059 if (j == width - 1) {
2061 u = src[p[1]] - 128;
2062 v = src[p[3]] - 128;
2064 a = chroma_keying_yuv (pa, &y, &u, &v, cr, cb,
2065 smin, smax, accept_angle_tg, accept_angle_ctg,
2066 one_over_kc, kfgy_scale, kg, noise_level2);
2076 src = src_tmp + src_stride;
2082 gst_alpha_set_packed_422_argb (const GstVideoFrame * in_frame,
2083 GstVideoFrame * out_frame, GstAlpha * alpha)
2088 gint s_alpha = CLAMP ((gint) (alpha->alpha * 255), 0, 255);
2092 const guint8 *src_tmp;
2096 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
2097 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
2099 width = GST_VIDEO_FRAME_WIDTH (in_frame);
2100 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
2102 src_stride = GST_VIDEO_FRAME_COMP_STRIDE (in_frame, 0);
2104 o[0] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 0);
2106 o[1] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 1);
2107 o[3] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 2);
2109 p[0] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 3);
2110 p[1] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 0);
2111 p[2] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 1);
2112 p[3] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 2);
2115 alpha->in_sdtv ? cog_ycbcr_to_rgb_matrix_8bit_sdtv :
2116 cog_ycbcr_to_rgb_matrix_8bit_hdtv, 12 * sizeof (gint));
2118 for (i = 0; i < height; i++) {
2121 for (j = 0; j < width - 1; j += 2) {
2122 r = APPLY_MATRIX (matrix, 0, src[o[0]], src[o[1]], src[o[3]]);
2123 g = APPLY_MATRIX (matrix, 1, src[o[0]], src[o[1]], src[o[3]]);
2124 b = APPLY_MATRIX (matrix, 2, src[o[0]], src[o[1]], src[o[3]]);
2126 dest[p[0]] = s_alpha;
2127 dest[p[1]] = CLAMP (r, 0, 255);
2128 dest[p[2]] = CLAMP (g, 0, 255);
2129 dest[p[3]] = CLAMP (b, 0, 255);
2131 r = APPLY_MATRIX (matrix, 0, src[o[2]], src[o[1]], src[o[3]]);
2132 g = APPLY_MATRIX (matrix, 1, src[o[2]], src[o[1]], src[o[3]]);
2133 b = APPLY_MATRIX (matrix, 2, src[o[2]], src[o[1]], src[o[3]]);
2135 dest[4 + p[0]] = s_alpha;
2136 dest[4 + p[1]] = CLAMP (r, 0, 255);
2137 dest[4 + p[2]] = CLAMP (g, 0, 255);
2138 dest[4 + p[3]] = CLAMP (b, 0, 255);
2144 if (j == width - 1) {
2145 r = APPLY_MATRIX (matrix, 0, src[o[0]], src[o[1]], src[o[3]]);
2146 g = APPLY_MATRIX (matrix, 1, src[o[0]], src[o[1]], src[o[3]]);
2147 b = APPLY_MATRIX (matrix, 2, src[o[0]], src[o[1]], src[o[3]]);
2149 dest[p[0]] = s_alpha;
2150 dest[p[1]] = CLAMP (r, 0, 255);
2151 dest[p[2]] = CLAMP (g, 0, 255);
2152 dest[p[3]] = CLAMP (b, 0, 255);
2157 src = src_tmp + src_stride;
2162 gst_alpha_chroma_key_packed_422_argb (const GstVideoFrame * in_frame,
2163 GstVideoFrame * out_frame, GstAlpha * alpha)
2172 gint pa = CLAMP ((gint) (alpha->alpha * 255), 0, 255);
2173 gint8 cb = alpha->cb, cr = alpha->cr;
2174 gint8 kg = alpha->kg;
2175 guint8 accept_angle_tg = alpha->accept_angle_tg;
2176 guint8 accept_angle_ctg = alpha->accept_angle_ctg;
2177 guint8 one_over_kc = alpha->one_over_kc;
2178 guint8 kfgy_scale = alpha->kfgy_scale;
2179 guint noise_level2 = alpha->noise_level2;
2182 const guint8 *src_tmp;
2185 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
2186 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
2188 width = GST_VIDEO_FRAME_WIDTH (in_frame);
2189 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
2191 src_stride = GST_VIDEO_FRAME_COMP_STRIDE (in_frame, 0);
2193 o[0] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 0);
2195 o[1] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 1);
2196 o[3] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 2);
2198 p[0] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 3);
2199 p[1] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 0);
2200 p[2] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 1);
2201 p[3] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 2);
2204 alpha->in_sdtv ? cog_ycbcr_to_rgb_matrix_8bit_sdtv :
2205 cog_ycbcr_to_rgb_matrix_8bit_hdtv, 12 * sizeof (gint));
2207 smin = 128 - alpha->black_sensitivity;
2208 smax = 128 + alpha->white_sensitivity;
2210 for (i = 0; i < height; i++) {
2213 for (j = 0; j < width - 1; j += 2) {
2215 u = src[o[1]] - 128;
2216 v = src[o[3]] - 128;
2218 a = chroma_keying_yuv (pa, &y, &u, &v, cr, cb,
2219 smin, smax, accept_angle_tg, accept_angle_ctg,
2220 one_over_kc, kfgy_scale, kg, noise_level2);
2224 r = APPLY_MATRIX (matrix, 0, y, u, v);
2225 g = APPLY_MATRIX (matrix, 1, y, u, v);
2226 b = APPLY_MATRIX (matrix, 2, y, u, v);
2229 dest[p[1]] = CLAMP (r, 0, 255);
2230 dest[p[2]] = CLAMP (g, 0, 255);
2231 dest[p[3]] = CLAMP (b, 0, 255);
2234 u = src[o[1]] - 128;
2235 v = src[o[3]] - 128;
2237 a = chroma_keying_yuv (pa, &y, &u, &v, cr, cb,
2238 smin, smax, accept_angle_tg, accept_angle_ctg,
2239 one_over_kc, kfgy_scale, kg, noise_level2);
2243 r = APPLY_MATRIX (matrix, 0, y, u, v);
2244 g = APPLY_MATRIX (matrix, 1, y, u, v);
2245 b = APPLY_MATRIX (matrix, 2, y, u, v);
2248 dest[4 + p[1]] = CLAMP (r, 0, 255);
2249 dest[4 + p[2]] = CLAMP (g, 0, 255);
2250 dest[4 + p[3]] = CLAMP (b, 0, 255);
2256 if (j == width - 1) {
2258 u = src[o[1]] - 128;
2259 v = src[o[3]] - 128;
2261 a = chroma_keying_yuv (pa, &y, &u, &v, cr, cb,
2262 smin, smax, accept_angle_tg, accept_angle_ctg,
2263 one_over_kc, kfgy_scale, kg, noise_level2);
2267 r = APPLY_MATRIX (matrix, 0, y, u, v);
2268 g = APPLY_MATRIX (matrix, 1, y, u, v);
2269 b = APPLY_MATRIX (matrix, 2, y, u, v);
2272 dest[p[1]] = CLAMP (r, 0, 255);
2273 dest[p[2]] = CLAMP (g, 0, 255);
2274 dest[p[3]] = CLAMP (b, 0, 255);
2279 src = src_tmp + src_stride;
2283 /* Protected with the alpha lock */
2285 gst_alpha_init_params_full (GstAlpha * alpha,
2286 const GstVideoFormatInfo * in_info, const GstVideoFormatInfo * out_info)
2292 guint target_r = alpha->target_r;
2293 guint target_g = alpha->target_g;
2294 guint target_b = alpha->target_b;
2297 switch (alpha->method) {
2298 case ALPHA_METHOD_GREEN:
2303 case ALPHA_METHOD_BLUE:
2312 /* RGB->RGB: convert to SDTV YUV, chroma keying, convert back
2313 * YUV->RGB: chroma keying, convert to RGB
2314 * RGB->YUV: convert to YUV, chroma keying
2315 * YUV->YUV: convert matrix, chroma keying
2317 if (GST_VIDEO_FORMAT_INFO_IS_RGB (in_info)
2318 && GST_VIDEO_FORMAT_INFO_IS_RGB (out_info))
2319 matrix = cog_rgb_to_ycbcr_matrix_8bit_sdtv;
2320 else if (GST_VIDEO_FORMAT_INFO_IS_YUV (in_info)
2321 && GST_VIDEO_FORMAT_INFO_IS_RGB (out_info))
2323 (alpha->in_sdtv) ? cog_rgb_to_ycbcr_matrix_8bit_sdtv :
2324 cog_rgb_to_ycbcr_matrix_8bit_hdtv;
2325 else if (GST_VIDEO_FORMAT_INFO_IS_RGB (in_info)
2326 && GST_VIDEO_FORMAT_INFO_IS_YUV (out_info))
2328 (alpha->out_sdtv) ? cog_rgb_to_ycbcr_matrix_8bit_sdtv :
2329 cog_rgb_to_ycbcr_matrix_8bit_hdtv;
2330 else /* yuv -> yuv */
2332 (alpha->out_sdtv) ? cog_rgb_to_ycbcr_matrix_8bit_sdtv :
2333 cog_rgb_to_ycbcr_matrix_8bit_hdtv;
2335 y = (matrix[0] * ((gint) target_r) +
2336 matrix[1] * ((gint) target_g) +
2337 matrix[2] * ((gint) target_b) + matrix[3]) >> 8;
2338 /* Cb,Cr without offset here because the chroma keying
2339 * works with them being in range [-128,127]
2342 (matrix[4] * ((gint) target_r) +
2343 matrix[5] * ((gint) target_g) + matrix[6] * ((gint) target_b)) >> 8;
2345 (matrix[8] * ((gint) target_r) +
2346 matrix[9] * ((gint) target_g) + matrix[10] * ((gint) target_b)) >> 8;
2348 kgl = sqrt (tmp1 * tmp1 + tmp2 * tmp2);
2349 alpha->cb = 127 * (tmp1 / kgl);
2350 alpha->cr = 127 * (tmp2 / kgl);
2352 tmp = 15 * tan (M_PI * alpha->angle / 180);
2353 tmp = MIN (tmp, 255);
2354 alpha->accept_angle_tg = tmp;
2355 tmp = 15 / tan (M_PI * alpha->angle / 180);
2356 tmp = MIN (tmp, 255);
2357 alpha->accept_angle_ctg = tmp;
2359 alpha->one_over_kc = 255 * 2 * tmp - 255;
2361 tmp = MIN (tmp, 255);
2362 alpha->kfgy_scale = tmp;
2363 alpha->kg = MIN (kgl, 127);
2365 alpha->noise_level2 = alpha->noise_level * alpha->noise_level;
2369 gst_alpha_init_params (GstAlpha * alpha)
2371 const GstVideoFormatInfo *finfo_in, *finfo_out;
2373 finfo_in = GST_VIDEO_FILTER (alpha)->in_info.finfo;
2374 finfo_out = GST_VIDEO_FILTER (alpha)->out_info.finfo;
2376 if (finfo_in != NULL && finfo_out != NULL) {
2377 gst_alpha_init_params_full (alpha, finfo_in, finfo_out);
2379 GST_DEBUG_OBJECT (alpha, "video formats not set yet");
2383 /* Protected with the alpha lock */
2385 gst_alpha_set_process_function_full (GstAlpha * alpha, GstVideoInfo * in_info,
2386 GstVideoInfo * out_info)
2388 alpha->process = NULL;
2390 switch (alpha->method) {
2391 case ALPHA_METHOD_SET:
2392 switch (GST_VIDEO_INFO_FORMAT (out_info)) {
2393 case GST_VIDEO_FORMAT_AYUV:
2394 switch (GST_VIDEO_INFO_FORMAT (in_info)) {
2395 case GST_VIDEO_FORMAT_AYUV:
2396 alpha->process = gst_alpha_set_ayuv_ayuv;
2398 case GST_VIDEO_FORMAT_Y444:
2399 case GST_VIDEO_FORMAT_Y42B:
2400 case GST_VIDEO_FORMAT_I420:
2401 case GST_VIDEO_FORMAT_YV12:
2402 case GST_VIDEO_FORMAT_Y41B:
2403 alpha->process = gst_alpha_set_planar_yuv_ayuv;
2405 case GST_VIDEO_FORMAT_YUY2:
2406 case GST_VIDEO_FORMAT_YVYU:
2407 case GST_VIDEO_FORMAT_UYVY:
2408 alpha->process = gst_alpha_set_packed_422_ayuv;
2410 case GST_VIDEO_FORMAT_ARGB:
2411 case GST_VIDEO_FORMAT_ABGR:
2412 case GST_VIDEO_FORMAT_RGBA:
2413 case GST_VIDEO_FORMAT_BGRA:
2414 alpha->process = gst_alpha_set_argb_ayuv;
2416 case GST_VIDEO_FORMAT_xRGB:
2417 case GST_VIDEO_FORMAT_xBGR:
2418 case GST_VIDEO_FORMAT_RGBx:
2419 case GST_VIDEO_FORMAT_BGRx:
2420 case GST_VIDEO_FORMAT_RGB:
2421 case GST_VIDEO_FORMAT_BGR:
2422 alpha->process = gst_alpha_set_rgb_ayuv;
2428 case GST_VIDEO_FORMAT_ARGB:
2429 case GST_VIDEO_FORMAT_ABGR:
2430 case GST_VIDEO_FORMAT_RGBA:
2431 case GST_VIDEO_FORMAT_BGRA:
2432 switch (GST_VIDEO_INFO_FORMAT (in_info)) {
2433 case GST_VIDEO_FORMAT_AYUV:
2434 alpha->process = gst_alpha_set_ayuv_argb;
2436 case GST_VIDEO_FORMAT_Y444:
2437 case GST_VIDEO_FORMAT_Y42B:
2438 case GST_VIDEO_FORMAT_I420:
2439 case GST_VIDEO_FORMAT_YV12:
2440 case GST_VIDEO_FORMAT_Y41B:
2441 alpha->process = gst_alpha_set_planar_yuv_argb;
2443 case GST_VIDEO_FORMAT_YUY2:
2444 case GST_VIDEO_FORMAT_YVYU:
2445 case GST_VIDEO_FORMAT_UYVY:
2446 alpha->process = gst_alpha_set_packed_422_argb;
2448 case GST_VIDEO_FORMAT_ARGB:
2449 case GST_VIDEO_FORMAT_ABGR:
2450 case GST_VIDEO_FORMAT_RGBA:
2451 case GST_VIDEO_FORMAT_BGRA:
2452 alpha->process = gst_alpha_set_argb_argb;
2454 case GST_VIDEO_FORMAT_xRGB:
2455 case GST_VIDEO_FORMAT_xBGR:
2456 case GST_VIDEO_FORMAT_RGBx:
2457 case GST_VIDEO_FORMAT_BGRx:
2458 case GST_VIDEO_FORMAT_RGB:
2459 case GST_VIDEO_FORMAT_BGR:
2460 alpha->process = gst_alpha_set_rgb_argb;
2471 case ALPHA_METHOD_GREEN:
2472 case ALPHA_METHOD_BLUE:
2473 case ALPHA_METHOD_CUSTOM:
2474 switch (GST_VIDEO_INFO_FORMAT (out_info)) {
2475 case GST_VIDEO_FORMAT_AYUV:
2476 switch (GST_VIDEO_INFO_FORMAT (in_info)) {
2477 case GST_VIDEO_FORMAT_AYUV:
2478 alpha->process = gst_alpha_chroma_key_ayuv_ayuv;
2480 case GST_VIDEO_FORMAT_Y444:
2481 case GST_VIDEO_FORMAT_Y42B:
2482 case GST_VIDEO_FORMAT_I420:
2483 case GST_VIDEO_FORMAT_YV12:
2484 case GST_VIDEO_FORMAT_Y41B:
2485 alpha->process = gst_alpha_chroma_key_planar_yuv_ayuv;
2487 case GST_VIDEO_FORMAT_YUY2:
2488 case GST_VIDEO_FORMAT_YVYU:
2489 case GST_VIDEO_FORMAT_UYVY:
2490 alpha->process = gst_alpha_chroma_key_packed_422_ayuv;
2492 case GST_VIDEO_FORMAT_ARGB:
2493 case GST_VIDEO_FORMAT_ABGR:
2494 case GST_VIDEO_FORMAT_RGBA:
2495 case GST_VIDEO_FORMAT_BGRA:
2496 alpha->process = gst_alpha_chroma_key_argb_ayuv;
2498 case GST_VIDEO_FORMAT_xRGB:
2499 case GST_VIDEO_FORMAT_xBGR:
2500 case GST_VIDEO_FORMAT_RGBx:
2501 case GST_VIDEO_FORMAT_BGRx:
2502 case GST_VIDEO_FORMAT_RGB:
2503 case GST_VIDEO_FORMAT_BGR:
2504 alpha->process = gst_alpha_chroma_key_rgb_ayuv;
2510 case GST_VIDEO_FORMAT_ARGB:
2511 case GST_VIDEO_FORMAT_ABGR:
2512 case GST_VIDEO_FORMAT_RGBA:
2513 case GST_VIDEO_FORMAT_BGRA:
2514 switch (GST_VIDEO_INFO_FORMAT (in_info)) {
2515 case GST_VIDEO_FORMAT_AYUV:
2516 alpha->process = gst_alpha_chroma_key_ayuv_argb;
2518 case GST_VIDEO_FORMAT_Y444:
2519 case GST_VIDEO_FORMAT_Y42B:
2520 case GST_VIDEO_FORMAT_I420:
2521 case GST_VIDEO_FORMAT_YV12:
2522 case GST_VIDEO_FORMAT_Y41B:
2523 alpha->process = gst_alpha_chroma_key_planar_yuv_argb;
2525 case GST_VIDEO_FORMAT_YUY2:
2526 case GST_VIDEO_FORMAT_YVYU:
2527 case GST_VIDEO_FORMAT_UYVY:
2528 alpha->process = gst_alpha_chroma_key_packed_422_argb;
2530 case GST_VIDEO_FORMAT_ARGB:
2531 case GST_VIDEO_FORMAT_ABGR:
2532 case GST_VIDEO_FORMAT_RGBA:
2533 case GST_VIDEO_FORMAT_BGRA:
2534 alpha->process = gst_alpha_chroma_key_argb_argb;
2536 case GST_VIDEO_FORMAT_xRGB:
2537 case GST_VIDEO_FORMAT_xBGR:
2538 case GST_VIDEO_FORMAT_RGBx:
2539 case GST_VIDEO_FORMAT_BGRx:
2540 case GST_VIDEO_FORMAT_RGB:
2541 case GST_VIDEO_FORMAT_BGR:
2542 alpha->process = gst_alpha_chroma_key_rgb_argb;
2556 return alpha->process != NULL;
2560 gst_alpha_set_process_function (GstAlpha * alpha)
2562 GstVideoInfo *info_in, *info_out;
2564 info_in = &GST_VIDEO_FILTER (alpha)->in_info;
2565 info_out = &GST_VIDEO_FILTER (alpha)->out_info;
2567 if (info_in->finfo != NULL && info_out->finfo != NULL) {
2568 gst_alpha_set_process_function_full (alpha, info_in, info_out);
2570 GST_DEBUG_OBJECT (alpha, "video formats not set yet");
2575 gst_alpha_before_transform (GstBaseTransform * btrans, GstBuffer * buf)
2577 GstAlpha *alpha = GST_ALPHA (btrans);
2578 GstClockTime timestamp;
2580 timestamp = gst_segment_to_stream_time (&btrans->segment, GST_FORMAT_TIME,
2581 GST_BUFFER_TIMESTAMP (buf));
2582 GST_LOG ("Got stream time of %" GST_TIME_FORMAT, GST_TIME_ARGS (timestamp));
2583 if (GST_CLOCK_TIME_IS_VALID (timestamp))
2584 gst_object_sync_values (GST_OBJECT (alpha), timestamp);
2587 static GstFlowReturn
2588 gst_alpha_transform_frame (GstVideoFilter * filter, GstVideoFrame * in_frame,
2589 GstVideoFrame * out_frame)
2591 GstAlpha *alpha = GST_ALPHA (filter);
2593 GST_ALPHA_LOCK (alpha);
2595 if (G_UNLIKELY (!alpha->process))
2596 goto not_negotiated;
2598 alpha->process (in_frame, out_frame, alpha);
2600 GST_ALPHA_UNLOCK (alpha);
2607 GST_ERROR_OBJECT (alpha, "Not negotiated yet");
2608 GST_ALPHA_UNLOCK (alpha);
2609 return GST_FLOW_NOT_NEGOTIATED;
2614 plugin_init (GstPlugin * plugin)
2616 return gst_element_register (plugin, "alpha", GST_RANK_NONE, GST_TYPE_ALPHA);
2619 GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
2622 "adds an alpha channel to video - constant or via chroma-keying",
2623 plugin_init, VERSION, GST_LICENSE, GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN)