mpp videoframe


原文链接: mpp videoframe

YUV文件转换成VIDEO_FRAME_INFO_S格式的转换问题 - 海思平台开放论坛 - 易百纳论坛 - Powered by Discuz!

u32LStride = u32Stride;
u32CStride = u32Stride;

u32LumaSize = (u32LStride * u32Height);
u32ChrmSize = (u32CStride * u32Height) >> 2;/* YUV 420 */
u32Size = u32LumaSize + (u32ChrmSize << 1);

1
我记得以前看过一个帖子
不要直接使用frame_info->stVFrame.u64VirAddr[0] = (HI_UL)HI_MPI_SYS_Mmap(frame_info->stVFrame.u64PhyAddr[0], size); 中的frame_info->stVFrame.u64VirAddr[0]
最好新建一个指针
unsigned char * pVirAddr = (unsigned char *)HI_MPI_SYS_Mmap( ... );
然后对 unsigned char * pVirAddr进行操作
你试一下

2
打印一下 你图像的长宽 size luma_size chrm_size 以及u32Stride[0] u32Stride[1]看看

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 数据位宽的图像,有些数据格式的存储方式是前 8bit 和后 2bit 分开存储,这里指后 2bit 数据跨距。

    HI_U64              u64HeaderPhyAddr[3];    //压缩头物理地址
    HI_U64              u64HeaderVirAddr[3];
    HI_U64              u64PhyAddr[3];          //虚拟地址。
    HI_U64              u64VirAddr[3];          //虚拟地址。
    HI_U64              u64ExtPhyAddr[3];
    HI_U64              u64ExtVirAddr[3];

    HI_S16              s16OffsetTop;        /* top offset of show area 图像顶部剪裁宽度。*/
    HI_S16              s16OffsetBottom;    /* bottom offset of show area 图像底部剪裁宽度。*/
    HI_S16              s16OffsetLeft;        /* left offset of show area 图像左侧剪裁宽度。*/
    HI_S16              s16OffsetRight;        /* right offset of show area 图像右侧剪裁宽度。*/

    HI_U32              u32MaxLuminance;    //显示图像的最大亮度。
    HI_U32              u32MinLuminance;

    HI_U32              u32TimeRef; //图像帧序列号。
    HI_U64              u64PTS;         //图像时间戳。

    HI_U64              u64PrivateData;
    HI_U32              u32FrameFlag;     /* FRAME_FLAG_E, can be OR operation. */
    VIDEO_SUPPLEMENT_S  stSupplement;
} VIDEO_FRAME_S;

【成员】

    成员名称
    描述
u32Width

图像宽度。

 u32Height
  图像高度。
enField

帧场模式。

 enPixelFormat

视频图像像素格式。

 enVideoFormat

视频图像格式。

 enCompressMode

视频压缩模式。

 enDynamicRange
  动态范围。
enColorGamut

色域范围。

 u32HeaderStride

图像压缩头跨距。

 u32Stride
  图像数据跨距。
u32ExtStride

10bit 数据位宽的图像,有些数据格式的存储方式是前 8bit 和后 2bit 分开存储,这里指后 2bit 数据跨距。

 u64HeaderPhyAddr
  压缩头物理地址
u64HeaderVirAddr

压缩头虚拟地址

 u64PhyAddr
物理地址。

u64VirAddr
虚拟地址。
u64ExtPhyAddr
10bit 数据位宽的图像,有些数据格式的存储方式是前 8bit 和后 2bit 分开存储,这里指后 2bit 数据的物理地 址。
u64ExtVirAddr
10bit 数据位宽的图像,有些数据格式的存储方式是前 8bit 和后 2bit 分开存储,这里指后 2bit 数据的虚拟地 址。

u32TimeRef
图像帧序列号。
U64PTS
图像时间戳。
u64PrivateData
私有数据。
u32FrameFlag
当前帧的标记,使用 FRAME_FLAG_E 里面的值标记, 可以按位或操作。
stSupplement

