Skip to content
Snippets Groups Projects
Reshape.cpp 10.4 KiB
Newer Older
Taoran Lu's avatar
Taoran Lu committed
/* 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_O1109_UNFIY_CRS
#include <UnitTools.h>
#endif
Taoran Lu's avatar
Taoran Lu committed
 //! \ingroup CommonLib
 //! \{

 // ====================================================================================================================
 // Constructor / destructor / create / destroy
 // ====================================================================================================================

Reshape::Reshape()
{
Taoran Lu's avatar
Taoran Lu committed
  m_CTUFlag = false;
  m_recReshaped = false;
  m_reshape = true;
#if  JVET_O1109_UNFIY_CRS
  m_chromaScale = (1 << CSCALE_FP_PREC);
#endif
Taoran Lu's avatar
Taoran Lu committed
}

Reshape::~Reshape()
{
}

void  Reshape::createDec(int bitDepth)
  m_lumaBD = bitDepth;
  m_reshapeLUTSize = 1 << m_lumaBD;
  m_initCW = m_reshapeLUTSize / PIC_CODE_CW_BINS;
Taoran Lu's avatar
Taoran Lu committed
  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);
Taoran Lu's avatar
Taoran Lu committed
}

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)
Taoran Lu's avatar
Taoran Lu committed
{
  int i, j;
Taoran Lu's avatar
Taoran Lu committed
  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];
Taoran Lu's avatar
Taoran Lu committed

    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;
Taoran Lu's avatar
Taoran Lu committed
  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]];
Taoran Lu's avatar
Taoran Lu committed
  for (i = 0; i < lutSize; i++)
  {
    outputLUT[i] = Clip3((Pel)0, (Pel)((1<<m_lumaBD)-1), outputLUT[i]);
  }
Taoran Lu's avatar
Taoran Lu committed
}


/** 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)];
Taoran Lu's avatar
Taoran Lu committed
  return(iAdj);
}

#if JVET_O1109_UNFIY_CRS
/** compute chroma residuce scale for TU
* \param average luma pred of TU
* \return chroma residue scale
*/
int  Reshape::calculateChromaAdjVpduNei(TransformUnit &tu, const CompArea &areaY)
{
  CodingStructure &cs = *tu.cs;
  int xPos = areaY.lumaPos().x;
  int yPos = areaY.lumaPos().y;
  int ctuSize = cs.sps->getCTUSize();
  if (ctuSize == 128)
  {
    xPos = xPos / 64 * 64;
    yPos = yPos / 64 * 64;
  }
  else
  {
    xPos = xPos / ctuSize * ctuSize;
    yPos = yPos / ctuSize * ctuSize;
  }

  if (isVPDUprocessed(xPos, yPos) && !cs.pcv->isEncoder)
  {
    return getChromaScale();
  }
  else
  {
    setVPDULoc(xPos, yPos);
    Position topLeft(xPos, yPos);
    CodingUnit *topLeftLuma;
    if (CS::isDualITree(cs) && cs.slice->getSliceType() == I_SLICE)
      topLeftLuma = tu.cs->picture->cs->getCU(topLeft, CHANNEL_TYPE_LUMA);
    else
      topLeftLuma = cs.getCU(topLeft, CHANNEL_TYPE_LUMA);

    xPos = topLeftLuma->lumaPos().x;
    yPos = topLeftLuma->lumaPos().y;
    CompArea lumaArea = CompArea(COMPONENT_Y, tu.chromaFormat, topLeftLuma->lumaPos(), topLeftLuma->lumaSize(), true);
    PelBuf piRecoY = cs.picture->getRecoBuf(lumaArea);
    int strideY = piRecoY.stride;
    int chromaScale = (1 << CSCALE_FP_PREC);
    int lumaValue = -1;

    Pel* recSrc0 = piRecoY.bufAt(0, 0);
    const uint32_t picH = tu.cs->picture->lheight();
    const uint32_t picW = tu.cs->picture->lwidth();
    const Pel   valueDC = 1 << (tu.cs->sps->getBitDepth(CHANNEL_TYPE_LUMA) - 1);
    int32_t recLuma = 0;
    int pelnum = 0;
    if (xPos > 0)
    {
      for (int i = 0; i < NEIG_NUM; i++)
      {
        int k = (yPos + i) >= picH ? (picH - yPos - 1) : i;
        recLuma += recSrc0[-1 + k * strideY];
        pelnum++;
      }
    }
    if (yPos > 0)
    {
      for (int i = 0; i < NEIG_NUM; i++)
      {
        int k = (xPos + i) >= picW ? (picW - xPos - 1) : i;
        recLuma += recSrc0[-strideY + k];
        pelnum++;
      }
    }
    if (pelnum == NEIG_NUM)
    {
      lumaValue = ClipPel((recLuma + (1 << (NEIG_NUM_LOG - 1))) >> NEIG_NUM_LOG, tu.cs->slice->clpRng(COMPONENT_Y));
    }
    else if (pelnum == (NEIG_NUM << 1))
    {
      lumaValue = ClipPel((recLuma + (1 << NEIG_NUM_LOG)) >> (NEIG_NUM_LOG + 1), tu.cs->slice->clpRng(COMPONENT_Y));
    }
    else
    {
      CHECK(pelnum != 0, "");
      lumaValue = ClipPel(valueDC, tu.cs->slice->clpRng(COMPONENT_Y));
    }
    chromaScale = calculateChromaAdj(lumaValue);
    setChromaScale(chromaScale);
    return(chromaScale);
  }
}
#endif
Taoran Lu's avatar
Taoran Lu committed
/** find inx of PWL for inverse mapping
* \param average luma pred of TU
* \return idx of PWL for inverse mapping
*/
int Reshape::getPWLIdxInv(int lumaVal)
{
  int idxS = 0;
Taoran Lu's avatar
Taoran Lu committed
  if (lumaVal < m_reshapePivot[m_sliceReshapeInfo.reshaperModelMinBinIdx + 1])
    return m_sliceReshapeInfo.reshaperModelMinBinIdx;
  else if (lumaVal >= m_reshapePivot[m_sliceReshapeInfo.reshaperModelMaxBinIdx])
    return m_sliceReshapeInfo.reshaperModelMaxBinIdx;
Taoran Lu's avatar
Taoran Lu committed
    for (idxS = m_sliceReshapeInfo.reshaperModelMinBinIdx; (idxS < m_sliceReshapeInfo.reshaperModelMaxBinIdx); idxS++)
      if (lumaVal < m_reshapePivot[idxS + 1])     break;
Taoran Lu's avatar
Taoran Lu committed
    }
    return idxS;
  }
}

