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;
}
参数含义:
关键帧最大间隔和关键帧最小间隔
参数解析:
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;
}