• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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