Home | History | Annotate | Download | only in OpenglSystemCommon
      1 /*
      2  * Copyright (C) 2016 Google, Inc.
      3  *
      4  * This software is licensed under the terms of the GNU General Public
      5  * License version 2, as published by the Free Software Foundation, and
      6  * may be copied, distributed, and modified under those terms.
      7  *
      8  * This program is distributed in the hope that it will be useful,
      9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     11  * GNU General Public License for more details.
     12  *
     13  */
     14 
     15 #include "FormatConversions.h"
     16 
     17 #include <cutils/log.h>
     18 #include <string.h>
     19 
     20 #define DEBUG 0
     21 
     22 #if DEBUG
     23 #define DD(...) ALOGD(...)
     24 #else
     25 #define DD(...)
     26 #endif
     27 
     28 void get_yv12_offsets(int width, int height,
     29                              uint32_t* yStride_out,
     30                              uint32_t* cStride_out,
     31                              uint32_t* totalSz_out) {
     32     uint32_t align = 16;
     33     uint32_t yStride = (width + (align - 1)) & ~(align-1);
     34     uint32_t uvStride = (yStride / 2 + (align - 1)) & ~(align-1);
     35     uint32_t uvHeight = height / 2;
     36     uint32_t sz = yStride * height + 2 * (uvHeight * uvStride);
     37 
     38     if (yStride_out) *yStride_out = yStride;
     39     if (cStride_out) *cStride_out = uvStride;
     40     if (totalSz_out) *totalSz_out = sz;
     41 }
     42 
     43 void get_yuv420p_offsets(int width, int height,
     44                                 uint32_t* yStride_out,
     45                                 uint32_t* cStride_out,
     46                                 uint32_t* totalSz_out) {
     47     uint32_t align = 1;
     48     uint32_t yStride = (width + (align - 1)) & ~(align-1);
     49     uint32_t uvStride = (yStride / 2 + (align - 1)) & ~(align-1);
     50     uint32_t uvHeight = height / 2;
     51     uint32_t sz = yStride * height + 2 * (uvHeight * uvStride);
     52 
     53     if (yStride_out) *yStride_out = yStride;
     54     if (cStride_out) *cStride_out = uvStride;
     55     if (totalSz_out) *totalSz_out = sz;
     56 }
     57 
     58 signed clamp_rgb(signed value) {
     59     if (value > 255) {
     60         value = 255;
     61     } else if (value < 0) {
     62         value = 0;
     63     }
     64     return value;
     65 }
     66 
     67 void rgb565_to_yv12(char* dest, char* src, int width, int height,
     68         int left, int top, int right, int bottom) {
     69     int align = 16;
     70     int yStride = (width + (align -1)) & ~(align-1);
     71     int cStride = (yStride / 2 + (align - 1)) & ~(align-1);
     72     int yOffset = 0;
     73     int cSize = cStride * height/2;
     74 
     75     uint16_t *rgb_ptr0 = (uint16_t *)src;
     76     uint8_t *yv12_y0 = (uint8_t *)dest;
     77     uint8_t *yv12_v0 = yv12_y0 + yStride * height;
     78     uint8_t *yv12_u0 = yv12_v0 + cSize;
     79 
     80     for (int j = top; j <= bottom; ++j) {
     81         uint8_t *yv12_y = yv12_y0 + j * yStride;
     82         uint8_t *yv12_v = yv12_v0 + (j/2) * cStride;
     83         uint8_t *yv12_u = yv12_v + cSize;
     84         uint16_t *rgb_ptr = rgb_ptr0 + j * width;
     85         bool jeven = (j & 1) == 0;
     86         for (int i = left; i <= right; ++i) {
     87             uint8_t r = ((rgb_ptr[i]) >> 11) & 0x01f;
     88             uint8_t g = ((rgb_ptr[i]) >> 5) & 0x03f;
     89             uint8_t b = (rgb_ptr[i]) & 0x01f;
     90             // convert to 8bits
     91             // http://stackoverflow.com/questions/2442576/how-does-one-convert-16-bit-rgb565-to-24-bit-rgb888
     92             uint8_t R = (r * 527 + 23) >> 6;
     93             uint8_t G = (g * 259 + 33) >> 6;
     94             uint8_t B = (b * 527 + 23) >> 6;
     95             // convert to YV12
     96             // frameworks/base/core/jni/android_hardware_camera2_legacy_LegacyCameraDevice.cpp
     97             yv12_y[i] = clamp_rgb((77 * R + 150 * G +  29 * B) >> 8);
     98             bool ieven = (i & 1) == 0;
     99             if (jeven && ieven) {
    100                 yv12_u[i] = clamp_rgb((( -43 * R - 85 * G + 128 * B) >> 8) + 128);
    101                 yv12_v[i] = clamp_rgb((( 128 * R - 107 * G - 21 * B) >> 8) + 128);
    102             }
    103         }
    104     }
    105 }
    106 
    107 void rgb888_to_yv12(char* dest, char* src, int width, int height,
    108         int left, int top, int right, int bottom) {
    109     DD("%s convert %d by %d", __func__, width, height);
    110     int align = 16;
    111     int yStride = (width + (align -1)) & ~(align-1);
    112     int cStride = (yStride / 2 + (align - 1)) & ~(align-1);
    113     int yOffset = 0;
    114     int cSize = cStride * height/2;
    115     int rgb_stride = 3;
    116 
    117     uint8_t *rgb_ptr0 = (uint8_t *)src;
    118     uint8_t *yv12_y0 = (uint8_t *)dest;
    119     uint8_t *yv12_v0 = yv12_y0 + yStride * height;
    120     uint8_t *yv12_u0 = yv12_v0 + cSize;
    121 
    122     for (int j = top; j <= bottom; ++j) {
    123         uint8_t *yv12_y = yv12_y0 + j * yStride;
    124         uint8_t *yv12_v = yv12_v0 + (j/2) * cStride;
    125         uint8_t *yv12_u = yv12_v + cSize;
    126         uint8_t  *rgb_ptr = rgb_ptr0 + j * width*rgb_stride;
    127         bool jeven = (j & 1) == 0;
    128         for (int i = left; i <= right; ++i) {
    129             uint8_t R = rgb_ptr[i*rgb_stride];
    130             uint8_t G = rgb_ptr[i*rgb_stride+1];
    131             uint8_t B = rgb_ptr[i*rgb_stride+2];
    132             // convert to YV12
    133             // frameworks/base/core/jni/android_hardware_camera2_legacy_LegacyCameraDevice.cpp
    134             yv12_y[i] = clamp_rgb((77 * R + 150 * G +  29 * B) >> 8);
    135             bool ieven = (i & 1) == 0;
    136             if (jeven && ieven) {
    137                 yv12_u[i] = clamp_rgb((( -43 * R - 85 * G + 128 * B) >> 8) + 128);
    138                 yv12_v[i] = clamp_rgb((( 128 * R - 107 * G - 21 * B) >> 8) + 128);
    139             }
    140         }
    141     }
    142 }
    143 
    144 void rgb888_to_yuv420p(char* dest, char* src, int width, int height,
    145         int left, int top, int right, int bottom) {
    146     DD("%s convert %d by %d", __func__, width, height);
    147     int yStride = width;
    148     int cStride = yStride / 2;
    149     int yOffset = 0;
    150     int cSize = cStride * height/2;
    151     int rgb_stride = 3;
    152 
    153     uint8_t *rgb_ptr0 = (uint8_t *)src;
    154     uint8_t *yv12_y0 = (uint8_t *)dest;
    155     uint8_t *yv12_u0 = yv12_y0 + yStride * height;
    156     uint8_t *yv12_v0 = yv12_u0 + cSize;
    157 
    158     for (int j = top; j <= bottom; ++j) {
    159         uint8_t *yv12_y = yv12_y0 + j * yStride;
    160         uint8_t *yv12_u = yv12_u0 + (j/2) * cStride;
    161         uint8_t *yv12_v = yv12_u + cStride;
    162         uint8_t  *rgb_ptr = rgb_ptr0 + j * width*rgb_stride;
    163         bool jeven = (j & 1) == 0;
    164         for (int i = left; i <= right; ++i) {
    165             uint8_t R = rgb_ptr[i*rgb_stride];
    166             uint8_t G = rgb_ptr[i*rgb_stride+1];
    167             uint8_t B = rgb_ptr[i*rgb_stride+2];
    168             // convert to YV12
    169             // frameworks/base/core/jni/android_hardware_camera2_legacy_LegacyCameraDevice.cpp
    170             yv12_y[i] = clamp_rgb((77 * R + 150 * G +  29 * B) >> 8);
    171             bool ieven = (i & 1) == 0;
    172             if (jeven && ieven) {
    173                 yv12_u[i] = clamp_rgb((( -43 * R - 85 * G + 128 * B) >> 8) + 128);
    174                 yv12_v[i] = clamp_rgb((( 128 * R - 107 * G - 21 * B) >> 8) + 128);
    175             }
    176         }
    177     }
    178 }
    179 // YV12 is aka YUV420Planar, or YUV420p; the only difference is that YV12 has
    180 // certain stride requirements for Y and UV respectively.
    181 void yv12_to_rgb565(char* dest, char* src, int width, int height,
    182         int left, int top, int right, int bottom) {
    183     DD("%s convert %d by %d", __func__, width, height);
    184     int align = 16;
    185     int yStride = (width + (align -1)) & ~(align-1);
    186     int cStride = (yStride / 2 + (align - 1)) & ~(align-1);
    187     int yOffset = 0;
    188     int cSize = cStride * height/2;
    189 
    190     uint16_t *rgb_ptr0 = (uint16_t *)dest;
    191     uint8_t *yv12_y0 = (uint8_t *)src;
    192     uint8_t *yv12_v0 = yv12_y0 + yStride * height;
    193     uint8_t *yv12_u0 = yv12_v0 + cSize;
    194 
    195     for (int j = top; j <= bottom; ++j) {
    196         uint8_t *yv12_y = yv12_y0 + j * yStride;
    197         uint8_t *yv12_v = yv12_v0 + (j/2) * cStride;
    198         uint8_t *yv12_u = yv12_v + cSize;
    199         uint16_t *rgb_ptr = rgb_ptr0 + (j-top) * (right-left+1);
    200         for (int i = left; i <= right; ++i) {
    201             // convert to rgb
    202             // frameworks/av/media/libstagefright/colorconversion/ColorConverter.cpp
    203             signed y1 = (signed)yv12_y[i] - 16;
    204             signed u = (signed)yv12_u[i / 2] - 128;
    205             signed v = (signed)yv12_v[i / 2] - 128;
    206 
    207             signed u_b = u * 517;
    208             signed u_g = -u * 100;
    209             signed v_g = -v * 208;
    210             signed v_r = v * 409;
    211 
    212             signed tmp1 = y1 * 298;
    213             signed b1 = clamp_rgb((tmp1 + u_b) / 256);
    214             signed g1 = clamp_rgb((tmp1 + v_g + u_g) / 256);
    215             signed r1 = clamp_rgb((tmp1 + v_r) / 256);
    216 
    217             uint16_t rgb1 = ((r1 >> 3) << 11) | ((g1 >> 2) << 5) | (b1 >> 3);
    218 
    219             rgb_ptr[i-left] = rgb1;
    220         }
    221     }
    222 }
    223 
    224 // YV12 is aka YUV420Planar, or YUV420p; the only difference is that YV12 has
    225 // certain stride requirements for Y and UV respectively.
    226 void yv12_to_rgb888(char* dest, char* src, int width, int height,
    227         int left, int top, int right, int bottom) {
    228     DD("%s convert %d by %d", __func__, width, height);
    229     int align = 16;
    230     int yStride = (width + (align -1)) & ~(align-1);
    231     int cStride = (yStride / 2 + (align - 1)) & ~(align-1);
    232     int yOffset = 0;
    233     int cSize = cStride * height/2;
    234     int rgb_stride = 3;
    235 
    236     uint8_t *rgb_ptr0 = (uint8_t *)dest;
    237     uint8_t *yv12_y0 = (uint8_t *)src;
    238     uint8_t *yv12_v0 = yv12_y0 + yStride * height;
    239     uint8_t *yv12_u0 = yv12_v0 + cSize;
    240 
    241     for (int j = top; j <= bottom; ++j) {
    242         uint8_t *yv12_y = yv12_y0 + j * yStride;
    243         uint8_t *yv12_v = yv12_v0 + (j/2) * cStride;
    244         uint8_t *yv12_u = yv12_v + cSize;
    245         uint8_t *rgb_ptr = rgb_ptr0 + (j-top) * (right-left+1) * rgb_stride;
    246         for (int i = left; i <= right; ++i) {
    247             // convert to rgb
    248             // frameworks/av/media/libstagefright/colorconversion/ColorConverter.cpp
    249             signed y1 = (signed)yv12_y[i] - 16;
    250             signed u = (signed)yv12_u[i / 2] - 128;
    251             signed v = (signed)yv12_v[i / 2] - 128;
    252 
    253             signed u_b = u * 517;
    254             signed u_g = -u * 100;
    255             signed v_g = -v * 208;
    256             signed v_r = v * 409;
    257 
    258             signed tmp1 = y1 * 298;
    259             signed b1 = clamp_rgb((tmp1 + u_b) / 256);
    260             signed g1 = clamp_rgb((tmp1 + v_g + u_g) / 256);
    261             signed r1 = clamp_rgb((tmp1 + v_r) / 256);
    262 
    263             rgb_ptr[(i-left)*rgb_stride] = r1;
    264             rgb_ptr[(i-left)*rgb_stride+1] = g1;
    265             rgb_ptr[(i-left)*rgb_stride+2] = b1;
    266         }
    267     }
    268 }
    269 
    270 // YV12 is aka YUV420Planar, or YUV420p; the only difference is that YV12 has
    271 // certain stride requirements for Y and UV respectively.
    272 void yuv420p_to_rgb888(char* dest, char* src, int width, int height,
    273         int left, int top, int right, int bottom) {
    274     DD("%s convert %d by %d", __func__, width, height);
    275     int yStride = width;
    276     int cStride = yStride / 2;
    277     int yOffset = 0;
    278     int cSize = cStride * height/2;
    279     int rgb_stride = 3;
    280 
    281     uint8_t *rgb_ptr0 = (uint8_t *)dest;
    282     uint8_t *yv12_y0 = (uint8_t *)src;
    283     uint8_t *yv12_u0 = yv12_y0 + yStride * height;
    284     uint8_t *yv12_v0 = yv12_u0 + cSize;
    285 
    286     for (int j = top; j <= bottom; ++j) {
    287         uint8_t *yv12_y = yv12_y0 + j * yStride;
    288         uint8_t *yv12_u = yv12_u0 + (j/2) * cStride;
    289         uint8_t *yv12_v = yv12_u + cSize;
    290         uint8_t *rgb_ptr = rgb_ptr0 + (j-top) * (right-left+1) * rgb_stride;
    291         for (int i = left; i <= right; ++i) {
    292             // convert to rgb
    293             // frameworks/av/media/libstagefright/colorconversion/ColorConverter.cpp
    294             signed y1 = (signed)yv12_y[i] - 16;
    295             signed u = (signed)yv12_u[i / 2] - 128;
    296             signed v = (signed)yv12_v[i / 2] - 128;
    297 
    298             signed u_b = u * 517;
    299             signed u_g = -u * 100;
    300             signed v_g = -v * 208;
    301             signed v_r = v * 409;
    302 
    303             signed tmp1 = y1 * 298;
    304             signed b1 = clamp_rgb((tmp1 + u_b) / 256);
    305             signed g1 = clamp_rgb((tmp1 + v_g + u_g) / 256);
    306             signed r1 = clamp_rgb((tmp1 + v_r) / 256);
    307 
    308             rgb_ptr[(i-left)*rgb_stride] = r1;
    309             rgb_ptr[(i-left)*rgb_stride+1] = g1;
    310             rgb_ptr[(i-left)*rgb_stride+2] = b1;
    311         }
    312     }
    313 }
    314 
    315 void copy_rgb_buffer_from_unlocked(
    316         char* _dst, char* raw_data,
    317         int unlockedWidth,
    318         int width, int height, int top, int left,
    319         int bpp) {
    320     char* dst = _dst;
    321     int dst_line_len = width * bpp;
    322     int src_line_len = unlockedWidth * bpp;
    323     char *src = (char *)raw_data + top*src_line_len + left*bpp;
    324     for (int y = 0; y < height; y++) {
    325         memcpy(dst, src, dst_line_len);
    326         src += src_line_len;
    327         dst += dst_line_len;
    328     }
    329 }
    330