HEVC码率控制算法1TEncRateCtrl
TEncRateCtrl类是码率控制的总类,后续的序列,GOP,帧都是基于该基础
码率控制的总流程为
1、在TEncTop::create中,定义了TEncRateCtrl的码率控制初始化,其中序列级别的码率控制也在TEncRateCtrl::init中
if ( m_RCEnableRateControl )
{
// 码率控制器初始化
m_cRateCtrl.init( m_framesToBeEncoded, m_RCTargetBitrate, m_iFrameRate, m_iGOPSize, m_iSourceWidth, m_iSourceHeight,
g_uiMaxCUWidth, g_uiMaxCUHeight, m_RCKeepHierarchicalBit, m_RCUseLCUSeparateModel, m_GOPList );
}
2、在TEncTop::encode中,定义了GOP级别的码率控制
if ( m_RCEnableRateControl )
{
m_cRateCtrl.initRCGOP( m_iNumPicRcvd );
}
3、在TEncGOP::compressGOP,定义了帧级别的码率控制
m_pcRateCtrl->initRCPic( frameLevel );
在CompressSlice中进行CTU级别的码率控制
先开看看成员属性
分别是序列,GOP和帧三个控制类,list<TEncRCPic*> m_listRCPictures中模板是TEncRCPic类,意思是已经编码完的帧放进list中
构造函数和析构函数就是对接下来的三个类进行初始化和销毁
再来看看主要的成员方法:
init函数就是输入cfg文件中的配置
cfg文件中keepHierBits有三种选择,选0 是等比例分配,也就是各帧的比重相同,如果是1就是按比例分类,2是自适应比特分类
KeepHierarchicalBit : 2 # Rate control: 0: equal bit allocation; 1: fixed ratio bit allocation; 2: adaptive ratio bit allocation
接着在
这里是低延时配置下GOPsize=4比重的取值,参考下表
GOPSIZE=4,如果是自适应比特分配,将adaptiveBit置为1,否则是0.
GOPsize=8,随机介入的情况,如果是自适应比特分配,将adaptiveBit置为2,否则是0.
GOPID2level ,根据 GOP中ID确定其分级,HEVC测试序列采用分级算法,这里的分级和后续的CTU层比重计算有关
可以看到GOP大小为4时,GOPlevel最大为3
当GOP大小为8时,GOPlevel最大为4
TEncRateCtrl::init的作用就是先把分级,GOP中不同帧的一些参数先给确定了,然后创建序列的实例,初始化G该视频序列seq中以GOP为单位的各帧的比重,以及各帧的Level,还有帧级的阿尔法和贝塔参数,如果开启了LCU的分割,还初始化LCU的阿尔法和贝塔参数
创建序列级实例,然后把cfg的配置文件参数传给该类,把上面确定的帧分级和GOP中各帧所占比重传给序列级别,初始化各帧的阿尔法和贝塔参数,如果采用了useLCUSeparateModel,这个是指LCU层的lambda算法,还需初始化LCU层的阿尔法和贝塔参数
1428行是采用了目标位饱和法进行速率控制,看到这个才发现看到的很多文献注水有多么严重
#if U0132_TARGET_BITS_SATURATIONBool m_CpbSaturationEnabled; // Enable target bits saturation to avoid CPB overflow and underflowInt m_cpbState; // CPB State UInt m_cpbSize; // CPB sizeUInt m_bufferingRate; // Buffering rate
#endif
#if U0132_TARGET_BITS_SATURATIONm_CpbSaturationEnabled = true;m_cpbSize = targetBitrate;m_cpbState = (UInt)(m_cpbSize*0.5f);m_bufferingRate = (Int)(targetBitrate / frameRate);
把 m_CpbSaturationEnabled由默认false改为true就开启了目标位饱和法进行速率控制算法
缓冲区大小为目标码率,即可以缓冲一秒的图像,初始缓冲区状态为缓冲区的一半,bufferRate就是码率/帧率。
具体算法原理参考
码率控制(五):流体流量模型 - 掘金 (juejin.cn)https://juejin.cn/post/6956881425610047524
#if U0132_TARGET_BITS_SATURATIONif (m_pcRateCtrl->getCpbSaturationEnabled() && frameLevel != 0){Int estimatedCpbFullness = m_pcRateCtrl->getCpbState() + m_pcRateCtrl->getBufferingRate();
// prevent overflowif (estimatedCpbFullness - estimatedBits > (Int)(m_pcRateCtrl->getCpbSize()*0.9f)){estimatedBits = estimatedCpbFullness - (Int)(m_pcRateCtrl->getCpbSize()*0.9f);}
estimatedCpbFullness -= m_pcRateCtrl->getBufferingRate();// prevent underflow
#if V0078_ADAPTIVE_LOWER_BOUNDif (estimatedCpbFullness - estimatedBits < m_pcRateCtrl->getRCPic()->getLowerBound()){estimatedBits = max(200, estimatedCpbFullness - m_pcRateCtrl->getRCPic()->getLowerBound());}
#elseif (estimatedCpbFullness - estimatedBits < (Int)(m_pcRateCtrl->getCpbSize()*0.1f)){estimatedBits = max(200, estimatedCpbFullness - (Int)(m_pcRateCtrl->getCpbSize()*0.1f));}
#endif
m_pcRateCtrl->getRCPic()->setTargetBits(estimatedBits);}
#endif
updateCpbState函数
编码完一帧后更新缓冲区状态,cpbstate用完判断缓冲区是上溢还是下溢出
#if U0132_TARGET_BITS_SATURATION
Int TEncRateCtrl::updateCpbState(Int actualBits)
{Int cpbState = 1;m_cpbState -= actualBits;if (m_cpbState < 0){cpbState = -1;}m_cpbState += m_bufferingRate;if (m_cpbState > m_cpbSize){cpbState = 0;}return cpbState;
}
如图所示,我编码了三帧,码率是20000bps,fps =30,bufferRate=666
初始缓冲区大小为10000,第一帧为14432bits,10000+666-14432 =-3766,缓冲区下溢
initRCGOP函数
initRCPIC函数
可以看到在GOP创建时传了seq和该GOP的大小,在pic创建时传入了seq,GOP还有该帧的level。
这里有个注意点,initRCGOP传参numberofpictures并不一定等于GOPsize,经过断点调试后发现,假如我设置只编码三帧,IPPP结构,GOPsize=4,会调用两次initRCGOP函数,第一次numberofpictures=1.为I帧,第二次numberofpictures=2,是剩下的两帧。对于第一帧I帧而言,GOPsize=1,对于2,3帧GOPsize依旧等于4,原因后面讲。
HEVC码率控制算法1TEncRateCtrl相关推荐
- VCIP2020:面向机器视觉的HEVC码率控制
本文来自VCIP2020文章<A Novel Visual Analysis Oriented Rate Control Scheme for HEVC> 深度学习的发展使得计算机视觉任务 ...
- H.264的码率控制算法
H.264的码率控制算法采用了多种技术,其中包括自适应基本单元层(Adaptive Basic Unit Layer).流量往返模型(Fluid Traffic Model).线性MAD模型.二次率失 ...
- HEVC码率控制介绍(R-Lamda)
本来是不想贴出相应的代码的,但是还是贴出来大概的模块吧,这样才能不纸上谈兵! R-lamda模型提出到优化已有2年,从近几年的文章来看,大体归为以下几类:一类是帧内的码率控制算法,一类是模型参数更新, ...
- JM编码器码率控制算法笔记:以JVT-G012r1为例
应用率失真优化需要三个算法/模型 根据信源输入及选择的编码框架,建立合适的R-D模型(通常是R-Q.D-Q关系): 根据给定的码率R以及缓冲区状态,为每个编码单元分配比特并带入R-D模型求解Q,并在编 ...
- H.264码率控制算法研究及JM相应代码分析(二)
在前一篇文章的基础上,现在先看一下MPEG4 编码标准中应用的码率控制算法,总结起来,各大算法都是在解决两个问题:RD 率失真的优化以及避免缓冲区的上溢下溢. MPEG-4 VM8 码率控制算法 在这 ...
- x264 码率控制算法原理
x264 的码率控制是如何实现的 ? 本文介绍 x264 码率控制算法的数学原理,和基本框架. 1.理论假设 有助于往下阅读,可以暂时跳过. 设变量: qscale = 拉格朗日常数 lam ...
- HEVC码率控制资料整理
本篇博客主要记录项目过程中参考过.写得比较好的博客. 下载 HEVC项目 YUV视频文件 安装与使用 https://lin-lz.blog.csdn.net/article/details/5277 ...
- HEVC码率控制TEncRCPic
TEncRCPic帧级别码率控制 先开看成员属性 补充:m_totalCostIntra是指该帧(I帧)的帧内所有LCU的代价总和,该值通过TEncSlice::calCostSliceI函数赋值,同 ...
- HEVC码率控制代码分析
参考阅读https://blog.csdn.net/HEVC_CJL/article/details/10982699和https://blog.csdn.net/NB_vol_1/article/d ...
最新文章
- IoT	、5G与边缘计算将会擦出怎样的火花?
- 如何通过 macOS 恢复功能重新安装 macOS
- (转)利用Ant与Proguard混淆引用的子工程项目jar包及打war包
- mysql增删查操作
- POJ - 3322 Bloxorz I(bfs+状态设计)
- linux服务器上svn的log_Linux服务器上搭建svn服务器
- java从url下载文件_Java从URL下载文件
- 队列消息在html中怎么排列,Redis实现消息队列
- 难以置信,MySQL也可以无损自由切换
- C++基础教程之函数重载,什么是C++函数重载?
- Java 学习如逆水行舟,不进则退,100 本 java 电子书推荐
- Vue电商网站项目开发总结
- 仿羊了个羊H5游戏源码
- matlab画航线图,【图文详解】如何画出华丽丽的全球航线图
- python滑稽脸程序
- 3. Git与TortoiseGit基本操作
- 学计算机基础知识的app,电脑基础知识零基础入门版-电脑基础知识APP手机大全v1.0 安卓版-007游戏网...
- team explorer_Team Explorer 2017独立安装程序的退还
- 软件版本A.B.C这些数字分别代表什么意思
- 电脑技巧——用键盘控制光标
热门文章
- 简单聊天室客户端界面的实现(ChatClient.java)
- 目标管理的S.M.A.R.T.理念
- OpenCV——角点检测原理分析(Harris,Shi-Tomasi、亚像素级角点检测)
- 多视图几何笔记(二)射影变换
- OCR文字识别之CTC原理和实现
- 【读书笔记】《偷影子的人》[法]马克·李维 —— 不想被叫醒的梦
- 联想昭阳E47A无线网卡指示灯不亮,搜不到无线信号,解决办法
- labview 添加自定义Lib
- eclipse在资源管理器中打开文件
- 单元测试实践篇:Mock