x265-1.8版本-encoder/ratecontrol.h注释

注:问号以及未注释部分 会在x265-1.9版本内更新

/*****************************************************************************
 * Copyright (C) 2013 x265 project
 *
 * Authors: Sumalatha Polureddy 
 *          Aarthi Priya Thirumalai 
 *          Xun Xu, PPLive Corporation 
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111, USA.
 *
 * This program is also available under a commercial proprietary license.
 * For more information, contact us at license @ x265.com.
 *****************************************************************************/

#ifndef X265_RATECONTROL_H
#define X265_RATECONTROL_H

#include "common.h"
#include "sei.h"

namespace X265_NS {
// encoder namespace

class Encoder;
class Frame;
class SEIBufferingPeriod;
struct SPS;
#define BASE_FRAME_DURATION 0.04  //播放一帧需要多少秒  基准为25fps

/* Arbitrary limitations as a sanity check. */
#define MAX_FRAME_DURATION 1.00 //播放一帧需要最长时间
#define MIN_FRAME_DURATION 0.01 //播放一帧需要最短时间

#define MIN_AMORTIZE_FRAME 10 //最小分摊帧数 (用于码率控制)
#define MIN_AMORTIZE_FRACTION 0.2  //最小分摊分数 (用于码率控制)
#define CLIP_DURATION(f) x265_clip3(MIN_FRAME_DURATION, MAX_FRAME_DURATION, f)

struct Predictor //用途:估计预测bits  存在于:RateControlEntry类(rowPreds[3][2]、*rowPred[2])和RateControl类(m_pred[4])中 updatePredictor中更新
{
    //预测当前帧的bits (p->coeff * var + p->offset) / (q * p->count)   q 一般为qscale  var 当前帧的framecost (可以是行的 也可以是8x8块的) 主要是 SATD与bits的映射关系
    double coeff;//当前未经量化的系数 累加和  (new_coeff = bits * q / var bits:实际编码bits q为qscale  var为satd值  p->coeff  *= p->decay  p->coeff  += new_coeff)
    double count;//当前个数的累加和 sum*0.5+1
    double decay;//固定值 0.5  用于求CplxSum: sum*0.5 + x  更新coeff、count、offset时应用
    double offset;//当前偏移量的累加和
};

struct HRDTiming
{
    double cpbInitialAT;
    double cpbFinalAT;
    double dpbOutputTime;
    double cpbRemovalTime;
};

struct RateControlEntry
{
    Predictor  rowPreds[3][2];// 第一维 slice类型:B_SLICE,P_SLICE,I_SLICE 第二维:所有帧 和P帧  遇到场景切换帧后全部初始化为(0.25,1.0,0.5,0.0)
    Predictor* rowPred[2];//指针 指向上面rowPreds对应帧类型的位置 所有帧 和P帧

