前言:计算机存储本质
记住一点,计算机所有的文件均为二进制文件,包括文本文件(它是特殊的二进制文件,为什么特殊?因为它里面全部可直接翻译为字符),这些二进制文件就是一群0101集合(特定软件能打开就能看到),他们的读取与写入,过程完全相同:
读入内存:文件-->二进制流-->-->按格式解码-->应用程序内存数据
写出文件:应用程序内存数据-->按格式编码-->二进制流-->文件
一直以来,我们对于文本文件的处理是比较好理解的,不论是前端的表格还是表单等参数,传到后端的本质都是字符串,所以很好理解,也很好处理。
但对于音频,图像,视频等多媒体文件,我就一直不理解它们的本质。
于是,我详细查询了网上资料,整合成如下几篇完整的《前世今生漫谈》
图片文件前世今生和衍生技术原理
补档:https://www.jianshu.com/p/3f31b72be674
https://www.jianshu.com/p/830202931e59
音频文件前世今生和衍生技术原理
https://www.jianshu.com/p/2f097ab27051
视频文件前世今生和衍生技术原理
https://www.jianshu.com/p/aa78924ee4da
视频文件前世今生漫谈
一、视频的原理
视频的本质:连续的图像序列,拍视频就是拍一组连续的图片
视频是连续的图像序列,由连续的帧构成,一帧即为一幅图像。由于人眼的视觉暂留效应,当帧序列以一定的速率播放时,我们看到的就是动作连续的视频。(人眼的帧率是24帧)于是就变成了视频。视频只有一系列的图片,音频需要后期配置,并加以音频视频同步调整。
其中音频视频同步还是有些复杂的,但大致原理是以音频的播放为基准,动态调节视频的渲染。因为人耳对声音的快慢感知度是比较强的,而对画面的快慢感知不强。
一般来说,画面放的快,声音放的慢为多。
拿视频帧的时间戳去和音频帧的时间戳对比,如果超过一定阈值,就让视频的改帧不渲染(掉帧),大概就是这么个意思。
有兴趣详细了解的可以看下几篇博客:
视频编解码基础概念
https://www.cnblogs.com/leisure_chn/p/10285829.html
二、视频的压缩技术简介
视频的压缩技术其实和音频、图片的压缩技术原理上差不多,主要是减少冗余。讲个故事来描述大致发展,可能就更容易理解(这个故事仅当理解用,如有不对的地方,欢迎指正):
最初的视频,其实就是连续图片的叠加,比如1秒20帧,拍个5秒就是100帧,也就是100张图片,但问题很明显,100张图片之间可能非常相似,冗余度太高,体积太大,即便采用高压缩比的jpeg格式,这100张图片起码也得30-40M,对于早期存储技术不发达的年代,5s视频40M,这显然是没法用的,即便存储能跟上,网络传输带宽也跟不上。
于是人们就想到一个办法,所谓【动】,实际就是一段时间内连续的位移,如果我们先确定一个参考图片,然后后续的图片只负责记录与该参考图片不同的地方,记录少量的一些位移差值,那岂不是大大减少文件大小了。
于是,视频的压缩标准就产生了,即按照上述原理编码解码的一套规则。
比如1s 20帧,20张图片,第一张图片是参考图片,它包含了所有完整的信息,是一张不依赖于其他图片的独立帧,我们管它叫I帧(关键帧),从第二张图片开始,到第20张图片,我们都不再记录完整图片,而是每一张图片只记录与前面一张图片的运动矢量,也就是差值,而这些帧,他们依赖于前面一张图片,我们管它叫P帧(差别帧,单向预测帧)。编码的时候后面19张图片都是不完整的,解码的时候只需要利用内存中的第一张图片数据和这些变化的差值拼接即可还原。
这样20张图片一组完整的组,就叫GOP(group of pictures 一组图片)。
举个例子:比如描述一个点的运动,比如用了5s从坐标5移动到了14,一共10张图片,
那么过程就是
5--6--7--8--9--10--11--12--13--14
对应帧的变化信息就是5 +1 +1 +1 +1 +1 +1 +1 +1 +1
对应帧就是I--P--P--P--P--P--P--P--P--P
I帧记录的这个点的初始位置(0,5)以及完整的图片必要信息
而P帧只是记录了这个变化差值,每次+1
编码和解码都是上述从左到右顺序来的,于是【I帧P帧】的视频压缩技术诞生了,原先1s 20张图片被压缩成了1s (1张完整图片+19张少量细节变化图片)
随着时代的发展,人们对于压缩技术的要求也朝着更小的方向发展,于是就想,上述的压缩逻辑能否进一步压缩呢?还是以上面这个点的运动为例:
我们知道,一般情况,很小一段时间内运动都是规则连续的,像上面
5 +1 +1 +1 +1 +1 +1 +1 +1 +1
这样规则的运动是否可以压缩成5 (+1*9)
呢?
当然可以,但是首要解决的问题是,我得清楚这个点的运动是5-14均匀连续的才行呀,如果不连续肯定不能这么压缩。那怎么判断出这个点确实是这样子均匀连续的呢?于是人们想到了【求平均】:每三张图进行对比,如果第二张图运动矢量恰好是第一张图和第三张图的平均值,那不就说明是均匀的变化嘛,那第二张图就不用单独记录了,只需要第一张和第三张就够了。
类似这样:
5--6--7--8--9
5-- -- 7-- --9
6恰好是(5和7)的平均值,说明5 6 7的变化是连续的,6编码时自身可以不用记录,只需要特殊标记一下就行,解码时只需在5 和 7 的已渲染基础上,两者叠加求平均即可还原。
我们管6这种【同时依赖于前面和后面帧的双向预测帧】叫B帧,B帧与P帧类似,却可以做到比P帧更高的压缩率:你P帧可以只记录变化量,我B帧甚至可以做到不记录任何变化量,你P帧服不服。
于是上述过程 5--6--7--8--9--10--11--12--13--14--15
对应帧变化信息 5--B--7--B--9--B-- 11--B--13--B--15
对应帧 I--B--P--B--P--B-- P-- B-- P-- B-- P
有时候为了追求更高的压缩率:可能出现更多的B帧
如 I B B P B B P B B P,不过不论怎么样I帧和P帧是必须的,因为它们可以作为参考帧,来修正调整误差,而B帧是基于它们的前后算出来的结果,不能直接作为参考帧。而且有个很重要的注意点:
B帧由于依赖前后帧的数据信息,就会导致编码和解码的顺序与自然顺序不同,也就是非线性编码。比如1 2 3 三张图片,在编码时,顺序就是1 3 2,解码时也需要按照1 3 2 顺序解码,再重排列还原成显示顺序1 2 3,所以每两个参考帧间插入越多的B帧,算法也就越复杂。
这种非线性编码解码的方式,导致了后来出现的音频视频不同步(音画不同步),后来就衍生出了DTS(编码时间戳)和PTD(显示时间戳)等一系列概念与技术手段,来解决音频视频不同步现象。