1 /* 2 * Copyright (C) 2011 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 /** 17 ****************************************************************************** 18 * @file M4TRAN_transition.c 19 * @brief 20 ****************************************************************************** 21 */ 22 23 /** 24 * OSAL (memset and memcpy) ***/ 25 #include "M4OSA_Memory.h" 26 27 #include "M4VFL_transition.h" 28 29 #include <string.h> 30 31 #ifdef LITTLE_ENDIAN 32 #define M4VFL_SWAP_SHORT(a) a = ((a & 0xFF) << 8) | ((a & 0xFF00) >> 8) 33 #else 34 #define M4VFL_SWAP_SHORT(a) 35 #endif 36 37 #define LUM_FACTOR_MAX 10 38 39 40 unsigned char M4VFL_modifyLumaByStep(M4ViComImagePlane *plane_in, M4ViComImagePlane *plane_out, 41 M4VFL_ModifLumParam *lum_param, void *user_data) 42 { 43 unsigned short *p_src, *p_dest, *p_src_line, *p_dest_line; 44 unsigned long pix_src; 45 unsigned long u_outpx, u_outpx2; 46 unsigned long u_width, u_stride, u_stride_out,u_height, pix; 47 unsigned long lf1, lf2, lf3; 48 long i, j; 49 50 if (lum_param->copy_chroma != 0) 51 { 52 /* copy chroma plane */ 53 54 } 55 56 /* apply luma factor */ 57 u_width = plane_in[0].u_width; 58 u_height = plane_in[0].u_height; 59 u_stride = (plane_in[0].u_stride >> 1); 60 u_stride_out = (plane_out[0].u_stride >> 1); 61 p_dest = (unsigned short *) &plane_out[0].pac_data[plane_out[0].u_topleft]; 62 p_src = (unsigned short *) &plane_in[0].pac_data[plane_in[0].u_topleft]; 63 p_dest_line = p_dest; 64 p_src_line = p_src; 65 66 switch(lum_param->lum_factor) 67 { 68 case 0: 69 /* very specific case : set luma plane to 16 */ 70 for (j = u_height; j != 0; j--) 71 { 72 memset((void *)p_dest,16, u_width); 73 p_dest += u_stride_out; 74 } 75 return 0; 76 77 case 1: 78 /* 0.25 */ 79 lf1 = 6; lf2 = 6; lf3 = 7; 80 break; 81 case 2: 82 /* 0.375 */ 83 lf1 = 7; lf2 = 7; lf3 = 7; 84 break; 85 case 3: 86 /* 0.5 */ 87 lf1 = 7; lf2 = 7; lf3 = 8; 88 break; 89 case 4: 90 /* 0.625 */ 91 lf1 = 7; lf2 = 8; lf3 = 8; 92 break; 93 case 5: 94 /* 0.75 */ 95 lf1 = 8; lf2 = 8; lf3 = 8; 96 break; 97 case 6: 98 /* 0.875 */ 99 lf1 = 9; lf2 = 8; lf3 = 7; 100 break; 101 default: 102 lf1 = 8; lf2 = 8; lf3 = 9; 103 break; 104 } 105 106 for (j = u_height; j != 0; j--) 107 { 108 p_dest = p_dest_line; 109 p_src = p_src_line; 110 for (i = (u_width >> 1); i != 0; i--) 111 { 112 pix_src = (unsigned long) *p_src++; 113 pix = pix_src & 0xFF; 114 u_outpx = (((pix << lf1) + (pix << lf2) + (pix << lf3) ) >> LUM_FACTOR_MAX); 115 pix = ((pix_src & 0xFF00) >> 8); 116 u_outpx2 = ((((pix << lf1) + (pix << lf2) + (pix << lf3) ) >> LUM_FACTOR_MAX)<< 8) ; 117 *p_dest++ = (unsigned short) (u_outpx2 | u_outpx); 118 } 119 p_dest_line += u_stride_out; 120 p_src_line += u_stride; 121 } 122 return 0; 123 } 124 125 126 unsigned char M4VFL_modifyLumaWithScale(M4ViComImagePlane *plane_in, 127 M4ViComImagePlane *plane_out, 128 unsigned long lum_factor, 129 void *user_data) 130 { 131 unsigned short *p_src, *p_dest, *p_src_line, *p_dest_line; 132 unsigned char *p_csrc, *p_cdest, *p_csrc_line, *p_cdest_line; 133 unsigned long pix_src; 134 unsigned long u_outpx, u_outpx2; 135 unsigned long u_width, u_stride, u_stride_out,u_height, pix; 136 long i, j; 137 138 /* copy or filter chroma */ 139 u_width = plane_in[1].u_width; 140 u_height = plane_in[1].u_height; 141 u_stride = plane_in[1].u_stride; 142 u_stride_out = plane_out[1].u_stride; 143 p_cdest_line = (unsigned char *) &plane_out[1].pac_data[plane_out[1].u_topleft]; 144 p_csrc_line = (unsigned char *) &plane_in[1].pac_data[plane_in[1].u_topleft]; 145 146 if (lum_factor > 256) 147 { 148 p_cdest = (unsigned char *) &plane_out[2].pac_data[plane_out[2].u_topleft]; 149 p_csrc = (unsigned char *) &plane_in[2].pac_data[plane_in[2].u_topleft]; 150 /* copy chroma */ 151 for (j = u_height; j != 0; j--) 152 { 153 for (i = u_width; i != 0; i--) 154 { 155 memcpy((void *)p_cdest_line, (void *)p_csrc_line, u_width); 156 memcpy((void *)p_cdest,(void *) p_csrc, u_width); 157 } 158 p_cdest_line += u_stride_out; 159 p_cdest += u_stride_out; 160 p_csrc_line += u_stride; 161 p_csrc += u_stride; 162 } 163 } 164 else 165 { 166 /* filter chroma */ 167 pix = (1024 - lum_factor) << 7; 168 for (j = u_height; j != 0; j--) 169 { 170 p_cdest = p_cdest_line; 171 p_csrc = p_csrc_line; 172 for (i = u_width; i != 0; i--) 173 { 174 *p_cdest++ = ((pix + (*p_csrc++ & 0xFF) * lum_factor) >> LUM_FACTOR_MAX); 175 } 176 p_cdest_line += u_stride_out; 177 p_csrc_line += u_stride; 178 } 179 p_cdest_line = (unsigned char *) &plane_out[2].pac_data[plane_out[2].u_topleft]; 180 p_csrc_line = (unsigned char *) &plane_in[2].pac_data[plane_in[2].u_topleft]; 181 for (j = u_height; j != 0; j--) 182 { 183 p_cdest = p_cdest_line; 184 p_csrc = p_csrc_line; 185 for (i = u_width; i != 0; i--) 186 { 187 *p_cdest++ = ((pix + (*p_csrc & 0xFF) * lum_factor) >> LUM_FACTOR_MAX); 188 } 189 p_cdest_line += u_stride_out; 190 p_csrc_line += u_stride; 191 } 192 } 193 /* apply luma factor */ 194 u_width = plane_in[0].u_width; 195 u_height = plane_in[0].u_height; 196 u_stride = (plane_in[0].u_stride >> 1); 197 u_stride_out = (plane_out[0].u_stride >> 1); 198 p_dest = (unsigned short *) &plane_out[0].pac_data[plane_out[0].u_topleft]; 199 p_src = (unsigned short *) &plane_in[0].pac_data[plane_in[0].u_topleft]; 200 p_dest_line = p_dest; 201 p_src_line = p_src; 202 203 for (j = u_height; j != 0; j--) 204 { 205 p_dest = p_dest_line; 206 p_src = p_src_line; 207 for (i = (u_width >> 1); i != 0; i--) 208 { 209 pix_src = (unsigned long) *p_src++; 210 pix = pix_src & 0xFF; 211 u_outpx = ((pix * lum_factor) >> LUM_FACTOR_MAX); 212 pix = ((pix_src & 0xFF00) >> 8); 213 u_outpx2 = (((pix * lum_factor) >> LUM_FACTOR_MAX)<< 8) ; 214 *p_dest++ = (unsigned short) (u_outpx2 | u_outpx); 215 } 216 p_dest_line += u_stride_out; 217 p_src_line += u_stride; 218 } 219 220 return 0; 221 } 222 223 /** 224 ************************************************************************************************* 225 * M4OSA_ERR M4VIFI_ImageBlendingonYUV420 (void *pUserData, 226 * M4VIFI_ImagePlane *pPlaneIn1, 227 * M4VIFI_ImagePlane *pPlaneIn2, 228 * M4VIFI_ImagePlane *pPlaneOut, 229 * UInt32 Progress) 230 * @brief Blends two YUV 4:2:0 Planar images. 231 * @note Blends YUV420 planar images, 232 * Map the value of progress from (0 - 1000) to (0 - 1024) 233 * Set the range of blendingfactor, 234 * 1. from 0 to (Progress << 1) ;for Progress <= 512 235 * 2. from (( Progress - 512)<< 1) to 1024 ;otherwise 236 * Set the increment of blendingfactor for each element in the image row by the factor, 237 * = (Range-1) / (image width-1) ;for width >= range 238 * = (Range) / (image width) ;otherwise 239 * Loop on each(= i) row of output Y plane (steps of 2) 240 * Loop on each(= j) column of output Y plane (steps of 2) 241 * Get four Y samples and one U & V sample from two input YUV4:2:0 images and 242 * Compute four Y sample and one U & V sample for output YUV4:2:0 image 243 * using the following, 244 * Out(i,j) = blendingfactor(i,j) * In1(i,j)+ (l - blendingfactor(i,j)) *In2(i,j) 245 * end loop column 246 * end loop row. 247 * @param pUserData: (IN) User Specific Parameter 248 * @param pPlaneIn1: (IN) Pointer to an array of image plane structures maintained 249 * for Y, U and V planes. 250 * @param pPlaneIn2: (IN) Pointer to an array of image plane structures maintained 251 * for Y, U and V planes. 252 * @param pPlaneOut: (OUT) Pointer to an array of image plane structures maintained 253 * for Y, U and V planes. 254 * @param Progress: (IN) Progress value (varies between 0 and 1000) 255 * @return M4VIFI_OK: No error 256 * @return M4VIFI_ILLEGAL_FRAME_HEIGHT: Error in height 257 * @return M4VIFI_ILLEGAL_FRAME_WIDTH: Error in width 258 ************************************************************************************************* 259 */ 260 261 /** Check for value is EVEN */ 262 #ifndef IS_EVEN 263 #define IS_EVEN(a) (!(a & 0x01)) 264 #endif 265 266 /** Used for fixed point implementation */ 267 #ifndef MAX_SHORT 268 #define MAX_SHORT 0x10000 269 #endif 270 271 #ifndef NULL 272 #define NULL 0 273 #endif 274 275 #ifndef FALSE 276 #define FALSE 0 277 #define TRUE !FALSE 278 #endif 279 280 unsigned char M4VIFI_ImageBlendingonYUV420 (void *pUserData, 281 M4ViComImagePlane *pPlaneIn1, 282 M4ViComImagePlane *pPlaneIn2, 283 M4ViComImagePlane *pPlaneOut, 284 UInt32 Progress) 285 { 286 UInt8 *pu8_data_Y_start1,*pu8_data_U_start1,*pu8_data_V_start1; 287 UInt8 *pu8_data_Y_start2,*pu8_data_U_start2,*pu8_data_V_start2; 288 UInt8 *pu8_data_Y_start3,*pu8_data_U_start3,*pu8_data_V_start3; 289 UInt8 *pu8_data_Y_current1, *pu8_data_Y_next1, *pu8_data_U1, *pu8_data_V1; 290 UInt8 *pu8_data_Y_current2, *pu8_data_Y_next2, *pu8_data_U2, *pu8_data_V2; 291 UInt8 *pu8_data_Y_current3,*pu8_data_Y_next3, *pu8_data_U3, *pu8_data_V3; 292 UInt32 u32_stride_Y1, u32_stride2_Y1, u32_stride_U1, u32_stride_V1; 293 UInt32 u32_stride_Y2, u32_stride2_Y2, u32_stride_U2, u32_stride_V2; 294 UInt32 u32_stride_Y3, u32_stride2_Y3, u32_stride_U3, u32_stride_V3; 295 UInt32 u32_height, u32_width; 296 UInt32 u32_blendfactor, u32_startA, u32_endA, u32_blend_inc, u32_x_accum; 297 UInt32 u32_col, u32_row, u32_rangeA, u32_progress; 298 UInt32 u32_U1,u32_V1,u32_U2,u32_V2, u32_Y1, u32_Y2; 299 300 301 /* Check the Y plane height is EVEN and image plane heights are same */ 302 if( (IS_EVEN(pPlaneIn1[0].u_height) == FALSE) || 303 (IS_EVEN(pPlaneIn2[0].u_height) == FALSE) || 304 (IS_EVEN(pPlaneOut[0].u_height) == FALSE) || 305 (pPlaneIn1[0].u_height != pPlaneOut[0].u_height) || 306 (pPlaneIn2[0].u_height != pPlaneOut[0].u_height) ) 307 { 308 return M4VIFI_ILLEGAL_FRAME_HEIGHT; 309 } 310 311 /* Check the Y plane width is EVEN and image plane widths are same */ 312 if( (IS_EVEN(pPlaneIn1[0].u_width) == FALSE) || 313 (IS_EVEN(pPlaneIn2[0].u_width) == FALSE) || 314 (IS_EVEN(pPlaneOut[0].u_width) == FALSE) || 315 (pPlaneIn1[0].u_width != pPlaneOut[0].u_width) || 316 (pPlaneIn2[0].u_width != pPlaneOut[0].u_width) ) 317 { 318 return M4VIFI_ILLEGAL_FRAME_WIDTH; 319 } 320 321 /* Set the pointer to the beginning of the input1 YUV420 image planes */ 322 pu8_data_Y_start1 = pPlaneIn1[0].pac_data + pPlaneIn1[0].u_topleft; 323 pu8_data_U_start1 = pPlaneIn1[1].pac_data + pPlaneIn1[1].u_topleft; 324 pu8_data_V_start1 = pPlaneIn1[2].pac_data + pPlaneIn1[2].u_topleft; 325 326 /* Set the pointer to the beginning of the input2 YUV420 image planes */ 327 pu8_data_Y_start2 = pPlaneIn2[0].pac_data + pPlaneIn2[0].u_topleft; 328 pu8_data_U_start2 = pPlaneIn2[1].pac_data + pPlaneIn2[1].u_topleft; 329 pu8_data_V_start2 = pPlaneIn2[2].pac_data + pPlaneIn2[2].u_topleft; 330 331 /* Set the pointer to the beginning of the output YUV420 image planes */ 332 pu8_data_Y_start3 = pPlaneOut[0].pac_data + pPlaneOut[0].u_topleft; 333 pu8_data_U_start3 = pPlaneOut[1].pac_data + pPlaneOut[1].u_topleft; 334 pu8_data_V_start3 = pPlaneOut[2].pac_data + pPlaneOut[2].u_topleft; 335 336 /* Set the stride for the next row in each input1 YUV420 plane */ 337 u32_stride_Y1 = pPlaneIn1[0].u_stride; 338 u32_stride_U1 = pPlaneIn1[1].u_stride; 339 u32_stride_V1 = pPlaneIn1[2].u_stride; 340 341 /* Set the stride for the next row in each input2 YUV420 plane */ 342 u32_stride_Y2 = pPlaneIn2[0].u_stride; 343 u32_stride_U2 = pPlaneIn2[1].u_stride; 344 u32_stride_V2 = pPlaneIn2[2].u_stride; 345 346 /* Set the stride for the next row in each output YUV420 plane */ 347 u32_stride_Y3 = pPlaneOut[0].u_stride; 348 u32_stride_U3 = pPlaneOut[1].u_stride; 349 u32_stride_V3 = pPlaneOut[2].u_stride; 350 351 u32_stride2_Y1 = u32_stride_Y1 << 1; 352 u32_stride2_Y2 = u32_stride_Y2 << 1; 353 u32_stride2_Y3 = u32_stride_Y3 << 1; 354 355 /* Get the size of the output image */ 356 u32_height = pPlaneOut[0].u_height; 357 u32_width = pPlaneOut[0].u_width; 358 359 /* User Specified Progress value */ 360 u32_progress = Progress; 361 362 /* Map Progress value from (0 - 1000) to (0 - 1024) -> for optimisation */ 363 if(u32_progress < 1000) 364 u32_progress = ((u32_progress << 10) / 1000); 365 else 366 u32_progress = 1024; 367 368 /* Set the range of blendingfactor */ 369 if(u32_progress <= 512) 370 { 371 u32_startA = 0; 372 u32_endA = (u32_progress << 1); 373 } 374 else /* u32_progress > 512 */ 375 { 376 u32_startA = (u32_progress - 512) << 1; 377 u32_endA = 1024; 378 } 379 u32_rangeA = u32_endA - u32_startA; 380 381 /* Set the increment of blendingfactor for each element in the image row */ 382 if ((u32_width >= u32_rangeA) && (u32_rangeA > 0) ) 383 { 384 u32_blend_inc = ((u32_rangeA-1) * MAX_SHORT) / (u32_width - 1); 385 } 386 else /* (u32_width < u32_rangeA) || (u32_rangeA < 0) */ 387 { 388 u32_blend_inc = (u32_rangeA * MAX_SHORT) / (u32_width); 389 } 390 391 /* Two YUV420 rows are computed at each pass */ 392 for (u32_row = u32_height; u32_row != 0; u32_row -=2) 393 { 394 /* Set pointers to the beginning of the row for each input image1 plane */ 395 pu8_data_Y_current1 = pu8_data_Y_start1; 396 pu8_data_U1 = pu8_data_U_start1; 397 pu8_data_V1 = pu8_data_V_start1; 398 399 /* Set pointers to the beginning of the row for each input image2 plane */ 400 pu8_data_Y_current2 = pu8_data_Y_start2; 401 pu8_data_U2 = pu8_data_U_start2; 402 pu8_data_V2 = pu8_data_V_start2; 403 404 /* Set pointers to the beginning of the row for each output image plane */ 405 pu8_data_Y_current3 = pu8_data_Y_start3; 406 pu8_data_U3 = pu8_data_U_start3; 407 pu8_data_V3 = pu8_data_V_start3; 408 409 /* Set pointers to the beginning of the next row for image luma plane */ 410 pu8_data_Y_next1 = pu8_data_Y_current1 + u32_stride_Y1; 411 pu8_data_Y_next2 = pu8_data_Y_current2 + u32_stride_Y2; 412 pu8_data_Y_next3 = pu8_data_Y_current3 + u32_stride_Y3; 413 414 /* Initialise blendfactor */ 415 u32_blendfactor = u32_startA; 416 /* Blendfactor Increment accumulator */ 417 u32_x_accum = 0; 418 419 /* Loop on each column of the output image */ 420 for (u32_col = u32_width; u32_col != 0 ; u32_col -=2) 421 { 422 /* Update the blending factor */ 423 u32_blendfactor = u32_startA + (u32_x_accum >> 16); 424 425 /* Get Luma value (x,y) of input Image1 */ 426 u32_Y1 = *pu8_data_Y_current1++; 427 428 /* Get chrominance2 value */ 429 u32_U1 = *pu8_data_U1++; 430 u32_V1 = *pu8_data_V1++; 431 432 /* Get Luma value (x,y) of input Image2 */ 433 u32_Y2 = *pu8_data_Y_current2++; 434 435 /* Get chrominance2 value */ 436 u32_U2 = *pu8_data_U2++; 437 u32_V2 = *pu8_data_V2++; 438 439 /* Compute Luma value (x,y) of Output image */ 440 *pu8_data_Y_current3++ = (UInt8)((u32_blendfactor * u32_Y2 + 441 (1024 - u32_blendfactor)*u32_Y1) >> 10); 442 /* Compute chroma(U) value of Output image */ 443 *pu8_data_U3++ = (UInt8)((u32_blendfactor * u32_U2 + 444 (1024 - u32_blendfactor)*u32_U1) >> 10); 445 /* Compute chroma(V) value of Output image */ 446 *pu8_data_V3++ = (UInt8)((u32_blendfactor * u32_V2 + 447 (1024 - u32_blendfactor)*u32_V1) >> 10); 448 449 /* Get Luma value (x,y+1) of input Image1 */ 450 u32_Y1 = *pu8_data_Y_next1++; 451 452 /* Get Luma value (x,y+1) of input Image2 */ 453 u32_Y2 = *pu8_data_Y_next2++; 454 455 /* Compute Luma value (x,y+1) of Output image*/ 456 *pu8_data_Y_next3++ = (UInt8)((u32_blendfactor * u32_Y2 + 457 (1024 - u32_blendfactor)*u32_Y1) >> 10); 458 /* Update accumulator */ 459 u32_x_accum += u32_blend_inc; 460 461 /* Update the blending factor */ 462 u32_blendfactor = u32_startA + (u32_x_accum >> 16); 463 464 /* Get Luma value (x+1,y) of input Image1 */ 465 u32_Y1 = *pu8_data_Y_current1++; 466 467 /* Get Luma value (x+1,y) of input Image2 */ 468 u32_Y2 = *pu8_data_Y_current2++; 469 470 /* Compute Luma value (x+1,y) of Output image*/ 471 *pu8_data_Y_current3++ = (UInt8)((u32_blendfactor * u32_Y2 + 472 (1024 - u32_blendfactor)*u32_Y1) >> 10); 473 474 /* Get Luma value (x+1,y+1) of input Image1 */ 475 u32_Y1 = *pu8_data_Y_next1++; 476 477 /* Get Luma value (x+1,y+1) of input Image2 */ 478 u32_Y2 = *pu8_data_Y_next2++; 479 480 /* Compute Luma value (x+1,y+1) of Output image*/ 481 *pu8_data_Y_next3++ = (UInt8)((u32_blendfactor * u32_Y2 + 482 (1024 - u32_blendfactor)*u32_Y1) >> 10); 483 /* Update accumulator */ 484 u32_x_accum += u32_blend_inc; 485 486 /* Working pointers are incremented just after each storage */ 487 488 }/* End of row scanning */ 489 490 /* Update working pointer of input image1 for next row */ 491 pu8_data_Y_start1 += u32_stride2_Y1; 492 pu8_data_U_start1 += u32_stride_U1; 493 pu8_data_V_start1 += u32_stride_V1; 494 495 /* Update working pointer of input image2 for next row */ 496 pu8_data_Y_start2 += u32_stride2_Y2; 497 pu8_data_U_start2 += u32_stride_U2; 498 pu8_data_V_start2 += u32_stride_V2; 499 500 /* Update working pointer of output image for next row */ 501 pu8_data_Y_start3 += u32_stride2_Y3; 502 pu8_data_U_start3 += u32_stride_U3; 503 pu8_data_V_start3 += u32_stride_V3; 504 505 }/* End of column scanning */ 506 507 return M4VIFI_OK; 508 } 509 /* End of file M4VIFI_ImageBlendingonYUV420.c */ 510 511