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@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
CLTonemappingImageKernel(const SmartPtr<CLContext> & context,const char * name)32 CLTonemappingImageKernel::CLTonemappingImageKernel (
33 const SmartPtr<CLContext> &context, const char *name)
34 : CLImageKernel (context, name)
35 {
36 }
37
CLTonemappingImageHandler(const SmartPtr<CLContext> & context,const char * name)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
set_tonemapping_kernel(SmartPtr<CLTonemappingImageKernel> & kernel)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
set_wb_config(const XCam3aResultWhiteBalance & wb)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
prepare_buffer_pool_video_info(const VideoBufferInfo & input,VideoBufferInfo & output)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
prepare_parameters(SmartPtr<VideoBuffer> & input,SmartPtr<VideoBuffer> & output)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>
create_cl_tonemapping_image_handler(const SmartPtr<CLContext> & context)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