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