码率控制

合集下载

码率控制

码率控制
我们再来看,一组画面的码流大小跟什么有关?当视频编码的压缩方式都一样,清晰度要求都一样的时候,GOP组的长度格式决定了码流的大小,例如:每秒25帧画面,GOP组长度为5,那么帧格式为IBPBP,那么1秒钟有5个I帧,10个B帧,10个P帧,如果GOP组长度为15,帧格式就是IBBPBBPBBPBBPBB,那么1秒钟内会有2个I帧和16个B帧和7个P帧,那么5个I帧比2个I帧占用的数据信息量大,所以GOP组的长度格式也决定了码流的大小。
最后,我们再来看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码率控制公式是一种用于控制视频码率的公式,可以根据视频的内容和特性来动态地调整码率,以达到最佳的视觉质量和压缩效率。

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 常用均方差形式表示:

码率控制与实现算法

码率控制与实现算法
2016
码率控制技术原理与 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 压缩参数
H265即HEVC,是一种高效的视频压缩标准。

在H265压缩参数中,主要有码率控制、分片处理、帧率控制等部分:
1. 码率控制:通过调整码率,可以控制视频的压缩效果和传输带宽。

较低的码率可以降低视频的压缩效果,但能够节省带宽;较高的码率则可以提高视频质量,但需要更多的带宽。

2. 分片处理:分片处理可以有效地降低视频的码率,从而节省带宽。

通过将视频画面分割成若干个较小的片,并对每个片进行独立的编码和传输,可以实现更高的压缩效果。

3. 帧率控制:这是视频压缩的一个重要参数,它决定了视频的流畅度和清晰度。

帧率越高,视频越流畅,但所需的存储空间也越大。

此外,H265还支持多种分辨率的视频压缩,包括4K、1080p、720p等,可以根据不同的需求选择合适的分辨率进行压缩。

如需更多信息,建议查阅相关文献或咨询专业人士。

homerHEVC代码阅读(42)——码率控制

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中的码流控制。

码流控制是指控制音视频数据的传输速率,以确保在不同网络环境下的媒体播放的稳定性和流畅性。

在FFmpeg中,有几种方法可以实现码流控制。

1. 码率控制:码率控制是一种通过控制编码参数来控制输出媒体文件的码率的方法。

在FFmpeg中,可以通过设置编码器的参数,如码率(bitrate)、帧率(framerate)、关键帧间隔(gop size)等来控制输出文件的码率。

通过调整这些参数,可以实现对码率的精确控制。

2. 帧丢弃:在某些情况下,网络带宽不足或媒体播放设备性能有限,无法实时处理所有的音视频帧。

为了保证播放的连续性,可以通过在编码过程中丢弃一些帧来减少数据量。

在FFmpeg中,可以使用参数"-vf"或"-af"来进行帧丢弃,通过设置适当的帧丢弃策略,可以在保持播放连续性的前提下减少码流大小。

3. 媒体格式转换:码流控制还可以通过转换媒体文件的格式来实现。

对于某些网络环境下传输速率较慢的情况,可以通过将媒体文件转换为更高压缩率的格式,如从AVI转换为MP4,从WAV转换为AAC等,来减小数据量,从而实现码流控制。

需要注意的是,在进行码流控制时,需要综合考虑网络带宽、媒体文件质量要求和播放设备性能等因素,以达到合理的码流控制效果。

FFmpeg提供了丰富的参数和选项,可以根据实际情况进行调整和优化。

以上是关于FFmpeg中码流控制的简要说明,希望能对你有所帮助。

如有更多细节或相关问题,请随时提问。

CV181x CV180x 芯片码率控制使用说明说明书

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声明法律声明本数据手册包含北京晶视智能科技有限公司(下称“晶视智能”)的保密信息。

未经授权,禁止使用或披露本数据手册中包含的信息。

如您未经授权披露全部或部分保密信息,导致晶视智能遭受任何损失或损害,您应对因之产生的损失/损害承担责任。

通信技术中的码率控制与编解码技术

通信技术中的码率控制与编解码技术

通信技术中的码率控制与编解码技术通信技术的快速发展使得信息传输变得更加高效和便捷。

码率控制与编解码技术作为通信技术中的重要组成部分,扮演着不可或缺的角色。

本文将探讨码率控制与编解码技术在通信领域中的应用,并讨论其对通信系统性能的影响。

首先,我们来了解一下什么是码率控制。

码率控制是一种在数据传输过程中动态调整码率的技术。

它的主要目的是在保证数据传输质量的同时,尽可能高效地利用带宽资源。

在视频通信中,码率控制可以根据网络状况动态调整视频的传输码率,以保证视频质量。

另外,在音频通信中,也可以使用码率控制来调整音频的传输码率。

在通信领域中,编解码技术是一种将原始数据转换为可传输或存储的编码形式,并在接收端将编码后的数据解码回原始形式的技术。

编解码技术可以提高数据传输的效率和可靠性。

在数据传输过程中,原始数据经过编码后可以减少数据的冗余,并提高数据的压缩比,从而实现更高效的数据传输。

解码过程则是对接收到的编码数据进行还原,以便正确获取原始数据。

码率控制与编解码技术在通信系统中的应用非常广泛。

首先,它们在音视频通信中扮演着重要的角色。

例如,在实时视频通信中,码率控制技术可以根据网络带宽的变化,动态调整视频的传输码率,以保证视频的连续和流畅播放。

同时,编解码技术可以将视频进行压缩,降低数据传输的需求,提高网络传输的效率。

在音频通信中,码率控制和编解码技术也可以保证音频的实时传输和高质量播放。

其次,码率控制与编解码技术也在移动通信中得到广泛应用。

在移动通信中,网络带宽和资源有限,因此码率控制非常重要。

通过动态调整数据传输码率,可以在保证数据的传输质量的同时,尽可能地节省网络资源。

而移动通信中使用的编解码技术可以提高数据的压缩比,减少数据传输的带宽需求,从而提高整体的数据传输效率。

此外,码率控制与编解码技术在实时互动应用中也起到了关键作用。

在视频会议、在线游戏等实时互动应用中,码率控制可以根据网络延迟和带宽的变化,动态调整传输码率,以提供高质量的实时交流和游戏体验。

HM编码器代码阅读(29)——码率控制

HM编码器代码阅读(29)——码率控制

HM编码器代码阅读(29)——码率控制版权声明:本文为博主原创文章,未经博主允许不得转载。

https:///NB_vol_1/article/details/55096464码率控制介绍码率控制码率控制也叫速率控制,主要是控制编码后的比特率。

