imx VPU解码分析4-wrap与hantro的关系

news2024/9/29 1:16:41

        前面已经分析了wrap和hantro,但是二者是如何结合的,wrap是如何封装hantro的,提供了哪些接口,封装了哪些细节还不太清楚,此文来探究下。这里还是只关注解码。

imx VPU解码分析1-wrap-CSDN博客

imx VPU解码分析2-hantro_huntenganw的博客-CSDN博客

imx VPU解码分析3-wrap的示例-CSDN博客

        上述文章已经分析了vpu_wrapper.h文件,这是wrap库对外的接口。vpu_wrapper_hantro.c这个文件就是封装的hantro接口,包含了hantro解码需要用到的api。

        这里分析下vpu_wrapper_hantro.c,看看具体如何操作的。

        首先看看头文件的包含:

#include "codec.h"

#include "codec_h264.h"

#include "codec_jpeg.h"

#include "codec_mpeg4.h"

#include "codec_vc1.h"

#include "codec_rv.h"

#include "codec_mpeg2.h"

#include "codec_vp6.h"

#include "codec_avs.h"

#include "codec_vp8.h"

#include "codec_webp.h"

#include "codec_hevc.h"

#include "codec_vp9.h"

        这些头文件在hantro/openmax_il/source/decoder下,即包含了这些相应的解码方式。

        然后是定义了几个内部结构体:

typedef enum

{

  VPU_DEC_STATE_OPEN=0,

  VPU_DEC_STATE_INITOK,

  VPU_DEC_STATE_REGFRMOK,

  VPU_DEC_STATE_DEC,

  VPU_DEC_STATE_STARTFRAMEOK,

  VPU_DEC_STATE_OUTOK,

  VPU_DEC_STATE_EOS,

  VPU_DEC_STATE_CORRUPT

}VpuDecState;

        这个结构体是具体的解码状态。可以对比VpuDecBufRetCode看看。

typedef struct

{

  /* open parameters */

  VpuCodStd CodecFormat;

  const void *pdwl;

  /* hantro decoder */

  CODEC_PROTOTYPE *codec;

  OMX_VIDEO_PARAM_CONFIGTYPE config;

  /* decode parameters */

  int iframeSearchEnable;

  int skipFrameMode;

  int skipFrameNum;

  int inputType; /*normal, kick, drain(EOS)*/

  int streamBufDelaySize; /*unit: bytes. used in stream mode:  valid data size should reach the threshold before decoding*/

  int initDataCountThd;

  VpuDecErrInfo nLastErrorInfo;  /*it record the last error info*/

  /*resolution for some special formats, such as package VC1 header,...*/

  int picWidth;

  int picHeight;

  /* init info */

  VpuDecInitInfo initInfo;

  /* out frame info */

  VpuDecOutFrameInfo frameInfo;

  /*used to store extended frame info*/

  VpuFrameExtInfo frmExtInfo;

  /* frame buffer management */

  int frameNum;

  VpuFrameBuffer frameBuf[VPU_MAX_FRAME_INDEX];  /*buffer node*/

  int frameBufState[VPU_MAX_FRAME_INDEX];  /*record frame state for clearing display frame(if user forgot to clear them)*/

  /* bitstream buffer pointer info */

  unsigned char* pBsBufVirtStart;

  unsigned char* pBsBufPhyStart;

  unsigned char* pBsBufPhyEnd;

  int nBsBufLen;

  int nBsBufOffset;

  /* state */

  VpuDecState state;

  /*management of consumed bytes: used to sync with frame boundary*/

  int nDecFrameRptEnabled; /*1:support frame reported; 0: not support*/

  int nAccumulatedConsumedStufferBytes;/*stuffer size between frames: if it <0, indicate that some frames are contained in config data*/

  int nAccumulatedConsumedFrmBytes; /*frame size: >=0*/

  int nAccumulatedConsumedBytes; /*it should match with the input data size == nAccumulatedConsumedStufferBytes+nAccumulatedConsumedFrmBytes*/

  VpuFrameBuffer* pLastDecodedFrm; /*the nearest decoded frame*/

  int nAdditionalSeqBytes; /*seq header inserted by wrapper itself , or config data */

  int nAdditionalFrmHeaderBytes; /*frame header inserted by wrapper itself */

  unsigned int nLastFrameEndPosPhy; /*point to the previous frame tail: used to compute the stuff data length between frames*/

  int nDecResolutionChangeEnabled; /*1: support resolution change notification; 0: not support*/

  int nPrivateSeqHeaderInserted;

  int nIsAvcc; /*for H.264/HEVC format*/

  int nNalSizeLen;

  int nNalNum; /*added for nal_size_length = 1 or 2*/

  bool eosing;

  bool ringbuffer;

  bool config_tile;

  int nFrameSize;

  int nOutFrameCount;

  int total_frames;

  long long total_time;

  int slice_info_num;

  RvDecSliceInfo slice_info[128];

  int frame_size;

  bool bSecureMode;

  bool bConsumeInputLater;

  int nSecureBufferAllocSize;

}VpuDecObj;

        这个结构体就是此文件中最重要的了,基本汇聚了所有信息,统统打包。

