Skip to content
Snippets Groups Projects
EncGOP.cpp 150 KiB
Newer Older
  • Learn to ignore specific revisions
  •   if (pcSlice->isIRAP())//(pocCurr == 0)
    
      {
        curPic->extendPicBorder();
        curPic->setBorderExtension(true);
    
        m_picBg->getRecoBuf().copyFrom(curPic->getRecoBuf());
        m_picOrig->getOrigBuf().copyFrom(curPic->getOrigBuf());
      }
      else
      {
        //cout << "update B" << pocCurr << endl;
        for (int y = 0; y < height; y += maxCuHeight)
        {
          for (int x = 0; x < width; x += maxCuWidth)
          {
            if (m_picBg->getSpliceIdx((y / maxCuHeight)*pcv->widthInCtus + x / maxCuWidth) == pocCurr)
            {
              for (int tmpy = 0; tmpy < maxCuHeight; tmpy++)
              {
                if (y + tmpy >= height)
                {
                  break;
                }
                for (int tmpx = 0; tmpx < maxCuWidth; tmpx++)
                {
                  if (x + tmpx >= width)
                  {
                    break;
                  }
                  bgLumaAddr[(y + tmpy)*stride + x + tmpx] = curLumaAddr[(y + tmpy)*stride + x + tmpx];
                  if (tmpy % 2 == 0 && tmpx % 2 == 0)
                  {
                    bgCbAddr[(y + tmpy) / 2 * cStride + (x + tmpx) / 2] = curCbAddr[(y + tmpy) / 2 * cStride + (x + tmpx) / 2];
                    bgCrAddr[(y + tmpy) / 2 * cStride + (x + tmpx) / 2] = curCrAddr[(y + tmpy) / 2 * cStride + (x + tmpx) / 2];
                  }
                }
              }
            }
          }
        }
        m_picBg->setBorderExtension(false);
        m_picBg->extendPicBorder();
        m_picBg->setBorderExtension(true);
    
        curPic->extendPicBorder();
        curPic->setBorderExtension(true);
        m_picOrig->getOrigBuf().copyFrom(curPic->getOrigBuf());
    
        m_picBg->setBorderExtension(false);
        m_picBg->extendPicBorder();
        m_picBg->setBorderExtension(true);
      }
    }
    
    
    void EncGOP::applyDeblockingFilterMetric( Picture* pcPic, uint32_t uiNumSlices )
    {
      PelBuf cPelBuf = pcPic->getRecoBuf().get( COMPONENT_Y );
      Pel* Rec    = cPelBuf.buf;
      const int  stride = cPelBuf.stride;
      const uint32_t picWidth = cPelBuf.width;
      const uint32_t picHeight = cPelBuf.height;
    
      Pel* tempRec = Rec;
      const Slice* pcSlice = pcPic->slices[0];
    
    #if MAX_TB_SIZE_SIGNALLING
      const uint32_t log2maxTB = pcSlice->getSPS()->getLog2MaxTbSize();
    #else
      const uint32_t log2maxTB = MAX_TB_LOG2_SIZEY;
    #endif
      const uint32_t maxTBsize = (1<<log2maxTB);
    
      const uint32_t minBlockArtSize = 8;
      const uint32_t noCol = (picWidth>>log2maxTB);
      const uint32_t noRows = (picHeight>>log2maxTB);
      CHECK(!(noCol > 1), "Unspecified error");
      CHECK(!(noRows > 1), "Unspecified error");
      std::vector<uint64_t> colSAD(noCol,  uint64_t(0));
      std::vector<uint64_t> rowSAD(noRows, uint64_t(0));
      uint32_t colIdx = 0;
      uint32_t rowIdx = 0;
      Pel p0, p1, p2, q0, q1, q2;
    
      int qp = pcSlice->getSliceQp();
      const int bitDepthLuma=pcSlice->getSPS()->getBitDepth(CHANNEL_TYPE_LUMA);
      int bitdepthScale = 1 << (bitDepthLuma-8);
      int beta = LoopFilter::getBeta( qp ) * bitdepthScale;
      const int thr2 = (beta>>2);
      const int thr1 = 2*bitdepthScale;
      uint32_t a = 0;
    
      if (maxTBsize > minBlockArtSize)
      {
        // Analyze vertical artifact edges
        for(int c = maxTBsize; c < picWidth; c += maxTBsize)
        {
          for(int r = 0; r < picHeight; r++)
          {
            p2 = Rec[c-3];
            p1 = Rec[c-2];
            p0 = Rec[c-1];
            q0 = Rec[c];
            q1 = Rec[c+1];
            q2 = Rec[c+2];
            a = ((abs(p2-(p1<<1)+p0)+abs(q0-(q1<<1)+q2))<<1);
            if ( thr1 < a && a < thr2)
            {
              colSAD[colIdx] += abs(p0 - q0);
            }
            Rec += stride;
          }
          colIdx++;
          Rec = tempRec;
        }
    
        // Analyze horizontal artifact edges
        for(int r = maxTBsize; r < picHeight; r += maxTBsize)
        {
          for(int c = 0; c < picWidth; c++)
          {
            p2 = Rec[c + (r-3)*stride];
            p1 = Rec[c + (r-2)*stride];
            p0 = Rec[c + (r-1)*stride];
            q0 = Rec[c + r*stride];
            q1 = Rec[c + (r+1)*stride];
            q2 = Rec[c + (r+2)*stride];
            a = ((abs(p2-(p1<<1)+p0)+abs(q0-(q1<<1)+q2))<<1);
            if (thr1 < a && a < thr2)
            {
              rowSAD[rowIdx] += abs(p0 - q0);
            }
          }
          rowIdx++;
        }
      }
    
      uint64_t colSADsum = 0;
      uint64_t rowSADsum = 0;
      for(int c = 0; c < noCol-1; c++)
      {
        colSADsum += colSAD[c];
      }
      for(int r = 0; r < noRows-1; r++)
      {
        rowSADsum += rowSAD[r];
      }
    
      colSADsum <<= 10;
      rowSADsum <<= 10;
      colSADsum /= (noCol-1);
      colSADsum /= picHeight;
      rowSADsum /= (noRows-1);
      rowSADsum /= picWidth;
    
      uint64_t avgSAD = ((colSADsum + rowSADsum)>>1);
      avgSAD >>= (bitDepthLuma-8);
    
      if ( avgSAD > 2048 )
      {
        avgSAD >>= 9;
        int offset = Clip3(2,6,(int)avgSAD);
        for (int i=0; i<uiNumSlices; i++)
        {
          Slice* pcLocalSlice = pcPic->slices[i];
          pcLocalSlice->setDeblockingFilterOverrideFlag   ( true);
          pcLocalSlice->setDeblockingFilterDisable        ( false);
          pcLocalSlice->setDeblockingFilterBetaOffsetDiv2 ( offset );
          pcLocalSlice->setDeblockingFilterTcOffsetDiv2   ( offset );
        }
      }
      else
      {
        for (int i=0; i<uiNumSlices; i++)
        {
          Slice* pcLocalSlice = pcPic->slices[i];
          const PPS* pcPPS = pcSlice->getPPS();
          pcLocalSlice->setDeblockingFilterOverrideFlag  ( false);
          pcLocalSlice->setDeblockingFilterDisable       ( pcPPS->getPPSDeblockingFilterDisabledFlag() );
          pcLocalSlice->setDeblockingFilterBetaOffsetDiv2( pcPPS->getDeblockingFilterBetaOffsetDiv2() );
          pcLocalSlice->setDeblockingFilterTcOffsetDiv2  ( pcPPS->getDeblockingFilterTcOffsetDiv2()   );
        }
      }
    }
    
    #if W0038_DB_OPT
    void EncGOP::applyDeblockingFilterParameterSelection( Picture* pcPic, const uint32_t numSlices, const int gopID )
    {
      enum DBFltParam
      {
        DBFLT_PARAM_AVAILABLE = 0,
        DBFLT_DISABLE_FLAG,
        DBFLT_BETA_OFFSETD2,
        DBFLT_TC_OFFSETD2,
        //NUM_DBFLT_PARAMS
      };
      const int MAX_BETA_OFFSET = 3;
      const int MIN_BETA_OFFSET = -3;
      const int MAX_TC_OFFSET = 3;
      const int MIN_TC_OFFSET = -3;
    
      PelUnitBuf reco = pcPic->getRecoBuf();
    
    
      const int currQualityLayer = (!pcPic->slices[0]->isIRAP()) ? m_pcCfg->getGOPEntry(gopID).m_temporalId+1 : 0;
    
      CHECK(!(currQualityLayer <MAX_ENCODER_DEBLOCKING_QUALITY_LAYERS), "Unspecified error");
    
      CodingStructure& cs = *pcPic->cs;
    
      if(!m_pcDeblockingTempPicYuv)
      {
        m_pcDeblockingTempPicYuv = new PelStorage;
        m_pcDeblockingTempPicYuv->create( cs.area );
        memset(m_DBParam, 0, sizeof(m_DBParam));
      }
    
      //preserve current reconstruction
      m_pcDeblockingTempPicYuv->copyFrom ( reco );
    
      const bool bNoFiltering      = m_DBParam[currQualityLayer][DBFLT_PARAM_AVAILABLE] && m_DBParam[currQualityLayer][DBFLT_DISABLE_FLAG]==false /*&& pcPic->getTLayer()==0*/;
      const int  maxBetaOffsetDiv2 = bNoFiltering? Clip3(MIN_BETA_OFFSET, MAX_BETA_OFFSET, m_DBParam[currQualityLayer][DBFLT_BETA_OFFSETD2]+1) : MAX_BETA_OFFSET;
      const int  minBetaOffsetDiv2 = bNoFiltering? Clip3(MIN_BETA_OFFSET, MAX_BETA_OFFSET, m_DBParam[currQualityLayer][DBFLT_BETA_OFFSETD2]-1) : MIN_BETA_OFFSET;
      const int  maxTcOffsetDiv2   = bNoFiltering? Clip3(MIN_TC_OFFSET, MAX_TC_OFFSET, m_DBParam[currQualityLayer][DBFLT_TC_OFFSETD2]+2)       : MAX_TC_OFFSET;
      const int  minTcOffsetDiv2   = bNoFiltering? Clip3(MIN_TC_OFFSET, MAX_TC_OFFSET, m_DBParam[currQualityLayer][DBFLT_TC_OFFSETD2]-2)       : MIN_TC_OFFSET;
    
      uint64_t distBetaPrevious      = std::numeric_limits<uint64_t>::max();
      uint64_t distMin               = std::numeric_limits<uint64_t>::max();
      bool   bDBFilterDisabledBest = true;
      int    betaOffsetDiv2Best    = 0;
      int    tcOffsetDiv2Best      = 0;
    
      for(int betaOffsetDiv2=maxBetaOffsetDiv2; betaOffsetDiv2>=minBetaOffsetDiv2; betaOffsetDiv2--)
      {
        uint64_t distTcMin = std::numeric_limits<uint64_t>::max();
        for(int tcOffsetDiv2=maxTcOffsetDiv2; tcOffsetDiv2 >= minTcOffsetDiv2; tcOffsetDiv2--)
        {
          for (int i=0; i<numSlices; i++)
          {
            Slice* pcSlice = pcPic->slices[i];
            pcSlice->setDeblockingFilterOverrideFlag  ( true);
            pcSlice->setDeblockingFilterDisable       ( false);
            pcSlice->setDeblockingFilterBetaOffsetDiv2( betaOffsetDiv2 );
            pcSlice->setDeblockingFilterTcOffsetDiv2  ( tcOffsetDiv2 );
          }
    
          // restore reconstruction
          reco.copyFrom( *m_pcDeblockingTempPicYuv );
    
          const uint64_t dist = preLoopFilterPicAndCalcDist( pcPic );
    
          if(dist < distMin)
          {
            distMin = dist;
            bDBFilterDisabledBest = false;
            betaOffsetDiv2Best  = betaOffsetDiv2;
            tcOffsetDiv2Best = tcOffsetDiv2;
          }
          if(dist < distTcMin)
          {
            distTcMin = dist;
          }
          else if(tcOffsetDiv2 <-2)
          {
            break;
          }
        }
        if(betaOffsetDiv2<-1 && distTcMin >= distBetaPrevious)
        {
          break;
        }
        distBetaPrevious = distTcMin;
      }
    
      //update:
      m_DBParam[currQualityLayer][DBFLT_PARAM_AVAILABLE] = 1;
      m_DBParam[currQualityLayer][DBFLT_DISABLE_FLAG]    = bDBFilterDisabledBest;
      m_DBParam[currQualityLayer][DBFLT_BETA_OFFSETD2]   = betaOffsetDiv2Best;
      m_DBParam[currQualityLayer][DBFLT_TC_OFFSETD2]     = tcOffsetDiv2Best;
    
      // restore reconstruction
      reco.copyFrom( *m_pcDeblockingTempPicYuv );
    
      const PPS* pcPPS = pcPic->slices[0]->getPPS();
      if(bDBFilterDisabledBest)
      {
        for (int i=0; i<numSlices; i++)
        {
          Slice* pcSlice = pcPic->slices[i];
          pcSlice->setDeblockingFilterOverrideFlag( true);
          pcSlice->setDeblockingFilterDisable     ( true);
        }
      }
      else if(betaOffsetDiv2Best == pcPPS->getDeblockingFilterBetaOffsetDiv2() &&  tcOffsetDiv2Best == pcPPS->getDeblockingFilterTcOffsetDiv2())
      {
        for (int i=0; i<numSlices; i++)
        {
          Slice*      pcSlice = pcPic->slices[i];
          pcSlice->setDeblockingFilterOverrideFlag   ( false);
          pcSlice->setDeblockingFilterDisable        ( pcPPS->getPPSDeblockingFilterDisabledFlag() );
          pcSlice->setDeblockingFilterBetaOffsetDiv2 ( pcPPS->getDeblockingFilterBetaOffsetDiv2() );
          pcSlice->setDeblockingFilterTcOffsetDiv2   ( pcPPS->getDeblockingFilterTcOffsetDiv2()   );
        }
      }
      else
      {
        for (int i=0; i<numSlices; i++)
        {
          Slice* pcSlice = pcPic->slices[i];
          pcSlice->setDeblockingFilterOverrideFlag   ( true);
          pcSlice->setDeblockingFilterDisable        ( false );
          pcSlice->setDeblockingFilterBetaOffsetDiv2 ( betaOffsetDiv2Best);
          pcSlice->setDeblockingFilterTcOffsetDiv2   ( tcOffsetDiv2Best);
        }
      }
    }
    #endif
    //! \}