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