/**
-copy Slice reshaper info structure
\param   tInfo describing the target Slice reshaper info structure
\param   sInfo describing the source Slice reshaper info structure
*/
Taoran Lu's avatar
Taoran Lu committed
void Reshape::copySliceReshaperInfo(SliceReshapeInfo& tInfo, SliceReshapeInfo& sInfo)
Taoran Lu's avatar
Taoran Lu committed
  tInfo.sliceReshaperModelPresentFlag = sInfo.sliceReshaperModelPresentFlag;
  if (sInfo.sliceReshaperModelPresentFlag)
Taoran Lu's avatar
Taoran Lu committed
    tInfo.reshaperModelMaxBinIdx = sInfo.reshaperModelMaxBinIdx;
    tInfo.reshaperModelMinBinIdx = sInfo.reshaperModelMinBinIdx;
    memcpy(tInfo.reshaperModelBinCWDelta, sInfo.reshaperModelBinCWDelta, sizeof(int)*(PIC_CODE_CW_BINS));
Taoran Lu's avatar
Taoran Lu committed
    tInfo.maxNbitsNeededDeltaCW = sInfo.maxNbitsNeededDeltaCW;
  }
Taoran Lu's avatar
Taoran Lu committed
  tInfo.sliceReshaperEnableFlag = sInfo.sliceReshaperEnableFlag;
  if (sInfo.sliceReshaperEnableFlag)
    tInfo.enableChromaAdj = sInfo.enableChromaAdj;
