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.
27 #include "va_backend.h"
38 #include <sys/types.h>
45 * Do dummy decode/encode, ignore the input data
46 * In order to debug memory leak or low performance issues, we need to isolate driver problems
47 * We export env "VA_FOOL", with which, we can do fake decode/encode:
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,framename.N,...
54 * LIBVA_FOOL_JPEG=<framename>:fill the content of filename to codedbuf for jpeg encoding
56 * . if set, do nothing for vaPutSurface
64 #define FOOL_CONTEXT_MAX 4
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 */
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 */
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 */
79 VAEntrypoint entrypoint; /* current entrypoint */
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
86 char *fool_buf[VABufferTypeMax]; /* memory of fool buffers */
87 unsigned int fool_buf_size[VABufferTypeMax]; /* size of memory of fool buffers */
88 unsigned int fool_buf_element[VABufferTypeMax]; /* element count of created buffers */
89 unsigned int fool_buf_count[VABufferTypeMax]; /* count of created buffers */
91 } fool_context[FOOL_CONTEXT_MAX]; /* trace five context at the same time */
93 #define DPY2INDEX(dpy) \
96 for (idx = 0; idx < FOOL_CONTEXT_MAX; idx++) \
97 if (fool_context[idx].dpy == dpy) \
100 if (idx == FOOL_CONTEXT_MAX) \
101 return 0; /* let driver go */
103 /* Prototype declarations (functions defined in va.c) */
105 void va_errorMessage(const char *msg, ...);
106 void va_infoMessage(const char *msg, ...);
108 int va_parseConfig(char *env, char *env_value);
110 void va_FoolInit(VADisplay dpy)
112 char env_value[1024];
115 for (fool_index = 0; fool_index < FOOL_CONTEXT_MAX; fool_index++)
116 if (fool_context[fool_index].dpy == 0)
119 if (fool_index == FOOL_CONTEXT_MAX)
122 memset(&fool_context[fool_index], 0, sizeof(struct _fool_context));
123 if (va_parseConfig("LIBVA_FOOL_POSTP", NULL) == 0) {
125 va_infoMessage("LIBVA_FOOL_POSTP is on, dummy vaPutSurface\n");
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");
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);
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 patten %s\n",
142 fool_context[fool_index].fn_jpg);
146 fool_context[fool_index].dpy = dpy;
150 int va_FoolEnd(VADisplay dpy)
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]);
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);
168 memset(&fool_context[idx], 0, sizeof(struct _fool_context));
174 int va_FoolCreateConfig(
177 VAEntrypoint entrypoint,
178 VAConfigAttrib *attrib_list,
180 VAConfigID *config_id /* out */
185 fool_context[idx].entrypoint = entrypoint;
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
193 if (((fool_codec & VA_FOOL_FLAG_DECODE) && (entrypoint == VAEntrypointVLD)) ||
194 ((fool_codec & VA_FOOL_FLAG_ENCODE) && (entrypoint == VAEntrypointEncSlice)) ||
195 ((fool_codec & VA_FOOL_FLAG_JPEG) && (entrypoint == VAEntrypointEncPicture)))
196 ; /* the fool_codec is meaningful */
200 return 0; /* driver continue */
204 VAStatus va_FoolCreateBuffer(
206 VAContextID context, /* in */
207 VABufferType type, /* in */
208 unsigned int size, /* in */
209 unsigned int num_elements, /* in */
211 VABufferID *buf_id /* out */
214 unsigned int new_size = size * num_elements;
215 unsigned int old_size;
218 old_size = fool_context[idx].fool_buf_size[type] * fool_context[idx].fool_buf_element[type];
220 if (old_size < new_size)
221 fool_context[idx].fool_buf[type] = realloc(fool_context[idx].fool_buf[type], new_size);
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
230 *buf_id = FOOL_BUFID_MAGIC | type;
232 return 1; /* don't call into driver */
235 VAStatus va_FoolBufferInfo(
237 VABufferID buf_id, /* in */
238 VABufferType *type, /* out */
239 unsigned int *size, /* out */
240 unsigned int *num_elements /* out */
243 unsigned int magic = buf_id & FOOL_BUFID_MASK;
246 if (magic != FOOL_BUFID_MAGIC)
249 *type = buf_id & 0xff;
250 *size = fool_context[idx].fool_buf_size[*type];
251 *num_elements = fool_context[idx].fool_buf_element[*type];;
253 return 1; /* don't call into driver */
256 static int va_FoolFillCodedBufEnc(int idx)
258 char file_name[1024];
259 struct stat file_stat;
260 VACodedBufferSegment *codedbuf;
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);
269 if ((fd = open(file_name, O_RDONLY)) != -1) {
270 fstat(fd, &file_stat);
271 fool_context[idx].file_count++; /* open next file */
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;
280 fool_context[idx].segbuf_enc = realloc(fool_context[idx].segbuf_enc, file_stat.st_size);
281 read(fd, fool_context[idx].segbuf_enc, file_stat.st_size);
284 codedbuf = (VACodedBufferSegment *)fool_context[idx].fool_buf[VAEncCodedBufferType];
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;
296 static int va_FoolFillCodedBufJPG(int idx)
298 struct stat file_stat;
299 VACodedBufferSegment *codedbuf;
302 if ((fd = open(fool_context[idx].fn_jpg, O_RDONLY)) != -1)
303 fstat(fd, &file_stat);
306 fool_context[idx].segbuf_jpg = realloc(fool_context[idx].segbuf_jpg, file_stat.st_size);
307 read(fd, fool_context[idx].segbuf_jpg, file_stat.st_size);
310 codedbuf = (VACodedBufferSegment *)fool_context[idx].fool_buf[VAEncCodedBufferType];
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;
322 static int va_FoolFillCodedBuf(int idx)
324 if (fool_context[idx].entrypoint == VAEntrypointEncSlice)
325 va_FoolFillCodedBufEnc(idx);
326 else if (fool_context[idx].entrypoint == VAEntrypointEncPicture)
327 va_FoolFillCodedBufJPG(idx);
333 VAStatus va_FoolMapBuffer(
335 VABufferID buf_id, /* in */
336 void **pbuf /* out */
339 unsigned int buftype = buf_id & 0xff;
340 unsigned int magic = buf_id & FOOL_BUFID_MASK;
343 if (magic != FOOL_BUFID_MAGIC)
346 /* buf_id is the buffer type */
347 *pbuf = fool_context[idx].fool_buf[buftype];
349 /* it is coded buffer, fill the fake segment buf from file */
350 if (*pbuf && (buftype == VAEncCodedBufferType))
351 va_FoolFillCodedBuf(idx);
353 return 1; /* don't call into driver */
356 VAStatus va_FoolUnmapBuffer(
358 VABufferID buf_id /* in */
361 unsigned int magic = buf_id & FOOL_BUFID_MASK;
363 if (magic != FOOL_BUFID_MAGIC)