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