/* * 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 <feng.yuan@intel.com> */ #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