    int64_t lastSatd;      //当前帧的SATD值 framecost  在rateControlStart中获取值 /* Contains the picture cost of the previous frame, required for resetAbr and VBV */
    int64_t leadingNoBSatd;//暂无任何作用 存储当前RC的最新非B帧的SATD值rateControlStart更新
    int64_t rowTotalBits;  //只在frameEncoder中应用:在processRowEncoder获取当前帧rowcount以前CTU编码占用的bits 紧接着在rateControlUpdateStats作适当修正 在m_rce2Pass中:不用 /* update cplxrsum and totalbits at the end of 2 rows */
    double  blurredComplexity; //预估当前非B帧的计算复杂度  在rateControlStart中获取值 m_shortTermCplxSum / m_shortTermCplxCount(当前非B帧及以前所有非B帧 framecost * (fps/25)的平均和) / (当前帧以前非B帧个数 + 1 ) 在m_rce2Pass中:?????
    double  qpaRc;//在rateControlStart中 获取预估qp参数值(未四舍五入) 在rateControlEnd 如果应用VBV 获取当前帧所有QP的平均值(多加了一次估计的QP值)  如果没有应用VBV 依然为在rateControlStart中 获取预估qp参数值(未四舍五入)
    double  qpAq;
    double  qRceq;//在rateControlStart中 获取数据对应未加权的qscale = m_lastRceq   m_lastRceq:在getQScale中获取数据对应未加权的qscale 初始化为1 应用cutree一般全序列是一个值:如果应用cutree 值:(fps/25)^(1 - m_param->rc.qCompress) 否则:是个变值 q = pow(rce->blurredComplexity, 1 - m_param->rc.qCompress)
    double  frameSizePlanned;  //根据估计qscale值预估的当前帧RC需要的bits  在rateEstimateQscale函数中获取数据 2pass???/* frame Size decided by RateCotrol before encoding the frame */
    double  bufferRate;        //只在frameEncoder中应用: 平均每帧最大的bits占用数目 在m_rce2Pass中:不用
    //计算方式:假设当前序列为 F0 F1 F2 F3 F4.....  
    //则: F0 = 0  F1 = F0*0.5  F2 = (F0*0.5 + F1)*0.5  F3 = ((F0*0.5 + F1)*0.5 + F2)*0.5  F4 = (((F0*0.5 + F1)*0.5 + F2)*0.5 + F3)*0.5
    double  movingAvgSum;      //滑动窗口平均framecost和 在rateEstimateQscale中获取数据
    double  rowCplxrSum;      //只在frameEncoder中应用:通过具体bits计算一帧rowcountCTU行前的cost值 在rateControlUpdateStats中获取数据:非B帧:rce->rowCplxrSum = rce->rowTotalBits * x265_qp2qScale(rce->qpaRc) / rce->qRceq; B帧:rce->rowCplxrSum = rce->rowTotalBits * x265_qp2qScale(rce->qpaRc) / (rce->qRceq * fabs(m_param->rc.pbFactor)); 在m_rce2Pass中:不用
    double  qpNoVbv;          //在rowDiagonalVbvRateControl应用 没经过VBV修正的估计量化参数 在rateControlStart和rateEstimateQscale中获取数据
    double  bufferFill;       //在rateControlStart VBV中获取扣除并行帧影响的RCbuffer
    double  frameDuration;
    double  clippedDuration;
    double  frameSizeEstimated; //用途:估计当前正在编码帧的占用bits 在rateEstimateQscale中获取当前帧的预估bits(rce->frameSizePlanned 在rowDiagonalVbvRateControl 根据当前已经编码的CTU重新更新当前帧预估的bits/* hold frameSize, updated from cu level vbv rc */
    double  frameSizeMaximum;   //当前level下当前帧占用的最大bits (x265自定义)rateControlStart中设置 (第一帧与其它帧分别设置) /* max frame Size according to minCR restrictions and level of the video */
    int     sliceType;          //在frameEncoder中:表示当前编码帧的帧类型:B_SLICE,P_SLICE,I_SLICE 
    int     bframes;            //无任何作用
    int     poc;                //在frameEncoder中: 当前poc RateControl::rateControlStart中赋值
    int     encodeOrder;        //在frameEncoder中: 当前的编码顺序(从0开始计数)
    bool    bLastMiniGopBFrame;//只在frameEncoder中应用: 标记当前帧是否为当前GOP的最后一个B帧 在m_rce2Pass中:不用
    bool    isActive;          //只在frameEncoder中应用:rateControlStart中置为ture rateControlEnd中置为false 在m_rce2Pass中:不用
    double  amortizeFrames;   // 码率控制bits分摊帧数 init初始化为为75   遇到I帧 /=1.1  随着编码分摊帧数越来越小 在非多pass结构应用 只I帧应用
    double  amortizeFraction; // 码率控制bits分摊分数 init初始化为为0.85  遇到I帧 /=1.1  随着编码分数越来越小 在非多pass结构应用 只I帧应用
    /* Required in 2-pass rate control */
    uint64_t expectedBits; /* total expected bits up to the current frame (current one excluded) */
    double   iCuCount;
    double   pCuCount;
    double   skipCuCount;
    double   expectedVbv;
    double   qScale;
    double   newQScale;//用途:???在rateEstimateQscale函数中获取预估qscale 2pass??? 
    double   newQp; //存储经过rateControlStart估计后的当前帧的量化参数
    int      mvBits;//用途??? 在rateEstimateQscale中对非B帧初始化为0  在m_rce2Pass中:???
    int      miscBits;
    int      coeffBits;//用途??? 在rateEstimateQscale中并且只是非B帧获取当前帧的framecost值 在m_rce2Pass中:???
    bool     keptAsRef;//当前是否可作参考帧  在frameEncoder中:1pass中在rateControlStart设置 2pass中???? 在m_rce2Pass中:???

    SEIPictureTiming *picTimingSEI;
    HRDTiming        *hrdTiming;
};

class RateControl// 用于码流控制  只在encoder类中存在
{
public:

