OLD | NEW |
(Empty) | |
| 1 /* |
| 2 * Copyright (c) 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 #define _GNU_SOURCE 1 |
| 26 #include "va.h" |
| 27 #include "va_backend.h" |
| 28 #include "va_trace.h" |
| 29 #include "va_fool.h" |
| 30 |
| 31 #include <assert.h> |
| 32 #include <stdarg.h> |
| 33 #include <stdlib.h> |
| 34 #include <stdio.h> |
| 35 #include <string.h> |
| 36 #include <dlfcn.h> |
| 37 #include <unistd.h> |
| 38 #include <sys/types.h> |
| 39 #include <sys/stat.h> |
| 40 #include <unistd.h> |
| 41 #include <time.h> |
| 42 #include <fcntl.h> |
| 43 |
| 44 /* |
| 45 * Do dummy decode/encode, ignore the input data |
| 46 * In order to debug memory leak or low performance issues, we need to isolate d
river problems |
| 47 * We export env "VA_FOOL", with which, we can do fake decode/encode: |
| 48 * |
| 49 * LIBVA_FOOL_DECODE: |
| 50 * . if set, decode does nothing |
| 51 * LIBVA_FOOL_ENCODE=<framename>: |
| 52 * . if set, encode does nothing, but fill in the coded buffer from the content
of files with |
| 53 * name framename.0,framename.1,framename.2, ..., framename.N, framename.N,fra
mename.N,... |
| 54 * LIBVA_FOOL_JPEG=<framename>:fill the content of filename to codedbuf for jpeg
encoding |
| 55 * LIBVA_FOOL_POSTP: |
| 56 * . if set, do nothing for vaPutSurface |
| 57 */ |
| 58 |
| 59 |
| 60 /* global settings */ |
| 61 int fool_codec = 0; |
| 62 int fool_postp = 0; |
| 63 |
| 64 #define FOOL_CONTEXT_MAX 4 |
| 65 |
| 66 #define FOOL_BUFID_MAGIC 0x12345600 |
| 67 #define FOOL_BUFID_MASK 0xffffff00 |
| 68 /* per context settings */ |
| 69 static struct _fool_context { |
| 70 VADisplay dpy; /* should use context as the key */ |
| 71 |
| 72 char *fn_enc;/* file pattern with codedbuf content for encode */ |
| 73 char *segbuf_enc; /* the segment buffer of coded buffer, load frome fn_enc *
/ |
| 74 int file_count; |
| 75 |
| 76 char *fn_jpg;/* file name of JPEG fool with codedbuf content */ |
| 77 char *segbuf_jpg; /* the segment buffer of coded buffer, load frome fn_jpg *
/ |
| 78 |
| 79 VAEntrypoint entrypoint; /* current entrypoint */ |
| 80 |
| 81 /* all buffers with same type share one malloc-ed memory |
| 82 * bufferID = (buffer numbers with the same type << 8) || type |
| 83 * the malloc-ed memory can be find by fool_buf[bufferID & 0xff] |
| 84 * the size is ignored here |
| 85 */ |
| 86 char *fool_buf[VABufferTypeMax]; /* memory of fool buffers */ |
| 87 unsigned int fool_buf_size[VABufferTypeMax]; /* size of memory of fool buffe
rs */ |
| 88 unsigned int fool_buf_element[VABufferTypeMax]; /* element count of created
buffers */ |
| 89 unsigned int fool_buf_count[VABufferTypeMax]; /* count of created buffers */ |
| 90 VAContextID context; |
| 91 } fool_context[FOOL_CONTEXT_MAX]; /* trace five context at the same time */ |
| 92 |
| 93 #define DPY2INDEX(dpy) \ |
| 94 int idx; \ |
| 95 \ |
| 96 for (idx = 0; idx < FOOL_CONTEXT_MAX; idx++) \ |
| 97 if (fool_context[idx].dpy == dpy) \ |
| 98 break; \ |
| 99 \ |
| 100 if (idx == FOOL_CONTEXT_MAX) \ |
| 101 return 0; /* let driver go */ |
| 102 |
| 103 /* Prototype declarations (functions defined in va.c) */ |
| 104 |
| 105 void va_errorMessage(const char *msg, ...); |
| 106 void va_infoMessage(const char *msg, ...); |
| 107 |
| 108 int va_parseConfig(char *env, char *env_value); |
| 109 |
| 110 void va_FoolInit(VADisplay dpy) |
| 111 { |
| 112 char env_value[1024]; |
| 113 int fool_index = 0; |
| 114 |
| 115 for (fool_index = 0; fool_index < FOOL_CONTEXT_MAX; fool_index++) |
| 116 if (fool_context[fool_index].dpy == 0) |
| 117 break; |
| 118 |
| 119 if (fool_index == FOOL_CONTEXT_MAX) |
| 120 return; |
| 121 |
| 122 memset(&fool_context[fool_index], 0, sizeof(struct _fool_context)); |
| 123 if (va_parseConfig("LIBVA_FOOL_POSTP", NULL) == 0) { |
| 124 fool_postp = 1; |
| 125 va_infoMessage("LIBVA_FOOL_POSTP is on, dummy vaPutSurface\n"); |
| 126 } |
| 127 |
| 128 if (va_parseConfig("LIBVA_FOOL_DECODE", NULL) == 0) { |
| 129 fool_codec |= VA_FOOL_FLAG_DECODE; |
| 130 va_infoMessage("LIBVA_FOOL_DECODE is on, dummy decode\n"); |
| 131 } |
| 132 if (va_parseConfig("LIBVA_FOOL_ENCODE", &env_value[0]) == 0) { |
| 133 fool_codec |= VA_FOOL_FLAG_ENCODE; |
| 134 fool_context[fool_index].fn_enc = strdup(env_value); |
| 135 va_infoMessage("LIBVA_FOOL_ENCODE is on, load encode data from file with
patten %s\n", |
| 136 fool_context[fool_index].fn_enc); |
| 137 } |
| 138 if (va_parseConfig("LIBVA_FOOL_JPEG", &env_value[0]) == 0) { |
| 139 fool_codec |= VA_FOOL_FLAG_JPEG; |
| 140 fool_context[fool_index].fn_jpg = strdup(env_value); |
| 141 va_infoMessage("LIBVA_FOOL_JPEG is on, load encode data from file with p
atten %s\n", |
| 142 fool_context[fool_index].fn_jpg); |
| 143 } |
| 144 |
| 145 if (fool_codec) |
| 146 fool_context[fool_index].dpy = dpy; |
| 147 } |
| 148 |
| 149 |
| 150 int va_FoolEnd(VADisplay dpy) |
| 151 { |
| 152 int i; |
| 153 DPY2INDEX(dpy); |
| 154 |
| 155 for (i = 0; i < VABufferTypeMax; i++) {/* free memory */ |
| 156 if (fool_context[idx].fool_buf[i]) |
| 157 free(fool_context[idx].fool_buf[i]); |
| 158 } |
| 159 if (fool_context[idx].segbuf_enc) |
| 160 free(fool_context[idx].segbuf_enc); |
| 161 if (fool_context[idx].segbuf_jpg) |
| 162 free(fool_context[idx].segbuf_jpg); |
| 163 if (fool_context[idx].fn_enc) |
| 164 free(fool_context[idx].fn_enc); |
| 165 if (fool_context[idx].fn_jpg) |
| 166 free(fool_context[idx].fn_jpg); |
| 167 |
| 168 memset(&fool_context[idx], 0, sizeof(struct _fool_context)); |
| 169 |
| 170 return 0; |
| 171 } |
| 172 |
| 173 |
| 174 int va_FoolCreateConfig( |
| 175 VADisplay dpy, |
| 176 VAProfile profile, |
| 177 VAEntrypoint entrypoint, |
| 178 VAConfigAttrib *attrib_list, |
| 179 int num_attribs, |
| 180 VAConfigID *config_id /* out */ |
| 181 ) |
| 182 { |
| 183 DPY2INDEX(dpy); |
| 184 |
| 185 fool_context[idx].entrypoint = entrypoint; |
| 186 |
| 187 /* |
| 188 * check fool_codec to align with current context |
| 189 * e.g. fool_codec = decode then for encode, the |
| 190 * vaBegin/vaRender/vaEnd also run into fool path |
| 191 * which is not desired |
| 192 */ |
| 193 if (((fool_codec & VA_FOOL_FLAG_DECODE) && (entrypoint == VAEntrypointVLD))
|| |
| 194 ((fool_codec & VA_FOOL_FLAG_ENCODE) && (entrypoint == VAEntrypointEncSli
ce)) || |
| 195 ((fool_codec & VA_FOOL_FLAG_JPEG) && (entrypoint == VAEntrypointEncPictu
re))) |
| 196 ; /* the fool_codec is meaningful */ |
| 197 else |
| 198 fool_codec = 0; |
| 199 |
| 200 return 0; /* driver continue */ |
| 201 } |
| 202 |
| 203 |
| 204 VAStatus va_FoolCreateBuffer( |
| 205 VADisplay dpy, |
| 206 VAContextID context, /* in */ |
| 207 VABufferType type, /* in */ |
| 208 unsigned int size, /* in */ |
| 209 unsigned int num_elements, /* in */ |
| 210 void *data, /* in */ |
| 211 VABufferID *buf_id /* out */ |
| 212 ) |
| 213 { |
| 214 unsigned int new_size = size * num_elements; |
| 215 unsigned int old_size; |
| 216 DPY2INDEX(dpy); |
| 217 |
| 218 old_size = fool_context[idx].fool_buf_size[type] * fool_context[idx].fool_bu
f_element[type]; |
| 219 |
| 220 if (old_size < new_size) |
| 221 fool_context[idx].fool_buf[type] = realloc(fool_context[idx].fool_buf[ty
pe], new_size); |
| 222 |
| 223 fool_context[idx].fool_buf_size[type] = size; |
| 224 fool_context[idx].fool_buf_element[type] = num_elements; |
| 225 fool_context[idx].fool_buf_count[type]++; |
| 226 /* because we ignore the vaRenderPicture, |
| 227 * all buffers with same type share same real memory |
| 228 * bufferID = (magic number) | type |
| 229 */ |
| 230 *buf_id = FOOL_BUFID_MAGIC | type; |
| 231 |
| 232 return 1; /* don't call into driver */ |
| 233 } |
| 234 |
| 235 VAStatus va_FoolBufferInfo( |
| 236 VADisplay dpy, |
| 237 VABufferID buf_id, /* in */ |
| 238 VABufferType *type, /* out */ |
| 239 unsigned int *size, /* out */ |
| 240 unsigned int *num_elements /* out */ |
| 241 ) |
| 242 { |
| 243 unsigned int magic = buf_id & FOOL_BUFID_MASK; |
| 244 DPY2INDEX(dpy); |
| 245 |
| 246 if (magic != FOOL_BUFID_MAGIC) |
| 247 return 0; |
| 248 |
| 249 *type = buf_id & 0xff; |
| 250 *size = fool_context[idx].fool_buf_size[*type]; |
| 251 *num_elements = fool_context[idx].fool_buf_element[*type];; |
| 252 |
| 253 return 1; /* don't call into driver */ |
| 254 } |
| 255 |
| 256 static int va_FoolFillCodedBufEnc(int idx) |
| 257 { |
| 258 char file_name[1024]; |
| 259 struct stat file_stat; |
| 260 VACodedBufferSegment *codedbuf; |
| 261 int i, fd = -1; |
| 262 |
| 263 /* try file_name.file_count, if fail, try file_name.file_count-- */ |
| 264 for (i=0; i<=1; i++) { |
| 265 sprintf(file_name, "%s.%d", |
| 266 fool_context[idx].fn_enc, |
| 267 fool_context[idx].file_count); |
| 268 |
| 269 if ((fd = open(file_name, O_RDONLY)) != -1) { |
| 270 fstat(fd, &file_stat); |
| 271 fool_context[idx].file_count++; /* open next file */ |
| 272 break; |
| 273 } |
| 274 |
| 275 fool_context[idx].file_count--; /* fall back to previous file */ |
| 276 if (fool_context[idx].file_count < 0) |
| 277 fool_context[idx].file_count = 0; |
| 278 } |
| 279 if (fd != -1) { |
| 280 fool_context[idx].segbuf_enc = realloc(fool_context[idx].segbuf_enc, fil
e_stat.st_size); |
| 281 read(fd, fool_context[idx].segbuf_enc, file_stat.st_size); |
| 282 close(fd); |
| 283 } |
| 284 codedbuf = (VACodedBufferSegment *)fool_context[idx].fool_buf[VAEncCodedBuff
erType]; |
| 285 codedbuf->size = file_stat.st_size; |
| 286 codedbuf->bit_offset = 0; |
| 287 codedbuf->status = 0; |
| 288 codedbuf->reserved = 0; |
| 289 codedbuf->buf = fool_context[idx].segbuf_enc; |
| 290 codedbuf->next = NULL; |
| 291 |
| 292 return 0; |
| 293 } |
| 294 |
| 295 |
| 296 static int va_FoolFillCodedBufJPG(int idx) |
| 297 { |
| 298 struct stat file_stat; |
| 299 VACodedBufferSegment *codedbuf; |
| 300 int i, fd = -1; |
| 301 |
| 302 if ((fd = open(fool_context[idx].fn_jpg, O_RDONLY)) != -1) |
| 303 fstat(fd, &file_stat); |
| 304 |
| 305 if (fd != -1) { |
| 306 fool_context[idx].segbuf_jpg = realloc(fool_context[idx].segbuf_jpg, fil
e_stat.st_size); |
| 307 read(fd, fool_context[idx].segbuf_jpg, file_stat.st_size); |
| 308 close(fd); |
| 309 } |
| 310 codedbuf = (VACodedBufferSegment *)fool_context[idx].fool_buf[VAEncCodedBuff
erType]; |
| 311 codedbuf->size = file_stat.st_size; |
| 312 codedbuf->bit_offset = 0; |
| 313 codedbuf->status = 0; |
| 314 codedbuf->reserved = 0; |
| 315 codedbuf->buf = fool_context[idx].segbuf_jpg; |
| 316 codedbuf->next = NULL; |
| 317 |
| 318 return 0; |
| 319 } |
| 320 |
| 321 |
| 322 static int va_FoolFillCodedBuf(int idx) |
| 323 { |
| 324 if (fool_context[idx].entrypoint == VAEntrypointEncSlice) |
| 325 va_FoolFillCodedBufEnc(idx); |
| 326 else if (fool_context[idx].entrypoint == VAEntrypointEncPicture) |
| 327 va_FoolFillCodedBufJPG(idx); |
| 328 |
| 329 return 0; |
| 330 } |
| 331 |
| 332 |
| 333 VAStatus va_FoolMapBuffer( |
| 334 VADisplay dpy, |
| 335 VABufferID buf_id, /* in */ |
| 336 void **pbuf /* out */ |
| 337 ) |
| 338 { |
| 339 unsigned int buftype = buf_id & 0xff; |
| 340 unsigned int magic = buf_id & FOOL_BUFID_MASK; |
| 341 DPY2INDEX(dpy); |
| 342 |
| 343 if (magic != FOOL_BUFID_MAGIC) |
| 344 return 0; |
| 345 |
| 346 /* buf_id is the buffer type */ |
| 347 *pbuf = fool_context[idx].fool_buf[buftype]; |
| 348 |
| 349 /* it is coded buffer, fill the fake segment buf from file */ |
| 350 if (*pbuf && (buftype == VAEncCodedBufferType)) |
| 351 va_FoolFillCodedBuf(idx); |
| 352 |
| 353 return 1; /* don't call into driver */ |
| 354 } |
| 355 |
| 356 VAStatus va_FoolUnmapBuffer( |
| 357 VADisplay dpy, |
| 358 VABufferID buf_id /* in */ |
| 359 ) |
| 360 { |
| 361 unsigned int magic = buf_id & FOOL_BUFID_MASK; |
| 362 |
| 363 if (magic != FOOL_BUFID_MAGIC) |
| 364 return 0; |
| 365 |
| 366 return 1; |
| 367 } |
OLD | NEW |