hisi系列,yuv保存结构体, u64PhyAddr[3]是申请一个结构体类型时,分配的一个物理地址,当保存一帧图片到这个结构体时
这帧图片分配的一端内存首地址,就放在这里,需要读取图片数据时,需要向内核,mmap,转换成虚拟地址
放在 u64VirAddr[3]里,Y,U,V 地址分别放在0,1,2数组里。
u32Stride是每一行占的长度,当设置为32对齐,或256对齐时,根据接入的相机的分辨率,会自动处理进行对齐,如640* 512,720* 576,如果不能满足要求,就回自动填充,进行对齐,对齐的目的应该是32系统,4字节对齐时,提高读取效率,有利于大量数据的图片处理。
u32Stride[0],u32Stride[1],u32Stride[2],分别代表y,u,v的对齐长度,u32Width和u32Stride[0]有可能是一样的长度大小,根据输入分辨率变化而变化。
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];
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;
在开发调试时,有时候需要保存为yuv格式图片,查看图片的情况,可以仿照hisi例程,将yuv数据,写进文件
sample_yuv_8bit_memset(&stFrameSrc.stVFrame, &bufSnap);
static SX_U32 sample_yuv_8bit_memset(VIDEO_FRAME_S* pVBuf, volatile SX_U8 *bufSnap )
{
SX_U32 u32Size=0;
unsigned int h=0;
PIXEL_FORMAT_E enPixelFormat = pVBuf->enPixelFormat;
HI_U32 u32UvHeight = 0;
HI_CHAR *pUserPageAddr=NULL;
char* pVBufVirt_Y=NULL;
char* pVBufVirt_C=NULL;
char* pMemContent=NULL;
u32UvHeight = pVBuf->u32Height / 2;
u32Size= (pVBuf->u32Stride[0]) * (pVBuf->u32Height) * 3 / 2;
pUserPageAddr = (HI_CHAR*) HI_MPI_SYS_Mmap( pVBuf->u64PhyAddr[0], u32Size);
if (HI_NULL == pUserPageAddr)
{
return -1;
}
// snap : copy Y
pVBufVirt_Y = pUserPageAddr;
if( bufSnap != NULL )
{
for( int i = 0; i < pVBuf->u32Height; i++ )
{
memcpy( (SX_U8 *)bufSnap + i*pVBuf->u32Width, pVBufVirt_Y + i*pVBuf->u32Stride[0], pVBuf->u32Width);
}
}
// fill black color
pVBufVirt_C = pVBufVirt_Y + (pVBuf->u32Stride[0]) * (pVBuf->u32Height);
long uvoffset = pVBuf->u32Height * pVBuf->u32Width;
for (h = 0; h < u32UvHeight; h++)
{
pMemContent = pVBufVirt_C + h * pVBuf->u32Stride[1];
memset( pMemContent, 0x80, pVBuf->u32Width);
memcpy( (SX_U8 *)bufSnap + uvoffset + h*pVBuf->u32Width, pMemContent, pVBuf->u32Width);
}
FILE* fd = NULL;
fd = fopen("my.yuv", "wb");
if (HI_NULL == fd)
{
printf("open file err!\n");
}
fwrite((SX_U8 *)bufSnap , pVBuf->u32Width*pVBuf->u32Height * 3 / 2 ,1,fd); //将整个buf的数据写到yuv文件里
fclose(fd);
printf("save file success!\n");
SX_S32 s32Ret = HI_MPI_SYS_Munmap((HI_VOID*)pUserPageAddr, u32Size);
if(HI_SUCCESS != s32Ret)
{
//printf("@@@@@@@@ 1 sample_yuv_8bit_memset unmap fail @@@@@@@@@@\r\n");
}
pVBufVirt_Y=NULL;
pVBufVirt_C=NULL;
pMemContent=NULL;
return 0;
}
将文件拷出来,使用yuvplayer工具,播放图片,如下图,可以设置不同格式的图片。