H264碼流打包分析
h264的功能分為兩層,視頻編碼層(VCL)和網(wǎng)絡(luò)提取層(NAL)??VCL數(shù)據(jù)即被壓縮編碼后的視頻數(shù)據(jù)序列。在VCL數(shù)據(jù)要封裝到NAL單元中之后,才可以用來傳輸或存儲(chǔ)。NAL單元格式如下圖:???Nal頭EBSPNal頭EBSPNal頭EBSP
NAL單元??每個(gè)NAL單元是一個(gè)一定語法元素的可變長字節(jié)字符串,包括包含一個(gè)字節(jié)的頭信息(用來表示數(shù)據(jù)類型),以及若干整數(shù)字節(jié)的負(fù)荷數(shù)據(jù)。一個(gè)NAL單元可以攜帶一個(gè)編碼片、A/B/C型數(shù)據(jù)分割或一個(gè)序列或圖像參數(shù)集?! AL單元按RTP序列號(hào)按序傳送。其中,T為負(fù)荷數(shù)據(jù)類型,占5bit;R為重要性指示位,占2個(gè)bit;最后的F為禁止位,占1bit。具體如下:?。?)NALU類型位可以表示NALU的32種不同類型特征,類型1~12是H.264定義的,類型24~31是用于H.264以外的,RTP負(fù)荷規(guī)范使用這其中的一些值來定義包聚合和分裂,其他值為H.264保留?!。?)重要性指示位 用于在重構(gòu)過程中標(biāo)記一個(gè)NAL單元的重要性,值越大,越重要。值為0表示這個(gè)NAL單元沒有用于預(yù)測(cè),因此可被解碼器拋棄而不會(huì)有錯(cuò)誤擴(kuò)散;值高于0表示此NAL單元要用于無飄移重構(gòu),且值越高,對(duì)此NAL單元丟失的影響越大。?。?)禁止位 編碼中默認(rèn)值為0,當(dāng)網(wǎng)絡(luò)識(shí)別此單元中存在比特錯(cuò)誤時(shí),可將其設(shè)為1,以便接收方丟掉該單元,主要用于適應(yīng)不同種類的網(wǎng)絡(luò)環(huán)境(比如有線無線相結(jié)合的環(huán)境)。例如對(duì)于從無線到有線的網(wǎng)關(guān),一邊是無線的非IP環(huán)境,一邊是有線網(wǎng)絡(luò)的無比特錯(cuò)誤的環(huán)境。假設(shè)一個(gè)NAL單元到達(dá)無線那邊時(shí),校驗(yàn)和檢測(cè)失敗,網(wǎng)關(guān)可以選擇從NAL流中去掉這個(gè)NAL單元,也可以把已知被破壞的NAL單元前傳給接收端。在這種情況下,智能的解碼器將嘗試重構(gòu)這個(gè)NAL單元(已知它可能包含比特錯(cuò)誤)。而非智能的解碼器將簡(jiǎn)單地拋棄這個(gè)NAL單元。NAL單元結(jié)構(gòu)規(guī)定了用于面向分組或用于流的傳輸子系統(tǒng)的通用格式。在H.320和MPEG-2系統(tǒng)中,NAL單元的流應(yīng)該在NAL單元邊界內(nèi),每個(gè)NAL單元前加一個(gè)3字節(jié)的起始前綴碼。在分組傳輸系統(tǒng)中,NAL單元由系統(tǒng)的傳輸規(guī)程確定幀界,因此不需要上述的起始前綴碼。一組NAL單元被稱為一個(gè)接入單元,定界后加上定時(shí)信息 (SEI),形成基本編碼圖像。該基本編碼圖像(PCP)由一組已編碼的NAL單元組成,其后是冗余編碼圖像(RCP),它是PCP同一視頻圖像的冗余表 示,用于解碼中PCP丟失情況下恢復(fù)信息。如果該編碼視頻圖像是編碼視頻序列的最后一幅圖像,應(yīng)出現(xiàn)序列NAL單元的end,表示該序列結(jié)束。一個(gè)圖像序列只有一個(gè)序列參數(shù)組,并被獨(dú)立解碼。如果該編碼圖像是整個(gè)NAL單元流的最后一幅圖像,則應(yīng)出現(xiàn)流的end。 H.264采用上述嚴(yán)格的接入單元,不僅使H.264可自適應(yīng)于多種網(wǎng)絡(luò),而且進(jìn)一步提高其抗誤碼能力。序列號(hào)的設(shè)置可發(fā)現(xiàn)丟的是哪一個(gè)VCL單元,冗余編碼圖像使得即使基本編碼圖像丟失,仍可得到較“粗糙”的圖像。??
實(shí)現(xiàn)RTP協(xié)議的H.264視頻傳輸系統(tǒng)?1.引言隨著信息產(chǎn)業(yè)的發(fā)展,人們對(duì)信息資源的要求已經(jīng)逐漸由文字和圖片過渡到音頻和視頻,并越來越強(qiáng)調(diào)獲取資源的實(shí)時(shí)性和互動(dòng)性。但人們又面臨著另外一種不可避免的尷尬,就是在網(wǎng)絡(luò)上看到生動(dòng)清晰的媒體演示的同時(shí),不得不為等待傳輸文件而花費(fèi)大量時(shí)間。為了解決這個(gè)矛盾,一種新的媒體技術(shù)應(yīng)運(yùn)而生,這就是流媒體技術(shù)。流媒體由于具有啟動(dòng)時(shí)延小、節(jié)省客戶端存儲(chǔ)空間等優(yōu)勢(shì),逐漸成為人們的首選,流媒體網(wǎng)絡(luò)應(yīng)用也在全球范圍內(nèi)得到不斷的發(fā)展。其中實(shí)時(shí)流傳輸協(xié)議 RTP 詳細(xì)說明了在互聯(lián)網(wǎng)上傳遞音頻和視頻的標(biāo)準(zhǔn)數(shù)據(jù)包格式,它與傳輸控制協(xié)議 RTCP 配合使用,成為流媒體技術(shù)最普遍采用的協(xié)議之一。?
??H.264/AVC 是ITU-T視頻編碼專家組(VCEG)和ISO/IEC動(dòng)態(tài)圖像專家組(MPEG )聯(lián)合組成的聯(lián)合視頻組(JVT)共同努力制訂的新一代視頻編碼標(biāo)準(zhǔn),它最大的優(yōu)勢(shì)是具有很高的數(shù)據(jù)壓縮比率,在同等圖像質(zhì)量的條件下,H.264 的壓縮比是MPEG-2 的2 倍以上,是 MPEG-4的1.5~2 倍。同時(shí),采用視頻編碼層(VCL)和網(wǎng)絡(luò)提取層(NAL )的分層設(shè)計(jì),非常適用于流媒體技術(shù)進(jìn)行實(shí)時(shí)傳輸。本文就是基于 RTP 協(xié)議,對(duì) H.264 視頻進(jìn)行流式打包傳輸,實(shí)現(xiàn)了一個(gè)基本的流媒體服務(wù)器功能,同時(shí)利用開源播放器VLC 作為接收端,構(gòu)成一個(gè)完整的H.264 視頻傳輸系統(tǒng)。
2.RTP 協(xié)議關(guān)鍵參數(shù)的設(shè)置??RTP 協(xié)議是 IETF 在 1996 年提出的適合實(shí)時(shí)數(shù)據(jù)傳輸?shù)男滦蛥f(xié)議。RTP 協(xié)議實(shí)際上是由實(shí)時(shí)傳輸協(xié)議RTP(Real-time Transport Protocol)和實(shí)時(shí)傳輸控制協(xié)議RTCP(Real-time Transport Control Protocol)兩部分組成。RTP 協(xié)議基于多播或單播網(wǎng)絡(luò)為用戶提供連續(xù)媒體數(shù)據(jù)的實(shí)時(shí)傳輸服務(wù);RTCP 協(xié)議是 RTP 協(xié)議的控制部分,用于實(shí)時(shí)監(jiān)控?cái)?shù)據(jù)傳輸質(zhì)量,為系統(tǒng)提供擁塞控制和流控制。RTP 協(xié)議在RFC3550 中有詳細(xì)介紹。每一個(gè) RTP 數(shù)據(jù)包都由固定包頭(Header )和載荷(Payload)兩個(gè)部分組成,其中包頭前12個(gè)字節(jié)的含義是固定的,而載荷則可以是音頻或視頻數(shù)據(jù)。RTP 固定包頭的格式如圖1所示:???????其中比較關(guān)鍵的參數(shù)設(shè)置解釋如下:(1)標(biāo)示位(M ):1 位,該標(biāo)示位的含義一般由具體的媒體應(yīng)用框架(profile )定義, 目的在于標(biāo)記處RTP 流中的重要事件。(2)載荷類型(PT):7 位,用來指出RTP負(fù)載的具體格式。在RFC3551中,對(duì)常用的音視頻格式的RTP 傳輸載荷類型做了默認(rèn)的取值規(guī)定,例如,類型2 表明該RTP數(shù)據(jù)包中承載的是用ITU G.721 算法編碼的語音數(shù)據(jù),采用頻率為 8000HZ,并且采用單聲道。(3)序號(hào):16 位,每發(fā)送一個(gè) RTP?數(shù)據(jù)包,序號(hào)加 1。接受者可以用它來檢測(cè)分組丟失和恢復(fù)分組順序。(4)時(shí)間戳:32?位,時(shí)間戳表示了 RTP?數(shù)據(jù)分組中第一個(gè)字節(jié)的采樣時(shí)間,反映出各RTP 包相對(duì)于時(shí)間戳初始值的偏差。對(duì)于RTP 發(fā)送端而言,采樣時(shí)間必須來源于一個(gè)線性單調(diào)遞增的時(shí)鐘。
??從 RTP?數(shù)據(jù)包的格式不難看出,它包含了傳輸媒體的類型、格式、序列號(hào)、時(shí)間戳以及是否有附加數(shù)據(jù)等信息。這些都為實(shí)時(shí)的流媒體傳輸提供了相應(yīng)的基礎(chǔ)。而傳輸控制協(xié)議RTCP為 RTP傳輸提供了擁塞控制和流控制,它的具體包結(jié)構(gòu)和各字段的含義可參考RFC3550,此處不再贅述。
3.? H.264 基本流結(jié)構(gòu)及其傳輸機(jī)制3.1 ?H.264 基本流的結(jié)構(gòu)H.264 的基本流(elementary stream,ES)的結(jié)構(gòu)分為兩層,包括視頻編碼層(VCL)和網(wǎng)絡(luò)適配層(NAL)。視頻編碼層負(fù)責(zé)高效的視頻內(nèi)容表示,而網(wǎng)絡(luò)適配層負(fù)責(zé)以網(wǎng)絡(luò)所要求的恰當(dāng)?shù)姆绞綄?duì)數(shù)據(jù)進(jìn)行打包和傳送。引入NAL并使之與VCL分離帶來的好處包括兩方面:其一、使信號(hào)處理和網(wǎng)絡(luò)傳輸分離,VCL 和NAL 可以在不同的處理平臺(tái)上實(shí)現(xiàn);其二、VCL 和NAL 分離設(shè)計(jì),使得在不同的網(wǎng)絡(luò)環(huán)境內(nèi),網(wǎng)關(guān)不需要因?yàn)榫W(wǎng)絡(luò)環(huán)境不同而對(duì)VCL比特流進(jìn)行重構(gòu)和重編碼。
H.264 的基本流由一系列NALU?(Network Abstraction Layer Unit )組成,不同的NALU數(shù)據(jù)量各不相同。H.264 草案指出[2],當(dāng)數(shù)據(jù)流是儲(chǔ)存在介質(zhì)上時(shí),在每個(gè)NALU 前添加起始碼:0x000001,用來指示一個(gè) NALU的起始和終止位置。在這樣的機(jī)制下,*在碼流中檢測(cè)起始碼,作為一個(gè)NALU得起始標(biāo)識(shí),當(dāng)檢測(cè)到下一個(gè)起始碼時(shí),當(dāng)前NALU結(jié)束。每個(gè)NALU單元由一個(gè)字節(jié)的 NALU頭(NALU Header)和若干個(gè)字節(jié)的載荷數(shù)據(jù)(RBSP)組成。其中NALU 頭的格式如圖2 所示:????????????????????????????????????????F:forbidden_zero_bit.1 位,如果有語法沖突,則為 1。當(dāng)網(wǎng)絡(luò)識(shí)別此單元存在比特錯(cuò)誤時(shí),可將其設(shè)為 1,以便接收方丟掉該單元。?NRI:nal_ref_idc.2 位,用來指示該NALU 的重要性等級(jí)。值越大,表示當(dāng)前NALU越重要。具體大于0 時(shí)取何值,沒有具體規(guī)定。Type:5 位,指出NALU 的類型。具體如表1 所示:????????????????????????????????????????????????????????????????????????
需要特別指出的是,NRI 值為 7 和 8 的NALU 分別為序列參數(shù)集(sps)和圖像參數(shù)集(pps)。參數(shù)集是一組很少改變的,為大量VCL NALU 提供解碼信息的數(shù)據(jù)。其中序列參數(shù)集作用于一系列連續(xù)的編碼圖像,而圖像參數(shù)集作用于編碼視頻序列中一個(gè)或多個(gè)獨(dú)立的圖像。如果*沒能正確接收到這兩個(gè)參數(shù)集,那么其他NALU?也是無法解碼的。因此它們一般在發(fā)送其它 NALU?之前發(fā)送,并且使用不同的信道或者更加可靠的傳輸協(xié)議(如TCP)進(jìn)行傳輸,也可以重復(fù)傳輸。?3.2? 適用于 H.264 視頻的傳輸機(jī)制前面分別討論了RTP 協(xié)議及H.264基本流的結(jié)構(gòu),那么如何使用RTP協(xié)議來傳輸H.264視頻了?一個(gè)有效的辦法就是從H.264視頻中剝離出每個(gè)NALU,在每個(gè)NALU前添加相應(yīng)的RTP包頭,然后將包含RTP 包頭和NALU 的數(shù)據(jù)包發(fā)送出去。下面就從RTP包頭和NALU兩方面分別闡述。完整的 RTP?固定包頭的格式在前面圖 1 中已經(jīng)指出,根據(jù)RFC3984[3],這里詳細(xì)給出各個(gè)位的具體設(shè)置。?V:版本號(hào),2 位。根據(jù)RFC3984,目前使用的RTP 版本號(hào)應(yīng)設(shè)為0x10。?P:填充位,1 位。當(dāng)前不使用特殊的加密算法,因此該位設(shè)為 0。?X:擴(kuò)展位,1 位。當(dāng)前固定頭后面不跟隨頭擴(kuò)展,因此該位也為 0。?CC:CSRC 計(jì)數(shù),4 位。表示跟在 RTP?固定包頭后面CSRC 的數(shù)目,對(duì)于本文所要實(shí)現(xiàn)的基本的流媒體服務(wù)器來說,沒有用到混合器,該位也設(shè)為 0x0。M:標(biāo)示位,1 位。如果當(dāng)前 NALU為一個(gè)接入單元最后的那個(gè)NALU,那么將M位置 1;或者當(dāng)前RTP 數(shù)據(jù)包為一個(gè)NALU 的最后的那個(gè)分片時(shí)(NALU 的分片在后面講述),M位置 1。其余情況下M 位保持為 0。?PT:載荷類型,7 位。對(duì)于H.264 視頻格式,當(dāng)前并沒有規(guī)定一個(gè)默認(rèn)的PT 值。因此選用大于 95 的值可以。此處設(shè)為0x60(十進(jìn)制96)。SQ:序號(hào),16 位。序號(hào)的起始值為隨機(jī)值,此處設(shè)為 0,每發(fā)送一個(gè)RTP 數(shù)據(jù)包,序號(hào)值加 1。?TS:時(shí)間戳,32 位。同序號(hào)一樣,時(shí)間戳的起始值也為隨機(jī)值,此處設(shè)為0。根據(jù)RFC3984, 與時(shí)間戳相應(yīng)的時(shí)鐘頻率必須為90000HZ。?SSRC:同步源標(biāo)示,32 位。SSRC應(yīng)該被隨機(jī)生成,以使在同一個(gè)RTP會(huì)話期中沒有任何兩個(gè)同步源具有相同的SSRC 識(shí)別符。此處僅有一個(gè)同步源,因此將其設(shè)為0x12345678。
對(duì)于每一個(gè)NALU,根據(jù)其包含的數(shù)據(jù)量的不同,其大小也有差異。在IP網(wǎng)絡(luò)中,當(dāng)要傳輸?shù)腎P 報(bào)文大小超過最大傳輸單元MTU(Maximum Transmission Unit )時(shí)就會(huì)產(chǎn)生IP分片情況。在以太網(wǎng)環(huán)境中可傳輸?shù)淖畲?IP 報(bào)文(MTU)的大小為 1500 字節(jié)。如果發(fā)送的IP數(shù)據(jù)包大于MTU,數(shù)據(jù)包就會(huì)被拆開來傳送,這樣就會(huì)產(chǎn)生很多數(shù)據(jù)包碎片,增加丟包率,降低網(wǎng)絡(luò)速度。對(duì)于視頻傳輸而言,若RTP 包大于MTU 而由底層協(xié)議任意拆包,可能會(huì)導(dǎo)致接收端播放器的延時(shí)播放甚至無法正常播放。因此對(duì)于大于MTU 的NALU 單元,必須進(jìn)行拆包處理。
RFC3984 給出了3 中不同的RTP 打包方案:(1)Single NALU Packet:在一個(gè)RTP 包中只封裝一個(gè)NALU,在本文中對(duì)于小于 1400字節(jié)的NALU 便采用這種打包方案。(2)Aggregation Packet:在一個(gè)RTP 包中封裝多個(gè)NALU,對(duì)于較小的NALU 可以采用這種打包方案,從而提高傳輸效率。?(3)Fragmentation Unit:一個(gè)NALU 封裝在多個(gè)RTP包中,在本文中,對(duì)于大于1400字節(jié)的NALU 便采用這種方案進(jìn)行拆包處理。
4.? H.264 流媒體傳輸系統(tǒng)的實(shí)現(xiàn)??一個(gè)完整的流媒體傳輸系統(tǒng)包含服務(wù)器端和客戶端兩個(gè)部分[5][6]。對(duì)于服務(wù)器端,其主要任務(wù)是讀取H.264 視頻,從碼流中分離出每個(gè)NALU 單元,分析NALU 的類型,設(shè)置相應(yīng)的 RTP?包頭,封裝 RTP?數(shù)據(jù)包并發(fā)送。而對(duì)于客戶端來說,其主要任務(wù)則是接收 RTP數(shù)據(jù)包,從RTP 包中解析出NALU 單元,然后送至*進(jìn)行解碼播放。該流媒體傳輸系統(tǒng)的框架如圖3 所示。?
5.?結(jié)論本文所設(shè)計(jì)的流媒體傳輸系統(tǒng)服務(wù)器端運(yùn)行在Windows XP 系統(tǒng),用VLC 播放器作為客戶端接收H.264 視頻RTP 數(shù)據(jù)包。經(jīng)測(cè)試,客戶端在經(jīng)過2 秒的緩沖過后即能流暢播放,傳輸速度設(shè)為 30 幀每秒的情況下,未出現(xiàn)丟包拖影等現(xiàn)象,視頻主觀質(zhì)量良好,與本地播放該H.264 視頻無明顯區(qū)別。
AnyChat采用國際領(lǐng)先的視頻編碼標(biāo)準(zhǔn)H.264(MPEG-4 part 10 AVC /H.264)編碼,H.264/AVC 在壓縮效率方面有著特殊的表現(xiàn),一般情況下達(dá)到 MPEG-2 及 MPEG-4 簡(jiǎn)化類壓縮效率的大約 2 倍。H.264具有許多與舊標(biāo)準(zhǔn)不同的新功能,它們一起實(shí)現(xiàn)了編碼效率的提高。特別是在幀內(nèi)預(yù)測(cè)與編碼、幀間預(yù)測(cè)與編碼、可變矢量塊大小、四分之一像素運(yùn)動(dòng)估計(jì)、多參考幀預(yù)測(cè)、自適應(yīng)環(huán)路去塊濾波器、整數(shù)變換、量化與變換系數(shù)掃描、熵編碼、加權(quán)預(yù)測(cè)等實(shí)現(xiàn)上都有其獨(dú)特的考慮。
佰銳科技采用先進(jìn)去馬賽克技術(shù),保障在視頻通訊過程中不出現(xiàn)花屏、馬賽克等現(xiàn)象。免費(fèi)測(cè)試下載地址:http://www2.bairuitech.com/downloads/bairuisoft/AnyChatCoreSDK_V3.0.rar?H264 視頻文件 幀格式 傳輸封裝等 雜碎rfc3984?Standards Track [Page 2] RFC 3984 RTP Payload Format for H.264 Video February 2005 1.按照RFC3984協(xié)議實(shí)現(xiàn)H264視頻流媒體
nalu單元 包起始 0x 00 00 00 01
H.264 NAL格式及分析器http://hi.baidu.com/zsw%5Fdavy/b ... c409cc7cd92ace.htmlhttp://hi.baidu.com/zsw_davy/blo ... 081312c8fc7acc.html
----------------------------------比特流信息----------------------------------------------
①NALU(Network Abstract Layer Unit):兩標(biāo)準(zhǔn)中的比特流都是以NAL為單位,每個(gè)NAL單元包含一個(gè)RBSP,NALU的頭信息定義了RBSP所屬類型。類型一般包括序列參數(shù)集(SPS)、圖像參數(shù)集(PPS)、增強(qiáng)信息(SEI)、條帶(Slice)等,其中,SPS和PPS屬于參數(shù)集,兩標(biāo)準(zhǔn)采用參數(shù)集機(jī)制是為了將一些主要的序列、圖像參數(shù)(解碼圖像尺寸、片組數(shù)、參考幀數(shù)、量化和濾波參數(shù)標(biāo)記等)與其他參數(shù)分離,通過解碼器先解碼出來。此外,為了增強(qiáng)圖像的清晰度,AVS-M添加了圖像頭(Picture head)信息。讀取NALU流程中,每個(gè)NALU前有一個(gè)起始碼0x000001,為防止內(nèi)部0x000001序列競(jìng)爭(zhēng),H.264編碼器在最后一字節(jié)前插入一個(gè)新的字節(jié)——0x03,所以解碼器檢測(cè)到該序列時(shí),需將0x03刪掉,而AVS-M只需識(shí)別出起始碼0x000001。
②讀取宏塊類型(mb type)和宏塊編碼模板(cbp):編解碼圖像以宏塊劃分,一個(gè)宏塊由一個(gè)16*16亮度塊和相應(yīng)的一個(gè)8*8cb和一個(gè)8*8cr色度塊組成。
(a) 兩標(biāo)準(zhǔn)的幀內(nèi)、幀間預(yù)測(cè)時(shí)宏塊的劃分是有區(qū)別的。H.264中,I_slice亮度塊有Intra_4*4和Intra_16*16兩種模式,色度塊只有8*8模式;P_slice宏塊分為16*16、16*8、8*16、8*8、8*4、4*8、4*4共7種模式。而AVS-M中,I_slice亮度塊有I_4*4和I_Direct兩模式,P_slice時(shí)宏塊的劃分和H.264中的劃分一致。
(b) 兩標(biāo)準(zhǔn)的宏塊cbp值計(jì)算也不相同。H.264中,Intra_16*16宏塊的亮度(色度)cbp直接通過讀mb type得到;非Intra_16*16宏塊的亮度cbp=coded_block_pattern%16,色度cbp=coded_block_pattern/16 。其中,亮度cbp最低4位有效,每位決定對(duì)應(yīng)宏塊的殘差系數(shù)能不能為0;色度cbp為0時(shí),對(duì)應(yīng)殘差系數(shù)為0,cbp為1時(shí),DC殘差系數(shù)不為0,AC系數(shù)為0,cbp為2時(shí),DC、AC殘差系數(shù)都不為0。AVS-M中,當(dāng)宏塊類型不是P_skip時(shí),直接從碼流中得到cbp的索引值,并以此索引值查表得到codenum值,再以codenum查表分別得到幀內(nèi)/幀間cbp。此cbp為6位,每位代表宏塊按8*8劃分時(shí)能不能包含非零系數(shù),當(dāng)變換系數(shù)不為0時(shí),需進(jìn)一步讀cbp_4*4中每位值來判斷一個(gè)8*8塊中4個(gè)4*4塊的系數(shù)能不能為0。------------------------------------------------------------------------------------------
總的來說H264的碼流的打包方式有兩種:一種為annex-b byte stream format的格式,這個(gè)是絕大部分編碼器的默認(rèn)輸出格式,就是每個(gè)幀的開頭的3~4個(gè)字節(jié)是H264的start_code,0x00000001或者0x000001。另一種是原始的NAL打包格式,就是開始的若干字節(jié)(1,2,4字節(jié))是NAL的長度,而不是start_code,此時(shí)必須借助某個(gè)全局的數(shù)據(jù)來獲得編碼器的profile,level,PPS,SPS等信息才可以解碼。
AVC vs. H.264AVC and H.264 are synonymous. The standard is known by the full names "ISO/IEC 14496-10" and "ITU-T Recommendation H.264". In addition, a number of alternate names are used (or have been) in reference to this standard. These include:MPEG-4 part 10MPEG-4 AVCAVCMPEG-4 (in the broadcasting world MPEG4 part 2 is ignored)H.264JVT (Joint Video Team, nowadays rarely used referring to actual spec)H.26L (early drafts went by this name)
All of the above (and those I've missed) include the?Annex B byte-stream format. Unlike earlier MPEG1/2/4 and H.26x codecs, the H.264 specification proper does not define a full bit-stream syntax. It describes a number of NAL (Network Abstraction Layer) units, a sequence of which can be decoded into video frames. These NAL units have no boundary markers, and rely on some unspecified format to provide framing.
Annex B of of the document specifies one such format, which wraps NAL units in a format resembling a traditional MPEG video elementary stream, thus making it suitable for use with containers like MPEG PS/TS unable to provide the required framing. Other formats, such as ISO base media based formats, are able to properly separate the NAL units and do not need the Annex B wrapping.
The H.264 spec suffers from a deficiency. It defines several header-type NAL units (SPS and PPS) without specifying how to pack them into the single codec data field available in most containers. Fortunately, most containers seem to have adopted the packing used by the ISO format known as MP4.
1. H.264起始碼在網(wǎng)絡(luò)傳輸h264數(shù)據(jù)時(shí),一個(gè)UDP包就是一個(gè)NALU,解碼器可以很方便的檢測(cè)出NAL分界和解碼。但是如果編碼數(shù)據(jù)存儲(chǔ)為一個(gè)文件,原來的解碼器將無法從數(shù)據(jù)流中分別出每個(gè)NAL的起始位置和終止位置,為此h.264用起始碼來解決這一問題。
H.264編碼時(shí),在每個(gè)NAL前添加起始碼 0x000001,解碼器在碼流中檢測(cè)到起始碼,當(dāng)前NAL結(jié)束。為了防止NAL內(nèi)部出現(xiàn)0x000001的數(shù)據(jù),h.264又提出"防止競(jìng)爭(zhēng) emulation prevention"機(jī)制,在編碼完一個(gè)NAL時(shí),如果檢測(cè)出有連續(xù)兩個(gè)0x00字節(jié),就在后面插入一個(gè)0x03。當(dāng)解碼器在NAL內(nèi)部檢測(cè)到0x000003的數(shù)據(jù),就把0x03拋棄,恢復(fù)原始數(shù)據(jù)。0x000000?? >>>>>>?? 0x000003000x000001?? >>>>>>?? 0x000003010x000002?? >>>>>>?? 0x000003020x000003?? >>>>>>?? 0x00000303
附上h.264解碼nalu中檢測(cè)起始碼的算法流程??for(;;)?{if next 24 bits are 0x000001?{??? ??? startCodeFound = true??? ??? break;?}?else?{??? ??? flush 8 bits??}?}// for(;;)?if(true == startCodeFound)?{???? //startcode found???? // Flush the start code found???? flush 24 bits????? //Now navigate up to next start code and put the in between stuff???? // in the nal structure.???? for(;;)??? {??? ?? get next 24 bits & check if it equals to 0x000001??? ?? if(false == (next 24 bits == 000001))??? ?? {??? ?? ?? // search for pattern 0x000000??? ?? ?? check if next 24 bits are 0x000000??? ?? ?? if(false == result)??? ?? ?? {??? ?? ?? ?? ??? // copy the byte into the buffer??? ?? ?? ?? ??? copy one byte to the Nal unit ?? ?? ?? ????? ?? ?? }??? ?? ?? else??? ?? ?? {??? ?? ?? ?? ??? break;??? ?? ?? }??? ?? }??? ?? else??? ?? {??? ?? ?? ??? break;??? ?? }??? }//for(;;)}
2. MPEG4起始碼MPEG4的特色是VOP,沒有NALU的概念,仍使用startcode對(duì)每幀進(jìn)行分界。MPEG4的起始碼是0x000001. 另外MPEG4中很多起始碼也很有用,比如video_object_sequence_start_code 0x000001B0 表示一個(gè)視頻對(duì)象序列的開始,VO_start_code 0x000001B6 表示一個(gè)VOP的開始. 0x000001B6之后的兩位,是00表示 I frame, 01 表示 P frame, 10 表示 B frame.
1.引言
H.264的主要目標(biāo):
1.高的視頻壓縮比
2.良好的網(wǎng)絡(luò)親和性
解決方案:VCL?? video coding layer ?? 視頻編碼層NAL?? network abstraction layer?? 網(wǎng)絡(luò)提取層
VCL:核心算法引擎塊,宏塊及片的語法級(jí)別的定義NAL:片級(jí)以上的語法級(jí)別(如序列參數(shù)集和圖像參數(shù)集),同時(shí)支持以下功能:獨(dú)立片解碼,起始碼唯一保證,SEI以及流格式編碼數(shù)據(jù)傳送
VCL設(shè)計(jì)目標(biāo):盡可能地獨(dú)立于網(wǎng)絡(luò)的情況下進(jìn)行高效的編解碼NAL設(shè)計(jì)目標(biāo):根據(jù)不同的網(wǎng)絡(luò)把數(shù)據(jù)打包成相應(yīng)的格式,將VCL產(chǎn)生的比特字符串適配到各種各樣的網(wǎng)絡(luò)和多元環(huán)境中。NALU頭結(jié)構(gòu):NALU類型(5bit)、重要性指示位(2bit)、禁止位(1bit)。?NALU類型:1~12由H.264使用,24~31由H.264以外的應(yīng)用使用。?重要性指示:標(biāo)志該NAL單元用于重建時(shí)的重要性,值越大,越重要。?禁止位:網(wǎng)絡(luò)發(fā)現(xiàn)NAL單元有比特錯(cuò)誤時(shí)可設(shè)置該比特為1,以便接收方丟掉該單元。?
2.NAL語法語義NAL層句法:在編碼器輸出的碼流中,數(shù)據(jù)的基本單元是句法元素。句法表征句法元素的組織結(jié)構(gòu)。語義闡述句法元素的具體含義。分組都有頭部,解碼器可以很方便的檢測(cè)出NAL的分界,依次取出NAL進(jìn)行解碼。但為了節(jié)省碼流,H.264沒有另外在NAL的頭部設(shè)立表示起始位置的句法元素。如果編碼數(shù)據(jù)是存儲(chǔ)在介質(zhì)上的,由于NAL是依次緊密相連的,解碼器就無法在數(shù)據(jù)流中分辨出每個(gè)NAL的起始位置和終止位置。
解決方案:在每個(gè)NAL前添加起始碼:0X000001
在某些類型的介質(zhì)上,為了尋址的方便,要求數(shù)據(jù)流在長度上對(duì)齊,或某個(gè)常數(shù)的整數(shù)倍。所以在起始碼前添加若干字節(jié)的0來填充。
檢測(cè)NAL的開始:0X000001和0X000000我們必須考慮當(dāng)NAL內(nèi)部出現(xiàn)了0X000001和0X000000解決方案:H.264提出了“防止競(jìng)爭(zhēng)”機(jī)制:0X000000——0X000003000X000001——0X000003010X000002——0X000003020X000003——0X00000303為此,我們可以知道:在NAL單元中,下面的三字節(jié)序列不應(yīng)在任何字節(jié)對(duì)齊的位置出現(xiàn)
0X000000
0X000001
0X000002
Forbidden_zero_bit =0;
Nal_ref_idc:表示NAL的優(yōu)先級(jí)。0~3,取值越大,表示當(dāng)前NAL越重要,需要優(yōu)先受到保護(hù)。如果當(dāng)前NAL是屬于參考幀的片,或是序列參數(shù)集,或是圖像參數(shù)集這些重要的單位時(shí),本句法元素必需大于0。Nal_unit_type:當(dāng)前NAL 單元的類型
3.H.264的NAL層處理結(jié)構(gòu)示意圖:NAL以NALU(NAL unit)為單元來支持編碼數(shù)據(jù)在基于分組交換技術(shù)網(wǎng)絡(luò)中傳輸。它定義了符合傳輸層或存儲(chǔ)介質(zhì)要求的數(shù)據(jù)格式,同時(shí)給出頭信息,從而提供了視頻編碼和外部世界的接口。NALU:定義了可用于基于分組和基于比特流系統(tǒng)的基本格式RTP封裝:只針對(duì)基于NAL單元的本地NAL接口。
三種不同的數(shù)據(jù)形式:SODB 數(shù)據(jù)比特串-->最原始的編碼數(shù)據(jù)RBSP 原始字節(jié)序列載荷-->在SODB的后面填加了結(jié)尾比特(RBSP trailing bits 一個(gè)bit“1”)若干比特“0”,以便字節(jié)對(duì)齊EBSP 擴(kuò)展字節(jié)序列載荷-->在RBSP基礎(chǔ)上填加了仿校驗(yàn)字節(jié)(0X03)它的原因是: 在NALU加到Annexb上時(shí),需要添加每組NALU之前的開始碼StartCodePrefix,如果該NALU對(duì)應(yīng)的slice為一幀的開始則用4位字節(jié)表示,ox00000001,否則用3位字節(jié)表示ox000001.為了使NALU主體中不包括與開始碼相沖突的,在編碼時(shí),每遇到兩個(gè)字節(jié)連續(xù)為0,就插入一個(gè)字節(jié)的0x03。解碼時(shí)將0x03去掉。也稱為脫殼操作
處理過程:1.將VCL層輸出的SODB封裝成nal_unit, Nal_unit是一個(gè)通用封裝格式,可以適用于有序字節(jié)流方式和IP包交換方式。2.針對(duì)不同的傳送網(wǎng)絡(luò)(電路交換|包交換),將nal_unit 封裝成針對(duì)不同網(wǎng)絡(luò)的封裝格 式。
第一步的具體過程:VCL層輸出的比特流SODB(String Of Data Bits),到nal_unit之間,經(jīng)過了以下三步處理:
1.SODB字節(jié)對(duì)齊處理后封裝成RBSP(Raw Byte Sequence Payload)。
2.為防止RBSP的字節(jié)流與有序字節(jié)流傳送方式下的SCP(start_code_prefix_one_3bytes,0x000001)出現(xiàn)字節(jié)競(jìng)爭(zhēng)情形,循環(huán)檢測(cè)RBSP前三個(gè)字節(jié),在出現(xiàn)字節(jié)競(jìng)爭(zhēng)時(shí)在第三字節(jié)前加入emulation_prevention_three_byte (0x03),具體方法:
nal_unit( NumBytesInNALunit ) {
forbidden_zero_bit
nal_ref_idc
nal_unit_type
NumBytesInRBSP = 0
for( i = 1; i < NumBytesInNALunit; i++ ) {
if( i + 2 < NumBytesInNALunit && next_bits( 24 ) = = 0x000003 ) {
rbsp_byte[ NumBytesInRBSP++ ]
rbsp_byte[ NumBytesInRBSP++ ]
i += 2
emulation_prevention_three_byte /* equal to 0x03 */
} else
rbsp_byte[ NumBytesInRBSP++ ]
}
}
3. 防字節(jié)競(jìng)爭(zhēng)處理后的RBSP再加一個(gè)字節(jié)的header(forbidden_zero_bit+ nal_ref_idc+ nal_unit_type),封裝成nal_unit.
第二步的具體過程:case1:有序字節(jié)流的封裝
byte_stream_nal_unit( NumBytesInNALunit ) {?
while( next_bits( 24 ) != 0x000001 )?
zero_byte /* equal to 0x00 */?
if( more_data_in_byte_stream( ) ) {?
start_code_prefix_one_3bytes /* equal to 0x000001 */ nal_unit( NumBytesInNALunit )
}?
}?
類似H.320和MPEG-2/H.222.0等傳輸系統(tǒng),傳輸NAL作為有序連續(xù)字節(jié)或比特流,同時(shí)要依靠數(shù)據(jù)本身識(shí)別NAL單元邊界。在這樣的應(yīng)用系統(tǒng)中,H.264/AVC規(guī)范定義了字節(jié)流格式,每個(gè)NAL單元前面增加3個(gè)字節(jié)的前綴,即同步字節(jié)。在比特流應(yīng)用中,每個(gè)圖像需要增加一個(gè)附加字節(jié)作為邊界定位。還有一種可選特性,在字節(jié)流中增加附加數(shù)據(jù),用做擴(kuò)充發(fā)送數(shù)據(jù)量,能實(shí)現(xiàn)快速邊界定位,恢復(fù)同步
Case2:IP網(wǎng)絡(luò)的RTP打包封裝
分組打包的規(guī)則?(1)額外開銷要少,使MTU尺寸在100~64k字節(jié)范圍都可以;?(2)不用對(duì)分組內(nèi)的數(shù)據(jù)解碼就可以判別該分組的重要性;?(3)載荷規(guī)范應(yīng)當(dāng)保證不用解碼就可識(shí)別由于其他的比特丟失而造成的分組不可解碼;?(4)支持將NALU分割成多個(gè)RTP分組;?(5)支持將多個(gè)NALU匯集在一個(gè)RTP分組中。?
RTP的頭標(biāo)可以是NALU的頭標(biāo),并可以實(shí)現(xiàn)以上的打包規(guī)則。?
一個(gè)RTP分組里放入一個(gè)NALU,將NALU(包括同時(shí)作為載荷頭標(biāo)的NALU頭)放入RTP的載荷中,設(shè)置RTP頭標(biāo)值。為了避免IP層對(duì)大分組的再一次分割,片分組的大小一般都要小于MTU尺寸。由于包傳送的路徑不同,解碼端要重新對(duì)片分組排序,RTP包含的次序信息可以用來解決這一問題。
NALU分割?
對(duì)于預(yù)先已經(jīng)編碼的內(nèi)容,NALU可能大于MTU尺寸的限制。雖然IP層的分割可以使數(shù)據(jù)塊小于64千字節(jié),但無法在應(yīng)用層實(shí)現(xiàn)保護(hù),從而降低了非等重保護(hù)方案的效果。由于UDP數(shù)據(jù)包小于64千字節(jié),而且一個(gè)片的長度對(duì)某些應(yīng)用場(chǎng)合來說太小,所以應(yīng)用層打包是RTP打包方案的一部分。
新的討論方案(IETF)應(yīng)當(dāng)符合以下特征:?(1)NALU的分塊以按RTP次序號(hào)升序傳輸;?(2)能夠標(biāo)記第一個(gè)和最后一個(gè)NALU分塊;?(3)可以檢測(cè)丟失的分塊。?
NALU合并?一些NALU如SEI、參數(shù)集等非常小,將它們合并在一起有利于減少頭標(biāo)開銷。已有兩種集合分組:?(1)單一時(shí)間集合分組(STAP),按時(shí)間戳進(jìn)行組合;?(2)多時(shí)間集合分組(MTAP),不同時(shí)間戳也可以組合。
NAL規(guī)范視頻數(shù)據(jù)的格式,主要是提供頭部信息,以適合各種媒體的傳輸和存儲(chǔ)。NAL支持各種網(wǎng)絡(luò),包括:1.任何使用RTP/IP協(xié)議的實(shí)時(shí)有線和無線Internet 服務(wù)2.作為MP4文件存儲(chǔ)和多媒體信息文件服務(wù)3.MPEG-2系統(tǒng)4.其它網(wǎng)?
NAL規(guī)定一種通用的格式,既適合面向包傳輸,也適合流傳送。實(shí)際上,包傳輸和流傳輸?shù)姆绞绞窍嗤?,不同之處是傳輸前面增加了一個(gè)起始碼前綴
在類似Internet/RTP面向包傳送協(xié)議系統(tǒng)中,包結(jié)構(gòu)中包含包邊界識(shí)別字節(jié),在這種情況下,不需要同步字節(jié)。
NAL單元分為VCL和非VCL兩種
VCL NAL單元包含視頻圖像采樣信息,
非VCL包含各種有關(guān)的附加信息,例如參數(shù)集(頭部信息,應(yīng)用到大量的VCL NAL單元)、提高性能的附加信息、定時(shí)信息等
參數(shù)集:
參數(shù)集是很少變化的信息,用于大量VCL NAL單元的解碼,分為兩種類型:1.序列參數(shù)集,作用于一串連續(xù)的視頻圖像,即視頻序列。兩個(gè)IDR圖像之間為序列參數(shù)集。IDR和I幀的區(qū)別見下面。
2.圖像參數(shù)集,作用于視頻序列中的一個(gè)或多個(gè)個(gè)別的圖像序列和圖像參數(shù)集機(jī)制,減少了重復(fù)參數(shù)的傳送,每個(gè)VCL NAL單元包含一個(gè)標(biāo)識(shí),指向有關(guān)的圖像參數(shù)集,每個(gè)圖像參數(shù)集包含一個(gè)標(biāo)識(shí),指向有關(guān)的序列參數(shù)集的內(nèi)容 因此,只用少數(shù)的指針信息,引用大量的參數(shù),大大減少每個(gè)VCL NAL單元重復(fù)傳送的信息。
序列和圖像參數(shù)集可以在發(fā)送VCL NAL單元以前發(fā)送,并且重復(fù)傳送,大大提高糾錯(cuò)能力。序列和圖像參數(shù)集可以在“帶內(nèi)”,也可以用更為可靠的其他“帶外”通道傳送。