码率控制
码率控制

最后,我们再来看VBR和CBR,对于VBR来说,它可以通过特殊的算法来控制一个GOP组的长度,也就是I帧的数量,当图像中运动图像多时,我可以把I帧数量加大,那么图像会很清晰,如果图像内元素基本静止时,它甚至可以把GOP组调到25的长度。那么根据前面的描述,可以想象这是一种为了确保图像质量的控制手段,它非常灵活,不死板,但是要求控制算法非常的精确,不精确会导致很多问题,例如码流突增后不降低,即使带宽足够,会导致图像出现问题。
码率控制实际上是一种编码ቤተ መጻሕፍቲ ባይዱ优化算法,它用于实现对视频流码流大小的控制。那么它控制的目的是什么呢?
我们可以试想一下,同样的视频编码格式,码流大,它包含的信息也就越多,那么对应的图像也就越清晰,反之亦然。目前常用的两种码流控制方式是VBR和CBR,VBR是动态比特率,CBR是固定比特率。那么他们是怎么来实现的呢?
总结一下,VBR码流控制方式可以降低图像动态画面少时候的带宽占用,CBR控制方式码流稳定,图像状态较稳定。他们为了解决的是不同需求下的不同应用。
没有参考资料,我自己写的,希望能对你有帮助。
我们首先看视频编码的目的,它是为了在有限的带宽中传输尽可能清晰的视频,我们以每秒25/帧的图像举例,25帧图像中定义了GOP组,目前主要是有I,B,P帧三种帧格式,I帧是关键帧,你可以想象它就是一幅JPEG压缩图像,而B,P帧是依靠I帧存在的,如果丢失了I帧,B,P帧是看不到图像的,B,P帧描述的不是实际的图像像素内容,而是每个相关像素的变化量,他们相对于I帧信息量会很小。GOP组是指一个关键帧I帧所在的组的长度,每个GOP组只有1个I帧。
vbr码率控制公式

vbr码率控制公式在视频编码过程中,码率控制是一项关键技术,它能够有效地控制视频的码率,使得视频能够在给定的带宽条件下进行有效传输和播放。
VBR码率控制公式是一种用于控制视频码率的公式,可以根据视频的内容和特性来动态地调整码率,以达到最佳的视觉质量和压缩效率。
VBR码率控制公式被广泛应用于各种视频编码标准中,如H.264、H.265等。
其核心思想是根据视频每一帧的复杂度来确定相应的码率,以保证视频在不同场景下的质量和一致性。
在实际应用中,VBR码率控制公式通常包括以下几个主要参数:1. 目标质量参数(Target Quality Parameter)目标质量参数用于设置视频的期望质量水平,一般以质量标准PSNR(Peak Signal-to-Noise Ratio)或SSIM(Structural Similarity Index)为依据。
通过调整目标质量参数,可以控制视频编码的质量,从而达到更好的视觉效果。
2. 带宽预测参数(Bandwidth Prediction Parameter)带宽预测参数用于预测当前网络环境下的可用带宽,以动态地调整视频的码率。
通过实时地监测网络带宽的变化,系统可以根据带宽预测参数来预测网络的可用带宽,并相应地调整视频的码率,以适应网络的实际情况。
3. 视频场景分析参数(Video Scene Analysis Parameter)视频场景分析参数用于分析视频的内容和特性,以确定视频每一帧的复杂度。
通过对视频的场景进行深入分析,系统可以根据视频场景分析参数来确定合适的编码方式和参数,从而达到更高的压缩效率和更好的视觉质量。
VBR码率控制公式的具体形式可以根据不同的视频编码标准和应用需求来进行调整和优化。
在实际应用中,研究人员提出了许多不同的VBR码率控制公式和算法,如基于模型的码率控制算法、基于反馈的码率控制算法等。
这些算法可以根据实际情况选择合适的调节策略,以确保视频的传输和播放效果。
码率控制与实现算法

