A191型RV1126 摄像头:gc2053
首先感谢这位大佬的博文,其中的一些细节我就不细说了
可以参考以下博文:
https://blog.csdn.net/qq_36769014/article/details/128224487
建议先仔细阅读官方文档这块的内容
我的参考代码在最下面
主要是参考sdk包里面的例子 rkmedia_vi_vp_vo_test.c
例子里面有些如何调用
/*
* -> VI2
* VI0 -> VP0 -- ISPP -> VI3
* -> VI4
* -> VI5
* How to use ISPP?
* 1. add code to kernel dts:
* &rkispp_vir2 {
* status = "okay";
* };
* 2. check new /dev/media*, as is my case: /dev/media5
* 3. media-ctl -p -d /dev/media5
* check rkispp_input_image for VP0: as is my case: /dev/video45
* check rkispp_m_bypass for VI2: as is my case: /dev/video46
* check rkispp_scale0 for VI3: as is my case: /dev/video47
* check rkispp_scale1 for VI4: as is my case: /dev/video48
* check rkispp_scale2 for VI5: as is my case: /dev/video49
* 4. config:
* media-ctl -d /dev/media5 -l '"rkispp_input_image":0->"rkispp-subdev":0[1]'
* media-ctl -d /dev/media5 --set-v4l2
* '"rkispp-subdev":0[fmt:YUYV8_2X8/1920x1080]' media-ctl -d /dev/media5
* --set-v4l2 '"rkispp-subdev":2[fmt:YUYV8_2X8/1920x1080]'
* 5. enable VI2, VI3, VI4, VI5(one or more) before VP0
*/
这个也仅供参考,实际不同板子和摄像头的效果是不同的。
我是修改了dts中的
&rkispp_vir1 {
status = “okay”;
};
开启了media3
rv1109-38-v10-spi-nand.dts
&i2c1 mipi_in_ucam0 vicap模块
gc2053 -> csi_dphy0 -> mipi_csi2 -> rkcif_mipi_lvds
对应的关系是一样的
rkvicap_mipi_lvds----rkcif_mipi_lvds
rkvicap--------------rkcif
rkvicap_dvp----------rkcif_dvp
我们首先要调用把media-ctl这个指令把 每个media对应出来的jvideo节点去理解
media-ctl -p -d /dev/media* 查看对应版本 和对应接口
画出数据链路拓补图
Source和符号->表示输出
Sink和符号 <- 就表示输入
ink 表示连接,或者表示链路
仅供参考
由此我们可以得到
/dev/media0 rkcif_mipi_lvds
/dev/media1 rkisp0
/dev/media2 rkispp0
当我添加上了rkispp_vir1之后 可以看到多了一个 /dev/media3,
仅供参考
input: /dev/video25, rkispp_input_image
output1: /dev/video26, rkispp_m_bypass
output2: /dev/video27, rkispp_scale0
output3: /dev/video28, rkispp_scale1
output4: /dev/video29 rkispp_scale2
再根据以上的 vp模块的运用中的第四点修改
最后加上rtsp的代码运行效果如下
// Copyright 2020 Fuzhou Rockchip Electronics Co., Ltd. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "sample_common.h"
#include "librtsp/rtsp_demo.h"
#include "rkmedia_api.h"
#include "rkmedia_venc.h"
/*
* -> VI2
* VI0 -> VP0 -- ISPP -> VI3
* -> VI4
* -> VI5
* How to use ISPP?
* 1. add code to kernel dts:
* &rkispp_vir2 {
* status = "okay";
* };
* 2. check new /dev/media*, as is my case: /dev/media5
* 3. media-ctl -p -d /dev/media5
* check rkispp_input_image for VP0: as is my case: /dev/video45
* check rkispp_m_bypass for VI2: as is my case: /dev/video46
* check rkispp_scale0 for VI3: as is my case: /dev/video47
* check rkispp_scale1 for VI4: as is my case: /dev/video48
* check rkispp_scale2 for VI5: as is my case: /dev/video49
* 4. config:
* media-ctl -d /dev/media5 -l '"rkispp_input_image":0->"rkispp-subdev":0[1]'
* media-ctl -d /dev/media5 --set-v4l2
* '"rkispp-subdev":0[fmt:YUYV8_2X8/1920x1080]' media-ctl -d /dev/media5
* --set-v4l2 '"rkispp-subdev":2[fmt:YUYV8_2X8/1920x1080]'
* 5. enable VI2, VI3, VI4, VI5(one or more) before VP0
*/
/*
================================================Myself===============================================
A191-eb-rv1126 sensor: gc2053 vi venc vp rtsp 网络四路监控
参考以上的官方提示
通过dts 添加rkispp_virl , 生成media3 对应映射出下面 video 节点
kernel dts:
* &rkispp_vir1 {
* status = "okay";
* };
media: /dev/media3,
input: /dev/video25, rkispp_input_image 打开
output1: /dev/video26, rkispp_m_bypass
output2: /dev/video27, rkispp_scale0
output3: /dev/video28, rkispp_scale1
output4: /dev/video29 rkispp_scale2
定义了四个(Video1GetVencBuffer)来分开四个线程rtsp,对应ip地址:video1 rtsp://192.168.101.36:554/live/video1_stream rkispp_m_bypass
video2 rtsp://192.168.101.36:555/live/video2_stream rkispp_scale0
video3 rtsp://192.168.101.36:556/live/video3_stream rkispp_scale1
video4 rtsp://192.168.101.36:557/live/video4_stream rkispp_scale2
vi通道 和 venc通道 都分别对应1~4
RK_MPI_SYS_GetMediaBuffer 函数调用后,还会打开视频流的,只用绑定好对应的vi和venc通道
配置VI通道属性->RK_MPI_VI_SetChnAttr()->RK_MPI_VI_EnableChn()s
往下分俩路走 1 RK_MPI_VI_StartStream()
2 RK_MPI_SYS_Bind()->RM_MPI_SYS_UnBind()
俩条线路的作用一样
最后都会以 RK_MPI_VI_DisableChn() 结束视频流
================================================Myself==================================================
*/
static bool quit = false;
static void sigterm_handler(int sig) {
fprintf(stderr, "signal %d\n", sig);
quit = true;
}
static RK_CHAR optstr[] = "?::a::I:M:i:m:";
static const struct option long_options[] = {
{"aiq", optional_argument, NULL, 'a'},
{"camid", required_argument, NULL, 'I'},
{"multictx", required_argument, NULL, 'M'},
{"input", required_argument, NULL, 'i'},
{"media", required_argument, NULL, 'm'},
{"help", optional_argument, NULL, '?'},
{NULL, 0, NULL, 0},
};
static void print_usage(const RK_CHAR *name) {
printf("usage example:\n");
#ifdef RKAIQ
printf("\t%s [-a [iqfiles_dir]]"
"[-I 0] "
"[-M 0] "
"[-i 45] "
"[-m 5] "
"\n",
name);
printf("\t-a | --aiq: enable aiq with dirpath provided, eg:-a "
"/oem/etc/iqfiles/, "
"set dirpath empty to using path by default, without this option aiq "
"should run in other application\n");
printf("\t-M | --multictx: switch of multictx in isp, set 0 to disable, set "
"1 to enable. Default: 0\n");
printf("\t-i | --input: intput video of ISPP. Default: 45\n");
printf("\t-m | --media: media of ISPP. Default: 5\n");
#else
printf("\t%s [-I 0]\n", name);
#endif
printf("\t-I | --camid: camera ctx id, Default 0\n");
}
static void *Video1GetVencBuffer(void *arg) {
printf("# Video1 Start %s thread, arg:%p\n", __func__, arg);
// init rtsp
rtsp_demo_handle rtsplive = NULL;
rtsp_session_handle session;
rtsplive = create_rtsp_demo(554);
session = rtsp_new_session(rtsplive, "/live/video1_stream");
rtsp_set_video(session, RTSP_CODEC_ID_VIDEO_H264, NULL, 0);
rtsp_sync_video_ts(session, rtsp_get_reltime(), rtsp_get_ntptime());
MEDIA_BUFFER mb = NULL;
while (!quit) {
mb = RK_MPI_SYS_GetMediaBuffer(RK_ID_VENC, 1,
-1);
if (mb) {
printf(
"-Get Video1 Encoded packet():ptr:%p, fd:%d, size:%zu, mode:%d, time "
"= %llu.\n",
RK_MPI_MB_GetPtr(mb), RK_MPI_MB_GetFD(mb), RK_MPI_MB_GetSize(mb),
RK_MPI_MB_GetModeID(mb), RK_MPI_MB_GetTimestamp(mb));
rtsp_tx_video(session, RK_MPI_MB_GetPtr(mb), RK_MPI_MB_GetSize(mb),
RK_MPI_MB_GetTimestamp(mb));
RK_MPI_MB_ReleaseBuffer(mb);
}
rtsp_do_event(rtsplive);
}
// release rtsp
rtsp_del_demo(rtsplive);
return NULL;
}
static void *Video2GetVencBuffer(void *arg) {
printf("# Video2 Start %s thread, arg:%p\n", __func__, arg);
// init rtsp
rtsp_demo_handle rtsplive = NULL;
rtsp_session_handle session;
rtsplive = create_rtsp_demo(555);
session = rtsp_new_session(rtsplive, "/live/video2_stream");
rtsp_set_video(session, RTSP_CODEC_ID_VIDEO_H264, NULL, 0);
rtsp_sync_video_ts(session, rtsp_get_reltime(), rtsp_get_ntptime());
MEDIA_BUFFER mb = NULL;
while (!quit) {
mb = RK_MPI_SYS_GetMediaBuffer(RK_ID_VENC, 2,
-1);
if (mb) {
printf(
"-Get Video2 Encoded packet():ptr:%p, fd:%d, size:%zu, mode:%d, time "
"= %llu.\n",
RK_MPI_MB_GetPtr(mb), RK_MPI_MB_GetFD(mb), RK_MPI_MB_GetSize(mb),
RK_MPI_MB_GetModeID(mb), RK_MPI_MB_GetTimestamp(mb));
rtsp_tx_video(session, RK_MPI_MB_GetPtr(mb), RK_MPI_MB_GetSize(mb),
RK_MPI_MB_GetTimestamp(mb));
RK_MPI_MB_ReleaseBuffer(mb);
}
rtsp_do_event(rtsplive);
}
// release rtsp
rtsp_del_demo(rtsplive);
return NULL;
}
static void *Video3GetVencBuffer(void *arg) {
printf("# Video3 Start %s thread, arg:%p\n", __func__, arg);
// init rtsp
rtsp_demo_handle rtsplive = NULL;
rtsp_session_handle session;
rtsplive = create_rtsp_demo(556);
session = rtsp_new_session(rtsplive, "/live/video3_stream");
rtsp_set_video(session, RTSP_CODEC_ID_VIDEO_H264, NULL, 0);
rtsp_sync_video_ts(session, rtsp_get_reltime(), rtsp_get_ntptime());
MEDIA_BUFFER mb = NULL;
while (!quit) {
mb = RK_MPI_SYS_GetMediaBuffer(RK_ID_VENC, 3,
-1);
if (mb) {
printf(
"-Get Video3 Encoded packet():ptr:%p, fd:%d, size:%zu, mode:%d, time "
"= %llu.\n",
RK_MPI_MB_GetPtr(mb), RK_MPI_MB_GetFD(mb), RK_MPI_MB_GetSize(mb),
RK_MPI_MB_GetModeID(mb), RK_MPI_MB_GetTimestamp(mb));
rtsp_tx_video(session, RK_MPI_MB_GetPtr(mb), RK_MPI_MB_GetSize(mb),
RK_MPI_MB_GetTimestamp(mb));
RK_MPI_MB_ReleaseBuffer(mb);
}
rtsp_do_event(rtsplive);
}
// release rtsp
rtsp_del_demo(rtsplive);
return NULL;
}
static void *Video4GetVencBuffer(void *arg) {
printf("# Video4 Start %s thread, arg:%p\n", __func__, arg);
// init rtsp
rtsp_demo_handle rtsplive = NULL;
rtsp_session_handle session;
rtsplive = create_rtsp_demo(557);
session = rtsp_new_session(rtsplive, "/live/video4_stream");
rtsp_set_video(session, RTSP_CODEC_ID_VIDEO_H264, NULL, 0);
rtsp_sync_video_ts(session, rtsp_get_reltime(), rtsp_get_ntptime());
MEDIA_BUFFER mb = NULL;
while (!quit) {
mb = RK_MPI_SYS_GetMediaBuffer(RK_ID_VENC, 4,
-1);
if (mb) {
printf(
"-Get Video4 Encoded packet():ptr:%p, fd:%d, size:%zu, mode:%d, time "
"= %llu.\n",
RK_MPI_MB_GetPtr(mb), RK_MPI_MB_GetFD(mb), RK_MPI_MB_GetSize(mb),
RK_MPI_MB_GetModeID(mb), RK_MPI_MB_GetTimestamp(mb));
rtsp_tx_video(session, RK_MPI_MB_GetPtr(mb), RK_MPI_MB_GetSize(mb),
RK_MPI_MB_GetTimestamp(mb));
RK_MPI_MB_ReleaseBuffer(mb);
}
rtsp_do_event(rtsplive);
}
// release rtsp
rtsp_del_demo(rtsplive);
return NULL;
}
//--------------------main------------------------
int main(int argc, char *argv[]) {
RK_U32 u32Width = 1920;
RK_U32 u32Height = 1080;
int ret = 0;
int disp_width = 640;
int disp_height = 360;
//sensor输入像素
int video_width = 1920;
int video_height = 1080;
//sensor输出像素
int video1_width = 1920;
int video1_height = 1080;
int video2_width = disp_width;
int video2_height = disp_height;
int video3_width = 640;
int video3_height = 360;
int video4_width = 640;
int video4_height = 480;
//sensor venc 输出像素
int video1_venc_width = 1920;
int video1_venc_height = 1080;
int video2_venc_width = disp_width;
int video2_venc_height = disp_height;
int video3_venc_width = 640;
int video3_venc_height = 360;
int video4_venc_width = 640;
int video4_venc_height = 480;
RK_S32 s32CamId = 0;
#ifdef RKAIQ
RK_BOOL bMultictx = RK_FALSE;
#endif
int media_id = 3;
int input_id = 25;
char media[128];
char video_input[128];
char video_output1[128];
char video_output2[128];
char video_output3[128];
char video_output4[128];
int c;
char *iq_file_dir = NULL;
while ((c = getopt_long(argc, argv, optstr, long_options, NULL)) != -1) {
const char *tmp_optarg = optarg;
switch (c) {
case 'a':
if (!optarg && NULL != argv[optind] && '-' != argv[optind][0]) {
tmp_optarg = argv[optind++];
}
if (tmp_optarg) {
iq_file_dir = (char *)tmp_optarg;
} else {
iq_file_dir = "/oem/etc/iqfiles";
}
break;
case 'I':
s32CamId = atoi(optarg);
break;
#ifdef RKAIQ
case 'M':
if (atoi(optarg)) {
bMultictx = RK_TRUE;
}
break;
#endif
case 'i':
input_id = atoi(optarg);
break;
case 'm':
media_id = atoi(optarg);
break;
case '?':
default:
print_usage(argv[0]);
return 0;
}
}
snprintf(media, sizeof(media), "/dev/media%d", media_id);
snprintf(video_input, sizeof(video_input), "/dev/video%d", input_id);
snprintf(video_output1, sizeof(video_output1), "/dev/video%d", input_id + 1);
snprintf(video_output2, sizeof(video_output2), "/dev/video%d", input_id + 2);
snprintf(video_output3, sizeof(video_output3), "/dev/video%d", input_id + 3);
snprintf(video_output4, sizeof(video_output4), "/dev/video%d", input_id + 4);
printf("media: %s, input: %s, output1: %s, output2: %s, output3: %s, "
"output4: %s\n",
media, video_input, video_output1, video_output2, video_output3,
video_output4);
printf("#CameraIdx: %d\n\n", s32CamId);
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 = RK_AIQ_WORKING_MODE_NORMAL;
int fps = 30;
SAMPLE_COMM_ISP_Init(s32CamId, hdr_mode, bMultictx, iq_file_dir);
SAMPLE_COMM_ISP_Run(s32CamId);
SAMPLE_COMM_ISP_SetFrameRate(s32CamId, fps);
#endif
}
//RK_MPI_SYS_Init
RK_MPI_SYS_Init(); // init
//设置media视频流
char cmd[256];
snprintf(
cmd, sizeof(cmd),
"media-ctl -d %s -l '\"rkispp_input_image\":0->\"rkispp-subdev\":0[1]'",
media);
system(cmd);
snprintf(cmd, sizeof(cmd),
"media-ctl -d %s --set-v4l2 "
"'\"rkispp-subdev\":0[fmt:YUYV8_2X8/1920x1080]'",
media);
system(cmd);
snprintf(cmd, sizeof(cmd),
"media-ctl -d %s --set-v4l2 "
"'\"rkispp-subdev\":2[fmt:YUYV8_2X8/1920x1080]'",
media);
system(cmd);
//配置rkmedia vi 节点初始化。(输出的四个节点初始化要在vp之前)
VI_CHN_ATTR_S vi_chn_attr;
vi_chn_attr.pcVideoNode = "rkispp_scale0";
vi_chn_attr.u32BufCnt = 3;
vi_chn_attr.u32Width = video_width;
vi_chn_attr.u32Height = video_height;
vi_chn_attr.enPixFmt = IMAGE_TYPE_NV12;
vi_chn_attr.enWorkMode = VI_WORK_MODE_NORMAL;
ret = RK_MPI_VI_SetChnAttr(s32CamId, 0, &vi_chn_attr);
ret |= RK_MPI_VI_EnableChn(s32CamId, 0);
if (ret) {
printf("Create vi[0] failed! ret=%d\n", ret);
return -1;
}
memset(&vi_chn_attr, 0, sizeof(vi_chn_attr));
vi_chn_attr.pcVideoNode = video_output1;
vi_chn_attr.u32BufCnt = 3;
vi_chn_attr.u32Width = video1_width;
vi_chn_attr.u32Height = video1_height;
vi_chn_attr.enPixFmt = IMAGE_TYPE_NV12;
vi_chn_attr.enWorkMode = VI_WORK_MODE_NORMAL;
ret = RK_MPI_VI_SetChnAttr(1, 1, &vi_chn_attr);
ret |= RK_MPI_VI_EnableChn(1, 1);
if (ret) {
printf("Create vi[1] failed! ret=%d\n", ret);
return -1;
}
memset(&vi_chn_attr, 0, sizeof(vi_chn_attr));
vi_chn_attr.pcVideoNode = video_output2;
vi_chn_attr.u32BufCnt = 3;
vi_chn_attr.u32Width = video2_width;
vi_chn_attr.u32Height = video2_height;
vi_chn_attr.enPixFmt = IMAGE_TYPE_NV12;
vi_chn_attr.enWorkMode = VI_WORK_MODE_NORMAL;
ret = RK_MPI_VI_SetChnAttr(2, 2, &vi_chn_attr);
ret |= RK_MPI_VI_EnableChn(2, 2);
if (ret) {
printf("Create vi[2] failed! ret=%d\n", ret);
return -1;
}
memset(&vi_chn_attr, 0, sizeof(vi_chn_attr));
vi_chn_attr.pcVideoNode = video_output3;
vi_chn_attr.u32BufCnt = 3;
vi_chn_attr.u32Width = video3_width;
vi_chn_attr.u32Height = video3_height;
vi_chn_attr.enPixFmt = IMAGE_TYPE_NV12;
vi_chn_attr.enWorkMode = VI_WORK_MODE_NORMAL;
ret = RK_MPI_VI_SetChnAttr(3, 3, &vi_chn_attr);
ret |= RK_MPI_VI_EnableChn(3, 3);
if (ret) {
printf("Create vi[3] failed! ret=%d\n", ret);
return -1;
}
memset(&vi_chn_attr, 0, sizeof(vi_chn_attr));
vi_chn_attr.pcVideoNode = video_output4;
vi_chn_attr.u32BufCnt = 3;
vi_chn_attr.u32Width = video4_width;
vi_chn_attr.u32Height = video4_height;
vi_chn_attr.enPixFmt = IMAGE_TYPE_NV12;
vi_chn_attr.enWorkMode = VI_WORK_MODE_NORMAL;
ret = RK_MPI_VI_SetChnAttr(4, 4, &vi_chn_attr);
ret |= RK_MPI_VI_EnableChn(4, 4);
if (ret) {
printf("Create vi[4] failed! ret=%d\n", ret);
return -1;
}
//接着初始化vp,实际上就是初始化media中rkispp_input_image 节点video25
VP_CHN_ATTR_S vp_chn_attr;
vp_chn_attr.pcVideoNode = video_input;
vp_chn_attr.u32BufCnt = 3;
vp_chn_attr.u32Width = video_width;
vp_chn_attr.u32Height = video_height;
vp_chn_attr.enPixFmt = IMAGE_TYPE_NV12;
vp_chn_attr.enWorkMode = VP_WORK_MODE_NORMAL;
ret = RK_MPI_VP_SetChnAttr(0, 0, &vp_chn_attr);
ret |= RK_MPI_VP_EnableChn(0, 0);
if (ret) {
printf("Create vp[0] failed! ret=%d\n", ret);
return -1;
}
//最后就是将video0 绑定到video25, 这样video26、video27就可以像正常的video节点取流、绑定
MPP_CHN_S Vi_SrcChn = {0};
MPP_CHN_S Vp_DestChn = {0};
printf("#Bind VI[0] to VP[0]....\n");
Vi_SrcChn.enModId = RK_ID_VI;
Vi_SrcChn.s32ChnId = 0;
Vp_DestChn.enModId = RK_ID_VP;
Vp_DestChn.s32ChnId = 0;
ret = RK_MPI_SYS_Bind(&Vi_SrcChn, &Vp_DestChn);
if (ret) {
printf("Bind vi[0] to vp[0] failed! ret=%d\n", ret);
return -1;
}
//创建venc通道
//venc 1
VENC_CHN_ATTR_S venc_chn_attr;
memset(&venc_chn_attr, 0, sizeof(venc_chn_attr));
venc_chn_attr.stVencAttr.enType = RK_CODEC_TYPE_H264;
venc_chn_attr.stRcAttr.enRcMode = VENC_RC_MODE_H264CBR;
venc_chn_attr.stRcAttr.stH264Cbr.u32Gop = 30;
venc_chn_attr.stRcAttr.stH264Cbr.u32BitRate = video1_venc_width * video1_venc_height;
// frame rate: in 30/1, out 30/1.
venc_chn_attr.stRcAttr.stH264Cbr.fr32DstFrameRateDen = 1;
venc_chn_attr.stRcAttr.stH264Cbr.fr32DstFrameRateNum = 30;
venc_chn_attr.stRcAttr.stH264Cbr.u32SrcFrameRateDen = 1;
venc_chn_attr.stRcAttr.stH264Cbr.u32SrcFrameRateNum = 30;
venc_chn_attr.stVencAttr.imageType = IMAGE_TYPE_NV12;
venc_chn_attr.stVencAttr.u32PicWidth = video1_venc_width;
venc_chn_attr.stVencAttr.u32PicHeight = video1_venc_height;
venc_chn_attr.stVencAttr.u32VirWidth = video1_venc_width;
venc_chn_attr.stVencAttr.u32VirHeight = video1_venc_height;
venc_chn_attr.stVencAttr.u32Profile = 77;
ret = RK_MPI_VENC_CreateChn(1, &venc_chn_attr);
if (ret) {
printf("ERROR: create VENC[1] error! ret=%d\n", ret);
return 0;
}
//venc 2
memset(&venc_chn_attr, 0, sizeof(venc_chn_attr));
venc_chn_attr.stVencAttr.enType = RK_CODEC_TYPE_H264;
venc_chn_attr.stRcAttr.enRcMode = VENC_RC_MODE_H264CBR;
venc_chn_attr.stRcAttr.stH264Cbr.u32Gop = 30;
venc_chn_attr.stRcAttr.stH264Cbr.u32BitRate = video2_venc_width * video2_venc_height;
// frame rate: in 30/1, out 30/1.
venc_chn_attr.stRcAttr.stH264Cbr.fr32DstFrameRateDen = 1;
venc_chn_attr.stRcAttr.stH264Cbr.fr32DstFrameRateNum = 30;
venc_chn_attr.stRcAttr.stH264Cbr.u32SrcFrameRateDen = 1;
venc_chn_attr.stRcAttr.stH264Cbr.u32SrcFrameRateNum = 30;
venc_chn_attr.stVencAttr.imageType = IMAGE_TYPE_NV12;
venc_chn_attr.stVencAttr.u32PicWidth = video2_venc_width;
venc_chn_attr.stVencAttr.u32PicHeight = video2_venc_height;
venc_chn_attr.stVencAttr.u32VirWidth = video2_venc_width;
venc_chn_attr.stVencAttr.u32VirHeight = video2_venc_height;
venc_chn_attr.stVencAttr.u32Profile = 77;
ret = RK_MPI_VENC_CreateChn(2, &venc_chn_attr);
if (ret) {
printf("ERROR: create VENC[2] error! ret=%d\n", ret);
return 0;
}
//venc 3
memset(&venc_chn_attr, 0, sizeof(venc_chn_attr));
venc_chn_attr.stVencAttr.enType = RK_CODEC_TYPE_H264;
venc_chn_attr.stRcAttr.enRcMode = VENC_RC_MODE_H264CBR;
venc_chn_attr.stRcAttr.stH264Cbr.u32Gop = 30;
venc_chn_attr.stRcAttr.stH264Cbr.u32BitRate = video3_venc_width * video3_venc_height;
// frame rate: in 30/1, out 30/1.
venc_chn_attr.stRcAttr.stH264Cbr.fr32DstFrameRateDen = 1;
venc_chn_attr.stRcAttr.stH264Cbr.fr32DstFrameRateNum = 30;
venc_chn_attr.stRcAttr.stH264Cbr.u32SrcFrameRateDen = 1;
venc_chn_attr.stRcAttr.stH264Cbr.u32SrcFrameRateNum = 30;
venc_chn_attr.stVencAttr.imageType = IMAGE_TYPE_NV12;
venc_chn_attr.stVencAttr.u32PicWidth = video3_venc_width;
venc_chn_attr.stVencAttr.u32PicHeight = video3_venc_height;
venc_chn_attr.stVencAttr.u32VirWidth = video3_venc_width;
venc_chn_attr.stVencAttr.u32VirHeight = video3_venc_height;
venc_chn_attr.stVencAttr.u32Profile = 77;
ret = RK_MPI_VENC_CreateChn(3, &venc_chn_attr);
if (ret) {
printf("ERROR: create VENC[3] error! ret=%d\n", ret);
return 0;
}
//venc 4
memset(&venc_chn_attr, 0, sizeof(venc_chn_attr));
venc_chn_attr.stVencAttr.enType = RK_CODEC_TYPE_H264;
venc_chn_attr.stRcAttr.enRcMode = VENC_RC_MODE_H264CBR;
venc_chn_attr.stRcAttr.stH264Cbr.u32Gop = 30;
venc_chn_attr.stRcAttr.stH264Cbr.u32BitRate = video4_venc_width * video4_venc_height;
// frame rate: in 30/1, out 30/1.
venc_chn_attr.stRcAttr.stH264Cbr.fr32DstFrameRateDen = 1;
venc_chn_attr.stRcAttr.stH264Cbr.fr32DstFrameRateNum = 30;
venc_chn_attr.stRcAttr.stH264Cbr.u32SrcFrameRateDen = 1;
venc_chn_attr.stRcAttr.stH264Cbr.u32SrcFrameRateNum = 30;
venc_chn_attr.stVencAttr.imageType = IMAGE_TYPE_NV12;
venc_chn_attr.stVencAttr.u32PicWidth = video4_venc_width;
venc_chn_attr.stVencAttr.u32PicHeight = video4_venc_height;
venc_chn_attr.stVencAttr.u32VirWidth = video4_venc_width;
venc_chn_attr.stVencAttr.u32VirHeight = video4_venc_height;
venc_chn_attr.stVencAttr.u32Profile = 77;
ret = RK_MPI_VENC_CreateChn(4, &venc_chn_attr);
if (ret) {
printf("ERROR: create VENC[4] error! ret=%d\n", ret);
return 0;
}
//绑定vi venc通道
MPP_CHN_S video1_rtspSrcChn;
video1_rtspSrcChn.enModId = RK_ID_VI;
video1_rtspSrcChn.s32ChnId = 1;
MPP_CHN_S video1_rtspDestChn;
video1_rtspDestChn.enModId = RK_ID_VENC;
video1_rtspDestChn.s32ChnId = 1;
ret = RK_MPI_SYS_Bind(&video1_rtspSrcChn, &video1_rtspDestChn);
if (ret) {
printf("ERROR: Bind VI[%d] and VENC[%d] error! ret=%d\n",video1_rtspSrcChn.s32ChnId,video1_rtspDestChn.s32ChnId,ret);
return 0;
}
MPP_CHN_S video2_rtspSrcChn;
video2_rtspSrcChn.enModId = RK_ID_VI;
video2_rtspSrcChn.s32ChnId = 2;
MPP_CHN_S video2_rtspDestChn;
video2_rtspDestChn.enModId = RK_ID_VENC;
video2_rtspDestChn.s32ChnId = 2;
ret = RK_MPI_SYS_Bind(&video2_rtspSrcChn, &video2_rtspDestChn);
if (ret) {
printf("ERROR: Bind VI[%d] and VENC[%d] error! ret=%d\n",video2_rtspSrcChn.s32ChnId,video2_rtspDestChn.s32ChnId,ret);
return 0;
}
MPP_CHN_S video3_rtspSrcChn;
video3_rtspSrcChn.enModId = RK_ID_VI;
video3_rtspSrcChn.s32ChnId = 3;
MPP_CHN_S video3_rtspDestChn;
video3_rtspDestChn.enModId = RK_ID_VENC;
video3_rtspDestChn.s32ChnId = 3;
ret = RK_MPI_SYS_Bind(&video3_rtspSrcChn, &video3_rtspDestChn);
if (ret) {
printf("ERROR: Bind VI[%d] and VENC[%d] error! ret=%d\n",video3_rtspSrcChn.s32ChnId,video3_rtspDestChn.s32ChnId,ret);
return 0;
}
MPP_CHN_S video4_rtspSrcChn;
video4_rtspSrcChn.enModId = RK_ID_VI;
video4_rtspSrcChn.s32ChnId = 4;
MPP_CHN_S video4_rtspDestChn;
video4_rtspDestChn.enModId = RK_ID_VENC;
video4_rtspDestChn.s32ChnId = 4;
ret = RK_MPI_SYS_Bind(&video4_rtspSrcChn, &video4_rtspDestChn);
if (ret) {
printf("ERROR: Bind VI[%d] and VENC[%d] error! ret=%d\n",video4_rtspSrcChn.s32ChnId,video4_rtspDestChn.s32ChnId,ret);
return 0;
}
//---------------start pthread----------------------
pthread_t th1,th2, th3 ,th4;
int chn = 1;
pthread_create(&th1, NULL, Video1GetVencBuffer, (void *)chn);
usleep(1000); // wait for th1 ready.
ret = RK_MPI_VI_StartStream(1, 1);
if (ret) {
printf("Start VI[1] failed! ret=%d\n", ret);
return -1;
}
chn = 2;
pthread_create(&th2, NULL, Video2GetVencBuffer, (void *)chn);
usleep(1000); // wait for th1 ready.
ret = RK_MPI_VI_StartStream(2, 2);
if (ret) {
printf("Start VI[2] failed! ret=%d\n", ret);
return -1;
}
chn = 3;
pthread_create(&th3, NULL, Video3GetVencBuffer, (void *)chn);
ret = RK_MPI_VI_StartStream(3, 3);
if (ret) {
printf("Start VI[3] failed! ret=%d\n", ret);
return -1;
}
chn = 4;
pthread_create(&th4, NULL, Video4GetVencBuffer, (void *)chn);
ret = RK_MPI_VI_StartStream(4, 4);
if (ret) {
printf("Start VI[4] failed! ret=%d\n", ret);
return -1;
}
//=========================================
printf("%s initial finish\n", __func__);
signal(SIGINT, sigterm_handler);
while (!quit) {
usleep(500000);
}
printf("%s exit!\n", __func__);
// pthread_join(th1, NULL);
// pthread_join(th2, NULL);
// pthread_join(th3, NULL);
// pthread_join(th4, NULL);
// unbind vi venc
ret = RK_MPI_SYS_UnBind(&video1_rtspSrcChn, &video1_rtspDestChn);
if (ret) {
printf("ERROR: UNBind VI[1] and VENC[1] error! ret=%d\n",ret);
return 0;
}
ret = RK_MPI_SYS_UnBind(&video2_rtspSrcChn, &video2_rtspDestChn);
if (ret) {
printf("ERROR: UNBind VI[2] and VENC[2] error! ret=%d\n",ret);
return 0;
}
ret = RK_MPI_SYS_UnBind(&video3_rtspSrcChn, &video3_rtspDestChn);
if (ret) {
printf("ERROR: UNBind VI[3] and VENC[3] error! ret=%d\n",ret);
return 0;
}
ret = RK_MPI_SYS_UnBind(&video4_rtspSrcChn, &video4_rtspDestChn);
if (ret) {
printf("ERROR: UNBind VI[4] and VENC[4] error! ret=%d\n",ret);
return 0;
}
// destroy venc before vi
ret = RK_MPI_VENC_DestroyChn(4);
if (ret) {
printf("ERROR: Destroy VENC[4] error! ret=%d\n", ret);
return 0;
}
ret = RK_MPI_VENC_DestroyChn(3);
if (ret) {
printf("ERROR: Destroy VENC[3] error! ret=%d\n", ret);
return 0;
}
ret = RK_MPI_VENC_DestroyChn(2);
if (ret) {
printf("ERROR: Destroy VENC[2] error! ret=%d\n", ret);
return 0;
}
ret = RK_MPI_VENC_DestroyChn(1);
if (ret) {
printf("ERROR: Destroy VENC[1] error! ret=%d\n", ret);
return 0;
}
// destroy vp before vi
Vi_SrcChn.enModId = RK_ID_VI;
Vi_SrcChn.s32ChnId = 0;
Vp_DestChn.enModId = RK_ID_VP;
Vp_DestChn.s32ChnId = 0;
ret = RK_MPI_SYS_UnBind(&Vi_SrcChn, &Vp_DestChn);
if (ret) {
printf("UnBind vi[0] to vp[0] failed! ret=%d\n", ret);
return -1;
}
// destroy vi chn
RK_MPI_VI_DisableChn(2, 2);
RK_MPI_VI_DisableChn(3, 3);
RK_MPI_VI_DisableChn(4, 4);
RK_MPI_VI_DisableChn(5, 5);
RK_MPI_VP_DisableChn(0, 0);
RK_MPI_VI_DisableChn(s32CamId, 0);
if (iq_file_dir) {
#ifdef RKAIQ
SAMPLE_COMM_ISP_Stop(s32CamId);
#endif
}
return 0;
}