zoukankan      html  css  js  c++  java
  • 如何获取 VPSS 图像数据

    数据结构

    视频图像帧信息

    typedef struct hiVIDEO_FRAME_INFO_S
    {
        VIDEO_FRAME_S stVFrame; //视频图像帧
        ...
    } VIDEO_FRAME_INFO_S;
    
    

    原始图像帧

    typedef struct hiVIDEO_FRAME_S
    {
        HI_U32              u32Width; //图像宽度
        HI_U32              u32Height; //图像高度
        ...
        PIXEL_FORMAT_E      enPixelFormat; //视频图像像素格式
        VIDEO_FORMAT_E      enVideoFormat; //视频图像格式
        ...
        DYNAMIC_RANGE_E     enDynamicRange;//动态范围枚举
        ...
        HI_U32              u32Stride[3]; //图像数据跨距
        ...
        HI_U64              u64PhyAddr[3]; //图像数据物理地址
        HI_U64              u64VirAddr[3]; //图像数据虚拟地址(内核态)
        ...
    
    } VIDEO_FRAME_S;
    

    enPixelFormat:像素存储格式决定怎么取获取和保存图片,如:yuv、rgb...
    enVideoFormat:这里获取帧数据时要保证格式为VIDEO_FORMAT_LINEAR线性存储的视频格式.
    enDynamicRange:动态范围主要分为 8bit数据 和10bit 数据,它们的保存图片方法存在差异。
    u32Stride:通常图像分配空间大小使用跨距计算。如YUV_400格式:u32Size = u32Stride[0] * u32Height。
    u64VirAddr:这个虚拟地址是内核态的,用户不操作。
    u64PhyAddr:用户要操作图像数据一般将这个物理地址HI_MPI_SYS_Mmap后使用。

    结构还包含其他一些成员,如:帧场模式、压缩模式、色域范围、压缩头信息、10bit数据分开存储信息、裁剪信息、亮度信息、帧号、时间、私有数据标记、补充信息等。

    参考流程

    源码路径 mpp/tools/vpss_chn_dump.c,值得注意的是tools目录下例程前提是外部应用开启了流,即这些代码不包含启动流的初始化。

    1. 设置 VPSS 物理通道属性VPSS_CHN_ATTR_S的队列长度u32Depth。当队列长度为0时取不到帧。
    s32Ret = HI_MPI_VPSS_GetChnAttr(Grp, Chn, &stChnAttr);
    
    stChnAttr.u32Depth = 2;
    s32Ret = HI_MPI_VPSS_SetChnAttr(Grp, Chn, &stChnAttr);
    
    1. 获取帧。
    s32Ret = HI_MPI_VPSS_GetChnFrame(Grp, Chn, &stFrame, s32MilliSec);
    
    1. 这里保存数据需要视频存储格式为线性的,根据动态范围选择对应保存方式。
    if (VIDEO_FORMAT_LINEAR != stFrame.stVFrame.enVideoFormat)
    {
        return;
    }
    
    if (DYNAMIC_RANGE_SDR8 == stFrame.stVFrame.enDynamicRange)
    {
        sample_yuv_8bit_dump(&stFrame.stVFrame, pfd);
    }
    

    以8bit数据的获取图像过程为例。首先需要计算图像帧占字节数,然后将这个大小的物理地址映射到虚拟空间,再把这块空间的数据写到文件,最后解除映射。

    sample_yuv_8bit_dump(VIDEO_FRAME_S *pVBuf, FILE *pfd)
    {
        //计算大小
        if (PIXEL_FORMAT_YUV_400 == pVBuf->enPixelFormat)
            u32Size = (pVBuf->u32Stride[0]) * (pVBuf->u32Height);
    
        //内存映射
        pUserPageAddr[0] = (HI_CHAR *)HI_MPI_SYS_Mmap(phy_addr, u32Size);
    
        //操作数据
        for (h = 0; h < pVBuf->u32Height; h++)
        {
            pMemContent = pUserPageAddr[0] + h * pVBuf->u32Stride[0];
            fwrite(pMemContent, pVBuf->u32Width, 1, pfd);
        }
    
        //解除映射
        HI_MPI_SYS_Munmap(pUserPageAddr[0], u32Size);
    }
    
    
    1. 释放获取的帧。
    s32Ret = HI_MPI_VPSS_ReleaseChnFrame(Grp, Chn, &stFrame);
    
    1. 这里是一个外部dump工具,结束时需要还原属性。
    stChnAttr.u32Depth = u32OrigDepth;
    s32Ret = HI_MPI_VPSS_SetChnAttr(VpssGrp, VpssChn, &stChnAttr);
    
  • 相关阅读:
    WinForm窗口间传值
    如何自定义标签
    oracle数据库开启的时候 是先开监听还是先开主服务,关数据库的时候呢???
    oracle 10g 安装时字符集的选择,和后边的修改
    Oracle数据库安装及配置(一)
    Win7下完全卸载Oracle 11g的步骤
    Oracle创建表空间、创建用户以及授权
    ORACLE创建表空间、创建用户、更改用户默认表空间以及授权、查看权限
    Linux 常用命令集合
    Java之JSP和Servlet基础知识
  • 原文地址:https://www.cnblogs.com/llil/p/14552807.html
Copyright © 2011-2022 走看看