forked from mirror/libbpg
255 lines
9 KiB
C++
255 lines
9 KiB
C++
|
/* 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-2014, 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.
|
||
|
*/
|
||
|
|
||
|
|
||
|
#include "TComTU.h"
|
||
|
#include "TComRom.h"
|
||
|
#include "TComDataCU.h"
|
||
|
#include "TComPic.h"
|
||
|
|
||
|
//----------------------------------------------------------------------------------------------------------------------
|
||
|
|
||
|
/*static*/ const UInt TComTU::NUMBER_OF_SECTIONS[TComTU::NUMBER_OF_SPLIT_MODES] = { 1, 2, 4 };
|
||
|
|
||
|
static const UInt partIdxStepShift [TComTU::NUMBER_OF_SPLIT_MODES] = { 0, 1, 2 };
|
||
|
|
||
|
//----------------------------------------------------------------------------------------------------------------------
|
||
|
|
||
|
TComTU::TComTU(TComDataCU *pcCU, const UInt absPartIdxCU, const UInt cuDepth, const UInt initTrDepthRelCU)
|
||
|
: mChromaFormat(pcCU->getSlice()->getSPS()->getChromaFormatIdc()),
|
||
|
mbProcessLastOfLevel(true), // does not matter. the top level is not 4 quadrants.
|
||
|
mCuDepth(cuDepth),
|
||
|
mSection(0),
|
||
|
mSplitMode(DONT_SPLIT),
|
||
|
mAbsPartIdxCU(absPartIdxCU),
|
||
|
mAbsPartIdxTURelCU(0),
|
||
|
mAbsPartIdxStep(pcCU->getPic()->getNumPartitionsInCtu() >> (pcCU->getDepth(absPartIdxCU)<<1)),
|
||
|
mpcCU(pcCU),
|
||
|
mLog2TrLumaSize(0),
|
||
|
mpParent(NULL)
|
||
|
{
|
||
|
TComSPS *pSPS=pcCU->getSlice()->getSPS();
|
||
|
mLog2TrLumaSize = g_aucConvertToBit[pSPS->getMaxCUWidth() >> (mCuDepth+initTrDepthRelCU)]+2;
|
||
|
|
||
|
const UInt baseOffset444=pcCU->getPic()->getMinCUWidth()*pcCU->getPic()->getMinCUHeight()*absPartIdxCU;
|
||
|
|
||
|
for(UInt i=0; i<MAX_NUM_COMPONENT; i++)
|
||
|
{
|
||
|
mTrDepthRelCU[i] = initTrDepthRelCU;
|
||
|
const UInt csx=getComponentScaleX(ComponentID(i), mChromaFormat);
|
||
|
const UInt csy=getComponentScaleY(ComponentID(i), mChromaFormat);
|
||
|
mOrigWidth[i]=mRect[i].width = (i < getNumberValidComponents(mChromaFormat)) ? (pcCU->getWidth( absPartIdxCU) >> csx) : 0;
|
||
|
mRect[i].height = (i < getNumberValidComponents(mChromaFormat)) ? (pcCU->getHeight(absPartIdxCU) >> csy) : 0;
|
||
|
mRect[i].x0=0;
|
||
|
mRect[i].y0=0;
|
||
|
mCodeAll[i]=true;
|
||
|
mOffsets[i]=baseOffset444>>(csx+csy);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
TComTURecurse::TComTURecurse( TComDataCU *pcCU,
|
||
|
const UInt absPartIdxCU)
|
||
|
: TComTU(pcCU, absPartIdxCU, pcCU->getDepth(absPartIdxCU), 0)
|
||
|
{ }
|
||
|
|
||
|
|
||
|
|
||
|
TComTU::TComTU(TComTU &parent, const Bool bProcessLastOfLevel, const TU_SPLIT_MODE splitMode, const Bool splitAtCurrentDepth, const ComponentID absPartIdxSourceComponent)
|
||
|
: mChromaFormat(parent.mChromaFormat),
|
||
|
mbProcessLastOfLevel(bProcessLastOfLevel),
|
||
|
mCuDepth(parent.mCuDepth),
|
||
|
mSection(0),
|
||
|
mSplitMode(splitMode),
|
||
|
mAbsPartIdxCU(parent.mAbsPartIdxCU),
|
||
|
mAbsPartIdxTURelCU(parent.GetRelPartIdxTU(absPartIdxSourceComponent)),
|
||
|
mAbsPartIdxStep(std::max<UInt>(1, (parent.GetAbsPartIdxNumParts(absPartIdxSourceComponent) >> partIdxStepShift[splitMode]))),
|
||
|
mpcCU(parent.mpcCU),
|
||
|
mLog2TrLumaSize(parent.mLog2TrLumaSize - ((splitMode != QUAD_SPLIT) ? 0 : 1)), //no change in width for vertical split
|
||
|
mpParent(&parent)
|
||
|
{
|
||
|
for(UInt i=0; i<MAX_NUM_COMPONENT; i++)
|
||
|
{
|
||
|
mTrDepthRelCU[i] = parent.mTrDepthRelCU[i] + ((splitAtCurrentDepth || (splitMode == DONT_SPLIT)) ? 0 : 1);
|
||
|
}
|
||
|
|
||
|
if (mSplitMode==DONT_SPLIT)
|
||
|
{
|
||
|
for(UInt i=0; i<MAX_NUM_COMPONENT; i++)
|
||
|
{
|
||
|
mRect[i] = (parent.mRect[i]);
|
||
|
mOffsets[i]=parent.mOffsets[i];
|
||
|
mCodeAll[i]=true; // The 1 TU at this level is coded.
|
||
|
mOrigWidth[i]=mRect[i].width;
|
||
|
}
|
||
|
return;
|
||
|
}
|
||
|
else if (mSplitMode==VERTICAL_SPLIT)
|
||
|
{
|
||
|
for(UInt i=0; i<MAX_NUM_COMPONENT; i++)
|
||
|
{
|
||
|
mRect[i].x0 = (parent.mRect[i].x0);
|
||
|
mRect[i].y0 = (parent.mRect[i].y0);
|
||
|
mRect[i].width = (parent.mRect[i].width);
|
||
|
mRect[i].height = (parent.mRect[i].height)>>1;
|
||
|
mOffsets[i]=parent.mOffsets[i];
|
||
|
mCodeAll[i]=true; // The 2 TUs at this level is coded.
|
||
|
mOrigWidth[i]=mRect[i].width;
|
||
|
}
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
for(UInt i=0; i<MAX_NUM_COMPONENT; i++)
|
||
|
{
|
||
|
mRect[i].width = (parent.mRect[i].width >> 1);
|
||
|
mRect[i].height= (parent.mRect[i].height>> 1);
|
||
|
mRect[i].x0=parent.mRect[i].x0;
|
||
|
mRect[i].y0=parent.mRect[i].y0;
|
||
|
mOffsets[i]=parent.mOffsets[i];
|
||
|
|
||
|
if ((mRect[i].width < MIN_TU_SIZE || mRect[i].height < MIN_TU_SIZE) && mRect[i].width!=0)
|
||
|
{
|
||
|
const UInt numPels=mRect[i].width * mRect[i].height;
|
||
|
if (numPels < (MIN_TU_SIZE*MIN_TU_SIZE))
|
||
|
{
|
||
|
// this level doesn't have enough pixels to have 4 blocks of any relative dimension
|
||
|
mRect[i].width = parent.mRect[i].width;
|
||
|
mRect[i].height= parent.mRect[i].height;
|
||
|
mCodeAll[i]=false; // go up a level, so only process one entry of a quadrant
|
||
|
mTrDepthRelCU[i]--;
|
||
|
}
|
||
|
else if (mRect[i].width < mRect[i].height)
|
||
|
{
|
||
|
mRect[i].width=MIN_TU_SIZE;
|
||
|
mRect[i].height=numPels/MIN_TU_SIZE;
|
||
|
mCodeAll[i]=true;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
mRect[i].height=MIN_TU_SIZE;
|
||
|
mRect[i].width=numPels/MIN_TU_SIZE;
|
||
|
mCodeAll[i]=true;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
mCodeAll[i]=true;
|
||
|
}
|
||
|
|
||
|
mOrigWidth[i]=mRect[i].width;
|
||
|
if (!mCodeAll[i] && mbProcessLastOfLevel) mRect[i].width=0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
Bool TComTURecurse::nextSection(const TComTU &parent)
|
||
|
{
|
||
|
if (mSplitMode==DONT_SPLIT)
|
||
|
{
|
||
|
mSection++;
|
||
|
return false;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
for(UInt i=0; i<MAX_NUM_COMPONENT; i++)
|
||
|
{
|
||
|
mOffsets[i]+=mRect[i].width*mRect[i].height;
|
||
|
if (mbProcessLastOfLevel) mRect[i].width=mOrigWidth[i];
|
||
|
mRect[i].x0+=mRect[i].width;
|
||
|
const TComRectangle &parentRect=parent.getRect(ComponentID(i));
|
||
|
if (mRect[i].x0 >= parentRect.x0+parentRect.width)
|
||
|
{
|
||
|
mRect[i].x0=parentRect.x0;
|
||
|
mRect[i].y0+=mRect[i].height;
|
||
|
}
|
||
|
if (!mCodeAll[i])
|
||
|
{
|
||
|
if (!mbProcessLastOfLevel || mSection!=2) mRect[i].width=0;
|
||
|
}
|
||
|
}
|
||
|
assert(mRect[COMPONENT_Cb].x0==mRect[COMPONENT_Cr].x0);
|
||
|
assert(mRect[COMPONENT_Cb].y0==mRect[COMPONENT_Cr].y0);
|
||
|
assert(mRect[COMPONENT_Cb].width==mRect[COMPONENT_Cr].width);
|
||
|
assert(mRect[COMPONENT_Cb].height==mRect[COMPONENT_Cr].height);
|
||
|
|
||
|
mAbsPartIdxTURelCU+=mAbsPartIdxStep;
|
||
|
mSection++;
|
||
|
return mSection< (1<<mSplitMode);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
UInt TComTU::GetEquivalentLog2TrSize(const ComponentID compID) const
|
||
|
{
|
||
|
return g_aucConvertToBit[ getRect(compID).height ] + 2;
|
||
|
}
|
||
|
|
||
|
|
||
|
Bool TComTU::useDST(const ComponentID compID)
|
||
|
{
|
||
|
TComDataCU *const pcCU = getCU();
|
||
|
const UInt absPartIdx = GetAbsPartIdxTU(compID);
|
||
|
|
||
|
return isLuma(compID) && pcCU->isIntra(absPartIdx);
|
||
|
}
|
||
|
|
||
|
|
||
|
Bool TComTU::isNonTransformedResidualRotated(const ComponentID compID)
|
||
|
{
|
||
|
// rotation only for 4x4 intra, and is only used for non-transformed blocks (the latter is not checked here)
|
||
|
return getCU()->getSlice()->getSPS()->getUseResidualRotation()
|
||
|
&& mRect[compID].width == 4
|
||
|
&& getCU()->isIntra(GetAbsPartIdxTU());
|
||
|
}
|
||
|
|
||
|
|
||
|
UInt TComTU::getGolombRiceStatisticsIndex(const ComponentID compID)
|
||
|
{
|
||
|
TComDataCU *const pcCU = getCU();
|
||
|
const UInt absPartIdx = GetAbsPartIdxTU(compID);
|
||
|
const Bool transformSkip = pcCU->getTransformSkip(absPartIdx, compID);
|
||
|
const Bool transquantBypass = pcCU->getCUTransquantBypass(absPartIdx);
|
||
|
|
||
|
//--------
|
||
|
|
||
|
const UInt channelTypeOffset = isChroma(compID) ? 2 : 0;
|
||
|
const UInt nonTransformedOffset = (transformSkip || transquantBypass) ? 1 : 0;
|
||
|
|
||
|
//--------
|
||
|
|
||
|
const UInt selectedIndex = channelTypeOffset + nonTransformedOffset;
|
||
|
assert(selectedIndex < RExt__GOLOMB_RICE_ADAPTATION_STATISTICS_SETS);
|
||
|
|
||
|
return selectedIndex;
|
||
|
}
|