Commit c4f3dabe authored by Fiona Glaser's avatar Fiona Glaser

Use low-resolution lookahead motion vectors as an extra predictor

Improves quality considerably (0-5%) in 1pass/CRF mode, especially with lower --me values and complex motion.
Reverses the order of lowres lookahead search to improve the usefulness of the extra predictors.
parent f8f53139
......@@ -416,7 +416,7 @@ 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, int16_t mvc[8][2], int *i_mvc )
void x264_mb_predict_mv_ref16x16( x264_t *h, int i_list, int i_ref, int16_t mvc[9][2], int *i_mvc )
{
int16_t (*mvr)[2] = h->mb.mvr[i_list][i_ref];
int i = 0;
......@@ -433,6 +433,13 @@ void x264_mb_predict_mv_ref16x16( x264_t *h, int i_list, int i_ref, int16_t mvc[
SET_MVP( h->mb.cache.mv[i_list][x264_scan8[12]] );
}
if( i_ref == 0 && h->frames.b_have_lowres )
{
int16_t (*lowres_mv)[2] = i_list ? h->fenc->lowres_mvs[1][h->fref1[0]->i_frame-h->fenc->i_frame-1]
: h->fenc->lowres_mvs[0][h->fenc->i_frame-h->fref0[0]->i_frame-1];
if( lowres_mv[0][0] != 0x7fff ) *(uint32_t*)mvc[i++] = (*(uint32_t*)lowres_mv[h->mb.i_mb_xy]*2)&0xfffeffff;
}
/* spatial predictors */
if( h->mb.i_neighbour & MB_LEFT )
{
......
......@@ -1016,7 +1016,7 @@ static void x264_mb_analyse_inter_p16x16( x264_t *h, x264_mb_analysis_t *a )
{
x264_me_t m;
int i_ref, i_mvc;
DECLARE_ALIGNED_4( int16_t mvc[7][2] );
DECLARE_ALIGNED_4( int16_t mvc[8][2] );
int i_halfpel_thresh = INT_MAX;
int *p_halfpel_thresh = h->mb.pic.i_fref[0]>1 ? &i_halfpel_thresh : NULL;
......@@ -1493,7 +1493,7 @@ static void x264_mb_analyse_inter_b16x16( x264_t *h, x264_mb_analysis_t *a )
x264_me_t m;
int i_ref, i_mvc;
DECLARE_ALIGNED_4( int16_t mvc[8][2] );
DECLARE_ALIGNED_4( int16_t mvc[9][2] );
int i_halfpel_thresh = INT_MAX;
int *p_halfpel_thresh = h->mb.pic.i_fref[0]>1 ? &i_halfpel_thresh : NULL;
......
......@@ -150,16 +150,17 @@ static int x264_slicetype_mb_cost( x264_t *h, x264_mb_analysis_t *a,
if( do_search[l] )
{
/* Reverse-order MV prediction. */
#define MVC(mv) { *(uint32_t*)mvc[i_mvc] = *(uint32_t*)mv; i_mvc++; }
if( i_mb_x > 0 )
MVC(fenc_mv[-1]);
if( i_mb_y > 0 )
if( i_mb_x < h->sps->i_mb_width - 1 )
MVC(fenc_mv[1]);
if( i_mb_y < h->sps->i_mb_height - 1 )
{
MVC(fenc_mv[-i_mb_stride]);
if( i_mb_x < h->sps->i_mb_width - 1 )
MVC(fenc_mv[-i_mb_stride+1]);
MVC(fenc_mv[i_mb_stride]);
if( i_mb_x > 0 )
MVC(fenc_mv[-i_mb_stride-1]);
MVC(fenc_mv[i_mb_stride-1]);
if( i_mb_x < h->sps->i_mb_width - 1 )
MVC(fenc_mv[i_mb_stride+1]);
}
#undef MVC
x264_median_mv( m[l].mvp, mvc[0], mvc[1], mvc[2] );
......@@ -288,20 +289,22 @@ static int x264_slicetype_frame_cost( x264_t *h, x264_mb_analysis_t *a,
if( p1 != p0 )
dist_scale_factor = ( ((b-p0) << 8) + ((p1-p0) >> 1) ) / (p1-p0);
/* Lowres lookahead goes backwards because the MVs are used as predictors in the main encode. */
/* This considerably improves MV prediction overall. */
if( h->sps->i_mb_width <= 2 || h->sps->i_mb_height <= 2 )
{
for( h->mb.i_mb_y = 0; h->mb.i_mb_y < h->sps->i_mb_height; h->mb.i_mb_y++ )
for( h->mb.i_mb_x = 0; h->mb.i_mb_x < h->sps->i_mb_width; h->mb.i_mb_x++ )
for( h->mb.i_mb_y = h->sps->i_mb_height - 1; h->mb.i_mb_y >= 0 ; h->mb.i_mb_y-- )
for( h->mb.i_mb_x = h->sps->i_mb_width - 1; h->mb.i_mb_x >= 0 ; h->mb.i_mb_x-- )
i_score += x264_slicetype_mb_cost( h, a, frames, p0, p1, b, dist_scale_factor, do_search );
}
/* the edge mbs seem to reduce the predictive quality of the
* whole frame's score, but are needed for a spatial distribution. */
else if( h->param.rc.i_vbv_buffer_size )
{
for( h->mb.i_mb_y = 0; h->mb.i_mb_y < h->sps->i_mb_height; h->mb.i_mb_y++ )
for( h->mb.i_mb_y = h->sps->i_mb_height - 1; h->mb.i_mb_y >= 0; h->mb.i_mb_y-- )
{
row_satd[ h->mb.i_mb_y ] = 0;
for( h->mb.i_mb_x = 0; h->mb.i_mb_x < h->sps->i_mb_width; h->mb.i_mb_x++ )
for( h->mb.i_mb_x = h->sps->i_mb_width - 1; h->mb.i_mb_x >= 0; h->mb.i_mb_x-- )
{
int i_mb_cost = x264_slicetype_mb_cost( h, a, frames, p0, p1, b, dist_scale_factor, do_search );
int i_mb_cost_aq = i_mb_cost;
......@@ -323,8 +326,8 @@ static int x264_slicetype_frame_cost( x264_t *h, x264_mb_analysis_t *a,
}
else
{
for( h->mb.i_mb_y = 1; h->mb.i_mb_y < h->sps->i_mb_height - 1; h->mb.i_mb_y++ )
for( h->mb.i_mb_x = 1; h->mb.i_mb_x < h->sps->i_mb_width - 1; h->mb.i_mb_x++ )
for( h->mb.i_mb_y = h->sps->i_mb_height - 2; h->mb.i_mb_y > 0; h->mb.i_mb_y-- )
for( h->mb.i_mb_x = h->sps->i_mb_width - 2; h->mb.i_mb_x > 0; h->mb.i_mb_x-- )
{
int i_mb_cost = x264_slicetype_mb_cost( h, a, frames, p0, p1, b, dist_scale_factor, do_search );
int i_mb_cost_aq = i_mb_cost;
......
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