typedef struct

{

  VpuDecObj obj;

}VpuDecHandleInternal;

        这个结构体就把VpuDecObj再次包装下,在下面的函数中,既用了VpuDecObj,又用了VpuDecHandleInternal,暂时不明白为啥这么做。

下面看看有哪些关键函数。

先看看static修饰的函数:

//将数据复制到解码器

static void VpuPutInBuf(VpuDecObj* pObj, unsigned char *pIn, unsigned int len, bool useRingBuffer);

//解码器对不同格式进行解析,通过pInData->pVirAddr == (unsigned char *)0x01 && pInData->nSize //== 0来判断数据读完,这里读完解码器中还有几帧数据待解

static VpuDecRetCode VPU_DecProcessInBuf(VpuDecObj* pObj, VpuBufferNode* pInData);

//查找解码帧

static int VpuSearchFrameIndex(VpuDecObj* pObj, unsigned char *pInPhysY);

//获取解码帧

static VpuDecRetCode VPU_DecGetFrame(VpuDecObj* pObj, int* pOutBufRetCode);

//解码指针的处理,结构返回值

static VpuDecRetCode VPU_DecDecode(VpuDecObj* pObj, int* pOutBufRetCode);

下面是对外的函数,所有函数的返回值都是VpuDecRetCode :

//加载解码器

VpuDecRetCode VPU_DecLoad()

//申请内存

VpuDecRetCode VPU_DecQueryMem(VpuMemInfo* pOutMemInfo)

//打开解码器,进行各种内存、指针、DWL的初始化,创建相应格式的解码器

VpuDecRetCode VPU_DecOpen(VpuDecHandle *pOutHandle, VpuDecOpenParam * pInParam,VpuMemInfo* pInMemInfo)

//查看支持的解码VpuDecCapability值

VpuDecRetCode VPU_DecGetCapability(VpuDecHandle InHandle,VpuDecCapability eInCapability, int* pOutCapbility)

//关闭解码支持

VpuDecRetCode VPU_DecDisCapability(VpuDecHandle InHandle,VpuDecCapability eInCapability)

//解码模式设置,参看VpuDecConfig结构体

VpuDecRetCode VPU_DecConfig(VpuDecHandle InHandle, VpuDecConfig InDecConf, void* pInParam)

//主解码函数

VpuDecRetCode VPU_DecDecodeBuf(VpuDecHandle InHandle, VpuBufferNode* pInData,

    int* pOutBufRetCode)

//获取初始化参数

VpuDecRetCode VPU_DecGetInitialInfo(VpuDecHandle InHandle, VpuDecInitInfo * pOutInitInfo)

