1 /* 2 * cl_image_warp_handler.cpp - CL image warping handler 3 * 4 * Copyright (c) 2016 Intel Corporation 5 * 6 * Licensed under the Apache License, Version 2.0 (the "License"); 7 * you may not use this file except in compliance with the License. 8 * You may obtain a copy of the License at 9 * 10 * http://www.apache.org/licenses/LICENSE-2.0 11 * 12 * Unless required by applicable law or agreed to in writing, software 13 * distributed under the License is distributed on an "AS IS" BASIS, 14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 * See the License for the specific language governing permissions and 16 * limitations under the License. 17 * 18 * Author: Zong Wei <wei.zong (at) intel.com> 19 */ 20 21 #include "cl_utils.h" 22 #include "cl_image_warp_handler.h" 23 24 namespace XCam { 25 26 #define CL_IMAGE_WARP_WG_WIDTH 8 27 #define CL_IMAGE_WARP_WG_HEIGHT 4 28 29 30 static const XCamKernelInfo kernel_image_warp_info [] = { 31 { 32 "kernel_image_warp_8_pixel", 33 #include "kernel_image_warp.clx" 34 , 0, 35 }, 36 { 37 "kernel_image_warp_1_pixel", 38 #include "kernel_image_warp.clx" 39 , 0, 40 } 41 }; 42 43 CLImageWarpKernel::CLImageWarpKernel ( 44 const SmartPtr<CLContext> &context, 45 const char *name, 46 uint32_t channel, 47 SmartPtr<CLImageHandler> &handler) 48 : CLImageKernel (context, name) 49 , _channel (channel) 50 { 51 _handler = handler.dynamic_cast_ptr<CLImageWarpHandler> (); 52 } 53 54 XCamReturn 55 CLImageWarpKernel::prepare_arguments ( 56 CLArgList &args, CLWorkSize &work_size) 57 { 58 SmartPtr<CLContext> context = get_context (); 59 SmartPtr<VideoBuffer> input = _handler->get_warp_input_buf (); 60 SmartPtr<VideoBuffer> output = _handler->get_output_buf (); 61 62 const VideoBufferInfo & video_info_in = input->get_video_info (); 63 const VideoBufferInfo & video_info_out = output->get_video_info (); 64 65 uint32_t info_index = 0; 66 if (_channel == CL_IMAGE_CHANNEL_Y) { 67 info_index = 0; 68 } else if (_channel == CL_IMAGE_CHANNEL_UV) { 69 info_index = 1; 70 } 71 72 CLImageDesc cl_desc_in, cl_desc_out; 73 cl_desc_in.format.image_channel_order = info_index == 0 ? CL_R : CL_RG; 74 cl_desc_in.format.image_channel_data_type = CL_UNORM_INT8; 75 cl_desc_in.width = video_info_in.width >> info_index; 76 cl_desc_in.height = video_info_in.height >> info_index; 77 cl_desc_in.row_pitch = video_info_in.strides[info_index]; 78 79 #if CL_IMAGE_WARP_WRITE_UINT 80 cl_desc_out.format.image_channel_data_type = info_index == 0 ? CL_UNSIGNED_INT16 : CL_UNSIGNED_INT32; 81 cl_desc_out.format.image_channel_order = CL_RGBA; 82 cl_desc_out.width = XCAM_ALIGN_DOWN (video_info_out.width >> info_index, 8) / 8; 83 cl_desc_out.height = video_info_out.height >> info_index; 84 #else 85 cl_desc_out.format.image_channel_order = info_index == 0 ? CL_R : CL_RG; 86 cl_desc_out.format.image_channel_data_type = CL_UNORM_INT8; 87 cl_desc_out.width = video_info_out.width >> info_index; 88 cl_desc_out.height = video_info_out.height >> info_index; 89 #endif 90 91 cl_desc_out.row_pitch = video_info_out.strides[info_index]; 92 SmartPtr<CLImage> image_in = convert_to_climage (context, input, cl_desc_in, video_info_in.offsets[info_index]); 93 94 CLWarpConfig warp_config = _handler->get_warp_config (); 95 if ((warp_config.trim_ratio > 0.5f) || (warp_config.trim_ratio < 0.0f)) { 96 warp_config.trim_ratio = 0.0f; 97 } 98 99 float sample_rate_x = (float)warp_config.width / (float)video_info_in.width; 100 float sample_rate_y = (float)warp_config.height / (float)video_info_in.height; 101 XCAM_LOG_DEBUG ("warp analyze image sample rate(%fx%f)", sample_rate_x, sample_rate_y); 102 warp_config.proj_mat[2] = warp_config.proj_mat[2] / sample_rate_x; 103 warp_config.proj_mat[5] = warp_config.proj_mat[5] / sample_rate_y; 104 warp_config.proj_mat[6] = warp_config.proj_mat[6] * sample_rate_x; 105 warp_config.proj_mat[7] = warp_config.proj_mat[7] * sample_rate_y; 106 107 /* 108 For NV12 image (YUV420), UV plane has half horizontal & vertical coordinate size of Y plane, 109 need to adjust the projection matrix as: 110 H(uv) = [0.5, 0, 0; 0, 0.5, 0; 0, 0, 1] * H(y) * [2, 0, 0; 0, 2, 0; 0, 0, 1] 111 */ 112 if (_channel == CL_IMAGE_CHANNEL_UV) { 113 warp_config.proj_mat[2] = 0.5 * warp_config.proj_mat[2]; 114 warp_config.proj_mat[5] = 0.5 * warp_config.proj_mat[5]; 115 warp_config.proj_mat[6] = 2.0 * warp_config.proj_mat[6]; 116 warp_config.proj_mat[7] = 2.0 * warp_config.proj_mat[7]; 117 } 118 119 /* 120 Trim image: shift toward origin then scale up 121 Trim Matrix (TMat) 122 TMat = [ scale_x, 0.0f, shift_x; 123 0.0f, scale_y, shift_y; 124 1.0f, 1.0f, 1.0f; ] 125 126 Warp Perspective Matrix = TMat * HMat 127 */ 128 #if CL_IMAGE_WARP_WRITE_UINT 129 float shift_x = warp_config.trim_ratio * cl_desc_out.width * 8.0f; 130 #else 131 float shift_x = warp_config.trim_ratio * cl_desc_out.width; 132 #endif 133 float shift_y = warp_config.trim_ratio * cl_desc_out.height; 134 float scale_x = 1.0f - 2.0f * warp_config.trim_ratio; 135 float scale_y = 1.0f - 2.0f * warp_config.trim_ratio; 136 137 warp_config.proj_mat[0] = scale_x * warp_config.proj_mat[0] + shift_x * warp_config.proj_mat[6]; 138 warp_config.proj_mat[1] = scale_x * warp_config.proj_mat[1] + shift_x * warp_config.proj_mat[7]; 139 warp_config.proj_mat[2] = scale_x * warp_config.proj_mat[2] + shift_x * warp_config.proj_mat[8]; 140 warp_config.proj_mat[3] = scale_y * warp_config.proj_mat[3] + shift_y * warp_config.proj_mat[6]; 141 warp_config.proj_mat[4] = scale_y * warp_config.proj_mat[4] + shift_y * warp_config.proj_mat[7]; 142 warp_config.proj_mat[5] = scale_y * warp_config.proj_mat[5] + shift_y * warp_config.proj_mat[8]; 143 144 XCAM_LOG_DEBUG ("warp config image size(%dx%d)", warp_config.width, warp_config.height); 145 XCAM_LOG_DEBUG ("proj_mat[%d]=(%f, %f, %f, %f, %f, %f, %f, %f, %f);", warp_config.frame_id, 146 warp_config.proj_mat[0], warp_config.proj_mat[1], warp_config.proj_mat[2], 147 warp_config.proj_mat[3], warp_config.proj_mat[4], warp_config.proj_mat[5], 148 warp_config.proj_mat[6], warp_config.proj_mat[7], warp_config.proj_mat[8]); 149 150 SmartPtr<CLImage> image_out = convert_to_climage (context, output, cl_desc_out, video_info_out.offsets[info_index]); 151 XCAM_FAIL_RETURN ( 152 WARNING, 153 image_in->is_valid () && image_out->is_valid (), 154 XCAM_RETURN_ERROR_MEM, 155 "cl image kernel(%s) in/out memory not available", get_kernel_name ()); 156 157 //set args; 158 work_size.dim = XCAM_DEFAULT_IMAGE_DIM; 159 work_size.local[0] = CL_IMAGE_WARP_WG_WIDTH; 160 work_size.local[1] = CL_IMAGE_WARP_WG_HEIGHT; 161 work_size.global[0] = XCAM_ALIGN_UP (cl_desc_out.width, work_size.local[0]); 162 work_size.global[1] = XCAM_ALIGN_UP(cl_desc_out.height, work_size.local[1]); 163 164 args.push_back (new CLMemArgument (image_in)); 165 args.push_back (new CLMemArgument (image_out)); 166 args.push_back (new CLArgumentT<CLWarpConfig> (warp_config)); 167 168 return XCAM_RETURN_NO_ERROR; 169 } 170 171 CLImageWarpHandler::CLImageWarpHandler (const SmartPtr<CLContext> &context, const char *name) 172 : CLImageHandler (context, name) 173 { 174 } 175 176 bool 177 CLImageWarpHandler::is_ready () 178 { 179 bool ret = !_warp_config_list.empty (); 180 return ret && CLImageHandler::is_ready (); 181 } 182 183 XCamReturn 184 CLImageWarpHandler::execute_done (SmartPtr<VideoBuffer> &output) 185 { 186 XCAM_UNUSED (output); 187 if (!_warp_config_list.empty ()) { 188 _warp_config_list.pop_front (); 189 } 190 191 return XCAM_RETURN_NO_ERROR; 192 } 193 194 SmartPtr<VideoBuffer> 195 CLImageWarpHandler::get_warp_input_buf () 196 { 197 return CLImageHandler::get_input_buf (); 198 } 199 200 bool 201 CLImageWarpHandler::set_warp_config (const XCamDVSResult& config) 202 { 203 CLWarpConfig warp_config; 204 warp_config.frame_id = config.frame_id; 205 warp_config.width = config.frame_width; 206 warp_config.height = config.frame_height; 207 for( int i = 0; i < 9; i++ ) { 208 warp_config.proj_mat[i] = config.proj_mat[i]; 209 } 210 XCAM_LOG_DEBUG ("warp_mat{%d}=[%f, %f, %f; %f, %f, %f; %f, %f, %f]", warp_config.frame_id + 1, 211 warp_config.proj_mat[0], warp_config.proj_mat[1], warp_config.proj_mat[2], 212 warp_config.proj_mat[3], warp_config.proj_mat[4], warp_config.proj_mat[5], 213 warp_config.proj_mat[6], warp_config.proj_mat[7], warp_config.proj_mat[8]); 214 #if 0 215 printf ("warp_mat{%d}=[%f, %f, %f; %f, %f, %f; %f, %f, %f]; \n", warp_config.frame_id + 1, 216 warp_config.proj_mat[0], warp_config.proj_mat[1], warp_config.proj_mat[2], 217 warp_config.proj_mat[3], warp_config.proj_mat[4], warp_config.proj_mat[5], 218 warp_config.proj_mat[6], warp_config.proj_mat[7], warp_config.proj_mat[8]); 219 #endif 220 _warp_config_list.push_back (warp_config); 221 222 return true; 223 } 224 225 CLWarpConfig 226 CLImageWarpHandler::get_warp_config () 227 { 228 CLWarpConfig warp_config; 229 230 if (_warp_config_list.size () > 0) { 231 warp_config = *(_warp_config_list.begin ()); 232 } else { 233 warp_config.frame_id = -1; 234 warp_config.proj_mat[0] = 1.0f; 235 warp_config.proj_mat[1] = 0.0f; 236 warp_config.proj_mat[2] = 0.0f; 237 warp_config.proj_mat[3] = 0.0f; 238 warp_config.proj_mat[4] = 1.0f; 239 warp_config.proj_mat[5] = 0.0f; 240 warp_config.proj_mat[6] = 0.0f; 241 warp_config.proj_mat[7] = 0.0f; 242 warp_config.proj_mat[8] = 1.0f; 243 } 244 245 return warp_config; 246 } 247 248 static SmartPtr<CLImageWarpKernel> 249 create_kernel_image_warp ( 250 const SmartPtr<CLContext> &context, 251 uint32_t channel, 252 SmartPtr<CLImageHandler> handler) 253 { 254 SmartPtr<CLImageWarpKernel> warp_kernel; 255 256 const char *name = (channel == CL_IMAGE_CHANNEL_Y ? "kernel_image_warp_y" : "kernel_image_warp_uv"); 257 char build_options[1024]; 258 xcam_mem_clear (build_options); 259 260 snprintf (build_options, sizeof (build_options), 261 " -DWARP_Y=%d ", 262 (channel == CL_IMAGE_CHANNEL_Y ? 1 : 0)); 263 264 warp_kernel = new CLImageWarpKernel (context, name, channel, handler); 265 XCAM_ASSERT (warp_kernel.ptr ()); 266 XCAM_FAIL_RETURN ( 267 ERROR, warp_kernel->build_kernel (kernel_image_warp_info[KernelImageWarp], build_options) == XCAM_RETURN_NO_ERROR, 268 NULL, "build image warp kernel failed"); 269 XCAM_ASSERT (warp_kernel->is_valid ()); 270 271 return warp_kernel; 272 } 273 274 SmartPtr<CLImageHandler> 275 create_cl_image_warp_handler (const SmartPtr<CLContext> &context) 276 { 277 SmartPtr<CLImageWarpHandler> warp_handler; 278 SmartPtr<CLImageKernel> warp_kernel; 279 280 warp_handler = new CLImageWarpHandler (context); 281 XCAM_ASSERT (warp_handler.ptr ()); 282 283 warp_kernel = create_kernel_image_warp (context, CL_IMAGE_CHANNEL_Y, warp_handler); 284 XCAM_ASSERT (warp_kernel.ptr ()); 285 warp_handler->add_kernel (warp_kernel); 286 287 warp_kernel = create_kernel_image_warp (context, CL_IMAGE_CHANNEL_UV, warp_handler); 288 XCAM_ASSERT (warp_kernel.ptr ()); 289 warp_handler->add_kernel (warp_kernel); 290 291 return warp_handler; 292 } 293 294 }; 295