1. 程式人生 > >H264碼流和Mp4結構詳解

H264碼流和Mp4結構詳解

一、概述

本文講述的是對H264編碼且封裝成MP4格式的視訊流進行RTP打包過程時需要了解的一些基本知識。

二、H264的基礎知識

1.H264的編碼格式

H.263 定義的碼流結構是分級結構,共四層。自上而下分別為:影象層(picturelayer)、塊組層(GOB layer)、巨集塊層(macroblock layer)和塊層(block layer)。而與H.263 相比,H.264的碼流結構和H.263 的有很大的區別,它採用的不再是嚴格的分級結構。H.264 支援4:2:0 的連續或隔行視訊的編碼和解碼。H.264 壓縮與H.263、MPEG-4 相比,視訊壓縮比提高了一倍。

H.264 的功能分為兩層:視訊編碼層(VCL, Video Coding Layer)和網路提取層(NAL,Network Abstraction Layer)。VCL 資料即編碼處理的輸出,它表示被壓縮編碼後的視訊資料序列。在VCL 資料傳輸或儲存之前,這些編碼的VCL 資料,先被對映或封裝進NAL 單元中。每個NAL 單元包括一個原始位元組序列負荷(RBSP, Raw Byte Sequence Payload)、一組對應於視訊編碼的NAL 頭資訊。RBSP 的基本結構是:在原始編碼資料的後面填加了結尾位元。一個bit“1”若干位元“0”,以便位元組對齊。

2.H264的傳輸

H.264 的編碼視訊序列包括一系列的NAL 單元,每個NAL 單元包含一個RBSP,見表1。編碼片(包括資料分割片IDR 片)和序列RBSP 結束符被定義為VCL NAL 單元,其餘
為NAL 單元。典型的RBSP 單元序列如圖2 所示。每個單元都按獨立的NAL 單元傳送。單元的資訊頭(一個位元組)定義了RBSP 單元的型別,NAL 單元的其餘部分為RBSP 資料。

 

3.H264的碼流結構

起始碼:如果NALU 對應的Slice 為一幀的開始,則用4 位元組表示,即0x00000001;否則用3 位元組表示,0x000001。

一個frame是可以分割成多個Slice來編碼的,而一個Slice編碼之後被打包進一個NAL單元,不過NAL單元除了容納Slice編碼的碼流外,還可以容納其他資料,比如序列引數集SPS。

三、MP4封裝的H264資料

MP4檔案中所有資料都封裝在box中,它是由若干個子box組成,每個box還可以包含另外的子box,且每個box都有長度和型別。“ftyp”(66 74 79 70)box:作為MP4格式的標誌幷包含關於檔案的一些資訊,有且僅有一個;“moov”(6D 6F 6F 76)box:包含了媒體的metadata資訊(特別是avcC中的sps和pps),有且僅有一個;“mdat”(6D 64 61 74)box:包含了MP4的媒體資料,可以有多個,也可以沒有。但是媒體資料的結構由metadata進行描述。MP4中box儲存方式為大端模式。一般,標準的box開頭會有四個位元組的box size。

在MP4格式檔案中,H264 slice並不是以00 00 00 01來作分割,而是儲存在mdat box中。H264基本碼流由一些列的NALU組成。原始的NALU單元組成:[start code] + [NALU header] + [NALU payload].

MP4資料格式:|"ftyp"box|"moov"box(及其子box)|"mdat"box|....|。

"mdat"box的格式:|box的length(4位元組)|box型別(4位元組)mdat-6D 64 61 74|NALU的length(4位元組)|NALU的header(1位元組)|payload|;

MP4封裝結構圖:

box結構圖:

用MP4info分析的例項分析圖:

四、H264視訊流的RTP封包

1.RTP打包原則

RTP的包長度必須要小於MTU(最大傳輸單元),IP協議中MTU的最大長度為1500位元組。除去IP報頭(20位元組)、UDP報頭(8位元組)、RTP頭(12位元組),所有RTP有效載荷(即NALU內容)的長度不得超過1460位元組。

2.RTP協議的報文結構 

開始12個八進位制出現在每個RTP包中,而CSRC標識列表僅出現在混合器插入時。各段含義如下: 
 ①版本(V)
version (V): 2 bits   2位,標識RTP版本,協議初始版本為0,RFC3550中規定的版本號為2。。 
 ②填充標識(P)
