Skip to content
Snippets Groups Projects
Picture.cpp 65.5 KiB
Newer Older
  • Learn to ignore specific revisions
  •   if (m_spliceIdx == NULL)
      {
        m_ctuNums = cs->pcv->sizeInCtus;
        m_spliceIdx = new int[m_ctuNums];
        memset(m_spliceIdx, 0, m_ctuNums * sizeof(int));
      }
    
    }
    
    void Picture::allocateNewSlice()
    {
      slices.push_back(new Slice);
      Slice& slice = *slices.back();
    
      memcpy(slice.getAlfAPSs(), cs->alfApss, sizeof(cs->alfApss));
    
      slice.setLmcsAPS(cs->lmcsAps);
    
      slice.setscalingListAPS( cs->scalinglistAps );
    
      slice.setPPS( cs->pps);
      slice.setSPS( cs->sps);
      if(slices.size()>=2)
      {
        slice.copySliceInfo( slices[slices.size()-2] );
        slice.initSlice();
      }
    }
    
    Slice *Picture::swapSliceObject(Slice * p, uint32_t i)
    {
      p->setSPS(cs->sps);
      p->setPPS(cs->pps);
    
      p->setAlfAPSs(cs->alfApss);
    
      if(cs->lmcsAps != nullptr)
        p->setLmcsAPS(cs->lmcsAps);
      if(cs->scalinglistAps != nullptr)
        p->setscalingListAPS( cs->scalinglistAps );
    
      Slice * pTmp = slices[i];
      slices[i] = p;
      pTmp->setSPS(0);
      pTmp->setPPS(0);
    
      memset(pTmp->getAlfAPSs(), 0, sizeof(*pTmp->getAlfAPSs())*ALF_CTB_MAX_NUM_APS);
    
      return pTmp;
    }
    
    void Picture::clearSliceBuffer()
    {
      for (uint32_t i = 0; i < uint32_t(slices.size()); i++)
      {
        delete slices[i];
      }
      slices.clear();
    }
    
    #if ENABLE_SPLIT_PARALLELISM
    
    void Picture::finishParallelPart( const UnitArea& area )
    {
      const UnitArea clipdArea = clipArea( area, *this );
      const int      sourceID  = scheduler.getSplitPicId( 0 );
      CHECK( scheduler.getSplitJobId() > 0, "Finish-CU cannot be called from within a mode- or split-parallelized block!" );
    
      // distribute the reconstruction across all of the parallel workers
      for( int tId = 1; tId < scheduler.getNumSplitThreads(); tId++ )
      {
        const int destID = scheduler.getSplitPicId( tId );
    
        M_BUFS( destID, PIC_RECONSTRUCTION ).subBuf( clipdArea ).copyFrom( M_BUFS( sourceID, PIC_RECONSTRUCTION ).subBuf( clipdArea ) );
      }
    }
    
    #if ENABLE_WPP_PARALLELISM
    void Picture::finishCtuPart( const UnitArea& ctuArea )
    {
      const UnitArea clipdArea = clipArea( ctuArea, *this );
      const int      sourceID  = scheduler.getSplitPicId( 0 );
      // distribute the reconstruction across all of the parallel workers
      for( int dataId = 0; dataId < scheduler.getNumPicInstances(); dataId++ )
      {
        if( dataId == sourceID ) continue;
    
        M_BUFS( dataId, PIC_RECONSTRUCTION ).subBuf( clipdArea ).copyFrom( M_BUFS( sourceID, PIC_RECONSTRUCTION ).subBuf( clipdArea ) );
      }
    }
    #endif
    
    #endif
    
    
    const TFilterCoeff DownsamplingFilterSRC[8][16][12] =
    
        { // D = 1
          {   0,   0,   0,   0,   0, 128,   0,   0,   0,   0,   0,   0 },
          {   0,   0,   0,   2,  -6, 127,   7,  -2,   0,   0,   0,   0 },
          {   0,   0,   0,   3, -12, 125,  16,  -5,   1,   0,   0,   0 },
          {   0,   0,   0,   4, -16, 120,  26,  -7,   1,   0,   0,   0 },
          {   0,   0,   0,   5, -18, 114,  36, -10,   1,   0,   0,   0 },
          {   0,   0,   0,   5, -20, 107,  46, -12,   2,   0,   0,   0 },
          {   0,   0,   0,   5, -21,  99,  57, -15,   3,   0,   0,   0 },
          {   0,   0,   0,   5, -20,  89,  68, -18,   4,   0,   0,   0 },
          {   0,   0,   0,   4, -19,  79,  79, -19,   4,   0,   0,   0 },
          {   0,   0,   0,   4, -18,  68,  89, -20,   5,   0,   0,   0 },
          {   0,   0,   0,   3, -15,  57,  99, -21,   5,   0,   0,   0 },
          {   0,   0,   0,   2, -12,  46, 107, -20,   5,   0,   0,   0 },
          {   0,   0,   0,   1, -10,  36, 114, -18,   5,   0,   0,   0 },
          {   0,   0,   0,   1,  -7,  26, 120, -16,   4,   0,   0,   0 },
          {   0,   0,   0,   1,  -5,  16, 125, -12,   3,   0,   0,   0 },
          {   0,   0,   0,   0,  -2,   7, 127,  -6,   2,   0,   0,   0 }
        },
        { // D = 1.5
          {   0,   2,   0, -14,  33,  86,  33, -14,   0,   2,   0,   0 },
          {   0,   1,   1, -14,  29,  85,  38, -13,  -1,   2,   0,   0 },
          {   0,   1,   2, -14,  24,  84,  43, -12,  -2,   2,   0,   0 },
          {   0,   1,   2, -13,  19,  83,  48, -11,  -3,   2,   0,   0 },
          {   0,   0,   3, -13,  15,  81,  53, -10,  -4,   3,   0,   0 },
          {   0,   0,   3, -12,  11,  79,  57,  -8,  -5,   3,   0,   0 },
          {   0,   0,   3, -11,   7,  76,  62,  -5,  -7,   3,   0,   0 },
          {   0,   0,   3, -10,   3,  73,  65,  -2,  -7,   3,   0,   0 },
          {   0,   0,   3,  -9,   0,  70,  70,   0,  -9,   3,   0,   0 },
          {   0,   0,   3,  -7,  -2,  65,  73,   3, -10,   3,   0,   0 },
          {   0,   0,   3,  -7,  -5,  62,  76,   7, -11,   3,   0,   0 },
          {   0,   0,   3,  -5,  -8,  57,  79,  11, -12,   3,   0,   0 },
          {   0,   0,   3,  -4, -10,  53,  81,  15, -13,   3,   0,   0 },
          {   0,   0,   2,  -3, -11,  48,  83,  19, -13,   2,   1,   0 },
          {   0,   0,   2,  -2, -12,  43,  84,  24, -14,   2,   1,   0 },
          {   0,   0,   2,  -1, -13,  38,  85,  29, -14,   1,   1,   0 }
        },
        { // D = 2
    
          {   0,   5,   -6,  -10,  37,  76,   37,  -10,  -6,    5,  0,   0}, //0
          {   0,   5,   -4,  -11,  33,  76,   40,  -9,    -7,    5,  0,   0}, //1
          //{   0,   5,   -3,  -12,  28,  75,   44,  -7,    -8,    5,  1,   0}, //2
          {  -1,   5,   -3,  -12,  29,  75,   45,  -7,    -8,   5,  0,   0}, //2 new coefficients in m24499
          {  -1,   4,   -2,  -13,  25,  75,   48,  -5,    -9,    5,  1,   0}, //3
          {  -1,   4,   -1,  -13,  22,  73,   52,  -3,    -10,  4,  1,   0}, //4
          {  -1,   4,   0,    -13,  18,  72,   55,  -1,    -11,  4,  2,  -1}, //5
          {  -1,   4,   1,    -13,  14,  70,   59,  2,    -12,  3,  2,  -1}, //6
          {  -1,   3,   1,    -13,  11,  68,   62,  5,    -12,  3,  2,  -1}, //7
          {  -1,   3,   2,    -13,  8,  65,   65,  8,    -13,  2,  3,  -1}, //8
          {  -1,   2,   3,    -12,  5,  62,   68,  11,    -13,  1,  3,  -1}, //9
          {  -1,   2,   3,    -12,  2,  59,   70,  14,    -13,  1,  4,  -1}, //10
          {  -1,   2,   4,    -11,  -1,  55,   72,  18,    -13,  0,  4,  -1}, //11
          {   0,   1,   4,    -10,  -3,  52,   73,  22,    -13,  -1,  4,  -1}, //12
          {   0,   1,   5,    -9,    -5,  48,   75,  25,    -13,  -2,  4,  -1}, //13
          //{   0,   1,   5,    -8,    -7,  44,   75,  28,    -12,  -3,  5,   0}, //14
    
          {    0,   0,   5,    -8,   -7,  45,   75,  29,    -12,  -3,  5,  -1}  , //14 new coefficients in m24499
    
          {   0,   0,   5,    -7,    -9,  40,   76,  33,    -11,  -4,  5,   0}, //15
    
        },
        { // D = 2.5
          {   2,  -3,   -9,  6,   39,  58,   39,  6,   -9,  -3,    2,    0}, // 0
          {   2,  -3,   -9,  4,   38,  58,   43,  7,   -9,  -4,    1,    0}, // 1
          {   2,  -2,   -9,  2,   35,  58,   44,  9,   -8,  -4,    1,    0}, // 2
          {   1,  -2,   -9,  1,   34,  58,   46,  11,   -8,  -5,    1,    0}, // 3
          //{   1,  -1,   -8,  -1,   31,  57,   48,  13,   -8,  -5,    1,    0}, // 4
    
          {   1,  -1,   -8,  -1,   31,  57,   47,  13,   -7,  -5,    1,    0},  // 4 new coefficients in m24499
    
          {   1,  -1,   -8,  -2,   29,  56,   49,  15,   -7,  -6,    1,    1}, // 5
          {   1,  0,   -8,  -3,   26,  55,   51,  17,   -7,  -6,    1,    1}, // 6
          {   1,  0,   -7,  -4,   24,  54,   52,  19,   -6,  -7,    1,    1}, // 7
          {   1,  0,   -7,  -5,   22,  53,   53,  22,   -5,  -7,    0,    1}, // 8
          {   1,  1,   -7,  -6,   19,  52,   54,  24,   -4,  -7,    0,    1}, // 9
          {   1,  1,   -6,  -7,   17,  51,   55,  26,   -3,  -8,    0,    1}, // 10
          {   1,  1,   -6,  -7,   15,  49,   56,  29,   -2,  -8,    -1,    1}, // 11
          //{   0,  1,   -5,  -8,   13,  48,   57,  31,   -1,  -8,    -1,    1}, // 12 new coefficients in m24499
    
          {   0,  1,   -5,  -7,   13,  47,  57,  31,  -1,    -8,   -1,    1}, // 12
    
          {   0,  1,   -5,  -8,   11,  46,   58,  34,   1,    -9,    -2,    1}, // 13
          {   0,  1,   -4,  -8,   9,    44,   58,  35,   2,    -9,    -2,    2}, // 14
          {   0,  1,   -4,  -9,   7,    43,   58,  38,   4,    -9,    -3,    2}, // 15
        },
        { // D = 3
          {  -2,  -7,   0,  17,  35,  43,  35,  17,   0,  -7,  -5,   2 },
          {  -2,  -7,  -1,  16,  34,  43,  36,  18,   1,  -7,  -5,   2 },
          {  -1,  -7,  -1,  14,  33,  43,  36,  19,   1,  -6,  -5,   2 },
          {  -1,  -7,  -2,  13,  32,  42,  37,  20,   3,  -6,  -5,   2 },
          {   0,  -7,  -3,  12,  31,  42,  38,  21,   3,  -6,  -5,   2 },
          {   0,  -7,  -3,  11,  30,  42,  39,  23,   4,  -6,  -6,   1 },
          {   0,  -7,  -4,  10,  29,  42,  40,  24,   5,  -6,  -6,   1 },
          {   1,  -7,  -4,   9,  27,  41,  40,  25,   6,  -5,  -6,   1 },
          {   1,  -6,  -5,   7,  26,  41,  41,  26,   7,  -5,  -6,   1 },
          {   1,  -6,  -5,   6,  25,  40,  41,  27,   9,  -4,  -7,   1 },
          {   1,  -6,  -6,   5,  24,  40,  42,  29,  10,  -4,  -7,   0 },
          {   1,  -6,  -6,   4,  23,  39,  42,  30,  11,  -3,  -7,   0 },
          {   2,  -5,  -6,   3,  21,  38,  42,  31,  12,  -3,  -7,   0 },
          {   2,  -5,  -6,   3,  20,  37,  42,  32,  13,  -2,  -7,  -1 },
          {   2,  -5,  -6,   1,  19,  36,  43,  33,  14,  -1,  -7,  -1 },
          {   2,  -5,  -7,   1,  18,  36,  43,  34,  16,  -1,  -7,  -2 }
        },
        { // D = 3.5
          {  -6,  -3,   5,  19,  31,  36,  31,  19,   5,  -3,  -6,   0 },
          {  -6,  -4,   4,  18,  31,  37,  32,  20,   6,  -3,  -6,  -1 },
          {  -6,  -4,   4,  17,  30,  36,  33,  21,   7,  -3,  -6,  -1 },
          {  -5,  -5,   3,  16,  30,  36,  33,  22,   8,  -2,  -6,  -2 },
          {  -5,  -5,   2,  15,  29,  36,  34,  23,   9,  -2,  -6,  -2 },
          {  -5,  -5,   2,  15,  28,  36,  34,  24,  10,  -2,  -6,  -3 },
          {  -4,  -5,   1,  14,  27,  36,  35,  24,  10,  -1,  -6,  -3 },
          {  -4,  -5,   0,  13,  26,  35,  35,  25,  11,   0,  -5,  -3 },
          {  -4,  -6,   0,  12,  26,  36,  36,  26,  12,   0,  -6,  -4 },
          {  -3,  -5,   0,  11,  25,  35,  35,  26,  13,   0,  -5,  -4 },
          {  -3,  -6,  -1,  10,  24,  35,  36,  27,  14,   1,  -5,  -4 },
          {  -3,  -6,  -2,  10,  24,  34,  36,  28,  15,   2,  -5,  -5 },
          {  -2,  -6,  -2,   9,  23,  34,  36,  29,  15,   2,  -5,  -5 },
          {  -2,  -6,  -2,   8,  22,  33,  36,  30,  16,   3,  -5,  -5 },
          {  -1,  -6,  -3,   7,  21,  33,  36,  30,  17,   4,  -4,  -6 },
          {  -1,  -6,  -3,   6,  20,  32,  37,  31,  18,   4,  -4,  -6 }
        },
        { // D = 4
          {  -9,   0,   9,  20,  28,  32,  28,  20,   9,   0,  -9,   0 },
          {  -9,   0,   8,  19,  28,  32,  29,  20,  10,   0,  -4,  -5 },
          {  -9,  -1,   8,  18,  28,  32,  29,  21,  10,   1,  -4,  -5 },
          {  -9,  -1,   7,  18,  27,  32,  30,  22,  11,   1,  -4,  -6 },
          {  -8,  -2,   6,  17,  27,  32,  30,  22,  12,   2,  -4,  -6 },
          {  -8,  -2,   6,  16,  26,  32,  31,  23,  12,   2,  -4,  -6 },
          {  -8,  -2,   5,  16,  26,  31,  31,  23,  13,   3,  -3,  -7 },
          {  -8,  -3,   5,  15,  25,  31,  31,  24,  14,   4,  -3,  -7 },
          {  -7,  -3,   4,  14,  25,  31,  31,  25,  14,   4,  -3,  -7 },
          {  -7,  -3,   4,  14,  24,  31,  31,  25,  15,   5,  -3,  -8 },
          {  -7,  -3,   3,  13,  23,  31,  31,  26,  16,   5,  -2,  -8 },
          {  -6,  -4,   2,  12,  23,  31,  32,  26,  16,   6,  -2,  -8 },
          {  -6,  -4,   2,  12,  22,  30,  32,  27,  17,   6,  -2,  -8 },
          {  -6,  -4,   1,  11,  22,  30,  32,  27,  18,   7,  -1,  -9 },
          {  -5,  -4,   1,  10,  21,  29,  32,  28,  18,   8,  -1,  -9 },
          {  -5,  -4,   0,  10,  20,  29,  32,  28,  19,   8,   0,  -9 }
        },
        { // D = 5.5
          {  -8,   7,  13,  18,  22,  24,  22,  18,  13,   7,   2, -10 },
          {  -8,   7,  13,  18,  22,  23,  22,  19,  13,   7,   2, -10 },
          {  -8,   6,  12,  18,  22,  23,  22,  19,  14,   8,   2, -10 },
          {  -9,   6,  12,  17,  22,  23,  23,  19,  14,   8,   3, -10 },
          {  -9,   6,  12,  17,  21,  23,  23,  19,  14,   9,   3, -10 },
          {  -9,   5,  11,  17,  21,  23,  23,  20,  15,   9,   3, -10 },
          {  -9,   5,  11,  16,  21,  23,  23,  20,  15,   9,   4, -10 },
          {  -9,   5,  10,  16,  21,  23,  23,  20,  15,  10,   4, -10 },
          { -10,   5,  10,  16,  20,  23,  23,  20,  16,  10,   5, -10 },
          { -10,   4,  10,  15,  20,  23,  23,  21,  16,  10,   5,  -9 },
          { -10,   4,   9,  15,  20,  23,  23,  21,  16,  11,   5,  -9 },
          { -10,   3,   9,  15,  20,  23,  23,  21,  17,  11,   5,  -9 },
          { -10,   3,   9,  14,  19,  23,  23,  21,  17,  12,   6,  -9 },
          { -10,   3,   8,  14,  19,  23,  23,  22,  17,  12,   6,  -9 },
          { -10,   2,   8,  14,  19,  22,  23,  22,  18,  12,   6,  -8 },
          { -10,   2,   7,  13,  19,  22,  23,  22,  18,  13,   7,  -8 }
        }
    
    #if JVET_P0590_SCALING_WINDOW
    #if JVET_P0592_CHROMA_PHASE
    void Picture::sampleRateConv( const std::pair<int, int> scalingRatio, const std::pair<int, int> compScale,
                                  const CPelBuf& beforeScale, const int beforeScaleLeftOffset, const int beforeScaleTopOffset,
                                  const PelBuf& afterScale, const int afterScaleLeftOffset, const int afterScaleTopOffset,
                                  const int bitDepth, const bool useLumaFilter, const bool downsampling,
                                  const bool horCollocatedPositionFlag, const bool verCollocatedPositionFlag )
    #else
    void Picture::sampleRateConv( const std::pair<int, int> scalingRatio,
                                  const CPelBuf& beforeScale, const int beforeScaleLeftOffset, const int beforeScaleTopOffset,
                                  const PelBuf& afterScale, const int afterScaleLeftOffset, const int afterScaleTopOffset,
                                  const int bitDepth, const bool useLumaFilter, const bool downsampling )
    #endif
    {
      const Pel* orgSrc = beforeScale.buf;
      const int orgWidth = beforeScale.width;
      const int orgHeight = beforeScale.height;
      const int orgStride = beforeScale.stride;
    
      Pel* scaledSrc = afterScale.buf;
      const int scaledWidth = afterScale.width;
      const int scaledHeight = afterScale.height;
      const int scaledStride = afterScale.stride;
    
      if( orgWidth == scaledWidth && orgHeight == scaledHeight && scalingRatio == SCALE_1X && !beforeScaleLeftOffset && !beforeScaleTopOffset && !afterScaleLeftOffset && !afterScaleTopOffset )
      {
        for( int j = 0; j < orgHeight; j++ )
        {
          memcpy( scaledSrc + j * scaledStride, orgSrc + j * orgStride, sizeof( Pel ) * orgWidth );
        }
    
        return;
      }
    
      const TFilterCoeff* filterHor = useLumaFilter ? &InterpolationFilter::m_lumaFilter[0][0] : &InterpolationFilter::m_chromaFilter[0][0];
      const TFilterCoeff* filterVer = useLumaFilter ? &InterpolationFilter::m_lumaFilter[0][0] : &InterpolationFilter::m_chromaFilter[0][0];
      const int numFracPositions = useLumaFilter ? 15 : 31;
      const int numFracShift = useLumaFilter ? 4 : 5;
      const int posShift = SCALE_RATIO_BITS - numFracShift;
    #if JVET_P0592_CHROMA_PHASE
      int addX = ( 1 << ( posShift - 1 ) ) + ( beforeScaleLeftOffset << posShift ) + ( ( int( 1 - horCollocatedPositionFlag ) * 8 * ( scalingRatio.first - SCALE_1X.first ) + ( 1 << ( 3 + compScale.first ) ) ) >> ( 4 + compScale.first ) );
      int addY = ( 1 << ( posShift - 1 ) ) + ( beforeScaleTopOffset << posShift ) + ( ( int( 1 - verCollocatedPositionFlag ) * 8 * ( scalingRatio.second - SCALE_1X.second ) + ( 1 << ( 3 + compScale.second ) ) ) >> ( 4 + compScale.second ) );
    #else
      int addX = ( 1 << ( posShift - 1 ) ) + ( beforeScaleLeftOffset << posShift );
      int addY = ( 1 << ( posShift - 1 ) ) + ( beforeScaleTopOffset << posShift );
    #endif
    
      if( downsampling )
      {
        int verFilter = 0;
        int horFilter = 0;
    
        if( scalingRatio.first > ( 15 << SCALE_RATIO_BITS ) / 4 )   horFilter = 7;
        else if( scalingRatio.first > ( 20 << SCALE_RATIO_BITS ) / 7 )   horFilter = 6;
        else if( scalingRatio.first > ( 5 << SCALE_RATIO_BITS ) / 2 )   horFilter = 5;
        else if( scalingRatio.first > ( 2 << SCALE_RATIO_BITS ) )   horFilter = 4;
        else if( scalingRatio.first > ( 5 << SCALE_RATIO_BITS ) / 3 )   horFilter = 3;
        else if( scalingRatio.first > ( 5 << SCALE_RATIO_BITS ) / 4 )   horFilter = 2;
        else if( scalingRatio.first > ( 20 << SCALE_RATIO_BITS ) / 19 )   horFilter = 1;
    
        if( scalingRatio.second > ( 15 << SCALE_RATIO_BITS ) / 4 )   verFilter = 7;
        else if( scalingRatio.second > ( 20 << SCALE_RATIO_BITS ) / 7 )   verFilter = 6;
        else if( scalingRatio.second > ( 5 << SCALE_RATIO_BITS ) / 2 )   verFilter = 5;
        else if( scalingRatio.second > ( 2 << SCALE_RATIO_BITS ) )   verFilter = 4;
        else if( scalingRatio.second > ( 5 << SCALE_RATIO_BITS ) / 3 )   verFilter = 3;
        else if( scalingRatio.second > ( 5 << SCALE_RATIO_BITS ) / 4 )   verFilter = 2;
        else if( scalingRatio.second > ( 20 << SCALE_RATIO_BITS ) / 19 )   verFilter = 1;
    
        filterHor = &DownsamplingFilterSRC[horFilter][0][0];
        filterVer = &DownsamplingFilterSRC[verFilter][0][0];
      }
    
      const int filterLength = downsampling ? 12 : ( useLumaFilter ? NTAPS_LUMA : NTAPS_CHROMA );
      const int log2Norm = downsampling ? 14 : 12;
    
      int *buf = new int[orgHeight * scaledWidth];
      int maxVal = ( 1 << bitDepth ) - 1;
    
      CHECK( bitDepth > 17, "Overflow may happen!" );
    
      for( int i = 0; i < scaledWidth; i++ )
      {
        const Pel* org = orgSrc;
        int refPos = ( ( i - afterScaleLeftOffset ) * scalingRatio.first + addX ) >> posShift;
        int integer = refPos >> numFracShift;
        int frac = refPos & numFracPositions;
        int* tmp = buf + i;
    
        for( int j = 0; j < orgHeight; j++ )
        {
          int sum = 0;
          const TFilterCoeff* f = filterHor + frac * filterLength;
    
          for( int k = 0; k < filterLength; k++ )
          {
            int xInt = std::min<int>( std::max( 0, integer + k - filterLength / 2 + 1 ), orgWidth - 1 );
            sum += f[k] * org[xInt]; // postpone horizontal filtering gain removal after vertical filtering
          }
    
          *tmp = sum;
    
          tmp += scaledWidth;
          org += orgStride;
        }
      }
    
      Pel* dst = scaledSrc;
    
      for( int j = 0; j < scaledHeight; j++ )
      {
        int refPos = ( ( j - afterScaleTopOffset ) * scalingRatio.second + addY ) >> posShift;
        int integer = refPos >> numFracShift;
        int frac = refPos & numFracPositions;
    
        for( int i = 0; i < scaledWidth; i++ )
        {
          int sum = 0;
          int* tmp = buf + i;
          const TFilterCoeff* f = filterVer + frac * filterLength;
    
          for( int k = 0; k < filterLength; k++ )
          {
            int yInt = std::min<int>( std::max( 0, integer + k - filterLength / 2 + 1 ), orgHeight - 1 );
            sum += f[k] * tmp[yInt*scaledWidth];
          }
    
          dst[i] = std::min<int>( std::max( 0, ( sum + ( 1 << ( log2Norm - 1 ) ) ) >> log2Norm ), maxVal );
        }
    
        dst += scaledStride;
      }
    
      delete[] buf;
    }
    #else
    #if JVET_P0592_CHROMA_PHASE
    void Picture::sampleRateConv( const std::pair<int, int> scalingRatio, const std::pair<int, int> compScale,
                                  const Pel* orgSrc, SizeType orgWidth, SizeType orgHeight, SizeType orgStride,
                                  Pel* scaledSrc, SizeType scaledWidth, SizeType scaledHeight,
                                  SizeType paddedWidth, SizeType paddedHeight, SizeType scaledStride,
                                  const int bitDepth, const bool useLumaFilter, const bool downsampling,
                                  const bool horCollocatedPositionFlag, const bool verCollocatedPositionFlag )
    #else
    
    void Picture::sampleRateConv( const Pel* orgSrc, SizeType orgWidth, SizeType orgHeight, SizeType orgStride, Pel* scaledSrc, SizeType scaledWidth, SizeType scaledHeight, SizeType paddedWidth, SizeType paddedHeight, SizeType scaledStride, const int bitDepth, const bool useLumaFilter, const bool downsampling )
    
    {
      if( orgWidth == scaledWidth && orgHeight == scaledHeight )
      {
        for( int j = 0; j < orgHeight; j++ )
        {
          memcpy( scaledSrc + j * scaledStride, orgSrc + j * orgStride, sizeof( Pel ) * orgWidth );
        }
    
        return;
      }
    
    
      const TFilterCoeff* filterHor = useLumaFilter ? &InterpolationFilter::m_lumaFilter[0][0] : &InterpolationFilter::m_chromaFilter[0][0];
      const TFilterCoeff* filterVer = useLumaFilter ? &InterpolationFilter::m_lumaFilter[0][0] : &InterpolationFilter::m_chromaFilter[0][0];
      const int numFracPositions = useLumaFilter ? 15 : 31;
    
      const int numFracShift = useLumaFilter ? 4 : 5;
    
    #if JVET_P0592_CHROMA_PHASE
      const int posShift = SCALE_RATIO_BITS - numFracShift;
      int addX = ( 1 << ( posShift - 1 ) ) + ( ( int( 1 - horCollocatedPositionFlag ) * 8 * ( scalingRatio.first - SCALE_1X.first ) + ( 1 << ( 3 + compScale.first ) ) ) >> ( 4 + compScale.first ) );
      int addY = ( 1 << ( posShift - 1 ) ) + ( ( int( 1 - verCollocatedPositionFlag ) * 8 * ( scalingRatio.second - SCALE_1X.second ) + ( 1 << ( 3 + compScale.second ) ) ) >> ( 4 + compScale.second ) );
    #endif
    
    
      if( downsampling )
      {
        int verFilter = 0;
        int horFilter = 0;
    
        if( 4 * orgHeight > 15 * scaledHeight )   verFilter = 7;
        else if( 7 * orgHeight > 20 * scaledHeight )   verFilter = 6;
        else if( 2 * orgHeight > 5 * scaledHeight )   verFilter = 5;
        else if( 1 * orgHeight > 2 * scaledHeight )   verFilter = 4;
        else if( 3 * orgHeight > 5 * scaledHeight )   verFilter = 3;
        else if( 4 * orgHeight > 5 * scaledHeight )   verFilter = 2;
        else if( 19 * orgHeight > 20 * scaledHeight )   verFilter = 1;
    
        if( 4 * orgWidth > 15 * scaledWidth )   horFilter = 7;
        else if( 7 * orgWidth > 20 * scaledWidth )   horFilter = 6;
        else if( 2 * orgWidth > 5 * scaledWidth )   horFilter = 5;
        else if( 1 * orgWidth > 2 * scaledWidth )   horFilter = 4;
        else if( 3 * orgWidth > 5 * scaledWidth )   horFilter = 3;
        else if( 4 * orgWidth > 5 * scaledWidth )   horFilter = 2;
        else if( 19 * orgWidth > 20 * scaledWidth )   horFilter = 1;
    
        filterHor = &DownsamplingFilterSRC[horFilter][0][0];
        filterVer = &DownsamplingFilterSRC[verFilter][0][0];
      }
    
    
      const int filerLength = downsampling ? 12 : ( useLumaFilter ? NTAPS_LUMA : NTAPS_CHROMA );
    
      const int log2Norm = downsampling ? 14 : 12;
    
    
      int *buf = new int[orgHeight * paddedWidth];
    
      int maxVal = ( 1 << bitDepth ) - 1;
    
      CHECK( bitDepth > 17, "Overflow may happen!" );
    
    
      for( int i = 0; i < paddedWidth; i++ )
    
    #if JVET_P0592_CHROMA_PHASE
        int refPos = ( i * scalingRatio.first + addX ) >> posShift;
        int integer = refPos >> numFracShift;
        int frac = refPos & numFracPositions;
    #else
    
        int integer = ( i * orgWidth ) / scaledWidth;
    
        int frac = ( ( i * orgWidth << numFracShift ) / scaledWidth ) & numFracPositions;
    
    
        int* tmp = buf + i;
    
        for( int j = 0; j < orgHeight; j++ )
        {
          int sum = 0;
    
          const TFilterCoeff* f = filterHor + frac * filerLength;
    
    
          for( int k = 0; k < filerLength; k++ )
          {
            int xInt = std::min<int>( std::max( 0, integer + k - filerLength / 2 + 1 ), orgWidth - 1 );
            sum += f[k] * org[xInt]; // postpone horizontal filtering gain removal after vertical filtering
          }
    
          *tmp = sum;
    
    
          tmp += paddedWidth;
    
      for( int j = 0; j < paddedHeight; j++ )
    
    #if JVET_P0592_CHROMA_PHASE
        int refPos = ( j * scalingRatio.second + addY ) >> posShift;
        int integer = refPos >> numFracShift;
        int frac = refPos & numFracPositions;
    #else
    
        int integer = ( j * orgHeight ) / scaledHeight;
    
        int frac = ( ( j * orgHeight << numFracShift ) / scaledHeight ) & numFracPositions;
    
        for( int i = 0; i < paddedWidth; i++ )
    
          const TFilterCoeff* f = filterVer + frac * filerLength;
    
    
          for( int k = 0; k < filerLength; k++ )
          {
            int yInt = std::min<int>( std::max( 0, integer + k - filerLength / 2 + 1 ), orgHeight - 1 );
    
            sum += f[k] * tmp[yInt*paddedWidth];
    
          }
    
          dst[i] = std::min<int>( std::max( 0, ( sum + ( 1 << ( log2Norm - 1 ) ) ) >> log2Norm ), maxVal );
        }
    
        dst += scaledStride;
      }
    
      delete[] buf;
    }
    
    #endif
    
    #if JVET_P0590_SCALING_WINDOW
    void Picture::rescalePicture( const std::pair<int, int> scalingRatio,
                                  const CPelUnitBuf& beforeScaling, const Window& scalingWindowBefore,
                                  const PelUnitBuf& afterScaling, const Window& scalingWindowAfter,
    #if JVET_P0592_CHROMA_PHASE
                                  const ChromaFormat chromaFormatIDC, const BitDepths& bitDepths, const bool useLumaFilter, const bool downsampling,
                                  const bool horCollocatedChromaFlag, const bool verCollocatedChromaFlag )
    #else
                                  const ChromaFormat chromaFormatIDC, const BitDepths& bitDepths, const bool useLumaFilter, const bool downsampling )
    #endif
    {
      for( int comp = 0; comp < ::getNumberValidComponents( chromaFormatIDC ); comp++ )
      {
        ComponentID compID = ComponentID( comp );
        const CPelBuf& beforeScale = beforeScaling.get( compID );
        const PelBuf& afterScale = afterScaling.get( compID );
    
    #if JVET_P0592_CHROMA_PHASE
        sampleRateConv( scalingRatio, std::pair<int, int>( ::getComponentScaleX( compID, chromaFormatIDC ), ::getComponentScaleY( compID, chromaFormatIDC ) ),
                        beforeScale, scalingWindowBefore.getWindowLeftOffset(), scalingWindowBefore.getWindowTopOffset(), 
                        afterScale, scalingWindowAfter.getWindowLeftOffset(), scalingWindowAfter.getWindowTopOffset(), 
                        bitDepths.recon[comp], downsampling || useLumaFilter ? true : isLuma( compID ), downsampling,
                        isLuma( compID ) ? 1 : horCollocatedChromaFlag, isLuma( compID ) ? 1 : verCollocatedChromaFlag );
    #else
        Picture::sampleRateConv( scalingRatio, 
                                 beforeScale, scalingWindowBefore.getWindowLeftOffset(), scalingWindowBefore.getWindowTopOffset(), 
                                 afterScale, scalingWindowAfter.getWindowLeftOffset(), scalingWindowAfter.getWindowTopOffset(), 
                                 bitDepths.recon[comp], downsampling || useLumaFilter ? true : isLuma( compID ), downsampling );
    #endif
      }
    }
    #elif JVET_P0592_CHROMA_PHASE
    void Picture::rescalePicture( const std::pair<int, int> scalingRatio,
                                  const CPelUnitBuf& beforeScaling, const Window& confBefore,
                                  const PelUnitBuf& afterScaling, const Window& confAfter,
                                  const ChromaFormat chromaFormatIDC, const BitDepths& bitDepths, const bool useLumaFilter, const bool downsampling,
                                  const bool horCollocatedChromaFlag, const bool verCollocatedChromaFlag )
    {
      for( int comp = 0; comp < ::getNumberValidComponents( chromaFormatIDC ); comp++ )
      {
        ComponentID compID = ComponentID( comp );
        const CPelBuf& beforeScale = beforeScaling.get( compID );
        const PelBuf& afterScale = afterScaling.get( compID );
        int widthBefore = beforeScale.width - ( ( ( confBefore.getWindowLeftOffset() + confBefore.getWindowRightOffset() ) * SPS::getWinUnitX( chromaFormatIDC ) ) >> getChannelTypeScaleX( (ChannelType)( comp > 0 ), chromaFormatIDC ) );
        int heightBefore = beforeScale.height - ( ( ( confBefore.getWindowTopOffset() + confBefore.getWindowBottomOffset() ) * SPS::getWinUnitY( chromaFormatIDC ) ) >> getChannelTypeScaleY( (ChannelType)( comp > 0 ), chromaFormatIDC ) );
        int widthAfter = afterScale.width - ( ( ( confAfter.getWindowLeftOffset() + confAfter.getWindowRightOffset() ) * SPS::getWinUnitX( chromaFormatIDC ) ) >> getChannelTypeScaleX( (ChannelType)( comp > 0 ), chromaFormatIDC ) );
        int heightAfter = afterScale.height - ( ( ( confAfter.getWindowTopOffset() + confAfter.getWindowBottomOffset() ) * SPS::getWinUnitY( chromaFormatIDC ) ) >> getChannelTypeScaleY( (ChannelType)( comp > 0 ), chromaFormatIDC ) );
    
        sampleRateConv( scalingRatio, std::pair<int, int>( ::getComponentScaleX( compID, chromaFormatIDC ), ::getComponentScaleY( compID, chromaFormatIDC ) ),
                        beforeScale.buf, widthBefore, heightBefore, beforeScale.stride,
                        afterScale.buf, widthAfter, heightAfter, afterScale.width, afterScale.height, afterScale.stride,
                        bitDepths.recon[comp], downsampling || useLumaFilter ? true : isLuma( compID ), downsampling,
                        isLuma( compID ) ? 1 : horCollocatedChromaFlag, isLuma( compID ) ? 1 : verCollocatedChromaFlag );
      }
    }
    #else
    
    void Picture::rescalePicture( const CPelUnitBuf& beforeScaling, const Window& confBefore, const PelUnitBuf& afterScaling, const Window& confAfter, const ChromaFormat chromaFormatIDC, const BitDepths& bitDepths, const bool useLumaFilter, const bool downsampling )
    
    {
      for( int comp = 0; comp < ::getNumberValidComponents( chromaFormatIDC ); comp++ )
      {
    
        ComponentID compID = ComponentID( comp );
        const CPelBuf& beforeScale = beforeScaling.get( compID );
        const PelBuf& afterScale = afterScaling.get( compID );
    
        int widthBefore = beforeScale.width - (((confBefore.getWindowLeftOffset() + confBefore.getWindowRightOffset()) * SPS::getWinUnitX(chromaFormatIDC)) >> getChannelTypeScaleX((ChannelType)(comp > 0), chromaFormatIDC));
        int heightBefore = beforeScale.height - (((confBefore.getWindowTopOffset() + confBefore.getWindowBottomOffset()) * SPS::getWinUnitY(chromaFormatIDC)) >> getChannelTypeScaleY((ChannelType)(comp > 0), chromaFormatIDC));
        int widthAfter = afterScale.width - (((confAfter.getWindowLeftOffset() + confAfter.getWindowRightOffset()) * SPS::getWinUnitX(chromaFormatIDC)) >> getChannelTypeScaleX((ChannelType)(comp > 0), chromaFormatIDC));
        int heightAfter = afterScale.height - (((confAfter.getWindowTopOffset() + confAfter.getWindowBottomOffset()) * SPS::getWinUnitY(chromaFormatIDC)) >> getChannelTypeScaleY((ChannelType)(comp > 0), chromaFormatIDC));
    
        Picture::sampleRateConv( beforeScale.buf,  widthBefore, heightBefore, beforeScale.stride, afterScale.buf, widthAfter, heightAfter, afterScale.width, afterScale.height, afterScale.stride, bitDepths.recon[comp], downsampling || useLumaFilter ? true : isLuma(compID), downsampling );
    
    void Picture::extendPicBorder()
    {
      if ( m_bIsBorderExtended )
      {
        return;
      }
    
      for(int comp=0; comp<getNumberValidComponents( cs->area.chromaFormat ); comp++)
      {
        ComponentID compID = ComponentID( comp );
        PelBuf p = M_BUFS( 0, PIC_RECONSTRUCTION ).get( compID );
        Pel *piTxt = p.bufAt(0,0);
        int xmargin = margin >> getComponentScaleX( compID, cs->area.chromaFormat );
        int ymargin = margin >> getComponentScaleY( compID, cs->area.chromaFormat );
    
        Pel*  pi = piTxt;
        // do left and right margins
    
    Philippe Hanhart's avatar
    Philippe Hanhart committed
          for (int y = 0; y < p.height; y++)
          {
            for (int x = 0; x < xmargin; x++ )
            {
              pi[ -xmargin + x ] = pi[0];
              pi[  p.width + x ] = pi[p.width-1];
            }
            pi += p.stride;
          }
    
    
        // pi is now the (0,height) (bottom left of image within bigger picture
        pi -= (p.stride + xmargin);
        // pi is now the (-marginX, height-1)
        for (int y = 0; y < ymargin; y++ )
        {
          ::memcpy( pi + (y+1)*p.stride, pi, sizeof(Pel)*(p.width + (xmargin << 1)));
        }
    
        // pi is still (-marginX, height-1)
        pi -= ((p.height-1) * p.stride);
        // pi is now (-marginX, 0)
        for (int y = 0; y < ymargin; y++ )
        {
          ::memcpy( pi - (y+1)*p.stride, pi, sizeof(Pel)*(p.width + (xmargin<<1)) );
        }
    
        // reference picture with horizontal wrapped boundary
        if (cs->sps->getWrapAroundEnabledFlag())
        {
          p = M_BUFS( 0, PIC_RECON_WRAP ).get( compID );
          p.copyFrom(M_BUFS( 0, PIC_RECONSTRUCTION ).get( compID ));
          piTxt = p.bufAt(0,0);
          pi = piTxt;
          int xoffset = cs->sps->getWrapAroundOffset() >> getComponentScaleX( compID, cs->area.chromaFormat );
          for (int y = 0; y < p.height; y++)
          {
            for (int x = 0; x < xmargin; x++ )
            {
    
              if( x < xoffset )
    
              {
                pi[ -x - 1 ] = pi[ -x - 1 + xoffset ];
                pi[  p.width + x ] = pi[ p.width + x - xoffset ];
              }
    
              {
                pi[ -x - 1 ] = pi[ 0 ];
                pi[  p.width + x ] = pi[ p.width - 1 ];
              }
            }
            pi += p.stride;
          }
          pi -= (p.stride + xmargin);
          for (int y = 0; y < ymargin; y++ )
          {
            ::memcpy( pi + (y+1)*p.stride, pi, sizeof(Pel)*(p.width + (xmargin << 1)));
          }
          pi -= ((p.height-1) * p.stride);
          for (int y = 0; y < ymargin; y++ )
          {
            ::memcpy( pi - (y+1)*p.stride, pi, sizeof(Pel)*(p.width + (xmargin<<1)) );
          }
        }
    
      }
    
      m_bIsBorderExtended = true;
    }
    
    PelBuf Picture::getBuf( const ComponentID compID, const PictureType &type )
    {
    
      return M_BUFS( ( type == PIC_ORIGINAL || type == PIC_TRUE_ORIGINAL || type == PIC_ORIGINAL_INPUT || type == PIC_TRUE_ORIGINAL_INPUT ) ? 0 : scheduler.getSplitPicId(), type ).getBuf( compID );
    
    }
    
    const CPelBuf Picture::getBuf( const ComponentID compID, const PictureType &type ) const
    {
    
      return M_BUFS( ( type == PIC_ORIGINAL || type == PIC_TRUE_ORIGINAL || type == PIC_ORIGINAL_INPUT || type == PIC_TRUE_ORIGINAL_INPUT ) ? 0 : scheduler.getSplitPicId(), type ).getBuf( compID );
    
    }
    
    PelBuf Picture::getBuf( const CompArea &blk, const PictureType &type )
    {
      if( !blk.valid() )
      {
        return PelBuf();
      }
    
    #if ENABLE_SPLIT_PARALLELISM
    
      const int jId = ( type == PIC_ORIGINAL || type == PIC_TRUE_ORIGINAL || type == PIC_ORIGINAL_INPUT || type == PIC_TRUE_ORIGINAL_INPUT ) ? 0 : scheduler.getSplitPicId();
    
    #endif
    #if !KEEP_PRED_AND_RESI_SIGNALS
      if( type == PIC_RESIDUAL || type == PIC_PREDICTION )
      {
        CompArea localBlk = blk;
        localBlk.x &= ( cs->pcv->maxCUWidthMask  >> getComponentScaleX( blk.compID, blk.chromaFormat ) );
        localBlk.y &= ( cs->pcv->maxCUHeightMask >> getComponentScaleY( blk.compID, blk.chromaFormat ) );
    
        return M_BUFS( jId, type ).getBuf( localBlk );
      }
    #endif
    
      return M_BUFS( jId, type ).getBuf( blk );
    }
    
    const CPelBuf Picture::getBuf( const CompArea &blk, const PictureType &type ) const
    {
      if( !blk.valid() )
      {
        return PelBuf();
      }
    
    #if ENABLE_SPLIT_PARALLELISM
    
      const int jId = ( type == PIC_ORIGINAL || type == PIC_TRUE_ORIGINAL ) ? 0 : scheduler.getSplitPicId();
    
    
    #endif
    #if !KEEP_PRED_AND_RESI_SIGNALS
      if( type == PIC_RESIDUAL || type == PIC_PREDICTION )
      {
        CompArea localBlk = blk;
        localBlk.x &= ( cs->pcv->maxCUWidthMask  >> getComponentScaleX( blk.compID, blk.chromaFormat ) );
        localBlk.y &= ( cs->pcv->maxCUHeightMask >> getComponentScaleY( blk.compID, blk.chromaFormat ) );
    
        return M_BUFS( jId, type ).getBuf( localBlk );
      }
    #endif
    
      return M_BUFS( jId, type ).getBuf( blk );
    }
    
    PelUnitBuf Picture::getBuf( const UnitArea &unit, const PictureType &type )
    {
      if( chromaFormat == CHROMA_400 )
      {
        return PelUnitBuf( chromaFormat, getBuf( unit.Y(), type ) );
      }
      else
      {
        return PelUnitBuf( chromaFormat, getBuf( unit.Y(), type ), getBuf( unit.Cb(), type ), getBuf( unit.Cr(), type ) );
      }
    }
    
    const CPelUnitBuf Picture::getBuf( const UnitArea &unit, const PictureType &type ) const
    {
      if( chromaFormat == CHROMA_400 )
      {
        return CPelUnitBuf( chromaFormat, getBuf( unit.Y(), type ) );
      }
      else
      {
        return CPelUnitBuf( chromaFormat, getBuf( unit.Y(), type ), getBuf( unit.Cb(), type ), getBuf( unit.Cr(), type ) );
      }
    }
    
    Pel* Picture::getOrigin( const PictureType &type, const ComponentID compID ) const
    {
    #if ENABLE_SPLIT_PARALLELISM
    
      const int jId = ( type == PIC_ORIGINAL || type == PIC_TRUE_ORIGINAL ) ? 0 : scheduler.getSplitPicId();
    
    
    void Picture::createSpliceIdx(int nums)
    {
      m_ctuNums = nums;
      m_spliceIdx = new int[m_ctuNums];
      memset(m_spliceIdx, 0, m_ctuNums * sizeof(int));
    }
    
    bool Picture::getSpliceFull()
    {
      int count = 0;
      for (int i = 0; i < m_ctuNums; i++)
      {
        if (m_spliceIdx[i] != 0)
          count++;
      }
      if (count < m_ctuNums * 0.25)
        return false;
      return true;
    }
    
    
    void Picture::addPictureToHashMapForInter()
    {
    
      int picWidth = slices[0]->getPPS()->getPicWidthInLumaSamples();
      int picHeight = slices[0]->getPPS()->getPicHeightInLumaSamples();
    
      uint32_t* blockHashValues[2][2];
    
      bool* bIsBlockSame[2][3];
    
      for (int i = 0; i < 2; i++)
      {
        for (int j = 0; j < 2; j++)
        {
    
          blockHashValues[i][j] = new uint32_t[picWidth*picHeight];
    
        }
    
        for (int j = 0; j < 3; j++)
        {
          bIsBlockSame[i][j] = new bool[picWidth*picHeight];
        }
      }
    
      m_hashMap.create(picWidth, picHeight);
    
      m_hashMap.generateBlock2x2HashValue(getOrigBuf(), picWidth, picHeight, slices[0]->getSPS()->getBitDepths(), blockHashValues[0], bIsBlockSame[0]);//2x2
      m_hashMap.generateBlockHashValue(picWidth, picHeight, 4, 4, blockHashValues[0], blockHashValues[1], bIsBlockSame[0], bIsBlockSame[1]);//4x4
      m_hashMap.addToHashMapByRowWithPrecalData(blockHashValues[1], bIsBlockSame[1][2], picWidth, picHeight, 4, 4);
    
      m_hashMap.generateBlockHashValue(picWidth, picHeight, 8, 8, blockHashValues[1], blockHashValues[0], bIsBlockSame[1], bIsBlockSame[0]);//8x8
      m_hashMap.addToHashMapByRowWithPrecalData(blockHashValues[0], bIsBlockSame[0][2], picWidth, picHeight, 8, 8);
    
      m_hashMap.generateBlockHashValue(picWidth, picHeight, 16, 16, blockHashValues[0], blockHashValues[1], bIsBlockSame[0], bIsBlockSame[1]);//16x16
      m_hashMap.addToHashMapByRowWithPrecalData(blockHashValues[1], bIsBlockSame[1][2], picWidth, picHeight, 16, 16);
    
      m_hashMap.generateBlockHashValue(picWidth, picHeight, 32, 32, blockHashValues[1], blockHashValues[0], bIsBlockSame[1], bIsBlockSame[0]);//32x32
      m_hashMap.addToHashMapByRowWithPrecalData(blockHashValues[0], bIsBlockSame[0][2], picWidth, picHeight, 32, 32);
    
      m_hashMap.generateBlockHashValue(picWidth, picHeight, 64, 64, blockHashValues[0], blockHashValues[1], bIsBlockSame[0], bIsBlockSame[1]);//64x64
      m_hashMap.addToHashMapByRowWithPrecalData(blockHashValues[1], bIsBlockSame[1][2], picWidth, picHeight, 64, 64);
    
      m_hashMap.setInitial();
    
      for (int i = 0; i < 2; i++)
      {
        for (int j = 0; j < 2; j++)
        {
          delete[] blockHashValues[i][j];
        }
    
        for (int j = 0; j < 3; j++)
        {
          delete[] bIsBlockSame[i][j];
        }
      }
    }