前言

  上一篇已经将himpp套入qt的基础上进行开发。那么qt中拿到frame则是很关键的交互,这是qt与海思可能编解码交叉开发的关键步骤。

 

受限制

  因为直接配置sample的vi比较麻烦,确实是困难的,其实就是配置驱动,所以我们只能从开发板的demo入手,去在相等条件下探测可能的留,从vpss中拿取后,进行软编码。
  当然,如果不用qt还有一种方式,也就是大量开发海思人员使用的方式,是基于sample写一个编码程序,然后使用本地socket交互,其实绝大部分海思开发者都是这样开发的,但是他们不涉及与qt的深入交互。

 

前提条件

  需要移植ffmpeg到海思平台,可参考博文《FFmpeg开发笔记(十):ffmpeg在ubuntu上的交叉编译移植到海思HI35xx平台》。

 

Demo演示

  从vpss中获取一帧图像,如下图:
  
  

 

相关的API

  (原本整理了一大半自己的习惯格式,后续海思看多了,觉得海思文档也还行,就是争对性的开发,无用信息有点多,所以此处还是用海思的文档,但是只提取涉及的部分,海思文档是个庞大的体系,需要动手,光看是很难理解的)。

HI_MPI_VPSS_GetChnFrame:从通道获取一帧处理完的数据

  用户从通道获取一帧处理完成的图像,必须与HI_MPI_VPSS_ReleaseChnFrame()配对使用。

函数原型

HI_S32 HI_MPI_VPSS_GetChnFrame(VPSS_GRP VpssGrp,
VPSS_CHN VpssChn,
VIDEO_FRAME_INFO_S *pstVideoFrame,
HI_S32 s32MilliSec);
  • 参数一:VpssGrou,通道组号,海思芯片通道号,
    取值[0, VPSS_MAX_GRP_NUM];
  • 参数二:VpssChn,通道号,通道组下的通道号,
    取值[0, VPSS_MAX_CHN_NUM];
  • 参数三:pstVideoFrame,帧数据的结构体,要取的数据就在这个帧里面,这
    是很关键的结构体,稍后是会深入讲解的重点;
  • 参数四:s32MilliSec,阻塞时间,跟其他阻塞有点区别,-1为阻塞,0为直
    接获取,其他整数位等待的超时时间。

返回值

   

其他注意

  

HI_MPI_VPSS_ReleaseChnFrame:释放一帧图像

  释放之前通过HI_MPI_VPSS_GetChnFrame获取获取的图像。

函数原型

HI_S32 HI_MPI_VPSS_ReleaseChnFrame (VPSS_GRP VpssGrp,
VPSS_CHN VpssChn,
const VIDEO_FRAME_INFO_S *pstVideoFrame);
  • 参数一:VpssGrou,通道组号,海思芯片通道号,
    取值[0, VPSS_MAX_GRP_NUM],之前获取使用的是哪个就哪个;
  • 参数二:VpssChn,通道号,通道组下的通道号,
    取值[0, VPSS_MAX_CHN_NUM];之前获取使用的是哪个就哪个;
  • 参数三:pstVideoFrame,帧数据的结构体,要取的数据就在这个帧里面,这
    是很关键的结构体,稍后是会深入讲解的重点;

返回值

  

其他注意

   

 

相关的结构体

VIDEO_FRAME_INFO_S:定义视频图像帧信息结构体

结构体原型

typedef struct hiVIDEO_FRAME_INFO_S
{
VIDEO_FRAME_S stVFrame; // 视频图像帧
HI_U32 u32PoolId; // 视频缓存池ID
MOD_ID_E enModId; // 当前帧数据是由哪一个硬件逻辑模块写出的
} VIDEO_FRAME_INFO_S;

VIDEO_FRAME_S:定义视频原始图像帧结构体

结构体原型

typedef struct hiVIDEO_FRAME_S
{
HI_U32 u32Width; // 图像宽度
HI_U32 u32Height; // 图像高度
VIDEO_FIELD_E enField; // 帧场模式
PIXEL_FORMAT_E enPixelFormat; // 视频图像像素格式
VIDEO_FORMAT_E enVideoFormat; // 视频图像格式
COMPRESS_MODE_E enCompressMode; // 视频压缩模式
DYNAMIC_RANGE_E enDynamicRange; // 动态范围
COLOR_GAMUT_E enColorGamut; // 色域范围
HI_U32 u32HeaderStride[3]; // 图像压缩头跨距
HI_U32 u32Stride[3]; // 图像数据跨距
HI_U32 u32ExtStride[3]; // 10bit数据位宽的图像,部分格式分开存
HI_U64 u64HeaderPhyAddr[3]; // 压缩头物理地址
HI_U64 u64HeaderVirAddr[3]; // 压缩头虚拟地址,内核态虚拟地址
HI_U64 u64PhyAddr[3]; // 图像数据物理地址
HI_U64 u64VirAddr[3]; // 图像数据虚拟地址,内核态虚拟地址
HI_U64 u64ExtPhyAddr[3]; // 10bit数据位宽度的图像,部分格式分开存
HI_U64 u64ExtVirAddr[3]; // 10bit数据位宽度的图像,部分格式分开存
HI_S16 s16OffsetTop; // 图像顶部剪裁宽度
HI_S16 s16OffsetBottom; // 图像底部剪裁宽度
HI_S16 s16OffsetLeft; // 图像左侧剪裁宽度
HI_S16 s16OffsetRight; // 图像右侧剪裁宽度
HI_U32 u32MaxLuminance; // 显示图像的最大亮度
HI_U32 u32MinLuminance; // 显示图像的最小亮度
HI_U32 u32TimeRef; // 图像帧序列号
HI_U64 u64PTS; // 图像时间戳
HI_U64 u64PrivateData; // 私有数据
HI_U32 u32FrameFlag; // 当前帧的标记,使用FRAME_FLAG_E标记
VIDEO_SUPPLEMENT_S stSupplement; // 图像的补充信息
} VIDEO_FRAME_S;

