1 /* 2 * x3a_analyzer_simple.cpp - a simple 3a analyzer 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 (at) intel.com> 19 */ 20 21 #include "x3a_analyzer_simple.h" 22 23 namespace XCam { 24 25 #define SIMPLE_MIN_TARGET_EXPOSURE_TIME 5000 //5ms 26 #define SIMPLE_MAX_TARGET_EXPOSURE_TIME 33000 //33ms 27 #define SIMPLE_DEFAULT_BLACK_LEVEL 0.05 28 29 class SimpleAeHandler 30 : public AeHandler 31 { 32 public: 33 SimpleAeHandler (X3aAnalyzerSimple *analyzer) 34 : _analyzer (analyzer) 35 {} 36 ~SimpleAeHandler () {} 37 38 virtual XCamReturn analyze (X3aResultList &output) { 39 return _analyzer->analyze_ae (output); 40 } 41 private: 42 X3aAnalyzerSimple *_analyzer; 43 }; 44 45 class SimpleAwbHandler 46 : public AwbHandler 47 { 48 public: 49 SimpleAwbHandler (X3aAnalyzerSimple *analyzer) 50 : _analyzer (analyzer) 51 {} 52 ~SimpleAwbHandler () {} 53 54 virtual XCamReturn analyze (X3aResultList &output) { 55 return _analyzer->analyze_awb (output); 56 } 57 private: 58 X3aAnalyzerSimple *_analyzer; 59 60 }; 61 62 class SimpleAfHandler 63 : public AfHandler 64 { 65 public: 66 SimpleAfHandler (X3aAnalyzerSimple *analyzer) 67 : _analyzer (analyzer) 68 {} 69 ~SimpleAfHandler () {} 70 71 virtual XCamReturn analyze (X3aResultList &output) { 72 return _analyzer->analyze_af (output); 73 } 74 75 private: 76 X3aAnalyzerSimple *_analyzer; 77 }; 78 79 class SimpleCommonHandler 80 : public CommonHandler 81 { 82 public: 83 SimpleCommonHandler (X3aAnalyzerSimple *analyzer) 84 : _analyzer (analyzer) 85 {} 86 ~SimpleCommonHandler () {} 87 88 virtual XCamReturn analyze (X3aResultList &output) { 89 XCAM_UNUSED (output); 90 return XCAM_RETURN_NO_ERROR; 91 } 92 93 private: 94 X3aAnalyzerSimple *_analyzer; 95 }; 96 97 X3aAnalyzerSimple::X3aAnalyzerSimple () 98 : X3aAnalyzer ("X3aAnalyzerSimple") 99 , _last_target_exposure ((double)SIMPLE_MIN_TARGET_EXPOSURE_TIME) 100 , _is_ae_started (false) 101 , _ae_calculation_interval (0) 102 { 103 } 104 105 X3aAnalyzerSimple::~X3aAnalyzerSimple () 106 { 107 } 108 109 SmartPtr<AeHandler> 110 X3aAnalyzerSimple::create_ae_handler () 111 { 112 SimpleAeHandler *handler = new SimpleAeHandler (this); 113 return handler; 114 } 115 116 SmartPtr<AwbHandler> 117 X3aAnalyzerSimple::create_awb_handler () 118 { 119 SimpleAwbHandler *handler = new SimpleAwbHandler (this); 120 return handler; 121 } 122 123 SmartPtr<AfHandler> 124 X3aAnalyzerSimple::create_af_handler () 125 { 126 SimpleAfHandler *handler = new SimpleAfHandler (this); 127 return handler; 128 } 129 130 SmartPtr<CommonHandler> 131 X3aAnalyzerSimple::create_common_handler () 132 { 133 SimpleCommonHandler *handler = new SimpleCommonHandler (this); 134 return handler; 135 } 136 137 XCamReturn 138 X3aAnalyzerSimple::configure_3a () 139 { 140 _is_ae_started = false; 141 _ae_calculation_interval = 0; 142 return XCAM_RETURN_NO_ERROR; 143 } 144 145 XCamReturn 146 X3aAnalyzerSimple::pre_3a_analyze (SmartPtr<X3aStats> &stats) 147 { 148 _current_stats = stats; 149 return XCAM_RETURN_NO_ERROR; 150 } 151 152 XCamReturn 153 X3aAnalyzerSimple::post_3a_analyze (X3aResultList &results) 154 { 155 _current_stats.release (); 156 157 XCam3aResultBlackLevel black_level; 158 SmartPtr<X3aBlackLevelResult> bl_result = new X3aBlackLevelResult (XCAM_3A_RESULT_BLACK_LEVEL); 159 160 xcam_mem_clear (black_level); 161 black_level.r_level = SIMPLE_DEFAULT_BLACK_LEVEL; 162 black_level.gr_level = SIMPLE_DEFAULT_BLACK_LEVEL; 163 black_level.gb_level = SIMPLE_DEFAULT_BLACK_LEVEL; 164 black_level.b_level = SIMPLE_DEFAULT_BLACK_LEVEL; 165 bl_result->set_standard_result (black_level); 166 results.push_back (bl_result); 167 168 return XCAM_RETURN_NO_ERROR; 169 } 170 171 XCamReturn 172 X3aAnalyzerSimple::analyze_awb (X3aResultList &output) 173 { 174 const XCam3AStats *stats = _current_stats->get_stats (); 175 double sum_r = 0.0, sum_gr = 0.0, sum_gb = 0.0, sum_b = 0.0; 176 double avg_r = 0.0, avg_gr = 0.0, avg_gb = 0.0, avg_b = 0.0; 177 double target_avg = 0.0; 178 XCam3aResultWhiteBalance wb; 179 180 xcam_mem_clear (wb); 181 XCAM_ASSERT (stats); 182 183 // calculate avg r, gr, gb, b 184 for (uint32_t i = 0; i < stats->info.height; ++i) 185 for (uint32_t j = 0; j < stats->info.width; ++j) { 186 sum_r += (double)(stats->stats[i * stats->info.aligned_width + j].avg_r); 187 sum_gr += (double)(stats->stats[i * stats->info.aligned_width + j].avg_gr); 188 sum_gb += (double)(stats->stats[i * stats->info.aligned_width + j].avg_gb); 189 sum_b += (double)(stats->stats[i * stats->info.aligned_width + j].avg_b); 190 } 191 192 avg_r = sum_r / (stats->info.width * stats->info.height); 193 avg_gr = sum_gr / (stats->info.width * stats->info.height); 194 avg_gb = sum_gb / (stats->info.width * stats->info.height); 195 avg_b = sum_b / (stats->info.width * stats->info.height); 196 197 target_avg = (avg_gr + avg_gb) / 2; 198 wb.r_gain = target_avg / avg_r; 199 wb.b_gain = target_avg / avg_b; 200 wb.gr_gain = 1.0; 201 wb.gb_gain = 1.0; 202 203 SmartPtr<X3aWhiteBalanceResult> result = new X3aWhiteBalanceResult (XCAM_3A_RESULT_WHITE_BALANCE); 204 result->set_standard_result (wb); 205 output.push_back (result); 206 207 XCAM_LOG_DEBUG ("X3aAnalyzerSimple analyze awb, r:%f, gr:%f, gb:%f, b:%f", 208 wb.r_gain, wb.gr_gain, wb.gb_gain, wb.b_gain); 209 210 return XCAM_RETURN_NO_ERROR; 211 } 212 213 XCamReturn 214 X3aAnalyzerSimple::analyze_ae (X3aResultList &output) 215 { 216 static const uint32_t expect_y_mean = 110; 217 218 const XCam3AStats *stats = _current_stats->get_stats (); 219 XCAM_FAIL_RETURN( 220 WARNING, 221 stats, 222 XCAM_RETURN_ERROR_UNKNOWN, 223 "failed to get XCam3AStats"); 224 225 double sum_y = 0.0; 226 double target_exposure = 1.0; 227 SmartPtr<X3aExposureResult> result = new X3aExposureResult (XCAM_3A_RESULT_EXPOSURE); 228 XCam3aResultExposure exposure; 229 230 xcam_mem_clear (exposure); 231 exposure.digital_gain = 1.0; 232 233 if (!_is_ae_started) { 234 _last_target_exposure = SIMPLE_MIN_TARGET_EXPOSURE_TIME; 235 exposure.exposure_time = _last_target_exposure; 236 exposure.analog_gain = 1.0; 237 238 result->set_standard_result (exposure); 239 output.push_back (result); 240 _is_ae_started = true; 241 return XCAM_RETURN_NO_ERROR; 242 } 243 244 if (_ae_calculation_interval % 10 == 0) { 245 for (uint32_t i = 0; i < stats->info.height; ++i) 246 for (uint32_t j = 0; j < stats->info.width; ++j) { 247 sum_y += (double)(stats->stats[i * stats->info.aligned_width + j].avg_y); 248 } 249 sum_y /= (stats->info.width * stats->info.height); 250 target_exposure = (expect_y_mean / sum_y) * _last_target_exposure; 251 target_exposure = XCAM_MAX (target_exposure, SIMPLE_MIN_TARGET_EXPOSURE_TIME); 252 253 if (target_exposure > SIMPLE_MAX_TARGET_EXPOSURE_TIME * 255) 254 target_exposure = SIMPLE_MAX_TARGET_EXPOSURE_TIME * 255; 255 256 if (target_exposure > SIMPLE_MAX_TARGET_EXPOSURE_TIME) { 257 exposure.exposure_time = SIMPLE_MAX_TARGET_EXPOSURE_TIME; 258 exposure.analog_gain = target_exposure / exposure.exposure_time; 259 } else { 260 exposure.exposure_time = target_exposure; 261 exposure.analog_gain = 1.0; 262 } 263 264 result->set_standard_result (exposure); 265 output.push_back (result); 266 _last_target_exposure = target_exposure; 267 } 268 269 _ae_calculation_interval++; 270 271 return XCAM_RETURN_NO_ERROR; 272 } 273 274 XCamReturn X3aAnalyzerSimple::analyze_af (X3aResultList &output) 275 { 276 XCAM_UNUSED (output); 277 return XCAM_RETURN_NO_ERROR; 278 } 279 280 }; 281