[x264-devel] commit: Optimize rounding of luma and chroma DC coefficients ( Jason Garrett-Glaser )
git version control
git at videolan.org
Mon Sep 14 22:00:02 CEST 2009
x264 | branch: master | Jason Garrett-Glaser <darkshikari at gmail.com> | Thu Sep 10 02:55:21 2009 -0700| [411ee507328890fb1fde96b37b6eef854d27101a] | committer: Jason Garrett-Glaser
Optimize rounding of luma and chroma DC coefficients
Reduce bitrate mostly-losslessly at low quantizers.
In some rare cases, bitrate reduction may be as high as 10%.
Luma rounding optimization (helps much less than chroma) requires trellis.
> http://git.videolan.org/gitweb.cgi/x264.git/?a=commit;h=411ee507328890fb1fde96b37b6eef854d27101a
---
encoder/macroblock.c | 80 +++++++++++++++++++++++++++++++++++++++++++++----
encoder/rdo.c | 9 +++++-
2 files changed, 81 insertions(+), 8 deletions(-)
diff --git a/encoder/macroblock.c b/encoder/macroblock.c
index a8d8023..db32ad2 100644
--- a/encoder/macroblock.c
+++ b/encoder/macroblock.c
@@ -59,13 +59,13 @@ static inline void idct_dequant_2x2_dc( int16_t dct[2][2], int16_t dct4x4[4][4][
dct4x4[3][0][0] = (d2 - d3) * dmf >> -qbits;
}
-static inline void idct_dequant_2x2_dconly( int16_t dct[2][2], int dequant_mf[6][4][4], int i_qp )
+static inline void idct_dequant_2x2_dconly( int16_t out[2][2], int16_t dct[2][2], int dequant_mf[6][4][4], int i_qp )
{
IDCT_DEQUANT_START
- dct[0][0] = (d0 + d1) * dmf >> -qbits;
- dct[0][1] = (d0 - d1) * dmf >> -qbits;
- dct[1][0] = (d2 + d3) * dmf >> -qbits;
- dct[1][1] = (d2 - d3) * dmf >> -qbits;
+ out[0][0] = (d0 + d1) * dmf >> -qbits;
+ out[0][1] = (d0 - d1) * dmf >> -qbits;
+ out[1][0] = (d2 + d3) * dmf >> -qbits;
+ out[1][1] = (d2 - d3) * dmf >> -qbits;
}
static inline void dct2x2dc( int16_t d[2][2], int16_t dct4x4[4][4][4] )
@@ -276,6 +276,64 @@ static void x264_mb_encode_i16x16( x264_t *h, int i_qp )
h->dctf.add16x16_idct_dc( p_dst, dct_dc4x4 );
}
+static inline int idct_dequant_round_2x2_dc( int16_t ref[2][2], int16_t dct[2][2], int dequant_mf[6][4][4], int i_qp )
+{
+ int16_t out[2][2];
+ idct_dequant_2x2_dconly( out, dct, dequant_mf, i_qp );
+ return ((ref[0][0] ^ (out[0][0]+32))
+ | (ref[0][1] ^ (out[0][1]+32))
+ | (ref[1][0] ^ (out[1][0]+32))
+ | (ref[1][1] ^ (out[1][1]+32))) >> 6;
+}
+
+/* Round down coefficients losslessly in DC-only chroma blocks.
+ * Unlike luma blocks, this can't be done with a lookup table or
+ * other shortcut technique because of the interdependencies
+ * between the coefficients due to the chroma DC transform. */
+static inline int x264_mb_optimize_chroma_dc( x264_t *h, int b_inter, int i_qp, int16_t dct2x2[2][2] )
+{
+ int16_t dct2x2_orig[2][2];
+ int coeff;
+ int nz = 0;
+
+ /* If the QP is too high, there's no benefit to rounding optimization. */
+ if( h->dequant4_mf[CQM_4IC + b_inter][i_qp%6][0][0] << (i_qp/6) > 32*64 )
+ return 1;
+
+ idct_dequant_2x2_dconly( dct2x2_orig, dct2x2, h->dequant4_mf[CQM_4IC + b_inter], i_qp );
+ dct2x2_orig[0][0] += 32;
+ dct2x2_orig[0][1] += 32;
+ dct2x2_orig[1][0] += 32;
+ dct2x2_orig[1][1] += 32;
+
+ /* If the DC coefficients already round to zero, terminate early. */
+ if( !((dct2x2_orig[0][0]|dct2x2_orig[0][1]|dct2x2_orig[1][0]|dct2x2_orig[1][1])>>6) )
+ return 0;
+
+ /* Start with the highest frequency coefficient... is this the best option? */
+ for( coeff = 3; coeff >= 0; coeff-- )
+ {
+ int sign = dct2x2[0][coeff] < 0 ? -1 : 1;
+ int level = dct2x2[0][coeff];
+
+ if( !level )
+ continue;
+
+ while( level )
+ {
+ dct2x2[0][coeff] = level - sign;
+ if( idct_dequant_round_2x2_dc( dct2x2_orig, dct2x2, h->dequant4_mf[CQM_4IC + b_inter], i_qp ) )
+ break;
+ level -= sign;
+ }
+
+ nz |= level;
+ dct2x2[0][coeff] = level;
+ }
+
+ return !!nz;
+}
+
void x264_mb_encode_8x8_chroma( x264_t *h, int b_inter, int i_qp )
{
int i, ch, nz, nz_dc;
@@ -315,11 +373,14 @@ void x264_mb_encode_8x8_chroma( x264_t *h, int b_inter, int i_qp )
else
nz_dc = h->quantf.quant_2x2_dc( dct2x2, h->quant4_mf[CQM_4IC+b_inter][i_qp][0]>>1, h->quant4_bias[CQM_4IC+b_inter][i_qp][0]<<
1 );
+
if( nz_dc )
{
+ if( !x264_mb_optimize_chroma_dc( h, b_inter, i_qp, dct2x2 ) )
+ continue;
h->mb.cache.non_zero_count[x264_scan8[25]+ch] = 1;
zigzag_scan_2x2_dc( h->dct.chroma_dc[ch], dct2x2 );
- idct_dequant_2x2_dconly( dct2x2, h->dequant4_mf[CQM_4IC + b_inter], i_qp );
+ idct_dequant_2x2_dconly( dct2x2, dct2x2, h->dequant4_mf[CQM_4IC + b_inter], i_qp );
h->dctf.add8x8_idct_dc( h->mb.pic.p_fdec[1+ch], dct2x2 );
h->mb.i_cbp_chroma = 1;
}
@@ -388,9 +449,14 @@ void x264_mb_encode_8x8_chroma( x264_t *h, int b_inter, int i_qp )
h->mb.cache.non_zero_count[x264_scan8[16+3]+24*ch] = 0;
if( !nz_dc ) /* Whole block is empty */
continue;
+ if( !x264_mb_optimize_chroma_dc( h, b_inter, i_qp, dct2x2 ) )
+ {
+ h->mb.cache.non_zero_count[x264_scan8[25]+ch] = 0;
+ continue;
+ }
/* DC-only */
zigzag_scan_2x2_dc( h->dct.chroma_dc[ch], dct2x2 );
- idct_dequant_2x2_dconly( dct2x2, h->dequant4_mf[CQM_4IC + b_inter], i_qp );
+ idct_dequant_2x2_dconly( dct2x2, dct2x2, h->dequant4_mf[CQM_4IC + b_inter], i_qp );
h->dctf.add8x8_idct_dc( p_dst, dct2x2 );
}
else
diff --git a/encoder/rdo.c b/encoder/rdo.c
index 4bbb63f..4041a5e 100644
--- a/encoder/rdo.c
+++ b/encoder/rdo.c
@@ -560,7 +560,14 @@ static ALWAYS_INLINE int quant_trellis_cabac( x264_t *h, int16_t *dct,
n.score += (uint64_t)f8_bits * i_lambda2 >> ( CABAC_SIZE_BITS - LAMBDA_BITS );
}
- n.score += ssd;
+ if( j || i || dc )
+ n.score += ssd;
+ /* Optimize rounding for DC coefficients in DC-only luma 4x4/8x8 blocks. */
+ else
+ {
+ d = i_coef * signs[0] - ((unquant_abs_level * signs[0] + 8)&~15);
+ n.score += (int64_t)d*d * coef_weight[i];
+ }
/* save the node if it's better than any existing node with the same cabac ctx */
if( n.score < nodes_cur[node_ctx].score )
More information about the x264-devel
mailing list