vatrace/vafool: save the context data into display context
[platform/upstream/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_BUFID_MAGIC   0x12345600
66 #define FOOL_BUFID_MASK    0xffffff00
67
68 struct fool_context {
69     char *fn_enc;/* file pattern with codedbuf content for encode */
70     char *segbuf_enc; /* the segment buffer of coded buffer, load frome fn_enc */
71     int file_count;
72
73     char *fn_jpg;/* file name of JPEG fool with codedbuf content */
74     char *segbuf_jpg; /* the segment buffer of coded buffer, load frome fn_jpg */
75
76     VAEntrypoint entrypoint; /* current entrypoint */
77     
78     /* all buffers with same type share one malloc-ed memory
79      * bufferID = (buffer numbers with the same type << 8) || type
80      * the malloc-ed memory can be find by fool_buf[bufferID & 0xff]
81      * the size is ignored here
82      */
83     char *fool_buf[VABufferTypeMax]; /* memory of fool buffers */
84     unsigned int fool_buf_size[VABufferTypeMax]; /* size of memory of fool buffers */
85     unsigned int fool_buf_element[VABufferTypeMax]; /* element count of created buffers */
86     unsigned int fool_buf_count[VABufferTypeMax]; /* count of created buffers */
87     VAContextID context;
88 };
89
90 #define FOOL_CTX(dpy) ((struct fool_context *)((VADisplayContextP)dpy)->vafool)
91 #define DPY2FOOLCTX(dpy)                                 \
92     struct fool_context *fool_ctx = FOOL_CTX(dpy);       \
93                                                          \
94     if (fool_ctx == NULL)                                \
95         return 0; /* let driver go */                    \
96
97 /* Prototype declarations (functions defined in va.c) */
98
99 void va_errorMessage(const char *msg, ...);
100 void va_infoMessage(const char *msg, ...);
101
102 int  va_parseConfig(char *env, char *env_value);
103
104 void va_FoolInit(VADisplay dpy)
105 {
106     char env_value[1024];
107     int fool_index = 0;
108
109     struct fool_context *fool_ctx = calloc(sizeof(struct fool_context), 1);
110     
111     if (fool_ctx == NULL)
112         return;
113     
114     if (va_parseConfig("LIBVA_FOOL_POSTP", NULL) == 0) {
115         fool_postp = 1;
116         va_infoMessage("LIBVA_FOOL_POSTP is on, dummy vaPutSurface\n");
117     }
118     
119     if (va_parseConfig("LIBVA_FOOL_DECODE", NULL) == 0) {
120         fool_codec  |= VA_FOOL_FLAG_DECODE;
121         va_infoMessage("LIBVA_FOOL_DECODE is on, dummy decode\n");
122     }
123     if (va_parseConfig("LIBVA_FOOL_ENCODE", &env_value[0]) == 0) {
124         fool_codec  |= VA_FOOL_FLAG_ENCODE;
125         fool_ctx->fn_enc = strdup(env_value);
126         va_infoMessage("LIBVA_FOOL_ENCODE is on, load encode data from file with patten %s\n",
127                        fool_ctx->fn_enc);
128     }
129     if (va_parseConfig("LIBVA_FOOL_JPEG", &env_value[0]) == 0) {
130         fool_codec  |= VA_FOOL_FLAG_JPEG;
131         fool_ctx->fn_jpg = strdup(env_value);
132         va_infoMessage("LIBVA_FOOL_JPEG is on, load encode data from file with patten %s\n",
133                        fool_ctx->fn_jpg);
134     }
135     
136     ((VADisplayContextP)dpy)->vafool = fool_ctx;
137 }
138
139
140 int va_FoolEnd(VADisplay dpy)
141 {
142     int i;
143     DPY2FOOLCTX(dpy);
144
145     for (i = 0; i < VABufferTypeMax; i++) {/* free memory */
146         if (fool_ctx->fool_buf[i])
147             free(fool_ctx->fool_buf[i]);
148     }
149     if (fool_ctx->segbuf_enc)
150         free(fool_ctx->segbuf_enc);
151     if (fool_ctx->segbuf_jpg)
152         free(fool_ctx->segbuf_jpg);
153     if (fool_ctx->fn_enc)
154         free(fool_ctx->fn_enc);
155     if (fool_ctx->fn_jpg)
156         free(fool_ctx->fn_jpg);
157
158     free(fool_ctx);
159     ((VADisplayContextP)dpy)->vafool = NULL;
160     
161     return 0;
162 }
163
164
165 int va_FoolCreateConfig(
166         VADisplay dpy,
167         VAProfile profile, 
168         VAEntrypoint entrypoint, 
169         VAConfigAttrib *attrib_list,
170         int num_attribs,
171         VAConfigID *config_id /* out */
172 )
173 {
174     DPY2FOOLCTX(dpy);
175
176     fool_ctx->entrypoint = entrypoint;
177     
178     /*
179      * check fool_codec to align with current context
180      * e.g. fool_codec = decode then for encode, the
181      * vaBegin/vaRender/vaEnd also run into fool path
182      * which is not desired
183      */
184     if (((fool_codec & VA_FOOL_FLAG_DECODE) && (entrypoint == VAEntrypointVLD)) ||
185         ((fool_codec & VA_FOOL_FLAG_ENCODE) && (entrypoint == VAEntrypointEncSlice)) ||
186         ((fool_codec & VA_FOOL_FLAG_JPEG) && (entrypoint == VAEntrypointEncPicture)))
187         ; /* the fool_codec is meaningful */
188     else
189         fool_codec = 0;
190
191     return 0; /* driver continue */
192 }
193
194
195 VAStatus va_FoolCreateBuffer(
196     VADisplay dpy,
197     VAContextID context,        /* in */
198     VABufferType type,          /* in */
199     unsigned int size,          /* in */
200     unsigned int num_elements,  /* in */
201     void *data,                 /* in */
202     VABufferID *buf_id          /* out */
203 )
204 {
205     unsigned int new_size = size * num_elements;
206     unsigned int old_size;
207     DPY2FOOLCTX(dpy);
208
209     old_size = fool_ctx->fool_buf_size[type] * fool_ctx->fool_buf_element[type];
210
211     if (old_size < new_size)
212         fool_ctx->fool_buf[type] = realloc(fool_ctx->fool_buf[type], new_size);
213     
214     fool_ctx->fool_buf_size[type] = size;
215     fool_ctx->fool_buf_element[type] = num_elements;
216     fool_ctx->fool_buf_count[type]++;
217     /* because we ignore the vaRenderPicture, 
218      * all buffers with same type share same real memory
219      * bufferID = (magic number) | type
220      */
221     *buf_id = FOOL_BUFID_MAGIC | type;
222
223     return 1; /* don't call into driver */
224 }
225
226 VAStatus va_FoolBufferInfo(
227     VADisplay dpy,
228     VABufferID buf_id,  /* in */
229     VABufferType *type, /* out */
230     unsigned int *size,         /* out */
231     unsigned int *num_elements /* out */
232 )
233 {
234     unsigned int magic = buf_id & FOOL_BUFID_MASK;
235     DPY2FOOLCTX(dpy);
236
237     if (magic != FOOL_BUFID_MAGIC)
238         return 0;
239
240     *type = buf_id & 0xff;
241     *size = fool_ctx->fool_buf_size[*type];
242     *num_elements = fool_ctx->fool_buf_element[*type];;
243     
244     return 1; /* don't call into driver */
245 }
246
247 static int va_FoolFillCodedBufEnc(struct fool_context *fool_ctx)
248 {
249     char file_name[1024];
250     struct stat file_stat = {0};
251     VACodedBufferSegment *codedbuf;
252     int i, fd = -1;
253
254     /* try file_name.file_count, if fail, try file_name.file_count-- */
255     for (i=0; i<=1; i++) {
256         snprintf(file_name, 1024, "%s.%d",
257                  fool_ctx->fn_enc,
258                  fool_ctx->file_count);
259
260         if ((fd = open(file_name, O_RDONLY)) != -1) {
261             fstat(fd, &file_stat);
262             fool_ctx->file_count++; /* open next file */
263             break;
264         } else /* fall back to the first file file */
265             fool_ctx->file_count = 0;
266     }
267     if (fd != -1) {
268         fool_ctx->segbuf_enc = realloc(fool_ctx->segbuf_enc, file_stat.st_size);
269         read(fd, fool_ctx->segbuf_enc, file_stat.st_size);
270         close(fd);
271     } else
272         va_errorMessage("Open file %s failed:%s\n", file_name, strerror(errno));
273
274     codedbuf = (VACodedBufferSegment *)fool_ctx->fool_buf[VAEncCodedBufferType];
275     codedbuf->size = file_stat.st_size;
276     codedbuf->bit_offset = 0;
277     codedbuf->status = 0;
278     codedbuf->reserved = 0;
279     codedbuf->buf = fool_ctx->segbuf_enc;
280     codedbuf->next = NULL;
281
282     return 0;
283 }
284
285
286 static int va_FoolFillCodedBufJPG(struct fool_context *fool_ctx)
287 {
288     struct stat file_stat = {0};
289     VACodedBufferSegment *codedbuf;
290     int i, fd = -1;
291
292     if ((fd = open(fool_ctx->fn_jpg, O_RDONLY)) != -1) {
293         fstat(fd, &file_stat);
294         fool_ctx->segbuf_jpg = realloc(fool_ctx->segbuf_jpg, file_stat.st_size);
295         read(fd, fool_ctx->segbuf_jpg, file_stat.st_size);
296         close(fd);
297     } else
298         va_errorMessage("Open file %s failed:%s\n", fool_ctx->fn_jpg, strerror(errno));
299
300     codedbuf = (VACodedBufferSegment *)fool_ctx->fool_buf[VAEncCodedBufferType];
301     codedbuf->size = file_stat.st_size;
302     codedbuf->bit_offset = 0;
303     codedbuf->status = 0;
304     codedbuf->reserved = 0;
305     codedbuf->buf = fool_ctx->segbuf_jpg;
306     codedbuf->next = NULL;
307
308     return 0;
309 }
310
311
312 static int va_FoolFillCodedBuf(struct fool_context *fool_ctx)
313 {
314     if (fool_ctx->entrypoint == VAEntrypointEncSlice)
315         va_FoolFillCodedBufEnc(fool_ctx);
316     else if (fool_ctx->entrypoint == VAEntrypointEncPicture)
317         va_FoolFillCodedBufJPG(fool_ctx);
318         
319     return 0;
320 }
321
322
323 VAStatus va_FoolMapBuffer(
324     VADisplay dpy,
325     VABufferID buf_id,  /* in */
326     void **pbuf         /* out */
327 )
328 {
329     unsigned int buftype = buf_id & 0xff;
330     unsigned int magic = buf_id & FOOL_BUFID_MASK;
331     DPY2FOOLCTX(dpy);
332
333     if (magic != FOOL_BUFID_MAGIC || buftype >= VABufferTypeMax || !pbuf)
334         return 0;
335
336     /* buf_id is the buffer type */
337     *pbuf = fool_ctx->fool_buf[buftype];
338
339     /* it is coded buffer, fill the fake segment buf from file */
340     if (*pbuf && (buftype == VAEncCodedBufferType))
341         va_FoolFillCodedBuf(fool_ctx);
342     
343     return 1; /* don't call into driver */
344 }
345
346 VAStatus va_FoolUnmapBuffer(
347         VADisplay dpy,
348         VABufferID buf_id       /* in */
349 )
350 {
351     unsigned int magic = buf_id & FOOL_BUFID_MASK;
352
353     if (magic != FOOL_BUFID_MAGIC)
354         return 0;
355
356     return 1;
357 }