    x265_param* m_param;         //配置参数信息
    Slice*      m_curSlice;      //当前编码的slice信息 /* all info about the current frame */
    SliceType   m_sliceType;     //当前编码的slice类型:B_SLICE,P_SLICE,I_SLICE  /* Current frame type */
    int         m_ncu;           //1/2下采样帧中的8x8块个数 /* number of CUs in a frame */
    int         m_qp;            //在rateControlStart中获取四舍五入的预估qp参数  ???/* updated qp for current frame */

    bool   m_isAbr;//是否应用ABR 当前不是CQP并且不是多pass 读的时候
    bool   m_isVbv;//是否应用VBV m_param->rc.vbvMaxBitrate > 0 && m_param->rc.vbvBufferSize > 0
    bool   m_isCbr;//CBR模式 如果最大码率设定小于目标码率 m_isCbr = m_param->rc.rateControlMode == X265_RC_ABR && m_isVbv && !m_2pass && m_param->rc.vbvMaxBitrate <= m_param->rc.bitrate;
    bool   m_singleFrameVbv;//初始化为0 如果平均每帧最大的bits占用数目*1.1 大于一秒的bits buffer大小置为1

    bool   m_isAbrReset;//用途 标记当前是否对RC进行重置  在rateEstimateQscale函数会根据是否下溢(前面占用bits过少 防止当前非B帧占用bits过多)对其置为true 在rateControlEnd中置为false 初始化为false
    int    m_lastAbrResetPoc;//记录最后的重置poc位置 该位置一定是非B帧  初始化为-1

    double m_rateTolerance;//码率buffer因子,默认为1.0 如果打开bStrictCbr 为0.7   abrBuffer = 2 * m_rateTolerance * m_bitrate 
    double m_frameDuration;  //当前播放一帧占用的时间(单位秒)   /* current frame duration in seconds */
    double m_bitrate; //当前配置的目标码率 (单位b) 配置的时候是kb 这里等于m_param->rc.bitrate * 1000
    double m_rateFactorConstant;//用途:一般分辨率越大 此值越大 一般在0.0x之间 只在CRF模式中应用  在RC类中初始化
    double m_bufferSize; //一秒的bits buffer大小 (vbv一秒占用的最大bits数目)
    double m_bufferFillFinal;  //当前码率控制中一秒钟占用的最大的buffer  一帧编码完毕后 减去当前帧占用的bits 加上预设一帧占用的最大bits 初始化为 一秒bits占用的配置buffer * m_param->rc.vbvBufferInit (VBV应用: 最大bits*0.9) /* real buffer as of the last finished frame */
    double m_bufferFill;       //VBV中应用,获取m_bufferFillFinal???/* planned buffer, if all in-progress frames hit their bit budget */
    double m_bufferRate;       //平均每帧最大的bits占用数目   vbvMaxBitrate / m_fps; /* # of bits added to buffer_fill after each frame */
    double m_vbvMaxRate;       //一秒钟占用的最大bits/* in kbps */
    double m_rateFactorMaxIncrement;//最大与配置之间的差值:m_param->rc.rfConstantMax - m_param->rc.rfConstant; /* Don't allow RF above (CRF + this value). */
    double m_rateFactorMaxDecrement;//配置与最小之间的差值:m_rateFactorMaxDecrement = m_param->rc.rfConstant - m_param->rc.rfConstantMin; /* don't allow RF below (this value). */

    Predictor m_pred[4];      //用途:用于预测当前帧占用的bits(predictSize函数) 数据更新:在一帧编码完毕后RateControl::updateVbv中更新维度:标号 0:不可参考b帧 1: P帧  2:I帧 3:可参考B帧 全部初始化为1.0 1.0 0.5 0.0 如果 m_param->rc.qCompress >= 0.8 .coeff初始为(0.5 0.75 1.0 0.5) 否则 .coeff初始为(0.75 1.0 1.0 0.75)  在RateControl::init和RateControl::rateControlStart函数中调用initFramePredictors()被初始化/* Slice predictors to preidct bits for each Slice type - I,P,Bref and B */
    int64_t m_leadingNoBSatd; //存储码流控制中最新的非B帧的SATD值 在rateControlStart函数中更新 初始化为0
    int     m_predType;       //????/* Type of slice predictors to be used - depends on the slice type */
    double  m_ipOffset; //用途:I帧与P帧的qp参数关系  P = Iqp + m_ipOffset 默认 2.9125608156077503
    double  m_pbOffset;//用途:P帧与B帧的qp参数关系  B = Pqp + m_pbOffset 默认 2.2710694220159415
    int64_t m_bframeBits;
    int64_t m_currentSatd; //当前的framecost 如果需要参考帧,取参考帧列表中各自第一帧当做参考帧的framecost   在rateControlStart中获取值
    int     m_qpConstant[3];//维度 P_SLICE B_SLICE I_SLICE 分别存储对应的固定QP值   2pass:???
    int     m_lastNonBPictType;//存储码流控制中最新的非B帧类型 在rateControlStart函数中更新 初始化为I帧
    int     m_framesDone;  //当前进入已经进入RC的帧数 初始化为0 ABR reset后也初始化为0 rateControlStart后累计1     /* # of frames passed through RateCotrol already */

