1 /* GStreamer |
|
2 * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu> |
|
3 * |
|
4 * This library is free software; you can redistribute it and/or |
|
5 * modify it under the terms of the GNU Library General Public |
|
6 * License as published by the Free Software Foundation; either |
|
7 * version 2 of the License, or (at your option) any later version. |
|
8 * |
|
9 * This library is distributed in the hope that it will be useful, |
|
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|
12 * Library General Public License for more details. |
|
13 * |
|
14 * You should have received a copy of the GNU Library General Public |
|
15 * License along with this library; if not, write to the |
|
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330, |
|
17 * Boston, MA 02111-1307, USA. |
|
18 */ |
|
19 |
|
20 /** |
|
21 * SECTION:element-alphacolor |
|
22 * |
|
23 * The alphacolor element does memory-efficient (in-place) colourspace |
|
24 * conversion from RGBA to AYUV, preserving the alpha channel. |
|
25 */ |
|
26 |
|
27 #ifdef HAVE_CONFIG_H |
|
28 #include "config.h" |
|
29 #endif |
|
30 |
|
31 #include "gstalphacolor.h" |
|
32 |
|
33 #include <gst/gst.h> |
|
34 #include <gst/video/video.h> |
|
35 |
|
36 #include <string.h> |
|
37 |
|
38 GST_DEBUG_CATEGORY_STATIC (alpha_color_debug); |
|
39 #define GST_CAT_DEFAULT alpha_color_debug |
|
40 |
|
41 /* elementfactory information */ |
|
42 static const GstElementDetails gst_alpha_color_details = |
|
43 GST_ELEMENT_DETAILS ("Alpha color filter", |
|
44 "Filter/Effect/Video", |
|
45 "RGBA to AYUV colorspace conversion preserving the alpha channel", |
|
46 "Wim Taymans <wim@fluendo.com>"); |
|
47 |
|
48 static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink", |
|
49 GST_PAD_SINK, |
|
50 GST_PAD_ALWAYS, |
|
51 GST_STATIC_CAPS (GST_VIDEO_CAPS_RGBA ";" GST_VIDEO_CAPS_BGRA) |
|
52 ); |
|
53 |
|
54 static GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE ("src", |
|
55 GST_PAD_SRC, |
|
56 GST_PAD_ALWAYS, |
|
57 GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV ("AYUV")) |
|
58 ); |
|
59 |
|
60 GST_BOILERPLATE (GstAlphaColor, gst_alpha_color, GstBaseTransform, |
|
61 GST_TYPE_BASE_TRANSFORM); |
|
62 |
|
63 static GstCaps *gst_alpha_color_transform_caps (GstBaseTransform * btrans, |
|
64 GstPadDirection direction, GstCaps * caps); |
|
65 static gboolean gst_alpha_color_set_caps (GstBaseTransform * btrans, |
|
66 GstCaps * incaps, GstCaps * outcaps); |
|
67 static GstFlowReturn gst_alpha_color_transform_ip (GstBaseTransform * btrans, |
|
68 GstBuffer * inbuf); |
|
69 |
|
70 static void |
|
71 gst_alpha_color_base_init (gpointer g_class) |
|
72 { |
|
73 GstElementClass *element_class = GST_ELEMENT_CLASS (g_class); |
|
74 |
|
75 gst_element_class_set_details (element_class, &gst_alpha_color_details); |
|
76 |
|
77 gst_element_class_add_pad_template (element_class, |
|
78 gst_static_pad_template_get (&sink_template)); |
|
79 gst_element_class_add_pad_template (element_class, |
|
80 gst_static_pad_template_get (&src_template)); |
|
81 } |
|
82 |
|
83 static void |
|
84 gst_alpha_color_class_init (GstAlphaColorClass * klass) |
|
85 { |
|
86 GstBaseTransformClass *gstbasetransform_class; |
|
87 |
|
88 gstbasetransform_class = (GstBaseTransformClass *) klass; |
|
89 |
|
90 gstbasetransform_class->transform_caps = |
|
91 GST_DEBUG_FUNCPTR (gst_alpha_color_transform_caps); |
|
92 gstbasetransform_class->set_caps = |
|
93 GST_DEBUG_FUNCPTR (gst_alpha_color_set_caps); |
|
94 gstbasetransform_class->transform_ip = |
|
95 GST_DEBUG_FUNCPTR (gst_alpha_color_transform_ip); |
|
96 |
|
97 GST_DEBUG_CATEGORY_INIT (alpha_color_debug, "alphacolor", 0, |
|
98 "RGB->YUV colorspace conversion preserving the alpha channels"); |
|
99 } |
|
100 |
|
101 static void |
|
102 gst_alpha_color_init (GstAlphaColor * alpha, GstAlphaColorClass * g_class) |
|
103 { |
|
104 GstBaseTransform *btrans = NULL; |
|
105 |
|
106 btrans = GST_BASE_TRANSFORM (alpha); |
|
107 |
|
108 btrans->always_in_place = TRUE; |
|
109 } |
|
110 |
|
111 static GstCaps * |
|
112 gst_alpha_color_transform_caps (GstBaseTransform * btrans, |
|
113 GstPadDirection direction, GstCaps * caps) |
|
114 { |
|
115 const GstCaps *tmpl_caps = NULL; |
|
116 GstCaps *result = NULL, *local_caps = NULL; |
|
117 guint i; |
|
118 |
|
119 local_caps = gst_caps_copy (caps); |
|
120 |
|
121 for (i = 0; i < gst_caps_get_size (local_caps); i++) { |
|
122 GstStructure *structure = gst_caps_get_structure (local_caps, i); |
|
123 |
|
124 /* Throw away the structure name and set it to transformed format */ |
|
125 if (direction == GST_PAD_SINK) { |
|
126 gst_structure_set_name (structure, "video/x-raw-yuv"); |
|
127 } else if (direction == GST_PAD_SRC) { |
|
128 gst_structure_set_name (structure, "video/x-raw-rgb"); |
|
129 } |
|
130 /* Remove any specific parameter from the structure */ |
|
131 gst_structure_remove_field (structure, "format"); |
|
132 gst_structure_remove_field (structure, "endianness"); |
|
133 gst_structure_remove_field (structure, "depth"); |
|
134 gst_structure_remove_field (structure, "bpp"); |
|
135 gst_structure_remove_field (structure, "red_mask"); |
|
136 gst_structure_remove_field (structure, "green_mask"); |
|
137 gst_structure_remove_field (structure, "blue_mask"); |
|
138 gst_structure_remove_field (structure, "alpha_mask"); |
|
139 } |
|
140 |
|
141 /* Get the appropriate template */ |
|
142 if (direction == GST_PAD_SINK) { |
|
143 tmpl_caps = gst_static_pad_template_get_caps (&src_template); |
|
144 } else if (direction == GST_PAD_SRC) { |
|
145 tmpl_caps = gst_static_pad_template_get_caps (&sink_template); |
|
146 } |
|
147 |
|
148 /* Intersect with our template caps */ |
|
149 result = gst_caps_intersect (local_caps, tmpl_caps); |
|
150 |
|
151 gst_caps_unref (local_caps); |
|
152 gst_caps_do_simplify (result); |
|
153 |
|
154 GST_LOG ("transformed %" GST_PTR_FORMAT " to %" GST_PTR_FORMAT, caps, result); |
|
155 |
|
156 return result; |
|
157 } |
|
158 |
|
159 static gboolean |
|
160 gst_alpha_color_set_caps (GstBaseTransform * btrans, GstCaps * incaps, |
|
161 GstCaps * outcaps) |
|
162 { |
|
163 GstAlphaColor *alpha; |
|
164 GstStructure *structure; |
|
165 gboolean ret; |
|
166 const GValue *fps; |
|
167 gint red_mask, alpha_mask; |
|
168 gint w, h, depth, bpp; |
|
169 |
|
170 alpha = GST_ALPHA_COLOR (btrans); |
|
171 structure = gst_caps_get_structure (incaps, 0); |
|
172 |
|
173 ret = gst_structure_get_int (structure, "width", &w); |
|
174 ret &= gst_structure_get_int (structure, "height", &h); |
|
175 fps = gst_structure_get_value (structure, "framerate"); |
|
176 ret &= (fps != NULL && GST_VALUE_HOLDS_FRACTION (fps)); |
|
177 ret &= gst_structure_get_int (structure, "red_mask", &red_mask); |
|
178 |
|
179 /* make sure these are really full RGBA caps */ |
|
180 ret &= gst_structure_get_int (structure, "alpha_mask", &alpha_mask); |
|
181 ret &= gst_structure_get_int (structure, "depth", &depth); |
|
182 ret &= gst_structure_get_int (structure, "bpp", &bpp); |
|
183 |
|
184 if (!ret || alpha_mask == 0 || red_mask == 0 || depth != 32 || bpp != 32) { |
|
185 GST_DEBUG_OBJECT (alpha, "incomplete or non-RGBA input caps!"); |
|
186 return FALSE; |
|
187 } |
|
188 |
|
189 alpha->in_width = w; |
|
190 alpha->in_height = h; |
|
191 alpha->in_rgba = TRUE; |
|
192 #if (G_BYTE_ORDER == G_BIG_ENDIAN) |
|
193 if (red_mask != 0x000000ff) |
|
194 #else |
|
195 if (red_mask != 0xff000000) |
|
196 #endif |
|
197 alpha->in_rgba = FALSE; |
|
198 |
|
199 return TRUE; |
|
200 } |
|
201 |
|
202 static void |
|
203 transform_rgb (guint8 * data, gint size) |
|
204 { |
|
205 guint8 y, u, v; |
|
206 |
|
207 while (size > 0) { |
|
208 y = data[0] * 0.299 + data[1] * 0.587 + data[2] * 0.114 + 0; |
|
209 u = data[0] * -0.169 + data[1] * -0.332 + data[2] * 0.500 + 128; |
|
210 v = data[0] * 0.500 + data[1] * -0.419 + data[2] * -0.0813 + 128; |
|
211 |
|
212 data[0] = data[3]; |
|
213 data[1] = y; |
|
214 data[2] = u; |
|
215 data[3] = v; |
|
216 |
|
217 data += 4; |
|
218 size -= 4; |
|
219 } |
|
220 } |
|
221 |
|
222 static void |
|
223 transform_bgr (guint8 * data, gint size) |
|
224 { |
|
225 guint8 y, u, v; |
|
226 |
|
227 while (size > 0) { |
|
228 y = data[2] * 0.299 + data[1] * 0.587 + data[0] * 0.114 + 0; |
|
229 u = data[2] * -0.169 + data[1] * -0.332 + data[0] * 0.500 + 128; |
|
230 v = data[2] * 0.500 + data[1] * -0.419 + data[0] * -0.0813 + 128; |
|
231 |
|
232 data[0] = data[3]; |
|
233 data[1] = y; |
|
234 data[2] = u; |
|
235 data[3] = v; |
|
236 |
|
237 data += 4; |
|
238 size -= 4; |
|
239 } |
|
240 } |
|
241 |
|
242 static GstFlowReturn |
|
243 gst_alpha_color_transform_ip (GstBaseTransform * btrans, GstBuffer * inbuf) |
|
244 { |
|
245 GstFlowReturn ret = GST_FLOW_OK; |
|
246 GstAlphaColor *alpha; |
|
247 |
|
248 alpha = GST_ALPHA_COLOR (btrans); |
|
249 |
|
250 /* Transform in place */ |
|
251 if (alpha->in_rgba) |
|
252 transform_rgb (GST_BUFFER_DATA (inbuf), GST_BUFFER_SIZE (inbuf)); |
|
253 else |
|
254 transform_bgr (GST_BUFFER_DATA (inbuf), GST_BUFFER_SIZE (inbuf)); |
|
255 |
|
256 return ret; |
|
257 } |
|
258 |
|
259 static gboolean |
|
260 plugin_init (GstPlugin * plugin) |
|
261 { |
|
262 return gst_element_register (plugin, "alphacolor", GST_RANK_NONE, |
|
263 GST_TYPE_ALPHA_COLOR); |
|
264 } |
|
265 |
|
266 GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, |
|
267 GST_VERSION_MINOR, |
|
268 "alphacolor", |
|
269 "RGBA to AYUV colorspace conversion preserving the alpha channel", |
|
270 plugin_init, VERSION, GST_LICENSE, GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN) |
|
271 |
|
272 |
|
273 #ifdef __SYMBIAN32__ |
|
274 EXPORT_C GstPluginDesc* _GST_PLUGIN_DESC() |
|
275 { |
|
276 return &gst_plugin_desc; |
|
277 } |
|
278 |
|
279 #endif |
|