[x264-devel] commit: Fix various early terminations with slices (Jason Garrett-Glaser )
git at videolan.org
git at videolan.org
Wed Apr 14 11:39:13 CEST 2010
x264 | branch: master | Jason Garrett-Glaser <darkshikari at gmail.com> | Sun Apr 11 13:36:50 2010 -0700| [5b86182d1240b441f28462abf3d40b7371de5ba3] | committer: Jason Garrett-Glaser
Fix various early terminations with slices
Neighbouring type values (type_top, etc) are now loaded even if the MB isn't available for prediction.
Significant overall performance increase (as high as 5-10%+) with lots of slices (e.g. with slice-max-size).
> http://git.videolan.org/gitweb.cgi/x264.git/?a=commit;h=5b86182d1240b441f28462abf3d40b7371de5ba3
---
common/macroblock.c | 71 +++++++++++++++++++++++++--------------------------
encoder/cabac.c | 12 ++++----
2 files changed, 41 insertions(+), 42 deletions(-)
diff --git a/common/macroblock.c b/common/macroblock.c
index 6dd19f6..0b9b903 100644
--- a/common/macroblock.c
+++ b/common/macroblock.c
@@ -958,66 +958,65 @@ static void inline x264_macroblock_cache_load_neighbours( x264_t *h, int mb_x, i
h->mb.i_mb_type_topleft = -1;
h->mb.i_mb_type_topright = -1;
- if( top >= 0 )
- {
- h->mb.i_neighbour_frame |= MB_TOP;
- h->mb.i_mb_top_xy = top;
- if( top >= h->sh.i_first_mb )
- {
- h->mb.i_neighbour |= MB_TOP;
- h->mb.i_mb_type_top = h->mb.type[h->mb.i_mb_top_xy];
-
- if( !h->param.b_constrained_intra || IS_INTRA( h->mb.i_mb_type_top ) )
- h->mb.i_neighbour_intra |= MB_TOP;
- }
- }
-
if( mb_x > 0 )
{
h->mb.i_neighbour_frame |= MB_LEFT;
h->mb.i_mb_left_xy = h->mb.i_mb_xy - 1;
+ h->mb.i_mb_type_left = h->mb.type[h->mb.i_mb_left_xy];
if( h->mb.i_mb_xy > h->sh.i_first_mb )
{
h->mb.i_neighbour |= MB_LEFT;
- h->mb.i_mb_type_left = h->mb.type[h->mb.i_mb_left_xy];
if( !h->param.b_constrained_intra || IS_INTRA( h->mb.i_mb_type_left ) )
h->mb.i_neighbour_intra |= MB_LEFT;
}
}
- if( mb_x > 0 && top - 1 >= 0 )
+ /* We can't predict from the previous threadslice since it hasn't been encoded yet. */
+ if( (h->i_threadslice_start >> h->mb.b_interlaced) != (mb_y >> h->mb.b_interlaced) )
{
- h->mb.i_neighbour_frame |= MB_TOPLEFT;
- h->mb.i_mb_topleft_xy = top - 1;
- if( top - 1 >= h->sh.i_first_mb )
+ if( top >= 0 )
{
- h->mb.i_neighbour |= MB_TOPLEFT;
+ h->mb.i_neighbour_frame |= MB_TOP;
+ h->mb.i_mb_top_xy = top;
+ h->mb.i_mb_type_top = h->mb.type[h->mb.i_mb_top_xy];
+ if( top >= h->sh.i_first_mb )
+ {
+ h->mb.i_neighbour |= MB_TOP;
+
+ if( !h->param.b_constrained_intra || IS_INTRA( h->mb.i_mb_type_top ) )
+ h->mb.i_neighbour_intra |= MB_TOP;
+ }
+ }
+
+ if( mb_x > 0 && top - 1 >= 0 )
+ {
+ h->mb.i_neighbour_frame |= MB_TOPLEFT;
+ h->mb.i_mb_topleft_xy = top - 1;
h->mb.i_mb_type_topright = h->mb.type[h->mb.i_mb_topleft_xy];
+ if( top - 1 >= h->sh.i_first_mb )
+ {
+ h->mb.i_neighbour |= MB_TOPLEFT;
- if( !h->param.b_constrained_intra || IS_INTRA( h->mb.i_mb_type_topleft ) )
- h->mb.i_neighbour_intra |= MB_TOPLEFT;
+ if( !h->param.b_constrained_intra || IS_INTRA( h->mb.i_mb_type_topleft ) )
+ h->mb.i_neighbour_intra |= MB_TOPLEFT;
+ }
}
- }
- if( mb_x < h->sps->i_mb_width - 1 && top + 1 >= 0 )
- {
- h->mb.i_neighbour_frame |= MB_TOPRIGHT;
- h->mb.i_mb_topright_xy = top + 1;
- if( top + 1 >= h->sh.i_first_mb )
+ if( mb_x < h->sps->i_mb_width - 1 && top + 1 >= 0 )
{
- h->mb.i_neighbour |= MB_TOPRIGHT;
+ h->mb.i_neighbour_frame |= MB_TOPRIGHT;
+ h->mb.i_mb_topright_xy = top + 1;
h->mb.i_mb_type_topleft = h->mb.type[h->mb.i_mb_topright_xy];
+ if( top + 1 >= h->sh.i_first_mb )
+ {
+ h->mb.i_neighbour |= MB_TOPRIGHT;
- if( !h->param.b_constrained_intra || IS_INTRA( h->mb.i_mb_type_topright ) )
- h->mb.i_neighbour_intra |= MB_TOPRIGHT;
+ if( !h->param.b_constrained_intra || IS_INTRA( h->mb.i_mb_type_topright ) )
+ h->mb.i_neighbour_intra |= MB_TOPRIGHT;
+ }
}
}
-
- /* We can't predict from the previous threadslice since it hasn't been encoded yet, so
- * only use left. */
- if( h->i_threadslice_start == mb_y )
- h->mb.i_neighbour_frame &= MB_LEFT;
}
void x264_macroblock_cache_load( x264_t *h, int mb_x, int mb_y )
diff --git a/encoder/cabac.c b/encoder/cabac.c
index 427dba7..a0dcff2 100644
--- a/encoder/cabac.c
+++ b/encoder/cabac.c
@@ -76,9 +76,9 @@ static void x264_cabac_mb_type( x264_t *h, x264_cabac_t *cb )
if( h->sh.i_type == SLICE_TYPE_I )
{
int ctx = 0;
- if( h->mb.i_mb_type_left >= 0 && h->mb.i_mb_type_left != I_4x4 )
+ if( (h->mb.i_neighbour & MB_LEFT) && h->mb.i_mb_type_left != I_4x4 )
ctx++;
- if( h->mb.i_mb_type_top >= 0 && h->mb.i_mb_type_top != I_4x4 )
+ if( (h->mb.i_neighbour & MB_TOP) && h->mb.i_mb_type_top != I_4x4 )
ctx++;
x264_cabac_mb_type_intra( h, cb, i_mb_type, 3+ctx, 3+3, 3+4, 3+5, 3+6, 3+7 );
@@ -110,9 +110,9 @@ static void x264_cabac_mb_type( x264_t *h, x264_cabac_t *cb )
else //if( h->sh.i_type == SLICE_TYPE_B )
{
int ctx = 0;
- if( h->mb.i_mb_type_left >= 0 && h->mb.i_mb_type_left != B_SKIP && h->mb.i_mb_type_left != B_DIRECT )
+ if( (h->mb.i_neighbour & MB_LEFT) && h->mb.i_mb_type_left != B_SKIP && h->mb.i_mb_type_left != B_DIRECT )
ctx++;
- if( h->mb.i_mb_type_top >= 0 && h->mb.i_mb_type_top != B_SKIP && h->mb.i_mb_type_top != B_DIRECT )
+ if( (h->mb.i_neighbour & MB_TOP) && h->mb.i_mb_type_top != B_SKIP && h->mb.i_mb_type_top != B_DIRECT )
ctx++;
if( i_mb_type == B_DIRECT )
@@ -277,8 +277,8 @@ static void x264_cabac_mb_qp_delta( x264_t *h, x264_cabac_t *cb )
#if !RDO_SKIP_BS
void x264_cabac_mb_skip( x264_t *h, int b_skip )
{
- int ctx = (h->mb.i_mb_type_left >= 0 && !IS_SKIP( h->mb.i_mb_type_left ))
- + (h->mb.i_mb_type_top >= 0 && !IS_SKIP( h->mb.i_mb_type_top ))
+ int ctx = ((h->mb.i_neighbour & MB_LEFT) && !IS_SKIP( h->mb.i_mb_type_left ))
+ + ((h->mb.i_neighbour & MB_TOP) && !IS_SKIP( h->mb.i_mb_type_top ))
+ (h->sh.i_type == SLICE_TYPE_P ? 11 : 24);
x264_cabac_encode_decision( &h->cabac, ctx, b_skip );
}
More information about the x264-devel
mailing list