903 lines
26 KiB
C
903 lines
26 KiB
C
#include <errno.h>
|
|
#include <getopt.h>
|
|
#include <signal.h>
|
|
#include <stdbool.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 "sample_comm.h"
|
|
|
|
#include "rk_gpio.h"
|
|
#include "rk_pwm.h"
|
|
#include "rtsp_demo.h"
|
|
#include <rk_smart_ir_api.h>
|
|
#define ENABLE_RKAIQ 1
|
|
#define ENABLE_RTSP 1
|
|
#define ENABLE_SMALL_STREAM 1
|
|
#define ENABLE_CHANGE_RESOLUTION 0
|
|
|
|
#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
|
|
|
|
#define SAVE_ENC_FRM_CNT_MAX 30
|
|
#define RUN_TOTAL_CNT_MAX 1000000
|
|
|
|
static FILE *venc0_file;
|
|
static RK_S32 g_s32FrameCnt = -1;
|
|
// static RK_U32 g_u32WrapLine = 0;
|
|
static char *g_sEntityName = NULL;
|
|
static bool quit = false;
|
|
static int venc_w[3] = {1920, 1280, 640};
|
|
static int venc_h[3] = {1080, 720, 480};
|
|
static int index_w_h = 1;
|
|
static int index_num = 3;
|
|
|
|
// SmartIr Params
|
|
#define ircut_on_gpio GPIO(RK_GPIO1, RK_PD1)
|
|
#define ircut_off_gpio GPIO(RK_GPIO1, RK_PD3)
|
|
#define irled_enable_gpio GPIO(RK_GPIO1, RK_PD0)
|
|
#define irled_pwm_channel 11
|
|
static float d2n_envL_th = 0.04f;
|
|
static float n2d_envL_th = 0.20f;
|
|
static float rggain_base = 1.0f;
|
|
static float bggain_base = 1.0f;
|
|
static float awbgain_rad = 0.10f;
|
|
static float awbgain_dis = 0.22f;
|
|
int rk_led_value = 100;
|
|
|
|
rtsp_demo_handle g_rtsplive = NULL;
|
|
static rtsp_session_handle g_rtsp_session;
|
|
|
|
typedef struct rk_smart_ir_ctx_s {
|
|
const rk_aiq_sys_ctx_t *aiq_ctx;
|
|
int cur_working_mode;
|
|
rk_smart_ir_params_t ir_configs;
|
|
RK_SMART_IR_STATUS_t state;
|
|
uint16_t switch_cnts;
|
|
bool awbgain_update;
|
|
} rk_smart_ir_ctx_t;
|
|
|
|
typedef struct sample_smartIr_s {
|
|
pthread_t tid;
|
|
bool tquit;
|
|
bool started;
|
|
const rk_aiq_sys_ctx_t *aiq_ctx;
|
|
rk_smart_ir_ctx_t *ir_ctx;
|
|
rk_smart_ir_params_t ir_configs;
|
|
rk_smart_ir_result_t ir_res;
|
|
rk_aiq_isp_stats_t *isp_status;
|
|
} sample_smartIr_t;
|
|
static sample_smartIr_t g_sample_smartIr_ctx;
|
|
|
|
static void sigterm_handler(int sig) { quit = true; }
|
|
|
|
static RK_CHAR optstr[] = "?::d:n:s:B:b:R:r:";
|
|
static const struct option long_options[] = {
|
|
{"d2n", required_argument, NULL, 'd'},
|
|
{"n2d", required_argument, NULL, 'n'},
|
|
{"switch_cnt", required_argument, NULL, 's'},
|
|
{"bg_max", required_argument, NULL, 'B'},
|
|
{"bg_min", required_argument, NULL, 'b'},
|
|
{"rg_max", required_argument, NULL, 'R'},
|
|
{"rg_min", optional_argument, NULL, 'r'},
|
|
{"help", optional_argument, NULL, '?'},
|
|
{NULL, 0, NULL, 0},
|
|
};
|
|
|
|
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 */
|
|
}
|
|
|
|
int rk_isp_enable_ircut(bool on) {
|
|
|
|
if (on) {
|
|
rk_gpio_set_value(ircut_on_gpio, 1);
|
|
usleep(100 * 1000);
|
|
rk_gpio_set_value(ircut_on_gpio, 0);
|
|
|
|
} else {
|
|
rk_gpio_set_value(ircut_off_gpio, 1);
|
|
usleep(100 * 1000);
|
|
rk_gpio_set_value(ircut_off_gpio, 0);
|
|
}
|
|
}
|
|
|
|
static void load_ir_configs(float d2n, float n2d, float rbase, float bbase, float rad,
|
|
float dis, int switch_cnt) {
|
|
sample_smartIr_t *smartIr_ctx = &g_sample_smartIr_ctx;
|
|
|
|
smartIr_ctx->ir_configs.d2n_envL_th = d2n;
|
|
smartIr_ctx->ir_configs.n2d_envL_th = n2d;
|
|
smartIr_ctx->ir_configs.rggain_base = rbase;
|
|
smartIr_ctx->ir_configs.bggain_base = bbase;
|
|
smartIr_ctx->ir_configs.awbgain_rad = rad;
|
|
smartIr_ctx->ir_configs.awbgain_dis = dis;
|
|
smartIr_ctx->ir_configs.switch_cnts_th = switch_cnt;
|
|
rk_smart_ir_config(smartIr_ctx->ir_ctx, &smartIr_ctx->ir_configs);
|
|
}
|
|
|
|
static void *switch_ir_thread(void *args) {
|
|
sample_smartIr_t *smartIr_ctx = &g_sample_smartIr_ctx;
|
|
int init_stat = smartIr_ctx->ir_ctx->state;
|
|
int ret, switch_flag, sleep_count = 15;
|
|
int irled_pwm_period = 5000, irled_pwm_duty = 0;
|
|
FILE *fp;
|
|
|
|
ret |= rk_gpio_export_direction(ircut_on_gpio, GPIO_DIRECTION_OUTPUT);
|
|
ret |= rk_gpio_export_direction(ircut_off_gpio, GPIO_DIRECTION_OUTPUT);
|
|
ret |= rk_gpio_export_direction(irled_enable_gpio, GPIO_DIRECTION_OUTPUT);
|
|
|
|
if (init_stat == RK_SMART_IR_STATUS_NIGHT) {
|
|
switch_flag = 0;
|
|
rk_gpio_set_value(irled_enable_gpio, 1);
|
|
} else {
|
|
switch_flag = 1;
|
|
rk_gpio_set_value(irled_enable_gpio, 0);
|
|
}
|
|
|
|
while (--sleep_count >= 0) {
|
|
if ((access("/dev/block/by-name/meta", F_OK)) == 0) {
|
|
printf("load meta partition finished\n");
|
|
break;
|
|
}
|
|
usleep(1000 * 1000);
|
|
}
|
|
|
|
irled_pwm_duty = MIN(rk_led_value, 100) / 100 * irled_pwm_period;
|
|
ret = rk_pwm_init(irled_pwm_channel, irled_pwm_period, irled_pwm_duty,
|
|
PWM_POLARITY_NORMAL);
|
|
if (ret) {
|
|
printf("rk_pwm_init error ret [%d]\n", ret);
|
|
}
|
|
|
|
while (!smartIr_ctx->tquit && (quit == false)) {
|
|
rk_aiq_uapi2_sysctl_get3AStatsBlk(smartIr_ctx->aiq_ctx, &smartIr_ctx->isp_status,
|
|
-1);
|
|
rk_smart_ir_runOnce(smartIr_ctx->ir_ctx, smartIr_ctx->isp_status,
|
|
&smartIr_ctx->ir_res);
|
|
rk_aiq_uapi2_sysctl_release3AStatsRef(smartIr_ctx->aiq_ctx,
|
|
smartIr_ctx->isp_status);
|
|
if (smartIr_ctx->ir_res.status == RK_SMART_IR_STATUS_DAY) {
|
|
if (switch_flag != 0) {
|
|
switch_flag = 0;
|
|
rk_gpio_set_value(irled_enable_gpio, 0);
|
|
if (rk_pwm_set_enable(irled_pwm_channel, false))
|
|
printf("pwm%d disable failed %d\n", irled_pwm_channel);
|
|
rk_isp_enable_ircut(true);
|
|
rk_aiq_uapi2_sysctl_switch_scene(smartIr_ctx->aiq_ctx, "normal", "day");
|
|
|
|
printf("SAMPLE_SMART_IR: switch to DAY\n");
|
|
system("make_meta --update --meta_path /dev/block/by-name/meta "
|
|
"--rk_color_mode 0");
|
|
}
|
|
} else if (smartIr_ctx->ir_res.status == RK_SMART_IR_STATUS_NIGHT) {
|
|
if (switch_flag != 1) {
|
|
switch_flag = 1;
|
|
rk_aiq_uapi2_sysctl_switch_scene(smartIr_ctx->aiq_ctx, "normal", "night");
|
|
rk_isp_enable_ircut(false);
|
|
rk_gpio_set_value(irled_enable_gpio, 1);
|
|
if (rk_pwm_set_enable(irled_pwm_channel, true))
|
|
printf("pwm%d enable failed %d\n", irled_pwm_channel);
|
|
|
|
printf("SAMPLE_SMART_IR: switch to Night\n");
|
|
system("make_meta --update --meta_path /dev/block/by-name/meta "
|
|
"--rk_color_mode 1");
|
|
}
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
void sample_smartIr_stop() {
|
|
sample_smartIr_t *smartIr_ctx = &g_sample_smartIr_ctx;
|
|
|
|
printf("%s-%d\n", __func__, __LINE__);
|
|
rk_pwm_deinit(irled_pwm_channel);
|
|
if (smartIr_ctx->started) {
|
|
smartIr_ctx->tquit = true;
|
|
pthread_join(smartIr_ctx->tid, NULL);
|
|
}
|
|
smartIr_ctx->started = false;
|
|
|
|
if (smartIr_ctx->ir_ctx) {
|
|
rk_smart_ir_deInit(smartIr_ctx->ir_ctx);
|
|
smartIr_ctx->ir_ctx = NULL;
|
|
}
|
|
}
|
|
|
|
static int errCnt = 0;
|
|
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, 1000);
|
|
if (s32Ret == RK_SUCCESS) {
|
|
if (venc0_file && loopCount <= SAVE_ENC_FRM_CNT_MAX) {
|
|
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();
|
|
if (fp && (loopCount <= SAVE_ENC_FRM_CNT_MAX)) {
|
|
char str[128] = {0};
|
|
int len;
|
|
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);
|
|
len = snprintf(str, sizeof(str), "seq:%u, pts:%llums\n", stFrame.u32Seq,
|
|
stFrame.pstPack->u64PTS / 1000);
|
|
fwrite(str, 1, len, fp);
|
|
fflush(fp);
|
|
}
|
|
loopCount++;
|
|
#if (ENABLE_RTSP)
|
|
// tx video to rtspls
|
|
if (loopCount > SAVE_ENC_FRM_CNT_MAX) {
|
|
if (g_rtsplive && g_rtsp_session) {
|
|
pData = RK_MPI_MB_Handle2VirAddr(stFrame.pstPack->pMbBlk);
|
|
rtsp_tx_video(g_rtsp_session, pData, stFrame.pstPack->u32Len,
|
|
stFrame.pstPack->u64PTS);
|
|
rtsp_do_event(g_rtsplive);
|
|
}
|
|
}
|
|
#endif
|
|
errCnt = 0;
|
|
s32Ret = RK_MPI_VENC_ReleaseStream(0, &stFrame);
|
|
|
|
#if (ENABLE_CHANGE_RESOLUTION)
|
|
if ((loopCount >= SAVE_ENC_FRM_CNT_MAX) &&
|
|
((loopCount % SAVE_ENC_FRM_CNT_MAX)) == 0) {
|
|
MPP_CHN_S stSrcChn, stDestChn;
|
|
VENC_CHN_ATTR_S stAttr;
|
|
VI_CHN_ATTR_S stChnAttr;
|
|
// unbind venc from vi
|
|
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_UnBind(&stSrcChn, &stDestChn);
|
|
if (s32Ret != RK_SUCCESS) {
|
|
RK_LOGE("RK_MPI_SYS_UnBind fail %x", s32Ret);
|
|
goto __FAILED;
|
|
}
|
|
s32Ret = RK_MPI_VENC_GetChnAttr(0, &stAttr);
|
|
if (s32Ret != RK_SUCCESS) {
|
|
RK_LOGE("RK_MPI_VENC_GetChnAttr fail %x", s32Ret);
|
|
goto __FAILED;
|
|
}
|
|
stAttr.stVencAttr.u32PicWidth = venc_w[index_w_h % index_num];
|
|
stAttr.stVencAttr.u32PicHeight = venc_h[index_w_h % index_num];
|
|
stAttr.stVencAttr.u32VirWidth = venc_w[index_w_h % index_num];
|
|
stAttr.stVencAttr.u32VirHeight = venc_h[index_w_h % index_num];
|
|
s32Ret = RK_MPI_VENC_SetChnAttr(0, &stAttr);
|
|
if (s32Ret != RK_SUCCESS) {
|
|
RK_LOGE("RK_MPI_VENC_SetChnAttr fail %x", s32Ret);
|
|
goto __FAILED;
|
|
}
|
|
usleep(80 * 1000);
|
|
stChnAttr.stIspOpt.stMaxSize.u32Width = venc_w[0];
|
|
stChnAttr.stIspOpt.stMaxSize.u32Height = venc_h[0];
|
|
stChnAttr.stSize.u32Width = venc_w[index_w_h % index_num];
|
|
stChnAttr.stSize.u32Height = venc_h[index_w_h % index_num];
|
|
s32Ret = RK_MPI_VI_SetChnAttr(0, 0, &stChnAttr);
|
|
if (s32Ret != RK_SUCCESS) {
|
|
RK_LOGE("RK_MPI_VI_SetChnAttr fail %x", s32Ret);
|
|
goto __FAILED;
|
|
}
|
|
|
|
s32Ret = RK_MPI_SYS_Bind(&stSrcChn, &stDestChn);
|
|
if (s32Ret != RK_SUCCESS) {
|
|
RK_LOGE("RK_MPI_SYS_Bind fail %x", s32Ret);
|
|
goto __FAILED;
|
|
}
|
|
index_w_h++;
|
|
}
|
|
#endif
|
|
#if (ENABLE_RTSP)
|
|
if (loopCount == SAVE_ENC_FRM_CNT_MAX) {
|
|
g_rtsplive = create_rtsp_demo(554);
|
|
if (g_rtsplive == NULL) {
|
|
printf("rtsp create fail");
|
|
goto __FAILED;
|
|
}
|
|
g_rtsp_session = rtsp_new_session(g_rtsplive, "/live/0");
|
|
if (g_rtsp_session == NULL) {
|
|
printf("rtsp create session fail");
|
|
goto __FAILED;
|
|
}
|
|
VENC_CHN_ATTR_S stAttr;
|
|
s32Ret = RK_MPI_VENC_GetChnAttr(0, &stAttr);
|
|
if (s32Ret != RK_SUCCESS) {
|
|
RK_LOGE("RK_MPI_VENC_GetChnAttr fail %x", s32Ret);
|
|
goto __FAILED;
|
|
}
|
|
if (stAttr.stVencAttr.enType == RK_VIDEO_ID_AVC)
|
|
rtsp_set_video(g_rtsp_session, RTSP_CODEC_ID_VIDEO_H264, NULL, 0);
|
|
else if (stAttr.stVencAttr.enType == RK_VIDEO_ID_HEVC)
|
|
rtsp_set_video(g_rtsp_session, RTSP_CODEC_ID_VIDEO_H265, NULL, 0);
|
|
rtsp_sync_video_ts(g_rtsp_session, rtsp_get_reltime(),
|
|
rtsp_get_ntptime());
|
|
}
|
|
#endif
|
|
|
|
} else {
|
|
if (errCnt < 10) {
|
|
printf("RK_MPI_VENC_GetChnFrame fail %x\n", s32Ret);
|
|
}
|
|
errCnt++;
|
|
}
|
|
|
|
#if 0
|
|
if ((g_s32FrameCnt >= 0) && (loopCount > g_s32FrameCnt)) {
|
|
quit = true;
|
|
break;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
__FAILED:
|
|
if (venc0_file)
|
|
fclose(venc0_file);
|
|
|
|
if (fp)
|
|
fclose(fp);
|
|
|
|
free(stFrame.pstPack);
|
|
return NULL;
|
|
}
|
|
|
|
static void *GetMediaBuffer(void *arg) {
|
|
void *pData = RK_NULL;
|
|
int loopCount = 0;
|
|
int s32Ret;
|
|
VENC_STREAM_S stFrame;
|
|
int chn = (int)arg;
|
|
stFrame.pstPack = malloc(sizeof(VENC_PACK_S));
|
|
while (!quit) {
|
|
s32Ret = RK_MPI_VENC_GetStream(chn, &stFrame, 1000);
|
|
if (s32Ret == RK_SUCCESS) {
|
|
if (loopCount < SAVE_ENC_FRM_CNT_MAX)
|
|
printf("chn:%d, loopCount:%d enc->seq:%d,pts=%lld\n", chn, loopCount,
|
|
stFrame.u32Seq, stFrame.pstPack->u32Len, stFrame.pstPack->u64PTS);
|
|
loopCount++;
|
|
s32Ret = RK_MPI_VENC_ReleaseStream(chn, &stFrame);
|
|
}
|
|
if ((g_s32FrameCnt >= 0) && (loopCount > g_s32FrameCnt)) {
|
|
quit = true;
|
|
break;
|
|
}
|
|
}
|
|
free(stFrame.pstPack);
|
|
return NULL;
|
|
}
|
|
|
|
static void *GetViBuffer(void *arg) {
|
|
void *pData = RK_NULL;
|
|
int loopCount = 0;
|
|
int s32Ret;
|
|
VIDEO_FRAME_INFO_S stFrame;
|
|
int chn = (int)arg;
|
|
int piple = ((int)arg >> 16);
|
|
void *pVirAddr;
|
|
|
|
while (!quit) {
|
|
s32Ret = RK_MPI_VI_GetChnFrame(piple, chn, &stFrame, 1000);
|
|
if (s32Ret == RK_SUCCESS) {
|
|
if (loopCount < SAVE_ENC_FRM_CNT_MAX)
|
|
printf("piple: %d, chn:%d, loopCount:%d vi->seq:%d pts=%lld\n", piple,
|
|
chn, loopCount, stFrame.stVFrame.u32TimeRef,
|
|
stFrame.stVFrame.u64PTS);
|
|
loopCount++;
|
|
pVirAddr = RK_MPI_MB_Handle2VirAddr(stFrame.stVFrame.pMbBlk);
|
|
s32Ret = RK_MPI_VI_ReleaseChnFrame(piple, chn, &stFrame);
|
|
}
|
|
if ((g_s32FrameCnt >= 0) && (loopCount > g_s32FrameCnt)) {
|
|
quit = true;
|
|
break;
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
static RK_S32 test_jpeg_init(int chnId, int width, int height, RK_CODEC_ID_E enType) {
|
|
VENC_CHN_ATTR_S stJpegChnAttr;
|
|
VENC_JPEG_PARAM_S stJpegParam;
|
|
VENC_RECV_PIC_PARAM_S stRecvParam;
|
|
// memset(&stJpegChnAttr,0,sizeof(VENC_JPEG_PARAM_S));
|
|
|
|
stJpegChnAttr.stVencAttr.enType = enType;
|
|
stJpegChnAttr.stVencAttr.enPixelFormat = RK_FMT_YUV420SP;
|
|
stJpegChnAttr.stVencAttr.u32PicWidth = width;
|
|
stJpegChnAttr.stVencAttr.u32PicHeight = height;
|
|
stJpegChnAttr.stVencAttr.u32VirWidth = width;
|
|
stJpegChnAttr.stVencAttr.u32VirHeight = height;
|
|
stJpegChnAttr.stVencAttr.u32StreamBufCnt = 1;
|
|
stJpegChnAttr.stVencAttr.u32BufSize = width * height;
|
|
|
|
stJpegChnAttr.stRcAttr.enRcMode = VENC_RC_MODE_MJPEGCBR;
|
|
stJpegChnAttr.stRcAttr.stMjpegCbr.u32BitRate = 64;
|
|
stJpegChnAttr.stRcAttr.stMjpegCbr.fr32DstFrameRateDen = 1;
|
|
stJpegChnAttr.stRcAttr.stMjpegCbr.fr32DstFrameRateNum = 1;
|
|
stJpegChnAttr.stRcAttr.stMjpegCbr.u32SrcFrameRateDen = 1;
|
|
stJpegChnAttr.stRcAttr.stMjpegCbr.u32SrcFrameRateNum = 1;
|
|
// stJpegChnAttr.stVencAttr.u32Depth = 1;
|
|
RK_MPI_VENC_CreateChn(chnId, &stJpegChnAttr);
|
|
stJpegParam.u32Qfactor = 75;
|
|
RK_MPI_VENC_SetJpegParam(chnId, &stJpegParam);
|
|
|
|
memset(&stRecvParam, 0, sizeof(VENC_RECV_PIC_PARAM_S));
|
|
stRecvParam.s32RecvPicNum = -1;
|
|
RK_MPI_VENC_StartRecvFrame(chnId, &stRecvParam);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static RK_S32 test_venc_init(int chnId, int width, int 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;
|
|
|
|
memset(&stAttr, 0, sizeof(VENC_CHN_ATTR_S));
|
|
stVencChnBufWrap.bEnable = false;
|
|
stVencChnBufWrap.u32BufLine = 1080;
|
|
|
|
memset(&stVencChnRefBufShare, 0, sizeof(VENC_CHN_REF_BUF_SHARE_S));
|
|
stVencChnRefBufShare.bEnable = true;
|
|
|
|
if (enType == RK_VIDEO_ID_AVC) {
|
|
stAttr.stRcAttr.enRcMode = VENC_RC_MODE_H264CBR;
|
|
stAttr.stRcAttr.stH264Cbr.u32BitRate = 2 * 1024;
|
|
stAttr.stRcAttr.stH264Cbr.u32Gop = 60;
|
|
} else if (enType == RK_VIDEO_ID_HEVC) {
|
|
stAttr.stRcAttr.enRcMode = VENC_RC_MODE_H265CBR;
|
|
stAttr.stRcAttr.stH265Cbr.u32BitRate = 2 * 1024;
|
|
stAttr.stRcAttr.stH265Cbr.u32Gop = 60;
|
|
}
|
|
|
|
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.u32StreamBufCnt = 5;
|
|
stAttr.stVencAttr.u32BufSize = width * height / 2;
|
|
stAttr.stVencAttr.enMirror = MIRROR_NONE;
|
|
|
|
RK_MPI_VENC_CreateChn(chnId, &stAttr);
|
|
RK_MPI_VENC_SetChnBufWrapAttr(chnId, &stVencChnBufWrap);
|
|
RK_MPI_VENC_SetChnRefBufShareAttr(chnId, &stVencChnRefBufShare);
|
|
|
|
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 devId, int pipeId) {
|
|
int ret = 0;
|
|
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 = pipeId;
|
|
stBindPipe.PipeId[0] = pipeId;
|
|
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 ret;
|
|
int buf_cnt = 1;
|
|
|
|
// VI init
|
|
VI_CHN_ATTR_S vi_chn_attr;
|
|
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.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);
|
|
|
|
RK_S64 s64ViEnSta = TEST_COMM_GetNowUs();
|
|
ret |= RK_MPI_VI_EnableChn(0, channelId);
|
|
RK_S64 s64ViEnEnd = TEST_COMM_GetNowUs();
|
|
printf(" vi en: %lld us\n", s64ViEnEnd - s64ViEnSta);
|
|
|
|
if (ret) {
|
|
printf("ERROR: create VI %d, error! ret=%d\n", channelId, ret);
|
|
return ret;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
#if 1
|
|
void klog(const char *log) {
|
|
FILE *fp = fopen("/dev/kmsg", "w");
|
|
if (NULL != fp) {
|
|
fprintf(fp, "[app-cli]: %s\n", log);
|
|
fclose(fp);
|
|
}
|
|
}
|
|
#else
|
|
void klog(const char *log) { return; }
|
|
#endif
|
|
|
|
static void print_usage(const RK_CHAR *name) {
|
|
printf("usage example:\n");
|
|
printf("\t%s -d 0.04 -n 0.2 -r 1.0 -r 1.0 -R 0.1 -D 0.3 -s 50\n", name);
|
|
printf("\t-s | --switch_cnt: switch_cnts_th, Default 50\n");
|
|
printf("\t-d | --d2n: d2n_envL_th, Default 0.04f\n");
|
|
printf("\t-n | --n2d: n2d_envL_th, Default 0.2f\n");
|
|
printf("\t-r | --rbase: rggain_base, Default 1.0f\n");
|
|
printf("\t-r | --bbase: bggain_base, Default 1.0f\n");
|
|
printf("\t-R | --rad: awbgain_rad, Default 0.1f\n");
|
|
printf("\t-D | --dis: awbgain_dis, Default 0.3f\n");
|
|
}
|
|
|
|
int main(int argc, char *argv[]) {
|
|
klog("main");
|
|
RK_S32 s32Ret = RK_FAILURE;
|
|
RK_U32 u32Width = 1920;
|
|
RK_U32 u32Height = 1080;
|
|
RK_CHAR *pOutPath = NULL;
|
|
RK_CODEC_ID_E enCodecType = RK_VIDEO_ID_AVC;
|
|
RK_S32 s32chnlId = 0;
|
|
|
|
g_s32FrameCnt = RUN_TOTAL_CNT_MAX;
|
|
pOutPath = "/tmp/venc-test.bin";
|
|
|
|
sample_smartIr_t *smartIr_ctx = &g_sample_smartIr_ctx;
|
|
float d2n = d2n_envL_th;
|
|
float n2d = n2d_envL_th;
|
|
float rbase = rggain_base;
|
|
float bbase = bggain_base;
|
|
float rad = awbgain_rad;
|
|
float dis = awbgain_dis;
|
|
int switch_cnt = 60;
|
|
int c;
|
|
if (argc > 1) {
|
|
while ((c = getopt_long(argc, argv, optstr, long_options, NULL)) != -1) {
|
|
const char *tmp_optarg = optarg;
|
|
switch (c) {
|
|
case 's':
|
|
switch_cnt = atoi(optarg);
|
|
break;
|
|
case 'd':
|
|
d2n = atof(optarg);
|
|
break;
|
|
case 'n':
|
|
n2d = atof(optarg);
|
|
break;
|
|
case 'r':
|
|
rbase = atof(optarg);
|
|
break;
|
|
case 'b':
|
|
bbase = atof(optarg);
|
|
break;
|
|
case 'R':
|
|
rad = atof(optarg);
|
|
break;
|
|
case 'D':
|
|
dis = atof(optarg);
|
|
break;
|
|
case '?':
|
|
default:
|
|
print_usage(argv[0]);
|
|
return 0;
|
|
}
|
|
}
|
|
}
|
|
printf(
|
|
"d2n_envL_th:%f, n2d_envL_th:%f, rggain_base:%f, bggain_base:%f, awbgain_rad:%f,"
|
|
"awbgain_dis:%f, switch_cnts_th:%d\n",
|
|
d2n, n2d, rbase, bbase, rad, dis, switch_cnt);
|
|
if (d2n < 0 || n2d < 0 || rbase < 0 || bbase < 0 || rad < 0 || dis < 0 ||
|
|
switch_cnt < 0) {
|
|
printf("invalid input param,please check!\n");
|
|
return -1;
|
|
}
|
|
|
|
signal(SIGINT, sigterm_handler);
|
|
RK_S64 s64VencInitStart = TEST_COMM_GetNowUs();
|
|
if (RK_MPI_SYS_Init() != RK_SUCCESS) {
|
|
printf("rockit init fail");
|
|
goto __FAILED;
|
|
}
|
|
|
|
klog("SYS_Init");
|
|
if (pOutPath) {
|
|
venc0_file = fopen(pOutPath, "w");
|
|
if (!venc0_file) {
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
#if (ENABLE_SMALL_STREAM)
|
|
// venc init, if is fast boot, must first init venc.
|
|
test_venc_init(1, 1280, 720, enCodecType); // RK_VIDEO_ID_AVC RK_VIDEO_ID_HEVC
|
|
klog("venc chn1");
|
|
test_jpeg_init(2, 640, 360, RK_VIDEO_ID_MJPEG); // RK_VIDEO_ID_AVC RK_VIDEO_ID_HEVC
|
|
klog("venc chn2");
|
|
// vi_dev_init(0, 0);
|
|
vi_chn_init(1, 1280, 720);
|
|
klog("vi ch1");
|
|
vi_chn_init(2, 640, 360);
|
|
klog("vi chn2");
|
|
|
|
MPP_CHN_S stSrcChn, stDestChn;
|
|
// bind vi to venc
|
|
stSrcChn.enModId = RK_ID_VI;
|
|
stSrcChn.s32DevId = 0;
|
|
stSrcChn.s32ChnId = 1;
|
|
|
|
stDestChn.enModId = RK_ID_VENC;
|
|
stDestChn.s32DevId = 0;
|
|
stDestChn.s32ChnId = 1;
|
|
s32Ret = RK_MPI_SYS_Bind(&stSrcChn, &stDestChn);
|
|
if (s32Ret != RK_SUCCESS) {
|
|
goto __FAILED;
|
|
}
|
|
klog("bind chn 1");
|
|
|
|
stSrcChn.s32ChnId = 2;
|
|
stDestChn.s32ChnId = 2;
|
|
s32Ret = RK_MPI_SYS_Bind(&stSrcChn, &stDestChn);
|
|
if (s32Ret != RK_SUCCESS) {
|
|
goto __FAILED;
|
|
}
|
|
klog("bind chn 2");
|
|
|
|
pthread_t main_thread1;
|
|
pthread_create(&main_thread1, NULL, GetMediaBuffer, 1);
|
|
pthread_t main_thread2;
|
|
pthread_create(&main_thread2, NULL, GetViBuffer, 2);
|
|
pthread_t main_thread3;
|
|
pthread_create(&main_thread3, NULL, GetMediaBuffer, 2);
|
|
#endif
|
|
|
|
#if (ENABLE_RKAIQ)
|
|
int rk_color_mode, file_size, fd, ret = 0;
|
|
void *mem, *vir_addr, *iq_mem, *vir_iqaddr;
|
|
off_t rk_color_mode_addr, addr_iq;
|
|
|
|
RK_S64 s64AiqInitStart = TEST_COMM_GetNowUs();
|
|
|
|
rk_led_value = (int)get_cmd_val("rk_led_value", 0);
|
|
int rk_night_mode = (int)get_cmd_val("rk_night_mode", 0);
|
|
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_color_mode_addr = (off_t)get_cmd_val("rk_color_mode", 16);
|
|
if ((fd = open("/dev/mem", O_RDWR | O_SYNC)) < 0) {
|
|
perror("open error");
|
|
return -1;
|
|
}
|
|
|
|
mem = mmap(0, MAP_SIZE_NIGHT, PROT_READ | PROT_WRITE, MAP_SHARED, fd,
|
|
rk_color_mode_addr & ~MAP_MASK_NIGHT);
|
|
vir_addr = mem + (rk_color_mode_addr & MAP_MASK_NIGHT);
|
|
rk_color_mode = *((unsigned long *)vir_addr);
|
|
|
|
addr_iq = (off_t)get_cmd_val("rk_iqbin_addr", 16);
|
|
file_size = (int)get_cmd_val("rk_iqbin_size", 16);
|
|
iq_mem =
|
|
mmap(0, file_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, addr_iq & ~MAP_MASK);
|
|
vir_iqaddr = iq_mem + (addr_iq & MAP_MASK);
|
|
|
|
rk_aiq_sys_ctx_t *aiq_ctx;
|
|
rk_aiq_static_info_t aiq_static_info;
|
|
rk_aiq_uapi2_sysctl_enumStaticMetasByPhyId(s32chnlId, &aiq_static_info);
|
|
|
|
if ((rk_night_mode == 2 && rk_color_mode) || rk_night_mode == 4) {
|
|
printf("=====night mode=====\n");
|
|
ret = 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);
|
|
return -1;
|
|
}
|
|
} else {
|
|
printf("=====day mode=======\n");
|
|
ret = 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);
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
ret = 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);
|
|
}
|
|
|
|
aiq_ctx = rk_aiq_uapi2_sysctl_init(aiq_static_info.sensor_info.sensor_name,
|
|
"/etc/iqfiles/", NULL, NULL);
|
|
if (aiq_ctx == NULL) {
|
|
printf("%s: failed to init aiq\n", aiq_static_info.sensor_info.sensor_name);
|
|
}
|
|
|
|
if (hdr_mode == RK_AIQ_WORKING_MODE_ISP_HDR2)
|
|
klog("aiq in hdr mode");
|
|
if (rk_aiq_uapi2_sysctl_prepare(aiq_ctx, 0, 0, hdr_mode)) {
|
|
printf("rkaiq engine prepare failed !\n");
|
|
return -1;
|
|
}
|
|
if (rk_aiq_uapi2_sysctl_start(aiq_ctx)) {
|
|
printf("rk_aiq_uapi2_sysctl_start failed\n");
|
|
return -1;
|
|
}
|
|
klog("aiq start");
|
|
if (rk_night_mode == 2) {
|
|
smartIr_ctx->aiq_ctx = aiq_ctx;
|
|
smartIr_ctx->ir_ctx = rk_smart_ir_init(aiq_ctx);
|
|
smartIr_ctx->ir_ctx->state = rk_color_mode;
|
|
load_ir_configs(d2n, n2d, rbase, bbase, rad, dis, switch_cnt);
|
|
smartIr_ctx->tquit = false;
|
|
pthread_create(&smartIr_ctx->tid, NULL, switch_ir_thread, NULL);
|
|
smartIr_ctx->started = true;
|
|
}
|
|
|
|
RK_S64 s64AiqInitEnd = TEST_COMM_GetNowUs();
|
|
printf("Aiq:%lld us\n", s64AiqInitEnd - s64AiqInitStart);
|
|
#endif
|
|
|
|
GetMediaBuffer0(NULL);
|
|
|
|
#if (ENABLE_SMALL_STREAM)
|
|
pthread_join(main_thread1, RK_NULL);
|
|
pthread_join(main_thread2, RK_NULL);
|
|
pthread_join(main_thread3, RK_NULL);
|
|
s32Ret |= RK_MPI_SYS_UnBind(&stSrcChn, &stDestChn);
|
|
s32Ret |= RK_MPI_VI_DisableChn(0, 1);
|
|
s32Ret |= RK_MPI_VI_DisableChn(0, 2);
|
|
|
|
s32Ret |= RK_MPI_VENC_StopRecvFrame(1);
|
|
s32Ret |= RK_MPI_VENC_StopRecvFrame(2);
|
|
if (s32Ret != RK_SUCCESS) {
|
|
return s32Ret;
|
|
}
|
|
|
|
s32Ret = RK_MPI_VENC_DestroyChn(1);
|
|
s32Ret = RK_MPI_VENC_DestroyChn(2);
|
|
s32Ret = RK_MPI_VI_DisableDev(0);
|
|
#endif
|
|
|
|
#if (ENABLE_RTSP)
|
|
if (g_rtsplive)
|
|
rtsp_del_demo(g_rtsplive);
|
|
#endif
|
|
|
|
__FAILED:
|
|
#if (ENABLE_RKAIQ)
|
|
if (fd > 0)
|
|
close(fd);
|
|
if (mem != MAP_FAILED)
|
|
munmap(mem, MAP_SIZE_NIGHT);
|
|
if (iq_mem != MAP_FAILED)
|
|
munmap(iq_mem, file_size);
|
|
if (rk_night_mode == 2) {
|
|
rk_gpio_unexport(irled_enable_gpio);
|
|
rk_gpio_unexport(ircut_on_gpio);
|
|
rk_gpio_unexport(ircut_off_gpio);
|
|
pthread_join(smartIr_ctx->tid, RK_NULL);
|
|
sample_smartIr_stop();
|
|
}
|
|
rk_aiq_uapi2_sysctl_stop(aiq_ctx, false);
|
|
rk_aiq_uapi2_sysctl_deinit(aiq_ctx);
|
|
#endif
|
|
|
|
RK_MPI_SYS_Exit();
|
|
return 0;
|
|
}
|