OSDN Git Service

va.h: fix comments error for arbitrary number of MBs per slice.
[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_trace.h"
30 #include "va_fool.h"
31
32 #include <assert.h>
33 #include <stdarg.h>
34 #include <stdlib.h>
35 #include <stdio.h>
36 #include <errno.h>
37 #include <string.h>
38 #include <dlfcn.h>
39 #include <unistd.h>
40 #include <sys/types.h>
41 #include <sys/stat.h>
42 #include <unistd.h>
43 #include <time.h>
44 #include <fcntl.h>
45
46 /*
47  * Do dummy decode/encode, ignore the input data
48  * In order to debug memory leak or low performance issues, we need to isolate driver problems
49  * We export env "VA_FOOL", with which, we can do fake decode/encode:
50  *
51  * LIBVA_FOOL_DECODE:
52  * . if set, decode does nothing
53  * LIBVA_FOOL_ENCODE=<framename>:
54  * . if set, encode does nothing, but fill in the coded buffer from the content of files with
55  *   name framename.0,framename.1,..., framename.N, framename.0,..., framename.N,...repeatly
56  *   Use file name to determine h264 or vp8
57  * LIBVA_FOOL_JPEG=<framename>:fill the content of filename to codedbuf for jpeg encoding
58  * LIBVA_FOOL_POSTP:
59  * . if set, do nothing for vaPutSurface
60  */
61
62
63 /* global settings */
64 int fool_codec = 0;
65 int fool_postp  = 0;
66
67 #define FOOL_BUFID_MAGIC   0x12345600
68 #define FOOL_BUFID_MASK    0xffffff00
69
70 struct fool_context {
71     int enabled; /* fool_codec is global, and it is for concurent encode/decode */
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 */
74     int file_count;
75
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 */
78
79     VAEntrypoint entrypoint; /* current entrypoint */
80     
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
85      */
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 */
90     VAContextID context;
91 };
92
93 #define FOOL_CTX(dpy) ((struct fool_context *)((VADisplayContextP)dpy)->vafool)
94
95 #define DPY2FOOLCTX(dpy)                                 \
96     struct fool_context *fool_ctx = FOOL_CTX(dpy);       \
97     if (fool_ctx == NULL)                                \
98         return 0; /* no fool for the context */          \
99
100 #define DPY2FOOLCTX_CHK(dpy)                             \
101     struct fool_context *fool_ctx = FOOL_CTX(dpy);       \
102     if ((fool_ctx == NULL) || (fool_ctx->enabled == 0))  \
103         return 0; /* no fool for the context */          \
104
105 /* Prototype declarations (functions defined in va.c) */
106
107 void va_errorMessage(const char *msg, ...);
108 void va_infoMessage(const char *msg, ...);
109
110 int  va_parseConfig(char *env, char *env_value);
111
112 void va_FoolInit(VADisplay dpy)
113 {
114     char env_value[1024];
115
116     struct fool_context *fool_ctx = calloc(sizeof(struct fool_context), 1);
117     
118     if (fool_ctx == NULL)
119         return;
120     
121     if (va_parseConfig("LIBVA_FOOL_POSTP", NULL) == 0) {
122         fool_postp = 1;
123         va_infoMessage("LIBVA_FOOL_POSTP is on, dummy vaPutSurface\n");
124     }
125     
126     if (va_parseConfig("LIBVA_FOOL_DECODE", NULL) == 0) {
127         fool_codec  |= VA_FOOL_FLAG_DECODE;
128         va_infoMessage("LIBVA_FOOL_DECODE is on, dummy decode\n");
129     }
130     if (va_parseConfig("LIBVA_FOOL_ENCODE", &env_value[0]) == 0) {
131         fool_codec  |= VA_FOOL_FLAG_ENCODE;
132         fool_ctx->fn_enc = strdup(env_value);
133         va_infoMessage("LIBVA_FOOL_ENCODE is on, load encode data from file with patten %s\n",
134                        fool_ctx->fn_enc);
135     }
136     if (va_parseConfig("LIBVA_FOOL_JPEG", &env_value[0]) == 0) {
137         fool_codec  |= VA_FOOL_FLAG_JPEG;
138         fool_ctx->fn_jpg = strdup(env_value);
139         va_infoMessage("LIBVA_FOOL_JPEG is on, load encode data from file with patten %s\n",
140                        fool_ctx->fn_jpg);
141     }
142     
143     ((VADisplayContextP)dpy)->vafool = fool_ctx;
144 }
145
146
147 int va_FoolEnd(VADisplay dpy)
148 {
149     int i;
150     DPY2FOOLCTX(dpy);
151
152     for (i = 0; i < VABufferTypeMax; i++) {/* free memory */
153         if (fool_ctx->fool_buf[i])
154             free(fool_ctx->fool_buf[i]);
155     }
156     if (fool_ctx->segbuf_enc)
157         free(fool_ctx->segbuf_enc);
158     if (fool_ctx->segbuf_jpg)
159         free(fool_ctx->segbuf_jpg);
160     if (fool_ctx->fn_enc)
161         free(fool_ctx->fn_enc);
162     if (fool_ctx->fn_jpg)
163         free(fool_ctx->fn_jpg);
164
165     free(fool_ctx);
166     ((VADisplayContextP)dpy)->vafool = NULL;
167     
168     return 0;
169 }
170
171 int va_FoolCreateConfig(
172         VADisplay dpy,
173         VAProfile profile, 
174         VAEntrypoint entrypoint, 
175         VAConfigAttrib *attrib_list,
176         int num_attribs,
177         VAConfigID *config_id /* out */
178 )
179 {
180     DPY2FOOLCTX(dpy);
181
182     fool_ctx->entrypoint = entrypoint;
183     
184     /*
185      * check fool_codec to align with current context
186      * e.g. fool_codec = decode then for encode, the
187      * vaBegin/vaRender/vaEnd also run into fool path
188      * which is not desired
189      */
190     if (((fool_codec & VA_FOOL_FLAG_DECODE) && (entrypoint == VAEntrypointVLD)) ||
191         ((fool_codec & VA_FOOL_FLAG_JPEG) && (entrypoint == VAEntrypointEncPicture)))
192         fool_ctx->enabled = 1;
193     else if ((fool_codec & VA_FOOL_FLAG_ENCODE) && (entrypoint == VAEntrypointEncSlice)) {
194         /* H264 is desired */
195         if (((profile == VAProfileH264Baseline ||
196               profile == VAProfileH264Main ||
197               profile == VAProfileH264High ||
198               profile == VAProfileH264ConstrainedBaseline)) &&
199             strstr(fool_ctx->fn_enc, "h264"))
200             fool_ctx->enabled = 1;
201
202         /* vp8 is desired */
203         if ((profile == VAProfileVP8Version0_3) &&
204             strstr(fool_ctx->fn_enc, "vp8"))
205             fool_ctx->enabled = 1;
206     }
207     if (fool_ctx->enabled)
208         va_infoMessage("FOOL is enabled for this context\n");
209     else
210         va_infoMessage("FOOL is not enabled for this context\n");
211
212     
213     return 0; /* continue */
214 }
215
216
217 VAStatus va_FoolCreateBuffer(
218     VADisplay dpy,
219     VAContextID context,        /* in */
220     VABufferType type,          /* in */
221     unsigned int size,          /* in */
222     unsigned int num_elements,  /* in */
223     void *data,                 /* in */
224     VABufferID *buf_id          /* out */
225 )
226 {
227     unsigned int new_size = size * num_elements;
228     unsigned int old_size;
229     DPY2FOOLCTX_CHK(dpy);
230
231     old_size = fool_ctx->fool_buf_size[type] * fool_ctx->fool_buf_element[type];
232
233     if (old_size < new_size)
234         fool_ctx->fool_buf[type] = realloc(fool_ctx->fool_buf[type], new_size);
235     
236     fool_ctx->fool_buf_size[type] = size;
237     fool_ctx->fool_buf_element[type] = num_elements;
238     fool_ctx->fool_buf_count[type]++;
239     /* because we ignore the vaRenderPicture, 
240      * all buffers with same type share same real memory
241      * bufferID = (magic number) | type
242      */
243     *buf_id = FOOL_BUFID_MAGIC | type;
244
245     return 1; /* don't call into driver */
246 }
247
248 VAStatus va_FoolBufferInfo(
249     VADisplay dpy,
250     VABufferID buf_id,  /* in */
251     VABufferType *type, /* out */
252     unsigned int *size,         /* out */
253     unsigned int *num_elements /* out */
254 )
255 {
256     unsigned int magic;
257     
258     DPY2FOOLCTX_CHK(dpy);
259
260     magic = buf_id & FOOL_BUFID_MASK;
261     if (magic != FOOL_BUFID_MAGIC)
262         return 0; /* could be VAImageBufferType from vaDeriveImage */
263     
264     *type = buf_id & 0xff;
265     *size = fool_ctx->fool_buf_size[*type];
266     *num_elements = fool_ctx->fool_buf_element[*type];;
267     
268     return 1; /* fool is valid */
269 }
270
271 static int va_FoolFillCodedBufEnc(struct fool_context *fool_ctx)
272 {
273     char file_name[1024];
274     struct stat file_stat = {0};
275     VACodedBufferSegment *codedbuf;
276     int i, fd = -1;
277
278     /* try file_name.file_count, if fail, try file_name.file_count-- */
279     for (i=0; i<=1; i++) {
280         snprintf(file_name, 1024, "%s.%d",
281                  fool_ctx->fn_enc,
282                  fool_ctx->file_count);
283
284         if ((fd = open(file_name, O_RDONLY)) != -1) {
285             fstat(fd, &file_stat);
286             fool_ctx->file_count++; /* open next file */
287             break;
288         } else /* fall back to the first file file */
289             fool_ctx->file_count = 0;
290     }
291     if (fd != -1) {
292         fool_ctx->segbuf_enc = realloc(fool_ctx->segbuf_enc, file_stat.st_size);
293         read(fd, fool_ctx->segbuf_enc, file_stat.st_size);
294         close(fd);
295     } else
296         va_errorMessage("Open file %s failed:%s\n", file_name, strerror(errno));
297
298     codedbuf = (VACodedBufferSegment *)fool_ctx->fool_buf[VAEncCodedBufferType];
299     codedbuf->size = file_stat.st_size;
300     codedbuf->bit_offset = 0;
301     codedbuf->status = 0;
302     codedbuf->reserved = 0;
303     codedbuf->buf = fool_ctx->segbuf_enc;
304     codedbuf->next = NULL;
305
306     return 0;
307 }
308
309 static int va_FoolFillCodedBufJPG(struct fool_context *fool_ctx)
310 {
311     struct stat file_stat = {0};
312     VACodedBufferSegment *codedbuf;
313     int fd = -1;
314
315     if ((fd = open(fool_ctx->fn_jpg, O_RDONLY)) != -1) {
316         fstat(fd, &file_stat);
317         fool_ctx->segbuf_jpg = realloc(fool_ctx->segbuf_jpg, file_stat.st_size);
318         read(fd, fool_ctx->segbuf_jpg, file_stat.st_size);
319         close(fd);
320     } else
321         va_errorMessage("Open file %s failed:%s\n", fool_ctx->fn_jpg, strerror(errno));
322
323     codedbuf = (VACodedBufferSegment *)fool_ctx->fool_buf[VAEncCodedBufferType];
324     codedbuf->size = file_stat.st_size;
325     codedbuf->bit_offset = 0;
326     codedbuf->status = 0;
327     codedbuf->reserved = 0;
328     codedbuf->buf = fool_ctx->segbuf_jpg;
329     codedbuf->next = NULL;
330
331     return 0;
332 }
333
334
335 static int va_FoolFillCodedBuf(struct fool_context *fool_ctx)
336 {
337     if (fool_ctx->entrypoint == VAEntrypointEncSlice)
338         va_FoolFillCodedBufEnc(fool_ctx);
339     else if (fool_ctx->entrypoint == VAEntrypointEncPicture)
340         va_FoolFillCodedBufJPG(fool_ctx);
341         
342     return 0;
343 }
344
345
346 VAStatus va_FoolMapBuffer(
347     VADisplay dpy,
348     VABufferID buf_id,  /* in */
349     void **pbuf         /* out */
350 )
351 {
352     unsigned int magic, buftype;
353     DPY2FOOLCTX_CHK(dpy);
354
355     magic = buf_id & FOOL_BUFID_MASK;
356     if (magic != FOOL_BUFID_MAGIC)
357         return 0; /* could be VAImageBufferType from vaDeriveImage */
358     
359     buftype = buf_id & 0xff;
360     *pbuf = fool_ctx->fool_buf[buftype];
361
362     /* it is coded buffer, fill coded segment from file */
363     if (*pbuf && (buftype == VAEncCodedBufferType))
364         va_FoolFillCodedBuf(fool_ctx);
365     
366     return 1; /* fool is valid */
367 }
368
369 VAStatus va_FoolCheckContinuity(VADisplay dpy)
370 {
371     DPY2FOOLCTX_CHK(dpy);
372
373     return 1; /* fool is valid */
374 }
375