📄 analyse.c
字号:
int *mode, int *pi_count )
{
int b_l = i_neighbour & MB_LEFT;
int b_t = i_neighbour & MB_TOP;
if( b_l && b_t )//
{
*pi_count = 6;
*mode++ = I_PRED_4x4_DC;
*mode++ = I_PRED_4x4_H;
*mode++ = I_PRED_4x4_V;
*mode++ = I_PRED_4x4_DDL;
if( i_neighbour & MB_TOPLEFT )
{
*mode++ = I_PRED_4x4_DDR;
*mode++ = I_PRED_4x4_VR;
*mode++ = I_PRED_4x4_HD;
*pi_count += 3;
}
*mode++ = I_PRED_4x4_VL;
*mode++ = I_PRED_4x4_HU;
}
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;
*mode++ = I_PRED_4x4_DDL;
*mode++ = I_PRED_4x4_VL;
*pi_count = 4;
}
else
{
*mode++ = I_PRED_4x4_DC_128;
*pi_count = 1;
}
}
static void x264_mb_analyse_intra_chroma( x264_t *h, x264_mb_analysis_t *a )
{
int i;
int i_max;
int predict_mode[9];
uint8_t *p_dstc[2], *p_srcc[2];
if( a->i_sad_i8x8chroma < COST_MAX )//已经做过色度预测分析
return;
/* 8x8 prediction selection for chroma */
p_dstc[0] = h->mb.pic.p_fdec[1];
p_dstc[1] = h->mb.pic.p_fdec[2];
p_srcc[0] = h->mb.pic.p_fenc[1];
p_srcc[1] = h->mb.pic.p_fenc[2];
predict_8x8chroma_mode_available( h->mb.i_neighbour, predict_mode, &i_max );
a->i_sad_i8x8chroma = COST_MAX;
for( i = 0; i < i_max; i++ )
{
int i_sad;
int i_mode;
i_mode = predict_mode[i];
/* we do the prediction */
h->predict_8x8c[i_mode]( p_dstc[0] );
h->predict_8x8c[i_mode]( p_dstc[1] );
/* we calculate the cost */
i_sad = h->pixf.mbcmp[PIXEL_8x8]( p_dstc[0], FDEC_STRIDE,
p_srcc[0], FENC_STRIDE ) +
h->pixf.mbcmp[PIXEL_8x8]( p_dstc[1], FDEC_STRIDE,
p_srcc[1], FENC_STRIDE ) +
a->i_lambda * bs_size_ue( x264_mb_pred_mode8x8c_fix[i_mode] );
/* if i_score is lower it is better */
if( a->i_sad_i8x8chroma > i_sad )
{
a->i_predict8x8chroma = i_mode;
a->i_sad_i8x8chroma = i_sad;
}
}
h->mb.i_chroma_pred_mode = a->i_predict8x8chroma;
}
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;
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];
int i_satd_thresh;
/* if( h->sh.i_type == SLICE_TYPE_B )
i_satd_thresh = a->i_best_satd * 9/8;
else*/
i_satd_thresh = a->i_best_satd * 5/4 ;//+ a->i_lambda * 10;
/*---------------- Try all mode and calculate their score ---------------*/
/* 16x16 prediction selection */
predict_16x16_mode_available( h->mb.i_neighbour, predict_mode, &i_max );//根据相邻宏块数据的信息确定可用的16*16帧内预测模式
for( i = 0; i < i_max; i++ )//i_max表示有效模式数组的长度
{
int i_sad;
int i_mode;
i_mode = predict_mode[i];
h->predict_16x16[i_mode]( p_dst );// h->predict_16x16为函数名数组//根据h->mb.pic.p_fdec中的相邻数据用i_mode预测当前
//宏块数据,预测值同样写入h->mb.pic.p_fdec解码重建宏块缓存(相应位置)
i_sad = h->pixf.mbcmp[PIXEL_16x16]( p_dst, FDEC_STRIDE, p_src, FENC_STRIDE );// +
//a->i_lambda * bs_size_ue( x264_mb_pred_mode16x16_fix[i_mode] );//rdo代价计算
if( a->i_sad_i16x16 > i_sad )
{
a->i_predict16x16 = i_mode;//更新当前最佳16*16帧内预测模式和代价
a->i_sad_i16x16 = i_sad;
}
}
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 )//什么物理概念?16*16帧内预测值过大时返回?
return;
}
/* 4x4 prediction selection */
if( flags & X264_ANALYSE_I4x4 )
{
a->i_sad_i4x4 = 0;
for( idx = 0; idx < 16; idx++ )//对16个4*4做
{
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 );//根据邻块预测当前4*4块的可能预测模式,与计算rdo代价有关
x = block_idx_x[idx];//4*4块的宏块内坐标
y = block_idx_y[idx];
p_src_by = p_src + 4 * x + 4 * y * FENC_STRIDE;//确定当前4*4块首像素在宏块缓存中的位置
p_dst_by = p_dst + 4 * x + 4 * y * FDEC_STRIDE;//32,表示宏块解码缓存对一宏块行,存储了32个像素
i_best = COST_MAX;
predict_4x4_mode_available( h->mb.i_neighbour4[idx], predict_mode, &i_max );//确定可用的4*4帧内预测模式
if( (h->mb.i_neighbour4[idx] & (MB_TOPRIGHT|MB_TOP)) == MB_TOP )//上邻4*4有效,右上邻无效时
/* emulate missing topright samples *///右上邻像素值=上邻的最后一像素值*0x01010101(乘这个数字什么概念?)
*(uint32_t*) &p_dst_by[4 - FDEC_STRIDE] = p_dst_by[3 - FDEC_STRIDE] * 0x01010101U;
for( i = 0; i < i_max; i++ )//对每种有效预测模式做,同上面的16*16方式
{
int i_sad;
int i_mode;
i_mode = predict_mode[i];
h->predict_4x4[i_mode]( p_dst_by );// h->predict_16x16为函数名数组//根据h->mb.pic.p_fdec中的相邻数据用i_mode预测当前
//宏块数据,预测值同样写入h->mb.pic.p_fdec宏块解码缓存(相应位置)
i_sad = h->pixf.mbcmp[PIXEL_4x4]( p_dst_by, FDEC_STRIDE,
p_src_by, FENC_STRIDE );
// + a->i_lambda * (i_pred_mode == x264_mb_pred_mode4x4_fix(i_mode) ? 1 : 4);
if( i_best > i_sad )//更新该4*4最小预测代价和最佳预测模式
{
a->i_predict4x4[x][y] = i_mode;
i_best = i_sad;
}
}
a->i_sad_i4x4 += i_best;//累计宏块的各4*4块最小预测代价作为宏块的最小预测代价
//下面在最佳模式下预测当前4*4块,最后更新fdec缓存(因为前面的fdec缓存中预测值是不断刷新的)
/* we need to encode this block now (for next ones) */
h->predict_4x4[a->i_predict4x4[x][y]]( p_dst_by );
x264_mb_encode_i4x4( h, idx, a->i_qp );//求亮度数据的重构值,写回宏块解码缓存fdec[]相应位置
h->mb.cache.intra4x4_pred_mode[x264_scan8[idx]] = a->i_predict4x4[x][y];//最佳模式写入h
}
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 );
}
else
a->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 */
if( flags & X264_ANALYSE_I8x8 )
{
a->i_sad_i8x8 = 0;
for( idx = 0; idx < 4; idx++ )//4个8*8块
{
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 * FENC_STRIDE;
p_dst_by = p_dst + 8 * x + 8 * y * FDEC_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, h->mb.i_neighbour8[idx] );
/* 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, FDEC_STRIDE,
p_src_by, FENC_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, h->mb.i_neighbour8[idx] );
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];
}
}
}
#define LOAD_FENC( m, src, xoff, yoff) \
(m)->i_stride[0] = h->mb.pic.i_stride[0]; \
(m)->i_stride[1] = h->mb.pic.i_stride[1]; \
(m)->p_fenc[0] = &(src)[0][(xoff)+(yoff)*FENC_STRIDE]; \
(m)->p_fenc[1] = &(src)[1][((xoff)>>1)+((yoff)>>1)*FENC_STRIDE]; \
(m)->p_fenc[2] = &(src)[2][((xoff)>>1)+((yoff)>>1)*FENC_STRIDE];
#define LOAD_HPELS(m, src, list, ref, xoff, yoff) \
(m)->p_fref[0] = &(src)[0][(xoff)+(yoff)*(m)->i_stride[0]]; \
(m)->p_fref[1] = &(src)[1][(xoff)+(yoff)*(m)->i_stride[0]]; \
(m)->p_fref[2] = &(src)[2][(xoff)+(yoff)*(m)->i_stride[0]]; \
(m)->p_fref[3] = &(src)[3][(xoff)+(yoff)*(m)->i_stride[0]]; \
(m)->p_fref[4] = &(src)[4][((xoff)>>1)+((yoff)>>1)*(m)->i_stride[1]]; \
(m)->p_fref[5] = &(src)[5][((xoff)>>1)+((yoff)>>1)*(m)->i_stride[1]]; \
(m)->integral = &h->mb.pic.p_integral[list][ref][(xoff)+(yoff)*(m)->i_stride[0]];
#define REF_COST(list, ref) \
(a->i_lambda * bs_size_te( h->sh.i_num_ref_idx_l##list##_active - 1, ref ))
static void x264_mb_analyse_inter_p16x16( x264_t *h, x264_mb_analysis_t *a )
{
x264_me_t m;
int i_ref;
int mvc[7][2], i_mvc;
int i_halfpel_thresh = INT_MAX;
int *p_halfpel_thresh = h->i_ref0>1 ? &i_halfpel_thresh : NULL;
/* 16x16 Search on all ref frame */
m.i_pixel = PIXEL_16x16;
m.p_cost_mv = a->p_cost_mv;
LOAD_FENC( &m, h->mb.pic.p_fenc, 0, 0 );//将待编码宏块数据从宏块缓存拷贝到运动估计结构体m->p_fenc[0],[1],[2]
a->l0.me16x16.cost = INT_MAX;
for( i_ref = 0; i_ref < h->i_ref0; i_ref++ )
{
const int i_ref_cost = REF_COST( 0, i_ref );//参考帧远近距离代价
i_halfpel_thresh -= i_ref_cost;
m.i_ref_cost = i_ref_cost;
m.i_ref = i_ref;
/* search with ref */
LOAD_HPELS( &m, h->mb.pic.p_fref[0][i_ref], 0, i_ref, 0, 0 );//从参考帧中读入y,u,v数据到m.p_fref[6],其实是指针赋值
x264_mb_predict_mv_16x16( h, 0, i_ref, m.mvp );//根据邻块信息计算当前宏块的预测矢量mvp
x264_mb_predict_mv_ref16x16( h, 0, i_ref, mvc, &i_mvc );//相邻宏块,参考帧中同空间位置的块运动矢量等信息写mvc[],即可能的预测矢量
x264_me_search_ref( h, &m, mvc, i_mvc, p_halfpel_thresh );//寻找确定搜索中心,然后搜索最佳整像素,半像素和1/4像素点,将最佳矢量和代价信息写入m
/* early termination
* SSD threshold would probably be better than SATD */
if( i_ref == 0 && a->b_try_pskip && m.cost-m.cost_mv < 300*a->i_lambda )
{
int mvskip[2];
x264_mb_predict_mv_pskip( h, mvskip );
if( abs(m.mv[0]-mvskip[0]) + abs(m.mv[1]-mvskip[1]) <= 1
&& x264_macroblock_probe_pskip( h ) )
{
h->mb.i_type = P_SKIP;
x264_analyse_update_cache( h, a );//Update MB from the analysis 根据分析结果,填写宏块解码相关二维表格信息
return;
}
}
m.cost += i_ref_cost;
i_halfpel_thresh += i_ref_cost;
if( m.cost < a->l0.me16x16.cost )//更新P16*16模式最佳代价
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -