H.264 定義
field:幀的交替行的集合。一幀由兩個(gè)場(chǎng)組成,一個(gè)頂場(chǎng)(top field)和一個(gè)底場(chǎng) (bottom field)。
frame:一個(gè)幀包含一個(gè)亮度(Y)樣本數(shù)組和兩個(gè)對(duì)應(yīng)的色度(CrCb)樣本數(shù)組。一個(gè)幀由兩個(gè) field 組成,一個(gè)頂場(chǎng)(top field)和一個(gè)底場(chǎng)(bottom field)。
- top field:組成一幀的兩個(gè)場(chǎng)之一。頂場(chǎng)的每一行在空間上位于底場(chǎng)的相應(yīng)行的正上方。
- bottom field:組成一幀的兩個(gè)場(chǎng)之一。底場(chǎng)的每一行在空間上位于頂場(chǎng)的對(duì)應(yīng)行的正下方。
picture:一個(gè) field 或一個(gè) frame 的統(tǒng)稱(chēng)。
視頻信號(hào)可按完整的幀序列漸進(jìn)地采樣,或者是被隔行采樣為隔行場(chǎng)序列。在交錯(cuò)視頻序列中,兩個(gè)場(chǎng)構(gòu)成一幅視頻幀,一個(gè)場(chǎng)包括一個(gè)完整視頻幀的奇數(shù)行或者是偶數(shù)行。這種采樣方法地優(yōu)點(diǎn)是,在相同地?cái)?shù)據(jù)率下,它在每秒鐘發(fā)送地場(chǎng)數(shù)可以是相同漸進(jìn)序列幀數(shù)的兩倍,同時(shí)能給出更平滑的運(yùn)動(dòng)視覺(jué)效果。
slice group:picture 的 macroblock 或 macroblock pair 的子集。將 picture 分割 slice group 是對(duì) picture 進(jìn)行分區(qū)。分區(qū)由宏塊到切片組映射指定(map[macroblock][slicegroup])。
slice:在特定 slice group 內(nèi)的光柵掃描中 連續(xù)排序 的整數(shù)個(gè)宏塊或宏塊對(duì)。
光柵掃描(RasterScan) 是指從左往右,由上往下,先掃描完一行,再移至下一行起始位置繼續(xù)掃描,H.264使用的主要就是光柵掃描順序。
連續(xù)排序指的是在同一行連續(xù)或跨行時(shí)上一行的尾和當(dāng)前行的頭連續(xù),即在掃描的順序中連續(xù)。
- I slice:使用來(lái)自同一 slice 內(nèi)的解碼樣本的預(yù)測(cè)進(jìn)行解碼的 slice,且不是 SI slice 的 slice。
- P slice:使用來(lái)自同一 slice 內(nèi)的解碼樣本的幀內(nèi)預(yù)測(cè) 或 來(lái)自前置解碼的參考圖片的幀間預(yù)測(cè)來(lái)解碼的 slice,最多使用一個(gè)運(yùn)動(dòng)矢量和參考索引來(lái)預(yù)測(cè)每個(gè)塊的樣本值。
- B slice:使用來(lái)自同一 slice 內(nèi)的解碼樣本的幀內(nèi)預(yù)測(cè)或來(lái)自先前解碼的參考圖片的幀間預(yù)測(cè)來(lái)解碼的切片,使用最多兩個(gè)運(yùn)動(dòng)矢量和參考索引來(lái)預(yù)測(cè)每個(gè)塊的樣本值。
- SI slice (switching I slice):使用來(lái)自同一 slice 內(nèi)的解碼樣本的預(yù)測(cè)和預(yù)測(cè)樣本的量化來(lái)編碼的 slice??梢詫?duì) SI slice 進(jìn)行編碼,使 SI slice 的解碼樣本的構(gòu)造與 SP slice 相同。
- SP slice (switching P slice):使用來(lái)自前置解碼的參考圖片的幀間預(yù)測(cè)進(jìn)行編碼的切片,最多使用一個(gè)運(yùn)動(dòng)矢量和參考索引來(lái)預(yù)測(cè)每個(gè)塊的樣本值。可以對(duì) SP slice 進(jìn)行編碼,使 SP slice 的解碼樣本的構(gòu)造與另一個(gè) SP 切片或 SI 切片相同。
macroblock :picture 中的一個(gè)16x16的像素塊,包含一個(gè) 16x16 的亮度樣本塊和兩個(gè)相應(yīng)的色度樣本塊(色度樣本塊的數(shù)量視采樣模式而定)。
- field macroblock :一個(gè)包含的 samples 來(lái)自單個(gè) field 的 macroblock。一個(gè) coded field 的 macroblocks 都是 field macroblocks 。當(dāng)使用 macroblock-adaptive frame/field (宏塊自適應(yīng)幀/場(chǎng))解碼時(shí),一個(gè) coded frame 的 macroblocks 可能是 field macroblocks 。
- frame macroblock :一個(gè)包含的 samples 來(lái)自一個(gè) coded frame 中兩個(gè) fields 的 macroblock 。當(dāng)不使用 macroblock-adaptive frame/field (宏塊自適應(yīng)幀/場(chǎng))解碼時(shí),coded frame 的所有宏塊都是 frame macroblock 。當(dāng)使用 macroblock-adaptive frame/field (宏塊自適應(yīng)幀/場(chǎng))解碼時(shí),編碼幀的一些宏塊可能是frame macroblock,也可能是 field macroblocks。
macroblock pair :picture 中一對(duì)垂直連續(xù)宏塊。
- field macroblock pair :解碼為兩個(gè)場(chǎng)宏塊的宏塊對(duì)。
- frame macroblock pair :解碼為兩個(gè)幀宏塊的宏塊對(duì)。
macroblock to slice group map :一種將 picture 的 **macroblock ** 映射到 slice group 的方法。macroblock 到 slice group 的映射由一個(gè)數(shù)字列表組成,每個(gè)編碼宏塊一個(gè),指定每個(gè)編碼宏塊所屬的 slice group。
skipped macroblock :沒(méi)有數(shù)據(jù)被編碼的 macroblock ,且指示該 macroblock 在解碼時(shí)跳過(guò)。這個(gè)指示可能對(duì)幾個(gè)宏塊是共同的。
macroblock partition :由 幀間預(yù)測(cè)的宏塊劃分 產(chǎn)生的亮度樣本塊和兩個(gè)對(duì)應(yīng)的色度樣本塊。
sub-macroblock :一個(gè)宏塊的四分之一樣本,即一個(gè)8x8的亮度塊和對(duì)應(yīng)的兩個(gè)色度塊。
sub-macroblock partition :由 幀間預(yù)測(cè)的子宏塊劃分 產(chǎn)生的亮度樣本塊和兩個(gè)對(duì)應(yīng)的色度樣本塊。
top macroblock of a macroblock pair :宏塊對(duì)的頂部宏塊,簡(jiǎn)稱(chēng) top macroblock。包含 macroblock pair 的 top row (頂行)的樣本(亮度樣本和色度樣本)。
- field macroblock pair ,top macroblock 表示 frame 的 top field 的 samples。
- frame macroblock pair ,top macroblock 表示 macroblock pair 上半部分 的 samples。
coded field:field 的編碼表示。
coded frame:frame 的編碼表示。
coded picture:picture 的編碼表示。coded picture 可以是一個(gè) coded field 或是 一個(gè) coded frame 。Coded picture 是主編碼圖片(primary coded picture)或冗余編碼圖片(redundant coded picture)的一個(gè)總稱(chēng),但不能同時(shí)指兩者。
coded video sequence:a sequence of access units,由按解碼順序排序的 IDR 訪(fǎng)問(wèn)單元(IDR access unit)及其后跟的零個(gè)或多個(gè)非 IDR 訪(fǎng)問(wèn)單元(non-IDR access units)組成。
access unit:一組 包含 primary coded picture 的 NAL 單元。除了 primary coded picture 之外,一個(gè) access unit 也可能包含一個(gè)或多個(gè) redundant coded pictures 或 其他不包含 slices 或 slices data partitions 的 coded picture。access unit 的解碼結(jié)果是一個(gè) decoded picture 。
- primary coded picture:primary picture 的編碼表示(符合H.264標(biāo)準(zhǔn)的可被正確解碼的 bistream)。primary coded picture 包含一張 picture 的所有宏塊。
-
redundant coded picture :primary picture 的 redundant picture 的編碼表示 。redundant 即冗余,用于增強(qiáng) primary picture的錯(cuò)誤恢復(fù)能力。
- redundant coded picture 通常覆蓋 primary picture 的一部分,因此不需要包含 primary coded picture 中的所有宏塊。
- 當(dāng) primary coded picture 的 bitstream 在傳輸中出錯(cuò)時(shí)(即 bitstream 不符合H.264標(biāo)準(zhǔn)),才對(duì) redundant coded picture 進(jìn)行解碼,并通過(guò) redundant picture 恢復(fù) primary picture。
- 通常只有 IDR picture 附有 redundant picture,因?yàn)?IDR picture 的損壞可能會(huì)破壞整個(gè)GOP。
- 順便說(shuō)一下,每個(gè) primary coded picture 可能有多達(dá)127個(gè) redundant pictures。因?yàn)閱蝹€(gè)access unit 最多可包含128張圖片。
IDR access unit:primary coded picture 是 IDR picture 的訪(fǎng)問(wèn)單元。
IDR picture: slices 全部是 I slice 或 SI slice 類(lèi)型的 coded picture 。在解碼 IDR 圖片后,解碼進(jìn)程將所有參考圖片標(biāo)記為"unused for reference"。在對(duì) IDR 圖片進(jìn)行解碼之后,可以對(duì)解碼順序中的所有后續(xù) coded picture 進(jìn)行解碼,而無(wú)需從在 IDR 圖片之前解碼的任何圖片進(jìn)行幀間預(yù)測(cè)。每個(gè) coded video sequence 的第一張圖片是 IDR picture。
IDR(instantaneous decoding refresh):瞬時(shí)解碼刷新。
random access : 隨機(jī)訪(fǎng)問(wèn):在比特流的開(kāi)始點(diǎn)以外的點(diǎn)開(kāi)始解碼過(guò)程的行為流。
reference field:當(dāng) coded field 采用 P, SP 和 B slices 編碼 或者 coded frame 采用 field macroblocks 編碼時(shí),reference field 可被用于幀間預(yù)測(cè)。
reference frame:當(dāng) coded frame 采用 P, SP 和 B slices 編碼時(shí),reference field 可被用于幀間預(yù)測(cè)。
reference picture:nal_ref_idc 不等于 0 的 picture (reference picture 表示當(dāng)前 picture 被別的 coded picture 引用)。reference picture 包含的樣本可用于在解碼順序的后續(xù)圖片的解碼過(guò)程中進(jìn)行幀間預(yù)測(cè)。
reference index:reference picture 的索引列表。
syntax element:語(yǔ)法元素:比特流中表示的數(shù)據(jù)元素。
syntax structure:語(yǔ)法結(jié)構(gòu):零個(gè)或多個(gè)語(yǔ)法元素以特定的順序一起出現(xiàn)在比特流中。
picture parameter set :一種語(yǔ)法結(jié)構(gòu),包含適用于零個(gè)或多個(gè)完整編碼圖片的語(yǔ)法元素,由每個(gè) slice header 中的 pic_parameter_set_id 確定。
sequence parameter set :一種語(yǔ)法結(jié)構(gòu),包含適用于零個(gè)或多個(gè)完整編碼視頻序列的語(yǔ)法元素,由每個(gè) slice header 中的 pic_parameter_set_id 的 picture parameter set 的 seq_parameter_set_id 確定。
NAL Unit :一種語(yǔ)法結(jié)構(gòu),包含指示要遵循的數(shù)據(jù)類(lèi)型(nal unit type 指示 RBSP的數(shù)據(jù)類(lèi)型)和包含該數(shù)據(jù)的 RBSP 形式的字節(jié)數(shù)據(jù)(必要時(shí)增加防競(jìng)爭(zhēng)字節(jié))。
RBSP(raw byte sequence payload):一種語(yǔ)法結(jié)構(gòu),包含整數(shù)個(gè)字節(jié),封裝在 NAL 單元中。 RBSP 要么是空的,要么是表示一個(gè)或多個(gè)語(yǔ)法元素的 SODB,后跟一個(gè) RBSP stop bit,然后是零個(gè)或多個(gè)等于 0 的后續(xù)位。
RBSP stop bit:RBSP 中位于 SODB 后的一個(gè)等于 1 的 bit ??梢酝ㄟ^(guò)從 RBSP 的末尾搜索 RBSP 的 stop bit 來(lái)識(shí)別 RBSP 中的 SODB 的結(jié)束。RBSP stop bit 是 RBSP 中的最后一個(gè)非零位。
SODB(string of data bits):表示一個(gè)或多個(gè)語(yǔ)法元素的若干位序列,SODB 存在于 RBSP 內(nèi),在 RBSP stop bit 之前。在 SODB 中,最左邊的位被認(rèn)為是第一個(gè)和最高有效位,最右邊的位被認(rèn)為是最后一個(gè)和最低有效位。
NAL unit
nal_unit( NumBytesInNALunit ) {
forbidden_zero_bit /* 1 bit */
nal_ref_idc /* 2 bits */
nal_unit_type /* 5 bits */
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 (跳過(guò)防競(jìng)爭(zhēng)字節(jié))*/
} else {
rbsp_byte[ NumBytesInRBSP++ ]
}
}
}
-
forbidden_zero_bit:應(yīng)該等于 0 -
nal_ref_idc:不等于 0 意味著 NAL unit 的內(nèi)容為一個(gè) sequence parameter set 或 一個(gè) picture parameter set 或 一個(gè) refrence picture 的 slice 或者 一個(gè) reference picture 的 slice data partition 。 -
nal_unit_type:指示 NAL unit 中的 RBSP data structure。- VCL NAL units 的 nal_unit_type 等于 1 to 5 。剩余的 NAL units 為 non-VCL NAL units 。

