/* 帧内预测主函数 */
static void x264_mb_analyse_intra( x264_t *h, x264_mb_analysis_t *a, int i_cost_inter )
{
const unsigned int flags = h->sh.i_type == SLICE_TYPE_I ? h->param.analyse.intra :
h->param.analyse.inter;
const int i_stride = h->mb.pic.i_stride[0];
uint8_t *p_src = h->mb.pic.p_fenc[0];
uint8_t *p_dst = h->mb.pic.p_fdec[0];
int
f8_satd_rd_ratio = 0;
int i, idx;
int i_max;
int predict_mode[9];
const int i_satd_thresh = a->i_best_satd * 5/4 + a->i_lambda * 10;
/*---------------- Try all mode and calculate their score ---------------*/
/* 16x16 prediction selection */
/* 16x16亮度 预测 */
predict_16x16_mode_available( h->mb.i_neighbour, predict_mode, &i_max );
for( i = 0; i < i_max; i++ )
{
int i_sad;
int i_mode;
i_mode = predict_mode[i];
h->predict_16x16[i_mode]( p_dst, i_stride );
i_sad = h->pixf.mbcmp[PIXEL_16x16]( p_dst, i_stride, p_src, i_stride ) +
a->i_lambda * bs_size_ue( x264_mb_pred_mode16x16_fix[i_mode] );
if( a->i_sad_i16x16 > i_sad )
{
a->i_predict16x16 = i_mode;
a->i_sad_i16x16
}
}
= i_sad;/* 8x8色度预测 */
if( a->b_mbrd )
{
f8_satd_rd_ratio = ((unsigned)i_cost_inter << 8) / a->i_best_satd + 1;
x264_mb_analyse_intra_chroma( h, a );
if( h->mb.b_chroma_me )
a->i_sad_i16x16 += a->i_sad_i8x8chroma;
if( a->i_sad_i16x16 < i_satd_thresh )
{
h->mb.i_type = I_16x16;
h->mb.i_intra16x16_pred_mode = a->i_predict16x16;
a->i_sad_i16x16 = x264_rd_cost_mb( h, a->i_lambda2 );
}
else
a->i_sad_i16x16 = a->i_sad_i16x16 * f8_satd_rd_ratio >> 8;
}
else
{
if( h->sh.i_type == SLICE_TYPE_B )
/* cavlc mb type prefix */
a->i_sad_i16x16 += a->i_lambda * i_mb_b_cost_table[I_16x16];
if( a->b_fast_intra && a->i_sad_i16x16 > 2*i_cost_inter )
return;
}
/* 4x4 prediction selection */
/* 4x4亮度预测 */
if( flags & X264_ANALYSE_I4x4 )
{
a->i_sad_i4x4 = 0;
for( idx = 0; idx < 16; idx++ )
{
uint8_t *p_src_by;
uint8_t *p_dst_by;
int
i_best;
int x, y;
int i_pred_mode;
i_pred_mode= x264_mb_predict_intra4x4_mode( h, idx );
x = block_idx_x[idx];
y = block_idx_y[idx];
p_src_by = p_src + 4 * x + 4 * y * i_stride;
p_dst_by = p_dst + 4 * x + 4 * y * i_stride;i_best = COST_MAX;
predict_4x4_mode_available( h->mb.i_neighbour4[idx], predict_mode,
&i_max );
for( i = 0; i < i_max; i++ )
{
int i_sad;
int i_mode;
i_mode = predict_mode[i];
h->predict_4x4[i_mode]( p_dst_by, i_stride );
i_sad = h->pixf.mbcmp[PIXEL_4x4]( p_dst_by, i_stride,
p_src_by, i_stride )
+ a->i_lambda * (i_pred_mode ==
x264_mb_pred_mode4x4_fix(i_mode) ? 1 : 4);
if( i_best > i_sad )
{
a->i_predict4x4[x][y] = i_mode;
i_best = i_sad;
}
}
a->i_sad_i4x4 += i_best;
/* we need to encode this block now (for next ones) */
h->predict_4x4[a->i_predict4x4[x][y]]( p_dst_by, i_stride );
/* 计算该最优模式下的比特率 */
x264_mb_encode_i4x4( h, idx, a->i_qp );
h->mb.cache.intra4x4_pred_mode[x264_scan8[idx]] = a->i_predict4x4[x][y];
}
a->i_sad_i4x4 += a->i_lambda * 24;
/* from JVT (SATD0) */
if( a->b_mbrd )
{
if( h->mb.b_chroma_me )
a->i_sad_i4x4 += a->i_sad_i8x8chroma;
if( a->i_sad_i4x4 < i_satd_thresh )
{
h->mb.i_type = I_4x4;
a->i_sad_i4x4 = x264_rd_cost_mb( h, a->i_lambda2 );
}
elsea->i_sad_i4x4 = a->i_sad_i4x4 * f8_satd_rd_ratio >> 8;
}
else
{
if( h->sh.i_type == SLICE_TYPE_B )
a->i_sad_i4x4 += a->i_lambda * i_mb_b_cost_table[I_4x4];
}
}
/* 8x8 prediction selection */
/* 如果有必要,那么进行8x8的亮度预测 */
if( flags & X264_ANALYSE_I8x8 )
{
a->i_sad_i8x8 = 0;
for( idx = 0; idx < 4; idx++ )
{
uint8_t *p_src_by;
uint8_t *p_dst_by;
int
i_best;
int x, y;
int i_pred_mode;
i_pred_mode= x264_mb_predict_intra4x4_mode( h, 4*idx );
x = idx&1;
y = idx>>1;
p_src_by = p_src + 8 * x + 8 * y * i_stride;
p_dst_by = p_dst + 8 * x + 8 * y * i_stride;
i_best = COST_MAX;
predict_4x4_mode_available( h->mb.i_neighbour8[idx], predict_mode,
&i_max );
for( i = 0; i < i_max; i++ )
{
int i_sad;
int i_mode;
i_mode = predict_mode[i];
h->predict_8x8[i_mode]( p_dst_by, i_stride, h->mb.i_neighbour );
/* could use sa8d, but it doesn't seem worth the speed cost (without
mmx at least) */
i_sad = h->pixf.mbcmp[PIXEL_8x8]( p_dst_by, i_stride,
p_src_by, i_stride )+ a->i_lambda * (i_pred_mode ==
x264_mb_pred_mode4x4_fix(i_mode) ? 1 : 4);
if( i_best > i_sad )
{
a->i_predict8x8[x][y] = i_mode;
i_best = i_sad;
}
}
a->i_sad_i8x8 += i_best;
/* we need to encode this block now (for next ones) */
h->predict_8x8[a->i_predict8x8[x][y]]( p_dst_by, i_stride,
h->mb.i_neighbour );
x264_mb_encode_i8x8( h, idx, a->i_qp );
x264_macroblock_cache_intra8x8_pred( h, 2*x, 2*y, a->i_predict8x8[x][y] );
}
if( a->b_mbrd )
{
if( h->mb.b_chroma_me )
a->i_sad_i8x8 += a->i_sad_i8x8chroma;
if( a->i_sad_i8x8 < i_satd_thresh )
{
h->mb.i_type = I_8x8;
a->i_sad_i8x8 = x264_rd_cost_mb( h, a->i_lambda2 );
}
else
a->i_sad_i8x8 = a->i_sad_i8x8 * f8_satd_rd_ratio >> 8;
}
else
{
// FIXME some bias like in i4x4?
if( h->sh.i_type == SLICE_TYPE_B )
a->i_sad_i8x8 += a->i_lambda * i_mb_b_cost_table[I_8x8];
}
}
}
/* 选取 16x16 亮度块,可用的帧内预测模式 */
static void predict_16x16_mode_available( unsigned int i_neighbour, int *mode, int
*pi_count ){
if( i_neighbour & MB_TOPLEFT )
{
/* top and left avaible */
*mode++ = I_PRED_16x16_V;
*mode++ = I_PRED_16x16_H;
*mode++ = I_PRED_16x16_DC;
*mode++ = I_PRED_16x16_P;
*pi_count = 4;
}
else if( i_neighbour & MB_LEFT )
{
/* left available*/
*mode++ = I_PRED_16x16_DC_LEFT;
*mode++ = I_PRED_16x16_H;
*pi_count = 2;
}
else if( i_neighbour & MB_TOP )
{
/* top available*/
*mode++ = I_PRED_16x16_DC_TOP;
*mode++ = I_PRED_16x16_V;
*pi_count = 2;
}
else
{
/* none avaible */
*mode = I_PRED_16x16_DC_128;
*pi_count = 1;
}
}
/* 从附近块中预测出一个模式 pred_mode */
int x264_mb_predict_intra4x4_mode( x264_t *h, int idx )
{
const int ma = h->mb.cache.intra4x4_pred_mode[x264_scan8[idx] - 1];
const int mb = h->mb.cache.intra4x4_pred_mode[x264_scan8[idx] - 8];
const int m = X264_MIN( x264_mb_pred_mode4x4_fix(ma),
x264_mb_pred_mode4x4_fix(mb) );
if( m < 0 )
return I_PRED_4x4_DC;
return m;}
/* 4x4(8x8)亮度块,可用的预测模式 */
static void predict_4x4_mode_available( unsigned int i_neighbour,
int *mode, int *pi_count )
{
/* FIXME even when b_tr == 0 there is some case where missing pixels
* are emulated and thus more mode are available TODO
* analysis and encode should be fixed too */
int b_l = i_neighbour & MB_LEFT;
int b_t = i_neighbour & MB_TOP;
int b_tr = i_neighbour & MB_TOPRIGHT;
if( b_l && b_t )
{
*mode++ = I_PRED_4x4_DC;
*mode++ = I_PRED_4x4_H;
*mode++ = I_PRED_4x4_V;
*mode++ = I_PRED_4x4_DDR;
*mode++ = I_PRED_4x4_VR;
*mode++ = I_PRED_4x4_HD;
*mode++ = I_PRED_4x4_HU;
*pi_count = 7;
}
else if( b_l )
{
*mode++ = I_PRED_4x4_DC_LEFT;
*mode++ = I_PRED_4x4_H;
*mode++ = I_PRED_4x4_HU;
*pi_count = 3;
}
else if( b_t )
{
*mode++ = I_PRED_4x4_DC_TOP;
*mode++ = I_PRED_4x4_V;
*pi_count = 2;
}
else
{
*mode++ = I_PRED_4x4_DC_128;
*pi_count = 1;
}
if( b_t && b_tr ){
*mode++ = I_PRED_4x4_DDL;
*mode++ = I_PRED_4x4_VL;
(*pi_count) += 2;
}
}
/* 编码/计算某个模式的比特率(为了选取最优模式) */
void x264_mb_encode_i4x4( x264_t *h, int idx, int i_qscale )
{
const int i_stride = h->mb.pic.i_stride[0];
const int i_offset = 4 * block_idx_x[idx] + 4 * block_idx_y[idx] * i_stride;
uint8_t *p_src = &h->mb.pic.p_fenc[0][i_offset];
uint8_t *p_dst = &h->mb.pic.p_fdec[0][i_offset];
int16_t dct4x4[4][4];
if( h->mb.b_lossless )
{
sub_zigzag_4x4full( h->dct.block[idx].luma4x4, p_src, p_dst, i_stride );
return;
}
h->dctf.sub4x4_dct( dct4x4, p_src, i_stride, p_dst, i_stride );
quant_4x4( dct4x4, h->quant4_mf[CQM_4IY], i_qscale, 1 );
scan_zigzag_4x4full( h->dct.block[idx].luma4x4, dct4x4 );
x264_mb_dequant_4x4( dct4x4, h->dequant4_mf[CQM_4IY], i_qscale );
/* output samples to fdec */
h->dctf.add4x4_idct( p_dst, i_stride, dct4x4 );
}
/* 16x16 亮度块水平预测 */
static void predict_16x16_h( uint8_t *src, int i_stride )
{
int i,j;
for( i = 0; i < 16; i++ )
{
uint8_t v;
v = src[-1];
for( j = 0; j < 16; j++ )
{src[j] = v;
}
src += i_stride;
}
}