Taoran Lu's avatar
Taoran Lu committed
  else
Taoran Lu's avatar
Taoran Lu committed
    tInfo.enableChromaAdj = 0;
Taoran Lu's avatar
Taoran Lu committed
}

/** Construct reshaper from syntax
* \param void
* \return void
*/
void Reshape::constructReshaper()
{
  int pwlFwdLUTsize = PIC_CODE_CW_BINS;
  int pwlFwdBinLen = m_reshapeLUTSize / PIC_CODE_CW_BINS;
Taoran Lu's avatar
Taoran Lu committed
  for (int i = 0; i < m_sliceReshapeInfo.reshaperModelMinBinIdx; i++)
    m_binCW[i] = 0;
Taoran Lu's avatar
Taoran Lu committed
  for (int i = m_sliceReshapeInfo.reshaperModelMaxBinIdx + 1; i < PIC_CODE_CW_BINS; i++)
    m_binCW[i] = 0;
Taoran Lu's avatar
Taoran Lu committed
  for (int i = m_sliceReshapeInfo.reshaperModelMinBinIdx; i <= m_sliceReshapeInfo.reshaperModelMaxBinIdx; i++)
    m_binCW[i] = (uint16_t)(m_sliceReshapeInfo.reshaperModelBinCWDelta[i] + (int)m_initCW);
Taoran Lu's avatar
Taoran Lu committed

  for (int i = 0; i < pwlFwdLUTsize; i++)
  {
    m_reshapePivot[i + 1] = m_reshapePivot[i] + m_binCW[i];
    int16_t Y1 = m_reshapePivot[i];
    int16_t Y2 = m_reshapePivot[i + 1];
Taoran Lu's avatar
Taoran Lu committed
    m_fwdLUT[i*pwlFwdBinLen] = Clip3((Pel)0, (Pel)((1 << m_lumaBD) - 1), (Pel)Y1);
    int log2PwlFwdBinLen = floorLog2(pwlFwdBinLen);
Taoran Lu's avatar
Taoran Lu committed
    int32_t scale = ((int32_t)(Y2 - Y1) * (1 << FP_PREC) + (1 << (log2PwlFwdBinLen - 1))) >> (log2PwlFwdBinLen);
Taoran Lu's avatar
Taoran Lu committed
    for (int j = 1; j < pwlFwdBinLen; j++)
    {
      int tempVal = Y1 + (((int32_t)scale * (int32_t)j + (1 << (FP_PREC - 1))) >> FP_PREC);
Taoran Lu's avatar
Taoran Lu committed
      m_fwdLUT[i*pwlFwdBinLen + j] = Clip3((Pel)0, (Pel)((1 << m_lumaBD) - 1), (Pel)tempVal);
Taoran Lu's avatar
Taoran Lu committed
  reverseLUT(m_fwdLUT, m_invLUT, m_reshapeLUTSize);
  updateChromaScaleLUT();
Taoran Lu's avatar
Taoran Lu committed
}

/** generate chroma residue scaling LUT
* \param void
* \return void
*/
Taoran Lu's avatar
Taoran Lu committed
void Reshape::updateChromaScaleLUT()
Taoran Lu's avatar
Taoran Lu committed
  for (int i = 0; i < PIC_CODE_CW_BINS; i++)
  {
Taoran Lu's avatar
Taoran Lu committed
    if (m_binCW[i] == 0)
Taoran Lu's avatar
Taoran Lu committed
      m_chromaAdjHelpLUT[i] = 1 << CSCALE_FP_PREC;
    else
Taoran Lu's avatar
Taoran Lu committed
      m_chromaAdjHelpLUT[i] = m_initCW * (1 << CSCALE_FP_PREC) / m_binCW[i];