H.264中NAL、Slice與frame意思及相互關系
H.264中NAL、Slice與frame意思及相互關系
NAL nal_unit_type中的1(非IDR圖像的編碼條帶)、2(編碼條帶數據分割塊A)、3(編碼條帶數據分割塊B)、4(編碼條帶數據分割塊C)、5(IDR圖像的編碼條帶)種類型
與
Slice種的三種編碼模式:I_slice、P_slice、B_slice
還有frame的3種類型:I frame、P frame、 B frame之間有什么映射關系么?
最后,NAL nal_unit_type中的6(SEI)、7(SPS)、8(PPS)屬于什么幀呢?
不好意思,文檔看得頭暈暈的了,問題比較多~~~
PS:偶是新人 沒多少分,要是哪位達人幫忙下的話 我就給我所有的分,好像只有十幾分
1 frame的數據可以分為多個slice.
每個slice中的數據,在幀內預測只用到自己slice的數據, 與其他slice 數據沒有依賴關系。
NAL 是用來將編碼的數據進行大包的。 比如,每一個slice 數據可以放在NAL 包中。
I frame 是自己獨立編碼,不依賴于其他frame 數據。
P frame 依賴 I frame 數據。
B frame 依賴 I frame, P frame 或其他 B frame 數據。
建議樓主看一點視頻編碼的書吧, 自己看標準還是很難懂的。
那NAL nal_unit_type中的哪幾種類型是I frame,現在只能確定nal_unit_type==5(IDR圖像的編碼條帶)是I frame
sps、pps、SEI算不算I frame呢? 還有 屬于編碼條帶分割的DPA、DPB、DPC呢?
能給個從視頻流中提取I frame 和P frame的方法么?
謝謝樓上的回復,我也翻了兩三本視頻的書籍,感覺都是一個樣的,都很少說到點的。樓主能推薦一兩本好點的視頻書籍么?
沒人回答么??
直接給你代碼吧 :)
//////////////////////////////////////////////////////////////////////////
// H.264 NAL type
enum H264NALTYPE{
H264NT_NAL = 0,
H264NT_SLICE,
H264NT_SLICE_DPA,
H264NT_SLICE_DPB,
H264NT_SLICE_DPC,
H264NT_SLICE_IDR,
H264NT_SEI,
H264NT_SPS,
H264NT_PPS,
};
int H264GetNALType(LPVOID pBSBuf, const LONG nBSLen)
{
if ( nBSLen < 5 ) // 不完整的NAL單元
return H264NT_NAL;
UINT8* pBS = (UINT8 *)pBSBuf;
ULONG nType = pBS[4] & 0×1F; // NAL類型在固定的位置上
if ( nType <= H264NT_PPS )
return nType;
return 0;
}
其中 H264NT_SLICE_IDR 是關鍵幀,H264NT_SLICE 是P幀
一個frame是可以分割成多個Slice來編碼的,而一個Slice編碼之后被打包進一個NAL單元,不過NAL單元除了容納Slice編碼的碼流外,還可以容納其他數據,比如序列參數集SPS。
1、NAL、Slice與frame意思及相互關系
NAL指網絡提取層,里面放一些與網絡相關的信息
Slice是片的意思,264中把圖像分成一幀(frame)或兩場(field),而幀又可以分成一個或幾個片(Slilce);片由宏塊(MB)組成。宏塊是編碼處理的基本單元。
2、NAL nal_unit_type中的1(非IDR圖像的編碼條帶)、2(編碼條帶數據分割塊A)、3(編碼條帶數據分割塊B)、4(編碼條帶數據分割塊C)、5(IDR圖像的編碼條帶)種類型
與 Slice種的三種編碼模式:I_slice、P_slice、B_slice
NAL nal_unit_type 里的五種類型,代表接下來數據是表示啥信息的和具體如何分塊。
I_slice、P_slice、B_slice 表示I類型的片、P類型的片,B類型的片.其中I_slice為幀內預測模式編碼;P_slice為單向預測編碼或幀內模式;B_slice 中為雙向預測或幀內模式。
3、還有frame的3種類型:I frame、P frame、 B frame之間有什么映射關系么?
I frame、P frame、 B frame關系同 I_slice、P_slice、B_slice,slice和frame區別在問題1中已經講明白。
4、最后,NAL nal_unit_type中的6(SEI)、7(SPS)、8(PPS)屬于什么幀呢?
NAL nal_unit_type 為序列參數集(SPS)、圖像參數集(PPS)、增強信息(SEI)不屬于啥幀的概念。表示后面的數據信息為序列參數集(SPS)、圖像參數集(PPS)、增強信息(SEI)。
能給個從視頻流中提取I frame 和P frame的方法么?
可以看slice中的頭信息。
查找NAL起始碼,然后讀取NAL類型不就可以了嗎
pBS[4] & 0×1F
怎么是第5個字節的第五位啊 前面4字節分別是什么(值)?
NAL單元的第1個字節的低五位吧?
然后在問個問題,怎么在一段視頻流中檢測 NAL的開始和結束?
H.264視頻流是以NAL單元傳送的。。。但在一個NAL單元里面,可能既存放I-Slice(P-Slice或B-Slice),同事也可能存放圖像的其他信息
那么 是不是說 I frame, P frame,B frame是把收到的NAL單元中的VCL的信息先提取出,然后按內容進行I、P、B frame分類?
而我們只能通過NAL nal_unit_type來判別NAL單元中數據的類型哈~~~
====================================================================《如何結合H.264標準看JM代碼》這個web文件,大家都應該有了吧。不過,那個web文檔是“H.264樂園”群中聊天的內容,因此看的不是很方便......我在開學來的時候看的時候,做了一些總結,希望與大家分享!不對的地方請指正!
1、一個sps后,有若干個pps嗎?
這主要又編碼器決定,但JM代碼中只有一個
2、標準中第二欄的C是什么意思?
請看標準7.2--分類(在表中以C標記)表明了片數據被劃分為三類片數據分割的情況。片數據A類分割包含所有的2類語法元素。片數據B類分割包含所有的3類語法元素。片數據C類分割包含所有的4類語法元素。其他類語法元素取值的含義未做規定。對于某些語法元素,使用一個垂直豎線表示其包含兩類語法元素。在這種情況下,該語法元素將使用的分類值將在文本中進一步確定。
3、一個NALU對應一個片嗎?
這種說法不太準確,NALU 包括一個片、SPS、PPS、SEI等等
4、decode_one_frame()包括I、P、B
5、 case NALU_TYPE_SLICE:
case NALU_TYPE_IDR:
case NALU_TYPE_DPA
case NALU_TYPE_DPB:
case NALU_TYPE_DPC
case NALU_TYPE_SEI:
case NALU_TYPE_PPS
case NALU_TYPE_SPS
case NALU_TYPE_AUD:
case NALU_TYPE_EOSEQ:
case NALU_TYPE_EOSTREAM:
case NALU_TYPE_FILL
問題:什么時候進入哪個,有什么說明的文章或書么?
答 :進入哪個 case 是由從 NALU 頭里解碼出來的 nalu_type 決定的
6、解碼器中的誤碼隱藏只對丟包有用,丟包之后,包的序號不連續,解碼器一旦檢測到包序號不連續就會將不連續地方的 ei_flag 置 1
7、字節流格式和RTP格式碼流,具體的不同點有哪些?相關的資料哪里有?
字節流格式主要用于文件存儲,因此在該格式碼流中 NALU 前面只有一個開始前綴,RTP格式碼流因為需要進行網絡傳輸, 因此 NALU 前面還有很多輔助信息
8、rtp格式就是在字節流前加包頭嗎?
不是,字節流=開始前綴+NALU,而 RTP 中沒有 開始前綴
9、RTP中沒有開始前綴,為什么還是要插03?
防止偽起始碼、、RTP完全可以不用起始碼,或許是為了與字節流格式統一吧
10、NALU是對RBSP的封裝。而RTP之類的是對NALU的封裝。
11、為什么要分ABC片?
——分ABC片主要目的是為了對重要程度不同的數據進行不同程度的保護
12、baseline沒有數據分割吧?
baseline只是如何產生RBSP,如何封裝NALU。具體如何傳輸,RTP之類只是一種方式,文件copy也是一種方式,那一般 baseline最多有多少參考幀?任意個。
13、解碼profile_idc之后解碼器要做什么工作?比如baseline不支持CABAC那么后面相應的位entropy_coding_mode_flag是不是就不存在了,如果存在,相抵觸怎么辦?
當然不會執行 CABAC 的代碼,編碼器如果是編碼 baseline ,那么碼流中自然就不存在與 CABAC 相關的語法元素,例如 entropy_coding_mode_flag ,解碼器解碼 SPS ,得知碼流是 baseline 后,自然也就不會去調用與 CABAC 相關的解碼程 序,也就不會出錯了。profile_idc 為 baseline ,active_pps->entropy_coding_mode_flag 就不會為 CABAC,,碼流是 否是 baseline 并不是由多少個參考幀決定的
14、JM 進行 CAVLC 編碼時候,對于 level = 8 的情況是采用 escape suffix 處理的,我修改代碼將 level = 8 的情況采用無符號數表示,結果編碼出來的碼流與未修改完全一樣
附:RBSP、SODB、EBSP三者的區別和聯系!
SODB:最原始的編碼數據,沒有任何附加數據
RBSP:在 SODB 的基礎上加了rbsp_stop_ont_bit(bit 值為 1)并用 0 按字節補位對齊
EBSP:在 RBSP 的基礎上增加了防止偽起始碼字節(0X03)
1、1 frame的數據可以分為多個slice.
2、每個slice中的數據,在幀內預測只用到自己slice的數據, 與其他slice 數據沒有依賴關系。
3、NAL 是用來將編碼的數據進行大包的。 比如,每一個slice 數據可以放在NAL 包中。
4、I frame. 是自己獨立編碼,不依賴于其他frame. 數據。
P frame. 依賴 I frame. 數據。
B frame. 依賴 I frame, P frame. 或其他 B frame. 數據。
一個frame是可以分割成多個Slice來編碼的,而一個Slice編碼之后被打包進一個NAL單元,不過NAL單元除了容納Slice編碼的碼流外,還可以容納其他數據,比如序列參數集SPS。
15、NAL、Slice與frame意思及相互關系
NAL指網絡提取層,里面放一些與網絡相關的信息
Slice是片的意思,264中把圖像分成一幀(frame)或兩場(field),而幀又可以分成一個或幾個片(Slilce);片由宏塊(MB)組成。宏塊是編碼處理的基本單元。
16、NAL nal_unit_type中的1(非IDR圖像的編碼條帶)、2(編碼條帶數據分割塊A)、3(編碼條帶數據分割塊B)、4(編碼條帶數據分割塊C)、5(IDR圖像的編碼條帶)種類型與 Slice種的三種編碼模式:I_slice、P_slice、B_slice NAL nal_unit_type 里的五種類型,代表接下來數據是表示啥信息的和具體如何分塊。I_slice、P_slice、B_slice 表示I類型的片、P類型的片,B類型的片.其中I_slice為幀內預測模式編碼;P_slice為單向預測編碼或幀內模式;B_slice 中為雙向預測或幀內模式。
17、還有frame的3種類型:I frame、P frame、 B frame之間有什么映射關系么?
I frame、P frame、 B frame關系同 I_slice、P_slice、B_slice,slice和frame區別在問題1中已經講明白。
18、最后,NAL nal_unit_type中的6(SEI)、7(SPS)、8(PPS)屬于什么幀呢?
NAL nal_unit_type 為序列參數集(SPS)、圖像參數集(PPS)、增強信息(SEI)不屬于啥幀的概念。表示后面的數據信息為序列參數集(SPS)、圖像參數集(PPS)、增強信息(SEI)。
下面以解碼過程為例說一下具體過程:
1、 過程:碼流→NALU→RBSP。

