blob: 82ad98167ef47aa0fbfecb423c8b7989afabceaf [file] [log] [blame]
Wim Taymans8b7c3ac2004-05-28 18:01:34 +00001/* GStreamer
2 * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
Jan Schmidte3155412008-01-31 00:00:23 +00003 * 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>
Wim Taymans8b7c3ac2004-05-28 18:01:34 +00006 *
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.
11 *
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.
16 *
17 * You should have received a copy of the GNU Library General Public
18 * License along with this library; if not, write to the
Tim-Philipp Müller230cf412012-11-04 00:07:18 +000019 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
20 * Boston, MA 02110-1301, USA.
Wim Taymans8b7c3ac2004-05-28 18:01:34 +000021 */
22
Sebastian Drögeafed9b92010-04-08 13:13:34 +020023/**
24 * SECTION:element-alpha
25 *
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.
30 *
31 * Sample pipeline:
32 * |[
Petr Viktorind089cd52016-02-28 10:12:36 +010033 * 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
Sebastian Drögeafed9b92010-04-08 13:13:34 +020037 * ]| This pipeline adds a alpha channel to the SMPTE color bars
Petr Viktorind089cd52016-02-28 10:12:36 +010038 * with green as the transparent color and overlays the output on
39 * top of a snow video stream.
Sebastian Drögeafed9b92010-04-08 13:13:34 +020040 */
41
42
Wim Taymans8b7c3ac2004-05-28 18:01:34 +000043#ifdef HAVE_CONFIG_H
44#include "config.h"
45#endif
Sebastian Dröge322a8f52010-03-15 19:07:28 +010046
47#include "gstalpha.h"
Wim Taymans8b7c3ac2004-05-28 18:01:34 +000048
Peter Kjellerstedtb234d9b2006-09-25 11:47:42 +000049#include <stdlib.h>
Wim Taymans8b7c3ac2004-05-28 18:01:34 +000050#include <string.h>
Wim Taymans2cf37532004-11-04 17:15:19 +000051#include <math.h>
Wim Taymans8b7c3ac2004-05-28 18:01:34 +000052
Sébastien Moutte0debb1e2006-03-30 23:37:16 +000053#ifndef M_PI
54#define M_PI 3.14159265358979323846
55#endif
56
Sebastian Dröge6b0c5352010-03-19 18:11:12 +010057/* Generated by -bad/ext/cog/generate_tables */
58static const int cog_ycbcr_to_rgb_matrix_8bit_hdtv[] = {
59 298, 0, 459, -63514,
60 298, -55, -136, 19681,
61 298, 541, 0, -73988,
62};
63
64static const int cog_ycbcr_to_rgb_matrix_8bit_sdtv[] = {
65 298, 0, 409, -57068,
66 298, -100, -208, 34707,
67 298, 516, 0, -70870,
68};
69
70static const gint cog_rgb_to_ycbcr_matrix_8bit_hdtv[] = {
71 47, 157, 16, 4096,
72 -26, -87, 112, 32768,
73 112, -102, -10, 32768,
74};
75
76static const gint cog_rgb_to_ycbcr_matrix_8bit_sdtv[] = {
77 66, 129, 25, 4096,
78 -38, -74, 112, 32768,
79 112, -94, -18, 32768,
80};
81
82static const gint cog_ycbcr_sdtv_to_ycbcr_hdtv_matrix_8bit[] = {
83 256, -30, -53, 10600,
84 0, 261, 29, -4367,
85 0, 19, 262, -3289,
86};
87
88static const gint cog_ycbcr_hdtv_to_ycbcr_sdtv_matrix_8bit[] = {
89 256, 25, 49, -9536,
90 0, 253, -28, 3958,
91 0, -19, 252, 2918,
92};
93
Wim Taymans8b7c3ac2004-05-28 18:01:34 +000094/* Alpha signals and args */
95enum
96{
97 /* FILL ME */
98 LAST_SIGNAL
99};
100
Wim Taymans71ebb152004-11-08 16:16:10 +0000101#define DEFAULT_METHOD ALPHA_METHOD_SET
Wim Taymans2cf37532004-11-04 17:15:19 +0000102#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
Sebastian Keller4ffab082008-05-29 11:30:16 +0000108#define DEFAULT_BLACK_SENSITIVITY 100
109#define DEFAULT_WHITE_SENSITIVITY 100
Sebastian Drögeab3b4bc2010-05-26 13:13:44 +0200110#define DEFAULT_PREFER_PASSTHROUGH FALSE
Wim Taymans2cf37532004-11-04 17:15:19 +0000111
Wim Taymans8b7c3ac2004-05-28 18:01:34 +0000112enum
113{
Sebastian Keller4ffab082008-05-29 11:30:16 +0000114 PROP_0,
115 PROP_METHOD,
116 PROP_ALPHA,
117 PROP_TARGET_R,
118 PROP_TARGET_G,
119 PROP_TARGET_B,
120 PROP_ANGLE,
121 PROP_NOISE_LEVEL,
122 PROP_BLACK_SENSITIVITY,
123 PROP_WHITE_SENSITIVITY,
Luis de Bethencourt671b4d22015-04-24 17:01:10 +0100124 PROP_PREFER_PASSTHROUGH
Wim Taymans8b7c3ac2004-05-28 18:01:34 +0000125};
126
127static GstStaticPadTemplate gst_alpha_src_template =
Wim Taymans476e2182011-07-04 16:09:33 +0200128GST_STATIC_PAD_TEMPLATE ("src",
Wim Taymans8b7c3ac2004-05-28 18:01:34 +0000129 GST_PAD_SRC,
130 GST_PAD_ALWAYS,
Wim Taymans476e2182011-07-04 16:09:33 +0200131 GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE ("{ AYUV, "
132 "ARGB, BGRA, ABGR, RGBA, Y444, xRGB, BGRx, xBGR, "
Wim Taymans99c10252011-07-04 18:10:55 +0200133 "RGBx, RGB, BGR, Y42B, YUY2, YVYU, UYVY, I420, YV12, Y41B } "))
Wim Taymans8b7c3ac2004-05-28 18:01:34 +0000134 );
135
136static GstStaticPadTemplate gst_alpha_sink_template =
Wim Taymans476e2182011-07-04 16:09:33 +0200137GST_STATIC_PAD_TEMPLATE ("sink",
Wim Taymans8b7c3ac2004-05-28 18:01:34 +0000138 GST_PAD_SINK,
139 GST_PAD_ALWAYS,
Wim Taymans476e2182011-07-04 16:09:33 +0200140 GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE ("{ AYUV, "
141 "ARGB, BGRA, ABGR, RGBA, Y444, xRGB, BGRx, xBGR, "
Wim Taymans99c10252011-07-04 18:10:55 +0200142 "RGBx, RGB, BGR, Y42B, YUY2, YVYU, UYVY, I420, YV12, " "Y41B } "))
Wim Taymans8b7c3ac2004-05-28 18:01:34 +0000143 );
144
Sebastian Drögeab3b4bc2010-05-26 13:13:44 +0200145static GstStaticCaps gst_alpha_alpha_caps =
Wim Taymans476e2182011-07-04 16:09:33 +0200146GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE ("{ AYUV, ARGB, BGRA, ABGR, RGBA }"));
Sebastian Drögeab3b4bc2010-05-26 13:13:44 +0200147
Tim-Philipp Müllerf60eb9a2011-12-12 02:31:36 +0000148/* FIXME: why do we need our own lock for this? */
Tim-Philipp Müllerf60eb9a2011-12-12 02:31:36 +0000149#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 ()); \
153} G_STMT_END
154
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); \
158} G_STMT_END
Sebastian Drögeab3b4bc2010-05-26 13:13:44 +0200159
Jan Schmidte3155412008-01-31 00:00:23 +0000160static GstCaps *gst_alpha_transform_caps (GstBaseTransform * btrans,
Edward Hervey75056542011-06-07 11:20:00 +0200161 GstPadDirection direction, GstCaps * caps, GstCaps * filter);
Sebastian Drögeab3b4bc2010-05-26 13:13:44 +0200162static void gst_alpha_before_transform (GstBaseTransform * btrans,
163 GstBuffer * buf);
Wim Taymans8b7c3ac2004-05-28 18:01:34 +0000164
Wim Taymans22146572011-12-21 23:51:03 +0100165static gboolean gst_alpha_set_info (GstVideoFilter * filter,
166 GstCaps * incaps, GstVideoInfo * in_info, GstCaps * outcaps,
167 GstVideoInfo * out_info);
168static GstFlowReturn gst_alpha_transform_frame (GstVideoFilter * filter,
169 GstVideoFrame * in_frame, GstVideoFrame * out_frame);
170
Edward Hervey4b2a0ab2012-01-04 13:25:40 +0100171static void gst_alpha_init_params_full (GstAlpha * alpha,
172 const GstVideoFormatInfo * in_info, const GstVideoFormatInfo * out_info);
Wim Taymans2cf37532004-11-04 17:15:19 +0000173static void gst_alpha_init_params (GstAlpha * alpha);
Tim-Philipp Müllerb072c782012-04-30 23:57:28 +0100174static void gst_alpha_set_process_function (GstAlpha * alpha);
Edward Hervey4b2a0ab2012-01-04 13:25:40 +0100175static gboolean gst_alpha_set_process_function_full (GstAlpha * alpha,
176 GstVideoInfo * in_info, GstVideoInfo * out_info);
Wim Taymans8b7c3ac2004-05-28 18:01:34 +0000177
178static void gst_alpha_set_property (GObject * object, guint prop_id,
179 const GValue * value, GParamSpec * pspec);
180static void gst_alpha_get_property (GObject * object, guint prop_id,
181 GValue * value, GParamSpec * pspec);
Sebastian Drögeab3b4bc2010-05-26 13:13:44 +0200182static void gst_alpha_finalize (GObject * object);
Wim Taymans8b7c3ac2004-05-28 18:01:34 +0000183
Wim Taymans237ca162011-04-25 12:49:36 +0200184#define gst_alpha_parent_class parent_class
185G_DEFINE_TYPE (GstAlpha, gst_alpha, GST_TYPE_VIDEO_FILTER);
Wim Taymans8b7c3ac2004-05-28 18:01:34 +0000186
187#define GST_TYPE_ALPHA_METHOD (gst_alpha_method_get_type())
188static GType
189gst_alpha_method_get_type (void)
190{
191 static GType alpha_method_type = 0;
Tim-Philipp Müller11cb7a32006-05-10 10:29:54 +0000192 static const GEnumValue alpha_method[] = {
Thomas Vander Stichele842a43f2005-11-22 18:11:58 +0000193 {ALPHA_METHOD_SET, "Set/adjust alpha channel", "set"},
Jean-François Fortin Tamf5cb19e2013-02-21 11:15:23 -0500194 {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"},
Wim Taymans8b7c3ac2004-05-28 18:01:34 +0000197 {0, NULL, NULL},
198 };
199
200 if (!alpha_method_type) {
201 alpha_method_type = g_enum_register_static ("GstAlphaMethod", alpha_method);
202 }
203 return alpha_method_type;
204}
205
Wim Taymans8b7c3ac2004-05-28 18:01:34 +0000206static void
Wim Taymans8b7c3ac2004-05-28 18:01:34 +0000207gst_alpha_class_init (GstAlphaClass * klass)
208{
Sebastian Dröge322a8f52010-03-15 19:07:28 +0100209 GObjectClass *gobject_class = (GObjectClass *) klass;
Wim Taymans237ca162011-04-25 12:49:36 +0200210 GstElementClass *gstelement_class = (GstElementClass *) klass;
Sebastian Dröge322a8f52010-03-15 19:07:28 +0100211 GstBaseTransformClass *btrans_class = (GstBaseTransformClass *) klass;
Wim Taymans22146572011-12-21 23:51:03 +0100212 GstVideoFilterClass *vfilter_class = (GstVideoFilterClass *) klass;
Wim Taymans8b7c3ac2004-05-28 18:01:34 +0000213
Wim Taymans237ca162011-04-25 12:49:36 +0200214 GST_DEBUG_CATEGORY_INIT (gst_alpha_debug, "alpha", 0,
215 "alpha - Element for adding alpha channel to streams");
216
Wim Taymans97f9bab2005-05-17 18:13:19 +0000217 gobject_class->set_property = gst_alpha_set_property;
218 gobject_class->get_property = gst_alpha_get_property;
Sebastian Drögeab3b4bc2010-05-26 13:13:44 +0200219 gobject_class->finalize = gst_alpha_finalize;
Wim Taymans97f9bab2005-05-17 18:13:19 +0000220
Sebastian Keller4ffab082008-05-29 11:30:16 +0000221 g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_METHOD,
Wim Taymans8b7c3ac2004-05-28 18:01:34 +0000222 g_param_spec_enum ("method", "Method",
223 "How the alpha channels should be created", GST_TYPE_ALPHA_METHOD,
Sebastian Dröge322a8f52010-03-15 19:07:28 +0100224 DEFAULT_METHOD, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
Sebastian Keller4ffab082008-05-29 11:30:16 +0000225 g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_ALPHA,
Wim Taymans8b7c3ac2004-05-28 18:01:34 +0000226 g_param_spec_double ("alpha", "Alpha", "The value for the alpha channel",
Edward Hervey7f27c4a2008-01-09 12:01:14 +0000227 0.0, 1.0, DEFAULT_ALPHA,
Sebastian Dröge322a8f52010-03-15 19:07:28 +0100228 G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
Sebastian Keller4ffab082008-05-29 11:30:16 +0000229 g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_TARGET_R,
Jean-François Fortin Tamf5cb19e2013-02-21 11:15:23 -0500230 g_param_spec_uint ("target-r", "Target Red",
231 "The red color value for custom RGB chroma keying", 0, 255,
Edward Hervey7f27c4a2008-01-09 12:01:14 +0000232 DEFAULT_TARGET_R,
Sebastian Dröge322a8f52010-03-15 19:07:28 +0100233 G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
Sebastian Keller4ffab082008-05-29 11:30:16 +0000234 g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_TARGET_G,
Jean-François Fortin Tamf5cb19e2013-02-21 11:15:23 -0500235 g_param_spec_uint ("target-g", "Target Green",
236 "The green color value for custom RGB chroma keying", 0, 255,
Edward Hervey7f27c4a2008-01-09 12:01:14 +0000237 DEFAULT_TARGET_G,
Sebastian Dröge322a8f52010-03-15 19:07:28 +0100238 G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
Sebastian Keller4ffab082008-05-29 11:30:16 +0000239 g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_TARGET_B,
Jean-François Fortin Tamf5cb19e2013-02-21 11:15:23 -0500240 g_param_spec_uint ("target-b", "Target Blue",
241 "The blue color value for custom RGB chroma keying", 0, 255,
Edward Hervey7f27c4a2008-01-09 12:01:14 +0000242 DEFAULT_TARGET_B,
Sebastian Dröge322a8f52010-03-15 19:07:28 +0100243 G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
Sebastian Keller4ffab082008-05-29 11:30:16 +0000244 g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_ANGLE,
Wim Taymans2cf37532004-11-04 17:15:19 +0000245 g_param_spec_float ("angle", "Angle", "Size of the colorcube to change",
Edward Hervey7f27c4a2008-01-09 12:01:14 +0000246 0.0, 90.0, DEFAULT_ANGLE,
Sebastian Dröge322a8f52010-03-15 19:07:28 +0100247 G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
Sebastian Keller4ffab082008-05-29 11:30:16 +0000248 g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_NOISE_LEVEL,
Sebastian Dröge322a8f52010-03-15 19:07:28 +0100249 g_param_spec_float ("noise-level", "Noise Level", "Size of noise radius",
Edward Hervey7f27c4a2008-01-09 12:01:14 +0000250 0.0, 64.0, DEFAULT_NOISE_LEVEL,
Sebastian Dröge322a8f52010-03-15 19:07:28 +0100251 G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
Sebastian Keller4ffab082008-05-29 11:30:16 +0000252 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,
Sebastian Dröge322a8f52010-03-15 19:07:28 +0100256 G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
Sebastian Keller4ffab082008-05-29 11:30:16 +0000257 g_object_class_install_property (G_OBJECT_CLASS (klass),
258 PROP_WHITE_SENSITIVITY, g_param_spec_uint ("white-sensitivity",
Jean-François Fortin Tamf5cb19e2013-02-21 11:15:23 -0500259 "White Sensitivity", "Sensitivity to bright colors", 0, 128,
Sebastian Keller4ffab082008-05-29 11:30:16 +0000260 DEFAULT_WHITE_SENSITIVITY,
Sebastian Dröge322a8f52010-03-15 19:07:28 +0100261 G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
Sebastian Drögeab3b4bc2010-05-26 13:13:44 +0200262 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));
Wim Taymans8b7c3ac2004-05-28 18:01:34 +0000268
Tim-Philipp Müllere09ae572012-04-10 00:51:41 +0100269 gst_element_class_set_static_metadata (gstelement_class, "Alpha filter",
Wim Taymans237ca162011-04-25 12:49:36 +0200270 "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>");
275
Vineeth TM10713092016-03-04 10:30:12 +0900276 gst_element_class_add_static_pad_template (gstelement_class,
277 &gst_alpha_sink_template);
278 gst_element_class_add_static_pad_template (gstelement_class,
279 &gst_alpha_src_template);
Wim Taymans237ca162011-04-25 12:49:36 +0200280
Sebastian Drögeab3b4bc2010-05-26 13:13:44 +0200281 btrans_class->before_transform =
282 GST_DEBUG_FUNCPTR (gst_alpha_before_transform);
Jan Schmidte3155412008-01-31 00:00:23 +0000283 btrans_class->transform_caps = GST_DEBUG_FUNCPTR (gst_alpha_transform_caps);
Wim Taymans22146572011-12-21 23:51:03 +0100284
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);
Wim Taymans8b7c3ac2004-05-28 18:01:34 +0000288}
289
290static void
Wim Taymans237ca162011-04-25 12:49:36 +0200291gst_alpha_init (GstAlpha * alpha)
Wim Taymans8b7c3ac2004-05-28 18:01:34 +0000292{
Wim Taymans8b7c3ac2004-05-28 18:01:34 +0000293 alpha->alpha = DEFAULT_ALPHA;
294 alpha->method = DEFAULT_METHOD;
Wim Taymans2cf37532004-11-04 17:15:19 +0000295 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;
Sebastian Keller4ffab082008-05-29 11:30:16 +0000300 alpha->black_sensitivity = DEFAULT_BLACK_SENSITIVITY;
301 alpha->white_sensitivity = DEFAULT_WHITE_SENSITIVITY;
Sebastian Drögeab3b4bc2010-05-26 13:13:44 +0200302
Tim-Philipp Müllerf60eb9a2011-12-12 02:31:36 +0000303 g_mutex_init (&alpha->lock);
Wim Taymans8b7c3ac2004-05-28 18:01:34 +0000304}
305
Sebastian Drögeab3b4bc2010-05-26 13:13:44 +0200306static void
307gst_alpha_finalize (GObject * object)
308{
309 GstAlpha *alpha = GST_ALPHA (object);
310
Tim-Philipp Müllerf60eb9a2011-12-12 02:31:36 +0000311 g_mutex_clear (&alpha->lock);
Sebastian Drögeab3b4bc2010-05-26 13:13:44 +0200312
313 G_OBJECT_CLASS (parent_class)->finalize (object);
314}
315
Wim Taymans8b7c3ac2004-05-28 18:01:34 +0000316static void
317gst_alpha_set_property (GObject * object, guint prop_id,
318 const GValue * value, GParamSpec * pspec)
319{
Sebastian Dröge322a8f52010-03-15 19:07:28 +0100320 GstAlpha *alpha = GST_ALPHA (object);
Sebastian Drögeab3b4bc2010-05-26 13:13:44 +0200321 gboolean reconfigure = FALSE;
Wim Taymans8b7c3ac2004-05-28 18:01:34 +0000322
Sebastian Drögeab3b4bc2010-05-26 13:13:44 +0200323 GST_ALPHA_LOCK (alpha);
Wim Taymans8b7c3ac2004-05-28 18:01:34 +0000324 switch (prop_id) {
Sebastian Drögeab3b4bc2010-05-26 13:13:44 +0200325 case PROP_METHOD:{
326 gint method = g_value_get_enum (value);
327
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;
332
Sebastian Dröge6b0c5352010-03-19 18:11:12 +0100333 gst_alpha_set_process_function (alpha);
Wim Taymans2cf37532004-11-04 17:15:19 +0000334 gst_alpha_init_params (alpha);
Wim Taymans8b7c3ac2004-05-28 18:01:34 +0000335 break;
Sebastian Drögeab3b4bc2010-05-26 13:13:44 +0200336 }
337 case PROP_ALPHA:{
338 gdouble a = g_value_get_double (value);
339
340 reconfigure = (a != alpha->alpha) && (a == 1.0 || alpha->alpha == 1.0)
341 && (alpha->method == ALPHA_METHOD_SET) && (alpha->prefer_passthrough);
342 alpha->alpha = a;
Wim Taymans8b7c3ac2004-05-28 18:01:34 +0000343 break;
Sebastian Drögeab3b4bc2010-05-26 13:13:44 +0200344 }
Sebastian Keller4ffab082008-05-29 11:30:16 +0000345 case PROP_TARGET_R:
Wim Taymans2cf37532004-11-04 17:15:19 +0000346 alpha->target_r = g_value_get_uint (value);
347 gst_alpha_init_params (alpha);
Wim Taymans8b7c3ac2004-05-28 18:01:34 +0000348 break;
Sebastian Keller4ffab082008-05-29 11:30:16 +0000349 case PROP_TARGET_G:
Wim Taymans2cf37532004-11-04 17:15:19 +0000350 alpha->target_g = g_value_get_uint (value);
351 gst_alpha_init_params (alpha);
352 break;
Sebastian Keller4ffab082008-05-29 11:30:16 +0000353 case PROP_TARGET_B:
Wim Taymans2cf37532004-11-04 17:15:19 +0000354 alpha->target_b = g_value_get_uint (value);
355 gst_alpha_init_params (alpha);
356 break;
Sebastian Keller4ffab082008-05-29 11:30:16 +0000357 case PROP_ANGLE:
Wim Taymans2cf37532004-11-04 17:15:19 +0000358 alpha->angle = g_value_get_float (value);
359 gst_alpha_init_params (alpha);
360 break;
Sebastian Keller4ffab082008-05-29 11:30:16 +0000361 case PROP_NOISE_LEVEL:
Wim Taymans2cf37532004-11-04 17:15:19 +0000362 alpha->noise_level = g_value_get_float (value);
363 gst_alpha_init_params (alpha);
Wim Taymans8b7c3ac2004-05-28 18:01:34 +0000364 break;
Sebastian Keller4ffab082008-05-29 11:30:16 +0000365 case PROP_BLACK_SENSITIVITY:
366 alpha->black_sensitivity = g_value_get_uint (value);
367 break;
368 case PROP_WHITE_SENSITIVITY:
369 alpha->white_sensitivity = g_value_get_uint (value);
370 break;
Sebastian Drögeab3b4bc2010-05-26 13:13:44 +0200371 case PROP_PREFER_PASSTHROUGH:{
372 gboolean prefer_passthrough = g_value_get_boolean (value);
373
Wim Taymans60f0e442011-08-23 19:09:31 +0200374 reconfigure = ((! !prefer_passthrough) != (! !alpha->prefer_passthrough))
Sebastian Drögeab3b4bc2010-05-26 13:13:44 +0200375 && (alpha->method == ALPHA_METHOD_SET) && (alpha->alpha == 1.0);
376 alpha->prefer_passthrough = prefer_passthrough;
377 break;
378 }
Wim Taymans8b7c3ac2004-05-28 18:01:34 +0000379 default:
380 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
381 break;
382 }
Sebastian Drögeab3b4bc2010-05-26 13:13:44 +0200383
384 if (reconfigure)
Wim Taymans44828ad2012-02-24 11:03:48 +0100385 gst_base_transform_reconfigure_src (GST_BASE_TRANSFORM_CAST (alpha));
Sebastian Drögeab3b4bc2010-05-26 13:13:44 +0200386
387 GST_ALPHA_UNLOCK (alpha);
Wim Taymans8b7c3ac2004-05-28 18:01:34 +0000388}
Wim Taymans06207972009-12-24 22:50:31 +0100389
Wim Taymans8b7c3ac2004-05-28 18:01:34 +0000390static void
391gst_alpha_get_property (GObject * object, guint prop_id, GValue * value,
392 GParamSpec * pspec)
393{
Sebastian Dröge322a8f52010-03-15 19:07:28 +0100394 GstAlpha *alpha = GST_ALPHA (object);
Wim Taymans8b7c3ac2004-05-28 18:01:34 +0000395
396 switch (prop_id) {
Sebastian Keller4ffab082008-05-29 11:30:16 +0000397 case PROP_METHOD:
Wim Taymans8b7c3ac2004-05-28 18:01:34 +0000398 g_value_set_enum (value, alpha->method);
399 break;
Sebastian Keller4ffab082008-05-29 11:30:16 +0000400 case PROP_ALPHA:
Wim Taymans8b7c3ac2004-05-28 18:01:34 +0000401 g_value_set_double (value, alpha->alpha);
402 break;
Sebastian Keller4ffab082008-05-29 11:30:16 +0000403 case PROP_TARGET_R:
Wim Taymans2cf37532004-11-04 17:15:19 +0000404 g_value_set_uint (value, alpha->target_r);
Wim Taymans8b7c3ac2004-05-28 18:01:34 +0000405 break;
Sebastian Keller4ffab082008-05-29 11:30:16 +0000406 case PROP_TARGET_G:
Wim Taymans2cf37532004-11-04 17:15:19 +0000407 g_value_set_uint (value, alpha->target_g);
408 break;
Sebastian Keller4ffab082008-05-29 11:30:16 +0000409 case PROP_TARGET_B:
Wim Taymans2cf37532004-11-04 17:15:19 +0000410 g_value_set_uint (value, alpha->target_b);
411 break;
Sebastian Keller4ffab082008-05-29 11:30:16 +0000412 case PROP_ANGLE:
Wim Taymans2cf37532004-11-04 17:15:19 +0000413 g_value_set_float (value, alpha->angle);
414 break;
Sebastian Keller4ffab082008-05-29 11:30:16 +0000415 case PROP_NOISE_LEVEL:
Wim Taymans2cf37532004-11-04 17:15:19 +0000416 g_value_set_float (value, alpha->noise_level);
Wim Taymans8b7c3ac2004-05-28 18:01:34 +0000417 break;
Sebastian Keller4ffab082008-05-29 11:30:16 +0000418 case PROP_BLACK_SENSITIVITY:
419 g_value_set_uint (value, alpha->black_sensitivity);
420 break;
421 case PROP_WHITE_SENSITIVITY:
422 g_value_set_uint (value, alpha->white_sensitivity);
423 break;
Sebastian Drögeab3b4bc2010-05-26 13:13:44 +0200424 case PROP_PREFER_PASSTHROUGH:
425 g_value_set_boolean (value, alpha->prefer_passthrough);
426 break;
Wim Taymans8b7c3ac2004-05-28 18:01:34 +0000427 default:
428 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
429 break;
430 }
431}
432
Jan Schmidte3155412008-01-31 00:00:23 +0000433static GstCaps *
434gst_alpha_transform_caps (GstBaseTransform * btrans,
Edward Hervey75056542011-06-07 11:20:00 +0200435 GstPadDirection direction, GstCaps * caps, GstCaps * filter)
Jan Schmidte3155412008-01-31 00:00:23 +0000436{
Sebastian Drögeab3b4bc2010-05-26 13:13:44 +0200437 GstAlpha *alpha = GST_ALPHA (btrans);
438 GstCaps *ret, *tmp, *tmp2;
Wim Taymans8b7c3ac2004-05-28 18:01:34 +0000439 GstStructure *structure;
Jan Schmidte3155412008-01-31 00:00:23 +0000440 gint i;
Wim Taymans8b7c3ac2004-05-28 18:01:34 +0000441
Sebastian Drögeab3b4bc2010-05-26 13:13:44 +0200442 tmp = gst_caps_new_empty ();
Wim Taymans8b7c3ac2004-05-28 18:01:34 +0000443
Sebastian Drögeab3b4bc2010-05-26 13:13:44 +0200444 GST_ALPHA_LOCK (alpha);
Sebastian Dröge2e043902010-03-22 13:13:59 +0100445 for (i = 0; i < gst_caps_get_size (caps); i++) {
446 structure = gst_structure_copy (gst_caps_get_structure (caps, i));
Sebastian Dröge985ec022010-03-20 20:46:19 +0100447
Sebastian Dröge2e043902010-03-22 13:13:59 +0100448 gst_structure_remove_field (structure, "format");
Mark Nauwelaerts8bf26fa2012-04-13 16:54:31 +0200449 gst_structure_remove_field (structure, "colorimetry");
Sebastian Dröge2e043902010-03-22 13:13:59 +0100450 gst_structure_remove_field (structure, "chroma-site");
Sebastian Dröge985ec022010-03-20 20:46:19 +0100451
Sebastian Drögeab3b4bc2010-05-26 13:13:44 +0200452 gst_caps_append_structure (tmp, structure);
Wim Taymans71ebb152004-11-08 16:16:10 +0000453 }
454
Sebastian Drögeab3b4bc2010-05-26 13:13:44 +0200455 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);
460 tmp = ret;
461 ret = NULL;
462
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);
467 tmp = NULL;
468 } else {
469 ret = tmp;
470 tmp = NULL;
471 }
472 } else {
473 ret = tmp;
474 tmp = NULL;
475 }
476
477 GST_DEBUG_OBJECT (alpha,
478 "Transformed %" GST_PTR_FORMAT " -> %" GST_PTR_FORMAT, caps, ret);
479
Edward Hervey75056542011-06-07 11:20:00 +0200480 if (filter) {
481 GstCaps *intersection;
482
483 GST_DEBUG_OBJECT (alpha, "Using filter caps %" GST_PTR_FORMAT, filter);
484 intersection =
485 gst_caps_intersect_full (filter, ret, GST_CAPS_INTERSECT_FIRST);
486 gst_caps_unref (ret);
487 ret = intersection;
488 GST_DEBUG_OBJECT (alpha, "Intersection %" GST_PTR_FORMAT, ret);
489 }
490
491
Sebastian Drögeab3b4bc2010-05-26 13:13:44 +0200492 GST_ALPHA_UNLOCK (alpha);
Jan Schmidte3155412008-01-31 00:00:23 +0000493
494 return ret;
495}
496
497static gboolean
Wim Taymans22146572011-12-21 23:51:03 +0100498gst_alpha_set_info (GstVideoFilter * filter,
499 GstCaps * incaps, GstVideoInfo * in_info, GstCaps * outcaps,
500 GstVideoInfo * out_info)
Jan Schmidte3155412008-01-31 00:00:23 +0000501{
Wim Taymans22146572011-12-21 23:51:03 +0100502 GstAlpha *alpha = GST_ALPHA (filter);
Sebastian Drögeab3b4bc2010-05-26 13:13:44 +0200503 gboolean passthrough;
Jan Schmidte3155412008-01-31 00:00:23 +0000504
Sebastian Drögeab3b4bc2010-05-26 13:13:44 +0200505 GST_ALPHA_LOCK (alpha);
Sebastian Dröge6b0c5352010-03-19 18:11:12 +0100506
Mark Nauwelaerts8bf26fa2012-04-13 16:54:31 +0200507 alpha->in_sdtv = in_info->colorimetry.matrix == GST_VIDEO_COLOR_MATRIX_BT601;
508 alpha->out_sdtv =
509 out_info->colorimetry.matrix == GST_VIDEO_COLOR_MATRIX_BT601;
Sebastian Dröge6b0c5352010-03-19 18:11:12 +0100510
Sebastian Drögeab3b4bc2010-05-26 13:13:44 +0200511 passthrough = alpha->prefer_passthrough &&
Wim Taymans22146572011-12-21 23:51:03 +0100512 GST_VIDEO_INFO_FORMAT (in_info) == GST_VIDEO_INFO_FORMAT (out_info)
Wim Taymans3c27f242011-07-04 17:00:34 +0200513 && alpha->in_sdtv == alpha->out_sdtv && alpha->method == ALPHA_METHOD_SET
514 && alpha->alpha == 1.0;
Sebastian Drögeab3b4bc2010-05-26 13:13:44 +0200515
516 GST_DEBUG_OBJECT (alpha,
517 "Setting caps %" GST_PTR_FORMAT " -> %" GST_PTR_FORMAT
518 " (passthrough: %d)", incaps, outcaps, passthrough);
Wim Taymans22146572011-12-21 23:51:03 +0100519 gst_base_transform_set_passthrough (GST_BASE_TRANSFORM_CAST (filter),
520 passthrough);
Sebastian Drögeab3b4bc2010-05-26 13:13:44 +0200521
Edward Hervey4b2a0ab2012-01-04 13:25:40 +0100522 if (!gst_alpha_set_process_function_full (alpha, in_info, out_info)
523 && !passthrough)
Wim Taymansb9b007e2011-07-04 18:06:48 +0200524 goto no_process;
525
Edward Hervey4b2a0ab2012-01-04 13:25:40 +0100526 gst_alpha_init_params_full (alpha, in_info->finfo, out_info->finfo);
Sebastian Drögeab3b4bc2010-05-26 13:13:44 +0200527
528 GST_ALPHA_UNLOCK (alpha);
Jan Schmidte3155412008-01-31 00:00:23 +0000529
Wim Taymans97f9bab2005-05-17 18:13:19 +0000530 return TRUE;
Wim Taymans476e2182011-07-04 16:09:33 +0200531
532 /* ERRORS */
Wim Taymans476e2182011-07-04 16:09:33 +0200533no_process:
534 {
535 GST_WARNING_OBJECT (alpha,
536 "No processing function for this caps and no passthrough mode");
537 GST_ALPHA_UNLOCK (alpha);
538 return FALSE;
539 }
Wim Taymans8b7c3ac2004-05-28 18:01:34 +0000540}
541
Sebastian Drögef7ba1252010-03-18 18:55:34 +0100542/* based on http://www.cs.utah.edu/~michael/chroma/
543 */
544static inline gint
Sebastian Dröge0294e1e2010-04-21 17:41:43 +0200545chroma_keying_yuv (gint a, gint * y, gint * u,
Sebastian Drögef7ba1252010-03-18 18:55:34 +0100546 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,
Sebastian Drögedad4e962010-03-18 19:00:09 +0100548 guint noise_level2)
Sebastian Drögef7ba1252010-03-18 18:55:34 +0100549{
550 gint tmp, tmp1;
551 gint x1, y1;
552 gint x, z;
553 gint b_alpha;
554
Sebastian Dröge0294e1e2010-04-21 17:41:43 +0200555 /* too dark or too bright, keep alpha */
556 if (*y < smin || *y > smax)
557 return a;
Sebastian Drögef7ba1252010-03-18 18:55:34 +0100558
559 /* Convert foreground to XZ coords where X direction is defined by
560 the key color */
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);
565
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
572 division) */
573
574 tmp = (x * accept_angle_tg) >> 4;
575 tmp = MIN (tmp, 127);
576
577 if (abs (z) > tmp) {
578 /* keep foreground Kfg = 0 */
579 return a;
580 }
581 /* Compute Kfg (implicitly) and Kbg, suppress foreground in XZ coord
582 according to Kfg */
583 tmp = (z * accept_angle_ctg) >> 4;
584 tmp = CLAMP (tmp, -128, 127);
585 x1 = abs (tmp);
586 y1 = z;
587
588 tmp1 = x - x1;
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;
593
594 tmp = (tmp1 * kfgy_scale) >> 4;
595 tmp1 = MIN (tmp, 255);
596
Sebastian Dröge0294e1e2010-04-21 17:41:43 +0200597 *y = (*y < tmp1) ? 0 : *y - tmp1;
Sebastian Drögef7ba1252010-03-18 18:55:34 +0100598
599 /* Convert suppressed foreground back to CbCr */
600 tmp = (x1 * cb - y1 * cr) >> 7;
601 *u = CLAMP (tmp, -128, 127);
602
603 tmp = (x1 * cr + y1 * cb) >> 7;
604 *v = CLAMP (tmp, -128, 127);
605
606 /* Deal with noise. For now, a circle around the key color with
607 radius of noise_level treated as exact key color. Introduces
608 sharp transitions.
609 */
610 tmp = z * z + (x - kg) * (x - kg);
611 tmp = MIN (tmp, 0xffff);
612
Sebastian Drögedad4e962010-03-18 19:00:09 +0100613 if (tmp < noise_level2)
Sebastian Drögef7ba1252010-03-18 18:55:34 +0100614 b_alpha = 0;
615
616 return b_alpha;
617}
618
Sebastian Drögeb64619d2010-03-19 18:51:59 +0100619#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)
620
Sebastian Dröge0294e1e2010-04-21 17:41:43 +0200621static void
Wim Taymans476e2182011-07-04 16:09:33 +0200622gst_alpha_set_argb_ayuv (const GstVideoFrame * in_frame,
623 GstVideoFrame * out_frame, GstAlpha * alpha)
Sebastian Dröge0294e1e2010-04-21 17:41:43 +0200624{
625 gint s_alpha = CLAMP ((gint) (alpha->alpha * 256), 0, 256);
Wim Taymans476e2182011-07-04 16:09:33 +0200626 const guint8 *src;
627 guint8 *dest;
628 gint width, height;
Sebastian Dröge0294e1e2010-04-21 17:41:43 +0200629 gint i, j;
630 gint matrix[12];
631 gint y, u, v;
632 gint o[4];
633
Wim Taymans3c27f242011-07-04 17:00:34 +0200634 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
635 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
Wim Taymans476e2182011-07-04 16:09:33 +0200636
Wim Taymansb9b007e2011-07-04 18:06:48 +0200637 width = GST_VIDEO_FRAME_WIDTH (in_frame);
638 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
Wim Taymans476e2182011-07-04 16:09:33 +0200639
Wim Taymansc395bf62013-09-19 16:55:25 +0200640 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);
Sebastian Dröge0294e1e2010-04-21 17:41:43 +0200644
645 memcpy (matrix,
646 alpha->out_sdtv ? cog_rgb_to_ycbcr_matrix_8bit_sdtv :
647 cog_rgb_to_ycbcr_matrix_8bit_hdtv, 12 * sizeof (gint));
648
649 for (i = 0; i < height; i++) {
650 for (j = 0; j < width; j++) {
651 dest[0] = (src[o[0]] * s_alpha) >> 8;
652
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]]);
656
657 dest[1] = y;
658 dest[2] = u;
659 dest[3] = v;
660
661 dest += 4;
662 src += 4;
663 }
664 }
Sebastian Dröge00b3eb12010-03-19 18:21:19 +0100665}
666
Sebastian Dröge0294e1e2010-04-21 17:41:43 +0200667static void
Wim Taymans476e2182011-07-04 16:09:33 +0200668gst_alpha_chroma_key_argb_ayuv (const GstVideoFrame * in_frame,
669 GstVideoFrame * out_frame, GstAlpha * alpha)
Sebastian Dröge0294e1e2010-04-21 17:41:43 +0200670{
Wim Taymans476e2182011-07-04 16:09:33 +0200671 const guint8 *src;
672 guint8 *dest;
673 gint width, height;
Sebastian Dröge0294e1e2010-04-21 17:41:43 +0200674 gint i, j;
675 gint a, y, u, v;
676 gint r, g, b;
677 gint smin, smax;
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;
686 gint matrix[12];
687 gint o[4];
Sebastian Dröge5bbc7dd2010-03-20 21:13:23 +0100688
Wim Taymans3c27f242011-07-04 17:00:34 +0200689 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
690 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
Wim Taymans476e2182011-07-04 16:09:33 +0200691
Wim Taymansb9b007e2011-07-04 18:06:48 +0200692 width = GST_VIDEO_FRAME_WIDTH (in_frame);
693 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
Wim Taymans476e2182011-07-04 16:09:33 +0200694
Wim Taymansc395bf62013-09-19 16:55:25 +0200695 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);
Sebastian Dröge0294e1e2010-04-21 17:41:43 +0200699
700 smin = 128 - alpha->black_sensitivity;
701 smax = 128 + alpha->white_sensitivity;
702
703 memcpy (matrix,
704 alpha->out_sdtv ? cog_rgb_to_ycbcr_matrix_8bit_sdtv :
705 cog_rgb_to_ycbcr_matrix_8bit_hdtv, 12 * sizeof (gint));
706
707 for (i = 0; i < height; i++) {
708 for (j = 0; j < width; j++) {
709 a = (src[o[0]] * pa) >> 8;
710 r = src[o[1]];
711 g = src[o[2]];
712 b = src[o[3]];
713
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;
717
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);
721
722 u += 128;
723 v += 128;
724
725 dest[0] = a;
726 dest[1] = y;
727 dest[2] = u;
728 dest[3] = v;
729
730 src += 4;
731 dest += 4;
732 }
733 }
Sebastian Dröge5bbc7dd2010-03-20 21:13:23 +0100734}
735
Sebastian Dröge0294e1e2010-04-21 17:41:43 +0200736static void
Wim Taymans476e2182011-07-04 16:09:33 +0200737gst_alpha_set_argb_argb (const GstVideoFrame * in_frame,
738 GstVideoFrame * out_frame, GstAlpha * alpha)
Sebastian Dröge0294e1e2010-04-21 17:41:43 +0200739{
Wim Taymans476e2182011-07-04 16:09:33 +0200740 const guint8 *src;
741 guint8 *dest;
742 gint width, height;
Sebastian Dröge0294e1e2010-04-21 17:41:43 +0200743 gint s_alpha = CLAMP ((gint) (alpha->alpha * 256), 0, 256);
744 gint i, j;
745 gint p[4], o[4];
Sebastian Dröge5bbc7dd2010-03-20 21:13:23 +0100746
Wim Taymans3c27f242011-07-04 17:00:34 +0200747 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
748 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
Sebastian Dröge5bbc7dd2010-03-20 21:13:23 +0100749
Wim Taymansb9b007e2011-07-04 18:06:48 +0200750 width = GST_VIDEO_FRAME_WIDTH (in_frame);
751 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
Wim Taymans476e2182011-07-04 16:09:33 +0200752
Wim Taymansc395bf62013-09-19 16:55:25 +0200753 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);
Wim Taymans476e2182011-07-04 16:09:33 +0200757
Wim Taymansc395bf62013-09-19 16:55:25 +0200758 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);
Sebastian Dröge5bbc7dd2010-03-20 21:13:23 +0100762
Sebastian Dröge0294e1e2010-04-21 17:41:43 +0200763 for (i = 0; i < height; i++) {
764 for (j = 0; j < width; j++) {
765 dest[p[0]] = (src[o[0]] * s_alpha) >> 8;
Sebastian Dröge5bbc7dd2010-03-20 21:13:23 +0100766
Sebastian Dröge0294e1e2010-04-21 17:41:43 +0200767 dest[p[1]] = src[o[1]];
768 dest[p[2]] = src[o[2]];
769 dest[p[3]] = src[o[3]];
770
771 dest += 4;
772 src += 4;
773 }
774 }
Sebastian Dröge985ec022010-03-20 20:46:19 +0100775}
776
Sebastian Dröge0294e1e2010-04-21 17:41:43 +0200777static void
Wim Taymans476e2182011-07-04 16:09:33 +0200778gst_alpha_chroma_key_argb_argb (const GstVideoFrame * in_frame,
779 GstVideoFrame * out_frame, GstAlpha * alpha)
Sebastian Dröge0294e1e2010-04-21 17:41:43 +0200780{
Wim Taymans476e2182011-07-04 16:09:33 +0200781 const guint8 *src;
782 guint8 *dest;
783 gint width, height;
Sebastian Dröge0294e1e2010-04-21 17:41:43 +0200784 gint i, j;
785 gint a, y, u, v;
786 gint r, g, b;
787 gint smin, smax;
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];
797 gint p[4], o[4];
798
Wim Taymans3c27f242011-07-04 17:00:34 +0200799 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
800 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
Sebastian Dröge0294e1e2010-04-21 17:41:43 +0200801
Wim Taymansb9b007e2011-07-04 18:06:48 +0200802 width = GST_VIDEO_FRAME_WIDTH (in_frame);
803 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
Wim Taymans476e2182011-07-04 16:09:33 +0200804
Wim Taymansc395bf62013-09-19 16:55:25 +0200805 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);
Wim Taymans476e2182011-07-04 16:09:33 +0200809
Wim Taymansc395bf62013-09-19 16:55:25 +0200810 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);
Sebastian Dröge0294e1e2010-04-21 17:41:43 +0200814
815 smin = 128 - alpha->black_sensitivity;
816 smax = 128 + alpha->white_sensitivity;
817
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));
820
821 for (i = 0; i < height; i++) {
822 for (j = 0; j < width; j++) {
823 a = (src[o[0]] * pa) >> 8;
824 r = src[o[1]];
825 g = src[o[2]];
826 b = src[o[3]];
827
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;
831
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);
835
836 u += 128;
837 v += 128;
838
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);
842
843 dest[p[0]] = a;
844 dest[p[1]] = CLAMP (r, 0, 255);
845 dest[p[2]] = CLAMP (g, 0, 255);
846 dest[p[3]] = CLAMP (b, 0, 255);
847
848 src += 4;
849 dest += 4;
850 }
851 }
852}
853
854static void
Wim Taymans476e2182011-07-04 16:09:33 +0200855gst_alpha_set_ayuv_argb (const GstVideoFrame * in_frame,
856 GstVideoFrame * out_frame, GstAlpha * alpha)
Sebastian Dröge0294e1e2010-04-21 17:41:43 +0200857{
Wim Taymans476e2182011-07-04 16:09:33 +0200858 const guint8 *src;
859 guint8 *dest;
860 gint width, height;
Sebastian Dröge0294e1e2010-04-21 17:41:43 +0200861 gint s_alpha = CLAMP ((gint) (alpha->alpha * 256), 0, 256);
862 gint y, x;
863 gint matrix[12];
864 gint r, g, b;
865 gint p[4];
866
Wim Taymans3c27f242011-07-04 17:00:34 +0200867 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
868 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
Wim Taymans476e2182011-07-04 16:09:33 +0200869
Wim Taymansb9b007e2011-07-04 18:06:48 +0200870 width = GST_VIDEO_FRAME_WIDTH (in_frame);
871 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
Wim Taymans476e2182011-07-04 16:09:33 +0200872
Wim Taymansc395bf62013-09-19 16:55:25 +0200873 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);
Sebastian Dröge0294e1e2010-04-21 17:41:43 +0200877
878 memcpy (matrix,
879 alpha->in_sdtv ? cog_ycbcr_to_rgb_matrix_8bit_sdtv :
880 cog_ycbcr_to_rgb_matrix_8bit_hdtv, 12 * sizeof (gint));
881
882 for (y = 0; y < height; y++) {
883 for (x = 0; x < width; x++) {
884 dest[p[0]] = (src[0] * s_alpha) >> 8;
885
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]);
889
890 dest[p[1]] = CLAMP (r, 0, 255);
891 dest[p[2]] = CLAMP (g, 0, 255);
892 dest[p[3]] = CLAMP (b, 0, 255);
893
894 dest += 4;
895 src += 4;
896 }
897 }
898}
899
900static void
Wim Taymans476e2182011-07-04 16:09:33 +0200901gst_alpha_chroma_key_ayuv_argb (const GstVideoFrame * in_frame,
902 GstVideoFrame * out_frame, GstAlpha * alpha)
Sebastian Dröge0294e1e2010-04-21 17:41:43 +0200903{
Wim Taymans476e2182011-07-04 16:09:33 +0200904 const guint8 *src;
905 guint8 *dest;
906 gint width, height;
Sebastian Dröge0294e1e2010-04-21 17:41:43 +0200907 gint i, j;
908 gint a, y, u, v;
909 gint r, g, b;
910 gint smin, smax;
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;
919 gint matrix[12];
920 gint p[4];
921
Wim Taymans3c27f242011-07-04 17:00:34 +0200922 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
923 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
Wim Taymans476e2182011-07-04 16:09:33 +0200924
Wim Taymansb9b007e2011-07-04 18:06:48 +0200925 width = GST_VIDEO_FRAME_WIDTH (in_frame);
926 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
Wim Taymans476e2182011-07-04 16:09:33 +0200927
Wim Taymansc395bf62013-09-19 16:55:25 +0200928 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);
Sebastian Dröge0294e1e2010-04-21 17:41:43 +0200932
933 smin = 128 - alpha->black_sensitivity;
934 smax = 128 + alpha->white_sensitivity;
935
936 memcpy (matrix,
937 alpha->in_sdtv ? cog_ycbcr_to_rgb_matrix_8bit_sdtv :
938 cog_ycbcr_to_rgb_matrix_8bit_hdtv, 12 * sizeof (gint));
939
940 for (i = 0; i < height; i++) {
941 for (j = 0; j < width; j++) {
942 a = (src[0] * pa) >> 8;
943 y = src[1];
944 u = src[2] - 128;
945 v = src[3] - 128;
946
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);
950
951 u += 128;
952 v += 128;
953
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);
957
958 dest[p[0]] = a;
959 dest[p[1]] = CLAMP (r, 0, 255);
960 dest[p[2]] = CLAMP (g, 0, 255);
961 dest[p[3]] = CLAMP (b, 0, 255);
962
963 src += 4;
964 dest += 4;
965 }
966 }
967}
Sebastian Dröge985ec022010-03-20 20:46:19 +0100968
969static void
Wim Taymans476e2182011-07-04 16:09:33 +0200970gst_alpha_set_ayuv_ayuv (const GstVideoFrame * in_frame,
971 GstVideoFrame * out_frame, GstAlpha * alpha)
Sebastian Dröge5bbc7dd2010-03-20 21:13:23 +0100972{
Wim Taymans476e2182011-07-04 16:09:33 +0200973 const guint8 *src;
974 guint8 *dest;
975 gint width, height;
Sebastian Dröge5bbc7dd2010-03-20 21:13:23 +0100976 gint s_alpha = CLAMP ((gint) (alpha->alpha * 256), 0, 256);
977 gint y, x;
978
Wim Taymans3c27f242011-07-04 17:00:34 +0200979 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
980 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
Wim Taymans476e2182011-07-04 16:09:33 +0200981
Wim Taymansb9b007e2011-07-04 18:06:48 +0200982 width = GST_VIDEO_FRAME_WIDTH (in_frame);
983 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
Wim Taymans476e2182011-07-04 16:09:33 +0200984
Sebastian Dröge5bbc7dd2010-03-20 21:13:23 +0100985 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;
989 dest[1] = src[1];
990 dest[2] = src[2];
991 dest[3] = src[3];
992
993 dest += 4;
994 src += 4;
995 }
996 }
997 } else {
998 gint matrix[12];
999
1000 memcpy (matrix,
1001 alpha->out_sdtv ? cog_ycbcr_hdtv_to_ycbcr_sdtv_matrix_8bit :
1002 cog_ycbcr_sdtv_to_ycbcr_hdtv_matrix_8bit, 12 * sizeof (gint));
1003
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]);
1010
1011 dest += 4;
1012 src += 4;
1013 }
1014 }
1015 }
1016}
1017
1018static void
Wim Taymans476e2182011-07-04 16:09:33 +02001019gst_alpha_chroma_key_ayuv_ayuv (const GstVideoFrame * in_frame,
1020 GstVideoFrame * out_frame, GstAlpha * alpha)
Sebastian Dröge985ec022010-03-20 20:46:19 +01001021{
Wim Taymans476e2182011-07-04 16:09:33 +02001022 const guint8 *src;
1023 guint8 *dest;
1024 gint width, height;
Sebastian Dröge985ec022010-03-20 20:46:19 +01001025 gint i, j;
1026 gint a, y, u, v;
1027 gint smin, smax;
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;
1036
Wim Taymans3c27f242011-07-04 17:00:34 +02001037 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
1038 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
Wim Taymans476e2182011-07-04 16:09:33 +02001039
Wim Taymansb9b007e2011-07-04 18:06:48 +02001040 width = GST_VIDEO_FRAME_WIDTH (in_frame);
1041 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
Wim Taymans476e2182011-07-04 16:09:33 +02001042
Sebastian Dröge985ec022010-03-20 20:46:19 +01001043 smin = 128 - alpha->black_sensitivity;
1044 smax = 128 + alpha->white_sensitivity;
1045
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;
1050 y = src[1];
1051 u = src[2] - 128;
1052 v = src[3] - 128;
1053
Sebastian Dröge0294e1e2010-04-21 17:41:43 +02001054 a = chroma_keying_yuv (a, &y, &u, &v, cr, cb,
Sebastian Dröge985ec022010-03-20 20:46:19 +01001055 smin, smax, accept_angle_tg, accept_angle_ctg,
1056 one_over_kc, kfgy_scale, kg, noise_level2);
1057
1058 u += 128;
1059 v += 128;
1060
1061 dest[0] = a;
1062 dest[1] = y;
1063 dest[2] = u;
1064 dest[3] = v;
1065
1066 src += 4;
1067 dest += 4;
1068 }
1069 }
1070 } else {
1071 gint matrix[12];
1072
1073 memcpy (matrix,
1074 alpha->out_sdtv ? cog_ycbcr_hdtv_to_ycbcr_sdtv_matrix_8bit :
1075 cog_ycbcr_sdtv_to_ycbcr_hdtv_matrix_8bit, 12 * sizeof (gint));
1076
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;
1083
Sebastian Dröge0294e1e2010-04-21 17:41:43 +02001084 a = chroma_keying_yuv (a, &y, &u, &v, cr, cb,
Sebastian Dröge985ec022010-03-20 20:46:19 +01001085 smin, smax, accept_angle_tg, accept_angle_ctg,
1086 one_over_kc, kfgy_scale, kg, noise_level2);
1087
1088 u += 128;
1089 v += 128;
1090
1091 dest[0] = a;
1092 dest[1] = y;
1093 dest[2] = u;
1094 dest[3] = v;
1095
1096 src += 4;
1097 dest += 4;
1098 }
1099 }
1100 }
1101}
1102
Sebastian Dröge0294e1e2010-04-21 17:41:43 +02001103static void
Wim Taymans476e2182011-07-04 16:09:33 +02001104gst_alpha_set_rgb_ayuv (const GstVideoFrame * in_frame,
1105 GstVideoFrame * out_frame, GstAlpha * alpha)
Sebastian Dröge0294e1e2010-04-21 17:41:43 +02001106{
Wim Taymans476e2182011-07-04 16:09:33 +02001107 const guint8 *src;
1108 guint8 *dest;
1109 gint width, height;
Sebastian Dröge0294e1e2010-04-21 17:41:43 +02001110 gint s_alpha = CLAMP ((gint) (alpha->alpha * 255), 0, 255);
1111 gint i, j;
1112 gint matrix[12];
1113 gint y, u, v;
1114 gint o[3];
1115 gint bpp;
1116
Wim Taymans3c27f242011-07-04 17:00:34 +02001117 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
1118 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
Sebastian Dröge0294e1e2010-04-21 17:41:43 +02001119
Wim Taymansb9b007e2011-07-04 18:06:48 +02001120 width = GST_VIDEO_FRAME_WIDTH (in_frame);
1121 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
Wim Taymans476e2182011-07-04 16:09:33 +02001122
Wim Taymansb9b007e2011-07-04 18:06:48 +02001123 bpp = GST_VIDEO_FRAME_COMP_PSTRIDE (in_frame, 0);
Wim Taymansc395bf62013-09-19 16:55:25 +02001124 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);
Sebastian Dröge0294e1e2010-04-21 17:41:43 +02001127
1128 memcpy (matrix,
1129 alpha->out_sdtv ? cog_rgb_to_ycbcr_matrix_8bit_sdtv :
1130 cog_rgb_to_ycbcr_matrix_8bit_hdtv, 12 * sizeof (gint));
1131
1132 for (i = 0; i < height; i++) {
1133 for (j = 0; j < width; j++) {
1134 dest[0] = s_alpha;
1135
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]]);
1139
1140 dest[1] = y;
1141 dest[2] = u;
1142 dest[3] = v;
1143
1144 dest += 4;
1145 src += bpp;
1146 }
1147 }
Sebastian Dröge985ec022010-03-20 20:46:19 +01001148}
1149
Sebastian Dröge00b3eb12010-03-19 18:21:19 +01001150static void
Wim Taymans476e2182011-07-04 16:09:33 +02001151gst_alpha_chroma_key_rgb_ayuv (const GstVideoFrame * in_frame,
1152 GstVideoFrame * out_frame, GstAlpha * alpha)
Sebastian Dröge0294e1e2010-04-21 17:41:43 +02001153{
Wim Taymans476e2182011-07-04 16:09:33 +02001154 const guint8 *src;
1155 guint8 *dest;
1156 gint width, height;
Sebastian Dröge0294e1e2010-04-21 17:41:43 +02001157 gint i, j;
1158 gint a, y, u, v;
1159 gint r, g, b;
1160 gint smin, smax;
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;
1169 gint matrix[12];
1170 gint o[3];
1171 gint bpp;
1172
Wim Taymans3c27f242011-07-04 17:00:34 +02001173 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
1174 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
Sebastian Dröge0294e1e2010-04-21 17:41:43 +02001175
Wim Taymansb9b007e2011-07-04 18:06:48 +02001176 width = GST_VIDEO_FRAME_WIDTH (in_frame);
1177 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
Wim Taymans476e2182011-07-04 16:09:33 +02001178
Wim Taymansb9b007e2011-07-04 18:06:48 +02001179 bpp = GST_VIDEO_FRAME_COMP_PSTRIDE (in_frame, 0);
Wim Taymans476e2182011-07-04 16:09:33 +02001180
Wim Taymansc395bf62013-09-19 16:55:25 +02001181 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);
Sebastian Dröge0294e1e2010-04-21 17:41:43 +02001184
1185 smin = 128 - alpha->black_sensitivity;
1186 smax = 128 + alpha->white_sensitivity;
1187
1188 memcpy (matrix,
1189 alpha->out_sdtv ? cog_rgb_to_ycbcr_matrix_8bit_sdtv :
1190 cog_rgb_to_ycbcr_matrix_8bit_hdtv, 12 * sizeof (gint));
1191
1192 for (i = 0; i < height; i++) {
1193 for (j = 0; j < width; j++) {
1194 a = pa;
1195 r = src[o[0]];
1196 g = src[o[1]];
1197 b = src[o[2]];
1198
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;
1202
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);
1206
1207 u += 128;
1208 v += 128;
1209
1210 dest[0] = a;
1211 dest[1] = y;
1212 dest[2] = u;
1213 dest[3] = v;
1214
1215 src += bpp;
1216 dest += 4;
1217 }
1218 }
1219}
1220
1221static void
Wim Taymans476e2182011-07-04 16:09:33 +02001222gst_alpha_set_rgb_argb (const GstVideoFrame * in_frame,
1223 GstVideoFrame * out_frame, GstAlpha * alpha)
Sebastian Dröge0294e1e2010-04-21 17:41:43 +02001224{
Wim Taymans476e2182011-07-04 16:09:33 +02001225 const guint8 *src;
1226 guint8 *dest;
1227 gint width, height;
Sebastian Dröge0294e1e2010-04-21 17:41:43 +02001228 gint s_alpha = CLAMP ((gint) (alpha->alpha * 255), 0, 255);
1229 gint i, j;
1230 gint p[4], o[3];
1231 gint bpp;
1232
Wim Taymans3c27f242011-07-04 17:00:34 +02001233 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
1234 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
Sebastian Dröge0294e1e2010-04-21 17:41:43 +02001235
Wim Taymansb9b007e2011-07-04 18:06:48 +02001236 width = GST_VIDEO_FRAME_WIDTH (in_frame);
1237 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
Sebastian Dröge0294e1e2010-04-21 17:41:43 +02001238
Wim Taymansb9b007e2011-07-04 18:06:48 +02001239 bpp = GST_VIDEO_FRAME_COMP_PSTRIDE (in_frame, 0);
Wim Taymans476e2182011-07-04 16:09:33 +02001240
Wim Taymansc395bf62013-09-19 16:55:25 +02001241 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);
Wim Taymans476e2182011-07-04 16:09:33 +02001244
Wim Taymansc395bf62013-09-19 16:55:25 +02001245 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);
Sebastian Dröge0294e1e2010-04-21 17:41:43 +02001249
1250 for (i = 0; i < height; i++) {
1251 for (j = 0; j < width; j++) {
1252 dest[p[0]] = s_alpha;
1253
1254 dest[p[1]] = src[o[0]];
1255 dest[p[2]] = src[o[1]];
1256 dest[p[3]] = src[o[2]];
1257
1258 dest += 4;
1259 src += bpp;
1260 }
1261 }
1262}
1263
1264static void
Wim Taymans476e2182011-07-04 16:09:33 +02001265gst_alpha_chroma_key_rgb_argb (const GstVideoFrame * in_frame,
1266 GstVideoFrame * out_frame, GstAlpha * alpha)
Sebastian Dröge0294e1e2010-04-21 17:41:43 +02001267{
Wim Taymans476e2182011-07-04 16:09:33 +02001268 const guint8 *src;
1269 guint8 *dest;
1270 gint width, height;
Sebastian Dröge0294e1e2010-04-21 17:41:43 +02001271 gint i, j;
1272 gint a, y, u, v;
1273 gint r, g, b;
1274 gint smin, smax;
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];
1284 gint p[4], o[3];
1285 gint bpp;
1286
Wim Taymans3c27f242011-07-04 17:00:34 +02001287 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
1288 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
Sebastian Dröge0294e1e2010-04-21 17:41:43 +02001289
Wim Taymansb9b007e2011-07-04 18:06:48 +02001290 width = GST_VIDEO_FRAME_WIDTH (in_frame);
1291 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
Sebastian Dröge0294e1e2010-04-21 17:41:43 +02001292
Wim Taymansb9b007e2011-07-04 18:06:48 +02001293 bpp = GST_VIDEO_FRAME_COMP_PSTRIDE (in_frame, 0);
Wim Taymans476e2182011-07-04 16:09:33 +02001294
Wim Taymansc395bf62013-09-19 16:55:25 +02001295 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);
Wim Taymans476e2182011-07-04 16:09:33 +02001298
Wim Taymansc395bf62013-09-19 16:55:25 +02001299 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);
Sebastian Dröge0294e1e2010-04-21 17:41:43 +02001303
1304 smin = 128 - alpha->black_sensitivity;
1305 smax = 128 + alpha->white_sensitivity;
1306
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));
1309
1310 for (i = 0; i < height; i++) {
1311 for (j = 0; j < width; j++) {
1312 a = pa;
1313 r = src[o[0]];
1314 g = src[o[1]];
1315 b = src[o[2]];
1316
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;
1320
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);
1324
1325 u += 128;
1326 v += 128;
1327
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);
1331
1332 dest[p[0]] = a;
1333 dest[p[1]] = CLAMP (r, 0, 255);
1334 dest[p[2]] = CLAMP (g, 0, 255);
1335 dest[p[3]] = CLAMP (b, 0, 255);
1336
1337 src += bpp;
1338 dest += 4;
1339 }
1340 }
1341}
1342
1343static void
Wim Taymans476e2182011-07-04 16:09:33 +02001344gst_alpha_set_planar_yuv_ayuv (const GstVideoFrame * in_frame,
1345 GstVideoFrame * out_frame, GstAlpha * alpha)
Sebastian Dröge00b3eb12010-03-19 18:21:19 +01001346{
Wim Taymans476e2182011-07-04 16:09:33 +02001347 guint8 *dest;
1348 gint width, height;
Sebastian Dröge00b3eb12010-03-19 18:21:19 +01001349 gint b_alpha = CLAMP ((gint) (alpha->alpha * 255), 0, 255);
Sebastian Dröge0294e1e2010-04-21 17:41:43 +02001350 const guint8 *srcY, *srcY_tmp;
1351 const guint8 *srcU, *srcU_tmp;
1352 const guint8 *srcV, *srcV_tmp;
Sebastian Dröge00b3eb12010-03-19 18:21:19 +01001353 gint i, j;
Sebastian Dröge00b3eb12010-03-19 18:21:19 +01001354 gint y_stride, uv_stride;
Sebastian Dröge0294e1e2010-04-21 17:41:43 +02001355 gint v_subs, h_subs;
Sebastian Dröge00b3eb12010-03-19 18:21:19 +01001356
Wim Taymans3c27f242011-07-04 17:00:34 +02001357 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
Wim Taymans476e2182011-07-04 16:09:33 +02001358
Wim Taymansb9b007e2011-07-04 18:06:48 +02001359 width = GST_VIDEO_FRAME_WIDTH (in_frame);
1360 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
Wim Taymans476e2182011-07-04 16:09:33 +02001361
Wim Taymansb9b007e2011-07-04 18:06:48 +02001362 y_stride = GST_VIDEO_FRAME_COMP_STRIDE (in_frame, 0);
1363 uv_stride = GST_VIDEO_FRAME_COMP_STRIDE (in_frame, 1);
Sebastian Dröge00b3eb12010-03-19 18:21:19 +01001364
Wim Taymans926e2fa2013-09-19 16:50:44 +02001365 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);
Sebastian Dröge00b3eb12010-03-19 18:21:19 +01001368
Wim Taymansb9b007e2011-07-04 18:06:48 +02001369 switch (GST_VIDEO_FRAME_FORMAT (in_frame)) {
Sebastian Dröge0294e1e2010-04-21 17:41:43 +02001370 case GST_VIDEO_FORMAT_I420:
1371 case GST_VIDEO_FORMAT_YV12:
1372 v_subs = h_subs = 2;
1373 break;
1374 case GST_VIDEO_FORMAT_Y444:
1375 v_subs = h_subs = 1;
1376 break;
1377 case GST_VIDEO_FORMAT_Y42B:
1378 v_subs = 1;
1379 h_subs = 2;
1380 break;
1381 case GST_VIDEO_FORMAT_Y41B:
1382 v_subs = 1;
1383 h_subs = 4;
1384 break;
1385 default:
1386 g_assert_not_reached ();
Tim-Philipp Müller4a7a78d2011-01-07 02:32:20 +00001387 return;
Sebastian Dröge0294e1e2010-04-21 17:41:43 +02001388 }
Sebastian Dröge00b3eb12010-03-19 18:21:19 +01001389
Sebastian Drögeb64619d2010-03-19 18:51:59 +01001390 if (alpha->in_sdtv == alpha->out_sdtv) {
1391 for (i = 0; i < height; i++) {
Sebastian Dröge0294e1e2010-04-21 17:41:43 +02001392 for (j = 0; j < width; j++) {
Sebastian Drögeb64619d2010-03-19 18:51:59 +01001393 dest[0] = b_alpha;
1394 dest[1] = srcY[0];
1395 dest[2] = srcU[0];
1396 dest[3] = srcV[0];
1397
1398 dest += 4;
1399 srcY++;
Sebastian Dröge0294e1e2010-04-21 17:41:43 +02001400 if ((j + 1) % h_subs == 0) {
1401 srcU++;
1402 srcV++;
1403 }
Sebastian Drögeb64619d2010-03-19 18:51:59 +01001404 }
Sebastian Dröge0294e1e2010-04-21 17:41:43 +02001405
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;
Sebastian Drögeb64619d2010-03-19 18:51:59 +01001410 } else {
Sebastian Dröge0294e1e2010-04-21 17:41:43 +02001411 srcU = srcU_tmp;
1412 srcV = srcV_tmp;
Sebastian Drögeb64619d2010-03-19 18:51:59 +01001413 }
Sebastian Dröge0294e1e2010-04-21 17:41:43 +02001414 }
1415 } else {
1416 gint matrix[12];
1417 gint a, y, u, v;
1418
1419 memcpy (matrix,
1420 alpha->out_sdtv ? cog_ycbcr_hdtv_to_ycbcr_sdtv_matrix_8bit :
1421 cog_ycbcr_sdtv_to_ycbcr_hdtv_matrix_8bit, 12 * sizeof (gint));
1422
1423 for (i = 0; i < height; i++) {
1424 for (j = 0; j < width; j++) {
1425 a = b_alpha;
1426 y = srcY[0];
1427 u = srcU[0];
1428 v = srcV[0];
1429
1430 dest[0] = a;
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);
1434
1435 dest += 4;
1436 srcY++;
1437 if ((j + 1) % h_subs == 0) {
1438 srcU++;
1439 srcV++;
1440 }
1441 }
1442
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;
1447 } else {
1448 srcU = srcU_tmp;
1449 srcV = srcV_tmp;
1450 }
1451 }
1452 }
1453}
1454
1455static void
Wim Taymans476e2182011-07-04 16:09:33 +02001456gst_alpha_chroma_key_planar_yuv_ayuv (const GstVideoFrame * in_frame,
Wim Taymansb9b007e2011-07-04 18:06:48 +02001457 GstVideoFrame * out_frame, GstAlpha * alpha)
Sebastian Dröge0294e1e2010-04-21 17:41:43 +02001458{
Wim Taymans476e2182011-07-04 16:09:33 +02001459 guint8 *dest;
1460 gint width, height;
Sebastian Dröge0294e1e2010-04-21 17:41:43 +02001461 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;
1465 gint i, j;
1466 gint a, y, u, v;
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;
1478
Wim Taymans3c27f242011-07-04 17:00:34 +02001479 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
Wim Taymans476e2182011-07-04 16:09:33 +02001480
Wim Taymansb9b007e2011-07-04 18:06:48 +02001481 width = GST_VIDEO_FRAME_WIDTH (in_frame);
1482 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
Wim Taymans476e2182011-07-04 16:09:33 +02001483
Wim Taymansb9b007e2011-07-04 18:06:48 +02001484 y_stride = GST_VIDEO_FRAME_COMP_STRIDE (in_frame, 0);
1485 uv_stride = GST_VIDEO_FRAME_COMP_STRIDE (in_frame, 1);
Sebastian Dröge0294e1e2010-04-21 17:41:43 +02001486
Wim Taymans926e2fa2013-09-19 16:50:44 +02001487 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);
Sebastian Dröge0294e1e2010-04-21 17:41:43 +02001490
Wim Taymansb9b007e2011-07-04 18:06:48 +02001491 switch (GST_VIDEO_FRAME_FORMAT (in_frame)) {
Sebastian Dröge0294e1e2010-04-21 17:41:43 +02001492 case GST_VIDEO_FORMAT_I420:
1493 case GST_VIDEO_FORMAT_YV12:
1494 v_subs = h_subs = 2;
1495 break;
1496 case GST_VIDEO_FORMAT_Y444:
1497 v_subs = h_subs = 1;
1498 break;
1499 case GST_VIDEO_FORMAT_Y42B:
1500 v_subs = 1;
1501 h_subs = 2;
1502 break;
1503 case GST_VIDEO_FORMAT_Y41B:
1504 v_subs = 1;
1505 h_subs = 4;
1506 break;
1507 default:
1508 g_assert_not_reached ();
Tim-Philipp Müller4a7a78d2011-01-07 02:32:20 +00001509 return;
Sebastian Dröge0294e1e2010-04-21 17:41:43 +02001510 }
1511
1512 if (alpha->in_sdtv == alpha->out_sdtv) {
1513 for (i = 0; i < height; i++) {
1514 for (j = 0; j < width; j++) {
1515 a = b_alpha;
1516 y = srcY[0];
1517 u = srcU[0] - 128;
1518 v = srcV[0] - 128;
1519
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);
1523
1524 u += 128;
1525 v += 128;
1526
1527 dest[0] = a;
1528 dest[1] = y;
1529 dest[2] = u;
1530 dest[3] = v;
1531
1532 dest += 4;
1533 srcY++;
1534 if ((j + 1) % h_subs == 0) {
1535 srcU++;
1536 srcV++;
1537 }
1538 }
1539
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;
1544 } else {
1545 srcU = srcU_tmp;
1546 srcV = srcV_tmp;
1547 }
Sebastian Dröge00b3eb12010-03-19 18:21:19 +01001548 }
Sebastian Drögeb64619d2010-03-19 18:51:59 +01001549 } else {
Sebastian Dröge9d9ba5b2010-03-20 10:20:53 +01001550 gint matrix[12];
1551
1552 memcpy (matrix,
Sebastian Drögeb64619d2010-03-19 18:51:59 +01001553 alpha->out_sdtv ? cog_ycbcr_hdtv_to_ycbcr_sdtv_matrix_8bit :
Sebastian Dröge9d9ba5b2010-03-20 10:20:53 +01001554 cog_ycbcr_sdtv_to_ycbcr_hdtv_matrix_8bit, 12 * sizeof (gint));
Sebastian Drögeb64619d2010-03-19 18:51:59 +01001555
1556 for (i = 0; i < height; i++) {
Sebastian Dröge0294e1e2010-04-21 17:41:43 +02001557 for (j = 0; j < width; j++) {
1558 a = b_alpha;
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;
Sebastian Drögeb64619d2010-03-19 18:51:59 +01001562
Sebastian Dröge0294e1e2010-04-21 17:41:43 +02001563 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);
1566
1567 dest[0] = a;
1568 dest[1] = y;
1569 dest[2] = u + 128;
1570 dest[3] = v + 128;
Sebastian Drögeb64619d2010-03-19 18:51:59 +01001571
1572 dest += 4;
1573 srcY++;
Sebastian Dröge0294e1e2010-04-21 17:41:43 +02001574 if ((j + 1) % h_subs == 0) {
1575 srcU++;
1576 srcV++;
1577 }
Sebastian Drögeb64619d2010-03-19 18:51:59 +01001578 }
Sebastian Dröge0294e1e2010-04-21 17:41:43 +02001579
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;
Sebastian Drögeb64619d2010-03-19 18:51:59 +01001584 } else {
Sebastian Dröge0294e1e2010-04-21 17:41:43 +02001585 srcU = srcU_tmp;
1586 srcV = srcV_tmp;
Sebastian Drögeb64619d2010-03-19 18:51:59 +01001587 }
Sebastian Dröge00b3eb12010-03-19 18:21:19 +01001588 }
Sebastian Dröge00b3eb12010-03-19 18:21:19 +01001589 }
1590}
1591
Sebastian Dröge0294e1e2010-04-21 17:41:43 +02001592static void
Wim Taymans476e2182011-07-04 16:09:33 +02001593gst_alpha_set_planar_yuv_argb (const GstVideoFrame * in_frame,
Wim Taymansb9b007e2011-07-04 18:06:48 +02001594 GstVideoFrame * out_frame, GstAlpha * alpha)
Jan Schmidte3155412008-01-31 00:00:23 +00001595{
Wim Taymans476e2182011-07-04 16:09:33 +02001596 guint8 *dest;
1597 gint width, height;
Sebastian Dröge0294e1e2010-04-21 17:41:43 +02001598 gint b_alpha = CLAMP ((gint) (alpha->alpha * 255), 0, 255);
Sebastian Drögef71157f2010-04-22 15:45:15 +02001599 const guint8 *srcY, *srcY_tmp;
Sebastian Dröge0294e1e2010-04-21 17:41:43 +02001600 const guint8 *srcU, *srcU_tmp;
1601 const guint8 *srcV, *srcV_tmp;
1602 gint i, j;
Sebastian Dröge0294e1e2010-04-21 17:41:43 +02001603 gint y_stride, uv_stride;
1604 gint v_subs, h_subs;
1605 gint matrix[12];
1606 gint a, y, u, v;
Sebastian Dröge1897ab22010-04-22 15:42:03 +02001607 gint r, g, b;
Sebastian Dröge0294e1e2010-04-21 17:41:43 +02001608 gint p[4];
1609
Wim Taymans3c27f242011-07-04 17:00:34 +02001610 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
Sebastian Dröge0294e1e2010-04-21 17:41:43 +02001611
Wim Taymansb9b007e2011-07-04 18:06:48 +02001612 width = GST_VIDEO_FRAME_WIDTH (in_frame);
1613 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
Wim Taymans476e2182011-07-04 16:09:33 +02001614
Wim Taymansc395bf62013-09-19 16:55:25 +02001615 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);
Wim Taymans476e2182011-07-04 16:09:33 +02001619
Wim Taymansb9b007e2011-07-04 18:06:48 +02001620 y_stride = GST_VIDEO_FRAME_COMP_STRIDE (in_frame, 0);
1621 uv_stride = GST_VIDEO_FRAME_COMP_STRIDE (in_frame, 1);
Sebastian Dröge0294e1e2010-04-21 17:41:43 +02001622
Wim Taymans926e2fa2013-09-19 16:50:44 +02001623 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);
Sebastian Dröge0294e1e2010-04-21 17:41:43 +02001626
Wim Taymansb9b007e2011-07-04 18:06:48 +02001627 switch (GST_VIDEO_FRAME_FORMAT (in_frame)) {
Sebastian Dröge0294e1e2010-04-21 17:41:43 +02001628 case GST_VIDEO_FORMAT_I420:
1629 case GST_VIDEO_FORMAT_YV12:
1630 v_subs = h_subs = 2;
1631 break;
1632 case GST_VIDEO_FORMAT_Y444:
1633 v_subs = h_subs = 1;
1634 break;
1635 case GST_VIDEO_FORMAT_Y42B:
1636 v_subs = 1;
1637 h_subs = 2;
1638 break;
1639 case GST_VIDEO_FORMAT_Y41B:
1640 v_subs = 1;
1641 h_subs = 4;
1642 break;
1643 default:
1644 g_assert_not_reached ();
Tim-Philipp Müller4a7a78d2011-01-07 02:32:20 +00001645 return;
Sebastian Dröge0294e1e2010-04-21 17:41:43 +02001646 }
1647
1648 memcpy (matrix,
1649 alpha->in_sdtv ? cog_ycbcr_to_rgb_matrix_8bit_sdtv :
1650 cog_ycbcr_to_rgb_matrix_8bit_hdtv, 12 * sizeof (gint));
1651
1652 for (i = 0; i < height; i++) {
1653 for (j = 0; j < width; j++) {
1654 a = b_alpha;
1655 y = srcY[0];
1656 u = srcU[0];
1657 v = srcV[0];
1658
1659 dest[p[0]] = a;
Sebastian Dröge1897ab22010-04-22 15:42:03 +02001660 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);
Sebastian Dröge0294e1e2010-04-21 17:41:43 +02001666
1667 dest += 4;
1668 srcY++;
1669 if ((j + 1) % h_subs == 0) {
1670 srcU++;
1671 srcV++;
1672 }
1673 }
1674
Sebastian Drögef71157f2010-04-22 15:45:15 +02001675 srcY_tmp = srcY = srcY_tmp + y_stride;
Sebastian Dröge0294e1e2010-04-21 17:41:43 +02001676 if ((i + 1) % v_subs == 0) {
Sebastian Drögef71157f2010-04-22 15:45:15 +02001677 srcU_tmp = srcU = srcU_tmp + uv_stride;
1678 srcV_tmp = srcV = srcV_tmp + uv_stride;
Sebastian Dröge0294e1e2010-04-21 17:41:43 +02001679 } else {
1680 srcU = srcU_tmp;
1681 srcV = srcV_tmp;
1682 }
1683 }
1684}
1685
1686static void
Wim Taymans476e2182011-07-04 16:09:33 +02001687gst_alpha_chroma_key_planar_yuv_argb (const GstVideoFrame * in_frame,
Wim Taymansb9b007e2011-07-04 18:06:48 +02001688 GstVideoFrame * out_frame, GstAlpha * alpha)
Sebastian Dröge0294e1e2010-04-21 17:41:43 +02001689{
Wim Taymans476e2182011-07-04 16:09:33 +02001690 guint8 *dest;
1691 gint width, height;
Sebastian Dröge0294e1e2010-04-21 17:41:43 +02001692 gint b_alpha = CLAMP ((gint) (alpha->alpha * 255), 0, 255);
Sebastian Drögef71157f2010-04-22 15:45:15 +02001693 const guint8 *srcY, *srcY_tmp;
Sebastian Dröge0294e1e2010-04-21 17:41:43 +02001694 const guint8 *srcU, *srcU_tmp;
1695 const guint8 *srcV, *srcV_tmp;
1696 gint i, j;
1697 gint a, y, u, v;
Sebastian Dröge1897ab22010-04-22 15:42:03 +02001698 gint r, g, b;
Sebastian Dröge0294e1e2010-04-21 17:41:43 +02001699 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;
Sebastian Dröge1fdbfb32010-03-20 10:24:56 +01001703 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;
Sebastian Dröge0294e1e2010-04-21 17:41:43 +02001710 gint matrix[12];
1711 gint p[4];
Jan Schmidte3155412008-01-31 00:00:23 +00001712
Wim Taymans3c27f242011-07-04 17:00:34 +02001713 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
Wim Taymans476e2182011-07-04 16:09:33 +02001714
Wim Taymansb9b007e2011-07-04 18:06:48 +02001715 width = GST_VIDEO_FRAME_WIDTH (in_frame);
1716 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
Wim Taymans476e2182011-07-04 16:09:33 +02001717
Wim Taymansc395bf62013-09-19 16:55:25 +02001718 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);
Jan Schmidte3155412008-01-31 00:00:23 +00001722
Wim Taymansb9b007e2011-07-04 18:06:48 +02001723 y_stride = GST_VIDEO_FRAME_COMP_STRIDE (in_frame, 0);
1724 uv_stride = GST_VIDEO_FRAME_COMP_STRIDE (in_frame, 1);
Jan Schmidte3155412008-01-31 00:00:23 +00001725
Wim Taymans926e2fa2013-09-19 16:50:44 +02001726 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);
Sebastian Dröge0294e1e2010-04-21 17:41:43 +02001729
Wim Taymansb9b007e2011-07-04 18:06:48 +02001730 switch (GST_VIDEO_FRAME_FORMAT (in_frame)) {
Sebastian Dröge0294e1e2010-04-21 17:41:43 +02001731 case GST_VIDEO_FORMAT_I420:
1732 case GST_VIDEO_FORMAT_YV12:
1733 v_subs = h_subs = 2;
1734 break;
1735 case GST_VIDEO_FORMAT_Y444:
1736 v_subs = h_subs = 1;
1737 break;
1738 case GST_VIDEO_FORMAT_Y42B:
1739 v_subs = 1;
1740 h_subs = 2;
1741 break;
1742 case GST_VIDEO_FORMAT_Y41B:
1743 v_subs = 1;
1744 h_subs = 4;
1745 break;
1746 default:
1747 g_assert_not_reached ();
Tim-Philipp Müller4a7a78d2011-01-07 02:32:20 +00001748 return;
Sebastian Dröge0294e1e2010-04-21 17:41:43 +02001749 }
1750
1751 memcpy (matrix,
1752 alpha->in_sdtv ? cog_ycbcr_to_rgb_matrix_8bit_sdtv :
1753 cog_ycbcr_to_rgb_matrix_8bit_hdtv, 12 * sizeof (gint));
1754
1755 for (i = 0; i < height; i++) {
1756 for (j = 0; j < width; j++) {
1757 a = b_alpha;
1758 y = srcY[0];
Sebastian Drögeb64619d2010-03-19 18:51:59 +01001759 u = srcU[0] - 128;
1760 v = srcV[0] - 128;
Jan Schmidte3155412008-01-31 00:00:23 +00001761
Sebastian Dröge0294e1e2010-04-21 17:41:43 +02001762 a = chroma_keying_yuv (a, &y, &u, &v, cr, cb, smin,
Sebastian Dröge1fdbfb32010-03-20 10:24:56 +01001763 smax, accept_angle_tg, accept_angle_ctg,
1764 one_over_kc, kfgy_scale, kg, noise_level2);
Jan Schmidte3155412008-01-31 00:00:23 +00001765
Sebastian Drögeb64619d2010-03-19 18:51:59 +01001766 u += 128;
1767 v += 128;
Jan Schmidte3155412008-01-31 00:00:23 +00001768
Sebastian Dröge1897ab22010-04-22 15:42:03 +02001769 dest[p[0]] = a;
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);
Sebastian Drögeb64619d2010-03-19 18:51:59 +01001776
Sebastian Dröge0294e1e2010-04-21 17:41:43 +02001777 dest += 4;
1778 srcY++;
1779 if ((j + 1) % h_subs == 0) {
1780 srcU++;
1781 srcV++;
1782 }
Sebastian Drögeb64619d2010-03-19 18:51:59 +01001783 }
Sebastian Dröge9d9ba5b2010-03-20 10:20:53 +01001784
Sebastian Drögef71157f2010-04-22 15:45:15 +02001785 srcY_tmp = srcY = srcY_tmp + y_stride;
Sebastian Dröge0294e1e2010-04-21 17:41:43 +02001786 if ((i + 1) % v_subs == 0) {
Sebastian Drögef71157f2010-04-22 15:45:15 +02001787 srcU_tmp = srcU = srcU_tmp + uv_stride;
1788 srcV_tmp = srcV = srcV_tmp + uv_stride;
Sebastian Dröge0294e1e2010-04-21 17:41:43 +02001789 } else {
1790 srcU = srcU_tmp;
1791 srcV = srcV_tmp;
Sebastian Drögeb64619d2010-03-19 18:51:59 +01001792 }
Wim Taymans71ebb152004-11-08 16:16:10 +00001793 }
1794}
Wim Taymans42b61352004-11-03 18:54:50 +00001795
Sebastian Dröge545b21c2010-04-22 15:20:24 +02001796static void
Wim Taymans476e2182011-07-04 16:09:33 +02001797gst_alpha_set_packed_422_ayuv (const GstVideoFrame * in_frame,
Wim Taymansb9b007e2011-07-04 18:06:48 +02001798 GstVideoFrame * out_frame, GstAlpha * alpha)
Sebastian Dröge545b21c2010-04-22 15:20:24 +02001799{
Wim Taymans476e2182011-07-04 16:09:33 +02001800 const guint8 *src;
1801 guint8 *dest;
1802 gint width, height;
Sebastian Dröge545b21c2010-04-22 15:20:24 +02001803 gint s_alpha = CLAMP ((gint) (alpha->alpha * 255), 0, 255);
1804 gint i, j;
1805 gint y, u, v;
1806 gint p[4]; /* Y U Y V */
1807 gint src_stride;
1808 const guint8 *src_tmp;
Wim Taymans8b7c3ac2004-05-28 18:01:34 +00001809
Wim Taymans3c27f242011-07-04 17:00:34 +02001810 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
1811 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
Wim Taymans476e2182011-07-04 16:09:33 +02001812
Wim Taymansb9b007e2011-07-04 18:06:48 +02001813 width = GST_VIDEO_FRAME_WIDTH (in_frame);
1814 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
Wim Taymans476e2182011-07-04 16:09:33 +02001815
Wim Taymansb9b007e2011-07-04 18:06:48 +02001816 src_stride = GST_VIDEO_FRAME_COMP_STRIDE (in_frame, 0);
Sebastian Dröge545b21c2010-04-22 15:20:24 +02001817
Wim Taymansc395bf62013-09-19 16:55:25 +02001818 p[0] = GST_VIDEO_FRAME_COMP_POFFSET (in_frame, 0);
Sebastian Dröge545b21c2010-04-22 15:20:24 +02001819 p[2] = p[0] + 2;
Wim Taymansc395bf62013-09-19 16:55:25 +02001820 p[1] = GST_VIDEO_FRAME_COMP_POFFSET (in_frame, 1);
1821 p[3] = GST_VIDEO_FRAME_COMP_POFFSET (in_frame, 2);
Sebastian Dröge545b21c2010-04-22 15:20:24 +02001822
1823 if (alpha->in_sdtv != alpha->out_sdtv) {
1824 gint matrix[12];
1825
1826 memcpy (matrix,
1827 alpha->in_sdtv ? cog_ycbcr_sdtv_to_ycbcr_hdtv_matrix_8bit :
1828 cog_ycbcr_hdtv_to_ycbcr_sdtv_matrix_8bit, 12 * sizeof (gint));
1829
1830 for (i = 0; i < height; i++) {
1831 src_tmp = src;
1832
1833 for (j = 0; j < width - 1; j += 2) {
1834 dest[0] = s_alpha;
1835 dest[4] = s_alpha;
1836
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]]);
1840
1841 dest[1] = y;
1842 dest[2] = u;
1843 dest[3] = v;
1844
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]]);
1848
1849 dest[5] = y;
1850 dest[6] = u;
1851 dest[7] = v;
1852
1853 dest += 8;
1854 src += 4;
1855 }
1856
1857 if (j == width - 1) {
1858 dest[0] = s_alpha;
1859
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]]);
1863
1864 dest[1] = y;
1865 dest[2] = u;
1866 dest[3] = v;
1867
1868 dest += 4;
1869 }
1870
1871 src = src_tmp + src_stride;
1872 }
1873 } else {
1874 for (i = 0; i < height; i++) {
1875 src_tmp = src;
1876
1877 for (j = 0; j < width - 1; j += 2) {
1878 dest[0] = s_alpha;
1879 dest[4] = s_alpha;
1880
1881 y = src[p[0]];
1882 u = src[p[1]];
Tim-Philipp Müllerc4fa54d2015-03-10 09:31:20 +00001883 v = src[p[3]];
Sebastian Dröge545b21c2010-04-22 15:20:24 +02001884
1885 dest[1] = y;
1886 dest[2] = u;
1887 dest[3] = v;
1888
1889 y = src[p[2]];
1890
1891 dest[5] = y;
1892 dest[6] = u;
1893 dest[7] = v;
1894
1895 dest += 8;
1896 src += 4;
1897 }
1898
1899 if (j == width - 1) {
1900 dest[0] = s_alpha;
1901
1902 y = src[p[0]];
1903 u = src[p[1]];
Tim-Philipp Müllerc4fa54d2015-03-10 09:31:20 +00001904 v = src[p[3]];
Sebastian Dröge545b21c2010-04-22 15:20:24 +02001905
1906 dest[1] = y;
1907 dest[2] = u;
1908 dest[3] = v;
1909
1910 dest += 4;
1911 }
1912
1913 src = src_tmp + src_stride;
1914 }
1915 }
1916}
1917
1918static void
Wim Taymans476e2182011-07-04 16:09:33 +02001919gst_alpha_chroma_key_packed_422_ayuv (const GstVideoFrame * in_frame,
Wim Taymansb9b007e2011-07-04 18:06:48 +02001920 GstVideoFrame * out_frame, GstAlpha * alpha)
Sebastian Dröge545b21c2010-04-22 15:20:24 +02001921{
Wim Taymans476e2182011-07-04 16:09:33 +02001922 const guint8 *src;
1923 guint8 *dest;
1924 gint width, height;
Sebastian Dröge545b21c2010-04-22 15:20:24 +02001925 gint i, j;
1926 gint a, y, u, v;
1927 gint smin, smax;
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 */
1937 gint src_stride;
1938 const guint8 *src_tmp;
1939
Wim Taymans3c27f242011-07-04 17:00:34 +02001940 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
1941 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
Wim Taymans476e2182011-07-04 16:09:33 +02001942
Wim Taymansb9b007e2011-07-04 18:06:48 +02001943 width = GST_VIDEO_FRAME_WIDTH (in_frame);
1944 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
Wim Taymans476e2182011-07-04 16:09:33 +02001945
Wim Taymansb9b007e2011-07-04 18:06:48 +02001946 src_stride = GST_VIDEO_FRAME_COMP_STRIDE (in_frame, 0);
Sebastian Dröge545b21c2010-04-22 15:20:24 +02001947
Wim Taymansc395bf62013-09-19 16:55:25 +02001948 p[0] = GST_VIDEO_FRAME_COMP_POFFSET (in_frame, 0);
Sebastian Dröge545b21c2010-04-22 15:20:24 +02001949 p[2] = p[0] + 2;
Wim Taymansc395bf62013-09-19 16:55:25 +02001950 p[1] = GST_VIDEO_FRAME_COMP_POFFSET (in_frame, 1);
1951 p[3] = GST_VIDEO_FRAME_COMP_POFFSET (in_frame, 2);
Sebastian Dröge545b21c2010-04-22 15:20:24 +02001952
1953 smin = 128 - alpha->black_sensitivity;
1954 smax = 128 + alpha->white_sensitivity;
1955
1956 if (alpha->in_sdtv != alpha->out_sdtv) {
1957 gint matrix[12];
1958
1959 memcpy (matrix,
1960 alpha->in_sdtv ? cog_ycbcr_sdtv_to_ycbcr_hdtv_matrix_8bit :
1961 cog_ycbcr_hdtv_to_ycbcr_sdtv_matrix_8bit, 12 * sizeof (gint));
1962
1963 for (i = 0; i < height; i++) {
1964 src_tmp = src;
1965
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;
1970
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);
1974
1975 dest[0] = a;
1976 dest[1] = y;
1977 dest[2] = u + 128;
1978 dest[3] = v + 128;
1979
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;
1983
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);
1987
1988 dest[4] = a;
1989 dest[5] = y;
1990 dest[6] = u + 128;
1991 dest[7] = v + 128;
1992
1993 dest += 8;
1994 src += 4;
1995 }
1996
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;
2001
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);
2005
2006 dest[0] = a;
2007 dest[1] = y;
2008 dest[2] = u + 128;
2009 dest[3] = v + 128;
2010
2011 dest += 4;
2012 }
2013
2014 src = src_tmp + src_stride;
2015 }
2016 } else {
2017 for (i = 0; i < height; i++) {
2018 src_tmp = src;
2019
2020 for (j = 0; j < width - 1; j += 2) {
2021 y = src[p[0]];
2022 u = src[p[1]] - 128;
2023 v = src[p[3]] - 128;
2024
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);
2028
2029 dest[0] = a;
2030 dest[1] = y;
2031 dest[2] = u + 128;
2032 dest[3] = v + 128;
2033
2034 y = src[p[2]];
2035 u = src[p[1]] - 128;
2036 v = src[p[3]] - 128;
2037
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);
2041
2042 dest[4] = a;
2043 dest[5] = y;
2044 dest[6] = u + 128;
2045 dest[7] = v + 128;
2046
2047 dest += 8;
2048 src += 4;
2049 }
2050
2051 if (j == width - 1) {
2052 y = src[p[0]];
2053 u = src[p[1]] - 128;
2054 v = src[p[3]] - 128;
2055
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);
2059
2060 dest[0] = a;
2061 dest[1] = y;
2062 dest[2] = u + 128;
2063 dest[3] = v + 128;
2064
2065 dest += 4;
2066 }
2067
2068 src = src_tmp + src_stride;
2069 }
2070 }
2071}
2072
2073static void
Wim Taymans476e2182011-07-04 16:09:33 +02002074gst_alpha_set_packed_422_argb (const GstVideoFrame * in_frame,
2075 GstVideoFrame * out_frame, GstAlpha * alpha)
Sebastian Dröge545b21c2010-04-22 15:20:24 +02002076{
Wim Taymans476e2182011-07-04 16:09:33 +02002077 const guint8 *src;
2078 guint8 *dest;
2079 gint width, height;
Sebastian Dröge545b21c2010-04-22 15:20:24 +02002080 gint s_alpha = CLAMP ((gint) (alpha->alpha * 255), 0, 255);
2081 gint i, j;
2082 gint p[4], o[4];
2083 gint src_stride;
2084 const guint8 *src_tmp;
2085 gint matrix[12];
2086 gint r, g, b;
2087
Wim Taymans3c27f242011-07-04 17:00:34 +02002088 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
2089 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
Wim Taymans476e2182011-07-04 16:09:33 +02002090
Wim Taymansb9b007e2011-07-04 18:06:48 +02002091 width = GST_VIDEO_FRAME_WIDTH (in_frame);
2092 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
Wim Taymans476e2182011-07-04 16:09:33 +02002093
Wim Taymansb9b007e2011-07-04 18:06:48 +02002094 src_stride = GST_VIDEO_FRAME_COMP_STRIDE (in_frame, 0);
Sebastian Dröge545b21c2010-04-22 15:20:24 +02002095
Wim Taymansc395bf62013-09-19 16:55:25 +02002096 o[0] = GST_VIDEO_FRAME_COMP_POFFSET (in_frame, 0);
Sebastian Dröge545b21c2010-04-22 15:20:24 +02002097 o[2] = o[0] + 2;
Wim Taymansc395bf62013-09-19 16:55:25 +02002098 o[1] = GST_VIDEO_FRAME_COMP_POFFSET (in_frame, 1);
2099 o[3] = GST_VIDEO_FRAME_COMP_POFFSET (in_frame, 2);
Sebastian Dröge545b21c2010-04-22 15:20:24 +02002100
Wim Taymansc395bf62013-09-19 16:55:25 +02002101 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);
Sebastian Dröge545b21c2010-04-22 15:20:24 +02002105
2106 memcpy (matrix,
2107 alpha->in_sdtv ? cog_ycbcr_to_rgb_matrix_8bit_sdtv :
2108 cog_ycbcr_to_rgb_matrix_8bit_hdtv, 12 * sizeof (gint));
2109
2110 for (i = 0; i < height; i++) {
2111 src_tmp = src;
2112
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]]);
2117
2118 dest[p[0]] = s_alpha;
Sebastian Dröge1897ab22010-04-22 15:42:03 +02002119 dest[p[1]] = CLAMP (r, 0, 255);
2120 dest[p[2]] = CLAMP (g, 0, 255);
2121 dest[p[3]] = CLAMP (b, 0, 255);
Sebastian Dröge545b21c2010-04-22 15:20:24 +02002122
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]]);
2126
2127 dest[4 + p[0]] = s_alpha;
Sebastian Dröge1897ab22010-04-22 15:42:03 +02002128 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);
Sebastian Dröge545b21c2010-04-22 15:20:24 +02002131
2132 dest += 8;
2133 src += 4;
2134 }
2135
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]]);
2140
2141 dest[p[0]] = s_alpha;
Sebastian Dröge1897ab22010-04-22 15:42:03 +02002142 dest[p[1]] = CLAMP (r, 0, 255);
2143 dest[p[2]] = CLAMP (g, 0, 255);
2144 dest[p[3]] = CLAMP (b, 0, 255);
Sebastian Dröge545b21c2010-04-22 15:20:24 +02002145
2146 dest += 4;
2147 }
2148
2149 src = src_tmp + src_stride;
2150 }
2151}
2152
2153static void
Wim Taymans476e2182011-07-04 16:09:33 +02002154gst_alpha_chroma_key_packed_422_argb (const GstVideoFrame * in_frame,
Wim Taymansb9b007e2011-07-04 18:06:48 +02002155 GstVideoFrame * out_frame, GstAlpha * alpha)
Sebastian Dröge545b21c2010-04-22 15:20:24 +02002156{
Wim Taymans476e2182011-07-04 16:09:33 +02002157 const guint8 *src;
2158 guint8 *dest;
2159 gint width, height;
Sebastian Dröge545b21c2010-04-22 15:20:24 +02002160 gint i, j;
2161 gint a, y, u, v;
2162 gint r, g, b;
2163 gint smin, smax;
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;
2172 gint p[4], o[4];
2173 gint src_stride;
2174 const guint8 *src_tmp;
2175 gint matrix[12];
2176
Wim Taymans3c27f242011-07-04 17:00:34 +02002177 src = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
2178 dest = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
Wim Taymans476e2182011-07-04 16:09:33 +02002179
Wim Taymansb9b007e2011-07-04 18:06:48 +02002180 width = GST_VIDEO_FRAME_WIDTH (in_frame);
2181 height = GST_VIDEO_FRAME_HEIGHT (in_frame);
Wim Taymans476e2182011-07-04 16:09:33 +02002182
Wim Taymansb9b007e2011-07-04 18:06:48 +02002183 src_stride = GST_VIDEO_FRAME_COMP_STRIDE (in_frame, 0);
Sebastian Dröge545b21c2010-04-22 15:20:24 +02002184
Wim Taymansc395bf62013-09-19 16:55:25 +02002185 o[0] = GST_VIDEO_FRAME_COMP_POFFSET (in_frame, 0);
Sebastian Dröge545b21c2010-04-22 15:20:24 +02002186 o[2] = o[0] + 2;
Wim Taymansc395bf62013-09-19 16:55:25 +02002187 o[1] = GST_VIDEO_FRAME_COMP_POFFSET (in_frame, 1);
2188 o[3] = GST_VIDEO_FRAME_COMP_POFFSET (in_frame, 2);
Sebastian Dröge545b21c2010-04-22 15:20:24 +02002189
Wim Taymansc395bf62013-09-19 16:55:25 +02002190 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);
Sebastian Dröge545b21c2010-04-22 15:20:24 +02002194
2195 memcpy (matrix,
2196 alpha->in_sdtv ? cog_ycbcr_to_rgb_matrix_8bit_sdtv :
2197 cog_ycbcr_to_rgb_matrix_8bit_hdtv, 12 * sizeof (gint));
2198
2199 smin = 128 - alpha->black_sensitivity;
2200 smax = 128 + alpha->white_sensitivity;
2201
2202 for (i = 0; i < height; i++) {
2203 src_tmp = src;
2204
2205 for (j = 0; j < width - 1; j += 2) {
2206 y = src[o[0]];
2207 u = src[o[1]] - 128;
2208 v = src[o[3]] - 128;
2209
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);
2213 u += 128;
2214 v += 128;
2215
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);
2219
2220 dest[p[0]] = a;
Sebastian Dröge1897ab22010-04-22 15:42:03 +02002221 dest[p[1]] = CLAMP (r, 0, 255);
2222 dest[p[2]] = CLAMP (g, 0, 255);
2223 dest[p[3]] = CLAMP (b, 0, 255);
Sebastian Dröge545b21c2010-04-22 15:20:24 +02002224
2225 y = src[o[2]];
2226 u = src[o[1]] - 128;
2227 v = src[o[3]] - 128;
2228
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);
2232 u += 128;
2233 v += 128;
2234
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);
2238
2239 dest[4 + p[0]] = a;
Sebastian Dröge1897ab22010-04-22 15:42:03 +02002240 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);
Sebastian Dröge545b21c2010-04-22 15:20:24 +02002243
2244 dest += 8;
2245 src += 4;
2246 }
2247
2248 if (j == width - 1) {
2249 y = src[o[0]];
2250 u = src[o[1]] - 128;
2251 v = src[o[3]] - 128;
2252
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);
2256 u += 128;
2257 v += 128;
2258
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);
2262
2263 dest[p[0]] = a;
Sebastian Dröge1897ab22010-04-22 15:42:03 +02002264 dest[p[1]] = CLAMP (r, 0, 255);
2265 dest[p[2]] = CLAMP (g, 0, 255);
2266 dest[p[3]] = CLAMP (b, 0, 255);
Sebastian Dröge545b21c2010-04-22 15:20:24 +02002267
2268 dest += 4;
2269 }
2270
2271 src = src_tmp + src_stride;
2272 }
2273}
Wim Taymans8b7c3ac2004-05-28 18:01:34 +00002274
Sebastian Drögeab3b4bc2010-05-26 13:13:44 +02002275/* Protected with the alpha lock */
Wim Taymans8b7c3ac2004-05-28 18:01:34 +00002276static void
Edward Hervey4b2a0ab2012-01-04 13:25:40 +01002277gst_alpha_init_params_full (GstAlpha * alpha,
2278 const GstVideoFormatInfo * in_info, const GstVideoFormatInfo * out_info)
Wim Taymans2cf37532004-11-04 17:15:19 +00002279{
Sebastian Dröge46025bb2010-03-19 18:18:08 +01002280 gfloat kgl;
2281 gfloat tmp;
2282 gfloat tmp1, tmp2;
2283 gfloat y;
Youness Alaouia65fd142013-02-21 15:01:15 -05002284 guint target_r = alpha->target_r;
2285 guint target_g = alpha->target_g;
2286 guint target_b = alpha->target_b;
Sebastian Dröge6b0c5352010-03-19 18:11:12 +01002287 const gint *matrix;
2288
Youness Alaouia65fd142013-02-21 15:01:15 -05002289 switch (alpha->method) {
2290 case ALPHA_METHOD_GREEN:
2291 target_r = 0;
2292 target_g = 255;
2293 target_b = 0;
2294 break;
2295 case ALPHA_METHOD_BLUE:
2296 target_r = 0;
2297 target_g = 0;
2298 target_b = 255;
2299 break;
2300 default:
2301 break;
2302 }
2303
Sebastian Drögeeb7a1462010-03-20 10:18:04 +01002304 /* 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
2308 */
Wim Taymansb9b007e2011-07-04 18:06:48 +02002309 if (GST_VIDEO_FORMAT_INFO_IS_RGB (in_info)
2310 && GST_VIDEO_FORMAT_INFO_IS_RGB (out_info))
Sebastian Drögeeb7a1462010-03-20 10:18:04 +01002311 matrix = cog_rgb_to_ycbcr_matrix_8bit_sdtv;
Wim Taymansb9b007e2011-07-04 18:06:48 +02002312 else if (GST_VIDEO_FORMAT_INFO_IS_YUV (in_info)
2313 && GST_VIDEO_FORMAT_INFO_IS_RGB (out_info))
Sebastian Drögeeb7a1462010-03-20 10:18:04 +01002314 matrix =
2315 (alpha->in_sdtv) ? cog_rgb_to_ycbcr_matrix_8bit_sdtv :
2316 cog_rgb_to_ycbcr_matrix_8bit_hdtv;
Wim Taymansb9b007e2011-07-04 18:06:48 +02002317 else if (GST_VIDEO_FORMAT_INFO_IS_RGB (in_info)
2318 && GST_VIDEO_FORMAT_INFO_IS_YUV (out_info))
Sebastian Drögeeb7a1462010-03-20 10:18:04 +01002319 matrix =
2320 (alpha->out_sdtv) ? cog_rgb_to_ycbcr_matrix_8bit_sdtv :
2321 cog_rgb_to_ycbcr_matrix_8bit_hdtv;
2322 else /* yuv -> yuv */
2323 matrix =
2324 (alpha->out_sdtv) ? cog_rgb_to_ycbcr_matrix_8bit_sdtv :
2325 cog_rgb_to_ycbcr_matrix_8bit_hdtv;
Wim Taymans2cf37532004-11-04 17:15:19 +00002326
Youness Alaouia65fd142013-02-21 15:01:15 -05002327 y = (matrix[0] * ((gint) target_r) +
2328 matrix[1] * ((gint) target_g) +
2329 matrix[2] * ((gint) target_b) + matrix[3]) >> 8;
Sebastian Dröge6b0c5352010-03-19 18:11:12 +01002330 /* Cb,Cr without offset here because the chroma keying
2331 * works with them being in range [-128,127]
2332 */
Wim Taymans2cf37532004-11-04 17:15:19 +00002333 tmp1 =
Youness Alaouia65fd142013-02-21 15:01:15 -05002334 (matrix[4] * ((gint) target_r) +
2335 matrix[5] * ((gint) target_g) + matrix[6] * ((gint) target_b)) >> 8;
Wim Taymans2cf37532004-11-04 17:15:19 +00002336 tmp2 =
Youness Alaouia65fd142013-02-21 15:01:15 -05002337 (matrix[8] * ((gint) target_r) +
2338 matrix[9] * ((gint) target_g) + matrix[10] * ((gint) target_b)) >> 8;
Sebastian Dröge6b0c5352010-03-19 18:11:12 +01002339
Wim Taymans2cf37532004-11-04 17:15:19 +00002340 kgl = sqrt (tmp1 * tmp1 + tmp2 * tmp2);
2341 alpha->cb = 127 * (tmp1 / kgl);
2342 alpha->cr = 127 * (tmp2 / kgl);
2343
Wim Taymans2cf37532004-11-04 17:15:19 +00002344 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;
2350 tmp = 1 / (kgl);
2351 alpha->one_over_kc = 255 * 2 * tmp - 255;
Sebastian Dröge46025bb2010-03-19 18:18:08 +01002352 tmp = 15 * y / kgl;
Wim Taymans2cf37532004-11-04 17:15:19 +00002353 tmp = MIN (tmp, 255);
2354 alpha->kfgy_scale = tmp;
2355 alpha->kg = MIN (kgl, 127);
Sebastian Drögedad4e962010-03-18 19:00:09 +01002356
2357 alpha->noise_level2 = alpha->noise_level * alpha->noise_level;
Wim Taymans2cf37532004-11-04 17:15:19 +00002358}
2359
Edward Hervey4b2a0ab2012-01-04 13:25:40 +01002360static void
2361gst_alpha_init_params (GstAlpha * alpha)
2362{
Tim-Philipp Müllerb072c782012-04-30 23:57:28 +01002363 const GstVideoFormatInfo *finfo_in, *finfo_out;
2364
2365 finfo_in = GST_VIDEO_FILTER (alpha)->in_info.finfo;
2366 finfo_out = GST_VIDEO_FILTER (alpha)->out_info.finfo;
2367
2368 if (finfo_in != NULL && finfo_out != NULL) {
2369 gst_alpha_init_params_full (alpha, finfo_in, finfo_out);
2370 } else {
2371 GST_DEBUG_OBJECT (alpha, "video formats not set yet");
2372 }
Edward Hervey4b2a0ab2012-01-04 13:25:40 +01002373}
2374
Sebastian Drögeab3b4bc2010-05-26 13:13:44 +02002375/* Protected with the alpha lock */
Edward Hervey7f27c4a2008-01-09 12:01:14 +00002376static gboolean
Edward Hervey4b2a0ab2012-01-04 13:25:40 +01002377gst_alpha_set_process_function_full (GstAlpha * alpha, GstVideoInfo * in_info,
2378 GstVideoInfo * out_info)
Sebastian Dröge6b0c5352010-03-19 18:11:12 +01002379{
2380 alpha->process = NULL;
Sebastian Dröge985ec022010-03-20 20:46:19 +01002381
Sebastian Dröge6b0c5352010-03-19 18:11:12 +01002382 switch (alpha->method) {
2383 case ALPHA_METHOD_SET:
Wim Taymans22146572011-12-21 23:51:03 +01002384 switch (GST_VIDEO_INFO_FORMAT (out_info)) {
Sebastian Dröge6b0c5352010-03-19 18:11:12 +01002385 case GST_VIDEO_FORMAT_AYUV:
Wim Taymans22146572011-12-21 23:51:03 +01002386 switch (GST_VIDEO_INFO_FORMAT (in_info)) {
Sebastian Dröge6b0c5352010-03-19 18:11:12 +01002387 case GST_VIDEO_FORMAT_AYUV:
Sebastian Dröge00b3eb12010-03-19 18:21:19 +01002388 alpha->process = gst_alpha_set_ayuv_ayuv;
Sebastian Dröge6b0c5352010-03-19 18:11:12 +01002389 break;
Sebastian Dröge0294e1e2010-04-21 17:41:43 +02002390 case GST_VIDEO_FORMAT_Y444:
2391 case GST_VIDEO_FORMAT_Y42B:
Sebastian Dröge6b0c5352010-03-19 18:11:12 +01002392 case GST_VIDEO_FORMAT_I420:
Sebastian Drögeba72a052010-04-21 17:15:33 +02002393 case GST_VIDEO_FORMAT_YV12:
Sebastian Dröge0294e1e2010-04-21 17:41:43 +02002394 case GST_VIDEO_FORMAT_Y41B:
2395 alpha->process = gst_alpha_set_planar_yuv_ayuv;
Sebastian Dröge6b0c5352010-03-19 18:11:12 +01002396 break;
Sebastian Dröge545b21c2010-04-22 15:20:24 +02002397 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;
2401 break;
Sebastian Dröge5bbc7dd2010-03-20 21:13:23 +01002402 case GST_VIDEO_FORMAT_ARGB:
Sebastian Dröge0294e1e2010-04-21 17:41:43 +02002403 case GST_VIDEO_FORMAT_ABGR:
2404 case GST_VIDEO_FORMAT_RGBA:
2405 case GST_VIDEO_FORMAT_BGRA:
Sebastian Dröge5bbc7dd2010-03-20 21:13:23 +01002406 alpha->process = gst_alpha_set_argb_ayuv;
2407 break;
Sebastian Drögeb78937a2010-03-20 21:30:58 +01002408 case GST_VIDEO_FORMAT_xRGB:
Sebastian Drögeb78937a2010-03-20 21:30:58 +01002409 case GST_VIDEO_FORMAT_xBGR:
Sebastian Drögeb78937a2010-03-20 21:30:58 +01002410 case GST_VIDEO_FORMAT_RGBx:
Sebastian Drögeb78937a2010-03-20 21:30:58 +01002411 case GST_VIDEO_FORMAT_BGRx:
Sebastian Drögeb78937a2010-03-20 21:30:58 +01002412 case GST_VIDEO_FORMAT_RGB:
Sebastian Dröge0294e1e2010-04-21 17:41:43 +02002413 case GST_VIDEO_FORMAT_BGR:
Sebastian Drögeb78937a2010-03-20 21:30:58 +01002414 alpha->process = gst_alpha_set_rgb_ayuv;
2415 break;
Sebastian Dröge6b0c5352010-03-19 18:11:12 +01002416 default:
2417 break;
2418 }
Sebastian Dröge985ec022010-03-20 20:46:19 +01002419 break;
2420 case GST_VIDEO_FORMAT_ARGB:
Sebastian Dröge0294e1e2010-04-21 17:41:43 +02002421 case GST_VIDEO_FORMAT_ABGR:
2422 case GST_VIDEO_FORMAT_RGBA:
2423 case GST_VIDEO_FORMAT_BGRA:
Wim Taymans22146572011-12-21 23:51:03 +01002424 switch (GST_VIDEO_INFO_FORMAT (in_info)) {
Sebastian Dröge985ec022010-03-20 20:46:19 +01002425 case GST_VIDEO_FORMAT_AYUV:
2426 alpha->process = gst_alpha_set_ayuv_argb;
2427 break;
Sebastian Dröge0294e1e2010-04-21 17:41:43 +02002428 case GST_VIDEO_FORMAT_Y444:
2429 case GST_VIDEO_FORMAT_Y42B:
Sebastian Dröge985ec022010-03-20 20:46:19 +01002430 case GST_VIDEO_FORMAT_I420:
Sebastian Drögeba72a052010-04-21 17:15:33 +02002431 case GST_VIDEO_FORMAT_YV12:
Sebastian Dröge0294e1e2010-04-21 17:41:43 +02002432 case GST_VIDEO_FORMAT_Y41B:
2433 alpha->process = gst_alpha_set_planar_yuv_argb;
Sebastian Dröge985ec022010-03-20 20:46:19 +01002434 break;
Sebastian Dröge545b21c2010-04-22 15:20:24 +02002435 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;
2439 break;
Sebastian Dröge5bbc7dd2010-03-20 21:13:23 +01002440 case GST_VIDEO_FORMAT_ARGB:
Sebastian Dröge0294e1e2010-04-21 17:41:43 +02002441 case GST_VIDEO_FORMAT_ABGR:
2442 case GST_VIDEO_FORMAT_RGBA:
2443 case GST_VIDEO_FORMAT_BGRA:
Sebastian Dröge5bbc7dd2010-03-20 21:13:23 +01002444 alpha->process = gst_alpha_set_argb_argb;
2445 break;
Sebastian Drögeb78937a2010-03-20 21:30:58 +01002446 case GST_VIDEO_FORMAT_xRGB:
Sebastian Drögeb78937a2010-03-20 21:30:58 +01002447 case GST_VIDEO_FORMAT_xBGR:
Sebastian Drögeb78937a2010-03-20 21:30:58 +01002448 case GST_VIDEO_FORMAT_RGBx:
Sebastian Drögeb78937a2010-03-20 21:30:58 +01002449 case GST_VIDEO_FORMAT_BGRx:
Sebastian Drögeb78937a2010-03-20 21:30:58 +01002450 case GST_VIDEO_FORMAT_RGB:
Sebastian Dröge0294e1e2010-04-21 17:41:43 +02002451 case GST_VIDEO_FORMAT_BGR:
Sebastian Drögeb78937a2010-03-20 21:30:58 +01002452 alpha->process = gst_alpha_set_rgb_argb;
2453 break;
Sebastian Dröge985ec022010-03-20 20:46:19 +01002454 default:
2455 break;
2456 }
2457 break;
Sebastian Dröge6b0c5352010-03-19 18:11:12 +01002458 default:
2459 break;
2460 }
2461 break;
2462 case ALPHA_METHOD_GREEN:
2463 case ALPHA_METHOD_BLUE:
2464 case ALPHA_METHOD_CUSTOM:
Wim Taymans22146572011-12-21 23:51:03 +01002465 switch (GST_VIDEO_INFO_FORMAT (out_info)) {
Sebastian Dröge6b0c5352010-03-19 18:11:12 +01002466 case GST_VIDEO_FORMAT_AYUV:
Wim Taymans22146572011-12-21 23:51:03 +01002467 switch (GST_VIDEO_INFO_FORMAT (in_info)) {
Sebastian Dröge6b0c5352010-03-19 18:11:12 +01002468 case GST_VIDEO_FORMAT_AYUV:
Sebastian Dröge00b3eb12010-03-19 18:21:19 +01002469 alpha->process = gst_alpha_chroma_key_ayuv_ayuv;
Sebastian Dröge6b0c5352010-03-19 18:11:12 +01002470 break;
Sebastian Dröge0294e1e2010-04-21 17:41:43 +02002471 case GST_VIDEO_FORMAT_Y444:
2472 case GST_VIDEO_FORMAT_Y42B:
Sebastian Dröge6b0c5352010-03-19 18:11:12 +01002473 case GST_VIDEO_FORMAT_I420:
Sebastian Drögeba72a052010-04-21 17:15:33 +02002474 case GST_VIDEO_FORMAT_YV12:
Sebastian Dröge0294e1e2010-04-21 17:41:43 +02002475 case GST_VIDEO_FORMAT_Y41B:
2476 alpha->process = gst_alpha_chroma_key_planar_yuv_ayuv;
Sebastian Dröge6b0c5352010-03-19 18:11:12 +01002477 break;
Sebastian Dröge545b21c2010-04-22 15:20:24 +02002478 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;
2482 break;
Sebastian Dröge5bbc7dd2010-03-20 21:13:23 +01002483 case GST_VIDEO_FORMAT_ARGB:
Sebastian Dröge0294e1e2010-04-21 17:41:43 +02002484 case GST_VIDEO_FORMAT_ABGR:
2485 case GST_VIDEO_FORMAT_RGBA:
2486 case GST_VIDEO_FORMAT_BGRA:
Sebastian Dröge5bbc7dd2010-03-20 21:13:23 +01002487 alpha->process = gst_alpha_chroma_key_argb_ayuv;
2488 break;
Sebastian Drögeb78937a2010-03-20 21:30:58 +01002489 case GST_VIDEO_FORMAT_xRGB:
Sebastian Drögeb78937a2010-03-20 21:30:58 +01002490 case GST_VIDEO_FORMAT_xBGR:
Sebastian Drögeb78937a2010-03-20 21:30:58 +01002491 case GST_VIDEO_FORMAT_RGBx:
Sebastian Drögeb78937a2010-03-20 21:30:58 +01002492 case GST_VIDEO_FORMAT_BGRx:
Sebastian Drögeb78937a2010-03-20 21:30:58 +01002493 case GST_VIDEO_FORMAT_RGB:
Sebastian Drögeb78937a2010-03-20 21:30:58 +01002494 case GST_VIDEO_FORMAT_BGR:
Sebastian Dröge0294e1e2010-04-21 17:41:43 +02002495 alpha->process = gst_alpha_chroma_key_rgb_ayuv;
Sebastian Drögeb78937a2010-03-20 21:30:58 +01002496 break;
Sebastian Dröge6b0c5352010-03-19 18:11:12 +01002497 default:
2498 break;
2499 }
Sebastian Dröge985ec022010-03-20 20:46:19 +01002500 break;
2501 case GST_VIDEO_FORMAT_ARGB:
Sebastian Dröge0294e1e2010-04-21 17:41:43 +02002502 case GST_VIDEO_FORMAT_ABGR:
2503 case GST_VIDEO_FORMAT_RGBA:
2504 case GST_VIDEO_FORMAT_BGRA:
Wim Taymans22146572011-12-21 23:51:03 +01002505 switch (GST_VIDEO_INFO_FORMAT (in_info)) {
Sebastian Dröge985ec022010-03-20 20:46:19 +01002506 case GST_VIDEO_FORMAT_AYUV:
2507 alpha->process = gst_alpha_chroma_key_ayuv_argb;
2508 break;
Sebastian Dröge0294e1e2010-04-21 17:41:43 +02002509 case GST_VIDEO_FORMAT_Y444:
2510 case GST_VIDEO_FORMAT_Y42B:
Sebastian Dröge985ec022010-03-20 20:46:19 +01002511 case GST_VIDEO_FORMAT_I420:
Sebastian Drögeba72a052010-04-21 17:15:33 +02002512 case GST_VIDEO_FORMAT_YV12:
Sebastian Dröge0294e1e2010-04-21 17:41:43 +02002513 case GST_VIDEO_FORMAT_Y41B:
2514 alpha->process = gst_alpha_chroma_key_planar_yuv_argb;
Sebastian Dröge985ec022010-03-20 20:46:19 +01002515 break;
Sebastian Dröge545b21c2010-04-22 15:20:24 +02002516 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;
2520 break;
Sebastian Dröge5bbc7dd2010-03-20 21:13:23 +01002521 case GST_VIDEO_FORMAT_ARGB:
Sebastian Dröge0294e1e2010-04-21 17:41:43 +02002522 case GST_VIDEO_FORMAT_ABGR:
2523 case GST_VIDEO_FORMAT_RGBA:
2524 case GST_VIDEO_FORMAT_BGRA:
Sebastian Dröge5bbc7dd2010-03-20 21:13:23 +01002525 alpha->process = gst_alpha_chroma_key_argb_argb;
2526 break;
Sebastian Drögeb78937a2010-03-20 21:30:58 +01002527 case GST_VIDEO_FORMAT_xRGB:
Sebastian Drögeb78937a2010-03-20 21:30:58 +01002528 case GST_VIDEO_FORMAT_xBGR:
Sebastian Drögeb78937a2010-03-20 21:30:58 +01002529 case GST_VIDEO_FORMAT_RGBx:
Sebastian Drögeb78937a2010-03-20 21:30:58 +01002530 case GST_VIDEO_FORMAT_BGRx:
Sebastian Drögeb78937a2010-03-20 21:30:58 +01002531 case GST_VIDEO_FORMAT_RGB:
Sebastian Dröge0294e1e2010-04-21 17:41:43 +02002532 case GST_VIDEO_FORMAT_BGR:
Sebastian Drögeb78937a2010-03-20 21:30:58 +01002533 alpha->process = gst_alpha_chroma_key_rgb_argb;
2534 break;
Sebastian Dröge985ec022010-03-20 20:46:19 +01002535 default:
2536 break;
2537 }
2538 break;
Sebastian Dröge6b0c5352010-03-19 18:11:12 +01002539 default:
2540 break;
2541 }
2542 break;
2543 default:
2544 break;
2545 }
2546 return alpha->process != NULL;
2547}
2548
Tim-Philipp Müllerb072c782012-04-30 23:57:28 +01002549static void
Edward Hervey4b2a0ab2012-01-04 13:25:40 +01002550gst_alpha_set_process_function (GstAlpha * alpha)
2551{
Tim-Philipp Müllerb072c782012-04-30 23:57:28 +01002552 GstVideoInfo *info_in, *info_out;
2553
2554 info_in = &GST_VIDEO_FILTER (alpha)->in_info;
2555 info_out = &GST_VIDEO_FILTER (alpha)->out_info;
2556
2557 if (info_in->finfo != NULL && info_out->finfo != NULL) {
2558 gst_alpha_set_process_function_full (alpha, info_in, info_out);
2559 } else {
2560 GST_DEBUG_OBJECT (alpha, "video formats not set yet");
2561 }
Edward Hervey4b2a0ab2012-01-04 13:25:40 +01002562}
2563
Sebastian Drögeab3b4bc2010-05-26 13:13:44 +02002564static void
2565gst_alpha_before_transform (GstBaseTransform * btrans, GstBuffer * buf)
2566{
2567 GstAlpha *alpha = GST_ALPHA (btrans);
2568 GstClockTime timestamp;
2569
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))
Stefan Sauerfb162c82011-11-04 18:41:36 +01002574 gst_object_sync_values (GST_OBJECT (alpha), timestamp);
Sebastian Drögeab3b4bc2010-05-26 13:13:44 +02002575}
2576
Wim Taymans97f9bab2005-05-17 18:13:19 +00002577static GstFlowReturn
Wim Taymans22146572011-12-21 23:51:03 +01002578gst_alpha_transform_frame (GstVideoFilter * filter, GstVideoFrame * in_frame,
2579 GstVideoFrame * out_frame)
Wim Taymans8b7c3ac2004-05-28 18:01:34 +00002580{
Wim Taymans22146572011-12-21 23:51:03 +01002581 GstAlpha *alpha = GST_ALPHA (filter);
Sebastian Drögeab3b4bc2010-05-26 13:13:44 +02002582
2583 GST_ALPHA_LOCK (alpha);
2584
Wim Taymans476e2182011-07-04 16:09:33 +02002585 if (G_UNLIKELY (!alpha->process))
2586 goto not_negotiated;
Wim Taymans8b7c3ac2004-05-28 18:01:34 +00002587
Wim Taymans22146572011-12-21 23:51:03 +01002588 alpha->process (in_frame, out_frame, alpha);
Sebastian Drögeab3b4bc2010-05-26 13:13:44 +02002589
2590 GST_ALPHA_UNLOCK (alpha);
Wim Taymans8b7c3ac2004-05-28 18:01:34 +00002591
Jan Schmidte3155412008-01-31 00:00:23 +00002592 return GST_FLOW_OK;
Wim Taymans476e2182011-07-04 16:09:33 +02002593
2594 /* ERRORS */
2595not_negotiated:
2596 {
2597 GST_ERROR_OBJECT (alpha, "Not negotiated yet");
2598 GST_ALPHA_UNLOCK (alpha);
2599 return GST_FLOW_NOT_NEGOTIATED;
2600 }
Wim Taymans8b7c3ac2004-05-28 18:01:34 +00002601}
2602
2603static gboolean
2604plugin_init (GstPlugin * plugin)
2605{
2606 return gst_element_register (plugin, "alpha", GST_RANK_NONE, GST_TYPE_ALPHA);
2607}
2608
2609GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
2610 GST_VERSION_MINOR,
Sebastian Drögeaa2cd462012-04-05 17:36:38 +02002611 alpha,
Jan Schmidte3155412008-01-31 00:00:23 +00002612 "adds an alpha channel to video - constant or via chroma-keying",
Thomas Vander Stichele6ff59b22005-11-14 02:13:35 +00002613 plugin_init, VERSION, GST_LICENSE, GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN)