Andriod下的硬编码和解码

关于音视频基础知识

视频

平常我们看到的视频格式其实上容器封装格式,即将音频和视频进行封装。当播放器进行播放时,通过解封这个容器拿出视频数据和音频数据分别进行解码,同步控制,再而通过不同的硬件去表现。比如mp4avi等都是封装格式。

实际上无关乎音频的话,那就是编码压缩格式,比如h264。视频的其实是每秒30帧的图片进行播放而营造的效果。也就是说一秒会有30张图片,而一张图片如果不压缩的话,按照RGB的方式存储一个像素三个字节,那么一个1920x720的分辨率将会有5MB,光是大概算下一张图片就有这么大,那么一秒,乃至两个小时视频那就会更大了。所以就要进行编码压缩。

颜色空间

参考:YUV格式

RGB

在图片上的像素点通过RGB三色通道来制造颜色,这样的话大概需要三个字节。

YUV

YUV也是一中颜色空间,其中Y代表的亮度,UV控制颜色。YUV是可以通过矩阵计算和RGB进行互换的。如果一张YUV的图片的像素只有Y数据的话,整体上就表现为一张黑白的图片。

YUV的表现格式

想象下我们有张黑白的图片即拥有Y向量,然后我们UV向量可以有选择给像素加上,可以理解为上色

YUV444

每个像素拥有完整Y、U、V分量,和RGB一样占三个字节,只不过计算不同而已

上色精确到每个像素点。

YUV422

两个像素共用一个UV分量。也就是说我们上色不精确到每个像素点了,而是每两个像素点,这么以来,占用的存储空间少了很多。比如4个像素,本来是4x3,现在的话4x1(Y) + 2x1(U) + 2x1(V)

YUV420

四个像素公用一个UV分量。同样上色变成了4个像素点上同样的UV分量。这么以来占用的空间又少了。

4x1(Y) + 1(U) + 1(V)

YUV的存储格式

上面的只是颜色表现方式,落实到具体的存储的话。又分为了好几种

packet

YUV数据在实际的字节数组中是连续交错存放。细分不同的格式也只是YUV存放不同而已。

1
VYUY422 V1 Y1 U1 Y2 V2 Y3 U2 Y4 ....

planar

Y、U、V分隔开连续存储

1
2
3
YYYY
UU
VV

SemiPlanar

Y连续存储,UV叫错存储

1
2
YYYY
UVUV

常见的存储格式解释

1
2
3
4
5
6
7
I420: YYYYYYYY UU VV =>YUV420P

YV12: YYYYYYYY VV UU =>YUV420P

NV12: YYYYYYYY UVUV =>YUV420SP

NV21: YYYYYYYY VUVU =>YUV420SP

RGB与YUV格式互转

RGB 转 YUV

1
2
3
Y = (0.257 * R) + (0.504 * G) + (0.098 * B) + 16
Cr = V = (0.439 * R) - (0.368 * G) - (0.071 * B) + 128
Cb = U = -( 0.148 * R) - (0.291 * G) + (0.439 * B) + 128

YUV转RGB

1
2
3
B = 1.164(Y - 16) + 2.018(U - 128)
G = 1.164(Y - 16) - 0.813(V - 128) - 0.391(U - 128)
R = 1.164(Y - 16) + 1.596(V - 128)

编码

解码

合成与解封