【音视频系列1】视频格式YUV444、YUV422,、YUV420详解

本篇文章仅介绍YUV444、YUV422、YUV420等使用比较频繁的格式

简介:

YUV,分为三个分量,“Y”表示明亮度(Luminance或Luma),也就是灰度值;而“U”和“V” 表示的则是色度(Chrominance或Chroma),作用是描述影像色彩及饱和度,用于指定像素的颜色。

历史:

Y'UV的发明是由于彩色电视与黑白电视的过渡时期。黑白视频只有Y(Luma,Luminance)视频,也就是灰阶值。到了彩色电视规格的制定,是以YUV/YIQ的格式来处理彩色电视图像,把UV视作表示彩度的C(Chrominance或Chroma),如果忽略C信号,那么剩下的Y(Luma)信号就跟之前的黑白电视频号相同,这样一来便解决彩色电视机与黑白电视机的兼容问题。Y'UV最大的优点在于只需占用极少的带宽。

YUV颜色空间分布:

如果一个图像的宽和高已经确定,那么对于转换后的YUV各个格式的字节占用如下:

  YUV444:表示每一个Y对应一个UV分量(如图),那么YUV对应的个数相同,YUV444所占用空间:即编码字节空间为=宽*高*3  (Y = U = V 宽高均相等)

    【音视频系列1】视频格式YUV444、YUV422,、YUV420详解

  YUV422:表示每两个Y对应一个UV分量,那么Y的个数是UV的个数*2,YUV422那么所占空间:即编码字节空间为=(Y)宽*高 + (U)宽*高*1/2 + (V)宽*高*1/2  = 宽*高*2  (Y宽 = 2*U宽 = 2*V宽,高度YUV相同)

    【音视频系列1】视频格式YUV444、YUV422,、YUV420详解 

   YUV420:表示每4个Y对应一个UV分量,那么Y的个数是UV的个数*4,YUV420那么所占空间:即编码字节空间为=(Y)宽*高 + (U)宽*高*1/4 * (V)宽*高*1/4 = 宽*高*3/2  (Y宽高均为UV宽高的两倍)

    【音视频系列1】视频格式YUV444、YUV422,、YUV420详解

 

分析:

编写C代码分别对各个格式进行读写分析,其中需要把YUV的每个分量保存为Y分量文件 ,此时需要YUV播放的软件,暂时使用YUV player

1:先用ffmpeg转换出3中格式的文件(本文使用图片进行测试:相当于一帧的视频)

  网络获取一张图片,使用ffmpeg生成3种格式的YUV文件,命令如下:

ffmpeg -i test.jpg -pix_fmt yuv444p test_444.yuv
ffmpeg -i test.jpg -pix_fmt yuv422p test_422.yuv
ffmpeg -i test.jpg -pix_fmt yuv420p test_420.yuv

  【音视频系列1】视频格式YUV444、YUV422,、YUV420详解

 2:用C代码读取并分别分离出各个文件的Y、U、V分量文件:

enum YUVTYPE
{
	YUV444,
	YUV422,
	YUV420
};
void read_split_yuvfile(const char* file, int width, int heiht, YUVTYPE yuvtype, int frames) {
	FILE* yuvFp = fopen(file, "rb+");
	FILE* yFp = fopen("E:\\test_y.y", "wb+");
	FILE* uFp = fopen("E:\\test_u.y", "wb+");
	FILE* vFp = fopen("E:\\test_v.y", "wb+");
	unsigned char* buf = NULL;
	int size = width * heiht;
	if (YUV444 == yuvtype)
		buf = (unsigned char*)malloc(size * 3);
	else if (YUV422 == yuvtype)
		buf = (unsigned char*)malloc(size << 1);
	else
		buf = (unsigned char*)malloc(size * 3 >> 1);
	for (int i = 0; i < frames; i++) {
		if (YUV444 == yuvtype) {
			fread(buf, 1, size * 3, yuvFp);
			fwrite(buf, 1, size, yFp);
			fwrite(buf + size, 1, size, uFp);
			fwrite(buf + (size << 1), 1, size, vFp);
		}
		else if (YUV422 == yuvtype) {
			fread(buf, 1, size << 1, yuvFp);
			fwrite(buf, 1, size, yFp);
			fwrite(buf + size, 1, size >> 1, uFp);
			fwrite(buf + (size * 3 >> 1), 1, size >> 1, vFp);
		}
		else {
			fread(buf, 1, size * 3 >> 1, yuvFp);
			fwrite(buf, 1, size, yFp);
			fwrite(buf + size, 1, size >> 2, uFp);
			fwrite(buf + (size * 5 >> 2), 1, size >> 2, vFp);
		}
		
	}
	free(buf);
	buf = NULL;
	fclose(yuvFp);
	fclose(yFp);
	fclose(uFp);
	fclose(vFp);
}

生成文件大小与YUV的分量比相同,YUV444为1:1:1  YUV422为2:1:1  YUV420为4:1:1

由于压缩比较高,所以YUV420使用的比较多,YUV分量图示如下:

 Y:

【音视频系列1】视频格式YUV444、YUV422,、YUV420详解

 

 U:

【音视频系列1】视频格式YUV444、YUV422,、YUV420详解

 

 V:

【音视频系列1】视频格式YUV444、YUV422,、YUV420详解

上一篇:SPARK SQL中自定义udf,udaf函数统计uv(使用bitmap)


下一篇:Django在根据models生成数据库表时报 __init__() missing 1 required positional argument: ‘on_delete‘