一、rv1126开发之视频输入和视频编码

news2024/11/15 21:48:29

RV1126 H264/HEVC编码流程

一、RV1126编码的流程图:

在这里插入图片描述

二、每个代码模块详细讲解

2.1. VI模块的创建

在这里插入图片描述VI模块的初始化:关键在于VI_CHN_ATTR_S结构体,这个结构体是VI设置的结构体。这个结构体的成员变量包括:pcVideoNode(video节点路径)、u32BufCnt(VI捕获视频缓冲区计数)、u32Width(分辨率宽度)、u32Height(分辨率高度)、 enPixFmt(VI格式)、enBufType(映射类型默认是:MMAP)、enWorkMode(VI通道模式)等成员变量。设置完成之后,则使用RK_MPI_VI_SetChnAttr进行设置VI操作,设置完成之后使用RK_MPI_VI_EnableChn使能VI层。

2.2. VENC模块的初始化

在这里插入图片描述VENC的初始化:关键在于VENC_CHN_ATTR_S结构体,这个结构体是VENC设置的结构体。这个结构体包含以下成员变量:enType(编码类型)、enRcMode()、u32Gop(关键帧间隔)、u32Bitrate(编码码率)、u32SrcFrameRateDen(原始帧率分母)、u32SrcFrameRateNum(目标帧率分子)、 fr32DstFrameRateNum(目标帧率分母)、 fr32DstFrameRateDen(目标帧率分子)、 imageType(流格式)、u32PicWidth(分辨率长度)、u32PicHeight(分辨率高度)、u32VirWidth(分辨率虚长度)、u32VirHeight(分辨率虚高度)、u32Profile(编码等级)。
设置完上述成员变量后,则使用RK_MPI_VENC_CreateChn创建编码层。

2.3. 绑定VI和VENC模块

在这里插入图片描述设置完VI模块和VENC模块后,需要进行绑定VI和VENC才能够正常采集到编码数据。采集的时候用到的结构体·MPP_CHN_S,其中MPP_CHN_S的enModId是模块的ID、 s32ChnId是通道id。 这里分别创建两个MPP_CHN_S结构体,一个是VI的MPP_CHN_S,它的enModId选择的是RK_ID_VI,s32Id应该和VI创建的ID进行适配;另外一个则是VENC的MPP_CHN_S,它的enModId选择的是RK_ID_VENC,s32ChnId和VENC创建的Id对应。创建完两个MPP_CHN_S结构体后,利用RK_MPI_SYS_BIND把VI和VENC进行绑定。

2.4. 创建线程采集VENC数据

在这里插入图片描述在这里插入图片描述从collect_venc_thread线程主要作用是获取VENC编码的码流数据,并实时保存到H264文件。在这个线程里面,有几个重要的API需要讲解:RK_MPI_SYS_GetMediaBuffer的作用是获取对应通道的数据,这个API第一个参数是模块ID,第二个参数是通道ID,第三个参数阻塞时间这里默认是-1不阻塞。获取VENC通道的数据后,这其中RK_MPI_MB_GetPtr是获取VENC缓冲区数据,RK_MPI_MB_GetSize是获取VENC的缓冲区长度,并把缓冲区数据fwrite写到H264文件。

#include <stdio.h>
#include "rkmedia_config.h"

void * collect_venc_thread(void * args)
{
   pthread_detach(pthread_self());  //线程取消和主线程的绑定,当结束时自动销毁
   MEDIA_BUFFER mb;
   FILE * h264_file = fopen("./test_output.h264", "w+");

   while (1)
   {
       mb = RK_MPI_SYS_GetMediaBuffer(RK_ID_VENC, 0 , -1);   //从编码器中获取一帧数据放到缓冲区  参数(模块(venc),通道号,-1(非阻塞,>=0:阻塞等待的时间)),
       if(!mb)
       {
           printf("Get Venc Buffer Break....\n");
           break;
       }

       printf("mmmmmm\n");

       //这里的mb只是一个地址,也就是指针
       //从缓冲区读取数据RK_MPI_MB_GetPtr(mb),大小RK_MPI_MB_GetSize(mb)也就是一帧编码的大小
       fwrite(RK_MPI_MB_GetPtr(mb), RK_MPI_MB_GetSize(mb), 1, h264_file); 
   }
   return NULL;
}


