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>
730 lines
21 KiB
C
730 lines
21 KiB
C
/* thunder boot service
|
|
/1.aiq init & run
|
|
/2.rockit vi & venc init, bind
|
|
*/
|
|
#include <dlfcn.h>
|
|
#include <errno.h>
|
|
#include <fcntl.h>
|
|
#include <sched.h>
|
|
#include <signal.h>
|
|
#include <stdbool.h>
|
|
#include <stddef.h>
|
|
#include <stdio.h>
|
|
#include <sys/mman.h>
|
|
#include <sys/poll.h>
|
|
#include <sys/stat.h>
|
|
#include <sys/types.h>
|
|
#include <time.h>
|
|
#include <unistd.h>
|
|
|
|
#include "rk_debug.h"
|
|
#include "rk_defines.h"
|
|
#include "rk_mpi_sys.h"
|
|
#include "rk_mpi_venc.h"
|
|
#include "rk_mpi_vi.h"
|
|
#include "rk_type.h"
|
|
#include <rk_aiq_user_api2_camgroup.h>
|
|
#include <rk_aiq_user_api2_imgproc.h>
|
|
#include <rk_aiq_user_api2_sysctl.h>
|
|
|
|
#include "rk_gpio.h"
|
|
#include "rk_meta.h"
|
|
#include "rk_meta_app_param.h"
|
|
#include "sensor_init_info.h"
|
|
#include "sensor_iq_info.h"
|
|
|
|
#define RKAIQ
|
|
|
|
#ifdef RKAIQ_USE_DLOPEN
|
|
void *rkaiq_dl = NULL;
|
|
XCamReturn (*dlsym_rk_aiq_uapi2_sysctl_enumStaticMetas)(int, rk_aiq_static_info_t*);
|
|
XCamReturn (*dlsym_rk_aiq_uapi2_sysctl_preInit_scene)(const char*, const char*, const char*);
|
|
XCamReturn (*dlsym_rk_aiq_uapi2_sysctl_preInit_iq_addr)(const char*, void *, size_t);
|
|
XCamReturn (*dlsym_rk_aiq_uapi2_sysctl_preInit_tb_info)(const char*, const rk_aiq_tb_info_t*);
|
|
rk_aiq_sys_ctx_t* (*dlsym_rk_aiq_uapi2_sysctl_init)(const char*,
|
|
const char*,
|
|
rk_aiq_error_cb ,
|
|
rk_aiq_metas_cb );
|
|
|
|
XCamReturn (*dlsym_rk_aiq_uapi2_sysctl_prepare)(const rk_aiq_sys_ctx_t*,
|
|
uint32_t , uint32_t ,
|
|
rk_aiq_working_mode_t );
|
|
|
|
XCamReturn (*dlsym_rk_aiq_uapi2_sysctl_start)(const rk_aiq_sys_ctx_t *);
|
|
XCamReturn (*dlsym_rk_aiq_uapi2_sysctl_stop)(const rk_aiq_sys_ctx_t*, bool);
|
|
XCamReturn (*dlsym_rk_aiq_uapi2_sysctl_deinit)(const rk_aiq_sys_ctx_t*);
|
|
#endif
|
|
//#define ENABLE_GET_STREAM
|
|
|
|
#define MAP_SIZE (4096UL * 50) // MAP_SIZE = 4 * 50 K
|
|
#define MAP_MASK (MAP_SIZE - 1) // MAP_MASK = 0XFFF
|
|
|
|
#define MAP_SIZE_NIGHT (4096UL) // MAP_SIZE = 4K
|
|
#define MAP_MASK_NIGHT (MAP_SIZE_NIGHT - 1) // MAP_MASK = 0XFFF
|
|
|
|
static FILE *venc0_file = NULL;
|
|
static RK_S32 g_s32FrameCnt = -1;
|
|
static VI_CHN_BUF_WRAP_S g_stViWrap;
|
|
static bool g_bWrap = true;
|
|
static RK_U32 g_u32WrapLine = 0;
|
|
static char *g_sEntityName = NULL;
|
|
static bool quit = false;
|
|
static struct app_param_info *g_pAppParam = NULL;
|
|
static struct sensor_init_cfg *g_pSensorInitParam = NULL;
|
|
|
|
static void sigterm_handler(int sig) { quit = true; }
|
|
|
|
#ifdef ENABLE_AOV
|
|
#define AOV_LUNCH_FILE "/tmp/aov_lunch"
|
|
#endif
|
|
|
|
#ifdef RKAIQ_USE_DLOPEN
|
|
static int dlsym_rkaiq (void)
|
|
{
|
|
rkaiq_dl = dlopen("/usr/lib/librkaiq.so", RTLD_LAZY);
|
|
if (!rkaiq_dl) {
|
|
printf("\ndlopen /usr/lib/librkaiq.so error\n");
|
|
return -1;
|
|
}
|
|
dlsym_rk_aiq_uapi2_sysctl_enumStaticMetas = dlsym(rkaiq_dl, "rk_aiq_uapi2_sysctl_enumStaticMetas");
|
|
dlsym_rk_aiq_uapi2_sysctl_preInit_scene = dlsym(rkaiq_dl, "rk_aiq_uapi2_sysctl_preInit_scene");
|
|
dlsym_rk_aiq_uapi2_sysctl_preInit_iq_addr = dlsym(rkaiq_dl, "rk_aiq_uapi2_sysctl_preInit_iq_addr");
|
|
dlsym_rk_aiq_uapi2_sysctl_preInit_tb_info = dlsym(rkaiq_dl, "rk_aiq_uapi2_sysctl_preInit_tb_info");
|
|
dlsym_rk_aiq_uapi2_sysctl_init = dlsym(rkaiq_dl, "rk_aiq_uapi2_sysctl_init");
|
|
dlsym_rk_aiq_uapi2_sysctl_prepare = dlsym(rkaiq_dl, "rk_aiq_uapi2_sysctl_prepare");
|
|
dlsym_rk_aiq_uapi2_sysctl_start = dlsym(rkaiq_dl, "rk_aiq_uapi2_sysctl_start");
|
|
dlsym_rk_aiq_uapi2_sysctl_stop = dlsym(rkaiq_dl, "rk_aiq_uapi2_sysctl_stop");
|
|
dlsym_rk_aiq_uapi2_sysctl_deinit = dlsym(rkaiq_dl, "rk_aiq_uapi2_sysctl_deinit");
|
|
return 0;
|
|
}
|
|
#else
|
|
#define dlsym_rk_aiq_uapi2_sysctl_enumStaticMetas rk_aiq_uapi2_sysctl_enumStaticMetas
|
|
#define dlsym_rk_aiq_uapi2_sysctl_preInit_scene rk_aiq_uapi2_sysctl_preInit_scene
|
|
#define dlsym_rk_aiq_uapi2_sysctl_preInit_iq_addr rk_aiq_uapi2_sysctl_preInit_iq_addr
|
|
#define dlsym_rk_aiq_uapi2_sysctl_preInit_tb_info rk_aiq_uapi2_sysctl_preInit_tb_info
|
|
#define dlsym_rk_aiq_uapi2_sysctl_init rk_aiq_uapi2_sysctl_init
|
|
#define dlsym_rk_aiq_uapi2_sysctl_prepare rk_aiq_uapi2_sysctl_prepare
|
|
#define dlsym_rk_aiq_uapi2_sysctl_start rk_aiq_uapi2_sysctl_start
|
|
#define dlsym_rk_aiq_uapi2_sysctl_stop rk_aiq_uapi2_sysctl_stop
|
|
#define dlsym_rk_aiq_uapi2_sysctl_deinit rk_aiq_uapi2_sysctl_deinit
|
|
#endif
|
|
|
|
/*
|
|
* * 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);
|
|
printf("get %s value: 0x%0lx\n", string, value);
|
|
}
|
|
return value;
|
|
}
|
|
|
|
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 */
|
|
}
|
|
|
|
#ifdef ENABLE_GET_STREAM
|
|
|
|
// fast client to get media buffer.
|
|
static void *GetMediaBuffer0(void *arg) {
|
|
(void)arg;
|
|
void *pData = RK_NULL;
|
|
int loopCount = 0;
|
|
int s32Ret;
|
|
VENC_STREAM_S stFrame;
|
|
|
|
FILE *fp = fopen("/tmp/pts.txt", "wb");
|
|
|
|
stFrame.pstPack = malloc(sizeof(VENC_PACK_S));
|
|
|
|
while (!quit) {
|
|
s32Ret = RK_MPI_VENC_GetStream(0, &stFrame, -1);
|
|
if (s32Ret == RK_SUCCESS) {
|
|
if (venc0_file) {
|
|
pData = RK_MPI_MB_Handle2VirAddr(stFrame.pstPack->pMbBlk);
|
|
fwrite(pData, 1, stFrame.pstPack->u32Len, venc0_file);
|
|
fflush(venc0_file);
|
|
}
|
|
RK_U64 nowUs = TEST_COMM_GetNowUs();
|
|
|
|
printf("chn:0, loopCount:%d enc->seq:%d wd:%d pts=%lld delay=%lldus\n",
|
|
loopCount, stFrame.u32Seq, stFrame.pstPack->u32Len,
|
|
stFrame.pstPack->u64PTS, nowUs - stFrame.pstPack->u64PTS);
|
|
if (fp) {
|
|
char str[128];
|
|
snprintf(str, sizeof(str), "seq:%u, pts:%llums\n", stFrame.u32Seq,
|
|
stFrame.pstPack->u64PTS / 1000);
|
|
fputs(str, fp);
|
|
fsync(fileno(fp));
|
|
}
|
|
|
|
s32Ret = RK_MPI_VENC_ReleaseStream(0, &stFrame);
|
|
loopCount++;
|
|
} else {
|
|
printf("RK_MPI_VENC_GetChnFrame fail %x\n", s32Ret);
|
|
}
|
|
|
|
if ((g_s32FrameCnt >= 0) && (loopCount > g_s32FrameCnt)) {
|
|
quit = true;
|
|
break;
|
|
}
|
|
|
|
usleep(10 * 1000);
|
|
}
|
|
|
|
if (venc0_file)
|
|
fclose(venc0_file);
|
|
|
|
if (fp)
|
|
fclose(fp);
|
|
|
|
free(stFrame.pstPack);
|
|
return NULL;
|
|
}
|
|
#endif
|
|
|
|
static RK_S32 test_venc_init(int chnId, int width, int height, int max_width,
|
|
int max_height, RK_CODEC_ID_E enType) {
|
|
VENC_RECV_PIC_PARAM_S stRecvParam;
|
|
VENC_CHN_BUF_WRAP_S stVencChnBufWrap;
|
|
VENC_CHN_REF_BUF_SHARE_S stVencChnRefBufShare;
|
|
VENC_CHN_ATTR_S stAttr;
|
|
RK_U32 fps = 0;
|
|
RK_U32 gop = 0;
|
|
|
|
fps = (RK_U32)get_cmd_val("rk_cam_fps", 10);
|
|
RK_ASSERT(fps > 0);
|
|
gop = fps * 2;
|
|
|
|
memset(&stAttr, 0, sizeof(VENC_CHN_ATTR_S));
|
|
|
|
memset(&stVencChnRefBufShare, 0, sizeof(VENC_CHN_REF_BUF_SHARE_S));
|
|
stVencChnRefBufShare.bEnable = true;
|
|
|
|
#if 0
|
|
if (enType == RK_VIDEO_ID_AVC) {
|
|
stAttr.stRcAttr.enRcMode = VENC_RC_MODE_H264CBR;
|
|
stAttr.stRcAttr.stH264Cbr.u32BitRate = g_pAppParam->venc_bitrate;
|
|
stAttr.stRcAttr.stH264Cbr.u32Gop = gop;
|
|
} else if (enType == RK_VIDEO_ID_HEVC) {
|
|
stAttr.stRcAttr.enRcMode = VENC_RC_MODE_H265CBR;
|
|
stAttr.stRcAttr.stH265Cbr.u32BitRate = g_pAppParam->venc_bitrate;
|
|
stAttr.stRcAttr.stH265Cbr.u32Gop = gop;
|
|
}
|
|
#endif
|
|
if (enType == RK_VIDEO_ID_AVC) {
|
|
stAttr.stRcAttr.enRcMode = VENC_RC_MODE_H264VBR;
|
|
stAttr.stRcAttr.stH264Vbr.u32BitRate = g_pAppParam->venc_bitrate;
|
|
stAttr.stRcAttr.stH264Vbr.u32MaxBitRate = g_pAppParam->venc_bitrate;
|
|
stAttr.stRcAttr.stH264Vbr.u32MinBitRate = 200;
|
|
stAttr.stRcAttr.stH264Vbr.u32Gop = gop;
|
|
stAttr.stRcAttr.stH264Vbr.u32SrcFrameRateNum = fps;
|
|
stAttr.stRcAttr.stH264Vbr.u32SrcFrameRateDen = 1;
|
|
stAttr.stRcAttr.stH264Vbr.fr32DstFrameRateNum = fps;
|
|
stAttr.stRcAttr.stH264Vbr.fr32DstFrameRateDen = 1;
|
|
} else if (enType == RK_VIDEO_ID_HEVC) {
|
|
stAttr.stRcAttr.enRcMode = VENC_RC_MODE_H265VBR;
|
|
stAttr.stRcAttr.stH265Vbr.u32BitRate = g_pAppParam->venc_bitrate;
|
|
stAttr.stRcAttr.stH265Vbr.u32MaxBitRate = g_pAppParam->venc_bitrate;
|
|
stAttr.stRcAttr.stH265Vbr.u32MinBitRate = 200;
|
|
stAttr.stRcAttr.stH265Vbr.u32Gop = gop;
|
|
stAttr.stRcAttr.stH265Vbr.u32SrcFrameRateNum = fps;
|
|
stAttr.stRcAttr.stH265Vbr.u32SrcFrameRateDen = 1;
|
|
stAttr.stRcAttr.stH265Vbr.fr32DstFrameRateNum = fps;
|
|
stAttr.stRcAttr.stH265Vbr.fr32DstFrameRateDen = 1;
|
|
}
|
|
|
|
stAttr.stVencAttr.enType = enType;
|
|
stAttr.stVencAttr.enPixelFormat = RK_FMT_YUV420SP;
|
|
if (enType == RK_VIDEO_ID_AVC)
|
|
stAttr.stVencAttr.u32Profile = H264E_PROFILE_HIGH;
|
|
else if (enType == RK_VIDEO_ID_HEVC)
|
|
stAttr.stVencAttr.u32Profile = H265E_PROFILE_MAIN;
|
|
stAttr.stVencAttr.u32PicWidth = width;
|
|
stAttr.stVencAttr.u32PicHeight = height;
|
|
stAttr.stVencAttr.u32VirWidth = width;
|
|
stAttr.stVencAttr.u32VirHeight = height;
|
|
stAttr.stVencAttr.u32MaxPicWidth = max_width;
|
|
stAttr.stVencAttr.u32MaxPicHeight = max_height;
|
|
stAttr.stVencAttr.u32StreamBufCnt = 4;
|
|
/* stAttr.stVencAttr.u32BufSize = max_width * max_height / 2; */
|
|
stAttr.stVencAttr.u32BufSize = max_width * max_height;
|
|
stAttr.stVencAttr.enMirror = MIRROR_NONE;
|
|
|
|
RK_MPI_VENC_CreateChn(chnId, &stAttr);
|
|
if (g_bWrap == true) {
|
|
stVencChnBufWrap.bEnable = g_bWrap;
|
|
stVencChnBufWrap.u32BufLine = g_u32WrapLine;
|
|
RK_MPI_VENC_SetChnBufWrapAttr(chnId, &stVencChnBufWrap);
|
|
}
|
|
RK_MPI_VENC_SetChnRefBufShareAttr(chnId, &stVencChnRefBufShare);
|
|
|
|
VENC_RC_PARAM_S stRcParam;
|
|
memset(&stRcParam, 0, sizeof(stRcParam));
|
|
if (enType == RK_VIDEO_ID_AVC) {
|
|
stRcParam.s32FirstFrameStartQp = 28;
|
|
stRcParam.stParamH264.u32MinQp = 10;
|
|
stRcParam.stParamH264.u32MaxQp = 51;
|
|
stRcParam.stParamH264.u32MinIQp = 10;
|
|
stRcParam.stParamH264.u32MaxIQp = 51;
|
|
stRcParam.stParamH264.u32FrmMinQp = 25;
|
|
stRcParam.stParamH264.u32FrmMinIQp = 24;
|
|
stRcParam.stParamH264.u32FrmMaxQp = 41;
|
|
stRcParam.stParamH264.u32FrmMaxIQp = 35;
|
|
} else if (enType == RK_VIDEO_ID_HEVC) {
|
|
stRcParam.s32FirstFrameStartQp = 28;
|
|
stRcParam.stParamH265.u32MinQp = 10;
|
|
stRcParam.stParamH265.u32MaxQp = 51;
|
|
stRcParam.stParamH265.u32MinIQp = 10;
|
|
stRcParam.stParamH265.u32MaxIQp = 51;
|
|
stRcParam.stParamH265.u32FrmMinQp = 25;
|
|
stRcParam.stParamH265.u32FrmMinIQp = 24;
|
|
stRcParam.stParamH265.u32FrmMaxQp = 41;
|
|
stRcParam.stParamH265.u32FrmMaxIQp = 35;
|
|
}
|
|
RK_MPI_VENC_SetRcParam(chnId, &stRcParam);
|
|
|
|
RK_MPI_VENC_EnableSvc(chnId, RK_TRUE);
|
|
|
|
memset(&stRecvParam, 0, sizeof(VENC_RECV_PIC_PARAM_S));
|
|
stRecvParam.s32RecvPicNum = -1;
|
|
RK_MPI_VENC_StartRecvFrame(chnId, &stRecvParam);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int vi_dev_init() {
|
|
int ret = 0;
|
|
int devId = 0;
|
|
int pipeId = devId;
|
|
|
|
VI_DEV_ATTR_S stDevAttr;
|
|
VI_DEV_BIND_PIPE_S stBindPipe;
|
|
memset(&stDevAttr, 0, sizeof(stDevAttr));
|
|
memset(&stBindPipe, 0, sizeof(stBindPipe));
|
|
// 0. get dev config status
|
|
ret = RK_MPI_VI_GetDevAttr(devId, &stDevAttr);
|
|
if (ret == RK_ERR_VI_NOT_CONFIG) {
|
|
// 0-1.config dev
|
|
ret = RK_MPI_VI_SetDevAttr(devId, &stDevAttr);
|
|
if (ret != RK_SUCCESS) {
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
// 1.get dev enable status
|
|
ret = RK_MPI_VI_GetDevIsEnable(devId);
|
|
if (ret != RK_SUCCESS) {
|
|
// 1-2.enable dev
|
|
ret = RK_MPI_VI_EnableDev(devId);
|
|
if (ret != RK_SUCCESS) {
|
|
return -1;
|
|
}
|
|
// 1-3.bind dev/pipe
|
|
stBindPipe.u32Num = 1;
|
|
stBindPipe.PipeId[0] = pipeId;
|
|
stBindPipe.bUserStartPipe[0] = RK_TRUE;
|
|
ret = RK_MPI_VI_SetDevBindPipe(devId, &stBindPipe);
|
|
if (ret != RK_SUCCESS) {
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int vi_chn_init(int channelId, int width, int height, int max_width, int max_height) {
|
|
int ret;
|
|
int buf_cnt = 3;
|
|
|
|
// VI init
|
|
VI_CHN_ATTR_S vi_chn_attr;
|
|
|
|
if (g_bWrap == false) {
|
|
buf_cnt = 1;
|
|
}
|
|
memset(&vi_chn_attr, 0, sizeof(vi_chn_attr));
|
|
vi_chn_attr.stIspOpt.u32BufCount = buf_cnt;
|
|
vi_chn_attr.stIspOpt.enMemoryType = VI_V4L2_MEMORY_TYPE_DMABUF;
|
|
vi_chn_attr.stSize.u32Width = width;
|
|
vi_chn_attr.stSize.u32Height = height;
|
|
vi_chn_attr.stIspOpt.stMaxSize.u32Width = max_width;
|
|
vi_chn_attr.stIspOpt.stMaxSize.u32Height = max_height;
|
|
vi_chn_attr.enPixelFormat = RK_FMT_YUV420SP;
|
|
vi_chn_attr.enCompressMode = COMPRESS_MODE_NONE;
|
|
vi_chn_attr.u32Depth = 2;
|
|
|
|
if (g_sEntityName != NULL)
|
|
memcpy(vi_chn_attr.stIspOpt.aEntityName, g_sEntityName, strlen(g_sEntityName));
|
|
ret = RK_MPI_VI_SetChnAttr(0, channelId, &vi_chn_attr);
|
|
|
|
if (g_bWrap == true) {
|
|
g_stViWrap.bEnable = g_bWrap;
|
|
g_stViWrap.u32BufLine = g_u32WrapLine;
|
|
g_stViWrap.u32WrapBufferSize = g_stViWrap.u32BufLine * max_width * 3 / 2;
|
|
RK_MPI_VI_SetChnWrapBufAttr(0, channelId, &g_stViWrap);
|
|
|
|
ret |= RK_MPI_VI_EnableChnExt(0, channelId);
|
|
if (ret) {
|
|
printf("ERROR: create VI error! ret=%d\n", ret);
|
|
return ret;
|
|
}
|
|
} else {
|
|
ret |= RK_MPI_VI_EnableChn(0, channelId);
|
|
if (ret) {
|
|
printf("ERROR: create VI error! ret=%d\n", ret);
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
static int g_err_cnt = 0;
|
|
static bool g_should_quit = false;
|
|
|
|
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_should_quit = true;
|
|
}
|
|
|
|
#if 1
|
|
void klog(const char *log) {
|
|
FILE *fp = fopen("/dev/kmsg", "w");
|
|
if (NULL != fp) {
|
|
fprintf(fp, "[app]: %s\n", log);
|
|
fclose(fp);
|
|
}
|
|
}
|
|
#else
|
|
void klog(const char *log) { return; }
|
|
#endif
|
|
|
|
int main(int argc, char *argv[]) {
|
|
klog("main");
|
|
|
|
RK_S32 s32Ret = RK_FAILURE;
|
|
RK_U32 u32Width = 0;
|
|
RK_U32 u32Height = 0;
|
|
RK_U32 u32MaxWidth = 0;
|
|
RK_U32 u32MaxHeight = 0;
|
|
RK_CHAR *pOutPath = NULL;
|
|
RK_CHAR *pCodecName = "H264";
|
|
|
|
RK_CODEC_ID_E enCodecType = RK_VIDEO_ID_Max; // RK_VIDEO_ID_HEVC;
|
|
RK_S32 s32chnlId = 0;
|
|
|
|
int mem_fd = -1;
|
|
off_t appParamOffs = 0, metaAddr = 0;
|
|
void *metaVirmem = NULL, *appVirAddr = NULL, *SensorInitVirAddr;
|
|
RK_U32 metaSize = (RK_U32)get_cmd_val("meta_part_size", 16);
|
|
metaAddr = (off_t)get_cmd_val("meta_load_addr", 16);
|
|
if ((mem_fd = open("/dev/mem", O_RDWR | O_SYNC)) < 0) {
|
|
printf("cannot open /dev/mem.\n");
|
|
return -1;
|
|
}
|
|
|
|
metaVirmem =
|
|
mmap(NULL, metaSize, PROT_READ | PROT_WRITE, MAP_SHARED, mem_fd, metaAddr);
|
|
if (metaVirmem != MAP_FAILED) {
|
|
// get sensir init cfg addr, include ircut info
|
|
SensorInitVirAddr = metaVirmem + SENSOR_INIT_OFFSET;
|
|
g_pSensorInitParam = (struct sensor_init_cfg *)(SensorInitVirAddr);
|
|
// get app param addr
|
|
appVirAddr = metaVirmem + APP_PARAM_OFFSET;
|
|
g_pAppParam = (struct app_param_info *)(appVirAddr);
|
|
u32Width = g_pAppParam->venc_w;
|
|
u32Height = g_pAppParam->venc_h;
|
|
u32MaxWidth = g_pSensorInitParam->cam_w;
|
|
u32MaxHeight = g_pSensorInitParam->cam_h;
|
|
|
|
switch (g_pAppParam->venc_type) {
|
|
case 1:
|
|
enCodecType = RK_VIDEO_ID_AVC; // h.264
|
|
break;
|
|
case 2:
|
|
default:
|
|
enCodecType = RK_VIDEO_ID_HEVC; // h.265
|
|
break;
|
|
}
|
|
printf("\n read from meta: w:%d, h:%d, bitrate:%d, venc type:%d\n",
|
|
g_pAppParam->venc_w, g_pAppParam->venc_h, g_pAppParam->venc_bitrate,
|
|
g_pAppParam->venc_type);
|
|
} else {
|
|
printf("mmap fail.\n");
|
|
goto __FAILED;
|
|
}
|
|
|
|
// ircut pull down to low power mode
|
|
int gpio_ircut_a = g_pSensorInitParam->ircut_a.gpio_index;
|
|
int gpio_ircut_b = g_pSensorInitParam->ircut_b.gpio_index;
|
|
if (gpio_ircut_a >= 0 && gpio_ircut_b >= 0) {
|
|
rk_gpio_export(gpio_ircut_a);
|
|
rk_gpio_set_direction(gpio_ircut_a, RK_FALSE);
|
|
rk_gpio_set_value(gpio_ircut_a, 0);
|
|
rk_gpio_export(gpio_ircut_b);
|
|
rk_gpio_set_direction(gpio_ircut_b, RK_FALSE);
|
|
rk_gpio_set_value(gpio_ircut_b, 0);
|
|
}
|
|
|
|
if (g_bWrap)
|
|
g_u32WrapLine = u32MaxHeight / 4; // 360 // 1080
|
|
g_s32FrameCnt = 20;
|
|
g_sEntityName = "/dev/video11";
|
|
|
|
#ifdef ENABLE_GET_STREAM
|
|
pOutPath = "/tmp/venc-test.bin";
|
|
|
|
if (pOutPath) {
|
|
venc0_file = fopen(pOutPath, "w");
|
|
if (!venc0_file) {
|
|
goto __FAILED;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
signal(SIGINT, sigterm_handler);
|
|
|
|
if (RK_MPI_SYS_Init() != RK_SUCCESS) {
|
|
goto __FAILED;
|
|
}
|
|
klog("sys_init");
|
|
test_venc_init(0, u32Width, u32Height, u32MaxWidth, u32MaxHeight,
|
|
enCodecType); // RK_VIDEO_ID_AVC RK_VIDEO_ID_HEVC
|
|
klog("venc_init");
|
|
|
|
vi_dev_init();
|
|
klog("vi_dev");
|
|
vi_chn_init(s32chnlId, u32Width, u32Height, u32MaxWidth, u32MaxHeight);
|
|
klog("vi_chn");
|
|
|
|
MPP_CHN_S stSrcChn, stDestChn;
|
|
// bind vi to venc
|
|
stSrcChn.enModId = RK_ID_VI;
|
|
stSrcChn.s32DevId = 0;
|
|
stSrcChn.s32ChnId = 0;
|
|
|
|
stDestChn.enModId = RK_ID_VENC;
|
|
stDestChn.s32DevId = 0;
|
|
stDestChn.s32ChnId = 0;
|
|
s32Ret = RK_MPI_SYS_Bind(&stSrcChn, &stDestChn);
|
|
if (s32Ret != RK_SUCCESS) {
|
|
goto __FAILED;
|
|
}
|
|
klog("bind");
|
|
|
|
#if 1
|
|
// venc init, if is fast boot, must first init venc.
|
|
if (fork() > 0) {
|
|
|
|
} else {
|
|
int loop_time = 0;
|
|
while (1) {
|
|
usleep(1000 * 1000); // when client online
|
|
#ifdef ENABLE_AOV
|
|
if (loop_time >= 3 && access(AOV_LUNCH_FILE, F_OK) == 0) {
|
|
printf("file %s has been detect\n", AOV_LUNCH_FILE);
|
|
break; //kill fastboot_server
|
|
}
|
|
#endif
|
|
loop_time++;
|
|
}
|
|
printf("sub service exit main\n");
|
|
return 0;
|
|
}
|
|
|
|
RK_MPI_VI_StartPipe(0);
|
|
klog("vi resume");
|
|
#endif
|
|
|
|
#ifdef RKAIQ
|
|
size_t file_size;
|
|
int ret = 0;
|
|
void *vir_iqaddr;
|
|
RK_S64 s64AiqInitStart = TEST_COMM_GetNowUs();
|
|
|
|
#ifdef RKAIQ_USE_DLOPEN
|
|
if (dlsym_rkaiq() != 0) {
|
|
goto __FAILED;
|
|
}
|
|
#endif
|
|
|
|
if (pOutPath) {
|
|
venc0_file = fopen(pOutPath, "w");
|
|
if (!venc0_file) {
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
// addr_iq = (off_t)get_cmd_val("rk_iqbin_addr", 16);
|
|
file_size = (int)get_cmd_val("rk_iqbin_size", 16);
|
|
vir_iqaddr =
|
|
metaVirmem + SENSOR_IQ_BIN_OFFSET + offsetof(struct sensor_iq_info, data);
|
|
klog("mmap iq mem");
|
|
|
|
int cam_hdr = (int)get_cmd_val("rk_cam_hdr", 0);
|
|
rk_aiq_working_mode_t hdr_mode =
|
|
(cam_hdr == 5) ? RK_AIQ_WORKING_MODE_ISP_HDR2 : RK_AIQ_WORKING_MODE_NORMAL;
|
|
|
|
rk_aiq_sys_ctx_t *aiq_ctx;
|
|
rk_aiq_static_info_t aiq_static_info;
|
|
dlsym_rk_aiq_uapi2_sysctl_enumStaticMetas(s32chnlId, &aiq_static_info);
|
|
klog("aiq enum");
|
|
|
|
if (g_pAppParam->color_mode) {
|
|
printf("=====night mode=====\n");
|
|
ret = dlsym_rk_aiq_uapi2_sysctl_preInit_scene(aiq_static_info.sensor_info.sensor_name,
|
|
"normal", "night");
|
|
if (ret < 0) {
|
|
printf("%s: failed to set night scene\n",
|
|
aiq_static_info.sensor_info.sensor_name);
|
|
goto __FAILED;
|
|
}
|
|
} else {
|
|
printf("=====day mode=======\n");
|
|
ret = dlsym_rk_aiq_uapi2_sysctl_preInit_scene(aiq_static_info.sensor_info.sensor_name,
|
|
"normal", "day");
|
|
if (ret < 0) {
|
|
printf("%s: failed to set day scene\n",
|
|
aiq_static_info.sensor_info.sensor_name);
|
|
goto __FAILED;
|
|
}
|
|
}
|
|
klog("preint scene");
|
|
|
|
ret = dlsym_rk_aiq_uapi2_sysctl_preInit_iq_addr(aiq_static_info.sensor_info.sensor_name,
|
|
vir_iqaddr, file_size);
|
|
if (ret < 0) {
|
|
printf("%s: failed to load binary iqfiles\n",
|
|
aiq_static_info.sensor_info.sensor_name);
|
|
}
|
|
klog("preinit iq addr");
|
|
|
|
rk_aiq_tb_info_t tb_info;
|
|
memset(&tb_info, 0, sizeof(rk_aiq_tb_info_t));
|
|
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;
|
|
dlsym_rk_aiq_uapi2_sysctl_preInit_tb_info(aiq_static_info.sensor_info.sensor_name,
|
|
&tb_info);
|
|
klog("preinit tb info");
|
|
|
|
aiq_ctx =
|
|
dlsym_rk_aiq_uapi2_sysctl_init(aiq_static_info.sensor_info.sensor_name, "/etc/iqfiles/",
|
|
SAMPLE_COMM_ISP_ErrCb, NULL);
|
|
klog("sysctl init");
|
|
if (aiq_ctx == NULL) {
|
|
printf("%s: failed to init aiq\n", aiq_static_info.sensor_info.sensor_name);
|
|
}
|
|
|
|
if (dlsym_rk_aiq_uapi2_sysctl_prepare(aiq_ctx, 0, 0, hdr_mode)) {
|
|
printf("rkaiq engine prepare failed !\n");
|
|
goto __FAILED;
|
|
}
|
|
klog("sysctl prepare");
|
|
|
|
if (dlsym_rk_aiq_uapi2_sysctl_start(aiq_ctx)) {
|
|
printf("rk_aiq_uapi2_sysctl_start failed\n");
|
|
goto __FAILED;
|
|
}
|
|
klog("sysctl start");
|
|
RK_S64 s64AiqInitEnd = TEST_COMM_GetNowUs();
|
|
printf("Aiq:%lld us\n", s64AiqInitEnd - s64AiqInitStart);
|
|
#endif
|
|
klog("aiq start");
|
|
#ifdef ENABLE_GET_STREAM
|
|
pOutPath = "/tmp/venc-test.bin";
|
|
|
|
if (pOutPath) {
|
|
venc0_file = fopen(pOutPath, "w");
|
|
if (!venc0_file) {
|
|
goto __FAILED;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
#ifdef ENABLE_GET_STREAM
|
|
GetMediaBuffer0(NULL);
|
|
|
|
s32Ret = RK_MPI_SYS_UnBind(&stSrcChn, &stDestChn);
|
|
s32Ret = RK_MPI_VI_DisableChn(0, 0);
|
|
s32Ret = RK_MPI_VENC_StopRecvFrame(0);
|
|
if (s32Ret != RK_SUCCESS) {
|
|
goto __FAILED;
|
|
}
|
|
|
|
s32Ret = RK_MPI_VENC_DestroyChn(0);
|
|
s32Ret = RK_MPI_VI_DisableDev(0);
|
|
#endif
|
|
|
|
#ifdef RKAIQ
|
|
int loop_cnt = 0x400;
|
|
while (1) {
|
|
if (g_should_quit) {
|
|
klog("should quit");
|
|
dlsym_rk_aiq_uapi2_sysctl_stop(aiq_ctx, false);
|
|
klog("aiq stop");
|
|
dlsym_rk_aiq_uapi2_sysctl_deinit(aiq_ctx);
|
|
klog("aiq deinit");
|
|
break;
|
|
}
|
|
usleep(1 * 1000); // when client online
|
|
if (loop_cnt-- == 0) {
|
|
klog("aiq timeout exit");
|
|
break;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
__FAILED:
|
|
#ifdef RKAIQ_USE_DLOPEN
|
|
if (rkaiq_dl != NULL) {
|
|
dlclose(rkaiq_dl);
|
|
}
|
|
#endif
|
|
if (metaVirmem != MAP_FAILED)
|
|
munmap(metaVirmem, metaSize);
|
|
if (mem_fd != -1)
|
|
close(mem_fd);
|
|
printf("main service exit main\n");
|
|
return 0;
|
|
}
|