X264学习6-熵编码和buffer操作

熵编码与码流buffer操作

bitstream buffer的操作

bitstream buffer操作的流程(version20171114)

其操作流程图(活动图)如下。
在这里插入图片描述

在x264码流操作中,主要涉及到两个内存空间:h->nal_buffer,h->thread[i]->out.p_bitstream。其中p_bitstream用于编码过程的码流写入操作;nal_buffer,为编码数据的nal和bytestream封装后的目标地址。

在每个单元(比如sps、pps、nal等)的码流写入后,都要调用bs_flush()。将当前字内已经写入的bit从低位bit移动到高位bit,同时确定下一个字节的位置,可能位于当前字内。

码流写入方式(version20100611)

写入码流的核心函数为bs_write()。

大小端模式

所谓的大端模式,是指数据的低位(就是权值较小的后面那几位)保存在内存的高地址中,而数据的高位,保存在内存的低地址中,这样的存储模式有点儿类似于把数据当作字符串顺序处理:地址由小向大增加,而数据从高位往低位放。

所谓的小端模式,是指数据的低位保存在内存的低地址中,而数 据的高位保存在内存的高地址中,这种存储模式将地址的高低和数据位权有效地结合起来,高地址部分权值高,低地址部分权值低,和我们的逻辑方法一致。

以小端模式,假设数据为0x12345678,内存和int数据的示意图如下。
在这里插入图片描述

码流在内存中的顺序

码流在内存中的顺序中为从低地址高位bit到高地址低位bit。在小端模式下,其在内存中顺序和寄存器中的次序如下。
在这里插入图片描述

码流写入流程

在这里插入图片描述

将语法元素写入码流的方式。不管是大端还是小端,写入方式是:从低位字节的低位bit写入语法元素。而实际需要从高地址字的高位bit写入,所以写完一个字后,需要字内字节交换。

建议的优化策略

码流由bytestream格式修改为netstream格式

这样就可以省去包头(0x00 00 01/0x00 00 00 01)封装和插入起始码0x03。

修改bit的写入过程

修改bit写入字内存的过程,避免字内字节交换。

CAVLC编码(version20100611)

CAVLC编码的总体流程

x264中CAVLC的总体实现流程

宏块级编码的初始化流程位于函数x264_init_vlc_tables()实现,其主要用于初始化CAVLC表格x264_level_token。

宏块级的CAVLC编码位于函数x264_macroblock_write_cavlc(),其具体流程如下。

在这里插入图片描述

block_residual_write_cavlc()的总体实现流程

block_residual_write_cavlc()概况如下。

/**
 *@brief 对4x4量化后的数据CAVLC编码并输出
 *@param[in] h指向当前编码器
 *@param[in] i_ctxBlockCat        i_ctxBlockCat:编码4x4块的类型,其定义具体如下。
             enum cabac_ctx_block_cat_e
             {
                 DCT_LUMA_DC   = 0,//亮度DC系数编码
                 DCT_LUMA_AC   = 1,//亮度AC系数编码
                 DCT_LUMA_4x4  = 2,//亮度x4块编码,包括DC和AC系数
                 DCT_CHROMA_DC = 3,//色度块的DC系数编码
                 DCT_CHROMA_AC = 4,//色度块的AC系数编码
                 DCT_LUMA_8x8  = 5,//亮度x8块编码
               };
 *@param[in] nC表示相邻块非0系数的情况
 *@param[in] 指向需要熵编码的量化数据
 *@return 非0系数的个数
 */
block_residual_write_cavlc( x264_t *h, int i_ctxBlockCat, dctcoef *l, int nC )

在x264中,block_residual_write_cavlc()分两层实现,第一层实现以宏的方式进行,具体代码如下。

![block_residual_write_cavlc()外层编码流程图](F:/block_residual_write_cavlc()外层编码流程图.svg)#define block_residual_write_cavlc(h,cat,idx,l)\
{\
    int nC = cat == DCT_CHROMA_DC ? 4 : ct_index[x264_mb_predict_non_zero_code( h, cat == DCT_LUMA_DC ? 0 : idx )];\
    uint8_t *nnz = &h->mb.cache.non_zero_count[x264_scan8[idx]];\
    if( !*nnz )\
        bs_write_vlc( &h->out.bs, x264_coeff0_token[nC] );\
    else\
        *nnz = block_residual_write_cavlc(h,cat,l,nC);\
}

在第一层中,具体实现流程如下。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值