Skip to content
Snippets Groups Projects
EncAppCfg.cpp 361 KiB
Newer Older
  • Learn to ignore specific revisions
  • Frank Bossen's avatar
    Frank Bossen committed
          {
            m_intraPeriod = m_gdrPeriod;
          }
    
    Frank Bossen's avatar
    Frank Bossen committed
      if (m_gopSize == 16)
    
      {
        if ((m_GOPList[0].m_POC == 16 && m_GOPList[0].m_temporalId == 0 )
            && (m_GOPList[1].m_POC == 8 && m_GOPList[1].m_temporalId == 1 )
            && (m_GOPList[2].m_POC == 4 && m_GOPList[2].m_temporalId == 2 )
            && (m_GOPList[3].m_POC == 2 && m_GOPList[3].m_temporalId == 3 )
            && (m_GOPList[4].m_POC == 1 && m_GOPList[4].m_temporalId == 4 )
            && (m_GOPList[5].m_POC == 3 && m_GOPList[5].m_temporalId == 4 )
            && (m_GOPList[6].m_POC == 6 && m_GOPList[6].m_temporalId == 3 )
            && (m_GOPList[7].m_POC == 5 && m_GOPList[7].m_temporalId == 4 )
            && (m_GOPList[8].m_POC == 7 && m_GOPList[8].m_temporalId == 4 )
            && (m_GOPList[9].m_POC == 12 && m_GOPList[9].m_temporalId == 2 )
            && (m_GOPList[10].m_POC == 10 && m_GOPList[10].m_temporalId == 3 )
            && (m_GOPList[11].m_POC == 9 && m_GOPList[11].m_temporalId == 4 )
            && (m_GOPList[12].m_POC == 11 && m_GOPList[12].m_temporalId == 4 )
            && (m_GOPList[13].m_POC == 14 && m_GOPList[13].m_temporalId == 3 )
            && (m_GOPList[14].m_POC == 13 && m_GOPList[14].m_temporalId == 4 )
            && (m_GOPList[15].m_POC == 15 && m_GOPList[15].m_temporalId == 4 ))
        {
          m_bpDeltasGOPStructure = true;
        }
      }
    
    Frank Bossen's avatar
    Frank Bossen committed
      else if (m_gopSize == 8)
    
      {
        if ((m_GOPList[0].m_POC == 8 && m_GOPList[0].m_temporalId == 0 )
            && (m_GOPList[1].m_POC == 4 && m_GOPList[1].m_temporalId == 1 )
            && (m_GOPList[2].m_POC == 2 && m_GOPList[2].m_temporalId == 2 )
            && (m_GOPList[3].m_POC == 1 && m_GOPList[3].m_temporalId == 3 )
            && (m_GOPList[4].m_POC == 3 && m_GOPList[4].m_temporalId == 3 )
            && (m_GOPList[5].m_POC == 6 && m_GOPList[5].m_temporalId == 2 )
            && (m_GOPList[6].m_POC == 5 && m_GOPList[6].m_temporalId == 3 )
            && (m_GOPList[7].m_POC == 7 && m_GOPList[7].m_temporalId == 3 ))
        {
          m_bpDeltasGOPStructure = true;
        }
      }
      else
      {
        m_bpDeltasGOPStructure = false;
      }
    
    Hendry's avatar
    Hendry committed
      for (int i = 0; m_GOPList[i].m_POC != -1 && i < MAX_GOP + 1; i++)
      {
        m_RPLList0[i].m_POC = m_RPLList1[i].m_POC = m_GOPList[i].m_POC;
        m_RPLList0[i].m_temporalId = m_RPLList1[i].m_temporalId = m_GOPList[i].m_temporalId;
        m_RPLList0[i].m_refPic = m_RPLList1[i].m_refPic = m_GOPList[i].m_refPic;
        m_RPLList0[i].m_sliceType = m_RPLList1[i].m_sliceType = m_GOPList[i].m_sliceType;
        m_RPLList0[i].m_isEncoded = m_RPLList1[i].m_isEncoded = m_GOPList[i].m_isEncoded;
    
        m_RPLList0[i].m_numRefPicsActive = m_GOPList[i].m_numRefPicsActive0;
        m_RPLList1[i].m_numRefPicsActive = m_GOPList[i].m_numRefPicsActive1;
        m_RPLList0[i].m_numRefPics = m_GOPList[i].m_numRefPics0;
        m_RPLList1[i].m_numRefPics = m_GOPList[i].m_numRefPics1;
    
    Frank Bossen's avatar
    Frank Bossen committed
        m_RPLList0[i].m_ltrpInSliceHeaderFlag = m_GOPList[i].m_ltrpInSliceHeaderFlag;
        m_RPLList1[i].m_ltrpInSliceHeaderFlag = m_GOPList[i].m_ltrpInSliceHeaderFlag;
    
    Hendry's avatar
    Hendry committed
        for (int j = 0; j < m_GOPList[i].m_numRefPics0; j++)
          m_RPLList0[i].m_deltaRefPics[j] = m_GOPList[i].m_deltaRefPics0[j];
        for (int j = 0; j < m_GOPList[i].m_numRefPics1; j++)
          m_RPLList1[i].m_deltaRefPics[j] = m_GOPList[i].m_deltaRefPics1[j];
      }
    
    
      if (m_compositeRefEnabled)
    
    Frank Bossen's avatar
    Frank Bossen committed
        for (int i = 0; i < m_gopSize; i++)
    
    Hendry's avatar
    Hendry committed
          m_RPLList0[i].m_POC *= 2;
          m_RPLList1[i].m_POC *= 2;
          for (int j = 0; j < m_RPLList0[i].m_numRefPics; j++)
          {
            m_RPLList0[i].m_deltaRefPics[j] *= 2;
          }
          for (int j = 0; j < m_RPLList1[i].m_numRefPics; j++)
          {
            m_RPLList1[i].m_deltaRefPics[j] *= 2;
          }
    
      for (list<const char*>::const_iterator it = argv_unhandled.begin(); it != argv_unhandled.end(); it++)
      {
        msg( ERROR, "Unhandled argument ignored: `%s'\n", *it);
      }
    
      if (argc == 1 || do_help)
      {
        /* argc == 1: no options have been specified */
        po::doHelp(cout, opts);
        return false;
      }
    
      if (err.is_errored)
      {
        if (!warnUnknowParameter)
        {
          /* error report has already been printed on stderr */
          return false;
        }
      }
    
      g_verbosity = MsgLevel( m_verbosity );
    
    
      /*
       * Set any derived parameters
       */
    #if EXTENSION_360_VIDEO
    
      m_inputFileWidth = m_sourceWidth;
      m_inputFileHeight = m_sourceHeight;
    
    Frank Bossen's avatar
    Frank Bossen committed
      m_ext360.setMaxCUInfo(m_ctuSize, 1 << MIN_CU_LOG2);
    
    #endif
    
      if (!inputPathPrefix.empty() && inputPathPrefix.back() != '/' && inputPathPrefix.back() != '\\' )
      {
        inputPathPrefix += "/";
      }
      m_inputFileName   = inputPathPrefix + m_inputFileName;
    
      if (m_firstValidFrame < 0)
      {
    
    Frank Bossen's avatar
    Frank Bossen committed
        m_firstValidFrame = m_frameSkip;
    
      }
      if (m_lastValidFrame < 0)
      {
        m_lastValidFrame = m_firstValidFrame + m_framesToBeEncoded - 1;
      }
    
    
      if( m_temporalSubsampleRatio < 1)
      {
        EXIT ( "Error: TemporalSubsampleRatio must be greater than 0" );
      }
    
    
      m_framesToBeEncoded = ( m_framesToBeEncoded + m_temporalSubsampleRatio - 1 ) / m_temporalSubsampleRatio;
      m_adIntraLambdaModifier = cfg_adIntraLambdaModifier.values;
      if(m_isField)
      {
        //Frame height
    
        m_iSourceHeightOrg = m_sourceHeight;
    
        m_sourceHeight = m_sourceHeight >> 1;
    
        //number of fields to encode
        m_framesToBeEncoded *= 2;
      }
    
    Mitsuru Katsumata's avatar
    Mitsuru Katsumata committed
        CHECK( m_numSubPics > MAX_NUM_SUB_PICS || m_numSubPics < 1, "Number of subpicture must be within 1 to 2^16" )
        if (!m_subPicSameSizeFlag)
        {
          CHECK(cfg_subPicCtuTopLeftX.values.size() != m_numSubPics, "Number of SubPicCtuTopLeftX values must be equal to NumSubPics");
          CHECK(cfg_subPicCtuTopLeftY.values.size() != m_numSubPics, "Number of SubPicCtuTopLeftY values must be equal to NumSubPics");
          CHECK(cfg_subPicWidth.values.size() != m_numSubPics, "Number of SubPicWidth values must be equal to NumSubPics");
          CHECK(cfg_subPicHeight.values.size() != m_numSubPics, "Number of SubPicHeight values must be equal to NumSubPics");
        }
        else
        {
          CHECK(cfg_subPicCtuTopLeftX.values.size() != 0, "Number of SubPicCtuTopLeftX values must be equal to 0");
          CHECK(cfg_subPicCtuTopLeftY.values.size() != 0, "Number of SubPicCtuTopLeftY values must be equal to 0");
          CHECK(cfg_subPicWidth.values.size() != 1, "Number of SubPicWidth values must be equal to 1");
          CHECK(cfg_subPicHeight.values.size() != 1, "Number of SubPicHeight values must be equal to 1");
        }
    
        CHECK( cfg_subPicTreatedAsPicFlag.values.size() != m_numSubPics, "Number of SubPicTreatedAsPicFlag values must be equal to NumSubPics");
        CHECK( cfg_loopFilterAcrossSubpicEnabledFlag.values.size() != m_numSubPics, "Number of LoopFilterAcrossSubpicEnabledFlag values must be equal to NumSubPics");
        if (m_subPicIdMappingExplicitlySignalledFlag)
        {
          CHECK( cfg_subPicId.values.size() != m_numSubPics, "Number of SubPicId values must be equal to NumSubPics");
        }
    
        m_subPicCtuTopLeftX                 = cfg_subPicCtuTopLeftX.values;
        m_subPicCtuTopLeftY                 = cfg_subPicCtuTopLeftY.values;
        m_subPicWidth                       = cfg_subPicWidth.values;
        m_subPicHeight                      = cfg_subPicHeight.values;
        m_subPicTreatedAsPicFlag            = cfg_subPicTreatedAsPicFlag.values;
        m_loopFilterAcrossSubpicEnabledFlag = cfg_loopFilterAcrossSubpicEnabledFlag.values;
    
        if (m_subPicIdMappingExplicitlySignalledFlag)
    
          for (int i=0; i < m_numSubPics; i++)
          {
            m_subPicId[i]                   = cfg_subPicId.values[i];
          }
    
    Frank Bossen's avatar
    Frank Bossen committed
        uint32_t tmpWidthVal  = (m_sourceWidth + m_ctuSize - 1) / m_ctuSize;
        uint32_t tmpHeightVal = (m_sourceHeight + m_ctuSize - 1) / m_ctuSize;
    
    Mitsuru Katsumata's avatar
    Mitsuru Katsumata committed
        if (!m_subPicSameSizeFlag)
        {
          for (int i = 0; i < m_numSubPics; i++)
          {
            CHECK(m_subPicCtuTopLeftX[i] + m_subPicWidth[i] > tmpWidthVal, "Subpicture must not exceed picture boundary");
            CHECK(m_subPicCtuTopLeftY[i] + m_subPicHeight[i] > tmpHeightVal, "Subpicture must not exceed picture boundary");
          }
        }
        else
        {
          uint32_t numSubpicCols = tmpWidthVal / m_subPicWidth[0];
    
          CHECK(tmpWidthVal % m_subPicWidth[0] != 0, "sps_subpic_width_minus1[0] is invalid.");
          CHECK(tmpHeightVal % m_subPicHeight[0] != 0, "sps_subpic_height_minus1[0] is invalid.");
    
    Mitsuru Katsumata's avatar
    Mitsuru Katsumata committed
          CHECK(numSubpicCols * (tmpHeightVal / m_subPicHeight[0]) != m_numSubPics, "when sps_subpic_same_size_flag is equal to, sps_num_subpics_minus1 is invalid");
        }
    
        // automatically determine subpicture ID lenght in case it is not specified
        if (m_subPicIdLen == 0)
    
          if (m_subPicIdMappingExplicitlySignalledFlag)
          {
            // use the heighest specified ID
            auto maxIdVal = std::max_element(m_subPicId.begin(),m_subPicId.end());
            m_subPicIdLen = ceilLog2(*maxIdVal);
          }
          else
    
            // use the number of subpictures
            m_subPicIdLen = ceilLog2(m_numSubPics);
    
    
        CHECK( m_subPicIdLen > 16, "SubPicIdLen must not exceed 16 bits" );
    
        CHECK(m_resChangeInClvsEnabled, "resolution change in CLVS and subpictures cannot be enabled together");
    
        if (m_sourceWidth <= 8)
    
          CHECK(m_numVerVirtualBoundaries != 0, "The number of vertical virtual boundaries shall be 0 when the picture width is less than or equal to 8");
    
    
        if (m_sourceHeight <= 8)
    
          CHECK(m_numHorVirtualBoundaries != 0, "The number of horizontal virtual boundaries shall be 0 when the picture height is less than or equal to 8");
      }
    
    
      if (m_cfgSubpictureLevelInfoSEI.m_enabled)
      {
        CHECK (m_numSubPics != m_cfgSubpictureLevelInfoSEI.m_numSubpictures, "NumSubPics must be equal to SEISubpicLevelInfoNumSubpics" );
    
    Zhipin Deng's avatar
    Zhipin Deng committed
        CHECK (m_cfgSubpictureLevelInfoSEI.m_sliMaxSublayers != m_maxSublayers, "SEISubpicLevelInfoMaxSublayers must be equal to vps_max_sublayers");
        if (m_cfgSubpictureLevelInfoSEI.m_sliSublayerInfoPresentFlag)
        {
          CHECK(cfg_sliRefLevels.values.size() < m_maxSublayers, "when sliSublayerInfoPresentFlag = 1, the number of reference levels must be greater than or equal to sublayers");
        }
    
        if (m_cfgSubpictureLevelInfoSEI.m_explicitFraction)
        {
          m_cfgSubpictureLevelInfoSEI.m_fractions = cfg_sliFractions.values;
          m_cfgSubpictureLevelInfoSEI.m_refLevels = cfg_sliRefLevels.values;
    
    Zhipin Deng's avatar
    Zhipin Deng committed
          if (m_cfgSubpictureLevelInfoSEI.m_sliSublayerInfoPresentFlag)
          {
            CHECK((int)cfg_sliRefLevels.values.size() / m_maxSublayers * m_cfgSubpictureLevelInfoSEI.m_numSubpictures * m_cfgSubpictureLevelInfoSEI.m_sliMaxSublayers != cfg_sliFractions.values.size(),
              "when sliSublayerInfoPresentFlag = 1, the number  of subpicture level fractions must be equal to the numer of subpictures times the number of reference levels times the number of sublayers");
          }
          else
          {
            CHECK((int)cfg_sliRefLevels.values.size() * m_cfgSubpictureLevelInfoSEI.m_numSubpictures != cfg_sliFractions.values.size(), "when sliSublayerInfoPresentFlag = 0, the number  of subpicture level fractions must be equal to the numer of subpictures times the number of reference levels");
          }
    
        m_cfgSubpictureLevelInfoSEI.m_nonSubpicLayersFraction = cfg_sliNonSubpicLayersFractions.values;
        if (m_cfgSubpictureLevelInfoSEI.m_sliSublayerInfoPresentFlag)
        {
          CHECK((int)cfg_sliNonSubpicLayersFractions.values.size() != ( cfg_sliRefLevels.values.size() * m_cfgSubpictureLevelInfoSEI.m_numSubpictures ),
            "when sliSublayerInfoPresentFlag = 1, the number  of non-subpicture level fractions must be equal to the numer of reference levels times the number of sublayers");
        }
        else
        {
          CHECK((int)cfg_sliNonSubpicLayersFractions.values.size() != ( cfg_sliRefLevels.values.size() ),
            "when sliSublayerInfoPresentFlag = 0, the number  of non-subpicture level fractions must be equal to the numer of reference levels");
        }
    
      if (m_costMode != COST_LOSSLESS_CODING && m_mixedLossyLossless)
    
        m_mixedLossyLossless = 0;
        msg(WARNING, "*************************************************************************\n");
        msg(WARNING, "* Mixed lossy lossles coding cannot enable in lossy costMode *\n");
        msg(WARNING, "* Forcely disabled  m_mixedLossyLossless *\n");
        msg(WARNING, "*************************************************************************\n");
    
      if (!m_mixedLossyLossless && cfgSliceLosslessArray.values.size() > 0)
    
        msg(WARNING, "*************************************************************************\n");
        msg(WARNING, "* Mixed lossy lossles coding is not enabled *\n");
        msg(WARNING, "* ignoring the value of SliceLosslessArray *\n");
        msg(WARNING, "*************************************************************************\n");
      }
    
      if (m_costMode == COST_LOSSLESS_CODING && m_mixedLossyLossless)
      {
        m_sliceLosslessArray.resize(cfgSliceLosslessArray.values.size());
    
        for (uint32_t i = 0; i < cfgSliceLosslessArray.values.size(); i++)
        {
          m_sliceLosslessArray[i] = cfgSliceLosslessArray.values[i];
        }
      }
    
    
      if( m_picPartitionFlag )
    
      {
        // store tile column widths
        m_tileColumnWidth.resize(cfgTileColumnWidth.values.size());
        for(uint32_t i=0; i<cfgTileColumnWidth.values.size(); i++)
        {
          m_tileColumnWidth[i]=cfgTileColumnWidth.values[i];
        }
    
        // store tile row heights
        m_tileRowHeight.resize(cfgTileRowHeight.values.size());
        for(uint32_t i=0; i<cfgTileRowHeight.values.size(); i++)
        {
          m_tileRowHeight[i]=cfgTileRowHeight.values[i];
        }
    
        // store rectangular slice positions
    
        if( !m_rasterSliceFlag )
    
        {
          m_rectSlicePos.resize(cfgRectSlicePos.values.size());
          for(uint32_t i=0; i<cfgRectSlicePos.values.size(); i++)
          {
            m_rectSlicePos[i]=cfgRectSlicePos.values[i];
          }
        }
    
        // store raster-scan slice sizes
    
        {
          m_rasterSliceSize.resize(cfgRasterSliceSize.values.size());
          for(uint32_t i=0; i<cfgRasterSliceSize.values.size(); i++)
          {
            m_rasterSliceSize[i]=cfgRasterSliceSize.values[i];
          }
        }
      }
    
      {
        m_tileColumnWidth.clear();
        m_tileRowHeight.clear();
        m_rectSlicePos.clear();
        m_rasterSliceSize.clear();
        m_rectSliceFixedWidth = 0;
        m_rectSliceFixedHeight = 0;
      }
    
    
      m_numSubProfile = (uint8_t) cfg_SubProfile.values.size();
      m_subProfile.resize(m_numSubProfile);
      for (uint8_t i = 0; i < m_numSubProfile; ++i)
      {
        m_subProfile[i] = cfg_SubProfile.values[i];
      }
    
      /* rules for input, output and internal bitdepths as per help text */
    
    Frank Bossen's avatar
    Frank Bossen committed
      if (m_msbExtendedBitDepth[CHANNEL_TYPE_LUMA] == 0)
    
    Frank Bossen's avatar
    Frank Bossen committed
        m_msbExtendedBitDepth[CHANNEL_TYPE_LUMA] = m_inputBitDepth[CHANNEL_TYPE_LUMA];
    
    Frank Bossen's avatar
    Frank Bossen committed
      if (m_msbExtendedBitDepth[CHANNEL_TYPE_CHROMA] == 0)
    
    Frank Bossen's avatar
    Frank Bossen committed
        m_msbExtendedBitDepth[CHANNEL_TYPE_CHROMA] = m_msbExtendedBitDepth[CHANNEL_TYPE_LUMA];
    
    Frank Bossen's avatar
    Frank Bossen committed
        m_internalBitDepth[CHANNEL_TYPE_LUMA] = m_msbExtendedBitDepth[CHANNEL_TYPE_LUMA];
    
      }
        m_internalBitDepth   [CHANNEL_TYPE_CHROMA] = m_internalBitDepth   [CHANNEL_TYPE_LUMA  ];
      if (m_inputBitDepth      [CHANNEL_TYPE_CHROMA] == 0)
      {
        m_inputBitDepth      [CHANNEL_TYPE_CHROMA] = m_inputBitDepth      [CHANNEL_TYPE_LUMA  ];
      }
      if (m_outputBitDepth     [CHANNEL_TYPE_LUMA  ] == 0)
      {
        m_outputBitDepth     [CHANNEL_TYPE_LUMA  ] = m_internalBitDepth   [CHANNEL_TYPE_LUMA  ];
      }
      if (m_outputBitDepth     [CHANNEL_TYPE_CHROMA] == 0)
      {
        m_outputBitDepth     [CHANNEL_TYPE_CHROMA] = m_outputBitDepth     [CHANNEL_TYPE_LUMA  ];
      }
    
    
    Frank Bossen's avatar
    Frank Bossen committed
      m_inputChromaFormatIDC = numberToChromaFormat(tmpInputChromaFormat);
      m_chromaFormatIDC = ((tmpChromaFormat == 0) ? (m_inputChromaFormatIDC) : (numberToChromaFormat(tmpChromaFormat)));
    
    #if EXTENSION_360_VIDEO
      m_ext360.processOptions(ext360CfgContext);
    #endif
    
    
      if (isY4mFileExt(m_inputFileName))
      {
        int          width = 0, height = 0, frameRate = 0, inputBitDepth = 0;
        ChromaFormat chromaFormat = CHROMA_420;
        VideoIOYuv   inputFile;
        inputFile.parseY4mFileHeader(m_inputFileName, width, height, frameRate, inputBitDepth, chromaFormat);
    
    Frank Bossen's avatar
    Frank Bossen committed
        if (width != m_sourceWidth || height != m_sourceHeight || frameRate != m_frameRate
    
            || inputBitDepth != m_inputBitDepth[0] || chromaFormat != m_chromaFormatIDC)
        {
          msg(WARNING, "\nWarning: Y4M file info is different from input setting. Using the info from Y4M file\n");
          m_sourceWidth            = width;
          m_sourceHeight           = height;
    
    Frank Bossen's avatar
    Frank Bossen committed
          m_frameRate              = frameRate;
    
          m_inputBitDepth[0]       = inputBitDepth;
          m_inputBitDepth[1]       = inputBitDepth;
          m_chromaFormatIDC        = chromaFormat;
    
    Frank Bossen's avatar
    Frank Bossen committed
          m_msbExtendedBitDepth[0] = m_inputBitDepth[0];
          m_msbExtendedBitDepth[1] = m_inputBitDepth[1];
    
      CHECK( !( tmpWeightedPredictionMethod >= 0 && tmpWeightedPredictionMethod <= WP_PER_PICTURE_WITH_HISTOGRAM_AND_PER_COMPONENT_AND_CLIPPING_AND_EXTENSION ), "Error in cfg" );
      m_weightedPredictionMethod = WeightedPredictionMethod(tmpWeightedPredictionMethod);
    
      CHECK( tmpFastInterSearchMode<0 || tmpFastInterSearchMode>FASTINTERSEARCH_MODE3, "Error in cfg" );
      m_fastInterSearchMode = FastInterSearchMode(tmpFastInterSearchMode);
    
      CHECK( tmpMotionEstimationSearchMethod < 0 || tmpMotionEstimationSearchMethod >= MESEARCH_NUMBER_OF_METHODS, "Error in cfg" );
      m_motionEstimationSearchMethod=MESearchMethod(tmpMotionEstimationSearchMethod);
    
    
      if (extendedProfile == ExtendedProfileName::AUTO)
      {
        if (xAutoDetermineProfile())
        {
          EXIT( "Unable to determine profile from configured settings");
        }
      }
    
        switch (extendedProfile)
        {
    
        case ExtendedProfileName::NONE: m_profile = Profile::NONE; break;
        case ExtendedProfileName::MAIN_10: m_profile = Profile::MAIN_10; break;
        case ExtendedProfileName::MAIN_10_444: m_profile = Profile::MAIN_10_444; break;
        case ExtendedProfileName::MAIN_10_STILL_PICTURE: m_profile = Profile::MAIN_10_STILL_PICTURE; break;
        case ExtendedProfileName::MAIN_10_444_STILL_PICTURE: m_profile = Profile::MAIN_10_444_STILL_PICTURE; break;
        case ExtendedProfileName::MULTILAYER_MAIN_10: m_profile = Profile::MULTILAYER_MAIN_10; break;
        case ExtendedProfileName::MULTILAYER_MAIN_10_444: m_profile = Profile::MULTILAYER_MAIN_10_444; break;
        case ExtendedProfileName::MULTILAYER_MAIN_10_STILL_PICTURE:
          m_profile = Profile::MULTILAYER_MAIN_10_STILL_PICTURE;
          break;
        case ExtendedProfileName::MULTILAYER_MAIN_10_444_STILL_PICTURE:
          m_profile = Profile::MULTILAYER_MAIN_10_444_STILL_PICTURE;
          break;
    
        case ExtendedProfileName::MAIN_12:
          m_profile = Profile::MAIN_12; break;
        case ExtendedProfileName::MAIN_12_444:
          m_profile = Profile::MAIN_12_444; break;
        case ExtendedProfileName::MAIN_16_444:
          m_profile = Profile::MAIN_16_444; break;
        case ExtendedProfileName::MAIN_12_INTRA:
          m_profile = Profile::MAIN_12_INTRA; break;
        case ExtendedProfileName::MAIN_12_444_INTRA:
          m_profile = Profile::MAIN_12_444_INTRA; break;
        case ExtendedProfileName::MAIN_16_444_INTRA:
          m_profile = Profile::MAIN_16_444_INTRA; break;
        case ExtendedProfileName::MAIN_12_STILL_PICTURE:
          m_profile = Profile::MAIN_12_STILL_PICTURE; break;
        case ExtendedProfileName::MAIN_12_444_STILL_PICTURE:
          m_profile = Profile::MAIN_12_444_STILL_PICTURE; break;
        case ExtendedProfileName::MAIN_16_444_STILL_PICTURE:
          m_profile = Profile::MAIN_16_444_STILL_PICTURE; break;
    
        default: EXIT("Unable to determine profile from configured settings"); break;
    
      {
        m_chromaFormatConstraint       = (tmpConstraintChromaFormat == 0) ? m_chromaFormatIDC : numberToChromaFormat(tmpConstraintChromaFormat);
        if (m_bitDepthConstraint == 0)
        {
    
          if (m_profile != Profile::NONE)
          {
            const ProfileFeatures *features = ProfileFeatures::getProfileFeatures(m_profile);
            CHECK(features->profile != m_profile, "Profile not found");
            m_bitDepthConstraint = features->maxBitDepth;
          }
    
          else // m_profile == Profile::NONE
          {
    
            m_bitDepthConstraint = 16; // max value - unconstrained.
    
        CHECK(m_bitDepthConstraint < m_internalBitDepth[CHANNEL_TYPE_LUMA], "MaxBitDepthConstraint setting does not allow the specified luma bit depth to be coded.");
        CHECK(m_bitDepthConstraint < m_internalBitDepth[CHANNEL_TYPE_CHROMA], "MaxBitDepthConstraint setting does not allow the specified chroma bit depth to be coded.");
        CHECK(m_chromaFormatConstraint < m_chromaFormatIDC, "MaxChromaFormatConstraint setting does not allow the specified chroma format to be coded.");
        CHECK(m_chromaFormatConstraint >= NUM_CHROMA_FORMAT, "Bad value given for MaxChromaFormatConstraint setting.")
        CHECK(m_bitDepthConstraint < 8 || m_bitDepthConstraint>16, "MaxBitDepthConstraint setting must be in the range 8 to 16 (inclusive)");
    
    
      m_inputColourSpaceConvert = stringToInputColourSpaceConvert(inputColourSpaceConvert, true);
    
      m_rgbFormat = (m_inputColourSpaceConvert == IPCOLOURSPACE_RGBtoGBR && m_chromaFormatIDC == CHROMA_444) ? true : false;
    
      if (m_profile == Profile::MAIN_12 || m_profile == Profile::MAIN_12_INTRA || m_profile == Profile::MAIN_12_STILL_PICTURE ||
          m_profile == Profile::MAIN_12_444 || m_profile == Profile::MAIN_12_444_INTRA || m_profile == Profile::MAIN_12_444_STILL_PICTURE ||
          m_profile == Profile::MAIN_16_444 || m_profile == Profile::MAIN_16_444_INTRA || m_profile == Profile::MAIN_16_444_STILL_PICTURE)
      {
        m_gciPresentFlag = true;
      }
      if (m_profile == Profile::MAIN_12_INTRA || m_profile == Profile::MAIN_12_444_INTRA || m_profile == Profile::MAIN_16_444_INTRA)
      {
    
    Frank Bossen's avatar
    Frank Bossen committed
        CHECK(m_intraPeriod != 1, "IntraPeriod setting must be 1 for Intra profiles")
    
      }
      if (m_profile == Profile::MULTILAYER_MAIN_10_STILL_PICTURE || m_profile == Profile::MAIN_10_STILL_PICTURE ||
          m_profile == Profile::MAIN_12_STILL_PICTURE || m_profile == Profile::MAIN_12_444_STILL_PICTURE || m_profile == Profile::MAIN_16_444_STILL_PICTURE)
      {
        CHECK(m_framesToBeEncoded != 1, "FramesToBeEncoded setting must be 1 for Still Picture profiles")
      }
    
      // Picture width and height must be multiples of 8 and minCuSize
      const int minResolutionMultiple = std::max(8, 1 << m_log2MinCuSize);
    
      switch (m_conformanceWindowMode)
      {
      case 0:
        {
          // no conformance or padding
          m_confWinLeft = m_confWinRight = m_confWinTop = m_confWinBottom = 0;
    
          m_sourcePadding[1] = m_sourcePadding[0] = 0;
    
          if (m_sourceWidth % minResolutionMultiple)
    
            m_sourcePadding[0] = m_confWinRight  = ((m_sourceWidth / minResolutionMultiple) + 1) * minResolutionMultiple - m_sourceWidth;
            m_sourceWidth  += m_confWinRight;
    
          if (m_sourceHeight % minResolutionMultiple)
    
            m_sourcePadding[1] = m_confWinBottom = ((m_sourceHeight / minResolutionMultiple) + 1) * minResolutionMultiple - m_sourceHeight;
            m_sourceHeight += m_confWinBottom;
    
            if ( m_isField )
            {
              m_iSourceHeightOrg += m_confWinBottom << 1;
    
              m_sourcePadding[1] = m_confWinBottom << 1;
    
          if (m_sourcePadding[0] % SPS::getWinUnitX(m_chromaFormatIDC) != 0)
    
          {
            EXIT( "Error: picture width is not an integer multiple of the specified chroma subsampling");
          }
    
          if (m_sourcePadding[1] % SPS::getWinUnitY(m_chromaFormatIDC) != 0)
    
          {
            EXIT( "Error: picture height is not an integer multiple of the specified chroma subsampling");
          }
    
          if (m_sourcePadding[0])
          {
            msg( INFO, "Info: Conformance window automatically enabled. Adding %i lumal pel horizontally\n", m_sourcePadding[0]);
          }
          if (m_sourcePadding[1])
          {
            msg( INFO, "Info: Conformance window automatically enabled. Adding %i lumal pel vertically\n", m_sourcePadding[1]);
          }
    
          m_sourceWidth  += m_sourcePadding[0];
          m_sourceHeight += m_sourcePadding[1];
          m_confWinRight  = m_sourcePadding[0];
          m_confWinBottom = m_sourcePadding[1];
    
          break;
        }
      case 3:
        {
          // conformance
          if ((m_confWinLeft == 0) && (m_confWinRight == 0) && (m_confWinTop == 0) && (m_confWinBottom == 0))
          {
            msg( ERROR, "Warning: Conformance window enabled, but all conformance window parameters set to zero\n");
          }
    
          if ((m_sourcePadding[1] != 0) || (m_sourcePadding[0]!=0))
    
          {
            msg( ERROR, "Warning: Conformance window enabled, padding parameters will be ignored\n");
          }
    
          m_sourcePadding[1] = m_sourcePadding[0] = 0;
    
      CHECK(((m_sourceWidth% minResolutionMultiple) || (m_sourceHeight % minResolutionMultiple)), "Picture width or height (after padding) is not a multiple of 8 or minCuSize, please use ConformanceWindowMode=1 for automatic adjustment or ConformanceWindowMode=2 to specify padding manually!!");
    
      if( m_conformanceWindowMode > 0 && m_subPicInfoPresentFlag )
      {
        for(int i = 0; i < m_numSubPics; i++)
        {
    
    Frank Bossen's avatar
    Frank Bossen committed
          CHECK((m_subPicCtuTopLeftX[i] * m_ctuSize)
                  >= (m_sourceWidth - m_confWinRight * SPS::getWinUnitX(m_chromaFormatIDC)),
                "No subpicture can be located completely outside of the conformance cropping window");
          CHECK(((m_subPicCtuTopLeftX[i] + m_subPicWidth[i]) * m_ctuSize)
                  <= (m_confWinLeft * SPS::getWinUnitX(m_chromaFormatIDC)),
                "No subpicture can be located completely outside of the conformance cropping window");
          CHECK((m_subPicCtuTopLeftY[i] * m_ctuSize)
                  >= (m_sourceHeight - m_confWinBottom * SPS::getWinUnitY(m_chromaFormatIDC)),
                "No subpicture can be located completely outside of the conformance cropping window");
          CHECK(((m_subPicCtuTopLeftY[i] + m_subPicHeight[i]) * m_ctuSize)
                  <= (m_confWinTop * SPS::getWinUnitY(m_chromaFormatIDC)),
                "No subpicture can be located completely outside of the conformance cropping window");
    
      if (tmpDecodedPictureHashSEIMappedType < 0 || tmpDecodedPictureHashSEIMappedType > to_underlying(HashType::NUM))
    
      {
        EXIT( "Error: bad checksum mode");
      }
      // Need to map values to match those of the SEI message:
      if (tmpDecodedPictureHashSEIMappedType==0)
      {
    
        m_decodedPictureHashSEIType = HashType::NONE;
    
        m_decodedPictureHashSEIType = static_cast<HashType>(tmpDecodedPictureHashSEIMappedType - 1);
    
      // Need to map values to match those of the SEI message:
      if (tmpSubpicDecodedPictureHashMappedType==0)
      {
    
        m_subpicDecodedPictureHashType = HashType::NONE;
    
        m_subpicDecodedPictureHashType = static_cast<HashType>(tmpSubpicDecodedPictureHashMappedType - 1);
    
    Frank Bossen's avatar
    Frank Bossen committed
      m_frameDeltaQps.resize(m_framesToBeEncoded + m_gopSize + 1);
    
      std::fill(m_frameDeltaQps.begin(), m_frameDeltaQps.end(), 0);
    
    
      if (m_qpIncrementAtSourceFrame.bPresent)
      {
        uint32_t switchingPOC = 0;
    
    Frank Bossen's avatar
    Frank Bossen committed
        if (m_qpIncrementAtSourceFrame.value > m_frameSkip)
    
        {
          // if switch source frame (ssf) = 10, and frame skip (fs)=2 and temporal subsample ratio (tsr) =1, then
          //    for this simulation switch at POC 8 (=10-2).
          // if ssf=10, fs=2, tsr=2, then for this simulation, switch at POC 4 (=(10-2)/2): POC0=Src2, POC1=Src4, POC2=Src6, POC3=Src8, POC4=Src10
    
    Frank Bossen's avatar
    Frank Bossen committed
          switchingPOC = (m_qpIncrementAtSourceFrame.value - m_frameSkip) / m_temporalSubsampleRatio;
    
        for (uint32_t i = switchingPOC; i < m_frameDeltaQps.size(); i++)
    
          m_frameDeltaQps[i] = 1;
    
        }
      }
    
    #if SHARP_LUMA_DELTA_QP
      CHECK( lumaLevelToDeltaQPMode >= LUMALVL_TO_DQP_NUM_MODES, "Error in cfg" );
    
      m_lumaLevelToDeltaQPMapping.mode=LumaLevelToDQPMode(lumaLevelToDeltaQPMode);
    
      if (m_lumaLevelToDeltaQPMapping.mode)
      {
        CHECK(  cfg_lumaLeveltoDQPMappingLuma.values.size() != cfg_lumaLeveltoDQPMappingQP.values.size(), "Error in cfg" );
        m_lumaLevelToDeltaQPMapping.mapping.resize(cfg_lumaLeveltoDQPMappingLuma.values.size());
        for(uint32_t i=0; i<cfg_lumaLeveltoDQPMappingLuma.values.size(); i++)
        {
          m_lumaLevelToDeltaQPMapping.mapping[i]=std::pair<int,int>(cfg_lumaLeveltoDQPMappingLuma.values[i], cfg_lumaLeveltoDQPMappingQP.values[i]);
        }
      }
    #endif
    
    
      CHECK(cfg_qpInValCb.values.size() != cfg_qpOutValCb.values.size(), "Chroma QP table for Cb is incomplete.");
      CHECK(cfg_qpInValCr.values.size() != cfg_qpOutValCr.values.size(), "Chroma QP table for Cr is incomplete.");
      CHECK(cfg_qpInValCbCr.values.size() != cfg_qpOutValCbCr.values.size(), "Chroma QP table for CbCr is incomplete.");
    
      if (m_useIdentityTableForNon420Chroma && m_chromaFormatIDC != CHROMA_420)
    
        m_chromaQpMappingTableParams.m_sameCQPTableForAllChromaFlag = true;
    
    
        cfg_qpInValCb.values    = { 26 };
        cfg_qpInValCr.values    = { 26 };
        cfg_qpInValCbCr.values  = { 26 };
        cfg_qpOutValCb.values   = { 26 };
        cfg_qpOutValCr.values   = { 26 };
        cfg_qpOutValCbCr.values = { 26 };
    
    
      // Need to have at least 2 points in the set. Add second one if only one given
      if (cfg_qpInValCb.values.size() == 1)
      {
        cfg_qpInValCb.values.push_back(cfg_qpInValCb.values[0] + 1);
        cfg_qpOutValCb.values.push_back(cfg_qpOutValCb.values[0] + 1);
      }
      if (cfg_qpInValCr.values.size() == 1)
      {
        cfg_qpInValCr.values.push_back(cfg_qpInValCr.values[0] + 1);
        cfg_qpOutValCr.values.push_back(cfg_qpOutValCr.values[0] + 1);
      }
      if (cfg_qpInValCbCr.values.size() == 1)
      {
        cfg_qpInValCbCr.values.push_back(cfg_qpInValCbCr.values[0] + 1);
        cfg_qpOutValCbCr.values.push_back(cfg_qpOutValCbCr.values[0] + 1);
      }
    
    
      int qpBdOffsetC = 6 * (m_internalBitDepth[CHANNEL_TYPE_CHROMA] - 8);
    
      m_chromaQpMappingTableParams.m_deltaQpInValMinus1[0].resize(cfg_qpInValCb.values.size());
      m_chromaQpMappingTableParams.m_deltaQpOutVal[0].resize(cfg_qpOutValCb.values.size());
    
      m_chromaQpMappingTableParams.m_numPtsInCQPTableMinus1[0] = (int) cfg_qpOutValCb.values.size() - 2;
      m_chromaQpMappingTableParams.m_qpTableStartMinus26[0]    = -26 + cfg_qpInValCb.values[0];
    
      CHECK(m_chromaQpMappingTableParams.m_qpTableStartMinus26[0] < -26 - qpBdOffsetC || m_chromaQpMappingTableParams.m_qpTableStartMinus26[0] > 36, "qpTableStartMinus26[0] is out of valid range of -26 -qpBdOffsetC to 36, inclusive.")
      CHECK(cfg_qpInValCb.values[0] != cfg_qpOutValCb.values[0], "First qpInValCb value should be equal to first qpOutValCb value");
    
      for (int i = 0; i < cfg_qpInValCb.values.size() - 1; i++)
    
        CHECK(cfg_qpInValCb.values[i] < -qpBdOffsetC || cfg_qpInValCb.values[i] > MAX_QP, "Some entries cfg_qpInValCb are out of valid range of -qpBdOffsetC to 63, inclusive.");
        CHECK(cfg_qpOutValCb.values[i] < -qpBdOffsetC || cfg_qpOutValCb.values[i] > MAX_QP, "Some entries cfg_qpOutValCb are out of valid range of -qpBdOffsetC to 63, inclusive.");
    
        m_chromaQpMappingTableParams.m_deltaQpInValMinus1[0][i] = cfg_qpInValCb.values[i + 1] - cfg_qpInValCb.values[i] - 1;
        m_chromaQpMappingTableParams.m_deltaQpOutVal[0][i] = cfg_qpOutValCb.values[i + 1] - cfg_qpOutValCb.values[i];
    
      if (!m_chromaQpMappingTableParams.m_sameCQPTableForAllChromaFlag)
    
        m_chromaQpMappingTableParams.m_deltaQpInValMinus1[1].resize(cfg_qpInValCr.values.size());
        m_chromaQpMappingTableParams.m_deltaQpOutVal[1].resize(cfg_qpOutValCr.values.size());
    
        m_chromaQpMappingTableParams.m_numPtsInCQPTableMinus1[1] = (int) cfg_qpOutValCr.values.size() - 2;
        m_chromaQpMappingTableParams.m_qpTableStartMinus26[1]    = -26 + cfg_qpInValCr.values[0];
    
        CHECK(m_chromaQpMappingTableParams.m_qpTableStartMinus26[1] < -26 - qpBdOffsetC || m_chromaQpMappingTableParams.m_qpTableStartMinus26[1] > 36, "qpTableStartMinus26[1] is out of valid range of -26 -qpBdOffsetC to 36, inclusive.")
        CHECK(cfg_qpInValCr.values[0] != cfg_qpOutValCr.values[0], "First qpInValCr value should be equal to first qpOutValCr value");
    
        for (int i = 0; i < cfg_qpInValCr.values.size() - 1; i++)
    
          CHECK(cfg_qpInValCr.values[i] < -qpBdOffsetC || cfg_qpInValCr.values[i] > MAX_QP, "Some entries cfg_qpInValCr are out of valid range of -qpBdOffsetC to 63, inclusive.");
          CHECK(cfg_qpOutValCr.values[i] < -qpBdOffsetC || cfg_qpOutValCr.values[i] > MAX_QP, "Some entries cfg_qpOutValCr are out of valid range of -qpBdOffsetC to 63, inclusive.");
    
          m_chromaQpMappingTableParams.m_deltaQpInValMinus1[1][i] = cfg_qpInValCr.values[i + 1] - cfg_qpInValCr.values[i] - 1;
          m_chromaQpMappingTableParams.m_deltaQpOutVal[1][i] = cfg_qpOutValCr.values[i + 1] - cfg_qpOutValCr.values[i];
    
        m_chromaQpMappingTableParams.m_deltaQpInValMinus1[2].resize(cfg_qpInValCbCr.values.size());
        m_chromaQpMappingTableParams.m_deltaQpOutVal[2].resize(cfg_qpOutValCbCr.values.size());
    
        m_chromaQpMappingTableParams.m_numPtsInCQPTableMinus1[2] = (int) cfg_qpOutValCbCr.values.size() - 2;
        m_chromaQpMappingTableParams.m_qpTableStartMinus26[2]    = -26 + cfg_qpInValCbCr.values[0];
    
        CHECK(m_chromaQpMappingTableParams.m_qpTableStartMinus26[2] < -26 - qpBdOffsetC || m_chromaQpMappingTableParams.m_qpTableStartMinus26[2] > 36, "qpTableStartMinus26[2] is out of valid range of -26 -qpBdOffsetC to 36, inclusive.")
        CHECK(cfg_qpInValCbCr.values[0] != cfg_qpInValCbCr.values[0], "First qpInValCbCr value should be equal to first qpOutValCbCr value");
    
        for (int i = 0; i < cfg_qpInValCbCr.values.size() - 1; i++)
    
          CHECK(cfg_qpInValCbCr.values[i] < -qpBdOffsetC || cfg_qpInValCbCr.values[i] > MAX_QP, "Some entries cfg_qpInValCbCr are out of valid range of -qpBdOffsetC to 63, inclusive.");
          CHECK(cfg_qpOutValCbCr.values[i] < -qpBdOffsetC || cfg_qpOutValCbCr.values[i] > MAX_QP, "Some entries cfg_qpOutValCbCr are out of valid range of -qpBdOffsetC to 63, inclusive.");
    
          m_chromaQpMappingTableParams.m_deltaQpInValMinus1[2][i] = cfg_qpInValCbCr.values[i + 1] - cfg_qpInValCbCr.values[i] - 1;
          m_chromaQpMappingTableParams.m_deltaQpOutVal[2][i] = cfg_qpInValCbCr.values[i + 1] - cfg_qpInValCbCr.values[i];
    
      CHECK(m_cuChromaQpOffsetSubdiv < 0, "MaxCuChromaQpOffsetSubdiv shall be >= 0");
    
      CHECK(cfg_crQpOffsetList.values.size() != cfg_cbQpOffsetList.values.size(), "Chroma QP offset lists shall be the same size");
    
      CHECK(cfg_cbCrQpOffsetList.values.size() != cfg_cbQpOffsetList.values.size() && cfg_cbCrQpOffsetList.values.size() > 0, "Chroma QP offset list for joint CbCr shall be either the same size as Cb and Cr or empty");
    
      if (m_cuChromaQpOffsetSubdiv > 0 && !cfg_cbQpOffsetList.values.size())
    
        msg(WARNING, "MaxCuChromaQpOffsetSubdiv has no effect when chroma QP offset lists are empty\n");
    
      }
      m_cuChromaQpOffsetList.resize(cfg_cbQpOffsetList.values.size());
      for (int i=0; i < cfg_cbQpOffsetList.values.size(); i++)
      {
    
    Frank Bossen's avatar
    Frank Bossen committed
        m_cuChromaQpOffsetList[i].u.comp.cbOffset = cfg_cbQpOffsetList.values[i];
        m_cuChromaQpOffsetList[i].u.comp.crOffset = cfg_crQpOffsetList.values[i];
        m_cuChromaQpOffsetList[i].u.comp.jointCbCrOffset =
          cfg_cbCrQpOffsetList.values.size() ? cfg_cbCrQpOffsetList.values[i] : 0;
    
      if ( m_LadfEnabed )
      {
        CHECK( m_LadfNumIntervals != cfg_LadfQpOffset.values.size(), "size of LadfQpOffset must be equal to LadfNumIntervals");
        CHECK( m_LadfNumIntervals - 1 != cfg_LadfIntervalLowerBound.values.size(), "size of LadfIntervalLowerBound must be equal to LadfNumIntervals - 1");
        m_LadfQpOffset = cfg_LadfQpOffset.values;
    
        m_LadfIntervalLowerBound[0] = 0;
    
        for (int k = 1; k < m_LadfNumIntervals; k++)
        {
          m_LadfIntervalLowerBound[k] = cfg_LadfIntervalLowerBound.values[k - 1];
        }
      }
    
    
      if (m_chromaFormatIDC != CHROMA_420)
      {
        if (!m_horCollocatedChromaFlag)
        {
          msg(WARNING, "\nWARNING: HorCollocatedChroma is forced to 1 for chroma formats other than 4:2:0\n");
          m_horCollocatedChromaFlag = true;
        }
        if (!m_verCollocatedChromaFlag)
        {
          msg(WARNING, "\nWARNING: VerCollocatedChroma is forced to 1 for chroma formats other than 4:2:0\n");
          m_verCollocatedChromaFlag = true;
        }
      }
    
    #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 > MAX_NUM_ALF_ALTERNATIVES_CHROMA, std::string("The maximum number of ALF Chroma filter alternatives must be in the range (1-") + std::to_string(MAX_NUM_ALF_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
    
    Frank Bossen's avatar
    Frank Bossen committed
          int filteredFrame                              = m_intraPeriod < 1 ? 2 * m_frameRate : 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++)