Home | History | Annotate | Download | only in ocl
      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