| /* |
| * aiq_wrapper.cpp - aiq wrapper: |
| * |
| * 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 <base/xcam_3a_description.h> |
| #include <xcam_std.h> |
| #include "x3a_analyzer_aiq.h" |
| #include "x3a_statistics_queue.h" |
| #include "aiq3a_utils.h" |
| #include "x3a_result_factory.h" |
| #include "x3a_analyze_tuner.h" |
| |
| #define DEFAULT_AIQ_CPF_FILE "/etc/atomisp/imx185.cpf" |
| |
| |
| using namespace XCam; |
| |
| #define AIQ_CONTEXT_CAST(context) ((XCam3AAiqContext*)(context)) |
| |
| class XCam3AAiqContext |
| : public AnalyzerCallback |
| { |
| public: |
| XCam3AAiqContext (); |
| ~XCam3AAiqContext (); |
| bool setup_analyzer (struct atomisp_sensor_mode_data &sensor_mode_data, const char *cpf); |
| void set_size (uint32_t width, uint32_t height); |
| bool setup_stats_pool (uint32_t bit_depth = 8); |
| bool is_stats_pool_ready () const { |
| return (_stats_pool.ptr () ? true : false); |
| } |
| SmartPtr<X3aAnalyzeTuner> &get_analyzer () { |
| return _analyzer; |
| } |
| |
| SmartPtr<X3aIspStatistics> get_stats_buffer (); |
| uint32_t get_results (X3aResultList &results); |
| |
| // derive from AnalyzerCallback |
| virtual void x3a_calculation_done (XAnalyzer *analyzer, X3aResultList &results); |
| void update_brightness_result(XCamCommonParam *params); |
| |
| private: |
| XCAM_DEAD_COPY (XCam3AAiqContext); |
| |
| private: |
| // members |
| SmartPtr<X3aAnalyzeTuner> _analyzer; |
| SmartPtr<X3aStatisticsQueue> _stats_pool; |
| uint32_t _video_width; |
| uint32_t _video_height; |
| |
| Mutex _result_mutex; |
| X3aResultList _results; |
| double _brightness_level; |
| }; |
| |
| XCam3AAiqContext::XCam3AAiqContext () |
| : _video_width (0) |
| , _video_height (0) |
| , _brightness_level(0) |
| { |
| } |
| |
| XCam3AAiqContext::~XCam3AAiqContext () |
| { |
| _analyzer->stop (); |
| _analyzer->deinit (); |
| } |
| |
| bool |
| XCam3AAiqContext::setup_analyzer (struct atomisp_sensor_mode_data &sensor_mode_data, const char *cpf) |
| { |
| XCAM_ASSERT (!_analyzer.ptr ()); |
| SmartPtr<X3aAnalyzer> aiq_analyzer = new X3aAnalyzerAiq (sensor_mode_data, cpf); |
| XCAM_ASSERT (aiq_analyzer.ptr ()); |
| |
| _analyzer = new X3aAnalyzeTuner (); |
| XCAM_ASSERT (_analyzer.ptr ()); |
| |
| _analyzer->set_analyzer (aiq_analyzer); |
| _analyzer->set_results_callback (this); |
| return true; |
| } |
| |
| void |
| XCam3AAiqContext::set_size (uint32_t width, uint32_t height) |
| { |
| _video_width = width; |
| _video_height = height; |
| } |
| |
| bool |
| XCam3AAiqContext::setup_stats_pool (uint32_t bit_depth) |
| { |
| VideoBufferInfo info; |
| info.init (XCAM_PIX_FMT_SGRBG16, _video_width, _video_height); |
| |
| _stats_pool = new X3aStatisticsQueue; |
| XCAM_ASSERT (_stats_pool.ptr ()); |
| |
| _stats_pool->set_bit_depth (bit_depth); |
| XCAM_FAIL_RETURN ( |
| WARNING, |
| _stats_pool->set_video_info (info), |
| false, |
| "3a stats set video info failed"); |
| |
| |
| if (!_stats_pool->reserve (6)) { |
| XCAM_LOG_WARNING ("init_3a_stats_pool failed to reserve stats buffer."); |
| return false; |
| } |
| |
| return true; |
| } |
| |
| SmartPtr<X3aIspStatistics> |
| XCam3AAiqContext::get_stats_buffer () |
| { |
| SmartPtr<X3aIspStatistics> new_stats = |
| _stats_pool->get_buffer (_stats_pool).dynamic_cast_ptr<X3aIspStatistics> (); |
| |
| XCAM_FAIL_RETURN ( |
| WARNING, |
| new_stats.ptr (), |
| NULL, |
| "get isp stats buffer failed"); |
| |
| return new_stats; |
| } |
| |
| |
| void |
| XCam3AAiqContext::x3a_calculation_done (XAnalyzer *analyzer, X3aResultList &results) |
| { |
| XCAM_UNUSED (analyzer); |
| SmartLock locker (_result_mutex); |
| _results.insert (_results.end (), results.begin (), results.end ()); |
| } |
| |
| void |
| XCam3AAiqContext::update_brightness_result(XCamCommonParam *params) |
| { |
| if( params->brightness == _brightness_level) |
| return; |
| _brightness_level = params->brightness; |
| |
| XCam3aResultBrightness xcam3a_brightness_result; |
| xcam_mem_clear (xcam3a_brightness_result); |
| xcam3a_brightness_result.head.type = XCAM_3A_RESULT_BRIGHTNESS; |
| xcam3a_brightness_result.head.process_type = XCAM_IMAGE_PROCESS_ALWAYS; |
| xcam3a_brightness_result.head.version = XCAM_VERSION; |
| xcam3a_brightness_result.brightness_level = _brightness_level; |
| |
| SmartPtr<X3aResult> brightness_result = |
| X3aResultFactory::instance ()->create_3a_result ((XCam3aResultHead*)&xcam3a_brightness_result); |
| _results.push_back(brightness_result); |
| } |
| |
| uint32_t |
| XCam3AAiqContext::get_results (X3aResultList &results) |
| { |
| uint32_t size = 0; |
| |
| SmartLock locker (_result_mutex); |
| |
| results.assign (_results.begin (), _results.end ()); |
| size = _results.size (); |
| _results.clear (); |
| |
| return size; |
| } |
| |
| static SmartPtr<X3aAnalyzeTuner> |
| get_analyzer (XCam3AContext *context) |
| { |
| XCam3AAiqContext *aiq_context = AIQ_CONTEXT_CAST (context); |
| if (!aiq_context) |
| return NULL; |
| |
| return aiq_context->get_analyzer (); |
| } |
| |
| static XCamReturn |
| xcam_create_context (XCam3AContext **context) |
| { |
| XCAM_ASSERT (context); |
| XCam3AAiqContext *aiq_context = new XCam3AAiqContext (); |
| *context = ((XCam3AContext*)(aiq_context)); |
| return XCAM_RETURN_NO_ERROR; |
| } |
| |
| static XCamReturn |
| xcam_destroy_context (XCam3AContext *context) |
| { |
| XCam3AAiqContext *aiq_context = AIQ_CONTEXT_CAST (context); |
| delete aiq_context; |
| return XCAM_RETURN_NO_ERROR; |
| } |
| |
| static XCamReturn |
| xcam_configure_3a (XCam3AContext *context, uint32_t width, uint32_t height, double framerate) |
| { |
| XCam3AAiqContext *aiq_context = AIQ_CONTEXT_CAST (context); |
| XCamReturn ret = XCAM_RETURN_NO_ERROR; |
| struct atomisp_sensor_mode_data sensor_mode_data; |
| |
| switch ((int)framerate) { |
| case 30: |
| sensor_mode_data.coarse_integration_time_min = 1; |
| sensor_mode_data.coarse_integration_time_max_margin = 1; |
| sensor_mode_data.fine_integration_time_min = 0; |
| sensor_mode_data.fine_integration_time_max_margin = 0; |
| sensor_mode_data.fine_integration_time_def = 0; |
| sensor_mode_data.frame_length_lines = 1125; |
| sensor_mode_data.line_length_pck = 1100; |
| sensor_mode_data.read_mode = 0; |
| sensor_mode_data.vt_pix_clk_freq_mhz = 37125000; |
| sensor_mode_data.crop_horizontal_start = 0; |
| sensor_mode_data.crop_vertical_start = 0; |
| sensor_mode_data.crop_horizontal_end = 1920; |
| sensor_mode_data.crop_vertical_end = 1080; |
| sensor_mode_data.output_width = 1920; |
| sensor_mode_data.output_height = 1080; |
| sensor_mode_data.binning_factor_x = 1; |
| sensor_mode_data.binning_factor_y = 1; |
| break; |
| default: |
| sensor_mode_data.coarse_integration_time_min = 1; |
| sensor_mode_data.coarse_integration_time_max_margin = 1; |
| sensor_mode_data.fine_integration_time_min = 0; |
| sensor_mode_data.fine_integration_time_max_margin = 0; |
| sensor_mode_data.fine_integration_time_def = 0; |
| sensor_mode_data.frame_length_lines = 1125; |
| sensor_mode_data.line_length_pck = 1320; |
| sensor_mode_data.read_mode = 0; |
| sensor_mode_data.vt_pix_clk_freq_mhz = 37125000; |
| sensor_mode_data.crop_horizontal_start = 0; |
| sensor_mode_data.crop_vertical_start = 0; |
| sensor_mode_data.crop_horizontal_end = 1920; |
| sensor_mode_data.crop_vertical_end = 1080; |
| sensor_mode_data.output_width = 1920; |
| sensor_mode_data.output_height = 1080; |
| sensor_mode_data.binning_factor_x = 1; |
| sensor_mode_data.binning_factor_y = 1; |
| break; |
| } |
| |
| XCAM_ASSERT (aiq_context); |
| const char *path_cpf = getenv ("AIQ_CPF_PATH"); |
| XCAM_FAIL_RETURN ( |
| WARNING, |
| aiq_context->setup_analyzer (sensor_mode_data, path_cpf == NULL ? DEFAULT_AIQ_CPF_FILE : path_cpf), |
| XCAM_RETURN_ERROR_UNKNOWN, |
| "setup aiq 3a analyzer failed"); |
| |
| SmartPtr<X3aAnalyzeTuner> analyzer = aiq_context->get_analyzer (); |
| |
| ret = analyzer->prepare_handlers (); |
| XCAM_FAIL_RETURN ( |
| WARNING, |
| ret == XCAM_RETURN_NO_ERROR, |
| ret, |
| "analyzer(aiq3alib) prepare handlers failed"); |
| |
| ret = analyzer->init (width, height, framerate); |
| XCAM_FAIL_RETURN ( |
| WARNING, |
| ret == XCAM_RETURN_NO_ERROR, |
| ret, |
| "configure aiq 3a failed"); |
| |
| ret = analyzer->start (); |
| XCAM_FAIL_RETURN ( |
| WARNING, |
| ret == XCAM_RETURN_NO_ERROR, |
| ret, |
| "start aiq 3a failed"); |
| |
| aiq_context->set_size (width, height); |
| |
| return XCAM_RETURN_NO_ERROR; |
| } |
| |
| static XCamReturn |
| xcam_set_3a_stats (XCam3AContext *context, XCam3AStats *stats, int64_t timestamp) |
| { |
| XCamReturn ret = XCAM_RETURN_NO_ERROR; |
| XCam3AAiqContext *aiq_context = AIQ_CONTEXT_CAST (context); |
| XCAM_ASSERT (aiq_context); |
| |
| SmartPtr<X3aAnalyzeTuner> analyzer = aiq_context->get_analyzer (); |
| XCAM_ASSERT (analyzer.ptr ()); |
| XCAM_ASSERT (stats); |
| |
| if (!aiq_context->is_stats_pool_ready ()) { |
| // init statistics queue |
| XCAM_FAIL_RETURN ( |
| WARNING, |
| aiq_context->setup_stats_pool (stats->info.bit_depth), |
| XCAM_RETURN_ERROR_UNKNOWN, |
| "aiq configure 3a failed on stats pool setup"); |
| } |
| |
| // Convert stats to atomisp_3a_stats; |
| SmartPtr<X3aIspStatistics> isp_stats = aiq_context->get_stats_buffer (); |
| if (!isp_stats.ptr ()) { |
| XCAM_LOG_WARNING ("get stats bufffer failed or stopped"); |
| return XCAM_RETURN_ERROR_MEM; |
| } |
| |
| struct atomisp_3a_statistics *raw_stats = isp_stats->get_isp_stats (); |
| XCAM_ASSERT (raw_stats); |
| |
| translate_3a_stats (stats, raw_stats); |
| isp_stats->set_timestamp (timestamp); |
| |
| ret = analyzer->push_3a_stats (isp_stats); |
| if (ret != XCAM_RETURN_NO_ERROR) { |
| XCAM_LOG_WARNING ("set 3a stats failed"); |
| } |
| |
| return ret; |
| } |
| |
| static XCamReturn |
| xcam_update_common_params (XCam3AContext *context, XCamCommonParam *params) |
| { |
| if (params) { |
| SmartPtr<X3aAnalyzeTuner> analyzer = get_analyzer (context); |
| XCAM_ASSERT (analyzer.ptr ()); |
| |
| analyzer->update_common_parameters (*params); |
| } |
| #if 0 |
| XCam3AAiqContext *aiq_context = AIQ_CONTEXT_CAST (context); |
| aiq_context->update_brightness_result(params); |
| #endif |
| return XCAM_RETURN_NO_ERROR; |
| } |
| |
| static XCamReturn |
| xcam_analyze_awb (XCam3AContext *context, XCamAwbParam *params) |
| { |
| if (params) { |
| SmartPtr<X3aAnalyzeTuner> analyzer = get_analyzer (context); |
| XCAM_ASSERT (analyzer.ptr ()); |
| |
| analyzer->update_awb_parameters (*params); |
| } |
| return XCAM_RETURN_NO_ERROR; |
| } |
| |
| static XCamReturn |
| xcam_analyze_ae (XCam3AContext *context, XCamAeParam *params) |
| { |
| if (params) { |
| SmartPtr<X3aAnalyzeTuner> analyzer = get_analyzer (context); |
| XCAM_ASSERT (analyzer.ptr ()); |
| |
| analyzer->update_ae_parameters (*params); |
| } |
| return XCAM_RETURN_NO_ERROR; |
| } |
| |
| static XCamReturn |
| xcam_analyze_af (XCam3AContext *context, XCamAfParam *params) |
| { |
| if (params) { |
| SmartPtr<X3aAnalyzeTuner> analyzer = get_analyzer (context); |
| XCAM_ASSERT (analyzer.ptr ()); |
| |
| analyzer->update_af_parameters (*params); |
| } |
| return XCAM_RETURN_NO_ERROR; |
| } |
| |
| static XCamReturn |
| xcam_combine_analyze_results (XCam3AContext *context, XCam3aResultHead *results[], uint32_t *res_count) |
| { |
| XCam3AAiqContext *aiq_context = AIQ_CONTEXT_CAST (context); |
| XCAM_ASSERT (aiq_context); |
| X3aResultList aiq_results; |
| uint32_t result_count = aiq_context->get_results (aiq_results); |
| |
| if (!result_count) { |
| *res_count = 0; |
| XCAM_LOG_DEBUG ("aiq wrapper combine with no result out"); |
| return XCAM_RETURN_NO_ERROR; |
| } |
| |
| // mark as static |
| static XCam3aResultHead *res_array[XCAM_3A_MAX_RESULT_COUNT]; |
| xcam_mem_clear (res_array); |
| XCAM_ASSERT (result_count < XCAM_3A_MAX_RESULT_COUNT); |
| |
| // result_count may changed |
| result_count = translate_3a_results_to_xcam (aiq_results, res_array, XCAM_3A_MAX_RESULT_COUNT); |
| |
| for (uint32_t i = 0; i < result_count; ++i) { |
| results[i] = res_array[i]; |
| } |
| *res_count = result_count; |
| XCAM_ASSERT (result_count > 0); |
| |
| return XCAM_RETURN_NO_ERROR; |
| } |
| |
| static void |
| xcam_free_results (XCam3aResultHead *results[], uint32_t res_count) |
| { |
| for (uint32_t i = 0; i < res_count; ++i) { |
| if (results[i]) |
| free_3a_result (results[i]); |
| } |
| } |
| |
| XCAM_BEGIN_DECLARE |
| |
| XCam3ADescription xcam_3a_desciption = { |
| XCAM_VERSION, |
| sizeof (XCam3ADescription), |
| xcam_create_context, |
| xcam_destroy_context, |
| xcam_configure_3a, |
| xcam_set_3a_stats, |
| xcam_update_common_params, |
| xcam_analyze_awb, |
| xcam_analyze_ae, |
| xcam_analyze_af, |
| xcam_combine_analyze_results, |
| xcam_free_results |
| }; |
| |
| XCAM_END_DECLARE |
| |