x264码率控制-帧duration计算

在编码器中,码率控制有两个重要的参数,1 时间基准 2 当前帧时间戳

一 为什么需要这两个

因为编码器的码率控制是以时间s为单位的,比如1000kbps,意思是1s有1000kbits的数据量,然后在编码器中并没有时间的概念,

只有时间基准和时间戳,这两个合并可以计算出来时间,所以编码器的码率控制都是以这两个参数为基础计算出来的。

 

时间基准:很多编码器设置的都是1/fps, 但是也有时候需要直接传入ms

为单位的帧pts,这样的话,时间基准就需要设置为1/1000, 还有如果像ts/mp4格式解码出来的视频帧,时间基准是1/90000,这样编码

的时候就设置成1/90000。

时间戳:当时间基准为1/fps时, 时间戳每次+1,依次递增,这样编码出来的帧之后,需要把时间戳scale为容器(flv,rtmp,mp4, ts等)需要的基准。

看下x264编码器中时间戳在码率控制中的作用。以下分析代码:

enum pic_struct_e

{

PIC_STRUCT_AUTO = 0, // automatically decide (default)

PIC_STRUCT_PROGRESSIVE = 1, // progressive frame

// "TOP" and "BOTTOM" are not supported in x264 (PAFF only)

PIC_STRUCT_TOP_BOTTOM = 4, // top field followed by bottom

PIC_STRUCT_BOTTOM_TOP = 5, // bottom field followed by top

PIC_STRUCT_TOP_BOTTOM_TOP = 6, // top field, bottom field, top field repeated

PIC_STRUCT_BOTTOM_TOP_BOTTOM = 7, // bottom field, top field, bottom field repeated

PIC_STRUCT_DOUBLE = 8, // double frame

PIC_STRUCT_TRIPLE = 9, // triple frame

};

这个枚举标示了一个帧需要占用多少个时间基准单元,这种是在设置的时间基准为1/fps,并且关闭了b_vfr_input的时候使用的。

b_vfr_input意思是变动帧率输入,这样编码器计算帧之间的duration, 直接用前后帧时间戳相减。见代码

h->lookahead->next.list[i]->i_duration = 2 * (h->lookahead->next.list[i+1]->i_pts - h->lookahead->next.list[i]->i_pts);

当b_vfr_input关闭的时候,时间基准需要被设置为1/fps, 要不然无法计算出帧duration。见代码

h->lookahead->next.list[i]->i_duration = delta_tfi_divisor[h->lookahead->next.list[i]->i_pic_struct];

delta_tfi_divisor是一个数组,预先设定了,某种类型的帧,duration为多少个时间基准单元。

接下来计算得到时间基准之后,开始用于码率控制。以crf码控为例

clip_qscale 为x264编码器中主要的帧级别的码控函数

double fenc_cpb_duration = (double)h->fenc->i_cpb_duration *
            h->sps->vui.i_num_units_in_tick / h->sps->vui.i_time_scale;

首先根据时间基准把duration换算成以秒为单位的时间。

total_duration += last_duration; //累加到当前编码帧的duration中,得到当前编码的总帧的duration,

通过总的编码帧duration以及

for( int j = 0; buffer_fill_cur >= 0 && buffer_fill_cur <= rcc->buffer_size; j++ )
{//先通过当前给定的qp值计算出来,需要消耗多少bits
 total_duration += last_duration;
buffer_fill_cur += rcc->vbv_max_rate * last_duration;
 int i_type = h->fenc->i_planned_type[j];
 int i_satd = h->fenc->i_planned_satd[j];
if( i_type == X264_TYPE_AUTO )
 break;
 i_type = IS_X264_TYPE_I( i_type ) ? SLICE_TYPE_I : IS_X264_TYPE_B( i_type ) ? SLICE_TYPE_B : SLICE_TYPE_P;
 cur_bits = predict_size( &rcc->pred[i_type], frame_q[i_type], i_satd );
buffer_fill_cur -= cur_bits;
last_duration = h->fenc->f_planned_cpb_duration[j];
}

然后按照当前的vbv码率控制给的参数计算出来,total_duration时长的帧最多能消耗多少bits

target_fill = X264_MIN( rcc->buffer_fill + total_duration * rcc->vbv_max_rate * 0.5, rcc->buffer_size * 0.5 ); 

然后比较这两,如果不足,就调大qp值。 qp的默认值为crf值

if( buffer_fill_cur < target_fill )
{
  q *= 1.01;
  terminate |= 1;
 continue;
 }

//VBV码率控制buf的限制,和上面的maxrate控制类似

target_fill = x264_clip3f( rcc->buffer_fill - total_duration * rcc->vbv_max_rate * 0.5, rcc->buffer_size * 0.8, rcc->buffer_size );
if( rcc->b_vbv_min_rate && buffer_fill_cur > target_fill )
 {
 q /= 1.01;
terminate |= 2;
 continue;
 }

最多调整1000次,最终得到一个合适的qp值。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值