1/* 2 * cl_bayer_basic_handler.cpp - CL bayer basic handler 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: Wind Yuan <feng.yuan@intel.com> 19 */ 20 21#include "cl_utils.h" 22#include "cl_bayer_basic_handler.h" 23#include "xcam_thread.h" 24 25#define GROUP_CELL_X_SIZE 64 26#define GROUP_CELL_Y_SIZE 4 27 28#define STATS_3A_CELL_X_SIZE 8 29#define STATS_3A_CELL_Y_SIZE GROUP_CELL_Y_SIZE 30 31#define STANDARD_3A_STATS_SIZE 8 32 33#define ENABLE_IMAGE_2D_INPUT 0 34 35namespace XCam { 36 37static const XCamKernelInfo kernel_bayer_basic_info = { 38 "kernel_bayer_basic", 39#include "kernel_bayer_basic.clx" 40 , 0, 41}; 42 43struct BayerPostData { 44 SmartPtr<VideoBuffer> image_buffer; 45 SmartPtr<CLBuffer> stats_cl_buf; 46}; 47 48class CLBayer3AStatsThread 49 : public Thread 50{ 51public: 52 CLBayer3AStatsThread (CLBayerBasicImageHandler *handler) 53 : Thread ("CLBayer3AStatsThread") 54 , _handler (handler) 55 {} 56 ~CLBayer3AStatsThread () {} 57 58 virtual bool emit_stop (); 59 bool queue_stats (SmartPtr<VideoBuffer> &buf, SmartPtr<CLBuffer> &stats); 60 SmartPtr<VideoBuffer> pop_buf (); 61protected: 62 virtual bool loop (); 63 virtual void stopped (); 64 65private: 66 CLBayerBasicImageHandler *_handler; 67 SafeList<BayerPostData> _stats_process_list; 68 SafeList<VideoBuffer> _buffer_done_list; 69}; 70 71bool 72CLBayer3AStatsThread::emit_stop () 73{ 74 _stats_process_list.pause_pop (); 75 _buffer_done_list.pause_pop (); 76 77 _stats_process_list.wakeup (); 78 _buffer_done_list.wakeup (); 79 80 return Thread::emit_stop (); 81} 82 83bool 84CLBayer3AStatsThread::queue_stats (SmartPtr<VideoBuffer> &buf, SmartPtr<CLBuffer> &stats) 85{ 86 XCAM_FAIL_RETURN ( 87 WARNING, 88 buf.ptr () && stats.ptr (), 89 false, 90 "cl bayer 3a-stats thread has error buffer/stats to queue"); 91 92 SmartPtr<BayerPostData> data = new BayerPostData; 93 XCAM_ASSERT (data.ptr ()); 94 data->image_buffer = buf; 95 data->stats_cl_buf = stats; 96 97 return _stats_process_list.push (data); 98} 99 100SmartPtr<VideoBuffer> 101CLBayer3AStatsThread::pop_buf () 102{ 103 return _buffer_done_list.pop (); 104} 105 106void 107CLBayer3AStatsThread::stopped () 108{ 109 _stats_process_list.clear (); 110 _buffer_done_list.clear (); 111} 112 113bool 114CLBayer3AStatsThread::loop () 115{ 116 XCamReturn ret = XCAM_RETURN_NO_ERROR; 117 SmartPtr<BayerPostData> data; 118 data = _stats_process_list.pop (); 119 if (!data.ptr ()) { 120 XCAM_LOG_INFO ("cl bayer 3a-stats thread is going to stop, processing data empty"); 121 return false; 122 } 123 124 XCAM_ASSERT (data->image_buffer.ptr ()); 125 XCAM_ASSERT (data->stats_cl_buf.ptr ()); 126 XCAM_ASSERT (_handler); 127 128 ret = _handler->process_stats_buffer (data->image_buffer, data->stats_cl_buf); 129 XCAM_FAIL_RETURN ( 130 WARNING, 131 ret == XCAM_RETURN_NO_ERROR, 132 false, 133 "cl bayer 3a-stats thread has error buffer on kernel post processing"); 134 135 XCAM_FAIL_RETURN ( 136 ERROR, 137 _buffer_done_list.push (data->image_buffer), 138 false, 139 "cl bayer 3a-stats thread failed to queue done-buffers"); 140 return true; 141} 142 143CLBayerBasicImageKernel::CLBayerBasicImageKernel (const SmartPtr<CLContext> &context) 144 : CLImageKernel (context, "kernel_bayer_basic") 145{ 146} 147 148XCamReturn 149CLBayerBasicImageHandler::process_stats_buffer (SmartPtr<VideoBuffer> &buffer, SmartPtr<CLBuffer> &cl_stats) 150{ 151 SmartPtr<X3aStats> stats_3a; 152 SmartPtr<CLContext> context = get_context (); 153 154 XCAM_OBJ_PROFILING_START; 155 156 context->finish (); 157 stats_3a = _3a_stats_context->copy_stats_out (cl_stats); 158 if (!stats_3a.ptr ()) { 159 XCAM_LOG_DEBUG ("copy 3a stats failed, maybe handler stopped"); 160 return XCAM_RETURN_ERROR_CL; 161 } 162 163 stats_3a->set_timestamp (buffer->get_timestamp ()); 164 buffer->attach_buffer (stats_3a); 165 166 if (cl_stats.ptr ()) 167 _3a_stats_context->release_buffer (cl_stats); 168 169 XCAM_OBJ_PROFILING_END ("3a_stats_cpu_copy(async)", XCAM_OBJ_DUR_FRAME_NUM); 170 171 return post_stats (stats_3a); 172} 173 174CLBayerBasicImageHandler::CLBayerBasicImageHandler ( 175 const SmartPtr<CLContext> &context, const char *name) 176 : CLImageHandler (context, name) 177 , _is_first_buf (true) 178{ 179 _blc_config.level_gr = XCAM_CL_BLC_DEFAULT_LEVEL; 180 _blc_config.level_r = XCAM_CL_BLC_DEFAULT_LEVEL; 181 _blc_config.level_b = XCAM_CL_BLC_DEFAULT_LEVEL; 182 _blc_config.level_gb = XCAM_CL_BLC_DEFAULT_LEVEL; 183 _blc_config.color_bits = 10; 184 185 _wb_config.r_gain = 1.0; 186 _wb_config.gr_gain = 1.0; 187 _wb_config.gb_gain = 1.0; 188 _wb_config.b_gain = 1.0; 189 190 for(int i = 0; i < XCAM_GAMMA_TABLE_SIZE; i++) 191 _gamma_table[i] = (float)i / 256.0f; 192 _gamma_table[XCAM_GAMMA_TABLE_SIZE] = 0.9999f; 193 194 _3a_stats_context = new CL3AStatsCalculatorContext (context); 195 XCAM_ASSERT (_3a_stats_context.ptr ()); 196 _3a_stats_thread = new CLBayer3AStatsThread (this); 197 XCAM_ASSERT (_3a_stats_thread.ptr ()); 198 199 XCAM_OBJ_PROFILING_INIT; 200} 201 202CLBayerBasicImageHandler::~CLBayerBasicImageHandler () 203{ 204 _3a_stats_thread->stop (); 205 _3a_stats_context->clean_up_data (); 206} 207 208void 209CLBayerBasicImageHandler::set_stats_bits (uint32_t stats_bits) 210{ 211 XCAM_ASSERT (_3a_stats_context.ptr ()); 212 _3a_stats_context->set_bit_depth (stats_bits); 213} 214 215bool 216CLBayerBasicImageHandler::set_bayer_kernel (SmartPtr<CLBayerBasicImageKernel> &kernel) 217{ 218 SmartPtr<CLImageKernel> image_kernel = kernel; 219 add_kernel (image_kernel); 220 _bayer_kernel = kernel; 221 return true; 222} 223 224bool 225CLBayerBasicImageHandler::set_blc_config (const XCam3aResultBlackLevel &blc) 226{ 227 _blc_config.level_r = (float)blc.r_level; 228 _blc_config.level_gr = (float)blc.gr_level; 229 _blc_config.level_gb = (float)blc.gb_level; 230 _blc_config.level_b = (float)blc.b_level; 231 //_blc_config.color_bits = 0; 232 return true; 233} 234 235bool 236CLBayerBasicImageHandler::set_wb_config (const XCam3aResultWhiteBalance &wb) 237{ 238 _wb_config.r_gain = (float)wb.r_gain; 239 _wb_config.gr_gain = (float)wb.gr_gain; 240 _wb_config.gb_gain = (float)wb.gb_gain; 241 _wb_config.b_gain = (float)wb.b_gain; 242 return true; 243} 244 245bool 246CLBayerBasicImageHandler::set_gamma_table (const XCam3aResultGammaTable &gamma) 247{ 248 for(int i = 0; i < XCAM_GAMMA_TABLE_SIZE; i++) 249 _gamma_table[i] = (float)gamma.table[i] / 256.0f; 250 251 return true; 252} 253 254void 255CLBayerBasicImageHandler::emit_stop () 256{ 257 _3a_stats_context->pre_stop (); 258 _3a_stats_thread->emit_stop (); 259} 260 261XCamReturn 262CLBayerBasicImageHandler::prepare_buffer_pool_video_info ( 263 const VideoBufferInfo &input, 264 VideoBufferInfo &output) 265{ 266 uint32_t format = XCAM_PIX_FMT_SGRBG16_planar; 267 bool format_inited = output.init (format, input.width / 2 , input.height / 2); 268 269 XCAM_FAIL_RETURN ( 270 WARNING, 271 format_inited, 272 XCAM_RETURN_ERROR_PARAM, 273 "CL image handler(%s) output format(%s) unsupported", 274 get_name (), xcam_fourcc_to_string (format)); 275 276 return XCAM_RETURN_NO_ERROR; 277} 278 279XCamReturn 280CLBayerBasicImageHandler::prepare_parameters ( 281 SmartPtr<VideoBuffer> &input, SmartPtr<VideoBuffer> &output) 282{ 283 SmartPtr<CLContext> context = get_context (); 284 const VideoBufferInfo & in_video_info = input->get_video_info (); 285 const VideoBufferInfo & out_video_info = output->get_video_info (); 286 CLImageDesc in_image_info; 287 CLImageDesc out_image_info; 288 CLArgList args; 289 CLWorkSize work_size; 290 291 XCAM_ASSERT (_bayer_kernel.ptr ()); 292 293 if (!_3a_stats_context->is_ready () && 294 !_3a_stats_context->allocate_data ( 295 in_video_info, 296 STANDARD_3A_STATS_SIZE / STATS_3A_CELL_X_SIZE, 297 STANDARD_3A_STATS_SIZE / STATS_3A_CELL_Y_SIZE)) { 298 XCAM_LOG_WARNING ("CL3AStatsCalculatorContext allocate data failed"); 299 return XCAM_RETURN_ERROR_MEM; 300 } 301 302 if (_is_first_buf) { 303 XCAM_FAIL_RETURN ( 304 WARNING, _3a_stats_thread->start (), XCAM_RETURN_ERROR_THREAD, 305 "cl bayer basic handler start 3a stats thread failed"); 306 } 307 308 in_image_info.format.image_channel_order = CL_RGBA; 309 in_image_info.format.image_channel_data_type = CL_UNSIGNED_INT32; //CL_UNORM_INT16; 310 in_image_info.width = in_video_info.aligned_width / 8; 311 in_image_info.height = in_video_info.height; 312 in_image_info.row_pitch = in_video_info.strides[0]; 313 314 out_image_info.format.image_channel_order = CL_RGBA; 315 out_image_info.format.image_channel_data_type = CL_UNSIGNED_INT32; //CL_UNORM_INT16; 316 out_image_info.width = out_video_info.width / 8; 317 out_image_info.height = out_video_info.aligned_height * 4; 318 out_image_info.row_pitch = out_video_info.strides[0]; 319 320#if ENABLE_IMAGE_2D_INPUT 321 SmartPtr<CLImage> image_in = convert_to_climage (context, input, in_image_info); 322#else 323 SmartPtr<CLBuffer> buffer_in = convert_to_clbuffer (context, input); 324#endif 325 uint32_t input_aligned_width = in_video_info.strides[0] / (2 * 8); // ushort8 326 SmartPtr<CLImage> image_out = convert_to_climage (context, output, out_image_info); 327 328 uint32_t out_aligned_height = out_video_info.aligned_height; 329 _blc_config.color_bits = in_video_info.color_bits; 330 331 SmartPtr<CLBuffer> gamma_table_buffer = new CLBuffer( 332 context, sizeof(float) * (XCAM_GAMMA_TABLE_SIZE + 1), 333 CL_MEM_READ_WRITE | CL_MEM_USE_HOST_PTR, &_gamma_table); 334 335 _stats_cl_buffer = _3a_stats_context->get_buffer (); 336 XCAM_FAIL_RETURN ( 337 WARNING, 338 _stats_cl_buffer.ptr () && _stats_cl_buffer->is_valid (), 339 XCAM_RETURN_ERROR_PARAM, 340 "CLBayerBasic handler get 3a stats buffer failed"); 341 342 XCAM_FAIL_RETURN ( 343 WARNING, 344 image_out->is_valid (), 345 XCAM_RETURN_ERROR_MEM, 346 "cl image handler(%s) out memory not available", XCAM_STR(get_name ())); 347 348 //set args; 349#if ENABLE_IMAGE_2D_INPUT 350 args.push_back (new CLMemArgument (image_in)); 351#else 352 args.push_back (new CLMemArgument (buffer_in)); 353#endif 354 args.push_back (new CLArgumentT<uint32_t> (input_aligned_width)); 355 args.push_back (new CLMemArgument (image_out)); 356 args.push_back (new CLArgumentT<uint32_t> (out_aligned_height)); 357 args.push_back (new CLArgumentT<CLBLCConfig> (_blc_config)); 358 args.push_back (new CLArgumentT<CLWBConfig> (_wb_config)); 359 args.push_back (new CLMemArgument (gamma_table_buffer)); 360 args.push_back (new CLMemArgument (_stats_cl_buffer)); 361 362 work_size.dim = XCAM_DEFAULT_IMAGE_DIM; 363 work_size.local[0] = 16; 364 work_size.local[1] = 2; 365 work_size.global[0] = XCAM_ALIGN_UP(out_video_info.width, GROUP_CELL_X_SIZE) / GROUP_CELL_X_SIZE * work_size.local[0]; 366 work_size.global[1] = XCAM_ALIGN_UP(out_video_info.aligned_height, GROUP_CELL_Y_SIZE) / GROUP_CELL_Y_SIZE * work_size.local[1]; 367 368 //printf ("work_size:g(%d, %d), l(%d, %d)\n", work_size.global[0], work_size.global[1], work_size.local[0], work_size.local[1]); 369 XCAM_ASSERT (_bayer_kernel.ptr ()); 370 XCamReturn ret = _bayer_kernel->set_arguments (args, work_size); 371 XCAM_FAIL_RETURN ( 372 WARNING, ret == XCAM_RETURN_NO_ERROR, ret, 373 "bayer basic kernel set arguments failed."); 374 375 return XCAM_RETURN_NO_ERROR; 376} 377 378XCamReturn 379CLBayerBasicImageHandler::execute_done (SmartPtr<VideoBuffer> &output) 380{ 381 XCAM_FAIL_RETURN ( 382 ERROR, _3a_stats_thread->queue_stats (output, _stats_cl_buffer), XCAM_RETURN_ERROR_UNKNOWN, 383 "cl bayer basic handler(%s) process 3a stats failed", XCAM_STR (get_name ())); 384 385 _stats_cl_buffer.release (); 386 387 if (_is_first_buf) { 388 _is_first_buf = false; 389 return XCAM_RETURN_BYPASS; 390 } 391 392 SmartPtr<VideoBuffer> done_buf = _3a_stats_thread->pop_buf (); 393 XCAM_FAIL_RETURN ( 394 WARNING, 395 done_buf.ptr (), 396 XCAM_RETURN_ERROR_MEM, 397 "cl bayer handler(%s) failed to get done buffer", get_name ()); 398 output = done_buf; 399 400 return XCAM_RETURN_NO_ERROR; 401} 402 403 404XCamReturn 405CLBayerBasicImageHandler::post_stats (const SmartPtr<X3aStats> &stats) 406{ 407 if (_stats_callback.ptr ()) 408 return _stats_callback->x3a_stats_ready (stats); 409 410 return XCAM_RETURN_NO_ERROR; 411} 412 413 414SmartPtr<CLImageHandler> 415create_cl_bayer_basic_image_handler (const SmartPtr<CLContext> &context, bool enable_gamma, uint32_t stats_bits) 416{ 417 SmartPtr<CLBayerBasicImageHandler> bayer_planar_handler; 418 SmartPtr<CLBayerBasicImageKernel> basic_kernel; 419 char build_options[1024]; 420 421 bayer_planar_handler = new CLBayerBasicImageHandler (context, "cl_handler_bayer_basic"); 422 bayer_planar_handler->set_stats_bits (stats_bits); 423 basic_kernel = new CLBayerBasicImageKernel (context); 424 XCAM_ASSERT (basic_kernel.ptr ()); 425 426 xcam_mem_clear (build_options); 427 snprintf (build_options, sizeof (build_options), 428 " -DENABLE_GAMMA=%d " 429 " -DENABLE_IMAGE_2D_INPUT=%d " 430 " -DSTATS_BITS=%d ", 431 (enable_gamma ? 1 : 0), 432 ENABLE_IMAGE_2D_INPUT, 433 stats_bits); 434 XCAM_FAIL_RETURN ( 435 ERROR, basic_kernel->build_kernel (kernel_bayer_basic_info, build_options) == XCAM_RETURN_NO_ERROR, NULL, 436 "build bayer-basic kernel(%s) failed", kernel_bayer_basic_info.kernel_name); 437 438 XCAM_ASSERT (basic_kernel->is_valid ()); 439 bayer_planar_handler->set_bayer_kernel (basic_kernel); 440 441 return bayer_planar_handler; 442} 443 444}; 445