移动开发中关于视频的一些基本概念

颜色编码

视频,本质上就是一连串的静态图片的播放过程。因此我们对于视频的的讨论都可以回到图片中去。

对于图片而言,可以分为两种颜色编码方法来表示图片:RGB和YUV。

RGB

现如今我们使用的屏幕设备都是RGB屏幕,主要有红,绿,蓝三种原色组成,其他的所有颜色都是这三种颜色通过比例组合而成。

移动开发中关于视频的一些基本概念

由于RGB设备的普及,所以图片/视频的展示都是使用RGB的颜色编码方法来展示的。

但是我们都知道一张RGB图片占用的磁盘空间有多大,假如1920×1080的图片,单个像素格式为RGB_888,就是一个像素占位24bit,那么一张图片的大小则是:

size = 1920x1080x3 byte = 5.93M

YUV颜色编码的图片则可以实现RGB近似的效果占用空间却明显小于后者,它也是视频在存储时的主要颜色编码形式。

YUV

不同于RGB的颜色分类方法,YUV则是把颜色分为亮度和色度。

Y指的是亮度(luma,Luminance),U,V则指的是色度,这种编码方法在不同的领域名称上会有细微的差别:比如YCbCr,Y’UV,YPbPr,这些都可以统称为YUV,一般YUV/Y‘UV都用于编码电视信号(模拟信号),而YCbCr则用于编码数字图像。在本文中我们说到YUV时,主要指的是YCbCr。

Y:亮度分量,(可以理解为图像的黑白部分)

Cb:色度的蓝色分量,(照片蓝色部分去掉亮度Y)

Cr:色度的红色分量,(照片红色部分去掉亮度Y)

一张图片通过YUV编码方式进行分离后的效果如下:

移动开发中关于视频的一些基本概念

关于YUV,如果对于YUV取值范围进行细分还可以分为两种类型:

  • TV range(Limit range):Y∈[16,235],Cb∈[16-240] ,Cr∈[16-240] ,主要是广播电视采用的数字标准。
  • Full range:Y、Cb、Cr∈[0-255] ,主要是PC端采用的标准,所以也称PC range。

YUV与RGB的转换

YUV和RGB这两种颜色编码方法是可以相互转换的,也就是知道其中一个就可以求取另一个,而而且这个转换方法是由国际相关组织提供的一些固定的公式(当然不同版本不同类型的协议公式有所不同):

以根据ITU-R BT.601 标准为例

在TV Range的的范围下

移动开发中关于视频的一些基本概念

// TV Range
RGB to YUV:  
Y = 0.299R+0.587G+0.114B   // Y本质上就是从原图得到的一张灰度图
Cr = V = 0.713(R−Y)=0.500R−0.419G−0.081B  
Cb = U = 0.564(B−Y)=−0.169R−0.331G+0.500B

YUV to RGB:  
R = 1.164(Y−16)+1.596(V−128)  
G = 1.164(Y−16)−0.813(V−128)−0.391(U−128)  
B = 1.164(Y−16)+2.018(U−128)



//RGB的范围是[0,255],Y的范围是[16,235],UV的范围是[16,239]

同样的标准下,Full range的公式则有所不同用:


RGB to YUV:  
Y = 0.299 * R + 0.587 * G + 0.114 * B      
Cr = V = -0.169 * R - 0.331 * G + 0.500 * B  
Cb = U = 0.500 * R - 0.439 * G - 0.081 * B

YUV to RGB:  
R = Y + 1.400V - 0.7  
G = Y - 0.343U - 0.711V + 0.526  
B = Y + 1.765U - 0.883

// RGB的范围是[0,255],Y的范围是[0,255],UV的范围是[0,255]

YUV采样方法

经过大量研究实验表明,视觉系统对色度的敏感度远小于亮度,因此再编码YUV图片时,常常会保证Y分量数据不变,相应比例减少U V分量的数据,但是图像的质量基本不会改变。

  • 4:4:4表示4个Y,对应4个Cb以及4个Cr。
    • 完全采样,占用空间size=wh3 byte
  • 4:2:2 表示4个Y,对应2个Cb以及2个Cr。
    • size=wh2 byte,节省1/3空间
  • 4:2:0 表示4个Y,对应1个Cb以及1个Cr。
    • size=wh1.5 byte 节省1/2的空间
  • 4:1:1 表示4个Y,对应1个Cb以及1个Cr。
    • size = wh1.5 byte 节省1/2的空间

以上几种采样方法,YUV420是视频图片帧中最常用的采样比例,在这个比例下,存储空间节省一半,但是图片质量变化不大。

YUV存储方式

对于YUV数据,有两种存储方式:

  • packed format
    • 紧缩格式是把数据混合在一起,交错存储。比如yuv422 packed可能是这样的

移动开发中关于视频的一些基本概念

  • Planar format(主要的)
    • 平面格式则是把不同的分量数据分开存储:先连续存储所有的Y,在连续存储所有的U,然后V……(下面的例子主要以palanar为主)

YUV存储格式

根据不同的采样方式以及不同的存储方式,可以生成不同的YUV存储格式。比如YV12/I420/YU12/NV12/NV21 都属于 YUV420。

