【音視頻系列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 寬高均相等)

    

  YUV422:表示每兩個Y對應一個UV分量,那么Y的個數是UV的個數*2,YUV422那么所占空間:即編碼字節空間為=(Y)寬*高 + (U)寬*高*1/2 + (V)寬*高*1/2  = 寬*高*2  (Y寬 = 2*U寬 = 2*V寬,高度YUV相同)

     

   YUV420:表示每4個Y對應一個UV分量,那么Y的個數是UV的個數*4,YUV420那么所占空間:即編碼字節空間為=(Y)寬*高 + (U)寬*高*1/4 * (V)寬*高*1/4 = 寬*高*3/2  (Y寬高均為UV寬高的兩倍)

    

 

分析:

編寫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

  

 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:

 

 U:

 

 V:


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM