海思RTSP推流第二篇——海思平台和H264编码Demo

news2025/1/22 9:23:29

前言:
记得行内一个老师说过,基础不牢,地动山摇,对于海思的编码过程还是不是很熟悉所以回头把这个分析一遍。
海思平台:
官方手册:HiMPP IPC V2.0 媒体处理软件开发参考,里面有介绍海思IPC平台的架构和框架;
这里贴几个图具体还得查看文档。
Hi35xx 典型的系统层次图:
在这里插入图片描述
海思媒体处理平台架构:分为好几个模块,视频输入( VI)、视频
处理( VPSS)、视频编码( VENC)、视频解码( VDEC)、视频输出(VO)、视频侦测分
析(VDA)、音频输入(AI)、音频输出(AO)、音频编码( AENC)、音频解码( ADEC)、
区域管理( REGION)等模块
在这里插入图片描述
各模块的简介,具体还是得查看手册可知道其细节
在这里插入图片描述
正文:海思平台H264编码的过程

一、会有相关的音视频的参数和概念

  1. 比如VPSS视频处理子系统,通道、码率控制模式等…对这些概念需要理解其作用;
    //编码协议类型
PAYLOAD_TYPE_E enPayLoad[1]= {PT_H264};
PIC_SIZE_E enSize[3] = {PIC_HD1080};
HI_U32 u32Profile = 0;

//定义视频缓存池属性结构体。
VB_CONF_S stVbConf;
//vi config
SAMPLE_VI_CONFIG_S stViConfig = {0};

//VPSS
VPSS_GRP VpssGrp;
VPSS_CHN VpssChn;
VPSS_GRP_ATTR_S stVpssGrpAttr;
VPSS_CHN_ATTR_S stVpssChnAttr;
VPSS_CHN_MODE_S stVpssChnMode;

//编码通道
VENC_CHN VencChn;
//定义编码通道码率控制器 模式 
SAMPLE_RC_E enRcMode= SAMPLE_RC_CBR;
//通道数
HI_S32 s32ChnNum=0;

HI_S32 s32Ret = HI_SUCCESS;
HI_U32 u32BlkSize;
SIZE_S stSize;
char c;

PAYLOAD_TYPE_E :定义编码协议类型枚举;
VB_CONF_S :定义视频缓存池属性结构体;
SAMPLE_RC_E :定义编码通道码率控制器 模式 ;
什么是码率? 码率就是数据传输时单位时间传送的数据位数。
重点提下码率控制模式:包含了vbr和cbr 、avbr、 qvbr 、cvbr、fixqp等多种

typedef enum sample_rc_e
{
    SAMPLE_RC_CBR = 0,      //CBR:(Constant Bit Rate)恒定码率
    SAMPLE_RC_VBR,          //VBR:(Variable Bit Rate)可变码率
	SAMPLE_RC_AVBR,         //AVBR(Adaptive Variable Bit rate)变码流:AVBR是通过对VBR的进一步改进,增加了自适应动态码率控制功能
    SAMPLE_RC_FIXQP         //FIXQP(固定质量)是一种视频编码方式
}SAMPLE_RC_E;

详细参考博客:https://blog.csdn.net/qq_28258885/article/details/118891810

  1. 对海思平台图形处理器的一些个人理解
    海思平台框架按照上面已经给出,分为多个模块VI、VPSS、VENC等模块,模块之间连接要通过绑定来实现数据传输,海思有一种数据交换模式叫在线和离线模式,在线模式下可以不经过内存直接把数据传输给另一个模块,VI和VPSS之间,图像采集编码这个过程需要申请一个大的内存——内存池,用于存放图像数据 stVbConf 设置相关参数,图像采集过程申请一个内存缓冲块存放数据,内存块在完成编码后需要释放如下图所示。
    在这里插入图片描述

二、海思平台视频编码过程

视频编码流程:申请内存池 -> 初始化sys -> 启动VI -> 启动视频处理子系统 -> 绑定VI和VPSS -> 启动VENC -> 绑定VENC和VPSS -> 获取和保存视频裸流;
过程中有相关的参数设置需要根据需要查阅手册配置合理的参数。

/******************************************
 step  1: init sys variable 
******************************************/

SAMPLE_COMM_VI_GetSizeBySensor(&enSize[0]);

/*video buffer*/
u32BlkSize = SAMPLE_COMM_SYS_CalcPicVbBlkSize(gs_enNorm,\
            enSize[0], SAMPLE_PIXEL_FORMAT, SAMPLE_SYS_ALIGN_WIDTH);
