re-arrange test programs
authorAustin Yuan <shengquan.yuan@intel.com>
Fri, 27 Nov 2009 09:54:30 +0000 (17:54 +0800)
committerAustin Yuan <shengquan.yuan@intel.com>
Fri, 27 Nov 2009 09:54:30 +0000 (17:54 +0800)
Signed-off-by: Austin Yuan <shengquan.yuan@intel.com>
27 files changed:
configure.ac
test/Makefile.am
test/basic/Makefile.am [new file with mode: 0644]
test/basic/test.c [moved from test/test.c with 100% similarity]
test/basic/test_01.c [moved from test/test_01.c with 100% similarity]
test/basic/test_02.c [moved from test/test_02.c with 100% similarity]
test/basic/test_03.c [moved from test/test_03.c with 100% similarity]
test/basic/test_04.c [moved from test/test_04.c with 100% similarity]
test/basic/test_05.c [moved from test/test_05.c with 100% similarity]
test/basic/test_06.c [moved from test/test_06.c with 100% similarity]
test/basic/test_07.c [moved from test/test_07.c with 100% similarity]
test/basic/test_08.c [moved from test/test_08.c with 100% similarity]
test/basic/test_09.c [moved from test/test_09.c with 100% similarity]
test/basic/test_10.c [moved from test/test_10.c with 100% similarity]
test/basic/test_11.c [moved from test/test_11.c with 100% similarity]
test/basic/test_common.c [moved from test/test_common.c with 100% similarity]
test/basic/testplan.txt [moved from test/testplan.txt with 100% similarity]
test/decode/Makefile.am [new file with mode: 0644]
test/decode/mpeg2-I.gif [new file with mode: 0644]
test/decode/mpeg2-I.m2v [moved from test/mpeg2-I.mpg with 100% similarity]
test/decode/mpeg2vldemo.c [moved from test/test_12.c with 58% similarity]
test/encode/Makefile.am [new file with mode: 0644]
test/encode/h264encode.c [new file with mode: 0644]
test/mpeg2-I.jpg [deleted file]
test/putsurface/Makefile.am [new file with mode: 0644]
test/putsurface/loadsurface.h [new file with mode: 0644]
test/putsurface/putsurface.c [new file with mode: 0644]

index c3aba90..b99c6b1 100644 (file)
@@ -126,6 +126,10 @@ AC_OUTPUT([
        i965_drv_video/shaders/mpeg2/vld/Makefile
        i965_drv_video/shaders/render/Makefile
        test/Makefile
+       test/basic/Makefile
+       test/decode/Makefile
+       test/putsurface/Makefile
+       test/encode/Makefile
        libva.pc
        libva-x11.pc
 ])
index 58e1677..5734226 100644 (file)
 # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
 # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
-check_PROGRAMS = test_01 test_02 test_03 test_04 test_05 test_06 \
-               test_07 test_08 test_09 test_10 test_11 test_12
 
 bin_PROGRAMS = vainfo
 
-testdir = $(bindir)
+AM_CFLAGS = -I$(top_srcdir)/src -I$(top_srcdir)/test/basic -I$(top_srcdir)/src/x11 -DIN_LIBVA
 
-AM_CFLAGS = -I$(top_srcdir)/../../include/external/ -I$(top_srcdir)/src -I$(top_srcdir)/src/x11 -DIN_LIBVA
-
-TESTS = $(check_PROGRAMS)
-
-TEST_LIBS = $(top_srcdir)/src/$(libvabackendlib)
 
 vainfo_LDADD = $(top_srcdir)/src/$(libvabackendlib)
 vainfo_DEPENDENCIES = $(top_srcdir)/src/$(libvabackendlib)
 vainfo_SOURCES = vainfo.c
 
-test_01_LDADD = $(TEST_LIBS)
-test_01_SOURCES = test_01.c
-
-test_02_LDADD = $(TEST_LIBS)
-test_02_SOURCES = test_02.c
-
-test_03_LDADD = $(TEST_LIBS)
-test_03_SOURCES = test_03.c
-
-test_04_LDADD = $(TEST_LIBS)
-test_04_SOURCES = test_04.c
-
-test_05_LDADD = $(TEST_LIBS)
-test_05_SOURCES = test_05.c
-
-test_06_LDADD = $(TEST_LIBS)
-test_06_SOURCES = test_06.c
-
-test_07_LDADD = $(TEST_LIBS)
-test_07_SOURCES = test_07.c
-
-test_08_LDADD = $(TEST_LIBS)
-test_08_SOURCES = test_08.c
-
-test_09_LDADD = $(TEST_LIBS)
-test_09_SOURCES = test_09.c
-
-test_10_LDADD = $(TEST_LIBS)
-test_10_SOURCES = test_10.c
-
-test_11_LDADD = $(TEST_LIBS)
-test_11_SOURCES = test_11.c
-
-test_12_LDADD = $(TEST_LIBS)
-test_12_SOURCES = test_12.c
-
-EXTRA_DIST = test_common.c mpeg2-I.jpg mpeg2-I.mpg
+SUBDIRS = basic decode encode putsurface
 
