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