ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

音视频开发项目-3RKMedia 三大模块初始化

音视频开发项目-3RKMedia 三大模块初始化 3. RKMedia 三大模块初始化VI / VENC / RGA这一篇讲rkmedia_module_function.cpp里的init_rkmedia_module_function()。这个函数是整个硬件侧的配置中心分辨率、帧率、码率、图像格式所有关键参数集中在这一个文件——集中配置是我刻意做的设计调参不用满项目找。一、先看全貌这个函数按顺序干五件事1. RK_MPI_SYS_Init() 系统级初始化 2. rkmedia_vi_init() 配置 VI视频输入 3. rkmedia_venc_init() 配置 VENC 01080P 高清编码 4. RGA 通道创建 配置 RGA硬件缩放器 5. rkmedia_venc_init() 配置 VENC 1720P 低清编码对应的数据通路就是开篇那张图VI 出 1080P一路直接进 VENC 0 编码另一路进 RGA 缩成 720P 再进 VENC 1。为什么把参数配置和 API 调用拆成两层rkmedia_module_function.cpp只填业务参数rkmedia_module.cpp只封装 RK_MPI 调用。以后换参数改前者换 SDK 版本改后者互不纠缠。二、VI视频输入RV1126_VI_CONFIG rkmedia_vi_config;memset(rkmedia_vi_config,0,sizeof(rkmedia_vi_config));rkmedia_vi_config.id0;rkmedia_vi_config.attr.pcVideoNodeCMOS_DEVICE_NAME;// rkispp_scale0rkmedia_vi_config.attr.u32BufCnt3;// 缓冲区个数rkmedia_vi_config.attr.u32Width1920;rkmedia_vi_config.attr.u32Height1080;rkmedia_vi_config.attr.enPixFmtIMAGE_TYPE_NV12;rkmedia_vi_config.attr.enBufTypeVI_CHN_BUF_TYPE_MMAP;rkmedia_vi_config.attr.enWorkModeVI_WORK_MODE_NORMAL;intretrkmedia_vi_init(rkmedia_vi_config);参数逐个说设计考量pcVideoNode rkispp_scale0V4L2 视频设备节点。RV1126 的 ISP 在/dev/下暴露多个节点scale0、scale1、scale2…不同节点出不同分辨率的图。scale0 是全尺寸的所以拿它当源——低清路反正有 RGA 在后面缩源头必须给最好的。节点名做成宏放在rkmedia_config_public.h#define CMOS_DEVICE_NAME rkispp_scale0换板子只改一处。u32BufCnt 3VI 驱动准备 3 个缓冲区轮转——一个在采集、一个在处理、一个排队采集和处理永不互相等待。3 是经验下限再少容易在偶发抖动时丢帧。IMAGE_TYPE_NV12YUV420SP 格式。RK 平台的 RGA 和硬件编码器都原生吃 NV12所以从采集到缩放到编码全程 NV12中间零格式转换、零 CPU 开销——这是全链路设计里最省心的一环。先 memset 再填结构体清零后只覆盖关心的字段其余字段天然是安全默认值不靠栈上的运气。底层封装在rkmedia_module.cpp就两步retRK_MPI_VI_SetChnAttr(CAMERA_ID,id,vi_attr);// 设属性ret|RK_MPI_VI_EnableChn(CAMERA_ID,id);// 使能通道RKMedia 的 API 命名规律就是这个RK_MPI_模块_动作。Set 完属性必须 Enable 通道才真正工作VENC 用的则是 Create创建即工作。成功之后还有一步RV1126_VI_CONTAINTER vi_container;vi_container.id0;vi_container.vi_idrkmedia_vi_config.id;set_vi_container(0,vi_container);// 存进容器VI 通道号被登记到一个全局容器里后面绑定时从容器里取。为什么多这一层把通道号的管理和业务流程分开业务代码不写死通道号只说我要 0 号业务实际通道号由容器解析。现在单任务场景下通道号恰好是 0 和 1但等将来多 assignment 并存、通道号动态分配时业务代码一行都不用改。容器实现在rkmedia_container.cpp带互斥锁的全局数组线程安全。三、VENC 01080P 高清编码通道RV1126_VENC_CONFIG rkmedia_venc_config{0};rkmedia_venc_config.id0;rkmedia_venc_config.attr.stVencAttr.enTypeRK_CODEC_TYPE_H264;rkmedia_venc_config.attr.stVencAttr.imageTypeIMAGE_TYPE_NV12;rkmedia_venc_config.attr.stVencAttr.u32PicWidth1920;rkmedia_venc_config.attr.stVencAttr.u32PicHeight1080;rkmedia_venc_config.attr.stVencAttr.u32VirWidth1920;rkmedia_venc_config.attr.stVencAttr.u32VirHeight1080;rkmedia_venc_config.attr.stVencAttr.u32Profile66;几个值得说的设计决策u32VirWidth / u32VirHeight虚宽高虚拟宽高是一行实际占的字节数物理宽高是画面有效区域。带对齐要求的硬件上两者可能不等某些平台要求 16/32 对齐画面 1080 高要填 1088。RV1126 上两者一致但我还是显式把两个字段都填上——不留给编译器猜的余地以后排查对齐问题也一目了然。u32Profile 66H264 的 profile 编号66 Baseline。直播场景我选 Baseline 是经过权衡的压缩率让位于解码兼容性和低延迟——Baseline 没有帧间双向预测低端手机、老款电视盒子都能流畅解解码缓冲也小。接着是码率控制rkmedia_venc_config.attr.stRcAttr.enRcModeVENC_RC_MODE_H264CBR;rkmedia_venc_config.attr.stRcAttr.stH264Cbr.u32Gop25;rkmedia_venc_config.attr.stRcAttr.stH264Cbr.u32BitRate1920*1080*3;rkmedia_venc_config.attr.stRcAttr.stH264Cbr.fr32DstFrameRateDen1;rkmedia_venc_config.attr.stRcAttr.stH264Cbr.fr32DstFrameRateNum25;rkmedia_venc_config.attr.stRcAttr.stH264Cbr.u32SrcFrameRateDen1;rkmedia_venc_config.attr.stRcAttr.stH264Cbr.u32SrcFrameRateNum25;整理成表参数值设计考量enRcModeH264CBR恒定码率。直播的标配带宽可预测瞬时波动小服务端好做分发u32Gop25关键帧间隔 25 帧 每 1 秒一个 IDR25fps 下。GOP fps 是我定的一般原则u32BitRate1920×1080×3 ≈ 6.2 Mbps码率公式宽×高×31080P 直播 4~8Mbps 区间的稳妥取值Src/DstFrameRate25/1源帧率和目标帧率一致不做抽帧/倍帧保持节奏纯净为什么 GOP 25一秒一个关键帧观众点开直播解码器必须从一个 IDR 帧起步——最坏情况下要等一个 GOP 的时长才能出画面。GOP 1 秒意味着最多等 1 秒这是直播首屏延迟和带宽开销的甜点再小关键帧太密码率白白上涨再大观众进直播间就是黑屏干等。帧率字段的填法提醒一下自己Den 位置填 1、Num 位置填 25和直觉相反照 SDK 注释来。底层就一个调用retRK_MPI_VENC_CreateChn(rv1126_venc_config-id,venc_chn_attr);四、RGA硬件缩放器低清路的关键RGA 这段是输入 1080P、输出 720P 的配置RGA_ATTR_S rga_info;/* 输入跟 VI 出图一致 */rga_info.stImgIn.u32Width1920;rga_info.stImgIn.u32Height1080;rga_info.stImgIn.imgTypeIMAGE_TYPE_NV12;/* 输出720P */rga_info.stImgOut.u32Width1280;rga_info.stImgOut.u32Height720;rga_info.stImgOut.imgTypeIMAGE_TYPE_NV12;/* 公共参数 */rga_info.u16BufPoolCnt3;rga_info.u16Rotaion0;rga_info.enFlipRGA_FLIP_H;// 水平镜像rga_info.bEnBufPoolRK_TRUE;retRK_MPI_RGA_CreateChn(0,rga_info);两个设计决策缩放交给 RGA 而不是 CPU。RGA 是独立硬件单元缩放、旋转、镜像、格式转换都不占 CPU。1080P→720P 每秒 25 帧 300 万像素的活软件做 CPU 直接吃穿硬件做零成本——能用专用硬件的地方绝不用通用算力这是嵌入式设计的第一原则。enFlip RGA_FLIP_H水平镜像。摄像头安装朝向决定了出图是镜像的硬件开关顺手打开成本为零。顺带一提u16Rotaion的拼写是 Rockchip 头文件就这么写的少个 t用 API 时照抄别好心纠正。五、VENC 1720P 低清编码通道和 VENC 0 结构一样参数按低清定位调整参数VENC 0高清VENC 1低清考量分辨率1920×10801280×720两档清晰度码率≈ 6.2Mbps≈ 2.8Mbps低清路码率预算本来就小GOP2530低清路码率预算紧GOP 略拉大省关键帧开销低清观众对首屏延迟相对不敏感多等 0.2 秒换带宽通道号 id01—两路参数的差异不是随手填的码率、GOP 都跟着这一路流的目标观众走。高清路给追求体验的观众GOP 紧凑、码率给足低清路给弱网观众一切从省。六、这一篇的设计要点参数配置与 API 封装分层集中配置便于调参NV12 全链路贯通采集、缩放、编码一个格式走到底零转换编码参数的经验值1080P 直播 ≈ 宽×高×3 的码率、GOP fps1 秒一个关键帧、Baseline profile容器层解耦通道号管理为多任务预留能用硬件的绝不用 CPURGA 缩放、VENC 编码下一篇模块都建好了怎么把它们接起来RK_MPI_SYS_Bind和五个工作线程的诞生。本篇对应源码rkmedia_module_function.cpp、rkmedia_module.cpp、rkmedia_config_public.h
返回列表