-valgrind:      $(check_PROGRAMS)
-       for a in $(check_PROGRAMS); do \
-               valgrind --leak-check=full --show-reachable=yes .libs/$$a; \
-       done
+valgrind:      vainfo
+       valgrind --leak-check=full --show-reachable=yes .libs/vainfo; 
diff --git a/test/basic/Makefile.am b/test/basic/Makefile.am
new file mode 100644 (file)
index 0000000..78eabcb
--- /dev/null
@@ -0,0 +1,66 @@
+# Copyright (c) 2007 Intel Corporation. All Rights Reserved.
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sub license, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+# 
+# The above copyright notice and this permission notice (including the
+# next paragraph) shall be included in all copies or substantial portions
+# of the Software.
+# 
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+# IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
+# ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+bin_PROGRAMS = test_01 test_02 test_03 test_04 test_05 test_06 \
+               test_07 test_08 test_09 test_10 test_11
+
+TEST_LIBS = $(top_srcdir)/src/$(libvabackendlib)
+
+test_01_LDADD = $(TEST_LIBS)
+test_01_SOURCES = test_01.c
+
+test_02_LDADD = $(TEST_LIBS)
+test_02_SOURCES = test_02.c
+
+test_03_LDADD = $(TEST_LIBS)
+test_03_SOURCES = test_03.c
+
+test_04_LDADD = $(TEST_LIBS)
+test_04_SOURCES = test_04.c
+
+test_05_LDADD = $(TEST_LIBS)
+test_05_SOURCES = test_05.c
+
+test_06_LDADD = $(TEST_LIBS)
+test_06_SOURCES = test_06.c
+
+test_07_LDADD = $(TEST_LIBS)
+test_07_SOURCES = test_07.c
+
+test_08_LDADD = $(TEST_LIBS)
+test_08_SOURCES = test_08.c
+
+test_09_LDADD = $(TEST_LIBS)
+test_09_SOURCES = test_09.c
+
+test_10_LDADD = $(TEST_LIBS)
+test_10_SOURCES = test_10.c
+
+test_11_LDADD = $(TEST_LIBS)
+test_11_SOURCES = test_11.c
+
+EXTRA_DIST = test_common.c
+
+valgrind:      $(bin_PROGRAMS)
+       for a in $(bin_PROGRAMS); do \
+               valgrind --leak-check=full --show-reachable=yes .libs/$$a; \
+       done
similarity index 100%
rename from test/test.c
rename to test/basic/test.c
similarity index 100%
rename from test/test_01.c
rename to test/basic/test_01.c
similarity index 100%
rename from test/test_02.c
rename to test/basic/test_02.c
similarity index 100%
rename from test/test_03.c
rename to test/basic/test_03.c
similarity index 100%
rename from test/test_04.c
rename to test/basic/test_04.c
similarity index 100%
rename from test/test_05.c
rename to test/basic/test_05.c
similarity index 100%
rename from test/test_06.c
rename to test/basic/test_06.c
similarity index 100%
rename from test/test_07.c
rename to test/basic/test_07.c
similarity index 100%
rename from test/test_08.c
rename to test/basic/test_08.c
similarity index 100%
rename from test/test_09.c
rename to test/basic/test_09.c
similarity index 100%
rename from test/test_10.c
rename to test/basic/test_10.c
similarity index 100%
rename from test/test_11.c
rename to test/basic/test_11.c
similarity index 100%
rename from test/test_common.c
rename to test/basic/test_common.c
similarity index 100%
rename from test/testplan.txt
rename to test/basic/testplan.txt
diff --git a/test/decode/Makefile.am b/test/decode/Makefile.am
new file mode 100644 (file)
index 0000000..9283671
--- /dev/null
@@ -0,0 +1,36 @@
+# Copyright (c) 2007 Intel Corporation. All Rights Reserved.
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sub license, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+# 
+# The above copyright notice and this permission notice (including the
+# next paragraph) shall be included in all copies or substantial portions
+# of the Software.
+# 
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+# IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
+# ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+bin_PROGRAMS = mpeg2vldemo
+
+AM_CFLAGS = -I$(top_srcdir)/src -I$(top_srcdir)/src/x11 -DIN_LIBVA
+
+TEST_LIBS = $(top_srcdir)/src/$(libvabackendlib)
+
+mpeg2vldemo_LDADD = $(TEST_LIBS)
+mpeg2vldemo_SOURCES = mpeg2vldemo.c
+
+
+valgrind:      $(bin_PROGRAMS)
+       for a in $(bin_PROGRAMS); do \
+               valgrind --leak-check=full --show-reachable=yes .libs/$$a; \
+       done
diff --git a/test/decode/mpeg2-I.gif b/test/decode/mpeg2-I.gif
new file mode 100644 (file)
index 0000000..81a25eb
Binary files /dev/null and b/test/decode/mpeg2-I.gif differ
similarity index 100%
rename from test/mpeg2-I.mpg
rename to test/decode/mpeg2-I.m2v
similarity index 58%
rename from test/test_12.c
rename to test/decode/mpeg2vldemo.c
index c9e4db9..945b69d 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007 Intel Corporation. All Rights Reserved.
+ * Copyright (c) 2007-2008 Intel Corporation. All Rights Reserved.
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the
  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  */
 
-#define TEST_DESCRIPTION       "Sample MPEG2 VLD Decoding"
-
-#ifdef IN_LIBVA
-#include <va_x11.h>
-#else
-#include <va/va_x11.h>
-#endif
+/*
+ * it is a real program to show how VAAPI decode work,
+ * It does VLD decode for a simple MPEG2 clip "mpeg2-I.m2v"
+ * "mpeg2-I.m2v" and VA parameters are hardcoded into mpeg2vldemo.c,
+ * See mpeg2-I.jif to know how those VA parameters come from
+ *
+ * gcc -o  mpeg2vldemo  mpeg2vldemo.c -lva -lva-x11
+ * ./mpeg2vldemo  : only do decode
+ * ./mpeg2vldemo <any parameter >: decode+display
+ *
+ */  
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <getopt.h>
+#include <X11/Xlib.h>
 
-#include "test_common.c"
+#include <unistd.h>
 
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <fcntl.h>
 
-void pre()
-{
-    test_init();
+#include <assert.h>
+
+#include <va/va.h>
+#include <va/va_x11.h>
+
+#define CHECK_VASTATUS(va_status,func)                                  \
+if (va_status != VA_STATUS_SUCCESS) {                                   \
+    fprintf(stderr,"%s:%s (%d) failed,exit\n", __func__, func, __LINE__); \
+    exit(1);                                                            \
 }
 
 /* Data dump of a 16x16 MPEG2 video clip,it has one I frame
@@ -120,23 +135,43 @@ static VASliceParameterBufferMPEG2 slice_param={
 #define CLIP_WIDTH  16
 #define CLIP_HEIGHT 16
 
-int surf_width=CLIP_WIDTH,surf_height=CLIP_HEIGHT;
-int win_width=CLIP_WIDTH<<1,win_height=CLIP_HEIGHT<<1;
+#define WIN_WIDTH  (CLIP_WIDTH<<1)
+#define WIN_HEIGHT (CLIP_HEIGHT<<1)
 
-void test()
+int main(int argc,char **argv)
 {
     VAEntrypoint entrypoints[5];
     int num_entrypoints,vld_entrypoint;
     VAConfigAttrib attrib;
     VAConfigID config_id;
-    VASurfaceID vaSurface;
-    VAContextID vaContext;
-    VABufferID vaPicParamBuf,vaIQMatrixBuf,vaSliceParamBuf,vaSliceDataBuf;
-    Window win = 0;
+    VASurfaceID surface_id;
+    VAContextID context_id;
+    VABufferID pic_param_buf,iqmatrix_buf,slice_param_buf,slice_data_buf;
+    int major_ver, minor_ver;
+    Display *x11_display;
+    VADisplay  va_dpy;
+    VAStatus va_status;
+    int putsurface=0;
+
+    if (argc > 1)
+        putsurface=1;
+    x11_display = XOpenDisplay(":0.0");
+
+    if (x11_display == NULL) {
+      fprintf(stderr, "Can't connect X server!\n");
+      exit(-1);
+    }
+
+    assert(x11_display);
+    
+    va_dpy = vaGetDisplay(x11_display);
+    va_status = vaInitialize(va_dpy, &major_ver, &minor_ver);
+    assert(va_status == VA_STATUS_SUCCESS);
     
     va_status = vaQueryConfigEntrypoints(va_dpy, VAProfileMPEG2Main, entrypoints, 
                              &num_entrypoints);
-    ASSERT( VA_STATUS_SUCCESS == va_status );
+    CHECK_VASTATUS(va_status, "vaQueryConfigEntrypoints");
 
     for        (vld_entrypoint = 0; vld_entrypoint < num_entrypoints; vld_entrypoint++) {
         if (entrypoints[vld_entrypoint] == VAEntrypointVLD)
@@ -144,107 +179,108 @@ void test()
     }
     if (vld_entrypoint == num_entrypoints) {
         /* not find VLD entry point */
-        ASSERT(0);
+        assert(0);
     }
 
     /* Assuming finding VLD, find out the format for the render target */
     attrib.type = VAConfigAttribRTFormat;
