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=snow ! mixer.sink_0 \
34 * videotestsrc pattern=smpte75 ! alpha method=green ! mixer.sink_1 \
35 * videomixer name=mixer sink_0::zorder=0 sink_1::zorder=1 ! \
36 * videoconvert ! autovideosink
37 * ]| This pipeline adds a alpha channel to the SMPTE color bars
38 * with green as the transparent color and overlays the output on
39 * top of a snow video stream.
54 #define M_PI 3.14159265358979323846
57 /* Generated by -bad/ext/cog/generate_tables */
58 static const int cog_ycbcr_to_rgb_matrix_8bit_hdtv[] = {
60 298, -55, -136, 19681,
64 static const int cog_ycbcr_to_rgb_matrix_8bit_sdtv[] = {
66 298, -100, -208, 34707,
70 static const gint cog_rgb_to_ycbcr_matrix_8bit_hdtv[] = {
73 112, -102, -10, 32768,
76 static const gint cog_rgb_to_ycbcr_matrix_8bit_sdtv[] = {
82 static const gint cog_ycbcr_sdtv_to_ycbcr_hdtv_matrix_8bit[] = {
88 static const gint cog_ycbcr_hdtv_to_ycbcr_sdtv_matrix_8bit[] = {
94 /* Alpha signals and args */
101 #define DEFAULT_METHOD ALPHA_METHOD_SET
102 #define DEFAULT_ALPHA 1.0
103 #define DEFAULT_TARGET_R 0
104 #define DEFAULT_TARGET_G 255
105 #define DEFAULT_TARGET_B 0
106 #define DEFAULT_ANGLE 20.0
107 #define DEFAULT_NOISE_LEVEL 2.0
108 #define DEFAULT_BLACK_SENSITIVITY 100
109 #define DEFAULT_WHITE_SENSITIVITY 100
110 #define DEFAULT_PREFER_PASSTHROUGH FALSE
122 PROP_BLACK_SENSITIVITY,
123 PROP_WHITE_SENSITIVITY,
124 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_POFFSET (in_frame, 3);
641 o[1] = GST_VIDEO_FRAME_COMP_POFFSET (in_frame, 0);
642 o[2] = GST_VIDEO_FRAME_COMP_POFFSET (in_frame, 1);
643 o[3] = GST_VIDEO_FRAME_COMP_POFFSET (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_POFFSET (in_frame, 3);
696 o[1] = GST_VIDEO_FRAME_COMP_POFFSET (in_frame, 0);
697 o[2] = GST_VIDEO_FRAME_COMP_POFFSET (in_frame, 1);
698 o[3] = GST_VIDEO_FRAME_COMP_POFFSET (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_POFFSET (out_frame, 3);
754 p[1] = GST_VIDEO_FRAME_COMP_POFFSET (out_frame, 0);
755 p[2] = GST_VIDEO_FRAME_COMP_POFFSET (out_frame, 1);
756 p[3] = GST_VIDEO_FRAME_COMP_POFFSET (out_frame, 2);
758 o[0] = GST_VIDEO_FRAME_COMP_POFFSET (in_frame, 3);
759 o[1] = GST_VIDEO_FRAME_COMP_POFFSET (in_frame, 0);
760 o[2] = GST_VIDEO_FRAME_COMP_POFFSET (in_frame, 1);
761 o[3] = GST_VIDEO_FRAME_COMP_POFFSET (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_POFFSET (out_frame, 3);
806 p[1] = GST_VIDEO_FRAME_COMP_POFFSET (out_frame, 0);
807 p[2] = GST_VIDEO_FRAME_COMP_POFFSET (out_frame, 1);
808 p[3] = GST_VIDEO_FRAME_COMP_POFFSET (out_frame, 2);
810 o[0] = GST_VIDEO_FRAME_COMP_POFFSET (in_frame, 3);
811 o[1] = GST_VIDEO_FRAME_COMP_POFFSET (in_frame, 0);
812 o[2] = GST_VIDEO_FRAME_COMP_POFFSET (in_frame, 1);
813 o[3] = GST_VIDEO_FRAME_COMP_POFFSET (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_POFFSET (out_frame, 3);
874 p[1] = GST_VIDEO_FRAME_COMP_POFFSET (out_frame, 0);
875 p[2] = GST_VIDEO_FRAME_COMP_POFFSET (out_frame, 1);
876 p[3] = GST_VIDEO_FRAME_COMP_POFFSET (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_POFFSET (out_frame, 3);
929 p[1] = GST_VIDEO_FRAME_COMP_POFFSET (out_frame, 0);
930 p[2] = GST_VIDEO_FRAME_COMP_POFFSET (out_frame, 1);
931 p[3] = GST_VIDEO_FRAME_COMP_POFFSET (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_POFFSET (in_frame, 0);
1125 o[1] = GST_VIDEO_FRAME_COMP_POFFSET (in_frame, 1);
1126 o[2] = GST_VIDEO_FRAME_COMP_POFFSET (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_POFFSET (in_frame, 0);
1182 o[1] = GST_VIDEO_FRAME_COMP_POFFSET (in_frame, 1);
1183 o[2] = GST_VIDEO_FRAME_COMP_POFFSET (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_POFFSET (in_frame, 0);
1242 o[1] = GST_VIDEO_FRAME_COMP_POFFSET (in_frame, 1);
1243 o[2] = GST_VIDEO_FRAME_COMP_POFFSET (in_frame, 2);
1245 p[0] = GST_VIDEO_FRAME_COMP_POFFSET (out_frame, 3);
1246 p[1] = GST_VIDEO_FRAME_COMP_POFFSET (out_frame, 0);
1247 p[2] = GST_VIDEO_FRAME_COMP_POFFSET (out_frame, 1);
1248 p[3] = GST_VIDEO_FRAME_COMP_POFFSET (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_POFFSET (in_frame, 0);
1296 o[1] = GST_VIDEO_FRAME_COMP_POFFSET (in_frame, 1);
1297 o[2] = GST_VIDEO_FRAME_COMP_POFFSET (in_frame, 2);
1299 p[0] = GST_VIDEO_FRAME_COMP_POFFSET (out_frame, 3);
1300 p[1] = GST_VIDEO_FRAME_COMP_POFFSET (out_frame, 0);
1301 p[2] = GST_VIDEO_FRAME_COMP_POFFSET (out_frame, 1);
1302 p[3] = GST_VIDEO_FRAME_COMP_POFFSET (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)
1349 gint b_alpha = CLAMP ((gint) (alpha->alpha * 255), 0, 255);
1350 const guint8 *srcY, *srcY_tmp;
1351 const guint8 *srcU, *srcU_tmp;
1352 const guint8 *srcV, *srcV_tmp;
1354 gint y_stride, uv_stride;
1355 gint v_subs, h_subs;
1357 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
1359 width = GST_VIDEO_FRAME_WIDTH (in_frame);
1360 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
1362 y_stride = GST_VIDEO_FRAME_COMP_STRIDE (in_frame, 0);
1363 uv_stride = GST_VIDEO_FRAME_COMP_STRIDE (in_frame, 1);
1365 srcY_tmp = srcY = GST_VIDEO_FRAME_COMP_DATA (in_frame, 0);
1366 srcU_tmp = srcU = GST_VIDEO_FRAME_COMP_DATA (in_frame, 1);
1367 srcV_tmp = srcV = GST_VIDEO_FRAME_COMP_DATA (in_frame, 2);
1369 switch (GST_VIDEO_FRAME_FORMAT (in_frame)) {
1370 case GST_VIDEO_FORMAT_I420:
1371 case GST_VIDEO_FORMAT_YV12:
1372 v_subs = h_subs = 2;
1374 case GST_VIDEO_FORMAT_Y444:
1375 v_subs = h_subs = 1;
1377 case GST_VIDEO_FORMAT_Y42B:
1381 case GST_VIDEO_FORMAT_Y41B:
1386 g_assert_not_reached ();
1390 if (alpha->in_sdtv == alpha->out_sdtv) {
1391 for (i = 0; i < height; i++) {
1392 for (j = 0; j < width; j++) {
1400 if ((j + 1) % h_subs == 0) {
1406 srcY_tmp = srcY = srcY_tmp + y_stride;
1407 if ((i + 1) % v_subs == 0) {
1408 srcU_tmp = srcU = srcU_tmp + uv_stride;
1409 srcV_tmp = srcV = srcV_tmp + uv_stride;
1420 alpha->out_sdtv ? cog_ycbcr_hdtv_to_ycbcr_sdtv_matrix_8bit :
1421 cog_ycbcr_sdtv_to_ycbcr_hdtv_matrix_8bit, 12 * sizeof (gint));
1423 for (i = 0; i < height; i++) {
1424 for (j = 0; j < width; j++) {
1431 dest[1] = APPLY_MATRIX (matrix, 0, y, u, v);
1432 dest[2] = APPLY_MATRIX (matrix, 1, y, u, v);
1433 dest[3] = APPLY_MATRIX (matrix, 2, y, u, v);
1437 if ((j + 1) % h_subs == 0) {
1443 srcY_tmp = srcY = srcY_tmp + y_stride;
1444 if ((i + 1) % v_subs == 0) {
1445 srcU_tmp = srcU = srcU_tmp + uv_stride;
1446 srcV_tmp = srcV = srcV_tmp + uv_stride;
1456 gst_alpha_chroma_key_planar_yuv_ayuv (const GstVideoFrame * in_frame,
1457 GstVideoFrame * out_frame, GstAlpha * alpha)
1461 gint b_alpha = CLAMP ((gint) (alpha->alpha * 255), 0, 255);
1462 const guint8 *srcY, *srcY_tmp;
1463 const guint8 *srcU, *srcU_tmp;
1464 const guint8 *srcV, *srcV_tmp;
1467 gint y_stride, uv_stride;
1468 gint v_subs, h_subs;
1469 gint smin = 128 - alpha->black_sensitivity;
1470 gint smax = 128 + alpha->white_sensitivity;
1471 gint8 cb = alpha->cb, cr = alpha->cr;
1472 gint8 kg = alpha->kg;
1473 guint8 accept_angle_tg = alpha->accept_angle_tg;
1474 guint8 accept_angle_ctg = alpha->accept_angle_ctg;
1475 guint8 one_over_kc = alpha->one_over_kc;
1476 guint8 kfgy_scale = alpha->kfgy_scale;
1477 guint noise_level2 = alpha->noise_level2;
1479 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
1481 width = GST_VIDEO_FRAME_WIDTH (in_frame);
1482 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
1484 y_stride = GST_VIDEO_FRAME_COMP_STRIDE (in_frame, 0);
1485 uv_stride = GST_VIDEO_FRAME_COMP_STRIDE (in_frame, 1);
1487 srcY_tmp = srcY = GST_VIDEO_FRAME_COMP_DATA (in_frame, 0);
1488 srcU_tmp = srcU = GST_VIDEO_FRAME_COMP_DATA (in_frame, 1);
1489 srcV_tmp = srcV = GST_VIDEO_FRAME_COMP_DATA (in_frame, 2);
1491 switch (GST_VIDEO_FRAME_FORMAT (in_frame)) {
1492 case GST_VIDEO_FORMAT_I420:
1493 case GST_VIDEO_FORMAT_YV12:
1494 v_subs = h_subs = 2;
1496 case GST_VIDEO_FORMAT_Y444:
1497 v_subs = h_subs = 1;
1499 case GST_VIDEO_FORMAT_Y42B:
1503 case GST_VIDEO_FORMAT_Y41B:
1508 g_assert_not_reached ();
1512 if (alpha->in_sdtv == alpha->out_sdtv) {
1513 for (i = 0; i < height; i++) {
1514 for (j = 0; j < width; j++) {
1520 a = chroma_keying_yuv (a, &y, &u, &v, cr, cb, smin,
1521 smax, accept_angle_tg, accept_angle_ctg,
1522 one_over_kc, kfgy_scale, kg, noise_level2);
1534 if ((j + 1) % h_subs == 0) {
1540 srcY_tmp = srcY = srcY_tmp + y_stride;
1541 if ((i + 1) % v_subs == 0) {
1542 srcU_tmp = srcU = srcU_tmp + uv_stride;
1543 srcV_tmp = srcV = srcV_tmp + uv_stride;
1553 alpha->out_sdtv ? cog_ycbcr_hdtv_to_ycbcr_sdtv_matrix_8bit :
1554 cog_ycbcr_sdtv_to_ycbcr_hdtv_matrix_8bit, 12 * sizeof (gint));
1556 for (i = 0; i < height; i++) {
1557 for (j = 0; j < width; j++) {
1559 y = APPLY_MATRIX (matrix, 0, srcY[0], srcU[0], srcV[0]);
1560 u = APPLY_MATRIX (matrix, 1, srcY[0], srcU[0], srcV[0]) - 128;
1561 v = APPLY_MATRIX (matrix, 2, srcY[0], srcU[0], srcV[0]) - 128;
1563 a = chroma_keying_yuv (a, &y, &u, &v, cr, cb, smin,
1564 smax, accept_angle_tg, accept_angle_ctg,
1565 one_over_kc, kfgy_scale, kg, noise_level2);
1574 if ((j + 1) % h_subs == 0) {
1580 srcY_tmp = srcY = srcY_tmp + y_stride;
1581 if ((i + 1) % v_subs == 0) {
1582 srcU_tmp = srcU = srcU_tmp + uv_stride;
1583 srcV_tmp = srcV = srcV_tmp + uv_stride;
1593 gst_alpha_set_planar_yuv_argb (const GstVideoFrame * in_frame,
1594 GstVideoFrame * out_frame, GstAlpha * alpha)
1598 gint b_alpha = CLAMP ((gint) (alpha->alpha * 255), 0, 255);
1599 const guint8 *srcY, *srcY_tmp;
1600 const guint8 *srcU, *srcU_tmp;
1601 const guint8 *srcV, *srcV_tmp;
1603 gint y_stride, uv_stride;
1604 gint v_subs, h_subs;
1610 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
1612 width = GST_VIDEO_FRAME_WIDTH (in_frame);
1613 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
1615 p[0] = GST_VIDEO_FRAME_COMP_POFFSET (out_frame, 3);
1616 p[1] = GST_VIDEO_FRAME_COMP_POFFSET (out_frame, 0);
1617 p[2] = GST_VIDEO_FRAME_COMP_POFFSET (out_frame, 1);
1618 p[3] = GST_VIDEO_FRAME_COMP_POFFSET (out_frame, 2);
1620 y_stride = GST_VIDEO_FRAME_COMP_STRIDE (in_frame, 0);
1621 uv_stride = GST_VIDEO_FRAME_COMP_STRIDE (in_frame, 1);
1623 srcY_tmp = srcY = GST_VIDEO_FRAME_COMP_DATA (in_frame, 0);
1624 srcU_tmp = srcU = GST_VIDEO_FRAME_COMP_DATA (in_frame, 1);
1625 srcV_tmp = srcV = GST_VIDEO_FRAME_COMP_DATA (in_frame, 2);
1627 switch (GST_VIDEO_FRAME_FORMAT (in_frame)) {
1628 case GST_VIDEO_FORMAT_I420:
1629 case GST_VIDEO_FORMAT_YV12:
1630 v_subs = h_subs = 2;
1632 case GST_VIDEO_FORMAT_Y444:
1633 v_subs = h_subs = 1;
1635 case GST_VIDEO_FORMAT_Y42B:
1639 case GST_VIDEO_FORMAT_Y41B:
1644 g_assert_not_reached ();
1649 alpha->in_sdtv ? cog_ycbcr_to_rgb_matrix_8bit_sdtv :
1650 cog_ycbcr_to_rgb_matrix_8bit_hdtv, 12 * sizeof (gint));
1652 for (i = 0; i < height; i++) {
1653 for (j = 0; j < width; j++) {
1660 r = APPLY_MATRIX (matrix, 0, y, u, v);
1661 g = APPLY_MATRIX (matrix, 1, y, u, v);
1662 b = APPLY_MATRIX (matrix, 2, y, u, v);
1663 dest[p[1]] = CLAMP (r, 0, 255);
1664 dest[p[2]] = CLAMP (g, 0, 255);
1665 dest[p[3]] = CLAMP (b, 0, 255);
1669 if ((j + 1) % h_subs == 0) {
1675 srcY_tmp = srcY = srcY_tmp + y_stride;
1676 if ((i + 1) % v_subs == 0) {
1677 srcU_tmp = srcU = srcU_tmp + uv_stride;
1678 srcV_tmp = srcV = srcV_tmp + uv_stride;
1687 gst_alpha_chroma_key_planar_yuv_argb (const GstVideoFrame * in_frame,
1688 GstVideoFrame * out_frame, GstAlpha * alpha)
1692 gint b_alpha = CLAMP ((gint) (alpha->alpha * 255), 0, 255);
1693 const guint8 *srcY, *srcY_tmp;
1694 const guint8 *srcU, *srcU_tmp;
1695 const guint8 *srcV, *srcV_tmp;
1699 gint y_stride, uv_stride;
1700 gint v_subs, h_subs;
1701 gint smin = 128 - alpha->black_sensitivity;
1702 gint smax = 128 + alpha->white_sensitivity;
1703 gint8 cb = alpha->cb, cr = alpha->cr;
1704 gint8 kg = alpha->kg;
1705 guint8 accept_angle_tg = alpha->accept_angle_tg;
1706 guint8 accept_angle_ctg = alpha->accept_angle_ctg;
1707 guint8 one_over_kc = alpha->one_over_kc;
1708 guint8 kfgy_scale = alpha->kfgy_scale;
1709 guint noise_level2 = alpha->noise_level2;
1713 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
1715 width = GST_VIDEO_FRAME_WIDTH (in_frame);
1716 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
1718 p[0] = GST_VIDEO_FRAME_COMP_POFFSET (out_frame, 3);
1719 p[1] = GST_VIDEO_FRAME_COMP_POFFSET (out_frame, 0);
1720 p[2] = GST_VIDEO_FRAME_COMP_POFFSET (out_frame, 1);
1721 p[3] = GST_VIDEO_FRAME_COMP_POFFSET (out_frame, 2);
1723 y_stride = GST_VIDEO_FRAME_COMP_STRIDE (in_frame, 0);
1724 uv_stride = GST_VIDEO_FRAME_COMP_STRIDE (in_frame, 1);
1726 srcY_tmp = srcY = GST_VIDEO_FRAME_COMP_DATA (in_frame, 0);
1727 srcU_tmp = srcU = GST_VIDEO_FRAME_COMP_DATA (in_frame, 1);
1728 srcV_tmp = srcV = GST_VIDEO_FRAME_COMP_DATA (in_frame, 2);
1730 switch (GST_VIDEO_FRAME_FORMAT (in_frame)) {
1731 case GST_VIDEO_FORMAT_I420:
1732 case GST_VIDEO_FORMAT_YV12:
1733 v_subs = h_subs = 2;
1735 case GST_VIDEO_FORMAT_Y444:
1736 v_subs = h_subs = 1;
1738 case GST_VIDEO_FORMAT_Y42B:
1742 case GST_VIDEO_FORMAT_Y41B:
1747 g_assert_not_reached ();
1752 alpha->in_sdtv ? cog_ycbcr_to_rgb_matrix_8bit_sdtv :
1753 cog_ycbcr_to_rgb_matrix_8bit_hdtv, 12 * sizeof (gint));
1755 for (i = 0; i < height; i++) {
1756 for (j = 0; j < width; j++) {
1762 a = chroma_keying_yuv (a, &y, &u, &v, cr, cb, smin,
1763 smax, accept_angle_tg, accept_angle_ctg,
1764 one_over_kc, kfgy_scale, kg, noise_level2);
1770 r = APPLY_MATRIX (matrix, 0, y, u, v);
1771 g = APPLY_MATRIX (matrix, 1, y, u, v);
1772 b = APPLY_MATRIX (matrix, 2, y, u, v);
1773 dest[p[1]] = CLAMP (r, 0, 255);
1774 dest[p[2]] = CLAMP (g, 0, 255);
1775 dest[p[3]] = CLAMP (b, 0, 255);
1779 if ((j + 1) % h_subs == 0) {
1785 srcY_tmp = srcY = srcY_tmp + y_stride;
1786 if ((i + 1) % v_subs == 0) {
1787 srcU_tmp = srcU = srcU_tmp + uv_stride;
1788 srcV_tmp = srcV = srcV_tmp + uv_stride;
1797 gst_alpha_set_packed_422_ayuv (const GstVideoFrame * in_frame,
1798 GstVideoFrame * out_frame, GstAlpha * alpha)
1803 gint s_alpha = CLAMP ((gint) (alpha->alpha * 255), 0, 255);
1806 gint p[4]; /* Y U Y V */
1808 const guint8 *src_tmp;
1810 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
1811 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
1813 width = GST_VIDEO_FRAME_WIDTH (in_frame);
1814 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
1816 src_stride = GST_VIDEO_FRAME_COMP_STRIDE (in_frame, 0);
1818 p[0] = GST_VIDEO_FRAME_COMP_POFFSET (in_frame, 0);
1820 p[1] = GST_VIDEO_FRAME_COMP_POFFSET (in_frame, 1);
1821 p[3] = GST_VIDEO_FRAME_COMP_POFFSET (in_frame, 2);
1823 if (alpha->in_sdtv != alpha->out_sdtv) {
1827 alpha->in_sdtv ? cog_ycbcr_sdtv_to_ycbcr_hdtv_matrix_8bit :
1828 cog_ycbcr_hdtv_to_ycbcr_sdtv_matrix_8bit, 12 * sizeof (gint));
1830 for (i = 0; i < height; i++) {
1833 for (j = 0; j < width - 1; j += 2) {
1837 y = APPLY_MATRIX (matrix, 0, src[p[0]], src[p[1]], src[p[3]]);
1838 u = APPLY_MATRIX (matrix, 1, src[p[0]], src[p[1]], src[p[3]]);
1839 v = APPLY_MATRIX (matrix, 2, src[p[0]], src[p[1]], src[p[3]]);
1845 y = APPLY_MATRIX (matrix, 0, src[p[2]], src[p[1]], src[p[3]]);
1846 u = APPLY_MATRIX (matrix, 1, src[p[2]], src[p[1]], src[p[3]]);
1847 v = APPLY_MATRIX (matrix, 2, src[p[2]], src[p[1]], src[p[3]]);
1857 if (j == width - 1) {
1860 y = APPLY_MATRIX (matrix, 0, src[p[0]], src[p[1]], src[p[3]]);
1861 u = APPLY_MATRIX (matrix, 1, src[p[0]], src[p[1]], src[p[3]]);
1862 v = APPLY_MATRIX (matrix, 2, src[p[0]], src[p[1]], src[p[3]]);
1871 src = src_tmp + src_stride;
1874 for (i = 0; i < height; i++) {
1877 for (j = 0; j < width - 1; j += 2) {
1899 if (j == width - 1) {
1913 src = src_tmp + src_stride;
1919 gst_alpha_chroma_key_packed_422_ayuv (const GstVideoFrame * in_frame,
1920 GstVideoFrame * out_frame, GstAlpha * alpha)
1928 gint pa = CLAMP ((gint) (alpha->alpha * 255), 0, 255);
1929 gint8 cb = alpha->cb, cr = alpha->cr;
1930 gint8 kg = alpha->kg;
1931 guint8 accept_angle_tg = alpha->accept_angle_tg;
1932 guint8 accept_angle_ctg = alpha->accept_angle_ctg;
1933 guint8 one_over_kc = alpha->one_over_kc;
1934 guint8 kfgy_scale = alpha->kfgy_scale;
1935 guint noise_level2 = alpha->noise_level2;
1936 gint p[4]; /* Y U Y V */
1938 const guint8 *src_tmp;
1940 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
1941 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
1943 width = GST_VIDEO_FRAME_WIDTH (in_frame);
1944 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
1946 src_stride = GST_VIDEO_FRAME_COMP_STRIDE (in_frame, 0);
1948 p[0] = GST_VIDEO_FRAME_COMP_POFFSET (in_frame, 0);
1950 p[1] = GST_VIDEO_FRAME_COMP_POFFSET (in_frame, 1);
1951 p[3] = GST_VIDEO_FRAME_COMP_POFFSET (in_frame, 2);
1953 smin = 128 - alpha->black_sensitivity;
1954 smax = 128 + alpha->white_sensitivity;
1956 if (alpha->in_sdtv != alpha->out_sdtv) {
1960 alpha->in_sdtv ? cog_ycbcr_sdtv_to_ycbcr_hdtv_matrix_8bit :
1961 cog_ycbcr_hdtv_to_ycbcr_sdtv_matrix_8bit, 12 * sizeof (gint));
1963 for (i = 0; i < height; i++) {
1966 for (j = 0; j < width - 1; j += 2) {
1967 y = APPLY_MATRIX (matrix, 0, src[p[0]], src[p[1]], src[p[3]]);
1968 u = APPLY_MATRIX (matrix, 1, src[p[0]], src[p[1]], src[p[3]]) - 128;
1969 v = APPLY_MATRIX (matrix, 2, src[p[0]], src[p[1]], src[p[3]]) - 128;
1971 a = chroma_keying_yuv (pa, &y, &u, &v, cr, cb,
1972 smin, smax, accept_angle_tg, accept_angle_ctg,
1973 one_over_kc, kfgy_scale, kg, noise_level2);
1980 y = APPLY_MATRIX (matrix, 0, src[p[2]], src[p[1]], src[p[3]]);
1981 u = APPLY_MATRIX (matrix, 1, src[p[2]], src[p[1]], src[p[3]]) - 128;
1982 v = APPLY_MATRIX (matrix, 2, src[p[2]], src[p[1]], src[p[3]]) - 128;
1984 a = chroma_keying_yuv (pa, &y, &u, &v, cr, cb,
1985 smin, smax, accept_angle_tg, accept_angle_ctg,
1986 one_over_kc, kfgy_scale, kg, noise_level2);
1997 if (j == width - 1) {
1998 y = APPLY_MATRIX (matrix, 0, src[p[0]], src[p[1]], src[p[3]]);
1999 u = APPLY_MATRIX (matrix, 1, src[p[0]], src[p[1]], src[p[3]]) - 128;
2000 v = APPLY_MATRIX (matrix, 2, src[p[0]], src[p[1]], src[p[3]]) - 128;
2002 a = chroma_keying_yuv (pa, &y, &u, &v, cr, cb,
2003 smin, smax, accept_angle_tg, accept_angle_ctg,
2004 one_over_kc, kfgy_scale, kg, noise_level2);
2014 src = src_tmp + src_stride;
2017 for (i = 0; i < height; i++) {
2020 for (j = 0; j < width - 1; j += 2) {
2022 u = src[p[1]] - 128;
2023 v = src[p[3]] - 128;
2025 a = chroma_keying_yuv (pa, &y, &u, &v, cr, cb,
2026 smin, smax, accept_angle_tg, accept_angle_ctg,
2027 one_over_kc, kfgy_scale, kg, noise_level2);
2035 u = src[p[1]] - 128;
2036 v = src[p[3]] - 128;
2038 a = chroma_keying_yuv (pa, &y, &u, &v, cr, cb,
2039 smin, smax, accept_angle_tg, accept_angle_ctg,
2040 one_over_kc, kfgy_scale, kg, noise_level2);
2051 if (j == width - 1) {
2053 u = src[p[1]] - 128;
2054 v = src[p[3]] - 128;
2056 a = chroma_keying_yuv (pa, &y, &u, &v, cr, cb,
2057 smin, smax, accept_angle_tg, accept_angle_ctg,
2058 one_over_kc, kfgy_scale, kg, noise_level2);
2068 src = src_tmp + src_stride;
2074 gst_alpha_set_packed_422_argb (const GstVideoFrame * in_frame,
2075 GstVideoFrame * out_frame, GstAlpha * alpha)
2080 gint s_alpha = CLAMP ((gint) (alpha->alpha * 255), 0, 255);
2084 const guint8 *src_tmp;
2088 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
2089 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
2091 width = GST_VIDEO_FRAME_WIDTH (in_frame);
2092 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
2094 src_stride = GST_VIDEO_FRAME_COMP_STRIDE (in_frame, 0);
2096 o[0] = GST_VIDEO_FRAME_COMP_POFFSET (in_frame, 0);
2098 o[1] = GST_VIDEO_FRAME_COMP_POFFSET (in_frame, 1);
2099 o[3] = GST_VIDEO_FRAME_COMP_POFFSET (in_frame, 2);
2101 p[0] = GST_VIDEO_FRAME_COMP_POFFSET (out_frame, 3);
2102 p[1] = GST_VIDEO_FRAME_COMP_POFFSET (out_frame, 0);
2103 p[2] = GST_VIDEO_FRAME_COMP_POFFSET (out_frame, 1);
2104 p[3] = GST_VIDEO_FRAME_COMP_POFFSET (out_frame, 2);
2107 alpha->in_sdtv ? cog_ycbcr_to_rgb_matrix_8bit_sdtv :
2108 cog_ycbcr_to_rgb_matrix_8bit_hdtv, 12 * sizeof (gint));
2110 for (i = 0; i < height; i++) {
2113 for (j = 0; j < width - 1; j += 2) {
2114 r = APPLY_MATRIX (matrix, 0, src[o[0]], src[o[1]], src[o[3]]);
2115 g = APPLY_MATRIX (matrix, 1, src[o[0]], src[o[1]], src[o[3]]);
2116 b = APPLY_MATRIX (matrix, 2, src[o[0]], src[o[1]], src[o[3]]);
2118 dest[p[0]] = s_alpha;
2119 dest[p[1]] = CLAMP (r, 0, 255);
2120 dest[p[2]] = CLAMP (g, 0, 255);
2121 dest[p[3]] = CLAMP (b, 0, 255);
2123 r = APPLY_MATRIX (matrix, 0, src[o[2]], src[o[1]], src[o[3]]);
2124 g = APPLY_MATRIX (matrix, 1, src[o[2]], src[o[1]], src[o[3]]);
2125 b = APPLY_MATRIX (matrix, 2, src[o[2]], src[o[1]], src[o[3]]);
2127 dest[4 + p[0]] = s_alpha;
2128 dest[4 + p[1]] = CLAMP (r, 0, 255);
2129 dest[4 + p[2]] = CLAMP (g, 0, 255);
2130 dest[4 + p[3]] = CLAMP (b, 0, 255);
2136 if (j == width - 1) {
2137 r = APPLY_MATRIX (matrix, 0, src[o[0]], src[o[1]], src[o[3]]);
2138 g = APPLY_MATRIX (matrix, 1, src[o[0]], src[o[1]], src[o[3]]);
2139 b = APPLY_MATRIX (matrix, 2, src[o[0]], src[o[1]], src[o[3]]);
2141 dest[p[0]] = s_alpha;
2142 dest[p[1]] = CLAMP (r, 0, 255);
2143 dest[p[2]] = CLAMP (g, 0, 255);
2144 dest[p[3]] = CLAMP (b, 0, 255);
2149 src = src_tmp + src_stride;
2154 gst_alpha_chroma_key_packed_422_argb (const GstVideoFrame * in_frame,
2155 GstVideoFrame * out_frame, GstAlpha * alpha)
2164 gint pa = CLAMP ((gint) (alpha->alpha * 255), 0, 255);
2165 gint8 cb = alpha->cb, cr = alpha->cr;
2166 gint8 kg = alpha->kg;
2167 guint8 accept_angle_tg = alpha->accept_angle_tg;
2168 guint8 accept_angle_ctg = alpha->accept_angle_ctg;
2169 guint8 one_over_kc = alpha->one_over_kc;
2170 guint8 kfgy_scale = alpha->kfgy_scale;
2171 guint noise_level2 = alpha->noise_level2;
2174 const guint8 *src_tmp;
2177 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
2178 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
2180 width = GST_VIDEO_FRAME_WIDTH (in_frame);
2181 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
2183 src_stride = GST_VIDEO_FRAME_COMP_STRIDE (in_frame, 0);
2185 o[0] = GST_VIDEO_FRAME_COMP_POFFSET (in_frame, 0);
2187 o[1] = GST_VIDEO_FRAME_COMP_POFFSET (in_frame, 1);
2188 o[3] = GST_VIDEO_FRAME_COMP_POFFSET (in_frame, 2);
2190 p[0] = GST_VIDEO_FRAME_COMP_POFFSET (out_frame, 3);
2191 p[1] = GST_VIDEO_FRAME_COMP_POFFSET (out_frame, 0);
2192 p[2] = GST_VIDEO_FRAME_COMP_POFFSET (out_frame, 1);
2193 p[3] = GST_VIDEO_FRAME_COMP_POFFSET (out_frame, 2);
2196 alpha->in_sdtv ? cog_ycbcr_to_rgb_matrix_8bit_sdtv :
2197 cog_ycbcr_to_rgb_matrix_8bit_hdtv, 12 * sizeof (gint));
2199 smin = 128 - alpha->black_sensitivity;
2200 smax = 128 + alpha->white_sensitivity;
2202 for (i = 0; i < height; i++) {
2205 for (j = 0; j < width - 1; j += 2) {
2207 u = src[o[1]] - 128;
2208 v = src[o[3]] - 128;
2210 a = chroma_keying_yuv (pa, &y, &u, &v, cr, cb,
2211 smin, smax, accept_angle_tg, accept_angle_ctg,
2212 one_over_kc, kfgy_scale, kg, noise_level2);
2216 r = APPLY_MATRIX (matrix, 0, y, u, v);
2217 g = APPLY_MATRIX (matrix, 1, y, u, v);
2218 b = APPLY_MATRIX (matrix, 2, y, u, v);
2221 dest[p[1]] = CLAMP (r, 0, 255);
2222 dest[p[2]] = CLAMP (g, 0, 255);
2223 dest[p[3]] = CLAMP (b, 0, 255);
2226 u = src[o[1]] - 128;
2227 v = src[o[3]] - 128;
2229 a = chroma_keying_yuv (pa, &y, &u, &v, cr, cb,
2230 smin, smax, accept_angle_tg, accept_angle_ctg,
2231 one_over_kc, kfgy_scale, kg, noise_level2);
2235 r = APPLY_MATRIX (matrix, 0, y, u, v);
2236 g = APPLY_MATRIX (matrix, 1, y, u, v);
2237 b = APPLY_MATRIX (matrix, 2, y, u, v);
2240 dest[4 + p[1]] = CLAMP (r, 0, 255);
2241 dest[4 + p[2]] = CLAMP (g, 0, 255);
2242 dest[4 + p[3]] = CLAMP (b, 0, 255);
2248 if (j == width - 1) {
2250 u = src[o[1]] - 128;
2251 v = src[o[3]] - 128;
2253 a = chroma_keying_yuv (pa, &y, &u, &v, cr, cb,
2254 smin, smax, accept_angle_tg, accept_angle_ctg,
2255 one_over_kc, kfgy_scale, kg, noise_level2);
2259 r = APPLY_MATRIX (matrix, 0, y, u, v);
2260 g = APPLY_MATRIX (matrix, 1, y, u, v);
2261 b = APPLY_MATRIX (matrix, 2, y, u, v);
2264 dest[p[1]] = CLAMP (r, 0, 255);
2265 dest[p[2]] = CLAMP (g, 0, 255);
2266 dest[p[3]] = CLAMP (b, 0, 255);
2271 src = src_tmp + src_stride;
2275 /* Protected with the alpha lock */
2277 gst_alpha_init_params_full (GstAlpha * alpha,
2278 const GstVideoFormatInfo * in_info, const GstVideoFormatInfo * out_info)
2284 guint target_r = alpha->target_r;
2285 guint target_g = alpha->target_g;
2286 guint target_b = alpha->target_b;
2289 switch (alpha->method) {
2290 case ALPHA_METHOD_GREEN:
2295 case ALPHA_METHOD_BLUE:
2304 /* RGB->RGB: convert to SDTV YUV, chroma keying, convert back
2305 * YUV->RGB: chroma keying, convert to RGB
2306 * RGB->YUV: convert to YUV, chroma keying
2307 * YUV->YUV: convert matrix, chroma keying
2309 if (GST_VIDEO_FORMAT_INFO_IS_RGB (in_info)
2310 && GST_VIDEO_FORMAT_INFO_IS_RGB (out_info))
2311 matrix = cog_rgb_to_ycbcr_matrix_8bit_sdtv;
2312 else if (GST_VIDEO_FORMAT_INFO_IS_YUV (in_info)
2313 && GST_VIDEO_FORMAT_INFO_IS_RGB (out_info))
2315 (alpha->in_sdtv) ? cog_rgb_to_ycbcr_matrix_8bit_sdtv :
2316 cog_rgb_to_ycbcr_matrix_8bit_hdtv;
2317 else if (GST_VIDEO_FORMAT_INFO_IS_RGB (in_info)
2318 && GST_VIDEO_FORMAT_INFO_IS_YUV (out_info))
2320 (alpha->out_sdtv) ? cog_rgb_to_ycbcr_matrix_8bit_sdtv :
2321 cog_rgb_to_ycbcr_matrix_8bit_hdtv;
2322 else /* yuv -> yuv */
2324 (alpha->out_sdtv) ? cog_rgb_to_ycbcr_matrix_8bit_sdtv :
2325 cog_rgb_to_ycbcr_matrix_8bit_hdtv;
2327 y = (matrix[0] * ((gint) target_r) +
2328 matrix[1] * ((gint) target_g) +
2329 matrix[2] * ((gint) target_b) + matrix[3]) >> 8;
2330 /* Cb,Cr without offset here because the chroma keying
2331 * works with them being in range [-128,127]
2334 (matrix[4] * ((gint) target_r) +
2335 matrix[5] * ((gint) target_g) + matrix[6] * ((gint) target_b)) >> 8;
2337 (matrix[8] * ((gint) target_r) +
2338 matrix[9] * ((gint) target_g) + matrix[10] * ((gint) target_b)) >> 8;
2340 kgl = sqrt (tmp1 * tmp1 + tmp2 * tmp2);
2341 alpha->cb = 127 * (tmp1 / kgl);
2342 alpha->cr = 127 * (tmp2 / kgl);
2344 tmp = 15 * tan (M_PI * alpha->angle / 180);
2345 tmp = MIN (tmp, 255);
2346 alpha->accept_angle_tg = tmp;
2347 tmp = 15 / tan (M_PI * alpha->angle / 180);
2348 tmp = MIN (tmp, 255);
2349 alpha->accept_angle_ctg = tmp;
2351 alpha->one_over_kc = 255 * 2 * tmp - 255;
2353 tmp = MIN (tmp, 255);
2354 alpha->kfgy_scale = tmp;
2355 alpha->kg = MIN (kgl, 127);
2357 alpha->noise_level2 = alpha->noise_level * alpha->noise_level;
2361 gst_alpha_init_params (GstAlpha * alpha)
2363 const GstVideoFormatInfo *finfo_in, *finfo_out;
2365 finfo_in = GST_VIDEO_FILTER (alpha)->in_info.finfo;
2366 finfo_out = GST_VIDEO_FILTER (alpha)->out_info.finfo;
2368 if (finfo_in != NULL && finfo_out != NULL) {
2369 gst_alpha_init_params_full (alpha, finfo_in, finfo_out);
2371 GST_DEBUG_OBJECT (alpha, "video formats not set yet");
2375 /* Protected with the alpha lock */
2377 gst_alpha_set_process_function_full (GstAlpha * alpha, GstVideoInfo * in_info,
2378 GstVideoInfo * out_info)
2380 alpha->process = NULL;
2382 switch (alpha->method) {
2383 case ALPHA_METHOD_SET:
2384 switch (GST_VIDEO_INFO_FORMAT (out_info)) {
2385 case GST_VIDEO_FORMAT_AYUV:
2386 switch (GST_VIDEO_INFO_FORMAT (in_info)) {
2387 case GST_VIDEO_FORMAT_AYUV:
2388 alpha->process = gst_alpha_set_ayuv_ayuv;
2390 case GST_VIDEO_FORMAT_Y444:
2391 case GST_VIDEO_FORMAT_Y42B:
2392 case GST_VIDEO_FORMAT_I420:
2393 case GST_VIDEO_FORMAT_YV12:
2394 case GST_VIDEO_FORMAT_Y41B:
2395 alpha->process = gst_alpha_set_planar_yuv_ayuv;
2397 case GST_VIDEO_FORMAT_YUY2:
2398 case GST_VIDEO_FORMAT_YVYU:
2399 case GST_VIDEO_FORMAT_UYVY:
2400 alpha->process = gst_alpha_set_packed_422_ayuv;
2402 case GST_VIDEO_FORMAT_ARGB:
2403 case GST_VIDEO_FORMAT_ABGR:
2404 case GST_VIDEO_FORMAT_RGBA:
2405 case GST_VIDEO_FORMAT_BGRA:
2406 alpha->process = gst_alpha_set_argb_ayuv;
2408 case GST_VIDEO_FORMAT_xRGB:
2409 case GST_VIDEO_FORMAT_xBGR:
2410 case GST_VIDEO_FORMAT_RGBx:
2411 case GST_VIDEO_FORMAT_BGRx:
2412 case GST_VIDEO_FORMAT_RGB:
2413 case GST_VIDEO_FORMAT_BGR:
2414 alpha->process = gst_alpha_set_rgb_ayuv;
2420 case GST_VIDEO_FORMAT_ARGB:
2421 case GST_VIDEO_FORMAT_ABGR:
2422 case GST_VIDEO_FORMAT_RGBA:
2423 case GST_VIDEO_FORMAT_BGRA:
2424 switch (GST_VIDEO_INFO_FORMAT (in_info)) {
2425 case GST_VIDEO_FORMAT_AYUV:
2426 alpha->process = gst_alpha_set_ayuv_argb;
2428 case GST_VIDEO_FORMAT_Y444:
2429 case GST_VIDEO_FORMAT_Y42B:
2430 case GST_VIDEO_FORMAT_I420:
2431 case GST_VIDEO_FORMAT_YV12:
2432 case GST_VIDEO_FORMAT_Y41B:
2433 alpha->process = gst_alpha_set_planar_yuv_argb;
2435 case GST_VIDEO_FORMAT_YUY2:
2436 case GST_VIDEO_FORMAT_YVYU:
2437 case GST_VIDEO_FORMAT_UYVY:
2438 alpha->process = gst_alpha_set_packed_422_argb;
2440 case GST_VIDEO_FORMAT_ARGB:
2441 case GST_VIDEO_FORMAT_ABGR:
2442 case GST_VIDEO_FORMAT_RGBA:
2443 case GST_VIDEO_FORMAT_BGRA:
2444 alpha->process = gst_alpha_set_argb_argb;
2446 case GST_VIDEO_FORMAT_xRGB:
2447 case GST_VIDEO_FORMAT_xBGR:
2448 case GST_VIDEO_FORMAT_RGBx:
2449 case GST_VIDEO_FORMAT_BGRx:
2450 case GST_VIDEO_FORMAT_RGB:
2451 case GST_VIDEO_FORMAT_BGR:
2452 alpha->process = gst_alpha_set_rgb_argb;
2462 case ALPHA_METHOD_GREEN:
2463 case ALPHA_METHOD_BLUE:
2464 case ALPHA_METHOD_CUSTOM:
2465 switch (GST_VIDEO_INFO_FORMAT (out_info)) {
2466 case GST_VIDEO_FORMAT_AYUV:
2467 switch (GST_VIDEO_INFO_FORMAT (in_info)) {
2468 case GST_VIDEO_FORMAT_AYUV:
2469 alpha->process = gst_alpha_chroma_key_ayuv_ayuv;
2471 case GST_VIDEO_FORMAT_Y444:
2472 case GST_VIDEO_FORMAT_Y42B:
2473 case GST_VIDEO_FORMAT_I420:
2474 case GST_VIDEO_FORMAT_YV12:
2475 case GST_VIDEO_FORMAT_Y41B:
2476 alpha->process = gst_alpha_chroma_key_planar_yuv_ayuv;
2478 case GST_VIDEO_FORMAT_YUY2:
2479 case GST_VIDEO_FORMAT_YVYU:
2480 case GST_VIDEO_FORMAT_UYVY:
2481 alpha->process = gst_alpha_chroma_key_packed_422_ayuv;
2483 case GST_VIDEO_FORMAT_ARGB:
2484 case GST_VIDEO_FORMAT_ABGR:
2485 case GST_VIDEO_FORMAT_RGBA:
2486 case GST_VIDEO_FORMAT_BGRA:
2487 alpha->process = gst_alpha_chroma_key_argb_ayuv;
2489 case GST_VIDEO_FORMAT_xRGB:
2490 case GST_VIDEO_FORMAT_xBGR:
2491 case GST_VIDEO_FORMAT_RGBx:
2492 case GST_VIDEO_FORMAT_BGRx:
2493 case GST_VIDEO_FORMAT_RGB:
2494 case GST_VIDEO_FORMAT_BGR:
2495 alpha->process = gst_alpha_chroma_key_rgb_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 switch (GST_VIDEO_INFO_FORMAT (in_info)) {
2506 case GST_VIDEO_FORMAT_AYUV:
2507 alpha->process = gst_alpha_chroma_key_ayuv_argb;
2509 case GST_VIDEO_FORMAT_Y444:
2510 case GST_VIDEO_FORMAT_Y42B:
2511 case GST_VIDEO_FORMAT_I420:
2512 case GST_VIDEO_FORMAT_YV12:
2513 case GST_VIDEO_FORMAT_Y41B:
2514 alpha->process = gst_alpha_chroma_key_planar_yuv_argb;
2516 case GST_VIDEO_FORMAT_YUY2:
2517 case GST_VIDEO_FORMAT_YVYU:
2518 case GST_VIDEO_FORMAT_UYVY:
2519 alpha->process = gst_alpha_chroma_key_packed_422_argb;
2521 case GST_VIDEO_FORMAT_ARGB:
2522 case GST_VIDEO_FORMAT_ABGR:
2523 case GST_VIDEO_FORMAT_RGBA:
2524 case GST_VIDEO_FORMAT_BGRA:
2525 alpha->process = gst_alpha_chroma_key_argb_argb;
2527 case GST_VIDEO_FORMAT_xRGB:
2528 case GST_VIDEO_FORMAT_xBGR:
2529 case GST_VIDEO_FORMAT_RGBx:
2530 case GST_VIDEO_FORMAT_BGRx:
2531 case GST_VIDEO_FORMAT_RGB:
2532 case GST_VIDEO_FORMAT_BGR:
2533 alpha->process = gst_alpha_chroma_key_rgb_argb;
2546 return alpha->process != NULL;
2550 gst_alpha_set_process_function (GstAlpha * alpha)
2552 GstVideoInfo *info_in, *info_out;
2554 info_in = &GST_VIDEO_FILTER (alpha)->in_info;
2555 info_out = &GST_VIDEO_FILTER (alpha)->out_info;
2557 if (info_in->finfo != NULL && info_out->finfo != NULL) {
2558 gst_alpha_set_process_function_full (alpha, info_in, info_out);
2560 GST_DEBUG_OBJECT (alpha, "video formats not set yet");
2565 gst_alpha_before_transform (GstBaseTransform * btrans, GstBuffer * buf)
2567 GstAlpha *alpha = GST_ALPHA (btrans);
2568 GstClockTime timestamp;
2570 timestamp = gst_segment_to_stream_time (&btrans->segment, GST_FORMAT_TIME,
2571 GST_BUFFER_TIMESTAMP (buf));
2572 GST_LOG ("Got stream time of %" GST_TIME_FORMAT, GST_TIME_ARGS (timestamp));
2573 if (GST_CLOCK_TIME_IS_VALID (timestamp))
2574 gst_object_sync_values (GST_OBJECT (alpha), timestamp);
2577 static GstFlowReturn
2578 gst_alpha_transform_frame (GstVideoFilter * filter, GstVideoFrame * in_frame,
2579 GstVideoFrame * out_frame)
2581 GstAlpha *alpha = GST_ALPHA (filter);
2583 GST_ALPHA_LOCK (alpha);
2585 if (G_UNLIKELY (!alpha->process))
2586 goto not_negotiated;
2588 alpha->process (in_frame, out_frame, alpha);
2590 GST_ALPHA_UNLOCK (alpha);
2597 GST_ERROR_OBJECT (alpha, "Not negotiated yet");
2598 GST_ALPHA_UNLOCK (alpha);
2599 return GST_FLOW_NOT_NEGOTIATED;
2604 plugin_init (GstPlugin * plugin)
2606 return gst_element_register (plugin, "alpha", GST_RANK_NONE, GST_TYPE_ALPHA);
2609 GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
2612 "adds an alpha channel to video - constant or via chroma-keying",
2613 plugin_init, VERSION, GST_LICENSE, GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN)