前言:RV1126进行CMOS摄像头采集,并进行VENC的视频编码处理,最终获取到H264码流。
一.RV1126 VI模块采集并进行VENC编码的流程
RV1126多线程采集VI模块编码VENC并保存到文件,一般分为四个步骤:分别是初始化VI模块、初始化VENC模块、绑定VI和VENC模块、多线程获取每一帧H264码流数据
1.1. 初始化VI模块:
VI模块的初始化实际上就是对VI_CHN_ATTR_S的参数进行设置、然后调用RK_MPI_VI_SetChnAttr设置VI模块并使能RK_MPI_VI_EnableChn,伪代码如下:
VI_CHN_ATTR_S vi_chn_attr;//(这里是设置VI的属性)
ret = RK_MPI_VI_SetChnAttr(CAMERA_ID, 0, &vi_chn_attr);
ret |= RK_MPI_VI_EnableChn(CAMERA_ID, 0);
1.2.初始化VENC模块:
VENC模块的初始化实际上就是对VENC_CHN_ATTR_S的参数进行设置、然后调用RK_MPI_VENC_CreateChn创建编码器,伪代码如下:
VENC_CHN_ATTR_S venc_chn_attr;
venc_chn_attr.stVencAttr.enType = RK_CODEC_TYPE_H264;//(这里是设置VENC的属性)
ret = RK_MPI_VENC_CreateChn(0, &venc_chn_attr);
1.3.绑定VI节点和VENC节点:
绑定VI节点和VENC节点,使其两个模块能够关联起来,使用的API是RK_MPI_SYS_Bind。关于这个API的定义,之前说过了,这里不在阐述。伪代码如下:
MPP_CHN_S vi_chn_s;
vi_chn_s.enModId = RK_ID_VI;
vi_chn_s.s32ChnId = 0;
MPP_CHN_S venc_chn_s;
venc_chn_s.enModId = RK_ID_VENC;
venc_chn_s.s32ChnId = 0;
ret = RK_MPI_SYS_Bind(&vi_chn_s, &venc_chn_s);
1.4.开启多线程采集VENC的数据
开启一个线程去采集每一帧VENC模块的数据,使用的API是RK_MPI_SYS_GetMediaBuffer, 模块ID是RK_ID_VENC,通道号ID是VENC创建的ID号。这个API的具体作用已经在之前的获取VI数据的课程里面已经讲解过,我们直接上伪代码:
while(1)
{
.........................
mb = RK_MPI_SYS_GetMediaBuffer(RK_ID_VENC, s32_chn_id, -1);
fwrite(RK_MPI_MB_GetPtr(mb), RK_MPI_MB_GetSize(mb), 1, h264_file);
.......................
}
接下来看完整代码演示:
#include <assert.h>
#include <fcntl.h>
#include <getopt.h>
#include <pthread.h>
#include <signal.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
// #include "common/sample_common.h"
#include "rkmedia_api.h"
#define CAMERA_PATH "rkispp_scale0"
#define CAMERA_ID 0
#define CAMERA_CHN 0
#define VENC_CHN 0
void * get_h264_venc_thread(void * args)
{
pthread_detach(pthread_self());
FILE * h264_file = fopen("test_camera.h264", "w+");
MEDIA_BUFFER mb;
while (1)
{
mb = RK_MPI_SYS_GetMediaBuffer(RK_ID_VENC, VENC_CHN, -1);
if(!mb)
{
printf("Get Venc Mb Break.....\n");
break;
}
printf("Get H264 One Frame.......\n");
fwrite(RK_MPI_MB_GetPtr(mb),RK_MPI_MB_GetSize(mb),1, h264_file);
RK_MPI_MB_ReleaseBuffer(mb);
}
return NULL;
}
int main(int argc, char *argv[])
{
int ret;
VI_CHN_ATTR_S vi_chn_attr;
vi_chn_attr.pcVideoNode = CAMERA_PATH; //Path
vi_chn_attr.u32Width = 1920; //Width
vi_chn_attr.u32Height = 1080; //Height
vi_chn_attr.enPixFmt = IMAGE_TYPE_NV12; //ImageType
vi_chn_attr.enBufType = VI_CHN_BUF_TYPE_MMAP;//BufType
vi_chn_attr.u32BufCnt = 3; //Cnt
vi_chn_attr.enWorkMode = VI_WORK_MODE_NORMAL; //Mode
ret = RK_MPI_VI_SetChnAttr(CAMERA_ID, CAMERA_CHN, &vi_chn_attr);
if(ret)
{
printf("Vi Set Attr Failed.....\n");
return 0;
}
else
{
printf("Vi Set Attr Success.....\n");
}
ret = RK_MPI_VI_EnableChn(CAMERA_ID, CAMERA_CHN);
if(ret)
{
printf("Vi Enable Attr Failed.....\n");
return 0;
}
else
{
printf("Vi Enable Attr Success.....\n");
}
VENC_CHN_ATTR_S venc_chn_attr;
//****** VENC Attr Set ************************//
venc_chn_attr.stVencAttr.enType = RK_CODEC_TYPE_H264;
venc_chn_attr.stVencAttr.u32PicWidth = 1920;
venc_chn_attr.stVencAttr.u32PicHeight = 1080;
venc_chn_attr.stVencAttr.u32VirWidth = 1920;
venc_chn_attr.stVencAttr.u32VirHeight = 1080;
venc_chn_attr.stVencAttr.u32Profile = 66;
venc_chn_attr.stVencAttr.imageType = IMAGE_TYPE_NV12;
venc_chn_attr.stVencAttr.enRotation = VENC_ROTATION_0;
//********* VENC RCMODE Set *******************//
venc_chn_attr.stRcAttr.enRcMode = VENC_RC_MODE_H264CBR;
venc_chn_attr.stRcAttr.stH264Cbr.u32Gop = 25;
//25/1 NUM/DEN == FrameRate
venc_chn_attr.stRcAttr.stH264Cbr.u32SrcFrameRateDen = 1; //
venc_chn_attr.stRcAttr.stH264Cbr.u32SrcFrameRateNum = 25;
venc_chn_attr.stRcAttr.stH264Cbr.fr32DstFrameRateDen = 1;
venc_chn_attr.stRcAttr.stH264Cbr.fr32DstFrameRateNum = 25;
venc_chn_attr.stRcAttr.stH264Cbr.u32BitRate = 8388608; //1M
ret = RK_MPI_VENC_CreateChn(VENC_CHN, &venc_chn_attr);
if(ret)
{
printf("Create Venc Failed .....\n");
return 0;
}
else
{
printf("Create Venc Success .....\n");
}
MPP_CHN_S vi_chn_s;
vi_chn_s.enModId = RK_ID_VI;
vi_chn_s.s32ChnId = CAMERA_CHN;
MPP_CHN_S venc_chn_s;
venc_chn_s.enModId = RK_ID_VENC;
venc_chn_s.s32ChnId = VENC_CHN;
ret = RK_MPI_SYS_Bind(&vi_chn_s, &venc_chn_s);
if(ret)
{
printf("RK_MPI_SYS_Bind Failed .....\n");
return 0;
}
else
{
printf("RK_MPI_SYS_Bind Success .....\n");
}
pthread_t pid;
pthread_create(&pid, NULL, get_h264_venc_thread, NULL);
while (1)
{
sleep(1);
}
RK_MPI_VI_DisableChn(CAMERA_ID, CAMERA_CHN);
RK_MPI_VENC_DestroyChn(VENC_CHN);
RK_MPI_SYS_UnBind(&vi_chn_s, &venc_chn_s);
return 0;
}