TComPicYuv、TComPic、TComPicSym、TComDataCU以及TComYuv的關係
首先用一張圖來描述它們之間的關係
1、HM首先使用TComPicYuv保存從文件中讀取出來的YUV數據
2、利用TComPicYuv構造TComPic,並把YUV數據複製給他(TComPic包含了TComPicYuv成員)
3、TComPic表示一幀圖像,包含了數據(TComPicYuv),以及圖像信息(TComPicSym,在TComPicSym中還包含了TComDataCU)
4、TComPic被放入圖像隊列中
5、處理圖像隊列中的每一個TComPic,實際是處理TComPic中的每一個CTU/CU(存放在TComPicSym中)
6、從TComPic中取出每一個CTU(用TComDataCU表示),調用xCompressCU進行處理
7、根據原始的CTU初始化TEncCu中的TComDataCU(最優的和臨時的),這兩個在編碼的時候會使用
8、把TComPic的數據複製給TComYuv對象,表示編碼過程中的數據(原始,預測、殘差、重建等)
9、進行編碼,tempCU用於編碼過程中,bestCU用於保存最優信息
10、產生的最優信息會被複制回TComPicSym中
TComPicYuv
TComPicYuv表示圖像的YUV數據
class TComPicYuv
{
private:
Pel* m_apiPicBufY; // 三個顏色分量的緩衝區,包括了填充的內容
Pel* m_apiPicBufU;
Pel* m_apiPicBufV;
Pel* m_piPicOrgY; // 三個顏色分量的起始地址,由m_apiPicBufY計算得到
Pel* m_piPicOrgU;
Pel* m_piPicOrgV;
Int m_iPicWidth; // 圖像的寬和高
Int m_iPicHeight;
Int m_iCuWidth; // LCU的寬和高
Int m_iCuHeight;
Int* m_cuOffsetY; // 每個CTU中三個顏色分量的偏移地址
Int* m_cuOffsetC;
Int* m_buOffsetY; // CTU中每個4x4分量的偏移地址
Int* m_buOffsetC;
Int m_iLumaMarginX; // Y分量的填充寬度和高度,如果圖像的尺寸不是LCU的整數倍,那麼需要填充
Int m_iLumaMarginY;
Int m_iChromaMarginX; // U、V分量的填充高度和寬度
Int m_iChromaMarginY;
Bool m_bIsBorderExtended; // 是否需要填充圖像
};
TComPic
TComPic表示一張圖像,它包含數據(TComPicYuv)和信息(TComPicSym)
class TComPic
{
private:
UInt m_uiTLayer; // 時域層
Bool m_bUsedByCurr; // 是否被作爲參考幀
Bool m_bIsLongTerm; // 是否爲長參考圖像
TComPicSym* m_apcPicSym; // 圖像的信息
TComPicYuv* m_apcPicYuv[2]; // 圖像的數據(索引0是原始圖像,索引1是重建圖像)
TComPicYuv* m_pcPicYuvPred; // 圖像的預測數據
TComPicYuv* m_pcPicYuvResi; // 圖像的殘差數據
Bool m_bReconstructed; // 是否被重建
Bool m_bNeededForOutput; // 是否需要輸出
UInt m_uiCurrSliceIdx; // 在此圖像中,當前條帶的索引
Bool m_bCheckLTMSB; // 沒啥用
Int m_numReorderPics[MAX_TLAYER]; // 每一層重排的圖像的個數
Window m_conformanceWindow; // 一致性窗口,用於輸出
Window m_defaultDisplayWindow; // 默認顯示的窗口
bool m_isTop; // 頂場還是底場
bool m_isField; // 幀還是場
// 條帶的CU鏈表,即:
// 每一個slice中有若干LCU,每一個LCU又被細分爲各個CU
// std::vector<TComDataCU*>就是存放LCU的CU
// 沒有用到,因爲CTU的相關信息存放在TComPicSym中
std::vector<std::vector<TComDataCU*> > m_vSliceCUDataLink;
// 增強信息
SEIMessages m_SEIs; ///< Any SEI messages that have been received. If !NULL we own the object.
// 其他省略****
};
TComPicSym
TComPicSym表示圖像的信息,它內部有一個TComDataCU數組,描述了圖像組每一個LCU(CTU)的信息
class TComPicSym
{
private:
UInt m_uiWidthInCU; // 圖像在橫向上有多少個CTU,一般認爲LCU就是CTU
UInt m_uiHeightInCU; // 圖像在縱向上有多少個CTU
UInt m_uiMaxCUWidth; // 最大的CU的尺寸:64x64
UInt m_uiMaxCUHeight;
UInt m_uiMinCUWidth; // 最小的CU的尺寸:4x4
UInt m_uiMinCUHeight;
UChar m_uhTotalDepth; // LCU可以劃分的最大深度:5
UInt m_uiNumPartitions; // CTU有多少個4x4的塊
UInt m_uiNumPartInWidth; // CTU橫向上有幾個4x4的塊
UInt m_uiNumPartInHeight; // CTU縱向上有幾個4x4的塊
UInt m_uiNumCUsInFrame; // 圖像有幾個CTU
TComSlice* m_pcTComSlice; // slice頭部信息
TComDataCU** m_apcTComDataCU; // 表示了每一個CTU,每一個TComDataCU表示CU以及其中所有4x4塊的信息
SAOParam* m_saoParam; // SAO的參數
// 其他省略***
};
TComDataCU
TComDataCU表示CU,它本身不存儲YUV數據,只包含CU應有的語法元素(包括係數)。TComDataCU存儲了CU中所有4x4小塊的信息。由於LCU也是CU,因此TComDataCU既能表示LCU也能表示普通CU。
class TComDataCU
{
private:
TComPic* m_pcPic; // CU所在的圖像
TComSlice* m_pcSlice; // CU所在的條帶
TComPattern* m_pcPattern; // 用於訪問臨近CU
UInt m_uiCUAddr; // 在slice中CU的地址
UInt m_uiAbsIdxInLCU; // 在LCU中Z掃描順序的地址
UInt m_uiCUPelX; // 以像素爲單位的CU地址
UInt m_uiCUPelY; // 以像素爲單位的CU地址
UInt m_uiNumPartition; // 當前CU中有多少個4x4的塊
UChar* m_puhWidth; // 存放CU寬度的數組(因爲CU會不斷分割,每個CU都具有自己的長寬,所以村要存放,這個數組的作用就是這樣的)
UChar* m_puhHeight; // 同上
UChar* m_puhDepth; // 存放CU深度的數組
Int m_unitSize; // partition的最小尺寸
/*
** 下面是CU中各種語法元素
*/
Bool* m_skipFlag; // 跳過標誌數組
Char* m_pePartSize; // 分割的尺寸的數組
Char* m_pePredMode; // 預測模式的數組
Bool* m_CUTransquantBypass; // 用於量化
Char* m_phQP; // 量化步長的數組
UChar* m_puhTrIdx; // 變換索引的數組
UChar* m_puhTransformSkip[3];// 變換跳過標誌數組
UChar* m_puhCbf[3]; // 編碼塊標誌數組
TComCUMvField m_acCUMvField[2]; // 運動估計的數組
TCoeff* m_pcTrCoeffY; // Y變換系數的數組
TCoeff* m_pcTrCoeffCb; // U變換系數的數組
TCoeff* m_pcTrCoeffCr; // V變換系數的數組
Pel* m_pcIPCMSampleY; // PCM 樣本的緩衝區
Pel* m_pcIPCMSampleCb;
Pel* m_pcIPCMSampleCr;
TComDataCU* m_pcCUAboveLeft; ///< pointer of above-left CU 當前CU左上角的CU
TComDataCU* m_pcCUAboveRight; ///< pointer of above-right CU 當前CU右上角的CU
TComDataCU* m_pcCUAbove; ///< pointer of above CU 當前CU上面的CU
TComDataCU* m_pcCULeft; ///< pointer of left CU 當前CU左邊的CU
TComDataCU* m_apcCUColocated[2]; ///< pointer of temporally colocated CU's for both directions CU的變形
TComMvField m_cMvFieldA; ///< motion vector of position A A位置的運動估計,A/B/C位置是什麼?
TComMvField m_cMvFieldB; ///< motion vector of position B B位置的運動估計
TComMvField m_cMvFieldC; ///< motion vector of position C C位置的運動估計
TComMv m_cMvPred; ///< motion vector predictor 運動向量預測
Bool* m_pbMergeFlag; ///< array of merge flags 合併標誌的數組
UChar* m_puhMergeIndex; ///< array of merge candidate indices 合併候選數組
#if AMP_MRG
Bool m_bIsMergeAMP;
#endif
UChar* m_puhLumaIntraDir; ///< array of intra directions (luma) // 幀內預測 亮度部分的 方向的數組(因爲LCU會分割成很多部分)
UChar* m_puhChromaIntraDir; ///< array of intra directions (chroma) // 幀內預測 色度部分的 方向的數組
UChar* m_puhInterDir; ///< array of inter directions // 幀間預測的方向的集合
Char* m_apiMVPIdx[2]; ///< array of motion vector predictor candidates // 運動向量的候選集
Char* m_apiMVPNum[2]; // 可能的運動向量的數量的數組
Bool* m_pbIPCMFlag; // intra_pcm標誌的集合
Bool m_bDecSubCu; // 指出瞭解碼模式
// RD即拉格朗日率失真,這個成員表示總的失真的代價
Double m_dTotalCost; // 總的代價
// 總的失真
UInt m_uiTotalDistortion; // 總的失真
// 總的比特數
UInt m_uiTotalBits; ///< sum of partition bits
// 總的二進制數
UInt m_uiTotalBins; ///< sum of partition bins
UInt* m_sliceStartCU; ///< Start CU address of current slice 當前slice開始CU的地址
UInt* m_sliceSegmentStartCU; ///< Start CU address of current slice 當前slice開始CU的地址
Char m_codedQP; // 量化的編碼
};
TComYuv
TComYuv保存了每一個CU對應的YUV數據,原始數據從TComPic中得到(實際從TComPic的TComPicYuv成員中得到)。它主要用於表示編碼過程中的原始數據、預測數據、殘差數據以及重建數據
class TComYuv
{
private:
Pel* m_apiBufY; // 顏色分量的起始地址
Pel* m_apiBufU;
Pel* m_apiBufV;
UInt m_iWidth; // CU(可以是LCU,也可以是普通CU)的寬和高
UInt m_iHeight;
UInt m_iCWidth; // CU色度分量的尺寸
UInt m_iCHeight;
};