前言
YUV与RGB是两种不同的颜色空间,视频一般都用YUV来进行存储,因为相同分辨率的视频RGB占用空间为YUV420的1.5倍
YUV的采样方式YUV根据采样方式的不同,其占用大小也不一样,主流有如下三种
- YUV444 每一个Y对应一组UV分量,即:一个YUV占8+8+8 = 24bits,3个字节。
- YUV422 每两个Y共用一组UV分量,即:一个YUV占8+4+4 = 16bits 2个字节。
- YUV420 每四个Y共用一组UV分量,即:一个YUV占8+2+2 = 12bits 1.5个字节。
因为YUV420占用空间最小,所以目前主流都是使用的YUV420方式,它根据存储方式的不同又分为YUV420P和YUV420SP两种 1、YUV420P 称为planer平面模式,Y ,U,V分别位于三个不同平面。一般在内存中按照如下方式存储:YYYY.....U......V.......或者YYYY.....V......U.......;
- I420:又叫YU12,是按照YUV顺序存储的,安卓摄像头视频录制的视频就支持这种存储方式 存储方式为:亮度(行×列) + U(行×列/4) + V(行×列/4)
- YV12:是按照YVU的顺序存储的 存储方式为:亮度(行×列) + V(行×列/4) + U(行×列/4)
planner格式的YUV420拿到每一个YUV像素的伪代码为(C语言):
2、YUV420SP 称为双-planner平面模式,用两个平面存储YUV,其中Y存储于一个平面,UV存储于另一个平面。一般在内存中按照如下方式存储:YYYY........U......V.......或者YYYY........UVUV.......
- NV12:存储顺序是先存Y,再UV交替存储。YYYYUVUVUV;iOS系统采用此种方式 存储方式为:亮度(行×列) + UV(行×列/2)
- NV21:存储顺序是先存Y,再存U,再VU交替存储。YYYYVUVUVU;按照系统采用此种方式 存储方式为:亮度(行×列) + VU(行×列/2) 双-planner平面模式分离出YUV的伪代码为(C语言,以NV12为例):
// 这里代表 y和uv的数据内存块
uint_8 *ybuf,uvbuf;
// 代表视频的宽高
int width,height;
for(int y = 0; y < height; y++) {
uint8_t *yBufferLine = ybuf+y * width;
// y/2能保证每四个YYYY对应一组uv
uint8_t *cbCrBufferLine = uvbuf + (y >> 1) * width;
for(int x = 0; x < width; x++) {
uint_8 y = yBufferLine[x];
uint_8 cb = cbCrBufferLine[x & ~1] ;
uint_8 cr = cbCrBufferLine[x | 1];
}
}