padding (P): 1 bit   1位,如設定填充位,在包末尾包含了額外的附加資訊,它不屬於有效載荷。附加資訊的最後一個位元組表示額外附加資訊的長度(包含該位元組本身)。該欄位之所以 存在是因為某些加密演算法需要固定大小的填充字,或為在底層協議資料單元中攜帶幾個RTP包。 
 ③擴充套件(X)
extension (X): 1 bit           1位,如果該位被設定,則在固定的頭部後存在一個擴充套件頭部,格式定義在RFC3550 5.3.1節。 
 ④CSRC計數(CC) 
 CSRC count (CC): 4 bits    4位,CSRC計數包括緊接在固定頭後標識CSRC個數。 
⑤標記(M) 
marker (M): 1 bit     1位,標記解釋由設定定義,目的在於允許重要事件在包流中標記出來。設定可定義其他標示位,或通過改變位數量來指定沒有標記位,該位的功能依賴於 profile的定義。profile可以改變該位的長度,但是要保持marker和payload type總長度不變(一共是8 bit)。。

或M:標示位,1 位。如果當前 NALU為一個接入單元最後的那個NALU,那麼將M位置 1;或者當前RTP 資料包為一個NALU 的最後的那個分片時(NALU 的分片在後面講述),M位置 1。其餘情況下M 位保持為 0。
⑥載荷型別(PT)
payload type (PT): 7 bits   7位,記錄後面資料使用哪種 Codec , receiver 端找出相應的 decoder 解碼出來,該位標記著RTP packet所攜帶資訊的型別,標準型別列出在RFC3551中。如果接收方不能識別該型別,必須忽略該packet。 
 ⑦系列號 
 sequence number:16 bits  16位,系列號隨每個RTP資料包傳送後而增加1,接收方可以根據該序列號重新排列資料包順序,或者探測包損失。系列號初值是隨機的,使對加密的文字攻擊更加困難。 
 ⑧時間戳
timestamp: 32 bits    32位,時標反映RTP資料包中第一個八進位制數的取樣時刻,取樣時刻必須從單調、線性增加的時鐘匯出,以允許同步與抖動計算。時標可以讓receiver端知道在正確的時間將資料播放出來。實際中當採用”分片封包模式“打包RTP時,當一個NALU打包完畢時,時間戳更一次。


RTP與RTCP協議介紹

   由上圖可知,如果只有系列號,並不能完整按照順序的將data播放出來,因為如果data中間有一段是沒有資料的,只有系列號的話會造成錯誤,需搭配上讓它知道在哪個時間將data正確播放出來,如此我們才能播放出正確無誤的資訊。 
⑨SSRC 
SSRC: 32 bits                     32位,SSRC段標識同步源。此標識不是隨機選擇的,目的在於使同一RTP包連線中沒有兩個同步源有相同的SSRC標識,也就是在一個RTP Session其間每個資料流都應該有一個不同的SSRC。儘管多個源選擇同一個標識的概率很低,所有RTP實現都必須探測並解決衝突。如源改變源傳輸地 址,也必須選擇一個新SSRC標識以避免插入成環行源。 
 ⑩CSRC列表
CSRC list: 0 to 15 items     bits0到15項,每項32位。CSRC列表表示包內的對載荷起作用的源。標識數量由CC段給出。如超出15個作用源,也僅標識15個。CSRC標識由 混合器插入,採用作用源的SSRC標識。只有存在Mixer的時候才有效。如一個將多聲道的語音流合併成一個單聲道的語音流,在這裡就列出原來每個聲道的 SSRC。

3.NALU header結構圖

NALU header由一個位元組組成, 它的語法如下:

F: 1 個位元.forbidden_zero_bit. 在 H.264 規範中規定了這一位必須為 0.

NRI: 2 個位元.nal_ref_idc. 取 00 ~ 11, 似乎指示這個 NALU 的重要性, 如00的NALU解碼器可以丟棄它而不影響影象的回放. 不過一般情況下不太關心這個屬性.

Type: 5 個位元.nal_unit_type. 這個 NALU 單元的型別. 但是在h264中只有 1~23 是有效的值.而其他的24~29在RTP封包採用”組合封包模式“和”分片封包模式“時所用的type型別,而非“單一NAL單元模式”時。