stVbConf.astCommPool[0].u32BlkSize = u32BlkSize;
stVbConf.astCommPool[0].u32BlkCnt = g_u32BlkCnt;


/******************************************
 step 2: mpp system init. 
******************************************/
s32Ret = SAMPLE_COMM_SYS_Init(&stVbConf);

/******************************************
 step 3: start vi dev & chn to capture
******************************************/
stViConfig.enViMode   = SENSOR_TYPE;
stViConfig.enRotate   = ROTATE_NONE;
stViConfig.enNorm     = VIDEO_ENCODING_MODE_AUTO;
stViConfig.enViChnSet = VI_CHN_SET_NORMAL;
stViConfig.enWDRMode  = WDR_MODE_NONE;
//开始视频输入
s32Ret = SAMPLE_COMM_VI_StartVi(&stViConfig);

/******************************************
 step 4: start vpss and vi bind vpss
******************************************/
s32Ret = SAMPLE_COMM_SYS_GetPicSize(gs_enNorm, enSize[0], &stSize);

VpssGrp = 0;
stVpssGrpAttr.u32MaxW = stSize.u32Width;
stVpssGrpAttr.u32MaxH = stSize.u32Height;
stVpssGrpAttr.bIeEn = HI_FALSE;
stVpssGrpAttr.bNrEn = HI_TRUE;
stVpssGrpAttr.bHistEn = HI_FALSE;
stVpssGrpAttr.bDciEn = HI_FALSE;
stVpssGrpAttr.enDieMode = VPSS_DIE_MODE_NODIE;
stVpssGrpAttr.enPixFmt = PIXEL_FORMAT_YUV_SEMIPLANAR_420;	
s32Ret = SAMPLE_COMM_VPSS_StartGroup(VpssGrp, &stVpssGrpAttr);

s32Ret = SAMPLE_COMM_VI_BindVpss(stViConfig.enViMode);

VpssChn = 0;
stVpssChnMode.enChnMode      = VPSS_CHN_MODE_USER;
stVpssChnMode.bDouble        = HI_FALSE;
stVpssChnMode.enPixelFormat  = PIXEL_FORMAT_YUV_SEMIPLANAR_420;
stVpssChnMode.u32Width       = stSize.u32Width;
stVpssChnMode.u32Height      = stSize.u32Height;
stVpssChnMode.enCompressMode = COMPRESS_MODE_SEG;
memset(&stVpssChnAttr, 0, sizeof(stVpssChnAttr));
stVpssChnAttr.s32SrcFrameRate = -1;
stVpssChnAttr.s32DstFrameRate = -1;
s32Ret = SAMPLE_COMM_VPSS_EnableChn(VpssGrp, VpssChn, &stVpssChnAttr, &stVpssChnMode, HI_NULL);


/******************************************
 step 5: start stream venc
******************************************/
printf("\t c) cbr.\n");
printf("\t v) vbr.\n");
printf("\t a) Avbr.\n");
printf("\t f) fixQp\n");
//选择码率控制模式
printf("please input choose rc mode!\n");
c = (char)getchar();
switch(c)
{
    case 'c':
        enRcMode = SAMPLE_RC_CBR;
        break;
    case 'v':
        enRcMode = SAMPLE_RC_VBR;
        break;
				
    case 'a':
        enRcMode = SAMPLE_RC_AVBR;
        break;
    case 'f':
        enRcMode = SAMPLE_RC_FIXQP;
        break;
    default:
        printf("rc mode! is invaild!\n");
        goto END_VENC_1080P_CLASSIC_4;
}

s32Ret = SAMPLE_COMM_VENC_Start(VencChn, enPayLoad[0],\
                                gs_enNorm, enSize[0], enRcMode,u32Profile);

s32Ret = SAMPLE_COMM_VENC_BindVpss(VencChn, VpssGrp, VpssChn);
    
/******************************************
 step 6: stream venc process -- get stream, then save it to file. 
******************************************/
s32Ret = SAMPLE_COMM_VENC_StartGetStream(s32ChnNum);

printf("please press twice ENTER to exit this sample\n");
getchar();
getchar();

/******************************************
 step 7: exit process
******************************************/
SAMPLE_COMM_VENC_StopGetStream();

视频裸流获取和保存是单独开了一个线程进行

/******************************************************************************
* funciton : start get venc stream process thread
******************************************************************************/
HI_S32 SAMPLE_COMM_VENC_StartGetStream(HI_S32 s32Cnt)
{
    gs_stPara.bThreadStart = HI_TRUE;
    gs_stPara.s32Cnt = s32Cnt;

    return pthread_create(&gs_VencPid, 0, SAMPLE_COMM_VENC_GetVencStreamProc, (HI_VOID*)&gs_stPara);
}

