Index: encoder/macroblock.c =================================================================== --- encoder/macroblock.c (revision 671) +++ encoder/macroblock.c (working copy) @@ -188,6 +188,7 @@ { int i, ch; int b_decimate = b_inter && (h->sh.i_type == SLICE_TYPE_B || h->param.analyse.b_dct_decimate); + b_decimate |= (h->sh.i_type == SLICE_TYPE_B) && (i_qscale > 30) && (h->param.analyse.b_dct_decimate); for( ch = 0; ch < 2; ch++ ) { Index: encoder/slicetype.c =================================================================== --- encoder/slicetype.c (revision 671) +++ encoder/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,63 @@ if( num_frames == 1 ) { -no_b_frames: - frames[1]->i_type = X264_TYPE_P; - if( h->param.b_pre_scenecut ) + 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 ) { - x264_slicetype_frame_cost( h, &a, frames, 0, 1, 1, 0 ); - if( scenecut( h, frames[1], 1 ) ) + 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) + { + if( h->param.b_pre_scenecut && scenecut( h, frames[1], 1)) + { + int flash_pic = 0; + + if ((num_frames > 1) && !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; + } + else + { frames[1]->i_type = idr_frame_type; + return; + } } + } + if (no_b_frames) + { + frames[1]->i_type = X264_TYPE_P; 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) @@ -419,18 +469,32 @@ for( j = 2; j <= X264_MIN( h->param.i_bframe, num_frames-1 ); j++ ) { + /* + 0 1 2 3 + j + */ int pthresh = X264_MAX(INTER_THRESH - P_SENS_BIAS * (j-1), INTER_THRESH/10); - int pcost = x264_slicetype_frame_cost( h, &a, frames, 0, j+1, j+1, 1 ); + int cost3p0 = x264_slicetype_frame_cost( h, &a, frames, 0, j+1, j+1, 1 ); + // fprintf( stderr, "frm%d+%d: %d <=> %d, I:%d/%d \n", // frames[0]->i_frame, j-1, pthresh, pcost/i_mb_count, // frames[j+1]->i_intra_mbs[j+1], i_mb_count ); - if( pcost > pthresh*i_mb_count || frames[j+1]->i_intra_mbs[j+1] > i_mb_count/3 ) + frames[j]->i_type = X264_TYPE_B; + + if (frames[j+1]->i_intra_mbs[j+1] > i_mb_count/3) { frames[j]->i_type = X264_TYPE_P; break; } - else - frames[j]->i_type = X264_TYPE_B; + else if (cost3p0 > pthresh*i_mb_count) + { + int cost2p0 = x264_slicetype_frame_cost( h, &a, frames, 0, j, j, 1 ); + if (cost3p0 > (cost2p0*11/10)) + { + frames[j]->i_type = X264_TYPE_P; + break; + } + } } }