Commit 94a4aede authored by Loren Merritt's avatar Loren Merritt

rd refinement of intra chroma direction (enabled in --subme 7)

patch by Alex Wright.


git-svn-id: svn://svn.videolan.org/x264/trunk@595 df754926-b1dd-0310-bc7b-ec298dee348c
parent e7a4aba9
......@@ -290,9 +290,6 @@ int x264_mb_predict_non_zero_code( x264_t *h, int idx );
* doesn't check for intra or cbp */
int x264_mb_transform_8x8_allowed( x264_t *h );
void x264_mb_encode_i4x4( x264_t *h, int idx, int i_qscale );
void x264_mb_encode_i8x8( x264_t *h, int idx, int i_qscale );
void x264_mb_mc( x264_t *h );
void x264_mb_mc_8x8( x264_t *h, int i8 );
......
......@@ -98,6 +98,7 @@ typedef struct
/* Chroma part */
int i_satd_i8x8chroma;
int i_satd_i8x8chroma_dir[4];
int i_predict8x8chroma;
/* II: Inter part P/B frame */
......@@ -456,6 +457,8 @@ static void x264_mb_analyse_intra_chroma( x264_t *h, x264_mb_analysis_t *a )
int i_mode = predict_mode[i];
int i_satd = satdu[i_mode] + satdv[i_mode]
+ a->i_lambda * bs_size_ue(i_mode);
a->i_satd_i8x8chroma_dir[i] = i_satd;
COPY2_IF_LT( a->i_satd_i8x8chroma, i_satd, a->i_predict8x8chroma, i_mode );
}
}
......@@ -477,6 +480,7 @@ static void x264_mb_analyse_intra_chroma( x264_t *h, x264_mb_analysis_t *a )
p_srcc[1], FENC_STRIDE ) +
a->i_lambda * bs_size_ue( x264_mb_pred_mode8x8c_fix[i_mode] );
a->i_satd_i8x8chroma_dir[i] = i_satd;
COPY2_IF_LT( a->i_satd_i8x8chroma, i_satd, a->i_predict8x8chroma, i_mode );
}
}
......@@ -718,15 +722,15 @@ static void x264_intra_rd_refine( x264_t *h, x264_mb_analysis_t *a )
uint8_t *p_src = h->mb.pic.p_fenc[0];
uint8_t *p_dst = h->mb.pic.p_fdec[0];
int i, idx, x, y;
int i_max, i_satd, i_best, i_mode;
int i, j, idx, x, y;
int i_max, i_satd, i_best, i_mode, i_thresh;
int i_pred_mode;
int predict_mode[9];
if( h->mb.i_type == I_16x16 )
{
int old_pred_mode = a->i_predict16x16;
int i_thresh = a->i_satd_i16x16_dir[old_pred_mode] * 9/8;
i_thresh = a->i_satd_i16x16_dir[old_pred_mode] * 9/8;
i_best = a->i_satd_i16x16;
predict_16x16_mode_available( h->mb.i_neighbour, predict_mode, &i_max );
for( i = 0; i < i_max; i++ )
......@@ -799,7 +803,7 @@ static void x264_intra_rd_refine( x264_t *h, x264_mb_analysis_t *a )
uint8_t *p_src_by;
uint8_t *p_dst_by;
int j;
int i_thresh = a->i_satd_i8x8_dir[a->i_predict8x8[idx]][idx] * 11/8;
i_thresh = a->i_satd_i8x8_dir[a->i_predict8x8[idx]][idx] * 11/8;
i_best = COST_MAX;
i_pred_mode = x264_mb_predict_intra4x4_mode( h, 4*idx );
......@@ -843,6 +847,43 @@ static void x264_intra_rd_refine( x264_t *h, x264_mb_analysis_t *a )
x264_macroblock_cache_intra8x8_pred( h, 2*x, 2*y, a->i_predict8x8[idx] );
}
}
/* RD selection for chroma prediction */
predict_8x8chroma_mode_available( h->mb.i_neighbour, predict_mode, &i_max );
if( i_max > 1 )
{
i_thresh = a->i_satd_i8x8chroma * 5/4;
for( i = j = 0; i < i_max; i++ )
if( a->i_satd_i8x8chroma_dir[i] < i_thresh &&
predict_mode[i] != a->i_predict8x8chroma )
{
predict_mode[j++] = predict_mode[i];
}
i_max = j;
if( i_max > 0 )
{
int i_qp_chroma = i_chroma_qp_table[x264_clip3( h->mb.i_qp + h->pps->i_chroma_qp_index_offset, 0, 51 )];
int i_chroma_lambda = i_qp0_cost2_table[i_qp_chroma];
/* the previous thing encoded was x264_intra_rd(), so the pixels and
* coefs for the current chroma mode are still around, so we only
* have to recount the bits. */
i_best = x264_rd_cost_i8x8_chroma( h, i_chroma_lambda, a->i_predict8x8chroma, 0 );
for( i = 0; i < i_max; i++ )
{
i_mode = predict_mode[i];
h->predict_8x8c[i_mode]( h->mb.pic.p_fdec[1] );
h->predict_8x8c[i_mode]( h->mb.pic.p_fdec[2] );
/* if we've already found a mode that needs no residual, then
* probably any mode with a residual will be worse.
* so avoid dct on the remaining modes to improve speed. */
i_satd = x264_rd_cost_i8x8_chroma( h, i_chroma_lambda, i_mode, h->mb.i_cbp_chroma != 0x00 );
COPY2_IF_LT( i_best, i_satd, a->i_predict8x8chroma, i_mode );
}
h->mb.i_chroma_pred_mode = a->i_predict8x8chroma;
}
}
}
#define LOAD_FENC( m, src, xoff, yoff) \
......
......@@ -1144,4 +1144,21 @@ static void x264_partition_i4x4_size_cabac( x264_t *h, x264_cabac_t *cb, int i4,
x264_cabac_mb_intra4x4_pred_mode( cb, i_pred, i_mode );
block_residual_write_cabac( h, cb, DCT_LUMA_4x4, i4, h->dct.block[i4].luma4x4, 16 );
}
static void x264_i8x8_chroma_size_cabac( x264_t *h, x264_cabac_t *cb )
{
x264_cabac_mb_intra_chroma_pred_mode( h, cb );
if( h->mb.i_cbp_chroma > 0 )
{
block_residual_write_cabac( h, cb, DCT_CHROMA_DC, 0, h->dct.chroma_dc[0], 4 );
block_residual_write_cabac( h, cb, DCT_CHROMA_DC, 1, h->dct.chroma_dc[1], 4 );
if( h->mb.i_cbp_chroma == 2 )
{
int i;
for( i = 0; i < 8; i++ )
block_residual_write_cabac( h, cb, DCT_CHROMA_AC, i, h->dct.block[16+i].residual_ac, 15 );
}
}
}
#endif
......@@ -801,4 +801,22 @@ static int x264_partition_i4x4_size_cavlc( x264_t *h, int i4, int i_mode )
block_residual_write_cavlc( h, &h->out.bs, i4, h->dct.block[i4].luma4x4, 16 );
return h->out.bs.i_bits_encoded;
}
static int x264_i8x8_chroma_size_cavlc( x264_t *h )
{
h->out.bs.i_bits_encoded = bs_size_ue( x264_mb_pred_mode8x8c_fix[ h->mb.i_chroma_pred_mode ] );
if( h->mb.i_cbp_chroma != 0 )
{
block_residual_write_cavlc( h, &h->out.bs, BLOCK_INDEX_CHROMA_DC, h->dct.chroma_dc[0], 4 );
block_residual_write_cavlc( h, &h->out.bs, BLOCK_INDEX_CHROMA_DC, h->dct.chroma_dc[1], 4 );
if( h->mb.i_cbp_chroma == 2 )
{
int i;
for( i = 0; i < 8; i++ )
block_residual_write_cavlc( h, &h->out.bs, 16 + i, h->dct.block[16+i].residual_ac, 15 );
}
}
return h->out.bs.i_bits_encoded;
}
#endif
......@@ -242,7 +242,7 @@ static void x264_mb_encode_i16x16( x264_t *h, int i_qscale )
h->dctf.add16x16_idct( p_dst, &dct4x4[1] );
}
static void x264_mb_encode_8x8_chroma( x264_t *h, int b_inter, int i_qscale )
void x264_mb_encode_8x8_chroma( x264_t *h, int b_inter, int i_qscale )
{
int i, ch;
int b_decimate = b_inter && (h->sh.i_type == SLICE_TYPE_B || h->param.analyse.b_dct_decimate);
......@@ -312,6 +312,19 @@ static void x264_mb_encode_8x8_chroma( x264_t *h, int b_inter, int i_qscale )
dct4x4[i][0][0] = dct2x2[0][i];
h->dctf.add8x8_idct( p_dst, dct4x4 );
}
/* coded block pattern */
h->mb.i_cbp_chroma = 0;
for( i = 0; i < 8; i++ )
{
int nz = array_non_zero_count( h->dct.block[16+i].residual_ac, 15 );
h->mb.cache.non_zero_count[x264_scan8[16+i]] = nz;
h->mb.i_cbp_chroma |= nz;
}
if( h->mb.i_cbp_chroma )
h->mb.i_cbp_chroma = 2; /* dc+ac (we can't do only ac) */
else if( array_non_zero( h->dct.chroma_dc[0], 8 ) )
h->mb.i_cbp_chroma = 1; /* dc only */
}
static void x264_macroblock_encode_skip( x264_t *h )
......@@ -569,7 +582,7 @@ void x264_macroblock_encode( x264_t *h )
/* encode the 8x8 blocks */
x264_mb_encode_8x8_chroma( h, !IS_INTRA( h->mb.i_type ), i_qp );
/* Calculate the Luma/Chroma pattern and non_zero_count */
/* coded block pattern and non_zero_count */
h->mb.i_cbp_luma = 0x00;
if( h->mb.i_type == I_16x16 )
{
......@@ -606,22 +619,6 @@ void x264_macroblock_encode( x264_t *h )
}
}
/* Calculate the chroma pattern */
h->mb.i_cbp_chroma = 0x00;
for( i = 0; i < 8; i++ )
{
const int nz = array_non_zero_count( h->dct.block[16+i].residual_ac, 15 );
h->mb.cache.non_zero_count[x264_scan8[16+i]] = nz;
if( nz > 0 )
{
h->mb.i_cbp_chroma = 0x02; /* dc+ac (we can't do only ac) */
}
}
if( h->mb.i_cbp_chroma == 0x00 && array_non_zero( h->dct.chroma_dc[0], 8 ) )
{
h->mb.i_cbp_chroma = 0x01; /* dc only */
}
if( h->param.b_cabac )
{
i_cbp_dc = ( h->mb.i_type == I_16x16 && array_non_zero( h->dct.luma16x16_dc, 16 ) )
......
......@@ -40,6 +40,9 @@ void x264_macroblock_write_cabac ( x264_t *h, x264_cabac_t *cb );
void x264_macroblock_write_cavlc ( x264_t *h, bs_t *s );
void x264_macroblock_encode_p8x8( x264_t *h, int i8 );
void x264_mb_encode_i4x4( x264_t *h, int idx, int i_qscale );
void x264_mb_encode_i8x8( x264_t *h, int idx, int i_qscale );
void x264_mb_encode_8x8_chroma( x264_t *h, int b_inter, int i_qscale );
void x264_cabac_mb_skip( x264_t *h, int b_skip );
......
......@@ -178,6 +178,31 @@ int x264_rd_cost_i4x4( x264_t *h, int i_lambda2, int i4, int i_mode )
return i_ssd + i_bits;
}
int x264_rd_cost_i8x8_chroma( x264_t *h, int i_lambda2, int i_mode, int b_dct )
{
int i_ssd, i_bits;
if( b_dct )
x264_mb_encode_8x8_chroma( h, 0, h->mb.i_qp );
i_ssd = ssd_plane( h, PIXEL_8x8, 1, 0, 0 ) +
ssd_plane( h, PIXEL_8x8, 2, 0, 0 );
h->mb.i_chroma_pred_mode = i_mode;
if( h->param.b_cabac )
{
x264_cabac_t cabac_tmp = h->cabac;
cabac_tmp.f8_bits_encoded = 0;
x264_i8x8_chroma_size_cabac( h, &cabac_tmp );
i_bits = ( cabac_tmp.f8_bits_encoded * i_lambda2 + 128 ) >> 8;
}
else
{
i_bits = x264_i8x8_chroma_size_cavlc( h ) * i_lambda2;
}
return i_ssd + i_bits;
}
/****************************************************************************
* Trellis RD quantization
****************************************************************************/
......
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