openh264碼控筆記一(整體框架)
一、名詞解釋
計算碼控時會用到如下的一些引數:
SAD (Sum of Absolute Difference)=SAE(Sum of Absolute Error)絕對誤差和
SATD(Sum of Absolute Transformed Difference)即hadamard變換後再絕對值求和
SSD (Sum of Squared Difference)=SSE(Sum of Squared Error) 差值的平方和
MAD (Mean Absolute Difference)=MAE(Mean Absolute Error) 平均絕對差值
MSD (Mean Squared Difference)=MSE(Mean Squared Error) 平均平方誤差
SAD絕對誤差和,僅反映殘差時域差異,影響PSNR值,不能有效反映碼流的大小。SATD將殘差經哈德曼變換的4×4塊的預測殘差絕對值總和,可以將其看作簡單的時頻變換,其值在一定程度上可以反映生成碼流的大小。因此,不用率失真最優化時,可將其作為模式選擇的依據。一般幀內要對所有的模式進行檢測,幀內預測選用SATD的原因同上。
在做運動估計時,一般而言,離最優匹配點越遠,匹配誤差值SAD越大,這就是有名的單一平面假設,現有的運動估計快速演算法大都利用該特性。但是,轉換後SATD值並不滿足該條件,如果在整象素中運用SATD搜尋,容易陷入區域性最優點。而在亞象素中,待搜尋點不多,各點處的SAD差異相對不大,可以用SATD選擇碼流較少的匹配位置。
RDO(Rate–distortion optimization)率失真優化,用來確定編碼模式,保證位元速率位元數和影象失真的最佳權衡點。
RQ模型是在上一層位元速率數一定的情況下用來確定下一層分配的位元數。RQ先於RDO進行。
二、碼控鉤子函式初始化
WelsRcInitFuncPointers函式初始化各種碼控模式下的鉤子函式。
三、RC_BITRATE_MODE碼控函式框架
四、結構體引數
1、幀級QP引數
TagWelsRc->iInitialQp
typedef struct TagWelsRc { int32_t iRcVaryPercentage; int32_t iRcVaryRatio; int32_t iInitialQp; //initial qp int64_t iBitRate; // Note: although the max bit rate is 240000*1200 which can be represented by int32, but there are many multipler of this iBitRate in the calculation of RC, so use int64 to avoid type conversion at all such places int32_t iPreviousBitrate; int32_t iPreviousGopSize; double fFrameRate; int32_t iBitsPerFrame; int32_t iMaxBitsPerFrame; double dPreviousFps; // bits allocation and status int32_t iRemainingBits; int32_t iBitsPerMb; int32_t iTargetBits; int32_t iCurrentBitsLevel;//0:normal; 1:limited; 2:exceeded. int32_t iIdrNum; int64_t iIntraComplexity; //255*255(MaxMbSAD)*36864(MaxFS) make the highest bit of 32-bit integer 1 int32_t iIntraMbCount; int64_t iIntraComplxMean; int8_t iTlOfFrames[VGOP_SIZE]; int32_t iRemainingWeights; int32_t iFrameDqBits; bool bGomRC; double* pGomComplexity; int32_t* pGomForegroundBlockNum; int32_t* pCurrentFrameGomSad; int32_t* pGomCost; int32_t bEnableGomQp; int32_t iAverageFrameQp; int32_t iMinFrameQp; int32_t iMaxFrameQp; int32_t iNumberMbFrame; int32_t iNumberMbGom; int32_t iGomSize; int32_t iSkipFrameNum; int32_t iFrameCodedInVGop; int32_t iSkipFrameInVGop; int32_t iGopNumberInVGop; int32_t iGopIndexInVGop; int32_t iSkipQpValue; int32_t iQpRangeUpperInFrame; int32_t iQpRangeLowerInFrame; int32_t iMinQp; int32_t iMaxQp; //int32_t delta_adaptive_qp; int32_t iSkipBufferRatio; int32_t iQStep; // *INT_MULTIPLY int32_t iFrameDeltaQpUpper; int32_t iFrameDeltaQpLower; int32_t iLastCalculatedQScale; //for skip frame and padding int32_t iBufferSizeSkip; int64_t iBufferFullnessSkip; int64_t iBufferMaxBRFullness[TIME_WINDOW_TOTAL];//0: EVEN_TIME_WINDOW; 1: ODD_TIME_WINDOW int32_t iPredFrameBit; bool bNeedShiftWindowCheck[TIME_WINDOW_TOTAL]; int32_t iBufferSizePadding; int32_t iBufferFullnessPadding; int32_t iPaddingSize; int32_t iPaddingBitrateStat; bool bSkipFlag; int32_t iContinualSkipFrames; SRCTemporal* pTemporalOverRc; //for scc int64_t iAvgCost2Bits; int64_t iCost2BitsIntra; int32_t iBaseQp; long long uiLastTimeStamp; //for statistics and online adjustments int32_t iActualBitRate; // TODO: to complete later float fLatestFrameRate; // TODO: to complete later } SWelsSvcRc;
2、Slice級QP引數
SRCSlicing->iCalculatedQpSlice
// slice level rc statistic info
typedef struct TagRCSlicing {
int32_t iComplexityIndexSlice;
int32_t iCalculatedQpSlice;
int32_t iStartMbSlice;
int32_t iEndMbSlice;
int32_t iTotalQpSlice;
int32_t iTotalMbSlice;
int32_t iTargetBitsSlice;
int32_t iBsPosSlice;
int32_t iFrameBitsSlice;
int32_t iGomBitsSlice;
int32_t iGomTargetBits;
//int32_t gom_coded_mb;
} SRCSlicing;
3、巨集塊級QP引數
TagMB->uiLumaQp/uiChromaQp
typedef struct TagMB {
/*************************mb_layer() syntax and generated********************************/
/*mb_layer():*/
Mb_Type uiMbType; // including MB detailed partition type, number and type of reference list
uint8_t uiSubMbType[4]; // sub MB types
int32_t iMbXY; // offset position of MB top left point based
int16_t iMbX; // position of MB in horizontal axis [0..32767]
int16_t iMbY; // position of MB in vertical axis [0..32767]
uint8_t uiNeighborAvail; // avail && same_slice: LEFT_MB_POS:0x01, TOP_MB_POS:0x02, TOPRIGHT_MB_POS = 0x04 ,TOPLEFT_MB_POS = 0x08;
uint8_t uiCbp;
SMVUnitXY* sMv;
int8_t* pRefIndex;
int32_t* pSadCost; // mb sad. set to 0 for intra mb
int8_t* pIntra4x4PredMode; // [MB_BLOCK4x4_NUM]
int8_t* pNonZeroCount; // [MB_LUMA_CHROMA_BLOCK4x4_NUM]
SMVUnitXY sP16x16Mv;
uint8_t uiLumaQp; // uiLumaQp: pPps->iInitialQp + sSliceHeader->delta_qp + mb->dquant.
uint8_t uiChromaQp;
uint16_t uiSliceIdc; // 2^16=65536 > MaxFS(36864) of level 5.1; AVC: iFirstMbInSlice?; SVC: (iFirstMbInSlice << 7) | ((uiDependencyId << 4) | uiQualityId);
uint32_t uiChromPredMode;
int32_t iLumaDQp;
SMVUnitXY sMvd[MB_BLOCK4x4_NUM]; //only for CABAC writing; storage structure the same as sMv, in 4x4 scan order.
int32_t iCbpDc;
//uint8_t reserved_filling_bytes[1]; // not deleting this line for further changes of this structure. filling bytes reserved to make structure aligned with 4 bytes, higher cache hit on less structure size by 2 cache lines( 2 * 64 bytes) once hit
} SMB, *PMb;