ss928_framework/libapi/ive/libapi_ive_od.c

352 lines
14 KiB
C
Raw 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 <sys/prctl.h>
#include <math.h>
#define OT_MACRO_IVE_OD_MILLI_SEC 20000
#define OT_MACRO_IVE_OD_QUERY_SLEEP 100
#define OT_MACRO_IVE_OD_LINEAR_NUM 2
#define OT_MACRO_IVE_OD_LINEAR_POINT0_X 80
#define OT_MACRO_IVE_OD_LINEAR_POINT0_Y 0
#define OT_MACRO_IVE_OD_LINEAR_POINT1_X 80
#define OT_MACRO_IVE_OD_LINEAR_POINT1_Y 20
#define OT_MACRO_IVE_OD_THREAD_NAME_LEN 16
#define OT_MACRO_IVE_OD_NUM_TWO 2
#define OT_MACRO_IVE_OD_POINT_NUM 10
#define OT_MACRO_IVE_RIGHT_SHIFT_TWENTY_EIGHT 28
typedef struct {
ot_svp_src_img src;
ot_svp_dst_img integ;
ot_ive_integ_ctrl integ_ctrl;
td_u32 width;
td_u32 height;
} ot_sample_ive_od_info;
static td_bool g_stop_signal = TD_FALSE;
static pthread_t g_ive_thread = 0;
static ot_sample_ive_od_info g_od_info;
static ot_struct_svp_switch g_od_switch = { TD_FALSE, TD_TRUE };
static struct_vi_cfg g_vi_config;
static td_void sample_ive_od_uninit(ot_sample_ive_od_info *od_info)
{
macro_svp_check_exps_return_void(od_info == TD_NULL, ENUM_SVP_ERR_LEVEL_ERROR, "od_info can't be null\n");
macro_svp_mmz_free(od_info->src.phys_addr[0], od_info->src.virt_addr[0]);
macro_svp_mmz_free(od_info->integ.phys_addr[0], od_info->integ.virt_addr[0]);
}
static td_s32 sample_ive_od_init(ot_sample_ive_od_info *od_info, td_u32 width, td_u32 height)
{
td_s32 ret = OT_ERR_IVE_NULL_PTR;
macro_svp_check_exps_return(od_info == TD_NULL, ret, ENUM_SVP_ERR_LEVEL_ERROR, "od_info can't be null\n");
(td_void)memset_s(od_info, sizeof(ot_sample_ive_od_info), 0, sizeof(ot_sample_ive_od_info));
ret = libapi_common_ive_create_image(&od_info->src, OT_SVP_IMG_TYPE_U8C1, width, height);
macro_svp_check_exps_goto(ret != TD_SUCCESS, od_init_fail, ENUM_SVP_ERR_LEVEL_ERROR,
"Error(%#x),Create src image failed!\n", ret);
ret = libapi_common_ive_create_image(&od_info->integ, OT_SVP_IMG_TYPE_U64C1, width, height);
macro_svp_check_exps_goto(ret != TD_SUCCESS, od_init_fail, ENUM_SVP_ERR_LEVEL_ERROR,
"Error(%#x),Create integ image failed!\n", ret);
od_info->integ_ctrl.out_ctrl = OT_IVE_INTEG_OUT_CTRL_COMBINE;
od_info->width = width / OT_IVE_CHAR_CALW;
od_info->height = height / OT_IVE_CHAR_CALH;
od_init_fail:
if (ret != TD_SUCCESS) {
sample_ive_od_uninit(od_info);
}
return ret;
}
static td_s32 sample_ive_linear_2d_classifer(ot_point *char_point, td_s32 char_num, ot_point *linear_point,
td_s32 linear_num)
{
td_s32 result_num;
td_s32 i, j;
td_bool test_flag;
ot_point *next_linear_point = TD_NULL;
result_num = 0;
next_linear_point = &linear_point[1];
for (i = 0; i < char_num; i++) {
test_flag = TD_TRUE;
for (j = 0; j < (linear_num - 1); j++) {
if (((char_point[i].y - linear_point[j].y) * (next_linear_point[j].x - linear_point[j].x) >
(char_point[i].x - linear_point[j].x) * (next_linear_point[j].y - linear_point[j].y) &&
(next_linear_point[j].x != linear_point[j].x)) ||
((char_point[i].x > linear_point[j].x) && (next_linear_point[j].x == linear_point[j].x))) {
test_flag = TD_FALSE;
break;
}
}
if (test_flag == TD_TRUE) {
result_num++;
}
}
return result_num;
}
static td_void sample_ive_prepare_dma_data(ot_sample_ive_od_info *od_ptr, ot_video_frame_info *ext_frm_info,
ot_svp_data *src_data, ot_svp_data *dst_data)
{
src_data->virt_addr = macro_svp_convert_ptr_to_addr(td_u64, ext_frm_info->video_frame.virt_addr[0]);
src_data->phys_addr = ext_frm_info->video_frame.phys_addr[0];
src_data->stride = ext_frm_info->video_frame.stride[0];
src_data->width = ext_frm_info->video_frame.width;
src_data->height = ext_frm_info->video_frame.height;
dst_data->virt_addr = od_ptr->src.virt_addr[0];
dst_data->phys_addr = od_ptr->src.phys_addr[0];
dst_data->stride = ext_frm_info->video_frame.stride[0];
dst_data->width = ext_frm_info->video_frame.width;
dst_data->height = ext_frm_info->video_frame.height;
}
static td_s32 sample_ive_query_task(ot_ive_handle handle)
{
td_s32 ret;
td_bool is_block = TD_TRUE;
td_bool is_finish = TD_FALSE;
ret = ss_mpi_ive_query(handle, &is_finish, is_block);
while (ret == OT_ERR_IVE_QUERY_TIMEOUT) {
usleep(OT_MACRO_IVE_OD_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);
return TD_SUCCESS;
}
static td_s32 sample_ive_get_char_point(ot_sample_ive_od_info *od_ptr, ot_point char_point[], td_u32 length)
{
td_u64 *vir_data = TD_NULL;
td_u32 i, j;
td_u64 top_left, top_right, btm_left, btm_right;
td_u64 *top_row_ptr = TD_NULL;
td_u64 *btm_row_ptr = TD_NULL;
td_u64 block_sum, block_sqrt;
td_float sqrt_val;
vir_data = macro_svp_convert_addr_to_ptr(td_u64, od_ptr->integ.virt_addr[0]);
macro_svp_check_exps_return(length > OT_IVE_CHAR_CALW * OT_IVE_CHAR_CALH, OT_ERR_IVE_ILLEGAL_PARAM,
ENUM_SVP_ERR_LEVEL_ERROR, "length(%u) is larger than %u\n", length, OT_IVE_CHAR_CALW * OT_IVE_CHAR_CALH);
for (j = 0; (j < OT_IVE_CHAR_CALH) && (j < length); j++) {
top_row_ptr = (0 == j) ? (vir_data) : (vir_data + (j * od_ptr->height - 1) * od_ptr->integ.stride[0]);
btm_row_ptr = vir_data + ((j + 1) * od_ptr->height - 1) * od_ptr->integ.stride[0];
for (i = 0; i < OT_IVE_CHAR_CALW; i++) {
top_left = (0 == j) ? (0) : ((0 == i) ? (0) : (top_row_ptr[i * od_ptr->width - 1]));
top_right = (0 == j) ? (0) : (top_row_ptr[(i + 1) * od_ptr->width - 1]);
btm_left = (0 == i) ? (0) : (btm_row_ptr[i * od_ptr->width - 1]);
btm_right = btm_row_ptr[(i + 1) * od_ptr->width - 1];
block_sum = (top_left & 0xfffffffLL) + (btm_right & 0xfffffffLL) -
(btm_left & 0xfffffffLL) - (top_right & 0xfffffffLL);
block_sqrt = (top_left >> OT_MACRO_IVE_RIGHT_SHIFT_TWENTY_EIGHT) +
(btm_right >> OT_MACRO_IVE_RIGHT_SHIFT_TWENTY_EIGHT) -
(btm_left >> OT_MACRO_IVE_RIGHT_SHIFT_TWENTY_EIGHT) -
(top_right >> OT_MACRO_IVE_RIGHT_SHIFT_TWENTY_EIGHT);
/* mean */
char_point[j * OT_IVE_CHAR_CALW + i].x = block_sum / (od_ptr->width * od_ptr->width);
/* sigma=sqrt(1/(w*h)*sum((x(i,j)-mean)^2)= sqrt(sum(x(i,j)^2)/(w*h)-mean^2) */
sqrt_val = block_sqrt / (od_ptr->width * od_ptr->height) - char_point[j * OT_IVE_CHAR_CALW + i].x *
char_point[j * OT_IVE_CHAR_CALW + i].x;
char_point[j * OT_IVE_CHAR_CALW + i].y = (td_u32)sqrt(sqrt_val);
}
}
return TD_SUCCESS;
}
static td_void sample_ive_set_linear_data(ot_struct_ive_linear_data *data)
{
data->linear_num = OT_MACRO_IVE_OD_LINEAR_NUM;
data->thresh_num = OT_IVE_CHAR_NUM / OT_MACRO_IVE_OD_NUM_TWO;
data->linear_point[0].x = OT_MACRO_IVE_OD_LINEAR_POINT0_X;
data->linear_point[0].y = OT_MACRO_IVE_OD_LINEAR_POINT0_Y;
data->linear_point[1].x = OT_MACRO_IVE_OD_LINEAR_POINT1_X;
data->linear_point[1].y = OT_MACRO_IVE_OD_LINEAR_POINT1_Y;
}
static td_void *sample_ive_od_proc(td_void *arg)
{
td_s32 ret;
ot_sample_ive_od_info *od_ptr = TD_NULL;
ot_video_frame_info base_frm_info, ext_frm_info;
const td_s32 vpss_grp = 0;
td_s32 vpss_chn[] = { OT_VPSS_CHN0, OT_VPSS_CHN1 };
ot_svp_data src_data, dst_data;
ot_ive_handle handle;
ot_point points[OT_MACRO_IVE_OD_POINT_NUM] = {{ 0, 0 }};
ot_point char_point[OT_IVE_CHAR_NUM];
ot_struct_ive_linear_data data;
ot_ive_dma_ctrl dma_ctrl = { OT_IVE_DMA_MODE_DIRECT_COPY, 0, 0, 0, 0 };
data.linear_point = &points[0];
od_ptr = (ot_sample_ive_od_info *)(arg);
macro_svp_check_exps_return(od_ptr == TD_NULL, TD_NULL, ENUM_SVP_ERR_LEVEL_ERROR, "od_ptr can't be null\n");
/* init data */
sample_ive_set_linear_data(&data);
while (g_stop_signal == TD_FALSE) {
/* get frame */
ret = ss_mpi_vpss_get_chn_frame(vpss_grp, vpss_chn[1], &ext_frm_info, OT_MACRO_IVE_OD_MILLI_SEC);
macro_svp_check_exps_continue(ret != TD_SUCCESS, ENUM_SVP_ERR_LEVEL_DEBUG,
"Error(%#x),ss_mpi_vpss_get_chn_frame failed, VPSS_GRP(%d), VPSS_CHN(%d)!\n", ret, vpss_grp, vpss_chn[1]);
ret = ss_mpi_vpss_get_chn_frame(vpss_grp, vpss_chn[0], &base_frm_info, OT_MACRO_IVE_OD_MILLI_SEC);
macro_svp_check_failed_goto(ret, ext_free, ENUM_SVP_ERR_LEVEL_ERROR,
"Error(%#x),ss_mpi_vpss_get_chn_frame failed, VPSS_GRP(%d), VPSS_CHN(%d)!\n", ret, vpss_grp, vpss_chn[0]);
/* prepare dma data */
sample_ive_prepare_dma_data(od_ptr, &ext_frm_info, &src_data, &dst_data);
/* dma */
ret = ss_mpi_ive_dma(&handle, &src_data, &dst_data, &dma_ctrl, TD_FALSE);
macro_svp_check_failed_err_level_goto(ret, base_free, "Error(%#x),ss_mpi_ive_dma failed!\n", ret);
/* integ */
ret = ss_mpi_ive_integ(&handle, &od_ptr->src, &od_ptr->integ, &od_ptr->integ_ctrl, TD_TRUE);
macro_svp_check_failed_err_level_goto(ret, base_free, "Error(%#x),ss_mpi_ive_integ failed!\n", ret);
/* query task */
ret = sample_ive_query_task(handle);
macro_svp_check_failed_err_level_goto(ret, base_free, "ive_query_task failed!\n");
/* get result */
ret = sample_ive_get_char_point(od_ptr, char_point, OT_IVE_CHAR_NUM);
macro_svp_check_failed_err_level_goto(ret, base_free, "sample_ive_get_char_point failed!\n");
/* classify */
ret = sample_ive_linear_2d_classifer(char_point, OT_IVE_CHAR_NUM, data.linear_point, data.linear_num);
macro_svp_check_exps_trace(ret > data.thresh_num, ENUM_SVP_ERR_LEVEL_DEBUG,
"\033[0;31m Occlusion detected!\033[0;39m\n");
/* send vo frame */
ret = ss_mpi_vo_send_frame(0, 0, &base_frm_info, OT_MACRO_IVE_OD_MILLI_SEC);
macro_svp_check_failed_err_level_goto(ret, base_free, "Error(%#x),sample_vo_send_frame failed!\n", ret);
base_free:
ret = ss_mpi_vpss_release_chn_frame(vpss_grp, vpss_chn[0], &base_frm_info);
macro_svp_check_exps_trace(ret != TD_SUCCESS, ENUM_SVP_ERR_LEVEL_DEBUG,
"Error(%#x),release_frame failed,Grp(%d) chn(%d)!\n", ret, vpss_grp, vpss_chn[0]);
ext_free:
ret = ss_mpi_vpss_release_chn_frame(vpss_grp, vpss_chn[1], &ext_frm_info);
macro_svp_check_exps_trace(ret != TD_SUCCESS, ENUM_SVP_ERR_LEVEL_DEBUG,
"Error(%#x),release_frame failed,Grp(%d) chn(%d)!\n", ret, vpss_grp, vpss_chn[1]);
}
return TD_NULL;
}
static td_s32 sample_ive_od_pause(td_void)
{
printf("---------------press Enter key to exit!---------------\n");
if (g_stop_signal == TD_TRUE) {
if (g_ive_thread != 0) {
pthread_join(g_ive_thread, TD_NULL);
g_ive_thread = 0;
}
sample_ive_od_uninit(&(g_od_info));
(td_void)memset_s(&g_od_info, sizeof(g_od_info), 0, sizeof(g_od_info));
sample_common_svp_stop_vi_vpss_venc_vo(&g_vi_config, &g_od_switch);
printf("\033[0;31mprogram termination abnormally!\033[0;39m\n");
return TD_TRUE;
}
(void)getchar();
if (g_stop_signal == TD_TRUE) {
if (g_ive_thread != 0) {
pthread_join(g_ive_thread, TD_NULL);
g_ive_thread = 0;
}
sample_ive_od_uninit(&(g_od_info));
(td_void)memset_s(&g_od_info, sizeof(g_od_info), 0, sizeof(g_od_info));
sample_common_svp_stop_vi_vpss_venc_vo(&g_vi_config, &g_od_switch);
printf("\033[0;31mprogram termination abnormally!\033[0;39m\n");
return TD_TRUE;
}
return TD_FALSE;
}
td_void libapi_ive_od(td_void)
{
td_s32 ret;
ot_size pic_size;
ot_enum_pic_size pic_type = PIC_1080P;
(td_void)memset_s(&g_od_info, sizeof(g_od_info), 0, sizeof(g_od_info));
/*
* step 1: start vi vpss venc vo
*/
ret = sample_common_svp_start_vi_vpss_venc_vo(&g_vi_config, &g_od_switch, &pic_type);
macro_svp_check_exps_goto(ret != TD_SUCCESS, end_od_0, ENUM_SVP_ERR_LEVEL_DEBUG,
"Error(%#x),sample_common_svp_start_vi_vpss_venc_vo failed!\n", ret);
ret = libapi_comm_sys_get_pic_size(pic_type, &pic_size);
macro_svp_check_exps_goto(ret != TD_SUCCESS, end_od_0, ENUM_SVP_ERR_LEVEL_DEBUG,
"Error(%#x),libapi_comm_sys_get_pic_size failed!\n", ret);
/*
* step 2: Init OD
*/
ret = sample_ive_od_init(&g_od_info, pic_size.width, pic_size.height);
macro_svp_check_exps_goto(ret != TD_SUCCESS, end_od_0, ENUM_SVP_ERR_LEVEL_DEBUG,
"sample_ive_od_init failed, Error(%#x)!\n", ret);
g_stop_signal = TD_FALSE;
/*
* step 3: Create work thread
*/
ret = prctl(PR_SET_NAME, "ive_od_proc", 0, 0, 0);
macro_svp_check_exps_goto(ret != TD_SUCCESS, end_od_0, ENUM_SVP_ERR_LEVEL_DEBUG, "set thread name failed!\n");
ret = pthread_create(&g_ive_thread, 0, sample_ive_od_proc, (td_void *)&g_od_info);
macro_svp_check_exps_goto(ret != TD_SUCCESS, end_od_0, ENUM_SVP_ERR_LEVEL_DEBUG, "pthread_create failed!\n");
ret = sample_ive_od_pause();
macro_svp_check_exps_return_void(ret == TD_TRUE, ENUM_SVP_ERR_LEVEL_DEBUG, "od exit!\n");
g_stop_signal = TD_TRUE;
pthread_join(g_ive_thread, TD_NULL);
g_ive_thread = 0;
sample_ive_od_uninit(&(g_od_info));
(td_void)memset_s(&g_od_info, sizeof(g_od_info), 0, sizeof(g_od_info));
end_od_0:
g_ive_thread = 0;
g_stop_signal = TD_TRUE;
sample_common_svp_stop_vi_vpss_venc_vo(&g_vi_config, &g_od_switch);
return;
}
/*
* function : Od sample signal handle
*/
td_void libapi_ive_od_handle_sig(td_void)
{
g_stop_signal = TD_TRUE;
}