Index: slicetype.c =================================================================== --- slicetype.c (revision 667) +++ slicetype.c (working copy) @@ -246,6 +246,11 @@ #undef TRY_BIDIR #undef SAVE_MVS +/* Evaluate cost of a candidate frame (b), using p0 as L0 + * and p1 as L1 references. + * 2 references different from b => B frame + * 1 references different from b => P frame + * 0 reference different from b => I frame */ int x264_slicetype_frame_cost( x264_t *h, x264_mb_analysis_t *a, x264_frame_t **frames, int p0, int p1, int b, int b_intra_penalty ) @@ -322,17 +327,14 @@ return i_score; } -static int scenecut( x264_t *h, x264_frame_t *frame, int pdist ) +static float scenecut_bias( x264_t *h, x264_frame_t *frame) { - int icost = frame->i_cost_est[0][0]; - int pcost = frame->i_cost_est[pdist][0]; float f_bias; int i_gop_size = frame->i_frame - h->frames.i_last_idr; 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 * h->param.i_keyint_min / ( h->param.i_keyint_max * 4 ); - int res; if( h->param.i_keyint_min == h->param.i_keyint_max ) f_thresh_min= f_thresh_max; @@ -347,7 +349,20 @@ * ( i_gop_size - h->param.i_keyint_min ) / ( h->param.i_keyint_max - h->param.i_keyint_min ); } + return f_bias; +} + + + +static int scenecut( x264_t *h, x264_frame_t *frame, int pdist ) +{ + int icost = frame->i_cost_est[0][0]; + int pcost = frame->i_cost_est[pdist][0]; + float f_bias = scenecut_bias(h, frame); + int i_gop_size = frame->i_frame - h->frames.i_last_idr; + int res; + res = pcost >= (1.0 - f_bias) * icost; if( res ) { @@ -369,8 +384,9 @@ int keyint_limit; int j; int i_mb_count = (h->sps->i_mb_width - 2) * (h->sps->i_mb_height - 2); - int cost1p0, cost2p0, cost1b1, cost2p1; + int cost1p0, cost2p0, cost1b0, cost2p1; int idr_frame_type; + int no_b_frames = 0; assert( h->frames.b_have_lowres ); @@ -389,29 +405,67 @@ if( num_frames == 1 ) { -no_b_frames: + no_b_frames = 1; + } + else + { + + cost2p0 = x264_slicetype_frame_cost( h, &a, frames, 0, 2, 2, 1 ); + if( frames[2]->i_intra_mbs[2] > i_mb_count / 2 ) + no_b_frames = 1; + + if (!no_b_frames ) + { + cost1b0 = x264_slicetype_frame_cost( h, &a, frames, 0, 2, 1, 0 ); + cost1p0 = x264_slicetype_frame_cost( h, &a, frames, 0, 1, 1, 0 ); + cost2p1 = x264_slicetype_frame_cost( h, &a, frames, 1, 2, 2, 0 ); +// fprintf( stderr, "PP: %d + %d <=> BP: %d + %d \n", +// cost1p0, cost2p1, cost1b0, cost2p0 ); + if( cost1p0 + cost2p1 < cost1b0 + cost2p0 ) + no_b_frames = 1; + } + } + + cost1p0 = x264_slicetype_frame_cost( h, &a, frames, 0, 1, 1, 0 ); + if (no_b_frames) + { frames[1]->i_type = X264_TYPE_P; if( h->param.b_pre_scenecut ) { - x264_slicetype_frame_cost( h, &a, frames, 0, 1, 1, 0 ); - if( scenecut( h, frames[1], 1 ) ) - frames[1]->i_type = idr_frame_type; + if( scenecut( h, frames[1], 1)) + { + int flash_pic = 0; + + if (num_frames > 1) + { + if (!scenecut( h, frames[2], 2)) + { + // if 0<--2 is not a scene cut, test if 1 could be a "flash" picture + int cost2p0, cost2p1; + + cost2p0 = x264_slicetype_frame_cost( h, &a, frames, 0, 2, 2, 1 ); + cost2p1 = x264_slicetype_frame_cost( h, &a, frames, 1, 2, 2, 0 ); + + if (cost2p0 < cost2p1) //real evaluation would be: (costIntra1 + cost2p0 < costIntra1 + cost2p1) + flash_pic = 1; + } + } + + if (flash_pic) + { + no_b_frames = 0; + frames[1]->i_type = X264_TYPE_B; + } + else + { + frames[1]->i_type = idr_frame_type; + } + } } - return; + if (no_b_frames) + return; } - cost2p1 = x264_slicetype_frame_cost( h, &a, frames, 0, 2, 2, 1 ); - if( frames[2]->i_intra_mbs[2] > i_mb_count / 2 ) - goto no_b_frames; - - cost1b1 = x264_slicetype_frame_cost( h, &a, frames, 0, 2, 1, 0 ); - cost1p0 = x264_slicetype_frame_cost( h, &a, frames, 0, 1, 1, 0 ); - cost2p0 = x264_slicetype_frame_cost( h, &a, frames, 1, 2, 2, 0 ); -// fprintf( stderr, "PP: %d + %d <=> BP: %d + %d \n", -// cost1p0, cost2p0, cost1b1, cost2p1 ); - if( cost1p0 + cost2p0 < cost1b1 + cost2p1 ) - goto no_b_frames; - // arbitrary and untuned #define INTER_THRESH 300 #define P_SENS_BIAS (50 - h->param.i_bframe_bias)