MPP音视频总结

news2024/10/29 3:10:58

基础篇

1.常用图像格式介绍

常用图像像素格式 RGB 和 YUV。

1.1RGB

RGB分类通常指的是将图像或颜色按照RGB(红、绿、蓝)颜色空间进行分组或分类。RGB图像格式通常包括RGB24(RGB888)、RGB32、RGBA、RGB565等。

RGB24是一种常用的图像颜色格式,表示每个像素使用24位(8位红、8位绿、8位蓝)来存储颜色信息。

RGB32是在RGB24的基础上增加了一个8位的alpha通道,用于表示透明度。每个像素总共占用32位。

RGB565使用16位表示颜色,其中5位用于红色,6位用于绿色,5位用于蓝色,适用于减少内存占用的场景

1.2YUV

        YUV 图像是指将亮度参量 Y 和色度参量 U/V 分开表示的像素格式,主要用于优化彩色视频信号的传输。YUV 相比于 RGB 格式最大的好处是可以做到在保持图像质量降低不明显的前提下,减小文件大小。YUV 格式之所以能够做到,是因为进行了采样操作。主流的采样方式有三种:YUV 4:4:4(YUV444),YUV 4:2:2(YUV422),YUV 4:2:0(YUV420)。

若以以黑点表示采样该像素点的 Y 分量,以空心圆圈表示采用该像素点的 UV 分量,则这三种采样方式如下:

YUV 存储格式

YUV 存储可以分为两种:packed(打包)和 planar(平面);

  • packed:Y、U、V 分量穿插着排列,三个分量存在一个 Byte 型数组里;

  • planar:Y、U、V 分量分别存在三个 Byte 型数组中;

常见的像素格式

YUV422:YUYV、YVYU、UYVY、VYUY

这四种格式每一种又可以分为 2 类(packed和planar),以 YUYV 为例,一个 6*4 的图像的存储方式如下:

	Y Y Y Y Y Y                   
	Y Y Y Y Y Y                  
	Y Y Y Y Y Y                   
	Y Y Y Y Y Y                    
	U U U U U U                  Y U Y V Y U Y V Y U Y V
	U U U U U U                  Y U Y V Y U Y V Y U Y V
    V V V V V V                  Y U Y V Y U Y V Y U Y V
	V V V V V V                  Y U Y V Y U Y V Y U Y V
	- Planar -                          - Packed - 
YUV420:I420(YU12)、YV12、NV12、NV21
  • YUV420p: I420、YV12
  • YUV420sp: NV12、NV21

 同样,对于一个6*4的图像,这四种像素格式的存储方式如下:

	Y Y Y Y Y Y      Y Y Y Y Y Y      Y Y Y Y Y Y      Y Y Y Y Y Y
	Y Y Y Y Y Y      Y Y Y Y Y Y      Y Y Y Y Y Y      Y Y Y Y Y Y
	Y Y Y Y Y Y      Y Y Y Y Y Y      Y Y Y Y Y Y      Y Y Y Y Y Y
	Y Y Y Y Y Y      Y Y Y Y Y Y      Y Y Y Y Y Y      Y Y Y Y Y Y
	U U U U U U      V V V V V V      U V U V U V      V U V U V U
	V V V V V V      U U U U U U      U V U V U V      V U V U V U
     - I420 -          - YV12 -         - NV12 -         - NV21 -
  • I420、YV12 三个分量均为平面格式,即分别存在三个数组中;
  • NV12、NV21 的存储格式为 Y 平面,UV 打包,即 Y 信息存储在一个数组中,UV 信息存储在一个另一个数组中。

2.链表

2.1普通链表

2.1.1链表的难点

链表的难点  --->  指针。

口诀:

  • 变量变量,能变,就是能读能写,必定在内存里
  • 指针指针,保存的是地址,32处理器中地址都是32位的,无论是什么类型的指针变量,都是4字节

2.2改进链表

2.3常见双向链表宏
struct list_head
{
  struct list_head *next, *prev;
};
  • next:指向链表中下一个节点的指针。
  • prev:指向链表中上一个节点的指针。
  • 这个结构体用于表示链表的每个节点,允许在链表中双向遍历。
初始化链表头部
#define LIST_HEAD_INIT(name) { &(name), &(name) }
  • 这是一个宏,用于初始化链表头部。
  • 它将链表头部的 next 和 prev 指针都指向自身,表示这是一个空链表。
 声明和初始化一个新的链表头部