-    va_status = vaGetConfigAttributes(va_dpy, VAProfileMPEG2Main, VAEntrypointVLD,
+    vaGetConfigAttributes(va_dpy, VAProfileMPEG2Main, VAEntrypointVLD,
                           &attrib, 1);
-    ASSERT( VA_STATUS_SUCCESS == va_status );
     if ((attrib.value & VA_RT_FORMAT_YUV420) == 0) {
         /* not find desired YUV420 RT format */
-        ASSERT(0);
+        assert(0);
     }
     
     va_status = vaCreateConfig(va_dpy, VAProfileMPEG2Main, VAEntrypointVLD,
                               &attrib, 1,&config_id);
-    ASSERT( VA_STATUS_SUCCESS == va_status );
-    
-    va_status = vaCreateSurfaces(va_dpy,surf_width,surf_height,
-                                VA_RT_FORMAT_YUV420, 1, &vaSurface);
-    ASSERT( VA_STATUS_SUCCESS == va_status );
+    CHECK_VASTATUS(va_status, "vaQueryConfigEntrypoints");
+
+    va_status = vaCreateSurfaces(va_dpy,CLIP_WIDTH,CLIP_HEIGHT,
+                                VA_RT_FORMAT_YUV420, 1, &surface_id);
+    CHECK_VASTATUS(va_status, "vaCreateSurfaces");
 
     /* Create a context for this decode pipe */
     va_status = vaCreateContext(va_dpy, config_id,
                                CLIP_WIDTH,
                                ((CLIP_HEIGHT+15)/16)*16,
                                VA_PROGRESSIVE,
-                               &vaSurface,
+                               &surface_id,
                                1,
-                               &vaContext);
-    ASSERT( VA_STATUS_SUCCESS == va_status );
+                               &context_id);
+    CHECK_VASTATUS(va_status, "vaCreateContext");
     
-    va_status = vaCreateBuffer(va_dpy, vaContext,
+    va_status = vaCreateBuffer(va_dpy, context_id,
                               VAPictureParameterBufferType,
                               sizeof(VAPictureParameterBufferMPEG2),
                               1, &pic_param,
-                              &vaPicParamBuf);
-    ASSERT( VA_STATUS_SUCCESS == va_status );
-
-    va_status = vaCreateBuffer(va_dpy, vaContext,
+                              &pic_param_buf);
+    CHECK_VASTATUS(va_status, "vaCreateBuffer");
+    
+    va_status = vaCreateBuffer(va_dpy, context_id,
                               VAIQMatrixBufferType,
                               sizeof(VAIQMatrixBufferMPEG2),
                               1, &iq_matrix,
-                              &vaIQMatrixBuf );
-    ASSERT( VA_STATUS_SUCCESS == va_status );
+                              &iqmatrix_buf );
+    CHECK_VASTATUS(va_status, "vaCreateBuffer");
                 
-    va_status = vaCreateBuffer(va_dpy, vaContext,
+    va_status = vaCreateBuffer(va_dpy, context_id,
                               VASliceParameterBufferType,
                               sizeof(VASliceParameterBufferMPEG2),
                               1,
-                              &slice_param, &vaSliceParamBuf);
-    ASSERT( VA_STATUS_SUCCESS == va_status );
+                              &slice_param, &slice_param_buf);
+    CHECK_VASTATUS(va_status, "vaCreateBuffer");
 
-    va_status = vaCreateBuffer(va_dpy, vaContext,
+    va_status = vaCreateBuffer(va_dpy, context_id,
                               VASliceDataBufferType,
                               0xc4-0x2f+1,
                               1,
                               mpeg2_clip+0x2f,
-                              &vaSliceDataBuf);
-    ASSERT( VA_STATUS_SUCCESS == va_status );
-
-    va_status = vaBeginPicture(va_dpy, vaContext, vaSurface);
-    ASSERT( VA_STATUS_SUCCESS == va_status );
-    
-    va_status = vaRenderPicture(va_dpy,vaContext, &vaPicParamBuf, 1);
-    ASSERT( VA_STATUS_SUCCESS == va_status );
-
-    va_status = vaRenderPicture(va_dpy,vaContext, &vaIQMatrixBuf, 1);
-    ASSERT( VA_STATUS_SUCCESS == va_status );
+                              &slice_data_buf);
+    CHECK_VASTATUS(va_status, "vaCreateBuffer");
 
-    va_status = vaRenderPicture(va_dpy,vaContext, &vaSliceParamBuf, 1);
-    ASSERT( VA_STATUS_SUCCESS == va_status );
+    va_status = vaBeginPicture(va_dpy, context_id, surface_id);
+    CHECK_VASTATUS(va_status, "vaBeginPicture");
 
-    va_status = vaRenderPicture(va_dpy,vaContext, &vaSliceDataBuf, 1);
-    ASSERT( VA_STATUS_SUCCESS == va_status );
-
-    va_status = vaEndPicture(va_dpy,vaContext);
-    ASSERT( VA_STATUS_SUCCESS == va_status );
-
-    va_status = vaSyncSurface(va_dpy, vaSurface);
-    ASSERT( VA_STATUS_SUCCESS == va_status );
+    va_status = vaRenderPicture(va_dpy,context_id, &pic_param_buf, 1);
+    CHECK_VASTATUS(va_status, "vaRenderPicture");
+    
+    va_status = vaRenderPicture(va_dpy,context_id, &iqmatrix_buf, 1);
+    CHECK_VASTATUS(va_status, "vaRenderPicture");
+    
+    va_status = vaRenderPicture(va_dpy,context_id, &slice_param_buf, 1);
+    CHECK_VASTATUS(va_status, "vaRenderPicture");
     
-    win = XCreateSimpleWindow(dpy, RootWindow(dpy, 0), 0, 0,
-                              win_width,win_height, 0, 0, WhitePixel(dpy, 0));
-    XMapWindow(dpy, win);
-    XSync(dpy, False);
+    va_status = vaRenderPicture(va_dpy,context_id, &slice_data_buf, 1);
+    CHECK_VASTATUS(va_status, "vaRenderPicture");
+    
+    va_status = vaEndPicture(va_dpy,context_id);
+    CHECK_VASTATUS(va_status, "vaEndPicture");
 