这里面涉及到一个比较重要的变量是视频流结构体

typedef struct hiVENC_STREAM_S
{
    VENC_PACK_S *pstPack;                           /*stream pack attribute*/
    HI_U32      u32PackCount;                       /*the pack number of one frame stream*/
    HI_U32      u32Seq;                             /*the list number of stream*/

    union
    {
        VENC_STREAM_INFO_H264_S  stH264Info;         /*the stream info of h264*/
        VENC_STREAM_INFO_JPEG_S  stJpegInfo;         /*the stream info of jpeg*/
        VENC_STREAM_INFO_MPEG4_S stMpeg4Info;       /*the stream info of mpeg4*/
        VENC_STREAM_INFO_H265_S  stH265Info;        /*the stream info of h265*/
    };
}VENC_STREAM_S;

保存H264流的函数

/******************************************************************************
* funciton : save H264 stream
******************************************************************************/
HI_S32 SAMPLE_COMM_VENC_SaveH264(FILE* fpH264File, VENC_STREAM_S *pstStream)
{
    HI_S32 i;

    
    for (i = 0; i < pstStream->u32PackCount; i++)
    {
        fwrite(pstStream->pstPack[i].pu8Addr+pstStream->pstPack[i].u32Offset,
               pstStream->pstPack[i].u32Len-pstStream->pstPack[i].u32Offset, 1, fpH264File);

        fflush(fpH264File);
    }
    

    return HI_SUCCESS;
}

细节过程还是需要结合源码和手册对照。

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

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

相关文章

polyfit曲线拟合

一、简介 polyfit函数是matlab中用于进行曲线拟合的一个函数。其数学基础是最小二乘法曲线拟合原理。曲线拟合&#xff1a;已知离散点上的数据集&#xff0c;即已知在点集上的函数值&#xff0c;构造一个解析函数&#xff08;其图形为一曲线&#xff09;使在原离散点上尽可能接…

深度学习 —— 个人学习笔记10(池化层、LeNet)

声明 本文章为个人学习使用&#xff0c;版面观感若有不适请谅解&#xff0c;文中知识仅代表个人观点&#xff0c;若出现错误&#xff0c;欢迎各位批评指正。 二十一、池化层 1、 最大池化层和平均池化层 与互相关运算符一样&#xff0c;汇聚窗口从输入张量的左上角开始&#…

打靶记录6——靶机EvilBox---One

靶机下载地址 https://www.vulnhub.com/entry/evilbox-one,736/学习记录 在进行目录爆破和文件爆破的过程当中&#xff0c;如果有发现新的路径&#xff0c;一定要对新的路径再次进行更深层次的爆破虚拟机出现问题就删除掉&#xff0c;重新导入虚拟机 目标: 获取两个flag&am…

如何准备专利申请书的摘要部分?

如何准备专利申请书的摘要部分&#xff1f;

基于概率神经网络的异方差不确定性估计

目录 摘要1 介绍2 预热3 分析3.1对称性和特征非线性3.2逆方差加权有效欠样本 4 方法5 实验5.1合成数据集5.2真实数据集6 结论 摘要 捕获任意不确定性是许多机器学习系统的关键部分。在深度学习中&#xff0c;达到这一目的的一种常用方法是训练神经网络&#xff0c;通过最大化观…

力扣SQL50 组合两个表 入门基础连表查询

Problem: 175. 组合两个表 select FirstName, LastName, City, State from Person left join Address on Person.PersonId Address.PersonId ;

AI说 | 如何入门AI行业,成为人工智能产品经理?(上)

这周在上海出差&#xff0c;划个水&#xff0c;发一篇之前写的文章&#xff0c;谈谈如何入门AI行业 另外&#xff0c;有朋友说我的文章读起来很累&#xff0c;自我反思&#xff0c;确实写的太长&#xff0c;后面我会在保证有趣或有干货的情况下&#xff0c;将文章内容尽量减短…

《深入浅出WPF》学习笔记四.提高效率,code snippets的使用

《深入浅出WPF》学习笔记四.提高效率,code snippets的使用 背景 再跟着视频教程学习Wpf的过程中,发现这个小技巧。很惭愧好几年开发经验&#xff0c;没用过这个东西。 这个信息差还是很让人头疼的&#xff0c;特别在此分享。 code snippets是什么 Code Snippets是插入代码…

Elasticsearch 未授权访问漏洞

Elasticsearch 未授权访问漏洞 ElasticSearch是一个基于Lucene的搜索服务器。它提供了一个分布式多用户能力的全文搜索引擎&#xff0c;基于RESTful web接口。Elasticsearch是用Java开发的&#xff0c;并作为Apache许可条款下的开放源码发布&#xff0c;是当前流行的企业级搜索…

