x264源码分析--参数keyint、min-keyint、keyint-min、scenecut

keyint、min-keyint、keyint-min
参数含义:
关键帧最大间隔和关键帧最小间隔
参数解析:
OPT("keyint")
    {
        if( strstr( value, "infinite" ) )
            p->i_keyint_max = X264_KEYINT_MAX_INFINITE;
        else
            p->i_keyint_max = atoi(value);
    }
    OPT2("min-keyint", "keyint-min")
    {
        p->i_keyint_min = atoi(value);
        if( p->i_keyint_max < p->i_keyint_min )
            p->i_keyint_max = p->i_keyint_min;
    }
代码逻辑:
x264_slicetype_analyse()
if( keyframe_dist >= h->param.i_keyint_max )
            {
                if( last_possible != 0 && last_possible != j )
                {
                    j = last_possible;
                    frm = frames[j];
                    keyframe_dist = frm->i_frame - last_keyframe;
                }
                last_possible = 0;
                if( frm->i_type != X264_TYPE_IDR )
                    frm->i_type = h->param.b_open_gop ? X264_TYPE_I : X264_TYPE_IDR;
            }
判断当前帧间隔,决定是否设置为关键帧。
if( frm->i_type == X264_TYPE_I && keyframe_dist >= h->param.i_keyint_min )
            {
                if( h->param.b_open_gop )
                {
                    last_keyframe = frm->i_frame;
                    if( h->param.b_bluray_compat )
                    {
                        // Use bluray order
                        int bframes = 0;
                        while( bframes < j-1 && IS_X264_TYPE_B( frames[j-1-bframes]->i_type ) )
                            bframes++;
                        last_keyframe -= bframes;
                    }
                }
                else if( frm->i_forced_type != X264_TYPE_I )
                    frm->i_type = X264_TYPE_IDR;
            }


参数名:scenecut
参数含义:
P帧大小比I帧大小百分比超过阈值,将当前帧类型调整为I帧。
参数解析:
OPT("scenecut")
    {
        p->i_scenecut_threshold = atobool(value);
        if( b_error || p->i_scenecut_threshold )
        {
            b_error = 0;
            p->i_scenecut_threshold = atoi(value);
        }
    }


代码逻辑:
static int scenecut_internal( x264_t *h, x264_mb_analysis_t *a, x264_frame_t **frames, int p0, int p1, int real_scenecut )
{
    x264_frame_t *frame = frames[p1];


    /* Don't do scenecuts on the right view of a frame-packed video. */
    if( real_scenecut && h->param.i_frame_packing == 5 && (frame->i_frame&1) )
        return 0;


    x264_slicetype_frame_cost( h, a, frames, p0, p1, p1 );


    int icost = frame->i_cost_est[0][0];
    int pcost = frame->i_cost_est[p1-p0][0];
    float f_bias;
    int i_gop_size = frame->i_frame - h->lookahead->i_last_keyframe;
    float f_thresh_max = h->param.i_scenecut_threshold / 100.0;// 占比,小数
    /* magic numbers pulled out of thin air */
    float f_thresh_min = f_thresh_max * 0.25;//最大占比的25% 是最小占比
    int res;


    if( h->param.i_keyint_min == h->param.i_keyint_max )
        f_thresh_min = f_thresh_max;

    if( i_gop_size <= h->param.i_keyint_min / 4 || h->param.b_intra_refresh )
        f_bias = f_thresh_min / 4;
    else if( i_gop_size <= h->param.i_keyint_min )
        f_bias = f_thresh_min * i_gop_size / h->param.i_keyint_min;
    else
    {
        f_bias = f_thresh_min
                 + ( f_thresh_max - f_thresh_min )//差值,映射到i_gop_size - h->param.i_keyint_min空间
                 * ( i_gop_size - h->param.i_keyint_min ) 
                 / ( h->param.i_keyint_max - h->param.i_keyint_min );//映射比值
    }


    res = pcost >= (1.0 - f_bias) * icost;//通过比值对比 I帧消耗和P帧消耗,如果大于比值,则判定为I帧,否则为P帧
    if( res && real_scenecut )
    {
        int imb = frame->i_intra_mbs[p1-p0];
        int pmb = NUM_MBS - imb;
        x264_log( h, X264_LOG_DEBUG, "scene cut at %d Icost:%d Pcost:%d ratio:%.4f bias:%.4f gop:%d (imb:%d pmb:%d)\n",
                  frame->i_frame,
                  icost, pcost, 1. - (double)pcost / icost,
                  f_bias, i_gop_size, imb, pmb );
    }
    return res;
}















阅读更多
个人分类: 音视频
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

关闭
关闭
关闭