luckfox-pico-sdk/project/app/component/fastboot_server/fastboot_server_dual_camera.c
luckfox-eng29 8f34c2760d project:build.sh: Added fastboot support; custom modifications to U-Boot and kernel implemented using patches.
project:cfg:BoardConfig_IPC: Added fastboot BoardConfig file and firmware post-scripts, distinguishing between
the BoardConfigs for Luckfox Pico Pro and Luckfox Pico Max. project:app: Added fastboot_client and rk_smart_door
for quick boot applications; updated rkipc app to adapt to the latest media library. media:samples: Added more
usage examples. media:rockit: Fixed bugs; removed support for retrieving data frames from VPSS. media:isp:
Updated rkaiq library and related tools to support connection to RKISP_Tuner. sysdrv:Makefile: Added support for
compiling drv_ko on Luckfox Pico Ultra W using Ubuntu; added support for custom root filesystem.
sysdrv:tools:board: Updated Buildroot optional mirror sources, updated some software versions, and stored device
tree files and configuration files that undergo multiple modifications for U-Boot and kernel separately.
sysdrv:source:mcu: Used RISC-V MCU SDK with RT-Thread system, mainly for initializing camera AE during quick
boot. sysdrv:source:uboot: Added support for fastboot; added high baud rate DDR bin for serial firmware upgrades.
sysdrv:source:kernel: Upgraded to version 5.10.160; increased NPU frequency for RV1106G3; added support for
fastboot.

Signed-off-by: luckfox-eng29 <eng29@luckfox.com>
2024-10-14 09:47:04 +08:00

1491 lines
46 KiB
C

