基本单元的结构体中,只定义了CU、PU、TU的属性信息,其头文件为Unit.h
,对基本单元的操作定义在UnitTools.h
中。命名空间CU
中定义了对CodingUnit
的操作,命名空间PU
和TU
分别定义了在预测和量化中用到的方法。
描述UnitArea
定义的区域的压缩方法和方式。
struct CodingUnit : public UnitArea
{
CodingStructure *cs; // 父级CodingStructure
Slice *slice; // 指向CU所属slice
ChannelType chType; // 颜色通道类型
PredMode predMode; // 预测模式,帧内还是帧间
uint8_t depth; // 总深度,为QTBTTT的深度,所有划分类型,一旦划分则+1
uint8_t qtDepth; // 四叉树深度
// btDepth和mtDepth都是描述MT的深度,在只有BT划分时,两者相等;但是CU使用TT划分时,两端的BTdepth将比mtdepth大1
uint8_t btDepth; // 二叉树深度
uint8_t mtDepth; // 多叉树深度
int8_t chromaQpAdj; // 色度QP偏移值
int8_t qp; // 实际编码QP值
SplitSeries splitSeries; // 其二进制数标识生成当前CU尺寸时,CTU划分顺序
bool skip; // 是否SKIP模式
bool mmvdSkip; // 是否SKIP with MMVD模式
bool affine; // 是否是affine 模式
int affineType; // 仿射运动模型类型(四参数、六参数)
bool triangle; // 是否三角形运动估计
bool transQuantBypass; // 是否是transform 和 quantization pass by
bool ipcm; // 是否 IPCM模式
uint8_t imv; // 运动适量精度
bool rootCbf; // coding block flag (三个通道都要为0,则为0)
#if JVET_M0140_SBT
uint8_t sbtInfo; // sub-block transform 信息
#endif
#if HEVC_TILES_WPP
uint32_t tileIdx;
#endif
#if !JVET_M0464_UNI_MTS
uint8_t emtFlag; // 多核变换,变换核信息
#endif
uint8_t GBiIdx; // generalized bi search?还未完全明白
int refIdxBi[2]; // 两个参考帧的索引
// needed for fast imv mode decisions
int8_t imvNumCand;
#if JVET_M0170_MRG_SHARELIST
Position shareParentPos; // 上层CU的位置信息
Size shareParentSize; // 上层CU的尺寸信息
#endif
#if JVET_M0483_IBC ==0
bool ibc; // 是否为IBC模式
#endif
#if JVET_M0444_SMVD
uint8_t smvdMode;
#endif
#if JVET_M0102_INTRA_SUBPARTITIONS
uint8_t ispMode; // 是否为ISP模式,帧内改进的逐行预测模式
#endif
// 构造函数
CodingUnit() : chType( CH_L ) { }
CodingUnit(const UnitArea &unit);
CodingUnit(const ChromaFormat _chromaFormat, const Area &area);
CodingUnit& operator=( const CodingUnit& other ); // 运算符重载
void initData(); // 初始化CU信息
unsigned idx; // 在上层CU中的索引
CodingUnit *next; // 指向下一个CU,stack中
PredictionUnit *firstPU; // 指向所包含的第一个PU
PredictionUnit *lastPU; // 指向包含的最后一个PU
TransformUnit *firstTU; // 指向所包含的第一个TU
TransformUnit *lastTU; // 指向包含的最后一个TU
#if JVET_M0140_SBT
const uint8_t getSbtIdx() const { assert( ( ( sbtInfo >> 0 ) & 0xf ) < NUMBER_SBT_IDX ); return ( sbtInfo >> 0 ) & 0xf; }
const uint8_t getSbtPos() const { return ( sbtInfo >> 4 ) & 0x3; }
void setSbtIdx( uint8_t idx ) { CHECK( idx >= NUMBER_SBT_IDX, "sbt_idx wrong" ); sbtInfo = ( idx << 0 ) + ( sbtInfo & 0xf0 ); }
void setSbtPos( uint8_t pos ) { CHECK( pos >= 4, "sbt_pos wrong" ); sbtInfo = ( pos << 4 ) + ( sbtInfo & 0xcf ); }
uint8_t getSbtTuSplit() const;
const uint8_t checkAllowedSbt() const;
#endif
};
描述UnitArea
的区域的预测信号的生成方式。
// IntraPredictionData 定义了帧内预测数据,包括帧内预测模式及相关参考行索引。
// InterPredictionData 定义了帧间预测数据,包含所有帧间预测数据(MV,refidx,merge,skip,trangleMerge,MMVD ,BV等)
struct PredictionUnit : public UnitArea, public IntraPredictionData, public InterPredictionData
{
CodingUnit *cu; // 所属cu
CodingStructure *cs; // 所属cs
ChannelType chType; // 颜色通道类型
// constructors 构造函数
PredictionUnit(): chType( CH_L ) { }
PredictionUnit(const UnitArea &unit);
PredictionUnit(const ChromaFormat _chromaFormat, const Area &area);
void initData(); // PU初始化
PredictionUnit& operator=(const IntraPredictionData& predData);
PredictionUnit& operator=(const InterPredictionData& predData);
PredictionUnit& operator=(const PredictionUnit& other);
PredictionUnit& operator=(const MotionInfo& mi);
unsigned idx; // CU中PU索引
#if JVET_M0170_MRG_SHARELIST
Position shareParentPos; // 上层CU位置和尺寸
Size shareParentSize;
#endif
PredictionUnit *next; // 指向CU中下一个PU
// for accessing motion information, which can have higher resolution than PUs (should always be used, when accessing neighboring motion information)
// 获取运动信息,MV的获取,可在固定位置
const MotionInfo& getMotionInfo() const;
const MotionInfo& getMotionInfo( const Position& pos ) const;
MotionBuf getMotionBuf();
CMotionBuf getMotionBuf() const;
};
描述UnitArea
的变换编码是如何进行的。
struct TransformUnit : public UnitArea
{
CodingUnit *cu;
CodingStructure *cs;
ChannelType chType;
#if JVET_M0427_INLOOP_RESHAPER
int m_chromaResScaleInv;
#endif
uint8_t depth; // TU相对深度
#if JVET_M0464_UNI_MTS
uint8_t mtsIdx; // 变换核索引
#else
uint8_t emtIdx;
#endif
#if JVET_M0140_SBT
bool noResidual; // 残差为0标志
#endif
uint8_t cbf [ MAX_NUM_TBLOCKS ]; // coding block flag
RDPCMMode rdpcm [ MAX_NUM_TBLOCKS ];
#if !JVET_M0464_UNI_MTS
bool transformSkip[ MAX_NUM_TBLOCKS ]; // 是否transform bypass
#endif
int8_t compAlpha [ MAX_NUM_TBLOCKS ];
TransformUnit() : chType( CH_L ) { }
TransformUnit(const UnitArea& unit);
TransformUnit(const ChromaFormat _chromaFormat, const Area &area);
void initData();
unsigned idx; // PU在CU中idx
TransformUnit *next; // 下一个PU、
#if JVET_M0102_INTRA_SUBPARTITIONS
TransformUnit *prev; //
#endif
void init(TCoeff **coeffs, Pel **pcmbuf);
TransformUnit& operator=(const TransformUnit& other);
void copyComponentFrom (const TransformUnit& other, const ComponentID compID);
#if JVET_M0140_SBT
void checkTuNoResidual( unsigned idx ); // 判断残差是否全0
#endif
CoeffBuf getCoeffs(const ComponentID id);
const CCoeffBuf getCoeffs(const ComponentID id) const;
PelBuf getPcmbuf(const ComponentID id);
const CPelBuf getPcmbuf(const ComponentID id) const;
#if JVET_M0427_INLOOP_RESHAPER
// inloop reshaper 针对HDR提出的环内滤波技术
int getChromaAdj( ) const;
void setChromaAdj(int i);
#endif
private:
TCoeff *m_coeffs[ MAX_NUM_TBLOCKS ];
Pel *m_pcmbuf[ MAX_NUM_TBLOCKS ];
};