Home | History | Annotate | Download | only in libswconverter
      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 }