//更新注册帧信息

VpuDecRetCode VPU_DecRegisterFrameBuffer(VpuDecHandle InHandle,VpuFrameBuffer *pInFrameBufArray, int nNum)

//获取解码帧

VpuDecRetCode VPU_DecGetOutputFrame(VpuDecHandle InHandle, VpuDecOutFrameInfo * pOutFrameInfo)

//获取解码帧信息

VpuDecRetCode VPU_DecGetConsumedFrameInfo(VpuDecHandle InHandle,VpuDecFrameLengthInfo* pOutFrameLengthInfo)

//释放帧缓冲区

VpuDecRetCode VPU_DecOutFrameDisplayed(VpuDecHandle InHandle, VpuFrameBuffer* pInFrameBuf)

//释放解码器

VpuDecRetCode VPU_DecFlushAll(VpuDecHandle InHandle)

//关闭解码器

VpuDecRetCode VPU_DecClose(VpuDecHandle InHandle)

//卸载解码器

VpuDecRetCode VPU_DecUnLoad()

//reset解码器

VpuDecRetCode VPU_DecReset(VpuDecHandle InHandle)

//获取内存

VpuDecRetCode VPU_DecGetMem(VpuMemDesc* pInOutMem)

//释放内存

VpuDecRetCode VPU_DecFreeMem(VpuMemDesc* pInMem)

        具体的解码过程在前文已经介绍,这里挑几个重点的函数探究下内部过程。

        VPU_DecOpen函数打开对应的编译器,对应前文讲的codec几个头文件,支持下面的解码器:

HantroHwDecOmx_decoder_create_h264

HantroHwDecOmx_decoder_create_mpeg2

HantroHwDecOmx_decoder_create_mpeg4

HantroHwDecOmx_decoder_create_vc1

HantroHwDecOmx_decoder_create_jpeg

HantroHwDecOmx_decoder_create_webp

HantroHwDecOmx_decoder_create_avs,

HantroHwDecOmx_decoder_create_vp6

HantroHwDecOmx_decoder_create_vp8

HantroHwDecOmx_decoder_create_hevc

HantroHwDecOmx_decoder_create_vp9

        VPU_DecDecodeBuf函数核心解码函数,如下示意图显示了其内部调用关系:

        这样基本就清晰了,可以看到最终调用了内层的decode函数来执行具体的解码过程,这个函数在codec.h中定义如下。

// Decode n bytes of data given in the stream buffer object.

// On return consumed should indicate how many bytes were consumed from the buffer.

//

// The function should return one of following:

//

//    CODEC_NEED_MORE  - nothing happened, codec needs more data.

//    CODEC_HAS_INFO   - headers were parsed and information about stream is ready.

//    CODEC_HAS_FRAME  - codec has one or more headers ready

//    less than zero   - one of the enumerated error values

//

// Parameters:

//

//    CODEC_PROTOTYPE  - this codec instance

//    STREAM_BUFFER    - data to be decoded

//    OMX_U32          - pointer to an integer that should on return indicate how many bytes were used from the input buffer

//    FRAME            - where to store any frames that are ready immediately

CODEC_STATE(*decode)(CODEC_PROTOTYPE *, STREAM_BUFFER *, OMX_U32 *, FRAME *);

        DecGetOutputFrame函数就是获取解码帧数据了。VPU_DEC_OUTPUT_DIS这个信号就可以取数据了。取完数据,使用DecOutFrameDisplayed函数释放掉。

        这样分析一遍wrap和hantro的联系就基本清晰了。

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

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

相关文章

HarmonyOS ArkTSTabs组件的使用(六)

Tabs组件的使用 ArkUI开发框架提供了一种页签容器组件Tabs&#xff0c;开发者通过Tabs组件可以很容易的实现内容视图的切换。页签容器Tabs的形式多种多样&#xff0c;不同的页面设计页签不一样&#xff0c;可以把页签设置在底部、顶部或者侧边。 Tabs组件的简单使用 Tabs组件…

