From fc2e7ba68bfcb5b22f510839b6f0b3da333671fd Mon Sep 17 00:00:00 2001 From: Loren Merritt Date: Sat, 8 Jan 2005 02:51:24 +0000 Subject: [PATCH] improved mv prediction: 1-3% better compression of B-frames early termination for B-frame ref search: up to 20% faster with lots of refs. git-svn-id: svn://svn.videolan.org/x264/trunk@88 df754926-b1dd-0310-bc7b-ec298dee348c --- common/macroblock.c | 17 +++++++++++++++-- common/macroblock.h | 2 +- encoder/analyse.c | 18 ++++++++++++++++-- 3 files changed, 32 insertions(+), 5 deletions(-) diff --git a/common/macroblock.c b/common/macroblock.c index 6324713a..a2f176fc 100644 --- a/common/macroblock.c +++ b/common/macroblock.c @@ -524,11 +524,24 @@ void x264_mb_load_mv_direct8x8( x264_t *h, int idx ) } /* This just improves encoder performance, it's not part of the spec */ -void x264_mb_predict_mv_ref16x16( x264_t *h, int i_list, int i_ref, int mvc[4][2], int *i_mvc ) +void x264_mb_predict_mv_ref16x16( x264_t *h, int i_list, int i_ref, int mvc[5][2], int *i_mvc ) { int16_t (*mvr)[2] = h->mb.mvr[i_list][i_ref]; - int i = 0; + + /* temporal */ + if( h->sh.i_type == SLICE_TYPE_B ) + { + if( h->mb.cache.ref[i_list][x264_scan8[12]] == i_ref ) + { + int16_t *mvp = h->mb.cache.mv[i_list][x264_scan8[12]]; + mvc[i][0] = mvp[0]; + mvc[i][1] = mvp[1]; + i++; + } + } + + /* spatial */ if( h->mb.i_mb_x > 0 ) { int i_mb_l = h->mb.i_mb_xy - 1; diff --git a/common/macroblock.h b/common/macroblock.h index 806585ba..ec0b0ae4 100644 --- a/common/macroblock.h +++ b/common/macroblock.h @@ -184,7 +184,7 @@ void x264_mb_load_mv_direct8x8( x264_t *h, int idx ); * set mvc with D_16x16 prediction. * uses all neighbors, even those that didn't end up using this ref. * h->mb. need only valid values from other blocks */ -void x264_mb_predict_mv_ref16x16( x264_t *h, int i_list, int i_ref, int mvc[4][2], int *i_mvc ); +void x264_mb_predict_mv_ref16x16( x264_t *h, int i_list, int i_ref, int mvc[5][2], int *i_mvc ); int x264_mb_predict_intra4x4_mode( x264_t *h, int idx ); diff --git a/encoder/analyse.c b/encoder/analyse.c index 3d98f41b..7b0d6b3a 100644 --- a/encoder/analyse.c +++ b/encoder/analyse.c @@ -794,6 +794,9 @@ static void x264_mb_analyse_inter_b16x16( x264_t *h, x264_mb_analysis_t *a ) x264_me_t m; int i_ref; + int mvc[5][2], i_mvc; + int i_fullpel_thresh = INT_MAX; + int *p_fullpel_thresh = h->i_ref0>1 ? &i_fullpel_thresh : NULL; /* 16x16 Search on all ref frame */ m.i_pixel = PIXEL_16x16; @@ -809,7 +812,8 @@ static void x264_mb_analyse_inter_b16x16( x264_t *h, x264_mb_analysis_t *a ) /* search with ref */ m.p_fref = h->mb.pic.p_fref[0][i_ref][0]; x264_mb_predict_mv_16x16( h, 0, i_ref, m.mvp ); - x264_me_search( h, &m, NULL, 0 ); + x264_mb_predict_mv_ref16x16( h, 0, i_ref, mvc, &i_mvc ); + x264_me_search_ref( h, &m, mvc, i_mvc, p_fullpel_thresh ); /* add ref cost */ m.cost += m.lm * bs_size_te( h->sh.i_num_ref_idx_l0_active - 1, i_ref ); @@ -819,18 +823,24 @@ static void x264_mb_analyse_inter_b16x16( x264_t *h, x264_mb_analysis_t *a ) a->l0.i_ref = i_ref; a->l0.me16x16 = m; } + + /* save mv for predicting neighbors */ + h->mb.mvr[0][i_ref][h->mb.i_mb_xy][0] = m.mv[0]; + h->mb.mvr[0][i_ref][h->mb.i_mb_xy][1] = m.mv[1]; } /* subtract ref cost, so we don't have to add it for the other MB types */ a->l0.me16x16.cost -= m.lm * bs_size_te( h->sh.i_num_ref_idx_l0_active - 1, a->l0.i_ref ); /* ME for list 1 */ + /* not using fullpel_thresh since we don't yet do more than 1 list 1 ref */ a->l1.me16x16.cost = INT_MAX; for( i_ref = 0; i_ref < h->i_ref1; i_ref++ ) { /* search with ref */ m.p_fref = h->mb.pic.p_fref[1][i_ref][0]; x264_mb_predict_mv_16x16( h, 1, i_ref, m.mvp ); - x264_me_search( h, &m, NULL, 0 ); + x264_mb_predict_mv_ref16x16( h, 1, i_ref, mvc, &i_mvc ); + x264_me_search( h, &m, mvc, i_mvc ); /* add ref cost */ m.cost += m.lm * bs_size_te( h->sh.i_num_ref_idx_l1_active - 1, i_ref ); @@ -840,6 +850,10 @@ static void x264_mb_analyse_inter_b16x16( x264_t *h, x264_mb_analysis_t *a ) a->l1.i_ref = i_ref; a->l1.me16x16 = m; } + + /* save mv for predicting neighbors */ + h->mb.mvr[1][i_ref][h->mb.i_mb_xy][0] = m.mv[0]; + h->mb.mvr[1][i_ref][h->mb.i_mb_xy][1] = m.mv[1]; } /* subtract ref cost, so we don't have to add it for the other MB types */ a->l1.me16x16.cost -= m.lm * bs_size_te( h->sh.i_num_ref_idx_l1_active - 1, a->l1.i_ref ); -- 2.40.0