#define LIST_HEAD(name) \
    struct list_head name = LIST_HEAD_INIT(name)
  • 这个宏用于声明和初始化一个新的链表头部。
  • name 是用户指定的链表头的名称。该宏创建一个 struct list_head 类型的变量,并使用 LIST_HEAD_INIT 进行初始化。
 初始化已定义的链表头部
#define INIT_LIST_HEAD(ptr) do { \
    (ptr)->next = (ptr); (ptr)->prev = (ptr); \
} while (0)
  • 这个宏用于初始化已定义的链表头部。
  • ptr 是指向链表头的指针,宏将其 next 和 prev 指针都设置为指向自身,以表示它是一个空链表。
 在链表中增加链表项
static __inline__ void __list_add(struct list_head *new,
                                   struct list_head *prev,
                                   struct list_head *next)
{
    next->prev = new;   // 将新节点的下一个节点的 prev 指针指向新节点
    new->next = next;   // 新节点的 next 指向原本的下一个节点
    new->prev = prev;   // 新节点的 prev 指向前一个节点
    prev->next = new;   // 前一个节点的 next 指向新节点
}
  • 参数

    • new:要添加的新节点。
    • prev:新节点要插入的位置之前的节点。
    • next:新节点要插入的位置之后的节点。
  • 功能:将新节点 new 插入到链表中,位置在 prevnext 之间。函数首先更新 next 节点的 prev 指针,使其指向新节点,然后更新新节点的 nextprev 指针,最后更新 prev 节点的 next 指针,以完成插入操作。

 在链表中替换列表项
static inline void list_replace(struct list_head *old,
                                 struct list_head *new)
{
    new->next = old->next;               // 新节点的 next 指向旧节点的下一个节点
    new->next->prev = new;               // 旧节点下一个节点的 prev 指向新节点
    new->prev = old->prev;               // 新节点的 prev 指向旧节点的前一个节点
    new->prev->next = new;               // 旧节点的前一个节点的 next 指向新节点
}
  • 参数

    • old:要被替换的旧节点。
    • new:新的节点,将替换旧节点。
  • 功能:替换链表中的旧节点 old 为新节点 new。函数更新新节点的 nextprev 指针,并相应地调整链表中相邻节点的指针,使链表保持连贯。

海思平台

媒体处理平台架构

主要的处理流程介绍如下:

        

        可以看到主要分为视频输入(VI)、视频处理(VPSS)、视频编码(VENC)、视频解码(VDEC)、视频输出(VO)、视频拼接(AVS)、音频输入(AI)、音频输出(AO)、音频编码(AENC)、音频解码(ADEC)、区 域管理(REGION)等模块,几个主要模块的大致功能为:

VI模块:捕获视频图像,可对其做剪切、去噪等处理,并输出多路不同分辨率的图像数据。

VDEC模块:解码模块对编码后的视频码流进行解码,并将解析后的图像数据送 VPSS 进行图像处理,再送 VO 显示。可对 H.265/H.264/JPEG 格式的视频码流进行解码。

VPSS模块:接收 VI 和解码模块发送过来的图像,可对图像进行图像增强、锐化等处理,并实现同源输出多路不同分辨率的图像数据用于编码、预览或抓拍。

VENC模块:编码模块接收 VI 捕获并经 VPSS 处理后输出的图像数据,可叠加用户通过 Region
模块设置的 OSD 图像,然后按不同协议进行编码并输出相应码流。

VO模块:接收 VPSS 处理后的输出图像,可进行播放控制等处理,最后按用户配置的输出协议输出给外围视频设备。

AVS模块:接收多路VI采集的图像,进行拼接合成全景图像(这里的AVS是指“视频拼接子系统”,我之前一直以为是编解码的AVS标准)。

AI模块:捕获音频数据,然后AENC模块支持按多种音频协议对其进行编码,最后输出音频码流。

ADEC模块:用户从网络或外围存储设备获取的音频码流可直接送给ADEC模块,ADEC支持解码多种不同的音频格式码流,解码后数据送给AO模块即可播放声音。

视频缓存池

