H.264笔记之二——宏块结构

    技术2022-05-11  31

    这里主要有一下几个过程:1. 初始化h->stat.frame,即全部清零。2. 写条带头:x264_slice_header_write,即把刚才x264_slice_header_init设置的一些参数写入。3. 如果是CABAC编码,则初始化CABAC。有关CABAC在后续相关章节讨论。4. 遍历一帧中的所有宏块,这是编码的主要部分:for( mb_xy = h->sh.i_first_mb, i_skip = 0; mb_xy < h->sh.i_last_mb; )其中sh.i_first_mb和sh.i_last_mb在x264_slice_header_init中赋值,分别是0和宏块行列数乘积。5. 最后输出码流尾部。其间穿插一些必要的初始化和配置。

    本章着重分析编码的主要部分,包括一下过程:需要注意的是,这里讨论的宏块是固定尺寸的,即Y分量计为16x16。(而运动宏块的尺寸则是多变的)

    1. 首先根据宏块的序号得出宏块的坐标。然后统计当前宏块的码流位置:int mb_spos = bs_pos(&h->out.bs) + x264_cabac_pos(&h->cabac);

    2. 然后出现一句:if( i_mb_x == 0 )    x264_fdec_filter_row( h, i_mb_y );这是对行进行去块过程。详细情况专门论述。

    3. 随后是x264_macroblock_cache_load,这里主要进行当前宏块和相关信息的提取。这个函数比较大,也在专题中论述。

    4. 接下去进行解码分析操作x264_macroblock_analyse

    5. 以及解码实体:x264_macroblock_encode

    6. 而后处理码流输出,也分CABAC和CAVLC两种情况。

    7. 接着出现x264_macroblock_cache_save,和x264_macroblock_cache_load对应,保存处理完的宏块。

    8. 更新宏块统计

    下面,首先看编码主体x264_macroblock_encode的结构。该函数按不同宏块类型情况进行不同的处理。包括如下类型:P_SKIPB_SKIPI_16x16 - 一次完成一个块h->mb.pic.p_fdec[0]的编码。   用函数指针h->predict_16x16[i_mode]进行帧内预测I_8x8   - 分4次完成。h->mb.pic.p_fdec[0][8 * (i&1) + 8 * (i>>1) * FDEC_STRIDE]指定了当前位置。即:   [0][1]   [2][3]   用函数指针完成4个宏块的帧内预测I_4x4 - 分16次完成。h->mb.pic.p_fdec[0][4 * block_idx_x[i] + 4 * block_idx_y[i] * FDEC_STRIDE]指定当前位置。   根据block_idx_x和block_idx_y的定义,其顺序是:   [0][1][4][5]   [2][3][6][7]   [8][9][c][d]   [a][b][e][f]   用函数指针完成4个宏块的帧内预测Inter - 首先进行运动补偿。见后续讨论。          然后分多种情形:   1. 无损压缩情况:h->mb.b_lossless == TRUE(必须采用4x4DCT)      根据上述I_4x4中描述的顺序遍历16个4x4块。      这里调用的函数是zigzag_sub_4x4_field,完成残差。(无损情况直接发送残差)   2. 指定采用8x8DCT情况:h->mb.b_transform_8x8 == TRUE      首先是作残差并DCT的函数:sub16x16_dct8。      然后对4个8x8的DCT系数块进行处理:包括可能的去噪x264_denoise_dct,量化(标量/矢量)。有关量化也在专题中论述。量化完成后进行系数扫描(对角平衡的普通扫描)。   3. 一般情况      接着处理色差分量,如果是Intra的则进行预测。最后写Coded Block Pattern。


    最新回复(0)