RBSP
Slice layer without partitioning syntax:包含 slice_data( )
的所有類(lèi)別。
slice_layer_without_partitioning_rbsp( ) {
slice_header( )
slice_data( ) /* all categories of slice_data( ) syntax */
rbsp_slice_trailing_bits( )
}
slice data partitioning:一種基于與每個(gè)語(yǔ)法元素相關(guān)聯(lián)的類(lèi)別將所選語(yǔ)法元素 劃分 為語(yǔ)法結(jié)構(gòu)的方法。 當(dāng)使用 slice data partitioning 時(shí),單個(gè) slice 的編碼數(shù)據(jù)被分成三個(gè)單獨(dú)的分區(qū):partition A包含類(lèi)別 2 的所有語(yǔ)法元素,partition B 包含類(lèi)別 3 的所有語(yǔ)法元素,partition C 包含類(lèi)別 4 的所有語(yǔ)法元素。如果語(yǔ)法元素未區(qū)分類(lèi)別,則所有 partiion 都包含該語(yǔ)法元素。partition 的區(qū)別在于 slice_data( ) 中的 macroblock_layer( ) 中的 residual( )。詳見(jiàn):T-REC-H.264-200305-S!!PDF-E.pdf 中的 7.3.4 Slice data syntax - 7.3.5.3.2 Residual block CABAC syntax 其中,C 列 表示 Category (類(lèi)別)。
slice_data( ) {
...
do {
... /* all */
... /* category 2 */
if( moreDataFlag ) {
...
macroblock_layer( ) /* category 2, 3, 4 */
}
...
} while( moreDataFlag )
}
macroblock_layer( ) {
... /* all */
... /* category 2 */
if( CodedBlockPatternLuma > 0 | | CodedBlockPatternChroma > 0
|| MbPartPredMode( mb_type, 0 ) = = Intra_16x16 ) {
residual( ) /* category 3, 4 */
}
}
residual( ) {
... /* category 3 */
... /* category 3, 4 */
}
Slice data partition A RBSP semantics:slice_data( ) 含類(lèi)別 2 的 slice_data( ) 的語(yǔ)法元素。Slice data partition A RBSP syntax:
slice_data_partition_a_layer_rbsp( ) {
slice_header( )
slice_id
slice_data( ) /* only category 2 parts of slice_data( ) syntax */
rbsp_slice_trailing_bits( )
}
Slice data partition B RBSP semantics:slice_data( ) 含類(lèi)別 3 的語(yǔ)法元素。Slice data partition B RBSP syntax:
slice_data_partition_b_layer_rbsp( ) {
slice_id
if( redundant_pic_cnt_present_flag )
redundant_pic_cnt
slice_data( ) /* only category 3 parts of slice_data( ) syntax */
rbsp_slice_trailing_bits( )
}
Slice data partition C RBSP semantics:slice_data( ) 含類(lèi)別 4 的語(yǔ)法元素。Slice data partition C RBSP syntax:
slice_data_partition_c_layer_rbsp( ) {
slice_id
if( redundant_pic_cnt_present_flag )
redundant_pic_cnt
slice_data( ) /* only category 4 parts of slice_data( ) syntax */
rbsp_slice_trailing_bits( )
}
slice header:coded slice 的 header(包含 slice 的相關(guān)信息)。
slice header syntax elements
-
first_mb_in_slice: 指定 slice 中第一個(gè)宏塊的地址。當(dāng) Annex A 中規(guī)定不允許任意 slice 順序時(shí),first_mb_in_slice 的值不得小于當(dāng)前 picture 中解碼順序位于當(dāng)前切片之前的任何其他切片的 first_mb_in_slice 的值。slice 的第一個(gè)宏塊地址導(dǎo)出如下。- 如果 MbaffFrameFlag 等于 0 ,
first_mb_in_slice是 slice 中第一個(gè)宏塊的宏塊地址,first_mb_in_slice 的范圍為0 to PicSizeInMbs - 1 - 如果 MbaffFrameFlag 等于 1 ,
first_mb_in_slice * 2是 slice 中第一個(gè)宏塊的宏塊地址,這是 slice 中第一個(gè)宏塊對(duì)的 top macroblock,first_mb_in_slice的范圍為0 to PicSizeInMbs/2 - 1
- 如果 MbaffFrameFlag 等于 0 ,
-
slice_type:
slice type pic_parameter_set_id:指定使用的 picture parameter set。-
frame_num:用作 picture 的標(biāo)識(shí)符,應(yīng)由 bitstream 中的log2_max_frame_num_minus4 + 4bits 進(jìn)行表示,frame_num 的約束如下:- 定義變量
PrevRefFrameNum:- 如果當(dāng)前 picture 是 IDR picture,則
PrevRefFrameNum = 0 - 否則,PrevRefFrameNum 顧名思義:previous reference frame
frame_num。
- 如果當(dāng)前 picture 是 IDR picture,則
-
frame_num的值約束如下:-
frame_num = 0: picture 是 IDR picture 。 -
frame_num == PrevRefFrameNum, 以下三個(gè)條件為 true 時(shí)成立- 當(dāng)前圖片和前面的參考圖片在解碼順序上屬于連續(xù)的訪(fǎng)問(wèn)單元。
- 當(dāng)前圖片和前面的參考圖片是具有相反奇偶性的參考場(chǎng)
- 以下任意條件為真
- 前面的參考圖片是 IDR 圖片
- 前面的參考圖片包括一個(gè)
memory_management_control_operation語(yǔ)法元素等于 5。(當(dāng)前面的參考圖片包括等于5的memory_management_control_operation語(yǔ)法元素時(shí),PrevRefFrameNum等于0。) - 在前面的參考圖片之前有一個(gè) primary coded picture,并且在前面的參考圖片之前的 primary coded picture 的 frame_num 不等于 PrevRefFrameNum 。
- 在前面的參考圖片之前有一個(gè) primary coded picture,并且在前面的參考圖片之前的 primary coded picture 不是參考圖片 。
-
frame_num != PrevRefFrameNum- 非
used for short-term reference的 field 或 frame 的 frame_num 為UnusedShortTermFrameNum = ( PrevRefFrameNum + 1 ) % MaxFrameNum。 - frame_num 的值約束如下:
- 如果
gaps_in_frame_num_value_allowed_flag等于 0,則當(dāng)前圖片的 frame_num 的值應(yīng)等于( PrevRefFrameNum + 1 ) % MaxFrameNum - 如果
gaps_in_frame_num_value_allowed_flag等于 1,則:- 如果
frame_num > PrevRefFrameNum,則在以下任一條件為真的解碼順序中,比特流中不應(yīng)有任何非參考圖片在前一個(gè)參考圖片之后和當(dāng)前圖片之前進(jìn)行解碼。- 非參考圖片的 frame_num 的值小于 PrevRefFrameNum。
- 非參考圖片的 frame_num 的值大于當(dāng)前圖片的 frame_num 的值。
- 否則
frame_num < PrevRefFrameNum,在以下兩個(gè)條件都為真的情況下,比特流中不應(yīng)有任何非參考圖片在前一個(gè)參考圖片之后和當(dāng)前圖片之前的解碼順序。- 非參考圖片的 frame_num 的值小于 PrevRefFrameNum。
- 非參考圖片的 frame_num 的值大于當(dāng)前圖片的 frame_num 的值。
- 如果
- 如果
- 非
-
- 定義變量
field_pic_flag:等于 1 時(shí)指示 slice 是 coded field 的 slice。bottom_field_flag:等于 1 時(shí) 指示 slice 是 coded bottom field 的 slice 。idr_pic_id identifies:指示是 IDR picture 的 slice 。
其中, pic_parameter_set_id, frame_num, field_pic_flag, bottom_field_flag, idr_pic_id, pic_order_cnt_lsb, delta_pic_order_cnt_bottom, delta_pic_order_cnt[ 0 ], delta_pic_order_cnt[ 1 ], sp_for_switch_flag, 和 slice_group_change_cycle 的值在同一個(gè) coded picture 的所有 slice header 中應(yīng)相同。
slice_id:標(biāo)識(shí)與 data partition 關(guān)聯(lián)的 slice。每個(gè) slice 在 所屬的 coded picture 內(nèi)具有唯一的 slice_id。當(dāng) Annex A 中規(guī)定不允許任意切片順序時(shí),在解碼順序中,編碼圖像的第一個(gè)切片的 slice_id 應(yīng)等于 0,并且對(duì)于coded picture 的每個(gè)后續(xù)切片, slice_id 的值應(yīng)以 1 進(jìn)行遞增。
H.264 視頻分層結(jié)構(gòu)
在H.264中,語(yǔ)法元素被組織成五個(gè)層次:
- 序列 (sequence)
- 圖像 (picture => frame or filed)
- 分片 (slice)
- 宏塊 (macroblock)
- 子塊 (sub-block)