功能:视频缓存池主要向媒体业务提供大块物理内存管理功能,负责内存的分配和回收,充
分发挥内存缓存池的作用,让物理内存资源在各个媒体处理模块中合理使用。
构成:一组大小相同、物理地址连续的缓存块组成一个视频缓存池。
使用注意点: 必须在系统初始化之前配置公共视频缓存池 。根据业务的不同,公共缓存池的数量、缓存块的大小和数量不同。
典型的公共视频缓存池数据流图:所有的视频输入通道都可以从公共视频缓存池中获取视频缓存块用于保存采集的图像,如图中所示 VI 从公共视频缓存池 B 中获取视频缓存块 Bm, 缓存块 Bm VI 发送给VPSS,输入缓存块 Bm 经过 VPSS 处理之后被释放回公共视频缓存池。假设 VPSS 通道的工作模式是USER ,则 VPSS 通道 0 从公共视频缓存池 B 中获取缓存块 Bi 作为输出图像缓存buffer发送给 VENC VPSS 通道 1 从公共视频缓存池 B 中获取缓存块 Bk 作为输出图像缓存buffer 发送给 VO Bi VENC 编码完之后释放回公共视频缓存池, Bk VO 显示完之后释放回公共视频缓存池。
                

系统绑定

        MPP提供系统绑定接口(HI_MPI_SYS_Bind),即通过数据接收者绑定数据源来建立两者之间的关联关系(只允许数据接收者绑定数据源)。绑定后,数据源生成的数据将自动发送给接收者。目前MPP支持的绑定关系如下:

数据源数据接受者
VIVO 、VENC、VPSS、PCIV、VI(虚拟PIPE)
VPSSVO、VENC、VPSS、PCIV、VI(虚拟PIPE)、AVS
VDECVO、VENC、VPSS、PCIV、VI(虚拟PIPE)
VO(WBC)VO、VENC、VPSS、PCIV、VI(虚拟PIPE)
AVSVO、VENC、VPSS、PCIV、VI(虚拟PIPE)
AIAO、AENC
ADECAO

海思提供绑定函数 HI_MPI_SYS_Bind 来实现数据源与数据接受者的绑定:

HI_S32 HI_MPI_SYS_Bind(const MPP_CHN_S *pstSrcChn, const MPP_CHN_S
*pstDestChn);
  •   pstSrcChn指源通道指针
  •   pstDestChn指目的通道指针
  •   API需求的头文件为:hi_comm_sys.h、mpi_sys.h,需求的库文件为:libmpi.a

 注意:同一个数据接收者只能绑定一个数据源

VENC绑定VI为数据源示例:

HI_S32 SAMPLE_COMM_VI_UnBind_VENC(VI_PIPE ViPipe, VI_CHN ViChn, VENC_CHN VencChn)
{
    MPP_CHN_S stSrcChn;
    MPP_CHN_S stDestChn;
 
    stSrcChn.enModId   = HI_ID_VI;
    stSrcChn.s32DevId  = ViPipe;
    stSrcChn.s32ChnId  = ViChn;
 
    stDestChn.enModId  = HI_ID_VENC;
    stDestChn.s32DevId = 0;
    stDestChn.s32ChnId = VencChn;
 
    CHECK_RET(HI_MPI_SYS_UnBind(&stSrcChn, &stDestChn), "HI_MPI_SYS_UnBind(VI-VENC)");
 
    return HI_SUCCESS;
}

解绑的API为 HI_MPI_SYS_UnBind 

HI_S32 HI_MPI_SYS_UnBind(const MPP_CHN_S *pstSrcChn, const MPP_CHN_S
*pstDestChn);

注意:pstDestChn如果找不到绑定的源通道,则直接返回成功。如果找到了绑定的源通道,但是绑定的源通道和pstSrcChn不匹配,则返回失败。

若需将上面的VENC和VI解绑,示例如下: 

HI_S32 SAMPLE_COMM_VI_UnBind_VENC(VI_PIPE ViPipe, VI_CHN ViChn, VENC_CHN VencChn)
{
    MPP_CHN_S stSrcChn;
    MPP_CHN_S stDestChn;
 
    stSrcChn.enModId   = HI_ID_VI;
    stSrcChn.s32DevId  = ViPipe;
    stSrcChn.s32ChnId  = ViChn;
 
    stDestChn.enModId  = HI_ID_VENC;
    stDestChn.s32DevId = 0;
    stDestChn.s32ChnId = VencChn;
 
    CHECK_RET(HI_MPI_SYS_UnBind(&stSrcChn, &stDestChn), "HI_MPI_SYS_UnBind(VI-VENC)");
 
    return HI_SUCCESS;
}

VO篇

