[x264-devel] Eliminate the possibility of CAVLC level code overflow
Jason Garrett-Glaser
git at videolan.org
Thu Mar 24 06:38:36 CET 2011
x264 | branch: master | Jason Garrett-Glaser <jason at x264.com> | Fri Mar 18 18:24:33 2011 -0700| [08d04a4d30b452faed3b763528611737d994b30b] | committer: Jason Garrett-Glaser
Eliminate the possibility of CAVLC level code overflow
Instead, if it happens, just re-encode the MB at higher QPs until it fits.
> http://git.videolan.org/gitweb.cgi/x264.git/?a=commit;h=08d04a4d30b452faed3b763528611737d994b30b
---
common/common.h | 1 +
common/set.c | 4 ++++
encoder/cavlc.c | 5 ++---
encoder/encoder.c | 17 ++++++++++++++++-
4 files changed, 23 insertions(+), 4 deletions(-)
diff --git a/common/common.h b/common/common.h
index 868f526..f2021b6 100644
--- a/common/common.h
+++ b/common/common.h
@@ -645,6 +645,7 @@ struct x264_t
int b_reencode_mb;
int ip_offset; /* Used by PIR to offset the quantizer of intra-refresh blocks. */
int b_deblock_rdo;
+ int b_overflow; /* If CAVLC had a level code overflow during bitstream writing. */
struct
{
diff --git a/common/set.c b/common/set.c
index 3690ed6..f8f6a11 100644
--- a/common/set.c
+++ b/common/set.c
@@ -236,6 +236,10 @@ int x264_cqm_init( x264_t *h )
h->param.rc.i_qp_max = min_qp_err-1;
if( max_qp_err >= h->param.rc.i_qp_min )
h->param.rc.i_qp_min = max_qp_err+1;
+ /* If long level-codes aren't allowed, we need to allow QP high enough to avoid them. */
+ if( !h->param.b_cabac && h->sps->i_profile_idc < PROFILE_HIGH )
+ while( h->chroma_qp_table[SPEC_QP(h->param.rc.i_qp_max)] <= 12 || h->param.rc.i_qp_max <= 12 )
+ h->param.rc.i_qp_max++;
if( h->param.rc.i_qp_min > h->param.rc.i_qp_max )
{
x264_log( h, X264_LOG_ERROR, "Impossible QP constraints for CQM (min=%d, max=%d)\n", h->param.rc.i_qp_min, h->param.rc.i_qp_max );
diff --git a/encoder/cavlc.c b/encoder/cavlc.c
index 720cd18..278b9a1 100644
--- a/encoder/cavlc.c
+++ b/encoder/cavlc.c
@@ -100,9 +100,8 @@ static inline int block_residual_write_cavlc_escape( x264_t *h, int i_suffix_len
/* Weight highly against overflows. */
s->i_bits_encoded += 2000;
#else
- x264_log(h, X264_LOG_WARNING, "OVERFLOW levelcode=%d is only allowed in High Profile\n", i_level_code );
- /* clip level, preserving sign */
- i_level_code = (1<<12) - 2 + (i_level_code & 1);
+ /* We've had an overflow; note it down and re-encode the MB later. */
+ h->mb.b_overflow = 1;
#endif
}
}
diff --git a/encoder/encoder.c b/encoder/encoder.c
index b4dde0b..d42ca31 100644
--- a/encoder/encoder.c
+++ b/encoder/encoder.c
@@ -1883,6 +1883,7 @@ static int x264_slice_write( x264_t *h )
* other inaccuracies. */
int overhead_guess = (NALU_OVERHEAD - (h->param.b_annexb && h->out.i_nal)) + 1 + h->param.b_cabac + 5;
int slice_max_size = h->param.i_slice_max_size > 0 ? (h->param.i_slice_max_size-overhead_guess)*8 : 0;
+ int back_up_bitstream = slice_max_size || (!h->param.b_cabac && h->sps->i_profile_idc < PROFILE_HIGH);
int starting_bits = bs_pos(&h->out.bs);
int b_deblock = h->sh.i_disable_deblocking_filter_idc != 1;
int b_hpel = h->fdec->b_kept_as_ref;
@@ -1933,7 +1934,7 @@ static int x264_slice_write( x264_t *h )
if( x264_bitstream_check_buffer( h ) )
return -1;
- if( slice_max_size )
+ if( back_up_bitstream )
{
mv_bits_bak = h->stat.frame.i_mv_bits;
tex_bits_bak = h->stat.frame.i_tex_bits;
@@ -1963,6 +1964,7 @@ static int x264_slice_write( x264_t *h )
x264_macroblock_analyse( h );
/* encode this macroblock -> be careful it can change the mb type to P_SKIP if needed */
+reencode:
x264_macroblock_encode( h );
if( h->param.b_cabac )
@@ -1991,6 +1993,19 @@ static int x264_slice_write( x264_t *h )
i_skip = 0;
}
x264_macroblock_write_cavlc( h );
+ /* If there was a CAVLC level code overflow, try again at a higher QP. */
+ if( h->mb.b_overflow )
+ {
+ h->mb.i_chroma_qp = h->chroma_qp_table[++h->mb.i_qp];
+ h->mb.i_skip_intra = 0;
+ h->mb.b_skip_mc = 0;
+ h->mb.b_overflow = 0;
+ h->out.bs = bs_bak;
+ i_skip = i_skip_bak;
+ h->stat.frame.i_mv_bits = mv_bits_bak;
+ h->stat.frame.i_tex_bits = tex_bits_bak;
+ goto reencode;
+ }
}
}
More information about the x264-devel
mailing list