Skip to content
Snippets Groups Projects
EncReshape.cpp 39.6 KiB
Newer Older
  • Learn to ignore specific revisions
  • Taoran Lu's avatar
    Taoran Lu committed
    */
    void EncReshape::initLUTfromdQPModel()
    {
      initModelParam();
      int pwlFwdLUTsize = PIC_CODE_CW_BINS;
    
      int pwlFwdBinLen = m_reshapeLUTSize / PIC_CODE_CW_BINS;
      int p1 = m_dQPModel.ScaleFracPrec; //=16, precision of 0.015
      int p2 = m_dQPModel.OffsetFracPrec; //=1, precision of 7.5
    
    Taoran Lu's avatar
    Taoran Lu committed
      int total_shift = p1 + p2;
    
      int scaleFP = (1 - 2 * m_dQPModel.ScaleSign)  * m_dQPModel.ScaleAbs;
      int offsetFP = (1 - 2 * m_dQPModel.OffsetSign) * m_dQPModel.OffsetAbs;
      int maxQP = (1 - 2 * m_dQPModel.MaxQPSign)  * m_dQPModel.MaxQPAbs;
      int minQP = (1 - 2 * m_dQPModel.MinQPSign)  * m_dQPModel.MinQPAbs;
    
    Taoran Lu's avatar
    Taoran Lu committed
      int maxFP = maxQP * (1 << total_shift);
      int minFP = minQP * (1 << total_shift);
      int temp, signval, absval;
      int dQPDIV6_FP;
    
      int32_t * SlopeLUT = new int32_t[m_reshapeLUTSize]();
      int32_t * fLUT_HP = new int32_t[m_reshapeLUTSize]();
    
      for (int i = 0; i < m_reshapeLUTSize; i++)
    
        int inputY = m_lumaBD < 10 ? i << (10 - m_lumaBD) : m_lumaBD > 10 ? i >> (m_lumaBD - 10) : i;
        temp = int64_t((scaleFP*inputY) * (1 << p2)) + int64_t(offsetFP * (1 << p1));
    
    Taoran Lu's avatar
    Taoran Lu committed
        temp = temp > maxFP ? maxFP : temp < minFP ? minFP : temp;
        signval = temp >= 0 ? 1 : -1;
        absval = signval * temp;
        dQPDIV6_FP = signval * (((absval + 3) / 6 + (1 << (total_shift - 17))) >> (total_shift - 16));
        SlopeLUT[i] = calcEXP2(dQPDIV6_FP);
      }
    
    
      if (m_dQPModel.FullRangeInputFlag == 0)
    
        for (int i = 0; i < (16 << (m_lumaBD - 8)); i++)                    {      SlopeLUT[i] = 0;    }
        for (int i = (235 << (m_lumaBD - 8)); i < m_reshapeLUTSize; i++)    {      SlopeLUT[i] = 0;    }
    
      for (int i = 0; i < m_reshapeLUTSize - 1; i++)
    
    Taoran Lu's avatar
    Taoran Lu committed
        fLUT_HP[i + 1] = fLUT_HP[i] + SlopeLUT[i];
      if (SlopeLUT != nullptr)   {    delete[] SlopeLUT;    SlopeLUT = nullptr;  }
    
    
      int max_Y = (fLUT_HP[m_reshapeLUTSize - 1] + (1 << 7)) >> 8;
    
    Taoran Lu's avatar
    Taoran Lu committed
      int Roffset = max_Y >> 1;
    
      for (int i = 0; i < m_reshapeLUTSize; i++)
    
        forwardReshapingLUT[i] = (short)(((fLUT_HP[i] >> 8) * (m_reshapeLUTSize - 1) + Roffset) / max_Y);
    
    Taoran Lu's avatar
    Taoran Lu committed
      }
    
      if (fLUT_HP != nullptr)   {    delete[] fLUT_HP;    fLUT_HP = nullptr;  }
      m_sliceReshapeInfo.reshape_model_min_bin_idx = 1;
      m_sliceReshapeInfo.reshape_model_max_bin_idx = 14;
    
      for (int i = 0; i < pwlFwdLUTsize; i++)
      {
        int16_t X1 = i * pwlFwdBinLen;
    
        m_reshapePivot[i] = forwardReshapingLUT[X1];
    
      m_reshapePivot[pwlFwdLUTsize] = ((1 << m_lumaBD) - 1);
    
    Taoran Lu's avatar
    Taoran Lu committed
    
      for (int i = 0; i < pwlFwdLUTsize; i++)
      {
    
        m_binCW[i] = m_reshapePivot[i + 1] - m_reshapePivot[i];
    
    Taoran Lu's avatar
    Taoran Lu committed
      }
    
      int maxAbsDeltaCW = 0, AbsDeltaCW = 0, DeltaCW = 0;
      for (int i = m_sliceReshapeInfo.reshape_model_min_bin_idx; i <= m_sliceReshapeInfo.reshape_model_max_bin_idx; i++)
      {
    
        DeltaCW = (int)m_binCW[i] - (int)m_initCW;
    
    Taoran Lu's avatar
    Taoran Lu committed
        m_sliceReshapeInfo.reshape_model_bin_CW_delta[i] = DeltaCW;
        AbsDeltaCW = (DeltaCW < 0) ? (-DeltaCW) : DeltaCW;
        if (AbsDeltaCW > maxAbsDeltaCW)     {      maxAbsDeltaCW = AbsDeltaCW;    }
      }
      m_sliceReshapeInfo.maxNbitsNeededDeltaCW = g_aucLog2[maxAbsDeltaCW << 1];
    
      for (int i = 0; i < pwlFwdLUTsize; i++)
      {
    
        int16_t Y1 = m_reshapePivot[i];
        int16_t Y2 = m_reshapePivot[i + 1];
        forwardReshapingLUT[i*pwlFwdBinLen] = Clip3((Pel)0, (Pel)((1 << m_lumaBD) - 1), (Pel)Y1);
        int log2_pwlFwdBinLen = g_aucLog2[pwlFwdBinLen];
    
    Taoran Lu's avatar
    Taoran Lu committed
        int32_t scale = ((int32_t)(Y2 - Y1) * (1 << FP_PREC) + (1 << (log2_pwlFwdBinLen - 1))) >> (log2_pwlFwdBinLen);
        for (int j = 1; j < pwlFwdBinLen; j++)
        {
          int tempVal = Y1 + (((int32_t)scale * (int32_t)j + (1 << (FP_PREC - 1))) >> FP_PREC);
    
          forwardReshapingLUT[i*pwlFwdBinLen + j] = Clip3((Pel)0, (Pel)((1<<m_lumaBD) -1), (Pel)tempVal);
    
      reverseLUT(forwardReshapingLUT, inverseReshapingLUT, m_reshapeLUTSize);
    
    Taoran Lu's avatar
    Taoran Lu committed
      updateChromaDQPLUT();
    }
    
    
    /**
    -Perform fixe point exp2 calculation
    \param   val  input value
    \retval  output value = exp2(val)
    */
    int EncReshape::calcEXP2(int val)
    {
      int32_t i, f, r, s;
      r = 0x00000e20;
    
      i = ((int32_t)(val)+0x8000) & ~0xffff;
      f = (int32_t)(val)-i;
      s = ((15 << 16) - i) >> 16;
    
      r = (r * f + 0x3e1cc333) >> 17;
      r = (r * f + 0x58bd46a6) >> 16;
      r = r * f + 0x7ffde4a3;
      return (uint32_t)r >> s;
    }
    
    void EncReshape::constructReshaperSDR()
    {
      int used_codewords;
    
      int tot_cw = m_reshapeLUTSize;
    
    Taoran Lu's avatar
    Taoran Lu committed
      int hist_bins = PIC_ANALYZE_CW_BINS;
    
      int hist_lens = m_initCWAnalyze;
      int log2_hist_lens = g_aucLog2[hist_lens];
      int16_t *Y_LUT_all = new int16_t[m_reshapeLUTSize + 1]();
    
    Taoran Lu's avatar
    Taoran Lu committed
      int i, j;
      int cw_scale_bins1, cw_scale_bins2;
      int max_allow_cw = tot_cw;
    
      cw_scale_bins1 = m_reshapeCW.BinCW[0];
      cw_scale_bins2 = m_reshapeCW.BinCW[1];
    
      used_codewords = 0;
      for (i = 0; i < hist_bins; i++)
    
        used_codewords += m_binCW[i];
    
    Taoran Lu's avatar
    Taoran Lu committed
    
      if (used_codewords > max_allow_cw)
      {
        int cnt0 = 0, cnt1 = 0, cnt2 = 0;
        for (i = 0; i < hist_bins; i++)
        {
    
          if (m_binCW[i] == hist_lens + 1)               cnt0++;
          else if (m_binCW[i] == cw_scale_bins1)         cnt1++;
          else if (m_binCW[i] == cw_scale_bins2)         cnt2++;
    
    Taoran Lu's avatar
    Taoran Lu committed
        }
    
        int delta_cw = used_codewords - max_allow_cw;
        int cw_reduce1 = (cw_scale_bins1 - hist_lens - 1) * cnt1;
        int cw_reduce2 = (hist_lens + 1 - cw_scale_bins2) * cnt0;
    
        if (delta_cw <= cw_reduce1)
        {
          int idx = 0;
          while (delta_cw > 0)
          {
    
            if (m_binCW[idx] > (hist_lens + 1))
    
              m_binCW[idx]--;
    
    Taoran Lu's avatar
    Taoran Lu committed
              delta_cw--;
            }
            idx++;
            if (idx == hist_bins)
              idx = 0;
          }
        }
        else if (delta_cw > cw_reduce1 && delta_cw <= (cw_reduce1 + cw_reduce2))
        {
          delta_cw -= cw_reduce1;
          int idx = 0;
          while (delta_cw > 0)
          {
    
            if (m_binCW[idx] > cw_scale_bins2 && m_binCW[idx] < cw_scale_bins1)
    
              m_binCW[idx]--;
    
    Taoran Lu's avatar
    Taoran Lu committed
              delta_cw--;
            }
            idx++;
            if (idx == hist_bins)
              idx = 0;
          }
          for (i = 0; i < hist_bins; i++)
          {
    
            if (m_binCW[i] == cw_scale_bins1)
              m_binCW[i] = hist_lens + 1;
    
    Taoran Lu's avatar
    Taoran Lu committed
          }
        }
        else if (delta_cw > (cw_reduce1 + cw_reduce2))
        {
          delta_cw -= (cw_reduce1 + cw_reduce2);
          int idx = 0;
          while (delta_cw > 0)
          {
    
            if (m_binCW[idx] > 0 && m_binCW[idx] < (hist_lens + 1))
    
              m_binCW[idx]--;
    
    Taoran Lu's avatar
    Taoran Lu committed
              delta_cw--;
            }
            idx++;
            if (idx == hist_bins)
              idx = 0;
          }
          for (i = 0; i < hist_bins; i++)
          {
    
            if (m_binCW[i] == m_initCWAnalyze + 1)
              m_binCW[i] = cw_scale_bins2;
            if (m_binCW[i] == cw_scale_bins1)
              m_binCW[i] = m_initCWAnalyze + 1;
    
    Taoran Lu's avatar
    Taoran Lu committed
          }
        }
      }
    
      for (int i = 0; i < PIC_CODE_CW_BINS; i++)
      {
    
        m_binCW[i] = m_binCW[2 * i] + m_binCW[2 * i + 1];
    
    Taoran Lu's avatar
    Taoran Lu committed
      }
      m_sliceReshapeInfo.reshape_model_min_bin_idx = 0;
      m_sliceReshapeInfo.reshape_model_max_bin_idx = PIC_CODE_CW_BINS - 1;
      for (int i = 0; i < PIC_CODE_CW_BINS; i++)
      {
    
        if (m_binCW[i] > 0)
    
    Taoran Lu's avatar
    Taoran Lu committed
        {
          m_sliceReshapeInfo.reshape_model_min_bin_idx = i;
          break;
        }
      }
      for (int i = PIC_CODE_CW_BINS - 1; i >= 0; i--)
      {
    
        if (m_binCW[i] > 0)
    
    Taoran Lu's avatar
    Taoran Lu committed
        {
          m_sliceReshapeInfo.reshape_model_max_bin_idx = i;
          break;
        }
      }
    
      int maxAbsDeltaCW = 0, AbsDeltaCW = 0, DeltaCW = 0;
      for (int i = m_sliceReshapeInfo.reshape_model_min_bin_idx; i <= m_sliceReshapeInfo.reshape_model_max_bin_idx; i++)
      {
    
        DeltaCW = (int)m_binCW[i] - (int)m_initCW;
    
    Taoran Lu's avatar
    Taoran Lu committed
        m_sliceReshapeInfo.reshape_model_bin_CW_delta[i] = DeltaCW;
        AbsDeltaCW = (DeltaCW < 0) ? (-DeltaCW) : DeltaCW;
        if (AbsDeltaCW > maxAbsDeltaCW)      {      maxAbsDeltaCW = AbsDeltaCW;    }
      }
      m_sliceReshapeInfo.maxNbitsNeededDeltaCW = g_aucLog2[maxAbsDeltaCW << 1];
    
      hist_bins = PIC_CODE_CW_BINS;
    
      hist_lens = m_initCW;
      log2_hist_lens = g_aucLog2[hist_lens];
    
    Taoran Lu's avatar
    Taoran Lu committed
    
      int sum_bins = 0;
    
      for (i = 0; i < hist_bins; i++)   {    sum_bins += m_binCW[i];  }
    
    Taoran Lu's avatar
    Taoran Lu committed
    
      CHECK(sum_bins > max_allow_cw, "SDR CW assignment is wrong!!");
    
    
      memset(Y_LUT_all, 0, (m_reshapeLUTSize + 1) * sizeof(int16_t));
    
    Taoran Lu's avatar
    Taoran Lu committed
      Y_LUT_all[0] = 0;
    
      for (i = 0; i < hist_bins; i++)
      {
    
        Y_LUT_all[(i + 1)*hist_lens] = Y_LUT_all[i*hist_lens] + m_binCW[i];
    
    Taoran Lu's avatar
    Taoran Lu committed
        int16_t Y1 = Y_LUT_all[i*hist_lens];
        int16_t Y2 = Y_LUT_all[(i + 1)*hist_lens];
    
        m_reshapePivot[i + 1] = Y2;
    
    Taoran Lu's avatar
    Taoran Lu committed
        int32_t scale = ((int32_t)(Y2 - Y1) * (1 << FP_PREC) + (1 << (log2_hist_lens - 1))) >> (log2_hist_lens);
    
        forwardReshapingLUT[i*hist_lens] = Clip3((Pel)0, (Pel)((1 << m_lumaBD) - 1), (Pel)Y1);
    
    Taoran Lu's avatar
    Taoran Lu committed
        for (j = 1; j < hist_lens; j++)
        {
          Y_LUT_all[i*hist_lens + j] = Y1 + (((int32_t)scale * (int32_t)j + (1 << (FP_PREC - 1))) >> FP_PREC);
    
          forwardReshapingLUT[i*hist_lens + j] = Clip3((Pel)0, (Pel)((1 << m_lumaBD) - 1), (Pel)Y_LUT_all[i*hist_lens + j]);
    
    Taoran Lu's avatar
    Taoran Lu committed
        }
      }
    
      for (i = 0; i < PIC_CODE_CW_BINS; i++)
      {
        int i_start = i*hist_lens;
        int i_end = (i + 1)*hist_lens - 1;
        m_cwLumaWeight[i] = forwardReshapingLUT[i_end] - forwardReshapingLUT[i_start];
      }
    
      if (Y_LUT_all != nullptr)   {     delete[] Y_LUT_all;    Y_LUT_all = nullptr;  }
    
    
      reverseLUT(forwardReshapingLUT, inverseReshapingLUT, m_reshapeLUTSize);
    
    Taoran Lu's avatar
    Taoran Lu committed
      updateChromaDQPLUT();
    }
    
    #endif
    //
    //! \}