| /* |
| * x3a_analyzer_simple.cpp - a simple 3a analyzer |
| * |
| * Copyright (c) 2015 Intel Corporation |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| * |
| * Author: Wind Yuan <[email protected]> |
| */ |
| |
| #include "x3a_analyzer_simple.h" |
| |
| namespace XCam { |
| |
| #define SIMPLE_MIN_TARGET_EXPOSURE_TIME 5000 //5ms |
| #define SIMPLE_MAX_TARGET_EXPOSURE_TIME 33000 //33ms |
| #define SIMPLE_DEFAULT_BLACK_LEVEL 0.05 |
| |
| class SimpleAeHandler |
| : public AeHandler |
| { |
| public: |
| SimpleAeHandler (X3aAnalyzerSimple *analyzer) |
| : _analyzer (analyzer) |
| {} |
| ~SimpleAeHandler () {} |
| |
| virtual XCamReturn analyze (X3aResultList &output) { |
| return _analyzer->analyze_ae (output); |
| } |
| private: |
| X3aAnalyzerSimple *_analyzer; |
| }; |
| |
| class SimpleAwbHandler |
| : public AwbHandler |
| { |
| public: |
| SimpleAwbHandler (X3aAnalyzerSimple *analyzer) |
| : _analyzer (analyzer) |
| {} |
| ~SimpleAwbHandler () {} |
| |
| virtual XCamReturn analyze (X3aResultList &output) { |
| return _analyzer->analyze_awb (output); |
| } |
| private: |
| X3aAnalyzerSimple *_analyzer; |
| |
| }; |
| |
| class SimpleAfHandler |
| : public AfHandler |
| { |
| public: |
| SimpleAfHandler (X3aAnalyzerSimple *analyzer) |
| : _analyzer (analyzer) |
| {} |
| ~SimpleAfHandler () {} |
| |
| virtual XCamReturn analyze (X3aResultList &output) { |
| return _analyzer->analyze_af (output); |
| } |
| |
| private: |
| X3aAnalyzerSimple *_analyzer; |
| }; |
| |
| class SimpleCommonHandler |
| : public CommonHandler |
| { |
| public: |
| SimpleCommonHandler (X3aAnalyzerSimple *analyzer) |
| : _analyzer (analyzer) |
| {} |
| ~SimpleCommonHandler () {} |
| |
| virtual XCamReturn analyze (X3aResultList &output) { |
| XCAM_UNUSED (output); |
| return XCAM_RETURN_NO_ERROR; |
| } |
| |
| private: |
| X3aAnalyzerSimple *_analyzer; |
| }; |
| |
| X3aAnalyzerSimple::X3aAnalyzerSimple () |
| : X3aAnalyzer ("X3aAnalyzerSimple") |
| , _last_target_exposure ((double)SIMPLE_MIN_TARGET_EXPOSURE_TIME) |
| , _is_ae_started (false) |
| , _ae_calculation_interval (0) |
| { |
| } |
| |
| X3aAnalyzerSimple::~X3aAnalyzerSimple () |
| { |
| } |
| |
| SmartPtr<AeHandler> |
| X3aAnalyzerSimple::create_ae_handler () |
| { |
| SimpleAeHandler *handler = new SimpleAeHandler (this); |
| return handler; |
| } |
| |
| SmartPtr<AwbHandler> |
| X3aAnalyzerSimple::create_awb_handler () |
| { |
| SimpleAwbHandler *handler = new SimpleAwbHandler (this); |
| return handler; |
| } |
| |
| SmartPtr<AfHandler> |
| X3aAnalyzerSimple::create_af_handler () |
| { |
| SimpleAfHandler *handler = new SimpleAfHandler (this); |
| return handler; |
| } |
| |
| SmartPtr<CommonHandler> |
| X3aAnalyzerSimple::create_common_handler () |
| { |
| SimpleCommonHandler *handler = new SimpleCommonHandler (this); |
| return handler; |
| } |
| |
| XCamReturn |
| X3aAnalyzerSimple::configure_3a () |
| { |
| _is_ae_started = false; |
| _ae_calculation_interval = 0; |
| return XCAM_RETURN_NO_ERROR; |
| } |
| |
| XCamReturn |
| X3aAnalyzerSimple::pre_3a_analyze (SmartPtr<X3aStats> &stats) |
| { |
| _current_stats = stats; |
| return XCAM_RETURN_NO_ERROR; |
| } |
| |
| XCamReturn |
| X3aAnalyzerSimple::post_3a_analyze (X3aResultList &results) |
| { |
| _current_stats.release (); |
| |
| XCam3aResultBlackLevel black_level; |
| SmartPtr<X3aBlackLevelResult> bl_result = new X3aBlackLevelResult (XCAM_3A_RESULT_BLACK_LEVEL); |
| |
| xcam_mem_clear (black_level); |
| black_level.r_level = SIMPLE_DEFAULT_BLACK_LEVEL; |
| black_level.gr_level = SIMPLE_DEFAULT_BLACK_LEVEL; |
| black_level.gb_level = SIMPLE_DEFAULT_BLACK_LEVEL; |
| black_level.b_level = SIMPLE_DEFAULT_BLACK_LEVEL; |
| bl_result->set_standard_result (black_level); |
| results.push_back (bl_result); |
| |
| return XCAM_RETURN_NO_ERROR; |
| } |
| |
| XCamReturn |
| X3aAnalyzerSimple::analyze_awb (X3aResultList &output) |
| { |
| const XCam3AStats *stats = _current_stats->get_stats (); |
| double sum_r = 0.0, sum_gr = 0.0, sum_gb = 0.0, sum_b = 0.0; |
| double avg_r = 0.0, avg_gr = 0.0, avg_gb = 0.0, avg_b = 0.0; |
| double target_avg = 0.0; |
| XCam3aResultWhiteBalance wb; |
| |
| xcam_mem_clear (wb); |
| XCAM_ASSERT (stats); |
| |
| // calculate avg r, gr, gb, b |
| for (uint32_t i = 0; i < stats->info.height; ++i) |
| for (uint32_t j = 0; j < stats->info.width; ++j) { |
| sum_r += (double)(stats->stats[i * stats->info.aligned_width + j].avg_r); |
| sum_gr += (double)(stats->stats[i * stats->info.aligned_width + j].avg_gr); |
| sum_gb += (double)(stats->stats[i * stats->info.aligned_width + j].avg_gb); |
| sum_b += (double)(stats->stats[i * stats->info.aligned_width + j].avg_b); |
| } |
| |
| avg_r = sum_r / (stats->info.width * stats->info.height); |
| avg_gr = sum_gr / (stats->info.width * stats->info.height); |
| avg_gb = sum_gb / (stats->info.width * stats->info.height); |
| avg_b = sum_b / (stats->info.width * stats->info.height); |
| |
| target_avg = (avg_gr + avg_gb) / 2; |
| wb.r_gain = target_avg / avg_r; |
| wb.b_gain = target_avg / avg_b; |
| wb.gr_gain = 1.0; |
| wb.gb_gain = 1.0; |
| |
| SmartPtr<X3aWhiteBalanceResult> result = new X3aWhiteBalanceResult (XCAM_3A_RESULT_WHITE_BALANCE); |
| result->set_standard_result (wb); |
| output.push_back (result); |
| |
| XCAM_LOG_DEBUG ("X3aAnalyzerSimple analyze awb, r:%f, gr:%f, gb:%f, b:%f", |
| wb.r_gain, wb.gr_gain, wb.gb_gain, wb.b_gain); |
| |
| return XCAM_RETURN_NO_ERROR; |
| } |
| |
| XCamReturn |
| X3aAnalyzerSimple::analyze_ae (X3aResultList &output) |
| { |
| static const uint32_t expect_y_mean = 110; |
| |
| const XCam3AStats *stats = _current_stats->get_stats (); |
| XCAM_FAIL_RETURN( |
| WARNING, |
| stats, |
| XCAM_RETURN_ERROR_UNKNOWN, |
| "failed to get XCam3AStats"); |
| |
| double sum_y = 0.0; |
| double target_exposure = 1.0; |
| SmartPtr<X3aExposureResult> result = new X3aExposureResult (XCAM_3A_RESULT_EXPOSURE); |
| XCam3aResultExposure exposure; |
| |
| xcam_mem_clear (exposure); |
| exposure.digital_gain = 1.0; |
| |
| if (!_is_ae_started) { |
| _last_target_exposure = SIMPLE_MIN_TARGET_EXPOSURE_TIME; |
| exposure.exposure_time = _last_target_exposure; |
| exposure.analog_gain = 1.0; |
| |
| result->set_standard_result (exposure); |
| output.push_back (result); |
| _is_ae_started = true; |
| return XCAM_RETURN_NO_ERROR; |
| } |
| |
| if (_ae_calculation_interval % 10 == 0) { |
| for (uint32_t i = 0; i < stats->info.height; ++i) |
| for (uint32_t j = 0; j < stats->info.width; ++j) { |
| sum_y += (double)(stats->stats[i * stats->info.aligned_width + j].avg_y); |
| } |
| sum_y /= (stats->info.width * stats->info.height); |
| target_exposure = (expect_y_mean / sum_y) * _last_target_exposure; |
| target_exposure = XCAM_MAX (target_exposure, SIMPLE_MIN_TARGET_EXPOSURE_TIME); |
| |
| if (target_exposure > SIMPLE_MAX_TARGET_EXPOSURE_TIME * 255) |
| target_exposure = SIMPLE_MAX_TARGET_EXPOSURE_TIME * 255; |
| |
| if (target_exposure > SIMPLE_MAX_TARGET_EXPOSURE_TIME) { |
| exposure.exposure_time = SIMPLE_MAX_TARGET_EXPOSURE_TIME; |
| exposure.analog_gain = target_exposure / exposure.exposure_time; |
| } else { |
| exposure.exposure_time = target_exposure; |
| exposure.analog_gain = 1.0; |
| } |
| |
| result->set_standard_result (exposure); |
| output.push_back (result); |
| _last_target_exposure = target_exposure; |
| } |
| |
| _ae_calculation_interval++; |
| |
| return XCAM_RETURN_NO_ERROR; |
| } |
| |
| XCamReturn X3aAnalyzerSimple::analyze_af (X3aResultList &output) |
| { |
| XCAM_UNUSED (output); |
| return XCAM_RETURN_NO_ERROR; |
| } |
| |
| }; |