其他注意

  

 

相关枚举

VIDEO_FIELD_E:帧场模式

  

PIXEL_FORMAT_E:视频图像像素格式

  
  

VIDEO_FORMAT_E:视频图像格式

  

COMPRESS_MODE_E:视频压缩模式

  

DYNAMIC_RANGE_E:动态范围

  

COLOR_GAMUT_E:色域范围

  

VIDEO_SUPPLEMENT_S:图像的补充信息

  

 

Demo

void HiMppManager::testGetVPssFrame()
{
VIDEO_FRAME_INFO_S videoFrameInfoS;
#if 0
// 搜索开开发板用了哪个通道(应该只有2个摄像头,绑定了vpss)
// 结果:探测到开发板在snap抓图模式下在通道组0通道0下有图片
for(int groupIndex = 0; groupIndex < VPSS_MAX_GRP_NUM; groupIndex++)
{
for(int channelIndex = 0; channelIndex < VPSS_MAX_CHN_NUM; channelIndex++)
{
HI_S32 s32MilliSec = 100;
HI_S32 ret = HI_MPI_VPSS_GetChnFrame(groupIndex, channelIndex, &videoFrameInfoS, s32MilliSec);
if(ret == 0)
{
LOG << QString("Succeed to get HI_MPI_VPSS_GetChnFrame(%1, %2, &videoFrameInfoS, %3)")
.arg(groupIndex)
.arg(channelIndex)
.arg(s32MilliSec);
break;
#if 0
}else{
LOG << QString("Failed to get HI_MPI_VPSS_GetChnFrame(%1, %2, &videoFrameInfoS, %3): %4")
.arg(groupIndex)
.arg(channelIndex)
.arg(s32MilliSec)
.arg(ret);
#endif
} }
}
#endif
while(HI_MPI_VPSS_GetChnFrame(0, 0, &videoFrameInfoS, -1) == 0)
{
LOG << "get frame";
LOG << videoFrameInfoS.stVFrame.enPixelFormat
<< "PIXEL_FORMAT_YVU_PLANAR_420:" << (int)PIXEL_FORMAT_YVU_PLANAR_420
<< "PIXEL_FORMAT_YVU_SEMIPLANAR_420:" << (int)PIXEL_FORMAT_YVU_SEMIPLANAR_420;
LOG << videoFrameInfoS.stVFrame.enVideoFormat;
HI_MPI_VPSS_ReleaseChnFrame(0, 0, &videoFrameInfoS);
LOG << "release frame"; }
}
 

入坑

入坑一:获取vpss图像一定帧数后无法再获取

问题

  使用海思sdk获取图像后,多次获取后,大概20次左右就获取失败了。

原因

  海思获取图像后,需要释放,是占用了缓存区。
  海思的HI_MPI_VPSS_GetChanFrame与Hi_MPI_VPSS_ReleaseChnFrame要成对使用。

解决方法

  

