x264 - x264_slicetype_frame_cost
来源:互联网 发布:淘宝金币不够用怎么办 编辑:程序博客网 时间:2024/06/10 03:03
static int x264_slicetype_frame_cost( x264_t *h, x264_mb_analysis_t *a,
x264_frame_t **frames, int p0, int p1, int b,
int b_intra_penalty )
{
int i_score = 0;
int do_search[2];
const x264_weight_t *w = x264_weight_none;
// 索引b, 表示待编码的帧
x264_frame_t *fenc = frames[b];
/* Check whether we already evaluated this frame
* If we have tried this frame as P, then we have also tried
* the preceding frames as B. (is this still true?) */
/* Also check that we already calculated the row SATDs for the current frame. */
// fenc->i_cost_est[][]
// 第一维表示前向参考距, 第二维表示后向参考距
if( fenc->i_cost_est[b-p0][p1-b] >= 0 && (!h->param.rc.i_vbv_buffer_size || fenc->i_row_satds[b-p0][p1-b][0] != -1) )
i_score = fenc->i_cost_est[b-p0][p1-b];
else
{
int dist_scale_factor = 128;
/* For each list, check to see whether we have lowres motion-searched this reference frame before. */
// 不做I帧编码, 可能按P帧编码
do_search[0] = b != p0 && fenc->lowres_mvs[0][b-p0-1][0][0] == 0x7FFF;
// 作B帧编码
do_search[1] = b != p1 && fenc->lowres_mvs[1][p1-b-1][0][0] == 0x7FFF;
if( do_search[0] )
{
if( h->param.analyse.i_weighted_pred && b == p1 )
{
// b == p1 表示作为P帧来编码
x264_emms();
// 计算编码帧平面的权重,
// fenc是待编码的帧,frames[p0]是前向参考帧
x264_weights_analyse( h, fenc, frames[p0], 1 );
// 获得待编码帧Y平面的权重
w = fenc->weight[0];
}
// b != p0, 按P帧编码
// b - p0 - 1 表示前向参考距
fenc->lowres_mvs[0][b-p0-1][0][0] = 0;
}
// if do_search[1], 按B帧编码
// p1 - b - 1 表示后向参考距
if( do_search[1] ) fenc->lowres_mvs[1][p1-b-1][0][0] = 0;
if( p1 != p0 ) // 待编帧不作为I帧来编码
dist_scale_factor = ( ((b-p0) << 8) + ((p1-p0) >> 1) ) / (p1-p0);
// #define PAD_SIZE 32
// /* cost_est, cost_est_aq, intra_mbs, num rows */
// #define NUM_INTS 4
// #define COST_EST 0
// #define COST_EST_AQ 1
// #define INTRA_MBS 2
// #define NUM_ROWS 3
// #define ROW_SATD (NUM_INTS + (h->mb.i_mb_y - h->i_threadslice_start))
int output_buf_size = h->mb.i_mb_height + (NUM_INTS + PAD_SIZE) * h->param.i_lookahead_threads;
// int *output_inter[17]
// int *output_intra[17]
int *output_inter[X264_LOOKAHEAD_THREAD_MAX+1];
int *output_intra[X264_LOOKAHEAD_THREAD_MAX+1];
// in macroblock.c
// int buf_lookahead_threads = (h->mb.i_mb_height + (4 + 32) * h->param.i_lookahead_threads) * sizeof(int) * 2;
// CHECKED_MALLOC( h->scratch_buffer2, buf_lookahead_threads );
// 从上述malloc代码, 得知 h->scratch_buffer2 分配了2倍的一块内存
// 一块赋予output_inter[0], 一块赋予output_intra[0]
// 每一块将被分为4段,分别保存cost_est, cost_est_aq, intra_mbs, num_rows
output_inter[0] = h->scratch_buffer2;
output_intra[0] = output_inter[0] + output_buf_size;
#if HAVE_OPENCL
if( h->param.b_opencl )
{
x264_opencl_lowres_init(h, fenc, a->i_lambda );
if( do_search[0] )
{
x264_opencl_lowres_init( h, frames[p0], a->i_lambda );
x264_opencl_motionsearch( h, frames, b, p0, 0, a->i_lambda, w );
}
if( do_search[1] )
{
x264_opencl_lowres_init( h, frames[p1], a->i_lambda );
x264_opencl_motionsearch( h, frames, b, p1, 1, a->i_lambda, NULL );
}
if( b != p0 )
x264_opencl_finalize_cost( h, a->i_lambda, frames, p0, p1, b, dist_scale_factor );
x264_opencl_flush( h );
i_score = fenc->i_cost_est[b-p0][p1-b];
}
else
#endif
{
if( h->param.i_lookahead_threads > 1 )
{
x264_slicetype_slice_t s[X264_LOOKAHEAD_THREAD_MAX];
for( int i = 0; i < h->param.i_lookahead_threads; i++ )
{
x264_t *t = h->lookahead_thread[i];
/* FIXME move this somewhere else */
t->mb.i_me_method = h->mb.i_me_method;
t->mb.i_subpel_refine = h->mb.i_subpel_refine;
t->mb.b_chroma_me = h->mb.b_chroma_me;
s[i] = (x264_slicetype_slice_t){ t, a, frames, p0, p1, b, dist_scale_factor, do_search, w,
output_inter[i], output_intra[i] };
t->i_threadslice_start = ((h->mb.i_mb_height * i + h->param.i_lookahead_threads/2) / h->param.i_lookahead_threads);
t->i_threadslice_end = ((h->mb.i_mb_height * (i+1) + h->param.i_lookahead_threads/2) / h->param.i_lookahead_threads);
int thread_height = t->i_threadslice_end - t->i_threadslice_start;
int thread_output_size = thread_height + NUM_INTS;
// 初始化输出缓冲区
memset( output_inter[i], 0, thread_output_size * sizeof(int) );
memset( output_intra[i], 0, thread_output_size * sizeof(int) );
output_inter[i][NUM_ROWS] = output_intra[i][NUM_ROWS] = thread_height;
output_inter[i+1] = output_inter[i] + thread_output_size + PAD_SIZE;
output_intra[i+1] = output_intra[i] + thread_output_size + PAD_SIZE;
x264_threadpool_run( h->lookaheadpool, (void*)x264_slicetype_slice_cost, &s[i] );
}
for( int i = 0; i < h->param.i_lookahead_threads; i++ )
x264_threadpool_wait( h->lookaheadpool, &s[i] );
}
else
{
// 一行为一个slice
// 因此 threadslice_start = 0, threadslice_end = i_mb.height
h->i_threadslice_start = 0;
h->i_threadslice_end = h->mb.i_mb_height;
// 将output_inter[0], output_intra[0]的除padding外部分都初始为0
memset( output_inter[0], 0, (output_buf_size - PAD_SIZE) * sizeof(int) );
memset( output_intra[0], 0, (output_buf_size - PAD_SIZE) * sizeof(int) );
// 将output_inter[0], output_intra[0]的NUM_ROWS段 赋值为 i_mb_height
output_inter[0][NUM_ROWS] = output_intra[0][NUM_ROWS] = h->mb.i_mb_height;
// 初始化s变量
x264_slicetype_slice_t s = (x264_slicetype_slice_t){ h, a, frames, p0, p1, b, dist_scale_factor, do_search, w,
output_inter[0], output_intra[0] };
// slice cost 计算, 见x264_slicetype_slice_cost
x264_slicetype_slice_cost( &s );
}
/* Sum up accumulators */
if( b == p1 )
fenc->i_intra_mbs[b-p0] = 0;
if( !fenc->b_intra_calculated )
{
// 初始化I帧代价估计
fenc->i_cost_est[0][0] = 0;
fenc->i_cost_est_aq[0][0] = 0;
}
// 初始化前向,后向距代价估计
fenc->i_cost_est[b-p0][p1-b] = 0;
fenc->i_cost_est_aq[b-p0][p1-b] = 0;
// row_satd_inter 指向P帧/B帧的i_row_satds
// row_satd_intra 指向I帧的i_row_satds
int *row_satd_inter = fenc->i_row_satds[b-p0][p1-b];
int *row_satd_intra = fenc->i_row_satds[0][0];
for( int i = 0; i < h->param.i_lookahead_threads; i++ )
{
if( b == p1 )
fenc->i_intra_mbs[b-p0] += output_inter[i][INTRA_MBS];
if( !fenc->b_intra_calculated )
{
// 统计待编帧作为I帧编码的代价
fenc->i_cost_est[0][0] += output_intra[i][COST_EST];
fenc->i_cost_est_aq[0][0] += output_intra[i][COST_EST_AQ];
}
// 统计待编帧作为P/B帧编码的代价
fenc->i_cost_est[b-p0][p1-b] += output_inter[i][COST_EST];
fenc->i_cost_est_aq[b-p0][p1-b] += output_inter[i][COST_EST_AQ];
if( h->param.rc.i_vbv_buffer_size )
{
// 如果h->param.rc.i_vbv_buffer_size不为0,
// 则将satd row估计拷贝到待编码帧row_satd_inter / row_satd_intra数组中
int row_count = output_inter[i][NUM_ROWS];
memcpy( row_satd_inter, output_inter[i] + NUM_INTS, row_count * sizeof(int) );
if( !fenc->b_intra_calculated )
memcpy( row_satd_intra, output_intra[i] + NUM_INTS, row_count * sizeof(int) );
row_satd_inter += row_count;
row_satd_intra += row_count;
}
}
// 获得当前待编帧作为I/P/B帧编码的代价
i_score = fenc->i_cost_est[b-p0][p1-b];
// 如果是作B帧编, 调整i_score
if( b != p1 )
i_score = (uint64_t)i_score * 100 / (120 + h->param.i_bframe_bias);
else
fenc->b_intra_calculated = 1;
// 将最终的i_score保存在待编帧的相应i_cost_est数组中
fenc->i_cost_est[b-p0][p1-b] = i_score;
x264_emms();
}
}
if( b_intra_penalty )
{
// arbitrary penalty for I-blocks after B-frames
int nmb = NUM_MBS;
i_score += (uint64_t)i_score * fenc->i_intra_mbs[b-p0] / (nmb * 8);
}
return i_score;
}
- x264 - x264_slicetype_frame_cost
- x264
- x264 - x264.mb.i_neighbour8
- X264 笔记
- 编译x264
- x264编译
- x264 git
- x264优化
- X264设定
- X264分析
- X264设定
- 编译x264
- x264编译
- x264记录
- x264 encode
- 编译x264
- x264 - x264_frame_init_lowres
- X264 - lookahead
- 关于oracle pl/sql工具加锁的解决
- python实现Excel转json
- jar包调用jar包内部和外部的配置文件
- 记录日志配置文档
- linux下如何修改Mysql的root密码
- x264 - x264_slicetype_frame_cost
- 对C++沉思录中代理类实现的质疑和修改
- ATCA构架
- ios基础-分辨率适配
- Ubuntu无法用putty登录
- 内核对象
- 修改后的小米文件管理器(去掉远程管理)
- Mysql的count函数
- 在shell中常用的特殊符号罗列