上层CodingStructure
结构体管理着一帧中所有的CU,PU和TU。可以通过简单的坐标操作获取一帧中所有位置的CU信息。下层CodingStructure
是进行RD搜索最优尺寸和最优预测模式的基本单元。想要深入理解VTM的代码逻辑,了解CodingStructure
中的属性和方法是基础。
class CodingStructure
{
public:
UnitArea area; // CodingStructure 所包含的区域
Picture *picture; // 与picture的映射
CodingStructure *parent; // 上层cs
#if JVET_M0246_AFFINE_AMVR
CodingStructure *bestCS;
#endif
Slice *slice;
UnitScale unitScale[MAX_NUM_COMPONENT];
ChannelType chType;
int baseQP;
int prevQP[MAX_NUM_CHANNEL_TYPE];
int currQP[MAX_NUM_CHANNEL_TYPE];
int chromaQpAdj; // 色度qp的offset
#if JVET_M0170_MRG_SHARELIST
Position sharedBndPos;
Size sharedBndSize;
#endif
bool isLossless;
const SPS *sps;
const PPS *pps;
#if HEVC_VPS
const VPS *vps;
#endif
const PreCalcValues* pcv; // 预定义和计算得到的block相关参数
CodingStructure(CUCache&, PUCache&, TUCache&); // 构造
void create( const UnitArea &_unit, const bool isTopLayer ); // 通过UnitArea创建新CS
void create( const ChromaFormat &_chromaFormat, const Area& _area, const bool isTopLayer ); // 通过area创建新的CodingStructure
void destroy(); // 释放CodingStructure
void releaseIntermediateData(); // 释放编码信息
void rebindPicBufs();
void createCoeffs(); // 分配coeff空间
void destroyCoeffs();
void allocateVectorsAtPicLevel(); // 给编码信息(CUs,pus,tus)分配预留空间
// ---------------------------------------------------------------------------
// global accessors
// ---------------------------------------------------------------------------
bool isDecomp (const Position &pos, const ChannelType _chType) const; // position处的重建信息是否已经生成
bool isDecomp (const Position &pos, const ChannelType _chType);
void setDecomp(const CompArea &area, const bool _isCoded = true); // 设定特定颜色通道重建标志
void setDecomp(const UnitArea &area, const bool _isCoded = true); // 多通道区域重建标志
const CodingUnit *getCU(const Position &pos, const ChannelType _chType) const; // 返回position处的CU
const PredictionUnit *getPU(const Position &pos, const ChannelType _chType) const; // 返回position处的pu
#if JVET_M0102_INTRA_SUBPARTITIONS
const TransformUnit *getTU(const Position &pos, const ChannelType _chType, const int subTuIdx = -1) const; // 返回position处的tu
#else
const TransformUnit *getTU(const Position &pos, const ChannelType _chType) const;
#endif
CodingUnit *getCU(const Position &pos, const ChannelType _chType);
PredictionUnit *getPU(const Position &pos, const ChannelType _chType);
#if JVET_M0102_INTRA_SUBPARTITIONS
TransformUnit *getTU(const Position &pos, const ChannelType _chType, const int subTuIdx = -1);
#else
TransformUnit *getTU(const Position &pos, const ChannelType _chType);
#endif
// 获取cs第一个cu,pu,tu
const CodingUnit *getCU(const ChannelType &_chType) const { return getCU(area.blocks[_chType].pos(), _chType); }
const PredictionUnit *getPU(const ChannelType &_chType) const { return getPU(area.blocks[_chType].pos(), _chType); }
const TransformUnit *getTU(const ChannelType &_chType) const { return getTU(area.blocks[_chType].pos(), _chType); }
CodingUnit *getCU(const ChannelType &_chType ) { return getCU(area.blocks[_chType].pos(), _chType); }
PredictionUnit *getPU(const ChannelType &_chType ) { return getPU(area.blocks[_chType].pos(), _chType); }
TransformUnit *getTU(const ChannelType &_chType ) { return getTU(area.blocks[_chType].pos(), _chType); }
// 获取cu,并判定是否在同一个slice和tile中,为了并行编码
#if HEVC_TILES_WPP
const CodingUnit *getCURestricted(const Position &pos, const unsigned curSliceIdx, const unsigned curTileIdx, const ChannelType _chType) const;
#else
const CodingUnit *getCURestricted(const Position &pos, const unsigned curSliceIdx, const ChannelType _chType) const;
#endif
const CodingUnit *getCURestricted(const Position &pos, const CodingUnit& curCu, const ChannelType _chType) const;
const PredictionUnit *getPURestricted(const Position &pos, const PredictionUnit& curPu, const ChannelType _chType) const;
const TransformUnit *getTURestricted(const Position &pos, const TransformUnit& curTu, const ChannelType _chType) const;
// 为cs在UnitArea处创建CU
CodingUnit& addCU(const UnitArea &unit, const ChannelType _chType);
PredictionUnit& addPU(const UnitArea &unit, const ChannelType _chType);
TransformUnit& addTU(const UnitArea &unit, const ChannelType _chType);
// 遍历CS中CU,返回遍历器 typedef UnitTraverser CUTraverser;
CUTraverser traverseCUs(const UnitArea& _unit, const ChannelType _chType);
PUTraverser traversePUs(const UnitArea& _unit, const ChannelType _chType);
TUTraverser traverseTUs(const UnitArea& _unit, const ChannelType _chType);
cCUTraverser traverseCUs(const UnitArea& _unit, const ChannelType _chType) const;
cPUTraverser traversePUs(const UnitArea& _unit, const ChannelType _chType) const;
cTUTraverser traverseTUs(const UnitArea& _unit, const ChannelType _chType) const;
IbcLumaCoverage getIbcLumaCoverage(const CompArea& chromaArea) const;
// ---------------------------------------------------------------------------
// encoding search utilities 自顶向下RDsearch相关参数和方法
// ---------------------------------------------------------------------------
static_vector<double, NUM_ENC_FEATURES> features;
double cost;
#if JVET_M0102_INTRA_SUBPARTITIONS
double lumaCost;
#endif
uint64_t fracBits;
Distortion dist;
Distortion interHad;
// clear所有数据,包括信号buf和编码信息
void initStructData (const int &QP = MAX_INT, const bool &_isLosses = false, const bool &skipMotBuf = false);
// 链接新的底层CodingStructure
void initSubStructure( CodingStructure& cs, const ChannelType chType, const UnitArea &subArea, const bool &isTuEnc);
// 从cs中复制编码信息
void copyStructure (const CodingStructure& cs, const ChannelType chType, const bool copyTUs = false, const bool copyRecoBuffer = false);
// 从底层CS复制编码信息到当前层cs
void useSubStructure (const CodingStructure& cs, const ChannelType chType, const UnitArea &subArea, const bool cpyPred, const bool cpyReco, const bool cpyOrgResi, const bool cpyResi);
void useSubStructure (const CodingStructure& cs, const ChannelType chType, const bool cpyPred, const bool cpyReco, const bool cpyOrgResi, const bool cpyResi) { useSubStructure(cs, chType, cs.area, cpyPred, cpyReco, cpyOrgResi, cpyResi); }
// 清空编码信息
void clearTUs();
void clearPUs();
void clearCUs();
private:
void createInternals(const UnitArea& _unit, const bool isTopLayer); // 预分配空间,并清空数据
public:
// 存放CS中所有cu,pu,tu
std::vector< CodingUnit*> cus;
std::vector<PredictionUnit*> pus;
std::vector< TransformUnit*> tus;
private:
// needed for TU encoding
bool m_isTuEnc;
unsigned *m_cuIdx [MAX_NUM_CHANNEL_TYPE];
unsigned *m_puIdx [MAX_NUM_CHANNEL_TYPE];
unsigned *m_tuIdx [MAX_NUM_CHANNEL_TYPE];
bool *m_isDecomp[MAX_NUM_CHANNEL_TYPE];
unsigned m_numCUs;
unsigned m_numPUs;
unsigned m_numTUs;
CUCache& m_cuCache;
PUCache& m_puCache;
TUCache& m_tuCache;
std::vector<SAOBlkParam> m_sao; // sao参数
// 视频信号二维数据,“继承”Unitbuf------struct PelStorage : public PelUnitBuf
PelStorage m_pred;
PelStorage m_resi;
PelStorage m_reco;
PelStorage m_orgr;
TCoeff *m_coeffs [ MAX_NUM_COMPONENT ];
Pel *m_pcmbuf [ MAX_NUM_COMPONENT ];
int m_offsets[ MAX_NUM_COMPONENT ];
MotionInfo *m_motionBuf; // 存储CS运动信息
public:
MotionBuf getMotionBuf( const Area& _area ); // 获取特定区域area的运动场motion field
MotionBuf getMotionBuf( const UnitArea& _area ) { return getMotionBuf( _area.Y() ); } // UnitArea的亮度的area的motion field
MotionBuf getMotionBuf() { return getMotionBuf( area.Y() ); } // cs的motion field
const CMotionBuf getMotionBuf( const Area& _area ) const;
const CMotionBuf getMotionBuf( const UnitArea& _area ) const { return getMotionBuf( _area.Y() ); }
const CMotionBuf getMotionBuf() const { return getMotionBuf( area.Y() ); }
MotionInfo& getMotionInfo( const Position& pos ); // 特定位置的运动信息
const MotionInfo& getMotionInfo( const Position& pos ) const;
public:
// ---------------------------------------------------------------------------
// temporary (shadowed) data accessors 数据访问接口
// ---------------------------------------------------------------------------
PelBuf getPredBuf(const CompArea &blk);
const CPelBuf getPredBuf(const CompArea &blk) const;
PelUnitBuf getPredBuf(const UnitArea &unit);
const CPelUnitBuf getPredBuf(const UnitArea &unit) const;
PelBuf getResiBuf(const CompArea &blk);
const CPelBuf getResiBuf(const CompArea &blk) const;
PelUnitBuf getResiBuf(const UnitArea &unit);
const CPelUnitBuf getResiBuf(const UnitArea &unit) const;
PelBuf getRecoBuf(const CompArea &blk);
const CPelBuf getRecoBuf(const CompArea &blk) const;
PelUnitBuf getRecoBuf(const UnitArea &unit);
const CPelUnitBuf getRecoBuf(const UnitArea &unit) const;
PelBuf getOrgResiBuf(const CompArea &blk);
const CPelBuf getOrgResiBuf(const CompArea &blk) const;
PelUnitBuf getOrgResiBuf(const UnitArea &unit);
const CPelUnitBuf getOrgResiBuf(const UnitArea &unit) const;
PelBuf getOrgBuf(const CompArea &blk);
const CPelBuf getOrgBuf(const CompArea &blk) const;
PelUnitBuf getOrgBuf(const UnitArea &unit);
const CPelUnitBuf getOrgBuf(const UnitArea &unit) const;
PelBuf getOrgBuf(const ComponentID &compID);
const CPelBuf getOrgBuf(const ComponentID &compID) const;
PelUnitBuf getOrgBuf();
const CPelUnitBuf getOrgBuf() const;
// pred buffer
PelBuf getPredBuf(const ComponentID &compID) { return m_pred.get(compID); }
const CPelBuf getPredBuf(const ComponentID &compID) const { return m_pred.get(compID); }
PelUnitBuf getPredBuf() { return m_pred; }
const CPelUnitBuf getPredBuf() const { return m_pred; }
// resi buffer
PelBuf getResiBuf(const ComponentID compID) { return m_resi.get(compID); }
const CPelBuf getResiBuf(const ComponentID compID) const { return m_resi.get(compID); }
PelUnitBuf getResiBuf() { return m_resi; }
const CPelUnitBuf getResiBuf() const { return m_resi; }
// org-resi buffer
PelBuf getOrgResiBuf(const ComponentID &compID) { return m_orgr.get(compID); }
const CPelBuf getOrgResiBuf(const ComponentID &compID) const { return m_orgr.get(compID); }
PelUnitBuf getOrgResiBuf() { return m_orgr; }
const CPelUnitBuf getOrgResiBuf() const { return m_orgr; }
// reco buffer
PelBuf getRecoBuf(const ComponentID compID) { return m_reco.get(compID); }
const CPelBuf getRecoBuf(const ComponentID compID) const { return m_reco.get(compID); }
PelUnitBuf getRecoBuf() { return m_reco; }
const CPelUnitBuf getRecoBuf() const { return m_reco; }
private:
inline PelBuf getBuf(const CompArea &blk, const PictureType &type);
inline const CPelBuf getBuf(const CompArea &blk, const PictureType &type) const;
inline PelUnitBuf getBuf(const UnitArea &unit, const PictureType &type);
inline const CPelUnitBuf getBuf(const UnitArea &unit, const PictureType &type) const;
};