3c7161b3a399e778fe9f7878ff3af13cce2e6f0f
[profile/ivi/libva.git] / va / va_fool.c
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 <errno.h>
36 #include <string.h>
37 #include <dlfcn.h>
38 #include <unistd.h>
39 #include <sys/types.h>
40 #include <sys/stat.h>
41 #include <unistd.h>
42 #include <time.h>
43 #include <fcntl.h>
44
45 /*
46  * Do dummy decode/encode, ignore the input data
47  * In order to debug memory leak or low performance issues, we need to isolate driver problems
48  * We export env "VA_FOOL", with which, we can do fake decode/encode:
49  *
50  * LIBVA_FOOL_DECODE:
51  * . if set, decode does nothing
52  * LIBVA_FOOL_ENCODE=<framename>:
53  * . if set, encode does nothing, but fill in the coded buffer from the content of files with
54  *   name framename.0,framename.1,..., framename.N, framename.0,..., framename.N,...repeatly
55  * LIBVA_FOOL_JPEG=<framename>:fill the content of filename to codedbuf for jpeg encoding
56  * LIBVA_FOOL_POSTP:
57  * . if set, do nothing for vaPutSurface
58  */
59
60
61 /* global settings */
62 int fool_codec = 0;
63 int fool_postp  = 0;
64
65 #define FOOL_CONTEXT_MAX 4
66
67 #define FOOL_BUFID_MAGIC   0x12345600
68 #define FOOL_BUFID_MASK    0xffffff00
69 /* per context settings */
70 static struct _fool_context {
71     VADisplay dpy; /* should use context as the key */
72
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 */
75     int file_count;
76
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 */
79
80     VAEntrypoint entrypoint; /* current entrypoint */
81     
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
86      */
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 */
91     VAContextID context;
92 } fool_context[FOOL_CONTEXT_MAX]; /* trace five context at the same time */
93
94 #define DPY2INDEX(dpy)                                  \
95     int idx;                                            \
96                                                         \
97     for (idx = 0; idx < FOOL_CONTEXT_MAX; idx++)        \
98         if (fool_context[idx].dpy == dpy)               \
99             break;                                      \
100                                                         \
101     if (idx == FOOL_CONTEXT_MAX)                        \
102         return 0;  /* let driver go */
103
104 /* Prototype declarations (functions defined in va.c) */
105
106 void va_errorMessage(const char *msg, ...);
107 void va_infoMessage(const char *msg, ...);
108
109 int  va_parseConfig(char *env, char *env_value);
110
111 void va_FoolInit(VADisplay dpy)
112 {
113     char env_value[1024];
114     int fool_index = 0;
115
116     for (fool_index = 0; fool_index < FOOL_CONTEXT_MAX; fool_index++)
117         if (fool_context[fool_index].dpy == 0)
118             break;
119
120     if (fool_index == FOOL_CONTEXT_MAX)
121         return;
122
123     memset(&fool_context[fool_index], 0, sizeof(struct _fool_context));
124     if (va_parseConfig("LIBVA_FOOL_POSTP", NULL) == 0) {
125         fool_postp = 1;
126         va_infoMessage("LIBVA_FOOL_POSTP is on, dummy vaPutSurface\n");
127     }
128     
129     if (va_parseConfig("LIBVA_FOOL_DECODE", NULL) == 0) {
130         fool_codec  |= VA_FOOL_FLAG_DECODE;
131         va_infoMessage("LIBVA_FOOL_DECODE is on, dummy decode\n");
132     }
133     if (va_parseConfig("LIBVA_FOOL_ENCODE", &env_value[0]) == 0) {
134         fool_codec  |= VA_FOOL_FLAG_ENCODE;
135         fool_context[fool_index].fn_enc = strdup(env_value);
136         va_infoMessage("LIBVA_FOOL_ENCODE is on, load encode data from file with patten %s\n",
137                        fool_context[fool_index].fn_enc);
138     }
139     if (va_parseConfig("LIBVA_FOOL_JPEG", &env_value[0]) == 0) {
140         fool_codec  |= VA_FOOL_FLAG_JPEG;
141         fool_context[fool_index].fn_jpg = strdup(env_value);
142         va_infoMessage("LIBVA_FOOL_JPEG is on, load encode data from file with patten %s\n",
143                        fool_context[fool_index].fn_jpg);
144     }
145     
146     if (fool_codec)
147         fool_context[fool_index].dpy = dpy;
148 }
149
150
151 int va_FoolEnd(VADisplay dpy)
152 {
153     int i;
154     DPY2INDEX(dpy);
155
156     for (i = 0; i < VABufferTypeMax; i++) {/* free memory */
157         if (fool_context[idx].fool_buf[i])
158             free(fool_context[idx].fool_buf[i]);
159     }
160     if (fool_context[idx].segbuf_enc)
161         free(fool_context[idx].segbuf_enc);
162     if (fool_context[idx].segbuf_jpg)
163         free(fool_context[idx].segbuf_jpg);
164     if (fool_context[idx].fn_enc)
165         free(fool_context[idx].fn_enc);
166     if (fool_context[idx].fn_jpg)
167         free(fool_context[idx].fn_jpg);
168     
169     memset(&fool_context[idx], 0, sizeof(struct _fool_context));
170     
171     return 0;
172 }
173
174
175 int va_FoolCreateConfig(
176         VADisplay dpy,
177         VAProfile profile, 
178         VAEntrypoint entrypoint, 
179         VAConfigAttrib *attrib_list,
180         int num_attribs,
181         VAConfigID *config_id /* out */
182 )
183 {
184     DPY2INDEX(dpy);
185
186     fool_context[idx].entrypoint = entrypoint;
187     
188     /*
189      * check fool_codec to align with current context
190      * e.g. fool_codec = decode then for encode, the
191      * vaBegin/vaRender/vaEnd also run into fool path
192      * which is not desired
193      */
194     if (((fool_codec & VA_FOOL_FLAG_DECODE) && (entrypoint == VAEntrypointVLD)) ||
195         ((fool_codec & VA_FOOL_FLAG_ENCODE) && (entrypoint == VAEntrypointEncSlice)) ||
196         ((fool_codec & VA_FOOL_FLAG_JPEG) && (entrypoint == VAEntrypointEncPicture)))
197         ; /* the fool_codec is meaningful */
198     else
199         fool_codec = 0;
200
201     return 0; /* driver continue */
202 }
203
204
205 VAStatus va_FoolCreateBuffer(
206     VADisplay dpy,
207     VAContextID context,        /* in */
208     VABufferType type,          /* in */
209     unsigned int size,          /* in */
210     unsigned int num_elements,  /* in */
211     void *data,                 /* in */
212     VABufferID *buf_id          /* out */
213 )
214 {
215     unsigned int new_size = size * num_elements;
216     unsigned int old_size;
217     DPY2INDEX(dpy);
218
219     old_size = fool_context[idx].fool_buf_size[type] * fool_context[idx].fool_buf_element[type];
220
221     if (old_size < new_size)
222         fool_context[idx].fool_buf[type] = realloc(fool_context[idx].fool_buf[type], new_size);
223     
224     fool_context[idx].fool_buf_size[type] = size;
225     fool_context[idx].fool_buf_element[type] = num_elements;
226     fool_context[idx].fool_buf_count[type]++;
227     /* because we ignore the vaRenderPicture, 
228      * all buffers with same type share same real memory
229      * bufferID = (magic number) | type
230      */
231     *buf_id = FOOL_BUFID_MAGIC | type;
232
233     return 1; /* don't call into driver */
234 }
235
236 VAStatus va_FoolBufferInfo(
237     VADisplay dpy,
238     VABufferID buf_id,  /* in */
239     VABufferType *type, /* out */
240     unsigned int *size,         /* out */
241     unsigned int *num_elements /* out */
242 )
243 {
244     unsigned int magic = buf_id & FOOL_BUFID_MASK;
245     DPY2INDEX(dpy);
246
247     if (magic != FOOL_BUFID_MAGIC)
248         return 0;
249
250     *type = buf_id & 0xff;
251     *size = fool_context[idx].fool_buf_size[*type];
252     *num_elements = fool_context[idx].fool_buf_element[*type];;
253     
254     return 1; /* don't call into driver */
255 }
256
257 static int va_FoolFillCodedBufEnc(int idx)
258 {
259     char file_name[1024];
260     struct stat file_stat = {0};
261     VACodedBufferSegment *codedbuf;
262     int i, fd = -1;
263
264     /* try file_name.file_count, if fail, try file_name.file_count-- */
265     for (i=0; i<=1; i++) {
266         snprintf(file_name, 1024, "%s.%d",
267                  fool_context[idx].fn_enc,
268                  fool_context[idx].file_count);
269
270         if ((fd = open(file_name, O_RDONLY)) != -1) {
271             fstat(fd, &file_stat);
272             fool_context[idx].file_count++; /* open next file */
273             break;
274         } else /* fall back to the first file file */
275             fool_context[idx].file_count = 0;
276     }
277     if (fd != -1) {
278         fool_context[idx].segbuf_enc = realloc(fool_context[idx].segbuf_enc, file_stat.st_size);
279         read(fd, fool_context[idx].segbuf_enc, file_stat.st_size);
280         close(fd);
281     } else
282         va_errorMessage("Open file %s failed:%s\n", file_name, strerror(errno));
283
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;
291
292     return 0;
293 }
294
295
296 static int va_FoolFillCodedBufJPG(int idx)
297 {
298     struct stat file_stat = {0};
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         fool_context[idx].segbuf_jpg = realloc(fool_context[idx].segbuf_jpg, file_stat.st_size);
305         read(fd, fool_context[idx].segbuf_jpg, file_stat.st_size);
306         close(fd);
307     } else
308         va_errorMessage("Open file %s failed:%s\n", fool_context[idx].fn_jpg, strerror(errno));
309
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;
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 }