fix missing file

This commit is contained in:
Lu Hui
2024-03-06 16:26:46 +08:00
parent a72e00d397
commit 242596ca09
46 changed files with 24903 additions and 0 deletions

View File

@@ -0,0 +1,25 @@
ifeq ($(PARAM_FILE), )
PARAM_FILE:=../Makefile.param
include $(PARAM_FILE)
endif
.PHONY: all clean $(MODULES)
MODULES = sys bin vpu audio mipi_tx venc vdec misc ive osdc isp
all:
@echo "########################################################################################################"
@echo "#"
@echo "# Compiling 'module libs' Configs as below ..."
@echo "# "CROSS_COMPILE=$(CROSS_COMPILE)
@echo "# "KERNEL_DIR=$(KERNEL_DIR)
@echo "#"
@echo "########################################################################################################"
@for x in $(MODULES); \
do cd $$x; if [ $$? ]; then $(MAKE) all || exit 1; cd -; fi; done
clean:
@for x in `find -L ./ -maxdepth 2 -mindepth 2 -name "Makefile" `; \
do cd `dirname $$x`; if [ $$? ]; then $(MAKE) clean; cd -; fi; done
@make -C isp clean
@echo "#"

View File

View File

@@ -0,0 +1,17 @@
.PHONY: clean all
.SILENT: clean all
include audio.mk
all:
cp lib/$(SDK_VER)/lib* $(MW_LIB)
clean:
rm $(MW_LIB)/libaac*
rm $(MW_LIB)/libcvi_audio*
rm $(MW_LIB)/libcvi_RES1*
rm $(MW_LIB)/libcvi_ssp*
rm $(MW_LIB)/libcvi_VoiceEngine*
rm $(MW_LIB)/libcvi_vqe*
rm $(MW_LIB)/libdnvqe*
rm $(MW_LIB)/libtinyalsa*

View File

@@ -0,0 +1,4 @@
ifeq ($(PARAM_FILE), )
PARAM_FILE:=../../../$(shell echo $(MW_VER))/Makefile.param
include $(PARAM_FILE)
endif

View File

@@ -0,0 +1,38 @@
SHELL = /bin/bash
ifeq ($(PARAM_FILE), )
PARAM_FILE:=../../Makefile.param
include $(PARAM_FILE)
endif
SDIR = $(PWD)/src
SRCS = $(wildcard $(SDIR)/*.c)
INCS = -I./include -I$(MW_INC) -I$(KERNEL_INC) -I$(SYS_INC)
OBJS = $(SRCS:.c=.o)
DEPS = $(SRCS:.c=.d)
TARGET_A = $(MW_LIB)/libcvi_gyro.a
TARGET_SO = $(MW_LIB)/libcvi_gyro.so
EXTRA_CFLAGS = $(INCS)
.PHONY : clean all install
all : $(TARGET_A) $(TARGET_SO) install
install:
@cp include/cvi_gyro.h $(MW_INC)
$(SDIR)/%.o: $(SDIR)/%.c
@$(CC) $(DEPFLAGS) $(CFLAGS) $(EXTRA_CFLAGS) -o $@ -c $<
@echo [$(notdir $(CC))] $(notdir $@)
$(TARGET_A): $(OBJS)
@$(AR) $(ARFLAGS) $(TARGET_A) $(OBJS)
@echo -e $(YELLOW)[LINK]$(END)[$(notdir $(AR))] $(notdir $(TARGET_A))
$(TARGET_SO): $(OBJS)
@$(LD) $(LDFLAGS) $(EXTRA_LDFLAGS) -o $@ --start-group $(OBJS) --end-group
@echo -e $(GREEN)[LINK]$(END)[$(notdir $(LD))] $(notdir $(TARGET_SO))
clean:
@rm -f $(OBJS) $(DEPS) $(TARGET_A) $(TARGET_SO)
-include $(DEPS)

View File

@@ -0,0 +1,216 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include <assert.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include "cvi_gyro.h"
#include "linux/cvi_gyro_ioctl.h"
#define DEV_NODE "/dev/cvi-gyro"
int g_devfd = CVI_FAILURE;
CVI_S32 _dev_check(CVI_VOID)
{
if (g_devfd <= 0) {
printf("Device gyro is not open, please check it\n");
return -1;
}
return CVI_SUCCESS;
}
CVI_S32 _cvi_gyro_get_2byte(int reg, CVI_S16 *val)
{
CVI_S32 ret = CVI_FAILURE;
if (_dev_check() == 0) {
struct cvi_gy_regval regval;
regval.addr = reg;
ret = ioctl(g_devfd, CVI_GYRO_IOC_READ_2BYTE, &regval);
*val = regval.val;
}
return ret;
}
CVI_S32 _cvi_gyro_get_xyz(int reg, CVI_S16 *x_val, CVI_S16 *y_val, CVI_S16 *z_val)
{
CVI_S32 ret = CVI_FAILURE;
if (_dev_check() == 0) {
struct cvi_gy_regval_6byte regval;
regval.addr = reg;
ret = ioctl(g_devfd, CVI_GYRO_IOC_READ_6BYTE, &regval);
if (x_val != NULL)
*x_val = regval.x_val;
if (y_val != NULL)
*y_val = regval.y_val;
if (z_val != NULL)
*z_val = regval.z_val;
return ret;
}
return ret;
}
CVI_S32 CVI_GYRO_Create(CVI_VOID)
{
if (g_devfd <= 0) {
g_devfd = open(DEV_NODE, O_RDWR);
if (g_devfd < 0) {
printf("Can't open %s\n", DEV_NODE);
return CVI_FAILURE;
}
}
return CVI_SUCCESS;
}
CVI_VOID CVI_GYRO_Destroy(CVI_VOID)
{
if (g_devfd > 0) {
close(g_devfd);
}
g_devfd = 0;
}
CVI_S32 CVI_GYRO_Reset(CVI_VOID)
{
CVI_S32 ret = CVI_FAILURE;
ret = CVI_GYRO_WRITE(PWR_MGMT_1, 0x80);
usleep(100 * 1000);
return ret;
}
CVI_S32 CVI_GYRO_GET_G_XYZ(CVI_S16 *x_val, CVI_S16 *y_val, CVI_S16 *z_val)
{
return _cvi_gyro_get_xyz(GYRO_XOUT_H, x_val, y_val, z_val);
}
CVI_S32 CVI_GYRO_GET_A_XYZ(CVI_S16 *x_val, CVI_S16 *y_val, CVI_S16 *z_val)
{
return _cvi_gyro_get_xyz(ACCEL_XOUT_H, x_val, y_val, z_val);
}
CVI_S32 CVI_GYRO_GET_GX(CVI_S16 *val)
{
return _cvi_gyro_get_2byte(GYRO_XOUT_H, val);
}
CVI_S32 CVI_GYRO_GET_GY(CVI_S16 *val)
{
return _cvi_gyro_get_2byte(GYRO_YOUT_H, val);
}
CVI_S32 CVI_GYRO_GET_GZ(CVI_S16 *val)
{
return _cvi_gyro_get_2byte(GYRO_ZOUT_H, val);
}
CVI_S32 CVI_GYRO_GET_AX(CVI_S16 *val)
{
return _cvi_gyro_get_2byte(ACCEL_XOUT_H, val);
}
CVI_S32 CVI_GYRO_GET_AY(CVI_S16 *val)
{
return _cvi_gyro_get_2byte(ACCEL_YOUT_H, val);
}
CVI_S32 CVI_GYRO_GET_AZ(CVI_S16 *val)
{
return _cvi_gyro_get_2byte(ACCEL_ZOUT_H, val);
}
CVI_S32 CVI_GYRO_GET_TEMP(CVI_S16 *val)
{
return _cvi_gyro_get_2byte(TEMP_OUT_H, val);
}
CVI_S32 CVI_GYRO_ACC_CALIBRATION(CVI_VOID)
{
if (_dev_check() == 0) {
return ioctl(g_devfd, CVI_GYRO_IOC_ACC_ADJUST);
}
return CVI_FAILURE;
}
CVI_S32 CVI_GYRO_CALIBRATION(CVI_VOID)
{
if (_dev_check() == 0) {
return ioctl(g_devfd, CVI_GYRO_IOC_ADJUST);
}
return CVI_FAILURE;
}
CVI_S32 CVI_GYRO_WHO_AM_I(CVI_U8 *val)
{
CVI_S32 ret = CVI_FAILURE;
struct cvi_gy_regval reg;
if (_dev_check() == 0) {
ret = ioctl(g_devfd, CVI_GYRO_IOC_CHECK, &reg);
if (val != NULL)
*val = (CVI_U8) (reg.val & 0xFF);
}
return ret;
}
CVI_S32 CVI_GYRO_READ(CVI_U8 addr, CVI_U8 *val)
{
CVI_S32 ret = CVI_FAILURE;
struct cvi_gy_regval reg;
if (_dev_check() == 0) {
reg.addr = addr;
ret = ioctl(g_devfd, CVI_GYRO_IOC_READ, &reg);
if (val != NULL)
*val = (CVI_U8) (reg.val & 0xFF);
}
return ret;
}
CVI_S32 CVI_GYRO_WRITE(CVI_U8 addr, CVI_U8 val)
{
CVI_S32 ret = CVI_FAILURE;
struct cvi_gy_regval reg;
if (_dev_check() == 0) {
reg.addr = addr;
reg.val = val;
ret = ioctl(g_devfd, CVI_GYRO_IOC_WRITE, &reg);
}
return ret;
}
CVI_S32 CVI_GYRO_WRITE_OR(CVI_U8 addr, CVI_U8 val)
{
CVI_S32 ret = CVI_FAILURE;
struct cvi_gy_regval reg;
if (_dev_check() == 0) {
reg.addr = addr;
reg.val = val;
ret = ioctl(g_devfd, CVI_GYRO_IOC_WRITE_OR, &reg);
}
return ret;
}
CVI_S32 CVI_GYRO_WRITE_AND(CVI_U8 addr, CVI_U8 val)
{
CVI_S32 ret = CVI_FAILURE;
struct cvi_gy_regval reg;
if (_dev_check() == 0) {
reg.addr = addr;
reg.val = val;
ret = ioctl(g_devfd, CVI_GYRO_IOC_WRITE_AND, &reg);
}
return ret;
}

View File

@@ -0,0 +1,38 @@
SHELL = /bin/bash
ifeq ($(PARAM_FILE), )
PARAM_FILE:=../../Makefile.param
include $(PARAM_FILE)
endif
SDIR = $(PWD)/src
SRCS = $(wildcard $(SDIR)/*.c)
INCS = -I./include -I$(MW_INC) -I$(KERNEL_INC) -I$(SYS_INC) -I../../3rdparty
OBJS = $(SRCS:.c=.o)
DEPS = $(SRCS:.c=.d)
TARGET_A = $(MW_LIB)/libcvi_ive.a
TARGET_SO = $(MW_LIB)/libcvi_ive.so
EXTRA_CFLAGS = $(INCS)
.PHONY : clean all install
all : $(TARGET_A) $(TARGET_SO) install
install:
@cp include/cvi_ive.h $(MW_INC)
$(SDIR)/%.o: $(SDIR)/%.c
@$(CC) $(DEPFLAGS) $(CFLAGS) $(EXTRA_CFLAGS) -o $@ -c $<
@echo [$(notdir $(CC))] $(notdir $@)
$(TARGET_A): $(OBJS)
@$(AR) $(ARFLAGS) $(TARGET_A) $(OBJS)
@echo -e $(YELLOW)[LINK]$(END)[$(notdir $(AR))] $(notdir $(TARGET_A))
$(TARGET_SO): $(OBJS)
@$(LD) $(LDFLAGS) $(EXTRA_LDFLAGS) -o $@ --start-group $(OBJS) --end-group
@echo -e $(GREEN)[LINK]$(END)[$(notdir $(LD))] $(notdir $(TARGET_SO))
clean:
@rm -f $(OBJS) $(DEPS) $(TARGET_A) $(TARGET_SO)
-include $(DEPS)

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,35 @@
SHELL = /bin/bash
ifeq ($(PARAM_FILE), )
PARAM_FILE:=../../Makefile.param
include $(PARAM_FILE)
endif
SDIR = $(PWD)/src
SRCS = $(wildcard $(SDIR)/*.c)
INCS = -I$(MW_INC) -I$(KERNEL_INC) -I$(SYS_INC) -I./include
OBJS = $(SRCS:.c=.o)
DEPS = $(SRCS:.c=.d)
TARGET_A = $(MW_LIB)/libmipi_tx.a
TARGET_SO = $(MW_LIB)/libmipi_tx.so
EXTRA_CFLAGS = $(INCS)
.PHONY : clean all
all : $(TARGET_A) $(TARGET_SO)
$(SDIR)/%.o: $(SDIR)/%.c
@$(CC) $(DEPFLAGS) $(CFLAGS) $(EXTRA_CFLAGS) -o $@ -c $<
@echo [$(notdir $(CC))] $(notdir $@)
$(TARGET_A): $(OBJS)
@$(AR) $(ARFLAGS) $(TARGET_A) $(OBJS)
@echo -e $(YELLOW)[LINK]$(END)[$(notdir $(AR))] $(notdir $(TARGET_A))
$(TARGET_SO): $(OBJS)
@$(LD) $(LDFLAGS) $(EXTRA_LDFLAGS) -o $@ --start-group $(OBJS) --end-group
@echo -e $(GREEN)[LINK]$(END)[$(notdir $(LD))] $(notdir $(TARGET_SO))
clean:
@rm -f $(OBJS) $(DEPS) $(TARGET_A) $(TARGET_SO)
-include $(DEPS)

View File

@@ -0,0 +1,153 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include <assert.h>
#include <unistd.h>
#include <fcntl.h> /* low-level i/o */
#include <unistd.h>
#include <errno.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include "mipi_tx.h"
static void _cal_htt_extra(struct combo_dev_cfg_s *dev_cfg)
{
unsigned char lane_num = 0, bits = 0;
unsigned short htt_old, htt_new, htt_new_extra;
unsigned short vtt;
float fps;
float bit_rate_MHz;
float clk_hs_MHz;
float clk_hs_ns;
float line_rate_KHz, line_time_us;
float over_head;
float t_period_max, t_period_real;
struct sync_info_s *sync_info = &dev_cfg->sync_info;
for (int i = 0; i < LANE_MAX_NUM; i++) {
if ((dev_cfg->lane_id[i] < 0) || (dev_cfg->lane_id[i] >= MIPI_TX_LANE_MAX))
continue;
if (dev_cfg->lane_id[i] != MIPI_TX_LANE_CLK)
++lane_num;
}
switch (dev_cfg->output_format) {
case OUT_FORMAT_RGB_16_BIT:
bits = 16;
break;
case OUT_FORMAT_RGB_18_BIT:
bits = 18;
break;
case OUT_FORMAT_RGB_24_BIT:
bits = 24;
break;
case OUT_FORMAT_RGB_30_BIT:
bits = 30;
break;
default:
break;
}
htt_old = sync_info->vid_hsa_pixels + sync_info->vid_hbp_pixels
+ sync_info->vid_hline_pixels + sync_info->vid_hfp_pixels;
vtt = sync_info->vid_vsa_lines + sync_info->vid_vbp_lines
+ sync_info->vid_active_lines + sync_info->vid_vfp_lines;
fps = dev_cfg->pixel_clk * 1000.0 / (htt_old * vtt);
bit_rate_MHz = dev_cfg->pixel_clk / 1000.0 * bits / lane_num;
clk_hs_MHz = bit_rate_MHz / 2;
clk_hs_ns = 1000 / clk_hs_MHz;
line_rate_KHz = vtt * fps / 1000;
line_time_us = 1000 / line_rate_KHz;
over_head = (3 * 50 * 2 * 3) + clk_hs_ns * 360;
t_period_max = line_time_us * 1000 - over_head;
t_period_real = clk_hs_ns * sync_info->vid_hline_pixels * bits / 4 / 2;
htt_new = (unsigned short)(htt_old * t_period_real / t_period_max);
if (htt_new > htt_old) {
if (htt_new & 0x0003)
htt_new += (4 - (htt_new & 0x0003));
htt_new_extra = htt_new - htt_old;
sync_info->vid_hfp_pixels += htt_new_extra;
dev_cfg->pixel_clk = htt_new * vtt * fps / 1000;
}
}
int mipi_tx_cfg(int fd, struct combo_dev_cfg_s *dev_cfg)
{
struct combo_dev_cfg_s dev_cfg_t = *dev_cfg;
_cal_htt_extra(&dev_cfg_t);
if (-1 == ioctl(fd, CVI_VIP_MIPI_TX_SET_DEV_CFG, &dev_cfg_t)) {
perror("CVI_VIP_MIPI_TX_SET_DEV_CFG");
return -1;
}
return 0;
}
int mipi_tx_send_cmd(int fd, struct cmd_info_s *cmd_info)
{
if (cmd_info->cmd_size == 0)
return -1;
if (-1 == ioctl(fd, CVI_VIP_MIPI_TX_SET_CMD, cmd_info)) {
perror("CVI_VIP_MIPI_TX_SET_CMD");
return -1;
}
return 0;
}
int mipi_tx_recv_cmd(int fd, struct get_cmd_info_s *cmd_info)
{
if (cmd_info->get_data_size == 0)
return -1;
if (-1 == ioctl(fd, CVI_VIP_MIPI_TX_GET_CMD, cmd_info)) {
perror("CVI_VIP_MIPI_TX_GET_CMD");
return -1;
}
return 0;
}
int mipi_tx_enable(int fd)
{
if (-1 == ioctl(fd, CVI_VIP_MIPI_TX_ENABLE, NULL)) {
perror("CVI_VIP_MIPI_TX_ENABLE");
return -1;
}
return 0;
}
int mipi_tx_disable(int fd)
{
if (-1 == ioctl(fd, CVI_VIP_MIPI_TX_DISABLE, NULL)) {
perror("CVI_VIP_MIPI_TX_DISABLE");
return -1;
}
return 0;
}
int mipi_tx_set_hs_settle(int fd, const struct hs_settle_s *hs_cfg)
{
if (-1 == ioctl(fd, CVI_VIP_MIPI_TX_SET_HS_SETTLE, hs_cfg)) {
perror("CVI_VIP_MIPI_TX_SET_HS_SETTLE");
return -1;
}
return 0;
}
int mipi_tx_get_hs_settle(int fd, struct hs_settle_s *hs_cfg)
{
if (-1 == ioctl(fd, CVI_VIP_MIPI_TX_GET_HS_SETTLE, hs_cfg)) {
perror("CVI_VIP_MIPI_TX_GET_HS_SETTLE");
return -1;
}
return 0;
}

View File

@@ -0,0 +1,35 @@
SHELL = /bin/bash
ifeq ($(PARAM_FILE), )
PARAM_FILE:=../../Makefile.param
include $(PARAM_FILE)
endif
SDIR = $(PWD)/src
SRCS = $(wildcard $(SDIR)/*.c)
INCS = -I$(MW_INC)
OBJS = $(SRCS:.c=.o)
DEPS = $(SRCS:.c=.d)
TARGET_A = $(MW_LIB)/libmisc.a
TARGET_SO = $(MW_LIB)/libmisc.so
EXTRA_CFLAGS = -I$(MW_INC) -I$(KERNEL_INC) -I$(SYS_INC)
.PHONY : clean all
all : $(TARGET_A) $(TARGET_SO)
$(SDIR)/%.o: $(SDIR)/%.c
@$(CC) $(DEPFLAGS) $(CFLAGS) $(EXTRA_CFLAGS) -o $@ -c $<
@echo [$(notdir $(CC))] $(notdir $@)
$(TARGET_A): $(OBJS)
@$(AR) $(ARFLAGS) $(TARGET_A) $(OBJS)
@echo -e $(YELLOW)[LINK]$(END)[$(notdir $(AR))] $(notdir $(TARGET_A))
$(TARGET_SO): $(OBJS)
@$(LD) $(LDFLAGS) $(EXTRA_LDFLAGS) -o $@ --start-group $(OBJS) --end-group
@echo -e $(GREEN)[LINK]$(END)[$(notdir $(LD))] $(notdir $(TARGET_SO))
clean:
@rm -f $(OBJS) $(DEPS) $(TARGET_A) $(TARGET_SO)
-include $(DEPS)

View File

@@ -0,0 +1,667 @@
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <fcntl.h> /* low-level i/o */
#include <unistd.h>
#include <signal.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <sys/prctl.h>
#include <linux/cvi_base.h>
#include <cvi_sys.h>
#include <cvi_misc.h>
#include <linux/cvi_errno.h>
#include "cvi_base.h"
#define CVI_EFUSE_CHIP_SN_SIZE 8
#define CVI_EFUSE_CHIP_SN_ADDR 0x0C
CVI_S32 CVI_MISC_SysSuspend(void)
{
CVI_VPSS_Suspend();
//CVI_GDC_Suspend();
CVI_VO_Suspend();
//TODO
//v4l2_dev_close(false, true, true, true);
return CVI_SUCCESS;
}
CVI_S32 CVI_MISC_SysResume(void)
{
//TODO
//v4l2_dev_open(false, true, true, true);
VI_VPSS_MODE_S stVIVPSSMode;
VPSS_MODE_S stVPSSMode;
CVI_SYS_GetVIVPSSMode(&stVIVPSSMode);
CVI_SYS_GetVPSSModeEx(&stVPSSMode);
//TODO
#if 0
if (init_vpss_device() != CVI_SUCCESS) {
CVI_TRACE_SYS(CVI_DBG_ERR, "init vpss failed.\n");
return CVI_FAILURE;
}
if (init_disp_device() != CVI_SUCCESS) {
CVI_TRACE_SYS(CVI_DBG_ERR, "init disp failed.\n");
return CVI_FAILURE;
}
if (init_dwa_device() != CVI_SUCCESS) {
CVI_TRACE_SYS(CVI_DBG_ERR, "init dwa failed.\n");
return CVI_FAILURE;
}
if (init_isp_device() != CVI_SUCCESS) {
CVI_TRACE_SYS(CVI_DBG_ERR, "init isp failed.\n");
return CVI_FAILURE;
}
#endif
CVI_SYS_SetVIVPSSMode(&stVIVPSSMode);
CVI_SYS_SetVPSSModeEx(&stVPSSMode);
CVI_VO_Resume();
//CVI_GDC_Resume();
CVI_VPSS_Resume();
return CVI_SUCCESS;
}
CVI_S32 CVI_MISC_GetChipSNSize(CVI_U32 *pu32SNSize)
{
if (pu32SNSize)
*pu32SNSize = CVI_EFUSE_CHIP_SN_SIZE;
return CVI_SUCCESS;
}
CVI_S32 CVI_MISC_GetChipSN(CVI_U8 *pu8SN, CVI_U32 u32SNSize)
{
FILE *fp;
if (!pu8SN)
return CVI_ERR_SYS_ILLEGAL_PARAM;
fp = fopen("/sys/class/cvi-base/base_efuse_shadow", "r");
if (!fp) {
CVI_TRACE_SYS(CVI_DBG_ERR, "Can't open efuse file.\n");
return CVI_ERR_SYS_NOTREADY;
}
if (u32SNSize > CVI_EFUSE_CHIP_SN_SIZE)
u32SNSize = CVI_EFUSE_CHIP_SN_SIZE;
fseek(fp, CVI_EFUSE_CHIP_SN_ADDR, SEEK_SET);
if (fread(pu8SN, 1, u32SNSize, fp) != u32SNSize) {
CVI_TRACE_SYS(CVI_DBG_ERR, "fread failed\n");
return CVI_FAILURE;
}
fclose(fp);
return CVI_SUCCESS;
}
#define SIGBASE_STATE_CHANGE 44
pthread_t pm_thread;
CVI_BOOL g_is_pm_running = CVI_FALSE;
static CVI_S32 register_pm_ioctl(int io_fd)
{
struct base_statesignal cs;
int ret;
memset(&cs, 0, sizeof(cs));
cs.signr = SIGBASE_STATE_CHANGE;
ret = ioctl(io_fd, IOCTL_STATESIG, &cs);
if (ret < 0) {
CVI_TRACE_SYS(CVI_DBG_ERR, "register connect signal fail %d", ret);
return -1;
}
return 0;
}
static CVI_VOID *pm_event_handler(CVI_VOID *data)
{
int base_pm_fd;
sigset_t mask;
siginfo_t info;
struct timespec ts;
int ret;
prctl(PR_SET_NAME, "pm_event_handler");
(void)(data);
if (open_device(BASE_DEV_NAME, &base_pm_fd) == -1) {
CVI_TRACE_SYS(CVI_DBG_ERR, "base dev open fail!\n");
return NULL;
}
/* BLOCK signal. */
sigemptyset(&mask);
sigaddset(&mask, SIGBASE_STATE_CHANGE);
if (sigprocmask(SIG_BLOCK, &mask, NULL) == -1) {
CVI_TRACE_SYS(CVI_DBG_ERR, "Cannot block SIGBASE_STATE_CHANGE: %s.\n", strerror(errno));
return NULL;
}
/* register signal */
if (register_pm_ioctl(base_pm_fd) < 0)
return NULL;
/* configure the timeout 50ms */
ts.tv_sec = 0;
ts.tv_nsec = 50000000;
while (g_is_pm_running) {
sigemptyset(&mask);
sigaddset(&mask, SIGBASE_STATE_CHANGE);
ret = sigtimedwait(&mask, &info, &ts);
if (ret == -1) {
if (errno == EINTR || errno == EAGAIN)
continue;
CVI_TRACE_SYS(CVI_DBG_ERR, "sigwaitinfo() failed: %s.\n", strerror(errno));
goto exit_loop;
}
if (info.si_signo == SIGBASE_STATE_CHANGE) {
CVI_U32 pm_state;
/* get current state. */
ret = ioctl(base_pm_fd, IOCTL_READ_STATE, &pm_state);
if (ret < 0) {
CVI_TRACE_SYS(CVI_DBG_ERR, "get currenct state fail %d\n", ret);
goto exit_loop;
}
CVI_TRACE_SYS(CVI_DBG_INFO, "receive state %d\n", pm_state);
printf("receive state %d\n", pm_state);
switch (pm_state) {
case BASE_STATE_SUSPEND_PREPARE: {
/* call VIP user space suspend. */
CVI_VI_Suspend();
CVI_MISC_SysSuspend();
/* notify the user space suspend is complete*/
ret = ioctl(base_pm_fd, IOCTL_USER_SUSPEND_DONE, 0);
if (ret < 0) {
CVI_TRACE_SYS(CVI_DBG_ERR, "set suspend done fail %d\n", ret);
goto exit_loop;
}
break;
}
case BASE_STATE_RESUME: {
CVI_MISC_SysResume();
/* call VIP user space resume. */
CVI_VI_Resume();
/* notify the user space resume is complete*/
ret = ioctl(base_pm_fd, IOCTL_USER_RESUME_DONE, 0);
if (ret < 0) {
CVI_TRACE_SYS(CVI_DBG_ERR, "set resume done fail %d\n", ret);
goto exit_loop;
}
break;
}
default:
/* receive other state change */
break;
}
} else {
CVI_TRACE_SYS(CVI_DBG_DEBUG, "other signal number %d, %d\n", ret, info.si_signo);
}
}
close(base_pm_fd);
exit_loop:
g_is_pm_running = CVI_FALSE;
pthread_exit(NULL);
}
CVI_S32 CVI_MISC_StartPMThread(void)
{
struct sched_param param;
pthread_attr_t attr;
if (g_is_pm_running == CVI_TRUE) {
CVI_TRACE_SYS(CVI_DBG_WARN, "already started\n");
return CVI_FAILURE;
}
g_is_pm_running = CVI_TRUE;
param.sched_priority = 70;
pthread_attr_init(&attr);
pthread_attr_setschedpolicy(&attr, SCHED_RR);
pthread_attr_setschedparam(&attr, &param);
pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED);
pthread_create(&pm_thread, &attr, (void *)pm_event_handler, NULL);
CVI_TRACE_SYS(CVI_DBG_INFO, "CVI_SYS_StartPMThread\n");
return CVI_SUCCESS;
}
CVI_S32 CVI_MISC_StopPMThread(void)
{
if (g_is_pm_running == CVI_FALSE) {
CVI_TRACE_SYS(CVI_DBG_WARN, "not start yet\n");
return CVI_FAILURE;
}
g_is_pm_running = CVI_FALSE;
if (pm_thread) {
pthread_join(pm_thread, NULL);
pm_thread = 0;
}
CVI_TRACE_SYS(CVI_DBG_INFO, "CVI_SYS_StopPMThread\n");
return CVI_SUCCESS;
}
// ===========================================================================
// EFUSE API
// ===========================================================================
static struct _CVI_EFUSE_AREA_S {
CVI_U32 addr;
CVI_U32 size;
} cvi_efuse_area[] = { [CVI_EFUSE_AREA_USER] = { 0x40, 40 },
[CVI_EFUSE_AREA_DEVICE_ID] = { 0x8c, 8 },
[CVI_EFUSE_AREA_HASH0_PUBLIC] = { 0xA8, 32 },
[CVI_EFUSE_AREA_LOADER_EK] = { 0xD8, 16 },
[CVI_EFUSE_AREA_DEVICE_EK] = { 0xE8, 16 },
[CVI_EFUSE_AREA_CHIP_SN] = { 0x0C, 8 } };
static struct _CVI_EFUSE_LOCK_S {
CVI_U32 wlock_shift;
CVI_U32 rlock_shift;
} cvi_efuse_lock[] = { [CVI_EFUSE_LOCK_HASH0_PUBLIC] = { 0, 8 },
[CVI_EFUSE_LOCK_LOADER_EK] = { 4, 12 },
[CVI_EFUSE_LOCK_DEVICE_EK] = { 6, 14 } };
static struct _CVI_EFUSE_USER_S {
CVI_U32 addr;
CVI_U32 size;
} cvi_efuse_user[] = {
{ 0x40, 4 },
{ 0x48, 4 },
{ 0x50, 4 },
{ 0x58, 4 },
{ 0x60, 4 },
{ 0x68, 4 },
{ 0x70, 4 },
{ 0x78, 4 },
{ 0x80, 4 },
{ 0x88, 4 },
};
#define CVI_EFUSE_TOTAL_SIZE 0x100
#define CVI_EFUSE_LOCK_ADDR 0xF8
#define CVI_EFUSE_SECURE_CONF_ADDR 0xA0
#define CVI_EFUSE_SCS_ENABLE_SHIFT 0
#define CVI_EFUSE_SW_INFO 0x2C
#define CVI_EFUSE_CUSTOMER_ADDR 0x4
#define CVI_EFUSE_PATH_PROG "/sys/class/cvi-base/base_efuse_prog"
#define CVI_EFUSE_PATH_SHADOW "/sys/class/cvi-base/base_efuse_shadow"
CVI_S32 CVI_EFUSE_GetSize(CVI_EFUSE_AREA_E area, CVI_U32 *size)
{
if (area >= ARRAY_SIZE(cvi_efuse_area) ||
cvi_efuse_area[area].size == 0) {
CVI_TRACE_SYS(CVI_DBG_ERR, "area (%d) is not found\n", area);
return CVI_ERR_SYS_NOMEM;
}
if (size)
*size = cvi_efuse_area[area].size;
return 0;
}
static CVI_S32 _CVI_EFUSE_Read(CVI_U32 addr, void *buf, CVI_U32 buf_size)
{
CVI_S32 ret = -1;
CVI_TRACE_SYS(CVI_DBG_DEBUG, "addr=0x%02x\n", addr);
if (!buf)
return CVI_ERR_SYS_ILLEGAL_PARAM;
FILE *fp = fopen(CVI_EFUSE_PATH_SHADOW, "r");
if (!fp) {
ret = errno;
CVI_TRACE_SYS(CVI_DBG_ERR, "fopen(%s)\n",
CVI_EFUSE_PATH_SHADOW);
return ret;
}
fseek(fp, addr, SEEK_SET);
ret = fread(buf, buf_size, 1, fp);
if (ret < 0)
CVI_TRACE_SYS(CVI_DBG_ERR, "ret=%d\n", ret);
fclose(fp);
return ret;
}
static CVI_S32 _CVI_EFUSE_Write(CVI_U32 addr, const void *buf, CVI_U32 buf_size)
{
CVI_TRACE_SYS(CVI_DBG_DEBUG, "addr=0x%02x\n", addr);
char cmd[64];
CVI_U32 value;
CVI_U32 aligned_addr = addr;
CVI_U32 aligned_size = buf_size;
void *aligned_buf = NULL;
size_t i;
if (!buf)
return CVI_ERR_SYS_ILLEGAL_PARAM;
if (aligned_addr % 4) {
aligned_addr -= aligned_addr % 4;
}
if (aligned_size % 4) {
aligned_size += 4 - aligned_size % 4;
}
aligned_buf = malloc(aligned_size);
memset(aligned_buf, 0, aligned_size);
memcpy((CVI_U8 *)aligned_buf + (addr - aligned_addr), buf, buf_size);
for (i = 0; i < aligned_size; i += 4) {
memcpy(&value, (CVI_U8 *)aligned_buf + i, sizeof(value));
snprintf(cmd, sizeof(cmd), "0x%04zx=0x%08x", addr + i, value);
CVI_TRACE_SYS(CVI_DBG_DEBUG, "cmd=%s\n", cmd);
FILE *fp = fopen(CVI_EFUSE_PATH_PROG, "w");
int ret;
if (!fp) {
ret = errno;
CVI_TRACE_SYS(CVI_DBG_ERR, "fopen(%s)\n",
CVI_EFUSE_PATH_PROG);
return ret;
}
ret = fwrite(cmd, strlen(cmd), 1, fp);
if (ret < 0)
CVI_TRACE_SYS(CVI_DBG_ERR, "ret=%d\n", ret);
fclose(fp);
}
return 0;
}
CVI_S32 CVI_EFUSE_Read(CVI_EFUSE_AREA_E area, CVI_U8 *buf, CVI_U32 buf_size)
{
CVI_U32 user_size = cvi_efuse_area[CVI_EFUSE_AREA_USER].size;
CVI_U8 user[user_size], *p;
CVI_S32 ret;
size_t i;
if (area >= ARRAY_SIZE(cvi_efuse_area) ||
cvi_efuse_area[area].size == 0) {
CVI_TRACE_SYS(CVI_DBG_ERR, "area (%d) is not found\n", area);
return CVI_ERR_SYS_NOMEM;
}
if (!buf)
return CVI_ERR_SYS_ILLEGAL_PARAM;
memset(buf, 0, buf_size);
if (buf_size > cvi_efuse_area[area].size)
buf_size = cvi_efuse_area[area].size;
if (area != CVI_EFUSE_AREA_USER)
return _CVI_EFUSE_Read(cvi_efuse_area[area].addr, buf,
buf_size);
memset(user, 0, user_size);
p = user;
for (i = 0; i < ARRAY_SIZE(cvi_efuse_user); i++) {
ret = _CVI_EFUSE_Read(cvi_efuse_user[i].addr, p,
cvi_efuse_user[i].size);
if (ret < 0)
return ret;
p += cvi_efuse_user[i].size;
}
memcpy(buf, user, buf_size);
return CVI_SUCCESS;
}
CVI_S32 CVI_EFUSE_Write(CVI_EFUSE_AREA_E area, const CVI_U8 *buf,
CVI_U32 buf_size)
{
CVI_U32 user_size = cvi_efuse_area[CVI_EFUSE_AREA_USER].size;
CVI_U8 user[user_size], *p;
CVI_S32 ret;
size_t i;
if (area >= ARRAY_SIZE(cvi_efuse_area) ||
cvi_efuse_area[area].size == 0) {
CVI_TRACE_SYS(CVI_DBG_ERR, "area (%d) is not found\n", area);
return CVI_ERR_SYS_NOMEM;
}
if (!buf)
return CVI_ERR_SYS_ILLEGAL_PARAM;
if (buf_size > cvi_efuse_area[area].size)
buf_size = cvi_efuse_area[area].size;
if (area != CVI_EFUSE_AREA_USER) {
return _CVI_EFUSE_Write(cvi_efuse_area[area].addr, buf,
buf_size);
}
memset(user, 0, user_size);
memcpy(user, buf, buf_size);
p = user;
for (i = 0; i < ARRAY_SIZE(cvi_efuse_user); i++) {
ret = _CVI_EFUSE_Write(cvi_efuse_user[i].addr, p,
cvi_efuse_user[i].size);
if (ret < 0)
return ret;
p += cvi_efuse_user[i].size;
}
return CVI_SUCCESS;
}
CVI_S32 CVI_EFUSE_EnableSecureBoot(void)
{
CVI_U32 value = 0x3 << CVI_EFUSE_SCS_ENABLE_SHIFT;
return _CVI_EFUSE_Write(CVI_EFUSE_SECURE_CONF_ADDR, &value,
sizeof(value));
}
CVI_S32 CVI_EFUSE_IsSecureBootEnabled(void)
{
CVI_U32 value = 0;
CVI_S32 ret = 0;
ret = _CVI_EFUSE_Read(CVI_EFUSE_SECURE_CONF_ADDR, &value,
sizeof(value));
CVI_TRACE_SYS(CVI_DBG_DEBUG, "ret=%d value=%u\n", ret, value);
if (ret < 0)
return ret;
value &= 0x3 << CVI_EFUSE_SCS_ENABLE_SHIFT;
return !!value;
}
CVI_S32 CVI_EFUSE_EnableFastBoot(void)
{
CVI_U32 value = 0, data;
CVI_S32 ret = 0;
CVI_U32 chip = 0;
CVI_SYS_GetChipId(&chip);
if (!IS_CHIP_CV181X(chip) && !IS_CHIP_CV180X(chip)) {
CVI_TRACE_SYS(CVI_DBG_DEBUG, "chip id=%d\n", chip);
return CVI_FAILURE;
}
ret = _CVI_EFUSE_Read(CVI_EFUSE_SW_INFO, &value, sizeof(value));
CVI_TRACE_SYS(CVI_DBG_DEBUG, "ret=%d value=%u\n", ret, value);
if (ret < 0)
return ret;
data = (value & (0x3 << 22)) >> 22;
if (data > 0x1)
return CVI_FAILURE;
data = (value & (0x3 << 24)) >> 24;
if (data > 0x1)
return CVI_FAILURE;
data = (value & (0x3 << 26)) >> 26;
if (data > 0x1)
return CVI_FAILURE;
// set sd dl button
value = (0x1 << 22);
value |= (0x1 << 24);
value |= (0x1 << 26);
ret = _CVI_EFUSE_Write(CVI_EFUSE_SW_INFO, &value, sizeof(value));
if (ret < 0)
return ret;
if (IS_CHIP_PKG_TYPE_QFN(chip))
value = 0x1E1E64; // AUX0
else
value = 0x1; // USB_ID
return _CVI_EFUSE_Write(CVI_EFUSE_CUSTOMER_ADDR, &value, sizeof(value));
}
CVI_S32 CVI_EFUSE_IsFastBootEnabled(void)
{
CVI_U32 value = 0;
CVI_S32 ret = 0;
CVI_U32 chip = 0;
CVI_SYS_GetChipId(&chip);
if (!IS_CHIP_CV181X(chip) && !IS_CHIP_CV180X(chip)) {
CVI_TRACE_SYS(CVI_DBG_DEBUG, "chip id=%d\n", chip);
return CVI_FAILURE;
}
ret = _CVI_EFUSE_Read(CVI_EFUSE_SW_INFO, &value, sizeof(value));
CVI_TRACE_SYS(CVI_DBG_DEBUG, "ret=%d value=%u\n", ret, value);
if (ret < 0)
return ret;
if (((value & (0x3 << 22)) != (0x1 << 22))
&& ((value & (0x3 << 24)) != (0x1 << 24))
&& ((value & (0x3 << 26)) != (0x1 << 26))) {
CVI_TRACE_SYS(CVI_DBG_DEBUG, "sw_info isn't fastboot config\n");
return CVI_FAILURE;
}
ret = _CVI_EFUSE_Read(CVI_EFUSE_CUSTOMER_ADDR, &value, sizeof(value));
CVI_TRACE_SYS(CVI_DBG_DEBUG, "ret=%d value=%u\n", ret, value);
if (ret < 0)
return ret;
if (IS_CHIP_PKG_TYPE_QFN(chip)) {
if (value == 0x1E1E64)
return CVI_SUCCESS; // AUX0
else
return CVI_FAILURE;
} else {
if (value == 0x1)
return CVI_SUCCESS; // USB_ID
else
return CVI_FAILURE;
}
return CVI_FAILURE;
}
CVI_S32 CVI_EFUSE_Lock(CVI_EFUSE_LOCK_E lock)
{
CVI_U32 value = 0;
CVI_S32 ret = 0;
if (lock >= ARRAY_SIZE(cvi_efuse_lock)) {
CVI_TRACE_SYS(CVI_DBG_ERR, "lock (%d) is not found\n", lock);
return CVI_ERR_SYS_NOMEM;
}
value = 0x3 << cvi_efuse_lock[lock].wlock_shift;
ret = _CVI_EFUSE_Write(CVI_EFUSE_LOCK_ADDR, &value, sizeof(value));
if (ret < 0)
return ret;
value = 0x3 << cvi_efuse_lock[lock].rlock_shift;
ret = _CVI_EFUSE_Write(CVI_EFUSE_LOCK_ADDR, &value, sizeof(value));
return ret;
}
CVI_S32 CVI_EFUSE_IsLocked(CVI_EFUSE_LOCK_E lock)
{
CVI_S32 ret = 0;
CVI_U32 value = 0;
if (lock >= ARRAY_SIZE(cvi_efuse_lock)) {
CVI_TRACE_SYS(CVI_DBG_ERR, "lock (%d) is not found\n", lock);
return CVI_ERR_SYS_NOMEM;
}
ret = _CVI_EFUSE_Read(CVI_EFUSE_LOCK_ADDR, &value, sizeof(value));
CVI_TRACE_SYS(CVI_DBG_DEBUG, "ret=%d value=%u\n", ret, value);
if (ret < 0)
return ret;
value &= 0x3 << cvi_efuse_lock[lock].wlock_shift;
return !!value;
}
CVI_S32 CVI_EFUSE_LockWrite(CVI_EFUSE_LOCK_E lock)
{
CVI_U32 value = 0;
CVI_S32 ret = 0;
if (lock >= ARRAY_SIZE(cvi_efuse_lock)) {
CVI_TRACE_SYS(CVI_DBG_ERR, "lock (%d) is not found\n", lock);
return CVI_ERR_SYS_NOMEM;
}
value = 0x3 << cvi_efuse_lock[lock].wlock_shift;
ret = _CVI_EFUSE_Write(CVI_EFUSE_LOCK_ADDR, &value, sizeof(value));
return ret;
}
CVI_S32 CVI_EFUSE_IsWriteLocked(CVI_EFUSE_LOCK_E lock)
{
CVI_S32 ret = 0;
CVI_U32 value = 0;
if (lock >= ARRAY_SIZE(cvi_efuse_lock)) {
CVI_TRACE_SYS(CVI_DBG_ERR, "lock (%d) is not found\n", lock);
return CVI_ERR_SYS_NOMEM;
}
ret = _CVI_EFUSE_Read(CVI_EFUSE_LOCK_ADDR, &value, sizeof(value));
CVI_TRACE_SYS(CVI_DBG_DEBUG, "ret=%d value=%u\n", ret, value);
if (ret < 0)
return ret;
value &= 0x3 << cvi_efuse_lock[lock].wlock_shift;
return !!value;
}

View File

@@ -0,0 +1,65 @@
SHELL = /bin/bash
ifeq ($(PARAM_FILE), )
PARAM_FILE:=../../Makefile.param
include $(PARAM_FILE)
endif
SDIR = $(PWD)/src
CSRCS := $(wildcard $(SDIR)/*.c)
COBJS = $(CSRCS:.c=.o)
CDEPS = $(CSRCS:.c=.d)
CXXSRCS := $(wildcard $(SDIR)/*.cpp)
CXXOBJS = $(CXXSRCS:.cpp=.o)
CXXDEPS = $(CXXSRCS:.cpp=.d)
TARGET_A = $(MW_LIB)/libosdc.a
TARGET_SO = $(MW_LIB)/libosdc.so
INCS = -I$(MW_INC) -I$(KERNEL_INC) -I$(OSDC_INC)
EXTRA_CFLAGS = $(INCS) -fpack-struct=8
EXTRA_CFLAGS += -DMMF_VERSION=\"$(shell git describe --always)\"
EXTRA_CFLAGS += -DSDK_VER=\"$(SDK_VER)\"
ifeq ($(SDK_VER), 32bit)
EXTRA_CFLAGS += -D_FILE_OFFSET_BITS=64
endif
EXTRA_CXXFLAGS = $(INCS) -fpack-struct=8
EXTRA_CXXFLAGS += -DMMF_VERSION=\"$(shell git describe --always)\"
EXTRA_CXXFLAGS += -DSDK_VER=\"$(SDK_VER)\"
ifeq ($(SDK_VER), 32bit)
EXTRA_CXXFLAGS += -D_FILE_OFFSET_BITS=64
endif
.PHONY : clean all
all : prepare $(TARGET_A) $(TARGET_SO)
prepare:
cp include/cmpr_canvas.h $(MW_INC)
cp include/cvi_osdc.h $(MW_INC)
cp include/osd_cmpr.h $(MW_INC)
$(SDIR)/%.o: $(SDIR)/%.c
@$(CC) $(DEPFLAGS) $(CFLAGS) $(EXTRA_CFLAGS) -o $@ -c $<
@echo [$(notdir $(CC))] $(notdir $@)
$(SDIR)/%.o: $(SDIR)/%.cpp
@$(CXX) $(DEPFLAGS) $(CXXFLAGS) $(EXTRA_CXXFLAGS) -o $@ -c $<
@echo [$(notdir $(CC))] $(notdir $@)
$(TARGET_A): $(COBJS) $(CXXOBJS)
@$(AR) $(ARFLAGS) $(TARGET_A) $(COBJS) $(CXXOBJS)
@echo -e $(YELLOW)[LINK]$(END)[$(notdir $(AR))] $(notdir $(TARGET_A))
@echo "$$AR_MRI" | $(AR) -M
$(TARGET_SO): $(OBJS) $(CXXOBJS)
@$(LD) $(LDFLAGS) $(EXTRA_LDFLAGS) -o $(TARGET_SO) --start-group $(COBJS) $(CXXOBJS) $(LIBS) --end-group
@echo -e $(GREEN)[LINK]$(END)[$(notdir $(LD))] $(notdir $(TARGET_SO))
clean:
@rm -f $(COBJS) $(CXXOBJS) $(CDEPS) $(CXXDEPS) $(TARGET_A) $(TARGET_SO)
@rm -f $(MW_INC)/cmpr_canvas.h
@rm -f $(MW_INC)/cvi_osdc.h
@rm -f $(MW_INC)/osd_cmpr.h
-include $(DEPS)

View File

@@ -0,0 +1,740 @@
#include "cmpr_canvas.h"
static bool is_in_range(int x, int begin, int end)
{
return (x >= begin && x < end);
}
template <typename T> T clip(const T &n, const T &lower, const T &upper)
{
return std::max(lower, std::min(n, upper));
}
int count_repeat_pixel(uint8_t *src, int pixel_sz, int pixel_num)
{
int num = pixel_num - 1;
for (int byte_i = 0; byte_i < pixel_sz; byte_i++) {
uint8_t ref = src[byte_i];
uint8_t *cur_ptr = &src[byte_i + pixel_sz];
for (int cnt = 0; cnt < num; cnt++) {
if (ref != (*cur_ptr)) {
num = cnt;
break;
}
cur_ptr += pixel_sz;
}
}
return num + 1;
}
int recycle_obj_slices(vector<OBJ_SLICE> &slice_vec, int end_idx, int x)
{
auto it = slice_vec.begin();
int recycle_cnt = 0;
for (int chk_cnt = 0; chk_cnt <= end_idx; chk_cnt++) {
if (x >= (*it).x1) {
it = slice_vec.erase(it);
recycle_cnt++;
} else {
++it;
}
}
return recycle_cnt;
}
void recycle_draw_obj(vector<DRAW_OBJ> &obj_vec, int y)
{
for (auto it = obj_vec.begin(); it != obj_vec.end();) {
if (y > (*it)._max_y) {
it = obj_vec.erase(it);
} else {
++it;
}
}
}
int obj_project_on_line(vector<DRAW_OBJ> &obj_vec, vector<OBJ_SLICE> &slice_vec,
int y, int &next_y, int canvas_width)
{
for (int obj_i = 0; obj_i < (int)obj_vec.size(); obj_i++) {
DRAW_OBJ &obj_attr = obj_vec[obj_i];
if (is_in_range(y, obj_attr._min_y, obj_attr._max_y) == false) {
next_y = min(next_y, max(obj_attr._min_y, y + 1));
continue;
}
if (obj_attr.type == RECT) {
OBJ_SLICE slice;
slice.x0 = obj_attr.rect.x;
slice.x1 = obj_attr.rect.x + obj_attr.rect.width;
slice.obj_id = obj_i;
slice_vec.push_back(slice);
next_y = min(next_y, obj_attr._max_y);
} else if (obj_attr.type == BIT_MAP ||
obj_attr.type == CMPR_BIT_MAP) {
OBJ_SLICE slice;
slice.x0 = obj_attr.bitmap.rect.x;
slice.x1 = obj_attr.bitmap.rect.x +
obj_attr.bitmap.rect.width;
slice.obj_id = obj_i;
next_y = min(next_y, obj_attr._max_y);
slice_vec.push_back(slice);
} else if (obj_attr.type == STROKE_RECT) {
int y1 = obj_attr.rect.y + obj_attr.rect.thickness;
int y2 = obj_attr.rect.y + obj_attr.rect.height -
obj_attr.rect.thickness;
if (is_in_range(y, y1, y2)) {
OBJ_SLICE slice0, slice1;
slice0.x0 = obj_attr.rect.x;
slice0.x1 = obj_attr.rect.x +
obj_attr.rect.thickness;
slice1.x1 =
obj_attr.rect.x + obj_attr.rect.width;
slice1.x0 = slice1.x1 - obj_attr.rect.thickness;
slice0.obj_id = obj_i;
slice1.obj_id = obj_i;
slice_vec.push_back(slice0);
slice_vec.push_back(slice1);
next_y = min(next_y, y2);
} else {
OBJ_SLICE slice;
slice.x0 = obj_attr.rect.x;
slice.x1 =
obj_attr.rect.x + obj_attr.rect.width;
slice.obj_id = obj_i;
slice_vec.push_back(slice);
next_y = min(
next_y,
(y > y1) ?
obj_attr.rect.y +
obj_attr.rect.height :
y1);
}
} else if (obj_attr.type == LINE) {
float pt_x0, pt_x1;
if (is_in_range(y, round(obj_attr.line._by[0]),
round(obj_attr.line._by[1]))) {
float delta_x0 = obj_attr.line._mx *
(y - obj_attr.line._by[0]);
pt_x0 = obj_attr.line._bx[0] + delta_x0;
float width = (y - obj_attr.line._by[0]) *
(obj_attr.line.ts_h /
(obj_attr.line._by[1] -
obj_attr.line._by[0]));
pt_x1 = pt_x0 - width;
} else if (is_in_range(
y, round(obj_attr.line._by[1]),
round(obj_attr.line._ey[0] + 1.))) {
float delta_x0 = obj_attr.line._mx *
(y - obj_attr.line._by[0]);
pt_x0 = obj_attr.line._bx[0] + delta_x0;
pt_x1 = pt_x0 - obj_attr.line.ts_h;
} else {
float delta_x0 = obj_attr.line._mx *
(y - obj_attr.line._by[1]);
pt_x0 = obj_attr.line._bx[1] + delta_x0;
float width = (obj_attr.line._ey[1] - y) *
(obj_attr.line.ts_h /
(obj_attr.line._ey[1] -
obj_attr.line._ey[0]));
pt_x1 = pt_x0 + width;
}
OBJ_SLICE slice;
slice.x0 = clip((int)round(min(pt_x0, pt_x1)), 0, canvas_width-1);
slice.x1 = clip((int)round(max(pt_x0, pt_x1)), 0, canvas_width-1);
slice.obj_id = obj_i;
slice_vec.push_back(slice);
next_y = y + 1;
}
}
return slice_vec.size();
}
void draw_cmpr_init(Cmpr_Canvas_Ctrl &ctrl, uint8_t *obuf, int buf_size,
Canvas_Attr *canvas)
{
bool trial_enc = (obuf == nullptr) || (buf_size == 0);
OSDCmpr_Ctrl *osdCmpr_ctrl = &ctrl.osdCmpr_ctrl;
//memset(osdCmpr_ctrl, 0, sizeof(OSDCmpr_Ctrl));
*osdCmpr_ctrl = {};
osdCmpr_ctrl->reg_image_width = canvas->width;
osdCmpr_ctrl->reg_image_height = canvas->height;
osdCmpr_ctrl->reg_palette_mode_en = OSDEC_PAL_BD > 0;
osdCmpr_ctrl->reg_palette_idx_bd = OSDEC_PAL_BD;
osdCmpr_ctrl->reg_run_len_bd = OSDEC_RL_BD;
osdCmpr_ctrl->reg_osd_format = canvas->format;
osdCmpr_ctrl->pel_sz = osd_cmpr_get_pixel_sz(canvas->format);
osd_cmpr_frame_init(&ctrl.osdCmpr_ctrl);
int hdr_sz;
if (trial_enc) {
buf_size = 0;
hdr_sz = 0;
} else {
osd_cmpr_enc_header(obuf, osdCmpr_ctrl);
hdr_sz = osd_cmpr_get_header_sz();
}
init_stream(&ctrl.bitstream, &obuf[hdr_sz], buf_size - hdr_sz,
trial_enc);
ctrl.md = NUM_OF_MODE; // must be invalid type to bypass the first run
ctrl.rl_cnt = -1;
}
void draw_cmpr_finish(Cmpr_Canvas_Ctrl &ctrl)
{
int dummy = 0;
RGBA dummy_c;
osd_cmpr_enc_const_pixel(dummy_c, ctrl.last_color, ctrl.rl_cnt, ctrl.md,
ctrl.code, dummy, true, OSDEC_MAX_RL,
&ctrl.osdCmpr_ctrl, &ctrl.bitstream);
}
void draw_cmpr_pixel(uint8_t *color_code_ptr, int length, bool is_first_pel,
Cmpr_Canvas_Ctrl &ctrl)
{
RGBA cur_c =
get_color(color_code_ptr, ctrl.osdCmpr_ctrl.reg_osd_format);
osd_cmpr_enc_const_pixel(cur_c, ctrl.last_color, ctrl.rl_cnt, ctrl.md,
ctrl.code, length, is_first_pel, OSDEC_MAX_RL,
&ctrl.osdCmpr_ctrl, &ctrl.bitstream);
while (length > 0) {
osd_cmpr_enc_followed_run(cur_c, ctrl.rl_cnt, ctrl.md,
ctrl.code, length, OSDEC_MAX_RL,
&ctrl.osdCmpr_ctrl, &ctrl.bitstream);
}
}
void draw_cmpr_canvas_line(Cmpr_Canvas_Ctrl &ctrl, vector<DRAW_OBJ> &obj_vec,
int y, int pixel_sz, vector<SEGMENT> &segment_vec)
{
for (int seg_i = 0; seg_i < (int)segment_vec.size(); seg_i++) {
SEGMENT &segment = segment_vec[seg_i];
if (segment.is_const) {
if(segment.width>0) {
draw_cmpr_pixel((uint8_t *)&segment.color.code,
segment.width, y == 0 && seg_i == 0,
ctrl);
}
} else {
int rep_cnt;
uint8_t *src_ptr = segment.color.buf;
if (segment.is_cmpr) {
int pel_cnt = 0;
while (pel_cnt < segment.width) {
rep_cnt = min(src_ptr[0] + 1,
segment.width - pel_cnt);
uint8_t *cur_ptr = &src_ptr[1];
draw_cmpr_pixel(cur_ptr, rep_cnt,
y == 0 && seg_i == 0 &&
pel_cnt == 0,
ctrl);
src_ptr += (1 + pixel_sz);
pel_cnt += rep_cnt;
}
segment.color.buf += *(segment.bs_len);
obj_vec[segment.id].bitmap.bs_offset +=
*(segment.bs_len);
segment.bs_len++;
} else {
for (int pel_i = 0; pel_i < segment.width;
pel_i += rep_cnt) {
uint8_t *cur_ptr =
&src_ptr[pel_i * pixel_sz];
rep_cnt = count_repeat_pixel(
cur_ptr, pixel_sz,
segment.width - pel_i);
draw_cmpr_pixel(cur_ptr, rep_cnt,
y == 0 && seg_i == 0 &&
pel_i == 0,
ctrl);
}
segment.color.buf +=
(segment.stride * pixel_sz);
}
}
}
}
void plot_segments_on_line(vector<DRAW_OBJ> &obj_vec, int width, int y,
int pixel_sz, int &next_y,
vector<SEGMENT> &segment_vec, uint32_t bg_color_code)
{
vector<OBJ_SLICE> slice_vec;
if (obj_project_on_line(obj_vec, slice_vec, y, next_y, width) == 0) {
SEGMENT bg_seg{ true, false, (uint16_t)width, 0, bg_color_code, 0 };
segment_vec.push_back(bg_seg);
return;
}
int step;
int next_slice_idx = -1;
for (int x = 0; x < width; x += step) {
int obj_idx = -1; // "-1": background
int x0 = x;
int x1 = width;
int slices_num = slice_vec.size();
if (next_slice_idx >= 0) {
x0 = slice_vec[next_slice_idx].x0;
x1 = slice_vec[next_slice_idx].x1;
obj_idx = next_slice_idx;
} else {
// iter all slices
for (int idx = (slices_num - 1); idx >= 0; idx--) {
if (is_in_range(x, slice_vec[idx].x0,
slice_vec[idx].x1)) {
x0 = slice_vec[idx].x0;
x1 = slice_vec[idx].x1;
obj_idx = idx;
break;
}
}
}
// find end point from higher priority slices
next_slice_idx = -1;
int end_x = x1;
for (int hp_slice_i = (slices_num - 1); hp_slice_i > obj_idx;
hp_slice_i--) {
if (is_in_range(slice_vec[hp_slice_i].x0, x0, end_x)) {
end_x = slice_vec[hp_slice_i].x0;
next_slice_idx = hp_slice_i;
}
}
step = end_x - x;
SEGMENT segment{ true, false, (uint16_t)width, 0, bg_color_code, 0 };
segment.width = step;
if (obj_idx >= 0) {
DRAW_OBJ &obj = obj_vec[slice_vec[obj_idx].obj_id];
segment.is_const = (obj.type == BIT_MAP ||
obj.type == CMPR_BIT_MAP) ?
false :
true;
if (segment.is_const) {
segment.color.code = obj.color.code;
} else {
segment.is_cmpr =
(obj.type == BIT_MAP) ? false : true;
int incr_y = y - obj.bitmap.rect.y;
if (!segment.is_cmpr) {
segment.stride = obj.bitmap.stride;
segment.color.buf =
obj.color.buf +
((incr_y * segment.stride) +
(x - slice_vec[obj_idx].x0)) *
pixel_sz;
} else {
segment.color.buf =
&obj.color.buf
[obj.bitmap.bs_offset];
segment.bs_len = &(
(uint16_t *)
obj.color.buf)[incr_y];
segment.id = slice_vec[obj_idx].obj_id;
}
}
// slices required recycle only when current segment is not background
int recycle_cnt = recycle_obj_slices(slice_vec, obj_idx,
x + step);
// correct next slice index due to recycled slices
next_slice_idx -= recycle_cnt;
}
segment_vec.push_back(segment);
} // end of draw a part of a slice
}
// ---------------------- cmpr_canvas main API ----------------------
int draw_cmpr_canvas(Canvas_Attr *canvas, DRAW_OBJ *objs, uint32_t obj_num,
uint8_t *obuf, int buf_size, uint32_t* p_osize)
{
vector<DRAW_OBJ> obj_vec(objs, objs+obj_num);
Cmpr_Canvas_Ctrl ctrl;
draw_cmpr_init(ctrl, obuf, buf_size, canvas);
size_t pixel_sz = osd_cmpr_get_pixel_sz(canvas->format);
int y_step;
for (int y = 0; y < canvas->height; y += y_step) {
int next_y = canvas->height;
vector<SEGMENT> segment_vec;
plot_segments_on_line(obj_vec, canvas->width, y, pixel_sz,
next_y, segment_vec, canvas->bg_color_code);
y_step = next_y - y;
for (int line_i = 0; line_i < y_step; line_i++) {
draw_cmpr_canvas_line(ctrl, obj_vec, y + line_i,
pixel_sz, segment_vec);
}
recycle_draw_obj(obj_vec, y + y_step - 1);
}
draw_cmpr_finish(ctrl);
uint32_t stream_sz = (ctrl.bitstream.bit_pos + 7) >> 3; // in byte
//add 16 bytes per DE's suggestion
*p_osize = (((stream_sz + osd_cmpr_get_header_sz() + 15) >> 4) + 1) << 4; // 16byte align
return ctrl.bitstream.status;
}
#if (CMPR_CANVAS_DBG)
void fill_n_pixel(void *dest, int width, int code, int pixel_sz)
{
if (pixel_sz == 4) {
fill_n((uint32_t *)dest, width, code);
} else if (pixel_sz == 2) {
fill_n((uint16_t *)dest, width, (uint16_t)code);
} else {
fill_n((uint8_t *)dest, width, (uint8_t)code);
}
}
int draw_canvas_raw_buffer2(Canvas_Attr &canvas, vector<DRAW_OBJ> obj_vec,
uint8_t *obuf)
{
size_t pixel_sz = osd_cmpr_get_pixel_sz(canvas.format);
//memset(obuf, 0, canvas.height*canvas.width*pixel_sz);
for (int obj_i = 0; obj_i < obj_vec.size(); obj_i++) {
DRAW_OBJ &obj_attr = obj_vec[obj_i];
if (obj_attr.type == STROKE_RECT) {
uint8_t *dest_ptr;
for (int y = obj_attr.rect.y;
y < (obj_attr.rect.y + obj_attr.rect.thickness);
y++) {
uint8_t *dest_ptr = &obuf[(y * canvas.width +
obj_attr.rect.x) *
pixel_sz];
fill_n_pixel(dest_ptr, obj_attr.rect.width,
obj_attr.color.code, pixel_sz);
}
int y2 = obj_attr.rect.y + obj_attr.rect.height -
obj_attr.rect.thickness;
for (int y = y2;
y < (obj_attr.rect.y + obj_attr.rect.height);
y++) {
uint8_t *dest_ptr = &obuf[(y * canvas.width +
obj_attr.rect.x) *
pixel_sz];
fill_n_pixel(dest_ptr, obj_attr.rect.width,
obj_attr.color.code, pixel_sz);
}
dest_ptr = &obuf[(obj_attr.rect.y * canvas.width +
obj_attr.rect.x) *
pixel_sz];
for (int y = obj_attr.rect.y;
y < (obj_attr.rect.y + obj_attr.rect.height);
y++) {
fill_n_pixel(dest_ptr, obj_attr.rect.thickness,
obj_attr.color.code, pixel_sz);
dest_ptr += (canvas.width * pixel_sz);
}
int x2 = obj_attr.rect.x + obj_attr.rect.width -
obj_attr.rect.thickness;
dest_ptr = &obuf[(obj_attr.rect.y * canvas.width + x2) *
pixel_sz];
for (int y = obj_attr.rect.y;
y < (obj_attr.rect.y + obj_attr.rect.height);
y++) {
fill_n_pixel(dest_ptr, obj_attr.rect.thickness,
obj_attr.color.code, pixel_sz);
dest_ptr += (canvas.width * pixel_sz);
}
} else if (obj_attr.type == RECT) {
uint8_t *dest_ptr =
&obuf[(obj_attr.rect.y * canvas.width +
obj_attr.rect.x) *
pixel_sz];
for (int y = 0; y < obj_attr.rect.height; y++) {
fill_n_pixel(dest_ptr, obj_attr.rect.width,
obj_attr.color.code, pixel_sz);
dest_ptr += (canvas.width * pixel_sz);
}
} else if (obj_attr.type == BIT_MAP) {
uint8_t *dest_ptr =
&obuf[(obj_attr.bitmap.rect.y * canvas.width +
obj_attr.bitmap.rect.x) *
pixel_sz];
uint8_t *src_ptr = obj_attr.color.buf;
for (int y = 0; y < obj_attr.rect.height; y++) {
memcpy(dest_ptr, src_ptr,
obj_attr.rect.width * pixel_sz);
dest_ptr += (canvas.width * pixel_sz);
src_ptr +=
(obj_attr.bitmap.rect.width * pixel_sz);
}
}
}
}
void draw_canvas_raw_line(uint8_t *obuf, Canvas_Attr &canvas,
vector<DRAW_OBJ> &obj_vec, int y, int pixel_sz,
vector<SEGMENT> &segment_vec)
{
uint8_t *dest_ptr = obuf + (y * canvas.width * pixel_sz);
for (int seg_i = 0; seg_i < segment_vec.size(); seg_i++) {
SEGMENT &segment = segment_vec[seg_i];
if (segment.is_const && segment.color.code != 0) {
fill_n_pixel(dest_ptr, segment.width,
segment.color.code, pixel_sz);
} else if (!segment.is_const) {
int rep_cnt;
uint8_t *src_ptr = segment.color.buf;
if (segment.is_cmpr) {
int pel_cnt = 0;
while (pel_cnt < segment.width) {
rep_cnt = min(src_ptr[0] + 1,
segment.width - pel_cnt);
fill_n_pixel(
&dest_ptr[pel_cnt * pixel_sz],
rep_cnt,
*((uint32_t *)&src_ptr[1]),
pixel_sz);
src_ptr += (1 + pixel_sz);
pel_cnt += rep_cnt;
}
segment.color.buf += *(segment.bs_len);
obj_vec[segment.id].bitmap.bs_offset +=
*(segment.bs_len);
segment.bs_len++;
} else {
memcpy(dest_ptr, src_ptr,
segment.width * pixel_sz);
segment.color.buf +=
(segment.stride * pixel_sz);
}
}
dest_ptr += (segment.width * pixel_sz);
}
}
int draw_canvas_raw_buffer(Canvas_Attr &canvas, vector<DRAW_OBJ> obj_vec,
uint8_t *obuf)
{
size_t pixel_sz = osd_cmpr_get_pixel_sz(canvas.format);
memset(obuf, 0, canvas.height * canvas.width * pixel_sz);
int y_step;
for (int y = 0; y < canvas.height; y += y_step) {
int next_y = canvas.height;
vector<SEGMENT> segment_vec;
plot_segments_on_line(obj_vec, canvas.width, canvas.height, y,
pixel_sz, next_y, segment_vec, canvas->bg_color_code);
y_step = next_y - y;
for (int line_i = 0; line_i < y_step; line_i++) {
draw_canvas_raw_line(obuf, canvas, obj_vec, y + line_i,
pixel_sz, segment_vec);
}
recycle_draw_obj(obj_vec, y + y_step - 1);
}
return 1;
}
#endif
int cmpr_bitmap(Canvas_Attr *canvas, uint8_t *ibuf, uint8_t *obuf, int width,
int height, int buf_size, uint32_t* p_osize)
{
size_t pixel_sz = osd_cmpr_get_pixel_sz(canvas->format);
memset(obuf, 0, buf_size);
uint8_t *cur_ptr = ibuf;
uint16_t *meta_ptr = (uint16_t *)obuf;
size_t meta_sz = height << 1;
uint8_t *bs_ptr = &obuf[meta_sz];
size_t bs_sz_cnt = meta_sz;
int rl_pair_sz = (1 + pixel_sz);
int step;
for (int y = 0; y < height; y++) {
int line_byte_cnt = 0;
for (int x = 0; x < width; x += step) {
int cnt = count_repeat_pixel(cur_ptr, pixel_sz,
width - x);
step = cnt;
while (cnt > 0) {
int new_bs_sz_cnt = bs_sz_cnt + rl_pair_sz;
if (new_bs_sz_cnt > buf_size) {
return -1;
}
int rl = min(cnt, 256);
*bs_ptr = (rl - 1);
memcpy(&bs_ptr[1], cur_ptr, pixel_sz);
bs_ptr += rl_pair_sz;
cnt -= rl;
bs_sz_cnt = new_bs_sz_cnt;
line_byte_cnt += rl_pair_sz;
}
cur_ptr += (step * pixel_sz);
}
meta_ptr[y] = line_byte_cnt;
}
*p_osize = bs_sz_cnt;
return 1;
}
uint32_t est_cmpr_canvas_size(Canvas_Attr *canvas, DRAW_OBJ *objs, uint32_t obj_num)
{
uint8_t *dummy = nullptr;
uint32_t bs_sz = 0;
draw_cmpr_canvas(canvas, objs, obj_num, dummy, 0, &bs_sz);
return ((bs_sz + BUF_GUARD_SIZE) >> 4) << 4;
}
void set_rect_position(RECT_ATTR &rect, Canvas_Attr *canvas, int pt_x, int pt_y,
int width, int height)
{
rect.x = clip(pt_x, 0, canvas->width - 1);
rect.y = clip(pt_y, 0, canvas->height -1);
rect.width = clip(width, 0, canvas->width - rect.x);
rect.height = clip(height, 0, canvas->height - rect.y);
}
void set_rect_obj_attr(DRAW_OBJ *obj_attr, Canvas_Attr *canvas,
uint32_t color_code, int pt_x, int pt_y, int width,
int height, bool is_filled, int thickness)
{
obj_attr->type = (is_filled) ? RECT : STROKE_RECT;
obj_attr->color.code = color_code;
set_rect_position(obj_attr->rect, canvas, pt_x, pt_y, width, height);
thickness = clip(thickness, MIN_THICKNESS, MAX_THICKNESS);
int min_allow_thickness = max((min(obj_attr->rect.height, obj_attr->rect.width)>>1)-1, 0);
obj_attr->rect.thickness = min(min_allow_thickness, thickness);
obj_attr->_max_y = obj_attr->rect.y + obj_attr->rect.height;
obj_attr->_min_y = obj_attr->rect.y;
}
void set_bitmap_obj_attr(DRAW_OBJ *obj_attr, Canvas_Attr *canvas, uint8_t *buf,
int pt_x, int pt_y, int width, int height,
bool is_cmpr)
{
if (is_cmpr) {
obj_attr->type = CMPR_BIT_MAP;
obj_attr->bitmap.bs_offset = height
<< 1; // 2B metadata for each line
} else {
obj_attr->type = BIT_MAP;
obj_attr->bitmap.stride = width;
}
set_rect_position(obj_attr->bitmap.rect, canvas, pt_x, pt_y, width,
height);
obj_attr->color.buf = buf;
obj_attr->_max_y = obj_attr->bitmap.rect.y + obj_attr->bitmap.rect.height;
obj_attr->_min_y = obj_attr->bitmap.rect.y;
}
void set_line_obj_attr(DRAW_OBJ *obj_attr, Canvas_Attr *canvas,
uint32_t color_code, int pt_x0, int pt_y0, int pt_x1,
int pt_y1, int thickness)
{
obj_attr->color.code = color_code;
pt_x0 = clip(pt_x0, 0, canvas->width);
pt_x1 = clip(pt_x1, 0, canvas->width);
pt_y0 = clip(pt_y0, 0, canvas->height);
pt_y1 = clip(pt_y1, 0, canvas->height);
thickness = clip(thickness, MIN_THICKNESS, MAX_THICKNESS);
if (pt_x0 == pt_x1 ||
pt_y0 == pt_y1) { // horizontal line: degenerate to rect
int x = min(pt_x0, pt_x1) - (thickness >> 1);
int y = min(pt_y0, pt_y1) - (thickness >> 1);
int width = thickness +
((pt_x0 == pt_x1) ?
0 :
max(pt_x0, pt_x1) - min(pt_x0, pt_x1));
int height = thickness +
((pt_y0 == pt_y1) ?
0 :
max(pt_y0, pt_y1) - min(pt_y0, pt_y1));
set_rect_obj_attr(obj_attr, canvas, color_code, x, y, width,
height, true, thickness);
} else {
obj_attr->color.code = color_code;
obj_attr->type = LINE;
int x[2], y[2];
bool is_y_incr = (pt_y1 > pt_y0);
x[0] = (is_y_incr) ? pt_x0 : pt_x1;
y[0] = (is_y_incr) ? pt_y0 : pt_y1;
x[1] = (is_y_incr) ? pt_x1 : pt_x0;
y[1] = (is_y_incr) ? pt_y1 : pt_y0;
int dx = x[1] - x[0];
int dy = y[1] - y[0];
obj_attr->line._mx = (dy != 0) ? dx / ((float)dy) :
FLT_MAX;
float thick_offset =
0.5 * thickness / pow(dx * dx + dy * dy, 0.5);
float thick_offset_x = thick_offset * dx;
float thick_offset_y = thick_offset * dy;
for (int side_i = 0; side_i < 2; side_i++) {
obj_attr->line._bx[side_i] =
clip(x[0] + ((dx >= 0) ? thick_offset_y :
(-thick_offset_y)),
(float)0., (float)canvas->width);
obj_attr->line._by[side_i] =
clip(y[0] + ((dx >= 0) ? (-thick_offset_x) :
thick_offset_x),
(float)0., (float)canvas->height);
obj_attr->line._ex[side_i] =
clip(x[1] + ((dx >= 0) ? thick_offset_y :
(-thick_offset_y)),
(float)0., (float)canvas->width);
obj_attr->line._ey[side_i] =
clip(y[1] + ((dx >= 0) ? (-thick_offset_x) :
thick_offset_x),
(float)0., (float)canvas->height);
thick_offset_x = -thick_offset_x;
thick_offset_y = -thick_offset_y;
}
obj_attr->line.ts_h =
(obj_attr->line._bx[0] +
obj_attr->line._mx * (obj_attr->line._by[1] -
obj_attr->line._by[0])) -
obj_attr->line._bx[1];
obj_attr->_min_y =
round(min(obj_attr->line._by[0], obj_attr->line._by[1]));
obj_attr->_max_y =
round(max(obj_attr->line._ey[1], obj_attr->line._ey[1]));
}
}
//==============================================================================================
//CVI interface
#ifdef __cplusplus
extern "C"
{
#endif
uint32_t CVI_OSDC_est_cmpr_canvas_size(Canvas_Attr *canvas, DRAW_OBJ *objs, uint32_t obj_num)
{
return est_cmpr_canvas_size(canvas, objs, obj_num);
}
int CVI_OSDC_draw_cmpr_canvas(Canvas_Attr *canvas, DRAW_OBJ *objs, uint32_t obj_num,
uint8_t *obuf, uint32_t buf_size, uint32_t *p_osize)
{
return draw_cmpr_canvas(canvas, objs, obj_num, obuf, buf_size, p_osize);
}
void CVI_OSDC_set_rect_obj_attr(Canvas_Attr *canvas, DRAW_OBJ *obj, uint32_t color_code, int pt_x, int pt_y, int width,
int height, bool is_filled, int thickness)
{
set_rect_obj_attr(obj, canvas, color_code, pt_x, pt_y, width, height, is_filled, thickness);
}
void CVI_OSDC_set_bitmap_obj_attr(Canvas_Attr *canvas, DRAW_OBJ *obj_attr, uint8_t *buf,
int pt_x, int pt_y, int width, int height, bool is_cmpr)
{
set_bitmap_obj_attr(obj_attr, canvas, buf, pt_x, pt_y, width, height, is_cmpr);
}
void CVI_OSDC_set_line_obj_attr(Canvas_Attr *canvas, DRAW_OBJ *obj, uint32_t color_code,
int pt_x0, int pt_y0, int pt_x1, int pt_y1, int thickness)
{
set_line_obj_attr(obj, canvas, color_code, pt_x0, pt_y0, pt_x1, pt_y1, thickness);
}
int CVI_OSDC_cmpr_bitmap(Canvas_Attr *canvas, uint8_t *ibuf, uint8_t *obuf, int width, int height,
int buf_size, uint32_t *p_osize)
{
return cmpr_bitmap(canvas, ibuf, obuf, width, height, buf_size, p_osize);
}
#if (CMPR_CANVAS_DBG)
int CVI_OSDC_draw_canvas_raw_buffer(Canvas_Attr &canvas, vector<DRAW_OBJ> obj_vec, uint8_t *obuf)
int CVI_OSDC_draw_canvas_raw_buffer2(Canvas_Attr &canvas, vector<DRAW_OBJ> obj_vec, uint8_t *obuf);
#endif
#ifdef __cplusplus
}
#endif

View File

@@ -0,0 +1,93 @@
#include <cvi_osdc.h>
#include <stdlib.h>
#include <string.h>
uint32_t CVI_OSDC_EstCmprCanvasSize(OSDC_Canvas_Attr_S *canvas, OSDC_DRAW_OBJ_S *objs, uint32_t obj_num)
{
return CVI_OSDC_est_cmpr_canvas_size(canvas, objs, obj_num);
}
int CVI_OSDC_DrawCmprCanvas(OSDC_Canvas_Attr_S *canvas, OSDC_DRAW_OBJ_S *objs, uint32_t obj_num,
uint8_t *obuf, uint32_t buf_size, uint32_t *p_osize)
{
return CVI_OSDC_draw_cmpr_canvas(canvas, objs, obj_num, obuf, buf_size, p_osize);
}
void CVI_OSDC_SetRectObjAttr(OSDC_Canvas_Attr_S *canvas, OSDC_DRAW_OBJ_S *obj, uint32_t color_code,
int pt_x, int pt_y, int width, int height, bool is_filled, int thickness)
{
CVI_OSDC_set_rect_obj_attr(canvas, obj, color_code, pt_x, pt_y, width, height, is_filled, thickness);
}
void CVI_OSDC_SetRectObjAttrEx(OSDC_Canvas_Attr_S *canvas, OSDC_DRAW_OBJ_S *obj, uint32_t color_code,
OSDC_RECT_ATTR_S *rects, int num, bool is_filled)
{
int i = 0;
for (i = 0; i < num; i++) {
CVI_OSDC_set_rect_obj_attr(canvas, obj, color_code, rects[i].x, rects[i].y,
rects[i].width, rects[i].height, is_filled, rects[i].thickness);
}
}
void CVI_OSDC_SetBitmapObjAttr(OSDC_Canvas_Attr_S *canvas, OSDC_DRAW_OBJ_S *obj_attr, uint8_t *buf,
int pt_x, int pt_y, int width, int height, bool is_cmpr)
{
CVI_OSDC_set_bitmap_obj_attr(canvas, obj_attr, buf, pt_x, pt_y, width, height, is_cmpr);
}
void CVI_OSDC_SetLineObjAttr(OSDC_Canvas_Attr_S *canvas, OSDC_DRAW_OBJ_S *obj, uint32_t color_code,
int pt_x0, int pt_y0, int pt_x1, int pt_y1, int thickness)
{
CVI_OSDC_set_line_obj_attr(canvas, obj, color_code, pt_x0, pt_y0, pt_x1, pt_y1, thickness);
}
void CVI_OSDC_SetLineObjAttrEx(OSDC_Canvas_Attr_S *canvas, OSDC_DRAW_OBJ_S *obj, uint32_t color_code,
OSDC_POINT_ATTR_S *points, int num, int thickness)
{
int i = 0, j = 0, delta_x, delta_y;
OSDC_POINT_ATTR_S *tmp = malloc(sizeof(OSDC_POINT_ATTR_S) * num);
if (!tmp)
return;
memcpy(tmp, points, sizeof(OSDC_POINT_ATTR_S) * num);
while (j++ < 5) {
for (i = 0; i < num - 1; ++i) {
delta_x = abs(tmp[i].x - tmp[i + 1].x);
delta_y = abs(tmp[i].y - tmp[i + 1].y);
if (delta_y < thickness)
tmp[i + 1].y = tmp[i].y;
if (delta_x < thickness)
tmp[i + 1].x = tmp[i].x;
}
delta_x = abs(tmp[num - 1].x - tmp[0].x);
delta_y = abs(tmp[num - 1].y - tmp[0].y);
if (delta_y < thickness)
tmp[0].y = tmp[num - 1].y;
if (delta_x < thickness)
tmp[0].x = tmp[num - 1].x;
delta_x = abs(tmp[1].x - tmp[0].x);
delta_y = abs(tmp[1].y - tmp[0].y);
if ((delta_x > thickness || delta_x == 0) &&
(delta_y > thickness || delta_y == 0))
break;
}
for (i = 0; i < num - 1; ++i) {
CVI_OSDC_set_line_obj_attr(canvas, obj + i, color_code, tmp[i].x, tmp[i].y,
tmp[i + 1].x, tmp[i + 1].y, thickness);
}
CVI_OSDC_set_line_obj_attr(canvas, obj + num - 1, color_code, tmp[num - 1].x, tmp[num - 1].y,
tmp[0].x, tmp[0].y, thickness);
free(tmp);
}
int CVI_OSDC_CmprBitmap(OSDC_Canvas_Attr_S *canvas, uint8_t *ibuf, uint8_t *obuf, int width, int height,
int buf_size, uint32_t *p_osize)
{
return CVI_OSDC_cmpr_bitmap(canvas, ibuf, obuf, width, height, buf_size, p_osize);
}

View File

@@ -0,0 +1,601 @@
#include <string.h>
#include <assert.h>
#include <stdio.h>
#include "osd_cmpr.h"
// -- arithmetic operation --
uint8_t get_bit_val(uint8_t *buf, int byte_idx, int bit_idx)
{
return (buf[byte_idx] >> bit_idx) & 0x1;
}
int min(int data1, int data2)
{
return (data1 <= data2) ? data1 : data2;
}
int max(int data1, int data2)
{
return (data1 >= data2) ? data1 : data2;
}
int clip(int data, int min, int max)
{
return (data > max) ? max : (data < min) ? min : data;
}
// -- streaming operation handler --
void init_stream(StreamBuffer *bs, const uint8_t *buf, int buf_size,
bool read_only)
{
bs->bit_pos = 0;
bs->stream = (uint8_t *)buf;
bs->buf_size = buf_size;
bs->status = 1;
if (!read_only)
memset((uint8_t *)buf, 0, sizeof(uint8_t) * buf_size);
}
void write_multibits(uint8_t *stream, uint8_t *src, int bit_pos, int bit_len)
{
assert(bit_len <= 8);
int dest_bit_i = bit_pos & 7;
int dest_byte_i = bit_pos >> 3;
uint16_t *dest_ptr_ex = (uint16_t *)&stream[dest_byte_i];
uint16_t src_data_ex = (*src) << dest_bit_i;
(*dest_ptr_ex) = (*dest_ptr_ex) | src_data_ex;
}
void write_stream(StreamBuffer *bs, uint8_t *src, int bit_len)
{
int next_bit_pos = bs->bit_pos + bit_len;
if (next_bit_pos < (bs->buf_size << 3)) {
while (bit_len >= 8) {
write_multibits(bs->stream, src, bs->bit_pos, 8);
bs->bit_pos += 8;
bit_len -= 8;
src++;
};
if (bit_len > 0) {
write_multibits(bs->stream, src, bs->bit_pos, bit_len);
}
} else {
bs->status = -1;
}
bs->bit_pos = next_bit_pos;
}
void move_stream_ptr(StreamBuffer *bs, int bit_len)
{
bs->bit_pos = min(bs->bit_pos + bit_len, (bs->buf_size << 3));
}
void parse_stream(StreamBuffer *bs, uint8_t *dest, int bit_len, bool read_only)
{
memset(dest, 0, sizeof(uint8_t) * (bit_len + 7) >> 3);
for (int bit = 0; bit < bit_len; bit++) {
int dest_byte_i = bit / 8;
int dest_bit_i = bit % 8;
int bs_byte_i = (bs->bit_pos + bit) / 8;
int bs_bit_i = (bs->bit_pos + bit) % 8;
dest[dest_byte_i] |=
(get_bit_val(bs->stream, bs_byte_i, bs_bit_i)
<< dest_bit_i);
}
bs->bit_pos = (read_only) ?
bs->bit_pos :
min(bs->bit_pos + bit_len, (bs->buf_size << 3));
}
// ------ ARGB format generic function ------
// tranform generic ARGB8888 into multiple pixel format
void set_color(uint8_t *ptr, RGBA color, OSD_FORMAT format)
{
if (format == OSD_ARGB8888) {
memcpy(ptr, &color, sizeof(RGBA));
} else if (format == OSD_ARGB1555) {
ARGB1555 out_c;
CPY_C(color, out_c)
memcpy(ptr, &out_c.code, sizeof(out_c.code));
} else if (format == OSD_ARGB4444) {
ARGB4444 out_c;
CPY_C(color, out_c)
memcpy(ptr, &out_c.code, sizeof(out_c.code));
} else if (format == OSD_LUT8 || format == OSD_LUT4) {
*ptr = color.a;
}
}
// tranform multiple pixel format into generic ARGB8888
RGBA get_color(uint8_t *ptr, OSD_FORMAT format)
{
RGBA out_c;
out_c.code = 0;
if (format == OSD_ARGB8888) {
RGBA in_c = *((RGBA *)ptr);
CPY_C(in_c, out_c)
} else if (format == OSD_ARGB1555) {
ARGB1555 in_c = *((ARGB1555 *)ptr);
CPY_C(in_c, out_c)
} else if (format == OSD_ARGB4444) {
ARGB4444 in_c = *((ARGB4444 *)ptr);
CPY_C(in_c, out_c)
} else if (format == OSD_LUT8 || format == OSD_LUT4) {
out_c.a = *ptr;
}
return out_c;
}
bool is_equal_color(RGBA c0, RGBA c1)
{
return c0.code == c1.code;
}
// ------ palette_cache ------
void palette_cache_init(vector<RGBA> &cache, int cache_sz)
{
int c_incr = 256 / cache_sz;
uint8_t c = 0;
for (int idx = 0; idx < cache_sz; idx++) {
uint32_t code = (c << 24) | (c << 16) | (c << 8) | c;
RGBA color = get_color((uint8_t *)&code);
cache.push_back(color);
c = clip(c + c_incr, 0, 255);
}
}
int palette_cache_lookup_color(vector<RGBA> &cache, RGBA color)
{
for (unsigned int idx = 0; idx < cache.size(); idx++) {
if (is_equal_color(cache[idx], color)) { // hit
palette_cache_lru_update(cache, idx);
return idx;
}
}
// miss
palette_cache_push_color(cache, color);
return -1;
}
void palette_cache_lru_update(vector<RGBA> &cache, int index)
{
if (index == 0)
return;
RGBA reg_color = cache[index];
for (int idx = index; idx > 0; idx--) {
cache[idx] = cache[idx - 1];
}
cache[0] = reg_color;
}
void palette_cache_push_color(vector<RGBA> &cache, RGBA color)
{
for (int idx = cache.size() - 1; idx > 0; idx--) {
cache[idx] = cache[idx - 1];
}
cache[0] = color;
}
// ------ syntax enc/dec ------
void enc_literal(StreamBuffer *bs, RGBA color, OSD_FORMAT format)
{
if (format == OSD_ARGB8888) {
write_stream(bs, (uint8_t *)(&color), sizeof(RGBA) << 3);
} else if (format == OSD_ARGB1555) {
ARGB1555 out_c;
CPY_C(color, out_c)
write_stream(bs, (uint8_t *)(&out_c.code),
sizeof(out_c.code) << 3);
} else if (format == OSD_ARGB4444) {
ARGB4444 out_c;
CPY_C(color, out_c)
write_stream(bs, (uint8_t *)(&out_c.code),
sizeof(out_c.code) << 3);
} else if (format == OSD_LUT8) {
write_stream(bs, (uint8_t *)(&color.a), 8);
} else if (format == OSD_LUT4) {
write_stream(bs, (uint8_t *)(&color.a), 4);
}
}
RGBA dec_literal(StreamBuffer *bs, OSD_FORMAT format)
{
RGBA color;
color.code = 0;
if (format == OSD_ARGB8888) {
parse_stream(bs, (uint8_t *)&color, sizeof(RGBA) * 8, false);
} else if (format == OSD_ARGB1555) {
ARGB1555 in_c;
parse_stream(bs, (uint8_t *)&in_c.code, sizeof(in_c.code) * 8,
false);
CPY_C(in_c, color)
} else if (format == OSD_ARGB4444) {
ARGB4444 in_c;
parse_stream(bs, (uint8_t *)&in_c.code, sizeof(in_c.code) * 8,
false);
CPY_C(in_c, color)
} else if (format == OSD_LUT8) {
parse_stream(bs, &color.a, 8, false);
} else if (format == OSD_LUT4) {
parse_stream(bs, &color.a, 4, false);
}
return color;
}
void enc_run_length(StreamBuffer *bs, int run_len, int run_len_bd)
{
if (run_len > 1) {
uint8_t run_syntax = run_len - 1;
write_stream(bs, &run_syntax, run_len_bd);
}
}
void enc_mode_syntax(StreamBuffer *bs, MODE_TYPE md, int run_len, CODE code,
OSDCmpr_Ctrl *p_ctrl)
{
if (p_ctrl->reg_palette_mode_en) {
uint16_t _syntax;
if (md == Palette) {
if (run_len > 1) {
_syntax = (code.palette_idx
<< (p_ctrl->reg_run_len_bd + 3)) |
((run_len - 1) << 3);
write_stream(
bs, (uint8_t *)&_syntax,
3 + p_ctrl->reg_run_len_bd +
p_ctrl->reg_palette_idx_bd);
} else {
_syntax = (code.palette_idx << 2) | 2;
write_stream(bs, (uint8_t *)&_syntax,
p_ctrl->reg_palette_idx_bd + 2);
}
} else if (md == Literal) {
if (run_len > 1) {
uint16_t _syntax = ((run_len - 1) << 3) | 4;
write_stream(bs, (uint8_t *)&_syntax,
3 + p_ctrl->reg_run_len_bd);
} else {
uint8_t lit_prefix = 1;
write_stream(bs, &lit_prefix, 1);
}
enc_literal(bs, code.color, p_ctrl->reg_osd_format);
}
} else {
uint8_t prefix = (run_len > 1) ? 0 : 1;
write_stream(bs, &prefix, 1);
enc_run_length(bs, run_len, p_ctrl->reg_run_len_bd);
enc_literal(bs, code.color, p_ctrl->reg_osd_format);
}
}
MODE_TYPE dec_mode_prefix(StreamBuffer *bs, bool palette_mode_en)
{
uint8_t prefix;
if (palette_mode_en) {
parse_stream(bs, &prefix, 3, true);
if (prefix == 0) {
move_stream_ptr(bs, 3);
return Palette_RL;
} else if (prefix == 4) {
move_stream_ptr(bs, 3);
return Literal_RL;
} else if ((prefix & 0x3) == 2) {
move_stream_ptr(bs, 2);
return Palette;
}
assert((prefix & 0x1) == 1);
move_stream_ptr(bs, 1);
return Literal;
} else {
parse_stream(bs, &prefix, 1, false);
return (prefix) ? Literal : Literal_RL;
}
}
CODE dec_code_syntax(StreamBuffer *bs, MODE_TYPE md, OSDCmpr_Ctrl *p_ctrl)
{
CODE retCode;
if (md == Literal || md == Literal_RL) {
retCode.color = dec_literal(bs, p_ctrl->reg_osd_format);
} else {
uint8_t pal_syntax;
parse_stream(bs, &pal_syntax, p_ctrl->reg_palette_idx_bd,
false);
retCode.palette_idx = pal_syntax;
}
return retCode;
}
RGBA pixel_preprocess(uint8_t *ptr, OSDCmpr_Ctrl *p_ctrl)
{
RGBA color = get_color(ptr, p_ctrl->reg_osd_format);
color.b = (color.b >> p_ctrl->reg_rgb_trunc_bit)
<< p_ctrl->reg_rgb_trunc_bit;
color.g = (color.g >> p_ctrl->reg_rgb_trunc_bit)
<< p_ctrl->reg_rgb_trunc_bit;
color.r = (color.r >> p_ctrl->reg_rgb_trunc_bit)
<< p_ctrl->reg_rgb_trunc_bit;
color.a = (color.a >> p_ctrl->reg_alpha_trunc_bit)
<< p_ctrl->reg_alpha_trunc_bit;
if (p_ctrl->reg_zeroize_by_alpha && color.a == 0) {
color.code = 0;
}
set_color(ptr, color, p_ctrl->reg_osd_format);
return color;
}
// ---------------------- OSD cmpr main API ----------------------
int osd_cmpr_enc_one_frame(uint8_t *ibuf, uint8_t *obs, OSDCmpr_Ctrl *p_ctrl)
{
StreamBuffer bitstream;
size_t width = p_ctrl->reg_image_width,
height = p_ctrl->reg_image_height;
init_stream(&bitstream, p_ctrl->bsbuf, p_ctrl->bs_buf_size, false);
uint8_t *inPtr = ibuf;
RGBA last_color;
int rl_cnt = 1;
CODE code;
MODE_TYPE md = NUM_OF_MODE;
int max_run_len = 1 << p_ctrl->reg_run_len_bd;
for (int line_i = 0; line_i < (int)height; line_i++) {
for (int pos_x = 0; pos_x < (int)width; pos_x++) {
RGBA cur = pixel_preprocess(inPtr, p_ctrl);
if ((pos_x == 0 && line_i == 0) ||
rl_cnt >= max_run_len ||
(!is_equal_color(cur, last_color))) { // new run
if (!(pos_x == 0 && line_i == 0)) { // write out
enc_mode_syntax(&bitstream, md, rl_cnt,
code, p_ctrl);
}
// mode detection
int cache_idx =
(p_ctrl->reg_palette_mode_en) ?
palette_cache_lookup_color(
p_ctrl->palette_cache,
cur) :
-1;
if (cache_idx >= 0) { // cache hit
code.palette_idx = cache_idx;
md = Palette;
} else { // cache miss
code.color = cur;
md = Literal;
}
rl_cnt = 1;
} else { // still within a run
rl_cnt++;
}
last_color = cur;
inPtr += p_ctrl->pel_sz;
}
}
enc_mode_syntax(&bitstream, md, rl_cnt, code, p_ctrl);
int blk_bs_size = ((bitstream.bit_pos + 127) >> 7)
<< 4; // in byte, 16byte align
memcpy(obs, p_ctrl->bsbuf, blk_bs_size * sizeof(uint8_t));
return blk_bs_size;
}
void osd_cmpr_dec_one_frame(uint8_t *bsbuf, size_t bs_size, uint8_t *obuf,
OSDCmpr_Ctrl *p_ctrl)
{
StreamBuffer bitstream;
init_stream(&bitstream, bsbuf, bs_size, true);
int remain_pix_cnt = p_ctrl->reg_image_width * p_ctrl->reg_image_height;
uint8_t *outPtr = obuf;
int run_len;
RGBA color;
while (remain_pix_cnt > 0) {
MODE_TYPE md = dec_mode_prefix(&bitstream,
p_ctrl->reg_palette_mode_en);
// decode run len
if (md == Literal_RL || md == Palette_RL) {
uint8_t run_syntax = 0;
parse_stream(&bitstream, &run_syntax,
p_ctrl->reg_run_len_bd, false);
run_len = run_syntax + 1;
} else {
run_len = 1;
}
CODE code = dec_code_syntax(&bitstream, md, p_ctrl);
if (md == Literal || md == Literal_RL) {
color = code.color;
palette_cache_push_color(p_ctrl->palette_cache, color);
} else if (md == Palette || md == Palette_RL) {
color = p_ctrl->palette_cache[code.palette_idx];
palette_cache_lru_update(p_ctrl->palette_cache,
code.palette_idx);
}
// reconstruct pixels
for (int idx = 0; idx < run_len; idx++) {
set_color(outPtr, color, p_ctrl->reg_osd_format);
outPtr += p_ctrl->pel_sz;
remain_pix_cnt--;
}
}
}
void osd_cmpr_enc_header(uint8_t *hdrbuf, OSDCmpr_Ctrl *p_ctrl)
{
StreamBuffer bs_header;
size_t width_m1 = p_ctrl->reg_image_width - 1,
height_m1 = p_ctrl->reg_image_height - 1;
init_stream(&bs_header, hdrbuf, HDR_SZ, false);
move_stream_ptr(&bs_header, 8); // bit[0:7] version
write_stream(&bs_header, (uint8_t *)&p_ctrl->reg_osd_format,
4); // bit[8:11] osd_format
move_stream_ptr(&bs_header, 3); // bit[12:14] reserved
size_t palette_cache_size = 1 << p_ctrl->reg_palette_idx_bd;
write_stream(&bs_header, (uint8_t *)&palette_cache_size,
8); // bit[15:22] palette_cache_size
write_stream(&bs_header, (uint8_t *)&p_ctrl->reg_alpha_trunc_bit,
2); // bit[23:24] alpha truncate
move_stream_ptr(&bs_header, 2); // bit[25:26] reserved
write_stream(&bs_header, (uint8_t *)&p_ctrl->reg_rgb_trunc_bit,
2); // bit[27:28] alpha truncate
move_stream_ptr(&bs_header, 2); // bit[29:30] reserved
write_stream(&bs_header, (uint8_t *)&width_m1,
16); // bit[31:46] image_width minus 1
write_stream(&bs_header, (uint8_t *)&height_m1,
16); // bit[47:62] image_height minus 1
}
void osd_cmpr_dec_header(uint8_t *hdrbuf, OSDCmpr_Ctrl *p_ctrl)
{
StreamBuffer bs_header;
init_stream(&bs_header, hdrbuf, HDR_SZ, true);
uint8_t palette_cache_size;
uint16_t width_m1, height_m1;
p_ctrl->reg_osd_format = OSD_ARGB8888;
p_ctrl->reg_alpha_trunc_bit = 0;
p_ctrl->reg_rgb_trunc_bit = 0;
move_stream_ptr(&bs_header, 8); // bit[0:7] version
parse_stream(&bs_header, (uint8_t *)&p_ctrl->reg_osd_format, 4,
false); // bit[8:11] osd_format
move_stream_ptr(&bs_header, 3); // bit[12:14] reserved
parse_stream(&bs_header, &palette_cache_size, 8,
false); // bit[15:22] palette_cache_size
parse_stream(&bs_header, (uint8_t *)&p_ctrl->reg_alpha_trunc_bit, 2,
false); // bit[23:24] alpha truncate
move_stream_ptr(&bs_header, 2); // bit[25:26] reserved
parse_stream(&bs_header, (uint8_t *)&p_ctrl->reg_rgb_trunc_bit, 2,
false); // bit[27:28] alpha truncate
move_stream_ptr(&bs_header, 2); // bit[29:30] reserved
parse_stream(&bs_header, (uint8_t *)&width_m1, 16,
false); // bit[31:46] image_width minus 1
parse_stream(&bs_header, (uint8_t *)&height_m1, 16,
false); // bit[47:62] image_height minus 1
p_ctrl->reg_palette_mode_en = palette_cache_size > 1;
if (p_ctrl->reg_palette_mode_en) {
int palette_idx_bd = 0;
while ((1 << palette_idx_bd) < palette_cache_size) {
palette_idx_bd++;
}
p_ctrl->reg_palette_idx_bd = palette_idx_bd;
}
p_ctrl->reg_image_width = width_m1 + 1;
p_ctrl->reg_image_height = height_m1 + 1;
}
void osd_cmpr_enc_followed_run(RGBA cur_c, int &rl_cnt, MODE_TYPE &md,
CODE &code, int &length, int max_run_len,
OSDCmpr_Ctrl *p_ctrl, StreamBuffer *bitstream)
{
enc_mode_syntax(bitstream, md, rl_cnt, code, p_ctrl);
rl_cnt = min(length, max_run_len);
length -= rl_cnt;
// followed run must select Palette idx 0
if (md != Palette || (md == Palette && code.palette_idx != 0)) {
if (p_ctrl->reg_palette_mode_en) {
code.palette_idx = 0;
md = Palette;
} else {
code.color = cur_c;
md = Literal;
}
}
}
void osd_cmpr_enc_const_pixel(RGBA cur_c, RGBA &last_c, int &rl_cnt,
MODE_TYPE &md, CODE &code, int &length,
bool is_force_new_run, int max_run_len,
OSDCmpr_Ctrl *p_ctrl, StreamBuffer *bitstream)
{
if ((!is_equal_color(cur_c, last_c)) || is_force_new_run ||
(rl_cnt == max_run_len)) {
// new run
enc_mode_syntax(bitstream, md, rl_cnt, code, p_ctrl);
// mode detection
int cache_idx = (p_ctrl->reg_palette_mode_en) ?
palette_cache_lookup_color(
p_ctrl->palette_cache, cur_c) :
-1;
if (cache_idx >= 0) { // cache hit
code.palette_idx = cache_idx;
md = Palette;
} else { // cache miss
code.color = cur_c;
md = Literal;
}
rl_cnt = min(length, max_run_len);
length -= rl_cnt;
last_c = cur_c;
} else { // still within a run
int new_rl_cnt = min(rl_cnt + length, max_run_len);
length -= (new_rl_cnt - rl_cnt);
rl_cnt = new_rl_cnt;
}
}
void osd_cmpr_debug_frame_compare(OSDCmpr_Ctrl *p_ctrl, uint8_t *buf0,
uint8_t *buf1)
{
int frame_pel_num = p_ctrl->reg_image_width * p_ctrl->reg_image_height;
uint8_t *ptr0 = buf0, *ptr1 = buf1;
for (int pel_i = 0; pel_i < frame_pel_num; pel_i++) {
RGBA color0 = get_color(ptr0, p_ctrl->reg_osd_format);
RGBA color1 = get_color(ptr1, p_ctrl->reg_osd_format);
if (!is_equal_color(color0, color1)) {
printf("pel idx %d %d %d\n", pel_i, color0.code,
color1.code);
break;
}
ptr0 += p_ctrl->pel_sz;
ptr1 += p_ctrl->pel_sz;
}
}
void osd_cmpr_frame_init(OSDCmpr_Ctrl *p_ctrl)
{
p_ctrl->palette_cache.clear();
palette_cache_init(p_ctrl->palette_cache,
1 << p_ctrl->reg_palette_idx_bd);
}
void osd_cmpr_setup(OSDCmpr_Ctrl *p_ctrl, OSDCmpr_Cfg *p_cfg)
{
p_ctrl->reg_image_width = p_cfg->img_width;
p_ctrl->reg_image_height = p_cfg->img_height;
p_ctrl->reg_zeroize_by_alpha = p_cfg->zeroize_by_alpha;
p_ctrl->reg_rgb_trunc_bit = p_cfg->rgb_trunc_bit;
p_ctrl->reg_alpha_trunc_bit = p_cfg->alpha_trunc_bit;
p_ctrl->reg_palette_mode_en = p_cfg->palette_mode_en;
p_ctrl->reg_run_len_bd = p_cfg->run_len_bd;
p_ctrl->reg_palette_idx_bd =
(p_cfg->palette_mode_en) ? p_cfg->palette_idx_bd : 0;
p_ctrl->reg_osd_format = p_cfg->osd_format;
p_ctrl->pel_sz = osd_cmpr_get_pixel_sz(p_cfg->osd_format);
p_ctrl->bs_buf_size = osd_cmpr_get_bs_buf_max_sz(
p_cfg->img_width * p_cfg->img_height, p_ctrl->pel_sz);
p_ctrl->bsbuf = (uint8_t *)calloc(p_ctrl->bs_buf_size, sizeof(uint8_t));
}
size_t osd_cmpr_get_pixel_sz(OSD_FORMAT format)
{
return (format == OSD_ARGB8888) ?
4 :
(format == OSD_ARGB1555 || format == OSD_ARGB4444) ?
2 :
1; // (OSD_LUT8, OSD_LUT4)
};
size_t osd_cmpr_get_bs_buf_max_sz(int pel_num, int pel_sz)
{
return HDR_SZ + ((((pel_num * (pel_sz * 8 + 1)) + 127) >> 7)
<< 4); // in bytes, 16byte align
}
size_t osd_cmpr_get_header_sz()
{
return HDR_SZ;
}

View File

@@ -0,0 +1,63 @@
SHELL = /bin/bash
ifeq ($(PARAM_FILE), )
PARAM_FILE:=../../Makefile.param
include $(PARAM_FILE)
endif
SDIR = $(PWD)/src
SRCS := $(wildcard $(SDIR)/*.c)
ifneq ($(MULTI_PROCESS_SUPPORT), 1)
SRCS := $(filter-out $(SDIR)/cvi_rpc.c, $(SRCS))
endif
OBJS = $(SRCS:.c=.o)
DEPS = $(SRCS:.c=.d)
ifeq ($(SDK_VER), 32bit)
SRCS_ASM = $(wildcard $(SDIR)/*.S)
else ifeq ($(SDK_VER), 64bit)
SRCS_ASM = $(wildcard $(SDIR)/*.S)
else
SRCS_ASM =
endif
OBJS_ASM = $(SRCS_ASM:.S=.o)
DEPS_ASM = $(SRCS_ASM:.S=.d)
TARGET_A = $(MW_LIB)/libsys.a
TARGET_SO = $(MW_LIB)/libsys.so
INCS = -I$(MW_INC) -I$(KERNEL_INC) -I$(SYS_INC) -I$(VPU_INC)
EXTRA_CFLAGS = $(INCS) -fpack-struct=8
EXTRA_CFLAGS += -DMMF_VERSION=\"$(shell git describe --always)\"
EXTRA_CFLAGS += -DSDK_VER=\"$(SDK_VER)\"
ifeq ($(SDK_VER), 32bit)
EXTRA_CFLAGS += -D_FILE_OFFSET_BITS=64
endif
LDFLAGS = -shared -fPIC -Wl,--gc-sections -export-dynamic -L$(MW_LIB) -L$(MW_3RD_LIB) --sysroot $(SYSROOT) $(CVI_TARGET_PACKAGES_LIBDIR)
.PHONY : clean all
all : $(TARGET_A) $(TARGET_SO)
$(SDIR)/%.o: $(SDIR)/%.c
@$(CC) $(DEPFLAGS) $(CFLAGS) $(EXTRA_CFLAGS) -o $@ -c $<
@echo [$(notdir $(CC))] $(notdir $@)
$(SDIR)/%.o: $(SDIR)/%.S
$(CC) $(DEPFLAGS) $(CFLAGS) $(EXTRA_CFLAGS) -o $@ -c $<
@echo [$(notdir $(CC))] $(notdir $@)
$(TARGET_A): $(OBJS) $(OBJS_ASM)
@$(AR) $(ARFLAGS) $(TARGET_A) $(OBJS) $(OBJS_ASM)
@echo -e $(YELLOW)[LINK]$(END)[$(notdir $(AR))] $(notdir $(TARGET_A))
@echo "$$AR_MRI" | $(AR) -M
$(TARGET_SO): $(OBJS) $(OBJS_ASM)
@$(CC) $(LDFLAGS) $(EXTRA_LDFLAGS) -o $(TARGET_SO) -Wl,--start-group $(OBJS) $(OBJS_ASM) $(LIBS) -Wl,--end-group
@echo -e $(GREEN)[LINK]$(END)[$(notdir $(LD))] $(notdir $(TARGET_SO))
clean:
@rm -f $(OBJS) $(OBJS_ASM) $(DEPS) $(DEPS_ASM) $(TARGET_A) $(TARGET_SO)
-include $(DEPS)

View File

@@ -0,0 +1,418 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include <assert.h>
#include <sys/queue.h>
#include <pthread.h>
#include <inttypes.h>
#include <math.h>
#include <getopt.h> /* getopt_long() */
#include <fcntl.h> /* low-level i/o */
#include <unistd.h>
#include <pthread.h>
#include <errno.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <sys/wait.h>
#include <linux/cvi_base.h>
#include <sys/prctl.h>
#include "cvi_base.h"
#include "cvi_buffer.h"
#include <linux/cvi_errno.h>
struct vdev dev_isp, dev_vpss, dev_disp, dev_dwa, dev_rgn;
static CVI_S32 base_fd = -1, sys_fd = -1;
static void *shared_mem;
static int shared_mem_usr_cnt;
/*
* @param type: 0(isp) 1(img) 2(sc) 3(disp)
* @param dev_id: dev id
*/
struct vdev *get_dev_info(CVI_U8 type, CVI_U8 dev_id)
{
UNUSED(dev_id);
if (type == VDEV_TYPE_ISP)
return &dev_isp;
else if (type == VDEV_TYPE_VPSS)
return &dev_vpss;
else if (type == VDEV_TYPE_DISP)
return &dev_disp;
else if (type == VDEV_TYPE_DWA)
return &dev_dwa;
else if (type == VDEV_TYPE_RGN)
return &dev_rgn;
return NULL;
}
int open_device(const char *dev_name, CVI_S32 *fd)
{
struct stat st;
*fd = open(dev_name, O_RDWR /* required */ | O_NONBLOCK | O_CLOEXEC, 0);
if (-1 == *fd) {
fprintf(stderr, "Cannot open '%s': %d, %s\n", dev_name, errno,
strerror(errno));
return -1;
}
if (-1 == fstat(*fd, &st)) {
close(*fd);
fprintf(stderr, "Cannot identify '%s': %d, %s\n", dev_name,
errno, strerror(errno));
return -1;
}
if (!S_ISCHR(st.st_mode)) {
close(*fd);
fprintf(stderr, "%s is no device\n", dev_name);
return -ENODEV;
}
return 0;
}
CVI_S32 close_device(CVI_S32 *fd)
{
if (*fd == -1)
return -1;
if (-1 == close(*fd)) {
fprintf(stderr, "%s: fd(%d) failure\n", __func__, *fd);
return -1;
}
*fd = -1;
return CVI_SUCCESS;
}
CVI_S32 get_rgn_fd(CVI_VOID)
{
if (dev_rgn.fd <= 0)
rgn_dev_open();
return dev_rgn.fd;
}
CVI_S32 rgn_dev_open(CVI_VOID)
{
if (dev_rgn.state != VDEV_STATE_OPEN) {
dev_rgn.state = VDEV_STATE_CLOSED;
if (open_device(RGN_DEV_NAME, &dev_rgn.fd) == -1) {
perror("RGN open failed\n");
dev_rgn.fd = -1;
return CVI_FAILURE;
}
dev_rgn.state = VDEV_STATE_OPEN;
}
return CVI_SUCCESS;
}
CVI_S32 rgn_dev_close(CVI_VOID)
{
if (dev_rgn.state != VDEV_STATE_CLOSED) {
if (close_device(&dev_rgn.fd) == -1) {
perror("RGN close failed\n");
dev_rgn.fd = -1;
return CVI_FAILURE;
}
dev_rgn.state = VDEV_STATE_CLOSED;
dev_rgn.fd = -1;
}
return CVI_SUCCESS;
}
CVI_S32 get_vo_fd(CVI_VOID)
{
if (dev_disp.fd <= 0)
vo_dev_open();
return dev_disp.fd;
}
CVI_S32 vo_dev_open(CVI_VOID)
{
if (dev_disp.state != VDEV_STATE_OPEN) {
// disp
strncpy(dev_disp.name, "VO", sizeof(dev_disp.name));
if (open_device(VO_DEV_NAME, &dev_disp.fd) == -1) {
CVI_TRACE_SYS(CVI_DBG_WARN, "Warning: Maybe no VO dev?\n");
dev_disp.fd = -1;
return CVI_FAILURE;
}
dev_disp.state = VDEV_STATE_OPEN;
}
return CVI_SUCCESS;
}
CVI_S32 vo_dev_close(CVI_VOID)
{
if (dev_disp.state != VDEV_STATE_CLOSED) {
if (close_device(&dev_disp.fd) == -1) {
perror("VO close failed\n");
dev_disp.fd = -1;
return CVI_FAILURE;
}
dev_disp.state = VDEV_STATE_CLOSED;
dev_disp.fd = -1;
}
return CVI_SUCCESS;
}
CVI_S32 get_vpss_fd(void)
{
if (dev_vpss.fd <= 0)
vpss_dev_open();
return dev_vpss.fd;
}
CVI_S32 vpss_dev_open(CVI_VOID)
{
CVI_S32 s32Ret = CVI_SUCCESS;
if (dev_vpss.state != VDEV_STATE_OPEN) {
snprintf(dev_vpss.name, sizeof(dev_vpss.name) - 1,
"/dev/cvi-vpss");
if (open_device(dev_vpss.name, &dev_vpss.fd) == -1) {
perror("VPSS open fail\n");
s32Ret = CVI_FAILURE;
return s32Ret;
}
dev_vpss.state = VDEV_STATE_OPEN;
}
return s32Ret;
}
CVI_S32 vpss_dev_close(CVI_VOID)
{
CVI_S32 s32Ret = CVI_SUCCESS;
if (dev_vpss.state != VDEV_STATE_CLOSED) {
s32Ret = close_device(&dev_vpss.fd);
if (s32Ret != CVI_SUCCESS) {
perror("VPSS close failed\n");
s32Ret = CVI_FAILURE;
return s32Ret;
}
dev_vpss.fd = -1;
dev_vpss.state = VDEV_STATE_CLOSED;
}
return s32Ret;
}
CVI_S32 get_vi_fd(CVI_VOID)
{
if (dev_isp.fd <= 0)
vi_dev_open();
return dev_isp.fd;
}
CVI_S32 vi_dev_open(CVI_VOID)
{
if (dev_isp.state != VDEV_STATE_OPEN) {
// isp
strncpy(dev_isp.name, "VI", sizeof(dev_isp.name));
dev_isp.state = VDEV_STATE_CLOSED;
if (open_device(VI_DEV_NAME, &dev_isp.fd) == -1) {
perror("VI open failed\n");
dev_isp.fd = -1;
return CVI_FAILURE;
}
dev_isp.state = VDEV_STATE_OPEN;
}
return CVI_SUCCESS;
}
CVI_S32 vi_dev_close(CVI_VOID)
{
if (dev_isp.state != VDEV_STATE_CLOSED) {
if (close_device(&dev_isp.fd) == -1) {
perror("VI close failed\n");
dev_isp.fd = -1;
return CVI_FAILURE;
}
dev_isp.state = VDEV_STATE_CLOSED;
dev_isp.fd = -1;
}
return CVI_SUCCESS;
}
CVI_S32 sys_dev_open(CVI_VOID)
{
if (sys_fd != -1) {
CVI_TRACE_SYS(CVI_DBG_INFO, "sys dev has already opened\n");
return CVI_SUCCESS;
}
if (open_device(SYS_DEV_NAME, &sys_fd) != 0) {
perror("sys open failed");
sys_fd = -1;
return CVI_ERR_SYS_NOTREADY;
}
return CVI_SUCCESS;
}
CVI_S32 sys_dev_close(CVI_VOID)
{
if (sys_fd == -1) {
CVI_TRACE_SYS(CVI_DBG_INFO, "sys dev is not opened\n");
return CVI_SUCCESS;
}
close_device(&sys_fd);
sys_fd = -1;
return CVI_SUCCESS;
}
CVI_S32 get_sys_fd(CVI_VOID)
{
if (sys_fd == -1)
sys_dev_open();
return sys_fd;
}
CVI_S32 dwa_dev_open(CVI_VOID)
{
CVI_S32 s32Ret = CVI_SUCCESS;
dwa_dev_close();
snprintf(dev_dwa.name, sizeof(dev_dwa.name) - 1, "/dev/cvi-dwa");
if (open_device(dev_dwa.name, &dev_dwa.fd) == -1) {
perror("dwa open failed");
return CVI_FAILURE;
}
dev_dwa.state = VDEV_STATE_OPEN;
return s32Ret;
}
CVI_S32 dwa_dev_close(CVI_VOID)
{
CVI_S32 s32Ret = CVI_SUCCESS;
if (dev_dwa.state != VDEV_STATE_CLOSED) {
close_device(&dev_dwa.fd);
dev_dwa.fd = -1;
dev_dwa.state = VDEV_STATE_CLOSED;
}
return s32Ret;
}
CVI_S32 base_dev_open(CVI_VOID)
{
if (base_fd != -1) {
CVI_TRACE_SYS(CVI_DBG_DEBUG, "base dev has already opened\n");
return CVI_SUCCESS;
}
if (open_device(BASE_DEV_NAME, &base_fd) != 0) {
perror("base open failed");
base_fd = -1;
return CVI_ERR_SYS_NOTREADY;
}
return CVI_SUCCESS;
}
CVI_S32 base_dev_close(CVI_VOID)
{
if (base_fd == -1) {
CVI_TRACE_SYS(CVI_DBG_INFO, "base dev is not opened\n");
return CVI_SUCCESS;
}
close_device(&base_fd);
base_fd = -1;
return CVI_SUCCESS;
}
CVI_S32 get_base_fd(CVI_VOID)
{
if (base_fd == -1)
base_dev_open();
return base_fd;
}
CVI_S32 vpss_close(void)
{
if (dev_vpss.state != VDEV_STATE_CLOSED) {
close_device(&dev_vpss.fd);
dev_vpss.state = VDEV_STATE_CLOSED;
}
return CVI_SUCCESS;
}
CVI_S32 vo_close(void)
{
if (dev_disp.state != VDEV_STATE_CLOSED) {
close_device(&dev_disp.fd);
dev_disp.state = VDEV_STATE_CLOSED;
}
return CVI_SUCCESS;
}
long get_diff_in_us(struct timespec t1, struct timespec t2)
{
struct timespec diff;
if (t2.tv_nsec-t1.tv_nsec < 0) {
diff.tv_sec = t2.tv_sec - t1.tv_sec - 1;
diff.tv_nsec = t2.tv_nsec - t1.tv_nsec + 1000000000;
} else {
diff.tv_sec = t2.tv_sec - t1.tv_sec;
diff.tv_nsec = t2.tv_nsec - t1.tv_nsec;
}
return (diff.tv_sec * 1000000.0 + diff.tv_nsec / 1000.0);
}
void *base_get_shm(void)
{
base_dev_open();
if (shared_mem == NULL) {
shared_mem = mmap(NULL, BASE_SHARE_MEM_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, base_fd, 0);
if (shared_mem == MAP_FAILED) {
CVI_TRACE_SYS(CVI_DBG_ERR, "base dev mmap fail!\n");
return NULL;
}
}
shared_mem_usr_cnt++;
return shared_mem;
}
void base_release_shm(void)
{
shared_mem_usr_cnt--;
if (shared_mem_usr_cnt == 0 && shared_mem != NULL) {
munmap((void *)shared_mem, BASE_SHARE_MEM_SIZE);
shared_mem = NULL;
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,675 @@
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <poll.h>
#include <string.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <signal.h>
#include <linux/socket.h>
#include <linux/genetlink.h>
#include <linux/thermal.h>
#include <errno.h>
#include <pthread.h>
#include <sys/prctl.h>
#include "cvi_sys.h"
/* Generic macros for dealing with netlink sockets. Might be duplicated
* elsewhere. It is recommended that commercial grade applications use
* libnl or libnetlink and use the interfaces provided by the library
*/
#define GENLMSG_DATA(glh) ((void *)(NLMSG_DATA(glh) + GENL_HDRLEN))
#define GENLMSG_PAYLOAD(glh) (NLMSG_PAYLOAD(glh, 0) - GENL_HDRLEN)
#define NLA_DATA(na) ((void *)((char *)(na) + NLA_HDRLEN))
#ifndef SOL_NETLINK
#define SOL_NETLINK 270
#endif
//Variables used for netlink
struct sockaddr_nl nl_address; //netlink socket address
struct nlattr *nl_na; //pointer to netlink attributes structure within the payload
struct { //memory for netlink request and response messages - headers are included
struct nlmsghdr n;
struct genlmsghdr g;
char buf[256];
} nl_request_msg, nl_response_msg;
struct thermal_event {
int orig;
unsigned short up_down;
unsigned short trip_id;
} thermal_event;
struct thermal_event *tz_evt;
typedef void (*event_cb_t)(int fps);
pthread_t thermal_thread;
CVI_BOOL g_is_thermal_running = CVI_FALSE;
event_cb_t callbackFunc;
int therm_sockets[2];
static int _init_bind_genl_socket(void)
{
//Step 1: Open the socket. Note that protocol = NETLINK_GENERIC
int nl_fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_GENERIC);
if (nl_fd < 0) {
perror("socket()");
return -1;
}
//Step 2: Bind the socket.
memset(&nl_address, 0, sizeof(nl_address));
nl_address.nl_family = AF_NETLINK;
nl_address.nl_groups = 0;
if (bind(nl_fd, (struct sockaddr *) &nl_address, sizeof(nl_address)) < 0) {
perror("bind()");
close(nl_fd);
return -1;
}
return nl_fd;
}
static int _get_mcast_grpid_genl_socket(int nl_fd, const char *family_name)
{
int nl_group_id = 0;
int nl_rxtx_length;
//Step 3. Resolve the family ID corresponding to the string "thermal_event"
//Populate the netlink header
nl_request_msg.n.nlmsg_type = GENL_ID_CTRL;
nl_request_msg.n.nlmsg_flags = NLM_F_REQUEST;
nl_request_msg.n.nlmsg_seq = 0;
nl_request_msg.n.nlmsg_pid = getpid();
nl_request_msg.n.nlmsg_len = NLMSG_LENGTH(GENL_HDRLEN);
//Populate the payload's "family header" : which in our case is genlmsghdr
nl_request_msg.g.cmd = CTRL_CMD_GETFAMILY;
nl_request_msg.g.version = 0x1;
//Populate the payload's "netlink attributes"
nl_na = (struct nlattr *) GENLMSG_DATA(&nl_request_msg);
nl_na->nla_type = CTRL_ATTR_FAMILY_NAME;
nl_na->nla_len = strlen(family_name) + 1 + NLA_HDRLEN;
strcpy(NLA_DATA(nl_na), family_name); //Family name length can be upto 16 chars including \0
nl_request_msg.n.nlmsg_len += NLMSG_ALIGN(nl_na->nla_len);
memset(&nl_address, 0, sizeof(nl_address));
nl_address.nl_family = AF_NETLINK;
//Send the family ID request message to the netlink controller
nl_rxtx_length = sendto(nl_fd, (char *) &nl_request_msg, nl_request_msg.n.nlmsg_len,
0, (struct sockaddr *) &nl_address, sizeof(nl_address));
if (nl_rxtx_length != (int) nl_request_msg.n.nlmsg_len) {
perror("sendto()");
close(nl_fd);
return -1;
}
//Wait for the response message
nl_rxtx_length = recv(nl_fd, &nl_response_msg, sizeof(nl_response_msg), 0);
if (nl_rxtx_length < 0) {
perror("recv()");
return -1;
}
//Validate response message
if (!NLMSG_OK((&nl_response_msg.n), (unsigned int) nl_rxtx_length)) {
fprintf(stderr, "family ID request : invalid message\n");
return -1;
}
if (nl_response_msg.n.nlmsg_type == NLMSG_ERROR) { //error
fprintf(stderr, "family ID request : receive error\n");
return -1;
}
//Extract family ID
nl_na = (struct nlattr *) GENLMSG_DATA(&nl_response_msg);
nl_na = (struct nlattr *) ((char *) nl_na + NLA_ALIGN(nl_na->nla_len));
#if 0
if (nl_na->nla_type == CTRL_ATTR_FAMILY_ID) {
int nl_family_id = *(__u16 *) NLA_DATA(nl_na);
fprintf(stderr, "family ID get : %u\n", nl_family_id);
}
#endif
do {
//CTRL_ATTR_VERSION
//CTRL_ATTR_HDRSIZE
//CTRL_ATTR_MAXATTR
//CTRL_ATTR_MCAST_GROUPS
nl_na = (struct nlattr *) ((char *) nl_na + NLA_ALIGN(nl_na->nla_len));
} while (*((char *) nl_na) != 0 && nl_na->nla_type != CTRL_ATTR_MCAST_GROUPS);
// fprintf(stderr, "family Mcast group get : %d len %u\n", nl_na->nla_type, nl_na->nla_len);
// for (unsigned short i = 0;i < nl_na->nla_len;i++)
// {
// printf("%02x ", *(((char *) nl_na)+i));
// if (i % 16 == 15) printf("\n");
// }
// printf("\n");
if (nl_na->nla_type == CTRL_ATTR_MCAST_GROUPS) {
nl_na = (struct nlattr *) NLA_DATA(nl_na);
// fprintf(stderr, "family Mcast group get NLA : %d len %u\n", nl_na->nla_type, nl_na->nla_len);
nl_na = (struct nlattr *) NLA_DATA(nl_na);
if (nl_na->nla_type == CTRL_ATTR_MCAST_GRP_ID) {
nl_group_id = *(__u32 *) NLA_DATA(nl_na);
// fprintf(stderr, "family Mcast grp id get : %d\n", nl_group_id);
nl_na = (struct nlattr *) ((char *) nl_na + NLA_ALIGN(nl_na->nla_len));
}
if (nl_na->nla_type == CTRL_ATTR_MCAST_GRP_NAME) {
// fprintf(stderr, "family Mcast grp name get : %s\n", (char *) NLA_DATA(nl_na));
nl_na = (struct nlattr *) ((char *) nl_na + NLA_ALIGN(nl_na->nla_len));
}
#ifdef THERMAL_GENL_EVENT_GROUP_NAME
nl_na = (struct nlattr *) NLA_DATA(nl_na);
if (nl_na->nla_type == CTRL_ATTR_MCAST_GRP_ID) {
nl_group_id = *(__u32 *) NLA_DATA(nl_na);
// fprintf(stderr, "family Mcast grp id get : %d\n", nl_group_id);
nl_na = (struct nlattr *) ((char *) nl_na + NLA_ALIGN(nl_na->nla_len));
}
if (nl_na->nla_type == CTRL_ATTR_MCAST_GRP_NAME) {
// fprintf(stderr, "family Mcast grp name get : %s\n", (char *) NLA_DATA(nl_na));
}
#endif
}
return nl_group_id;
}
static int _get_notify_genl_socket(int nl_fd, int *trip_id, int *up_down)
{
int nl_rxtx_length; //Number of bytes sent or received via send() or recv()
//Step 4. Send own custom message
memset(&nl_response_msg, 0, sizeof(nl_response_msg));
//Receive reply from kernel
nl_rxtx_length = recv(nl_fd, &nl_response_msg, sizeof(nl_response_msg), 0);
if (nl_rxtx_length < 0) {
perror("recv()");
return -1;
}
//Validate response message
if (nl_response_msg.n.nlmsg_type == NLMSG_ERROR) { //Error
CVI_TRACE_SYS(CVI_DBG_ERR, "Error while receiving reply from kernel: NACK Received\n");
return -1;
}
if (nl_rxtx_length < 0) {
CVI_TRACE_SYS(CVI_DBG_ERR, "Error while receiving reply from kernel\n");
return -1;
}
if (!NLMSG_OK((&nl_response_msg.n), (unsigned int) nl_rxtx_length)) {
CVI_TRACE_SYS(CVI_DBG_ERR, "Error while receiving reply from kernel: Invalid Message\n");
return -1;
}
//Parse the reply message
nl_rxtx_length = GENLMSG_PAYLOAD(&nl_response_msg.n);
nl_na = (struct nlattr *) GENLMSG_DATA(&nl_response_msg);
// fprintf(stderr, "Recv Response: type %d len %u\n", nl_na->nla_type, nl_na->nla_len);
#ifdef THERMAL_GENL_EVENT_GROUP_NAME
if ((nl_response_msg.g.cmd != THERMAL_GENL_EVENT_TZ_TRIP_UP) &&
(nl_response_msg.g.cmd != THERMAL_GENL_EVENT_TZ_TRIP_DOWN))
return -1;
if (nl_na->nla_type != THERMAL_GENL_ATTR_TZ_TRIP_ID) {
// fprintf(stderr, "Response: type %d len %u\n", nl_na->nla_type, nl_na->nla_len);
// for (unsigned short i = 0;i < nl_na->nla_len;i++)
// {
// printf("%02x ", *(((char *) nl_na)+i));
// if (i % 16 == 15) printf("\n");
// }
// printf("\n");
nl_na = (struct nlattr *) ((char *) nl_na + NLA_ALIGN(nl_na->nla_len));
}
*trip_id = *(__u32 *) NLA_DATA(nl_na);
*up_down = (nl_response_msg.g.cmd == THERMAL_GENL_EVENT_TZ_TRIP_UP) ? 0 : 1;
#else
tz_evt = (struct thermal_event *) NLA_DATA(nl_na);
*trip_id = tz_evt->trip_id;
*up_down = tz_evt->up_down;
#endif
return 0;
}
static int _read_cooling_maxstate(void)
{
CVI_CHAR buf[32];
char temp_path[128] = "/sys/class/thermal/cooling_device0/max_state";
int fd = open(temp_path, O_RDONLY);
if (fd < 0) {
CVI_TRACE_SYS(CVI_DBG_ERR, "open cooling max_state failed\n");
return -1;
}
read(fd, buf, sizeof(buf));
close(fd);
return atoi(buf);
}
static int _write_cooling_curstate(int cur_state)
{
CVI_CHAR buf[32];
char temp_path[128] = "/sys/class/thermal/cooling_device0/cur_state";
int fd = open(temp_path, O_WRONLY);
if (fd < 0) {
CVI_TRACE_SYS(CVI_DBG_ERR, "open cooling cur_state failed\n");
return -1;
}
snprintf(buf, sizeof(buf), "%d", cur_state);
write(fd, buf, sizeof(buf));
close(fd);
return 0;
}
static int _write_trip_pointers(int trip_id, int trip_temps, const char *target)
{
CVI_CHAR buf[32];
CVI_S32 trip_point_fd = 0;
char temp_path[128] = "/sys/class/thermal/thermal_zone0/trip_point_?_";
strcat(temp_path, target);
temp_path[44] = 0x30 + trip_id;
trip_point_fd = open(temp_path, O_WRONLY);
if (trip_point_fd < 0) {
CVI_TRACE_SYS(CVI_DBG_ERR, "open trip point temp failed\n");
return -1;
}
snprintf(buf, sizeof(buf), "%d", trip_temps);
write(trip_point_fd, buf, sizeof(buf));
close(trip_point_fd);
return 0;
}
static unsigned int _read_trip_pointers(int trip_temps[], unsigned int uplimit)
{
CVI_CHAR buf[32];
CVI_S32 trip_point_fd = 0;
char temp_path[128] = "/sys/class/thermal/thermal_zone0/trip_point_?_temp";
char type_path[128] = "/sys/class/thermal/thermal_zone0/trip_point_?_type";
unsigned int trip_id;
for (trip_id = 0; trip_id < uplimit; trip_id++) {
temp_path[44] = 0x30 + trip_id;
type_path[44] = 0x30 + trip_id;
trip_point_fd = open(temp_path, O_RDONLY);
if (trip_point_fd < 0) {
CVI_TRACE_SYS(CVI_DBG_ERR, "open trip point temp failed\n");
break;
}
read(trip_point_fd, buf, sizeof(buf));
close(trip_point_fd);
trip_temps[trip_id] = strtol(buf, NULL, 10);
trip_point_fd = open(type_path, O_RDONLY);
if (trip_point_fd < 0) {
CVI_TRACE_SYS(CVI_DBG_ERR, "open trip point type failed\n");
break;
}
read(trip_point_fd, buf, sizeof(buf));
close(trip_point_fd);
if (strncmp(buf, "critical", 8) == 0) {
trip_temps[trip_id] = 0;
break;
}
}
return trip_id;
}
static int _read_chip_temp(CVI_S32 *temp)
{
CVI_CHAR buf[32];
CVI_S32 thermal_fd = 0;
thermal_fd = open("/sys/class/thermal/thermal_zone0/temp", O_RDONLY);
if (thermal_fd < 0) {
CVI_TRACE_SYS(CVI_DBG_ERR, "open thermal failed\n");
return -1;
}
read(thermal_fd, buf, sizeof(buf));
close(thermal_fd);
*temp = strtol(buf, NULL, 10);
return 0;
}
static void _log_event(FILE *fpEvtlog, int trip_id, int up_down, int fps, int state)
{
time_t rawtime;
struct tm *info;
char buffer[80];
char str_buffer[128];
int ret;
CVI_S32 temp = 0;
if (!fpEvtlog)
return;
_read_chip_temp(&temp);
time(&rawtime);
info = localtime(&rawtime);
strftime(buffer, 80, "%y/%m/%d %X", info);
if (trip_id < 0) {
ret = snprintf(str_buffer, 128, "[%s] temp %d\n", buffer, temp);
} else if (fps <= 0) {
ret = snprintf(str_buffer, 128, "[%s] temp %d trip_id %d %s. %sCoolingState %d\n"
, buffer, temp, trip_id, (up_down) ? "down" : "up"
, (fps == 0) ? "Restore FPS, " : "", state);
} else {
ret = snprintf(str_buffer, 128, "[%s] temp %d trip_id %d %s. Set FPS:%d CoolingState %d\n"
, buffer, temp, trip_id, (up_down) ? "down" : "up"
, fps, state);
}
fwrite(str_buffer, ret, 1, fpEvtlog);
fflush(fpEvtlog);
}
static void _dump_register(FILE *fpEvtlog)
{
FILE *fpReadReg = NULL;
if (!fpEvtlog)
return;
fpReadReg = fopen("/sys/class/cvi-base/base_efuse_shadow", "r");
if (fpReadReg) {
char str_buffer[128] = "dump register:\n";
int ahead = 0, read;
fwrite(str_buffer, strlen(str_buffer), 1, fpEvtlog);
do {
char out_buffer[128];
int out = 0;
read = fread(str_buffer, 1, sizeof(str_buffer), fpReadReg);
// printf("fread %d byte\n", read);
for (int j = 0; j < read; j++) {
if ((j%16) == 0)
out = snprintf(out_buffer, 128, "%04X ", j + ahead);
out += snprintf(out_buffer + out, 128 - out, "%02X ", str_buffer[j]);
if ((j%16) == 15) {
out += snprintf(out_buffer + out, 128 - out, "\n");
fwrite(out_buffer, out, 1, fpEvtlog);
out = 0;
}
}
ahead = read;
} while (read == sizeof(str_buffer));
fclose(fpReadReg);
fflush(fpEvtlog);
}
}
void CVI_SYS_RegisterThermalCallback(void (*setFPS)(int))
{
callbackFunc = setFPS;
}
static CVI_VOID *tz_event_handler(CVI_VOID *data)
{
int nl_fd; //netlink socket's file descriptor
int nl_group_id;
int err;
int trip_temps[10];
CVI_U32 trip_num;
CVI_S32 init_temp = 0;
int FPS_ARRAY[4] = {0, 15, 5, 1};
int COOLING_ARRAY[4] = {0, 1, 2, 3};
int FPS;
CVI_U32 zone;
CVI_U32 i;
int max_state;
char *CtrlEnv = getenv("cvitherm_ctl");
char *EvtlogEnv = getenv("cvitherm_log");
char *EvtlogInterval = getenv("cvitherm_interval");
FILE *fpEvtlog = NULL;
int iEvtlogInterval = (EvtlogInterval) ? atoi(EvtlogInterval) : 10;
prctl(PR_SET_NAME, "tz_event_handler");
(void)(data);
nl_fd = _init_bind_genl_socket();
if (nl_fd < 0) {
CVI_TRACE_SYS(CVI_DBG_ERR, "init netlink socket fail\n");
goto exit_loop;
}
nl_group_id = _get_mcast_grpid_genl_socket(nl_fd, THERMAL_GENL_FAMILY_NAME);
if (nl_group_id == 0) {
CVI_TRACE_SYS(CVI_DBG_ERR, "get mcast grp id fail\n");
close(nl_fd);
goto exit_loop;
}
err = setsockopt(nl_fd, SOL_NETLINK, NETLINK_ADD_MEMBERSHIP, &nl_group_id, sizeof(nl_group_id));
if (err < 0) {
CVI_TRACE_SYS(CVI_DBG_ERR, "NETLINK_ADD_MEMBERSHIP fail\n");
close(nl_fd);
goto exit_loop;
}
if (_read_chip_temp(&init_temp) < 0) {
CVI_TRACE_SYS(CVI_DBG_ERR, "Read init temp fail\n");
close(nl_fd);
goto exit_loop;
}
max_state = _read_cooling_maxstate();
trip_num = _read_trip_pointers(trip_temps, sizeof(trip_temps)/sizeof(int));
if (EvtlogEnv) {
fpEvtlog = fopen(EvtlogEnv, "a");
_dump_register(fpEvtlog);
}
if (CtrlEnv) {
char *colon = strchr(CtrlEnv, ':');
char *newString = NULL, *newString2 = NULL;
char *comma = CtrlEnv;
if (colon) {
newString = strndup(CtrlEnv, colon - CtrlEnv);
comma = colon;
colon = strchr(colon+1, ':');
if (colon) {
newString2 = strndup(comma, colon - comma);
comma = colon+1;
for (i = 1; comma && (*comma) && i < sizeof(COOLING_ARRAY)/sizeof(int); i++) {
COOLING_ARRAY[i] = atoi(comma);
comma = strchr(comma, ',');
if (comma)
comma++;
}
comma = newString2;
}
comma++;
for (i = 1; comma && (*comma) && i < sizeof(FPS_ARRAY)/sizeof(int); i++) {
FPS_ARRAY[i] = atoi(comma);
comma = strchr(comma, ',');
if (comma)
comma++;
}
comma = newString;
}
for (i = 0; comma && (*comma) && i < trip_num; i++) {
int hyst;
trip_temps[i] = atoi(comma)*1000;
_write_trip_pointers(i, trip_temps[i], "temp");
comma = strchr(comma, ',');
if (comma)
comma++;
hyst = atoi(comma)*1000;
_write_trip_pointers(i, hyst, "hyst");
comma = strchr(comma, ',');
if (comma)
comma++;
}
if (newString)
free(newString);
if (newString2)
free(newString2);
}
#if 0
printf("FPS: ");
for (i = 0; i < sizeof(FPS_ARRAY)/sizeof(int); i++) {
printf("[%d] ", FPS_ARRAY[i]);
}
printf("\n");
printf("TRIPs: ");
for (i = 0; i < trip_num; i++) {
printf("[%d] ", trip_temps[i]);
}
printf("\n");
printf("COOLINGs: ");
for (i = 0; i < sizeof(COOLING_ARRAY)/sizeof(int); i++) {
printf("[%d] ", COOLING_ARRAY[i]);
}
printf("\n");
#endif
for (zone = 0; zone < trip_num; zone++) {
if (init_temp < trip_temps[zone]) {
break;
}
}
//Not zero zone
if (zone > 1) {
FPS = FPS_ARRAY[zone];
if (callbackFunc)
callbackFunc(FPS);
}
_write_cooling_curstate((COOLING_ARRAY[zone] > max_state) ? max_state : COOLING_ARRAY[zone]);
CVI_TRACE_SYS(CVI_DBG_INFO, "Read init_temp %d max_state %d trip_point_num %d zone %d\n"
, init_temp, max_state, trip_num, zone);
while (g_is_thermal_running) {
int trip_id, up_down;
int up_check, down_check;
CVI_U32 next_zone = zone;
int r;
int max_fd = nl_fd;
fd_set readfds;
struct timeval tv;
FD_ZERO(&readfds);
FD_SET(nl_fd, &readfds);
FD_SET(therm_sockets[1], &readfds);
tv.tv_sec = iEvtlogInterval;
tv.tv_usec = 0;
if (therm_sockets[1] > max_fd)
max_fd = therm_sockets[1];
r = select(max_fd + 1, &readfds, NULL, NULL, &tv);
if (r == -1) {
if (errno == EINTR)
continue;
continue;
} else if (r == 0) {
//fprintf(stderr, "%s: select timeout\n", __func__);
_log_event(fpEvtlog, -1, -1, -1, -1);
continue;
} else if (FD_ISSET(therm_sockets[1], &readfds)) {
break;
}
if (_get_notify_genl_socket(nl_fd, &trip_id, &up_down) < 0) {
CVI_TRACE_SYS(CVI_DBG_ERR, "_get_notify_genl_socket fail\n");
continue;
}
CVI_TRACE_SYS(CVI_DBG_INFO, "Got trip %d %s\n", trip_id, (up_down) ? "down" : "up");
down_check = zone - 1;
up_check = zone;
if (down_check == trip_id && up_down == 1) {
next_zone = zone - 1;
} else if (trip_id < down_check && up_down == 1) {
next_zone = trip_id;
} else if (up_check == trip_id && up_down == 0) {
next_zone = zone + 1;
} else if (trip_id > up_check && up_down == 0) {
next_zone = trip_id + 1;
}
if (next_zone != zone && next_zone < sizeof(COOLING_ARRAY)/sizeof(int)) {
int next_state = COOLING_ARRAY[next_zone];
if (next_state > max_state)
next_state = max_state;
_write_cooling_curstate(next_state);
FPS = FPS_ARRAY[next_zone];
if (callbackFunc) {
callbackFunc(FPS);
_log_event(fpEvtlog, trip_id, up_down, FPS, next_state);
} else {
_log_event(fpEvtlog, trip_id, up_down, -1, next_state);
}
zone = next_zone;
}
}
if (fpEvtlog) {
fclose(fpEvtlog);
fpEvtlog = NULL;
}
close(nl_fd);
exit_loop:
g_is_thermal_running = CVI_FALSE;
pthread_exit(NULL);
}
CVI_S32 CVI_SYS_StartThermalThread(void)
{
struct sched_param param;
pthread_attr_t attr;
if (g_is_thermal_running == CVI_TRUE) {
CVI_TRACE_SYS(CVI_DBG_WARN, "already started\n");
return CVI_FAILURE;
}
g_is_thermal_running = CVI_TRUE;
socketpair(AF_UNIX, SOCK_SEQPACKET, 0, therm_sockets);
param.sched_priority = 85;
pthread_attr_init(&attr);
pthread_attr_setschedpolicy(&attr, SCHED_RR);
pthread_attr_setschedparam(&attr, &param);
pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED);
pthread_create(&thermal_thread, &attr, (void *)tz_event_handler, NULL);
CVI_TRACE_SYS(CVI_DBG_INFO, "CVI_SYS_StartThermalThread\n");
return CVI_SUCCESS;
}
CVI_S32 CVI_SYS_StopThermalThread(void)
{
if (g_is_thermal_running == CVI_FALSE) {
CVI_TRACE_SYS(CVI_DBG_WARN, "not start yet\n");
return CVI_FAILURE;
}
g_is_thermal_running = CVI_FALSE;
if (thermal_thread) {
char buf[8];
write(therm_sockets[0], buf, 8);
pthread_join(thermal_thread, NULL);
thermal_thread = 0;
}
close(therm_sockets[0]);
close(therm_sockets[1]);
CVI_TRACE_SYS(CVI_DBG_INFO, "CVI_SYS_StopThermalThread\n");
return CVI_SUCCESS;
}

View File

@@ -0,0 +1,84 @@
#include "cvi_misc.h"
#include <fcntl.h>
#include <stdint.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <pthread.h>
#ifdef ENABLE_TRACE
static int sTraceFD = -1;
pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
#else
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-parameter"
#endif
static inline void init(void)
{
#ifdef ENABLE_TRACE
const char *traceFileName = "/sys/kernel/debug/tracing/trace_marker";
sTraceFD = open(traceFileName, O_WRONLY);
if (sTraceFD == -1) {
printf("error opening trace file, errno(%d), %s\n", errno, strerror(errno));
// sEnabledTags remains zero indicating that no tracing can occur
}
#endif
}
void CVI_SYS_TraceBegin(const char *name)
{
#ifdef ENABLE_TRACE
pthread_mutex_lock(&lock);
if (sTraceFD == -1) {
init();
}
pthread_mutex_unlock(&lock);
char buf[1024] = {};
size_t len = snprintf(buf, 1024, "B|%d|%s", getpid(), name);
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-result"
write(sTraceFD, buf, len);
#pragma GCC diagnostic pop
#endif
}
void CVI_SYS_TraceCounter(const char *name, signed int value)
{
#ifdef ENABLE_TRACE
char buf[1024] = {};
snprintf(buf, 1024, "C|%d|%s|%d", getpid(), name, value);
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-result"
write(sTraceFD, buf, strlen(buf));
#pragma GCC diagnostic pop
#endif
}
void CVI_SYS_TraceEnd(void)
{
#ifdef ENABLE_TRACE
char buf = 'E';
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-result"
write(sTraceFD, &buf, 1);
#pragma GCC diagnostic pop
#endif
}
#ifndef ENABLE_TRACE
#pragma GCC diagnostic pop
#endif

View File

@@ -0,0 +1,552 @@
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/queue.h>
#include <pthread.h>
#include <stdatomic.h>
#include <inttypes.h>
#include "hashmap.h"
#include "devmem.h"
#include "cvi_base.h"
#include "cvi_vb.h"
#include "cvi_sys.h"
#include "vb_ioctl.h"
#include "linux/vb_uapi.h"
#ifndef UNUSED
#define UNUSED(x) ((x) = (x))
#endif
typedef struct _pool {
CVI_U64 memBase;
void *vmemBase;
CVI_U32 u32BlkSize;
CVI_U32 u32BlkCnt;
VB_REMAP_MODE_E enRemapMode;
} VB_POOL_S;
static Hashmap *vbMmapHash;
pthread_mutex_t hash_lock;
static atomic_bool vb_inited = ATOMIC_VAR_INIT(false);
static int _vb_hash_key(void *key)
{
return (((uintptr_t)key) >> 10);
}
static bool _vb_hash_equals(void *keyA, void *keyB)
{
return (keyA == keyB);
}
VB_BLK CVI_VB_GetBlockwithID(VB_POOL Pool, CVI_U32 u32BlkSize, MOD_ID_E modId)
{
CVI_TRACE_VB(CVI_DBG_ERR, "Pls use CVI_VB_GetBlock\n");
UNUSED(Pool);
UNUSED(u32BlkSize);
UNUSED(modId);
return 0;
}
/**************************************************************************
* Public APIs.
**************************************************************************/
/* CVI_VB_GetBlock: acquice a vb_blk with specific size from pool.
*
* @param pool: the pool to acquice blk. if VB_INVALID_POOLID, go through common-pool to search.
* @param u32BlkSize: the size of vb_blk to acquire.
* @return: the vb_blk if available. otherwise, VB_INVALID_HANDLE.
*/
VB_BLK CVI_VB_GetBlock(VB_POOL Pool, CVI_U32 u32BlkSize)
{
CVI_S32 s32Ret, fd;
struct cvi_vb_blk_cfg cfg;
fd = get_base_fd();
if (fd == -1) {
CVI_TRACE_VB(CVI_DBG_ERR, "get_base_fd failed.\n");
return VB_INVALID_HANDLE;
}
memset(&cfg, 0, sizeof(cfg));
cfg.pool_id = Pool;
cfg.blk_size = u32BlkSize;
s32Ret = vb_ioctl_get_block(fd, &cfg);
if (s32Ret != CVI_SUCCESS) {
CVI_TRACE_VB(CVI_DBG_ERR, "vb_ioctl_get_block fail, ret(%d)\n", s32Ret);
return VB_INVALID_HANDLE;
}
return (VB_BLK)cfg.blk;
}
/* CVI_VB_ReleaseBlock: release a vb_blk.
*
* @param Block: the vb_blk going to be released.
* @return: CVI_SUCCESS if success; others if fail.
*/
CVI_S32 CVI_VB_ReleaseBlock(VB_BLK Block)
{
CVI_S32 s32Ret, fd;
fd = get_base_fd();
if (fd == -1) {
CVI_TRACE_VB(CVI_DBG_ERR, "get_base_fd failed.\n");
return CVI_ERR_VB_NOTREADY;
}
s32Ret = vb_ioctl_release_block(fd, Block);
if (s32Ret != CVI_SUCCESS) {
CVI_TRACE_VB(CVI_DBG_ERR, "vb_ioctl_release_block fail, ret(%d)\n", s32Ret);
return CVI_FAILURE;
}
return CVI_SUCCESS;
}
VB_BLK CVI_VB_PhysAddr2Handle(CVI_U64 u64PhyAddr)
{
CVI_S32 s32Ret, fd;
struct cvi_vb_blk_info blk_info;
fd = get_base_fd();
if (fd == -1) {
CVI_TRACE_VB(CVI_DBG_ERR, "get_base_fd failed.\n");
return VB_INVALID_HANDLE;
}
memset(&blk_info, 0, sizeof(blk_info));
blk_info.phy_addr = u64PhyAddr;
s32Ret = vb_ioctl_phys_to_handle(fd, &blk_info);
if (s32Ret != CVI_SUCCESS) {
CVI_TRACE_VB(CVI_DBG_ERR, "vb_ioctl_phys_to_handle fail, ret(%d)\n", s32Ret);
return VB_INVALID_HANDLE;
}
return (VB_BLK)blk_info.blk;
}
CVI_U64 CVI_VB_Handle2PhysAddr(VB_BLK Block)
{
CVI_S32 s32Ret, fd;
struct cvi_vb_blk_info blk_info;
fd = get_base_fd();
if (fd == -1) {
CVI_TRACE_VB(CVI_DBG_ERR, "get_base_fd failed.\n");
return 0;
}
memset(&blk_info, 0, sizeof(blk_info));
blk_info.blk = Block;
s32Ret = vb_ioctl_get_blk_info(fd, &blk_info);
if (s32Ret != CVI_SUCCESS) {
CVI_TRACE_VB(CVI_DBG_ERR, "vb_ioctl_get_blk_info fail, ret(%d)\n", s32Ret);
return 0;
}
return (CVI_U64)blk_info.phy_addr;
}
VB_POOL CVI_VB_Handle2PoolId(VB_BLK Block)
{
CVI_S32 s32Ret, fd;
struct cvi_vb_blk_info blk_info;
fd = get_base_fd();
if (fd == -1) {
CVI_TRACE_VB(CVI_DBG_ERR, "get_base_fd failed.\n");
return VB_INVALID_POOLID;
}
memset(&blk_info, 0, sizeof(blk_info));
blk_info.blk = Block;
s32Ret = vb_ioctl_get_blk_info(fd, &blk_info);
if (s32Ret != CVI_SUCCESS) {
CVI_TRACE_VB(CVI_DBG_ERR, "vb_ioctl_get_blk_info fail, ret(%d)\n", s32Ret);
return VB_INVALID_POOLID;
}
return (VB_POOL)blk_info.pool_id;
}
CVI_S32 CVI_VB_InquireUserCnt(VB_BLK Block, CVI_U32 *pCnt)
{
CVI_S32 s32Ret, fd;
struct cvi_vb_blk_info blk_info;
MOD_CHECK_NULL_PTR(CVI_ID_VB, pCnt);
fd = get_base_fd();
if (fd == -1) {
CVI_TRACE_VB(CVI_DBG_ERR, "get_base_fd failed.\n");
return CVI_ERR_VB_NOTREADY;
}
memset(&blk_info, 0, sizeof(blk_info));
blk_info.blk = Block;
s32Ret = vb_ioctl_get_blk_info(fd, &blk_info);
if (s32Ret != CVI_SUCCESS) {
CVI_TRACE_VB(CVI_DBG_ERR, "vb_ioctl_get_blk_info fail, ret(%d)\n", s32Ret);
return CVI_FAILURE;
}
*pCnt = blk_info.usr_cnt;
return CVI_SUCCESS;
}
CVI_S32 CVI_VB_Init(void)
{
CVI_S32 s32Ret, fd;
bool expect = false;
// Only init once until exit.
if (!atomic_compare_exchange_strong(&vb_inited, &expect, true))
return CVI_SUCCESS;
fd = get_base_fd();
if (fd == -1) {
CVI_TRACE_VB(CVI_DBG_ERR, "get_base_fd failed.\n");
return CVI_ERR_VB_NOTREADY;
}
s32Ret = vb_ioctl_init(fd);
if (s32Ret != CVI_SUCCESS) {
CVI_TRACE_VB(CVI_DBG_ERR, "vb_ioctl_init fail, ret(%d)\n", s32Ret);
return CVI_FAILURE;
}
return CVI_SUCCESS;
}
CVI_S32 CVI_VB_Exit(void)
{
CVI_S32 s32Ret, fd;
bool expect = true;
// Only exit once.
if (!atomic_compare_exchange_strong(&vb_inited, &expect, false))
return CVI_SUCCESS;
fd = get_base_fd();
if (fd == -1) {
CVI_TRACE_VB(CVI_DBG_ERR, "get_base_fd failed.\n");
return CVI_ERR_VB_NOTREADY;
}
s32Ret = vb_ioctl_exit(fd);
if (s32Ret != CVI_SUCCESS) {
CVI_TRACE_VB(CVI_DBG_ERR, "vb_ioctl_exit fail, ret(%d)\n", s32Ret);
base_dev_close();
return CVI_FAILURE;
}
base_dev_close();
return CVI_SUCCESS;
}
VB_POOL CVI_VB_CreatePool(VB_POOL_CONFIG_S *pstVbPoolCfg)
{
CVI_S32 s32Ret, fd;
struct cvi_vb_pool_cfg cfg;
MOD_CHECK_NULL_PTR(CVI_ID_VB, pstVbPoolCfg);
fd = get_base_fd();
if (fd == -1) {
CVI_TRACE_VB(CVI_DBG_ERR, "get_base_fd failed.\n");
return CVI_ERR_VB_NOTREADY;
}
memset(&cfg, 0, sizeof(cfg));
cfg.blk_size = pstVbPoolCfg->u32BlkSize;
cfg.blk_cnt = pstVbPoolCfg->u32BlkCnt;
cfg.remap_mode = pstVbPoolCfg->enRemapMode;
strncpy(cfg.pool_name, pstVbPoolCfg->acName, VB_POOL_NAME_LEN - 1);
s32Ret = vb_ioctl_create_pool(fd, &cfg);
if (s32Ret != CVI_SUCCESS) {
CVI_TRACE_VB(CVI_DBG_ERR, "vb_ioctl_create_pool fail, ret(%d)\n", s32Ret);
return VB_INVALID_POOLID;
}
return (VB_POOL)cfg.pool_id;
}
VB_POOL CVI_VB_CreateExPool(VB_POOL_CONFIG_EX_S *pstVbPoolExCfg)
{
CVI_S32 s32Ret, fd, i;
struct cvi_vb_pool_ex_cfg cfg;
MOD_CHECK_NULL_PTR(CVI_ID_VB, pstVbPoolExCfg);
fd = get_base_fd();
if (fd == -1) {
CVI_TRACE_VB(CVI_DBG_ERR, "get_base_fd failed.\n");
return CVI_ERR_VB_NOTREADY;
}
memset(&cfg, 0, sizeof(cfg));
cfg.blk_cnt = pstVbPoolExCfg->u32BlkCnt;
for (i = 0; i < VB_POOL_MAX_BLK; i++) {
cfg.au64PhyAddr[i][0] = pstVbPoolExCfg->astUserBlk[i].au64PhyAddr[0];
cfg.au64PhyAddr[i][1] = pstVbPoolExCfg->astUserBlk[i].au64PhyAddr[1];
cfg.au64PhyAddr[i][2] = pstVbPoolExCfg->astUserBlk[i].au64PhyAddr[2];
}
s32Ret = vb_ioctl_create_ex_pool(fd, &cfg);
if (s32Ret != CVI_SUCCESS) {
CVI_TRACE_VB(CVI_DBG_ERR, "vb_ioctl_create_ex_pool fail, ret(%d)\n", s32Ret);
return VB_INVALID_POOLID;
}
return (VB_POOL)cfg.pool_id;
}
CVI_S32 CVI_VB_DestroyPool(VB_POOL Pool)
{
CVI_S32 s32Ret, fd;
fd = get_base_fd();
if (fd == -1) {
CVI_TRACE_VB(CVI_DBG_ERR, "get_base_fd failed.\n");
return CVI_ERR_VB_NOTREADY;
}
s32Ret = vb_ioctl_destroy_pool(fd, Pool);
if (s32Ret != CVI_SUCCESS) {
CVI_TRACE_VB(CVI_DBG_ERR, "vb_ioctl_destroy_pool fail, ret(%d)\n", s32Ret);
return CVI_FAILURE;
}
if (vbMmapHash && hashmapGet(vbMmapHash, (void *)(uintptr_t)Pool))
CVI_VB_MunmapPool(Pool);
return CVI_SUCCESS;
}
CVI_S32 CVI_VB_SetConfig(const VB_CONFIG_S *pstVbConfig)
{
CVI_S32 s32Ret, fd;
struct cvi_vb_cfg cfg;
CVI_U32 i;
MOD_CHECK_NULL_PTR(CVI_ID_VB, pstVbConfig);
if (pstVbConfig->u32MaxPoolCnt > VB_COMM_POOL_MAX_CNT
|| pstVbConfig->u32MaxPoolCnt == 0) {
CVI_TRACE_VB(CVI_DBG_ERR, "Invalid vb u32MaxPoolCnt(%d)\n",
pstVbConfig->u32MaxPoolCnt);
return CVI_ERR_VB_ILLEGAL_PARAM;
}
fd = get_base_fd();
if (fd == -1) {
CVI_TRACE_VB(CVI_DBG_ERR, "get_base_fd failed.\n");
return CVI_ERR_VB_NOTREADY;
}
memset(&cfg, 0, sizeof(cfg));
cfg.comm_pool_cnt = pstVbConfig->u32MaxPoolCnt;
for (i = 0; i < cfg.comm_pool_cnt; ++i) {
cfg.comm_pool[i].blk_size = pstVbConfig->astCommPool[i].u32BlkSize;
cfg.comm_pool[i].blk_cnt = pstVbConfig->astCommPool[i].u32BlkCnt;
cfg.comm_pool[i].remap_mode = pstVbConfig->astCommPool[i].enRemapMode;
strncpy(cfg.comm_pool[i].pool_name,
pstVbConfig->astCommPool[i].acName, VB_POOL_NAME_LEN - 1);
}
s32Ret = vb_ioctl_set_config(fd, &cfg);
if (s32Ret != CVI_SUCCESS) {
CVI_TRACE_VB(CVI_DBG_ERR, "vb_ioctl_set_config fail, ret(%d)\n", s32Ret);
return CVI_FAILURE;
}
return CVI_SUCCESS;
}
CVI_S32 CVI_VB_GetConfig(VB_CONFIG_S *pstVbConfig)
{
CVI_S32 s32Ret, fd;
struct cvi_vb_cfg cfg;
CVI_U32 i;
MOD_CHECK_NULL_PTR(CVI_ID_VB, pstVbConfig);
fd = get_base_fd();
if (fd == -1) {
CVI_TRACE_VB(CVI_DBG_ERR, "get_base_fd failed.\n");
return CVI_ERR_VB_NOTREADY;
}
s32Ret = vb_ioctl_get_config(fd, &cfg);
if (s32Ret != CVI_SUCCESS) {
CVI_TRACE_VB(CVI_DBG_ERR, "vb_ioctl_get_config fail, ret(%d)\n", s32Ret);
return CVI_FAILURE;
}
memset(pstVbConfig, 0, sizeof(*pstVbConfig));
pstVbConfig->u32MaxPoolCnt = cfg.comm_pool_cnt;
for (i = 0; i < cfg.comm_pool_cnt; ++i) {
pstVbConfig->astCommPool[i].u32BlkSize = cfg.comm_pool[i].blk_size;
pstVbConfig->astCommPool[i].u32BlkCnt = cfg.comm_pool[i].blk_cnt;
pstVbConfig->astCommPool[i].enRemapMode = cfg.comm_pool[i].remap_mode;
strncpy(pstVbConfig->astCommPool[i].acName, cfg.comm_pool[i].pool_name,
MAX_VB_POOL_NAME_LEN - 1);
}
return CVI_SUCCESS;
}
/* CVI_VB_MmapPool - mmap the whole pool to get virtual-address
*
* @param Pool: pool id
* @return CVI_SUCCESS if success; others if fail
*/
CVI_S32 CVI_VB_MmapPool(VB_POOL Pool)
{
CVI_S32 s32Ret, fd;
struct cvi_vb_pool_cfg cfg;
VB_POOL_S *pstVbPool = NULL;
void *vaddr;
if (!vbMmapHash) {
vbMmapHash = hashmapCreate(20, _vb_hash_key, _vb_hash_equals);
pthread_mutex_init(&hash_lock, NULL);
}
pthread_mutex_lock(&hash_lock);
pstVbPool = hashmapGet(vbMmapHash, (void *)(uintptr_t)Pool);
if (pstVbPool) {
pthread_mutex_unlock(&hash_lock);
return CVI_SUCCESS;
}
fd = get_base_fd();
if (fd == -1) {
CVI_TRACE_VB(CVI_DBG_ERR, "get_base_fd failed.\n");
pthread_mutex_unlock(&hash_lock);
return CVI_ERR_VB_NOTREADY;
}
memset(&cfg, 0, sizeof(cfg));
cfg.pool_id = Pool;
s32Ret = vb_ioctl_get_pool_cfg(fd, &cfg);
if (s32Ret != CVI_SUCCESS) {
CVI_TRACE_VB(CVI_DBG_ERR, "vb_ioctl_get_pool_cfg fail, ret(%d)\n", s32Ret);
pthread_mutex_unlock(&hash_lock);
return CVI_ERR_VB_ILLEGAL_PARAM;
}
pstVbPool = (VB_POOL_S *)malloc(sizeof(*pstVbPool));
if (pstVbPool == NULL) {
CVI_TRACE_VB(CVI_DBG_ERR, "malloc failed.\n");
pthread_mutex_unlock(&hash_lock);
return CVI_ERR_VB_NOMEM;
}
if (cfg.remap_mode == VB_REMAP_MODE_CACHED)
vaddr = CVI_SYS_MmapCache(cfg.mem_base, cfg.blk_cnt * cfg.blk_size);
else
vaddr = CVI_SYS_Mmap(cfg.mem_base, cfg.blk_cnt * cfg.blk_size);
if (vaddr == NULL) {
CVI_TRACE_VB(CVI_DBG_ERR, "mmap failed.\n");
pthread_mutex_unlock(&hash_lock);
return CVI_ERR_VB_NOMEM;
}
pstVbPool->vmemBase = vaddr;
pstVbPool->memBase = cfg.mem_base;
pstVbPool->u32BlkSize = cfg.blk_size;
pstVbPool->u32BlkCnt = cfg.blk_cnt;
pstVbPool->enRemapMode = cfg.remap_mode;
hashmapPut(vbMmapHash, (void *)(uintptr_t)Pool, (void *)pstVbPool);
pthread_mutex_unlock(&hash_lock);
return CVI_SUCCESS;
}
CVI_S32 CVI_VB_MunmapPool(VB_POOL Pool)
{
VB_POOL_S *pstVbPool = NULL;
if (vbMmapHash == NULL) {
CVI_TRACE_VB(CVI_DBG_ERR, "not mmap yet.\n");
return CVI_ERR_VB_NOTREADY;
}
pthread_mutex_lock(&hash_lock);
pstVbPool = hashmapGet(vbMmapHash, (void *)(uintptr_t)Pool);
if (pstVbPool == NULL) {
CVI_TRACE_VB(CVI_DBG_ERR, "not mmap yet.\n");
pthread_mutex_unlock(&hash_lock);
return CVI_ERR_VB_NOTREADY;
}
if (CVI_SYS_Munmap(pstVbPool->vmemBase, pstVbPool->u32BlkCnt * pstVbPool->u32BlkSize) != CVI_SUCCESS) {
CVI_TRACE_VB(CVI_DBG_ERR, "unmap failed.\n");
pthread_mutex_unlock(&hash_lock);
return CVI_ERR_VB_ILLEGAL_PARAM;
}
hashmapRemove(vbMmapHash, (void *)(uintptr_t)Pool);
free(pstVbPool);
pthread_mutex_unlock(&hash_lock);
if (hashmapSize(vbMmapHash) == 0) {
hashmapFree(vbMmapHash);
vbMmapHash = NULL;
pthread_mutex_destroy(&hash_lock);
}
return CVI_SUCCESS;
}
/* CVI_VB_GetBlockVirAddr - to get virtual-address of the Block
*
* @param Pool: pool id
* @param Block: block id
* @param ppVirAddr: virtual-address of the Block, cached if pool create with VB_REMAP_MODE_CACHED
* @return CVI_SUCCESS if success; others if fail
*/
CVI_S32 CVI_VB_GetBlockVirAddr(VB_POOL Pool, VB_BLK Block, void **ppVirAddr)
{
VB_POOL poolId;
CVI_U64 phyAddr;
VB_POOL_S *pstVbPool = NULL;
MOD_CHECK_NULL_PTR(CVI_ID_VB, ppVirAddr);
if (vbMmapHash == NULL) {
CVI_TRACE_VB(CVI_DBG_ERR, "not mmap yet.\n");
return CVI_ERR_VB_NOTREADY;
}
pthread_mutex_lock(&hash_lock);
pstVbPool = hashmapGet(vbMmapHash, (void *)(uintptr_t)Pool);
if (pstVbPool == NULL) {
CVI_TRACE_VB(CVI_DBG_ERR, "not mmap yet.\n");
pthread_mutex_unlock(&hash_lock);
return CVI_ERR_VB_NOTREADY;
}
pthread_mutex_unlock(&hash_lock);
poolId = CVI_VB_Handle2PoolId(Block);
if (poolId != Pool) {
CVI_TRACE_VB(CVI_DBG_ERR, "Blk's Pool(%d) isn't given one(%d).\n", poolId, Pool);
return CVI_ERR_VB_ILLEGAL_PARAM;
}
phyAddr = CVI_VB_Handle2PhysAddr(Block);
if (!phyAddr) {
CVI_TRACE_VB(CVI_DBG_ERR, "phyAddr = 0.\n");
return CVI_ERR_VB_ILLEGAL_PARAM;
}
*ppVirAddr = pstVbPool->vmemBase + (phyAddr - pstVbPool->memBase);
return CVI_SUCCESS;
}
CVI_VOID CVI_VB_PrintPool(VB_POOL Pool)
{
CVI_S32 s32Ret, fd;
fd = get_base_fd();
if (fd == -1) {
CVI_TRACE_VB(CVI_DBG_ERR, "get_base_fd failed.\n");
return;
}
s32Ret = vb_ioctl_print_pool(fd, Pool);
if (s32Ret != CVI_SUCCESS)
CVI_TRACE_VB(CVI_DBG_ERR, "vb_ioctl_print_pool fail, ret(%d)\n", s32Ret);
}

View File

@@ -0,0 +1,90 @@
/*
** read/write phy addr in userspace
** open /dev/mem
** taiqiang.cao@bitmain.com
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <unistd.h>
#include <errno.h>
#include <termios.h>
#include <signal.h>
#include <fcntl.h>
#include <ctype.h>
#include <inttypes.h>
#include "devmem.h"
int devm_open(void)
{
int fd;
fd = open("/dev/mem", O_RDWR | O_SYNC);
if (fd == -1) {
printf("cannot open '/dev/mem'\n");
goto open_err;
}
return fd;
open_err:
return -1;
}
int devm_open_cached(void)
{
int fd;
fd = open("/dev/mem", O_RDWR);
if (fd == -1) {
printf("cannot open '/dev/mem'\n");
goto open_err;
}
return fd;
open_err:
return -1;
}
void devm_close(int fd)
{
if (fd)
close(fd);
}
void *devm_map(int fd, uint64_t phy_addr, size_t len)
{
off_t offset;
void *map_base;
uint32_t padding;
offset = phy_addr & ~(sysconf(_SC_PAGE_SIZE) - 1);
padding = phy_addr - offset;
map_base = mmap(NULL, len + padding, PROT_READ | PROT_WRITE,
MAP_SHARED, fd, offset);
if (map_base == MAP_FAILED) {
perror("mmap failed\n");
printf("phy_addr = %#"PRIx64", length = %zu\t, mapped memory length = %zu\t, pa_offset = %#"PRIx64"\n"
, phy_addr, len, len + padding, (intmax_t)offset);
goto mmap_err;
}
return map_base + padding;
mmap_err:
return NULL;
}
void devm_unmap(void *virt_addr, size_t len)
{
uint64_t addr;
/* page align */
addr = (((uint64_t)(uintptr_t)virt_addr) & ~(sysconf(_SC_PAGE_SIZE) - 1));
munmap((void *)(uintptr_t)addr, len + (unsigned long) virt_addr - addr);
}

View File

@@ -0,0 +1,362 @@
/*
* Copyright (C) 2007 The Android Open Source Project
*
* 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 "hashmap.h"
#include <assert.h>
#include <errno.h>
#include <pthread.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include <sys/types.h>
Hashmap *hashmapCreate(size_t initialCapacity, int (*hash)(void *key), bool (*equals)(void *keyA, void *keyB))
{
assert(hash != NULL);
assert(equals != NULL);
Hashmap *map = malloc(sizeof(Hashmap));
// 0.75 load factor.
size_t minimumBucketCount = initialCapacity * 4 / 3;
if (map == NULL) {
return NULL;
}
map->bucketCount = 1;
while (map->bucketCount <= minimumBucketCount) {
// Bucket count must be power of 2.
map->bucketCount <<= 1;
}
map->buckets = calloc(map->bucketCount, sizeof(Entry *));
if (map->buckets == NULL) {
free(map);
return NULL;
}
map->size = 0;
map->hash = hash;
map->equals = equals;
pthread_mutex_init(&map->lock, NULL);
return map;
}
/**
* Hashes the given key.
*/
#ifdef __clang__
__attribute__((no_sanitize("integer")))
#endif
static inline int hashKey(Hashmap *map, void *key)
{
int h = map->hash(key);
// We apply this secondary hashing discovered by Doug Lea to defend
// against bad hashes.
h += ~(h << 9);
h ^= (((unsigned int)h) >> 14);
h += (h << 4);
h ^= (((unsigned int)h) >> 10);
return h;
}
size_t hashmapSize(Hashmap *map)
{
return map->size;
}
static inline size_t calculateIndex(size_t bucketCount, int hash)
{
return ((size_t)hash) & (bucketCount - 1);
}
static void expandIfNecessary(Hashmap *map)
{
// If the load factor exceeds 0.75...
if (map->size > (map->bucketCount * 3 / 4)) {
// Start off with a 0.33 load factor.
size_t newBucketCount = map->bucketCount << 1;
Entry **newBuckets = calloc(newBucketCount, sizeof(Entry *));
if (newBuckets == NULL) {
// Abort expansion.
return;
}
// Move over existing entries.
size_t i;
for (i = 0; i < map->bucketCount; i++) {
Entry *entry = map->buckets[i];
while (entry != NULL) {
Entry *next = entry->next;
size_t index = calculateIndex(newBucketCount, entry->hash);
entry->next = newBuckets[index];
newBuckets[index] = entry;
entry = next;
}
}
// Copy over internals.
free(map->buckets);
map->buckets = newBuckets;
map->bucketCount = newBucketCount;
}
}
void hashmapLock(Hashmap *map)
{
pthread_mutex_lock(&map->lock);
}
void hashmapUnlock(Hashmap *map)
{
pthread_mutex_unlock(&map->lock);
}
void hashmapFree(Hashmap *map)
{
size_t i;
for (i = 0; i < map->bucketCount; i++) {
Entry *entry = map->buckets[i];
while (entry != NULL) {
Entry *next = entry->next;
free(entry);
entry = next;
}
}
free(map->buckets);
pthread_mutex_destroy(&map->lock);
free(map);
}
#ifdef __clang__
__attribute__((no_sanitize("integer")))
#endif
/* FIXME: relies on signed integer overflow, which is undefined behavior */
int hashmapHash(void *key, size_t keySize)
{
int h = keySize;
char *data = (char *)key;
size_t i;
for (i = 0; i < keySize; i++) {
h = h * 31 + *data;
data++;
}
return h;
}
static Entry *createEntry(void *key, int hash, void *value)
{
Entry *entry = malloc(sizeof(Entry));
if (entry == NULL) {
return NULL;
}
entry->key = key;
entry->hash = hash;
entry->value = value;
entry->next = NULL;
return entry;
}
static inline bool equalKeys(void *keyA, int hashA, void *keyB, int hashB, bool (*equals)(void *, void *))
{
if (keyA == keyB)
return true;
if (hashA != hashB)
return false;
return equals(keyA, keyB);
}
void *hashmapPut(Hashmap *map, void *key, void *value)
{
int hash = hashKey(map, key);
size_t index = calculateIndex(map->bucketCount, hash);
Entry **p = &(map->buckets[index]);
while (true) {
Entry *current = *p;
// Add a new entry.
if (current == NULL) {
*p = createEntry(key, hash, value);
if (*p == NULL) {
errno = ENOMEM;
return NULL;
}
map->size++;
expandIfNecessary(map);
return NULL;
}
// Replace existing entry.
if (equalKeys(current->key, current->hash, key, hash, map->equals)) {
void *oldValue = current->value;
current->value = value;
return oldValue;
}
// Move to next entry.
p = &current->next;
}
}
void *hashmapGet(Hashmap *map, void *key)
{
int hash = hashKey(map, key);
size_t index = calculateIndex(map->bucketCount, hash);
Entry *entry = map->buckets[index];
while (entry != NULL) {
if (equalKeys(entry->key, entry->hash, key, hash, map->equals)) {
return entry->value;
}
entry = entry->next;
}
return NULL;
}
bool hashmapContainsKey(Hashmap *map, void *key)
{
int hash = hashKey(map, key);
size_t index = calculateIndex(map->bucketCount, hash);
Entry *entry = map->buckets[index];
while (entry != NULL) {
if (equalKeys(entry->key, entry->hash, key, hash, map->equals)) {
return true;
}
entry = entry->next;
}
return false;
}
void *hashmapMemoize(Hashmap *map, void *key, void *(*initialValue)(void *key, void *context), void *context)
{
int hash = hashKey(map, key);
size_t index = calculateIndex(map->bucketCount, hash);
Entry **p = &(map->buckets[index]);
while (true) {
Entry *current = *p;
// Add a new entry.
if (current == NULL) {
*p = createEntry(key, hash, NULL);
if (*p == NULL) {
errno = ENOMEM;
return NULL;
}
void *value = initialValue(key, context);
(*p)->value = value;
map->size++;
expandIfNecessary(map);
return value;
}
// Return existing value.
if (equalKeys(current->key, current->hash, key, hash, map->equals)) {
return current->value;
}
// Move to next entry.
p = &current->next;
}
}
void *hashmapRemove(Hashmap *map, void *key)
{
int hash = hashKey(map, key);
size_t index = calculateIndex(map->bucketCount, hash);
// Pointer to the current entry.
Entry **p = &(map->buckets[index]);
Entry *current;
while ((current = *p) != NULL) {
if (equalKeys(current->key, current->hash, key, hash, map->equals)) {
void *value = current->value;
*p = current->next;
free(current);
map->size--;
return value;
}
p = &current->next;
}
return NULL;
}
void hashmapForEach(Hashmap *map, bool (*callback)(void *key, void *value, void *context), void *context)
{
size_t i;
for (i = 0; i < map->bucketCount; i++) {
Entry *entry = map->buckets[i];
while (entry != NULL) {
Entry *next = entry->next;
if (!callback(entry->key, entry->value, context)) {
return;
}
entry = next;
}
}
}
size_t hashmapCurrentCapacity(Hashmap *map)
{
size_t bucketCount = map->bucketCount;
return bucketCount * 3 / 4;
}
size_t hashmapCountCollisions(Hashmap *map)
{
size_t collisions = 0;
size_t i;
for (i = 0; i < map->bucketCount; i++) {
Entry *entry = map->buckets[i];
while (entry != NULL) {
if (entry->next != NULL) {
collisions++;
}
entry = entry->next;
}
}
return collisions;
}
int hashmapIntHash(void *key)
{
// Return the key value itself.
return *((int *)key);
}
bool hashmapIntEquals(void *keyA, void *keyB)
{
int a = *((int *)keyA);
int b = *((int *)keyB);
return a == b;
}

View File

@@ -0,0 +1,205 @@
/***************************************************************************
* Copyright (C) CVITEK, Inc - All Rights Reserved
* Unauthorized copying of this file, via any medium is strictly prohibited
* Proprietary and confidential
* Written by Jammy Huang <jammy.huang@wisecore.com.tw>, Nov. 2019
**************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <stdbool.h>
#include <errno.h>
#include <linux/types.h>
#include <linux/i2c.h>
#include <linux/i2c-dev.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <devmem.h>
#include <linux/cvi_common.h>
int i2c_file = -1;
int i2c_slave_addr;
int i2cInit(uint8_t i2c_bus, uint8_t slave_addr)
{
#define FILENAME_SIZE 12
char filename[FILENAME_SIZE];
char writeSize = 0;
writeSize = snprintf(filename, FILENAME_SIZE, "/dev/i2c-%d", i2c_bus);
if (writeSize > FILENAME_SIZE) {
perror("Please enlarge the space of filename");
}
i2c_file = open(filename, O_RDWR);
if (i2c_file < 0) {
/* ERROR HANDLING: you can check errno to see what went wrong */
perror("Failed to open the i2c bus");
return -1;
}
i2c_slave_addr = slave_addr;
return 0;
}
void i2cExit(void)
{
close(i2c_file);
}
int i2cRead(uint16_t addr, unsigned int addr_nbytes, uint8_t *buffer,
unsigned int data_nbytes)
{
if (addr_nbytes > 2) {
printf("i2c addr length at most 2.\n");
return -1;
}
uint8_t tx[2];
if (addr_nbytes == 2) {
tx[0] = addr >> 8;
tx[1] = addr & 0xff;
} else {
tx[0] = addr & 0xff;
}
struct i2c_msg messages[] = {
{
.addr = i2c_slave_addr,
.flags = 0,
.buf = tx,
.len = addr_nbytes,
},
{
.addr = i2c_slave_addr,
.flags = I2C_M_RD | I2C_M_NOSTART,
.buf = buffer,
.len = data_nbytes,
},
};
struct i2c_rdwr_ioctl_data payload = {
.msgs = messages,
.nmsgs = ARRAY_SIZE(messages),
};
if (ioctl(i2c_file, I2C_RDWR, &payload) < 0) {
/* ERROR HANDLING: i2c transaction failed */
printf("Failed to read from the i2c bus.\n");
return -1;
}
return 0;
}
int i2cWrite(uint16_t addr, unsigned int addr_nbytes, uint8_t *buffer,
unsigned int data_nbytes)
{
if (addr_nbytes > 2) {
printf("i2c addr length at most 2.\n");
return -1;
}
uint16_t len = addr_nbytes + data_nbytes;
uint8_t *tx = malloc(len);
if (addr_nbytes == 2) {
tx[0] = addr >> 8;
tx[1] = addr & 0xff;
memcpy(&tx[2], buffer, data_nbytes);
} else {
tx[0] = addr & 0xff;
memcpy(&tx[1], buffer, data_nbytes);
}
struct i2c_msg messages[] = {
{
.addr = i2c_slave_addr,
.flags = 0,
.buf = tx,
.len = len,
},
};
struct i2c_rdwr_ioctl_data payload = {
.msgs = messages,
.nmsgs = ARRAY_SIZE(messages),
};
if (ioctl(i2c_file, I2C_RDWR, &payload) < 0) {
/* ERROR HANDLING: i2c transaction failed */
printf("Failed to write to the i2c bus.\n");
free(tx);
return -1;
}
free(tx);
return 0;
}
// TODO: refine
#define ISP_BASE_ADDR 0x0A000000
#define ISP_REG_RANGE 0x80000
static void *reg_base;
static int devm_fd = -1;
int regInit(void)
{
if (devm_fd != -1)
return -EMFILE;
devm_fd = devm_open();
if (devm_fd < 0)
return -1;
reg_base = devm_map(devm_fd, ISP_BASE_ADDR, ISP_REG_RANGE);
return 0;
}
int regExit(void)
{
if (reg_base != 0)
devm_unmap(reg_base, ISP_REG_RANGE);
if (devm_fd)
devm_close(devm_fd);
devm_fd = -1;
return 0;
}
uint32_t regRead(uint32_t addr)
{
return *(uint32_t *)(reg_base + addr - ISP_BASE_ADDR);
}
void regWrite(uint32_t addr, uint32_t data)
{
*(uint32_t *)(reg_base + addr - ISP_BASE_ADDR) = data;
}
void regReadBurst(uint32_t addr, uint32_t *buffer, unsigned int ndws)
{
for (unsigned int i = 0; i < ndws; ++i)
buffer[i] = regRead(addr + (i << 2));
}
void regWriteBurst(uint32_t addr, uint32_t *buffer, unsigned int ndws)
{
for (unsigned int i = 0; i < ndws; ++i)
regWrite(addr + (i << 2), buffer[i]);
}
void regWriteMask(uint32_t addr, uint32_t data, uint32_t mask)
{
uint32_t value;
value = regRead(addr) & ~mask;
value |= (data & mask);
regWrite(addr, value);
}

View File

@@ -0,0 +1,124 @@
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h> /* low-level i/o */
#include <unistd.h>
#include <errno.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <linux/cvi_comm_sys.h>
#include "sys_ioctl.h"
#define SYS_S_CTRL_VALUE(_fd, _cfg, _ioctl)\
do {\
struct sys_ext_control ec1;\
memset(&ec1, 0, sizeof(ec1));\
ec1.id = _ioctl;\
ec1.value = _cfg;\
if (ioctl(_fd, SYS_IOC_S_CTRL, &ec1) < 0) {\
fprintf(stderr, "SYS_IOC_S_CTRL - %s NG\n", __func__);\
return -1;\
} \
return 0;\
} while (0)
#define SYS_S_CTRL_VALUE64(_fd, _cfg, _ioctl)\
do {\
struct sys_ext_control ec1;\
memset(&ec1, 0, sizeof(ec1));\
ec1.id = _ioctl;\
ec1.value64 = _cfg;\
if (ioctl(_fd, SYS_IOC_S_CTRL, &ec1) < 0) {\
fprintf(stderr, "SYS_IOC_S_CTRL - %s NG\n", __func__);\
perror("SYS_IOC_S_CTRL\n");\
return -1;\
} \
return 0;\
} while (0)
#define SYS_S_CTRL_PTR(_fd, _cfg, _ioctl)\
do {\
struct sys_ext_control ec1;\
memset(&ec1, 0, sizeof(ec1));\
ec1.id = _ioctl;\
ec1.ptr = (void *)_cfg;\
if (ioctl(_fd, SYS_IOC_S_CTRL, &ec1) < 0) {\
fprintf(stderr, "SYS_IOC_S_CTRL - %s NG\n", __func__);\
perror("SYS_IOC_S_CTRL\n");\
return -1;\
} \
return 0;\
} while (0)
#define SYS_G_CTRL_VALUE(_fd, _out, _ioctl)\
do {\
struct sys_ext_control ec1;\
memset(&ec1, 0, sizeof(ec1));\
ec1.id = _ioctl;\
ec1.value = 0;\
if (ioctl(_fd, SYS_IOC_G_CTRL, &ec1) < 0) {\
fprintf(stderr, "SYS_IOC_G_CTRL - %s NG\n", __func__);\
perror("SYS_IOC_G_CTRL\n");\
return -1;\
} \
*_out = ec1.value;\
return 0;\
} while (0)
#define SYS_G_CTRL_PTR(_fd, _cfg, _ioctl)\
do {\
struct sys_ext_control ec1;\
memset(&ec1, 0, sizeof(ec1));\
ec1.id = _ioctl;\
ec1.ptr = (void *)_cfg;\
if (ioctl(_fd, SYS_IOC_G_CTRL, &ec1) < 0) {\
fprintf(stderr, "SYS_IOC_G_CTRL - %s NG\n", __func__);\
perror("SYS_IOC_G_CTRL\n");\
return -1;\
} \
return 0;\
} while (0)
int sys_set_vivpssmode(int fd, const VI_VPSS_MODE_S *cfg)
{
SYS_S_CTRL_PTR(fd, cfg, SYS_IOCTL_SET_VIVPSSMODE);
}
int sys_set_vpssmode(int fd, VPSS_MODE_E val)
{
SYS_S_CTRL_VALUE(fd, val, SYS_IOCTL_SET_VPSSMODE);
}
int sys_set_vpssmodeex(int fd, const VPSS_MODE_S *cfg)
{
SYS_S_CTRL_PTR(fd, cfg, SYS_IOCTL_SET_VPSSMODE_EX);
}
int sys_set_sys_init(int fd)
{
SYS_S_CTRL_VALUE(fd, 0, SYS_IOCTL_SET_SYS_INIT);
}
int sys_get_vivpssmode(int fd, const VI_VPSS_MODE_S *cfg)
{
SYS_G_CTRL_PTR(fd, cfg, SYS_IOCTL_GET_VIVPSSMODE);
}
int sys_get_vpssmode(int fd, VPSS_MODE_E *val)
{
SYS_G_CTRL_VALUE(fd, val, SYS_IOCTL_GET_VPSSMODE);
}
int sys_get_vpssmodeex(int fd, const VPSS_MODE_S *cfg)
{
SYS_G_CTRL_PTR(fd, cfg, SYS_IOCTL_GET_VPSSMODE_EX);
}
int sys_get_sys_init(int fd, CVI_U32 *val)
{
SYS_G_CTRL_VALUE(fd, val, SYS_IOCTL_GET_SYS_INIT);
}

View File

@@ -0,0 +1,141 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <pthread.h>
#include <fcntl.h> /* low-level i/o */
#include <unistd.h>
#include <errno.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include "vb_ioctl.h"
#define VB_CTRL_PTR(_fd, _cfg, _ioctl)\
do {\
struct vb_ext_control ec1;\
int ret;\
memset(&ec1, 0, sizeof(ec1));\
ec1.id = _ioctl;\
ec1.ptr = (void *)_cfg;\
ret = ioctl(_fd, IOCTL_VB_CMD, &ec1);\
if (ret < 0)\
fprintf(stderr, "IOCTL_VB_CMD - %s NG\n", __func__);\
return ret;\
} while (0)
#define VB_CTRL_S_VALUE(_fd, _cfg, _ioctl)\
do {\
struct vb_ext_control ec1;\
int ret;\
memset(&ec1, 0, sizeof(ec1));\
ec1.id = _ioctl;\
ec1.value = _cfg;\
ret = ioctl(_fd, IOCTL_VB_CMD, &ec1);\
if (ret < 0)\
fprintf(stderr, "IOCTL_VB_CMD - %s NG\n", __func__);\
return ret;\
} while (0)
#define VB_CTRL_S_VALUE64(_fd, _cfg, _ioctl)\
do {\
struct vb_ext_control ec1;\
int ret;\
memset(&ec1, 0, sizeof(ec1));\
ec1.id = _ioctl;\
ec1.value64 = _cfg;\
ret = ioctl(_fd, IOCTL_VB_CMD, &ec1);\
if (ret < 0)\
fprintf(stderr, "IOCTL_VB_CMD - %s NG\n", __func__);\
return ret;\
} while (0)
#define VB_CTRL_G_VALUE(_fd, _out, _ioctl)\
do {\
struct vb_ext_control ec1;\
int ret;\
memset(&ec1, 0, sizeof(ec1));\
ec1.id = _ioctl;\
ec1.value = 0;\
ret = ioctl(_fd, IOCTL_VB_CMD, &ec1);\
if (ret < 0)\
fprintf(stderr, "IOCTL_VB_CMD - %s NG\n", __func__);\
*_out = ec1.value;\
return ret;\
} while (0)
int vb_ioctl_set_config(int fd, struct cvi_vb_cfg *cfg)
{
VB_CTRL_PTR(fd, cfg, VB_IOCTL_SET_CONFIG);
}
int vb_ioctl_get_config(int fd, struct cvi_vb_cfg *cfg)
{
VB_CTRL_PTR(fd, cfg, VB_IOCTL_GET_CONFIG);
}
int vb_ioctl_init(int fd)
{
VB_CTRL_PTR(fd, NULL, VB_IOCTL_INIT);
}
int vb_ioctl_exit(int fd)
{
VB_CTRL_PTR(fd, NULL, VB_IOCTL_EXIT);
}
int vb_ioctl_create_pool(int fd, struct cvi_vb_pool_cfg *cfg)
{
VB_CTRL_PTR(fd, cfg, VB_IOCTL_CREATE_POOL);
}
int vb_ioctl_create_ex_pool(int fd, struct cvi_vb_pool_ex_cfg *cfg)
{
VB_CTRL_PTR(fd, cfg, VB_IOCTL_CREATE_EX_POOL);
}
int vb_ioctl_destroy_pool(int fd, VB_POOL poolId)
{
VB_CTRL_S_VALUE(fd, poolId, VB_IOCTL_DESTROY_POOL);
}
int vb_ioctl_phys_to_handle(int fd, struct cvi_vb_blk_info *blk_info)
{
VB_CTRL_PTR(fd, blk_info, VB_IOCTL_PHYS_TO_HANDLE);
}
int vb_ioctl_get_blk_info(int fd, struct cvi_vb_blk_info *blk_info)
{
VB_CTRL_PTR(fd, blk_info, VB_IOCTL_GET_BLK_INFO);
}
int vb_ioctl_get_pool_cfg(int fd, struct cvi_vb_pool_cfg *pool_cfg)
{
VB_CTRL_PTR(fd, pool_cfg, VB_IOCTL_GET_POOL_CFG);
}
int vb_ioctl_get_block(int fd, struct cvi_vb_blk_cfg *blk_cfg)
{
VB_CTRL_PTR(fd, blk_cfg, VB_IOCTL_GET_BLOCK);
}
int vb_ioctl_release_block(int fd, VB_BLK blk)
{
VB_CTRL_S_VALUE64(fd, blk, VB_IOCTL_RELEASE_BLOCK);
}
int vb_ioctl_get_pool_max_cnt(int fd, CVI_U32 *vb_max_pools)
{
VB_CTRL_G_VALUE(fd, vb_max_pools, VB_IOCTL_GET_POOL_MAX_CNT);
}
int vb_ioctl_print_pool(int fd, VB_POOL poolId)
{
VB_CTRL_S_VALUE(fd, poolId, VB_IOCTL_PRINT_POOL);
}
int vb_ioctl_unit_test(int fd, CVI_U32 op)
{
VB_CTRL_S_VALUE(fd, op, VB_IOCTL_UNIT_TEST);
}

View File

@@ -0,0 +1,44 @@
SHELL = /bin/bash
ifeq ($(PARAM_FILE), )
PARAM_FILE:=../../Makefile.param
include $(PARAM_FILE)
endif
SDIR = $(PWD)/src
SRCS = $(wildcard $(SDIR)/*.c)
INCS = -I$(MW_INC) -I$(KERNEL_INC) -I$(SYS_INC) -I$(PWD)/include
OBJS = $(SRCS:.c=.o)
DEPS = $(SRCS:.c=.d)
TARGET_A = $(MW_LIB)/libvdec.a
TARGET_SO = $(MW_LIB)/libvdec.so
EXTRA_CFLAGS = $(INCS)
ifeq ($(DEBUG), 1)
EXTRA_CFLAGS += -g -O0
endif
.PHONY : clean all
all : prepare $(TARGET_A) $(TARGET_SO)
$(SDIR)/%.o: $(SDIR)/%.c
@$(CC) $(DEPFLAGS) $(CFLAGS) $(EXTRA_CFLAGS) -o $@ -c $<
@echo [$(notdir $(CC))] $(notdir $@)
$(TARGET_A): $(OBJS)
@$(AR) $(ARFLAGS) $@ $(OBJS)
@echo -e $(YELLOW)[LINK]$(END)[$(notdir $(AR))] $(notdir $@)
$(TARGET_SO): $(OBJS)
@$(LD) $(LDFLAGS) $(LEXTRA_LDFLAGS) -o $@ --start-group $(OBJS) $(LIBS) --end-group
@echo -e $(GREEN)[LINK]$(END)[$(notdir $(LD))] $(notdir $@)
clean:
@rm -f $(OBJS) $(DEPS) $(TARGET_A) $(TARGET_SO)
prepare:
@echo "SDK_VER = ${SDK_VER}"
@head=`git rev-parse --verify --short HEAD`
@date=`git show -s --format=%cd --date=short ${head}`
-include $(DEPS)

View File

@@ -0,0 +1,272 @@
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include "devmem.h"
#include "cvi_vdec.h"
#include <linux/cvi_vc_drv_ioctl.h>
#define UNUSED(x) ((void)(x))
vdec_dbg vdecDbg;
static CVI_S32 s32DevmemFd = -1;
static CVI_U32 u32ChannelCreatedCnt;
typedef struct _VIDEO_FRAME_INFO_EX_S {
const VIDEO_FRAME_INFO_S *pstFrame;
CVI_S32 s32MilliSec;
} VIDEO_FRAME_INFO_EX_S;
typedef struct _VDEC_STREAM_EX_S {
const VDEC_STREAM_S *pstStream;
CVI_S32 s32MilliSec;
} VDEC_STREAM_EX_S;
CVI_S32 s32VdecFd[VDEC_MAX_CHN_NUM] = {0};
CVI_S32 CVI_VDEC_CreateChn(VDEC_CHN VdChn, const VDEC_CHN_ATTR_S *pstAttr)
{
CVI_S32 s32Ret = CVI_FAILURE;
CVI_CHAR devName[255];
if (s32DevmemFd == -1) {
s32DevmemFd = devm_open_cached();
if (s32DevmemFd < 0)
return CVI_FAILURE;
}
if (s32VdecFd[VdChn] == 0) {
sprintf(devName, "/dev/%s%d", CVI_VC_DRV_DECODER_DEV_NAME, VdChn);
s32VdecFd[VdChn] = open(devName, O_RDWR | O_DSYNC | O_CLOEXEC);
CVI_VDEC_TRACE("open device (%s) fd: %d\n", devName, s32VdecFd[VdChn]);
}
if (s32VdecFd[VdChn] > 0) {
s32Ret = ioctl(s32VdecFd[VdChn], CVI_VC_VDEC_CREATE_CHN, pstAttr);
if (s32Ret != CVI_SUCCESS) {
CVI_VDEC_ERR("ioctl CVI_VC_VDEC_CREATE_CHN fail with %d\n", s32Ret);
return s32Ret;
}
u32ChannelCreatedCnt += 1;
} else {
CVI_VDEC_ERR("fail to open device %s\n", devName);
s32Ret = CVI_FAILURE;
}
return s32Ret;
}
CVI_S32 CVI_VDEC_DestroyChn(VDEC_CHN VdChn)
{
CVI_S32 s32Ret = CVI_SUCCESS;
if (s32VdecFd[VdChn] > 0) {
s32Ret = ioctl(s32VdecFd[VdChn], CVI_VC_VDEC_DESTROY_CHN, NULL);
if (s32Ret != CVI_SUCCESS) {
CVI_VDEC_ERR("ioctl CVI_VC_VDEC_DESTROY_CHN fail with %d\n", s32Ret);
return s32Ret;
}
close(s32VdecFd[VdChn]);
s32VdecFd[VdChn] = 0;
}
u32ChannelCreatedCnt -= 1;
if (u32ChannelCreatedCnt == 0) {
devm_close(s32DevmemFd);
s32DevmemFd = -1;
}
return s32Ret;
}
CVI_S32 CVI_VDEC_GetChnAttr(VDEC_CHN VdChn, VDEC_CHN_ATTR_S *pstAttr)
{
if (s32VdecFd[VdChn] > 0) {
return ioctl(s32VdecFd[VdChn], CVI_VC_VDEC_GET_CHN_ATTR, pstAttr);
}
return CVI_FAILURE;
}
CVI_S32 CVI_VDEC_SetChnAttr(VDEC_CHN VdChn, const VDEC_CHN_ATTR_S *pstAttr)
{
if (s32VdecFd[VdChn] > 0) {
return ioctl(s32VdecFd[VdChn], CVI_VC_VDEC_SET_CHN_ATTR, pstAttr);
}
return CVI_FAILURE;
}
CVI_S32 CVI_VDEC_StartRecvStream(VDEC_CHN VdChn)
{
if (s32VdecFd[VdChn] > 0) {
return ioctl(s32VdecFd[VdChn], CVI_VC_VDEC_START_RECV_STREAM, NULL);
}
return CVI_FAILURE;
}
CVI_S32 CVI_VDEC_StopRecvStream(VDEC_CHN VdChn)
{
if (s32VdecFd[VdChn] > 0) {
return ioctl(s32VdecFd[VdChn], CVI_VC_VDEC_STOP_RECV_STREAM, NULL);
}
return CVI_FAILURE;
}
CVI_S32 CVI_VDEC_QueryStatus(VDEC_CHN VdChn, VDEC_CHN_STATUS_S *pstStatus)
{
if (s32VdecFd[VdChn] > 0) {
return ioctl(s32VdecFd[VdChn], CVI_VC_VDEC_QUERY_STATUS, pstStatus);
}
return CVI_FAILURE;
}
CVI_S32 CVI_VDEC_GetFd(VDEC_CHN VdChn)
{
if (s32VdecFd[VdChn] <= 0) {
CVI_CHAR devName[255];
sprintf(devName, "/dev/%s%d", CVI_VC_DRV_DECODER_DEV_NAME, VdChn);
s32VdecFd[VdChn] = open(devName, O_RDWR | O_DSYNC | O_CLOEXEC);
CVI_VDEC_TRACE("open device (%s) fd: %d\n", devName, s32VdecFd[VdChn]);
}
return s32VdecFd[VdChn];
}
CVI_S32 CVI_VDEC_CloseFd(VDEC_CHN VdChn)
{
// close fd in destroy channel
UNUSED(VdChn);
return CVI_SUCCESS;
}
CVI_S32 CVI_VDEC_ResetChn(VDEC_CHN VdChn)
{
if (s32VdecFd[VdChn] > 0) {
return ioctl(s32VdecFd[VdChn], CVI_VC_VDEC_RESET_CHN);
}
return CVI_FAILURE;
}
CVI_S32 CVI_VDEC_SetChnParam(VDEC_CHN VdChn, const VDEC_CHN_PARAM_S *pstParam)
{
if (s32VdecFd[VdChn] > 0) {
return ioctl(s32VdecFd[VdChn], CVI_VC_VDEC_SET_CHN_PARAM, pstParam);
}
return CVI_FAILURE;
}
CVI_S32 CVI_VDEC_GetChnParam(VDEC_CHN VdChn, VDEC_CHN_PARAM_S *pstParam)
{
if (s32VdecFd[VdChn] > 0) {
return ioctl(s32VdecFd[VdChn], CVI_VC_VDEC_GET_CHN_PARAM, pstParam);
}
return CVI_FAILURE;
}
/* s32MilliSec: -1 is block,0 is no block,other positive number is timeout */
CVI_S32 CVI_VDEC_SendStream(VDEC_CHN VdChn, const VDEC_STREAM_S *pstStream, CVI_S32 s32MilliSec)
{
if (s32VdecFd[VdChn] > 0) {
VDEC_STREAM_EX_S stStreamEx, *pstStreamEx = &stStreamEx;
pstStreamEx->pstStream = pstStream;
pstStreamEx->s32MilliSec = s32MilliSec;
return ioctl(s32VdecFd[VdChn], CVI_VC_VDEC_SEND_STREAM, pstStreamEx);
}
return CVI_FAILURE;
}
CVI_S32 CVI_VDEC_GetFrame(VDEC_CHN VdChn, VIDEO_FRAME_INFO_S *pstFrameInfo, CVI_S32 s32MilliSec)
{
if (s32VdecFd[VdChn] > 0) {
CVI_S32 s32Ret = CVI_SUCCESS;
VIDEO_FRAME_INFO_EX_S stFrameInfoEx, *pstFrameInfoEx = &stFrameInfoEx;
pstFrameInfoEx->pstFrame = pstFrameInfo;
pstFrameInfoEx->s32MilliSec = s32MilliSec;
s32Ret = ioctl(s32VdecFd[VdChn], CVI_VC_VDEC_GET_FRAME, pstFrameInfoEx);
if (s32Ret == CVI_SUCCESS) {
int i = 0;
for (i = 0; i < 3; i++) {
if (pstFrameInfo->stVFrame.u64PhyAddr[i] &&
pstFrameInfo->stVFrame.u32Length[i]) {
pstFrameInfo->stVFrame.pu8VirAddr[i] =
devm_map(s32DevmemFd,
pstFrameInfo->stVFrame.u64PhyAddr[i],
pstFrameInfo->stVFrame.u32Length[i]);
}
}
}
return s32Ret;
}
return CVI_FAILURE;
}
CVI_S32 CVI_VDEC_ReleaseFrame(VDEC_CHN VdChn, const VIDEO_FRAME_INFO_S *pstFrameInfo)
{
if (s32VdecFd[VdChn] > 0) {
int i = 0;
for (i = 0; i < 3; i++) {
if (pstFrameInfo->stVFrame.pu8VirAddr[i] && pstFrameInfo->stVFrame.u32Length[i]) {
devm_unmap(pstFrameInfo->stVFrame.pu8VirAddr[i], pstFrameInfo->stVFrame.u32Length[i]);
}
}
return ioctl(s32VdecFd[VdChn], CVI_VC_VDEC_RELEASE_FRAME, pstFrameInfo);
}
return CVI_FAILURE;
}
CVI_S32 CVI_VDEC_AttachVbPool(VDEC_CHN VdChn, const VDEC_CHN_POOL_S *pstPool)
{
if (s32VdecFd[VdChn] > 0) {
return ioctl(s32VdecFd[VdChn], CVI_VC_VDEC_ATTACH_VBPOOL, pstPool);
}
return CVI_FAILURE;
}
CVI_S32 CVI_VDEC_DetachVbPool(VDEC_CHN VdChn)
{
if (s32VdecFd[VdChn] > 0) {
return ioctl(s32VdecFd[VdChn], CVI_VC_VDEC_DETACH_VBPOOL, NULL);
}
return CVI_FAILURE;
}
CVI_S32 CVI_VDEC_SetModParam(const VDEC_MOD_PARAM_S *pstModParam)
{
VDEC_CHN VdChn = 0; // default hard-code
if (s32VdecFd[VdChn] == 0) {
CVI_CHAR devName[255];
sprintf(devName, "/dev/%s%d", CVI_VC_DRV_DECODER_DEV_NAME, VdChn);
s32VdecFd[VdChn] = open(devName, O_RDWR | O_DSYNC | O_CLOEXEC);
if (s32DevmemFd == -1) {
s32DevmemFd = devm_open_cached();
if (s32DevmemFd < 0)
return CVI_FAILURE;
}
}
if (s32VdecFd[VdChn] > 0) {
return ioctl(s32VdecFd[0], CVI_VC_VDEC_SET_MOD_PARAM, pstModParam);
}
return CVI_FAILURE;
}
CVI_S32 CVI_VDEC_GetModParam(VDEC_MOD_PARAM_S *pstModParam)
{
VDEC_CHN VdChn = 0; // default hard-code
if (s32VdecFd[VdChn] > 0) {
return ioctl(s32VdecFd[VdChn], CVI_VC_VDEC_GET_MOD_PARAM, pstModParam);
}
return CVI_FAILURE;
}

View File

@@ -0,0 +1,59 @@
SHELL = /bin/bash
ifeq ($(PARAM_FILE), )
PARAM_FILE:=../../Makefile.param
include $(PARAM_FILE)
endif
SDIR = src
SRCS = $(wildcard $(SDIR)/*.c)
INCS = -I$(MW_INC) -I$(KERNEL_INC) -I$(SYS_INC) -Iinclude
OBJS = $(SRCS:.c=.o)
DEPS = $(SRCS:.c=.d)
TARGET_A = $(MW_LIB)/libvenc.a
TARGET_SO = $(MW_LIB)/libvenc.so
ifeq ($(MULTI_PROCESS_SUPPORT), 1)
DEFS += -DRPC_MULTI_PROCESS
endif
EXTRA_CFLAGS = $(INCS) $(DEFS)
ifeq ($(DEBUG), 1)
EXTRA_CFLAGS += -g -O0
endif
ldflags-y = -lsys
ifeq ($(CLI_DEBUG_SUPPORT), 1)
DEFS += -DCLI_DEBUG_SUPPORT
ldflags-y += -lcli
LIB_A_FLAGS += $(MW_3RD_LIB)/libcli.a
LIB_SO_FLAGS += $(MW_3RD_LIB)/libcli.so
endif
TMP_INC = $(MW_INC)/cvi_jpg* $(MW_INC)/cvi_h265*
.PHONY : clean all
all : prepare $(TARGET_A) $(TARGET_SO)
$(SDIR)/%.o: $(SDIR)/%.c
@$(CC) $(DEPFLAGS) $(CFLAGS) $(EXTRA_CFLAGS) -o $@ -c $<
@echo [$(notdir $(CC))] $(notdir $@)
$(TARGET_A): $(OBJS) $(LIB_A_FLAGS)
@$(AR) $(ARFLAGS) $@ $(OBJS)
@echo -e $(YELLOW)[LINK]$(END)[$(notdir $(AR))] $(notdir $@)
$(TARGET_SO): $(OBJS) $(LIB_SO_FLAGS)
@$(LD) $(LDFLAGS) $(ldflags-y) -o $@ --start-group $(OBJS) --end-group
@echo -e $(GREEN)[LINK]$(END)[$(notdir $(LD))] $(notdir $@)
clean:
@rm -f $(OBJS) $(DEPS) $(TARGET_A) $(TARGET_SO)
prepare:
@echo "SDK_VER = ${SDK_VER}"
@head=`git rev-parse --verify --short HEAD`
@date=`git show -s --format=%cd --date=short ${head}`
-include $(DEPS)

View File

@@ -0,0 +1,695 @@
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <stdlib.h>
#include "devmem.h"
#include "cvi_venc.h"
#include <linux/cvi_vc_drv_ioctl.h>
#define UNUSED(x) ((void)(x))
typedef struct _VENC_STREAM_EX_S {
VENC_STREAM_S *pstStream;
CVI_S32 s32MilliSec;
} VENC_STREAM_EX_S;
typedef struct _VENC_USER_DATA_S {
CVI_U8 *pu8Data;
CVI_U32 u32Len;
} VENC_USER_DATA_S;
typedef struct _VIDEO_FRAME_INFO_EX_S {
const VIDEO_FRAME_INFO_S *pstFrame;
CVI_S32 s32MilliSec;
} VIDEO_FRAME_INFO_EX_S;
typedef struct _USER_FRAME_INFO_EX_S {
const USER_FRAME_INFO_S *pstUserFrame;
CVI_S32 s32MilliSec;
} USER_FRAME_INFO_EX_S;
#define CVI_VENC_NO_INPUT -10
#define CVI_VENC_INPUT_ERR -11
#define DUMP_YUV "dump_src.yuv"
#define DUMP_BS "dump_bs.bin"
venc_dbg vencDbg;
static CVI_S32 s32DevmemFd = -1;
static CVI_U32 u32ChannelCreatedCnt;
CVI_S32 s32VencFd[VENC_MAX_CHN_NUM] = {0};
CVI_U8 *pStreamPackArray[VENC_MAX_CHN_NUM][8] = {NULL};
static CVI_S32 cviGetEnv(CVI_CHAR *env, CVI_CHAR *fmt, CVI_VOID *param)
{
CVI_CHAR *debugEnv;
CVI_S32 val = CVI_VENC_NO_INPUT;
debugEnv = getenv(env);
if (debugEnv) {
if (strcmp(fmt, "%s") == 0) {
strcpy(param, debugEnv);
} else {
if (sscanf(debugEnv, fmt, &val) != 1)
return CVI_VENC_INPUT_ERR;
CVI_VENC_TRACE("%s = 0x%X\n", env, val);
}
}
return val;
}
static CVI_VOID cviChangeMask(CVI_S32 frameIdx)
{
venc_dbg *pDbg = &vencDbg;
pDbg->currMask = pDbg->dbgMask;
if (pDbg->startFn >= 0) {
if (frameIdx >= pDbg->startFn &&
frameIdx <= pDbg->endFn)
pDbg->currMask = pDbg->dbgMask;
else
pDbg->currMask = CVI_VENC_MASK_ERR;
}
CVI_VENC_TRACE("currMask = 0x%X\n", pDbg->currMask);
}
CVI_VOID cviGetMask(void)
{
venc_dbg *pDbg = &vencDbg;
CVI_VENC_TRACE("\n");
memset(pDbg, 0, sizeof(venc_dbg));
pDbg->dbgMask = cviGetEnv("venc_mask", "0x%x", NULL);
if (pDbg->dbgMask == CVI_VENC_NO_INPUT ||
pDbg->dbgMask == CVI_VENC_INPUT_ERR)
pDbg->dbgMask = CVI_VENC_MASK_ERR;
else
pDbg->dbgMask |= CVI_VENC_MASK_ERR;
pDbg->currMask = pDbg->dbgMask;
pDbg->startFn = cviGetEnv("venc_sfn", "%d", NULL);
pDbg->endFn = cviGetEnv("venc_efn", "%d", NULL);
cviGetEnv("venc_dir", "%s", pDbg->dbgDir);
cviChangeMask(0);
}
static CVI_S32 openDevice(VENC_CHN VeChn)
{
if (s32VencFd[VeChn] <= 0) {
CVI_CHAR devName[255];
sprintf(devName, "/dev/%s%d", CVI_VC_DRV_ENCODER_DEV_NAME, VeChn);
s32VencFd[VeChn] = open(devName, O_RDWR | O_DSYNC | O_CLOEXEC);
if (s32VencFd[VeChn] <= 0) {
CVI_VENC_ERR("open device (%s) fail\n", devName);
return CVI_FAILURE;
}
CVI_VENC_TRACE("open device (%s) fd: %d\n", devName, s32VencFd[VeChn]);
}
if (s32DevmemFd == -1) {
s32DevmemFd = devm_open_cached();
if (s32DevmemFd < 0) {
CVI_VENC_ERR("devm_open fail\n");
return CVI_FAILURE;
}
}
return CVI_SUCCESS;
}
CVI_S32 CVI_VENC_CreateChn(VENC_CHN VeChn, const VENC_CHN_ATTR_S *pstAttr)
{
CVI_S32 s32Ret = CVI_FAILURE;
CVI_CHAR devName[255];
if (openDevice(VeChn) != CVI_SUCCESS) {
CVI_VENC_ERR("openDevice fail\n");
return s32Ret;
}
if (s32VencFd[VeChn] > 0) {
s32Ret = ioctl(s32VencFd[VeChn], CVI_VC_VENC_CREATE_CHN, pstAttr);
if (s32Ret != CVI_SUCCESS) {
CVI_VENC_ERR("ioctl CVI_VC_VENC_CREATE_CHN fail with %d\n", s32Ret);
return s32Ret;
}
u32ChannelCreatedCnt += 1;
} else {
CVI_VENC_ERR("fail to open device %s\n", devName);
s32Ret = CVI_FAILURE;
}
return s32Ret;
}
CVI_S32 CVI_VENC_DestroyChn(VENC_CHN VeChn)
{
CVI_S32 s32Ret = CVI_SUCCESS;
if (s32VencFd[VeChn] > 0) {
s32Ret = ioctl(s32VencFd[VeChn], CVI_VC_VENC_DESTROY_CHN);
if (s32Ret != CVI_SUCCESS) {
CVI_VENC_ERR("ioctl CVI_VC_VENC_DESTROY_CHN fail with %d\n", s32Ret);
return s32Ret;
}
close(s32VencFd[VeChn]);
s32VencFd[VeChn] = 0;
}
u32ChannelCreatedCnt -= 1;
if (u32ChannelCreatedCnt == 0) {
devm_close(s32DevmemFd);
s32DevmemFd = -1;
}
return s32Ret;
}
CVI_S32 CVI_VENC_ResetChn(VENC_CHN VeChn)
{
if (s32VencFd[VeChn] > 0) {
return ioctl(s32VencFd[VeChn], CVI_VC_VENC_RESET_CHN);
}
return CVI_FAILURE;
}
CVI_S32 CVI_VENC_StartRecvFrame(VENC_CHN VeChn, const VENC_RECV_PIC_PARAM_S *pstRecvParam)
{
if (s32VencFd[VeChn] > 0) {
return ioctl(s32VencFd[VeChn], CVI_VC_VENC_START_RECV_FRAME, pstRecvParam);
}
return CVI_FAILURE;
}
CVI_S32 CVI_VENC_StopRecvFrame(VENC_CHN VeChn)
{
if (s32VencFd[VeChn] > 0) {
return ioctl(s32VencFd[VeChn], CVI_VC_VENC_STOP_RECV_FRAME);
}
return CVI_FAILURE;
}
CVI_S32 CVI_VENC_QueryStatus(VENC_CHN VeChn, VENC_CHN_STATUS_S *pstStatus)
{
if (s32VencFd[VeChn] > 0) {
return ioctl(s32VencFd[VeChn], CVI_VC_VENC_QUERY_STATUS, pstStatus);
}
return CVI_FAILURE;
}
CVI_S32 CVI_VENC_SetChnAttr(VENC_CHN VeChn, const VENC_CHN_ATTR_S *pstChnAttr)
{
if (s32VencFd[VeChn] > 0) {
return ioctl(s32VencFd[VeChn], CVI_VC_VENC_SET_CHN_ATTR, pstChnAttr);
}
return CVI_FAILURE;
}
CVI_S32 CVI_VENC_GetChnAttr(VENC_CHN VeChn, VENC_CHN_ATTR_S *pstChnAttr)
{
if (s32VencFd[VeChn] > 0) {
return ioctl(s32VencFd[VeChn], CVI_VC_VENC_GET_CHN_ATTR, pstChnAttr);
}
return CVI_FAILURE;
}
CVI_S32 CVI_VENC_GetStream(VENC_CHN VeChn, VENC_STREAM_S *pstStream, CVI_S32 S32MilliSec)
{
CVI_S32 s32Ret = CVI_SUCCESS;
if (s32VencFd[VeChn] > 0) {
VENC_STREAM_EX_S stStreamEx, *pstStreamEx = &stStreamEx;
pstStreamEx->pstStream = pstStream;
pstStreamEx->s32MilliSec = S32MilliSec;
s32Ret = ioctl(s32VencFd[VeChn], CVI_VC_VENC_GET_STREAM, pstStreamEx);
if (s32Ret == CVI_SUCCESS) {
CVI_U32 i = 0;
VENC_PACK_S *ppack;
for (i = 0; i < pstStreamEx->pstStream->u32PackCount; i++) {
ppack = &pstStreamEx->pstStream->pstPack[i];
if (ppack->u64PhyAddr && ppack->u32Len) {
pStreamPackArray[VeChn][i] = ppack->pu8Addr;
ppack->pu8Addr = devm_map(s32DevmemFd, ppack->u64PhyAddr, ppack->u32Len);
}
}
}
return s32Ret;
}
return CVI_FAILURE;
}
CVI_S32 CVI_VENC_ReleaseStream(VENC_CHN VeChn, VENC_STREAM_S *pstStream)
{
if (s32VencFd[VeChn] > 0) {
CVI_U32 i = 0;
VENC_PACK_S *ppack;
for (i = 0; i < pstStream->u32PackCount; i++) {
ppack = &pstStream->pstPack[i];
if (ppack->u64PhyAddr && ppack->u32Len) {
devm_unmap(ppack->pu8Addr, ppack->u32Len);
ppack->pu8Addr = pStreamPackArray[VeChn][i];
}
}
return ioctl(s32VencFd[VeChn], CVI_VC_VENC_RELEASE_STREAM, pstStream);
}
return CVI_FAILURE;
}
CVI_S32 CVI_VENC_InsertUserData(VENC_CHN VeChn, CVI_U8 *pu8Data, CVI_U32 u32Len)
{
if (s32VencFd[VeChn] > 0) {
VENC_USER_DATA_S stUserData, *pstUserData = &stUserData;
pstUserData->pu8Data = pu8Data;
pstUserData->u32Len = u32Len;
return ioctl(s32VencFd[VeChn], CVI_VC_VENC_INSERT_USERDATA, pstUserData);
}
return CVI_FAILURE;
}
CVI_S32 CVI_VENC_SendFrame(VENC_CHN VeChn, const VIDEO_FRAME_INFO_S *pstFrame, CVI_S32 s32MilliSec)
{
if (s32VencFd[VeChn] > 0) {
VIDEO_FRAME_INFO_EX_S stFrameEx, *pstFrameEx = &stFrameEx;
pstFrameEx->pstFrame = pstFrame;
pstFrameEx->s32MilliSec = s32MilliSec;
return ioctl(s32VencFd[VeChn], CVI_VC_VENC_SEND_FRAME, pstFrameEx);
}
return CVI_FAILURE;
}
CVI_S32 CVI_VENC_SendFrameEx(VENC_CHN VeChn, const USER_FRAME_INFO_S *pstFrame, CVI_S32 s32MilliSec)
{
if (s32VencFd[VeChn] > 0) {
USER_FRAME_INFO_EX_S stUserFrameEx, *pstUserFrameEx = &stUserFrameEx;
pstUserFrameEx->pstUserFrame = pstFrame;
pstUserFrameEx->s32MilliSec = s32MilliSec;
return ioctl(s32VencFd[VeChn], CVI_VC_VENC_SEND_FRAMEEX, pstUserFrameEx);
}
return CVI_FAILURE;
}
CVI_S32 CVI_VENC_RequestIDR(VENC_CHN VeChn, CVI_BOOL bInstant)
{
if (s32VencFd[VeChn] > 0) {
return ioctl(s32VencFd[VeChn], CVI_VC_VENC_REQUEST_IDR, &bInstant);
}
return CVI_FAILURE;
}
CVI_S32 CVI_VENC_GetFd(VENC_CHN VeChn)
{
if (openDevice(VeChn) != CVI_SUCCESS) {
CVI_VENC_ERR("openDevice fail\n");
return CVI_FAILURE;
}
return s32VencFd[VeChn];
}
CVI_S32 CVI_VENC_CloseFd(VENC_CHN VeChn)
{
// close fd in destroy channel
UNUSED(VeChn);
return CVI_SUCCESS;
}
CVI_S32 CVI_VENC_SetRoiAttr(VENC_CHN VeChn, const VENC_ROI_ATTR_S *pstRoiAttr)
{
if (s32VencFd[VeChn] > 0) {
return ioctl(s32VencFd[VeChn], CVI_VC_VENC_SET_ROI_ATTR, pstRoiAttr);
}
return CVI_FAILURE;
}
CVI_S32 CVI_VENC_GetRoiAttr(VENC_CHN VeChn, CVI_U32 u32Index, VENC_ROI_ATTR_S *pstRoiAttr)
{
if (s32VencFd[VeChn] > 0) {
pstRoiAttr->u32Index = u32Index;
return ioctl(s32VencFd[VeChn], CVI_VC_VENC_GET_ROI_ATTR, pstRoiAttr);
}
return CVI_FAILURE;
}
CVI_S32 CVI_VENC_SetH264Trans(VENC_CHN VeChn, const VENC_H264_TRANS_S *pstH264Trans)
{
if (s32VencFd[VeChn] > 0) {
return ioctl(s32VencFd[VeChn], CVI_VC_VENC_SET_H264_TRANS, pstH264Trans);
}
return CVI_FAILURE;
}
CVI_S32 CVI_VENC_GetH264Trans(VENC_CHN VeChn, VENC_H264_TRANS_S *pstH264Trans)
{
if (s32VencFd[VeChn] > 0) {
return ioctl(s32VencFd[VeChn], CVI_VC_VENC_GET_H264_TRANS, pstH264Trans);
}
return CVI_FAILURE;
}
CVI_S32 CVI_VENC_SetH264Entropy(VENC_CHN VeChn, const VENC_H264_ENTROPY_S *pstH264EntropyEnc)
{
if (s32VencFd[VeChn] > 0) {
return ioctl(s32VencFd[VeChn], CVI_VC_VENC_SET_H264_ENTROPY, pstH264EntropyEnc);
}
return CVI_FAILURE;
}
CVI_S32 CVI_VENC_GetH264Entropy(VENC_CHN VeChn, VENC_H264_ENTROPY_S *pstH264EntropyEnc)
{
if (s32VencFd[VeChn] > 0) {
return ioctl(s32VencFd[VeChn], CVI_VC_VENC_GET_H264_ENTROPY, pstH264EntropyEnc);
}
return CVI_FAILURE;
}
CVI_S32 CVI_VENC_SetH264Vui(VENC_CHN VeChn, const VENC_H264_VUI_S *pstH264Vui)
{
if (s32VencFd[VeChn] > 0) {
return ioctl(s32VencFd[VeChn], CVI_VC_VENC_SET_H264_VUI, pstH264Vui);
}
return CVI_FAILURE;
}
CVI_S32 CVI_VENC_GetH264Vui(VENC_CHN VeChn, VENC_H264_VUI_S *pstH264Vui)
{
if (s32VencFd[VeChn] > 0) {
return ioctl(s32VencFd[VeChn], CVI_VC_VENC_GET_H264_VUI, pstH264Vui);
}
return CVI_FAILURE;
}
CVI_S32 CVI_VENC_SetH265Vui(VENC_CHN VeChn, const VENC_H265_VUI_S *pstH265Vui)
{
if (s32VencFd[VeChn] > 0) {
return ioctl(s32VencFd[VeChn], CVI_VC_VENC_SET_H265_VUI, pstH265Vui);
}
return CVI_FAILURE;
}
CVI_S32 CVI_VENC_GetH265Vui(VENC_CHN VeChn, VENC_H265_VUI_S *pstH265Vui)
{
if (s32VencFd[VeChn] > 0) {
return ioctl(s32VencFd[VeChn], CVI_VC_VENC_GET_H265_VUI, pstH265Vui);
}
return CVI_FAILURE;
}
CVI_S32 CVI_VENC_SetJpegParam(VENC_CHN VeChn, const VENC_JPEG_PARAM_S *pstJpegParam)
{
if (s32VencFd[VeChn] > 0) {
return ioctl(s32VencFd[VeChn], CVI_VC_VENC_SET_JPEG_PARAM, pstJpegParam);
}
return CVI_FAILURE;
}
CVI_S32 CVI_VENC_GetJpegParam(VENC_CHN VeChn, VENC_JPEG_PARAM_S *pstJpegParam)
{
if (s32VencFd[VeChn] > 0) {
return ioctl(s32VencFd[VeChn], CVI_VC_VENC_GET_JPEG_PARAM, pstJpegParam);
}
return CVI_FAILURE;
}
CVI_S32 CVI_VENC_GetRcParam(VENC_CHN VeChn, VENC_RC_PARAM_S *pstRcParam)
{
if (s32VencFd[VeChn] > 0) {
return ioctl(s32VencFd[VeChn], CVI_VC_VENC_GET_RC_PARAM, pstRcParam);
}
return CVI_FAILURE;
}
CVI_S32 CVI_VENC_SetRcParam(VENC_CHN VeChn, const VENC_RC_PARAM_S *pstRcParam)
{
if (s32VencFd[VeChn] > 0) {
return ioctl(s32VencFd[VeChn], CVI_VC_VENC_SET_RC_PARAM, pstRcParam);
}
return CVI_FAILURE;
}
CVI_S32 CVI_VENC_SetRefParam(VENC_CHN VeChn, const VENC_REF_PARAM_S *pstRefParam)
{
if (s32VencFd[VeChn] > 0) {
return ioctl(s32VencFd[VeChn], CVI_VC_VENC_SET_REF_PARAM, pstRefParam);
}
return CVI_FAILURE;
}
CVI_S32 CVI_VENC_GetRefParam(VENC_CHN VeChn, VENC_REF_PARAM_S *pstRefParam)
{
if (s32VencFd[VeChn] > 0) {
return ioctl(s32VencFd[VeChn], CVI_VC_VENC_GET_REF_PARAM, pstRefParam);
}
return CVI_FAILURE;
}
CVI_S32 CVI_VENC_SetH265Trans(VENC_CHN VeChn, const VENC_H265_TRANS_S *pstH265Trans)
{
if (s32VencFd[VeChn] > 0) {
return ioctl(s32VencFd[VeChn], CVI_VC_VENC_SET_H265_TRANS, pstH265Trans);
}
return CVI_FAILURE;
}
CVI_S32 CVI_VENC_GetH265Trans(VENC_CHN VeChn, VENC_H265_TRANS_S *pstH265Trans)
{
if (s32VencFd[VeChn] > 0) {
return ioctl(s32VencFd[VeChn], CVI_VC_VENC_GET_H265_TRANS, pstH265Trans);
}
return CVI_FAILURE;
}
CVI_S32 CVI_VENC_SetFrameLostStrategy(VENC_CHN VeChn, const VENC_FRAMELOST_S *pstFrmLostParam)
{
if (s32VencFd[VeChn] > 0) {
return ioctl(s32VencFd[VeChn], CVI_VC_VENC_SET_FRAMELOST_STRATEGY, pstFrmLostParam);
}
return CVI_FAILURE;
}
CVI_S32 CVI_VENC_GetFrameLostStrategy(VENC_CHN VeChn, VENC_FRAMELOST_S *pstFrmLostParam)
{
if (s32VencFd[VeChn] > 0) {
return ioctl(s32VencFd[VeChn], CVI_VC_VENC_GET_FRAMELOST_STRATEGY, pstFrmLostParam);
}
return CVI_FAILURE;
}
CVI_S32 CVI_VENC_SetSuperFrameStrategy(VENC_CHN VeChn, const VENC_SUPERFRAME_CFG_S *pstSuperFrmParam)
{
if (s32VencFd[VeChn] > 0) {
return ioctl(s32VencFd[VeChn], CVI_VC_VENC_SET_SUPERFRAME_STRATEGY, pstSuperFrmParam);
}
return CVI_FAILURE;
}
CVI_S32 CVI_VENC_GetSuperFrameStrategy(VENC_CHN VeChn, VENC_SUPERFRAME_CFG_S *pstSuperFrmParam)
{
if (s32VencFd[VeChn] > 0) {
return ioctl(s32VencFd[VeChn], CVI_VC_VENC_GET_SUPERFRAME_STRATEGY, pstSuperFrmParam);
}
return CVI_FAILURE;
}
CVI_S32 CVI_VENC_SetChnParam(VENC_CHN VeChn, const VENC_CHN_PARAM_S *pstChnParam)
{
if (s32VencFd[VeChn] > 0) {
return ioctl(s32VencFd[VeChn], CVI_VC_VENC_SET_CHN_PARAM, pstChnParam);
}
return CVI_FAILURE;
}
CVI_S32 CVI_VENC_GetChnParam(VENC_CHN VeChn, VENC_CHN_PARAM_S *pstChnParam)
{
if (s32VencFd[VeChn] > 0) {
return ioctl(s32VencFd[VeChn], CVI_VC_VENC_GET_CHN_PARAM, pstChnParam);
}
return CVI_FAILURE;
}
CVI_S32 CVI_VENC_SetModParam(const VENC_PARAM_MOD_S *pstModParam)
{
VENC_CHN VeChn = 0; // default hard-code
if (s32DevmemFd == -1) {
s32DevmemFd = devm_open_cached();
if (s32DevmemFd < 0)
return CVI_FAILURE;
}
if (openDevice(VeChn) != CVI_SUCCESS) {
CVI_VENC_ERR("openDevice fail\n");
return CVI_FAILURE;
}
if (s32VencFd[VeChn] > 0) {
return ioctl(s32VencFd[VeChn], CVI_VC_VENC_SET_MOD_PARAM, pstModParam);
}
return CVI_FAILURE;
}
CVI_S32 CVI_VENC_GetModParam(VENC_PARAM_MOD_S *pstModParam)
{
VENC_CHN VeChn = 0; // default hard-code
if (openDevice(VeChn) != CVI_SUCCESS) {
CVI_VENC_ERR("openDevice fail\n");
return CVI_FAILURE;
}
if (s32VencFd[VeChn] > 0) {
return ioctl(s32VencFd[VeChn], CVI_VC_VENC_GET_MOD_PARAM, pstModParam);
}
return CVI_FAILURE;
}
CVI_S32 CVI_VENC_AttachVbPool(VENC_CHN VeChn, const VENC_CHN_POOL_S *pstPool)
{
if (s32VencFd[VeChn] > 0) {
return ioctl(s32VencFd[VeChn], CVI_VC_VENC_ATTACH_VBPOOL, pstPool);
}
return CVI_FAILURE;
}
CVI_S32 CVI_VENC_DetachVbPool(VENC_CHN VeChn)
{
if (s32VencFd[VeChn] > 0) {
return ioctl(s32VencFd[VeChn], CVI_VC_VENC_DETACH_VBPOOL);
}
return CVI_FAILURE;
}
CVI_S32 CVI_VENC_SetCuPrediction(VENC_CHN VeChn,
const VENC_CU_PREDICTION_S *pstCuPrediction)
{
if (s32VencFd[VeChn] > 0) {
return ioctl(s32VencFd[VeChn], CVI_VC_VENC_SET_CUPREDICTION, pstCuPrediction);
}
return CVI_FAILURE;
}
CVI_S32 CVI_VENC_GetCuPrediction(VENC_CHN VeChn, VENC_CU_PREDICTION_S *pstCuPrediction)
{
if (s32VencFd[VeChn] > 0) {
return ioctl(s32VencFd[VeChn], CVI_VC_VENC_GET_CUPREDICTION, pstCuPrediction);
}
return CVI_FAILURE;
}
CVI_S32 CVI_VENC_CalcFrameParam(VENC_CHN VeChn, VENC_FRAME_PARAM_S *pstFrameParam)
{
if (s32VencFd[VeChn] > 0) {
return ioctl(s32VencFd[VeChn], CVI_VC_VENC_CALC_FRAME_PARAM, pstFrameParam);
}
return CVI_FAILURE;
}
CVI_S32 CVI_VENC_SetFrameParam(VENC_CHN VeChn, const VENC_FRAME_PARAM_S *pstFrameParam)
{
if (s32VencFd[VeChn] > 0) {
return ioctl(s32VencFd[VeChn], CVI_VC_VENC_SET_FRAME_PARAM, pstFrameParam);
}
return CVI_FAILURE;
}
CVI_S32 CVI_VENC_GetFrameParam(VENC_CHN VeChn, VENC_FRAME_PARAM_S *pstFrameParam)
{
if (s32VencFd[VeChn] > 0) {
return ioctl(s32VencFd[VeChn], CVI_VC_VENC_GET_FRAME_PARAM, pstFrameParam);
}
return CVI_FAILURE;
}
CVI_S32 CVI_VENC_SetH264SliceSplit(VENC_CHN VeChn, const VENC_H264_SLICE_SPLIT_S *pstSliceSplit)
{
if (s32VencFd[VeChn] > 0) {
return ioctl(s32VencFd[VeChn], CVI_VC_VENC_SET_H264_SLICE_SPLIT, pstSliceSplit);
}
return CVI_FAILURE;
}
CVI_S32 CVI_VENC_GetH264SliceSplit(VENC_CHN VeChn, VENC_H264_SLICE_SPLIT_S *pstSliceSplit)
{
if (s32VencFd[VeChn] > 0) {
return ioctl(s32VencFd[VeChn], CVI_VC_VENC_GET_H264_SLICE_SPLIT, pstSliceSplit);
}
return CVI_FAILURE;
}
CVI_S32 CVI_VENC_SetH265SliceSplit(VENC_CHN VeChn, const VENC_H265_SLICE_SPLIT_S *pstSliceSplit)
{
if (s32VencFd[VeChn] > 0) {
return ioctl(s32VencFd[VeChn], CVI_VC_VENC_SET_H265_SLICE_SPLIT, pstSliceSplit);
}
return CVI_FAILURE;
}
CVI_S32 CVI_VENC_GetH265SliceSplit(VENC_CHN VeChn, VENC_H265_SLICE_SPLIT_S *pstSliceSplit)
{
if (s32VencFd[VeChn] > 0) {
return ioctl(s32VencFd[VeChn], CVI_VC_VENC_GET_H265_SLICE_SPLIT, pstSliceSplit);
}
return CVI_FAILURE;
}
CVI_S32 CVI_VENC_SetH264Dblk(VENC_CHN VeChn, const VENC_H264_DBLK_S *pstH264Dblk)
{
if (s32VencFd[VeChn] > 0) {
return ioctl(s32VencFd[VeChn], CVI_VC_VENC_SET_H264_Dblk, pstH264Dblk);
}
return CVI_FAILURE;
}
CVI_S32 CVI_VENC_GetH264Dblk(VENC_CHN VeChn, VENC_H264_DBLK_S *pstH264Dblk)
{
if (s32VencFd[VeChn] > 0) {
return ioctl(s32VencFd[VeChn], CVI_VC_VENC_GET_H264_Dblk, pstH264Dblk);
}
return CVI_FAILURE;
}
CVI_S32 CVI_VENC_SetH265Dblk(VENC_CHN VeChn, const VENC_H265_DBLK_S *pstH265Dblk)
{
if (s32VencFd[VeChn] > 0) {
return ioctl(s32VencFd[VeChn], CVI_VC_VENC_SET_H265_Dblk, pstH265Dblk);
}
return CVI_FAILURE;
}
CVI_S32 CVI_VENC_GetH265Dblk(VENC_CHN VeChn, VENC_H265_DBLK_S *pstH265Dblk)
{
if (s32VencFd[VeChn] > 0) {
return ioctl(s32VencFd[VeChn], CVI_VC_VENC_GET_H265_Dblk, pstH265Dblk);
}
return CVI_FAILURE;
}
CVI_S32 CVI_VENC_SetH264IntraPred(VENC_CHN VeChn, const VENC_H264_INTRA_PRED_S *pstH264IntraPred)
{
if (s32VencFd[VeChn] > 0) {
return ioctl(s32VencFd[VeChn], CVI_VC_VENC_SET_H264_INTRA_PRED, pstH264IntraPred);
}
return CVI_FAILURE;
}
CVI_S32 CVI_VENC_GetH264IntraPred(VENC_CHN VeChn, VENC_H264_INTRA_PRED_S *pstH264IntraPred)
{
if (s32VencFd[VeChn] > 0) {
return ioctl(s32VencFd[VeChn], CVI_VC_VENC_GET_H264_INTRA_PRED, pstH264IntraPred);
}
return CVI_FAILURE;
}

View File

@@ -0,0 +1,44 @@
SHELL = /bin/bash
ifeq ($(PARAM_FILE), )
PARAM_FILE:=../../Makefile.param
include $(PARAM_FILE)
endif
SDIR = $(PWD)/src
SRCS = $(wildcard $(SDIR)/*.c)
SRCS := $(filter-out $(SDIR)/cvi_gdc.c, $(SRCS))
SRCS := $(filter-out $(SDIR)/gdc_mesh.c, $(SRCS))
INCS = -I$(MW_INC) -I$(ISP_INC) -I$(KERNEL_INC) -I$(SYS_INC) -I$(BIN_INC) -I./include
OBJS = $(SRCS:.c=.o)
DEPS = $(SRCS:.c=.d)
TARGET_A = $(MW_LIB)/libvpu.a
TARGET_SO = $(MW_LIB)/libvpu.so
EXTRA_CFLAGS = $(INCS)
.PHONY : clean all
all : $(TARGET_A) $(TARGET_SO)
$(SDIR)/gdc_mesh_1822.o: $(SDIR)/gdc_mesh_1822.c
@$(CC) $(DEPFLAGS) $(CFLAGS) $(EXTRA_CFLAGS) -O3 -c $< -o $@
@echo [$(notdir $(CC))] $(notdir $@)
$(SDIR)/%.o: $(SDIR)/%.c
@$(CC) $(DEPFLAGS) $(CFLAGS) $(EXTRA_CFLAGS) -c $< -o $@
@echo [$(notdir $(CC))] $(notdir $@)
$(TARGET_A): $(OBJS)
@$(AR) $(ARFLAGS) $(TARGET_A) $(OBJS)
@echo -e $(YELLOW)[LINK]$(END)[$(notdir $(AR))] $(notdir $(TARGET_A))
$(TARGET_SO): $(OBJS)
@$(LD) $(LDFLAGS) -o $(TARGET_SO) --start-group $(OBJS) --end-group
@echo -e $(GREEN)[LINK]$(END)[$(notdir $(LD))] $(notdir $(TARGET_SO))
clean:
@rm -f $(OBJS) $(DEPS) $(TARGET_A) $(TARGET_SO)
-include $(DEPS)

View File

@@ -0,0 +1,640 @@
#include <errno.h>
#include <pthread.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/prctl.h>
#include <inttypes.h>
#include <unistd.h>
#include <sys/mman.h>
#include "cvi_buffer.h"
#include "cvi_base.h"
#include "cvi_sys.h"
#include "cvi_vb.h"
#include "cvi_gdc.h"
#include "ioctl_vio.h"
#include "gdc_mesh.h"
#define DWA_YUV_BLACK 0x808000
#define DWA_RGB_BLACK 0x0
#define CHECK_GDC_FORMAT(imgIn, imgOut) \
do { \
if (imgIn.stVFrame.enPixelFormat != imgOut.stVFrame.enPixelFormat) { \
CVI_TRACE_GDC(CVI_DBG_ERR, "in/out pixelformat(%d-%d) mismatch\n", \
imgIn.stVFrame.enPixelFormat, imgOut.stVFrame.enPixelFormat); \
return CVI_ERR_GDC_ILLEGAL_PARAM; \
} \
if (!GDC_SUPPORT_FMT(imgIn.stVFrame.enPixelFormat)) { \
CVI_TRACE_GDC(CVI_DBG_ERR, "pixelformat(%d) unsupported\n", imgIn.stVFrame.enPixelFormat); \
return CVI_ERR_GDC_ILLEGAL_PARAM; \
} \
} while (0)
static CVI_S32 gdc_rotation_check_size(ROTATION_E enRotation, const GDC_TASK_ATTR_S *pstTask)
{
if (enRotation > ROTATION_270) {
CVI_TRACE_GDC(CVI_DBG_ERR, "invalid rotation(%d).\n", enRotation);
return CVI_ERR_GDC_ILLEGAL_PARAM;
}
if (enRotation == ROTATION_90 || enRotation == ROTATION_270) {
if (pstTask->stImgOut.stVFrame.u32Width < pstTask->stImgIn.stVFrame.u32Height) {
CVI_TRACE_GDC(CVI_DBG_ERR, "rotation(%d) invalid: 'output width(%d) < input height(%d)'\n",
enRotation, pstTask->stImgOut.stVFrame.u32Width,
pstTask->stImgIn.stVFrame.u32Height);
return CVI_ERR_GDC_ILLEGAL_PARAM;
}
if (pstTask->stImgOut.stVFrame.u32Height < pstTask->stImgIn.stVFrame.u32Width) {
CVI_TRACE_GDC(CVI_DBG_ERR, "rotation(%d) invalid: 'output height(%d) < input width(%d)'\n",
enRotation, pstTask->stImgOut.stVFrame.u32Height,
pstTask->stImgIn.stVFrame.u32Width);
return CVI_ERR_GDC_ILLEGAL_PARAM;
}
} else {
if (pstTask->stImgOut.stVFrame.u32Width < pstTask->stImgIn.stVFrame.u32Width) {
CVI_TRACE_GDC(CVI_DBG_ERR, "rotation(%d) invalid: 'output width(%d) < input width(%d)'\n",
enRotation, pstTask->stImgOut.stVFrame.u32Width,
pstTask->stImgIn.stVFrame.u32Width);
return CVI_ERR_GDC_ILLEGAL_PARAM;
}
if (pstTask->stImgOut.stVFrame.u32Height < pstTask->stImgIn.stVFrame.u32Height) {
CVI_TRACE_GDC(CVI_DBG_ERR, "rotation(%d) invalid: 'output height(%d) < input height(%d)'\n",
enRotation, pstTask->stImgOut.stVFrame.u32Height,
pstTask->stImgIn.stVFrame.u32Height);
return CVI_ERR_GDC_ILLEGAL_PARAM;
}
}
return CVI_SUCCESS;
}
CVI_S32 CVI_GDC_Suspend(void)
{
CVI_TRACE_GDC(CVI_DBG_DEBUG, "+\n");
CVI_TRACE_GDC(CVI_DBG_DEBUG, "-\n");
return CVI_SUCCESS;
}
CVI_S32 CVI_GDC_Resume(void)
{
CVI_TRACE_GDC(CVI_DBG_DEBUG, "+\n");
CVI_TRACE_GDC(CVI_DBG_DEBUG, "-\n");
return CVI_SUCCESS;
}
/**************************************************************************
* Public APIs.
**************************************************************************/
CVI_S32 CVI_GDC_BeginJob(GDC_HANDLE *phHandle)
{
MOD_CHECK_NULL_PTR(CVI_ID_GDC, phHandle);
return CVI_SUCCESS;
}
CVI_S32 CVI_GDC_EndJob(GDC_HANDLE hHandle)
{
UNUSED(hHandle);
return CVI_SUCCESS;
}
CVI_S32 CVI_GDC_CancelJob(GDC_HANDLE hHandle)
{
if (hHandle == CVI_NULL) {
CVI_TRACE_GDC(CVI_DBG_ERR, "Null pointer.\n");
return CVI_ERR_GDC_NULL_PTR;
}
return CVI_SUCCESS;
}
CVI_S32 CVI_GDC_AddCorrectionTask(GDC_HANDLE hHandle, const GDC_TASK_ATTR_S *pstTask,
const FISHEYE_ATTR_S *pstFishEyeAttr)
{
MOD_CHECK_NULL_PTR(CVI_ID_GDC, pstTask);
MOD_CHECK_NULL_PTR(CVI_ID_GDC, pstFishEyeAttr);
CHECK_GDC_FORMAT(pstTask->stImgIn, pstTask->stImgOut);
struct gdc_task_param *param = calloc(1, sizeof(*param));
if (pstFishEyeAttr->bEnable) {
if (pstFishEyeAttr->u32RegionNum == 0) {
CVI_TRACE_GDC(CVI_DBG_ERR, "RegionNum(%d) can't be 0 if enable fisheye.\n",
pstFishEyeAttr->u32RegionNum);
//gdc_proc_ctx->stFishEyeStatus.u32AddTaskFail++;
return CVI_ERR_GDC_ILLEGAL_PARAM;
}
if (((CVI_U32)pstFishEyeAttr->s32HorOffset > pstTask->stImgIn.stVFrame.u32Width) ||
((CVI_U32)pstFishEyeAttr->s32VerOffset > pstTask->stImgIn.stVFrame.u32Height)) {
CVI_TRACE_GDC(CVI_DBG_ERR, "center pos(%d %d) out of frame size(%d %d).\n",
pstFishEyeAttr->s32HorOffset, pstFishEyeAttr->s32VerOffset,
pstTask->stImgIn.stVFrame.u32Width, pstTask->stImgIn.stVFrame.u32Height);
//gdc_proc_ctx->stFishEyeStatus.u32AddTaskFail++;
return CVI_ERR_GDC_ILLEGAL_PARAM;
}
for (CVI_U32 i = 0; i < pstFishEyeAttr->u32RegionNum; ++i) {
if ((pstFishEyeAttr->enMountMode == FISHEYE_WALL_MOUNT) &&
(pstFishEyeAttr->astFishEyeRegionAttr[i].enViewMode == FISHEYE_VIEW_360_PANORAMA)) {
CVI_TRACE_GDC(CVI_DBG_ERR, "Rgn(%d): WALL_MOUNT not support Panorama_360.\n", i);
//gdc_proc_ctx->stFishEyeStatus.u32AddTaskFail++;
return CVI_ERR_GDC_ILLEGAL_PARAM;
}
if ((pstFishEyeAttr->enMountMode == FISHEYE_CEILING_MOUNT) &&
(pstFishEyeAttr->astFishEyeRegionAttr[i].enViewMode == FISHEYE_VIEW_180_PANORAMA)) {
CVI_TRACE_GDC(CVI_DBG_ERR, "Rgn(%d): CEILING_MOUNT not support Panorama_180.\n", i);
//gdc_proc_ctx->stFishEyeStatus.u32AddTaskFail++;
return CVI_ERR_GDC_ILLEGAL_PARAM;
}
if ((pstFishEyeAttr->enMountMode == FISHEYE_DESKTOP_MOUNT) &&
(pstFishEyeAttr->astFishEyeRegionAttr[i].enViewMode == FISHEYE_VIEW_180_PANORAMA)) {
CVI_TRACE_GDC(CVI_DBG_ERR, "Rgn(%d): DESKTOP_MOUNT not support Panorama_180.\n", i);
//gdc_proc_ctx->stFishEyeStatus.u32AddTaskFail++;
return CVI_ERR_GDC_ILLEGAL_PARAM;
}
}
}
param->stTask = *pstTask;
param->type = GDC_TASK_TYPE_FISHEYE;
param->stFishEyeAttr = *pstFishEyeAttr;
if (param->stTask.reserved != CVI_GDC_MAGIC) {
CVI_U64 paddr;
CVI_VOID *vaddr;
if (CVI_SYS_IonAlloc(&paddr, &vaddr, "gdc_mesh", CVI_GDC_MESH_SIZE_FISHEYE) != CVI_SUCCESS) {
CVI_TRACE_GDC(CVI_DBG_ERR, "Can't acquire memory for mesh.\n");
//gdc_proc_ctx->stFishEyeStatus.u32AddTaskFail++;
return CVI_ERR_GDC_NOBUF;
}
param->stTask.au64privateData[0] = paddr;
param->stTask.au64privateData[1] = (uintptr_t)vaddr;
#if 0
FILE *fp;
int f_size;
CVI_U64 mesh_tbl_addr;
CVI_U16 *mesh_id;
fp = fopen("mesh_id.bin", "r");
if (fp == NULL) {
CVI_TRACE_GDC(CVI_DBG_ERR, "mesh id file not found.\n");
return CVI_ERR_VO_NOT_PERMIT;
}
fseek(fp, 0, SEEK_END);
f_size = ftell(fp);
if (f_size == -1) {
CVI_TRACE_GDC(CVI_DBG_ERR, "mesh id file can't tell.\n");
return CVI_ERR_VO_NOT_PERMIT;
}
fseek(fp, 0, SEEK_SET);
fread(vaddr, 1, f_size, fp);
fclose(fp);
mesh_id = vaddr;
paddr += ALIGN(f_size + 0x1000, 32);
vaddr += ALIGN(f_size + 0x1000, 32);
fp = fopen("mesh_tbl.bin", "r");
if (fp == NULL) {
CVI_TRACE_GDC(CVI_DBG_ERR, "mesh tbl file not found.\n");
return CVI_ERR_VO_NOT_PERMIT;
}
fseek(fp, 0, SEEK_END);
f_size = ftell(fp);
if (f_size == -1) {
CVI_TRACE_GDC(CVI_DBG_ERR, "mesh tbl file can't tell.\n");
return CVI_ERR_VO_NOT_PERMIT;
}
fseek(fp, 0, SEEK_SET);
fread(vaddr, 1, f_size, fp);
fclose(fp);
mesh_tbl_addr = paddr;
/**!! offset changes by mesh file !!**/
CVI_U32 offset[3] = {0x300, 0x300, 0x2800};
CVI_U8 index = 0;
while (*mesh_id != 0xffff) {
if (*mesh_id == 0xfffb) {
if (index > 3) {
CVI_TRACE_GDC(CVI_DBG_ERR, "check mesh.\n");
continue;
}
*(++mesh_id) = mesh_tbl_addr & 0x0fff;
*(++mesh_id) = (mesh_tbl_addr >> 12) & 0x0fff;
*(++mesh_id) = (mesh_tbl_addr >> 24) & 0x0fff;
*(++mesh_id) = (mesh_tbl_addr >> 36) & 0x000f;
mesh_tbl_addr += offset[index++];
}
++mesh_id;
}
#else
SIZE_S in_size, out_size;
in_size.u32Width = pstTask->stImgIn.stVFrame.u32Width;
in_size.u32Height = pstTask->stImgIn.stVFrame.u32Height;
out_size.u32Width = pstTask->stImgOut.stVFrame.u32Width;
out_size.u32Height = pstTask->stImgOut.stVFrame.u32Height;
mesh_gen_fisheye(in_size, out_size, pstFishEyeAttr, paddr, vaddr, ROTATION_0);
CVI_SYS_IonFlushCache(paddr, vaddr, CVI_GDC_MESH_SIZE_FISHEYE);
#endif
}
//gdc_proc_ctx->stFishEyeStatus.u32AddTaskSuc++;
return CVI_SUCCESS;
}
CVI_S32 CVI_GDC_AddRotationTask(GDC_HANDLE hHandle, const GDC_TASK_ATTR_S *pstTask, ROTATION_E enRotation)
{
MOD_CHECK_NULL_PTR(CVI_ID_GDC, pstTask);
CHECK_GDC_FORMAT(pstTask->stImgIn, pstTask->stImgOut);
if (gdc_rotation_check_size(enRotation, pstTask) != CVI_SUCCESS) {
CVI_TRACE_GDC(CVI_DBG_ERR, "gdc_rotation_check_size fail\n");
return CVI_ERR_GDC_ILLEGAL_PARAM;
}
struct gdc_task_param *param = calloc(1, sizeof(*param));
param->stTask = *pstTask;
param->type = GDC_TASK_TYPE_ROT;
param->enRotation = enRotation;
if (param->stTask.reserved != CVI_GDC_MAGIC) {
SIZE_S in_size, out_size;
CVI_U64 paddr;
CVI_VOID *vaddr;
if (CVI_SYS_IonAlloc_Cached(&paddr, &vaddr, "gdc_mesh", CVI_GDC_MESH_SIZE_ROT) != CVI_SUCCESS) {
CVI_TRACE_GDC(CVI_DBG_ERR, "Can't acquire memory for mesh.\n");
return CVI_ERR_GDC_NOBUF;
}
in_size.u32Width = pstTask->stImgIn.stVFrame.u32Width;
in_size.u32Height = pstTask->stImgIn.stVFrame.u32Height;
out_size.u32Width = pstTask->stImgOut.stVFrame.u32Width;
out_size.u32Height = pstTask->stImgOut.stVFrame.u32Height;
mesh_gen_rotation(in_size, out_size, enRotation, paddr, vaddr);
CVI_SYS_IonFlushCache(paddr, vaddr, CVI_GDC_MESH_SIZE_ROT);
param->stTask.au64privateData[0] = paddr;
param->stTask.au64privateData[1] = (uintptr_t)vaddr;
}
return CVI_SUCCESS;
}
CVI_S32 CVI_GDC_AddAffineTask(GDC_HANDLE hHandle, const GDC_TASK_ATTR_S *pstTask, const AFFINE_ATTR_S *pstAffineAttr)
{
MOD_CHECK_NULL_PTR(CVI_ID_GDC, pstTask);
MOD_CHECK_NULL_PTR(CVI_ID_GDC, pstAffineAttr);
CHECK_GDC_FORMAT(pstTask->stImgIn, pstTask->stImgOut);
if (pstAffineAttr->u32RegionNum == 0) {
CVI_TRACE_GDC(CVI_DBG_ERR, "u32RegionNum(%d) can't be zero.\n", pstAffineAttr->u32RegionNum);
return CVI_ERR_GDC_ILLEGAL_PARAM;
}
if (pstAffineAttr->stDestSize.u32Width > pstTask->stImgOut.stVFrame.u32Width) {
CVI_TRACE_GDC(CVI_DBG_ERR, "dest's width(%d) can't be larger than frame's width(%d)\n",
pstAffineAttr->stDestSize.u32Width, pstTask->stImgOut.stVFrame.u32Width);
return CVI_ERR_GDC_ILLEGAL_PARAM;
}
for (CVI_U32 i = 0; i < pstAffineAttr->u32RegionNum; ++i) {
CVI_TRACE_GDC(CVI_DBG_INFO, "u32RegionNum(%d) (%f, %f) (%f, %f) (%f, %f) (%f, %f)\n", i,
pstAffineAttr->astRegionAttr[i][0].x, pstAffineAttr->astRegionAttr[i][0].y,
pstAffineAttr->astRegionAttr[i][1].x, pstAffineAttr->astRegionAttr[i][1].y,
pstAffineAttr->astRegionAttr[i][2].x, pstAffineAttr->astRegionAttr[i][2].y,
pstAffineAttr->astRegionAttr[i][3].x, pstAffineAttr->astRegionAttr[i][3].y);
if ((pstAffineAttr->astRegionAttr[i][0].x < 0) || (pstAffineAttr->astRegionAttr[i][0].y < 0) ||
(pstAffineAttr->astRegionAttr[i][1].x < 0) || (pstAffineAttr->astRegionAttr[i][1].y < 0) ||
(pstAffineAttr->astRegionAttr[i][2].x < 0) || (pstAffineAttr->astRegionAttr[i][2].y < 0) ||
(pstAffineAttr->astRegionAttr[i][3].x < 0) || (pstAffineAttr->astRegionAttr[i][3].y < 0)) {
CVI_TRACE_GDC(CVI_DBG_ERR, "u32RegionNum(%d) affine point can't be negative\n", i);
return CVI_ERR_GDC_ILLEGAL_PARAM;
}
if ((pstAffineAttr->astRegionAttr[i][1].x < pstAffineAttr->astRegionAttr[i][0].x) ||
(pstAffineAttr->astRegionAttr[i][3].x < pstAffineAttr->astRegionAttr[i][2].x)) {
CVI_TRACE_GDC(CVI_DBG_ERR, "u32RegionNum(%d) point1/3's x should be bigger thant 0/2's\n", i);
return CVI_ERR_GDC_ILLEGAL_PARAM;
}
if ((pstAffineAttr->astRegionAttr[i][2].y < pstAffineAttr->astRegionAttr[i][0].y) ||
(pstAffineAttr->astRegionAttr[i][3].y < pstAffineAttr->astRegionAttr[i][1].y)) {
CVI_TRACE_GDC(CVI_DBG_ERR, "u32RegionNum(%d) point2/3's y should be bigger thant 0/1's\n", i);
return CVI_ERR_GDC_ILLEGAL_PARAM;
}
}
struct gdc_task_param *param = calloc(1, sizeof(*param));
param->stTask = *pstTask;
param->type = GDC_TASK_TYPE_AFFINE;
param->stAffineAttr = *pstAffineAttr;
SIZE_S in_size, out_size;
CVI_U64 paddr;
CVI_VOID *vaddr;
if (CVI_SYS_IonAlloc_Cached(&paddr, &vaddr, "gdc_mesh", CVI_GDC_MESH_SIZE_AFFINE) != CVI_SUCCESS) {
CVI_TRACE_GDC(CVI_DBG_ERR, "Can't acquire memory for mesh.\n");
return CVI_ERR_GDC_NOBUF;
}
in_size.u32Width = pstTask->stImgIn.stVFrame.u32Width;
in_size.u32Height = pstTask->stImgIn.stVFrame.u32Height;
out_size.u32Width = pstTask->stImgOut.stVFrame.u32Width;
out_size.u32Height = pstTask->stImgOut.stVFrame.u32Height;
mesh_gen_affine(in_size, out_size, pstAffineAttr, paddr, vaddr);
CVI_SYS_IonFlushCache(paddr, vaddr, CVI_GDC_MESH_SIZE_AFFINE);
param->stTask.au64privateData[0] = paddr;
param->stTask.au64privateData[1] = (uintptr_t)vaddr;
return CVI_SUCCESS;
}
CVI_S32 CVI_GDC_AddLDCTask(GDC_HANDLE hHandle, const GDC_TASK_ATTR_S *pstTask
, const LDC_ATTR_S *pstLDCAttr, ROTATION_E enRotation)
{
MOD_CHECK_NULL_PTR(CVI_ID_GDC, pstTask);
MOD_CHECK_NULL_PTR(CVI_ID_GDC, pstLDCAttr);
CHECK_GDC_FORMAT(pstTask->stImgIn, pstTask->stImgOut);
if (enRotation != ROTATION_0) {
if (gdc_rotation_check_size(enRotation, pstTask) != CVI_SUCCESS) {
CVI_TRACE_GDC(CVI_DBG_ERR, "gdc_rotation_check_size fail\n");
return CVI_ERR_GDC_ILLEGAL_PARAM;
}
}
struct gdc_task_param *param = calloc(1, sizeof(*param));
param->stTask = *pstTask;
param->type = GDC_TASK_TYPE_LDC;
param->stLDCAttr = *pstLDCAttr;
param->stTask.au64privateData[3] = enRotation;
return CVI_SUCCESS;
}
// cnv
#define CVI_GDC_MESH_SIZE_CNV (100000)
//offset[0:2]=tbl_param[0:2], len_tbl = tbl_param[3], len_idl = tbl_param[4]
CVI_S32 CVI_GDC_AddCorrectionTaskCNV(GDC_HANDLE hHandle, const GDC_TASK_ATTR_S *pstTask
, const FISHEYE_ATTR_S *pstFishEyeAttr, uint8_t *p_tbl, uint8_t *p_idl, uint32_t *tbl_param)
{
CHECK_GDC_FORMAT(pstTask->stImgIn, pstTask->stImgOut);
struct gdc_task_param *param = calloc(1, sizeof(*param));
int32_t len_tbl = tbl_param[4];
int32_t len_idl = tbl_param[3];
if (pstFishEyeAttr->bEnable) {
if (pstFishEyeAttr->u32RegionNum == 0) {
CVI_TRACE_GDC(CVI_DBG_ERR, "RegionNum(%d) can't be 0 if enable fisheye.\n"
, pstFishEyeAttr->u32RegionNum);
return CVI_ERR_GDC_ILLEGAL_PARAM;
}
if (((CVI_U32)pstFishEyeAttr->s32HorOffset > pstTask->stImgIn.stVFrame.u32Width)
|| ((CVI_U32)pstFishEyeAttr->s32VerOffset > pstTask->stImgIn.stVFrame.u32Height)) {
CVI_TRACE_GDC(CVI_DBG_ERR, "center pos(%d %d) out of frame size(%d %d).\n"
, pstFishEyeAttr->s32HorOffset, pstFishEyeAttr->s32VerOffset
, pstTask->stImgIn.stVFrame.u32Width, pstTask->stImgIn.stVFrame.u32Height);
return CVI_ERR_GDC_ILLEGAL_PARAM;
}
for (CVI_U32 i = 0; i < pstFishEyeAttr->u32RegionNum; ++i) {
if ((pstFishEyeAttr->enMountMode == FISHEYE_WALL_MOUNT)
&& (pstFishEyeAttr->astFishEyeRegionAttr[i].enViewMode == FISHEYE_VIEW_360_PANORAMA)) {
CVI_TRACE_GDC(CVI_DBG_ERR, "Rgn(%d): WALL_MOUNT not support Panorama_360.\n", i);
return CVI_ERR_GDC_ILLEGAL_PARAM;
}
if ((pstFishEyeAttr->enMountMode == FISHEYE_CEILING_MOUNT)
&& (pstFishEyeAttr->astFishEyeRegionAttr[i].enViewMode == FISHEYE_VIEW_180_PANORAMA)) {
CVI_TRACE_GDC(CVI_DBG_ERR, "Rgn(%d): CEILING_MOUNT not support Panorama_180.\n", i);
return CVI_ERR_GDC_ILLEGAL_PARAM;
}
if ((pstFishEyeAttr->enMountMode == FISHEYE_DESKTOP_MOUNT)
&& (pstFishEyeAttr->astFishEyeRegionAttr[i].enViewMode == FISHEYE_VIEW_180_PANORAMA)) {
CVI_TRACE_GDC(CVI_DBG_ERR, "Rgn(%d): DESKTOP_MOUNT not support Panorama_180.\n", i);
return CVI_ERR_GDC_ILLEGAL_PARAM;
}
}
}
param->stTask = *pstTask;
param->type = GDC_TASK_TYPE_FISHEYE;
param->stFishEyeAttr = *pstFishEyeAttr;
if (param->stTask.reserved != CVI_GDC_MAGIC) {
CVI_U64 paddr;
CVI_VOID *vaddr;
if (CVI_SYS_IonAlloc(&paddr, &vaddr, "gdc_mesh", CVI_GDC_MESH_SIZE_CNV) != CVI_SUCCESS) {
CVI_TRACE_GDC(CVI_DBG_ERR, "Can't acquire memory for mesh.\n");
return CVI_ERR_GDC_NOBUF;
}
param->stTask.au64privateData[0] = paddr;
param->stTask.au64privateData[1] = (uintptr_t)vaddr;
#if 1
int f_size;
CVI_U64 mesh_tbl_addr;
CVI_U16 *mesh_id;
f_size = len_idl;
memcpy(vaddr, p_idl, f_size);
mesh_id = vaddr;
paddr += ALIGN(f_size + 0x1000, 32);
vaddr += ALIGN(f_size + 0x1000, 32);
f_size = len_tbl;
memcpy(vaddr, p_tbl, f_size);
mesh_tbl_addr = paddr;
/**!! offset changes by mesh file !!**/
CVI_U32 offset[3] = {0x1440, 0x1200, 0x1200};
CVI_U8 index = 0;
offset[0] = tbl_param[0];
offset[1] = tbl_param[1];
offset[2] = tbl_param[2];
while (*mesh_id != 0xffff) {
if (*mesh_id == 0xfffb) {
if (index > 3) {
CVI_TRACE_GDC(CVI_DBG_ERR, "check mesh.\n");
continue;
}
*(++mesh_id) = mesh_tbl_addr & 0x0fff;
*(++mesh_id) = (mesh_tbl_addr >> 12) & 0x0fff;
*(++mesh_id) = (mesh_tbl_addr >> 24) & 0x0fff;
*(++mesh_id) = (mesh_tbl_addr >> 36) & 0x000f;
mesh_tbl_addr += offset[index++];
}
++mesh_id;
}
#else
SIZE_S in_size, out_size;
in_size.u32Width = pstTask->stImgIn.stVFrame.u32Width;
in_size.u32Height = pstTask->stImgIn.stVFrame.u32Height;
out_size.u32Width = pstTask->stImgOut.stVFrame.u32Width;
out_size.u32Height = pstTask->stImgOut.stVFrame.u32Height;
mesh_gen_fisheye(in_size, out_size, pstFishEyeAttr, paddr, vaddr);
CVI_SYS_IonFlushCache(paddr, vaddr, CVI_GDC_MESH_SIZE_FISHEYE);
#endif
}
return CVI_SUCCESS;
}
//#define CVI_GDC_MESH_SIZE_CNV (100000)
unsigned char ptbl[200000];
unsigned char ptbid[100000];
// static int flag_mem = 1;
int f_size;
#define USE_BIN_TXT 0 // 0: use mesh txt data, 1: use mesh tbl bin data
CVI_S32 CVI_GDC_AddCnvWarpTask(const float *pfmesh_data, GDC_HANDLE hHandle, const GDC_TASK_ATTR_S *pstTask,
const FISHEYE_ATTR_S *pstAffineAttr, bool *bReNew)
{
CHECK_GDC_FORMAT(pstTask->stImgIn, pstTask->stImgOut);
struct gdc_task_param *param = calloc(1, sizeof(*param));
param->stTask = *pstTask;
param->type = GDC_TASK_TYPE_FISHEYE; // GDC_TASK_TYPE_AFFINE;
param->stFishEyeAttr = *pstAffineAttr;
*bReNew = true;
if (*bReNew == false) {
return CVI_SUCCESS;
}
if (param->stTask.reserved != CVI_GDC_MAGIC) {
CVI_U64 paddr;
CVI_VOID *vaddr;
if (CVI_SYS_IonAlloc_Cached(&paddr, &vaddr, "gdc_mesh", CVI_GDC_MESH_SIZE_CNV) != CVI_SUCCESS) {
*bReNew = true;
CVI_TRACE_GDC(CVI_DBG_ERR, "Can't acquire memory for mesh.\n");
return CVI_ERR_GDC_NOBUF;
}
#if USE_BIN_TXT
FILE *fp;
// int f_size;
// flag_mem = 1;
CVI_U64 mesh_tbl_addr;
CVI_U16 *mesh_id;
if (flag_mem) {
memset(ptbid, 0, sizeof(ptbid));
fp = fopen("cnv_mesh_id.bin", "r");
if (fp == NULL) {
CVI_TRACE_GDC(CVI_DBG_ERR, "mesh id file not found.\n");
return CVI_ERR_VO_NOT_PERMIT;
}
fseek(fp, 0, SEEK_END);
f_size = ftell(fp);
if (f_size == -1) {
CVI_TRACE_GDC(CVI_DBG_ERR, "mesh id file can't tell.\n");
return CVI_ERR_VO_NOT_PERMIT;
}
fseek(fp, 0, SEEK_SET);
fread(ptbid, 1, f_size, fp);
fclose(fp);
printf("mesh id size: %d\n", f_size);
}
mesh_id = vaddr;
memcpy(mesh_id, ptbid, f_size);
paddr += ALIGN(f_size + 0x1000, 32);
vaddr += ALIGN(f_size + 0x1000, 32);
if (flag_mem) {
flag_mem = 0;
memset(ptbl, 0, sizeof(ptbl));
fp = fopen("cnv_mesh_tbl.bin", "r");
if (fp == NULL) {
CVI_TRACE_GDC(CVI_DBG_ERR, "mesh tbl file not found.\n");
return CVI_ERR_VO_NOT_PERMIT;
}
fseek(fp, 0, SEEK_END);
f_size = ftell(fp);
if (f_size == -1) {
CVI_TRACE_GDC(CVI_DBG_ERR, "mesh tbl file can't tell.\n");
return CVI_ERR_VO_NOT_PERMIT;
}
fseek(fp, 0, SEEK_SET);
fread(ptbl, 1, f_size, fp);
fclose(fp);
}
memcpy(vaddr, ptbl, f_size);
printf("mesh tbl size: %d\n", f_size);
mesh_tbl_addr = paddr;
/**!! offset changes by mesh file !!**/
CVI_U32 offset[3] = { 0x1440, 0x1200, 0x1200 };
CVI_U8 index = 0;
while (*mesh_id != 0xffff) {
if (*mesh_id == 0xfffb) {
if (index > 3) {
CVI_TRACE_GDC(CVI_DBG_ERR, "check mesh.\n");
continue;
}
*(++mesh_id) = mesh_tbl_addr & 0x0fff;
*(++mesh_id) = (mesh_tbl_addr >> 12) & 0x0fff;
*(++mesh_id) = (mesh_tbl_addr >> 24) & 0x0fff;
*(++mesh_id) = (mesh_tbl_addr >> 36) & 0x000f;
mesh_tbl_addr += offset[index++];
}
++mesh_id;
}
#else
SIZE_S in_size, out_size;
in_size.u32Width = pstTask->stImgIn.stVFrame.u32Width;
in_size.u32Height = pstTask->stImgIn.stVFrame.u32Height;
out_size.u32Width = pstTask->stImgOut.stVFrame.u32Width;
out_size.u32Height = pstTask->stImgOut.stVFrame.u32Height;
struct timeval t0, t1;
gettimeofday(&t0, NULL);
// got cnv mesh table from file
// get_cnv_warp_mesh_tbl(in_size, out_size, pstAffineAttr, paddr, vaddr);
// FISHEYE_ATTR_S pstFisheyeAttr;
mesh_gen_cnv(pfmesh_data, in_size, out_size, pstAffineAttr, paddr, vaddr);
gettimeofday(&t1, NULL);
unsigned long elapsed_dwa = (t1.tv_sec - t0.tv_sec) * 1000000 + t1.tv_usec - t0.tv_usec;
printf("mesh_gen_cnv speed: %lu\n", elapsed_dwa);
#endif
printf("out[0]\n");
CVI_SYS_IonFlushCache(paddr, vaddr,
CVI_GDC_MESH_SIZE_CNV); // 0x100000);
printf("out[1]\n");
param->stTask.au64privateData[0] = paddr;
param->stTask.au64privateData[1] = (uintptr_t)vaddr;
printf("finished\n");
*bReNew = false;
}
return CVI_SUCCESS;
}
CVI_S32 CVI_GDC_SetMeshSize(int nMeshHor, int nMeshVer)
{
return set_mesh_size(nMeshHor, nMeshVer);
}

View File

@@ -0,0 +1,684 @@
#include <errno.h>
#include <pthread.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/prctl.h>
#include <inttypes.h>
#include <unistd.h>
#include <sys/mman.h>
#include <linux/cvi_vi_ctx.h>
#include <linux/vi_uapi.h>
#include <linux/vpss_uapi.h>
#include "cvi_buffer.h"
#include "cvi_base.h"
#include "cvi_sys.h"
#include "cvi_vb.h"
#include "cvi_gdc.h"
#include "gdc_mesh.h"
#include "dwa_ioctl.h"
#include "vi_ioctl.h"
#include "vpss_ioctl.h"
#include "gdc_ctx.h"
#define DWA_YUV_BLACK 0x808000
#define DWA_RGB_BLACK 0x0
#define CHECK_GDC_FORMAT(imgIn, imgOut) \
do { \
if (imgIn.stVFrame.enPixelFormat != imgOut.stVFrame.enPixelFormat) { \
CVI_TRACE_GDC(CVI_DBG_ERR, "in/out pixelformat(%d-%d) mismatch\n", \
imgIn.stVFrame.enPixelFormat, imgOut.stVFrame.enPixelFormat); \
return CVI_ERR_GDC_ILLEGAL_PARAM; \
} \
if (!GDC_SUPPORT_FMT(imgIn.stVFrame.enPixelFormat)) { \
CVI_TRACE_GDC(CVI_DBG_ERR, "pixelformat(%d) unsupported\n", imgIn.stVFrame.enPixelFormat); \
return CVI_ERR_GDC_ILLEGAL_PARAM; \
} \
} while (0)
static CVI_S32 gdc_rotation_check_size(ROTATION_E enRotation, const GDC_TASK_ATTR_S *pstTask)
{
if (enRotation >= ROTATION_MAX) {
CVI_TRACE_GDC(CVI_DBG_ERR, "invalid rotation(%d).\n", enRotation);
return CVI_ERR_GDC_ILLEGAL_PARAM;
}
if (enRotation == ROTATION_90 || enRotation == ROTATION_270 || enRotation == ROTATION_XY_FLIP) {
if (pstTask->stImgOut.stVFrame.u32Width < pstTask->stImgIn.stVFrame.u32Height) {
CVI_TRACE_GDC(CVI_DBG_ERR, "rotation(%d) invalid: 'output width(%d) < input height(%d)'\n",
enRotation, pstTask->stImgOut.stVFrame.u32Width,
pstTask->stImgIn.stVFrame.u32Height);
return CVI_ERR_GDC_ILLEGAL_PARAM;
}
if (pstTask->stImgOut.stVFrame.u32Height < pstTask->stImgIn.stVFrame.u32Width) {
CVI_TRACE_GDC(CVI_DBG_ERR, "rotation(%d) invalid: 'output height(%d) < input width(%d)'\n",
enRotation, pstTask->stImgOut.stVFrame.u32Height,
pstTask->stImgIn.stVFrame.u32Width);
return CVI_ERR_GDC_ILLEGAL_PARAM;
}
} else {
if (pstTask->stImgOut.stVFrame.u32Width < pstTask->stImgIn.stVFrame.u32Width) {
CVI_TRACE_GDC(CVI_DBG_ERR, "rotation(%d) invalid: 'output width(%d) < input width(%d)'\n",
enRotation, pstTask->stImgOut.stVFrame.u32Width,
pstTask->stImgIn.stVFrame.u32Width);
return CVI_ERR_GDC_ILLEGAL_PARAM;
}
if (pstTask->stImgOut.stVFrame.u32Height < pstTask->stImgIn.stVFrame.u32Height) {
CVI_TRACE_GDC(CVI_DBG_ERR, "rotation(%d) invalid: 'output height(%d) < input height(%d)'\n",
enRotation, pstTask->stImgOut.stVFrame.u32Height,
pstTask->stImgIn.stVFrame.u32Height);
return CVI_ERR_GDC_ILLEGAL_PARAM;
}
}
return CVI_SUCCESS;
}
void gdcq_init(void)
{
}
CVI_S32 CVI_GDC_Suspend(void)
{
CVI_TRACE_GDC(CVI_DBG_DEBUG, "+\n");
CVI_TRACE_GDC(CVI_DBG_DEBUG, "-\n");
return CVI_SUCCESS;
}
CVI_S32 CVI_GDC_Resume(void)
{
CVI_TRACE_GDC(CVI_DBG_DEBUG, "+\n");
CVI_TRACE_GDC(CVI_DBG_DEBUG, "-\n");
return CVI_SUCCESS;
}
/**************************************************************************
* Public APIs.
**************************************************************************/
CVI_S32 CVI_GDC_BeginJob(GDC_HANDLE *phHandle)
{
MOD_CHECK_NULL_PTR(CVI_ID_GDC, phHandle);
struct vdev *d = get_dev_info(VDEV_TYPE_DWA, 0);
if (!IS_VDEV_OPEN(d->state)) {
CVI_TRACE_GDC(CVI_DBG_ERR, "gdc state(%d) incorrect.", d->state);
return CVI_ERR_GDC_SYS_NOTREADY;
}
struct gdc_handle_data cfg;
memset(&cfg, 0, sizeof(cfg));
if (gdc_begin_job(d->fd, &cfg))
return CVI_FAILURE;
*phHandle = cfg.handle;
return CVI_SUCCESS;
}
CVI_S32 CVI_GDC_EndJob(GDC_HANDLE hHandle)
{
struct vdev *d = get_dev_info(VDEV_TYPE_DWA, 0);
if (!IS_VDEV_OPEN(d->state)) {
CVI_TRACE_GDC(CVI_DBG_ERR, "gdc state(%d) incorrect.", d->state);
return CVI_ERR_GDC_SYS_NOTREADY;
}
struct gdc_handle_data cfg;
memset(&cfg, 0, sizeof(cfg));
cfg.handle = hHandle;
return gdc_end_job(d->fd, &cfg);
}
CVI_S32 CVI_GDC_CancelJob(GDC_HANDLE hHandle)
{
struct vdev *d = get_dev_info(VDEV_TYPE_DWA, 0);
if (!IS_VDEV_OPEN(d->state)) {
CVI_TRACE_GDC(CVI_DBG_ERR, "gdc state(%d) incorrect.", d->state);
return CVI_ERR_GDC_SYS_NOTREADY;
}
struct gdc_handle_data cfg;
memset(&cfg, 0, sizeof(cfg));
cfg.handle = hHandle;
return gdc_cancel_job(d->fd, &cfg);
}
CVI_S32 CVI_GDC_AddCorrectionTask(GDC_HANDLE hHandle, const GDC_TASK_ATTR_S *pstTask,
const FISHEYE_ATTR_S *pstFishEyeAttr)
{
MOD_CHECK_NULL_PTR(CVI_ID_GDC, pstTask);
MOD_CHECK_NULL_PTR(CVI_ID_GDC, pstFishEyeAttr);
CHECK_GDC_FORMAT(pstTask->stImgIn, pstTask->stImgOut);
UNUSED(hHandle);
CVI_TRACE_GDC(CVI_DBG_ERR, "not supported\n");
return CVI_ERR_GDC_NOT_SUPPORT;
}
CVI_S32 CVI_GDC_AddRotationTask(GDC_HANDLE hHandle, const GDC_TASK_ATTR_S *pstTask, ROTATION_E enRotation)
{
MOD_CHECK_NULL_PTR(CVI_ID_GDC, pstTask);
CHECK_GDC_FORMAT(pstTask->stImgIn, pstTask->stImgOut);
UNUSED(hHandle);
if (enRotation == ROTATION_180) {
CVI_TRACE_GDC(CVI_DBG_ERR, "do not support rotation 180\n");
return CVI_ERR_GDC_NOT_SUPPORT;
}
if (gdc_rotation_check_size(enRotation, pstTask) != CVI_SUCCESS) {
CVI_TRACE_GDC(CVI_DBG_ERR, "gdc_rotation_check_size fail\n");
return CVI_ERR_GDC_ILLEGAL_PARAM;
}
struct vdev *d = get_dev_info(VDEV_TYPE_DWA, 0);
if (!IS_VDEV_OPEN(d->state)) {
CVI_TRACE_GDC(CVI_DBG_ERR, "gdc state(%d) incorrect.", d->state);
return CVI_ERR_GDC_SYS_NOTREADY;
}
struct gdc_task_attr attr;
memset(&attr, 0, sizeof(attr));
attr.handle = hHandle;
memcpy(&attr.stImgIn, &pstTask->stImgIn, sizeof(attr.stImgIn));
memcpy(&attr.stImgOut, &pstTask->stImgOut, sizeof(attr.stImgOut));
//memcpy(attr.au64privateData, pstTask->au64privateData, sizeof(attr.au64privateData));
//attr.reserved = pstTask->reserved;
attr.enRotation = enRotation;
return gdc_add_rotation_task(d->fd, &attr);
}
CVI_S32 CVI_GDC_AddAffineTask(GDC_HANDLE hHandle, const GDC_TASK_ATTR_S *pstTask, const AFFINE_ATTR_S *pstAffineAttr)
{
MOD_CHECK_NULL_PTR(CVI_ID_GDC, pstTask);
MOD_CHECK_NULL_PTR(CVI_ID_GDC, pstAffineAttr);
CHECK_GDC_FORMAT(pstTask->stImgIn, pstTask->stImgOut);
UNUSED(hHandle);
CVI_TRACE_GDC(CVI_DBG_ERR, "not supported\n");
return CVI_ERR_GDC_NOT_SUPPORT;
}
CVI_S32 CVI_GDC_AddLDCTask(GDC_HANDLE hHandle, const GDC_TASK_ATTR_S *pstTask
, const LDC_ATTR_S *pstLDCAttr, ROTATION_E enRotation)
{
MOD_CHECK_NULL_PTR(CVI_ID_GDC, pstTask);
MOD_CHECK_NULL_PTR(CVI_ID_GDC, pstLDCAttr);
CHECK_GDC_FORMAT(pstTask->stImgIn, pstTask->stImgOut);
UNUSED(hHandle);
if (enRotation == ROTATION_180) {
CVI_TRACE_GDC(CVI_DBG_ERR, "do not support rotation 180\n");
return CVI_ERR_GDC_NOT_SUPPORT;
}
if (enRotation != ROTATION_0) {
if (gdc_rotation_check_size(enRotation, pstTask) != CVI_SUCCESS) {
CVI_TRACE_GDC(CVI_DBG_ERR, "gdc_rotation_check_size fail\n");
return CVI_ERR_GDC_ILLEGAL_PARAM;
}
}
struct vdev *d = get_dev_info(VDEV_TYPE_DWA, 0);
if (!IS_VDEV_OPEN(d->state)) {
CVI_TRACE_GDC(CVI_DBG_ERR, "gdc state(%d) incorrect.", d->state);
return CVI_ERR_GDC_SYS_NOTREADY;
}
struct gdc_task_attr attr;
memset(&attr, 0, sizeof(attr));
attr.handle = hHandle;
memcpy(&attr.stImgIn, &pstTask->stImgIn, sizeof(attr.stImgIn));
memcpy(&attr.stImgOut, &pstTask->stImgOut, sizeof(attr.stImgOut));
memcpy(attr.au64privateData, pstTask->au64privateData, sizeof(attr.au64privateData));
attr.reserved = pstTask->reserved;
attr.enRotation = enRotation;
return gdc_add_ldc_task(d->fd, &attr);
}
CVI_S32 CVI_GDC_AddCorrectionTaskCNV(GDC_HANDLE hHandle, const GDC_TASK_ATTR_S *pstTask
, const FISHEYE_ATTR_S *pstFishEyeAttr, uint8_t *p_tbl, uint8_t *p_idl, uint32_t *tbl_param)
{
CHECK_GDC_FORMAT(pstTask->stImgIn, pstTask->stImgOut);
UNUSED(hHandle);
UNUSED(pstFishEyeAttr);
UNUSED(p_tbl);
UNUSED(p_idl);
UNUSED(tbl_param);
CVI_TRACE_GDC(CVI_DBG_ERR, "not supported\n");
return CVI_ERR_GDC_NOT_SUPPORT;
}
CVI_S32 CVI_GDC_AddCnvWarpTask(const float *pfmesh_data, GDC_HANDLE hHandle, const GDC_TASK_ATTR_S *pstTask,
const FISHEYE_ATTR_S *pstAffineAttr, bool *bReNew)
{
CHECK_GDC_FORMAT(pstTask->stImgIn, pstTask->stImgOut);
UNUSED(pfmesh_data);
UNUSED(hHandle);
UNUSED(pstAffineAttr);
UNUSED(bReNew);
CVI_TRACE_GDC(CVI_DBG_ERR, "not supported\n");
return CVI_ERR_GDC_NOT_SUPPORT;
}
CVI_S32 CVI_GDC_GenLDCMesh(CVI_U32 u32Width, CVI_U32 u32Height, const LDC_ATTR_S *pstLDCAttr,
const char *name, CVI_U64 *pu64PhyAddr, CVI_VOID **ppVirAddr)
{
CVI_U64 paddr;
CVI_VOID *vaddr;
SIZE_S in_size, out_size;
CVI_U32 mesh_1st_size = 0, mesh_2nd_size = 0, mesh_size = 0;
ROTATION_E enRotation = ROTATION_0;
if (pstLDCAttr->bAspect) {
if (pstLDCAttr->s32XYRatio < 0 || pstLDCAttr->s32XYRatio > 100) {
CVI_TRACE_GDC(CVI_DBG_ERR, "Invalid LDC s32XYRatio(%d).\n"
, pstLDCAttr->s32XYRatio);
return CVI_ERR_GDC_ILLEGAL_PARAM;
}
} else {
if (pstLDCAttr->s32XRatio < 0 || pstLDCAttr->s32XRatio > 100) {
CVI_TRACE_GDC(CVI_DBG_ERR, "Invalid LDC s32XRatio(%d).\n"
, pstLDCAttr->s32XRatio);
return CVI_ERR_GDC_ILLEGAL_PARAM;
}
if (pstLDCAttr->s32YRatio < 0 || pstLDCAttr->s32YRatio > 100) {
CVI_TRACE_GDC(CVI_DBG_ERR, "Invalid LDC s32YRatio(%d).\n"
, pstLDCAttr->s32YRatio);
return CVI_ERR_GDC_ILLEGAL_PARAM;
}
}
if (pstLDCAttr->s32CenterXOffset < -511 || pstLDCAttr->s32CenterXOffset > 511) {
CVI_TRACE_GDC(CVI_DBG_ERR, "Invalid LDC s32CenterXOffset(%d).\n"
, pstLDCAttr->s32CenterXOffset);
return CVI_ERR_GDC_ILLEGAL_PARAM;
}
if (pstLDCAttr->s32CenterYOffset < -511 || pstLDCAttr->s32CenterYOffset > 511) {
CVI_TRACE_GDC(CVI_DBG_ERR, "Invalid LDC s32CenterYOffset(%d).\n"
, pstLDCAttr->s32CenterYOffset);
return CVI_ERR_GDC_ILLEGAL_PARAM;
}
if (pstLDCAttr->s32DistortionRatio < -300 || pstLDCAttr->s32DistortionRatio > 500) {
CVI_TRACE_GDC(CVI_DBG_ERR, "Invalid LDC s32DistortionRatio(%d).\n"
, pstLDCAttr->s32DistortionRatio);
return CVI_ERR_GDC_ILLEGAL_PARAM;
}
if (!name) {
CVI_TRACE_GDC(CVI_DBG_ERR, "Please asign name for LDC mesh\n");
return CVI_ERR_GDC_ILLEGAL_PARAM;
}
in_size.u32Width = ALIGN(u32Width, DEFAULT_ALIGN);
in_size.u32Height = ALIGN(u32Height, DEFAULT_ALIGN);
out_size.u32Width = in_size.u32Width;
out_size.u32Height = in_size.u32Height;
mesh_gen_get_size(in_size, out_size, &mesh_1st_size, &mesh_2nd_size);
mesh_size = mesh_1st_size + mesh_2nd_size;
CVI_TRACE_GDC(CVI_DBG_DEBUG, "W=%d, H=%d, mesh_size=%d\n",
in_size.u32Width, in_size.u32Height,
mesh_size);
if (CVI_SYS_IonAlloc_Cached(&paddr, &vaddr, name, mesh_size) != CVI_SUCCESS) {
CVI_TRACE_GDC(CVI_DBG_ERR, " Can't acquire memory for LDC mesh.\n");
return CVI_ERR_GDC_NOMEM;
}
if (mesh_gen_ldc(in_size, out_size, pstLDCAttr, paddr, vaddr, enRotation) != CVI_SUCCESS) {
CVI_SYS_IonFree(paddr, vaddr);
CVI_TRACE_GDC(CVI_DBG_ERR, "Can't generate ldc mesh.\n");
return CVI_ERR_GDC_ILLEGAL_PARAM;
}
CVI_SYS_IonFlushCache(paddr, vaddr, mesh_size);
*pu64PhyAddr = paddr;
*ppVirAddr = vaddr;
return CVI_SUCCESS;
}
CVI_S32 CVI_GDC_LoadLDCMesh(CVI_U32 u32Width, CVI_U32 u32Height, const char *fileNname
, const char *tskName, CVI_U64 *pu64PhyAddr, CVI_VOID **ppVirAddr)
{
CVI_U64 paddr;
CVI_VOID *vaddr;
SIZE_S in_size, out_size;
CVI_U32 mesh_1st_size = 0, mesh_2nd_size = 0, mesh_size = 0;
if (!fileNname) {
CVI_TRACE_GDC(CVI_DBG_ERR, "Please asign name for LDC mesh\n");
return CVI_ERR_GDC_ILLEGAL_PARAM;
}
if (!tskName) {
CVI_TRACE_GDC(CVI_DBG_ERR, "Please asign task name for LDC\n");
return CVI_ERR_GDC_ILLEGAL_PARAM;
}
in_size.u32Width = ALIGN(u32Width, DEFAULT_ALIGN);
in_size.u32Height = ALIGN(u32Height, DEFAULT_ALIGN);
out_size.u32Width = in_size.u32Width;
out_size.u32Height = in_size.u32Height;
mesh_gen_get_size(in_size, out_size, &mesh_1st_size, &mesh_2nd_size);
mesh_size = mesh_1st_size + mesh_2nd_size;
CVI_TRACE_GDC(CVI_DBG_DEBUG, "W=%d, H=%d, mesh_size=%d\n"
, in_size.u32Width, in_size.u32Height, mesh_size);
// acquire memory space for mesh.
if (CVI_SYS_IonAlloc_Cached(&paddr, &vaddr, tskName, mesh_size) != CVI_SUCCESS) {
CVI_TRACE_GDC(CVI_DBG_ERR, "Can't acquire memory for mesh.\n");
return CVI_ERR_GDC_NOMEM;
}
FILE *fp = fopen(fileNname, "rb");
if (!fp) {
CVI_TRACE_GDC(CVI_DBG_ERR, "open file:%s failed.\n", fileNname);
CVI_SYS_IonFree(paddr, vaddr);
return CVI_ERR_GDC_ILLEGAL_PARAM;
}
fseek(fp, 0, SEEK_END);
int fileSize = ftell(fp);
if (mesh_size != (CVI_U32)fileSize) {
CVI_TRACE_GDC(CVI_DBG_ERR, "loadmesh file:(%s) size is not match.\n", fileNname);
CVI_SYS_IonFree(paddr, vaddr);
fclose(fp);
return CVI_FAILURE;
}
rewind(fp);
CVI_TRACE_GDC(CVI_DBG_DEBUG, "load mesh size:%d, mesh phy addr:%#"PRIx64", vir addr:%p.\n",
mesh_size, paddr, vaddr);
fread(vaddr, mesh_size, 1, fp);
fclose(fp);
CVI_SYS_IonFlushCache(paddr, vaddr, mesh_size);
*pu64PhyAddr = paddr;
*ppVirAddr = vaddr;
return CVI_SUCCESS;
}
CVI_S32 CVI_GDC_SetBufWrapAttr(GDC_HANDLE hHandle, const GDC_TASK_ATTR_S *pstTask, const DWA_BUF_WRAP_S *pstBufWrap)
{
struct dwa_buf_wrap_cfg *cfg;
struct vdev *d;
CVI_S32 s32Ret;
d = get_dev_info(VDEV_TYPE_DWA, 0);
if (!IS_VDEV_OPEN(d->state)) {
CVI_TRACE_GDC(CVI_DBG_ERR, "gdc state(%d) incorrect.", d->state);
return CVI_ERR_GDC_SYS_NOTREADY;
}
cfg = malloc(sizeof(*cfg));
if (!cfg) {
CVI_TRACE_GDC(CVI_DBG_ERR, "gdc malloc fails.\n");
return CVI_FAILURE;
}
memset(cfg, 0, sizeof(*cfg));
cfg->handle = hHandle;
memcpy(&cfg->stTask.stImgIn, &pstTask->stImgIn, sizeof(cfg->stTask.stImgIn));
memcpy(&cfg->stTask.stImgOut, &pstTask->stImgOut, sizeof(cfg->stTask.stImgOut));
memcpy(&cfg->stBufWrap, pstBufWrap, sizeof(cfg->stBufWrap));
s32Ret = gdc_set_chn_buf_wrap(d->fd, cfg);
free(cfg);
return s32Ret;
}
CVI_S32 CVI_GDC_GetBufWrapAttr(GDC_HANDLE hHandle, const GDC_TASK_ATTR_S *pstTask, DWA_BUF_WRAP_S *pstBufWrap)
{
struct dwa_buf_wrap_cfg *cfg;
struct vdev *d;
CVI_S32 s32Ret;
d = get_dev_info(VDEV_TYPE_DWA, 0);
if (!IS_VDEV_OPEN(d->state)) {
CVI_TRACE_GDC(CVI_DBG_ERR, "gdc state(%d) incorrect.", d->state);
return CVI_ERR_GDC_SYS_NOTREADY;
}
cfg = malloc(sizeof(*cfg));
if (!cfg) {
CVI_TRACE_GDC(CVI_DBG_ERR, "gdc malloc fails.\n");
return CVI_FAILURE;
}
memset(cfg, 0, sizeof(*cfg));
cfg->handle = hHandle;
memcpy(&cfg->stTask, pstTask, sizeof(cfg->stTask));
s32Ret = gdc_get_chn_buf_wrap(d->fd, cfg);
free(cfg);
if (s32Ret == CVI_SUCCESS)
memcpy(pstBufWrap, &cfg->stBufWrap, sizeof(*pstBufWrap));
return s32Ret;
}
CVI_S32 CVI_GDC_DumpMesh(MESH_DUMP_ATTR_S *pMeshDumpAttr)
{
MOD_CHECK_NULL_PTR(CVI_ID_GDC, pMeshDumpAttr);
CVI_U64 phyMesh;
CVI_VOID *virMesh;
CVI_U32 u32Width, u32Height, vpssGrp, vpssChn, viChn;
SIZE_S in_size, out_size;
CVI_U32 mesh_1st_size, mesh_2nd_size, meshSize;
CVI_S32 s32Ret;
CVI_S32 fd;
struct vpss_chn_attr attr;
FILE *fp;
MOD_ID_E mod = pMeshDumpAttr->enModId;
CVI_CHAR *filePath = pMeshDumpAttr->binFileName;
switch (mod) {
case CVI_ID_VI:
viChn = pMeshDumpAttr->viMeshAttr.chn;
phyMesh = g_vi_mesh[viChn].paddr;
virMesh = g_vi_mesh[viChn].vaddr;
u32Width = gViCtx->chnAttr[viChn].stSize.u32Width;
u32Height = gViCtx->chnAttr[viChn].stSize.u32Height;
in_size.u32Width = ALIGN(u32Width, DEFAULT_ALIGN);
in_size.u32Height = ALIGN(u32Height, DEFAULT_ALIGN);
out_size.u32Width = in_size.u32Width;
out_size.u32Height = in_size.u32Height;
mesh_gen_get_size(in_size, out_size, &mesh_1st_size, &mesh_2nd_size);
meshSize = mesh_1st_size + mesh_2nd_size;
break;
case CVI_ID_VPSS:
fd = get_vpss_fd();
attr.VpssGrp = vpssGrp = pMeshDumpAttr->vpssMeshAttr.grp;
attr.VpssChn = vpssChn = pMeshDumpAttr->vpssMeshAttr.chn;
phyMesh = mesh[vpssGrp][vpssChn].paddr;
virMesh = mesh[vpssGrp][vpssChn].vaddr;
s32Ret = vpss_get_chn_attr(fd, &attr);
if (s32Ret != CVI_SUCCESS) {
CVI_TRACE_GDC(CVI_DBG_ERR, "Grp(%d) Chn(%d) get chn attr fail\n", vpssGrp, vpssChn);
return s32Ret;
}
u32Width = attr.stChnAttr.u32Width;
u32Height = attr.stChnAttr.u32Height;
in_size.u32Width = ALIGN(u32Width, DEFAULT_ALIGN);
in_size.u32Height = ALIGN(u32Height, DEFAULT_ALIGN);
out_size.u32Width = in_size.u32Width;
out_size.u32Height = in_size.u32Height;
mesh_gen_get_size(in_size, out_size, &mesh_1st_size, &mesh_2nd_size);
meshSize = mesh_1st_size + mesh_2nd_size;
break;
default:
CVI_TRACE_GDC(CVI_DBG_ERR, "not supported\n");
return CVI_ERR_GDC_NOT_SUPPORT;
}
CVI_TRACE_GDC(CVI_DBG_DEBUG, "dump mesh size:%d, mesh phy addr:%#"PRIx64", vir addr:%p.\n",
meshSize, phyMesh, virMesh);
fp = fopen(filePath, "wb");
if (!fp) {
CVI_TRACE_GDC(CVI_DBG_ERR, "open file:%s failed.\n", filePath);
return CVI_ERR_GDC_ILLEGAL_PARAM;
}
fwrite(virMesh, meshSize, 1, fp);
fflush(fp);
fclose(fp);
return CVI_SUCCESS;
}
CVI_S32 CVI_GDC_LoadMesh(MESH_DUMP_ATTR_S *pMeshDumpAttr)
{
MOD_CHECK_NULL_PTR(CVI_ID_GDC, pMeshDumpAttr);
CVI_U64 phyMesh;
CVI_VOID *virMesh;
CVI_U32 vpssGrp = 0, vpssChn = 0, viChn = 0;
SIZE_S in_size, out_size;
CVI_U32 mesh_1st_size, mesh_2nd_size, mesh_size;
CVI_U32 u32Width, u32Height;
struct cvi_gdc_mesh *pmesh;
FILE *fp;
CVI_S32 fd;
MOD_ID_E mod = pMeshDumpAttr->enModId;
CVI_CHAR *filePath = pMeshDumpAttr->binFileName;
CVI_S32 s32Ret;
struct vpss_chn_attr attr;
switch (mod) {
case CVI_ID_VI:
viChn = pMeshDumpAttr->viMeshAttr.chn;
pmesh = &g_vi_mesh[viChn];
u32Width = gViCtx->chnAttr[viChn].stSize.u32Width;
u32Height = gViCtx->chnAttr[viChn].stSize.u32Height;
in_size.u32Width = ALIGN(u32Width, DEFAULT_ALIGN);
in_size.u32Height = ALIGN(u32Height, DEFAULT_ALIGN);
break;
case CVI_ID_VPSS:
fd = get_vpss_fd();
attr.VpssGrp = vpssGrp = pMeshDumpAttr->vpssMeshAttr.grp;
attr.VpssChn = vpssChn = pMeshDumpAttr->vpssMeshAttr.chn;
pmesh = &mesh[vpssGrp][vpssChn];
s32Ret = vpss_get_chn_attr(fd, &attr);
if (s32Ret != CVI_SUCCESS) {
CVI_TRACE_GDC(CVI_DBG_ERR, "Grp(%d) Chn(%d) get chn attr fail\n", vpssGrp, vpssChn);
return s32Ret;
}
u32Width = attr.stChnAttr.u32Width;
u32Height = attr.stChnAttr.u32Height;
in_size.u32Width = ALIGN(u32Width, DEFAULT_ALIGN);
in_size.u32Height = ALIGN(u32Height, DEFAULT_ALIGN);
break;
default:
CVI_TRACE_GDC(CVI_DBG_ERR, "not supported\n");
return CVI_ERR_GDC_NOT_SUPPORT;
}
out_size.u32Width = in_size.u32Width;
out_size.u32Height = in_size.u32Height;
mesh_gen_get_size(in_size, out_size, &mesh_1st_size, &mesh_2nd_size);
mesh_size = mesh_1st_size + mesh_2nd_size;
fp = fopen(filePath, "rb");
if (!fp) {
CVI_TRACE_GDC(CVI_DBG_ERR, "open file:%s failed.\n", filePath);
return CVI_ERR_GDC_ILLEGAL_PARAM;
}
fseek(fp, 0, SEEK_END);
int fileSize = ftell(fp);
if (mesh_size != (CVI_U32)fileSize) {
CVI_TRACE_GDC(CVI_DBG_ERR, "loadmesh file:(%s) size is not match.\n", filePath);
fclose(fp);
return CVI_FAILURE;
}
rewind(fp);
// acquire memory space for mesh.
if (CVI_SYS_IonAlloc_Cached(&phyMesh, &virMesh, "gdc_mesh", mesh_size) != CVI_SUCCESS) {
CVI_TRACE_GDC(CVI_DBG_ERR, "Can't acquire memory for gdc mesh.\n");
fclose(fp);
return CVI_ERR_VPSS_NOMEM;
}
CVI_TRACE_GDC(CVI_DBG_DEBUG, "load mesh size:%d, mesh phy addr:%#"PRIx64", vir addr:%p.\n",
mesh_size, phyMesh, virMesh);
pmesh->paddr = phyMesh;
pmesh->vaddr = virMesh;
fread(virMesh, mesh_size, 1, fp);
CVI_SYS_IonFlushCache(phyMesh, virMesh, mesh_size);
switch (mod) {
case CVI_ID_VI:
g_vi_mesh[viChn].meshSize = mesh_size;
//vi_ctx.stLDCAttr[viChn].bEnable = CVI_TRUE;
fd = get_vi_fd();
struct vi_chn_ldc_cfg vi_cfg;
vi_cfg.ViChn = viChn;
vi_cfg.enRotation = ROTATION_0;
//vi_cfg.stLDCAttr = *pstLDCAttr;
vi_cfg.stLDCAttr.bEnable = CVI_TRUE;
vi_cfg.meshHandle = pmesh->paddr;
if (vi_sdk_set_chn_ldc(fd, &vi_cfg) != CVI_SUCCESS) {
CVI_TRACE_GDC(CVI_DBG_ERR, "VI Set Chn(%d) LDC fail\n", viChn);
fclose(fp);
return CVI_FAILURE;
}
break;
case CVI_ID_VPSS:
mesh[vpssGrp][vpssChn].meshSize = mesh_size;
//vpssCtx[vpssGrp].stChnCfgs[vpssChn].stLDCAttr.bEnable = CVI_TRUE;
fd = get_vpss_fd();
struct vpss_chn_ldc_cfg vpss_cfg;
vpss_cfg.VpssGrp = vpssGrp;
vpss_cfg.VpssChn = vpssChn;
vpss_cfg.enRotation = ROTATION_0;
//vpss_cfg.stLDCAttr = *pstLDCAttr;
vpss_cfg.stLDCAttr.bEnable = CVI_TRUE;
vpss_cfg.meshHandle = pmesh->paddr;
if (vpss_set_chn_ldc(fd, &vpss_cfg) != CVI_SUCCESS) {
CVI_TRACE_GDC(CVI_DBG_ERR, "VPSS Set Chn(%d) LDC fail\n", vpssChn);
fclose(fp);
return CVI_FAILURE;
}
break;
default:
CVI_TRACE_GDC(CVI_DBG_ERR, "not supported\n");
fclose(fp);
return CVI_ERR_GDC_NOT_SUPPORT;
}
fclose(fp);
return CVI_SUCCESS;
}

View File

@@ -0,0 +1,319 @@
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/queue.h>
#include <pthread.h>
#include <stdatomic.h>
#include <inttypes.h>
#include <fcntl.h> /* low-level i/o */
#include <unistd.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include "cvi_base.h"
#include <linux/cvi_math.h>
#include "cvi_sys.h"
#include "cvi_vpss.h"
#include "cvi_vo.h"
#include "cvi_region.h"
#include "hashmap.h"
#include "rgn_ioctl.h"
struct rgn_canvas {
STAILQ_ENTRY(rgn_canvas) stailq;
RGN_HANDLE Handle;
CVI_U64 u64PhyAddr;
CVI_U8 *pu8VirtAddr;
CVI_U32 u32Size;
};
static pthread_once_t once = PTHREAD_ONCE_INIT;
static pthread_mutex_t canvas_q_lock = PTHREAD_MUTEX_INITIALIZER;
STAILQ_HEAD(rgn_canvas_q, rgn_canvas) canvas_q;
static void rgn_init(void)
{
STAILQ_INIT(&canvas_q);
}
/**************************************************************************
* Public APIs.
**************************************************************************/
CVI_S32 CVI_RGN_Create(RGN_HANDLE Handle, const RGN_ATTR_S *pstRegion)
{
CVI_S32 fd = -1;
MOD_CHECK_NULL_PTR(CVI_ID_RGN, pstRegion);
// Driver control
fd = get_rgn_fd();
if (rgn_create(fd, Handle, pstRegion) != CVI_SUCCESS) {
CVI_TRACE_RGN(CVI_DBG_INFO, "Create RGN fail.\n");
return CVI_FAILURE;
}
pthread_mutex_lock(&canvas_q_lock);
pthread_once(&once, rgn_init);
pthread_mutex_unlock(&canvas_q_lock);
return CVI_SUCCESS;
}
CVI_S32 CVI_RGN_Destroy(RGN_HANDLE Handle)
{
CVI_S32 fd = -1;
// Driver control
fd = get_rgn_fd();
if (rgn_destroy(fd, Handle) != CVI_SUCCESS) {
CVI_TRACE_RGN(CVI_DBG_INFO, "Destroy RGN fail.\n");
return CVI_FAILURE;
}
return CVI_SUCCESS;
}
CVI_S32 CVI_RGN_GetAttr(RGN_HANDLE Handle, RGN_ATTR_S *pstRegion)
{
CVI_S32 fd = -1;
MOD_CHECK_NULL_PTR(CVI_ID_RGN, pstRegion);
// Driver control
fd = get_rgn_fd();
if (rgn_get_attr(fd, Handle, pstRegion) != CVI_SUCCESS) {
CVI_TRACE_RGN(CVI_DBG_INFO, "Get RGN attributes fail.\n");
return CVI_FAILURE;
}
return CVI_SUCCESS;
}
CVI_S32 CVI_RGN_SetAttr(RGN_HANDLE Handle, const RGN_ATTR_S *pstRegion)
{
CVI_S32 fd = -1;
MOD_CHECK_NULL_PTR(CVI_ID_RGN, pstRegion);
// Driver control
fd = get_rgn_fd();
if (rgn_set_attr(fd, Handle, pstRegion) != CVI_SUCCESS) {
CVI_TRACE_RGN(CVI_DBG_INFO, "Set RGN attributes fail.\n");
return CVI_FAILURE;
}
return CVI_SUCCESS;
}
CVI_S32 CVI_RGN_SetBitMap(RGN_HANDLE Handle, const BITMAP_S *pstBitmap)
{
CVI_S32 fd = -1;
CVI_S32 s32Ret;
MOD_CHECK_NULL_PTR(CVI_ID_RGN, pstBitmap);
// Driver control
fd = get_rgn_fd();
s32Ret = rgn_set_bit_map(fd, Handle, pstBitmap);
if (s32Ret != CVI_SUCCESS) {
CVI_TRACE_RGN(CVI_DBG_INFO, "Set RGN Bitmap fail, s32Ret=%x.\n", s32Ret);
return s32Ret;
}
return CVI_SUCCESS;
}
CVI_S32 CVI_RGN_AttachToChn(RGN_HANDLE Handle, const MMF_CHN_S *pstChn, const RGN_CHN_ATTR_S *pstChnAttr)
{
CVI_S32 fd = -1;
MOD_CHECK_NULL_PTR(CVI_ID_RGN, pstChn);
MOD_CHECK_NULL_PTR(CVI_ID_RGN, pstChnAttr);
#ifdef __SOC_PHOBOS__
if (pstChn->enModId == CVI_ID_VO) {
CVI_TRACE_RGN(CVI_DBG_ERR, "No vo device, cannot attach to vo!\n");
return CVI_ERR_RGN_ILLEGAL_PARAM;
}
#endif
// Driver control
fd = get_rgn_fd();
if (rgn_attach_to_chn(fd, Handle, pstChn, pstChnAttr) != CVI_SUCCESS) {
CVI_TRACE_RGN(CVI_DBG_INFO, "Attach RGN to channel fail.\n");
return CVI_FAILURE;
}
return CVI_SUCCESS;
}
CVI_S32 CVI_RGN_DetachFromChn(RGN_HANDLE Handle, const MMF_CHN_S *pstChn)
{
CVI_S32 fd = -1;
MOD_CHECK_NULL_PTR(CVI_ID_RGN, pstChn);
#ifdef __SOC_PHOBOS__
if (pstChn->enModId == CVI_ID_VO) {
CVI_TRACE_RGN(CVI_DBG_ERR, "No vo device, cannot detach from vo!\n");
return CVI_ERR_RGN_ILLEGAL_PARAM;
}
#endif
// Driver control
fd = get_rgn_fd();
if (rgn_detach_from_chn(fd, Handle, pstChn) != CVI_SUCCESS) {
CVI_TRACE_RGN(CVI_DBG_INFO, "Detach RGN from channel fail.\n");
return CVI_FAILURE;
}
return CVI_SUCCESS;
}
CVI_S32 CVI_RGN_SetDisplayAttr(RGN_HANDLE Handle, const MMF_CHN_S *pstChn, const RGN_CHN_ATTR_S *pstChnAttr)
{
CVI_S32 fd = -1;
MOD_CHECK_NULL_PTR(CVI_ID_RGN, pstChn);
MOD_CHECK_NULL_PTR(CVI_ID_RGN, pstChnAttr);
// Driver control
fd = get_rgn_fd();
if (rgn_set_display_attr(fd, Handle, pstChn, pstChnAttr) != CVI_SUCCESS) {
CVI_TRACE_RGN(CVI_DBG_INFO, "Set display RGN attributes fail.\n");
return CVI_FAILURE;
}
return CVI_SUCCESS;
}
CVI_S32 CVI_RGN_GetDisplayAttr(RGN_HANDLE Handle, const MMF_CHN_S *pstChn, RGN_CHN_ATTR_S *pstChnAttr)
{
CVI_S32 fd = -1;
MOD_CHECK_NULL_PTR(CVI_ID_RGN, pstChn);
MOD_CHECK_NULL_PTR(CVI_ID_RGN, pstChnAttr);
// Driver control
fd = get_rgn_fd();
if (rgn_get_display_attr(fd, Handle, pstChn, pstChnAttr) != CVI_SUCCESS) {
CVI_TRACE_RGN(CVI_DBG_INFO, "Get display RGN attributes fail.\n");
return CVI_FAILURE;
}
return CVI_SUCCESS;
}
CVI_S32 CVI_RGN_GetCanvasInfo(RGN_HANDLE Handle, RGN_CANVAS_INFO_S *pstCanvasInfo)
{
CVI_S32 fd = -1;
CVI_S32 s32Ret;
struct rgn_canvas *canvas;
MOD_CHECK_NULL_PTR(CVI_ID_RGN, pstCanvasInfo);
// Driver control
fd = get_rgn_fd();
s32Ret = rgn_get_canvas_info(fd, Handle, pstCanvasInfo);
if (s32Ret != CVI_SUCCESS) {
CVI_TRACE_RGN(CVI_DBG_INFO, "Get RGN canvas information fail, s32Ret=%x.\n", s32Ret);
return s32Ret;
}
canvas = calloc(1, sizeof(struct rgn_canvas));
if (!canvas) {
CVI_TRACE_RGN(CVI_DBG_ERR, "malloc failed.\n");
return CVI_ERR_RGN_NOMEM;
}
pthread_mutex_lock(&canvas_q_lock);
canvas->u64PhyAddr = pstCanvasInfo->u64PhyAddr;
canvas->u32Size = pstCanvasInfo->u32Stride * pstCanvasInfo->stSize.u32Height;
pstCanvasInfo->pu8VirtAddr = canvas->pu8VirtAddr =
CVI_SYS_Mmap(pstCanvasInfo->u64PhyAddr, canvas->u32Size);
if (pstCanvasInfo->pu8VirtAddr == NULL) {
free(canvas);
CVI_TRACE_RGN(CVI_DBG_INFO, "CVI_SYS_Mmap NG.\n");
return CVI_FAILURE;
}
canvas->Handle = Handle;
pstCanvasInfo->pstCanvasCmprAttr = (RGN_CANVAS_CMPR_ATTR_S *)pstCanvasInfo->pu8VirtAddr;
pstCanvasInfo->pstObjAttr = (RGN_CMPR_OBJ_ATTR_S *)(pstCanvasInfo->pu8VirtAddr +
sizeof(RGN_CANVAS_CMPR_ATTR_S));
STAILQ_INSERT_TAIL(&canvas_q, canvas, stailq);
pthread_mutex_unlock(&canvas_q_lock);
return CVI_SUCCESS;
}
CVI_S32 CVI_RGN_UpdateCanvas(RGN_HANDLE Handle)
{
CVI_S32 fd = -1;
struct rgn_canvas *canvas;
// Driver control
fd = get_rgn_fd();
if (rgn_update_canvas(fd, Handle) != CVI_SUCCESS) {
CVI_TRACE_RGN(CVI_DBG_INFO, "Update RGN canvas fail.\n");
return CVI_FAILURE;
}
pthread_mutex_lock(&canvas_q_lock);
if (!STAILQ_EMPTY(&canvas_q)) {
STAILQ_FOREACH(canvas, &canvas_q, stailq) {
if (canvas->Handle == Handle) {
STAILQ_REMOVE(&canvas_q, canvas, rgn_canvas, stailq);
CVI_SYS_Munmap(canvas->pu8VirtAddr, canvas->u32Size);
free(canvas);
break;
}
}
}
pthread_mutex_unlock(&canvas_q_lock);
return CVI_SUCCESS;
}
/* CVI_RGN_Invert_Color - invert color per luma statistics of video content
* Chns' pixel-format should be YUV.
* RGN's pixel-format should be ARGB1555.
*
* @param Handle: RGN Handle
* @param pstChn: the chn which rgn attached
* @param pu32Color: rgn's content
*/
CVI_S32 CVI_RGN_Invert_Color(RGN_HANDLE Handle, MMF_CHN_S *pstChn, CVI_U32 *pu32Color)
{
CVI_S32 fd = -1;
MOD_CHECK_NULL_PTR(CVI_ID_RGN, pstChn);
MOD_CHECK_NULL_PTR(CVI_ID_RGN, pu32Color);
// Driver control
fd = get_rgn_fd();
if (rgn_invert_color(fd, Handle, pstChn, (void *)pu32Color) != CVI_SUCCESS) {
CVI_TRACE_RGN(CVI_DBG_INFO, "Invert RGN color fail.\n");
return CVI_FAILURE;
}
return CVI_SUCCESS;
}
CVI_S32 CVI_RGN_SetChnPalette(RGN_HANDLE Handle, const MMF_CHN_S *pstChn, RGN_PALETTE_S *pstPalette)
{
struct vdev *d;
// Driver control
d = get_dev_info(VDEV_TYPE_RGN, 0);
if (!IS_VDEV_OPEN(d->state)) {
CVI_TRACE_RGN(CVI_DBG_ERR, "rgn state(%d) incorrect.", d->state);
return CVI_ERR_RGN_SYS_NOTREADY;
}
if (rgn_set_chn_palette(d->fd, Handle, pstChn, pstPalette) != CVI_SUCCESS) {
CVI_TRACE_RGN(CVI_DBG_INFO, "Invert RGN color fail.\n");
return CVI_FAILURE;
}
return CVI_SUCCESS;
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,41 @@
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include <errno.h>
#include "dwa_ioctl.h"
CVI_S32 gdc_begin_job(CVI_S32 fd, struct gdc_handle_data *cfg)
{
return ioctl(fd, CVI_DWA_BEGIN_JOB, cfg);
}
CVI_S32 gdc_end_job(CVI_S32 fd, struct gdc_handle_data *cfg)
{
return ioctl(fd, CVI_DWA_END_JOB, cfg);
}
CVI_S32 gdc_cancel_job(CVI_S32 fd, struct gdc_handle_data *cfg)
{
return ioctl(fd, CVI_DWA_CANCEL_JOB, cfg);
}
CVI_S32 gdc_add_rotation_task(CVI_S32 fd, struct gdc_task_attr *attr)
{
return ioctl(fd, CVI_DWA_ADD_ROT_TASK, attr);
}
CVI_S32 gdc_add_ldc_task(CVI_S32 fd, struct gdc_task_attr *attr)
{
return ioctl(fd, CVI_DWA_ADD_LDC_TASK, attr);
}
CVI_S32 gdc_set_chn_buf_wrap(CVI_S32 fd, const struct dwa_buf_wrap_cfg *cfg)
{
return ioctl(fd, CVI_DWA_SET_BUF_WRAP, cfg);
}
CVI_S32 gdc_get_chn_buf_wrap(CVI_S32 fd, struct dwa_buf_wrap_cfg *cfg)
{
return ioctl(fd, CVI_DWA_GET_BUF_WRAP, cfg);
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,137 @@
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <pthread.h>
#include <fcntl.h> /* low-level i/o */
#include <unistd.h>
#include <errno.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <linux/cvi_comm_video.h>
#include "rgn_ioctl.h"
#include <linux/rgn_uapi.h>
static inline CVI_S32 S_CTRL_PTR(int _fd, void *_cfg, int _ioctl, CVI_U32 _handle)
{
struct rgn_ext_control ec1;
memset(&ec1, 0, sizeof(ec1));
ec1.id = _ioctl;
ec1.handle = _handle;
ec1.ptr1 = (void *) _cfg;
if (ioctl(_fd, RGN_IOC_S_CTRL, &ec1) < 0) {
fprintf(stderr, "RGN_IOC_S_CTRL - %s NG, %s\n", __func__, strerror(errno));
return -1;
}
return 0;
}
static inline CVI_S32 SDK_CTRL_GET_CFG(int _fd, void *_cfg1, void *_cfg2, int _ioctl, CVI_U32 _handle)
{
struct rgn_ext_control ec1;
memset(&ec1, 0, sizeof(ec1));
ec1.id = RGN_IOCTL_SDK_CTRL;
ec1.sdk_id = _ioctl;
ec1.handle = _handle;
ec1.ptr1 = _cfg1;
ec1.ptr2 = _cfg2;
if (ioctl(_fd, RGN_IOC_G_CTRL, &ec1) < 0) {
fprintf(stderr, "RGN_SDK_IOC_G_CTRL(%d-%d) - %s NG, %s\n",
ec1.id, ec1.sdk_id, __func__, strerror(errno));
return -1;
}
return 0;
}
static inline CVI_S32 SDK_CTRL_SET_CFG(int _fd, void *_cfg1, void *_cfg2, int _ioctl, CVI_U32 _handle)
{
struct rgn_ext_control ec1;
memset(&ec1, 0, sizeof(ec1));
ec1.id = RGN_IOCTL_SDK_CTRL;
ec1.sdk_id = _ioctl;
ec1.handle = _handle;
ec1.ptr1 = _cfg1;
ec1.ptr2 = _cfg2;
if (ioctl(_fd, RGN_IOC_S_CTRL, &ec1) < 0) {
fprintf(stderr, "RGN_SDK_IOC_S_CTRL(%d-%d) - %s NG, %s\n",
ec1.id, ec1.sdk_id, __func__, strerror(errno));
return -1;
}
return 0;
}
int rgn_create(int fd, int Handle, const RGN_ATTR_S *pstRegion)
{
return SDK_CTRL_SET_CFG(fd, (void *)pstRegion, NULL, RGN_SDK_CREATE, Handle);
}
int rgn_destroy(int fd, int Handle)
{
return SDK_CTRL_SET_CFG(fd, NULL, NULL, RGN_SDK_DESTORY, Handle);
}
int rgn_get_attr(int fd, int Handle, RGN_ATTR_S *pstRegion)
{
return SDK_CTRL_GET_CFG(fd, (void *)pstRegion, NULL, RGN_SDK_GET_ATTR, Handle);
}
int rgn_set_attr(int fd, int Handle, const RGN_ATTR_S *pstRegion)
{
return SDK_CTRL_SET_CFG(fd, (void *)pstRegion, NULL, RGN_SDK_SET_ATTR, Handle);
}
int rgn_set_bit_map(int fd, int Handle, const BITMAP_S *pstBitmap)
{
return SDK_CTRL_SET_CFG(fd, (void *)pstBitmap, NULL, RGN_SDK_SET_BIT_MAP, Handle);
}
int rgn_attach_to_chn(int fd, int Handle, const MMF_CHN_S *pstChn, const RGN_CHN_ATTR_S *pstChnAttr)
{
return SDK_CTRL_SET_CFG(fd, (void *)pstChn, (void *)pstChnAttr, RGN_SDK_ATTACH_TO_CHN, Handle);
}
int rgn_detach_from_chn(int fd, int Handle, const MMF_CHN_S *pstChn)
{
return SDK_CTRL_SET_CFG(fd, (void *)pstChn, NULL, RGN_SDK_DETACH_FROM_CHN, Handle);
}
int rgn_set_display_attr(int fd, int Handle, const MMF_CHN_S *pstChn, const RGN_CHN_ATTR_S *pstChnAttr)
{
return SDK_CTRL_SET_CFG(fd, (void *)pstChn, (void *)pstChnAttr, RGN_SDK_SET_DISPLAY_ATTR, Handle);
}
int rgn_get_display_attr(int fd, int Handle, const MMF_CHN_S *pstChn, RGN_CHN_ATTR_S *pstChnAttr)
{
return SDK_CTRL_GET_CFG(fd, (void *)pstChn, pstChnAttr, RGN_SDK_GET_DISPLAY_ATTR, Handle);
}
int rgn_get_canvas_info(int fd, int Handle, RGN_CANVAS_INFO_S *pstCanvasInfo)
{
return SDK_CTRL_GET_CFG(fd, (void *)pstCanvasInfo, NULL, RGN_SDK_GET_CANVAS_INFO, Handle);
}
int rgn_update_canvas(int fd, int Handle)
{
return SDK_CTRL_SET_CFG(fd, NULL, NULL, RGN_SDK_UPDATE_CANVAS, Handle);
}
int rgn_invert_color(int fd, int Handle, MMF_CHN_S *pstChn, void *pu32Color)
{
return SDK_CTRL_SET_CFG(fd, (void *)pstChn, pu32Color, RGN_SDK_INVERT_COLOR, Handle);
}
int rgn_set_chn_palette(int fd, int Handle, const MMF_CHN_S *pstChn, RGN_PALETTE_S *pstPalette)
{
return SDK_CTRL_SET_CFG(fd, (void *)pstChn, (void *)pstPalette, RGN_SDK_SET_CHN_PALETTE, Handle);
}

View File

@@ -0,0 +1,405 @@
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <pthread.h>
#include <fcntl.h> /* low-level i/o */
#include <unistd.h>
#include <errno.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <linux/cvi_comm_video.h>
#include <linux/cvi_comm_vo.h>
#include "vi_ioctl.h"
#include <linux/vi_uapi.h>
#define S_CTRL_VALUE(_fd, _cfg, _ioctl)\
do {\
struct vi_ext_control ec1;\
memset(&ec1, 0, sizeof(ec1));\
ec1.id = _ioctl;\
ec1.value = _cfg;\
if (ioctl(_fd, VI_IOC_S_CTRL, &ec1) < 0) {\
fprintf(stderr, "VI_IOC_S_CTRL - %s NG, %s\n", __func__, strerror(errno));\
return -1;\
} \
return 0;\
} while (0)
#define S_CTRL_VALUE64(_fd, _cfg, _ioctl)\
do {\
struct vi_ext_control ec1;\
memset(&ec1, 0, sizeof(ec1));\
ec1.id = _ioctl;\
ec1.value64 = _cfg;\
if (ioctl(_fd, VI_IOC_S_CTRL, &ec1) < 0) {\
fprintf(stderr, "VI_IOC_S_CTRL - %s NG, %s\n", __func__, strerror(errno));\
return -1;\
} \
return 0;\
} while (0)
#define S_CTRL_PTR(_fd, _cfg, _ioctl)\
do {\
struct vi_ext_control ec1;\
memset(&ec1, 0, sizeof(ec1));\
ec1.id = _ioctl;\
ec1.ptr = (void *)_cfg;\
if (ioctl(_fd, VI_IOC_S_CTRL, &ec1) < 0) {\
fprintf(stderr, "VI_IOC_S_CTRL - %s NG, %s\n", __func__, strerror(errno));\
return -1;\
} \
return 0;\
} while (0)
#define G_CTRL_VALUE(_fd, _out, _ioctl)\
do {\
struct vi_ext_control ec1;\
memset(&ec1, 0, sizeof(ec1));\
ec1.id = _ioctl;\
ec1.value = 0;\
if (ioctl(_fd, VI_IOC_G_CTRL, &ec1) < 0) {\
fprintf(stderr, "VI_IOC_G_CTRL - %s NG, %s\n", __func__, strerror(errno));\
return -1;\
} \
*_out = ec1.value;\
return 0;\
} while (0)
#define G_CTRL_PTR(_fd, _cfg, _ioctl)\
do {\
struct vi_ext_control ec1;\
memset(&ec1, 0, sizeof(ec1));\
ec1.id = _ioctl;\
ec1.ptr = (void *)_cfg;\
if (ioctl(_fd, VI_IOC_G_CTRL, &ec1) < 0) {\
fprintf(stderr, "VI_IOC_G_CTRL - %s NG, %s\n", __func__, strerror(errno));\
return -1;\
} \
return 0;\
} while (0)
#define SDK_CTRL_SET_CFG(_fd, _cfg, _ioctl, _dev, _pipe, _chn, _val)\
do {\
struct vi_ext_control ec1;\
memset(&ec1, 0, sizeof(ec1));\
ec1.id = VI_IOCTL_SDK_CTRL;\
ec1.sdk_id = _ioctl;\
ec1.sdk_cfg.dev = _dev;\
ec1.sdk_cfg.pipe = _pipe;\
ec1.sdk_cfg.chn = _chn;\
ec1.sdk_cfg.val = _val;\
ec1.sdk_cfg.ptr = (void *)_cfg;\
if (ioctl(_fd, VI_IOC_S_CTRL, &ec1) < 0) {\
fprintf(stderr, "VI_SDK_IOC_S_CTRL - %s NG, %s\n", __func__, strerror(errno));\
return -1;\
} \
return 0;\
} while (0)
int vi_enable_usr_pic(int fd, bool enable)
{
S_CTRL_VALUE(fd, enable, VI_IOCTL_USR_PIC_ONOFF);
}
int vi_set_usr_pic(int fd, struct cvi_isp_usr_pic_cfg *cfg)
{
S_CTRL_PTR(fd, cfg, VI_IOCTL_USR_PIC_CFG);
}
int vi_put_usr_pic(int fd, CVI_U64 phyAddr)
{
S_CTRL_VALUE64(fd, phyAddr, VI_IOCTL_USR_PIC_PUT);
}
int vi_set_usr_pic_timing(int fd, CVI_U32 fps)
{
S_CTRL_VALUE(fd, fps, VI_IOCTL_USR_PIC_TIMING);
}
int vi_set_be_online(int fd, CVI_BOOL online)
{
S_CTRL_VALUE(fd, online, VI_IOCTL_BE_ONLINE);
}
int vi_set_online(int fd, CVI_BOOL online)
{
S_CTRL_VALUE(fd, online, VI_IOCTL_ONLINE);
}
int vi_set_hdr(int fd, CVI_BOOL is_hdr_on)
{
S_CTRL_VALUE(fd, is_hdr_on, VI_IOCTL_HDR);
}
int vi_set_3dnr(int fd, CVI_BOOL is_3dnr_on)
{
S_CTRL_VALUE(fd, is_3dnr_on, VI_IOCTL_3DNR);
}
int vi_get_pipe_dump(int fd, struct cvi_vip_isp_raw_blk *raw_dump)
{
G_CTRL_PTR(fd, raw_dump, VI_IOCTL_GET_PIPE_DUMP);
}
int vi_put_pipe_dump(int fd, CVI_U32 dev_num)
{
S_CTRL_VALUE(fd, dev_num, VI_IOCTL_PUT_PIPE_DUMP);
}
int vi_set_yuv_bypass_path(int fd, struct cvi_vip_isp_yuv_param *param)
{
S_CTRL_PTR(fd, param, VI_IOCTL_YUV_BYPASS_PATH);
}
int vi_set_compress_mode(int fd, CVI_BOOL is_compress_on)
{
S_CTRL_VALUE(fd, is_compress_on, VI_IOCTL_COMPRESS_EN);
}
int vi_set_lvds_flow(int fd, CVI_BOOL is_lvds_flow_on)
{
S_CTRL_VALUE(fd, is_lvds_flow_on, VI_IOCTL_SUBLVDS_PATH);
}
int vi_set_clk(int fd, CVI_BOOL clk_on)
{
S_CTRL_VALUE(fd, clk_on, VI_IOCTL_CLK_CTRL);
}
#ifdef ARCH_CV182X
int vi_set_rgbir(int fd, CVI_BOOL is_rgbir)
{
S_CTRL_VALUE(fd, is_rgbir, VI_IOCTL_RGBIR);
}
#endif
int vi_get_ip_dump_list(int fd, struct ip_info *ip_info_list)
{
G_CTRL_PTR(fd, ip_info_list, VI_IOCTL_GET_IP_INFO);
}
int vi_set_trig_preraw(int fd, CVI_U32 dev_num)
{
S_CTRL_VALUE(fd, dev_num, VI_IOCTL_TRIG_PRERAW);
}
int vi_set_online2sc(int fd, struct cvi_isp_sc_online *online)
{
S_CTRL_PTR(fd, online, VI_IOCTL_SC_ONLINE);
}
int vi_get_tun_addr(int fd, struct isp_tuning_cfg *tun_buf_info)
{
G_CTRL_PTR(fd, tun_buf_info, VI_IOCTL_GET_TUN_ADDR);
}
int vi_get_rgbmap_le_buf(int fd, struct cvi_vip_memblock *buf)
{
G_CTRL_PTR(fd, buf, VI_IOCTL_GET_RGBMAP_LE_PHY_BUF);
}
int vi_get_rgbmap_se_buf(int fd, struct cvi_vip_memblock *buf)
{
G_CTRL_PTR(fd, buf, VI_IOCTL_GET_RGBMAP_SE_PHY_BUF);
}
int vi_get_dma_size(int fd, CVI_U32 *size)
{
G_CTRL_VALUE(fd, size, VI_IOCTL_GET_BUF_SIZE);
}
int vi_set_dma_buf_info(int fd, struct cvi_vi_dma_buf_info *param)
{
S_CTRL_PTR(fd, param, VI_IOCTL_SET_DMA_BUF_INFO);
}
int vi_set_enq_buf(int fd, struct vi_buffer *buf)
{
S_CTRL_PTR(fd, buf, VI_IOCTL_ENQ_BUF);
}
int vi_set_start_streaming(int fd)
{
S_CTRL_VALUE(fd, 1, VI_IOCTL_START_STREAMING);
}
int vi_set_stop_streaming(int fd)
{
S_CTRL_VALUE(fd, 1, VI_IOCTL_STOP_STREAMING);
}
int vi_sdk_set_dev_attr(int fd, int dev, VI_DEV_ATTR_S *pstDevAttr)
{
SDK_CTRL_SET_CFG(fd, pstDevAttr, VI_SDK_SET_DEV_ATTR, dev, -1, -1, -1);
}
int vi_sdk_get_dev_attr(int fd, int dev, VI_DEV_ATTR_S *pstDevAttr)
{
SDK_CTRL_SET_CFG(fd, pstDevAttr, VI_SDK_GET_DEV_ATTR, dev, -1, -1, -1);
}
int vi_sdk_enable_dev(int fd, int dev)
{
SDK_CTRL_SET_CFG(fd, NULL, VI_SDK_ENABLE_DEV, dev, -1, -1, -1);
}
int vi_sdk_create_pipe(int fd, int pipe, VI_PIPE_ATTR_S *pstPipeAttr)
{
SDK_CTRL_SET_CFG(fd, pstPipeAttr, VI_SDK_CREATE_PIPE, -1, pipe, -1, -1);
}
int vi_sdk_start_pipe(int fd, int pipe)
{
SDK_CTRL_SET_CFG(fd, NULL, VI_SDK_START_PIPE, -1, pipe, -1, -1);
}
int vi_sdk_get_chn_attr(int fd, int pipe, int chn, VI_CHN_ATTR_S *pstChnAttr)
{
SDK_CTRL_SET_CFG(fd, pstChnAttr, VI_SDK_GET_CHN_ATTR, -1, pipe, chn, -1);
}
int vi_sdk_set_chn_attr(int fd, int pipe, int chn, VI_CHN_ATTR_S *pstChnAttr)
{
SDK_CTRL_SET_CFG(fd, pstChnAttr, VI_SDK_SET_CHN_ATTR, -1, pipe, chn, -1);
}
int vi_sdk_enable_chn(int fd, int pipe, int chn)
{
SDK_CTRL_SET_CFG(fd, NULL, VI_SDK_ENABLE_CHN, -1, pipe, chn, -1);
}
int vi_sdk_disable_chn(int fd, int pipe, int chn)
{
SDK_CTRL_SET_CFG(fd, NULL, VI_SDK_DISABLE_CHN, -1, pipe, chn, -1);
}
int vi_sdk_set_motion_lv(int fd, struct mlv_info_s *pmlv_i)
{
SDK_CTRL_SET_CFG(fd, pmlv_i, VI_SDK_SET_MOTION_LV, -1, -1, -1, -1);
}
int vi_sdk_enable_dis(int fd, int pipe)
{
SDK_CTRL_SET_CFG(fd, NULL, VI_SDK_ENABLE_DIS, -1, pipe, -1, -1);
}
int vi_sdk_disable_dis(int fd, int pipe)
{
SDK_CTRL_SET_CFG(fd, NULL, VI_SDK_DISABLE_DIS, -1, pipe, -1, -1);
}
int vi_sdk_set_dis_info(int fd, struct dis_info_s *pdis_i)
{
SDK_CTRL_SET_CFG(fd, pdis_i, VI_SDK_SET_DIS_INFO, -1, -1, -1, -1);
}
int vi_sdk_set_dev_timing_attr(int fd, int dev, VI_DEV_TIMING_ATTR_S *pstDevTimingAttr)
{
SDK_CTRL_SET_CFG(fd, pstDevTimingAttr, VI_SDK_SET_DEV_TIMING_ATTR, dev, -1, -1, -1);
}
int vi_sdk_set_pipe_frm_src(int fd, int pipe, VI_PIPE_FRAME_SOURCE_E *source)
{
SDK_CTRL_SET_CFG(fd, source, VI_SDK_SET_PIPE_FRM_SRC, -1, pipe, -1, -1);
}
int vi_sdk_send_pipe_raw(int fd, int pipe, VIDEO_FRAME_INFO_S *sVideoFrm)
{
SDK_CTRL_SET_CFG(fd, sVideoFrm, VI_SDK_SEND_PIPE_RAW, -1, pipe, -1, -1);
}
int vi_sdk_get_chn_frame(int fd, int pipe, int chn, VIDEO_FRAME_INFO_S *pstFrameInfo, CVI_S32 s32MilliSec)
{
SDK_CTRL_SET_CFG(fd, pstFrameInfo, VI_SDK_GET_CHN_FRAME, -1, pipe, chn, s32MilliSec);
}
int vi_sdk_release_chn_frame(int fd, int pipe, int chn, VIDEO_FRAME_INFO_S *pstFrameInfo)
{
SDK_CTRL_SET_CFG(fd, pstFrameInfo, VI_SDK_RELEASE_CHN_FRAME, -1, pipe, chn, -1);
}
int vi_sdk_set_chn_crop(int fd, int pipe, int chn, VI_CROP_INFO_S *pstCropInfo)
{
SDK_CTRL_SET_CFG(fd, pstCropInfo, VI_SDK_SET_CHN_CROP, -1, pipe, chn, -1);
}
int vi_sdk_get_chn_crop(int fd, int pipe, int chn, VI_CROP_INFO_S *pstCropInfo)
{
SDK_CTRL_SET_CFG(fd, pstCropInfo, VI_SDK_GET_CHN_CROP, -1, pipe, chn, -1);
}
int vi_sdk_get_pipe_attr(int fd, int pipe, VI_PIPE_ATTR_S *pstPipeAttr)
{
SDK_CTRL_SET_CFG(fd, pstPipeAttr, VI_SDK_GET_PIPE_ATTR, -1, pipe, -1, -1);
}
int vi_sdk_set_pipe_attr(int fd, int pipe, VI_PIPE_ATTR_S *pstPipeAttr)
{
SDK_CTRL_SET_CFG(fd, pstPipeAttr, VI_SDK_SET_PIPE_ATTR, -1, pipe, -1, -1);
}
int vi_sdk_get_pipe_dump_attr(int fd, int pipe, VI_DUMP_ATTR_S *pstDumpAttr)
{
SDK_CTRL_SET_CFG(fd, pstDumpAttr, VI_SDK_GET_PIPE_DUMP_ATTR, -1, pipe, -1, -1);
}
int vi_sdk_set_pipe_dump_attr(int fd, int pipe, VI_DUMP_ATTR_S *pstDumpAttr)
{
SDK_CTRL_SET_CFG(fd, pstDumpAttr, VI_SDK_SET_PIPE_DUMP_ATTR, -1, pipe, -1, -1);
}
int vi_sdk_get_pipe_frame(int fd, int pipe, VIDEO_FRAME_INFO_S *pstFrameInfo, CVI_S32 s32MilliSec)
{
SDK_CTRL_SET_CFG(fd, pstFrameInfo, VI_SDK_GET_PIPE_FRAME, -1, pipe, -1, s32MilliSec);
}
int vi_sdk_release_pipe_frame(int fd, int pipe, VIDEO_FRAME_INFO_S *pstFrameInfo)
{
SDK_CTRL_SET_CFG(fd, pstFrameInfo, VI_SDK_RELEASE_PIPE_FRAME, -1, pipe, -1, -1);
}
int vi_sdk_start_smooth_rawdump(int fd, int pipe, struct cvi_vip_isp_smooth_raw_param *smooth_raw_param)
{
SDK_CTRL_SET_CFG(fd, smooth_raw_param, VI_SDK_START_SMOOTH_RAWDUMP, -1, pipe, -1, -1);
}
int vi_sdk_stop_smooth_rawdump(int fd, int pipe, struct cvi_vip_isp_smooth_raw_param *smooth_raw_param)
{
SDK_CTRL_SET_CFG(fd, smooth_raw_param, VI_SDK_STOP_SMOOTH_RAWDUMP, -1, pipe, -1, -1);
}
int vi_sdk_get_smooth_rawdump(int fd, int pipe, VIDEO_FRAME_INFO_S *pstFrameInfo, CVI_S32 s32MilliSec)
{
SDK_CTRL_SET_CFG(fd, pstFrameInfo, VI_SDK_GET_SMOOTH_RAWDUMP, -1, pipe, -1, s32MilliSec);
}
int vi_sdk_put_smooth_rawdump(int fd, int pipe, VIDEO_FRAME_INFO_S *pstFrameInfo)
{
SDK_CTRL_SET_CFG(fd, pstFrameInfo, VI_SDK_PUT_SMOOTH_RAWDUMP, -1, pipe, -1, -1);
}
int vi_sdk_set_chn_rotation(int fd, const struct vi_chn_rot_cfg *cfg)
{
SDK_CTRL_SET_CFG(fd, cfg, VI_SDK_SET_CHN_ROTATION, -1, -1, cfg->ViChn, -1);
}
int vi_sdk_set_chn_ldc(int fd, const struct vi_chn_ldc_cfg *cfg)
{
SDK_CTRL_SET_CFG(fd, cfg, VI_SDK_SET_CHN_LDC, -1, -1, cfg->ViChn, -1);
}
int vi_sdk_attach_vbpool(int fd, const struct vi_vb_pool_cfg *cfg)
{
SDK_CTRL_SET_CFG(fd, cfg, VI_SDK_ATTACH_VB_POOL, -1, -1, cfg->ViChn, -1);
}
int vi_sdk_detach_vbpool(int fd, const struct vi_vb_pool_cfg *cfg)
{
SDK_CTRL_SET_CFG(fd, cfg, VI_SDK_DETACH_VB_POOL, -1, -1, cfg->ViChn, -1);
}

View File

@@ -0,0 +1,338 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <pthread.h>
#include <fcntl.h> /* low-level i/o */
#include <unistd.h>
#include <errno.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <linux/cvi_common.h>
#include <linux/cvi_comm_vo.h>
#include <linux/vo_uapi.h>
#include "vo_ioctl.h"
#define VO_S_CTRL_VALUE(_fd, _cfg, _ioctl)\
do {\
struct vo_ext_control ec1;\
memset(&ec1, 0, sizeof(ec1));\
ec1.id = _ioctl;\
ec1.value = _cfg;\
if (ioctl(_fd, VO_IOC_S_CTRL, &ec1) < 0) {\
fprintf(stderr, "VO_IOC_S_CTRL - %s NG, %s\n", __func__, strerror(errno));\
return -1;\
} \
return 0;\
} while (0)
#define VO_S_CTRL_VALUE64(_fd, _cfg, _ioctl)\
do {\
struct vo_ext_control ec1;\
memset(&ec1, 0, sizeof(ec1));\
ec1.id = _ioctl;\
ec1.value64 = _cfg;\
if (ioctl(_fd, VO_IOC_S_CTRL, &ec1) < 0) {\
fprintf(stderr, "VO_IOC_S_CTRL - %s NG, %s\n", __func__, strerror(errno));\
return -1;\
} \
return 0;\
} while (0)
#define VO_SDK_CTRL_PTR(_fd, _cfg, _ioctl, _sdk_id)\
do {\
struct vo_ext_control ec1;\
memset(&ec1, 0, sizeof(ec1));\
ec1.id = _ioctl;\
ec1.sdk_id = _sdk_id;\
ec1.ptr = (void *)_cfg;\
if (ioctl(_fd, VO_IOC_S_CTRL, &ec1) < 0) {\
fprintf(stderr, "VO_IOC_S_CTRL - %s NG, %s\n", __func__, strerror(errno));\
return -1;\
} \
return 0;\
} while (0)
#define VO_S_CTRL_PTR(_fd, _cfg, _ioctl)\
do {\
struct vo_ext_control ec1;\
memset(&ec1, 0, sizeof(ec1));\
ec1.id = _ioctl;\
ec1.ptr = (void *)_cfg;\
if (ioctl(_fd, VO_IOC_S_CTRL, &ec1) < 0) {\
fprintf(stderr, "VO_IOC_S_CTRL - %s NG,%s\n", __func__, strerror(errno));\
return -1;\
} \
return 0;\
} while (0)
#define VO_G_CTRL_VALUE(_fd, _out, _ioctl)\
do {\
struct vo_ext_control ec1;\
memset(&ec1, 0, sizeof(ec1));\
ec1.id = _ioctl;\
ec1.value = 0;\
if (ioctl(_fd, VO_IOC_G_CTRL, &ec1) < 0) {\
fprintf(stderr, "VO_IOC_G_CTRL - %s NG, %s\n", __func__, strerror(errno));\
return -1;\
} \
*_out = ec1.value;\
return 0;\
} while (0)
#define VO_G_CTRL_PTR(_fd, _cfg, _ioctl)\
do {\
struct vo_ext_control ec1;\
memset(&ec1, 0, sizeof(ec1));\
ec1.id = _ioctl;\
ec1.ptr = (void *)_cfg;\
if (ioctl(_fd, VO_IOC_G_CTRL, &ec1) < 0) {\
fprintf(stderr, "VO_IOC_G_CTRL - %s NG, %s\n", __func__, strerror(errno));\
return -1;\
} \
return 0;\
} while (0)
#define VO_S_CTRL_ARR(_fd, _cfg, _size, _ioctl)\
do {\
struct vo_ext_control ec1;\
memset(&ec1, 0, sizeof(ec1));\
ec1.id = _ioctl;\
ec1.ptr = (void *)_cfg;\
ec1.size = _size;\
if (ioctl(_fd, VO_IOC_S_CTRL, &ec1) < 0) {\
fprintf(stderr, "VO_IOC_G_CTRL - %s NG, %s\n", __func__, strerror(errno));\
return -1;\
} \
return 0;\
} while (0)
int vo_set_pattern(int fd, enum cvi_vip_pattern pattern)
{
VO_S_CTRL_VALUE(fd, pattern, VO_IOCTL_PATTERN);
}
int vo_set_mode(int fd, int mode)
{
VO_S_CTRL_VALUE(fd, mode, VO_IOCTL_ONLINE);
}
int vo_set_frame_bgcolor(int fd, void *rgb)
{
VO_S_CTRL_PTR(fd, rgb, VO_IOCTL_FRAME_BGCOLOR);
}
int vo_set_window_bgcolor(int fd, void *rgb)
{
VO_S_CTRL_PTR(fd, rgb, VO_IOCTL_WINDOW_BGCOLOR);
}
int vo_set_intf(int fd, struct cvi_disp_intf_cfg *cfg)
{
VO_S_CTRL_PTR(fd, cfg, VO_IOCTL_INTF);
}
int vo_enable_window_bgcolor(int fd, int enable)
{
VO_S_CTRL_VALUE(fd, enable, VO_IOCTL_ENABLE_WIN_BGCOLOR);
}
int vo_set_align(int fd, int align)
{
VO_S_CTRL_VALUE(fd, align, VO_IOCTL_SET_ALIGN);
}
int vo_set_rgn(int fd, struct cvi_rgn_cfg *cfg)
{
VO_S_CTRL_PTR(fd, cfg, VO_IOCTL_SET_RGN);
}
int vo_set_csc(int fd, struct cvi_csc_cfg *cfg)
{
VO_S_CTRL_PTR(fd, cfg, VO_IOCTL_SET_CUSTOM_CSC);
}
int vo_set_clk(int fd, CVI_U32 clk_freq)
{
VO_S_CTRL_VALUE(fd, clk_freq, VO_IOCTL_SET_CLK);
}
int vo_set_i80_sw_mode(int fd, CVI_U32 enable)
{
VO_S_CTRL_VALUE(fd, enable, VO_IOCTL_I80_SW_MODE);
}
int vo_send_i80_cmd(int fd, CVI_U32 cmd)
{
VO_S_CTRL_VALUE(fd, cmd, VO_IOCTL_I80_CMD);
}
int vo_get_videolayer_size(int fd, SIZE_S *vsize)
{
VO_S_CTRL_PTR(fd, vsize, VO_IOCTL_GET_VLAYER_SIZE);
}
int vo_get_intf_type(int fd, CVI_S32 *vo_sel)
{
VO_G_CTRL_PTR(fd, vo_sel, VO_IOCTL_GET_INTF_TYPE);
}
int vo_get_panel_status(int fd, CVI_U32 *is_init)
{
VO_G_CTRL_PTR(fd, is_init, VO_IOCTL_GET_PANEL_STATUS);
}
int vo_set_gamma_ctrl(int fd, VO_GAMMA_INFO_S *gamma_attr)
{
VO_S_CTRL_PTR(fd, gamma_attr, VO_IOCTL_GAMMA_LUT_UPDATE);
}
int vo_get_gamma_ctrl(int fd, VO_GAMMA_INFO_S *gamma_attr)
{
VO_G_CTRL_PTR(fd, gamma_attr, VO_IOCTL_GAMMA_LUT_READ);
}
int vo_set_tgt_compose(int fd, struct vo_rect *area)
{
VO_S_CTRL_PTR(fd, area, VO_IOCTL_SEL_TGT_COMPOSE);
}
int vo_set_tgt_crop(int fd, struct vo_rect *area)
{
VO_S_CTRL_PTR(fd, area, VO_IOCTL_SEL_TGT_CROP);
}
int vo_set_dv_timings(int fd, struct vo_dv_timings *timings)
{
VO_S_CTRL_PTR(fd, timings, VO_IOCTL_SET_DV_TIMINGS);
}
int vo_get_dv_timings(int fd, struct vo_dv_timings *timings)
{
VO_G_CTRL_PTR(fd, timings, VO_IOCTL_GET_DV_TIMINGS);
}
int vo_set_stop_streaming(int fd)
{
VO_S_CTRL_VALUE(fd, 1, VO_IOCTL_STOP_STREAMING);
}
int vo_set_start_streaming(int fd)
{
VO_S_CTRL_VALUE(fd, 1, VO_IOCTL_START_STREAMING);
}
int vo_enq_buf(int fd, struct vo_buffer *buf)
{
VO_S_CTRL_PTR(fd, buf, VO_IOCTL_ENQ_BUF);
}
//vo sdk API list
int vo_sdk_clearchnbuf(int fd, struct vo_clear_chn_buf_cfg *cfg)
{
VO_SDK_CTRL_PTR(fd, cfg, VO_IOCTL_SDK_CTRL, VO_SDK_CLEAR_CHNBUF);
}
int vo_sdk_send_frame(int fd, struct vo_snd_frm_cfg *cfg)
{
VO_SDK_CTRL_PTR(fd, cfg, VO_IOCTL_SDK_CTRL, VO_SDK_SEND_FRAME);
}
int vo_sdk_get_panelstatue(int fd, struct vo_panel_status_cfg *cfg)
{
VO_SDK_CTRL_PTR(fd, cfg, VO_IOCTL_SDK_CTRL, VO_SDK_GET_PANELSTATUE);
}
int vo_sdk_get_pubattr(int fd, struct vo_pub_attr_cfg *cfg)
{
VO_SDK_CTRL_PTR(fd, cfg, VO_IOCTL_SDK_CTRL, VO_SDK_GET_PUBATTR);
}
int vo_sdk_set_pubattr(int fd, struct vo_pub_attr_cfg *cfg)
{
VO_SDK_CTRL_PTR(fd, cfg, VO_IOCTL_SDK_CTRL, VO_SDK_SET_PUBATTR);
}
int vo_sdk_suspend(int fd)
{
VO_SDK_CTRL_PTR(fd, NULL, VO_IOCTL_SDK_CTRL, VO_SDK_SUSPEND);
}
int vo_sdk_resume(int fd)
{
VO_SDK_CTRL_PTR(fd, NULL, VO_IOCTL_SDK_CTRL, VO_SDK_RESUME);
}
int vo_sdk_get_displaybuflen(int fd, struct vo_display_buflen_cfg *cfg)
{
VO_SDK_CTRL_PTR(fd, cfg, VO_IOCTL_SDK_CTRL, VO_SDK_GET_DISPLAYBUFLEN);
}
int vo_sdk_set_displaybuflen(int fd, struct vo_display_buflen_cfg *cfg)
{
VO_SDK_CTRL_PTR(fd, cfg, VO_IOCTL_SDK_CTRL, VO_SDK_SET_DISPLAYBUFLEN);
}
int vo_sdk_set_videolayerattr(int fd, struct vo_video_layer_attr_cfg *cfg)
{
VO_SDK_CTRL_PTR(fd, cfg, VO_IOCTL_SDK_CTRL, VO_SDK_SET_VIDEOLAYERATTR);
}
int vo_sdk_get_videolayerattr(int fd, struct vo_video_layer_attr_cfg *cfg)
{
VO_SDK_CTRL_PTR(fd, cfg, VO_IOCTL_SDK_CTRL, VO_SDK_GET_VIDEOLAYERATTR);
}
int vo_sdk_enable_videolayer(int fd, struct vo_video_layer_cfg *cfg)
{
VO_SDK_CTRL_PTR(fd, cfg, VO_IOCTL_SDK_CTRL, VO_SDK_ENABLE_VIDEOLAYER);
}
int vo_sdk_disable_videolayer(int fd, struct vo_video_layer_cfg *cfg)
{
VO_SDK_CTRL_PTR(fd, cfg, VO_IOCTL_SDK_CTRL, VO_SDK_DISABLE_VIDEOLAYER);
}
int vo_sdk_set_chnattr(int fd, struct vo_chn_attr_cfg *cfg)
{
VO_SDK_CTRL_PTR(fd, cfg, VO_IOCTL_SDK_CTRL, VO_SDK_SET_CHNATTR);
}
int vo_sdk_get_chnattr(int fd, struct vo_chn_attr_cfg *cfg)
{
VO_SDK_CTRL_PTR(fd, cfg, VO_IOCTL_SDK_CTRL, VO_SDK_GET_CHNATTR);
}
int vo_sdk_set_chnrotation(int fd, struct vo_chn_rotation_cfg *cfg)
{
VO_SDK_CTRL_PTR(fd, cfg, VO_IOCTL_SDK_CTRL, VO_SDK_SET_CHNROTATION);
}
int vo_sdk_get_chnrotation(int fd, struct vo_chn_rotation_cfg *cfg)
{
VO_SDK_CTRL_PTR(fd, cfg, VO_IOCTL_SDK_CTRL, VO_SDK_GET_CHNROTATION);
}
int vo_sdk_enable_chn(int fd, struct vo_chn_cfg *cfg)
{
VO_SDK_CTRL_PTR(fd, cfg, VO_IOCTL_SDK_CTRL, VO_SDK_ENABLE_CHN);
}
int vo_sdk_disable_chn(int fd, struct vo_chn_cfg *cfg)
{
VO_SDK_CTRL_PTR(fd, cfg, VO_IOCTL_SDK_CTRL, VO_SDK_DISABLE_CHN);
}
int vo_sdk_enable(int fd, struct vo_dev_cfg *cfg)
{
VO_SDK_CTRL_PTR(fd, cfg, VO_IOCTL_SDK_CTRL, VO_SDK_ENABLE);
}
int vo_sdk_disable(int fd, struct vo_dev_cfg *cfg)
{
VO_SDK_CTRL_PTR(fd, cfg, VO_IOCTL_SDK_CTRL, VO_SDK_DISABLE);
}

View File

@@ -0,0 +1,258 @@
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include <math.h>
#include <errno.h>
#include "vpss_ioctl.h"
CVI_S32 vpss_send_frame(CVI_S32 fd, struct vpss_snd_frm_cfg *cfg)
{
return ioctl(fd, CVI_VPSS_SEND_FRAME, cfg);
}
CVI_S32 vpss_send_chn_frame(CVI_S32 fd, struct vpss_chn_frm_cfg *cfg)
{
return ioctl(fd, CVI_VPSS_SEND_CHN_FRAME, cfg);
}
CVI_S32 vpss_release_chn_frame(CVI_S32 fd, const struct vpss_chn_frm_cfg *cfg)
{
return ioctl(fd, CVI_VPSS_RELEASE_CHN_FRAME, cfg);
}
CVI_S32 vpss_create_grp(CVI_S32 fd, struct vpss_crt_grp_cfg *cfg)
{
return ioctl(fd, CVI_VPSS_CREATE_GROUP, cfg);
}
CVI_S32 vpss_destroy_grp(CVI_S32 fd, VPSS_GRP VpssGrp)
{
return ioctl(fd, CVI_VPSS_DESTROY_GROUP, &VpssGrp);
}
CVI_S32 vpss_get_available_grp(CVI_S32 fd, VPSS_GRP *pVpssGrp)
{
return ioctl(fd, CVI_VPSS_GET_AVAIL_GROUP, pVpssGrp);
}
CVI_S32 vpss_start_grp(CVI_S32 fd, struct vpss_str_grp_cfg *cfg)
{
return ioctl(fd, CVI_VPSS_START_GROUP, cfg);
}
CVI_S32 vpss_stop_grp(CVI_S32 fd, VPSS_GRP VpssGrp)
{
return ioctl(fd, CVI_VPSS_STOP_GROUP, &VpssGrp);
}
CVI_S32 vpss_reset_grp(CVI_S32 fd, VPSS_GRP VpssGrp)
{
return ioctl(fd, CVI_VPSS_RESET_GROUP, &VpssGrp);
}
CVI_S32 vpss_set_grp_attr(CVI_S32 fd, const struct vpss_grp_attr *cfg)
{
return ioctl(fd, CVI_VPSS_SET_GRP_ATTR, cfg);
}
CVI_S32 vpss_get_grp_attr(CVI_S32 fd, struct vpss_grp_attr *cfg)
{
return ioctl(fd, CVI_VPSS_GET_GRP_ATTR, cfg);
}
CVI_S32 vpss_set_grp_crop(CVI_S32 fd, const struct vpss_grp_crop_cfg *cfg)
{
return ioctl(fd, CVI_VPSS_SET_GRP_CROP, cfg);
}
CVI_S32 vpss_get_grp_crop(CVI_S32 fd, struct vpss_grp_crop_cfg *cfg)
{
return ioctl(fd, CVI_VPSS_GET_GRP_CROP, cfg);
}
CVI_VOID _vpss_pack_fixed_point_norm(VPSS_NORMALIZE_S *pstNormalize)
{
CVI_U16 sc_frac[3];
CVI_U8 sub[3];
CVI_U16 sub_frac[3];
CVI_DOUBLE sub_int;
VPSS_NORMALIZE_S stNormalize;
struct vpss_int_normalize *int_norm;
if (!pstNormalize->bEnable)
return;
memcpy(&stNormalize, pstNormalize, sizeof(stNormalize));
for (CVI_U8 i = 0; i < 3; ++i) {
sc_frac[i] = pstNormalize->factor[i] * 8192;
sub_frac[i]
= modf(pstNormalize->mean[i], &sub_int) * 1024;
sub[i] = sub_int;
}
int_norm = (struct vpss_int_normalize *)pstNormalize;
int_norm->enable = 1;
int_norm->rounding = pstNormalize->rounding;
for (CVI_U8 i = 0; i < 3; ++i) {
int_norm->sc_frac[i] = sc_frac[i];
int_norm->sub[i] = sub[i];
int_norm->sub_frac[i] = sub_frac[i];
}
}
CVI_S32 vpss_set_chn_attr(CVI_S32 fd, struct vpss_chn_attr *attr)
{
if (sizeof(struct vpss_int_normalize) > sizeof(VPSS_NORMALIZE_S)) {
fprintf(stderr, "Kernel cannnot use float\n");
return CVI_FAILURE;
}
_vpss_pack_fixed_point_norm(&attr->stChnAttr.stNormalize);
return ioctl(fd, CVI_VPSS_SET_CHN_ATTR, attr);
}
CVI_S32 vpss_get_chn_attr(CVI_S32 fd, struct vpss_chn_attr *attr)
{
return ioctl(fd, CVI_VPSS_GET_CHN_ATTR, attr);
}
CVI_S32 vpss_show_chn(CVI_S32 fd, struct vpss_en_chn_cfg *cfg)
{
return ioctl(fd, CVI_VPSS_SHOW_CHN, cfg);
}
CVI_S32 vpss_hide_chn(CVI_S32 fd, struct vpss_en_chn_cfg *cfg)
{
return ioctl(fd, CVI_VPSS_HIDE_CHN, cfg);
}
CVI_S32 vpss_enable_chn(CVI_S32 fd, struct vpss_en_chn_cfg *cfg)
{
return ioctl(fd, CVI_VPSS_ENABLE_CHN, cfg);
}
CVI_S32 vpss_disable_chn(CVI_S32 fd, struct vpss_en_chn_cfg *cfg)
{
return ioctl(fd, CVI_VPSS_DISABLE_CHN, cfg);
}
CVI_S32 vpss_get_chn_frame(CVI_S32 fd, struct vpss_chn_frm_cfg *cfg)
{
return ioctl(fd, CVI_VPSS_GET_CHN_FRAME, cfg);
}
CVI_S32 vpss_set_chn_wrap(CVI_S32 fd, const struct vpss_chn_wrap_cfg *cfg)
{
return ioctl(fd, CVI_VPSS_SET_CHN_BUF_WRAP, cfg);
}
CVI_S32 vpss_get_chn_wrap(CVI_S32 fd, struct vpss_chn_wrap_cfg *cfg)
{
return ioctl(fd, CVI_VPSS_GET_CHN_BUF_WRAP, cfg);
}
CVI_S32 vpss_set_chn_rotation(CVI_S32 fd, const struct vpss_chn_rot_cfg *cfg)
{
return ioctl(fd, CVI_VPSS_SET_CHN_ROTATION, cfg);
}
CVI_S32 vpss_get_chn_rotation(CVI_S32 fd, struct vpss_chn_rot_cfg *cfg)
{
return ioctl(fd, CVI_VPSS_GET_CHN_ROTATION, cfg);
}
CVI_S32 vpss_set_chn_align(CVI_S32 fd, const struct vpss_chn_align_cfg *cfg)
{
return ioctl(fd, CVI_VPSS_SET_CHN_ALIGN, cfg);
}
CVI_S32 vpss_get_chn_align(CVI_S32 fd, struct vpss_chn_align_cfg *cfg)
{
return ioctl(fd, CVI_VPSS_GET_CHN_ALIGN, cfg);
}
CVI_S32 vpss_set_chn_ldc(CVI_S32 fd, const struct vpss_chn_ldc_cfg *cfg)
{
return ioctl(fd, CVI_VPSS_SET_CHN_LDC, cfg);
}
CVI_S32 vpss_get_chn_ldc(CVI_S32 fd, struct vpss_chn_ldc_cfg *cfg)
{
return ioctl(fd, CVI_VPSS_GET_CHN_LDC, cfg);
}
CVI_S32 vpss_set_chn_crop(CVI_S32 fd, const struct vpss_chn_crop_cfg *cfg)
{
return ioctl(fd, CVI_VPSS_SET_CHN_CROP, cfg);
}
CVI_S32 vpss_get_chn_crop(CVI_S32 fd, struct vpss_chn_crop_cfg *cfg)
{
return ioctl(fd, CVI_VPSS_GET_CHN_CROP, cfg);
}
CVI_S32 vpss_set_coef_level(CVI_S32 fd, const struct vpss_chn_coef_level_cfg *cfg)
{
return ioctl(fd, CVI_VPSS_SET_CHN_SCALE_COEFF_LEVEL, cfg);
}
CVI_S32 vpss_get_coef_level(CVI_S32 fd, struct vpss_chn_coef_level_cfg *cfg)
{
return ioctl(fd, CVI_VPSS_GET_CHN_SCALE_COEFF_LEVEL, cfg);
}
CVI_S32 vpss_set_chn_yratio(CVI_S32 fd, const struct vpss_chn_yratio_cfg *cfg)
{
return ioctl(fd, CVI_VPSS_SET_CHN_YRATIO, cfg);
}
CVI_S32 vpss_get_chn_yratio(CVI_S32 fd, struct vpss_chn_yratio_cfg *cfg)
{
return ioctl(fd, CVI_VPSS_GET_CHN_YRATIO, cfg);
}
CVI_S32 vpss_set_grp_csc(CVI_S32 fd, const struct vpss_grp_csc_cfg *cfg)
{
return ioctl(fd, CVI_VPSS_SET_GRP_CSC_CFG, cfg);
}
CVI_S32 vpss_attach_vbpool(CVI_S32 fd, const struct vpss_vb_pool_cfg *cfg)
{
return ioctl(fd, CVI_VPSS_ATTACH_VB_POOL, cfg);
}
CVI_S32 vpss_detach_vbpool(CVI_S32 fd, const struct vpss_vb_pool_cfg *cfg)
{
return ioctl(fd, CVI_VPSS_DETACH_VB_POOL, cfg);
}
CVI_S32 vpss_trigger_snap_frame(CVI_S32 fd, struct vpss_snap_cfg *cfg)
{
return ioctl(fd, CVI_VPSS_TRIGGER_SNAP_FRAME, cfg);
}
CVI_S32 vpss_get_proc_amp_ctrl(CVI_S32 fd, struct vpss_proc_amp_ctrl_cfg *cfg)
{
return ioctl(fd, CVI_VPSS_GET_AMP_CTRL, cfg);
}
CVI_S32 vpss_get_proc_amp(CVI_S32 fd, struct vpss_proc_amp_cfg *cfg)
{
return ioctl(fd, CVI_VPSS_GET_AMP_CFG, cfg);
}
CVI_S32 vpss_get_all_proc_amp(CVI_S32 fd, struct vpss_all_proc_amp_cfg *cfg)
{
return ioctl(fd, CVI_VPSS_GET_ALL_AMP, cfg);
}
CVI_S32 vpss_get_binscene(CVI_S32 fd, struct vpss_scene *cfg)
{
return ioctl(fd, CVI_VPSS_GET_SCENE, cfg);
}