init libxcam source code
diff --git a/xcore/Makefile.am b/xcore/Makefile.am
new file mode 100644
index 0000000..a3d5ba6
--- /dev/null
+++ b/xcore/Makefile.am
@@ -0,0 +1,131 @@
+lib_LTLIBRARIES = libxcam_core.la
+
+PTHREAD_LDFLAGS = -pthread
+
+XCAM_CORE_CXXFLAGS = $(XCAM_CXXFLAGS)
+XCAM_CORE_LIBS = \
+ $(NULL)
+
+if DEBUG
+endif
+
+if HAVE_IA_AIQ
+if USE_LOCAL_AIQ
+IA_IMAGING_CFLAGS = \
+ -I$(top_srcdir)/ext/ia_imaging/include \
+ $(NULL)
+
+IA_IMAGING_LIBS = \
+ -L$(top_srcdir)/ext/ia_imaging/lib \
+ -lia_aiq \
+ -lia_isp_2_2 \
+ -lia_cmc_parser \
+ -lia_mkn \
+ -lia_nvm \
+ -lia_tools \
+ -lia_log \
+ $(NULL)
+
+else
+IA_IMAGING_CFLAGS = $(IA_AIQ_CFLAGS)
+IA_IMAGING_LIBS = $(IA_AIQ_LIBS)
+endif
+
+XCAM_CORE_CXXFLAGS += \
+ $(IA_IMAGING_CFLAGS) \
+ $(NULL)
+
+XCAM_CORE_LIBS += \
+ $(IA_IMAGING_LIBS) \
+ $(NULL)
+
+endif
+
+
+if HAVE_LIBDRM
+XCAM_CORE_CXXFLAGS += $(LIBDRM_CFLAGS)
+XCAM_CORE_LIBS += $(LIBDRM_LIBS)
+endif
+
+if USE_LOCAL_ATOMISP
+XCAM_CORE_CXXFLAGS += \
+ -I$(top_srcdir)/ext/atomisp \
+ $(NULL)
+endif
+
+xcam_sources = \
+ atomisp_device.cpp \
+ device_manager.cpp \
+ handler_interface.cpp \
+ image_processor.cpp \
+ isp_controller.cpp \
+ isp_image_processor.cpp \
+ isp_config_translator.cpp \
+ poll_thread.cpp \
+ sensor_descriptor.cpp \
+ v4l2_buffer_proxy.cpp \
+ v4l2_device.cpp \
+ x3a_analyzer.cpp \
+ x3a_analyzer_manager.cpp \
+ x3a_analyzer_simple.cpp \
+ x3a_image_process_center.cpp \
+ x3a_isp_config.cpp \
+ x3a_result.cpp \
+ x3a_statistics_queue.cpp \
+ xcam_common.cpp \
+ xcam_thread.cpp \
+ $(NULL)
+
+if HAVE_IA_AIQ
+xcam_sources += \
+ libtbd.c \
+ xcam_cpf_reader.c \
+ aiq_handler.cpp \
+ x3a_analyzer_aiq.cpp \
+ $(NULL)
+endif
+
+libxcam_core_la_CXXFLAGS = \
+ $(XCAM_CORE_CXXFLAGS) \
+ $(NULL)
+
+libxcam_core_la_SOURCES = \
+ $(xcam_sources) \
+ $(NULL)
+
+libxcam_core_la_LDFLAGS = \
+ -no-undefined \
+ $(PTHREAD_LDFLAGS) \
+ $(NULL)
+
+libxcam_core_la_LIBADD = \
+ $(XCAM_CORE_LIBS) \
+ $(NULL)
+
+
+libxcam_coreincludedir = $(includedir)/xcam
+
+libxcam_coreinclude_HEADERS = \
+ device_manager.h \
+ handler_interface.h \
+ image_processor.h \
+ safe_list.h \
+ smartptr.h \
+ v4l2_buffer_proxy.h \
+ v4l2_device.h \
+ video_buffer.h \
+ x3a_analyzer.h \
+ x3a_analyzer_manager.h \
+ x3a_event.h \
+ x3a_image_process_center.h \
+ x3a_isp_config.h \
+ x3a_result.h \
+ xcam_3a_result.h \
+ xcam_3a_types.h \
+ xcam_common.h \
+ xcam_defs.h \
+ xcam_mutex.h \
+ xcam_thread.h \
+ xcam_utils.h \
+ $(NULL)
+
diff --git a/xcore/aiq_handler.cpp b/xcore/aiq_handler.cpp
new file mode 100644
index 0000000..dc3ec7a
--- /dev/null
+++ b/xcore/aiq_handler.cpp
@@ -0,0 +1,1103 @@
+/*
+ * aiq_handler.cpp - AIQ handler
+ *
+ * Copyright (c) 2012-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>
+ * Author: Yan Zhang <yan.y.zhang@intel.com>
+ */
+
+#include "aiq_handler.h"
+#include "x3a_isp_config.h"
+
+#include <string.h>
+#include <math.h>
+
+#include "ia_isp_2_2.h"
+
+#define MAX_STATISTICS_WIDTH 150
+#define MAX_STATISTICS_HEIGHT 150
+
+namespace XCam {
+
+struct IspInputParameters {
+ ia_aiq_frame_use frame_use;
+ ia_aiq_frame_params *sensor_frame_params;
+ ia_aiq_exposure_parameters *exposure_results;
+ ia_aiq_awb_results *awb_results;
+ ia_aiq_gbce_results *gbce_results;
+ ia_aiq_pa_results *pa_results;
+ int8_t manual_brightness;
+ int8_t manual_contrast;
+ int8_t manual_hue;
+ int8_t manual_saturation;
+ int8_t manual_sharpness;
+ int8_t manual_nr_level;
+ ia_isp_effect effects;
+
+ IspInputParameters ()
+ : frame_use (ia_aiq_frame_use_preview)
+ , sensor_frame_params (NULL)
+ , exposure_results (NULL)
+ , awb_results (NULL)
+ , gbce_results (NULL)
+ , pa_results (NULL)
+ , manual_brightness (0)
+ , manual_contrast (0)
+ , manual_hue (0)
+ , manual_saturation (0)
+ , manual_sharpness (0)
+ , manual_nr_level (0)
+ , effects (ia_isp_effect_none)
+ {}
+};
+
+class IaIspAdaptor22
+ : public IaIspAdaptor
+{
+public:
+ IaIspAdaptor22 () {
+ xcam_mem_clear (&_input_params);
+ }
+ ~IaIspAdaptor22 () {
+ if (_handle)
+ ia_isp_2_2_deinit (_handle);
+ }
+
+ virtual bool init (
+ const ia_binary_data *cpf,
+ unsigned int max_width,
+ unsigned int max_height,
+ ia_cmc_t *cmc,
+ ia_mkn *mkn);
+
+ virtual bool convert_statistics (
+ void *statistics,
+ ia_aiq_rgbs_grid **out_rgbs_grid,
+ ia_aiq_af_grid **out_af_grid);
+
+ virtual bool run (
+ const IspInputParameters *isp_input_params,
+ ia_binary_data *output_data);
+
+private:
+ ia_isp_2_2_input_params _input_params;
+
+};
+
+bool
+IaIspAdaptor22::init (
+ const ia_binary_data *cpf,
+ unsigned int max_width,
+ unsigned int max_height,
+ ia_cmc_t *cmc,
+ ia_mkn *mkn)
+{
+ xcam_mem_clear (&_input_params);
+ _input_params.isp_vamem_type = 1;
+ _handle = ia_isp_2_2_init (cpf, max_width, max_height, cmc, mkn);
+ XCAM_FAIL_RETURN (ERROR, _handle, false, "ia_isp 2.2 init failed");
+ return true;
+}
+
+bool
+IaIspAdaptor22::convert_statistics (
+ void *statistics,
+ ia_aiq_rgbs_grid **out_rgbs_grid,
+ ia_aiq_af_grid **out_af_grid)
+{
+ ia_err err;
+ err = ia_isp_2_2_statistics_convert (_handle, statistics, out_rgbs_grid, out_af_grid);
+ XCAM_FAIL_RETURN (ERROR, err == ia_err_none, false, "ia_isp 2.2 convert stats failed");
+ return true;
+}
+
+bool
+IaIspAdaptor22::run (
+ const IspInputParameters *isp_input_params,
+ ia_binary_data *output_data)
+{
+ ia_err err;
+
+ _input_params.frame_use = isp_input_params->frame_use;
+ _input_params.sensor_frame_params = isp_input_params->sensor_frame_params;
+ _input_params.exposure_results = isp_input_params->exposure_results;
+ _input_params.awb_results = isp_input_params->awb_results;
+ _input_params.gbce_results = isp_input_params->gbce_results;
+ _input_params.pa_results = isp_input_params->pa_results;
+ _input_params.manual_brightness = isp_input_params->manual_brightness;
+ _input_params.manual_contrast = isp_input_params->manual_contrast;
+ _input_params.manual_hue = isp_input_params->manual_hue;
+ _input_params.manual_saturation = isp_input_params->manual_saturation;
+ _input_params.nr_setting.feature_level = ia_isp_feature_level_high;
+ _input_params.nr_setting.strength = isp_input_params->manual_nr_level;
+ _input_params.ee_setting.feature_level = ia_isp_feature_level_high;
+ _input_params.ee_setting.strength = isp_input_params->manual_sharpness;
+ _input_params.effects = isp_input_params->effects;
+
+ err = ia_isp_2_2_run (_handle, &_input_params, output_data);
+ XCAM_FAIL_RETURN (ERROR, err == ia_err_none, false, "ia_isp 2.2 run failed");
+ return true;
+}
+
+#if 0
+
+class IaIspAdaptor15
+ : public IaIspAdaptor
+{
+public:
+ IaIspAdaptor15 () {
+ xcam_mem_clear (&_input_params);
+ }
+ ~IaIspAdaptor15 () {
+ if (_handle)
+ ia_isp_1_5_deinit (_handle);
+ }
+ virtual bool init (
+ const ia_binary_data *cpf,
+ unsigned int max_width,
+ unsigned int max_height,
+ ia_cmc_t *cmc,
+ ia_mkn *mkn);
+ virtual bool convert_statistics (
+ void *statistics,
+ ia_aiq_rgbs_grid **out_rgbs_grid,
+ ia_aiq_af_grid **out_af_grid);
+ virtual bool run (
+ const IspInputParameters *isp_input_params,
+ ia_binary_data *output_data);
+
+private:
+ ia_isp_1_5_input_params _input_params;
+
+};
+
+bool
+IaIspAdaptor15::init (
+ const ia_binary_data *cpf,
+ unsigned int max_width,
+ unsigned int max_height,
+ ia_cmc_t *cmc,
+ ia_mkn *mkn)
+{
+ xcam_mem_clear (&_input_params);
+ _input_params.isp_vamem_type = 1;
+ _handle = ia_isp_1_5_init (cpf, max_width, max_height, cmc, mkn);
+ XCAM_FAIL_RETURN (ERROR, _handle, false, "ia_isp 1.5 init failed");
+ return true;
+}
+
+bool
+IaIspAdaptor15::convert_statistics (
+ void *statistics,
+ ia_aiq_rgbs_grid **out_rgbs_grid,
+ ia_aiq_af_grid **out_af_grid)
+{
+ ia_err err;
+ err = ia_isp_1_5_statistics_convert (_handle, statistics, out_rgbs_grid, out_af_grid);
+ XCAM_FAIL_RETURN (ERROR, err == ia_err_none, false, "ia_isp 1.5 convert stats failed");
+ return true;
+}
+
+bool
+IaIspAdaptor15::run (
+ const IspInputParameters *isp_input_params,
+ ia_binary_data *output_data)
+{
+ ia_err err;
+
+ _input_params.frame_use = isp_input_params->frame_use;
+ _input_params.sensor_frame_params = isp_input_params->sensor_frame_params;
+ _input_params.exposure_results = isp_input_params->exposure_results;
+ _input_params.awb_results = isp_input_params->awb_results;
+ _input_params.gbce_results = isp_input_params->gbce_results;
+ _input_params.pa_results = isp_input_params->pa_results;
+ _input_params.manual_brightness = isp_input_params->manual_brightness;
+ _input_params.manual_contrast = isp_input_params->manual_contrast;
+ _input_params.manual_hue = isp_input_params->manual_hue;
+ _input_params.manual_saturation = isp_input_params->manual_saturation;
+ _input_params.nr_setting.feature_level = ia_isp_feature_level_high;
+ _input_params.nr_setting.strength = isp_input_params->manual_nr_level;
+ _input_params.ee_setting.feature_level = ia_isp_feature_level_high;
+ _input_params.ee_setting.strength = isp_input_params->manual_sharpness;
+ _input_params.effects = isp_input_params->effects;
+
+ err = ia_isp_1_5_run (_handle, &_input_params, output_data);
+ XCAM_FAIL_RETURN (ERROR, err == ia_err_none, false, "ia_isp 1.5 run failed");
+ return true;
+}
+
+#endif
+
+static double
+_calculate_new_value_by_speed (double start, double end, double speed)
+{
+ XCAM_ASSERT (speed >= 0.0 && speed <= 1.0);
+ static const double value_equal_range = 0.000001;
+
+ if (fabs (end - start) <= value_equal_range)
+ return end;
+ return (start * (1.0 - speed) + end * speed);
+}
+
+static double
+_imx185_sensor_gain_code_to_mutiplier (uint32_t code)
+{
+ /* 185 sensor code : DB = 160 : 48 */
+ double db;
+ db = code * 48.0 / 160.0;
+ return pow (10.0, db / 20.0);
+}
+
+static uint32_t
+_mutiplier_to_imx185_sensor_gain_code (double mutiplier)
+{
+ double db = log10 (mutiplier) * 20;
+ if (db > 48)
+ db = 48;
+ return (uint32_t) (db * 160 / 48);
+}
+
+static uint32_t
+_time_to_coarse_line (ia_aiq_exposure_sensor_descriptor *desc, uint32_t time_us)
+{
+ float value = time_us * desc->pixel_clock_freq_mhz;
+
+ value = (value + desc->pixel_periods_per_line / 2) / desc->pixel_periods_per_line;
+ return (uint32_t)(value);
+}
+
+AiqAeHandler::AiqAeResult::AiqAeResult()
+{
+ xcam_mem_clear (&ae_result);
+ xcam_mem_clear (&ae_exp_ret);
+ xcam_mem_clear (&aiq_exp_param);
+ xcam_mem_clear (&sensor_exp_param);
+ xcam_mem_clear (&weight_grid);
+ xcam_mem_clear (&flash_param);
+}
+
+void
+AiqAeHandler::AiqAeResult::copy (ia_aiq_ae_results *result)
+{
+ XCAM_ASSERT (result);
+
+ this->ae_result = *result;
+ this->aiq_exp_param = *result->exposures[0].exposure;
+ this->sensor_exp_param = *result->exposures[0].sensor_exposure;
+ this->weight_grid = *result->weight_grid;
+ this->flash_param = *result->flash;
+
+ this->ae_exp_ret.exposure = &this->aiq_exp_param;
+ this->ae_exp_ret.sensor_exposure = &this->sensor_exp_param;
+ this->ae_result.exposures = &this->ae_exp_ret;
+ this->ae_result.weight_grid = &this->weight_grid;
+ this->ae_result.flash = &this->flash_param;
+ this->ae_result.num_exposures = 1;
+}
+
+AiqAeHandler::AiqAeHandler (SmartPtr<AiqCompositor> &aiq_compositor)
+ : _aiq_compositor (aiq_compositor)
+ , _started (false)
+{
+ xcam_mem_clear (&_ia_ae_window);
+ xcam_mem_clear (&_sensor_descriptor);
+ xcam_mem_clear (&_manual_limits);
+ xcam_mem_clear (&_input);
+ _input.num_exposures = 1;
+ _input.frame_use = _aiq_compositor->get_frame_use();
+ _input.flash_mode = ia_aiq_flash_mode_off;
+ _input.operation_mode = ia_aiq_ae_operation_mode_automatic;
+ _input.metering_mode = ia_aiq_ae_metering_mode_evaluative;
+ _input.priority_mode = ia_aiq_ae_priority_mode_normal;
+ _input.flicker_reduction_mode = ia_aiq_ae_flicker_reduction_auto;
+ _input.sensor_descriptor = NULL;
+ _input.exposure_window = NULL;
+ _input.exposure_coordinate = NULL;
+ _input.ev_shift = 0.0;
+ _input.manual_exposure_time_us = -1;
+ _input.manual_analog_gain = -1.0;
+ _input.manual_iso = -1.0;
+ _input.aec_features = NULL;
+ _input.manual_limits = NULL;
+}
+
+bool
+AiqAeHandler::set_description (struct atomisp_sensor_mode_data *sensor_data)
+{
+ XCAM_ASSERT (sensor_data);
+
+ _sensor_descriptor.pixel_clock_freq_mhz = sensor_data->vt_pix_clk_freq_mhz / 1000000.0f;
+ _sensor_descriptor.pixel_periods_per_line = sensor_data->line_length_pck;
+ _sensor_descriptor.line_periods_per_field = sensor_data->frame_length_lines;
+ _sensor_descriptor.line_periods_vertical_blanking = sensor_data->frame_length_lines
+ - (sensor_data->crop_vertical_end - sensor_data->crop_vertical_start + 1)
+ / sensor_data->binning_factor_y;
+ _sensor_descriptor.fine_integration_time_min = sensor_data->fine_integration_time_def;
+ _sensor_descriptor.fine_integration_time_max_margin = sensor_data->line_length_pck - sensor_data->fine_integration_time_def;
+ _sensor_descriptor.coarse_integration_time_min = sensor_data->coarse_integration_time_min;
+ _sensor_descriptor.coarse_integration_time_max_margin = sensor_data->coarse_integration_time_max_margin;
+
+ return true;
+}
+
+bool
+AiqAeHandler::ensure_ia_parameters ()
+{
+ bool ret = true;
+ ret = ret && ensure_ae_mode ();
+ ret = ret && ensure_ae_metering_mode ();
+ ret = ret && ensure_ae_priority_mode ();
+ ret = ret && ensure_ae_flicker_mode ();
+ ret = ret && ensure_ae_manual ();
+ ret = ret && ensure_ae_ev_shift ();
+ _input.sensor_descriptor = &_sensor_descriptor;
+ return ret;
+}
+
+bool AiqAeHandler::ensure_ae_mode ()
+{
+ XCamAeMode mode = this->get_mode_unlock();
+ switch (mode) {
+ case XCAM_AE_MODE_AUTO:
+ case XCAM_AE_MODE_MANUAL:
+ _input.operation_mode = ia_aiq_ae_operation_mode_automatic;
+ break;
+
+ case XCAM_AE_MODE_NOT_SET:
+ default:
+ XCAM_LOG_ERROR("unsupported ae mode:%d", mode);
+ return false;
+ }
+ return true;
+}
+bool AiqAeHandler::ensure_ae_metering_mode ()
+{
+ XCamAeMeteringMode mode = this->get_metering_mode_unlock();
+
+ _input.exposure_window = NULL;
+
+ switch (mode) {
+ case XCAM_AE_METERING_MODE_AUTO:
+ _input.metering_mode = ia_aiq_ae_metering_mode_evaluative;
+ break;
+ case XCAM_AE_METERING_MODE_SPOT:
+ {
+ _input.metering_mode = ia_aiq_ae_metering_mode_evaluative;
+ const XCam3AWindow & window = this->get_window_unlock();
+ if (window.x_end > window.x_start &&
+ window.y_end > window.y_start) {
+ _aiq_compositor->convert_window_to_ia(window, _ia_ae_window);
+ _input.exposure_window = &_ia_ae_window;
+ }
+ }
+ break;
+ case XCAM_AE_METERING_MODE_CENTER:
+ _input.metering_mode = ia_aiq_ae_metering_mode_center;
+ break;
+ default:
+ XCAM_LOG_ERROR("unsupported ae mode:%d", mode);
+ return false;
+ }
+ return true;
+}
+
+bool AiqAeHandler::ensure_ae_priority_mode ()
+{
+ _input.priority_mode = ia_aiq_ae_priority_mode_normal;
+ return true;
+}
+
+bool AiqAeHandler::ensure_ae_flicker_mode ()
+{
+ XCamFlickerMode mode = this->get_flicker_mode_unlock ();
+ switch (mode) {
+ case XCAM_AE_FLICKER_MODE_AUTO:
+ _input.flicker_reduction_mode = ia_aiq_ae_flicker_reduction_auto;
+ break;
+ case XCAM_AE_FLICKER_MODE_50HZ:
+ _input.flicker_reduction_mode = ia_aiq_ae_flicker_reduction_50hz;
+ break;
+ case XCAM_AE_FLICKER_MODE_60HZ:
+ _input.flicker_reduction_mode = ia_aiq_ae_flicker_reduction_60hz;
+ break;
+ case XCAM_AE_FLICKER_MODE_OFF:
+ _input.flicker_reduction_mode = ia_aiq_ae_flicker_reduction_off;
+ break;
+ default:
+ XCAM_LOG_ERROR ("flicker mode(%d) unknown", mode);
+ return false;
+ }
+ return true;
+}
+
+bool AiqAeHandler::ensure_ae_manual ()
+{
+ _input.manual_exposure_time_us = this->_manual_exposure_time;
+ _input.manual_analog_gain = this->_manual_analog_gain;
+ return true;
+}
+
+bool AiqAeHandler::ensure_ae_ev_shift ()
+{
+ _input.ev_shift = this->get_ev_shift_unlock();
+ return true;
+}
+
+SmartPtr<X3aResult>
+AiqAeHandler::pop_result ()
+{
+ //AnalyzerHandler::HanlderLock lock(this);
+
+ X3aIspExposureResult *result = new X3aIspExposureResult(XCAM_IMAGE_PROCESS_ONCE);
+ struct atomisp_exposure sensor;
+ XCam3aResultExposure exposure;
+
+ xcam_mem_clear (&sensor);
+ sensor.integration_time[0] = _result.sensor_exp_param.coarse_integration_time;
+ sensor.integration_time[1] = _result.sensor_exp_param.fine_integration_time;
+ sensor.gain[0] = _result.sensor_exp_param.analog_gain_code_global;
+ sensor.gain[1] = _result.sensor_exp_param.digital_gain_global;
+ result->set_isp_config (sensor);
+
+ xcam_mem_clear (&exposure);
+ exposure.exposure_time = _result.aiq_exp_param.exposure_time_us;
+ exposure.analog_gain = _result.aiq_exp_param.analog_gain;
+ exposure.digital_gain = _result.aiq_exp_param.digital_gain;
+ exposure.aperture = _result.aiq_exp_param.aperture_fn;
+ result->set_standard_result (exposure);
+
+ return result;
+}
+
+XCamReturn
+AiqAeHandler::analyze (X3aResultList &output)
+{
+ ia_aiq *ia_handle = NULL;
+ ia_aiq_ae_results *ae_result = NULL;
+ ia_aiq_exposure_sensor_parameters *cur_sensor_result = NULL;
+ ia_err ia_error = ia_err_none;
+ bool need_apply = false;
+ SmartPtr<X3aResult> result;
+
+ AnalyzerHandler::HanlderLock lock(this);
+
+ if (!ensure_ia_parameters ()) {
+ XCAM_LOG_ERROR ("AIQ AE ensure ia parameters failed");
+ return XCAM_RETURN_ERROR_PARAM;
+ }
+
+ ia_handle = _aiq_compositor->get_handle ();
+ XCAM_ASSERT (ia_handle);
+ ia_error = ia_aiq_ae_run (ia_handle, &_input, &ae_result);
+ XCAM_FAIL_RETURN (ERROR, ia_error == ia_err_none, XCAM_RETURN_ERROR_AIQ, "AIQ run AE failed");
+
+ cur_sensor_result = ae_result->exposures[0].sensor_exposure;
+
+ if (!_started) {
+ _result.copy (ae_result);
+ _started = true;
+ need_apply = true;
+ } else {
+ //TODO
+ ia_aiq_exposure_sensor_parameters *last_sensor_res = &_result.sensor_exp_param;
+ if (last_sensor_res->coarse_integration_time != cur_sensor_result->coarse_integration_time ||
+ last_sensor_res->fine_integration_time != cur_sensor_result->fine_integration_time ||
+ last_sensor_res->analog_gain_code_global != cur_sensor_result->analog_gain_code_global ||
+ last_sensor_res->digital_gain_global != cur_sensor_result->digital_gain_global) {
+ ia_aiq_exposure_sensor_parameters cur_cp_res = *cur_sensor_result;
+ if (!manual_control_result (cur_cp_res, *last_sensor_res)) {
+ XCAM_LOG_WARNING ("manual control AE result failed");
+ }
+ _result.copy (ae_result);
+ _result.sensor_exp_param = cur_cp_res;
+ need_apply = true;
+ }
+ }
+
+ if (need_apply) {
+ result = pop_result ();
+ if (result.ptr())
+ output.push_back (result);
+ }
+
+ return XCAM_RETURN_NO_ERROR;
+}
+
+bool
+AiqAeHandler::manual_control_result (
+ ia_aiq_exposure_sensor_parameters &cur_res,
+ const ia_aiq_exposure_sensor_parameters &last_res)
+{
+ adjust_ae_speed (cur_res, last_res, this->get_speed_unlock());
+ adjust_ae_limitation (cur_res);
+
+ return true;
+}
+
+void
+AiqAeHandler::adjust_ae_speed (
+ ia_aiq_exposure_sensor_parameters &cur_res,
+ const ia_aiq_exposure_sensor_parameters &last_res,
+ double ae_speed)
+{
+ double last_gain, input_gain, ret_gain;
+ ia_aiq_exposure_sensor_parameters tmp_res;
+
+ if (XCAM_DOUBLE_EQUAL_AROUND(ae_speed, 1.0 ))
+ return;
+ xcam_mem_clear (&tmp_res);
+ tmp_res.coarse_integration_time = _calculate_new_value_by_speed (
+ last_res.coarse_integration_time,
+ cur_res.coarse_integration_time,
+ ae_speed);
+
+ last_gain = _imx185_sensor_gain_code_to_mutiplier (last_res.analog_gain_code_global);
+ input_gain = _imx185_sensor_gain_code_to_mutiplier (cur_res.analog_gain_code_global);
+ ret_gain = _calculate_new_value_by_speed (last_gain, input_gain, ae_speed);
+
+ tmp_res.analog_gain_code_global = _mutiplier_to_imx185_sensor_gain_code (ret_gain);
+
+ XCAM_LOG_DEBUG ("AE speed: from (shutter:%d, gain:%d[%.03f]) to (shutter:%d, gain:%d[%.03f])",
+ cur_res.coarse_integration_time, cur_res.analog_gain_code_global, input_gain,
+ tmp_res.coarse_integration_time, tmp_res.analog_gain_code_global, ret_gain);
+
+ cur_res.coarse_integration_time = tmp_res.coarse_integration_time;
+ cur_res.analog_gain_code_global = tmp_res.analog_gain_code_global;
+}
+
+void
+AiqAeHandler::adjust_ae_limitation (ia_aiq_exposure_sensor_parameters &cur_res)
+{
+ ia_aiq_exposure_sensor_descriptor * desc = &_sensor_descriptor;
+ uint64_t exposure_min = this->_exposure_time_min;
+ uint64_t exposure_max = this->_exposure_time_max;
+ double analog_max = this->_max_analog_gain;
+ uint32_t min_coarse_value = 0, max_coarse_value = 0;
+
+ if (exposure_min) {
+ min_coarse_value = _time_to_coarse_line (desc, exposure_min);
+ if (min_coarse_value < desc->coarse_integration_time_min)
+ min_coarse_value = desc->coarse_integration_time_min;
+ if (cur_res.coarse_integration_time < min_coarse_value)
+ cur_res.coarse_integration_time = min_coarse_value;
+ }
+ if (exposure_max) {
+ max_coarse_value = _time_to_coarse_line (desc, (uint32_t)exposure_max);
+ if (max_coarse_value > (uint32_t)(desc->line_periods_per_field - desc->coarse_integration_time_max_margin))
+ max_coarse_value = desc->line_periods_per_field - desc->coarse_integration_time_max_margin;
+ if (cur_res.coarse_integration_time > max_coarse_value)
+ cur_res.coarse_integration_time = max_coarse_value;
+ }
+
+ if (analog_max >= 1.0) {
+ /* limit gains */
+ double gain = _imx185_sensor_gain_code_to_mutiplier (cur_res.analog_gain_code_global);
+ if (gain > analog_max)
+ cur_res.analog_gain_code_global = _mutiplier_to_imx185_sensor_gain_code (analog_max);
+ }
+}
+
+XCamFlickerMode
+AiqAeHandler::get_flicker_mode ()
+{
+ {
+ AnalyzerHandler::HanlderLock lock(this);
+ }
+ return AeHandler::get_flicker_mode ();
+}
+
+int64_t
+AiqAeHandler::get_current_exposure_time ()
+{
+ AnalyzerHandler::HanlderLock lock(this);
+
+ return (int64_t)_result.aiq_exp_param.exposure_time_us;
+}
+
+double
+AiqAeHandler::get_current_analog_gain ()
+{
+ AnalyzerHandler::HanlderLock lock(this);
+ return (double)_result.aiq_exp_param.analog_gain;
+}
+
+double
+AiqAeHandler::get_max_analog_gain ()
+{
+ {
+ AnalyzerHandler::HanlderLock lock(this);
+ }
+ return AeHandler::get_max_analog_gain ();
+}
+
+AiqAwbHandler::AiqAwbHandler (SmartPtr<AiqCompositor> &aiq_compositor)
+ : _aiq_compositor (aiq_compositor)
+ , _started (false)
+{
+ xcam_mem_clear (&_cct_range);
+ xcam_mem_clear (&_result);
+ xcam_mem_clear (&_history_result);
+ xcam_mem_clear (&_cct_range);
+ xcam_mem_clear (&_input);
+
+ _input.frame_use = aiq_compositor->get_frame_use ();
+ _input.scene_mode = ia_aiq_awb_operation_mode_auto;
+ _input.manual_cct_range = NULL;
+ _input.manual_white_coordinate = NULL;
+}
+
+XCamReturn
+AiqAwbHandler::analyze (X3aResultList &output)
+{
+ ia_aiq *ia_handle = NULL;
+ ia_aiq_awb_results *awb_ret = NULL;
+ ia_err ia_error = ia_err_none;
+
+ XCAM_UNUSED (output);
+
+ AnalyzerHandler::HanlderLock lock(this);
+
+ if (!ensure_ia_parameters ()) {
+ XCAM_LOG_ERROR ("AIQ AE ensure ia parameters failed");
+ return XCAM_RETURN_ERROR_PARAM;
+ }
+
+ ia_handle = _aiq_compositor->get_handle ();
+ XCAM_ASSERT (ia_handle);
+ ia_error = ia_aiq_awb_run (ia_handle, &_input, &awb_ret);
+ XCAM_FAIL_RETURN (ERROR, ia_error == ia_err_none, XCAM_RETURN_ERROR_AIQ, "AIQ run AWB failed");
+
+ _result = *awb_ret;
+ if (!_started) {
+ _history_result = _result;
+ _started = true;
+ }
+ adjust_speed (_history_result);
+ _history_result = _result;
+
+ return XCAM_RETURN_NO_ERROR;
+}
+
+bool
+AiqAwbHandler::ensure_ia_parameters ()
+{
+ bool ret = true;
+
+ _input.frame_use = _aiq_compositor->get_frame_use ();
+ ret = ret && ensure_awb_mode ();
+ return ret;
+}
+
+bool
+AiqAwbHandler::ensure_awb_mode ()
+{
+ XCamAwbMode mode = get_mode_unlock();
+
+ _input.manual_cct_range = NULL;
+ _input.scene_mode = ia_aiq_awb_operation_mode_auto;
+
+ switch (mode) {
+ case XCAM_AWB_MODE_AUTO:
+ _input.scene_mode = ia_aiq_awb_operation_mode_auto;
+ break;
+ case XCAM_AWB_MODE_MANUAL:
+ if (this->_cct_min && this->_cct_max) {
+ _input.scene_mode = ia_aiq_awb_operation_mode_manual_cct_range;
+ _cct_range.max_cct = this->_cct_max;
+ _cct_range.min_cct = this->_cct_min;
+ _input.manual_cct_range = &_cct_range;
+ } else
+ _input.scene_mode = ia_aiq_awb_operation_mode_auto;
+ break;
+ case XCAM_AWB_MODE_DAYLIGHT:
+ _input.scene_mode = ia_aiq_awb_operation_mode_daylight;
+ break;
+ case XCAM_AWB_MODE_SUNSET:
+ _input.scene_mode = ia_aiq_awb_operation_mode_sunset;
+ break;
+ case XCAM_AWB_MODE_CLOUDY:
+ _input.scene_mode = ia_aiq_awb_operation_mode_partly_overcast;
+ break;
+ case XCAM_AWB_MODE_TUNGSTEN:
+ _input.scene_mode = ia_aiq_awb_operation_mode_incandescent;
+ break;
+ case XCAM_AWB_MODE_FLUORESCENT:
+ _input.scene_mode = ia_aiq_awb_operation_mode_fluorescent;
+ break;
+ case XCAM_AWB_MODE_WARM_FLUORESCENT:
+ _input.scene_mode = ia_aiq_awb_operation_mode_incandescent;
+ break;
+ case XCAM_AWB_MODE_SHADOW:
+ _input.scene_mode = ia_aiq_awb_operation_mode_fully_overcast;
+ break;
+ case XCAM_AWB_MODE_WARM_INCANDESCENT:
+ _input.scene_mode = ia_aiq_awb_operation_mode_incandescent;
+ break;
+ case XCAM_AWB_MODE_NOT_SET:
+ break;
+
+ default:
+ XCAM_LOG_ERROR ("unknown or unsupported AWB mode(%d)", mode);
+ return false;
+ }
+ return true;
+}
+
+void
+AiqAwbHandler::adjust_speed (const ia_aiq_awb_results &last_ret)
+{
+ _result.final_r_per_g =
+ _calculate_new_value_by_speed (
+ last_ret.final_r_per_g, _result.final_r_per_g, get_speed_unlock ());
+ _result.final_b_per_g =
+ _calculate_new_value_by_speed (
+ last_ret.final_b_per_g, _result.final_b_per_g, get_speed_unlock ());
+}
+
+XCamReturn
+AiqAfHandler::analyze (X3aResultList &output)
+{
+ // TODO
+ XCAM_UNUSED (output);
+ return XCAM_RETURN_NO_ERROR;
+}
+
+AiqCommonHandler::AiqCommonHandler (SmartPtr<AiqCompositor> &aiq_compositor)
+ : _aiq_compositor (aiq_compositor)
+ , _gbce_result (NULL)
+{
+}
+
+
+XCamReturn
+AiqCommonHandler::analyze (X3aResultList &output)
+{
+ ia_aiq *ia_handle = NULL;
+ ia_aiq_gbce_results *gbce_result = NULL;
+ ia_err ia_error = ia_err_none;
+
+ XCAM_UNUSED (output);
+
+ AnalyzerHandler::HanlderLock lock(this);
+
+ if (has_gbce_unlock()) {
+ ia_aiq_gbce_input_params gbce_input;
+ xcam_mem_clear (&gbce_input);
+ gbce_input.gbce_level = ia_aiq_gbce_level_use_tuning;
+ gbce_input.frame_use = _aiq_compositor->get_frame_use ();
+ gbce_input.ev_shift = 0; // Todo
+ ia_handle = _aiq_compositor->get_handle ();
+ XCAM_ASSERT (ia_handle);
+ ia_error = ia_aiq_gbce_run (ia_handle, &gbce_input, &gbce_result);
+
+ XCAM_FAIL_RETURN (ERROR, ia_error == ia_err_none, XCAM_RETURN_ERROR_AIQ, "AIQ run GBCE failed");
+
+ //TODO, need copy GBCE result out, not just assign
+ _gbce_result = gbce_result;
+ } else {
+ _gbce_result = NULL;
+ }
+ return XCAM_RETURN_NO_ERROR;
+}
+
+class CmcParser {
+public:
+ explicit CmcParser (ia_binary_data &cpf)
+ {
+ _cmc = ia_cmc_parser_init (&cpf);
+ }
+ ~CmcParser ()
+ {
+ if (_cmc)
+ ia_cmc_parser_deinit (_cmc);
+ }
+ ia_cmc_t *get() {
+ return _cmc;
+ }
+
+private:
+ ia_cmc_t *_cmc;
+};
+
+void
+AiqCompositor::convert_window_to_ia (const XCam3AWindow &window, ia_rectangle &ia_window)
+{
+ ia_rectangle source;
+ ia_coordinate_system source_system;
+ ia_coordinate_system target_system = {IA_COORDINATE_TOP, IA_COORDINATE_LEFT, IA_COORDINATE_BOTTOM, IA_COORDINATE_RIGHT};
+
+ source_system.left = 0;
+ source_system.top = 0;
+ source_system.right = this->_width;
+ source_system.bottom = this->_height;
+ XCAM_ASSERT (_width && _height);
+
+ source.left = window.x_start;
+ source.top = window.y_start;
+ source.right = window.x_end;
+ source.bottom = window.y_end;
+ ia_coordinate_convert_rect (&source_system, &source, &target_system, &ia_window);
+}
+
+AiqCompositor::AiqCompositor ()
+ : _ia_handle (NULL)
+ , _ia_mkn (NULL)
+ , _pa_result (NULL)
+ , _frame_use (ia_aiq_frame_use_video)
+ , _width (0)
+ , _height (0)
+{
+ xcam_mem_clear (&_frame_params);
+}
+
+AiqCompositor::~AiqCompositor ()
+{
+}
+
+bool
+AiqCompositor::open (ia_binary_data &cpf)
+{
+ CmcParser cmc (cpf);
+
+ _ia_mkn = ia_mkn_init (ia_mkn_cfg_compression, 32000, 100000);
+ _ia_handle =
+ ia_aiq_init (
+ &cpf, NULL, NULL,
+ MAX_STATISTICS_WIDTH, MAX_STATISTICS_HEIGHT,
+ 1, //max_num_stats_in
+ cmc.get(),
+ _ia_mkn);
+
+ if (_ia_handle == NULL) {
+ XCAM_LOG_WARNING ("AIQ init failed");
+ return false;
+ }
+
+ _adaptor = new IaIspAdaptor22;
+ XCAM_ASSERT (_adaptor.ptr());
+ if (!_adaptor->init (&cpf, MAX_STATISTICS_WIDTH, MAX_STATISTICS_HEIGHT, cmc.get(), _ia_mkn)) {
+ XCAM_LOG_WARNING ("AIQ isp adaptor init failed");
+ return false;
+ }
+
+ _pa_result = NULL;
+
+ XCAM_LOG_DEBUG ("Aiq compositor opened");
+ return true;
+}
+
+void
+AiqCompositor::close ()
+{
+ _adaptor.release ();
+ if (_ia_handle) {
+ ia_aiq_deinit (_ia_handle);
+ _ia_handle = NULL;
+ }
+
+ if (_ia_mkn) {
+ ia_mkn_uninit (_ia_mkn);
+ _ia_mkn = NULL;
+ }
+
+ _ae_handler.release ();
+ _awb_handler.release ();
+ _af_handler.release ();
+ _common_handler.release ();
+
+ _pa_result = NULL;
+
+ XCAM_LOG_DEBUG ("Aiq compositor closed");
+}
+
+bool
+AiqCompositor::set_sensor_mode_data (struct atomisp_sensor_mode_data *sensor_mode)
+{
+ _frame_params.horizontal_crop_offset = sensor_mode->crop_horizontal_start;
+ _frame_params.vertical_crop_offset = sensor_mode->crop_vertical_start;
+ _frame_params.cropped_image_height = sensor_mode->crop_vertical_end - sensor_mode->crop_vertical_start + 1;
+ _frame_params.cropped_image_width = sensor_mode->crop_horizontal_end - sensor_mode->crop_horizontal_start + 1;
+
+ /* hard code to 254? */
+ _frame_params.horizontal_scaling_denominator = 254;
+ _frame_params.vertical_scaling_denominator = 254;
+
+ if ((_frame_params.cropped_image_width == 0) || (_frame_params.cropped_image_height == 0)) {
+ _frame_params.horizontal_scaling_numerator = 0;
+ _frame_params.vertical_scaling_numerator = 0;
+ } else {
+ _frame_params.horizontal_scaling_numerator =
+ sensor_mode->output_width * 254 * sensor_mode->binning_factor_x / _frame_params.cropped_image_width;
+ _frame_params.vertical_scaling_numerator =
+ sensor_mode->output_height * 254 * sensor_mode->binning_factor_y / _frame_params.cropped_image_height;
+ }
+
+ if (!_ae_handler->set_description (sensor_mode)) {
+ XCAM_LOG_WARNING ("AIQ set ae description failed");
+ return XCAM_RETURN_ERROR_AIQ;
+ }
+ return true;
+}
+
+bool
+AiqCompositor::set_3a_stats (SmartPtr<X3aIspStatistics> &stats)
+{
+ ia_aiq_statistics_input_params aiq_stats_input;
+ ia_aiq_rgbs_grid *rgbs_grids = NULL;
+ ia_aiq_af_grid *af_grids = NULL;
+
+ xcam_mem_clear (&aiq_stats_input);
+ aiq_stats_input.frame_timestamp = stats->get_timestamp();
+ aiq_stats_input.frame_id = stats->get_timestamp() + 1;
+ aiq_stats_input.rgbs_grids = (const ia_aiq_rgbs_grid **)&rgbs_grids;
+ aiq_stats_input.num_rgbs_grids = 1;
+ aiq_stats_input.af_grids = (const ia_aiq_af_grid **)(&af_grids);
+ aiq_stats_input.num_af_grids = 1;
+
+ aiq_stats_input.frame_af_parameters = NULL;
+ aiq_stats_input.external_histograms = NULL;
+ aiq_stats_input.num_external_histograms = 0;
+ aiq_stats_input.camera_orientation = ia_aiq_camera_orientation_unknown;
+
+ if (_pa_result)
+ aiq_stats_input.frame_pa_parameters = _pa_result;
+ if (_ae_handler->is_started())
+ aiq_stats_input.frame_ae_parameters = _ae_handler->get_result ();
+ //if (_awb_handler->is_started())
+ // aiq_stats_input.frame_awb_parameters = _awb_handler->get_result();
+
+ if (!_adaptor->convert_statistics (stats->get_3a_stats(), &rgbs_grids, &af_grids)) {
+ XCAM_LOG_WARNING ("ia isp adaptor convert 3a stats failed");
+ return false;
+ }
+
+ XCAM_LOG_DEBUG ("statistics grid info, width:%u, height:%u, blk_r:%u, blk_b:%u, blk_gr:%u, blk_gb:%u",
+ aiq_stats_input.rgbs_grids[0]->grid_width,
+ aiq_stats_input.rgbs_grids[0]->grid_height,
+ aiq_stats_input.rgbs_grids[0]->blocks_ptr->avg_r,
+ aiq_stats_input.rgbs_grids[0]->blocks_ptr->avg_b,
+ aiq_stats_input.rgbs_grids[0]->blocks_ptr->avg_gr,
+ aiq_stats_input.rgbs_grids[0]->blocks_ptr->avg_gb);
+
+ if (ia_aiq_statistics_set(get_handle (), &aiq_stats_input) != ia_err_none) {
+ XCAM_LOG_ERROR ("Aiq set statistic failed");
+ return false;
+ }
+ return true;
+}
+
+XCamReturn AiqCompositor::integrate (X3aResultList &results)
+{
+ IspInputParameters isp_params;
+ ia_aiq_pa_input_params pa_input;
+ ia_aiq_pa_results *pa_result = NULL;
+ ia_err ia_error = ia_err_none;
+ ia_binary_data output;
+ AiqAeHandler *aiq_ae = _ae_handler.ptr();
+ AiqAwbHandler *aiq_awb = _awb_handler.ptr();
+ AiqAfHandler *aiq_af = _af_handler.ptr();
+ AiqCommonHandler *aiq_common = _common_handler.ptr();
+ struct atomisp_parameters *isp_3a_result = NULL;
+ SmartPtr<X3aResult> isp_results;
+
+ XCAM_FAIL_RETURN (
+ ERROR,
+ aiq_ae && aiq_awb && aiq_af && aiq_common,
+ XCAM_RETURN_ERROR_PARAM,
+ "handlers are not AIQ inherited");
+
+ xcam_mem_clear (&pa_input);
+ pa_input.frame_use = _frame_use;
+ pa_input.awb_results = aiq_awb->get_result ();
+ if (aiq_ae->is_started())
+ pa_input.exposure_params = (aiq_ae->get_result ())->exposures[0].exposure;
+ pa_input.sensor_frame_params = &_frame_params;
+ pa_input.color_gains = NULL;
+
+ ia_error = ia_aiq_pa_run (_ia_handle, &pa_input, &pa_result);
+ if (ia_error != ia_err_none) {
+ XCAM_LOG_WARNING ("AIQ pa run failed"); // but not return error
+ }
+ _pa_result = pa_result;
+
+ isp_params.frame_use = _frame_use;
+ isp_params.awb_results = aiq_awb->get_result ();
+ if (aiq_ae->is_started())
+ isp_params.exposure_results = (aiq_ae->get_result ())->exposures[0].exposure;
+ isp_params.gbce_results = aiq_common->get_gbce_result ();
+ isp_params.sensor_frame_params = &_frame_params;
+ isp_params.pa_results = pa_result;
+
+ isp_params.manual_brightness = (int8_t)(aiq_common->get_brightness_unlock() * 128.0);
+ isp_params.manual_contrast = (int8_t)(aiq_common->get_contrast_unlock() * 128.0);
+ isp_params.manual_saturation = (int8_t)(aiq_common->get_saturation_unlock() * 128.0);
+ isp_params.manual_hue = (int8_t)(aiq_common->get_hue_unlock() * 128.0);
+ isp_params.manual_sharpness = (int8_t)(aiq_common->get_sharpness_unlock() * 128.0);
+ isp_params.manual_nr_level = (int8_t)(aiq_common->get_nr_level_unlock() * 128.0);
+
+ xcam_mem_clear (&output);
+ if (!_adaptor->run (&isp_params, &output)) {
+ XCAM_LOG_ERROR("Aiq to isp adaptor running failed");
+ return XCAM_RETURN_ERROR_ISP;
+ }
+ isp_3a_result = ((struct atomisp_parameters *)output.data);
+ isp_results = generate_3a_configs (isp_3a_result);
+ results.push_back (isp_results);
+ return XCAM_RETURN_NO_ERROR;
+}
+
+SmartPtr<X3aResult>
+AiqCompositor::generate_3a_configs (struct atomisp_parameters *parameters)
+{
+ SmartPtr<X3aResult> ret;
+
+ X3aAtomIspParametersResult *x3a_result =
+ new X3aAtomIspParametersResult (XCAM_IMAGE_PROCESS_ONCE);
+ x3a_result->set_isp_config (*parameters);
+ ret = x3a_result;
+ return ret;
+}
+
+void
+AiqCompositor::set_ae_handler (SmartPtr<AiqAeHandler> &handler)
+{
+ XCAM_ASSERT (!_ae_handler.ptr());
+ _ae_handler = handler;
+}
+
+void
+AiqCompositor::set_awb_handler (SmartPtr<AiqAwbHandler> &handler)
+{
+ XCAM_ASSERT (!_awb_handler.ptr());
+ _awb_handler = handler;
+}
+
+void
+AiqCompositor::set_af_handler (SmartPtr<AiqAfHandler> &handler)
+{
+ XCAM_ASSERT (!_af_handler.ptr());
+ _af_handler = handler;
+}
+
+void
+AiqCompositor::set_common_handler (SmartPtr<AiqCommonHandler> &handler)
+{
+ XCAM_ASSERT (!_common_handler.ptr());
+ _common_handler = handler;
+}
+
+
+};
diff --git a/xcore/aiq_handler.h b/xcore/aiq_handler.h
new file mode 100644
index 0000000..e78db94
--- /dev/null
+++ b/xcore/aiq_handler.h
@@ -0,0 +1,284 @@
+/*
+ * aiq_handler.h - AIQ handler
+ *
+ * Copyright (c) 2014-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>
+ */
+
+#ifndef XCAM_AIQ_HANDLER_H
+#define XCAM_AIQ_HANDLER_H
+
+#include "xcam_common.h"
+#include "xcam_defs.h"
+#include "xcam_utils.h"
+#include "handler_interface.h"
+#include "x3a_statistics_queue.h"
+#include "ia_types.h"
+#include "ia_aiq_types.h"
+#include "ia_cmc_parser.h"
+#include "ia_mkn_encoder.h"
+#include "ia_aiq.h"
+#include "ia_coordinate.h"
+
+typedef struct ia_isp_t ia_isp;
+
+namespace XCam {
+
+class AiqCompositor;
+struct IspInputParameters;
+
+class IaIspAdaptor {
+public:
+ explicit IaIspAdaptor()
+ : _handle (NULL)
+ {}
+ virtual ~IaIspAdaptor() {}
+
+ virtual bool init (
+ const ia_binary_data *cpf,
+ unsigned int max_width,
+ unsigned int max_height,
+ ia_cmc_t *cmc,
+ ia_mkn *mkn) = 0;
+ virtual bool convert_statistics (
+ void *statistics,
+ ia_aiq_rgbs_grid **out_rgbs_grid,
+ ia_aiq_af_grid **out_af_grid) = 0;
+ virtual bool run (
+ const IspInputParameters *isp_input_params,
+ ia_binary_data *output_data) = 0;
+
+private:
+ XCAM_DEAD_COPY (IaIspAdaptor);
+
+protected:
+ ia_isp *_handle;
+};
+
+class AiqAeHandler
+ : public AeHandler
+{
+private:
+ struct AiqAeResult {
+ ia_aiq_ae_results ae_result;
+ ia_aiq_ae_exposure_result ae_exp_ret;
+ ia_aiq_exposure_parameters aiq_exp_param;
+ ia_aiq_exposure_sensor_parameters sensor_exp_param;
+ ia_aiq_hist_weight_grid weight_grid;
+ ia_aiq_flash_parameters flash_param;
+
+ AiqAeResult();
+ void copy (ia_aiq_ae_results *result);
+
+ XCAM_DEAD_COPY (AiqAeResult);
+ };
+
+public:
+ explicit AiqAeHandler (SmartPtr<AiqCompositor> &aiq_compositor);
+ ~AiqAeHandler () {}
+
+ bool is_started () const {
+ return _started;
+ }
+
+ bool set_description (struct atomisp_sensor_mode_data *sensor_mode_data);
+
+ ia_aiq_ae_results *get_result () {
+ return &_result.ae_result;
+ }
+
+ //virtual functions from AnalyzerHandler
+ virtual XCamReturn analyze (X3aResultList &output);
+
+ // virtual functions from AeHandler
+ virtual XCamFlickerMode get_flicker_mode ();
+ virtual int64_t get_current_exposure_time ();
+ virtual double get_current_analog_gain ();
+ virtual double get_max_analog_gain ();
+
+private:
+ bool ensure_ia_parameters ();
+ bool ensure_ae_mode ();
+ bool ensure_ae_metering_mode ();
+ bool ensure_ae_priority_mode ();
+ bool ensure_ae_flicker_mode ();
+ bool ensure_ae_manual ();
+ bool ensure_ae_ev_shift ();
+
+ void adjust_ae_speed (
+ ia_aiq_exposure_sensor_parameters &cur_res,
+ const ia_aiq_exposure_sensor_parameters &last_res, double ae_speed);
+ void adjust_ae_limitation (ia_aiq_exposure_sensor_parameters &cur_res);
+ bool manual_control_result (
+ ia_aiq_exposure_sensor_parameters &cur_res,
+ const ia_aiq_exposure_sensor_parameters &last_res);
+
+ SmartPtr<X3aResult> pop_result ();
+
+ static void convert_xcam_window_to_ia (const XCam3AWindow &window, ia_rectangle &ia_window);
+
+private:
+ XCAM_DEAD_COPY (AiqAeHandler);
+
+protected:
+ SmartPtr<AiqCompositor> _aiq_compositor;
+ /* AIQ */
+ ia_rectangle _ia_ae_window;
+ ia_aiq_exposure_sensor_descriptor _sensor_descriptor;
+ ia_aiq_ae_manual_limits _manual_limits;
+
+ ia_aiq_ae_input_params _input;
+
+ /* result */
+ AiqAeResult _result;
+ uint32_t _calculate_period;
+ bool _started;
+};
+
+class AiqAwbHandler
+ : public AwbHandler
+{
+public:
+ explicit AiqAwbHandler (SmartPtr<AiqCompositor> &aiq_compositor);
+ ~AiqAwbHandler () {}
+
+ virtual XCamReturn analyze (X3aResultList &output);
+
+ ia_aiq_awb_results *get_result () {
+ return &_result;
+ }
+ bool is_started () const {
+ return _started;
+ }
+
+private:
+ bool ensure_ia_parameters ();
+ bool ensure_awb_mode ();
+ void adjust_speed (const ia_aiq_awb_results &last_ret);
+
+ XCAM_DEAD_COPY (AiqAwbHandler);
+
+protected:
+ SmartPtr<AiqCompositor> _aiq_compositor;
+ /*aiq*/
+ ia_aiq_awb_input_params _input;
+ ia_aiq_awb_manual_cct_range _cct_range;
+
+ ia_aiq_awb_results _result;
+ ia_aiq_awb_results _history_result;
+ bool _started;
+};
+
+class AiqAfHandler
+ : public AfHandler
+{
+public:
+ explicit AiqAfHandler (SmartPtr<AiqCompositor> &aiq_compositor)
+ : _aiq_compositor (aiq_compositor)
+ {}
+ ~AiqAfHandler () {}
+
+ virtual XCamReturn analyze (X3aResultList &output);
+
+private:
+ XCAM_DEAD_COPY (AiqAfHandler);
+
+protected:
+ SmartPtr<AiqCompositor> _aiq_compositor;
+};
+
+class AiqCommonHandler
+ : public CommonHandler
+{
+public:
+ explicit AiqCommonHandler (SmartPtr<AiqCompositor> &aiq_compositor);
+ ~AiqCommonHandler () {}
+
+ virtual XCamReturn analyze (X3aResultList &output);
+ ia_aiq_gbce_results *get_gbce_result () {
+ return _gbce_result;
+ }
+
+private:
+ XCAM_DEAD_COPY (AiqCommonHandler);
+
+protected:
+ SmartPtr<AiqCompositor> _aiq_compositor;
+ ia_aiq_gbce_results *_gbce_result;
+};
+
+class AiqCompositor {
+public:
+ explicit AiqCompositor ();
+ ~AiqCompositor ();
+
+ void set_ae_handler (SmartPtr<AiqAeHandler> &handler);
+ void set_awb_handler (SmartPtr<AiqAwbHandler> &handler);
+ void set_af_handler (SmartPtr<AiqAfHandler> &handler);
+ void set_common_handler (SmartPtr<AiqCommonHandler> &handler);
+
+ void set_frame_use (ia_aiq_frame_use value) {
+ _frame_use = value;
+ }
+ void set_size (uint32_t width, uint32_t height) {
+ _width = width;
+ _height = height;
+ }
+ bool open (ia_binary_data &cpf);
+ void close ();
+
+ bool set_sensor_mode_data (struct atomisp_sensor_mode_data *sensor_mode);
+ bool set_3a_stats (SmartPtr<X3aIspStatistics> &stats);
+
+ ia_aiq * get_handle () {
+ return _ia_handle;
+ }
+ ia_aiq_frame_use get_frame_use () const {
+ return _frame_use;
+ }
+
+ XCamReturn integrate ( X3aResultList &results);
+
+ SmartPtr<X3aResult> generate_3a_configs (struct atomisp_parameters *parameters);
+ void convert_window_to_ia (const XCam3AWindow &window, ia_rectangle &ia_window);
+
+private:
+
+ XCAM_DEAD_COPY (AiqCompositor);
+
+private:
+ SmartPtr<IaIspAdaptor> _adaptor;
+ SmartPtr<AiqAeHandler> _ae_handler;
+ SmartPtr<AiqAwbHandler> _awb_handler;
+ SmartPtr<AiqAfHandler> _af_handler;
+ SmartPtr<AiqCommonHandler> _common_handler;
+ ia_aiq *_ia_handle;
+ ia_mkn *_ia_mkn;
+ ia_aiq_pa_results *_pa_result;
+ ia_aiq_frame_use _frame_use;
+ ia_aiq_frame_params _frame_params;
+
+ /*grids*/
+ ;
+
+ uint32_t _width;
+ uint32_t _height;
+
+};
+
+};
+
+#endif //XCAM_AIQ_HANDLER_H
diff --git a/xcore/atomisp_device.cpp b/xcore/atomisp_device.cpp
new file mode 100644
index 0000000..5e30e6c
--- /dev/null
+++ b/xcore/atomisp_device.cpp
@@ -0,0 +1,186 @@
+/*
+ * atomisp_device.cpp - atomisp device
+ *
+ * Copyright (c) 2014-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 "atomisp_device.h"
+#include "v4l2_buffer_proxy.h"
+#include <linux/v4l2-subdev.h>
+#if HAVE_LIBDRM
+#include <drm.h>
+#include <drm_mode.h>
+#include <xf86drm.h>
+#include <xf86drmMode.h>
+
+#define DEFAULT_DRM_DEVICE "i915"
+#endif
+
+namespace XCam {
+
+AtomispDevice::AtomispDevice (const char *name)
+ : V4l2Device (name)
+ , _drm_handle (-1)
+{
+}
+
+AtomispDevice::~AtomispDevice ()
+{
+#if HAVE_LIBDRM
+ if (_drm_handle > 0)
+ drmClose (_drm_handle);
+#endif
+}
+
+XCamReturn
+AtomispDevice::pre_set_format (struct v4l2_format &format)
+{
+ uint32_t fps_n = 0, fps_d = 0;
+ struct v4l2_subdev_format subdev_fmt;
+
+ // set framerate by subdev
+ this->get_framerate (fps_n, fps_d);
+ if (fps_n != 0 && fps_d != 0) {
+ struct v4l2_subdev_frame_interval frame_intvl;
+
+ xcam_mem_clear (&frame_intvl);
+ if (io_control (VIDIOC_SUBDEV_G_FRAME_INTERVAL, &frame_intvl) < 0) {
+ XCAM_LOG_WARNING ("atomisp device(%s) get framerate failed ", XCAM_STR (get_device_name()));
+ } else {
+ frame_intvl.interval.denominator = fps_n;
+ frame_intvl.interval.numerator = fps_d;
+ if (io_control (VIDIOC_SUBDEV_S_FRAME_INTERVAL, &frame_intvl) < 0) {
+ XCAM_LOG_WARNING ("atomisp device(%s) set framerate failed", XCAM_STR (get_device_name()));
+ }
+ }
+ }
+
+ xcam_mem_clear (&subdev_fmt);
+ subdev_fmt.pad = 0;
+ subdev_fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE;
+ subdev_fmt.format.width = format.fmt.pix.width + 32;
+ subdev_fmt.format.height = format.fmt.pix.height + 17;
+ subdev_fmt.format.code = V4L2_MBUS_FMT_SRGGB10_1X10; //depends on sensor V4L2_MBUS_FMT_UYVY8_1X16;
+ subdev_fmt.format.field = V4L2_FIELD_NONE;
+
+ if (io_control(VIDIOC_SUBDEV_S_FMT, &subdev_fmt) < 0) {
+ XCAM_LOG_ERROR ("atomisp device(%s) set subdev format failed", XCAM_STR (get_device_name()));
+ return XCAM_RETURN_ERROR_IOCTL;
+ }
+ return XCAM_RETURN_NO_ERROR;
+}
+
+XCamReturn
+AtomispDevice::allocate_buffer (
+ SmartPtr<V4l2Buffer> &buf,
+ const struct v4l2_format &format,
+ const uint32_t index)
+{
+#if HAVE_LIBDRM
+ if (get_mem_type () == V4L2_MEMORY_DMABUF) {
+ buf = create_drm_buf (format, index);
+ if (!buf.ptr()) {
+ XCAM_LOG_WARNING ("atomisp device(%s) allocate buffer failed", XCAM_STR (get_device_name()));
+ return XCAM_RETURN_ERROR_MEM;
+ }
+ return XCAM_RETURN_NO_ERROR;
+ }
+#endif
+
+ return V4l2Device::allocate_buffer (buf, format, index);
+}
+
+#if HAVE_LIBDRM
+
+class DrmV4l2Buffer
+ : public V4l2Buffer
+{
+public:
+ explicit DrmV4l2Buffer (
+ uint32_t gem_handle,
+ const struct v4l2_buffer &buf,
+ const struct v4l2_format &format,
+ AtomispDevice *device
+ )
+ : V4l2Buffer (buf, format)
+ , _gem_handle (gem_handle)
+ , _device (device)
+ {}
+ ~DrmV4l2Buffer ();
+
+private:
+ uint32_t _gem_handle;
+ AtomispDevice *_device;
+};
+
+DrmV4l2Buffer::~DrmV4l2Buffer ()
+{
+ XCAM_ASSERT (_device);
+ int handle = _device->get_drm_handle ();
+ if (handle > 0) {
+ struct drm_mode_destroy_dumb gem;
+ xcam_mem_clear (&gem);
+ gem.handle = _gem_handle;
+ xcam_device_ioctl (handle, DRM_IOCTL_MODE_DESTROY_DUMB, &gem);
+ }
+}
+
+
+SmartPtr<V4l2Buffer>
+AtomispDevice::create_drm_buf (const struct v4l2_format &format, const uint32_t index)
+{
+ struct drm_mode_create_dumb gem;
+ struct drm_prime_handle prime;
+ struct v4l2_buffer v4l2_buf;
+ int ret = 0;
+
+ xcam_mem_clear (&gem);
+ xcam_mem_clear (&prime);
+ xcam_mem_clear (&v4l2_buf);
+
+ if (_drm_handle < 0)
+ _drm_handle = drmOpen (DEFAULT_DRM_DEVICE, NULL);
+ if (_drm_handle < 0) {
+ XCAM_LOG_WARNING ("open drm device(%s) failed", DEFAULT_DRM_DEVICE);
+ return NULL;
+ }
+
+ gem.width = format.fmt.pix.bytesperline;
+ gem.height = format.fmt.pix.height;
+ gem.bpp = 8;
+ ret = xcam_device_ioctl (_drm_handle, DRM_IOCTL_MODE_CREATE_DUMB, &gem);
+ XCAM_ASSERT (ret >= 0);
+
+ prime.handle = gem.handle;
+ ret = xcam_device_ioctl (_drm_handle, DRM_IOCTL_PRIME_HANDLE_TO_FD, &prime);
+ if (ret < 0) {
+ XCAM_LOG_WARNING ("create drm failed on DRM_IOCTL_PRIME_HANDLE_TO_FD");
+ return NULL;
+ }
+
+ v4l2_buf.index = index;
+ v4l2_buf.type = get_capture_buf_type ();
+ v4l2_buf.memory = V4L2_MEMORY_DMABUF;
+ v4l2_buf.m.fd = prime.fd;
+ v4l2_buf.length = XCAM_MAX (format.fmt.pix.sizeimage, gem.size); // todo check gem.size and format.fmt.pix.length
+ XCAM_LOG_DEBUG ("create drm buffer size:%lld", gem.size);
+ return new DrmV4l2Buffer (gem.handle, v4l2_buf, format, this);
+}
+
+#endif
+
+};
diff --git a/xcore/atomisp_device.h b/xcore/atomisp_device.h
new file mode 100644
index 0000000..72f2479
--- /dev/null
+++ b/xcore/atomisp_device.h
@@ -0,0 +1,62 @@
+/*
+ * atomisp_device.h - atomisp device
+ *
+ * Copyright (c) 2014-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>
+ */
+
+#ifndef XCAM_ATOMISP_DEVICE_H
+#define XCAM_ATOMISP_DEVICE_H
+
+#include "xcam_common.h"
+#include "xcam_defs.h"
+#include "v4l2_device.h"
+
+namespace XCam {
+
+class AtomispDevice
+ : public V4l2Device
+{
+ friend class DrmV4l2Buffer;
+
+public:
+ explicit AtomispDevice (const char *name = NULL);
+ ~AtomispDevice ();
+
+protected:
+ virtual XCamReturn pre_set_format (struct v4l2_format &format);
+ virtual XCamReturn allocate_buffer (
+ SmartPtr<V4l2Buffer> &buf,
+ const struct v4l2_format &format,
+ const uint32_t index);
+
+private:
+ XCAM_DEAD_COPY (AtomispDevice);
+
+#if HAVE_LIBDRM
+ int get_drm_handle () const {
+ return _drm_handle;
+ }
+ SmartPtr<V4l2Buffer> create_drm_buf (const struct v4l2_format &format, const uint32_t index);
+#endif
+
+private:
+ int _drm_handle;
+};
+
+};
+
+#endif //XCAM_ATOMISP_DEVICE_H
diff --git a/xcore/device_manager.cpp b/xcore/device_manager.cpp
new file mode 100644
index 0000000..193350c
--- /dev/null
+++ b/xcore/device_manager.cpp
@@ -0,0 +1,337 @@
+/*
+ * device_manager.h - device manager
+ *
+ * Copyright (c) 2014-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 "device_manager.h"
+#include "poll_thread.h"
+#include "xcam_thread.h"
+#include "x3a_image_process_center.h"
+#include "x3a_analyzer_manager.h"
+#include "isp_image_processor.h"
+#include "isp_controller.h"
+#if HAVE_IA_AIQ
+#include "x3a_analyzer_aiq.h"
+#endif
+
+#define XCAM_FAILED_STOP(exp, msg, ...) \
+ if ((exp) != XCAM_RETURN_NO_ERROR) { \
+ XCAM_LOG_ERROR (msg, ## __VA_ARGS__); \
+ stop (); \
+ return ret; \
+ }
+
+namespace XCam {
+
+class MessageThread
+ : public Thread
+{
+public:
+ explicit MessageThread (DeviceManager *dev_manager)
+ : Thread ("MessageThread")
+ , _manager (dev_manager)
+ {}
+
+protected:
+ virtual bool loop ();
+
+ DeviceManager *_manager;
+};
+
+bool
+MessageThread::loop()
+{
+ XCamReturn ret = _manager->message_loop();
+ if (ret == XCAM_RETURN_NO_ERROR || ret == XCAM_RETURN_ERROR_TIMEOUT)
+ return true;
+
+ return false;
+}
+
+XCamMessage::XCamMessage (XCamMessageType type, int64_t timestamp, const char *message)
+ : timestamp (timestamp)
+ , msg_id (type)
+{
+ if (message)
+ this->msg = strdup (message);
+}
+
+XCamMessage::~XCamMessage ()
+{
+ if (msg)
+ xcam_free (msg);
+}
+
+DeviceManager::DeviceManager()
+ : _has_3a (true)
+ , _is_running (false)
+{
+ _3a_process_center = new X3aImageProcessCenter;
+ XCAM_LOG_DEBUG ("~DeviceManager construction");
+}
+
+DeviceManager::~DeviceManager()
+{
+ XCAM_LOG_DEBUG ("~DeviceManager destruction");
+}
+
+bool
+DeviceManager::set_capture_device (SmartPtr<V4l2Device> &device)
+{
+ if (is_running())
+ return false;
+
+ XCAM_ASSERT (device.ptr () && !_device.ptr ());
+ _device = device;
+ return true;
+}
+bool
+DeviceManager::set_event_device (SmartPtr<V4l2SubDevice> &device)
+{
+ if (is_running())
+ return false;
+
+ XCAM_ASSERT (device.ptr () && !_subdevice.ptr ());
+ _subdevice = device;
+ return true;
+}
+
+bool
+DeviceManager::set_isp_controller (SmartPtr<IspController> &controller)
+{
+ if (is_running())
+ return false;
+
+ XCAM_ASSERT (controller.ptr () && !_isp_controller.ptr ());
+ _isp_controller = controller;
+ return true;
+}
+
+bool
+DeviceManager::set_analyzer (SmartPtr<X3aAnalyzer> &analyzer)
+{
+ if (is_running())
+ return false;
+
+ XCAM_ASSERT (analyzer.ptr () && !_3a_analyzer.ptr ());
+ _3a_analyzer = analyzer;
+ return true;
+}
+
+bool
+DeviceManager::add_image_processor (SmartPtr<ImageProcessor> &processor)
+{
+ if (is_running())
+ return false;
+
+ XCAM_ASSERT (processor.ptr ());
+ return _3a_process_center->insert_processor (processor);
+}
+
+XCamReturn
+DeviceManager::start ()
+{
+ XCamReturn ret = XCAM_RETURN_NO_ERROR;
+
+ // start device
+ XCAM_ASSERT (_device->is_opened());
+ if (!_device.ptr() || !_device->is_opened()) {
+ XCAM_FAILED_STOP (ret = XCAM_RETURN_ERROR_FILE, "capture device not ready");
+ }
+ XCAM_FAILED_STOP (ret = _device->start(), "capture device start failed");
+
+ //start subdevice
+ XCAM_ASSERT (_subdevice->is_opened());
+ if (!_subdevice.ptr() || !_subdevice->is_opened()) {
+ XCAM_FAILED_STOP (ret = XCAM_RETURN_ERROR_FILE, "event device not ready");
+ }
+ XCAM_FAILED_STOP (ret = _subdevice->start(), "start event device failed");
+
+ //suppose _device and _subdevice already started
+ if (!_isp_controller.ptr ())
+ _isp_controller = new IspController (_device);
+ XCAM_ASSERT (_isp_controller.ptr());
+
+ if (_has_3a) {
+ // Initialize and start analyzer
+ uint32_t width = 0, height = 0;
+
+ if (!_3a_analyzer.ptr()) {
+ _3a_analyzer = X3aAnalyzerManager::instance()->create_analyzer();
+ }
+ if (!_3a_analyzer.ptr()) {
+ XCAM_FAILED_STOP (ret = XCAM_RETURN_ERROR_PARAM, "create analyzer failed");
+ }
+ _3a_analyzer->set_results_callback (this);
+
+ _device->get_size (width, height);
+ XCAM_FAILED_STOP (ret = _3a_analyzer->init (width, height), "initialize analyzer failed");
+
+ XCAM_FAILED_STOP (ret = _3a_analyzer->start (), "start analyzer failed");
+
+ // Initialize and start image processors
+ if (!_3a_process_center->has_processors()) {
+ // default processor
+ SmartPtr<ImageProcessor> default_processor = new IspImageProcessor (_isp_controller);
+ XCAM_ASSERT (default_processor.ptr ());
+ _3a_process_center->insert_processor (default_processor);
+ }
+
+ _3a_process_center->set_image_callback(this);
+ XCAM_FAILED_STOP (ret = _3a_process_center->start (), "3A process center start failed");
+
+ }
+
+ //Initialize and start poll thread
+ _poll_thread = new PollThread;
+ _poll_thread->set_capture_device (_device);
+ _poll_thread->set_event_device (_subdevice);
+ _poll_thread->set_isp_controller (_isp_controller);
+ _poll_thread->set_callback (this);
+
+ XCAM_FAILED_STOP (ret = _poll_thread->start(), "start poll failed");
+
+ _is_running = true;
+
+ XCAM_LOG_DEBUG ("Device manager started");
+ return XCAM_RETURN_NO_ERROR;
+}
+
+XCamReturn
+DeviceManager::stop ()
+{
+ _is_running = false;
+
+ if (_poll_thread.ptr())
+ _poll_thread->stop ();
+
+ if (_3a_analyzer.ptr()) {
+ _3a_analyzer->stop ();
+ _3a_analyzer->deinit ();
+ }
+
+ if (_3a_process_center.ptr())
+ _3a_process_center->stop ();
+
+ _subdevice->stop ();
+ _device->stop ();
+
+ _isp_controller.release ();
+ _poll_thread.release ();
+
+ XCAM_LOG_DEBUG ("Device manager stopped");
+ return XCAM_RETURN_NO_ERROR;
+}
+
+XCamReturn
+DeviceManager::poll_3a_stats_ready (SmartPtr<X3aIspStatistics> &stats)
+{
+ XCamReturn ret = XCAM_RETURN_NO_ERROR;
+ X3aResultList results;
+ XCAM_ASSERT (_3a_analyzer.ptr());
+
+ ret = _3a_analyzer->push_3a_stats (stats);
+ XCAM_FAIL_RETURN (ERROR,
+ ret == XCAM_RETURN_NO_ERROR,
+ ret,
+ "analyze 3a statistics failed");
+
+ return XCAM_RETURN_NO_ERROR;
+}
+
+XCamReturn
+DeviceManager::poll_dvs_stats_ready ()
+{
+ XCAM_ASSERT (false);
+ // TODO
+ return XCAM_RETURN_NO_ERROR;
+}
+
+XCamReturn
+DeviceManager::poll_buffer_ready (SmartPtr<V4l2BufferProxy> &buf)
+{
+ if (_has_3a) {
+ SmartPtr<VideoBuffer> video_buf = buf;
+ if (_3a_process_center->put_buffer (video_buf) == false)
+ return XCAM_RETURN_ERROR_UNKNOWN;
+ }
+ return XCAM_RETURN_NO_ERROR;
+}
+
+XCamReturn
+DeviceManager::poll_buffer_failed (int64_t timestamp, const char *msg)
+{
+ post_message (XCAM_MESSAGE_BUF_ERROR, timestamp, msg);
+ return XCAM_RETURN_NO_ERROR;
+}
+
+void
+DeviceManager::x3a_calculation_done (X3aAnalyzer *analyzer, X3aResultList &results)
+{
+ XCamReturn ret = _3a_process_center->put_3a_results (results);
+ if (ret != XCAM_RETURN_NO_ERROR && ret != XCAM_RETURN_BYPASS) {
+ XCAM_LOG_WARNING ("apply 3a results failed");
+ return;
+ }
+ AnalyzerCallback::x3a_calculation_done (analyzer, results);
+}
+
+void
+DeviceManager::x3a_calculation_failed (X3aAnalyzer *analyzer, int64_t timestamp, const char *msg)
+{
+ AnalyzerCallback::x3a_calculation_failed (analyzer, timestamp, msg);
+}
+
+void
+DeviceManager::process_buffer_done (ImageProcessor *processor, SmartPtr<VideoBuffer> &buf)
+{
+ ImageProcessCallback::process_buffer_done (processor, buf);
+ handle_buffer (buf);
+}
+
+void
+DeviceManager::process_buffer_failed (ImageProcessor *processor, SmartPtr<VideoBuffer> &buf)
+{
+ ImageProcessCallback::process_buffer_failed (processor, buf);
+}
+
+void
+DeviceManager::process_image_result_done (ImageProcessor *processor, SmartPtr<X3aResult> &result)
+{
+ ImageProcessCallback::process_image_result_done (processor, result);
+}
+
+void
+DeviceManager::post_message (XCamMessageType type, int64_t timestamp, const char *msg)
+{
+ SmartPtr<XCamMessage> new_msg = new XCamMessage (type, timestamp, msg);
+ _msg_queue.push (new_msg);
+}
+
+XCamReturn
+DeviceManager::message_loop ()
+{
+ const static int32_t msg_time_out = -1; //wait until wakeup
+ SmartPtr<XCamMessage> msg = _msg_queue.pop (msg_time_out);
+ if (!msg.ptr ())
+ return XCAM_RETURN_ERROR_THREAD;
+ handle_message (msg);
+ return XCAM_RETURN_NO_ERROR;
+}
+
+};
diff --git a/xcore/device_manager.h b/xcore/device_manager.h
new file mode 100644
index 0000000..5b1489b
--- /dev/null
+++ b/xcore/device_manager.h
@@ -0,0 +1,133 @@
+/*
+ * device_manager.h - device manager
+ *
+ * Copyright (c) 2014-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>
+ */
+
+#ifndef XCAM_DEVICE_MANAGER_H
+#define XCAM_DEVICE_MANAGER_H
+
+#include "xcam_common.h"
+#include "xcam_defs.h"
+#include "smartptr.h"
+#include "v4l2_device.h"
+#include "v4l2_buffer_proxy.h"
+#include "x3a_analyzer.h"
+#include "image_processor.h"
+#include "x3a_statistics_queue.h"
+#include "poll_thread.h"
+
+namespace XCam {
+
+enum XCamMessageType {
+ XCAM_MESSAGE_BUF_OK = 0,
+ XCAM_MESSAGE_BUF_ERROR,
+ XCAM_MESSAGE_STATS_OK,
+ XCAM_MESSAGE_STATS_ERROR,
+ XCAM_MESSAGE_3A_RESULTS_OK,
+ XCAM_MESSAGE_3A_RESULTS_ERROR,
+};
+
+struct XCamMessage {
+ int64_t timestamp;
+ XCamMessageType msg_id;
+ char *msg;
+
+ XCamMessage (
+ XCamMessageType type,
+ int64_t timestamp = InvalidTimestamp,
+ const char *message = NULL);
+ ~XCamMessage ();
+};
+
+class MessageThread;
+class X3aImageProcessCenter;
+
+class DeviceManager
+ : public PollCallback
+ , public AnalyzerCallback
+ , public ImageProcessCallback
+{
+ friend class MessageThread;
+
+public:
+ DeviceManager();
+ virtual ~DeviceManager();
+
+ bool set_capture_device (SmartPtr<V4l2Device> &device);
+ bool set_event_device (SmartPtr<V4l2SubDevice> &device);
+ bool set_isp_controller (SmartPtr<IspController> &controller);
+ bool set_analyzer (SmartPtr<X3aAnalyzer> &analyzer);
+ bool add_image_processor (SmartPtr<ImageProcessor> &processor);
+
+ bool is_running () const {
+ return _is_running;
+ }
+ bool has_3a () const {
+ return _has_3a;
+ }
+
+ XCamReturn start ();
+ XCamReturn stop ();
+
+protected:
+ virtual void handle_message (SmartPtr<XCamMessage> &msg) = 0;
+ virtual void handle_buffer (SmartPtr<VideoBuffer> &buf) = 0;
+
+protected:
+ //virtual functions derived from PollCallback
+ virtual XCamReturn poll_buffer_ready (SmartPtr<V4l2BufferProxy> &buf);
+ virtual XCamReturn poll_buffer_failed (int64_t timestamp, const char *msg);
+ virtual XCamReturn poll_3a_stats_ready (SmartPtr<X3aIspStatistics> &stats);
+ virtual XCamReturn poll_dvs_stats_ready ();
+
+ //virtual functions derived from AnalyzerCallback
+ virtual void x3a_calculation_done (X3aAnalyzer *analyzer, X3aResultList &results);
+ virtual void x3a_calculation_failed (X3aAnalyzer *analyzer, int64_t timestamp, const char *msg);
+
+ //virtual functions derived from ImageProcessCallback
+ virtual void process_buffer_done (ImageProcessor *processor, SmartPtr<VideoBuffer> &buf);
+ virtual void process_buffer_failed (ImageProcessor *processor, SmartPtr<VideoBuffer> &buf);
+ virtual void process_image_result_done (ImageProcessor *processor, SmartPtr<X3aResult> &result);
+
+private:
+ void post_message (XCamMessageType type, int64_t timestamp, const char *msg);
+ XCamReturn message_loop ();
+
+ XCAM_DEAD_COPY (DeviceManager);
+
+protected:
+ SmartPtr<V4l2Device> _device;
+ SmartPtr<V4l2SubDevice> _subdevice;
+ SmartPtr<PollThread> _poll_thread;
+ SmartPtr<IspController> _isp_controller;
+
+ /* 3A calculation and image processing*/
+ bool _has_3a;
+ SmartPtr<X3aAnalyzer> _3a_analyzer;
+ SmartPtr<X3aImageProcessCenter> _3a_process_center;
+
+ /* msg queue */
+ SafeList<XCamMessage> _msg_queue;
+ SmartPtr<MessageThread> _msg_thread;
+
+ bool _is_running;
+};
+
+};
+
+#endif //XCAM_DEVICE_MANAGER_H
diff --git a/xcore/handler_interface.cpp b/xcore/handler_interface.cpp
new file mode 100644
index 0000000..6fdf586
--- /dev/null
+++ b/xcore/handler_interface.cpp
@@ -0,0 +1,455 @@
+/*
+ * handler_interface.cpp - handler interface
+ *
+ * Copyright (c) 2014-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 "handler_interface.h"
+
+namespace XCam {
+
+AeHandler::AeHandler()
+ : _mode (XCAM_AE_MODE_AUTO)
+ , _metering_mode ()
+ , _window ()
+ , _flicker_mode ()
+ , _speed (1.0)
+ , _exposure_time_min (UINT64_C(0))
+ , _exposure_time_max (UINT64_C(0))
+ , _max_analog_gain (0.0)
+ , _manual_exposure_time (UINT64_C (0))
+ , _manual_analog_gain (0.0)
+ , _aperture_fn (0.0)
+ , _ev_shift (0.0)
+{
+ _window.x_start = 0;
+ _window.y_start = 0;
+ _window.x_end = 0;
+ _window.y_end = 0;
+ _window.weight = 0;
+}
+
+bool
+AeHandler::set_mode (XCamAeMode mode)
+{
+ AnalyzerHandler::HanlderLock lock(this);
+ _mode = mode;
+
+ XCAM_LOG_DEBUG ("ae set mode [%d]", mode);
+ return true;
+}
+
+bool
+AeHandler::set_metering_mode (XCamAeMeteringMode mode)
+{
+ AnalyzerHandler::HanlderLock lock(this);
+ _metering_mode = mode;
+
+ XCAM_LOG_DEBUG ("ae set metering mode [%d]", mode);
+ return true;
+}
+
+bool
+AeHandler::set_window (XCam3AWindow *window)
+{
+ AnalyzerHandler::HanlderLock lock(this);
+ _window = *window;
+
+ XCAM_LOG_DEBUG ("ae set metering mode window [x:%d, y:%d, x_end:%d, y_end:%d, weight:%d]",
+ window->x_start,
+ window->y_start,
+ window->x_end,
+ window->y_end,
+ window->weight);
+ return true;
+}
+
+bool
+AeHandler::set_ev_shift (double ev_shift)
+{
+ AnalyzerHandler::HanlderLock lock(this);
+ _ev_shift = ev_shift;
+
+ XCAM_LOG_DEBUG ("ae set ev shift:%.03f", ev_shift);
+ return true;
+}
+
+bool
+AeHandler::set_speed (double speed)
+{
+ AnalyzerHandler::HanlderLock lock(this);
+ _speed = speed;
+
+ XCAM_LOG_DEBUG ("ae set speed:%.03f", speed);
+ return true;
+}
+
+bool
+AeHandler::set_flicker_mode (XCamFlickerMode flicker)
+{
+ AnalyzerHandler::HanlderLock lock(this);
+ _flicker_mode = flicker;
+
+ XCAM_LOG_DEBUG ("ae set flicker:%d", flicker);
+ return true;
+}
+
+XCamFlickerMode
+AeHandler::get_flicker_mode ()
+{
+ AnalyzerHandler::HanlderLock lock(this);
+ return _flicker_mode;
+}
+
+int64_t
+AeHandler::get_current_exposure_time ()
+{
+ AnalyzerHandler::HanlderLock lock(this);
+ if (_mode == XCAM_AE_MODE_MANUAL)
+ return _manual_exposure_time;
+ return INT64_C(-1);
+}
+
+double
+AeHandler::get_current_analog_gain ()
+{
+ AnalyzerHandler::HanlderLock lock(this);
+ if (_mode == XCAM_AE_MODE_MANUAL)
+ return _manual_analog_gain;
+ return 0.0;
+}
+
+bool
+AeHandler::set_manual_exposure_time (int64_t time_in_us)
+{
+ AnalyzerHandler::HanlderLock lock(this);
+ _manual_exposure_time = time_in_us;
+
+ XCAM_LOG_DEBUG ("ae set manual exposure time: %lldus", time_in_us);
+ return true;
+}
+
+bool
+AeHandler::set_manual_analog_gain (double gain)
+{
+ AnalyzerHandler::HanlderLock lock(this);
+ _manual_analog_gain = gain;
+
+ XCAM_LOG_DEBUG ("ae set manual analog gain: %.03f", gain);
+ return true;
+}
+
+bool
+AeHandler::set_aperture (double fn)
+{
+ AnalyzerHandler::HanlderLock lock(this);
+ _aperture_fn = fn;
+
+ XCAM_LOG_DEBUG ("ae set aperture fn: %.03f", fn);
+ return true;
+}
+
+bool
+AeHandler::set_max_analog_gain (double max_gain)
+{
+ AnalyzerHandler::HanlderLock lock(this);
+ _max_analog_gain = max_gain;
+
+ XCAM_LOG_DEBUG ("ae set max analog_gain: %.03f", max_gain);
+ return true;
+}
+
+double AeHandler::get_max_analog_gain ()
+{
+ AnalyzerHandler::HanlderLock lock(this);
+ return _max_analog_gain;
+}
+
+bool AeHandler::set_exposure_time_range (int64_t min_time_in_us, int64_t max_time_in_us)
+{
+ AnalyzerHandler::HanlderLock lock(this);
+ _exposure_time_min = min_time_in_us;
+ _exposure_time_max = max_time_in_us;
+
+ XCAM_LOG_DEBUG ("ae set exposrue range[%lldus, %lldus]", min_time_in_us, max_time_in_us);
+ return true;
+}
+
+bool
+AeHandler::get_exposure_time_range (int64_t *min_time_in_us, int64_t *max_time_in_us)
+{
+ XCAM_ASSERT (min_time_in_us && max_time_in_us);
+
+ AnalyzerHandler::HanlderLock lock(this);
+ *min_time_in_us = _exposure_time_min;
+ *max_time_in_us = _exposure_time_max;
+
+ return true;
+}
+
+AwbHandler::AwbHandler()
+ : _mode (XCAM_AWB_MODE_AUTO)
+ , _speed (1.0)
+ , _cct_min (0)
+ , _cct_max (0)
+ , _gr_gain (0.0)
+ , _r_gain (0.0)
+ , _b_gain (0.0)
+ , _gb_gain (0.0)
+{}
+
+bool
+AwbHandler::set_mode (XCamAwbMode mode)
+{
+ AnalyzerHandler::HanlderLock lock(this);
+ _mode = mode;
+
+ XCAM_LOG_DEBUG ("awb set mode [%d]", mode);
+ return true;
+}
+
+bool
+AwbHandler::set_speed (double speed)
+{
+ XCAM_FAIL_RETURN (
+ ERROR,
+ (0.0 < speed) && (speed <= 1.0),
+ false,
+ "awb speed(%f) is out of range, suggest (0.0, 1.0]", speed);
+
+ AnalyzerHandler::HanlderLock lock(this);
+ _speed = speed;
+
+ XCAM_LOG_DEBUG ("awb set speed [%f]", speed);
+ return true;
+}
+
+bool
+AwbHandler::set_color_temperature_range (uint32_t cct_min, uint32_t cct_max)
+{
+ XCAM_FAIL_RETURN (
+ ERROR,
+ (cct_min <= cct_max),
+ false,
+ "awb set wrong cct(%u, %u) parameters", cct_min, cct_max);
+
+ AnalyzerHandler::HanlderLock lock(this);
+ _cct_min = cct_min;
+ _cct_max = cct_max;
+
+ XCAM_LOG_DEBUG ("awb set cct range [%u, %u]", cct_min, cct_max);
+ return true;
+}
+
+bool
+AwbHandler::set_manual_gain (double gr, double r, double b, double gb)
+{
+ XCAM_FAIL_RETURN (
+ ERROR,
+ gr >= 0.0 && r >= 0.0 && b >= 0.0 && gb >= 0.0,
+ false,
+ "awb manual gain value must >= 0.0");
+
+ AnalyzerHandler::HanlderLock lock(this);
+ _gr_gain = gr;
+ _r_gain = r;
+ _b_gain = b;
+ _gb_gain = gb;
+ XCAM_LOG_DEBUG ("awb set manual gain value(gr:%.03f, r:%.03f, b:%.03f, gb:%.03f)", gr, r, b, gb);
+ return true;
+}
+
+CommonHandler::CommonHandler()
+ : _is_manual_gamma (false)
+ , _nr_level (0.0)
+ , _tnr_level (0.0)
+ , _brightness (0.0)
+ , _contrast (0.0)
+ , _hue (0.0)
+ , _saturation (0.0)
+ , _sharpness (0.0)
+ , _enable_dvs (false)
+ , _enable_gbce (false)
+ , _enable_night_mode (false)
+{}
+
+bool CommonHandler::set_dvs (bool enable)
+{
+ AnalyzerHandler::HanlderLock lock(this);
+ _enable_dvs = enable;
+
+ XCAM_LOG_DEBUG ("common 3A enable dvs:%s", XCAM_BOOL2STR(enable));
+ return true;
+}
+
+bool
+CommonHandler::set_gbce (bool enable)
+{
+ AnalyzerHandler::HanlderLock lock(this);
+ _enable_gbce = enable;
+
+ XCAM_LOG_DEBUG ("common 3A enable gbce:%s", XCAM_BOOL2STR(enable));
+ return true;
+}
+
+bool
+CommonHandler::set_night_mode (bool enable)
+{
+ AnalyzerHandler::HanlderLock lock(this);
+ _enable_night_mode = enable;
+
+ XCAM_LOG_DEBUG ("common 3A enable night mode:%s", XCAM_BOOL2STR(enable));
+ return true;
+}
+
+/* Picture quality */
+bool
+CommonHandler::set_noise_reduction_level (double level)
+{
+ XCAM_FAIL_RETURN (
+ ERROR,
+ level >= -1.0 && level < 1.0,
+ false,
+ "set NR levlel(%.03f) out of range[-1.0, 1.0]", level);
+
+ AnalyzerHandler::HanlderLock lock(this);
+ _nr_level = level;
+
+ XCAM_LOG_DEBUG ("common 3A set NR level:%.03f", level);
+ return true;
+}
+
+bool
+CommonHandler::set_temporal_noise_reduction_level (double level)
+{
+ XCAM_FAIL_RETURN (
+ ERROR,
+ level >= -1.0 && level < 1.0,
+ false,
+ "set TNR levlel(%.03f) out of range[-1.0, 1.0]", level);
+
+ AnalyzerHandler::HanlderLock lock(this);
+ _tnr_level = level;
+
+ XCAM_LOG_DEBUG ("common 3A set TNR level:%.03f", level);
+ return true;
+}
+
+bool
+CommonHandler::set_manual_brightness (double level)
+{
+ XCAM_FAIL_RETURN (
+ ERROR,
+ level >= -1.0 && level < 1.0,
+ false,
+ "set brightness levlel(%.03f) out of range[-1.0, 1.0]", level);
+
+ AnalyzerHandler::HanlderLock lock(this);
+ _brightness = level;
+
+ XCAM_LOG_DEBUG ("common 3A set brightness level:%.03f", level);
+ return true;
+}
+
+bool CommonHandler::set_manual_contrast (double level)
+{
+ XCAM_FAIL_RETURN (
+ ERROR,
+ level >= -1.0 && level < 1.0,
+ false,
+ "set contrast levlel(%.03f) out of range[-1.0, 1.0]", level);
+
+ AnalyzerHandler::HanlderLock lock(this);
+ _contrast = level;
+
+ XCAM_LOG_DEBUG ("common 3A set contrast level:%.03f", level);
+ return true;
+}
+
+bool CommonHandler::set_manual_hue (double level)
+{
+ XCAM_FAIL_RETURN (
+ ERROR,
+ level >= -1.0 && level < 1.0,
+ false,
+ "set hue levlel(%.03f) out of range[-1.0, 1.0]", level);
+
+ AnalyzerHandler::HanlderLock lock(this);
+ _hue = level;
+
+ XCAM_LOG_DEBUG ("common 3A set hue level:%.03f", level);
+ return true;
+}
+
+bool
+CommonHandler::set_manual_saturation (double level)
+{
+ XCAM_FAIL_RETURN (
+ ERROR,
+ level >= -1.0 && level < 1.0,
+ false,
+ "set saturation levlel(%.03f) out of range[-1.0, 1.0]", level);
+
+ AnalyzerHandler::HanlderLock lock(this);
+ _saturation = level;
+
+ XCAM_LOG_DEBUG ("common 3A set saturation level:%.03f", level);
+ return true;
+}
+
+bool CommonHandler::set_manual_sharpness (double level)
+{
+ XCAM_FAIL_RETURN (
+ ERROR,
+ level >= -1.0 && level < 1.0,
+ false,
+ "set sharpness levlel(%.03f) out of range[-1.0, 1.0]", level);
+
+ AnalyzerHandler::HanlderLock lock(this);
+ _sharpness = level;
+
+ XCAM_LOG_DEBUG ("common 3A set sharpness level:%.03f", level);
+ return true;
+}
+
+bool
+CommonHandler::set_gamma_table (double *r_table, double *g_table, double *b_table)
+{
+ AnalyzerHandler::HanlderLock lock(this);
+ if (!r_table && ! g_table && !b_table) {
+ _is_manual_gamma = false;
+ XCAM_LOG_DEBUG ("common 3A disabled gamma");
+ return true;
+ }
+
+ if (!r_table || !g_table || !b_table) {
+ XCAM_LOG_ERROR ("common 3A gamma table parameters wrong");
+ return false;
+ }
+
+ for (uint32_t i = 0; i < XCAM_GAMMA_TABLE_SIZE; ++i) {
+ _r_gamma [i] = r_table [i];
+ _g_gamma [i] = g_table [i];
+ _b_gamma [i] = b_table [i];
+ }
+ _is_manual_gamma = true;
+
+ XCAM_LOG_DEBUG ("common 3A enabled RGB gamma");
+ return true;
+}
+
+};
diff --git a/xcore/handler_interface.h b/xcore/handler_interface.h
new file mode 100644
index 0000000..e200c4b
--- /dev/null
+++ b/xcore/handler_interface.h
@@ -0,0 +1,259 @@
+/*
+ * handler_interface.h - handler interface
+ *
+ * Copyright (c) 2014-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>
+ */
+
+#ifndef XCAM_HANDLER_INTERFACE_H
+#define XCAM_HANDLER_INTERFACE_H
+
+#include "xcam_common.h"
+#include "xcam_defs.h"
+#include "xcam_mutex.h"
+#include "xcam_utils.h"
+#include "x3a_result.h"
+#include "xcam_3a_types.h"
+
+namespace XCam {
+
+class AnalyzerHandler {
+ friend class HanlderLock;
+public:
+ explicit AnalyzerHandler() {}
+ virtual ~AnalyzerHandler () {}
+
+ virtual XCamReturn analyze (X3aResultList &output) = 0;
+
+protected:
+ class HanlderLock
+ : public SmartLock
+ {
+ public:
+ HanlderLock(AnalyzerHandler *handler)
+ : SmartLock (handler->_mutex)
+ {}
+ ~HanlderLock() {}
+ };
+
+ // members
+ Mutex _mutex;
+};
+
+class AeHandler
+ : public AnalyzerHandler
+{
+public:
+ explicit AeHandler();
+ virtual ~AeHandler() {}
+
+ bool set_mode (XCamAeMode mode);
+ bool set_metering_mode (XCamAeMeteringMode mode);
+ bool set_window (XCam3AWindow *window);
+ bool set_ev_shift (double ev_shift);
+ bool set_speed (double speed);
+ bool set_flicker_mode (XCamFlickerMode flicker);
+ bool set_manual_exposure_time (int64_t time_in_us);
+ bool set_manual_analog_gain (double gain);
+ bool set_aperture (double fn);
+ bool set_max_analog_gain (double max_gain);
+ bool set_exposure_time_range (int64_t min_time_in_us, int64_t max_time_in_us);
+ bool get_exposure_time_range (int64_t *min_time_in_us, int64_t *max_time_in_us);
+
+ //virtual functions
+ virtual XCamFlickerMode get_flicker_mode ();
+ virtual int64_t get_current_exposure_time ();
+ virtual double get_current_analog_gain ();
+ virtual double get_max_analog_gain ();
+
+protected:
+ XCamAeMode get_mode_unlock() const {
+ return _mode;
+ }
+ XCamAeMeteringMode get_metering_mode_unlock() const {
+ return _metering_mode;
+ }
+ const XCam3AWindow &get_window_unlock() const {
+ return _window;
+ }
+ XCamFlickerMode get_flicker_mode_unlock() const {
+ return _flicker_mode;
+ }
+ double get_speed_unlock() const {
+ return _speed;
+ }
+ double get_ev_shift_unlock() const {
+ return _ev_shift;
+ }
+
+private:
+ XCAM_DEAD_COPY (AeHandler);
+
+protected:
+ XCamAeMode _mode;
+ XCamAeMeteringMode _metering_mode;
+ XCam3AWindow _window;
+ XCamFlickerMode _flicker_mode;
+ double _speed;
+
+ /* exposure limitation */
+ uint64_t _exposure_time_min, _exposure_time_max; // exposure time range
+ double _max_analog_gain;
+
+ /* exposure manual values */
+ uint64_t _manual_exposure_time;
+ double _manual_analog_gain;
+
+ double _aperture_fn;
+
+ /*ev*/
+ double _ev_shift;
+};
+
+class AwbHandler
+ : public AnalyzerHandler
+{
+public:
+ explicit AwbHandler();
+ virtual ~AwbHandler() {}
+
+ bool set_mode (XCamAwbMode mode);
+ bool set_speed (double speed);
+ bool set_color_temperature_range (uint32_t cct_min, uint32_t cct_max);
+ bool set_manual_gain (double gr, double r, double b, double gb);
+
+protected:
+ XCamAwbMode get_mode_unlock() const {
+ return _mode;
+ }
+ double get_speed_unlock () const {
+ return _speed;
+ }
+
+private:
+ XCAM_DEAD_COPY (AwbHandler);
+
+protected:
+ XCamAwbMode _mode;
+ double _speed;
+ uint32_t _cct_min, _cct_max;
+ XCam3AWindow _window;
+
+ /* manual gain */
+ double _gr_gain;
+ double _r_gain;
+ double _b_gain;
+ double _gb_gain;
+};
+
+class AfHandler
+ : public AnalyzerHandler
+{
+public:
+ explicit AfHandler() {}
+ virtual ~AfHandler() {}
+private:
+ XCAM_DEAD_COPY (AfHandler);
+
+protected:
+};
+
+class CommonHandler
+ : public AnalyzerHandler
+{
+public:
+ explicit CommonHandler();
+ virtual ~CommonHandler() {}
+
+ bool set_dvs (bool enable);
+ bool set_gbce (bool enable);
+ bool set_night_mode (bool enable);
+
+ /* Picture quality */
+ bool set_noise_reduction_level (double level);
+ bool set_temporal_noise_reduction_level (double level);
+ bool set_manual_brightness (double level);
+ bool set_manual_contrast (double level);
+ bool set_manual_hue (double level);
+ bool set_manual_saturation (double level);
+ bool set_manual_sharpness (double level);
+ bool set_gamma_table (double *r_table, double *g_table, double *b_table);
+
+public:
+ bool has_gbce_unlock () const {
+ return _enable_gbce;
+ }
+ bool has_dvs_unlock () const {
+ return _enable_dvs;
+ }
+ bool has_night_mode_unlock () const {
+ return _enable_night_mode;
+ }
+
+ double get_nr_level_unlock () const {
+ return _nr_level;
+ }
+ double get_tnr_level_unlock () const {
+ return _tnr_level;
+ }
+ double get_brightness_unlock () const {
+ return _brightness;
+ }
+ double get_contrast_unlock () const {
+ return _contrast;
+ }
+ double get_hue_unlock () const {
+ return _hue;
+ }
+ double get_saturation_unlock () const {
+ return _saturation;
+ }
+ double get_sharpness_unlock () const {
+ return _sharpness;
+ }
+
+private:
+ XCAM_DEAD_COPY (CommonHandler);
+
+protected:
+ /* R, G, B gamma table, size = XCAM_GAMMA_TABLE_SIZE */
+ bool _is_manual_gamma;
+ double _r_gamma [XCAM_GAMMA_TABLE_SIZE];
+ double _g_gamma [XCAM_GAMMA_TABLE_SIZE];
+ double _b_gamma [XCAM_GAMMA_TABLE_SIZE];
+
+ /*
+ * manual brightness, contrast, hue, saturation, sharpness
+ * -1.0 < value < 1.0
+ */
+ double _nr_level;
+ double _tnr_level;
+
+ double _brightness;
+ double _contrast;
+ double _hue;
+ double _saturation;
+ double _sharpness;
+
+ /* others */
+ bool _enable_dvs;
+ bool _enable_gbce;
+ bool _enable_night_mode;
+};
+
+};
+
+#endif // XCAM_HANDLER_INTERFACE_H
diff --git a/xcore/image_processor.cpp b/xcore/image_processor.cpp
new file mode 100644
index 0000000..ab33306
--- /dev/null
+++ b/xcore/image_processor.cpp
@@ -0,0 +1,231 @@
+/*
+ * image_processor.h - 3a image processor
+ *
+ * Copyright (c) 2014-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 "image_processor.h"
+#include "xcam_thread.h"
+
+namespace XCam {
+
+void
+ImageProcessCallback::process_buffer_done (ImageProcessor *processor, SmartPtr<VideoBuffer> &buf) {
+ XCAM_ASSERT (buf.ptr() && processor);
+
+ int64_t ts = buf->get_timestamp();
+ XCAM_UNUSED (ts);
+ XCAM_LOG_DEBUG (
+ "processor(%s) handled buffer(" XCAM_TIMESTAMP_FORMAT ") successfully",
+ XCAM_STR(processor->get_name()),
+ XCAM_TIMESTAMP_ARGS (ts));
+}
+
+void
+ImageProcessCallback::process_buffer_failed (ImageProcessor *processor, SmartPtr<VideoBuffer> &buf)
+{
+ XCAM_ASSERT (buf.ptr() && processor);
+
+ int64_t ts = buf->get_timestamp();
+ XCAM_UNUSED (ts);
+ XCAM_LOG_WARNING (
+ "processor(%s) handled buffer(" XCAM_TIMESTAMP_FORMAT ") failed",
+ XCAM_STR(processor->get_name()),
+ XCAM_TIMESTAMP_ARGS (ts));
+}
+
+void
+ImageProcessCallback::process_image_result_done (ImageProcessor *processor, SmartPtr<X3aResult> &result)
+{
+ XCAM_ASSERT (result.ptr() && processor);
+
+ int64_t ts = result->get_timestamp();
+ XCAM_UNUSED (ts);
+
+ XCAM_LOG_DEBUG (
+ "processor(%s) processed result(type:%d, timestamp:" XCAM_TIMESTAMP_FORMAT ") done",
+ XCAM_STR(processor->get_name()),
+ (int)result->get_type(),
+ XCAM_TIMESTAMP_ARGS (ts));
+}
+
+class ImageProcessorThread
+ : public Thread
+{
+public:
+ ImageProcessorThread (ImageProcessor *processor)
+ : Thread ("image_processor")
+ , _processor (processor)
+ {}
+ ~ImageProcessorThread () {}
+
+ virtual bool loop ();
+
+private:
+ ImageProcessor *_processor;
+};
+
+bool ImageProcessorThread::loop ()
+{
+ XCamReturn ret = _processor->buffer_process_loop ();
+ if (ret == XCAM_RETURN_NO_ERROR || ret == XCAM_RETURN_ERROR_TIMEOUT)
+ return true;
+ return false;
+}
+
+ImageProcessor::ImageProcessor (const char* name)
+ : _name (NULL)
+ , _callback (NULL)
+{
+ _processor_thread = new ImageProcessorThread (this);
+ if (name)
+ _name = strdup (name);
+}
+
+ImageProcessor::~ImageProcessor ()
+{
+ if (_name)
+ xcam_free (_name);
+}
+
+bool
+ImageProcessor::set_callback (ImageProcessCallback *callback)
+{
+ XCAM_ASSERT (!_callback);
+ _callback = callback;
+ return true;
+}
+
+XCamReturn
+ImageProcessor::start()
+{
+ if (!_processor_thread->start()) {
+ return XCAM_RETURN_ERROR_THREAD;
+ }
+ XCAM_LOG_INFO ("ImageProcessor(%s) started", XCAM_STR (_name));
+ return XCAM_RETURN_NO_ERROR;
+}
+
+XCamReturn
+ImageProcessor::stop()
+{
+ _video_buf_queue.wakeup ();
+ _processor_thread->stop ();
+ XCAM_LOG_DEBUG ("ImageProcessor(%s) stopped", XCAM_STR (_name));
+ return XCAM_RETURN_NO_ERROR;
+}
+
+XCamReturn
+ImageProcessor::push_buffer (SmartPtr<VideoBuffer> &buf)
+{
+ if (_video_buf_queue.push (buf))
+ return XCAM_RETURN_NO_ERROR;
+
+ XCAM_LOG_DEBUG ("processor push buffer failed");
+ return XCAM_RETURN_ERROR_UNKNOWN;
+}
+
+XCamReturn
+ImageProcessor::push_3a_results (X3aResultList &results)
+{
+ X3aResultList valid_results;
+ XCamReturn ret = XCAM_RETURN_NO_ERROR;
+
+ filter_valid_results (results, valid_results);
+ if (valid_results.empty())
+ return XCAM_RETURN_BYPASS;
+
+ ret = apply_3a_results (valid_results);
+
+ if (ret != XCAM_RETURN_NO_ERROR && ret != XCAM_RETURN_BYPASS) {
+ XCAM_LOG_WARNING ("processor(%s) apply results failed", XCAM_STR(get_name()));
+ return ret;
+ }
+
+ if (_callback) {
+ for (X3aResultList::iterator i_res = valid_results.begin();
+ i_res != valid_results.end(); ++i_res) {
+ SmartPtr<X3aResult> &res = *i_res;
+ _callback->process_image_result_done (this, res);
+ }
+ }
+
+ return ret;
+}
+
+XCamReturn
+ImageProcessor::push_3a_result (SmartPtr<X3aResult> &result)
+{
+ X3aResultList valid_results;
+ XCamReturn ret = XCAM_RETURN_NO_ERROR;
+
+ if (!can_process_result(result))
+ return XCAM_RETURN_BYPASS;
+
+ ret = apply_3a_result (result);
+
+ if (ret != XCAM_RETURN_NO_ERROR && ret != XCAM_RETURN_BYPASS) {
+ XCAM_LOG_WARNING ("processor(%s) apply result failed", XCAM_STR(get_name()));
+ return ret;
+ }
+
+ if (_callback) {
+ _callback->process_image_result_done (this, result);
+ }
+
+ return ret;
+}
+
+void
+ImageProcessor::filter_valid_results (X3aResultList &input, X3aResultList &valid_results)
+{
+ for (X3aResultList::iterator i_res = input.begin(); i_res != input.end(); ) {
+ SmartPtr<X3aResult> &res = *i_res;
+ if (can_process_result(res)) {
+ valid_results.push_back (res);
+ input.erase (i_res++);
+ } else
+ ++i_res;
+ }
+}
+
+XCamReturn ImageProcessor::buffer_process_loop ()
+{
+ XCamReturn ret = XCAM_RETURN_NO_ERROR;
+ SmartPtr<VideoBuffer> new_buf;
+ SmartPtr<VideoBuffer> buf = _video_buf_queue.pop();
+
+ if (!buf.ptr())
+ return XCAM_RETURN_ERROR_MEM;
+
+ ret = this->process_buffer (buf, new_buf);
+ if (ret != XCAM_RETURN_NO_ERROR) {
+ XCAM_LOG_DEBUG ("processing buffer failed");
+ }
+
+ if (_callback) {
+ if (ret == XCAM_RETURN_NO_ERROR)
+ _callback->process_buffer_done (this, new_buf);
+ else
+ _callback->process_buffer_failed (this, buf);
+ }
+
+ return XCAM_RETURN_NO_ERROR;
+}
+
+
+};
diff --git a/xcore/image_processor.h b/xcore/image_processor.h
new file mode 100644
index 0000000..777e8cc
--- /dev/null
+++ b/xcore/image_processor.h
@@ -0,0 +1,97 @@
+/*
+ * image_processor.h - 3a image processor
+ *
+ * Copyright (c) 2014-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>
+ */
+
+#ifndef XCAM_IMAGE_PROCESSOR_H
+#define XCAM_IMAGE_PROCESSOR_H
+
+#include "xcam_common.h"
+#include "xcam_defs.h"
+#include "xcam_utils.h"
+#include "video_buffer.h"
+#include "x3a_result.h"
+#include "smartptr.h"
+#include "safe_list.h"
+
+namespace XCam {
+
+class ImageProcessor;
+
+/* callback interface */
+class ImageProcessCallback {
+public:
+ ImageProcessCallback () {}
+ virtual ~ImageProcessCallback () {}
+ virtual void process_buffer_done (ImageProcessor *processor, SmartPtr<VideoBuffer> &buf);
+ virtual void process_buffer_failed (ImageProcessor *processor, SmartPtr<VideoBuffer> &buf);
+ virtual void process_image_result_done (ImageProcessor *processor, SmartPtr<X3aResult> &result);
+
+private:
+ XCAM_DEAD_COPY (ImageProcessCallback);
+};
+
+class ImageProcessorThread;
+
+/* base class, ImageProcessor */
+class ImageProcessor
+{
+ friend class ImageProcessorThread;
+
+ typedef SafeList<VideoBuffer> VideoBufQueue;
+
+public:
+ explicit ImageProcessor (const char* name);
+ virtual ~ImageProcessor ();
+
+ const char *get_name () const {
+ return _name;
+ }
+
+ bool set_callback (ImageProcessCallback *callback);
+ XCamReturn start();
+ XCamReturn stop ();
+
+ XCamReturn push_buffer (SmartPtr<VideoBuffer> &buf);
+ XCamReturn push_3a_results (X3aResultList &results);
+ XCamReturn push_3a_result (SmartPtr<X3aResult> &result);
+
+protected:
+ virtual bool can_process_result (SmartPtr<X3aResult> &result) = 0;
+ virtual XCamReturn apply_3a_results (X3aResultList &results) = 0;
+ virtual XCamReturn apply_3a_result (SmartPtr<X3aResult> &result) = 0;
+ // buffer runs in another thread
+ virtual XCamReturn process_buffer(SmartPtr<VideoBuffer> &input, SmartPtr<VideoBuffer> &output) = 0;
+
+private:
+ void filter_valid_results (X3aResultList &input, X3aResultList &valid_results);
+ XCamReturn buffer_process_loop ();
+
+private:
+ XCAM_DEAD_COPY (ImageProcessor);
+
+protected:
+ char *_name;
+ ImageProcessCallback *_callback;
+ SmartPtr<ImageProcessorThread> _processor_thread;
+ VideoBufQueue _video_buf_queue;
+};
+
+};
+
+#endif //XCAM_IMAGE_PROCESSOR_H
diff --git a/xcore/isp_config_translator.cpp b/xcore/isp_config_translator.cpp
new file mode 100644
index 0000000..d370579
--- /dev/null
+++ b/xcore/isp_config_translator.cpp
@@ -0,0 +1,144 @@
+/*
+ * isp_config_translator.cpp - isp config translator
+ *
+ * Copyright (c) 2014-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 "isp_config_translator.h"
+#include <math.h>
+
+namespace XCam {
+
+static uint32_t
+_get_max_bits (double value)
+{
+ uint32_t max_int = 0;
+ uint32_t interger_bits = 0;
+
+ max_int = (uint32_t)value;
+ while (max_int) {
+ ++interger_bits;
+ max_int = (max_int >> 1);
+ }
+ return interger_bits;
+}
+
+IspConfigTranslator::IspConfigTranslator (SmartPtr<SensorDescriptor> &sensor)
+ : _sensor (sensor)
+{
+ XCAM_ASSERT (_sensor.ptr());
+}
+
+IspConfigTranslator::~IspConfigTranslator ()
+{
+}
+
+XCamReturn
+IspConfigTranslator::translate_white_balance (
+ const XCam3aResultWhiteBalance &from,
+ struct atomisp_wb_config &to)
+{
+ uint32_t interger_bits = 0;
+ double multiplier = 0.0;
+ double max_gain = XCAM_MAX (from.b_gain, from.r_gain);
+ max_gain = XCAM_MAX (max_gain, from.gr_gain);
+ max_gain = XCAM_MAX (max_gain, from.gb_gain);
+
+ interger_bits = _get_max_bits (max_gain);
+ multiplier = (double)(1 << (16 - interger_bits));
+ to.integer_bits = interger_bits;
+ to.gr = (uint32_t)(from.gr_gain * multiplier + 0.5);
+ to.r = (uint32_t)(from.r_gain * multiplier + 0.5);
+ to.b = (uint32_t)(from.b_gain * multiplier + 0.5);
+ to.gb = (uint32_t)(from.gb_gain * multiplier + 0.5);
+
+ return XCAM_RETURN_NO_ERROR;
+}
+
+XCamReturn
+IspConfigTranslator::translate_black_level (
+ const XCam3aResultBlackLevel &from, struct atomisp_ob_config &to)
+{
+ double multiplier = (double)(1 << 16);
+
+ to.mode = atomisp_ob_mode_fixed;
+ to.level_gr = (uint32_t)(from.gr_level * multiplier + 0.5);
+ to.level_r = (uint32_t)(from.r_level * multiplier + 0.5);
+ to.level_b = (uint32_t)(from.b_level * multiplier + 0.5);
+ to.level_gb = (uint32_t)(from.gb_level * multiplier + 0.5);
+
+ return XCAM_RETURN_NO_ERROR;
+}
+
+XCamReturn
+IspConfigTranslator::translate_color_matrix (
+ const XCam3aResultColorMatrix &from, struct atomisp_cc_config &to)
+{
+ double max_value = 0.0;
+ uint32_t interger_bits = 0;
+ double multiplier = 0.0;
+ bool have_minus = false;
+ uint32_t i = 0;
+
+ for (i = 0; i < XCAM_COLOR_MATRIX_SIZE; ++i) {
+ if (fabs(from.matrix [i]) > max_value)
+ max_value = fabs(from.matrix [i]);
+ if (from.matrix [i] < 0)
+ have_minus = true;
+ }
+ interger_bits = _get_max_bits (max_value);
+ if (have_minus)
+ ++interger_bits;
+
+ XCAM_ASSERT (interger_bits < 13);
+ to.fraction_bits = 13 - interger_bits;
+ multiplier = (double)(1 << (13 - interger_bits));
+ for (i = 0; i < XCAM_COLOR_MATRIX_SIZE; ++i) {
+ to.matrix[i] = (int32_t)(from.matrix [i] * multiplier);
+ }
+ return XCAM_RETURN_NO_ERROR;
+}
+
+
+XCamReturn
+IspConfigTranslator::translate_exposure (
+ const XCam3aResultExposure &from,
+ struct atomisp_exposure &to)
+{
+ uint32_t coarse_time = 0, fine_time = 0;
+ int32_t analog_code = 0, digital_code = 0;
+ if (!_sensor->is_ready ()) {
+ XCAM_LOG_WARNING ("translate exposure failed since sensor not ready");
+ return XCAM_RETURN_ERROR_SENSOR;
+ }
+ if (!_sensor->exposure_time_to_integration (from.exposure_time, coarse_time, fine_time)) {
+ XCAM_LOG_WARNING ("translate exposure time failed");
+ return XCAM_RETURN_ERROR_SENSOR;
+ }
+ to.integration_time[0] = coarse_time;
+ to.integration_time[1] = fine_time;
+
+ if (!_sensor->exposure_gain_to_code (from.analog_gain, from.digital_gain, analog_code, digital_code)) {
+ XCAM_LOG_WARNING ("translate exposure gain failed");
+ return XCAM_RETURN_ERROR_SENSOR;
+ }
+ to.gain[0] = analog_code;
+ to.gain[1] = digital_code;
+ return XCAM_RETURN_NO_ERROR;
+}
+
+};
diff --git a/xcore/isp_config_translator.h b/xcore/isp_config_translator.h
new file mode 100644
index 0000000..c24e9c3
--- /dev/null
+++ b/xcore/isp_config_translator.h
@@ -0,0 +1,60 @@
+/*
+ * isp_config_translator.h - isp config translator
+ *
+ * Copyright (c) 2014-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>
+ */
+
+#ifndef XCAM_ISP_CONFIG_TRANSLATOR_H
+#define XCAM_ISP_CONFIG_TRANSLATOR_H
+
+#include "xcam_common.h"
+#include "xcam_defs.h"
+#include "xcam_utils.h"
+#include "x3a_result.h"
+#include "sensor_descriptor.h"
+#include "smartptr.h"
+#include <linux/atomisp.h>
+
+namespace XCam {
+
+class IspConfigTranslator {
+public:
+ explicit IspConfigTranslator (SmartPtr<SensorDescriptor> &sensor);
+ ~IspConfigTranslator ();
+
+ XCamReturn translate_white_balance (const XCam3aResultWhiteBalance &from, struct atomisp_wb_config &to);
+ XCamReturn translate_black_level (const XCam3aResultBlackLevel &from, struct atomisp_ob_config &to);
+ XCamReturn translate_color_matrix (const XCam3aResultColorMatrix &from, struct atomisp_cc_config &to);
+ XCamReturn translate_exposure (const XCam3aResultExposure &from, struct atomisp_exposure &to);
+ XCamReturn translate_demosaicing (const X3aDemosaicResult &from, struct atomisp_de_config &to);
+ XCamReturn translate_defect_pixel (const XCam3aResultDefectPixel &from, struct atomisp_dp_config &to);
+ XCamReturn translate_noise_reduction (const XCam3aResultNoiseReduction &from, struct atomisp_nr_config &to);
+ XCamReturn translate_edge_enhancement (const XCam3aResultEdgeEnhancement &from, struct atomisp_ee_config &to);
+ XCamReturn translate_gamma_table (const XCam3aResultGammaTable &from, struct atomisp_gamma_table &to);
+ XCamReturn translate_macc (const XCam3aResultMaccMatrix &from, struct atomisp_macc_table &to);
+ XCamReturn translate_ctc (const XCam3aResultChromaToneControl &from, struct atomisp_ctc_table &to);
+
+private:
+ XCAM_DEAD_COPY (IspConfigTranslator);
+
+private:
+ SmartPtr<SensorDescriptor> _sensor;
+};
+
+}
+
+#endif //XCAM_ISP_CONFIG_TRANSLATOR_H
diff --git a/xcore/isp_controller.cpp b/xcore/isp_controller.cpp
new file mode 100644
index 0000000..96d21a8
--- /dev/null
+++ b/xcore/isp_controller.cpp
@@ -0,0 +1,128 @@
+/*
+ * isp_controller.cpp - isp controller
+ *
+ * Copyright (c) 2014-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 "isp_controller.h"
+#include "v4l2_device.h"
+#include "x3a_statistics_queue.h"
+#include "x3a_isp_config.h"
+
+#include <linux/atomisp.h>
+
+namespace XCam {
+
+IspController::IspController (SmartPtr<V4l2Device> & device)
+ : _device (device)
+{
+}
+IspController::~IspController ()
+{
+}
+
+XCamReturn
+IspController::get_sensor_mode_data (struct atomisp_sensor_mode_data &sensor_mode_data)
+{
+ if ( _device->io_control (ATOMISP_IOC_G_SENSOR_MODE_DATA, &sensor_mode_data) < 0) {
+ XCAM_LOG_WARNING (" get ISP sensor mode data failed");
+ return XCAM_RETURN_ERROR_IOCTL;
+ }
+ return XCAM_RETURN_NO_ERROR;
+}
+
+XCamReturn
+IspController::get_isp_parameter (struct atomisp_parm ¶meters)
+{
+ if ( _device->io_control (ATOMISP_IOC_G_ISP_PARM, ¶meters) < 0) {
+ XCAM_LOG_WARNING (" get ISP parameters failed");
+ return XCAM_RETURN_ERROR_IOCTL;
+ }
+ return XCAM_RETURN_NO_ERROR;
+}
+
+XCamReturn
+IspController::get_3a_statistics (SmartPtr<X3aIspStatistics> &stats)
+{
+ struct atomisp_3a_statistics *isp_stats = NULL;
+
+ XCAM_ASSERT (stats.ptr());
+ XCAM_FAIL_RETURN (WARNING, stats.ptr(),
+ XCAM_RETURN_ERROR_PARAM, "stats empty");
+
+ isp_stats = stats->get_3a_stats ();
+
+ if ( _device->io_control (ATOMISP_IOC_G_3A_STAT, isp_stats) < 0) {
+ XCAM_LOG_WARNING (" get 3a stats failed from ISP");
+ return XCAM_RETURN_ERROR_IOCTL;
+ }
+ return XCAM_RETURN_NO_ERROR;
+}
+
+XCamReturn
+IspController::set_3a_config (X3aIspConfig *config)
+{
+ struct atomisp_parameters &isp_config = config->get_isp_configs ();
+ if ( _device->io_control (ATOMISP_IOC_S_PARAMETERS, &isp_config) < 0) {
+ XCAM_LOG_WARNING (" set 3a config failed to ISP");
+ return XCAM_RETURN_ERROR_IOCTL;
+ }
+
+ return XCAM_RETURN_NO_ERROR;
+}
+
+XCamReturn
+IspController::set_3a_exposure (X3aIspExposureResult *res)
+{
+ const struct atomisp_exposure &exposure = res->get_isp_config ();
+ return set_3a_exposure (exposure);
+
+ return XCAM_RETURN_NO_ERROR;
+}
+
+XCamReturn
+IspController::set_3a_exposure (const struct atomisp_exposure &exposure)
+{
+ if ( _device->io_control (ATOMISP_IOC_S_EXPOSURE, (struct atomisp_exposure*)(&exposure)) < 0) {
+ XCAM_LOG_WARNING (" set exposure result failed to device");
+ return XCAM_RETURN_ERROR_IOCTL;
+ }
+ XCAM_LOG_DEBUG ("isp set exposure result, integration_time:%d, gain code:%d",
+ exposure.integration_time[0], exposure.gain[0]);
+
+ return XCAM_RETURN_NO_ERROR;
+}
+
+XCamReturn
+IspController::set_3a_focus (const XCam3aResultFocus &focus)
+{
+ int position = focus.position;
+ struct v4l2_control control;
+
+ xcam_mem_clear (&control);
+ control.id = V4L2_CID_FOCUS_ABSOLUTE;
+ control.value = position;
+
+ if (_device->io_control (VIDIOC_S_CTRL, &control) < 0) {
+ XCAM_LOG_WARNING (" set focus result failed to device");
+ return XCAM_RETURN_ERROR_IOCTL;
+ }
+ return XCAM_RETURN_NO_ERROR;
+}
+
+
+};
diff --git a/xcore/isp_controller.h b/xcore/isp_controller.h
new file mode 100644
index 0000000..ba2ff84
--- /dev/null
+++ b/xcore/isp_controller.h
@@ -0,0 +1,55 @@
+/*
+ * isp_controller.h - isp controller
+ *
+ * Copyright (c) 2014-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>
+ */
+#ifndef XCAM_ISP_CONTROLLER_H
+#define XCAM_ISP_CONTROLLER_H
+
+#include "x3a_isp_config.h"
+
+namespace XCam {
+
+class V4l2Device;
+class X3aIspStatistics;
+class X3aIspConfig;
+
+class IspController {
+public:
+ explicit IspController (SmartPtr<V4l2Device> & device);
+ ~IspController ();
+
+ XCamReturn get_sensor_mode_data (struct atomisp_sensor_mode_data &sensor_mode_data);
+ XCamReturn get_isp_parameter (struct atomisp_parm ¶meters);
+
+ XCamReturn get_3a_statistics (SmartPtr<X3aIspStatistics> &stats);
+ XCamReturn set_3a_config (X3aIspConfig *config);
+ XCamReturn set_3a_exposure (X3aIspExposureResult *res);
+ XCamReturn set_3a_exposure (const struct atomisp_exposure &exposure);
+ XCamReturn set_3a_focus (const XCam3aResultFocus &focus);
+
+private:
+
+ XCAM_DEAD_COPY (IspController);
+
+private:
+ SmartPtr<V4l2Device> _device;
+};
+
+};
+
+#endif //XCAM_ISP_CONTROLLER_H
diff --git a/xcore/isp_image_processor.cpp b/xcore/isp_image_processor.cpp
new file mode 100644
index 0000000..43a9e7e
--- /dev/null
+++ b/xcore/isp_image_processor.cpp
@@ -0,0 +1,173 @@
+/*
+ * isp_image_processor.cpp - isp image processor
+ *
+ * Copyright (c) 2014-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 "isp_image_processor.h"
+#include "x3a_isp_config.h"
+#include "isp_controller.h"
+#include "isp_config_translator.h"
+
+namespace XCam {
+
+IspImageProcessor::IspImageProcessor (SmartPtr<IspController> &controller)
+ : ImageProcessor ("IspImageProcessor")
+ , _controller (controller)
+ , _3a_config (new X3aIspConfig)
+{
+ _sensor = new SensorDescriptor;
+ _translator = new IspConfigTranslator (_sensor);
+ XCAM_LOG_DEBUG ("IspImageProcessor construction");
+}
+
+IspImageProcessor::~IspImageProcessor ()
+{
+ XCAM_LOG_DEBUG ("~IspImageProcessor destruction");
+}
+
+XCamReturn
+IspImageProcessor::process_buffer(SmartPtr<VideoBuffer> &input, SmartPtr<VideoBuffer> &output)
+{
+ output = input;
+ return XCAM_RETURN_NO_ERROR;
+}
+
+bool
+IspImageProcessor::can_process_result (SmartPtr<X3aResult> &result)
+{
+ XCAM_ASSERT (result.ptr());
+ switch (result->get_type()) {
+ case X3aIspConfig::IspExposureParameters:
+ case X3aIspConfig::IspAllParameters:
+ case XCAM_3A_RESULT_WHITE_BALANCE:
+ case XCAM_3A_RESULT_EXPOSURE:
+ case XCAM_3A_RESULT_BLACK_LEVEL:
+ case XCAM_3A_RESULT_YUV2RGB_MATRIX:
+ case XCAM_3A_RESULT_RGB2YUV_MATRIX:
+ return true;
+ default:
+ return false;
+ }
+
+ return false;
+}
+
+XCamReturn
+IspImageProcessor::apply_3a_results (X3aResultList &results)
+{
+ XCamReturn ret = XCAM_RETURN_NO_ERROR;
+
+ if (results.empty())
+ return XCAM_RETURN_ERROR_PARAM;
+
+ // activate sensor to make translator work
+ if (!_sensor->is_ready()) {
+ struct atomisp_sensor_mode_data sensor_data;
+ xcam_mem_clear (&sensor_data);
+ if (_controller->get_sensor_mode_data(sensor_data) != XCAM_RETURN_NO_ERROR) {
+ XCAM_LOG_WARNING ("ispimageprocessor initiliaze sensor failed");
+ } else
+ _sensor->set_sensor_data (sensor_data);
+ XCAM_ASSERT (_sensor->is_ready());
+ }
+
+ if ((ret = merge_results (results)) != XCAM_RETURN_NO_ERROR) {
+ XCAM_LOG_WARNING ("merge 3a result to isp config failed");
+ return XCAM_RETURN_ERROR_UNKNOWN;
+ }
+
+ if ((ret = apply_exposure_result (results)) != XCAM_RETURN_NO_ERROR) {
+ XCAM_LOG_WARNING ("set 3a exposure to sensor failed");
+ }
+
+ // check _3a_config
+ XCAM_ASSERT (_3a_config.ptr());
+ XCAM_ASSERT (_controller.ptr());
+ ret = _controller->set_3a_config (_3a_config.ptr());
+ if (ret != XCAM_RETURN_NO_ERROR) {
+ XCAM_LOG_WARNING ("set 3a config to isp failed");
+ }
+ _3a_config->clear ();
+ return ret;
+}
+
+XCamReturn
+IspImageProcessor::apply_3a_result (SmartPtr<X3aResult> &result)
+{
+ XCamReturn ret = XCAM_RETURN_NO_ERROR;
+
+ X3aResultList results;
+ results.push_back (result);
+ ret = apply_3a_results (results);
+ return ret;
+}
+
+XCamReturn
+IspImageProcessor::merge_results (X3aResultList &results)
+{
+ if (results.empty())
+ return XCAM_RETURN_ERROR_PARAM;
+
+ for (X3aResultList::iterator iter = results.begin ();
+ iter != results.end ();)
+ {
+ SmartPtr<X3aResult> &x3a_result = *iter;
+ if (_3a_config->attach (x3a_result, _translator.ptr())) {
+ x3a_result->set_done (true);
+ results.erase (iter++);
+ } else
+ ++iter;
+ }
+ return XCAM_RETURN_NO_ERROR;
+}
+
+XCamReturn
+IspImageProcessor::apply_exposure_result (X3aResultList &results)
+{
+ XCamReturn ret = XCAM_RETURN_NO_ERROR;
+
+ for (X3aResultList::iterator iter = results.begin ();
+ iter != results.end ();)
+ {
+ if ((*iter)->get_type() == X3aIspConfig::IspExposureParameters) {
+ X3aIspExposureResult *res = dynamic_cast<X3aIspExposureResult*> ((*iter).ptr());
+ if (!res || ((ret = _controller->set_3a_exposure (res)) != XCAM_RETURN_NO_ERROR)) {
+ XCAM_LOG_WARNING ("set 3a exposure to sensor failed");
+ }
+ res->set_done (true);
+ results.erase (iter++);
+ } else if ((*iter)->get_type() == XCAM_3A_RESULT_EXPOSURE) {
+ X3aExposureResult *res = dynamic_cast<X3aExposureResult*>((*iter).ptr());
+ struct atomisp_exposure isp_exposure;
+ xcam_mem_clear (&isp_exposure);
+ ret = _translator->translate_exposure (res->get_standard_result (), isp_exposure);
+ if (ret != XCAM_RETURN_NO_ERROR) {
+ XCAM_LOG_WARNING ("translate 3a exposure to sensor failed");
+ }
+ if ((ret = _controller->set_3a_exposure (isp_exposure)) != XCAM_RETURN_NO_ERROR) {
+ XCAM_LOG_WARNING ("set 3a exposure to sensor failed");
+ }
+ res->set_done (true);
+ results.erase (iter++);
+ } else
+ ++iter;
+ }
+ return XCAM_RETURN_NO_ERROR;
+}
+
+};
diff --git a/xcore/isp_image_processor.h b/xcore/isp_image_processor.h
new file mode 100644
index 0000000..d1339b4
--- /dev/null
+++ b/xcore/isp_image_processor.h
@@ -0,0 +1,65 @@
+/*
+ * isp_image_processor.h - isp image processor
+ *
+ * Copyright (c) 2014-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>
+ */
+
+#ifndef XCAM_ISP_IMAGE_PROCESSOR_H
+#define XCAM_ISP_IMAGE_PROCESSOR_H
+
+#include "xcam_common.h"
+#include "xcam_defs.h"
+#include "xcam_utils.h"
+#include "image_processor.h"
+
+namespace XCam {
+
+class X3aIspConfig;
+class IspController;
+class IspConfigTranslator;
+class SensorDescriptor;
+
+class IspImageProcessor
+ : public ImageProcessor
+{
+public:
+ explicit IspImageProcessor (SmartPtr<IspController> &controller);
+ virtual ~IspImageProcessor ();
+
+protected:
+ //derive from ImageProcessor
+ virtual bool can_process_result (SmartPtr<X3aResult> &result);
+ virtual XCamReturn apply_3a_results (X3aResultList &results);
+ virtual XCamReturn apply_3a_result (SmartPtr<X3aResult> &result);
+ virtual XCamReturn process_buffer (SmartPtr<VideoBuffer> &input, SmartPtr<VideoBuffer> &output);
+
+private:
+ XCamReturn merge_results (X3aResultList &results);
+ XCamReturn apply_exposure_result (X3aResultList &results);
+
+ XCAM_DEAD_COPY (IspImageProcessor);
+
+private:
+ SmartPtr<IspController> _controller;
+ SmartPtr<SensorDescriptor> _sensor;
+ SmartPtr<IspConfigTranslator> _translator;
+ SmartPtr<X3aIspConfig> _3a_config;
+};
+
+};
+
+#endif //XCAM_ISP_IMAGE_PROCESSOR_H
diff --git a/xcore/libtbd.c b/xcore/libtbd.c
new file mode 100644
index 0000000..6c86af6
--- /dev/null
+++ b/xcore/libtbd.c
@@ -0,0 +1,647 @@
+/*
+** Copyright 2012-2013 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.
+*/
+
+#include <stdbool.h> /* defines bool type */
+#include <stddef.h> /* defines size_t */
+#include <stdint.h> /* defines integer types with specified widths */
+#include <stdio.h> /* defines FILE */
+#include <string.h> /* defines memcpy and memset */
+
+#include "libtbd.h" /* our own header file */
+
+/*!
+* \brief Debug messages.
+*/
+#ifdef __ANDROID__
+#define LOG_TAG "libtbd"
+#include <utils/Log.h>
+#define MSG_LOG(...) LOGD(__VA_ARGS__)
+#define MSG_ERR(...) LOGE(__VA_ARGS__)
+#else
+#include <stdio.h>
+#define MSG_LOG(...) fprintf(stdout, __VA_ARGS__); fprintf(stdout, "\n");
+#define MSG_ERR(...) fprintf(stderr, __VA_ARGS__); fprintf(stderr, "\n");
+#endif
+
+/*
+ * Checks the validity of the pointer
+ * param[in] a_ptr Pointer to be examined
+ * return True if pointer ok
+ */
+bool is_valid_pointer(void* a_ptr)
+{
+ if ((!a_ptr) || ((unsigned long)(a_ptr) % sizeof(uint32_t))) {
+ return false;
+ } else {
+ return true;
+ }
+}
+
+/*
+ * Calculates checksum for a data block.
+ * param[in] a_data_ptr Data from where to calculate the checksum
+ * param[in] a_data_size Size of the data
+ * return The checksum
+ */
+uint32_t get_checksum(void *a_data_ptr, size_t a_data_size)
+{
+ uint32_t *ptr32 = a_data_ptr;
+ int size32 = a_data_size / sizeof(uint32_t);
+
+ /* Simple checksum algorithm: summing up the data content
+ * as 32-bit numbers */
+ uint32_t checksum32 = 0;
+ if (size32) {
+ if (size32 & 0x01) {
+ checksum32 += *ptr32++;
+ size32 -= 1;
+ }
+ if (size32 & 0x02) {
+ checksum32 += *ptr32++;
+ checksum32 += *ptr32++;
+ size32 -= 2;
+ }
+ for (; size32 > 0; size32-=4) {
+ checksum32 += *ptr32++;
+ checksum32 += *ptr32++;
+ checksum32 += *ptr32++;
+ checksum32 += *ptr32++;
+ }
+ }
+
+ return checksum32;
+}
+
+/*
+ * Common subroutine to validate Tagged Binary Data container, without
+ * paying attention to checksum or data tagging. This function assumes
+ * that the data resides in "legal" memory area as there is no size
+ * given together with input pointer.
+ * param[in] a_data_ptr Pointer to container
+ * return Return code indicating possible errors
+ */
+tbd_error_t validate_anysize(void *a_data_ptr)
+{
+ uint8_t *byte_ptr, *eof_ptr;
+ tbd_record_header_t *record_ptr;
+ uint32_t record_size;
+
+ /* Container should begin with a header */
+ tbd_header_t *header_ptr = a_data_ptr;
+
+ /* Check against illegal pointers */
+ if (!is_valid_pointer(header_ptr)) {
+ MSG_ERR("LIBTBD ERROR: Cannot access data!");
+ return tbd_err_data;
+ }
+
+ /* Check that the indicated data size makes sense,
+ * and is not too much or too little */
+ if (header_ptr->size % sizeof(uint32_t)) {
+ MSG_ERR("LIBTBD ERROR: Size in header should be multiple of 4 bytes!");
+ return tbd_err_data;
+ }
+ if (header_ptr->size < sizeof(tbd_header_t)) {
+ MSG_ERR("LIBTBD ERROR: Invalid data header!");
+ return tbd_err_data;
+ }
+
+ /* First record is just after header, a byte pointer is needed
+ * to do math with sizes and pointers */
+ byte_ptr = (uint8_t *)(header_ptr + 1);
+ eof_ptr = (uint8_t *)(a_data_ptr) + header_ptr->size;
+
+ /* Loop until there are no more records to go */
+ while (byte_ptr < eof_ptr) {
+ /* At least one more record is expected */
+
+ /* Record header must be within the given data size */
+ if (byte_ptr + sizeof(tbd_record_header_t) > eof_ptr) {
+ MSG_ERR("LIBTBD ERROR: Invalid data header!");
+ return tbd_err_data;
+ }
+
+ record_ptr = (tbd_record_header_t *)(byte_ptr);
+ record_size = record_ptr->size;
+
+ /* Check that the indicated record size makes sense,
+ * and is not too much or too little */
+ if (record_size % sizeof(uint32_t)) {
+ MSG_ERR("LIBTBD ERROR: Size in record should be multiple of 4 bytes!");
+ return tbd_err_data;
+ }
+ if (record_size < sizeof(tbd_record_header_t)) {
+ MSG_ERR("LIBTBD ERROR: Invalid record header!");
+ return tbd_err_data;
+ }
+ if (byte_ptr + record_size > eof_ptr) {
+ MSG_ERR("LIBTBD ERROR: Invalid record header!");
+ return tbd_err_data;
+ }
+
+ /* This record ok, continue the while loop... */
+ byte_ptr += record_size;
+ }
+
+ /* Seems that we have a valid data with no more headers */
+ return tbd_err_none;
+}
+
+/*
+ * Common subroutine to validate Tagged Binary Data, without paying
+ * attention to checksum or data tagging. Also, this function does
+ * check that the data fits in the given buffer size.
+ * param[in] a_data_ptr Pointer to data buffer
+ * param[in] a_data_size Size of the data buffer
+ * return Return code indicating possible errors
+ */
+tbd_error_t validate(void *a_data_ptr, size_t a_data_size)
+{
+ /* Container should begin with a header */
+ tbd_header_t *header_ptr = a_data_ptr;
+
+ /* Check against illegal pointers */
+ if (!is_valid_pointer(header_ptr)) {
+ MSG_ERR("LIBTBD ERROR: Cannot access data!");
+ return tbd_err_data;
+ }
+
+ /* Check that the TBD header fits into given data */
+ if (sizeof(tbd_header_t) > a_data_size) {
+ MSG_ERR("TBD ERROR: #1 Too small data buffer given!");
+ return tbd_err_data;
+ }
+
+ /* Check that the indicated data fits in the buffer */
+ if (header_ptr->size > a_data_size) {
+ MSG_ERR("TBD ERROR: #2 Too small data buffer given!");
+ return tbd_err_data;
+ }
+
+ /* Check the the content is ok */
+ return validate_anysize(a_data_ptr);
+}
+
+/*
+ * Creates a new, empty Tagged Binary Data container with the tag
+ * that was given. Also updates the checksum and size accordingly.
+ * Note that the buffer size must be large enough for the header
+ * to fit in, the exact amount being 24 bytes (for tbd_header_t).
+ * param[in] a_data_ptr Pointer to modifiable container buffer
+ * param[in] a_data_size Size of the container buffer
+ * param[in] a_tag Tag the container shall have
+ * param[out] a_new_size Updated container size
+ * return Return code indicating possible errors
+ */
+tbd_error_t tbd_create(void *a_data_ptr, size_t a_data_size
+ , tbd_tag_t a_tag, size_t *a_new_size)
+{
+ tbd_header_t *header_ptr;
+
+ /* Check that the TBD header fits into given data */
+ if (sizeof(tbd_header_t) > a_data_size) {
+ MSG_ERR("LIBTBD ERROR: Not enough data given!");
+ return tbd_err_argument;
+ }
+
+ /* Nullify everything */
+ memset(a_data_ptr, 0, sizeof(tbd_header_t));
+
+ /* The header is what we need */
+ header_ptr = a_data_ptr;
+
+ header_ptr->tag = a_tag;
+
+ header_ptr->size = sizeof(tbd_header_t);
+ header_ptr->version = IA_TBD_VERSION;
+ header_ptr->revision = IA_TBD_REVISION;
+ header_ptr->config_bits = 0;
+ header_ptr->checksum = get_checksum(header_ptr, sizeof(tbd_header_t));
+
+ *a_new_size = sizeof(tbd_header_t);
+
+ return tbd_err_none;
+}
+
+/*
+ * Performs number of checks to given Tagged Binary Data container,
+ * including the verification of the checksum. The function does not
+ * care about the tag type of the container.
+ * param[in] a_data_ptr Pointer to container buffer
+ * param[in] a_data_size Size of the container buffer
+ * return Return code indicating possible errors
+ */
+tbd_error_t tbd_validate_anytag(void *a_data_ptr, size_t a_data_size)
+{
+ tbd_header_t *header_ptr;
+
+ /* Check the the content is ok */
+ int r;
+ if ((r = validate(a_data_ptr, a_data_size))) {
+ return r;
+ }
+
+ /* Container should begin with a header */
+ header_ptr = a_data_ptr;
+
+ /* Check that the checksum is correct */
+
+ /* When calculating the checksum for the original data, the checksum
+ * field has been filled with zero value - so after inserting the
+ * checksum in its place, the new calculated checksum is actually
+ * two times the original */
+
+ if (get_checksum(header_ptr, header_ptr->size) - header_ptr->checksum != header_ptr->checksum) {
+ MSG_ERR("LIBTBD ERROR: Checksum doesn't match!");
+ return tbd_err_data;
+ }
+
+ /* Seems that we have valid data */
+ return tbd_err_none;
+}
+
+/*
+ * Performs number of checks to given Tagged Binary Data container,
+ * including the verification of the checksum. Also, the data must have
+ * been tagged properly. The tag is further used to check endianness,
+ * and if it seems wrong, a specific debug message is printed out.
+ * param[in] a_data_ptr Pointer to container buffer
+ * param[in] a_data_size Size of the container buffer
+ * param[in] a_tag Tag the data must have
+ * return Return code indicating possible errors
+ */
+tbd_error_t tbd_validate(void *a_data_ptr, size_t a_data_size
+ , tbd_tag_t a_tag)
+{
+ tbd_header_t *header_ptr;
+
+ /* Check the the content is ok */
+ int r;
+ if ((r = validate(a_data_ptr, a_data_size))) {
+ return r;
+ }
+
+ /* Container should begin with a header */
+ header_ptr = a_data_ptr;
+
+ /* Check that the tag is correct */
+ if (header_ptr->tag != a_tag) {
+ /* See if we have wrong endianness or incorrect tag */
+ uint32_t reverse_tag = ( (((a_tag) >> 24) & 0x000000FF)
+ | (((a_tag) >> 8) & 0x0000FF00)
+ | (((a_tag) << 8) & 0x00FF0000)
+ | (((a_tag) << 24) & 0xFF000000) );
+
+ if (reverse_tag == header_ptr->tag) {
+ MSG_ERR("LIBTBD ERROR: Wrong endianness of data!");
+ } else {
+ MSG_ERR("LIBTBD ERROR: Data is not tagged properly!");
+ }
+ return tbd_err_data;
+ }
+
+ /* Check that the checksum is correct */
+
+ /* When calculating the checksum for the original data, the checksum
+ * field has been filled with zero value - so after inserting the
+ * checksum in its place, the new calculated checksum is actually
+ * two times the original */
+
+ if (get_checksum(header_ptr, header_ptr->size) - header_ptr->checksum != header_ptr->checksum) {
+ MSG_ERR("LIBTBD ERROR: Checksum doesn't match!");
+ return tbd_err_data;
+ }
+
+ /* Seems that we have valid data */
+ return tbd_err_none;
+}
+
+/*
+ * Checks if a given kind of record exists in the Tagged Binary Data,
+ * and if yes, tells the location of such record as well as its size.
+ * If there are multiple records that match the query, the indicated
+ * record is the first one.
+ * param[in] a_data_ptr Pointer to container buffer
+ * param[in] a_record_class Class the record must have
+ * param[in] a_record_format Format the record must have
+ * param[out] a_record_data Record data (or NULL if not found)
+ * param[out] a_record_size Record size (or 0 if not found)
+ * return Return code indicating possible errors
+ */
+tbd_error_t tbd_get_record(void *a_data_ptr
+ , tbd_class_t a_record_class, tbd_format_t a_record_format
+ , void **a_record_data, size_t *a_record_size)
+{
+ tbd_header_t *header_ptr;
+ uint8_t *byte_ptr, *eof_ptr;
+
+ /* Check the the content is ok */
+ int r;
+ if ((r = validate_anysize(a_data_ptr))) {
+ return r;
+ }
+
+ /* Container should begin with a header */
+ header_ptr = a_data_ptr;
+
+ /* First record is just after header */
+ byte_ptr = (uint8_t *)(header_ptr + 1);
+ eof_ptr = (uint8_t *)(a_data_ptr) + header_ptr->size;
+
+ /* Loop until there are no more records to go */
+ while (byte_ptr < eof_ptr) {
+ /* At least one more record is expected */
+ tbd_record_header_t *record_ptr = (tbd_record_header_t *)(byte_ptr);
+
+ uint16_t record_class = record_ptr->class_id;
+ uint8_t record_format = record_ptr->format_id;
+ uint32_t record_size = record_ptr->size;
+
+ if (((a_record_class == tbd_class_any) || (a_record_class == record_class))
+ && ((a_record_format == tbd_format_any) || (a_record_format == record_format))) {
+
+ /* Match found */
+ *a_record_data = record_ptr + 1;
+ *a_record_size = record_size - sizeof(tbd_record_header_t);
+
+ return tbd_err_none;
+
+ }
+
+ /* Match not found yet, continue the while loop... */
+ byte_ptr += record_size;
+ }
+
+ MSG_LOG("libtbd: Record not found!");
+ *a_record_data = NULL;
+ *a_record_size = 0;
+ return tbd_err_none;
+}
+
+/*
+ * The given record is inserted into the Tagged Binary Data container
+ * that must exist already. New records are always added to the end,
+ * regardless if a record with the same class and format field already
+ * exists in the data. Also updates the checksum and size accordingly.
+ * Note that the buffer size must be large enough for the inserted
+ * record to fit in, the exact amount being the size of original
+ * Tagged Binary Data container plus the size of record data to be
+ * inserted plus 8 bytes (for tbd_record_header_t).
+ * param[in] a_data_ptr Pointer to modifiable container buffer
+ * param[in] a_data_size Size of buffer (surplus included)
+ * param[in] a_record_class Class the record shall have
+ * param[in] a_record_format Format the record shall have
+ * param[in] a_record_data Record data
+ * param[in] a_record_size Record size
+ * param[out] a_new_size Updated container size
+ * return Return code indicating possible errors
+ */
+tbd_error_t tbd_insert_record(void *a_data_ptr, size_t a_data_size
+ , tbd_class_t a_record_class, tbd_format_t a_record_format
+ , void *a_record_data, size_t a_record_size
+ , size_t *a_new_size)
+{
+ tbd_header_t *header_ptr;
+ size_t new_size;
+ tbd_record_header_t *record_ptr;
+ int r;
+
+ /* Check the the content is ok */
+ if ((r = validate(a_data_ptr, a_data_size))) {
+ return r;
+ }
+
+ /* Container should begin with a header */
+ header_ptr = a_data_ptr;
+
+ /* Check that the new record fits into given data */
+ new_size = header_ptr->size + sizeof(tbd_record_header_t) + a_record_size;
+
+ if (new_size > a_data_size) {
+ MSG_ERR("LIBTBD ERROR: #3 Too small data buffer given!");
+ return tbd_err_argument;
+ }
+
+ /* Check against illegal pointers */
+ if (!is_valid_pointer(a_record_data)) {
+ MSG_ERR("LIBTBD ERROR: Cannot access data!");
+ return tbd_err_data;
+ }
+
+ /* Check that the indicated data size makes sense */
+ if (a_record_size % sizeof(uint32_t)) {
+ MSG_ERR("LIBTBD ERROR: Size in record should be multiple of 4 bytes!");
+ return tbd_err_data;
+ }
+
+ /* Where our record should go */
+ record_ptr = (tbd_record_header_t *)((char *)(a_data_ptr) + header_ptr->size);
+
+ /* Create record header and store the record itself */
+ record_ptr->size = sizeof(tbd_record_header_t) + a_record_size;
+ record_ptr->format_id = a_record_format;
+ record_ptr->packing_key = 0;
+ record_ptr->class_id = a_record_class;
+ record_ptr++;
+ memcpy(record_ptr, a_record_data, a_record_size);
+
+ /* Update the header */
+ header_ptr->size = new_size;
+ header_ptr->checksum = 0;
+ header_ptr->checksum = get_checksum(header_ptr, new_size);
+
+ *a_new_size = new_size;
+
+ return tbd_err_none;
+}
+
+/*
+ * The indicated record is removed from the Tagged Binary Data, after
+ * which the checksum and size are updated accordingly. If there are
+ * multiple records that match the class and format, only the first
+ * instance is removed. If no record is found, nothing will be done.
+ * Note that the resulting Tagged Binary Data container will
+ * be smaller than the original, but it does not harm to store the
+ * resulting container in its original length, either.
+ * param[in] a_data_ptr Pointer to modifiable container buffer
+ * param[in] a_record_class Class the record should have
+ * param[in] a_record_format Format the record should have
+ * param[out] a_new_size Updated container size
+ * return Return code indicating possible errors
+ */
+tbd_error_t tbd_remove_record(void *a_data_ptr
+ , tbd_class_t a_record_class, tbd_format_t a_record_format
+ , size_t *a_new_size)
+{
+ tbd_header_t *header_ptr;
+ uint8_t *byte_ptr, *eof_ptr;
+ size_t new_size;
+
+ /* Check the the content is ok */
+ int r;
+ if ((r = validate_anysize(a_data_ptr))) {
+ return r;
+ }
+
+ /* Container should begin with a header */
+ header_ptr = a_data_ptr;
+
+ /* First record is just after header */
+ byte_ptr = (uint8_t *)(header_ptr + 1);
+ eof_ptr = (uint8_t *)(a_data_ptr) + header_ptr->size;
+
+ /* Loop until there are no more records to go */
+ while (byte_ptr < eof_ptr) {
+ /* At least one more record is expected */
+ tbd_record_header_t *record_ptr = (tbd_record_header_t *)(byte_ptr);
+
+ uint16_t record_class = record_ptr->class_id;
+ uint8_t record_format = record_ptr->format_id;
+ uint32_t record_size = record_ptr->size;
+
+ if (((a_record_class == tbd_class_any) || (a_record_class == record_class))
+ && ((a_record_format == tbd_format_any) || (a_record_format == record_format))) {
+
+ /* Match found, remove the record */
+ memcpy(byte_ptr, byte_ptr + record_size, eof_ptr - (byte_ptr + record_size));
+
+ /* Update the header */
+ new_size = header_ptr->size - record_size;
+ header_ptr->size = new_size;
+ header_ptr->checksum = 0;
+ header_ptr->checksum = get_checksum(header_ptr, new_size);
+
+ *a_new_size = new_size;
+
+ return tbd_err_none;
+
+ }
+
+ /* Match not found yet, continue the while loop... */
+ byte_ptr += record_size;
+ }
+
+ MSG_LOG("libtbd: Record not found!");
+ *a_new_size = header_ptr->size;
+ return tbd_err_none;
+}
+
+/*
+ * Validates the Tagged Binary data container and generates a human
+ * readable detailed report on the content, including information about
+ * the records contained.
+ * param[in] a_data_ptr Pointer to container buffer
+ * param[in] a_data_size Size of the container buffer
+ * param[in] a_outfile Pointer to open file (may be stdout)
+ * return Return code indicating possible errors
+ */
+tbd_error_t tbd_infoprint(void *a_data_ptr, size_t a_data_size
+ , FILE *a_outfile)
+{
+ tbd_header_t *header_ptr;
+ uint8_t *byte_ptr, *eof_ptr, record_format, record_packing;
+ int num_of_records = 0, total_data = 0;
+ uint16_t record_class;
+ uint32_t record_size;
+
+ /* Check the the content is ok */
+ int r;
+ if ((r = validate(a_data_ptr, a_data_size))) {
+ return r;
+ }
+
+ /* Container should begin with a header */
+ header_ptr = a_data_ptr;
+
+ fprintf(a_outfile, "Data tag: 0x%08x (\'%c\' \'%c\' \'%c\' \'%c\')\n", header_ptr->tag, ((char *)(&header_ptr->tag))[0], ((char *)(&header_ptr->tag))[1], ((char *)(&header_ptr->tag))[2], ((char *)(&header_ptr->tag))[3]);
+ fprintf(a_outfile, "Data size: %d (0x%x), buffer size %d (0x%x)\n", header_ptr->size, header_ptr->size, a_data_size, a_data_size);
+ fprintf(a_outfile, "Data version: 0x%08x\n", header_ptr->version);
+ fprintf(a_outfile, "Data revision: 0x%08x\n", header_ptr->revision);
+ fprintf(a_outfile, "Data config: 0x%08x\n", header_ptr->config_bits);
+ fprintf(a_outfile, "Data checksum: 0x%08x\n", header_ptr->checksum);
+
+ fprintf(a_outfile, "\n");
+
+ /* First record is just after header */
+ byte_ptr = (uint8_t *)(header_ptr + 1);
+ eof_ptr = (uint8_t *)(a_data_ptr) + header_ptr->size;
+
+ /* Loop until there are no more records to go */
+ while (byte_ptr < eof_ptr) {
+ /* At least one more record is expected */
+ tbd_record_header_t *record_ptr = (tbd_record_header_t *)(byte_ptr);
+ num_of_records++;
+
+ record_class = record_ptr->class_id;
+ record_format = record_ptr->format_id;
+ record_packing = record_ptr->packing_key;
+ record_size = record_ptr->size;
+ total_data += record_size - sizeof(tbd_record_header_t);
+
+ fprintf(a_outfile, "Record size: %d (0x%x)\n", record_size, record_size);
+ fprintf(a_outfile, "Size w/o header: %d (0x%x)\n", record_size - sizeof(tbd_record_header_t), record_size - sizeof(tbd_record_header_t));
+ fprintf(a_outfile, "Record class: %d", record_class);
+ switch (record_class) {
+ case tbd_class_any:
+ fprintf(a_outfile, " \"tbd_class_any\"\n");
+ break;
+ case tbd_class_aiq:
+ fprintf(a_outfile, " \"tbd_class_aiq\"\n");
+ break;
+ case tbd_class_drv:
+ fprintf(a_outfile, " \"tbd_class_drv\"\n");
+ break;
+ case tbd_class_hal:
+ fprintf(a_outfile, " \"tbd_class_hal\"\n");
+ break;
+ default:
+ fprintf(a_outfile, " (unknown class)\n");
+ break;
+ }
+ fprintf(a_outfile, "Record format: %d", record_format);
+ switch (record_format) {
+ case tbd_format_any:
+ fprintf(a_outfile, " \"tbd_format_any\"\n");
+ break;
+ case tbd_format_custom:
+ fprintf(a_outfile, " \"tbd_format_custom\"\n");
+ break;
+ case tbd_format_container:
+ fprintf(a_outfile, " \"tbd_format_container\"\n");
+ break;
+ default:
+ fprintf(a_outfile, " (unknown format)\n");
+ break;
+ }
+ fprintf(a_outfile, "Packing: %d", record_packing);
+ if (record_packing == 0) {
+ fprintf(a_outfile, " (no packing)\n");
+ } else {
+ fprintf(a_outfile, "\n");
+ }
+
+ fprintf(a_outfile, "\n");
+
+ /* Continue the while loop... */
+ byte_ptr += record_size;
+ }
+
+ fprintf(a_outfile, "Number of records found: %d\n", num_of_records);
+ fprintf(a_outfile, "Total data in records: %d bytes (without headers)\n", total_data);
+ fprintf(a_outfile, "\n");
+ return tbd_err_none;
+}
+
diff --git a/xcore/libtbd.h b/xcore/libtbd.h
new file mode 100644
index 0000000..9df7799
--- /dev/null
+++ b/xcore/libtbd.h
@@ -0,0 +1,250 @@
+/*
+** Copyright 2012-2013 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.
+*/
+
+/*
+ * \file libtbd.h
+ * \brief Tagged Binary Data handling
+ */
+
+#ifndef __LIBTBD_H__
+#define __LIBTBD_H__
+
+#include <stddef.h> /* defines size_t */
+#include <stdint.h> /* defines integer types with specified widths */
+#include <stdio.h> /* defines FILE */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*!
+ * Revision of TBD System, format 0xYYMMDDVV, where:
+ * - YY: year,
+ * - MM: month,
+ * - DD: day,
+ * - VV: version ('01','02' etc.)
+ */
+#define IA_TBD_VERSION 0x12032201
+
+/*!
+ * Revision of TBD data set, format 0xYYMMDDVV, where:
+ * - YY: year,
+ * - MM: month,
+ * - DD: day,
+ * - VV: version ('01','02' etc.)
+ */
+#define IA_TBD_REVISION 0x13091001
+
+/*!
+* \brief Error codes for libtbd.
+*/
+typedef enum
+{
+ tbd_err_none = 0 , /*!< No errors */
+ tbd_err_general = (1 << 1), /*!< General error */
+ tbd_err_nomemory = (1 << 2), /*!< Out of memory */
+ tbd_err_data = (1 << 3), /*!< Corrupted data */
+ tbd_err_internal = (1 << 4), /*!< Error in code */
+ tbd_err_argument = (1 << 5) /*!< Invalid argument for a function */
+} tbd_error_t;
+
+/*!
+ * \brief Header structure for TBD container, followed by actual records.
+ */
+typedef struct
+{
+ uint32_t tag; /*!< Tag identifier, also checks endianness */
+ uint32_t size; /*!< Container size including this header */
+ uint32_t version; /*!< Version of TBD system, format 0xYYMMDDVV */
+ uint32_t revision; /*!< Revision of TBD data set, format 0xYYMMDDVV */
+ uint32_t config_bits; /*!< Configuration flag bits set */
+ uint32_t checksum; /*!< Global checksum, header included */
+} tbd_header_t;
+
+/*!
+ * \brief Tag identifiers used in TBD container header.
+ */
+#define CHTOU32(a,b,c,d) ((uint32_t)(a)|((uint32_t)(b)<<8)|((uint32_t)(c)<<16)|((uint32_t)(d)<<24))
+typedef enum
+{
+ tbd_tag_cpff = CHTOU32('C','P','F','F'), /*!< CPF File */
+ tbd_tag_aiqb = CHTOU32('A','I','Q','B'), /*!< AIQ configuration */
+ tbd_tag_aiqd = CHTOU32('A','I','Q','D'), /*!< AIQ data */
+ tbd_tag_halb = CHTOU32('H','A','L','B'), /*!< CameraHAL configuration */
+ tbd_tag_drvb = CHTOU32('D','R','V','B') /*!< Sensor driver configuration */
+} tbd_tag_t;
+
+/*!
+ * \brief Record structure. Data is located right after this header.
+ */
+typedef struct
+{
+ uint32_t size; /*!< Size of record including header */
+ uint8_t format_id; /*!< tbd_format_t enumeration values used */
+ uint8_t packing_key; /*!< Packing method; 0 = no packing */
+ uint16_t class_id; /*!< tbd_class_t enumeration values used */
+} tbd_record_header_t;
+
+/*!
+ * \brief Format ID enumeration describes the data format of the record.
+ */
+typedef enum
+{
+ tbd_format_any = 0, /*!< Unspecified format */
+ tbd_format_custom, /*!< User specified format */
+ tbd_format_container /*!< Record is actually another TBD container */
+} tbd_format_t;
+
+/*!
+ * \brief Class ID enumeration describes the data class of the record.
+ */
+typedef enum
+{
+ tbd_class_any = 0, /*!< Unspecified record class */
+ tbd_class_aiq, /*!< Used for AIC and 3A records */
+ tbd_class_drv, /*!< Used for driver records */
+ tbd_class_hal /*!< Used for HAL records */
+} tbd_class_t;
+
+/*!
+ * \brief Creates a new Tagged Binary Data container.
+ * Creates a new, empty Tagged Binary Data container with the tag
+ * that was given. Also updates the checksum and size accordingly.
+ * Note that the buffer size must be large enough for the header
+ * to fit in, the exact amount being 24 bytes (for tbd_header_t).
+ * @param[in] a_data_ptr Pointer to modifiable container buffer
+ * @param[in] a_data_size Size of the container buffer
+ * @param[in] a_tag Tag the container shall have
+ * @param[out] a_new_size Updated container size
+ * @return Return code indicating possible errors
+ */
+tbd_error_t tbd_create(void *a_data_ptr,
+ size_t a_data_size,
+ tbd_tag_t a_tag,
+ size_t *a_new_size);
+
+/*!
+ * \brief Checks if Tagged Binary Data is valid. All tags are accepted.
+ * Performs number of checks to given Tagged Binary Data container,
+ * including the verification of the checksum. The function does not
+ * care about the tag type of the container.
+ * @param[in] a_data_ptr Pointer to container buffer
+ * @param[in] a_data_size Size of the container buffer
+ * @return Return code indicating possible errors
+ */
+tbd_error_t tbd_validate_anytag(void *a_data_ptr,
+ size_t a_data_size);
+
+/*!
+ * \brief Checks if Tagged Binary Data is valid, and tagged properly.
+ * Performs number of checks to given Tagged Binary Data container,
+ * including the verification of the checksum. Also, the data must have
+ * been tagged properly. The tag is further used to check endianness,
+ * and if it seems wrong, a specific debug message is printed out.
+ * @param[in] a_data_ptr Pointer to container buffer
+ * @param[in] a_data_size Size of the container buffer
+ * @param[in] a_tag Tag the data must have
+ * @return Return code indicating possible errors
+ */
+tbd_error_t tbd_validate(void *a_data_ptr,
+ size_t a_data_size,
+ tbd_tag_t a_tag);
+
+/*!
+ * \brief Finds a record of given kind from within the container.
+ * Checks if a given kind of record exists in the Tagged Binary Data,
+ * and if yes, tells the location of such record as well as its size.
+ * If there are multiple records that match the query, the indicated
+ * record is the first one.
+ * @param[in] a_data_ptr Pointer to container buffer
+ * @param[in] a_record_class Class the record must have
+ * @param[in] a_record_format Format the record must have
+ * @param[out] a_record_data Record data (or NULL if not found)
+ * @param[out] a_record_size Record size (or 0 if not found)
+ * @return Return code indicating possible errors
+ */
+tbd_error_t tbd_get_record(void *a_data_ptr,
+ tbd_class_t a_record_class,
+ tbd_format_t a_record_format,
+ void **a_record_data,
+ size_t *a_record_size);
+
+/*!
+ * \brief Updates the Tagged Binary Data with the given record inserted.
+ * The given record is inserted into the Tagged Binary Data container
+ * that must exist already. New records are always added to the end,
+ * regardless if a record with the same class and format field already
+ * exists in the data. Also updates the checksum and size accordingly.
+ * Note that the buffer size must be large enough for the inserted
+ * record to fit in, the exact amount being the size of original
+ * Tagged Binary Data container plus the size of record data to be
+ * inserted plus 8 bytes (for tbd_record_header_t).
+ * @param[in] a_data_ptr Pointer to modifiable container buffer
+ * @param[in] a_data_size Size of buffer (surplus included)
+ * @param[in] a_record_class Class the record shall have
+ * @param[in] a_record_format Format the record shall have
+ * @param[in] a_record_data Record data
+ * @param[in] a_record_size Record size
+ * @param[out] a_new_size Updated container size
+ * @return Return code indicating possible errors
+ */
+tbd_error_t tbd_insert_record(void *a_data_ptr,
+ size_t a_data_size,
+ tbd_class_t a_record_class,
+ tbd_format_t a_record_format,
+ void *a_record_data,
+ size_t a_record_size,
+ size_t *a_new_size);
+
+/*!
+ * \brief Updates the Tagged Binary Data with the given record removed.
+ * The indicated record is removed from the Tagged Binary Data, after
+ * which the checksum and size are updated accordingly. If there are
+ * multiple records that match the class and format, only the first
+ * instance is removed. If no record is found, nothing will be done.
+ * Note that the resulting Tagged Binary Data container will
+ * be smaller than the original, but it does not harm to store the
+ * resulting container in its original length, either.
+ * @param[in] a_data_ptr Pointer to modifiable container buffer
+ * @param[in] a_record_class Class the record should have
+ * @param[in] a_record_format Format the record should have
+ * @param[out] a_new_size Updated container size
+ * @return Return code indicating possible errors
+ */
+tbd_error_t tbd_remove_record(void *a_data_ptr,
+ tbd_class_t a_record_class,
+ tbd_format_t a_record_format,
+ size_t *a_new_size);
+
+/*!
+ * \brief Writes all possible information about the Tagged Binary Data.
+ * Validates the Tagged Binary data container and generates a human
+ * readable detailed report on the content, including information about
+ * the records contained.
+ * @param[in] a_data_ptr Pointer to container buffer
+ * @param[in] a_data_size Size of the container buffer
+ * @param[in] a_outfile Pointer to open file (may be stdout)
+ * @return Return code indicating possible errors
+ */
+tbd_error_t tbd_infoprint(void *a_data_ptr,
+ size_t a_data_size,
+ FILE *a_outfile);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __LIBTBD_H__ */
diff --git a/xcore/poll_thread.cpp b/xcore/poll_thread.cpp
new file mode 100644
index 0000000..b1c6538
--- /dev/null
+++ b/xcore/poll_thread.cpp
@@ -0,0 +1,300 @@
+/*
+ * poll_thread.cpp - poll thread for event and buffer
+ *
+ * Copyright (c) 2014-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 "poll_thread.h"
+#include "xcam_thread.h"
+#include "x3a_statistics_queue.h"
+#include <unistd.h>
+
+namespace XCam {
+
+class PollThread;
+
+class EventPollThread
+ : public Thread
+{
+public:
+ EventPollThread (PollThread *poll)
+ : Thread ("event_poll")
+ , _poll (poll)
+ {}
+
+protected:
+ virtual bool started () {
+ XCamReturn ret = _poll->init_3a_stats_pool ();
+ if (ret != XCAM_RETURN_NO_ERROR)
+ return false;
+ return true;
+ }
+ virtual bool loop () {
+ XCamReturn ret = _poll->poll_subdev_event_loop ();
+
+ if (ret == XCAM_RETURN_NO_ERROR || ret == XCAM_RETURN_ERROR_TIMEOUT)
+ return true;
+ return false;
+ }
+
+private:
+ PollThread *_poll;
+};
+
+class CapturePollThread
+ : public Thread
+{
+public:
+ CapturePollThread (PollThread *poll)
+ : Thread ("capture_poll")
+ , _poll (poll)
+ {}
+
+protected:
+ virtual bool loop () {
+ XCamReturn ret = _poll->poll_buffer_loop ();
+
+ if (ret == XCAM_RETURN_NO_ERROR || ret == XCAM_RETURN_ERROR_TIMEOUT)
+ return true;
+ return false;
+ }
+
+private:
+ PollThread *_poll;
+};
+
+const int PollThread::default_subdev_event_timeout = 50; // ms
+const int PollThread::default_capture_event_timeout = 50; // ms
+
+PollThread::PollThread ()
+ : _callback (NULL)
+{
+ _event_loop = new EventPollThread(this);
+ _capture_loop = new CapturePollThread (this);
+
+ XCAM_LOG_DEBUG ("PollThread constructed");
+}
+
+PollThread::~PollThread ()
+{
+ stop();
+
+ XCAM_LOG_DEBUG ("~PollThread destructed");
+}
+
+
+bool
+PollThread::set_capture_device (SmartPtr<V4l2Device> &dev)
+{
+ XCAM_ASSERT (!_capture_dev.ptr());
+ _capture_dev = dev;
+ return true;
+}
+
+bool
+PollThread::set_event_device (SmartPtr<V4l2SubDevice> &dev)
+{
+ XCAM_ASSERT (!_event_dev.ptr());
+ _event_dev = dev;
+ return true;
+}
+
+bool
+PollThread::set_isp_controller (SmartPtr<IspController> &isp)
+{
+ XCAM_ASSERT (!_isp_controller.ptr());
+ _isp_controller = isp;
+ return true;
+}
+
+bool
+PollThread::set_callback (PollCallback *callback)
+{
+ XCAM_ASSERT (!_callback);
+ _callback = callback;
+ return true;
+}
+
+XCamReturn PollThread::start ()
+{
+ _3a_stats_pool = new X3aStatisticsQueue;
+ if (!_event_loop->start ()) {
+ return XCAM_RETURN_ERROR_THREAD;
+ }
+ if (!_capture_loop->start ()) {
+ return XCAM_RETURN_ERROR_THREAD;
+ }
+
+ return XCAM_RETURN_NO_ERROR;
+}
+
+XCamReturn PollThread::stop ()
+{
+ if (_3a_stats_pool.ptr ())
+ _3a_stats_pool->wakeup();
+
+ _event_loop->stop ();
+ _capture_loop->stop ();
+
+ // can't release now, stats buffer may still in use
+ //_3a_stats_pool.release ();
+ return XCAM_RETURN_NO_ERROR;
+}
+
+XCamReturn
+PollThread::init_3a_stats_pool ()
+{
+ XCamReturn ret = XCAM_RETURN_NO_ERROR;
+ struct atomisp_parm parameters;
+
+ xcam_mem_clear (¶meters);
+ ret = _isp_controller->get_isp_parameter (parameters);
+ if (ret != XCAM_RETURN_NO_ERROR ) {
+ XCAM_LOG_WARNING ("get isp parameters failed");
+ return ret;
+ }
+ if (!parameters.info.width || !parameters.info.height) {
+ XCAM_LOG_WARNING ("get isp parameters width or height wrong");
+ return XCAM_RETURN_ERROR_ISP;
+ }
+ _3a_stats_pool->set_grid_info (parameters.info);
+ return XCAM_RETURN_NO_ERROR;
+}
+
+XCamReturn
+PollThread::capture_3a_stats (SmartPtr<X3aIspStatistics> &stats)
+{
+ XCamReturn ret = XCAM_RETURN_NO_ERROR;
+ SmartPtr<X3aIspStatistics> new_stats = _3a_stats_pool->acquire_stats();
+
+ if (!new_stats.ptr()) {
+ XCAM_LOG_WARNING ("request stats buffer failed.");
+ return XCAM_RETURN_ERROR_MEM;
+ }
+
+ ret = _isp_controller->get_3a_statistics (new_stats);
+ if (ret != XCAM_RETURN_NO_ERROR) {
+ XCAM_LOG_WARNING ("get 3a stats from ISP failed");
+ return ret;
+ }
+
+ stats = new_stats;
+ return ret;
+}
+
+XCamReturn
+PollThread::handle_events (struct v4l2_event &event)
+{
+ XCamReturn ret = XCAM_RETURN_NO_ERROR;
+ switch (event.type) {
+ case V4L2_EVENT_ATOMISP_3A_STATS_READY:
+ ret = handle_3a_stats_event (event);
+ break;
+ case V4L2_EVENT_FRAME_SYNC:
+ break;
+ default:
+ ret = XCAM_RETURN_ERROR_UNKNOWN;
+ break;
+ }
+
+ return ret;
+}
+
+XCamReturn
+PollThread::handle_3a_stats_event (struct v4l2_event &event)
+{
+ XCamReturn ret = XCAM_RETURN_NO_ERROR;
+ SmartPtr<X3aIspStatistics> stats;
+
+ ret = capture_3a_stats (stats);
+ if (ret != XCAM_RETURN_NO_ERROR || !stats.ptr() || !stats->get_3a_stats()) {
+ XCAM_LOG_WARNING ("capture 3a stats failed");
+ return ret;
+ }
+ stats->set_timestamp (XCAM_TIMESPEC_2_USEC (event.timestamp));
+
+ XCAM_ASSERT (_callback);
+ return _callback->poll_3a_stats_ready (stats);
+}
+
+XCamReturn
+PollThread::poll_subdev_event_loop ()
+{
+ XCamReturn ret = XCAM_RETURN_NO_ERROR;
+ struct v4l2_event event;
+ int poll_ret = 0;
+
+ poll_ret = _event_dev->poll_event (PollThread::default_subdev_event_timeout);
+
+ if (poll_ret < 0) {
+ XCAM_LOG_WARNING ("poll event failed but continue");
+ ::usleep (50000); // 50ms
+ return XCAM_RETURN_ERROR_TIMEOUT;
+ }
+
+ /* timeout */
+ if (poll_ret == 0) {
+ XCAM_LOG_DEBUG ("poll event timeout and continue");
+ return XCAM_RETURN_ERROR_TIMEOUT;
+ }
+
+ xcam_mem_clear (&event);
+ ret = _event_dev->dequeue_event (event);
+ if (ret != XCAM_RETURN_NO_ERROR) {
+ XCAM_LOG_WARNING ("dequeue event failed on dev:%s", XCAM_STR(_event_dev->get_device_name()));
+ return XCAM_RETURN_ERROR_IOCTL;
+ }
+
+ ret = handle_events (event);
+ return ret;
+}
+
+XCamReturn
+PollThread::poll_buffer_loop ()
+{
+ XCamReturn ret = XCAM_RETURN_NO_ERROR;
+ int poll_ret = 0;
+ SmartPtr<V4l2Buffer> buf;
+
+ poll_ret = _capture_dev->poll_event (PollThread::default_capture_event_timeout);
+
+ if (poll_ret < 0) {
+ XCAM_LOG_WARNING ("poll buffer event got error but continue");
+ ::usleep (50000); // 50ms
+ return XCAM_RETURN_ERROR_TIMEOUT;
+ }
+
+ /* timeout */
+ if (poll_ret == 0) {
+ XCAM_LOG_DEBUG ("poll buffer timeout and continue");
+ return XCAM_RETURN_ERROR_TIMEOUT;
+ }
+
+ ret = _capture_dev->dequeue_buffer (buf);
+ if (ret != XCAM_RETURN_NO_ERROR) {
+ XCAM_LOG_WARNING ("capture buffer failed");
+ return ret;
+ }
+ XCAM_ASSERT (buf.ptr());
+ XCAM_ASSERT (_callback);
+
+ SmartPtr<V4l2BufferProxy> buf_proxy = new V4l2BufferProxy (buf, _capture_dev);
+
+ return _callback->poll_buffer_ready (buf_proxy);
+}
+
+};
diff --git a/xcore/poll_thread.h b/xcore/poll_thread.h
new file mode 100644
index 0000000..4fe8731
--- /dev/null
+++ b/xcore/poll_thread.h
@@ -0,0 +1,100 @@
+/*
+ * poll_thread.h - poll thread for event and buffer
+ *
+ * Copyright (c) 2014-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>
+ */
+
+#ifndef XCAM_POLL_THREAD_H
+#define XCAM_POLL_THREAD_H
+
+#include "xcam_common.h"
+#include "xcam_mutex.h"
+#include "x3a_event.h"
+#include "v4l2_buffer_proxy.h"
+#include "x3a_statistics_queue.h"
+#include "v4l2_device.h"
+#include "isp_controller.h"
+
+namespace XCam {
+
+class X3aIspStatistics;
+
+class PollCallback {
+public:
+ virtual ~PollCallback() {}
+ virtual XCamReturn poll_buffer_ready (SmartPtr<V4l2BufferProxy> &buf) = 0;
+ virtual XCamReturn poll_buffer_failed (int64_t timestamp, const char *msg) = 0;
+ virtual XCamReturn poll_3a_stats_ready (SmartPtr<X3aIspStatistics> &stats) = 0;
+ virtual XCamReturn poll_dvs_stats_ready() = 0;
+};
+
+class V4l2Device;
+class V4l2SubDevice;
+class X3aStatisticsQueue;
+class EventPollThread;
+class CapturePollThread;
+
+class PollThread
+{
+ friend class EventPollThread;
+ friend class CapturePollThread;
+public:
+ explicit PollThread ();
+ ~PollThread ();
+
+ bool set_capture_device (SmartPtr<V4l2Device> &dev);
+ bool set_event_device (SmartPtr<V4l2SubDevice> &sub_dev);
+ bool set_isp_controller (SmartPtr<IspController> &isp);
+ bool set_callback (PollCallback *callback);
+
+ XCamReturn start();
+ XCamReturn stop ();
+
+protected:
+ XCamReturn poll_subdev_event_loop ();
+ XCamReturn poll_buffer_loop ();
+
+ XCamReturn handle_events (struct v4l2_event &event);
+ XCamReturn handle_3a_stats_event (struct v4l2_event &event);
+
+private:
+ XCamReturn init_3a_stats_pool ();
+ XCamReturn capture_3a_stats (SmartPtr<X3aIspStatistics> &stats);
+
+
+private:
+ XCAM_DEAD_COPY (PollThread);
+
+private:
+ static const int default_subdev_event_timeout;
+ static const int default_capture_event_timeout;
+
+ SmartPtr<EventPollThread> _event_loop;
+ SmartPtr<CapturePollThread> _capture_loop;
+
+ SmartPtr<V4l2SubDevice> _event_dev;
+ SmartPtr<X3aStatisticsQueue> _3a_stats_pool;
+
+ SmartPtr<V4l2Device> _capture_dev;
+ SmartPtr<IspController> _isp_controller;
+
+ PollCallback *_callback;
+};
+
+};
+
+#endif //XCAM_POLL_THREAD_H
diff --git a/xcore/safe_list.h b/xcore/safe_list.h
new file mode 100644
index 0000000..f4222cd
--- /dev/null
+++ b/xcore/safe_list.h
@@ -0,0 +1,117 @@
+/*
+ * safe_list.h - safe list template
+ *
+ * Copyright (c) 2014 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>
+ */
+
+#ifndef XCAM_SAFE_LIST_H
+#define XCAM_SAFE_LIST_H
+
+#include "xcam_defs.h"
+#include "xcam_common.h"
+#include "smartptr.h"
+#include "xcam_mutex.h"
+#include <errno.h>
+#include <list>
+
+namespace XCam {
+
+template<class OBj>
+class SafeList {
+public:
+ typedef SmartPtr<OBj> ObjPtr;
+
+ SafeList () {}
+ ~SafeList () {
+ }
+
+ /*
+ * timeout, -1, wait until wakeup
+ * >=0, wait for @timeout microsseconds
+ */
+ inline ObjPtr pop (int32_t timeout = -1);
+ inline bool push (ObjPtr &obj);
+ uint32_t size () {
+ SmartLock lock(_mutex);
+ return _obj_list.size();
+ }
+ bool is_empty () {
+ SmartLock lock(_mutex);
+ return _obj_list.empty();
+ }
+ void wakeup () {
+ _new_obj_cond.broadcast ();
+ }
+ inline void clear ();
+
+private:
+ std::list<ObjPtr> _obj_list;
+ Mutex _mutex;
+ XCam::Cond _new_obj_cond;
+};
+
+
+template<class OBj>
+typename SafeList<OBj>::ObjPtr
+SafeList<OBj>::pop (int32_t timeout)
+{
+ SmartLock lock (_mutex);
+ int code = 0;
+
+ if (_obj_list.empty()) {
+ if (timeout < 0)
+ code = _new_obj_cond.wait(_mutex);
+ else
+ code = _new_obj_cond.timedwait(_mutex, timeout);
+ }
+
+ if (_obj_list.empty()) {
+ if (code == ETIMEDOUT) {
+ XCAM_LOG_DEBUG ("safe list pop timeout");
+ } else {
+ XCAM_LOG_DEBUG ("safe list pop failed");
+ }
+ return NULL;
+ }
+
+ SafeList<OBj>::ObjPtr obj = *_obj_list.begin ();
+ _obj_list.erase (_obj_list.begin ());
+ return obj;
+}
+
+template<class OBj>
+bool
+SafeList<OBj>::push (SafeList<OBj>::ObjPtr &obj)
+{
+ SmartLock lock (_mutex);
+ _obj_list.push_back (obj);
+ _new_obj_cond.signal ();
+ return true;
+}
+
+template<class OBj>
+void SafeList<OBj>::clear ()
+{
+ SmartLock lock (_mutex);
+ typename std::list<typename SafeList<OBj>::ObjPtr>::iterator i_obj = _obj_list.begin ();
+ while (i_obj != _obj_list.end ()) {
+ _obj_list.erase (i_obj++);
+ }
+}
+
+};
+#endif //XCAM_SAFE_LIST_H
diff --git a/xcore/sensor_descriptor.cpp b/xcore/sensor_descriptor.cpp
new file mode 100644
index 0000000..a749a83
--- /dev/null
+++ b/xcore/sensor_descriptor.cpp
@@ -0,0 +1,99 @@
+/*
+ * sensor_descriptor.h - sensor descriptor
+ *
+ * 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 "sensor_descriptor.h"
+#include <math.h>
+
+namespace XCam {
+
+SensorDescriptor::SensorDescriptor ()
+{
+ xcam_mem_clear (&_sensor_data);
+}
+
+SensorDescriptor::~SensorDescriptor ()
+{
+}
+
+bool
+SensorDescriptor::is_ready ()
+{
+ return (_sensor_data.line_length_pck > 0);
+}
+
+void
+SensorDescriptor::set_sensor_data (struct atomisp_sensor_mode_data &data)
+{
+ _sensor_data = data;
+}
+
+bool
+SensorDescriptor::exposure_time_to_integration (
+ int32_t exposure_time, uint32_t &coarse_time, uint32_t &fine_time)
+{
+ if (exposure_time < 0 || !is_ready ())
+ return false;
+
+ uint32_t pixel_periods = ((uint64_t)exposure_time) * _sensor_data.vt_pix_clk_freq_mhz / XCAM_SECONDS_2_TIMESTAMP (1);
+
+ coarse_time = pixel_periods / _sensor_data.line_length_pck;
+ fine_time = pixel_periods % _sensor_data.line_length_pck;
+ return true;
+}
+
+bool
+SensorDescriptor::exposure_integration_to_time (
+ uint32_t coarse_time, uint32_t fine_time, int32_t &exposure_time)
+{
+ if (!is_ready ())
+ return false;
+
+ uint64_t pixel_periods = coarse_time * _sensor_data.line_length_pck + fine_time;
+ exposure_time = pixel_periods * XCAM_SECONDS_2_TIMESTAMP(1) / _sensor_data.vt_pix_clk_freq_mhz;
+ return true;
+}
+
+bool
+SensorDescriptor::exposure_gain_to_code (
+ double analog_gain, double digital_gain,
+ int32_t &analog_code, int32_t &digital_code)
+{
+ XCAM_ASSERT (digital_gain == 1.0);
+ double db = log10 (analog_gain * digital_gain) * 20;
+ if (db > 48)
+ db = 48;
+ analog_code = (uint32_t) (db * 160.0 / 48);
+ digital_code = 0;
+ return true;
+}
+
+bool
+SensorDescriptor::exposure_code_to_gain (
+ int32_t analog_code, int32_t digital_code,
+ double &analog_gain, double &digital_gain)
+{
+ double db = analog_code * 48.0 / 160.0;
+ analog_gain = pow (10.0, db / 20.0);
+ digital_gain = 1.0;
+
+ return true;
+}
+
+};
diff --git a/xcore/sensor_descriptor.h b/xcore/sensor_descriptor.h
new file mode 100644
index 0000000..3443539
--- /dev/null
+++ b/xcore/sensor_descriptor.h
@@ -0,0 +1,68 @@
+/*
+ * sensor_descriptor.h - sensor descriptor
+ *
+ * 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>
+ */
+
+#ifndef XCAM_SENSOR_DESCRIPTOR_H
+#define XCAM_SENSOR_DESCRIPTOR_H
+
+#include "xcam_common.h"
+#include "xcam_defs.h"
+#include "xcam_utils.h"
+#include <linux/atomisp.h>
+
+namespace XCam {
+
+class SensorDescriptor {
+public:
+ explicit SensorDescriptor ();
+ virtual ~SensorDescriptor ();
+
+ void set_sensor_data (struct atomisp_sensor_mode_data &data);
+ virtual bool is_ready ();
+
+ // Input: exposure_time
+ // Output: coarse_time, fine_time
+ virtual bool exposure_time_to_integration (
+ int32_t exposure_time, uint32_t &coarse_time, uint32_t &fine_time);
+ // Input: coarse_time, fine_time
+ // Output: exposure_time
+ virtual bool exposure_integration_to_time (
+ uint32_t coarse_time, uint32_t fine_time, int32_t &exposure_time);
+
+ // Input : analog_gain, digital_gain
+ // Output: analog_code, digital_code
+ virtual bool exposure_gain_to_code (
+ double analog_gain, double digital_gain,
+ int32_t &analog_code, int32_t &digital_code);
+
+ // Input : analog_code, digital_code
+ // Output : analog_gain, digital_gain
+ virtual bool exposure_code_to_gain (
+ int32_t analog_code, int32_t digital_code,
+ double &analog_gain, double &digital_gain);
+
+private:
+ XCAM_DEAD_COPY (SensorDescriptor);
+
+private:
+ struct atomisp_sensor_mode_data _sensor_data;
+};
+
+};
+#endif //XCAM_SENSOR_DESCRIPTOR_H
diff --git a/xcore/smartptr.h b/xcore/smartptr.h
new file mode 100644
index 0000000..66f22d3
--- /dev/null
+++ b/xcore/smartptr.h
@@ -0,0 +1,137 @@
+/*
+ * xcam_SmartPtr.h - start pointer
+ *
+ * Copyright (c) 2014 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>
+ */
+#ifndef XCAM_SMARTPTR_H
+#define XCAM_SMARTPTR_H
+
+#include <stdint.h>
+#include <atomic>
+#include "xcam_defs.h"
+
+namespace XCam {
+
+class RefCount {
+public:
+ RefCount (): _ref_count(1) {}
+ void ref() {
+ ++_ref_count;
+ }
+ uint32_t unref() {
+ return --_ref_count;
+ }
+private:
+ mutable std::atomic<uint32_t> _ref_count;
+};
+
+
+template <typename Obj>
+class SmartPtr {
+private:
+ template<typename ObjDerive> friend class SmartPtr;
+public:
+ SmartPtr (Obj *obj = NULL) : _ptr (obj), _ref(NULL) {
+ if (_ptr)
+ _ref = new RefCount();
+ }
+ template <typename ObjDerive>
+ SmartPtr (ObjDerive *obj) : _ptr (obj), _ref(NULL) {
+ if (_ptr)
+ _ref = new RefCount();
+ }
+
+ // copy from pointer
+ SmartPtr (const SmartPtr<Obj> &obj)
+ : _ptr(obj._ptr), _ref(obj._ref) {
+ if (_ptr)
+ _ref->ref();
+ }
+ template <typename ObjDerive>
+ SmartPtr (const SmartPtr<ObjDerive> &obj)
+ : _ptr(obj._ptr), _ref(obj._ref) {
+ if (_ptr)
+ _ref->ref();
+ }
+ ~SmartPtr () {
+ release();
+ }
+
+ /* operator = */
+ SmartPtr<Obj> & operator = (Obj *obj) {
+ release ();
+ new_pointer (obj, NULL);
+ return *this;
+ }
+ template <typename ObjDerive>
+ SmartPtr<Obj> & operator = (ObjDerive *obj) {
+ release ();
+ new_pointer (obj, NULL);
+ return *this;
+ }
+ SmartPtr<Obj> & operator = (const SmartPtr<Obj> &obj) {
+ release ();
+ new_pointer (obj._ptr, obj._ref);
+ return *this;
+ }
+ template <typename ObjDerive>
+ SmartPtr<Obj> & operator = (const SmartPtr<ObjDerive> &obj) {
+ release ();
+ new_pointer (obj._ptr, obj._ref);
+ }
+
+ Obj *operator -> () const {
+ return _ptr;
+ }
+
+ Obj *ptr() const {
+ return _ptr;
+ }
+
+ void release() {
+ if (!_ptr)
+ return;
+ XCAM_ASSERT (_ref);
+ if (!_ref->unref()) {
+ delete _ref;
+ delete _ptr;
+ }
+ _ptr = NULL;
+ _ref = NULL;
+ }
+private:
+ void new_pointer (Obj *obj, RefCount *ref) {
+ if (!obj) {
+ _ptr = NULL;
+ _ref = NULL;
+ }
+ _ptr = obj;
+ if (ref) {
+ _ref = ref;
+ _ref->ref();
+ } else
+ _ref = new RefCount();
+ }
+
+private:
+
+ Obj *_ptr;
+ RefCount *_ref;
+};
+
+}; // end namespace
+#endif //XCAM_SMARTPTR_H
\ No newline at end of file
diff --git a/xcore/v4l2_buffer_proxy.cpp b/xcore/v4l2_buffer_proxy.cpp
new file mode 100644
index 0000000..64e7fb5
--- /dev/null
+++ b/xcore/v4l2_buffer_proxy.cpp
@@ -0,0 +1,115 @@
+/*
+ * v4l2_buffer_proxy.cpp - v4l2 buffer proxy
+ *
+ * Copyright (c) 2014-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 "v4l2_buffer_proxy.h"
+#include "v4l2_device.h"
+
+namespace XCam {
+V4l2Buffer::V4l2Buffer (const struct v4l2_buffer &buf, const struct v4l2_format &format)
+{
+ _buf = buf;
+ _format = format;
+}
+
+V4l2Buffer::~V4l2Buffer ()
+{
+}
+
+V4l2BufferProxy::V4l2BufferProxy (SmartPtr<V4l2Buffer> &buf, SmartPtr<V4l2Device> &device)
+ : _buf (buf)
+ , _device (device)
+{
+ VideoBufferInfo info;
+ struct timeval ts = buf->get_buf().timestamp;
+
+ xcam_mem_clear (&info);
+ v4l2_format_to_video_info (buf->get_format(), info);
+ set_video_info (info);
+ set_timestamp (XCAM_TIMEVAL_2_USEC (ts));
+}
+
+V4l2BufferProxy::~V4l2BufferProxy ()
+{
+ XCAM_ASSERT (_buf.ptr());
+ if (_device.ptr())
+ _device->queue_buffer (_buf);
+ XCAM_LOG_DEBUG ("v4l2 buffer released");
+}
+
+void
+V4l2BufferProxy::v4l2_format_to_video_info (
+ const struct v4l2_format &format, VideoBufferInfo &info)
+{
+ xcam_mem_clear (&info);
+
+ info.format = format.fmt.pix.pixelformat;
+ info.width = format.fmt.pix.width;
+ info.height = format.fmt.pix.height;
+ info.size = format.fmt.pix.sizeimage;
+ switch (format.fmt.pix.pixelformat) {
+ case V4L2_PIX_FMT_NV12: // 420
+ case V4L2_PIX_FMT_NV21:
+ info.components = 2;
+ info.strides [0] = format.fmt.pix.bytesperline * 2 / 3;
+ info.strides [1] = format.fmt.pix.bytesperline;
+ info.offsets[0] = 0;
+ info.offsets[1] = info.strides [0] * format.fmt.pix.height;
+ break;
+ case V4L2_PIX_FMT_YUV422P: // 422
+ info.components = 3;
+ info.strides [0] = format.fmt.pix.bytesperline / 2;
+ info.strides [1] = info.strides [0] / 2 ;
+ info.strides [2] = info.strides [0] / 2 ;
+ info.offsets[0] = 0;
+ info.offsets[1] = info.strides [0] * format.fmt.pix.height;
+ info.offsets[2] = info.offsets[1] + info.strides [1] * format.fmt.pix.height;
+ break;
+ default:
+ XCAM_LOG_WARNING (
+ "unknown v4l2 format(%s) to video info",
+ xcam_fourcc_to_string (format.fmt.pix.pixelformat));
+ break;
+ }
+
+}
+
+const struct v4l2_buffer &
+V4l2BufferProxy::get_v4l2_buf () const
+{
+ XCAM_ASSERT (_buf.ptr());
+ return _buf->get_buf ();
+}
+
+uint8_t *
+V4l2BufferProxy::map ()
+{
+ const struct v4l2_buffer & v4l2_buf = get_v4l2_buf ();
+ if (v4l2_buf.memory == V4L2_MEMORY_DMABUF)
+ return NULL;
+ return (uint8_t *)(v4l2_buf.m.userptr);
+}
+
+bool
+V4l2BufferProxy::unmap ()
+{
+ return true;
+}
+
+};
diff --git a/xcore/v4l2_buffer_proxy.h b/xcore/v4l2_buffer_proxy.h
new file mode 100644
index 0000000..af09936
--- /dev/null
+++ b/xcore/v4l2_buffer_proxy.h
@@ -0,0 +1,121 @@
+/*
+ * v4l2_buffer_proxy.h - v4l2 buffer proxy
+ *
+ * Copyright (c) 2014-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>
+ */
+
+#ifndef XCAM_V4L2_BUFFER_PROXY_H
+#define XCAM_V4L2_BUFFER_PROXY_H
+
+#include "video_buffer.h"
+#include "smartptr.h"
+#include <linux/videodev2.h>
+
+namespace XCam {
+
+class V4l2Device;
+
+class V4l2Buffer {
+public:
+ explicit V4l2Buffer (const struct v4l2_buffer &buf, const struct v4l2_format &format);
+ virtual ~V4l2Buffer ();
+
+ const struct v4l2_buffer & get_buf () const {
+ return _buf;
+ }
+
+ void set_timestamp (const struct timeval &time) {
+ _buf.timestamp = time;
+ }
+
+ void set_timecode (const struct v4l2_timecode &code) {
+ _buf.timecode = code;
+ }
+
+ void set_sequence (const uint32_t sequence) {
+ _buf.sequence = sequence;
+ }
+
+ void set_length (const uint32_t value) {
+ _buf.length = value;
+ }
+
+ void reset () {
+ xcam_mem_clear (&_buf.timestamp);
+ xcam_mem_clear (&_buf.timecode);
+ _buf.sequence = 0;
+ //_buf.length = 0;
+ }
+
+ const struct v4l2_format & get_format () const {
+ return _format;
+ }
+
+private:
+ XCAM_DEAD_COPY (V4l2Buffer);
+
+private:
+ struct v4l2_buffer _buf;
+ struct v4l2_format _format;
+};
+
+class V4l2BufferProxy
+ : public VideoBuffer
+{
+public:
+ explicit V4l2BufferProxy (SmartPtr<V4l2Buffer> &buf, SmartPtr<V4l2Device> &device);
+
+ ~V4l2BufferProxy ();
+
+ int get_v4l2_buf_index () {
+ return get_v4l2_buf().index;
+ }
+
+ int get_v4l2_mem_type () {
+ return get_v4l2_buf().memory;
+ }
+
+ int get_v4l2_buf_length () {
+ return get_v4l2_buf().length;
+ }
+
+ int get_v4l2_dma_fd () {
+ return get_v4l2_buf().m.fd;
+ }
+
+ uintptr_t get_v4l2_userptr () {
+ return get_v4l2_buf().m.userptr;
+ }
+
+ virtual uint8_t *map ();
+ virtual bool unmap ();
+
+private:
+ const struct v4l2_buffer & get_v4l2_buf () const;
+
+ void v4l2_format_to_video_info (
+ const struct v4l2_format &format, VideoBufferInfo &info);
+
+ XCAM_DEAD_COPY (V4l2BufferProxy);
+
+private:
+ SmartPtr<V4l2Buffer> _buf;
+ SmartPtr<V4l2Device> _device;
+};
+};
+
+#endif //XCAM_V4L2_BUFFER_PROXY_H
diff --git a/xcore/v4l2_device.cpp b/xcore/v4l2_device.cpp
new file mode 100644
index 0000000..ea4d225
--- /dev/null
+++ b/xcore/v4l2_device.cpp
@@ -0,0 +1,691 @@
+/*
+ * v4l2_device.cpp - v4l2 device
+ *
+ * Copyright (c) 2014-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>
+ * Author: John Ye <john.ye@intel.com>
+ */
+
+#include "v4l2_device.h"
+#include <sys/ioctl.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <poll.h>
+#include <sys/mman.h>
+
+#include "v4l2_buffer_proxy.h"
+
+namespace XCam {
+
+#define XCAM_V4L2_DEFAULT_BUFFER_COUNT 6
+
+V4l2Device::V4l2Device (const char *name)
+ : _name (NULL)
+ , _fd (-1)
+ , _sensor_id (0)
+ , _capture_mode (0)
+ , _capture_buf_type (V4L2_BUF_TYPE_VIDEO_CAPTURE)
+ , _memory_type (V4L2_MEMORY_MMAP)
+ , _fps_n (0)
+ , _fps_d (0)
+ , _active (false)
+ , _buf_count (XCAM_V4L2_DEFAULT_BUFFER_COUNT)
+{
+ if (name)
+ _name = strdup (name);
+ xcam_mem_clear (&_format);
+}
+
+V4l2Device::~V4l2Device ()
+{
+ close();
+ if (_name)
+ xcam_free (_name);
+}
+
+bool
+V4l2Device::set_device_name (const char *name)
+{
+ XCAM_ASSERT (name);
+
+ if (is_opened()) {
+ XCAM_LOG_WARNING ("can't set device name since device opened");
+ return false;
+ }
+ if (_name)
+ xcam_free (_name);
+ _name = strdup (name);
+ return true;
+}
+
+bool
+V4l2Device::set_sensor_id (int id)
+{
+ if (is_opened()) {
+ XCAM_LOG_WARNING ("can't set sensor id since device opened");
+ return false;
+ }
+ _sensor_id = id;
+ return true;
+}
+
+bool
+V4l2Device::set_capture_mode (uint32_t capture_mode)
+{
+ if (is_opened()) {
+ XCAM_LOG_WARNING ("can't set sensor id since device opened");
+ return false;
+ }
+ _capture_mode = capture_mode;
+ return true;
+}
+
+bool
+V4l2Device::set_framerate (uint32_t n, uint32_t d)
+{
+ if (_format.fmt.pix.pixelformat) {
+ XCAM_LOG_WARNING ("device(%s) set framerate failed since formated was already set.", XCAM_STR(_name));
+ return false;
+ }
+
+ _fps_n = n;
+ _fps_d = d;
+
+ return true;
+}
+
+void
+V4l2Device::get_framerate (uint32_t &n, uint32_t &d)
+{
+ n = _fps_n;
+ d = _fps_d;
+}
+
+bool
+V4l2Device::set_mem_type (enum v4l2_memory type) {
+ if (is_activated ()) {
+ XCAM_LOG_WARNING ("device(%s) set mem type failed", XCAM_STR (_name));
+ return false;
+ }
+ _memory_type = type;
+ return true;
+}
+
+bool
+V4l2Device::set_buffer_count (uint32_t buf_count)
+{
+ if (is_activated ()) {
+ XCAM_LOG_WARNING ("device(%s) set buffer count failed", XCAM_STR (_name));
+ return false;
+ }
+ _buf_count = buf_count;
+ return true;
+}
+
+
+XCamReturn
+V4l2Device::open ()
+{
+ struct v4l2_streamparm param;
+
+ if (is_opened()) {
+ XCAM_LOG_DEBUG ("device(%s) was already opened", XCAM_STR(_name));
+ return XCAM_RETURN_NO_ERROR;
+ }
+
+ if (!_name) {
+ XCAM_LOG_DEBUG ("v4l2 device open failed, there's no device name");
+ return XCAM_RETURN_ERROR_PARAM;
+ }
+ _fd = ::open (_name, O_RDWR);
+ if (_fd == -1) {
+ XCAM_LOG_DEBUG ("open device(%s) failed", _name);
+ return XCAM_RETURN_ERROR_IOCTL;
+ }
+
+ // set sensor id
+ if (io_control (VIDIOC_S_INPUT, &_sensor_id) < 0) {
+ XCAM_LOG_WARNING ("set sensor id(%d) failed but continue", _sensor_id);
+ }
+
+ // set capture mode
+ xcam_mem_clear (¶m);
+ param.type = _capture_buf_type;
+ param.parm.capture.capturemode = _capture_mode;
+ if (io_control (VIDIOC_S_PARM, ¶m) < 0) {
+ XCAM_LOG_WARNING ("set capture mode(0x%08x) failed but continue", _capture_mode);
+ }
+
+ return XCAM_RETURN_NO_ERROR;
+}
+
+XCamReturn
+V4l2Device::close ()
+{
+ if (!is_opened())
+ return XCAM_RETURN_NO_ERROR;
+ ::close (_fd);
+ _fd = -1;
+ return XCAM_RETURN_NO_ERROR;
+}
+
+int
+V4l2Device::io_control (int cmd, void *arg)
+
+{
+ if (_fd <= 0)
+ return -1;
+
+ return xcam_device_ioctl (_fd, cmd, arg);
+}
+
+int
+V4l2Device::poll_event (int timeout_msec)
+{
+ struct pollfd poll_fd;
+ int ret = 0;
+
+ XCAM_ASSERT (_fd > 0);
+
+ xcam_mem_clear (&poll_fd);
+ poll_fd.fd = _fd;
+ poll_fd.events = (POLLPRI | POLLIN | POLLERR | POLLNVAL | POLLHUP);
+
+ ret = poll (&poll_fd, 1, timeout_msec);
+ if (ret > 0 && (poll_fd.revents & (POLLERR | POLLNVAL | POLLHUP))) {
+ XCAM_LOG_DEBUG ("v4l2 subdev(%s) polled error", XCAM_STR(_name));
+ return -1;
+ }
+ return ret;
+
+}
+
+XCamReturn
+V4l2Device::set_format (struct v4l2_format &format)
+{
+ XCamReturn ret = XCAM_RETURN_NO_ERROR;
+
+ XCAM_FAIL_RETURN (ERROR, !is_activated (), XCAM_RETURN_ERROR_PARAM,
+ "Cannot set format to v4l2 device while it is active.");
+
+ XCAM_FAIL_RETURN (ERROR, is_opened (), XCAM_RETURN_ERROR_FILE,
+ "Cannot set format to v4l2 device while it is closed.");
+
+ ret = pre_set_format (format);
+ if (ret != XCAM_RETURN_NO_ERROR) {
+ XCAM_LOG_WARNING ("device(%s) pre_set_format failed", XCAM_STR (_name));
+ return ret;
+ }
+
+ if (io_control (VIDIOC_S_FMT, &format) < 0) {
+ if (errno == EBUSY) {
+ // TODO log device name
+ XCAM_LOG_ERROR("Video device is busy, fail to set format.");
+ } else {
+ // TODO log format details and errno
+ XCAM_LOG_ERROR("Fail to set format.");
+ }
+
+ return XCAM_RETURN_ERROR_IOCTL;
+ }
+
+ while (_fps_n && _fps_d) {
+ struct v4l2_streamparm param;
+ xcam_mem_clear (¶m);
+ param.type = _capture_buf_type;
+ if (io_control (VIDIOC_G_PARM, ¶m) < 0) {
+ XCAM_LOG_WARNING ("device(%s) set framerate failed on VIDIOC_G_PARM but continue", XCAM_STR (_name));
+ break;
+ }
+
+ if (!(param.parm.capture.capability & V4L2_CAP_TIMEPERFRAME))
+ break;
+
+ param.parm.capture.timeperframe.numerator = _fps_d;
+ param.parm.capture.timeperframe.denominator = _fps_n;
+
+ if (io_control (VIDIOC_S_PARM, ¶m) < 0) {
+ XCAM_LOG_WARNING ("device(%s) set framerate failed on VIDIOC_S_PARM but continue", XCAM_STR (_name));
+ break;
+ }
+ _fps_n = param.parm.capture.timeperframe.denominator;
+ _fps_d = param.parm.capture.timeperframe.numerator;
+ XCAM_LOG_INFO ("device(%s) set framerate(%d/%d)", XCAM_STR (_name), _fps_n, _fps_d);
+ }
+
+ ret = post_set_format (format);
+ if (ret != XCAM_RETURN_NO_ERROR) {
+ XCAM_LOG_WARNING ("device(%s) post_set_format failed", XCAM_STR (_name));
+ return ret;
+ }
+
+ _format = format;
+ XCAM_LOG_INFO (
+ "device(%s) set format(w:%d, h:%d, pixelformat:%s, bytesperline:%d,image_size:%d)",
+ XCAM_STR (_name),
+ format.fmt.pix.width, format.fmt.pix.height,
+ xcam_fourcc_to_string (format.fmt.pix.pixelformat),
+ format.fmt.pix.bytesperline,
+ format.fmt.pix.sizeimage);
+
+ return XCAM_RETURN_NO_ERROR;
+}
+
+/*! \brief v4l2 set format
+ *
+ * \param[in] width format width
+ * \param[in] height format height
+ * \param[in] pixelformat fourcc
+ * \param[in] field V4L2_FIELD_INTERLACED or V4L2_FIELD_NONE
+ */
+XCamReturn
+V4l2Device::set_format (
+ uint32_t width, uint32_t height,
+ uint32_t pixelformat, enum v4l2_field field, uint32_t bytes_perline)
+{
+
+ struct v4l2_format format;
+ xcam_mem_clear (&format);
+
+ format.type = _capture_buf_type;
+ format.fmt.pix.width = width;
+ format.fmt.pix.height = height;
+ format.fmt.pix.pixelformat = pixelformat;
+ format.fmt.pix.field = field;
+
+ if (bytes_perline != 0)
+ format.fmt.pix.bytesperline = bytes_perline;
+
+ return set_format (format);
+}
+
+XCamReturn
+V4l2Device::pre_set_format (struct v4l2_format &format)
+{
+ XCAM_UNUSED (format);
+ return XCAM_RETURN_NO_ERROR;
+}
+
+XCamReturn
+V4l2Device::post_set_format (struct v4l2_format &format)
+{
+ XCAM_UNUSED (format);
+ return XCAM_RETURN_NO_ERROR;
+}
+
+std::list<struct v4l2_fmtdesc>
+V4l2Device::enum_formats ()
+{
+ std::list<struct v4l2_fmtdesc> formats;
+ struct v4l2_fmtdesc format;
+ uint32_t i = 0;
+
+ while (1) {
+ xcam_mem_clear (&format);
+ format.index = i++;
+ format.type = _capture_buf_type;
+ if (this->io_control (VIDIOC_ENUM_FMT, &format) < 0) {
+ if (errno == EINVAL)
+ break;
+ else { // error
+ XCAM_LOG_DEBUG ("enum formats failed");
+ return formats;
+ }
+ }
+ formats.push_back (format);
+ }
+
+ return formats;
+}
+
+XCamReturn
+V4l2Device::get_format (struct v4l2_format &format)
+{
+ if (is_activated ()) {
+ format = _format;
+ return XCAM_RETURN_NO_ERROR;
+ }
+
+ if (!is_opened ())
+ return XCAM_RETURN_ERROR_IOCTL;
+
+ xcam_mem_clear (&format);
+ format.type = _capture_buf_type;
+
+ if (this->io_control (VIDIOC_G_FMT, &format) < 0) {
+ // FIXME: also log the device name?
+ XCAM_LOG_ERROR("Fail to get format via ioctl VIDVIO_G_FMT.");
+ return XCAM_RETURN_ERROR_IOCTL;
+ }
+
+ return XCAM_RETURN_NO_ERROR;
+}
+
+XCamReturn
+V4l2Device::start ()
+{
+ XCamReturn ret = XCAM_RETURN_NO_ERROR;
+ // request buffer first
+ ret = request_buffer ();
+ XCAM_FAIL_RETURN (
+ ERROR, ret == XCAM_RETURN_NO_ERROR, ret,
+ "device(%s) start failed", XCAM_STR (_name));
+
+ //alloc buffers
+ ret = init_buffer_pool ();
+ XCAM_FAIL_RETURN (
+ ERROR, ret == XCAM_RETURN_NO_ERROR, ret,
+ "device(%s) start failed", XCAM_STR (_name));
+
+ //queue all buffers
+ for (uint32_t i = 0; i < _buf_count; ++i) {
+ SmartPtr<V4l2Buffer> &buf = _buf_pool [i];
+ XCAM_ASSERT (buf.ptr());
+ XCAM_ASSERT (buf->get_buf().index == i);
+ ret = queue_buffer (buf);
+ if (ret != XCAM_RETURN_NO_ERROR) {
+ XCAM_LOG_ERROR (
+ "device(%s) start failed on queue index:%d",
+ XCAM_STR (_name), i);
+ stop ();
+ return ret;
+ }
+ }
+
+ // stream on
+ if (io_control (VIDIOC_STREAMON, &_capture_buf_type) < 0) {
+ XCAM_LOG_ERROR (
+ "device(%s) start failed on VIDIOC_STREAMON",
+ XCAM_STR (_name));
+ stop ();
+ return XCAM_RETURN_ERROR_IOCTL;
+ }
+ _active = true;
+ XCAM_LOG_INFO ("device(%s) started successfully", XCAM_STR (_name));
+ return XCAM_RETURN_NO_ERROR;
+}
+
+XCamReturn
+V4l2Device::stop ()
+{
+ // stream off
+ if (_active) {
+ if (io_control (VIDIOC_STREAMOFF, &_capture_buf_type) < 0) {
+ XCAM_LOG_WARNING ("device(%s) steamoff failed", XCAM_STR (_name));
+ }
+ _active = false;
+ }
+
+ fini_buffer_pool ();
+
+ XCAM_LOG_INFO ("device(%s) stopped", XCAM_STR (_name));
+ return XCAM_RETURN_NO_ERROR;
+}
+
+XCamReturn
+V4l2Device::request_buffer ()
+{
+ struct v4l2_requestbuffers request_buf;
+
+ XCAM_ASSERT (!is_activated());
+
+ xcam_mem_clear (&request_buf);
+ request_buf.type = _capture_buf_type;
+ request_buf.count = _buf_count;
+ request_buf.memory = _memory_type;
+
+ if (io_control (VIDIOC_REQBUFS, &request_buf) < 0) {
+ XCAM_LOG_INFO ("device(%s) starts failed on VIDIOC_REQBUFS", XCAM_STR (_name));
+ return XCAM_RETURN_ERROR_IOCTL;
+ }
+
+ if (request_buf.count != _buf_count) {
+ XCAM_LOG_DEBUG (
+ "device(%s) request buffer count doesn't match user settings, reset buffer count to %d",
+ XCAM_STR (_name), request_buf.count);
+ _buf_count = request_buf.count;
+ }
+ return XCAM_RETURN_NO_ERROR;
+}
+
+XCamReturn
+V4l2Device::allocate_buffer (
+ SmartPtr<V4l2Buffer> &buf,
+ const struct v4l2_format &format,
+ const uint32_t index)
+{
+ struct v4l2_buffer v4l2_buf;
+
+ xcam_mem_clear (&v4l2_buf);
+ v4l2_buf.index = index;
+ v4l2_buf.type = _capture_buf_type;
+ v4l2_buf.memory = _memory_type;
+
+ switch (_memory_type) {
+ case V4L2_MEMORY_DMABUF:
+ {
+ struct v4l2_exportbuffer expbuf;
+ xcam_mem_clear (&expbuf);
+ expbuf.type = _capture_buf_type;
+ expbuf.index = index;
+ expbuf.flags = O_CLOEXEC;
+ if (io_control (VIDIOC_EXPBUF, &expbuf) < 0) {
+ XCAM_LOG_WARNING ("device(%s) get dma buf(%d) failed", XCAM_STR (_name), index);
+ return XCAM_RETURN_ERROR_MEM;
+ }
+ v4l2_buf.m.fd = expbuf.fd;
+ v4l2_buf.length = format.fmt.pix.sizeimage;
+ }
+ break;
+ case V4L2_MEMORY_MMAP:
+ {
+ void *pointer;
+ if (io_control (VIDIOC_QUERYBUF, &v4l2_buf) < 0) {
+ XCAM_LOG_WARNING("device(%s) query MMAP buf(%d) failed", XCAM_STR(_name), index);
+ return XCAM_RETURN_ERROR_MEM;
+ }
+ pointer = mmap (0, v4l2_buf.length, PROT_READ | PROT_WRITE, MAP_SHARED, _fd, v4l2_buf.m.offset);
+ if (pointer == MAP_FAILED) {
+ XCAM_LOG_WARNING("device(%s) mmap buf(%d) failed", XCAM_STR(_name), index);
+ return XCAM_RETURN_ERROR_MEM;
+ }
+ v4l2_buf.m.userptr = (uintptr_t) pointer;
+ }
+ break;
+ case V4L2_MEMORY_USERPTR:
+ default:
+ XCAM_ASSERT (false);
+ XCAM_LOG_WARNING (
+ "device(%s) allocated buffer mem_type(%d) doesn't support",
+ XCAM_STR (_name), _memory_type);
+ return XCAM_RETURN_ERROR_MEM;
+ }
+
+ buf = new V4l2Buffer (v4l2_buf, _format);
+
+ return XCAM_RETURN_NO_ERROR;
+}
+
+XCamReturn
+V4l2Device::init_buffer_pool ()
+{
+ XCamReturn ret = XCAM_RETURN_NO_ERROR;
+ uint32_t i = 0;
+
+ _buf_pool.clear ();
+ _buf_pool.reserve (_buf_count);
+
+ for (; i < _buf_count; i++) {
+ SmartPtr<V4l2Buffer> new_buf;
+ ret = allocate_buffer (new_buf, _format, i);
+ if (ret != XCAM_RETURN_NO_ERROR) {
+ break;
+ }
+ _buf_pool.push_back (new_buf);
+ }
+
+ if (_buf_pool.empty()) {
+ XCAM_LOG_ERROR ("No bufer allocated in device(%s)", XCAM_STR (_name));
+ return XCAM_RETURN_ERROR_MEM;
+ }
+
+ if (i != _buf_count) {
+ XCAM_LOG_WARNING (
+ "device(%s) allocate buffer count:%d failback to %d",
+ XCAM_STR (_name), _buf_count, i);
+ _buf_count = i;
+ }
+
+ return XCAM_RETURN_NO_ERROR;
+}
+
+XCamReturn
+V4l2Device::fini_buffer_pool()
+{
+ _buf_pool.clear ();
+ return XCAM_RETURN_NO_ERROR;
+}
+
+XCamReturn
+V4l2Device::dequeue_buffer(SmartPtr<V4l2Buffer> &buf)
+{
+ struct v4l2_buffer v4l2_buf;
+
+ if (!is_activated()) {
+ XCAM_LOG_DEBUG (
+ "device(%s) dequeue buffer failed since not activated", XCAM_STR (_name));
+ return XCAM_RETURN_ERROR_PARAM;
+ }
+
+ xcam_mem_clear (&v4l2_buf);
+ v4l2_buf.type = _capture_buf_type;
+ v4l2_buf.memory = _memory_type;
+
+ if (this->io_control (VIDIOC_DQBUF, &v4l2_buf) < 0) {
+ XCAM_LOG_ERROR ("device(%s) fail to dequeue buffer.", XCAM_STR (_name));
+ return XCAM_RETURN_ERROR_IOCTL;
+ }
+
+ XCAM_LOG_DEBUG ("device(%s) dequeue buffer index:%d", XCAM_STR (_name), v4l2_buf.index);
+
+ if (v4l2_buf.index > _buf_count) {
+ XCAM_LOG_ERROR (
+ "device(%s) dequeue wrong buffer index:%d",
+ XCAM_STR (_name), v4l2_buf.index);
+ return XCAM_RETURN_ERROR_ISP;
+ }
+ buf = _buf_pool [v4l2_buf.index];
+ buf->set_timestamp (v4l2_buf.timestamp);
+ buf->set_timecode (v4l2_buf.timecode);
+ buf->set_sequence (v4l2_buf.sequence);
+ //buf.set_length (v4l2_buf.length); // not necessary to set length
+ return XCAM_RETURN_NO_ERROR;
+}
+
+XCamReturn
+V4l2Device::queue_buffer (SmartPtr<V4l2Buffer> &buf)
+{
+ XCAM_ASSERT (buf.ptr());
+ buf->reset ();
+
+ struct v4l2_buffer v4l2_buf = buf->get_buf ();
+ XCAM_ASSERT (v4l2_buf.index < _buf_count);
+
+ XCAM_LOG_DEBUG ("device(%s) queue buffer index:%d", XCAM_STR (_name), v4l2_buf.index);
+ if (io_control (VIDIOC_QBUF, &v4l2_buf) < 0) {
+ XCAM_LOG_ERROR("fail to enqueue buffer index:%d.", v4l2_buf.index);
+ return XCAM_RETURN_ERROR_IOCTL;
+ }
+ return XCAM_RETURN_NO_ERROR;
+}
+
+V4l2SubDevice::V4l2SubDevice (const char *name)
+ : V4l2Device (name)
+{
+}
+
+XCamReturn
+V4l2SubDevice::subscribe_event (int event)
+{
+ struct v4l2_event_subscription sub;
+ int ret = 0;
+
+ XCAM_ASSERT (is_opened());
+
+ xcam_mem_clear (&sub);
+ sub.type = event;
+
+ ret = this->io_control (VIDIOC_SUBSCRIBE_EVENT, &sub);
+ if (ret < 0) {
+ XCAM_LOG_DEBUG ("subdev(%s) subscribe event(%d) failed", XCAM_STR(_name), event);
+ return XCAM_RETURN_ERROR_IOCTL;
+ }
+ return XCAM_RETURN_NO_ERROR;
+}
+
+XCamReturn
+V4l2SubDevice::unsubscribe_event (int event)
+{
+ struct v4l2_event_subscription sub;
+ int ret = 0;
+
+ XCAM_ASSERT (is_opened());
+
+ xcam_mem_clear (&sub);
+ sub.type = event;
+
+ ret = this->io_control (VIDIOC_UNSUBSCRIBE_EVENT, &sub);
+ if (ret < 0) {
+ XCAM_LOG_DEBUG ("subdev(%s) unsubscribe event(%d) failed", XCAM_STR(_name), event);
+ return XCAM_RETURN_ERROR_IOCTL;
+ }
+ return XCAM_RETURN_NO_ERROR;
+}
+
+XCamReturn
+V4l2SubDevice::dequeue_event (struct v4l2_event &event)
+{
+ int ret = 0;
+ XCAM_ASSERT (is_opened());
+
+ ret = this->io_control (VIDIOC_DQEVENT, &event);
+ if (ret < 0) {
+ XCAM_LOG_DEBUG ("subdev(%s) dequeue event failed", XCAM_STR(_name));
+ return XCAM_RETURN_ERROR_IOCTL;
+ }
+
+ return XCAM_RETURN_NO_ERROR;
+}
+
+XCamReturn V4l2SubDevice::start ()
+{
+ if (!is_opened())
+ return XCAM_RETURN_ERROR_PARAM;
+
+ _active = true;
+ return XCAM_RETURN_NO_ERROR;
+}
+
+XCamReturn V4l2SubDevice::stop ()
+{
+ if (_active)
+ _active = false;
+
+ return XCAM_RETURN_NO_ERROR;
+}
+
+};
diff --git a/xcore/v4l2_device.h b/xcore/v4l2_device.h
new file mode 100644
index 0000000..fa09c53
--- /dev/null
+++ b/xcore/v4l2_device.h
@@ -0,0 +1,168 @@
+/*
+ * v4l2_device.h - v4l2 device
+ *
+ * Copyright (c) 2014-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>
+ */
+
+#ifndef XCAM_V4L2_DEVICE_H
+#define XCAM_V4L2_DEVICE_H
+
+#include "xcam_common.h"
+#include "smartptr.h"
+#include <linux/videodev2.h>
+#include <list>
+#include <vector>
+
+extern "C" {
+ struct v4l2_event;
+ struct v4l2_format;
+ struct v4l2_fmtdesc;
+ struct v4l2_frmsizeenum;
+}
+
+namespace XCam {
+
+class V4l2Buffer;
+
+class V4l2Device {
+ friend class V4l2BufferProxy;
+ typedef std::vector<SmartPtr<V4l2Buffer>> BufferPool;
+
+public:
+ V4l2Device (const char *name = NULL);
+ virtual ~V4l2Device ();
+
+ // before device open
+ bool set_device_name (const char *name);
+ bool set_sensor_id (int id);
+ bool set_capture_mode (uint32_t capture_mode);
+
+ int get_fd () const {
+ return _fd;
+ }
+ const char *get_device_name () const {
+ return _name;
+ }
+ bool is_opened () const {
+ return (_fd != -1);
+ }
+ bool is_activated () const {
+ return _active;
+ }
+
+ // set_mem_type must before set_format
+ bool set_mem_type (enum v4l2_memory type);
+ enum v4l2_memory get_mem_type () const {
+ return _memory_type;
+ }
+ enum v4l2_buf_type get_capture_buf_type () const {
+ return _capture_buf_type;
+ }
+ void get_size (uint32_t &width, uint32_t &height) const {
+ width = _format.fmt.pix.width;
+ height = _format.fmt.pix.height;
+ }
+ uint32_t get_pixel_format () const {
+ return _format.fmt.pix.pixelformat;
+ }
+
+ bool set_buffer_count (uint32_t buf_count);
+
+ // set_framerate must before set_format
+ bool set_framerate (uint32_t n, uint32_t d);
+ void get_framerate (uint32_t &n, uint32_t &d);
+
+ XCamReturn open ();
+ XCamReturn close ();
+ // set_format
+ XCamReturn get_format (struct v4l2_format &format);
+ XCamReturn set_format (struct v4l2_format &format);
+ XCamReturn set_format (
+ uint32_t width, uint32_t height, uint32_t pixelformat,
+ enum v4l2_field field = V4L2_FIELD_NONE, uint32_t bytes_perline = 0);
+
+ std::list<struct v4l2_fmtdesc> enum_formats ();
+
+ virtual XCamReturn start ();
+ virtual XCamReturn stop ();
+
+ int poll_event (int timeout_msec);
+ XCamReturn dequeue_buffer (SmartPtr<V4l2Buffer> &buf);
+ XCamReturn queue_buffer (SmartPtr<V4l2Buffer> &buf);
+
+ // use as less as possible
+ int io_control (int cmd, void *arg);
+
+protected:
+
+ //virtual functions, handle private actions on set_format
+ virtual XCamReturn pre_set_format (struct v4l2_format &format);
+ virtual XCamReturn post_set_format (struct v4l2_format &format);
+ virtual XCamReturn allocate_buffer (
+ SmartPtr<V4l2Buffer> &buf,
+ const struct v4l2_format &format,
+ const uint32_t index);
+
+private:
+ XCamReturn request_buffer ();
+ XCamReturn init_buffer_pool ();
+ XCamReturn fini_buffer_pool ();
+
+ XCAM_DEAD_COPY (V4l2Device);
+
+protected:
+ char *_name;
+ int _fd;
+ int32_t _sensor_id;
+ uint32_t _capture_mode;
+ enum v4l2_buf_type _capture_buf_type;
+ enum v4l2_memory _memory_type;
+
+ struct v4l2_format _format;
+ uint32_t _fps_n;
+ uint32_t _fps_d;
+
+ bool _active;
+
+ // buffer pool
+ BufferPool _buf_pool;
+ uint32_t _buf_count;
+
+ XCamReturn buffer_new();
+ XCamReturn buffer_del();
+};
+
+class V4l2SubDevice
+ : public V4l2Device
+{
+public:
+ explicit V4l2SubDevice (const char *name = NULL);
+
+ XCamReturn subscribe_event (int event);
+ XCamReturn unsubscribe_event (int event);
+ XCamReturn dequeue_event (struct v4l2_event &event);
+
+ virtual XCamReturn start ();
+ virtual XCamReturn stop ();
+
+private:
+ XCAM_DEAD_COPY (V4l2SubDevice);
+};
+
+};
+#endif // XCAM_V4L2_DEVICE_H
+
diff --git a/xcore/video_buffer.h b/xcore/video_buffer.h
new file mode 100644
index 0000000..66e9ce9
--- /dev/null
+++ b/xcore/video_buffer.h
@@ -0,0 +1,78 @@
+/*
+ * video_buffer.h - video buffer base
+ *
+ * Copyright (c) 2014-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>
+ */
+
+#ifndef XCAM_VIDEO_BUFFER_H
+#define XCAM_VIDEO_BUFFER_H
+
+#include "xcam_defs.h"
+#include "xcam_common.h"
+#include "xcam_utils.h"
+
+namespace XCam {
+
+#define XCAM_VIDEO_MAX_COMPONENTS 4
+
+typedef struct _VideoBufferInfo {
+ uint32_t format;
+ uint32_t width;
+ uint32_t height;
+ uint32_t size;
+ uint32_t components;
+ uint32_t strides [XCAM_VIDEO_MAX_COMPONENTS];
+ uint32_t offsets [XCAM_VIDEO_MAX_COMPONENTS];
+} VideoBufferInfo;
+
+class VideoBuffer {
+public:
+ explicit VideoBuffer (int64_t timestamp = InvalidTimestamp)
+ : _timestamp (timestamp)
+ {}
+ explicit VideoBuffer (const VideoBufferInfo &info, int64_t timestamp = InvalidTimestamp)
+ : _videoinfo (info)
+ , _timestamp (timestamp)
+ {}
+ virtual ~VideoBuffer () {}
+
+ virtual uint8_t *map () = 0;
+ virtual bool unmap () = 0;
+
+ const VideoBufferInfo & get_video_info () const {
+ return _videoinfo;
+ }
+ int64_t get_timestamp () const {
+ return _timestamp;
+ }
+
+ void set_video_info (const VideoBufferInfo &info) {
+ _videoinfo = info;
+ }
+
+ void set_timestamp (int64_t timestamp) {
+ _timestamp = timestamp;
+ }
+
+private:
+ VideoBufferInfo _videoinfo;
+ int64_t _timestamp; // in microseconds
+};
+
+};
+
+#endif //XCAM_BUFFER_PROXY_H
diff --git a/xcore/x3a_analyzer.cpp b/xcore/x3a_analyzer.cpp
new file mode 100644
index 0000000..57b5264
--- /dev/null
+++ b/xcore/x3a_analyzer.cpp
@@ -0,0 +1,548 @@
+/*
+ * x3a_analyzer.cpp - 3a analyzer
+ *
+ * Copyright (c) 2014-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 "x3a_analyzer.h"
+#include "xcam_thread.h"
+#include "safe_list.h"
+#include "x3a_statistics_queue.h"
+
+namespace XCam {
+
+class AnalyzerThread
+ : public Thread
+{
+public:
+ AnalyzerThread (X3aAnalyzer *analyzer);
+ ~AnalyzerThread ();
+
+ void triger_stop() {
+ _3a_stats_queue.wakeup ();
+ }
+ bool push_stats (SmartPtr<X3aIspStatistics> &stats);
+
+protected:
+ virtual bool started ();
+ virtual void stopped () {
+ _3a_stats_queue.clear ();
+ }
+ virtual bool loop ();
+
+private:
+ X3aAnalyzer *_analyzer;
+ SafeList<X3aIspStatistics> _3a_stats_queue;
+};
+
+AnalyzerThread::AnalyzerThread (X3aAnalyzer *analyzer)
+ : Thread ("AnalyzerThread")
+ , _analyzer (analyzer)
+{}
+
+AnalyzerThread::~AnalyzerThread ()
+{
+ _3a_stats_queue.clear ();
+}
+
+bool
+AnalyzerThread::push_stats (SmartPtr<X3aIspStatistics> &stats)
+{
+ _3a_stats_queue.push (stats);
+ return true;
+}
+
+bool
+AnalyzerThread::started ()
+{
+ XCamReturn ret = XCAM_RETURN_NO_ERROR;
+
+ XCAM_ASSERT (_analyzer);
+ ret = _analyzer->configure_3a ();
+ if (ret != XCAM_RETURN_NO_ERROR) {
+ _analyzer->notify_calculation_failed (NULL, 0, "configure 3a failed");
+ XCAM_LOG_WARNING ("analyzer(%s) configure 3a failed", XCAM_STR(_analyzer->get_name()));
+ return false;
+ }
+
+ return true;
+}
+
+bool
+AnalyzerThread::loop ()
+{
+ const static int32_t timeout = -1;
+ SmartPtr<X3aIspStatistics> stats = _3a_stats_queue.pop (timeout);
+ if (!stats.ptr()) {
+ XCAM_LOG_DEBUG ("analyzer thread got empty stats, stop thread");
+ return false;
+ }
+ XCamReturn ret = _analyzer->analyze_3a_statistics (stats);
+ if (ret == XCAM_RETURN_NO_ERROR || ret == XCAM_RETURN_BYPASS)
+ return true;
+
+ XCAM_LOG_DEBUG ("analyzer(%s) failed to analyze 3a stats", XCAM_STR(_analyzer->get_name()));
+ return false;
+}
+
+void
+AnalyzerCallback::x3a_calculation_done (X3aAnalyzer *analyzer, X3aResultList &results)
+{
+ XCAM_UNUSED (analyzer);
+
+ for (X3aResultList::iterator i_res = results.begin();
+ i_res != results.end(); ++i_res) {
+ SmartPtr<X3aResult> res = *i_res;
+ XCAM_LOG_DEBUG (
+ "calculated 3a result(type:%d, timestamp:" XCAM_TIMESTAMP_FORMAT ")",
+ res->get_type (), XCAM_TIMESTAMP_ARGS (res->get_timestamp ()));
+ }
+}
+
+void
+AnalyzerCallback::x3a_calculation_failed (X3aAnalyzer *analyzer, int64_t timestamp, const char *msg)
+{
+ XCAM_UNUSED (analyzer);
+
+ XCAM_LOG_WARNING (
+ "Calculate 3a result failed, ts(" XCAM_TIMESTAMP_FORMAT "), msg:%s",
+ XCAM_TIMESTAMP_ARGS (timestamp), XCAM_STR (msg));
+}
+
+X3aAnalyzer::X3aAnalyzer (const char *name)
+ : _name (NULL)
+ , _width (0)
+ , _height (0)
+ , _ae_handler (NULL)
+ , _awb_handler (NULL)
+ , _af_handler (NULL)
+ , _common_handler (NULL)
+ , _callback (NULL)
+{
+ if (name)
+ _name = strdup (name);
+ _3a_analyzer_thread = new AnalyzerThread (this);
+}
+
+X3aAnalyzer::~X3aAnalyzer()
+{
+ if (_name)
+ xcam_free (_name);
+}
+
+bool
+X3aAnalyzer::set_results_callback (AnalyzerCallback *callback)
+{
+ XCAM_ASSERT (!_callback);
+ _callback = callback;
+ return true;
+}
+
+XCamReturn
+X3aAnalyzer::init (uint32_t width, uint32_t height)
+{
+ XCamReturn ret = XCAM_RETURN_NO_ERROR;
+ SmartPtr<AeHandler> ae_handler;
+ SmartPtr<AwbHandler> awb_handler;
+ SmartPtr<AfHandler> af_handler;
+ SmartPtr<CommonHandler> common_handler;
+
+
+ XCAM_ASSERT (!_width && !_height);
+ _width = width;
+ _height = height;
+
+ XCAM_ASSERT (!_ae_handler.ptr() || !_awb_handler.ptr() ||
+ !_af_handler.ptr() || !_common_handler.ptr());
+
+ ae_handler = create_ae_handler ();
+ awb_handler = create_awb_handler ();
+ af_handler = create_af_handler ();
+ common_handler = create_common_handler ();
+
+ if (!ae_handler.ptr() || !awb_handler.ptr() || !af_handler.ptr() || !common_handler.ptr()) {
+ XCAM_LOG_WARNING ("create handlers failed");
+ deinit ();
+ return XCAM_RETURN_ERROR_MEM;
+ }
+ _ae_handler = ae_handler;
+ _awb_handler = awb_handler;
+ _af_handler = af_handler;
+ _common_handler = common_handler;
+
+ ret = internal_init (width, height);
+ if (ret != XCAM_RETURN_NO_ERROR) {
+ XCAM_LOG_WARNING ("analyzer init failed");
+ deinit ();
+ return ret;
+ }
+
+ XCAM_LOG_INFO (
+ "Analyzer(%s) initialized(w:%d, h:%d).",
+ XCAM_STR(get_name()), _width, _height);
+ return XCAM_RETURN_NO_ERROR;
+}
+
+XCamReturn
+X3aAnalyzer::deinit ()
+{
+ internal_deinit();
+
+ _ae_handler.release ();
+ _awb_handler.release ();
+ _af_handler.release ();
+ _common_handler.release ();
+
+ _width = 0;
+ _height = 0;
+
+ XCAM_LOG_INFO ("Analyzer(%s) deinited.", XCAM_STR(get_name()));
+ return XCAM_RETURN_NO_ERROR;
+}
+
+XCamReturn
+X3aAnalyzer::start ()
+{
+ if (_3a_analyzer_thread->start () == false) {
+ XCAM_LOG_WARNING ("analyzer thread start failed");
+ stop ();
+ return XCAM_RETURN_ERROR_THREAD;
+ }
+
+ XCAM_LOG_INFO ("Analyzer(%s) started.", XCAM_STR(get_name()));
+ return XCAM_RETURN_NO_ERROR;
+}
+
+XCamReturn
+X3aAnalyzer::stop ()
+{
+ _3a_analyzer_thread->triger_stop ();
+ _3a_analyzer_thread->stop ();
+
+ XCAM_LOG_INFO ("Analyzer(%s) stopped.", XCAM_STR(get_name()));
+ return XCAM_RETURN_NO_ERROR;
+}
+
+XCamReturn
+X3aAnalyzer::push_3a_stats (SmartPtr<X3aIspStatistics> &stats)
+{
+ if (!_3a_analyzer_thread->is_running())
+ return XCAM_RETURN_ERROR_THREAD;
+
+ if (_3a_analyzer_thread->push_stats (stats))
+ return XCAM_RETURN_NO_ERROR;
+
+ return XCAM_RETURN_ERROR_THREAD;
+}
+
+XCamReturn
+X3aAnalyzer::analyze_3a_statistics (SmartPtr<X3aIspStatistics> &stats)
+{
+ XCamReturn ret = XCAM_RETURN_NO_ERROR;
+ X3aResultList results;
+
+ ret = pre_3a_analyze (stats);
+ if (ret != XCAM_RETURN_NO_ERROR) {
+ notify_calculation_failed(
+ NULL, stats->get_timestamp (), "ae calculation failed");
+ return ret;
+ }
+
+ ret = _ae_handler->analyze (results);
+ if (ret != XCAM_RETURN_NO_ERROR) {
+ notify_calculation_failed(
+ _ae_handler.ptr(), stats->get_timestamp (), "ae calculation failed");
+ return ret;
+ }
+
+ ret = _awb_handler->analyze (results);
+ if (ret != XCAM_RETURN_NO_ERROR) {
+ notify_calculation_failed(
+ _awb_handler.ptr(), stats->get_timestamp (), "awb calculation failed");
+ return ret;
+ }
+
+ ret = _af_handler->analyze (results);
+ if (ret != XCAM_RETURN_NO_ERROR) {
+ notify_calculation_failed(
+ _af_handler.ptr(), stats->get_timestamp (), "af calculation failed");
+ return ret;
+ }
+
+ ret = _common_handler->analyze (results);
+ if (ret != XCAM_RETURN_NO_ERROR) {
+ notify_calculation_failed(
+ _common_handler.ptr(), stats->get_timestamp (), "3a other calculation failed");
+ return ret;
+ }
+
+ ret = post_3a_analyze (results);
+ if (ret != XCAM_RETURN_NO_ERROR) {
+ notify_calculation_failed(
+ NULL, stats->get_timestamp (), "3a collect results failed");
+ return ret;
+ }
+
+ if (!results.empty ())
+ notify_calculation_done (results);
+
+ return ret;
+
+}
+
+void
+X3aAnalyzer::notify_calculation_failed (AnalyzerHandler *handler, int64_t timestamp, const char *msg)
+{
+ XCAM_UNUSED (handler);
+
+ if (_callback)
+ _callback->x3a_calculation_failed (this, timestamp, msg);
+ XCAM_LOG_DEBUG (
+ "calculation failed on ts:" XCAM_TIMESTAMP_FORMAT ", reason:%s",
+ XCAM_TIMESTAMP_ARGS (timestamp), XCAM_STR (msg));
+}
+
+void
+X3aAnalyzer::notify_calculation_done (X3aResultList &results)
+{
+ XCAM_ASSERT (!results.empty ());
+ if (_callback)
+ _callback->x3a_calculation_done (this, results);
+}
+
+/* AWB */
+bool
+X3aAnalyzer::set_awb_mode (XCamAwbMode mode)
+{
+ XCAM_ASSERT (_awb_handler.ptr());
+ return _awb_handler->set_mode (mode);
+}
+
+bool
+X3aAnalyzer::set_awb_speed (double speed)
+{
+ XCAM_ASSERT (_awb_handler.ptr());
+ return _awb_handler->set_speed (speed);
+}
+
+bool
+X3aAnalyzer::set_awb_color_temperature_range (uint32_t cct_min, uint32_t cct_max)
+{
+ XCAM_ASSERT (_awb_handler.ptr());
+ return _awb_handler->set_color_temperature_range (cct_min, cct_max);
+}
+
+bool
+X3aAnalyzer::set_awb_manual_gain (double gr, double r, double b, double gb)
+{
+ XCAM_ASSERT (_awb_handler.ptr());
+ return _awb_handler->set_manual_gain (gr, r, b, gb);
+}
+
+/* AE */
+bool
+X3aAnalyzer::set_ae_mode (XCamAeMode mode)
+{
+ XCAM_ASSERT (_ae_handler.ptr());
+ return _ae_handler->set_mode (mode);
+}
+
+bool
+X3aAnalyzer::set_ae_metering_mode (XCamAeMeteringMode mode)
+{
+ XCAM_ASSERT (_ae_handler.ptr());
+ return _ae_handler->set_metering_mode (mode);
+}
+
+bool
+X3aAnalyzer::set_ae_window (XCam3AWindow *window)
+{
+ XCAM_ASSERT (_ae_handler.ptr());
+ return _ae_handler->set_window (window);
+}
+
+bool
+X3aAnalyzer::set_ae_ev_shift (double ev_shift)
+{
+ XCAM_ASSERT (_ae_handler.ptr());
+ return _ae_handler->set_ev_shift (ev_shift);
+}
+
+bool
+X3aAnalyzer::set_ae_speed (double speed)
+{
+ XCAM_ASSERT (_ae_handler.ptr());
+ return _ae_handler->set_speed (speed);
+}
+
+bool
+X3aAnalyzer::set_ae_flicker_mode (XCamFlickerMode flicker)
+{
+ XCAM_ASSERT (_ae_handler.ptr());
+ return _ae_handler->set_flicker_mode (flicker);
+}
+
+XCamFlickerMode
+X3aAnalyzer::get_ae_flicker_mode ()
+{
+ XCAM_ASSERT (_ae_handler.ptr());
+ return _ae_handler->get_flicker_mode ();
+}
+
+uint64_t
+X3aAnalyzer::get_ae_current_exposure_time ()
+{
+ XCAM_ASSERT (_ae_handler.ptr());
+ return _ae_handler->get_current_exposure_time();
+}
+
+double
+X3aAnalyzer::get_ae_current_analog_gain ()
+{
+ XCAM_ASSERT (_ae_handler.ptr());
+ return _ae_handler->get_current_analog_gain ();
+}
+
+bool
+X3aAnalyzer::set_ae_manual_exposure_time (int64_t time_in_us)
+{
+ XCAM_ASSERT (_ae_handler.ptr());
+ return _ae_handler->set_manual_exposure_time (time_in_us);
+}
+
+bool
+X3aAnalyzer::set_ae_manual_analog_gain (double gain)
+{
+ XCAM_ASSERT (_ae_handler.ptr());
+ return _ae_handler->set_manual_analog_gain (gain);
+}
+
+bool
+X3aAnalyzer::set_ae_aperture (double fn)
+{
+ XCAM_ASSERT (_ae_handler.ptr());
+ return _ae_handler->set_aperture (fn);
+}
+
+bool
+X3aAnalyzer::set_ae_max_analog_gain (double max_gain)
+{
+ XCAM_ASSERT (_ae_handler.ptr());
+ return _ae_handler->set_max_analog_gain (max_gain);
+}
+
+double
+X3aAnalyzer::get_ae_max_analog_gain ()
+{
+ XCAM_ASSERT (_ae_handler.ptr());
+ return _ae_handler->get_max_analog_gain();
+}
+
+bool
+X3aAnalyzer::set_ae_exposure_time_range (int64_t min_time_in_us, int64_t max_time_in_us)
+{
+ XCAM_ASSERT (_ae_handler.ptr());
+ return _ae_handler->set_exposure_time_range (min_time_in_us, max_time_in_us);
+}
+
+bool
+X3aAnalyzer::get_ae_exposure_time_range (int64_t *min_time_in_us, int64_t *max_time_in_us)
+{
+ XCAM_ASSERT (_ae_handler.ptr());
+ return _ae_handler->get_exposure_time_range (min_time_in_us, max_time_in_us);
+}
+
+/* DVS */
+bool
+X3aAnalyzer::set_dvs (bool enable)
+{
+ XCAM_ASSERT (_common_handler.ptr());
+ return _common_handler->set_dvs (enable);
+}
+
+bool
+X3aAnalyzer::set_gbce (bool enable)
+{
+ XCAM_ASSERT (_common_handler.ptr());
+ return _common_handler->set_gbce (enable);
+}
+
+bool
+X3aAnalyzer::set_night_mode (bool enable)
+{
+ XCAM_ASSERT (_common_handler.ptr());
+ return _common_handler->set_night_mode (enable);
+}
+
+/* Picture quality */
+bool
+X3aAnalyzer::set_noise_reduction_level (double level)
+{
+ XCAM_ASSERT (_common_handler.ptr());
+ return _common_handler->set_noise_reduction_level (level);
+}
+
+bool
+X3aAnalyzer::set_temporal_noise_reduction_level (double level)
+{
+ XCAM_ASSERT (_common_handler.ptr());
+ return _common_handler->set_temporal_noise_reduction_level (level);
+}
+
+bool
+X3aAnalyzer::set_manual_brightness (double level)
+{
+ XCAM_ASSERT (_common_handler.ptr());
+ return _common_handler->set_manual_brightness (level);
+}
+
+bool
+X3aAnalyzer::set_manual_contrast (double level)
+{
+ XCAM_ASSERT (_common_handler.ptr());
+ return _common_handler->set_manual_contrast (level);
+}
+
+bool
+X3aAnalyzer::set_manual_hue (double level)
+{
+ XCAM_ASSERT (_common_handler.ptr());
+ return _common_handler->set_manual_hue (level);
+}
+
+bool
+X3aAnalyzer::set_manual_saturation (double level)
+{
+ XCAM_ASSERT (_common_handler.ptr());
+ return _common_handler->set_manual_saturation (level);
+}
+
+bool
+X3aAnalyzer::set_manual_sharpness (double level)
+{
+ XCAM_ASSERT (_common_handler.ptr());
+ return _common_handler->set_manual_sharpness (level);
+}
+
+bool
+X3aAnalyzer::set_gamma_table (double *r_table, double *g_table, double *b_table)
+{
+ XCAM_ASSERT (_common_handler.ptr());
+ return _common_handler->set_gamma_table (r_table, g_table, b_table);
+}
+
+};
diff --git a/xcore/x3a_analyzer.h b/xcore/x3a_analyzer.h
new file mode 100644
index 0000000..5173b5d
--- /dev/null
+++ b/xcore/x3a_analyzer.h
@@ -0,0 +1,168 @@
+/*
+ * x3a_analyzer.h - 3a analyzer
+ *
+ * Copyright (c) 2014-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>
+ */
+
+#ifndef XCAM_3A_ANALYZER_H
+#define XCAM_3A_ANALYZER_H
+
+#include "xcam_common.h"
+#include "xcam_defs.h"
+#include "xcam_utils.h"
+#include "handler_interface.h"
+
+namespace XCam {
+
+class X3aAnalyzer;
+class X3aIspStatistics;
+
+class AnalyzerCallback {
+public:
+ explicit AnalyzerCallback () {}
+ virtual ~AnalyzerCallback () {}
+ virtual void x3a_calculation_done (X3aAnalyzer *analyzer, X3aResultList &results);
+ virtual void x3a_calculation_failed (X3aAnalyzer *analyzer, int64_t timestamp, const char *msg);
+
+private:
+ XCAM_DEAD_COPY (AnalyzerCallback);
+};
+
+class AnalyzerThread;
+
+class X3aAnalyzer {
+ friend class AnalyzerThread;
+public:
+ explicit X3aAnalyzer (const char *name = NULL);
+ virtual ~X3aAnalyzer ();
+
+ bool set_results_callback (AnalyzerCallback *callback);
+
+ XCamReturn init (uint32_t width, uint32_t height);
+ XCamReturn deinit ();
+ XCamReturn start ();
+ XCamReturn stop ();
+
+ /* analyze 3A statistics */
+ XCamReturn push_3a_stats (SmartPtr<X3aIspStatistics> &stats);
+
+ /* AWB */
+ bool set_awb_mode (XCamAwbMode mode);
+ bool set_awb_speed (double speed);
+ bool set_awb_color_temperature_range (uint32_t cct_min, uint32_t cct_max);
+ bool set_awb_manual_gain (double gr, double r, double b, double gb);
+
+ /* AE */
+ bool set_ae_mode (XCamAeMode mode);
+ bool set_ae_metering_mode (XCamAeMeteringMode mode);
+ bool set_ae_window (XCam3AWindow *window);
+ bool set_ae_ev_shift (double ev_shift);
+ bool set_ae_speed (double speed);
+ bool set_ae_flicker_mode (XCamFlickerMode flicker);
+
+ XCamFlickerMode get_ae_flicker_mode ();
+ uint64_t get_ae_current_exposure_time ();
+ double get_ae_current_analog_gain ();
+
+ bool set_ae_manual_exposure_time (int64_t time_in_us);
+ bool set_ae_manual_analog_gain (double gain);
+ bool set_ae_aperture (double fn);
+ bool set_ae_max_analog_gain (double max_gain);
+ double get_ae_max_analog_gain ();
+ bool set_ae_exposure_time_range (int64_t min_time_in_us, int64_t max_time_in_us);
+ bool get_ae_exposure_time_range (int64_t *min_time_in_us, int64_t *max_time_in_us);
+
+ /* DVS */
+ bool set_dvs (bool enable);
+ bool set_gbce (bool enable);
+ bool set_night_mode (bool enable);
+
+ /* Picture quality */
+ bool set_noise_reduction_level (double level);
+ bool set_temporal_noise_reduction_level (double level);
+ bool set_manual_brightness (double level);
+ bool set_manual_contrast (double level);
+ bool set_manual_hue (double level);
+ bool set_manual_saturation (double level);
+ bool set_manual_sharpness (double level);
+ bool set_gamma_table (double *r_table, double *g_table, double *b_table);
+
+ uint32_t get_width () const {
+ return _width;
+ }
+ uint32_t get_height () const {
+ return _height;
+ }
+ const char * get_name () const {
+ return _name;
+ }
+
+ SmartPtr<AeHandler> get_ae_handler () {
+ return _ae_handler;
+ }
+ SmartPtr<AwbHandler> get_awb_handler () {
+ return _awb_handler;
+ }
+ SmartPtr<AfHandler> get_af_handler () {
+ return _af_handler;
+ }
+ SmartPtr<CommonHandler> get_common_handler () {
+ return _common_handler;
+ }
+
+protected:
+ /* virtual function list */
+ virtual SmartPtr<AeHandler> create_ae_handler () = 0;
+ virtual SmartPtr<AwbHandler> create_awb_handler () = 0;
+ virtual SmartPtr<AfHandler> create_af_handler () = 0;
+ virtual SmartPtr<CommonHandler> create_common_handler () = 0;
+ virtual XCamReturn internal_init (uint32_t width, uint32_t height) = 0;
+ virtual XCamReturn internal_deinit () = 0;
+
+ // in 3a stats thread
+ virtual XCamReturn configure_3a () = 0;
+ // @param[in] stats, 3a statistics prepared
+ virtual XCamReturn pre_3a_analyze (SmartPtr<X3aIspStatistics> &stats) = 0;
+ // @param[out] results, new 3a results merged into \c results
+ virtual XCamReturn post_3a_analyze (X3aResultList &results) = 0;
+
+protected:
+ void notify_calculation_done (X3aResultList &results);
+ void notify_calculation_failed (AnalyzerHandler *handler, int64_t timestamp, const char *msg);
+
+private:
+ XCamReturn analyze_3a_statistics (SmartPtr<X3aIspStatistics> &stats);
+
+ XCAM_DEAD_COPY (X3aAnalyzer);
+
+private:
+ char *_name;
+ uint32_t _width;
+ uint32_t _height;
+
+ SmartPtr<AeHandler> _ae_handler;
+ SmartPtr<AwbHandler> _awb_handler;
+ SmartPtr<AfHandler> _af_handler;
+ SmartPtr<CommonHandler> _common_handler;
+
+ SmartPtr<AnalyzerThread> _3a_analyzer_thread;
+ AnalyzerCallback *_callback;
+
+};
+
+}
+#endif //XCAM_3A_ANALYZER_H
diff --git a/xcore/x3a_analyzer_aiq.cpp b/xcore/x3a_analyzer_aiq.cpp
new file mode 100644
index 0000000..dd5ae6b
--- /dev/null
+++ b/xcore/x3a_analyzer_aiq.cpp
@@ -0,0 +1,239 @@
+/*
+ * x3a_analyzer_aiq.h - 3a analyzer from AIQ
+ *
+ * Copyright (c) 2014-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 "x3a_analyzer_aiq.h"
+#include "aiq_handler.h"
+#include "isp_controller.h"
+#include "xcam_cpf_reader.h"
+#include "ia_types.h"
+
+namespace XCam {
+
+class CpfReader {
+public:
+ explicit CpfReader (const char *name);
+ ~CpfReader();
+ bool read (ia_binary_data &binary);
+private:
+ XCamCpfBlob *_aiq_cpf;
+ char *_name;
+};
+
+CpfReader::CpfReader (const char *name)
+ : _name (strdup(name))
+{
+ _aiq_cpf = xcam_cpf_blob_new ();
+ XCAM_ASSERT (name);
+}
+CpfReader::~CpfReader()
+{
+ if (_aiq_cpf)
+ xcam_cpf_blob_free (_aiq_cpf);
+ if (_name)
+ xcam_free (_name);
+}
+
+bool CpfReader::read (ia_binary_data &binary)
+{
+ if (!xcam_cpf_read (_name, _aiq_cpf, NULL)) {
+ XCAM_LOG_ERROR ("parse CPF(%s) failed", XCAM_STR (_name));
+ return false;
+ }
+ binary.data = _aiq_cpf->data;
+ binary.size = _aiq_cpf->size;
+ XCAM_LOG_INFO ("read cpf(%s) ok", XCAM_STR (_name));
+ return true;
+}
+
+X3aAnalyzerAiq::X3aAnalyzerAiq (SmartPtr<IspController> &isp, const char *cpf_path)
+ : X3aAnalyzer ("X3aAnalyzerAiq")
+ , _isp (isp)
+ , _cpf_path (NULL)
+{
+ if (cpf_path)
+ _cpf_path = strdup (cpf_path);
+
+ _aiq_compositor = new AiqCompositor ();
+ XCAM_ASSERT (_aiq_compositor.ptr());
+ xcam_mem_clear (&_sensor_mode_data);
+
+ XCAM_LOG_DEBUG ("X3aAnalyzerAiq constructed");
+}
+
+X3aAnalyzerAiq::~X3aAnalyzerAiq()
+{
+ if (_cpf_path)
+ xcam_free (_cpf_path);
+
+ XCAM_LOG_DEBUG ("~X3aAnalyzerAiq destructed");
+}
+
+SmartPtr<AeHandler>
+X3aAnalyzerAiq::create_ae_handler ()
+{
+
+ SmartPtr<AiqAeHandler> ae_handler = new AiqAeHandler (_aiq_compositor);
+ _aiq_compositor->set_ae_handler (ae_handler);
+ return ae_handler;
+}
+
+SmartPtr<AwbHandler>
+X3aAnalyzerAiq::create_awb_handler ()
+{
+ SmartPtr<AiqAwbHandler> awb_handler = new AiqAwbHandler (_aiq_compositor);
+ _aiq_compositor->set_awb_handler (awb_handler);
+ return awb_handler;
+}
+
+SmartPtr<AfHandler>
+X3aAnalyzerAiq::create_af_handler ()
+{
+
+ SmartPtr<AiqAfHandler> af_handler = new AiqAfHandler (_aiq_compositor);
+ _aiq_compositor->set_af_handler (af_handler);
+ return af_handler;
+}
+
+SmartPtr<CommonHandler>
+X3aAnalyzerAiq::create_common_handler ()
+{
+ SmartPtr<AiqCommonHandler> common_handler = new AiqCommonHandler (_aiq_compositor);
+ _aiq_compositor->set_common_handler (common_handler);
+ return common_handler;
+}
+
+XCamReturn
+X3aAnalyzerAiq::internal_init (uint32_t width, uint32_t height)
+{
+ XCAM_ASSERT (_cpf_path);
+ CpfReader reader (_cpf_path);
+ ia_binary_data binary;
+
+ XCAM_ASSERT (_aiq_compositor.ptr());
+
+ xcam_mem_clear (&binary);
+ XCAM_FAIL_RETURN (
+ ERROR,
+ reader.read(binary),
+ XCAM_RETURN_ERROR_AIQ,
+ "read cpf file(%s) failed", _cpf_path);
+
+ _aiq_compositor->set_size (width, height);
+ XCAM_FAIL_RETURN (
+ ERROR,
+ _aiq_compositor->open (binary),
+ XCAM_RETURN_ERROR_AIQ,
+ "AIQ open failed");
+
+ return XCAM_RETURN_NO_ERROR;
+}
+
+XCamReturn
+X3aAnalyzerAiq::internal_deinit ()
+{
+ if (_aiq_compositor.ptr ())
+ _aiq_compositor->close ();
+
+ return XCAM_RETURN_NO_ERROR;
+}
+
+XCamReturn
+X3aAnalyzerAiq::configure_3a ()
+{
+ XCamReturn ret = XCAM_RETURN_NO_ERROR;
+ X3aResultList first_results;
+ struct atomisp_sensor_mode_data sensor_mode_data;
+ xcam_mem_clear (&sensor_mode_data);
+
+ XCAM_ASSERT (_isp.ptr());
+ xcam_mem_clear (&sensor_mode_data);
+
+ ret = _isp->get_sensor_mode_data (sensor_mode_data);
+ XCAM_FAIL_RETURN (WARNING, ret == XCAM_RETURN_NO_ERROR, ret, "get sensor mode data failed");
+
+ if (!_aiq_compositor->set_sensor_mode_data (&sensor_mode_data)) {
+ XCAM_LOG_WARNING ("AIQ configure 3a failed");
+ return XCAM_RETURN_ERROR_AIQ;
+ }
+
+ XCAM_LOG_DEBUG ("X3aAnalyzerAiq got sensor mode data, coarse_time_min:%u, "
+ "coarse_time_max_margin:%u, "
+ "fine_time_min:%u, fine_time_max_margin:%u, "
+ "fine_time_def:%u, "
+ "frame_length_lines:%u, line_length_pck:%u, "
+ "vt_pix_clk_freq_mhz:%u, "
+ "crop_horizontal_start:%u, crop_vertical_start:%u, "
+ "crop_horizontal_end:%u, crop_vertical_end:%u, "
+ "output_width:%u, output_height:%u, "
+ "binning_factor_x:%u, binning_factor_y:%u",
+ sensor_mode_data.coarse_integration_time_min,
+ sensor_mode_data.coarse_integration_time_max_margin,
+ sensor_mode_data.fine_integration_time_min,
+ sensor_mode_data.fine_integration_time_max_margin,
+ sensor_mode_data.fine_integration_time_def,
+ sensor_mode_data.frame_length_lines,
+ sensor_mode_data.line_length_pck,
+ sensor_mode_data.vt_pix_clk_freq_mhz,
+ sensor_mode_data.crop_horizontal_start,
+ sensor_mode_data.crop_vertical_start,
+ sensor_mode_data.crop_horizontal_end,
+ sensor_mode_data.crop_vertical_end,
+ sensor_mode_data.output_width,
+ sensor_mode_data.output_height,
+ (uint32_t)sensor_mode_data.binning_factor_x,
+ (uint32_t)sensor_mode_data.binning_factor_y);
+
+ // initialize ae and awb
+ get_ae_handler ()->analyze (first_results);
+ get_awb_handler ()->analyze (first_results);
+
+ ret = _aiq_compositor->integrate (first_results);
+ XCAM_FAIL_RETURN (WARNING, ret == XCAM_RETURN_NO_ERROR, ret, "AIQ configure_3a failed on integrate results");
+
+ if (!first_results.empty()) {
+ notify_calculation_done (first_results);
+ }
+
+ return XCAM_RETURN_NO_ERROR;
+}
+
+XCamReturn
+X3aAnalyzerAiq::pre_3a_analyze (SmartPtr<X3aIspStatistics> &stats)
+{
+ if (!_aiq_compositor->set_3a_stats (stats)) {
+ XCAM_LOG_WARNING ("Aiq compositor set 3a stats failed");
+ return XCAM_RETURN_ERROR_UNKNOWN;
+ }
+
+ return XCAM_RETURN_NO_ERROR;
+}
+
+XCamReturn
+X3aAnalyzerAiq::post_3a_analyze (X3aResultList &results)
+{
+ XCamReturn ret = XCAM_RETURN_NO_ERROR;
+
+ ret = _aiq_compositor->integrate (results);
+ XCAM_FAIL_RETURN (WARNING, ret == XCAM_RETURN_NO_ERROR, ret, "AIQ integrate 3A results failed");
+
+ return XCAM_RETURN_NO_ERROR;
+}
+
+};
diff --git a/xcore/x3a_analyzer_aiq.h b/xcore/x3a_analyzer_aiq.h
new file mode 100644
index 0000000..5cc1687
--- /dev/null
+++ b/xcore/x3a_analyzer_aiq.h
@@ -0,0 +1,68 @@
+/*
+ * x3a_analyzer_aiq.h - 3a analyzer from AIQ
+ *
+ * Copyright (c) 2014-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>
+ */
+
+#ifndef XCAM_3A_ANALYZER_AIQ_H
+#define XCAM_3A_ANALYZER_AIQ_H
+
+#include "xcam_common.h"
+#include "xcam_defs.h"
+#include "xcam_utils.h"
+#include "x3a_analyzer.h"
+#include <linux/atomisp.h>
+
+namespace XCam {
+
+class AiqCompositor;
+class IspController;
+
+class X3aAnalyzerAiq
+ : public X3aAnalyzer
+{
+public:
+ explicit X3aAnalyzerAiq (SmartPtr<IspController> &isp, const char *cpf_path);
+ ~X3aAnalyzerAiq ();
+
+private:
+
+ XCAM_DEAD_COPY (X3aAnalyzerAiq);
+
+protected:
+ virtual SmartPtr<AeHandler> create_ae_handler ();
+ virtual SmartPtr<AwbHandler> create_awb_handler ();
+ virtual SmartPtr<AfHandler> create_af_handler ();
+ virtual SmartPtr<CommonHandler> create_common_handler ();
+
+ virtual XCamReturn internal_init (uint32_t width, uint32_t height);
+ virtual XCamReturn internal_deinit ();
+
+ virtual XCamReturn configure_3a ();
+ virtual XCamReturn pre_3a_analyze (SmartPtr<X3aIspStatistics> &stats);
+ virtual XCamReturn post_3a_analyze (X3aResultList &results);
+
+private:
+ SmartPtr <AiqCompositor> _aiq_compositor;
+
+ SmartPtr <IspController> _isp;
+ struct atomisp_sensor_mode_data _sensor_mode_data;
+ char *_cpf_path;
+};
+
+};
+#endif //XCAM_3A_ANALYZER_AIQ_H
diff --git a/xcore/x3a_analyzer_manager.cpp b/xcore/x3a_analyzer_manager.cpp
new file mode 100644
index 0000000..5af82f7
--- /dev/null
+++ b/xcore/x3a_analyzer_manager.cpp
@@ -0,0 +1,115 @@
+/*
+ * x3a_analyzer_manager.cpp - analyzer manager
+ *
+ * Copyright (c) 2014-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 "x3a_analyzer_manager.h"
+#include "x3a_analyzer_simple.h"
+#if HAVE_IA_AIQ
+#include "x3a_analyzer_aiq.h"
+#endif
+
+#include <sys/types.h>
+#include <dirent.h>
+
+namespace XCam {
+
+#define XCAM_DEFAULT_3A_LIB_DIR "/usr/lib/xcam"
+
+SmartPtr<X3aAnalyzerManager> X3aAnalyzerManager::_instance(NULL);
+Mutex X3aAnalyzerManager::_mutex;
+
+SmartPtr<X3aAnalyzerManager>
+X3aAnalyzerManager::instance()
+{
+ SmartLock lock(_mutex);
+ if (_instance.ptr())
+ return _instance;
+ _instance = new X3aAnalyzerManager;
+ return _instance;
+}
+
+X3aAnalyzerManager::X3aAnalyzerManager ()
+{
+ XCAM_LOG_DEBUG ("X3aAnalyzerManager construction");
+}
+X3aAnalyzerManager::~X3aAnalyzerManager ()
+{
+ XCAM_LOG_DEBUG ("X3aAnalyzerManager destruction");
+}
+
+SmartPtr<X3aAnalyzer>
+X3aAnalyzerManager::create_analyzer()
+{
+ SmartPtr<X3aAnalyzer> analyzer = find_analyzer();
+ if (!analyzer.ptr())
+ analyzer = new X3aAnalyzerSimple;
+ return analyzer;
+}
+
+#if 0
+/* C interface of 3A lib */
+typedef struct _XCam3ADescription {
+ XCamReturn (*run_awb) (XCamAwbParams *params, uint64_t timestamp);
+ XCamReturn (*run_awb) (XCamAwbParams *params, uint64_t timestamp);
+ XCamReturn (*run_awb) (XCamAwbParams *params, uint64_t timestamp);
+ XCamReturn (*get_combined_result) (XCam3aResultList *results , uint64_t *timestamp);
+} XCam3ADescription;
+#endif
+
+SmartPtr<X3aAnalyzer>
+X3aAnalyzerManager::find_analyzer ()
+{
+ char lib_path[512];
+ const char *dir_path = NULL;
+ DIR *dir_3a = NULL;
+ struct dirent *dirent_3a = NULL;
+ SmartPtr<X3aAnalyzer> analyzer;
+
+ dir_path = getenv ("XCAM_3A_LIB");
+ if (!dir_path) {
+ dir_path = XCAM_DEFAULT_3A_LIB_DIR;
+ }
+ dir_3a = opendir (dir_path);
+ if (dir_3a) {
+ while ((dirent_3a = readdir (dir_3a)) != NULL) {
+ if (dirent_3a->d_type != DT_LNK &&
+ dirent_3a->d_type != DT_REG)
+ continue;
+ snprintf (lib_path, sizeof(lib_path), "%s/%s", dir_path, dirent_3a->d_name);
+ analyzer = load_analyzer_from_binary (lib_path);
+ if (analyzer.ptr())
+ break;
+ }
+ }
+ if (dir_3a)
+ closedir (dir_3a);
+ return analyzer;
+}
+
+SmartPtr<X3aAnalyzer>
+X3aAnalyzerManager::load_analyzer_from_binary (const char *path)
+{
+ SmartPtr<X3aAnalyzer> loaded_analyzer;
+ // TODO
+ return loaded_analyzer;
+}
+
+};
+
diff --git a/xcore/x3a_analyzer_manager.h b/xcore/x3a_analyzer_manager.h
new file mode 100644
index 0000000..2fb99f1
--- /dev/null
+++ b/xcore/x3a_analyzer_manager.h
@@ -0,0 +1,51 @@
+/*
+ * x3a_analyzer_manager.h - analyzer manager
+ *
+ * Copyright (c) 2014-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>
+ */
+
+#ifndef XCAM_3A_ANALYZER_MANAGER_H
+#define XCAM_3A_ANALYZER_MANAGER_H
+
+#include "x3a_analyzer.h"
+
+namespace XCam {
+
+class X3aAnalyzerManager
+{
+protected:
+ explicit X3aAnalyzerManager ();
+public:
+ virtual ~X3aAnalyzerManager ();
+
+ static SmartPtr<X3aAnalyzerManager> instance();
+
+ virtual SmartPtr<X3aAnalyzer> create_analyzer();
+
+private:
+ SmartPtr<X3aAnalyzer> find_analyzer ();
+ SmartPtr<X3aAnalyzer> load_analyzer_from_binary (const char *path);
+
+private:
+ XCAM_DEAD_COPY (X3aAnalyzerManager);
+
+private:
+ static SmartPtr<X3aAnalyzerManager> _instance;
+ static Mutex _mutex;
+};
+};
+#endif //XCAM_3A_ANALYZER_MANAGER_H
diff --git a/xcore/x3a_analyzer_simple.cpp b/xcore/x3a_analyzer_simple.cpp
new file mode 100644
index 0000000..17c4905
--- /dev/null
+++ b/xcore/x3a_analyzer_simple.cpp
@@ -0,0 +1,272 @@
+/*
+ * 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 <feng.yuan@intel.com>
+ */
+
+#include "x3a_analyzer_simple.h"
+#include "x3a_statistics_queue.h"
+#include <linux/atomisp.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)
+{
+}
+
+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;
+ return XCAM_RETURN_NO_ERROR;
+}
+
+XCamReturn
+X3aAnalyzerSimple::pre_3a_analyze (SmartPtr<X3aIspStatistics> &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 struct atomisp_3a_statistics *stats = _current_stats->get_3a_stats ();
+ uint32_t cell_count = stats->grid_info.bqs_per_grid_cell * stats->grid_info.bqs_per_grid_cell;
+ uint32_t bits_depth = stats->grid_info.elem_bit_depth;
+ 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);
+
+ // calculate avg r, gr, gb, b
+ for (uint32_t i = 0; i < stats->grid_info.height; ++i)
+ for (uint32_t j = 0; j < stats->grid_info.width; ++j) {
+ sum_r += ((double)(stats->data[i * stats->grid_info.width + j].awb_r)) / cell_count;
+ sum_gr += ((double)(stats->data[i * stats->grid_info.width + j].awb_gr)) / cell_count;
+ sum_gb += ((double)(stats->data[i * stats->grid_info.width + j].awb_gb)) / cell_count;
+ sum_b += ((double)(stats->data[i * stats->grid_info.width + j].awb_b)) / cell_count;
+ }
+
+ avg_r = sum_r / (stats->grid_info.width * stats->grid_info.height);
+ avg_gr = sum_gr / (stats->grid_info.width * stats->grid_info.height);
+ avg_gb = sum_gb / (stats->grid_info.width * stats->grid_info.height);
+ avg_b = sum_b / (stats->grid_info.width * stats->grid_info.height);
+ avg_r = avg_r / (1 << (bits_depth - 8));
+ avg_gr = avg_gr / (1 << (bits_depth - 8));
+ avg_gb = avg_gb / (1 << (bits_depth - 8));
+ avg_b = avg_b / (1 << (bits_depth - 8));
+ 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 = 150;
+
+ const struct atomisp_3a_statistics *stats = _current_stats->get_3a_stats ();
+ uint32_t cell_count = stats->grid_info.bqs_per_grid_cell * stats->grid_info.bqs_per_grid_cell;
+ uint32_t bits_depth = stats->grid_info.elem_bit_depth;
+ 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;
+ }
+
+ for (uint32_t i = 0; i < stats->grid_info.height; ++i)
+ for (uint32_t j = 0; j < stats->grid_info.width; ++j) {
+ sum_y += ((double)(stats->data[i * stats->grid_info.width + j].ae_y)) / cell_count;
+ }
+ sum_y /= (stats->grid_info.width * stats->grid_info.height);
+ sum_y /= (1 << (bits_depth - 8)); // make it in 8 bits
+ 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) {
+ 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);
+
+ return XCAM_RETURN_NO_ERROR;
+}
+
+XCamReturn X3aAnalyzerSimple::analyze_af (X3aResultList &output)
+{
+ XCAM_UNUSED (output);
+ return XCAM_RETURN_NO_ERROR;
+}
+
+};
diff --git a/xcore/x3a_analyzer_simple.h b/xcore/x3a_analyzer_simple.h
new file mode 100644
index 0000000..91fd7bb
--- /dev/null
+++ b/xcore/x3a_analyzer_simple.h
@@ -0,0 +1,75 @@
+/*
+ * x3a_analyzer_simple.h - 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 <feng.yuan@intel.com>
+ */
+
+#ifndef XCAM_3A_ANALYZER_SIMPLE_H
+#define XCAM_3A_ANALYZER_SIMPLE_H
+
+#include "xcam_common.h"
+#include "xcam_defs.h"
+#include "xcam_utils.h"
+#include "x3a_analyzer.h"
+#include <linux/atomisp.h>
+
+namespace XCam {
+
+class X3aAnalyzerSimple
+ : public X3aAnalyzer
+{
+public:
+ explicit X3aAnalyzerSimple ();
+ ~X3aAnalyzerSimple ();
+
+private:
+
+ XCAM_DEAD_COPY (X3aAnalyzerSimple);
+
+protected:
+ virtual SmartPtr<AeHandler> create_ae_handler ();
+ virtual SmartPtr<AwbHandler> create_awb_handler ();
+ virtual SmartPtr<AfHandler> create_af_handler ();
+ virtual SmartPtr<CommonHandler> create_common_handler ();
+
+ virtual XCamReturn internal_init (uint32_t width, uint32_t height) {
+ XCAM_UNUSED (width);
+ XCAM_UNUSED (height);
+ return XCAM_RETURN_NO_ERROR;
+ }
+ virtual XCamReturn internal_deinit () {
+ _is_ae_started = false;
+ return XCAM_RETURN_NO_ERROR;
+ }
+ virtual XCamReturn configure_3a ();
+ virtual XCamReturn pre_3a_analyze (SmartPtr<X3aIspStatistics> &stats);
+ virtual XCamReturn post_3a_analyze (X3aResultList &results);
+
+public:
+ XCamReturn analyze_ae (X3aResultList &output);
+ XCamReturn analyze_awb (X3aResultList &output);
+ XCamReturn analyze_af (X3aResultList &output);
+
+private:
+ SmartPtr<X3aIspStatistics> _current_stats;
+ double _last_target_exposure;
+ bool _is_ae_started;
+};
+
+};
+#endif //XCAM_3A_ANALYZER_SIMPLE_H
+
diff --git a/xcore/x3a_event.h b/xcore/x3a_event.h
new file mode 100644
index 0000000..f8c7e03
--- /dev/null
+++ b/xcore/x3a_event.h
@@ -0,0 +1,64 @@
+/*
+ * x3a_event.h - event
+ *
+ * Copyright (c) 2014 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>
+ */
+
+#ifndef XCAM_3A_EVENT_H
+#define XCAM_3A_EVENT_H
+
+#include "xcam_defs.h"
+#include "xcam_common.h"
+
+namespace XCam {
+
+class X3aEvent
+ //:public ObjectLife
+{
+public:
+ enum Type {
+ TYPE_ISP_STATISTICS,
+ TYPE_ISP_FRAME_SYNC,
+ };
+
+protected:
+ explicit X3aEvent (X3aEvent::Type type, uint64_t timestamp)
+ : _timestamp (timestamp)
+ , _type (type)
+ {}
+ virtual ~X3aEvent() {}
+
+public:
+ uint64_t get_timestamp () const {
+ return _timestamp;
+ }
+ Type get_type () const {
+ return _type;
+ }
+
+private:
+ XCAM_DEAD_COPY (X3aEvent);
+
+protected:
+ uint64_t _timestamp;
+ X3aEvent::Type _type;
+};
+
+};
+
+#endif //XCAM_3A_EVENT_H
+
diff --git a/xcore/x3a_image_process_center.cpp b/xcore/x3a_image_process_center.cpp
new file mode 100644
index 0000000..0d6c681
--- /dev/null
+++ b/xcore/x3a_image_process_center.cpp
@@ -0,0 +1,236 @@
+/*
+ * x3a_image_process_center.cpp - 3a process center
+ *
+ * Copyright (c) 2014-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 "x3a_image_process_center.h"
+
+namespace XCam {
+
+X3aImageProcessCenter::X3aImageProcessCenter()
+ : _callback (NULL)
+{
+ XCAM_LOG_DEBUG ("X3aImageProcessCenter construction");
+}
+
+X3aImageProcessCenter::~X3aImageProcessCenter()
+{
+ stop ();
+ XCAM_LOG_DEBUG ("~X3aImageProcessCenter destruction");
+}
+
+bool
+X3aImageProcessCenter::set_image_callback (ImageProcessCallback *callback)
+{
+ XCAM_ASSERT (!_callback);
+ _callback = callback;
+ return true;
+}
+
+bool
+X3aImageProcessCenter::insert_processor (SmartPtr<ImageProcessor> &processor)
+{
+ _image_processors.push_back (processor);
+ XCAM_LOG_INFO ("Add processor(%s) into image processor center", XCAM_STR (processor->get_name()));
+ return true;
+}
+
+bool
+X3aImageProcessCenter::has_processors ()
+{
+ return !_image_processors.empty();
+}
+
+XCamReturn
+X3aImageProcessCenter::start ()
+{
+ XCamReturn ret = XCAM_RETURN_NO_ERROR;
+
+ if (_image_processors.empty()) {
+ XCAM_LOG_ERROR ("process center start failed, no processor found");
+ return XCAM_RETURN_ERROR_PARAM;
+ }
+
+ for (ImageProcessorList::iterator i_pro = _image_processors.begin ();
+ i_pro != _image_processors.end(); ++i_pro)
+ {
+ SmartPtr<ImageProcessor> &processor = *i_pro;
+ XCAM_ASSERT (processor.ptr());
+ processor->set_callback (this);
+ ret = processor->start ();
+ if (ret != XCAM_RETURN_NO_ERROR) {
+ XCAM_LOG_ERROR ("processor(%s) start failed", XCAM_STR(processor->get_name()));
+ break;
+ }
+ }
+
+ if (ret != XCAM_RETURN_NO_ERROR)
+ stop();
+ else {
+ XCAM_LOG_INFO ("3a process center started");
+ }
+
+ return ret;
+}
+
+XCamReturn
+X3aImageProcessCenter::stop ()
+{
+ for (ImageProcessorList::iterator i_pro = _image_processors.begin ();
+ i_pro != _image_processors.end(); ++i_pro)
+ {
+ SmartPtr<ImageProcessor> &processor = *i_pro;
+ XCAM_ASSERT (processor.ptr());
+ processor->stop ();
+ }
+
+ XCAM_LOG_INFO ("3a process center stopped");
+
+ _image_processors.clear();
+ return XCAM_RETURN_NO_ERROR;
+}
+
+bool
+X3aImageProcessCenter::put_buffer (SmartPtr<VideoBuffer> &buf)
+{
+ XCAM_ASSERT (!_image_processors.empty());
+ if (_image_processors.empty())
+ return false;
+
+ ImageProcessorList::iterator i_pro = _image_processors.begin ();
+ SmartPtr<ImageProcessor> &processor = *i_pro;
+ if (processor->push_buffer (buf) != XCAM_RETURN_NO_ERROR)
+ return false;
+ return true;
+}
+
+
+XCamReturn
+X3aImageProcessCenter::put_3a_results (X3aResultList &results)
+{
+ XCamReturn ret = XCAM_RETURN_NO_ERROR;
+
+ XCAM_FAIL_RETURN (ERROR, !results.empty(), XCAM_RETURN_ERROR_PARAM, "results empty");
+
+ for (ImageProcessorIter i_pro = _image_processors.begin();
+ i_pro != _image_processors.end(); i_pro++) {
+ SmartPtr<ImageProcessor> &processor = *i_pro;
+ XCAM_ASSERT (processor.ptr());
+ ret = processor->push_3a_results (results);
+ if (ret != XCAM_RETURN_NO_ERROR && ret != XCAM_RETURN_BYPASS) {
+ XCAM_LOG_WARNING ("processor(%s) gailed on results", XCAM_STR(processor->get_name()));
+ break;
+ }
+ if (results.empty ()) {
+ XCAM_LOG_DEBUG ("results done");
+ return XCAM_RETURN_NO_ERROR;
+ }
+ }
+
+ if (!results.empty()) {
+ XCAM_LOG_DEBUG ("process center: results left without being processed");
+ return XCAM_RETURN_BYPASS;
+ }
+
+ return XCAM_RETURN_NO_ERROR;
+}
+
+XCamReturn
+X3aImageProcessCenter::put_3a_result (SmartPtr<X3aResult> &result)
+{
+ XCamReturn ret = XCAM_RETURN_NO_ERROR;
+
+ XCAM_FAIL_RETURN (ERROR, !result.ptr(), XCAM_RETURN_ERROR_PARAM, "result empty");
+
+ for (ImageProcessorIter i_pro = _image_processors.begin();
+ i_pro != _image_processors.end(); i_pro++)
+ {
+ SmartPtr<ImageProcessor> &processor = *i_pro;
+ XCAM_ASSERT (processor.ptr());
+ ret = processor->push_3a_result (result);
+
+ if (ret == XCAM_RETURN_BYPASS)
+ continue;
+
+ if (ret == XCAM_RETURN_NO_ERROR)
+ return XCAM_RETURN_NO_ERROR;
+
+ XCAM_LOG_WARNING ("processor(%s) failed on result", XCAM_STR(processor->get_name()));
+ return ret;
+ }
+
+ if (ret == XCAM_RETURN_BYPASS) {
+ XCAM_LOG_WARNING ("processor center: no processor can handle result()");
+ }
+
+ return ret;
+}
+
+void
+X3aImageProcessCenter::process_buffer_done (ImageProcessor *processor, SmartPtr<VideoBuffer> &buf)
+{
+ ImageProcessorIter i_pro = _image_processors.begin();
+ for (; i_pro != _image_processors.end(); ++i_pro)
+ {
+ SmartPtr<ImageProcessor> &cur_pro = *i_pro;
+ XCAM_ASSERT (cur_pro.ptr());
+ if (cur_pro.ptr() == processor)
+ break;
+ }
+
+ XCAM_ASSERT (i_pro != _image_processors.end());
+ if (i_pro == _image_processors.end()) {
+ XCAM_LOG_ERROR ("processor doesn't found from list of image center");
+ return;
+ }
+
+ if (++i_pro != _image_processors.end()) {
+ SmartPtr<ImageProcessor> &next_processor = *i_pro;
+ XCAM_ASSERT (next_processor.ptr());
+ XCamReturn ret = next_processor->push_buffer (buf);
+ if (ret != XCAM_RETURN_NO_ERROR) {
+ XCAM_LOG_ERROR ("processor(%s) failed in push_buffer", next_processor->get_name());
+ }
+ return;
+ }
+
+ //all processor done
+ if (_callback)
+ _callback->process_buffer_done (processor, buf);
+ else
+ ImageProcessCallback::process_buffer_done (processor, buf);
+}
+
+void
+X3aImageProcessCenter::process_buffer_failed (ImageProcessor *processor, SmartPtr<VideoBuffer> &buf)
+{
+ if (_callback)
+ _callback->process_buffer_failed(processor, buf);
+ else
+ ImageProcessCallback::process_buffer_failed (processor, buf);
+}
+
+void
+X3aImageProcessCenter::process_image_result_done (ImageProcessor *processor, SmartPtr<X3aResult> &result)
+{
+ if (_callback)
+ _callback->process_image_result_done(processor, result);
+ else
+ ImageProcessCallback::process_image_result_done (processor, result);
+}
+
+};
diff --git a/xcore/x3a_image_process_center.h b/xcore/x3a_image_process_center.h
new file mode 100644
index 0000000..7e4516f
--- /dev/null
+++ b/xcore/x3a_image_process_center.h
@@ -0,0 +1,66 @@
+/*
+ * x3a_image_process_center.h - 3a process center
+ *
+ * Copyright (c) 2014-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>
+ */
+
+#ifndef XCAM_3A_IMAGE_PROCESS_CENTER_H
+#define XCAM_3A_IMAGE_PROCESS_CENTER_H
+
+#include "xcam_common.h"
+#include "xcam_defs.h"
+#include "xcam_utils.h"
+#include "image_processor.h"
+
+namespace XCam {
+
+class X3aImageProcessCenter
+ : public ImageProcessCallback
+{
+ typedef std::list<SmartPtr<ImageProcessor> > ImageProcessorList;
+ typedef std::list<SmartPtr<ImageProcessor> >::iterator ImageProcessorIter;
+public:
+ explicit X3aImageProcessCenter();
+ ~X3aImageProcessCenter();
+
+ bool insert_processor (SmartPtr<ImageProcessor> &processor);
+ bool has_processors ();
+ bool set_image_callback (ImageProcessCallback *callback);
+
+ XCamReturn start ();
+ XCamReturn stop ();
+
+ bool put_buffer (SmartPtr<VideoBuffer> &buf);
+
+ XCamReturn put_3a_results (X3aResultList &results);
+ XCamReturn put_3a_result (SmartPtr<X3aResult> &result);
+
+ //derived from ImageProcessCallback
+ virtual void process_buffer_done (ImageProcessor *processor, SmartPtr<VideoBuffer> &buf);
+ virtual void process_buffer_failed (ImageProcessor *processor, SmartPtr<VideoBuffer> &buf);
+ virtual void process_image_result_done (ImageProcessor *processor, SmartPtr<X3aResult> &result);
+
+private:
+ XCAM_DEAD_COPY (X3aImageProcessCenter);
+
+private:
+ ImageProcessorList _image_processors;
+ ImageProcessCallback *_callback;
+};
+
+};
+#endif //XCAM_3A_IMAGE_PROCESS_CENTER_H
diff --git a/xcore/x3a_isp_config.cpp b/xcore/x3a_isp_config.cpp
new file mode 100644
index 0000000..224d836
--- /dev/null
+++ b/xcore/x3a_isp_config.cpp
@@ -0,0 +1,283 @@
+/*
+ * x3a_isp_config.h - 3A ISP config
+ *
+ * Copyright (c) 2014-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 "x3a_isp_config.h"
+#include "isp_config_translator.h"
+
+namespace XCam {
+
+void AtomIspConfigContent::clear ()
+{
+ xcam_mem_clear (this);
+}
+
+void
+AtomIspConfigContent::copy (const struct atomisp_parameters &config)
+{
+ xcam_mem_clear (&isp_config);
+ if (config.wb_config) {
+ wb = *config.wb_config;
+ isp_config.wb_config = &wb;
+ }
+ if (config.cc_config) {
+ cc = *config.cc_config;
+ isp_config.cc_config = &cc;
+ }
+ if (config.tnr_config) {
+ tnr = *config.tnr_config;
+ isp_config.tnr_config = &tnr;
+ }
+ if (config.ecd_config) {
+ ecd_config = *config.ecd_config;
+ isp_config.ecd_config = &ecd_config;
+ }
+ if (config.ynr_config) {
+ ynr = *config.ynr_config;
+ isp_config.ynr_config = &ynr;
+ }
+ if (config.fc_config) {
+ fc_config = *config.fc_config;
+ isp_config.fc_config = &fc_config;
+ }
+ if (config.cnr_config) {
+ cnr = *config.cnr_config;
+ isp_config.cnr_config = &cnr;
+ }
+ if (config.macc_config) {
+ macc_config = *config.macc_config;
+ isp_config.macc_config = &macc_config;
+ }
+ if (config.ctc_config) {
+ ctc_config = *config.ctc_config;
+ isp_config.ctc_config = &ctc_config;
+ }
+ if (config.formats_config) {
+ formats = *config.formats_config;
+ isp_config.formats_config = &formats;
+ }
+ if (config.aa_config) {
+ aa = *config.aa_config;
+ isp_config.aa_config = &aa;
+ }
+ if (config.baa_config) {
+ baa = *config.baa_config;
+ isp_config.baa_config = &baa;
+ }
+ if (config.ce_config) {
+ ce = *config.ce_config;
+ isp_config.ce_config = &ce;
+ }
+ if (config.dvs_6axis_config) {
+ dvs_6axis = *config.dvs_6axis_config;
+ isp_config.dvs_6axis_config = &dvs_6axis;
+ }
+ if (config.ob_config) {
+ ob = *config.ob_config;
+ isp_config.ob_config = &ob;
+ }
+ if (config.nr_config) {
+ nr = *config.nr_config;
+ isp_config.nr_config = &nr;
+ }
+ if (config.dp_config) {
+ dp = *config.dp_config;
+ isp_config.dp_config = &dp;
+ }
+ if (config.ee_config) {
+ ee = *config.ee_config;
+ isp_config.ee_config = ⅇ
+ }
+ if (config.de_config) {
+ de = *config.de_config;
+ isp_config.de_config = &de;
+ }
+ if (config.ctc_table) {
+ ctc_table = *config.ctc_table;
+ isp_config.ctc_table = &ctc_table;
+ }
+ if (config.gc_config) {
+ gc_config = *config.gc_config;
+ isp_config.gc_config = &gc_config;
+ }
+ if (config.anr_config) {
+ anr = *config.anr_config;
+ isp_config.anr_config = &anr;
+ }
+ if (config.a3a_config) {
+ a3a = *config.a3a_config;
+ isp_config.a3a_config = &a3a;
+ }
+ if (config.xnr_config) {
+ xnr = *config.xnr_config;
+ isp_config.xnr_config = &xnr;
+ }
+ if (config.dz_config) {
+ dz_config = *config.dz_config;
+ isp_config.dz_config = &dz_config;
+ }
+ if (config.yuv2rgb_cc_config) {
+ yuv2rgb_cc = *config.yuv2rgb_cc_config;
+ isp_config.yuv2rgb_cc_config = &yuv2rgb_cc;
+ }
+ if (config.rgb2yuv_cc_config) {
+ rgb2yuv_cc = *config.rgb2yuv_cc_config;
+ isp_config.rgb2yuv_cc_config = &rgb2yuv_cc;
+ }
+ if (config.macc_table) {
+ macc_table = *config.macc_table;
+ isp_config.macc_table = &macc_table;
+ }
+ if (config.gamma_table) {
+ gamma_table = *config.gamma_table;
+ isp_config.gamma_table = &gamma_table;
+ }
+ if (config.r_gamma_table) {
+ r_gamma_table = *config.r_gamma_table;
+ isp_config.r_gamma_table = &r_gamma_table;
+ }
+ if (config.g_gamma_table) {
+ g_gamma_table = *config.g_gamma_table;
+ isp_config.g_gamma_table = &g_gamma_table;
+ }
+ if (config.b_gamma_table) {
+ b_gamma_table = *config.b_gamma_table;
+ isp_config.b_gamma_table = &b_gamma_table;
+ }
+ if (config.shading_table) {
+ shading_table = *config.shading_table;
+ isp_config.shading_table = &shading_table;
+ }
+ if (config.morph_table) {
+ morph_table = *config.morph_table;
+ isp_config.morph_table = &morph_table;
+ }
+ if (config.xnr_table) {
+ xnr_table = *config.xnr_table;
+ isp_config.xnr_table = &xnr_table;
+ }
+ if (config.anr_thres) {
+ anr_thres = *config.anr_thres;
+ isp_config.anr_thres = &anr_thres;
+ }
+ if (config.motion_vector) {
+ motion_vector = *config.motion_vector;
+ isp_config.motion_vector = &motion_vector;
+ }
+}
+
+X3aIspConfig::X3aIspConfig ()
+{
+}
+
+X3aIspConfig::~X3aIspConfig()
+{
+ clear ();
+}
+
+
+bool X3aIspConfig::clear()
+{
+ _isp_content.clear ();
+ _3a_results.clear ();
+ return true;
+}
+
+bool
+X3aIspConfig::attach (SmartPtr<X3aResult> &result, IspConfigTranslator *translator)
+{
+ uint32_t type = result->get_type ();
+
+ XCAM_ASSERT (translator);
+
+ if (!result.ptr() || !result->get_ptr ()) {
+ XCAM_LOG_ERROR ("3A result empty");
+ return false;
+ }
+ switch (type) {
+ case X3aIspConfig::IspAllParameters: {
+ X3aAtomIspParametersResult *isp_3a =
+ dynamic_cast<X3aAtomIspParametersResult*>(result.ptr());
+ XCAM_ASSERT (isp_3a);
+ _isp_content.copy (isp_3a->get_isp_config());
+ }
+ break;
+
+ case XCAM_3A_RESULT_WHITE_BALANCE: {
+ struct atomisp_wb_config wb;
+ X3aWhiteBalanceResult *wb_res =
+ dynamic_cast<X3aWhiteBalanceResult*>(result.ptr());
+ XCAM_ASSERT (wb_res);
+ xcam_mem_clear (&wb);
+ if (translator->translate_white_balance (wb_res->get_standard_result(), wb)
+ != XCAM_RETURN_NO_ERROR) {
+ XCAM_LOG_WARNING ("translate white balance failed");
+ return false;
+ }
+ _isp_content.wb = wb;
+ _isp_content.isp_config.wb_config = &_isp_content.wb;
+ }
+ break;
+ case XCAM_3A_RESULT_BLACK_LEVEL: {
+ struct atomisp_ob_config ob;
+ X3aBlackLevelResult *bl_res =
+ dynamic_cast<X3aBlackLevelResult*>(result.ptr());
+ XCAM_ASSERT (bl_res);
+ xcam_mem_clear (&ob);
+ if (translator->translate_black_level (bl_res->get_standard_result(), ob)
+ != XCAM_RETURN_NO_ERROR) {
+ XCAM_LOG_WARNING ("translate black level failed");
+ return false;
+ }
+ _isp_content.ob = ob;
+ _isp_content.isp_config.ob_config = &_isp_content.ob;
+ }
+ break;
+ case XCAM_3A_RESULT_YUV2RGB_MATRIX:
+ case XCAM_3A_RESULT_RGB2YUV_MATRIX:
+ {
+ struct atomisp_cc_config cc;
+ X3aColorMatrixResult *cc_res =
+ dynamic_cast<X3aColorMatrixResult*>(result.ptr());
+ XCAM_ASSERT (cc_res);
+ xcam_mem_clear (&cc);
+ if (translator->translate_color_matrix (cc_res->get_standard_result(), cc)
+ != XCAM_RETURN_NO_ERROR) {
+ XCAM_LOG_WARNING ("translate color matrix failed");
+ return false;
+ }
+ if (type == XCAM_3A_RESULT_YUV2RGB_MATRIX) {
+ _isp_content.yuv2rgb_cc = cc;
+ _isp_content.isp_config.yuv2rgb_cc_config = &_isp_content.yuv2rgb_cc;
+ } else {
+ _isp_content.rgb2yuv_cc = cc;
+ _isp_content.isp_config.rgb2yuv_cc_config = &_isp_content.rgb2yuv_cc;
+ }
+ }
+ break;
+ default:
+ return false;
+ }
+
+ _3a_results.push_back (result);
+ return true;
+}
+
+};
+
diff --git a/xcore/x3a_isp_config.h b/xcore/x3a_isp_config.h
new file mode 100644
index 0000000..f54072b
--- /dev/null
+++ b/xcore/x3a_isp_config.h
@@ -0,0 +1,191 @@
+/*
+ * x3a_isp_config.h - 3A ISP config
+ *
+ * Copyright (c) 2014-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>
+ */
+
+#ifndef XCAM_3A_ISP_CONFIG_H
+#define XCAM_3A_ISP_CONFIG_H
+
+#include "xcam_defs.h"
+#include "xcam_common.h"
+#include "xcam_utils.h"
+#include "xcam_3a_result.h"
+#include "x3a_result.h"
+#include <linux/atomisp.h>
+
+namespace XCam {
+
+#define XCAM_3A_ISP_RESULT_TYPE_START (XCAM_3A_RESULT_USER_DEFINED_TYPE + 0x1000)
+
+struct AtomIspConfigContent {
+ struct atomisp_parameters isp_config;
+ //content
+ struct atomisp_wb_config wb;
+ struct atomisp_ob_config ob; //black level
+ struct atomisp_cc_config cc;
+ struct atomisp_cc_config yuv2rgb_cc;
+ struct atomisp_cc_config rgb2yuv_cc;
+ struct atomisp_nr_config nr;
+ struct atomisp_tnr_config tnr;
+ struct atomisp_ynr_config ynr;
+ struct atomisp_cnr_config cnr;
+ struct atomisp_anr_config anr;
+ struct atomisp_xnr_config xnr;
+ struct atomisp_xnr_table xnr_table;
+ struct atomisp_ee_config ee;
+ struct atomisp_dp_config dp;
+ struct atomisp_de_config de;
+ struct atomisp_ecd_config ecd_config;
+ struct atomisp_fc_config fc_config;
+ struct atomisp_ctc_config ctc_config;
+ struct atomisp_ctc_table ctc_table;
+ struct atomisp_macc_config macc_config;
+ struct atomisp_macc_table macc_table;
+ struct atomisp_gamma_table gamma_table;
+ struct atomisp_rgb_gamma_table r_gamma_table;
+ struct atomisp_rgb_gamma_table g_gamma_table;
+ struct atomisp_rgb_gamma_table b_gamma_table;
+ struct atomisp_gc_config gc_config;
+ struct atomisp_shading_table shading_table;
+ struct atomisp_3a_config a3a;
+
+ struct atomisp_dvs_6axis_config dvs_6axis;
+
+
+ struct atomisp_formats_config formats;
+ struct atomisp_aa_config aa;
+ struct atomisp_aa_config baa;
+ struct atomisp_ce_config ce;
+ struct atomisp_morph_table morph_table;
+ struct atomisp_anr_thres anr_thres;
+
+ struct atomisp_dz_config dz_config;
+ struct atomisp_vector motion_vector;
+
+ void clear ();
+ void copy (const struct atomisp_parameters &config);
+
+ AtomIspConfigContent () {
+ clear ();
+ }
+};
+
+class IspConfigTranslator;
+
+class X3aIspConfig
+{
+public:
+ enum X3aIspConfigType {
+ IspAllParameters = XCAM_3A_ISP_RESULT_TYPE_START,
+ IspExposureParameters,
+ };
+
+ struct X3aIspResultDummy {
+ XCam3aResultHead head;
+ };
+public:
+ explicit X3aIspConfig ();
+ virtual ~X3aIspConfig();
+
+public:
+ const struct atomisp_parameters &get_isp_configs () const {
+ return _isp_content.isp_config;
+ }
+ struct atomisp_parameters &get_isp_configs () {
+ return _isp_content.isp_config;
+ }
+ bool clear ();
+ bool attach (SmartPtr<X3aResult> &result, IspConfigTranslator *translator);
+
+private:
+ XCAM_DEAD_COPY (X3aIspConfig);
+
+protected:
+ AtomIspConfigContent _isp_content;
+ std::list< SmartPtr<X3aResult> > _3a_results;
+};
+
+template <typename IspConfig, typename StandardResult, uint32_t type>
+class X3aIspResultT
+ : public X3aStandardResultT<StandardResult>
+{
+public:
+ X3aIspResultT (
+ XCamImageProcessType process_type = XCAM_IMAGE_PROCESS_ALWAYS
+ )
+ : X3aStandardResultT<StandardResult> (type, process_type)
+ {
+ X3aResult::set_ptr((void*)&_isp_config);
+ }
+
+ ~X3aIspResultT () {}
+
+ // set config
+ void set_isp_config (IspConfig &config) {
+ _isp_config = config;
+ }
+ const IspConfig &get_isp_config () const {
+ return _isp_config;
+ }
+
+private:
+ IspConfig _isp_config;
+};
+
+
+/* special X3aAtomIspParametersResult type */
+template <>
+class X3aIspResultT<struct atomisp_parameters, X3aIspConfig::X3aIspResultDummy, X3aIspConfig::IspAllParameters>
+ : public X3aStandardResultT<X3aIspConfig::X3aIspResultDummy>
+ {
+public:
+ X3aIspResultT (
+ XCamImageProcessType process_type = XCAM_IMAGE_PROCESS_ALWAYS)
+ : X3aStandardResultT<X3aIspConfig::X3aIspResultDummy> ((uint32_t)X3aIspConfig::IspAllParameters, process_type)
+ {
+ X3aResult::set_ptr((void*)&_content.isp_config);
+ }
+
+ ~X3aIspResultT () {}
+
+ // get config
+ struct atomisp_parameters &get_isp_config () {
+ return _content.isp_config;
+ }
+ const struct atomisp_parameters &get_isp_config () const {
+ return _content.isp_config;
+ }
+
+ // set config
+ void set_isp_config (struct atomisp_parameters &config) {
+ _content.copy (config);
+ }
+
+private:
+ AtomIspConfigContent _content;
+ };
+
+typedef
+X3aIspResultT<struct atomisp_parameters, X3aIspConfig::X3aIspResultDummy, X3aIspConfig::IspAllParameters> X3aAtomIspParametersResult;
+typedef
+X3aIspResultT<struct atomisp_exposure, XCam3aResultExposure, X3aIspConfig::IspExposureParameters> X3aIspExposureResult;
+
+};
+
+#endif //XCAM_3A_ISP_CONFIG_H
+
diff --git a/xcore/x3a_result.cpp b/xcore/x3a_result.cpp
new file mode 100644
index 0000000..bea897f
--- /dev/null
+++ b/xcore/x3a_result.cpp
@@ -0,0 +1,25 @@
+/*
+ * x3a_result.cpp - 3A calculation result
+ *
+ * Copyright (c) 2014 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 "x3a_result.h"
+
+namespace XCam {
+
+};
diff --git a/xcore/x3a_result.h b/xcore/x3a_result.h
new file mode 100644
index 0000000..5ac5bc6
--- /dev/null
+++ b/xcore/x3a_result.h
@@ -0,0 +1,144 @@
+/*
+ * x3a_result.h - 3A calculation result
+ *
+ * Copyright (c) 2014-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>
+ */
+
+#ifndef XCAM_3A_RESULT_H
+#define XCAM_3A_RESULT_H
+
+#include "xcam_common.h"
+#include "xcam_utils.h"
+#include "smartptr.h"
+#include "xcam_3a_result.h"
+#include <list>
+
+namespace XCam {
+
+class X3aResult
+{
+protected:
+ explicit X3aResult (
+ uint32_t type,
+ XCamImageProcessType process_type = XCAM_IMAGE_PROCESS_ALWAYS,
+ uint64_t timestamp = XCam::InvalidTimestamp
+ )
+ : _type (type)
+ , _process_type (process_type)
+ , _timestamp (timestamp)
+ , _ptr (NULL)
+ , _processed (false)
+ {}
+
+public:
+ virtual ~X3aResult() {}
+
+ void *get_ptr () const {
+ return _ptr;
+ }
+ bool is_done() const {
+ return _processed;
+ }
+ void set_done (bool flag) {
+ _processed = flag;
+ }
+ uint64_t get_timestamp () const {
+ return _timestamp;
+ }
+ uint32_t get_type () const {
+ return _type;
+ }
+
+ void set_process_type (XCamImageProcessType process) {
+ _process_type = process;
+ }
+ XCamImageProcessType get_process_type () const {
+ return _process_type;
+ }
+
+protected:
+ void set_ptr (void *ptr) {
+ _ptr = ptr;
+ }
+
+ //virtual bool to_isp_config (SmartPtr<X3aIspConfig> &config) = 0;
+
+private:
+ XCAM_DEAD_COPY (X3aResult);
+
+protected:
+ //XCam3aResultType _type;
+ uint32_t _type; // XCam3aResultType
+ XCamImageProcessType _process_type;
+ uint64_t _timestamp;
+ void *_ptr;
+ bool _processed;
+};
+
+typedef std::list<SmartPtr<X3aResult>> X3aResultList;
+
+/* !
+ * \template StandardResult must inherited from XCam3aResultHead
+ */
+template <typename StandardResult>
+class X3aStandardResultT
+ : public X3aResult
+{
+public:
+ explicit X3aStandardResultT (uint32_t type, XCamImageProcessType process_type = XCAM_IMAGE_PROCESS_ALWAYS)
+ : X3aResult (type, process_type)
+ {
+ set_ptr((void*)&_result);
+ _result.head.type = (XCam3aResultType)type;
+ _result.head.process_type = _process_type;
+ _result.head.version = XCAM_VERSION;
+ }
+ ~X3aStandardResultT () {}
+
+ void set_standard_result (StandardResult &res) {
+ uint32_t offset = sizeof (XCam3aResultHead);
+ XCAM_ASSERT (sizeof (StandardResult) >= offset);
+ memcpy ((uint8_t*)(&_result) + offset, (uint8_t*)(&res) + offset, sizeof (StandardResult) - offset);
+ }
+
+ StandardResult &get_standard_result () {
+ return _result;
+ }
+ const StandardResult &get_standard_result () const {
+ return _result;
+ }
+
+private:
+ StandardResult _result;
+};
+
+typedef X3aStandardResultT<XCam3aResultWhiteBalance> X3aWhiteBalanceResult;
+typedef X3aStandardResultT<XCam3aResultBlackLevel> X3aBlackLevelResult;
+typedef X3aStandardResultT<XCam3aResultColorMatrix> X3aColorMatrixResult;
+typedef X3aStandardResultT<XCam3aResultExposure> X3aExposureResult;
+typedef X3aStandardResultT<XCam3aResultFocus> X3aFocusResult;
+typedef X3aStandardResultT<XCam3aResultDemosaic> X3aDemosaicResult;
+typedef X3aStandardResultT<XCam3aResultDefectPixel> X3aDefectPixelResult;
+typedef X3aStandardResultT<XCam3aResultNoiseReduction> X3aNoiseReductionResult;
+typedef X3aStandardResultT<XCam3aResultEdgeEnhancement> X3aEdgeEnhancementResult;
+typedef X3aStandardResultT<XCam3aResultGammaTable> X3aGammaTableResult;
+typedef X3aStandardResultT<XCam3aResultMaccMatrix> X3aMaccMatrixResult;
+typedef X3aStandardResultT<XCam3aResultChromaToneControl> X3aChromaToneControlResult;
+
+};
+
+#endif //XCAM_3A_RESULT_H
diff --git a/xcore/x3a_statistics_queue.cpp b/xcore/x3a_statistics_queue.cpp
new file mode 100644
index 0000000..11c048c
--- /dev/null
+++ b/xcore/x3a_statistics_queue.cpp
@@ -0,0 +1,125 @@
+/*
+ * x3a_statistics_queue.c - statistics queue
+ *
+ * Copyright (c) 2014-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 "x3a_statistics_queue.h"
+#include <linux/videodev2.h>
+#include <linux/atomisp.h>
+
+namespace XCam {
+
+X3aIspStatistics::~X3aIspStatistics ()
+{
+ if (_3a_pool && _3a_stats)
+ _3a_pool->release_stats(_3a_stats);
+}
+
+X3aStatisticsQueue::X3aStatisticsQueue()
+ : _list_size(6)
+ , _list_allocated(false)
+{
+ xcam_mem_clear (&_grid_info);
+}
+
+X3aStatisticsQueue::~X3aStatisticsQueue()
+{
+ clear ();
+}
+
+bool
+X3aStatisticsQueue::pre_alloc_stats ()
+{
+ XCAM_ASSERT (_grid_info.width && _grid_info.height);
+ XCAM_ASSERT (_grid_info.aligned_width && _grid_info.aligned_height);
+ XCAM_ASSERT (_list_size);
+ XCAM_ASSERT (_3a_stats_list.empty());
+
+ uint32_t grid_size = _grid_info.aligned_width * _grid_info.aligned_height;
+ //uint32_t grid_size = _grid_info.width * _grid_info.height;
+
+ for (uint32_t i = 0; i < _list_size; ++i) {
+ struct atomisp_3a_statistics *stats = xcam_malloc0_type (struct atomisp_3a_statistics);
+ stats->data = (struct atomisp_3a_output*)xcam_malloc0 (grid_size * sizeof(*stats->data));
+ XCAM_ASSERT (stats && stats->data);
+ if (!stats || !stats->data)
+ return false;
+ stats->grid_info = _grid_info;
+ _3a_stats_list.push (stats);
+ }
+
+ _list_allocated = true;
+ return true;
+}
+
+SmartPtr<X3aIspStatistics>
+X3aStatisticsQueue::acquire_stats ()
+{
+ struct atomisp_3a_statistics *stats;
+
+ SmartLock locker(_list_mutex);
+
+ if (!_list_allocated && !pre_alloc_stats ()) {
+ XCAM_LOG_ERROR ("prealloc 3a stats failed");
+ return NULL;
+ }
+
+ if (_3a_stats_list.empty())
+ _list_release.wait (_list_mutex);
+
+ if (_3a_stats_list.empty()) {
+ XCAM_LOG_WARNING ("3a stats list waked up but still empty, check why");
+ return NULL;
+ }
+
+ stats = _3a_stats_list.front();
+ XCAM_ASSERT (stats);
+ _3a_stats_list.pop ();
+ return new X3aIspStatistics(this, stats);
+
+}
+
+void
+X3aStatisticsQueue::wakeup ()
+{
+ XCAM_LOG_INFO ("wakeup all stats in acquiring");
+ _list_release.broadcast ();
+}
+
+void
+X3aStatisticsQueue::release_stats (struct atomisp_3a_statistics *_3a_stats)
+{
+ SmartLock locker(_list_mutex);
+ _3a_stats_list.push (_3a_stats);
+ XCAM_ASSERT (_3a_stats_list.size() <= _list_size);
+ _list_release.signal ();
+}
+
+void
+X3aStatisticsQueue::clear ()
+{
+ XCAM_ASSERT (!_list_allocated || _3a_stats_list.size() == _list_size);
+ while (!_3a_stats_list.empty()) {
+ struct atomisp_3a_statistics *stats = _3a_stats_list.front ();
+ _3a_stats_list.pop ();
+ xcam_free (stats->data);
+ xcam_free (stats);
+ }
+}
+
+};
diff --git a/xcore/x3a_statistics_queue.h b/xcore/x3a_statistics_queue.h
new file mode 100644
index 0000000..b337702
--- /dev/null
+++ b/xcore/x3a_statistics_queue.h
@@ -0,0 +1,108 @@
+/*
+ * x3a_statistics_queue.h - statistics queue
+ *
+ * Copyright (c) 2014-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>
+ */
+
+#ifndef XCAM_3A_STATISTIC_QUEUE_H
+#define XCAM_3A_STATISTIC_QUEUE_H
+
+#include "xcam_common.h"
+#include "x3a_event.h"
+#include "xcam_mutex.h"
+#include "xcam_utils.h"
+#include "smartptr.h"
+#include <queue>
+#include <linux/atomisp.h>
+
+namespace XCam {
+
+class X3aStatisticsQueue;
+
+class X3aIspStatistics
+ : public X3aEvent
+{
+ friend class X3aStatisticsQueue;
+protected:
+ explicit X3aIspStatistics (
+ X3aStatisticsQueue* pool,
+ struct atomisp_3a_statistics *stats,
+ uint64_t timestamp = XCam::InvalidTimestamp
+ )
+ : X3aEvent (X3aEvent::TYPE_ISP_STATISTICS, timestamp)
+ , _3a_pool (pool)
+ , _3a_stats (stats)
+ , _timestamp (timestamp)
+ {}
+public:
+ virtual ~X3aIspStatistics ();
+ const struct atomisp_3a_statistics *get_3a_stats () const {
+ return _3a_stats;
+ }
+ struct atomisp_3a_statistics *get_3a_stats () {
+ return _3a_stats;
+ }
+
+ int64_t get_timestamp () const {
+ return _timestamp;
+ }
+ void set_timestamp (int64_t timestamp) {
+ _timestamp = timestamp;
+ }
+
+private:
+ XCAM_DEAD_COPY (X3aIspStatistics);
+
+private:
+ X3aStatisticsQueue *_3a_pool;
+ struct atomisp_3a_statistics *_3a_stats;
+ int64_t _timestamp;
+};
+
+class X3aStatisticsQueue {
+ friend class X3aIspStatistics;
+ typedef std::queue<struct atomisp_3a_statistics *> StatsList;
+public:
+ explicit X3aStatisticsQueue ();
+ ~X3aStatisticsQueue();
+
+ void set_grid_info (struct atomisp_grid_info &info) {
+ _grid_info = info;
+ }
+
+ SmartPtr<X3aIspStatistics> acquire_stats ();
+ void wakeup ();
+
+private:
+ void release_stats (struct atomisp_3a_statistics *_3a_stats);
+ bool pre_alloc_stats ();
+ void clear ();
+
+ XCAM_DEAD_COPY (X3aStatisticsQueue);
+
+private:
+ StatsList _3a_stats_list;
+ uint32_t _list_size;
+ bool _list_allocated;
+ XCam::Mutex _list_mutex;
+ XCam::Cond _list_release;
+ struct atomisp_grid_info _grid_info;
+};
+
+};
+
+#endif //XCAM_3A_STATISTIC_QUEUE_H
diff --git a/xcore/xcam_3a_result.h b/xcore/xcam_3a_result.h
new file mode 100644
index 0000000..1038522
--- /dev/null
+++ b/xcore/xcam_3a_result.h
@@ -0,0 +1,196 @@
+/*
+ * xcam_3a_result.h - 3A result interface
+ *
+ * Copyright (c) 2014-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>
+ */
+
+#ifndef C_XCAM_3A_RESULT_H
+#define C_XCAM_3A_RESULT_H
+
+#include <stdlib.h>
+#include <stdint.h>
+#include <stddef.h>
+
+XCAM_BEGIN_DECLARE
+
+typedef enum _ImageProcessType {
+ XCAM_IMAGE_PROCESS_ONCE,
+ XCAM_IMAGE_PROCESS_ALWAYS,
+} XCamImageProcessType;
+
+typedef enum _XCam3aResultType {
+ /* White Balance */
+ XCAM_3A_RESULT_WHITE_BALANCE,
+ XCAM_3A_RESULT_BLACK_LEVEL,
+ XCAM_3A_RESULT_YUV2RGB_MATRIX,
+ XCAM_3A_RESULT_RGB2YUV_MATRIX,
+
+ /* Exposure */
+ XCAM_3A_RESULT_EXPOSURE,
+
+ /* Focus */
+ XCAM_3A_RESULT_FOCUS,
+
+ XCAM_3A_RESULT_DEMOSAIC,
+ //XCAM_3A_RESULT_EIGEN_COLOR_DEMOSAICING,
+ XCAM_3A_RESULT_DEFECT_PIXEL_CORRECTION,
+
+ /* noise reduction */
+ XCAM_3A_RESULT_NOISE_REDUCTION,
+ XCAM_3A_RESULT_TEMPORAL_NOISE_REDUCTION,
+ XCAM_3A_RESULT_LUMA_NOISE_REDUCTION,
+ XCAM_3A_RESULT_ADVANCED_NOISE_REDUCTION,
+ XCAM_3A_RESULT_CHROMA_NOISER_EDUCTION,
+
+ XCAM_3A_RESULT_EDGE_ENHANCEMENT,
+ //XCAM_3A_RESULT_FRIGLE_CONTROL,
+ XCAM_3A_RESULT_MACC,
+ //XCAM_3A_RESULT_MACCTABLE,
+ XCAM_3A_RESULT_CHROMA_TONE_CONTROL,
+ //XCAM_3A_RESULT_CHROMATONECONTROLTABLE,
+ XCAM_3A_RESULT_CHROMA_ENHANCEMENT,
+ XCAM_3A_RESULT_Y_GAMMA,
+ XCAM_3A_RESULT_R_GAMMA,
+ XCAM_3A_RESULT_G_GAMMA,
+ XCAM_3A_RESULT_B_GAMMA,
+ //XCAM_3A_RESULT_SHADING_TABLE,
+ XCAM_3A_RESULT_USER_DEFINED_TYPE = 0x8000,
+} XCam3aResultType;
+
+/* matrix size 3x3 */
+#define XCAM_COLOR_MATRIX_SIZE 9
+#define XCAM_GAMMA_TABLE_SIZE 256
+#define XCAM_CHROMA_AXIS_SIZE 16
+#define XCAM_CHROMA_MATRIX_SIZE 4
+
+typedef struct _XCam3aResultHead {
+ XCam3aResultType type;
+ XCamImageProcessType process_type;
+ uint32_t version;
+ void (*destroy) (void);
+} XCam3aResultHead;
+
+typedef struct _XCam3aResultList {
+ XCam3aResultHead *result;
+ XCam3aResultHead *next;
+} XCam3aResultList;
+
+typedef struct _XCam3aResultWhiteBalance {
+ XCam3aResultHead head;
+
+ /* data */
+ double r_gain;
+ double gr_gain;
+ double gb_gain;
+ double b_gain;
+} XCam3aResultWhiteBalance;
+
+typedef struct _XCam3aResultBlackLevel {
+ XCam3aResultHead head;
+
+ /* data */
+ double r_level;
+ double gr_level;
+ double gb_level;
+ double b_level;
+} XCam3aResultBlackLevel;
+
+typedef struct _XCam3aResultColorMatrix {
+ XCam3aResultHead head;
+
+ /* data */
+ double matrix [XCAM_COLOR_MATRIX_SIZE];
+} XCam3aResultColorMatrix;
+
+typedef struct _XCam3aResultExposure {
+ XCam3aResultHead head;
+
+ /* data */
+ int32_t exposure_time; //in micro seconds
+ double analog_gain; // multipler
+ double digital_gain; // multipler
+ double aperture; //fn
+} XCam3aResultExposure;
+
+typedef struct _XCam3aResultFocus {
+ XCam3aResultHead head;
+
+ /* data */
+ int32_t position;
+} XCam3aResultFocus;
+
+typedef struct _XCam3aResultDemosaic {
+ XCam3aResultHead head;
+
+ /* data */
+ double noise;
+ double thresthold_cr;
+ double thresthold_cb;
+} XCam3aResultDemosaic;
+
+
+/* DefectPixel Correction */
+typedef struct _XCam3aResultDefectPixel {
+ XCam3aResultHead head;
+
+ /* data */
+ double gain;
+ double thresthold;
+} XCam3aResultDefectPixel;
+
+typedef struct _XCam3aResultNoiseReduction {
+ XCam3aResultHead head;
+
+ /* data */
+ double gain;
+ double thresthold1;
+ double thresthold2;
+} XCam3aResultNoiseReduction;
+
+typedef struct _XCam3aResultEdgeEnhancement {
+ XCam3aResultHead head;
+
+ /* data */
+ double gain;
+ double thresthold;
+} XCam3aResultEdgeEnhancement;
+
+typedef struct _XCam3aResultGammaTable {
+ XCam3aResultHead head;
+
+ /* data */
+ double table[XCAM_GAMMA_TABLE_SIZE];
+} XCam3aResultGammaTable;
+
+typedef struct _XCam3aResultMaccMatrix {
+ XCam3aResultHead head;
+
+ /* data */
+ double table[XCAM_CHROMA_AXIS_SIZE * XCAM_CHROMA_MATRIX_SIZE];
+} XCam3aResultMaccMatrix;
+
+typedef struct _XCam3aResultChromaToneControl {
+ XCam3aResultHead head;
+
+ /* data */
+ double uv_gain [XCAM_GAMMA_TABLE_SIZE]; // according to Y
+} XCam3aResultChromaToneControl;
+
+
+XCAM_END_DECLARE
+
+#endif
diff --git a/xcore/xcam_3a_types.h b/xcore/xcam_3a_types.h
new file mode 100644
index 0000000..b9171dc
--- /dev/null
+++ b/xcore/xcam_3a_types.h
@@ -0,0 +1,132 @@
+/*
+ * Copyright (c) 2014 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>
+ */
+
+/*!
+ * \file xcam_3a_types.h
+ * \brief 3A interface variable types
+ */
+
+#ifndef __XCAM_3A_TYPES_H
+#define __XCAM_3A_TYPES_H
+
+#include <string.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdint.h>
+
+typedef enum {
+ XCAM_MODE_NONE = -1,
+ XCAM_MODE_PREVIEW = 0,
+ XCAM_MODE_CAPTURE = 1,
+ XCAM_MODE_VIDEO = 2,
+ XCAM_MODE_CONTINUOUS_CAPTURE = 3
+} XCamMode;
+
+typedef enum {
+ XCAM_AE_MODE_NOT_SET = -1,
+ XCAM_AE_MODE_AUTO,
+ XCAM_AE_MODE_MANUAL,
+ XCAM_AE_MODE_SHUTTER_PRIORITY,
+ XCAM_AE_MODE_APERTURE_PRIORITY
+} XCamAeMode;
+
+typedef enum {
+ XCAM_AE_METERING_MODE_AUTO, /*mode_evaluative*/
+ XCAM_AE_METERING_MODE_SPOT, /*window*/
+ XCAM_AE_METERING_MODE_CENTER, /*mode_center*/
+} XCamAeMeteringMode;
+
+typedef enum {
+ XCAM_SCENE_MODE_NOT_SET = -1,
+ XCAM_SCENE_MODE_AUTO,
+ XCAM_SCENE_MODE_PORTRAIT,
+ XCAM_SCENE_MODE_SPORTS,
+ XCAM_SCENE_MODE_LANDSCAPE,
+ XCAM_SCENE_MODE_NIGHT,
+ XCAM_SCENE_MODE_NIGHT_PORTRAIT,
+ XCAM_SCENE_MODE_FIREWORKS,
+ XCAM_SCENE_MODE_TEXT,
+ XCAM_SCENE_MODE_SUNSET,
+ XCAM_SCENE_MODE_PARTY,
+ XCAM_SCENE_MODE_CANDLELIGHT,
+ XCAM_SCENE_MODE_BEACH_SNOW,
+ XCAM_SCENE_MODE_DAWN_DUSK,
+ XCAM_SCENE_MODE_FALL_COLORS,
+ XCAM_SCENE_MODE_BACKLIGHT
+} XCamSceneMode;
+
+typedef enum {
+ XCAM_AWB_MODE_NOT_SET = -1,
+ XCAM_AWB_MODE_AUTO = 0,
+ XCAM_AWB_MODE_MANUAL,
+ XCAM_AWB_MODE_DAYLIGHT,
+ XCAM_AWB_MODE_SUNSET,
+ XCAM_AWB_MODE_CLOUDY,
+ XCAM_AWB_MODE_TUNGSTEN,
+ XCAM_AWB_MODE_FLUORESCENT,
+ XCAM_AWB_MODE_WARM_FLUORESCENT,
+ XCAM_AWB_MODE_SHADOW,
+ XCAM_AWB_MODE_WARM_INCANDESCENT
+} XCamAwbMode;
+
+typedef enum {
+ XCAM_AE_ISO_MODE_AUTO, /* Automatic */
+ XCAM_AE_ISO_MODE_MANUAL /* Manual */
+} XCamIsoMode;
+
+typedef enum {
+ XCAM_AE_FLICKER_MODE_AUTO,
+ XCAM_AE_FLICKER_MODE_50HZ,
+ XCAM_AE_FLICKER_MODE_60HZ,
+ XCAM_AE_FLICKER_MODE_OFF
+} XCamFlickerMode;
+
+#if 0
+typedef enum {
+ XCAM_AF_MODE_NOT_SET = -1,
+ XCAM_AF_MODE_AUTO,
+ XCAM_AF_MODE_MACRO,
+ XCAM_AF_MODE_INFINITY,
+ XCAM_AF_MODE_FIXED,
+ XCAM_AF_MODE_MANUAL,
+ XCAM_AF_MODE_CONTINUOUS
+} XCamAfMode;
+#endif
+
+/*! \brief XCam3AWindow.
+ * Represents a rectangle area. Could be converted to
+ * AIQ ia_rectangle, see convert_xcam_to_ia_window().
+ */
+typedef struct _XCam3AWindow {
+ int32_t x_start; /*!< X of start point (left-upper corner) */
+ int32_t y_start; /*!< Y of start point (left-upper corner) */
+ int32_t x_end; /*!< X of end point (right-bottom corner) */
+ int32_t y_end; /*!< Y of start point (left-upper corner) */
+ int weight;
+} XCam3AWindow;
+
+typedef struct _XCamExposureResult {
+ int64_t time_in_us;
+ double analog_gain;
+ double digital_gain;
+ double aperture_fn;
+ int32_t iso;
+} XCamExposureResult;
+
+#endif //__XCAM_3A_TYPES_H
+
diff --git a/xcore/xcam_common.cpp b/xcore/xcam_common.cpp
new file mode 100644
index 0000000..6c7df2f
--- /dev/null
+++ b/xcore/xcam_common.cpp
@@ -0,0 +1,80 @@
+/*
+ * xcam_common.cpp - xcam common
+ *
+ * Copyright (c) 2014-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 "xcam_common.h"
+#include <fcntl.h>
+#include <errno.h>
+#include <sys/ioctl.h>
+
+void * xcam_malloc(size_t size)
+{
+ return malloc (size);
+}
+
+void * xcam_malloc0(size_t size)
+{
+ void * ptr = malloc (size);
+ memset (ptr, 0, size);
+ return ptr;
+}
+
+void xcam_free(void *ptr)
+{
+ if (ptr)
+ free (ptr);
+}
+
+int xcam_device_ioctl (int fd, int cmd, void *arg)
+{
+ int ret = 0;
+ int tried_time = 0;
+
+ if (fd < 0)
+ return -1;
+
+ while (1) {
+ ret = ioctl (fd, cmd, arg);
+ if (ret >= 0)
+ break;
+ if (errno != EINTR && errno != EAGAIN)
+ break;
+ if (++tried_time > 5)
+ break;
+ }
+
+ if (ret >= 0) {
+ XCAM_LOG_DEBUG ("ioctl return ok on fd(%d), cmd:%d", fd, cmd);
+ } else {
+ XCAM_LOG_DEBUG ("ioctl failed on fd(%d), cmd:%d, error:%s",
+ fd, cmd, strerror(errno));
+ }
+ return ret;
+}
+
+const char *
+xcam_fourcc_to_string (uint32_t fourcc)
+{
+ static char str[5];
+
+ xcam_mem_clear (str);
+ memcpy (str, &fourcc, 4);
+ return str;
+}
+
diff --git a/xcore/xcam_common.h b/xcore/xcam_common.h
new file mode 100644
index 0000000..3efd320
--- /dev/null
+++ b/xcore/xcam_common.h
@@ -0,0 +1,77 @@
+/*
+ * xcam_common.h - xcam common and utilities
+ *
+ * Copyright (c) 2014 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>
+ */
+
+#ifndef XCAM_COMMON_H
+#define XCAM_COMMON_H
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <string.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <pthread.h>
+#include "xcam_defs.h"
+
+XCAM_BEGIN_DECLARE
+
+typedef enum {
+ XCAM_RETURN_NO_ERROR = 0,
+ XCAM_RETURN_BYPASS = 1,
+
+ /* errors */
+ XCAM_RETURN_ERROR_PARAM = -1,
+ XCAM_RETURN_ERROR_MEM = -2,
+ XCAM_RETURN_ERROR_FILE = -3,
+ XCAM_RETURN_ERROR_AIQ = -4,
+ XCAM_RETURN_ERROR_ISP = -5,
+ XCAM_RETURN_ERROR_SENSOR = -6,
+ XCAM_RETURN_ERROR_THREAD = -7,
+ XCAM_RETURN_ERROR_IOCTL = -8,
+
+ XCAM_RETURN_ERROR_TIMEOUT = -9,
+
+ XCAM_RETURN_ERROR_UNKNOWN = -255,
+} XCamReturn;
+
+#define xcam_malloc_type(TYPE) (TYPE*)(xcam_malloc(sizeof(TYPE)))
+#define xcam_malloc0_type(TYPE) (TYPE*)(xcam_malloc0(sizeof(TYPE)))
+#define xcam_mem_clear(ptr) memset((ptr), 0, sizeof(*(ptr)))
+
+void * xcam_malloc (size_t size);
+void * xcam_malloc0 (size_t size);
+
+void xcam_free (void *ptr);
+
+/*
+ * return, 0 successfully
+ * else, check errno
+ */
+int xcam_device_ioctl (int fd, int cmd, void *arg);
+const char *xcam_fourcc_to_string (uint32_t fourcc);
+
+XCAM_END_DECLARE
+
+#endif //XCAM_COMMON_H
+
diff --git a/xcore/xcam_cpf_reader.c b/xcore/xcam_cpf_reader.c
new file mode 100644
index 0000000..c88dc6f
--- /dev/null
+++ b/xcore/xcam_cpf_reader.c
@@ -0,0 +1,165 @@
+/*
+ * xcam_thread.h - xcam basic thread
+ *
+ * Copyright (c) 2014 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 "xcam_cpf_reader.h"
+#include "xcam_common.h"
+
+#include <string.h>
+#include <stdlib.h>
+#include "libtbd.h"
+
+#undef XCAM_FAIL_RETURN_VAL
+#define XCAM_FAIL_RETURN_VAL(exp, ret) \
+ if (!(exp)) { \
+ XCAM_LOG_WARNING ("XCAM_FAIL_RETURN_VAL %s", #exp); \
+ return ret; \
+ }
+
+#undef XCAM_FAIL_RETURN
+#define XCAM_FAIL_RETURN(exp) \
+ if (!(exp)) { \
+ XCAM_LOG_WARNING ("XCAM_FAIL_RETURN %s", #exp); \
+ return ; \
+ }
+
+void *xcam_new0(size_t size)
+{
+ void *buf = malloc (size);
+ memset (buf, 0, size);
+ return buf;
+}
+
+XCamCpfBlob * xcam_cpf_blob_new ()
+{
+ return (XCamCpfBlob*) xcam_new0 (sizeof(XCamCpfBlob));
+}
+
+void xcam_cpf_blob_free (XCamCpfBlob *blob)
+{
+ XCAM_FAIL_RETURN (blob);
+
+ if (blob->data)
+ xcam_free (blob->data);
+
+ xcam_free (blob);
+}
+
+static int32_t
+read_cpf_file (const char *cpf_file, uint8_t **buf)
+{
+ int32_t size = 0;
+ FILE *fp = fopen (cpf_file, "rb");
+ XCAM_FAIL_RETURN_VAL (fp, -1);
+
+ *buf = NULL;
+
+ if (fseek (fp, 0, SEEK_END) < 0)
+ goto read_error;
+ if ((size = ftell (fp)) <= 0)
+ goto read_error;
+ if (fseek( fp, 0, SEEK_SET) < 0)
+ goto read_error;
+
+ *buf = (uint8_t*) xcam_new0 (size);
+ if (fread (*buf, 1, size, fp) != size)
+ goto read_error;
+
+ fclose (fp);
+ return size;
+
+read_error:
+ XCAM_LOG_ERROR ("read cpf(%s) failed", cpf_file);
+ fclose (fp);
+ if (*buf) {
+ xcam_free (*buf);
+ *buf = NULL;
+ }
+ return -1;
+
+}
+
+boolean
+xcam_cpf_read (const char *cpf_file, XCamCpfBlob *aiq_cpf, XCamCpfBlob *hal_cpf)
+{
+ uint8_t *cpf_buf;
+ int32_t cpf_size;
+
+ uint8_t *blob;
+ int32_t blob_size;
+
+ XCAM_FAIL_RETURN_VAL (cpf_file, FALSE);
+ XCAM_FAIL_RETURN_VAL (aiq_cpf, FALSE);
+
+ /* read cpf */
+ if ((cpf_size = read_cpf_file(cpf_file, &cpf_buf)) <= 0) {
+ XCAM_LOG_ERROR ("read cpf_file(%s) failed.", cpf_file);
+ return FALSE;
+ }
+
+ /* check sum */
+ if (tbd_validate (cpf_buf, cpf_size, tbd_tag_cpff) != tbd_err_none) {
+ XCAM_LOG_ERROR ("tbd validate cpf file(%s) failed.", cpf_file);
+ goto free_buf;
+ }
+
+ /* fetch AIQ */
+ if ( (tbd_get_record (cpf_buf, tbd_class_aiq, tbd_format_any,
+ (void**)&blob, (size_t*)&blob_size) != tbd_err_none) ||
+ !blob || blob_size <= 0) {
+ XCAM_LOG_ERROR ("CPF parse AIQ record failed.");
+ goto free_buf;
+ }
+ aiq_cpf->data = (uint8_t*) malloc (blob_size);
+ aiq_cpf->size = blob_size;
+ memcpy (aiq_cpf->data, blob, blob_size);
+
+
+#if 0 //DRV not necessary
+ /* fetch DRV */
+ if (tbd_get_record (cpf_buf, tbd_class_drv, tbd_format_any,
+ &drv_blob.data, &drv_blob.size) != tbd_err_none) {
+ XCAM_LOG_ERROR ("CPF parse DRV record failed.");
+ return FALSE;
+ }
+#endif
+
+
+ /* fetch HAL */
+ if (hal_cpf) {
+ if (tbd_get_record (cpf_buf, tbd_class_hal, tbd_format_any,
+ (void**)&blob, (size_t*)&blob_size) != tbd_err_none) {
+ XCAM_LOG_WARNING ("CPF doesn't have HAL record.");
+ // ignore HAL, not necessary
+ } else if (blob && blob_size > 0) {
+ hal_cpf->data = (uint8_t*) malloc (blob_size);
+ hal_cpf->size = blob_size;
+ memcpy (hal_cpf->data, blob, blob_size);
+ }
+ }
+
+ xcam_free (cpf_buf);
+ return TRUE;
+
+free_buf:
+ xcam_free (cpf_buf);
+ return FALSE;
+
+}
diff --git a/xcore/xcam_cpf_reader.h b/xcore/xcam_cpf_reader.h
new file mode 100644
index 0000000..cffb4e2
--- /dev/null
+++ b/xcore/xcam_cpf_reader.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2014 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>
+ */
+
+/*
+ * \file xcam_cpf_reader.h
+ * \brief xcam CPF reader
+*/
+
+#ifndef _XCAM_CPF_READER_H
+#define _XCAM_CPF_READER_H
+
+#include "xcam_defs.h"
+#include <stdint.h>
+#include <string.h>
+#include <stddef.h>
+
+XCAM_BEGIN_DECLARE
+
+
+typedef int boolean;
+
+#ifndef TRUE
+#define TRUE 1
+#endif
+
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+typedef struct _XCamCpfBlob XCamCpfBlob;
+
+/*! \brief CPF blob
+ */
+struct _XCamCpfBlob {
+ uint8_t *data; /*!< pointer to buffer*/
+ uint32_t size; /*!< buffer size*/
+};
+
+/*! \brief XCam CPF blob allocation.
+ * buffer is initialized to zero
+ *
+ * \return pointer to XCam CPF Blob
+ */
+XCamCpfBlob * xcam_cpf_blob_new ();
+
+/*! \brief XCam CPF blob release.
+ * release the blob structure as well as the buffer inside it.
+ *
+ * \param[in,out] pointer to XCam CPF Blob
+ */
+void xcam_cpf_blob_free (XCamCpfBlob *blob);
+
+/*! \brief XCam CPF blob release.
+ * release the blob structure as well as the buffer inside it. Called in xcam_3a_init().
+ *
+ * \param[in] cpf_file CPF file name
+ * \param[out] aiq_cpf pointer to XCam CPF Blob which will hold AIQ records
+ * \param[out] hal_cpf pointer to XCam CPF HAL which will hold HAL records
+ */
+boolean xcam_cpf_read (const char *cpf_file, XCamCpfBlob *aiq_cpf, XCamCpfBlob *hal_cpf);
+
+XCAM_END_DECLARE
+
+#endif //_XCAM_CPF_READER_H
diff --git a/xcore/xcam_defs.h b/xcore/xcam_defs.h
new file mode 100644
index 0000000..519c1fa
--- /dev/null
+++ b/xcore/xcam_defs.h
@@ -0,0 +1,106 @@
+/*
+ * xcam_defs.h - macros defines
+ *
+ * Copyright (c) 2014-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>
+ */
+
+#ifndef XCAM_DEFS_H
+#define XCAM_DEFS_H
+
+#ifndef XCAM_LOG_ERROR
+#define XCAM_LOG_ERROR(format, ...) \
+ printf ("XCAM ERROR %s:%d: " format "\n", __FILE__, __LINE__, ## __VA_ARGS__)
+#endif
+
+#ifndef XCAM_LOG_WARNING
+#define XCAM_LOG_WARNING(format, ...) \
+ printf ("XCAM WARNING %s:%d: " format "\n", __FILE__, __LINE__, ## __VA_ARGS__)
+#endif
+
+#ifndef XCAM_LOG_INFO
+#define XCAM_LOG_INFO(format, ...) \
+ printf ("XCAM INFO %s:%d: " format "\n", __FILE__, __LINE__, ## __VA_ARGS__)
+#endif
+
+#ifdef DEBUG
+#ifndef XCAM_LOG_DEBUG
+#define XCAM_LOG_DEBUG(format, ...) \
+ printf ("XCAM DEBUG %s:%d: " format "\n", __FILE__, __LINE__, ## __VA_ARGS__)
+#endif
+#else
+#define XCAM_LOG_DEBUG(...)
+#endif
+
+#define XCAM_ASSERT(exp) assert(exp)
+
+#ifdef __cplusplus
+#define XCAM_BEGIN_DECLARE extern "C" {
+#define XCAM_END_DECLARE }
+#else
+#define XCAM_BEGIN_DECLARE
+#define XCAM_END_DECLARE
+#endif
+
+#ifndef __user
+#define __user
+#endif
+
+#define XCAM_UNUSED(variable) (void)(variable)
+
+#define XCAM_MAX(a, b) ((a) > (b) ? (a) : (b))
+#define XCAM_MIN(a, b) ((a) < (b) ? (a) : (b))
+
+#define XCAM_FAIL_RETURN(LEVEL, exp, ret, msg, ...) \
+ if (!(exp)) { \
+ XCAM_LOG_##LEVEL (msg, ## __VA_ARGS__); \
+ return (ret); \
+ }
+
+#define XCAM_DEAD_COPY(ClassObj) \
+ ClassObj (const ClassObj&); \
+ ClassObj & operator= (const ClassObj&) \
+
+
+#define XCAM_STR(str) ((str) ? (str) : "null")
+#define XCAM_BOOL2STR(value) ((value) ? "true" : "false")
+
+#define XCAM_DOUBLE_EQUAL(a, b, tolerance) \
+ (((a) >= ((b) - tolerance)) && ((a) <= ((b) + tolerance)))
+
+#define XCAM_DOUBLE_EQUAL_AROUND(a, b) \
+ XCAM_DOUBLE_EQUAL(a, b, 0.000001)
+
+#define XCAM_GAMMA_TABLE_SIZE 256
+
+#define XCAM_TIMESPEC_2_USEC(timespec) ((timespec).tv_sec*1000000LL + (timespec).tv_nsec/1000)
+#define XCAM_TIMEVAL_2_USEC(timeval) ((timeval).tv_sec*1000000LL + (timeval).tv_usec)
+
+#define XCAM_TIMESTAMP_2_SECONDS(t) ((t)/1000000)
+#define XCAM_SECONDS_2_TIMESTAMP(t) ((t)*1000000)
+
+#define XCAM_TIMESTAMP_FORMAT "%02d:%02d:%02d.%03d"
+
+#define XCAM_TIMESTAMP_ARGS(t) \
+ (int32_t)(XCAM_TIMESTAMP_2_SECONDS(t)/3600), \
+ (int32_t)((XCAM_TIMESTAMP_2_SECONDS(t)%3600)/60), \
+ (int32_t)(XCAM_TIMESTAMP_2_SECONDS(t)%60), \
+ (int32_t)(((t)/1000)%1000)
+
+// align must be a interger of power 2
+#define XCAM_ALIGN_UP(value, align) (((value)+((align)-1))&(~((align)-1)))
+
+#endif //XCAM_DEFS_H
diff --git a/xcore/xcam_mutex.h b/xcore/xcam_mutex.h
new file mode 100644
index 0000000..bed8227
--- /dev/null
+++ b/xcore/xcam_mutex.h
@@ -0,0 +1,106 @@
+/*
+ * xcam_mutex.h - Lock
+ *
+ * Copyright (c) 2014 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>
+ */
+
+#ifndef XCAM_MUTEX_H
+#define XCAM_MUTEX_H
+
+#include <pthread.h>
+#include <sys/time.h>
+
+namespace XCam {
+
+class Mutex {
+ friend class Cond;
+private:
+ XCAM_DEAD_COPY (Mutex);
+
+public:
+ Mutex () {
+ pthread_mutex_init (&_mutex, NULL);
+ }
+ virtual ~Mutex () {
+ pthread_mutex_destroy (&_mutex);
+ }
+
+ void lock() {
+ pthread_mutex_lock (&_mutex);
+ }
+ void unlock() {
+ pthread_mutex_unlock (&_mutex);
+ }
+
+private:
+ pthread_mutex_t _mutex;
+};
+
+class Cond {
+private:
+ XCAM_DEAD_COPY (Cond);
+
+public:
+ Cond () {
+ pthread_cond_init (&_cond, NULL);
+ }
+ ~Cond () {
+ pthread_cond_destroy (&_cond);
+ }
+
+ int wait (Mutex &mutex) {
+ return pthread_cond_wait (&_cond, &mutex._mutex);
+ }
+ int timedwait (Mutex &mutex, uint32_t time_in_us) {
+ struct timeval now;
+ struct timespec abstime;
+
+ gettimeofday (&now, NULL);
+ now.tv_usec += time_in_us;
+ abstime.tv_sec += now.tv_sec + now.tv_usec / 1000000;
+ abstime.tv_nsec = (now.tv_usec % 1000000) * 1000;
+
+ return pthread_cond_timedwait (&_cond, &mutex._mutex, &abstime);
+ }
+
+ int signal() {
+ return pthread_cond_signal (&_cond);
+ }
+ int broadcast() {
+ return pthread_cond_broadcast (&_cond);
+ }
+private:
+ pthread_cond_t _cond;
+};
+
+class SmartLock {
+private:
+ XCAM_DEAD_COPY (SmartLock);
+
+public:
+ SmartLock (XCam::Mutex &mutex): _mutex(mutex) {
+ _mutex.lock();
+ }
+ virtual ~SmartLock () {
+ _mutex.unlock();
+ }
+private:
+ XCam::Mutex &_mutex;
+};
+};
+#endif //XCAM_MUTEX_H
+
diff --git a/xcore/xcam_thread.cpp b/xcore/xcam_thread.cpp
new file mode 100644
index 0000000..8daa41e
--- /dev/null
+++ b/xcore/xcam_thread.cpp
@@ -0,0 +1,115 @@
+/*
+ * xcam_thread.cpp - Thread
+ *
+ * Copyright (c) 2014 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 "xcam_thread.h"
+#include "xcam_mutex.h"
+
+namespace XCam {
+
+Thread::Thread (const char *name)
+ : _name (NULL)
+ , _thread_id (0)
+ , _started (false)
+{
+ if (name)
+ _name = strdup (name);
+}
+
+Thread::~Thread ()
+{
+ if (_name)
+ xcam_free (_name);
+}
+
+int
+Thread::thread_func (void *user_data)
+{
+ Thread *thread = (Thread *)user_data;
+ bool ret = true;
+
+ {
+ // Make sure running after start
+ SmartLock locker(thread->_mutex);
+ pthread_detach (pthread_self());
+ }
+ ret = thread->started ();
+
+ while (true) {
+ {
+ SmartLock locker(thread->_mutex);
+ if (!thread->_started || ret == false) {
+ thread->_started = false;
+ thread->_thread_id = 0;
+ thread->_exit_cond.signal();
+ ret = false;
+ break;
+ }
+ }
+
+ ret = thread->loop ();
+ }
+
+ thread->stopped ();
+
+ return 0;
+}
+
+bool
+Thread::started ()
+{
+ XCAM_LOG_DEBUG ("Thread(%s) started", XCAM_STR(_name));
+ return true;
+}
+
+void
+Thread::stopped ()
+{
+ XCAM_LOG_DEBUG ("Thread(%s) stopped", XCAM_STR(_name));
+}
+
+bool Thread::start ()
+{
+ SmartLock locker(_mutex);
+ if (_started)
+ return true;
+
+ if (pthread_create (&_thread_id, NULL, (void * (*)(void*))thread_func, this) != 0)
+ return false;
+ _started = true;
+ return true;
+}
+
+bool Thread::stop ()
+{
+ SmartLock locker(_mutex);
+ if (_started) {
+ _started = false;
+ _exit_cond.wait(_mutex);
+ }
+ return true;
+}
+
+bool Thread::is_running ()
+{
+ SmartLock locker(_mutex);
+ return _started;
+}
+
+};
diff --git a/xcore/xcam_thread.h b/xcore/xcam_thread.h
new file mode 100644
index 0000000..248d883
--- /dev/null
+++ b/xcore/xcam_thread.h
@@ -0,0 +1,63 @@
+/*
+ * xcam_thread.h - Thread
+ *
+ * Copyright (c) 2014 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>
+ */
+
+#ifndef XCAM_THREAD_H
+#define XCAM_THREAD_H
+
+#include <pthread.h>
+#include "xcam_defs.h"
+#include "xcam_common.h"
+#include "xcam_mutex.h"
+
+namespace XCam {
+
+class Thread {
+public:
+ Thread (const char *name = NULL);
+ virtual ~Thread ();
+
+ bool start ();
+ bool stop ();
+ bool is_running ();
+
+protected:
+ // return true to start loop, else the thread stopped
+ virtual bool started ();
+ virtual void stopped ();
+ // return true to continue; false to stop
+ virtual bool loop () = 0;
+private:
+ XCAM_DEAD_COPY (Thread);
+
+
+private:
+ static int thread_func (void *user_data);
+
+private:
+ char *_name;
+ pthread_t _thread_id;
+ XCam::Mutex _mutex;
+ XCam::Cond _exit_cond;
+ bool _started;
+};
+
+};
+
+#endif //XCAM_THREAD_H
diff --git a/xcore/xcam_utils.h b/xcore/xcam_utils.h
new file mode 100644
index 0000000..c44f621
--- /dev/null
+++ b/xcore/xcam_utils.h
@@ -0,0 +1,31 @@
+/*
+ * xcam_utils.h - xcam utilities
+ *
+ * Copyright (c) 2014-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>
+ */
+
+#ifndef XCAM_UTILS_H
+#define XCAM_UTILS_H
+
+#include "xcam_common.h"
+
+namespace XCam {
+
+static const int64_t InvalidTimestamp = INT64_C(-1);
+};
+
+#endif //XCAM_UTILS_H