图像的补充信息。
【注意事项】
 10bit 数据不压缩时在内存中的存储方式是是紧凑排列的。
 10bit YUV 段压缩数据存储是前 8bit 和后 2bit 分开存储。
 10bit tile 64x16 数据(即 VDH 解码之后的数据)不管是压缩还是非压缩,在内存 中的存储方式都是前 8bit 和后 2bit 分开存储。

    【相关数据类型及接口】

定义二维广义图像信息。

定义

typedef struct hiIVE_IMAGE_S
{
HI_U64 au64PhyAddr[3]; /* RW;The physical address of the image /
HI_U64 au64VirAddr[3]; /
RW;The virtual address of the image /
HI_U32 au32Stride[3]; /
RW;The stride of the image /
HI_U32 u32Width; /
RW;The width of the image /
HI_U32 u32Height; /
RW;The height of the image /
IVE_IMAGE_TYPE_E enType; /
RW;The type of the image */
}IVE_IMAGE_S;
1
2
3
4
5
6
7
8
9
成员

成员名称 描述
au64PhyAddr[3] 广义图像的物理地址数组
au64VirAddr[3] 广义图像的虚拟地址数组
au32Stride[3] 广义图像的跨度
u32Width 广义图像的宽度
u32Height 广义图像的高度
enType 广义图像的图像类型
二维广义图像类型表

类型 图像描述 内存地址 跨度
IVE_IMAGE_TYPE_U8C1 8bit 无符号单通道图像 仅用到 IVE_IMAGE_S 中的 au64PhyAddr[0]、au64VirAddr[0] 仅用到 u32Stride[0]
图像描述

如果图片类型为 IVE_IMAGE_TYPE_U8C1 时,n 取 8。

关于对 Width 和 Stride 的理解,请参考 yuv 图像里的stride和plane的解释
2 代码实现

根据上一小节的分析,我们知道 Width 是小于等于 Stride 的。当输入的图片格式是 U8C1 时,图片的 Width 等于 Stride。当然下面的代码也可以进一步简化。
这里的代码是想参考 opencv 的 countNonZero 函数,返回值是灰度值不为0的像素数。同时也打印出各个像素点的灰度值。
但是此方法耗时过长,对720x576的图像处理一次时间为0.28s,推荐使用3 使用海思 IVE 实现 countNonZero

代码

/*
As we all know, au32Stride[0] greater than u32Width
*/
static HI_U32 CountNonZero(IVE_IMAGE_S *pstImg)
{

HI_U16 u16Row;
HI_U16 u16List;
HI_U8* u8copy;      //read
HI_U8* u8origin;    //change line
HI_U16 height;
HI_U16 width;

HI_U16 NonZeroCount = 0;

height = pstImg->u32Height;
width  = pstImg->u32Width;    

u8copy   = (HI_U8 *)(HI_UL)pstImg->au64VirAddr[0];
u8origin = (HI_U8 *)(HI_UL)pstImg->au64VirAddr[0];

for (u16Row = 0; u16Row < height; ++u16Row)
{
    for(u16List = 0; u16List < width; ++u16List)
    {
        printf("%d ", *u8copy);
        if(*u8copy != 0)
        {
            NonZeroCount++;
        }
        u8copy += 1;
    }
    printf("\n");
    u8origin += pstImg->au32Stride[0]; //switch to the next line
    u8copy = u8origin;
}

return NonZeroCount;

}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
效果

先使用 CV 生成一张 64x64 的图像,其中 10~19 行是黑色部分。
#include
#include
#include
#include
#include

using namespace cv;
using namespace std;

int main()
{

Mat image(64, 64, CV_8UC1);

for (int i = 0; i < image.rows; i++)    
{
    uchar* p = image.ptr<uchar>(i);
    for (int j = 0; j < image.cols; j++)
    {
        if (i < 20 && i>=10)     
        {
            p[j] = 0;
        }
        else
        {
            p[j] = 255;
        }
    }
}

imwrite("demo.jpg", image);

return 0;

}

转化为 yuv 格式图像
ffmpeg -i demo.jpg -pix_fmt gray demo.yuv
结果
————————————————
版权声明:本文为CSDN博主「壹贰四六玖」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_40421682/article/details/102989114

`