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