#include <stdio.h>
#include <sys/poll.h>
#include <errno.h>
#include <errno.h>
#include <fcntl.h>
#include <getopt.h>
#include <unistd.h>
#include <stdbool.h>
#include <signal.h>
#include <time.h>
#include <sys/mman.h>
#include <sys/poll.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stddef.h>
#include <fcntl.h>
#include "rk_type.h"
#include "rk_debug.h"
#include "rk_defines.h"
#include "rtsp_demo.h"
#include "rk_pwm.h"
#include "rk_mpi_mb.h"
#include "rk_mpi_venc.h"
#include "rk_mpi_vi.h"
#include "rk_mpi_sys.h"
#include "rk_mpi_rgn.h"
#include "rk_mpi_avs.h"
#include "rk_comm_avs.h"
#include "rk_gpio.h"
#include "rk_meta.h"
#include "sensor_init_info.h"
#include "rk_meta_app_param.h"
#include "sensor_iq_info.h"
#include <rk_aiq_user_api2_camgroup.h>
#include <rk_aiq_user_api2_imgproc.h>
#include <rk_aiq_user_api2_sysctl.h>
#define CAM_NUM 2
#define VENC_CHN_NUM 1
#define MMAP_START_FROM_ZERO 0
#define SERVER_DEBUG_PRT 0
#define SENSOR 0
#define SECONDARY_SENSOR 1
#define ENABLE_RTSP 1
#define EPTZ_DEV_INDEX 1
#define OSD_FILE_PATH "/oem/usr/share/osd_image.data"
#define ISP_CLK_CORE_RATE "clk_core_isp3p2 420000000"
#define ISP_ACLK_RATE "aclk_isp3p2 350000000"
// for argb8888
#define TEST_ARGB32_PIX_SIZE 4
#define TEST_ARGB32_RED 0xFF0000FF
#define TEST_ARGB32_GREEN 0x00FF00FF
#define TEST_ARGB32_BLUE 0x0000FFFF
#define TEST_ARGB32_TRANS 0x00000000
#define TEST_ARGB32_BLACK 0x000000FF
#define MMAP_SIZE (4096UL) //MMAP_SIZE = 4K
#define MMAP_MASK (MMAP_SIZE - 1) //MMAP_MASK = 0XFFF
#define SAVE_ENC_FRM_CNT_MAX 30
#define RUN_TOTAL_CNT_MAX 1000000
#if SERVER_DEBUG_PRT
#define DBG(fmt, args...) printf("Server DBG: "fmt"", ##args)
#else
#define DBG(fmt, args...)
#endif
#define INFO(fmt, args...) printf("Server INFO: "fmt"", ##args)
#define ERR(fmt, args...) printf("Server ERR: "fmt"", ##args)
#define ALIGN_2(data) (data / 2 * 2)
static int32_t g_s32FrameCnt = -1;
static bool quit = false;
static int g_err_cnt = 0;
static bool g_should_quit = false;
static int g_bypass_cnt = 0;
#if (EPTZ_DEV_INDEX == 0)
static int g_eptz_dev = 0;
#else
static int g_eptz_dev = 1;
#endif
pthread_mutex_t g_rtsp_mutex = PTHREAD_MUTEX_INITIALIZER;
rtsp_demo_handle g_rtsplive = NULL;
static rtsp_session_handle g_rtsp_session_0;
static rk_aiq_sys_ctx_t *g_aiq_ctx[2];
static void sigterm_handler(int sig) { quit = true; }
void handle_pipe(int sig) { printf("%s sig = %d\n", __func__, sig); }
typedef struct _rkEptz {
int32_t u32MultipleOfZoom;
int32_t s32EptzViIndex;
uint32_t u32ZoomStep;
uint32_t u32ZoomSwitch;
uint32_t u32ZoomLimit;
} VI_EPTZ_S;
typedef struct _rkMpiAVSCtx {
uint32_t u32SrcWidth;
uint32_t u32SrcHeight;
AVS_CHN s32ChnId;
AVS_MOD_PARAM_S stAvsModParam;
AVS_GRP_ATTR_S stAvsGrpAttr;
AVS_PIPE_ATTR_S stAvsPipeAttr[2];
AVS_CHN_ATTR_S stAvsChnAttr[AVS_MAX_CHN_NUM];
} AVS_CTX_S;
typedef struct _rkMpiVICtx {
uint32_t u32Width;
uint32_t u32Height;
VI_DEV s32DevId;
VI_CHN s32ChnId;
VI_EPTZ_S stEptz;
VI_CROP_INFO_S stCropInfo;
VI_DEV_ATTR_S stDevAttr;
VI_DEV_BIND_PIPE_S stBindPipe;
VI_CHN_ATTR_S stChnAttr;
} VI_CTX_S;
typedef struct _rkMpiVENCCtx {
uint32_t u32Width;
uint32_t u32Height;
uint32_t u32Gop;
uint32_t u32BitRate;
uint32_t u32StreamBufCnt;
uint32_t enCodecType;
PIXEL_FORMAT_E enPixelFormat;
VENC_CHN s32ChnId;
VENC_CHN s32ChnNum;
VENC_CHN_ATTR_S stChnAttr;
VENC_RC_PARAM_S stRcParam;
VENC_RECV_PIC_PARAM_S stRecvParam;
VENC_CHN_REF_BUF_SHARE_S stVencChnRefBufShare;
} VENC_CTX_S;
typedef struct _rkMpiRGNCtx {
uint32_t u32BgAlpha;
uint32_t u32FgAlpha;
uint32_t u32Color;
uint32_t u32Layer;
BITMAP_S stBitmap;
MPP_CHN_S stMppChn;
RGN_HANDLE rgnHandle;
RGN_ATTR_S stRgnAttr;
RGN_CHN_ATTR_S stRgnChnAttr;
} RGN_CTX_S;
typedef struct _FunctionCtx {
uint32_t avs_splice_en;
uint32_t avs_overlay_en;
uint32_t cover_en;
uint32_t osd_en;
uint32_t eptz_en;
uint32_t single_boot;
uint32_t switch_resolution;
} Func_En_S;
typedef struct _rkMpiCtx {
Func_En_S func;
VI_CTX_S vi[2];
AVS_CTX_S avs;
VENC_CTX_S venc;
RGN_CTX_S rgn[2];
} MPI_CTX_S;
typedef struct meta_info
{
struct app_param_info *app_params;
struct sensor_init_cfg *sensor_init[2];
} META_INFO;
static void set_argb8888_buffer(uint32_t *buf, uint32_t size, uint32_t color) {
for (uint32_t i = 0; buf && (i < size); i++)
*buf++ = color;
}
static XCamReturn SAMPLE_COMM_ISP_ErrCb(rk_aiq_err_msg_t* msg) {
g_err_cnt++;
if (g_err_cnt <= 2)
printf("=== %u ===\n", msg->err_code);
if (msg->err_code == XCAM_RETURN_BYPASS){
g_bypass_cnt++;
if(g_bypass_cnt == 2){
g_should_quit = true;
printf("zlj bypass cnt=%d\n", g_bypass_cnt);
}
}
}
static void rtsp_init()
{
g_rtsplive = create_rtsp_demo(554);
g_rtsp_session_0 = rtsp_new_session(g_rtsplive, "/live/0");
rtsp_set_video(g_rtsp_session_0, RTSP_CODEC_ID_VIDEO_H264, NULL, 0);
rtsp_sync_video_ts(g_rtsp_session_0, rtsp_get_reltime(), rtsp_get_ntptime());
}
static int cover_init(MPI_CTX_S *ctx)
{
int32_t ret = 0;
ret = RK_MPI_RGN_Create(ctx->rgn[0].rgnHandle, &ctx->rgn[0].stRgnAttr);
if (0 != ret) {
RK_LOGE("RK_MPI_RGN_Create (%d) failed with %#x!", ctx->rgn[0].rgnHandle, ret);
RK_MPI_RGN_Destroy(ctx->rgn[0].rgnHandle);
return ret;
}
ret = RK_MPI_RGN_AttachToChn(ctx->rgn[0].rgnHandle, &ctx->rgn[0].stMppChn, &ctx->rgn[0].stRgnChnAttr);
if (0 != ret) {
RK_LOGE("RK_MPI_RGN_AttachToChn (%d) failed with %#x!", ctx->rgn[0].rgnHandle, ret);
return ret;
}
ret = RK_MPI_RGN_GetDisplayAttr(ctx->rgn[0].rgnHandle, &ctx->rgn[0].stMppChn, &ctx->rgn[0].stRgnChnAttr);
if (0 != ret) {
RK_LOGE("RK_MPI_RGN_GetDisplayAttr (%d)) failed with %#x!", ctx->rgn[0].rgnHandle,
ret);
return ret;
}
ctx->rgn[0].stRgnChnAttr.bShow = RK_TRUE;
ctx->rgn[0].stRgnChnAttr.enType = COVER_RGN;
ctx->rgn[0].stRgnChnAttr.unChnAttr.stCoverChn.stRect.s32X = 0;
ctx->rgn[0].stRgnChnAttr.unChnAttr.stCoverChn.stRect.s32Y = 480;
ctx->rgn[0].stRgnChnAttr.unChnAttr.stCoverChn.stRect.u32Width = 240;
ctx->rgn[0].stRgnChnAttr.unChnAttr.stCoverChn.stRect.u32Height = 240;
ctx->rgn[0].stRgnChnAttr.unChnAttr.stCoverChn.u32Color = 0xffff00;
ctx->rgn[0].stRgnChnAttr.unChnAttr.stCoverChn.enCoordinate = RGN_ABS_COOR;
ctx->rgn[0].stRgnChnAttr.unChnAttr.stCoverChn.u32Layer = 1;
RK_LOGE("cover region %d <%d, %d, %d, %d>, color<0x%x>",
ctx->rgn[0].rgnHandle, ctx->rgn[0].stRgnChnAttr.unChnAttr.stCoverChn.stRect.s32X,
ctx->rgn[0].stRgnChnAttr.unChnAttr.stCoverChn.stRect.s32Y,
ctx->rgn[0].stRgnChnAttr.unChnAttr.stCoverChn.stRect.u32Width,
ctx->rgn[0].stRgnChnAttr.unChnAttr.stCoverChn.stRect.u32Height,
ctx->rgn[0].stRgnChnAttr.unChnAttr.stCoverChn.u32Color);
ret = RK_MPI_RGN_SetDisplayAttr(ctx->rgn[0].rgnHandle, &ctx->rgn[0].stMppChn, &ctx->rgn[0].stRgnChnAttr);
if (0 != ret) {
RK_LOGE("RK_MPI_RGN_SetDisplayAttr (%d)) failed with %#x!", ctx->rgn[0].rgnHandle,
ret);
return ret;
}
return 0;
}
static int osd_init(MPI_CTX_S *ctx)
{
int32_t ret = 0;
ret = RK_MPI_RGN_Create(ctx->rgn[1].rgnHandle, &ctx->rgn[1].stRgnAttr);
if (0 != ret) {
RK_LOGE("RK_MPI_RGN_Create (%d) failed with %#x!", ctx->rgn[1].rgnHandle, ret);
RK_MPI_RGN_Destroy(ctx->rgn[1].rgnHandle);
return ret;
}
ret = RK_MPI_RGN_AttachToChn(ctx->rgn[1].rgnHandle, &ctx->rgn[1].stMppChn, &ctx->rgn[1].stRgnChnAttr);
if (0 != ret) {
RK_LOGE("RK_MPI_RGN_AttachToChn (%d) failed with %#x!", ctx->rgn[1].rgnHandle, ret);
return ret;
}
RK_LOGI("Display region to chn success!");
ret = RK_MPI_RGN_SetBitMap(ctx->rgn[1].rgnHandle, &ctx->rgn[1].stBitmap);
if (ret != 0) {
RK_LOGE("RK_MPI_RGN_SetBitMap failed with %#x!", ret);
return ret;
}
}
static void save_code_stream_file(int chn, VENC_STREAM_S stFrame)
{
char OutPath[16];
void *pData = RK_NULL;
FILE *file = NULL;
sprintf(OutPath, "/tmp/venc%d.bin", chn);
file = fopen(OutPath, "a+");
if (file) {
pData = (void *)RK_MPI_MB_Handle2VirAddr(stFrame.pstPack->pMbBlk);
fwrite(pData, 1, stFrame.pstPack->u32Len, file);
fflush(file);
}
if (file)
fclose(file);
}
static void *GetVencStream(void *arg) {
void *pData = RK_NULL;
int ret;
int chn = 0, errCnt = 0, loopCount = 0;
VENC_STREAM_S stFrame;
MPI_CTX_S *ctx = (MPI_CTX_S *)arg;
stFrame.pstPack = malloc(sizeof(VENC_PACK_S));
while (!quit) {
ret = RK_MPI_VENC_GetStream(chn, &stFrame, 1000);
if (ret == 0) {
if (ctx->func.single_boot) {
ret = RK_MPI_VI_DisableChn(1, 0);
if (ret != 0) {
RK_LOGE("RK_MPI_VI_DisableChn failure:%#X Pipe:0 ChnId:\n", ret);
return (int *)ret;
}
ctx->func.single_boot = 0;
}
if (ctx->func.eptz_en) {
/* eptz handle */
int32_t ret = 0;
uint32_t u32SrcWidth = ctx->vi[g_eptz_dev].stChnAttr.stSize.u32Width * 100;
uint32_t u32SrcHeight = ctx->vi[g_eptz_dev].stChnAttr.stSize.u32Height * 100;
ret = RK_MPI_VI_GetEptz(g_eptz_dev, 0, &ctx->vi[g_eptz_dev].stCropInfo);
if (ret != 0) {
RK_LOGE("RK_MPI_VI_GetEptz failure:%#X Pipe:%d ChnId:0\n", ret, g_eptz_dev);
return (int *)ret;
}
ctx->vi[g_eptz_dev].stCropInfo.stCropRect.u32Width = ALIGN_2(u32SrcWidth / ctx->vi[g_eptz_dev].stEptz.u32MultipleOfZoom);
ctx->vi[g_eptz_dev].stCropInfo.stCropRect.u32Height = ALIGN_2(u32SrcHeight / ctx->vi[g_eptz_dev].stEptz.u32MultipleOfZoom);
ctx->vi[g_eptz_dev].stCropInfo.stCropRect.s32X = ALIGN_2((ctx->vi[g_eptz_dev].stChnAttr.stSize.u32Width - ctx->vi[g_eptz_dev].stCropInfo.stCropRect.u32Width) / 2);
ctx->vi[g_eptz_dev].stCropInfo.stCropRect.s32Y = ALIGN_2((ctx->vi[g_eptz_dev].stChnAttr.stSize.u32Height - ctx->vi[g_eptz_dev].stCropInfo.stCropRect.u32Height) / 2);
ret = RK_MPI_VI_SetEptz(g_eptz_dev, 0, ctx->vi[g_eptz_dev].stCropInfo);
if (ret != 0) {
RK_LOGE("RK_MPI_VI_SetEptz failure:%#X pipe:%d chnid:0", ret, g_eptz_dev);
return (int *)ret;
}
ctx->vi[g_eptz_dev].stEptz.u32MultipleOfZoom += ctx->vi[g_eptz_dev].stEptz.u32ZoomStep;
if (ctx->vi[g_eptz_dev].stEptz.u32MultipleOfZoom > ctx->vi[g_eptz_dev].stEptz.u32ZoomLimit) {
ctx->vi[g_eptz_dev].stEptz.u32MultipleOfZoom = 100;
}
if (ctx->vi[g_eptz_dev].stEptz.u32MultipleOfZoom > ctx->vi[g_eptz_dev].stEptz.u32ZoomSwitch) {
ctx->vi[g_eptz_dev].stEptz.s32EptzViIndex = 1;
} else {
ctx->vi[g_eptz_dev].stEptz.s32EptzViIndex = 0;
}
}
if (loopCount <= SAVE_ENC_FRM_CNT_MAX) {
printf("chn:%d, loopCount:%d enc->seq:%d, pkt_size=%lu, pts=%llu\n", chn, loopCount,
stFrame.u32Seq, stFrame.pstPack->u32Len, stFrame.pstPack->u64PTS);
save_code_stream_file(chn, stFrame);
}
#if (ENABLE_RTSP)
// tx video to rtspls
if (loopCount > SAVE_ENC_FRM_CNT_MAX) {
if (g_rtsplive && g_rtsp_session_0 && chn == 0) {
pData = (void *)RK_MPI_MB_Handle2VirAddr(stFrame.pstPack->pMbBlk);
rtsp_tx_video(g_rtsp_session_0, pData, stFrame.pstPack->u32Len,
stFrame.pstPack->u64PTS);
rtsp_do_event(g_rtsplive);
}
}
#endif
ret = RK_MPI_VENC_ReleaseStream(chn, &stFrame);
if (ret != 0) {
ERR("venc release chn %d failed\n", chn);
goto __FAILED;
}
errCnt = 0;
loopCount++;
} else {
if (errCnt < 10) {
ERR("RK_MPI_VENC_GetChnFrame fail %x\n", ret);
}
errCnt++;
}
}
__FAILED:
free(stFrame.pstPack);
return NULL;
}
void klog(const char *log) {
FILE *fp = fopen("/dev/kmsg", "w");
if (NULL != fp) {
fprintf(fp, "[app]: %s", log);
fclose(fp);
}
}
//TODO
RK_U64 TEST_COMM_GetNowUs() {
struct timespec time = {0, 0};
clock_gettime(CLOCK_MONOTONIC, &time);
return (RK_U64)time.tv_sec * 1000000 + (RK_U64)time.tv_nsec / 1000; /* microseconds */
}
/*
* * get cmdline from /proc/cmdline
* */
static int read_cmdline_to_buf(void *buf, int len)
{
int fd;
int ret;
if(buf == NULL || len < 0){
printf("%s: illegal para\n", __func__);
return -1;
}
memset(buf, 0, len);
fd = open("/proc/cmdline", O_RDONLY);
if(fd < 0){
perror("open:");
return -1;
}
ret = read(fd, buf, len);
close(fd);
return ret;
}
long get_cmd_val(const char *string, int len) {
char *addr;
long value = 0;
char key_equal[16];
static char cmdline[1024];
static char cmd_init = 0;
if (cmd_init == 0) {
cmd_init = 1;
memset(cmdline, 0, sizeof(cmdline));
read_cmdline_to_buf(cmdline, sizeof(cmdline));
}
snprintf(key_equal, sizeof(key_equal), "%s=", string);
addr = strstr(cmdline, string);
if (addr) {
value = strtol(addr + strlen(string) + 1, NULL, len);
INFO("get %s value: 0x%0lx\n", string, value);
}
return value;
}
static void* mmap_memory_to_viraddr(off_t phy_addr, size_t size)
{
void *vir_addr, *vir_addr_align_4k;
int mem_fd, vir_addr_offset;
if((mem_fd = open("/dev/mem", O_RDWR | O_SYNC)) < 0)
{
perror ("Open dev/mem Error:");
return NULL;
}
vir_addr_align_4k = mmap(MMAP_START_FROM_ZERO, size, PROT_READ | PROT_WRITE, MAP_SHARED, mem_fd, phy_addr);
vir_addr_offset = phy_addr & MMAP_MASK;
vir_addr = vir_addr_align_4k + vir_addr_offset;
close(mem_fd);
return vir_addr;
}
__attribute__((unused)) static int dump_virmem_hex(char *buf_dump_addr, const char *msg)
{
printf("\ndump [%s]\n", msg);
char *pdata = (char *)(buf_dump_addr);
for (char j=0; j<64; j++ ) {
printf("%02x ", *(pdata+j) & 0xff);
if ((j+1)%16 == 0) {
printf("\n");
}
}
printf("\n");
return 0;
}
__attribute__((unused)) static void dump_meta_sensor_app_params(struct meta_info *handle) {
int camId = 0;
for(; camId < CAM_NUM; camId++) {
printf("\n");
printf("sensor[%d] init info:\n", camId);
printf("cam_w: %d, cam_h: %d\n",
handle->sensor_init[camId]->cam_w,
handle->sensor_init[camId]->cam_h);
printf("app[%d] params info:\n", camId);
printf("venc_w: %d, venc_h: %d, venc_type: %d, venc_bitrate: %d, fps: %d, cam_mirror_flip: %d, night_mode: %d, color_mode: %d\n",
handle->app_params->venc_w,
handle->app_params->venc_h,
handle->app_params->venc_type,
handle->app_params->venc_bitrate,
handle->app_params->cam_fps,
handle->app_params->cam_mirror_flip,
handle->app_params->night_mode,
handle->app_params->color_mode);
}
printf("\n");
}
static void* get_meta_params(struct meta_info *handle) {
int app_param_offset, meta_size;
off_t metaAddr;
void *metaVirmem = NULL, *appVirAddr = NULL, *SensorInitVirAddr;
struct app_param_info *AppParam = NULL;
struct sensor_init_cfg *SensorInitParam = NULL;
meta_size = (int)get_cmd_val("meta_part_size", 16);
metaAddr = (off_t)get_cmd_val("meta_load_addr", 16);
metaVirmem = mmap_memory_to_viraddr(metaAddr, (size_t)meta_size);
if (metaVirmem != MAP_FAILED) {
SensorInitVirAddr = metaVirmem + SENSOR_INIT_OFFSET;
handle->sensor_init[SENSOR] = (struct sensor_init_cfg*)(SensorInitVirAddr);
SensorInitVirAddr = metaVirmem + SECONDARY_SENSOR_INIT_OFFSET;
handle->sensor_init[SECONDARY_SENSOR] = (struct sensor_init_cfg*)(SensorInitVirAddr);
app_param_offset = (int)get_cmd_val(RK_APP_PARAM_OFFSET, 16);
appVirAddr = metaVirmem + app_param_offset;
handle->app_params = (struct app_param_info *)(appVirAddr);
return metaVirmem;
} else {
ERR("meta addr mmap fail.\n");
return metaVirmem;
}
}
static int vi_init(MPI_CTX_S *ctx)
{
int ret, devId;
for (devId = 0; devId < CAM_NUM; devId++) {
memset(&ctx->vi[devId].stDevAttr, 0, sizeof(ctx->vi[devId].stDevAttr));
memset(&ctx->vi[devId].stBindPipe, 0, sizeof(ctx->vi[devId].stBindPipe));
ret = RK_MPI_VI_GetDevAttr(devId, &ctx->vi[devId].stDevAttr);
if (ret == RK_ERR_VI_NOT_CONFIG) {
ret = RK_MPI_VI_SetDevAttr(devId, &ctx->vi[devId].stDevAttr);
if (ret != 0)
ERR("VI dev %d set attr failed ret: %d\n", devId, ret);
} else {
ERR("VI dev %d has been configed\n", devId);
}
ret = RK_MPI_VI_GetDevIsEnable(devId);
if (ret != 0) {
ret = RK_MPI_VI_EnableDev(devId);
if (ret != 0)
ERR("VI dev %d enable failed ret: %d\n", devId, ret);
ctx->vi[devId].stBindPipe.u32Num = devId;
ctx->vi[devId].stBindPipe.PipeId[0] = devId;
ret = RK_MPI_VI_SetDevBindPipe(devId, &ctx->vi[devId].stBindPipe);
if (ret != 0)
ERR("VI dev %d set bind pipe failed ret: %d\n", devId, ret);
} else {
ERR("VI dev %d has been enabled\n", devId);
}
ret = RK_MPI_VI_SetChnAttr(devId, 0, &ctx->vi[devId].stChnAttr);
if (ret) {
ERR("VI dev %d set chn 0 attr error! ret=%d\n", devId, ret);
}
ret = RK_MPI_VI_EnableChn(devId, 0);
if (ret) {
ERR("create VI dev %d chn 0 error! ret=%d\n", devId, ret);
}
}
return 0;
}
static int avs_init(MPI_CTX_S *ctx)
{
int AvsGrp = 0, AvsChn = 0, ret, AvsPipe;
ret = RK_MPI_AVS_SetModParam(&ctx->avs.stAvsModParam);
if (0 != ret) {
printf("RK_MPI_AVS_SetModParam failed, ret is %#x\n", ret);
return ret;
}
ret = RK_MPI_AVS_CreateGrp(AvsGrp, &ctx->avs.stAvsGrpAttr);
if (0 != ret) {
printf("RK_MPI_AVS_CreateGrp failed, ret is %#x\n", ret);
return ret;
}
if (ctx->avs.stAvsGrpAttr.enMode == AVS_MODE_NOBLEND_OVL) {
for (AvsPipe = 0; AvsPipe < 2; AvsPipe++) {//todo pipe_num
ret = RK_MPI_AVS_SetPipeAttr(AvsGrp, AvsPipe, &ctx->avs.stAvsPipeAttr[AvsPipe]);
if (ret != 0) {
RK_LOGE("avs [%d, %d] RK_MPI_AVS_SetPipeAttr failed: %#x!",
AvsGrp, AvsPipe, ret);
return ret;
}
RK_LOGV("avs [%d, %d] RK_MPI_AVS_SetPipeAttr already.", AvsGrp, AvsPipe);
}
}
ret = RK_MPI_AVS_SetChnAttr(AvsGrp, AvsChn, &ctx->avs.stAvsChnAttr[0]);
if (0 != ret) {
printf("RK_MPI_AVS_SetChnAttr failed, ret is %#x\n", ret);
return ret;
}
ret = RK_MPI_AVS_EnableChn(AvsGrp, AvsChn);
if (0 != ret) {
printf("RK_MPI_AVS_EnableChn failed, ret is %#x\n", ret);
return ret;
}
ret = RK_MPI_AVS_StartGrp(AvsGrp);
if (0 != ret) {
printf("RK_MPI_AVS_StartGrp failed, ret is %#x\n", ret);
return ret;
}
}
static int venc_init(MPI_CTX_S *ctx)
{
int32_t ret = 0;
for (ctx->venc.s32ChnId = 0; ctx->venc.s32ChnId < VENC_CHN_NUM; ctx->venc.s32ChnId++) {
ret = RK_MPI_VENC_CreateChn(ctx->venc.s32ChnId, &ctx->venc.stChnAttr);
if (ret != 0) {
RK_LOGE("venc [%d] RK_MPI_VENC_CreateChn failed: %#x!",
ctx->venc.s32ChnId, ret);
return ret;
}
ret = RK_MPI_VENC_SetChnRefBufShareAttr(ctx->venc.s32ChnId, &ctx->venc.stVencChnRefBufShare);
if (ret != 0) {
RK_LOGE("venc [%d] RK_MPI_VENC_SetChnRefBufShareAttr failed: %#x!",
ctx->venc.s32ChnId, ret);
return ret;
}
ret = RK_MPI_VENC_SetRcParam(ctx->venc.s32ChnId, &ctx->venc.stRcParam);
if (ret != 0) {
RK_LOGE("venc [%d] RK_MPI_VENC_SetRcParam failed: %#x!",
ctx->venc.s32ChnId, ret);
return ret;
}
ret = RK_MPI_VENC_EnableSvc(ctx->venc.s32ChnId, RK_TRUE);
if (ret != 0) {
RK_LOGE("venc [%d] RK_MPI_VENC_EnableSvc failed: %#x!",
ctx->venc.s32ChnId, ret);
return ret;
}
ret = RK_MPI_VENC_StartRecvFrame(ctx->venc.s32ChnId, &ctx->venc.stRecvParam);
if (ret != 0) {
RK_LOGE("venc [%d] RK_MPI_VENC_StartRecvFrame failed: %#x!",
ctx->venc.s32ChnId, ret);
return ret;
}
}
return ret;
}
static int32_t vi_bind_venc()
{
int32_t ret;
MPP_CHN_S stSrcChn, stDestChn;
memset(&stSrcChn, 0, sizeof(stSrcChn));
memset(&stDestChn, 0, sizeof(stDestChn));
stSrcChn.enModId = RK_ID_VI;
stSrcChn.s32DevId = 0;
stSrcChn.s32ChnId = 0;
stDestChn.enModId = RK_ID_VENC;
stDestChn.s32DevId = 0;
stDestChn.s32ChnId = 0;
ret = RK_MPI_SYS_Bind(&stSrcChn, &stDestChn);
if (ret != 0)
ERR("VI dev 0 chn 0 bind VENC dev 0 chn 0 failed, ret: %d\n", ret);
return ret;
}
static int32_t vi_bind_avs()
{
int PipeId = 0;
int32_t ret;
MPP_CHN_S stSrcChn, stDestChn;
for (; PipeId < CAM_NUM; PipeId++) {
memset(&stSrcChn, 0, sizeof(stSrcChn));
memset(&stDestChn, 0, sizeof(stDestChn));
stSrcChn.enModId = RK_ID_VI;
stSrcChn.s32DevId = PipeId;
stSrcChn.s32ChnId = 0;
stDestChn.enModId = RK_ID_AVS;
stDestChn.s32DevId = 0;
stDestChn.s32ChnId = PipeId;
ret = RK_MPI_SYS_Bind(&stSrcChn, &stDestChn);
if (ret != 0)
ERR("VI dev %d chn 0 bind AVS dev 0 chn %d failed, ret: %d\n", PipeId, PipeId, ret);
}
return ret;
}
static int32_t avs_bind_venc()
{
int pipeId = 0;
int32_t ret;
MPP_CHN_S stSrcChn, stDestChn;
for (; pipeId < 1; pipeId++) {
memset(&stSrcChn, 0, sizeof(stSrcChn));
memset(&stDestChn, 0, sizeof(stDestChn));
stSrcChn.enModId = RK_ID_AVS;
stSrcChn.s32DevId = 0;
stSrcChn.s32ChnId = 0;
stDestChn.enModId = RK_ID_VENC;
stDestChn.s32DevId = 0;
stDestChn.s32ChnId = 0;
ret = RK_MPI_SYS_Bind(&stSrcChn, &stDestChn);
if (ret != 0)
ERR("AVS dev 0 chn 0 bind VENC dev 0 chn 0 failed, ret: %d\n", ret);
}
return ret;
}
static int32_t vi_unbind_venc()
{
int32_t ret;
MPP_CHN_S stSrcChn, stDestChn;
memset(&stSrcChn, 0, sizeof(stSrcChn));
memset(&stDestChn, 0, sizeof(stDestChn));
stSrcChn.enModId = RK_ID_VI;
stSrcChn.s32DevId = 0;
stSrcChn.s32ChnId = 0;
stDestChn.enModId = RK_ID_VENC;
stDestChn.s32DevId = 0;
stDestChn.s32ChnId = 0;
ret = RK_MPI_SYS_UnBind(&stSrcChn, &stDestChn);
if (ret != 0)
ERR("VI dev 0 chn 0 unbind VENC dev 0 chn 0 failed, ret: %d\n", ret);
return ret;
}
static int32_t vi_unbind_avs()
{
int PipeId = 0;
int32_t ret;
MPP_CHN_S stSrcChn, stDestChn;
for (; PipeId < CAM_NUM; PipeId++) {
memset(&stSrcChn, 0, sizeof(stSrcChn));
memset(&stDestChn, 0, sizeof(stDestChn));
stSrcChn.enModId = RK_ID_VI;
stSrcChn.s32DevId = PipeId;
stSrcChn.s32ChnId = 0;
stDestChn.enModId = RK_ID_AVS;
stDestChn.s32DevId = 0;
stDestChn.s32ChnId = PipeId;
ret = RK_MPI_SYS_UnBind(&stSrcChn, &stDestChn);
if (ret != 0)
ERR("VI dev %d chn 0 unbind AVS dev 0 chn %d failed, ret: %d\n", PipeId, PipeId, ret);
}
return ret;
}
static int32_t avs_unbind_venc()
{
int pipeId = 0;
int32_t ret;
MPP_CHN_S stSrcChn, stDestChn;
for (; pipeId < 1; pipeId++) {
memset(&stSrcChn, 0, sizeof(stSrcChn));
memset(&stDestChn, 0, sizeof(stDestChn));
stSrcChn.enModId = RK_ID_AVS;
stSrcChn.s32DevId = 0;
stSrcChn.s32ChnId = 0;
stDestChn.enModId = RK_ID_VENC;
stDestChn.s32DevId = 0;
stDestChn.s32ChnId = 0;
ret = RK_MPI_SYS_UnBind(&stSrcChn, &stDestChn);
if (ret != 0)
ERR("AVS dev 0 chn 0 unbind VENC dev 0 chn 0 failed, ret: %d\n", ret);
}
return ret;
}
static int32_t cover_osd_deinit(bool osd_en, bool cover_en, MPI_CTX_S *ctx)
{
int32_t ret = 0, rgnHandle_num = 1;
RGN_HANDLE rgnHandle;
if (osd_en && cover_en) {
rgnHandle_num = 2;
} else if (!(osd_en || cover_en)) {
rgnHandle_num = 0;
RK_LOGE("Osd and Cover has not been inited\n");
return 0;
} else {
rgnHandle_num = 1;
}
/* cover: rgn[0], osd: rgn[1] */
for (rgnHandle = 0; rgnHandle < rgnHandle_num; rgnHandle++) {
if (osd_en && !cover_en)
rgnHandle = 1;
ret = RK_MPI_RGN_DetachFromChn(rgnHandle, &ctx->rgn[rgnHandle].stMppChn);
if (0 != ret) {
RK_LOGE("RK_MPI_RGN_DetachFrmChn (%d) failed with %#x!", rgnHandle, ret);
return ret;
}
ret = RK_MPI_RGN_Destroy(rgnHandle);
if (0 != ret) {
RK_LOGE("RK_MPI_RGN_Destroy [%d] failed with %#x", rgnHandle, ret);
return ret;
}
}
}
static int32_t avs_deinit()
{
int32_t AvsGrp = 0, ret;
ret = RK_MPI_AVS_StopGrp(AvsGrp);
if (ret != 0) {
RK_LOGE("avs [%d, %d] RK_MPI_AVS_StopGrp failed: %#x!!",
AvsGrp, 0, ret);
return ret;
}
RK_LOGV("avs [%d, %d] RK_MPI_AVS_StopGrp already.", AvsGrp, 0);
ret = RK_MPI_AVS_DestroyGrp(AvsGrp);
if (ret != 0) {
RK_LOGE("avs [%d, %d] RK_MPI_AVS_DestroyGrp failed: %#x!!",
AvsGrp, 0, ret);
return ret;
}
RK_LOGV("avs [%d, %d] RK_MPI_AVS_DestroyGrp already.", AvsGrp, 0);
return 0;
}
static int32_t venc_deinit()
{
int ChnId = 0, ret = 0;
ret = RK_MPI_VENC_StopRecvFrame(ChnId);
if (ret != 0) {
RK_LOGE("venc %d RK_MPI_VENC_StopRecvFrame failed: %#x!!",
ChnId, ret);
return ret;
}
ret = RK_MPI_VENC_DestroyChn(ChnId);
if (ret != 0) {
RK_LOGE("venc %d RK_MPI_VENC_DestroyChn failed: %#x!!",
ChnId, ret);
return ret;
}
}
static int32_t vi_deinit()
{
int ret, DevId, ChnId = 0;
for (DevId = 0; DevId < CAM_NUM; DevId++) {
ret = RK_MPI_VI_DisableChn(DevId, ChnId);
if (ret != 0) {
RK_LOGE("vi dev %d chn %d RK_MPI_VI_DisableChn failed: %#x!!",
DevId, ChnId, ret);
return ret;
}
ret = RK_MPI_VI_DisableDev(DevId);
if (ret != 0) {
RK_LOGE("vi dev %d chn %d RK_MPI_VI_DisableDev failed: %#x!!",
DevId, ChnId, ret);
return ret;
}
}
}
static int aiq_deinit()
{
int CamId;
for (CamId = 0; CamId < CAM_NUM; CamId++) {
rk_aiq_uapi2_sysctl_stop(g_aiq_ctx[CamId], false);
rk_aiq_uapi2_sysctl_deinit(g_aiq_ctx[CamId]);
}
}
static int aiq_init_start(struct meta_info *handle, void *metaVirmem, int is_second_init, MPI_CTX_S *ctx)
{
int cam_hdr, camId, file_size, file_size_secondary, ret;
void *vir_iqaddr, *vir_iqaddr_scondary, *appVirAddr;
rk_aiq_working_mode_t hdr_mode;
rk_aiq_static_info_t aiq_static_info;
char *sensor_name;
file_size = (int)get_cmd_val("rk_iqbin_size", 16);
file_size_secondary = (int)get_cmd_val("rk_iqbin_secondary_size", 16);
vir_iqaddr = metaVirmem + SENSOR_IQ_BIN_OFFSET + offsetof(struct sensor_iq_info, data);
vir_iqaddr_scondary = metaVirmem + SENSOR_IQ_BIN_OFFSET + SENSOR_IQ_BIN_MAX_SIZE;
#if SERVER_DEBUG_PRT
dump_virmem_hex(vir_iqaddr, "main_aiq");
dump_virmem_hex(vir_iqaddr_scondary, "secondary_aiq");
#endif
cam_hdr = (int)get_cmd_val("rk_cam_hdr", 0);
hdr_mode = (cam_hdr == 5) ? RK_AIQ_WORKING_MODE_ISP_HDR2 : RK_AIQ_WORKING_MODE_NORMAL;
for (camId = 0; camId < CAM_NUM; camId++) {
rk_aiq_uapi2_sysctl_enumStaticMetasByPhyId(camId, &aiq_static_info);
sensor_name = aiq_static_info.sensor_info.sensor_name;
printf("sensor name: %s\n", sensor_name);
if (handle->app_params[0].color_mode) {
ret = rk_aiq_uapi2_sysctl_preInit_scene(sensor_name, "normal", "night");
printf("------night mode------\n");
} else {
ret = rk_aiq_uapi2_sysctl_preInit_scene(sensor_name, "normal", "day");
printf("------day mode------\n");
}
if (ret < 0)
ERR("%s: failed to set night scene\n", sensor_name);
klog("preinit scene\n");
if (camId == 0)
ret = rk_aiq_uapi2_sysctl_preInit_iq_addr(sensor_name, vir_iqaddr, file_size);
else
ret = rk_aiq_uapi2_sysctl_preInit_iq_addr(sensor_name, vir_iqaddr_scondary, file_size_secondary);
if (ret < 0)
ERR("%s: failed to load binary iqfiles\n", sensor_name);
klog("preinit iq addr\n");
rk_aiq_uapi2_sysctl_preInit_devBufCnt(sensor_name, "rkraw_rx", 2);
rk_aiq_tb_info_t tb_info;
if (is_second_init) {
memset(&tb_info, 0, sizeof(tb_info));
tb_info.magic = sizeof(rk_aiq_tb_info_t) - 2;
tb_info.is_pre_aiq = false;
tb_info.prd_type = RK_AIQ_PRD_TYPE_TB_BATIPC;
rk_aiq_uapi2_sysctl_preInit_tb_info(sensor_name, &tb_info);
klog("preinit tb info\n");
g_aiq_ctx[camId] = rk_aiq_uapi2_sysctl_init(sensor_name,
"/etc/iqfiles/", NULL, NULL);
} else {
memset(&tb_info, 0, sizeof(tb_info));
tb_info.magic = sizeof(rk_aiq_tb_info_t) - 2;
tb_info.is_pre_aiq = true;
tb_info.prd_type = RK_AIQ_PRD_TYPE_TB_BATIPC;
rk_aiq_uapi2_sysctl_preInit_tb_info(sensor_name, &tb_info);
klog("preinit tb info\n");
g_aiq_ctx[camId] = rk_aiq_uapi2_sysctl_init(sensor_name,
"/etc/iqfiles/", SAMPLE_COMM_ISP_ErrCb, NULL);
}
klog("aiq init\n");
if (g_aiq_ctx[camId] == NULL)
ERR("%s: failed to init aiq\n", sensor_name);
if (rk_aiq_uapi2_sysctl_prepare(g_aiq_ctx[camId], 0, 0, hdr_mode))
ERR("rkaiq engine prepare failed !\n");
klog("aiq prepare\n");
if (rk_aiq_uapi2_sysctl_start(g_aiq_ctx[camId]))
ERR("rk_aiq_uapi2_sysctl_start failed\n");
klog("aiq start\n");
}
return 0;
}
int32_t load_file_osdmem(const RK_CHAR *filename, uint8_t *pu8Virt, uint32_t u32Width,
uint32_t u32Height, uint32_t pixel_size, uint32_t shift_value) {
uint32_t mem_len = u32Width;
uint32_t read_len = mem_len * pixel_size >> shift_value;
uint32_t read_height;
FILE *file = NULL;
file = fopen(filename, "rb");
if (file == NULL) {
RK_LOGE("open filename: %s file failed!", filename);
return -1;
}
for (read_height = 0; read_height < u32Height; read_height++) {
fread((pu8Virt + (u32Width * read_height * pixel_size >> shift_value)), 1,
read_len, file);
}
fclose(file);
return 0;
}
static int param_init(MPI_CTX_S *ctx, struct meta_info *handle)
{
uint32_t fps = 0, gop = 0, enType = RK_VIDEO_ID_HEVC;
uint32_t i, enWorkMode, ret;
ctx->func.eptz_en = 1;
ctx->func.cover_en = 1;
ctx->func.avs_overlay_en = 0;
ctx->func.avs_splice_en = 1;
ctx->func.single_boot = 0;
ctx->func.switch_resolution = 1;
ctx->func.osd_en = 0;
if (ctx->func.avs_overlay_en)
enWorkMode = AVS_MODE_NOBLEND_OVL;
else if (ctx->func.avs_splice_en)
enWorkMode = AVS_MODE_NOBLEND_VER;
ret = access(OSD_FILE_PATH, 0);
if (ret == 0) {
ctx->func.osd_en = 1;
} else {
ctx->func.osd_en = 0;
}
/* VI parameters init */
for (i = 0; i < CAM_NUM; i++) {
ctx->vi[i].stChnAttr.stSize.u32Width = handle->sensor_init[i]->cam_w;
ctx->vi[i].stChnAttr.stSize.u32Height = handle->sensor_init[i]->cam_h;
ctx->vi[i].stChnAttr.stIspOpt.u32BufCount = 3;
ctx->vi[i].stChnAttr.stIspOpt.enMemoryType = VI_V4L2_MEMORY_TYPE_DMABUF;
ctx->vi[i].stChnAttr.stIspOpt.stMaxSize.u32Width = handle->sensor_init[i]->cam_w;
ctx->vi[i].stChnAttr.stIspOpt.stMaxSize.u32Height = handle->sensor_init[i]->cam_h;
ctx->vi[i].stChnAttr.enPixelFormat = RK_FMT_YUV420SP;
ctx->vi[i].stChnAttr.enCompressMode = COMPRESS_MODE_NONE;
ctx->vi[i].stChnAttr.u32Depth = 0;
ctx->vi[i].stChnAttr.stFrameRate.s32SrcFrameRate = -1;
ctx->vi[i].stChnAttr.stFrameRate.s32DstFrameRate = -1;
}
if (ctx->func.eptz_en) {
ctx->vi[g_eptz_dev].stEptz.u32MultipleOfZoom = 100;
ctx->vi[g_eptz_dev].stEptz.s32EptzViIndex = 1;
ctx->vi[g_eptz_dev].stEptz.u32ZoomStep = 1;
ctx->vi[g_eptz_dev].stEptz.u32ZoomSwitch = 270;
ctx->vi[g_eptz_dev].stEptz.u32ZoomLimit = 600;
}
/* VI parameters init END */
/* COVER parameters init */
/* Init RGN[0] */
if (ctx->func.cover_en) {
ctx->rgn[0].rgnHandle = 0;
ctx->rgn[0].stRgnAttr.enType = COVER_RGN;
ctx->rgn[0].stMppChn.enModId = RK_ID_VI;
ctx->rgn[0].stMppChn.s32ChnId = 0;
ctx->rgn[0].stMppChn.s32DevId = 0;
ctx->rgn[0].stRgnChnAttr.bShow = RK_TRUE;
ctx->rgn[0].stRgnChnAttr.enType = COVER_RGN;
ctx->rgn[0].stRgnChnAttr.unChnAttr.stCoverChn.stRect.s32X = 0;
ctx->rgn[0].stRgnChnAttr.unChnAttr.stCoverChn.stRect.s32Y = 480;
ctx->rgn[0].stRgnChnAttr.unChnAttr.stCoverChn.stRect.u32Width = 640;
ctx->rgn[0].stRgnChnAttr.unChnAttr.stCoverChn.stRect.u32Height = 240;
ctx->rgn[0].stRgnChnAttr.unChnAttr.stCoverChn.u32Color = 0x00ff00;
ctx->rgn[0].stRgnChnAttr.unChnAttr.stCoverChn.u32Layer = 1;
ctx->rgn[0].stRgnChnAttr.unChnAttr.stCoverChn.enCoordinate = RGN_ABS_COOR;
RK_LOGE("cover region %d <%d, %d, %d, %d>, color<0x%x>",
ctx->rgn[0].rgnHandle, ctx->rgn[0].stRgnChnAttr.unChnAttr.stCoverChn.stRect.s32X,
ctx->rgn[0].stRgnChnAttr.unChnAttr.stCoverChn.stRect.s32Y,
ctx->rgn[0].stRgnChnAttr.unChnAttr.stCoverChn.stRect.u32Width,
ctx->rgn[0].stRgnChnAttr.unChnAttr.stCoverChn.stRect.u32Height,
ctx->rgn[0].stRgnChnAttr.unChnAttr.stCoverChn.u32Color);
}
/* COVER parameters init END */
/* OSD OVERLAY parameters init */
if (ctx->func.osd_en) {
RK_CHAR *filename = OSD_FILE_PATH;
int u32Width = 128;
int u32Height = 128;
int s32X = 0;
int s32Y = 0;
ctx->rgn[1].rgnHandle = 1;
ctx->rgn[1].stMppChn.enModId = RK_ID_VENC;
ctx->rgn[1].stMppChn.s32DevId = 0;
ctx->rgn[1].stMppChn.s32ChnId = 0;
/****************************************
step 1: create overlay regions
****************************************/
ctx->rgn[1].stRgnAttr.enType = OVERLAY_RGN;
ctx->rgn[1].stRgnAttr.unAttr.stOverlay.enPixelFmt = (PIXEL_FORMAT_E)RK_FMT_ARGB8888;
ctx->rgn[1].stRgnAttr.unAttr.stOverlay.stSize.u32Width = u32Width;
ctx->rgn[1].stRgnAttr.unAttr.stOverlay.stSize.u32Height = u32Height;
ctx->rgn[1].stRgnAttr.unAttr.stOverlay.u32ClutNum = 0;
/*********************************************
step 2: display overlay regions to groups
*********************************************/
memset(&ctx->rgn[1].stRgnChnAttr, 0, sizeof(ctx->rgn[1].stRgnChnAttr));
ctx->rgn[1].stRgnChnAttr.bShow = RK_TRUE;
ctx->rgn[1].stRgnChnAttr.enType = OVERLAY_RGN;
ctx->rgn[1].stRgnChnAttr.unChnAttr.stOverlayChn.stPoint.s32X = s32X;
ctx->rgn[1].stRgnChnAttr.unChnAttr.stOverlayChn.stPoint.s32Y = s32Y;
ctx->rgn[1].stRgnChnAttr.unChnAttr.stOverlayChn.u32BgAlpha = 0;
ctx->rgn[1].stRgnChnAttr.unChnAttr.stOverlayChn.u32FgAlpha = 0;
ctx->rgn[1].stRgnChnAttr.unChnAttr.stOverlayChn.u32Layer = 0;
ctx->rgn[1].stRgnChnAttr.unChnAttr.stOverlayChn.stQpInfo.bEnable = RK_FALSE;
ctx->rgn[1].stRgnChnAttr.unChnAttr.stOverlayChn.stQpInfo.bForceIntra = RK_TRUE;
ctx->rgn[1].stRgnChnAttr.unChnAttr.stOverlayChn.stQpInfo.bAbsQp = RK_FALSE;
ctx->rgn[1].stRgnChnAttr.unChnAttr.stOverlayChn.stQpInfo.s32Qp = RK_FALSE;
ctx->rgn[1].stRgnChnAttr.unChnAttr.stOverlayChn.u32ColorLUT[0] = 0x00;
ctx->rgn[1].stRgnChnAttr.unChnAttr.stOverlayChn.u32ColorLUT[1] = 0xFFFFFF;
ctx->rgn[1].stRgnChnAttr.unChnAttr.stOverlayChn.stInvertColor.bInvColEn = RK_FALSE;
ctx->rgn[1].stRgnChnAttr.unChnAttr.stOverlayChn.stInvertColor.stInvColArea.u32Width = 16;
ctx->rgn[1].stRgnChnAttr.unChnAttr.stOverlayChn.stInvertColor.stInvColArea.u32Height = 16;
ctx->rgn[1].stRgnChnAttr.unChnAttr.stOverlayChn.stInvertColor.enChgMod = LESSTHAN_LUM_THRESH;
ctx->rgn[1].stRgnChnAttr.unChnAttr.stOverlayChn.stInvertColor.u32LumThresh = 100;
/*********************************************
step 3: show bitmap
*********************************************/
RK_S64 s64ShowBmpStart = TEST_COMM_GetNowUs();
ctx->rgn[1].stBitmap.enPixelFormat = (PIXEL_FORMAT_E)RK_FMT_ARGB8888;
ctx->rgn[1].stBitmap.u32Width = u32Width;
ctx->rgn[1].stBitmap.u32Height = u32Height;
RK_U16 ColorBlockSize = ctx->rgn[1].stBitmap.u32Height * ctx->rgn[1].stBitmap.u32Width;
ctx->rgn[1].stBitmap.pData = malloc(ColorBlockSize * TEST_ARGB32_PIX_SIZE);
uint8_t *ColorData = (uint8_t *)ctx->rgn[1].stBitmap.pData;
if (filename) {
uint32_t ret = load_file_osdmem(filename, ctx->rgn[1].stBitmap.pData, u32Width, u32Height,
TEST_ARGB32_PIX_SIZE, 0);
if (0 != ret) {
set_argb8888_buffer((uint32_t *)ColorData, ColorBlockSize / 4, TEST_ARGB32_RED);
set_argb8888_buffer((uint32_t *)(ColorData + ColorBlockSize),
ColorBlockSize / 4, TEST_ARGB32_GREEN);
set_argb8888_buffer((uint32_t *)(ColorData + 2 * ColorBlockSize),
ColorBlockSize / 4, TEST_ARGB32_BLUE);
set_argb8888_buffer((uint32_t *)(ColorData + 3 * ColorBlockSize),
ColorBlockSize / 4, TEST_ARGB32_BLACK);
}
}
}
/* OSD OVERLAY parameters init END */
/* AVS parameters init */
//assume assist sensor is small resolution use it as default
switch (enWorkMode) {
case AVS_MODE_NOBLEND_VER:
/* Splicing mode */
ctx->avs.stAvsModParam.u32WorkingSetSize = 0;
ctx->avs.stAvsModParam.enMBSource = MB_SOURCE_PRIVATE;
ctx->avs.stAvsGrpAttr.enMode = AVS_MODE_NOBLEND_VER;
ctx->avs.stAvsGrpAttr.bSyncPipe = 0;
ctx->avs.stAvsGrpAttr.u32PipeNum = 2;
ctx->avs.stAvsGrpAttr.stGainAttr.enMode = AVS_GAIN_MODE_AUTO;
ctx->avs.stAvsGrpAttr.stFrameRate.s32SrcFrameRate = -1;
ctx->avs.stAvsChnAttr[0].enCompressMode = COMPRESS_MODE_NONE;
ctx->avs.stAvsChnAttr[0].stFrameRate.s32SrcFrameRate = -1;
ctx->avs.stAvsChnAttr[0].stFrameRate.s32DstFrameRate = -1;
ctx->avs.stAvsChnAttr[0].u32Depth = 0;
ctx->avs.stAvsChnAttr[0].u32Width = handle->sensor_init[1]->cam_w;
ctx->avs.stAvsChnAttr[0].u32Height = handle->sensor_init[1]->cam_h * 2;
ctx->avs.stAvsChnAttr[0].enDynamicRange = DYNAMIC_RANGE_SDR8;
ctx->avs.stAvsChnAttr[0].u32FrameBufCnt = 2;
break;
case AVS_MODE_NOBLEND_OVL:
/* Overlay mode */
ctx->avs.stAvsModParam.u32WorkingSetSize = 0;
ctx->avs.stAvsModParam.enMBSource = MB_SOURCE_PRIVATE;
ctx->avs.stAvsGrpAttr.enMode = AVS_MODE_NOBLEND_OVL;
ctx->avs.stAvsGrpAttr.u32PipeNum = 2;
ctx->avs.stAvsGrpAttr.stGainAttr.enMode = AVS_GAIN_MODE_AUTO;
ctx->avs.stAvsGrpAttr.stOutAttr.stSize.u32Width = handle->sensor_init[1]->cam_w;
ctx->avs.stAvsGrpAttr.stOutAttr.stSize.u32Height = handle->sensor_init[1]->cam_h;
for (int32_t i = 0; i < 2; i++) {//todo pipe num
ctx->avs.stAvsPipeAttr[i].u32Priority = i;
ctx->avs.stAvsPipeAttr[i].stSrcRect.s32X = 0;
ctx->avs.stAvsPipeAttr[i].stSrcRect.s32Y = 0;
ctx->avs.stAvsPipeAttr[i].stSrcRect.u32Width = handle->sensor_init[i]->cam_w;
ctx->avs.stAvsPipeAttr[i].stSrcRect.u32Height = handle->sensor_init[i]->cam_h;
if (0 == i) {
ctx->avs.stAvsPipeAttr[i].stDstRect.u32Width = handle->sensor_init[1]->cam_w;
ctx->avs.stAvsPipeAttr[i].stDstRect.u32Height = handle->sensor_init[1]->cam_h;
ctx->avs.stAvsPipeAttr[i].stDstRect.s32X = 0;
ctx->avs.stAvsPipeAttr[i].stDstRect.s32Y = 0;
} else {
ctx->avs.stAvsPipeAttr[i].stDstRect.u32Width = handle->sensor_init[1]->cam_w / 4;
ctx->avs.stAvsPipeAttr[i].stDstRect.u32Height = handle->sensor_init[1]->cam_h / 4;
ctx->avs.stAvsPipeAttr[i].stDstRect.s32X = 0;
ctx->avs.stAvsPipeAttr[i].stDstRect.s32Y = 0;
}
}
ctx->avs.stAvsChnAttr[0].enCompressMode = COMPRESS_MODE_NONE;
ctx->avs.stAvsChnAttr[0].stFrameRate.s32SrcFrameRate = -1;
ctx->avs.stAvsChnAttr[0].stFrameRate.s32DstFrameRate = -1;
ctx->avs.stAvsChnAttr[0].u32Depth = 0;
ctx->avs.stAvsChnAttr[0].u32Width = handle->sensor_init[1]->cam_w;
ctx->avs.stAvsChnAttr[0].u32Height = handle->sensor_init[1]->cam_h;
ctx->avs.stAvsChnAttr[0].enDynamicRange = DYNAMIC_RANGE_SDR8;
ctx->avs.stAvsChnAttr[0].u32FrameBufCnt = 2;
break;
default:
ERR("unsupport avs mode\n");
}
/* AVS parameters init END */
/* VENC parameters init */
fps = (uint32_t)get_cmd_val("rk_cam_fps", 10);
RK_ASSERT(fps > 0);
gop = fps * 2;
memset(&ctx->venc.stChnAttr,0,sizeof(ctx->venc.stChnAttr));
memset(&ctx->venc.stVencChnRefBufShare, 0, sizeof(ctx->venc.stVencChnRefBufShare));
ctx->venc.s32ChnNum = 1;
if (handle->app_params->venc_type == 1)
ctx->venc.enCodecType = RK_VIDEO_ID_AVC;
else
ctx->venc.enCodecType = RK_VIDEO_ID_HEVC;
if (ctx->venc.enCodecType == RK_VIDEO_ID_AVC) {
ctx->venc.stChnAttr.stRcAttr.enRcMode = VENC_RC_MODE_H264VBR;
ctx->venc.stChnAttr.stRcAttr.stH264Vbr.u32BitRate = handle->app_params->venc_bitrate;
ctx->venc.stChnAttr.stRcAttr.stH264Vbr.u32MaxBitRate = handle->app_params->venc_bitrate;
ctx->venc.stChnAttr.stRcAttr.stH264Vbr.u32MinBitRate = 200;
ctx->venc.stChnAttr.stRcAttr.stH264Vbr.u32Gop = gop;
ctx->venc.stChnAttr.stRcAttr.stH264Vbr.u32SrcFrameRateNum = fps;
ctx->venc.stChnAttr.stRcAttr.stH264Vbr.u32SrcFrameRateDen = 1;
ctx->venc.stChnAttr.stRcAttr.stH264Vbr.fr32DstFrameRateNum = fps;
ctx->venc.stChnAttr.stRcAttr.stH264Vbr.fr32DstFrameRateDen = 1;
} else if (ctx->venc.enCodecType == RK_VIDEO_ID_HEVC) {
ctx->venc.stChnAttr.stRcAttr.enRcMode = VENC_RC_MODE_H265VBR;
ctx->venc.stChnAttr.stRcAttr.stH265Vbr.u32BitRate = handle->app_params->venc_bitrate;
ctx->venc.stChnAttr.stRcAttr.stH265Vbr.u32MaxBitRate = handle->app_params->venc_bitrate;
ctx->venc.stChnAttr.stRcAttr.stH265Vbr.u32MinBitRate = 200;
ctx->venc.stChnAttr.stRcAttr.stH265Vbr.u32Gop = gop;
ctx->venc.stChnAttr.stRcAttr.stH265Vbr.u32SrcFrameRateNum = fps;
ctx->venc.stChnAttr.stRcAttr.stH265Vbr.u32SrcFrameRateDen = 1;
ctx->venc.stChnAttr.stRcAttr.stH265Vbr.fr32DstFrameRateNum = fps;
ctx->venc.stChnAttr.stRcAttr.stH265Vbr.fr32DstFrameRateDen = 1;
}
ctx->venc.stChnAttr.stVencAttr.enType = ctx->venc.enCodecType;
ctx->venc.stChnAttr.stVencAttr.enPixelFormat = RK_FMT_YUV420SP;
if (ctx->venc.enCodecType == RK_VIDEO_ID_AVC)
ctx->venc.stChnAttr.stVencAttr.u32Profile = H264E_PROFILE_HIGH;
else if (ctx->venc.enCodecType == RK_VIDEO_ID_HEVC)
ctx->venc.stChnAttr.stVencAttr.u32Profile = H265E_PROFILE_MAIN;
if (ctx->avs.stAvsGrpAttr.enMode == AVS_MODE_NOBLEND_VER) {
//assume assist sensor is small resolution use it as default
ctx->venc.stChnAttr.stVencAttr.u32PicWidth = handle->sensor_init[1]->cam_w;
ctx->venc.stChnAttr.stVencAttr.u32VirWidth = handle->sensor_init[1]->cam_w;
ctx->venc.stChnAttr.stVencAttr.u32PicHeight = handle->sensor_init[1]->cam_h * 2;
ctx->venc.stChnAttr.stVencAttr.u32VirHeight = handle->sensor_init[1]->cam_h * 2;
ctx->venc.stChnAttr.stVencAttr.u32MaxPicWidth = handle->sensor_init[1]->cam_w;
ctx->venc.stChnAttr.stVencAttr.u32MaxPicHeight = handle->sensor_init[1]->cam_h * 2;
ctx->venc.stChnAttr.stVencAttr.u32BufSize = ctx->venc.stChnAttr.stVencAttr.u32PicWidth * ctx->venc.stChnAttr.stVencAttr.u32PicHeight / 2;
} else if (ctx->avs.stAvsGrpAttr.enMode == AVS_MODE_NOBLEND_OVL) {
//use assist sensor resolution as default
ctx->venc.stChnAttr.stVencAttr.u32PicWidth = handle->sensor_init[1]->cam_w;
ctx->venc.stChnAttr.stVencAttr.u32PicHeight = handle->sensor_init[1]->cam_h;
ctx->venc.stChnAttr.stVencAttr.u32VirWidth = handle->sensor_init[1]->cam_w;
ctx->venc.stChnAttr.stVencAttr.u32VirHeight = handle->sensor_init[1]->cam_h;
ctx->venc.stChnAttr.stVencAttr.u32MaxPicWidth = handle->sensor_init[1]->cam_w;
ctx->venc.stChnAttr.stVencAttr.u32MaxPicHeight = handle->sensor_init[1]->cam_h;
ctx->venc.stChnAttr.stVencAttr.u32BufSize = handle->sensor_init[1]->cam_w * handle->sensor_init[1]->cam_h / 2;
}
if (ctx->func.single_boot) {
ctx->venc.stChnAttr.stVencAttr.u32PicWidth = handle->sensor_init[0]->cam_w;
ctx->venc.stChnAttr.stVencAttr.u32PicHeight = handle->sensor_init[0]->cam_h;
ctx->venc.stChnAttr.stVencAttr.u32VirWidth = handle->sensor_init[0]->cam_w;
ctx->venc.stChnAttr.stVencAttr.u32VirHeight = handle->sensor_init[0]->cam_h;
ctx->venc.stChnAttr.stVencAttr.u32MaxPicWidth = handle->sensor_init[0]->cam_w;
ctx->venc.stChnAttr.stVencAttr.u32MaxPicHeight = handle->sensor_init[0]->cam_h;
ctx->venc.stChnAttr.stVencAttr.u32BufSize = handle->sensor_init[0]->cam_w * handle->sensor_init[0]->cam_h / 2;
}
ctx->venc.stChnAttr.stVencAttr.u32StreamBufCnt = 4;
ctx->venc.stChnAttr.stVencAttr.enMirror = MIRROR_NONE;
ctx->venc.stVencChnRefBufShare.bEnable = true;
memset(&ctx->venc.stRcParam, 0, sizeof(ctx->venc.stRcParam));
if (ctx->venc.enCodecType == RK_VIDEO_ID_AVC) {
ctx->venc.stRcParam.s32FirstFrameStartQp = 28;
ctx->venc.stRcParam.stParamH264.u32MinQp = 10;
ctx->venc.stRcParam.stParamH264.u32MaxQp = 51;
ctx->venc.stRcParam.stParamH264.u32MinIQp = 10;
ctx->venc.stRcParam.stParamH264.u32MaxIQp = 51;
ctx->venc.stRcParam.stParamH264.u32FrmMinQp = 25;
ctx->venc.stRcParam.stParamH264.u32FrmMinIQp = 24;
ctx->venc.stRcParam.stParamH264.u32FrmMaxQp = 41;
ctx->venc.stRcParam.stParamH264.u32FrmMaxIQp = 35;
} else if (ctx->venc.enCodecType == RK_VIDEO_ID_HEVC) {
ctx->venc.stRcParam.s32FirstFrameStartQp = 28;
ctx->venc.stRcParam.stParamH265.u32MinQp = 10;
ctx->venc.stRcParam.stParamH265.u32MaxQp = 51;
ctx->venc.stRcParam.stParamH265.u32MinIQp = 10;
ctx->venc.stRcParam.stParamH265.u32MaxIQp = 51;
ctx->venc.stRcParam.stParamH265.u32FrmMinQp = 25;
ctx->venc.stRcParam.stParamH265.u32FrmMinIQp = 24;
ctx->venc.stRcParam.stParamH265.u32FrmMaxQp = 41;
ctx->venc.stRcParam.stParamH265.u32FrmMaxIQp = 35;
}
memset(&ctx->venc.stRecvParam, 0, sizeof(ctx->venc.stRecvParam));
ctx->venc.stRecvParam.s32RecvPicNum = -1;
/* VENC parameters init END */
return 0;
}
static void aiq_quit()
{
int camId = 0;
for (; camId < CAM_NUM; camId++) {
if (g_aiq_ctx[camId]) {
klog("should quit\n");
rk_aiq_uapi2_sysctl_stop(g_aiq_ctx[camId], false);
klog("aiq stop\n");
rk_aiq_uapi2_sysctl_deinit(g_aiq_ctx[camId]);
klog("aiq deinit\n");
}
}
}
int echo(char *file_path, char *buf, int lenth)
{
FILE *fp = NULL;
fp = fopen(file_path, "w");
if (fp == NULL) {
perror("fopen error\n");
return -1;
}
if (lenth > fwrite(buf, 1, lenth, fp))
{
ERR("fwrite error\n");
fclose(fp);
return -1;
}
INFO("echo \"%s\" > %s successfully\n", buf, file_path);
fclose(fp);
return 0;
}
int main(int argc, char *argv[])
{
klog("main\n");
MPI_CTX_S ctx;
void *metaVirmem = NULL;
int meta_size, ret;
struct meta_info handle;
struct sigaction action;
action.sa_handler = handle_pipe;
sigemptyset(&action.sa_mask);
action.sa_flags = 0;
handle.sensor_init[0] = (struct sensor_init_cfg *)malloc(sizeof(struct sensor_init_cfg));
handle.sensor_init[1] = (struct sensor_init_cfg *)malloc(sizeof(struct sensor_init_cfg));
handle.app_params = (struct app_param_info *)malloc(sizeof(struct app_param_info));
g_s32FrameCnt = RUN_TOTAL_CNT_MAX;
sigaction(SIGPIPE, &action, NULL);
signal(SIGINT, sigterm_handler);
if (RK_MPI_SYS_Init() != 0) {
goto __FAILED;
}
klog("mpi sys init\n");
meta_size = (uint32_t)get_cmd_val("meta_part_size", 16);
metaVirmem = get_meta_params(&handle);
if (metaVirmem == MAP_FAILED)
goto __FAILED;
#if SERVER_DEBUG_PRT
dump_meta_sensor_app_params(&handle);
#endif
memset(&ctx, 0, sizeof(MPI_CTX_S));
/*
* single cam boot
* vi dev0 chn0 -> venc chn 0
*
* dual cam boot
* vi dev0 chn0 -> avs pipe 0->avs (avs input)
* vi dev1 chn0 -> avs pipe 1->avs (avs input)
* avs chn 0 -> venc (avs output)
* cover -> vi dev0 chn0
* osd -> venc chn0
*/
param_init(&ctx, &handle);
venc_init(&ctx);
vi_init(&ctx);
if (ctx.func.single_boot)
vi_bind_venc();
else {
avs_init(&ctx);
vi_bind_avs();
avs_bind_venc();
}
if (ctx.func.cover_en)
cover_init(&ctx);
if (ctx.func.osd_en)
osd_init(&ctx);
ret = aiq_init_start(&handle, metaVirmem, false, &ctx);
if (ret)
goto __FAILED;
if (ctx.func.eptz_en) {
INFO("eptz is enabled, fix isp aclk to 350MHz, core_clk to 420MHz\n");
echo("/proc/clk/rate", ISP_CLK_CORE_RATE, sizeof(ISP_CLK_CORE_RATE));
echo("/proc/clk/rate", ISP_ACLK_RATE, sizeof(ISP_ACLK_RATE));
}
#if (ENABLE_RTSP)
rtsp_init();
#endif
pthread_t main_thread0;
pthread_create(&main_thread0, NULL, GetVencStream, &ctx);
int loop_cnt = 0x400;
while (1) {
if (g_should_quit) {
aiq_quit();
break;
}
usleep(1 * 1000); // when client online
if (loop_cnt-- == 0) {
klog("aiq timeout exit\n");
break;
}
}
ret = aiq_init_start(&handle, metaVirmem, true, &ctx);
pthread_join(main_thread0, RK_NULL);
#if (ENABLE_RTSP)
if (g_rtsplive)
rtsp_del_demo(g_rtsplive);
#endif
__FAILED:
vi_unbind_avs();
avs_unbind_venc();
avs_deinit();
cover_osd_deinit(ctx.func.osd_en, ctx.func.cover_en, &ctx);
venc_deinit();
vi_deinit();
aiq_deinit();
if (metaVirmem != MAP_FAILED)
munmap(metaVirmem, meta_size);
printf("app exit\n");
return 0;
}