项目1:RV1126的高分辨率VENC编码模块的设置
本文介绍了高分辨率(1920*1080)VENC编码模块的配置实现。主要内容包括:1)通过RV1126_VENC_CONFIG结构体设置编码参数,包括H264编码类型、1920x1080分辨率、Baseline编码等级、CBR码率控制等关键参数;2)封装rkmedia_venc_init函数初始化VENC模块;3)将VENC模块ID存入venc_containers数组进行统一管理。文章详细说明了
一.本章节介绍

本章节主要是介绍视觉项目的高分辨率(1920 * 1080)的VENC编码模块的讲解,在这个项目中VENC编码模块参数的设置是至关重要的,它可以对VI数据进行硬件编码让其可以进行高分辨率编码码流的推流(如上图)。高分辨率VENC模块的配置在源文件rkmedia_module_function.cpp里面。
二.高分辨率VENC的思维导图

上面思维导图主要是描述VENC模块设置的大致流程,首先对RV1126_VENC_CONFIG结构体进行参数设置,然后调用rkmedia_venc_init对VENC模块进行设置,设置完成后再把VENC的模块ID放到VENC管理数组里面(venc_containers)。
三.高分辨率VENC模块设置的代码
RV1126_VENC_CONFIG rkmedia_venc_config = {0};
memset(&rkmedia_venc_config, 0, sizeof(rkmedia_venc_config));
rkmedia_venc_config.id = 0;
rkmedia_venc_config.attr.stVencAttr.enType = RK_CODEC_TYPE_H264; // 编码器协议类型
rkmedia_venc_config.attr.stVencAttr.imageType = IMAGE_TYPE_NV12; // 输入图像类型
rkmedia_venc_config.attr.stVencAttr.u32PicWidth = 1920; // 编码图像宽度
rkmedia_venc_config.attr.stVencAttr.u32PicHeight = 1080; // 编码图像高度
rkmedia_venc_config.attr.stVencAttr.u32VirWidth = 1920; // 编码图像虚宽度,一般来说u32VirWidth和u32PicWidth是一致的
rkmedia_venc_config.attr.stVencAttr.u32VirHeight = 1080; // 编码图像虚高度,一般来说u32VirHeight和u32PicHeight是一致的
rkmedia_venc_config.attr.stVencAttr.u32Profile = 66; // 编码等级H.264: 66: Baseline; 77:Main Profile; 100:High Profile; H.265: default:Main; Jpege/MJpege: default:Baseline(编码等级的作用主要是改变画面质量,66的画面质量最差利于网络传输,100的质量最好)
rkmedia_venc_config.attr.stRcAttr.enRcMode = VENC_RC_MODE_H264CBR; // 编码器码率控制模式
rkmedia_venc_config.attr.stRcAttr.stH264Cbr.u32Gop = 25; // GOPSIZE:关键帧间隔
rkmedia_venc_config.attr.stRcAttr.stH264Cbr.u32BitRate = 1920 * 1080 * 3; // 码率
rkmedia_venc_config.attr.stRcAttr.stH264Cbr.fr32DstFrameRateDen = 1; // 目的帧率分子:填的是1固定
rkmedia_venc_config.attr.stRcAttr.stH264Cbr.fr32DstFrameRateNum = 25; // 目的帧率分母:填的是25固定
rkmedia_venc_config.attr.stRcAttr.stH264Cbr.u32SrcFrameRateDen = 1; // 源头帧率分子:填的是1固定
rkmedia_venc_config.attr.stRcAttr.stH264Cbr.u32SrcFrameRateNum = 25; // 源头帧率分母:填的是25固定
上述的参数是高分辨率VENC编码器的参数设置,我们来看看每个参数设置的意义
stVencAttr.enType:编码器协议类型,这里填写的是H264编码器类型,RK_CODEC_TYPE_H264
stVencAttr.imageType:编码器图像类型,这里写的类型要和图像输入类型保持一致,所以填写IMAGE_TYPE_NV12
stVencAttr.enType.u32PicWidth:编码图像的分辨率宽度,这里是高分辨率所以写1920
stVencAttr.enType.u32PicHeight:编码图像的分辨率高度,这里是高分辨率所以写1080
stVencAttr.enType.u32VirWidth:编码图像的分辨率虚宽,这里写的跟u32PicWidth保持一致,所以填写1920
stVencAttr.enType.u32VirHeight:编码图像的分辨率虚高,这里写的跟u32PicHeight保持一致,所以填写1080
stVencAttr.enType.u32Profile:编码等级,这里填写66,指的是Baseline,这种模式更加适用于视频传输
stRcAttr.enRcMode:编码器码率控制类型,这里填写的是H264 CBR码率控制模式,VENC_RC_MODE_H264CBR,下面码率控制的结构体都是以stH264Cbr作为设置
stRcAttr.stH264Cbr.u32Gop:H264的CBR码率控制GOP设置,这里GOP的设置是25
stRcAttr.stH264Cbr.u32BitRate:H264的CBR码率控制码率大小的设置,这里是1920 * 1080 * 3 = 6220800比特率/s ~= 700KB/s
stRcAttr.stH264Cbr.u32SrcFrameRateDen:H264的CBR码率控制控制结构体的源帧率分母的设置,这里写的是25
stRcAttr.stH264Cbr.u32SrcFrameRateNum:H264的CBR码率控制控制结构体的源帧率分子的设置,这里写的是1
stRcAttr.stH264Cbr.u32DstFrameRateDen:H264的CBR码率控制控制结构体的目标帧率分母的设置,这里写的是25
stRcAttr.stH264Cbr.u32DstFrameRateNum:H264的CBR码率控制控制结构体的目标帧率分子的设置,这里写的是1
(备注:通常情况下源帧率的分子、分母和目标帧率的分子、分母数值保持一致)
设置完上述VENC编码参数后,我们就要调用自己封装的函数rkmedia_venc_init函数,对VENC模块进行设置,具体的实现如下:
//VENC的初始化
int rkmedia_venc_init(RV1126_VENC_CONFIG *rv1126_venc_config)
{
int ret;
VENC_CHN_ATTR_S venc_chn_attr = rv1126_venc_config->attr;
unsigned int venc_id = rv1126_venc_config->id;
ret = RK_MPI_VENC_CreateChn(rv1126_venc_config->id, &venc_chn_attr);
if (ret != 0)
{
printf("create rv1126_venc_module failed\n");
return -1;
}
else
{
printf("create rv1126_venc_module success\n");
}
return 0;
}
这个自定义函数还是非常简单的,就是把RK_MPI_VENC_CreateChn封装了一层,然后把RV1126_VENC_CONFIG的结构体指针传进去。
设置完VENC模块后,就要把VENC模块的ID号设置到VENC容器数组里面,高分辨率VENC的ID号是0,调用自己封装的函数是set_venc_container
ret = rkmedia_venc_init(&rkmedia_venc_config); // VENC模块的初始化
if (ret != 0)
{
printf("venc init error\n");
}
else
{
RV1126_VENC_CONTAINER venc_container;
venc_container.id = 0;
venc_container.venc_id = rkmedia_venc_config.id;
set_venc_container(0, &venc_container);
printf("venc init success\n");
}
set_venc_container具体的实现:
在这个自定义的函数里面,最主要是把VENC的ID号存放在VENC模块数组里面(venc_ontainers),具体结构如下图:
int set_venc_container(unsigned int index, RV1126_VENC_CONTAINER *venc_container)
{
pthread_mutex_lock(&all_containers_mutex);
all_containers.venc_containers[index] = *venc_container;
pthread_mutex_unlock(&all_containers_mutex);
return 0;
}
在这个自定义的函数里面,最主要是把VENC的ID号存放在VENC模块数组里面(venc_containers),具体结构如下图:
typedef struct
{
unsigned int container_id;
RV1126_VI_CONTAINTER vi_containers[ALL_CONTAINER_NUM];
RV1126_AI_CONTAINTER ai_containers[ALL_CONTAINER_NUM];
RV1126_VENC_CONTAINER venc_containers[ALL_CONTAINER_NUM];
RV1126_AENC_CONTAINER aenc_containers[ALL_CONTAINER_NUM];
}RV1126_ALL_CONTAINER;
关于RV1126_ALL_CONTAINER的作用已经在上一篇章讲解过了,这次VENC的ID号需要存放到venc_containers数组里面,这样更容易管理VENC模块号ID。
火山引擎开发者社区是火山引擎打造的AI技术生态平台,聚焦Agent与大模型开发,提供豆包系列模型(图像/视频/视觉)、智能分析与会话工具,并配套评测集、动手实验室及行业案例库。社区通过技术沙龙、挑战赛等活动促进开发者成长,新用户可领50万Tokens权益,助力构建智能应用。
更多推荐
所有评论(0)