    double  m_cplxrSum;          //用途用于估计QP值(在RC中一直累加) 后续更新:在rateControlUpdateStats函数中累加 rce->rowCplxrSum  在rateControlEnd中更新为一帧的bits*qscale(已扣除rowcount行累加的部分)值 初始化用于估计第一帧I帧的QP参数 0.01 * pow(700000, m_qCompress) * pow(m_ncu, 0.5) * tuneCplxFactor  其中tuneCplxFactor如果应用720p以上并且应用cutree为2.0 其它为1.0/* sum of bits*qscale/rceq */
    double  m_wantedBitsWindow;  //表示当前应该需要的bits数目(从重置一直累加到当前) 初始化:m_bitrate * m_frameDuration  在RateControl::rateControlEnd 累加:m_wantedBitsWindow += m_frameDuration * m_bitrate /* target bitrate * window */
    double  m_accumPQp;   //用途:???初始化为 0.01*24(ABR模式)在rateControlStart函数中更新 m_accumPQp*0.95+m_qp   /* for determining I-frame quant */
    double  m_accumPNorm;//用途:???初始化为0.01在rateControlStart函数中更新 m_accumPNorm
    double  m_lastQScaleFor[3]; //(rateEstimateQscale 只获取对应帧类型最近的qscale值[3]  getDiffLimitedQScale??? init2pass???)??? 存储对应帧类型最近的qscale值[3] 为B_SLICE,P_SLICE,I_SLICE  全部初始化为:ABR: QP=24 对应的 qscale(3.4) CRF:m_param->rc.rfConstant对应的qscale /* last qscale for a specific pict type, used for max_diff & ipb factor stuff */
    double  m_lstep;//在类初构造时初始化 为pow(2, m_param->rc.qpStep / 6.0)
    /*m_shortTermCplxSum 当前非B帧及以前所有非B帧 framecost * (fps/25)的平均和  
      计算方式: 设当前序列 I0BBBP1BBBP2BBBP3
      则当前m_shortTermCplxSum = (((I0*fps/25)*0.5 + P1*fps/25)*0.5 + P2*fps/25)*0.5 + P3
      m_shortTermCplxCount 当前帧以前非B帧个数 + 1
      I0 = 1
      P1 = I0*0.5 + 1 = 1.5
      P2 = P1*0.5 + 1 = 1.75
      P3 = P2*0.5 + 1 = 1.875
    **/
    double  m_shortTermCplxSum;// 当前非B帧及以前所有非B帧 framecost * (fps/25)的平均和   初始化为0 rateEstimateQscale获取数据
    double  m_shortTermCplxCount;//当前帧以前非B帧个数 + 1 初始化为0 rateEstimateQscale获取数据
    double  m_lastRceq;//在getQScale中获取数据对应未加权的qscale 初始化为1 应用cutree一般全序列是一个值:如果应用cutree 值:(fps/25)^(1 - m_param->rc.qCompress) 否则:是个变值 q = pow(rce->blurredComplexity, 1 - m_param->rc.qCompress)
    double  m_qCompress;  //用途:????如果应用cutree 设置强度系数为1 否则从配置参数中获取 m_qCompress = m_param->rc.qCompress
    int64_t m_totalBits;        //在RC中一直累加占用的所有已编码bits  在rateControlUpdateStats中累加当前row行以前的编码bits 在rateControlEnd中累加一帧的bits(扣除前面rowcount行的占用bits)init中初始化为0/* total bits used for already encoded frames (after ammortization) */
    int64_t m_encodedBits;      //当前已经编码帧占用的bits init初始化为0 rateControlEnd中更新/* bits used for encoded frames (without ammortization) */
    double  m_fps;
    int64_t m_satdCostWindow[50];//用途:存储当前滑动窗口每帧的下采样framecost 全部初始化为0 (根据滑动窗口大小(x265定为20))
    int64_t m_encodedBitsWindow[50];//用途:存储当前滑动窗口每帧占用的实际bits(在rateControlEnd中获取数据) 如果不对要全部修改注释 全部初始化为0 (根据滑动窗口大小(x265定为20))
    int     m_sliderPos;//等于编码顺序(从1计数) 用于指示滑动窗口的下标 初始化为0

