/*
|
* rk_aiq_user_api2_camgroup.cpp
|
*
|
* Copyright (c) 2021 Rockchip 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 "rk_aiq_user_api2_sysctl.h"
|
#include "rk_aiq_user_api2_camgroup.h"
|
#include "RkAiqCamGroupManager.h"
|
#include "common/panorama_stitchingApp.h"
|
|
using namespace RkCam;
|
using namespace XCam;
|
|
static XCamReturn
|
_cam_group_bind(rk_aiq_camgroup_ctx_t* camgroup_ctx, rk_aiq_sys_ctx_t* aiq_ctx)
|
{
|
#ifdef RKAIQ_ENABLE_CAMGROUP
|
ENTER_XCORE_FUNCTION();
|
|
XCamReturn ret = XCAM_RETURN_NO_ERROR;
|
|
// bind aiq to group
|
ret = camgroup_ctx->cam_group_manager->bind(aiq_ctx->_rkAiqManager.ptr());
|
if (ret) {
|
LOGE("bind sensor %s aiq ctx %p failed !", aiq_ctx->_sensor_entity_name, aiq_ctx);
|
return ret;
|
}
|
|
camgroup_ctx->cam_group_manager->setContainerCtx(camgroup_ctx);
|
|
// bind group to aiq
|
aiq_ctx->_camGroupManager = camgroup_ctx->cam_group_manager.ptr();
|
aiq_ctx->_analyzer->setCamGroupManager(aiq_ctx->_camGroupManager);
|
// set first one as main cam
|
aiq_ctx->_rkAiqManager->setCamGroupManager(aiq_ctx->_camGroupManager,
|
camgroup_ctx->cam_ctxs_num == 0 ? true : false);
|
|
camgroup_ctx->cam_ctxs_num++;
|
camgroup_ctx->cam_ctxs_array[aiq_ctx->_camPhyId] = aiq_ctx;
|
|
LOGD("%s: bind sensor %s aiq ctx success !", aiq_ctx->_sensor_entity_name, aiq_ctx);
|
|
EXIT_XCORE_FUNCTION();
|
#endif
|
|
return XCAM_RETURN_NO_ERROR;
|
}
|
|
static XCamReturn
|
_cam_group_unbind(rk_aiq_camgroup_ctx_t* camgroup_ctx, rk_aiq_sys_ctx_t* aiq_ctx)
|
{
|
#ifdef RKAIQ_ENABLE_CAMGROUP
|
ENTER_XCORE_FUNCTION();
|
|
XCamReturn ret = XCAM_RETURN_NO_ERROR;
|
|
ret = camgroup_ctx->cam_group_manager->unbind(aiq_ctx->_camPhyId);
|
if (ret) {
|
LOGE("unbind sensor %s aiq ctx 0x%x failed !", aiq_ctx->_sensor_entity_name, aiq_ctx);
|
return ret;
|
}
|
aiq_ctx->_camGroupManager = NULL;
|
aiq_ctx->_analyzer->setCamGroupManager(NULL);
|
aiq_ctx->_rkAiqManager->setCamGroupManager(NULL, false);
|
camgroup_ctx->cam_ctxs_array[aiq_ctx->_camPhyId] = NULL;
|
camgroup_ctx->cam_ctxs_num--;
|
|
LOGD("%s: unbind sensor %s aiq ctx success !", aiq_ctx->_sensor_entity_name, aiq_ctx);
|
|
EXIT_XCORE_FUNCTION();
|
#endif
|
|
return XCAM_RETURN_NO_ERROR;
|
}
|
|
rk_aiq_camgroup_ctx_t*
|
rk_aiq_uapi2_camgroup_create(rk_aiq_camgroup_instance_cfg_t* cfg)
|
{
|
#ifdef RKAIQ_ENABLE_CAMGROUP
|
ENTER_XCORE_FUNCTION();
|
|
XCamReturn ret = XCAM_RETURN_NO_ERROR;
|
|
rk_aiq_camgroup_ctx_t* camgroup_ctx = NULL;
|
rk_aiq_sys_ctx_t* aiq_ctx = NULL;
|
std::string single_iq_file;
|
std::string camgroup_iq_file;
|
std::string overlap_map_file;
|
|
camgroup_ctx = new rk_aiq_camgroup_ctx_t();
|
|
if (!camgroup_ctx)
|
goto error;
|
|
camgroup_ctx->cam_group_manager = new RkAiqCamGroupManager();
|
if (!camgroup_ctx->cam_group_manager.ptr())
|
goto error;
|
|
camgroup_ctx->_apiMutex = new Mutex();
|
//RKAIQ_API_SMART_LOCK(camgroup_ctx);
|
|
if (cfg->sns_num > RK_AIQ_CAM_GROUP_MAX_CAMS) {
|
LOGE("nums %s is over the max cams %d !", cfg->sns_num, RK_AIQ_CAM_GROUP_MAX_CAMS);
|
return NULL;
|
}
|
|
camgroup_ctx->cam_type = RK_AIQ_CAM_TYPE_GROUP;
|
camgroup_ctx->cam_ctxs_num = 0;
|
memset(camgroup_ctx->cam_ctxs_array, 0, sizeof(camgroup_ctx->cam_ctxs_array));
|
camgroup_ctx->_srcOverlapMap_s = NULL;
|
camgroup_ctx->_camgroup_calib = NULL;
|
|
if (cfg->config_file_dir) {
|
if (cfg->single_iq_file) {
|
//single_iq_file += cfg->config_file_dir;
|
//single_iq_file += "/";
|
single_iq_file += cfg->single_iq_file;
|
}
|
if (cfg->group_iq_file) {
|
camgroup_iq_file += cfg->config_file_dir;
|
camgroup_iq_file += "/";
|
camgroup_iq_file += cfg->group_iq_file;
|
}
|
if (cfg->overlap_map_file) {
|
overlap_map_file += cfg->config_file_dir;
|
overlap_map_file += "/";
|
overlap_map_file += cfg->overlap_map_file;
|
}
|
}
|
|
if (overlap_map_file.length()) {
|
camgroup_ctx->_srcOverlapMap_s = new RK_PS_SrcOverlapMap();
|
ret = rk_aiq_uapi2_camgroup_getOverlapMap_from_file(overlap_map_file.c_str(),
|
&camgroup_ctx->_srcOverlapMap_s);
|
if (ret) {
|
delete camgroup_ctx->_srcOverlapMap_s;
|
camgroup_ctx->_srcOverlapMap_s = NULL;
|
}
|
}
|
|
for (int i = 0; i < cfg->sns_num; i++) {
|
if (single_iq_file.length())
|
rk_aiq_uapi_sysctl_preInit(cfg->sns_ent_nm_array[i],
|
RK_AIQ_WORKING_MODE_NORMAL, /* nonsense */
|
single_iq_file.c_str());
|
|
if (cfg->pHwEvt_cb)
|
rk_aiq_uapi2_sysctl_regHwEvtCb(cfg->sns_ent_nm_array[i],
|
cfg->pHwEvt_cb,
|
cfg->pHwEvtCbCtx);
|
|
aiq_ctx = rk_aiq_uapi_sysctl_init(cfg->sns_ent_nm_array[i],
|
cfg->config_file_dir, NULL, NULL);
|
if (!aiq_ctx) {
|
LOGE("init aiq ctx %d for %s failed !", i, cfg->sns_ent_nm_array[i]);
|
goto error;
|
}
|
// notify single cam work as multiple mode
|
rk_aiq_uapi_sysctl_setMulCamConc(aiq_ctx, true);
|
|
if (camgroup_ctx->_srcOverlapMap_s) {
|
aiq_ctx->_hw_info.module_rotation =
|
camgroup_ctx->_srcOverlapMap_s->srcOverlapPositon[i];
|
|
// update module rotation info
|
aiq_ctx->_analyzer->setHwInfos(aiq_ctx->_hw_info);
|
}
|
|
ret = _cam_group_bind(camgroup_ctx, aiq_ctx);
|
if (ret) {
|
LOGE("%s: bind sensor %s aiq ctx 0x%x failed !",
|
__func__, aiq_ctx->_sensor_entity_name, aiq_ctx);
|
goto error;
|
}
|
}
|
|
if (camgroup_iq_file.length())
|
camgroup_ctx->_camgroup_calib = RkAiqCalibDbV2::createCalibDbCamgroup(camgroup_iq_file.c_str());
|
|
ret = camgroup_ctx->cam_group_manager->setCamgroupCalib(camgroup_ctx->_camgroup_calib);
|
if (ret) {
|
LOGE("%s: set camgroup calib failed !", __func__);
|
goto error;
|
}
|
ret = camgroup_ctx->cam_group_manager->init();
|
if (ret) {
|
LOGE("%s: init failed !", __func__);
|
goto error;
|
}
|
|
LOGD("%s: create camgroup 0x%x success !", __func__, camgroup_ctx);
|
|
EXIT_XCORE_FUNCTION();
|
|
return camgroup_ctx;
|
|
error:
|
LOGE("%s failed", __func__);
|
if (camgroup_ctx)
|
rk_aiq_uapi2_camgroup_destroy(camgroup_ctx);
|
#endif
|
return NULL;
|
}
|
|
struct RK_PS_SrcOverlapMap*
|
rk_aiq_uapi2_camgroup_getOverlapMap(rk_aiq_camgroup_ctx_t* camgroup_ctx)
|
{
|
#ifdef RKAIQ_ENABLE_CAMGROUP
|
if (camgroup_ctx->_srcOverlapMap_s)
|
return camgroup_ctx->_srcOverlapMap_s;
|
else
|
return NULL;
|
#else
|
return NULL;
|
#endif
|
}
|
|
XCamReturn
|
rk_aiq_uapi2_camgroup_getOverlapMap_from_file(const char* map_file, struct RK_PS_SrcOverlapMap** overlapMap)
|
{
|
#ifdef RKAIQ_ENABLE_CAMGROUP
|
FILE *fp2 = fopen(map_file, "rb");
|
|
if (fp2) {
|
fread(*overlapMap, sizeof(RK_PS_SrcOverlapMap), 1, fp2);
|
fclose(fp2);
|
return XCAM_RETURN_NO_ERROR;
|
} else {
|
LOGE("get overlap data from %s error!", map_file);
|
return XCAM_RETURN_ERROR_FAILED;
|
}
|
#else
|
return XCAM_RETURN_ERROR_FAILED;
|
#endif
|
}
|
|
rk_aiq_sys_ctx_t*
|
rk_aiq_uapi2_camgroup_getAiqCtxBySnsNm(rk_aiq_camgroup_ctx_t* camgroup_ctx, const char* sns_entity_name)
|
{
|
#ifdef RKAIQ_ENABLE_CAMGROUP
|
ENTER_XCORE_FUNCTION();
|
|
RKAIQ_API_SMART_LOCK(camgroup_ctx);
|
|
for (int i = 0; i < RK_AIQ_CAM_GROUP_MAX_CAMS; i++) {
|
if (camgroup_ctx->cam_ctxs_array[i]) {
|
if (strcmp(camgroup_ctx->cam_ctxs_array[i]->_sensor_entity_name, sns_entity_name) == 0) {
|
LOGD("%s: get sensor %s aiq ctx 0x%x success !",
|
__func__, sns_entity_name, camgroup_ctx->cam_ctxs_array[i]);
|
return camgroup_ctx->cam_ctxs_array[i];
|
}
|
}
|
}
|
|
LOGD("%s: get sensor %s aiq ctx failed !", __func__, sns_entity_name);
|
|
EXIT_XCORE_FUNCTION();
|
#endif
|
|
return NULL;
|
|
}
|
|
XCamReturn
|
rk_aiq_uapi2_camgroup_bind(rk_aiq_camgroup_ctx_t* camgroup_ctx, rk_aiq_sys_ctx_t** ctx, int num)
|
{
|
#ifdef RKAIQ_ENABLE_CAMGROUP
|
ENTER_XCORE_FUNCTION();
|
|
XCamReturn ret = XCAM_RETURN_NO_ERROR;
|
|
RKAIQ_API_SMART_LOCK(camgroup_ctx);
|
|
if (camgroup_ctx->cam_ctxs_num + num > RK_AIQ_CAM_GROUP_MAX_CAMS) {
|
LOGE("binded num %d + num %d > max %d !", camgroup_ctx->cam_ctxs_num, num, RK_AIQ_CAM_GROUP_MAX_CAMS);
|
return XCAM_RETURN_ERROR_OUTOFRANGE;
|
}
|
|
for (int j = 0; j < num; j++) {
|
// query bind status firstly
|
bool need_bind = true;
|
for (int i = 0; i < RK_AIQ_CAM_GROUP_MAX_CAMS; i++) {
|
if (camgroup_ctx->cam_ctxs_array[i] == ctx[j]) {
|
LOGI("already binded for ctx 0x%x", ctx[j]);
|
need_bind = false;
|
break;
|
}
|
}
|
// find a empty slot
|
if (need_bind) {
|
for (int i = 0; i < RK_AIQ_CAM_GROUP_MAX_CAMS; i++) {
|
if (camgroup_ctx->cam_ctxs_array[i] == NULL) {
|
ret = _cam_group_bind(camgroup_ctx, ctx[j]);
|
if (ret) {
|
LOGE("%s: bind sensor %s aiq ctx 0x%x failed !",
|
__func__, ctx[j]->_sensor_entity_name, ctx[j]);
|
break;
|
}
|
}
|
}
|
}
|
}
|
|
LOGD("%s: bind sensor aiq ctxs success !", __func__);
|
|
EXIT_XCORE_FUNCTION();
|
#endif
|
|
return XCAM_RETURN_NO_ERROR;
|
}
|
|
XCamReturn
|
rk_aiq_uapi2_camgroup_unbind(rk_aiq_camgroup_ctx_t* camgroup_ctx, rk_aiq_sys_ctx_t** ctx, int num)
|
{
|
#ifdef RKAIQ_ENABLE_CAMGROUP
|
ENTER_XCORE_FUNCTION();
|
|
RKAIQ_API_SMART_LOCK(camgroup_ctx);
|
|
for (int j = 0; j < num; j++) {
|
for (int i = 0; i < RK_AIQ_CAM_GROUP_MAX_CAMS; i++) {
|
if (camgroup_ctx->cam_ctxs_array[i] == ctx[j]) {
|
if (_cam_group_unbind(camgroup_ctx, ctx[j])) {
|
LOGE("%s: unbind sensor %s aiq ctx 0x%x failed !",
|
__func__, ctx[j]->_sensor_entity_name, ctx[j]);
|
break;
|
}
|
}
|
}
|
}
|
|
LOGD("%s: unbind sensor aiq ctxs success !", __func__);
|
|
EXIT_XCORE_FUNCTION();
|
#endif
|
|
return XCAM_RETURN_NO_ERROR;
|
}
|
|
XCamReturn
|
rk_aiq_uapi2_camgroup_prepare(rk_aiq_camgroup_ctx_t* camgroup_ctx, rk_aiq_working_mode_t mode)
|
{
|
#ifdef RKAIQ_ENABLE_CAMGROUP
|
ENTER_XCORE_FUNCTION();
|
|
XCamReturn ret = XCAM_RETURN_NO_ERROR;
|
|
RKAIQ_API_SMART_LOCK(camgroup_ctx);
|
|
for (int i = 0; i < RK_AIQ_CAM_GROUP_MAX_CAMS; i++) {
|
rk_aiq_sys_ctx_t* aiq_ctx = camgroup_ctx->cam_ctxs_array[i];
|
if (aiq_ctx) {
|
ret = rk_aiq_uapi_sysctl_prepare(aiq_ctx, 0, 0, mode);
|
if (ret) {
|
LOGE("%s: prepare failed for aiq ctx 0x%x !", __func__, aiq_ctx);
|
continue;
|
}
|
}
|
}
|
|
ret = camgroup_ctx->cam_group_manager->prepare();
|
if (ret) {
|
LOGE("%s: prepare failed !", __func__);
|
return ret;
|
}
|
|
LOGD("%s: prepare camgroup success !", __func__);
|
|
EXIT_XCORE_FUNCTION();
|
#endif
|
|
return XCAM_RETURN_NO_ERROR;
|
}
|
|
XCamReturn
|
rk_aiq_uapi2_camgroup_start(rk_aiq_camgroup_ctx_t* camgroup_ctx)
|
{
|
#ifdef RKAIQ_ENABLE_CAMGROUP
|
ENTER_XCORE_FUNCTION();
|
|
XCamReturn ret = XCAM_RETURN_NO_ERROR;
|
|
RKAIQ_API_SMART_LOCK(camgroup_ctx);
|
|
ret = camgroup_ctx->cam_group_manager->start();
|
if (ret) {
|
LOGE("%s: start failed !", __func__);
|
return ret;
|
}
|
|
for (int i = 0; i < RK_AIQ_CAM_GROUP_MAX_CAMS; i++) {
|
rk_aiq_sys_ctx_t* aiq_ctx = camgroup_ctx->cam_ctxs_array[i];
|
if (aiq_ctx) {
|
ret = rk_aiq_uapi_sysctl_start(aiq_ctx);
|
if (ret) {
|
LOGE("%s: start failed for aiq ctx 0x%x !", __func__, aiq_ctx);
|
continue;
|
}
|
}
|
}
|
|
LOGD("%s: start camgroup success !", __func__);
|
|
EXIT_XCORE_FUNCTION();
|
#endif
|
|
return XCAM_RETURN_NO_ERROR;
|
}
|
|
XCamReturn
|
rk_aiq_uapi2_camgroup_stop(rk_aiq_camgroup_ctx_t* camgroup_ctx)
|
{
|
#ifdef RKAIQ_ENABLE_CAMGROUP
|
ENTER_XCORE_FUNCTION();
|
|
XCamReturn ret = XCAM_RETURN_NO_ERROR;
|
|
RKAIQ_API_SMART_LOCK(camgroup_ctx);
|
|
ret = camgroup_ctx->cam_group_manager->stop();
|
if (ret) {
|
LOGE("%s: stop failed !", __func__);
|
return ret;
|
}
|
|
for (int i = 0; i < RK_AIQ_CAM_GROUP_MAX_CAMS; i++) {
|
rk_aiq_sys_ctx_t* aiq_ctx = camgroup_ctx->cam_ctxs_array[i];
|
if (aiq_ctx) {
|
ret = rk_aiq_uapi_sysctl_stop(aiq_ctx, false);
|
if (ret) {
|
LOGE("%s: stop failed for aiq ctx 0x%x !", __func__, aiq_ctx);
|
continue;
|
}
|
}
|
}
|
|
LOGD("%s: stop camgroup success !", __func__);
|
|
EXIT_XCORE_FUNCTION();
|
#endif
|
|
return XCAM_RETURN_NO_ERROR;
|
|
}
|
|
XCamReturn
|
rk_aiq_uapi2_camgroup_destroy(rk_aiq_camgroup_ctx_t* camgroup_ctx)
|
{
|
#ifdef RKAIQ_ENABLE_CAMGROUP
|
ENTER_XCORE_FUNCTION();
|
|
XCamReturn ret = XCAM_RETURN_NO_ERROR;
|
{
|
RKAIQ_API_SMART_LOCK(camgroup_ctx);
|
for (int i = 0; i < RK_AIQ_CAM_GROUP_MAX_CAMS; i++) {
|
rk_aiq_sys_ctx_t* aiq_ctx = camgroup_ctx->cam_ctxs_array[i];
|
if (aiq_ctx) {
|
ret = _cam_group_unbind(camgroup_ctx, aiq_ctx);
|
if (ret) {
|
LOGE("%s: unbind sensor %s aiq ctx 0x%x failed !",
|
__func__, aiq_ctx->_sensor_entity_name, aiq_ctx);
|
continue;
|
}
|
rk_aiq_uapi_sysctl_deinit(aiq_ctx);
|
}
|
}
|
|
if (camgroup_ctx->cam_ctxs_num > 0) {
|
LOGE("impossible case, some aiq ctx may not deinit !");
|
}
|
ret = camgroup_ctx->cam_group_manager->deInit();
|
if (ret) {
|
LOGE("%s: deinit failed !", __func__);
|
return ret;
|
}
|
camgroup_ctx->cam_group_manager.release();
|
}
|
if (camgroup_ctx->_camgroup_calib) {
|
RkAiqCalibDbV2::CamCalibDbCamgroupFree(camgroup_ctx->_camgroup_calib);
|
}
|
if (camgroup_ctx->_srcOverlapMap_s)
|
delete camgroup_ctx->_srcOverlapMap_s;
|
camgroup_ctx->_apiMutex.release();
|
delete camgroup_ctx;
|
|
LOGD("%s: destroy camgroup success !", __func__);
|
|
EXIT_XCORE_FUNCTION();
|
#endif
|
|
return XCAM_RETURN_NO_ERROR;
|
}
|
|
XCamReturn
|
rk_aiq_uapi2_camgroup_getCamInfos(rk_aiq_camgroup_ctx_t* camgroup_ctx, rk_aiq_camgroup_camInfos_t* camInfos)
|
{
|
#ifdef RKAIQ_ENABLE_CAMGROUP
|
ENTER_XCORE_FUNCTION();
|
|
XCamReturn ret = XCAM_RETURN_NO_ERROR;
|
{
|
RKAIQ_API_SMART_LOCK(camgroup_ctx);
|
if (!camInfos) {
|
LOGE("null params !");
|
return XCAM_RETURN_ERROR_PARAM;
|
}
|
|
camInfos->valid_sns_num = camgroup_ctx->cam_ctxs_num;
|
|
for (int i = 0, j = 0; i < RK_AIQ_CAM_GROUP_MAX_CAMS; i++) {
|
rk_aiq_sys_ctx_t* aiq_ctx = camgroup_ctx->cam_ctxs_array[i];
|
|
if (aiq_ctx) {
|
camInfos->sns_ent_nm[j] = aiq_ctx->_sensor_entity_name;
|
camInfos->sns_camPhyId[j] = aiq_ctx->_camPhyId;
|
j++;
|
}
|
}
|
}
|
EXIT_XCORE_FUNCTION();
|
#endif
|
|
return XCAM_RETURN_NO_ERROR;
|
}
|