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