存在码率控制模块的原因是,有时候解码器处理的速度不够快、网络带宽不行,这些情况的存在要求我们必须减少数据的发送量(即比特率要变小),减少数据的发送量意味着我们要对数据进行更近一步的压缩,在编码器中就表现为量化参数QP的变化。

当满足一定码率要求的情况下,我们还需要让编码的失真尽量小。

码率控制的核心就是要确定量化参数QP。

如果不使用码率控制,那么量化参数QP就是自定义的或者根据需要选择码率控制是一级一级进行控制的,先分配图像组级(GOP)的比特数,然后分配图像级的比特数,再分配CTU级别的比特数。

利用已经分配的比特数来确定量化参数。

更多的细节请参考/nb_vol_1/article/details/53288902码率控制在HEVC中的实现码率控制流程在TEncCfg中有个布尔类型的m_RCEnableRateControl成员,它表示是否使用码率控制在HM中码率控制的流程是:1、在TEncTop::create中,定义了编码序列级别的码率控制1.if ( m_RCEnableRateControl )2.{3.// 码率控制器初始化4.m_cRateCtrl.init( m_framesToBeEncoded, m_RCTargetBitrate, m_iFrameRate, m_iGOPSize, m_iSourceWidth, m_iSourceHeight,5.g_uiMaxCUWidth, g_uiMaxCUHeight, m_RCKeepHierarchicalBit, m_RCUseLCUSeparateModel, m_GOPList );6.}2、在TEncTop::encode中,定义了图像组级别的码率控制1.if ( m_RCEnableRateControl )2.{3.m_cRateCtrl.initRCGOP( m_iNumPicRcvd );4.}1.if ( m_RCEnableRateControl )2.{3.m_cRateCtrl.destroyRCGOP();4.}3、在TEncGOP::compressGOP,定义了图像级别的码率控制m_pcRateCtrl->initRCPic( frameLevel );4、在TEncSlice::compressSlice()中,设置CTU(LCU)级别的码率控制参数1.if ( m_pcCfg->getUseRateCtrl() )2.{3.Int estQP = pcSlice->getSliceQp();4.Double estLambda = -1.0;5.Double bpp = -1.0;7.if( ( rpcPic->getSlice( 0)->getSliceType() == I_SLICE && m_pcCfg->getForceIntraQP() ) || !m_pcCfg->getLCULevelRC() )8.{9.estQP = pcSlice->getSliceQp();10.}11.else12.{13.bpp = m_pcRateCtrl->getRCPic()->getLCUT argetBpp(pcSlice->getSli ceType());14.if( rpcPic->getSlice( 0)->getSliceType() == I_SLICE)15.{16.estLambda = m_pcRateCtrl->getRCPic()->getLCUEstLambdaAndQP(bpp, pcSlice->getSliceQp(), &estQP);17.}18.else19.{20.estLambda = m_pcRateCtrl->getRCPic()->getLCUEstLambda( bpp );21.estQP = m_pcRateCtrl->getRCPic()->getLCUEstQP ( estLambda, pcSlice->getSliceQp() );22.}23.24.estQP = Clip3( -pcSlice->getSPS()->getQpBDOffsetY(), MAX_QP, estQP );26.m_pcRdCost->setLambda(estLambda);27.#if RDOQ_CHROMA_LAMBDA28.// set lambda for RDOQ29.Doubleweight=m_pcRdCost->getChromaWeight();30.const Double lambdaArray[3] = { estLambda, (estLambda / weight), (estLambda / weight) };31.m_pcTrQuant->setLambdas( lambdaArray );32.#else33.m_pcTrQuant->setLambda( estLambda );34.#endif35.}36.37.m_pcRateCtrl->setRCQP( estQP );38.#if ADAPTIVE_QP_SELECTION39.pcCU->getSlice()->setSliceQpBase( estQP );40.#endif41.}5、在TEncSlice::compressSlice中,编码完成一个CTU之后,需要更新剩余比特数等相关的参数1.if ( m_pcCfg->getUseRateCtrl() )2.{3.4.Int actualQP = g_RCInvalidQPValue;5.Double actualLambda = m_pcRdCost->getLambda();6.Int actualBits = pcCU->getTotalBits();7.Int numberOfEffectivePixels = 0;8.for ( Int idx = 0; idx < rpcPic->getNumPartInCU();idx++ )9.{10.if( pcCU->getPredictionMode( idx ) != MODE_NONE && ( !pcCU->isSkipped( idx ) ) )11.{12.numberOfEffectivePixels = numberOfEffectivePixels + 16;13.break;14.}15.}16.17.if ( numberOfEffectivePixels == 0 )18.{19.actualQP = g_RCInvalidQPValue;20.}21.else22.{23.actualQP = pcCU->getQP( 0 );24.}25.m_pcRdCost->setLambda(oldLambda);26.27.m_pcRateCtrl->getRCPic()->updateAfterLCU( m_p cRateCtrl->getRCPic()->getLCUCoded(), actualBits, actualQP, actualLambda,28.pcCU->getSlice()->getSliceType() == I_SLICE ? 0 : m_pcCfg->getLCULevelRC() );29.}6、在TEncGOP::compressGOP中,每编码完成一个图像,就更新剩余比特数等码率控制相关的参数1.if ( m_pcCfg->getUseRateCtrl() )2.{3.Double avgQP = m_pcRateCtrl->getRCPic()->calAverageQP();4.Double avgLambda = m_pcRateCtrl->getRCPic()->calAverageLambda();5.if ( avgLambda < 0.0 )6.{7.avgLambda = lambda;8.}9.m_pcRateCtrl->getRCPic()->updateAfterPicture( a ctualHeadBits, actualTotalBits, avgQP, avgLambda, pcSlice->getSliceType());10.m_pcRateCtrl->getRCPic()->addToPictureLsit( m_ pcRateCtrl->getPicList() );11.12.m_pcRateCtrl->getRCSeq()->updateAfterPic( actu alTotalBits );13.if ( pcSlice->getSliceType() != I_SLICE )14.{15.m_pcRateCtrl->getRCGOP()->updateAfterPicture( actualT otalBits );16.}17.else// for intra picture, the estimated bits are used to update the current status in the GOP18.{19.m_pcRateCtrl->getRCGOP()->updateAfterPicture( estimatedBits );20.}21.}码率控制的相关结构CTU(LCU)级别的码率控制结构1./*2.** LCU(CTU)级别的码率控制信息3.*/4.struct TRCLCU5.{6.// 实际比特数7.Int m_actualBits;8.// 相应的QP9.Int m_QP; // QP of skip mode is set to g_RCInvalidQPValue10.// 目标比特数11.Int m_targetBits;12.// lambda参数13.Double m_lambda;14.// 比特权重15.Double m_bitWeight;16.// 像素的数量17.Int m_numberOfPixel;18.// 帧内的代价19.Double m_costIntra;20.// 剩余的比特数(目标的剩余比特数)21.Int m_targetBitsLeft;22.};码率参数结构1./*2.** 码率控制参数!3.*/4.struct TRCParameter5.{6.Double m_alpha; // alpha参数7.Double m_beta; // beta参数8.};编码序列级别的码率控制结构1./*2.** seq序列级别(级别比gop高)的码率控制3.*/4.class TEncRCSeq5.{6.public:7.TEncRCSeq();8.~TEncRCSeq();9.10.public:11.Void create( Int totalFrames, Int targetBitrate, Int frameRate, Int GOPSize, Int picWidth, Int picHeight, Int LCUWidth, Int LCUHeight, Int numberOfLevel, Bool useLCUSeparateModel, Int adaptiveBit );12.Void destroy();13.14.// 初始化比特率15.Void initBitsRatio( Int bitsRatio[] );16.// 初始化gop到level的映射17.Void initGOPID2Level( Int GOPID2Level[] );18.// 初始化pic的码率控制参数19.Void initPicPara( TRCParameter* picPara = NULL ); // NULL to initial with default value20.// 初始化LCU的码率控制参数21.Void initLCUPara( TRCParameter** LCUPara = NULL ); // NULL to initial with default value22.// 在处理完一帧之后更新23.Void updateAfterPic ( Int bits );24.// 设置总得比特率25.Void setAllBitRatio( Double basicLambda, Double* equaCoeffA, Double* equaCoeffB );26.27.public:28.Int getTotalFrames() { returnm_totalFrames; }29.Int getTargetRate() { return m_targetRate; }30.Int getFrameRate() { return m_frameRate; }31.Int getGOPSize() { return m_GOPSize; }32.Int getPicWidth() { return m_picWidth; }33.Int getPicHeight() { return m_picHeight; }34.Int getLCUWidth() { return m_LCUWidth; }35.Int getLCUHeight() { returnm_LCUHeight; }36.Int getNumberOfLevel() { returnm_numberOfLevel; }37.Int getAverageBits() { returnm_averageBits; }38.Int getLeftAverageBits() { assert( m_framesLeft > 0); return(Int)(m_bitsLeft /m_framesLeft); }39.Bool getUseLCUSeparateModel() { returnm_useLCUSeparateModel; }40.41.Int getNumPixel() { returnm_numberOfPixel; }42.Int64 getTargetBits() { return m_targetBits; }43.Int getNumberOfLCU() { returnm_numberOfLCU; }44.Int* getBitRatio() { return m_bitsRatio; }45.Int getBitRatio( Int idx ){ assert( idx<m_GOPSize); return m_bitsRatio[idx]; }46.Int* getGOPID2Level() { returnm_GOPID2Level; }47.Int getGOPID2Level( Int ID ) { assert( ID <m_GOPSize ); return m_GOPID2Level[ID]; }48.TRCParameter* getPicPara() { return m_picPara; }49.TRCParameter getPicPara( Int level ) { assert( level < m_numberOfLevel ); return m_picPara[level]; }50.Void setPicPara( Int level, TRCParameter para ){ assert( level < m_numberOfLevel ); m_picPara[level] = para; }51.TRCParameter** getLCUPara() { return m_LCUPara; }52.TRCParameter* getLCUPara( Int level ) { assert( level < m_numberOfLevel ); return m_LCUPara[level]; }53.TRCParameter getLCUPara( Int level, Int LCUIdx ){ assert( LCUIdx < m_numberOfLCU ); return getLCUPara(level)[LCUIdx]; }54.Void setLCUPara( Int level, Int LCUIdx, TRCParameter para ) { assert( level < m_numberOfLevel );assert( LCUIdx < m_numberOfLCU ); m_LCUPara[level][LCUIdx]= para; }55.56.Int getFramesLeft() { return m_framesLeft; }57.Int64 getBitsLeft() { return m_bitsLeft; }58.59.Double getSeqBpp() { return m_seqTargetBpp; }60.Double getAlphaUpdate() { return m_alphaUpdate; }61.Double getBetaUpdate() { return m_betaUpdate; }62.63.Int getAdaptiveBits() { return m_adaptiveBit; }64.Double getLastLambda() { return m_lastLambda; }65.Void setLastLambda( Double lamdba ) { m_lastLambda = lamdba; }66.67.private:68.// 总的帧数69.Int m_totalFrames;70.// 目标码率71.Int m_targetRate;72.// 帧率73.Int m_frameRate;74.// gop的大小75.Int m_GOPSize;76.// 帧宽和高77.Int m_picWidth;78.Int m_picHeight;79.// LCU的宽和高80.Int m_LCUWidth;81.Int m_LCUHeight;82.// level的数量83.Int m_numberOfLevel;84.// 平均的比特数85.Int m_averageBits;86.87.// 像素的数量88.Int m_numberOfPixel;89.// 目标比特数90.Int64 m_targetBits;91.// LCU的数量92.Int m_numberOfLCU;93.// 比特率94.Int* m_bitsRatio;95.// gop的id到level的映射96.Int* m_GOPID2Level;97.// pic的码率控制参数98.TRCParameter* m_picPara;99.// LCU的码率控制参数100.TRCParameter** m_LCUPara; 101.102.// 剩余的帧数103.Int m_framesLeft;104.// 剩余的比特数105.Int64 m_bitsLeft;106.Double m_seqTargetBpp; 107.// alpha参数的更新108.Double m_alphaUpdate; 109.// beta参数的更新110.Double m_betaUpdate;111.// 是否使用LCU分开的模型112.Bool m_useLCUSeparateModel;113.114.// 自适应的比特115.Int m_adaptiveBit;116.// 最后的lambda参数117.Double m_lastLambda;118.};图像组(gop)级别的码率控制1./*2.** GOP级别的码率控制3.*/4.class TEncRCGOP5.{6.public:7.TEncRCGOP();8.~TEncRCGOP();9.10.public:11.Void create( TEncRCSeq* encRCSeq, Int numPic );12.Void destroy();13.14.// 在处理完一帧之后更新15.Void updateAfterPicture( Int bitsCost );16.17.private:18.// 预估一个gop占用的比特数19.Int xEstGOPTargetBits( TEncRCSeq* encRCSeq, Int GOPSize );20.Void xCalEquaCoeff( TEncRCSeq* encRCSeq, Double* lambdaRatio, Double* equaCoeffA, Double* equaCoeffB, Int GOPSize );21.Double xSolveEqua( Double targetBpp, Double* equaCoeffA, Double* equaCoeffB, Int GOPSize );22.23.public:24.TEncRCSeq* getEncRCSeq() { return m_encRCSeq; }25.Int getNumPic() { return m_numPic;}26.Int getTargetBits() { return m_targetBits; }27.Int getPicLeft() { return m_picLeft; }28.Int getBitsLeft() { return m_bitsLeft; }29.Int getTargetBitInGOP( Int i ) { return m_picTargetBitInGOP[i]; }30.31.private:32.// 所属的码率控制序列33.TEncRCSeq* m_encRCSeq;34.// 该gop中,每一帧的目标比特数35.Int* m_picTargetBitInGOP;36.// 帧数量37.Int m_numPic;38.// gop总的目标比特数39.Int m_targetBits;40.// 还剩多少帧处理完成41.Int m_picLeft;42.// 还剩多少比特43.Int m_bitsLeft;44.};图像级别的码率控制对象1./*2.** 图像级别的码率控制3.*/4.class TEncRCPic5.{6.public:7.TEncRCPic();8.~TEncRCPic();9.10.public:11.Void create( TEncRCSeq* encRCSeq, TEncRCGOP* encRCGOP, Int frameLevel, list<TEncRCPic*>& listPreviousPictures );12.Void destroy();13.14.Int estimatePicQP( Double lambda, list<TEncRCPic*>& listPreviousPictures );15.Int getRefineBitsForIntra(Int orgBits);16.Double calculateLambdaIntra(double alpha, double beta, double MADPerPixel, double bitsPerPixel);17.Double estimatePicLambda( list<TEncRCPic*>& listPreviousPictures, SliceType eSliceType);18.19.Void updateAlphaBetaIntra(double*alpha, double *beta);20.21.Double getLCUTargetBpp(SliceType eSliceType);22.Double getLCUEstLambdaAndQP(Double bpp, IntclipPicQP, Int *estQP);23.Double getLCUEstLambda( Double bpp );24.Int getLCUEstQP( Double lambda, Int clipPicQP );25.26.Void updateAfterLCU( Int LCUIdx, Int bits, Int QP,Double lambda, Bool updateLCUParameter = true );27.Void updateAfterPicture( Int actualHeaderBits, IntactualT otalBits, Double averageQP, Double averageLambda, SliceType eSliceType);28.29.Void addToPictureLsit( list<TEncRCPic*>& listPreviousPictures );30.Double calAverageQP();31.Double calAverageLambda();32.33.private:34.Int xEstPicTargetBits( TEncRCSeq* encRCSeq, TEncRCGOP* encRCGOP );35.Int xEstPicHeaderBits( list<TEncRCPic*>& listPreviousPictures, Int frameLevel );36.37.public:38.TEncRCSeq* getRCSequence() { return m_encRCSeq; }39.TEncRCGOP* getRCGOP() { returnm_encRCGOP; }40.41.Int getFrameLevel() { returnm_frameLevel; }42.Int getNumberOfPixel() { returnm_numberOfPixel; }43.Int getNumberOfLCU() { returnm_numberOfLCU; }44.Int getTargetBits() { returnm_targetBits; }45.Int getEstHeaderBits() { returnm_estHeaderBits; }46.Int getLCULeft() { returnm_LCULeft; }47.Int getBitsLeft() { returnm_bitsLeft; }48.Int getPixelsLeft() { returnm_pixelsLeft; }49.Int getBitsCoded() { returnm_targetBits - m_estHeaderBits - m_bitsLeft; }50.Int getLCUCoded() { returnm_numberOfLCU - m_LCULeft; }51.TRCLCU* getLCU() { returnm_LCUs; }52.TRCLCU& getLCU( Int LCUIdx ) { return m_LCUs[LCUIdx]; }53.Int getPicActualHeaderBits() { returnm_picActualHeaderBits; }54.Void setTargetBits( Int bits ) { m_targetBits = bits; m_bitsLeft = bits;}55.Void setTotalIntraCost(Double cost) { m_totalCostIntra = cost; }56.Void getLCUInitTargetBits();57.58.Int getPicActualBits() { returnm_picActualBits; }59.Int getPicActualQP() { returnm_picQP; }60.Double getPicActualLambda() { return m_picLambda; }61.Int getPicEstQP() { returnm_estPicQP; }62.Void setPicEstQP( Int QP ) { m_estPicQP = QP; }63.Double getPicEstLambda() { returnm_estPicLambda; }64.Void setPicEstLambda( Double lambda ) { m_picLambda = lambda; }65.66.private:67.// 所属的码率控制序列68.TEncRCSeq* m_encRCSeq;69.// 所属的码率控制gop70.TEncRCGOP* m_encRCGOP;71.72.// 帧的level73.Int m_frameLevel;74.// 像素的数量75.Int m_numberOfPixel;76.// LCU的数量77.Int m_numberOfLCU;78.// 目标比特数79.Int m_targetBits;80.// 帧头部/slice头部等占用的比特数81.Int m_estHeaderBits;82.// 预估的帧的qp83.Int m_estPicQP;84.// 预估的lambda85.Double m_estPicLambda;86.87.// 剩下的LCU的数量88.Int m_LCULeft;89.// 剩下的比特数量90.Int m_bitsLeft;91.// 剩下的像素数量92.Int m_pixelsLeft;93.94.// 该帧对应的LCU码率控制对象95.TRCLCU* m_LCUs;96.// 真实的头部占用的比特数97.Int m_picActualHeaderBits; // only SH and potential APS98.// 帧内模式消耗的比特数99.Double m_totalCostIntra;100.// 帧内模式还剩余的比特数101.Double m_remainingCostIntra;102.// 帧真实占用的比特数103.Int m_picActualBits; // the whole picture, including header104.// 帧的qp105.Int m_picQP; // in integer form106.// 帧的lambda参数107.Double m_picLambda;108.};码率控制对象1./*2.** 码率控制管理器3.** 管理了TEncRCSeq TEncRCGOP TEncRCPic等对象4.*/5.class TEncRateCtrl6.{7.public:8.TEncRateCtrl();9.~TEncRateCtrl();10.11.public:12.Void init( Int totalFrames, Int targetBitrate, Int frameRate, Int GOPSize, Int picWidth, Int picHeight, Int LCUWidth, Int LCUHeight, Int keepHierBits, Bool useLCUSeparateModel, GOPEntry GOPList[MAX_GOP] );13.Void destroy();14.Void initRCPic( Int frameLevel );15.Void initRCGOP( Int numberOfPictures );16.Void destroyRCGOP();17.18.public:19.Void setRCQP ( Int QP ) { m_RCQP = QP; }20.Int getRCQP () { return m_RCQP; }21.TEncRCSeq* getRCSeq() { assert ( m_encRCSeq != NULL ); return m_encRCSeq; }22.TEncRCGOP* getRCGOP() { assert ( m_encRCGOP != NULL ); return m_encRCGOP; }23.TEncRCPic* getRCPic() { assert ( m_encRCPic != NULL ); return m_encRCPic; }24.list<TEncRCPic*>& getPicList() { returnm_listRCPictures; }25.26.private:27.// 当前的码率控制序列28.TEncRCSeq* m_encRCSeq;29.// 当前码率控制gop30.TEncRCGOP* m_encRCGOP;31.// 当前对应的码率控制pic32.TEncRCPic* m_encRCPic;33.// TEncRCPic列表(应该是一个gop中/或者一个序列中的所有帧)34.list<TEncRCPic*> m_listRCPictures;35.// qp参数36.Int m_RCQP;37.};码率控制是怎么样控制比特率的首先我们找到码率控制初始化函数TEncRateCtrl::initTEncRateCtrl::initRCGOP用于图像组级别的码率控制的初始化,实际初始化在TEncRCGOP::create中,其中调用了一个比较重要的函数是xEstGOPTargetBits,用于估计GOP占用的比特数TEncRateCtrl::initRCPic,图像级别的码率控制的初始化,实际调用TEncRCGOP::create这几个初始化函数的大致功能都是比特率分配,即每一帧多少比特、每一个CTU多少个比特之类的这些都没有什么看头,最重要的是看码率控制在HEVC中怎么样和编码器结合起来的重点1——计算QP:在TEncSlice::compressSlice中(1)获取bpp(bits per pixel),通过getLCUTargetBpp得到(2)获取Lambda参数,通过bpp等参数调用getLCUEstLambda得到(3)获取码率控制对象计算出的QP,通过Lambda和slice的QP等参数调用getLCUEstQP得到(4)把计算出来的QP保存起来,调用setRCQP1.if ( m_pcCfg->getUseRateCtrl() )2.{3.Int estQP = pcSlice->getSliceQp();4.Double estLambda = -1.0;5.Double bpp = -1.0;6.7.if( ( rpcPic->getSlice( 0)->getSliceType() == I_SLICE && m_pcCfg->getForceIntraQP() ) || !m_pcCfg->getLCULevelRC() )8.{9.estQP = pcSlice->getSliceQp();10.}11.else12.{13.bpp = m_pcRateCtrl->getRCPic()->getLCUT argetBpp(pcSlice->getSli ceType());14.if( rpcPic->getSlice( 0)->getSliceType() == I_SLICE)15.{16.estLambda = m_pcRateCtrl->getRCPic()->getLCUEstLambdaAndQP(bpp, pcSlice->getSliceQp(), &estQP);17.}18.else19.{20.estLambda = m_pcRateCtrl->getRCPic()->getLCUEstLambda( bpp );21.estQP = m_pcRateCtrl->getRCPic()->getLCUEstQP ( estLambda, pcSlice->getSliceQp() );22.}23.24.estQP = Clip3( -pcSlice->getSPS()->getQpBDOffsetY(), MAX_QP, estQP );25.26.m_pcRdCost->setLambda(estLambda);27.#if RDOQ_CHROMA_LAMBDA28.// set lambda for RDOQ29.Doubleweight=m_pcRdCost->getChromaWeight();30.const Double lambdaArray[3] = { estLambda, (estLambda / weight), (estLambda / weight) };31.m_pcTrQuant->setLambdas( lambdaArray );32.#else33.m_pcTrQuant->setLambda( estLambda );34.#endif35.}36.37.m_pcRateCtrl->setRCQP( estQP );38.#if ADAPTIVE_QP_SELECTION39.pcCU->getSlice()->setSliceQpBase( estQP );40.#endif41.}重点2——把计算出来的QP应用到编码上:在TEncCu::xCompressCU中(1)把iMinQP设置为通过码率控制计算出来的QP(调用getRCQP)(2)把iMaxQP设置为通过码率控制计算出来的QP(调用getRCQP)(3)然后利用iMinQP和iMaxQP进行编码1.// 使用码率控制2.// 注意这里的QP使用了,码率控制对象计算出来的QP3.// 通过QP,码率控制对象控制了编码器的比特率4.if ( m_pcEncCfg->getUseRateCtrl() )5.{6.iMinQP = m_pcRateCtrl->getRCQP();7.iMaxQP = m_pcRateCtrl->getRCQP();重点3——根据比特率动态调整:(1)编码一个CTU或者图像之后,可以得到它占用的比特数(2)调用updateAfterLCU/updateAfterPicture,更新剩余比特数、Lambda等相关参数下一次计算QP的时候就利用这些参数重新计算,就能够自适应的改变比特率1.if ( m_pcCfg->getUseRateCtrl() )2.{3.4.Int actualQP = g_RCInvalidQPValue;5.Double actualLambda = m_pcRdCost->getLambda();6.Int actualBits = pcCU->getTotalBits();7.Int numberOfEffectivePixels = 0;8.for ( Int idx = 0; idx < rpcPic->getNumPartInCU(); idx++ )9.{10.if( pcCU->getPredictionMode( idx ) != MODE_NONE && ( !pcCU->isSkipped( idx ) ) )11.{12.numberOfEffectivePixels = numberOfEffectivePixels + 16;13.break;14.}15.}16.17.if ( numberOfEffectivePixels == 0 )19.actualQP = g_RCInvalidQPValue;20.}21.else22.{23.actualQP = pcCU->getQP( 0 );24.}25.m_pcRdCost->setLambda(oldLambda);26.27.m_pcRateCtrl->getRCPic()->updateAfterLCU( m_p cRateCtrl->getRCPic()->getLCUCoded(), actualBits, actualQP, actualLambda,28.pcCU->getSlice()->getSliceType() == I_SLICE ? 0 : m_pcCfg->getLCULevelRC() );29.}1.if ( m_pcCfg->getUseRateCtrl() )2.{3.Double avgQP = m_pcRateCtrl->getRCPic()->calAverageQP();4.Double avgLambda = m_pcRateCtrl->getRCPic()->calAverageLambda();5.if ( avgLambda < 0.0 )6.{7.avgLambda = lambda;8.}9.m_pcRateCtrl->getRCPic()->updateAfterPicture( a ctualHeadBits, actualTotalBits, avgQP, avgLambda, pcSlice->getSliceType());10.m_pcRateCtrl->getRCPic()->addToPictureLsit( m_ pcRateCtrl->getPicList() );12.m_pcRateCtrl->getRCSeq()->updateAfterPic( actu alTotalBits );13.if ( pcSlice->getSliceType() != I_SLICE )14.{15.m_pcRateCtrl->getRCGOP()->updateAfterPicture( actualT otalBits );16.}17.else// for intra picture, the estimated bits are used to update the current status in the GOP18.{19.m_pcRateCtrl->getRCGOP()->updateAfterPicture( estimatedBits );20.}21.}。

数字音视频技术:码率控制

数字音视频技术:码率控制

数字⾳视频技术:码率控制⼀. 概述1.1 来源及其作⽤为什么要使⽤码率控制?这个问题是由现实产⽣的。

在传输压缩编码视频的时候,必须要考虑两个问题:视频质量和传输带宽,如果带宽⼤,肯定要尽可能传输质量更好的视频;如果带宽低,则需要提⾼压缩⽐,减⼩码流;如果带宽动态变化,那么码流也需要动态改变来适应带宽,总之,码流与带宽紧密相关。

与此同时,我们希望尽可能的得到⾼清晰的还原图像,所以在能接受的视频质量范围内对视频尽可能的压缩来提⾼带宽利⽤率是码率控制的根本。

码率控制的来源知道以后,它的作⽤也就很明显,就是提⾼带宽利⽤率,在保持视频还原清晰度的情形下,尽可能的节省带宽。

视频编码(有损)的⽬标是尽可能多的节省⽐特(码率)的同时尽量保持视频质量,码率控制是平衡码率和质量的重要⼯具。

1.2 ⾯临的问题码率控制是个说起来简单做起来的事情。

之前已经总结过,可以从两个⽅⾯来理解码率控制,⼀是从内容的率失真优化⾓度考虑量化与码率关系,⼆是从信道传输和转移概率的⾓度来分析码率和编码模式的关系。

这两个⽅向都有同样的⼀个问题,与“先有鸡还是先有蛋”类似。

以QP和R的关系为例,为了得到可控的码流,我们需要提前控制QP,但是QP⼜依赖码流来计算给出,所以这个先后问题变成⼀个死循环,需要找到⼀个突破点。

1.3 主要发展为了解决先有鸡还是先有蛋的问题,我们找到⼀个突破⼝,既然理论的⽅法被证明是很难⾛通,那么可以选择⾛数值模拟的⽅法,通过⼀系列的实验,得到⼀系列的经验公式,尤其是选取⼀个合适的初始值,进⽽破解鸡还是蛋的问题。

在选择实验模拟这条路之后,突然有了很多的思路可以去做,⾸先是和理论结合最紧密的部分:概率分布。

通过计算不同概率分布下的率失真函数,得到⼀系列经验公式和参考模型,在利⽤DCT变化对亮度和⾊度系数进⾏处理后,最优模拟是拉普拉斯分布以及⼀部分⾼斯分布。

通过计算可以得到常⽤的6中R-D模型,⽽这些基础模型⼜被进⼀步演化成不同的码率控制算法。

vbr码率控制公式

vbr码率控制公式

vbr码率控制公式摘要:1.VBR 码率控制公式的概述2.VBR 码率控制公式的计算方法3.VBR 码率控制公式的应用实例4.VBR 码率控制公式的优点与局限性正文:一、VBR 码率控制公式的概述VBR(Variable Bitrate)即可变比特率,是一种在数字音频压缩技术中常见的码率控制方式。

它可以根据音频信号的复杂程度实时调整编码的码率,从而在保证音频质量的同时降低存储空间和传输带宽的需求。

VBR 码率控制公式是一种计算音频编码码率的方法,适用于各种音频压缩格式,如MP3、AAC 等。

二、VBR 码率控制公式的计算方法VBR 码率控制公式的计算通常基于音频信号的复杂程度,主要通过分析音频信号的频谱特性来实现。

常见的计算方法有以下几种:1.采用平均音量法:通过计算音频信号的平均音量,得到一个相对稳定的码率参考值。

此方法简单易行,但对音频信号的动态范围较大的情况处理不够理想。

2.采用峰值音量法:通过计算音频信号的峰值音量,得到一个较高的码率参考值。

此方法适用于动态范围较大的音频信号,但计算复杂度较高。

3.采用自适应方法:结合平均音量法和峰值音量法,根据音频信号的实时变化动态调整码率参考值。

此方法综合了前两种方法的优点,适用于各种类型的音频信号。

三、VBR 码率控制公式的应用实例以MP3 音频格式为例,VBR 码率控制公式可以应用于音频编码过程中的码率控制。

在MP3 编码器中,可以根据VBR 码率控制公式计算出的码率参考值,采用相应的量化参数来调整音频信号的编码码率。

这样,在保证音频质量的同时,可以有效地降低音频文件的存储空间和传输带宽需求。

四、VBR 码率控制公式的优点与局限性VBR 码率控制公式的优点在于,可以根据音频信号的实时变化动态调整编码码率,从而实现音频质量与存储空间的平衡。

此外,VBR 码率控制公式适用于各种音频压缩格式,具有较好的通用性。

然而,VBR 码率控制公式也存在一定的局限性。

基于H.264的码率控制算法

基于H.264的码率控制算法

基于H.264的码率控制算法基于H.264的码率控制算法一、前言随着数字视频通信和视频编码技术的快速发展,H.264编码已成为目前最流行的视频编码标准之一。

为了实现高质量的视频传输和存储,码率控制算法被广泛应用于H.264编码中。

本文将重点探讨基于H.264的码率控制算法。

二、H.264编码简介H.264编码是一种视频压缩技术,通过减少冗余信息以及利用空间和时间相关性来达到数据压缩的目的。

H.264编码算法具有出色的画质表现和高压缩比。

然而,由于视频传输和存储资源有限,需要对视频流的码率进行控制以适应特定的需求。

三、码率控制算法1. 码率控制概述码率控制是指根据特定的应用需求,通过调整编码参数来控制视频编码的码率。

码率控制算法能够根据输入的视频源和目标码率生成合适的视频码流。

常见的码率控制算法包括恒定码率(CBR)、可变码率(VBR)和动态码率(DRC)。

2. CBR码率控制CBR码率控制算法固定每个视频帧的码率,将帧间码率均匀分配,保持恒定的传输速率。

这种算法适用于对传输延迟和网络带宽要求较高的应用,如实时视频通话等。

然而,CBR码率控制算法对于视频中的运动场景和细节丰富的部分可能会出现压缩失真。

3. VBR码率控制VBR码率控制算法根据视频内容的复杂程度动态调整每个视频帧的码率。

在静止或低运动的场景中,VBR算法会降低码率以减少冗余信息的传输,而在高运动的场景中会提高码率以保持画质。

VBR算法可以更好地适应视频内容的变化,但在网络带宽不稳定的情况下,可能会导致传输延迟或视频卡顿。

4. DRC码率控制DRC码率控制算法是基于H.264标准的一种动态码率控制方法,它通过监测编码器的缓冲区状态和网络的带宽情况来动态地调整码率。

当网络带宽较大时,DRC算法会增加码率以提高视频质量,而当网络带宽较小时,DRC算法会降低码率以保持视频的连续性。

DRC算法能够更好地适应网络环境的变化,提供更好的用户体验。

vbr码率控制公式

vbr码率控制公式

vbr码率控制公式
摘要:
1.引言
2.VBR 码率控制公式的定义
3.VBR 码率控制公式的应用
4.VBR 码率控制公式的优点与局限性
5.总结
正文:
视频比特率控制(VBR)是一种广泛应用于视频压缩领域的技术,它能够在保持视频质量的前提下,有效地控制视频文件的大小。

VBR 码率控制公式是VBR 技术的核心,它通过计算视频的复杂度和画面变化程度来动态调整码率。

VBR 码率控制公式如下:
码率(kbps)= 视频复杂度(V)× 画面变化程度(A)× 1.25
其中,视频复杂度(V)是根据视频中的画面细节、色彩丰富程度等因素来评估的,画面变化程度(A)则是根据视频中场景的动态变化来评估的。

这个公式能够根据视频内容的复杂性和变化程度来动态调整码率,从而在保证视频质量的前提下,实现对视频文件大小的有效控制。

VBR 码率控制公式广泛应用于各种视频压缩格式中,如H.264/AVC、MPEG-4 等。

这些格式通过对视频内容进行实时分析,动态调整码率,从而在保证视频质量的前提下,实现对视频文件大小的有效控制。

然而,VBR 码率控制公式也存在一些局限性。

首先,它对视频内容的复杂
度和画面变化程度的评估可能不够准确,从而导致码率控制效果不佳。

其次,由于公式中的系数1.25 的存在,VBR 码率控制公式可能会使视频的码率略高于实际需要的码率,从而造成一定的资源浪费。

总的来说,VBR 码率控制公式是一种在保证视频质量的前提下,有效控制视频文件大小的技术。

动态平衡码率和固定码率

动态平衡码率和固定码率

动态平衡码率和固定码率1.引言1.1 概述概述部分的内容:动态平衡码率和固定码率是在数字通信领域中常用的两种码率控制技术。

在数据传输过程中,码率是指单位时间内传输的比特数。

动态平衡码率和固定码率在不同的场景下具有不同的特点和应用优势。

动态平衡码率是一种自适应的码率控制技术,它根据网络传输的情况和带宽的变化,动态地调整传输的码率。

这种技术可以根据网络的负载情况和实时带宽的变化,自动进行码率的调整,以保证数据传输的稳定性和效率。

动态平衡码率的应用场景主要包括实时视频传输、视频会议、移动通信等。

固定码率则是指在传输过程中始终保持不变的码率。

这种方式下,数据传输的速率始终保持不变,不受网络负载的影响。

固定码率的应用场景包括网络直播、点对点传输等相对稳定的数据传输场景。

动态平衡码率和固定码率各有其优势和限制。

动态平衡码率能够根据网络状况灵活调整码率,从而提供更好的视频传输质量和用户体验。

而固定码率则适用于网络稳定的场景,能够以恒定的码率保证数据的连续性和稳定性。

本文将对动态平衡码率和固定码率的定义和原理进行详细讨论,探究它们在不同场景下的应用,以及它们之间的比较和优劣势。

最后,我们还将展望未来,分析动态平衡码率和固定码率在通信技术发展中的趋势和前景。

1.2 文章结构文章结构部分的内容可以这样写:文章结构部分旨在介绍本文的整体组织和章节划分。

通过清晰的结构安排,读者可以更好地理解文章的主题和内容。

本文主要围绕动态平衡码率和固定码率展开讨论。

第一部分为引言部分,引言部分包括概述、文章结构以及目的。

在概述中,我们将简要介绍动态平衡码率和固定码率的概念和背景。

在文章结构部分,我们将详细介绍整个文章的组织结构和各章节的主题。

最后,在目的部分,我们将阐明本文的目的和意义。

第二部分是正文部分,正文部分将会详细探讨动态平衡码率和固定码率。

在2.1节中,将对动态平衡码率进行定义和原理的解释,并探讨其应用场景和优势。

在2.2节中,则会对固定码率进行定义和原理的解释,并讨论其应用场景和限制。

编码效率 传输效率 cpri 控制

编码效率 传输效率 cpri 控制
Page 16
(六)素描头像的三个阶段:
1、大体阶段。
先观察,首先看对象的特征, 先观察,首先看对象的特征, 主要任务是整体入手, 主要任务是整体入手,安排 构图、定位置、 构图、定位置、确定结构轮 廓用长短不一的直线, 廓用长短不一的直线,要求 动势、 动势、头、颈比例和基本型 正确, 正确,画出大的明暗交界线 及投影位置。 及投影位置。
Page 5
头 部
3 骼

额骨 颧骨 鼻骨 颞骨
Page 6

顶骨 上颌骨 下颌骨 枕骨
2、如何简化头像的形体观察方法?
头部的体积,可以借助最 简单的立方体来理解,再 进一步分析正面和侧面是 不同方向的两个面。
Page 7
(三),人物头部的标准比例和五官的位置、透视。
1、标准比例: “三停“”指发际到眉毛为上停,眉毛到鼻底为中停,鼻 底到下巴为下停。 “五眼”:正面看脸部最宽处为五个眼睛的距
Page 18
3、调整完成阶段 、
调整阶段, 调整阶段,主要任务是上大色调 和整体到局部, 和整体到局部,局部到整体的这样 过程,要多动脑,少动手, 过程,要多动脑,少动手,对画面 进行全面检查,对画面黑、 进行全面检查,对画面黑、白、灰 的调整统一的过程, 的调整统一的过程,不要进行大的 修改, 修改,以观察概括和加强减弱等方 突出主要五官刻划, 法,突出主要五官刻划,屏弃琐碎 的不必要的非本质的东西的描写, 的不必要的非本质的东西的描写, 努力做到使形象准确、鲜明、 努力做到使形象准确、鲜明、生动 做到画面的完整和谐统一。 、做到画面的完整和谐统一。
Page 12
2、眉、眼、鼻、嘴、耳: 、 深入观察掌握结构,各角度的透视变化。 深入观察掌握结构,各角度的透视变化。

海思动态自适应码率控制算法

海思动态自适应码率控制算法

海思动态自适应码率控制算法海思动态自适应码率控制算法是一种用于视频编码的技术,它根据视频内容的复杂程度和网络传输的带宽情况,自动调整视频的码率,以提供更好的观看体验。

该算法在实际应用中具有很高的效果和可靠性。

动态自适应码率控制算法的主要目标是在不损失视频质量的前提下,根据网络带宽的变化,动态调整视频的码率。

这样可以保证在网络带宽较低的情况下,视频仍然能够流畅播放;而在带宽较高的情况下,可以提供更高质量的视频。

该算法的实现过程可以分为以下几个步骤:1. 测量网络带宽:动态自适应码率控制算法首先需要测量当前的网络带宽。

这可以通过发送一系列数据包并测量其传输时间来实现。

根据传输时间的长短,可以估算出当前的网络带宽。

2. 估算视频复杂度:视频的复杂度是指视频内容的变化程度。

复杂度较高的视频通常包含较多的细节和运动,需要较高的码率来保证画面的清晰度。

而复杂度较低的视频则可以使用较低的码率来编码。

因此,在动态自适应码率控制算法中,需要对视频的复杂度进行估算。

3. 调整码率:根据网络带宽和视频复杂度的估算结果,动态自适应码率控制算法会自动调整视频的码率。

当网络带宽较低或视频复杂度较高时,会增加视频的码率,以保证视频质量。

而当网络带宽较高或视频复杂度较低时,可以降低视频的码率,以提高带宽的利用率。

4. 监控和反馈:动态自适应码率控制算法会持续监控网络带宽和视频复杂度的变化,并根据变化情况进行相应的调整。

同时,算法还会根据观看体验的反馈来进行优化。

例如,当用户反馈视频卡顿时,算法会尽可能提高视频的码率,以改善观看体验。

海思动态自适应码率控制算法在实际应用中具有很高的效果和可靠性。

它可以根据网络带宽和视频复杂度的变化,自动调整视频的码率,以提供更好的观看体验。

这种算法不仅可以应用于互联网视频服务,也可以应用于视频会议、远程监控等领域。

海思动态自适应码率控制算法是一种重要的视频编码技术,它可以根据网络带宽和视频复杂度的变化,自动调整视频的码率,以提供更好的观看体验。

vtm帧级码率控制代码

vtm帧级码率控制代码

vtm帧级码率控制代码
本文将介绍vtm帧级码率控制代码的实现方法。

vtm是一个高效的视频编码器,具有丰富的编码功能和优秀的编码质量。

在视频编码过程中,码率控制是一个重要的环节,可以保证编码后的视频质量和大小符合需求。

vtm支持帧级码率控制,可以根据每个帧的复杂度和码率需求进行动态调整,从而达到最优的编码效果。

vtm帧级码率控制代码的实现主要分为以下几个步骤:
1. 设置视频编码参数。

包括分辨率、帧率、码率等基本参数,以及码率控制模式和目标码率等码率控制相关参数。

2. 对每个编码帧进行编码。

在编码过程中,需要根据当前帧的复杂度和码率需求进行动态调整,以保证编码后的视频质量和大小符合需求。

具体的调整方法包括:
- 计算当前帧的复杂度。

一般可以使用帧间预测的残差大小或运动矢量大小来度量当前帧的复杂度。

- 根据当前帧的复杂度和码率需求,确定当前帧的QP值。

QP值越大,压缩率越低,码率越小,但视频质量也会降低。

- 根据当前帧的QP值和目标码率,确定当前帧的码率。

码率的计算可以使用贪心算法或动态规划算法等方法。

3. 输出编码结果。

编码结果包括编码后的视频流和码率控制相关的统计信息,如码率、QP值、复杂度等。

总之,vtm帧级码率控制代码的实现需要对视频编码原理和码率控制算法有深入的理解,以及对vtm编码器的代码结构和接口有熟悉
的掌握。

通过合理的码率控制策略,可以最大化地利用码率资源,得到高质量的视频编码结果。

视频编码线性码率控制模型

视频编码线性码率控制模型

视频编码线性码率控制模型
视频编码线性码率控制模型是指通过调整视频编码的比特率来控制视频质量和传输速度的一种算法。

在视频压缩过程中,码率控制是非常重要的一环,它能够使视频在固定带宽下尽可能的保证画面质量和显示效果。

本文将从以下三个方面详细介绍视频编码线性码率控制模型。

一、线性码率控制模型的原理
线性码率控制模型(LRC)是一种基于带宽和视频复杂度的编码
方法,通过控制编码的比特率来保证视频在传输过程中的画面质量。

LRC模型的算法流程如下:首先,获取视频的帧率、
像素和全局运动信息等相关参数;然后,通过比特率控制模型矩阵计算出理论码率;最后,调整视频编码的比特率,使实际码率接近理论码率。

二、线性码率控制模型的优点
相较于其他码率控制算法,线性码率控制模型具有如下优点:
1. 稳定性强:在视频数据的不同复杂度下,该模型能够对带宽资源进行更加精细的调节,从而保证视频在传输中的稳定性。

2. 适应性好:线性码率控制模型可以适应不同网络环境和视频质量需求,从而保障了视频在任何情况下的高清晰度和流畅性。

3. 可靠性高:该模型的调节精度非常高,可以准确的保证视频
的码率控制,从而将码率调制在最佳状态,提升视频传输的可靠性。

三、线性码率控制模型的应用
目前,LRC已经广泛应用于视频会议、监控视频、互联网直播等应用场景中。

尤其是在视频会议和监控视频领域,由于对视频质量和带宽控制要求非常高,因此LRC模型成为了首选的编码算法。

总之,线性码率控制模型是一种非常实用、稳定和优秀的视频编码算法,它可以保证视频在任何网络环境下的高清晰度和流畅性。

随着视频应用场景的不断扩展,该模型的应用前景也将越来越广阔。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 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值。

相关文档
最新文档