Home | History | Annotate | Download | only in putsurface
      1 /*
      2  * Copyright (c) 2008-2009 Intel Corporation. All Rights Reserved.
      3  *
      4  * Permission is hereby granted, free of charge, to any person obtaining a
      5  * copy of this software and associated documentation files (the
      6  * "Software"), to deal in the Software without restriction, including
      7  * without limitation the rights to use, copy, modify, merge, publish,
      8  * distribute, sub license, and/or sell copies of the Software, and to
      9  * permit persons to whom the Software is furnished to do so, subject to
     10  * the following conditions:
     11  *
     12  * The above copyright notice and this permission notice (including the
     13  * next paragraph) shall be included in all copies or substantial portions
     14  * of the Software.
     15  *
     16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
     17  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
     18  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
     19  * IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
     20  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
     21  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
     22  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
     23  */
     24 
     25 #include <stdio.h>
     26 #include <string.h>
     27 #include <stdlib.h>
     28 #include <stdint.h>
     29 #include <getopt.h>
     30 
     31 #include <sys/time.h>
     32 
     33 #include <unistd.h>
     34 
     35 #include <sys/types.h>
     36 #include <sys/stat.h>
     37 #include <fcntl.h>
     38 #include <assert.h>
     39 #include <pthread.h>
     40 
     41 /*currently, if XCheckWindowEvent was called  in more than one thread, it would cause
     42  * XIO:  fatal IO error 11 (Resource temporarily unavailable) on X server ":0.0"
     43  *       after 87 requests (83 known processed) with 0 events remaining.
     44  *
     45  *       X Error of failed request:  BadGC (invalid GC parameter)
     46  *       Major opcode of failed request:  60 (X_FreeGC)
     47  *       Resource id in failed request:  0x600034
     48  *       Serial number of failed request:  398
     49  *       Current serial number in output stream:  399
     50  * The root cause is unknown. */
     51 
     52 #define CHECK_VASTATUS(va_status,func)                                  \
     53 if (va_status != VA_STATUS_SUCCESS) {                                   \
     54     fprintf(stderr,"%s:%s (%d) failed,exit\n", __func__, func, __LINE__); \
     55     exit(1);                                                            \
     56 }
     57 #include "../loadsurface.h"
     58 
     59 #define SURFACE_NUM 16
     60 
     61 static  void *win_display;
     62 static  VADisplay va_dpy;
     63 static  VAImageFormat *va_image_formats;
     64 static  int va_num_image_formats = -1;
     65 static  VAConfigID vpp_config_id = VA_INVALID_ID;
     66 static  VASurfaceAttrib *va_surface_attribs;
     67 static  int va_num_surface_attribs = -1;
     68 static  VASurfaceID surface_id[SURFACE_NUM];
     69 static  pthread_mutex_t surface_mutex[SURFACE_NUM];
     70 
     71 static  void *drawable_thread0, *drawable_thread1;
     72 static  int surface_width = 352, surface_height = 288;
     73 static  int win_x = 0, win_y = 0;
     74 static  int win_width = 352, win_height = 288;
     75 static  int frame_rate = 0;
     76 static  unsigned long long frame_num_total = ~0;
     77 static  int check_event = 1;
     78 static  int put_pixmap = 0;
     79 static  int test_clip = 0;
     80 static  int display_field = VA_FRAME_PICTURE;
     81 static  pthread_mutex_t gmutex;
     82 static  int box_width = 32;
     83 static  int multi_thread = 0;
     84 static  int verbose = 0;
     85 static  int test_color_conversion = 0;
     86 static  unsigned int csc_src_fourcc = 0, csc_dst_fourcc = 0;
     87 static  VAImage csc_dst_fourcc_image;
     88 static  VASurfaceID csc_render_surface;
     89 
     90 
     91 typedef struct {
     92     char * fmt_str;
     93     unsigned int fourcc;
     94 } fourcc_map;
     95 fourcc_map va_fourcc_map[] = {
     96     {"YUYV", VA_FOURCC_YUY2},
     97     {"YUY2", VA_FOURCC_YUY2},
     98     {"NV12", VA_FOURCC_NV12},
     99     {"YV12", VA_FOURCC_YV12},
    100     {"BGRA", VA_FOURCC_BGRA},
    101     {"RGBA", VA_FOURCC_RGBA},
    102     {"BGRX", VA_FOURCC_BGRX},
    103     {"RGBX", VA_FOURCC_RGBX},
    104 };
    105 unsigned int map_str_to_vafourcc (char * str)
    106 {
    107     unsigned int i;
    108     for (i=0; i< sizeof(va_fourcc_map)/sizeof(fourcc_map); i++) {
    109         if (!strcmp(va_fourcc_map[i].fmt_str, str)) {
    110             return va_fourcc_map[i].fourcc;
    111         }
    112     }
    113 
    114     return 0;
    115 
    116 }
    117 char* map_vafourcc_to_str (unsigned int format)
    118 {
    119     static char unknown_format[] = "unknown-format";
    120     unsigned int i;
    121     for (i=0; i< sizeof(va_fourcc_map)/sizeof(fourcc_map); i++) {
    122         if (va_fourcc_map[i].fourcc == format) {
    123             return va_fourcc_map[i].fmt_str;
    124         }
    125     }
    126 
    127     return unknown_format;
    128 
    129 }
    130 
    131 static int
    132 va_value_equals(const VAGenericValue *v1, const VAGenericValue *v2)
    133 {
    134     if (v1->type != v2->type)
    135         return 0;
    136 
    137     switch (v1->type) {
    138     case VAGenericValueTypeInteger:
    139         return v1->value.i == v2->value.i;
    140     case VAGenericValueTypeFloat:
    141         return v1->value.f == v2->value.f;
    142     case VAGenericValueTypePointer:
    143         return v1->value.p == v2->value.p;
    144     case VAGenericValueTypeFunc:
    145         return v1->value.fn == v2->value.fn;
    146     }
    147     return 0;
    148 }
    149 
    150 static int
    151 ensure_image_formats(void)
    152 {
    153     VAStatus va_status;
    154     VAImageFormat *image_formats;
    155     int num_image_formats;
    156 
    157     if (va_num_image_formats >= 0)
    158         return va_num_image_formats;
    159 
    160     num_image_formats = vaMaxNumImageFormats(va_dpy);
    161     if (num_image_formats == 0)
    162         return 0;
    163 
    164     image_formats = malloc(num_image_formats * sizeof(*image_formats));
    165     if (!image_formats)
    166         return 0;
    167 
    168     va_status = vaQueryImageFormats(va_dpy, image_formats, &num_image_formats);
    169     CHECK_VASTATUS(va_status, "vaQuerySurfaceAttributes()");
    170 
    171     va_image_formats = image_formats;
    172     va_num_image_formats = num_image_formats;
    173     return num_image_formats;
    174 }
    175 
    176 static const VAImageFormat *
    177 lookup_image_format(uint32_t fourcc)
    178 {
    179     int i;
    180 
    181     if (!ensure_image_formats())
    182         return NULL;
    183 
    184     for (i = 0; i < va_num_image_formats; i++) {
    185         const VAImageFormat * const image_format = &va_image_formats[i];
    186         if (image_format->fourcc == fourcc)
    187             return image_format;
    188     }
    189     return NULL;
    190 }
    191 
    192 static int
    193 ensure_surface_attribs(void)
    194 {
    195     VAStatus va_status;
    196     VASurfaceAttrib *surface_attribs;
    197     unsigned int num_image_formats, num_surface_attribs;
    198 
    199     if (va_num_surface_attribs >= 0)
    200         return va_num_surface_attribs;
    201 
    202     num_image_formats = vaMaxNumImageFormats(va_dpy);
    203     if (num_image_formats == 0)
    204         return 0;
    205 
    206     va_status = vaCreateConfig(va_dpy, VAProfileNone, VAEntrypointVideoProc,
    207         NULL, 0, &vpp_config_id);
    208     CHECK_VASTATUS(va_status, "vaCreateConfig()");
    209 
    210     /* Guess the number of surface attributes, thus including any
    211        pixel-format supported by the VA driver */
    212     num_surface_attribs = VASurfaceAttribCount + num_image_formats;
    213     surface_attribs = malloc(num_surface_attribs * sizeof(*surface_attribs));
    214     if (!surface_attribs)
    215         return 0;
    216 
    217     va_status = vaQuerySurfaceAttributes(va_dpy, vpp_config_id,
    218         surface_attribs, &num_surface_attribs);
    219     if (va_status == VA_STATUS_SUCCESS)
    220         va_surface_attribs =  surface_attribs;
    221     else if (va_status == VA_STATUS_ERROR_MAX_NUM_EXCEEDED) {
    222         va_surface_attribs = realloc(surface_attribs,
    223             num_surface_attribs * sizeof(*va_surface_attribs));
    224         if (!va_surface_attribs) {
    225             free(surface_attribs);
    226             return 0;
    227         }
    228         va_status = vaQuerySurfaceAttributes(va_dpy, vpp_config_id,
    229             va_surface_attribs, &num_surface_attribs);
    230     }
    231     CHECK_VASTATUS(va_status, "vaQuerySurfaceAttributes()");
    232     va_num_surface_attribs = num_surface_attribs;
    233     return num_surface_attribs;
    234 }
    235 
    236 static const VASurfaceAttrib *
    237 lookup_surface_attrib(VASurfaceAttribType type, const VAGenericValue *value)
    238 {
    239     int i;
    240 
    241     if (!ensure_surface_attribs())
    242         return NULL;
    243 
    244     for (i = 0; i < va_num_surface_attribs; i++) {
    245         const VASurfaceAttrib * const surface_attrib = &va_surface_attribs[i];
    246         if (surface_attrib->type != type)
    247             continue;
    248         if (!(surface_attrib->flags & VA_SURFACE_ATTRIB_SETTABLE))
    249             continue;
    250         if (va_value_equals(&surface_attrib->value, value))
    251             return surface_attrib;
    252     }
    253     return NULL;
    254 }
    255 
    256 int csc_preparation ()
    257 {
    258     VAStatus va_status;
    259 
    260     // 1. make sure dst fourcc is supported for vaImage
    261     if (!lookup_image_format(csc_dst_fourcc)) {
    262         test_color_conversion = 0;
    263         printf("VA driver doesn't support %s image, skip additional color conversion\n",  map_vafourcc_to_str(csc_dst_fourcc));
    264         goto cleanup;
    265     }
    266 
    267     // 2. make sure src_fourcc is supported for vaSurface
    268     VASurfaceAttrib surface_attribs[1], * const s_attrib = &surface_attribs[0];
    269     s_attrib->type = VASurfaceAttribPixelFormat;
    270     s_attrib->flags = VA_SURFACE_ATTRIB_SETTABLE;
    271     s_attrib->value.type = VAGenericValueTypeInteger;
    272     s_attrib->value.value.i = csc_src_fourcc;
    273 
    274     if (!lookup_surface_attrib(VASurfaceAttribPixelFormat, &s_attrib->value)) {
    275         printf("VA driver doesn't support %s surface, skip additional color conversion\n",  map_vafourcc_to_str(csc_src_fourcc));
    276         test_color_conversion = 0;
    277         goto cleanup;
    278     }
    279 
    280     // 3 create all objs required by csc
    281     // 3.1 vaSurface with src fourcc
    282     va_status = vaCreateSurfaces(
    283         va_dpy,
    284         VA_RT_FORMAT_YUV420, surface_width, surface_height,
    285         &surface_id[0], SURFACE_NUM,
    286         surface_attribs, 1
    287     );
    288     CHECK_VASTATUS(va_status,"vaCreateSurfaces");
    289 
    290     // 3.2 vaImage with dst fourcc
    291     VAImageFormat image_format;
    292     image_format.fourcc = csc_dst_fourcc;
    293     image_format.byte_order = VA_LSB_FIRST;
    294     image_format.bits_per_pixel = 16;
    295 
    296     va_status = vaCreateImage(va_dpy, &image_format,
    297                     surface_width, surface_height,
    298                     &csc_dst_fourcc_image);
    299     CHECK_VASTATUS(va_status,"vaCreateImage");
    300 
    301 
    302     // 3.3 create a temp VASurface for final rendering(vaPutSurface)
    303     s_attrib->value.value.i = VA_FOURCC_NV12;
    304     va_status = vaCreateSurfaces(va_dpy, VA_RT_FORMAT_YUV420,
    305                                  surface_width, surface_height,
    306                                  &csc_render_surface, 1,
    307                                  surface_attribs, 1);
    308     CHECK_VASTATUS(va_status,"vaCreateSurfaces");
    309 
    310 
    311 cleanup:
    312     return test_color_conversion;
    313 }
    314 
    315 static VASurfaceID get_next_free_surface(int *index)
    316 {
    317     VASurfaceStatus surface_status;
    318     int i;
    319 
    320     assert(index);
    321 
    322     if (multi_thread == 0) {
    323         i = *index;
    324         i++;
    325         if (i == SURFACE_NUM)
    326             i = 0;
    327         *index = i;
    328 
    329         return surface_id[i];
    330     }
    331 
    332     for (i=0; i<SURFACE_NUM; i++) {
    333         surface_status = (VASurfaceStatus)0;
    334         vaQuerySurfaceStatus(va_dpy, surface_id[i], &surface_status);
    335         if (surface_status == VASurfaceReady)
    336         {
    337             if (0 == pthread_mutex_trylock(&surface_mutex[i]))
    338             {
    339                 *index = i;
    340                 break;
    341             }
    342         }
    343     }
    344 
    345     if (i==SURFACE_NUM)
    346         return VA_INVALID_SURFACE;
    347     else
    348         return surface_id[i];
    349 }
    350 
    351 static int upload_source_YUV_once_for_all()
    352 {
    353     VAImage surface_image;
    354     void *surface_p=NULL, *U_start,*V_start;
    355     VAStatus va_status;
    356     int box_width_loc=8;
    357     int row_shift_loc=0;
    358     int i;
    359 
    360     for (i=0; i<SURFACE_NUM; i++) {
    361         printf("\rLoading data into surface %d.....", i);
    362         upload_surface(va_dpy, surface_id[i], box_width_loc, row_shift_loc, 0);
    363 
    364         row_shift_loc++;
    365         if (row_shift_loc==(2*box_width_loc)) row_shift_loc= 0;
    366     }
    367     printf("\n");
    368 
    369     return 0;
    370 }
    371 
    372 /*
    373  * Helper function for profiling purposes
    374  */
    375 static unsigned long get_tick_count(void)
    376 {
    377     struct timeval tv;
    378     if (gettimeofday(&tv, NULL))
    379         return 0;
    380     return tv.tv_usec/1000+tv.tv_sec*1000;
    381 }
    382 
    383 static void update_clipbox(VARectangle *cliprects, int width, int height)
    384 {
    385     if (test_clip == 0)
    386         return;
    387 
    388     srand((unsigned)time(NULL));
    389 
    390     cliprects[0].x = (rand() % width);
    391     cliprects[0].y = (rand() % height);
    392     cliprects[0].width = (rand() % (width - cliprects[0].x));
    393     cliprects[0].height = (rand() % (height - cliprects[0].y));
    394 
    395     cliprects[1].x = (rand() % width);
    396     cliprects[1].y = (rand() % height);
    397     cliprects[1].width = (rand() % (width - cliprects[1].x));
    398     cliprects[1].height = (rand() % (height - cliprects[1].y));
    399     printf("\nTest clip (%d,%d, %d x %d) and (%d,%d, %d x %d) \n",
    400            cliprects[0].x, cliprects[0].y, cliprects[0].width, cliprects[0].height,
    401            cliprects[1].x, cliprects[1].y, cliprects[1].width, cliprects[1].height);
    402 }
    403 
    404 static void* putsurface_thread(void *data)
    405 {
    406     int width=win_width, height=win_height;
    407     void *drawable = data;
    408     int quit = 0;
    409     VAStatus vaStatus;
    410     int row_shift = 0;
    411     int index = 0;
    412     unsigned int frame_num=0, start_time, putsurface_time;
    413     VARectangle cliprects[2]; /* client supplied clip list */
    414     int continue_display = 0;
    415 
    416     if (drawable == drawable_thread0)
    417         printf("Enter into thread0\n\n");
    418     if (drawable == drawable_thread1)
    419         printf("Enter into thread1\n\n");
    420 
    421     putsurface_time = 0;
    422     while (!quit) {
    423         VASurfaceID surface_id = VA_INVALID_SURFACE;
    424 
    425         while (surface_id == VA_INVALID_SURFACE)
    426             surface_id = get_next_free_surface(&index);
    427 
    428         if (verbose) printf("Thread: %p Display surface 0x%x,\n", drawable, surface_id);
    429 
    430         if (multi_thread)
    431             upload_surface(va_dpy, surface_id, box_width, row_shift, display_field);
    432 
    433         if (check_event)
    434             pthread_mutex_lock(&gmutex);
    435 
    436         start_time = get_tick_count();
    437 	if ((continue_display == 0) && getenv("FRAME_STOP")) {
    438             char c;
    439             printf("Press any key to display frame %d...(c/C to continue)\n", frame_num);
    440             c = getchar();
    441             if (c == 'c' || c == 'C')
    442                 continue_display = 1;
    443         }
    444         if (test_color_conversion) {
    445             static int _put_surface_count = 0;
    446             if (_put_surface_count++ %50 == 0) {
    447                 printf("do additional colorcoversion from %s to %s\n", map_vafourcc_to_str(csc_src_fourcc), map_vafourcc_to_str(csc_dst_fourcc));
    448             }
    449             // get image from surface, csc_src_fourcc to csc_dst_fourcc conversion happens
    450             vaStatus = vaGetImage(va_dpy, surface_id, 0, 0,
    451                 surface_width, surface_height, csc_dst_fourcc_image.image_id);
    452             CHECK_VASTATUS(vaStatus,"vaGetImage");
    453 
    454             // render csc_dst_fourcc image to temp surface
    455             vaStatus = vaPutImage(va_dpy, csc_render_surface, csc_dst_fourcc_image.image_id,
    456                                     0, 0, surface_width, surface_height,
    457                                     0, 0, surface_width, surface_height);
    458             CHECK_VASTATUS(vaStatus,"vaPutImage");
    459 
    460             // render the temp surface, it should be same with original surface without color conversion test
    461             vaStatus = vaPutSurface(va_dpy, csc_render_surface, CAST_DRAWABLE(drawable),
    462                                     0,0,surface_width,surface_height,
    463                                     0,0,width,height,
    464                                     (test_clip==0)?NULL:&cliprects[0],
    465                                     (test_clip==0)?0:2,
    466                                     display_field);
    467             CHECK_VASTATUS(vaStatus,"vaPutSurface");
    468         }
    469         else {
    470             vaStatus = vaPutSurface(va_dpy, surface_id, CAST_DRAWABLE(drawable),
    471                                     0,0,surface_width,surface_height,
    472                                     0,0,width,height,
    473                                     (test_clip==0)?NULL:&cliprects[0],
    474                                     (test_clip==0)?0:2,
    475                                     display_field);
    476             CHECK_VASTATUS(vaStatus,"vaPutSurface");
    477         }
    478 
    479         putsurface_time += (get_tick_count() - start_time);
    480 
    481         if (check_event)
    482             pthread_mutex_unlock(&gmutex);
    483 
    484         pthread_mutex_unlock(&surface_mutex[index]); /* locked in get_next_free_surface */
    485 
    486         if ((frame_num % 0xff) == 0) {
    487             fprintf(stderr, "%.2f FPS             \r", 256000.0 / (float)putsurface_time);
    488             putsurface_time = 0;
    489             update_clipbox(cliprects, width, height);
    490         }
    491 
    492         if (check_event)
    493             check_window_event(win_display, drawable, &width, &height, &quit);
    494 
    495         if (multi_thread) { /* reload surface content */
    496             row_shift++;
    497             if (row_shift==(2*box_width)) row_shift= 0;
    498         }
    499 
    500         if (frame_rate != 0) /* rough framerate control */
    501             usleep(1000/frame_rate*1000);
    502 
    503         frame_num++;
    504         if (frame_num >= frame_num_total)
    505             quit = 1;
    506     }
    507 
    508     if (drawable == drawable_thread1)
    509         pthread_exit(NULL);
    510 
    511     return 0;
    512 }
    513 int main(int argc,char **argv)
    514 {
    515     int major_ver, minor_ver;
    516     VAStatus va_status;
    517     pthread_t thread1;
    518     int ret;
    519     char c;
    520     int i;
    521     char str_src_fmt[5], str_dst_fmt[5];
    522 
    523     static struct option long_options[] =
    524                  {
    525                    {"fmt1",  required_argument,       NULL, '1'},
    526                    {"fmt2",  required_argument,       NULL, '2'},
    527                    {0, 0, 0, 0}
    528                  };
    529 
    530     while ((c =getopt_long(argc,argv,"w:h:g:r:d:f:tcep?n:1:2:v", long_options, NULL)) != EOF) {
    531         switch (c) {
    532             case '?':
    533                 printf("putsurface <options>\n");
    534                 printf("           -g <widthxheight+x_location+y_location> window geometry\n");
    535                 printf("           -w/-h resolution of surface\n");
    536                 printf("           -r <framerate>\n");
    537                 printf("           -d the dimension of black/write square box, default is 32\n");
    538                 printf("           -t multi-threads\n");
    539                 printf("           -c test clipbox\n");
    540                 printf("           -f <1/2> top field, or bottom field\n");
    541                 printf("           -1 source format (fourcc) for color conversion test\n");
    542                 printf("           -2 dest   format (fourcc) for color conversion test\n");
    543                 printf("           --fmt1 same to -1\n");
    544                 printf("           --fmt2 same to -2\n");
    545                 printf("           -v verbose output\n");
    546                 exit(0);
    547                 break;
    548             case 'g':
    549                 ret = sscanf(optarg, "%dx%d+%d+%d", &win_width, &win_height, &win_x, &win_y);
    550                 if (ret != 4) {
    551                     printf("invalid window geometry, must be widthxheight+x_location+y_location\n");
    552                     exit(0);
    553                 } else
    554                     printf("Create window at (%d, %d), width = %d, height = %d\n",
    555                            win_x, win_y, win_width, win_height);
    556                 break;
    557             case 'r':
    558                 frame_rate = atoi(optarg);
    559                 break;
    560             case 'w':
    561                 surface_width = atoi(optarg);
    562                 break;
    563             case 'h':
    564                 surface_height = atoi(optarg);
    565                 break;
    566             case 'n':
    567                 frame_num_total = atoi(optarg);
    568                 break;
    569             case 'd':
    570                 box_width = atoi(optarg);
    571                 break;
    572             case 't':
    573                 multi_thread = 1;
    574                 printf("Two threads to do vaPutSurface\n");
    575                 break;
    576             case 'e':
    577                 check_event = 0;
    578                 break;
    579             case 'p':
    580                 put_pixmap = 1;
    581                 break;
    582             case 'c':
    583                 test_clip = 1;
    584                 break;
    585             case 'f':
    586                 if (atoi(optarg) == 1) {
    587                     printf("Display TOP field\n");
    588                     display_field = VA_TOP_FIELD;
    589                 } else if (atoi(optarg) == 2) {
    590                     printf("Display BOTTOM field\n");
    591                     display_field = VA_BOTTOM_FIELD;
    592                 } else
    593                     printf("The validate input for -f is: 1(top field)/2(bottom field)\n");
    594                 break;
    595             case '1':
    596                 sscanf(optarg, "%s", str_src_fmt);
    597                 csc_src_fourcc = map_str_to_vafourcc (str_src_fmt);
    598 
    599 				if (!csc_src_fourcc) {
    600                     printf("invalid fmt1: %s\n", str_src_fmt );
    601                     exit(0);
    602                 }
    603                 break;
    604             case '2':
    605                 sscanf(optarg, "%s", str_dst_fmt);
    606                 csc_dst_fourcc = map_str_to_vafourcc (str_dst_fmt);
    607 
    608 				if (!csc_dst_fourcc) {
    609                     printf("invalid fmt1: %s\n", str_dst_fmt );
    610                     exit(0);
    611                 }
    612                 break;
    613             case 'v':
    614                 verbose = 1;
    615                 printf("Enable verbose output\n");
    616                 break;
    617         }
    618     }
    619 
    620     if (csc_src_fourcc && csc_dst_fourcc) {
    621         test_color_conversion = 1;
    622     }
    623 
    624     win_display = (void *)open_display();
    625     if (win_display == NULL) {
    626         fprintf(stderr, "Can't open the connection of display!\n");
    627         exit(-1);
    628     }
    629     create_window(win_display, win_x, win_y, win_width, win_height);
    630 
    631     va_dpy = vaGetDisplay(win_display);
    632     va_status = vaInitialize(va_dpy, &major_ver, &minor_ver);
    633     CHECK_VASTATUS(va_status, "vaInitialize");
    634 
    635     if (test_color_conversion) {
    636         ret = csc_preparation();
    637     }
    638     if (!test_color_conversion || !ret ) {
    639         va_status = vaCreateSurfaces(
    640             va_dpy,
    641             VA_RT_FORMAT_YUV420, surface_width, surface_height,
    642             &surface_id[0], SURFACE_NUM,
    643             NULL, 0
    644         );
    645 	}
    646     CHECK_VASTATUS(va_status, "vaCreateSurfaces");
    647     if (multi_thread == 0) /* upload the content for all surfaces */
    648         upload_source_YUV_once_for_all();
    649 
    650     if (check_event)
    651         pthread_mutex_init(&gmutex, NULL);
    652 
    653     for(i = 0; i< SURFACE_NUM; i++)
    654         pthread_mutex_init(&surface_mutex[i], NULL);
    655 
    656     if (multi_thread == 1)
    657         ret = pthread_create(&thread1, NULL, putsurface_thread, (void*)drawable_thread1);
    658 
    659     putsurface_thread((void *)drawable_thread0);
    660 
    661     if (multi_thread == 1)
    662         pthread_join(thread1, (void **)&ret);
    663     printf("thread1 is free\n");
    664 
    665     if (test_color_conversion) {
    666         // destroy temp surface/image
    667         va_status = vaDestroySurfaces(va_dpy, &csc_render_surface, 1);
    668         CHECK_VASTATUS(va_status,"vaDestroySurfaces");
    669 
    670         va_status = vaDestroyImage(va_dpy, csc_dst_fourcc_image.image_id);
    671         CHECK_VASTATUS(va_status,"vaDestroyImage");
    672     }
    673 
    674     if (vpp_config_id != VA_INVALID_ID) {
    675         vaDestroyConfig (va_dpy, vpp_config_id);
    676         vpp_config_id = VA_INVALID_ID;
    677     }
    678 
    679     vaDestroySurfaces(va_dpy,&surface_id[0],SURFACE_NUM);
    680     vaTerminate(va_dpy);
    681 
    682     free(va_image_formats);
    683     free(va_surface_attribs);
    684     close_display(win_display);
    685 
    686     return 0;
    687 }
    688