int main()
{
    RK_U32 u32Width = 1920;
    RK_U32 u32Height = 1080;
    RK_CHAR *pDeviceName = "rkispp_scale0";  //最大宽度3264,可进行缩放1-8倍,这部分去看rv1126的手册中的VI视频节点部分
    RK_CHAR *pOutPath = NULL;
    RK_CHAR *pIqfilesPath = NULL;
    CODEC_TYPE_E enCodecType = RK_CODEC_TYPE_H264;  //编码类型
    RK_CHAR *pCodecName = "H264";
    RK_S32 s32CamId = 0;  //vi管道号,一般为0
    RK_U32 u32BufCnt = 3;

#if 0
    rk_aiq_working_mode_t hdr_mode = RK_AIQ_WORKING_MODE_NORMAL;
    SAMPLE_COMM_ISP_Init(hdr_mode, RK_FALSE);
    SAMPLE_COMM_ISP_Run();
    SAMPLE_COMM_ISP_SetFrameRate(30);
#endif

    int ret;
    RK_MPI_SYS_Init();
    VI_CHN_ATTR_S vi_chn_attr;
    vi_chn_attr.pcVideoNode = pDeviceName;  //设置 VI的视频节点,比如“/dev/video0”,这部分去看rv1126的手册中的VI视频节点部分
    vi_chn_attr.u32BufCnt = u32BufCnt;  //vi捕获视频缓冲区计数
    vi_chn_attr.u32Width = u32Width;    //分辨率设置
    vi_chn_attr.u32Height = u32Height;
    vi_chn_attr.enPixFmt = IMAGE_TYPE_NV12;     //视频的格式
    vi_chn_attr.enBufType = VI_CHN_BUF_TYPE_MMAP;     //映射的方式
    vi_chn_attr.enWorkMode = VI_WORK_MODE_NORMAL;
    //通道号这里应该设置为0
    ret = RK_MPI_VI_SetChnAttr(s32CamId, 1, &vi_chn_attr);  //设置vi设备属性,参数(vi管道号,vi通道号,vi通道属性结构体指针),管道号对应了sensor的个数
    ret |= RK_MPI_VI_EnableChn(s32CamId, 1);
    if (ret)
    {
        printf("ERROR: create VI[0] error! ret=%d\n", ret);
        return 0;
    }

    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; //设置编码器属性的编码类型为H264
    venc_chn_attr.stVencAttr.imageType = IMAGE_TYPE_NV12;  //输入图形类型
    //下面这部分是分辨率,设置为想要的分辨率即可 
    venc_chn_attr.stVencAttr.u32PicWidth = u32Width; 
    venc_chn_attr.stVencAttr.u32PicHeight = u32Height;
    venc_chn_attr.stVencAttr.u32VirWidth = u32Width;
    venc_chn_attr.stVencAttr.u32VirHeight = u32Height;
    venc_chn_attr.stVencAttr.u32Profile = 77; //编码等级,这块查看文档
    /*编码属性结构体之码率控制属性*/
    venc_chn_attr.stRcAttr.enRcMode = VENC_RC_MODE_H264CBR;  //编码协议类型,H264
    //H264编码通道Cbr模式属性,此外还有H265,Mjpeg的模式属性
    venc_chn_attr.stRcAttr.stH264Cbr.u32Gop = 30;   //GOP,I帧间隔        
    venc_chn_attr.stRcAttr.stH264Cbr.u32BitRate = u32Width * u32Height;   //平均比特率,取值[2000-98000000],比特率设置,单位bps
    // frame rate: in 30/1, out 30/1.  这样的设置实际输入帧率是30,输出帧率为30
    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;   //数据源帧率分子
    
    ret = RK_MPI_VENC_CreateChn(0, &venc_chn_attr);   //参数(通道号,视频编码属性结构体)
    if (ret)
    {
        printf("ERROR: create VENC[0] error! ret=%d\n", ret);
        return 0;
    }

    /* vi视频输入通道和venc视频编码通道绑定 */
    MPP_CHN_S stSrcChn;
    stSrcChn.enModId = RK_ID_VI;  //属性设置为vi
    stSrcChn.s32DevId = 0;  //vi设备号,其实就是上面的管道号
    stSrcChn.s32ChnId = 1;  //vi设备的通道号,与上面设置的属性对应
    
    MPP_CHN_S stDestChn;
    stDestChn.enModId = RK_ID_VENC;  //属性设置为venc
    stDestChn.s32DevId = 0;   // 视频编码设备号默认0
    stDestChn.s32ChnId = 0;     //视频编码通道
    ret = RK_MPI_SYS_Bind(&stSrcChn, &stDestChn);
    if (ret)
    {
        printf("ERROR: Bind VI[0] and VENC[0] error! ret=%d\n", ret);
        return 0;
    }

    pthread_t pid;
    ret = pthread_create(&pid, NULL, collect_venc_thread, NULL);
    if(ret != 0)
    {
        printf("Create Venc Thread Failed....\n");
    }

    while (1)
    {
       sleep(20);
    }
    

    return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1534742.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Java Web基础】一些网页设计基础(五)

文章目录 1. 图片在盒子内部垂直居中2. 底部设计&#xff0c;图片或子元素居中于父盒子&#xff08;水平、垂直&#xff09;&#xff0c;随着屏幕大小放大或缩小3. 使用thymeleaf的th:each会导致样式失效错乱问题 1. 图片在盒子内部垂直居中 用弹性盒子实现垂直居中及用css实现…

html5cssjs代码 035 课程表

html5&css&js代码 035 课程表 一、代码二、解释基本结构示例代码常用属性样式和装饰响应式表格辅助技术 一个具有亮蓝色背景的网页&#xff0c;其中包含一个样式化的表格用于展示一周课程安排。表格设计了交替行颜色、鼠标悬停效果以及亮色表头&#xff0c;并对单元格设…

使用Oxygen编辑器的项目来做团队协作

▲ 搜索“大龙谈智能内容”关注公众号▲ 扫码见我视频号上的视频 今天&#xff0c;分享一种在Oxygen中使用项目文件进行团队协作的高效方法。这种方法不仅能帮助我们轻松共享文件和文件夹&#xff0c;还能确保团队成员使用统一的项目级别选项和发布配置&#xff0c;从而提高工…

模板高级使用(非类型模板参数,特化,分离编译)

文章目录 模板没有实例化取内嵌类型报错问题非类型模板参数模板的特化函数模板的特化类模板的特化1.全特化2.偏特化 模板的分离编译 模板没有实例化取内嵌类型报错问题 首先在这里分享一个模板的常见报错问题。就是模板的在没有实例化的情况下去取模板类里面的内嵌类型这时候的…

【面试题】HashMap为什么可以插入null而Hashtable就不可以(源码分析)

首先hashmap可以插入null值&#xff0c;但是hashtable和hashcurrentHashmap是不支持的&#xff1b;这是因为在 hashmap对插入key为null进行了特殊处理&#xff0c;当插入的值为null的时候会将哈希值设置为0 但是hashtable会直接抛出异常&#xff1a; 并且hashmap是线程不…

2024全国水科技大会【发言单位】天健水务集团(杭州)有限公司

天健水务&#xff0c;始创于2003年&#xff0c;下属浙江天行健水务有限公司、杭州天勤水处理技术有限公司、杭州天行健新能源有限公司&#xff0c;是一家致力于现代化水处理设备与系统研发、生产及工程应用的国家高新技术企业。以天健智造、天健工程、天健运维的“一站式全流程…

uniapp ios证书失效

前面是按照网上查找的方法 作者大大的地址 1、一个ios账户&#xff08;688付费版&#xff09; 2、登录 Apple Developer 3、创建Identifiers ps&#xff1a;创建时需继承苹果的sdk&#xff0c;只需要一个就行 点击continue再点击Register即可 4、创建.cer证书 &…

软件测试简历,你真的会写简历吗?一周疯狂面试6家...

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 简历元素 一份合格…

SqlServer数据库复习总结资料

基于课堂上学到的以及书上的看到的&#xff0c;总结出的数据库复习资料 一、数据库概述 基本概念 1.数据 数据&#xff08;Data&#xff09;是事物的符号表示&#xff0c;可以是声音、图像、文字、数字&#xff0c;也可以是计算机代码。 2.数据库 数据库&#xff08;DataBase…

WebSocket 使用示例,后台为nodejs

效果图 页面代码 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8" /><meta name"viewport" content"widthdevice-width, initial-scale1.0" /><title>WebSocket Client</title&g…

java NIO群聊系统

demo要求&#xff1a; 1&#xff09;编写一个NIO群聊系统&#xff0c;实现服务器端和客户端之间的数据简单通讯&#xff08;非阻塞&#xff09; 2&#xff09;实现多人群聊 3&#xff09;服务器端&#xff1a;可以监测用户上线&#xff0c;离线&#xff0c;并实现消息转发功…

利用autodl服务器跑模型

1. 租用服务器 本地改模型 服务器 将改进好的、数据集处理好的模型压缩为zip文件上传到阿里云盘打开服务器AUTODL服务器&#xff0c;在主页中选择容器实例 在此位置进行开关机操作&#xff0c;若停止服务器&#xff0c;必须关机&#xff0c;不然会一直扣钱 2. 运行模型 选择…

【Unity】捕捉PC桌面的插件

【背景】 之前介绍了如何用一款名为uWindowCapture的Unity免费插件在Unity的Canvas上展示PC桌面。经过一段时间的使用,本篇继续分享此插件的一些功能和限制。 在此感谢作者Hecomi。 【特征和限制】 一般局域网络环境只能最多达到15帧的帧率,所以别幻想用来窜流游戏或者看电…

【个人记录】CentOS7安装MySQL 5.7和libmysqlclient.so.20

记录 之前使用MariaDB 发现使用的libmysqlclient.so是18版本的&#xff0c;一些程序需要20版本的库&#xff0c;查了一下需要安装5.7以上版本的才有libmysqlclient.so.20&#xff0c;这里简单记录一下怎么安装。 安装MySQL 5.7 Yum源 yum install -y https://repo.mysql.com…

【C++】狗屁不通文章生成器2.0

【C】狗屁不通文章生成器2.0 1 前言2 改进2.1 字词的前后关系2.2 文章生成系统 3 实现(部分)3.1 class wordpair3.1.1 转化为 json3.1.2 添加后缀词3.1.3 选择后缀词 3.2 class createArticle3.2.1文本分割3.2.2生成文章 4演示4.1 wordpair(3x2), 启动词(春天)4.2 wordpair(2x1…

电脑维修的相关资料,有需要的自取

电脑维修的相关资料&#xff0c;有需要的自取。 链接&#xff1a;https://pan.baidu.com/s/1X81sBNAOmomFvug6mK56Bw 提取码&#xff1a;52pj 爆笑幽默段子&#xff1a;电脑出故障了&#xff0c;准备拿去修&#xff0c;结果被女朋 友拦住了。女朋友&#xff1a;“你们男人一定…

ginblog博客系统/golang+vue

ginblog博客系统 前台&#xff1a; 后台&#xff1a; Gitee的项目地址&#xff0c;点击进入下载 注意&#xff1a; 数据库文件导入在model里面&#xff0c;直接导入即可。 admin和front前后台系统记住修改https里的地址为自己的IP地址&#xff1a; front同上。

Doris实战——工商信息查询平台的湖仓一体建设

目录 前言 一、架构1.0&#xff1a;传统Lambda架构 二、OLAP引擎调研 三、架构2.0&#xff1a;数据服务层All in Apache Doris 四、架构 3.0&#xff1a;基于Doris Multi-Catalog的湖仓一体架构 五、实践经验 5.1 引入Merge-on-Write&#xff0c;百亿级单表查询提速近三…

学习vue3第九节(新加指令 v-pre/v-once/v-memo/v-cloak )

1、v-pre 作用&#xff1a;防止编译器解析某个特定的元素及其内容&#xff0c;即v-pre 会跳过当前元素以及其子元素的vue语法解析&#xff0c;并将其保持原样输出&#xff1b; 用于&#xff1a;vue 中一些没有指令和插值表达式的节点的元素&#xff0c;使用 v-pre 可以提高 Vu…

【项目实践】VS配置Qt

文章目录 前言版本使用具体步骤1&#xff09;安装Qt或者添加删除组件2&#xff09;VS安装Qt Visual Studio Tools 如何使用遇到的问题双击ui文件编辑报错 前言 最近因为一个项目&#xff0c;需要使用Qt&#xff0c;本来想使用Python的&#xff0c;但是由于另外一个第三方的库是…