本文正在参加「金石计划 . 分割6万现金大奖」
前语
学习视频编解码需求有一些根底的概念,先了解这些根底的概念,才干更好的了解整个视频编解码的进程,只要了解了编解码的整个进程,才干知道怎么去开发,怎么完成某一步的功用,它是一个很庞大的体系,所以触及的一些根底会比较多,高级的做法还会触及openGL去对视频做处理,所以了解这些根底的理论能更好的进入这个范畴。我个人也是自学的,所以有说得不对的当地,期望能在评论区指正。
颜色空间
咱们常说的RGB和YUV都是颜色空间中的一种。
RGB便是咱们常用到的光的三原色模型(红绿蓝),一般的图片都是RGB,简略来说3种原色经过不同的比例组成不同的颜色。而RGB颜色空间又会细分红不同的颜色空间,比方sRGB、Adobe RGB等,他们所包含的颜色范围不同,这又称为色域。
这些在日子中都有运用到的,比方显现器支持不同的色域,总之这不是这篇文章的重点,只需求简略了解RGB是什么以及咱们的图片往往都是运用的RGB。
YUV(也称YCbCr)用于编码和存储更相关于RGB更好,所以一般会用在视频。YUV触及到HVS(人类视觉体系对颜色空间的感知才干),简略来说便是我这个颜色的信息有这么多,你人是接纳不完的,只能接纳一部分,那我就把信息弄成人能接纳的那部分。
这儿首要讲YUV,YUV分为3个数值,Y表明亮度,U表明色调,V表明饱和度,一般Y比较重要,有Y重量就能 显现出图片,不过是黑白。依据采样不同YUV又分为YUV 4:4:4,YUV 4:2:2和YUV 4:2:0。一般我咱们的手机摄像头的采样都是运用YUV420,而YUV420又依据格局分为NV12和YU12,简略来说他们都是420的采样,可是数据的排布不同,比方我去网上找的图
YU12中放入Y重量,再放入U重量,最终放入V重量
NV12中先放入Y重量,然后U重量和V重量交叉放入
当然除了这两种之外还有YV12和NV21,这儿就不扩展了,也是差不多的意思。那在现实中是怎么体现不同的?拿Android来举例,虽然摄像头采集都用的YUV420,可是他不同的摄像头都是用的不同的硬件厂商,所以终究会出现的格局也会不同,而Android的解码器MediaCoder是用的NV12(没记错的话),所以在判别数据是YU12的状况下需求转成NV12(这个是能够互转的)
最终说说YUV和RGB的不同,YUV需求存储的数据小于RGB。YUV和RGB能够经过公式进行转换:
Y = 0.299R + 0.587G + 0.114B
U = -0.147R – 0.289G + 0.436B = 0.492*(B-Y)
V = 0.615R – 0.515G – 0.100B = 0.877(R-Y)
R = Y + 1.140V
G = Y – 0.394U – 0.581V
B = Y + 2.032U
帧
视频的播映简略来了解便是每隔多少时刻显现一张图片,每张图片都相当于一个帧。当然真实的概念并不完全是这样的,只是这样想会比较简略了解。
1秒播映30张图片咱们称为1秒30帧,1秒播映60张图片我咱们称为1秒60帧,也能够称为60fps。结合日子,咱们往常玩游戏觉得卡顿是由于前一段时刻的帧率平稳,可是突然帧率变低,所以导致咱们感官反应到卡顿。
视频的帧又分为I帧,P帧和B帧,这当然是很重要的一个概念,为什么要分为3种不同的帧呢?简略来说是为了紧缩,当了解每种帧的含义之后,就能知道为什么和这样设计。
I帧
I帧又称为关键帧,它无需参阅其它帧,由自己生成,对帧内的数据进行紧缩后生成,自己就能显现出图画。
P帧
P帧会向前参阅I帧生成,所以没有I帧的状况下仅有P帧的状况下是无法显现图画。
B帧
B帧会向前参阅I帧,向后参阅B帧生成,所以没有I帧和P帧的状况下B帧无法显现图画。
这是他们的一个大致区别,可能刚这样看还了解不了,不要紧,等到下面解说视频的编码流程的时分就能了解了。
GOP和IDR
这是和帧相关的概念,但不是十分重要的,所以简略了解就行。
GOP全称Group of picture即图画组,每两个I帧之间是一个GOP,所以GOP是包含一个I帧和多个P帧和B帧。那这个概念会在什么当地体现出用处呢?直播,直播的时分,数据传输,你拿到一个GOP后进行播映,假如不是一个GOP,比方你刚开始翻开直播的时分是推了P帧给你,你这时分没有I帧,只拿P帧是显现不出完整图片的。你也能够简略了解成I帧之后的多个P帧和B帧依赖于当时I帧,可是他们并不依赖于其它I帧,所以他们形成了一个组。
IDR是一个和改写相关的概念,它的翻译是立即改写图画,所以它一定是一个I帧。举个比方(我也不知道这个比方对不对,没触及过直播相关的),你看直播的时分卡顿了,可是卡顿好的之后会有个跳帧的作用,不会接着卡顿的当地持续播映,其实便是接纳到了一个IDR,会把前面没有播映的帧丢掉,直接播映这个I帧。
PTS和DTS
这个也是和帧有关的,但它也和编解码进程有关,它们都是时刻戳,PTS表明显现时刻戳,它告知视频要依照这个PTS的次序去播映,DTS表明解码时刻戳,它告知文件要依照这个DTS的次序去存储。
这个下面讲编解码流程的时分可能会更简略了解,这儿简略来说便是咱们一般视频都是一I B B B P 这种帧的次序去播映,可是编码之后存储的是 I P B B B 这样的次序。
码率
这是一个数据传输的指标,码率又叫作比特率,即数据传输时单位时刻传送的数据位数,一般用kbps、Mbps表明。比特率越高,每秒传送数据就越多,画质就越明晰。
提到Mbps,许多人就知道是什么了,没错,便是咱们的宽度,多少兆宽度便是多少Mbps,经过换算8Mbps = 1MB/s,可是这是理想的状况,加上损耗,大约会10Mbps = 1MB/s,看到这个相信咱们就都了解了,为什么你家网速在电信拉的是100兆,下载的时分却只要10兆每秒,这便是一个换算进程。
那为什么比特率越高,影响画质呢,这其实是和视频文件巨细有关,比方你视频文件越大,帧数越高,分辨率越高,那你的视频文件就越大,所以你需求更高的比特率来传输。那假如文件大我比特率低会怎样?会卡顿,你播映这一帧的时分下一帧还没下好,这不便是你往常怒喷网速的原因吗?
视频流
这个关于根底来说也不是首要的概念,简略了解一下就行。一般像视频这种比较大的文件都是流文件,拿图片来做比照就能看出比较明显的差别。视频和图片在磁盘中存储的文件都是紧缩过的文件.mp4 ,.png这些。可是图片能变成位图(原始图片)悉数放到内存中,可是视频能够吗?当然不行,你把整个视频放到内存中那内存不炸掉,有的人说,一个视频只要几十MB,应该Hold得住啊,你那个是紧缩往后的巨细,实践的巨细后边会说,可是内存是装不下的,所以视频的播映和传输需求用到流的方法。
视频编解码
进入正题了,了解上面的概念会对编解码的进程更简略了解。上面也说了,咱们往常存储在本地的视频,是紧缩过的。那假如视频不紧缩,原始的数据会有多大呢?经过一个核算进程去稳固上面的根底常识。
比方咱们视频的分辨率是1920 * 1080,视频是60fps,采样我就算用YUV420,这个视频的时长100秒,取个整数好核算。
咱们假定未紧缩的状况,先核算1帧的巨细(YUV420占用1.5个字节)
1920 * 1080 * 1.5 = 3110400 = 2.96MB ,光一帧就2.96MB,一秒便是177.6MB,整个视频便是17.3GB
你家网速100兆10MB/S,下1秒钟的视频要17秒。紧缩往后的便是秒下好,这便是视频为什么要编码。
视频编解码流程
这是我在网上随意找的图,视频的编解码流程大约便是这样子,假如咱们有个mp4文件,mp4文件其实便是一个紧缩包,你能够把它的后缀改成zip然后解压,你就能看到里边的编码后的视频文件和编码后的音频文件(能够把编码简略了解成紧缩)。
咱们的设备在播映mp4文件的时分,会拿到里边的编码后的视频文件和编码后的音频文件,别离用视频解码器和音频解码器进行解码(你能够先简略了解解码器是一个硬件设备),解码后也都是流文件,再进行音视频同步播映,一般是视频配合音频完成同步,这便是视频播映的一个流程。
这个编码后的视频文件的格局一般是H246,H265,MJPG等,编码后的音频格局一般是AAC,MP3等。这时就有人问了,我没有mp4文件,我只要H264文件,能直接播映视频吗?当然能,没声音罢了,你能够解压mp4文件,拿里边的.h264文件丢到播映器看看能不能播映。
这个流程没画出前面的部分,比方咱们录像的时分,也是视频和音频分隔录,由视频编码器和音频编码器别离编码成h264和aac等,然后再进行打包成mp4,avi等格局的文件。
视频编码文件
我这边由于内容比较多,首要只讲视频,音频的话以后独自写一篇文章。
是这样的,咱们做任何东西都有一套标准,而视频紧缩也是有标准,那这个标准是谁来定的呢,必定是某某安排定的,谁做得快,谁牛逼,谁来定。所以有两个安排界说了视频编码的规矩,一个叫ISO(国际标准安排),另一个叫ITU(国际电传视讯联盟),他们两个比较牛逼,所以他们说得算。
用这两个安排的标准去紧缩的视频得到的格局是不同的,解码时也要用相应的标准去解码。ISO主打的是MPEG系列,ITU主打的是H.26X系列。由于咱们现实中一般用到H.26X比较多,所以首要讲这个,目前用得比较广泛的是H264和H265,便是咱们进行视频编码后会得到一个.h264或者.h265的文件。
h264又称为AVC,他们是同一个东西,h265又称为HEVC。
视频编码流程
视频编码流程指的是怎么从原视频数据变成H265文件(编码后文件)的进程。
这个进程中简略分为帧内紧缩和帧间紧缩。而整个视频编码的核心步骤又分为猜测、改变、量化和熵编码 ,这个进程会触及到一些核算,直接经过它来了解视频编码进程会更为复杂,而先了解大约的视频编码的原理,再去详细的看这些进程,就会更简略看懂每一步做了什么。举个比方,比方“改变”这个进程(我网上随意找张图)
这个数据块做DCT前后的改变,这是会触及到核算,假如没有视频编码的根底去看这些内容,我感觉意义不大,有了一定的根底再去看才是更好的做法。
那什么是根底,怎么才干快速了解视频编码的进程,才是入门最重要的,这就要触及到一个重要的概念:宏块
上面讲了这个进程中简略分为帧内紧缩和帧间紧缩,先讲帧内紧缩,独自拿一帧来举例,它相当于一张图片,假如的尺寸是19201080,那它便是有19201080个像素,咱们能够对它拆分红多个 n x n 的像素块。这个像素块便是宏块。这个进程可能不是很好了解,不要紧,我用视频剖析东西举例个比方
能看到视频被均分红许多块(由于这个东西比较旧没办法定位到I帧,所以先不用管图中显现的S的部分),而宏块又分为许多不同的子块,有4 x 4的,有 8 x 8 的,有 16 x 16的,所以一个视频被划分红多个不同的类型的宏块 ,能够在图中看到当时这一帧,某个类型的宏块的数量,比方这儿的16 x 16就有2486个。
这儿能够简略扩展一下,划分的越大,紧缩的作用就越好,比方16 x 16的作用好过8 x 8的,而我没记错的话,H264最大只能划分红16 x 16,而H265能划分到64 x 64。所以同一个视频,用H265编码出来的成果比H264占用的空间更小。
为什么宏块要划分红不同的类型,比方直接悉数16 x 16不行吗?这个直接解说的话很难解说状况他的划分原理,可是我找到一张图,能让人一眼就看出为什么
那它是怎么对一个宏块进行紧缩的呢?
简略来说,附近的两个像素其实差别不大,宏块里边的像素差别都不是很大,所以它只会保存宏块里边榜首行的像素,和榜首列的像素,然后其它的像素都用这一行一列的像素去猜测,而这个猜测一共有9种方法。感觉用语言很难解说清楚,我又要借上面那位老哥的另一张图来说了。
这样也能很明显的看出,经过不同的猜测方法,咱们就能用很少的像素推出这个宏块的其它像素。假如你了解了这儿的内容,那你应该就能知道视频紧缩的进程是有损紧缩仍是无损紧缩?
大约了解了帧内紧缩,咱们再讲讲帧间紧缩。上面咱们说视频帧分为I帧、P帧和B帧,I帧便是关键帧,I帧不会参阅其它帧,所以它是会把这一帧悉数划分红宏块。P帧便是类似度和I帧在90%以上(实践并不是90%,这个材料我还不敢确认,反正以上便是类似度超越多少),P帧有一部分是I帧的宏块运动后的成果,有一部分是新产生的宏块,所以P帧只保存了新的宏块和部分老宏块运动相关的数据,而B帧的紧缩率更高,它完全运动相关的数据。
我上面那张图便是P这么, 看到上面有些宏块显现S,这个便是表明运动的宏块。比方咱们也能够用东西来剖析运动相关的状况
所以帧间的一个编码进程能够简略这样了解(实践必定不会这样简略),榜首帧必定是I帧,编码后直接输出到文件,下一帧和I帧进行比较,假如类似度很低差别很大,那它便是I帧,持续输出到文件,假如类似度很高,超越多少以上,他便是B帧,B帧不会马上输出,能够简略了解放到一个缓冲区。假如类似度比较高,超越了多少以上,他便是P帧,P帧就会输出,P帧输出之后,B帧会对P帧进行参阅,所以是一个双向猜测,最终输出B帧。所以编码后的文件里边存的帧的次序是IPBBB这样的,这个次序便是DTS,而播映时会依照IBBBP的次序去播,这个次序便是PTS
总结
其实这个视频编码的相关的常识触及的许多,特别是触及到许多往常没触摸过的概念,首要仍是要把一些这个范畴相关的概念先了解清楚,再去了解大致的一个流程,再去了解某一步操作相对详细的流程,再去看代码会好一点。
并且这个进程中最好是需求经过一些东西自己去剖析,会更深入,包含一些视频剖析东西和ffmpeg,我这儿由于是讲根底,所以没有举例用ffmpeg来操作,一般看视频参数,修改视频之类的,都能经过ffmpeg去完成,它的功用很强壮。可是这一切仍是首先需求了解这些概念,才干知道详细去怎么剖析。