劉敏慧,賀波濤
(1.武漢郵電科學(xué)研究院,湖北武漢430074;2.武漢烽火眾智數(shù)字技術(shù)有限公司,湖北武漢430074)
隨著我國經(jīng)濟和社會的發(fā)展,網(wǎng)絡(luò)視頻監(jiān)控在城鄉(xiāng)治安、交通等方面日益發(fā)揮著重要的作用,流媒體編解碼和監(jiān)控視頻實時傳輸?shù)燃夹g(shù)是網(wǎng)絡(luò)視頻監(jiān)控的關(guān)鍵技術(shù)[1]。從如今的編解碼技術(shù)來看,被市場廣泛采用的是H.264 標(biāo)準(zhǔn),同時新一代的H.265 標(biāo)準(zhǔn)市場占比正在穩(wěn)步提升,其優(yōu)秀的視頻壓縮性能可以節(jié)約傳輸帶寬和存儲空間[2]。同時,網(wǎng)絡(luò)視頻監(jiān)控[3]對實時的網(wǎng)絡(luò)傳輸有很大需求[4],實時傳輸協(xié)議(Real-time Transport Protocol,RTP)[5]解決了該問題,RTP 可采用用戶數(shù)據(jù)包協(xié)議(User Datagram Protocol,UDP)來實時傳輸數(shù)據(jù),攝像頭在采集到監(jiān)控視頻后,其H.265 碼流會被封裝在RTP信息包中,RTP 信息包被再次封裝為UDP 的負載,最終封裝在ip 數(shù)據(jù)包的負載中。文中研究的內(nèi)容是如何從Wireshark 抓取的RTP 包中提取出H.265碼流并保存,且實現(xiàn)該碼流的高清流暢播放,保存的H.265 碼流可用作關(guān)鍵幀的提取、轉(zhuǎn)碼及圖像處理研究,具有較高的研究價值。
H.265 是繼H.264 之后,由ITU-T VCEG 組織發(fā)布的新一代視頻編碼標(biāo)準(zhǔn)[6]。H.265 標(biāo)準(zhǔn)基于現(xiàn)有的H.264 視頻編碼標(biāo)準(zhǔn)[7],保留了一部分原有技術(shù),同時改進了一些相關(guān)技術(shù)。新標(biāo)準(zhǔn)使用先進的技術(shù)來改善碼流、編碼質(zhì)量、延遲和算法復(fù)雜度之間的關(guān)系,以實現(xiàn)最佳設(shè)置。具體研究內(nèi)容包括提高壓縮效率、提高魯棒性和錯誤恢復(fù)能力、降低實時時延、降低信道采集時間和隨機訪問時延、降低復(fù)雜度[8]。HEVC[9]不僅提升視頻質(zhì)量,而且在相同的視頻質(zhì)量的情況下,相比H.264 實現(xiàn)了兩倍的壓縮率,同時可支持4K清晰度,甚至最高清晰度可達到8K(8 192×4 320)[10]。
H.265 碼流[11]的圖像幀序列由起始碼(00 00 00 01 或00 00 01)、VPS、SPS、PPS、SEI、IDR 幀、P 幀、B幀、I幀等組成。
網(wǎng)絡(luò)抽象層(Network Abstraction Layer,NAL)是H.265 視頻編碼標(biāo)準(zhǔn)的一部分,NAL 負責(zé)格式化視頻數(shù)據(jù)并提供頭信息,從而保證視頻數(shù)據(jù)在各種信道和存儲介質(zhì)上的穩(wěn)定傳輸。H.265 碼流由一系列的NALU 組成,每個VPS、SPS、PPS、SEI、I 幀、P 幀都可以稱為一個NALU,常見NALU 類型如表1所示。
表1 常見NALU類型
NALU 的結(jié)構(gòu)為NALU 頭+NALU 負載。H.265碼流的NALU 頭由兩個字節(jié)組成,它的語法如圖1所示。
圖1 NALU結(jié)構(gòu)/FU indicator結(jié)構(gòu)
F:1 bit,forbidden_zero_bit,在H.265 規(guī)范中規(guī)定了這一位必須為0。禁止位0 表示正常,1 表示錯誤,一般都是0。Type:6 bit,nal_unit_type,常見NALU 類型如表1所示。LayerID:6 bit,nuh_reserved_zero_6bits,為0。TID:3 bit,nuh_temporal_id_plus1,為1。
從RTP 數(shù)據(jù)包中提取H.265 碼流,首先需要抓取數(shù)據(jù)包。Wireshark 作為全世界最為流行的網(wǎng)絡(luò)封包分析軟件之一,可以抓取網(wǎng)絡(luò)封包,并且盡可能地顯示出最為詳細的信息。抓取的數(shù)據(jù)包可以保存為pcap 格式[12]的文件,文中就是從包含已抓取數(shù)據(jù)包的pcap 文件中提取H.265 碼流信息的[13]。pcap 文件的格式如圖2所示。
圖2 pcap文件格式
文中需要抓取的是攜帶著H.265 碼流信息的RTP 數(shù)據(jù)包,抓取時不可避免地捕獲ARP、TCP 等非必須數(shù)據(jù)包,可用Wireshark 本身的過濾規(guī)則來除去,也可在自制的提取碼流方案中添加規(guī)則過濾。文中推薦使用第二種方法,該方法普適性更好,給研發(fā)人員的自主性更大,在提取時也不會因為個別包的疏漏而出現(xiàn)問題。
從pcap 文件中提取H.265 碼流,需要獲取H.265碼流在網(wǎng)絡(luò)傳輸時的打包方式。文中的H.265 碼流在傳輸層采用的是UDP 協(xié)議,UDP 是開放式系統(tǒng)互聯(lián)(Open System Interconnection,OSI)參考模型中的一種無連接的傳輸層協(xié)議。相比于傳輸層另一種協(xié)議——傳輸控制協(xié)議(Transport Control Protocol,TCP),UDP 雖然提供不可靠的信息傳輸服務(wù),但它額外開銷小、時延短、無連接,非常適合多媒體數(shù)據(jù)流的傳輸,在文中情況下,UDP 也是個好選擇[14]。
RTP 協(xié)議[15]規(guī)定了在互聯(lián)網(wǎng)上傳輸視頻和音頻的標(biāo)準(zhǔn)數(shù)據(jù)包格式,它創(chuàng)建在UDP 之上,并與之結(jié)合使用,方便RTP 使用其端口號和效驗服務(wù),依托UDP低傳輸時延的特點,更好地匹配視頻傳輸業(yè)務(wù)。
RTP 包由包頭和負載兩部分組成[16],H.265 碼流數(shù)據(jù)存儲在RTP 數(shù)據(jù)包的負載中,其包頭中存儲了負載類型(payload typePT)、序列號(Sequence Number)、時間戳(Timestamp)、同步源標(biāo)識符(SSRC)等信息,包頭的信息不是必要的,在設(shè)計時可以直接偏移12 字節(jié)到負載部分。
在以太網(wǎng)中,數(shù)據(jù)鏈路層能夠確定發(fā)送的一個數(shù)據(jù)包的最大長度稱為最大傳輸單元(Maximum Transmission Unit,MTU),為1 500 字節(jié),文中采用的監(jiān)控視頻的分辨率是1 920×1 080,由于通過H.265標(biāo)準(zhǔn)壓縮后的每幀圖像遠遠超過1 500 字節(jié),因此為了實現(xiàn)H.265 碼流在網(wǎng)絡(luò)上的傳輸,必須對每幀圖像進行分割再打包成適合在以太網(wǎng)上傳輸?shù)拇笮『线m的RTP 數(shù)據(jù)包。
上文已知H.265 碼流由一系列的NALU 組成,每個VPS、SPS、PPS、SEI、I 幀、P 幀都可以稱為一個NALU,不同類型的NALU 之間大小差距很大[17]。對于VPS、SPS、PPS、SEI 等小于MTU 的NALU,打包時只需將該NALU 去掉起始碼并添加在RTP 包頭后即可。對于I 幀、P 幀等大于MTU 的NALU,使用FU 打包,就是將一個NALU 分片打包成幾個RTP 數(shù)據(jù)包,即fragmentation unit,簡稱FU。每個分片單元為12字節(jié)的RTP 包頭和2 字節(jié)的FU indicator、1 個字節(jié)的FU Header 及被分割的H.265 碼流段的組合。RTP 包負載結(jié)構(gòu)如圖3所示。
圖3 RTP負載結(jié)構(gòu)
首先分析FU indicator 結(jié)構(gòu),如圖1所示,與上文NALU 頭的格式完全一致。F:1 bit,為禁止位,通常情況下為0。Type:6 bit,表示的是分片封包的類型,NALU 的Type 表示當(dāng)前NALU(幀)的類型,在文中為49。LayerId 為0,TID 為1。如圖4所示,F(xiàn)U Header 結(jié)構(gòu)中,S:1 bit,開始位,若為1 表示分片NAL 單元的開始。若跟隨的FU 負載不是分片NALU 的首個包,則開始位為0。E:1 bit,結(jié)束位,若為1,則表示分片NALU 的結(jié)束,即跟隨的FU 負載是分片NALU 的最后一個包,當(dāng)跟隨的FU 負載不是分片NALU 的最后分片時,結(jié)束位設(shè)為0。此結(jié)構(gòu)中的Type 表示被分片的原始圖像幀的類型,注意與FU indicator 中的Type 相區(qū)別。
圖4 FU Header結(jié)構(gòu)
文中抓取的RTP 數(shù)據(jù)包存儲在pcap 文件中,若要提取RTP 數(shù)據(jù)包負載的H.265 碼流,則需要去掉不需要網(wǎng)絡(luò)傳輸中添加的各種頭信息,如pcap 文件頭、pcap 數(shù)據(jù)包頭、數(shù)據(jù)鏈路層頭、ip 頭、UDP 頭、RTP 頭等,并為每個NALU 恢復(fù)起始碼及分片包的原始NALU 頭。
根據(jù)圖5,在用UDP 頭的src_port 來判定是否為文中所需數(shù)據(jù)包時,需要先做一些準(zhǔn)備工作,根據(jù)圖2pacp 文件結(jié)構(gòu)解析,為了獲得負載上的H.265 碼流數(shù)據(jù),首先將pcap 文件的24 字節(jié)文件頭去掉,對于單個pacp 的數(shù)據(jù)包n,需去掉數(shù)據(jù)包頭n,使用包頭信息的caplen 項作為遍歷指針的偏移依據(jù),以實現(xiàn)對每個pcap 數(shù)據(jù)包負載的遍歷。
圖5 pcap文件中的H.265碼流提取
通過src_port 確定了是否為所需RTP 包,若為假則繼續(xù)遍歷pcap 文件,若為真則開始寫H.265 輸出文件。首先寫入起始碼,判斷該RTP 包是否為分片包,若為假,則直接將RTP 負載寫入輸出文件;若為真且為圖像幀的首個分片包[18],則將FU indicator 的Type 位清零,并與FU Header 的Type 位組合為新的NALU 頭,將其寫入H.265 輸出文件。去掉RTP 數(shù)據(jù)包的RTP 頭和FU 分片頭,將剩余的負載部分寫入H.265 輸出文件,若非圖像幀的首個分片包,則只需去掉RTP 數(shù)據(jù)包的RTP 頭和FU 分片頭并將RTP數(shù)據(jù)包的剩余部分寫入H.265 輸出文件,每處理完一個RTP 數(shù)據(jù)包就繼續(xù)遍歷pcap 文件,直至文件結(jié)束。
提取H.265 視頻完成后可用ffplay 進行播放,直接用VLC 多媒體播放器(Video LAN Client,VLC)拉流播放的效果如圖6所示。文中提取的H.265 碼流播放效果如圖7所示,由圖7可看出,圖像質(zhì)量已還原成攝像頭直接采集的播放效果。
圖6 VLC拉流播放效果
圖7 文中提取的H.265碼流播放效果
文中通過對H.265 碼流結(jié)構(gòu)、RTP 打包方式、pcap 文件格式及數(shù)據(jù)包在以太網(wǎng)上的傳輸?shù)钠饰?,設(shè)計并實現(xiàn)了從網(wǎng)絡(luò)上抓取H.265 碼流并將其從保存的pcap 文件中提取出來,提取成功的H.265 碼流文件可用作標(biāo)準(zhǔn)H.265 序列,也可以用來提取I 幀、B幀等,利于對單幀圖像進行研究。在工程上,該提取視頻的實現(xiàn)方法能為廣大的視頻開發(fā)人員提供一些參考,便于分析RTP 包和視頻幀序列。對于廣大視頻用戶來說,每次視頻方面研究的完成,都預(yù)示著將來更清晰、更高幀率、更小帶寬的視頻服務(wù)。