Commit e9a4a4ff authored by Frank Bossen's avatar Frank Bossen

Merge branch 'M0427-INLOOP-RESHAPER' into 'master'

JVET-M0427 Picture reconstruction with mapping

See merge request jvet/VVCSoftware_VTM!162
parents 73244967 2405c823
Pipeline #702 passed with stage
......@@ -114,6 +114,7 @@ ALF : 1
IBC : 0 # turned off in CTC
AllowDisFracMMVD : 1
AffineAmvr : 0
LumaReshapeEnable : 1 # luma reshaping. 0: disable 1:enable
# Fast tools
PBIntraFast : 1
......
......@@ -131,6 +131,7 @@ MHIntra : 1
IBC : 0 # turned off in CTC
AllowDisFracMMVD : 1
AffineAmvr : 0
LumaReshapeEnable : 1 # luma reshaping. 0: disable 1:enable
# Fast tools
PBIntraFast : 1
......
......@@ -134,6 +134,7 @@ Triangle : 1
IBC : 0 # turned off in CTC
AllowDisFracMMVD : 1
AffineAmvr : 0
LumaReshapeEnable : 1 # luma reshaping. 0: disable 1:enable
# Fast tools
PBIntraFast : 1
......
......@@ -149,6 +149,7 @@ Triangle : 1
IBC : 0 # turned off in CTC
AllowDisFracMMVD : 1
AffineAmvr : 1
LumaReshapeEnable : 1 # luma reshaping. 0: disable 1:enable
# Fast tools
PBIntraFast : 1
......
......@@ -556,6 +556,12 @@ void EncApp::xInitLibCfg()
#endif
m_cEncLib.setUseALF ( m_alf );
#if JVET_M0427_INLOOP_RESHAPER
m_cEncLib.setReshaper ( m_lumaReshapeEnable );
m_cEncLib.setReshapeSignalType ( m_reshapeSignalType );
m_cEncLib.setReshapeIntraCMD ( m_intraCMD );
m_cEncLib.setReshapeCW ( m_reshapeCW );
#endif
}
void EncApp::xCreateLib( std::list<PelUnitBuf*>& recBufList
......
......@@ -888,7 +888,11 @@ bool EncAppCfg::parseCfg( int argc, char* argv[] )
("WrapAroundOffset", m_wrapAroundOffset, 0u, "Offset in luma samples used for computing the horizontal wrap-around position")
// ADD_NEW_TOOL : (encoder app) add parsing parameters here
#if JVET_M0427_INLOOP_RESHAPER
("LumaReshapeEnable", m_lumaReshapeEnable, false, "Enable Reshaping for Luma Channel")
("ReshapeSignalType", m_reshapeSignalType, 0u, "Input signal type: 0: SDR, 1:PQ, 2:HLG")
("IntraCMD", m_intraCMD, 0u, "IntraChroma MD: 0: none, 1:fixed to default wPSNR weight")
#endif
("LCTUFast", m_useFastLCTU, false, "Fast methods for large CTU")
("FastMrg", m_useFastMrg, false, "Fast methods for inter merge")
("PBIntraFast", m_usePbIntraFast, false, "Fast assertion if the intra mode is probable")
......@@ -1842,6 +1846,14 @@ bool EncAppCfg::parseCfg( int argc, char* argv[] )
}
}
#if JVET_M0427_INLOOP_RESHAPER
m_reshapeCW.binCW.resize(3);
m_reshapeCW.rspFps = m_iFrameRate;
m_reshapeCW.rspIntraPeriod = m_iIntraPeriod;
m_reshapeCW.rspPicSize = m_iSourceWidth*m_iSourceHeight;
m_reshapeCW.rspFpsToIp = std::max(16, 16 * (int)(round((double)m_iFrameRate /16.0)));
m_reshapeCW.rspBaseQP = m_iQP;
#endif
#if ENABLE_TRACING
g_trace_ctx = tracing_init(sTracingFile, sTracingRule);
if( bTracingChannelsList && g_trace_ctx )
......@@ -2225,6 +2237,25 @@ bool EncAppCfg::xCheckParameter()
#if SHARP_LUMA_DELTA_QP
xConfirmPara( m_lumaLevelToDeltaQPMapping.mode && m_uiDeltaQpRD > 0, "Luma-level-based Delta QP cannot be used together with slice level multiple-QP optimization\n" );
#endif
#if JVET_M0427_INLOOP_RESHAPER
if (!m_lumaReshapeEnable)
{
m_reshapeSignalType = RESHAPE_SIGNAL_NULL;
m_intraCMD = 0;
}
if (m_lumaReshapeEnable && m_reshapeSignalType == RESHAPE_SIGNAL_PQ)
{
m_intraCMD = 1;
}
else if (m_lumaReshapeEnable && m_reshapeSignalType == RESHAPE_SIGNAL_SDR)
{
m_intraCMD = 0;
}
else
{
m_lumaReshapeEnable = false;
}
#endif
xConfirmPara( m_cbQpOffset < -12, "Min. Chroma Cb QP Offset is -12" );
xConfirmPara( m_cbQpOffset > 12, "Max. Chroma Cb QP Offset is 12" );
......@@ -3180,7 +3211,14 @@ void EncAppCfg::xPrintParameter()
msg( VERBOSE, "WrapAroundOffset:%d ", m_wrapAroundOffset );
}
// ADD_NEW_TOOL (add some output indicating the usage of tools)
#if JVET_M0427_INLOOP_RESHAPER
msg(VERBOSE, "Reshape:%d ", m_lumaReshapeEnable);
if (m_lumaReshapeEnable)
{
msg(VERBOSE, "(Sigal:%s ", m_reshapeSignalType==0? "SDR" : "HDR-PQ");
msg(VERBOSE, ") ");
}
#endif
msg( VERBOSE, "\nFAST TOOL CFG: " );
if( m_LargeCTU )
{
......
......@@ -262,7 +262,12 @@ protected:
unsigned m_wrapAroundOffset;
// ADD_NEW_TOOL : (encoder app) add tool enabling flags and associated parameters here
#if JVET_M0427_INLOOP_RESHAPER
bool m_lumaReshapeEnable;
uint32_t m_reshapeSignalType;
uint32_t m_intraCMD;
ReshapeCW m_reshapeCW;
#endif
unsigned m_uiMaxCUWidth; ///< max. CU width in pixel
unsigned m_uiMaxCUHeight; ///< max. CU height in pixel
unsigned m_uiMaxCUDepth; ///< max. CU depth (as specified by command line)
......
......@@ -343,6 +343,99 @@ void AreaBuf<Pel>::addWeightedAvg(const AreaBuf<const Pel> &other1, const AreaBu
#undef ADD_AVG_INC
}
#if JVET_M0427_INLOOP_RESHAPER
template<>
void AreaBuf<Pel>::rspSignal(std::vector<Pel>& pLUT)
{
Pel* dst = buf;
Pel* src = buf;
if (width == 1)
{
THROW("Blocks of width = 1 not supported");
}
else
{
for (unsigned y = 0; y < height; y++)
{
for (unsigned x = 0; x < width; x++)
{
dst[x] = pLUT[src[x]];
}
dst += stride;
src += stride;
}
}
}
template<>
void AreaBuf<Pel>::scaleSignal(const int scale, const bool dir, const ClpRng& clpRng)
{
Pel* dst = buf;
Pel* src = buf;
int sign, absval;
int maxAbsclipBD = (1<<clpRng.bd) - 1;
if (dir) // forward
{
if (width == 1)
{
THROW("Blocks of width = 1 not supported");
}
else
{
for (unsigned y = 0; y < height; y++)
{
for (unsigned x = 0; x < width; x++)
{
sign = src[x] >= 0 ? 1 : -1;
absval = sign * src[x];
dst[x] = (Pel)Clip3(-maxAbsclipBD, maxAbsclipBD, sign * (((absval << CSCALE_FP_PREC) + (scale >> 1)) / scale));
}
dst += stride;
src += stride;
}
}
}
else // inverse
{
for (unsigned y = 0; y < height; y++)
{
for (unsigned x = 0; x < width; x++)
{
sign = src[x] >= 0 ? 1 : -1;
absval = sign * src[x];
dst[x] = sign * ((absval * scale + (1 << (CSCALE_FP_PREC - 1))) >> CSCALE_FP_PREC);
}
dst += stride;
src += stride;
}
}
}
template<>
Pel AreaBuf <Pel> ::computeAvg() const
{
const Pel* src = buf;
if (width == 1)
{
THROW("Blocks of width = 1 not supported");
}
else
{
int32_t acc = 0;
#define AVG_INC \
src += stride;
#define AVG_OP(ADDR) acc += src[ADDR]
SIZE_AWARE_PER_EL_OP(AVG_OP, AVG_INC);
#undef AVG_INC
#undef AVG_OP
return Pel((acc + (area() >> 1)) / area());
}
}
#endif
template<>
void AreaBuf<Pel>::addAvg( const AreaBuf<const Pel> &other1, const AreaBuf<const Pel> &other2, const ClpRng& clpRng)
{
......
......@@ -132,6 +132,11 @@ struct AreaBuf : public Size
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]; }
......
......@@ -969,6 +969,14 @@ void CodingStructure::copyStructure( const CodingStructure& other, const Channel
// copy data to picture
picture->getRecoBuf( area ).copyFrom( recoBuf );
#if JVET_M0427_INLOOP_RESHAPER
CPelUnitBuf predBuf = other.getPredBuf(area);
if (parent)
{
getPredBuf(area).copyFrom(predBuf);
}
picture->getPredBuf(area).copyFrom(predBuf);
#endif
}
}
......
......@@ -53,6 +53,9 @@ enum PictureType
{
PIC_RECONSTRUCTION = 0,
PIC_ORIGINAL,
#if JVET_M0427_INLOOP_RESHAPER
PIC_TRUE_ORIGINAL,
#endif
PIC_PREDICTION,
PIC_RESIDUAL,
PIC_ORG_RESI,
......
......@@ -404,7 +404,6 @@ static const int CHROMA_REFINEMENT_CANDIDATES = 8; /// 8 candidates BV to choose
static const int IBC_FAST_METHOD_NOINTRA_IBCCBF0 = 0x01;
static const int IBC_FAST_METHOD_BUFFERBV = 0X02;
static const int IBC_FAST_METHOD_ADAPTIVE_SEARCHRANGE = 0X04;
#if JVET_M0512_MOTION_BUFFER_COMPRESSION
static constexpr int MV_EXPONENT_BITCOUNT = 4;
static constexpr int MV_MANTISSA_BITCOUNT = 6;
......@@ -412,7 +411,12 @@ static constexpr int MV_MANTISSA_UPPER_LIMIT = ((1 << (MV_MANTISSA_BITCOUNT - 1)
static constexpr int MV_MANTISSA_LIMIT = (1 << (MV_MANTISSA_BITCOUNT - 1));
static constexpr int MV_EXPONENT_MASK = ((1 << MV_EXPONENT_BITCOUNT) - 1);
#endif
#if JVET_M0427_INLOOP_RESHAPER
static const int PIC_ANALYZE_CW_BINS = 32;
static const int PIC_CODE_CW_BINS = 16;
static const int FP_PREC = 14;
static const int CSCALE_FP_PREC = 11;
#endif
// ====================================================================================================================
// Macro functions
// ====================================================================================================================
......
......@@ -742,6 +742,9 @@ void Picture::create(const ChromaFormat &_chromaFormat, const Size &size, const
if( !_decoder )
{
M_BUFS( 0, PIC_ORIGINAL ). create( _chromaFormat, a );
#if JVET_M0427_INLOOP_RESHAPER
M_BUFS( 0, PIC_TRUE_ORIGINAL ). create( _chromaFormat, a );
#endif
}
#if !KEEP_PRED_AND_RESI_SIGNALS
......@@ -846,6 +849,14 @@ const CPelUnitBuf Picture::getOrigBuf(const UnitArea &unit) const { return getBu
PelUnitBuf Picture::getOrigBuf() { return M_BUFS(0, PIC_ORIGINAL); }
const CPelUnitBuf Picture::getOrigBuf() const { return M_BUFS(0, PIC_ORIGINAL); }
#if JVET_M0427_INLOOP_RESHAPER
PelBuf Picture::getOrigBuf(const ComponentID compID) { return getBuf(compID, PIC_ORIGINAL); }
const CPelBuf Picture::getOrigBuf(const ComponentID compID) const { return getBuf(compID, PIC_ORIGINAL); }
PelUnitBuf Picture::getTrueOrigBuf() { return M_BUFS(0, PIC_TRUE_ORIGINAL); }
const CPelUnitBuf Picture::getTrueOrigBuf() const { return M_BUFS(0, PIC_TRUE_ORIGINAL); }
PelBuf Picture::getTrueOrigBuf(const CompArea &blk) { return getBuf(blk, PIC_TRUE_ORIGINAL); }
const CPelBuf Picture::getTrueOrigBuf(const CompArea &blk) const { return getBuf(blk, PIC_TRUE_ORIGINAL); }
#endif
PelBuf Picture::getPredBuf(const CompArea &blk) { return getBuf(blk, PIC_PREDICTION); }
const CPelBuf Picture::getPredBuf(const CompArea &blk) const { return getBuf(blk, PIC_PREDICTION); }
PelUnitBuf Picture::getPredBuf(const UnitArea &unit) { return getBuf(unit, PIC_PREDICTION); }
......
......@@ -192,6 +192,14 @@ struct Picture : public UnitArea
const CPelUnitBuf getOrigBuf(const UnitArea &unit) const;
PelUnitBuf getOrigBuf();
const CPelUnitBuf getOrigBuf() const;
#if JVET_M0427_INLOOP_RESHAPER
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;
#endif
PelBuf getPredBuf(const CompArea &blk);
const CPelBuf getPredBuf(const CompArea &blk) const;
......
......@@ -176,6 +176,11 @@ void RdCost::init()
m_motionLambda = 0;
m_iCostScale = 0;
#if JVET_M0427_INLOOP_RESHAPER
m_signalType = RESHAPE_SIGNAL_NULL;
m_chromaWeight = 1.0;
m_lumaBD = 10;
#endif
}
......@@ -2858,7 +2863,15 @@ Distortion RdCost::xGetHADs( const DistParam &rcDtParam )
#if WCG_EXT
#if JVET_M0427_INLOOP_RESHAPER
uint32_t RdCost::m_signalType;
double RdCost::m_chromaWeight;
int RdCost::m_lumaBD;
std::vector<double> RdCost::m_reshapeLumaLevelToWeightPLUT;
std::vector<double> RdCost::m_lumaLevelToWeightPLUT;
#else
double RdCost::m_lumaLevelToWeightPLUT[LUMA_LEVEL_TO_DQP_LUT_MAXSIZE];
#endif
void RdCost::saveUnadjustedLambda()
{
......@@ -2891,6 +2904,88 @@ void RdCost::initLumaLevelToWeightTable()
}
}
#if JVET_M0427_INLOOP_RESHAPER
void RdCost::initLumaLevelToWeightTableReshape()
{
int lutSize = 1 << m_lumaBD;
if (m_reshapeLumaLevelToWeightPLUT.empty())
m_reshapeLumaLevelToWeightPLUT.resize(lutSize, 1.0);
if (m_lumaLevelToWeightPLUT.empty())
m_lumaLevelToWeightPLUT.resize(lutSize, 1.0);
if (m_signalType == RESHAPE_SIGNAL_PQ)
{
for (int i = 0; i < (1 << m_lumaBD); i++)
{
double x = m_lumaBD < 10 ? i << (10 - m_lumaBD) : m_lumaBD > 10 ? i >> (m_lumaBD - 10) : i;
double y;
y = 0.015*x - 1.5 - 6;
y = y < -3 ? -3 : (y > 6 ? 6 : y);
m_reshapeLumaLevelToWeightPLUT[i] = pow(2.0, y / 3.0);
m_lumaLevelToWeightPLUT[i] = m_reshapeLumaLevelToWeightPLUT[i];
}
}
}
void RdCost::updateReshapeLumaLevelToWeightTableChromaMD(std::vector<Pel>& ILUT)
{
for (int i = 0; i < (1 << m_lumaBD); i++)
{
m_reshapeLumaLevelToWeightPLUT[i] = m_lumaLevelToWeightPLUT[ILUT[i]];
}
}
void RdCost::restoreReshapeLumaLevelToWeightTable()
{
for (int i = 0; i < (1 << m_lumaBD); i++)
{
m_reshapeLumaLevelToWeightPLUT.at(i) = m_lumaLevelToWeightPLUT.at(i);
}
}
void RdCost::updateReshapeLumaLevelToWeightTable(SliceReshapeInfo &sliceReshape, Pel *wtTable, double cwt)
{
if (m_signalType == RESHAPE_SIGNAL_SDR)
{
if (sliceReshape.getSliceReshapeModelPresentFlag())
{
double wBin = 1.0;
double weight = 1.0;
int histLens = (1 << m_lumaBD) / PIC_CODE_CW_BINS;
for (int i = 0; i < PIC_CODE_CW_BINS; i++)
{
if ((i < sliceReshape.reshaperModelMinBinIdx) || (i > sliceReshape.reshaperModelMaxBinIdx))
weight = 1.0;
else
{
if (sliceReshape.reshaperModelBinCWDelta[i] == 1 || (sliceReshape.reshaperModelBinCWDelta[i] == -1 * histLens))
weight = wBin;
else
{
weight = (double)wtTable[i] / (double)histLens;
weight = weight*weight;
}
}
for (int j = 0; j < histLens; j++)
{
int ii = i*histLens + j;
m_reshapeLumaLevelToWeightPLUT[ii] = weight;
}
}
m_chromaWeight = cwt;
}
else
{
THROW("updateReshapeLumaLevelToWeightTable ERROR!!");
}
}
else
{
THROW("updateReshapeLumaLevelToWeightTable not support other signal types!!");
}
}
#endif
Distortion RdCost::getWeightedMSE(int compIdx, const Pel org, const Pel cur, const uint32_t uiShift, const Pel orgLuma)
{
Distortion distortionVal = 0;
......@@ -2902,8 +2997,32 @@ Distortion RdCost::getWeightedMSE(int compIdx, const Pel org, const Pel cur, con
CHECK(org!=orgLuma, "");
}
// use luma to get weight
#if JVET_M0427_INLOOP_RESHAPER
double weight = 1.0;
if (m_signalType == RESHAPE_SIGNAL_SDR)
{
if (compIdx == COMPONENT_Y)
{
weight = m_reshapeLumaLevelToWeightPLUT[orgLuma];
}
else
{
weight = m_chromaWeight;
}
}
else
{
weight = m_reshapeLumaLevelToWeightPLUT[orgLuma];
}
#else
double weight = m_lumaLevelToWeightPLUT[orgLuma];
#endif
#if JVET_M0427_INLOOP_RESHAPER // FIXED_PT_WD_CALCULATION
int64_t fixedPTweight = (int64_t)(weight * (double)(1 << 16));
Intermediate_Int mse = Intermediate_Int((fixedPTweight*(iTemp*iTemp) + (1 << 15)) >> 16);
#else
Intermediate_Int mse = Intermediate_Int(weight*(double)iTemp*(double)iTemp+0.5);
#endif
distortionVal = Distortion( mse >> uiShift);
return distortionVal;
}
......
......@@ -107,7 +107,15 @@ private:
#if WCG_EXT
double m_dLambda_unadjusted; // TODO: check is necessary
double m_DistScaleUnadjusted;
#if JVET_M0427_INLOOP_RESHAPER
static std::vector<double> m_reshapeLumaLevelToWeightPLUT;
static std::vector<double> m_lumaLevelToWeightPLUT;
static uint32_t m_signalType;
static double m_chromaWeight;
static int m_lumaBD;
#else
static double m_lumaLevelToWeightPLUT[LUMA_LEVEL_TO_DQP_LUT_MAXSIZE];
#endif
#endif
double m_DistScale;
double m_dLambdaMotionSAD[2 /* 0=standard, 1=for transquant bypass when mixed-lossless cost evaluation enabled*/];
......@@ -290,6 +298,15 @@ public:
void saveUnadjustedLambda ();
void initLumaLevelToWeightTable ();
inline double getWPSNRLumaLevelWeight (int val) { return m_lumaLevelToWeightPLUT[val]; }
#if JVET_M0427_INLOOP_RESHAPER
void initLumaLevelToWeightTableReshape();
void updateReshapeLumaLevelToWeightTableChromaMD (std::vector<Pel>& ILUT);
void restoreReshapeLumaLevelToWeightTable ();
inline double getWPSNRReshapeLumaLevelWeight (int val) { return m_reshapeLumaLevelToWeightPLUT[val]; }
void setReshapeInfo (uint32_t type, int lumaBD) { m_signalType = type; m_lumaBD = lumaBD; }
void updateReshapeLumaLevelToWeightTable (SliceReshapeInfo &sliceReshape, Pel *wtTable, double cwt);
inline std::vector<double>& getLumaLevelWeightTable () { return m_lumaLevelToWeightPLUT; }
#endif
#endif
private:
......
/* 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-2019, 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 Reshape.cpp
\brief common reshaper class
*/
#include "Reshape.h"
#include <stdio.h>
#include <string.h>
#include <math.h>
#if JVET_M0427_INLOOP_RESHAPER
//! \ingroup CommonLib
//! \{
// ====================================================================================================================
// Constructor / destructor / create / destroy
// ====================================================================================================================
Reshape::Reshape()
{
m_CTUFlag = false;
m_recReshaped = false;
m_reshape = true;
}
Reshape::~Reshape()
{
}
void Reshape::createDec(int bitDepth)
{
m_lumaBD = bitDepth;
m_reshapeLUTSize = 1 << m_lumaBD;
m_initCW = m_reshapeLUTSize / PIC_CODE_CW_BINS;
if (m_fwdLUT.empty())
m_fwdLUT.resize(m_reshapeLUTSize, 0);
if (m_invLUT.empty())
m_invLUT.resize(m_reshapeLUTSize, 0);
if (m_binCW.empty())
m_binCW.resize(PIC_CODE_CW_BINS, 0);
if (m_reshapePivot.empty())
m_reshapePivot.resize(PIC_CODE_CW_BINS + 1, 0);
if (m_chromaAdjHelpLUT.empty())
m_chromaAdjHelpLUT.resize(PIC_CODE_CW_BINS, 1<<CSCALE_FP_PREC);
}
void Reshape::destroy()
{
}
/**
-Perform inverse of a one dimension LUT
\param InputLUT describing the input LUT
\retval OutputLUT describing the inversed LUT of InputLUT
\param lut_size size of LUT in number of samples
*/
void Reshape::reverseLUT(std::vector<Pel>& inputLUT, std::vector<Pel>& outputLUT, uint16_t lutSize)
{
int i, j;
outputLUT[m_reshapePivot[m_sliceReshapeInfo.reshaperModelMinBinIdx]] = m_sliceReshapeInfo.reshaperModelMinBinIdx*m_initCW;
for (i = m_sliceReshapeInfo.reshaperModelMinBinIdx; i <= m_sliceReshapeInfo.reshaperModelMaxBinIdx; i++)
{
int16_t X1 = m_reshapePivot[i];
int16_t X2 = m_reshapePivot[i + 1];
outputLUT[X2] = (i + 1)*m_initCW;
int16_t Y1 = outputLUT[X1];
int16_t Y2 = outputLUT[X2];
if (X2 !=X1)
{
int32_t scale = (int32_t)(Y2 - Y1) * (1 << FP_PREC) / (int32_t)(X2 - X1);
for (j = X1 + 1; j < X2; j++)
{
outputLUT[j] = (Pel)((scale*(int32_t)(j - X1) + (1 << (FP_PREC - 1))) >> FP_PREC) + Y1;
}
}
}
for (i = 0; i < m_reshapePivot[m_sliceReshapeInfo.reshaperModelMinBinIdx]; i++)
outputLUT[i] = outputLUT[m_reshapePivot[m_sliceReshapeInfo.reshaperModelMinBinIdx]];
for (i = m_reshapePivot[m_sliceReshapeInfo.reshaperModelMaxBinIdx + 1]; i < m_reshapeLUTSize; i++)
outputLUT[i] = outputLUT[m_reshapePivot[m_sliceReshapeInfo.reshaperModelMaxBinIdx + 1]];
bool clipRange = ((m_sliceReshapeInfo.reshaperModelMinBinIdx > 0) && (m_sliceReshapeInfo.reshaperModelMaxBinIdx < (PIC_CODE_CW_BINS - 1)));
for (i = 0; i < lutSize; i++)
{
if (clipRange) outputLUT[i] = Clip3((Pel)(16<<(m_lumaBD-8)), (Pel)(235<<(m_lumaBD-8)), outputLUT[i]);
else outputLUT[i] = Clip3((Pel)0, (Pel)((1<<m_lumaBD)-1), outputLUT[i]);
}
}
/** compute chroma residuce scale for TU
* \param average luma pred of TU
* \return chroma residue scale
*/
int Reshape::calculateChromaAdj(Pel avgLuma)
{
int lumaIdx = Clip3<int>(0, (1<<m_lumaBD) - 1, avgLuma);
int iAdj = m_chromaAdjHelpLUT[getPWLIdxInv(lumaIdx)];
return(iAdj);
}
/** find inx of PWL for inverse mapping
* \param average luma pred of TU
* \return idx of PWL for inverse mapping
*/