Factor out image utilities.
authorgb <gb@5584edef-b1fe-4b99-b61b-dd2bab72e969>
Fri, 26 Mar 2010 15:16:01 +0000 (15:16 +0000)
committergb <gb@5584edef-b1fe-4b99-b61b-dd2bab72e969>
Fri, 26 Mar 2010 15:16:01 +0000 (15:16 +0000)
tests/Makefile.am
tests/image.c [new file with mode: 0644]
tests/image.h [new file with mode: 0644]
tests/test-windows.c

index 12ab814..85e326c 100644 (file)
@@ -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 (file)
index 0000000..478ed77
--- /dev/null
@@ -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 (file)
index 0000000..eb914de
--- /dev/null
@@ -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 <gst/vaapi/gstvaapiimage.h>
+
+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 */
index 3aa4a50..7292bba 100644 (file)
@@ -22,6 +22,7 @@
 #include <gst/vaapi/gstvaapiwindow_x11.h>
 #include <gst/vaapi/gstvaapisurface.h>
 #include <gst/vaapi/gstvaapiimage.h>
+#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");