    /* To detect a pattern of low detailed static frames in single pass ABR using satdcosts */
    int64_t m_lastBsliceSatdCost;//最近的非参考B帧的framcost 初始化为0 rateControlStart中计算
    int     m_numBframesInPattern;//连续b帧(非参考)framecost相同的个数   初始化为0  rateControlStart中计算   一般很少有这种情况
    bool    m_isPatternPresent;//如果当前非B帧前又大于bframes个数个连续framecost相同 置为true  在b帧framecost不同与前一个b帧cost时置为false 初始化为false rateControlStart中计算
    bool    m_isSceneTransition;//如果当前帧是场景切换帧 标记为true  如果 初始化为false
    //设x为场景切换帧
    //IBBBPBBBxBBBPBBBP  对应m_isSceneTransition值
    //00000000111111110
    int     m_lastPredictorReset;//记录Predictor重置的编码位置(编码顺序) rce->encodeOrder  初始化为0

    /* a common variable on which rateControlStart, rateControlEnd and rateControUpdateStats waits to
     * sync the calls to these functions. For example
     * -F2:
     * rceStart  10
     * rceUpdate 10
     * rceEnd    9
     * rceStart  11
     * rceUpdate 11
     * rceEnd    10
     * rceStart  12
     * rceUpdate 12
     * rceEnd    11 */
    ThreadSafeInteger m_startEndOrder;//控制RC互相等待的数据(全局控制) 初始化为0
    /*与三个函数有关系rateControlStart、rateControlUpdateStats、rateControlEnd、setFinalFrameCount
    rateControlStart:一直是蓄势待发的状态 一旦不满足条件即执行 :m_startEndOrder < rce->encodeOrder * 2 && !m_bTerminated  (此函数用于估计当前帧的qP值)
    rateControlUpdateStats: 会对m_startEndOrder更新两次 一次必须累加1  一次满足条件:if (rce->encodeOrder < m_param->frameNumThreads - 1)  m_startEndOrder累加1 (帧编码大约一半时进入)
    rateControlEnd:帧编码结束  (在编码完毕时是蓄势待发状态) 一旦不满足条件即执行 :(m_startEndOrder < (rce->encodeOrder + m_param->frameNumThreads) * 2 - 1 && !m_bTerminated)  满足条件立即执行:(m_finalFrameCount && orderValue >= 2 * m_finalFrameCount) 
                     执行完毕时会对m_startEndOrder累加1
    setFinalFrameCount:m_finalFrameCount 一直为0 再读完帧的时候 设置为编码帧数
    约定符号:
    start 表示 rateControlStart可以执行  
    UP0   表示 rateControlUpdateStats更新m_startEndOrder第一次
    UP1   表示 rateControlUpdateStats更新m_startEndOrder第二次(不满足不更新)  if (rce->encodeOrder < m_param->frameNumThreads - 1)
    end0  表示 rateControlEnd 满足条件执行
    end1  表示 rateControlEnd 满足第二条件 立即执行 (m_finalFrameCount && m_startEndOrder >= 2 * m_finalFrameCount)  需要改进!
    END   表示end执行m_startEndOrder累加1
    (x/y/z/g)  x: 当前poc  y 当前编码序号  z start执行需要满足的最小序号  g end执行需要满足的最小序号
    以4framethread编码10帧为例
                       (0/0/0/7)    (4/1/2/9)      (2/2/4/11)      (1/3/6/13)        (3/4/8/15)        (8/5/10/17)       (6/6/12/19)      (5/7/14/21)       (7/8/16/23)        (9/9/18/25) 
    m_startEndOrder 0:  start    
    m_startEndOrder 1:  UP0  
    m_startEndOrder 2:  UP1 ---触发-->start
    m_startEndOrder 3:                 UP0
    m_startEndOrder 4:                 UP1---触发--->start
    m_startEndOrder 5:                                UP0
    m_startEndOrder 6:                                UP1 ---触发--->start
    m_startEndOrder 7:  end0<-------------------触发------------------UP0
    m_startEndOrder 8:  END  --------------------------触发--------------------------->start
    m_startEndOrder 9:              end0<----------------------触发---------------------UP0
    m_startEndOrder10:               END  ----------------------------触发----------------------------->start
    m_startEndOrder11:                               end0<----------------------触发---------------------UP0
    m_startEndOrder12:                                END  ----------------------------触发------------------------------->start
    m_startEndOrder13:                                               end0<-----------------------触发-----------------------UP0
    m_startEndOrder14:                                                END  -----------------------------触发-------------------------------->start
    m_startEndOrder15:                                                                 end0<-----------------------触发-----------------------UP0
    m_startEndOrder16:                                                                  END  -----------------------------触发-------------------------------->start
    m_startEndOrder17:                                                                                   end0<-----------------------触发-----------------------UP0
    m_startEndOrder18:                                                                                    END  -----------------------------触发-------------------------------->start
    m_startEndOrder19:                                                                                                     end0<-----------------------触发-----------------------UP0
    m_startEndOrder20:                                                                                                      END 
    外环控制                                                                                                     setFinalFrameCount 设定m_finalFrameCount值 并将所有RC打开 (当前再也没有其它帧)
    m_startEndOrder20:                                                                                                      END(通过setFinalFrameCount) 这里到底触发哪个,很容易出问题  也可能会先触发后面的 潜在威胁 (一般先进行前面的)
    m_startEndOrder20:                                                                                                                       end1
    m_startEndOrder21:                                                                                                                       END(没有触发只说 潜在的危险,只是系统默认顺序执行)
    m_startEndOrder22:                                                                                                                                        END(没有触发只说 潜在的危险,只是系统默认顺序执行,这是是在20的情况下进入的)
    m_startEndOrder23:                                                                                                                                                            END(没有触发只说 潜在的危险,只是系统默认顺序执行,这是是在22的情况下进入的)

    **/
    int     m_finalFrameCount;   /* set when encoder begins flushing */
    bool    m_bTerminated;       //是否码流控制结束  初始化为false 结束置为ture/* set true when encoder is closing */

