OSDN Git Service

1) cleanup for VA_FOOL
[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 "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 <string.h>
36 #include <dlfcn.h>
37 #include <unistd.h>
38 #include <sys/types.h>
39 #include <sys/stat.h>
40 #include <unistd.h>
41 #include <time.h>
42
43 /*
44  * Do dummy decode/encode, ignore the input data
45  * In order to debug memory leak or low performance issues, we need to isolate driver problems
46  * We export env "VA_FOOL", with which, we can do fake decode/encode:
47  *
48  * LIBVA_FOOL_DECODE:
49  * . if set, decode does nothing, but fill in some YUV data
50  * LIBVA_FOOL_ENCODE=<clip name>:
51  * . if set, encode does nothing, but fill in the coded buffer from a H264 clip.
52  * . VA CONTEXT/CONFIG/SURFACE will call into drivers, but VA Buffer creation is done in here
53  * . Bypass all "vaBeginPic/vaRenderPic/vaEndPic"
54  * LIBVA_FOOL_POSTP:
55  * . if set, do nothing for vaPutSurface
56  */
57
58
59 /* global settings */
60
61 /* LIBVA_FOOL_DECODE/LIBVA_FOOL_ENCODE/LIBVA_FOOL_POSTP */
62 int fool_decode = 0;
63 int fool_encode = 0;
64 int fool_postp  = 0;
65
66
67
68 #define NAL_BUF_SIZE  65536  // maximum NAL unit size
69 #define RING_BUF_SIZE  8192  // input ring buffer size, MUST be a power of two!
70 #define MAX_FRAME 16
71 #define SLICE_NUM 4
72
73 #define FOOL_CONTEXT_MAX 4
74 /* per context settings */
75 static struct _fool_context {
76     VADisplay dpy; /* should use context as the key */
77
78     VAProfile fool_profile; /* current profile for buffers */
79     VAEntrypoint fool_entrypoint; /* current entrypoint */
80
81     FILE *fool_fp_codedclip; /* load a clip from disk for fooling encode*/
82     char *frame_buf;
83     VACodedBufferSegment *codebuf;
84
85     /* all buffers with same type share one malloc-ed memory
86      * bufferID = (buffer numbers with the same type << 8) || type
87      * the malloc-ed memory can be find by fool_buf[bufferID & 0xff]
88      * the size is ignored here
89      */
90     char *fool_buf[VABufferTypeMax]; /* memory of fool buffers */
91     unsigned int fool_buf_size[VABufferTypeMax]; /* size of memory of fool buffers */
92     unsigned int fool_buf_count[VABufferTypeMax]; /* count of created buffers */
93     VAContextID context;
94 } fool_context[FOOL_CONTEXT_MAX] = { {0} }; /* trace five context at the same time */
95
96 #define FOOL_DECODE(idx) (fool_decode && (fool_context[idx].fool_entrypoint == VAEntrypointVLD))
97 #define FOOL_ENCODE(idx)                                                \
98     (fool_encode                                                        \
99      && (fool_context[idx].fool_entrypoint == VAEntrypointEncSlice)     \
100      && (fool_context[idx].fool_profile >= VAProfileH264Baseline)       \
101      && (fool_context[idx].fool_profile <= VAProfileH264High))
102
103
104
105 #define DPY2INDEX(dpy)                                  \
106     int idx;                                            \
107                                                         \
108     for (idx = 0; idx < FOOL_CONTEXT_MAX; idx++)        \
109         if (fool_context[idx].dpy == dpy)               \
110             break;                                      \
111                                                         \
112     if (idx == FOOL_CONTEXT_MAX)                        \
113         return 0;  /* let driver go */
114
115
116 /* Prototype declarations (functions defined in va.c) */
117
118 void va_errorMessage(const char *msg, ...);
119 void va_infoMessage(const char *msg, ...);
120
121 int va_parseConfig(char *env, char *env_value);
122
123 VAStatus vaBufferInfo(
124         VADisplay dpy,
125         VAContextID context,    /* in */
126         VABufferID buf_id,              /* in */
127         VABufferType *type,             /* out */
128         unsigned int *size,             /* out */
129         unsigned int *num_elements      /* out */
130 );
131
132 VAStatus vaLockSurface(VADisplay dpy,
133         VASurfaceID surface,
134         unsigned int *fourcc, /* following are output argument */
135         unsigned int *luma_stride,
136         unsigned int *chroma_u_stride,
137         unsigned int *chroma_v_stride,
138         unsigned int *luma_offset,
139         unsigned int *chroma_u_offset,
140         unsigned int *chroma_v_offset,
141         unsigned int *buffer_name,
142         void **buffer 
143 );
144
145 VAStatus vaUnlockSurface(VADisplay dpy,
146         VASurfaceID surface
147 );
148
149
150 void va_FoolInit(VADisplay dpy)
151 {
152     char env_value[1024];
153     int fool_index = 0;
154
155     for (fool_index = 0; fool_index < FOOL_CONTEXT_MAX; fool_index++)
156         if (fool_context[fool_index].dpy == 0)
157             break;
158
159     if (fool_index == FOOL_CONTEXT_MAX)
160         return;
161
162     if (va_parseConfig("LIBVA_FOOL_POSTP", NULL) == 0) {
163         fool_postp = 1;
164         va_infoMessage("LIBVA_FOOL_POSTP is on, dummy vaPutSurface\n");
165     }
166
167
168     if (va_parseConfig("LIBVA_FOOL_DECODE", NULL) == 0) {
169         fool_decode = 1;
170         va_infoMessage("LIBVA_FOOL_DECODE is on, dummy decode\n");
171     }
172
173
174     if (va_parseConfig("LIBVA_FOOL_ENCODE", &env_value[0]) == 0) {
175         fool_context[fool_index].fool_fp_codedclip = fopen(env_value, "r");
176
177         if (fool_context[fool_index].fool_fp_codedclip) {
178             fool_encode = 1;
179         } else
180             fool_encode = 0;
181
182         if (fool_encode) /* malloc the buffer for fake clip */
183         {
184             fool_context[fool_index].frame_buf = malloc(MAX_FRAME*SLICE_NUM*NAL_BUF_SIZE*sizeof(char));
185             fool_context[fool_index].codebuf = malloc(sizeof(VACodedBufferSegment));
186         }
187
188         if (fool_context[fool_index].frame_buf == NULL)
189             fool_encode = 0;
190
191         if (fool_encode)
192             va_infoMessage("LIBVA_FOOL_ENCODE is on, dummy encode\n");
193
194     }
195
196     if (fool_encode || fool_decode)
197         fool_context[fool_index].dpy = dpy;
198 }
199
200
201 int va_FoolEnd(VADisplay dpy)
202 {
203     int i;
204
205     DPY2INDEX(dpy);
206
207     for (i = 0; i < VABufferTypeMax; i++) {/* free memory */
208         if (fool_context[idx].fool_buf[i])
209             free(fool_context[idx].fool_buf[i]);
210     }
211     if (fool_context[idx].fool_fp_codedclip)
212         fclose(fool_context[idx].fool_fp_codedclip);
213
214     if (fool_context[idx].frame_buf)
215         free(fool_context[idx].frame_buf);
216     
217     if (fool_context[idx].codebuf)
218         free(fool_context[idx].codebuf);
219
220     memset(&fool_context[idx], sizeof(struct _fool_context), 0);
221     return 0;
222 }
223
224 int va_FoolCodedBuf(VADisplay dpy)
225 {
226     /* do nothing */
227     return 0;
228 }
229
230
231 int va_FoolCreateConfig(
232         VADisplay dpy,
233         VAProfile profile, 
234         VAEntrypoint entrypoint, 
235         VAConfigAttrib *attrib_list,
236         int num_attribs,
237         VAConfigID *config_id /* out */
238 )
239 {
240     DPY2INDEX(dpy);
241
242     /* call into driver level to allocate real context/surface/buffers, etc */
243     fool_context[idx].fool_profile = profile;
244     fool_context[idx].fool_entrypoint = entrypoint;
245     return 0;
246 }
247
248 static int yuvgen_planar(
249         int width, int height,
250         unsigned char *Y_start, int Y_pitch,
251         unsigned char *U_start, int U_pitch,
252         unsigned char *V_start, int V_pitch,
253         int UV_interleave, int box_width, int row_shift,
254         int field
255 )
256 {
257     int row;
258
259     /* copy Y plane */
260     for (row=0;row<height;row++) {
261         unsigned char *Y_row = Y_start + row * Y_pitch;
262         int jj, xpos, ypos;
263
264         ypos = (row / box_width) & 0x1;
265
266         /* fill garbage data into the other field */
267         if (((field == VA_TOP_FIELD) && (row &1))
268                 || ((field == VA_BOTTOM_FIELD) && ((row &1)==0))) { 
269             memset(Y_row, 0xff, width);
270             continue;
271         }
272
273         for (jj=0; jj<width; jj++) {
274             xpos = ((row_shift + jj) / box_width) & 0x1;
275
276             if ((xpos == 0) && (ypos == 0))
277                 Y_row[jj] = 0xeb;
278             if ((xpos == 1) && (ypos == 1))
279                 Y_row[jj] = 0xeb;
280
281             if ((xpos == 1) && (ypos == 0))
282                 Y_row[jj] = 0x10;
283             if ((xpos == 0) && (ypos == 1))
284                 Y_row[jj] = 0x10;
285         }
286     }
287
288     /* copy UV data */
289     for( row =0; row < height/2; row++) {
290         unsigned short value = 0x80;
291
292         /* fill garbage data into the other field */
293         if (((field == VA_TOP_FIELD) && (row &1))
294                 || ((field == VA_BOTTOM_FIELD) && ((row &1)==0))) {
295             value = 0xff;
296         }
297
298         if (UV_interleave) {
299             unsigned short *UV_row = (unsigned short *)(U_start + row * U_pitch);
300
301             memset(UV_row, value, width);
302         } else {
303             unsigned char *U_row = U_start + row * U_pitch;
304             unsigned char *V_row = V_start + row * V_pitch;
305
306             memset (U_row,value,width/2);
307             memset (V_row,value,width/2);
308         }
309     }
310
311     return 0;
312 }
313
314
315 int va_FoolCreateSurfaces(
316         VADisplay dpy,
317         int width,
318         int height,
319         int format,
320         int num_surfaces,
321         VASurfaceID *surfaces   /* out */
322 )
323 {
324     int i;
325     unsigned int fourcc; /* following are output argument */
326     unsigned int luma_stride;
327     unsigned int chroma_u_stride;
328     unsigned int chroma_v_stride;
329     unsigned int luma_offset;
330     unsigned int chroma_u_offset;
331     unsigned int chroma_v_offset;
332     unsigned int buffer_name;
333     void *buffer = NULL;
334     unsigned char *Y_data, *U_data, *V_data;
335
336     int box_width = num_surfaces/2;
337     int row_shift = 0;
338     VAStatus va_status;
339
340     DPY2INDEX(dpy);
341
342     if (FOOL_DECODE(idx)) { 
343         /* call into driver level to allocate real context/surface/buffers, etc
344          * fill in the YUV data, will be overwrite if it is encode context
345          */
346         for (i = 0; i < num_surfaces; i++) {
347             /* fool decoder: fill with auto-generated YUV data */
348             va_status = vaLockSurface(dpy, surfaces[i], &fourcc,
349                     &luma_stride, &chroma_u_stride, &chroma_v_stride,
350                     &luma_offset, &chroma_u_offset, &chroma_v_offset,
351                     &buffer_name, &buffer);
352
353             if (va_status != VA_STATUS_SUCCESS)
354                 return 0;
355
356             if (!buffer) {
357                 vaUnlockSurface(dpy, surfaces[i]);
358                 return 0;
359             }
360
361             Y_data = buffer;
362
363             /* UV should be same for NV12 */
364             U_data = buffer + chroma_u_offset;
365             V_data = buffer + chroma_v_offset;
366
367             yuvgen_planar(width, height,
368                     Y_data, luma_stride,
369                     U_data, chroma_v_stride,
370                     V_data, chroma_v_stride,
371                     (fourcc==VA_FOURCC_NV12),
372                     box_width, row_shift, 0);
373
374             vaUnlockSurface(dpy, surfaces[i]);
375
376             row_shift++;
377             if (row_shift==(2*box_width))
378                 row_shift= 0;
379         }
380         return 0; /* the return value is ignored */
381     }
382     return 0; /* the return value is ignored */
383 }
384
385 VAStatus va_FoolCreateBuffer (
386         VADisplay dpy,
387         VAContextID context,    /* in */
388         VABufferType type,              /* in */
389         unsigned int size,              /* in */
390         unsigned int num_elements,      /* in */
391         void *data,                     /* in */
392         VABufferID *buf_id              /* out */
393 )
394 {
395     DPY2INDEX(dpy);
396
397     if (FOOL_ENCODE(idx) || FOOL_DECODE(idx)) { /* fool buffer creation */
398         int new_size = size * num_elements;
399
400         if (type == VAEncCodedBufferType) /* only a VACodedBufferSegment */
401             new_size = sizeof(VACodedBufferSegment);
402
403         if (fool_context[idx].fool_buf_size[type] == 0)
404             fool_context[idx].fool_buf[type] = calloc(1, new_size);
405         else if (fool_context[idx].fool_buf_size[type] <= new_size)
406             fool_context[idx].fool_buf[type] = realloc(fool_context[idx].fool_buf, new_size);
407
408         if (fool_context[idx].fool_buf[type] == NULL) {
409             va_FoolEnd(dpy);
410             return 0; /* let driver go */
411         }
412
413         /* because we ignore the vaRenderPicture, 
414          * all buffers with same type share same real memory
415          * bufferID = (buffer count << 8) | type
416          */
417         fool_context[idx].fool_buf_count[type]++;
418         *buf_id = (fool_context[idx].fool_buf_count[type] << 8) | type;
419
420         return 1; /* don't call into driver */
421     }
422
423     return 0; /* let driver go ... */
424 }
425
426 VAStatus va_FoolMapBuffer (
427         VADisplay dpy,
428         VABufferID buf_id,      /* in */
429         void **pbuf     /* out */
430 )
431 {
432     VABufferType type;
433     unsigned int size,frame_size = 0;
434     unsigned int num_elements;
435     DPY2INDEX(dpy);
436
437     if (FOOL_ENCODE(idx) || FOOL_DECODE(idx)) { /* fool buffer creation */
438         unsigned int buf_idx = buf_id & 0xff;
439
440         /* Image buffer? */
441         vaBufferInfo(dpy, fool_context[idx].context, buf_id, &type, &size, &num_elements);
442         if (type == VAImageBufferType  && FOOL_ENCODE(idx))
443             return 0;
444
445         /* buf_id is the buffer type */
446         if (fool_context[idx].fool_buf[buf_idx] != NULL)
447             *pbuf = fool_context[idx].fool_buf[buf_idx];
448         else
449             *pbuf = NULL;
450
451         /* expect APP to MapBuffer when get the the coded data */
452         if (*pbuf && (buf_idx == VAEncCodedBufferType)) { /* it is coded buffer */
453             /* read from a clip */
454             frame_size = va_FoolGetFrame(fool_context[idx].fool_fp_codedclip,
455                     fool_context[idx].frame_buf);
456
457             memset(fool_context[idx].codebuf,0,sizeof(VACodedBufferSegment));
458             fool_context[idx].codebuf->size = frame_size;
459             fool_context[idx].codebuf->bit_offset = 0;
460             fool_context[idx].codebuf->status = 0;
461             fool_context[idx].codebuf->reserved = 0;
462             fool_context[idx].codebuf->buf = fool_context[idx].frame_buf;
463             fool_context[idx].codebuf->next = NULL;
464             *pbuf = fool_context[idx].codebuf;
465         }
466         return 1; /* don't call into driver */
467     }
468
469     return 0; /* let driver go ... */
470 }
471
472
473 int va_FoolBeginPicture(
474         VADisplay dpy,
475         VAContextID context,
476         VASurfaceID render_target
477 )
478 {
479     DPY2INDEX(dpy);
480
481     if (FOOL_ENCODE(idx) || FOOL_DECODE(idx)) {
482         if (fool_context[idx].context == 0)
483             fool_context[idx].context = context;
484         return 1; /* don't call into driver level */
485     }
486
487     return 0; /* let driver go ... */
488 }
489
490 int va_FoolRenderPicture(
491         VADisplay dpy,
492         VAContextID context,
493         VABufferID *buffers,
494         int num_buffers
495 )
496 {
497     DPY2INDEX(dpy);
498
499     if (FOOL_ENCODE(idx) || FOOL_DECODE(idx))
500         return 1; /* don't call into driver level */
501
502     return 0;  /* let driver go ... */
503 }
504
505
506 int va_FoolEndPicture(
507         VADisplay dpy,
508         VAContextID context
509 )
510 {
511     DPY2INDEX(dpy);
512
513     /* don't call into driver level */
514
515     /* do real fooling operation here */
516
517     /* only support H264 encoding currently */
518     if (FOOL_ENCODE(idx)) {
519         /* expect vaMapBuffer will handle it
520          * or else, need to save the codedbuf ID,
521          * and fool encode it here
522          */
523         /* va_FoolCodedBuf(dpy); */
524         return 1; /* don't call into driver level */
525     }
526
527     if (FOOL_DECODE(idx))
528         return 1;  /* don't call into driver level */
529
530     return 0; /* let driver go ... */
531 }
532
533 int va_FoolSyncSurface(
534         VADisplay dpy, 
535         VASurfaceID render_target
536 )
537 {
538     DPY2INDEX(dpy);
539
540     /*Fill in black and white squares. */
541     if (FOOL_DECODE(idx) || FOOL_DECODE(idx))
542         return 1;
543
544     return 0;
545
546 }
547
548 VAStatus va_FoolUnmapBuffer(
549         VADisplay dpy,
550         VABufferID buf_id       /* in */
551 )
552 {
553     DPY2INDEX(dpy);
554
555     if (FOOL_ENCODE(idx) || FOOL_DECODE(idx))
556         return 1; /* fool buffer creation */
557     
558     return 0;
559 }
560
561 VAStatus va_FoolQuerySubpictureFormats(
562         VADisplay dpy,
563         VAImageFormat *format_list,
564         unsigned int *flags,
565         unsigned int *num_formats
566 )
567 {
568     DPY2INDEX(dpy);
569
570     if (FOOL_ENCODE(idx) || FOOL_DECODE(idx)) { 
571         if (num_formats)
572             *num_formats = 0;
573         return 1;
574     }
575     return 0;
576 }
577