Home | History | Annotate | Download | only in ocl
      1 /*
      2  * cl_tonemapping_handler.cpp - CL tonemapping 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: Wu Junkai <junkai.wu (at) intel.com>
     19  */
     20 
     21 #include "cl_utils.h"
     22 #include "cl_tonemapping_handler.h"
     23 
     24 namespace XCam {
     25 
     26 static const XCamKernelInfo kernel_tonemapping_info = {
     27     "kernel_tonemapping",
     28 #include "kernel_tonemapping.clx"
     29     , 0,
     30 };
     31 
     32 CLTonemappingImageKernel::CLTonemappingImageKernel (
     33     const SmartPtr<CLContext> &context, const char *name)
     34     : CLImageKernel (context, name)
     35 {
     36 }
     37 
     38 CLTonemappingImageHandler::CLTonemappingImageHandler (
     39     const SmartPtr<CLContext> &context, const char *name)
     40     : CLImageHandler (context, name)
     41     , _output_format (XCAM_PIX_FMT_SGRBG16_planar)
     42 {
     43     _wb_config.r_gain = 1.0;
     44     _wb_config.gr_gain = 1.0;
     45     _wb_config.gb_gain = 1.0;
     46     _wb_config.b_gain = 1.0;
     47 }
     48 
     49 bool
     50 CLTonemappingImageHandler::set_tonemapping_kernel(SmartPtr<CLTonemappingImageKernel> &kernel)
     51 {
     52     SmartPtr<CLImageKernel> image_kernel = kernel;
     53     add_kernel (image_kernel);
     54     _tonemapping_kernel = kernel;
     55     return true;
     56 }
     57 
     58 bool
     59 CLTonemappingImageHandler::set_wb_config (const XCam3aResultWhiteBalance &wb)
     60 {
     61     _wb_config.r_gain = (float)wb.r_gain;
     62     _wb_config.gr_gain = (float)wb.gr_gain;
     63     _wb_config.gb_gain = (float)wb.gb_gain;
     64     _wb_config.b_gain = (float)wb.b_gain;
     65     return true;
     66 }
     67 
     68 XCamReturn
     69 CLTonemappingImageHandler::prepare_buffer_pool_video_info (
     70     const VideoBufferInfo &input,
     71     VideoBufferInfo &output)
     72 {
     73     bool format_inited = output.init (_output_format, input.width, input.height);
     74 
     75     XCAM_FAIL_RETURN (
     76         WARNING,
     77         format_inited,
     78         XCAM_RETURN_ERROR_PARAM,
     79         "CL image handler(%s) output format(%s) unsupported",
     80         XCAM_STR(get_name ()), xcam_fourcc_to_string (_output_format));
     81 
     82     return XCAM_RETURN_NO_ERROR;
     83 }
     84 
     85 XCamReturn
     86 CLTonemappingImageHandler::prepare_parameters (
     87     SmartPtr<VideoBuffer> &input,
     88     SmartPtr<VideoBuffer> &output)
     89 {
     90     SmartPtr<CLContext> context = get_context ();
     91     float y_max = 0.0f, y_target = 0.0f;
     92     CLArgList args;
     93     CLWorkSize work_size;
     94     XCAM_ASSERT (_tonemapping_kernel.ptr ());
     95 
     96     const VideoBufferInfo &video_info = input->get_video_info ();
     97 
     98     CLImageDesc desc;
     99     desc.format.image_channel_order = CL_RGBA;
    100     desc.format.image_channel_data_type = CL_UNORM_INT16;
    101     desc.width = video_info.aligned_width / 4;
    102     desc.height = video_info.aligned_height * 4;
    103     desc.row_pitch = video_info.strides[0];
    104     desc.array_size = 4;
    105     desc.slice_pitch = video_info.strides [0] * video_info.aligned_height;
    106 
    107     SmartPtr<CLImage> image_in = convert_to_climage (context, input, desc);
    108     SmartPtr<CLImage> image_out = convert_to_climage (context, output, desc);
    109     int image_height = video_info.aligned_height;
    110 
    111     XCAM_FAIL_RETURN (
    112         WARNING,
    113         image_in->is_valid () && image_out->is_valid (),
    114         XCAM_RETURN_ERROR_MEM,
    115         "cl image handler(%s) in/out memory not available", XCAM_STR(get_name ()));
    116 
    117     SmartPtr<X3aStats> stats;
    118     SmartPtr<CLVideoBuffer> cl_buf = input.dynamic_cast_ptr<CLVideoBuffer> ();
    119     if (cl_buf.ptr ()) {
    120         stats = cl_buf->find_3a_stats ();
    121     }
    122 #if HAVE_LIBDRM
    123     else {
    124         SmartPtr<DrmBoBuffer> bo_buf = input.dynamic_cast_ptr<DrmBoBuffer> ();
    125         stats = bo_buf->find_3a_stats ();
    126     }
    127 #endif
    128     XCAM_FAIL_RETURN (
    129         ERROR,
    130         stats.ptr (),
    131         XCAM_RETURN_ERROR_MEM,
    132         "CLTonemappingImageKernel find_3a_stats failed");
    133     XCam3AStats *stats_ptr = stats->get_stats ();
    134     XCAM_ASSERT (stats_ptr);
    135 
    136     int pixel_totalnum = stats_ptr->info.aligned_width * stats_ptr->info.aligned_height;
    137     int pixel_num = 0;
    138     int hist_bin_count = 1 << stats_ptr->info.bit_depth;
    139     int64_t cumulative_value = 0;
    140     int saturated_thresh = pixel_totalnum * 0.003f;
    141     int percent_90_thresh = pixel_totalnum * 0.1f;
    142     int medium_thresh = pixel_totalnum * 0.5f;
    143     float y_saturated = 0;
    144     float y_percent_90 = 0;
    145     float y_average = 0;
    146     float y_medium = 0;
    147 
    148     for (int i = (hist_bin_count - 1); i >= 0; i--)
    149     {
    150         pixel_num += stats_ptr->hist_y[i];
    151         if ((y_saturated == 0) && (pixel_num >= saturated_thresh))
    152         {
    153             y_saturated = i;
    154         }
    155         if ((y_percent_90 == 0) && (pixel_num >= percent_90_thresh))
    156         {
    157             y_percent_90 = i;
    158         }
    159         if ((y_medium == 0) && (pixel_num >= medium_thresh))
    160         {
    161             y_medium = i;
    162         }
    163         cumulative_value += i * stats_ptr->hist_y[i];
    164     }
    165 
    166     y_average = cumulative_value / pixel_totalnum;
    167 
    168     if (y_saturated < (hist_bin_count - 1)) {
    169         y_saturated = y_saturated + 1;
    170     }
    171 
    172     y_target =  (hist_bin_count / y_saturated) * (1.5 * y_medium + 0.5 * y_average) / 2;
    173 
    174     if (y_target < 4) {
    175         y_target = 4;
    176     }
    177     if ((y_target > y_saturated) || (y_saturated < 4)) {
    178         y_target = y_saturated / 4;
    179     }
    180 
    181     y_max = hist_bin_count * (2 * y_saturated + y_target) / y_saturated - y_saturated - y_target;
    182 
    183     y_target = y_target / pow(2, stats_ptr->info.bit_depth - 8);
    184     y_max = y_max / pow(2, stats_ptr->info.bit_depth - 8);
    185 
    186     //set args;
    187     args.push_back (new CLMemArgument (image_in));
    188     args.push_back (new CLMemArgument (image_out));
    189     args.push_back (new CLArgumentT<float> (y_max));
    190     args.push_back (new CLArgumentT<float> (y_target));
    191     args.push_back (new CLArgumentT<int> (image_height));
    192 
    193     const CLImageDesc out_info = image_out->get_image_desc ();
    194     work_size.dim = XCAM_DEFAULT_IMAGE_DIM;
    195     work_size.global[0] = out_info.width;
    196     work_size.global[1] = out_info.height / 4;
    197     work_size.local[0] = 8;
    198     work_size.local[1] = 8;
    199 
    200     XCAM_ASSERT (_tonemapping_kernel.ptr ());
    201     XCamReturn ret = _tonemapping_kernel->set_arguments (args, work_size);
    202     XCAM_FAIL_RETURN (
    203         WARNING, ret == XCAM_RETURN_NO_ERROR, ret,
    204         "tone mapping kernel set arguments failed.");
    205 
    206     return XCAM_RETURN_NO_ERROR;
    207 }
    208 
    209 
    210 SmartPtr<CLImageHandler>
    211 create_cl_tonemapping_image_handler (const SmartPtr<CLContext> &context)
    212 {
    213     SmartPtr<CLTonemappingImageHandler> tonemapping_handler;
    214     SmartPtr<CLTonemappingImageKernel> tonemapping_kernel;
    215 
    216     tonemapping_kernel = new CLTonemappingImageKernel (context, "kernel_tonemapping");
    217     XCAM_ASSERT (tonemapping_kernel.ptr ());
    218     XCAM_FAIL_RETURN (
    219         ERROR, tonemapping_kernel->build_kernel (kernel_tonemapping_info, NULL) == XCAM_RETURN_NO_ERROR, NULL,
    220         "build tonemapping kernel(%s) failed", kernel_tonemapping_info.kernel_name);
    221 
    222     XCAM_ASSERT (tonemapping_kernel->is_valid ());
    223     tonemapping_handler = new CLTonemappingImageHandler(context, "cl_handler_tonemapping");
    224     tonemapping_handler->set_tonemapping_kernel(tonemapping_kernel);
    225 
    226     return tonemapping_handler;
    227 }
    228 
    229 };
    230