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);
535 alpha->in_sdtv = in_info.colorimetry.matrix = GST_VIDEO_COLOR_MATRIX_BT601;
536 alpha->out_sdtv = out_info.colorimetry.matrix = GST_VIDEO_COLOR_MATRIX_BT601;
538 passthrough = alpha->prefer_passthrough &&
539 GST_VIDEO_INFO_FORMAT (&in_info) == GST_VIDEO_INFO_FORMAT (&out_info)
540 && alpha->in_sdtv == alpha->out_sdtv && alpha->method == ALPHA_METHOD_SET
541 && alpha->alpha == 1.0;
543 GST_DEBUG_OBJECT (alpha,
544 "Setting caps %" GST_PTR_FORMAT " -> %" GST_PTR_FORMAT
545 " (passthrough: %d)", incaps, outcaps, passthrough);
546 gst_base_transform_set_passthrough (btrans, passthrough);
548 alpha->in_info = in_info;
549 alpha->out_info = out_info;
551 if (!gst_alpha_set_process_function (alpha) && !passthrough)
554 gst_alpha_init_params (alpha);
556 GST_ALPHA_UNLOCK (alpha);
563 GST_WARNING_OBJECT (alpha,
564 "Failed to parse caps %" GST_PTR_FORMAT " -> %" GST_PTR_FORMAT, incaps,
570 GST_WARNING_OBJECT (alpha,
571 "No processing function for this caps and no passthrough mode");
572 GST_ALPHA_UNLOCK (alpha);
577 /* based on http://www.cs.utah.edu/~michael/chroma/
580 chroma_keying_yuv (gint a, gint * y, gint * u,
581 gint * v, gint cr, gint cb, gint smin, gint smax, guint8 accept_angle_tg,
582 guint8 accept_angle_ctg, guint8 one_over_kc, guint8 kfgy_scale, gint8 kg,
590 /* too dark or too bright, keep alpha */
591 if (*y < smin || *y > smax)
594 /* Convert foreground to XZ coords where X direction is defined by
596 tmp = ((*u) * cb + (*v) * cr) >> 7;
597 x = CLAMP (tmp, -128, 127);
598 tmp = ((*v) * cb - (*u) * cr) >> 7;
599 z = CLAMP (tmp, -128, 127);
601 /* WARNING: accept angle should never be set greater than "somewhat less
602 than 90 degrees" to avoid dealing with negative/infinite tg. In reality,
603 80 degrees should be enough if foreground is reasonable. If this seems
604 to be a problem, go to alternative ways of checking point position
605 (scalar product or line equations). This angle should not be too small
606 either to avoid infinite ctg (used to suppress foreground without use of
609 tmp = (x * accept_angle_tg) >> 4;
610 tmp = MIN (tmp, 127);
613 /* keep foreground Kfg = 0 */
616 /* Compute Kfg (implicitly) and Kbg, suppress foreground in XZ coord
618 tmp = (z * accept_angle_ctg) >> 4;
619 tmp = CLAMP (tmp, -128, 127);
624 tmp1 = MAX (tmp1, 0);
625 b_alpha = (tmp1 * one_over_kc) / 2;
626 b_alpha = 255 - CLAMP (b_alpha, 0, 255);
627 b_alpha = (a * b_alpha) >> 8;
629 tmp = (tmp1 * kfgy_scale) >> 4;
630 tmp1 = MIN (tmp, 255);
632 *y = (*y < tmp1) ? 0 : *y - tmp1;
634 /* Convert suppressed foreground back to CbCr */
635 tmp = (x1 * cb - y1 * cr) >> 7;
636 *u = CLAMP (tmp, -128, 127);
638 tmp = (x1 * cr + y1 * cb) >> 7;
639 *v = CLAMP (tmp, -128, 127);
641 /* Deal with noise. For now, a circle around the key color with
642 radius of noise_level treated as exact key color. Introduces
645 tmp = z * z + (x - kg) * (x - kg);
646 tmp = MIN (tmp, 0xffff);
648 if (tmp < noise_level2)
654 #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)
657 gst_alpha_set_argb_ayuv (const GstVideoFrame * in_frame,
658 GstVideoFrame * out_frame, GstAlpha * alpha)
660 gint s_alpha = CLAMP ((gint) (alpha->alpha * 256), 0, 256);
669 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
670 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
672 width = GST_VIDEO_FRAME_WIDTH (in_frame);
673 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
675 o[0] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 3);
676 o[1] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 0);
677 o[2] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 1);
678 o[3] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 2);
681 alpha->out_sdtv ? cog_rgb_to_ycbcr_matrix_8bit_sdtv :
682 cog_rgb_to_ycbcr_matrix_8bit_hdtv, 12 * sizeof (gint));
684 for (i = 0; i < height; i++) {
685 for (j = 0; j < width; j++) {
686 dest[0] = (src[o[0]] * s_alpha) >> 8;
688 y = APPLY_MATRIX (matrix, 0, src[o[1]], src[o[2]], src[o[3]]);
689 u = APPLY_MATRIX (matrix, 1, src[o[1]], src[o[2]], src[o[3]]);
690 v = APPLY_MATRIX (matrix, 2, src[o[1]], src[o[2]], src[o[3]]);
703 gst_alpha_chroma_key_argb_ayuv (const GstVideoFrame * in_frame,
704 GstVideoFrame * out_frame, GstAlpha * alpha)
713 gint pa = CLAMP ((gint) (alpha->alpha * 256), 0, 256);
714 gint8 cb = alpha->cb, cr = alpha->cr;
715 gint8 kg = alpha->kg;
716 guint8 accept_angle_tg = alpha->accept_angle_tg;
717 guint8 accept_angle_ctg = alpha->accept_angle_ctg;
718 guint8 one_over_kc = alpha->one_over_kc;
719 guint8 kfgy_scale = alpha->kfgy_scale;
720 guint noise_level2 = alpha->noise_level2;
724 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
725 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
727 width = GST_VIDEO_FRAME_WIDTH (in_frame);
728 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
730 o[0] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 3);
731 o[1] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 0);
732 o[2] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 1);
733 o[3] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 2);
735 smin = 128 - alpha->black_sensitivity;
736 smax = 128 + alpha->white_sensitivity;
739 alpha->out_sdtv ? cog_rgb_to_ycbcr_matrix_8bit_sdtv :
740 cog_rgb_to_ycbcr_matrix_8bit_hdtv, 12 * sizeof (gint));
742 for (i = 0; i < height; i++) {
743 for (j = 0; j < width; j++) {
744 a = (src[o[0]] * pa) >> 8;
749 y = APPLY_MATRIX (matrix, 0, r, g, b);
750 u = APPLY_MATRIX (matrix, 1, r, g, b) - 128;
751 v = APPLY_MATRIX (matrix, 2, r, g, b) - 128;
753 a = chroma_keying_yuv (a, &y, &u, &v, cr, cb,
754 smin, smax, accept_angle_tg, accept_angle_ctg,
755 one_over_kc, kfgy_scale, kg, noise_level2);
772 gst_alpha_set_argb_argb (const GstVideoFrame * in_frame,
773 GstVideoFrame * out_frame, GstAlpha * alpha)
778 gint s_alpha = CLAMP ((gint) (alpha->alpha * 256), 0, 256);
782 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
783 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
785 width = GST_VIDEO_FRAME_WIDTH (in_frame);
786 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
788 p[0] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 3);
789 p[1] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 0);
790 p[2] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 1);
791 p[3] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 2);
793 o[0] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 3);
794 o[1] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 0);
795 o[2] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 1);
796 o[3] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 2);
798 for (i = 0; i < height; i++) {
799 for (j = 0; j < width; j++) {
800 dest[p[0]] = (src[o[0]] * s_alpha) >> 8;
802 dest[p[1]] = src[o[1]];
803 dest[p[2]] = src[o[2]];
804 dest[p[3]] = src[o[3]];
813 gst_alpha_chroma_key_argb_argb (const GstVideoFrame * in_frame,
814 GstVideoFrame * out_frame, GstAlpha * alpha)
823 gint pa = CLAMP ((gint) (alpha->alpha * 256), 0, 256);
824 gint8 cb = alpha->cb, cr = alpha->cr;
825 gint8 kg = alpha->kg;
826 guint8 accept_angle_tg = alpha->accept_angle_tg;
827 guint8 accept_angle_ctg = alpha->accept_angle_ctg;
828 guint8 one_over_kc = alpha->one_over_kc;
829 guint8 kfgy_scale = alpha->kfgy_scale;
830 guint noise_level2 = alpha->noise_level2;
831 gint matrix[12], matrix2[12];
834 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
835 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
837 width = GST_VIDEO_FRAME_WIDTH (in_frame);
838 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
840 p[0] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 3);
841 p[1] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 0);
842 p[2] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 1);
843 p[3] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 2);
845 o[0] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 3);
846 o[1] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 0);
847 o[2] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 1);
848 o[3] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 2);
850 smin = 128 - alpha->black_sensitivity;
851 smax = 128 + alpha->white_sensitivity;
853 memcpy (matrix, cog_rgb_to_ycbcr_matrix_8bit_sdtv, 12 * sizeof (gint));
854 memcpy (matrix2, cog_ycbcr_to_rgb_matrix_8bit_sdtv, 12 * sizeof (gint));
856 for (i = 0; i < height; i++) {
857 for (j = 0; j < width; j++) {
858 a = (src[o[0]] * pa) >> 8;
863 y = APPLY_MATRIX (matrix, 0, r, g, b);
864 u = APPLY_MATRIX (matrix, 1, r, g, b) - 128;
865 v = APPLY_MATRIX (matrix, 2, r, g, b) - 128;
867 a = chroma_keying_yuv (a, &y, &u, &v, cr, cb,
868 smin, smax, accept_angle_tg, accept_angle_ctg,
869 one_over_kc, kfgy_scale, kg, noise_level2);
874 r = APPLY_MATRIX (matrix2, 0, y, u, v);
875 g = APPLY_MATRIX (matrix2, 1, y, u, v);
876 b = APPLY_MATRIX (matrix2, 2, y, u, v);
879 dest[p[1]] = CLAMP (r, 0, 255);
880 dest[p[2]] = CLAMP (g, 0, 255);
881 dest[p[3]] = CLAMP (b, 0, 255);
890 gst_alpha_set_ayuv_argb (const GstVideoFrame * in_frame,
891 GstVideoFrame * out_frame, GstAlpha * alpha)
896 gint s_alpha = CLAMP ((gint) (alpha->alpha * 256), 0, 256);
902 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
903 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
905 width = GST_VIDEO_FRAME_WIDTH (in_frame);
906 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
908 p[0] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 3);
909 p[1] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 0);
910 p[2] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 1);
911 p[3] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 2);
914 alpha->in_sdtv ? cog_ycbcr_to_rgb_matrix_8bit_sdtv :
915 cog_ycbcr_to_rgb_matrix_8bit_hdtv, 12 * sizeof (gint));
917 for (y = 0; y < height; y++) {
918 for (x = 0; x < width; x++) {
919 dest[p[0]] = (src[0] * s_alpha) >> 8;
921 r = APPLY_MATRIX (matrix, 0, src[1], src[2], src[3]);
922 g = APPLY_MATRIX (matrix, 1, src[1], src[2], src[3]);
923 b = APPLY_MATRIX (matrix, 2, src[1], src[2], src[3]);
925 dest[p[1]] = CLAMP (r, 0, 255);
926 dest[p[2]] = CLAMP (g, 0, 255);
927 dest[p[3]] = CLAMP (b, 0, 255);
936 gst_alpha_chroma_key_ayuv_argb (const GstVideoFrame * in_frame,
937 GstVideoFrame * out_frame, GstAlpha * alpha)
946 gint pa = CLAMP ((gint) (alpha->alpha * 256), 0, 256);
947 gint8 cb = alpha->cb, cr = alpha->cr;
948 gint8 kg = alpha->kg;
949 guint8 accept_angle_tg = alpha->accept_angle_tg;
950 guint8 accept_angle_ctg = alpha->accept_angle_ctg;
951 guint8 one_over_kc = alpha->one_over_kc;
952 guint8 kfgy_scale = alpha->kfgy_scale;
953 guint noise_level2 = alpha->noise_level2;
957 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
958 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
960 width = GST_VIDEO_FRAME_WIDTH (in_frame);
961 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
963 p[0] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 3);
964 p[1] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 0);
965 p[2] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 1);
966 p[3] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 2);
968 smin = 128 - alpha->black_sensitivity;
969 smax = 128 + alpha->white_sensitivity;
972 alpha->in_sdtv ? cog_ycbcr_to_rgb_matrix_8bit_sdtv :
973 cog_ycbcr_to_rgb_matrix_8bit_hdtv, 12 * sizeof (gint));
975 for (i = 0; i < height; i++) {
976 for (j = 0; j < width; j++) {
977 a = (src[0] * pa) >> 8;
982 a = chroma_keying_yuv (a, &y, &u, &v, cr, cb,
983 smin, smax, accept_angle_tg, accept_angle_ctg,
984 one_over_kc, kfgy_scale, kg, noise_level2);
989 r = APPLY_MATRIX (matrix, 0, y, u, v);
990 g = APPLY_MATRIX (matrix, 1, y, u, v);
991 b = APPLY_MATRIX (matrix, 2, y, u, v);
994 dest[p[1]] = CLAMP (r, 0, 255);
995 dest[p[2]] = CLAMP (g, 0, 255);
996 dest[p[3]] = CLAMP (b, 0, 255);
1005 gst_alpha_set_ayuv_ayuv (const GstVideoFrame * in_frame,
1006 GstVideoFrame * out_frame, GstAlpha * alpha)
1011 gint s_alpha = CLAMP ((gint) (alpha->alpha * 256), 0, 256);
1014 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
1015 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
1017 width = GST_VIDEO_FRAME_WIDTH (in_frame);
1018 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
1020 if (alpha->in_sdtv == alpha->out_sdtv) {
1021 for (y = 0; y < height; y++) {
1022 for (x = 0; x < width; x++) {
1023 dest[0] = (src[0] * s_alpha) >> 8;
1036 alpha->out_sdtv ? cog_ycbcr_hdtv_to_ycbcr_sdtv_matrix_8bit :
1037 cog_ycbcr_sdtv_to_ycbcr_hdtv_matrix_8bit, 12 * sizeof (gint));
1039 for (y = 0; y < height; y++) {
1040 for (x = 0; x < width; x++) {
1041 dest[0] = (src[0] * s_alpha) >> 8;
1042 dest[1] = APPLY_MATRIX (matrix, 0, src[1], src[2], src[3]);
1043 dest[2] = APPLY_MATRIX (matrix, 1, src[1], src[2], src[3]);
1044 dest[3] = APPLY_MATRIX (matrix, 2, src[1], src[2], src[3]);
1054 gst_alpha_chroma_key_ayuv_ayuv (const GstVideoFrame * in_frame,
1055 GstVideoFrame * out_frame, GstAlpha * alpha)
1063 gint pa = CLAMP ((gint) (alpha->alpha * 256), 0, 256);
1064 gint8 cb = alpha->cb, cr = alpha->cr;
1065 gint8 kg = alpha->kg;
1066 guint8 accept_angle_tg = alpha->accept_angle_tg;
1067 guint8 accept_angle_ctg = alpha->accept_angle_ctg;
1068 guint8 one_over_kc = alpha->one_over_kc;
1069 guint8 kfgy_scale = alpha->kfgy_scale;
1070 guint noise_level2 = alpha->noise_level2;
1072 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
1073 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
1075 width = GST_VIDEO_FRAME_WIDTH (in_frame);
1076 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
1078 smin = 128 - alpha->black_sensitivity;
1079 smax = 128 + alpha->white_sensitivity;
1081 if (alpha->in_sdtv == alpha->out_sdtv) {
1082 for (i = 0; i < height; i++) {
1083 for (j = 0; j < width; j++) {
1084 a = (src[0] * pa) >> 8;
1089 a = chroma_keying_yuv (a, &y, &u, &v, cr, cb,
1090 smin, smax, accept_angle_tg, accept_angle_ctg,
1091 one_over_kc, kfgy_scale, kg, noise_level2);
1109 alpha->out_sdtv ? cog_ycbcr_hdtv_to_ycbcr_sdtv_matrix_8bit :
1110 cog_ycbcr_sdtv_to_ycbcr_hdtv_matrix_8bit, 12 * sizeof (gint));
1112 for (i = 0; i < height; i++) {
1113 for (j = 0; j < width; j++) {
1114 a = (src[0] * pa) >> 8;
1115 y = APPLY_MATRIX (matrix, 0, src[1], src[2], src[3]);
1116 u = APPLY_MATRIX (matrix, 1, src[1], src[2], src[3]) - 128;
1117 v = APPLY_MATRIX (matrix, 2, src[1], src[2], src[3]) - 128;
1119 a = chroma_keying_yuv (a, &y, &u, &v, cr, cb,
1120 smin, smax, accept_angle_tg, accept_angle_ctg,
1121 one_over_kc, kfgy_scale, kg, noise_level2);
1139 gst_alpha_set_rgb_ayuv (const GstVideoFrame * in_frame,
1140 GstVideoFrame * out_frame, GstAlpha * alpha)
1145 gint s_alpha = CLAMP ((gint) (alpha->alpha * 255), 0, 255);
1152 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
1153 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
1155 width = GST_VIDEO_FRAME_WIDTH (in_frame);
1156 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
1158 bpp = GST_VIDEO_FRAME_COMP_PSTRIDE (in_frame, 0);
1159 o[0] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 0);
1160 o[1] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 1);
1161 o[2] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 2);
1164 alpha->out_sdtv ? cog_rgb_to_ycbcr_matrix_8bit_sdtv :
1165 cog_rgb_to_ycbcr_matrix_8bit_hdtv, 12 * sizeof (gint));
1167 for (i = 0; i < height; i++) {
1168 for (j = 0; j < width; j++) {
1171 y = APPLY_MATRIX (matrix, 0, src[o[0]], src[o[1]], src[o[2]]);
1172 u = APPLY_MATRIX (matrix, 1, src[o[0]], src[o[1]], src[o[2]]);
1173 v = APPLY_MATRIX (matrix, 2, src[o[0]], src[o[1]], src[o[2]]);
1186 gst_alpha_chroma_key_rgb_ayuv (const GstVideoFrame * in_frame,
1187 GstVideoFrame * out_frame, GstAlpha * alpha)
1196 gint pa = CLAMP ((gint) (alpha->alpha * 255), 0, 255);
1197 gint8 cb = alpha->cb, cr = alpha->cr;
1198 gint8 kg = alpha->kg;
1199 guint8 accept_angle_tg = alpha->accept_angle_tg;
1200 guint8 accept_angle_ctg = alpha->accept_angle_ctg;
1201 guint8 one_over_kc = alpha->one_over_kc;
1202 guint8 kfgy_scale = alpha->kfgy_scale;
1203 guint noise_level2 = alpha->noise_level2;
1208 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
1209 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
1211 width = GST_VIDEO_FRAME_WIDTH (in_frame);
1212 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
1214 bpp = GST_VIDEO_FRAME_COMP_PSTRIDE (in_frame, 0);
1216 o[0] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 0);
1217 o[1] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 1);
1218 o[2] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 2);
1220 smin = 128 - alpha->black_sensitivity;
1221 smax = 128 + alpha->white_sensitivity;
1224 alpha->out_sdtv ? cog_rgb_to_ycbcr_matrix_8bit_sdtv :
1225 cog_rgb_to_ycbcr_matrix_8bit_hdtv, 12 * sizeof (gint));
1227 for (i = 0; i < height; i++) {
1228 for (j = 0; j < width; j++) {
1234 y = APPLY_MATRIX (matrix, 0, r, g, b);
1235 u = APPLY_MATRIX (matrix, 1, r, g, b) - 128;
1236 v = APPLY_MATRIX (matrix, 2, r, g, b) - 128;
1238 a = chroma_keying_yuv (a, &y, &u, &v, cr, cb,
1239 smin, smax, accept_angle_tg, accept_angle_ctg,
1240 one_over_kc, kfgy_scale, kg, noise_level2);
1257 gst_alpha_set_rgb_argb (const GstVideoFrame * in_frame,
1258 GstVideoFrame * out_frame, GstAlpha * alpha)
1263 gint s_alpha = CLAMP ((gint) (alpha->alpha * 255), 0, 255);
1268 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
1269 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
1271 width = GST_VIDEO_FRAME_WIDTH (in_frame);
1272 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
1274 bpp = GST_VIDEO_FRAME_COMP_PSTRIDE (in_frame, 0);
1276 o[0] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 0);
1277 o[1] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 1);
1278 o[2] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 2);
1280 p[0] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 3);
1281 p[1] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 0);
1282 p[2] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 1);
1283 p[3] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 2);
1285 for (i = 0; i < height; i++) {
1286 for (j = 0; j < width; j++) {
1287 dest[p[0]] = s_alpha;
1289 dest[p[1]] = src[o[0]];
1290 dest[p[2]] = src[o[1]];
1291 dest[p[3]] = src[o[2]];
1300 gst_alpha_chroma_key_rgb_argb (const GstVideoFrame * in_frame,
1301 GstVideoFrame * out_frame, GstAlpha * alpha)
1310 gint pa = CLAMP ((gint) (alpha->alpha * 255), 0, 255);
1311 gint8 cb = alpha->cb, cr = alpha->cr;
1312 gint8 kg = alpha->kg;
1313 guint8 accept_angle_tg = alpha->accept_angle_tg;
1314 guint8 accept_angle_ctg = alpha->accept_angle_ctg;
1315 guint8 one_over_kc = alpha->one_over_kc;
1316 guint8 kfgy_scale = alpha->kfgy_scale;
1317 guint noise_level2 = alpha->noise_level2;
1318 gint matrix[12], matrix2[12];
1322 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
1323 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
1325 width = GST_VIDEO_FRAME_WIDTH (in_frame);
1326 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
1328 bpp = GST_VIDEO_FRAME_COMP_PSTRIDE (in_frame, 0);
1330 o[0] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 0);
1331 o[1] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 1);
1332 o[2] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 2);
1334 p[0] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 3);
1335 p[1] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 0);
1336 p[2] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 1);
1337 p[3] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 2);
1339 smin = 128 - alpha->black_sensitivity;
1340 smax = 128 + alpha->white_sensitivity;
1342 memcpy (matrix, cog_rgb_to_ycbcr_matrix_8bit_sdtv, 12 * sizeof (gint));
1343 memcpy (matrix2, cog_ycbcr_to_rgb_matrix_8bit_sdtv, 12 * sizeof (gint));
1345 for (i = 0; i < height; i++) {
1346 for (j = 0; j < width; j++) {
1352 y = APPLY_MATRIX (matrix, 0, r, g, b);
1353 u = APPLY_MATRIX (matrix, 1, r, g, b) - 128;
1354 v = APPLY_MATRIX (matrix, 2, r, g, b) - 128;
1356 a = chroma_keying_yuv (a, &y, &u, &v, cr, cb,
1357 smin, smax, accept_angle_tg, accept_angle_ctg,
1358 one_over_kc, kfgy_scale, kg, noise_level2);
1363 r = APPLY_MATRIX (matrix2, 0, y, u, v);
1364 g = APPLY_MATRIX (matrix2, 1, y, u, v);
1365 b = APPLY_MATRIX (matrix2, 2, y, u, v);
1368 dest[p[1]] = CLAMP (r, 0, 255);
1369 dest[p[2]] = CLAMP (g, 0, 255);
1370 dest[p[3]] = CLAMP (b, 0, 255);
1379 gst_alpha_set_planar_yuv_ayuv (const GstVideoFrame * in_frame,
1380 GstVideoFrame * out_frame, GstAlpha * alpha)
1385 gint b_alpha = CLAMP ((gint) (alpha->alpha * 255), 0, 255);
1386 const guint8 *srcY, *srcY_tmp;
1387 const guint8 *srcU, *srcU_tmp;
1388 const guint8 *srcV, *srcV_tmp;
1390 gint y_stride, uv_stride;
1391 gint v_subs, h_subs;
1393 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
1394 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
1396 width = GST_VIDEO_FRAME_WIDTH (in_frame);
1397 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
1399 y_stride = GST_VIDEO_FRAME_COMP_STRIDE (in_frame, 0);
1400 uv_stride = GST_VIDEO_FRAME_COMP_STRIDE (in_frame, 1);
1402 srcY_tmp = srcY = src;
1403 srcU_tmp = srcU = src + GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 1);
1404 srcV_tmp = srcV = src + GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 2);
1406 switch (GST_VIDEO_FRAME_FORMAT (in_frame)) {
1407 case GST_VIDEO_FORMAT_I420:
1408 case GST_VIDEO_FORMAT_YV12:
1409 v_subs = h_subs = 2;
1411 case GST_VIDEO_FORMAT_Y444:
1412 v_subs = h_subs = 1;
1414 case GST_VIDEO_FORMAT_Y42B:
1418 case GST_VIDEO_FORMAT_Y41B:
1423 g_assert_not_reached ();
1427 if (alpha->in_sdtv == alpha->out_sdtv) {
1428 for (i = 0; i < height; i++) {
1429 for (j = 0; j < width; j++) {
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;
1457 alpha->out_sdtv ? cog_ycbcr_hdtv_to_ycbcr_sdtv_matrix_8bit :
1458 cog_ycbcr_sdtv_to_ycbcr_hdtv_matrix_8bit, 12 * sizeof (gint));
1460 for (i = 0; i < height; i++) {
1461 for (j = 0; j < width; j++) {
1468 dest[1] = APPLY_MATRIX (matrix, 0, y, u, v);
1469 dest[2] = APPLY_MATRIX (matrix, 1, y, u, v);
1470 dest[3] = APPLY_MATRIX (matrix, 2, y, u, v);
1474 if ((j + 1) % h_subs == 0) {
1480 srcY_tmp = srcY = srcY_tmp + y_stride;
1481 if ((i + 1) % v_subs == 0) {
1482 srcU_tmp = srcU = srcU_tmp + uv_stride;
1483 srcV_tmp = srcV = srcV_tmp + uv_stride;
1493 gst_alpha_chroma_key_planar_yuv_ayuv (const GstVideoFrame * in_frame,
1494 GstVideoFrame * out_frame, GstAlpha * alpha)
1499 gint b_alpha = CLAMP ((gint) (alpha->alpha * 255), 0, 255);
1500 const guint8 *srcY, *srcY_tmp;
1501 const guint8 *srcU, *srcU_tmp;
1502 const guint8 *srcV, *srcV_tmp;
1505 gint y_stride, uv_stride;
1506 gint v_subs, h_subs;
1507 gint smin = 128 - alpha->black_sensitivity;
1508 gint smax = 128 + alpha->white_sensitivity;
1509 gint8 cb = alpha->cb, cr = alpha->cr;
1510 gint8 kg = alpha->kg;
1511 guint8 accept_angle_tg = alpha->accept_angle_tg;
1512 guint8 accept_angle_ctg = alpha->accept_angle_ctg;
1513 guint8 one_over_kc = alpha->one_over_kc;
1514 guint8 kfgy_scale = alpha->kfgy_scale;
1515 guint noise_level2 = alpha->noise_level2;
1517 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
1518 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
1520 width = GST_VIDEO_FRAME_WIDTH (in_frame);
1521 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
1523 y_stride = GST_VIDEO_FRAME_COMP_STRIDE (in_frame, 0);
1524 uv_stride = GST_VIDEO_FRAME_COMP_STRIDE (in_frame, 1);
1526 srcY_tmp = srcY = src;
1527 srcU_tmp = srcU = src + GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 1);
1528 srcV_tmp = srcV = src + GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 2);
1530 switch (GST_VIDEO_FRAME_FORMAT (in_frame)) {
1531 case GST_VIDEO_FORMAT_I420:
1532 case GST_VIDEO_FORMAT_YV12:
1533 v_subs = h_subs = 2;
1535 case GST_VIDEO_FORMAT_Y444:
1536 v_subs = h_subs = 1;
1538 case GST_VIDEO_FORMAT_Y42B:
1542 case GST_VIDEO_FORMAT_Y41B:
1547 g_assert_not_reached ();
1551 if (alpha->in_sdtv == alpha->out_sdtv) {
1552 for (i = 0; i < height; i++) {
1553 for (j = 0; j < width; j++) {
1559 a = chroma_keying_yuv (a, &y, &u, &v, cr, cb, smin,
1560 smax, accept_angle_tg, accept_angle_ctg,
1561 one_over_kc, kfgy_scale, kg, noise_level2);
1573 if ((j + 1) % h_subs == 0) {
1579 srcY_tmp = srcY = srcY_tmp + y_stride;
1580 if ((i + 1) % v_subs == 0) {
1581 srcU_tmp = srcU = srcU_tmp + uv_stride;
1582 srcV_tmp = srcV = srcV_tmp + uv_stride;
1592 alpha->out_sdtv ? cog_ycbcr_hdtv_to_ycbcr_sdtv_matrix_8bit :
1593 cog_ycbcr_sdtv_to_ycbcr_hdtv_matrix_8bit, 12 * sizeof (gint));
1595 for (i = 0; i < height; i++) {
1596 for (j = 0; j < width; j++) {
1598 y = APPLY_MATRIX (matrix, 0, srcY[0], srcU[0], srcV[0]);
1599 u = APPLY_MATRIX (matrix, 1, srcY[0], srcU[0], srcV[0]) - 128;
1600 v = APPLY_MATRIX (matrix, 2, srcY[0], srcU[0], srcV[0]) - 128;
1602 a = chroma_keying_yuv (a, &y, &u, &v, cr, cb, smin,
1603 smax, accept_angle_tg, accept_angle_ctg,
1604 one_over_kc, kfgy_scale, kg, noise_level2);
1613 if ((j + 1) % h_subs == 0) {
1619 srcY_tmp = srcY = srcY_tmp + y_stride;
1620 if ((i + 1) % v_subs == 0) {
1621 srcU_tmp = srcU = srcU_tmp + uv_stride;
1622 srcV_tmp = srcV = srcV_tmp + uv_stride;
1632 gst_alpha_set_planar_yuv_argb (const GstVideoFrame * in_frame,
1633 GstVideoFrame * out_frame, GstAlpha * alpha)
1638 gint b_alpha = CLAMP ((gint) (alpha->alpha * 255), 0, 255);
1639 const guint8 *srcY, *srcY_tmp;
1640 const guint8 *srcU, *srcU_tmp;
1641 const guint8 *srcV, *srcV_tmp;
1643 gint y_stride, uv_stride;
1644 gint v_subs, h_subs;
1650 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
1651 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
1653 width = GST_VIDEO_FRAME_WIDTH (in_frame);
1654 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
1656 p[0] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 3);
1657 p[1] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 0);
1658 p[2] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 1);
1659 p[3] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 2);
1661 y_stride = GST_VIDEO_FRAME_COMP_STRIDE (in_frame, 0);
1662 uv_stride = GST_VIDEO_FRAME_COMP_STRIDE (in_frame, 1);
1664 srcY_tmp = srcY = src;
1665 srcU_tmp = srcU = src + GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 1);
1666 srcV_tmp = srcV = src + GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 2);
1668 switch (GST_VIDEO_FRAME_FORMAT (in_frame)) {
1669 case GST_VIDEO_FORMAT_I420:
1670 case GST_VIDEO_FORMAT_YV12:
1671 v_subs = h_subs = 2;
1673 case GST_VIDEO_FORMAT_Y444:
1674 v_subs = h_subs = 1;
1676 case GST_VIDEO_FORMAT_Y42B:
1680 case GST_VIDEO_FORMAT_Y41B:
1685 g_assert_not_reached ();
1690 alpha->in_sdtv ? cog_ycbcr_to_rgb_matrix_8bit_sdtv :
1691 cog_ycbcr_to_rgb_matrix_8bit_hdtv, 12 * sizeof (gint));
1693 for (i = 0; i < height; i++) {
1694 for (j = 0; j < width; j++) {
1701 r = APPLY_MATRIX (matrix, 0, y, u, v);
1702 g = APPLY_MATRIX (matrix, 1, y, u, v);
1703 b = APPLY_MATRIX (matrix, 2, y, u, v);
1704 dest[p[1]] = CLAMP (r, 0, 255);
1705 dest[p[2]] = CLAMP (g, 0, 255);
1706 dest[p[3]] = CLAMP (b, 0, 255);
1710 if ((j + 1) % h_subs == 0) {
1716 srcY_tmp = srcY = srcY_tmp + y_stride;
1717 if ((i + 1) % v_subs == 0) {
1718 srcU_tmp = srcU = srcU_tmp + uv_stride;
1719 srcV_tmp = srcV = srcV_tmp + uv_stride;
1728 gst_alpha_chroma_key_planar_yuv_argb (const GstVideoFrame * in_frame,
1729 GstVideoFrame * out_frame, GstAlpha * alpha)
1734 gint b_alpha = CLAMP ((gint) (alpha->alpha * 255), 0, 255);
1735 const guint8 *srcY, *srcY_tmp;
1736 const guint8 *srcU, *srcU_tmp;
1737 const guint8 *srcV, *srcV_tmp;
1741 gint y_stride, uv_stride;
1742 gint v_subs, h_subs;
1743 gint smin = 128 - alpha->black_sensitivity;
1744 gint smax = 128 + alpha->white_sensitivity;
1745 gint8 cb = alpha->cb, cr = alpha->cr;
1746 gint8 kg = alpha->kg;
1747 guint8 accept_angle_tg = alpha->accept_angle_tg;
1748 guint8 accept_angle_ctg = alpha->accept_angle_ctg;
1749 guint8 one_over_kc = alpha->one_over_kc;
1750 guint8 kfgy_scale = alpha->kfgy_scale;
1751 guint noise_level2 = alpha->noise_level2;
1755 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
1756 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
1758 width = GST_VIDEO_FRAME_WIDTH (in_frame);
1759 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
1761 p[0] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 3);
1762 p[1] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 0);
1763 p[2] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 1);
1764 p[3] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 2);
1766 y_stride = GST_VIDEO_FRAME_COMP_STRIDE (in_frame, 0);
1767 uv_stride = GST_VIDEO_FRAME_COMP_STRIDE (in_frame, 1);
1769 srcY_tmp = srcY = src;
1770 srcU_tmp = srcU = src + GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 1);
1771 srcV_tmp = srcV = src + GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 2);
1773 switch (GST_VIDEO_FRAME_FORMAT (in_frame)) {
1774 case GST_VIDEO_FORMAT_I420:
1775 case GST_VIDEO_FORMAT_YV12:
1776 v_subs = h_subs = 2;
1778 case GST_VIDEO_FORMAT_Y444:
1779 v_subs = h_subs = 1;
1781 case GST_VIDEO_FORMAT_Y42B:
1785 case GST_VIDEO_FORMAT_Y41B:
1790 g_assert_not_reached ();
1795 alpha->in_sdtv ? cog_ycbcr_to_rgb_matrix_8bit_sdtv :
1796 cog_ycbcr_to_rgb_matrix_8bit_hdtv, 12 * sizeof (gint));
1798 for (i = 0; i < height; i++) {
1799 for (j = 0; j < width; j++) {
1805 a = chroma_keying_yuv (a, &y, &u, &v, cr, cb, smin,
1806 smax, accept_angle_tg, accept_angle_ctg,
1807 one_over_kc, kfgy_scale, kg, noise_level2);
1813 r = APPLY_MATRIX (matrix, 0, y, u, v);
1814 g = APPLY_MATRIX (matrix, 1, y, u, v);
1815 b = APPLY_MATRIX (matrix, 2, y, u, v);
1816 dest[p[1]] = CLAMP (r, 0, 255);
1817 dest[p[2]] = CLAMP (g, 0, 255);
1818 dest[p[3]] = CLAMP (b, 0, 255);
1822 if ((j + 1) % h_subs == 0) {
1828 srcY_tmp = srcY = srcY_tmp + y_stride;
1829 if ((i + 1) % v_subs == 0) {
1830 srcU_tmp = srcU = srcU_tmp + uv_stride;
1831 srcV_tmp = srcV = srcV_tmp + uv_stride;
1840 gst_alpha_set_packed_422_ayuv (const GstVideoFrame * in_frame,
1841 GstVideoFrame * out_frame, GstAlpha * alpha)
1846 gint s_alpha = CLAMP ((gint) (alpha->alpha * 255), 0, 255);
1849 gint p[4]; /* Y U Y V */
1851 const guint8 *src_tmp;
1853 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
1854 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
1856 width = GST_VIDEO_FRAME_WIDTH (in_frame);
1857 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
1859 src_stride = GST_VIDEO_FRAME_COMP_STRIDE (in_frame, 0);
1861 p[0] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 0);
1863 p[1] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 1);
1864 p[3] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 2);
1866 if (alpha->in_sdtv != alpha->out_sdtv) {
1870 alpha->in_sdtv ? cog_ycbcr_sdtv_to_ycbcr_hdtv_matrix_8bit :
1871 cog_ycbcr_hdtv_to_ycbcr_sdtv_matrix_8bit, 12 * sizeof (gint));
1873 for (i = 0; i < height; i++) {
1876 for (j = 0; j < width - 1; j += 2) {
1880 y = APPLY_MATRIX (matrix, 0, src[p[0]], src[p[1]], src[p[3]]);
1881 u = APPLY_MATRIX (matrix, 1, src[p[0]], src[p[1]], src[p[3]]);
1882 v = APPLY_MATRIX (matrix, 2, src[p[0]], src[p[1]], src[p[3]]);
1888 y = APPLY_MATRIX (matrix, 0, src[p[2]], src[p[1]], src[p[3]]);
1889 u = APPLY_MATRIX (matrix, 1, src[p[2]], src[p[1]], src[p[3]]);
1890 v = APPLY_MATRIX (matrix, 2, src[p[2]], src[p[1]], src[p[3]]);
1900 if (j == width - 1) {
1903 y = APPLY_MATRIX (matrix, 0, src[p[0]], src[p[1]], src[p[3]]);
1904 u = APPLY_MATRIX (matrix, 1, src[p[0]], src[p[1]], src[p[3]]);
1905 v = APPLY_MATRIX (matrix, 2, src[p[0]], src[p[1]], src[p[3]]);
1914 src = src_tmp + src_stride;
1917 for (i = 0; i < height; i++) {
1920 for (j = 0; j < width - 1; j += 2) {
1942 if (j == width - 1) {
1956 src = src_tmp + src_stride;
1962 gst_alpha_chroma_key_packed_422_ayuv (const GstVideoFrame * in_frame,
1963 GstVideoFrame * out_frame, GstAlpha * alpha)
1971 gint pa = CLAMP ((gint) (alpha->alpha * 255), 0, 255);
1972 gint8 cb = alpha->cb, cr = alpha->cr;
1973 gint8 kg = alpha->kg;
1974 guint8 accept_angle_tg = alpha->accept_angle_tg;
1975 guint8 accept_angle_ctg = alpha->accept_angle_ctg;
1976 guint8 one_over_kc = alpha->one_over_kc;
1977 guint8 kfgy_scale = alpha->kfgy_scale;
1978 guint noise_level2 = alpha->noise_level2;
1979 gint p[4]; /* Y U Y V */
1981 const guint8 *src_tmp;
1983 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
1984 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
1986 width = GST_VIDEO_FRAME_WIDTH (in_frame);
1987 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
1989 src_stride = GST_VIDEO_FRAME_COMP_STRIDE (in_frame, 0);
1991 p[0] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 0);
1993 p[1] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 1);
1994 p[3] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 2);
1996 smin = 128 - alpha->black_sensitivity;
1997 smax = 128 + alpha->white_sensitivity;
1999 if (alpha->in_sdtv != alpha->out_sdtv) {
2003 alpha->in_sdtv ? cog_ycbcr_sdtv_to_ycbcr_hdtv_matrix_8bit :
2004 cog_ycbcr_hdtv_to_ycbcr_sdtv_matrix_8bit, 12 * sizeof (gint));
2006 for (i = 0; i < height; i++) {
2009 for (j = 0; j < width - 1; j += 2) {
2010 y = APPLY_MATRIX (matrix, 0, src[p[0]], src[p[1]], src[p[3]]);
2011 u = APPLY_MATRIX (matrix, 1, src[p[0]], src[p[1]], src[p[3]]) - 128;
2012 v = APPLY_MATRIX (matrix, 2, src[p[0]], src[p[1]], src[p[3]]) - 128;
2014 a = chroma_keying_yuv (pa, &y, &u, &v, cr, cb,
2015 smin, smax, accept_angle_tg, accept_angle_ctg,
2016 one_over_kc, kfgy_scale, kg, noise_level2);
2023 y = APPLY_MATRIX (matrix, 0, src[p[2]], src[p[1]], src[p[3]]);
2024 u = APPLY_MATRIX (matrix, 1, src[p[2]], src[p[1]], src[p[3]]) - 128;
2025 v = APPLY_MATRIX (matrix, 2, src[p[2]], src[p[1]], src[p[3]]) - 128;
2027 a = chroma_keying_yuv (pa, &y, &u, &v, cr, cb,
2028 smin, smax, accept_angle_tg, accept_angle_ctg,
2029 one_over_kc, kfgy_scale, kg, noise_level2);
2040 if (j == width - 1) {
2041 y = APPLY_MATRIX (matrix, 0, src[p[0]], src[p[1]], src[p[3]]);
2042 u = APPLY_MATRIX (matrix, 1, src[p[0]], src[p[1]], src[p[3]]) - 128;
2043 v = APPLY_MATRIX (matrix, 2, src[p[0]], src[p[1]], src[p[3]]) - 128;
2045 a = chroma_keying_yuv (pa, &y, &u, &v, cr, cb,
2046 smin, smax, accept_angle_tg, accept_angle_ctg,
2047 one_over_kc, kfgy_scale, kg, noise_level2);
2057 src = src_tmp + src_stride;
2060 for (i = 0; i < height; i++) {
2063 for (j = 0; j < width - 1; j += 2) {
2065 u = src[p[1]] - 128;
2066 v = src[p[3]] - 128;
2068 a = chroma_keying_yuv (pa, &y, &u, &v, cr, cb,
2069 smin, smax, accept_angle_tg, accept_angle_ctg,
2070 one_over_kc, kfgy_scale, kg, noise_level2);
2078 u = src[p[1]] - 128;
2079 v = src[p[3]] - 128;
2081 a = chroma_keying_yuv (pa, &y, &u, &v, cr, cb,
2082 smin, smax, accept_angle_tg, accept_angle_ctg,
2083 one_over_kc, kfgy_scale, kg, noise_level2);
2094 if (j == width - 1) {
2096 u = src[p[1]] - 128;
2097 v = src[p[3]] - 128;
2099 a = chroma_keying_yuv (pa, &y, &u, &v, cr, cb,
2100 smin, smax, accept_angle_tg, accept_angle_ctg,
2101 one_over_kc, kfgy_scale, kg, noise_level2);
2111 src = src_tmp + src_stride;
2117 gst_alpha_set_packed_422_argb (const GstVideoFrame * in_frame,
2118 GstVideoFrame * out_frame, GstAlpha * alpha)
2123 gint s_alpha = CLAMP ((gint) (alpha->alpha * 255), 0, 255);
2127 const guint8 *src_tmp;
2131 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
2132 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
2134 width = GST_VIDEO_FRAME_WIDTH (in_frame);
2135 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
2137 src_stride = GST_VIDEO_FRAME_COMP_STRIDE (in_frame, 0);
2139 o[0] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 0);
2141 o[1] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 1);
2142 o[3] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 2);
2144 p[0] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 3);
2145 p[1] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 0);
2146 p[2] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 1);
2147 p[3] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 2);
2150 alpha->in_sdtv ? cog_ycbcr_to_rgb_matrix_8bit_sdtv :
2151 cog_ycbcr_to_rgb_matrix_8bit_hdtv, 12 * sizeof (gint));
2153 for (i = 0; i < height; i++) {
2156 for (j = 0; j < width - 1; j += 2) {
2157 r = APPLY_MATRIX (matrix, 0, src[o[0]], src[o[1]], src[o[3]]);
2158 g = APPLY_MATRIX (matrix, 1, src[o[0]], src[o[1]], src[o[3]]);
2159 b = APPLY_MATRIX (matrix, 2, src[o[0]], src[o[1]], src[o[3]]);
2161 dest[p[0]] = s_alpha;
2162 dest[p[1]] = CLAMP (r, 0, 255);
2163 dest[p[2]] = CLAMP (g, 0, 255);
2164 dest[p[3]] = CLAMP (b, 0, 255);
2166 r = APPLY_MATRIX (matrix, 0, src[o[2]], src[o[1]], src[o[3]]);
2167 g = APPLY_MATRIX (matrix, 1, src[o[2]], src[o[1]], src[o[3]]);
2168 b = APPLY_MATRIX (matrix, 2, src[o[2]], src[o[1]], src[o[3]]);
2170 dest[4 + p[0]] = s_alpha;
2171 dest[4 + p[1]] = CLAMP (r, 0, 255);
2172 dest[4 + p[2]] = CLAMP (g, 0, 255);
2173 dest[4 + p[3]] = CLAMP (b, 0, 255);
2179 if (j == width - 1) {
2180 r = APPLY_MATRIX (matrix, 0, src[o[0]], src[o[1]], src[o[3]]);
2181 g = APPLY_MATRIX (matrix, 1, src[o[0]], src[o[1]], src[o[3]]);
2182 b = APPLY_MATRIX (matrix, 2, src[o[0]], src[o[1]], src[o[3]]);
2184 dest[p[0]] = s_alpha;
2185 dest[p[1]] = CLAMP (r, 0, 255);
2186 dest[p[2]] = CLAMP (g, 0, 255);
2187 dest[p[3]] = CLAMP (b, 0, 255);
2192 src = src_tmp + src_stride;
2197 gst_alpha_chroma_key_packed_422_argb (const GstVideoFrame * in_frame,
2198 GstVideoFrame * out_frame, GstAlpha * alpha)
2207 gint pa = CLAMP ((gint) (alpha->alpha * 255), 0, 255);
2208 gint8 cb = alpha->cb, cr = alpha->cr;
2209 gint8 kg = alpha->kg;
2210 guint8 accept_angle_tg = alpha->accept_angle_tg;
2211 guint8 accept_angle_ctg = alpha->accept_angle_ctg;
2212 guint8 one_over_kc = alpha->one_over_kc;
2213 guint8 kfgy_scale = alpha->kfgy_scale;
2214 guint noise_level2 = alpha->noise_level2;
2217 const guint8 *src_tmp;
2220 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
2221 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
2223 width = GST_VIDEO_FRAME_WIDTH (in_frame);
2224 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
2226 src_stride = GST_VIDEO_FRAME_COMP_STRIDE (in_frame, 0);
2228 o[0] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 0);
2230 o[1] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 1);
2231 o[3] = GST_VIDEO_FRAME_COMP_OFFSET (in_frame, 2);
2233 p[0] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 3);
2234 p[1] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 0);
2235 p[2] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 1);
2236 p[3] = GST_VIDEO_FRAME_COMP_OFFSET (out_frame, 2);
2239 alpha->in_sdtv ? cog_ycbcr_to_rgb_matrix_8bit_sdtv :
2240 cog_ycbcr_to_rgb_matrix_8bit_hdtv, 12 * sizeof (gint));
2242 smin = 128 - alpha->black_sensitivity;
2243 smax = 128 + alpha->white_sensitivity;
2245 for (i = 0; i < height; i++) {
2248 for (j = 0; j < width - 1; j += 2) {
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);
2269 u = src[o[1]] - 128;
2270 v = src[o[3]] - 128;
2272 a = chroma_keying_yuv (pa, &y, &u, &v, cr, cb,
2273 smin, smax, accept_angle_tg, accept_angle_ctg,
2274 one_over_kc, kfgy_scale, kg, noise_level2);
2278 r = APPLY_MATRIX (matrix, 0, y, u, v);
2279 g = APPLY_MATRIX (matrix, 1, y, u, v);
2280 b = APPLY_MATRIX (matrix, 2, y, u, v);
2283 dest[4 + p[1]] = CLAMP (r, 0, 255);
2284 dest[4 + p[2]] = CLAMP (g, 0, 255);
2285 dest[4 + p[3]] = CLAMP (b, 0, 255);
2291 if (j == width - 1) {
2293 u = src[o[1]] - 128;
2294 v = src[o[3]] - 128;
2296 a = chroma_keying_yuv (pa, &y, &u, &v, cr, cb,
2297 smin, smax, accept_angle_tg, accept_angle_ctg,
2298 one_over_kc, kfgy_scale, kg, noise_level2);
2302 r = APPLY_MATRIX (matrix, 0, y, u, v);
2303 g = APPLY_MATRIX (matrix, 1, y, u, v);
2304 b = APPLY_MATRIX (matrix, 2, y, u, v);
2307 dest[p[1]] = CLAMP (r, 0, 255);
2308 dest[p[2]] = CLAMP (g, 0, 255);
2309 dest[p[3]] = CLAMP (b, 0, 255);
2314 src = src_tmp + src_stride;
2318 /* Protected with the alpha lock */
2320 gst_alpha_init_params (GstAlpha * alpha)
2326 const GstVideoFormatInfo *in_info, *out_info;
2329 in_info = alpha->in_info.finfo;
2330 out_info = alpha->out_info.finfo;
2332 /* RGB->RGB: convert to SDTV YUV, chroma keying, convert back
2333 * YUV->RGB: chroma keying, convert to RGB
2334 * RGB->YUV: convert to YUV, chroma keying
2335 * YUV->YUV: convert matrix, chroma keying
2337 if (GST_VIDEO_FORMAT_INFO_IS_RGB (in_info)
2338 && GST_VIDEO_FORMAT_INFO_IS_RGB (out_info))
2339 matrix = cog_rgb_to_ycbcr_matrix_8bit_sdtv;
2340 else if (GST_VIDEO_FORMAT_INFO_IS_YUV (in_info)
2341 && GST_VIDEO_FORMAT_INFO_IS_RGB (out_info))
2343 (alpha->in_sdtv) ? cog_rgb_to_ycbcr_matrix_8bit_sdtv :
2344 cog_rgb_to_ycbcr_matrix_8bit_hdtv;
2345 else if (GST_VIDEO_FORMAT_INFO_IS_RGB (in_info)
2346 && GST_VIDEO_FORMAT_INFO_IS_YUV (out_info))
2348 (alpha->out_sdtv) ? cog_rgb_to_ycbcr_matrix_8bit_sdtv :
2349 cog_rgb_to_ycbcr_matrix_8bit_hdtv;
2350 else /* yuv -> yuv */
2352 (alpha->out_sdtv) ? cog_rgb_to_ycbcr_matrix_8bit_sdtv :
2353 cog_rgb_to_ycbcr_matrix_8bit_hdtv;
2355 y = (matrix[0] * ((gint) alpha->target_r) +
2356 matrix[1] * ((gint) alpha->target_g) +
2357 matrix[2] * ((gint) alpha->target_b) + matrix[3]) >> 8;
2358 /* Cb,Cr without offset here because the chroma keying
2359 * works with them being in range [-128,127]
2362 (matrix[4] * ((gint) alpha->target_r) +
2363 matrix[5] * ((gint) alpha->target_g) +
2364 matrix[6] * ((gint) alpha->target_b)) >> 8;
2366 (matrix[8] * ((gint) alpha->target_r) +
2367 matrix[9] * ((gint) alpha->target_g) +
2368 matrix[10] * ((gint) alpha->target_b)) >> 8;
2370 kgl = sqrt (tmp1 * tmp1 + tmp2 * tmp2);
2371 alpha->cb = 127 * (tmp1 / kgl);
2372 alpha->cr = 127 * (tmp2 / kgl);
2374 tmp = 15 * tan (M_PI * alpha->angle / 180);
2375 tmp = MIN (tmp, 255);
2376 alpha->accept_angle_tg = tmp;
2377 tmp = 15 / tan (M_PI * alpha->angle / 180);
2378 tmp = MIN (tmp, 255);
2379 alpha->accept_angle_ctg = tmp;
2381 alpha->one_over_kc = 255 * 2 * tmp - 255;
2383 tmp = MIN (tmp, 255);
2384 alpha->kfgy_scale = tmp;
2385 alpha->kg = MIN (kgl, 127);
2387 alpha->noise_level2 = alpha->noise_level * alpha->noise_level;
2390 /* Protected with the alpha lock */
2392 gst_alpha_set_process_function (GstAlpha * alpha)
2394 alpha->process = NULL;
2396 switch (alpha->method) {
2397 case ALPHA_METHOD_SET:
2398 switch (GST_VIDEO_INFO_FORMAT (&alpha->out_info)) {
2399 case GST_VIDEO_FORMAT_AYUV:
2400 switch (GST_VIDEO_INFO_FORMAT (&alpha->in_info)) {
2401 case GST_VIDEO_FORMAT_AYUV:
2402 alpha->process = gst_alpha_set_ayuv_ayuv;
2404 case GST_VIDEO_FORMAT_Y444:
2405 case GST_VIDEO_FORMAT_Y42B:
2406 case GST_VIDEO_FORMAT_I420:
2407 case GST_VIDEO_FORMAT_YV12:
2408 case GST_VIDEO_FORMAT_Y41B:
2409 alpha->process = gst_alpha_set_planar_yuv_ayuv;
2411 case GST_VIDEO_FORMAT_YUY2:
2412 case GST_VIDEO_FORMAT_YVYU:
2413 case GST_VIDEO_FORMAT_UYVY:
2414 alpha->process = gst_alpha_set_packed_422_ayuv;
2416 case GST_VIDEO_FORMAT_ARGB:
2417 case GST_VIDEO_FORMAT_ABGR:
2418 case GST_VIDEO_FORMAT_RGBA:
2419 case GST_VIDEO_FORMAT_BGRA:
2420 alpha->process = gst_alpha_set_argb_ayuv;
2422 case GST_VIDEO_FORMAT_xRGB:
2423 case GST_VIDEO_FORMAT_xBGR:
2424 case GST_VIDEO_FORMAT_RGBx:
2425 case GST_VIDEO_FORMAT_BGRx:
2426 case GST_VIDEO_FORMAT_RGB:
2427 case GST_VIDEO_FORMAT_BGR:
2428 alpha->process = gst_alpha_set_rgb_ayuv;
2434 case GST_VIDEO_FORMAT_ARGB:
2435 case GST_VIDEO_FORMAT_ABGR:
2436 case GST_VIDEO_FORMAT_RGBA:
2437 case GST_VIDEO_FORMAT_BGRA:
2438 switch (GST_VIDEO_INFO_FORMAT (&alpha->in_info)) {
2439 case GST_VIDEO_FORMAT_AYUV:
2440 alpha->process = gst_alpha_set_ayuv_argb;
2442 case GST_VIDEO_FORMAT_Y444:
2443 case GST_VIDEO_FORMAT_Y42B:
2444 case GST_VIDEO_FORMAT_I420:
2445 case GST_VIDEO_FORMAT_YV12:
2446 case GST_VIDEO_FORMAT_Y41B:
2447 alpha->process = gst_alpha_set_planar_yuv_argb;
2449 case GST_VIDEO_FORMAT_YUY2:
2450 case GST_VIDEO_FORMAT_YVYU:
2451 case GST_VIDEO_FORMAT_UYVY:
2452 alpha->process = gst_alpha_set_packed_422_argb;
2454 case GST_VIDEO_FORMAT_ARGB:
2455 case GST_VIDEO_FORMAT_ABGR:
2456 case GST_VIDEO_FORMAT_RGBA:
2457 case GST_VIDEO_FORMAT_BGRA:
2458 alpha->process = gst_alpha_set_argb_argb;
2460 case GST_VIDEO_FORMAT_xRGB:
2461 case GST_VIDEO_FORMAT_xBGR:
2462 case GST_VIDEO_FORMAT_RGBx:
2463 case GST_VIDEO_FORMAT_BGRx:
2464 case GST_VIDEO_FORMAT_RGB:
2465 case GST_VIDEO_FORMAT_BGR:
2466 alpha->process = gst_alpha_set_rgb_argb;
2477 case ALPHA_METHOD_GREEN:
2478 case ALPHA_METHOD_BLUE:
2479 case ALPHA_METHOD_CUSTOM:
2480 switch (GST_VIDEO_INFO_FORMAT (&alpha->out_info)) {
2481 case GST_VIDEO_FORMAT_AYUV:
2482 switch (GST_VIDEO_INFO_FORMAT (&alpha->in_info)) {
2483 case GST_VIDEO_FORMAT_AYUV:
2484 alpha->process = gst_alpha_chroma_key_ayuv_ayuv;
2486 case GST_VIDEO_FORMAT_Y444:
2487 case GST_VIDEO_FORMAT_Y42B:
2488 case GST_VIDEO_FORMAT_I420:
2489 case GST_VIDEO_FORMAT_YV12:
2490 case GST_VIDEO_FORMAT_Y41B:
2491 alpha->process = gst_alpha_chroma_key_planar_yuv_ayuv;
2493 case GST_VIDEO_FORMAT_YUY2:
2494 case GST_VIDEO_FORMAT_YVYU:
2495 case GST_VIDEO_FORMAT_UYVY:
2496 alpha->process = gst_alpha_chroma_key_packed_422_ayuv;
2498 case GST_VIDEO_FORMAT_ARGB:
2499 case GST_VIDEO_FORMAT_ABGR:
2500 case GST_VIDEO_FORMAT_RGBA:
2501 case GST_VIDEO_FORMAT_BGRA:
2502 alpha->process = gst_alpha_chroma_key_argb_ayuv;
2504 case GST_VIDEO_FORMAT_xRGB:
2505 case GST_VIDEO_FORMAT_xBGR:
2506 case GST_VIDEO_FORMAT_RGBx:
2507 case GST_VIDEO_FORMAT_BGRx:
2508 case GST_VIDEO_FORMAT_RGB:
2509 case GST_VIDEO_FORMAT_BGR:
2510 alpha->process = gst_alpha_chroma_key_rgb_ayuv;
2516 case GST_VIDEO_FORMAT_ARGB:
2517 case GST_VIDEO_FORMAT_ABGR:
2518 case GST_VIDEO_FORMAT_RGBA:
2519 case GST_VIDEO_FORMAT_BGRA:
2520 switch (GST_VIDEO_INFO_FORMAT (&alpha->in_info)) {
2521 case GST_VIDEO_FORMAT_AYUV:
2522 alpha->process = gst_alpha_chroma_key_ayuv_argb;
2524 case GST_VIDEO_FORMAT_Y444:
2525 case GST_VIDEO_FORMAT_Y42B:
2526 case GST_VIDEO_FORMAT_I420:
2527 case GST_VIDEO_FORMAT_YV12:
2528 case GST_VIDEO_FORMAT_Y41B:
2529 alpha->process = gst_alpha_chroma_key_planar_yuv_argb;
2531 case GST_VIDEO_FORMAT_YUY2:
2532 case GST_VIDEO_FORMAT_YVYU:
2533 case GST_VIDEO_FORMAT_UYVY:
2534 alpha->process = gst_alpha_chroma_key_packed_422_argb;
2536 case GST_VIDEO_FORMAT_ARGB:
2537 case GST_VIDEO_FORMAT_ABGR:
2538 case GST_VIDEO_FORMAT_RGBA:
2539 case GST_VIDEO_FORMAT_BGRA:
2540 alpha->process = gst_alpha_chroma_key_argb_argb;
2542 case GST_VIDEO_FORMAT_xRGB:
2543 case GST_VIDEO_FORMAT_xBGR:
2544 case GST_VIDEO_FORMAT_RGBx:
2545 case GST_VIDEO_FORMAT_BGRx:
2546 case GST_VIDEO_FORMAT_RGB:
2547 case GST_VIDEO_FORMAT_BGR:
2548 alpha->process = gst_alpha_chroma_key_rgb_argb;
2562 return alpha->process != NULL;
2566 gst_alpha_start (GstBaseTransform * btrans)
2568 GstAlpha *alpha = GST_ALPHA (btrans);
2570 GST_ALPHA_LOCK (alpha);
2571 gst_alpha_init_params (alpha);
2572 GST_ALPHA_UNLOCK (alpha);
2578 gst_alpha_before_transform (GstBaseTransform * btrans, GstBuffer * buf)
2580 GstAlpha *alpha = GST_ALPHA (btrans);
2581 GstClockTime timestamp;
2583 timestamp = gst_segment_to_stream_time (&btrans->segment, GST_FORMAT_TIME,
2584 GST_BUFFER_TIMESTAMP (buf));
2585 GST_LOG ("Got stream time of %" GST_TIME_FORMAT, GST_TIME_ARGS (timestamp));
2586 if (GST_CLOCK_TIME_IS_VALID (timestamp))
2587 gst_object_sync_values (G_OBJECT (alpha), timestamp);
2590 static GstFlowReturn
2591 gst_alpha_transform (GstBaseTransform * btrans, GstBuffer * in, GstBuffer * out)
2593 GstAlpha *alpha = GST_ALPHA (btrans);
2594 GstVideoFrame in_frame, out_frame;
2596 GST_ALPHA_LOCK (alpha);
2598 if (G_UNLIKELY (!alpha->process))
2599 goto not_negotiated;
2601 if (!gst_video_frame_map (&in_frame, &alpha->in_info, in, GST_MAP_READ))
2604 if (!gst_video_frame_map (&out_frame, &alpha->out_info, out, GST_MAP_WRITE))
2607 alpha->process (&in_frame, &out_frame, alpha);
2609 gst_video_frame_unmap (&out_frame);
2610 gst_video_frame_unmap (&in_frame);
2612 GST_ALPHA_UNLOCK (alpha);
2619 GST_ERROR_OBJECT (alpha, "Not negotiated yet");
2620 GST_ALPHA_UNLOCK (alpha);
2621 return GST_FLOW_NOT_NEGOTIATED;
2625 GST_ERROR_OBJECT (alpha, "Invalid input frame");
2626 GST_ALPHA_UNLOCK (alpha);
2631 GST_ERROR_OBJECT (alpha, "Invalid output frame");
2632 gst_video_frame_unmap (&in_frame);
2633 GST_ALPHA_UNLOCK (alpha);
2639 plugin_init (GstPlugin * plugin)
2641 gst_controller_init (NULL, NULL);
2643 return gst_element_register (plugin, "alpha", GST_RANK_NONE, GST_TYPE_ALPHA);
2646 GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
2649 "adds an alpha channel to video - constant or via chroma-keying",
2650 plugin_init, VERSION, GST_LICENSE, GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN)