1 /*
2 * cl_3a_image_processor.cpp - CL 3A image processor
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 #include "cl_3a_image_processor.h"
21 #include "cl_context.h"
22 #include "cl_csc_handler.h"
23 #include "cl_bayer_pipe_handler.h"
24 #include "cl_yuv_pipe_handler.h"
25 #if ENABLE_YEENR_HANDLER
26 #include "cl_ee_handler.h"
27 #endif
28 #include "cl_tnr_handler.h"
29 #include "cl_tonemapping_handler.h"
30 #include "cl_newtonemapping_handler.h"
31 #include "cl_bayer_basic_handler.h"
32
33 #define XCAM_CL_3A_IMAGE_MAX_POOL_SIZE 6
34
35 namespace XCam {
36
CL3aImageProcessor()37 CL3aImageProcessor::CL3aImageProcessor ()
38 : CLImageProcessor ("CL3aImageProcessor")
39 , _output_fourcc (V4L2_PIX_FMT_NV12)
40 , _3a_stats_bits (8)
41 , _pipeline_profile (BasicPipelineProfile)
42 , _capture_stage (TonemappingStage)
43 , _wdr_mode (WDRdisabled)
44 , _tnr_mode (0)
45 , _enable_gamma (true)
46 , _enable_macc (true)
47 , _snr_mode (0)
48 {
49 keep_attached_buf (true);
50 XCAM_LOG_DEBUG ("CL3aImageProcessor constructed");
51 }
52
~CL3aImageProcessor()53 CL3aImageProcessor::~CL3aImageProcessor ()
54 {
55 XCAM_LOG_DEBUG ("CL3aImageProcessor destructed");
56 }
57
58 void
set_stats_callback(const SmartPtr<StatsCallback> & callback)59 CL3aImageProcessor::set_stats_callback (const SmartPtr<StatsCallback> &callback)
60 {
61 XCAM_ASSERT (callback.ptr ());
62 _stats_callback = callback;
63 }
64
65 bool
set_output_format(uint32_t fourcc)66 CL3aImageProcessor::set_output_format (uint32_t fourcc)
67 {
68 XCAM_FAIL_RETURN (
69 WARNING,
70 V4L2_PIX_FMT_NV12 == fourcc,
71 false,
72 "cl 3a processor doesn't support output format: %s",
73 xcam_fourcc_to_string (fourcc));
74
75 _output_fourcc = fourcc;
76 return true;
77 }
78
79 bool
set_capture_stage(CaptureStage capture_stage)80 CL3aImageProcessor::set_capture_stage (CaptureStage capture_stage)
81 {
82 _capture_stage = capture_stage;
83 return true;
84 }
85
86 bool
set_3a_stats_bits(uint32_t bits)87 CL3aImageProcessor::set_3a_stats_bits (uint32_t bits)
88 {
89 switch (bits) {
90 case 8:
91 case 12:
92 _3a_stats_bits = bits;
93 break;
94 default:
95 XCAM_LOG_WARNING ("cl image processor 3a stats doesn't support %d-bits", bits);
96 return false;
97 }
98 return true;
99 }
100
101 bool
can_process_result(SmartPtr<X3aResult> & result)102 CL3aImageProcessor::can_process_result (SmartPtr<X3aResult> &result)
103 {
104 if (result.ptr() == NULL)
105 return false;
106 switch (result->get_type ()) {
107 case XCAM_3A_RESULT_WHITE_BALANCE:
108 case XCAM_3A_RESULT_BLACK_LEVEL:
109 case XCAM_3A_RESULT_R_GAMMA:
110 case XCAM_3A_RESULT_G_GAMMA:
111 case XCAM_3A_RESULT_B_GAMMA:
112 case XCAM_3A_RESULT_RGB2YUV_MATRIX:
113 case XCAM_3A_RESULT_DEFECT_PIXEL_CORRECTION:
114 case XCAM_3A_RESULT_MACC:
115 case XCAM_3A_RESULT_BAYER_NOISE_REDUCTION:
116 case XCAM_3A_RESULT_BRIGHTNESS:
117 case XCAM_3A_RESULT_3D_NOISE_REDUCTION:
118 case XCAM_3A_RESULT_TEMPORAL_NOISE_REDUCTION_YUV:
119 case XCAM_3A_RESULT_EDGE_ENHANCEMENT:
120 return true;
121
122 default:
123 return false;
124 }
125
126 return false;
127 }
128
129 XCamReturn
apply_3a_results(X3aResultList & results)130 CL3aImageProcessor::apply_3a_results (X3aResultList &results)
131 {
132 XCamReturn ret = XCAM_RETURN_NO_ERROR;
133
134 for (X3aResultList::iterator iter = results.begin (); iter != results.end (); ++iter)
135 {
136 SmartPtr<X3aResult> &result = *iter;
137 ret = apply_3a_result (result);
138 if (ret != XCAM_RETURN_NO_ERROR)
139 break;
140 }
141 return ret;
142 }
143
144 XCamReturn
apply_3a_result(SmartPtr<X3aResult> & result)145 CL3aImageProcessor::apply_3a_result (SmartPtr<X3aResult> &result)
146 {
147 STREAM_LOCK;
148
149 if (result.ptr() == NULL)
150 return XCAM_RETURN_BYPASS;
151
152 uint32_t res_type = result->get_type ();
153
154 switch (res_type) {
155 case XCAM_3A_RESULT_WHITE_BALANCE: {
156 SmartPtr<X3aWhiteBalanceResult> wb_res = result.dynamic_cast_ptr<X3aWhiteBalanceResult> ();
157 XCAM_ASSERT (wb_res.ptr ());
158 if (_bayer_basic_pipe.ptr ()) {
159 _bayer_basic_pipe->set_wb_config (wb_res->get_standard_result ());
160 _bayer_basic_pipe->set_3a_result (result);
161 }
162 break;
163 }
164
165 case XCAM_3A_RESULT_BLACK_LEVEL: {
166 SmartPtr<X3aBlackLevelResult> bl_res = result.dynamic_cast_ptr<X3aBlackLevelResult> ();
167 XCAM_ASSERT (bl_res.ptr ());
168 if (_bayer_basic_pipe.ptr ()) {
169 _bayer_basic_pipe->set_blc_config (bl_res->get_standard_result ());
170 _bayer_basic_pipe->set_3a_result (result);
171 }
172 break;
173 }
174
175 case XCAM_3A_RESULT_DEFECT_PIXEL_CORRECTION: {
176 SmartPtr<X3aDefectPixelResult> def_res = result.dynamic_cast_ptr<X3aDefectPixelResult> ();
177 XCAM_ASSERT (def_res.ptr ());
178 XCAM_UNUSED (def_res);
179 break;
180 }
181
182 case XCAM_3A_RESULT_RGB2YUV_MATRIX: {
183 SmartPtr<X3aColorMatrixResult> csc_res = result.dynamic_cast_ptr<X3aColorMatrixResult> ();
184 XCAM_ASSERT (csc_res.ptr ());
185 if (_csc.ptr()) {
186 _csc->set_matrix (csc_res->get_standard_result ());
187 _csc->set_3a_result (result);
188 }
189 if (_yuv_pipe.ptr()) {
190 _yuv_pipe->set_rgbtoyuv_matrix (csc_res->get_standard_result ());
191 _yuv_pipe->set_3a_result (result);
192 }
193 break;
194 }
195
196 case XCAM_3A_RESULT_MACC: {
197 SmartPtr<X3aMaccMatrixResult> macc_res = result.dynamic_cast_ptr<X3aMaccMatrixResult> ();
198 XCAM_ASSERT (macc_res.ptr ());
199 if (_yuv_pipe.ptr()) {
200 _yuv_pipe->set_macc_table (macc_res->get_standard_result ());
201 _yuv_pipe->set_3a_result (result);
202 }
203 break;
204 }
205 case XCAM_3A_RESULT_R_GAMMA:
206 case XCAM_3A_RESULT_B_GAMMA:
207 break;
208
209 case XCAM_3A_RESULT_G_GAMMA:
210 case XCAM_3A_RESULT_Y_GAMMA: {
211 SmartPtr<X3aGammaTableResult> gamma_res = result.dynamic_cast_ptr<X3aGammaTableResult> ();
212 XCAM_ASSERT (gamma_res.ptr ());
213 if (_bayer_basic_pipe.ptr ()) {
214 _bayer_basic_pipe->set_gamma_table (gamma_res->get_standard_result ());
215 _bayer_basic_pipe->set_3a_result (result);
216 }
217 break;
218 }
219
220 case XCAM_3A_RESULT_3D_NOISE_REDUCTION: {
221 SmartPtr<X3aTemporalNoiseReduction> nr_res = result.dynamic_cast_ptr<X3aTemporalNoiseReduction> ();
222 XCAM_ASSERT (nr_res.ptr ());
223 XCAM_UNUSED (nr_res);
224
225 break;
226 }
227
228 case XCAM_3A_RESULT_TEMPORAL_NOISE_REDUCTION_YUV: {
229 SmartPtr<X3aTemporalNoiseReduction> tnr_res = result.dynamic_cast_ptr<X3aTemporalNoiseReduction> ();
230 XCAM_ASSERT (tnr_res.ptr ());
231 if (_yuv_pipe.ptr ()) {
232 _yuv_pipe->set_tnr_yuv_config(tnr_res->get_standard_result ());
233 _yuv_pipe->set_3a_result (result);
234 }
235 break;
236 }
237
238 case XCAM_3A_RESULT_EDGE_ENHANCEMENT: {
239 SmartPtr<X3aEdgeEnhancementResult> ee_ee_res = result.dynamic_cast_ptr<X3aEdgeEnhancementResult> ();
240 XCAM_ASSERT (ee_ee_res.ptr ());
241 if (_bayer_pipe.ptr()) {
242 _bayer_pipe->set_ee_config (ee_ee_res->get_standard_result ());
243 _bayer_pipe->set_3a_result (result);
244 }
245 #if ENABLE_YEENR_HANDLER
246 if (_ee.ptr()) {
247 _ee->set_ee_config_ee (ee_ee_res->get_standard_result ());
248 _ee->set_3a_result (result);
249 }
250 #endif
251 break;
252 }
253
254 case XCAM_3A_RESULT_BAYER_NOISE_REDUCTION: {
255 SmartPtr<X3aBayerNoiseReduction> bnr_res = result.dynamic_cast_ptr<X3aBayerNoiseReduction> ();
256 XCAM_ASSERT (bnr_res.ptr ());
257 if (_bayer_pipe.ptr()) {
258 _bayer_pipe->set_bnr_config (bnr_res->get_standard_result ());
259 _bayer_pipe->set_3a_result (result);
260 }
261
262 break;
263 }
264
265 case XCAM_3A_RESULT_BRIGHTNESS: {
266 SmartPtr<X3aBrightnessResult> brightness_res = result.dynamic_cast_ptr<X3aBrightnessResult> ();
267 XCAM_ASSERT (brightness_res.ptr ());
268 float brightness_level = ((XCam3aResultBrightness)brightness_res->get_standard_result()).brightness_level;
269 XCAM_UNUSED (brightness_level);
270 break;
271 }
272
273 default:
274 XCAM_LOG_WARNING ("CL3aImageProcessor unknown 3a result:%d", res_type);
275 break;
276 }
277
278 return XCAM_RETURN_NO_ERROR;
279 }
280
281 XCamReturn
create_handlers()282 CL3aImageProcessor::create_handlers ()
283 {
284 SmartPtr<CLImageHandler> image_handler;
285 SmartPtr<CLContext> context = get_cl_context ();
286
287 XCAM_ASSERT (context.ptr ());
288
289 /* bayer pipeline */
290 image_handler = create_cl_bayer_basic_image_handler (context, _enable_gamma, _3a_stats_bits);
291 _bayer_basic_pipe = image_handler.dynamic_cast_ptr<CLBayerBasicImageHandler> ();
292 XCAM_FAIL_RETURN (
293 WARNING,
294 _bayer_basic_pipe.ptr (),
295 XCAM_RETURN_ERROR_CL,
296 "CL3aImageProcessor create bayer basic pipe handler failed");
297 image_handler->set_pool_size (XCAM_CL_3A_IMAGE_MAX_POOL_SIZE);
298 _bayer_basic_pipe->set_stats_callback (_stats_callback);
299 add_handler (image_handler);
300
301 /* tone mapping */
302 switch(_wdr_mode) {
303 case Gaussian: {
304 image_handler = create_cl_tonemapping_image_handler (context);
305 _tonemapping = image_handler.dynamic_cast_ptr<CLTonemappingImageHandler> ();
306 XCAM_FAIL_RETURN (
307 WARNING,
308 _tonemapping.ptr (),
309 XCAM_RETURN_ERROR_CL,
310 "CL3aImageProcessor create tonemapping handler failed");
311 _tonemapping->enable_handler (true);
312 image_handler->set_pool_size (XCAM_CL_3A_IMAGE_MAX_POOL_SIZE);
313 add_handler (image_handler);
314 break;
315 }
316 case Haleq: {
317 image_handler = create_cl_newtonemapping_image_handler (context);
318 _newtonemapping = image_handler.dynamic_cast_ptr<CLNewTonemappingImageHandler> ();
319 XCAM_FAIL_RETURN (
320 WARNING,
321 _newtonemapping.ptr (),
322 XCAM_RETURN_ERROR_CL,
323 "CL3aImageProcessor create tonemapping handler failed");
324 _newtonemapping->enable_handler (true);
325 image_handler->set_pool_size (XCAM_CL_3A_IMAGE_MAX_POOL_SIZE);
326 add_handler (image_handler);
327 break;
328 }
329 default:
330 XCAM_LOG_DEBUG ("WDR disabled");
331 break;
332 }
333
334 /* bayer pipe */
335 image_handler = create_cl_bayer_pipe_image_handler (context);
336 _bayer_pipe = image_handler.dynamic_cast_ptr<CLBayerPipeImageHandler> ();
337 XCAM_FAIL_RETURN (
338 WARNING,
339 image_handler.ptr (),
340 XCAM_RETURN_ERROR_CL,
341 "CL3aImageProcessor create bayer pipe handler failed");
342
343 _bayer_pipe->enable_denoise (XCAM_DENOISE_TYPE_BNR & _snr_mode);
344 image_handler->set_pool_size (XCAM_CL_3A_IMAGE_MAX_POOL_SIZE * 2);
345 add_handler (image_handler);
346 if(_capture_stage == BasicbayerStage)
347 return XCAM_RETURN_NO_ERROR;
348
349 image_handler = create_cl_yuv_pipe_image_handler (context);
350 _yuv_pipe = image_handler.dynamic_cast_ptr<CLYuvPipeImageHandler> ();
351 XCAM_FAIL_RETURN (
352 WARNING,
353 _yuv_pipe.ptr (),
354 XCAM_RETURN_ERROR_CL,
355 "CL3aImageProcessor create yuv pipe handler failed");
356 _yuv_pipe->set_tnr_enable (_tnr_mode & CL_TNR_TYPE_YUV);
357 image_handler->set_pool_size (XCAM_CL_3A_IMAGE_MAX_POOL_SIZE * 2);
358 add_handler (image_handler);
359
360 #if ENABLE_YEENR_HANDLER
361 /* ee */
362 image_handler = create_cl_ee_image_handler (context);
363 _ee = image_handler.dynamic_cast_ptr<CLEeImageHandler> ();
364 XCAM_FAIL_RETURN (
365 WARNING,
366 _ee.ptr (),
367 XCAM_RETURN_ERROR_CL,
368 "CL3aImageProcessor create ee handler failed");
369 _ee->enable_handler (XCAM_DENOISE_TYPE_EE & _snr_mode);
370 image_handler->set_pool_type (CLImageHandler::CLVideoPoolType);
371 image_handler->set_pool_size (XCAM_CL_3A_IMAGE_MAX_POOL_SIZE);
372 add_handler (image_handler);
373 #endif
374
375 XCAM_FAIL_RETURN (
376 WARNING,
377 post_config (),
378 XCAM_RETURN_ERROR_CL,
379 "CL3aImageProcessor post_config failed");
380
381 return XCAM_RETURN_NO_ERROR;
382 }
383
384 bool
post_config()385 CL3aImageProcessor::post_config ()
386 {
387 CLImageProcessor::ImageHandlerList::iterator i_handler = handlers_begin ();
388 CLImageProcessor::ImageHandlerList::iterator end = handlers_end ();
389 uint32_t swap_y_count = 0;
390 bool start_count = false;
391 bool ret = true;
392
393 if (!_yuv_pipe.ptr ()) //not necessary to check
394 return true;
395
396 for (; i_handler != end; ++i_handler) {
397 if (!start_count) {
398 SmartPtr<CLYuvPipeImageHandler> convert_yuv = (*i_handler).dynamic_cast_ptr<CLYuvPipeImageHandler> ();
399 if (convert_yuv.ptr () && convert_yuv.ptr () == _yuv_pipe.ptr ())
400 start_count = true;
401 continue;
402 }
403
404 SmartPtr<CLCloneImageHandler> clone_y = (*i_handler).dynamic_cast_ptr<CLCloneImageHandler> ();
405 if (clone_y.ptr () && clone_y->is_handler_enabled () && (clone_y->get_clone_flags () & SwappedBuffer::SwapY))
406 swap_y_count++;
407 }
408
409 if (swap_y_count % 2 == 1)
410 ret = _yuv_pipe->enable_buf_pool_swap_flags (SwappedBuffer::SwapY | SwappedBuffer::SwapUV, SwappedBuffer::OrderY1Y0 | SwappedBuffer::OrderUV0UV1);
411 else
412 ret = _yuv_pipe->enable_buf_pool_swap_flags (SwappedBuffer::SwapY | SwappedBuffer::SwapUV, SwappedBuffer::OrderY0Y1 | SwappedBuffer::OrderUV0UV1);
413
414 return ret;
415 }
416
417 bool
set_profile(const CL3aImageProcessor::PipelineProfile value)418 CL3aImageProcessor::set_profile (const CL3aImageProcessor::PipelineProfile value)
419 {
420 _pipeline_profile = value;
421
422 if (value >= AdvancedPipelineProfile)
423 _tnr_mode |= CL_TNR_TYPE_YUV;
424
425 if (value >= ExtremePipelineProfile) {
426 _snr_mode |= XCAM_DENOISE_TYPE_BNR;
427 }
428 STREAM_LOCK;
429 if (_yuv_pipe.ptr ())
430 _yuv_pipe->set_tnr_enable (_tnr_mode & CL_TNR_TYPE_YUV);
431
432 return true;
433 }
434
435 bool
set_gamma(bool enable)436 CL3aImageProcessor::set_gamma (bool enable)
437 {
438 _enable_gamma = enable;
439
440 STREAM_LOCK;
441
442 return true;
443 }
444
445 bool
set_denoise(uint32_t mode)446 CL3aImageProcessor::set_denoise (uint32_t mode)
447 {
448 _snr_mode = mode;
449
450 STREAM_LOCK;
451 if (_bayer_pipe.ptr ())
452 _bayer_pipe->enable_denoise (XCAM_DENOISE_TYPE_BNR & _snr_mode);
453
454 return true;
455 }
456
457 bool
set_macc(bool enable)458 CL3aImageProcessor::set_macc (bool enable)
459 {
460 _enable_macc = enable;
461
462 STREAM_LOCK;
463 return true;
464 }
465
466 bool
set_tonemapping(CLTonemappingMode wdr_mode)467 CL3aImageProcessor::set_tonemapping (CLTonemappingMode wdr_mode)
468 {
469 _wdr_mode = wdr_mode;
470
471 STREAM_LOCK;
472
473 return true;
474 }
475
476 bool
set_tnr(uint32_t mode,uint8_t level)477 CL3aImageProcessor::set_tnr (uint32_t mode, uint8_t level)
478 {
479 XCAM_UNUSED (level);
480 _tnr_mode = mode;
481
482 STREAM_LOCK;
483 if (_yuv_pipe.ptr ())
484 _yuv_pipe->set_tnr_enable (_tnr_mode & CL_TNR_TYPE_YUV);
485
486 return true;
487 }
488
489 };
490