OSDN Git Service

Remove incorrect "BPP" suffix from 10-bit render target formats
[android-x86/hardware-intel-common-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 "sysdeps.h"
27 #include "va.h"
28 #include "va_backend.h"
29 #include "va_internal.h"
30 #include "va_trace.h"
31 #include "va_fool.h"
32
33 #include <assert.h>
34 #include <stdarg.h>
35 #include <stdlib.h>
36 #include <stdio.h>
37 #include <errno.h>
38 #include <string.h>
39 #include <dlfcn.h>
40 #include <unistd.h>
41 #include <sys/types.h>
42 #include <sys/stat.h>
43 #include <unistd.h>
44 #include <time.h>
45 #include <fcntl.h>
46
47 /*
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:
51  *
52  * LIBVA_FOOL_DECODE:
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
59  * LIBVA_FOOL_POSTP:
60  * . if set, do nothing for vaPutSurface
61  */
62
63
64 /* global settings */
65 int va_fool_codec = 0;
66 int va_fool_postp  = 0;
67
68 #define FOOL_BUFID_MAGIC   0x12345600
69 #define FOOL_BUFID_MASK    0xffffff00
70
71 struct fool_context {
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 */
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 };
93
94 #define FOOL_CTX(dpy) ((struct fool_context *)((VADisplayContextP)dpy)->vafool)
95
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 */          \
100
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 */          \
105
106
107 void va_FoolInit(VADisplay dpy)
108 {
109     char env_value[1024];
110
111     struct fool_context *fool_ctx = calloc(sizeof(struct fool_context), 1);
112     
113     if (fool_ctx == NULL)
114         return;
115     
116     if (va_parseConfig("LIBVA_FOOL_POSTP", NULL) == 0) {
117         va_fool_postp = 1;
118         va_infoMessage(dpy, "LIBVA_FOOL_POSTP is on, dummy vaPutSurface\n");
119     }
120     
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");
124     }
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",
129                        fool_ctx->fn_enc);
130     }
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",
135                        fool_ctx->fn_jpg);
136     }
137     
138     ((VADisplayContextP)dpy)->vafool = fool_ctx;
139 }
140
141
142 int va_FoolEnd(VADisplay dpy)
143 {
144     int i;
145     DPY2FOOLCTX(dpy);
146
147     for (i = 0; i < VABufferTypeMax; i++) {/* free memory */
148         if (fool_ctx->fool_buf[i])
149             free(fool_ctx->fool_buf[i]);
150     }
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);
159
160     free(fool_ctx);
161     ((VADisplayContextP)dpy)->vafool = NULL;
162     
163     return 0;
164 }
165
166 int va_FoolCreateConfig(
167         VADisplay dpy,
168         VAProfile profile, 
169         VAEntrypoint entrypoint, 
170         VAConfigAttrib *attrib_list,
171         int num_attribs,
172         VAConfigID *config_id /* out */
173 )
174 {
175     DPY2FOOLCTX(dpy);
176
177     fool_ctx->entrypoint = entrypoint;
178     
179     /*
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
184      */
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;
195
196         /* vp8 is desired */
197         if ((profile == VAProfileVP8Version0_3) &&
198             strstr(fool_ctx->fn_enc, "vp8"))
199             fool_ctx->enabled = 1;
200     }
201     if (fool_ctx->enabled)
202         va_infoMessage(dpy, "FOOL is enabled for this context\n");
203     else
204         va_infoMessage(dpy, "FOOL is not enabled for this context\n");
205
206     
207     return 0; /* continue */
208 }
209
210
211 VAStatus va_FoolCreateBuffer(
212     VADisplay dpy,
213     VAContextID context,        /* in */
214     VABufferType type,          /* in */
215     unsigned int size,          /* in */
216     unsigned int num_elements,  /* in */
217     void *data,                 /* in */
218     VABufferID *buf_id          /* out */
219 )
220 {
221     unsigned int new_size = size * num_elements;
222     unsigned int old_size;
223     DPY2FOOLCTX_CHK(dpy);
224
225     old_size = fool_ctx->fool_buf_size[type] * fool_ctx->fool_buf_element[type];
226
227     if (old_size < new_size)
228         fool_ctx->fool_buf[type] = realloc(fool_ctx->fool_buf[type], new_size);
229     
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
236      */
237     *buf_id = FOOL_BUFID_MAGIC | type;
238
239     return 1; /* don't call into driver */
240 }
241
242 VAStatus va_FoolBufferInfo(
243     VADisplay dpy,
244     VABufferID buf_id,  /* in */
245     VABufferType *type, /* out */
246     unsigned int *size,         /* out */
247     unsigned int *num_elements /* out */
248 )
249 {
250     unsigned int magic;
251     
252     DPY2FOOLCTX_CHK(dpy);
253
254     magic = buf_id & FOOL_BUFID_MASK;
255     if (magic != FOOL_BUFID_MAGIC)
256         return 0; /* could be VAImageBufferType from vaDeriveImage */
257     
258     *type = buf_id & 0xff;
259     *size = fool_ctx->fool_buf_size[*type];
260     *num_elements = fool_ctx->fool_buf_element[*type];;
261     
262     return 1; /* fool is valid */
263 }
264
265 static int va_FoolFillCodedBufEnc(VADisplay dpy, struct fool_context *fool_ctx)
266 {
267     char file_name[1024];
268     struct stat file_stat = {0};
269     VACodedBufferSegment *codedbuf;
270     int i, fd = -1;
271     ssize_t ret;
272
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",
276                  fool_ctx->fn_enc,
277                  fool_ctx->file_count);
278
279         if ((fd = open(file_name, O_RDONLY)) != -1) {
280             if (fstat(fd, &file_stat) != -1) {
281                 fool_ctx->file_count++; /* open next file */
282                 break;
283             }
284             va_errorMessage(dpy, "Identify file %s failed:%s\n",
285                             file_name, strerror(errno));
286             close(fd);
287             fd = -1;
288         }
289         /* fall back to the first file file */
290         fool_ctx->file_count = 0;
291     }
292     if (fd != -1) {
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);
297         close(fd);
298     } else
299         va_errorMessage(dpy, "Open file %s failed:%s\n", file_name, strerror(errno));
300
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;
308
309     return 0;
310 }
311
312 static int va_FoolFillCodedBufJPG(VADisplay dpy, struct fool_context *fool_ctx)
313 {
314     struct stat file_stat = {0};
315     VACodedBufferSegment *codedbuf;
316     int fd = -1;
317     ssize_t ret;
318
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);
325         } else {
326             va_errorMessage(dpy, "Identify file %s failed:%s\n",
327                             fool_ctx->fn_jpg, strerror(errno));
328         }
329         close(fd);
330     } else
331         va_errorMessage(dpy, "Open file %s failed:%s\n", fool_ctx->fn_jpg, strerror(errno));
332
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;
340
341     return 0;
342 }
343
344
345 static int va_FoolFillCodedBuf(VADisplay dpy, struct fool_context *fool_ctx)
346 {
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);
351         
352     return 0;
353 }
354
355
356 VAStatus va_FoolMapBuffer(
357     VADisplay dpy,
358     VABufferID buf_id,  /* in */
359     void **pbuf         /* out */
360 )
361 {
362     unsigned int magic, buftype;
363     DPY2FOOLCTX_CHK(dpy);
364
365     magic = buf_id & FOOL_BUFID_MASK;
366     if (magic != FOOL_BUFID_MAGIC)
367         return 0; /* could be VAImageBufferType from vaDeriveImage */
368     
369     buftype = buf_id & 0xff;
370     *pbuf = fool_ctx->fool_buf[buftype];
371
372     /* it is coded buffer, fill coded segment from file */
373     if (*pbuf && (buftype == VAEncCodedBufferType))
374         va_FoolFillCodedBuf(dpy, fool_ctx);
375     
376     return 1; /* fool is valid */
377 }
378
379 VAStatus va_FoolCheckContinuity(VADisplay dpy)
380 {
381     DPY2FOOLCTX_CHK(dpy);
382
383     return 1; /* fool is valid */
384 }
385