x264源码分析--函数x264_rc_analyse_slice

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

}

以上如果有注释不准或者不太清晰的地方,还请多拍砖留言,一起交流学习。

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值