1 /*
2 * cl_bayer_basic_handler.cpp - CL bayer basic 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: Wind Yuan <feng.yuan@intel.com>
19 */
20
21 #include "cl_utils.h"
22 #include "cl_bayer_basic_handler.h"
23 #include "xcam_thread.h"
24
25 #define GROUP_CELL_X_SIZE 64
26 #define GROUP_CELL_Y_SIZE 4
27
28 #define STATS_3A_CELL_X_SIZE 8
29 #define STATS_3A_CELL_Y_SIZE GROUP_CELL_Y_SIZE
30
31 #define STANDARD_3A_STATS_SIZE 8
32
33 #define ENABLE_IMAGE_2D_INPUT 0
34
35 namespace XCam {
36
37 static const XCamKernelInfo kernel_bayer_basic_info = {
38 "kernel_bayer_basic",
39 #include "kernel_bayer_basic.clx"
40 , 0,
41 };
42
43 struct BayerPostData {
44 SmartPtr<VideoBuffer> image_buffer;
45 SmartPtr<CLBuffer> stats_cl_buf;
46 };
47
48 class CLBayer3AStatsThread
49 : public Thread
50 {
51 public:
CLBayer3AStatsThread(CLBayerBasicImageHandler * handler)52 CLBayer3AStatsThread (CLBayerBasicImageHandler *handler)
53 : Thread ("CLBayer3AStatsThread")
54 , _handler (handler)
55 {}
~CLBayer3AStatsThread()56 ~CLBayer3AStatsThread () {}
57
58 virtual bool emit_stop ();
59 bool queue_stats (SmartPtr<VideoBuffer> &buf, SmartPtr<CLBuffer> &stats);
60 SmartPtr<VideoBuffer> pop_buf ();
61 protected:
62 virtual bool loop ();
63 virtual void stopped ();
64
65 private:
66 CLBayerBasicImageHandler *_handler;
67 SafeList<BayerPostData> _stats_process_list;
68 SafeList<VideoBuffer> _buffer_done_list;
69 };
70
71 bool
emit_stop()72 CLBayer3AStatsThread::emit_stop ()
73 {
74 _stats_process_list.pause_pop ();
75 _buffer_done_list.pause_pop ();
76
77 _stats_process_list.wakeup ();
78 _buffer_done_list.wakeup ();
79
80 return Thread::emit_stop ();
81 }
82
83 bool
queue_stats(SmartPtr<VideoBuffer> & buf,SmartPtr<CLBuffer> & stats)84 CLBayer3AStatsThread::queue_stats (SmartPtr<VideoBuffer> &buf, SmartPtr<CLBuffer> &stats)
85 {
86 XCAM_FAIL_RETURN (
87 WARNING,
88 buf.ptr () && stats.ptr (),
89 false,
90 "cl bayer 3a-stats thread has error buffer/stats to queue");
91
92 SmartPtr<BayerPostData> data = new BayerPostData;
93 XCAM_ASSERT (data.ptr ());
94 data->image_buffer = buf;
95 data->stats_cl_buf = stats;
96
97 return _stats_process_list.push (data);
98 }
99
100 SmartPtr<VideoBuffer>
pop_buf()101 CLBayer3AStatsThread::pop_buf ()
102 {
103 return _buffer_done_list.pop ();
104 }
105
106 void
stopped()107 CLBayer3AStatsThread::stopped ()
108 {
109 _stats_process_list.clear ();
110 _buffer_done_list.clear ();
111 }
112
113 bool
loop()114 CLBayer3AStatsThread::loop ()
115 {
116 XCamReturn ret = XCAM_RETURN_NO_ERROR;
117 SmartPtr<BayerPostData> data;
118 data = _stats_process_list.pop ();
119 if (!data.ptr ()) {
120 XCAM_LOG_INFO ("cl bayer 3a-stats thread is going to stop, processing data empty");
121 return false;
122 }
123
124 XCAM_ASSERT (data->image_buffer.ptr ());
125 XCAM_ASSERT (data->stats_cl_buf.ptr ());
126 XCAM_ASSERT (_handler);
127
128 ret = _handler->process_stats_buffer (data->image_buffer, data->stats_cl_buf);
129 XCAM_FAIL_RETURN (
130 WARNING,
131 ret == XCAM_RETURN_NO_ERROR,
132 false,
133 "cl bayer 3a-stats thread has error buffer on kernel post processing");
134
135 XCAM_FAIL_RETURN (
136 ERROR,
137 _buffer_done_list.push (data->image_buffer),
138 false,
139 "cl bayer 3a-stats thread failed to queue done-buffers");
140 return true;
141 }
142
CLBayerBasicImageKernel(const SmartPtr<CLContext> & context)143 CLBayerBasicImageKernel::CLBayerBasicImageKernel (const SmartPtr<CLContext> &context)
144 : CLImageKernel (context, "kernel_bayer_basic")
145 {
146 }
147
148 XCamReturn
process_stats_buffer(SmartPtr<VideoBuffer> & buffer,SmartPtr<CLBuffer> & cl_stats)149 CLBayerBasicImageHandler::process_stats_buffer (SmartPtr<VideoBuffer> &buffer, SmartPtr<CLBuffer> &cl_stats)
150 {
151 SmartPtr<X3aStats> stats_3a;
152 SmartPtr<CLContext> context = get_context ();
153
154 XCAM_OBJ_PROFILING_START;
155
156 context->finish ();
157 stats_3a = _3a_stats_context->copy_stats_out (cl_stats);
158 if (!stats_3a.ptr ()) {
159 XCAM_LOG_DEBUG ("copy 3a stats failed, maybe handler stopped");
160 return XCAM_RETURN_ERROR_CL;
161 }
162
163 stats_3a->set_timestamp (buffer->get_timestamp ());
164 buffer->attach_buffer (stats_3a);
165
166 if (cl_stats.ptr ())
167 _3a_stats_context->release_buffer (cl_stats);
168
169 XCAM_OBJ_PROFILING_END ("3a_stats_cpu_copy(async)", XCAM_OBJ_DUR_FRAME_NUM);
170
171 return post_stats (stats_3a);
172 }
173
CLBayerBasicImageHandler(const SmartPtr<CLContext> & context,const char * name)174 CLBayerBasicImageHandler::CLBayerBasicImageHandler (
175 const SmartPtr<CLContext> &context, const char *name)
176 : CLImageHandler (context, name)
177 , _is_first_buf (true)
178 {
179 _blc_config.level_gr = XCAM_CL_BLC_DEFAULT_LEVEL;
180 _blc_config.level_r = XCAM_CL_BLC_DEFAULT_LEVEL;
181 _blc_config.level_b = XCAM_CL_BLC_DEFAULT_LEVEL;
182 _blc_config.level_gb = XCAM_CL_BLC_DEFAULT_LEVEL;
183 _blc_config.color_bits = 10;
184
185 _wb_config.r_gain = 1.0;
186 _wb_config.gr_gain = 1.0;
187 _wb_config.gb_gain = 1.0;
188 _wb_config.b_gain = 1.0;
189
190 for(int i = 0; i < XCAM_GAMMA_TABLE_SIZE; i++)
191 _gamma_table[i] = (float)i / 256.0f;
192 _gamma_table[XCAM_GAMMA_TABLE_SIZE] = 0.9999f;
193
194 _3a_stats_context = new CL3AStatsCalculatorContext (context);
195 XCAM_ASSERT (_3a_stats_context.ptr ());
196 _3a_stats_thread = new CLBayer3AStatsThread (this);
197 XCAM_ASSERT (_3a_stats_thread.ptr ());
198
199 XCAM_OBJ_PROFILING_INIT;
200 }
201
~CLBayerBasicImageHandler()202 CLBayerBasicImageHandler::~CLBayerBasicImageHandler ()
203 {
204 _3a_stats_thread->stop ();
205 _3a_stats_context->clean_up_data ();
206 }
207
208 void
set_stats_bits(uint32_t stats_bits)209 CLBayerBasicImageHandler::set_stats_bits (uint32_t stats_bits)
210 {
211 XCAM_ASSERT (_3a_stats_context.ptr ());
212 _3a_stats_context->set_bit_depth (stats_bits);
213 }
214
215 bool
set_bayer_kernel(SmartPtr<CLBayerBasicImageKernel> & kernel)216 CLBayerBasicImageHandler::set_bayer_kernel (SmartPtr<CLBayerBasicImageKernel> &kernel)
217 {
218 SmartPtr<CLImageKernel> image_kernel = kernel;
219 add_kernel (image_kernel);
220 _bayer_kernel = kernel;
221 return true;
222 }
223
224 bool
set_blc_config(const XCam3aResultBlackLevel & blc)225 CLBayerBasicImageHandler::set_blc_config (const XCam3aResultBlackLevel &blc)
226 {
227 _blc_config.level_r = (float)blc.r_level;
228 _blc_config.level_gr = (float)blc.gr_level;
229 _blc_config.level_gb = (float)blc.gb_level;
230 _blc_config.level_b = (float)blc.b_level;
231 //_blc_config.color_bits = 0;
232 return true;
233 }
234
235 bool
set_wb_config(const XCam3aResultWhiteBalance & wb)236 CLBayerBasicImageHandler::set_wb_config (const XCam3aResultWhiteBalance &wb)
237 {
238 _wb_config.r_gain = (float)wb.r_gain;
239 _wb_config.gr_gain = (float)wb.gr_gain;
240 _wb_config.gb_gain = (float)wb.gb_gain;
241 _wb_config.b_gain = (float)wb.b_gain;
242 return true;
243 }
244
245 bool
set_gamma_table(const XCam3aResultGammaTable & gamma)246 CLBayerBasicImageHandler::set_gamma_table (const XCam3aResultGammaTable &gamma)
247 {
248 for(int i = 0; i < XCAM_GAMMA_TABLE_SIZE; i++)
249 _gamma_table[i] = (float)gamma.table[i] / 256.0f;
250
251 return true;
252 }
253
254 void
emit_stop()255 CLBayerBasicImageHandler::emit_stop ()
256 {
257 _3a_stats_context->pre_stop ();
258 _3a_stats_thread->emit_stop ();
259 }
260
261 XCamReturn
prepare_buffer_pool_video_info(const VideoBufferInfo & input,VideoBufferInfo & output)262 CLBayerBasicImageHandler::prepare_buffer_pool_video_info (
263 const VideoBufferInfo &input,
264 VideoBufferInfo &output)
265 {
266 uint32_t format = XCAM_PIX_FMT_SGRBG16_planar;
267 bool format_inited = output.init (format, input.width / 2 , input.height / 2);
268
269 XCAM_FAIL_RETURN (
270 WARNING,
271 format_inited,
272 XCAM_RETURN_ERROR_PARAM,
273 "CL image handler(%s) output format(%s) unsupported",
274 get_name (), xcam_fourcc_to_string (format));
275
276 return XCAM_RETURN_NO_ERROR;
277 }
278
279 XCamReturn
prepare_parameters(SmartPtr<VideoBuffer> & input,SmartPtr<VideoBuffer> & output)280 CLBayerBasicImageHandler::prepare_parameters (
281 SmartPtr<VideoBuffer> &input, SmartPtr<VideoBuffer> &output)
282 {
283 SmartPtr<CLContext> context = get_context ();
284 const VideoBufferInfo & in_video_info = input->get_video_info ();
285 const VideoBufferInfo & out_video_info = output->get_video_info ();
286 CLImageDesc in_image_info;
287 CLImageDesc out_image_info;
288 CLArgList args;
289 CLWorkSize work_size;
290
291 XCAM_ASSERT (_bayer_kernel.ptr ());
292
293 if (!_3a_stats_context->is_ready () &&
294 !_3a_stats_context->allocate_data (
295 in_video_info,
296 STANDARD_3A_STATS_SIZE / STATS_3A_CELL_X_SIZE,
297 STANDARD_3A_STATS_SIZE / STATS_3A_CELL_Y_SIZE)) {
298 XCAM_LOG_WARNING ("CL3AStatsCalculatorContext allocate data failed");
299 return XCAM_RETURN_ERROR_MEM;
300 }
301
302 if (_is_first_buf) {
303 XCAM_FAIL_RETURN (
304 WARNING, _3a_stats_thread->start (), XCAM_RETURN_ERROR_THREAD,
305 "cl bayer basic handler start 3a stats thread failed");
306 }
307
308 in_image_info.format.image_channel_order = CL_RGBA;
309 in_image_info.format.image_channel_data_type = CL_UNSIGNED_INT32; //CL_UNORM_INT16;
310 in_image_info.width = in_video_info.aligned_width / 8;
311 in_image_info.height = in_video_info.height;
312 in_image_info.row_pitch = in_video_info.strides[0];
313
314 out_image_info.format.image_channel_order = CL_RGBA;
315 out_image_info.format.image_channel_data_type = CL_UNSIGNED_INT32; //CL_UNORM_INT16;
316 out_image_info.width = out_video_info.width / 8;
317 out_image_info.height = out_video_info.aligned_height * 4;
318 out_image_info.row_pitch = out_video_info.strides[0];
319
320 #if ENABLE_IMAGE_2D_INPUT
321 SmartPtr<CLImage> image_in = convert_to_climage (context, input, in_image_info);
322 #else
323 SmartPtr<CLBuffer> buffer_in = convert_to_clbuffer (context, input);
324 #endif
325 uint32_t input_aligned_width = in_video_info.strides[0] / (2 * 8); // ushort8
326 SmartPtr<CLImage> image_out = convert_to_climage (context, output, out_image_info);
327
328 uint32_t out_aligned_height = out_video_info.aligned_height;
329 _blc_config.color_bits = in_video_info.color_bits;
330
331 SmartPtr<CLBuffer> gamma_table_buffer = new CLBuffer(
332 context, sizeof(float) * (XCAM_GAMMA_TABLE_SIZE + 1),
333 CL_MEM_READ_WRITE | CL_MEM_USE_HOST_PTR, &_gamma_table);
334
335 _stats_cl_buffer = _3a_stats_context->get_buffer ();
336 XCAM_FAIL_RETURN (
337 WARNING,
338 _stats_cl_buffer.ptr () && _stats_cl_buffer->is_valid (),
339 XCAM_RETURN_ERROR_PARAM,
340 "CLBayerBasic handler get 3a stats buffer failed");
341
342 XCAM_FAIL_RETURN (
343 WARNING,
344 image_out->is_valid (),
345 XCAM_RETURN_ERROR_MEM,
346 "cl image handler(%s) out memory not available", XCAM_STR(get_name ()));
347
348 //set args;
349 #if ENABLE_IMAGE_2D_INPUT
350 args.push_back (new CLMemArgument (image_in));
351 #else
352 args.push_back (new CLMemArgument (buffer_in));
353 #endif
354 args.push_back (new CLArgumentT<uint32_t> (input_aligned_width));
355 args.push_back (new CLMemArgument (image_out));
356 args.push_back (new CLArgumentT<uint32_t> (out_aligned_height));
357 args.push_back (new CLArgumentT<CLBLCConfig> (_blc_config));
358 args.push_back (new CLArgumentT<CLWBConfig> (_wb_config));
359 args.push_back (new CLMemArgument (gamma_table_buffer));
360 args.push_back (new CLMemArgument (_stats_cl_buffer));
361
362 work_size.dim = XCAM_DEFAULT_IMAGE_DIM;
363 work_size.local[0] = 16;
364 work_size.local[1] = 2;
365 work_size.global[0] = XCAM_ALIGN_UP(out_video_info.width, GROUP_CELL_X_SIZE) / GROUP_CELL_X_SIZE * work_size.local[0];
366 work_size.global[1] = XCAM_ALIGN_UP(out_video_info.aligned_height, GROUP_CELL_Y_SIZE) / GROUP_CELL_Y_SIZE * work_size.local[1];
367
368 //printf ("work_size:g(%d, %d), l(%d, %d)\n", work_size.global[0], work_size.global[1], work_size.local[0], work_size.local[1]);
369 XCAM_ASSERT (_bayer_kernel.ptr ());
370 XCamReturn ret = _bayer_kernel->set_arguments (args, work_size);
371 XCAM_FAIL_RETURN (
372 WARNING, ret == XCAM_RETURN_NO_ERROR, ret,
373 "bayer basic kernel set arguments failed.");
374
375 return XCAM_RETURN_NO_ERROR;
376 }
377
378 XCamReturn
execute_done(SmartPtr<VideoBuffer> & output)379 CLBayerBasicImageHandler::execute_done (SmartPtr<VideoBuffer> &output)
380 {
381 XCAM_FAIL_RETURN (
382 ERROR, _3a_stats_thread->queue_stats (output, _stats_cl_buffer), XCAM_RETURN_ERROR_UNKNOWN,
383 "cl bayer basic handler(%s) process 3a stats failed", XCAM_STR (get_name ()));
384
385 _stats_cl_buffer.release ();
386
387 if (_is_first_buf) {
388 _is_first_buf = false;
389 return XCAM_RETURN_BYPASS;
390 }
391
392 SmartPtr<VideoBuffer> done_buf = _3a_stats_thread->pop_buf ();
393 XCAM_FAIL_RETURN (
394 WARNING,
395 done_buf.ptr (),
396 XCAM_RETURN_ERROR_MEM,
397 "cl bayer handler(%s) failed to get done buffer", get_name ());
398 output = done_buf;
399
400 return XCAM_RETURN_NO_ERROR;
401 }
402
403
404 XCamReturn
post_stats(const SmartPtr<X3aStats> & stats)405 CLBayerBasicImageHandler::post_stats (const SmartPtr<X3aStats> &stats)
406 {
407 if (_stats_callback.ptr ())
408 return _stats_callback->x3a_stats_ready (stats);
409
410 return XCAM_RETURN_NO_ERROR;
411 }
412
413
414 SmartPtr<CLImageHandler>
create_cl_bayer_basic_image_handler(const SmartPtr<CLContext> & context,bool enable_gamma,uint32_t stats_bits)415 create_cl_bayer_basic_image_handler (const SmartPtr<CLContext> &context, bool enable_gamma, uint32_t stats_bits)
416 {
417 SmartPtr<CLBayerBasicImageHandler> bayer_planar_handler;
418 SmartPtr<CLBayerBasicImageKernel> basic_kernel;
419 char build_options[1024];
420
421 bayer_planar_handler = new CLBayerBasicImageHandler (context, "cl_handler_bayer_basic");
422 bayer_planar_handler->set_stats_bits (stats_bits);
423 basic_kernel = new CLBayerBasicImageKernel (context);
424 XCAM_ASSERT (basic_kernel.ptr ());
425
426 xcam_mem_clear (build_options);
427 snprintf (build_options, sizeof (build_options),
428 " -DENABLE_GAMMA=%d "
429 " -DENABLE_IMAGE_2D_INPUT=%d "
430 " -DSTATS_BITS=%d ",
431 (enable_gamma ? 1 : 0),
432 ENABLE_IMAGE_2D_INPUT,
433 stats_bits);
434 XCAM_FAIL_RETURN (
435 ERROR, basic_kernel->build_kernel (kernel_bayer_basic_info, build_options) == XCAM_RETURN_NO_ERROR, NULL,
436 "build bayer-basic kernel(%s) failed", kernel_bayer_basic_info.kernel_name);
437
438 XCAM_ASSERT (basic_kernel->is_valid ());
439 bayer_planar_handler->set_bayer_kernel (basic_kernel);
440
441 return bayer_planar_handler;
442 }
443
444 };
445