1 /*
2  * aiq_handler.cpp - AIQ handler
3  *
4  *  Copyright (c) 2012-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  * Author: Yan Zhang <yan.y.zhang@intel.com>
20  */
21 
22 #include "aiq_handler.h"
23 #include "x3a_isp_config.h"
24 
25 #include <string.h>
26 #include <math.h>
27 
28 #include "ia_isp_2_2.h"
29 
30 #define MAX_STATISTICS_WIDTH 150
31 #define MAX_STATISTICS_HEIGHT 150
32 
33 //#define USE_RGBS_GRID_WEIGHTING
34 #define USE_HIST_GRID_WEIGHTING
35 
36 namespace XCam {
37 
38 struct IspInputParameters {
39     ia_aiq_frame_use            frame_use;
40     ia_aiq_frame_params        *sensor_frame_params;
41     ia_aiq_exposure_parameters *exposure_results;
42     ia_aiq_awb_results         *awb_results;
43     ia_aiq_gbce_results        *gbce_results;
44     ia_aiq_pa_results          *pa_results;
45 #ifdef HAVE_AIQ_2_7
46     ia_aiq_sa_results          *sa_results;
47 #endif
48     int8_t                      manual_brightness;
49     int8_t                      manual_contrast;
50     int8_t                      manual_hue;
51     int8_t                      manual_saturation;
52     int8_t                      manual_sharpness;
53     int8_t                      manual_nr_level;
54     ia_isp_effect               effects;
55 
IspInputParametersXCam::IspInputParameters56     IspInputParameters ()
57         : frame_use (ia_aiq_frame_use_preview)
58         , sensor_frame_params (NULL)
59         , exposure_results (NULL)
60         , awb_results (NULL)
61         , gbce_results (NULL)
62         , pa_results (NULL)
63 #ifdef HAVE_AIQ_2_7
64         , sa_results (NULL)
65 #endif
66         , manual_brightness (0)
67         , manual_contrast (0)
68         , manual_hue (0)
69         , manual_saturation (0)
70         , manual_sharpness (0)
71         , manual_nr_level (0)
72         , effects (ia_isp_effect_none)
73     {}
74 };
75 
76 class IaIspAdaptor22
77     : public IaIspAdaptor
78 {
79 public:
IaIspAdaptor22()80     IaIspAdaptor22 () {
81         xcam_mem_clear (_input_params);
82     }
~IaIspAdaptor22()83     ~IaIspAdaptor22 () {
84         if (_handle)
85             ia_isp_2_2_deinit (_handle);
86     }
87 
88     virtual bool init (
89         const ia_binary_data *cpf,
90         unsigned int max_width,
91         unsigned int max_height,
92         ia_cmc_t *cmc,
93         ia_mkn *mkn);
94 
95     virtual bool convert_statistics (
96         void *statistics,
97         ia_aiq_rgbs_grid **out_rgbs_grid,
98         ia_aiq_af_grid **out_af_grid);
99 
100     virtual bool run (
101         const IspInputParameters *isp_input_params,
102         ia_binary_data *output_data);
103 
104 private:
105     ia_isp_2_2_input_params  _input_params;
106 
107 };
108 
109 bool
init(const ia_binary_data * cpf,unsigned int max_width,unsigned int max_height,ia_cmc_t * cmc,ia_mkn * mkn)110 IaIspAdaptor22::init (
111     const ia_binary_data *cpf,
112     unsigned int max_width,
113     unsigned int max_height,
114     ia_cmc_t *cmc,
115     ia_mkn *mkn)
116 {
117     xcam_mem_clear (_input_params);
118     _input_params.isp_vamem_type = 1;
119     _handle = ia_isp_2_2_init (cpf, max_width, max_height, cmc, mkn);
120     XCAM_FAIL_RETURN (ERROR, _handle, false, "ia_isp 2.2 init failed");
121     return true;
122 }
123 
124 bool
convert_statistics(void * statistics,ia_aiq_rgbs_grid ** out_rgbs_grid,ia_aiq_af_grid ** out_af_grid)125 IaIspAdaptor22::convert_statistics (
126     void *statistics,
127     ia_aiq_rgbs_grid **out_rgbs_grid,
128     ia_aiq_af_grid **out_af_grid)
129 {
130     ia_err err;
131     err = ia_isp_2_2_statistics_convert (_handle, statistics, out_rgbs_grid, out_af_grid);
132     XCAM_FAIL_RETURN (ERROR, err == ia_err_none, false, "ia_isp 2.2 convert stats failed");
133     return true;
134 }
135 
136 bool
run(const IspInputParameters * isp_input_params,ia_binary_data * output_data)137 IaIspAdaptor22::run (
138     const IspInputParameters *isp_input_params,
139     ia_binary_data *output_data)
140 {
141     ia_err err;
142 
143     _input_params.frame_use = isp_input_params->frame_use;
144     _input_params.sensor_frame_params = isp_input_params->sensor_frame_params;
145     _input_params.exposure_results = isp_input_params->exposure_results;
146     _input_params.awb_results = isp_input_params->awb_results;
147     _input_params.gbce_results = isp_input_params->gbce_results;
148     _input_params.pa_results = isp_input_params->pa_results;
149 #ifdef HAVE_AIQ_2_7
150     _input_params.sa_results = isp_input_params->sa_results;
151 #endif
152     _input_params.manual_brightness = isp_input_params->manual_brightness;
153     _input_params.manual_contrast = isp_input_params->manual_contrast;
154     _input_params.manual_hue = isp_input_params->manual_hue;
155     _input_params.manual_saturation = isp_input_params->manual_saturation;
156     _input_params.nr_setting.feature_level = ia_isp_feature_level_high;
157     _input_params.nr_setting.strength = isp_input_params->manual_nr_level;
158     _input_params.ee_setting.feature_level = ia_isp_feature_level_high;
159     _input_params.ee_setting.strength = isp_input_params->manual_sharpness;
160     _input_params.effects = isp_input_params->effects;
161 
162     err = ia_isp_2_2_run (_handle, &_input_params, output_data);
163     XCAM_FAIL_RETURN (ERROR, err == ia_err_none, false, "ia_isp 2.2 run failed");
164     return true;
165 }
166 
167 #if 0
168 
169 class IaIspAdaptor15
170     : public IaIspAdaptor
171 {
172 public:
173     IaIspAdaptor15 () {
174         xcam_mem_clear (&_input_params);
175     }
176     ~IaIspAdaptor15 () {
177         if (_handle)
178             ia_isp_1_5_deinit (_handle);
179     }
180     virtual bool init (
181         const ia_binary_data *cpf,
182         unsigned int max_width,
183         unsigned int max_height,
184         ia_cmc_t *cmc,
185         ia_mkn *mkn);
186     virtual bool convert_statistics (
187         void *statistics,
188         ia_aiq_rgbs_grid **out_rgbs_grid,
189         ia_aiq_af_grid **out_af_grid);
190     virtual bool run (
191         const IspInputParameters *isp_input_params,
192         ia_binary_data *output_data);
193 
194 private:
195     ia_isp_1_5_input_params  _input_params;
196 
197 };
198 
199 bool
200 IaIspAdaptor15::init (
201     const ia_binary_data *cpf,
202     unsigned int max_width,
203     unsigned int max_height,
204     ia_cmc_t *cmc,
205     ia_mkn *mkn)
206 {
207     xcam_mem_clear (&_input_params);
208     _input_params.isp_vamem_type = 1;
209     _handle = ia_isp_1_5_init (cpf, max_width, max_height, cmc, mkn);
210     XCAM_FAIL_RETURN (ERROR, _handle, false, "ia_isp 1.5 init failed");
211     return true;
212 }
213 
214 bool
215 IaIspAdaptor15::convert_statistics (
216     void *statistics,
217     ia_aiq_rgbs_grid **out_rgbs_grid,
218     ia_aiq_af_grid **out_af_grid)
219 {
220     ia_err err;
221     err = ia_isp_1_5_statistics_convert (_handle, statistics, out_rgbs_grid, out_af_grid);
222     XCAM_FAIL_RETURN (ERROR, err == ia_err_none, false, "ia_isp 1.5 convert stats failed");
223     return true;
224 }
225 
226 bool
227 IaIspAdaptor15::run (
228     const IspInputParameters *isp_input_params,
229     ia_binary_data *output_data)
230 {
231     ia_err err;
232 
233     _input_params.frame_use = isp_input_params->frame_use;
234     _input_params.sensor_frame_params = isp_input_params->sensor_frame_params;
235     _input_params.exposure_results = isp_input_params->exposure_results;
236     _input_params.awb_results = isp_input_params->awb_results;
237     _input_params.gbce_results = isp_input_params->gbce_results;
238     _input_params.pa_results = isp_input_params->pa_results;
239     _input_params.manual_brightness = isp_input_params->manual_brightness;
240     _input_params.manual_contrast = isp_input_params->manual_contrast;
241     _input_params.manual_hue = isp_input_params->manual_hue;
242     _input_params.manual_saturation = isp_input_params->manual_saturation;
243     _input_params.nr_setting.feature_level = ia_isp_feature_level_high;
244     _input_params.nr_setting.strength = isp_input_params->manual_nr_level;
245     _input_params.ee_setting.feature_level = ia_isp_feature_level_high;
246     _input_params.ee_setting.strength = isp_input_params->manual_sharpness;
247     _input_params.effects = isp_input_params->effects;
248 
249     err = ia_isp_1_5_run (_handle, &_input_params, output_data);
250     XCAM_FAIL_RETURN (ERROR, err == ia_err_none, false, "ia_isp 1.5 run failed");
251     return true;
252 }
253 
254 #endif
255 
256 static double
_calculate_new_value_by_speed(double start,double end,double speed)257 _calculate_new_value_by_speed (double start, double end, double speed)
258 {
259     XCAM_ASSERT (speed >= 0.0 && speed <= 1.0);
260     static const double value_equal_range = 0.000001;
261 
262     if (fabs (end - start) <= value_equal_range)
263         return end;
264     return (start * (1.0 - speed) + end * speed);
265 }
266 
267 static double
_imx185_sensor_gain_code_to_mutiplier(uint32_t code)268 _imx185_sensor_gain_code_to_mutiplier (uint32_t code)
269 {
270     /* 185 sensor code : DB = 160 : 48 */
271     double db;
272     db = code * 48.0 / 160.0;
273     return pow (10.0, db / 20.0);
274 }
275 
276 static uint32_t
_mutiplier_to_imx185_sensor_gain_code(double mutiplier)277 _mutiplier_to_imx185_sensor_gain_code (double mutiplier)
278 {
279     double db = log10 (mutiplier) * 20;
280     if (db > 48)
281         db = 48;
282     return (uint32_t) (db * 160 / 48);
283 }
284 
285 static uint32_t
_time_to_coarse_line(const ia_aiq_exposure_sensor_descriptor * desc,uint32_t time_us)286 _time_to_coarse_line (const ia_aiq_exposure_sensor_descriptor *desc, uint32_t time_us)
287 {
288     float value =  time_us * desc->pixel_clock_freq_mhz;
289 
290     value = (value + desc->pixel_periods_per_line / 2) / desc->pixel_periods_per_line;
291     return (uint32_t)(value);
292 }
293 
294 static uint32_t
_coarse_line_to_time(const ia_aiq_exposure_sensor_descriptor * desc,uint32_t coarse_line)295 _coarse_line_to_time (const ia_aiq_exposure_sensor_descriptor *desc, uint32_t coarse_line)
296 {
297     return coarse_line * desc->pixel_periods_per_line / desc->pixel_clock_freq_mhz;
298 }
299 
AiqAeResult()300 AiqAeHandler::AiqAeResult::AiqAeResult()
301 {
302     xcam_mem_clear (ae_result);
303     xcam_mem_clear (ae_exp_ret);
304     xcam_mem_clear (aiq_exp_param);
305     xcam_mem_clear (sensor_exp_param);
306     xcam_mem_clear (weight_grid);
307     xcam_mem_clear (flash_param);
308 }
309 
310 void
copy(ia_aiq_ae_results * result)311 AiqAeHandler::AiqAeResult::copy (ia_aiq_ae_results *result)
312 {
313     XCAM_ASSERT (result);
314 
315     this->ae_result = *result;
316     this->aiq_exp_param = *result->exposures[0].exposure;
317     this->sensor_exp_param = *result->exposures[0].sensor_exposure;
318     this->weight_grid = *result->weight_grid;
319 #ifdef HAVE_AIQ_2_7
320     this->flash_param = result->flashes[0];
321 #else
322     this->flash_param = *result->flash;
323 #endif
324 
325     this->ae_exp_ret.exposure = &this->aiq_exp_param;
326     this->ae_exp_ret.sensor_exposure = &this->sensor_exp_param;
327     this->ae_result.exposures = &this->ae_exp_ret;
328     this->ae_result.weight_grid = &this->weight_grid;
329 #ifdef HAVE_AIQ_2_7
330     this->ae_result.flashes[0] = this->flash_param;
331 #else
332     this->ae_result.flash = &this->flash_param;
333 #endif
334     this->ae_result.num_exposures = 1;
335 }
336 
AiqAeHandler(SmartPtr<AiqCompositor> & aiq_compositor)337 AiqAeHandler::AiqAeHandler (SmartPtr<AiqCompositor> &aiq_compositor)
338     : _aiq_compositor (aiq_compositor)
339     , _started (false)
340 {
341     xcam_mem_clear (_ia_ae_window);
342     xcam_mem_clear (_sensor_descriptor);
343     xcam_mem_clear (_manual_limits);
344     xcam_mem_clear (_input);
345     _input.num_exposures = 1;
346     _input.frame_use = _aiq_compositor->get_frame_use();
347     _input.flash_mode = ia_aiq_flash_mode_off;
348     _input.operation_mode = ia_aiq_ae_operation_mode_automatic;
349     _input.metering_mode = ia_aiq_ae_metering_mode_evaluative;
350     _input.priority_mode = ia_aiq_ae_priority_mode_normal;
351     _input.flicker_reduction_mode = ia_aiq_ae_flicker_reduction_auto;
352     _input.sensor_descriptor = NULL;
353     _input.exposure_window = NULL;
354     _input.exposure_coordinate = NULL;
355     _input.ev_shift = 0.0;
356     _input.manual_exposure_time_us = -1;
357     _input.manual_analog_gain = -1.0;
358     _input.manual_iso = -1.0;
359     _input.aec_features = NULL;
360     _input.manual_limits = &_manual_limits;
361 }
362 
363 bool
set_description(struct atomisp_sensor_mode_data * sensor_data)364 AiqAeHandler::set_description (struct atomisp_sensor_mode_data *sensor_data)
365 {
366     XCAM_ASSERT (sensor_data);
367 
368     _sensor_descriptor.pixel_clock_freq_mhz = sensor_data->vt_pix_clk_freq_mhz / 1000000.0f;
369     _sensor_descriptor.pixel_periods_per_line = sensor_data->line_length_pck;
370     _sensor_descriptor.line_periods_per_field = sensor_data->frame_length_lines;
371     _sensor_descriptor.line_periods_vertical_blanking = sensor_data->frame_length_lines
372             - (sensor_data->crop_vertical_end - sensor_data->crop_vertical_start + 1)
373             / sensor_data->binning_factor_y;
374     _sensor_descriptor.fine_integration_time_min = sensor_data->fine_integration_time_def;
375     _sensor_descriptor.fine_integration_time_max_margin = sensor_data->line_length_pck - sensor_data->fine_integration_time_def;
376     _sensor_descriptor.coarse_integration_time_min = sensor_data->coarse_integration_time_min;
377     _sensor_descriptor.coarse_integration_time_max_margin = sensor_data->coarse_integration_time_max_margin;
378 
379     return true;
380 }
381 
382 bool
ensure_ia_parameters()383 AiqAeHandler::ensure_ia_parameters ()
384 {
385     bool ret = true;
386     ret = ret && ensure_ae_mode ();
387     ret = ret && ensure_ae_metering_mode ();
388     ret = ret && ensure_ae_priority_mode ();
389     ret = ret && ensure_ae_flicker_mode ();
390     ret = ret && ensure_ae_manual ();
391     ret = ret && ensure_ae_ev_shift ();
392     _input.sensor_descriptor = &_sensor_descriptor;
393     return ret;
394 }
395 
ensure_ae_mode()396 bool AiqAeHandler::ensure_ae_mode ()
397 {
398     XCamAeMode mode = this->get_mode_unlock();
399     switch (mode) {
400     case XCAM_AE_MODE_AUTO:
401     case XCAM_AE_MODE_MANUAL:
402         _input.operation_mode = ia_aiq_ae_operation_mode_automatic;
403         break;
404 
405     case XCAM_AE_MODE_NOT_SET:
406     default:
407         XCAM_LOG_ERROR("unsupported ae mode:%d", mode);
408         return false;
409     }
410     return true;
411 }
ensure_ae_metering_mode()412 bool AiqAeHandler::ensure_ae_metering_mode ()
413 {
414     XCamAeMeteringMode mode = this->get_metering_mode_unlock();
415 
416     _input.exposure_window = NULL;
417 
418     switch (mode) {
419     case XCAM_AE_METERING_MODE_AUTO:
420         _input.metering_mode = ia_aiq_ae_metering_mode_evaluative;
421         break;
422     case XCAM_AE_METERING_MODE_SPOT:
423     {
424         _input.metering_mode = ia_aiq_ae_metering_mode_evaluative;
425         const XCam3AWindow & window = this->get_window_unlock();
426         if (window.x_end > window.x_start &&
427                 window.y_end > window.y_start) {
428             _aiq_compositor->convert_window_to_ia(window, _ia_ae_window);
429             _input.exposure_window = &_ia_ae_window;
430         }
431     }
432     break;
433     case XCAM_AE_METERING_MODE_CENTER:
434         _input.metering_mode = ia_aiq_ae_metering_mode_center;
435         break;
436     case XCAM_AE_METERING_MODE_WEIGHTED_WINDOW:
437     {
438         _input.metering_mode = ia_aiq_ae_metering_mode_evaluative;
439         const XCam3AWindow & weighted_window = this->get_window_unlock();
440 
441         XCAM_LOG_DEBUG ("ensure_ae_metering_mode weighted_window x_start = %d, y_start = %d, x_end = %d, y_end = %d ",
442                         weighted_window.x_start, weighted_window.y_start, weighted_window.x_end, weighted_window.y_end);
443 
444         if (weighted_window.x_end > weighted_window.x_start &&
445                 weighted_window.y_end > weighted_window.y_start) {
446             _aiq_compositor->convert_window_to_ia(weighted_window, _ia_ae_window);
447             _input.exposure_window = &_ia_ae_window;
448         }
449     }
450     break;
451     default:
452         XCAM_LOG_ERROR("unsupported ae mode:%d", mode);
453         return false;
454     }
455     return true;
456 }
457 
ensure_ae_priority_mode()458 bool AiqAeHandler::ensure_ae_priority_mode ()
459 {
460     _input.priority_mode = ia_aiq_ae_priority_mode_normal;
461     return true;
462 }
463 
ensure_ae_flicker_mode()464 bool AiqAeHandler::ensure_ae_flicker_mode ()
465 {
466     XCamFlickerMode mode = this->get_flicker_mode_unlock ();
467     switch (mode) {
468     case XCAM_AE_FLICKER_MODE_AUTO:
469         _input.flicker_reduction_mode = ia_aiq_ae_flicker_reduction_auto;
470         break;
471     case XCAM_AE_FLICKER_MODE_50HZ:
472         _input.flicker_reduction_mode = ia_aiq_ae_flicker_reduction_50hz;
473         break;
474     case XCAM_AE_FLICKER_MODE_60HZ:
475         _input.flicker_reduction_mode = ia_aiq_ae_flicker_reduction_60hz;
476         break;
477     case XCAM_AE_FLICKER_MODE_OFF:
478         _input.flicker_reduction_mode = ia_aiq_ae_flicker_reduction_off;
479         break;
480     default:
481         XCAM_LOG_ERROR ("flicker mode(%d) unknown", mode);
482         return false;
483     }
484     return true;
485 }
486 
ensure_ae_manual()487 bool AiqAeHandler::ensure_ae_manual ()
488 {
489     if (this->get_mode_unlock () == XCAM_AE_MODE_MANUAL) {
490         _input.manual_exposure_time_us = get_manual_exposure_time_unlock ();
491         _input.manual_analog_gain = get_manual_analog_gain_unlock ();
492     }
493     else {
494         _input.manual_exposure_time_us = -1;
495         _input.manual_analog_gain = -1;
496     }
497 
498     _input.manual_limits->manual_exposure_time_min =
499         _sensor_descriptor.coarse_integration_time_min
500         * _sensor_descriptor.pixel_periods_per_line
501         / _sensor_descriptor.pixel_clock_freq_mhz;
502     _input.manual_limits->manual_exposure_time_max =
503         (_sensor_descriptor.line_periods_per_field - _sensor_descriptor.coarse_integration_time_max_margin)
504         * _sensor_descriptor.pixel_periods_per_line
505         / _sensor_descriptor.pixel_clock_freq_mhz;
506 
507     uint64_t exp_min_us = 0, exp_max_us = 0;
508     get_exposure_time_range_unlock (exp_min_us, exp_max_us);
509     if (exp_min_us && (int64_t)exp_min_us > _input.manual_limits->manual_exposure_time_min) {
510         _input.manual_limits->manual_exposure_time_min = exp_min_us;
511     }
512     if (exp_max_us && (int64_t)exp_max_us < _input.manual_limits->manual_exposure_time_max) {
513         _input.manual_limits->manual_exposure_time_max = exp_max_us;
514     }
515 
516     _input.manual_limits->manual_frame_time_us_min = -1;
517     _input.manual_limits->manual_frame_time_us_max = 1000000 / _aiq_compositor->get_framerate ();
518     _input.manual_limits->manual_iso_min = -1;
519     _input.manual_limits->manual_iso_max = -1;
520 
521     return true;
522 }
523 
ensure_ae_ev_shift()524 bool AiqAeHandler::ensure_ae_ev_shift ()
525 {
526     _input.ev_shift = this->get_ev_shift_unlock();
527     return true;
528 }
529 
530 SmartPtr<X3aResult>
pop_result()531 AiqAeHandler::pop_result ()
532 {
533     //AnalyzerHandler::HandlerLock lock(this);
534 
535     X3aIspExposureResult *result = new X3aIspExposureResult(XCAM_IMAGE_PROCESS_ONCE);
536     struct atomisp_exposure sensor;
537     XCam3aResultExposure exposure;
538 
539     xcam_mem_clear (sensor);
540     sensor.integration_time[0] = _result.sensor_exp_param.coarse_integration_time;
541     sensor.integration_time[1] = _result.sensor_exp_param.fine_integration_time;
542     sensor.gain[0] = _result.sensor_exp_param.analog_gain_code_global;
543     sensor.gain[1] = _result.sensor_exp_param.digital_gain_global;
544     result->set_isp_config (sensor);
545 
546     xcam_mem_clear (exposure);
547     exposure.exposure_time = _result.aiq_exp_param.exposure_time_us;
548     exposure.analog_gain = _result.aiq_exp_param.analog_gain;
549     exposure.digital_gain = _result.aiq_exp_param.digital_gain;
550     exposure.aperture = _result.aiq_exp_param.aperture_fn;
551     result->set_standard_result (exposure);
552 
553     return result;
554 }
555 
556 XCamReturn
analyze(X3aResultList & output)557 AiqAeHandler::analyze (X3aResultList &output)
558 {
559     ia_aiq  *ia_handle = NULL;
560     ia_aiq_ae_results *ae_result = NULL;
561     ia_aiq_exposure_sensor_parameters *cur_sensor_result = NULL;
562     ia_err ia_error = ia_err_none;
563     bool need_apply = false;
564     SmartPtr<X3aResult> result;
565 
566     AnalyzerHandler::HandlerLock lock(this);
567 
568     if (!ensure_ia_parameters ()) {
569         XCAM_LOG_ERROR ("AIQ AE ensure ia parameters failed");
570         return XCAM_RETURN_ERROR_PARAM;
571     }
572 
573     ia_handle = _aiq_compositor->get_handle ();
574     XCAM_ASSERT (ia_handle);
575     ia_error = ia_aiq_ae_run (ia_handle, &_input, &ae_result);
576     XCAM_FAIL_RETURN (ERROR, ia_error == ia_err_none, XCAM_RETURN_ERROR_AIQ, "AIQ run AE failed");
577 
578     cur_sensor_result = ae_result->exposures[0].sensor_exposure;
579 
580     if (!_started) {
581         _result.copy (ae_result);
582         _started = true;
583         need_apply = true;
584     } else {
585         //TODO
586         ia_aiq_exposure_sensor_parameters *last_sensor_res = &_result.sensor_exp_param;
587         if (last_sensor_res->coarse_integration_time !=  cur_sensor_result->coarse_integration_time ||
588                 last_sensor_res->fine_integration_time !=  cur_sensor_result->fine_integration_time ||
589                 last_sensor_res->analog_gain_code_global !=  cur_sensor_result->analog_gain_code_global ||
590                 last_sensor_res->digital_gain_global !=  cur_sensor_result->digital_gain_global) {
591             ia_aiq_exposure_sensor_parameters cur_cp_res = *cur_sensor_result;
592             ia_aiq_exposure_parameters cur_aiq_exp = *ae_result->exposures[0].exposure;
593             if (!manual_control_result (cur_cp_res, cur_aiq_exp, *last_sensor_res)) {
594                 XCAM_LOG_WARNING ("manual control AE result failed");
595             }
596             _result.copy (ae_result);
597             _result.sensor_exp_param = cur_cp_res;
598             _result.aiq_exp_param = cur_aiq_exp;
599 
600             need_apply = true;
601         }
602     }
603 
604     if (need_apply) {
605         result = pop_result ();
606         if (result.ptr())
607             output.push_back (result);
608     }
609 
610     return XCAM_RETURN_NO_ERROR;
611 }
612 
613 bool
manual_control_result(ia_aiq_exposure_sensor_parameters & cur_res,ia_aiq_exposure_parameters & cur_aiq_exp,const ia_aiq_exposure_sensor_parameters & last_res)614 AiqAeHandler::manual_control_result (
615     ia_aiq_exposure_sensor_parameters &cur_res,
616     ia_aiq_exposure_parameters &cur_aiq_exp,
617     const ia_aiq_exposure_sensor_parameters &last_res)
618 {
619     adjust_ae_speed (cur_res, cur_aiq_exp, last_res, this->get_speed_unlock());
620     adjust_ae_limitation (cur_res, cur_aiq_exp);
621 
622     return true;
623 }
624 
625 void
adjust_ae_speed(ia_aiq_exposure_sensor_parameters & cur_res,ia_aiq_exposure_parameters & cur_aiq_exp,const ia_aiq_exposure_sensor_parameters & last_res,double ae_speed)626 AiqAeHandler::adjust_ae_speed (
627     ia_aiq_exposure_sensor_parameters &cur_res,
628     ia_aiq_exposure_parameters &cur_aiq_exp,
629     const ia_aiq_exposure_sensor_parameters &last_res,
630     double ae_speed)
631 {
632     double last_gain, input_gain, ret_gain;
633     ia_aiq_exposure_sensor_parameters tmp_res;
634 
635     if (XCAM_DOUBLE_EQUAL_AROUND(ae_speed, 1.0 ))
636         return;
637     xcam_mem_clear (tmp_res);
638     tmp_res.coarse_integration_time = _calculate_new_value_by_speed (
639                                           last_res.coarse_integration_time,
640                                           cur_res.coarse_integration_time,
641                                           ae_speed);
642 
643     last_gain = _imx185_sensor_gain_code_to_mutiplier (last_res.analog_gain_code_global);
644     input_gain = _imx185_sensor_gain_code_to_mutiplier (cur_res.analog_gain_code_global);
645     ret_gain = _calculate_new_value_by_speed (last_gain, input_gain, ae_speed);
646 
647     tmp_res.analog_gain_code_global = _mutiplier_to_imx185_sensor_gain_code (ret_gain);
648 
649     XCAM_LOG_DEBUG ("AE speed: from (shutter:%d, gain:%d[%.03f]) to (shutter:%d, gain:%d[%.03f])",
650                     cur_res.coarse_integration_time, cur_res.analog_gain_code_global, input_gain,
651                     tmp_res.coarse_integration_time, tmp_res.analog_gain_code_global, ret_gain);
652 
653     cur_res.coarse_integration_time = tmp_res.coarse_integration_time;
654     cur_res.analog_gain_code_global = tmp_res.analog_gain_code_global;
655     cur_aiq_exp.exposure_time_us = _coarse_line_to_time (&_sensor_descriptor,
656                                    cur_res.coarse_integration_time);
657     cur_aiq_exp.analog_gain = ret_gain;
658 }
659 
660 void
adjust_ae_limitation(ia_aiq_exposure_sensor_parameters & cur_res,ia_aiq_exposure_parameters & cur_aiq_exp)661 AiqAeHandler::adjust_ae_limitation (ia_aiq_exposure_sensor_parameters &cur_res,
662                                     ia_aiq_exposure_parameters &cur_aiq_exp)
663 {
664     ia_aiq_exposure_sensor_descriptor * desc = &_sensor_descriptor;
665     uint64_t exposure_min = 0, exposure_max = 0;
666     double analog_max = get_max_analog_gain_unlock ();
667     uint32_t min_coarse_value = desc->coarse_integration_time_min;
668     uint32_t max_coarse_value = desc->line_periods_per_field - desc->coarse_integration_time_max_margin;
669     uint32_t value;
670 
671     get_exposure_time_range_unlock (exposure_min, exposure_max);
672 
673     if (exposure_min) {
674         value = _time_to_coarse_line (desc, (uint32_t)exposure_min);
675         min_coarse_value = (value > min_coarse_value) ? value : min_coarse_value;
676     }
677     if (cur_res.coarse_integration_time < min_coarse_value) {
678         cur_res.coarse_integration_time = min_coarse_value;
679         cur_aiq_exp.exposure_time_us = _coarse_line_to_time (desc, min_coarse_value);
680     }
681 
682     if (exposure_max) {
683         value = _time_to_coarse_line (desc, (uint32_t)exposure_max);
684         max_coarse_value = (value < max_coarse_value) ? value : max_coarse_value;
685     }
686     if (cur_res.coarse_integration_time > max_coarse_value) {
687         cur_res.coarse_integration_time = max_coarse_value;
688         cur_aiq_exp.exposure_time_us = _coarse_line_to_time (desc, max_coarse_value);
689     }
690 
691     if (analog_max >= 1.0) {
692         /* limit gains */
693         double gain = _imx185_sensor_gain_code_to_mutiplier (cur_res.analog_gain_code_global);
694         if (gain > analog_max) {
695             cur_res.analog_gain_code_global = _mutiplier_to_imx185_sensor_gain_code (analog_max);
696             cur_aiq_exp.analog_gain = analog_max;
697         }
698     }
699 }
700 
701 XCamFlickerMode
get_flicker_mode()702 AiqAeHandler::get_flicker_mode ()
703 {
704     {
705         AnalyzerHandler::HandlerLock lock(this);
706     }
707     return AeHandler::get_flicker_mode ();
708 }
709 
710 int64_t
get_current_exposure_time()711 AiqAeHandler::get_current_exposure_time ()
712 {
713     AnalyzerHandler::HandlerLock lock(this);
714 
715     return (int64_t)_result.aiq_exp_param.exposure_time_us;
716 }
717 
718 double
get_current_analog_gain()719 AiqAeHandler::get_current_analog_gain ()
720 {
721     AnalyzerHandler::HandlerLock lock(this);
722     return (double)_result.aiq_exp_param.analog_gain;
723 }
724 
725 double
get_max_analog_gain()726 AiqAeHandler::get_max_analog_gain ()
727 {
728     {
729         AnalyzerHandler::HandlerLock lock(this);
730     }
731     return AeHandler::get_max_analog_gain ();
732 }
733 
734 XCamReturn
set_RGBS_weight_grid(ia_aiq_rgbs_grid ** out_rgbs_grid)735 AiqAeHandler::set_RGBS_weight_grid (ia_aiq_rgbs_grid **out_rgbs_grid)
736 {
737     AnalyzerHandler::HandlerLock lock(this);
738 
739     rgbs_grid_block *rgbs_grid_ptr = (*out_rgbs_grid)->blocks_ptr;
740     uint32_t rgbs_grid_index = 0;
741     uint16_t rgbs_grid_width = (*out_rgbs_grid)->grid_width;
742     uint16_t rgbs_grid_height = (*out_rgbs_grid)->grid_height;
743 
744     XCAM_LOG_DEBUG ("rgbs_grid_width = %d, rgbs_grid_height = %d", rgbs_grid_width, rgbs_grid_height);
745 
746     uint64_t weight_sum = 0;
747 
748     uint32_t image_width = 0;
749     uint32_t image_height = 0;
750     _aiq_compositor->get_size (image_width, image_height);
751     XCAM_LOG_DEBUG ("image_width = %d, image_height = %d", image_width, image_height);
752 
753     uint32_t hor_pixels_per_grid = (image_width + (rgbs_grid_width >> 1)) / rgbs_grid_width;
754     uint32_t vert_pixels_per_gird = (image_height + (rgbs_grid_height >> 1)) / rgbs_grid_height;
755     XCAM_LOG_DEBUG ("rgbs grid: %d x %d pixels per grid cell", hor_pixels_per_grid, vert_pixels_per_gird);
756 
757     XCam3AWindow weighted_window = this->get_window_unlock ();
758     uint32_t weighted_grid_width = ((weighted_window.x_end - weighted_window.x_start + 1) +
759                                     (hor_pixels_per_grid >> 1)) / hor_pixels_per_grid;
760     uint32_t weighted_grid_height = ((weighted_window.y_end - weighted_window.y_start + 1) +
761                                      (vert_pixels_per_gird >> 1)) / vert_pixels_per_gird;
762     XCAM_LOG_DEBUG ("weighted_grid_width = %d, weighted_grid_height = %d", weighted_grid_width, weighted_grid_height);
763 
764     uint32_t *weighted_avg_gr = (uint32_t*)xcam_malloc0 (5 * weighted_grid_width * weighted_grid_height * sizeof(uint32_t));
765     if (NULL == weighted_avg_gr) {
766         return XCAM_RETURN_ERROR_MEM;
767     }
768     uint32_t *weighted_avg_r = weighted_avg_gr + (weighted_grid_width * weighted_grid_height);
769     uint32_t *weighted_avg_b = weighted_avg_r + (weighted_grid_width * weighted_grid_height);
770     uint32_t *weighted_avg_gb = weighted_avg_b + (weighted_grid_width * weighted_grid_height);
771     uint32_t *weighted_sat = weighted_avg_gb + (weighted_grid_width * weighted_grid_height);
772 
773     for (uint32_t win_index = 0; win_index < XCAM_AE_MAX_METERING_WINDOW_COUNT; win_index++) {
774         XCAM_LOG_DEBUG ("window start point(%d, %d), end point(%d, %d), weight = %d",
775                         _params.window_list[win_index].x_start, _params.window_list[win_index].y_start,
776                         _params.window_list[win_index].x_end, _params.window_list[win_index].y_end,
777                         _params.window_list[win_index].weight);
778 
779         if ((_params.window_list[win_index].weight <= 0) ||
780                 (_params.window_list[win_index].x_start < 0) ||
781                 ((uint32_t)_params.window_list[win_index].x_end > image_width) ||
782                 (_params.window_list[win_index].y_start < 0) ||
783                 ((uint32_t)_params.window_list[win_index].y_end > image_height) ||
784                 (_params.window_list[win_index].x_start >= _params.window_list[win_index].x_end) ||
785                 (_params.window_list[win_index].y_start >= _params.window_list[win_index].y_end) ||
786                 ((uint32_t)_params.window_list[win_index].x_end - (uint32_t)_params.window_list[win_index].x_start > image_width) ||
787                 ((uint32_t)_params.window_list[win_index].y_end - (uint32_t)_params.window_list[win_index].y_start > image_height)) {
788             XCAM_LOG_DEBUG ("skip window index = %d ", win_index);
789             continue;
790         }
791 
792         rgbs_grid_index = (_params.window_list[win_index].x_start +
793                            (hor_pixels_per_grid >> 1)) / hor_pixels_per_grid +
794                           ((_params.window_list[win_index].y_start + (vert_pixels_per_gird >> 1))
795                            / vert_pixels_per_gird) * rgbs_grid_width;
796 
797         weight_sum += _params.window_list[win_index].weight;
798 
799         XCAM_LOG_DEBUG ("cumulate rgbs grid statistic, window index = %d ", win_index);
800         for (uint32_t i = 0; i < weighted_grid_height; i++) {
801             for (uint32_t j = 0; j < weighted_grid_width; j++) {
802                 weighted_avg_gr[j + i * weighted_grid_width] += rgbs_grid_ptr[rgbs_grid_index + j +
803                         i * rgbs_grid_width].avg_gr * _params.window_list[win_index].weight;
804                 weighted_avg_r[j + i * weighted_grid_width] += rgbs_grid_ptr[rgbs_grid_index + j +
805                         i * rgbs_grid_width].avg_r * _params.window_list[win_index].weight;
806                 weighted_avg_b[j + i * weighted_grid_width] += rgbs_grid_ptr[rgbs_grid_index + j +
807                         i * rgbs_grid_width].avg_b * _params.window_list[win_index].weight;
808                 weighted_avg_gb[j + i * weighted_grid_width] += rgbs_grid_ptr[rgbs_grid_index + j +
809                         i * rgbs_grid_width].avg_gb * _params.window_list[win_index].weight;
810                 weighted_sat[j + i * weighted_grid_width] += rgbs_grid_ptr[rgbs_grid_index + j +
811                         i * rgbs_grid_width].sat * _params.window_list[win_index].weight;
812             }
813         }
814     }
815     XCAM_LOG_DEBUG ("sum of weighing factor = %" PRIu64, weight_sum);
816 
817     rgbs_grid_index = (weighted_window.x_start + (hor_pixels_per_grid >> 1)) / hor_pixels_per_grid +
818                       (weighted_window.y_start + (vert_pixels_per_gird >> 1)) / vert_pixels_per_gird * rgbs_grid_width;
819     for (uint32_t i = 0; i < weighted_grid_height; i++) {
820         for (uint32_t j = 0; j < weighted_grid_width; j++) {
821             rgbs_grid_ptr[rgbs_grid_index + j + i * rgbs_grid_width].avg_gr =
822                 weighted_avg_gr[j + i * weighted_grid_width] / weight_sum;
823             rgbs_grid_ptr[rgbs_grid_index + j + i * rgbs_grid_width].avg_r =
824                 weighted_avg_r[j + i * weighted_grid_width] / weight_sum;
825             rgbs_grid_ptr[rgbs_grid_index + j + i * rgbs_grid_width].avg_b =
826                 weighted_avg_b[j + i * weighted_grid_width] / weight_sum;
827             rgbs_grid_ptr[rgbs_grid_index + j + i * rgbs_grid_width].avg_gb =
828                 weighted_avg_gb[j + i * weighted_grid_width] / weight_sum;
829             rgbs_grid_ptr[rgbs_grid_index + j + i * rgbs_grid_width].sat =
830                 weighted_sat[j + i * weighted_grid_width] / weight_sum;
831         }
832     }
833 
834     xcam_free (weighted_avg_gr);
835 
836     return XCAM_RETURN_NO_ERROR;
837 }
838 
839 
840 XCamReturn
set_hist_weight_grid(ia_aiq_hist_weight_grid ** out_weight_grid)841 AiqAeHandler::set_hist_weight_grid (ia_aiq_hist_weight_grid **out_weight_grid)
842 {
843     AnalyzerHandler::HandlerLock lock(this);
844 
845     uint16_t hist_grid_width = (*out_weight_grid)->width;
846     uint16_t hist_grid_height = (*out_weight_grid)->height;
847     uint32_t hist_grid_index = 0;
848 
849     unsigned char* weights_map_ptr = (*out_weight_grid)->weights;
850 
851     uint32_t image_width = 0;
852     uint32_t image_height = 0;
853     _aiq_compositor->get_size (image_width, image_height);
854 
855     uint32_t hor_pixels_per_grid = (image_width + (hist_grid_width >> 1)) / hist_grid_width;
856     uint32_t vert_pixels_per_gird = (image_height + (hist_grid_height >> 1)) / hist_grid_height;
857     XCAM_LOG_DEBUG ("hist weight grid: %d x %d pixels per grid cell", hor_pixels_per_grid, vert_pixels_per_gird);
858 
859     memset (weights_map_ptr, 0, hist_grid_width * hist_grid_height);
860 
861     for (uint32_t win_index = 0; win_index < XCAM_AE_MAX_METERING_WINDOW_COUNT; win_index++) {
862         XCAM_LOG_DEBUG ("window start point(%d, %d), end point(%d, %d), weight = %d",
863                         _params.window_list[win_index].x_start, _params.window_list[win_index].y_start,
864                         _params.window_list[win_index].x_end, _params.window_list[win_index].y_end,
865                         _params.window_list[win_index].weight);
866 
867         if ((_params.window_list[win_index].weight <= 0) ||
868                 (_params.window_list[win_index].weight > 15) ||
869                 (_params.window_list[win_index].x_start < 0) ||
870                 ((uint32_t)_params.window_list[win_index].x_end > image_width) ||
871                 (_params.window_list[win_index].y_start < 0) ||
872                 ((uint32_t)_params.window_list[win_index].y_end > image_height) ||
873                 (_params.window_list[win_index].x_start >= _params.window_list[win_index].x_end) ||
874                 (_params.window_list[win_index].y_start >= _params.window_list[win_index].y_end) ||
875                 ((uint32_t)_params.window_list[win_index].x_end - (uint32_t)_params.window_list[win_index].x_start > image_width) ||
876                 ((uint32_t)_params.window_list[win_index].y_end - (uint32_t)_params.window_list[win_index].y_start > image_height)) {
877             XCAM_LOG_DEBUG ("skip window index = %d ", win_index);
878             continue;
879         }
880 
881         uint32_t weighted_grid_width =
882             ((_params.window_list[win_index].x_end - _params.window_list[win_index].x_start + 1) +
883              (hor_pixels_per_grid >> 1)) / hor_pixels_per_grid;
884         uint32_t weighted_grid_height =
885             ((_params.window_list[win_index].y_end - _params.window_list[win_index].y_start + 1) +
886              (vert_pixels_per_gird >> 1)) / vert_pixels_per_gird;
887 
888         hist_grid_index = (_params.window_list[win_index].x_start + (hor_pixels_per_grid >> 1)) / hor_pixels_per_grid +
889                           ((_params.window_list[win_index].y_start + (vert_pixels_per_gird >> 1)) /
890                            vert_pixels_per_gird) * hist_grid_width;
891 
892         for (uint32_t i = 0; i < weighted_grid_height; i++) {
893             for (uint32_t j = 0; j < weighted_grid_width; j++) {
894                 weights_map_ptr[hist_grid_index + j + i * hist_grid_width] = _params.window_list[win_index].weight;
895             }
896         }
897     }
898     return XCAM_RETURN_NO_ERROR;
899 }
900 
901 XCamReturn
dump_hist_weight_grid(const ia_aiq_hist_weight_grid * weight_grid)902 AiqAeHandler::dump_hist_weight_grid (const ia_aiq_hist_weight_grid *weight_grid)
903 {
904     XCAM_LOG_DEBUG ("E dump_hist_weight_grid");
905     if (NULL == weight_grid) {
906         return XCAM_RETURN_ERROR_PARAM;
907     }
908 
909     uint16_t grid_width = weight_grid->width;
910     uint16_t grid_height = weight_grid->height;
911 
912     for (uint32_t i = 0; i < grid_height; i++) {
913         for (uint32_t j = 0; j < grid_width; j++) {
914             printf ("%d  ", weight_grid->weights[j + i * grid_width]);
915         }
916         printf("\n");
917     }
918 
919     XCAM_LOG_DEBUG ("X dump_hist_weight_grid");
920     return XCAM_RETURN_NO_ERROR;
921 }
922 
923 XCamReturn
dump_RGBS_grid(const ia_aiq_rgbs_grid * rgbs_grid)924 AiqAeHandler::dump_RGBS_grid (const ia_aiq_rgbs_grid *rgbs_grid)
925 {
926     XCAM_LOG_DEBUG ("E dump_RGBS_grid");
927     if (NULL == rgbs_grid) {
928         return XCAM_RETURN_ERROR_PARAM;
929     }
930 
931     uint16_t grid_width = rgbs_grid->grid_width;
932     uint16_t grid_height = rgbs_grid->grid_height;
933 
934     printf("AVG B\n");
935     for (uint32_t i = 0; i < grid_height; i++) {
936         for (uint32_t j = 0; j < grid_width; j++) {
937             printf ("%d  ", rgbs_grid->blocks_ptr[j + i * grid_width].avg_b);
938         }
939         printf("\n");
940     }
941     printf("AVG Gb\n");
942     for (uint32_t i = 0; i < grid_height; i++) {
943         for (uint32_t j = 0; j < grid_width; j++) {
944             printf ("%d  ", rgbs_grid->blocks_ptr[j + i * grid_width].avg_gb);
945         }
946         printf("\n");
947     }
948     printf("AVG Gr\n");
949     for (uint32_t i = 0; i < grid_height; i++) {
950         for (uint32_t j = 0; j < grid_width; j++) {
951             printf ("%d  ", rgbs_grid->blocks_ptr[j + i * grid_width].avg_gr);
952         }
953         printf("\n");
954     }
955     printf("AVG R\n");
956     for (uint32_t i = 0; i < grid_height; i++) {
957         for (uint32_t j = 0; j < grid_width; j++) {
958             printf ("%d  ", rgbs_grid->blocks_ptr[j + i * grid_width].avg_r);
959             //printf ("%d  ", rgbs_grid->blocks_ptr[j + i * grid_width].sat);
960         }
961         printf("\n");
962     }
963 
964     XCAM_LOG_DEBUG ("X dump_RGBS_grid");
965     return XCAM_RETURN_NO_ERROR;
966 }
967 
AiqAwbHandler(SmartPtr<AiqCompositor> & aiq_compositor)968 AiqAwbHandler::AiqAwbHandler (SmartPtr<AiqCompositor> &aiq_compositor)
969     : _aiq_compositor (aiq_compositor)
970     , _started (false)
971 {
972     xcam_mem_clear (_cct_range);
973     xcam_mem_clear (_result);
974     xcam_mem_clear (_history_result);
975     xcam_mem_clear (_cct_range);
976     xcam_mem_clear (_input);
977 
978     _input.frame_use = aiq_compositor->get_frame_use ();
979     _input.scene_mode = ia_aiq_awb_operation_mode_auto;
980     _input.manual_cct_range = NULL;
981     _input.manual_white_coordinate = NULL;
982 }
983 
984 XCamReturn
analyze(X3aResultList & output)985 AiqAwbHandler::analyze (X3aResultList &output)
986 {
987     ia_aiq  *ia_handle = NULL;
988     ia_aiq_awb_results *awb_ret = NULL;
989     ia_err ia_error = ia_err_none;
990 
991     XCAM_UNUSED (output);
992 
993     AnalyzerHandler::HandlerLock lock(this);
994 
995     if (!ensure_ia_parameters ()) {
996         XCAM_LOG_ERROR ("AIQ AE ensure ia parameters failed");
997         return XCAM_RETURN_ERROR_PARAM;
998     }
999 
1000     ia_handle = _aiq_compositor->get_handle ();
1001     XCAM_ASSERT (ia_handle);
1002     ia_error = ia_aiq_awb_run (ia_handle, &_input, &awb_ret);
1003     XCAM_FAIL_RETURN (ERROR, ia_error == ia_err_none, XCAM_RETURN_ERROR_AIQ, "AIQ run AWB failed");
1004 
1005     _result = *awb_ret;
1006     if (!_started) {
1007         _history_result = _result;
1008         _started = true;
1009     }
1010     adjust_speed (_history_result);
1011     _history_result = _result;
1012 
1013     return XCAM_RETURN_NO_ERROR;
1014 }
1015 
1016 bool
ensure_ia_parameters()1017 AiqAwbHandler::ensure_ia_parameters ()
1018 {
1019     bool ret = true;
1020 
1021     _input.frame_use = _aiq_compositor->get_frame_use ();
1022     ret = ret && ensure_awb_mode ();
1023     return ret;
1024 }
1025 
1026 bool
ensure_awb_mode()1027 AiqAwbHandler::ensure_awb_mode ()
1028 {
1029     XCamAwbMode mode = get_mode_unlock();
1030 
1031     _input.manual_cct_range = NULL;
1032     _input.scene_mode = ia_aiq_awb_operation_mode_auto;
1033 
1034     switch (mode) {
1035     case XCAM_AWB_MODE_AUTO:
1036         _input.scene_mode = ia_aiq_awb_operation_mode_auto;
1037         break;
1038     case XCAM_AWB_MODE_MANUAL: {
1039         uint32_t cct_min = 0, cct_max = 0;
1040         get_cct_range_unlock (cct_min, cct_max);
1041         if (cct_min  && cct_max) {
1042             _input.scene_mode = ia_aiq_awb_operation_mode_manual_cct_range;
1043             _cct_range.max_cct = cct_min;
1044             _cct_range.min_cct = cct_max;
1045             _input.manual_cct_range = &_cct_range;
1046         } else
1047             _input.scene_mode = ia_aiq_awb_operation_mode_auto;
1048         break;
1049     }
1050     case XCAM_AWB_MODE_DAYLIGHT:
1051         _input.scene_mode = ia_aiq_awb_operation_mode_daylight;
1052         break;
1053     case XCAM_AWB_MODE_SUNSET:
1054         _input.scene_mode = ia_aiq_awb_operation_mode_sunset;
1055         break;
1056     case XCAM_AWB_MODE_CLOUDY:
1057         _input.scene_mode = ia_aiq_awb_operation_mode_partly_overcast;
1058         break;
1059     case XCAM_AWB_MODE_TUNGSTEN:
1060         _input.scene_mode = ia_aiq_awb_operation_mode_incandescent;
1061         break;
1062     case XCAM_AWB_MODE_FLUORESCENT:
1063         _input.scene_mode = ia_aiq_awb_operation_mode_fluorescent;
1064         break;
1065     case XCAM_AWB_MODE_WARM_FLUORESCENT:
1066         _input.scene_mode = ia_aiq_awb_operation_mode_incandescent;
1067         break;
1068     case XCAM_AWB_MODE_SHADOW:
1069         _input.scene_mode = ia_aiq_awb_operation_mode_fully_overcast;
1070         break;
1071     case XCAM_AWB_MODE_WARM_INCANDESCENT:
1072         _input.scene_mode = ia_aiq_awb_operation_mode_incandescent;
1073         break;
1074     case XCAM_AWB_MODE_NOT_SET:
1075         break;
1076 
1077     default:
1078         XCAM_LOG_ERROR ("unknown or unsupported AWB mode(%d)", mode);
1079         return false;
1080     }
1081     return true;
1082 }
1083 
1084 void
adjust_speed(const ia_aiq_awb_results & last_ret)1085 AiqAwbHandler::adjust_speed (const ia_aiq_awb_results &last_ret)
1086 {
1087     _result.final_r_per_g =
1088         _calculate_new_value_by_speed (
1089             last_ret.final_r_per_g, _result.final_r_per_g, get_speed_unlock ());
1090     _result.final_b_per_g =
1091         _calculate_new_value_by_speed (
1092             last_ret.final_b_per_g, _result.final_b_per_g, get_speed_unlock ());
1093 }
1094 
1095 uint32_t
get_current_estimate_cct()1096 AiqAwbHandler::get_current_estimate_cct ()
1097 {
1098     AnalyzerHandler::HandlerLock lock(this);
1099     return (uint32_t)_result.cct_estimate;
1100 }
1101 
1102 XCamReturn
analyze(X3aResultList & output)1103 AiqAfHandler::analyze (X3aResultList &output)
1104 {
1105     // TODO
1106     XCAM_UNUSED (output);
1107     return XCAM_RETURN_NO_ERROR;
1108 }
1109 
AiqCommonHandler(SmartPtr<AiqCompositor> & aiq_compositor)1110 AiqCommonHandler::AiqCommonHandler (SmartPtr<AiqCompositor> &aiq_compositor)
1111     : _aiq_compositor (aiq_compositor)
1112     , _gbce_result (NULL)
1113 {
1114 }
1115 
1116 
1117 XCamReturn
analyze(X3aResultList & output)1118 AiqCommonHandler::analyze (X3aResultList &output)
1119 {
1120     ia_aiq  *ia_handle = NULL;
1121     ia_aiq_gbce_results *gbce_result = NULL;
1122     ia_err ia_error = ia_err_none;
1123 
1124     XCAM_UNUSED (output);
1125 
1126     AnalyzerHandler::HandlerLock lock(this);
1127 
1128     ia_aiq_gbce_input_params gbce_input;
1129     xcam_mem_clear (gbce_input);
1130     if (has_gbce_unlock()) {
1131         gbce_input.gbce_level = ia_aiq_gbce_level_use_tuning;
1132     }
1133     else {
1134         gbce_input.gbce_level = ia_aiq_gbce_level_bypass;
1135     }
1136     gbce_input.frame_use = _aiq_compositor->get_frame_use ();
1137     gbce_input.ev_shift = _aiq_compositor->get_ae_ev_shift_unlock ();
1138     ia_handle = _aiq_compositor->get_handle ();
1139     XCAM_ASSERT (ia_handle);
1140     ia_error = ia_aiq_gbce_run (ia_handle, &gbce_input, &gbce_result);
1141 
1142     XCAM_FAIL_RETURN (ERROR, ia_error == ia_err_none, XCAM_RETURN_ERROR_AIQ, "AIQ run GBCE failed");
1143 
1144     //TODO, need copy GBCE result out, not just assign
1145     _gbce_result = gbce_result;
1146 
1147     return XCAM_RETURN_NO_ERROR;
1148 }
1149 
1150 class CmcParser {
1151 public:
CmcParser(ia_binary_data & cpf)1152     explicit CmcParser (ia_binary_data &cpf)
1153     {
1154         _cmc = ia_cmc_parser_init (&cpf);
1155     }
~CmcParser()1156     ~CmcParser ()
1157     {
1158         if (_cmc)
1159             ia_cmc_parser_deinit (_cmc);
1160     }
get()1161     ia_cmc_t *get() {
1162         return _cmc;
1163     }
1164 
1165 private:
1166     ia_cmc_t *_cmc;
1167 };
1168 
1169 void
convert_window_to_ia(const XCam3AWindow & window,ia_rectangle & ia_window)1170 AiqCompositor::convert_window_to_ia (const XCam3AWindow &window, ia_rectangle &ia_window)
1171 {
1172     ia_rectangle source;
1173     ia_coordinate_system source_system;
1174     ia_coordinate_system target_system = {IA_COORDINATE_TOP, IA_COORDINATE_LEFT, IA_COORDINATE_BOTTOM, IA_COORDINATE_RIGHT};
1175 
1176     source_system.left = 0;
1177     source_system.top = 0;
1178     source_system.right = this->_width;
1179     source_system.bottom = this->_height;
1180     XCAM_ASSERT (_width && _height);
1181 
1182     source.left = window.x_start;
1183     source.top = window.y_start;
1184     source.right = window.x_end;
1185     source.bottom = window.y_end;
1186     ia_coordinate_convert_rect (&source_system, &source, &target_system, &ia_window);
1187 }
1188 
AiqCompositor()1189 AiqCompositor::AiqCompositor ()
1190     : _ia_handle (NULL)
1191     , _ia_mkn (NULL)
1192     , _pa_result (NULL)
1193 #ifdef HAVE_AIQ_2_7
1194     , _sa_result (NULL)
1195 #endif
1196     , _frame_use (ia_aiq_frame_use_video)
1197     , _width (0)
1198     , _height (0)
1199 {
1200     xcam_mem_clear (_frame_params);
1201 }
1202 
~AiqCompositor()1203 AiqCompositor::~AiqCompositor ()
1204 {
1205 }
1206 
1207 bool
open(ia_binary_data & cpf)1208 AiqCompositor::open (ia_binary_data &cpf)
1209 {
1210     CmcParser cmc (cpf);
1211 
1212     _ia_mkn = ia_mkn_init (ia_mkn_cfg_compression, 32000, 100000);
1213     _ia_handle =
1214         ia_aiq_init (
1215             &cpf, NULL, NULL,
1216             MAX_STATISTICS_WIDTH, MAX_STATISTICS_HEIGHT,
1217             1, //max_num_stats_in
1218             cmc.get(),
1219             _ia_mkn);
1220 
1221     if (_ia_handle == NULL) {
1222         XCAM_LOG_WARNING ("AIQ init failed");
1223         return false;
1224     }
1225 
1226     _adaptor = new IaIspAdaptor22;
1227     XCAM_ASSERT (_adaptor.ptr());
1228     if (!_adaptor->init (&cpf, MAX_STATISTICS_WIDTH, MAX_STATISTICS_HEIGHT, cmc.get(), _ia_mkn)) {
1229         XCAM_LOG_WARNING ("AIQ isp adaptor init failed");
1230         return false;
1231     }
1232 
1233     _pa_result = NULL;
1234 #ifdef HAVE_AIQ_2_7
1235     _sa_result = NULL;
1236 #endif
1237 
1238     XCAM_LOG_DEBUG ("Aiq compositor opened");
1239     return true;
1240 }
1241 
1242 void
close()1243 AiqCompositor::close ()
1244 {
1245     _adaptor.release ();
1246     if (_ia_handle) {
1247         ia_aiq_deinit (_ia_handle);
1248         _ia_handle = NULL;
1249     }
1250 
1251     if (_ia_mkn) {
1252         ia_mkn_uninit (_ia_mkn);
1253         _ia_mkn = NULL;
1254     }
1255 
1256     _ae_handler.release ();
1257     _awb_handler.release ();
1258     _af_handler.release ();
1259     _common_handler.release ();
1260 
1261     _pa_result = NULL;
1262 #ifdef HAVE_AIQ_2_7
1263     _sa_result = NULL;
1264 #endif
1265 
1266     XCAM_LOG_DEBUG ("Aiq compositor closed");
1267 }
1268 
1269 bool
set_sensor_mode_data(struct atomisp_sensor_mode_data * sensor_mode)1270 AiqCompositor::set_sensor_mode_data (struct atomisp_sensor_mode_data *sensor_mode)
1271 {
1272     _frame_params.horizontal_crop_offset = sensor_mode->crop_horizontal_start;
1273     _frame_params.vertical_crop_offset = sensor_mode->crop_vertical_start;
1274     _frame_params.cropped_image_height = sensor_mode->crop_vertical_end - sensor_mode->crop_vertical_start + 1;
1275     _frame_params.cropped_image_width = sensor_mode->crop_horizontal_end - sensor_mode->crop_horizontal_start + 1;
1276 
1277     /* hard code to 254? */
1278     _frame_params.horizontal_scaling_denominator = 254;
1279     _frame_params.vertical_scaling_denominator = 254;
1280 
1281     if ((_frame_params.cropped_image_width == 0) || (_frame_params.cropped_image_height == 0)) {
1282         _frame_params.horizontal_scaling_numerator = 0;
1283         _frame_params.vertical_scaling_numerator = 0;
1284     } else {
1285         _frame_params.horizontal_scaling_numerator =
1286             sensor_mode->output_width * 254 * sensor_mode->binning_factor_x / _frame_params.cropped_image_width;
1287         _frame_params.vertical_scaling_numerator =
1288             sensor_mode->output_height * 254 * sensor_mode->binning_factor_y / _frame_params.cropped_image_height;
1289     }
1290 
1291     if (!_ae_handler->set_description (sensor_mode)) {
1292         XCAM_LOG_WARNING ("AIQ set ae description failed");
1293         return XCAM_RETURN_ERROR_AIQ;
1294     }
1295     return true;
1296 }
1297 
1298 bool
set_3a_stats(SmartPtr<X3aIspStatistics> & stats)1299 AiqCompositor::set_3a_stats (SmartPtr<X3aIspStatistics> &stats)
1300 {
1301     ia_aiq_statistics_input_params aiq_stats_input;
1302     ia_aiq_rgbs_grid *rgbs_grids = NULL;
1303     ia_aiq_af_grid *af_grids = NULL;
1304 
1305     xcam_mem_clear (aiq_stats_input);
1306     aiq_stats_input.frame_timestamp = stats->get_timestamp();
1307     aiq_stats_input.frame_id = stats->get_timestamp() + 1;
1308     aiq_stats_input.rgbs_grids = (const ia_aiq_rgbs_grid **)&rgbs_grids;
1309     aiq_stats_input.num_rgbs_grids = 1;
1310     aiq_stats_input.af_grids = (const ia_aiq_af_grid **)(&af_grids);
1311     aiq_stats_input.num_af_grids = 1;
1312 
1313     aiq_stats_input.frame_af_parameters = NULL;
1314     aiq_stats_input.external_histograms = NULL;
1315     aiq_stats_input.num_external_histograms = 0;
1316     aiq_stats_input.camera_orientation = ia_aiq_camera_orientation_unknown;
1317 
1318     if (_pa_result)
1319         aiq_stats_input.frame_pa_parameters = _pa_result;
1320 
1321 #ifdef HAVE_AIQ_2_7
1322     if (_sa_result)
1323         aiq_stats_input.frame_sa_parameters = _sa_result;
1324 #endif
1325 
1326     if (_ae_handler->is_started()) {
1327 #ifdef USE_HIST_GRID_WEIGHTING
1328         if (XCAM_AE_METERING_MODE_WEIGHTED_WINDOW == _ae_handler->get_metering_mode ()) {
1329             ia_aiq_ae_results* ae_result = _ae_handler->get_result ();
1330 
1331             if (XCAM_RETURN_NO_ERROR != _ae_handler->set_hist_weight_grid (&(ae_result->weight_grid))) {
1332                 XCAM_LOG_ERROR ("ae handler set hist weight grid failed");
1333             }
1334         }
1335 #endif
1336         aiq_stats_input.frame_ae_parameters = _ae_handler->get_result ();
1337         //_ae_handler->dump_hist_weight_grid (aiq_stats_input.frame_ae_parameters->weight_grid);
1338     }
1339     //if (_awb_handler->is_started())
1340     //    aiq_stats_input.frame_awb_parameters = _awb_handler->get_result();
1341 
1342     if (!_adaptor->convert_statistics (stats->get_isp_stats(), &rgbs_grids, &af_grids)) {
1343         XCAM_LOG_WARNING ("ia isp adaptor convert 3a stats failed");
1344         return false;
1345     }
1346 
1347     if (XCAM_AE_METERING_MODE_WEIGHTED_WINDOW == _ae_handler->get_metering_mode ()) {
1348 #ifdef USE_RGBS_GRID_WEIGHTING
1349         if (XCAM_RETURN_NO_ERROR != _ae_handler->set_RGBS_weight_grid(&rgbs_grids)) {
1350             XCAM_LOG_ERROR ("ae handler update RGBS weighted statistic failed");
1351         }
1352         //_ae_handler->dump_RGBS_grid (*(aiq_stats_input.rgbs_grids));
1353 #endif
1354     }
1355     XCAM_LOG_DEBUG ("statistics grid info, width:%u, height:%u, blk_r:%u, blk_b:%u, blk_gr:%u, blk_gb:%u",
1356                     aiq_stats_input.rgbs_grids[0]->grid_width,
1357                     aiq_stats_input.rgbs_grids[0]->grid_height,
1358                     aiq_stats_input.rgbs_grids[0]->blocks_ptr->avg_r,
1359                     aiq_stats_input.rgbs_grids[0]->blocks_ptr->avg_b,
1360                     aiq_stats_input.rgbs_grids[0]->blocks_ptr->avg_gr,
1361                     aiq_stats_input.rgbs_grids[0]->blocks_ptr->avg_gb);
1362 
1363     if (ia_aiq_statistics_set(get_handle (), &aiq_stats_input) != ia_err_none) {
1364         XCAM_LOG_ERROR ("Aiq set statistic failed");
1365         return false;
1366     }
1367     return true;
1368 }
1369 
convert_color_effect(IspInputParameters & isp_input)1370 XCamReturn AiqCompositor::convert_color_effect (IspInputParameters &isp_input)
1371 {
1372     AiqCommonHandler *aiq_common = _common_handler.ptr();
1373 
1374     switch (aiq_common->get_color_effect()) {
1375     case XCAM_COLOR_EFFECT_NONE:
1376         isp_input.effects = ia_isp_effect_none;
1377         break;
1378     case XCAM_COLOR_EFFECT_SKY_BLUE:
1379         isp_input.effects = ia_isp_effect_sky_blue;
1380         break;
1381     case XCAM_COLOR_EFFECT_SKIN_WHITEN_LOW:
1382         isp_input.effects = ia_isp_effect_skin_whiten_low;
1383         break;
1384     case XCAM_COLOR_EFFECT_SKIN_WHITEN:
1385         isp_input.effects = ia_isp_effect_skin_whiten;
1386         break;
1387     case XCAM_COLOR_EFFECT_SKIN_WHITEN_HIGH:
1388         isp_input.effects = ia_isp_effect_skin_whiten_high;
1389         break;
1390     case XCAM_COLOR_EFFECT_SEPIA:
1391         isp_input.effects = ia_isp_effect_sepia;
1392         break;
1393     case XCAM_COLOR_EFFECT_NEGATIVE:
1394         isp_input.effects = ia_isp_effect_negative;
1395         break;
1396     case XCAM_COLOR_EFFECT_GRAYSCALE:
1397         isp_input.effects = ia_isp_effect_grayscale;
1398         break;
1399     default:
1400         isp_input.effects = ia_isp_effect_none;
1401         break;
1402     }
1403 
1404     return XCAM_RETURN_NO_ERROR;
1405 }
1406 
1407 XCamReturn
apply_gamma_table(struct atomisp_parameters * isp_param)1408 AiqCompositor::apply_gamma_table (struct atomisp_parameters *isp_param)
1409 {
1410     if (_common_handler->_params.is_manual_gamma) {
1411         int i;
1412 
1413         if (isp_param->r_gamma_table) {
1414             isp_param->r_gamma_table->vamem_type = 1; //IA_CSS_VAMEM_TYPE_2 = 1;
1415             for (i = 0; i < XCAM_GAMMA_TABLE_SIZE; ++i) {
1416                 // change from double to u0.12
1417                 isp_param->r_gamma_table->data.vamem_2[i] =
1418                     (uint32_t) (_common_handler->_params.r_gamma[i] * 4096.0);
1419             }
1420             isp_param->r_gamma_table->data.vamem_2[256] = 4091;
1421         }
1422 
1423         if (isp_param->g_gamma_table) {
1424             isp_param->g_gamma_table->vamem_type = 1; //IA_CSS_VAMEM_TYPE_2 = 1;
1425             for (i = 0; i < XCAM_GAMMA_TABLE_SIZE; ++i) {
1426                 // change from double to u0.12
1427                 isp_param->g_gamma_table->data.vamem_2[i] =
1428                     (uint32_t) (_common_handler->_params.g_gamma[i] * 4096.0);
1429             }
1430             isp_param->g_gamma_table->data.vamem_2[256] = 4091;
1431         }
1432 
1433         if (isp_param->b_gamma_table) {
1434             isp_param->b_gamma_table->vamem_type = 1; //IA_CSS_VAMEM_TYPE_2 = 1;
1435             for (i = 0; i < XCAM_GAMMA_TABLE_SIZE; ++i) {
1436                 // change from double to u0.12
1437                 isp_param->b_gamma_table->data.vamem_2[i] =
1438                     (uint32_t) (_common_handler->_params.b_gamma[i] * 4096.0);
1439             }
1440             isp_param->b_gamma_table->data.vamem_2[256] = 4091;
1441         }
1442     }
1443 
1444     return XCAM_RETURN_NO_ERROR;
1445 }
1446 
1447 XCamReturn
apply_night_mode(struct atomisp_parameters * isp_param)1448 AiqCompositor::apply_night_mode (struct atomisp_parameters *isp_param)
1449 {
1450     static const struct atomisp_cc_config night_yuv2rgb_cc_config = {
1451         10,
1452         {   1 << 10, 0, 0,  /* 1.0, 0, 0 */
1453             1 << 10, 0, 0,  /* 1.0, 0, 0 */
1454             1 << 10, 0, 0
1455         }
1456     }; /* 1.0, 0, 0 */
1457     static const struct atomisp_wb_config night_wb_config = {
1458         1,
1459         1 << 15, 1 << 15, 1 << 15, 1 << 15
1460     }; /* 1.0, 1.0, 1.0, 1.0*/
1461 
1462     if (isp_param->ctc_config)
1463         isp_param->ctc_config = NULL;
1464 
1465     *isp_param->wb_config = night_wb_config;
1466     *isp_param->yuv2rgb_cc_config = night_yuv2rgb_cc_config;
1467 
1468     return XCAM_RETURN_NO_ERROR;
1469 }
1470 
1471 double
calculate_value_by_factor(double factor,double min,double mid,double max)1472 AiqCompositor::calculate_value_by_factor (double factor, double min, double mid, double max)
1473 {
1474     XCAM_ASSERT (factor >= -1.0 && factor <= 1.0);
1475     XCAM_ASSERT (min <= mid && max >= mid);
1476 
1477     if (factor >= 0.0)
1478         return (mid * (1.0 - factor) + max * factor);
1479     else
1480         return (mid * (1.0 + factor) + min * (-factor));
1481 }
1482 
1483 XCamReturn
limit_nr_levels(struct atomisp_parameters * isp_param)1484 AiqCompositor::limit_nr_levels (struct atomisp_parameters *isp_param)
1485 {
1486 #define NR_MIN_FACOTR 0.1
1487 #define NR_MAX_FACOTR 6.0
1488 #define NR_MID_FACOTR 1.0
1489     SmartPtr<AiqCommonHandler> aiq_common = _common_handler;
1490 
1491     if (!XCAM_DOUBLE_EQUAL_AROUND (aiq_common->_params.nr_level, 0.0)) {
1492         double nr_factor;
1493         nr_factor = calculate_value_by_factor (
1494                         aiq_common->_params.nr_level, NR_MIN_FACOTR, NR_MID_FACOTR, NR_MAX_FACOTR);
1495         if (isp_param->nr_config) {
1496             isp_param->nr_config->bnr_gain =
1497                 XCAM_MIN (isp_param->nr_config->bnr_gain * nr_factor, 65535);
1498             isp_param->nr_config->ynr_gain =
1499                 XCAM_MIN (isp_param->nr_config->ynr_gain * nr_factor, 65535);
1500         }
1501         if (isp_param->cnr_config) {
1502             isp_param->cnr_config->sense_gain_vy =
1503                 XCAM_MIN (isp_param->cnr_config->sense_gain_vy * nr_factor, 8191);
1504             isp_param->cnr_config->sense_gain_vu =
1505                 XCAM_MIN (isp_param->cnr_config->sense_gain_vu * nr_factor, 8191);
1506             isp_param->cnr_config->sense_gain_vv =
1507                 XCAM_MIN (isp_param->cnr_config->sense_gain_vv * nr_factor, 8191);
1508             isp_param->cnr_config->sense_gain_hy =
1509                 XCAM_MIN (isp_param->cnr_config->sense_gain_hy * nr_factor, 8191);
1510             isp_param->cnr_config->sense_gain_hu =
1511                 XCAM_MIN (isp_param->cnr_config->sense_gain_hu * nr_factor, 8191);
1512             isp_param->cnr_config->sense_gain_hv =
1513                 XCAM_MIN (isp_param->cnr_config->sense_gain_hv * nr_factor, 8191);
1514         }
1515     }
1516 
1517     if (!XCAM_DOUBLE_EQUAL_AROUND (aiq_common->_params.tnr_level, 0.0)) {
1518         double tnr_factor;
1519         tnr_factor = calculate_value_by_factor (
1520                          aiq_common->_params.tnr_level, NR_MIN_FACOTR, NR_MID_FACOTR, NR_MAX_FACOTR);
1521         if (isp_param->tnr_config) {
1522             isp_param->tnr_config->gain =
1523                 XCAM_MIN (isp_param->tnr_config->gain * tnr_factor, 65535);
1524             if (XCAM_DOUBLE_EQUAL_AROUND (aiq_common->_params.tnr_level, 1.0)) {
1525                 isp_param->tnr_config->gain = 65535;
1526                 isp_param->tnr_config->threshold_y = 0;
1527                 isp_param->tnr_config->threshold_uv = 0;
1528             }
1529         }
1530         XCAM_LOG_DEBUG ("set TNR gain:%u", isp_param->tnr_config->gain);
1531     }
1532 
1533     return XCAM_RETURN_NO_ERROR;
1534 }
1535 
integrate(X3aResultList & results)1536 XCamReturn AiqCompositor::integrate (X3aResultList &results)
1537 {
1538     IspInputParameters isp_params;
1539     ia_aiq_pa_input_params pa_input;
1540     ia_aiq_pa_results *pa_result = NULL;
1541 #ifdef HAVE_AIQ_2_7
1542     ia_aiq_sa_input_params sa_input;
1543     ia_aiq_sa_results *sa_result = NULL;
1544 #endif
1545     ia_err ia_error = ia_err_none;
1546     ia_binary_data output;
1547     AiqAeHandler *aiq_ae = _ae_handler.ptr();
1548     AiqAwbHandler *aiq_awb = _awb_handler.ptr();
1549     AiqAfHandler *aiq_af = _af_handler.ptr();
1550     AiqCommonHandler *aiq_common = _common_handler.ptr();
1551     struct atomisp_parameters *isp_3a_result = NULL;
1552     SmartPtr<X3aResult> isp_results;
1553 
1554     XCAM_FAIL_RETURN (
1555         ERROR,
1556         aiq_ae && aiq_awb && aiq_af && aiq_common,
1557         XCAM_RETURN_ERROR_PARAM,
1558         "handlers are not AIQ inherited");
1559 
1560     xcam_mem_clear (pa_input);
1561 #ifndef HAVE_AIQ_2_7
1562     pa_input.frame_use = _frame_use;
1563     pa_input.sensor_frame_params = &_frame_params;
1564 #endif
1565     if (aiq_ae->is_started())
1566         pa_input.exposure_params = (aiq_ae->get_result ())->exposures[0].exposure;
1567     pa_input.color_gains = NULL;
1568 
1569     if (aiq_common->_params.enable_night_mode) {
1570         pa_input.awb_results = NULL;
1571         isp_params.effects = ia_isp_effect_grayscale;
1572     }
1573     else {
1574         pa_input.awb_results = aiq_awb->get_result ();
1575     }
1576 
1577     ia_error = ia_aiq_pa_run (_ia_handle, &pa_input, &pa_result);
1578     if (ia_error != ia_err_none) {
1579         XCAM_LOG_WARNING ("AIQ pa run failed"); // but not return error
1580     }
1581     _pa_result = pa_result;
1582 
1583     if (aiq_awb->get_mode_unlock () == XCAM_AWB_MODE_MANUAL) {
1584         if (XCAM_DOUBLE_EQUAL_AROUND (aiq_awb->_params.gr_gain, 0.0) ||
1585                 XCAM_DOUBLE_EQUAL_AROUND (aiq_awb->_params.r_gain, 0.0)  ||
1586                 XCAM_DOUBLE_EQUAL_AROUND (aiq_awb->_params.b_gain, 0.0)  ||
1587                 XCAM_DOUBLE_EQUAL_AROUND (aiq_awb->_params.gb_gain, 0.0)) {
1588             XCAM_LOG_DEBUG ("Zero gain would cause ISP division fatal error");
1589         }
1590         else {
1591 #ifdef HAVE_AIQ_2_7
1592             _pa_result->color_gains.gr = aiq_awb->_params.gr_gain;
1593             _pa_result->color_gains.r = aiq_awb->_params.r_gain;
1594             _pa_result->color_gains.b = aiq_awb->_params.b_gain;
1595             _pa_result->color_gains.gb = aiq_awb->_params.gb_gain;
1596 #else
1597             _pa_result->color_gains[0] = aiq_awb->_params.gr_gain;
1598             _pa_result->color_gains[1] = aiq_awb->_params.r_gain;
1599             _pa_result->color_gains[2] = aiq_awb->_params.b_gain;
1600             _pa_result->color_gains[3] = aiq_awb->_params.gb_gain;
1601 #endif
1602         }
1603     }
1604 
1605 #ifdef HAVE_AIQ_2_7
1606     xcam_mem_clear (sa_input);
1607     sa_input.frame_use = _frame_use;
1608     sa_input.sensor_frame_params = &_frame_params;
1609     if (aiq_common->_params.enable_night_mode) {
1610         sa_input.awb_results = NULL;
1611     }
1612     else {
1613         sa_input.awb_results = aiq_awb->get_result ();
1614     }
1615 
1616     ia_error = ia_aiq_sa_run (_ia_handle, &sa_input, &sa_result);
1617     if (ia_error != ia_err_none) {
1618         XCAM_LOG_WARNING ("AIQ sa run failed"); // but not return error
1619     }
1620     _sa_result = sa_result;
1621 #endif
1622 
1623     isp_params.frame_use = _frame_use;
1624     isp_params.awb_results = aiq_awb->get_result ();
1625     if (aiq_ae->is_started())
1626         isp_params.exposure_results = (aiq_ae->get_result ())->exposures[0].exposure;
1627     isp_params.gbce_results = aiq_common->get_gbce_result ();
1628     isp_params.sensor_frame_params = &_frame_params;
1629     isp_params.pa_results = pa_result;
1630 #ifdef HAVE_AIQ_2_7
1631     isp_params.sa_results = sa_result;
1632 #endif
1633 
1634     isp_params.manual_brightness = (int8_t)(aiq_common->get_brightness_unlock() * 128.0);
1635     isp_params.manual_contrast = (int8_t)(aiq_common->get_contrast_unlock() * 128.0);
1636     isp_params.manual_saturation = (int8_t)(aiq_common->get_saturation_unlock() * 128.0);
1637     isp_params.manual_hue = (int8_t)(aiq_common->get_hue_unlock() * 128.0);
1638     isp_params.manual_sharpness = (int8_t)(aiq_common->get_sharpness_unlock() * 128.0);
1639     isp_params.manual_nr_level = (int8_t)(aiq_common->get_nr_level_unlock() * 128.0);
1640 
1641     convert_color_effect(isp_params);
1642 
1643     xcam_mem_clear (output);
1644     if (!_adaptor->run (&isp_params, &output)) {
1645         XCAM_LOG_ERROR("Aiq to isp adaptor running failed");
1646         return XCAM_RETURN_ERROR_ISP;
1647     }
1648     isp_3a_result = ((struct atomisp_parameters *)output.data);
1649     apply_gamma_table (isp_3a_result);
1650     limit_nr_levels (isp_3a_result);
1651     if (aiq_common->_params.enable_night_mode)
1652     {
1653         apply_night_mode (isp_3a_result);
1654     }
1655 
1656     isp_results = generate_3a_configs (isp_3a_result);
1657     results.push_back (isp_results);
1658     return XCAM_RETURN_NO_ERROR;
1659 }
1660 
1661 SmartPtr<X3aResult>
generate_3a_configs(struct atomisp_parameters * parameters)1662 AiqCompositor::generate_3a_configs (struct atomisp_parameters *parameters)
1663 {
1664     SmartPtr<X3aResult> ret;
1665 
1666     X3aAtomIspParametersResult *x3a_result =
1667         new X3aAtomIspParametersResult (XCAM_IMAGE_PROCESS_ONCE);
1668     x3a_result->set_isp_config (*parameters);
1669     ret = x3a_result;
1670     return ret;
1671 }
1672 
1673 void
set_ae_handler(SmartPtr<AiqAeHandler> & handler)1674 AiqCompositor::set_ae_handler (SmartPtr<AiqAeHandler> &handler)
1675 {
1676     XCAM_ASSERT (!_ae_handler.ptr());
1677     _ae_handler = handler;
1678 }
1679 
1680 void
set_awb_handler(SmartPtr<AiqAwbHandler> & handler)1681 AiqCompositor::set_awb_handler (SmartPtr<AiqAwbHandler> &handler)
1682 {
1683     XCAM_ASSERT (!_awb_handler.ptr());
1684     _awb_handler = handler;
1685 }
1686 
1687 void
set_af_handler(SmartPtr<AiqAfHandler> & handler)1688 AiqCompositor::set_af_handler (SmartPtr<AiqAfHandler> &handler)
1689 {
1690     XCAM_ASSERT (!_af_handler.ptr());
1691     _af_handler = handler;
1692 }
1693 
1694 void
set_common_handler(SmartPtr<AiqCommonHandler> & handler)1695 AiqCompositor::set_common_handler (SmartPtr<AiqCommonHandler> &handler)
1696 {
1697     XCAM_ASSERT (!_common_handler.ptr());
1698     _common_handler = handler;
1699 }
1700 
1701 
1702 };
1703