音视频学习之-YUV裸数据

音视频技术分层结构(雷神的图)

1 什么是yuv?

YUV中,Y表示明亮度,也就是灰度值;而U,V则表示色度,用于描述影像色彩及饱和度,用于指定像素的颜色。

  

YUV将亮度信息Y与色彩信息UV分离,没有UV也可以显示完整的黑白图像,并且YUV不像RGB那样要求三个独立的视频信号同时传输,所以用YUV方式传送占用的频宽比RGB小很多(后面代码证明YUV数据量明显比RGB小很多)

2 yuv的采样方式

主流的采样方式有三种,YUV4:4:4,YUV4:2:2,YUV4:2:0

以黑点表示采样该像素点的Y分量,以空心圆圈表示采用该像素点的UV分量。

1 YUV 4:4:4采样,每一个Y对应一组UV分量。

2 YUV 4:2:2采样,每两个Y共用一组UV分量。 

3 YUV 4:2:0采样,每四个Y共用一组UV分量。 

3 yuv的存储方式

YUV的存储格式有两大类:planar和packed。

planar格式:先连续存储所有像素点的Y,紧接着存储所有像素点的U,随后是所有像素点的V。

packed格式: 每个像素点的Y,U,V是连续交叉存储的。

YUYV 格式 (属于YUV422)(packed格式)

YUYV为YUV422采样的存储格式中的一种,相邻的两个Y共用其相邻的两个Cb、Cr,分析,对于像素点Y’00、Y’01 而言,其Cb、Cr的值均为 Cb00、Cr00,其他的像素点的YUV取值依次类推。

UYVY 格式 (属于YUV422)(packed格式)

UYVY格式也是YUV422采样的存储格式中的一种,只不过与YUYV不同的是UV的排列顺序不一样而已,还原其每个像素点的YUV值的方法与上面一样。

YUV422P(属于YUV422)(planar格式)

YUV422P也属于YUV422的一种,它是一种Plane模式,即平面模式,并不是将YUV数据交错存储,而是先存放所有的Y分量,然后存储所有的U(Cb)分量,最后存储所有的V(Cr)分量,如上图所示。其每一个像素点的YUV值提取方法也是遵循YUV422格式的最基本提取方法,即两个Y共用一个UV。比如,对于像素点Y’00、Y’01 而言,其Cb、Cr的值均为 Cb00、Cr00。

YV12,YU12格式(属于YUV420)(planar格式)

YU12和YV12属于YUV420格式,也是一种Plane模式,将Y、U、V分量分别打包,依次存储。其每一个像素点的YUV数据提取遵循YUV420格式的提取方式,即4个Y分量共用一组UV。注意,上图中,Y’00、Y’01、Y’10、Y’11共用Cr00、Cb00,其他依次类推。

NV12、NV21(属于YUV420)(planar格式)

NV12和NV21属于YUV420格式,是一种two-plane模式,即Y和UV分为两个Plane,但是UV(CbCr)为交错存储,而不是分为三个plane。其提取方式与上一种类似,即Y’00、Y’01、Y’10、Y’11共用Cr00、Cb00

YUV文件大计小算

以720×488大小图象YUV420 planar为例,其存储格式是: 共大小为(720×480×3>>1)字节,

分为三个部分:Y,U和V

Y分量: (720×480)个字节 U(Cb)分量:(720×480>>2)个字节 V(Cr)分量:(720×480>>2)个字节

三个部分内部均是行优先存储,三个部分之间是Y,U,V 顺序存储。 即 0--720×480字节是Y分量值, 720×480--720×480×5/4字节是U分量 720×480×5/4 --720×480×3/2字节是V分量。

4 :2: 2 和4:2:0 转换

最简单的方式:

YUV4:2:2 —> YUV4:2:0 Y不变,将U和V信号值在行(垂直方向)在进行一次隔行抽样。 YUV4:2:0 —> YUV4:2:2 Y不变,将U和V信号值的每一行分别拷贝一份形成连续两行数据。