mac添加Chrome插件的方法

如果是.crx的插件 更改后缀crx为zip 后续步骤同下文.zip文件 如果是.zip的插件 使用终端进行解压 注意不要用解压工具解压&#xff0c;一定要用终端&#xff0c;命令行解压 // 进入到“插件名.zip”文件的目录下&#xff0c;输入下面命令&#xff1a; unzip 插件名.zip -…

【项目管理】甘特图(2)——甘特图教程

哈喽啊&#xff0c;你好&#xff0c;我是雷工。 通过上节初步认识了甘特图&#xff0c;本节学习如何一步步创建甘特图&#xff0c;以下为学习笔记。 一、样例展示 下边记录创建甘特图的操作步骤&#xff0c;完成的实际效果如下图所示&#xff1a; 实例图的上端展示项目的重要…

mysql 查询

-- 多表查询select * from tb_dept,tb_emp; 内来链接 -- 内连接 -- A 查询员工的姓名 &#xff0c; 及所属的部门名称 &#xff08;隐式内连接实现&#xff09;select tb_emp.name,tb_dept.name from tb_emp,tb_dept where tb_emp.idtb_emp.id;-- 推荐使用select a.name,b.n…

树与二叉树堆:堆

堆的概念&#xff1a; 一般是把数组的数据在逻辑结构上看成一颗完全二叉树&#xff0c;如下图所示。 注意&#xff1a;别将C语言中的堆和数据结构的堆混为一谈&#xff0c;本文所讲的数据结构的堆是一种完全二叉树&#xff0c;而C语言中的堆其实是一种内存区域的划分 堆的分类…

OpenShift 4 - 部署 RHODS 环境,运行 AI/ML 应用(视频)

《OpenShift / RHEL / DevSecOps 汇总目录》 说明&#xff1a;本文已经在 OpenShift 4.14 RHODS 1.33 的环境中验证 文章目录 RHODS 简介安装 RHODS 环境运行环境说明用 RHODS Operator 安装环境创建 Jupyter Notebook 运行环境 开发调式 AI/ML 应用部署运行 AI/ML 应用视频参…

第十一章 目标检测中的NMS(工具)

精度提升 众所周知&#xff0c;非极大值抑制NMS是目标检测常用的后处理算法&#xff0c;用于剔除冗余检测框&#xff0c;本文将对可以提升精度的各种NMS方法及其变体进行阶段性总结。 总体概要&#xff1a; 对NMS进行分类&#xff0c;大致可分为以下六种&#xff0c;这里是依…

OSG文字-各种文字效果(边框、阴影及颜色倾斜)示例(2)

各种文字效果(边框、阴影及颜色倾斜)示例 各种文字效果(边框、阴影及颜色倾斜)示例的代码如程序清单9-2所示&#xff1a; 1. /* 各种文字效果(边框、阴影及颜色倾斜)示例 */ 2. osg::ref_ptr<osg::Camera> createAllKindText(const string &strDataFolder) 3. {…

火狐挂代理访问问题Software is preventing Firefox from safely connecting to this site

1、报错 Software is preventing Firefox from safely connecting to this site2、解决步骤 火狐浏览器访问http://burp&#xff0c;右上角有下载按钮下载下来证书文件 在 Firefox 中设置证书颁发机构 (CA) 验证

【在飞书捷径中用HTTP请求】

在飞书捷径的请求体中的变量&#xff0c;注意外面要有个双引号。

直播岗位认知篇

一、直播岗位概述 直播岗位&#xff0c;也称为直播主播或直播运营&#xff0c;是指在互联网直播平台上进行直播活动的工作岗位。该岗位的主要职责是通过直播形式&#xff0c;向观众展示自己的才艺、分享生活、销售产品或服务&#xff0c;并引导观众互动和参与。直播主播需要具…

