Skip to content
Snippets Groups Projects
EncAppCfg.cpp 386 KiB
Newer Older
  • Learn to ignore specific revisions
  •       if (m_chromaSampleLocType != Chroma420LocType::UNSPECIFIED)
          {
            m_verCollocatedChromaFlag =
              m_chromaSampleLocType == Chroma420LocType::TOP_LEFT || m_chromaSampleLocType == Chroma420LocType::TOP ? 1 : 0;
          }
          else
          {
            m_verCollocatedChromaFlag = 0;
          }
        }
      }
    
      CHECK(m_verCollocatedChromaFlag != 0 && m_verCollocatedChromaFlag != 1, "m_verCollocatedChromaFlag should be 0 or 1");
      CHECK(m_horCollocatedChromaFlag != 0 && m_horCollocatedChromaFlag != 1, "m_horCollocatedChromaFlag should be 0 or 1");
    
    
    #if JVET_O0756_CONFIG_HDRMETRICS && !JVET_O0756_CALCULATE_HDRMETRICS
      if ( m_calculateHdrMetrics == true)
      {
        printf ("Warning: Configuration enables HDR metric calculations.  However, HDR metric support was not linked when compiling the VTM.\n");
        m_calculateHdrMetrics = false;
      }
    #endif
    
    
    Frank Bossen's avatar
    Frank Bossen committed
    #if GDR_ENABLED
    
      if (m_gdrEnabled)
      {
        m_virtualBoundariesEnabledFlag = 1;
        m_virtualBoundariesPresentFlag = 0;
      }
      else
      {
        m_virtualBoundariesEnabledFlag = 0;
      }
    
    #else
    
      m_virtualBoundariesEnabledFlag = 0;
    
    #endif
    
      if( m_numVerVirtualBoundaries > 0 || m_numHorVirtualBoundaries > 0 )
        m_virtualBoundariesEnabledFlag = 1;
    
      if( m_virtualBoundariesEnabledFlag )
    
        CHECK( m_subPicInfoPresentFlag && m_virtualBoundariesPresentFlag != 1, "When subpicture signalling is present, the signalling of virtual boundaries, if present, shall be in the SPS" );
    
    
        if( m_virtualBoundariesPresentFlag )
    
          CHECK( m_numVerVirtualBoundaries > 3, "Number of vertical virtual boundaries must be comprised between 0 and 3 included" );
          CHECK( m_numHorVirtualBoundaries > 3, "Number of horizontal virtual boundaries must be comprised between 0 and 3 included" );
          CHECK( m_numVerVirtualBoundaries != cfg_virtualBoundariesPosX.values.size(), "Size of VirtualBoundariesPosX must be equal to NumVerVirtualBoundaries");
          CHECK( m_numHorVirtualBoundaries != cfg_virtualBoundariesPosY.values.size(), "Size of VirtualBoundariesPosY must be equal to NumHorVirtualBoundaries");
          m_virtualBoundariesPosX = cfg_virtualBoundariesPosX.values;
          if (m_numVerVirtualBoundaries > 1)
    
            sort(m_virtualBoundariesPosX.begin(), m_virtualBoundariesPosX.end());
    
          for (unsigned i = 0; i < m_numVerVirtualBoundaries; i++)
    
            CHECK( m_virtualBoundariesPosX[i] == 0 || m_virtualBoundariesPosX[i] >= m_sourceWidth, "The vertical virtual boundary must be within the picture" );
    
            CHECK( m_virtualBoundariesPosX[i] % 8, "The vertical virtual boundary must be a multiple of 8 luma samples" );
            if (i > 0)
            {
    
    Frank Bossen's avatar
    Frank Bossen committed
              CHECK(
                m_virtualBoundariesPosX[i] - m_virtualBoundariesPosX[i - 1] < m_ctuSize,
                "The distance between any two vertical virtual boundaries shall be greater than or equal to the CTU size");
    
            }
          }
          m_virtualBoundariesPosY = cfg_virtualBoundariesPosY.values;
          if (m_numHorVirtualBoundaries > 1)
          {
            sort(m_virtualBoundariesPosY.begin(), m_virtualBoundariesPosY.end());
          }
          for (unsigned i = 0; i < m_numHorVirtualBoundaries; i++)
          {
    
            CHECK( m_virtualBoundariesPosY[i] == 0 || m_virtualBoundariesPosY[i] >= m_sourceHeight, "The horizontal virtual boundary must be within the picture" );
    
            CHECK( m_virtualBoundariesPosY[i] % 8, "The horizontal virtual boundary must be a multiple of 8 luma samples" );
            if (i > 0)
            {
    
    Frank Bossen's avatar
    Frank Bossen committed
              CHECK(m_virtualBoundariesPosY[i] - m_virtualBoundariesPosY[i - 1] < m_ctuSize,
                    "The distance between any two horizontal virtual boundaries shall be greater than or equal to the CTU "
                    "size");
    
        CHECK(m_maxNumAlfAlternativesChroma < 1 || m_maxNumAlfAlternativesChroma > ALF_MAX_NUM_ALTERNATIVES_CHROMA,
              std::string("The maximum number of ALF Chroma filter alternatives must be in the range (1-")
                + std::to_string(ALF_MAX_NUM_ALTERNATIVES_CHROMA) + std::string(", inclusive)"));
    
      // reading external dQP description from file
      if ( !m_dQPFileName.empty() )
      {
        FILE* fpt=fopen( m_dQPFileName.c_str(), "r" );
        if ( fpt )
        {
    
          int val;
          int poc = 0;
          m_frameDeltaQps.clear();
          while (poc < m_framesToBeEncoded)
    
            if (fscanf(fpt, "%d", &val) == EOF)
    
            m_frameDeltaQps.push_back(val);
            poc++;
    
          }
          fclose(fpt);
        }
      }
    
      if( m_masteringDisplay.colourVolumeSEIEnabled )
      {
        for(uint32_t idx=0; idx<6; idx++)
        {
          m_masteringDisplay.primaries[idx/2][idx%2] = uint16_t((cfg_DisplayPrimariesCode.values.size() > idx) ? cfg_DisplayPrimariesCode.values[idx] : 0);
        }
        for(uint32_t idx=0; idx<2; idx++)
        {
          m_masteringDisplay.whitePoint[idx] = uint16_t((cfg_DisplayWhitePointCode.values.size() > idx) ? cfg_DisplayWhitePointCode.values[idx] : 0);
        }
      }
    
      // set sei film grain parameters.
      CHECK(!m_fgcSEIEnabled && m_fgcSEIAnalysisEnabled, "FGC SEI must be enabled in order to perform film grain analysis!");
      if (m_fgcSEIEnabled)
      {
    
        if (m_iQP < 17 && m_fgcSEIAnalysisEnabled == true)
        {   // TODO: JVET_Z0047_FG_IMPROVEMENT: check this; the constraint may have gone
    
          msg(WARNING, "*************************************************************************\n");
          msg(WARNING, "* WARNING: Film Grain Estimation is disabled for Qp<17! FGC SEI will use default parameters for film grain! *\n");
          msg(WARNING, "*************************************************************************\n");
          m_fgcSEIAnalysisEnabled = false;
        }
    
    Frank Bossen's avatar
    Frank Bossen committed
        if (m_intraPeriod < 1)
        {   // low delay configuration
    
          msg(WARNING, "*************************************************************************\n");
          msg(WARNING, "* WARNING: For low delay configuration, FGC SEI is inserted for first frame only!*\n");
          msg(WARNING, "*************************************************************************\n");
          m_fgcSEIPerPictureSEI   = false;
          m_fgcSEIPersistenceFlag = true;
        }
    
    Frank Bossen's avatar
    Frank Bossen committed
        else if (m_intraPeriod == 1)
        {   // all intra configuration
          msg(WARNING, "*************************************************************************\n");
          msg(WARNING, "* WARNING: For Intra Period = 1, FGC SEI is inserted per frame!*\n");
          msg(WARNING, "*************************************************************************\n");
          m_fgcSEIPerPictureSEI   = true;
          m_fgcSEIPersistenceFlag = false;
    
        }
        if (!m_fgcSEIPerPictureSEI && !m_fgcSEIPersistenceFlag) {
          msg(WARNING, "*************************************************************************\n");
          msg(WARNING, "* WARNING: SEIPerPictureSEI is set to 0, SEIPersistenceFlag needs to be set to 1! *\n");
          msg(WARNING, "*************************************************************************\n");
          m_fgcSEIPersistenceFlag = true;
        }
        else if (m_fgcSEIPerPictureSEI && m_fgcSEIPersistenceFlag) {
          msg(WARNING, "*************************************************************************\n");
          msg(WARNING, "* WARNING: SEIPerPictureSEI is set to 1, SEIPersistenceFlag needs to be set to 0! *\n");
          msg(WARNING, "*************************************************************************\n");
          m_fgcSEIPersistenceFlag = false;
        }
    
        if (m_fgcSEIAnalysisEnabled && m_fgcSEITemporalFilterStrengths.empty())
        {
    
          // By default: in random-acces = filter RAPs, in all-intra = filter every frame, otherwise = filter every 2s
    
          int filteredFrame = m_intraPeriod < 1 ? 2 * m_frameRate.getIntValRound() : m_intraPeriod;
    
          m_fgcSEITemporalFilterStrengths[filteredFrame] = 1.5;
        }
    
        uint32_t numModelCtr;
        if (m_fgcSEICompModelPresent[0])
        {
          numModelCtr = 0;
          for (uint8_t i = 0; i <= m_fgcSEINumIntensityIntervalMinus1[0]; i++)
          {
            m_fgcSEIIntensityIntervalLowerBound[0][i] = uint32_t((cfg_FgcSEIIntensityIntervalLowerBoundComp0.values.size() > i) ? cfg_FgcSEIIntensityIntervalLowerBoundComp0.values[i] : 10);
            m_fgcSEIIntensityIntervalUpperBound[0][i] = uint32_t((cfg_FgcSEIIntensityIntervalUpperBoundComp0.values.size() > i) ? cfg_FgcSEIIntensityIntervalUpperBoundComp0.values[i] : 250);
            for (uint8_t j = 0; j <= m_fgcSEINumModelValuesMinus1[0]; j++)
            {
              m_fgcSEICompModelValue[0][i][j] = uint32_t((cfg_FgcSEICompModelValueComp0.values.size() > numModelCtr) ? cfg_FgcSEICompModelValueComp0.values[numModelCtr] : 24);
              numModelCtr++;
            }
          }
        }
        if (m_fgcSEICompModelPresent[1])
        {
          numModelCtr = 0;
          for (uint8_t i = 0; i <= m_fgcSEINumIntensityIntervalMinus1[1]; i++)
          {
            m_fgcSEIIntensityIntervalLowerBound[1][i] = uint32_t((cfg_FgcSEIIntensityIntervalLowerBoundComp1.values.size() > i) ? cfg_FgcSEIIntensityIntervalLowerBoundComp1.values[i] : 60);
            m_fgcSEIIntensityIntervalUpperBound[1][i] = uint32_t((cfg_FgcSEIIntensityIntervalUpperBoundComp1.values.size() > i) ? cfg_FgcSEIIntensityIntervalUpperBoundComp1.values[i] : 200);
    
            for (uint8_t j = 0; j <= m_fgcSEINumModelValuesMinus1[1]; j++)
            {
              m_fgcSEICompModelValue[1][i][j] = uint32_t((cfg_FgcSEICompModelValueComp1.values.size() > numModelCtr) ? cfg_FgcSEICompModelValueComp1.values[numModelCtr] : 16);
              numModelCtr++;
            }
          }
        }
        if (m_fgcSEICompModelPresent[2])
        {
          numModelCtr = 0;
          for (uint8_t i = 0; i <= m_fgcSEINumIntensityIntervalMinus1[2]; i++)
          {
            m_fgcSEIIntensityIntervalLowerBound[2][i] = uint32_t((cfg_FgcSEIIntensityIntervalLowerBoundComp2.values.size() > i) ? cfg_FgcSEIIntensityIntervalLowerBoundComp2.values[i] : 60);
            m_fgcSEIIntensityIntervalUpperBound[2][i] = uint32_t((cfg_FgcSEIIntensityIntervalUpperBoundComp2.values.size() > i) ? cfg_FgcSEIIntensityIntervalUpperBoundComp2.values[i] : 250);
    
            for (uint8_t j = 0; j <= m_fgcSEINumModelValuesMinus1[2]; j++)
            {
              m_fgcSEICompModelValue[2][i][j] = uint32_t((cfg_FgcSEICompModelValueComp2.values.size() > numModelCtr) ? cfg_FgcSEICompModelValueComp2.values[numModelCtr] : 12);
              numModelCtr++;
            }
          }
        }
        m_fgcSEILog2ScaleFactor = m_fgcSEILog2ScaleFactor ? m_fgcSEILog2ScaleFactor : 2;
      }
    
      if (m_ctiSEIEnabled)
    
      {
        CHECK(!m_ctiSEICrossComponentFlag && m_ctiSEICrossComponentInferred, "CTI CrossComponentFlag is 0, but CTI CrossComponentInferred is 1 (must be 0 for CrossComponentFlag 0)");
        CHECK(!m_ctiSEICrossComponentFlag && !m_ctiSEICrossComponentInferred && !m_ctiSEINumberChromaLut, "For CTI CrossComponentFlag = 0, CTI NumberChromaLut needs to be specified (1 or 2) ");
        CHECK(m_ctiSEICrossComponentFlag && !m_ctiSEICrossComponentInferred && !m_ctiSEINumberChromaLut, "For CTI CrossComponentFlag = 1 and CrossComponentInferred = 0, CTI NumberChromaLut needs to be specified (1 or 2) ");
    
        CHECK(cfg_SEICTILut0.values.empty(), "SEI CTI (SEICTIEnabled) but no LUT0 specified");
        m_ctiSEILut[0].presentFlag = true;
        m_ctiSEILut[0].numLutValues = (int)cfg_SEICTILut0.values.size();
        m_ctiSEILut[0].lutValues = cfg_SEICTILut0.values;
    
    
        if (!m_ctiSEICrossComponentFlag || (m_ctiSEICrossComponentFlag && !m_ctiSEICrossComponentInferred))
    
        {
          CHECK(cfg_SEICTILut1.values.empty(), "SEI CTI LUT1 not specified");
          m_ctiSEILut[1].presentFlag = true;
          m_ctiSEILut[1].numLutValues = (int)cfg_SEICTILut1.values.size();
          m_ctiSEILut[1].lutValues = cfg_SEICTILut1.values;
    
    
          if (m_ctiSEINumberChromaLut == 1)
    
          { // Cb lut the same as Cr lut
            m_ctiSEILut[2].presentFlag = true;
            m_ctiSEILut[2].numLutValues = m_ctiSEILut[1].numLutValues;
            m_ctiSEILut[2].lutValues = m_ctiSEILut[1].lutValues;
          }
    
          else if (m_ctiSEINumberChromaLut == 2)
    
          { // read from cfg
            CHECK(cfg_SEICTILut2.values.empty(), "SEI CTI LUT2 not specified");
            m_ctiSEILut[2].presentFlag = true;
            m_ctiSEILut[2].numLutValues = (int)cfg_SEICTILut2.values.size();
            m_ctiSEILut[2].lutValues = cfg_SEICTILut2.values;
          }
    
          {
            CHECK(m_ctiSEINumberChromaLut < 1 && m_ctiSEINumberChromaLut > 2, "Number of chroma LUTs is missing or out of range!");
          }
        }
        //  check if lut size is power of 2
    
        for (int idx = 0; idx < MAX_NUM_COMPONENT; idx++)
    
        {
          int n = m_ctiSEILut[idx].numLutValues - 1;
          CHECK(n > 0 && (n & (n - 1)) != 0, "Size of LUT minus 1 should be power of 2!");
          CHECK(n > MAX_CTI_LUT_SIZE, "LUT size minus 1 is larger than MAX_CTI_LUT_SIZE (64)!");
        }
      }
    
      if ( m_omniViewportSEIEnabled && !m_omniViewportSEICancelFlag )
      {
        CHECK (!( m_omniViewportSEICntMinus1 >= 0 && m_omniViewportSEICntMinus1 < 16 ), "SEIOmniViewportCntMinus1 must be in the range of 0 to 16");
        m_omniViewportSEIAzimuthCentre.resize  (m_omniViewportSEICntMinus1+1);
        m_omniViewportSEIElevationCentre.resize(m_omniViewportSEICntMinus1+1);
        m_omniViewportSEITiltCentre.resize     (m_omniViewportSEICntMinus1+1);
        m_omniViewportSEIHorRange.resize       (m_omniViewportSEICntMinus1+1);
        m_omniViewportSEIVerRange.resize       (m_omniViewportSEICntMinus1+1);
        for(int i=0; i<(m_omniViewportSEICntMinus1+1); i++)
        {
          m_omniViewportSEIAzimuthCentre[i]   = cfg_omniViewportSEIAzimuthCentre  .values.size() > i ? cfg_omniViewportSEIAzimuthCentre  .values[i] : 0;
          m_omniViewportSEIElevationCentre[i] = cfg_omniViewportSEIElevationCentre.values.size() > i ? cfg_omniViewportSEIElevationCentre.values[i] : 0;
          m_omniViewportSEITiltCentre[i]      = cfg_omniViewportSEITiltCentre     .values.size() > i ? cfg_omniViewportSEITiltCentre     .values[i] : 0;
          m_omniViewportSEIHorRange[i]        = cfg_omniViewportSEIHorRange       .values.size() > i ? cfg_omniViewportSEIHorRange       .values[i] : 0;
          m_omniViewportSEIVerRange[i]        = cfg_omniViewportSEIVerRange       .values.size() > i ? cfg_omniViewportSEIVerRange       .values[i] : 0;
        }
      }
    
      if(!m_rwpSEIRwpCancelFlag && m_rwpSEIEnabled)
      {
        CHECK (!( m_rwpSEINumPackedRegions > 0 && m_rwpSEINumPackedRegions <= std::numeric_limits<uint8_t>::max() ), "SEIRwpNumPackedRegions must be in the range of 1 to 255");
        CHECK (!(cfg_rwpSEIRwpTransformType.values.size() == m_rwpSEINumPackedRegions), "Number of must SEIRwpTransformType values be equal to SEIRwpNumPackedRegions");
        CHECK (!(cfg_rwpSEIRwpGuardBandFlag.values.size() == m_rwpSEINumPackedRegions), "Number of must SEIRwpGuardBandFlag values must be equal to SEIRwpNumPackedRegions");
        CHECK (!(cfg_rwpSEIProjRegionWidth.values.size() == m_rwpSEINumPackedRegions), "Number of must SEIProjRegionWidth values must be equal to SEIRwpNumPackedRegions");
        CHECK (!(cfg_rwpSEIProjRegionHeight.values.size() == m_rwpSEINumPackedRegions), "Number of must SEIProjRegionHeight values must be equal to SEIRwpNumPackedRegions");
        CHECK (!(cfg_rwpSEIRwpSEIProjRegionTop.values.size() == m_rwpSEINumPackedRegions), "Number of must SEIRwpSEIProjRegionTop values must be equal to SEIRwpNumPackedRegions");
        CHECK (!(cfg_rwpSEIProjRegionLeft.values.size() == m_rwpSEINumPackedRegions), "Number of must SEIProjRegionLeft values must be equal to SEIRwpNumPackedRegions");
        CHECK (!(cfg_rwpSEIPackedRegionWidth.values.size() == m_rwpSEINumPackedRegions), "Number of must SEIPackedRegionWidth values must be equal to SEIRwpNumPackedRegions");
        CHECK (!(cfg_rwpSEIPackedRegionHeight.values.size() == m_rwpSEINumPackedRegions), "Number of must SEIPackedRegionHeight values must be equal to SEIRwpNumPackedRegions");
        CHECK (!(cfg_rwpSEIPackedRegionTop.values.size() == m_rwpSEINumPackedRegions), "Number of must SEIPackedRegionTop values must be equal to SEIRwpNumPackedRegions");
        CHECK (!(cfg_rwpSEIPackedRegionLeft.values.size() == m_rwpSEINumPackedRegions), "Number of must SEIPackedRegionLeft values must be equal to SEIRwpNumPackedRegions");
    
        m_rwpSEIRwpTransformType.resize(m_rwpSEINumPackedRegions);
        m_rwpSEIRwpGuardBandFlag.resize(m_rwpSEINumPackedRegions);
        m_rwpSEIProjRegionWidth.resize(m_rwpSEINumPackedRegions);
        m_rwpSEIProjRegionHeight.resize(m_rwpSEINumPackedRegions);
        m_rwpSEIRwpSEIProjRegionTop.resize(m_rwpSEINumPackedRegions);
        m_rwpSEIProjRegionLeft.resize(m_rwpSEINumPackedRegions);
        m_rwpSEIPackedRegionWidth.resize(m_rwpSEINumPackedRegions);
        m_rwpSEIPackedRegionHeight.resize(m_rwpSEINumPackedRegions);
        m_rwpSEIPackedRegionTop.resize(m_rwpSEINumPackedRegions);
        m_rwpSEIPackedRegionLeft.resize(m_rwpSEINumPackedRegions);
        m_rwpSEIRwpLeftGuardBandWidth.resize(m_rwpSEINumPackedRegions);
        m_rwpSEIRwpRightGuardBandWidth.resize(m_rwpSEINumPackedRegions);
        m_rwpSEIRwpTopGuardBandHeight.resize(m_rwpSEINumPackedRegions);
        m_rwpSEIRwpBottomGuardBandHeight.resize(m_rwpSEINumPackedRegions);
        m_rwpSEIRwpGuardBandNotUsedForPredFlag.resize(m_rwpSEINumPackedRegions);
        m_rwpSEIRwpGuardBandType.resize(4*m_rwpSEINumPackedRegions);
        for( int i=0; i < m_rwpSEINumPackedRegions; i++ )
        {
          m_rwpSEIRwpTransformType[i]                     = cfg_rwpSEIRwpTransformType.values[i];
          CHECK (!( m_rwpSEIRwpTransformType[i] >= 0 && m_rwpSEIRwpTransformType[i] <= 7 ), "SEIRwpTransformType must be in the range of 0 to 7");
          m_rwpSEIRwpGuardBandFlag[i]                     = cfg_rwpSEIRwpGuardBandFlag.values[i];
          m_rwpSEIProjRegionWidth[i]                      = cfg_rwpSEIProjRegionWidth.values[i];
          m_rwpSEIProjRegionHeight[i]                     = cfg_rwpSEIProjRegionHeight.values[i];
          m_rwpSEIRwpSEIProjRegionTop[i]                  = cfg_rwpSEIRwpSEIProjRegionTop.values[i];
          m_rwpSEIProjRegionLeft[i]                       = cfg_rwpSEIProjRegionLeft.values[i];
          m_rwpSEIPackedRegionWidth[i]                    = cfg_rwpSEIPackedRegionWidth.values[i];
          m_rwpSEIPackedRegionHeight[i]                   = cfg_rwpSEIPackedRegionHeight.values[i];
          m_rwpSEIPackedRegionTop[i]                      = cfg_rwpSEIPackedRegionTop.values[i];
    
          m_rwpSEIPackedRegionLeft[i]                     = cfg_rwpSEIPackedRegionLeft.values[i];
    
          if( m_rwpSEIRwpGuardBandFlag[i] )
          {
            m_rwpSEIRwpLeftGuardBandWidth[i]              =  cfg_rwpSEIRwpLeftGuardBandWidth.values[i];
            m_rwpSEIRwpRightGuardBandWidth[i]             =  cfg_rwpSEIRwpRightGuardBandWidth.values[i];
            m_rwpSEIRwpTopGuardBandHeight[i]              =  cfg_rwpSEIRwpTopGuardBandHeight.values[i];
            m_rwpSEIRwpBottomGuardBandHeight[i]           =  cfg_rwpSEIRwpBottomGuardBandHeight.values[i];
            CHECK (! ( m_rwpSEIRwpLeftGuardBandWidth[i] > 0 || m_rwpSEIRwpRightGuardBandWidth[i] > 0 || m_rwpSEIRwpTopGuardBandHeight[i] >0 || m_rwpSEIRwpBottomGuardBandHeight[i] >0 ), "At least one of the RWP guard band parameters mut be greater than zero");
            m_rwpSEIRwpGuardBandNotUsedForPredFlag[i]     =  cfg_rwpSEIRwpGuardBandNotUsedForPredFlag.values[i];
            for( int j=0; j < 4; j++ )
            {
              m_rwpSEIRwpGuardBandType[i*4 + j]           =  cfg_rwpSEIRwpGuardBandType.values[i*4 + j];
            }
    
          }
        }
      }
    
      if (m_gcmpSEIEnabled && !m_gcmpSEICancelFlag)
      {
        int numFace = m_gcmpSEIPackingType == 4 || m_gcmpSEIPackingType == 5 ? 5 : 6;
        CHECK (!(cfg_gcmpSEIFaceIndex.values.size()                  == numFace), "Number of SEIGcmpFaceIndex must be equal to 5 when SEIGcmpPackingType is equal to 4 or 5, otherwise, it must be equal to 6");
        CHECK (!(cfg_gcmpSEIFaceRotation.values.size()               == numFace), "Number of SEIGcmpFaceRotation must be equal to 5 when SEIGcmpPackingType is equal to 4 or 5, otherwise, it must be equal to 6");
        m_gcmpSEIFaceIndex.resize(numFace);
        m_gcmpSEIFaceRotation.resize(numFace);
        if (m_gcmpSEIMappingFunctionType == 2)
        {
          CHECK (!(cfg_gcmpSEIFunctionCoeffU.values.size()           == numFace), "Number of SEIGcmpFunctionCoeffU must be equal to 5 when SEIGcmpPackingType is equal to 4 or 5, otherwise, it must be equal to 6");
          CHECK (!(cfg_gcmpSEIFunctionUAffectedByVFlag.values.size() == numFace), "Number of SEIGcmpFunctionUAffectedByVFlag must be equal to 5 when SEIGcmpPackingType is equal to 4 or 5, otherwise, it must be equal to 6");
          CHECK (!(cfg_gcmpSEIFunctionCoeffV.values.size()           == numFace), "Number of SEIGcmpFunctionCoeffV must be equal to 5 when SEIGcmpPackingType is equal to 4 or 5, otherwise, it must be equal to 6");
          CHECK (!(cfg_gcmpSEIFunctionVAffectedByUFlag.values.size() == numFace), "Number of SEIGcmpFunctionVAffectedByUFlag must be equal to 5 when SEIGcmpPackingType is equal to 4 or 5, otherwise, it must be equal to 6");
          m_gcmpSEIFunctionCoeffU.resize(numFace);
          m_gcmpSEIFunctionUAffectedByVFlag.resize(numFace);
          m_gcmpSEIFunctionCoeffV.resize(numFace);
          m_gcmpSEIFunctionVAffectedByUFlag.resize(numFace);
        }
        for (int i = 0; i < numFace; i++)
        {
          m_gcmpSEIFaceIndex[i]                = cfg_gcmpSEIFaceIndex.values[i];
          m_gcmpSEIFaceRotation[i]             = cfg_gcmpSEIFaceRotation.values[i];
          if (m_gcmpSEIMappingFunctionType == 2)
          {
            m_gcmpSEIFunctionCoeffU[i]           = cfg_gcmpSEIFunctionCoeffU.values[i];
            m_gcmpSEIFunctionUAffectedByVFlag[i] = cfg_gcmpSEIFunctionUAffectedByVFlag.values[i];
            m_gcmpSEIFunctionCoeffV[i]           = cfg_gcmpSEIFunctionCoeffV.values[i];
            m_gcmpSEIFunctionVAffectedByUFlag[i] = cfg_gcmpSEIFunctionVAffectedByUFlag.values[i];
          }
        }
      }
    
      if ( m_sdiSEIEnabled )
      {
        if (m_sdiSEIMultiviewInfoFlag || m_sdiSEIAuxiliaryInfoFlag)
        {
          m_sdiSEILayerId.resize(m_sdiSEIMaxLayersMinus1 + 1);
          m_sdiSEIViewIdVal.resize(m_sdiSEIMaxLayersMinus1 + 1);
          m_sdiSEIAuxId.resize(m_sdiSEIMaxLayersMinus1 + 1);
          m_sdiSEINumAssociatedPrimaryLayersMinus1.resize(m_sdiSEIMaxLayersMinus1 + 1);
          for (int i = 0; i <= m_sdiSEIMaxLayersMinus1; i++)
          {
            m_sdiSEILayerId[i] = cfg_sdiSEILayerId.values[i];
            if (m_sdiSEIMultiviewInfoFlag)
            {
              m_sdiSEIViewIdVal[i] = cfg_sdiSEIViewIdVal.values[i];
            }
            if (m_sdiSEIAuxiliaryInfoFlag)
            {
              m_sdiSEIAuxId[i] = cfg_sdiSEIAuxId.values[i];
              if (m_sdiSEIAuxId[i] > 0)
              {
                m_sdiSEINumAssociatedPrimaryLayersMinus1[i] = cfg_sdiSEINumAssociatedPrimaryLayersMinus1.values[i];
              }
            }
          }
        }
      }
      if ( m_maiSEIEnabled )
      {
        if (m_maiSEIIntrinsicParamFlag)
        {
          int numViews = m_maiSEIIntrinsicParamsEqualFlag ? 1 : m_maiSEINumViewsMinus1 + 1;
          m_maiSEISignFocalLengthX       .resize( numViews );
          m_maiSEIExponentFocalLengthX   .resize( numViews );
          m_maiSEIMantissaFocalLengthX   .resize( numViews );
          m_maiSEISignFocalLengthY       .resize( numViews );
          m_maiSEIExponentFocalLengthY   .resize( numViews );
          m_maiSEIMantissaFocalLengthY   .resize( numViews );
          m_maiSEISignPrincipalPointX    .resize( numViews );
          m_maiSEIExponentPrincipalPointX.resize( numViews );
          m_maiSEIMantissaPrincipalPointX.resize( numViews );
          m_maiSEISignPrincipalPointY    .resize( numViews );
          m_maiSEIExponentPrincipalPointY.resize( numViews );
          m_maiSEIMantissaPrincipalPointY.resize( numViews );
          m_maiSEISignSkewFactor         .resize( numViews );
          m_maiSEIExponentSkewFactor     .resize( numViews );
          m_maiSEIMantissaSkewFactor     .resize( numViews );
          for( int i = 0; i  <=  ( m_maiSEIIntrinsicParamsEqualFlag ? 0 : m_maiSEINumViewsMinus1 ); i++ )
          {
            m_maiSEISignFocalLengthX       [i] = cfg_maiSEISignFocalLengthX.values[i];
            m_maiSEIExponentFocalLengthX   [i] = cfg_maiSEIExponentFocalLengthX.values[i];
            m_maiSEIMantissaFocalLengthX   [i] = cfg_maiSEIMantissaFocalLengthX.values[i];
            m_maiSEISignFocalLengthY       [i] = cfg_maiSEISignFocalLengthY.values[i];
            m_maiSEIExponentFocalLengthY   [i] = cfg_maiSEIExponentFocalLengthY.values[i];
            m_maiSEIMantissaFocalLengthY   [i] = cfg_maiSEIMantissaFocalLengthY.values[i];
            m_maiSEISignPrincipalPointX    [i] = cfg_maiSEISignPrincipalPointX.values[i];
            m_maiSEIExponentPrincipalPointX[i] = cfg_maiSEIExponentPrincipalPointX.values[i];
            m_maiSEIMantissaPrincipalPointX[i] = cfg_maiSEIMantissaPrincipalPointX.values[i];
            m_maiSEISignPrincipalPointY    [i] = cfg_maiSEISignPrincipalPointY.values[i];
            m_maiSEIExponentPrincipalPointY[i] = cfg_maiSEIExponentPrincipalPointY.values[i];
            m_maiSEIMantissaPrincipalPointY[i] = cfg_maiSEIMantissaPrincipalPointY.values[i];
            m_maiSEISignSkewFactor         [i] = cfg_maiSEISignSkewFactor.values[i];
            m_maiSEIExponentSkewFactor     [i] = cfg_maiSEIExponentSkewFactor.values[i];
            m_maiSEIMantissaSkewFactor     [i] = cfg_maiSEIMantissaSkewFactor.values[i];
          }
        }
      }
    
      if (m_mvpSEIEnabled)
      {
        int numViews = m_mvpSEINumViewsMinus1 + 1;
        m_mvpSEIViewPosition.resize(numViews);
        for (int i = 0; i <= m_mvpSEINumViewsMinus1; i++)
        {
    
    Byeongdoo Choi's avatar
    Byeongdoo Choi committed
          m_mvpSEIViewPosition[i] = cfg_mvpSEIViewPosition.values[i];
    
      if ( m_driSEIEnabled )
      {
        m_driSEINonlinearModel.resize(m_driSEINonlinearNumMinus1+1);
        for(int i=0; i<(m_driSEINonlinearNumMinus1+1); i++)
        {
          m_driSEINonlinearModel[i]   = cfg_driSEINonlinearModel.values.size() > i ? cfg_driSEINonlinearModel.values[i] : 0;
        }
      }
    
    Taoran Lu's avatar
    Taoran Lu committed
      m_reshapeCW.binCW.resize(3);
    
      m_reshapeCW.rspFps     = m_frameRate.getIntValRound();
    
      m_reshapeCW.rspPicSize = m_sourceWidth*m_sourceHeight;
    
      m_reshapeCW.rspFpsToIp = std::max(16, 16 * (int) (round(m_frameRate.getFloatVal() / 16.0)));
    
    Taoran Lu's avatar
    Taoran Lu committed
      m_reshapeCW.rspBaseQP = m_iQP;
    
      m_reshapeCW.updateCtrl = m_updateCtrl;
      m_reshapeCW.adpOption = m_adpOption;
      m_reshapeCW.initialCW = m_initialCW;
    
    #if ENABLE_TRACING
      g_trace_ctx = tracing_init(sTracingFile, sTracingRule);
      if( bTracingChannelsList && g_trace_ctx )
      {
        std::string sChannelsList;
        g_trace_ctx->getChannelsList( sChannelsList );
        msg( INFO, "\n Using tracing channels:\n\n%s\n", sChannelsList.c_str() );
      }
    #endif
    
    #if ENABLE_QPA
    
      if (m_bUsePerceptQPA && !m_bUseAdaptiveQP && m_dualTree && (m_cbQpOffsetDualTree != 0 || m_crQpOffsetDualTree != 0 || m_cbCrQpOffsetDualTree != 0))
    
      {
        msg( WARNING, "*************************************************************************\n" );
        msg( WARNING, "* WARNING: chroma QPA on, ignoring nonzero dual-tree chroma QP offsets! *\n" );
        msg( WARNING, "*************************************************************************\n" );
      }
    
    
      if ((m_iQP < 38) && m_bUsePerceptQPA && !m_bUseAdaptiveQP && (m_sourceWidth <= 2048) && (m_sourceHeight <= 1280)
    
    Frank Bossen's avatar
    Frank Bossen committed
    #if WCG_EXT && ER_CHROMA_QP_WCG_PPS
    
          && (!m_wcgChromaQpControl.enabled)
    
    Frank Bossen's avatar
    Frank Bossen committed
    #endif
          && ((1 << (m_log2MaxTbSize + 1)) == m_ctuSize) && (m_sourceWidth > 512 || m_sourceHeight > 320))
    
        m_cuQpDeltaSubdiv = 2;
    
    Frank Bossen's avatar
    Frank Bossen committed
      if ((m_iQP < 38) && (m_gopSize > 4) && m_bUsePerceptQPA && !m_bUseAdaptiveQP && (m_sourceHeight <= 1280)
          && (m_sourceWidth <= 2048))
    
        msg( WARNING, "*************************************************************************\n" );
        msg( WARNING, "* WARNING: QPA on with large CTU for <=HD sequences, limiting CTU size! *\n" );
        msg( WARNING, "*************************************************************************\n" );
    
    Frank Bossen's avatar
    Frank Bossen committed
        m_ctuSize = m_maxCuWidth;
        if ((1u << m_log2MaxTbSize) > m_ctuSize)
        {
          m_log2MaxTbSize--;
        }
    
    #if JVET_Z0120_SII_SEI_PROCESSING
      m_ShutterFilterEnable = false;
    #endif
      if (m_siiSEIEnabled)
      {
        assert(m_siiSEITimeScale >= 0 && m_siiSEITimeScale <= MAX_UINT);
        uint32_t sii_max_sub_layers = (uint32_t)cfg_siiSEIInputNumUnitsInSI.values.size();
        assert(sii_max_sub_layers > 0);
        if (sii_max_sub_layers > 1)
        {
          m_siiSEISubLayerNumUnitsInSI.resize(sii_max_sub_layers);
          for (int32_t i = 0; i < sii_max_sub_layers; i++)
          {
            m_siiSEISubLayerNumUnitsInSI[i] = cfg_siiSEIInputNumUnitsInSI.values[i];
            assert(m_siiSEISubLayerNumUnitsInSI[i] >= 0 && m_siiSEISubLayerNumUnitsInSI[i] <= MAX_UINT);
          }
        }
        else
        {
          m_siiSEINumUnitsInShutterInterval = cfg_siiSEIInputNumUnitsInSI.values[0];
          assert(m_siiSEINumUnitsInShutterInterval >= 0 && m_siiSEINumUnitsInShutterInterval <= MAX_UINT);
        }
    #if JVET_Z0120_SII_SEI_PROCESSING
        uint32_t siiMaxSubLayersMinus1 = sii_max_sub_layers - 1;
        int blending_ratio = (m_siiSEISubLayerNumUnitsInSI[0] / m_siiSEISubLayerNumUnitsInSI[siiMaxSubLayersMinus1]);
    
        if (sii_max_sub_layers > 1 && m_siiSEISubLayerNumUnitsInSI[0] ==
                                    (blending_ratio * m_siiSEISubLayerNumUnitsInSI[siiMaxSubLayersMinus1]))
        {
          m_ShutterFilterEnable = true;
    
          double  fpsHFR        = m_frameRate.getFloatVal();
    
          bool    checkEqualValuesOfSFR = true;
          bool    checkSubLayerSI       = false;
    
          double shutterAngleFactor = (fpsHFR * ((double)(m_siiSEISubLayerNumUnitsInSI[siiMaxSubLayersMinus1])))/((double)m_siiSEITimeScale);
    
    
          // If shutterAngleFactor = 1 indicates that shutterAngle = 360
    
          // If shutterAngleFactor = 0.5 indicates that shutterAngle = 180
          // If shutterAngleFactor = 0.25 indicates that shutterAngle = 90
    
          if (shutterAngleFactor < 0.5)
          {
            for (int i = 0; i < siiMaxSubLayersMinus1; i++)
            {
              m_siiSEISubLayerNumUnitsInSI[i] = m_siiSEISubLayerNumUnitsInSI[siiMaxSubLayersMinus1];
            }
            m_ShutterFilterEnable = false;
            printf("Warning: For the shutterAngle = %d, the blending can't be applied\n", (int)(shutterAngleFactor * 360));
          }
    
          // supports only the case of SFR = HFR / 2
    
          if (m_siiSEISubLayerNumUnitsInSI[siiMaxSubLayersMinus1] < m_siiSEISubLayerNumUnitsInSI[siiMaxSubLayersMinus1 - 1])
          {
    
            checkSubLayerSI = true;
    
          }
          // check shutter interval for all sublayer remains same for LFR pictures
          for (i = 1; i < siiMaxSubLayersMinus1; i++)
          {
            if (m_siiSEISubLayerNumUnitsInSI[0] != m_siiSEISubLayerNumUnitsInSI[i])
            {
    
              checkEqualValuesOfSFR = false;
    
            }
          }
          if (checkSubLayerSI && checkEqualValuesOfSFR)
          {
            setBlendingRatioSII(blending_ratio);
          }
          else
          {
            m_ShutterFilterEnable = false;
          }
        }
        else
        {
          printf("Warning: SII-processing is applied for multiple shutter intervals and number of LFR units should be 2 times of number of HFR units\n");
        }
    #endif
      }
    
        assert(cfg_poSEIPayloadType.values.size() > 1);
    
        assert(cfg_poSEIProcessingOrder.values.size() == cfg_poSEIPayloadType.values.size());
    
    #else
        CHECK(cfg_poSEIPayloadType.values.size() <= 1, "there should be at least 2 SEIPOPayLoadType");
        CHECK(cfg_poSEIProcessingOrder.values.size() != cfg_poSEIPayloadType.values.size(), "the number of SEIPOPayLoadType should be equal to the number of SEIPOProcessingOrder");
        CHECK(cfg_poSEIPrefixFlag.values.size() <= 1, "there should be at least 2 SEIPOPrefixFlag");
    
        m_poSEIPrefixFlag.resize((uint32_t)cfg_poSEIPayloadType.values.size());
    #endif
    
        m_poSEIPayloadType.resize((uint32_t) cfg_poSEIPayloadType.values.size());
        m_poSEIProcessingOrder.resize((uint32_t) cfg_poSEIPayloadType.values.size());
        m_poSEIPrefixByte.resize((uint32_t) cfg_poSEIPayloadType.values.size());
    
        for (uint32_t i = 0; i < (uint32_t) cfg_poSEIPayloadType.values.size(); i++)
    
    #if JVET_AD0386_SEI
          m_poSEIPrefixFlag[i] =      cfg_poSEIPrefixFlag.values[i];
    #endif
    
          m_poSEIPayloadType[i]     = cfg_poSEIPayloadType.values[i];
    
    #if JVET_AD0386_SEI
          if (m_poSEIPayloadType[i] == (uint16_t)SEI::PayloadType::MASTERING_DISPLAY_COLOUR_VOLUME ||
              m_poSEIPayloadType[i] == (uint16_t)SEI::PayloadType::CONTENT_LIGHT_LEVEL_INFO ||
              m_poSEIPayloadType[i] == (uint16_t)SEI::PayloadType::ALTERNATIVE_TRANSFER_CHARACTERISTICS ||
              m_poSEIPayloadType[i] == (uint16_t)SEI::PayloadType::AMBIENT_VIEWING_ENVIRONMENT ||
              m_poSEIPayloadType[i] == (uint16_t)SEI::PayloadType::MULTIVIEW_ACQUISITION_INFO ||
              m_poSEIPayloadType[i] == (uint16_t)SEI::PayloadType::MULTIVIEW_VIEW_POSITION ||
              m_poSEIPayloadType[i] == (uint16_t)SEI::PayloadType::SEI_MANIFEST ||
              m_poSEIPayloadType[i] == (uint16_t)SEI::PayloadType::SEI_PREFIX_INDICATION ||
              m_poSEIPayloadType[i] == (uint16_t)SEI::PayloadType::VDI_SEI_ENVELOPE ||
              m_poSEIPayloadType[i] == (uint16_t)SEI::PayloadType::SEI_PROCESSING_ORDER
            )
          {
    
            CHECK(m_poSEIPrefixFlag[i] == true, "The value of po_sei_prefix_flag shall be equal to 0 when po_sei_payload_type is equal to 137, 144, 147, 148, 179, 180, 200, 201, 208, and 213");
    
          m_poSEIProcessingOrder[i] = (uint16_t) cfg_poSEIProcessingOrder.values[i];
    
    #if JVET_AD0386_SEI
          if (m_poSEIPrefixFlag[i])
    
          if (m_poSEIPayloadType[i] == (uint16_t) SEI::PayloadType::USER_DATA_REGISTERED_ITU_T_T35)
    
            assert(cfg_poSEINumofPrefixByte.values[i] > 0);
    
            m_poSEIPrefixByte[i].resize(cfg_poSEINumofPrefixByte.values[i]);
            for (uint32_t j = 0; j < cfg_poSEINumofPrefixByte.values[i]; j++)
    
              m_poSEIPrefixByte[i][j] = (uint8_t) cfg_poSEIPrefixByte.values[prefixByteIdx++];
    
    #if JVET_AD0386_SEI
          else
          {
            cfg_poSEINumofPrefixByte.values[i] = 0;
          }
    #endif
    
          // Error check, to avoid same PayloadType and same prefix bytes when present with different PayloadOrder
    
    #if JVET_AD0386_SEI
            if (m_poSEIPrefixFlag[i])
            {
                if ((m_poSEIPayloadType[j] == m_poSEIPayloadType[i]) && m_poSEIPrefixFlag[j])
    #else
    
            auto payloadType = SEI::PayloadType(cfg_poSEIPayloadType.values[i]);
    
            if (payloadType == SEI::PayloadType::USER_DATA_REGISTERED_ITU_T_T35)
            {
              for (uint32_t j = 0; j < i; j++)
              {
    
    eeehey's avatar
    eeehey committed
                if (m_poSEIPayloadType[j] == m_poSEIPayloadType[i])
    
                  auto numofPrefixBytes = std::min(cfg_poSEINumofPrefixByte.values[i], cfg_poSEINumofPrefixByte.values[j]);
                  if (std::equal(m_poSEIPrefixByte[i].begin() + 1, m_poSEIPrefixByte[i].begin() + numofPrefixBytes - 1,
                                 m_poSEIPrefixByte[j].begin()))
    
    #if JVET_AD0386_SEI
                    CHECK(m_poSEIProcessingOrder[j] != m_poSEIProcessingOrder[i], "multiple SEI messages with the same po_sei_payload_type and prefix content present when present shall have the same value of po_sei_processing_order");
    #else
    
                    assert(m_poSEIProcessingOrder[j] == m_poSEIProcessingOrder[i]);
    
    #if !JVET_AD0386_SEI
              }
    #endif
            }
    #if JVET_AD0386_SEI
            else
            {
              if (m_poSEIPayloadType[j] == m_poSEIPayloadType[i])
              {
    
                CHECK(m_poSEIProcessingOrder[j] != m_poSEIProcessingOrder[i], "multiple SEI messages with the same po_sei_payload_type without prefix content shall have the same value of po_sei_processing_order");
    
    #if !JVET_AD0386_SEI // error check already done above
    
        // Error check, to avoid all SEI messages share the same PayloadOrder
        assert(!std::equal(cfg_poSEIProcessingOrder.values.begin() + 1, cfg_poSEIProcessingOrder.values.end(),
                           cfg_poSEIProcessingOrder.values.begin()));
    
        assert(m_poSEIPayloadType.size() > 0);
        assert(m_poSEIProcessingOrder.size() == m_poSEIPayloadType.size());
    
      if (m_postFilterHintSEIEnabled)
      {
    
        CHECK(cfg_postFilterHintSEIValues.values.size() <= 0, "The number of filter coefficient shall be greater than zero");
        CHECK(!(cfg_postFilterHintSEIValues.values.size() == ((m_postFilterHintSEIChromaCoeffPresentFlag ? 3 : 1) * m_postFilterHintSEISizeY * m_postFilterHintSEISizeX)), "The number of filter coefficient shall match the matrix size and considering whether filters for chroma is present of not");
    
        m_postFilterHintValues.resize(cfg_postFilterHintSEIValues.values.size());
    
        for (uint32_t i = 0; i < m_postFilterHintValues.size(); i++)
        {
          m_postFilterHintValues[i] = cfg_postFilterHintSEIValues.values[i];
        }
      }
    
    
      if( m_costMode == COST_LOSSLESS_CODING )
      {
    
        bool firstSliceLossless = false;
        if (m_mixedLossyLossless)
        {
          if (m_sliceLosslessArray.size() > 0)
          {
            for (uint32_t i = 0; i < m_sliceLosslessArray.size(); i++)
            {
              if (m_sliceLosslessArray[i] == 0)
              {
                firstSliceLossless = true;
                break;
              }
            }
          }
        }
        else
        {
          firstSliceLossless = true;
        }
    
    Frank Bossen's avatar
    Frank Bossen committed
        if (firstSliceLossless) // if first slice is lossless
    
          m_iQP = LOSSLESS_AND_MIXED_LOSSLESS_RD_COST_TEST_QP - ((m_internalBitDepth[ChannelType::LUMA] - 8) * 6);
    
    Frank Bossen's avatar
    Frank Bossen committed
      m_maxCuWidth = m_maxCuHeight = m_ctuSize;
    
    
      // check validity of input parameters
      if( xCheckParameter() )
      {
        // return check failed
        return false;
      }
    
      // print-out parameters
      xPrintParameter();
    
      return true;
    }
    
    #ifdef _MSC_VER
    // Restore optimizations
    
    #pragma optimize( "", on )
    #endif
    
    
    
    // ====================================================================================================================
    // Private member functions
    // ====================================================================================================================
    
    
    ///< auto determine the profile to use given the other configuration settings. Returns 1 if erred. Can select profile 'NONE'
    
    int EncAppCfg::xAutoDetermineProfile()
    {
    
      const int maxBitDepth =
        std::max(m_internalBitDepth[ChannelType::LUMA], m_internalBitDepth[getLastChannel(m_chromaFormatIdc)]);
    
      m_profile=Profile::NONE;
    
    
      switch (m_chromaFormatIdc)
    
      case ChromaFormat::_400:
      case ChromaFormat::_420:
    
        if (maxBitDepth <= 10)
        {
    
    Frank Bossen's avatar
    Frank Bossen committed
          if (m_level == Level::LEVEL15_5 && m_framesToBeEncoded == 1)
          {
            m_profile = m_maxLayers > 1 ? Profile::MULTILAYER_MAIN_10_STILL_PICTURE : Profile::MAIN_10_STILL_PICTURE;
          }
          else
          {
            m_profile = m_maxLayers > 1 ? Profile::MULTILAYER_MAIN_10 : Profile::MAIN_10;
          }
    
    Frank Bossen's avatar
    Frank Bossen committed
          m_profile = (m_level == Level::LEVEL15_5 && m_framesToBeEncoded == 1) ? Profile::MAIN_12_STILL_PICTURE
                      : (m_intraPeriod == 1)                                    ? Profile::MAIN_12_INTRA
                                                                                : Profile::MAIN_12;
    
        }
        else if (maxBitDepth <= 16)
        {
          // Since there's no 16bit 420 profiles in VVC, we use 444 profiles.
    
    Frank Bossen's avatar
    Frank Bossen committed
          m_profile = (m_level == Level::LEVEL15_5 && m_framesToBeEncoded == 1) ? Profile::MAIN_16_444_STILL_PICTURE
                      : (m_intraPeriod == 1)                                    ? Profile::MAIN_16_444_INTRA
                                                                                : Profile::MAIN_16_444;
    
      case ChromaFormat::_422:
      case ChromaFormat::_444:
    
        if (maxBitDepth <= 10)
        {
    
    Frank Bossen's avatar
    Frank Bossen committed
          if (m_level == Level::LEVEL15_5 && m_framesToBeEncoded == 1)
          {
            m_profile =
              m_maxLayers > 1 ? Profile::MULTILAYER_MAIN_10_444_STILL_PICTURE : Profile::MAIN_10_444_STILL_PICTURE;
          }
          else
          {
            m_profile = m_maxLayers > 1 ? Profile::MULTILAYER_MAIN_10_444 : Profile::MAIN_10_444;
          }
    
    Frank Bossen's avatar
    Frank Bossen committed
          m_profile = (m_level == Level::LEVEL15_5 && m_framesToBeEncoded == 1) ? Profile::MAIN_12_444_STILL_PICTURE
                      : (m_intraPeriod == 1)                                    ? Profile::MAIN_12_444_INTRA
                                                                                : Profile::MAIN_12_444;
    
    Frank Bossen's avatar
    Frank Bossen committed
          m_profile = (m_level == Level::LEVEL15_5 && m_framesToBeEncoded == 1) ? Profile::MAIN_16_444_STILL_PICTURE
                      : (m_intraPeriod == 1)                                    ? Profile::MAIN_16_444_INTRA
                                                                                : Profile::MAIN_16_444;
    
        break;
    
      default: return 1;
      }
    
      if (m_profile == Profile::MAIN_12_INTRA || m_profile == Profile::MAIN_12_444_INTRA || m_profile == Profile::MAIN_16_444_INTRA ||
          m_profile == Profile::MAIN_12_STILL_PICTURE || m_profile == Profile::MAIN_12_444_STILL_PICTURE || m_profile == Profile::MAIN_16_444_STILL_PICTURE)
      {
        m_allRapPicturesFlag = 1;
      }
    
    bool EncAppCfg::xCheckParameter()
    {
      msg( NOTICE, "\n" );
    
      if (m_decodedPictureHashSEIType == HashType::NONE)
    
      {
        msg( DETAILS, "******************************************************************\n");
        msg( DETAILS, "** WARNING: --SEIDecodedPictureHash is now disabled by default. **\n");
        msg( DETAILS, "**          Automatic verification of decoded pictures by a     **\n");
        msg( DETAILS, "**          decoder requires this option to be enabled.         **\n");
        msg( DETAILS, "******************************************************************\n");
      }
      if( m_profile==Profile::NONE )
      {
        msg( DETAILS, "***************************************************************************\n");
        msg( DETAILS, "** WARNING: For conforming bitstreams a valid Profile value must be set! **\n");
        msg( DETAILS, "***************************************************************************\n");
      }
      if( m_level==Level::NONE )
      {
        msg( DETAILS, "***************************************************************************\n");
        msg( DETAILS, "** WARNING: For conforming bitstreams a valid Level value must be set!   **\n");
        msg( DETAILS, "***************************************************************************\n");
      }
    
      bool check_failed = false; /* abort if there is a fatal configuration problem */
    #define xConfirmPara(a,b) check_failed |= confirmPara(a,b)
    
    
      xConfirmPara(m_alfapsIDShift < 0, "ALF APSs shift should be positive");
      xConfirmPara(m_alfapsIDShift + m_maxNumAlfAps > ALF_CTB_MAX_NUM_APS, "The number of ALF APSs should not be more than ALF_CTB_MAX_NUM_APS");
    
      if( m_depQuantEnabledFlag )
      {
        xConfirmPara( !m_useRDOQ || !m_useRDOQTS, "RDOQ and RDOQTS must be equal to 1 if dependent quantization is enabled" );
        xConfirmPara( m_signDataHidingEnabledFlag, "SignHideFlag must be equal to 0 if dependent quantization is enabled" );
      }
    
        const int minCUSize = 1 << m_log2MinCuSize;
    
    Frank Bossen's avatar
    Frank Bossen committed
        xConfirmPara(m_wrapAroundOffset <= m_ctuSize + minCUSize,
                     "Wrap-around offset must be greater than CtbSizeY + MinCbSize");
    
        xConfirmPara(m_wrapAroundOffset > m_sourceWidth, "Wrap-around offset must not be greater than the source picture width");
    
        xConfirmPara( m_wrapAroundOffset % minCUSize != 0, "Wrap-around offset must be an integer multiple of the specified minimum CU size" );
    
      }
    
    
    #if SHARP_LUMA_DELTA_QP && ENABLE_QPA
      xConfirmPara( m_bUsePerceptQPA && m_lumaLevelToDeltaQPMapping.mode >= 2, "QPA and SharpDeltaQP mode 2 cannot be used together" );
      if( m_bUsePerceptQPA && m_lumaLevelToDeltaQPMapping.mode == LUMALVL_TO_DQP_AVG_METHOD )
      {
        msg( WARNING, "*********************************************************************************\n" );
        msg( WARNING, "** WARNING: Applying custom luma-based QPA with activity-based perceptual QPA! **\n" );
        msg( WARNING, "*********************************************************************************\n" );
    
        m_lumaLevelToDeltaQPMapping.mode = LUMALVL_TO_DQP_NUM_MODES; // special QPA mode
      }
    #endif
    
    
    
      xConfirmPara( m_useAMaxBT && !m_SplitConsOverrideEnabledFlag, "AMaxBt can only be used with PartitionConstriantsOverride enabled" );
    
      xConfirmPara(m_bitstreamFileName.empty(), "A bitstream file name must be specified (BitstreamFile)");
    
      xConfirmPara(m_internalBitDepth[ChannelType::CHROMA] != m_internalBitDepth[ChannelType::LUMA],
                   "The internalBitDepth must be the same for luma and chroma");
    
      if (m_profile != Profile::NONE)
    
      {
        xConfirmPara(m_log2MaxTransformSkipBlockSize>=6, "Transform Skip Log2 Max Size must be less or equal to 5 for given profile.");
        xConfirmPara(m_transformSkipRotationEnabledFlag==true, "UseResidualRotation must not be enabled for given profile.");
        xConfirmPara(m_transformSkipContextEnabledFlag==true, "UseSingleSignificanceMapContext must not be enabled for given profile.");
        xConfirmPara(m_highPrecisionOffsetsEnabledFlag==true, "UseHighPrecisionPredictionWeighting must not be enabled for given profile.");
        xConfirmPara(m_cabacBypassAlignmentEnabledFlag, "AlignCABACBeforeBypass cannot be enabled for given profile.");
      }
    
      if (m_profile != Profile::NONE && m_profile != Profile::MAIN_12_444 && m_profile != Profile::MAIN_16_444 && m_profile != Profile::MAIN_12_444_INTRA && m_profile != Profile::MAIN_16_444_INTRA && m_profile != Profile::MAIN_12_444_STILL_PICTURE && m_profile != Profile::MAIN_12_444_STILL_PICTURE && m_profile != Profile::MAIN_16_444_STILL_PICTURE)
      {
    
        xConfirmPara(m_rrcRiceExtensionEnableFlag == true, "Extention of the Golomb-Rice parameter derivation for RRC must not be enabled for given profile.");
    
        xConfirmPara(m_persistentRiceAdaptationEnabledFlag==true, "GolombRiceParameterAdaption must not be enabled for given profile.");
        xConfirmPara(m_extendedPrecisionProcessingFlag==true, "UseExtendedPrecision must not be enabled for given profile.");
    
        xConfirmPara(m_tsrcRicePresentFlag == true, "TSRCRicePresent must not be enabled for given profile.");
    
        xConfirmPara(m_reverseLastSigCoeffEnabledFlag == true, "ReverseLastSigCoeff must not be enabled for given profile.");
    
      xConfirmPara(m_inputBitDepth[ChannelType::LUMA] < 8, "InputBitDepth must be at least 8");
      xConfirmPara(m_inputBitDepth[ChannelType::CHROMA] < 8, "InputBitDepthC must be at least 8");
    
      if ((m_internalBitDepth[ChannelType::LUMA] < m_inputBitDepth[ChannelType::LUMA])
          || (m_internalBitDepth[ChannelType::CHROMA] < m_inputBitDepth[ChannelType::CHROMA]))
    
      {
          msg(WARNING, "*****************************************************************************\n");
          msg(WARNING, "** WARNING: InternalBitDepth is set to the lower value than InputBitDepth! **\n");
    
    Takeshi Tsukuba's avatar
    Takeshi Tsukuba committed
          msg(WARNING, "**          min_qp_prime_ts_minus4 will be clipped to 0 at the low end!    **\n");
    
          msg(WARNING, "*****************************************************************************\n");
      }
    
    
        for (const auto bd: m_internalBitDepth)
    
          xConfirmPara((bd > 8), "Model is not configured to support high enough internal accuracies - enable "
                                 "RExt__HIGH_BIT_DEPTH_SUPPORT to use increased precision internal data types etc...");
    
        for (const auto bd: m_internalBitDepth)
    
          xConfirmPara((bd > 12), "Model is not configured to support high enough internal accuracies - enable "
                                  "RExt__HIGH_BIT_DEPTH_SUPPORT to use increased precision internal data types etc...");
    
      xConfirmPara((m_msbExtendedBitDepth[ChannelType::LUMA] < m_inputBitDepth[ChannelType::LUMA]),
    
    Frank Bossen's avatar
    Frank Bossen committed
                   "MSB-extended bit depth for luma channel (--MSBExtendedBitDepth) must be greater than or equal to input "
                   "bit depth for luma channel (--InputBitDepth)");
    
      xConfirmPara((m_msbExtendedBitDepth[ChannelType::CHROMA] < m_inputBitDepth[ChannelType::CHROMA]),
    
    Frank Bossen's avatar
    Frank Bossen committed
                   "MSB-extended bit depth for chroma channel (--MSBExtendedBitDepthC) must be greater than or equal to "
                   "input bit depth for chroma channel (--InputBitDepthC)");
    
      bool check_sps_range_extension_flag = m_extendedPrecisionProcessingFlag || m_rrcRiceExtensionEnableFlag
                                            || m_persistentRiceAdaptationEnabledFlag || m_tsrcRicePresentFlag;
    
      if (m_internalBitDepth[ChannelType::LUMA] <= 10)
      {
    
        xConfirmPara( (check_sps_range_extension_flag == 1) ,
    
                     "RExt tools (Extended Precision Processing, RRC Rice Extension, Persistent Rice Adaptation and TSRC Rice Extension) must be disabled for BitDepth is less than or equal to 10 (the value of sps_range_extension_flag shall be 0 when BitDepth is less than or equal to 10.)");
    
      xConfirmPara(m_chromaFormatIdc >= ChromaFormat::NUM, "ChromaFormatIDC must be either 400, 420, 422 or 444");
    
      std::string sTempIPCSC="InputColourSpaceConvert must be empty, "+getListOfColourSpaceConverts(true);
      xConfirmPara( m_inputColourSpaceConvert >= NUMBER_INPUT_COLOUR_SPACE_CONVERSIONS,         sTempIPCSC.c_str() );
    
      xConfirmPara(m_inputChromaFormatIDC >= ChromaFormat::NUM, "InputChromaFormatIDC must be either 400, 420, 422 or 444");
    
      xConfirmPara(m_frameRate.getFloatVal() <= 0, "Frame rate cannot be 0 or less");
    
      xConfirmPara( m_framesToBeEncoded <= 0,                                                   "Total Number Of Frames encoded must be more than 0" );
      xConfirmPara( m_framesToBeEncoded < m_switchPOC,                                          "debug POC out of range" );
    
    
    Frank Bossen's avatar
    Frank Bossen committed
      xConfirmPara(m_gopSize < 1, "GOP Size must be greater or equal to 1");
      xConfirmPara(m_gopSize > 1 && m_gopSize % 2, "GOP Size must be a multiple of 2, if GOP Size is greater than 1");
      xConfirmPara((m_intraPeriod > 0 && m_intraPeriod < m_gopSize) || m_intraPeriod == 0,
                   "Intra period must be more than GOP size, or -1 , not 0");
    
      xConfirmPara( m_drapPeriod < 0,                                                           "DRAP period must be greater or equal to 0" );
    
      xConfirmPara( m_edrapPeriod < 0,                                                          "EDRAP period must be greater or equal to 0" );
    
    Frank Bossen's avatar
    Frank Bossen committed
      xConfirmPara(m_intraRefreshType < 0 || m_intraRefreshType > 3,
                   "Decoding Refresh Type must be comprised between 0 and 3 included");
    
        if (!m_frameFieldInfoSEIEnabled)
        {
          msg( WARNING, "*************************************************************************************\n");
          msg( WARNING, "** WARNING: Frame field information SEI should be enabled for field coding!        **\n");
          msg( WARNING, "*************************************************************************************\n");
        }
    
      if ( m_pictureTimingSEIEnabled && (!m_bufferingPeriodSEIEnabled))
      {
        msg( WARNING, "****************************************************************************\n");
        msg( WARNING, "** WARNING: Picture Timing SEI requires Buffering Period SEI. Disabling.  **\n");
        msg( WARNING, "****************************************************************************\n");
        m_pictureTimingSEIEnabled = false;
      }
    
      xConfirmPara(m_bufferingPeriodSEIEnabled && m_rcCpbSize == 0,
                   "RCCpbSize must be greater than zero, when buffering period SEI is enabled");
    
      xConfirmPara (m_log2MaxTransformSkipBlockSize < 2, "Transform Skip Log2 Max Size must be at least 2 (4x4)");
    
    
      xConfirmPara ( m_onePictureOnlyConstraintFlag && m_framesToBeEncoded!=1, "When onePictureOnlyConstraintFlag is true, the number of frames to be encoded must be 1" );