Cavlc
需要内容
coeff_token 编码非零系数的个数(totalcoeff)和trailingones(没个宏块一个)
Trailing_ones_sign_flag trailing one值得符号
Level_prefix 非零系数码字的第一部分(每个系数一个,除了trailing ones)
Level_suffix 非零系数码字的第二部分(不总是存在)
Total_zeros 编码第一个非零系数后面发生的零的总数(按zigzag顺序)(每个块一个)
Run_before 编码每个非零系数前的零的个数,按照反zigzag顺序
函数中对应代码
最开始调用计算非零个数 函数在x264_quant_init中初始化
调用函数 i_total = h->quantf.coeff_level_run[ctx_block_cat]( l, &runlevel );
初始化函数 pf->coeff_level_run4 = x264_coeff_level_run4;
pf->coeff_level_run8 = x264_coeff_level_run8;
pf->coeff_level_run[ DCT_LUMA_AC] = x264_coeff_level_run15;
pf->coeff_level_run[ DCT_LUMA_4x4] = x264_coeff_level_run16;
后面是个宏定义
#define level_run(num)\
static int x264_coeff_level_run##num( dctcoef *dct, x264_run_level_t *runlevel )\
{\
int i_last = runlevel->last = x264_coeff_last##num(dct);\
int i_total = 0;\
int mask = 0;\
do\
{\
runlevel->level[i_total++] = dct[i_last];\
mask |= 1 << (i_last);\
while( --i_last >= 0 && dct[i_last] == 0 );\
} while( i_last >= 0 );\
runlevel->mask = mask;\
return i_total;\
}
level_run(4)
level_run(8)
level_run(15)
level_run(16)
展开
static int x264_coeff_level_run16( dctcoef *dct, x264_run_level_t *runlevel )
{
int i_last = runlevel->last = x264_coeff_last16(dct);
int i_total = 0;
int mask = 0;
do
{
runlevel->level[i_total++] = dct[i_last];
mask |= 1 << (i_last);
while ( --i_last >= 0; && dct[i_last] == 0 )
} while (i_last >= 0)
runlevel->mask = mask;
return total;
}
第二行的x264_coeff_last16(dct)还是个宏定义
#define last(num)\
static int x264_coeff_last##num( dctcoef *l )\
{\
int i_last = num-1;\
while( i_last >= 0 && l[i_last] == 0 )\
i_last--;\
return i_last;\
}
last(4)
last(8)
last(15)
last(16)
last(64)
展开
static int x264_coeff_last16( dctcoef *l )
{
int i_last = num-1;
while ( i_last >= 0 && l[i_last] == 0 )
i_last--;
return i_last;
}
这样这个宏的整体脉络比较清晰了,传输过来的dct就是活着4x4 8x8 16x16的zig之后的那个一维数组,第二个函数x264_coeff_last16来统计这个序列中从最后开始有多少个0,最后返回第一个不是0的位置。
Runlevel中的last就是标识这个位置的。
里面的第二个循环就是将所有不为0的数复制到runlevel->level数组中,这个数组的元素个数和dct里面相同,因为复制的位置都完全相同的。
Level->mask元素暂且不知道具体含义,指示对每个位置都做了下左移位操作,有几个非0的元素就做几次左移。