652 lines
27 KiB
C++
652 lines
27 KiB
C++
/*
|
|
* Copyright (c) 2022 Rockchip Electronics Co., Ltd.
|
|
*
|
|
* 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: Cody Xie <cody.xie@rock-chips.com>
|
|
*/
|
|
#include "cac_adaptor.h"
|
|
|
|
#include <fcntl.h>
|
|
|
|
#include <fstream>
|
|
#include <iostream>
|
|
|
|
#define __STDC_FORMAT_MACROS
|
|
#include <cinttypes>
|
|
|
|
#include "algos/acac/lut_buffer.h"
|
|
#include "algos/acac/rk_aiq_types_acac_algo.h"
|
|
#include "common/rk_aiq_comm.h"
|
|
#include "common/rk_aiq_types_priv.h"
|
|
#include "xcore/base/xcam_log.h"
|
|
|
|
namespace RkCam {
|
|
|
|
#define RKCAC_STRENGTH_FIX_BITS 7
|
|
#define RKCAC_EDGE_DETECT_FIX_BITS 4
|
|
|
|
#define CAC_PSF_BUF_NUM 2
|
|
#define BITS_PER_BYTE 8
|
|
#define BYTES_PER_WORD 4
|
|
#define BITS_PER_WORD (BITS_PER_BYTE * BYTES_PER_WORD)
|
|
|
|
#define INTERP_CAC(x0, x1, ratio) ((ratio) * ((x1) - (x0)) + (x0))
|
|
|
|
#define DIV_ROUND_UP(n, d) (((n) + (d)-1) / (d))
|
|
|
|
#if RKAIQ_HAVE_CAC_V03 || RKAIQ_HAVE_CAC_V10
|
|
static const uint32_t IspBigModeWidthLimit = 2688;
|
|
static const uint32_t IspBigModeSizeLimit = IspBigModeWidthLimit * 1536;
|
|
static const uint32_t CacPsfCountLimit = 1632;
|
|
static const uint8_t CacChannelCount = 2;
|
|
#else // RKAIQ_HAVE_CAC_V11
|
|
static const uint32_t IspBigModeWidthLimit = 1536;
|
|
static const uint32_t IspBigModeSizeLimit = IspBigModeWidthLimit * 864;
|
|
static const uint32_t CacPsfCountLimit = 336;
|
|
static const uint8_t CacChannelCount = 2;
|
|
#endif
|
|
static const uint8_t CacScaleFactorDefault = 64;
|
|
static const uint8_t CacScaleFactorBigMode = 128;
|
|
static const uint8_t CacStrengthDistance = 128;
|
|
static const uint8_t CacPsfKernelSize = 7 * 5;
|
|
static const uint8_t CacPsfKernelWordSizeInMemory =
|
|
DIV_ROUND_UP((CacPsfKernelSize - 1) * BITS_PER_BYTE, BITS_PER_WORD);
|
|
static const uint8_t CacPsfBufferCount = CAC_PSF_BUF_NUM;
|
|
|
|
template<class T>
|
|
static constexpr const T& CacClamp( const T& v, const T& lo, const T& hi ) {
|
|
return v < lo ? lo : hi < v ? hi : v;
|
|
}
|
|
|
|
static inline bool IsIspBigMode(uint32_t width, uint32_t height, bool is_multi_sensor) {
|
|
if (is_multi_sensor || width > IspBigModeWidthLimit || width * height > IspBigModeSizeLimit) {
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* cac_wsize=bigmode_en ? (pic_width+126)>>7 : (pic_width+62)>>6;
|
|
* cac_hsize=bigmode_en ? (pic_height+126)>>7 : (pic_height+62)>>6;
|
|
* lut_h_wsize = cac_wsize*9
|
|
* lut_v_size = cac_hsize*2
|
|
*/
|
|
static inline void CalcCacLutConfig(uint32_t width, uint32_t height, bool is_big_mode,
|
|
LutBufferConfig& config) {
|
|
config.Width = width;
|
|
config.Height = height;
|
|
config.IsBigMode = is_big_mode;
|
|
if (config.IsBigMode) {
|
|
config.ScaleFactor = CacScaleFactorBigMode;
|
|
} else {
|
|
config.ScaleFactor = CacScaleFactorDefault;
|
|
}
|
|
/**
|
|
* CAC only processes R & B channels, that means for R or R channels,
|
|
* which have only half size of full picture, only need to div round up by 32(scale==64) or
|
|
* 64(scale==128). For calculate convinient, use full picture size to calculate
|
|
*/
|
|
config.LutHCount = is_big_mode ? (width + 126) >> 7 : (width + 62) >> 6;
|
|
config.LutVCount = is_big_mode ? (height + 126) >> 7 : (height + 62) >> 6;
|
|
config.PsfCfgCount = config.LutHCount * config.LutVCount;
|
|
XCAM_ASSERT(config.PsfCfgCount <= CacPsfCountLimit);
|
|
/**
|
|
* CAC stores one PSF point's kernel in 9 words, one kernel size is 8 bytes.
|
|
* (8bytes*8bits/byte + 32 - 1) / 32bits/word = 9 words.
|
|
*/
|
|
}
|
|
|
|
CacAlgoAdaptor::~CacAlgoAdaptor() {
|
|
current_lut_.clear();
|
|
lut_manger_ = nullptr;
|
|
};
|
|
|
|
#if RKAIQ_HAVE_CAC_V03
|
|
XCamReturn CacAlgoAdaptor::SetApiAttr(const rkaiq_cac_v03_api_attr_t* attr) {
|
|
if (!attr_) {
|
|
attr_ = std::unique_ptr<rkaiq_cac_v03_api_attr_t>(new rkaiq_cac_v03_api_attr_t);
|
|
}
|
|
if (attr->op_mode == RKAIQ_CAC_API_OPMODE_INVALID) {
|
|
return XCAM_RETURN_ERROR_PARAM;
|
|
} else if (attr->op_mode == RKAIQ_CAC_API_OPMODE_AUTO) {
|
|
attr_->iso_cnt = attr->iso_cnt;
|
|
attr_->op_mode = attr->op_mode;
|
|
memcpy(attr_->auto_params, attr->auto_params, sizeof(attr->auto_params));
|
|
} else if (attr->op_mode == RKAIQ_CAC_API_OPMODE_MANUAL) {
|
|
attr_->op_mode = attr->op_mode;
|
|
memcpy(&attr_->manual_param, &attr->manual_param, sizeof(attr->manual_param));
|
|
}
|
|
enable_ = attr_->enable = attr->enable;
|
|
isReCal_ = true;
|
|
|
|
return XCAM_RETURN_NO_ERROR;
|
|
}
|
|
#elif RKAIQ_HAVE_CAC_V10
|
|
XCamReturn CacAlgoAdaptor::SetApiAttr(const rkaiq_cac_v10_api_attr_t* attr) {
|
|
if (!attr_) {
|
|
attr_ = std::unique_ptr<rkaiq_cac_v10_api_attr_t>(new rkaiq_cac_v10_api_attr_t);
|
|
}
|
|
if (attr->op_mode == RKAIQ_CAC_API_OPMODE_INVALID) {
|
|
return XCAM_RETURN_ERROR_PARAM;
|
|
} else if (attr->op_mode == RKAIQ_CAC_API_OPMODE_AUTO) {
|
|
attr_->iso_cnt = attr->iso_cnt;
|
|
memcpy(attr_->auto_params, attr->auto_params, sizeof(attr->auto_params));
|
|
} else if (attr->op_mode == RKAIQ_CAC_API_OPMODE_MANUAL) {
|
|
memcpy(&attr_->manual_param, &attr->manual_param, sizeof(attr->manual_param));
|
|
}
|
|
attr_->op_mode = attr->op_mode;
|
|
enable_ = attr_->enable = attr->enable;
|
|
isReCal_ = true;
|
|
|
|
return XCAM_RETURN_NO_ERROR;
|
|
}
|
|
#elif RKAIQ_HAVE_CAC_V11
|
|
XCamReturn CacAlgoAdaptor::SetApiAttr(const rkaiq_cac_v11_api_attr_t* attr) {
|
|
if (attr->op_mode == RKAIQ_CAC_API_OPMODE_INVALID) {
|
|
return XCAM_RETURN_ERROR_PARAM;
|
|
}
|
|
|
|
if (!attr_) {
|
|
attr_ = std::unique_ptr<rkaiq_cac_v11_api_attr_t>(new rkaiq_cac_v11_api_attr_t);
|
|
}
|
|
|
|
attr_->op_mode = attr->op_mode;
|
|
if (attr->op_mode == RKAIQ_CAC_API_OPMODE_AUTO) {
|
|
attr_->iso_cnt = attr->iso_cnt;
|
|
memcpy(attr_->auto_params, attr->auto_params, sizeof(attr->auto_params));
|
|
} else if (attr->op_mode == RKAIQ_CAC_API_OPMODE_MANUAL) {
|
|
memcpy(&attr_->manual_param, &attr->manual_param, sizeof(attr->manual_param));
|
|
}
|
|
enable_ = attr_->enable = attr->enable;
|
|
isReCal_ = true;
|
|
|
|
return XCAM_RETURN_NO_ERROR;
|
|
}
|
|
#endif
|
|
|
|
#if RKAIQ_HAVE_CAC_V03
|
|
XCamReturn CacAlgoAdaptor::GetApiAttr(rkaiq_cac_v03_api_attr_t* attr) {
|
|
if (attr_ == nullptr) {
|
|
return XCAM_RETURN_ERROR_FAILED;
|
|
}
|
|
memcpy(attr, attr_.get(), sizeof(*attr));
|
|
|
|
return XCAM_RETURN_NO_ERROR;
|
|
}
|
|
#elif RKAIQ_HAVE_CAC_V10
|
|
XCamReturn CacAlgoAdaptor::GetApiAttr(rkaiq_cac_v10_api_attr_t* attr) {
|
|
if (attr_ == nullptr) {
|
|
return XCAM_RETURN_ERROR_FAILED;
|
|
}
|
|
memcpy(attr, attr_.get(), sizeof(*attr));
|
|
|
|
return XCAM_RETURN_NO_ERROR;
|
|
}
|
|
#elif RKAIQ_HAVE_CAC_V11
|
|
XCamReturn CacAlgoAdaptor::GetApiAttr(rkaiq_cac_v11_api_attr_t* attr) {
|
|
if (attr_ == nullptr) {
|
|
return XCAM_RETURN_ERROR_FAILED;
|
|
}
|
|
memcpy(attr, attr_.get(), sizeof(*attr));
|
|
|
|
return XCAM_RETURN_NO_ERROR;
|
|
}
|
|
#endif
|
|
|
|
#if RKAIQ_HAVE_CAC_V03 || RKAIQ_HAVE_CAC_V10 || RKAIQ_HAVE_CAC_V11
|
|
#if RKAIQ_HAVE_CAC_V03
|
|
XCamReturn CacAlgoAdaptor::Config(const AlgoCtxInstanceCfg* config,
|
|
const CalibDbV2_Cac_V03_t* calib) {
|
|
#elif RKAIQ_HAVE_CAC_V10
|
|
XCamReturn CacAlgoAdaptor::Config(const AlgoCtxInstanceCfg* config,
|
|
const CalibDbV2_Cac_V10_t* calib) {
|
|
#elif RKAIQ_HAVE_CAC_V11
|
|
XCamReturn CacAlgoAdaptor::Config(const AlgoCtxInstanceCfg* config,
|
|
const CalibDbV2_Cac_V11_t* calib) {
|
|
#endif
|
|
(void)(config);
|
|
|
|
LOGD_ACAC("%s : Enter", __func__);
|
|
ctx_config_ = config;
|
|
enable_ = calib != nullptr ? calib->SettingPara.enable : false;
|
|
calib_ = calib;
|
|
|
|
if (attr_ == nullptr) {
|
|
#if RKAIQ_HAVE_CAC_V03
|
|
attr_ = std::unique_ptr<rkaiq_cac_v03_api_attr_t>(new rkaiq_cac_v03_api_attr_t);
|
|
#elif RKAIQ_HAVE_CAC_V10
|
|
attr_ = std::unique_ptr<rkaiq_cac_v10_api_attr_t>(new rkaiq_cac_v10_api_attr_t);
|
|
#elif RKAIQ_HAVE_CAC_V11
|
|
attr_ = std::unique_ptr<rkaiq_cac_v11_api_attr_t>(new rkaiq_cac_v11_api_attr_t);
|
|
#endif
|
|
}
|
|
|
|
attr_->op_mode = RKAIQ_CAC_API_OPMODE_AUTO;
|
|
attr_->iso_cnt = calib_->TuningPara.SettingByIso_len;
|
|
XCAM_ASSERT(attr_->iso_cnt <= RKAIQ_CAC_MAX_ISO_CNT);
|
|
memcpy(attr_->auto_params, calib_->TuningPara.SettingByIso,
|
|
sizeof(calib_->TuningPara.SettingByIso[0]) * attr_->iso_cnt);
|
|
memcpy(&attr_->manual_param, calib_->TuningPara.SettingByIso,
|
|
sizeof(calib_->TuningPara.SettingByIso[0]));
|
|
#if !RKAIQ_HAVE_CAC_V03
|
|
memcpy(&attr_->persist_params, &calib->SettingPara, sizeof(calib->SettingPara));
|
|
attr_->enable = attr_->persist_params.enable;
|
|
|
|
#else
|
|
attr_->enable = enable_;
|
|
#endif
|
|
|
|
if (!enable_) {
|
|
attr_->enable = false;
|
|
return XCAM_RETURN_BYPASS;
|
|
}
|
|
|
|
valid_ = true;
|
|
return XCAM_RETURN_NO_ERROR;
|
|
}
|
|
#endif
|
|
|
|
XCamReturn CacAlgoAdaptor::Prepare(const RkAiqAlgoConfigAcac* config) {
|
|
LutBufferConfig lut_config{};
|
|
LutBufferConfig full_lut_config{};
|
|
uint32_t width = config->width;
|
|
uint32_t height = config->height;
|
|
bool is_big_mode = IsIspBigMode(width, height, config->is_multi_sensor);
|
|
char cac_map_path[RKCAC_MAX_PATH_LEN] = {0};
|
|
|
|
LOGD_ACAC("%s : en %d valid: %d Enter", __func__, enable_, valid_);
|
|
|
|
isReCal_ = true;
|
|
|
|
if (!enable_ || !valid_) {
|
|
return XCAM_RETURN_BYPASS;
|
|
}
|
|
|
|
config_ = config;
|
|
if (config->is_multi_isp) {
|
|
#if (RKAIQ_HAVE_CAC_V03 || RKAIQ_HAVE_CAC_V10) && defined(ISP_HW_V30) || RKAIQ_HAVE_CAC_V11
|
|
CalcCacLutConfig(width, height, is_big_mode, full_lut_config);
|
|
width = width / 2 + config->multi_isp_extended_pixel;
|
|
CalcCacLutConfig(width, height, is_big_mode, lut_config);
|
|
#endif
|
|
} else {
|
|
CalcCacLutConfig(width, height, is_big_mode, lut_config);
|
|
}
|
|
if (lut_manger_ == nullptr) {
|
|
lut_manger_ =
|
|
std::unique_ptr<LutBufferManager>(new LutBufferManager(lut_config, config->mem_ops));
|
|
lut_manger_->ImportHwBuffers(0);
|
|
if (config->is_multi_isp) {
|
|
lut_manger_->ImportHwBuffers(1);
|
|
}
|
|
}
|
|
auto* buf = lut_manger_->GetFreeHwBuffer(0);
|
|
if (buf == nullptr) {
|
|
LOGW_ACAC("No buffer available, maybe only one buffer ?!");
|
|
return XCAM_RETURN_NO_ERROR;
|
|
}
|
|
current_lut_.clear();
|
|
current_lut_.emplace_back(buf);
|
|
if (buf->State != LutBufferState::kInitial) {
|
|
LOGW_ACAC("Buffer in use, will not update lut!");
|
|
return XCAM_RETURN_NO_ERROR;
|
|
}
|
|
#if (RKAIQ_HAVE_CAC_V03 || RKAIQ_HAVE_CAC_V10) && defined(ISP_HW_V30) || RKAIQ_HAVE_CAC_V11
|
|
if (config->is_multi_isp) {
|
|
auto* buf = lut_manger_->GetFreeHwBuffer(1);
|
|
if (buf == nullptr) {
|
|
LOGW_ACAC("No buffer available, maybe only one buffer ?!");
|
|
return XCAM_RETURN_NO_ERROR;
|
|
}
|
|
current_lut_.emplace_back(buf);
|
|
}
|
|
#endif
|
|
XCAM_ASSERT(current_lut_.size() == (uint32_t)(config->is_multi_isp + 1));
|
|
|
|
#if !RKAIQ_HAVE_CAC_V03
|
|
if (attr_->persist_params.psf_path[0] != '/') {
|
|
strcpy(cac_map_path, config->iqpath);
|
|
strcat(cac_map_path, "/");
|
|
}
|
|
strcat(cac_map_path, attr_->persist_params.psf_path);
|
|
|
|
std::ifstream ifs(cac_map_path, std::ios::binary);
|
|
if (!ifs.is_open()) {
|
|
LOGE_ACAC("Failed to open PSF file %s", cac_map_path);
|
|
valid_ = false;
|
|
return XCAM_RETURN_ERROR_FILE;
|
|
}
|
|
|
|
if (!config->is_multi_isp) {
|
|
uint32_t line_offset = lut_config.LutHCount * CacPsfKernelWordSizeInMemory * BYTES_PER_WORD;
|
|
uint32_t size = lut_config.LutHCount * lut_config.LutVCount * CacPsfKernelWordSizeInMemory *
|
|
BYTES_PER_WORD;
|
|
for (int ch = 0; ch < CacChannelCount; ch++) {
|
|
char* addr0 = reinterpret_cast<char*>(current_lut_[0]->Addr) + ch * size;
|
|
ifs.read(addr0, size);
|
|
}
|
|
} else {
|
|
#if RKAIQ_HAVE_CAC_V10 && defined(ISP_HW_V30) || RKAIQ_HAVE_CAC_V11
|
|
XCAM_ASSERT(current_lut_.size() > 1);
|
|
// Read and Split Memory
|
|
// a == line_size - line_offset
|
|
// b == line_offset
|
|
// c == line_offset - a = 2 * line_offset - line_size
|
|
// For each line:
|
|
// read b size to left
|
|
// copy c from left to right
|
|
// read a' to right
|
|
// - +---------------------------+
|
|
// | |<---a---->| | |<---a'--->|
|
|
// | | |<-c->| |
|
|
// v |<---b---------->| |
|
|
// | | | | | |
|
|
// - +---------------------------+
|
|
// |<---------line_size------->|
|
|
//
|
|
uint32_t line_offset = lut_config.LutHCount * CacPsfKernelWordSizeInMemory * BYTES_PER_WORD;
|
|
uint32_t line_size =
|
|
full_lut_config.LutHCount * CacPsfKernelWordSizeInMemory * BYTES_PER_WORD;
|
|
for (int ch = 0; ch < CacChannelCount; ch++) {
|
|
char* addr0 = reinterpret_cast<char*>(current_lut_[0]->Addr) +
|
|
ch * line_offset * lut_config.LutVCount;
|
|
char* addr1 = reinterpret_cast<char*>(current_lut_[1]->Addr) +
|
|
ch * line_offset * lut_config.LutVCount;
|
|
for (uint32_t i = 0; i < full_lut_config.LutVCount; i++) {
|
|
ifs.read(addr0 + (i * line_offset), line_offset);
|
|
memcpy(addr1 + (i * line_offset),
|
|
addr0 + (i * line_offset) + line_size - line_offset,
|
|
2 * line_offset - line_size);
|
|
ifs.read(addr1 + (i * line_size) + line_offset, line_size - line_offset);
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
#endif
|
|
|
|
return XCAM_RETURN_NO_ERROR;
|
|
}
|
|
|
|
void CacAlgoAdaptor::OnFrameEvent(const RkAiqAlgoProcAcac* input, RkAiqAlgoProcResAcac* output) {
|
|
int i;
|
|
int iso_low = 50;
|
|
int iso_high = 50;
|
|
int gain_high, gain_low;
|
|
float ratio = 1.0;
|
|
int iso_div = 50;
|
|
int max_iso_step = attr_->iso_cnt;
|
|
int iso = input->iso;
|
|
LOGD_ACAC("%s : en %d valid: %d Enter", __func__, enable_, valid_);
|
|
|
|
if (current_lut_.empty()) {
|
|
valid_ = false;
|
|
} else {
|
|
valid_ = true;
|
|
}
|
|
|
|
if (attr_->op_mode == RKAIQ_CAC_API_OPMODE_AUTO &&
|
|
lastIso_ != input->iso)
|
|
isReCal_ = true;
|
|
|
|
lastIso_ = input->iso;
|
|
if (!isReCal_) {
|
|
output->res_com.cfg_update = false;
|
|
LOGD_ACAC("skip cac reCalc");
|
|
return ;
|
|
}
|
|
|
|
output->res_com.cfg_update = true;
|
|
isReCal_ = false;
|
|
|
|
if (!enable_ || !valid_) {
|
|
output->config[0].bypass_en = 1;
|
|
#if (RKAIQ_HAVE_CAC_V03 || RKAIQ_HAVE_CAC_V10) && defined(ISP_HW_V30)|| RKAIQ_HAVE_CAC_V11
|
|
output->config[1].bypass_en = 1;
|
|
#endif
|
|
output->enable = false;
|
|
return;
|
|
}
|
|
|
|
for (i = max_iso_step - 1; i >= 0; i--) {
|
|
if (iso < iso_div * (2 << i)) {
|
|
iso_low = iso_div * (2 << (i)) / 2;
|
|
iso_high = iso_div * (2 << i);
|
|
}
|
|
}
|
|
ratio = static_cast<float>(iso - iso_low) / (iso_high - iso_low);
|
|
if (iso_low == iso) {
|
|
iso_high = iso;
|
|
ratio = 0;
|
|
}
|
|
if (iso_high == iso) {
|
|
iso_low = iso;
|
|
ratio = 1;
|
|
}
|
|
gain_high = (int)(log(static_cast<float>(iso_high) / 50) / log(2.0));
|
|
gain_low = (int)(log(static_cast<float>(iso_low) / 50) / log(2.0));
|
|
|
|
gain_low = MIN(MAX(gain_low, 0), max_iso_step - 1);
|
|
gain_high = MIN(MAX(gain_high, 0), max_iso_step - 1);
|
|
|
|
XCAM_ASSERT(gain_low >= 0 && gain_low < max_iso_step);
|
|
XCAM_ASSERT(gain_high >= 0 && gain_high < max_iso_step);
|
|
|
|
#if RKAIQ_HAVE_CAC_V03
|
|
output->enable = attr_->enable;
|
|
output->config[0].center_en = 0;
|
|
output->config[0].center_width = 0;
|
|
output->config[0].center_height = 0;
|
|
output->config[0].psf_sft_bit = 2;
|
|
output->config[0].bypass_en = attr_->enable;
|
|
output->config[0].cfg_num = current_lut_[0]->Config.PsfCfgCount;
|
|
output->config[0].buf_fd = current_lut_[0]->Fd;
|
|
output->config[0].hsize = current_lut_[0]->Config.LutHCount * CacPsfKernelWordSizeInMemory;
|
|
output->config[0].vsize = current_lut_[0]->Config.LutVCount * CacChannelCount;
|
|
if (config_->is_multi_isp) {
|
|
memcpy(&output->config[1], &output->config[0], sizeof(output->config[0]));
|
|
if (current_lut_.size() > 1) {
|
|
output->config[1].buf_fd = current_lut_[1]->Fd;
|
|
}
|
|
}
|
|
#else //not RKAIQ_HAVE_CAC_V03
|
|
|
|
#if 0
|
|
output->config[0].strength[0] = 128;
|
|
output->config[0].strength[1] = 256;
|
|
output->config[0].strength[2] = 384;
|
|
output->config[0].strength[3] = 512;
|
|
output->config[0].strength[4] = 640;
|
|
output->config[0].strength[5] = 768;
|
|
output->config[0].strength[6] = 896;
|
|
output->config[0].strength[7] = 1024;
|
|
output->config[0].strength[8] = 1152;
|
|
output->config[0].strength[9] = 1280;
|
|
output->config[0].strength[10] = 1408;
|
|
output->config[0].strength[11] = 1536;
|
|
output->config[0].strength[12] = 1568;
|
|
output->config[0].strength[13] = 1600;
|
|
output->config[0].strength[14] = 1632;
|
|
output->config[0].strength[15] = 1664;
|
|
output->config[0].strength[16] = 1696;
|
|
output->config[0].strength[17] = 1728;
|
|
output->config[0].strength[18] = 1760;
|
|
output->config[0].strength[19] = 1792;
|
|
output->config[0].strength[20] = 1824;
|
|
output->config[0].strength[21] = 2047;
|
|
#endif
|
|
output->config[0].center_en = attr_->persist_params.center_en;
|
|
output->config[0].center_width = attr_->persist_params.center_x;
|
|
output->config[0].center_height = attr_->persist_params.center_y;
|
|
output->config[0].psf_sft_bit = attr_->persist_params.psf_shift_bits;
|
|
output->config[0].cfg_num = current_lut_[0]->Config.PsfCfgCount;
|
|
output->config[0].buf_fd = current_lut_[0]->Fd;
|
|
output->config[0].hsize = current_lut_[0]->Config.LutHCount * CacPsfKernelWordSizeInMemory;
|
|
output->config[0].vsize = current_lut_[0]->Config.LutVCount * CacChannelCount;
|
|
|
|
if (attr_->op_mode == RKAIQ_CAC_API_OPMODE_MANUAL) {
|
|
for (i = 0; i < RKCAC_STRENGTH_TABLE_LEN; i++) {
|
|
float strength = attr_->manual_param.global_strength > 0
|
|
? attr_->manual_param.global_strength
|
|
: attr_->manual_param.strength_table[i];
|
|
output->config[0].strength[i] = ROUND_F(attr_->manual_param.strength_table[i] * (1 << RKCAC_STRENGTH_FIX_BITS));
|
|
output->config[0].strength[i] =
|
|
output->config[0].strength[i] > 2047 ? 2047 : output->config[0].strength[i];
|
|
}
|
|
output->config[0].bypass_en = attr_->manual_param.bypass;
|
|
#if RKAIQ_HAVE_CAC_V11
|
|
output->config[0].clip_g_mode = attr_->manual_param.clip_g_mode;
|
|
output->config[0].neg_clip0_en = attr_->manual_param.neg_clip0_enable;
|
|
output->config[0].edge_detect_en = attr_->manual_param.edge_detect_en;
|
|
output->config[0].flat_thed_b = ROUND_F(attr_->manual_param.flat_thed_b * (1 << RKCAC_EDGE_DETECT_FIX_BITS));
|
|
output->config[0].flat_thed_r = ROUND_F(attr_->manual_param.flat_thed_r * (1 << RKCAC_EDGE_DETECT_FIX_BITS));
|
|
output->config[0].offset_r = CacClamp<uint32_t>(attr_->manual_param.offset_r, 0, 1 << 16);
|
|
//ROUND_F(attr_->manual_param.offset_r);
|
|
output->config[0].offset_b = CacClamp<uint32_t>(attr_->manual_param.offset_b, 0, 1 << 16);
|
|
//ROUND_F(attr_->manual_param.offset_b);
|
|
output->config[0].expo_thed_b =
|
|
(!attr_->manual_param.expo_det_b_en << 20) | CacClamp<uint32_t>(attr_->manual_param.expo_thed_b, 0, 0xfffff);
|
|
output->config[0].expo_thed_r =
|
|
(!attr_->manual_param.expo_det_r_en << 20) | CacClamp<uint32_t>(attr_->manual_param.expo_thed_r, 0, 0xfffff);
|
|
output->config[0].expo_adj_b = CacClamp<uint32_t>(attr_->manual_param.expo_adj_b, 0, 0xfffff);
|
|
output->config[0].expo_adj_r = CacClamp<uint32_t>(attr_->manual_param.expo_adj_r, 0, 0xfffff);
|
|
output->enable = attr_->enable;
|
|
#endif
|
|
} else if (attr_->op_mode == RKAIQ_CAC_API_OPMODE_AUTO) {
|
|
float strength[RKCAC_STRENGTH_TABLE_LEN] = {1.0f};
|
|
float strenth_low = 0.0;
|
|
float strenth_high = 0.0;
|
|
for (i = 0; i < RKCAC_STRENGTH_TABLE_LEN; i++) {
|
|
strenth_low = attr_->auto_params[gain_low].global_strength > 0
|
|
? attr_->auto_params[gain_low].global_strength
|
|
: attr_->auto_params[gain_low].strength_table[i];
|
|
strenth_high = attr_->auto_params[gain_high].global_strength > 0
|
|
? attr_->auto_params[gain_high].global_strength
|
|
: attr_->auto_params[gain_high].strength_table[i];
|
|
strength[i] = INTERP_CAC(strenth_low,
|
|
strenth_high, ratio);
|
|
output->config[0].strength[i] = ROUND_F(strength[i] * (1 << RKCAC_STRENGTH_FIX_BITS));
|
|
output->config[0].strength[i] =
|
|
output->config[0].strength[i] > 2047 ? 2047 : output->config[0].strength[i];
|
|
}
|
|
output->config[0].bypass_en = INTERP_CAC(attr_->auto_params[gain_low].bypass,
|
|
attr_->auto_params[gain_high].bypass, ratio);
|
|
|
|
#if RKAIQ_HAVE_CAC_V11
|
|
output->config[0].clip_g_mode =
|
|
INTERP_CAC((int)attr_->auto_params[gain_low].clip_g_mode,
|
|
(int)attr_->auto_params[gain_high].clip_g_mode, ratio);
|
|
output->config[0].neg_clip0_en =
|
|
INTERP_CAC((int)attr_->auto_params[gain_low].neg_clip0_enable,
|
|
(int)attr_->auto_params[gain_high].neg_clip0_enable, ratio);
|
|
output->config[0].edge_detect_en =
|
|
INTERP_CAC((int)attr_->auto_params[gain_low].edge_detect_en,
|
|
(int)attr_->auto_params[gain_high].edge_detect_en, ratio);
|
|
|
|
float flat_thed_b = INTERP_CAC(attr_->auto_params[gain_low].flat_thed_b,
|
|
attr_->auto_params[gain_high].flat_thed_b, ratio);
|
|
output->config[0].flat_thed_b = ROUND_F(flat_thed_b * (1 << RKCAC_EDGE_DETECT_FIX_BITS));
|
|
|
|
float flat_thed_r = INTERP_CAC(attr_->auto_params[gain_low].flat_thed_r,
|
|
attr_->auto_params[gain_high].flat_thed_r, ratio);
|
|
output->config[0].flat_thed_r = ROUND_F(flat_thed_r * (1 << RKCAC_EDGE_DETECT_FIX_BITS));
|
|
|
|
float offset_b = INTERP_CAC(attr_->auto_params[gain_low].offset_b,
|
|
attr_->auto_params[gain_high].offset_b, ratio);
|
|
output->config[0].offset_b = CacClamp<uint32_t>(ROUND_F(input->hdr_ratio * offset_b), 0, 1 << 16);
|
|
|
|
float offset_r = INTERP_CAC(attr_->auto_params[gain_low].offset_r,
|
|
attr_->auto_params[gain_high].offset_r, ratio);
|
|
output->config[0].offset_r = CacClamp<uint32_t>(ROUND_F(input->hdr_ratio * offset_r), 0, 1 << 16);
|
|
|
|
int exp_det_r_en = INTERP_CAC(attr_->auto_params[gain_low].expo_det_r_en,
|
|
attr_->auto_params[gain_high].expo_det_r_en, ratio);
|
|
int exp_det_b_en = INTERP_CAC(attr_->auto_params[gain_low].expo_det_b_en,
|
|
attr_->auto_params[gain_high].expo_det_b_en, ratio);
|
|
|
|
uint32_t expo_thed_b = INTERP_CAC(attr_->auto_params[gain_low].expo_thed_b,
|
|
attr_->auto_params[gain_high].expo_thed_b, ratio);
|
|
uint32_t expo_thed_r = INTERP_CAC(attr_->auto_params[gain_low].expo_thed_r,
|
|
attr_->auto_params[gain_high].expo_thed_r, ratio);
|
|
uint32_t expo_adj_b = INTERP_CAC(attr_->auto_params[gain_low].expo_adj_b,
|
|
attr_->auto_params[gain_high].expo_adj_b, ratio);
|
|
uint32_t expo_adj_r = INTERP_CAC(attr_->auto_params[gain_low].expo_adj_r,
|
|
attr_->auto_params[gain_high].expo_adj_r, ratio);
|
|
expo_thed_b = input->hdr_ratio * expo_thed_b;
|
|
expo_thed_r = input->hdr_ratio * expo_thed_r;
|
|
expo_adj_b = input->hdr_ratio * expo_adj_b;
|
|
expo_adj_r = input->hdr_ratio * expo_adj_r;
|
|
output->config[0].expo_thed_b =
|
|
(static_cast<int>(!exp_det_b_en) << 20) | CacClamp<uint32_t>(expo_thed_b, 0, 0xfffff);
|
|
output->config[0].expo_thed_r =
|
|
(static_cast<int>(!exp_det_r_en) << 20) | CacClamp<uint32_t>(expo_thed_r, 0, 0xfffff);
|
|
output->config[0].expo_adj_b = CacClamp<uint32_t>(expo_adj_b, 0, 0xfffff);
|
|
output->config[0].expo_adj_r = CacClamp<uint32_t>(expo_adj_r, 0, 0xfffff);
|
|
#endif
|
|
|
|
#if (RKAIQ_HAVE_CAC_V10) && defined(ISP_HW_V30) || RKAIQ_HAVE_CAC_V11
|
|
memcpy(&output->config[1], &output->config[0], sizeof(output->config[0]));
|
|
if (current_lut_.size() > 1) {
|
|
output->config[1].buf_fd = current_lut_[1]->Fd;
|
|
if (output->config[0].center_en) {
|
|
uint16_t w = config_->width / 4;
|
|
uint16_t e = config_->multi_isp_extended_pixel / 4;
|
|
uint16_t x = attr_->persist_params.center_x;
|
|
output->config[1].center_width = x - (w / 2 - e);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
|
|
|
|
}
|
|
#endif
|
|
output->enable = attr_->enable;
|
|
|
|
#if 0
|
|
LOGD_ACAC("global en : %d", output->enable);
|
|
LOGD_ACAC("center en: %d", output->config[0].center_en);
|
|
LOGD_ACAC("center x: %u", output->config[0].center_width);
|
|
LOGD_ACAC("center y: %u", output->config[0].center_height);
|
|
LOGD_ACAC("psf shift bits: %u", output->config[0].psf_sft_bit);
|
|
LOGD_ACAC("psf cfg num: %u", output->config[0].cfg_num);
|
|
LOGD_ACAC("psf buf fd: %d", output->config[0].buf_fd);
|
|
#if (RKAIQ_HAVE_CAC_V03 || RKAIQ_HAVE_CAC_V10) && defined(ISP_HW_V30)
|
|
if (current_lut_.size() > 1) {
|
|
LOGD_ACAC("psf buf fd right: %d", output->config[1].buf_fd);
|
|
LOGD_ACAC("center x right: %d", output->config[1].center_width);
|
|
LOGD_ACAC("center y right: %d", output->config[1].center_height);
|
|
}
|
|
#endif
|
|
LOGD_ACAC("psf hwsize: %u", output->config[0].hsize);
|
|
LOGD_ACAC("psf vsize: %u", output->config[0].vsize);
|
|
for (i = 0; i < RKCAC_STRENGTH_TABLE_LEN; i++) {
|
|
LOGD_ACAC("strength %d: %u", i, output->config[0].strength[i]);
|
|
}
|
|
#if RKAIQ_HAVE_CAC_V11
|
|
LOGD_ACAC("clip_g_mode: %u", output->config[0].clip_g_mode);
|
|
LOGD_ACAC("edge_detect_en: %u", output->config[0].edge_detect_en);
|
|
LOGD_ACAC("neg_clip0_en: %u", output->config[0].neg_clip0_en);
|
|
LOGD_ACAC("expo_thed_b: %u", output->config[0].expo_thed_b);
|
|
LOGD_ACAC("expo_thed_r: %u", output->config[0].expo_thed_r);
|
|
LOGD_ACAC("expo_adj_b: %u", output->config[0].expo_adj_b);
|
|
LOGD_ACAC("expo_adj_r: %u", output->config[0].expo_adj_r);
|
|
LOGD_ACAC("flat_thed_b: %u", output->config[0].flat_thed_b);
|
|
LOGD_ACAC("flat_thed_r: %u", output->config[0].flat_thed_r);
|
|
#endif
|
|
#endif
|
|
}
|
|
|
|
} // namespace RkCam
|