簡述如下:

  0     沒有定義
  1-23  NAL單元  單個 NAL 單元包.
  24    STAP-A   單一時間的組合包
  25    STAP-B   單一時間的組合包
  26    MTAP16   多個時間的組合包
  27    MTAP24   多個時間的組合包
  28    FU-A     分片的單元
  29    FU-B     分片的單元
  30-31 沒有定義

4.RTP打包模式

主要分為三種模式:單一NALU模式、分片模式、組合模式,實際中前兩種用的比較多。

(1)單一NALU模式

一個RTP包僅由一個完整的NALU組成。這種情況下RTP NAL頭型別欄位和原始的H.264的NALU頭型別欄位是一樣的。適合條件是當NALU的長度小於RTP包長減去12時。

特別NALU type 值為 7 和 8 的NALU分別為序列引數集(sps)和影象引數集(pps)。

(2)組合封包模式

即可能是由多個 NAL 單元組成一個 RTP 包. 分別有4種組合方式: STAP-A, STAP-B, MTAP16, MTAP24.那麼這裡的型別值分別是 24, 25, 26 以及 27.適合條件當 NALU 的長度特別小時, 可以把幾個 NALU 單元封在一個 RTP 包中.

(3)分片封包模式Fragmentation Units (FUs)

用於把一個 NALU 單元封裝成多個 RTP 包. 存在兩種型別 FU-A 和 FU-B. 型別值分別是 28 和 29。適合條件當 NALU 的長度超過 MTU 時, 就必須對 NALU 單元進行分片封包. 

FU indicator 結構

  
F:當網路識別此單元存在位元錯誤時,可將其設為 1,以便接收方丟掉該單元。 
NRI:必須根據分片NAL單元的NRI域的值設定,用來指示該NALU的重要性等級。值越大,表示當前NALU越重要。
TYPE:28表示FU-A和29表示FU-B

FU Header 結構:

S:當設定成1,開始位指示分片NAL單元的開始。當跟隨的FU荷載不是分片NAL單元荷載的開始,開始位設為0。                
E:當設定成1,結束位指示分片NAL單元的結束。即荷載的最後位元組是分片NAL單元的最後一個位元組。當跟隨的FU荷載不是分片NAL單元的最後分片,結束位設定為0。
R:保留位必須設定為0,接收者必須忽略該位。

Type:與NALU的header中的Type型別一致。

相關推薦

H264Mp4結構