1.如何读取一张YUV420格式的图片到内存(通常用于保存固定背景图)

  1. 根据显示图片文件名获取图片长和宽的大小(调用strstr函数获取文件名中特定字段的位置)
  2. 由图片长款大小,分别计算亮度、色度、图片字节大小(亮度大小=图片分辨率,色度大小=(图片分辨率>>4)*2,图片大小=二者相加)
  3. 创建视频缓存池VB(默认D1分辨率704*576,ipc子码流通常为D1大小)
  4. 从创建好的缓存池中,获取缓存块(大小为要显示图片的大小)
  5. 一个帧缓存块所在缓存池的 ID
  6. 获取缓存块的物理地址,并转化对应的虚拟地址。
  7. 到此准备工作结束
  8. 图像帧结构体进行赋值,(缓存池ID、图像数据物理地址、图像数据虚拟地址、宽、高、视频图像像素格式-yuv420图像数据跨距{图像宽大小}、帧场模式
  9. 只读模式fopen打开要显示图像文件,fread读取图像数据到虚拟地址中

2.如何通过VO的设备ID来获取VO设备的亮度、色度、对比度、锐度等参数

  1. 遍历VO设备的链表,从链表节点 pos 中获取对应的 VoDevEntry 结构体指针
  2. 判断找到的VO链表项的voID是否和传入的设备ID相等
  3. 如果相等,获取VO设备结构体中的亮度、色度、对比度等参数
static int GetVoDevData(int voId, VoDevStruct **devStruct)
{
    int result = ERR_DEVID;
    struct list_head *pos = NULL;
    struct list_head *save = NULL;

    //确保 voId 和 devStruct 参数的有效性
    VO_CHECK_VOID(voId);
    CHECK_POINTER(devStruct);

    //使用 list_for_each_safe 宏安全遍历链表 voDevs
    list_for_each_safe(pos, save, &voDevs) 
    {
        //通过链表节点获取对应的 VoDevStruct 结构体指针
        (*devStruct) = list_entry(pos, VoDevStruct , node);
        //检查 (*devStruct) 是否为 NULL,如果是,记录错误并返回
        if (NULL == (*devStruct))
        {
            LogErr("find vo info err. voId = %d\n", voId);
            result = ERR_INPOITERNULL;
            goto EXIT_0;
        }

        //如果找到匹配的 voId,则设置 result 为成功状态 ERR_OK,并跳出循环
        if ((*devStruct)->voId == voId)
        {
            result = ERR_OK;
            break;
        }
    }
    
EXIT_0:

    return result;
}

3.VO子系统如何接收VPSS发送的视频流

4. VO模块如何实现视频流的播放控制等操作

5.VO模块如何按照不同协议进行编码并输出相应码流

文章持续更新中……

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

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

相关文章

【CSS】入门详解

你是否曾经浏览网页时,被一些网站精美的布局、炫酷的动画和赏心悦目的色彩所吸引?这背后神奇的力量就是 CSS(层叠样式表)。CSS 就像网页的化妆师,它负责网页的样式和布局,让原本枯燥的 HTML 结构变得生动有…

AttributeError: module ‘pandas‘ has no attribute ‘datetime‘

今天在进行时间序列问题处理时候,发生如下报错: AttributeError: module pandas has no attribute datetime 因为在新的pands版本中pandas已不再支持datetime模块。 from datetime import datetime 需要导入datetime库。 原代码: impor…

2025选题|基于Hadoop的物品租赁系统的设计与实现

作者简介:Java领域优质创作者、CSDN博客专家 、CSDN内容合伙人、掘金特邀作者、阿里云博客专家、51CTO特邀作者、多年架构师设计经验、多年校企合作经验,被多个学校常年聘为校外企业导师,指导学生毕业设计并参与学生毕业答辩指导,…

《虚拟现实的边界:探索虚拟世界的未来可能》

内容概要 在虚拟现实(VR)技术的浪潮中,我们见证了其从实验室的奇想逐渐走向日常生活的非凡旅程。技术发展的背后是不断突破的创新,早期的设备虽然笨重,但如今却趋向精致、轻巧,用户体验显著提升。想象一下…

【MySQL】视图特性 用户管理

> 作者:დ旧言~ > 座右铭:松树千年终是朽,槿花一日自为荣。 > 目标:了解什么是视图,我们又该如何管理用户。 > 毒鸡汤:有些事情,总是不明白,所以我不会坚持。早安! >…

旧衣物回收小程序开发,线上线下相结合

当下,绿色发展是重中之重,旧衣回收作为一件利国利民的模式,在发展中深受大众欢迎。随着大众生活水平的提高,家中闲置的衣物逐年增加,这也为旧衣回收市场发展提供了广阔的发展前景,为入局者和创业者提供新的…

keepalived+web 实现双机热备

环境:利用keeplived实现web服务器的双机热备(高可用) 注意: (1) 利用keeplivedweb做双击热备(高可用),最少需要两台服务器,可以实现多域名对应一个VIP,并且访问不同域名,显示不同主页&#xf…

a50股指期货是什么意思?

首先,股指期货,顾名思义,就是以股票指数为标的的期货合约。啥是期货呢?简单来说,就是现在约定好价格,将来某个时间再交易的东西。而A50股指期货,就是以A50指数为标的的期货合约。 A50指数&…

理解UUID 无序性对数据存储的影响

文章目录 背景问题1,移动数据问题2,频繁的页分裂背景 如果以UUID为主键,对于mysql 可能存在的问题。 问题1,移动数据 从上图来看,如果UUID是随机的话,以0012,0021 这个节点来说,如果插入的是0015,相当于要把16到21的数据向后移动一个位置,如果是自增的话,只会在尾…

HarmonyOS ArkTS与C++数据类型转换

1. HarmonyOS ArkTS与C数据类型转换 本文介绍了C与TS各自数据类型与互相之间的数据类型转换,在需要使用C模块时可以快速上手对各种数据类型进行转换。 1.1. 概述 HarmonyOS的主力开发语言是ArkTS,也提供了C语言的支持,对于一些能力&#xff…

Docker:容器

Docker:容器 容器容器命令docker psdocker createdocker startdocker rundocker logsdocker execdocker stopdocker restartdocekr rmdocker killdocker pausedocker unpausedocker commitdocker cpdocker diffdocker exportdocker importdocker renamedocker stats…

Es环境搭建 ▎kibana组件 ▎ik分词器 ▎idea继承Es ▎idea中Es操作

目录 安装Es 安装Es可视化界面(elasticsearch-head) elasticsearch-head安装: 安装可视化Kibana组件 汉化kibana ​编辑 启动服务器: 安装ik分词器插件 Idea继承Es 索引库操作 文档操作 安装Es Es下载地址: ES下载地址https://www.elastic.co/cn/downloads/elasticsea…

苏州金龙技术创新赋能旅游新质生产力

2024年10月23日,备受瞩目的“2024第六届旅游出行大会”在云南省丽江市正式开幕。作为客车行业新质生产力标杆客车,苏州金龙在大会期间现场展示了新V系V12商旅版、V11和V8E纯电车型,为旅游出行提供全新升级方案。 其中,全新15座V1…

SpringBoot3集成Swagger接口文档功能、接口排序以及如何设置接口页面的title/keyword/description?

一、SpringBoot3集成Swagger接口文档功能 在SpringBoot3 中集成 Swagger 接口文档,如果按照网上的很多提示,会有些问题。在这个过程中我就遇到报错: Caused by: java.lang.ClassNotFoundException: javax.servlet.http.HttpServletRequest 因…

总裁主题CeoMax-Pro主题7.6开心版

激活方式: 1.授权接口源码ceotheme-auth-api.zip搭建一个站点,绑定www.ceotheme.com域名,并配置任意一个域名的 SSL 证书。 2.在 hosts 中添加:127.0.0.1 www.ceotheme.com 3.上传class-wp-http.php到wp-includes目录&#xff…

Rust命令行,实现自动反编译Android APK包工具

Rust-CLI实现自动反编译APK Rust提供了比较好的CLI接口,可以快速的编写命令行应用, 用于日常的工具类使用。 分享一个用Rust命令行实现自动反编译Android APK包工具,是之前学习Rust写的一个练手小工具,可以快速反编译APK,同时也学习下用Rust…

Flutter升级与降级

升级 版本升级 // 升级到指定版本flutter upgrade 版本号// 升级到最新版本flutter upgrade 降级 1.需要先确定想要降级的版本号。 2.切换到系统安装Flutter的目录 3.在https://github.com/flutter/flutter,找到要回退的版本号对应的commit序号(具…

熵与信息论

经典信息论的核心概念是香农熵。假设我们得到了一个变量X的值,X的香农熵量化了我们在获悉 X的值时所能得到的平均信息量;另一种观点是将X的看作在我们获悉的值前对其不确定程度的度量。这两种观点是互补的;我们既可以将看作在我们获悉X的值前…

Vue3+ts+vite自动导入vue的依赖

Vue3tsvite自动导入vue的依赖 unplugin-auto-import 主要依赖 npm i -D unplugin-auto-import// vite.config.ts import AutoImport from unplugin-auto-import/viteexport default defineConfig({plugins: [AutoImport({ imports: ["vue", "vue-router"…

研发运营一体化(DevOps)能力成熟度模型

目录 应用设计 安全风险管理 技术运 持续交付 敏捷开发管理 基于微服务的端到端持续交付流水线案例 应用设计 安全风险管理 技术运 持续交付