VTM数据结构3
前言
VTM对AreaBuf,UnitBuf,PelStorage的定义在CommonLib/Buffer.h中
简介: VTM中AreaBuf,UnitBuf,PelStorage描述了二维视频信号在内存中的操作,可以根据位置来访问到相应的信号值。
它们以结构体模板的方式来书写,其中AeraBuf为UnitArea提供了一种数据类型,而PelStorage就是一个Pel类型的UnitBuf.
提示:以下是本篇文章正文内容,下面案例可供参考
一、AreaBuf
简介:描述了最基本二维信号在内存中的存储。
1.定义
VTM中AreaBuf的定义:
template<typename T>
struct AreaBuf : public Size
{
T* buf; //定义一个指针变量
int stride; //定义一个步长
// the proper type causes awful lot of errors
//ptrdiff_t stride;
AreaBuf() : Size(), buf( NULL ), stride( 0 ) { }
AreaBuf( T *_buf, const Size &size ) : Size( size ), buf( _buf ), stride( size.width ) { }
AreaBuf( T *_buf, const int &_stride, const Size &size ) : Size( size ), buf( _buf ), stride( _stride ) { }
AreaBuf( T *_buf, const SizeType &_width, const SizeType &_height ) : Size( _width, _height ), buf( _buf ), stride( _width ) { }
AreaBuf( T *_buf, const int &_stride, const SizeType &_width, const SizeType &_height ) : Size( _width, _height ), buf( _buf ), stride( _stride ) { }
operator AreaBuf<const T>() const { return AreaBuf<const T>( buf, stride, width, height ); }
void fill ( const T &val );
void memset ( const int val );
void copyFrom ( const AreaBuf<const T> &other );
void reconstruct ( const AreaBuf<const T> &pred, const AreaBuf<const T> &resi, const ClpRng& clpRng);
void copyClip ( const AreaBuf<const T> &src, const ClpRng& clpRng);
void subtract ( const AreaBuf<const T> &other );
void extendSingleBorderPel();
void extendBorderPel ( unsigned margin );
void addWeightedAvg ( const AreaBuf<const T> &other1, const AreaBuf<const T> &other2, const ClpRng& clpRng, const int8_t gbiIdx);
void removeWeightHighFreq ( const AreaBuf<T>& other, const bool bClip, const ClpRng& clpRng, const int8_t iGbiWeight);
void addAvg ( const AreaBuf<const T> &other1, const AreaBuf<const T> &other2, const ClpRng& clpRng );
void removeHighFreq ( const AreaBuf<T>& other, const bool bClip, const ClpRng& clpRng);
void updateHistogram ( std::vector<int32_t>& hist ) const;
T meanDiff ( const AreaBuf<const T> &other ) const;
void subtract ( const T val );
void linearTransform ( const int scale, const int shift, const int offset, bool bClip, const ClpRng& clpRng );
void transposedFrom ( const AreaBuf<const T> &other );
void toLast ( const ClpRng& clpRng );
#if JVET_M0427_INLOOP_RESHAPER
void rspSignal ( std::vector<Pel>& pLUT );
void scaleSignal ( const int scale, const bool dir , const ClpRng& clpRng);
T computeAvg ( ) const;
#endif
T& at( const int &x, const int &y ) { return buf[y * stride + x]; }
const T& at( const int &x, const int &y ) const { return buf[y * stride + x]; }
T& at( const Position &pos ) { return buf[pos.y * stride + pos.x]; }
const T& at( const Position &pos ) const { return buf[pos.y * stride + pos.x]; }
T* bufAt( const int &x, const int &y ) { return &at( x, y ); }
const T* bufAt( const int &x, const int &y ) const { return &at( x, y ); }
T* bufAt( const Position& pos ) { return &at( pos ); }
const T* bufAt( const Position& pos ) const { return &at( pos ); }
AreaBuf< T> subBuf( const Position &pos, const Size &size ) { return AreaBuf< T>( bufAt( pos ), stride, size ); }
AreaBuf<const T> subBuf( const Position &pos, const Size &size ) const { return AreaBuf<const T>( bufAt( pos ), stride, size ); }
AreaBuf< T> subBuf( const int &x, const int &y, const unsigned &_w, const unsigned &_h ) { return AreaBuf< T>( bufAt( x, y ), stride, _w, _h ); }
AreaBuf<const T> subBuf( const int &x, const int &y, const unsigned &_w, const unsigned &_h ) const { return AreaBuf<const T>( bufAt( x, y ), stride, _w, _h ); }
};
2.内存操作方法的定义
template<typename T>
void AreaBuf<T>::fill(const T &val)
{
if( sizeof( T ) == 1 )
{
if( width == stride )
{
::memset( buf, reinterpret_cast< const signed char& >( val ), width * height * sizeof( T ) );
}
else
{
T* dest = buf;
size_t line = width * sizeof( T );
for( unsigned y = 0; y < height; y++ )
{
::memset( dest, reinterpret_cast< const signed char& >( val ), line );
dest += stride;
}
}
}
else if( T( 0 ) == val )
{
if( width == stride )
{
::memset( buf, 0, width * height * sizeof( T ) );
}
else
{
T* dest = buf;
size_t line = width * sizeof( T );
for( unsigned y = 0; y < height; y++ )
{
::memset( dest, 0, line );
dest += stride;
}
}
}
else
{
T* dest = buf;
#define FILL_INC dest += stride
#define FILL_OP( ADDR ) dest[ADDR] = val
SIZE_AWARE_PER_EL_OP( FILL_OP, FILL_INC );
#undef FILL_INC
#undef FILL_OP
}
}
template<typename T>
void AreaBuf<T>::memset( const int val )
{
if( width == stride )
{
::memset( buf, val, width * height * sizeof( T ) );
}
else
{
T* dest = buf;
size_t line = width * sizeof( T );
for( int y = 0; y < height; y++ )
{
::memset( dest, val, line );
dest += stride;
}
}
}
template<typename T>
void AreaBuf<T>::copyFrom( const AreaBuf<const T> &other )
{
#if !defined(__GNUC__) || __GNUC__ > 5
static_assert( std::is_trivially_copyable<T>::value, "Type T is not trivially_copyable" );
#endif
CHECK( width != other.width, "Incompatible size" );
CHECK( height != other.height, "Incompatible size" );
if( buf == other.buf )
{
return;
}
if( width == stride && stride == other.stride )
{
memcpy( buf, other.buf, width * height * sizeof( T ) );
}
else
{
T* dst = buf;
const T* src = other.buf;
const unsigned srcStride = other.stride;
for( unsigned y = 0; y < height; y++ )
{
memcpy( dst, src, width * sizeof( T ) );
dst += stride;
src += srcStride;
}
}
}
template<typename T>
void AreaBuf<T>::subtract( const AreaBuf<const T> &other )
{
CHECK( width != other.width, "Incompatible size" );
CHECK( height != other.height, "Incompatible size" );
T* dest = buf;
const T* subs = other.buf;
#define SUBS_INC \
dest += stride; \
subs += other.stride; \
#define SUBS_OP( ADDR ) dest[ADDR] -= subs[ADDR]
SIZE_AWARE_PER_EL_OP( SUBS_OP, SUBS_INC );
#undef SUBS_OP
#undef SUBS_INC
}
template<typename T>
void AreaBuf<T>::copyClip( const AreaBuf<const T> &src, const ClpRng& clpRng )
{
THROW( "Type not supported" );
}
template<>
void AreaBuf<Pel>::copyClip( const AreaBuf<const Pel> &src, const ClpRng& clpRng );
template<typename T>
void AreaBuf<T>::reconstruct( const AreaBuf<const T> &pred, const AreaBuf<const T> &resi, const ClpRng& clpRng )
{
THROW( "Type not supported" );
}
template<>
void AreaBuf<Pel>::reconstruct( const AreaBuf<const Pel> &pred, const AreaBuf<const Pel> &resi, const ClpRng& clpRng );
template<typename T>
void AreaBuf<T>::addAvg( const AreaBuf<const T> &other1, const AreaBuf<const T> &other2, const ClpRng& clpRng )
{
THROW( "Type not supported" );
}
template<>
void AreaBuf<Pel>::addAvg( const AreaBuf<const Pel> &other1, const AreaBuf<const Pel> &other2, const ClpRng& clpRng );
template<typename T>
void AreaBuf<T>::linearTransform( const int scale, const int shift, const int offset, bool bClip, const ClpRng& clpRng )
{
THROW( "Type not supported" );
}
template<>
void AreaBuf<Pel>::linearTransform( const int scale, const int shift, const int offset, bool bClip, const ClpRng& clpRng );
template<typename T>
void AreaBuf<T>::toLast( const ClpRng& clpRng )
{
THROW( "Type not supported" );
}
template<>
void AreaBuf<Pel>::toLast( const ClpRng& clpRng );
template<typename T>
void AreaBuf<T>::removeWeightHighFreq(const AreaBuf<T>& other, const bool bClip, const ClpRng& clpRng, const int8_t gbiWeight)
{
const int8_t gbiWeightOther = g_GbiWeightBase - gbiWeight;
const int8_t log2WeightBase = g_GbiLog2WeightBase;
const Pel* src = other.buf;
const int srcStride = other.stride;
Pel* dst = buf;
const int dstStride = stride;
#if ENABLE_SIMD_OPT_GBI
if(!bClip)
{
if(!(width & 7))
g_pelBufOP.removeWeightHighFreq8(dst, dstStride, src, srcStride, width, height, 16, gbiWeight);
else if(!(width & 3))
g_pelBufOP.removeWeightHighFreq4(dst, dstStride, src, srcStride, width, height, 16, gbiWeight);
else
CHECK(true, "Not supported");
}
else
{
#endif
int normalizer = ((1 << 16) + (gbiWeight > 0 ? (gbiWeight >> 1) : -(gbiWeight >> 1))) / gbiWeight;
int weight0 = normalizer << log2WeightBase;
int weight1 = gbiWeightOther * normalizer;
#define REM_HF_INC \
src += srcStride; \
dst += dstStride; \
#define REM_HF_OP_CLIP( ADDR ) dst[ADDR] = ClipPel<T>( (dst[ADDR]*weight0 - src[ADDR]*weight1 + (1<<15))>>16, clpRng )
#define REM_HF_OP( ADDR ) dst[ADDR] = (dst[ADDR]*weight0 - src[ADDR]*weight1 + (1<<15))>>16
if(bClip)
{
SIZE_AWARE_PER_EL_OP(REM_HF_OP_CLIP, REM_HF_INC);
}
else
{
SIZE_AWARE_PER_EL_OP(REM_HF_OP, REM_HF_INC);
}
#undef REM_HF_INC
#undef REM_HF_OP
#undef REM_HF_OP_CLIP
#if ENABLE_SIMD_OPT_GBI
}
#endif
}
template<typename T>
void AreaBuf<T>::removeHighFreq( const AreaBuf<T>& other, const bool bClip, const ClpRng& clpRng )
{
const T* src = other.buf;
const int srcStride = other.stride;
T* dst = buf;
const int dstStride = stride;
#if ENABLE_SIMD_OPT_GBI
if (!bClip)
{
if(!(width & 7))
g_pelBufOP.removeHighFreq8(dst, dstStride, src, srcStride, width, height);
else if (!(width & 3))
g_pelBufOP.removeHighFreq4(dst, dstStride, src, srcStride, width, height);
else
CHECK(true, "Not supported");
}
else
{
#endif
#define REM_HF_INC \
src += srcStride; \
dst += dstStride; \
#define REM_HF_OP_CLIP( ADDR ) dst[ADDR] = ClipPel<T>( 2 * dst[ADDR] - src[ADDR], clpRng )
#define REM_HF_OP( ADDR ) dst[ADDR] = 2 * dst[ADDR] - src[ADDR]
if( bClip )
{
SIZE_AWARE_PER_EL_OP( REM_HF_OP_CLIP, REM_HF_INC );
}
else
{
SIZE_AWARE_PER_EL_OP( REM_HF_OP, REM_HF_INC );
}
#undef REM_HF_INC
#undef REM_HF_OP
#undef REM_HF_OP_CLIP
#if ENABLE_SIMD_OPT_GBI
}
#endif
}
template<typename T>
void AreaBuf<T>::updateHistogram( std::vector<int32_t>& hist ) const
{
const T* data = buf;
for( std::size_t y = 0; y < height; y++, data += stride )
{
for( std::size_t x = 0; x < width; x++ )
{
hist[ data[x] ]++;
}
}
}
template<typename T>
void AreaBuf<T>::extendBorderPel( unsigned margin )
{
T* p = buf;
int h = height;
int w = width;
int s = stride;
CHECK( ( w + 2 * margin ) > s, "Size of buffer too small to extend" );
// do left and right margins
for( int y = 0; y < h; y++ )
{
for( int x = 0; x < margin; x++ )
{
*( p - margin + x ) = p[0];
p[w + x] = p[w - 1];
}
p += s;
}
// p is now the (0,height) (bottom left of image within bigger picture
p -= ( s + margin );
// p is now the (-margin, height-1)
for( int y = 0; y < margin; y++ )
{
::memcpy( p + ( y + 1 ) * s, p, sizeof( T ) * ( w + ( margin << 1 ) ) );
}
// pi is still (-marginX, height-1)
p -= ( ( h - 1 ) * s );
// pi is now (-marginX, 0)
for( int y = 0; y < margin; y++ )
{
::memcpy( p - ( y + 1 ) * s, p, sizeof( T ) * ( w + ( margin << 1 ) ) );
}
}
template<typename T>
T AreaBuf<T>::meanDiff( const AreaBuf<const T> &other ) const
{
int64_t acc = 0;
CHECK( width != other.width, "Incompatible size" );
CHECK( height != other.height, "Incompatible size" );
const T* src1 = buf;
const T* src2 = other.buf;
#define MEAN_DIFF_INC \
src1 += stride; \
src2 += other.stride; \
#define MEAN_DIFF_OP(ADDR) acc += src1[ADDR] - src2[ADDR]
SIZE_AWARE_PER_EL_OP( MEAN_DIFF_OP, MEAN_DIFF_INC );
#undef MEAN_DIFF_INC
#undef MEAN_DIFF_OP
return T( acc / area() );
}
#if ENABLE_SIMD_OPT_BUFFER && defined(TARGET_SIMD_X86)
template<> void AreaBuf<Pel>::subtract( const Pel val );
#endif
template<typename T>
void AreaBuf<T>::subtract( const T val )
{
T* dst = buf;
#define OFFSET_INC dst += stride
#define OFFSET_OP(ADDR) dst[ADDR] -= val
SIZE_AWARE_PER_EL_OP( OFFSET_OP, OFFSET_INC );
#undef OFFSET_INC
#undef OFFSET_OP
}
template<typename T>
void AreaBuf<T>::transposedFrom( const AreaBuf<const T> &other )
{
CHECK( width * height != other.width * other.height, "Incompatible size" );
T* dst = buf;
const T* src = other.buf;
width = other.height;
height = other.width;
stride = stride < width ? width : stride;
for( unsigned y = 0; y < other.height; y++ )
{
for( unsigned x = 0; x < other.width; x++ )
{
dst[y + x*stride] = src[x + y*other.stride];
}
}
}
二、UnitBuf
1.定义
代码如下:
template<typename T>
struct UnitBuf
{
typedef static_vector<AreaBuf<T>, MAX_NUM_COMPONENT> UnitBufBuffers;
typedef static_vector<AreaBuf<const T>, MAX_NUM_COMPONENT> ConstUnitBufBuffers;
ChromaFormat chromaFormat; //枚举类型
UnitBufBuffers bufs; // AreaBuf型的数组,数组中有size信息,指针和步长信息
UnitBuf() : chromaFormat( NUM_CHROMA_FORMAT ) { }
UnitBuf( const ChromaFormat &_chromaFormat, const UnitBufBuffers& _bufs ) : chromaFormat( _chromaFormat ), bufs( _bufs ) { }
UnitBuf( const ChromaFormat &_chromaFormat, UnitBufBuffers&& _bufs ) : chromaFormat( _chromaFormat ), bufs( std::forward<UnitBufBuffers>( _bufs ) ) { }
UnitBuf( const ChromaFormat &_chromaFormat, const AreaBuf<T> &blkY ) : chromaFormat( _chromaFormat ), bufs{ blkY } { }
UnitBuf( const ChromaFormat &_chromaFormat, AreaBuf<T> &&blkY ) : chromaFormat( _chromaFormat ), bufs{ std::forward<AreaBuf<T> >(blkY) } { }
UnitBuf( const ChromaFormat &_chromaFormat, const AreaBuf<T> &blkY, const AreaBuf<T> &blkCb, const AreaBuf<T> &blkCr ) : chromaFormat( _chromaFormat ), bufs{ blkY, blkCb, blkCr } { }
UnitBuf( const ChromaFormat &_chromaFormat, AreaBuf<T> &&blkY, AreaBuf<T> &&blkCb, AreaBuf<T> &&blkCr ) : chromaFormat( _chromaFormat ), bufs{ std::forward<AreaBuf<T> >(blkY), std::forward<AreaBuf<T> >(blkCb), std::forward<AreaBuf<T> >(blkCr) } { }
operator UnitBuf<const T>() const
{
return UnitBuf<const T>( chromaFormat, ConstUnitBufBuffers( bufs.begin(), bufs.end() ) );
}
AreaBuf<T>& get( const ComponentID comp ) { return bufs[comp]; }
const AreaBuf<T>& get( const ComponentID comp ) const { return bufs[comp]; }
AreaBuf<T>& Y() { return bufs[0]; }
const AreaBuf<T>& Y() const { return bufs[0]; }
AreaBuf<T>& Cb() { return bufs[1]; }
const AreaBuf<T>& Cb() const { return bufs[1]; }
AreaBuf<T>& Cr() { return bufs[2]; }
const AreaBuf<T>& Cr() const { return bufs[2]; }
void fill ( const T &val );
void copyFrom ( const UnitBuf<const T> &other );
void reconstruct ( const UnitBuf<const T> &pred, const UnitBuf<const T> &resi, const ClpRngs& clpRngs );
void copyClip ( const UnitBuf<const T> &src, const ClpRngs& clpRngs );
void subtract ( const UnitBuf<const T> &other );
void addWeightedAvg ( const UnitBuf<const T> &other1, const UnitBuf<const T> &other2, const ClpRngs& clpRngs, const uint8_t gbiIdx = GBI_DEFAULT, const bool chromaOnly = false, const bool lumaOnly = false);
void addAvg ( const UnitBuf<const T> &other1, const UnitBuf<const T> &other2, const ClpRngs& clpRngs, const bool chromaOnly = false, const bool lumaOnly = false);
void extendSingleBorderPel();
void extendBorderPel ( unsigned margin );
void removeHighFreq ( const UnitBuf<T>& other, const bool bClip, const ClpRngs& clpRngs
, const int8_t gbiWeight = g_GbiWeights[GBI_DEFAULT]
);
UnitBuf< T> subBuf (const UnitArea& subArea);
const UnitBuf<const T> subBuf (const UnitArea& subArea) const;
};
2.内存操作
代码如下(示例):
template<typename T>
void UnitBuf<T>::fill( const T &val )
{
for( unsigned i = 0; i < bufs.size(); i++ )
{
bufs[i].fill( val );
}
}
template<typename T>
void UnitBuf<T>::copyFrom( const UnitBuf<const T> &other )
{
CHECK( chromaFormat != other.chromaFormat, "Incompatible formats" );
for( unsigned i = 0; i < bufs.size(); i++ )
{
bufs[i].copyFrom( other.bufs[i] );
}
}
template<typename T>
void UnitBuf<T>::subtract( const UnitBuf<const T> &other )
{
CHECK( chromaFormat != other.chromaFormat, "Incompatible formats" );
for( unsigned i = 0; i < bufs.size(); i++ )
{
bufs[i].subtract( other.bufs[i] );
}
}
template<typename T>
void UnitBuf<T>::copyClip(const UnitBuf<const T> &src, const ClpRngs& clpRngs)
{
CHECK( chromaFormat != src.chromaFormat, "Incompatible formats" );
for( unsigned i = 0; i < bufs.size(); i++ )
{
bufs[i].copyClip( src.bufs[i], clpRngs.comp[i] );
}
}
template<typename T>
void UnitBuf<T>::reconstruct(const UnitBuf<const T> &pred, const UnitBuf<const T> &resi, const ClpRngs& clpRngs)
{
CHECK( chromaFormat != pred.chromaFormat, "Incompatible formats" );
CHECK( chromaFormat != resi.chromaFormat, "Incompatible formats" );
for( unsigned i = 0; i < bufs.size(); i++ )
{
bufs[i].reconstruct( pred.bufs[i], resi.bufs[i], clpRngs.comp[i] );
}
}
template<typename T>
void UnitBuf<T>::addWeightedAvg(const UnitBuf<const T> &other1, const UnitBuf<const T> &other2, const ClpRngs& clpRngs, const uint8_t gbiIdx /* = GBI_DEFAULT */, const bool chromaOnly /* = false */, const bool lumaOnly /* = false */)
{
const size_t istart = chromaOnly ? 1 : 0;
const size_t iend = lumaOnly ? 1 : bufs.size();
CHECK(lumaOnly && chromaOnly, "should not happen");
for(size_t i = istart; i < iend; i++)
{
bufs[i].addWeightedAvg(other1.bufs[i], other2.bufs[i], clpRngs.comp[i], gbiIdx);
}
}
template<typename T>
void UnitBuf<T>::addAvg(const UnitBuf<const T> &other1, const UnitBuf<const T> &other2, const ClpRngs& clpRngs, const bool chromaOnly /* = false */, const bool lumaOnly /* = false */)
{
const size_t istart = chromaOnly ? 1 : 0;
const size_t iend = lumaOnly ? 1 : bufs.size();
CHECK( lumaOnly && chromaOnly, "should not happen" );
for( size_t i = istart; i < iend; i++)
{
bufs[i].addAvg( other1.bufs[i], other2.bufs[i], clpRngs.comp[i]);
}
}
template<typename T>
void UnitBuf<T>::extendSingleBorderPel()
{
for( unsigned i = 0; i < bufs.size(); i++ )
{
bufs[i].extendSingleBorderPel();
}
}
template<typename T>
void UnitBuf<T>::extendBorderPel( unsigned margin )
{
for( unsigned i = 0; i < bufs.size(); i++ )
{
bufs[i].extendBorderPel( margin );
}
}
template<typename T>
void UnitBuf<T>::removeHighFreq( const UnitBuf<T>& other, const bool bClip, const ClpRngs& clpRngs
, const int8_t gbiWeight
)
{
if(gbiWeight != g_GbiWeights[GBI_DEFAULT])
{
bufs[0].removeWeightHighFreq(other.bufs[0], bClip, clpRngs.comp[0], gbiWeight);
return;
}
bufs[0].removeHighFreq(other.bufs[0], bClip, clpRngs.comp[0]);
}
template<typename T>
UnitBuf<T> UnitBuf<T>::subBuf( const UnitArea& subArea )
{
UnitBuf<T> subBuf;
subBuf.chromaFormat = chromaFormat;
unsigned blockIdx = 0;
for( auto &subAreaBuf : bufs )
{
subBuf.bufs.push_back( subAreaBuf.subBuf( subArea.blocks[blockIdx].pos(), subArea.blocks[blockIdx].size() ) );
blockIdx++;
}
return subBuf;
}
template<typename T>
const UnitBuf<const T> UnitBuf<T>::subBuf( const UnitArea& subArea ) const
{
UnitBuf<const T> subBuf;
subBuf.chromaFormat = chromaFormat;
unsigned blockIdx = 0;
for( const auto &subAreaBuf : bufs )
{
subBuf.bufs.push_back( subAreaBuf.subBuf( subArea.blocks[blockIdx].pos(), subArea.blocks[blockIdx].size() ) );
blockIdx++;
}
return subBuf;
}
三、PelStorage
PelStorage定义:
代码如下:
typedef UnitBuf< Pel> PelUnitBuf;
typedef UnitBuf<const Pel> CPelUnitBuf;
struct PelStorage : public PelUnitBuf
{
PelStorage();
~PelStorage();
void swap( PelStorage& other );
void createFromBuf( PelUnitBuf buf );
void create( const UnitArea &_unit );
void create( const ChromaFormat &_chromaFormat, const Area& _area, const unsigned _maxCUSize = 0, const unsigned _margin = 0, const unsigned _alignment = 0, const bool _scaleChromaMargin = true );
void destroy();
PelBuf getBuf( const CompArea &blk );
const CPelBuf getBuf( const CompArea &blk ) const;
PelBuf getBuf( const ComponentID CompID );
const CPelBuf getBuf( const ComponentID CompID ) const;
PelUnitBuf getBuf( const UnitArea &unit );
const CPelUnitBuf getBuf( const UnitArea &unit ) const;
Pel *getOrigin( const int id ) const { return m_origin[id]; }
private:
Pel *m_origin[MAX_NUM_COMPONENT];
};
PelStorage成员函数的实现:
PelStorage::PelStorage() //构造函数
{
for( uint32_t i = 0; i < MAX_NUM_COMPONENT; i++ )
{
m_origin[i] = nullptr; //将所有的指针置空
}
}
//析构函数直接调用destroy函数
PelStorage::~PelStorage()
{
destroy();
}
void PelStorage::create( const UnitArea &_UnitArea )
{
create( _UnitArea.chromaFormat, _UnitArea.blocks[0] );
}
void PelStorage::create( const ChromaFormat &_chromaFormat, const Area& _area, const unsigned _maxCUSize, const unsigned _margin, const unsigned _alignment, const bool _scaleChromaMargin )
{
CHECK( !bufs.empty(), "Trying to re-create an already initialized buffer" );
chromaFormat = _chromaFormat;
const uint32_t numCh = getNumberValidComponents( _chromaFormat );
unsigned extHeight = _area.height;
unsigned extWidth = _area.width;
if( _maxCUSize )
{
extHeight = ( ( _area.height + _maxCUSize - 1 ) / _maxCUSize ) * _maxCUSize;
extWidth = ( ( _area.width + _maxCUSize - 1 ) / _maxCUSize ) * _maxCUSize;
}
for( uint32_t i = 0; i < numCh; i++ )
{
const ComponentID compID = ComponentID( i );
const unsigned scaleX = ::getComponentScaleX( compID, _chromaFormat );
const unsigned scaleY = ::getComponentScaleY( compID, _chromaFormat );
unsigned scaledHeight = extHeight >> scaleY;
unsigned scaledWidth = extWidth >> scaleX;
unsigned ymargin = _margin >> (_scaleChromaMargin?scaleY:0);
unsigned xmargin = _margin >> (_scaleChromaMargin?scaleX:0);
unsigned totalWidth = scaledWidth + 2*xmargin;
unsigned totalHeight = scaledHeight +2*ymargin;
if( _alignment )
{
// make sure buffer lines are align
CHECK( _alignment != MEMORY_ALIGN_DEF_SIZE, "Unsupported alignment" );
totalWidth = ( ( totalWidth + _alignment - 1 ) / _alignment ) * _alignment;
}
uint32_t area = totalWidth * totalHeight;
CHECK( !area, "Trying to create a buffer with zero area" );
m_origin[i] = ( Pel* ) xMalloc( Pel, area );
Pel* topLeft = m_origin[i] + totalWidth * ymargin + xmargin;
bufs.push_back( PelBuf( topLeft, totalWidth, _area.width >> scaleX, _area.height >> scaleY ) );
}
}
void PelStorage::createFromBuf( PelUnitBuf buf )
{
chromaFormat = buf.chromaFormat;
const uint32_t numCh = ::getNumberValidComponents( chromaFormat );
bufs.resize(numCh);
for( uint32_t i = 0; i < numCh; i++ )
{
PelBuf cPelBuf = buf.get( ComponentID( i ) );
bufs[i] = PelBuf( cPelBuf.bufAt( 0, 0 ), cPelBuf.stride, cPelBuf.width, cPelBuf.height );
}
}
void PelStorage::swap( PelStorage& other )
{
const uint32_t numCh = ::getNumberValidComponents( chromaFormat );
for( uint32_t i = 0; i < numCh; i++ )
{
// check this otherwise it would turn out to get very weird
CHECK( chromaFormat != other.chromaFormat , "Incompatible formats" );
CHECK( get( ComponentID( i ) ) != other.get( ComponentID( i ) ) , "Incompatible formats" );
CHECK( get( ComponentID( i ) ).stride != other.get( ComponentID( i ) ).stride, "Incompatible formats" );
std::swap( bufs[i].buf, other.bufs[i].buf );
std::swap( bufs[i].stride, other.bufs[i].stride );
std::swap( m_origin[i], other.m_origin[i] );
}
}
void PelStorage::destroy()
{
chromaFormat = NUM_CHROMA_FORMAT;
for( uint32_t i = 0; i < MAX_NUM_COMPONENT; i++ )
{
if( m_origin[i] )
{
xFree( m_origin[i] );
m_origin[i] = nullptr;
}
}
bufs.clear();
}
PelBuf PelStorage::getBuf( const ComponentID CompID )
{
return bufs[CompID];
}
const CPelBuf PelStorage::getBuf( const ComponentID CompID ) const
{
return bufs[CompID];
}
PelBuf PelStorage::getBuf( const CompArea &blk )
{
const PelBuf& r = bufs[blk.compID];
CHECKD( rsAddr( blk.bottomRight(), r.stride ) >= ( ( r.height - 1 ) * r.stride + r.width ), "Trying to access a buf outside of bound!" );
return PelBuf( r.buf + rsAddr( blk, r.stride ), r.stride, blk );
}
const CPelBuf PelStorage::getBuf( const CompArea &blk ) const
{
const PelBuf& r = bufs[blk.compID];
return CPelBuf( r.buf + rsAddr( blk, r.stride ), r.stride, blk );
}
PelUnitBuf PelStorage::getBuf( const UnitArea &unit )
{
return ( chromaFormat == CHROMA_400 ) ? PelUnitBuf( chromaFormat, getBuf( unit.Y() ) ) : PelUnitBuf( chromaFormat, getBuf( unit.Y() ), getBuf( unit.Cb() ), getBuf( unit.Cr() ) );
}
const CPelUnitBuf PelStorage::getBuf( const UnitArea &unit ) const
{
return ( chromaFormat == CHROMA_400 ) ? CPelUnitBuf( chromaFormat, getBuf( unit.Y() ) ) : CPelUnitBuf( chromaFormat, getBuf( unit.Y() ), getBuf( unit.Cb() ), getBuf( unit.Cr() ) );
}
总结
AreaBuf,UnitBuf,PelStorage完成了数据在内存中的存储