一、概述 本文講述的是對H264編碼且封裝成MP4格式的視訊流進行RTP打包過程時需要了解的一些基本知識。 二、H264的基礎知識 1.H264的編碼格式 H.263 定義的碼流結構是分級結構,共四層。自上而下分別為:影象層(picturelayer)、塊組層(GOB

H264中SPS PPS<轉>

擴展 vlc 地址 逗號 部分 級別 軟件 第一個 bottom 轉載地址:https://zhuanlan.zhihu.com/p/27896239 1 SPS和PPS從何處而來? 2 SPS和PPS中的每個參數起什麽作用? 3 如何解析SDP中

H264中SPS PPS

轉載地址:https://zhuanlan.zhihu.com/p/27896239 1 SPS和PPS從何處而來? 2 SPS和PPS中的每個引數起什麼作用? 3 如何解析SDP中包含的H.264的SPS和PPS串? 1 客戶端抓包 在做客戶端視訊解碼時,一

RTP協議全解析(H264PS

寫在前面:RTP的解析,網上找了很多資料,但是都不全,所以我力圖整理出一個比較全面的解析, 其中借鑑了很多文章,我都列在了文章最後,在此表示感謝。 網際網路的發展離不開大家的無私奉獻,我決定從我做起,希望大家支援。 1、RTP Header解析         

Elasticsearch建立索引對映結構

前言 這篇文章詳細介紹瞭如何建立索引和某個型別的對映。 下文中[address]指代elasticsearch伺服器訪問地址(http://localhost:9200)。 1       建立索引 1.1     簡單建立語句 curl -XPUT [addres

媒體開發: RTP協議全解析(H264PS

1、RTP Header解析                                                                                                                                      

H264結構分析rtp打包結構

網路抽象層單元型別 (NALU): NALU頭由一個位元組組成,它的語法如下:       +---------------+       |0|1|2|3|4|5|6|7|       +-+-+-+-+-+-+-+-+       |F|NRI|  Type   |       +---------

從wireshark中獲取H264

1、首先從https://github.com/volvet/h264extractor打包下載 2、讀README.md 全文如下: # h264extractor wireshark plugin to extract h264 stream from rt

js ES6 SetMap數據結構

... 文章 正常 col rfi 關註 ash comm 遍歷 這篇文章主要介紹了ES6學習筆記之Set和Map數據結構,結合實例形式詳細分析了ECMAScript中基本數據結構Set和Map的常用屬性與方法的功能、用法及相關註意事項,需要的朋友可以參考下

Django 前後端不分離 代結構

stat file .site ini sta 文件的 ase numeric 輸出結果 Demo: hello_pycharm 根目錄文件:hello_pycharm [__init__.py __pycache__ settings.py urls.py ws

、反補碼的

原碼 原碼就是符號位加上真值的絕對值, 即用第一位表示符號, 其餘位表示值. 比如如果是8位二進位制: [+1]原 = 0000 0001 [-1]原 = 1000 0001 第一位是符號位. 因為第一位是符號位, 所以8位二進位制數的取值範圍就是: [1111 1111

MyBatis的體系結構配置檔案

一、SqlSessionFactory MyBatis 的應用都是以一個 SqlSessionFactory 的例項為中心的,它是單個數據庫對映關係經過編譯後的記憶體映象;SqlSessionFactory 的例項可以通過 SqlSessionFactoryBuilder 獲得。而 SqlSes

java8(Stream API)使用:篩選、切片、對映、查詢、匹配歸約等操作

上一篇中介紹了集合操作的痛點並發現集合操作的這些痛點在java8流API面前基本都不是事,隨後引出了流的定義並介紹了流操作的型別、特徵,以及使用流的基本步驟,本篇將逐一介紹Stream Api中各種流操作及一些特殊流的使用。 用謂詞篩選 關於篩選在該系列前面文章中已經出現

PE結構(64位32位的差別)

1 基本概念 下表描述了貫穿於本文中的一些概念: 名稱 描述 地址 是“虛擬地址”而不是“實體地址”。為什麼不是“實體地址”呢?因為資料在記憶體的位置經常在變,這樣可以節省記憶體開支、避開錯誤的記憶體位置等的優勢。同時使用者並不需要知道具體的“真實地址”,因為系統自己會為程

RTP協議解析H264提取

一、 h264基礎概念SODB: 資料位元串-->最原始的編碼資料RBSP: 原始位元組序列載荷-->在SODB的後面填加了結尾位元(RBSP trailing bits 一個bit“1”)若干位元“0”,以便位元組對齊。EBSP: 擴充套件位元組序列載荷– >在RBS

H264的兩種形式:Annex BAVCC——非常詳細的翻譯

本文需要讀者對H.264流有一定的瞭解才可以理解2種格式差異。          首先要理解的是沒有標準的H.264基本流格式。文件中的確包含了一個Annex,特別是描述了一種可能的格式Annex B格式,但是這個並不是一個必須要求的格式。標準文件中指定了視訊怎樣編碼成獨立的包,但是這些包是怎樣儲存和傳輸的

總結linux中管線資料重導向的及區別

以下是自己的理解,有錯誤請指正下,謝謝 一:資料流重導向:我覺得就是把命令產生的結果儲存到檔案或者裝置, 或者把檔案或者裝置的內容傳給命令。      如:我要查出/dev 下所有的目錄檔案:      例1 把命令產生的結果儲存到檔案或者裝置:       ls -al

哈佛結構馮諾依曼結構

備註:原文來自http://blog.sina.com.cn/s/blog_8701e6ba0102v333.html 書本上都說ARM是哈佛結構,但是我總感覺好像看不出來。後來針對S3C2440的ARM9核進行分析,我有了自己的見解。 我的結論是“ARM9被稱為是哈

登入時生成驗證後臺驗證(驗證圖片用jsp顯示出來的)

登入視窗程式碼HTML <section class="mainlogin"> <div class="container"> <div class="col-md-4 col-md-offset-7 loginconte

用ffmpeg提取mp4h264寫檔案花屏

1、用ffmpeg提取mp4的h264碼流寫檔案的方法網上有很多,不知道的請參考雷神部落格:http://blog.csdn.net/leixiaohua1020/article/details/11800877 2、但是這麼寫出來的檔案是有問題的,首先的確能播放,但是會有