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