像素格式之YUV(基于海思Hisi35xx平台)

Ps:总结归纳一下自己工作中遇到的一些关于YUV格式的知识点和问题。水平有限,写的不太完整,后续会不断完善。如果有错误和不足之处,还请各位不吝赐教。

YUV格式简介

  • YUV,是一种颜色编码方法。YUV,YCbCr,YPbPr等专有名词都可以称为YUV。Y表示亮度、U(Cb)V(Cr)表示色度。
  • YUV是被欧洲电视系统所采用的一种颜色编码方法(属于PAL),是PAL和SECAM模拟彩色电视制式采用的颜色空间。
  • 在现代彩色电视系统中,通常采用三管彩色摄影机或彩色CCD摄影机进行取像,然后把取得的彩色图像信号经分色、分别放大校正后得到RGB,再经过矩阵变换电路得到亮度信号Y和两个色差信号R-Y(即U)、B-Y(即V),最后发送端将亮度和色差三个信号分别进行编码,用同一信道发送出去。这种色彩的表示方法就是所谓的YUV色彩空间表示。采用YUV色彩空间的重要性是它的亮度信号Y和色度信号U、V是分离的。

YUV的存储格式

通常分为:
1.打包(Packed)格式;
像素点的Y、U、V是连续交替存储的。

YUV/YUV/YUV/YUV/YUV/YUV....

2.平面(Planar)格式;
像素点的Y、U、V,是分别连续存储的。相当于将YUV拆成三个平面存储。

YYYYYY/UUUUUU/VVVVVV...

3.平面格式又有Semi-Planar的类别;
像素点的Y是连续存储的,U、V分量是交叉存放的。

YYYYYY/UV/UV/UV/UV/UV/UV...

YUV的采样方式

主流有:
1.YUV444:每一个Y分量对应一组UV分量,平均一个像素占用8+8+8=24位。
2.YUV422:每两个Y分量共用一组UV分量,8+4+4=16位。

YUVY / UYVY / YUV422P / YUY2  ,此处要注意,YUY2是packed打包格式的。

3.YUV420:每四个Y分量共用一组UV分量,8+4+0=12位。

YUV420P :YV12、YU12 是一种Planar格式。两者的区别是:YU12存储顺序是YUV,即YCbCr。YV12,存储顺序是YVU,即YCrCb。
YUV420SP:NV12、NV21 是一种Semi-Planar格式。NV12是IOS的模式,NV12是Android的模式。 其实nv系列,都属于semi-plane系列

4.YUV411:每四个Y分量共用一组UV分量,8+2+2=12位。

此处借用一张图来补充说明三种采样方式的差别:
像素格式之YUV(基于海思Hisi35xx平台)_第1张图片
注意要把YUV的采样方式和存储格式结合起来分析:

对于Planar的YUV格式,Y、U、V分别连续存储。
对于Packed的YUV格式,Y、U、V连续交替存储。

对于每种方式的Size大小,可借鉴以下方式分析:

YUV-sp422:宽(Stride) * 高 * 2
YUV-sp420:宽(Stride) * 高 * 1.5
YUV-400:  宽(Stride) * 高
//YUV-SP422
|-Width(Stride)-|
Y    Y    Y    Y     --    --
Y    Y    Y    Y   Heigth
Y    Y    Y    Y
Y    Y    Y    Y     --
U    V    U    V         Heigth * 2
U    V    U    V
U    V    U    V
U    V    U    V           --

//YUV-SP420
|-Width(Stride)-|
Y    Y    Y    Y     --    --
Y    Y    Y    Y   Heigth
Y    Y    Y    Y
Y    Y    Y    Y     --
U    V    U    V         Heigth * 1.5
U    V    U    V           --

以海思芯片(hisi35xx)为例,在视频处理子系统(VPSS)上,通过接口获取的一帧处理完成的图像,这里我们以NV21的采样格式,SP420的打包格式 来讲。

在通过接口HI_MPI_VPSS_GetChnFrame获得指向视频图像帧信息结构体( VIDEO_FRAME_INFO_S)的指针后,我们需要抽出其中的视频原始图像帧结构( VIDEO_FRAME_S)。
我们可通过该结构获得其中的宽度、高度、像素格式、跨距、物理地址、虚拟地址等信息。

这里讲一下图像跨距(stride)的概念。
不同于图像的宽度,图像跨距又叫扫描宽度,是单行像素(一个扫描行)的宽度。当视频图像存储在内存时,图像的每一行末尾可能包含一些扩展内容,这些扩展的内容只影响图像如何存储在内存中,但是不影响图像如何显示出来。如果每一行像素末尾拥有扩展内容,Stride的值一定大于图像的宽度值。所以在处理一个视频帧时,在计算的时候必须把stride也计算进去。

1.在得到帧图像的各种信息后,首先我们从内存中映射出可供用户进程操作的地址。

HI_VOID* HI_MPI_SYS_MmapCache(HI_U64 u64PhyAddr, HI_U32 u32Size);    
//参数1:需映射的内存单元起始地址。参数2:映射的字节数。

参数1,即图像帧结构中的物理地址。
参数2,即帧图像大小。根据通道属性为YUVsp420,所以这里的Size大小为Stride * Height * 3 / 2。
此接口函数返回的是一个物理地址,这里即Y分量的首地址。可得:

//Y分量的地址   pUserPageAddr为上述接口函数返回值
pVBufVirt_Y = pUserPageAddr; 
//UV分量的地址 Y分量之后才开始UV分量                   
pVBufVirt_C = pVBufVirt_Y + stride * height;    

在得到这些地址之后,我们就可以对图像格式进行转换。具体的转换后续再进行详细记录。
具体方式有:
1.通过Libyuv库进行转换,SP420->P420->YUY2。
2.通过NEON指令转换。 NV21->YUY2。
等。

//V1.0
2019.12.06
1.总结了YUV采样格式、YUV存储方式,已经基于海思平台的简单操作。

你可能感兴趣的:(像素格式)