• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2011 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 /**
17  ******************************************************************************
18  * @file        M4TRAN_transition.c
19  * @brief
20  ******************************************************************************
21 */
22 
23 /**
24  * OSAL (memset and memcpy) ***/
25 #include "M4OSA_Memory.h"
26 
27 #include "M4VFL_transition.h"
28 
29 #include <string.h>
30 
31 #ifdef LITTLE_ENDIAN
32 #define M4VFL_SWAP_SHORT(a) a = ((a & 0xFF) << 8) | ((a & 0xFF00) >> 8)
33 #else
34 #define M4VFL_SWAP_SHORT(a)
35 #endif
36 
37 #define LUM_FACTOR_MAX 10
38 
39 
M4VFL_modifyLumaByStep(M4ViComImagePlane * plane_in,M4ViComImagePlane * plane_out,M4VFL_ModifLumParam * lum_param,void * user_data)40 unsigned char M4VFL_modifyLumaByStep(M4ViComImagePlane *plane_in, M4ViComImagePlane *plane_out,
41                                      M4VFL_ModifLumParam *lum_param, void *user_data)
42 {
43     unsigned short *p_src, *p_dest, *p_src_line, *p_dest_line;
44     unsigned long pix_src;
45     unsigned long u_outpx, u_outpx2;
46     unsigned long u_width, u_stride, u_stride_out,u_height, pix;
47     unsigned long lf1, lf2, lf3;
48     long i, j;
49 
50     if (lum_param->copy_chroma != 0)
51     {
52         /* copy chroma plane */
53 
54     }
55 
56     /* apply luma factor */
57     u_width = plane_in[0].u_width;
58     u_height = plane_in[0].u_height;
59     u_stride = (plane_in[0].u_stride >> 1);
60     u_stride_out = (plane_out[0].u_stride >> 1);
61     p_dest = (unsigned short *) &plane_out[0].pac_data[plane_out[0].u_topleft];
62     p_src = (unsigned short *) &plane_in[0].pac_data[plane_in[0].u_topleft];
63     p_dest_line = p_dest;
64     p_src_line = p_src;
65 
66     switch(lum_param->lum_factor)
67     {
68     case 0:
69         /* very specific case : set luma plane to 16 */
70         for (j = u_height; j != 0; j--)
71         {
72             memset((void *)p_dest,16, u_width);
73             p_dest += u_stride_out;
74         }
75         return 0;
76 
77     case 1:
78         /* 0.25 */
79         lf1 = 6; lf2 = 6; lf3 = 7;
80         break;
81     case 2:
82         /* 0.375 */
83         lf1 = 7; lf2 = 7; lf3 = 7;
84         break;
85     case 3:
86         /* 0.5 */
87         lf1 = 7; lf2 = 7; lf3 = 8;
88         break;
89     case 4:
90         /* 0.625 */
91         lf1 = 7; lf2 = 8; lf3 = 8;
92         break;
93     case 5:
94         /* 0.75 */
95         lf1 = 8; lf2 = 8; lf3 = 8;
96         break;
97     case 6:
98         /* 0.875 */
99         lf1 = 9; lf2 = 8; lf3 = 7;
100         break;
101     default:
102         lf1 = 8; lf2 = 8; lf3 = 9;
103         break;
104     }
105 
106     for (j = u_height; j != 0; j--)
107     {
108         p_dest = p_dest_line;
109         p_src = p_src_line;
110         for (i = (u_width >> 1); i != 0; i--)
111         {
112             pix_src = (unsigned long) *p_src++;
113             pix = pix_src & 0xFF;
114             u_outpx = (((pix << lf1) + (pix << lf2) + (pix << lf3) ) >> LUM_FACTOR_MAX);
115             pix = ((pix_src & 0xFF00) >> 8);
116             u_outpx2 = ((((pix << lf1) + (pix << lf2) + (pix << lf3) ) >> LUM_FACTOR_MAX)<< 8) ;
117             *p_dest++ = (unsigned short) (u_outpx2 | u_outpx);
118         }
119         p_dest_line += u_stride_out;
120         p_src_line += u_stride;
121     }
122     return 0;
123 }
124 
125 
M4VFL_modifyLumaWithScale(M4ViComImagePlane * plane_in,M4ViComImagePlane * plane_out,unsigned long lum_factor,void * user_data)126 unsigned char M4VFL_modifyLumaWithScale(M4ViComImagePlane *plane_in,
127                                          M4ViComImagePlane *plane_out,
128                                          unsigned long lum_factor,
129                                          void *user_data)
130 {
131     unsigned short *p_src, *p_dest, *p_src_line, *p_dest_line;
132     unsigned char *p_csrc, *p_cdest, *p_csrc_line, *p_cdest_line;
133     unsigned long pix_src;
134     unsigned long u_outpx, u_outpx2;
135     unsigned long u_width, u_stride, u_stride_out,u_height, pix;
136     long i, j;
137 
138     /* copy or filter chroma */
139     u_width = plane_in[1].u_width;
140     u_height = plane_in[1].u_height;
141     u_stride = plane_in[1].u_stride;
142     u_stride_out = plane_out[1].u_stride;
143     p_cdest_line = (unsigned char *) &plane_out[1].pac_data[plane_out[1].u_topleft];
144     p_csrc_line = (unsigned char *) &plane_in[1].pac_data[plane_in[1].u_topleft];
145 
146     if (lum_factor > 256)
147     {
148         p_cdest = (unsigned char *) &plane_out[2].pac_data[plane_out[2].u_topleft];
149         p_csrc = (unsigned char *) &plane_in[2].pac_data[plane_in[2].u_topleft];
150         /* copy chroma */
151         for (j = u_height; j != 0; j--)
152         {
153             for (i = u_width; i != 0; i--)
154             {
155                 memcpy((void *)p_cdest_line, (void *)p_csrc_line, u_width);
156                 memcpy((void *)p_cdest,(void *) p_csrc, u_width);
157             }
158             p_cdest_line += u_stride_out;
159             p_cdest += u_stride_out;
160             p_csrc_line += u_stride;
161             p_csrc += u_stride;
162         }
163     }
164     else
165     {
166         /* filter chroma */
167         pix = (1024 - lum_factor) << 7;
168         for (j = u_height; j != 0; j--)
169         {
170             p_cdest = p_cdest_line;
171             p_csrc = p_csrc_line;
172             for (i = u_width; i != 0; i--)
173             {
174                 *p_cdest++ = ((pix + (*p_csrc++ & 0xFF) * lum_factor) >> LUM_FACTOR_MAX);
175             }
176             p_cdest_line += u_stride_out;
177             p_csrc_line += u_stride;
178         }
179         p_cdest_line = (unsigned char *) &plane_out[2].pac_data[plane_out[2].u_topleft];
180         p_csrc_line = (unsigned char *) &plane_in[2].pac_data[plane_in[2].u_topleft];
181         for (j = u_height; j != 0; j--)
182         {
183             p_cdest = p_cdest_line;
184             p_csrc = p_csrc_line;
185             for (i = u_width; i != 0; i--)
186             {
187                 *p_cdest++ = ((pix + (*p_csrc & 0xFF) * lum_factor) >> LUM_FACTOR_MAX);
188             }
189             p_cdest_line += u_stride_out;
190             p_csrc_line += u_stride;
191         }
192     }
193     /* apply luma factor */
194     u_width = plane_in[0].u_width;
195     u_height = plane_in[0].u_height;
196     u_stride = (plane_in[0].u_stride >> 1);
197     u_stride_out = (plane_out[0].u_stride >> 1);
198     p_dest = (unsigned short *) &plane_out[0].pac_data[plane_out[0].u_topleft];
199     p_src = (unsigned short *) &plane_in[0].pac_data[plane_in[0].u_topleft];
200     p_dest_line = p_dest;
201     p_src_line = p_src;
202 
203     for (j = u_height; j != 0; j--)
204     {
205         p_dest = p_dest_line;
206         p_src = p_src_line;
207         for (i = (u_width >> 1); i != 0; i--)
208         {
209             pix_src = (unsigned long) *p_src++;
210             pix = pix_src & 0xFF;
211             u_outpx = ((pix * lum_factor) >> LUM_FACTOR_MAX);
212             pix = ((pix_src & 0xFF00) >> 8);
213             u_outpx2 = (((pix * lum_factor) >> LUM_FACTOR_MAX)<< 8) ;
214             *p_dest++ = (unsigned short) (u_outpx2 | u_outpx);
215         }
216         p_dest_line += u_stride_out;
217         p_src_line += u_stride;
218     }
219 
220     return 0;
221 }
222 
223 /**
224  *************************************************************************************************
225  * M4OSA_ERR M4VIFI_ImageBlendingonYUV420 (void *pUserData,
226  *                                                  M4VIFI_ImagePlane *pPlaneIn1,
227  *                                                  M4VIFI_ImagePlane *pPlaneIn2,
228  *                                                  M4VIFI_ImagePlane *pPlaneOut,
229  *                                                  UInt32 Progress)
230  * @brief   Blends two YUV 4:2:0 Planar images.
231  * @note    Blends YUV420 planar images,
232  *          Map the value of progress from (0 - 1000) to (0 - 1024)
233  *          Set the range of blendingfactor,
234  *                  1. from 0 to (Progress << 1)            ;for Progress <= 512
235  *                  2. from (( Progress - 512)<< 1) to 1024 ;otherwise
236  *          Set the increment of blendingfactor for each element in the image row by the factor,
237  *                  =  (Range-1) / (image width-1)  ;for width >= range
238  *                  =  (Range) / (image width)      ;otherwise
239  *          Loop on each(= i) row of output Y plane (steps of 2)
240  *              Loop on each(= j) column of output Y plane (steps of 2)
241  *                  Get four Y samples and one U & V sample from two input YUV4:2:0 images and
242  *                  Compute four Y sample and one U & V sample for output YUV4:2:0 image
243  *                      using the following,
244  *                  Out(i,j) = blendingfactor(i,j) * In1(i,j)+ (l - blendingfactor(i,j)) *In2(i,j)
245  *              end loop column
246  *          end loop row.
247  * @param   pUserData: (IN)  User Specific Parameter
248  * @param   pPlaneIn1: (IN)  Pointer to an array of image plane structures maintained
249  *           for Y, U and V planes.
250  * @param   pPlaneIn2: (IN)  Pointer to an array of image plane structures maintained
251  *           for Y, U and V planes.
252  * @param   pPlaneOut: (OUT) Pointer to an array of image plane structures maintained
253  *           for Y, U and V planes.
254  * @param   Progress:  (IN)  Progress value (varies between 0 and 1000)
255  * @return  M4VIFI_OK: No error
256  * @return  M4VIFI_ILLEGAL_FRAME_HEIGHT: Error in height
257  * @return  M4VIFI_ILLEGAL_FRAME_WIDTH:  Error in width
258  *************************************************************************************************
259 */
260 
261 /** Check for value is EVEN */
262 #ifndef IS_EVEN
263 #define IS_EVEN(a)  (!(a & 0x01))
264 #endif
265 
266 /** Used for fixed point implementation */
267 #ifndef MAX_SHORT
268 #define MAX_SHORT   0x10000
269 #endif
270 
271 #ifndef NULL
272 #define NULL    0
273 #endif
274 
275 #ifndef FALSE
276 #define FALSE   0
277 #define TRUE    !FALSE
278 #endif
279 
M4VIFI_ImageBlendingonYUV420(void * pUserData,M4ViComImagePlane * pPlaneIn1,M4ViComImagePlane * pPlaneIn2,M4ViComImagePlane * pPlaneOut,UInt32 Progress)280 unsigned char M4VIFI_ImageBlendingonYUV420 (void *pUserData,
281                                             M4ViComImagePlane *pPlaneIn1,
282                                             M4ViComImagePlane *pPlaneIn2,
283                                             M4ViComImagePlane *pPlaneOut,
284                                             UInt32 Progress)
285 {
286     UInt8    *pu8_data_Y_start1,*pu8_data_U_start1,*pu8_data_V_start1;
287     UInt8    *pu8_data_Y_start2,*pu8_data_U_start2,*pu8_data_V_start2;
288     UInt8    *pu8_data_Y_start3,*pu8_data_U_start3,*pu8_data_V_start3;
289     UInt8    *pu8_data_Y_current1, *pu8_data_Y_next1, *pu8_data_U1, *pu8_data_V1;
290     UInt8    *pu8_data_Y_current2, *pu8_data_Y_next2, *pu8_data_U2, *pu8_data_V2;
291     UInt8    *pu8_data_Y_current3,*pu8_data_Y_next3, *pu8_data_U3, *pu8_data_V3;
292     UInt32   u32_stride_Y1, u32_stride2_Y1, u32_stride_U1, u32_stride_V1;
293     UInt32   u32_stride_Y2, u32_stride2_Y2, u32_stride_U2, u32_stride_V2;
294     UInt32   u32_stride_Y3, u32_stride2_Y3, u32_stride_U3, u32_stride_V3;
295     UInt32   u32_height,  u32_width;
296     UInt32   u32_blendfactor, u32_startA, u32_endA, u32_blend_inc, u32_x_accum;
297     UInt32   u32_col, u32_row, u32_rangeA, u32_progress;
298     UInt32   u32_U1,u32_V1,u32_U2,u32_V2, u32_Y1, u32_Y2;
299 
300 
301     /* Check the Y plane height is EVEN and image plane heights are same */
302     if( (IS_EVEN(pPlaneIn1[0].u_height) == FALSE)                ||
303         (IS_EVEN(pPlaneIn2[0].u_height) == FALSE)                ||
304         (IS_EVEN(pPlaneOut[0].u_height) == FALSE)                ||
305         (pPlaneIn1[0].u_height != pPlaneOut[0].u_height)         ||
306         (pPlaneIn2[0].u_height != pPlaneOut[0].u_height) )
307     {
308         return M4VIFI_ILLEGAL_FRAME_HEIGHT;
309     }
310 
311     /* Check the Y plane width is EVEN and image plane widths are same */
312     if( (IS_EVEN(pPlaneIn1[0].u_width) == FALSE)                 ||
313         (IS_EVEN(pPlaneIn2[0].u_width) == FALSE)                 ||
314         (IS_EVEN(pPlaneOut[0].u_width) == FALSE)                 ||
315         (pPlaneIn1[0].u_width  != pPlaneOut[0].u_width)          ||
316         (pPlaneIn2[0].u_width  != pPlaneOut[0].u_width)  )
317     {
318         return M4VIFI_ILLEGAL_FRAME_WIDTH;
319     }
320 
321     /* Set the pointer to the beginning of the input1 YUV420 image planes */
322     pu8_data_Y_start1 = pPlaneIn1[0].pac_data + pPlaneIn1[0].u_topleft;
323     pu8_data_U_start1 = pPlaneIn1[1].pac_data + pPlaneIn1[1].u_topleft;
324     pu8_data_V_start1 = pPlaneIn1[2].pac_data + pPlaneIn1[2].u_topleft;
325 
326     /* Set the pointer to the beginning of the input2 YUV420 image planes */
327     pu8_data_Y_start2 = pPlaneIn2[0].pac_data + pPlaneIn2[0].u_topleft;
328     pu8_data_U_start2 = pPlaneIn2[1].pac_data + pPlaneIn2[1].u_topleft;
329     pu8_data_V_start2 = pPlaneIn2[2].pac_data + pPlaneIn2[2].u_topleft;
330 
331     /* Set the pointer to the beginning of the output YUV420 image planes */
332     pu8_data_Y_start3 = pPlaneOut[0].pac_data + pPlaneOut[0].u_topleft;
333     pu8_data_U_start3 = pPlaneOut[1].pac_data + pPlaneOut[1].u_topleft;
334     pu8_data_V_start3 = pPlaneOut[2].pac_data + pPlaneOut[2].u_topleft;
335 
336     /* Set the stride for the next row in each input1 YUV420 plane */
337     u32_stride_Y1 = pPlaneIn1[0].u_stride;
338     u32_stride_U1 = pPlaneIn1[1].u_stride;
339     u32_stride_V1 = pPlaneIn1[2].u_stride;
340 
341     /* Set the stride for the next row in each input2 YUV420 plane */
342     u32_stride_Y2 = pPlaneIn2[0].u_stride;
343     u32_stride_U2 = pPlaneIn2[1].u_stride;
344     u32_stride_V2 = pPlaneIn2[2].u_stride;
345 
346     /* Set the stride for the next row in each output YUV420 plane */
347     u32_stride_Y3 = pPlaneOut[0].u_stride;
348     u32_stride_U3 = pPlaneOut[1].u_stride;
349     u32_stride_V3 = pPlaneOut[2].u_stride;
350 
351     u32_stride2_Y1   = u32_stride_Y1 << 1;
352     u32_stride2_Y2   = u32_stride_Y2 << 1;
353     u32_stride2_Y3   = u32_stride_Y3 << 1;
354 
355     /* Get the size of the output image */
356     u32_height = pPlaneOut[0].u_height;
357     u32_width  = pPlaneOut[0].u_width;
358 
359     /* User Specified Progress value */
360     u32_progress = Progress;
361 
362     /* Map Progress value from (0 - 1000) to (0 - 1024) -> for optimisation */
363     if(u32_progress < 1000)
364         u32_progress = ((u32_progress << 10) / 1000);
365     else
366         u32_progress = 1024;
367 
368     /* Set the range of blendingfactor */
369     if(u32_progress <= 512)
370     {
371         u32_startA = 0;
372         u32_endA   = (u32_progress << 1);
373     }
374     else /* u32_progress > 512 */
375     {
376         u32_startA = (u32_progress - 512) << 1;
377         u32_endA   =  1024;
378     }
379     u32_rangeA = u32_endA - u32_startA;
380 
381     /* Set the increment of blendingfactor for each element in the image row */
382     if ((u32_width >= u32_rangeA) && (u32_rangeA > 0) )
383     {
384         u32_blend_inc   = ((u32_rangeA-1) * MAX_SHORT) / (u32_width - 1);
385     }
386     else /* (u32_width < u32_rangeA) || (u32_rangeA < 0) */
387     {
388         u32_blend_inc   = (u32_rangeA * MAX_SHORT) / (u32_width);
389     }
390 
391     /* Two YUV420 rows are computed at each pass */
392     for (u32_row = u32_height; u32_row != 0; u32_row -=2)
393     {
394         /* Set pointers to the beginning of the row for each input image1 plane */
395         pu8_data_Y_current1 = pu8_data_Y_start1;
396         pu8_data_U1 = pu8_data_U_start1;
397         pu8_data_V1 = pu8_data_V_start1;
398 
399         /* Set pointers to the beginning of the row for each input image2 plane */
400         pu8_data_Y_current2 = pu8_data_Y_start2;
401         pu8_data_U2 = pu8_data_U_start2;
402         pu8_data_V2 = pu8_data_V_start2;
403 
404         /* Set pointers to the beginning of the row for each output image plane */
405         pu8_data_Y_current3 = pu8_data_Y_start3;
406         pu8_data_U3 = pu8_data_U_start3;
407         pu8_data_V3 = pu8_data_V_start3;
408 
409         /* Set pointers to the beginning of the next row for image luma plane */
410         pu8_data_Y_next1 = pu8_data_Y_current1 + u32_stride_Y1;
411         pu8_data_Y_next2 = pu8_data_Y_current2 + u32_stride_Y2;
412         pu8_data_Y_next3 = pu8_data_Y_current3 + u32_stride_Y3;
413 
414         /* Initialise blendfactor */
415         u32_blendfactor   = u32_startA;
416         /* Blendfactor Increment accumulator */
417         u32_x_accum = 0;
418 
419         /* Loop on each column of the output image */
420         for (u32_col = u32_width; u32_col != 0 ; u32_col -=2)
421         {
422             /* Update the blending factor */
423             u32_blendfactor = u32_startA + (u32_x_accum >> 16);
424 
425             /* Get Luma value (x,y) of input Image1 */
426             u32_Y1 = *pu8_data_Y_current1++;
427 
428             /* Get chrominance2 value */
429             u32_U1 = *pu8_data_U1++;
430             u32_V1 = *pu8_data_V1++;
431 
432             /* Get Luma value (x,y) of input Image2 */
433             u32_Y2 = *pu8_data_Y_current2++;
434 
435             /* Get chrominance2 value */
436             u32_U2 = *pu8_data_U2++;
437             u32_V2 = *pu8_data_V2++;
438 
439             /* Compute Luma value (x,y) of Output image */
440             *pu8_data_Y_current3++  = (UInt8)((u32_blendfactor * u32_Y2 +
441                                                      (1024 - u32_blendfactor)*u32_Y1) >> 10);
442             /* Compute chroma(U) value of Output image */
443             *pu8_data_U3++          = (UInt8)((u32_blendfactor * u32_U2 +
444                                                      (1024 - u32_blendfactor)*u32_U1) >> 10);
445             /* Compute chroma(V) value of Output image */
446             *pu8_data_V3++          = (UInt8)((u32_blendfactor * u32_V2 +
447                                                      (1024 - u32_blendfactor)*u32_V1) >> 10);
448 
449             /* Get Luma value (x,y+1) of input Image1 */
450             u32_Y1 = *pu8_data_Y_next1++;
451 
452              /* Get Luma value (x,y+1) of input Image2 */
453             u32_Y2 = *pu8_data_Y_next2++;
454 
455             /* Compute Luma value (x,y+1) of Output image*/
456             *pu8_data_Y_next3++ = (UInt8)((u32_blendfactor * u32_Y2 +
457                                                     (1024 - u32_blendfactor)*u32_Y1) >> 10);
458             /* Update accumulator */
459             u32_x_accum += u32_blend_inc;
460 
461             /* Update the blending factor */
462             u32_blendfactor = u32_startA + (u32_x_accum >> 16);
463 
464             /* Get Luma value (x+1,y) of input Image1 */
465             u32_Y1 = *pu8_data_Y_current1++;
466 
467             /* Get Luma value (x+1,y) of input Image2 */
468             u32_Y2 = *pu8_data_Y_current2++;
469 
470             /* Compute Luma value (x+1,y) of Output image*/
471             *pu8_data_Y_current3++ = (UInt8)((u32_blendfactor * u32_Y2 +
472                                                  (1024 - u32_blendfactor)*u32_Y1) >> 10);
473 
474             /* Get Luma value (x+1,y+1) of input Image1 */
475             u32_Y1 = *pu8_data_Y_next1++;
476 
477             /* Get Luma value (x+1,y+1) of input Image2 */
478             u32_Y2 = *pu8_data_Y_next2++;
479 
480             /* Compute Luma value (x+1,y+1) of Output image*/
481             *pu8_data_Y_next3++ = (UInt8)((u32_blendfactor * u32_Y2 +
482                                                  (1024 - u32_blendfactor)*u32_Y1) >> 10);
483             /* Update accumulator */
484             u32_x_accum += u32_blend_inc;
485 
486             /* Working pointers are incremented just after each storage */
487 
488         }/* End of row scanning */
489 
490         /* Update working pointer of input image1 for next row */
491         pu8_data_Y_start1 += u32_stride2_Y1;
492         pu8_data_U_start1 += u32_stride_U1;
493         pu8_data_V_start1 += u32_stride_V1;
494 
495         /* Update working pointer of input image2 for next row */
496         pu8_data_Y_start2 += u32_stride2_Y2;
497         pu8_data_U_start2 += u32_stride_U2;
498         pu8_data_V_start2 += u32_stride_V2;
499 
500         /* Update working pointer of output image for next row */
501         pu8_data_Y_start3 += u32_stride2_Y3;
502         pu8_data_U_start3 += u32_stride_U3;
503         pu8_data_V_start3 += u32_stride_V3;
504 
505     }/* End of column scanning */
506 
507     return M4VIFI_OK;
508 }
509 /* End of file M4VIFI_ImageBlendingonYUV420.c */
510 
511