如果是字節流的碼流當然就首先要對字節流進行解析,這就要看附錄 B 了,如何查找起始碼和去除偽起始碼(為什么有偽起始碼呢?);如果是 RTP 格式的碼流,那就要按 RFC3984 來解析了(標準沒有規定 RTP 格式碼流的解析過程);字節流解析完后提取出來的就是 NALU 了,對 NALU 的解析就要看第七章了。黑色的粗體字都是在碼流中可能出現的語法元素,解碼器的首要任務就是要對這些語法元素進行解析。對于這些碼流中的語法元素我們要進行解析必須知道三個問題:
(1)、什么時候存在于碼流中?這樣我們才能知道當前解析的是哪個語法元素;
(2)、采用什么樣的熵編碼方式?這樣我們才能知道如何解析;
(3)、含義是什么?這樣我們才知道解析出來之后用來干什么。
NALU 的前面三個語法元素所組成的一個字節我們稱為 NALU 頭,其余部分(也就是語法表 7.3.1 中的其余部分)我們稱為 NALU 體。對 NALU 體的解析要看 7.3.2 小節。因為 NALU 有很多種類型,所以要針對 NALU 的不同類型去解析 NALU 體(表 7-1 說明了不同 NALU 對應的語法表)。例如,如果當前的 NALU 是 SPS,那么當然就要看 7.3.1 小節;如果當前的 NALU 是 DPA,那么當然就要看 7.3.2.9.1 小節了;
2、對于屬于 VCL 的 NALU(哪些 NALU 是 VCL NALU 呢?如果你看了 nal_unit_type 的語義,你就應該知道),例如表 7-1 中類型為 5 的 NALU,根據表 7-1 我們知道 NALU 體的語法表是 7.3.2.8。而從 7.3.2.8 我們可以看到,對這種 NALU 的 NALU 體解析實際就是對片級語法進行解析。語法表 7.3.2.8 顯示片級語法解析首先要解析 slice_header()(這種帶括號的表示是另一個語法結構),那么 slice_header() 怎么解析呢?往下看,7.3.3 的所有內容都被第一行的 slice_header() 包括在內,所以 7.3.3 就是對 slice_header() 這個語法層的碼流規定;
3、按照語法表 7.3.2.8 解析完了 slice_header() 就該解析 slice_data() 了。下面以最常見的 I 幀(CAVLC 熵編碼、非 MBAFF)的解析過程為例簡單描述怎么繼續讀標準。這時在碼流中出現的第一個 slice_data() 層的語法元素是語法表 7.3.4 中的 macroblock_layer(),也就是說直接到了宏塊層的語法解析,那就要又要看 7.3.5 小節了;
4、基于我們對編解碼流程的了解,我們知道解碼是一個預測值加殘差得到重建圖像的過程,那么我們下面的解碼過程就要分成兩步走了:首先,得到預測值;其次,得到殘差。基于我們對 H.264 關鍵技術的了解,我們知道 intra 宏塊(提醒:我們舉的例子是 I 幀,因此解析的是 intra 宏塊)的預測值是需要使用到預測模式的,所以我們需要解析語法表 7.3.5 中的 mb_pred(mb_type) 語法層,那么又去看 7.3.5.1 小節。按照 7.3.5.1 小節解析出宏塊或塊的預測方式后我們怎么計算預測值呢?去看標準 8.3 小節;得到預測值后我們繼續按照語法表 7.3.5 解析語法元素直到 residual() 語法層,這就又要去看 7.3.5.3 小節;按照 7.3.5.3 小節解析出殘差系數后我們如何把它還原成真實的殘差呢?去看標準 8.5 小節;
5、預測值和殘差都有了,加起來就是解碼圖像了。解碼的主要工作到此也算基本完成了。當然,上面的過程中還會用到標準其他章節的相關內容(例如,8.5 小節會用到 5.7 小節中定義的 InverseRasterScan)總體過程也就如此吧,詳細內容要大家自己去認真的學習