luckfox-pico-sdk/media/samples/example/demo/sample_demo_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

717 lines
23 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif
#endif /* End of #ifdef __cplusplus */
#include "rockiva/rockiva_ba_api.h"
#include <assert.h>
#include <errno.h>
#include <fcntl.h>
#include <getopt.h>
#include <pthread.h>
#include <signal.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/prctl.h>
#include <time.h>
#include <unistd.h>
#include "rtsp_demo.h"
#include "sample_comm.h"
#include <stdatomic.h>
pthread_mutex_t g_rtsp_mutex = PTHREAD_MUTEX_INITIALIZER;
static rtsp_demo_handle g_rtsplive = NULL;
static rtsp_session_handle g_rtsp_session_0, g_rtsp_session_1, g_rtsp_session_2,
g_rtsp_session_3;
static int rociva_run_flag = 0;
static RockIvaHandle rkba_handle;
static RockIvaBaTaskParams initParams;
static RockIvaInitParam globalParams;
typedef struct _rkMpiCtx {
SAMPLE_VI_CTX_S vi[4]; // camera 0: 0,1; camera 1: 2,3
SAMPLE_VENC_CTX_S venc[4];
} SAMPLE_MPI_CTX_S;
static bool quit = false;
static void sigterm_handler(int sig) {
fprintf(stderr, "signal %d\n", sig);
quit = true;
}
static RK_CHAR optstr[] = "?::r:f:W:H:w:h:s:n:b:";
static const struct option long_options[] = {
{"hdr", required_argument, NULL, 'r'},
{"fps", required_argument, NULL, 'f'},
{"main_width", required_argument, NULL, 'W'},
{"main_height", required_argument, NULL, 'H'},
{"sub_width", required_argument, NULL, 'w'},
{"sub_height", required_argument, NULL, 'h'},
{"sensorid", required_argument, NULL, 's'},
{"enable_npu", required_argument, NULL, 'n'},
{"buf_share", required_argument, NULL, 'b'},
{"help", optional_argument, NULL, '?'},
{NULL, 0, NULL, 0},
};
/******************************************************************************
* function : venc thread
******************************************************************************/
static void *venc0_get_stream(void *pArgs) {
printf("#Start %s , arg:%p\n", __func__, pArgs);
SAMPLE_VENC_CTX_S *ctx = (SAMPLE_VENC_CTX_S *)(pArgs);
RK_S32 s32Ret = RK_FAILURE;
// char name[256] = {0};
// FILE *fp = RK_NULL;
void *pData = RK_NULL;
RK_S32 loopCount = 0;
while (!quit) {
s32Ret = SAMPLE_COMM_VENC_GetStream(ctx, &pData);
if (s32Ret == RK_SUCCESS) {
RK_LOGD("chn:%d, loopCount:%d wd:%d\n", ctx->s32ChnId, loopCount,
ctx->stFrame.pstPack->u32Len);
// exit when complete
if (ctx->s32loopCount > 0) {
if (loopCount >= ctx->s32loopCount) {
SAMPLE_COMM_VENC_ReleaseStream(ctx);
quit = true;
break;
}
}
PrintStreamDetails(ctx->s32ChnId, ctx->stFrame.pstPack->u32Len);
pthread_mutex_lock(&g_rtsp_mutex);
rtsp_tx_video(g_rtsp_session_0, pData, ctx->stFrame.pstPack->u32Len,
ctx->stFrame.pstPack->u64PTS);
rtsp_do_event(g_rtsplive);
pthread_mutex_unlock(&g_rtsp_mutex);
SAMPLE_COMM_VENC_ReleaseStream(ctx);
loopCount++;
}
usleep(1000);
}
return RK_NULL;
}
static void *venc1_get_stream(void *pArgs) {
printf("#Start %s , arg:%p\n", __func__, pArgs);
SAMPLE_VENC_CTX_S *ctx = (SAMPLE_VENC_CTX_S *)(pArgs);
RK_S32 s32Ret = RK_FAILURE;
// char name[256] = {0};
// FILE *fp = RK_NULL;
void *pData = RK_NULL;
RK_S32 loopCount = 0;
while (!quit) {
s32Ret = SAMPLE_COMM_VENC_GetStream(ctx, &pData);
if (s32Ret == RK_SUCCESS) {
RK_LOGD("chn:%d, loopCount:%d wd:%d\n", ctx->s32ChnId, loopCount,
ctx->stFrame.pstPack->u32Len);
// exit when complete
if (ctx->s32loopCount > 0) {
if (loopCount >= ctx->s32loopCount) {
SAMPLE_COMM_VENC_ReleaseStream(ctx);
quit = true;
break;
}
}
PrintStreamDetails(ctx->s32ChnId, ctx->stFrame.pstPack->u32Len);
pthread_mutex_lock(&g_rtsp_mutex);
rtsp_tx_video(g_rtsp_session_1, pData, ctx->stFrame.pstPack->u32Len,
ctx->stFrame.pstPack->u64PTS);
rtsp_do_event(g_rtsplive);
pthread_mutex_unlock(&g_rtsp_mutex);
SAMPLE_COMM_VENC_ReleaseStream(ctx);
loopCount++;
}
usleep(1000);
}
return RK_NULL;
}
static void *venc2_get_stream(void *pArgs) {
printf("#Start %s , arg:%p\n", __func__, pArgs);
SAMPLE_VENC_CTX_S *ctx = (SAMPLE_VENC_CTX_S *)(pArgs);
RK_S32 s32Ret = RK_FAILURE;
// char name[256] = {0};
// FILE *fp = RK_NULL;
void *pData = RK_NULL;
RK_S32 loopCount = 0;
while (!quit) {
s32Ret = SAMPLE_COMM_VENC_GetStream(ctx, &pData);
if (s32Ret == RK_SUCCESS) {
RK_LOGD("chn:%d, loopCount:%d wd:%d\n", ctx->s32ChnId, loopCount,
ctx->stFrame.pstPack->u32Len);
// exit when complete
if (ctx->s32loopCount > 0) {
if (loopCount >= ctx->s32loopCount) {
SAMPLE_COMM_VENC_ReleaseStream(ctx);
quit = true;
break;
}
}
PrintStreamDetails(ctx->s32ChnId, ctx->stFrame.pstPack->u32Len);
pthread_mutex_lock(&g_rtsp_mutex);
rtsp_tx_video(g_rtsp_session_2, pData, ctx->stFrame.pstPack->u32Len,
ctx->stFrame.pstPack->u64PTS);
rtsp_do_event(g_rtsplive);
pthread_mutex_unlock(&g_rtsp_mutex);
SAMPLE_COMM_VENC_ReleaseStream(ctx);
loopCount++;
}
usleep(1000);
}
return RK_NULL;
}
static void *venc3_get_stream(void *pArgs) {
printf("#Start %s , arg:%p\n", __func__, pArgs);
SAMPLE_VENC_CTX_S *ctx = (SAMPLE_VENC_CTX_S *)(pArgs);
RK_S32 s32Ret = RK_FAILURE;
// char name[256] = {0};
// FILE *fp = RK_NULL;
void *pData = RK_NULL;
RK_S32 loopCount = 0;
while (!quit) {
s32Ret = SAMPLE_COMM_VENC_GetStream(ctx, &pData);
if (s32Ret == RK_SUCCESS) {
RK_LOGD("chn:%d, loopCount:%d wd:%d\n", ctx->s32ChnId, loopCount,
ctx->stFrame.pstPack->u32Len);
// exit when complete
if (ctx->s32loopCount > 0) {
if (loopCount >= ctx->s32loopCount) {
SAMPLE_COMM_VENC_ReleaseStream(ctx);
quit = true;
break;
}
}
PrintStreamDetails(ctx->s32ChnId, ctx->stFrame.pstPack->u32Len);
pthread_mutex_lock(&g_rtsp_mutex);
rtsp_tx_video(g_rtsp_session_3, pData, ctx->stFrame.pstPack->u32Len,
ctx->stFrame.pstPack->u64PTS);
rtsp_do_event(g_rtsplive);
pthread_mutex_unlock(&g_rtsp_mutex);
SAMPLE_COMM_VENC_ReleaseStream(ctx);
loopCount++;
}
usleep(1000);
}
return RK_NULL;
}
void rkba_callback(const RockIvaBaResult *result, const RockIvaExecuteStatus status,
void *userData) {
if (result->objNum == 0)
return;
printf("status is %d, frame %d, result->objNum is %d\n", status, result->frameId,
result->objNum);
for (int i = 0; i < result->objNum; i++) {
printf("topLeft:[%d,%d], bottomRight:[%d,%d],"
"objId is %d, frameId is %d, score is %d, type is %d\n",
result->triggerObjects[i].objInfo.rect.topLeft.x,
result->triggerObjects[i].objInfo.rect.topLeft.y,
result->triggerObjects[i].objInfo.rect.bottomRight.x,
result->triggerObjects[i].objInfo.rect.bottomRight.y,
result->triggerObjects[i].objInfo.objId,
result->triggerObjects[i].objInfo.frameId,
result->triggerObjects[i].objInfo.score,
result->triggerObjects[i].objInfo.type);
}
}
int rockiva_init() {
RockIvaRetCode ret;
// const char *model_type;
memset(&initParams, 0, sizeof(initParams));
memset(&globalParams, 0, sizeof(globalParams));
snprintf(globalParams.modelPath, ROCKIVA_PATH_LENGTH, "/usr/lib/");
globalParams.coreMask = 0x04;
globalParams.logLevel = ROCKIVA_LOG_ERROR;
globalParams.detModel |= ROCKIVA_OBJECT_TYPE_FACE;
globalParams.detModel |= ROCKIVA_OBJECT_TYPE_PERSON;
globalParams.detModel |= ROCKIVA_OBJECT_TYPE_NON_VEHICLE;
globalParams.detModel |= ROCKIVA_OBJECT_TYPE_VEHICLE;
globalParams.imageInfo.width = 720;
globalParams.imageInfo.height = 576;
globalParams.imageInfo.format = ROCKIVA_IMAGE_FORMAT_YUV420SP_NV12;
ROCKIVA_Init(&rkba_handle, ROCKIVA_MODE_VIDEO, &globalParams, NULL);
printf("ROCKIVA_Init over\n");
// 构建一个区域入侵规则
int web_width = 704;
int web_height = 480;
int ri_x = 0;
int ri_y = 0;
int ri_w = 704;
int ri_h = 480;
initParams.baRules.areaInBreakRule[0].ruleEnable = 1;
initParams.baRules.areaInBreakRule[0].sense = 50;
initParams.baRules.areaInBreakRule[0].alertTime = 1000; // ms
initParams.baRules.areaInBreakRule[0].minObjSize[2].height = 5;
initParams.baRules.areaInBreakRule[0].minObjSize[2].width = 5;
initParams.baRules.areaInBreakRule[0].event = ROCKIVA_BA_TRIP_EVENT_STAY;
initParams.baRules.areaInBreakRule[0].ruleID = 0;
initParams.baRules.areaInBreakRule[0].objType =
ROCKIVA_OBJECT_TYPE_BITMASK(ROCKIVA_OBJECT_TYPE_PERSON);
initParams.baRules.areaInBreakRule[0].area.pointNum = 4;
initParams.baRules.areaInBreakRule[0].area.points[0].x =
ROCKIVA_PIXEL_RATION_CONVERT(web_width, ri_x);
initParams.baRules.areaInBreakRule[0].area.points[0].y =
ROCKIVA_PIXEL_RATION_CONVERT(web_height, ri_y);
initParams.baRules.areaInBreakRule[0].area.points[1].x =
ROCKIVA_PIXEL_RATION_CONVERT(web_width, ri_x + ri_w);
initParams.baRules.areaInBreakRule[0].area.points[1].y =
ROCKIVA_PIXEL_RATION_CONVERT(web_height, ri_y);
initParams.baRules.areaInBreakRule[0].area.points[2].x =
ROCKIVA_PIXEL_RATION_CONVERT(web_width, ri_x + ri_w);
initParams.baRules.areaInBreakRule[0].area.points[2].y =
ROCKIVA_PIXEL_RATION_CONVERT(web_height, ri_y + ri_h);
initParams.baRules.areaInBreakRule[0].area.points[3].x =
ROCKIVA_PIXEL_RATION_CONVERT(web_width, ri_x);
initParams.baRules.areaInBreakRule[0].area.points[3].y =
ROCKIVA_PIXEL_RATION_CONVERT(web_height, ri_y + ri_h);
printf("(%d,%d), (%d,%d), (%d,%d), (%d,%d)\n",
initParams.baRules.areaInBreakRule[0].area.points[0].x,
initParams.baRules.areaInBreakRule[0].area.points[0].y,
initParams.baRules.areaInBreakRule[0].area.points[1].x,
initParams.baRules.areaInBreakRule[0].area.points[1].y,
initParams.baRules.areaInBreakRule[0].area.points[2].x,
initParams.baRules.areaInBreakRule[0].area.points[2].y,
initParams.baRules.areaInBreakRule[0].area.points[3].x,
initParams.baRules.areaInBreakRule[0].area.points[3].y);
initParams.aiConfig.detectResultMode = 0;
ret = ROCKIVA_BA_Init(rkba_handle, &initParams, rkba_callback);
if (ret != ROCKIVA_RET_SUCCESS) {
printf("ROCKIVA_BA_Init error %d\n", ret);
return -1;
}
printf("ROCKIVA_BA_Init success\n");
rociva_run_flag = 1;
return ret;
}
int rockiva_deinit() {
rociva_run_flag = 0;
ROCKIVA_BA_Release(rkba_handle);
ROCKIVA_Release(rkba_handle);
return 0;
}
int rkipc_rockiva_write_nv12_frame_by_fd(uint16_t width, uint16_t height,
uint32_t frame_id, int32_t fd) {
int ret;
if (!rociva_run_flag)
return 0;
RockIvaImage *image = (RockIvaImage *)malloc(sizeof(RockIvaImage));
memset(image, 0, sizeof(RockIvaImage));
image->info.transformMode = ROCKIVA_IMAGE_TRANSFORM_NONE;
image->info.width = width;
image->info.height = height;
image->info.format = ROCKIVA_IMAGE_FORMAT_YUV420SP_NV12;
image->frameId = frame_id;
image->dataAddr = NULL;
image->dataPhyAddr = NULL;
image->dataFd = fd;
ret = ROCKIVA_PushFrame(rkba_handle, image, NULL);
free(image);
return ret;
}
pthread_t get_vi_to_npu_thread;
static void *rkipc_get_vi_to_npu(void *arg) {
printf("#Start %s thread, arg:%p\n", __func__, arg);
int s32Ret;
int32_t loopCount = 0;
VIDEO_FRAME_INFO_S stViFrame;
while (!quit) {
s32Ret = RK_MPI_VI_GetChnFrame(0, 1, &stViFrame, 1000);
if (s32Ret == RK_SUCCESS) {
RK_LOGD("loopCount is %d, w is %d, h is %d, seq is %d, pts is %lld\n",
loopCount, stViFrame.stVFrame.u32Width, stViFrame.stVFrame.u32Height,
stViFrame.stVFrame.u32TimeRef, stViFrame.stVFrame.u64PTS / 1000);
// void *data = RK_MPI_MB_Handle2VirAddr(stViFrame.stVFrame.pMbBlk);
int32_t fd = RK_MPI_MB_Handle2Fd(stViFrame.stVFrame.pMbBlk);
rkipc_rockiva_write_nv12_frame_by_fd(
stViFrame.stVFrame.u32Width, stViFrame.stVFrame.u32Height, loopCount, fd);
s32Ret = RK_MPI_VI_ReleaseChnFrame(0, 1, &stViFrame);
if (s32Ret != RK_SUCCESS)
printf("RK_MPI_VI_ReleaseChnFrame fail %x\n", s32Ret);
loopCount++;
} else {
printf("RK_MPI_VI_GetChnFrame timeout %x\n", s32Ret);
}
}
return NULL;
}
static void print_usage(const RK_CHAR *name) {
printf("usage example:\n");
printf("\t%s -s 0 -W 1920 -H 1080 -w 720 -h 576 -f 30 -r 0 -s 1 -W 1920 -H 1080 -w "
"720 -h 576 -f 30 -r 0 -n 1 -b 1\n",
name);
printf("\trtsp://xx.xx.xx.xx/live/0, sensor 0 main-stream, Default OPEN\n");
printf("\trtsp://xx.xx.xx.xx/live/1, sensor 0 sub-stream, Default OPEN\n");
printf("\trtsp://xx.xx.xx.xx/live/2, sensor 1 main-stream, Default OPEN\n");
printf("\trtsp://xx.xx.xx.xx/live/3, sensor 1 sub-stream, Default OPEN\n");
printf("\t-s | --sensor id\n");
printf("\t-f | --fps: frame per second, Default 30\n");
printf("\t-r | --hdr: high dynamic range, Default 0\n");
printf("\t-W | --main_width: main-stream with, Default 1920\n");
printf("\t-H | --main_height: main-stream height, Default 1080\n");
printf("\t-w | --sub_width: sub-stream with, Default 720\n");
printf("\t-h | --sub_height: sub-stream height, Default 576\n");
printf("\t-n | --enable_npu: enable npu, Default 1\n");
printf("\t-b | --buf_share: enable buf share, Default 1\n");
}
/******************************************************************************
* function : main()
* Description : main
******************************************************************************/
void handle_pipe(int sig) { printf("%s sig = %d\n", __func__, sig); }
int main(int argc, char *argv[]) {
// RK_S32 s32Ret = RK_FAILURE;
SAMPLE_MPI_CTX_S *ctx;
int cam_0_fps = 30;
int cam_0_enable_hdr = 0;
int cam_0_video_0_width = 1920;
int cam_0_video_0_height = 1080;
int cam_0_video_1_width = 720;
int cam_0_video_1_height = 576;
// int cam_0_video_2_width = 896;
// int cam_0_video_2_height = 512;
int cam_1_fps = 30;
int cam_1_enable_hdr = 0;
int cam_1_video_0_width = 1920;
int cam_1_video_0_height = 1080;
int cam_1_video_1_width = 720;
int cam_1_video_1_height = 576;
int enable_npu = 1;
int enable_buf_share = 1;
CODEC_TYPE_E enCodecType = RK_CODEC_TYPE_H265;
VENC_RC_MODE_E enRcMode = VENC_RC_MODE_H265CBR;
RK_CHAR *pCodecName = "H265";
RK_S32 s32CamId = -1;
MPP_CHN_S vi_chn[6], venc_chn[4];
RK_CHAR *pOutPathVenc = "/userdata";
RK_S32 s32CamNum = 4;
RK_S32 s32loopCnt = -1;
RK_S32 s32BitRate = 4 * 1024;
RK_S32 i;
char *iq_file_dir = "/oem/usr/share/iqfiles";
if (argc < 2) {
print_usage(argv[0]);
return 0;
}
struct sigaction action;
action.sa_handler = handle_pipe;
sigemptyset(&action.sa_mask);
action.sa_flags = 0;
sigaction(SIGPIPE, &action, NULL);
ctx = (SAMPLE_MPI_CTX_S *)(malloc(sizeof(SAMPLE_MPI_CTX_S)));
memset(ctx, 0, sizeof(SAMPLE_MPI_CTX_S));
signal(SIGINT, sigterm_handler);
#ifdef RKAIQ
RK_BOOL bMultictx = RK_TRUE;
#endif
int c;
while ((c = getopt_long(argc, argv, optstr, long_options, NULL)) != -1) {
switch (c) {
case 's':
s32CamId = atoi(optarg);
break;
case 'f':
if (s32CamId == 0)
cam_0_fps = atoi(optarg);
if (s32CamId == 1)
cam_1_fps = atoi(optarg);
break;
case 'r':
if (s32CamId == 0)
cam_0_enable_hdr = atoi(optarg);
if (s32CamId == 1)
cam_1_enable_hdr = atoi(optarg);
break;
case 'W':
if (s32CamId == 0)
cam_0_video_0_width = atoi(optarg);
if (s32CamId == 1)
cam_1_video_0_width = atoi(optarg);
break;
case 'H':
if (s32CamId == 0)
cam_0_video_0_height = atoi(optarg);
if (s32CamId == 1)
cam_1_video_0_height = atoi(optarg);
break;
case 'w':
if (s32CamId == 0)
cam_0_video_1_width = atoi(optarg);
if (s32CamId == 1)
cam_1_video_1_width = atoi(optarg);
break;
case 'h':
if (s32CamId == 0)
cam_0_video_1_height = atoi(optarg);
if (s32CamId == 1)
cam_1_video_1_height = atoi(optarg);
break;
case 'n':
enable_npu = atoi(optarg);
break;
case 'b':
enable_buf_share = atoi(optarg);
break;
case '?':
default:
print_usage(argv[0]);
return 0;
}
}
printf("sensor 0: main:%d*%d, sub:%d*%d\n", cam_0_video_0_width, cam_0_video_0_height,
cam_0_video_1_width, cam_0_video_1_height);
printf("sensor 1: main:%d*%d, sub:%d*%d\n", cam_1_video_0_width, cam_1_video_0_height,
cam_1_video_1_width, cam_1_video_1_height);
if (cam_0_video_0_width <= 0 || cam_1_video_0_width <= 0 ||
cam_0_video_0_height <= 0 || cam_1_video_0_height <= 0) {
printf("invalid main stream width/height,please check!\n");
return -1;
}
printf("#CodecName:%s\n", pCodecName);
printf("#IQ Path: %s\n", iq_file_dir);
if (iq_file_dir) {
#ifdef RKAIQ
printf("#Rkaiq XML DirPath: %s\n", iq_file_dir);
printf("#bMultictx: %d\n\n", bMultictx);
rk_aiq_working_mode_t hdr_mode_0 = RK_AIQ_WORKING_MODE_NORMAL;
rk_aiq_working_mode_t hdr_mode_1 = RK_AIQ_WORKING_MODE_NORMAL;
if (cam_0_enable_hdr)
hdr_mode_0 = RK_AIQ_WORKING_MODE_ISP_HDR2;
if (cam_1_enable_hdr)
hdr_mode_1 = RK_AIQ_WORKING_MODE_ISP_HDR2;
SAMPLE_COMM_ISP_Init(0, hdr_mode_0, bMultictx, iq_file_dir);
SAMPLE_COMM_ISP_Run(0);
SAMPLE_COMM_ISP_SetFrameRate(0, cam_0_fps);
SAMPLE_COMM_ISP_Init(1, hdr_mode_1, bMultictx, iq_file_dir);
SAMPLE_COMM_ISP_Run(1);
SAMPLE_COMM_ISP_SetFrameRate(1, cam_1_fps);
#endif
}
// init rtsp
g_rtsplive = create_rtsp_demo(554);
g_rtsp_session_0 = rtsp_new_session(g_rtsplive, "/live/0");
g_rtsp_session_1 = rtsp_new_session(g_rtsplive, "/live/1");
g_rtsp_session_2 = rtsp_new_session(g_rtsplive, "/live/2");
g_rtsp_session_3 = rtsp_new_session(g_rtsplive, "/live/3");
rtsp_set_video(g_rtsp_session_0, RTSP_CODEC_ID_VIDEO_H265, NULL, 0);
rtsp_set_video(g_rtsp_session_1, RTSP_CODEC_ID_VIDEO_H265, NULL, 0);
rtsp_set_video(g_rtsp_session_2, RTSP_CODEC_ID_VIDEO_H265, NULL, 0);
rtsp_set_video(g_rtsp_session_3, RTSP_CODEC_ID_VIDEO_H265, NULL, 0);
rtsp_sync_video_ts(g_rtsp_session_0, rtsp_get_reltime(), rtsp_get_ntptime());
rtsp_sync_video_ts(g_rtsp_session_1, rtsp_get_reltime(), rtsp_get_ntptime());
rtsp_sync_video_ts(g_rtsp_session_2, rtsp_get_reltime(), rtsp_get_ntptime());
rtsp_sync_video_ts(g_rtsp_session_3, rtsp_get_reltime(), rtsp_get_ntptime());
if (enable_npu)
rockiva_init();
if (RK_MPI_SYS_Init() != RK_SUCCESS) {
goto __FAILED;
}
// Init VI and VENC 0~4
for (i = 0; i < s32CamNum; i++) {
if (i == 0) {
ctx->vi[i].u32Width = cam_0_video_0_width;
ctx->vi[i].u32Height = cam_0_video_0_height;
}
if (i == 1) {
ctx->vi[i].u32Width = cam_0_video_1_width;
ctx->vi[i].u32Height = cam_0_video_1_height;
}
if (i == 2) {
ctx->vi[i].u32Width = cam_1_video_0_width;
ctx->vi[i].u32Height = cam_1_video_0_height;
}
if (i == 3) {
ctx->vi[i].u32Width = cam_1_video_1_width;
ctx->vi[i].u32Height = cam_1_video_1_height;
}
if (i < 2) {
ctx->vi[i].s32DevId = 0;
ctx->vi[i].u32PipeId = 0;
ctx->vi[i].s32ChnId = i;
} else {
ctx->vi[i].s32DevId = 1;
ctx->vi[i].u32PipeId = 1;
ctx->vi[i].s32ChnId = i - 2;
}
ctx->vi[i].stChnAttr.stIspOpt.u32BufCount = 2;
ctx->vi[i].stChnAttr.stIspOpt.enMemoryType = VI_V4L2_MEMORY_TYPE_DMABUF;
ctx->vi[i].stChnAttr.u32Depth = 0;
ctx->vi[i].stChnAttr.enPixelFormat = RK_FMT_YUV420SP;
ctx->vi[i].stChnAttr.enCompressMode = COMPRESS_MODE_NONE;
ctx->vi[i].stChnAttr.stFrameRate.s32SrcFrameRate = -1;
ctx->vi[i].stChnAttr.stFrameRate.s32DstFrameRate = -1;
if ((i == 1) && enable_npu) { // NPU only 10 fps, need anothor buffer
ctx->vi[i].stChnAttr.stIspOpt.u32BufCount = 3;
ctx->vi[i].stChnAttr.u32Depth = 1;
pthread_create(&get_vi_to_npu_thread, NULL, rkipc_get_vi_to_npu, NULL);
}
SAMPLE_COMM_VI_CreateChn(&ctx->vi[i]);
vi_chn[i].enModId = RK_ID_VI;
vi_chn[i].s32DevId = ctx->vi[i].s32DevId;
vi_chn[i].s32ChnId = ctx->vi[i].s32ChnId;
ctx->venc[i].s32ChnId = i;
if (i == 0) {
ctx->venc[i].u32Width = cam_0_video_0_width;
ctx->venc[i].u32Height = cam_0_video_0_height;
ctx->venc[i].stChnAttr.stVencAttr.u32BufSize =
cam_0_video_0_width * cam_0_video_0_height / 4;
ctx->venc[i].u32Fps = cam_0_fps;
}
if (i == 1) {
ctx->venc[i].u32Width = cam_0_video_1_width;
ctx->venc[i].u32Height = cam_0_video_1_height;
ctx->venc[i].stChnAttr.stVencAttr.u32BufSize =
cam_0_video_1_width * cam_0_video_1_height / 4;
ctx->venc[i].u32Fps = cam_0_fps;
}
if (i == 2) {
ctx->venc[i].u32Width = cam_1_video_0_width;
ctx->venc[i].u32Height = cam_1_video_0_height;
ctx->venc[i].stChnAttr.stVencAttr.u32BufSize =
cam_1_video_0_width * cam_1_video_0_height / 4;
ctx->venc[i].u32Fps = cam_1_fps;
}
if (i == 3) {
ctx->venc[i].u32Width = cam_1_video_1_width;
ctx->venc[i].u32Height = cam_1_video_1_height;
ctx->venc[i].stChnAttr.stVencAttr.u32BufSize =
cam_1_video_1_width * cam_1_video_1_height / 4;
ctx->venc[i].u32Fps = cam_1_fps;
}
ctx->venc[i].u32Gop = 50;
ctx->venc[i].u32BitRate = s32BitRate;
ctx->venc[i].enCodecType = enCodecType;
ctx->venc[i].enRcMode = enRcMode;
if (i == 0)
ctx->venc[i].getStreamCbFunc = venc0_get_stream;
if (i == 1)
ctx->venc[i].getStreamCbFunc = venc1_get_stream;
if (i == 2)
ctx->venc[i].getStreamCbFunc = venc2_get_stream;
if (i == 3)
ctx->venc[i].getStreamCbFunc = venc3_get_stream;
ctx->venc[i].s32loopCount = s32loopCnt;
ctx->venc[i].dstFilePath = pOutPathVenc;
// H264 66Baseline 77Main Profile 100High Profile
// H265 0Main Profile 1Main 10 Profile
// MJPEG 0Baseline
ctx->venc[i].stChnAttr.stVencAttr.u32Profile = 0;
ctx->venc[i].stChnAttr.stGopAttr.enGopMode = VENC_GOPMODE_NORMALP;
ctx->venc[i].enable_buf_share = enable_buf_share;
SAMPLE_COMM_VENC_CreateChn(&ctx->venc[i]);
printf("venc[%d]:u32BufSize:%d\n", i,
ctx->venc[i].stChnAttr.stVencAttr.u32BufSize);
venc_chn[i].enModId = RK_ID_VENC;
venc_chn[i].s32DevId = 0;
venc_chn[i].s32ChnId = ctx->venc[i].s32ChnId;
}
SAMPLE_COMM_Bind(&vi_chn[0], &venc_chn[0]);
SAMPLE_COMM_Bind(&vi_chn[1], &venc_chn[1]);
SAMPLE_COMM_Bind(&vi_chn[2], &venc_chn[2]);
SAMPLE_COMM_Bind(&vi_chn[3], &venc_chn[3]);
printf("%s initial finish\n", __func__);
while (!quit) {
sleep(1);
}
printf("%s exit!\n", __func__);
for (i = 0; i < s32CamNum; i++) {
if (ctx->venc[i].getStreamCbFunc) {
pthread_join(ctx->venc[i].getStreamThread, NULL);
}
}
if (enable_npu)
rockiva_deinit();
pthread_join(get_vi_to_npu_thread, NULL);
if (g_rtsplive)
rtsp_del_demo(g_rtsplive);
SAMPLE_COMM_UnBind(&vi_chn[0], &venc_chn[0]);
SAMPLE_COMM_UnBind(&vi_chn[1], &venc_chn[1]);
SAMPLE_COMM_UnBind(&vi_chn[2], &venc_chn[2]);
SAMPLE_COMM_UnBind(&vi_chn[3], &venc_chn[3]);
// Destroy VI[0]
for (i = 0; i < s32CamNum; i++) {
SAMPLE_COMM_VENC_DestroyChn(&ctx->venc[i]);
SAMPLE_COMM_VI_DestroyChn(&ctx->vi[i]);
}
__FAILED:
RK_MPI_SYS_Exit();
if (iq_file_dir) {
#ifdef RKAIQ
for (int i = 0; i < s32CamNum; i++) {
SAMPLE_COMM_ISP_Stop(i);
}
#endif
}
if (ctx) {
free(ctx);
ctx = RK_NULL;
}
return 0;
}
#ifdef __cplusplus
#if __cplusplus
}
#endif
#endif /* End of #ifdef __cplusplus */