2 * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
3 * Copyright (C) <2007> Wim Taymans <wim.taymans@collabora.co.uk>
4 * Copyright (C) <2007> Edward Hervey <edward.hervey@collabora.co.uk>
5 * Copyright (C) <2007> Jan Schmidt <thaytan@noraisin.net>
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Library General Public License for more details.
17 * You should have received a copy of the GNU Library General Public
18 * License along with this library; if not, write to the
19 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 * Boston, MA 02111-1307, USA.
24 * SECTION:element-alpha
26 * The alpha element adds an alpha channel to a video stream. The values
27 * of the alpha channel can be either be set to a constant or can be
28 * dynamically calculated via chroma keying, e.g. blue can be set as
29 * the transparent color.
33 * gst-launch videotestsrc pattern=smpte75 ! alpha method=green ! \
34 * videomixer name=mixer ! videoconvert ! autovideosink \
35 * videotestsrc pattern=snow ! mixer.
36 * ]| This pipeline adds a alpha channel to the SMPTE color bars
37 * with green as the transparent color and mixes the output with
38 * a snow video stream.
53 #define M_PI 3.14159265358979323846
56 /* Generated by -bad/ext/cog/generate_tables */
57 static const int cog_ycbcr_to_rgb_matrix_8bit_hdtv[] = {
59 298, -55, -136, 19681,
63 static const int cog_ycbcr_to_rgb_matrix_8bit_sdtv[] = {
65 298, -100, -208, 34707,
69 static const gint cog_rgb_to_ycbcr_matrix_8bit_hdtv[] = {
72 112, -102, -10, 32768,
75 static const gint cog_rgb_to_ycbcr_matrix_8bit_sdtv[] = {
81 static const gint cog_ycbcr_sdtv_to_ycbcr_hdtv_matrix_8bit[] = {
87 static const gint cog_ycbcr_hdtv_to_ycbcr_sdtv_matrix_8bit[] = {
93 /* Alpha signals and args */
100 #define DEFAULT_METHOD ALPHA_METHOD_SET
101 #define DEFAULT_ALPHA 1.0
102 #define DEFAULT_TARGET_R 0
103 #define DEFAULT_TARGET_G 255
104 #define DEFAULT_TARGET_B 0
105 #define DEFAULT_ANGLE 20.0
106 #define DEFAULT_NOISE_LEVEL 2.0
107 #define DEFAULT_BLACK_SENSITIVITY 100
108 #define DEFAULT_WHITE_SENSITIVITY 100
109 #define DEFAULT_PREFER_PASSTHROUGH FALSE
121 PROP_BLACK_SENSITIVITY,
122 PROP_WHITE_SENSITIVITY,
123 PROP_PREFER_PASSTHROUGH,
127 static GstStaticPadTemplate gst_alpha_src_template =
128 GST_STATIC_PAD_TEMPLATE ("src",
131 GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE ("{ AYUV, "
132 "ARGB, BGRA, ABGR, RGBA, Y444, xRGB, BGRx, xBGR, "
133 "RGBx, RGB, BGR Y42B, YUY2, YVYU, UYVY, I420, YV12, " "Y41B } "))
136 static GstStaticPadTemplate gst_alpha_sink_template =
137 GST_STATIC_PAD_TEMPLATE ("sink",
140 GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE ("{ AYUV, "
141 "ARGB, BGRA, ABGR, RGBA, Y444, xRGB, BGRx, xBGR, "
142 "RGBx, RGB, BGR Y42B, YUY2, YVYU, UYVY, I420, YV12, " "Y41B } "))
145 static GstStaticCaps gst_alpha_alpha_caps =
146 GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE ("{ AYUV, ARGB, BGRA, ABGR, RGBA }"));
148 #define GST_ALPHA_LOCK(alpha) G_STMT_START { \
149 GST_LOG_OBJECT (alpha, "Locking alpha from thread %p", g_thread_self ()); \
150 g_static_mutex_lock (&alpha->lock); \
151 GST_LOG_OBJECT (alpha, "Locked alpha from thread %p", g_thread_self ()); \
154 #define GST_ALPHA_UNLOCK(alpha) G_STMT_START { \
155 GST_LOG_OBJECT (alpha, "Unlocking alpha from thread %p", g_thread_self ()); \
156 g_static_mutex_unlock (&alpha->lock); \
159 static gboolean gst_alpha_start (GstBaseTransform * trans);
160 static gboolean gst_alpha_get_unit_size (GstBaseTransform * btrans,
161 GstCaps * caps, gsize * size);
162 static GstCaps *gst_alpha_transform_caps (GstBaseTransform * btrans,
163 GstPadDirection direction, GstCaps * caps, GstCaps * filter);
164 static gboolean gst_alpha_set_caps (GstBaseTransform * btrans,
165 GstCaps * incaps, GstCaps * outcaps);
166 static GstFlowReturn gst_alpha_transform (GstBaseTransform * btrans,
167 GstBuffer * in, GstBuffer * out);
168 static void gst_alpha_before_transform (GstBaseTransform * btrans,
171 static void gst_alpha_init_params (GstAlpha * alpha);
172 static gboolean gst_alpha_set_process_function (GstAlpha * alpha);
174 static void gst_alpha_set_property (GObject * object, guint prop_id,
175 const GValue * value, GParamSpec * pspec);
176 static void gst_alpha_get_property (GObject * object, guint prop_id,
177 GValue * value, GParamSpec * pspec);
178 static void gst_alpha_finalize (GObject * object);
180 #define gst_alpha_parent_class parent_class
181 G_DEFINE_TYPE (GstAlpha, gst_alpha, GST_TYPE_VIDEO_FILTER);
183 #define GST_TYPE_ALPHA_METHOD (gst_alpha_method_get_type())
185 gst_alpha_method_get_type (void)
187 static GType alpha_method_type = 0;
188 static const GEnumValue alpha_method[] = {
189 {ALPHA_METHOD_SET, "Set/adjust alpha channel", "set"},
190 {ALPHA_METHOD_GREEN, "Chroma Key green", "green"},
191 {ALPHA_METHOD_BLUE, "Chroma Key blue", "blue"},
192 {ALPHA_METHOD_CUSTOM, "Chroma Key on target_r/g/b", "custom"},
196 if (!alpha_method_type) {
197 alpha_method_type = g_enum_register_static ("GstAlphaMethod", alpha_method);
199 return alpha_method_type;
203 gst_alpha_class_init (GstAlphaClass * klass)
205 GObjectClass *gobject_class = (GObjectClass *) klass;
206 GstElementClass *gstelement_class = (GstElementClass *) klass;
207 GstBaseTransformClass *btrans_class = (GstBaseTransformClass *) klass;
209 GST_DEBUG_CATEGORY_INIT (gst_alpha_debug, "alpha", 0,
210 "alpha - Element for adding alpha channel to streams");
212 gobject_class->set_property = gst_alpha_set_property;
213 gobject_class->get_property = gst_alpha_get_property;
214 gobject_class->finalize = gst_alpha_finalize;
216 g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_METHOD,
217 g_param_spec_enum ("method", "Method",
218 "How the alpha channels should be created", GST_TYPE_ALPHA_METHOD,
219 DEFAULT_METHOD, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
220 g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_ALPHA,
221 g_param_spec_double ("alpha", "Alpha", "The value for the alpha channel",
222 0.0, 1.0, DEFAULT_ALPHA,
223 G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
224 g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_TARGET_R,
225 g_param_spec_uint ("target-r", "Target Red", "The Red target", 0, 255,
227 G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
228 g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_TARGET_G,
229 g_param_spec_uint ("target-g", "Target Green", "The Green target", 0, 255,
231 G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
232 g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_TARGET_B,
233 g_param_spec_uint ("target-b", "Target Blue", "The Blue target", 0, 255,
235 G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
236 g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_ANGLE,
237 g_param_spec_float ("angle", "Angle", "Size of the colorcube to change",
238 0.0, 90.0, DEFAULT_ANGLE,
239 G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
240 g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_NOISE_LEVEL,
241 g_param_spec_float ("noise-level", "Noise Level", "Size of noise radius",
242 0.0, 64.0, DEFAULT_NOISE_LEVEL,
243 G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
244 g_object_class_install_property (G_OBJECT_CLASS (klass),
245 PROP_BLACK_SENSITIVITY, g_param_spec_uint ("black-sensitivity",
246 "Black Sensitivity", "Sensitivity to dark colors", 0, 128,
247 DEFAULT_BLACK_SENSITIVITY,
248 G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
249 g_object_class_install_property (G_OBJECT_CLASS (klass),
250 PROP_WHITE_SENSITIVITY, g_param_spec_uint ("white-sensitivity",
251 "Sensitivity", "Sensitivity to bright colors", 0, 128,
252 DEFAULT_WHITE_SENSITIVITY,
253 G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
254 g_object_class_install_property (G_OBJECT_CLASS (klass),
255 PROP_PREFER_PASSTHROUGH, g_param_spec_boolean ("prefer-passthrough",
256 "Prefer Passthrough",
257 "Don't do any processing for alpha=1.0 if possible",
258 DEFAULT_PREFER_PASSTHROUGH,
259 G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
261 gst_element_class_set_details_simple (gstelement_class, "Alpha filter",
262 "Filter/Effect/Video",
263 "Adds an alpha channel to video - uniform or via chroma-keying",
264 "Wim Taymans <wim.taymans@gmail.com>\n"
265 "Edward Hervey <edward.hervey@collabora.co.uk>\n"
266 "Jan Schmidt <thaytan@noraisin.net>");
268 gst_element_class_add_pad_template (gstelement_class,
269 gst_static_pad_template_get (&gst_alpha_sink_template));
270 gst_element_class_add_pad_template (gstelement_class,
271 gst_static_pad_template_get (&gst_alpha_src_template));
273 btrans_class->start = GST_DEBUG_FUNCPTR (gst_alpha_start);
274 btrans_class->transform = GST_DEBUG_FUNCPTR (gst_alpha_transform);
275 btrans_class->before_transform =
276 GST_DEBUG_FUNCPTR (gst_alpha_before_transform);
277 btrans_class->get_unit_size = GST_DEBUG_FUNCPTR (gst_alpha_get_unit_size);
278 btrans_class->transform_caps = GST_DEBUG_FUNCPTR (gst_alpha_transform_caps);
279 btrans_class->set_caps = GST_DEBUG_FUNCPTR (gst_alpha_set_caps);
283 gst_alpha_init (GstAlpha * alpha)
285 alpha->alpha = DEFAULT_ALPHA;
286 alpha->method = DEFAULT_METHOD;
287 alpha->target_r = DEFAULT_TARGET_R;
288 alpha->target_g = DEFAULT_TARGET_G;
289 alpha->target_b = DEFAULT_TARGET_B;
290 alpha->angle = DEFAULT_ANGLE;
291 alpha->noise_level = DEFAULT_NOISE_LEVEL;
292 alpha->black_sensitivity = DEFAULT_BLACK_SENSITIVITY;
293 alpha->white_sensitivity = DEFAULT_WHITE_SENSITIVITY;
295 g_static_mutex_init (&alpha->lock);
299 gst_alpha_finalize (GObject * object)
301 GstAlpha *alpha = GST_ALPHA (object);
303 g_static_mutex_free (&alpha->lock);
305 G_OBJECT_CLASS (parent_class)->finalize (object);
309 gst_alpha_set_property (GObject * object, guint prop_id,
310 const GValue * value, GParamSpec * pspec)
312 GstAlpha *alpha = GST_ALPHA (object);
313 gboolean reconfigure = FALSE;
315 GST_ALPHA_LOCK (alpha);
318 gint method = g_value_get_enum (value);
320 reconfigure = (method != alpha->method) && (method == ALPHA_METHOD_SET
321 || alpha->method == ALPHA_METHOD_SET) && (alpha->alpha == 1.0)
322 && (alpha->prefer_passthrough);
323 alpha->method = method;
325 switch (alpha->method) {
326 case ALPHA_METHOD_GREEN:
328 alpha->target_g = 255;
331 case ALPHA_METHOD_BLUE:
334 alpha->target_b = 255;
339 gst_alpha_set_process_function (alpha);
340 gst_alpha_init_params (alpha);
344 gdouble a = g_value_get_double (value);
346 reconfigure = (a != alpha->alpha) && (a == 1.0 || alpha->alpha == 1.0)
347 && (alpha->method == ALPHA_METHOD_SET) && (alpha->prefer_passthrough);
352 alpha->target_r = g_value_get_uint (value);
353 gst_alpha_init_params (alpha);
356 alpha->target_g = g_value_get_uint (value);
357 gst_alpha_init_params (alpha);
360 alpha->target_b = g_value_get_uint (value);
361 gst_alpha_init_params (alpha);
364 alpha->angle = g_value_get_float (value);
365 gst_alpha_init_params (alpha);
367 case PROP_NOISE_LEVEL:
368 alpha->noise_level = g_value_get_float (value);
369 gst_alpha_init_params (alpha);
371 case PROP_BLACK_SENSITIVITY:
372 alpha->black_sensitivity = g_value_get_uint (value);
374 case PROP_WHITE_SENSITIVITY:
375 alpha->white_sensitivity = g_value_get_uint (value);
377 case PROP_PREFER_PASSTHROUGH:{
378 gboolean prefer_passthrough = g_value_get_boolean (value);
380 reconfigure = ((!!prefer_passthrough) != (!!alpha->prefer_passthrough))
381 && (alpha->method == ALPHA_METHOD_SET) && (alpha->alpha == 1.0);
382 alpha->prefer_passthrough = prefer_passthrough;
386 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
391 gst_base_transform_reconfigure (GST_BASE_TRANSFORM_CAST (alpha));
393 GST_ALPHA_UNLOCK (alpha);
397 gst_alpha_get_property (GObject * object, guint prop_id, GValue * value,
400 GstAlpha *alpha = GST_ALPHA (object);
404 g_value_set_enum (value, alpha->method);
407 g_value_set_double (value, alpha->alpha);
410 g_value_set_uint (value, alpha->target_r);
413 g_value_set_uint (value, alpha->target_g);
416 g_value_set_uint (value, alpha->target_b);
419 g_value_set_float (value, alpha->angle);
421 case PROP_NOISE_LEVEL:
422 g_value_set_float (value, alpha->noise_level);
424 case PROP_BLACK_SENSITIVITY:
425 g_value_set_uint (value, alpha->black_sensitivity);
427 case PROP_WHITE_SENSITIVITY:
428 g_value_set_uint (value, alpha->white_sensitivity);
430 case PROP_PREFER_PASSTHROUGH:
431 g_value_set_boolean (value, alpha->prefer_passthrough);
434 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
440 gst_alpha_get_unit_size (GstBaseTransform * btrans,
441 GstCaps * caps, gsize * size)
445 if (!gst_video_info_from_caps (&info, caps))
450 GST_DEBUG_OBJECT (btrans, "unit size = %d for format %s w %d height %d",
451 *size, GST_VIDEO_INFO_NAME (&info), GST_VIDEO_INFO_WIDTH (&info),
452 GST_VIDEO_INFO_HEIGHT (&info));
458 gst_alpha_transform_caps (GstBaseTransform * btrans,
459 GstPadDirection direction, GstCaps * caps, GstCaps * filter)
461 GstAlpha *alpha = GST_ALPHA (btrans);
462 GstCaps *ret, *tmp, *tmp2;
463 GstStructure *structure;
466 tmp = gst_caps_new_empty ();
468 GST_ALPHA_LOCK (alpha);
469 for (i = 0; i < gst_caps_get_size (caps); i++) {
470 structure = gst_structure_copy (gst_caps_get_structure (caps, i));
472 gst_structure_remove_field (structure, "format");
473 gst_structure_remove_field (structure, "color-matrix");
474 gst_structure_remove_field (structure, "chroma-site");
476 gst_caps_append_structure (tmp, structure);
479 if (direction == GST_PAD_SINK) {
480 tmp2 = gst_static_caps_get (&gst_alpha_alpha_caps);
481 ret = gst_caps_intersect (tmp, tmp2);
482 gst_caps_unref (tmp);
483 gst_caps_unref (tmp2);
487 if (alpha->prefer_passthrough && alpha->method == ALPHA_METHOD_SET
488 && alpha->alpha == 1.0) {
489 ret = gst_caps_copy (caps);
490 gst_caps_append (ret, tmp);
501 GST_DEBUG_OBJECT (alpha,
502 "Transformed %" GST_PTR_FORMAT " -> %" GST_PTR_FORMAT, caps, ret);
505 GstCaps *intersection;
507 GST_DEBUG_OBJECT (alpha, "Using filter caps %" GST_PTR_FORMAT, filter);
509 gst_caps_intersect_full (filter, ret, GST_CAPS_INTERSECT_FIRST);
510 gst_caps_unref (ret);
512 GST_DEBUG_OBJECT (alpha, "Intersection %" GST_PTR_FORMAT, ret);
516 GST_ALPHA_UNLOCK (alpha);
522 gst_alpha_set_caps (GstBaseTransform * btrans,
523 GstCaps * incaps, GstCaps * outcaps)
525 GstAlpha *alpha = GST_ALPHA (btrans);
526 GstVideoInfo in_info, out_info;
527 gboolean passthrough;
529 if (!gst_video_info_from_caps (&in_info, incaps) ||
530 !gst_video_info_from_caps (&out_info, outcaps))
533 GST_ALPHA_LOCK (alpha);
536 in_info.color_matrix ? g_str_equal (in_info.color_matrix, "sdtv") : TRUE;
538 out_info.color_matrix ? g_str_equal (out_info.color_matrix,
541 passthrough = alpha->prefer_passthrough &&
542 GST_VIDEO_INFO_FORMAT (&in_info) == GST_VIDEO_INFO_FORMAT (&out_info)
543 && alpha->in_sdtv == alpha->out_sdtv && alpha->method == ALPHA_METHOD_SET
544 && alpha->alpha == 1.0;
546 GST_DEBUG_OBJECT (alpha,
547 "Setting caps %" GST_PTR_FORMAT " -> %" GST_PTR_FORMAT
548 " (passthrough: %d)", incaps, outcaps, passthrough);
549 gst_base_transform_set_passthrough (btrans, passthrough);
551 alpha->in_info = in_info;
552 alpha->out_info = out_info;
554 if (!gst_alpha_set_process_function (alpha) && !passthrough)
557 gst_alpha_init_params (alpha);
559 GST_ALPHA_UNLOCK (alpha);
566 GST_WARNING_OBJECT (alpha,
567 "Failed to parse caps %" GST_PTR_FORMAT " -> %" GST_PTR_FORMAT, incaps,
573 GST_WARNING_OBJECT (alpha,
574 "No processing function for this caps and no passthrough mode");
575 GST_ALPHA_UNLOCK (alpha);
580 /* based on http://www.cs.utah.edu/~michael/chroma/
583 chroma_keying_yuv (gint a, gint * y, gint * u,
584 gint * v, gint cr, gint cb, gint smin, gint smax, guint8 accept_angle_tg,
585 guint8 accept_angle_ctg, guint8 one_over_kc, guint8 kfgy_scale, gint8 kg,
593 /* too dark or too bright, keep alpha */
594 if (*y < smin || *y > smax)
597 /* Convert foreground to XZ coords where X direction is defined by
599 tmp = ((*u) * cb + (*v) * cr) >> 7;
600 x = CLAMP (tmp, -128, 127);
601 tmp = ((*v) * cb - (*u) * cr) >> 7;
602 z = CLAMP (tmp, -128, 127);
604 /* WARNING: accept angle should never be set greater than "somewhat less
605 than 90 degrees" to avoid dealing with negative/infinite tg. In reality,
606 80 degrees should be enough if foreground is reasonable. If this seems
607 to be a problem, go to alternative ways of checking point position
608 (scalar product or line equations). This angle should not be too small
609 either to avoid infinite ctg (used to suppress foreground without use of
612 tmp = (x * accept_angle_tg) >> 4;
613 tmp = MIN (tmp, 127);
616 /* keep foreground Kfg = 0 */
619 /* Compute Kfg (implicitly) and Kbg, suppress foreground in XZ coord
621 tmp = (z * accept_angle_ctg) >> 4;
622 tmp = CLAMP (tmp, -128, 127);
627 tmp1 = MAX (tmp1, 0);
628 b_alpha = (tmp1 * one_over_kc) / 2;
629 b_alpha = 255 - CLAMP (b_alpha, 0, 255);
630 b_alpha = (a * b_alpha) >> 8;
632 tmp = (tmp1 * kfgy_scale) >> 4;
633 tmp1 = MIN (tmp, 255);
635 *y = (*y < tmp1) ? 0 : *y - tmp1;
637 /* Convert suppressed foreground back to CbCr */
638 tmp = (x1 * cb - y1 * cr) >> 7;
639 *u = CLAMP (tmp, -128, 127);
641 tmp = (x1 * cr + y1 * cb) >> 7;
642 *v = CLAMP (tmp, -128, 127);
644 /* Deal with noise. For now, a circle around the key color with
645 radius of noise_level treated as exact key color. Introduces
648 tmp = z * z + (x - kg) * (x - kg);
649 tmp = MIN (tmp, 0xffff);
651 if (tmp < noise_level2)
657 #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)
660 gst_alpha_set_argb_ayuv (const GstVideoFrame * in_frame,
661 GstVideoFrame * out_frame, GstAlpha * alpha)
663 gint s_alpha = CLAMP ((gint) (alpha->alpha * 256), 0, 256);
672 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
673 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
675 width = GST_VIDEO_FRAME_WIDTH (in_frame);
676 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
678 o[0] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 3);
679 o[1] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 0);
680 o[2] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 1);
681 o[3] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 2);
684 alpha->out_sdtv ? cog_rgb_to_ycbcr_matrix_8bit_sdtv :
685 cog_rgb_to_ycbcr_matrix_8bit_hdtv, 12 * sizeof (gint));
687 for (i = 0; i < height; i++) {
688 for (j = 0; j < width; j++) {
689 dest[0] = (src[o[0]] * s_alpha) >> 8;
691 y = APPLY_MATRIX (matrix, 0, src[o[1]], src[o[2]], src[o[3]]);
692 u = APPLY_MATRIX (matrix, 1, src[o[1]], src[o[2]], src[o[3]]);
693 v = APPLY_MATRIX (matrix, 2, src[o[1]], src[o[2]], src[o[3]]);
706 gst_alpha_chroma_key_argb_ayuv (const GstVideoFrame * in_frame,
707 GstVideoFrame * out_frame, GstAlpha * alpha)
716 gint pa = CLAMP ((gint) (alpha->alpha * 256), 0, 256);
717 gint8 cb = alpha->cb, cr = alpha->cr;
718 gint8 kg = alpha->kg;
719 guint8 accept_angle_tg = alpha->accept_angle_tg;
720 guint8 accept_angle_ctg = alpha->accept_angle_ctg;
721 guint8 one_over_kc = alpha->one_over_kc;
722 guint8 kfgy_scale = alpha->kfgy_scale;
723 guint noise_level2 = alpha->noise_level2;
727 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
728 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
730 width = GST_VIDEO_FRAME_WIDTH (in_frame);
731 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
733 o[0] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 3);
734 o[1] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 0);
735 o[2] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 1);
736 o[3] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 2);
738 smin = 128 - alpha->black_sensitivity;
739 smax = 128 + alpha->white_sensitivity;
742 alpha->out_sdtv ? cog_rgb_to_ycbcr_matrix_8bit_sdtv :
743 cog_rgb_to_ycbcr_matrix_8bit_hdtv, 12 * sizeof (gint));
745 for (i = 0; i < height; i++) {
746 for (j = 0; j < width; j++) {
747 a = (src[o[0]] * pa) >> 8;
752 y = APPLY_MATRIX (matrix, 0, r, g, b);
753 u = APPLY_MATRIX (matrix, 1, r, g, b) - 128;
754 v = APPLY_MATRIX (matrix, 2, r, g, b) - 128;
756 a = chroma_keying_yuv (a, &y, &u, &v, cr, cb,
757 smin, smax, accept_angle_tg, accept_angle_ctg,
758 one_over_kc, kfgy_scale, kg, noise_level2);
775 gst_alpha_set_argb_argb (const GstVideoFrame * in_frame,
776 GstVideoFrame * out_frame, GstAlpha * alpha)
781 gint s_alpha = CLAMP ((gint) (alpha->alpha * 256), 0, 256);
785 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
786 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
788 width = GST_VIDEO_FRAME_WIDTH (in_frame);
789 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
791 p[0] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 3);
792 p[1] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 0);
793 p[2] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 1);
794 p[3] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 2);
796 o[0] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 3);
797 o[1] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 0);
798 o[2] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 1);
799 o[3] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 2);
801 for (i = 0; i < height; i++) {
802 for (j = 0; j < width; j++) {
803 dest[p[0]] = (src[o[0]] * s_alpha) >> 8;
805 dest[p[1]] = src[o[1]];
806 dest[p[2]] = src[o[2]];
807 dest[p[3]] = src[o[3]];
816 gst_alpha_chroma_key_argb_argb (const GstVideoFrame * in_frame,
817 GstVideoFrame * out_frame, GstAlpha * alpha)
826 gint pa = CLAMP ((gint) (alpha->alpha * 256), 0, 256);
827 gint8 cb = alpha->cb, cr = alpha->cr;
828 gint8 kg = alpha->kg;
829 guint8 accept_angle_tg = alpha->accept_angle_tg;
830 guint8 accept_angle_ctg = alpha->accept_angle_ctg;
831 guint8 one_over_kc = alpha->one_over_kc;
832 guint8 kfgy_scale = alpha->kfgy_scale;
833 guint noise_level2 = alpha->noise_level2;
834 gint matrix[12], matrix2[12];
837 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
838 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
840 width = GST_VIDEO_FRAME_WIDTH (in_frame);
841 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
843 p[0] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 3);
844 p[1] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 0);
845 p[2] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 1);
846 p[3] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 2);
848 o[0] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 3);
849 o[1] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 0);
850 o[2] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 1);
851 o[3] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 2);
853 smin = 128 - alpha->black_sensitivity;
854 smax = 128 + alpha->white_sensitivity;
856 memcpy (matrix, cog_rgb_to_ycbcr_matrix_8bit_sdtv, 12 * sizeof (gint));
857 memcpy (matrix2, cog_ycbcr_to_rgb_matrix_8bit_sdtv, 12 * sizeof (gint));
859 for (i = 0; i < height; i++) {
860 for (j = 0; j < width; j++) {
861 a = (src[o[0]] * pa) >> 8;
866 y = APPLY_MATRIX (matrix, 0, r, g, b);
867 u = APPLY_MATRIX (matrix, 1, r, g, b) - 128;
868 v = APPLY_MATRIX (matrix, 2, r, g, b) - 128;
870 a = chroma_keying_yuv (a, &y, &u, &v, cr, cb,
871 smin, smax, accept_angle_tg, accept_angle_ctg,
872 one_over_kc, kfgy_scale, kg, noise_level2);
877 r = APPLY_MATRIX (matrix2, 0, y, u, v);
878 g = APPLY_MATRIX (matrix2, 1, y, u, v);
879 b = APPLY_MATRIX (matrix2, 2, y, u, v);
882 dest[p[1]] = CLAMP (r, 0, 255);
883 dest[p[2]] = CLAMP (g, 0, 255);
884 dest[p[3]] = CLAMP (b, 0, 255);
893 gst_alpha_set_ayuv_argb (const GstVideoFrame * in_frame,
894 GstVideoFrame * out_frame, GstAlpha * alpha)
899 gint s_alpha = CLAMP ((gint) (alpha->alpha * 256), 0, 256);
905 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
906 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
908 width = GST_VIDEO_FRAME_WIDTH (in_frame);
909 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
911 p[0] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 3);
912 p[1] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 0);
913 p[2] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 1);
914 p[3] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 2);
917 alpha->in_sdtv ? cog_ycbcr_to_rgb_matrix_8bit_sdtv :
918 cog_ycbcr_to_rgb_matrix_8bit_hdtv, 12 * sizeof (gint));
920 for (y = 0; y < height; y++) {
921 for (x = 0; x < width; x++) {
922 dest[p[0]] = (src[0] * s_alpha) >> 8;
924 r = APPLY_MATRIX (matrix, 0, src[1], src[2], src[3]);
925 g = APPLY_MATRIX (matrix, 1, src[1], src[2], src[3]);
926 b = APPLY_MATRIX (matrix, 2, src[1], src[2], src[3]);
928 dest[p[1]] = CLAMP (r, 0, 255);
929 dest[p[2]] = CLAMP (g, 0, 255);
930 dest[p[3]] = CLAMP (b, 0, 255);
939 gst_alpha_chroma_key_ayuv_argb (const GstVideoFrame * in_frame,
940 GstVideoFrame * out_frame, GstAlpha * alpha)
949 gint pa = CLAMP ((gint) (alpha->alpha * 256), 0, 256);
950 gint8 cb = alpha->cb, cr = alpha->cr;
951 gint8 kg = alpha->kg;
952 guint8 accept_angle_tg = alpha->accept_angle_tg;
953 guint8 accept_angle_ctg = alpha->accept_angle_ctg;
954 guint8 one_over_kc = alpha->one_over_kc;
955 guint8 kfgy_scale = alpha->kfgy_scale;
956 guint noise_level2 = alpha->noise_level2;
960 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
961 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
963 width = GST_VIDEO_FRAME_WIDTH (in_frame);
964 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
966 p[0] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 3);
967 p[1] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 0);
968 p[2] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 1);
969 p[3] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 2);
971 smin = 128 - alpha->black_sensitivity;
972 smax = 128 + alpha->white_sensitivity;
975 alpha->in_sdtv ? cog_ycbcr_to_rgb_matrix_8bit_sdtv :
976 cog_ycbcr_to_rgb_matrix_8bit_hdtv, 12 * sizeof (gint));
978 for (i = 0; i < height; i++) {
979 for (j = 0; j < width; j++) {
980 a = (src[0] * pa) >> 8;
985 a = chroma_keying_yuv (a, &y, &u, &v, cr, cb,
986 smin, smax, accept_angle_tg, accept_angle_ctg,
987 one_over_kc, kfgy_scale, kg, noise_level2);
992 r = APPLY_MATRIX (matrix, 0, y, u, v);
993 g = APPLY_MATRIX (matrix, 1, y, u, v);
994 b = APPLY_MATRIX (matrix, 2, y, u, v);
997 dest[p[1]] = CLAMP (r, 0, 255);
998 dest[p[2]] = CLAMP (g, 0, 255);
999 dest[p[3]] = CLAMP (b, 0, 255);
1008 gst_alpha_set_ayuv_ayuv (const GstVideoFrame * in_frame,
1009 GstVideoFrame * out_frame, GstAlpha * alpha)
1014 gint s_alpha = CLAMP ((gint) (alpha->alpha * 256), 0, 256);
1017 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
1018 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
1020 width = GST_VIDEO_FRAME_WIDTH (in_frame);
1021 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
1023 if (alpha->in_sdtv == alpha->out_sdtv) {
1024 for (y = 0; y < height; y++) {
1025 for (x = 0; x < width; x++) {
1026 dest[0] = (src[0] * s_alpha) >> 8;
1039 alpha->out_sdtv ? cog_ycbcr_hdtv_to_ycbcr_sdtv_matrix_8bit :
1040 cog_ycbcr_sdtv_to_ycbcr_hdtv_matrix_8bit, 12 * sizeof (gint));
1042 for (y = 0; y < height; y++) {
1043 for (x = 0; x < width; x++) {
1044 dest[0] = (src[0] * s_alpha) >> 8;
1045 dest[1] = APPLY_MATRIX (matrix, 0, src[1], src[2], src[3]);
1046 dest[2] = APPLY_MATRIX (matrix, 1, src[1], src[2], src[3]);
1047 dest[3] = APPLY_MATRIX (matrix, 2, src[1], src[2], src[3]);
1057 gst_alpha_chroma_key_ayuv_ayuv (const GstVideoFrame * in_frame,
1058 GstVideoFrame * out_frame, GstAlpha * alpha)
1066 gint pa = CLAMP ((gint) (alpha->alpha * 256), 0, 256);
1067 gint8 cb = alpha->cb, cr = alpha->cr;
1068 gint8 kg = alpha->kg;
1069 guint8 accept_angle_tg = alpha->accept_angle_tg;
1070 guint8 accept_angle_ctg = alpha->accept_angle_ctg;
1071 guint8 one_over_kc = alpha->one_over_kc;
1072 guint8 kfgy_scale = alpha->kfgy_scale;
1073 guint noise_level2 = alpha->noise_level2;
1075 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
1076 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
1078 width = GST_VIDEO_FRAME_WIDTH (in_frame);
1079 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
1081 smin = 128 - alpha->black_sensitivity;
1082 smax = 128 + alpha->white_sensitivity;
1084 if (alpha->in_sdtv == alpha->out_sdtv) {
1085 for (i = 0; i < height; i++) {
1086 for (j = 0; j < width; j++) {
1087 a = (src[0] * pa) >> 8;
1092 a = chroma_keying_yuv (a, &y, &u, &v, cr, cb,
1093 smin, smax, accept_angle_tg, accept_angle_ctg,
1094 one_over_kc, kfgy_scale, kg, noise_level2);
1112 alpha->out_sdtv ? cog_ycbcr_hdtv_to_ycbcr_sdtv_matrix_8bit :
1113 cog_ycbcr_sdtv_to_ycbcr_hdtv_matrix_8bit, 12 * sizeof (gint));
1115 for (i = 0; i < height; i++) {
1116 for (j = 0; j < width; j++) {
1117 a = (src[0] * pa) >> 8;
1118 y = APPLY_MATRIX (matrix, 0, src[1], src[2], src[3]);
1119 u = APPLY_MATRIX (matrix, 1, src[1], src[2], src[3]) - 128;
1120 v = APPLY_MATRIX (matrix, 2, src[1], src[2], src[3]) - 128;
1122 a = chroma_keying_yuv (a, &y, &u, &v, cr, cb,
1123 smin, smax, accept_angle_tg, accept_angle_ctg,
1124 one_over_kc, kfgy_scale, kg, noise_level2);
1142 gst_alpha_set_rgb_ayuv (const GstVideoFrame * in_frame,
1143 GstVideoFrame * out_frame, GstAlpha * alpha)
1148 gint s_alpha = CLAMP ((gint) (alpha->alpha * 255), 0, 255);
1155 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
1156 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
1158 width = GST_VIDEO_FRAME_WIDTH (in_frame);
1159 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
1161 bpp = GST_VIDEO_FRAME_COMP_PSTRIDE (in_frame, 0);
1162 o[0] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 0);
1163 o[1] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 1);
1164 o[2] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 2);
1167 alpha->out_sdtv ? cog_rgb_to_ycbcr_matrix_8bit_sdtv :
1168 cog_rgb_to_ycbcr_matrix_8bit_hdtv, 12 * sizeof (gint));
1170 for (i = 0; i < height; i++) {
1171 for (j = 0; j < width; j++) {
1174 y = APPLY_MATRIX (matrix, 0, src[o[0]], src[o[1]], src[o[2]]);
1175 u = APPLY_MATRIX (matrix, 1, src[o[0]], src[o[1]], src[o[2]]);
1176 v = APPLY_MATRIX (matrix, 2, src[o[0]], src[o[1]], src[o[2]]);
1189 gst_alpha_chroma_key_rgb_ayuv (const GstVideoFrame * in_frame,
1190 GstVideoFrame * out_frame, GstAlpha * alpha)
1199 gint pa = CLAMP ((gint) (alpha->alpha * 255), 0, 255);
1200 gint8 cb = alpha->cb, cr = alpha->cr;
1201 gint8 kg = alpha->kg;
1202 guint8 accept_angle_tg = alpha->accept_angle_tg;
1203 guint8 accept_angle_ctg = alpha->accept_angle_ctg;
1204 guint8 one_over_kc = alpha->one_over_kc;
1205 guint8 kfgy_scale = alpha->kfgy_scale;
1206 guint noise_level2 = alpha->noise_level2;
1211 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
1212 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
1214 width = GST_VIDEO_FRAME_WIDTH (in_frame);
1215 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
1217 bpp = GST_VIDEO_FRAME_COMP_PSTRIDE (in_frame, 0);
1219 o[0] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 0);
1220 o[1] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 1);
1221 o[2] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 2);
1223 smin = 128 - alpha->black_sensitivity;
1224 smax = 128 + alpha->white_sensitivity;
1227 alpha->out_sdtv ? cog_rgb_to_ycbcr_matrix_8bit_sdtv :
1228 cog_rgb_to_ycbcr_matrix_8bit_hdtv, 12 * sizeof (gint));
1230 for (i = 0; i < height; i++) {
1231 for (j = 0; j < width; j++) {
1237 y = APPLY_MATRIX (matrix, 0, r, g, b);
1238 u = APPLY_MATRIX (matrix, 1, r, g, b) - 128;
1239 v = APPLY_MATRIX (matrix, 2, r, g, b) - 128;
1241 a = chroma_keying_yuv (a, &y, &u, &v, cr, cb,
1242 smin, smax, accept_angle_tg, accept_angle_ctg,
1243 one_over_kc, kfgy_scale, kg, noise_level2);
1260 gst_alpha_set_rgb_argb (const GstVideoFrame * in_frame,
1261 GstVideoFrame * out_frame, GstAlpha * alpha)
1266 gint s_alpha = CLAMP ((gint) (alpha->alpha * 255), 0, 255);
1271 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
1272 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
1274 width = GST_VIDEO_FRAME_WIDTH (in_frame);
1275 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
1277 bpp = GST_VIDEO_FRAME_COMP_PSTRIDE (in_frame, 0);
1279 o[0] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 0);
1280 o[1] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 1);
1281 o[2] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 2);
1283 p[0] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 3);
1284 p[1] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 0);
1285 p[2] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 1);
1286 p[3] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 2);
1288 for (i = 0; i < height; i++) {
1289 for (j = 0; j < width; j++) {
1290 dest[p[0]] = s_alpha;
1292 dest[p[1]] = src[o[0]];
1293 dest[p[2]] = src[o[1]];
1294 dest[p[3]] = src[o[2]];
1303 gst_alpha_chroma_key_rgb_argb (const GstVideoFrame * in_frame,
1304 GstVideoFrame * out_frame, GstAlpha * alpha)
1313 gint pa = CLAMP ((gint) (alpha->alpha * 255), 0, 255);
1314 gint8 cb = alpha->cb, cr = alpha->cr;
1315 gint8 kg = alpha->kg;
1316 guint8 accept_angle_tg = alpha->accept_angle_tg;
1317 guint8 accept_angle_ctg = alpha->accept_angle_ctg;
1318 guint8 one_over_kc = alpha->one_over_kc;
1319 guint8 kfgy_scale = alpha->kfgy_scale;
1320 guint noise_level2 = alpha->noise_level2;
1321 gint matrix[12], matrix2[12];
1325 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
1326 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
1328 width = GST_VIDEO_FRAME_WIDTH (in_frame);
1329 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
1331 bpp = GST_VIDEO_FRAME_COMP_PSTRIDE (in_frame, 0);
1333 o[0] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 0);
1334 o[1] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 1);
1335 o[2] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 2);
1337 p[0] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 3);
1338 p[1] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 0);
1339 p[2] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 1);
1340 p[3] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 2);
1342 smin = 128 - alpha->black_sensitivity;
1343 smax = 128 + alpha->white_sensitivity;
1345 memcpy (matrix, cog_rgb_to_ycbcr_matrix_8bit_sdtv, 12 * sizeof (gint));
1346 memcpy (matrix2, cog_ycbcr_to_rgb_matrix_8bit_sdtv, 12 * sizeof (gint));
1348 for (i = 0; i < height; i++) {
1349 for (j = 0; j < width; j++) {
1355 y = APPLY_MATRIX (matrix, 0, r, g, b);
1356 u = APPLY_MATRIX (matrix, 1, r, g, b) - 128;
1357 v = APPLY_MATRIX (matrix, 2, r, g, b) - 128;
1359 a = chroma_keying_yuv (a, &y, &u, &v, cr, cb,
1360 smin, smax, accept_angle_tg, accept_angle_ctg,
1361 one_over_kc, kfgy_scale, kg, noise_level2);
1366 r = APPLY_MATRIX (matrix2, 0, y, u, v);
1367 g = APPLY_MATRIX (matrix2, 1, y, u, v);
1368 b = APPLY_MATRIX (matrix2, 2, y, u, v);
1371 dest[p[1]] = CLAMP (r, 0, 255);
1372 dest[p[2]] = CLAMP (g, 0, 255);
1373 dest[p[3]] = CLAMP (b, 0, 255);
1382 gst_alpha_set_planar_yuv_ayuv (const GstVideoFrame * in_frame,
1383 GstVideoFrame * out_frame, GstAlpha * alpha)
1388 gint b_alpha = CLAMP ((gint) (alpha->alpha * 255), 0, 255);
1389 const guint8 *srcY, *srcY_tmp;
1390 const guint8 *srcU, *srcU_tmp;
1391 const guint8 *srcV, *srcV_tmp;
1393 gint y_stride, uv_stride;
1394 gint v_subs, h_subs;
1396 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
1397 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
1399 width = GST_VIDEO_FRAME_WIDTH (in_frame);
1400 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
1402 y_stride = GST_VIDEO_FRAME_COMP_STRIDE (in_frame, 0);
1403 uv_stride = GST_VIDEO_FRAME_COMP_STRIDE (in_frame, 1);
1405 srcY_tmp = srcY = src;
1406 srcU_tmp = srcU = src + GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 1);
1407 srcV_tmp = srcV = src + GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 2);
1409 switch (GST_VIDEO_FRAME_FORMAT (in_frame)) {
1410 case GST_VIDEO_FORMAT_I420:
1411 case GST_VIDEO_FORMAT_YV12:
1412 v_subs = h_subs = 2;
1414 case GST_VIDEO_FORMAT_Y444:
1415 v_subs = h_subs = 1;
1417 case GST_VIDEO_FORMAT_Y42B:
1421 case GST_VIDEO_FORMAT_Y41B:
1426 g_assert_not_reached ();
1430 if (alpha->in_sdtv == alpha->out_sdtv) {
1431 for (i = 0; i < height; i++) {
1432 for (j = 0; j < width; j++) {
1440 if ((j + 1) % h_subs == 0) {
1446 srcY_tmp = srcY = srcY_tmp + y_stride;
1447 if ((i + 1) % v_subs == 0) {
1448 srcU_tmp = srcU = srcU_tmp + uv_stride;
1449 srcV_tmp = srcV = srcV_tmp + uv_stride;
1460 alpha->out_sdtv ? cog_ycbcr_hdtv_to_ycbcr_sdtv_matrix_8bit :
1461 cog_ycbcr_sdtv_to_ycbcr_hdtv_matrix_8bit, 12 * sizeof (gint));
1463 for (i = 0; i < height; i++) {
1464 for (j = 0; j < width; j++) {
1471 dest[1] = APPLY_MATRIX (matrix, 0, y, u, v);
1472 dest[2] = APPLY_MATRIX (matrix, 1, y, u, v);
1473 dest[3] = APPLY_MATRIX (matrix, 2, y, u, v);
1477 if ((j + 1) % h_subs == 0) {
1483 srcY_tmp = srcY = srcY_tmp + y_stride;
1484 if ((i + 1) % v_subs == 0) {
1485 srcU_tmp = srcU = srcU_tmp + uv_stride;
1486 srcV_tmp = srcV = srcV_tmp + uv_stride;
1496 gst_alpha_chroma_key_planar_yuv_ayuv (const GstVideoFrame * in_frame,
1497 GstVideoFrame * out_frame, GstAlpha * alpha)
1502 gint b_alpha = CLAMP ((gint) (alpha->alpha * 255), 0, 255);
1503 const guint8 *srcY, *srcY_tmp;
1504 const guint8 *srcU, *srcU_tmp;
1505 const guint8 *srcV, *srcV_tmp;
1508 gint y_stride, uv_stride;
1509 gint v_subs, h_subs;
1510 gint smin = 128 - alpha->black_sensitivity;
1511 gint smax = 128 + alpha->white_sensitivity;
1512 gint8 cb = alpha->cb, cr = alpha->cr;
1513 gint8 kg = alpha->kg;
1514 guint8 accept_angle_tg = alpha->accept_angle_tg;
1515 guint8 accept_angle_ctg = alpha->accept_angle_ctg;
1516 guint8 one_over_kc = alpha->one_over_kc;
1517 guint8 kfgy_scale = alpha->kfgy_scale;
1518 guint noise_level2 = alpha->noise_level2;
1520 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
1521 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
1523 width = GST_VIDEO_FRAME_WIDTH (in_frame);
1524 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
1526 y_stride = GST_VIDEO_FRAME_COMP_STRIDE (in_frame, 0);
1527 uv_stride = GST_VIDEO_FRAME_COMP_STRIDE (in_frame, 1);
1529 srcY_tmp = srcY = src;
1530 srcU_tmp = srcU = src + GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 1);
1531 srcV_tmp = srcV = src + GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 2);
1533 switch (GST_VIDEO_FRAME_FORMAT (in_frame)) {
1534 case GST_VIDEO_FORMAT_I420:
1535 case GST_VIDEO_FORMAT_YV12:
1536 v_subs = h_subs = 2;
1538 case GST_VIDEO_FORMAT_Y444:
1539 v_subs = h_subs = 1;
1541 case GST_VIDEO_FORMAT_Y42B:
1545 case GST_VIDEO_FORMAT_Y41B:
1550 g_assert_not_reached ();
1554 if (alpha->in_sdtv == alpha->out_sdtv) {
1555 for (i = 0; i < height; i++) {
1556 for (j = 0; j < width; j++) {
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);
1576 if ((j + 1) % h_subs == 0) {
1582 srcY_tmp = srcY = srcY_tmp + y_stride;
1583 if ((i + 1) % v_subs == 0) {
1584 srcU_tmp = srcU = srcU_tmp + uv_stride;
1585 srcV_tmp = srcV = srcV_tmp + uv_stride;
1595 alpha->out_sdtv ? cog_ycbcr_hdtv_to_ycbcr_sdtv_matrix_8bit :
1596 cog_ycbcr_sdtv_to_ycbcr_hdtv_matrix_8bit, 12 * sizeof (gint));
1598 for (i = 0; i < height; i++) {
1599 for (j = 0; j < width; j++) {
1601 y = APPLY_MATRIX (matrix, 0, srcY[0], srcU[0], srcV[0]);
1602 u = APPLY_MATRIX (matrix, 1, srcY[0], srcU[0], srcV[0]) - 128;
1603 v = APPLY_MATRIX (matrix, 2, srcY[0], srcU[0], srcV[0]) - 128;
1605 a = chroma_keying_yuv (a, &y, &u, &v, cr, cb, smin,
1606 smax, accept_angle_tg, accept_angle_ctg,
1607 one_over_kc, kfgy_scale, kg, noise_level2);
1616 if ((j + 1) % h_subs == 0) {
1622 srcY_tmp = srcY = srcY_tmp + y_stride;
1623 if ((i + 1) % v_subs == 0) {
1624 srcU_tmp = srcU = srcU_tmp + uv_stride;
1625 srcV_tmp = srcV = srcV_tmp + uv_stride;
1635 gst_alpha_set_planar_yuv_argb (const GstVideoFrame * in_frame,
1636 GstVideoFrame * out_frame, GstAlpha * alpha)
1641 gint b_alpha = CLAMP ((gint) (alpha->alpha * 255), 0, 255);
1642 const guint8 *srcY, *srcY_tmp;
1643 const guint8 *srcU, *srcU_tmp;
1644 const guint8 *srcV, *srcV_tmp;
1646 gint y_stride, uv_stride;
1647 gint v_subs, h_subs;
1653 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
1654 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
1656 width = GST_VIDEO_FRAME_WIDTH (in_frame);
1657 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
1659 p[0] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 3);
1660 p[1] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 0);
1661 p[2] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 1);
1662 p[3] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 2);
1664 y_stride = GST_VIDEO_FRAME_COMP_STRIDE (in_frame, 0);
1665 uv_stride = GST_VIDEO_FRAME_COMP_STRIDE (in_frame, 1);
1667 srcY_tmp = srcY = src;
1668 srcU_tmp = srcU = src + GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 1);
1669 srcV_tmp = srcV = src + GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 2);
1671 switch (GST_VIDEO_FRAME_FORMAT (in_frame)) {
1672 case GST_VIDEO_FORMAT_I420:
1673 case GST_VIDEO_FORMAT_YV12:
1674 v_subs = h_subs = 2;
1676 case GST_VIDEO_FORMAT_Y444:
1677 v_subs = h_subs = 1;
1679 case GST_VIDEO_FORMAT_Y42B:
1683 case GST_VIDEO_FORMAT_Y41B:
1688 g_assert_not_reached ();
1693 alpha->in_sdtv ? cog_ycbcr_to_rgb_matrix_8bit_sdtv :
1694 cog_ycbcr_to_rgb_matrix_8bit_hdtv, 12 * sizeof (gint));
1696 for (i = 0; i < height; i++) {
1697 for (j = 0; j < width; j++) {
1704 r = APPLY_MATRIX (matrix, 0, y, u, v);
1705 g = APPLY_MATRIX (matrix, 1, y, u, v);
1706 b = APPLY_MATRIX (matrix, 2, y, u, v);
1707 dest[p[1]] = CLAMP (r, 0, 255);
1708 dest[p[2]] = CLAMP (g, 0, 255);
1709 dest[p[3]] = CLAMP (b, 0, 255);
1713 if ((j + 1) % h_subs == 0) {
1719 srcY_tmp = srcY = srcY_tmp + y_stride;
1720 if ((i + 1) % v_subs == 0) {
1721 srcU_tmp = srcU = srcU_tmp + uv_stride;
1722 srcV_tmp = srcV = srcV_tmp + uv_stride;
1731 gst_alpha_chroma_key_planar_yuv_argb (const GstVideoFrame * in_frame,
1732 GstVideoFrame * out_frame, GstAlpha * alpha)
1737 gint b_alpha = CLAMP ((gint) (alpha->alpha * 255), 0, 255);
1738 const guint8 *srcY, *srcY_tmp;
1739 const guint8 *srcU, *srcU_tmp;
1740 const guint8 *srcV, *srcV_tmp;
1744 gint y_stride, uv_stride;
1745 gint v_subs, h_subs;
1746 gint smin = 128 - alpha->black_sensitivity;
1747 gint smax = 128 + alpha->white_sensitivity;
1748 gint8 cb = alpha->cb, cr = alpha->cr;
1749 gint8 kg = alpha->kg;
1750 guint8 accept_angle_tg = alpha->accept_angle_tg;
1751 guint8 accept_angle_ctg = alpha->accept_angle_ctg;
1752 guint8 one_over_kc = alpha->one_over_kc;
1753 guint8 kfgy_scale = alpha->kfgy_scale;
1754 guint noise_level2 = alpha->noise_level2;
1758 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
1759 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
1761 width = GST_VIDEO_FRAME_WIDTH (in_frame);
1762 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
1764 p[0] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 3);
1765 p[1] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 0);
1766 p[2] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 1);
1767 p[3] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 2);
1769 y_stride = GST_VIDEO_FRAME_COMP_STRIDE (in_frame, 0);
1770 uv_stride = GST_VIDEO_FRAME_COMP_STRIDE (in_frame, 1);
1772 srcY_tmp = srcY = src;
1773 srcU_tmp = srcU = src + GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 1);
1774 srcV_tmp = srcV = src + GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 2);
1776 switch (GST_VIDEO_FRAME_FORMAT (in_frame)) {
1777 case GST_VIDEO_FORMAT_I420:
1778 case GST_VIDEO_FORMAT_YV12:
1779 v_subs = h_subs = 2;
1781 case GST_VIDEO_FORMAT_Y444:
1782 v_subs = h_subs = 1;
1784 case GST_VIDEO_FORMAT_Y42B:
1788 case GST_VIDEO_FORMAT_Y41B:
1793 g_assert_not_reached ();
1798 alpha->in_sdtv ? cog_ycbcr_to_rgb_matrix_8bit_sdtv :
1799 cog_ycbcr_to_rgb_matrix_8bit_hdtv, 12 * sizeof (gint));
1801 for (i = 0; i < height; i++) {
1802 for (j = 0; j < width; j++) {
1808 a = chroma_keying_yuv (a, &y, &u, &v, cr, cb, smin,
1809 smax, accept_angle_tg, accept_angle_ctg,
1810 one_over_kc, kfgy_scale, kg, noise_level2);
1816 r = APPLY_MATRIX (matrix, 0, y, u, v);
1817 g = APPLY_MATRIX (matrix, 1, y, u, v);
1818 b = APPLY_MATRIX (matrix, 2, y, u, v);
1819 dest[p[1]] = CLAMP (r, 0, 255);
1820 dest[p[2]] = CLAMP (g, 0, 255);
1821 dest[p[3]] = CLAMP (b, 0, 255);
1825 if ((j + 1) % h_subs == 0) {
1831 srcY_tmp = srcY = srcY_tmp + y_stride;
1832 if ((i + 1) % v_subs == 0) {
1833 srcU_tmp = srcU = srcU_tmp + uv_stride;
1834 srcV_tmp = srcV = srcV_tmp + uv_stride;
1843 gst_alpha_set_packed_422_ayuv (const GstVideoFrame * in_frame,
1844 GstVideoFrame * out_frame, GstAlpha * alpha)
1849 gint s_alpha = CLAMP ((gint) (alpha->alpha * 255), 0, 255);
1852 gint p[4]; /* Y U Y V */
1854 const guint8 *src_tmp;
1856 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
1857 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
1859 width = GST_VIDEO_FRAME_WIDTH (in_frame);
1860 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
1862 src_stride = GST_VIDEO_FRAME_COMP_STRIDE (in_frame, 0);
1864 p[0] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 0);
1866 p[1] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 1);
1867 p[3] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 2);
1869 if (alpha->in_sdtv != alpha->out_sdtv) {
1873 alpha->in_sdtv ? cog_ycbcr_sdtv_to_ycbcr_hdtv_matrix_8bit :
1874 cog_ycbcr_hdtv_to_ycbcr_sdtv_matrix_8bit, 12 * sizeof (gint));
1876 for (i = 0; i < height; i++) {
1879 for (j = 0; j < width - 1; j += 2) {
1883 y = APPLY_MATRIX (matrix, 0, src[p[0]], src[p[1]], src[p[3]]);
1884 u = APPLY_MATRIX (matrix, 1, src[p[0]], src[p[1]], src[p[3]]);
1885 v = APPLY_MATRIX (matrix, 2, src[p[0]], src[p[1]], src[p[3]]);
1891 y = APPLY_MATRIX (matrix, 0, src[p[2]], src[p[1]], src[p[3]]);
1892 u = APPLY_MATRIX (matrix, 1, src[p[2]], src[p[1]], src[p[3]]);
1893 v = APPLY_MATRIX (matrix, 2, src[p[2]], src[p[1]], src[p[3]]);
1903 if (j == width - 1) {
1906 y = APPLY_MATRIX (matrix, 0, src[p[0]], src[p[1]], src[p[3]]);
1907 u = APPLY_MATRIX (matrix, 1, src[p[0]], src[p[1]], src[p[3]]);
1908 v = APPLY_MATRIX (matrix, 2, src[p[0]], src[p[1]], src[p[3]]);
1917 src = src_tmp + src_stride;
1920 for (i = 0; i < height; i++) {
1923 for (j = 0; j < width - 1; j += 2) {
1945 if (j == width - 1) {
1959 src = src_tmp + src_stride;
1965 gst_alpha_chroma_key_packed_422_ayuv (const GstVideoFrame * in_frame,
1966 GstVideoFrame * out_frame, GstAlpha * alpha)
1974 gint pa = CLAMP ((gint) (alpha->alpha * 255), 0, 255);
1975 gint8 cb = alpha->cb, cr = alpha->cr;
1976 gint8 kg = alpha->kg;
1977 guint8 accept_angle_tg = alpha->accept_angle_tg;
1978 guint8 accept_angle_ctg = alpha->accept_angle_ctg;
1979 guint8 one_over_kc = alpha->one_over_kc;
1980 guint8 kfgy_scale = alpha->kfgy_scale;
1981 guint noise_level2 = alpha->noise_level2;
1982 gint p[4]; /* Y U Y V */
1984 const guint8 *src_tmp;
1986 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
1987 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
1989 width = GST_VIDEO_FRAME_WIDTH (in_frame);
1990 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
1992 src_stride = GST_VIDEO_FRAME_COMP_STRIDE (in_frame, 0);
1994 p[0] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 0);
1996 p[1] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 1);
1997 p[3] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 2);
1999 smin = 128 - alpha->black_sensitivity;
2000 smax = 128 + alpha->white_sensitivity;
2002 if (alpha->in_sdtv != alpha->out_sdtv) {
2006 alpha->in_sdtv ? cog_ycbcr_sdtv_to_ycbcr_hdtv_matrix_8bit :
2007 cog_ycbcr_hdtv_to_ycbcr_sdtv_matrix_8bit, 12 * sizeof (gint));
2009 for (i = 0; i < height; i++) {
2012 for (j = 0; j < width - 1; j += 2) {
2013 y = APPLY_MATRIX (matrix, 0, src[p[0]], src[p[1]], src[p[3]]);
2014 u = APPLY_MATRIX (matrix, 1, src[p[0]], src[p[1]], src[p[3]]) - 128;
2015 v = APPLY_MATRIX (matrix, 2, src[p[0]], src[p[1]], src[p[3]]) - 128;
2017 a = chroma_keying_yuv (pa, &y, &u, &v, cr, cb,
2018 smin, smax, accept_angle_tg, accept_angle_ctg,
2019 one_over_kc, kfgy_scale, kg, noise_level2);
2026 y = APPLY_MATRIX (matrix, 0, src[p[2]], src[p[1]], src[p[3]]);
2027 u = APPLY_MATRIX (matrix, 1, src[p[2]], src[p[1]], src[p[3]]) - 128;
2028 v = APPLY_MATRIX (matrix, 2, src[p[2]], src[p[1]], src[p[3]]) - 128;
2030 a = chroma_keying_yuv (pa, &y, &u, &v, cr, cb,
2031 smin, smax, accept_angle_tg, accept_angle_ctg,
2032 one_over_kc, kfgy_scale, kg, noise_level2);
2043 if (j == width - 1) {
2044 y = APPLY_MATRIX (matrix, 0, src[p[0]], src[p[1]], src[p[3]]);
2045 u = APPLY_MATRIX (matrix, 1, src[p[0]], src[p[1]], src[p[3]]) - 128;
2046 v = APPLY_MATRIX (matrix, 2, src[p[0]], src[p[1]], src[p[3]]) - 128;
2048 a = chroma_keying_yuv (pa, &y, &u, &v, cr, cb,
2049 smin, smax, accept_angle_tg, accept_angle_ctg,
2050 one_over_kc, kfgy_scale, kg, noise_level2);
2060 src = src_tmp + src_stride;
2063 for (i = 0; i < height; i++) {
2066 for (j = 0; j < width - 1; j += 2) {
2068 u = src[p[1]] - 128;
2069 v = src[p[3]] - 128;
2071 a = chroma_keying_yuv (pa, &y, &u, &v, cr, cb,
2072 smin, smax, accept_angle_tg, accept_angle_ctg,
2073 one_over_kc, kfgy_scale, kg, noise_level2);
2081 u = src[p[1]] - 128;
2082 v = src[p[3]] - 128;
2084 a = chroma_keying_yuv (pa, &y, &u, &v, cr, cb,
2085 smin, smax, accept_angle_tg, accept_angle_ctg,
2086 one_over_kc, kfgy_scale, kg, noise_level2);
2097 if (j == width - 1) {
2099 u = src[p[1]] - 128;
2100 v = src[p[3]] - 128;
2102 a = chroma_keying_yuv (pa, &y, &u, &v, cr, cb,
2103 smin, smax, accept_angle_tg, accept_angle_ctg,
2104 one_over_kc, kfgy_scale, kg, noise_level2);
2114 src = src_tmp + src_stride;
2120 gst_alpha_set_packed_422_argb (const GstVideoFrame * in_frame,
2121 GstVideoFrame * out_frame, GstAlpha * alpha)
2126 gint s_alpha = CLAMP ((gint) (alpha->alpha * 255), 0, 255);
2130 const guint8 *src_tmp;
2134 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
2135 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
2137 width = GST_VIDEO_FRAME_WIDTH (in_frame);
2138 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
2140 src_stride = GST_VIDEO_FRAME_COMP_STRIDE (in_frame, 0);
2142 o[0] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 0);
2144 o[1] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 1);
2145 o[3] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 2);
2147 p[0] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 3);
2148 p[1] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 0);
2149 p[2] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 1);
2150 p[3] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 2);
2153 alpha->in_sdtv ? cog_ycbcr_to_rgb_matrix_8bit_sdtv :
2154 cog_ycbcr_to_rgb_matrix_8bit_hdtv, 12 * sizeof (gint));
2156 for (i = 0; i < height; i++) {
2159 for (j = 0; j < width - 1; j += 2) {
2160 r = APPLY_MATRIX (matrix, 0, src[o[0]], src[o[1]], src[o[3]]);
2161 g = APPLY_MATRIX (matrix, 1, src[o[0]], src[o[1]], src[o[3]]);
2162 b = APPLY_MATRIX (matrix, 2, src[o[0]], src[o[1]], src[o[3]]);
2164 dest[p[0]] = s_alpha;
2165 dest[p[1]] = CLAMP (r, 0, 255);
2166 dest[p[2]] = CLAMP (g, 0, 255);
2167 dest[p[3]] = CLAMP (b, 0, 255);
2169 r = APPLY_MATRIX (matrix, 0, src[o[2]], src[o[1]], src[o[3]]);
2170 g = APPLY_MATRIX (matrix, 1, src[o[2]], src[o[1]], src[o[3]]);
2171 b = APPLY_MATRIX (matrix, 2, src[o[2]], src[o[1]], src[o[3]]);
2173 dest[4 + p[0]] = s_alpha;
2174 dest[4 + p[1]] = CLAMP (r, 0, 255);
2175 dest[4 + p[2]] = CLAMP (g, 0, 255);
2176 dest[4 + p[3]] = CLAMP (b, 0, 255);
2182 if (j == width - 1) {
2183 r = APPLY_MATRIX (matrix, 0, src[o[0]], src[o[1]], src[o[3]]);
2184 g = APPLY_MATRIX (matrix, 1, src[o[0]], src[o[1]], src[o[3]]);
2185 b = APPLY_MATRIX (matrix, 2, src[o[0]], src[o[1]], src[o[3]]);
2187 dest[p[0]] = s_alpha;
2188 dest[p[1]] = CLAMP (r, 0, 255);
2189 dest[p[2]] = CLAMP (g, 0, 255);
2190 dest[p[3]] = CLAMP (b, 0, 255);
2195 src = src_tmp + src_stride;
2200 gst_alpha_chroma_key_packed_422_argb (const GstVideoFrame * in_frame,
2201 GstVideoFrame * out_frame, GstAlpha * alpha)
2210 gint pa = CLAMP ((gint) (alpha->alpha * 255), 0, 255);
2211 gint8 cb = alpha->cb, cr = alpha->cr;
2212 gint8 kg = alpha->kg;
2213 guint8 accept_angle_tg = alpha->accept_angle_tg;
2214 guint8 accept_angle_ctg = alpha->accept_angle_ctg;
2215 guint8 one_over_kc = alpha->one_over_kc;
2216 guint8 kfgy_scale = alpha->kfgy_scale;
2217 guint noise_level2 = alpha->noise_level2;
2220 const guint8 *src_tmp;
2223 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
2224 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
2226 width = GST_VIDEO_FRAME_WIDTH (in_frame);
2227 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
2229 src_stride = GST_VIDEO_FRAME_COMP_STRIDE (in_frame, 0);
2231 o[0] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 0);
2233 o[1] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 1);
2234 o[3] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 2);
2236 p[0] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 3);
2237 p[1] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 0);
2238 p[2] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 1);
2239 p[3] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 2);
2242 alpha->in_sdtv ? cog_ycbcr_to_rgb_matrix_8bit_sdtv :
2243 cog_ycbcr_to_rgb_matrix_8bit_hdtv, 12 * sizeof (gint));
2245 smin = 128 - alpha->black_sensitivity;
2246 smax = 128 + alpha->white_sensitivity;
2248 for (i = 0; i < height; i++) {
2251 for (j = 0; j < width - 1; j += 2) {
2253 u = src[o[1]] - 128;
2254 v = src[o[3]] - 128;
2256 a = chroma_keying_yuv (pa, &y, &u, &v, cr, cb,
2257 smin, smax, accept_angle_tg, accept_angle_ctg,
2258 one_over_kc, kfgy_scale, kg, noise_level2);
2262 r = APPLY_MATRIX (matrix, 0, y, u, v);
2263 g = APPLY_MATRIX (matrix, 1, y, u, v);
2264 b = APPLY_MATRIX (matrix, 2, y, u, v);
2267 dest[p[1]] = CLAMP (r, 0, 255);
2268 dest[p[2]] = CLAMP (g, 0, 255);
2269 dest[p[3]] = CLAMP (b, 0, 255);
2272 u = src[o[1]] - 128;
2273 v = src[o[3]] - 128;
2275 a = chroma_keying_yuv (pa, &y, &u, &v, cr, cb,
2276 smin, smax, accept_angle_tg, accept_angle_ctg,
2277 one_over_kc, kfgy_scale, kg, noise_level2);
2281 r = APPLY_MATRIX (matrix, 0, y, u, v);
2282 g = APPLY_MATRIX (matrix, 1, y, u, v);
2283 b = APPLY_MATRIX (matrix, 2, y, u, v);
2286 dest[4 + p[1]] = CLAMP (r, 0, 255);
2287 dest[4 + p[2]] = CLAMP (g, 0, 255);
2288 dest[4 + p[3]] = CLAMP (b, 0, 255);
2294 if (j == width - 1) {
2296 u = src[o[1]] - 128;
2297 v = src[o[3]] - 128;
2299 a = chroma_keying_yuv (pa, &y, &u, &v, cr, cb,
2300 smin, smax, accept_angle_tg, accept_angle_ctg,
2301 one_over_kc, kfgy_scale, kg, noise_level2);
2305 r = APPLY_MATRIX (matrix, 0, y, u, v);
2306 g = APPLY_MATRIX (matrix, 1, y, u, v);
2307 b = APPLY_MATRIX (matrix, 2, y, u, v);
2310 dest[p[1]] = CLAMP (r, 0, 255);
2311 dest[p[2]] = CLAMP (g, 0, 255);
2312 dest[p[3]] = CLAMP (b, 0, 255);
2317 src = src_tmp + src_stride;
2321 /* Protected with the alpha lock */
2323 gst_alpha_init_params (GstAlpha * alpha)
2329 const GstVideoFormatInfo *in_info, *out_info;
2332 in_info = alpha->in_info.finfo;
2333 out_info = alpha->out_info.finfo;
2335 /* RGB->RGB: convert to SDTV YUV, chroma keying, convert back
2336 * YUV->RGB: chroma keying, convert to RGB
2337 * RGB->YUV: convert to YUV, chroma keying
2338 * YUV->YUV: convert matrix, chroma keying
2340 if (GST_VIDEO_FORMAT_INFO_IS_RGB (in_info)
2341 && GST_VIDEO_FORMAT_INFO_IS_RGB (out_info))
2342 matrix = cog_rgb_to_ycbcr_matrix_8bit_sdtv;
2343 else if (GST_VIDEO_FORMAT_INFO_IS_YUV (in_info)
2344 && GST_VIDEO_FORMAT_INFO_IS_RGB (out_info))
2346 (alpha->in_sdtv) ? cog_rgb_to_ycbcr_matrix_8bit_sdtv :
2347 cog_rgb_to_ycbcr_matrix_8bit_hdtv;
2348 else if (GST_VIDEO_FORMAT_INFO_IS_RGB (in_info)
2349 && GST_VIDEO_FORMAT_INFO_IS_YUV (out_info))
2351 (alpha->out_sdtv) ? cog_rgb_to_ycbcr_matrix_8bit_sdtv :
2352 cog_rgb_to_ycbcr_matrix_8bit_hdtv;
2353 else /* yuv -> yuv */
2355 (alpha->out_sdtv) ? cog_rgb_to_ycbcr_matrix_8bit_sdtv :
2356 cog_rgb_to_ycbcr_matrix_8bit_hdtv;
2358 y = (matrix[0] * ((gint) alpha->target_r) +
2359 matrix[1] * ((gint) alpha->target_g) +
2360 matrix[2] * ((gint) alpha->target_b) + matrix[3]) >> 8;
2361 /* Cb,Cr without offset here because the chroma keying
2362 * works with them being in range [-128,127]
2365 (matrix[4] * ((gint) alpha->target_r) +
2366 matrix[5] * ((gint) alpha->target_g) +
2367 matrix[6] * ((gint) alpha->target_b)) >> 8;
2369 (matrix[8] * ((gint) alpha->target_r) +
2370 matrix[9] * ((gint) alpha->target_g) +
2371 matrix[10] * ((gint) alpha->target_b)) >> 8;
2373 kgl = sqrt (tmp1 * tmp1 + tmp2 * tmp2);
2374 alpha->cb = 127 * (tmp1 / kgl);
2375 alpha->cr = 127 * (tmp2 / kgl);
2377 tmp = 15 * tan (M_PI * alpha->angle / 180);
2378 tmp = MIN (tmp, 255);
2379 alpha->accept_angle_tg = tmp;
2380 tmp = 15 / tan (M_PI * alpha->angle / 180);
2381 tmp = MIN (tmp, 255);
2382 alpha->accept_angle_ctg = tmp;
2384 alpha->one_over_kc = 255 * 2 * tmp - 255;
2386 tmp = MIN (tmp, 255);
2387 alpha->kfgy_scale = tmp;
2388 alpha->kg = MIN (kgl, 127);
2390 alpha->noise_level2 = alpha->noise_level * alpha->noise_level;
2393 /* Protected with the alpha lock */
2395 gst_alpha_set_process_function (GstAlpha * alpha)
2397 alpha->process = NULL;
2399 switch (alpha->method) {
2400 case ALPHA_METHOD_SET:
2401 switch (GST_VIDEO_INFO_FORMAT (&alpha->out_info)) {
2402 case GST_VIDEO_FORMAT_AYUV:
2403 switch (GST_VIDEO_INFO_FORMAT (&alpha->in_info)) {
2404 case GST_VIDEO_FORMAT_AYUV:
2405 alpha->process = gst_alpha_set_ayuv_ayuv;
2407 case GST_VIDEO_FORMAT_Y444:
2408 case GST_VIDEO_FORMAT_Y42B:
2409 case GST_VIDEO_FORMAT_I420:
2410 case GST_VIDEO_FORMAT_YV12:
2411 case GST_VIDEO_FORMAT_Y41B:
2412 alpha->process = gst_alpha_set_planar_yuv_ayuv;
2414 case GST_VIDEO_FORMAT_YUY2:
2415 case GST_VIDEO_FORMAT_YVYU:
2416 case GST_VIDEO_FORMAT_UYVY:
2417 alpha->process = gst_alpha_set_packed_422_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 alpha->process = gst_alpha_set_argb_ayuv;
2425 case GST_VIDEO_FORMAT_xRGB:
2426 case GST_VIDEO_FORMAT_xBGR:
2427 case GST_VIDEO_FORMAT_RGBx:
2428 case GST_VIDEO_FORMAT_BGRx:
2429 case GST_VIDEO_FORMAT_RGB:
2430 case GST_VIDEO_FORMAT_BGR:
2431 alpha->process = gst_alpha_set_rgb_ayuv;
2437 case GST_VIDEO_FORMAT_ARGB:
2438 case GST_VIDEO_FORMAT_ABGR:
2439 case GST_VIDEO_FORMAT_RGBA:
2440 case GST_VIDEO_FORMAT_BGRA:
2441 switch (GST_VIDEO_INFO_FORMAT (&alpha->in_info)) {
2442 case GST_VIDEO_FORMAT_AYUV:
2443 alpha->process = gst_alpha_set_ayuv_argb;
2445 case GST_VIDEO_FORMAT_Y444:
2446 case GST_VIDEO_FORMAT_Y42B:
2447 case GST_VIDEO_FORMAT_I420:
2448 case GST_VIDEO_FORMAT_YV12:
2449 case GST_VIDEO_FORMAT_Y41B:
2450 alpha->process = gst_alpha_set_planar_yuv_argb;
2452 case GST_VIDEO_FORMAT_YUY2:
2453 case GST_VIDEO_FORMAT_YVYU:
2454 case GST_VIDEO_FORMAT_UYVY:
2455 alpha->process = gst_alpha_set_packed_422_argb;
2457 case GST_VIDEO_FORMAT_ARGB:
2458 case GST_VIDEO_FORMAT_ABGR:
2459 case GST_VIDEO_FORMAT_RGBA:
2460 case GST_VIDEO_FORMAT_BGRA:
2461 alpha->process = gst_alpha_set_argb_argb;
2463 case GST_VIDEO_FORMAT_xRGB:
2464 case GST_VIDEO_FORMAT_xBGR:
2465 case GST_VIDEO_FORMAT_RGBx:
2466 case GST_VIDEO_FORMAT_BGRx:
2467 case GST_VIDEO_FORMAT_RGB:
2468 case GST_VIDEO_FORMAT_BGR:
2469 alpha->process = gst_alpha_set_rgb_argb;
2480 case ALPHA_METHOD_GREEN:
2481 case ALPHA_METHOD_BLUE:
2482 case ALPHA_METHOD_CUSTOM:
2483 switch (GST_VIDEO_INFO_FORMAT (&alpha->out_info)) {
2484 case GST_VIDEO_FORMAT_AYUV:
2485 switch (GST_VIDEO_INFO_FORMAT (&alpha->in_info)) {
2486 case GST_VIDEO_FORMAT_AYUV:
2487 alpha->process = gst_alpha_chroma_key_ayuv_ayuv;
2489 case GST_VIDEO_FORMAT_Y444:
2490 case GST_VIDEO_FORMAT_Y42B:
2491 case GST_VIDEO_FORMAT_I420:
2492 case GST_VIDEO_FORMAT_YV12:
2493 case GST_VIDEO_FORMAT_Y41B:
2494 alpha->process = gst_alpha_chroma_key_planar_yuv_ayuv;
2496 case GST_VIDEO_FORMAT_YUY2:
2497 case GST_VIDEO_FORMAT_YVYU:
2498 case GST_VIDEO_FORMAT_UYVY:
2499 alpha->process = gst_alpha_chroma_key_packed_422_ayuv;
2501 case GST_VIDEO_FORMAT_ARGB:
2502 case GST_VIDEO_FORMAT_ABGR:
2503 case GST_VIDEO_FORMAT_RGBA:
2504 case GST_VIDEO_FORMAT_BGRA:
2505 alpha->process = gst_alpha_chroma_key_argb_ayuv;
2507 case GST_VIDEO_FORMAT_xRGB:
2508 case GST_VIDEO_FORMAT_xBGR:
2509 case GST_VIDEO_FORMAT_RGBx:
2510 case GST_VIDEO_FORMAT_BGRx:
2511 case GST_VIDEO_FORMAT_RGB:
2512 case GST_VIDEO_FORMAT_BGR:
2513 alpha->process = gst_alpha_chroma_key_rgb_ayuv;
2519 case GST_VIDEO_FORMAT_ARGB:
2520 case GST_VIDEO_FORMAT_ABGR:
2521 case GST_VIDEO_FORMAT_RGBA:
2522 case GST_VIDEO_FORMAT_BGRA:
2523 switch (GST_VIDEO_INFO_FORMAT (&alpha->in_info)) {
2524 case GST_VIDEO_FORMAT_AYUV:
2525 alpha->process = gst_alpha_chroma_key_ayuv_argb;
2527 case GST_VIDEO_FORMAT_Y444:
2528 case GST_VIDEO_FORMAT_Y42B:
2529 case GST_VIDEO_FORMAT_I420:
2530 case GST_VIDEO_FORMAT_YV12:
2531 case GST_VIDEO_FORMAT_Y41B:
2532 alpha->process = gst_alpha_chroma_key_planar_yuv_argb;
2534 case GST_VIDEO_FORMAT_YUY2:
2535 case GST_VIDEO_FORMAT_YVYU:
2536 case GST_VIDEO_FORMAT_UYVY:
2537 alpha->process = gst_alpha_chroma_key_packed_422_argb;
2539 case GST_VIDEO_FORMAT_ARGB:
2540 case GST_VIDEO_FORMAT_ABGR:
2541 case GST_VIDEO_FORMAT_RGBA:
2542 case GST_VIDEO_FORMAT_BGRA:
2543 alpha->process = gst_alpha_chroma_key_argb_argb;
2545 case GST_VIDEO_FORMAT_xRGB:
2546 case GST_VIDEO_FORMAT_xBGR:
2547 case GST_VIDEO_FORMAT_RGBx:
2548 case GST_VIDEO_FORMAT_BGRx:
2549 case GST_VIDEO_FORMAT_RGB:
2550 case GST_VIDEO_FORMAT_BGR:
2551 alpha->process = gst_alpha_chroma_key_rgb_argb;
2565 return alpha->process != NULL;
2569 gst_alpha_start (GstBaseTransform * btrans)
2571 GstAlpha *alpha = GST_ALPHA (btrans);
2573 GST_ALPHA_LOCK (alpha);
2574 gst_alpha_init_params (alpha);
2575 GST_ALPHA_UNLOCK (alpha);
2581 gst_alpha_before_transform (GstBaseTransform * btrans, GstBuffer * buf)
2583 GstAlpha *alpha = GST_ALPHA (btrans);
2584 GstClockTime timestamp;
2586 timestamp = gst_segment_to_stream_time (&btrans->segment, GST_FORMAT_TIME,
2587 GST_BUFFER_TIMESTAMP (buf));
2588 GST_LOG ("Got stream time of %" GST_TIME_FORMAT, GST_TIME_ARGS (timestamp));
2589 if (GST_CLOCK_TIME_IS_VALID (timestamp))
2590 gst_object_sync_values (G_OBJECT (alpha), timestamp);
2593 static GstFlowReturn
2594 gst_alpha_transform (GstBaseTransform * btrans, GstBuffer * in, GstBuffer * out)
2596 GstAlpha *alpha = GST_ALPHA (btrans);
2597 GstVideoFrame in_frame, out_frame;
2599 GST_ALPHA_LOCK (alpha);
2601 if (G_UNLIKELY (!alpha->process))
2602 goto not_negotiated;
2604 if (!gst_video_frame_map (&in_frame, &alpha->in_info, in, GST_MAP_READ))
2607 if (!gst_video_frame_map (&out_frame, &alpha->out_info, out, GST_MAP_WRITE))
2610 alpha->process (&in_frame, &out_frame, alpha);
2612 gst_video_frame_unmap (&out_frame);
2613 gst_video_frame_unmap (&in_frame);
2615 GST_ALPHA_UNLOCK (alpha);
2622 GST_ERROR_OBJECT (alpha, "Not negotiated yet");
2623 GST_ALPHA_UNLOCK (alpha);
2624 return GST_FLOW_NOT_NEGOTIATED;
2628 GST_ERROR_OBJECT (alpha, "Invalid input frame");
2629 GST_ALPHA_UNLOCK (alpha);
2634 GST_ERROR_OBJECT (alpha, "Invalid output frame");
2635 gst_video_frame_unmap (&in_frame);
2636 GST_ALPHA_UNLOCK (alpha);
2642 plugin_init (GstPlugin * plugin)
2644 gst_controller_init (NULL, NULL);
2646 return gst_element_register (plugin, "alpha", GST_RANK_NONE, GST_TYPE_ALPHA);
2649 GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
2652 "adds an alpha channel to video - constant or via chroma-keying",
2653 plugin_init, VERSION, GST_LICENSE, GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN)