新的视频编码标准参考软件相较于上一代参考软件HM, 有着z-index 类等函数叠加顺序上不优,TcomdataCU这个数据模型太模糊等等细节问题。 新加入了面向对象设计程序,取消了z-index的使用,消除CTU->z-index的信号寻址。
整体的数据结构模型
引导位置部分 Navigation
- Size, Position, Area (Position + Size)
代表基本的二维导航信息
Size 宽度、高度:UInt–描述矩形的大小 Position x,y:Int–描述一个点的2D位置 Area:Position + Size 位于特定位置的特定大小的矩形 CompArea:Area 多分量信号的特定分量(compID)内的区域
struct Size
{
SizeType width;
SizeType height;
Size() : width(0), height(0) { }
Size(const SizeType _width, const SizeType _height) : width(_width), height(_height) { }
bool operator!=(const Size &other) const { return (width != other.width) || (height != other.height); }
bool operator==(const Size &other) const { return (width == other.width) && (height == other.height); }
uint32_t area() const { return (uint32_t) width * (uint32_t) height; }
#if REUSE_CU_RESULTS_WITH_MULTIPLE_TUS
void resizeTo(const Size newSize) { width = newSize.width; height = newSize.height; }
#endif
};
struct Position
{
PosType x;
PosType y;
Position() : x(0), y(0) { }
Position(const PosType _x, const PosType _y) : x(_x), y(_y) { }
bool operator!=(const Position &other) const { return x != other.x || y != other.y; }
bool operator==(const Position &other) const { return x == other.x && y == other.y; }
Position offset(const Position pos) const { return Position(x + pos.x, y + pos.y); }
Position offset(const PosType _x, const PosType _y) const { return Position(x + _x , y + _y ); }
void repositionTo(const Position newPos) { x = newPos.x; y = newPos.y; }
void relativeTo (const Position origin) { x -= origin.x; y -= origin.y; }
Position operator-( const Position &other ) const { return{ x - other.x, y - other.y };
};
struct Area : public Position, public Size
{
Area() : Position(), Size() { }
Area(const Position &_pos, const Size &_size) : Position(_pos), Size(_size) { }
Area(const PosType _x, const PosType _y, const SizeType _w, const SizeType _h) : Position(_x, _y), Size(_w, _h) { }
Position& pos() { return *this; }
const Position& pos() const { return *this; }
Size& size() { return *this; }
const Size& size() const { return *this; }
const Position& topLeft() const { return *this; }
Position topRight() const { return { (PosType) (x + width - 1), y };
Position bottomLeft() const { return { x , (PosType) (y + height - 1) }; }
Position bottomRight() const { return { (PosType) (x + width - 1), (PosType) (y + height - 1) }; }
Position center() const { return { (PosType) (x + width / 2), (PosType) (y + height / 2) }; }
bool contains(const Position &_pos) const { return (_pos.x >= x) && (_pos.x < (x + width)) && (_pos.y >= y) && (_pos.y < (y + height)); }
bool contains(const Area &_area) const { return contains(_area.pos()) && contains(_area.bottomRight()); }
bool operator!=(const Area &other) const { return (Size::operator!=(other)) || (Position::operator!=(other)); }
bool operator==(const Area &other) const { return (Size::operator==(other)) && (Position::operator==(other)); }
};
- compArea
给定组件(块)中的区域 - UnitArea
表示多通道信号中的一个区域 描述协同定位的组件的组成的一组块
enum ComponentID
{
COMPONENT_Y = 0,
COMPONENT_Cb = 1,
COMPONENT_Cr = 2,
MAX_NUM_COMPONENT = 3,
JOINT_CbCr = MAX_NUM_COMPONENT,
MAX_NUM_TBLOCKS = MAX_NUM_COMPONENT
};
struct CompArea : public Area
{
CompArea() : Area(), chromaFormat(NUM_CHROMA_FORMAT), compID(MAX_NUM_TBLOCKS) { }
CompArea(const ComponentID _compID, const ChromaFormat _cf, const Area &_area, const bool isLuma = false) : Area(_area), chromaFormat(_cf), compID(_compID) { if (isLuma) xRecalcLumaToChroma(); }
CompArea(const ComponentID _compID, const ChromaFormat _cf, const Position& _pos, const Size& _size, const bool isLuma = false) : Area(_pos, _size), chromaFormat(_cf), compID(_compID) { if (isLuma) xRecalcLumaToChroma(); }
CompArea(const ComponentID _compID, const ChromaFormat _cf, const uint32_t _x, const uint32_t _y, const uint32_t _w, const uint32_t _h, const bool isLuma = false) : Area(_x, _y, _w, _h), chromaFormat(_cf), compID(_compID) { if (isLuma) xRecalcLumaToChroma(); }
ChromaFormat chromaFormat;
ComponentID compID;
Position chromaPos() const;
Position lumaPos() const;
Size chromaSize() const;
Size lumaSize() const;
Position compPos( const ComponentID compID ) const;
Position chanPos( const ChannelType chType ) const;
Position topLeftComp (const ComponentID _compID) const { return recalcPosition(chromaFormat, compID, _compID, *this); }
Position topRightComp (const ComponentID _compID) const { return recalcPosition(chromaFormat, compID, _compID, { (PosType) (x + width - 1), y }); }
Position bottomLeftComp (const ComponentID _compID) const { return recalcPosition(chromaFormat, compID, _compID, { x , (PosType) (y + height - 1 )}); }
Position bottomRightComp(const ComponentID _compID) const { return recalcPosition(chromaFormat, compID, _compID, { (PosType) (x + width - 1), (PosType) (y + height - 1 )}); }
bool valid() const { return chromaFormat < NUM_CHROMA_FORMAT && compID < MAX_NUM_TBLOCKS && width != 0 && height != 0; }
const bool operator==(const CompArea &other) const
{
if (chromaFormat != other.chromaFormat) return false;
if (compID != other.compID) return false;
return Position::operator==(other) && Size::operator==(other);
}
const bool operator!=(const CompArea &other) const { return !(operator==(other)); }
#if REUSE_CU_RESULTS_WITH_MULTIPLE_TUS
void resizeTo (const Size& newSize) { Size::resizeTo(newSize); }
#endif
void repositionTo (const Position& newPos) { Position::repositionTo(newPos); }
void positionRelativeTo(const CompArea& origCompArea) { Position::relativeTo(origCompArea); }
private:
void xRecalcLumaToChroma();
};
struct UnitArea
{
ChromaFormat chromaFormat;
UnitBlocksType blocks;
UnitArea() : chromaFormat(NUM_CHROMA_FORMAT) { }
UnitArea(const ChromaFormat _chromaFormat);
UnitArea(const ChromaFormat _chromaFormat, const Area &area);
UnitArea(const ChromaFormat _chromaFormat, const CompArea &blkY);
UnitArea(const ChromaFormat _chromaFormat, CompArea &&blkY);
UnitArea(const ChromaFormat _chromaFormat, const CompArea &blkY, const CompArea &blkCb, const CompArea &blkCr);
UnitArea(const ChromaFormat _chromaFormat, CompArea &&blkY, CompArea &&blkCb, CompArea &&blkCr);
CompArea& Y() { return blocks[COMPONENT_Y]; }
const CompArea& Y() const { return blocks[COMPONENT_Y]; }
CompArea& Cb() { return blocks[COMPONENT_Cb]; }
const CompArea& Cb() const { return blocks[COMPONENT_Cb]; }
CompArea& Cr() { return blocks[COMPONENT_Cr]; }
const CompArea& Cr() const { return blocks[COMPONENT_Cr]; }
CompArea& block(const ComponentID comp) { return blocks[comp]; }
const CompArea& block(const ComponentID comp) const { return blocks[comp]; }
bool contains(const UnitArea& other) const;
bool contains(const UnitArea& other, const ChannelType chType) const;
CompArea& operator[]( const int n ) { return blocks[n]; }
const CompArea& operator[]( const int n ) const { return blocks[n]; }
const bool operator==(const UnitArea &other) const
{
if (chromaFormat != other.chromaFormat) return false;
if (blocks.size() != other.blocks.size()) return false;
for (uint32_t i = 0; i < blocks.size(); i++)
{
if (blocks[i] != other.blocks[i]) return false;
}
return true;
}
#if REUSE_CU_RESULTS_WITH_MULTIPLE_TUS
void resizeTo (const UnitArea& unit);
#endif
void repositionTo(const UnitArea& unit);
const bool operator!=(const UnitArea &other) const { return !(*this == other); }
const Position& lumaPos () const { return Y(); }
const Size& lumaSize() const { return Y(); }
const Position& chromaPos () const { return Cb(); }
const Size& chromaSize() const { return Cb(); }
const UnitArea singleComp(const ComponentID compID) const;
const UnitArea singleChan(const ChannelType chType) const;
const SizeType lwidth() const { return Y().width; }
const SizeType lheight() const { return Y().height; }
const PosType lx() const { return Y().x; }
const PosType ly() const { return Y().y; }
bool valid() const { return chromaFormat != NUM_CHROMA_FORMAT && blocks.size() > 0; }
};
UnitArea blocks [0…N-1]: CompArea 由N个块组成的组合体,a multi-component compound consisting of N blocks CodingUnit : UnitArea 描述如何对这个UnitArea描述的区域进行编码 PredictionUnit : UnitArea 描述如何生成该UnitArea的预测信号 TransformUnit : UnitArea 描述如何应用此UnitArea的转换编码
信号存储器部分(signal storage)
- AreaBuf
描述二维信号在线性存储器中的存储布局 包含简单的操作(复制、填充等)。)
(1) AreaBuf (defined for Pel and TCoeff as PelAreaBuf and CoeffAreaBuf)
at(x,y) –返回位置(x,y)处的信号值 bufAt(x,y) –返回指向缓冲区位置(x,y)的原始指针 subBuf(x,y,w,h) -返回一个AreaBuf,描述一个大小为(w,h)的区域偏移量(x,y) fill(val) –用定义的值填充指定区域 copy from(other) –从其他区域复制内容 substract、addAvg、reconstruct、removeHighFreq –替代TComYuv功能的方法 (2) UnitBuf (similar interface to AreaBuf) bufs[0…n-1]:Areabuf–包含不同组件的信号描述
- UnitAreaBuf
描述了多分量二维信号在线性存储器中的存储布局 包含简单的操作(复制、填充等)。) - PelStorage
一个UnitAreaBuf,它也分配自己的内存
编码信息(coding information)
- picture
包含输入和输出信号以及元数据(切片信息等。) - CodingUnit, PredictionUnit, TransformUnit
单个单元的单个对象 包含相应的信息 包括位置信息(从UnitArea获得) - CodingStructure
管理编码单元,将它们与图片链接 包含自上而下RD搜索的附加功能
struct CodingUnit : public UnitArea
{
CodingStructure *cs;
Slice *slice;
ChannelType chType;
PredMode predMode;
uint8_t depth;
uint8_t qtDepth;
uint8_t btDepth;
uint8_t mtDepth;
int8_t chromaQpAdj;
int8_t qp;
SplitSeries splitSeries;
TreeType treeType;
ModeType modeType;
ModeTypeSeries modeTypeSeries;
bool skip;
bool mmvdSkip;
bool affine;
int affineType;
bool colorTransform;
bool geoFlag;
int bdpcmMode;
int bdpcmModeChroma;
uint8_t imv;
bool rootCbf;
uint8_t sbtInfo;
uint32_t tileIdx;
uint8_t mtsFlag;
uint32_t lfnstIdx;
uint8_t BcwIdx;
int refIdxBi[2];
bool mipFlag;
int8_t imvNumCand;
uint8_t smvdMode;
uint8_t ispMode;
bool useEscape[MAX_NUM_CHANNEL_TYPE];
bool useRotation[MAX_NUM_CHANNEL_TYPE];
bool reuseflag[MAX_NUM_CHANNEL_TYPE][MAXPLTPREDSIZE];
uint8_t lastPLTSize[MAX_NUM_CHANNEL_TYPE];
uint8_t reusePLTSize[MAX_NUM_CHANNEL_TYPE];
uint8_t curPLTSize[MAX_NUM_CHANNEL_TYPE];
Pel curPLT[MAX_NUM_COMPONENT][MAXPLTSIZE];
CodingUnit() : chType( CH_L ) { }
CodingUnit(const UnitArea &unit);
CodingUnit(const ChromaFormat _chromaFormat, const Area &area);
CodingUnit& operator=( const CodingUnit& other );
void initData();
unsigned idx;
CodingUnit *next;
PredictionUnit *firstPU;
PredictionUnit *lastPU;
TransformUnit *firstTU;
TransformUnit *lastTU;
#if ENABLE_SPLIT_PARALLELISM
int64_t cacheId;
bool cacheUsed;
#endif
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;
const bool checkCCLMAllowed() const;
const bool isSepTree() const;
const bool isLocalSepTree() const;
const bool isConsInter() const { return modeType == MODE_TYPE_INTER; }
const bool isConsIntra() const { return modeType == MODE_TYPE_INTRA; }
};
编码结构结构体
class CodingStructure
{
public:
UnitArea area;
Picture *picture;
CodingStructure *parent;
CodingStructure *bestCS;
Slice *slice;
UnitScale unitScale[MAX_NUM_COMPONENT];
int baseQP;
int prevQP[MAX_NUM_CHANNEL_TYPE];
int currQP[MAX_NUM_CHANNEL_TYPE];
int chromaQpAdj;
const SPS *sps;
const PPS *pps;
PicHeader *picHeader;
APS* alfApss[ALF_CTB_MAX_NUM_APS];
APS * lmcsAps;
APS * scalinglistAps;
const VPS *vps;
const PreCalcValues* pcv;
CodingStructure(CUCache&, PUCache&, TUCache&);
void create(const UnitArea &_unit, const bool isTopLayer, const bool isPLTused);
void create(const ChromaFormat &_chromaFormat, const Area& _area, const bool isTopLayer, const bool isPLTused);
void destroy();
void releaseIntermediateData();
void rebindPicBufs();
void createCoeffs(const bool isPLTused);
void destroyCoeffs();
void allocateVectorsAtPicLevel();
bool isDecomp (const Position &pos, const ChannelType _chType) const;
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;
const PredictionUnit *getPU(const Position &pos, const ChannelType _chType) const;
const TransformUnit *getTU(const Position &pos, const ChannelType _chType, const int subTuIdx = -1) const;
CodingUnit *getCU(const Position &pos, const ChannelType _chType);
CodingUnit *getLumaCU( const Position &pos );
PredictionUnit *getPU(const Position &pos, const ChannelType _chType);
TransformUnit *getTU(const Position &pos, const ChannelType _chType, const int subTuIdx = -1);
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); }
const CodingUnit *getCURestricted(const Position &pos, const Position curPos, const unsigned curSliceIdx, const unsigned curTileIdx, const ChannelType _chType) const;
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;
CodingUnit& addCU(const UnitArea &unit, const ChannelType _chType);
PredictionUnit& addPU(const UnitArea &unit, const ChannelType _chType);
TransformUnit& addTU(const UnitArea &unit, const ChannelType _chType);
void addEmptyTUs(Partitioner &partitioner);
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;
static_vector<double, NUM_ENC_FEATURES> features;
double cost;
bool useDbCost;
double costDbOffset;
double lumaCost;
uint64_t fracBits;
Distortion dist;
Distortion interHad;
TreeType treeType;
ModeType modeType;
void initStructData (const int &QP = MAX_INT, const bool &skipMotBuf = false);
void initSubStructure( CodingStructure& cs, const ChannelType chType, const UnitArea &subArea, const bool &isTuEnc);
void copyStructure (const CodingStructure& cs, const ChannelType chType, const bool copyTUs = false, const bool copyRecoBuffer = false);
void useSubStructure (const CodingStructure& cs, const ChannelType chType, const UnitArea &subArea, const bool cpyPred, const bool cpyReco, const bool cpyOrgResi, const bool cpyResi, const bool updateCost);
void useSubStructure (const CodingStructure& cs, const ChannelType chType, const bool cpyPred, const bool cpyReco, const bool cpyOrgResi, const bool cpyResi, const bool updateCost) { useSubStructure(cs, chType, cs.area, cpyPred, cpyReco, cpyOrgResi, cpyResi, updateCost); }
void clearTUs();
void clearPUs();
void clearCUs();
const int signalModeCons( const PartSplit split, Partitioner &partitioner, const ModeType modeTypeParent ) const;
void clearCuPuTuIdxMap ( const UnitArea &_area, uint32_t numCu, uint32_t numPu, uint32_t numTu, uint32_t* pOffset );
void getNumCuPuTuOffset ( uint32_t* pArray )
{
pArray[0] = m_numCUs; pArray[1] = m_numPUs; pArray[2] = m_numTUs;
pArray[3] = m_offsets[0]; pArray[4] = m_offsets[1]; pArray[5] = m_offsets[2];
}
private:
void createInternals(const UnitArea& _unit, const bool isTopLayer, const bool isPLTused);
public:
std::vector< CodingUnit*> cus;
std::vector<PredictionUnit*> pus;
std::vector< TransformUnit*> tus;
LutMotionCand motionLut;
void addMiToLut(static_vector<MotionInfo, MAX_NUM_HMVP_CANDS>& lut, const MotionInfo &mi);
PLTBuf prevPLT;
void resetPrevPLT(PLTBuf& prevPLT);
void reorderPrevPLT(PLTBuf& prevPLT, uint8_t curPLTSize[MAX_NUM_CHANNEL_TYPE], Pel curPLT[MAX_NUM_COMPONENT][MAXPLTSIZE], bool reuseflag[MAX_NUM_CHANNEL_TYPE][MAXPLTPREDSIZE], uint32_t compBegin, uint32_t numComp, bool jointPLT);
void setPrevPLT(PLTBuf predictor);
void storePrevPLT(PLTBuf& predictor);
private:
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;
PelStorage m_pred;
PelStorage m_resi;
PelStorage m_reco;
PelStorage m_orgr;
TCoeff *m_coeffs [ MAX_NUM_COMPONENT ];
Pel *m_pcmbuf [ MAX_NUM_COMPONENT ];
bool *m_runType[ MAX_NUM_CHANNEL_TYPE ];
int m_offsets[ MAX_NUM_COMPONENT ];
MotionInfo *m_motionBuf;
public:
CodingStructure *bestParent;
double tmpColorSpaceCost;
bool firstColorSpaceSelected;
double tmpColorSpaceIntraCost[2];
bool firstColorSpaceTestOnly;
bool resetIBCBuffer;
MotionBuf getMotionBuf( const Area& _area );
MotionBuf getMotionBuf( const UnitArea& _area ) { return getMotionBuf( _area.Y() ); }
MotionBuf getMotionBuf() { return getMotionBuf( area.Y() ); }
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:
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;
PelUnitBuf& getRecoBufRef() { return m_reco; }
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;
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; }
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; }
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; }
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;
};
struct Picture : public UnitArea
{
uint32_t margin;
Picture();
void create( const ChromaFormat &_chromaFormat, const Size &size, const unsigned _maxCUSize, const unsigned margin, const bool bDecoder, const int layerId, const bool gopBasedTemporalFilterEnabled = false );
void destroy();
void createTempBuffers( const unsigned _maxCUSize );
void destroyTempBuffers();
PelBuf getOrigBuf(const CompArea &blk);
const CPelBuf getOrigBuf(const CompArea &blk) const;
PelUnitBuf getOrigBuf(const UnitArea &unit);
const CPelUnitBuf getOrigBuf(const UnitArea &unit) const;
PelUnitBuf getOrigBuf();
const CPelUnitBuf getOrigBuf() const;
PelBuf getOrigBuf(const ComponentID compID);
const CPelBuf getOrigBuf(const ComponentID compID) const;
PelUnitBuf getTrueOrigBuf();
const CPelUnitBuf getTrueOrigBuf() const;
PelBuf getTrueOrigBuf(const CompArea &blk);
const CPelBuf getTrueOrigBuf(const CompArea &blk) const;
PelUnitBuf getFilteredOrigBuf();
const CPelUnitBuf getFilteredOrigBuf() const;
PelBuf getFilteredOrigBuf(const CompArea &blk);
const CPelBuf getFilteredOrigBuf(const CompArea &blk) const;
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 ComponentID compID, bool wrap=false);
const CPelBuf getRecoBuf(const ComponentID compID, bool wrap=false) const;
PelBuf getRecoBuf(const CompArea &blk, bool wrap=false);
const CPelBuf getRecoBuf(const CompArea &blk, bool wrap=false) const;
PelUnitBuf getRecoBuf(const UnitArea &unit, bool wrap=false);
const CPelUnitBuf getRecoBuf(const UnitArea &unit, bool wrap=false) const;
PelUnitBuf getRecoBuf(bool wrap=false);
const CPelUnitBuf getRecoBuf(bool wrap=false) const;
PelBuf getBuf(const ComponentID compID, const PictureType &type);
const CPelBuf getBuf(const ComponentID compID, const PictureType &type) const;
PelBuf getBuf(const CompArea &blk, const PictureType &type);
const CPelBuf getBuf(const CompArea &blk, const PictureType &type) const;
PelUnitBuf getBuf(const UnitArea &unit, const PictureType &type);
const CPelUnitBuf getBuf(const UnitArea &unit, const PictureType &type) const;
void extendPicBorder( const PPS *pps );
void extendWrapBorder( const PPS *pps );
void finalInit( const VPS* vps, const SPS& sps, const PPS& pps, PicHeader *picHeader, APS** alfApss, APS* lmcsAps, APS* scalingListAps );
int getPOC() const { return poc; }
int getDecodingOrderNumber() const { return m_decodingOrderNumber; }
void setDecodingOrderNumber(const int val) { m_decodingOrderNumber = val; }
NalUnitType getPictureType() const { return m_pictureType; }
void setPictureType(const NalUnitType val) { m_pictureType = val; }
void setBorderExtension( bool bFlag) { m_bIsBorderExtended = bFlag;}
Pel* getOrigin( const PictureType &type, const ComponentID compID ) const;
void setLossyQPValue(int i) { m_lossyQP = i; }
int getLossyQPValue() const { return m_lossyQP; }
void fillSliceLossyLosslessArray(std::vector<uint16_t> sliceLosslessArray, bool mixedLossyLossless);
bool losslessSlice(uint32_t sliceIdx) const { return m_lossylosslessSliceArray[sliceIdx]; }
int getSpliceIdx(uint32_t idx) const { return m_spliceIdx[idx]; }
void setSpliceIdx(uint32_t idx, int poc) { m_spliceIdx[idx] = poc; }
void createSpliceIdx(int nums);
bool getSpliceFull();
static void sampleRateConv( const std::pair<int, int> scalingRatio, const std::pair<int, int> compScale,
const CPelBuf& beforeScale, const int beforeScaleLeftOffset, const int beforeScaleTopOffset,
const PelBuf& afterScale, const int afterScaleLeftOffset, const int afterScaleTopOffset,
const int bitDepth, const bool useLumaFilter, const bool downsampling,
const bool horCollocatedPositionFlag, const bool verCollocatedPositionFlag );
static void rescalePicture( const std::pair<int, int> scalingRatio,
const CPelUnitBuf& beforeScaling, const Window& scalingWindowBefore,
const PelUnitBuf& afterScaling, const Window& scalingWindowAfter,
const ChromaFormat chromaFormatIDC, const BitDepths& bitDepths, const bool useLumaFilter, const bool downsampling,
const bool horCollocatedChromaFlag, const bool verCollocatedChromaFlag );
private:
Window m_conformanceWindow;
Window m_scalingWindow;
int m_decodingOrderNumber;
NalUnitType m_pictureType;
public:
bool m_isSubPicBorderSaved;
PelStorage m_bufSubPicAbove;
PelStorage m_bufSubPicBelow;
PelStorage m_bufSubPicLeft;
PelStorage m_bufSubPicRight;
PelStorage m_bufWrapSubPicAbove;
PelStorage m_bufWrapSubPicBelow;
void saveSubPicBorder(int POC, int subPicX0, int subPicY0, int subPicWidth, int subPicHeight);
void extendSubPicBorder(int POC, int subPicX0, int subPicY0, int subPicWidth, int subPicHeight);
void restoreSubPicBorder(int POC, int subPicX0, int subPicY0, int subPicWidth, int subPicHeight);
bool getSubPicSaved() { return m_isSubPicBorderSaved; }
void setSubPicSaved(bool bVal) { m_isSubPicBorderSaved = bVal; }
bool m_bIsBorderExtended;
bool m_wrapAroundValid;
unsigned m_wrapAroundOffset;
bool referenced;
bool reconstructed;
bool neededForOutput;
bool usedByCurr;
bool longTerm;
bool topField;
bool fieldPic;
int m_prevQP[MAX_NUM_CHANNEL_TYPE];
bool precedingDRAP;
bool nonReferencePictureFlag;
int poc;
uint32_t temporalId;
int layerId;
std::vector<SubPic> subPictures;
int numSlices;
std::vector<int> sliceSubpicIdx;
bool subLayerNonReferencePictureDueToSTSA;
int* m_spliceIdx;
int m_ctuNums;
int m_lossyQP;
std::vector<bool> m_lossylosslessSliceArray;
bool interLayerRefPicFlag;
#if ENABLE_SPLIT_PARALLELISM
PelStorage m_bufs[PARL_SPLIT_MAX_NUM_JOBS][NUM_PIC_TYPES];
#else
PelStorage m_bufs[NUM_PIC_TYPES];
#endif
const Picture* unscaledPic;
TComHash m_hashMap;
TComHash* getHashMap() { return &m_hashMap; }
const TComHash* getHashMap() const { return &m_hashMap; }
void addPictureToHashMapForInter();
CodingStructure* cs;
std::deque<Slice*> slices;
SEIMessages SEIs;
uint32_t getPicWidthInLumaSamples() const { return getRecoBuf( COMPONENT_Y ).width; }
uint32_t getPicHeightInLumaSamples() const { return getRecoBuf( COMPONENT_Y ).height; }
Window& getConformanceWindow() { return m_conformanceWindow; }
const Window& getConformanceWindow() const { return m_conformanceWindow; }
Window& getScalingWindow() { return m_scalingWindow; }
const Window& getScalingWindow() const { return m_scalingWindow; }
bool isRefScaled( const PPS* pps ) const { return unscaledPic->getPicWidthInLumaSamples() != pps->getPicWidthInLumaSamples() ||
unscaledPic->getPicHeightInLumaSamples() != pps->getPicHeightInLumaSamples() ||
getScalingWindow().getWindowLeftOffset() != pps->getScalingWindow().getWindowLeftOffset() ||
getScalingWindow().getWindowRightOffset() != pps->getScalingWindow().getWindowRightOffset() ||
getScalingWindow().getWindowTopOffset() != pps->getScalingWindow().getWindowTopOffset() ||
getScalingWindow().getWindowBottomOffset() != pps->getScalingWindow().getWindowBottomOffset(); }
bool isWrapAroundEnabled( const PPS* pps ) const { return pps->getWrapAroundEnabledFlag() && !isRefScaled( pps ); }
void allocateNewSlice();
Slice *swapSliceObject(Slice * p, uint32_t i);
void clearSliceBuffer();
MCTSInfo mctsInfo;
std::vector<AQpLayer*> aqlayer;
#if !KEEP_PRED_AND_RESI_SIGNALS
private:
UnitArea m_ctuArea;
#endif
#if ENABLE_SPLIT_PARALLELISM
public:
void finishParallelPart ( const UnitArea& ctuArea );
#endif
#if ENABLE_SPLIT_PARALLELISM
public:
Scheduler scheduler;
#endif
public:
SAOBlkParam *getSAO(int id = 0) { return &m_sao[id][0]; };
void resizeSAO(unsigned numEntries, int dstid) { m_sao[dstid].resize(numEntries); }
void copySAO(const Picture& src, int dstid) { std::copy(src.m_sao[0].begin(), src.m_sao[0].end(), m_sao[dstid].begin()); }
#if ENABLE_QPA
std::vector<double> m_uEnerHpCtu;
std::vector<Pel> m_iOffsetCtu;
#if ENABLE_QPA_SUB_CTU
std::vector<int8_t> m_subCtuQP;
#endif
#endif
std::vector<SAOBlkParam> m_sao[2];
std::vector<uint8_t> m_alfCtuEnableFlag[MAX_NUM_COMPONENT];
uint8_t* getAlfCtuEnableFlag( int compIdx ) { return m_alfCtuEnableFlag[compIdx].data(); }
std::vector<uint8_t>* getAlfCtuEnableFlag() { return m_alfCtuEnableFlag; }
void resizeAlfCtuEnableFlag( int numEntries )
{
for( int compIdx = 0; compIdx < MAX_NUM_COMPONENT; compIdx++ )
{
m_alfCtuEnableFlag[compIdx].resize( numEntries );
std::fill( m_alfCtuEnableFlag[compIdx].begin(), m_alfCtuEnableFlag[compIdx].end(), 0 );
}
}
std::vector<short> m_alfCtbFilterIndex;
short* getAlfCtbFilterIndex() { return m_alfCtbFilterIndex.data(); }
std::vector<short>& getAlfCtbFilterIndexVec() { return m_alfCtbFilterIndex; }
void resizeAlfCtbFilterIndex(int numEntries)
{
m_alfCtbFilterIndex.resize(numEntries);
for (int i = 0; i < numEntries; i++)
{
m_alfCtbFilterIndex[i] = 0;
}
}
std::vector<uint8_t> m_alfCtuAlternative[MAX_NUM_COMPONENT];
std::vector<uint8_t>& getAlfCtuAlternative( int compIdx ) { return m_alfCtuAlternative[compIdx]; }
uint8_t* getAlfCtuAlternativeData( int compIdx ) { return m_alfCtuAlternative[compIdx].data(); }
void resizeAlfCtuAlternative( int numEntries )
{
for( int compIdx = 1; compIdx < MAX_NUM_COMPONENT; compIdx++ )
{
m_alfCtuAlternative[compIdx].resize( numEntries );
std::fill( m_alfCtuAlternative[compIdx].begin(), m_alfCtuAlternative[compIdx].end(), 0 );
}
}
};
编码结构codingstructure:
为了便于管理,新增了一个类CodingStructure把一帧中的CU全都放在了这里,这样对CU的操作变得更加方便,可以直接通过坐标来取得所要的CU
- 包含CodingUnit等。实例化并映射它们到picture上
- TComDataCU的替换,但全局分配
顶层编码结构包含帧中的所有CU、PU和TU信息 子级编码结构包含一个特定单位区域的表示 - 创建之后,它是空的,需要被填充
addCU/PU/TU方法创建并映射特定的对象 getCU/PU/TU获取使用全局位置寻址的特定对象 - 动态分配所需的资源
使用dynamic_cache(动态缓存)提高性能
codingStructure中的几个操作: area:unit area——描述编码结构跨越图片中的哪个区域 addCU(UnitArea)-创建并定位一个跨越UnitArea的编码单元 getCU(Position)–返回位于指定位置的编码单位 (PredictionUnit, TransformUnit有模拟接口) set decomp(CompArea)–将指定的CompArea设置为重建的 set decomp(UnitArea)-模拟多通道操作 is decomp(Position)-告知该位置的重建信号是否已生成
initStructData(…)–清除当前包含的所有数据(信号和编码信息) init substructure(…)–在层次结构的底部链接新的编码结构 use substructure(…)–从子结构中复制编码数据 copy structure(…)–从另一个结构复制编码数据,不依赖于父子绑定
codingstructure 的 rdcost过程
通过codingstruture的分层级联搜索: best-temp搜索方案。 codingstructure在一个局部的区域建立,访问UnitArea之外需要返回上层的cs。 cs1是cs2的父节点,父节点不知道子节点,但是最好的子节点将传递给父节点。 通过cs2访问(32,32)位置的CU,直接就返回cu2这个cu单元。 而想要获取非cs2所在的area的cu,可以通过父节点cs1,最后返回[16,32]的cu单元。 想要通过cs1父节点访问子节点位置的cu,访问不到,只能返回null。
partitioner
- 一个简单的类管理分裂(CU和TU,四叉树和MTT)
- 建模为一个堆栈——在当前处理的区域上创建新的拆分作为拆分级别
- 比较于HEVC
包含当前拆分信息的访问器(partitioner.curr*) 深度(CU,TU)以及实际的当前UnitArea - 对于QTBT和其他(除HEVC功能外)
允许设置分割限制(例如,特定级别的约束分割) 允许执行分割合理性检查(canSplit) // 需提前了解其他数据结构
typedef std::vector <UnitArea> Partitioning;
struct PartLevel
{
PartSplit split;
Partitioning parts;
unsigned idx;
bool checkdIfImplicit;
bool isImplicit;
PartSplit implicitSplit;
PartSplit firstSubPartSplit;
bool canQtSplit;
bool qgEnable;
bool qgChromaEnable;
int modeType;
PartLevel();
PartLevel( const PartSplit _split, const Partitioning& _parts );
PartLevel( const PartSplit _split, Partitioning&& _parts );
};
typedef static_vector<PartLevel, 2 * MAX_CU_DEPTH + 1> PartitioningStack;
class Partitioner
{
protected:
PartitioningStack m_partStack;
#if _DEBUG
UnitArea m_currArea;
#endif
public:
unsigned currDepth;
unsigned currQtDepth;
unsigned currTrDepth;
unsigned currBtDepth;
unsigned currMtDepth;
unsigned currSubdiv;
Position currQgPos;
Position currQgChromaPos;
unsigned currImplicitBtDepth;
ChannelType chType;
TreeType treeType;
ModeType modeType;
virtual ~Partitioner () { }
const PartLevel& currPartLevel () const { return m_partStack.back(); }
const UnitArea& currArea () const { return currPartLevel().parts[currPartIdx()]; }
const unsigned currPartIdx () const { return currPartLevel().idx; }
const PartitioningStack& getPartStack () const { return m_partStack; }
const bool currQgEnable () const { return currPartLevel().qgEnable; }
const bool currQgChromaEnable () const { return currPartLevel().qgChromaEnable; }
SplitSeries getSplitSeries () const;
ModeTypeSeries getModeTypeSeries () const;
virtual void initCtu ( const UnitArea& ctuArea, const ChannelType _chType, const Slice& slice ) = 0;
virtual void splitCurrArea ( const PartSplit split, const CodingStructure &cs ) = 0;
virtual void exitCurrSplit () = 0;
virtual bool nextPart ( const CodingStructure &cs, bool autoPop = false ) = 0;
virtual bool hasNextPart () = 0;
virtual void setCUData ( CodingUnit& cu );
virtual void copyState ( const Partitioner& other );
public:
virtual void canSplit ( const CodingStructure &cs, bool& canNo, bool& canQt, bool& canBh, bool& canBv, bool& canTh, bool& canTv ) = 0;
virtual bool canSplit ( const PartSplit split, const CodingStructure &cs ) = 0;
virtual bool isSplitImplicit ( const PartSplit split, const CodingStructure &cs ) = 0;
virtual PartSplit getImplicitSplit ( const CodingStructure &cs ) = 0;
bool isSepTree ( const CodingStructure &cs );
bool isLocalSepTree ( const CodingStructure &cs );
bool isConsInter () { return modeType == MODE_TYPE_INTER; }
bool isConsIntra () { return modeType == MODE_TYPE_INTRA; }
};
所有权
每个数据块都由某个对象拥有,该对象需要分配和释放它 画 由EncLib或DecLib拥有 拥有信号缓冲区、切片对象、SEI消息和TileMap AreaBuf,UnitBuf 不拥有任何数据 像素存储 可能拥有缓冲区(取决于create或createFromBuf是否用于创建) 拥有的数据存储在m_origin成员中
编码结构 顶层:归图片所有 链接到图片的信号缓冲区,不拥有它们 其他(RD-Search中的临时):归EncCu或IntraSearch所有 包含自己的信号缓冲器,拥有它们 总是拥有描述结构和布局的缓冲区(不是信号) 拥有变换系数缓冲器 不拥有CodingUnit等。,只通过dynamic_cache链接到它们
编码单元,预测单元,转换单元 归dynamic_cache所有–对象需要由get获取,由cache释放 变压器单元 不拥有变换系数缓冲器 从编码结构到缓冲区的链接 动态缓存 顶层缓存是全局的(在运行时动态分配,在退出时释放) RD-搜索缓存归EncCu和IntraSearch所有
|