- access unit: A set of NAL units always containing a primary coded picture.
- coded video sequence: A sequence of access units that consists.
- in decoding order, of an instantaneous decoding refresh (IDR) access unit followed by zero or more non-IDR access units including all subsequent access units up to but not including any subsequent IDR access unit.
- IDR access unit: An access unit in which the primary coded picture is an IDR picture.
- IDR picture: A coded picture containing only slices with I or SI slice types that causes a "reset" in the decoding process
H.264 碼流分層結(jié)構(gòu)

NAL unit 和 coded picture 的順序以及與訪(fǎng)問(wèn)單元的關(guān)聯(lián)
在 primary coded picture 的最后一個(gè) VCL NAL unit 之后,首個(gè)以下的任何 NAL unit 指定新訪(fǎng)問(wèn)單元的開(kāi)始:
- access unit delimiter NAL unit (when present)
- sequence parameter set NAL unit (when present)
- picture parameter set NAL unit (when present)
- SEI NAL unit (when present)
- NAL units with nal_unit_type in the range of 13 to 18, inclusive
- first VCL NAL unit of a primary coded picture (always present)
訪(fǎng)問(wèn)單元內(nèi)的 coded picture 和非 VCL NAL 單元的順序應(yīng)遵守以下約束:
- 當(dāng)存在 access unit delimiter(間隔符) NAL unit 時(shí),它應(yīng)該是第一個(gè) NAL 單元。任何訪(fǎng)問(wèn)單元中最多有一個(gè) access unit delimiter NAL unit 。
- 當(dāng)存在任何 SEI NAL units 時(shí),它們應(yīng)位于 primary coded picture 之前。
- 當(dāng)存在包含 buffering period SEI message 的 SEI NAL unit 時(shí),buffering period SEI message 應(yīng)是該訪(fǎng)問(wèn)單元中第一個(gè) SEI NAL unit 的第一個(gè) SEI message payload 。
- primary coded picture 應(yīng)在相應(yīng)的 redundant coded pictures 之前。
- 當(dāng)存在 redundant coded pictures 時(shí),它們應(yīng)按redundant_pic_cnt 值的升序排列。
- 當(dāng) end of sequence NAL unit 出現(xiàn)時(shí),它應(yīng)跟隨在 primary coded picture 和所有 redundant coded pictures(如果有)之后。
- 當(dāng)end of stream NAL unit 存在時(shí),它應(yīng)是最后一個(gè) NAL unit。
- nal_unit_type 等于 0、12 或在 19 到 31 范圍內(nèi)(含)的 NAL unit 不得位于 primary coded picture 的第一個(gè) VCL NAL 之前。
- Sequence parameter set NAL units 或 picture parameter set NAL units 可能存在于訪(fǎng)問(wèn)單元中。
H.264 封裝格式

