Home | History | Annotate | Download | only in ocl
      1 /*
      2  * cl_post_image_processor.cpp - CL post 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  * Author: Yinhang Liu <yinhangx.liu (at) intel.com>
     20  */
     21 
     22 #include "cl_post_image_processor.h"
     23 #include "cl_context.h"
     24 
     25 #include "cl_tnr_handler.h"
     26 #include "cl_retinex_handler.h"
     27 #include "cl_defog_dcp_handler.h"
     28 #include "cl_wavelet_denoise_handler.h"
     29 #include "cl_newwavelet_denoise_handler.h"
     30 #include "cl_3d_denoise_handler.h"
     31 #include "cl_image_scaler.h"
     32 #include "cl_wire_frame_handler.h"
     33 #include "cl_csc_handler.h"
     34 #include "cl_image_warp_handler.h"
     35 #include "cl_image_360_stitch.h"
     36 #include "cl_video_stabilizer.h"
     37 
     38 #define XCAM_CL_POST_IMAGE_DEFAULT_POOL_SIZE 6
     39 #define XCAM_CL_POST_IMAGE_MAX_POOL_SIZE 12
     40 
     41 namespace XCam {
     42 
     43 CLPostImageProcessor::CLPostImageProcessor ()
     44     : CLImageProcessor ("CLPostImageProcessor")
     45     , _output_fourcc (V4L2_PIX_FMT_NV12)
     46     , _out_sample_type (OutSampleYuv)
     47     , _scaler_factor (1.0)
     48     , _tnr_mode (TnrYuv)
     49     , _defog_mode (CLPostImageProcessor::DefogDisabled)
     50     , _wavelet_basis (CL_WAVELET_DISABLED)
     51     , _wavelet_channel (CL_IMAGE_CHANNEL_UV)
     52     , _wavelet_bayes_shrink (false)
     53     , _3d_denoise_mode (CLPostImageProcessor::Denoise3DDisabled)
     54     , _3d_denoise_ref_count (3)
     55     , _enable_scaler (false)
     56     , _enable_wireframe (false)
     57     , _enable_image_warp (false)
     58     , _enable_stitch (false)
     59     , _stitch_enable_seam (false)
     60     , _stitch_fisheye_map (false)
     61     , _stitch_lsc (false)
     62     , _stitch_fm_ocl (false)
     63     , _stitch_scale_mode (CLBlenderScaleLocal)
     64     , _stitch_width (0)
     65     , _stitch_height (0)
     66     , _stitch_res_mode (0)
     67     , _surround_mode (SphereView)
     68 {
     69     XCAM_LOG_DEBUG ("CLPostImageProcessor constructed");
     70 }
     71 
     72 CLPostImageProcessor::~CLPostImageProcessor ()
     73 {
     74     XCAM_LOG_DEBUG ("CLPostImageProcessor destructed");
     75 }
     76 
     77 bool
     78 CLPostImageProcessor::set_output_format (uint32_t fourcc)
     79 {
     80     switch (fourcc) {
     81     case XCAM_PIX_FMT_RGBA64:
     82     case V4L2_PIX_FMT_XBGR32:
     83     case V4L2_PIX_FMT_ABGR32:
     84     case V4L2_PIX_FMT_BGR32:
     85     case V4L2_PIX_FMT_RGB32:
     86     case V4L2_PIX_FMT_ARGB32:
     87     case V4L2_PIX_FMT_XRGB32:
     88         _out_sample_type = OutSampleRGB;
     89         break;
     90     case V4L2_PIX_FMT_NV12:
     91         _out_sample_type = OutSampleYuv;
     92         break;
     93     default:
     94         XCAM_LOG_WARNING (
     95             "cl post processor doesn't support output format: %s",
     96             xcam_fourcc_to_string(fourcc));
     97         return false;
     98     }
     99 
    100     _output_fourcc = fourcc;
    101     return true;
    102 }
    103 
    104 void
    105 CLPostImageProcessor::set_stats_callback (const SmartPtr<StatsCallback> &callback)
    106 {
    107     XCAM_ASSERT (callback.ptr ());
    108     _stats_callback = callback;
    109 }
    110 
    111 bool
    112 CLPostImageProcessor::set_scaler_factor (const double factor)
    113 {
    114     _scaler_factor = factor;
    115 
    116     return true;
    117 }
    118 
    119 bool
    120 CLPostImageProcessor::can_process_result (SmartPtr < X3aResult > & result)
    121 {
    122     if (!result.ptr ())
    123         return false;
    124 
    125     switch (result->get_type ()) {
    126     case XCAM_3A_RESULT_TEMPORAL_NOISE_REDUCTION_YUV:
    127     case XCAM_3A_RESULT_3D_NOISE_REDUCTION:
    128     case XCAM_3A_RESULT_WAVELET_NOISE_REDUCTION:
    129     case XCAM_3A_RESULT_FACE_DETECTION:
    130     case XCAM_3A_RESULT_DVS:
    131         return true;
    132     default:
    133         return false;
    134     }
    135 
    136     return false;
    137 }
    138 
    139 XCamReturn
    140 CLPostImageProcessor::apply_3a_results (X3aResultList &results)
    141 {
    142     XCamReturn ret = XCAM_RETURN_NO_ERROR;
    143 
    144     for (X3aResultList::iterator iter = results.begin (); iter != results.end (); ++iter)
    145     {
    146         SmartPtr<X3aResult> &result = *iter;
    147         ret = apply_3a_result (result);
    148         if (ret != XCAM_RETURN_NO_ERROR)
    149             break;
    150     }
    151 
    152     return ret;
    153 }
    154 
    155 XCamReturn
    156 CLPostImageProcessor::apply_3a_result (SmartPtr<X3aResult> &result)
    157 {
    158     STREAM_LOCK;
    159 
    160     if (!result.ptr ())
    161         return XCAM_RETURN_BYPASS;
    162 
    163     uint32_t res_type = result->get_type ();
    164 
    165     switch (res_type) {
    166     case XCAM_3A_RESULT_TEMPORAL_NOISE_REDUCTION_YUV: {
    167         SmartPtr<X3aTemporalNoiseReduction> tnr_res = result.dynamic_cast_ptr<X3aTemporalNoiseReduction> ();
    168         XCAM_ASSERT (tnr_res.ptr ());
    169         if (_tnr.ptr ()) {
    170             if (_defog_mode != CLPostImageProcessor::DefogDisabled) {
    171                 XCam3aResultTemporalNoiseReduction config;
    172                 xcam_mem_clear (config);
    173                 // isp processor
    174                 // config.gain = 0.12;
    175 
    176                 // cl processor
    177                 config.gain = 0.22;
    178 
    179                 config.threshold [0] = 0.00081;
    180                 config.threshold [1] = 0.00072;
    181                 _tnr->set_yuv_config (config);
    182             } else {
    183                 _tnr->set_yuv_config (tnr_res->get_standard_result ());
    184             }
    185         }
    186         break;
    187     }
    188     case XCAM_3A_RESULT_3D_NOISE_REDUCTION: {
    189         SmartPtr<X3aTemporalNoiseReduction> nr_res = result.dynamic_cast_ptr<X3aTemporalNoiseReduction> ();
    190         XCAM_ASSERT (nr_res.ptr ());
    191         if (_3d_denoise.ptr ()) {
    192             _3d_denoise->set_denoise_config (nr_res->get_standard_result ());
    193         }
    194         break;
    195     }
    196     case XCAM_3A_RESULT_WAVELET_NOISE_REDUCTION: {
    197         SmartPtr<X3aWaveletNoiseReduction> wavelet_res = result.dynamic_cast_ptr<X3aWaveletNoiseReduction> ();
    198         XCAM_ASSERT (wavelet_res.ptr ());
    199         if (_wavelet.ptr()) {
    200             _wavelet->set_denoise_config (wavelet_res->get_standard_result ());
    201         }
    202         if (_newwavelet.ptr()) {
    203             _newwavelet->set_denoise_config (wavelet_res->get_standard_result ());
    204         }
    205         break;
    206     }
    207     case XCAM_3A_RESULT_FACE_DETECTION: {
    208         SmartPtr<X3aFaceDetectionResult> fd_res = result.dynamic_cast_ptr<X3aFaceDetectionResult> ();
    209         XCAM_ASSERT (fd_res.ptr ());
    210         if (_wireframe.ptr ()) {
    211             _wireframe->set_wire_frame_config (fd_res->get_standard_result_ptr (), get_scaler_factor ());
    212         }
    213         break;
    214     }
    215     case XCAM_3A_RESULT_DVS: {
    216         SmartPtr<X3aDVSResult> dvs_res = result.dynamic_cast_ptr<X3aDVSResult> ();
    217         XCAM_ASSERT (dvs_res.ptr ());
    218         if (_image_warp.ptr ()) {
    219             _image_warp->set_warp_config (dvs_res->get_standard_result ());
    220         }
    221         break;
    222     }
    223     default:
    224         XCAM_LOG_WARNING ("CLPostImageProcessor unknown 3a result: %d", res_type);
    225         break;
    226     }
    227 
    228     return XCAM_RETURN_NO_ERROR;
    229 }
    230 
    231 
    232 XCamReturn
    233 CLPostImageProcessor::create_handlers ()
    234 {
    235     SmartPtr<CLImageHandler> image_handler;
    236     SmartPtr<CLContext> context = get_cl_context ();
    237 
    238     XCAM_ASSERT (context.ptr ());
    239 
    240     /* defog: retinex */
    241     image_handler = create_cl_retinex_image_handler (context);
    242     _retinex = image_handler.dynamic_cast_ptr<CLRetinexImageHandler> ();
    243     XCAM_FAIL_RETURN (
    244         WARNING,
    245         _retinex.ptr (),
    246         XCAM_RETURN_ERROR_CL,
    247         "CLPostImageProcessor create retinex handler failed");
    248     _retinex->enable_handler (_defog_mode == CLPostImageProcessor::DefogRetinex);
    249     image_handler->set_pool_type (CLImageHandler::CLVideoPoolType);
    250     image_handler->set_pool_size (XCAM_CL_POST_IMAGE_MAX_POOL_SIZE);
    251     add_handler (image_handler);
    252 
    253     /* defog: dark channel prior */
    254     image_handler = create_cl_defog_dcp_image_handler (context);
    255     _defog_dcp = image_handler.dynamic_cast_ptr<CLDefogDcpImageHandler> ();
    256     XCAM_FAIL_RETURN (
    257         WARNING,
    258         _defog_dcp.ptr (),
    259         XCAM_RETURN_ERROR_CL,
    260         "CLPostImageProcessor create defog handler failed");
    261     _defog_dcp->enable_handler (_defog_mode == CLPostImageProcessor::DefogDarkChannelPrior);
    262     image_handler->set_pool_type (CLImageHandler::CLVideoPoolType);
    263     image_handler->set_pool_size (XCAM_CL_POST_IMAGE_MAX_POOL_SIZE);
    264     add_handler (image_handler);
    265 
    266     /* Temporal Noise Reduction */
    267     if (_defog_mode != CLPostImageProcessor::DefogDisabled) {
    268         switch (_tnr_mode) {
    269         case TnrYuv: {
    270             image_handler = create_cl_tnr_image_handler (context, CL_TNR_TYPE_YUV);
    271             _tnr = image_handler.dynamic_cast_ptr<CLTnrImageHandler> ();
    272             XCAM_FAIL_RETURN (
    273                 WARNING,
    274                 _tnr.ptr (),
    275                 XCAM_RETURN_ERROR_CL,
    276                 "CLPostImageProcessor create tnr handler failed");
    277             image_handler->set_pool_type (CLImageHandler::CLVideoPoolType);
    278             image_handler->set_pool_size (XCAM_CL_POST_IMAGE_DEFAULT_POOL_SIZE);
    279             add_handler (image_handler);
    280             break;
    281         }
    282         case TnrDisable:
    283             XCAM_LOG_DEBUG ("CLPostImageProcessor disable tnr");
    284             break;
    285         default:
    286             XCAM_LOG_WARNING ("CLPostImageProcessor unknown tnr mode (%d)", _tnr_mode);
    287             break;
    288         }
    289     }
    290 
    291     /* wavelet denoise */
    292     switch (_wavelet_basis) {
    293     case CL_WAVELET_HAT: {
    294         image_handler = create_cl_wavelet_denoise_image_handler (context, _wavelet_channel);
    295         _wavelet = image_handler.dynamic_cast_ptr<CLWaveletDenoiseImageHandler> ();
    296         XCAM_FAIL_RETURN (
    297             WARNING,
    298             _wavelet.ptr (),
    299             XCAM_RETURN_ERROR_CL,
    300             "CLPostImageProcessor create wavelet denoise handler failed");
    301         _wavelet->enable_handler (true);
    302         image_handler->set_pool_type (CLImageHandler::CLVideoPoolType);
    303         image_handler->set_pool_size (XCAM_CL_POST_IMAGE_DEFAULT_POOL_SIZE);
    304         add_handler (image_handler);
    305         break;
    306     }
    307     case CL_WAVELET_HAAR: {
    308         image_handler = create_cl_newwavelet_denoise_image_handler (context, _wavelet_channel, _wavelet_bayes_shrink);
    309         _newwavelet = image_handler.dynamic_cast_ptr<CLNewWaveletDenoiseImageHandler> ();
    310         XCAM_FAIL_RETURN (
    311             WARNING,
    312             _newwavelet.ptr (),
    313             XCAM_RETURN_ERROR_CL,
    314             "CLPostImageProcessor create new wavelet denoise handler failed");
    315         _newwavelet->enable_handler (true);
    316         image_handler->set_pool_type (CLImageHandler::CLVideoPoolType);
    317         image_handler->set_pool_size (XCAM_CL_POST_IMAGE_DEFAULT_POOL_SIZE);
    318         add_handler (image_handler);
    319         break;
    320     }
    321     case CL_WAVELET_DISABLED:
    322     default :
    323         XCAM_LOG_DEBUG ("unknown or disable wavelet (%d)", _wavelet_basis);
    324         break;
    325     }
    326 
    327     /* 3D noise reduction */
    328     if (_3d_denoise_mode != CLPostImageProcessor::Denoise3DDisabled) {
    329         uint32_t denoise_channel = CL_IMAGE_CHANNEL_UV;
    330 
    331         if (_3d_denoise_mode == CLPostImageProcessor::Denoise3DUV) {
    332             denoise_channel = CL_IMAGE_CHANNEL_UV;
    333         } else if (_3d_denoise_mode == CLPostImageProcessor::Denoise3DYuv) {
    334             denoise_channel = CL_IMAGE_CHANNEL_Y | CL_IMAGE_CHANNEL_UV;
    335         }
    336 
    337         image_handler = create_cl_3d_denoise_image_handler (context, denoise_channel, _3d_denoise_ref_count);
    338         _3d_denoise = image_handler.dynamic_cast_ptr<CL3DDenoiseImageHandler> ();
    339         XCAM_FAIL_RETURN (
    340             WARNING,
    341             _3d_denoise.ptr (),
    342             XCAM_RETURN_ERROR_CL,
    343             "CL3aImageProcessor create 3D noise reduction handler failed");
    344         image_handler->set_pool_type (CLImageHandler::CLVideoPoolType);
    345         image_handler->set_pool_size (XCAM_CL_POST_IMAGE_MAX_POOL_SIZE);
    346         image_handler->enable_handler (true);
    347         add_handler (image_handler);
    348     }
    349 
    350     /* image scaler */
    351     image_handler = create_cl_image_scaler_handler (context, V4L2_PIX_FMT_NV12);
    352     _scaler = image_handler.dynamic_cast_ptr<CLImageScaler> ();
    353     XCAM_FAIL_RETURN (
    354         WARNING,
    355         _scaler.ptr (),
    356         XCAM_RETURN_ERROR_CL,
    357         "CLPostImageProcessor create scaler handler failed");
    358     _scaler->set_scaler_factor (_scaler_factor, _scaler_factor);
    359     _scaler->set_buffer_callback (_stats_callback);
    360     image_handler->set_pool_type (CLImageHandler::CLVideoPoolType);
    361     image_handler->enable_handler (_enable_scaler);
    362     add_handler (image_handler);
    363 
    364     /* wire frame */
    365     image_handler = create_cl_wire_frame_image_handler (context);
    366     _wireframe = image_handler.dynamic_cast_ptr<CLWireFrameImageHandler> ();
    367     XCAM_FAIL_RETURN (
    368         WARNING,
    369         _wireframe.ptr (),
    370         XCAM_RETURN_ERROR_CL,
    371         "CLPostImageProcessor create wire frame handler failed");
    372     _wireframe->enable_handler (_enable_wireframe);
    373     image_handler->set_pool_type (CLImageHandler::CLVideoPoolType);
    374     image_handler->set_pool_size (XCAM_CL_POST_IMAGE_DEFAULT_POOL_SIZE);
    375     add_handler (image_handler);
    376 
    377     /* image warp */
    378     image_handler = create_cl_image_warp_handler (context);
    379     _image_warp = image_handler.dynamic_cast_ptr<CLImageWarpHandler> ();
    380     XCAM_FAIL_RETURN (
    381         WARNING,
    382         _image_warp.ptr (),
    383         XCAM_RETURN_ERROR_CL,
    384         "CLPostImageProcessor create image warp handler failed");
    385     _image_warp->enable_handler (_enable_image_warp);
    386     image_handler->set_pool_type (CLImageHandler::CLVideoPoolType);
    387     image_handler->set_pool_size (XCAM_CL_POST_IMAGE_MAX_POOL_SIZE);
    388     add_handler (image_handler);
    389 
    390     /* video stabilization */
    391     image_handler = create_cl_video_stab_handler (context);
    392     _video_stab = image_handler.dynamic_cast_ptr<CLVideoStabilizer> ();
    393     XCAM_FAIL_RETURN (
    394         WARNING,
    395         _video_stab.ptr (),
    396         XCAM_RETURN_ERROR_CL,
    397         "CLPostImageProcessor create video stabilizer failed");
    398     _video_stab->enable_handler (false);
    399     image_handler->set_pool_type (CLImageHandler::CLVideoPoolType);
    400     image_handler->set_pool_size (XCAM_CL_POST_IMAGE_MAX_POOL_SIZE);
    401     add_handler (image_handler);
    402 
    403     /* image stitch */
    404     image_handler =
    405         create_image_360_stitch (context, _stitch_enable_seam, _stitch_scale_mode,
    406                                  _stitch_fisheye_map, _stitch_lsc, (SurroundMode) _surround_mode, (StitchResMode) _stitch_res_mode);
    407     _stitch = image_handler.dynamic_cast_ptr<CLImage360Stitch> ();
    408     XCAM_FAIL_RETURN (
    409         WARNING,
    410         _stitch.ptr (),
    411         XCAM_RETURN_ERROR_CL,
    412         "CLPostImageProcessor create image stitch handler failed");
    413     _stitch->set_output_size (_stitch_width, _stitch_height);
    414 #if HAVE_OPENCV
    415     _stitch->set_feature_match_ocl (_stitch_fm_ocl);
    416 #endif
    417     image_handler->set_pool_type (CLImageHandler::CLVideoPoolType);
    418     image_handler->set_pool_size (XCAM_CL_POST_IMAGE_MAX_POOL_SIZE);
    419     image_handler->enable_handler (_enable_stitch);
    420     add_handler (image_handler);
    421 
    422     /* csc (nv12torgba) */
    423     image_handler = create_cl_csc_image_handler (context, CL_CSC_TYPE_NV12TORGBA);
    424     _csc = image_handler.dynamic_cast_ptr<CLCscImageHandler> ();
    425     XCAM_FAIL_RETURN (
    426         WARNING,
    427         _csc .ptr (),
    428         XCAM_RETURN_ERROR_CL,
    429         "CLPostImageProcessor create csc handler failed");
    430     _csc->enable_handler (_out_sample_type == OutSampleRGB);
    431     _csc->set_output_format (_output_fourcc);
    432     image_handler->set_pool_type (CLImageHandler::CLVideoPoolType);
    433     image_handler->set_pool_size (XCAM_CL_POST_IMAGE_DEFAULT_POOL_SIZE);
    434     add_handler (image_handler);
    435 
    436     return XCAM_RETURN_NO_ERROR;
    437 }
    438 
    439 bool
    440 CLPostImageProcessor::set_tnr (CLTnrMode mode)
    441 {
    442     _tnr_mode = mode;
    443 
    444     STREAM_LOCK;
    445 
    446     return true;
    447 }
    448 
    449 bool
    450 CLPostImageProcessor::set_defog_mode (CLDefogMode mode)
    451 {
    452     _defog_mode = mode;
    453 
    454     STREAM_LOCK;
    455 
    456     return true;
    457 }
    458 
    459 bool
    460 CLPostImageProcessor::set_wavelet (CLWaveletBasis basis, uint32_t channel, bool bayes_shrink)
    461 {
    462     _wavelet_basis = basis;
    463     _wavelet_channel = (CLImageChannel) channel;
    464     _wavelet_bayes_shrink = bayes_shrink;
    465 
    466     STREAM_LOCK;
    467 
    468     return true;
    469 }
    470 
    471 bool
    472 CLPostImageProcessor::set_3ddenoise_mode (CL3DDenoiseMode mode, uint8_t ref_frame_count)
    473 {
    474     _3d_denoise_mode = mode;
    475     _3d_denoise_ref_count = ref_frame_count;
    476 
    477     STREAM_LOCK;
    478 
    479     return true;
    480 }
    481 
    482 bool
    483 CLPostImageProcessor::set_scaler (bool enable)
    484 {
    485     _enable_scaler = enable;
    486 
    487     STREAM_LOCK;
    488 
    489     return true;
    490 }
    491 
    492 bool
    493 CLPostImageProcessor::set_wireframe (bool enable)
    494 {
    495     _enable_wireframe = enable;
    496 
    497     STREAM_LOCK;
    498 
    499     return true;
    500 }
    501 
    502 bool
    503 CLPostImageProcessor::set_image_warp (bool enable)
    504 {
    505     _enable_image_warp = enable;
    506 
    507     STREAM_LOCK;
    508 
    509     return true;
    510 }
    511 
    512 bool
    513 CLPostImageProcessor::set_image_stitch (
    514     bool enable_stitch, bool enable_seam, CLBlenderScaleMode scale_mode, bool enable_fisheye_map,
    515     bool lsc, bool fm_ocl, uint32_t stitch_width, uint32_t stitch_height, uint32_t res_mode)
    516 {
    517     XCAM_ASSERT (scale_mode < CLBlenderScaleMax);
    518 
    519     _enable_stitch = enable_stitch;
    520     if (enable_stitch)
    521         _stitch_enable_seam = enable_seam;
    522     else
    523         _stitch_enable_seam = false;
    524 
    525     _stitch_scale_mode = scale_mode;
    526     _stitch_fisheye_map = enable_fisheye_map;
    527     _stitch_lsc = lsc;
    528     _stitch_width = stitch_width;
    529     _stitch_height = stitch_height;
    530     _stitch_res_mode = res_mode;
    531 
    532 #if HAVE_OPENCV
    533     _stitch_fm_ocl = fm_ocl;
    534 #else
    535     XCAM_UNUSED (fm_ocl);
    536 #endif
    537 
    538     STREAM_LOCK;
    539 
    540     return true;
    541 }
    542 
    543 };
    544