Home | History | Annotate | Download | only in testingcamera
      1 #pragma version(1)
      2 #pragma rs java_package_name(com.android.testingcamera)
      3 #pragma rs_fp_relaxed
      4 
      5 uchar *yuv_in;
      6 
      7 // Input globals
      8 uint32_t yuv_height;
      9 uint32_t yuv_width;
     10 uint32_t out_width;
     11 uint32_t out_height;
     12 // Derived globals
     13 uint32_t y_stride;
     14 uint32_t uv_stride;
     15 uint32_t u_start;
     16 uint32_t v_start;
     17 float x_scale;
     18 float y_scale;
     19 
     20 enum ImageFormat {
     21     NV16 = 16,
     22     NV21 = 17,
     23     RGB_565 = 4,
     24     UNKNOWN = 0,
     25     YUY2 = 20,
     26     YV12 = 0x32315659
     27 };
     28 
     29 // Must be called before using any conversion methods
     30 void init_convert(uint32_t yw, uint32_t yh, uint32_t format,
     31         uint32_t ow, uint32_t oh) {
     32     yuv_height = yh;
     33     yuv_width = yw;
     34     out_width = ow;
     35     out_height = oh;
     36 
     37     x_scale = (float)yuv_width / out_width;
     38     y_scale = (float)yuv_height / out_height;
     39 
     40     switch (format) {
     41     case NV16:
     42     case NV21:
     43         y_stride = yuv_width;
     44         uv_stride = yuv_width;
     45         v_start = y_stride * yuv_height;
     46         u_start = v_start + 1;
     47         break;
     48     case YV12:
     49         // Minimum align-16 stride
     50         y_stride = (yuv_width + 0xF) & ~0xF;
     51         uv_stride = (y_stride / 2 + 0xF) & ~0xF;
     52         v_start = y_stride * yuv_height;
     53         u_start = v_start + uv_stride * (yuv_height / 2);
     54         break;
     55     case YUY2:
     56         y_stride = yuv_width * 2;
     57         uv_stride = y_stride;
     58         u_start = 1;
     59         v_start = 3;
     60         break;
     61     case RGB_565:
     62     case UNKNOWN:
     63     default:
     64         y_stride = yuv_width;
     65         uv_stride = yuv_width;
     66         v_start = 0;
     67         u_start = 0;
     68     }
     69 }
     70 
     71 // Makes up a conversion for unknown YUV types to try to display something
     72 // Asssumes that there's at least 1bpp in input YUV data
     73 uchar4 __attribute__((kernel)) convert_unknown(uint32_t x, uint32_t y) {
     74     uint32_t x_scaled = x * x_scale;
     75     uint32_t y_scaled = y * y_scale;
     76 
     77     uchar4 out;
     78     out.r = yuv_in[y_stride * y_scaled + x_scaled];
     79     out.g = 128;
     80     out.b = 128;
     81     out.a = 255; // For affine transform later
     82     return out;
     83 }
     84 
     85 // Converts semiplanar YVU to interleaved YUV, nearest neighbor
     86 uchar4 __attribute__((kernel)) convert_semiplanar(uint32_t x, uint32_t y) {
     87     uint32_t x_scaled = x * x_scale;
     88     uint32_t y_scaled = y * y_scale;
     89 
     90     uint32_t uv_row = y_scaled / 2; // truncation is important here
     91     uint32_t uv_col = x_scaled & ~0x1;
     92     uint32_t vu_pixel = uv_row * uv_stride + uv_col;
     93 
     94     uchar4 out;
     95     out.r = yuv_in[y_stride * y_scaled + x_scaled];
     96     out.g = yuv_in[u_start + vu_pixel];
     97     out.b = yuv_in[v_start + vu_pixel];
     98     out.a = 255; // For affine transform later
     99     return out;
    100 }
    101 
    102 // Converts planar YVU to interleaved YUV, nearest neighbor
    103 uchar4 __attribute__((kernel)) convert_planar(uint32_t x, uint32_t y) {
    104     uint32_t x_scaled = x * x_scale;
    105     uint32_t y_scaled = y * y_scale;
    106 
    107     uint32_t uv_row = y_scaled / 2; // truncation is important here
    108     uint32_t vu_pixel = uv_stride * uv_row + x_scaled / 2;
    109 
    110     uchar4 out;
    111     out.r = yuv_in[y_stride * y_scaled + x_scaled];
    112     out.g = yuv_in[u_start + vu_pixel];
    113     out.b = yuv_in[v_start + vu_pixel];
    114     out.a = 255; // For affine transform later
    115     return out;
    116 }
    117 
    118 // Converts interleaved 4:2:2 YUV to interleaved YUV, nearest neighbor
    119 uchar4 __attribute__((kernel)) convert_interleaved(uint32_t x, uint32_t y) {
    120     uint32_t x_scaled = x * x_scale;
    121     uint32_t y_scaled = y * y_scale;
    122 
    123     uint32_t uv_col = 2 * (x_scaled & ~0x1);
    124     uint32_t vu_pixel = y_stride * y_scaled + uv_col;
    125 
    126     uchar4 out;
    127     out.r = yuv_in[y_stride * y_scaled + x_scaled * 2];
    128     out.g = yuv_in[u_start + vu_pixel];
    129     out.b = yuv_in[v_start + vu_pixel];
    130     out.a = 255; // For affine transform later
    131     return out;
    132 }
    133