diff options
Diffstat (limited to 'test/putsurface/putsurface.c')
-rw-r--r-- | test/putsurface/putsurface.c | 343 |
1 files changed, 343 insertions, 0 deletions
diff --git a/test/putsurface/putsurface.c b/test/putsurface/putsurface.c new file mode 100644 index 0000000..359d1e0 --- /dev/null +++ b/test/putsurface/putsurface.c @@ -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; +} |