• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * cl_retinex_handler.cpp - CL retinex handler
3  *
4  *  Copyright (c) 2016 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: wangfei <feix.w.wang@intel.com>
19  *             Wind Yuan <feng.yuan@intel.com>
20  */
21 
22 #include "cl_utils.h"
23 #include "cl_retinex_handler.h"
24 #include <algorithm>
25 #include "cl_device.h"
26 
27 namespace XCam {
28 
29 static uint32_t retinex_gauss_scale [3] = {2, 8, 20}; //{20, 60, 150};
30 static float retinex_gauss_sigma [3] = {2.0f, 8.0f, 20.0f}; //{12.0f, 40.0f, 120.0f};
31 static float retinex_config_log_min = -0.12f; // -0.18f
32 static float retinex_config_log_max = 0.18f;  //0.2f
33 
34 enum {
35     KernelScaler = 0,
36     KernelGaussian,
37     KernelRetinex,
38 };
39 
40 const static XCamKernelInfo kernel_retinex_info [] = {
41     {
42         "kernel_image_scaler",
43 #include "kernel_image_scaler.clx"
44         , 0,
45     },
46     {
47         "kernel_gauss",
48 #include "kernel_gauss.clx"
49         , 0,
50     },
51     {
52         "kernel_retinex",
53 #include "kernel_retinex.clx"
54         , 0,
55     },
56 };
57 
CLRetinexScalerImageKernel(const SmartPtr<CLContext> & context,const CLImageScalerMemoryLayout mem_layout,SmartPtr<CLRetinexImageHandler> & retinex)58 CLRetinexScalerImageKernel::CLRetinexScalerImageKernel (
59     const SmartPtr<CLContext> &context,
60     const CLImageScalerMemoryLayout mem_layout,
61     SmartPtr<CLRetinexImageHandler> &retinex)
62     : CLScalerKernel (context, mem_layout)
63     , _retinex(retinex)
64 {
65 }
66 
67 SmartPtr<VideoBuffer>
get_input_buffer()68 CLRetinexScalerImageKernel::get_input_buffer ()
69 {
70     return _retinex->get_input_buf ();
71 }
72 
73 SmartPtr<VideoBuffer>
get_output_buffer()74 CLRetinexScalerImageKernel::get_output_buffer ()
75 {
76     return _retinex->get_scaler_buf1 ();
77 }
78 
CLRetinexGaussImageKernel(const SmartPtr<CLContext> & context,SmartPtr<CLRetinexImageHandler> & retinex,uint32_t index,uint32_t radius,float sigma)79 CLRetinexGaussImageKernel::CLRetinexGaussImageKernel (
80     const SmartPtr<CLContext> &context,
81     SmartPtr<CLRetinexImageHandler> &retinex,
82     uint32_t index,
83     uint32_t radius, float sigma)
84     : CLGaussImageKernel (context, radius, sigma)
85     , _retinex (retinex)
86     , _index (index)
87 {
88 }
89 
90 SmartPtr<VideoBuffer>
get_input_buf()91 CLRetinexGaussImageKernel::get_input_buf ()
92 {
93     return _retinex->get_scaler_buf1 ();
94 }
95 
96 SmartPtr<VideoBuffer>
get_output_buf()97 CLRetinexGaussImageKernel::get_output_buf ()
98 {
99     return _retinex->get_gaussian_buf (_index);
100 }
101 
CLRetinexImageKernel(const SmartPtr<CLContext> & context,SmartPtr<CLRetinexImageHandler> & retinex)102 CLRetinexImageKernel::CLRetinexImageKernel (const SmartPtr<CLContext> &context, SmartPtr<CLRetinexImageHandler> &retinex)
103     : CLImageKernel (context, "kernel_retinex"),
104       _retinex (retinex)
105 {
106 }
107 
108 XCamReturn
prepare_arguments(CLArgList & args,CLWorkSize & work_size)109 CLRetinexImageKernel::prepare_arguments (
110     CLArgList &args, CLWorkSize &work_size)
111 {
112     SmartPtr<CLContext> context = get_context ();
113     SmartPtr<VideoBuffer> input = _retinex->get_input_buf ();
114     SmartPtr<VideoBuffer> output = _retinex->get_output_buf ();
115 
116     const VideoBufferInfo & video_info_in = input->get_video_info ();
117     const VideoBufferInfo & video_info_out = output->get_video_info ();
118     SmartPtr<CLImage> image_in, image_in_uv;
119     SmartPtr<CLImage> image_out, image_out_uv;
120     SmartPtr<CLImage> image_in_ga[XCAM_RETINEX_MAX_SCALE];
121 
122     CLImageDesc cl_desc_in, cl_desc_out, cl_desc_ga;
123 
124     cl_desc_in.format.image_channel_data_type = CL_UNORM_INT8; //CL_UNSIGNED_INT32;
125     cl_desc_in.format.image_channel_order = CL_RGBA;
126     cl_desc_in.width = video_info_in.width / 4; // 16;
127     cl_desc_in.height = video_info_in.height;
128     cl_desc_in.row_pitch = video_info_in.strides[0];
129     image_in = convert_to_climage (context, input, cl_desc_in, video_info_in.offsets[0]);
130 
131     cl_desc_in.height = video_info_in.height / 2;
132     cl_desc_in.row_pitch = video_info_in.strides[1];
133     image_in_uv = convert_to_climage (context, input, cl_desc_in, video_info_in.offsets[1]);
134 
135     cl_desc_out.format.image_channel_data_type = CL_UNORM_INT8; //CL_UNSIGNED_INT32;
136     cl_desc_out.format.image_channel_order = CL_RGBA;
137     cl_desc_out.width = video_info_out.width / 4; // 16;
138     cl_desc_out.height = video_info_out.height;
139     cl_desc_out.row_pitch = video_info_out.strides[0];
140     image_out = convert_to_climage (context, output, cl_desc_out, video_info_out.offsets[0]);
141 
142     cl_desc_out.height = video_info_out.height / 2;
143     cl_desc_out.row_pitch = video_info_out.strides[1];
144     image_out_uv = convert_to_climage (context, output, cl_desc_out, video_info_out.offsets[1]);
145 
146     XCAM_FAIL_RETURN (
147         WARNING,
148         image_in->is_valid () && image_in_uv->is_valid () &&
149         image_out->is_valid () && image_out_uv->is_valid(),
150         XCAM_RETURN_ERROR_MEM,
151         "cl image kernel(%s) in/out memory not available", get_kernel_name ());
152 
153     for (uint32_t i = 0; i < XCAM_RETINEX_MAX_SCALE; ++i) {
154         SmartPtr<VideoBuffer> gaussian_buf = _retinex->get_gaussian_buf (i);
155         XCAM_ASSERT (gaussian_buf.ptr ());
156 
157         const VideoBufferInfo & video_info_gauss = gaussian_buf->get_video_info ();
158 
159         cl_desc_ga.format.image_channel_data_type = CL_UNORM_INT8;
160         cl_desc_ga.format.image_channel_order = CL_R;
161         cl_desc_ga.width = video_info_gauss.width;
162         cl_desc_ga.height = video_info_gauss.height;
163         cl_desc_ga.row_pitch = video_info_gauss.strides[0];
164         image_in_ga[i] = convert_to_climage (context, gaussian_buf, cl_desc_ga, video_info_gauss.offsets[0]);
165 
166         XCAM_FAIL_RETURN (
167             WARNING,
168             image_in_ga[i]->is_valid (),
169             XCAM_RETURN_ERROR_MEM,
170             "cl image kernel(%s) gauss memory[%d] is invalid", get_kernel_name (), i);
171     }
172     CLRetinexConfig retinex_config;
173     retinex_config.log_min = retinex_config_log_min;
174     retinex_config.log_max = retinex_config_log_max;
175     retinex_config.gain = 1.0f / (retinex_config.log_max - retinex_config.log_min);
176     retinex_config.width = (float)video_info_in.width;
177     retinex_config.height = (float)video_info_in.height;
178 
179     //set args;
180     args.push_back (new CLMemArgument (image_in));
181     args.push_back (new CLMemArgument (image_in_uv));
182     for (uint32_t i = 0; i < XCAM_RETINEX_MAX_SCALE; ++i) {
183         args.push_back (new CLMemArgument (image_in_ga[i]));
184     }
185     args.push_back (new CLMemArgument (image_out));
186     args.push_back (new CLMemArgument (image_out_uv));
187     args.push_back (new CLArgumentT<CLRetinexConfig> (retinex_config));
188 
189     work_size.dim = XCAM_DEFAULT_IMAGE_DIM;
190     work_size.global[0] = video_info_out.width / 4;
191     work_size.global[1] = video_info_out.height;
192     work_size.local[0] = 16;
193     work_size.local[1] = 2;
194 
195     return XCAM_RETURN_NO_ERROR;
196 }
197 
CLRetinexImageHandler(const SmartPtr<CLContext> & context,const char * name)198 CLRetinexImageHandler::CLRetinexImageHandler (const SmartPtr<CLContext> &context, const char *name)
199     : CLImageHandler (context, name)
200     , _scaler_factor(XCAM_RETINEX_SCALER_FACTOR)
201 {
202 }
203 
204 void
emit_stop()205 CLRetinexImageHandler::emit_stop ()
206 {
207     if (_scaler_buf_pool.ptr ())
208         _scaler_buf_pool->stop ();
209 }
210 
211 XCamReturn
prepare_output_buf(SmartPtr<VideoBuffer> & input,SmartPtr<VideoBuffer> & output)212 CLRetinexImageHandler::prepare_output_buf (SmartPtr<VideoBuffer> &input, SmartPtr<VideoBuffer> &output)
213 {
214     CLImageHandler::prepare_output_buf(input, output);
215     XCamReturn ret = XCAM_RETURN_NO_ERROR;
216     ret = prepare_scaler_buf (input->get_video_info ());
217     XCAM_FAIL_RETURN(
218         WARNING,
219         ret == XCAM_RETURN_NO_ERROR,
220         ret,
221         "CLRetinexImageHandler prepare scaled video buf failed");
222 
223     return XCAM_RETURN_NO_ERROR;
224 }
225 
226 XCamReturn
prepare_scaler_buf(const VideoBufferInfo & video_info)227 CLRetinexImageHandler::prepare_scaler_buf (const VideoBufferInfo &video_info)
228 {
229     if (!_scaler_buf_pool.ptr ()) {
230         SmartPtr<CLContext> context = get_context ();
231         VideoBufferInfo scaler_video_info;
232         uint32_t new_width = XCAM_ALIGN_UP ((uint32_t)(video_info.width * _scaler_factor), 8);
233         uint32_t new_height = XCAM_ALIGN_UP ((uint32_t)(video_info.height * _scaler_factor), 4);
234 
235         scaler_video_info.init (video_info.format, new_width, new_height);
236 
237         _scaler_buf_pool = new CLVideoBufferPool ();
238         XCAM_ASSERT (_scaler_buf_pool.ptr ());
239         _scaler_buf_pool->set_video_info (scaler_video_info);
240         _scaler_buf_pool->reserve (XCAM_RETINEX_MAX_SCALE + 1);
241 
242         _scaler_buf1 = _scaler_buf_pool->get_buffer (_scaler_buf_pool);
243         XCAM_ASSERT (_scaler_buf1.ptr ());
244 
245         for (int i = 0; i < XCAM_RETINEX_MAX_SCALE; ++i) {
246             _gaussian_buf[i] = _scaler_buf_pool->get_buffer (_scaler_buf_pool);
247             XCAM_ASSERT (_gaussian_buf[i].ptr ());
248         }
249     }
250 
251     return XCAM_RETURN_NO_ERROR;
252 }
253 
254 bool
set_retinex_kernel(SmartPtr<CLRetinexImageKernel> & kernel)255 CLRetinexImageHandler::set_retinex_kernel(SmartPtr<CLRetinexImageKernel> &kernel)
256 {
257     SmartPtr<CLImageKernel> image_kernel = kernel;
258     add_kernel (image_kernel);
259     _retinex_kernel = kernel;
260     return true;
261 }
262 
263 bool
set_retinex_scaler_kernel(SmartPtr<CLRetinexScalerImageKernel> & kernel)264 CLRetinexImageHandler::set_retinex_scaler_kernel(SmartPtr<CLRetinexScalerImageKernel> &kernel)
265 {
266     SmartPtr<CLImageKernel> image_kernel = kernel;
267     add_kernel (image_kernel);
268     _retinex_scaler_kernel = kernel;
269     return true;
270 }
271 
272 static SmartPtr<CLRetinexScalerImageKernel>
create_kernel_retinex_scaler(const SmartPtr<CLContext> & context,SmartPtr<CLRetinexImageHandler> handler)273 create_kernel_retinex_scaler (
274     const SmartPtr<CLContext> &context, SmartPtr<CLRetinexImageHandler> handler)
275 {
276     SmartPtr<CLRetinexScalerImageKernel> kernel;
277 
278     kernel = new CLRetinexScalerImageKernel (context, CL_IMAGE_SCALER_NV12_Y, handler);
279     XCAM_ASSERT (kernel.ptr ());
280     XCAM_FAIL_RETURN (
281         ERROR, kernel->build_kernel (kernel_retinex_info[KernelScaler], NULL) == XCAM_RETURN_NO_ERROR, NULL,
282         "build retinex scaler kernel(%s) failed", kernel_retinex_info[KernelScaler].kernel_name);
283 
284     XCAM_ASSERT (kernel->is_valid ());
285     return kernel;
286 }
287 
288 static SmartPtr<CLRetinexGaussImageKernel>
create_kernel_retinex_gaussian(const SmartPtr<CLContext> & context,SmartPtr<CLRetinexImageHandler> handler,uint32_t index,uint32_t radius,float sigma)289 create_kernel_retinex_gaussian (
290     const SmartPtr<CLContext> &context,
291     SmartPtr<CLRetinexImageHandler> handler,
292     uint32_t index,
293     uint32_t radius, float sigma)
294 {
295     SmartPtr<CLRetinexGaussImageKernel> kernel;
296     char build_options[1024];
297 
298     xcam_mem_clear (build_options);
299     snprintf (build_options, sizeof (build_options), " -DGAUSS_RADIUS=%d ", radius);
300 
301     kernel = new CLRetinexGaussImageKernel (context, handler, index, radius, sigma);
302     XCAM_ASSERT (kernel.ptr ());
303     XCAM_FAIL_RETURN (
304         ERROR, kernel->build_kernel (kernel_retinex_info[KernelGaussian], build_options) == XCAM_RETURN_NO_ERROR, NULL,
305         "build retinex gaussian kernel(%s) failed", kernel_retinex_info[KernelGaussian].kernel_name);
306 
307     XCAM_ASSERT (kernel->is_valid ());
308 
309     return kernel;
310 }
311 
312 static SmartPtr<CLRetinexImageKernel>
create_kernel_retinex(const SmartPtr<CLContext> & context,SmartPtr<CLRetinexImageHandler> handler)313 create_kernel_retinex (const SmartPtr<CLContext> &context, SmartPtr<CLRetinexImageHandler> handler)
314 {
315     SmartPtr<CLRetinexImageKernel> kernel;
316     char build_options[1024];
317 
318     xcam_mem_clear (build_options);
319     snprintf (build_options, sizeof (build_options), " -DRETINEX_SCALE_SIZE=%d ", XCAM_RETINEX_MAX_SCALE);
320 
321     kernel = new CLRetinexImageKernel (context, handler);
322     XCAM_ASSERT (kernel.ptr ());
323     XCAM_FAIL_RETURN (
324         ERROR, kernel->build_kernel (kernel_retinex_info[KernelRetinex], build_options) == XCAM_RETURN_NO_ERROR, NULL,
325         "build retinex kernel(%s) failed", kernel_retinex_info[KernelRetinex].kernel_name);
326 
327     XCAM_ASSERT (kernel->is_valid ());
328     return kernel;
329 }
330 
331 SmartPtr<CLImageHandler>
create_cl_retinex_image_handler(const SmartPtr<CLContext> & context)332 create_cl_retinex_image_handler (const SmartPtr<CLContext> &context)
333 {
334     SmartPtr<CLRetinexImageHandler> retinex_handler;
335 
336     SmartPtr<CLRetinexScalerImageKernel> retinex_scaler_kernel;
337     SmartPtr<CLRetinexImageKernel> retinex_kernel;
338 
339     retinex_handler = new CLRetinexImageHandler (context, "cl_handler_retinex");
340     retinex_scaler_kernel = create_kernel_retinex_scaler (context, retinex_handler);
341     XCAM_FAIL_RETURN (
342         ERROR,
343         retinex_scaler_kernel.ptr () && retinex_scaler_kernel->is_valid (),
344         NULL,
345         "Retinex handler create scaler kernel failed");
346     retinex_handler->set_retinex_scaler_kernel (retinex_scaler_kernel);
347 
348     for (uint32_t i = 0; i < XCAM_RETINEX_MAX_SCALE; ++i) {
349         SmartPtr<CLImageKernel> retinex_gauss_kernel;
350         retinex_gauss_kernel = create_kernel_retinex_gaussian (
351                                    context, retinex_handler, i, retinex_gauss_scale [i], retinex_gauss_sigma [i]);
352         XCAM_FAIL_RETURN (
353             ERROR,
354             retinex_gauss_kernel.ptr () && retinex_gauss_kernel->is_valid (),
355             NULL,
356             "Retinex handler create gaussian kernel failed");
357         retinex_handler->add_kernel (retinex_gauss_kernel);
358     }
359 
360     retinex_kernel = create_kernel_retinex (context, retinex_handler);
361     XCAM_FAIL_RETURN (
362         ERROR,
363         retinex_kernel.ptr () && retinex_kernel->is_valid (),
364         NULL,
365         "Retinex handler create retinex kernel failed");
366     retinex_handler->set_retinex_kernel (retinex_kernel);
367 
368     return retinex_handler;
369 }
370 
371 }
372