在YUV420中,一个像素点对应一个Y,一个4X4的小方块对应一个U和V。对于所有YUV420图像,它们的Y值排列是完全相同的,因为只有Y的图像就是灰度图像。YUV420sp与YUV420p的数据格式它们的UV排列在原理上是完全不同的。420p它是先把U存放完后,再存放V,也就是说UV它们是连续的。而420sp它是UV、UV这样交替存放的。(见下图) 有了上面的理论,我就可以准确的计算出一个YUV420在内存中存放的大小。 width * hight =Y(总和) U = Y / 4 V = Y / 4。所以YUV420 数据在内存中的长度是 width * hight * 3 / 2,

假设一个分辨率为8X4的YUV图像,它们的格式如下图:

YUV420p数据格式如下图

4 RGB格式

RGB格式比YUV数据量大很多,具体可以参考下面RGB和YUV的转换公式

将RGB24格式像素数据转换为YUV420P格式像素数据

RGB到YUV的转换公式:
Y= 0.299*R+0.587*G+0.114*B

 U=-0.147*R-0.289*G+0.463*B

V= 0.615*R-0.515*G-0.100*B在转换的过程中有以下几点需要注意:

 1) RGB24存储方式是Packed,YUV420P存储方式是Packed。

 2) U,V在水平和垂直方向的取样数是Y的一半

代码如下(雷神的code)


unsigned char clip_value(unsigned char x,unsigned char min_val,unsigned char  max_val){

	if(x>max_val){

		return max_val;

	}else if(x<min_val){

		return min_val;

	}else{

		return x;

	}

}

 

//RGB to YUV420

bool RGB24_TO_YUV420(unsigned char *RgbBuf,int w,int h,unsigned char *yuvBuf)

{

	unsigned char*ptrY, *ptrU, *ptrV, *ptrRGB;

	memset(yuvBuf,0,w*h*3/2);

	ptrY = yuvBuf;

	ptrU = yuvBuf + w*h;

	ptrV = ptrU + (w*h*1/4);

	unsigned char y, u, v, r, g, b;

	for (int j = 0; j<h;j++){

		ptrRGB = RgbBuf + w*j*3 ;

		for (int i = 0;i<w;i++){

			

			r = *(ptrRGB++);

			g = *(ptrRGB++);

			b = *(ptrRGB++);

			y = (unsigned char)( ( 66 * r + 129 * g +  25 * b + 128) >> 8) + 16  ;          

			u = (unsigned char)( ( -38 * r -  74 * g + 112 * b + 128) >> 8) + 128 ;          

			v = (unsigned char)( ( 112 * r -  94 * g -  18 * b + 128) >> 8) + 128 ;

			*(ptrY++) = clip_value(y,0,255);

			if (j%2==0&&i%2 ==0){

				*(ptrU++) =clip_value(u,0,255);

			}

			else{

				if (i%2==0){

				*(ptrV++) =clip_value(v,0,255);

				}

			}

		}

	}

	return true;

}

 

/**

 * Convert RGB24 file to YUV420P file

 * @param url_in  Location of Input RGB file.

 * @param w       Width of Input RGB file.

 * @param h       Height of Input RGB file.

 * @param num     Number of frames to process.

 * @param url_out Location of Output YUV file.

 */

int simplest_rgb24_to_yuv420(char *url_in, int w, int h,int num,char *url_out){

	FILE *fp=fopen(url_in,"rb+");

	FILE *fp1=fopen(url_out,"wb+");

 

	unsigned char *pic_rgb24=(unsigned char *)malloc(w*h*3);

	unsigned char *pic_yuv420=(unsigned char *)malloc(w*h*3/2);

 

	for(int i=0;i<num;i++){

		fread(pic_rgb24,1,w*h*3,fp);

		RGB24_TO_YUV420(pic_rgb24,w,h,pic_yuv420);

		fwrite(pic_yuv420,1,w*h*3/2,fp1);

	}

 

	free(pic_rgb24);

	free(pic_yuv420);

	fclose(fp);

	fclose(fp1);

 

	return 0;

}

上述代码可以看出,RGB24(R G B各占8位)数据量是宽*高*3      转为YUV(Y占8位 UV各占2bit)后数据量小了一半

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值