1 /* 2 * cl_image_scaler.cpp - CL image scaler 3 * 4 * Copyright (c) 2015 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_scaler.h" 23 24 namespace XCam { 25 26 static const XCamKernelInfo kernel_scale_info = { 27 "kernel_image_scaler", 28 #include "kernel_image_scaler.clx" 29 , 0, 30 }; 31 32 CLScalerKernel::CLScalerKernel ( 33 const SmartPtr<CLContext> &context, 34 CLImageScalerMemoryLayout mem_layout 35 ) 36 : CLImageKernel (context, "kernel_image_scaler") 37 , _mem_layout (mem_layout) 38 { 39 } 40 41 XCamReturn 42 CLScalerKernel::prepare_arguments (CLArgList &args, CLWorkSize &work_size) 43 { 44 XCamReturn ret = XCAM_RETURN_NO_ERROR; 45 SmartPtr<CLContext> context = get_context (); 46 47 SmartPtr<VideoBuffer> input = get_input_buffer (); 48 SmartPtr<VideoBuffer> output = get_output_buffer (); 49 SmartPtr<CLImage> image_in, image_out; 50 51 XCAM_FAIL_RETURN ( 52 WARNING, 53 input.ptr () && output.ptr (), 54 XCAM_RETURN_ERROR_MEM, 55 "cl image kernel(%s) get input/output buffer failed", XCAM_STR(get_kernel_name ())); 56 57 const VideoBufferInfo &input_info = input->get_video_info (); 58 const VideoBufferInfo &output_info = output->get_video_info (); 59 60 uint32_t output_width = 0, output_height = 0; 61 CLImageDesc output_imageDesc; 62 63 uint32_t channel_bits = XCAM_ALIGN_UP (output_info.color_bits, 8); 64 if (channel_bits == 8) 65 output_imageDesc.format.image_channel_data_type = CL_UNSIGNED_INT8; 66 else if (channel_bits == 16) 67 output_imageDesc.format.image_channel_data_type = CL_UNSIGNED_INT16; 68 69 if ((CL_IMAGE_SCALER_NV12_UV == get_mem_layout ()) && (V4L2_PIX_FMT_NV12 == input_info.format)) { 70 output_imageDesc.format.image_channel_order = CL_RG; 71 output_imageDesc.width = output_info.width / 2; 72 output_imageDesc.height = output_info.height / 2; 73 output_imageDesc.row_pitch = output_info.strides[1]; 74 75 image_out = convert_to_climage (context, output, output_imageDesc, output_info.offsets[1]); 76 output_width = output_info.width / 2; 77 output_height = output_info.height / 2; 78 } else { 79 output_imageDesc.format.image_channel_order = CL_R; 80 output_imageDesc.width = output_info.width; 81 output_imageDesc.height = output_info.height; 82 output_imageDesc.row_pitch = output_info.strides[0]; 83 84 image_out = convert_to_climage (context, output, output_imageDesc, output_info.offsets[0]); 85 output_width = output_info.width; 86 output_height = output_info.height; 87 } 88 89 CLImageDesc input_imageDesc; 90 channel_bits = XCAM_ALIGN_UP (input_info.color_bits, 8); 91 if (channel_bits == 8) 92 input_imageDesc.format.image_channel_data_type = CL_UNSIGNED_INT8; 93 else if (channel_bits == 16) 94 input_imageDesc.format.image_channel_data_type = CL_UNSIGNED_INT16; 95 96 if ((CL_IMAGE_SCALER_NV12_UV == get_mem_layout ()) && (V4L2_PIX_FMT_NV12 == input_info.format)) { 97 input_imageDesc.format.image_channel_order = CL_RG; 98 input_imageDesc.width = input_info.width / 2; 99 input_imageDesc.height = input_info.height / 2; 100 input_imageDesc.row_pitch = input_info.strides[1]; 101 102 image_in = convert_to_climage (context, input, input_imageDesc, input_info.offsets[1]); 103 } else { 104 input_imageDesc.format.image_channel_order = CL_R; 105 input_imageDesc.width = input_info.width; 106 input_imageDesc.height = input_info.height; 107 input_imageDesc.row_pitch = input_info.strides[0]; 108 109 image_in = convert_to_climage (context, input, input_imageDesc, input_info.offsets[0]); 110 } 111 112 //set args; 113 args.push_back (new CLMemArgument (image_in)); 114 args.push_back (new CLMemArgument (image_out)); 115 args.push_back (new CLArgumentT<uint32_t> (output_width)); 116 args.push_back (new CLArgumentT<uint32_t> (output_height)); 117 118 work_size.dim = XCAM_DEFAULT_IMAGE_DIM; 119 work_size.global[0] = XCAM_ALIGN_UP (output_width, XCAM_CL_IMAGE_SCALER_KERNEL_LOCAL_WORK_SIZE0); 120 work_size.global[1] = XCAM_ALIGN_UP (output_height, XCAM_CL_IMAGE_SCALER_KERNEL_LOCAL_WORK_SIZE1); 121 work_size.local[0] = XCAM_CL_IMAGE_SCALER_KERNEL_LOCAL_WORK_SIZE0; 122 work_size.local[1] = XCAM_CL_IMAGE_SCALER_KERNEL_LOCAL_WORK_SIZE1; 123 124 return ret; 125 } 126 127 CLImageScalerKernel::CLImageScalerKernel ( 128 const SmartPtr<CLContext> &context, 129 CLImageScalerMemoryLayout mem_layout, 130 SmartPtr<CLImageScaler> &scaler 131 ) 132 : CLScalerKernel (context, mem_layout) 133 , _scaler (scaler) 134 { 135 } 136 137 SmartPtr<VideoBuffer> 138 CLImageScalerKernel::get_input_buffer () 139 { 140 return _scaler->get_input_buf (); 141 } 142 143 SmartPtr<VideoBuffer> 144 CLImageScalerKernel::get_output_buffer () 145 { 146 return _scaler->get_scaler_buf (); 147 } 148 149 CLImageScaler::CLImageScaler (const SmartPtr<CLContext> &context) 150 : CLImageHandler (context, "CLImageScaler") 151 , _h_scaler_factor (0.5) 152 , _v_scaler_factor (0.5) 153 { 154 } 155 156 void 157 CLImageScaler::emit_stop () 158 { 159 if (_scaler_buf_pool.ptr ()) 160 _scaler_buf_pool->stop (); 161 } 162 163 bool 164 CLImageScaler::set_scaler_factor (const double h_factor, const double v_factor) 165 { 166 _h_scaler_factor = h_factor; 167 _v_scaler_factor = v_factor; 168 169 return true; 170 } 171 172 bool 173 CLImageScaler::get_scaler_factor (double &h_factor, double &v_factor) const 174 { 175 h_factor = _h_scaler_factor; 176 v_factor = _v_scaler_factor; 177 178 return true; 179 }; 180 181 XCamReturn 182 CLImageScaler::prepare_output_buf (SmartPtr<VideoBuffer> &input, SmartPtr<VideoBuffer> &output) 183 { 184 XCamReturn ret = XCAM_RETURN_NO_ERROR; 185 output = input; 186 187 ret = prepare_scaler_buf (input->get_video_info (), _scaler_buf); 188 XCAM_FAIL_RETURN( 189 WARNING, 190 ret == XCAM_RETURN_NO_ERROR, 191 ret, 192 "CLImageScalerKernel prepare scaled video buf failed"); 193 194 _scaler_buf->set_timestamp (input->get_timestamp ()); 195 196 return ret; 197 } 198 199 XCamReturn 200 CLImageScaler::execute_done (SmartPtr<VideoBuffer> &output) 201 { 202 XCAM_UNUSED (output); 203 get_context ()->finish(); 204 XCAM_ASSERT (_scaler_buf.ptr ()); 205 206 //post buffer out 207 return post_buffer (_scaler_buf); 208 } 209 210 XCamReturn 211 CLImageScaler::prepare_scaler_buf (const VideoBufferInfo &video_info, SmartPtr<VideoBuffer> &output) 212 { 213 if (!_scaler_buf_pool.ptr ()) { 214 VideoBufferInfo scaler_video_info; 215 uint32_t new_width = XCAM_ALIGN_UP ((uint32_t)(video_info.width * _h_scaler_factor), 216 2 * XCAM_CL_IMAGE_SCALER_KERNEL_LOCAL_WORK_SIZE0); 217 uint32_t new_height = XCAM_ALIGN_UP ((uint32_t)(video_info.height * _v_scaler_factor), 218 2 * XCAM_CL_IMAGE_SCALER_KERNEL_LOCAL_WORK_SIZE1); 219 220 scaler_video_info.init (video_info.format, new_width, new_height); 221 222 _scaler_buf_pool = new CLVideoBufferPool (); 223 XCAM_ASSERT (_scaler_buf_pool.ptr ()); 224 _scaler_buf_pool->set_video_info (scaler_video_info); 225 _scaler_buf_pool->reserve (6); 226 } 227 228 output = _scaler_buf_pool->get_buffer (_scaler_buf_pool); 229 XCAM_ASSERT (output.ptr ()); 230 231 return XCAM_RETURN_NO_ERROR; 232 } 233 234 XCamReturn 235 CLImageScaler::post_buffer (const SmartPtr<VideoBuffer> &buffer) 236 { 237 if (_scaler_callback.ptr ()) 238 return _scaler_callback->scaled_image_ready (buffer); 239 240 return XCAM_RETURN_NO_ERROR; 241 } 242 243 static SmartPtr<CLImageKernel> 244 create_scale_kernel ( 245 const SmartPtr<CLContext> &context, SmartPtr<CLImageScaler> &handler, CLImageScalerMemoryLayout layout) 246 { 247 SmartPtr<CLImageKernel> kernel; 248 kernel = new CLImageScalerKernel (context, layout, handler); 249 XCAM_ASSERT (kernel.ptr ()); 250 XCAM_FAIL_RETURN ( 251 ERROR, kernel->build_kernel (kernel_scale_info, NULL) == XCAM_RETURN_NO_ERROR, NULL, 252 "build scaler kernel(%s) failed", kernel_scale_info.kernel_name); 253 XCAM_ASSERT (kernel->is_valid ()); 254 return kernel; 255 } 256 257 SmartPtr<CLImageHandler> 258 create_cl_image_scaler_handler (const SmartPtr<CLContext> &context, const uint32_t format) 259 { 260 SmartPtr<CLImageScaler> scaler_handler; 261 SmartPtr<CLImageKernel> scaler_kernel; 262 263 scaler_handler = new CLImageScaler (context); 264 XCAM_ASSERT (scaler_handler.ptr ()); 265 266 if (V4L2_PIX_FMT_NV12 == format) { 267 //Y 268 scaler_kernel = create_scale_kernel (context, scaler_handler, CL_IMAGE_SCALER_NV12_Y); 269 XCAM_FAIL_RETURN (ERROR, scaler_kernel.ptr (), NULL, "build CL_IMAGE_SCALER_NV12_Y kernel failed"); 270 scaler_handler->add_kernel (scaler_kernel); 271 //UV 272 scaler_kernel = create_scale_kernel (context, scaler_handler, CL_IMAGE_SCALER_NV12_UV); 273 XCAM_FAIL_RETURN (ERROR, scaler_kernel.ptr (), NULL, "build CL_IMAGE_SCALER_NV12_UV kernel failed"); 274 scaler_handler->add_kernel (scaler_kernel); 275 } else if (XCAM_PIX_FMT_RGBA64 == format) { 276 scaler_kernel = create_scale_kernel (context, scaler_handler, CL_IMAGE_SCALER_RGBA); 277 XCAM_FAIL_RETURN (ERROR, scaler_kernel.ptr (), NULL, "build CL_IMAGE_SCALER_RGBA kernel failed"); 278 scaler_handler->add_kernel (scaler_kernel); 279 } else { 280 XCAM_LOG_ERROR ("create cl image scaler failed, unknown format:0x%08x", format); 281 return NULL; 282 } 283 284 return scaler_handler; 285 } 286 287 }; 288