Hi3516开发笔记(十):Qt从VPSS中获取通道图像数据存储为jpg文件的更多相关文章

  1. 【Qt开发】关于Qt应用程序中的堆栈、静态存储区的使用错误

    [Qt开发]关于Qt应用程序中的堆栈.静态存储区的使用错误 标签:[Qt开发] 最近终于又碰到了这个问题,想在main函数中定义一个局部大的数组,结果运行就报错,尼玛!刚开始真的不知道到发生了什么,后 ...

  2. sitecore开发入门之如何在代码中获取SITECORE图像URL

    using Sitecore; using Sitecore.Data.Items; using Sitecore.Resources.Media; public string GetUrl() { ...

  3. Hi3516开发笔记(一):海思HI3516DV300芯片介绍,入手开发板以及Demo测试

    前言   目前主流国产芯片为RV11XX.RK33XX.Hi35XX系列,本系列开启Hi3516系列的开发教程.   Hi3516DV300芯片介绍   Hi3516DV300为专业行Smart IP ...

  4. Hi3516开发笔记(四):Hi3516虚拟机编译uboot、kernel、roofts和userdata以及分区表

    若该文为原创文章,转载请注明原文出处本文章博客地址:https://hpzwl.blog.csdn.net/article/details/121572767红胖子(红模仿)的博文大全:开发技术集合( ...

  5. Hi3516开发笔记(六):通过HiTools使用USB/串口将uboot、kernel、roofts和userdata按照分区表烧写镜像

    若该文为原创文章,转载请注明原文出处本文章博客地址:https://hpzwl.blog.csdn.net/article/details/121706033红胖子(红模仿)的博文大全:开发技术集合( ...

  6. Hi3516开发笔记(二):Hi3516虚拟机基础环境搭建之串口调试、网络连接以及sftp文件传输

    前言   搭建Hi3516的基础虚拟机,为交叉编译环境搭建前期工作.后续会编译一个基本的C语言程序Demo,在HI3516上跑.   虚拟机   开发本对虚拟机做了一些基本要求,如下图:    其实重 ...

  7. [OpenCV Qt教程] 在Qt图形界面中显示OpenCV图像的OpenGL Widget (第一部分)

    本文译自:http://www.robot-home.it/blog/en/software/tutorial-opencv-qt-opengl-widget-per-visualizzare-imm ...

  8. IOS开发数据存储篇—IOS中的几种数据存储方式

    IOS开发数据存储篇—IOS中的几种数据存储方式 发表于2016/4/5 21:02:09  421人阅读 分类: 数据存储 在项目开发当中,我们经常会对一些数据进行本地缓存处理.离线缓存的数据一般都 ...

  9. Android编程中的5种数据存储方式

    Android编程中的5种数据存储方式 作者:牛奶.不加糖 字体:[增加 减小] 类型:转载 时间:2015-12-03我要评论 这篇文章主要介绍了Android编程中的5种数据存储方式,结合实例形式 ...

随机推荐

  1. jQuery其他操作与bootstrap框架

    目录 标签操作 样式操作 位置操作 文本值操作 属性操作 文档处理 事件操作 常见事件 克隆案例 悬浮事件hover() 监听input输入值事件 阻止后续事件 事件委托 动画效果 bootstrap ...

  2. python之数据类型的内置方法(str, list)

    目录 字符串的内置方法 移除首尾指定字符 字母大小写相关操作 判断字符串的开头或结尾是否是指定字符 字符串特殊的输出方法 拼接字符串 替换指定字符 判断是否是纯数字 查找指定字符对应的索引值 文本位置 ...

  3. 07makefile文件

    makefile 规则: 目标: 依赖 (tab)命令 第一个版本: main: main.c fun1.c fun2.c sum.c gcc -o main main.c fun1.c fun2.c ...

  4. 历经70+场面试,我发现了大厂面试的bug,并总结其中心得

    想起了学弟在去年秋招时面试了50余家,加上暑期实习面试了20余家,加起来也面试了70余场. 基本把国内有名的互联网公司都面了一遍,不敢说自己的面试经验很丰富,但也是不差的. 这次专门把大厂的面试做了个 ...

  5. 阿里巴巴开源限流组件Sentinel初探

    1 Sentinel主页 https://github.com/alibaba/Sentinel/wiki/主页 1.1 Sentinel介绍 随着微服务的流行,服务和服务之间的稳定性变得越来越重要. ...

  6. Ubuntu,CenOS等Linux系统更改环境变量方法,以安装anaconda为例

    [环境配置的原因] 在windows系统下,很多软件的安装都需要设置环境变量,比如安装JAVA JDK.如果不安装环境变量,在非软件安装的目录下运行javac命令,将会报告"找不到文件&qu ...

  7. 2020.09.12【NOIP提高组&普及组】模拟赛C组 总结

    总结:这次比赛成绩并不理想,虽然策略得当 \(P.S.\):太多题有多组数据,但是样例只有一个数据 各题题解和改题情况 T1 匹配 题面 描述 给你一个由{a,b-z,A,B-.Z}组成的字符串,我们 ...

  8. Eclipse for Python开发环境部署

    Eclipse for Python开发环境部署 工欲善其事,必先利其器. 对开发人员来说,顺手的开发工具必定事半功倍.自学编程的小白不知道该选择那个开发工具,Eclipse作为一个功能强大且开源免费 ...

  9. 2.shell脚本99乘法表

    shell脚本99乘法表 [root@localhost data]# vim cf.sh

  10. 1.为什么要从古典概率入门概率学《zobol的考研概率论教程》

    在入门概率论与数理统计这门课中,刚开始我们都会从古典概率开始学习,为什么要选择它呢?这是因为古典概率作为一种将生活中的事情简化为有限种情况,并假设它们的发生可能差不多的手段,十分的好用且简洁. 这里我 ...