RV1126+FFMPEG推流项目(4)VENC模块视频编码流程

server/2025/1/16 17:46:56/

        在RV1126+FFMPEG推流项目(3)VI模块视频编码流程-CSDN博客,说了vi的编码流程,这篇说VENC的初始化(硬件编码)。

        上一篇提到了几个重要的数据结构体,这节说这个RV1126_VENC_CONFIG。继续认识一下。

/*** @brief RV1126_VENC_CONFIG 结构体定义* * 该结构体用于配置RV1126视频编码(VENC)的相关参数。* 包含视频编码通道的ID和属性配置。*/typedef struct
{unsigned int id;   //< 视频编码通道ID,用于标识不同的视频编码通道VENC_CHN_ATTR_S attr; //< 视频编码通道属性,包含通道的具体配置信息
} RV1126_VENC_CONFIG;

        之前提到RV1126_VENC_CONFIG 是自封装的一个数据结构,里面最重要的成员就是VENC_CHN_ATTR_S 数据结构。  

typedef struct rkVENC_CHN_ATTR_S {VENC_ATTR_S stVencAttr;    // 编码器基础属性结构体 VENC_RC_ATTR_S stRcAttr;   // 编码码率控制属性结构体 VENC_GOP_ATTR_S stGopAttr; // 编码器GOP属性结构体 
} VENC_CHN_ATTR_S;

        可以看到VENC_CHN_ATTR_S数据结构里面又套着三个数据结构体。下面通过编码来学习一下。


        VENC_ATTR_S(定义编码器属性结构体):来源于rk1126开发手册,看一下成员

        第一个参数编码器的类型,把视频和音频的都放在了这个枚举里面,要哪个就选择那个。

编码:

 //初始化Vemc编码模块RV1126_VENC_CONFIG rv_venc;memset(&rv_venc, 0, sizeof(rv_venc)); //先把空间初始化rv_venc.id = 0;//视频编码器属性rv_venc.attr. stVencAttr.enType = RK_CODEC_TYPE_H264; // 编码协议 设置成h264,需要265就写成265的rv_venc.attr.stVencAttr.imageType = IMAGE_TYPE_NV12;  // 图形格式 和rv_vi.attr.enPixFmt保持一样rv_venc.attr.stVencAttr.u32VirHeight =  1080; //图片高度和分辨率 vi的u32Height一样rv_venc.attr.stVencAttr.u32VirWidth = 1920; //图片高度和分辨率 vi的u32Width一样rv_venc.attr.stVencAttr.u32PicHeight = 1080;//图片高度和分辨率 vi的u32Height一样rv_venc.attr.stVencAttr.u32PicWidth = 1920;图片高度和分辨率 vi的u32Width一样rv_venc.attr.stVencAttr.u32Profile = 77; //  //后面调节画面质量更详细所说,传输的编码质量,66基本能看,77还不错,100最好,更具业务而定

 


         VENC_RC_ATTR_S(定义编码通道码率控制器属性):

 

      这里有一个非常重要的问题,你要是选着了264的编码器,就像选择264的码率控制器,H264CBR和 H264VBR和H264AVBR都可以,就是不能用265的,如果要用265码率控制器就要用265的编码器。

编码: 

 

