Commit fc2e7ba6 authored by Loren Merritt's avatar Loren Merritt

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
parent 7fc5f99d
......@@ -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;
......
......@@ -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 );
......
......@@ -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 );
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment