Add initial VA/GLX support.
[profile/ivi/gstreamer-vaapi.git] / tests / test-windows.c
1 /*
2  *  test-windows.c - Test GstVaapiWindow
3  *
4  *  gstreamer-vaapi (C) 2010 Splitted-Desktop Systems
5  *
6  *  This program is free software; you can redistribute it and/or modify
7  *  it under the terms of the GNU General Public License as published by
8  *  the Free Software Foundation; either version 2 of the License, or
9  *  (at your option) any later version.
10  *
11  *  This program is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *  GNU General Public License for more details.
15  *
16  *  You should have received a copy of the GNU General Public License
17  *  along with this program; if not, write to the Free Software
18  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
19  */
20
21 #include <gst/vaapi/gstvaapidisplay_x11.h>
22 #include <gst/vaapi/gstvaapiwindow_x11.h>
23 #include <gst/vaapi/gstvaapisurface.h>
24 #include <gst/vaapi/gstvaapiimage.h>
25
26 static inline void pause(void)
27 {
28     g_print("Press any key to continue...\n");
29     getchar();
30 }
31
32 typedef void (*DrawRectFunc)(
33     guchar *pixels[3],
34     guint   stride[3],
35     gint    x,
36     gint    y,
37     guint   width,
38     guint   height,
39     guint32 color
40 );
41
42 static void draw_rect_ARGB(
43     guchar *pixels[3],
44     guint   stride[3],
45     gint    x,
46     gint    y,
47     guint   width,
48     guint   height,
49     guint32 color
50 )
51 {
52     guint i, j;
53
54     color = GUINT32_TO_BE(color);
55
56     for (j = 0; j < height; j++) {
57         guint32 *p = (guint32 *)(pixels[0] + (y + j) * stride[0] + x * 4);
58         for (i = 0; i < width; i++)
59             p[i] = color;
60     }
61 }
62
63 static void draw_rect_BGRA(
64     guchar *pixels[3],
65     guint   stride[3],
66     gint    x,
67     gint    y,
68     guint   width,
69     guint   height,
70     guint32 color
71 )
72 {
73     // Converts ARGB color to BGRA
74     color = GUINT32_SWAP_LE_BE(color);
75
76     draw_rect_ARGB(pixels, stride, x, y, width, height, color);
77 }
78
79 static void draw_rect_RGBA(
80     guchar *pixels[3],
81     guint   stride[3],
82     gint    x,
83     gint    y,
84     guint   width,
85     guint   height,
86     guint32 color
87 )
88 {
89     // Converts ARGB color to RGBA
90     color = ((color >> 24) & 0xff) | ((color & 0xffffff) << 8);
91
92     draw_rect_ARGB(pixels, stride, x, y, width, height, color);
93 }
94
95 static void draw_rect_ABGR(
96     guchar *pixels[3],
97     guint   stride[3],
98     gint    x,
99     gint    y,
100     guint   width,
101     guint   height,
102     guint32 color
103 )
104 {
105     // Converts ARGB color to ABGR
106     color = ((color & 0xff00ff00)   |
107              ((color >> 16) & 0xff) |
108              ((color & 0xff) << 16));
109
110     draw_rect_ARGB(pixels, stride, x, y, width, height, color);
111 }
112
113 static void draw_rect_NV12( // Y, UV planes
114     guchar *pixels[3],
115     guint   stride[3],
116     gint    x,
117     gint    y,
118     guint   width,
119     guint   height,
120     guint32 color
121 )
122 {
123     const guchar Y  = color >> 16;
124     const guchar Cb = color >> 8;
125     const guchar Cr = color;
126     guchar *dst;
127     guint i, j;
128
129     dst = pixels[0] + y * stride[0] + x;
130     for (j = 0; j < height; j++, dst += stride[0])
131         for (i = 0; i < width; i++)
132             dst[i] = Y;
133
134     x      /= 2;
135     y      /= 2;
136     width  /= 2;
137     height /= 2;
138
139     dst = pixels[1] + y * stride[1] + x * 2;
140     for (j = 0; j < height; j++, dst += stride[1])
141         for (i = 0; i < width; i++) {
142             dst[2*i + 0] = Cb;
143             dst[2*i + 1] = Cr;
144         }
145 }
146
147 static void draw_rect_YV12( // Y, U, V planes
148     guchar *pixels[3],
149     guint   stride[3],
150     gint    x,
151     gint    y,
152     guint   width,
153     guint   height,
154     guint32 color
155 )
156 {
157     const guchar Y  = color >> 16;
158     const guchar Cb = color >> 8;
159     const guchar Cr = color;
160     guchar *pY, *pU, *pV;
161     guint i, j;
162
163     pY = pixels[0] + y * stride[0] + x;
164     for (j = 0; j < height; j++, pY += stride[0])
165         for (i = 0; i < width; i++)
166             pY[i] = Y;
167
168     x      /= 2;
169     y      /= 2;
170     width  /= 2;
171     height /= 2;
172
173     pU = pixels[1] + y * stride[1] + x;
174     pV = pixels[2] + y * stride[2] + x;
175     for (j = 0; j < height; j++, pU += stride[1], pV += stride[2])
176         for (i = 0; i < width; i++) {
177             pU[i] = Cb;
178             pV[i] = Cr;
179         }
180 }
181
182 static void draw_rect_AYUV(
183     guchar *pixels[3],
184     guint   stride[3],
185     gint    x,
186     gint    y,
187     guint   width,
188     guint   height,
189     guint32 color
190 )
191 {
192     guint i, j;
193
194     color = color | 0xff000000;
195
196     for (j = 0; j < height; j++) {
197         guint32 *p = (guint32 *)(pixels[0] + (y + j) * stride[0] + x * 4);
198         for (i = 0; i < width; i++)
199             p[i] = color;
200     }
201 }
202
203 static gboolean draw_rgb_rects(GstVaapiImage *image)
204 {
205     GstVaapiImageFormat format = GST_VAAPI_IMAGE_FORMAT(image);
206     guint               w      = GST_VAAPI_IMAGE_WIDTH(image);
207     guint               h      = GST_VAAPI_IMAGE_HEIGHT(image);
208     guchar             *pixels[3];
209     guint               stride[3];
210     guint32             red_color, green_color, blue_color, black_color;
211     DrawRectFunc        draw_rect;
212
213     if (!gst_vaapi_image_map(image))
214         return FALSE;
215
216     switch (format) {
217     case GST_VAAPI_IMAGE_ARGB:
218         draw_rect   = draw_rect_ARGB;
219         goto RGB_colors;
220     case GST_VAAPI_IMAGE_BGRA:
221         draw_rect   = draw_rect_BGRA;
222         goto RGB_colors;
223     case GST_VAAPI_IMAGE_RGBA:
224         draw_rect   = draw_rect_RGBA;
225         goto RGB_colors;
226     case GST_VAAPI_IMAGE_ABGR:
227         draw_rect   = draw_rect_ABGR;
228     RGB_colors:
229         pixels[0]   = gst_vaapi_image_get_plane(image, 0);
230         stride[0]   = gst_vaapi_image_get_pitch(image, 0);
231         red_color   = 0xffff0000;
232         green_color = 0xff00ff00;
233         blue_color  = 0xff0000ff;
234         black_color = 0xff000000;
235         break;
236     case GST_VAAPI_IMAGE_NV12:
237         draw_rect   = draw_rect_NV12;
238         pixels[0]   = gst_vaapi_image_get_plane(image, 0);
239         stride[0]   = gst_vaapi_image_get_pitch(image, 0);
240         pixels[1]   = gst_vaapi_image_get_plane(image, 1);
241         stride[1]   = gst_vaapi_image_get_pitch(image, 1);
242         goto YUV_colors;
243     case GST_VAAPI_IMAGE_YV12:
244         draw_rect   = draw_rect_YV12;
245         pixels[0]   = gst_vaapi_image_get_plane(image, 0);
246         stride[0]   = gst_vaapi_image_get_pitch(image, 0);
247         pixels[1]   = gst_vaapi_image_get_plane(image, 2);
248         stride[1]   = gst_vaapi_image_get_pitch(image, 2);
249         pixels[2]   = gst_vaapi_image_get_plane(image, 1);
250         stride[2]   = gst_vaapi_image_get_pitch(image, 1);
251         goto YUV_colors;
252     case GST_VAAPI_IMAGE_I420:
253         draw_rect   = draw_rect_YV12;
254         pixels[0]   = gst_vaapi_image_get_plane(image, 0);
255         stride[0]   = gst_vaapi_image_get_pitch(image, 0);
256         pixels[1]   = gst_vaapi_image_get_plane(image, 1);
257         stride[1]   = gst_vaapi_image_get_pitch(image, 1);
258         pixels[2]   = gst_vaapi_image_get_plane(image, 2);
259         stride[2]   = gst_vaapi_image_get_pitch(image, 2);
260         goto YUV_colors;
261     case GST_VAAPI_IMAGE_AYUV:
262         draw_rect   = draw_rect_AYUV;
263         pixels[0]   = gst_vaapi_image_get_plane(image, 0);
264         stride[0]   = gst_vaapi_image_get_pitch(image, 0);
265     YUV_colors:
266         red_color   = 0x515af0;
267         green_color = 0x913622;
268         blue_color  = 0x29f06e;
269         black_color = 0x108080;
270         break;
271     default:
272         gst_vaapi_image_unmap(image);
273         return FALSE;
274     }
275
276     draw_rect(pixels, stride, 0,   0,   w/2, h/2, red_color);
277     draw_rect(pixels, stride, w/2, 0,   w/2, h/2, green_color);
278     draw_rect(pixels, stride, 0,   h/2, w/2, h/2, blue_color);
279     draw_rect(pixels, stride, w/2, h/2, w/2, h/2, black_color);
280
281     if (!gst_vaapi_image_unmap(image))
282         return FALSE;
283
284     return TRUE;
285 }
286
287 static gboolean
288 upload_image(GstVaapiSurface *surface, GstVaapiImage *image)
289 {
290     GstVaapiDisplay *display;
291     GstVaapiImageFormat format;
292     GstVaapiSubpicture *subpicture;
293
294     display = gst_vaapi_object_get_display(GST_VAAPI_OBJECT(surface));
295     if (!display)
296         return FALSE;
297
298     format = gst_vaapi_image_get_format(image);
299     if (!format)
300         return FALSE;
301
302     if (gst_vaapi_surface_put_image(surface, image))
303         return TRUE;
304
305     g_print("could not upload %" GST_FOURCC_FORMAT" image to surface\n",
306             GST_FOURCC_ARGS(format));
307
308     if (!gst_vaapi_display_has_subpicture_format(display, format))
309         return FALSE;
310
311     g_print("trying as a subpicture\n");
312
313     subpicture = gst_vaapi_subpicture_new(image);
314     if (!subpicture)
315         g_error("could not create Gst/VA subpicture");
316
317     if (!gst_vaapi_surface_associate_subpicture(surface, subpicture,
318                                                 NULL, NULL))
319         g_error("could not associate subpicture to surface");
320
321     /* The surface holds a reference to the subpicture. This is safe */
322     g_object_unref(subpicture);
323     return TRUE;
324 }
325
326 int
327 main(int argc, char *argv[])
328 {
329     GstVaapiDisplay    *display;
330     GstVaapiWindow     *window;
331     GstVaapiSurface    *surface;
332     GstVaapiImage      *image   = NULL;
333     guint flags = GST_VAAPI_PICTURE_STRUCTURE_FRAME;
334     guint i;
335
336     static const GstVaapiImageFormat image_formats[] = {
337         GST_VAAPI_IMAGE_NV12,
338         GST_VAAPI_IMAGE_YV12,
339         GST_VAAPI_IMAGE_I420,
340         GST_VAAPI_IMAGE_AYUV,
341         GST_VAAPI_IMAGE_ARGB,
342         GST_VAAPI_IMAGE_BGRA,
343         GST_VAAPI_IMAGE_RGBA,
344         GST_VAAPI_IMAGE_ABGR,
345         0
346     };
347
348     static const GstVaapiChromaType chroma_type = GST_VAAPI_CHROMA_TYPE_YUV420;
349     static const guint              width       = 320;
350     static const guint              height      = 240;
351     static const guint              win_width   = 640;
352     static const guint              win_height  = 480;
353
354     gst_init(&argc, &argv);
355
356     display = gst_vaapi_display_x11_new(NULL);
357     if (!display)
358         g_error("could not create Gst/VA display");
359
360     surface = gst_vaapi_surface_new(display, chroma_type, width, height);
361     if (!surface)
362         g_error("could not create Gst/VA surface");
363
364     for (i = 0; image_formats[i]; i++) {
365         const GstVaapiImageFormat format = image_formats[i];
366
367         image = gst_vaapi_image_new(display, format, width, height);
368         if (!image)
369             continue;
370
371         if (!draw_rgb_rects(image))
372             g_error("could not draw RGB rectangles");
373
374         if (upload_image(surface, image))
375             break;
376     }
377     if (!image)
378         g_error("could not create Gst/VA image");
379
380     if (!gst_vaapi_surface_sync(surface))
381         g_error("could not complete image upload");
382
383     g_print("#\n");
384     g_print("# Create window with gst_vaapi_window_x11_new()\n");
385     g_print("#\n");
386     {
387         window = gst_vaapi_window_x11_new(display, win_width, win_height);
388         if (!window)
389             g_error("could not create window");
390
391         gst_vaapi_window_show(window);
392
393         if (!gst_vaapi_window_put_surface(window, surface, NULL, NULL, flags))
394             g_error("could not render surface");
395
396         pause();
397         g_object_unref(window);
398     }
399
400     g_print("#\n");
401     g_print("# Create window with gst_vaapi_window_x11_new_with_xid()\n");
402     g_print("#\n");
403     {
404         Display * const dpy = GST_VAAPI_DISPLAY_XDISPLAY(display);
405         Window rootwin, win;
406         int screen;
407         unsigned long white_pixel, black_pixel;
408
409         screen      = DefaultScreen(dpy);
410         rootwin     = RootWindow(dpy, screen);
411         white_pixel = WhitePixel(dpy, screen);
412         black_pixel = BlackPixel(dpy, screen);
413
414         win = XCreateSimpleWindow(
415             dpy,
416             rootwin,
417             0, 0, win_width, win_height,
418             0, black_pixel,
419             white_pixel
420         );
421         if (!win)
422             g_error("could not create X window");
423
424         window = gst_vaapi_window_x11_new_with_xid(display, win);
425         if (!window)
426             g_error("could not create window");
427
428         gst_vaapi_window_show(window);
429
430         if (!gst_vaapi_window_put_surface(window, surface, NULL, NULL, flags))
431             g_error("could not render surface");
432
433         pause();
434         g_object_unref(window);
435         XUnmapWindow(dpy, win);
436         XDestroyWindow(dpy, win);
437     }
438
439     g_object_unref(image);
440     g_object_unref(surface);
441     g_object_unref(display);
442     gst_deinit();
443     return 0;
444 }