M4VFL_transition.c revision 3b25fdc4a33b53cfcf67315c2d42ad699b8cefe2
1/*
2 * Copyright (C) 2004-2011 NXP Software
3 * Copyright (C) 2011 The Android Open Source Project
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 *      http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17/**
18 ******************************************************************************
19 * @file        M4TRAN_transition.c
20 * @brief
21 ******************************************************************************
22*/
23
24/**
25 * OSAL (memset and memcpy) ***/
26#include "M4OSA_Memory.h"
27
28#include "M4VFL_transition.h"
29
30#include <string.h>
31
32#ifdef LITTLE_ENDIAN
33#define M4VFL_SWAP_SHORT(a) a = ((a & 0xFF) << 8) | ((a & 0xFF00) >> 8)
34#else
35#define M4VFL_SWAP_SHORT(a)
36#endif
37
38#define LUM_FACTOR_MAX 10
39
40
41unsigned char M4VFL_modifyLumaByStep(M4ViComImagePlane *plane_in, M4ViComImagePlane *plane_out,
42                                     M4VFL_ModifLumParam *lum_param, void *user_data)
43{
44    unsigned short *p_src, *p_dest, *p_src_line, *p_dest_line;
45    unsigned long pix_src;
46    unsigned long u_outpx, u_outpx2;
47    unsigned long u_width, u_stride, u_stride_out,u_height, pix;
48    unsigned long lf1, lf2, lf3;
49    long i, j;
50
51    if (lum_param->copy_chroma != 0)
52    {
53        /* copy chroma plane */
54
55    }
56
57    /* apply luma factor */
58    u_width = plane_in[0].u_width;
59    u_height = plane_in[0].u_height;
60    u_stride = (plane_in[0].u_stride >> 1);
61    u_stride_out = (plane_out[0].u_stride >> 1);
62    p_dest = (unsigned short *) &plane_out[0].pac_data[plane_out[0].u_topleft];
63    p_src = (unsigned short *) &plane_in[0].pac_data[plane_in[0].u_topleft];
64    p_dest_line = p_dest;
65    p_src_line = p_src;
66
67    switch(lum_param->lum_factor)
68    {
69    case 0:
70        /* very specific case : set luma plane to 16 */
71        for (j = u_height; j != 0; j--)
72        {
73            memset((void *)p_dest,16, u_width);
74            p_dest += u_stride_out;
75        }
76        return 0;
77
78    case 1:
79        /* 0.25 */
80        lf1 = 6; lf2 = 6; lf3 = 7;
81        break;
82    case 2:
83        /* 0.375 */
84        lf1 = 7; lf2 = 7; lf3 = 7;
85        break;
86    case 3:
87        /* 0.5 */
88        lf1 = 7; lf2 = 7; lf3 = 8;
89        break;
90    case 4:
91        /* 0.625 */
92        lf1 = 7; lf2 = 8; lf3 = 8;
93        break;
94    case 5:
95        /* 0.75 */
96        lf1 = 8; lf2 = 8; lf3 = 8;
97        break;
98    case 6:
99        /* 0.875 */
100        lf1 = 9; lf2 = 8; lf3 = 7;
101        break;
102    default:
103        lf1 = 8; lf2 = 8; lf3 = 9;
104        break;
105    }
106
107    for (j = u_height; j != 0; j--)
108    {
109        p_dest = p_dest_line;
110        p_src = p_src_line;
111        for (i = (u_width >> 1); i != 0; i--)
112        {
113            pix_src = (unsigned long) *p_src++;
114            pix = pix_src & 0xFF;
115            u_outpx = (((pix << lf1) + (pix << lf2) + (pix << lf3) ) >> LUM_FACTOR_MAX);
116            pix = ((pix_src & 0xFF00) >> 8);
117            u_outpx2 = ((((pix << lf1) + (pix << lf2) + (pix << lf3) ) >> LUM_FACTOR_MAX)<< 8) ;
118            *p_dest++ = (unsigned short) (u_outpx2 | u_outpx);
119        }
120        p_dest_line += u_stride_out;
121        p_src_line += u_stride;
122    }
123    return 0;
124}
125
126
127unsigned char M4VFL_modifyLumaWithScale(M4ViComImagePlane *plane_in,
128                                         M4ViComImagePlane *plane_out,
129                                         unsigned long lum_factor,
130                                         void *user_data)
131{
132    unsigned short *p_src, *p_dest, *p_src_line, *p_dest_line;
133    unsigned char *p_csrc, *p_cdest, *p_csrc_line, *p_cdest_line;
134    unsigned long pix_src;
135    unsigned long u_outpx, u_outpx2;
136    unsigned long u_width, u_stride, u_stride_out,u_height, pix;
137    long i, j;
138
139    /* copy or filter chroma */
140    u_width = plane_in[1].u_width;
141    u_height = plane_in[1].u_height;
142    u_stride = plane_in[1].u_stride;
143    u_stride_out = plane_out[1].u_stride;
144    p_cdest_line = (unsigned char *) &plane_out[1].pac_data[plane_out[1].u_topleft];
145    p_csrc_line = (unsigned char *) &plane_in[1].pac_data[plane_in[1].u_topleft];
146
147    if (lum_factor > 256)
148    {
149        p_cdest = (unsigned char *) &plane_out[2].pac_data[plane_out[2].u_topleft];
150        p_csrc = (unsigned char *) &plane_in[2].pac_data[plane_in[2].u_topleft];
151        /* copy chroma */
152        for (j = u_height; j != 0; j--)
153        {
154            for (i = u_width; i != 0; i--)
155            {
156                memcpy((void *)p_cdest_line, (void *)p_csrc_line, u_width);
157                memcpy((void *)p_cdest,(void *) p_csrc, u_width);
158            }
159            p_cdest_line += u_stride_out;
160            p_cdest += u_stride_out;
161            p_csrc_line += u_stride;
162            p_csrc += u_stride;
163        }
164    }
165    else
166    {
167        /* filter chroma */
168        pix = (1024 - lum_factor) << 7;
169        for (j = u_height; j != 0; j--)
170        {
171            p_cdest = p_cdest_line;
172            p_csrc = p_csrc_line;
173            for (i = u_width; i != 0; i--)
174            {
175                *p_cdest++ = ((pix + (*p_csrc++ & 0xFF) * lum_factor) >> LUM_FACTOR_MAX);
176            }
177            p_cdest_line += u_stride_out;
178            p_csrc_line += u_stride;
179        }
180        p_cdest_line = (unsigned char *) &plane_out[2].pac_data[plane_out[2].u_topleft];
181        p_csrc_line = (unsigned char *) &plane_in[2].pac_data[plane_in[2].u_topleft];
182        for (j = u_height; j != 0; j--)
183        {
184            p_cdest = p_cdest_line;
185            p_csrc = p_csrc_line;
186            for (i = u_width; i != 0; i--)
187            {
188                *p_cdest++ = ((pix + (*p_csrc & 0xFF) * lum_factor) >> LUM_FACTOR_MAX);
189            }
190            p_cdest_line += u_stride_out;
191            p_csrc_line += u_stride;
192        }
193    }
194    /* apply luma factor */
195    u_width = plane_in[0].u_width;
196    u_height = plane_in[0].u_height;
197    u_stride = (plane_in[0].u_stride >> 1);
198    u_stride_out = (plane_out[0].u_stride >> 1);
199    p_dest = (unsigned short *) &plane_out[0].pac_data[plane_out[0].u_topleft];
200    p_src = (unsigned short *) &plane_in[0].pac_data[plane_in[0].u_topleft];
201    p_dest_line = p_dest;
202    p_src_line = p_src;
203
204    for (j = u_height; j != 0; j--)
205    {
206        p_dest = p_dest_line;
207        p_src = p_src_line;
208        for (i = (u_width >> 1); i != 0; i--)
209        {
210            pix_src = (unsigned long) *p_src++;
211            pix = pix_src & 0xFF;
212            u_outpx = ((pix * lum_factor) >> LUM_FACTOR_MAX);
213            pix = ((pix_src & 0xFF00) >> 8);
214            u_outpx2 = (((pix * lum_factor) >> LUM_FACTOR_MAX)<< 8) ;
215            *p_dest++ = (unsigned short) (u_outpx2 | u_outpx);
216        }
217        p_dest_line += u_stride_out;
218        p_src_line += u_stride;
219    }
220
221    return 0;
222}
223
224
225unsigned char M4VFL_applyClosingCurtain(M4ViComImagePlane *plane_in, M4ViComImagePlane *plane_out,
226                                         unsigned short curtain_factor, void *user_data)
227{
228    unsigned char *p_src, *p_srcu, *p_srcv,*p_dest, *p_destu, *p_destv;
229    unsigned long u_width, u_widthuv, u_stride_out, u_stride_out_uv,u_stride, u_stride_uv,u_height;
230    long j;
231    unsigned long nb_black_lines;
232
233    u_width = plane_in[0].u_width;
234    u_height = plane_in[0].u_height;
235    u_stride_out = plane_out[0].u_stride ;
236    u_stride_out_uv = plane_out[1].u_stride;
237    p_dest = (unsigned char *) &plane_out[0].pac_data[plane_out[0].u_topleft];
238    p_destu = (unsigned char *) &plane_out[1].pac_data[plane_out[1].u_topleft];
239    p_destv = (unsigned char *) &plane_out[2].pac_data[plane_out[2].u_topleft];
240    u_widthuv = u_width >> 1;
241
242    /* nb_black_lines is even */
243    nb_black_lines = (unsigned long) ((curtain_factor >> 1) << 1);
244
245    for (j = (nb_black_lines >> 1); j != 0; j--)
246    { /* set black lines */
247        memset((void *)p_dest, 0,u_width);
248        p_dest += u_stride_out;
249        memset((void *)p_dest, 0,u_width);
250        p_dest += u_stride_out;
251        memset((void *)p_destu, 128,u_widthuv);
252        memset((void *)p_destv, 128,u_widthuv);
253        p_destu += u_stride_out_uv;
254        p_destv += u_stride_out_uv;
255    }
256
257    p_src = (unsigned char *) &plane_in[0].pac_data[plane_in[0].u_topleft +\
258         (nb_black_lines * plane_in[0].u_stride)];
259    p_srcu = (unsigned char *) &plane_in[1].pac_data[plane_in[1].u_topleft +\
260         ((nb_black_lines * plane_in[1].u_stride) >> 1)];
261    p_srcv = (unsigned char *) &plane_in[2].pac_data[plane_in[2].u_topleft+\
262         ((nb_black_lines * plane_in[2].u_stride) >> 1)];
263    u_stride = plane_in[0].u_stride ;
264    u_stride_uv = plane_in[1].u_stride;
265
266    /* copy other lines from source */
267    for (j = (u_height - nb_black_lines) >> 1; j != 0; j--)
268    {
269        memcpy((void *)p_dest, (void *)p_src, u_width);
270        p_dest += u_stride_out;
271        p_src += u_stride;
272        memcpy((void *)p_dest,(void *) p_src, u_width);
273        p_dest += u_stride_out;
274        p_src += u_stride;
275        memcpy((void *)p_destu,(void *) p_srcu, u_widthuv);
276        memcpy((void *)p_destv, (void *)p_srcv, u_widthuv);
277        p_destu += u_stride_out_uv;
278        p_destv += u_stride_out_uv;
279        p_srcu += u_stride_uv;
280        p_srcv += u_stride_uv;
281    }
282
283    return 0;
284}
285
286
287unsigned char M4VFL_applyOpeningCurtain(M4ViComImagePlane *plane_in,
288                                         M4ViComImagePlane *plane_out,
289                                         unsigned short curtain_factor, void *user_data)
290{
291    unsigned char *p_src, *p_srcu, *p_srcv,*p_dest, *p_destu, *p_destv;
292    unsigned long u_width, u_widthuv, u_stride_out, u_stride_out_uv,u_stride, u_stride_uv,u_height;
293    long j;
294    unsigned long nb_black_lines;
295
296    u_width = plane_in[0].u_width;
297    u_height = plane_in[0].u_height;
298    u_stride_out = plane_out[0].u_stride ;
299    u_stride_out_uv = plane_out[1].u_stride;
300    p_dest = (unsigned char *) &plane_out[0].pac_data[plane_out[0].u_topleft];
301    p_destu = (unsigned char *) &plane_out[1].pac_data[plane_out[1].u_topleft];
302    p_destv = (unsigned char *) &plane_out[2].pac_data[plane_out[2].u_topleft];
303    u_widthuv = u_width >> 1;
304
305    /* nb_black_lines is even */
306    nb_black_lines = (unsigned long) ((curtain_factor >> 1) << 1);
307
308    p_src = (unsigned char *) &plane_in[0].pac_data[plane_in[0].u_topleft +\
309         ((u_height - nb_black_lines) * plane_in[0].u_stride)];
310    p_srcu = (unsigned char *) &plane_in[1].pac_data[plane_in[1].u_topleft +\
311         (((u_height - nb_black_lines) * plane_in[1].u_stride) >> 1)];
312    p_srcv = (unsigned char *) &plane_in[2].pac_data[plane_in[2].u_topleft+\
313         (((u_height - nb_black_lines) * plane_in[2].u_stride) >> 1)];
314    u_stride = plane_in[0].u_stride ;
315    u_stride_uv = plane_in[1].u_stride;
316
317    for (j = (u_height - nb_black_lines) >> 1; j != 0; j--)
318    {
319        memset((void *)p_dest, 0,u_width);
320        p_dest += u_stride_out;
321        memset((void *)p_dest,0, u_width);
322        p_dest += u_stride_out;
323        memset((void *)p_destu, 128,u_widthuv);
324        memset((void *)p_destv, 128,u_widthuv);
325        p_destu += u_stride_out_uv;
326        p_destv += u_stride_out_uv;
327    }
328
329    for (j = (nb_black_lines >> 1); j != 0; j--)
330    {
331        memcpy((void *)p_dest,(void *) p_src, u_width);
332        p_dest += u_stride_out;
333        p_src += u_stride;
334        memcpy((void *)p_dest,(void *) p_src, u_width);
335        p_dest += u_stride_out;
336        p_src += u_stride;
337        memcpy((void *)p_destu,(void *) p_srcu, u_widthuv);
338        memcpy((void *)p_destv, (void *)p_srcv, u_widthuv);
339        p_destu += u_stride_out_uv;
340        p_destv += u_stride_out_uv;
341        p_srcu += u_stride_uv;
342        p_srcv += u_stride_uv;
343    }
344
345    return 0;
346}
347
348unsigned char M4VFL_applyFallingCurtain(M4ViComImagePlane *plane_in,
349                                         M4ViComImagePlane *plane_out,
350                                         unsigned short curtain_factor, void *user_data)
351{
352    unsigned char *p_src, *p_srcu, *p_srcv,*p_dest, *p_destu, *p_destv;
353    unsigned long u_width, u_widthuv, u_stride_out, u_stride_out_uv,u_stride, u_stride_uv,u_height;
354    long j;
355    unsigned long nb_black_lines;
356
357    u_width = plane_in[0].u_width;
358    u_height = plane_in[0].u_height;
359    u_stride_out = plane_out[0].u_stride ;
360    u_stride_out_uv = plane_out[1].u_stride;
361    p_dest = (unsigned char *) &plane_out[0].pac_data[plane_out[0].u_topleft];
362    p_destu = (unsigned char *) &plane_out[1].pac_data[plane_out[1].u_topleft];
363    p_destv = (unsigned char *) &plane_out[2].pac_data[plane_out[2].u_topleft];
364    u_widthuv = u_width >> 1;
365
366    /* nb_black_lines is even */
367    nb_black_lines = (unsigned long) ((curtain_factor >> 1) << 1);
368
369    p_src = (unsigned char *) &plane_in[0].pac_data[plane_in[0].u_topleft];
370    p_srcu = (unsigned char *) &plane_in[1].pac_data[plane_in[1].u_topleft];
371    p_srcv = (unsigned char *) &plane_in[2].pac_data[plane_in[2].u_topleft];
372    u_stride = plane_in[0].u_stride ;
373    u_stride_uv = plane_in[1].u_stride;
374
375    for (j = (nb_black_lines >> 1); j != 0; j--)
376    {
377        memcpy((void *)p_dest,(void *) p_src, u_width);
378        p_dest += u_stride_out;
379        p_src += u_stride;
380        memcpy((void *)p_dest,(void *) p_src, u_width);
381        p_dest += u_stride_out;
382        p_src += u_stride;
383        memcpy((void *)p_destu,(void *) p_srcu, u_widthuv);
384        memcpy((void *)p_destv,(void *) p_srcv, u_widthuv);
385        p_destu += u_stride_out_uv;
386        p_destv += u_stride_out_uv;
387        p_srcu += u_stride_uv;
388        p_srcv += u_stride_uv;
389    }
390
391    for (j = (u_height - nb_black_lines) >> 1; j != 0; j--)
392    {
393        memset((void *)p_dest, 0,u_width);
394        p_dest += u_stride_out;
395        memset((void *)p_dest, 0,u_width);
396        p_dest += u_stride_out;
397        memset((void *)p_destu, 128,u_widthuv);
398        memset((void *)p_destv, 128,u_widthuv);
399        p_destu += u_stride_out_uv;
400        p_destv += u_stride_out_uv;
401    }
402    return 0;
403}
404
405/**
406 ******************************************************************************
407 * unsigned char M4VFL_applyCurtain(M4ViComImagePlane *plane_in, M4ViComImagePlane *plane_out,
408 *                                   M4VFL_CurtainParam *curtain_factor, void *user_data)
409 * @brief    This function applies a black curtain onto a YUV420 image.
410 * @note    THis function writes black lines either at the top of the image or at
411 *            the bottom of the image. The other lines are copied from the source image.
412 *            First the number of black lines is compted and is rounded to an even integer.
413 * @param    plane_in: (IN) pointer to the 3 image planes of the source image
414 * @param    plane_out: (OUT) pointer to the 3 image planes of the destination image
415 * @param    user_data: (IN) pointer to some user_data
416 * @param    curtain_factor: (IN) structure with the parameters of the curtain
417 *           (nb of black lines and if at the top/bottom of the image)
418 * @return    0: there is no error
419 ******************************************************************************
420*/
421unsigned char M4VFL_applyCurtain(M4ViComImagePlane *plane_in, M4ViComImagePlane *plane_out,
422                                 M4VFL_CurtainParam *curtain_factor, void *user_data)
423{
424    unsigned char *p_src, *p_srcu, *p_srcv,*p_dest, *p_destu, *p_destv;
425    unsigned long u_width, u_widthuv, u_stride_out, u_stride_out_uv,u_stride, u_stride_uv,u_height;
426    long j;
427    unsigned long nb_black_lines;
428
429    u_width = plane_in[0].u_width;
430    u_height = plane_in[0].u_height;
431    u_stride_out = plane_out[0].u_stride ;
432    u_stride_out_uv = plane_out[1].u_stride;
433    p_dest = (unsigned char *) &plane_out[0].pac_data[plane_out[0].u_topleft];
434    p_destu = (unsigned char *) &plane_out[1].pac_data[plane_out[1].u_topleft];
435    p_destv = (unsigned char *) &plane_out[2].pac_data[plane_out[2].u_topleft];
436    u_widthuv = u_width >> 1;
437    u_stride = plane_in[0].u_stride ;
438    u_stride_uv = plane_in[1].u_stride;
439
440    /* nb_black_lines is even */
441    nb_black_lines = (unsigned long) ((curtain_factor->nb_black_lines >> 1) << 1);
442
443    if (curtain_factor->top_is_black)
444    {
445        /* black lines first */
446        /* compute index of of first source pixels (Y, U and V) to copy after the black lines */
447        p_src = (unsigned char *) &plane_in[0].pac_data[plane_in[0].u_topleft +\
448             ((nb_black_lines) * plane_in[0].u_stride)];
449        p_srcu = (unsigned char *) &plane_in[1].pac_data[plane_in[1].u_topleft +\
450             (((nb_black_lines) * plane_in[1].u_stride) >> 1)];
451        p_srcv = (unsigned char *) &plane_in[2].pac_data[plane_in[2].u_topleft+\
452             (((nb_black_lines) * plane_in[2].u_stride) >> 1)];
453
454        /* write black lines */
455        for (j = (nb_black_lines >> 1); j != 0; j--)
456        {
457            memset((void *)p_dest, 0,u_width);
458            p_dest += u_stride_out;
459            memset((void *)p_dest, 0,u_width);
460            p_dest += u_stride_out;
461            memset((void *)p_destu, 128,u_widthuv);
462            memset((void *)p_destv, 128,u_widthuv);
463            p_destu += u_stride_out_uv;
464            p_destv += u_stride_out_uv;
465        }
466
467        /* copy from source image */
468        for (j = (u_height - nb_black_lines) >> 1; j != 0; j--)
469        {
470            memcpy((void *)p_dest, (void *)p_src, u_width);
471            p_dest += u_stride_out;
472            p_src += u_stride;
473            memcpy((void *)p_dest,(void *) p_src, u_width);
474            p_dest += u_stride_out;
475            p_src += u_stride;
476            memcpy((void *)p_destu,(void *) p_srcu, u_widthuv);
477            memcpy((void *)p_destv, (void *)p_srcv, u_widthuv);
478            p_destu += u_stride_out_uv;
479            p_destv += u_stride_out_uv;
480            p_srcu += u_stride_uv;
481            p_srcv += u_stride_uv;
482        }
483    }
484    else
485    {
486        /* black lines at the bottom of the image */
487        p_src = (unsigned char *) &plane_in[0].pac_data[plane_in[0].u_topleft];
488        p_srcu = (unsigned char *) &plane_in[1].pac_data[plane_in[1].u_topleft];
489        p_srcv = (unsigned char *) &plane_in[2].pac_data[plane_in[2].u_topleft];
490
491        /* copy from source image image */
492        for (j = (nb_black_lines >> 1); j != 0; j--)
493        {
494            memcpy((void *)p_dest, (void *)p_src, u_width);
495            p_dest += u_stride_out;
496            p_src += u_stride;
497            memcpy((void *)p_dest,(void *) p_src, u_width);
498            p_dest += u_stride_out;
499            p_src += u_stride;
500            memcpy((void *)p_destu,(void *) p_srcu, u_widthuv);
501            memcpy((void *)p_destv,(void *) p_srcv, u_widthuv);
502            p_destu += u_stride_out_uv;
503            p_destv += u_stride_out_uv;
504            p_srcu += u_stride_uv;
505            p_srcv += u_stride_uv;
506        }
507
508        /* write black lines*/
509        /* the pointers to p_dest, p_destu and p_destv are used through the two loops "for" */
510        for (j = (u_height - nb_black_lines) >> 1; j != 0; j--)
511        {
512            memset((void *)p_dest, 0,u_width);
513            p_dest += u_stride_out;
514            memset((void *)p_dest, 0,u_width);
515            p_dest += u_stride_out;
516            memset((void *)p_destu, 128,u_widthuv);
517            memset((void *)p_destv, 128,u_widthuv);
518            p_destu += u_stride_out_uv;
519            p_destv += u_stride_out_uv;
520        }
521    }
522
523    return 0;
524}
525
526/**
527 *************************************************************************************************
528 * M4OSA_ERR M4VIFI_ImageBlendingonYUV420 (void *pUserData,
529 *                                                  M4VIFI_ImagePlane *pPlaneIn1,
530 *                                                  M4VIFI_ImagePlane *pPlaneIn2,
531 *                                                  M4VIFI_ImagePlane *pPlaneOut,
532 *                                                  UInt32 Progress)
533 * @brief   Blends two YUV 4:2:0 Planar images.
534 * @note    Blends YUV420 planar images,
535 *          Map the value of progress from (0 - 1000) to (0 - 1024)
536 *          Set the range of blendingfactor,
537 *                  1. from 0 to (Progress << 1)            ;for Progress <= 512
538 *                  2. from (( Progress - 512)<< 1) to 1024 ;otherwise
539 *          Set the increment of blendingfactor for each element in the image row by the factor,
540 *                  =  (Range-1) / (image width-1)  ;for width >= range
541 *                  =  (Range) / (image width)      ;otherwise
542 *          Loop on each(= i) row of output Y plane (steps of 2)
543 *              Loop on each(= j) column of output Y plane (steps of 2)
544 *                  Get four Y samples and one U & V sample from two input YUV4:2:0 images and
545 *                  Compute four Y sample and one U & V sample for output YUV4:2:0 image
546 *                      using the following,
547 *                  Out(i,j) = blendingfactor(i,j) * In1(i,j)+ (l - blendingfactor(i,j)) *In2(i,j)
548 *              end loop column
549 *          end loop row.
550 * @param   pUserData: (IN)  User Specific Parameter
551 * @param   pPlaneIn1: (IN)  Pointer to an array of image plane structures maintained
552 *           for Y, U and V planes.
553 * @param   pPlaneIn2: (IN)  Pointer to an array of image plane structures maintained
554 *           for Y, U and V planes.
555 * @param   pPlaneOut: (OUT) Pointer to an array of image plane structures maintained
556 *           for Y, U and V planes.
557 * @param   Progress:  (IN)  Progress value (varies between 0 and 1000)
558 * @return  M4VIFI_OK: No error
559 * @return  M4VIFI_ILLEGAL_FRAME_HEIGHT: Error in height
560 * @return  M4VIFI_ILLEGAL_FRAME_WIDTH:  Error in width
561 *************************************************************************************************
562*/
563
564/** Check for value is EVEN */
565#ifndef IS_EVEN
566#define IS_EVEN(a)  (!(a & 0x01))
567#endif
568
569/** Used for fixed point implementation */
570#ifndef MAX_SHORT
571#define MAX_SHORT   0x10000
572#endif
573
574#ifndef NULL
575#define NULL    0
576#endif
577
578#ifndef FALSE
579#define FALSE   0
580#define TRUE    !FALSE
581#endif
582
583unsigned char M4VIFI_ImageBlendingonYUV420 (void *pUserData,
584                                            M4ViComImagePlane *pPlaneIn1,
585                                            M4ViComImagePlane *pPlaneIn2,
586                                            M4ViComImagePlane *pPlaneOut,
587                                            UInt32 Progress)
588{
589    UInt8    *pu8_data_Y_start1,*pu8_data_U_start1,*pu8_data_V_start1;
590    UInt8    *pu8_data_Y_start2,*pu8_data_U_start2,*pu8_data_V_start2;
591    UInt8    *pu8_data_Y_start3,*pu8_data_U_start3,*pu8_data_V_start3;
592    UInt8    *pu8_data_Y_current1, *pu8_data_Y_next1, *pu8_data_U1, *pu8_data_V1;
593    UInt8    *pu8_data_Y_current2, *pu8_data_Y_next2, *pu8_data_U2, *pu8_data_V2;
594    UInt8    *pu8_data_Y_current3,*pu8_data_Y_next3, *pu8_data_U3, *pu8_data_V3;
595    UInt32   u32_stride_Y1, u32_stride2_Y1, u32_stride_U1, u32_stride_V1;
596    UInt32   u32_stride_Y2, u32_stride2_Y2, u32_stride_U2, u32_stride_V2;
597    UInt32   u32_stride_Y3, u32_stride2_Y3, u32_stride_U3, u32_stride_V3;
598    UInt32   u32_height,  u32_width;
599    UInt32   u32_blendfactor, u32_startA, u32_endA, u32_blend_inc, u32_x_accum;
600    UInt32   u32_col, u32_row, u32_rangeA, u32_progress;
601    UInt32   u32_U1,u32_V1,u32_U2,u32_V2, u32_Y1, u32_Y2;
602
603
604    /* Check the Y plane height is EVEN and image plane heights are same */
605    if( (IS_EVEN(pPlaneIn1[0].u_height) == FALSE)                ||
606        (IS_EVEN(pPlaneIn2[0].u_height) == FALSE)                ||
607        (IS_EVEN(pPlaneOut[0].u_height) == FALSE)                ||
608        (pPlaneIn1[0].u_height != pPlaneOut[0].u_height)         ||
609        (pPlaneIn2[0].u_height != pPlaneOut[0].u_height) )
610    {
611        return M4VIFI_ILLEGAL_FRAME_HEIGHT;
612    }
613
614    /* Check the Y plane width is EVEN and image plane widths are same */
615    if( (IS_EVEN(pPlaneIn1[0].u_width) == FALSE)                 ||
616        (IS_EVEN(pPlaneIn2[0].u_width) == FALSE)                 ||
617        (IS_EVEN(pPlaneOut[0].u_width) == FALSE)                 ||
618        (pPlaneIn1[0].u_width  != pPlaneOut[0].u_width)          ||
619        (pPlaneIn2[0].u_width  != pPlaneOut[0].u_width)  )
620    {
621        return M4VIFI_ILLEGAL_FRAME_WIDTH;
622    }
623
624    /* Set the pointer to the beginning of the input1 YUV420 image planes */
625    pu8_data_Y_start1 = pPlaneIn1[0].pac_data + pPlaneIn1[0].u_topleft;
626    pu8_data_U_start1 = pPlaneIn1[1].pac_data + pPlaneIn1[1].u_topleft;
627    pu8_data_V_start1 = pPlaneIn1[2].pac_data + pPlaneIn1[2].u_topleft;
628
629    /* Set the pointer to the beginning of the input2 YUV420 image planes */
630    pu8_data_Y_start2 = pPlaneIn2[0].pac_data + pPlaneIn2[0].u_topleft;
631    pu8_data_U_start2 = pPlaneIn2[1].pac_data + pPlaneIn2[1].u_topleft;
632    pu8_data_V_start2 = pPlaneIn2[2].pac_data + pPlaneIn2[2].u_topleft;
633
634    /* Set the pointer to the beginning of the output YUV420 image planes */
635    pu8_data_Y_start3 = pPlaneOut[0].pac_data + pPlaneOut[0].u_topleft;
636    pu8_data_U_start3 = pPlaneOut[1].pac_data + pPlaneOut[1].u_topleft;
637    pu8_data_V_start3 = pPlaneOut[2].pac_data + pPlaneOut[2].u_topleft;
638
639    /* Set the stride for the next row in each input1 YUV420 plane */
640    u32_stride_Y1 = pPlaneIn1[0].u_stride;
641    u32_stride_U1 = pPlaneIn1[1].u_stride;
642    u32_stride_V1 = pPlaneIn1[2].u_stride;
643
644    /* Set the stride for the next row in each input2 YUV420 plane */
645    u32_stride_Y2 = pPlaneIn2[0].u_stride;
646    u32_stride_U2 = pPlaneIn2[1].u_stride;
647    u32_stride_V2 = pPlaneIn2[2].u_stride;
648
649    /* Set the stride for the next row in each output YUV420 plane */
650    u32_stride_Y3 = pPlaneOut[0].u_stride;
651    u32_stride_U3 = pPlaneOut[1].u_stride;
652    u32_stride_V3 = pPlaneOut[2].u_stride;
653
654    u32_stride2_Y1   = u32_stride_Y1 << 1;
655    u32_stride2_Y2   = u32_stride_Y2 << 1;
656    u32_stride2_Y3   = u32_stride_Y3 << 1;
657
658    /* Get the size of the output image */
659    u32_height = pPlaneOut[0].u_height;
660    u32_width  = pPlaneOut[0].u_width;
661
662    /* User Specified Progress value */
663    u32_progress = Progress;
664
665    /* Map Progress value from (0 - 1000) to (0 - 1024) -> for optimisation */
666    if(u32_progress < 1000)
667        u32_progress = ((u32_progress << 10) / 1000);
668    else
669        u32_progress = 1024;
670
671    /* Set the range of blendingfactor */
672    if(u32_progress <= 512)
673    {
674        u32_startA = 0;
675        u32_endA   = (u32_progress << 1);
676    }
677    else /* u32_progress > 512 */
678    {
679        u32_startA = (u32_progress - 512) << 1;
680        u32_endA   =  1024;
681    }
682    u32_rangeA = u32_endA - u32_startA;
683
684    /* Set the increment of blendingfactor for each element in the image row */
685    if ((u32_width >= u32_rangeA) && (u32_rangeA > 0) )
686    {
687        u32_blend_inc   = ((u32_rangeA-1) * MAX_SHORT) / (u32_width - 1);
688    }
689    else /* (u32_width < u32_rangeA) || (u32_rangeA < 0) */
690    {
691        u32_blend_inc   = (u32_rangeA * MAX_SHORT) / (u32_width);
692    }
693
694    /* Two YUV420 rows are computed at each pass */
695    for (u32_row = u32_height; u32_row != 0; u32_row -=2)
696    {
697        /* Set pointers to the beginning of the row for each input image1 plane */
698        pu8_data_Y_current1 = pu8_data_Y_start1;
699        pu8_data_U1 = pu8_data_U_start1;
700        pu8_data_V1 = pu8_data_V_start1;
701
702        /* Set pointers to the beginning of the row for each input image2 plane */
703        pu8_data_Y_current2 = pu8_data_Y_start2;
704        pu8_data_U2 = pu8_data_U_start2;
705        pu8_data_V2 = pu8_data_V_start2;
706
707        /* Set pointers to the beginning of the row for each output image plane */
708        pu8_data_Y_current3 = pu8_data_Y_start3;
709        pu8_data_U3 = pu8_data_U_start3;
710        pu8_data_V3 = pu8_data_V_start3;
711
712        /* Set pointers to the beginning of the next row for image luma plane */
713        pu8_data_Y_next1 = pu8_data_Y_current1 + u32_stride_Y1;
714        pu8_data_Y_next2 = pu8_data_Y_current2 + u32_stride_Y2;
715        pu8_data_Y_next3 = pu8_data_Y_current3 + u32_stride_Y3;
716
717        /* Initialise blendfactor */
718        u32_blendfactor   = u32_startA;
719        /* Blendfactor Increment accumulator */
720        u32_x_accum = 0;
721
722        /* Loop on each column of the output image */
723        for (u32_col = u32_width; u32_col != 0 ; u32_col -=2)
724        {
725            /* Update the blending factor */
726            u32_blendfactor = u32_startA + (u32_x_accum >> 16);
727
728            /* Get Luma value (x,y) of input Image1 */
729            u32_Y1 = *pu8_data_Y_current1++;
730
731            /* Get chrominance2 value */
732            u32_U1 = *pu8_data_U1++;
733            u32_V1 = *pu8_data_V1++;
734
735            /* Get Luma value (x,y) of input Image2 */
736            u32_Y2 = *pu8_data_Y_current2++;
737
738            /* Get chrominance2 value */
739            u32_U2 = *pu8_data_U2++;
740            u32_V2 = *pu8_data_V2++;
741
742            /* Compute Luma value (x,y) of Output image */
743            *pu8_data_Y_current3++  = (UInt8)((u32_blendfactor * u32_Y2 +
744                                                     (1024 - u32_blendfactor)*u32_Y1) >> 10);
745            /* Compute chroma(U) value of Output image */
746            *pu8_data_U3++          = (UInt8)((u32_blendfactor * u32_U2 +
747                                                     (1024 - u32_blendfactor)*u32_U1) >> 10);
748            /* Compute chroma(V) value of Output image */
749            *pu8_data_V3++          = (UInt8)((u32_blendfactor * u32_V2 +
750                                                     (1024 - u32_blendfactor)*u32_V1) >> 10);
751
752            /* Get Luma value (x,y+1) of input Image1 */
753            u32_Y1 = *pu8_data_Y_next1++;
754
755             /* Get Luma value (x,y+1) of input Image2 */
756            u32_Y2 = *pu8_data_Y_next2++;
757
758            /* Compute Luma value (x,y+1) of Output image*/
759            *pu8_data_Y_next3++ = (UInt8)((u32_blendfactor * u32_Y2 +
760                                                    (1024 - u32_blendfactor)*u32_Y1) >> 10);
761            /* Update accumulator */
762            u32_x_accum += u32_blend_inc;
763
764            /* Update the blending factor */
765            u32_blendfactor = u32_startA + (u32_x_accum >> 16);
766
767            /* Get Luma value (x+1,y) of input Image1 */
768            u32_Y1 = *pu8_data_Y_current1++;
769
770            /* Get Luma value (x+1,y) of input Image2 */
771            u32_Y2 = *pu8_data_Y_current2++;
772
773            /* Compute Luma value (x+1,y) of Output image*/
774            *pu8_data_Y_current3++ = (UInt8)((u32_blendfactor * u32_Y2 +
775                                                 (1024 - u32_blendfactor)*u32_Y1) >> 10);
776
777            /* Get Luma value (x+1,y+1) of input Image1 */
778            u32_Y1 = *pu8_data_Y_next1++;
779
780            /* Get Luma value (x+1,y+1) of input Image2 */
781            u32_Y2 = *pu8_data_Y_next2++;
782
783            /* Compute Luma value (x+1,y+1) of Output image*/
784            *pu8_data_Y_next3++ = (UInt8)((u32_blendfactor * u32_Y2 +
785                                                 (1024 - u32_blendfactor)*u32_Y1) >> 10);
786            /* Update accumulator */
787            u32_x_accum += u32_blend_inc;
788
789            /* Working pointers are incremented just after each storage */
790
791        }/* End of row scanning */
792
793        /* Update working pointer of input image1 for next row */
794        pu8_data_Y_start1 += u32_stride2_Y1;
795        pu8_data_U_start1 += u32_stride_U1;
796        pu8_data_V_start1 += u32_stride_V1;
797
798        /* Update working pointer of input image2 for next row */
799        pu8_data_Y_start2 += u32_stride2_Y2;
800        pu8_data_U_start2 += u32_stride_U2;
801        pu8_data_V_start2 += u32_stride_V2;
802
803        /* Update working pointer of output image for next row */
804        pu8_data_Y_start3 += u32_stride2_Y3;
805        pu8_data_U_start3 += u32_stride_U3;
806        pu8_data_V_start3 += u32_stride_V3;
807
808    }/* End of column scanning */
809
810    return M4VIFI_OK;
811}
812/* End of file M4VIFI_ImageBlendingonYUV420.c */
813
814