-
Huanbang Chen authored
1. JVET-L0271: Simplification of affine AMVP list construction 2. JVET_L0694/L0045/L0047: Combination of affine mode clean up and line buffer reduction 3. JVET_L0632/L0142: Affine merge list construction 4. JVET_L0369: Moving ATMVP into the affine merge list
Huanbang Chen authored1. JVET-L0271: Simplification of affine AMVP list construction 2. JVET_L0694/L0045/L0047: Combination of affine mode clean up and line buffer reduction 3. JVET_L0632/L0142: Affine merge list construction 4. JVET_L0369: Moving ATMVP into the affine merge list
Contexts.h 16.42 KiB
/* The copyright in this software is being made available under the BSD
* License, included below. This software may be subject to other third party
* and contributor rights, including patent rights, and no such rights are
* granted under this license.
*
* Copyright (c) 2010-2018, ITU/ISO/IEC
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* * Neither the name of the ITU/ISO/IEC nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
/** \file Contexts.h
* \brief Classes providing probability descriptions and contexts (header)
*/
#ifndef __CONTEXTS__
#define __CONTEXTS__
#include "CommonDef.h"
#include "Slice.h"
#include <vector>
struct BinFracBits
{
uint32_t intBits[2];
};
enum BPMType
{
BPM_Undefined = 0,
BPM_Std,
BPM_NUM
};
class ProbModelTables
{
protected:
static const uint8_t m_NextState [128][2]; // Std
static const uint32_t m_EstFracBits [128]; // Std
static const BinFracBits m_BinFracBits_128 [128]; // Std
static const uint32_t m_EstFracProb [128]; // Std
static const uint8_t m_LPSTable_64_4 [ 64][4]; // Std
static const uint8_t m_RenormTable_32 [ 32]; // Std MP MPI
};
class BinProbModelBase : public ProbModelTables
{
public:
BinProbModelBase () {}
~BinProbModelBase() {}
static uint32_t estFracBitsEP () { return ( 1 << SCALE_BITS ); }
static uint32_t estFracBitsEP ( unsigned numBins ) { return ( numBins << SCALE_BITS ); }
};
class BinProbModel_Std : public BinProbModelBase
{
public:
BinProbModel_Std () : m_State( 0 ) {}
~BinProbModel_Std () {}
public:
void init ( int qp, int initId );
void update ( unsigned bin ) { m_State = m_NextState [m_State][bin]; }
static uint8_t getDefaultWinSize () { return uint8_t(0); }
void setLog2WindowSize ( uint8_t log2WindowSize ) {}
void estFracBitsUpdate ( unsigned bin, uint64_t& b ) { b += m_EstFracBits [m_State ^bin];
m_State = m_NextState [m_State][bin]; }
uint32_t estFracBits ( unsigned bin ) const { return m_EstFracBits [m_State ^bin]; }
static uint32_t estFracBitsTrm ( unsigned bin ) { return ( bin ? 0x3bfbb : 0x0010c ); }
BinFracBits getFracBitsArray () const { return m_BinFracBits_128 [m_State]; }
public:
uint8_t state () const { return ( m_State >> 1 ); }
uint8_t mps () const { return ( m_State & 1 ); }
uint8_t getLPS ( unsigned range ) const { return m_LPSTable_64_4 [m_State>>1][(range>>6)&3]; }
static uint8_t getRenormBitsLPS ( unsigned LPS ) { return m_RenormTable_32 [LPS>>3]; }
static uint8_t getRenormBitsRange( unsigned range ) { return 1; }
uint16_t getState () const { return uint16_t(m_State); }
void setState ( uint16_t pState ) { m_State = uint8_t ( pState); }
public:
uint64_t estFracExcessBits ( const BinProbModel_Std& r ) const
{
return ( ((uint64_t)m_EstFracProb[m_State^0]) * m_EstFracBits[r.m_State^0]
+ ((uint64_t)m_EstFracProb[m_State^1]) * m_EstFracBits[r.m_State^1] + ( 1 << ( SCALE_BITS - 1 ) ) ) >> SCALE_BITS;
}
private:
uint8_t m_State;
};
class CtxSet
{
public:
CtxSet( uint16_t offset, uint16_t size ) : Offset( offset ), Size( size ) {}
CtxSet( const CtxSet& ctxSet ) : Offset( ctxSet.Offset ), Size( ctxSet.Size ) {}
CtxSet( std::initializer_list<CtxSet> ctxSets );
public:
uint16_t operator() () const
{
return Offset;
}
uint16_t operator() ( uint16_t inc ) const
{
CHECKD( inc >= Size, "Specified context increment (" << inc << ") exceed range of context set [0;" << Size - 1 << "]." );
return Offset + inc;
}
bool operator== ( const CtxSet& ctxSet ) const
{
return ( Offset == ctxSet.Offset && Size == ctxSet.Size );
}
bool operator!= ( const CtxSet& ctxSet ) const
{
return ( Offset != ctxSet.Offset || Size != ctxSet.Size );
}
public:
uint16_t Offset;
uint16_t Size;
};
class ContextSetCfg
{
public:
// context sets: specify offset and size
static const CtxSet SplitFlag;
static const CtxSet BTSplitFlag;
static const CtxSet SkipFlag;
static const CtxSet MergeFlag;
static const CtxSet MergeIdx;
static const CtxSet PartSize;
static const CtxSet PredMode;
static const CtxSet IPredMode [2]; // [ ChannelType ]
static const CtxSet PdpcFlag;
static const CtxSet DeltaQP;
static const CtxSet InterDir;
static const CtxSet RefPic;
#if JVET_L0054_MMVD
static const CtxSet MmvdFlag;
static const CtxSet MmvdMergeIdx;
static const CtxSet MmvdStepMvpIdx;
#endif
static const CtxSet AffineFlag;
static const CtxSet AffineType;
#if JVET_L0632_AFFINE_MERGE
static const CtxSet AffMergeIdx;
#endif
static const CtxSet Mvd;
static const CtxSet TransSubdivFlag;
static const CtxSet QtRootCbf;
static const CtxSet QtCbf [3]; // [ channel ]
static const CtxSet SigCoeffGroup [4]; // [ ChannelType ]
static const CtxSet LastX [2]; // [ ChannelType ]
static const CtxSet LastY [2]; // [ ChannelType ]
static const CtxSet SigFlag [6]; // [ ChannelType + State ]
static const CtxSet ParFlag [2]; // [ ChannelType ]
static const CtxSet GtxFlag [4]; // [ ChannelType + x ]
static const CtxSet MVPIdx;
static const CtxSet SaoMergeFlag;
static const CtxSet SaoTypeIdx;
static const CtxSet TransformSkipFlag;
static const CtxSet TransquantBypassFlag;
static const CtxSet RdpcmFlag;
static const CtxSet RdpcmDir;
static const CtxSet EMTTuIndex;
static const CtxSet EMTCuFlag;
static const CtxSet CrossCompPred;
static const CtxSet ChromaQpAdjFlag;
static const CtxSet ChromaQpAdjIdc;
static const CtxSet ImvFlag;
#if JVET_L0646_GBI
static const CtxSet GBiIdx;
#endif
static const CtxSet ctbAlfFlag;
static const unsigned NumberOfContexts;
// combined sets for less complex copying
// NOTE: The contained CtxSet's should directly follow each other in the initalization list;
// otherwise, you will copy more elements than you want !!!
static const CtxSet Sao;
public:
static const std::vector<uint8_t>& getInitTable( unsigned initId );
private:
static std::vector<std::vector<uint8_t> > sm_InitTables;
static CtxSet addCtxSet( std::initializer_list<std::initializer_list<uint8_t> > initSet2d );
};
class FracBitsAccess
{
public:
virtual BinFracBits getFracBitsArray( unsigned ctxId ) const = 0;
};
template <class BinProbModel>
class CtxStore : public FracBitsAccess
{
public:
CtxStore();
CtxStore( bool dummy );
CtxStore( const CtxStore<BinProbModel>& ctxStore );
public:
void copyFrom ( const CtxStore<BinProbModel>& src ) { checkInit(); ::memcpy( m_Ctx, src.m_Ctx, sizeof( BinProbModel ) * ContextSetCfg::NumberOfContexts ); }
void copyFrom ( const CtxStore<BinProbModel>& src, const CtxSet& ctxSet ) { checkInit(); ::memcpy( m_Ctx+ctxSet.Offset, src.m_Ctx+ctxSet.Offset, sizeof( BinProbModel ) * ctxSet.Size ); }
void init ( int qp, int initId );
void setWinSizes( const std::vector<uint8_t>& log2WindowSizes );
void loadPStates( const std::vector<uint16_t>& probStates );
void savePStates( std::vector<uint16_t>& probStates ) const;
const BinProbModel& operator[] ( unsigned ctxId ) const { return m_Ctx[ctxId]; }
BinProbModel& operator[] ( unsigned ctxId ) { return m_Ctx[ctxId]; }
uint32_t estFracBits ( unsigned bin,
unsigned ctxId ) const { return m_Ctx[ctxId].estFracBits(bin); }
BinFracBits getFracBitsArray( unsigned ctxId ) const { return m_Ctx[ctxId].getFracBitsArray(); }
private:
inline void checkInit() { if( m_Ctx ) return; m_CtxBuffer.resize( ContextSetCfg::NumberOfContexts ); m_Ctx = m_CtxBuffer.data(); }
private:
std::vector<BinProbModel> m_CtxBuffer;
BinProbModel* m_Ctx;
};
class Ctx;
class SubCtx
{
friend class Ctx;
public:
SubCtx( const CtxSet& ctxSet, const Ctx& ctx ) : m_CtxSet( ctxSet ), m_Ctx( ctx ) {}
SubCtx( const SubCtx& subCtx ) : m_CtxSet( subCtx.m_CtxSet ), m_Ctx( subCtx.m_Ctx ) {}
const SubCtx& operator= ( const SubCtx& ) = delete;
private:
const CtxSet m_CtxSet;
const Ctx& m_Ctx;
};
class Ctx : public ContextSetCfg
{
public:
Ctx();
Ctx( const BinProbModel_Std* dummy );
Ctx( const Ctx& ctx );
public:
const Ctx& operator= ( const Ctx& ctx )
{
m_BPMType = ctx.m_BPMType;
switch( m_BPMType )
{
case BPM_Std: m_CtxStore_Std .copyFrom( ctx.m_CtxStore_Std ); break;
default: break;
}
::memcpy( m_GRAdaptStats, ctx.m_GRAdaptStats, sizeof( unsigned ) * RExt__GOLOMB_RICE_ADAPTATION_STATISTICS_SETS );
return *this;
}
SubCtx operator= ( SubCtx&& subCtx )
{
m_BPMType = subCtx.m_Ctx.m_BPMType;
switch( m_BPMType )
{
case BPM_Std: m_CtxStore_Std .copyFrom( subCtx.m_Ctx.m_CtxStore_Std, subCtx.m_CtxSet ); break;
default: break;
}
return std::move(subCtx);
}
void init ( int qp, int initId )
{
switch( m_BPMType )
{
case BPM_Std: m_CtxStore_Std .init( qp, initId ); break;
default: break;
}
for( std::size_t k = 0; k < RExt__GOLOMB_RICE_ADAPTATION_STATISTICS_SETS; k++ )
{
m_GRAdaptStats[k] = 0;
}
}
void loadPStates( const std::vector<uint16_t>& probStates )
{
switch( m_BPMType )
{
case BPM_Std: m_CtxStore_Std .loadPStates( probStates ); break;
default: break;
}
}
void savePStates( std::vector<uint16_t>& probStates ) const
{
switch( m_BPMType )
{
case BPM_Std: m_CtxStore_Std .savePStates( probStates ); break;
default: break;
}
}
void initCtxAndWinSize( unsigned ctxId, const Ctx& ctx, const uint8_t winSize )
{
switch( m_BPMType )
{
case BPM_Std:
m_CtxStore_Std [ctxId] = ctx.m_CtxStore_Std [ctxId];
m_CtxStore_Std [ctxId] . setLog2WindowSize (winSize);
break;
default:
break;
}
}
const unsigned& getGRAdaptStats ( unsigned id ) const { return m_GRAdaptStats[id]; }
unsigned& getGRAdaptStats ( unsigned id ) { return m_GRAdaptStats[id]; }
public:
unsigned getBPMType () const { return m_BPMType; }
const Ctx& getCtx () const { return *this; }
Ctx& getCtx () { return *this; }
explicit operator const CtxStore<BinProbModel_Std> &() const { return m_CtxStore_Std; }
explicit operator CtxStore<BinProbModel_Std> &() { return m_CtxStore_Std; }
const FracBitsAccess& getFracBitsAcess() const
{
switch( m_BPMType )
{
case BPM_Std: return m_CtxStore_Std;
default: THROW("BPMType out of range");
}
}
private:
BPMType m_BPMType;
CtxStore<BinProbModel_Std> m_CtxStore_Std;
protected:
unsigned m_GRAdaptStats[RExt__GOLOMB_RICE_ADAPTATION_STATISTICS_SETS];
#if ENABLE_SPLIT_PARALLELISM || ENABLE_WPP_PARALLELISM
public:
int64_t cacheId;
bool cacheUsed;
#endif
};
typedef dynamic_cache<Ctx> CtxCache;
class TempCtx
{
TempCtx( const TempCtx& ) = delete;
const TempCtx& operator=( const TempCtx& ) = delete;
public:
TempCtx ( CtxCache* cache ) : m_ctx( *cache->get() ), m_cache( cache ) {}
TempCtx ( CtxCache* cache, const Ctx& ctx ) : m_ctx( *cache->get() ), m_cache( cache ) { m_ctx = ctx; }
TempCtx ( CtxCache* cache, SubCtx&& subCtx ) : m_ctx( *cache->get() ), m_cache( cache ) { m_ctx = std::forward<SubCtx>(subCtx); }
~TempCtx() { m_cache->cache( &m_ctx ); }
const Ctx& operator=( const Ctx& ctx ) { return ( m_ctx = ctx ); }
SubCtx operator=( SubCtx&& subCtx ) { return m_ctx = std::forward<SubCtx>( subCtx ); }
operator const Ctx& () const { return m_ctx; }
operator Ctx& () { return m_ctx; }
private:
Ctx& m_ctx;
CtxCache* m_cache;
};
class CtxStateBuf
{
public:
CtxStateBuf () : m_valid(false) {}
~CtxStateBuf() {}
inline void reset() { m_valid = false; }
inline bool getIfValid(Ctx &ctx) const
{
if (m_valid)
{
ctx.loadPStates(m_states);
return true;
}
return false;
}
inline void store(const Ctx &ctx)
{
ctx.savePStates(m_states);
m_valid = true;
}
private:
std::vector<uint16_t> m_states;
bool m_valid;
};
class CtxStateArray
{
public:
CtxStateArray () {}
~CtxStateArray() {}
inline void resetAll()
{
for (std::size_t k = 0; k < m_data.size(); k++)
{
m_data[k].reset();
}
}
inline void resize(std::size_t reqSize)
{
if (m_data.size() < reqSize)
{
m_data.resize(reqSize);
}
}
inline bool getIfValid(Ctx &ctx, unsigned id) const
{
if (id < m_data.size())
{
return m_data[id].getIfValid(ctx);
}
return false;
}
inline void store(const Ctx &ctx, unsigned id)
{
if (id >= m_data.size())
{
resize(id + 1);
}
m_data[id].store(ctx);
}
private:
std::vector<CtxStateBuf> m_data;
};
class CtxWSizeSet
{
public:
CtxWSizeSet() : m_valid(false), m_changes(false), m_coded(false), m_log2WinSizes() {}
bool isValid() const { return m_valid; }
const std::vector<uint8_t>& getWinSizeBuffer() const { return m_log2WinSizes; }
std::vector<uint8_t>& getWinSizeBuffer() { return m_log2WinSizes; }
int getMode() const { return ( !m_valid || !m_changes ? 0 : ( m_coded ? 2 : 1 ) ); }
void setInvalid() { m_valid = m_changes = m_coded = false; }
void setCoded() { m_coded = true; }
void setValidOnly() { m_valid = true; }
void setValid( uint8_t defSize )
{
m_valid = true;
m_changes = false;
for( std::size_t n = 0; n < m_log2WinSizes.size(); n++ )
{
if( m_log2WinSizes[n] && m_log2WinSizes[n] != defSize )
{
m_changes = true;
return;
}
}
}
private:
bool m_valid;
bool m_changes;
bool m_coded;
std::vector<uint8_t> m_log2WinSizes;
};
#endif