1 /* 2 * 3 * Copyright 2012 Samsung Electronics S.LSI Co. LTD 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 swconvertor.c 20 * 21 * @brief SEC_OMX specific define. It support MFC 6.x tiled. 22 * 23 * @author ShinWon Lee (shinwon.lee (at) samsung.com) 24 * 25 * @version 1.0 26 * 27 * @history 28 * 2012.02.01 : Create 29 */ 30 31 #include "stdio.h" 32 #include "stdlib.h" 33 #include "swconverter.h" 34 35 /* 2D Configurable tiled memory access (TM) 36 * Return the linear address from tiled position (x, y) */ 37 unsigned int Tile2D_To_Linear( 38 unsigned int width, 39 unsigned int height, 40 unsigned int xpos, 41 unsigned int ypos, 42 int crFlag) 43 { 44 int tileNumX; 45 int tileX, tileY; 46 int tileAddr; 47 int offset; 48 int addr; 49 50 width = ((width + 15) / 16) * 16; 51 tileNumX = width / 16; 52 53 /* crFlag - 0: Y plane, 1: CbCr plane */ 54 if (crFlag == 0) { 55 tileX = xpos / 16; 56 tileY = ypos / 16; 57 tileAddr = tileY * tileNumX + tileX; 58 offset = (ypos & 15) * 16 + (xpos & 15); 59 addr = (tileAddr << 8) | offset; 60 } else { 61 tileX = xpos / 16; 62 tileY = ypos / 8; 63 tileAddr = tileY * tileNumX + tileX; 64 offset = (ypos & 7) * 16 + (xpos & 15); 65 addr = (tileAddr << 7) | offset; 66 } 67 68 return addr; 69 } 70 71 /* 72 * De-interleaves src to dest1, dest2 73 * 74 * @param dest1 75 * Address of de-interleaved data[out] 76 * 77 * @param dest2 78 * Address of de-interleaved data[out] 79 * 80 * @param src 81 * Address of interleaved data[in] 82 * 83 * @param src_size 84 * Size of interleaved data[in] 85 */ 86 void csc_deinterleave_memcpy( 87 unsigned char *dest1, 88 unsigned char *dest2, 89 unsigned char *src, 90 unsigned int src_size) 91 { 92 unsigned int i = 0; 93 for(i=0; i<src_size/2; i++) { 94 dest1[i] = src[i*2]; 95 dest2[i] = src[i*2+1]; 96 } 97 } 98 99 /* 100 * Interleaves src1, src2 to dest 101 * 102 * @param dest 103 * Address of interleaved data[out] 104 * 105 * @param src1 106 * Address of de-interleaved data[in] 107 * 108 * @param src2 109 * Address of de-interleaved data[in] 110 * 111 * @param src_size 112 * Size of de-interleaved data[in] 113 */ 114 void csc_interleave_memcpy( 115 unsigned char *dest, 116 unsigned char *src1, 117 unsigned char *src2, 118 unsigned int src_size) 119 { 120 unsigned int i = 0; 121 for(i=0; i<src_size; i++) { 122 dest[i*2] = src1[i]; 123 dest[i*2+1] = src2[i]; 124 } 125 } 126 127 /* 128 * Converts tiled data to linear for mfc 6.x tiled 129 * 1. y of nv12t to y of yuv420p 130 * 2. y of nv12t to y of yuv420s 131 * 132 * @param dst 133 * y address of yuv420[out] 134 * 135 * @param src 136 * y address of nv12t[in] 137 * 138 * @param yuv420_width 139 * real width of yuv420[in] 140 * it should be even 141 * 142 * @param yuv420_height 143 * real height of yuv420[in] 144 * it should be even. 145 * 146 */ 147 void csc_tiled_to_linear_y( 148 unsigned char *y_dst, 149 unsigned char *y_src, 150 unsigned int width, 151 unsigned int height) 152 { 153 unsigned int i, j, k; 154 unsigned int aligned_width, aligned_height; 155 unsigned int tiled_width; 156 unsigned int src_offset, dst_offset; 157 158 aligned_height = height & (~0xF); 159 aligned_width = width & (~0xF); 160 tiled_width = ((width + 15) >> 4) << 4; 161 162 for (i = 0; i < aligned_height; i = i + 16) { 163 for (j = 0; j<aligned_width; j = j + 16) { 164 src_offset = (tiled_width * i) + (j << 4); 165 dst_offset = width * i + j; 166 for (k = 0; k < 8; k++) { 167 memcpy(y_dst + dst_offset, y_src + src_offset, 16); 168 src_offset += 16; 169 dst_offset += width; 170 memcpy(y_dst + dst_offset, y_src + src_offset, 16); 171 src_offset += 16; 172 dst_offset += width; 173 } 174 } 175 if (aligned_width != width) { 176 src_offset = (tiled_width * i) + (j << 4); 177 dst_offset = width * i + j; 178 for (k = 0; k < 8; k++) { 179 memcpy(y_dst + dst_offset, y_src + src_offset, width - j); 180 src_offset += 16; 181 dst_offset += width; 182 memcpy(y_dst + dst_offset, y_src + src_offset, width - j); 183 src_offset += 16; 184 dst_offset += width; 185 } 186 } 187 } 188 189 if (aligned_height != height) { 190 for (j = 0; j<aligned_width; j = j + 16) { 191 src_offset = (tiled_width * i) + (j << 4); 192 dst_offset = width * i + j; 193 for (k = 0; k < height - aligned_height; k = k + 2) { 194 memcpy(y_dst + dst_offset, y_src + src_offset, 16); 195 src_offset += 16; 196 dst_offset += width; 197 memcpy(y_dst + dst_offset, y_src + src_offset, 16); 198 src_offset += 16; 199 dst_offset += width; 200 } 201 } 202 if (aligned_width != width) { 203 src_offset = (tiled_width * i) + (j << 4); 204 dst_offset = width * i + j; 205 for (k = 0; k < height - aligned_height; k = k + 2) { 206 memcpy(y_dst + dst_offset, y_src + src_offset, width - j); 207 src_offset += 16; 208 dst_offset += width; 209 memcpy(y_dst + dst_offset, y_src + src_offset, width - j); 210 src_offset += 16; 211 dst_offset += width; 212 } 213 } 214 } 215 } 216 217 /* 218 * Converts tiled data to linear for mfc 6.x tiled 219 * 1. uv of nv12t to uv of yuv420s 220 * 221 * @param dst 222 * uv address of yuv420s[out] 223 * 224 * @param src 225 * uv address of nv12t[in] 226 * 227 * @param yuv420_width 228 * real width of yuv420s[in] 229 * 230 * @param yuv420_height 231 * real height of yuv420s[in] 232 * 233 */ 234 void csc_tiled_to_linear_uv( 235 unsigned char *uv_dst, 236 unsigned char *uv_src, 237 unsigned int width, 238 unsigned int height) 239 { 240 unsigned int i, j, k; 241 unsigned int aligned_width, aligned_height; 242 unsigned int tiled_width; 243 unsigned int src_offset, dst_offset; 244 245 aligned_height = height & (~0x7); 246 aligned_width = width & (~0xF); 247 tiled_width = ((width + 15) >> 4) << 4; 248 249 for (i = 0; i < aligned_height; i = i + 8) { 250 for (j = 0; j<aligned_width; j = j + 16) { 251 src_offset = (tiled_width * i) + (j << 3); 252 dst_offset = width * i + j; 253 for (k = 0; k < 4; k++) { 254 memcpy(uv_dst + dst_offset, uv_src + src_offset, 16); 255 src_offset += 16; 256 dst_offset += width; 257 memcpy(uv_dst + dst_offset, uv_src + src_offset, 16); 258 src_offset += 16; 259 dst_offset += width; 260 } 261 } 262 if (aligned_width != width) { 263 src_offset = (tiled_width * i) + (j << 3); 264 dst_offset = width * i + j; 265 for (k = 0; k < 4; k++) { 266 memcpy(uv_dst + dst_offset, uv_src + src_offset, width - j); 267 src_offset += 16; 268 dst_offset += width; 269 memcpy(uv_dst + dst_offset, uv_src + src_offset, width - j); 270 src_offset += 16; 271 dst_offset += width; 272 } 273 } 274 } 275 276 if (aligned_height != height) { 277 for (j = 0; j<aligned_width; j = j + 16) { 278 src_offset = (tiled_width * i) + (j << 3); 279 dst_offset = width * i + j; 280 for (k = 0; k < height - aligned_height; k = k + 1) { 281 memcpy(uv_dst + dst_offset, uv_src + src_offset, 16); 282 src_offset += 16; 283 dst_offset += width; 284 } 285 } 286 if (aligned_width != width) { 287 src_offset = (tiled_width * i) + (j << 3); 288 dst_offset = width * i + j; 289 for (k = 0; k < height - aligned_height; k = k + 1) { 290 memcpy(uv_dst + dst_offset, uv_src + src_offset, width - j); 291 src_offset += 16; 292 dst_offset += width; 293 } 294 } 295 } 296 } 297 298 /* 299 * Converts tiled data to linear for mfc 6.x tiled 300 * 1. uv of nt12t to uv of yuv420p 301 * 302 * @param u_dst 303 * u address of yuv420p[out] 304 * 305 * @param v_dst 306 * v address of yuv420p[out] 307 * 308 * @param uv_src 309 * uv address of nt12t[in] 310 * 311 * @param yuv420_width 312 * real width of yuv420p[in] 313 * 314 * @param yuv420_height 315 * real height of yuv420p[in] 316 */ 317 void csc_tiled_to_linear_uv_deinterleave( 318 unsigned char *u_dst, 319 unsigned char *v_dst, 320 unsigned char *uv_src, 321 unsigned int width, 322 unsigned int height) 323 { 324 unsigned int i, j, k; 325 unsigned int aligned_width, aligned_height; 326 unsigned int tiled_width; 327 unsigned int src_offset, dst_offset; 328 329 aligned_height = height & (~0x7); 330 aligned_width = width & (~0xF); 331 tiled_width = ((width + 15) >> 4) << 4; 332 333 for (i = 0; i < aligned_height; i = i + 8) { 334 for (j = 0; j<aligned_width; j = j + 16) { 335 src_offset = (tiled_width * i) + (j << 3); 336 dst_offset = (width >> 1) * i + (j >> 1); 337 for (k = 0; k < 4; k++) { 338 csc_deinterleave_memcpy(u_dst + dst_offset, v_dst + dst_offset, 339 uv_src + src_offset, 16); 340 src_offset += 16; 341 dst_offset += width >> 1; 342 csc_deinterleave_memcpy(u_dst + dst_offset, v_dst + dst_offset, 343 uv_src + src_offset, 16); 344 src_offset += 16; 345 dst_offset += width >> 1; 346 } 347 } 348 if (aligned_width != width) { 349 src_offset = (tiled_width * i) + (j << 3); 350 dst_offset = (width >> 1) * i + (j >> 1); 351 for (k = 0; k < 4; k++) { 352 csc_deinterleave_memcpy(u_dst + dst_offset, v_dst + dst_offset, 353 uv_src + src_offset, width - j); 354 src_offset += 16; 355 dst_offset += width >> 1; 356 csc_deinterleave_memcpy(u_dst + dst_offset, v_dst + dst_offset, 357 uv_src + src_offset, width - j); 358 src_offset += 16; 359 dst_offset += width >> 1; 360 } 361 } 362 } 363 if (aligned_height != height) { 364 for (j = 0; j<aligned_width; j = j + 16) { 365 src_offset = (tiled_width * i) + (j << 3); 366 dst_offset = (width >> 1) * i + (j >> 1); 367 for (k = 0; k < height - aligned_height; k = k + 1) { 368 csc_deinterleave_memcpy(u_dst + dst_offset, v_dst + dst_offset, 369 uv_src + src_offset, 16); 370 src_offset += 16; 371 dst_offset += width >> 1; 372 } 373 } 374 if (aligned_width != width) { 375 src_offset = (tiled_width * i) + (j << 3); 376 dst_offset = (width >> 1) * i + (j >> 1); 377 for (k = 0; k < height - aligned_height; k = k + 1) { 378 csc_deinterleave_memcpy(u_dst + dst_offset, v_dst + dst_offset, 379 uv_src + src_offset, width - j); 380 src_offset += 16; 381 dst_offset += width >> 1; 382 } 383 } 384 } 385 } 386 387 /* 388 * Converts linear data to tiled 389 * It supports mfc 6.x tiled 390 * 1. y of yuv420 to y of nv12t 391 * 392 * @param dst 393 * y address of nv12t[out] 394 * 395 * @param src 396 * y address of yuv420[in] 397 * 398 * @param yuv420_width 399 * real width of yuv420[in] 400 * it should be even 401 * 402 * @param yuv420_height 403 * real height of yuv420[in] 404 * it should be even. 405 * 406 */ 407 void csc_linear_to_tiled_y( 408 unsigned char *y_dst, 409 unsigned char *y_src, 410 unsigned int width, 411 unsigned int height) 412 { 413 414 } 415 416 /* 417 * Converts and interleaves linear data to tiled 418 * It supports mfc 6.x tiled 419 * 1. uv of nv12t to uv of yuv420 420 * 421 * @param dst 422 * uv address of nv12t[out] 423 * 424 * @param src 425 * u address of yuv420[in] 426 * 427 * @param src 428 * v address of yuv420[in] 429 * 430 * @param yuv420_width 431 * real width of yuv420[in] 432 * 433 * @param yuv420_height 434 * real height of yuv420[in] 435 * 436 */ 437 void csc_linear_to_tiled_uv( 438 unsigned char *uv_dst, 439 unsigned char *u_src, 440 unsigned char *v_src, 441 unsigned int width, 442 unsigned int height) 443 { 444 445 } 446 447 void Tile2D_To_YUV420(unsigned char *Y_plane, unsigned char *Cb_plane, unsigned char *Cr_plane, 448 unsigned int y_addr, unsigned int c_addr, unsigned int width, unsigned int height) 449 { 450 int x, y, j, k, l; 451 int out_of_width, actual_width; 452 unsigned int base_addr, data; 453 454 // y: 0, 16, 32, ... 455 for (y = 0; y < height; y += 16) { 456 // x: 0, 16, 32, ... 457 for (x = 0; x < width; x += 16) { 458 out_of_width = (x + 16) > width ? 1 : 0; 459 base_addr = y_addr + Tile2D_To_Linear(width, height, x, y, 0); 460 461 for (k = 0; (k < 16) && ((y + k) < height); k++) { 462 actual_width = out_of_width ? ((width%4)?((width%16) / 4 + 1) : ((width%16) / 4)) : 4; 463 for (l = 0; l < actual_width; l++) { 464 data = *((unsigned int*)(base_addr + 16*k + l*4)); 465 for (j = 0; (j < 4) && (x + l*4 + j) < width; j++) { 466 Y_plane[(y+k)*width + x + l*4 +j] = (data>>(8*j))&0xff; 467 } 468 } 469 } 470 } 471 } 472 473 for (y = 0; y < height/2; y += 8) { 474 for (x = 0; x < width; x += 16) { 475 out_of_width = (x + 16) > width ? 1 : 0; 476 base_addr = c_addr + Tile2D_To_Linear(width, height/2, x, y, 1); 477 for (k = 0; (k < 8) && ((y+k) < height/2); k++) { 478 actual_width = out_of_width ? ((width%4) ? ((width%16) / 4 + 1) : ((width%16) / 4)) : 4; 479 for (l = 0; l < actual_width; l++) { 480 data = *((unsigned int*)(base_addr + 16*k + l*4)); 481 for (j = 0; (j < 2) && (x/2 + l*2 +j) < width/2; j++) { 482 Cb_plane[(y+k)*width/2 + x/2 + l*2 +j] = (data>> (8*2*j))&0xff; 483 Cr_plane[(y+k)*width/2 + x/2 + l*2 +j] = (data>>(8*2*j+8))&0xff; 484 } 485 } 486 } 487 } 488 } 489 } 490 491 /* 492 * Converts RGB565 to YUV420P 493 * 494 * @param y_dst 495 * Y plane address of YUV420P[out] 496 * 497 * @param u_dst 498 * U plane address of YUV420P[out] 499 * 500 * @param v_dst 501 * V plane address of YUV420P[out] 502 * 503 * @param rgb_src 504 * Address of RGB565[in] 505 * 506 * @param width 507 * Width of RGB565[in] 508 * 509 * @param height 510 * Height of RGB565[in] 511 */ 512 void csc_RGB565_to_YUV420P( 513 unsigned char *y_dst, 514 unsigned char *u_dst, 515 unsigned char *v_dst, 516 unsigned char *rgb_src, 517 int width, 518 int height) 519 { 520 unsigned int i, j; 521 unsigned int tmp; 522 523 unsigned int R, G, B; 524 unsigned int Y, U, V; 525 526 unsigned int offset1 = width * height; 527 unsigned int offset2 = width/2 * height/2; 528 529 unsigned short int *pSrc = (unsigned short int *)rgb_src; 530 531 unsigned char *pDstY = (unsigned char *)y_dst; 532 unsigned char *pDstU = (unsigned char *)u_dst; 533 unsigned char *pDstV = (unsigned char *)v_dst; 534 535 unsigned int yIndex = 0; 536 unsigned int uIndex = 0; 537 unsigned int vIndex = 0; 538 539 for (j = 0; j < height; j++) { 540 for (i = 0; i < width; i++) { 541 tmp = pSrc[j * width + i]; 542 543 R = (tmp & 0x0000F800) >> 8; 544 G = (tmp & 0x000007E0) >> 3; 545 B = (tmp & 0x0000001F); 546 B = B << 3; 547 548 Y = ((66 * R) + (129 * G) + (25 * B) + 128); 549 Y = Y >> 8; 550 Y += 16; 551 552 pDstY[yIndex++] = (unsigned char)Y; 553 554 if ((j % 2) == 0 && (i % 2) == 0) { 555 U = ((-38 * R) - (74 * G) + (112 * B) + 128); 556 U = U >> 8; 557 U += 128; 558 V = ((112 * R) - (94 * G) - (18 * B) + 128); 559 V = V >> 8; 560 V += 128; 561 562 pDstU[uIndex++] = (unsigned char)U; 563 pDstV[vIndex++] = (unsigned char)V; 564 } 565 } 566 } 567 } 568 569 /* 570 * Converts RGB565 to YUV420SP 571 * 572 * @param y_dst 573 * Y plane address of YUV420SP[out] 574 * 575 * @param uv_dst 576 * UV plane address of YUV420SP[out] 577 * 578 * @param rgb_src 579 * Address of RGB565[in] 580 * 581 * @param width 582 * Width of RGB565[in] 583 * 584 * @param height 585 * Height of RGB565[in] 586 */ 587 void csc_RGB565_to_YUV420SP( 588 unsigned char *y_dst, 589 unsigned char *uv_dst, 590 unsigned char *rgb_src, 591 int width, 592 int height) 593 { 594 unsigned int i, j; 595 unsigned int tmp; 596 597 unsigned int R, G, B; 598 unsigned int Y, U, V; 599 600 unsigned int offset = width * height; 601 602 unsigned short int *pSrc = (unsigned short int *)rgb_src; 603 604 unsigned char *pDstY = (unsigned char *)y_dst; 605 unsigned char *pDstUV = (unsigned char *)uv_dst; 606 607 unsigned int yIndex = 0; 608 unsigned int uvIndex = 0; 609 610 for (j = 0; j < height; j++) { 611 for (i = 0; i < width; i++) { 612 tmp = pSrc[j * width + i]; 613 614 R = (tmp & 0x0000F800) >> 11; 615 R = R * 8; 616 G = (tmp & 0x000007E0) >> 5; 617 G = G * 4; 618 B = (tmp & 0x0000001F); 619 B = B * 8; 620 621 Y = ((66 * R) + (129 * G) + (25 * B) + 128); 622 Y = Y >> 8; 623 Y += 16; 624 625 pDstY[yIndex++] = (unsigned char)Y; 626 627 if ((j % 2) == 0 && (i % 2) == 0) { 628 U = ((-38 * R) - (74 * G) + (112 * B) + 128); 629 U = U >> 8; 630 U += 128; 631 V = ((112 * R) - (94 * G) - (18 * B) + 128); 632 V = V >> 8; 633 V += 128; 634 635 pDstUV[uvIndex++] = (unsigned char)U; 636 pDstUV[uvIndex++] = (unsigned char)V; 637 } 638 } 639 } 640 } 641 642 /* 643 * Converts RGB8888 to YUV420P 644 * 645 * @param y_dst 646 * Y plane address of YUV420P[out] 647 * 648 * @param u_dst 649 * U plane address of YUV420P[out] 650 * 651 * @param v_dst 652 * V plane address of YUV420P[out] 653 * 654 * @param rgb_src 655 * Address of ARGB8888[in] 656 * 657 * @param width 658 * Width of ARGB8888[in] 659 * 660 * @param height 661 * Height of ARGB8888[in] 662 */ 663 void csc_ARGB8888_to_YUV420P( 664 unsigned char *y_dst, 665 unsigned char *u_dst, 666 unsigned char *v_dst, 667 unsigned char *rgb_src, 668 unsigned int width, 669 unsigned int height) 670 { 671 unsigned int i, j; 672 unsigned int tmp; 673 674 unsigned int R, G, B; 675 unsigned int Y, U, V; 676 677 unsigned int offset1 = width * height; 678 unsigned int offset2 = width/2 * height/2; 679 680 unsigned int *pSrc = (unsigned int *)rgb_src; 681 682 unsigned char *pDstY = (unsigned char *)y_dst; 683 unsigned char *pDstU = (unsigned char *)u_dst; 684 unsigned char *pDstV = (unsigned char *)v_dst; 685 686 unsigned int yIndex = 0; 687 unsigned int uIndex = 0; 688 unsigned int vIndex = 0; 689 690 for (j = 0; j < height; j++) { 691 for (i = 0; i < width; i++) { 692 tmp = pSrc[j * width + i]; 693 694 R = (tmp & 0x00FF0000) >> 16; 695 G = (tmp & 0x0000FF00) >> 8; 696 B = (tmp & 0x000000FF); 697 698 Y = ((66 * R) + (129 * G) + (25 * B) + 128); 699 Y = Y >> 8; 700 Y += 16; 701 702 pDstY[yIndex++] = (unsigned char)Y; 703 704 if ((j % 2) == 0 && (i % 2) == 0) { 705 U = ((-38 * R) - (74 * G) + (112 * B) + 128); 706 U = U >> 8; 707 U += 128; 708 V = ((112 * R) - (94 * G) - (18 * B) + 128); 709 V = V >> 8; 710 V += 128; 711 712 pDstU[uIndex++] = (unsigned char)U; 713 pDstV[vIndex++] = (unsigned char)V; 714 } 715 } 716 } 717 } 718 719 720 /* 721 * Converts ARGB8888 to YUV420S 722 * 723 * @param y_dst 724 * Y plane address of YUV420S[out] 725 * 726 * @param uv_dst 727 * UV plane address of YUV420S[out] 728 * 729 * @param rgb_src 730 * Address of ARGB8888[in] 731 * 732 * @param width 733 * Width of ARGB8888[in] 734 * 735 * @param height 736 * Height of ARGB8888[in] 737 */ 738 void csc_ARGB8888_to_YUV420SP( 739 unsigned char *y_dst, 740 unsigned char *uv_dst, 741 unsigned char *rgb_src, 742 unsigned int width, 743 unsigned int height) 744 { 745 unsigned int i, j; 746 unsigned int tmp; 747 748 unsigned int R, G, B; 749 unsigned int Y, U, V; 750 751 unsigned int offset = width * height; 752 753 unsigned int *pSrc = (unsigned int *)rgb_src; 754 755 unsigned char *pDstY = (unsigned char *)y_dst; 756 unsigned char *pDstUV = (unsigned char *)uv_dst; 757 758 unsigned int yIndex = 0; 759 unsigned int uvIndex = 0; 760 761 for (j = 0; j < height; j++) { 762 for (i = 0; i < width; i++) { 763 tmp = pSrc[j * width + i]; 764 765 R = (tmp & 0x00FF0000) >> 16; 766 G = (tmp & 0x0000FF00) >> 8; 767 B = (tmp & 0x000000FF); 768 769 Y = ((66 * R) + (129 * G) + (25 * B) + 128); 770 Y = Y >> 8; 771 Y += 16; 772 773 pDstY[yIndex++] = (unsigned char)Y; 774 775 if ((j % 2) == 0 && (i % 2) == 0) { 776 U = ((-38 * R) - (74 * G) + (112 * B) + 128); 777 U = U >> 8; 778 U += 128; 779 V = ((112 * R) - (94 * G) - (18 * B) + 128); 780 V = V >> 8; 781 V += 128; 782 783 pDstUV[uvIndex++] = (unsigned char)U; 784 pDstUV[uvIndex++] = (unsigned char)V; 785 } 786 } 787 } 788 }