| /* | |
| * Copyright (c) 2008-2009 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. | |
| */ | |
| #include <stdio.h> | |
| #include <string.h> | |
| #include <stdlib.h> | |
| #include <stdint.h> | |
| #include <getopt.h> | |
| #include <sys/time.h> | |
| #include <unistd.h> | |
| #include <sys/types.h> | |
| #include <sys/stat.h> | |
| #include <fcntl.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 16 | |
| static void *win_display; | |
| static VADisplay va_dpy; | |
| static VAImageFormat *va_image_formats; | |
| static int va_num_image_formats = -1; | |
| static VAConfigID vpp_config_id = VA_INVALID_ID; | |
| static VASurfaceAttrib *va_surface_attribs; | |
| static int va_num_surface_attribs = -1; | |
| static VASurfaceID surface_id[SURFACE_NUM]; | |
| static pthread_mutex_t surface_mutex[SURFACE_NUM]; | |
| static void *drawable_thread0, *drawable_thread1; | |
| static int surface_width = 352, surface_height = 288; | |
| static int win_x = 0, win_y = 0; | |
| static int win_width = 352, win_height = 288; | |
| static int frame_rate = 0; | |
| static unsigned long long frame_num_total = ~0; | |
| static int check_event = 1; | |
| static int put_pixmap = 0; | |
| static int test_clip = 0; | |
| static int display_field = VA_FRAME_PICTURE; | |
| static pthread_mutex_t gmutex; | |
| static int box_width = 32; | |
| static int multi_thread = 0; | |
| static int verbose = 0; | |
| static int test_color_conversion = 0; | |
| static int csc_src_fourcc = 0, csc_dst_fourcc = 0; | |
| static VAImage csc_dst_fourcc_image; | |
| static VASurfaceID csc_render_surface; | |
| typedef struct { | |
| char* fmt_str; | |
| unsigned int fourcc; | |
| } fourcc_map; | |
| fourcc_map va_fourcc_map[] = { | |
| {"YUYV", VA_FOURCC_YUY2}, | |
| {"YUY2", VA_FOURCC_YUY2}, | |
| {"NV12", VA_FOURCC_NV12}, | |
| {"YV12", VA_FOURCC_YV12}, | |
| {"BGRA", VA_FOURCC_BGRA}, | |
| {"RGBA", VA_FOURCC_RGBA}, | |
| {"BGRX", VA_FOURCC_BGRX}, | |
| {"RGBX", VA_FOURCC_RGBX}, | |
| }; | |
| unsigned int map_str_to_vafourcc (char * str) | |
| { | |
| int i; | |
| for (i=0; i< sizeof(va_fourcc_map)/sizeof(fourcc_map); i++) { | |
| if (!strcmp(va_fourcc_map[i].fmt_str, str)) { | |
| return va_fourcc_map[i].fourcc; | |
| } | |
| } | |
| return 0; | |
| } | |
| char* map_vafourcc_to_str (unsigned int format) | |
| { | |
| static char unknown_format[] = "unknown-format"; | |
| int i; | |
| for (i=0; i< sizeof(va_fourcc_map)/sizeof(fourcc_map); i++) { | |
| if (va_fourcc_map[i].fourcc == format) { | |
| return va_fourcc_map[i].fmt_str; | |
| } | |
| } | |
| return unknown_format; | |
| } | |
| static int | |
| va_value_equals(const VAGenericValue *v1, const VAGenericValue *v2) | |
| { | |
| if (v1->type != v2->type) | |
| return 0; | |
| switch (v1->type) { | |
| case VAGenericValueTypeInteger: | |
| return v1->value.i == v2->value.i; | |
| case VAGenericValueTypeFloat: | |
| return v1->value.f == v2->value.f; | |
| case VAGenericValueTypePointer: | |
| return v1->value.p == v2->value.p; | |
| case VAGenericValueTypeFunc: | |
| return v1->value.fn == v2->value.fn; | |
| } | |
| return 0; | |
| } | |
| static int | |
| ensure_image_formats(void) | |
| { | |
| VAStatus va_status; | |
| VAImageFormat *image_formats; | |
| int num_image_formats; | |
| if (va_num_image_formats >= 0) | |
| return va_num_image_formats; | |
| num_image_formats = vaMaxNumImageFormats(va_dpy); | |
| if (num_image_formats == 0) | |
| return 0; | |
| image_formats = malloc(num_image_formats * sizeof(*image_formats)); | |
| if (!image_formats) | |
| return 0; | |
| va_status = vaQueryImageFormats(va_dpy, image_formats, &num_image_formats); | |
| CHECK_VASTATUS(va_status, "vaQuerySurfaceAttributes()"); | |
| va_image_formats = image_formats; | |
| va_num_image_formats = num_image_formats; | |
| return num_image_formats; | |
| } | |
| static const VAImageFormat * | |
| lookup_image_format(uint32_t fourcc) | |
| { | |
| int i; | |
| if (!ensure_image_formats()) | |
| return NULL; | |
| for (i = 0; i < va_num_image_formats; i++) { | |
| const VAImageFormat * const image_format = &va_image_formats[i]; | |
| if (image_format->fourcc == fourcc) | |
| return image_format; | |
| } | |
| return NULL; | |
| } | |
| static int | |
| ensure_surface_attribs(void) | |
| { | |
| VAStatus va_status; | |
| VASurfaceAttrib *surface_attribs; | |
| unsigned int num_image_formats, num_surface_attribs; | |
| if (va_num_surface_attribs >= 0) | |
| return va_num_surface_attribs; | |
| num_image_formats = vaMaxNumImageFormats(va_dpy); | |
| if (num_image_formats == 0) | |
| return 0; | |
| va_status = vaCreateConfig(va_dpy, VAProfileNone, VAEntrypointVideoProc, | |
| NULL, 0, &vpp_config_id); | |
| CHECK_VASTATUS(va_status, "vaCreateConfig()"); | |
| /* Guess the number of surface attributes, thus including any | |
| pixel-format supported by the VA driver */ | |
| num_surface_attribs = VASurfaceAttribCount + num_image_formats; | |
| surface_attribs = malloc(num_surface_attribs * sizeof(*surface_attribs)); | |
| if (!surface_attribs) | |
| return 0; | |
| va_status = vaQuerySurfaceAttributes(va_dpy, vpp_config_id, | |
| surface_attribs, &num_surface_attribs); | |
| if (va_status == VA_STATUS_SUCCESS) | |
| va_surface_attribs = surface_attribs; | |
| else if (va_status == VA_STATUS_ERROR_MAX_NUM_EXCEEDED) { | |
| va_surface_attribs = realloc(surface_attribs, | |
| num_surface_attribs * sizeof(*va_surface_attribs)); | |
| if (!va_surface_attribs) { | |
| free(surface_attribs); | |
| return 0; | |
| } | |
| va_status = vaQuerySurfaceAttributes(va_dpy, vpp_config_id, | |
| va_surface_attribs, &num_surface_attribs); | |
| } | |
| CHECK_VASTATUS(va_status, "vaQuerySurfaceAttributes()"); | |
| va_num_surface_attribs = num_surface_attribs; | |
| return num_surface_attribs; | |
| } | |
| static const VASurfaceAttrib * | |
| lookup_surface_attrib(VASurfaceAttribType type, const VAGenericValue *value) | |
| { | |
| int i; | |
| if (!ensure_surface_attribs()) | |
| return NULL; | |
| for (i = 0; i < va_num_surface_attribs; i++) { | |
| const VASurfaceAttrib * const surface_attrib = &va_surface_attribs[i]; | |
| if (surface_attrib->type != type) | |
| continue; | |
| if (!(surface_attrib->flags & VA_SURFACE_ATTRIB_SETTABLE)) | |
| continue; | |
| if (va_value_equals(&surface_attrib->value, value)) | |
| return surface_attrib; | |
| } | |
| return NULL; | |
| } | |
| int csc_preparation () | |
| { | |
| VAStatus va_status; | |
| // 1. make sure dst fourcc is supported for vaImage | |
| if (!lookup_image_format(csc_dst_fourcc)) { | |
| test_color_conversion = 0; | |
| printf("VA driver doesn't support %s image, skip additional color conversion\n", map_vafourcc_to_str(csc_dst_fourcc)); | |
| goto cleanup; | |
| } | |
| // 2. make sure src_fourcc is supported for vaSurface | |
| VASurfaceAttrib surface_attribs[1], * const s_attrib = &surface_attribs[0]; | |
| s_attrib->type = VASurfaceAttribPixelFormat; | |
| s_attrib->flags = VA_SURFACE_ATTRIB_SETTABLE; | |
| s_attrib->value.type = VAGenericValueTypeInteger; | |
| s_attrib->value.value.i = csc_src_fourcc; | |
| if (!lookup_surface_attrib(VASurfaceAttribPixelFormat, &s_attrib->value)) { | |
| printf("VA driver doesn't support %s surface, skip additional color conversion\n", map_vafourcc_to_str(csc_src_fourcc)); | |
| test_color_conversion = 0; | |
| goto cleanup; | |
| } | |
| // 3 create all objs required by csc | |
| // 3.1 vaSurface with src fourcc | |
| va_status = vaCreateSurfaces( | |
| va_dpy, | |
| VA_RT_FORMAT_YUV420, surface_width, surface_height, | |
| &surface_id[0], SURFACE_NUM, | |
| surface_attribs, 1 | |
| ); | |
| CHECK_VASTATUS(va_status,"vaCreateSurfaces"); | |
| // 3.2 vaImage with dst fourcc | |
| VAImageFormat image_format; | |
| image_format.fourcc = csc_dst_fourcc; | |
| image_format.byte_order = VA_LSB_FIRST; | |
| image_format.bits_per_pixel = 16; | |
| va_status = vaCreateImage(va_dpy, &image_format, | |
| surface_width, surface_height, | |
| &csc_dst_fourcc_image); | |
| CHECK_VASTATUS(va_status,"vaCreateImage"); | |
| // 3.3 create a temp VASurface for final rendering(vaPutSurface) | |
| s_attrib->value.value.i = VA_FOURCC_NV12; | |
| va_status = vaCreateSurfaces(va_dpy, VA_RT_FORMAT_YUV420, | |
| surface_width, surface_height, | |
| &csc_render_surface, 1, | |
| surface_attribs, 1); | |
| CHECK_VASTATUS(va_status,"vaCreateSurfaces"); | |
| cleanup: | |
| return test_color_conversion; | |
| } | |
| static VASurfaceID get_next_free_surface(int *index) | |
| { | |
| VASurfaceStatus surface_status; | |
| int i; | |
| assert(index); | |
| if (multi_thread == 0) { | |
| i = *index; | |
| i++; | |
| if (i == SURFACE_NUM) | |
| i = 0; | |
| *index = i; | |
| return surface_id[i]; | |
| } | |
| for (i=0; i<SURFACE_NUM; i++) { | |
| surface_status = (VASurfaceStatus)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 upload_source_YUV_once_for_all() | |
| { | |
| int box_width_loc=8; | |
| int row_shift_loc=0; | |
| int i; | |
| for (i=0; i<SURFACE_NUM; i++) { | |
| printf("\rLoading data into surface %d.....", i); | |
| upload_surface(va_dpy, surface_id[i], box_width_loc, row_shift_loc, 0); | |
| row_shift_loc++; | |
| if (row_shift_loc==(2*box_width_loc)) row_shift_loc= 0; | |
| } | |
| printf("\n"); | |
| return 0; | |
| } | |
| /* | |
| * Helper function for profiling purposes | |
| */ | |
| static unsigned long get_tick_count(void) | |
| { | |
| struct timeval tv; | |
| if (gettimeofday(&tv, NULL)) | |
| return 0; | |
| return tv.tv_usec/1000+tv.tv_sec*1000; | |
| } | |
| static void update_clipbox(VARectangle *cliprects, int width, int height) | |
| { | |
| if (test_clip == 0) | |
| return; | |
| srand((unsigned)time(NULL)); | |
| cliprects[0].x = (rand() % width); | |
| cliprects[0].y = (rand() % height); | |
| cliprects[0].width = (rand() % (width - cliprects[0].x)); | |
| cliprects[0].height = (rand() % (height - cliprects[0].y)); | |
| cliprects[1].x = (rand() % width); | |
| cliprects[1].y = (rand() % height); | |
| cliprects[1].width = (rand() % (width - cliprects[1].x)); | |
| cliprects[1].height = (rand() % (height - cliprects[1].y)); | |
| printf("\nTest clip (%d,%d, %d x %d) and (%d,%d, %d x %d) \n", | |
| cliprects[0].x, cliprects[0].y, cliprects[0].width, cliprects[0].height, | |
| cliprects[1].x, cliprects[1].y, cliprects[1].width, cliprects[1].height); | |
| } | |
| static void* putsurface_thread(void *data) | |
| { | |
| int width=win_width, height=win_height; | |
| void *drawable = data; | |
| int quit = 0; | |
| VAStatus vaStatus; | |
| int row_shift = 0; | |
| int index = 0; | |
| unsigned int frame_num=0, start_time, putsurface_time; | |
| VARectangle cliprects[2]; /* client supplied clip list */ | |
| int continue_display = 0; | |
| if (drawable == drawable_thread0) | |
| printf("Enter into thread0\n\n"); | |
| if (drawable == drawable_thread1) | |
| printf("Enter into thread1\n\n"); | |
| putsurface_time = 0; | |
| 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: %p Display surface 0x%x,\n", drawable, surface_id); | |
| if (multi_thread) | |
| upload_surface(va_dpy, surface_id, box_width, row_shift, display_field); | |
| if (check_event) | |
| pthread_mutex_lock(&gmutex); | |
| start_time = get_tick_count(); | |
| if ((continue_display == 0) && getenv("FRAME_STOP")) { | |
| char c; | |
| printf("Press any key to display frame %d...(c/C to continue)\n", frame_num); | |
| c = getchar(); | |
| if (c == 'c' || c == 'C') | |
| continue_display = 1; | |
| } | |
| if (test_color_conversion) { | |
| static int _put_surface_count = 0; | |
| if (_put_surface_count++ %50 == 0) { | |
| printf("do additional colorcoversion from %s to %s\n", map_vafourcc_to_str(csc_src_fourcc), map_vafourcc_to_str(csc_dst_fourcc)); | |
| } | |
| // get image from surface, csc_src_fourcc to csc_dst_fourcc conversion happens | |
| vaStatus = vaGetImage(va_dpy, surface_id, 0, 0, | |
| surface_width, surface_height, csc_dst_fourcc_image.image_id); | |
| CHECK_VASTATUS(vaStatus,"vaGetImage"); | |
| // render csc_dst_fourcc image to temp surface | |
| vaStatus = vaPutImage(va_dpy, csc_render_surface, csc_dst_fourcc_image.image_id, | |
| 0, 0, surface_width, surface_height, | |
| 0, 0, surface_width, surface_height); | |
| CHECK_VASTATUS(vaStatus,"vaPutImage"); | |
| // render the temp surface, it should be same with original surface without color conversion test | |
| vaStatus = vaPutSurface(va_dpy, csc_render_surface, CAST_DRAWABLE(drawable), | |
| 0,0,surface_width,surface_height, | |
| 0,0,width,height, | |
| (test_clip==0)?NULL:&cliprects[0], | |
| (test_clip==0)?0:2, | |
| display_field); | |
| CHECK_VASTATUS(vaStatus,"vaPutSurface"); | |
| } | |
| else { | |
| vaStatus = vaPutSurface(va_dpy, surface_id, CAST_DRAWABLE(drawable), | |
| 0,0,surface_width,surface_height, | |
| 0,0,width,height, | |
| (test_clip==0)?NULL:&cliprects[0], | |
| (test_clip==0)?0:2, | |
| display_field); | |
| CHECK_VASTATUS(vaStatus,"vaPutSurface"); | |
| } | |
| putsurface_time += (get_tick_count() - start_time); | |
| if (check_event) | |
| pthread_mutex_unlock(&gmutex); | |
| pthread_mutex_unlock(&surface_mutex[index]); /* locked in get_next_free_surface */ | |
| if ((frame_num % 0xff) == 0) { | |
| fprintf(stderr, "%.2f FPS \r", 256000.0 / (float)putsurface_time); | |
| putsurface_time = 0; | |
| update_clipbox(cliprects, width, height); | |
| } | |
| if (check_event) | |
| check_window_event(win_display, drawable, &width, &height, &quit); | |
| if (multi_thread) { /* reload surface content */ | |
| row_shift++; | |
| if (row_shift==(2*box_width)) row_shift= 0; | |
| } | |
| if (frame_rate != 0) /* rough framerate control */ | |
| usleep(1000/frame_rate*1000); | |
| frame_num++; | |
| if (frame_num >= frame_num_total) | |
| quit = 1; | |
| } | |
| if (drawable == drawable_thread1) | |
| pthread_exit(NULL); | |
| return 0; | |
| } | |
| int main(int argc,char **argv) | |
| { | |
| int major_ver, minor_ver; | |
| VAStatus va_status; | |
| pthread_t thread1; | |
| int ret; | |
| int c; | |
| int i; | |
| char str_src_fmt[5], str_dst_fmt[5]; | |
| static struct option long_options[] = | |
| { | |
| {"fmt1", required_argument, NULL, '1'}, | |
| {"fmt2", required_argument, NULL, '2'}, | |
| {0, 0, 0, 0} | |
| }; | |
| while ((c =getopt_long(argc,argv,"w:h:g:r:d:f:tcep?n:1:2:v", long_options, NULL)) != EOF) { | |
| switch (c) { | |
| case '?': | |
| printf("putsurface <options>\n"); | |
| printf(" -g <widthxheight+x_location+y_location> window geometry\n"); | |
| printf(" -w/-h resolution of surface\n"); | |
| printf(" -r <framerate>\n"); | |
| printf(" -d the dimension of black/write square box, default is 32\n"); | |
| printf(" -t multi-threads\n"); | |
| printf(" -c test clipbox\n"); | |
| printf(" -f <1/2> top field, or bottom field\n"); | |
| printf(" -1 source format (fourcc) for color conversion test\n"); | |
| printf(" -2 dest format (fourcc) for color conversion test\n"); | |
| printf(" --fmt1 same to -1\n"); | |
| printf(" --fmt2 same to -2\n"); | |
| printf(" -v verbose output\n"); | |
| exit(0); | |
| break; | |
| case 'g': | |
| ret = sscanf(optarg, "%dx%d+%d+%d", &win_width, &win_height, &win_x, &win_y); | |
| if (ret != 4) { | |
| printf("invalid window geometry, must be widthxheight+x_location+y_location\n"); | |
| exit(0); | |
| } else | |
| printf("Create window at (%d, %d), width = %d, height = %d\n", | |
| win_x, win_y, win_width, win_height); | |
| break; | |
| case 'r': | |
| frame_rate = atoi(optarg); | |
| break; | |
| case 'w': | |
| surface_width = atoi(optarg); | |
| break; | |
| case 'h': | |
| surface_height = atoi(optarg); | |
| break; | |
| case 'n': | |
| frame_num_total = 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 '1': | |
| sscanf(optarg, "%s", str_src_fmt); | |
| csc_src_fourcc = map_str_to_vafourcc (str_src_fmt); | |
| if (!csc_src_fourcc) { | |
| printf("invalid fmt1: %s\n", str_src_fmt ); | |
| exit(0); | |
| } | |
| break; | |
| case '2': | |
| sscanf(optarg, "%s", str_dst_fmt); | |
| csc_dst_fourcc = map_str_to_vafourcc (str_dst_fmt); | |
| if (!csc_dst_fourcc) { | |
| printf("invalid fmt1: %s\n", str_dst_fmt ); | |
| exit(0); | |
| } | |
| break; | |
| case 'v': | |
| verbose = 1; | |
| printf("Enable verbose output\n"); | |
| break; | |
| } | |
| } | |
| if (csc_src_fourcc && csc_dst_fourcc) { | |
| test_color_conversion = 1; | |
| } | |
| win_display = (void *)open_display(); | |
| if (win_display == NULL) { | |
| fprintf(stderr, "Can't open the connection of display!\n"); | |
| exit(-1); | |
| } | |
| create_window(win_display, win_x, win_y, win_width, win_height); | |
| va_dpy = vaGetDisplay(win_display); | |
| va_status = vaInitialize(va_dpy, &major_ver, &minor_ver); | |
| CHECK_VASTATUS(va_status, "vaInitialize"); | |
| if (test_color_conversion) { | |
| ret = csc_preparation(); | |
| } | |
| if (!test_color_conversion || !ret ) { | |
| va_status = vaCreateSurfaces( | |
| va_dpy, | |
| VA_RT_FORMAT_YUV420, surface_width, surface_height, | |
| &surface_id[0], SURFACE_NUM, | |
| NULL, 0 | |
| ); | |
| } | |
| CHECK_VASTATUS(va_status, "vaCreateSurfaces"); | |
| if (multi_thread == 0) /* upload the content for all surfaces */ | |
| upload_source_YUV_once_for_all(); | |
| 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, putsurface_thread, (void*)drawable_thread1); | |
| putsurface_thread((void *)drawable_thread0); | |
| if (multi_thread == 1) | |
| pthread_join(thread1, (void **)&ret); | |
| printf("thread1 is free\n"); | |
| if (test_color_conversion) { | |
| // destroy temp surface/image | |
| va_status = vaDestroySurfaces(va_dpy, &csc_render_surface, 1); | |
| CHECK_VASTATUS(va_status,"vaDestroySurfaces"); | |
| va_status = vaDestroyImage(va_dpy, csc_dst_fourcc_image.image_id); | |
| CHECK_VASTATUS(va_status,"vaDestroyImage"); | |
| } | |
| if (vpp_config_id != VA_INVALID_ID) { | |
| vaDestroyConfig (va_dpy, vpp_config_id); | |
| vpp_config_id = VA_INVALID_ID; | |
| } | |
| vaDestroySurfaces(va_dpy,&surface_id[0],SURFACE_NUM); | |
| vaTerminate(va_dpy); | |
| free(va_image_formats); | |
| free(va_surface_attribs); | |
| close_display(win_display); | |
| return 0; | |
| } |