//初始化所有的rkmedia
int init_rkmedia_module_function()
{int ret;rkmedia_function_init(); //初始化rkmedia功能RV1126_VI_CONFIG rv_vi;memset(&rv_vi, 0, sizeof(rv_vi));//配置rv_virv_vi.id = 0; //视频通道IDrv_vi.attr.pcVideoNode = COMS_DEVICE_NAME; //video视频节点路径/*VI捕获视频缓冲区计数,默认是3比如说vi和摄像头直接基础没有缓存区,vi模块如果数度跟不上会造成数据的丢失所以加上缓存区的,就可以减轻vi模块的压力,也是类似与一个生产着和消费着模型,主要是摄像头每时每刻都在采集数据不会停的所以加上缓存去,就可以大大保存数据的完整性。至于为啥3,这是工程师的经验*/rv_vi.attr.u32BufCnt = 3; rv_vi.attr.u32Width = 1920;//视频输入的宽度,一般和CMOS摄像头或者外设的宽度一致rv_vi.attr.u32Height = 1080;视频输入的高度,一般和CMOS摄像头或者外设的高度一致rv_vi.attr.enPixFmt = IMAGE_TYPE_NV12; // 图形格式 和vi_chn_attr.enPixFmt保持一样/***  VI_CHN_BUF_TYPE_MMAP和VI_CHN_BUF_TYPE_DMA*  VI_CHN_BUF_TYPE_DMA:vi模块直接和内存打交道,优点:速度快,缺点:如果硬件差的,可能会造成发热,频繁操作加快硬件损坏* I_CHN_BUF_TYPE_MMAP:中间有一个虚拟内存,vi和内存不直接接触,优点:硬件使用时间会长,缺点:有一点点延迟,但是不影响*/rv_vi.attr.enBufType = VI_CHN_BUF_TYPE_MMAP; //视频输入的图像格式,默认是NV12(IMAGE_TYPE_NV12)rv_vi.attr.enWorkMode = VI_WORK_MODE_NORMAL; //VI的工作模式,默认是NORMAL(VI_WORK_MODE_NORMAL)ret = rkmedia_vi_init(&rv_vi); //初始化rv_viif(ret != 0){printf("vi初始化失败\n");}else{printf("vi 初始化成功\n");/*** 设置容器的目的是为了后面开发,可以轻易拿到 vi的id,直接从容器里面拿*/RV1126_VI_CONTAINER vi_container; //创建出容器vi_container.id = 0; //所有vi_id的索引vi_container.vi_id = rv_vi.id; //id,储存到里面去set_vi_container(0, & vi_container); //把vi_id设置到容器里面}//配置Vemc编码模块RV1126_VENC_CONFIG rv_venc;memset(&rv_venc, 0, sizeof(rv_venc)); //先把空间初始化rv_venc.id = 0; //一般都是从0开始的通道号//视频编码器属性rv_venc.attr. stVencAttr.enType = RK_CODEC_TYPE_H264; // 编码协议 设置成h264,需要265就写成265的rv_venc.attr.stVencAttr.imageType = IMAGE_TYPE_NV12;  // 图形格式 和rv_vi.attr.enPixFmt保持一样rv_venc.attr.stVencAttr.u32VirHeight =  1080; //图片高度和分辨率 vi的u32Height一样rv_venc.attr.stVencAttr.u32VirWidth = 1920; //图片高度和分辨率 vi的u32Width一样rv_venc.attr.stVencAttr.u32PicHeight = 1080;//图片高度和分辨率 vi的u32Height一样rv_venc.attr.stVencAttr.u32PicWidth = 1920;图片高度和分辨率 vi的u32Width一样rv_venc.attr.stVencAttr.u32Profile = 66; //  //后面调节画面质量更详细所说,传输的编码质量,66基本能看,77还不错,100最好,更具业务而定/*** 视频码率控制属性有一个细节,选择264的编码器,就要选择264的率控制* 不可以选择264的编码器,就要选择265的率控制*/rv_venc.attr.stRcAttr.enRcMode =  VENC_RC_MODE_H264CBR; //编码器码率控制模式rv_venc.attr.stRcAttr.stH264Cbr.u32Gop = 30;//目前是30,每30帧插入一个帧GOPSIZE:关键帧间隔,目前我随意的,根据情况,值大需要的解码时间就,值小就要更更多的带宽rv_venc.attr.stRcAttr.stH264Cbr.u32SrcFrameRateDen = 1;//源帧率分子rv_venc.attr.stRcAttr.stH264Cbr.u32SrcFrameRateNum = 25;   // 源帧率分母rv_venc.attr.stRcAttr.stH264Cbr.fr32DstFrameRateNum = 1; // 目标帧率分子rv_venc.attr.stRcAttr.stH264Cbr.fr32DstFrameRateDen = 25;// 目标帧率分母rv_venc.attr.stRcAttr.stH264Cbr.u32BitRate = 1920 * 1080 * 3;//码率 每一个像素都是3中颜色组成//gop属性器stGopAttr查了很多资料,可以不配置ret = rkmedia_venc_init(&rv_venc); //初始化Vemc编码模块if(ret != 0){printf("venc,配置失败\n");}else{//成功了,//把可以轻易拿到 enc的id,保存到容器里面,直接从容器里面拿RV1126_VENC_CONTAINER venc_container;venc_container.id = 0;//所有venc_id的索引venc_container.venc_id = rv_venc.id;set_venc_container(0, &venc_container);//设置进去}
}