渲染器——双端Diff算法

简单 Diff 算法利用虚拟节点的 key 属性&#xff0c;尽可能地复用 DOM 元素&#xff0c;并通过移动 DOM 的方式来完成更新&#xff0c;从而减少不断地创建和销毁DOM 元素带来的性能开销。但是&#xff0c;简单 Diff 算法仍然存在很多缺陷&#xff0c;这些缺陷可以通过双端 Diff…

GPU Microarch 学习笔记【3】Tensor Core

目录 1. 指令与架构 2. Load 3. 计算MMA 4. Set, Step 与thread group 5. OCTET 6. Tensor Core微架构 7. Final Nvidia自从Volta/Turing&#xff08;2018&#xff09;架构开始&#xff0c;在stream multi processor中加入了tensor core&#xff0c;用于加速矩阵计算。如…

c语言上机作业:迭代法求平方根

1.题目 设计一个函数func用迭代法编程求一个数的平方根。平方根的迭代公式为&#xff1a;牛顿迭代法&#xff0c;(要求前后两次迭代值求差的绝对值小于10的-9次方) 2.思路 a.这里要求我们设置一个函数能够完成牛顿迭代法&#xff0c;这里需要使用到函数迭代的知识&#xff0…

【Java 进阶篇】揭秘 Jackson:Java 对象转 JSON 注解的魔法

嗨&#xff0c;亲爱的同学们&#xff01;欢迎来到这篇关于 Jackson JSON 解析器中 Java 对象转 JSON 注解的详细解析指南。JSON&#xff08;JavaScript Object Notation&#xff09;是一种常用于数据交换的轻量级数据格式&#xff0c;而 Jackson 作为一款优秀的 JSON 解析库&am…

基于SSM的社区生鲜商城的设计与实现

末尾获取源码 开发语言&#xff1a;Java Java开发工具&#xff1a;JDK1.8 后端框架&#xff1a;SSM 前端&#xff1a;采用JSP技术开发 数据库&#xff1a;MySQL5.7和Navicat管理工具结合 服务器&#xff1a;Tomcat8.5 开发软件&#xff1a;IDEA / Eclipse 是否Maven项目&#x…

OpenAI 超 700 名员工联名逼宫董事会;ChatGPT 新功能“阅后即焚”丨 RTE 开发者日报 Vol.89

开发者朋友们大家好&#xff1a; 这里是 「RTE 开发者日报」 &#xff0c;每天和大家一起看新闻、聊八卦。我们的社区编辑团队会整理分享 RTE &#xff08;Real Time Engagement&#xff09; 领域内「有话题的 新闻 」、「有态度的 观点 」、「有意思的 数据 」、「有思考的 文…

相对定位、绝对定位、固定定位、绝对定位堆叠顺序

相对定位&#xff1a;相对自己本身进行偏移 CSS语法&#xff1a; position: relative;/*相对自己进行定位*/ top: 10px;/*距离上边*/ left: 10px;/*距离左边*/ 演示图&#xff1a; 绝对定位&#xff1a;默认以浏览器进行定位。如果想依照父盒子定位&#xff0c;需要在父盒子…

SpringBean的配置详解

Bean的基础配置 例如&#xff1a;配置UserDaoImpl由Spring容器负责管理 <beanid"userDao"class"com.xfy.dao.Impl.UserDaoImpl"></bean> 此时存储到Spring容器中的Bean的beanName是userDao&#xff0c;值是UserDaoImpl&#xff0c;可以根据bea…

P2 C++变量

前言 一 C变量的作用 本期我们来讨论一下c 中的变量。 在一个 C 程序中&#xff0c;大部分内容实际上都是在使用数据。我们操作任何类型的数据&#xff0c;如包括我们想要改变、想要修改&#xff0c; 想要读和写数据。我们都需要把数据存储进叫做变量的东西里面。变量允许我们…