YUV格式有YUY2、YUYV、YVYU、UYVY、AYUV、Y41P、Y411、Y211、IF09、IYUV、YV12、YVU9、YUV411、YUV420等,其中比较常见的YUV420分为两种:YUV420P和YUV420SP。

YV12/I420/YU12

YV12与YV12都称为YUV420P(Planar格式),表示他们都是4:2:0,而且是Planar的存储方式。他俩的区别在于在分开存储时,u分量和v分量谁在前面(Y分量总是在最前面)。

存储示意图

  • YU12: YYYYYYYY UU VV
  • YV12: YYYYYYYY VV UU

YU12格式在Android平台中也称作I420

YU12/I420存储格式

移动开发中关于视频的一些基本概念

YV12存储格式

YV12的存储方式就是把上图中的U和V分量的存储位置对调即可。

NV21/NV12格式

这两种格式都属于YUV420SP(Semi-Planar)格式,这种格式和planar类似,但是UV分量时交错存储的。

因此NV21和NV12的区别主要在于UV分量交错存储时,谁在前面:

  • NV12: YYYYYYYY UVUV
  • NV21: YYYYYYYY VUVU

NV12存储格式

移动开发中关于视频的一些基本概念

NV21存储格式

在NV12的基础上,把U和V的分量位置对调即可

虽然YUV的存储格式繁多但是对于一般的开发者而言,掌握了上述几种基本可以满足需要了。

小结

显示RGB

存储YUV

视频基本概念

复用(封装)与解复用(解封装)

  • muxer(复用)

    • 把音频,视频,字幕合并到一个封装格式中 .在Android中实现复用的是MediaMuxer
  • demuxer(解复用)

    • 从媒体封装格式把视频,音频,字幕等拆分开来,在Android中,实现解复用的是MediaExtractor

帧率

即视频在一秒钟之内的帧数,电影一般24,手机设备录制一般30,60。

帧类型

视频中存在三种帧,I帧,P帧,B帧:

  • I帧: 也称关键帧,依靠自身的数据即可解码出一帧图像。编码压缩比例不高
  • P帧:预测帧,利用时间和空间的相关性,依靠前一帧和自身来解码处一帧数据 编码压缩比例较高
  • B帧: 双向预测帧,即需要利用前后两帧的数据来解码自身这一帧的数据,编码压缩比例极高。

因为B帧这种特殊的存在,所以未解码的视频流中,帧的解码顺序与播放顺序是不一致的。

假如正常帧播放顺序是I B P,那么在视频流中这三帧的顺序应该是I P B,因为B帧的生成需要前后两帧数据,所以会出现先解码P帧,再解码B帧的情况。

一般视频中I帧较少,P帧,B帧占大多数,所以才能把一部电影压缩到几个G的大小。

PTS和DTS

  • PTS 显示时间戳。指示帧应该在什么时间点被呈现给用户。PTS 是在解码后确定的时间戳,用于视频帧或音频帧的渲染或播放顺序
  • DTS 解码时间戳。 指示解码器应该在什么时间点开始解码该帧(解码顺序)。DTS 是在解码之前确定的时间戳,由解码器按正确的顺序解码帧。(它是在编码时由编码器设置的)

有了解码时间戳,就可以保证I/P/B帧的按照正确顺序解码,有了PTS,则可以保证I/P/B帧的按照正确顺序播放

音视频同步

由于我们说的视频往往是指音频+视频,而这两者又是独立的数据,分别由独立的设备进行播放,因此再播放时,往往需要主要音视频的同步。音视频同步的基本原理就是管理音视频的数据,按照PTS的时间顺序播放。

实际操作来看,一般需要选取一个参考时间轴,这个参考每次音频或者视频解码完成之后,通过比对现实时间戳和参考时间轴时间来控制播放进度。

而这个参考时间轴,可以选择音频时间轴,视频时间轴,或独立时间轴,一般选择独立时间轴。

编码标准

前面虽然讲到,从RGB转向YUV的过程是可以显著节省视频的存储空间,但是这远远不够,最终视频存储空间还是要靠编码来进行压缩。因此市面上有很多对视频帧进行编码的编码标准:h263,h264(重点),h265,vp8,vp9…

其中,H.264是目前使用最广泛,支持最广泛的适配编码器,而随着4K/8K的逐步普及,视频编码器应该会逐渐向H.265 过渡。

视频编码标准的算法一般是非常复杂的,对于一般开发者而言不需要深入接触

封装格式

对于视频而言,一般指的是视频+音频。而这两种数据本质上是独立的数据,因此需要把他们按照特定的规则协议封装成一个文件让播放器播放。

目前市面上主要的封装格式有:MP4(主要),MKV,AVI,FLV,TS…

这些封装格式主要可以分为两类:存储类,流媒体类

  • 存储类: 面向存储使用
    • MP4,MKV,AVI
  • 流媒体类: 面向流媒体使用
    • FLV,TS

之所以会出现这样的区别,主要是看封装格式是否能支持一遍下载,一边解码,一边播放。

资料参考

https://ibabyblue.github.io/2020/04/27/YUV%E4%B8%8ERGB%E6%A0%BC%E5%BC%8F%E8%BD%AC%E6%8D%A2/

© 版权声明

相关文章

暂无评论

您必须登录才能参与评论!
立即登录
暂无评论...