OSDN Git Service

4d7be9829424ab42eae702de8d40cd441f2e0e43
[android-x86/hardware-intel-common-libva.git] / test / loadsurface.h
1 /*
2  * Copyright (c) 2008-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 #include "loadsurface_yuv.h"
25
26 static int scale_2dimage(unsigned char *src_img, int src_imgw, int src_imgh,
27                          unsigned char *dst_img, int dst_imgw, int dst_imgh)
28 {
29     int row=0, col=0;
30
31     for (row=0; row<dst_imgh; row++) {
32         for (col=0; col<dst_imgw; col++) {
33             *(dst_img + row * dst_imgw + col) = *(src_img + (row * src_imgh/dst_imgh) * src_imgw + col * src_imgw/dst_imgw);
34         }
35     }
36
37     return 0;
38 }
39
40
41 static int YUV_blend_with_pic(int width, int height,
42                               unsigned char *Y_start, int Y_pitch,
43                               unsigned char *U_start, int U_pitch,
44                               unsigned char *V_start, int V_pitch,
45                               unsigned int fourcc, int fixed_alpha)
46 {
47     /* PIC YUV format */
48     unsigned char *pic_y_old = yuvga_pic;
49     unsigned char *pic_u_old = pic_y_old + 640*480;
50     unsigned char *pic_v_old = pic_u_old + 640*480/4;
51     unsigned char *pic_y, *pic_u, *pic_v;
52
53     int alpha_values[] = {100,90,80,70,60,50,40,30,20,30,40,50,60,70,80,90};
54     
55     static int alpha_idx = 0;
56     int alpha;
57     int allocated = 0;
58     
59     int row, col;
60
61     if (fixed_alpha == 0) {
62         alpha = alpha_values[alpha_idx % 16 ];
63         alpha_idx ++;
64     } else
65         alpha = fixed_alpha;
66
67     //alpha = 0;
68     
69     pic_y = pic_y_old;
70     pic_u = pic_u_old;
71     pic_v = pic_v_old;
72     
73     if (width != 640 || height != 480) { /* need to scale the pic */
74         pic_y = (unsigned char *)malloc(width * height);
75         if(pic_y == NULL) {
76            printf("Failed to allocate memory for pic_y\n");
77            return -1;
78         }
79
80         pic_u = (unsigned char *)malloc(width * height/4);
81         if(pic_u == NULL) {
82            printf("Failed to allocate memory for pic_u\n");
83            free(pic_y);
84            return -1;
85         }
86
87         pic_v = (unsigned char *)malloc(width * height/4);
88         if(pic_v == NULL) {
89            printf("Failed to allocate memory for pic_v\n");
90            free(pic_y);
91            free(pic_u);
92            return -1;
93         }
94         allocated = 1;
95
96         memset(pic_y, 0, width * height);
97         memset(pic_u, 0, width * height /4);
98         memset(pic_v, 0, width * height /4);
99         
100         scale_2dimage(pic_y_old, 640, 480,
101                       pic_y, width, height);
102         scale_2dimage(pic_u_old, 320, 240,
103                       pic_u, width/2, height/2);
104         scale_2dimage(pic_v_old, 320, 240,
105                       pic_v, width/2, height/2);
106     }
107
108     /* begin blend */
109
110     /* Y plane */
111     int Y_pixel_stride = 1;
112     if (fourcc == VA_FOURCC_YUY2) 
113         Y_pixel_stride = 2;
114          
115     for (row=0; row<height; row++) {
116         unsigned char *p = Y_start + row * Y_pitch;
117         unsigned char *q = pic_y + row * width;
118         for (col=0; col<width; col++, q++) {
119             *p  = *p * (100 - alpha) / 100 + *q * alpha/100;
120             p += Y_pixel_stride;
121         }
122     }
123
124     /* U/V plane */
125     int U_pixel_stride = 0, V_pixel_stride = 0;
126     int v_factor_to_nv12 = 1;
127     switch (fourcc) {
128     case VA_FOURCC_YV12:
129         U_pixel_stride = V_pixel_stride = 1;
130         break;
131     case VA_FOURCC_NV12:
132         U_pixel_stride = V_pixel_stride = 2;
133         break;
134     case VA_FOURCC_YUY2:
135         U_pixel_stride = V_pixel_stride = 4;
136         v_factor_to_nv12 = 2;
137         break;
138     default:
139         break;
140     }
141     for (row=0; row<height/2*v_factor_to_nv12; row++) {
142         unsigned char *pU = U_start + row * U_pitch;
143         unsigned char *pV = V_start + row * V_pitch;
144         unsigned char *qU = pic_u + row/v_factor_to_nv12 * width/2;
145         unsigned char *qV = pic_v + row/v_factor_to_nv12 * width/2;
146             
147         for (col=0; col<width/2; col++, qU++, qV++) {
148             *pU  = *pU * (100 - alpha) / 100 + *qU * alpha/100;
149             *pV  = *pV * (100 - alpha) / 100 + *qV * alpha/100;
150
151             pU += U_pixel_stride;
152             pV += V_pixel_stride;
153         }
154     }
155         
156     if (allocated) {
157         free(pic_y);
158         free(pic_u);
159         free(pic_v);
160     }
161     
162     return 0;
163 }
164
165 static int yuvgen_planar(int width, int height,
166                          unsigned char *Y_start, int Y_pitch,
167                          unsigned char *U_start, int U_pitch,
168                          unsigned char *V_start, int V_pitch,
169                          unsigned int fourcc, int box_width, int row_shift,
170                          int field)
171 {
172     int row, alpha;
173     unsigned char uv_value = 0x80;
174
175     /* copy Y plane */
176     int y_factor = 1;
177     if (fourcc == VA_FOURCC_YUY2) y_factor = 2;
178     for (row=0;row<height;row++) {
179         unsigned char *Y_row = Y_start + row * Y_pitch;
180         int jj, xpos, ypos;
181
182         ypos = (row / box_width) & 0x1;
183
184         /* fill garbage data into the other field */
185         if (((field == VA_TOP_FIELD) && (row &1))
186             || ((field == VA_BOTTOM_FIELD) && ((row &1)==0))) { 
187             memset(Y_row, 0xff, width);
188             continue;
189         }
190         
191         for (jj=0; jj<width; jj++) {
192             xpos = ((row_shift + jj) / box_width) & 0x1;
193             if (xpos == ypos)
194                 Y_row[jj*y_factor] = 0xeb;
195             else 
196                 Y_row[jj*y_factor] = 0x10;
197
198             if (fourcc == VA_FOURCC_YUY2) {
199                 Y_row[jj*y_factor+1] = uv_value; // it is for UV
200             }
201         }
202     }
203   
204     /* copy UV data */
205     for( row =0; row < height/2; row++) {
206
207         /* fill garbage data into the other field */
208         if (((field == VA_TOP_FIELD) && (row &1))
209             || ((field == VA_BOTTOM_FIELD) && ((row &1)==0))) {
210             uv_value = 0xff;
211         }
212
213         unsigned char *U_row = U_start + row * U_pitch;
214         unsigned char *V_row = V_start + row * V_pitch;
215         switch (fourcc) {
216         case VA_FOURCC_NV12:
217             memset(U_row, uv_value, width);
218             break;
219         case VA_FOURCC_YV12:
220             memset (U_row,uv_value,width/2);
221             memset (V_row,uv_value,width/2);
222             break;
223         case VA_FOURCC_YUY2:
224             // see above. it is set with Y update.
225             break;
226         default:
227             printf("unsupported fourcc in loadsurface.h\n");
228             assert(0);
229         }
230     }
231
232     if (getenv("AUTO_NOUV"))
233         return 0;
234
235     if (getenv("AUTO_ALPHA"))
236         alpha = 0;
237     else
238         alpha = 70;
239     
240     YUV_blend_with_pic(width,height,
241                        Y_start, Y_pitch,
242                        U_start, U_pitch,
243                        V_start, V_pitch,
244                        fourcc, alpha);
245     
246     return 0;
247 }
248
249 static int upload_surface(VADisplay va_dpy, VASurfaceID surface_id,
250                           int box_width, int row_shift,
251                           int field)
252 {
253     VAImage surface_image;
254     void *surface_p=NULL, *U_start = NULL,*V_start = NULL;
255     VAStatus va_status;
256     unsigned int pitches[3]={0,0,0};
257     
258     va_status = vaDeriveImage(va_dpy,surface_id,&surface_image);
259     CHECK_VASTATUS(va_status,"vaDeriveImage");
260
261     vaMapBuffer(va_dpy,surface_image.buf,&surface_p);
262     assert(VA_STATUS_SUCCESS == va_status);
263
264     pitches[0] = surface_image.pitches[0];
265     switch (surface_image.format.fourcc) {
266     case VA_FOURCC_NV12:
267         U_start = (char *)surface_p + surface_image.offsets[1];
268         V_start = (char *)U_start + 1;
269         pitches[1] = surface_image.pitches[1];
270         pitches[2] = surface_image.pitches[1];
271         break;
272     case VA_FOURCC_IYUV:
273         U_start = (char *)surface_p + surface_image.offsets[1];
274         V_start = (char *)surface_p + surface_image.offsets[2];
275         pitches[1] = surface_image.pitches[1];
276         pitches[2] = surface_image.pitches[2];
277         break;
278     case VA_FOURCC_YV12:
279         U_start = (char *)surface_p + surface_image.offsets[2];
280         V_start = (char *)surface_p + surface_image.offsets[1];
281         pitches[1] = surface_image.pitches[2];
282         pitches[2] = surface_image.pitches[1];
283         break;
284     case VA_FOURCC_YUY2:
285         U_start = (char *)surface_p + 1;
286         V_start = (char *)surface_p + 3;
287         pitches[1] = surface_image.pitches[0];
288         pitches[2] = surface_image.pitches[0];
289         break;
290     default:
291         assert(0);
292     }
293
294     /* assume surface is planar format */
295     yuvgen_planar(surface_image.width, surface_image.height,
296                   (unsigned char *)surface_p, pitches[0],
297                   (unsigned char *)U_start, pitches[1],
298                   (unsigned char *)V_start, pitches[2],
299                   surface_image.format.fourcc,
300                   box_width, row_shift, field);
301         
302     vaUnmapBuffer(va_dpy,surface_image.buf);
303
304     vaDestroyImage(va_dpy,surface_image.image_id);
305
306     return 0;
307 }
308
309 /*
310  * Upload YUV data from memory into a surface
311  * if src_fourcc == NV12, assume the buffer pointed by src_U
312  * is UV interleaved (src_V is ignored)
313  */
314 static int upload_surface_yuv(VADisplay va_dpy, VASurfaceID surface_id,
315                               int src_fourcc, int src_width, int src_height,
316                               unsigned char *src_Y, unsigned char *src_U, unsigned char *src_V)
317 {
318     VAImage surface_image;
319     unsigned char *surface_p=NULL, *Y_start=NULL, *U_start=NULL;
320     int Y_pitch=0, U_pitch=0, row;
321     VAStatus va_status;
322     
323     va_status = vaDeriveImage(va_dpy,surface_id, &surface_image);
324     CHECK_VASTATUS(va_status,"vaDeriveImage");
325
326     vaMapBuffer(va_dpy,surface_image.buf,(void **)&surface_p);
327     assert(VA_STATUS_SUCCESS == va_status);
328
329     Y_start = surface_p;
330     Y_pitch = surface_image.pitches[0];
331     switch (surface_image.format.fourcc) {
332     case VA_FOURCC_NV12:
333         U_start = (unsigned char *)surface_p + surface_image.offsets[1];
334         U_pitch = surface_image.pitches[1];
335         break;
336     case VA_FOURCC_IYUV:
337         U_start = (unsigned char *)surface_p + surface_image.offsets[1];
338         U_pitch = surface_image.pitches[1];
339         break;
340     case VA_FOURCC_YV12:
341         U_start = (unsigned char *)surface_p + surface_image.offsets[2];
342         U_pitch = surface_image.pitches[2];
343         break;
344     case VA_FOURCC_YUY2:
345         U_start = surface_p + 1;
346         U_pitch = surface_image.pitches[0];
347         break;
348     default:
349         assert(0);
350     }
351
352     /* copy Y plane */
353     for (row=0;row<src_height;row++) {
354         unsigned char *Y_row = Y_start + row * Y_pitch;
355         memcpy(Y_row, src_Y + row*src_width, src_width);
356     }
357   
358     for (row =0; row < src_height/2; row++) {
359         unsigned char *U_row = U_start + row * U_pitch;
360         unsigned char *u_ptr = NULL, *v_ptr=NULL;
361         int j;
362         switch (surface_image.format.fourcc) {
363         case VA_FOURCC_NV12:
364             if (src_fourcc == VA_FOURCC_NV12) {
365                 memcpy(U_row, src_U + row * src_width, src_width);
366                 break;
367             } else if (src_fourcc == VA_FOURCC_IYUV) {
368                 u_ptr = src_U + row * (src_width/2);
369                 v_ptr = src_V + row * (src_width/2);
370             } else if (src_fourcc == VA_FOURCC_YV12) {
371                 v_ptr = src_U + row * (src_width/2);
372                 u_ptr = src_V + row * (src_width/2);
373             }
374             for(j = 0; j < src_width/2; j++) {
375                 U_row[2*j] = u_ptr[j];
376                 U_row[2*j+1] = v_ptr[j];
377             }
378             break;
379         case VA_FOURCC_IYUV:
380         case VA_FOURCC_YV12:
381         case VA_FOURCC_YUY2:
382         default:
383             printf("unsupported fourcc in load_surface_yuv\n");
384             assert(0);
385         }
386     }
387     
388     vaUnmapBuffer(va_dpy,surface_image.buf);
389
390     vaDestroyImage(va_dpy,surface_image.image_id);
391
392     return 0;
393 }
394
395 /*
396  * Download YUV data from a surface into memory
397  * Some hardward doesn't have a aperture for linear access of
398  * tiled surface, thus use vaGetImage to expect the implemnetion
399  * to do tile to linear convert
400  * 
401  * if dst_fourcc == NV12, assume the buffer pointed by dst_U
402  * is UV interleaved (src_V is ignored)
403  */
404 static int download_surface_yuv(VADisplay va_dpy, VASurfaceID surface_id,
405                                 int dst_fourcc, int dst_width, int dst_height,
406                                 unsigned char *dst_Y, unsigned char *dst_U, unsigned char *dst_V)
407 {
408     VAImage surface_image;
409     unsigned char *surface_p=NULL, *Y_start=NULL, *U_start=NULL;
410     int Y_pitch=0, U_pitch=0, row;
411     VAStatus va_status;
412     
413     va_status = vaDeriveImage(va_dpy,surface_id, &surface_image);
414     CHECK_VASTATUS(va_status,"vaDeriveImage");
415
416     vaMapBuffer(va_dpy,surface_image.buf,(void **)&surface_p);
417     assert(VA_STATUS_SUCCESS == va_status);
418
419     Y_start = surface_p;
420     Y_pitch = surface_image.pitches[0];
421     switch (surface_image.format.fourcc) {
422     case VA_FOURCC_NV12:
423         U_start = (unsigned char *)surface_p + surface_image.offsets[1];
424         U_pitch = surface_image.pitches[1];
425         break;
426     case VA_FOURCC_IYUV:
427         U_start = (unsigned char *)surface_p + surface_image.offsets[1];
428         U_pitch = surface_image.pitches[1];
429         break;
430     case VA_FOURCC_YV12:
431         U_start = (unsigned char *)surface_p + surface_image.offsets[2];
432         U_pitch = surface_image.pitches[2];
433         break;
434     case VA_FOURCC_YUY2:
435         U_start = surface_p + 1;
436         U_pitch = surface_image.pitches[0];
437         break;
438     default:
439         assert(0);
440     }
441
442     /* copy Y plane */
443     for (row=0;row<dst_height;row++) {
444         unsigned char *Y_row = Y_start + row * Y_pitch;
445         memcpy(dst_Y + row*dst_width, Y_row, dst_width);
446     }
447   
448     for (row =0; row < dst_height/2; row++) {
449         unsigned char *U_row = U_start + row * U_pitch;
450         unsigned char *u_ptr = NULL, *v_ptr = NULL;
451         int j;
452         switch (surface_image.format.fourcc) {
453         case VA_FOURCC_NV12:
454             if (dst_fourcc == VA_FOURCC_NV12) {
455                 memcpy(dst_U + row * dst_width, U_row, dst_width);
456                 break;
457             } else if (dst_fourcc == VA_FOURCC_IYUV) {
458                 u_ptr = dst_U + row * (dst_width/2);
459                 v_ptr = dst_V + row * (dst_width/2);
460             } else if (dst_fourcc == VA_FOURCC_YV12) {
461                 v_ptr = dst_U + row * (dst_width/2);
462                 u_ptr = dst_V + row * (dst_width/2);
463             }
464             for(j = 0; j < dst_width/2; j++) {
465                 u_ptr[j] = U_row[2*j];
466                 v_ptr[j] = U_row[2*j+1];
467             }
468             break;
469         case VA_FOURCC_IYUV:
470         case VA_FOURCC_YV12:
471         case VA_FOURCC_YUY2:
472         default:
473             printf("unsupported fourcc in load_surface_yuv\n");
474             assert(0);
475         }
476     }
477     
478     vaUnmapBuffer(va_dpy,surface_image.buf);
479
480     vaDestroyImage(va_dpy,surface_image.image_id);
481
482     return 0;
483 }