From 9248f187350db7833a1feb1e901044e995061f0b Mon Sep 17 00:00:00 2001 From: gb Date: Fri, 26 Mar 2010 15:16:01 +0000 Subject: [PATCH] Factor out image utilities. --- tests/Makefile.am | 2 +- tests/image.c | 320 +++++++++++++++++++++++++++++++++++++++++++++++++++ tests/image.h | 44 +++++++ tests/test-windows.c | 271 ++----------------------------------------- 4 files changed, 372 insertions(+), 265 deletions(-) create mode 100644 tests/image.c create mode 100644 tests/image.h diff --git a/tests/Makefile.am b/tests/Makefile.am index 12ab814..85e326c 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -42,7 +42,7 @@ test_surfaces_SOURCES = test-surfaces.c test_surfaces_CFLAGS = $(TEST_CFLAGS) $(TEST_X11_CFLAGS) test_surfaces_LDADD = $(TEST_LIBS) $(TEST_X11_LIBS) -test_windows_SOURCES = test-windows.c +test_windows_SOURCES = test-windows.c image.c test_windows_CFLAGS = $(TEST_CFLAGS) $(TEST_X11_CFLAGS) test_windows_LDADD = $(TEST_LIBS) $(TEST_X11_LIBS) diff --git a/tests/image.c b/tests/image.c new file mode 100644 index 0000000..478ed77 --- /dev/null +++ b/tests/image.c @@ -0,0 +1,320 @@ +/* + * image.c - Image utilities for the tests + * + * gstreamer-vaapi (C) 2010 Splitted-Desktop Systems + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "image.h" + +GstVaapiImage * +image_generate( + GstVaapiDisplay *display, + GstVaapiImageFormat format, + guint width, + guint height +) +{ + const guint w = width; + const guint h = height; + GstVaapiImage *image; + + image = gst_vaapi_image_new(display, format, w, h); + if (!image) + return NULL; + + if (image_draw_rectangle(image, 0, 0, w/2, h/2, 0xffff0000) && + image_draw_rectangle(image, w/2, 0, w/2, h/2, 0xff00ff00) && + image_draw_rectangle(image, 0, h/2, w/2, h/2, 0xff0000ff) && + image_draw_rectangle(image, w/2, h/2, w/2, h/2, 0xff000000)) + return image; + + g_object_unref(image); + return NULL; +} + +typedef void (*DrawRectFunc)( + guchar *pixels[3], + guint stride[3], + gint x, + gint y, + guint width, + guint height, + guint32 color +); + +static void draw_rect_ARGB( + guchar *pixels[3], + guint stride[3], + gint x, + gint y, + guint width, + guint height, + guint32 color +) +{ + guint i, j; + + color = GUINT32_TO_BE(color); + + for (j = 0; j < height; j++) { + guint32 *p = (guint32 *)(pixels[0] + (y + j) * stride[0] + x * 4); + for (i = 0; i < width; i++) + p[i] = color; + } +} + +static void draw_rect_BGRA( + guchar *pixels[3], + guint stride[3], + gint x, + gint y, + guint width, + guint height, + guint32 color +) +{ + // Converts ARGB color to BGRA + color = GUINT32_SWAP_LE_BE(color); + + draw_rect_ARGB(pixels, stride, x, y, width, height, color); +} + +static void draw_rect_RGBA( + guchar *pixels[3], + guint stride[3], + gint x, + gint y, + guint width, + guint height, + guint32 color +) +{ + // Converts ARGB color to RGBA + color = ((color >> 24) & 0xff) | ((color & 0xffffff) << 8); + + draw_rect_ARGB(pixels, stride, x, y, width, height, color); +} + +static void draw_rect_ABGR( + guchar *pixels[3], + guint stride[3], + gint x, + gint y, + guint width, + guint height, + guint32 color +) +{ + // Converts ARGB color to ABGR + color = ((color & 0xff00ff00) | + ((color >> 16) & 0xff) | + ((color & 0xff) << 16)); + + draw_rect_ARGB(pixels, stride, x, y, width, height, color); +} + +static void draw_rect_NV12( // Y, UV planes + guchar *pixels[3], + guint stride[3], + gint x, + gint y, + guint width, + guint height, + guint32 color +) +{ + const guchar Y = color >> 16; + const guchar Cb = color >> 8; + const guchar Cr = color; + guchar *dst; + guint i, j; + + dst = pixels[0] + y * stride[0] + x; + for (j = 0; j < height; j++, dst += stride[0]) + for (i = 0; i < width; i++) + dst[i] = Y; + + x /= 2; + y /= 2; + width /= 2; + height /= 2; + + dst = pixels[1] + y * stride[1] + x * 2; + for (j = 0; j < height; j++, dst += stride[1]) + for (i = 0; i < width; i++) { + dst[2*i + 0] = Cb; + dst[2*i + 1] = Cr; + } +} + +static void draw_rect_YV12( // Y, V, U planes + guchar *pixels[3], + guint stride[3], + gint x, + gint y, + guint width, + guint height, + guint32 color +) +{ + const guchar Y = color >> 16; + const guchar Cb = color >> 8; + const guchar Cr = color; + guchar *pY, *pU, *pV; + guint i, j; + + pY = pixels[0] + y * stride[0] + x; + for (j = 0; j < height; j++, pY += stride[0]) + for (i = 0; i < width; i++) + pY[i] = Y; + + x /= 2; + y /= 2; + width /= 2; + height /= 2; + + pU = pixels[1] + y * stride[1] + x; + pV = pixels[2] + y * stride[2] + x; + for (j = 0; j < height; j++, pU += stride[1], pV += stride[2]) + for (i = 0; i < width; i++) { + pU[i] = Cb; + pV[i] = Cr; + } +} + +static void draw_rect_I420( // Y, U, V planes + guchar *pixels[3], + guint stride[3], + gint x, + gint y, + guint width, + guint height, + guint32 color +) +{ + guchar *new_pixels[3] = { pixels[0], pixels[2], pixels[1] }; + guint new_stride[3] = { stride[0], stride[2], stride[1] }; + + draw_rect_YV12(new_pixels, new_stride, x, y, width, height, color); +} + +static void draw_rect_AYUV( + guchar *pixels[3], + guint stride[3], + gint x, + gint y, + guint width, + guint height, + guint32 color +) +{ + guint i, j; + + color = color | 0xff000000; + + for (j = 0; j < height; j++) { + guint32 *p = (guint32 *)(pixels[0] + (y + j) * stride[0] + x * 4); + for (i = 0; i < width; i++) + p[i] = color; + } +} + +static inline guint32 argb2yuv(guint32 color) +{ + const gint32 r = (color >> 16) & 0xff; + const gint32 g = (color >> 8) & 0xff; + const gint32 b = (color ) & 0xff; + + const guint32 y = (( 263 * r + 516 * g + 100 * b) >> 10) + 16; + const guint32 u = ((-152 * r - 298 * g + 450 * b) >> 10) + 128; + const guint32 v = (( 450 * r - 376 * g - 73 * b) >> 10) + 128; + + return (y << 16) | (u << 8) | v; +} + +gboolean +image_draw_rectangle( + GstVaapiImage *image, + gint x, + gint y, + guint width, + guint height, + guint32 color +) +{ + const GstVaapiImageFormat image_format = gst_vaapi_image_get_format(image); + const guint image_width = gst_vaapi_image_get_width(image); + const guint image_height = gst_vaapi_image_get_height(image); + GstVaapiDisplay *display; + guchar *pixels[3]; + guint stride[3]; + DrawRectFunc draw_rect = NULL; + guint i; + + static const struct { + GstVaapiImageFormat format; + DrawRectFunc draw_rect; + } + map[] = { +#define _(FORMAT) { GST_VAAPI_IMAGE_##FORMAT, draw_rect_##FORMAT } + _(ARGB), + _(BGRA), + _(RGBA), + _(ABGR), + _(NV12), + _(YV12), + _(I420), + _(AYUV), +#undef _ + { 0, } + }; + + for (i = 0; !draw_rect && map[i].format; i++) + if (map[i].format == image_format) + draw_rect = map[i].draw_rect; + if (!draw_rect) + return FALSE; + + display = gst_vaapi_object_get_display(GST_VAAPI_OBJECT(image)); + if (!display) + return FALSE; + + if (!gst_vaapi_image_map(image)) + return FALSE; + + for (i = 0; i < gst_vaapi_image_get_plane_count(image); i++) { + pixels[i] = gst_vaapi_image_get_plane(image, i); + stride[i] = gst_vaapi_image_get_pitch(image, i); + } + + if (gst_vaapi_image_format_is_yuv(image_format)) + color = argb2yuv(color); + + if (x < 0) + x = 0; + if (y < 0) + y = 0; + if (width > image_width - x) + width = image_width - x; + if (height > image_height - y) + height = image_height - y; + + gst_vaapi_display_lock(display); + draw_rect(pixels, stride, x, y, width, height, color); + gst_vaapi_display_unlock(display); + return gst_vaapi_image_unmap(image); +} diff --git a/tests/image.h b/tests/image.h new file mode 100644 index 0000000..eb914de --- /dev/null +++ b/tests/image.h @@ -0,0 +1,44 @@ +/* + * image.h - Image utilities for the tests + * + * gstreamer-vaapi (C) 2010 Splitted-Desktop Systems + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifndef IMAGE_H +#define IMAGE_H + +#include + +GstVaapiImage * +image_generate( + GstVaapiDisplay *display, + GstVaapiImageFormat format, + guint width, + guint height +); + +gboolean +image_draw_rectangle( + GstVaapiImage *image, + gint x, + gint y, + guint width, + guint height, + guint32 color +); + +#endif /* IMAGE_H */ diff --git a/tests/test-windows.c b/tests/test-windows.c index 3aa4a50..7292bba 100644 --- a/tests/test-windows.c +++ b/tests/test-windows.c @@ -22,6 +22,7 @@ #include #include #include +#include "image.h" static inline void pause(void) { @@ -29,261 +30,6 @@ static inline void pause(void) getchar(); } -typedef void (*DrawRectFunc)( - guchar *pixels[3], - guint stride[3], - gint x, - gint y, - guint width, - guint height, - guint32 color -); - -static void draw_rect_ARGB( - guchar *pixels[3], - guint stride[3], - gint x, - gint y, - guint width, - guint height, - guint32 color -) -{ - guint i, j; - - color = GUINT32_TO_BE(color); - - for (j = 0; j < height; j++) { - guint32 *p = (guint32 *)(pixels[0] + (y + j) * stride[0] + x * 4); - for (i = 0; i < width; i++) - p[i] = color; - } -} - -static void draw_rect_BGRA( - guchar *pixels[3], - guint stride[3], - gint x, - gint y, - guint width, - guint height, - guint32 color -) -{ - // Converts ARGB color to BGRA - color = GUINT32_SWAP_LE_BE(color); - - draw_rect_ARGB(pixels, stride, x, y, width, height, color); -} - -static void draw_rect_RGBA( - guchar *pixels[3], - guint stride[3], - gint x, - gint y, - guint width, - guint height, - guint32 color -) -{ - // Converts ARGB color to RGBA - color = ((color >> 24) & 0xff) | ((color & 0xffffff) << 8); - - draw_rect_ARGB(pixels, stride, x, y, width, height, color); -} - -static void draw_rect_ABGR( - guchar *pixels[3], - guint stride[3], - gint x, - gint y, - guint width, - guint height, - guint32 color -) -{ - // Converts ARGB color to ABGR - color = ((color & 0xff00ff00) | - ((color >> 16) & 0xff) | - ((color & 0xff) << 16)); - - draw_rect_ARGB(pixels, stride, x, y, width, height, color); -} - -static void draw_rect_NV12( // Y, UV planes - guchar *pixels[3], - guint stride[3], - gint x, - gint y, - guint width, - guint height, - guint32 color -) -{ - const guchar Y = color >> 16; - const guchar Cb = color >> 8; - const guchar Cr = color; - guchar *dst; - guint i, j; - - dst = pixels[0] + y * stride[0] + x; - for (j = 0; j < height; j++, dst += stride[0]) - for (i = 0; i < width; i++) - dst[i] = Y; - - x /= 2; - y /= 2; - width /= 2; - height /= 2; - - dst = pixels[1] + y * stride[1] + x * 2; - for (j = 0; j < height; j++, dst += stride[1]) - for (i = 0; i < width; i++) { - dst[2*i + 0] = Cb; - dst[2*i + 1] = Cr; - } -} - -static void draw_rect_YV12( // Y, U, V planes - guchar *pixels[3], - guint stride[3], - gint x, - gint y, - guint width, - guint height, - guint32 color -) -{ - const guchar Y = color >> 16; - const guchar Cb = color >> 8; - const guchar Cr = color; - guchar *pY, *pU, *pV; - guint i, j; - - pY = pixels[0] + y * stride[0] + x; - for (j = 0; j < height; j++, pY += stride[0]) - for (i = 0; i < width; i++) - pY[i] = Y; - - x /= 2; - y /= 2; - width /= 2; - height /= 2; - - pU = pixels[1] + y * stride[1] + x; - pV = pixels[2] + y * stride[2] + x; - for (j = 0; j < height; j++, pU += stride[1], pV += stride[2]) - for (i = 0; i < width; i++) { - pU[i] = Cb; - pV[i] = Cr; - } -} - -static void draw_rect_AYUV( - guchar *pixels[3], - guint stride[3], - gint x, - gint y, - guint width, - guint height, - guint32 color -) -{ - guint i, j; - - color = color | 0xff000000; - - for (j = 0; j < height; j++) { - guint32 *p = (guint32 *)(pixels[0] + (y + j) * stride[0] + x * 4); - for (i = 0; i < width; i++) - p[i] = color; - } -} - -static gboolean draw_rgb_rects(GstVaapiImage *image) -{ - GstVaapiImageFormat format = GST_VAAPI_IMAGE_FORMAT(image); - guint w = GST_VAAPI_IMAGE_WIDTH(image); - guint h = GST_VAAPI_IMAGE_HEIGHT(image); - guchar *pixels[3]; - guint stride[3]; - guint32 red_color, green_color, blue_color, black_color; - DrawRectFunc draw_rect; - - if (!gst_vaapi_image_map(image)) - return FALSE; - - switch (format) { - case GST_VAAPI_IMAGE_ARGB: - draw_rect = draw_rect_ARGB; - goto RGB_colors; - case GST_VAAPI_IMAGE_BGRA: - draw_rect = draw_rect_BGRA; - goto RGB_colors; - case GST_VAAPI_IMAGE_RGBA: - draw_rect = draw_rect_RGBA; - goto RGB_colors; - case GST_VAAPI_IMAGE_ABGR: - draw_rect = draw_rect_ABGR; - RGB_colors: - pixels[0] = gst_vaapi_image_get_plane(image, 0); - stride[0] = gst_vaapi_image_get_pitch(image, 0); - red_color = 0xffff0000; - green_color = 0xff00ff00; - blue_color = 0xff0000ff; - black_color = 0xff000000; - break; - case GST_VAAPI_IMAGE_NV12: - draw_rect = draw_rect_NV12; - pixels[0] = gst_vaapi_image_get_plane(image, 0); - stride[0] = gst_vaapi_image_get_pitch(image, 0); - pixels[1] = gst_vaapi_image_get_plane(image, 1); - stride[1] = gst_vaapi_image_get_pitch(image, 1); - goto YUV_colors; - case GST_VAAPI_IMAGE_YV12: - draw_rect = draw_rect_YV12; - pixels[0] = gst_vaapi_image_get_plane(image, 0); - stride[0] = gst_vaapi_image_get_pitch(image, 0); - pixels[1] = gst_vaapi_image_get_plane(image, 2); - stride[1] = gst_vaapi_image_get_pitch(image, 2); - pixels[2] = gst_vaapi_image_get_plane(image, 1); - stride[2] = gst_vaapi_image_get_pitch(image, 1); - goto YUV_colors; - case GST_VAAPI_IMAGE_I420: - draw_rect = draw_rect_YV12; - pixels[0] = gst_vaapi_image_get_plane(image, 0); - stride[0] = gst_vaapi_image_get_pitch(image, 0); - pixels[1] = gst_vaapi_image_get_plane(image, 1); - stride[1] = gst_vaapi_image_get_pitch(image, 1); - pixels[2] = gst_vaapi_image_get_plane(image, 2); - stride[2] = gst_vaapi_image_get_pitch(image, 2); - goto YUV_colors; - case GST_VAAPI_IMAGE_AYUV: - draw_rect = draw_rect_AYUV; - pixels[0] = gst_vaapi_image_get_plane(image, 0); - stride[0] = gst_vaapi_image_get_pitch(image, 0); - YUV_colors: - red_color = 0x515af0; - green_color = 0x913622; - blue_color = 0x29f06e; - black_color = 0x108080; - break; - default: - gst_vaapi_image_unmap(image); - return FALSE; - } - - draw_rect(pixels, stride, 0, 0, w/2, h/2, red_color); - draw_rect(pixels, stride, w/2, 0, w/2, h/2, green_color); - draw_rect(pixels, stride, 0, h/2, w/2, h/2, blue_color); - draw_rect(pixels, stride, w/2, h/2, w/2, h/2, black_color); - - if (!gst_vaapi_image_unmap(image)) - return FALSE; - - return TRUE; -} - static gboolean upload_image(GstVaapiSurface *surface, GstVaapiImage *image) { @@ -364,15 +110,12 @@ main(int argc, char *argv[]) for (i = 0; image_formats[i]; i++) { const GstVaapiImageFormat format = image_formats[i]; - image = gst_vaapi_image_new(display, format, width, height); - if (!image) - continue; - - if (!draw_rgb_rects(image)) - g_error("could not draw RGB rectangles"); - - if (upload_image(surface, image)) - break; + image = image_generate(display, format, width, height); + if (image) { + if (upload_image(surface, image)) + break; + g_object_unref(image); + } } if (!image) g_error("could not create Gst/VA image"); -- 2.7.4