2 * Copyright (c) 2009 Intel Corporation. All Rights Reserved.
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:
12 * The above copyright notice and this permission notice (including the
13 * next paragraph) shall be included in all copies or substantial portions
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.
28 #include "va_backend.h"
29 #include "va_internal.h"
41 #include <sys/types.h>
48 * Do dummy decode/encode, ignore the input data
49 * In order to debug memory leak or low performance issues, we need to isolate driver problems
50 * We export env "VA_FOOL", with which, we can do fake decode/encode:
53 * . if set, decode does nothing
54 * LIBVA_FOOL_ENCODE=<framename>:
55 * . if set, encode does nothing, but fill in the coded buffer from the content of files with
56 * name framename.0,framename.1,..., framename.N, framename.0,..., framename.N,...repeatly
57 * Use file name to determine h264 or vp8
58 * LIBVA_FOOL_JPEG=<framename>:fill the content of filename to codedbuf for jpeg encoding
60 * . if set, do nothing for vaPutSurface
65 int va_fool_codec = 0;
66 int va_fool_postp = 0;
68 #define FOOL_BUFID_MAGIC 0x12345600
69 #define FOOL_BUFID_MASK 0xffffff00
72 int enabled; /* va_fool_codec is global, and it is for concurent encode/decode */
73 char *fn_enc;/* file pattern with codedbuf content for encode */
74 char *segbuf_enc; /* the segment buffer of coded buffer, load frome fn_enc */
77 char *fn_jpg;/* file name of JPEG fool with codedbuf content */
78 char *segbuf_jpg; /* the segment buffer of coded buffer, load frome fn_jpg */
80 VAEntrypoint entrypoint; /* current entrypoint */
82 /* all buffers with same type share one malloc-ed memory
83 * bufferID = (buffer numbers with the same type << 8) || type
84 * the malloc-ed memory can be find by fool_buf[bufferID & 0xff]
85 * the size is ignored here
87 char *fool_buf[VABufferTypeMax]; /* memory of fool buffers */
88 unsigned int fool_buf_size[VABufferTypeMax]; /* size of memory of fool buffers */
89 unsigned int fool_buf_element[VABufferTypeMax]; /* element count of created buffers */
90 unsigned int fool_buf_count[VABufferTypeMax]; /* count of created buffers */
94 #define FOOL_CTX(dpy) ((struct fool_context *)((VADisplayContextP)dpy)->vafool)
96 #define DPY2FOOLCTX(dpy) \
97 struct fool_context *fool_ctx = FOOL_CTX(dpy); \
98 if (fool_ctx == NULL) \
99 return 0; /* no fool for the context */ \
101 #define DPY2FOOLCTX_CHK(dpy) \
102 struct fool_context *fool_ctx = FOOL_CTX(dpy); \
103 if ((fool_ctx == NULL) || (fool_ctx->enabled == 0)) \
104 return 0; /* no fool for the context */ \
107 void va_FoolInit(VADisplay dpy)
109 char env_value[1024];
111 struct fool_context *fool_ctx = calloc(sizeof(struct fool_context), 1);
113 if (fool_ctx == NULL)
116 if (va_parseConfig("LIBVA_FOOL_POSTP", NULL) == 0) {
118 va_infoMessage(dpy, "LIBVA_FOOL_POSTP is on, dummy vaPutSurface\n");
121 if (va_parseConfig("LIBVA_FOOL_DECODE", NULL) == 0) {
122 va_fool_codec |= VA_FOOL_FLAG_DECODE;
123 va_infoMessage(dpy, "LIBVA_FOOL_DECODE is on, dummy decode\n");
125 if (va_parseConfig("LIBVA_FOOL_ENCODE", &env_value[0]) == 0) {
126 va_fool_codec |= VA_FOOL_FLAG_ENCODE;
127 fool_ctx->fn_enc = strdup(env_value);
128 va_infoMessage(dpy, "LIBVA_FOOL_ENCODE is on, load encode data from file with patten %s\n",
131 if (va_parseConfig("LIBVA_FOOL_JPEG", &env_value[0]) == 0) {
132 va_fool_codec |= VA_FOOL_FLAG_JPEG;
133 fool_ctx->fn_jpg = strdup(env_value);
134 va_infoMessage(dpy, "LIBVA_FOOL_JPEG is on, load encode data from file with patten %s\n",
138 ((VADisplayContextP)dpy)->vafool = fool_ctx;
142 int va_FoolEnd(VADisplay dpy)
147 for (i = 0; i < VABufferTypeMax; i++) {/* free memory */
148 if (fool_ctx->fool_buf[i])
149 free(fool_ctx->fool_buf[i]);
151 if (fool_ctx->segbuf_enc)
152 free(fool_ctx->segbuf_enc);
153 if (fool_ctx->segbuf_jpg)
154 free(fool_ctx->segbuf_jpg);
155 if (fool_ctx->fn_enc)
156 free(fool_ctx->fn_enc);
157 if (fool_ctx->fn_jpg)
158 free(fool_ctx->fn_jpg);
161 ((VADisplayContextP)dpy)->vafool = NULL;
166 int va_FoolCreateConfig(
169 VAEntrypoint entrypoint,
170 VAConfigAttrib *attrib_list,
172 VAConfigID *config_id /* out */
177 fool_ctx->entrypoint = entrypoint;
180 * check va_fool_codec to align with current context
181 * e.g. va_fool_codec = decode then for encode, the
182 * vaBegin/vaRender/vaEnd also run into fool path
183 * which is not desired
185 if (((va_fool_codec & VA_FOOL_FLAG_DECODE) && (entrypoint == VAEntrypointVLD)) ||
186 ((va_fool_codec & VA_FOOL_FLAG_JPEG) && (entrypoint == VAEntrypointEncPicture)))
187 fool_ctx->enabled = 1;
188 else if ((va_fool_codec & VA_FOOL_FLAG_ENCODE) && (entrypoint == VAEntrypointEncSlice)) {
189 /* H264 is desired */
190 if (((profile == VAProfileH264Main ||
191 profile == VAProfileH264High ||
192 profile == VAProfileH264ConstrainedBaseline)) &&
193 strstr(fool_ctx->fn_enc, "h264"))
194 fool_ctx->enabled = 1;
197 if ((profile == VAProfileVP8Version0_3) &&
198 strstr(fool_ctx->fn_enc, "vp8"))
199 fool_ctx->enabled = 1;
201 if (fool_ctx->enabled)
202 va_infoMessage(dpy, "FOOL is enabled for this context\n");
204 va_infoMessage(dpy, "FOOL is not enabled for this context\n");
207 return 0; /* continue */
211 VAStatus va_FoolCreateBuffer(
213 VAContextID context, /* in */
214 VABufferType type, /* in */
215 unsigned int size, /* in */
216 unsigned int num_elements, /* in */
218 VABufferID *buf_id /* out */
221 unsigned int new_size = size * num_elements;
222 unsigned int old_size;
223 DPY2FOOLCTX_CHK(dpy);
225 old_size = fool_ctx->fool_buf_size[type] * fool_ctx->fool_buf_element[type];
227 if (old_size < new_size)
228 fool_ctx->fool_buf[type] = realloc(fool_ctx->fool_buf[type], new_size);
230 fool_ctx->fool_buf_size[type] = size;
231 fool_ctx->fool_buf_element[type] = num_elements;
232 fool_ctx->fool_buf_count[type]++;
233 /* because we ignore the vaRenderPicture,
234 * all buffers with same type share same real memory
235 * bufferID = (magic number) | type
237 *buf_id = FOOL_BUFID_MAGIC | type;
239 return 1; /* don't call into driver */
242 VAStatus va_FoolBufferInfo(
244 VABufferID buf_id, /* in */
245 VABufferType *type, /* out */
246 unsigned int *size, /* out */
247 unsigned int *num_elements /* out */
252 DPY2FOOLCTX_CHK(dpy);
254 magic = buf_id & FOOL_BUFID_MASK;
255 if (magic != FOOL_BUFID_MAGIC)
256 return 0; /* could be VAImageBufferType from vaDeriveImage */
258 *type = buf_id & 0xff;
259 *size = fool_ctx->fool_buf_size[*type];
260 *num_elements = fool_ctx->fool_buf_element[*type];;
262 return 1; /* fool is valid */
265 static int va_FoolFillCodedBufEnc(VADisplay dpy, struct fool_context *fool_ctx)
267 char file_name[1024];
268 struct stat file_stat = {0};
269 VACodedBufferSegment *codedbuf;
273 /* try file_name.file_count, if fail, try file_name.file_count-- */
274 for (i=0; i<=1; i++) {
275 snprintf(file_name, 1024, "%s.%d",
277 fool_ctx->file_count);
279 if ((fd = open(file_name, O_RDONLY)) != -1) {
280 if (fstat(fd, &file_stat) != -1) {
281 fool_ctx->file_count++; /* open next file */
284 va_errorMessage(dpy, "Identify file %s failed:%s\n",
285 file_name, strerror(errno));
289 /* fall back to the first file file */
290 fool_ctx->file_count = 0;
293 fool_ctx->segbuf_enc = realloc(fool_ctx->segbuf_enc, file_stat.st_size);
294 ret = read(fd, fool_ctx->segbuf_enc, file_stat.st_size);
295 if (ret < file_stat.st_size)
296 va_errorMessage(dpy, "Reading file %s failed.\n", file_name);
299 va_errorMessage(dpy, "Open file %s failed:%s\n", file_name, strerror(errno));
301 codedbuf = (VACodedBufferSegment *)fool_ctx->fool_buf[VAEncCodedBufferType];
302 codedbuf->size = file_stat.st_size;
303 codedbuf->bit_offset = 0;
304 codedbuf->status = 0;
305 codedbuf->reserved = 0;
306 codedbuf->buf = fool_ctx->segbuf_enc;
307 codedbuf->next = NULL;
312 static int va_FoolFillCodedBufJPG(VADisplay dpy, struct fool_context *fool_ctx)
314 struct stat file_stat = {0};
315 VACodedBufferSegment *codedbuf;
319 if ((fd = open(fool_ctx->fn_jpg, O_RDONLY)) != -1) {
320 if (fstat(fd, &file_stat) != -1) {
321 fool_ctx->segbuf_jpg = realloc(fool_ctx->segbuf_jpg, file_stat.st_size);
322 ret = read(fd, fool_ctx->segbuf_jpg, file_stat.st_size);
323 if (ret < file_stat.st_size)
324 va_errorMessage(dpy, "Reading file %s failed.\n", fool_ctx->fn_jpg);
326 va_errorMessage(dpy, "Identify file %s failed:%s\n",
327 fool_ctx->fn_jpg, strerror(errno));
331 va_errorMessage(dpy, "Open file %s failed:%s\n", fool_ctx->fn_jpg, strerror(errno));
333 codedbuf = (VACodedBufferSegment *)fool_ctx->fool_buf[VAEncCodedBufferType];
334 codedbuf->size = file_stat.st_size;
335 codedbuf->bit_offset = 0;
336 codedbuf->status = 0;
337 codedbuf->reserved = 0;
338 codedbuf->buf = fool_ctx->segbuf_jpg;
339 codedbuf->next = NULL;
345 static int va_FoolFillCodedBuf(VADisplay dpy, struct fool_context *fool_ctx)
347 if (fool_ctx->entrypoint == VAEntrypointEncSlice)
348 va_FoolFillCodedBufEnc(dpy, fool_ctx);
349 else if (fool_ctx->entrypoint == VAEntrypointEncPicture)
350 va_FoolFillCodedBufJPG(dpy, fool_ctx);
356 VAStatus va_FoolMapBuffer(
358 VABufferID buf_id, /* in */
359 void **pbuf /* out */
362 unsigned int magic, buftype;
363 DPY2FOOLCTX_CHK(dpy);
365 magic = buf_id & FOOL_BUFID_MASK;
366 if (magic != FOOL_BUFID_MAGIC)
367 return 0; /* could be VAImageBufferType from vaDeriveImage */
369 buftype = buf_id & 0xff;
370 *pbuf = fool_ctx->fool_buf[buftype];
372 /* it is coded buffer, fill coded segment from file */
373 if (*pbuf && (buftype == VAEncCodedBufferType))
374 va_FoolFillCodedBuf(dpy, fool_ctx);
376 return 1; /* fool is valid */
379 VAStatus va_FoolCheckContinuity(VADisplay dpy)
381 DPY2FOOLCTX_CHK(dpy);
383 return 1; /* fool is valid */