1 /* 2 * cl_3a_image_processor.cpp - CL 3A image processor 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 (at) intel.com> 19 */ 20 #include "cl_3a_image_processor.h" 21 #include "cl_context.h" 22 #include "cl_csc_handler.h" 23 #include "cl_bayer_pipe_handler.h" 24 #include "cl_yuv_pipe_handler.h" 25 #if ENABLE_YEENR_HANDLER 26 #include "cl_ee_handler.h" 27 #endif 28 #include "cl_tnr_handler.h" 29 #include "cl_tonemapping_handler.h" 30 #include "cl_newtonemapping_handler.h" 31 #include "cl_bayer_basic_handler.h" 32 33 #define XCAM_CL_3A_IMAGE_MAX_POOL_SIZE 6 34 35 namespace XCam { 36 37 CL3aImageProcessor::CL3aImageProcessor () 38 : CLImageProcessor ("CL3aImageProcessor") 39 , _output_fourcc (V4L2_PIX_FMT_NV12) 40 , _3a_stats_bits (8) 41 , _pipeline_profile (BasicPipelineProfile) 42 , _capture_stage (TonemappingStage) 43 , _wdr_mode (WDRdisabled) 44 , _tnr_mode (0) 45 , _enable_gamma (true) 46 , _enable_macc (true) 47 , _snr_mode (0) 48 { 49 keep_attached_buf (true); 50 XCAM_LOG_DEBUG ("CL3aImageProcessor constructed"); 51 } 52 53 CL3aImageProcessor::~CL3aImageProcessor () 54 { 55 XCAM_LOG_DEBUG ("CL3aImageProcessor destructed"); 56 } 57 58 void 59 CL3aImageProcessor::set_stats_callback (const SmartPtr<StatsCallback> &callback) 60 { 61 XCAM_ASSERT (callback.ptr ()); 62 _stats_callback = callback; 63 } 64 65 bool 66 CL3aImageProcessor::set_output_format (uint32_t fourcc) 67 { 68 XCAM_FAIL_RETURN ( 69 WARNING, 70 V4L2_PIX_FMT_NV12 == fourcc, 71 false, 72 "cl 3a processor doesn't support output format: %s", 73 xcam_fourcc_to_string (fourcc)); 74 75 _output_fourcc = fourcc; 76 return true; 77 } 78 79 bool 80 CL3aImageProcessor::set_capture_stage (CaptureStage capture_stage) 81 { 82 _capture_stage = capture_stage; 83 return true; 84 } 85 86 bool 87 CL3aImageProcessor::set_3a_stats_bits (uint32_t bits) 88 { 89 switch (bits) { 90 case 8: 91 case 12: 92 _3a_stats_bits = bits; 93 break; 94 default: 95 XCAM_LOG_WARNING ("cl image processor 3a stats doesn't support %d-bits", bits); 96 return false; 97 } 98 return true; 99 } 100 101 bool 102 CL3aImageProcessor::can_process_result (SmartPtr<X3aResult> &result) 103 { 104 if (result.ptr() == NULL) 105 return false; 106 switch (result->get_type ()) { 107 case XCAM_3A_RESULT_WHITE_BALANCE: 108 case XCAM_3A_RESULT_BLACK_LEVEL: 109 case XCAM_3A_RESULT_R_GAMMA: 110 case XCAM_3A_RESULT_G_GAMMA: 111 case XCAM_3A_RESULT_B_GAMMA: 112 case XCAM_3A_RESULT_RGB2YUV_MATRIX: 113 case XCAM_3A_RESULT_DEFECT_PIXEL_CORRECTION: 114 case XCAM_3A_RESULT_MACC: 115 case XCAM_3A_RESULT_BAYER_NOISE_REDUCTION: 116 case XCAM_3A_RESULT_BRIGHTNESS: 117 case XCAM_3A_RESULT_3D_NOISE_REDUCTION: 118 case XCAM_3A_RESULT_TEMPORAL_NOISE_REDUCTION_YUV: 119 case XCAM_3A_RESULT_EDGE_ENHANCEMENT: 120 return true; 121 122 default: 123 return false; 124 } 125 126 return false; 127 } 128 129 XCamReturn 130 CL3aImageProcessor::apply_3a_results (X3aResultList &results) 131 { 132 XCamReturn ret = XCAM_RETURN_NO_ERROR; 133 134 for (X3aResultList::iterator iter = results.begin (); iter != results.end (); ++iter) 135 { 136 SmartPtr<X3aResult> &result = *iter; 137 ret = apply_3a_result (result); 138 if (ret != XCAM_RETURN_NO_ERROR) 139 break; 140 } 141 return ret; 142 } 143 144 XCamReturn 145 CL3aImageProcessor::apply_3a_result (SmartPtr<X3aResult> &result) 146 { 147 STREAM_LOCK; 148 149 if (result.ptr() == NULL) 150 return XCAM_RETURN_BYPASS; 151 152 uint32_t res_type = result->get_type (); 153 154 switch (res_type) { 155 case XCAM_3A_RESULT_WHITE_BALANCE: { 156 SmartPtr<X3aWhiteBalanceResult> wb_res = result.dynamic_cast_ptr<X3aWhiteBalanceResult> (); 157 XCAM_ASSERT (wb_res.ptr ()); 158 if (_bayer_basic_pipe.ptr ()) { 159 _bayer_basic_pipe->set_wb_config (wb_res->get_standard_result ()); 160 _bayer_basic_pipe->set_3a_result (result); 161 } 162 break; 163 } 164 165 case XCAM_3A_RESULT_BLACK_LEVEL: { 166 SmartPtr<X3aBlackLevelResult> bl_res = result.dynamic_cast_ptr<X3aBlackLevelResult> (); 167 XCAM_ASSERT (bl_res.ptr ()); 168 if (_bayer_basic_pipe.ptr ()) { 169 _bayer_basic_pipe->set_blc_config (bl_res->get_standard_result ()); 170 _bayer_basic_pipe->set_3a_result (result); 171 } 172 break; 173 } 174 175 case XCAM_3A_RESULT_DEFECT_PIXEL_CORRECTION: { 176 SmartPtr<X3aDefectPixelResult> def_res = result.dynamic_cast_ptr<X3aDefectPixelResult> (); 177 XCAM_ASSERT (def_res.ptr ()); 178 XCAM_UNUSED (def_res); 179 break; 180 } 181 182 case XCAM_3A_RESULT_RGB2YUV_MATRIX: { 183 SmartPtr<X3aColorMatrixResult> csc_res = result.dynamic_cast_ptr<X3aColorMatrixResult> (); 184 XCAM_ASSERT (csc_res.ptr ()); 185 if (_csc.ptr()) { 186 _csc->set_matrix (csc_res->get_standard_result ()); 187 _csc->set_3a_result (result); 188 } 189 if (_yuv_pipe.ptr()) { 190 _yuv_pipe->set_rgbtoyuv_matrix (csc_res->get_standard_result ()); 191 _yuv_pipe->set_3a_result (result); 192 } 193 break; 194 } 195 196 case XCAM_3A_RESULT_MACC: { 197 SmartPtr<X3aMaccMatrixResult> macc_res = result.dynamic_cast_ptr<X3aMaccMatrixResult> (); 198 XCAM_ASSERT (macc_res.ptr ()); 199 if (_yuv_pipe.ptr()) { 200 _yuv_pipe->set_macc_table (macc_res->get_standard_result ()); 201 _yuv_pipe->set_3a_result (result); 202 } 203 break; 204 } 205 case XCAM_3A_RESULT_R_GAMMA: 206 case XCAM_3A_RESULT_B_GAMMA: 207 break; 208 209 case XCAM_3A_RESULT_G_GAMMA: 210 case XCAM_3A_RESULT_Y_GAMMA: { 211 SmartPtr<X3aGammaTableResult> gamma_res = result.dynamic_cast_ptr<X3aGammaTableResult> (); 212 XCAM_ASSERT (gamma_res.ptr ()); 213 if (_bayer_basic_pipe.ptr ()) { 214 _bayer_basic_pipe->set_gamma_table (gamma_res->get_standard_result ()); 215 _bayer_basic_pipe->set_3a_result (result); 216 } 217 break; 218 } 219 220 case XCAM_3A_RESULT_3D_NOISE_REDUCTION: { 221 SmartPtr<X3aTemporalNoiseReduction> nr_res = result.dynamic_cast_ptr<X3aTemporalNoiseReduction> (); 222 XCAM_ASSERT (nr_res.ptr ()); 223 XCAM_UNUSED (nr_res); 224 225 break; 226 } 227 228 case XCAM_3A_RESULT_TEMPORAL_NOISE_REDUCTION_YUV: { 229 SmartPtr<X3aTemporalNoiseReduction> tnr_res = result.dynamic_cast_ptr<X3aTemporalNoiseReduction> (); 230 XCAM_ASSERT (tnr_res.ptr ()); 231 if (_yuv_pipe.ptr ()) { 232 _yuv_pipe->set_tnr_yuv_config(tnr_res->get_standard_result ()); 233 _yuv_pipe->set_3a_result (result); 234 } 235 break; 236 } 237 238 case XCAM_3A_RESULT_EDGE_ENHANCEMENT: { 239 SmartPtr<X3aEdgeEnhancementResult> ee_ee_res = result.dynamic_cast_ptr<X3aEdgeEnhancementResult> (); 240 XCAM_ASSERT (ee_ee_res.ptr ()); 241 if (_bayer_pipe.ptr()) { 242 _bayer_pipe->set_ee_config (ee_ee_res->get_standard_result ()); 243 _bayer_pipe->set_3a_result (result); 244 } 245 #if ENABLE_YEENR_HANDLER 246 if (_ee.ptr()) { 247 _ee->set_ee_config_ee (ee_ee_res->get_standard_result ()); 248 _ee->set_3a_result (result); 249 } 250 #endif 251 break; 252 } 253 254 case XCAM_3A_RESULT_BAYER_NOISE_REDUCTION: { 255 SmartPtr<X3aBayerNoiseReduction> bnr_res = result.dynamic_cast_ptr<X3aBayerNoiseReduction> (); 256 XCAM_ASSERT (bnr_res.ptr ()); 257 if (_bayer_pipe.ptr()) { 258 _bayer_pipe->set_bnr_config (bnr_res->get_standard_result ()); 259 _bayer_pipe->set_3a_result (result); 260 } 261 262 break; 263 } 264 265 case XCAM_3A_RESULT_BRIGHTNESS: { 266 SmartPtr<X3aBrightnessResult> brightness_res = result.dynamic_cast_ptr<X3aBrightnessResult> (); 267 XCAM_ASSERT (brightness_res.ptr ()); 268 float brightness_level = ((XCam3aResultBrightness)brightness_res->get_standard_result()).brightness_level; 269 XCAM_UNUSED (brightness_level); 270 break; 271 } 272 273 default: 274 XCAM_LOG_WARNING ("CL3aImageProcessor unknown 3a result:%d", res_type); 275 break; 276 } 277 278 return XCAM_RETURN_NO_ERROR; 279 } 280 281 XCamReturn 282 CL3aImageProcessor::create_handlers () 283 { 284 SmartPtr<CLImageHandler> image_handler; 285 SmartPtr<CLContext> context = get_cl_context (); 286 287 XCAM_ASSERT (context.ptr ()); 288 289 /* bayer pipeline */ 290 image_handler = create_cl_bayer_basic_image_handler (context, _enable_gamma, _3a_stats_bits); 291 _bayer_basic_pipe = image_handler.dynamic_cast_ptr<CLBayerBasicImageHandler> (); 292 XCAM_FAIL_RETURN ( 293 WARNING, 294 _bayer_basic_pipe.ptr (), 295 XCAM_RETURN_ERROR_CL, 296 "CL3aImageProcessor create bayer basic pipe handler failed"); 297 image_handler->set_pool_size (XCAM_CL_3A_IMAGE_MAX_POOL_SIZE); 298 _bayer_basic_pipe->set_stats_callback (_stats_callback); 299 add_handler (image_handler); 300 301 /* tone mapping */ 302 switch(_wdr_mode) { 303 case Gaussian: { 304 image_handler = create_cl_tonemapping_image_handler (context); 305 _tonemapping = image_handler.dynamic_cast_ptr<CLTonemappingImageHandler> (); 306 XCAM_FAIL_RETURN ( 307 WARNING, 308 _tonemapping.ptr (), 309 XCAM_RETURN_ERROR_CL, 310 "CL3aImageProcessor create tonemapping handler failed"); 311 _tonemapping->enable_handler (true); 312 image_handler->set_pool_size (XCAM_CL_3A_IMAGE_MAX_POOL_SIZE); 313 add_handler (image_handler); 314 break; 315 } 316 case Haleq: { 317 image_handler = create_cl_newtonemapping_image_handler (context); 318 _newtonemapping = image_handler.dynamic_cast_ptr<CLNewTonemappingImageHandler> (); 319 XCAM_FAIL_RETURN ( 320 WARNING, 321 _newtonemapping.ptr (), 322 XCAM_RETURN_ERROR_CL, 323 "CL3aImageProcessor create tonemapping handler failed"); 324 _newtonemapping->enable_handler (true); 325 image_handler->set_pool_size (XCAM_CL_3A_IMAGE_MAX_POOL_SIZE); 326 add_handler (image_handler); 327 break; 328 } 329 default: 330 XCAM_LOG_DEBUG ("WDR disabled"); 331 break; 332 } 333 334 /* bayer pipe */ 335 image_handler = create_cl_bayer_pipe_image_handler (context); 336 _bayer_pipe = image_handler.dynamic_cast_ptr<CLBayerPipeImageHandler> (); 337 XCAM_FAIL_RETURN ( 338 WARNING, 339 image_handler.ptr (), 340 XCAM_RETURN_ERROR_CL, 341 "CL3aImageProcessor create bayer pipe handler failed"); 342 343 _bayer_pipe->enable_denoise (XCAM_DENOISE_TYPE_BNR & _snr_mode); 344 image_handler->set_pool_size (XCAM_CL_3A_IMAGE_MAX_POOL_SIZE * 2); 345 add_handler (image_handler); 346 if(_capture_stage == BasicbayerStage) 347 return XCAM_RETURN_NO_ERROR; 348 349 image_handler = create_cl_yuv_pipe_image_handler (context); 350 _yuv_pipe = image_handler.dynamic_cast_ptr<CLYuvPipeImageHandler> (); 351 XCAM_FAIL_RETURN ( 352 WARNING, 353 _yuv_pipe.ptr (), 354 XCAM_RETURN_ERROR_CL, 355 "CL3aImageProcessor create yuv pipe handler failed"); 356 _yuv_pipe->set_tnr_enable (_tnr_mode & CL_TNR_TYPE_YUV); 357 image_handler->set_pool_size (XCAM_CL_3A_IMAGE_MAX_POOL_SIZE * 2); 358 add_handler (image_handler); 359 360 #if ENABLE_YEENR_HANDLER 361 /* ee */ 362 image_handler = create_cl_ee_image_handler (context); 363 _ee = image_handler.dynamic_cast_ptr<CLEeImageHandler> (); 364 XCAM_FAIL_RETURN ( 365 WARNING, 366 _ee.ptr (), 367 XCAM_RETURN_ERROR_CL, 368 "CL3aImageProcessor create ee handler failed"); 369 _ee->enable_handler (XCAM_DENOISE_TYPE_EE & _snr_mode); 370 image_handler->set_pool_type (CLImageHandler::CLVideoPoolType); 371 image_handler->set_pool_size (XCAM_CL_3A_IMAGE_MAX_POOL_SIZE); 372 add_handler (image_handler); 373 #endif 374 375 XCAM_FAIL_RETURN ( 376 WARNING, 377 post_config (), 378 XCAM_RETURN_ERROR_CL, 379 "CL3aImageProcessor post_config failed"); 380 381 return XCAM_RETURN_NO_ERROR; 382 } 383 384 bool 385 CL3aImageProcessor::post_config () 386 { 387 CLImageProcessor::ImageHandlerList::iterator i_handler = handlers_begin (); 388 CLImageProcessor::ImageHandlerList::iterator end = handlers_end (); 389 uint32_t swap_y_count = 0; 390 bool start_count = false; 391 bool ret = true; 392 393 if (!_yuv_pipe.ptr ()) //not necessary to check 394 return true; 395 396 for (; i_handler != end; ++i_handler) { 397 if (!start_count) { 398 SmartPtr<CLYuvPipeImageHandler> convert_yuv = (*i_handler).dynamic_cast_ptr<CLYuvPipeImageHandler> (); 399 if (convert_yuv.ptr () && convert_yuv.ptr () == _yuv_pipe.ptr ()) 400 start_count = true; 401 continue; 402 } 403 404 SmartPtr<CLCloneImageHandler> clone_y = (*i_handler).dynamic_cast_ptr<CLCloneImageHandler> (); 405 if (clone_y.ptr () && clone_y->is_handler_enabled () && (clone_y->get_clone_flags () & SwappedBuffer::SwapY)) 406 swap_y_count++; 407 } 408 409 if (swap_y_count % 2 == 1) 410 ret = _yuv_pipe->enable_buf_pool_swap_flags (SwappedBuffer::SwapY | SwappedBuffer::SwapUV, SwappedBuffer::OrderY1Y0 | SwappedBuffer::OrderUV0UV1); 411 else 412 ret = _yuv_pipe->enable_buf_pool_swap_flags (SwappedBuffer::SwapY | SwappedBuffer::SwapUV, SwappedBuffer::OrderY0Y1 | SwappedBuffer::OrderUV0UV1); 413 414 return ret; 415 } 416 417 bool 418 CL3aImageProcessor::set_profile (const CL3aImageProcessor::PipelineProfile value) 419 { 420 _pipeline_profile = value; 421 422 if (value >= AdvancedPipelineProfile) 423 _tnr_mode |= CL_TNR_TYPE_YUV; 424 425 if (value >= ExtremePipelineProfile) { 426 _snr_mode |= XCAM_DENOISE_TYPE_BNR; 427 } 428 STREAM_LOCK; 429 if (_yuv_pipe.ptr ()) 430 _yuv_pipe->set_tnr_enable (_tnr_mode & CL_TNR_TYPE_YUV); 431 432 return true; 433 } 434 435 bool 436 CL3aImageProcessor::set_gamma (bool enable) 437 { 438 _enable_gamma = enable; 439 440 STREAM_LOCK; 441 442 return true; 443 } 444 445 bool 446 CL3aImageProcessor::set_denoise (uint32_t mode) 447 { 448 _snr_mode = mode; 449 450 STREAM_LOCK; 451 if (_bayer_pipe.ptr ()) 452 _bayer_pipe->enable_denoise (XCAM_DENOISE_TYPE_BNR & _snr_mode); 453 454 return true; 455 } 456 457 bool 458 CL3aImageProcessor::set_macc (bool enable) 459 { 460 _enable_macc = enable; 461 462 STREAM_LOCK; 463 return true; 464 } 465 466 bool 467 CL3aImageProcessor::set_tonemapping (CLTonemappingMode wdr_mode) 468 { 469 _wdr_mode = wdr_mode; 470 471 STREAM_LOCK; 472 473 return true; 474 } 475 476 bool 477 CL3aImageProcessor::set_tnr (uint32_t mode, uint8_t level) 478 { 479 XCAM_UNUSED (level); 480 _tnr_mode = mode; 481 482 STREAM_LOCK; 483 if (_yuv_pipe.ptr ()) 484 _yuv_pipe->set_tnr_enable (_tnr_mode & CL_TNR_TYPE_YUV); 485 486 return true; 487 } 488 489 }; 490