1 /* GStreamer unit test for the alphacolor element
2 *
3 * Copyright (C) 2007 Tim-Philipp Müller <tim centricular net>
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Library General Public License for more details.
14 *
15 * You should have received a copy of the GNU Library General Public
16 * License along with this library; if not, write to the
17 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
18 * Boston, MA 02110-1301, USA.
19 */
20
21 #include <gst/check/gstcheck.h>
22 #include <gst/video/video.h>
23
24 /* For ease of programming we use globals to keep refs for our floating
25 * src and sink pads we create; otherwise we always have to do get_pad,
26 * get_peer, and then remove references in every test function */
27 GstPad *mysrcpad, *mysinkpad;
28
29 static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink",
30 GST_PAD_SINK,
31 GST_PAD_ALWAYS,
32 GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE ("AYUV"))
33 );
34 static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src",
35 GST_PAD_SRC,
36 GST_PAD_ALWAYS,
37 GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE ("{ RGBA, RGB }"))
38 );
39
40 static GstElement *
setup_alphacolor(void)41 setup_alphacolor (void)
42 {
43 GstElement *alphacolor;
44
45 alphacolor = gst_check_setup_element ("alphacolor");
46 mysrcpad = gst_check_setup_src_pad (alphacolor, &srctemplate);
47 mysinkpad = gst_check_setup_sink_pad (alphacolor, &sinktemplate);
48
49 gst_pad_set_active (mysrcpad, TRUE);
50 gst_pad_set_active (mysinkpad, TRUE);
51
52 return alphacolor;
53 }
54
55 static void
cleanup_alphacolor(GstElement * alphacolor)56 cleanup_alphacolor (GstElement * alphacolor)
57 {
58 GST_DEBUG ("cleaning up");
59
60 gst_pad_set_active (mysrcpad, FALSE);
61 gst_pad_set_active (mysinkpad, FALSE);
62 gst_check_teardown_src_pad (alphacolor);
63 gst_check_teardown_sink_pad (alphacolor);
64 gst_check_teardown_element (alphacolor);
65 }
66
67 #define WIDTH 3
68 #define HEIGHT 4
69
70 static GstCaps *
create_caps_rgb24(void)71 create_caps_rgb24 (void)
72 {
73 GstCaps *caps;
74
75 caps = gst_caps_new_simple ("video/x-raw",
76 "width", G_TYPE_INT, 3,
77 "height", G_TYPE_INT, 4,
78 "framerate", GST_TYPE_FRACTION, 0, 1,
79 "format", G_TYPE_STRING, "RGB", NULL);
80
81 return caps;
82 }
83
84 static GstCaps *
create_caps_rgba32(void)85 create_caps_rgba32 (void)
86 {
87 GstCaps *caps;
88
89 caps = gst_caps_new_simple ("video/x-raw",
90 "width", G_TYPE_INT, 3,
91 "height", G_TYPE_INT, 4,
92 "framerate", GST_TYPE_FRACTION, 0, 1,
93 "format", G_TYPE_STRING, "RGBA", NULL);
94
95 return caps;
96 }
97
98 static GstBuffer *
create_buffer_rgb24_3x4(void)99 create_buffer_rgb24_3x4 (void)
100 {
101 /* stride is rounded up to multiple of 4, so 3 bytes padding for each row */
102 const guint8 rgb24_3x4_img[HEIGHT * GST_ROUND_UP_4 (WIDTH * 3)] = {
103 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00,
104 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00,
105 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
106 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00
107 };
108 guint rowstride = GST_ROUND_UP_4 (WIDTH * 3);
109 GstBuffer *buf;
110 GstMapInfo info;
111
112 buf = gst_buffer_new_and_alloc (HEIGHT * rowstride);
113 gst_buffer_map (buf, &info, GST_MAP_READWRITE);
114 fail_unless_equals_int (info.size, sizeof (rgb24_3x4_img));
115 memcpy (info.data, rgb24_3x4_img, sizeof (rgb24_3x4_img));
116
117 gst_buffer_unmap (buf, &info);
118
119 return buf;
120 }
121
122 static GstBuffer *
create_buffer_rgba32_3x4(void)123 create_buffer_rgba32_3x4 (void)
124 {
125 /* stride is rounded up to multiple of 4, so 3 bytes padding for each row */
126 /* should be: RED BLUE WHITE where 'nothing' is fully transparent
127 * GREEN RED BLUE and all other colours are fully
128 * NOTHING GREEN RED opaque.
129 * BLACK NOTHING GREEN
130 */
131 const guint8 rgba32_3x4_img[HEIGHT * WIDTH * 4] = {
132 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff,
133 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff,
134 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff,
135 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff
136 };
137 guint rowstride = WIDTH * 4;
138 GstBuffer *buf;
139 GstMapInfo map;
140
141 buf = gst_buffer_new_and_alloc (HEIGHT * rowstride);
142 gst_buffer_map (buf, &map, GST_MAP_READWRITE);
143 fail_unless_equals_int (map.size, sizeof (rgba32_3x4_img));
144 memcpy (map.data, rgba32_3x4_img, sizeof (rgba32_3x4_img));
145
146 gst_buffer_unmap (buf, &map);
147
148 return buf;
149 }
150
GST_START_TEST(test_rgb24)151 GST_START_TEST (test_rgb24)
152 {
153 GstElement *alphacolor;
154 GstBuffer *inbuffer;
155 GstCaps *incaps;
156
157 incaps = create_caps_rgb24 ();
158 alphacolor = setup_alphacolor ();
159
160 fail_unless_equals_int (gst_element_set_state (alphacolor, GST_STATE_PLAYING),
161 GST_STATE_CHANGE_SUCCESS);
162
163 gst_check_setup_events (mysrcpad, alphacolor, incaps, GST_FORMAT_TIME);
164
165 inbuffer = create_buffer_rgb24_3x4 ();
166 ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
167
168 /* pushing gives away reference; this should error out with a not-negotiated
169 * error, alphacolor should only accept RGBA caps, not but plain RGB24 caps */
170 GST_DEBUG ("push it");
171 fail_unless_equals_int (gst_pad_push (mysrcpad, inbuffer),
172 GST_FLOW_NOT_NEGOTIATED);
173 GST_DEBUG ("pushed it");
174
175 fail_unless (g_list_length (buffers) == 0);
176
177 fail_unless_equals_int (gst_element_set_state (alphacolor, GST_STATE_NULL),
178 GST_STATE_CHANGE_SUCCESS);
179
180 /* cleanup */
181 GST_DEBUG ("cleanup alphacolor");
182 cleanup_alphacolor (alphacolor);
183 GST_DEBUG ("cleanup, unref incaps");
184 ASSERT_CAPS_REFCOUNT (incaps, "incaps", 1);
185 gst_caps_unref (incaps);
186 }
187
188 GST_END_TEST;
189
190 /* these macros assume WIDTH and HEIGHT is fixed to what's defined above */
191 #define fail_unless_ayuv_pixel_has_alpha(ayuv,x,y,a) \
192 { \
193 guint8 *pixel; \
194 pixel = ((guint8*)(ayuv) + ((WIDTH * 4) * (y)) + ((x) * 4)); \
195 fail_unless_equals_int (pixel[0], a); \
196 }
197
GST_START_TEST(test_rgba32)198 GST_START_TEST (test_rgba32)
199 {
200 GstElement *alphacolor;
201 GstBuffer *inbuffer;
202 GstBuffer *outbuffer;
203 GstCaps *incaps;
204 guint8 *ayuv;
205 guint outlength;
206 GstMapInfo map;
207
208 incaps = create_caps_rgba32 ();
209 alphacolor = setup_alphacolor ();
210
211 fail_unless_equals_int (gst_element_set_state (alphacolor, GST_STATE_PLAYING),
212 GST_STATE_CHANGE_SUCCESS);
213
214 gst_check_setup_events (mysrcpad, alphacolor, incaps, GST_FORMAT_TIME);
215
216 inbuffer = create_buffer_rgba32_3x4 ();
217 GST_DEBUG ("Created buffer of %" G_GSIZE_FORMAT " bytes",
218 gst_buffer_get_size (inbuffer));
219 ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
220
221 /* pushing gives away reference */
222 GST_DEBUG ("push it");
223 fail_unless_equals_int (gst_pad_push (mysrcpad, inbuffer), GST_FLOW_OK);
224 GST_DEBUG ("pushed it");
225
226 /* ... and puts a new buffer on the global list */
227 fail_unless (g_list_length (buffers) == 1);
228 outbuffer = (GstBuffer *) buffers->data;
229 fail_if (outbuffer == NULL);
230 fail_unless (GST_IS_BUFFER (outbuffer));
231
232 ASSERT_BUFFER_REFCOUNT (outbuffer, "outbuffer", 1);
233 outlength = WIDTH * HEIGHT * 4; /* output is AYUV */
234 gst_buffer_map (outbuffer, &map, GST_MAP_READ);
235 fail_unless_equals_int (map.size, outlength);
236
237 ayuv = map.data;
238
239 /* check alpha values (0x00 = totally transparent, 0xff = totally opaque) */
240 fail_unless_ayuv_pixel_has_alpha (ayuv, 0, 0, 0xff);
241 fail_unless_ayuv_pixel_has_alpha (ayuv, 1, 0, 0xff);
242 fail_unless_ayuv_pixel_has_alpha (ayuv, 2, 0, 0xff);
243 fail_unless_ayuv_pixel_has_alpha (ayuv, 0, 1, 0xff);
244 fail_unless_ayuv_pixel_has_alpha (ayuv, 1, 1, 0xff);
245 fail_unless_ayuv_pixel_has_alpha (ayuv, 2, 1, 0xff);
246 fail_unless_ayuv_pixel_has_alpha (ayuv, 0, 2, 0x00);
247 fail_unless_ayuv_pixel_has_alpha (ayuv, 1, 2, 0xff);
248 fail_unless_ayuv_pixel_has_alpha (ayuv, 2, 2, 0xff);
249 fail_unless_ayuv_pixel_has_alpha (ayuv, 0, 3, 0xff);
250 fail_unless_ayuv_pixel_has_alpha (ayuv, 1, 3, 0x00);
251 fail_unless_ayuv_pixel_has_alpha (ayuv, 2, 3, 0xff);
252
253 /* we don't check the YUV data, because apparently results differ slightly
254 * depending on whether we run in valgrind or not */
255
256 gst_buffer_unmap (outbuffer, &map);
257
258 buffers = g_list_remove (buffers, outbuffer);
259 gst_buffer_unref (outbuffer);
260
261 fail_unless_equals_int (gst_element_set_state (alphacolor, GST_STATE_NULL),
262 GST_STATE_CHANGE_SUCCESS);
263
264 /* cleanup */
265 GST_DEBUG ("cleanup alphacolor");
266 cleanup_alphacolor (alphacolor);
267 GST_DEBUG ("cleanup, unref incaps");
268 ASSERT_CAPS_REFCOUNT (incaps, "incaps", 1);
269 gst_caps_unref (incaps);
270 }
271
272 GST_END_TEST;
273
274
275 static Suite *
alphacolor_suite(void)276 alphacolor_suite (void)
277 {
278 Suite *s = suite_create ("alphacolor");
279 TCase *tc_chain = tcase_create ("general");
280
281 suite_add_tcase (s, tc_chain);
282 tcase_add_test (tc_chain, test_rgb24);
283 tcase_add_test (tc_chain, test_rgba32);
284
285 return s;
286 }
287
288 GST_CHECK_MAIN (alphacolor);
289