OLD | NEW |
(Empty) | |
| 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 <getopt.h> |
| 29 |
| 30 #include <sys/time.h> |
| 31 |
| 32 #include <unistd.h> |
| 33 |
| 34 #include <sys/types.h> |
| 35 #include <sys/stat.h> |
| 36 #include <fcntl.h> |
| 37 #include <assert.h> |
| 38 #include <pthread.h> |
| 39 |
| 40 /*currently, if XCheckWindowEvent was called in more than one thread, it would
cause |
| 41 * XIO: fatal IO error 11 (Resource temporarily unavailable) on X server ":0.0" |
| 42 * after 87 requests (83 known processed) with 0 events remaining. |
| 43 * |
| 44 * X Error of failed request: BadGC (invalid GC parameter) |
| 45 * Major opcode of failed request: 60 (X_FreeGC) |
| 46 * Resource id in failed request: 0x600034 |
| 47 * Serial number of failed request: 398 |
| 48 * Current serial number in output stream: 399 |
| 49 * The root cause is unknown. */ |
| 50 |
| 51 #define CHECK_VASTATUS(va_status,func) \ |
| 52 if (va_status != VA_STATUS_SUCCESS) { \ |
| 53 fprintf(stderr,"%s:%s (%d) failed,exit\n", __func__, func, __LINE__); \ |
| 54 exit(1); \ |
| 55 } |
| 56 #include "../loadsurface.h" |
| 57 |
| 58 #define SURFACE_NUM 16 |
| 59 |
| 60 static void *win_display; |
| 61 static VADisplay va_dpy; |
| 62 static VASurfaceID surface_id[SURFACE_NUM]; |
| 63 static pthread_mutex_t surface_mutex[SURFACE_NUM]; |
| 64 |
| 65 static void *drawable_thread0, *drawable_thread1; |
| 66 static int surface_width = 352, surface_height = 288; |
| 67 static int win_x = 0, win_y = 0; |
| 68 static int win_width = 352, win_height = 288; |
| 69 static int frame_rate = 0; |
| 70 static unsigned long long frame_num_total = ~0; |
| 71 static int check_event = 1; |
| 72 static int put_pixmap = 0; |
| 73 static int test_clip = 0; |
| 74 static int display_field = VA_FRAME_PICTURE; |
| 75 static pthread_mutex_t gmutex; |
| 76 static int box_width = 32; |
| 77 static int multi_thread = 0; |
| 78 static int verbose = 0; |
| 79 |
| 80 static VASurfaceID get_next_free_surface(int *index) |
| 81 { |
| 82 VASurfaceStatus surface_status; |
| 83 int i; |
| 84 |
| 85 assert(index); |
| 86 |
| 87 if (multi_thread == 0) { |
| 88 i = *index; |
| 89 i++; |
| 90 if (i == SURFACE_NUM) |
| 91 i = 0; |
| 92 *index = i; |
| 93 |
| 94 return surface_id[i]; |
| 95 } |
| 96 |
| 97 for (i=0; i<SURFACE_NUM; i++) { |
| 98 surface_status = (VASurfaceStatus)0; |
| 99 vaQuerySurfaceStatus(va_dpy, surface_id[i], &surface_status); |
| 100 if (surface_status == VASurfaceReady) |
| 101 { |
| 102 if (0 == pthread_mutex_trylock(&surface_mutex[i])) |
| 103 { |
| 104 *index = i; |
| 105 break; |
| 106 } |
| 107 } |
| 108 } |
| 109 |
| 110 if (i==SURFACE_NUM) |
| 111 return VA_INVALID_SURFACE; |
| 112 else |
| 113 return surface_id[i]; |
| 114 } |
| 115 |
| 116 static int upload_source_YUV_once_for_all() |
| 117 { |
| 118 VAImage surface_image; |
| 119 void *surface_p=NULL, *U_start,*V_start; |
| 120 VAStatus va_status; |
| 121 int box_width_loc=8; |
| 122 int row_shift_loc=0; |
| 123 int i; |
| 124 |
| 125 for (i=0; i<SURFACE_NUM; i++) { |
| 126 printf("\rLoading data into surface %d.....", i); |
| 127 upload_surface(va_dpy, surface_id[i], box_width_loc, row_shift_loc, 0); |
| 128 |
| 129 row_shift_loc++; |
| 130 if (row_shift_loc==(2*box_width_loc)) row_shift_loc= 0; |
| 131 } |
| 132 printf("\n"); |
| 133 |
| 134 return 0; |
| 135 } |
| 136 |
| 137 /* |
| 138 * Helper function for profiling purposes |
| 139 */ |
| 140 static unsigned long get_tick_count(void) |
| 141 { |
| 142 struct timeval tv; |
| 143 if (gettimeofday(&tv, NULL)) |
| 144 return 0; |
| 145 return tv.tv_usec/1000+tv.tv_sec*1000; |
| 146 } |
| 147 |
| 148 static void update_clipbox(VARectangle *cliprects, int width, int height) |
| 149 { |
| 150 if (test_clip == 0) |
| 151 return; |
| 152 |
| 153 srand((unsigned)time(NULL)); |
| 154 |
| 155 cliprects[0].x = (rand() % width); |
| 156 cliprects[0].y = (rand() % height); |
| 157 cliprects[0].width = (rand() % (width - cliprects[0].x)); |
| 158 cliprects[0].height = (rand() % (height - cliprects[0].y)); |
| 159 |
| 160 cliprects[1].x = (rand() % width); |
| 161 cliprects[1].y = (rand() % height); |
| 162 cliprects[1].width = (rand() % (width - cliprects[1].x)); |
| 163 cliprects[1].height = (rand() % (height - cliprects[1].y)); |
| 164 printf("\nTest clip (%d,%d, %d x %d) and (%d,%d, %d x %d) \n", |
| 165 cliprects[0].x, cliprects[0].y, cliprects[0].width, cliprects[0].heig
ht, |
| 166 cliprects[1].x, cliprects[1].y, cliprects[1].width, cliprects[1].heig
ht); |
| 167 } |
| 168 |
| 169 static void* putsurface_thread(void *data) |
| 170 { |
| 171 int width=win_width, height=win_height; |
| 172 void *drawable = data; |
| 173 int quit = 0; |
| 174 VAStatus vaStatus; |
| 175 int row_shift = 0; |
| 176 int index = 0; |
| 177 unsigned int frame_num=0, start_time, putsurface_time; |
| 178 VARectangle cliprects[2]; /* client supplied clip list */ |
| 179 int continue_display = 0; |
| 180 |
| 181 if (drawable == drawable_thread0) |
| 182 printf("Enter into thread0\n\n"); |
| 183 if (drawable == drawable_thread1) |
| 184 printf("Enter into thread1\n\n"); |
| 185 |
| 186 putsurface_time = 0; |
| 187 while (!quit) { |
| 188 VASurfaceID surface_id = VA_INVALID_SURFACE; |
| 189 |
| 190 while (surface_id == VA_INVALID_SURFACE) |
| 191 surface_id = get_next_free_surface(&index); |
| 192 |
| 193 if (verbose) printf("Thread %x Display surface 0x%p,\n", (unsigned int)d
rawable, (void *)surface_id); |
| 194 |
| 195 if (multi_thread) |
| 196 upload_surface(va_dpy, surface_id, box_width, row_shift, display_fie
ld); |
| 197 |
| 198 if (check_event) |
| 199 pthread_mutex_lock(&gmutex); |
| 200 |
| 201 start_time = get_tick_count(); |
| 202 if ((continue_display == 0) && getenv("FRAME_STOP")) { |
| 203 char c; |
| 204 printf("Press any key to display frame %d...(c/C to continue)\n", fr
ame_num); |
| 205 c = getchar(); |
| 206 if (c == 'c' || c == 'C') |
| 207 continue_display = 1; |
| 208 } |
| 209 vaStatus = vaPutSurface(va_dpy, surface_id, CAST_DRAWABLE(drawable), |
| 210 0,0,surface_width,surface_height, |
| 211 0,0,width,height, |
| 212 (test_clip==0)?NULL:&cliprects[0], |
| 213 (test_clip==0)?0:2, |
| 214 display_field); |
| 215 CHECK_VASTATUS(vaStatus,"vaPutSurface"); |
| 216 putsurface_time += (get_tick_count() - start_time); |
| 217 |
| 218 if (check_event) |
| 219 pthread_mutex_unlock(&gmutex); |
| 220 |
| 221 pthread_mutex_unlock(&surface_mutex[index]); /* locked in get_next_free_
surface */ |
| 222 |
| 223 if ((frame_num % 0xff) == 0) { |
| 224 fprintf(stderr, "%.2f FPS \r", 256000.0 / (float)putsurf
ace_time); |
| 225 putsurface_time = 0; |
| 226 update_clipbox(cliprects, width, height); |
| 227 } |
| 228 |
| 229 if (check_event) |
| 230 check_window_event(win_display, drawable, &width, &height, &quit); |
| 231 |
| 232 if (multi_thread) { /* reload surface content */ |
| 233 row_shift++; |
| 234 if (row_shift==(2*box_width)) row_shift= 0; |
| 235 } |
| 236 |
| 237 if (frame_rate != 0) /* rough framerate control */ |
| 238 usleep(1000/frame_rate*1000); |
| 239 |
| 240 frame_num++; |
| 241 if (frame_num >= frame_num_total) |
| 242 quit = 1; |
| 243 } |
| 244 |
| 245 if (drawable == drawable_thread1) |
| 246 pthread_exit(NULL); |
| 247 |
| 248 return 0; |
| 249 } |
| 250 |
| 251 |
| 252 int main(int argc,char **argv) |
| 253 { |
| 254 int major_ver, minor_ver; |
| 255 VAStatus va_status; |
| 256 pthread_t thread1; |
| 257 int ret; |
| 258 char c; |
| 259 int i; |
| 260 |
| 261 while ((c =getopt(argc,argv,"w:h:g:r:d:f:tcep?n:v") ) != EOF) { |
| 262 switch (c) { |
| 263 case '?': |
| 264 printf("putsurface <options>\n"); |
| 265 printf(" -g <widthxheight+x_location+y_location> windo
w geometry\n"); |
| 266 printf(" -w/-h resolution of surface\n"); |
| 267 printf(" -r <framerate>\n"); |
| 268 printf(" -d the dimension of black/write square box, d
efault is 32\n"); |
| 269 printf(" -t multi-threads\n"); |
| 270 printf(" -c test clipbox\n"); |
| 271 printf(" -f <1/2> top field, or bottom field\n"); |
| 272 printf(" -v verbose output\n"); |
| 273 exit(0); |
| 274 break; |
| 275 case 'g': |
| 276 ret = sscanf(optarg, "%dx%d+%d+%d", &win_width, &win_height, &wi
n_x, &win_y); |
| 277 if (ret != 4) { |
| 278 printf("invalid window geometry, must be widthxheight+x_loca
tion+y_location\n"); |
| 279 exit(0); |
| 280 } else |
| 281 printf("Create window at (%d, %d), width = %d, height = %d\n
", |
| 282 win_x, win_y, win_width, win_height); |
| 283 break; |
| 284 case 'r': |
| 285 frame_rate = atoi(optarg); |
| 286 break; |
| 287 case 'w': |
| 288 surface_width = atoi(optarg); |
| 289 break; |
| 290 case 'h': |
| 291 surface_height = atoi(optarg); |
| 292 break; |
| 293 case 'n': |
| 294 frame_num_total = atoi(optarg); |
| 295 break; |
| 296 case 'd': |
| 297 box_width = atoi(optarg); |
| 298 break; |
| 299 case 't': |
| 300 multi_thread = 1; |
| 301 printf("Two threads to do vaPutSurface\n"); |
| 302 break; |
| 303 case 'e': |
| 304 check_event = 0; |
| 305 break; |
| 306 case 'p': |
| 307 put_pixmap = 1; |
| 308 break; |
| 309 case 'c': |
| 310 test_clip = 1; |
| 311 break; |
| 312 case 'f': |
| 313 if (atoi(optarg) == 1) { |
| 314 printf("Display TOP field\n"); |
| 315 display_field = VA_TOP_FIELD; |
| 316 } else if (atoi(optarg) == 2) { |
| 317 printf("Display BOTTOM field\n"); |
| 318 display_field = VA_BOTTOM_FIELD; |
| 319 } else |
| 320 printf("The validate input for -f is: 1(top field)/2(bottom
field)\n"); |
| 321 break; |
| 322 case 'v': |
| 323 verbose = 1; |
| 324 printf("Enable verbose output\n"); |
| 325 break; |
| 326 } |
| 327 } |
| 328 |
| 329 win_display = (void *)open_display(); |
| 330 if (win_display == NULL) { |
| 331 fprintf(stderr, "Can't open the connection of display!\n"); |
| 332 exit(-1); |
| 333 } |
| 334 create_window(win_display, win_x, win_y, win_width, win_height); |
| 335 |
| 336 va_dpy = vaGetDisplay(win_display); |
| 337 va_status = vaInitialize(va_dpy, &major_ver, &minor_ver); |
| 338 CHECK_VASTATUS(va_status, "vaInitialize"); |
| 339 |
| 340 va_status = vaCreateSurfaces(va_dpy,surface_width, surface_height, |
| 341 VA_RT_FORMAT_YUV420, SURFACE_NUM, &surface_id[0]
); |
| 342 CHECK_VASTATUS(va_status, "vaCreateSurfaces"); |
| 343 if (multi_thread == 0) /* upload the content for all surfaces */ |
| 344 upload_source_YUV_once_for_all(); |
| 345 |
| 346 if (check_event) |
| 347 pthread_mutex_init(&gmutex, NULL); |
| 348 |
| 349 for(i = 0; i< SURFACE_NUM; i++) |
| 350 pthread_mutex_init(&surface_mutex[i], NULL); |
| 351 |
| 352 if (multi_thread == 1) |
| 353 ret = pthread_create(&thread1, NULL, putsurface_thread, (void*)drawable_
thread1); |
| 354 |
| 355 putsurface_thread((void *)drawable_thread0); |
| 356 |
| 357 if (multi_thread == 1) |
| 358 pthread_join(thread1, (void **)&ret); |
| 359 printf("thread1 is free\n"); |
| 360 |
| 361 vaDestroySurfaces(va_dpy,&surface_id[0],SURFACE_NUM); |
| 362 vaTerminate(va_dpy); |
| 363 |
| 364 close_display(win_display); |
| 365 |
| 366 return 0; |
| 367 } |
OLD | NEW |