zabbix监控中文乱码解决方案

zabbix切换中文后&#xff0c;会出现乱码情况&#xff0c;如下图&#xff1a; 解决方案如下&#xff1a; 1、找到字体 WinR打开运行&#xff0c;输入fonts&#xff0c;回车进入Windows字体目录&#xff0c;找到微软雅黑-常规字体&#xff0c;复制出来将文件名修改为msyh.ttf…

Substance Painter工具栏及快捷键

3 菜单栏_哔哩哔哩_bilibili ctrl右键左右滑动调整笔刷大小/左键流量 上下滑动有其他作用 线框显示工具 制作随机效果 Fill要配合遮罩使用 白色遮罩显示底色&#xff0c;黑色遮罩不显示底色 核心工具 图层关系 必须添加在蒙版的效果下 选择中蒙版 滤镜仅能添加在图层下 id图…

k8s中yaml文件的编写

目录 1.编写pod.yaml 2.编写deploment.yaml 3.编写service.yaml关联创建的pod 4.总结获取K8S资源配置清单文件模板方法 方法1&#xff1a;根据现有资源导出yaml文件修改配置&#xff0c;重新创建 方法2&#xff1a;根据现有资源&#xff0c;进入其配置中&#xff0c;复制…

Go语言实现多协程文件下载器

文章目录 前言流程图主函数下载文件初始化分片下载worker分发下载任务获取下载文件的大小下载文件分片错误重试项目演示最后 前言 你好&#xff0c;我是醉墨居士&#xff0c;最近在开发文件传输相关的项目&#xff0c;然后顺手写了一个多协程文件下载器&#xff0c;代码非常精…

Cxx primer-chap12-Dynamic Memory

目前我们使用的对象都是语言本身代替我们管理其生命周期和作用域&#xff0c;例如global object、局部的自动变量和局部的static变量&#xff0c;除此之外&#xff0c;语言也允许我们创建动态分配的对象&#xff08;即运行时创建的对象&#xff09;&#xff1a;不同类型的对象&…

SpringCloud概述和基本工程搭建

目录 1.认识微服务 1.1单体架构 1.2集群和分布式架构 1.3微服务架构 1.4微服务的优势 2.微服务解决方案-Spring Cloud 2.1什么是Spring Cloud 2.2Spring Cloud Alibaba 2.3SpringCloud实现对比 3.服务拆分原则 3.1单一职责原则 3.2服务自治原则 3.3单向依赖原则 …

前端:Vue

一、引入 Vue是一套前端框架&#xff0c;免除javaScript中的DOM操作&#xff0c;简化书写。基于MVVM思想&#xff0c;实现数据的双向绑定&#xff0c;将编程的关注点放在数据上。 框架&#xff1a;是一个半成品软件&#xff0c;是一套可重用的、通用的、软件基础代码模型。基于…

C#初级——字典Dictionary

字典 字典是C#中的一种集合&#xff0c;它存储键值对&#xff0c;并且每个键与一个值相关联。 创建字典 Dictionary<键的类型, 值的类型> 字典名字 new Dictionary<键的类型, 值的类型>(); Dictionary<int, string> dicStudent new Dictionary<int, str…

深度学习-----------数值稳定性

目录 神经网络的梯度数值稳定性的常见两个问题例子&#xff1a;MLP 梯度爆炸梯度爆炸的问题 梯度消失梯度消失的问题 总结模型初始化和激活函数让训练更加稳定让每层的方差是一个常数 权重初始化正向均值和方差正向均值正向方差 反向均值和方差Xavier初始正向和反向的均值和方差…

HTTP:从基础概念到协议机制,详解请求响应与状态保持

文章目录 一、HTTP概述1、HTTP的理解2、HTTP是无状态的协议 二、HTTP协议的过程1、URL&#xff08;统一资源定位符&#xff09;2、客户端3、服务器端 三、HTTP请求与响应1、HTTP请求和响应2、HTTP请求方法3、状态码 四、HTTP报文1、请求报文首部2、响应报文首部3、首部字段 五、…

全网唯一!R语言顶刊配色包TheBestColors

与Matlab相比&#xff0c;R语言在绘图方面有着天然的优势。 比如在配色方面&#xff0c;R语言有各式各样现成的包&#xff0c;按理说配色这种事应该很方便才对。 但实际体验下来&#xff0c;发现似乎不是那么回事。 首先&#xff0c;你很难记住每个包的调用方法以及每种配色…