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

        前面已经分析了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的联系就基本清晰了。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

值得收藏推荐的 21 款免费数据恢复软件工具

使用这些免费数据恢复工具 之一找回您认为永远消失的文件。我根据这些程序的易用性和提供的功能对这些程序进行了排名。 这些应用程序从您的硬盘驱动器、USB 驱动器、媒体卡等恢复文档、视频、图像、音乐等。我建议每个计算机所有者安装其中一个程序&#xff0c;最好尽快&#…

【MySQL】一些内置函数(时间函数、字符串函数、数学函数等,学会了有妙用)

内置函数 前言正式开始时间函数显示当前日期、时间、日期时间的日期计算相差多少天示例创建一张表&#xff0c;记录生日 留言表 字符串函数charsetconcatinstr(string, substring)ucase和lcaseleft(string, length)length求字符串长度replace(str, search_str, replace_str)tri…

【LeetCode刷题笔记】DFSBFS(一)

51. N 皇后 解题思路: DFS + 回溯 :由于 NxN 个格子放 N 个皇后, 同一行不能放置 2 个皇后,所以皇后必然放置在不同行 。 因此,可以从第 0 行开始,逐行地尝试,在每一个 i

Pyside6/PyQt6的QTreeWidget如何添加多级子项,如何实现选中父项,子项也全部选中功能,源码示例

文章目录 📖 介绍 📖🏡 环境 🏡📒 使用方法 📒📝 数据📝 源码📖 介绍 📖 在UI开发中经常会需要展示/让用户多层级选择,这篇文章记录了一个QTreeWidget如何添加多级子项,如何实现选中父项,子项也全部选中/取消选中功能的源码示例,大家可以举一反三实现自…

合理运用ChatGPT使用Python编写一个桌面便签应用

ChatGPT的编程能力也不差&#xff0c;本次我就一步一步提要求&#xff0c;让ChatGPT根据我的要求&#xff0c;编写出一个可用的&#xff0c;可打包运行的桌面便签。 代码 import sys from PyQt5.QtWidgets import QApplication, QMainWindow, QMenu, QAction, QSystemTrayIco…

php一句话木马免杀

php一句话木马免杀 针对于php一句话木马做免杀&#xff1a; 利用php动态函数的特性&#xff0c;将危险函数拆分成字符&#xff0c;最终使用字符串拼接的方式&#xff0c;然后重新拼接&#xff0c;后加括号执行代码&#xff0c;并且可以使用花指令进行包装&#xff0c;如无限i…

Unity收费对谁影响最大

Unity的收费政策对以下几类人群影响最大&#xff1a; 游戏开发商&#xff1a;Unity收费政策中最直接的影响对象就是游戏开发商。对于那些使用Unity引擎制作游戏的开发商来说&#xff0c;他们将需要考虑新的许可证费用和服务费用&#xff0c;这可能会对他们的盈利和发展产生影响…

springboot项目基于jdk17、分布式事务seata-server-1.7.1、分库分表shardingSphere5.2.1开发过程中出现的问题

由于项目需要&#xff0c;springboot项目需基于jdk17环境开发&#xff0c;结合nacos2.0.3、分布式事务seata-server-1.7.1、分库分表shardingSphere5.2.1等&#xff0c;项目启动过程中出现的问题解决方式小结。 问题一&#xff1a; Caused by: java.lang.RuntimeException: j…

C++ LibCurl实现Web指纹识别

Web指纹识别是一种通过分析Web应用程序的特征和元数据&#xff0c;以确定应用程序所使用的技术栈和配置的技术。这项技术旨在识别Web服务器、Web应用框架、后端数据库、JavaScript库等组件的版本和配置信息。通过分析HTTP响应头、HTML源代码、JavaScript代码、CSS文件等&#x…

【Mysql系列】LAG与LEAD开窗函数

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

visionOS空间计算实战开发教程Day 5 纹理和材质

在​​Day 4​​​中我们使用了​​ImmersiveSpace​​并在其中添加了一个立方体&#xff0c;但对这个立方体我们只配置了长宽高&#xff0c;并没有做进一步的操作。 本文中我们会通过纹理和材质对这个立方体的六个面分别进行不同的绘制。首先我们将​​ImmersiveView​​分拆…

Redis入门与应用

目录 Redis的技术全景 两大维度 三大主线 Redis的版本选择与安装 Redis的linux安装 Redis的启动 默认配置 带参数启动 配置文件启动 操作 停止 Redis全局命令 键名的生产实践 Redis常用数据结构 字符串&#xff08;String&#xff09; 操作命令 set 设置值 g…

XDAG同步节点部署

系统环境要求 JDK : v17 Maven : v3.9.1-v3.9.5 MySQL : v8.0系列 1、MySQL8.0安装 1&#xff09;docker-compose安装详情 MySQL安装 2&#xff09;配置数据库账号密码及键表 # docker exec -it mysql8 /bin/bash # root0286a1fd60e6:/# mysql -uroot -p Enter password:…

Android : ListView + BaseAdapter-简单应用

​​容器与适配器&#xff1a;​​​​​ http://t.csdnimg.cn/ZfAJ7 示例图&#xff1a; 实体类 News.java package com.example.mylistviewbaseadapter.entity;public class News {private String title;private String content;private int img;public News(Str…

Django报错:RuntimeError at /home/ 解决办法

错误提示&#xff1a; RuntimeError at /home/ Model class django.contrib.contenttypes.models.ContentType doesnt declare an explicit app_label and isnt in an application in INSTALLED_APPS. 原因剖析&#xff1a; 博主在使用pycharm创建Django项目的时候&#xff0…

golang 断点调试

1.碰见如下报错,调试器没有打印变量信息 Delve is too old for Go version 1.21.2 (maximum supported version 1.19) 2. 解决办法 升级delve delve是go语言的debug工具。 go install github.com/go-delve/delve/cmd/dlvlatest报错 Get “https://proxy.golang.org/github…

第四代智能井盖传感器:智能井盖监测传感器怎么监测井盖位移

大街小巷的井盖是城市基础设施的重要组成部分&#xff0c;关系到广大市民的生活质量与安全。政府部门始终将其列为重要的建设和管理对象&#xff0c;通过高效的管理和维护&#xff0c;可以增强市民的安全感和幸福感。然而单纯依赖人工检修的方式&#xff0c;无疑会使工作量和工…

31、Flink的SQL Gateway介绍及示例

Flink 系列文章 1、Flink 部署、概念介绍、source、transformation、sink使用示例、四大基石介绍和示例等系列综合文章链接 13、Flink 的table api与sql的基本概念、通用api介绍及入门示例 14、Flink 的table api与sql之数据类型: 内置数据类型以及它们的属性 15、Flink 的ta…

【opencv】计算机视觉:停车场车位实时识别

目录 目标 整体流程 背景 详细讲解 目标 我们想要在一个实时的停车场监控视频中&#xff0c;看看要有多少个车以及有多少个空缺车位。然后我们可以标记空的&#xff0c;然后来车之后&#xff0c;实时告诉应该停在那里最方便、最近&#xff01;&#xff01;&#xff01;实现…

轻量封装WebGPU渲染系统示例<37>- 多个局部点光源应用于非金属材质形成的效果(源码)

当前示例源码github地址: https://github.com/vilyLei/voxwebgpu/blob/feature/rendering/src/voxgpu/sample/BasePbrMaterialMultiLights.ts 当前示例运行效果: 此示例基于此渲染系统实现&#xff0c;当前示例TypeScript源码如下&#xff1a; export class BasePbrMaterial…