    /* hrd stuff */
    SEIBufferingPeriod m_bufPeriodSEI;
    double  m_nominalRemovalTime;
    double  m_prevCpbFinalAT;

    /* 2 pass */
    bool    m_2pass;    //当前是否是2pass  是为true 否为false
    int     m_numEntries;
    FILE*   m_statFileOut;
    FILE*   m_cutreeStatFileOut;
    FILE*   m_cutreeStatFileIn;
    double  m_lastAccumPNorm;
    double  m_expectedBitsSum;   /* sum of qscale2bits after rceq, ratefactor, and overflow, only includes finished frames */
    int64_t m_predictedBits;//????在rateControlStart VBV模式下一开始获取已编码bits数目
    RateControlEntry* m_rce2Pass;

    struct
    {
        uint16_t *qpBuffer[2]; /* Global buffers for converting MB-tree quantizer data. */
        int qpBufPos;          /* In order to handle pyramid reordering, QP buffer acts as a stack.
                                * This value is the current position (0 or 1). */
    } m_cuTreeStats;

    RateControl(x265_param& p);
    bool init(const SPS& sps);
    void initHRD(SPS& sps);

    void setFinalFrameCount(int count);
    void terminate();          /* un-block all waiting functions so encoder may close */
    void destroy();

    // to be called for each curFrame to process RateControl and set QP
    int  rateControlStart(Frame* curFrame, RateControlEntry* rce, Encoder* enc);
    /** 函数功能             : 当前帧编码一半时即时更新数据,便于后续帧快速估计  更新m_startEndOrder计数
    /*  调用范围             : 只在processRowEncoder函数中被调用
    * \参数 rce              : 当前帧RC相关数据
    * \返回                  : null * */
    void rateControlUpdateStats(RateControlEntry* rce);
    int  rateControlEnd(Frame* curFrame, int64_t bits, RateControlEntry* rce);
    /** 函数功能             : 更新predictor、根据当前编码情况估计当前帧占用的bits、计算最优qp参数值、判断是否需要重新编码
    /*  调用范围             : 只在processRowEncoder函数中被调用(只在对角线CTU进入)
    * \参数 curFrame         : 当前编码帧
    * \参数 row              : 当前CTU行号
    * \参数 rce              : 当前帧的码率控制数据
    * \参数 qpVbv            : 当前CTU对应的baseQp量化参数
    * \返回                  : 0:正常编码 -1:qp跳到过大 需要重新编码 * */
    int  rowDiagonalVbvRateControl(Frame* curFrame, uint32_t row, RateControlEntry* rce, double& qpVbv);
    int  rateControlSliceType(int frameNum);
    bool cuTreeReadFor2Pass(Frame* curFrame);
    void hrdFullness(SEIBufferingPeriod* sei);
    int writeRateControlFrameStats(Frame* curFrame, RateControlEntry* rce);
protected:

