概述
x264_rc_analyse_slice 函数的功能是分析当前要编码的slice,并计算得到cost。大体流程,先从编码缓存fenc中找到当前要编码的编码帧。然后计算cost,这种计算cost来控制码控的方法是用于B帧和2pass模式的。
下面具体看代码:
int x264_rc_analyse_slice( x264_t *h )//分析一个slice,在B帧和2pass的时候计算残差
{
int p0 = 0, p1, b;//p0 向前参考的帧序号,p1向后参考的帧序号,b b帧的序号
int cost;//最后得到的残差和
x264_emms();//emms指令集初始化
if( IS_X264_TYPE_I(h->fenc->i_type) )//是否是I帧
p1 = b = 0;//I帧的话,参考帧都要清零,因为不参考别的帧
else if( h->fenc->i_type == X264_TYPE_P )//如果是P帧
p1 = b = h->fenc->i_bframes + 1;//向后参考的帧是b帧数量+1,因为前面有连续bframes个B帧
else //B
{
p1 = (h->fref_nearest[1]->i_poc - h->fref_nearest[0]->i_poc)/2;//p0是初始便宜,相当于计算后面一个参考帧的相对位置
b = (h->fenc->i_poc - h->fref_nearest[0]->i_poc)/2;//当前这个b帧的相对位置
}
/* We don't need to assign p0/p1 since we are not performing any real analysis here. */
x264_frame_t **frames = &h->fenc - b;//偏移到当前的编码帧,fenc是编码帧缓存
/* cost should have been already calculated by x264_slicetype_decide */
cost = frames[b]->i_cost_est[b-p0][p1-b];//残差预测,i_cost_est是事先预测好的,这里仅仅是通过帧的相对序号来索引
assert( cost >= 0 );
if( h->param.rc.b_mb_tree && !h->param.rc.b_stat_read )//如果是宏块树调整码率,但是却无法读取到状态 2pass编码模式
{
cost = x264_slicetype_frame_cost_recalculate( h, frames, p0, p1, b );//第一次,还没有stat_read的时候,先把所以的帧的satd计算一遍,satd哈德曼变换后的残差
if( b && h->param.rc.i_vbv_buffer_size )//vbv buffer大小
x264_slicetype_frame_cost_recalculate( h, frames, b, b, b );
}
/* In AQ, use the weighted score instead. */
else if( h->param.rc.i_aq_mode )//如果是自适应量化
cost = frames[b]->i_cost_est_aq[b-p0][p1-b];//编码消耗预测
h->fenc->i_row_satd = h->fenc->i_row_satds[b-p0][p1-b];//编码帧satd
h->fdec->i_row_satd = h->fdec->i_row_satds[b-p0][p1-b];//重建帧satd
h->fdec->i_satd = cost;//先赋值事先预测好的satd
memcpy( h->fdec->i_row_satd, h->fenc->i_row_satd, h->mb.i_mb_height * sizeof(int) );//初始化重建帧的satd
if( !IS_X264_TYPE_I(h->fenc->i_type) )//如果帧类型不是I帧
{
memcpy( h->fdec->i_row_satds[0][0], h->fenc->i_row_satds[0][0], h->mb.i_mb_height * sizeof(int) );
} //重建帧的satd等于编码帧的satd,因为I帧不参考别的帧
if( h->param.b_intra_refresh && h->param.rc.i_vbv_buffer_size && h->fenc->i_type == X264_TYPE_P )
{
int ip_factor = 256 * h->param.rc.f_ip_factor; /* fix8 */
for( int y = 0; y < h->mb.i_mb_height; y++ )
{
int mb_xy = y * h->mb.i_mb_stride + h->fdec->i_pir_start_col;
for( int x = h->fdec->i_pir_start_col; x <= h->fdec->i_pir_end_col; x++, mb_xy++ )
{
int intra_cost = (h->fenc->i_intra_cost[mb_xy] * ip_factor + 128) >> 8;//帧内消耗
int inter_cost = h->fenc->lowres_costs[b-p0][p1-b][mb_xy] & LOWRES_COST_MASK;//帧间消耗
int diff = intra_cost - inter_cost;//帧内satd - 帧间satd
if( h->param.rc.i_aq_mode )//如果是自适应量化
h->fdec->i_row_satd[y] += (diff * frames[b]->i_inv_qscale_factor[mb_xy] + 128) >> 8;//循环把残差累加起来 *自适应量化因子
else
h->fdec->i_row_satd[y] += diff;//如果不是自适应量化
cost += diff;
}
}
}
return cost;//返回计算出来的结果cost bits
}
以上如果有注释不准或者不太清晰的地方,还请多拍砖留言,一起交流学习。
最后
以上就是活泼小刺猬为你收集整理的x264源码分析--函数x264_rc_analyse_slice的全部内容,希望文章能够帮你解决x264源码分析--函数x264_rc_analyse_slice所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复