[x264-devel] commit: Use low-resolution lookahead motion vectors as an extra predictor ( Jason Garrett-Glaser )
git version control
git at videolan.org
Wed Sep 17 09:56:53 CEST 2008
x264 | branch: master | Jason Garrett-Glaser <darkshikari at gmail.com> | Wed Sep 17 00:33:37 2008 -0700| [6d4af8d257162ac8881a0f96d9552eb928328d95] | committer: Jason Garrett-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.
> http://git.videolan.org/gitweb.cgi/x264.git/?a=commit;h=6d4af8d257162ac8881a0f96d9552eb928328d95
---
common/macroblock.c | 9 ++++++++-
encoder/analyse.c | 4 ++--
encoder/slicetype.c | 29 ++++++++++++++++-------------
3 files changed, 26 insertions(+), 16 deletions(-)
diff --git a/common/macroblock.c b/common/macroblock.c
index f194ede..115ae4e 100644
--- a/common/macroblock.c
+++ b/common/macroblock.c
@@ -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 )
{
diff --git a/encoder/analyse.c b/encoder/analyse.c
index 2a294ff..ecbaf4e 100644
--- a/encoder/analyse.c
+++ b/encoder/analyse.c
@@ -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;
diff --git a/encoder/slicetype.c b/encoder/slicetype.c
index fd06d41..04034f1 100644
--- a/encoder/slicetype.c
+++ b/encoder/slicetype.c
@@ -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;
More information about the x264-devel
mailing list