H.266/VVC技术学习34:视频属性杂谈

1 位、比特、字节的概念

1.1 位(bit)

我们常说的比特,其实就是位。这是计算机中的最小数据单位,一位二进制的数,说白了就是一个0或者1。

1.2 字节(Byte)

字节是存储空间的基本计量单位,1个字节=8个比特,下面我们用英文单位来表示这个等式:1B=8b。这里我们就一定要对大写的B(Byte)和小写的b(bit)进行严格的区分了。
可见,我们定义的东西最小都是8个比特,即256种8位二进制数的排列方式表示的。

因此,我们经常定义的类型,现在可以大致了解他们的大小:
char:1字节,8bit。最常用的ASCII码定义了128个字符,小于256,故可以表示;
int:4字节,32bit,数据范围为-2147483648~2147483647;
long、double等都是同样的道理,这里不再赘述。

1.3 其他

这些就是我们老生常谈的东西了,前面我们知道了1B=8b,后面我们从B开始看一些更大的东西:

KB:1 KB = 1024 B
MB:1 MB = 1024 KB
GB:1 GB = 1024 MB
TB:1 TB = 1024 GB

1.4 和视频相关

在VVC中,编码方式通常设比特深度为10,即用10位来表示一个像素值,故范围就是0~1023了。

2 分辨率、像素的概念

2.1 分辨率

一张图片分辨率是1920x1080,就是说这张图片在屏幕上按1:1放大时,水平方向有1920个像素点(色块),垂直方向有1080个像素点(色块)。

2.2 像素

每张图片都是由色块组成的,每个色块称为一个像素,如1920x1080的图片就有2073600个像素

2.3 像素值

每个像素里面的颜色就是像素值。若要表示颜色,最原始的情况是采用三原色(红、绿、蓝)使用不同的深浅得到各种想要的颜色,后来为了视频压缩的方便,通过计算得到YCbCr。其中Y是亮度,对应黑白电视,这个分量更为重要,而Cb为相应Y的蓝色分量,Cb的b就是blue;Cr为相应Y的蓝色分量,Cr的r就是red。

前面1.4我们提过像素值的范围是0-1023了哦。这里Y,Cb,Cr的值都是0-1023的值。

3 YCbCr通道的4:2:0格式

人眼对Y分量更敏感,对Cb、Cr分量相对没有过高的要求,故进行视频压缩时,可以采用4:2:0取样方法。
在这里插入图片描述
在这里插入图片描述
可见,每4个Y分量共用一组Cb和Cr分量,这样对于Cb和Cr分量,需要表示的面积仅仅是Y分量的1/4,且对人眼影响很小,几乎不会看出瑕疵。

4 yuv文件

4.1 存储方式

yuv文件先将Y分量的像素值存起来,占据整个文件2/3的大小,然后将Cb分量的像素值存起来,占据整个文件1/6的大小,最后将Cb分量的像素值存起来,占据整个文件最后1/6的大小。这样,一个视频的一帧就可以被完整表达出来。

4.2 播放方式

视频主要的功能是用来看的。我们已知了yuv文件的储存方法,那么如何将它播放成视频呢?这里需要SDL来把.yuv“扔”在电脑屏幕上。这里就是一个大的话题了,有兴趣的可以参考雷神博客(向雷神致敬),如果后面还会开这种杂谈的话,会具体谈一谈这个的~

5 计算实例

这是编码得到basketballdrill的一帧(分辨率832x480,比特深度为10bit):
在这里插入图片描述
下面我们来计算得出这个大小:
比特深度为10,而字节是存储空间的基本计量单位,10位要占用2字节。故一个通道的一个像素都要占用2字节来存储像素值。
分辨率是832x480,则Y分量共有832x480个像素值,Cb和Cr分别有416x240个像素值。
综上,这里的1198080的来源就是:

Y: 832x480x2 = 798720;
Cb:416x240x2 = 199680;
Cr:416x240x2 = 199680

以上三者相加,得出结果:1198080。

思考:
以下问题请读者自行考虑:
1、如果比特深度为8,为什么大小减小了一半?
2、比特深度为9或10,视频的大小都是一样的,那为何不使用比特深度为16进行视频的编码?

6 比特深度从10转8

带着上面的问题1,我们继续深入内存中,我们探究一下存储像素值的方式:
以比特深度10为例,像素值256将会以下面的方式存储:00000001 00000000,特别要注意的是,如果将其按char类型8位数组tmp的方式存储,则tmp[1]并非按上面的顺序得到的00000000,而是前面的00000001,tmp[0]才是00000000。这里可能需要读者暂停思考下,因为C语言的逻辑顺序和底层内存并不相同哦。
下面我们要做的是把10比特转换成8比特,那么256这个值应当变成256/4即64。我想,到了这里大家应该都会明白计算的方式了,前面我们知道10比特深度高位的8位只有最后2位有值,将其左移8位得到的数值加上低位的8位即可得到真正的10比特深度像素值,那么接下来除以4就可以将其“下采样”成8比特深度的yuv图片。
举个例子:还是上面的256,高位上tmp[1] = 1,左移8位变为256,加上低位的0依然等于256,除以4等于64,这就是8比特深度下的256的像素值。

YUVBitConvert(int width, int height, short *yuv)//10bit深度,像素值应使用short
{
	unsigned char* yuv10 = new unsigned char[width * height * 3];	
	memcpy(yuv10, yuv, width * height * 3 * sizeof(unsigned char));

	unsigned char* yuv8  = m_yuv;
	for (int i = 0; i < height * width * 3 / 2; ++i) //由10变成8,每个像素值都少了一位
	{
		yuv8[i] = (yuv10[2 * i] + yuv10[2 * i + 1] << 8) >> 2;
	}

	delete yuv10;
	yuv10= NULL;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值