ss928_framework/libapi/ive/libapi_ive_gmm2.c

688 lines
28 KiB
C
Raw Permalink Normal View History

2024-12-16 13:31:45 +08:00
/*
Copyright (c), 2001-2022, Shenshu Tech. Co., Ltd.
*/
#include "libapi_common_ive.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <signal.h>
#include <semaphore.h>
#include <pthread.h>
#include <limits.h>
#define OT_MACRO_IVE_SRC_NUM 2
#define OT_MACRO_IVE_GMM2_QUERY_SLEEP 100
#define OT_MACRO_IVE_GMM2_FIRST_FRMAE_NUM 500
#define OT_MACRO_IVE_GMM2_MAX_CCL_REGION 60
#define OT_MACRO_IVE_GMM2_UPDATA_FACTOR_VAL1 16
#define OT_MACRO_IVE_GMM2_UPDATA_FACTOR_VAL2 200
#define OT_MACRO_IVE_GMM2_CHANGE_FACTOR_VAL1 20
#define OT_MACRO_IVE_GMM2_CHANGE_FACTOR_VAL2 200
#define OT_MACRO_IVE_GMM2_CREATE_FACTOR_VAL1 8
#define OT_MACRO_IVE_GMM2_CREATE_FACTOR_VAL2 4
#define OT_MACRO_IVE_GMM2_MAX_GRAD_SUM 10
#define OT_MACRO_IVE_GMM2_RATIO_BETWEEN_GRAD_AND_FG 100
#define OT_MACRO_IVE_16BIT_TO_8BIT_NUM 255
#define OT_MACRO_IVE_16BIT_TO_8BIT_DEN (255 * 4)
#define OT_MACRO_IVE_CCL_STEP 2
#define OT_MACRO_IVE_CCL_INIT_AREA_THR 4
#define OT_MACRO_IVE_GMM2_THRESH_LOW_THR 5
#define OT_MACRO_IVE_GMM2_NUM_TWO 2
#define OT_MACRO_IVE_GMM2_MODEL_NUM 3
#define OT_MACRO_IVE_GMM2_MAX_VAR ((16 * 16)<<7)
#define OT_MACRO_IVE_GMM2_MIN_VAR ((8 * 8)<<7)
#define OT_MACRO_IVE_GMM2_GLB_SNS_FACTOR 8
#define OT_MACRO_IVE_GMM2_FREQ_HTR 12000
#define OT_MACRO_IVE_GMM2_FREQ_INIT_VAL 20000
#define OT_MACRO_IVE_GMM2_LIFT_THR 500
#define OT_MACRO_IVE_GMM2_NUM_THREE 3
#define OT_MACRO_IVE_GMM2_CHANGE_FACTOR_ABS_THRESHOLD 10
#define OT_MACRO_IVE_GMM2_FACTOR_MAX_VAL 8
#define OT_MACRO_IVE_GMM2_NUM_TWO 2
#define OT_MACRO_IVE_GMM2_CIF_WIDTH 352
#define OT_MACRO_IVE_GMM2_CIF_HEIGHT 288
#define OT_MACRO_IVE_TOTAL_FRAME 700
typedef struct {
ot_svp_src_img src[OT_MACRO_IVE_SRC_NUM];
ot_svp_dst_img fg;
ot_svp_dst_img bg;
ot_svp_src_img factor;
ot_svp_dst_img match_model_info;
ot_svp_src_img fg_mask;
ot_svp_src_img last_image;
ot_svp_dst_img diff_image;
ot_svp_dst_img mag_image;
ot_svp_dst_img cur_norm_mag;
ot_svp_dst_img last_norm_mag;
ot_svp_dst_mem_info model;
ot_svp_dst_mem_info blob;
ot_ive_gmm2_ctrl gmm2_ctrl;
FILE *fp_src;
FILE *fp_fg;
FILE *fp_bg;
} ot_struct_ive_gmm2_info;
static ot_struct_ive_gmm2_info g_gmm2_info;
static td_bool g_stop_signal = TD_FALSE;
/*
* gmm2 uninit
*/
static td_void _ive_gmm2_uninit(ot_struct_ive_gmm2_info *gmm2)
{
td_u16 i;
macro_svp_check_exps_return_void(gmm2 == TD_NULL, ENUM_SVP_ERR_LEVEL_ERROR, "gmm2 can't be null\n");
for (i = 0; i < OT_MACRO_IVE_SRC_NUM; i++) {
macro_svp_mmz_free(gmm2->src[i].phys_addr[0], gmm2->src[i].virt_addr[0]);
}
macro_svp_mmz_free(gmm2->fg.phys_addr[0], gmm2->fg.virt_addr[0]);
macro_svp_mmz_free(gmm2->bg.phys_addr[0], gmm2->bg.virt_addr[0]);
macro_svp_mmz_free(gmm2->factor.phys_addr[0], gmm2->factor.virt_addr[0]);
macro_svp_mmz_free(gmm2->match_model_info.phys_addr[0], gmm2->match_model_info.virt_addr[0]);
macro_svp_mmz_free(gmm2->fg_mask.phys_addr[0], gmm2->fg_mask.virt_addr[0]);
macro_svp_mmz_free(gmm2->diff_image.phys_addr[0], gmm2->diff_image.virt_addr[0]);
macro_svp_mmz_free(gmm2->mag_image.phys_addr[0], gmm2->mag_image.virt_addr[0]);
macro_svp_mmz_free(gmm2->cur_norm_mag.phys_addr[0], gmm2->cur_norm_mag.virt_addr[0]);
macro_svp_mmz_free(gmm2->last_norm_mag.phys_addr[0], gmm2->last_norm_mag.virt_addr[0]);
macro_svp_mmz_free(gmm2->model.phys_addr, gmm2->model.virt_addr);
macro_svp_mmz_free(gmm2->blob.phys_addr, gmm2->blob.virt_addr);
macro_svp_close_file(gmm2->fp_src);
macro_svp_close_file(gmm2->fp_fg);
macro_svp_close_file(gmm2->fp_bg);
}
/*
* function: create gmm2 image memory
*/
static td_s32 _ive_gmm2_create_image(ot_struct_ive_gmm2_info *gmm2, ot_size pic_size)
{
td_s32 ret;
td_u16 i, j;
td_u8 *tmp_ptr = TD_NULL;
(td_void)memset_s(gmm2, sizeof(ot_struct_ive_gmm2_info), 0, sizeof(ot_struct_ive_gmm2_info));
for (i = 0; i < OT_MACRO_IVE_SRC_NUM; i++) {
ret = libapi_common_ive_create_image(&(gmm2->src[i]), OT_SVP_IMG_TYPE_U8C1, pic_size.width, pic_size.height);
macro_svp_check_exps_return(ret != TD_SUCCESS, ret, ENUM_SVP_ERR_LEVEL_ERROR,
"Error(%#x),Create src[%d] image failed!\n", ret, i);
}
ret = libapi_common_ive_create_image(&(gmm2->fg), OT_SVP_IMG_TYPE_U8C1, pic_size.width, pic_size.height);
macro_svp_check_exps_return(ret != TD_SUCCESS, ret, ENUM_SVP_ERR_LEVEL_ERROR,
"Error(%#x),Create fg image failed!\n", ret);
ret = libapi_common_ive_create_image(&(gmm2->bg), OT_SVP_IMG_TYPE_U8C1, pic_size.width, pic_size.height);
macro_svp_check_exps_return(ret != TD_SUCCESS, ret, ENUM_SVP_ERR_LEVEL_ERROR,
"Error(%#x),Create bg image failed!\n", ret);
ret = libapi_common_ive_create_image(&(gmm2->factor), OT_SVP_IMG_TYPE_U16C1, pic_size.width, pic_size.height);
macro_svp_check_exps_return(ret != TD_SUCCESS, ret, ENUM_SVP_ERR_LEVEL_ERROR,
"Error(%#x),Create factor image failed!\n", ret);
tmp_ptr = macro_svp_convert_addr_to_ptr(td_u8, gmm2->factor.virt_addr[0]);
for (i = 0; i < gmm2->factor.height; i++) {
for (j = 0; j < gmm2->factor.width; j++) {
tmp_ptr[OT_MACRO_IVE_GMM2_NUM_TWO * j] = OT_MACRO_IVE_GMM2_CREATE_FACTOR_VAL1;
tmp_ptr[OT_MACRO_IVE_GMM2_NUM_TWO * j + 1] = OT_MACRO_IVE_GMM2_CREATE_FACTOR_VAL2;
}
tmp_ptr += gmm2->factor.stride[0] * sizeof(td_u16);
}
ret = libapi_common_ive_create_image(&(gmm2->match_model_info), OT_SVP_IMG_TYPE_U8C1,
pic_size.width, pic_size.height);
macro_svp_check_exps_return(ret != TD_SUCCESS, ret, ENUM_SVP_ERR_LEVEL_ERROR,
"Error(%#x),Create match_model image failed!\n", ret);
ret = libapi_common_ive_create_image(&(gmm2->fg_mask), OT_SVP_IMG_TYPE_U8C1, pic_size.width, pic_size.height);
macro_svp_check_exps_return(ret != TD_SUCCESS, ret, ENUM_SVP_ERR_LEVEL_ERROR,
"Error(%#x),Create fg_mask image failed!\n", ret);
ret = libapi_common_ive_create_image(&(gmm2->diff_image), OT_SVP_IMG_TYPE_U8C1, pic_size.width, pic_size.height);
macro_svp_check_exps_return(ret != TD_SUCCESS, ret, ENUM_SVP_ERR_LEVEL_ERROR,
"Error(%#x),Create diff_image failed!\n", ret);
ret = libapi_common_ive_create_image(&(gmm2->mag_image), OT_SVP_IMG_TYPE_U16C1, pic_size.width, pic_size.height);
macro_svp_check_exps_return(ret != TD_SUCCESS, ret, ENUM_SVP_ERR_LEVEL_ERROR,
"Error(%#x),Create mag_image failed!\n", ret);
ret = libapi_common_ive_create_image(&(gmm2->cur_norm_mag), OT_SVP_IMG_TYPE_U8C1, pic_size.width, pic_size.height);
macro_svp_check_exps_return(ret != TD_SUCCESS, ret, ENUM_SVP_ERR_LEVEL_ERROR,
"Error(%#x),Create cur_nor_mag image failed!\n", ret);
ret = libapi_common_ive_create_image(&(gmm2->last_norm_mag), OT_SVP_IMG_TYPE_U8C1, pic_size.width, pic_size.height);
macro_svp_check_exps_return(ret != TD_SUCCESS, ret, ENUM_SVP_ERR_LEVEL_ERROR,
"Error(%#x),Create last_nor_mag image failed!\n", ret);
return ret;
}
/*
* set gmm2 ctrl info
*/
static td_void _ive_gmm2_set_ctrl_info(ot_struct_ive_gmm2_info *gmm2)
{
gmm2->gmm2_ctrl.var_rate = 1;
gmm2->gmm2_ctrl.model_num = OT_MACRO_IVE_GMM2_MODEL_NUM;
gmm2->gmm2_ctrl.max_var = OT_MACRO_IVE_GMM2_MAX_VAR;
gmm2->gmm2_ctrl.min_var = OT_MACRO_IVE_GMM2_MIN_VAR;
gmm2->gmm2_ctrl.global_sns_factor = OT_MACRO_IVE_GMM2_GLB_SNS_FACTOR;
gmm2->gmm2_ctrl.sns_factor_mode = OT_IVE_GMM2_SNS_FACTOR_MODE_PIXEL;
gmm2->gmm2_ctrl.freq_threshold = OT_MACRO_IVE_GMM2_FREQ_HTR;
gmm2->gmm2_ctrl.freq_init_val = OT_MACRO_IVE_GMM2_FREQ_INIT_VAL;
gmm2->gmm2_ctrl.freq_add_factor = 0xEF;
gmm2->gmm2_ctrl.freq_reduce_factor = 0xFF00;
gmm2->gmm2_ctrl.life_threshold = OT_MACRO_IVE_GMM2_LIFT_THR;
gmm2->gmm2_ctrl.life_update_factor_mode = OT_IVE_GMM2_LIFE_UPDATE_FACTOR_MODE_GLOBAL;
}
/*
* function: init gmm2 data
*/
static td_s32 _ive_gmm2_init(ot_struct_ive_gmm2_info *gmm2, ot_size pic_size)
{
td_s32 ret = OT_ERR_IVE_NULL_PTR;
td_u32 size;
td_char path[PATH_MAX] = {0};
const td_char *src_file = "./gmm2_352x288_sp400_frm1000.yuv";
macro_svp_check_exps_return(gmm2 == TD_NULL, ret, ENUM_SVP_ERR_LEVEL_ERROR, "gmm2 can't be null\n");
macro_svp_check_exps_return((strlen(src_file) > PATH_MAX) || (realpath(src_file, path) == TD_NULL),
OT_ERR_IVE_ILLEGAL_PARAM, ENUM_SVP_ERR_LEVEL_ERROR, "invalid file!\n");
/* create img memory */
ret = _ive_gmm2_create_image(gmm2, pic_size);
macro_svp_check_exps_goto(ret != TD_SUCCESS, fail, ENUM_SVP_ERR_LEVEL_ERROR,
"_ive_gmm2_create_image failed\n");
/* set gmm2 ctrl info */
_ive_gmm2_set_ctrl_info(gmm2);
/* create gmm2 model and blob mem_info */
size = gmm2->gmm2_ctrl.model_num * sizeof(td_u64) * gmm2->src[0].width * gmm2->src[0].height;
ret = libapi_common_ive_create_mem_info(&gmm2->model, size);
macro_svp_check_exps_goto(ret != TD_SUCCESS, fail, ENUM_SVP_ERR_LEVEL_ERROR,
"Error(%#x),Create model mem info failed!\n", ret);
(td_void)memset_s(macro_svp_convert_addr_to_ptr(td_void, gmm2->model.virt_addr),
gmm2->model.size, 0, gmm2->model.size);
size = sizeof(ot_ive_ccblob);
ret = libapi_common_ive_create_mem_info(&gmm2->blob, size);
macro_svp_check_exps_goto(ret != TD_SUCCESS, fail, ENUM_SVP_ERR_LEVEL_ERROR,
"Error(%#x),Create blob mem info failed!\n", ret);
/* open src file */
ret = TD_FAILURE;
gmm2->fp_src = fopen(path, "rb");
macro_svp_check_exps_goto(gmm2->fp_src == TD_NULL, fail, ENUM_SVP_ERR_LEVEL_ERROR, "Open file failed!\n");
/* open fg file */
macro_svp_check_exps_goto(realpath("./", path) == TD_NULL, fail,
ENUM_SVP_ERR_LEVEL_ERROR, "invalid path\n");
ret = strcat_s(path, PATH_MAX, "/fg_352x288_sp400.yuv");
macro_svp_check_exps_goto(ret != EOK, fail, ENUM_SVP_ERR_LEVEL_ERROR, "strcat_s failed!\n");
ret = TD_FAILURE;
gmm2->fp_fg = fopen(path, "wb");
macro_svp_check_exps_goto(gmm2->fp_fg == TD_NULL, fail, ENUM_SVP_ERR_LEVEL_ERROR, "Open file failed!\n");
/* openc bg file */
macro_svp_check_exps_goto(realpath("./", path) == TD_NULL, fail,
ENUM_SVP_ERR_LEVEL_ERROR, "invalid path\n");
ret = strcat_s(path, PATH_MAX, "/bg_352x288_sp400.yuv");
macro_svp_check_exps_goto(ret != EOK, fail, ENUM_SVP_ERR_LEVEL_ERROR, "strcat_s failed!\n");
ret = TD_FAILURE;
gmm2->fp_bg = fopen(path, "wb");
macro_svp_check_exps_goto(gmm2->fp_bg == TD_NULL, fail, ENUM_SVP_ERR_LEVEL_ERROR,
"Error,Open file %s failed!\n", path);
return TD_SUCCESS;
fail:
_ive_gmm2_uninit(gmm2);
return ret;
}
static td_s32 _ive_gen_fg_mask(ot_svp_src_img *fg, ot_svp_dst_img *mask)
{
td_s32 ret;
ot_ive_handle handle;
ot_ive_threshold_ctrl ctrl;
ctrl.mode = OT_IVE_THRESHOLD_MODE_BINARY;
ctrl.min_val = 0;
ctrl.max_val = 1;
ctrl.low_threshold = OT_MACRO_IVE_GMM2_THRESH_LOW_THR;
ret = ss_mpi_ive_threshold(&handle, fg, mask, &ctrl, TD_FALSE);
macro_svp_check_exps_return(ret != TD_SUCCESS, ret, ENUM_SVP_ERR_LEVEL_ERROR,
"Error(%#x),ss_mpi_ive_thresh failed!\n", ret);
return ret;
}
/*
* Reduce the factor gradually to the default value
*/
static td_void _ive_reduce_factor(ot_svp_img *factor)
{
td_u16 i, j;
td_u8 *tmp_ptr = TD_NULL;
tmp_ptr = macro_svp_convert_addr_to_ptr(td_u8, factor->virt_addr[0]);
for (i = 0; i < factor->height; i++) {
for (j = 0; j < factor->width; j++) {
tmp_ptr[j << 1] = ot_macro_ive_max(OT_MACRO_IVE_GMM2_FACTOR_MAX_VAL, tmp_ptr[i << 1] - 1);
tmp_ptr[(i << 1) + 1] = ot_macro_ive_max(OT_MACRO_IVE_GMM2_FACTOR_MAX_VAL, tmp_ptr[(i << 1) + 1] -
OT_MACRO_IVE_GMM2_NUM_TWO);
}
tmp_ptr += factor->stride[0] * sizeof(td_u16);
}
}
/*
* Change factor by difference frame
*/
static td_bool _ive_change_factor_by_diff_frame(ot_svp_src_img *src_img,
ot_svp_src_img *last_img, ot_svp_dst_img *diff_img, ot_svp_dst_img *factor)
{
td_s32 ret;
ot_ive_handle handle;
td_bool is_finish = TD_FALSE;
td_bool is_block = TD_TRUE;
td_u16 i, j;
const td_s32 abs_thr = OT_MACRO_IVE_GMM2_CHANGE_FACTOR_ABS_THRESHOLD;
td_u32 point_sum = 0;
ot_ive_sub_ctrl sub_ctrl;
td_u8 *tmp_ptr = TD_NULL;
td_u8 *factor_ptr = TD_NULL;
sub_ctrl.mode = OT_IVE_SUB_MODE_ABS;
ret = ss_mpi_ive_sub(&handle, src_img, last_img, diff_img, &sub_ctrl, TD_TRUE);
macro_svp_check_exps_return(ret != TD_SUCCESS, TD_FALSE, ENUM_SVP_ERR_LEVEL_ERROR,
"Error(%#x),ss_mpi_ive_sub failed!\n", ret);
/* Wait task finish */
ret = ss_mpi_ive_query(handle, &is_finish, is_block);
while (ret == OT_ERR_IVE_QUERY_TIMEOUT) {
usleep(OT_MACRO_IVE_GMM2_QUERY_SLEEP);
ret = ss_mpi_ive_query(handle, &is_finish, is_block);
}
macro_svp_check_exps_return(ret != TD_SUCCESS, TD_FALSE, ENUM_SVP_ERR_LEVEL_ERROR,
"Error(%#x),ss_mpi_ive_query failed!\n", ret);
tmp_ptr = macro_svp_convert_addr_to_ptr(td_u8, diff_img->virt_addr[0]);
for (i = 0; i < src_img->height; i++) {
for (j = 0; j < src_img->width; j++) {
point_sum += (tmp_ptr[j] > abs_thr);
}
tmp_ptr += diff_img->stride[0];
}
if ((point_sum * OT_MACRO_IVE_GMM2_NUM_THREE) <= (src_img->width * src_img->height * OT_MACRO_IVE_GMM2_NUM_TWO)) {
return TD_FALSE;
}
tmp_ptr = macro_svp_convert_addr_to_ptr(td_u8, diff_img->virt_addr[0]);
factor_ptr = macro_svp_convert_addr_to_ptr(td_u8, factor->virt_addr[0]);
for (i = 0; i < src_img->height; i++) {
for (j = 0; j < src_img->width; j++) {
if (tmp_ptr[j] > abs_thr) {
factor_ptr[j << 1] = OT_MACRO_IVE_GMM2_CHANGE_FACTOR_VAL1;
factor_ptr[(j << 1) + 1] = OT_MACRO_IVE_GMM2_CHANGE_FACTOR_VAL2;
}
}
tmp_ptr += diff_img->stride[0];
factor_ptr += factor->stride[0] * sizeof(td_u16);
}
return TD_TRUE;
}
static td_s32 _ive_set_ctrl_info(ot_ive_ccl_ctrl *ccl_ctrl, ot_ive_mag_and_ang_ctrl *mag_and_ang_ctrl,
ot_ive_16bit_to_8bit_ctrl *ctrl_16to8bit, ot_ive_sub_ctrl *sub_ctrl)
{
td_s32 ret;
td_s8 mask[OT_IVE_MASK_NUM] = { 0, 0, 0, 0, 0, 0, -1, 0, 1, 0, 0, -2, 0, 2, 0, 0, -1, 0, 1, 0, 0, 0, 0, 0, 0 };
/* set ccl ctrl info */
ccl_ctrl->mode = OT_IVE_CCL_MODE_8C;
ccl_ctrl->step = OT_MACRO_IVE_CCL_STEP;
ccl_ctrl->init_area_threshold = OT_MACRO_IVE_CCL_INIT_AREA_THR;
/* set mag_and_ang ctrl info */
ret = memcpy_s(mag_and_ang_ctrl->mask, OT_IVE_MASK_NUM, mask, OT_IVE_MASK_NUM);
macro_svp_check_exps_return(ret != EOK, OT_ERR_IVE_ILLEGAL_PARAM, ENUM_SVP_ERR_LEVEL_ERROR,
"memcpy_s mask failed!\n");
mag_and_ang_ctrl->threshold = 0;
mag_and_ang_ctrl->out_ctrl = OT_IVE_MAG_AND_ANG_OUT_CTRL_MAG;
/* set 16bit_to_8bit ctrl info */
ctrl_16to8bit->bias = 0;
ctrl_16to8bit->mode = OT_IVE_16BIT_TO_8BIT_MODE_U16_TO_U8;
ctrl_16to8bit->num = OT_MACRO_IVE_16BIT_TO_8BIT_NUM;
ctrl_16to8bit->denominator = OT_MACRO_IVE_16BIT_TO_8BIT_DEN;
/* set sub ctrl info */
sub_ctrl->mode = OT_IVE_SUB_MODE_ABS;
return TD_SUCCESS;
}
static td_s32 _ive_calc_grad_diff_bewteen_img(ot_struct_ive_gmm2_info *gmm2, td_s32 cur_idx)
{
td_s32 ret;
td_bool is_finish = TD_FALSE;
td_bool is_block = TD_TRUE;
ot_ive_handle handle;
ot_ive_ccl_ctrl ccl_ctrl;
ot_ive_ccblob *ccl_blob = TD_NULL;
ot_ive_mag_and_ang_ctrl mag_and_ang_ctrl;
ot_ive_16bit_to_8bit_ctrl ctrl_16to8bit;
ot_ive_sub_ctrl sub_ctrl;
ret = _ive_set_ctrl_info(&ccl_ctrl, &mag_and_ang_ctrl, &ctrl_16to8bit, &sub_ctrl);
macro_svp_check_exps_return(ret != TD_SUCCESS, ret, ENUM_SVP_ERR_LEVEL_ERROR, "ive_set_ctrl_info failed!\n");
ret = ss_mpi_ive_ccl(&handle, &gmm2->fg_mask, &gmm2->blob, &ccl_ctrl, TD_TRUE);
macro_svp_check_failed_err_level_return(ret, ret, "Error(%#x),ss_mpi_ive_ccl failed!\n", ret);
/* Wait task finish */
ret = ss_mpi_ive_query(handle, &is_finish, is_block);
while (ret == OT_ERR_IVE_QUERY_TIMEOUT) {
usleep(OT_MACRO_IVE_GMM2_QUERY_SLEEP);
ret = ss_mpi_ive_query(handle, &is_finish, is_block);
}
macro_svp_check_failed_err_level_return(ret, ret, "Error(%#x),ss_mpi_ive_query failed!\n", ret);
ccl_blob = macro_svp_convert_addr_to_ptr(ot_ive_ccblob, gmm2->blob.virt_addr);
if (ccl_blob->info.bits.rgn_num > 0) {
/* Calc the gradient difference of the current image and the last image */
ret = ss_mpi_ive_mag_and_ang(&handle, &gmm2->src[cur_idx], &gmm2->mag_image,
TD_NULL, &mag_and_ang_ctrl, TD_FALSE);
macro_svp_check_failed_err_level_return(ret, ret, "Error(%#x),ss_mpi_ive_mag_and_ang failed!\n", ret);
ret = ss_mpi_ive_16bit_to_8bit(&handle, &gmm2->mag_image, &gmm2->cur_norm_mag, &ctrl_16to8bit, TD_FALSE);
macro_svp_check_failed_err_level_return(ret, ret, "Error(%#x),ss_mpi_ive_16bit_to_8bit failed!\n", ret);
ret = ss_mpi_ive_mag_and_ang(&handle, &gmm2->src[1 - cur_idx], &gmm2->mag_image, TD_NULL,
&mag_and_ang_ctrl, TD_FALSE);
macro_svp_check_failed_err_level_return(ret, ret, "Error(%#x),ss_mpi_ive_mag_and_ang failed!\n", ret);
ret = ss_mpi_ive_16bit_to_8bit(&handle, &gmm2->mag_image, &gmm2->last_norm_mag, &ctrl_16to8bit, TD_FALSE);
macro_svp_check_failed_err_level_return(ret, ret, "Error(%#x),ss_mpi_ive_16bit_to_8bit failed!\n", ret);
ret = ss_mpi_ive_sub(&handle, &gmm2->cur_norm_mag, &gmm2->last_norm_mag, &gmm2->diff_image, &sub_ctrl, TD_TRUE);
macro_svp_check_failed_err_level_return(ret, ret, "Error(%#x),ss_mpi_ive_sub failed!\n", ret);
ret = ss_mpi_ive_query(handle, &is_finish, is_block);
while (ret == OT_ERR_IVE_QUERY_TIMEOUT) {
usleep(OT_MACRO_IVE_GMM2_QUERY_SLEEP);
ret = ss_mpi_ive_query(handle, &is_finish, is_block);
}
macro_svp_check_failed_err_level_return(ret, ret, "Error(%#x),ss_mpi_ive_query failed!\n", ret);
}
return TD_SUCCESS;
}
static td_void _ive_get_grad_and_fg_sum(ot_svp_src_img *fg_mask, ot_svp_src_img *diff_img,
ot_svp_rect_u16 rect, td_s32 *fg_sum, td_s32 *grad_sum)
{
td_u8 *fg_cur_ptr = TD_NULL;
td_u8 *grad_diff_ptr = TD_NULL;
td_u16 top, left, right, bottom;
td_u16 i, j;
top = rect.x;
left = rect.y;
right = rect.width;
bottom = rect.height;
*fg_sum = 0;
*grad_sum = 0;
fg_cur_ptr = (macro_svp_convert_addr_to_ptr(td_u8, fg_mask->virt_addr[0])) + top * fg_mask->stride[0];
grad_diff_ptr = (macro_svp_convert_addr_to_ptr(td_u8, diff_img->virt_addr[0])) + top * diff_img->stride[0];
for (i = top; i < bottom; i++) {
for (j = left; j < right; j++) {
if (fg_cur_ptr[j] != 0) {
(*fg_sum)++;
*grad_sum = grad_diff_ptr[j] ? (*grad_sum) + 1 : (*grad_sum) + 0;
}
}
fg_cur_ptr += fg_mask->stride[0];
grad_diff_ptr += diff_img->stride[0];
}
}
static td_void _ive_update_mask_and_factor(ot_svp_rect_u16 rect, td_s32 fg_sum, td_s32 grad_sum,
ot_svp_src_img *factor, ot_svp_src_img *mask)
{
td_u8 *fg_cur_ptr = TD_NULL;
td_u8 *factor_ptr = TD_NULL;
td_u16 top, left, right, bottom;
td_u16 i, j;
top = rect.x;
left = rect.y;
right = rect.width;
bottom = rect.height;
if ((grad_sum >= OT_MACRO_IVE_GMM2_MAX_GRAD_SUM) &&
(grad_sum * OT_MACRO_IVE_GMM2_RATIO_BETWEEN_GRAD_AND_FG >= fg_sum)) {
return;
}
factor_ptr = (macro_svp_convert_addr_to_ptr(td_u8, factor->virt_addr[0])) +
sizeof(td_u16) * top * factor->stride[0];
fg_cur_ptr = (macro_svp_convert_addr_to_ptr(td_u8, mask->virt_addr[0])) +
top * mask->stride[0];
for (i = top; i < bottom; i++) {
for (j = left; j < right; j++) {
if (fg_cur_ptr[j] != 0) {
factor_ptr[j << 1] = OT_MACRO_IVE_GMM2_UPDATA_FACTOR_VAL1;
factor_ptr[(j << 1) + 1] = OT_MACRO_IVE_GMM2_UPDATA_FACTOR_VAL2;
}
}
fg_cur_ptr += mask->stride[0];
factor_ptr += factor->stride[0] * sizeof(td_u16);
}
}
/*
* Change factor by gradient
*/
static td_void _ive_change_factror_by_grad(ot_struct_ive_gmm2_info *gmm2, td_s32 cur_idx)
{
td_s32 ret;
td_u16 k;
td_s32 fg_sum, grad_sum;
ot_ive_ccblob *ccl_blob = TD_NULL;
ot_svp_rect_u16 rect;
ret = _ive_calc_grad_diff_bewteen_img(gmm2, cur_idx);
macro_svp_check_exps_return_void(ret != TD_SUCCESS, ENUM_SVP_ERR_LEVEL_ERROR,
"_ive_calc_grad_diff_bewteen_cur_and_last_img failed\n");
ccl_blob = macro_svp_convert_addr_to_ptr(ot_ive_ccblob, gmm2->blob.virt_addr);
/* for each blob, analyze the gradient change */
for (k = 0; k < OT_IVE_MAX_RGN_NUM; k++) {
if (ccl_blob->rgn[k].area == 0) {
continue;
}
rect.x = ccl_blob->rgn[k].top;
rect.y = ccl_blob->rgn[k].left;
rect.width = ccl_blob->rgn[k].right;
rect.height = ccl_blob->rgn[k].bottom;
if (((ccl_blob->rgn[k].right - ccl_blob->rgn[k].left) *
(ccl_blob->rgn[k].bottom - ccl_blob->rgn[k].top)) < OT_MACRO_IVE_GMM2_MAX_CCL_REGION) {
continue;
}
_ive_get_grad_and_fg_sum(&gmm2->fg_mask, &gmm2->diff_image, rect, &fg_sum, &grad_sum);
_ive_update_mask_and_factor(rect, fg_sum, grad_sum, &gmm2->factor, &gmm2->fg_mask);
}
}
/*
* Adjustment factor
*/
static td_void _ive_adjust_factor(ot_struct_ive_gmm2_info *gmm2, td_s32 cur_idx)
{
td_bool is_changed;
/* First, reduce the factor gradually to the default value */
_ive_reduce_factor(&gmm2->factor);
/*
* Second, analyze the frame difference
* When the number of changed pixels is more than the threshold, there maybe a light switch.
* And then, we should set a big factor to adapt to it quickly.
*/
is_changed = _ive_change_factor_by_diff_frame(&gmm2->src[cur_idx], &gmm2->src[1 - cur_idx],
&gmm2->diff_image, &gmm2->factor);
if (is_changed == TD_TRUE) {
return;
}
/*
* Third, analyze the gradient for foreground blobs
* When gradient change of a foreground blob is very small, it maybe a local illumination change,
* a ghost, or a static object.
* Here we try to reduce the influence by a local illumination change or a ghost only.
*/
(td_void)_ive_change_factror_by_grad(gmm2, cur_idx);
}
static td_s32 _ive_gmm2_write_fg_bg_file(ot_struct_ive_gmm2_info *gmm2)
{
td_s32 ret;
ret = libapi_common_ive_write_file(&(gmm2->fg), gmm2->fp_fg);
macro_svp_check_exps_return(ret != TD_SUCCESS, ret, ENUM_SVP_ERR_LEVEL_ERROR,
"Error(%#x),Write fg file failed!\n", ret);
ret = libapi_common_ive_write_file(&(gmm2->bg), gmm2->fp_bg);
macro_svp_check_exps_return(ret != TD_SUCCESS, ret, ENUM_SVP_ERR_LEVEL_ERROR,
"Error(%#x),Write bg file failed!\n", ret);
return ret;
}
static td_s32 _ive_gmm2_proc(ot_struct_ive_gmm2_info *gmm2)
{
td_s32 ret = OT_ERR_IVE_NULL_PTR;
ot_ive_handle handle;
td_bool is_finish = TD_FALSE;
td_bool is_block = TD_TRUE;
td_bool is_instant = TD_TRUE;
td_u32 frame_num;
td_s32 cur_idx = 0;
const td_u32 total_frame = OT_MACRO_IVE_TOTAL_FRAME;
macro_svp_check_exps_return(gmm2 == TD_NULL, ret, ENUM_SVP_ERR_LEVEL_ERROR, "gmm2 can't be null\n");
for (frame_num = 1; (frame_num < total_frame) && (g_stop_signal == TD_FALSE); frame_num++) {
macro_svp_trace_info("Proc Frame %u/%u\n", frame_num, total_frame);
ret = libapi_common_ive_read_file(&(gmm2->src[cur_idx]), gmm2->fp_src);
macro_svp_check_exps_return(ret != TD_SUCCESS, ret, ENUM_SVP_ERR_LEVEL_ERROR,
"Error(%#x),Read src file failed!\n", ret);
/* To building a stable background model quickly at the begin, some parameters are set specially. */
if (gmm2->gmm2_ctrl.model_num == 1) {
/*
* If the parameter u8ModelNum is set to 1, the parameter u16FreqReduFactor
* is usually set to a small value at the first N frames. Here, N = 500.
*/
gmm2->gmm2_ctrl.freq_reduce_factor = (frame_num >= OT_MACRO_IVE_GMM2_FIRST_FRMAE_NUM) ? 0xFFA0 : 0xFC00;
} else {
/*
* If the parameter u8ModelNum is more than 1, the global life mode should be used at the first N frames,
* and the parameter u16GlbLifeUpdateFactor is usually set to a big value. Here, N = 500.
*/
if (frame_num >= OT_MACRO_IVE_GMM2_FIRST_FRMAE_NUM) {
gmm2->gmm2_ctrl.life_update_factor_mode = OT_IVE_GMM2_LIFE_UPDATE_FACTOR_MODE_PIXEL;
} else {
gmm2->gmm2_ctrl.global_life_update_factor = 0xFFFF / frame_num;
}
}
ret = ss_mpi_ive_gmm2(&handle, &gmm2->src[cur_idx], &gmm2->factor, &gmm2->fg, &gmm2->bg,
&gmm2->match_model_info, &gmm2->model, &gmm2->gmm2_ctrl, is_instant);
macro_svp_check_exps_return(ret != TD_SUCCESS, ret, ENUM_SVP_ERR_LEVEL_ERROR,
"Error(%#x),ss_mpi_ive_gmm2 failed!\n", ret);
/* factor adjustment */
if (frame_num > 1) {
ret = _ive_gen_fg_mask(&(gmm2->fg), &(gmm2->fg_mask));
macro_svp_check_exps_return(ret != TD_SUCCESS, ret, ENUM_SVP_ERR_LEVEL_ERROR,
"Error(%#x),_ive_gen_fg_mask failed!\n", ret);
_ive_adjust_factor(gmm2, cur_idx);
} else {
ret = ss_mpi_ive_query(handle, &is_finish, is_block);
while (ret == OT_ERR_IVE_QUERY_TIMEOUT) {
usleep(OT_MACRO_IVE_GMM2_QUERY_SLEEP);
ret = ss_mpi_ive_query(handle, &is_finish, is_block);
}
macro_svp_check_exps_return(ret != TD_SUCCESS, ret, ENUM_SVP_ERR_LEVEL_ERROR,
"Error(%#x),ss_mpi_ive_query failed!\n", ret);
}
// ret = _ive_gmm2_write_fg_bg_file(gmm2);
// macro_svp_check_exps_return(ret != TD_SUCCESS, ret, ENUM_SVP_ERR_LEVEL_ERROR,
// "Error(%#x),Write fg bg file failed!\n", ret);
cur_idx = 1 - cur_idx;
}
return TD_SUCCESS;
}
static td_void _ive_gmm2_stop(td_void)
{
_ive_gmm2_uninit(&g_gmm2_info);
(td_void)memset_s(&g_gmm2_info, sizeof(g_gmm2_info), 0, sizeof(g_gmm2_info));
// libapi_common_ive_mpi_exit();
printf("\033[0;31mprogram termination abnormally!\033[0;39m\n");
}
/*
* function: gmm2 func
*/
td_void libapi_ive_gmm2(td_void)
{
td_s32 ret;
ot_size pic_size = { OT_MACRO_IVE_GMM2_CIF_WIDTH, OT_MACRO_IVE_GMM2_CIF_HEIGHT };
(td_void)memset_s(&g_gmm2_info, sizeof(g_gmm2_info), 0, sizeof(g_gmm2_info));
// ret = libapi_common_ive_check_mpi_init();
// macro_svp_check_exps_return_void(ret != TD_TRUE, ENUM_SVP_ERR_LEVEL_ERROR, "ive_check_mpi_init failed!\n");
ret = _ive_gmm2_init(&g_gmm2_info, pic_size);
macro_svp_check_exps_goto(ret != TD_SUCCESS, gmm2_fail, ENUM_SVP_ERR_LEVEL_ERROR,
"Error(%#x),_ive_gmm2_init failed!\n", ret);
ret = _ive_gmm2_proc(&g_gmm2_info);
if (g_stop_signal == TD_TRUE) {
_ive_gmm2_stop();
return;
}
if (ret == TD_SUCCESS) {
macro_svp_trace_info("Process success!\n");
} else {
macro_svp_trace_err("gmm2 process failed!\n");
}
g_stop_signal = TD_TRUE;
_ive_gmm2_uninit(&g_gmm2_info);
(td_void)memset_s(&g_gmm2_info, sizeof(g_gmm2_info), 0, sizeof(g_gmm2_info));
gmm2_fail:
g_stop_signal = TD_TRUE;
// libapi_common_ive_mpi_exit();
}
/*
* function : Gmm2 signal handle
*/
td_void libapi_ive_gmm2_handle_sig(td_void)
{
g_stop_signal = TD_TRUE;
}