blob: bbc9df5002440f6c7b314dfe754e31bf3ffd41b2 [file] [log] [blame]
/*
* Copyright (C) 2015-2020 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.
*/
#define LOG_TAG "AiqEngine"
#include "iutils/Utils.h"
#include "iutils/Errors.h"
#include "iutils/CameraLog.h"
#include "PlatformData.h"
#include "AiqEngine.h"
#include "FaceDetection.h"
namespace icamera {
AiqEngine::AiqEngine(int cameraId, SensorHwCtrl *sensorHw, LensHw *lensHw, AiqSetting *setting) :
mCameraId(cameraId),
mAiqSetting(setting),
mFirstAiqRunning(true),
mFirstExposureSetting(true),
mAiqRunningForPerframe(false),
m3ACadenceSequence(0),
mLastStatsSequence(-1)
{
LOG1("%s, mCameraId = %d", __func__, mCameraId);
CLEAR(mRgbsGridArray);
CLEAR(mAfGridArray);
mAiqCore = new AiqCore(mCameraId);
mSensorManager = new SensorManager(mCameraId, sensorHw);
mLensManager = new LensManager(mCameraId, lensHw);
// Should consider better place to maintain the life cycle of AiqResultStorage
mAiqResultStorage = AiqResultStorage::getInstance(mCameraId);
mCurrentStatsSequence = 0;
}
AiqEngine::~AiqEngine()
{
LOG1("%s, mCameraId = %d", __func__, mCameraId);
delete mLensManager;
delete mSensorManager;
delete mAiqCore;
AiqResultStorage::releaseAiqResultStorage(mCameraId);
}
int AiqEngine::init()
{
AutoMutex l(mEngineLock);
LOG1("%s, mCameraId = %d", __func__, mCameraId);
if (mAiqCore->init() != OK) {
return UNKNOWN_ERROR;
}
mSensorManager->init();
LOG1("%s, end mCameraId = %d", __func__, mCameraId);
return OK;
}
int AiqEngine::deinit()
{
AutoMutex l(mEngineLock);
LOG1("%s, mCameraId = %d", __func__, mCameraId);
mSensorManager->deinit();
mAiqCore->deinit();
LOG1("%s, end mCameraId = %d", __func__, mCameraId);
return OK;
}
int AiqEngine::configure(const std::vector<ConfigMode>& configModes)
{
AutoMutex l(mEngineLock);
LOG1("%s, mCameraId = %d", __func__, mCameraId);
mAiqCore->configure(configModes);
return OK;
}
int AiqEngine::startEngine()
{
AutoMutex l(mEngineLock);
LOG1("%s, mCameraId = %d", __func__, mCameraId);
mFirstAiqRunning = true;
mFirstExposureSetting = true;
mSensorManager->reset();
mLensManager->start();
m3ACadenceSequence = 0;
LOG1("%s, end mCameraId = %d", __func__, mCameraId);
return OK;
}
int AiqEngine::stopEngine()
{
AutoMutex l(mEngineLock);
LOG1("%s, end mCameraId = %d", __func__, mCameraId);
mLensManager->stop();
return OK;
}
int AiqEngine::run3A(long *settingSequence)
{
LOG3A("%s", __func__);
// Run 3A in call thread
AutoMutex l(mEngineLock);
// Handle 3A cadence logic
int run3ACadence = mAiqParam.run3ACadence;
if (run3ACadence < 1) {
LOGW("Invalid 3A cadence %d, use default 1.", run3ACadence);
run3ACadence = 1;
}
LOG2("%s: run3ACadence is %d", __func__, run3ACadence);
if (m3ACadenceSequence % run3ACadence != 0) {
// Skip 3A per cadence
m3ACadenceSequence ++;
return OK;
}
LOG2("%s: run 3A for cadence sequence %ld", __func__, m3ACadenceSequence);
m3ACadenceSequence ++;
mAiqRunningForPerframe = (settingSequence != nullptr);
AiqState state = prepareInputParam();
AiqResult *aiqResult = mAiqResultStorage->acquireAiqResult();
aiqResult->mTuningMode = mAiqParam.tuningMode;
if (state == AIQ_STATE_RUN) {
state = runAiq(aiqResult);
}
if (state == AIQ_STATE_RESULT_SET) {
state = handleAiqResult(aiqResult);
}
if (state == AIQ_STATE_DONE) {
done(aiqResult);
}
mAiqResultStorage->unLockAiqStatistics();
if (settingSequence) {
*settingSequence = mAiqResultStorage->getAiqResult()->mSequence;
LOG3A("%s, sequence %ld, mLastStatsSequence %ld", __func__, *settingSequence,
mLastStatsSequence);
}
PlatformData::saveMakernoteData(mCameraId, mAiqParam.makernoteMode,
mAiqResultStorage->getAiqResult()->mSequence);
return (state == AIQ_STATE_DONE || state == AIQ_STATE_WAIT) ? 0 : UNKNOWN_ERROR;
}
EventListener *AiqEngine::getSofEventListener()
{
AutoMutex l(mEngineLock);
LOG1("%s, mCameraId = %d", __func__, mCameraId);
return mSensorManager->getSofEventListener();
}
int AiqEngine::saveAfGridData(const ia_aiq_af_grid* afGrid, ia_aiq_af_grid* dst)
{
LOG3A("%s", __func__);
if (afGrid == nullptr
|| afGrid->filter_response_1 == nullptr
|| afGrid->filter_response_2 == nullptr
|| afGrid->grid_width == 0
|| afGrid->grid_height == 0) {
LOGE("%s, af grids are invalid", __func__);
return BAD_VALUE;
}
size_t gridSize = afGrid->grid_width * afGrid->grid_height;
if (afGrid->grid_width != dst->grid_width || afGrid->grid_height != dst->grid_height) {
if (dst->filter_response_1 != nullptr) {
delete [] dst->filter_response_1;
}
dst->filter_response_1 = new int[gridSize];
if (dst->filter_response_2 != nullptr) {
delete [] dst->filter_response_2;
}
dst->filter_response_2 = new int[gridSize];
}
dst->grid_width = afGrid->grid_width;
dst->grid_height = afGrid->grid_height;
dst->block_width = afGrid->block_width;
dst->block_height = afGrid->block_height;
MEMCPY_S(dst->filter_response_1, gridSize * sizeof(int),
afGrid->filter_response_1, gridSize * sizeof(int));
MEMCPY_S(dst->filter_response_2, gridSize * sizeof(int),
afGrid->filter_response_2, gridSize * sizeof(int));
LOG3A("%s, grid size=[%dx%d]", __func__, dst->grid_width, dst->grid_height);
return OK;
}
int AiqEngine::saveRgbsGridData(const ia_aiq_rgbs_grid* rgbsGrid, ia_aiq_rgbs_grid* dst)
{
LOG3A("%s", __func__);
if (rgbsGrid == nullptr
|| rgbsGrid->blocks_ptr == nullptr
|| rgbsGrid->grid_width == 0
|| rgbsGrid->grid_height == 0) {
LOGE("%s, rgbs grids are invalid", __func__);
return BAD_VALUE;
}
size_t gridSize = rgbsGrid->grid_width * rgbsGrid->grid_height;
if (rgbsGrid->grid_width != dst->grid_width || rgbsGrid->grid_height != dst->grid_height) {
if (dst->blocks_ptr != nullptr) {
delete [] dst->blocks_ptr;
}
dst->blocks_ptr = new rgbs_grid_block[gridSize];
}
dst->grid_width = rgbsGrid->grid_width;
dst->grid_height = rgbsGrid->grid_height;
MEMCPY_S(dst->blocks_ptr, gridSize * sizeof(rgbs_grid_block),
rgbsGrid->blocks_ptr, gridSize * sizeof(rgbs_grid_block));
dst->shading_correction = rgbsGrid->shading_correction;
LOG3A("%s, grid size=[%dx%d]", __func__, dst->grid_width, dst->grid_height);
return OK;
}
int AiqEngine::prepareStats(ia_aiq_statistics_input_params_v4 *statsParam,
ia_aiq_gbce_results *gbceResults,
AiqStatistics *aiqStatistics)
{
mLastStatsSequence = aiqStatistics->mSequence;
LOG3A("%s, sequence %ld", __func__, aiqStatistics->mSequence);
statsParam->rgbs_grids = mRgbsGridArray;
statsParam->af_grids = mAfGridArray;
int ret = OK;
do {
// The statistics timestamp is incorrect. If possible, use SOF timestamp instead.
unsigned long long timestamp = mSensorManager->getSofTimestamp(aiqStatistics->mSequence);
if (timestamp == 0) {
LOG2("The sof sequence was not found %ld", aiqStatistics->mSequence);
timestamp = aiqStatistics->mTimestamp;
}
statsParam->frame_id = aiqStatistics->mSequence;
statsParam->frame_timestamp = timestamp;
statsParam->num_rgbs_grids = PlatformData::getExposureNum(mCameraId,
CameraUtils::isMultiExposureCase(mAiqParam.tuningMode));
if (statsParam->num_rgbs_grids > 1) {
for (unsigned int i = 0; i < statsParam->num_rgbs_grids; i++) {
statsParam->rgbs_grids[i] = &(aiqStatistics->mRgbsGridArray[i]);
}
} else {
statsParam->rgbs_grids[0] = &(aiqStatistics->mRgbsGridArray[0]);
}
statsParam->af_grids[0] = &(aiqStatistics->mAfGridArray[0]);
statsParam->num_af_grids = 1;
statsParam->external_histograms = nullptr;
statsParam->num_external_histograms = 0;
statsParam->camera_orientation = ia_aiq_camera_orientation_unknown;
const AiqResult *feedback = mAiqResultStorage->getAiqResult(aiqStatistics->mSequence);
if (feedback == nullptr) {
LOGW("%s: no feed back result for sequence %ld! use the latest instead",
__func__, aiqStatistics->mSequence);
feedback = mAiqResultStorage->getAiqResult();
}
statsParam->frame_ae_parameters = &feedback->mAeResults;
statsParam->frame_af_parameters = &feedback->mAfResults;
statsParam->frame_pa_parameters = &feedback->mPaResults;
statsParam->awb_results = &feedback->mAwbResults;
statsParam->frame_sa_parameters = &feedback->mSaResults;
*gbceResults = feedback->mGbceResults;
} while (0);
LOG3A("%s end", __func__);
return ret;
}
void AiqEngine::setAiqResult(AiqResult *aiqResult, bool skip)
{
SensorExpGroup sensorExposures;
for (unsigned int i = 0; i < aiqResult->mAeResults.num_exposures; i++) {
SensorExposure exposure;
exposure.sensorParam = *aiqResult->mAeResults.exposures[i].sensor_exposure;
exposure.realDigitalGain = (aiqResult->mAeResults.exposures[i].exposure)->digital_gain;
sensorExposures.push_back(exposure);
}
bool useSof = !mFirstExposureSetting;
aiqResult->mSequence = mSensorManager->updateSensorExposure(sensorExposures, useSof);
if (mFirstExposureSetting) {
mFirstExposureSetting = false;
}
aiqResult->mSkip = skip;
if (skip) {
LOG3A("%s, skipping frame aiqResult->mSequence = %ld", __func__, aiqResult->mSequence);
}
mLensManager->setLensResult(aiqResult->mAeResults, aiqResult->mAfResults);
aiqResult->mAiqParam = mAiqParam;
}
int AiqEngine::getSkippingNum(AiqResult *aiqResult)
{
LOG3A("%s", __func__);
int skipNum = 0;
if (!mFirstAiqRunning) {
const AiqResult *lastResult = mAiqResultStorage->getAiqResult();
if (lastResult->mTuningMode != aiqResult->mTuningMode) {
// Skip 3 frames when pipe switching
skipNum = 3;
}
} else if (mAiqRunningForPerframe) {
// The 1st result takes effect @ frame (initialSkip) (applied before stream on)
skipNum = PlatformData::getInitialSkipFrame(mCameraId);
}
return skipNum;
}
bool AiqEngine::needRun3A(AiqStatistics *aiqStatistics)
{
LOG3A("%s", __func__);
// Force to run 3a for per-frame control case
if (mAiqRunningForPerframe) {
return true;
}
// Force to run 3a for the first time running
if (mFirstAiqRunning) {
return true;
}
if (aiqStatistics == nullptr) {
LOG3A("no stats and not need to re-run 3A");
return false;
}
if (mLastStatsSequence == aiqStatistics->mSequence) {
LOG3A("no new stats skip, mLastStatsSequence = %ld", mLastStatsSequence);
return false;
} else if (mSensorManager->getCurrentExposureAppliedDelay() > kMaxExposureAppliedDelay) {
LOG3A("exposure setting applied delay is too larger, skip it");
return false;
}
return true;
}
AiqEngine::AiqState AiqEngine::prepareInputParam(void)
{
// set Aiq Params
int ret = mAiqSetting->getAiqParameter(mAiqParam);
if (ret != OK)
return AIQ_STATE_ERROR;
// Update sensor info for the first-run of AIQ
if (mFirstAiqRunning) {
mSensorManager->setFrameRate(mAiqParam.fps);
// set sensor info if needed
ia_aiq_exposure_sensor_descriptor sensorDescriptor;
ia_aiq_frame_params frameParams;
CLEAR(sensorDescriptor);
CLEAR(frameParams);
ret = mSensorManager->getSensorInfo(frameParams, sensorDescriptor);
CheckError((ret != OK), AIQ_STATE_ERROR, "Get sensor info failed:%d", ret);
mAiqCore->setSensorInfo(frameParams, sensorDescriptor);
}
// update lens related parameters
mLensManager->getLensInfo(mAiqParam);
mAiqCore->updateParameter(mAiqParam);
// set Stats
ia_aiq_statistics_input_params_v4 statsParam;
CLEAR(statsParam);
ia_aiq_gbce_results gbceResults;
CLEAR(gbceResults);
AiqStatistics *aiqStats =
const_cast<AiqStatistics*>(mAiqResultStorage->getAndLockAiqStatistics());
if (!needRun3A(aiqStats)) {
return AIQ_STATE_WAIT;
}
if (aiqStats == nullptr) {
LOG3A("%s: run aiq without stats data", __func__);
return AIQ_STATE_RUN;
}
// update face detection related parameters
ia_atbx_face faces[MAX_FACES_DETECTABLE];
ia_atbx_face_state facesState;
if (PlatformData::isFaceAeEnabled(mCameraId)) {
facesState.num_faces = 0;
facesState.faces = faces;
int ret = icamera::FaceDetection::getResult(mCameraId, &facesState);
if (ret == OK && facesState.num_faces > 0) {
ia_rectangle rect = facesState.faces[0].face_area;
LOG3A("@%s, face number:%d, left:%d, top:%d, right:%d, bottom:%d", __func__,
facesState.num_faces, rect.left, rect.top, rect.right, rect.bottom);
statsParam.faces = &facesState;
}
}
ret = prepareStats(&statsParam, &gbceResults, aiqStats);
if (ret != OK) {
LOG3A("%s: no useful stats", __func__);
return AIQ_STATE_RUN;
}
mAiqCore->setStatistics(&statsParam);
return AIQ_STATE_RUN;
}
AiqEngine::AiqState AiqEngine::runAiq(AiqResult *aiqResult)
{
int ret = mAiqCore->runAiq(aiqResult);
if (ret != OK) {
return AIQ_STATE_ERROR;
}
return AIQ_STATE_RESULT_SET;
}
AiqEngine::AiqState AiqEngine::handleAiqResult(AiqResult *aiqResult)
{
LOG2("%s: aiqResult->mTuningMode = %d", __func__, aiqResult->mTuningMode);
applyManualTonemaps(aiqResult);
return AIQ_STATE_DONE;
}
int AiqEngine::applyManualTonemaps(AiqResult *aiqResult)
{
/*
* Normal use-case is the automatic modes, and we need not do anything here
*/
if (mAiqParam.tonemapMode == TONEMAP_MODE_FAST ||
mAiqParam.tonemapMode == TONEMAP_MODE_HIGH_QUALITY) {
return OK;
}
if (mAiqParam.tonemapMode == TONEMAP_MODE_GAMMA_VALUE) {
AiqUtils::applyTonemapGamma(mAiqParam.tonemapGamma, &aiqResult->mGbceResults);
} else if (mAiqParam.tonemapMode == TONEMAP_MODE_PRESET_CURVE) {
if (mAiqParam.tonemapPresetCurve == TONEMAP_PRESET_CURVE_SRGB) {
AiqUtils::applyTonemapSRGB(&aiqResult->mGbceResults);
} else if (mAiqParam.tonemapPresetCurve == TONEMAP_PRESET_CURVE_REC709) {
AiqUtils::applyTonemapREC709(&aiqResult->mGbceResults);
}
} else if (mAiqParam.tonemapMode == TONEMAP_MODE_CONTRAST_CURVE) {
AiqUtils::applyTonemapCurve(mAiqParam.tonemapCurves, &aiqResult->mGbceResults);
AiqUtils::applyAwbGainForTonemapCurve(mAiqParam.tonemapCurves, &aiqResult->mAwbResults);
}
// use unity value for tone map table
if (aiqResult->mGbceResults.tone_map_lut_size > 0 && aiqResult->mGbceResults.tone_map_lut) {
for (unsigned int i = 0; i < aiqResult->mGbceResults.tone_map_lut_size; i++) {
aiqResult->mGbceResults.tone_map_lut[i] = 1.0;
}
}
return OK;
}
AiqEngine::AiqState AiqEngine::done(AiqResult *aiqResult)
{
int skipNum = getSkippingNum(aiqResult);
AiqResult *tmp = aiqResult;
for (int i = 0; i < skipNum; i++) {
// Increase the sensor settings sequence id, so for any frame that
// its sequence id is bigger than the user expected id will be discarded.
setAiqResult(tmp, true);
mAiqResultStorage->updateAiqResult(tmp->mSequence);
tmp = mAiqResultStorage->acquireAiqResult();
*tmp = *aiqResult;
}
setAiqResult(tmp, false);
mAiqResultStorage->updateAiqResult(tmp->mSequence);
mFirstAiqRunning = false;
return AIQ_STATE_WAIT;
}
} /* namespace icamera */