-    va_status = vaPutSurface(va_dpy, vaSurface, win,
-                            0,0,surf_width,surf_height,
-                            0,0,win_width,win_height,
-                            NULL,0,0);
-    ASSERT( VA_STATUS_SUCCESS == va_status );
+    va_status = vaSyncSurface(va_dpy, surface_id);
+    CHECK_VASTATUS(va_status, "vaSyncSurface");
+    
+    if (putsurface) {
+        Window  win;
+        win = XCreateSimpleWindow(x11_display, RootWindow(x11_display, 0), 0, 0,
+                              WIN_WIDTH,WIN_HEIGHT, 0, 0, WhitePixel(x11_display, 0));
+        XMapWindow(x11_display, win);
+        XSync(x11_display, False);
+        va_status = vaPutSurface(va_dpy, surface_id, win,
+                                0,0,CLIP_WIDTH,CLIP_HEIGHT,
+                                0,0,WIN_WIDTH,WIN_HEIGHT,
+                                NULL,0,0);
+        CHECK_VASTATUS(va_status, "vaPutSurface");
+    }
 
     printf("press any key to exit\n");
     getchar();
-    
-    vaDestroySurfaces(va_dpy,&vaSurface,1);
+
+    vaDestroySurfaces(va_dpy,&surface_id,1);
     vaDestroyConfig(va_dpy,config_id);
-    vaDestroyContext(va_dpy,vaContext);
-}
+    vaDestroyContext(va_dpy,context_id);
 
-void post()
-{
-    test_terminate();
+    vaTerminate(va_dpy);
+    XCloseDisplay(x11_display);
+    
+    return 0;
 }
