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@intel.com> 19 */ 20 21#include "x3a_analyzer_simple.h" 22 23namespace 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 29class SimpleAeHandler 30 : public AeHandler 31{ 32public: 33 SimpleAeHandler (X3aAnalyzerSimple *analyzer) 34 : _analyzer (analyzer) 35 {} 36 ~SimpleAeHandler () {} 37 38 virtual XCamReturn analyze (X3aResultList &output) { 39 return _analyzer->analyze_ae (output); 40 } 41private: 42 X3aAnalyzerSimple *_analyzer; 43}; 44 45class SimpleAwbHandler 46 : public AwbHandler 47{ 48public: 49 SimpleAwbHandler (X3aAnalyzerSimple *analyzer) 50 : _analyzer (analyzer) 51 {} 52 ~SimpleAwbHandler () {} 53 54 virtual XCamReturn analyze (X3aResultList &output) { 55 return _analyzer->analyze_awb (output); 56 } 57private: 58 X3aAnalyzerSimple *_analyzer; 59 60}; 61 62class SimpleAfHandler 63 : public AfHandler 64{ 65public: 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 75private: 76 X3aAnalyzerSimple *_analyzer; 77}; 78 79class SimpleCommonHandler 80 : public CommonHandler 81{ 82public: 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 93private: 94 X3aAnalyzerSimple *_analyzer; 95}; 96 97X3aAnalyzerSimple::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 105X3aAnalyzerSimple::~X3aAnalyzerSimple () 106{ 107} 108 109SmartPtr<AeHandler> 110X3aAnalyzerSimple::create_ae_handler () 111{ 112 SimpleAeHandler *handler = new SimpleAeHandler (this); 113 return handler; 114} 115 116SmartPtr<AwbHandler> 117X3aAnalyzerSimple::create_awb_handler () 118{ 119 SimpleAwbHandler *handler = new SimpleAwbHandler (this); 120 return handler; 121} 122 123SmartPtr<AfHandler> 124X3aAnalyzerSimple::create_af_handler () 125{ 126 SimpleAfHandler *handler = new SimpleAfHandler (this); 127 return handler; 128} 129 130SmartPtr<CommonHandler> 131X3aAnalyzerSimple::create_common_handler () 132{ 133 SimpleCommonHandler *handler = new SimpleCommonHandler (this); 134 return handler; 135} 136 137XCamReturn 138X3aAnalyzerSimple::configure_3a () 139{ 140 _is_ae_started = false; 141 _ae_calculation_interval = 0; 142 return XCAM_RETURN_NO_ERROR; 143} 144 145XCamReturn 146X3aAnalyzerSimple::pre_3a_analyze (SmartPtr<X3aStats> &stats) 147{ 148 _current_stats = stats; 149 return XCAM_RETURN_NO_ERROR; 150} 151 152XCamReturn 153X3aAnalyzerSimple::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 171XCamReturn 172X3aAnalyzerSimple::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 213XCamReturn 214X3aAnalyzerSimple::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 274XCamReturn X3aAnalyzerSimple::analyze_af (X3aResultList &output) 275{ 276 XCAM_UNUSED (output); 277 return XCAM_RETURN_NO_ERROR; 278} 279 280}; 281