H.264 結(jié)構(gòu)分析

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 grouppicturemacroblockmacroblock 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 unitprimary 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 。
NAL unit type codes

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
  • 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 + 4 bits 進(jìn)行表示,frame_num 的約束如下:

    • 定義變量 PrevRefFrameNum
      • 如果當(dāng)前 picture 是 IDR picture,則 PrevRefFrameNum = 0
      • 否則,PrevRefFrameNum 顧名思義:previous reference frame frame_num 。
    • 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)
H.264_video_structure
  • 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)

RBSP Sequence

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)始:

  1. access unit delimiter NAL unit (when present)
  2. sequence parameter set NAL unit (when present)
  3. picture parameter set NAL unit (when present)
  4. SEI NAL unit (when present)
  5. NAL units with nal_unit_type in the range of 13 to 18, inclusive
  6. first VCL NAL unit of a primary coded picture (always present)

訪(fǎng)問(wèn)單元內(nèi)的 coded picture 和非 VCL NAL 單元的順序應(yīng)遵守以下約束:

  1. 當(dāng)存在 access unit delimiter(間隔符) NAL unit 時(shí),它應(yīng)該是第一個(gè) NAL 單元。任何訪(fǎng)問(wèn)單元中最多有一個(gè) access unit delimiter NAL unit 。
  2. 當(dāng)存在任何 SEI NAL units 時(shí),它們應(yīng)位于 primary coded picture 之前。
  3. 當(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 。
  4. primary coded picture 應(yīng)在相應(yīng)的 redundant coded pictures 之前。
  5. 當(dāng)存在 redundant coded pictures 時(shí),它們應(yīng)按redundant_pic_cnt 值的升序排列。
  6. 當(dāng) end of sequence NAL unit 出現(xiàn)時(shí),它應(yīng)跟隨在 primary coded picture 和所有 redundant coded pictures(如果有)之后。
  7. 當(dāng)end of stream NAL unit 存在時(shí),它應(yīng)是最后一個(gè) NAL unit。
  8. nal_unit_type 等于 0、12 或在 19 到 31 范圍內(nèi)(含)的 NAL unit 不得位于 primary coded picture 的第一個(gè) VCL NAL 之前。
  9. Sequence parameter set NAL units 或 picture parameter set NAL units 可能存在于訪(fǎng)問(wèn)單元中。

H.264 封裝格式

H.264 Package format

Annexb 格式

Annexb 格式主要用于實(shí)時(shí)播放(直播流),每一個(gè)NAL單元前面都有一個(gè) StartCode (起始碼)。
一共有兩種起始碼 start_code

  • 0x000001 3 字節(jié),用在單幀多 slice(即單幀多個(gè)NALU)之間間隔。
  • 0x00000001 4 字節(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,從而得出一幀。

參考文獻(xiàn)

T-REC-H.264-200305-S!!PDF-E.pdf

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀(guān)點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容