diff --git a/test/encode/Makefile.am b/test/encode/Makefile.am
new file mode 100644 (file)
index 0000000..6d2d5a9
--- /dev/null
@@ -0,0 +1,36 @@
+# Copyright (c) 2007 Intel Corporation. All Rights Reserved.
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sub license, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+# 
+# The above copyright notice and this permission notice (including the
+# next paragraph) shall be included in all copies or substantial portions
+# of the Software.
+# 
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+# IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
+# ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+bin_PROGRAMS = h264encode
+
+AM_CFLAGS = -I$(top_srcdir)/src -I$(top_srcdir)/src/x11 -DIN_LIBVA
+
+TEST_LIBS = $(top_srcdir)/src/$(libvabackendlib)
+
+h264encode_LDADD = $(TEST_LIBS)
+h264encode_SOURCES = h264encode.c
+
+
+valgrind:      $(bin_PROGRAMS)
+       for a in $(bin_PROGRAMS); do \
+               valgrind --leak-check=full --show-reachable=yes .libs/$$a; \
+       done
diff --git a/test/encode/h264encode.c b/test/encode/h264encode.c
new file mode 100644 (file)
index 0000000..4a4d914
--- /dev/null
@@ -0,0 +1,428 @@
+/*
+ * Copyright (c) 2007-2008 Intel Corporation. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * it is a real program to show how VAAPI encoding work,
+ * It does H264 element stream level encoding on auto-generated YUV data
+ *
+ * gcc -o  h264encode  h264encode -lva -lva-x11 -I /usr/include/va
+ * ./h264encode -w <width> -h <height> -n <frame_num>
+ *
+ */  
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <getopt.h>
+#include <X11/Xlib.h>
+
+#include <unistd.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include <assert.h>
+
+#include "va.h"
+#include "va_x11.h"
+
+
+#define CHECK_VASTATUS(va_status,func)                                  \
+if (va_status != VA_STATUS_SUCCESS) {                                   \
+    fprintf(stderr,"%s:%s (%d) failed,exit\n", __func__, func, __LINE__); \
+    exit(1);                                                            \
+}
+
+#define SURFACE_NUM 18 /* 16 surfaces for src, 2 surface for reconstructed/reference */
+
+static  Display *x11_display;
+static  VADisplay va_dpy;
+static  VAContextID context_id;
+static  VASurfaceID surface_id[SURFACE_NUM];
+static  Window display_win = 0;
+static  int win_width;
+static  int win_height;
+
+static  int coded_fd;
+static  char coded_file[256];
+
+static  int frame_width=352, frame_height=288;
+static  int frame_rate = 30;
+static  int frame_count = 1000;
+static  int intra_count = 30;
+static  int frame_bitrate = 64000;
+static  int initial_qp = 15;
+static  int minimal_qp = 0;
+
+static int upload_source_YUV_once_for_all()
+{
+    VAImage surface_image;
+    void *surface_p=NULL, *U_start,*V_start;
+    VAStatus va_status;
+    int box_width=8;
+    int row_shift=0;
+    int i;
+    
+    for (i=0; i<SURFACE_NUM-2; i++) {
+        upload_surafce(va_dpy, surface_id[i], box_width, row_shift, 0);
+        
+        row_shift++;
+        if (row_shift==(2*box_width)) row_shift= 0;
+    }
+
+    return 0;
+}
+
+
+static int save_coded_buf(VABufferID coded_buf, int current_frame, int frame_skipped)
+{    
+    void *coded_p=NULL;
+    int coded_size,coded_offset,wrt_size;
+    VAStatus va_status;
+
+    va_status = vaMapBuffer(va_dpy,coded_buf,&coded_p);
+    coded_size = *((unsigned long *) coded_p); /* first DWord is the coded video size */
+    coded_offset = *((unsigned long *) (coded_p + 4)); /* second DWord is byte offset */
+    wrt_size = write(coded_fd,coded_p+coded_offset,coded_size);
+    assert(wrt_size==coded_size);
+    vaUnmapBuffer(va_dpy,coded_buf);
+
+
+    printf("\r      "); /* return back to startpoint */
+    switch (current_frame % 4) {
+        case 0:
+            printf("|");
+            break;
+        case 1:
+            printf("/");
+            break;
+        case 2:
+            printf("-");
+            break;
+        case 3:
+            printf("\\");
+            break;
+    }
+    printf("%08d", current_frame);
+    if (current_frame % intra_count == 0)
+        printf("(I)");
+    else
+        printf("(P)");
+    
+    printf("(%06d bytes coded)",coded_size);
+    if (frame_skipped)
+        printf("(SKipped)");
+
+    return;
+}
+
+
+static int display_surface(int current_frame, int *exit_encode)
+{
+    Window win = display_win;
+    XEvent event;
+    VAStatus va_status;
+    
+    if (current_frame == 0) {
+        win_width = frame_width;
+        win_height = frame_height;
+    }
+    
+    if (win == 0) { /* display reconstructed surface */
+        win = XCreateSimpleWindow(x11_display, RootWindow(x11_display, 0), 0, 0,
+                                  frame_width, frame_height, 0, 0, WhitePixel(x11_display, 0));
+        XMapWindow(x11_display, win);
+        XSync(x11_display, False);
+
+        display_win = win;
+    }
+
+    *exit_encode = 0;
+    while(XPending(x11_display)) {
+        XNextEvent(x11_display, &event);
+            
+        /* bail on any focused key press */
+        if(event.type == KeyPress) {  
+            *exit_encode = 1;
+            break;
+        }
+            
+        /* rescale the video to fit the window */
+        if(event.type == ConfigureNotify) { 
+            win_width = event.xconfigure.width;
+            win_height = event.xconfigure.height;
+        }      
+    }  
+    
+    va_status = vaPutSurface(va_dpy, surface_id[current_frame], win,
+                             0,0, frame_width, frame_height,
+                             0,0, win_width, win_height,
+                             NULL,0,0);
+    return;
+}
+
+enum {
+    SH_LEVEL_1=10,
+    SH_LEVEL_1B=11,
+    SH_LEVEL_2=20,
+    SH_LEVEL_3=30,
+    SH_LEVEL_31=31,
+    SH_LEVEL_32=32,
+    SH_LEVEL_4=40,
+    SH_LEVEL_5=50
+};
+
+static int do_h264_encoding(void)
+{
+    VAEncSequenceParameterBufferH264 seq_h264;
+    VAEncPictureParameterBufferH264 pic_h264;
+    VAEncSliceParameterBuffer slice_h264;
+    VAStatus va_status;
+    VABufferID coded_buf, seq_param_buf, pic_param_buf, slice_param_buf;
+    int codedbuf_size;
+    VASurfaceStatus surface_status;
+    int src_surface, dst_surface, ref_surface;
+    int putsurface=0, frame_skipped = 0;
+    int exit_encode = 0;
+    int i;
+
+    codedbuf_size = (frame_width * frame_height * 400) / (16*16);
+
+    src_surface = 0;
+    
+    /* the last two frames are reference/reconstructed frame */
+    dst_surface = SURFACE_NUM - 1;
+    ref_surface = SURFACE_NUM - 2;
+    
+    for (i=0; i < frame_count; i++) {
+        va_status = vaBeginPicture(va_dpy, context_id, surface_id[src_surface]);
+        CHECK_VASTATUS(va_status,"vaBeginPicture");
+
+        if (i == 0) {
+            seq_h264.level_idc = SH_LEVEL_3;
+            seq_h264.picture_width_in_mbs = frame_width;
+            seq_h264.picture_height_in_mbs = frame_height;
+            seq_h264.bits_per_second = frame_bitrate;
+            seq_h264.frame_rate = frame_rate;
+            seq_h264.initial_qp = initial_qp;
+            seq_h264.min_qp = minimal_qp;
+            seq_h264.basic_unit_size = 6;
+            seq_h264.intra_period = intra_count;
+            
+            va_status = vaCreateBuffer(va_dpy, context_id,
+                                       VAEncSequenceParameterBufferType,
+                                       sizeof(seq_h264),1,&seq_h264,&seq_param_buf);
+            CHECK_VASTATUS(va_status,"vaCreateBuffer");;
+
+            va_status = vaRenderPicture(va_dpy,context_id, &seq_param_buf, 1);
+            CHECK_VASTATUS(va_status,"vaRenderPicture");;
+        }
+
+        va_status = vaCreateBuffer(va_dpy,context_id,VAEncCodedBufferType,
+                                   codedbuf_size, 1, NULL, &coded_buf);
+
+        /* if a frame is skipped, current frame still use last reference frame */
+        if (frame_skipped == 0) {
+            /* swap ref/dst */
+            int tmp = dst_surface;
+            dst_surface = ref_surface;
+            ref_surface = tmp;
+        } 
+        
+        pic_h264.reference_picture = surface_id[ref_surface];
+        pic_h264.reconstructed_picture= surface_id[dst_surface];
+        pic_h264.coded_buf = coded_buf;
+        pic_h264.picture_width = frame_width;
+        pic_h264.picture_height = frame_height;
+        pic_h264.last_picture = (i==frame_count);
+        
+        va_status = vaCreateBuffer(va_dpy, context_id,VAEncPictureParameterBufferType,
+                                   sizeof(pic_h264),1,&pic_h264,&pic_param_buf);
+        CHECK_VASTATUS(va_status,"vaCreateBuffer");;
+
+        /* one frame, one slice */
+        slice_h264.start_row_number = 0;
+        slice_h264.slice_height = frame_height/16; /* Measured by MB */
+        slice_h264.slice_flags.bits.is_intra = i % intra_count;
+        slice_h264.slice_flags.bits.disable_deblocking_filter_idc = 0;
+        va_status = vaCreateBuffer(va_dpy,context_id,VAEncSliceParameterBufferType,
+                                   sizeof(slice_h264),1,&slice_h264,&slice_param_buf);
+        CHECK_VASTATUS(va_status,"vaCreateBuffer");;
+
+        va_status = vaRenderPicture(va_dpy,context_id, &pic_param_buf, 1);
+        CHECK_VASTATUS(va_status,"vaRenderPicture");;
+        
+        va_status = vaRenderPicture(va_dpy,context_id, &slice_param_buf, 1);
+        CHECK_VASTATUS(va_status,"vaRenderPicture");;
+        
+        va_status = vaEndPicture(va_dpy,context_id);
+        CHECK_VASTATUS(va_status,"vaEndPicture");;
+
+        va_status = vaSyncSurface(va_dpy, surface_id[0]);
+        CHECK_VASTATUS(va_status,"vaSyncSurface");;
+
+        va_status = vaQuerySurfaceStatus(va_dpy, surface_id[src_surface],&surface_status);
+        frame_skipped = (surface_status & VASurfaceSkipped);
+
+        save_coded_buf(coded_buf, i, frame_skipped);
+        
+        /* should display reconstructed frame, but just diplay source frame */
+        display_surface(src_surface, &exit_encode);
+        if (exit_encode)
+            frame_count = i;
+        
+        /* use next surface */
+        src_surface++;
+        if (src_surface == (SURFACE_NUM - 2))
+            src_surface = 0;
+    }
+
+    return 0;
+}
+
+int main(int argc,char **argv)
+{
+    VAEntrypoint entrypoints[5];
+    int num_entrypoints,slice_entrypoint;
+    VAConfigAttrib attrib[2];
+    VAConfigID config_id;
+    int major_ver, minor_ver;
+    VAStatus va_status;
+    char c;
+
+    strcpy(coded_file, "/tmp/demo.264");
+    while ((c =getopt(argc,argv,"w:h:n:p:f:r:q:s:o:?") ) != EOF) {
+        switch (c) {
+                case 'w':
+                    frame_width = atoi(optarg);
+                    break;
+                case 'h':
+                    frame_height = atoi(optarg);
+                    break;
+                case 'n':
+                    frame_count = atoi(optarg);
+                    break;
+                case 'p':
+                    intra_count = atoi(optarg);
+                    break;
+                case 'f':
+                    frame_rate = atoi(optarg);
+                    break;
+                case 'b':
+                    frame_bitrate = atoi(optarg);
+                    break;
+                case 'q':
+                    initial_qp = atoi(optarg);
+                    break;
+                case 's':
+                    minimal_qp = atoi(optarg);
+                    break;
+                case 'o':
+                    strcpy(coded_file, optarg);
+                    break;
+                case ':':
+                case '?':
+                    printf("./h264encode <options>\n");
+                    printf("   -w -h: resolution\n");
+                    printf("   -n frame number\n");
+                    printf("   -p P frame count between two I frames\n");
+                    printf("   -f frame rate\n");
+                    printf("   -r bit rate\n");
+                    printf("   -q initial QP\n");
+                    printf("   -s maximum QP\n");
+                    printf("   -s coded file\n");
+                    exit(0);
+        }
+    }
+    
+    x11_display = XOpenDisplay(":0.0");
+    assert(x11_display);
+    
+    va_dpy = vaGetDisplay(x11_display);
+    va_status = vaInitialize(va_dpy, &major_ver, &minor_ver);
+    CHECK_VASTATUS(va_status, "vaInitialize");
+
+    vaQueryConfigEntrypoints(va_dpy, VAProfileH264Baseline, entrypoints, 
+                             &num_entrypoints);
+    for        (slice_entrypoint = 0; slice_entrypoint < num_entrypoints; slice_entrypoint++) {
+        if (entrypoints[slice_entrypoint] == VAEntrypointEncSlice)
+            break;
+    }
+    if (slice_entrypoint == num_entrypoints) {
+        /* not find Slice entry point */
+        assert(0);
+    }
+
+    /* find out the format for the render target, and rate control mode */
+    attrib[0].type = VAConfigAttribRTFormat;
+    attrib[1].type = VAConfigAttribRateControl;
+    vaGetConfigAttributes(va_dpy, VAProfileH264Baseline, VAEntrypointEncSlice,
+                          &attrib[0], 2);
+    if ((attrib[0].value & VA_RT_FORMAT_YUV420) == 0) {
+        /* not find desired YUV420 RT format */
+        assert(0);
+    }
+    if ((attrib[1].value & VA_RC_VBR) == 0) {
+        /* Can't find matched RC mode */
+        printf("VBR mode doesn't found, exit\n");
+        assert(0);
+    }
+    attrib[0].value = VA_RT_FORMAT_YUV420; /* set to desired RT format */
+    attrib[1].value = VA_RC_VBR; /* set to desired RC mode */
+    
+    va_status = vaCreateConfig(va_dpy, VAProfileH264Baseline, VAEntrypointEncSlice,
+                              &attrib[0], 2,&config_id);
+    CHECK_VASTATUS(va_status, "vaCreateConfig");
+    
+    va_status = vaCreateSurfaces(va_dpy,frame_width, frame_height,
+                                 VA_RT_FORMAT_YUV420, SURFACE_NUM, &surface_id[0]);
+    CHECK_VASTATUS(va_status, "vaCreateSurfaces");
+    
+    /* Create a context for this decode pipe */
+    va_status = vaCreateContext(va_dpy, config_id,
+                                frame_width, ((frame_height+15)/16)*16,
+                                VA_PROGRESSIVE,&surface_id[0],SURFACE_NUM,&context_id);
+    CHECK_VASTATUS(va_status, "vaCreateContext");
+
+    /* store coded data into a file */
+    coded_fd = open(coded_file,O_CREAT|O_RDWR, 0);
+    if (coded_fd == -1) {
+        printf("Open file %s failed, exit\n", coded_file);
+        exit(1);
+    }
+
+    printf("Coded %d frames, %dx%d, save the coded file into %s\n",
+           frame_count, frame_width, frame_height, coded_file);
+    do_h264_encoding();
+    
+    vaDestroySurfaces(va_dpy,&surface_id[0],3);
+    vaDestroyConfig(va_dpy,config_id);
+    vaDestroyContext(va_dpy,context_id);
+    
+    vaTerminate(va_dpy);
+    
+    XCloseDisplay(x11_display);
+    
+    return 0;
+}
diff --git a/test/mpeg2-I.jpg b/test/mpeg2-I.jpg
deleted file mode 100644 (file)
index f5a6c50..0000000
Binary files a/test/mpeg2-I.jpg and /dev/null differ
diff --git a/test/putsurface/Makefile.am b/test/putsurface/Makefile.am
new file mode 100644 (file)
index 0000000..3e5c864
--- /dev/null
@@ -0,0 +1,36 @@
+# Copyright (c) 2007 Intel Corporation. All Rights Reserved.
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sub license, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+# 
+# The above copyright notice and this permission notice (including the
+# next paragraph) shall be included in all copies or substantial portions
+# of the Software.
+# 
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+# IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
+# ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+bin_PROGRAMS = putsurface
+
+AM_CFLAGS = -I$(top_srcdir)/src -I$(top_srcdir)/src/x11 -DIN_LIBVA
+
+TEST_LIBS = $(top_srcdir)/src/$(libvabackendlib)
+
+putsurface_LDADD = $(TEST_LIBS)
+putsurface_SOURCES = putsurface.c
+
+
+valgrind:      $(bin_PROGRAMS)
+       for a in $(bin_PROGRAMS); do \
+               valgrind --leak-check=full --show-reachable=yes .libs/$$a; \
+       done
diff --git a/test/putsurface/loadsurface.h b/test/putsurface/loadsurface.h
new file mode 100644 (file)
index 0000000..4c5da2d
--- /dev/null
@@ -0,0 +1,97 @@
+
+
+static int yuvgen_planar(int width, int height,
+                         unsigned char *Y_start, int Y_pitch,
+                         unsigned char *U_start, int U_pitch,
+                         unsigned char *V_start, int V_pitch,
+                         int UV_interleave, int box_width, int row_shift,
+                         int field)
+{
+    int row;
+
+    /* copy Y plane */
+    for (row=0;row<height;row++) {
+        unsigned char *Y_row = Y_start + row * Y_pitch;
+        int jj, xpos, ypos;
+
+        ypos = (row / box_width) & 0x1;
+
+        /* fill garbage data into the other field */
+        if (((field == VA_TOP_FIELD) && (row &1))
+            || ((field == VA_BOTTOM_FIELD) && ((row &1)==0))) { 
+            memset(Y_row, 0xff, width);
+            continue;
+        }
+        
+        for (jj=0; jj<width; jj++) {
+            xpos = ((row_shift + jj) / box_width) & 0x1;
+                        
+            if ((xpos == 0) && (ypos == 0))
+                Y_row[jj] = 0xeb;
+            if ((xpos == 1) && (ypos == 1))
+                Y_row[jj] = 0xeb;
+                        
+            if ((xpos == 1) && (ypos == 0))
+                Y_row[jj] = 0x10;
+            if ((xpos == 0) && (ypos == 1))
+                Y_row[jj] = 0x10;
+        }
+    }
+  
+    /* copy UV data */
+    for( row =0; row < height/2; row++) {
+        unsigned short value = 0x80;
+
+        /* fill garbage data into the other field */
+        if (((field == VA_TOP_FIELD) && (row &1))
+            || ((field == VA_BOTTOM_FIELD) && ((row &1)==0))) {
+            value = 0xff;
+        }
+
+        if (UV_interleave) {
+            unsigned short *UV_row = (unsigned short *)(U_start + row * U_pitch);
+
+            memset(UV_row, value, width);
+        } else {
+            unsigned char *U_row = U_start + row * U_pitch;
+            unsigned char *V_row = V_start + row * V_pitch;
+            
+            memset (U_row,value,width/2);
+            memset (V_row,value,width/2);
+        }
+    }
+
+    return 0;
+}
+
+static int upload_surface(VADisplay va_dpy, VASurfaceID surface_id,
+                          int box_width, int row_shift,
+                          int field)
+{
+    VAImage surface_image;
+    void *surface_p=NULL, *U_start,*V_start;
+    VAStatus va_status;
+    
+    va_status = vaDeriveImage(va_dpy,surface_id,&surface_image);
+    CHECK_VASTATUS(va_status,"vaDeriveImage");
+
+    vaMapBuffer(va_dpy,surface_image.buf,&surface_p);
+    assert(VA_STATUS_SUCCESS == va_status);
+        
+    U_start = surface_p + surface_image.offsets[1];
+    V_start = surface_p + surface_image.offsets[2];
+
+    /* assume surface is planar format */
+    yuvgen_planar(surface_image.width, surface_image.height,
+                  surface_p, surface_image.pitches[0],
+                  U_start, surface_image.pitches[1],
+                  V_start, surface_image.pitches[2],
+                  (surface_image.format.fourcc==VA_FOURCC_NV12),
+                  box_width, row_shift, field);
+        
+    vaUnmapBuffer(va_dpy,surface_image.buf);
+
+    vaDestroyImage(va_dpy,surface_image.image_id);
+
+    return 0;
+}
diff --git a/test/putsurface/putsurface.c b/test/putsurface/putsurface.c
new file mode 100644 (file)
index 0000000..359d1e0
--- /dev/null
@@ -0,0 +1,343 @@
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <getopt.h>
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <sys/time.h>
+
+#include <unistd.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include <va/va.h>
+#include <va/va_x11.h>
+
+#include <assert.h>
+
+#include <pthread.h>
+
+/*currently, if XCheckWindowEvent was called  in more than one thread, it would cause
+ * XIO:  fatal IO error 11 (Resource temporarily unavailable) on X server ":0.0"
+ *       after 87 requests (83 known processed) with 0 events remaining.
+ *
+ *       X Error of failed request:  BadGC (invalid GC parameter)
+ *       Major opcode of failed request:  60 (X_FreeGC)
+ *       Resource id in failed request:  0x600034
+ *       Serial number of failed request:  398
+ *       Current serial number in output stream:  399
+ * The root cause is unknown. */
+
+#define CHECK_VASTATUS(va_status,func)                                  \
+if (va_status != VA_STATUS_SUCCESS) {                                   \
+    fprintf(stderr,"%s:%s (%d) failed,exit\n", __func__, func, __LINE__); \
+    exit(1);                                                            \
+}
+
+#include "loadsurface.h"
+
+
+#define SURFACE_NUM 5
+static  VASurfaceID surface_id[SURFACE_NUM];
+static  int surface_width=352, surface_height=288;
+static  int win_width=352, win_height=288;
+static  Window win_thread0, win_thread1;
+static  Pixmap pixmap_thread0, pixmap_thread1;
+static  GC context_thread0, context_thread1;
+static  Display *x11_display;
+static  VADisplay *va_dpy;
+static  int multi_thread=0;
+static  int put_pixmap = 0;
+static  int test_clip = 1;
+static  int display_field = VA_FRAME_PICTURE;
+static  int check_event = 1;
+static  int verbose=0;
+static  pthread_mutex_t surface_mutex[SURFACE_NUM];
+
+static pthread_mutex_t gmutex;
+
+static  int box_width=32;
+
+static Pixmap create_pixmap(int width, int height)
+{
+    int screen = DefaultScreen(x11_display);
+    Window root;
+    Pixmap pixmap;
+    XWindowAttributes attr;
+    
+    root = RootWindow(x11_display, screen);
+
+    XGetWindowAttributes (x11_display, root, &attr);
+    
+    printf("Create a pixmap from ROOT window %dx%d\n\n", attr.width, attr.height);
+    pixmap = XCreatePixmap(x11_display, root, attr.width, attr.height,
+                           DefaultDepth(x11_display, DefaultScreen(x11_display)));
+
+    return pixmap;
+}
+
+static int create_window(int width, int height)
+{
+    int screen = DefaultScreen(x11_display);
+    Window root, win;
+
+    root = RootWindow(x11_display, screen);
+
+    printf("Create window0 for thread0\n");
+    win_thread0 = win = XCreateSimpleWindow(x11_display, root, 0, 0, width, height,
+                                            0, 0, WhitePixel(x11_display, 0));
+    if (win) {
+        XSizeHints sizehints;
+        sizehints.width  = width;
+        sizehints.height = height;
+        sizehints.flags = USSize;
+        XSetNormalHints(x11_display, win, &sizehints);
+        XSetStandardProperties(x11_display, win, "Thread 0", "Thread 0",
+                               None, (char **)NULL, 0, &sizehints);
+
+        XMapWindow(x11_display, win);
+    }
+    context_thread0 = XCreateGC(x11_display, win, 0, 0);
+    XSelectInput(x11_display, win, KeyPressMask | StructureNotifyMask);
+    XSync(x11_display, False);
+
+    if (put_pixmap)
+        pixmap_thread0 = create_pixmap(width, height);
+    
+    if (multi_thread == 0)
+        return 0;
+
+    printf("Create window1 for thread1\n");
+    
+    win_thread1 = win = XCreateSimpleWindow(x11_display, root, width, 0, width, height,
+                                            0, 0, WhitePixel(x11_display, 0));
+    if (win) {
+        XSizeHints sizehints;
+        sizehints.width  = width;
+        sizehints.height = height;
+        sizehints.flags = USSize;
+        XSetNormalHints(x11_display, win, &sizehints);
+        XSetStandardProperties(x11_display, win, "Thread 1", "Thread 1",
+                               None, (char **)NULL, 0, &sizehints);
+
+        XMapWindow(x11_display, win);
+    }
+    if (put_pixmap)
+        pixmap_thread1 = create_pixmap(width, height);
+
+    context_thread1 = XCreateGC(x11_display, win, 0, 0);
+    XSelectInput(x11_display, win, KeyPressMask | StructureNotifyMask);
+    XSync(x11_display, False);
+    
+    return 0;
+}
+
+static VASurfaceID get_next_free_surface(int *index)
+{
+    VASurfaceStatus surface_status;
+    int i;
+
+    assert(index);
+
+    for (i=0; i<SURFACE_NUM; i++) {
+        surface_status = 0;
+        vaQuerySurfaceStatus(va_dpy, surface_id[i], &surface_status);
+        if (surface_status == VASurfaceReady)
+        {
+            if (0 == pthread_mutex_trylock(&surface_mutex[i]))
+            {
+                *index = i;
+                break;
+            }
+        }
+    }
+
+    if (i==SURFACE_NUM)
+        return VA_INVALID_SURFACE;
+    else
+        return surface_id[i];
+}
+
+static int putsurface_thread(void *data)
+{
+    int width=win_width, height=win_height;
+    Drawable draw;
+    Window win = (Window)data;
+    Pixmap pixmap = 0;
+    GC context = NULL;
+    int quit = 0;
+    VAStatus vaStatus;
+    int row_shift = 0;
+    int index = 0;
+    Bool is_event; 
+    XEvent event;
+
+    if (win == win_thread0) {
+        printf("Enter into thread0\n\n");
+        pixmap = pixmap_thread0;
+        context = context_thread0;
+    }
+    
+    if (win == win_thread1) {
+        printf("Enter into thread1\n\n");
+        pixmap = pixmap_thread1;
+        context = context_thread1;
+    }
+    
+    if (put_pixmap) {
+        printf("vaPutSurface into a Pixmap, then copy into the Window\n\n");
+        draw = pixmap;
+    } else {
+        printf("vaPutSurface into a Window directly\n\n");
+        draw = win;
+    }
+    
+    while (!quit) {
+        VASurfaceID surface_id = VA_INVALID_SURFACE;
+        
+        while (surface_id == VA_INVALID_SURFACE)
+            surface_id = get_next_free_surface(&index);
+
+        if (verbose) printf("Thread %x Display surface 0x%p,\n", (unsigned int)win, (void *)surface_id);
+
+        upload_surface(va_dpy, surface_id, box_width, row_shift, display_field);
+        
+        vaStatus = vaPutSurface(va_dpy, surface_id, draw,
+                                0,0,surface_width,surface_height,
+                                0,0,width,height,
+                                NULL,0,display_field);
+        CHECK_VASTATUS(vaStatus,"vaPutSurface");
+
+        if (put_pixmap)
+            XCopyArea(x11_display, pixmap, win,  context, 0, 0, width, height, 0, 0);
+        
+        pthread_mutex_unlock(&surface_mutex[index]);
+
+        if (check_event) {
+            pthread_mutex_lock(&gmutex);
+            is_event =XCheckWindowEvent(x11_display, win, StructureNotifyMask|KeyPressMask,&event);
+            pthread_mutex_unlock(&gmutex);
+            if (is_event) {
+                /* bail on any focused key press */
+                if(event.type == KeyPress) {  
+                    quit = 1;
+                    break;
+                }
+
+                /* rescale the video to fit the window */
+                if(event.type == ConfigureNotify) { 
+                    width = event.xconfigure.width;
+                    height = event.xconfigure.height;
+                    printf("Scale window to %dx%d\n", width, height);
+                }      
+            }
+        }
+        
+        row_shift++;
+        if (row_shift==(2*box_width)) row_shift= 0;
+    }
+
+    pthread_exit(NULL);
+}
+
+
+int main(int argc,char **argv)
+{
+    int major_ver, minor_ver;
+    VAStatus va_status;
+    pthread_t thread1;
+    int ret;
+    char c;
+    int i;
+
+    while ((c =getopt(argc,argv,"w:h:d:f:tep?nv") ) != EOF) {
+        switch (c) {
+            case '?':
+                printf("putsurface <options>\n");
+                printf("           -p output to pixmap\n");
+                printf("           -d the dimension of black/write square box, default is 32\n");
+                printf("           -t multi-threads\n");
+                printf("           -e don't check X11 event\n");
+                printf("           -c test clipbox\n");
+                printf("           -f <1/2> top field, or bottom field\n");
+                printf("           -v verbose output\n");
+                exit(0);
+                break;
+            case 'w':
+                win_width = atoi(optarg);
+                break;
+            case 'h':
+                win_height = atoi(optarg);
+                break;
+            case 'd':
+                box_width = atoi(optarg);
+                break;
+            case 't':
+                multi_thread = 1;
+                printf("Two threads to do vaPutSurface\n");
+                break;
+            case 'e':
+                check_event = 0;
+                break;
+            case 'p':
+                put_pixmap = 1;
+                break;
+            case 'c':
+                test_clip = 1;
+                break;
+            case 'f':
+                if (atoi(optarg) == 1) {
+                    printf("Display TOP field\n");
+                    display_field = VA_TOP_FIELD;
+                } else if (atoi(optarg) == 2) {
+                    printf("Display BOTTOM field\n");
+                    display_field = VA_BOTTOM_FIELD;
+                } else
+                    printf("The validate input for -f is: 1(top field)/2(bottom field)\n");
+                break;
+            case 'v':
+                verbose = 1;
+                printf("Enable verbose output\n");
+                break;
+        }
+    }
+    
+    x11_display = XOpenDisplay(":0.0");
+    if (x11_display == NULL) {
+        fprintf(stderr, "Can't connect X server!\n");
+        exit(-1);
+    }
+
+    create_window(win_width, win_height);
+
+    va_dpy = vaGetDisplay(x11_display);
+    va_status = vaInitialize(va_dpy, &major_ver, &minor_ver);
+    CHECK_VASTATUS(va_status, "vaInitialize");
+
+    surface_width = win_width;
+    surface_height = win_height;
+    va_status = vaCreateSurfaces(va_dpy,surface_width, surface_height,
+                                VA_RT_FORMAT_YUV420, SURFACE_NUM, &surface_id[0]);
+    CHECK_VASTATUS(va_status, "vaCreateSurfaces");
+
+    if (check_event)
+        pthread_mutex_init(&gmutex, NULL);
+    
+    for(i = 0; i< SURFACE_NUM; i++)
+        pthread_mutex_init(&surface_mutex[i], NULL);
+    
+    if (multi_thread == 1) 
+        ret = pthread_create(&thread1, NULL, (void *)putsurface_thread, (void*)win_thread1);
+
+    putsurface_thread((void *)win_thread0);
+
+    if (multi_thread == 1) 
+        pthread_join(thread1, (void **)&ret);
+
+    vaDestroySurfaces(va_dpy,&surface_id[0],SURFACE_NUM);    
+    vaTerminate(va_dpy);
+    
+    return 0;
+}