Annexb 格式
Annexb 格式主要用于實(shí)時(shí)播放(直播流),每一個(gè)NAL單元前面都有一個(gè) StartCode (起始碼)。
一共有兩種起始碼 start_code
-
0x0000013 字節(jié),用在單幀多 slice(即單幀多個(gè)NALU)之間間隔。 -
0x000000014 字節(jié),用在幀之間,或者SPS等之前。
防字節(jié)競(jìng)爭(zhēng)處理:用起始碼定位NALU邊界存在一個(gè)問(wèn)題,即NALU中可能存在與起始碼相同的數(shù)據(jù)。為了防止這個(gè)問(wèn)題,在構(gòu)建NALU時(shí),需要在數(shù)據(jù)中的0x000000,0x000001,0x000002,0x000003中插入防競(jìng)爭(zhēng)字節(jié)(Emulation Prevention Bytes)0x03 。
AVCC 格式
AVCC 格式主要用于存儲(chǔ)(如存儲(chǔ)在硬盤(pán)的文件:FLV、MP4、MKV通常用AVCC格式來(lái)存儲(chǔ)。),AVCC格式不使用起始碼作為NALU的分界,AVCC在每個(gè)NALU前都加上一個(gè)大端格式的前綴(1、2、4字節(jié),代表NALU長(zhǎng)度)。
在解析 AVCC 格式的時(shí)候需要將指定的前綴字節(jié)數(shù)的值保存在一個(gè)頭部對(duì)象中,這個(gè)都通常稱(chēng)為 sequence header 。同時(shí),SPS 和 PPS 數(shù)據(jù)也需要保存在 sequence header 中。(這些數(shù)據(jù)的存儲(chǔ)和傳輸是文件容器的任務(wù)(即 FLV 中的 AVC Sequence header),超出了本文的范疇)。
雖然 AVCC 格式不使用起始碼,但防競(jìng)爭(zhēng)字節(jié)還是有的。因此在構(gòu)建 NALU 時(shí),同樣在數(shù)據(jù)中的0x000000,0x000001,0x000002,0x000003中插入防競(jìng)爭(zhēng)字節(jié)(Emulation Prevention Bytes) 0x03 。
RTP 格式
RTP 格式主要用于網(wǎng)絡(luò)傳輸(例如:RTC)。而在IP網(wǎng)絡(luò)中,當(dāng)要傳輸?shù)腎P報(bào)文大小超過(guò) 最大傳輸單元MTU 時(shí)就會(huì)產(chǎn)生IP分片情況。若交給底層協(xié)議拆包容易出問(wèn)題,因此此時(shí)需要主動(dòng)拆分NALU再打包成RTP包后發(fā)送。
RTP 的 NALU :
Single NAL Unit Packet: payload 中僅包含一個(gè) NAL 單元。 NAL header 的 type 等于原始 NAL 單元類(lèi)型。
Aggregation packet:用于將多個(gè) NAL 單元聚合為單個(gè) RTP payload 的數(shù)據(jù)包類(lèi)型。
Fragmentation unit: 用于將單個(gè) NAL 單元分段到多個(gè) RTP 數(shù)據(jù)包上。
Type Packet Type name
-------------------------------------------------
0 undefined
1-23 NAL unit Single NAL unit packet per H.264
24 STAP-A Single-time aggregation packet
25 STAP-B Single-time aggregation packet
26 MTAP16 Multi-time aggregation packet
27 MTAP24 Multi-time aggregation packet
28 FU-A Fragmentation unit
29 FU-B Fragmentation unit
30-31 undefined
詳見(jiàn):rfc3984
思考
為什么需要多總格式?
媒體可分為本地文件和直播流:
如果是本地文件,則我們只需要讀取一次SPS,PPS的信息,然后就可以一直進(jìn)行解碼,所以將SP,PPS等信息放到文件的頭部,打開(kāi)文件,先讀取這些信息初始化解碼器,就可以順利的解碼。如 FLV,MP4,MKV 等常用的本地存儲(chǔ)方式采用 AVCC 封裝 NALU。
如果是直播流,如果將SPS,PPS放到頭部,那么中途播放的用戶(hù)無(wú)法接收到SPS ,PPS信息,導(dǎo)致無(wú)法初始化解碼器,所以必須每隔一段時(shí)間發(fā)送一次SPS,PPS等信息,一般是放在IDR幀之前進(jìn)行發(fā)送,如 mpeg-ts 直播流采用 Annex-B 結(jié)構(gòu)封裝 NALU。
H.264 in FLV
在 NAL 中沒(méi)有 frame 的概念,NAL 中包含的圖像數(shù)據(jù)其實(shí)是 frame 的 Slice,一個(gè) 或 多個(gè) Slice 構(gòu)成 一個(gè) frame。
H.264 在 FLV 中的 Frame 實(shí)際是一個(gè)包含 AVCPacket 的 FLV Video Tag 包含了一個(gè) 或 多個(gè) NALU (即一個(gè) 或 多個(gè) Slice)。比如 I Frame 由一個(gè) 或 多個(gè) I Slice 構(gòu)成。
FLV Video Tag 中的 AVCPacket 是使用 AVCC 格式封裝的(AVCC在每個(gè)NALU前都加上一個(gè)大端格式的前綴代表NALU長(zhǎng)度),因此可以知道一個(gè) AVCPacket 中每個(gè) NALU 的長(zhǎng)度,從而解出每個(gè) NALU 中的 Slice,從而得出一幀。
