Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  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  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.     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.     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.         }
  470.         else {
  471.             vaStatus = vaPutSurface(va_dpy, surface_id, CAST_DRAWABLE(drawable),
  472.                                     0,0,surface_width,surface_height,
  473.                                     0,0,width,height,
  474.                                     (test_clip==0)?NULL:&cliprects[0],
  475.                                     (test_clip==0)?0:2,
  476.                                     display_field);
  477.             CHECK_VASTATUS(vaStatus,"vaPutSurface");
  478.         }
  479.    
  480.         putsurface_time += (get_tick_count() - start_time);
  481.        
  482.         if (check_event)
  483.             pthread_mutex_unlock(&gmutex);
  484.        
  485.         pthread_mutex_unlock(&surface_mutex[index]); /* locked in get_next_free_surface */
  486.        
  487.         if ((frame_num % 0xff) == 0) {
  488.             fprintf(stderr, "%.2f FPS             \r", 256000.0 / (float)putsurface_time);
  489.             putsurface_time = 0;
  490.             update_clipbox(cliprects, width, height);
  491.         }
  492.        
  493.         if (check_event)
  494.             check_window_event(win_display, drawable, &width, &height, &quit);
  495.  
  496.         if (multi_thread) { /* reload surface content */
  497.             row_shift++;
  498.             if (row_shift==(2*box_width)) row_shift= 0;
  499.         }
  500.        
  501.         if (frame_rate != 0) /* rough framerate control */
  502.             usleep(1000/frame_rate*1000);
  503.  
  504.         frame_num++;
  505.         if (frame_num >= frame_num_total)
  506.             quit = 1;
  507.     }
  508.    
  509.     if (drawable == drawable_thread1)    
  510.         pthread_exit(NULL);
  511.    
  512.     return 0;
  513. }
  514. int main(int argc,char **argv)
  515. {
  516.     int major_ver, minor_ver;
  517.     VAStatus va_status;
  518.     pthread_t thread1;
  519.     int ret;
  520.     char c;
  521.     int i;
  522.     char str_src_fmt[5], str_dst_fmt[5];
  523.  
  524.     static struct option long_options[] =
  525.                  {
  526.                    {"fmt1",  required_argument,       NULL, '1'},
  527.                    {"fmt2",  required_argument,       NULL, '2'},
  528.                    {0, 0, 0, 0}
  529.                  };
  530.  
  531.     while ((c =getopt_long(argc,argv,"w:h:g:r:d:f:tcep?n:1:2:v", long_options, NULL)) != EOF) {
  532.         switch (c) {
  533.             case '?':
  534.                 printf("putsurface <options>\n");
  535.                 printf("           -g <widthxheight+x_location+y_location> window geometry\n");
  536.                 printf("           -w/-h resolution of surface\n");
  537.                 printf("           -r <framerate>\n");
  538.                 printf("           -d the dimension of black/write square box, default is 32\n");
  539.                 printf("           -t multi-threads\n");
  540.                 printf("           -c test clipbox\n");
  541.                 printf("           -f <1/2> top field, or bottom field\n");
  542.                 printf("           -1 source format (fourcc) for color conversion test\n");
  543.                 printf("           -2 dest   format (fourcc) for color conversion test\n");
  544.                 printf("           --fmt1 same to -1\n");
  545.                 printf("           --fmt2 same to -2\n");
  546.                 printf("           -v verbose output\n");
  547.                 exit(0);
  548.                 break;
  549.             case 'g':
  550.                 ret = sscanf(optarg, "%dx%d+%d+%d", &win_width, &win_height, &win_x, &win_y);
  551.                 if (ret != 4) {
  552.                     printf("invalid window geometry, must be widthxheight+x_location+y_location\n");
  553.                     exit(0);
  554.                 } else
  555.                     printf("Create window at (%d, %d), width = %d, height = %d\n",
  556.                            win_x, win_y, win_width, win_height);
  557.                 break;
  558.             case 'r':
  559.                 frame_rate = atoi(optarg);
  560.                 break;
  561.             case 'w':
  562.                 surface_width = atoi(optarg);
  563.                 break;
  564.             case 'h':
  565.                 surface_height = atoi(optarg);
  566.                 break;
  567.             case 'n':
  568.                 frame_num_total = atoi(optarg);
  569.                 break;
  570.             case 'd':
  571.                 box_width = atoi(optarg);
  572.                 break;
  573.             case 't':
  574.                 multi_thread = 1;
  575.                 printf("Two threads to do vaPutSurface\n");
  576.                 break;
  577.             case 'e':
  578.                 check_event = 0;
  579.                 break;
  580.             case 'p':
  581.                 put_pixmap = 1;
  582.                 break;
  583.             case 'c':
  584.                 test_clip = 1;
  585.                 break;
  586.             case 'f':
  587.                 if (atoi(optarg) == 1) {
  588.                     printf("Display TOP field\n");
  589.                     display_field = VA_TOP_FIELD;
  590.                 } else if (atoi(optarg) == 2) {
  591.                     printf("Display BOTTOM field\n");
  592.                     display_field = VA_BOTTOM_FIELD;
  593.                 } else
  594.                     printf("The validate input for -f is: 1(top field)/2(bottom field)\n");
  595.                 break;
  596.             case '1':
  597.                 sscanf(optarg, "%s", str_src_fmt);
  598.                 csc_src_fourcc = map_str_to_vafourcc (str_src_fmt);
  599.                
  600.                                 if (!csc_src_fourcc) {
  601.                     printf("invalid fmt1: %s\n", str_src_fmt );
  602.                     exit(0);
  603.                 }
  604.                 break;
  605.             case '2':
  606.                 sscanf(optarg, "%s", str_dst_fmt);
  607.                 csc_dst_fourcc = map_str_to_vafourcc (str_dst_fmt);
  608.                
  609.                                 if (!csc_dst_fourcc) {
  610.                     printf("invalid fmt1: %s\n", str_dst_fmt );
  611.                     exit(0);
  612.                 }
  613.                 break;
  614.             case 'v':
  615.                 verbose = 1;
  616.                 printf("Enable verbose output\n");
  617.                 break;
  618.         }
  619.     }
  620.  
  621.     if (csc_src_fourcc && csc_dst_fourcc) {
  622.         test_color_conversion = 1;
  623.     }
  624.    
  625.     win_display = (void *)open_display();
  626.     if (win_display == NULL) {
  627.         fprintf(stderr, "Can't open the connection of display!\n");
  628.         exit(-1);
  629.     }
  630.     create_window(win_display, win_x, win_y, win_width, win_height);
  631.  
  632.     va_dpy = vaGetDisplay(win_display);
  633.     va_status = vaInitialize(va_dpy, &major_ver, &minor_ver);
  634.     CHECK_VASTATUS(va_status, "vaInitialize");
  635.  
  636.     if (test_color_conversion) {
  637.         ret = csc_preparation();
  638.     }
  639.     if (!test_color_conversion || !ret ) {
  640.         va_status = vaCreateSurfaces(
  641.             va_dpy,
  642.             VA_RT_FORMAT_YUV420, surface_width, surface_height,
  643.             &surface_id[0], SURFACE_NUM,
  644.             NULL, 0
  645.         );
  646.         }
  647.     CHECK_VASTATUS(va_status, "vaCreateSurfaces");
  648.     if (multi_thread == 0) /* upload the content for all surfaces */
  649.         upload_source_YUV_once_for_all();
  650.    
  651.     if (check_event)
  652.         pthread_mutex_init(&gmutex, NULL);
  653.    
  654.     for(i = 0; i< SURFACE_NUM; i++)
  655.         pthread_mutex_init(&surface_mutex[i], NULL);
  656.    
  657.     if (multi_thread == 1)
  658.         ret = pthread_create(&thread1, NULL, putsurface_thread, (void*)drawable_thread1);
  659.  
  660.     putsurface_thread((void *)drawable_thread0);
  661.  
  662.     if (multi_thread == 1)
  663.         pthread_join(thread1, (void **)&ret);
  664.     printf("thread1 is free\n");
  665.  
  666.     if (test_color_conversion) {
  667.         // destroy temp surface/image
  668.         va_status = vaDestroySurfaces(va_dpy, &csc_render_surface, 1);
  669.         CHECK_VASTATUS(va_status,"vaDestroySurfaces");
  670.        
  671.         va_status = vaDestroyImage(va_dpy, csc_dst_fourcc_image.image_id);
  672.         CHECK_VASTATUS(va_status,"vaDestroyImage");
  673.     }
  674.  
  675.     if (vpp_config_id != VA_INVALID_ID) {
  676.         vaDestroyConfig (va_dpy, vpp_config_id);
  677.         vpp_config_id = VA_INVALID_ID;
  678.     }
  679.  
  680.     vaDestroySurfaces(va_dpy,&surface_id[0],SURFACE_NUM);    
  681.     vaTerminate(va_dpy);
  682.  
  683.     free(va_image_formats);
  684.     free(va_surface_attribs);
  685.     close_display(win_display);
  686.    
  687.     return 0;
  688. }
  689.