    static const int   s_slidingWindowFrames;
    static const char* s_defaultStatFileName;

    double m_amortizeFraction;//码率控制bits分摊分数 init初始化为为0.85  遇到I帧 /=1.1  随着编码分数越来越小 在非多pass结构应用 只I帧应用
    int    m_amortizeFrames;//码率控制bits分摊帧数 init初始化为为75   遇到I帧 /=1.1  随着编码分摊帧数越来越小 在非多pass结构应用 只I帧应用  
    int    m_residualFrames;//类构造时初始化为0 分摊帧数随着编码越来越小 只在rateControlEnd中应用 
    int    m_partialResidualFrames;//码率控制bits分摊帧数 类初始化时为0 在非多pass结构应用 遇到I帧 更新为X265_MIN((int)rce->amortizeFrames, m_param->keyframeMax); 遇到非I帧 m_partialResidualFrames--;
    int    m_residualCost;//init初始化为0  剩余帧分摊bits占用的平均cost 只在rateControlEnd中应用
    int    m_partialResidualCost;//I帧的剩余cost init初始化为0 在非多pass结构应用 遇到I帧获取数据 在 rateControlUpdateStats中获取数据 m_partialResidualCost = (int)((rce->rowTotalBits * rce->amortizeFraction) / m_partialResidualFrames);

    /** 函数功能             : 获取当前帧所在的zone
    /*  调用范围             : 只在rateControlStart(只在CQP模式应用)、getDiffLimitedQScale和RateControl::getQScale函数中被调用
    * \返回                  : 返回当前帧所在的zone * */
    x265_zone* getZone();
    /** 函数功能             : 在1pass中只在非B帧应用获取预测的qscale如果有对应zone信息对qcale进行修正、在2pass中对所有帧应用获取预测的qscale如果有对应zone信息对qcale进行修正
    /*  调用范围             : 只在initPass2()和rateEstimateQscale(只在非B帧应用)函数中被调用 注意:1pass中只在rateEstimateQscale函数中调用 2pass中只在initPass2()调用
    * \参数 rce              : 码流控制数据 在initPass2():m_rce2Pass 在rateEstimateQscale:当前编码帧的RC参数 
    * \参数 rateFactor       : 参数因子在initPass2():1.0 rateFactor  在rateEstimateQscale:在非B帧中进入 CRF:m_rateFactorConstant ABR:m_wantedBitsWindow / m_cplxrSum
    * \返回                  : 返回qscale值 * */
    double getQScale(RateControlEntry *rce, double rateFactor);
    double rateEstimateQscale(Frame* pic, RateControlEntry *rce); // main logic for calculating QP based on ABR
    /** 函数功能             : 根据当前已编码bits数目修正预估的qscale值并计算overflow值(qScale *= overflow)
    /*  调用范围             : 只在rateEstimateQscale函数中被调用
    * \参数 qScale           : qscale参数
    * \返回                  : 返回修正后的qscale值 * */
    double tuneAbrQScaleFromFeedback(double qScale);
    /** 函数功能             : 累加m_accumPQp*0.95+m_qp和m_accumPNorm*0.95+1
    /*  调用范围             : 只在rateControlStart函数中被调用
    * \返回                  : null * */
    void   accumPQpUpdate();

