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
40unsigned 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
126unsigned 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
280unsigned 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