• h264码流分析


    ---------------------------------------------------------------------------------------------------------------------------

    说明:本文档是基于码流文件ducks.264。文档中只有括号里面的参数才会编入码流,如

    nC=0

    (coeff_token):ce(v)=1(0,0)

    只有coeff_token在码流中有,nC只是为了读者方便。ce(v)=1(0,0)1代表码流中的字符串,括号里面是10进制。

                                                                                                                                           Writed by Bnian

    ---------------------------------------------------------------------------------------------------------------------------

    SPS层句法

    00000000   00 00 00 01 67 42 0028 da 01 40 16 e4 00 00 00  

    01100111 01000010 00000000 0010100067 42 00 28

    禁止0位(forbidden_zero_bit):         f(1)=0,应为0;

    NAL参考ID内容(nal_ref_idc):        u(2)=11(3)NALU最高优先级

    nal_unit_type):         u(5)=00111(7)SPS,序列参数集(seq_parameter_set

    (profile_idc):      u(8)=01000010(66),基本简表

    set0):        u(1)=0,可以不遵从相关简表规定

    set1):        u(1)=0,可以不遵从相关简表规定

    set2):        u(1)=0,可以不遵从相关简表规定

    set3):        u(1)=0,可以不遵从相关简表规定

    reserved_zero_4bits):     u(4)=0000

    level_idc):         u(8)=00101000(40),级别号4.0,处于baseline

    11011010 00000001 01000000 00010110 11100100da 01 40 16 e4

    seq_parameter_set_id): ue(v)=1(0),序列参数集ID=0

    log2_max_frame_num_minus4):    ue(v)=1(0),最多帧数=2^4=16

    pic_order_cnt_type):       ue(v)=011(2),图像顺序类型为2

    num_ref_frames):   ue(v)=010(1),参考帧的最大数

    gaps_in_frame_num_value_allowed_flag):    u(1)=0(0),帧数差异标记

    (pic_width_in_mbs_minus1):   ue(v)=0000001010000(79)((79+1)*16=1280),宽度

    pic_height_in_map_units_minus1):ue(v)=00000101101(44)(44+1)*16=720),高度

    frame_mbs_only_flag):   u(1)=1(1),只是帧宏块,没有场宏块

    (direct_8x8_inference_flag):    u(1)=1(1),

    (frame_cropping_flag):     u(1)=0(0),不存在帧剪切偏移参数

    (vui_parameters_present_flag):       u(1)=0(0),没有VUI信息,默认矩阵系数2

    (rbsp_trailing_bits):  100

    PPS层句法

    00000001 01 68 ce38 80 00 00 00 01 65 88 84 27 23 c5 e5 

    01101000 11001110 00111000 10000000(68 ce 38 80)

    禁止0位(forbidden_zero_bit):         f(1)=0,应为0;

    NAL参考ID内容(nal_ref_idc):        u(2)=11(3)NALU最高优先级

    nal_unit_type):         u(5)=01000(8)PPS,图像参数集(pic_parameter_set

    pic_parameter_set_id):  ue(v)=1(0),图像参数集ID=0

    seq_parameter_set_id): ue(v)=1(0),序列参数集ID=0

    entropy_coding_mode_flag):  u(1)=0(0)CAVLC

    pic_order_present_flag):         u(1)=0(0)

    num_slice_groups_minus1):   ue(v)=1(0)

    num_ref_idx_l0_active_minus1):    ue(v)=1(0)

    num_ref_idx_l1_active_minus1):    ue(v)=1(0)

    weighted_pred_flag):      u(1)=0(0)

     

    00111000

    weighted_bipred_idc):     u(2)=00(0)

    pic_init_qp_minus26):     se(v)=1(0)

    pic_init_qs_minus26):      se(v)=1(0)

    chroma_qp_index_offset):       se(v)=1(0)

    (deblocking_filter_control_present_flag):        u(1)=0(0),

    (constrained_intra_pred_flag):         u(1)=0(0),

    (redundant_pic_cnt_present_flag): u(1)=0(0),

    (rbsp_trailing_bits):  100000000

    I

    01100101 10001000 10000100 00100111(65 88 84 27)

    禁止0位(forbidden_zero_bit):         f(1)=0,应为0;

    NAL参考ID内容(nal_ref_idc):        u(2)=11 (3)NALU最高优先级

    nal_unit_type):u(5)=00101(5)IDR图像的片

    first_mb_in_slice):   ue(v)=1(0)

    slice_type):       ue(v)=0001000(7)I条带,I slice

    (pic_parameter_set_id):  ue(v)=1(0),

    frame_num:u(v)=0000(0)

    (Idr_pic_id):ue(v)=1(0)

    (no_output_of_prior_pics_flag):u(1)=0

    (Long_term_reference_flag):u(1)=0

    (slice_qp_delta):        se(v)=00100(2),QP=26+2=28

     

    P(ducks.Frame2.Mb2)

    0003d310   f0 00 00 00 01 41 9a 60 96 db 41 fe 0e aa 50 b6       

    01000001(41)

    禁止0位(forbidden_zero_bit):         f(1)=0,应为0;

    NAL参考ID内容(nal_ref_idc):        u(2)=10(2)NALU优先级

    nal_unit_type):         u(5)=00001(1),不分区、非IDR图像的片

    10011010 01100000 10010110 (9a,60,96)

    片头句法

    (first_mb_in_slice):   ue(v)=1(0),

    slice_type):       ue(v)=00110(5)I条带,P slice

    pic_parameter_set_id):  ue(v)=1(0)

    frame_num):    u(v)=0011(3)

     (num_ref_idx_active_override_flag): u(1)=0,不重载参考图像

    ref_pic_list_recordering_flag_10: u(1)=0,不重排序

    adaptive_ref_pic_marking_mode_flag: u(1)=0, 先入先出(FIFO:使用滑动窗的机制,先入先出,在这种模式下没有办法对长期参考帧进行操作

    slice_qp_delta):        se(v)=00100(2)QP=26+2=28

    宏块层句法

     (mb_skip_run): ue(v)=1(0),不跳

    P_L0_L0_8x16

     (mb_type):ue(v)=011(2) , 预测模式为P_L0_L0_8x16

    11011011 01000001 11111110(db 41 fe )

    宏块的第一个8x16:

    mvd_10[mbPartIdx=0][0][compIdx=0]:se(v)=011(-1),水平运动矢量

    mvd_10[mbPartIdx=0][0][compIdx=1]:se(v)=011(-1),垂直运动矢量

    宏块的第二个8x16:

    mvd_10[mbPartIdx=1][0][compIdx=0]:se(v)= 011 (-1),水平运动矢量----mvdmv是不同滴

    mvd_10[mbPartIdx=1][0][compIdx=1]:se(v)=010(1),垂直运动矢量-------------------

     (Coded_block_pattern):me(v)=000011111(45),CBP=15,CodeBlockPatternLuma=CBP%16=13,CodeBlockPatternLuma=CBP/16=238*8块都有非零系数,1个色度信号全零);

    (Mb_qp_delta): se(v)=1(0), QP=28+0=28

    残差块CAVLC编码:16*16宏块先分解成4个8*8块(红(0)绿(1)棕(2)蓝(3),每个8*8块再分4个4*4块。然后在对每一个4*4块进行编码(看<THE H.264 ADVANCED第125页>):(Coded_block_pattern6位,低4位分别指出48*8块中是否有非零系数,高2位指出色度信号Cr和Cb是否有非零系数;coeff_token指出每个4*4块非零系数的个数)

                       0  1  4   5

                       2 3  6   7

    8  9  12  13

    10 11  14 15

    残差块句法

    先对luma16*16进行编码,在对色度进行编码

    块8x8(0):

    块4x4(0):

    nC=0;

    (coeff_token):ce(v)=1(0,0)

    块4x4(1):

    nA(块4*4(0))=0,nC=Na=0;

     (coeff_token):ce(v)=1(0,0)

    00001110 10101010 01010000 101101100eaa 50 b6)

    块4x4(2):

      nB(块4*4(0))=0 ,nC= nB=0;

         (coeff_token):ce(v)=00000111 (TotalCoff(coeff_token)=2,TrailingOnes(Coeff_token)=0)

                                                     Suffixlength=0

    非零系数1:(Level_prefix(1):ce(v)= 01(1)  Suffixlength=1

      由CAVLC残差句法可知,因为以下条件成立:

    i==TrailingOnes(coeff_token)&&TrailingOnes(coeff_token)<3

    所以levelCode+=2=2; 

                Level(1)=-2

    非零系数2:(Level_prefix(0):ce(v)=01(1)    

                     Level_suffix:u(v)=0(0)       

                       Level(0)=2

    Zeroleft=(Total_zeros):ce(v)=101(2)

    (Run _before(1):ce(v)= 00(2)    zeroleft=0

    Run _before(0)=0,不编码

         综上所述,块4x4(2)的矩阵A(反zig-zag)是:

                  

         至于怎么变成H264visa软件里面的coef,留待高手去考究,我就不写了。

      块4x4(3):

    nB(块4*4(1))=0,nA(块4*4(2))=2,nC=(nB+nA+1)>>1=1.5,

    (coeff_token):ce(v)=1 (0,0)  

    因为CodeBlockPatternLuma=CBP%16=13, 二进制是1101,所以块8x8(1)为全0         

    块8x8(2):

    块4x4(8):

    nB(块4*4(2))=2,nC=nB=2,

    (coeff_token):ce(v)=0100(4,3)

    (Trailing_ones_sign_flag(3)):u(1)=0(+)

    (Trailing_ones_sign_flag(2)):u(1)=0(+)

    (Trailing_ones_sign_flag(1)):u(1)=1(-)

                                                   Suffixlength=0

    非零系数1:(Level_prefix(0):ce(v)=01(1)  Suffixlength=1

    Level(0)=-1

    Zeroleft=(Total_zeros):ce(v)=101(5)

    (Run_before(3)):ce(v)= 10(1)    zeroleft=4

    0003d320    44 ed 71 3d 55 fa f5 07 76 b3 41 b5 28 65 ab fe 

    01000100 11101101(44 ed )

    (Run_before(2)):ce(v)=01(2)     zeroleft=2

    (Run _before(1)):ce(v)=00(2)     zeroleft=0

    必然有Run_before(0)=0,但不编码

    综上所述,块4x4(8)的矩阵A(反zig-zag)是:

     

    块4x4(9):

    nA(块4*4(8))=4, nB(块4*4(3))=0,nC=(nA+nB+1)>>2=2.5,

     (coeff_token):ce(v)=0100 (4,3)

    (Trailing_ones_sign_flag(3)):u(1)=1(-)

    (Trailing_ones_sign_flag(2)):u(1)=1(-)

    (Trailing_ones_sign_flag(1)):u(1)=1(-)

                                                   Suffixlength=0

    非零系数1:(Level_prefix(0):ce(v)=01(1)  Suffixlength=1

    Level(0)=-1

    Zeroleft=(Total_zeros):ce(v)=101(5)

    01110001 00111101(71 3d)

     (Run_before(3)):ce(v)= 011(2)    zeroleft=3

    (Run_before(2)):ce(v)=10(1)     zeroleft=2

    (Run _before(1)):ce(v)=00(2)     zeroleft=0

    必然有Run_before(0)=0,但不编码

    综上所述,块4x4(9)的矩阵A(反zig-zag)是:

    块4x4(10):

    nB(块4*4(8))=4 ,nC=nB=4,

    (coeff_token):ce(v)=1001(6,3)

    (Trailing_ones_sign_flag(5)):u(1)=1(-)

    (Trailing_ones_sign_flag(4)):u(1)=1(-)

    (Trailing_ones_sign_flag(3)):u(1)=1(-)

                                                   Suffixlength=0

    非零系数1:(Level_prefix(2):ce(v)=01(1)  Suffixlength=1

                Level(2)=-1

    01010101 11111010(55 fa )

    非零系数2:(Level_prefix(1):ce(v)=01(1)    

                     Level_suffix:u(v)=0(0)         Suffixlength=1

                       Level(1)=2

    非零系数3:(Level_prefix(0):ce(v)= 1(0)    

                      Level_suffix:u(v)=0(0)        Suffixlength=1

                       Level(0)=1

    Zeroleft=(Total_zeros):ce(v)=101 (4)

    (Run _before(5)):ce(v)= 11(0)    zeroleft=4

    (Run_before(4)):ce(v)=11(0)     zeroleft=4

    (Run _before(3)):ce(v)= 10(1)    zeroleft=3

    (Run _before(2)):ce(v)=10(1)     zeroleft=2

    11110101 00000111(f5 07)

    (Run _before(1)):ce(v)= 1(0)    zeroleft=2

    Run _before(0)=2,不编码

    综上所述,块4x4(10)的矩阵A(反zig-zag)是:

                  

    块4x4(11):

    nB(块4*4(10))=6, nA块4*4(9))=4 ,nC=(nB+Nb+1)>>1=5.5,

    (coeff_token):ce(v)= 1110 (1,1)

     (Trailing_ones_sign_flag(0)):u(1)=1(-)

    Zeroleft=(Total_zeros):ce(v)=010(2)

    Run _before(0))=2,不编码  

    综上所述,块4x4(11)的矩阵A(反zig-zag)是:

                  

    块8x8(3):

    块4x4(12):

    nA(块4*4(9))=4,nB(块4*4(6))=0,nC=(nA+Nb+1)>>1=2.5,

     (coeff_token):ce(v)=0000111(3,0)

    01110110 10110011(76 b3 )

    Suffixlength=0

    非零系数1:(Level_prefix(2):ce(v)=01(1)     Suffixlength=0

               Level(2)=-2

    非零系数2:(Level_prefix(1):ce(v)=1(0)    

                      Level_suffix:u(v)=1(1)         Suffixlength=1

                       Level(1)=-1

    非零系数3:(Level_prefix(0):ce(v)= 01(1)    

                     Level_suffix:u(v)=1(1)       

                        Level(0)=-2

    Zeroleft=(Total_zeros):ce(v)=0101(0) 

    综上所述,块4x4(12)的矩阵A(反zig-zag)是:

                  

    块4x4(13):

    nA(块4*4(12))=3, nB(块4*4(7))=0,nC=(nB+Nb+1)>>1=2,

     (coeff_token):ce(v)=10(1,1)

     (Trailing_ones_sign_flag(0)):u(1)=0(+)

    Zeroleft=(Total_zeros):ce(v)=1 (0)

        综上所述,块4x4(13)的矩阵A(反zig-zag)是:

                  

    01000001 10110101(41 b5)

    块4x4(14):

    nA(块4*4(11))=1, nB(块4*4(12))=3,nC=(nB+Nb+1)>>1=2.5,

    (coeff_token):ce(v)=10(1,1)

    (Trailing_ones_sign_flag(0)):u(1)=1(-)

    Zeroleft=(Total_zeros):ce(v)=0000011 (9)

        综上所述,块4x4(14)的矩阵A(反zig-zag)是:

                  

    块4x4(15):

    nA(块4*4(14))=1, nB(块4*4(13))=1,nC=(nB+Na+1)>>1=1.5,

    (coeff_token):ce(v)=01(1,1)

     (Trailing_ones_sign_flag(0)):u(1)=1(-)

    Zeroleft=(Total_zeros):ce(v)=010(2)

        综上所述,块4x4(15)的矩阵A(反zig-zag)是:

                  

    Chroma DC

    因为4:2:0,所以nC=-1,

    (coeff_token):ce(v)=1 (1,1)

    00101000 0110010128 65

    (Trailing_ones_sign_flag(0)):u(1)=0(+)

    Zeroleft=(Total_zeros):ce(v)=01 (2)

        综上所述,UDC2X2的矩阵A(反zig-zag)是:

                  

    此处先对A进行IDCT,然后再进行反量化(参考书《THE H.264 ADVANCEDVIDEO COMPRESSION STANDARD》)第183页,反量化过程参考《H.264变换和量化的分析。pdf》楼剑,陆亮

    (coeff_token):ce(v)=01 (0,0)

    综上所述,V  DC2X2的矩阵A(反zig-zag)是:

                  

    Chroma AC

    U:

    块4x4(18)

    nC=0,

     (coeff_token):ce(v)=000011(4,3)

    (Trailing_ones_sign_flag(3)):u(1)=0(+)

    (Trailing_ones_sign_flag(2)):u(1)=0(+)

    (Trailing_ones_sign_flag(1)):u(1)=1(-)

    Suffixlength=0

    非零系数1:(Level_prefix(0):ce(v)=01(1)     Suffixlength=1

               Level(0)=-1

    10101011 11111110ab fe

    Zeroleft=(Total_zeros):ce(v)=101(5) (特别注意,此处并没有算左上角哪一位)

    (Run _before(3)):ce(v)= 010(3)    zeroleft=2

    (Run_before(2)):ce(v)=1(0)     zeroleft=2

    (Run _before(1)):ce(v)= 1(0)    zeroleft=2

    Run _before(0)=2,不编码

    综上所述,块4x4(18)的矩阵A(反zig-zag)是(已经把DC部分写进去了):

                  

    块4x4(19)

    nA(块4*4(18))=4,nC=(nA)=4

    (coeff_token):ce(v)=1111(0,0)

    综上所述,块4x4(19)的矩阵A(反zig-zag)是(已经把DC部分写进去了):

                  

    块4x4(20)

    nB(块4*4(18))=4,nC=(nB)=4

    (coeff_token):ce(v)=1110(1,1)

    0003d330    84 7ff2 d2 a2 9c 87 54 7b 43 30 44 b4 bc 94 1a 

    10000100 01111111(84 7f)

    (Trailing_ones_sign_flag(0)):u(1)=1(-)

    Zeroleft=(Total_zeros):ce(v)=000010(8)(特别注意,此处并没有算左上角哪一位)

    综上所述,块4x4(20)的矩阵A(反zig-zag)是(已经把DC部分写进去了):

                  

    块4x4(21)

    nB(块4*4(19))=0,nB(块4*4(20))=1,nC=(nB+Na+1)>>2=1

    (coeff_token):ce(v)=001(2,2)

     (Trailing_ones_sign_flag(1)):u(1)=1(-)

    (Trailing_ones_sign_flag(0)):u(1)=1(-)

    Zeroleft=(Total_zeros):ce(v)=111(0)(特别注意,此处并没有算左上角哪一位)

    综上所述,块4x4(21)的矩阵A(反zig-zag)是(已经把DC部分写进去了):

                  

     

    P_ 8x8ref0(ducks.Frame2.Mb2)

    (mb_skip_run): ue(v)=1(0),不跳

    (mb_type)ue(v)=00101(4) , 预测模式为P_8x8ref0

    11101001 10011000 11101101 01010110(e9 98 ed56 42 bb 63)

    每个块8X8的预测类型:

    (sub_mb_type(0)):ue(v)=011(2),预测模式为P_L0_4X8

    (sub_mb_type(1)): ue(v)=1(0), 预测模式为P_L0_8X8

    (sub_mb_type(2)) :ue(v)=010(1), 预测模式为P_L0_8X4

    (sub_mb_type(3)) :ue(v)=011(1), 预测模式为P_L0_4X8

    块8x8(0):

    mvd_10[mbPartIdx=0][submbpartidx=0][compIdx=0]:se(v)=00110(3),水平运动矢量

    mvd_10[mbPartIdx=0][0][compIdx=1]:se(v)=00111(-3),垂直运动矢量

    (mvd_10[mbPartIdx=0][1][compIdx=0]):se(v)=011(-1),水平运动矢量

    mvd_10[mbPartIdx=0][1][compIdx=1]:se(v)=010(1),垂直运动矢量

    块8x8(1):

    mvd_10[mbPartIdx=1][0][compIdx=0]:se(v)=1(0),水平运动矢量

    mvd_10[mbPartIdx=1][0][compIdx=1]:se(v)=010(1),垂直运动矢量

    块8x8(2):

    mvd_10[mbPartIdx=2][0][compIdx=0]:se(v)=1(0),水平运动矢量

    mvd_10[mbPartIdx=2][0][compIdx=1]:se(v)=1(0),垂直运动矢量

    01000010 10111011 01100011 00110000(42 bb 6330)

    mvd_10[mbPartIdx=2][1][compIdx=0]:se(v)=00100(2),水平运动矢量

    mvd_10[mbPartIdx=2][1][compIdx=1]:se(v)=00101(-2),垂直运动矢量

    块8x8(3):

    mvd_10[mbPartIdx=3][0][compIdx=0]:se(v)=011(-1),水平运动矢量

    mvd_10[mbPartIdx=3][0][compIdx=1]:se(v)=1(0),垂直运动矢量

    mvd_10[mbPartIdx=3][1][compIdx=0]:se(v)=011(-1),水平运动矢量

    mvd_10[mbPartIdx=3][1][compIdx=1]:se(v)=011(-1),垂直运动矢量

    (Coded_block_pattern):me(v)=0001100(15),CBP=15,CodeBlockPatternLuma=CBP%16=15,CodeBlockPatternLuma=CBP/16=0(每个8*8块都有非零系数,色度信号CrCb全零);

    (Mb_qp_delta):se(v)=1(0), QP=28+0=28

    下面主要来讲讲在宏块层句法中,各种类型宏块(intra_4x4,intra_16x16,p_8x8ref0和非p_8x8ref0的inter)中的区别:

    1、   sub_mb_pred(mb_type)和mb_pred(mb_type)的选择:只有p_8x8ref0时,选择sub_mb_pred(mb_type)。p_8x8ref0类型:16x16块分为4个8x8块,然后每个8x8块还会细分成更小的块。所以在sub_mb_pred(mb_type)中首先要给出每一个更小的块的sub_mb_type,然后给出每一个更小的块的运动矢量(这步和mb_pred(mb_type)是一样的)。而当选择mb_pred(mb_type)时,若宏块是intra类型时,就不会有运动矢量的说法。而是给出了另外几个参数:

     

    2、   残差句法中的特殊情况:

    若宏块类型是intre6x6时,先要对亮度DC进行CAVLC变换,这一点在其他类型中是没有的

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     



     成功不一定需要努力,但封神的道路一定得写好每一行代码! 


  • 相关阅读:
    <frame>、<iframe>、<embed>、<object> 和 <applet>
    xss攻击
    回流 和 重绘
    defer 和 async 的区别
    从输入URL到浏览页面的过程
    webkit vs v8
    缓存
    LeetCode
    LeetCode
    LeetCode
  • 原文地址:https://www.cnblogs.com/Bnian/p/5171291.html
Copyright © 2020-2023  润新知