視頻
視頻采集裝置一秒鐘會(huì)捕捉幾十幀數(shù)據(jù),動(dòng)畫一般25幀以上汹来,一般視頻文件30幀數(shù)據(jù)续膳,對(duì)于捕捉一些清晰動(dòng)作的甚至要達(dá)到60幀以上,但是對(duì)于一組幀收班,幀和幀之間的變化很小坟岔,為了壓縮數(shù)據(jù),我們將第一幀(I幀)完整保存下來闺阱,沒有關(guān)鍵幀炮车,后面數(shù)據(jù)幀無法解碼。接下來章節(jié)主要著重介紹我們經(jīng)常在視頻編碼當(dāng)中用到的 H.264編碼
常用的視頻編解碼器
x264/x265:x265壓縮比更高酣溃,占用CPU也更高
openH264:支持SVC(會(huì)將圖分層瘦穆,小中大,根據(jù)網(wǎng)絡(luò)情況發(fā)送赊豌,缺點(diǎn)是移動(dòng)端很多硬件不支持扛或,只能使用軟編,cpu消耗高)
vp8/vp9:vpx系列碘饼,vp8對(duì)應(yīng)x264熙兔,vp9對(duì)應(yīng)x265
H.264背景
H.264是[國(guó)際標(biāo)準(zhǔn)化組織]([ISO])和國(guó)際電信聯(lián)盟(ITU)共同提出的繼MPEG4之后的新一代數(shù)字視頻壓縮格式。H.264是在MPEG-4技術(shù)的基礎(chǔ)之上建立起來的艾恼,其編解碼流程主要包括5個(gè)部分:幀間和幀內(nèi)預(yù)測(cè)住涉、變換(Transform)和反變換、量化(Quantization)和反量化钠绍、環(huán)路濾波(Loop Filter)舆声、熵編碼(Entropy Coding)。與其它現(xiàn)有的視頻編碼標(biāo)準(zhǔn)相比柳爽,在相同的帶寬下提供更加優(yōu)秀的圖象質(zhì)量媳握。通過該標(biāo)準(zhǔn),在同等圖象質(zhì)量下的壓縮效率比以前的標(biāo)準(zhǔn)(MPEG2)提高了2倍左右
H.264中的基本概念
I幀
I幀:關(guān)鍵幀磷脯,采用幀內(nèi)壓縮技術(shù)P幀
P幀:向前參考幀蛾找,壓縮時(shí)參考前一幀(幀間壓縮技術(shù),后面幀只存與它前一幀的差異)B幀
B幀:雙向參考幀赵誓,壓縮時(shí)既參考前一幀也參考后一幀打毛,幀間壓縮技術(shù)PTS與DTS
PTS(Presentation Time Stamp):PTS主要用于度量解碼后的視頻幀什么時(shí)候被顯示出來。
DTS(Decode Time Stamp):DTS主要是標(biāo)識(shí)內(nèi)存中的bit流再什么時(shí)候開始送入解碼器中進(jìn)行解碼俩功。
備注:DTS主要用戶視頻的解碼隘冲,在解碼階段使用。PTS主要用于視頻的同步和輸出绑雄,在display的時(shí)候使用。再?zèng)]有B frame的時(shí)候輸出順序一樣
-
GOF
Group of Frame(一組幀)奥邮,GOP是畫面組万牺,一個(gè)GOP是一組連續(xù)的畫面罗珍,GOP一般有兩個(gè)數(shù)字,如M=3脚粟,N=12(M指定I幀與P幀之間的距離覆旱,N指定兩個(gè)I幀之間的距離),GOF結(jié)構(gòu)格式如下:
1 -
IDR
在H.264中核无,圖像以序列為單位進(jìn)行組織扣唱。一個(gè)序列的第一個(gè)圖像叫做 IDR 圖像(立即刷新圖像),IDR 圖像都是 I 幀圖像团南。H.264引入IDR圖像是為了解碼的重同步噪沙,當(dāng)解碼器解碼到 IDR 圖像時(shí),立即將參考幀隊(duì)列清空吐根,將已解碼的數(shù)據(jù)全部輸出或拋棄正歼,重新查找參數(shù)集,開始一個(gè)新的序列拷橘。這樣局义,如果前一個(gè)序列出現(xiàn)重大錯(cuò)誤,在這里可以獲得重新同步的機(jī)會(huì)冗疮。IDR圖像之后的圖像永遠(yuǎn)不會(huì)使用IDR之前的圖像的數(shù)據(jù)來解碼萄唇。IDR 圖像一定是 I 圖像,但 I 圖像不一定是IDR圖像术幔。I幀之后的圖像有可能會(huì)使用I幀之前的圖像做運(yùn)動(dòng)參考
IDR SPS與PPS
SPS:Sequence Parameter Set,序列參數(shù)集另萤,存放幀數(shù)、參考幀數(shù)目特愿、解碼圖像尺寸仲墨、幀場(chǎng)編碼模式選擇標(biāo)識(shí)等
PPS:Picture Parameter Set,圖像參數(shù)稽核揍障,存放熵編碼模式選擇標(biāo)識(shí)目养、片組數(shù)目、初始量化參數(shù)和去方塊濾波系數(shù)調(diào)整標(biāo)識(shí)等
備注:在接收一組幀之前我們首先會(huì)收到SPS和PPS毒嫡,如果沒有這兩個(gè)參數(shù)我們是無法解碼的
H.264原理與結(jié)構(gòu)
主要使用壓縮技術(shù)
- 幀內(nèi)預(yù)測(cè)壓縮(解決空域數(shù)據(jù)冗余問題癌蚁,一幅圖里面的顏色,色彩兜畸,光亮努释,人不是很敏感,可以刪掉)
- 幀間預(yù)測(cè)壓縮(解決時(shí)域數(shù)據(jù)冗余問題咬摇,隨著時(shí)間軸的推進(jìn)刪除重復(fù)圖)
- 整數(shù)離散余弦變換(DCT)伐蒂,將空間上的相關(guān)性變?yōu)轭l域上無關(guān)的數(shù)據(jù),然后進(jìn)行量化
CABAC壓縮(無損壓縮)
H.264碼流
SODB:String Of Data Bits原始數(shù)據(jù)比特流肛鹏,長(zhǎng)度不一定是8的倍數(shù)逸邦,由VCL層產(chǎn)生
-
RBSP:Raw Byte Sequence PayLoad (SODB + trailing bits)相當(dāng)于給SODB補(bǔ)結(jié)束標(biāo)記(在SODB最后一位補(bǔ)1恩沛,如果不是8字節(jié)對(duì)齊,則補(bǔ)0進(jìn)行對(duì)齊)
RBSP序列
RBSP描述說明 EBSP:Encapsulate Byte Sequence Payload 在生成壓縮流之后缕减,在每個(gè)幀的開始處加一個(gè)起始位(起始碼:00 00 01或00 00 00 01雷客,如果實(shí)際數(shù)據(jù)有00 00那么需增加一個(gè)0x03進(jìn)行沖突區(qū)分)
-
NALU:NAL Header(1個(gè)字節(jié)) + RBSP
NALU
備注:NAL Header 由三部分組成,forbidden_bit(1bit)桥狡,nal_reference_bit(2bits)(優(yōu)先級(jí))搅裙,nal_unit_type(5bits)(類型)
H.264原始碼流是由一個(gè)接一個(gè)NALU組成耐量,它的功能分為兩層聂薪,VCL(視頻編碼層)和 NAL(網(wǎng)絡(luò)提取層).
VCL(Video Coding Layer) + NAL(Network Abstraction Layer)
VCL:Video Coding Layer 視頻數(shù)據(jù)編碼層,包括核心壓縮引擎和塊扒俯,宏塊和片的語(yǔ)法級(jí)別定義局雄,設(shè)計(jì)目標(biāo)是盡可能地獨(dú)立于網(wǎng)絡(luò)進(jìn)行高效的編碼
NAL:Network Abstraction Layer 視頻數(shù)據(jù)網(wǎng)絡(luò)抽象層甥啄,負(fù)責(zé)將VCL產(chǎn)生的比特字符串適配到各種各樣的網(wǎng)絡(luò)和多元環(huán)境中,覆蓋了所有片級(jí)以上的語(yǔ)法級(jí)別
在VCL進(jìn)行數(shù)據(jù)傳輸或存儲(chǔ)之前炬搭,這些編碼的VCL數(shù)據(jù)蜈漓,被映射或封裝進(jìn)NAL單元(NALU)
H.264結(jié)構(gòu)
整體結(jié)構(gòu)參考如下圖
NALU單元詳解
- NAL Header
F:
forbidden_zero_bit,在H.264規(guī)范中規(guī)定該位必須為0NRI:
指示重要性Type:
NALU單元類型
nal_unit_type | 說明 |
---|---|
0 | 沒有定義 |
1-23 |
NAL單元 單個(gè) NAL 單元包 |
1 | 非IDR圖像中不采用數(shù)據(jù)劃分的片段 |
2 | 非IDR圖像中A類數(shù)據(jù)劃分片段 |
3 | 非IDR圖像中B類數(shù)據(jù)劃分片段 |
4 | 非IDR圖像中C類數(shù)據(jù)劃分片段 |
5 | IDR圖像分片 |
6 | 補(bǔ)充增強(qiáng)信息單元(SEI) |
7 | 序列參數(shù)集(SPS) |
8 | 圖像參數(shù)集(PPS) |
9 | 分解符 |
10 | 序列結(jié)束 |
11 | 碼流結(jié)束 |
12 | 填充 |
13-23 | 保留 |
24 | STAP-A 單一時(shí)間的組合包 |
25 | STAP-B 單一時(shí)間的組合包 |
26 | MTAP16 多個(gè)時(shí)間的組合包 |
27 | MTAP24 多個(gè)時(shí)間的組合包 |
28 | FU-A 分片的單元 |
29 | FU-B 分片的單元 |
30-31 | 沒有定義 |
-
NAL類型介紹
單一類型:一個(gè)RTP包只包含一個(gè)NALU
組合類型:一個(gè)RTP包含多個(gè)NALU宫盔,類型是24-27
分片類型:一個(gè)NALU單元分成多個(gè)RTP包融虽,類型是28和29
單一類型
組合類型
分片類型 -
FU Header
FU Header
S:
start bit,用于指明分片的開始
E:
end bit灼芭,用于指明分片的結(jié)束
R:
未使用有额,設(shè)置為0
Type:
指明分片NAL類型
Slice片詳解
由H264碼流分層圖可得知,NALU的主體就是Slice(片)彼绷,片是H.264提出的新概念巍佑,通過編碼圖片后切分通過高效的方式整合出來的概念。一張圖片有一個(gè)或者多個(gè)片寄悯,而片由NALU裝載并進(jìn)行網(wǎng)絡(luò)傳輸?shù)挠┧ァR粋€(gè)Slice包含一幀圖像的部分或全部數(shù)據(jù),換言之猜旬,一幀視頻圖像可以編碼為一個(gè)或若干個(gè)Slice脆栋。一個(gè)Slice最少包含一個(gè)宏塊,最多包含整幀圖像的數(shù)據(jù)洒擦。在不同的編碼實(shí)現(xiàn)中椿争,同一幀圖像中所構(gòu)成的Slice數(shù)目不一定相同。設(shè)置片的目的是為了限制誤碼的擴(kuò)散和傳輸熟嫩,應(yīng)使編碼片相互間是獨(dú)立的秦踪。某片的預(yù)測(cè)不能以其他片中的宏塊為參考圖像,這樣某一片中的預(yù)測(cè)誤差才不會(huì)傳播到其他片中。
一個(gè)Slice由Slice Header + Slice Data構(gòu)成洋侨,如下圖所示:
- Slice 類型
slice類型 | 說明 |
---|---|
I slice | 幀內(nèi)編碼的條帶(只包含I宏塊) |
P slice | 單向幀間編碼的條帶(包含P和I宏塊) |
B slice | 雙向幀間編碼的條帶(包含B和I宏塊) |
SI slice | 切換I條帶舍扰,用于擴(kuò)展檔次中碼流切換使用(一種特殊類型的編碼宏塊) |
SP slice | 切換P條帶,用于擴(kuò)展檔次中碼流切換使用(包含P 和I或 I宏塊,用于不同碼流之間的切換) |
- Slice Header
Slice header中主要保存了當(dāng)前slice的一些全局的信息希坚,slice body中的宏塊在進(jìn)行解碼時(shí)需依賴這些信息。其中比較常見的一些語(yǔ)法元素有
slice header參數(shù) | 說明 |
---|---|
first_mb_in_slice | 第一個(gè)宏塊在slice的位置 |
slice_type | slice的類型 |
pic_parameter_set_id | 當(dāng)前slice所依賴的pps的id陵且;范圍 0 到 255 |
colour_plane_id | 當(dāng)標(biāo)識(shí)位separate_colour_plane_flag為true時(shí)裁僧,colour_plane_id表示當(dāng)前的顏色分量,0慕购、1聊疲、2分別表示Y、U沪悲、V分量 |
frame_num | 表示當(dāng)前幀序號(hào)的一種計(jì)量方式 |
field_pic_flag | 場(chǎng)編碼標(biāo)識(shí)位获洲。當(dāng)該標(biāo)識(shí)位為1時(shí)表示當(dāng)前slice按照?qǐng)鲞M(jìn)行編碼;該標(biāo)識(shí)位為0時(shí)表示當(dāng)前slice按照幀進(jìn)行編碼 |
bottom_field_flag | 底場(chǎng)標(biāo)識(shí)位殿如。該標(biāo)志位為1表示當(dāng)前slice是某一幀的底場(chǎng)贡珊;為0表示當(dāng)前slice為某一幀的頂場(chǎng) |
idr_pic_id | 表示IDR幀的序號(hào)。某一個(gè)IDR幀所屬的所有slice涉馁,其idr_pic_id應(yīng)保持一致门岔。該值的取值范圍為[0,65535] |
pic_order_cnt_lsb | 表示當(dāng)前幀序號(hào)的另一種計(jì)量方式 |
delta_pic_order_cnt_bottom | 表示頂場(chǎng)與底場(chǎng)POC差值的計(jì)算方法,不存在則默認(rèn)為0 |
slice_qp_delta | 用于計(jì)算當(dāng)前slice內(nèi)所使用的初始qp值 |
slice_type
slice_type值 | 說明 |
---|---|
0 | P (P slice) |
1 | B (B slice) |
2 | I (I slice) |
3 | SP (SP slice) |
4 | SI (SI slice) |
5 | P (P slice) |
6 | B (B slice) |
7 | I (I slice) |
8 | SP (SP slice) |
9 | SI (SI slice) |
宏塊詳解
宏塊是視頻信息的主要承載者烤送。一個(gè)編碼圖像通常劃分為多個(gè)宏塊組成.包含著每一個(gè)像素的亮度和色度信息寒随。視頻解碼最主要的工作則是提供高效的方式從碼流中獲得宏塊中像素陣列 。
一個(gè)宏塊 = 一個(gè)16*16的亮度像素 + 一個(gè)8×8Cb + 一個(gè)8×8Cr彩色像素塊組成帮坚。(YCbCr 是屬于 YUV 家族的一員,在YCbCr 中 Y 是指亮度分量妻往,Cb 指藍(lán)色色度分量,而 Cr 指紅色色度分量)
在 H.264 中试和,句法元素共被組織成 序列讯泣、圖像、片灰署、宏塊判帮、子宏塊五個(gè)層次, 句法元素的分層結(jié)構(gòu)有助于更有效地節(jié)省碼流。例如溉箕,再一個(gè)圖像中晦墙,經(jīng)常會(huì)在各個(gè)片之間有相同的數(shù)據(jù),如果每個(gè)片都同時(shí)攜帶這些數(shù)據(jù)肴茄,勢(shì)必會(huì)造成碼流的浪費(fèi)晌畅。更為有效的做法是將該圖像的公共信息抽取出來,形成圖像一級(jí)的句法元素寡痰,而在片級(jí)只攜帶該片自身獨(dú)有的句法元素抗楔。宏塊的具體結(jié)構(gòu)如下:
宏塊結(jié)構(gòu)
宏塊結(jié)構(gòu) | 說明 |
---|---|
mb_type | 宏塊類型棋凳,確定該 MB 是幀內(nèi)或幀間(P 或 B)編碼模式,確定該 MB 分割的尺寸 |
mb_pred | 預(yù)測(cè)類型连躏,確定幀內(nèi)預(yù)測(cè)模式(幀內(nèi)宏塊)確定表 0 或表 1 參考圖 像剩岳,和每一宏塊分割的差分編碼的運(yùn)動(dòng)矢量(幀間宏塊,除 8×8 宏塊分割的幀內(nèi) MB) |
sub_mb_pred | 預(yù)測(cè)類型入热,(只對(duì) 8×8MB 分割的幀內(nèi) MB)確定每一子宏塊的子宏 塊分割拍棕,每一宏塊分割的表 0 和/或表 1 的參考圖象;每一 宏塊子分割的差分編碼運(yùn)動(dòng)矢量 |
coded_block_pattern | 指出哪個(gè) 8×8 塊(亮度和彩色)包 編碼變換系數(shù) |
mb_qp_delta | 量化參數(shù)的改變值 |
YUV(YCbCr)
YUV是從電視系統(tǒng)衍生出來的一種顏色編碼方法,Y表示明亮度勺良,也就是灰階值绰播,它是基礎(chǔ)信號(hào),U和V表示的則是色度尚困,UV的作用是描述影像色彩及飽和度蠢箩,它們用于指定像素的顏色。YUV亮度信息(Y)與色彩信息(UV)分離事甜,沒有 UV 信息一樣可以顯示完整的圖像谬泌,沒有UV分量,則只是黑白顯示讳侨,YUV 不像RGB 那樣要求三個(gè)獨(dú)立的視頻信號(hào)同時(shí)傳輸呵萨,而且用 YUV 數(shù)據(jù)占用的內(nèi)容更少。
YCbCr 中跨跨,Y 是指亮度分量潮峦,Cb 指藍(lán)色色度分量,而 Cr 指紅色色度分量
- YUV與RGB的相互轉(zhuǎn)換
RGB轉(zhuǎn)YUV:
Y = 0.299R + 0.587G + 0.114B
Cb = 0.564(B - Y)
Cr = 0.713(R - Y)
YUV轉(zhuǎn)RGB:
R = Y + 1.402Cr
G = Y - 0.344Cb - 0.714Cr
B = Y + 1.772Cb
- YUV常見格式
- YUV4:2:0:
YUV4:2:0并不意味著只有Y和Cb兩個(gè)分量勇婴,而沒有Cr分量忱嘹。它實(shí)際指的是對(duì)每行掃描線來說,只有一種色度分量耕渴,它以2:1的抽樣率存儲(chǔ)拘悦。例如相鄰的掃描行存儲(chǔ)不同的色度分量,也就是說橱脸,如果一行時(shí)4:2:0的話础米,下一行就是4:0:2,在下一行就是4:0:2添诉,在下一行就是4:2:0進(jìn)行以此類推 - YUV4:2:2
- YUV4:4:4
舉例一副圖片假設(shè)像素矩陣如下:
上圖中每個(gè)像素的 3 個(gè)分量的信息是完整的屁桑,Y : Cb : Cr = 4 : 4 : 4,屬于 YUV444 格式栏赴。
人類視覺系統(tǒng)對(duì)亮度信號(hào)比色度信號(hào)敏感的原理蘑斧,我們可以省略圖片的一些信息,對(duì)圖片的質(zhì)量影響卻不會(huì)太大,比如將該像素矩陣存儲(chǔ)為:
此時(shí)竖瘾,每?jī)蓚€(gè) Y 共用一組 UV 分量沟突,Y : Cb : Cr = 4 : 2 : 2,屬于 YUV422 格式捕传。
同理我們進(jìn)一步得出YUV420格式如下:
每四個(gè) Y 共用一組 UV 分量惠拭,Cb、Cr 交替出現(xiàn)庸论,在第一行數(shù)據(jù)里 Y : Cb : Cr = 4 : 2 : 0求橄;而在第二行數(shù)據(jù),Y : Cb : Cr = 4 : 0 : 2葡公,這就是最常見的 YUV420 格式。
- YUV存儲(chǔ)格式分類
- planar平面存儲(chǔ)
I420(YUV420P): YYYYYYYY UU VV
YV12(YUV420P):YYYYYYYY VV UU - packed打包存儲(chǔ)
NV12(YUV420SP):YYYYYYYY UVUV
NV21(YUV420SP):YYYYYYYY VUVU
planar 先存儲(chǔ)所有 Y条霜,緊接著存儲(chǔ)所有 U催什,最后是 V;而 packed 則是每個(gè)像素點(diǎn)的 Y宰睡、U蒲凶、V 連續(xù)交叉存儲(chǔ)。
現(xiàn)在我們不管是移動(dòng)端(安卓和IOS)也好拆内,PC端也好旋圆,在轉(zhuǎn)成YUV之后可能出現(xiàn)圖像倒置或反轉(zhuǎn),可能和平臺(tái)支持的YUV存儲(chǔ)格式不同有關(guān)麸恍,例如安卓默認(rèn)的是NV21灵巧,ios默認(rèn)是NV12,PC端是I420抹沪,屏幕倒置旋轉(zhuǎn)主要原因還是存儲(chǔ)格式不一樣刻肄,要讓他們一樣就是要做成一個(gè)統(tǒng)一的格式