http://www.ppmy.cn/server/158874.html

相关文章

Opencv之模板匹配可视化

模板匹配 目录 模板匹配1 概念函数理解1.1 概念1.2 步骤1.3 函数 2 实际测试2.1 图片数据2.2 代码测试 1 概念函数理解 1.1 概念 模板匹配是一种在较大图像中寻找与给定模板图像最相似区域的技术。它是图像处理和计算机视觉中的一个基本任务&#xff0c;广泛应用于各种领域&am…

docker-compose和docker-harbor

docker-compose 自动编排工具&#xff0c;可根据dockerfile自动化部署docker容器 yaml文件格式&#xff0c;注意缩进 docker-harbor 私有仓库 公有云------阿里云&#xff0c;腾讯云 私有云------docker仓库 仓库--------保存镜像的地址 Harbor是vmware公司做的docker仓库的…

ChatGPT正在朝着全面个人助手迈出重要一步,推出了一个名为“Tasks”的新功能

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

55_OpenResty开发入门

Nginx编程需要用到Lua语言,因此我们必须先学习Lua的基本语法。Nginx本身也是C语言开发,因此也允许基于Lua做拓展。多级缓存的实现离不开Nginx编程,而Nginx编程又离不开OpenResty。 1.OpenResty概述 OpenResty是一款基于NGINX和LuaJIT的Web平台。通过Lua扩展NGINX实现的可伸…

java fastjson2将 map、实体类、list等 类型转换为JSON介绍

Fastjson2 提供了强大的类型转换功能&#xff0c;可以方便地将 JSON 字符串解析为 Java 对象、集合类型&#xff0c;或者其他自定义类型。这些功能使得 Fastjson2 在 JSON 数据的处理上更为灵活和高效。下面详细介绍 Fastjson2 的类型转换方法和相关用法。 1. 基本的类型转换 …

Spring Boot中的配置文件有哪些类型

在 Spring Boot 中&#xff0c;配置文件用于管理应用程序的设置和参数&#xff0c;通常存放在项目的 src/main/resources 目录下。Spring Boot 支持多种类型的配置文件&#xff0c;并通过这些文件来控制应用的行为和环境配置。 1. application.properties application.proper…

HTTP 缓存机制详解

一、引言 在当今数字化时代&#xff0c;网络应用的性能直接关系到用户体验。想象一下&#xff0c;当你在浏览网页时&#xff0c;每一次点击都需要漫长的等待来加载新内容&#xff0c;那该是多么糟糕的体验。而 HTTP 缓存机制就像是一位神奇的加速助手&#xff0c;能够显著提升…

Python对接GitHub:详细操作指南

在现代软件开发中,GitHub已经成为不可或缺的代码托管和版本控制平台。作为开发者,能够通过编程方式与GitHub交互可以大大提高工作效率。本文将详细介绍如何使用Python对接GitHub,实现仓库管理、文件操作、Issue处理、Pull Request管理以及Tag操作等功能。 © ivwdcwso (ID:…