    int    getPredictorType(int lowresSliceType, int sliceType);
    /** 函数功能             : 更新帧predictor并且更新当前最新的VBVbuffer
    /*  调用范围             : 只在rateControlEnd函数中被调用
    * \参数 bits             : 当前帧编码完毕占用的实际bits数目
    * \参数 rce              : 当前帧码率控制数据
    * \返回                  : null * */
    void   updateVbv(int64_t bits, RateControlEntry* rce);
    /** 函数功能             : 求predictor中系数的CplxSum和
    /*  调用范围             : 只在rowDiagonalVbvRateControl和RateControl::updateVbv函数中被调用 
    * \参数 p                : 在rowDiagonalVbvRateControl:rowPred[0] 和 rowPred[1] 在RateControl::updateVbv:m_pred[predType] 
    * \参数 q                : 在rowDiagonalVbvRateControl:qscale值 在RateControl::updateVbv:rce->qpaRc 
    * \参数 var              : 在rowDiagonalVbvRateControl:当前row已编码CTU的对应下采样SATD值的累加和  在RateControl::updateVbv:当前帧的SATD值 framecost 
    * \参数 bits             : 在rowDiagonalVbvRateControl:当前row已编码CTU占用bits的累加和 在RateControl::updateVbv:当前帧编码占用的实际bits 
    * \返回                  : null * */
    void   updatePredictor(Predictor *p, double q, double var, double bits);
    /** 函数功能             : 如果应用VBV:根据下采样SATD信息修正qscale值  否则 只是简单的clip操作
    /*  调用范围             : 只在initPass2()、rateEstimateQscale函数中被调用
    * \参数 curFrame         : 当前编码帧
    * \参数 rce              : 当前编码帧的相关码率控制信息
    * \参数 q                : qscale参数
    * \返回                  : 返回修正后的qscale * */
    double clipQscale(Frame* pic, RateControlEntry* rce, double q);
    /** 函数功能             : VBV中更新根据当前帧并行情况更新当前RCbuffer
    /*  调用范围             : 只在RateControl::rateControlStart函数中被调用
    * \参数 enc              : 上层encodr类
    * \返回                  : null * */
    void   updateVbvPlan(Encoder* enc);
    /** 函数功能             : 根据当前帧类型的predictor qscale参数 以及对应下采样的SATD值 预估当前块/帧 占用的bits
    /*  调用范围             : 只在rateControlStart、rateEstimateQscale、clipQscale、predictRowsSizeSum函数中被调用
    * \参数 p                : rateControlStart:m_pred[m_predType]预测器(forceqp时应)、rateEstimateQscale:m_pred[m_predType]、clipQscale:m_pred[m_predType]预测器、predictRowsSizeSum:rowPred[0]、rowPred[1]
    * \参数 q                : rateControlStart:当前量化参数(forceqp时应)、rateEstimateQscale:qscale参数、clipQscale:qscale参数、predictRowsSizeSum:当前的qscale值
    * \参数 var              : rateControlStart:当前帧的framecost(forceqp时应)、rateEstimateQscale:当前帧的framecost、clipQscale:当前帧的framecost、predictRowsSizeSum:当前行未编码CTU的SATD和
    * \返回                  : 返回预测bits * */
    double predictSize(Predictor *p, double q, double var);
    /** 函数功能             : 检测是否下溢(前面占用bits过少 防止当前非B帧占用bits过多)rateEstimateQscale中用于下溢检测并重置ABR  rateControlEnd用于关闭前面重置的标志位
    /*  调用范围             : 只在rateEstimateQscale和RateControl::rateControlEnd函数中被调用
    * \参数 rce              : 当前编码帧的RC参数
    * \参数 isFrameDone      : 当前帧是否编码完毕 rateEstimateQscale为false rateControlEnd为true
    * \返回                  : null * */
    void   checkAndResetABR(RateControlEntry* rce, bool isFrameDone);
    /** 函数功能             : 计算当前帧已经编码bits加上未编码预测bits
    /*  调用范围             : 只在rowDiagonalVbvRateControl函数中被调用
    * \参数 curFrame         : 当前编码帧
    * \参数 rce              : 当前帧的码率控制数据
    * \参数 qpVbv            : 当前更新后的QP参数
    * \参数 encodedBitsSoFar : 用于回存当前帧已经编码的bits
    * \返回                  : 返回当前帧已经编码bits加上未编码预测bits * */
    double predictRowsSizeSum(Frame* pic, RateControlEntry* rce, double qpm, int32_t& encodedBits);
    bool   initPass2();
    /** 函数功能             : 初始化Predictor
    /*  调用范围             : 只在RateControl::init和RateControl::rateControlStart函数中被调用
    * \返回                  : null * */
    void   initFramePredictors();
    double getDiffLimitedQScale(RateControlEntry *rce, double q);
    double countExpectedBits();
    bool   vbv2Pass(uint64_t allAvailableBits);
    bool   findUnderflow(double *fills, int *t0, int *t1, int over);
    bool   fixUnderflow(int t0, int t1, double adjustment, double qscaleMin, double qscaleMax);
};
}
#endif // ifndef X265_RATECONTROL_H


 

你可能感兴趣的:(x265代码注释)