码率控制技术原理
当D=O时,编码对应于无损压缩,输入码率应大于或等于信源熵 H(X);若D一为最大允许失真,则相应码率下限为R(D一)。典型的 率失真曲线R—D如图3.1所示。R(D’)为D’的凸递减函数。
码率控制技术原理
率失真优化主要用于模式选择。在H.264视频标准中,有以下几种 模式:INTRA.4x4,INTRA.16x16,SKIP,INTER—16×16, INTER.16×8,INTER.8×16,INTER.8×8。 假设图像序列S被分割为K个不同的块4,相应的像素用6t来表示。 编码6t所选择的编码模式%分为帧间编码和帧内编码。每种编码模 式都包括预测编码的模式和编码参数。其中编码参数包括变换系数 和量化参数等。对于帧间模式,编码参数还包括一个或多个运动矢 量。
码率控,视频应用对压缩比有较高的要求。无损 编码所能提供的压缩比远不能满足实际视频应用的需求,但如果我们能够 接受某种程度的失真,高的压缩比也不难获得。人眼视觉系统对高频信号 变化不敏感,部分高频信息丢失不会降低主观视频质量,主流的视频编码 算法正是采用了量化方法消除视频信号的生理视觉冗余,获得比无损压缩 更高的压缩比而又不会带来视频质量的显著降低。率失真(RateDistortion 理论旨在描述编码失真度(Distortion,重构误差)和编码数据速率的关系。 该理论建立在图像是连续的基础上,在有限数据速率下,由于存在量化误 差,必然存在失真。尽管率失真理论没有给出最优编码器,但它还是给出 了容许失真条件下信息压缩允许的下界。当使用有损编码方法时,重构图 像g(x,y)和原始图像f(x,y)存在差别。一般地,失真度D函数形式可以根 据需要任意选取,例如平方代价函数、绝对代价函数等。在图像编码中,D 常用均方差形式表示:
码率控制与实现算法

码率控制技术原理与 H.264的码率控制算法介绍
小组成员:池品臻 陈申 陈天壹 陈仙锋 程 宏浩
码率控制技术原理
引起编码器的输出比特码率波动的原因主要有两个。首先,数字视
频信号中包含了大量的时域和空域冗余,编码器的主要任务就是去
除这些冗余。由于时间冗余和空间冗余是随机的,从而造成编码器 输出比特率波动。另一个原因是变长编码,变长编码根据某个事件 (如零游程)的发生概率来设计码字。事件发生的概率越大,其编码
码字越短,反之亦然,从而引起编码器输出比特率的变化。
码率控制技术原理
由于视频应用的要求和目的不同,根据输出码率是否要求恒定,传
输码流的信道可分为两种类型,即可变比特率的码率控制
VBR(Variable Bit Rate)和恒定比特率的码率控制CBR(Constant Bit Rate)。在变比特率信道下,可以为更高的运动量或更详细的 纹理信息分配更多的带宽,从而获得更高效的带宽共享,有利于获
H(X);若D一为最大允许失真,则相应码率下限为R(D一)。典型的
率失真曲线R—D如图3.1所示。R(D’)为D’的凸递减函数。
码率控制技术原理
率失真优化主要用于模式选择。在H.264视频标准中,有以下几种
模式:INTRA.4x4,INTRA.16x16,SKIP,INTER—16×16,
INTER.16×8,INTER.8×16,INTER.8×8。 假设图像序列S被分割为K个不同的块4,相应的像素用6t来表示。 编码6t所选择的编码模式%分为帧间编码和帧内编码。每种编码模
所需的码字位数,Q指基本单元的量化步长,MAD通过以下线性预测
模型进行预测:
H.264的码率控制算法
1。基本单元的定义 假设某一帧由Nmbpic个宏块组成,那么定义基本单元为一 个由Nmbpic个宏块中连续的Nmbunit个宏块所组成的组。那么在该 帧中的总的基本单元的个数为: Nunit=Nmbpic/Nmbunit 需要注意的是,如果采用了比较大的基本单元,那么PSNR 可以达到一个较高的值,同时比特的波动也会增大。另一方面,如 果采用了比较小的基本单元,比特的波动会比较的小,但是相应的
h265 压缩参数

h265 压缩参数
H265即HEVC,是一种高效的视频压缩标准。
在H265压缩参数中,主要有码率控制、分片处理、帧率控制等部分:
1. 码率控制:通过调整码率,可以控制视频的压缩效果和传输带宽。
较低的码率可以降低视频的压缩效果,但能够节省带宽;较高的码率则可以提高视频质量,但需要更多的带宽。
2. 分片处理:分片处理可以有效地降低视频的码率,从而节省带宽。
通过将视频画面分割成若干个较小的片,并对每个片进行独立的编码和传输,可以实现更高的压缩效果。
3. 帧率控制:这是视频压缩的一个重要参数,它决定了视频的流畅度和清晰度。
帧率越高,视频越流畅,但所需的存储空间也越大。
此外,H265还支持多种分辨率的视频压缩,包括4K、1080p、720p等,可以根据不同的需求选择合适的分辨率进行压缩。
如需更多信息,建议查阅相关文献或咨询专业人士。
homerHEVC代码阅读(42)——码率控制

homerHEVC代码阅读(42)——码率控制一、码率控制的相关理论请看:HEVC/H.265理论知识(9)——码率控制二、码率控制可以分为几个几个级别,HomerHEVC只支持帧级和CTU级的码率控制三、码率控制实际就是控制量化参数,通过量化参数来提高码率或者降低码率四、码率控制基本都要配备缓冲区,因为码率控制不可能完全精确,因此需要使用缓冲区来匹配比特生成的速度和发送的速度码率控制初始化,基本就是根据缓冲区计算,每一个CTU应该分配多少比特数:1.void hmr_rc_init(hvenc_engine_t* enc_engine)2.{3./* 缓冲区的大小 */4.enc_engine->rc.vbv_size = enc_engine->vbv_size*1000;5.enc_engine->rc.vbv_fullness = enc_engine->vbv_init*1000;6./* 每一帧平均的尺寸 */7.enc_engine->rc.average_pict_size = enc_engine->bitrate*1000/enc_engine->frame_rate;8./* 每一个CTU平均的比特数 */9.enc_engine->rc.average_bits_per_ctu = enc_engine->rc.average_pict_size/enc_engine->pict_total_ctu;10.enc_engine->hvenc->rc = enc_engine->rc;11.}帧级码率控制初始化,目的是计算一帧的目标比特数:1.void hmr_rc_init_pic(hvenc_engine_t* enc_engine,slice_t *currslice)2.{3.int ithreads;4.int clipped_intra_period = enc_engine->intra_period==0?20:enc_engine->intra_period;5.double intra_avg_size = 2.25*enc_engine->rc.average_pict_size*sqrt((double)clipped_i ntra_period);6.7.enc_engine->rc = enc_engine->hvenc->rc;8.enc_engine->rc.extra_bits = 0;9.switch(currslice->slice_type)10.{11.case I_SLICE:12.{13.enc_engine->rc.target_pict_size = min(intra_avg_size, enc_engine->rc.vbv_fullness);///*(2.25-((double)enc_engine->avg_dist/15000.))**/2.25*enc_engine->rc.average_pict_size*sqrt((double)clipped_intra_period);14.if(enc_engine->num_b>0)15.enc_engine->rc.target_pict_size *= (1.0+.1*enc_engine->num_b);//.5*enc_engine->rc.average_pic t_size;16.break;17.}18.case P_SLICE:19.{20.enc_engine->rc.target_pict_size = (enc_engine->rc.average_pict_size*clipped_intra_period-intra_avg_size)/(clipped_intra_period-1);//.5*enc_engine->rc.average_pict_size;21.if(enc_engine->num_b>0)22.enc_engine->rc.target_pict_size *= (1.0+.1*enc_engine->num_b);//.5*enc_engine->rc.average_pic t_size;23.break;24.}25.case B_SLICE:26.{27.enc_engine->rc.target_pict_size = enc_engine->rc.average_pict_size/2;28.break;29.}30.}31.32.#ifdef COMPUTE_AS_HM33.currslice->qp = enc_engine->pict_qp-(enc_engine->num_encoded_frames%4);34.if(currslice->qp<1)35.{36.currslice->qp=1;37.}38.#endif39.40.enc_engine->rc.target_bits_per_ctu = enc_engine->rc.target_pict_size/enc_engine->pict_total_ctu;41.42.for(ithreads=0;ithreads<enc_engine->wfpp_num_ threads;ithreads++)43.{44.henc_thread_t* henc_th = enc_engine->thread[ithreads];45.46.henc_th->target_pict_size = (uint32_t)enc_engine->rc.target_pict_size;47.henc_th->num_encoded_ctus = 0;48.henc_th->num_bits = 0;49.henc_th->acc_qp = 0;50.}51.enc_engine->hvenc->rc = enc_engine->rc;52.}如果屏幕大小改变了,那么需要调整目标比特数:1.void hmr_rc_change_pic_mode(henc_thread_t* et, slice_t *currslice)2.{3.hvenc_engine_t* enc_engine = et->enc_engine;4.int clipped_intra_period = (enc_engine->intra_period==0)?20:enc_engine->intra_period;5.double pic_size_new;6.int consumed_bitrate = 0;7.int consumed_ctus = 0;8.int current_pic_size = enc_engine->rc.target_pict_size;9.10.// if(enc_engine->is_scene_change)11.{12.int ithreads;13.14.15.if(et->enc_engine->gop_reinit_on_scene_change && enc_engine->rc.vbv_fullness<.5*enc_engine->rc.vbv_size)16.{17.pic_size_new = 1.*enc_engine->rc.average_pict_size*sqrt((double)clipped_intr a_period);18.}19.else20.{21.pic_size_new= .75*enc_engine->rc.average_pict_size*sqrt((double)clipped_i ntra_period);22.}23.enc_engine->rc.target_pict_size = min(pic_size_new, enc_engine->rc.vbv_fullness);24.25.enc_engine->rc.target_bits_per_ctu = enc_engine->rc.target_pict_size/enc_engine->pict_total_ctu;26.27.for(ithreads=0;ithreads<enc_engine->wfpp_num_ threads;ithreads++)28.{29.henc_thread_t* henc_th = enc_engine->thread[ithreads];30.31.henc_th->target_pict_size = (uint32_t)enc_engine->rc.target_pict_size;32.consumed_bitrate += henc_th->num_bits;33.consumed_ctus += henc_th->num_encoded_ctus;34.}35.enc_engine->rc.extra_bits = enc_engine->rc.target_pict_size*((double)consumed_ctus/et-> enc_engine->pict_total_ctu)-consumed_bitrate;//clip(((double)pic_size_new/current_pic_size)*consumed_bitrate - consumed_bitrate, 0, pic_size_new/2);36.}37.38.enc_engine->hvenc->rc = enc_engine->rc;39.}根据码率控制获取CTU的量化参数:1.int hmr_rc_get_cu_qp(henc_thread_t* et, ctu_info_t *ctu, cu_partition_info_t *curr_cu_info, slice_t *currslice)2.{3.int qp;4.#ifdef COMPUTE_AS_HM5.double debug_qp = currslice->qp+ctu->ctu_number%4;//28+ctu->ctu_number%4;6.if(et->enc_engine->bitrate_mode == BR_FIXED_QP)7.{8.qp = et->enc_engine->current_pict.slice.qp;9.}10.else//cbr, vbr11.{12.if(curr_cu_info->depth <= et->enc_engine->qp_depth)13.qp = (int)debug_qp;//hmr_rc_calc_cu_qp(et);14.else15.qp = curr_cu_info->parent->qp;16.}17.#else18.if(et->enc_engine->bitrate_mode == BR_FIXED_QP)19.{20.qp = et->enc_engine->current_pict.slice.qp;21.}22.else//cbr, vbr23.{24.if(curr_cu_info->depth <= et->enc_engine->qp_depth)25.{26.qp = hmr_rc_calc_cu_qp(et, ctu, currslice);27.}28.else29.qp = curr_cu_info->parent->qp;30.}31.#endif32.33.return qp;34.}1.int hmr_rc_calc_cu_qp(henc_thread_t* curr_thread, ctu_info_t*ctu/*, cu_partition_info_t *curr_cu_info*/, slice_t *currslice)2.{3.hvenc_engine_t* enc_engine = curr_thread->enc_engine;4.int ithreads;5.double qp;6.double pic_corrector = 0.0;7.double vbv_corrector;8.double consumed_bitrate = 0.0, entropy;9.double min_vbv_size;10.int consumed_ctus = 0;11.for(ithreads=0;ithreads<enc_engine->wfpp_num_ threads;ithreads++)12.{13.henc_thread_t* henc_th = enc_engine->thread[ithreads];14.15.consumed_bitrate += henc_th->num_bits;16.consumed_ctus += henc_th->num_encoded_ctus;17.}18.19.entropy = 3;//sqrt(((double)enc_engine->avg_dist/3000.)*(curr_cu_info-> variance))/40;//25.0;20.21.consumed_bitrate += enc_engine->rc.extra_bits;22.23.// if(consumed_ctus>0 && (currslice->slice_type != P_SLICE || enc_engine->is_scene_change))24.{25.if(consumed_bitrate>1.5*enc_engine->rc.target_b its_per_ctu*consumed_ctus)//*consumed_ctus && currslice->slice_type != I_SLICE)26.{27.if(currslice->slice_type == I_SLICE)28.pic_corrector =2.5*.0125*(consumed_bitrate/(enc_engine->rc.target_bits_per_ ctu*consumed_ctus));29.else30.pic_corrector= .0125*(consumed_bitrate/(enc_engine->rc.target_bits_per_ct u*consumed_ctus));31.}32.pic_corrector = clip(pic_corrector, 0, .5);33.34.}35.36.min_vbv_size = clip(enc_engine->rc.vbv_fullness,enc_engine->rc.vbv_fullness, enc_engine->rc.vbv_size*.95);37.38.39.if(consumed_bitrate>enc_engine->rc.target_bits_ per_ctu*consumed_ctus)40.vbv_corrector = 1.0-clip((min_vbv_size-consumed_bitrate+enc_engine->rc.target_bits_per_ctu*consu med_ctus)/enc_engine->rc.vbv_size, 0.0, 1.0);41.else42.vbv_corrector = 1.0-clip((min_vbv_size)/enc_engine->rc.vbv_size, 0.0, 1.0);43.qp = ((pic_corrector+vbv_corrector)/1.)*(MAX_QP)+/*(pic_corrector-1)+*/(entropy-3.);44.45.//variable rate46.if(enc_engine->bitrate_mode == BR_VBR)47.{48.if(qp<enc_engine->qp_min)49.qp=enc_engine->qp_min;50.}51.52.if(curr_thread->enc_engine->intra_period>1)53.{54.if(currslice->slice_type == I_SLICE || (enc_engine->is_scene_change && enc_engine->gop_reinit_on_scene_change))55.{56.qp/=clip(1.5-((double)enc_engine->avg_dist/15000.),1.15,1.5);57.}58.else if(currslice->slice_type == B_SLICE && enc_engine->num_b!=enc_engine->gop_size)59.{60.qp*=clip(1.125-((double)enc_engine->avg_dist/15000.),1.15,1.5);61.}62.63.else if(enc_engine->is_scene_change)64.qp/=1.1;65.}66.67.if((enc_engine->is_scene_change) && qp<=5)68.{69.qp=5;70.}71.72.if(enc_engine->num_encoded_frames==0)73.{74.qp+=4;75.}76.else if(currslice->slice_type == I_SLICE && consumed_bitrate > 1.*(enc_engine->rc.target_bits_per_ctu*consumed_ctus) && enc_engine->rc.vbv_fullness<.5*enc_engine->rc.vbv_size)//co ntrol scene changes in I frames77.{78.qp+=2;79.}80.81.return (int)clip(qp+.5,1.0,MAX_QP);82.}。
ffmpeg码流控制

ffmpeg码流控制FFmpeg是一个开源的多媒体处理工具,它可以用于音视频编解码、转码、流媒体处理等多种用途。
在这里,我们来讨论FFmpeg中的码流控制。
码流控制是指控制音视频数据的传输速率,以确保在不同网络环境下的媒体播放的稳定性和流畅性。
在FFmpeg中,有几种方法可以实现码流控制。
1. 码率控制:码率控制是一种通过控制编码参数来控制输出媒体文件的码率的方法。
在FFmpeg中,可以通过设置编码器的参数,如码率(bitrate)、帧率(framerate)、关键帧间隔(gop size)等来控制输出文件的码率。
通过调整这些参数,可以实现对码率的精确控制。
2. 帧丢弃:在某些情况下,网络带宽不足或媒体播放设备性能有限,无法实时处理所有的音视频帧。
为了保证播放的连续性,可以通过在编码过程中丢弃一些帧来减少数据量。
在FFmpeg中,可以使用参数"-vf"或"-af"来进行帧丢弃,通过设置适当的帧丢弃策略,可以在保持播放连续性的前提下减少码流大小。
3. 媒体格式转换:码流控制还可以通过转换媒体文件的格式来实现。
对于某些网络环境下传输速率较慢的情况,可以通过将媒体文件转换为更高压缩率的格式,如从AVI转换为MP4,从WAV转换为AAC等,来减小数据量,从而实现码流控制。
需要注意的是,在进行码流控制时,需要综合考虑网络带宽、媒体文件质量要求和播放设备性能等因素,以达到合理的码流控制效果。
FFmpeg提供了丰富的参数和选项,可以根据实际情况进行调整和优化。
以上是关于FFmpeg中码流控制的简要说明,希望能对你有所帮助。
如有更多细节或相关问题,请随时提问。
CV181x CV180x 芯片码率控制使用说明说明书

CV181x/CV180x芯片码率控制使用说明Version:1.3.0Release date:2022-06-13©2022北京晶视智能科技有限公司本文件所含信息归北京晶视智能科技有限公司所有。
未经授权,严禁全部或部分复制或披露该等信息。
目录1声明22码率控制参数意义和使用方法42.1CBR参数说明及使用方法 (4)2.2VBR参数说明及使用方法 (5)2.3AVBR参数说明及使用方法 (6)2.4宏块级码率控制参数说明及使用方法 (8)2.5码率过高丢帧参数及使用说明 (8)3GOP结构参数意义和使用方法93.1单参考P帧GOP结构属性说明及使用方法 (9)3.2智能P帧GOP结构属性说明及使用方法 (9)4码率控制专题104.1码率稳定 (10)4.2图像质量提升 (10)4.3调节呼吸效应 (11)4.4限制I帧幅度 (11)4.5减少运动拖影 (11)4.6减少色度偏移 (11)4.7码率控制的起始QP (11)4.8低码率场景 (11)4.9注意事项 (12)目录修订记录Revision Date Description0.12021/05/24Start from CV181x/CV180x芯片码率控制使用说明_v0.2.0.31.1.12021/06/09Start from CV181x/CV180x芯片码率控制使用说明_v0.10.12021/06/10增加AVBR参数说明及使用方法1.2.02021/09/22Start from CV181x/CV180x芯片码率控制使用说明_v1.1.11.3.02022/06/13Start from CV181x/CV180x芯片码率控制使用说明_v1.2.0CHAPTER1声明法律声明本数据手册包含北京晶视智能科技有限公司(下称“晶视智能”)的保密信息。
未经授权,禁止使用或披露本数据手册中包含的信息。
如您未经授权披露全部或部分保密信息,导致晶视智能遭受任何损失或损害,您应对因之产生的损失/损害承担责任。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
X264码率控制流程分析码率控制的理论知识:码率控制的目的和意义:图像通信中码率控制的目的:通过调节编码参数,控制单位时间内的编码视频流的数据量,以使产生的比特流符合各种应用的需求。
视频压缩的效率和视频内容有很大的关系,对于变化多样的画面,视频编码的输出的码流变化较大,在信道环境不好的时候就容易导致解码端显示的质量的不稳定。
率失真理论:由于传输带宽和存储空间的限制,视频应用对压缩比有较高的要求。
而无损编码较低的压缩比无法满足视频在实际应用中的需求。
但如果给视频引入一定程度的失真,通常可以获得较高的压缩比。
率失真理论对有损压缩编码下的失真和编码性能之间的关系的描述,为码率控制的研究提供了坚实的理论依据。
率失真理论主旨是描述编码失真度和编码数据速率的关系。
该理论建立在图像是连续的基础上的,在有限数据速率下,由于存在量化误差,必然存在失真。
当使用有损编码方法时,重建图像g(x,y)和原始图像f(x,y)之间存在差异,失真度D的函数形式在理论上是可以根据需要自由选取的,在图像编码中,D 常用均方差形式表示的,典型的率失真曲线。
R(D)为D的凸减函数。
对于怎么选择哪个函数的率失真效果更好,则是比较哪个函数的率失真函数更为接近典型的率失真函数的曲线。
x264码率控制方法:采用的码率控制算法并没有采用拉格朗日代价函数来控制编码,而是使用一种更简单的方法,即利用半精度帧的SATD(sum of absolute transformed difference)作为模式选择的依据。
SATD 即将残差经哈德曼变换的4×4块的预测残差绝对值总和,可以将其看作简单的时频变换,其值在一定程度上可以反映生成码流的大小。
SATD是将残差经哈达曼变换4*4块的预测残差绝对值总和。
自适应宏块层码率控制策略:X264的宏块没有任何码率控制的机制,其在帧层得到一个QP后,属于该帧的所有宏块都用着统一的QP进行量化。
码率控制性能测度:1、比特率误差|ABR-TBR|/TBR ,越小越好。
2、编码器性能。
3、缓冲区满度与TBL的匹配程度。
4、跳帧数。
5、PSNR波动越小越好。
x264中码率控制的流程(对于重点函数在下面有注释):1.在进行编码时,Encode--->x264_encoder_open(主要是进行参数的修订设置,进行初始化)---->x264_ratecontrol_new2.encode--->Encode_frame--->x264_encoder_encode--->x264_ratecontrol_slice_type3.encode--->Encode_frame--->x264_encoder_encode--->x264_ratecontrol_start**************4.encode--->Encode_frame--->x264_encoder_encode--->x264_ratecontrol_qp5.encode--->Encode_frame--->x264_encoder_encode--->x264_slices_write--->x264_slice_write--->x264_ratecontrol_mb********************6.encode--->Encode_frame--->x264_encoder_encode--->x264_ratecontrol_end(在编完一帧过后)7.在编完过后,encode--->x264_encoder_close---->ratecontrol summary/x264_ratecontrol_delete函数注释:在编码中所用的编码方式:#define X264_RC_CQP 0#define X264_RC_CRF 1#define X264_RC_ABR 21.x264_ratecontrol_new( x264_t *h ){ // 获取RC方式,FPS,bitrate,rc->buffer_rate,rc->buffer_size// 在码率控制的时候会出现2pass,参数的初始化rc = h->rc;rc->b_abr = h->param.rc.i_rc_method != X264_RC_CQP && !h->param.rc.b_stat_read;rc->b_2pass = h->param.rc.i_rc_method == X264_RC_ABR && h->param.rc.b_stat_read; ..........if( h->param.rc.b_mb_tree )//这里设置mb_tree{h->param.rc.f_pb_factor = 1;rc->qcompress = 1;}elserc->qcompress = h->param.rc.f_qcompress;..............rc->ip_offset = 6.0 * log(h->param.rc.f_ip_factor) / log(2.0);rc->pb_offset = 6.0 * log(h->param.rc.f_pb_factor) / log(2.0);rc->qp_constant[SLICE_TYPE_P] = h->param.rc.i_qp_constant;rc->qp_constant[SLICE_TYPE_I] = x264_clip3( h->param.rc.i_qp_constant - rc->ip_offset + 0.5, 0, 51 ); rc->qp_constant[SLICE_TYPE_B] = x264_clip3( h->param.rc.i_qp_constant + rc->pb_offset + 0.5, 0, 51 );}2.int x264_ratecontrol_slice_type( x264_t *h, int frame_num ){//根据不同类型来获取不同的qp_constanth->param.rc.i_qp_constant = (h->stat.i_frame_count[SLICE_TYPE_P] == 0) ? 24: 1 + h->stat.f_frame_qp[SLICE_TYPE_P] / h->stat.i_frame_count[SLICE_TYPE_P];rc->qp_constant[SLICE_TYPE_P] = x264_clip3( h->param.rc.i_qp_constant, 0, 51 );rc->qp_constant[SLICE_TYPE_I] = x264_clip3( (int)( qscale2qp( qp2qscale( h->param.rc.i_qp_constant ) / fabs( h->param.rc.f_ip_factor )) + 0.5 ), 0, 51 );rc->qp_constant[SLICE_TYPE_B] =x264_clip3( (int)( qscale2qp( qp2qscale( h->param.rc.i_qp_constant ) * fabs( h->param.rc.f_pb_factor )) + 0.5 ), 0, 51 );}3.x264_ratecontrol_start( h, h->fenc->i_qpplus1, overhead*8 );这个函数的目的就是在一帧的编码前就选择QP/* Init the rate control *//* FIXME: Include slice header bit cost. */x264_ratecontrol_start( h, h->fenc->i_qpplus1, overhead*8 );对x264_ratecontrol_start函数的解析如下:x264_zone_t *zone = get_zone( h, h->fenc->i_frame );//找到h->fenc->i_frame所在的zone ....................//由各种不同的slice类型,vbv等等参数获取的q值if( i_force_qp ){q = i_force_qp - 1;//}else if( rc->b_abr ){q = qscale2qp( rate_estimate_qscale( h ) );//下面有注解}else if( rc->b_2pass ){rce->new_qscale = rate_estimate_qscale( h );q = qscale2qp( rce->new_qscale );}else /* CQP */{if( h->sh.i_type == SLICE_TYPE_B && h->fdec->b_kept_as_ref )q = ( rc->qp_constant[ SLICE_TYPE_B ] + rc->qp_constant[ SLICE_TYPE_P ] ) / 2;elseq = rc->qp_constant[ h->sh.i_type ];if( zone ){if( zone->b_force_qp )q += zone->i_qp - rc->qp_constant[SLICE_TYPE_P];elseq -= 6*log(zone->f_bitrate_factor)/log(2);}///////////////////////////////////////////////////////////////////* Terminology:* qp = h.264's quantizer* qscale = linearized quantizer = Lagrange multiplier*/static inline double qp2qscale(double qp){return 0.85 * pow(2.0, ( qp - 12.0 ) / 6.0);}static inline double qscale2qp(double qscale){return 12.0 + 6.0 * log(qscale/0.85) / log(2.0);}////////////////////////////////////////////////////////////////////////rate_estimate_qscale( h )// update qscale for 1 frame based on actual bits used so far(即根据所需BIT来计算qscale) static float rate_estimate_qscale( x264_t *h ){//这里是分别针对B,P帧分别进行,因为I帧是已经设定if( pict_type == SLICE_TYPE_B ){//这里B帧的q的大小是由参考帧求的..........................................// 由predict_size获得帧的sizercc->frame_size_planned = predict_size( rcc->pred_b_from_p, q, h->fref1[h->i_ref1-1]->i_satd ); x264_ratecontrol_set_estimated_size(h, rcc->frame_size_planned);//////////////////////////void x264_ratecontrol_set_estimated_size( x264_t *h, int bits ){x264_pthread_mutex_lock( &h->fenc->mutex );h->rc->frame_size_estimated = bits;///***********x264_pthread_mutex_unlock( &h->fenc->mutex );}////////////////////////////}////P帧的q值获取else{//这里的分有1pass和2pass的选择...................选择predicted_bits,求出diffdiff = predicted_bits - (int64_t)rce.expected_bits;q /= x264_clip3f((double)(abr_buffer - diff) / abr_buffer, .5, 2);}}4.int x264_ratecontrol_qp( x264_t *h ){return h->rc->qpm;}5.void x264_ratecontrol_mb( x264_t *h, int bits ){//这个函数主要是针对一行的bitsif( h->sh.i_type == SLICE_TYPE_B ){//由参考的图像求对应的行的qp,有已编码的bits获得此行的bits和qpint avg_qp = X264_MIN(h->fref0[0]->i_row_qp[y+1], h->fref1[0]->i_row_qp[y+1])+ rc->pb_offset * ((h->fenc->i_type == X264_TYPE_BREF) ? 0.5 : 1);rc->qpm = X264_MIN(X264_MAX( rc->qp, avg_qp), 51); //avg_qp could go higher than 51 due to pb_offseti_estimated = row_bits_so_far(h, y); //FIXME: compute full estimated sizeif (i_estimated > h->rc->frame_size_planned)x264_ratecontrol_set_estimated_size(h, i_estimated);}//I, p,这里还要参考缓冲区的状态else{//对I,P帧在考虑VBV的情况下求的bits和qp}}6./* After encoding one frame, save stats and update ratecontrol state */int x264_ratecontrol_end( x264_t *h, int bits ){///统计ipb类型的Mb的个数,并计算平均QPh->fdec->f_qp_avg_rc = rc->qpa_rc /= h->mb.i_mb_count;h->fdec->f_qp_avg_aq = rc->qpa_aq /= h->mb.i_mb_count;}7.void x264_ratecontrol_summary( x264_t *h ){x264_ratecontrol_t *rc = h->rc;//ABRif( rc->b_abr && h->param.rc.i_rc_method == X264_RC_ABR && rc->cbr_decay > .9999 ){double base_cplx = h->mb.i_mb_count * (h->param.i_bframe ? 120 : 80);double mbtree_offset = h->param.rc.b_mb_tree ? (1.0-h->param.rc.f_qcompress)*13.5 : 0;x264_log( h, X264_LOG_INFO, "final ratefactor: %.2f\n",qscale2qp( pow( base_cplx, 1 - rc->qcompress )* rc->cplxr_sum / rc->wanted_bits_window ) - mbtree_offset );}}/////////////////////////////void x264_ratecontrol_delete( x264_t *h )///////释放RC开辟的空间通过以上的流程总结x264码率控制的过程基本是有以下三步:1.对码率控制的相关变量进行初始化,如,I,P,B的初始QP值,RC的方式,VBV的初始状态等等;2.获取编码帧的复杂度,x264用SATD表示,对于采用的不同参数的码率控制的方式,由前面已编码的Bits,复杂度,目标比特的设置等一些条件来获取编码当前帧的qp值。