Skip to content
Snippets Groups Projects
Reshape.cpp 9.87 KiB
Newer Older
  • Learn to ignore specific revisions
  • 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>
    
    #include <UnitTools.h>
    
    Taoran Lu's avatar
    Taoran Lu committed
     //! \ingroup CommonLib
     //! \{
    
     // ====================================================================================================================
     // Constructor / destructor / create / destroy
     // ====================================================================================================================
    
    Reshape::Reshape()
    
    : m_CTUFlag (false)
    , m_recReshaped (false)
    , m_reshape (true)
    , m_chromaScale (1 << CSCALE_FP_PREC)
    , m_vpduX (-1)
    , m_vpduY (-1)
    {
    
    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);
    
    Taoran Lu's avatar
    Taoran Lu committed
      if (m_inputPivot.empty())
        m_inputPivot.resize(PIC_CODE_CW_BINS + 1, 0);
      if (m_fwdScaleCoef.empty())
        m_fwdScaleCoef.resize(PIC_CODE_CW_BINS, 1 << FP_PREC);
      if (m_invScaleCoef.empty())
        m_invScaleCoef.resize(PIC_CODE_CW_BINS, 1 << FP_PREC);
    
      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()
    {
    }
    
    
    
    /** 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);
    }
    
    
    /** 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();
    
    Taoran Lu's avatar
    Taoran Lu committed
      int numNeighbor = std::min(64, ctuSize);
    
      int numNeighborLog = floorLog2(numNeighbor);
    
      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;
    
    Taoran Lu's avatar
    Taoran Lu committed
        const CodingUnit *cuAbove, *cuLeft;
    
        if (CS::isDualITree(cs) && cs.slice->getSliceType() == I_SLICE)
    
    Taoran Lu's avatar
    Taoran Lu committed
        {
    
          topLeftLuma = tu.cs->picture->cs->getCU(topLeft, CHANNEL_TYPE_LUMA);
    
    Taoran Lu's avatar
    Taoran Lu committed
          cuAbove = cs.picture->cs->getCURestricted(topLeftLuma->lumaPos().offset(0, -1), *topLeftLuma, CHANNEL_TYPE_LUMA);
          cuLeft  = cs.picture->cs->getCURestricted(topLeftLuma->lumaPos().offset(-1, 0), *topLeftLuma, CHANNEL_TYPE_LUMA);
        }
    
    Taoran Lu's avatar
    Taoran Lu committed
        {
    
          topLeftLuma = cs.getCU(topLeft, CHANNEL_TYPE_LUMA);
    
    Taoran Lu's avatar
    Taoran Lu committed
          cuAbove = cs.getCURestricted(topLeftLuma->lumaPos().offset(0, -1), *topLeftLuma, CHANNEL_TYPE_LUMA);
          cuLeft  = cs.getCURestricted(topLeftLuma->lumaPos().offset(-1, 0), *topLeftLuma, 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;
    
    Taoran Lu's avatar
    Taoran Lu committed
        if (cuLeft != nullptr)
    
    Taoran Lu's avatar
    Taoran Lu committed
          for (int i = 0; i < numNeighbor; i++)
    
          {
            int k = (yPos + i) >= picH ? (picH - yPos - 1) : i;
            recLuma += recSrc0[-1 + k * strideY];
            pelnum++;
          }
        }
    
    Taoran Lu's avatar
    Taoran Lu committed
        if (cuAbove != nullptr)
    
    Taoran Lu's avatar
    Taoran Lu committed
          for (int i = 0; i < numNeighbor; i++)
    
          {
            int k = (xPos + i) >= picW ? (picW - xPos - 1) : i;
            recLuma += recSrc0[-strideY + k];
            pelnum++;
          }
        }
    
    Taoran Lu's avatar
    Taoran Lu committed
        if (pelnum == numNeighbor)
    
    Taoran Lu's avatar
    Taoran Lu committed
          lumaValue = ClipPel((recLuma + (1 << (numNeighborLog - 1))) >> numNeighborLog, tu.cs->slice->clpRng(COMPONENT_Y));
    
    Taoran Lu's avatar
    Taoran Lu committed
        else if (pelnum == (numNeighbor << 1))
    
    Taoran Lu's avatar
    Taoran Lu committed
          lumaValue = ClipPel((recLuma + (1 << numNeighborLog)) >> (numNeighborLog + 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);
      }
    }
    
    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
      for (idxS = m_sliceReshapeInfo.reshaperModelMinBinIdx; (idxS <= m_sliceReshapeInfo.reshaperModelMaxBinIdx); idxS++)
      {
        if (lumaVal < m_reshapePivot[idxS + 1])     break;
      }
    
      return std::min(idxS, PIC_CODE_CW_BINS-1);
    
    Taoran Lu's avatar
    Taoran Lu committed
    }
    
    /**
    -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;
    
    #if JVET_P0371_CHROMA_SCALING_OFFSET
        tInfo.chrResScalingOffset = sInfo.chrResScalingOffset;
    #endif
    
    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];
        m_inputPivot[i + 1] = m_inputPivot[i] + m_initCW;
        m_fwdScaleCoef[i] = ((int32_t)m_binCW[i] * (1 << FP_PREC) + (1 << (floorLog2(pwlFwdBinLen) - 1))) >> floorLog2(pwlFwdBinLen);
        if (m_binCW[i] == 0)
        {
          m_invScaleCoef[i] = 0;
          m_chromaAdjHelpLUT[i] = 1 << CSCALE_FP_PREC;
        }
        else
        {
          m_invScaleCoef[i] = (int32_t)(m_initCW * (1 << FP_PREC) / m_binCW[i]);
    
    #if JVET_P0371_CHROMA_SCALING_OFFSET
          m_chromaAdjHelpLUT[i] = (int32_t)(m_initCW * (1 << FP_PREC) / ( m_binCW[i] + m_sliceReshapeInfo.chrResScalingOffset ) );
    #else
    
    Taoran Lu's avatar
    Taoran Lu committed
          m_chromaAdjHelpLUT[i] = m_invScaleCoef[i];
    
    Taoran Lu's avatar
    Taoran Lu committed
        }
      }
      for (int lumaSample = 0; lumaSample < m_reshapeLUTSize; lumaSample++)
      {
        int idxY = lumaSample / m_initCW;
        int tempVal = m_reshapePivot[idxY] + ((m_fwdScaleCoef[idxY] * (lumaSample - m_inputPivot[idxY]) + (1 << (FP_PREC - 1))) >> FP_PREC);
        m_fwdLUT[lumaSample] = Clip3((Pel)0, (Pel)((1 << m_lumaBD) - 1), (Pel)(tempVal));
    
        int idxYInv = getPWLIdxInv(lumaSample);
        int invSample = m_inputPivot[idxYInv] + ((m_invScaleCoef[idxYInv] * (lumaSample - m_reshapePivot[idxYInv]) + (1 << (FP_PREC - 1))) >> FP_PREC);
        m_invLUT[lumaSample] = Clip3((Pel)0, (Pel)((1 << m_lumaBD) - 1), (Pel)(invSample));
      }