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