x264代码分析-slicetype-cost计算

前面一篇博客讲解了,在打开scenecut的情况下,帧类型是由icost和pcost以及距离上一次编码IDR的距离来计算得到的最终结果的。

那么这些cost是如何计算得到的呢?

看下面代码:

static int scenecut_internal( x264_t *h, x264_mb_analysis_t *a, x264_frame_t **frames, int p0, int p1, int real_scenecut )

{

x264_frame_t *frame = frames[p1];

/* Don't do scenecuts on the right view of a frame-packed video. */

if( real_scenecut && h->param.i_frame_packing == 5 && (frame->i_frame&1) ) // frame_packing和3d有关就不管了

       return 0;

slicetype_frame_cost( h, a, frames, p0, p1, p1 );

int icost = frame->i_cost_est[0][0]; //icost

int pcost = frame->i_cost_est[p1-p0][0];// pcost

这里主要是看p0, p1,参数,本来还应该有一个b参数

当前帧的cost其实可以表示为int cur_cost = frame->i_cost_est[ b - p0 ][ p1 - b];

再和上面的下标对比,就可以看得出来。b表示当前帧,为什么写成b?

因为我们姑且认为所有的帧都有两个方向上的参考帧,b - p0就是向前参考,p1 - b 就是后向参考,他们的差值就是距离参考帧的距离。

可以简单用表格表示为:

p0 b p1

当 p0 = b = p1的时候 就是当前帧,意思就是I帧没有参考帧。

接下来进到slicetype_frame_cost函数深入看下cost怎么计算的。(函数比较复杂,还没有完全弄懂,粗略介绍下!)

 

static int slicetype_frame_cost( x264_t *h, x264_mb_analysis_t *a,

x264_frame_t **frames, int p0, int p1, int b )// 0, 1, 1

{

int i_score = 0;// 临时变量cost值

int do_search[2];

const x264_weight_t *w = x264_weight_none; 

x264_frame_t *fenc = frames[b]; //帧顺序 p0, b, p1, b的前后参考帧为p0和p1, 当p1 == b的时候,b这个位置就是p帧,没有后向参考

多线程跑

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);

//一个线程计算几行的cost,

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;

x264_threadpool_run( h->lookaheadpool, (void*)slicetype_slice_cost, &s[i] );

进入slicetype_slice_cost看看

循环遍历计算每一个宏块的cost

static void slicetype_slice_cost( x264_slicetype_slice_t *s )

{

x264_t *h = s->h;

 

/* Lowres lookahead goes backwards because the MVs are used as predictors in the main encode.

* This considerably improves MV prediction overall. */

 

/* The edge mbs seem to reduce the predictive quality of the

* whole frame's score, but are needed for a spatial distribution. */

int do_edges = h->param.rc.b_mb_tree || h->param.rc.i_vbv_buffer_size || h->mb.i_mb_width <= 2 || h->mb.i_mb_height <= 2;

 

int start_y = X264_MIN( h->i_threadslice_end - 1, h->mb.i_mb_height - 2 + do_edges );

int end_y = X264_MAX( h->i_threadslice_start, 1 - do_edges );

int start_x = h->mb.i_mb_width - 2 + do_edges;

int end_x = 1 - do_edges;

 

for( h->mb.i_mb_y = start_y; h->mb.i_mb_y >= end_y; h->mb.i_mb_y-- )

for( h->mb.i_mb_x = start_x; h->mb.i_mb_x >= end_x; h->mb.i_mb_x-- )

slicetype_mb_cost( h, s->a, s->frames, s->p0, s->p1, s->b, s->dist_scale_factor,

s->do_search, s->w, s->output_inter, s->output_intra );

}

 

static void slicetype_mb_cost( x264_t *h, x264_mb_analysis_t *a,

x264_frame_t **frames, int p0, int p1, int b,

int dist_scale_factor, int do_search[2], const x264_weight_t *w,

int *output_inter, int *output_intra )

{

x264_frame_t *fref0 = frames[p0];

x264_frame_t *fref1 = frames[p1];

x264_frame_t *fenc = frames[b];

const int b_bidir = (b < p1);// 是B帧

const int i_mb_x = h->mb.i_mb_x;

const int i_mb_y = h->mb.i_mb_y;

const int i_mb_stride = h->mb.i_mb_width;//一行宏块个数

const int i_mb_xy = i_mb_x + i_mb_y * i_mb_stride;//宏块坐标

const int i_stride = fenc->i_stride_lowres;

const int i_pel_offset = 8 * (i_mb_x + i_mb_y * i_stride);

const int i_bipred_weight = h->param.analyse.b_weighted_bipred ? 64 - (dist_scale_factor>>2) : 32;

int16_t (*fenc_mvs[2])[2] = { b != p0 ? &fenc->lowres_mvs[0][b-p0-1][i_mb_xy] : NULL, b != p1 ? &fenc->lowres_mvs[1][p1-b-1][i_mb_xy] : NULL };

//前后两个方向的mv, 这里直接从fenc 中取内存, 自己没有内存

int (*fenc_costs[2]) = { b != p0 ? &fenc->lowres_mv_costs[0][b-p0-1][i_mb_xy] : NULL, b != p1 ? &fenc->lowres_mv_costs[1][p1-b-1][i_mb_xy] : NULL };

// 编码cost也是一样的道理

int b_frame_score_mb = (i_mb_x > 0 && i_mb_x < h->mb.i_mb_width - 1 &&

i_mb_y > 0 && i_mb_y < h->mb.i_mb_height - 1) ||

h->mb.i_mb_width <= 2 || h->mb.i_mb_height <= 2;

/*后续计算在这个参考帧中的icost和pcost*/

 

 

 

 

 

 

 

 

 

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值