Skip to content
Snippets Groups Projects
EncAppCfg.cpp 223 KiB
Newer Older
  • Learn to ignore specific revisions
  •     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()-1;
        for (int i = 0; i < cfg_qpInValCbCr.values.size(); 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] = (i == 0) ? cfg_qpInValCbCr.values[i] + qpBdOffsetC : cfg_qpInValCbCr.values[i] - cfg_qpInValCbCr.values[i - 1] - 1;
          m_chromaQpMappingTableParams.m_deltaQpOutVal[2][i] = (i == 0) ? cfg_qpOutValCbCr.values[i] + qpBdOffsetC : cfg_qpOutValCbCr.values[i] - cfg_qpOutValCbCr.values[i - 1];
    
    #if LUMA_ADAPTIVE_DEBLOCKING_FILTER_QP_OFFSET
      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];
        }
      }
    #endif
    
    
    #if JVET_O0610_CFG
      if (m_AccessUnitDelimiter == false)
      {
        printf ("Warning: Access unit delimiters are disabled. VVC requires the presence of access unit delimiters\n");
      }
    #endif
    
    
      if ( m_loopFilterAcrossVirtualBoundariesDisabledFlag )
      {
        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_iSourceWidth, "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)
          {
            CHECK( m_virtualBoundariesPosX[i] - m_virtualBoundariesPosX[i-1] < m_uiCTUSize, "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_iSourceHeight, "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)
          {
            CHECK( m_virtualBoundariesPosY[i] - m_virtualBoundariesPosY[i-1] < m_uiCTUSize, "The distance between any two horizontal virtual boundaries shall be greater than or equal to the CTU size" );
          }
        }
      }
    
    
    #if JVET_O0090_ALF_CHROMA_FILTER_ALTERNATIVES_CTB
      if ( m_alf )
      {
    
        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 iValue;
          int iPOC = 0;
          while ( iPOC < m_framesToBeEncoded )
          {
            if ( fscanf(fpt, "%d", &iValue ) == EOF )
            {
              break;
            }
            m_aidQP[ iPOC ] = iValue;
            iPOC++;
          }
          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);
        }
      }
    
      if( m_toneMappingInfoSEIEnabled && !m_toneMapCancelFlag )
      {
        if( m_toneMapModelId == 2 && !cfg_startOfCodedInterval.values.empty() )
        {
          const uint32_t num = 1u<< m_toneMapTargetBitDepth;
          m_startOfCodedInterval = new int[num];
          for(uint32_t i=0; i<num; i++)
          {
            m_startOfCodedInterval[i] = cfg_startOfCodedInterval.values.size() > i ? cfg_startOfCodedInterval.values[i] : 0;
          }
        }
        else
        {
          m_startOfCodedInterval = NULL;
        }
        if( ( m_toneMapModelId == 3 ) && ( m_numPivots > 0 ) )
        {
          if( !cfg_codedPivotValue.values.empty() && !cfg_targetPivotValue.values.empty() )
          {
            m_codedPivotValue  = new int[m_numPivots];
            m_targetPivotValue = new int[m_numPivots];
            for(uint32_t i=0; i<m_numPivots; i++)
            {
              m_codedPivotValue[i]  = cfg_codedPivotValue.values.size()  > i ? cfg_codedPivotValue.values [i] : 0;
              m_targetPivotValue[i] = cfg_targetPivotValue.values.size() > i ? cfg_targetPivotValue.values[i] : 0;
            }
          }
        }
        else
        {
          m_codedPivotValue = NULL;
          m_targetPivotValue = NULL;
        }
      }
    
      if( m_kneeSEIEnabled && !m_kneeSEICancelFlag )
      {
        CHECK(!( m_kneeSEINumKneePointsMinus1 >= 0 && m_kneeSEINumKneePointsMinus1 < 999 ), "Inconsistent config");
        m_kneeSEIInputKneePoint  = new int[m_kneeSEINumKneePointsMinus1+1];
        m_kneeSEIOutputKneePoint = new int[m_kneeSEINumKneePointsMinus1+1];
        for(int i=0; i<(m_kneeSEINumKneePointsMinus1+1); i++)
        {
          m_kneeSEIInputKneePoint[i]  = cfg_kneeSEIInputKneePointValue.values.size()  > i ? cfg_kneeSEIInputKneePointValue.values[i]  : 1;
          m_kneeSEIOutputKneePoint[i] = cfg_kneeSEIOutputKneePointValue.values.size() > i ? cfg_kneeSEIOutputKneePointValue.values[i] : 0;
        }
      }
    
      if(m_timeCodeSEIEnabled)
      {
        for(int i = 0; i < m_timeCodeSEINumTs && i < MAX_TIMECODE_SEI_SETS; i++)
        {
          m_timeSetArray[i].clockTimeStampFlag    = cfg_timeCodeSeiTimeStampFlag        .values.size()>i ? cfg_timeCodeSeiTimeStampFlag        .values [i] : false;
          m_timeSetArray[i].numUnitFieldBasedFlag = cfg_timeCodeSeiNumUnitFieldBasedFlag.values.size()>i ? cfg_timeCodeSeiNumUnitFieldBasedFlag.values [i] : 0;
          m_timeSetArray[i].countingType          = cfg_timeCodeSeiCountingType         .values.size()>i ? cfg_timeCodeSeiCountingType         .values [i] : 0;
          m_timeSetArray[i].fullTimeStampFlag     = cfg_timeCodeSeiFullTimeStampFlag    .values.size()>i ? cfg_timeCodeSeiFullTimeStampFlag    .values [i] : 0;
          m_timeSetArray[i].discontinuityFlag     = cfg_timeCodeSeiDiscontinuityFlag    .values.size()>i ? cfg_timeCodeSeiDiscontinuityFlag    .values [i] : 0;
          m_timeSetArray[i].cntDroppedFlag        = cfg_timeCodeSeiCntDroppedFlag       .values.size()>i ? cfg_timeCodeSeiCntDroppedFlag       .values [i] : 0;
          m_timeSetArray[i].numberOfFrames        = cfg_timeCodeSeiNumberOfFrames       .values.size()>i ? cfg_timeCodeSeiNumberOfFrames       .values [i] : 0;
          m_timeSetArray[i].secondsValue          = cfg_timeCodeSeiSecondsValue         .values.size()>i ? cfg_timeCodeSeiSecondsValue         .values [i] : 0;
          m_timeSetArray[i].minutesValue          = cfg_timeCodeSeiMinutesValue         .values.size()>i ? cfg_timeCodeSeiMinutesValue         .values [i] : 0;
          m_timeSetArray[i].hoursValue            = cfg_timeCodeSeiHoursValue           .values.size()>i ? cfg_timeCodeSeiHoursValue           .values [i] : 0;
          m_timeSetArray[i].secondsFlag           = cfg_timeCodeSeiSecondsFlag          .values.size()>i ? cfg_timeCodeSeiSecondsFlag          .values [i] : 0;
          m_timeSetArray[i].minutesFlag           = cfg_timeCodeSeiMinutesFlag          .values.size()>i ? cfg_timeCodeSeiMinutesFlag          .values [i] : 0;
          m_timeSetArray[i].hoursFlag             = cfg_timeCodeSeiHoursFlag            .values.size()>i ? cfg_timeCodeSeiHoursFlag            .values [i] : 0;
          m_timeSetArray[i].timeOffsetLength      = cfg_timeCodeSeiTimeOffsetLength     .values.size()>i ? cfg_timeCodeSeiTimeOffsetLength     .values [i] : 0;
          m_timeSetArray[i].timeOffsetValue       = cfg_timeCodeSeiTimeOffsetValue      .values.size()>i ? cfg_timeCodeSeiTimeOffsetValue      .values [i] : 0;
        }
      }
    
    
    Taoran Lu's avatar
    Taoran Lu committed
      m_reshapeCW.binCW.resize(3);
      m_reshapeCW.rspFps = m_iFrameRate;
    
    #if !JVET_O0432_LMCS_ENCODER
    
    Taoran Lu's avatar
    Taoran Lu committed
      m_reshapeCW.rspIntraPeriod = m_iIntraPeriod;
    
    Taoran Lu's avatar
    Taoran Lu committed
      m_reshapeCW.rspPicSize = m_iSourceWidth*m_iSourceHeight;
    
    Taoran Lu's avatar
    Taoran Lu committed
      m_reshapeCW.rspFpsToIp = std::max(16, 16 * (int)(round((double)m_iFrameRate /16.0)));
    
    Taoran Lu's avatar
    Taoran Lu committed
      m_reshapeCW.rspBaseQP = m_iQP;
    
    #if JVET_O0432_LMCS_ENCODER
      m_reshapeCW.updateCtrl = m_updateCtrl;
      m_reshapeCW.adpOption = m_adpOption;
      m_reshapeCW.initialCW = m_initialCW;
    #endif
    
    #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))
      {
        msg( WARNING, "*************************************************************************\n" );
        msg( WARNING, "* WARNING: chroma QPA on, ignoring nonzero dual-tree chroma QP offsets! *\n" );
        msg( WARNING, "*************************************************************************\n" );
      }
    
    
    #if ENABLE_QPA_SUB_CTU
     #if QP_SWITCHING_FOR_PARALLEL
    
      if ((m_iQP < 38) && m_bUsePerceptQPA && !m_bUseAdaptiveQP && (m_iSourceWidth <= 2048) && (m_iSourceHeight <= 1280)
    
      if (((int)m_fQP < 38) && m_bUsePerceptQPA && !m_bUseAdaptiveQP && (m_iSourceWidth <= 2048) && (m_iSourceHeight <= 1280)
    
    #if MAX_TB_SIZE_SIGNALLING
          && ((1 << (m_log2MaxTbSize + 1)) == m_uiCTUSize) && (m_iSourceWidth > 512 || m_iSourceHeight > 320))
    #else
        && ((1 << (MAX_TB_LOG2_SIZEY + 1)) == m_uiCTUSize) && (m_iSourceWidth > 512 || m_iSourceHeight > 320))
    #endif
    
        m_cuQpDeltaSubdiv = 2;
    
      if( ( m_iQP < 38 ) && ( m_iGOPSize > 4 ) && m_bUsePerceptQPA && !m_bUseAdaptiveQP && ( m_iSourceHeight <= 1280 ) && ( m_iSourceWidth <= 2048 ) )
    
      if( ( ( int ) m_fQP < 38 ) && ( m_iGOPSize > 4 ) && m_bUsePerceptQPA && !m_bUseAdaptiveQP && ( m_iSourceHeight <= 1280 ) && ( m_iSourceWidth <= 2048 ) )
    
        msg( WARNING, "*************************************************************************\n" );
        msg( WARNING, "* WARNING: QPA on with large CTU for <=HD sequences, limiting CTU size! *\n" );
        msg( WARNING, "*************************************************************************\n" );
    
    #if MAX_TB_SIZE_SIGNALLING
        if( ( 1u << m_log2MaxTbSize         ) > m_uiCTUSize ) m_log2MaxTbSize--;
    #endif
    
    Karsten Suehring's avatar
    Karsten Suehring committed
      const int minCuSize = 1 << MIN_CU_LOG2;
      m_uiMaxCodingDepth = 0;
      while( ( m_uiCTUSize >> m_uiMaxCodingDepth ) > minCuSize )
    
    Karsten Suehring's avatar
    Karsten Suehring committed
        m_uiMaxCodingDepth++;
      }
      m_uiLog2DiffMaxMinCodingBlockSize = m_uiMaxCodingDepth;
      m_uiMaxCUWidth = m_uiMaxCUHeight = m_uiCTUSize;
      m_uiMaxCUDepth = m_uiMaxCodingDepth;
    
    
      // check validity of input parameters
      if( xCheckParameter() )
      {
        // return check failed
        return false;
      }
    
      // print-out parameters
      xPrintParameter();
    
      return true;
    }
    
    
    // ====================================================================================================================
    // Private member functions
    // ====================================================================================================================
    
    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)
    
    
      if( m_profile != Profile::NEXT )
      {
        THROW( "Next profile with an alternative partitioner has to be enabled if HEVC_USE_RQT is off!" );
    #if ENABLE_WPP_PARALLELISM
        xConfirmPara( m_numWppThreads > 1, "WPP-style parallelization only supported with NEXT profile" );
    #endif
        xConfirmPara( m_LMChroma, "LMChroma only allowed with NEXT profile" );
        xConfirmPara( m_ImvMode, "IMV is only allowed with NEXT profile" );
    
        xConfirmPara( m_PLTMode, "PLT Mode only allowed with NEXT profile");
    
    Yu Han's avatar
    Yu Han committed
        xConfirmPara(m_IBCMode, "IBC Mode only allowed with NEXT profile");
    
        xConfirmPara( m_HashME, "Hash motion estimation only allowed with NEXT profile" );
    
        xConfirmPara( m_useFastLCTU, "Fast large CTU can only be applied when encoding with NEXT profile" );
    
    Tung Nguyen's avatar
    Tung Nguyen committed
        xConfirmPara( m_MTS, "MTS only allowed with NEXT profile" );
        xConfirmPara( m_MTSIntraMaxCand, "MTS only allowed with NEXT profile" );
        xConfirmPara( m_MTSInterMaxCand, "MTS only allowed with NEXT profile" );
    
        xConfirmPara( m_SMVD, "SMVD is only allowed with NEXT profile" );
    
        xConfirmPara( m_compositeRefEnabled, "Composite Reference Frame is only allowed with NEXT profile" );
        xConfirmPara( m_GBi, "GBi is only allowed with NEXT profile" );
        xConfirmPara( m_GBiFast, "GBiFast is only allowed with NEXT profile" );
    
        xConfirmPara( m_Triangle, "Triangle is only allowed with NEXT profile" );
    
        xConfirmPara(m_DMVR, "DMVR only allowed with NEXT profile");
    
        xConfirmPara(m_MmvdDisNum, "Number of distance MMVD entry setting only allowed with NEXT profile");
    
        xConfirmPara(m_RdpcmMode, "RDPCM only allowed with NEXT profile");
    
    #if JVET_O0376_SPS_JOINTCBCR_FLAG
        xConfirmPara(m_JointCbCrMode, "JointCbCr only allowed with NEXT profile");
    
    Fangdong Chen's avatar
    Fangdong Chen committed
    #endif
    
        // ADD_NEW_TOOL : (parameter check) add a check for next tools here
      }
      else
      {
        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" );
        }
    
    
        xConfirmPara( m_wrapAroundOffset <= m_uiCTUSize + (m_uiMaxCUWidth >> m_uiLog2DiffMaxMinCodingBlockSize), "Wrap-around offset must be greater than CtbSizeY + MinCbSize" );
    
        xConfirmPara( m_wrapAroundOffset > m_iSourceWidth, "Wrap-around offset must not be greater than the source picture width" );
    
        int minCUSize =  m_uiCTUSize >> m_uiLog2DiffMaxMinCodingBlockSize;
        xConfirmPara( m_wrapAroundOffset % minCUSize != 0, "Wrap-around offset must be an integer multiple of the specified minimum CU size" );
    
      }
    
    #if ENABLE_SPLIT_PARALLELISM
      xConfirmPara( m_numSplitThreads < 1, "Number of used threads cannot be smaller than 1" );
      xConfirmPara( m_numSplitThreads > PARL_SPLIT_MAX_NUM_THREADS, "Number of used threads cannot be higher than the number of actual jobs" );
    #if _MSC_VER && ENABLE_WPP_PARALLELISM
      xConfirmPara( m_numSplitThreads > 1 && m_numSplitThreads != NUM_SPLIT_THREADS_IF_MSVC, "Due to poor implementation by Microsoft, NumSplitThreads cannot be set dynamically on runtime!" );
    #endif
    #else
      xConfirmPara( m_numSplitThreads != 1, "ENABLE_SPLIT_PARALLELISM is disabled, numSplitThreads has to be 1" );
    #endif
    
    #if ENABLE_WPP_PARALLELISM
      xConfirmPara( m_numWppThreads < 1, "Number of threads used for WPP-style parallelization cannot be smaller than 1" );
      xConfirmPara( m_numWppThreads > PARL_WPP_MAX_NUM_THREADS, "Number of threads used for WPP-style parallelization cannot be bigger than PARL_WPP_MAX_NUM_THREADS" );
      xConfirmPara( !m_ensureWppBitEqual && m_numWppThreads > 1, "WPP bit equality is implied when using WPP-style parallelism" );
    #if ENABLE_WPP_STATIC_LINK
      xConfirmPara( m_numWppExtraLines != 0, "WPP-style extra lines out of range" );
    #else
      xConfirmPara( m_numWppExtraLines < 0, "WPP-style extra lines out of range" );
    #endif
    #else
      xConfirmPara( m_numWppThreads != 1, "ENABLE_WPP_PARALLELISM is disabled, numWppThreads has to be 1" );
      xConfirmPara( m_ensureWppBitEqual, "ENABLE_WPP_PARALLELISM is disabled, cannot ensure being WPP bit-equal" );
    #endif
    
    
    #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)");
      const uint32_t maxBitDepth=(m_chromaFormatIDC==CHROMA_400) ? m_internalBitDepth[CHANNEL_TYPE_LUMA] : std::max(m_internalBitDepth[CHANNEL_TYPE_LUMA], m_internalBitDepth[CHANNEL_TYPE_CHROMA]);
    
      xConfirmPara(m_bitDepthConstraint<maxBitDepth, "The internalBitDepth must not be greater than the bitDepthConstraint value");
    
      xConfirmPara(m_chromaFormatConstraint<m_chromaFormatIDC, "The chroma format used must not be greater than the chromaFormatConstraint value");
    
      if (m_profile==Profile::MAINREXT || m_profile==Profile::HIGHTHROUGHPUTREXT)
      {
        xConfirmPara(m_lowerBitRateConstraintFlag==false && m_intraConstraintFlag==false, "The lowerBitRateConstraint flag cannot be false when intraConstraintFlag is false");
        xConfirmPara(m_cabacBypassAlignmentEnabledFlag && m_profile!=Profile::HIGHTHROUGHPUTREXT, "AlignCABACBeforeBypass must not be enabled unless the high throughput profile is being used.");
        if (m_profile == Profile::MAINREXT)
        {
          const uint32_t intraIdx = m_intraConstraintFlag ? 1:0;
          const uint32_t bitDepthIdx = (m_bitDepthConstraint == 8 ? 0 : (m_bitDepthConstraint ==10 ? 1 : (m_bitDepthConstraint == 12 ? 2 : (m_bitDepthConstraint == 16 ? 3 : 4 ))));
          const uint32_t chromaFormatIdx = uint32_t(m_chromaFormatConstraint);
          const bool bValidProfile = (bitDepthIdx > 3 || chromaFormatIdx>3) ? false : (validRExtProfileNames[intraIdx][bitDepthIdx][chromaFormatIdx] != NONE);
          xConfirmPara(!bValidProfile, "Invalid intra constraint flag, bit depth constraint flag and chroma format constraint flag combination for a RExt profile");
          const bool bUsingGeneralRExtTools  = m_transformSkipRotationEnabledFlag        ||
                                               m_transformSkipContextEnabledFlag         ||
                                               m_rdpcmEnabledFlag[RDPCM_SIGNAL_IMPLICIT] ||
                                               m_rdpcmEnabledFlag[RDPCM_SIGNAL_EXPLICIT] ||
                                               !m_enableIntraReferenceSmoothing          ||
                                               m_persistentRiceAdaptationEnabledFlag     ||
                                               m_log2MaxTransformSkipBlockSize!=2;
    
          const bool bUsingChromaQPTool      = m_cuChromaQpOffsetSubdiv >= 0;
    
          const bool bUsingExtendedPrecision = m_extendedPrecisionProcessingFlag;
    
          xConfirmPara((m_chromaFormatConstraint==CHROMA_420 || m_chromaFormatConstraint==CHROMA_400) && bUsingChromaQPTool, "CU Chroma QP adjustment cannot be used for 4:0:0 or 4:2:0 RExt profiles");
          xConfirmPara(m_bitDepthConstraint != 16 && bUsingExtendedPrecision, "Extended precision can only be used in 16-bit RExt profiles");
          if (!(m_chromaFormatConstraint == CHROMA_400 && m_bitDepthConstraint == 16) && m_chromaFormatConstraint!=CHROMA_444)
          {
            xConfirmPara(bUsingGeneralRExtTools, "Combination of tools and profiles are not possible in the specified RExt profile.");
          }
          xConfirmPara( m_onePictureOnlyConstraintFlag && m_chromaFormatConstraint!=CHROMA_444, "chroma format constraint must be 4:4:4 when one-picture-only constraint flag is 1");
          xConfirmPara( m_onePictureOnlyConstraintFlag && m_bitDepthConstraint != 8 && m_bitDepthConstraint != 16, "bit depth constraint must be 8 or 16 when one-picture-only constraint flag is 1");
          xConfirmPara( m_onePictureOnlyConstraintFlag && m_framesToBeEncoded > 1, "Number of frames to be encoded must be 1 when one-picture-only constraint flag is 1.");
    
          if (!m_intraConstraintFlag && m_bitDepthConstraint==16 && m_chromaFormatConstraint==CHROMA_444)
          {
            msg( WARNING, "********************************************************************************************************\n");
            msg( WARNING, "** WARNING: The RExt constraint flags describe a non standard combination (used for development only) **\n");
            msg( WARNING, "********************************************************************************************************\n");
          }
        }
        else
        {
          xConfirmPara( m_chromaFormatConstraint != CHROMA_444, "chroma format constraint must be 4:4:4 in the High Throughput 4:4:4 16-bit Intra profile.");
          xConfirmPara( m_bitDepthConstraint     != 16,         "bit depth constraint must be 4:4:4 in the High Throughput 4:4:4 16-bit Intra profile.");
          xConfirmPara( m_intraConstraintFlag    != 1,          "intra constraint flag must be 1 in the High Throughput 4:4:4 16-bit Intra profile.");
        }
      }
      else
      {
        xConfirmPara(m_bitDepthConstraint!=((m_profile==Profile::MAIN10 || m_profile==Profile::NEXT)?10:8), "BitDepthConstraint must be 8 for MAIN profile and 10 for MAIN10 profile.");
        xConfirmPara(m_chromaFormatConstraint!=CHROMA_420 && m_profile!=Profile::NEXT, "ChromaFormatConstraint must be 420 for non main-RExt and non-Next profiles.");
        xConfirmPara(m_intraConstraintFlag==true, "IntraConstraintFlag must be false for non main_RExt profiles.");
        xConfirmPara(m_lowerBitRateConstraintFlag==false, "LowerBitrateConstraintFlag must be true for non main-RExt profiles.");
        xConfirmPara(m_profile == Profile::MAINSTILLPICTURE && m_framesToBeEncoded > 1, "Number of frames to be encoded must be 1 when main still picture profile is used.");
    
        xConfirmPara(m_crossComponentPredictionEnabledFlag==true, "CrossComponentPrediction must not be used for non main-RExt profiles.");
    
    Tung Nguyen's avatar
    Tung Nguyen committed
        xConfirmPara(m_log2MaxTransformSkipBlockSize>=6, "Transform Skip Log2 Max Size must be less or equal to 5.");
    
        xConfirmPara(m_transformSkipRotationEnabledFlag==true, "UseResidualRotation must not be enabled for non main-RExt profiles.");
        xConfirmPara(m_transformSkipContextEnabledFlag==true, "UseSingleSignificanceMapContext must not be enabled for non main-RExt profiles.");
        xConfirmPara(m_rdpcmEnabledFlag[RDPCM_SIGNAL_IMPLICIT]==true, "ImplicitResidualDPCM must not be enabled for non main-RExt profiles.");
        xConfirmPara(m_rdpcmEnabledFlag[RDPCM_SIGNAL_EXPLICIT]==true, "ExplicitResidualDPCM must not be enabled for non main-RExt profiles.");
        xConfirmPara(m_persistentRiceAdaptationEnabledFlag==true, "GolombRiceParameterAdaption must not be enabled for non main-RExt profiles.");
        xConfirmPara(m_extendedPrecisionProcessingFlag==true, "UseExtendedPrecision must not be enabled for non main-RExt profiles.");
        xConfirmPara(m_highPrecisionOffsetsEnabledFlag==true, "UseHighPrecisionPredictionWeighting must not be enabled for non main-RExt profiles.");
        xConfirmPara(m_enableIntraReferenceSmoothing==false, "EnableIntraReferenceSmoothing must be enabled for non main-RExt profiles.");
        xConfirmPara(m_cabacBypassAlignmentEnabledFlag, "AlignCABACBeforeBypass cannot be enabled for non main-RExt profiles.");
      }
    
    
      // check range of parameters
      xConfirmPara( m_inputBitDepth[CHANNEL_TYPE_LUMA  ] < 8,                                   "InputBitDepth must be at least 8" );
      xConfirmPara( m_inputBitDepth[CHANNEL_TYPE_CHROMA] < 8,                                   "InputBitDepthC must be at least 8" );
    
    
      if (m_extendedPrecisionProcessingFlag)
      {
        for (uint32_t channelType = 0; channelType < MAX_NUM_CHANNEL_TYPE; channelType++)
        {
          xConfirmPara((m_internalBitDepth[channelType] > 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...");
        }
      }
      else
      {
        for (uint32_t channelType = 0; channelType < MAX_NUM_CHANNEL_TYPE; channelType++)
        {
          xConfirmPara((m_internalBitDepth[channelType] > 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[CHANNEL_TYPE_LUMA  ] < m_inputBitDepth[CHANNEL_TYPE_LUMA  ]), "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[CHANNEL_TYPE_CHROMA] < m_inputBitDepth[CHANNEL_TYPE_CHROMA]), "MSB-extended bit depth for chroma channel (--MSBExtendedBitDepthC) must be greater than or equal to input bit depth for chroma channel (--InputBitDepthC)" );
    
      xConfirmPara( m_log2SaoOffsetScale[CHANNEL_TYPE_LUMA]   > (m_internalBitDepth[CHANNEL_TYPE_LUMA  ]<10?0:(m_internalBitDepth[CHANNEL_TYPE_LUMA  ]-10)), "SaoLumaOffsetBitShift must be in the range of 0 to InternalBitDepth-10, inclusive");
      xConfirmPara( m_log2SaoOffsetScale[CHANNEL_TYPE_CHROMA] > (m_internalBitDepth[CHANNEL_TYPE_CHROMA]<10?0:(m_internalBitDepth[CHANNEL_TYPE_CHROMA]-10)), "SaoChromaOffsetBitShift must be in the range of 0 to InternalBitDepthC-10, inclusive");
    
      xConfirmPara( m_chromaFormatIDC >= NUM_CHROMA_FORMAT,                                     "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 >= NUM_CHROMA_FORMAT,                                "InputChromaFormatIDC must be either 400, 420, 422 or 444" );
      xConfirmPara( m_iFrameRate <= 0,                                                          "Frame rate must be more than 1" );
      xConfirmPara( m_temporalSubsampleRatio < 1,                                               "Temporal subsample rate must be no less than 1" );
      xConfirmPara( m_framesToBeEncoded <= 0,                                                   "Total Number Of Frames encoded must be more than 0" );
      xConfirmPara( m_framesToBeEncoded < m_switchPOC,                                          "debug POC out of range" );
    
      xConfirmPara( m_iGOPSize < 1 ,                                                            "GOP Size must be greater or equal to 1" );
      xConfirmPara( m_iGOPSize > 1 &&  m_iGOPSize % 2,                                          "GOP Size must be a multiple of 2, if GOP Size is greater than 1" );
      xConfirmPara( (m_iIntraPeriod > 0 && m_iIntraPeriod < m_iGOPSize) || m_iIntraPeriod == 0, "Intra period must be more than GOP size, or -1 , not 0" );
      xConfirmPara( m_iDecodingRefreshType < 0 || m_iDecodingRefreshType > 3,                   "Decoding Refresh Type must be comprised between 0 and 3 included" );
      if(m_iDecodingRefreshType == 3)
      {
        xConfirmPara( !m_recoveryPointSEIEnabled,                                               "When using RecoveryPointSEI messages as RA points, recoveryPointSEI must be enabled" );
      }
    
      if (m_isField)
      {
        if (!m_pictureTimingSEIEnabled)
        {
          msg( WARNING, "****************************************************************************\n");
          msg( WARNING, "** WARNING: Picture Timing SEI should be enabled for field coding!        **\n");
          msg( WARNING, "****************************************************************************\n");
        }
      }
    
      if(m_crossComponentPredictionEnabledFlag && (m_chromaFormatIDC != CHROMA_444))
      {
        msg( WARNING, "****************************************************************************\n");
        msg( WARNING, "** WARNING: Cross-component prediction is specified for 4:4:4 format only **\n");
        msg( WARNING, "****************************************************************************\n");
    
        m_crossComponentPredictionEnabledFlag = false;
      }
    
      if ( m_CUTransquantBypassFlagForce && m_bUseHADME )
      {
        msg( WARNING, "****************************************************************************\n");
        msg( WARNING, "** WARNING: --HadamardME has been disabled due to the enabling of         **\n");
        msg( WARNING, "**          --CUTransquantBypassFlagForce                                 **\n");
        msg( WARNING, "****************************************************************************\n");
    
        m_bUseHADME = false; // this has been disabled so that the lambda is calculated slightly differently for lossless modes (as a result of JCTVC-R0104).
      }
    
      xConfirmPara (m_log2MaxTransformSkipBlockSize < 2, "Transform Skip Log2 Max Size must be at least 2 (4x4)");
    
    
      if( m_SubPuMvpMode == 3 && m_maxNumMergeCand < 7 )
      {
        msg( WARNING, "****************************************************************************\n" );
        msg( WARNING, "** WARNING: Allowing less than 7 merge candidates, although both          **\n" );
        msg( WARNING, "**          advanced sup-pu temporal merging modes are enabled.           **\n" );
        msg( WARNING, "****************************************************************************\n" );
      }
      else if( m_SubPuMvpMode != 0 && m_maxNumMergeCand < 6 )
      {
        msg( WARNING, "****************************************************************************\n" );
        msg( WARNING, "** WARNING: Allowing less than 6 merge candidates, although               **\n" );
        msg( WARNING, "**          an advanced sup-pu temporal merging mode is enabled.          **\n" );
        msg( WARNING, "****************************************************************************\n" );
      }
      xConfirmPara( m_iQP < -6 * (m_internalBitDepth[CHANNEL_TYPE_LUMA] - 8) || m_iQP > MAX_QP, "QP exceeds supported range (-QpBDOffsety to 63)" );
    #if W0038_DB_OPT
      xConfirmPara( m_deblockingFilterMetric!=0 && (m_bLoopFilterDisable || m_loopFilterOffsetInPPS), "If DeblockingFilterMetric is non-zero then both LoopFilterDisable and LoopFilterOffsetInPPS must be 0");
    #else
      xConfirmPara( m_DeblockingFilterMetric && (m_bLoopFilterDisable || m_loopFilterOffsetInPPS), "If DeblockingFilterMetric is true then both LoopFilterDisable and LoopFilterOffsetInPPS must be 0");
    #endif
      xConfirmPara( m_loopFilterBetaOffsetDiv2 < -6 || m_loopFilterBetaOffsetDiv2 > 6,          "Loop Filter Beta Offset div. 2 exceeds supported range (-6 to 6)" );
      xConfirmPara( m_loopFilterTcOffsetDiv2 < -6 || m_loopFilterTcOffsetDiv2 > 6,              "Loop Filter Tc Offset div. 2 exceeds supported range (-6 to 6)" );
      xConfirmPara( m_iSearchRange < 0 ,                                                        "Search Range must be more than 0" );
      xConfirmPara( m_bipredSearchRange < 0 ,                                                   "Bi-prediction refinement search range must be more than 0" );
      xConfirmPara( m_minSearchWindow < 0,                                                      "Minimum motion search window size for the adaptive window ME must be greater than or equal to 0" );
      xConfirmPara( m_iMaxDeltaQP > MAX_DELTA_QP,                                               "Absolute Delta QP exceeds supported range (0 to 7)" );
    
    #if ENABLE_QPA
      xConfirmPara( m_bUsePerceptQPA && m_uiDeltaQpRD > 0,                                      "Perceptual QPA cannot be used together with slice-level multiple-QP optimization" );
    #endif
    
    #if SHARP_LUMA_DELTA_QP
      xConfirmPara( m_lumaLevelToDeltaQPMapping.mode && m_uiDeltaQpRD > 0,                      "Luma-level-based Delta QP cannot be used together with slice level multiple-QP optimization\n" );
    #endif
    
      if (m_lumaLevelToDeltaQPMapping.mode && m_lumaReshapeEnable)
      {
        msg(WARNING, "For HDR-PQ, reshaper should be used mutual-exclusively with Luma-level-based Delta QP. If use luma DQP, turn reshaper off.\n");
        m_lumaReshapeEnable = false;
      }
    
    Taoran Lu's avatar
    Taoran Lu committed
      if (!m_lumaReshapeEnable)
    
    Taoran Lu's avatar
    Taoran Lu committed
        m_reshapeSignalType = RESHAPE_SIGNAL_NULL;
        m_intraCMD = 0;
    
    Taoran Lu's avatar
    Taoran Lu committed
      if (m_lumaReshapeEnable && m_reshapeSignalType == RESHAPE_SIGNAL_PQ)
    
    Taoran Lu's avatar
    Taoran Lu committed
        m_intraCMD = 1;
    
    #if JVET_O0432_LMCS_ENCODER
      else if (m_lumaReshapeEnable && (m_reshapeSignalType == RESHAPE_SIGNAL_SDR || m_reshapeSignalType == RESHAPE_SIGNAL_HLG))
    #else
    
    Taoran Lu's avatar
    Taoran Lu committed
      else if (m_lumaReshapeEnable && m_reshapeSignalType == RESHAPE_SIGNAL_SDR)
    
    Taoran Lu's avatar
    Taoran Lu committed
        m_intraCMD = 0;
    
    Taoran Lu's avatar
    Taoran Lu committed
        m_lumaReshapeEnable = false;
    
    #if JVET_O0432_LMCS_ENCODER
      if (m_lumaReshapeEnable)
      {
        xConfirmPara(m_updateCtrl < 0, "Min. LMCS Update Control is 0");
        xConfirmPara(m_updateCtrl > 2, "Max. LMCS Update Control is 2");
        xConfirmPara(m_adpOption < 0, "Min. LMCS Adaptation Option is 0");
        xConfirmPara(m_adpOption > 4, "Max. LMCS Adaptation Option is 4");
        xConfirmPara(m_initialCW < 0, "Min. Initial Total Codeword is 0");
        xConfirmPara(m_initialCW > 1023, "Max. Initial Total Codeword is 1023");
        if (m_updateCtrl > 0 && m_adpOption > 2) { m_adpOption -= 2; }
      }
    #endif
    
    
      xConfirmPara( m_cbQpOffset < -12,   "Min. Chroma Cb QP Offset is -12" );
      xConfirmPara( m_cbQpOffset >  12,   "Max. Chroma Cb QP Offset is  12" );
      xConfirmPara( m_crQpOffset < -12,   "Min. Chroma Cr QP Offset is -12" );
      xConfirmPara( m_crQpOffset >  12,   "Max. Chroma Cr QP Offset is  12" );
      xConfirmPara( m_cbQpOffsetDualTree < -12,   "Min. Chroma Cb QP Offset for dual tree is -12" );
      xConfirmPara( m_cbQpOffsetDualTree >  12,   "Max. Chroma Cb QP Offset for dual tree is  12" );
      xConfirmPara( m_crQpOffsetDualTree < -12,   "Min. Chroma Cr QP Offset for dual tree is -12" );
      xConfirmPara( m_crQpOffsetDualTree >  12,   "Max. Chroma Cr QP Offset for dual tree is  12" );
    
    #if JVET_O0376_SPS_JOINTCBCR_FLAG
      if (m_JointCbCrMode && (m_chromaFormatIDC == CHROMA_400))
    
    Fangdong Chen's avatar
    Fangdong Chen committed
      {
        msg( WARNING, "****************************************************************************\n");
    
        msg( WARNING, "** WARNING: --JointCbCr has been disabled because the chromaFormat is 400 **\n");
    
    Fangdong Chen's avatar
    Fangdong Chen committed
        msg( WARNING, "****************************************************************************\n");
    
        m_JointCbCrMode = false;
    
      if (m_JointCbCrMode)
    
    Fangdong Chen's avatar
    Fangdong Chen committed
      {
    
    Fangdong Chen's avatar
    Fangdong Chen committed
        xConfirmPara( m_cbCrQpOffset < -12, "Min. Joint Cb-Cr QP Offset is -12");
        xConfirmPara( m_cbCrQpOffset >  12, "Max. Joint Cb-Cr QP Offset is  12");
        xConfirmPara( m_cbCrQpOffsetDualTree < -12, "Min. Joint Cb-Cr QP Offset for dual tree is -12");
        xConfirmPara( m_cbCrQpOffsetDualTree >  12, "Max. Joint Cb-Cr QP Offset for dual tree is  12");
    
    Fangdong Chen's avatar
    Fangdong Chen committed
      }
    #else
    
    Fangdong Chen's avatar
    Fangdong Chen committed
      xConfirmPara( m_cbCrQpOffset < -12, "Min. Joint Cb-Cr QP Offset is -12");
      xConfirmPara( m_cbCrQpOffset >  12, "Max. Joint Cb-Cr QP Offset is  12");
      xConfirmPara( m_cbCrQpOffsetDualTree < -12, "Min. Joint Cb-Cr QP Offset for dual tree is -12");
      xConfirmPara( m_cbCrQpOffsetDualTree >  12, "Max. Joint Cb-Cr QP Offset for dual tree is  12");
    
    Fangdong Chen's avatar
    Fangdong Chen committed
    #endif
    
      xConfirmPara( m_iQPAdaptationRange <= 0,                                                  "QP Adaptation Range must be more than 0" );
      if (m_iDecodingRefreshType == 2)
      {
        xConfirmPara( m_iIntraPeriod > 0 && m_iIntraPeriod <= m_iGOPSize ,                      "Intra period must be larger than GOP size for periodic IDR pictures");
      }
      xConfirmPara( m_uiMaxCUDepth > MAX_CU_DEPTH,                                              "MaxPartitionDepth exceeds predefined MAX_CU_DEPTH limit");
      xConfirmPara( m_uiMaxCUWidth > MAX_CU_SIZE,                                               "MaxCUWith exceeds predefined MAX_CU_SIZE limit");
    
      xConfirmPara( m_uiMinQT[0] < 1<<MIN_CU_LOG2,                                              "Minimum QT size should be larger than or equal to 4");
      xConfirmPara( m_uiMinQT[1] < 1<<MIN_CU_LOG2,                                              "Minimum QT size should be larger than or equal to 4");
    
    #if JVET_O0526_MIN_CTU_SIZE
      xConfirmPara( m_uiCTUSize < 32,                                                           "CTUSize must be greater than or equal to 32");
      xConfirmPara( m_uiCTUSize > 128,                                                          "CTUSize must be less than or equal to 128");
      xConfirmPara( m_uiCTUSize != 32 && m_uiCTUSize != 64 && m_uiCTUSize != 128,               "CTUSize must be a power of 2 (32, 64, or 128)");
    #else
    
      xConfirmPara( m_uiCTUSize < 16,                                                           "Maximum partition width size should be larger than or equal to 16");
      xConfirmPara( m_uiCTUSize < 16,                                                           "Maximum partition height size should be larger than or equal to 16");
    
    #if !JVET_O0640_PICTURE_SIZE_CONSTRAINT
    
      xConfirmPara( (m_iSourceWidth  % (1<<MIN_CU_LOG2))!=0,                                    "Resulting coded frame width must be a multiple of the minimum unit size");
      xConfirmPara( (m_iSourceHeight % (1<<MIN_CU_LOG2))!=0,                                    "Resulting coded frame height must be a multiple of the minimum unit size");
      xConfirmPara( (m_iSourceWidth  % (1<<MIN_CU_LOG2))!=0,                                    "Resulting coded frame width must be a multiple of the minimum unit size");
      xConfirmPara( (m_iSourceHeight % (1<<MIN_CU_LOG2))!=0,                                    "Resulting coded frame height must be a multiple of the minimum unit size");
      xConfirmPara( (m_iSourceWidth  % (1<<MIN_CU_LOG2))!=0,                                    "Resulting coded frame width must be a multiple of the minimum unit size");
      xConfirmPara( (m_iSourceHeight % (1<<MIN_CU_LOG2))!=0,                                    "Resulting coded frame height must be a multiple of the minimum unit size");
    
      xConfirmPara( m_uiMaxCUDepth < 1,                                                         "MaxPartitionDepth must be greater than zero");
      xConfirmPara( (m_uiMaxCUWidth  >> m_uiMaxCUDepth) < 4,                                    "Minimum partition width size should be larger than or equal to 8");
      xConfirmPara( (m_uiMaxCUHeight >> m_uiMaxCUDepth) < 4,                                    "Minimum partition height size should be larger than or equal to 8");
      xConfirmPara( m_uiMaxCUWidth < 16,                                                        "Maximum partition width size should be larger than or equal to 16");
      xConfirmPara( m_uiMaxCUHeight < 16,                                                       "Maximum partition height size should be larger than or equal to 16");
    
    #if JVET_O0640_PICTURE_SIZE_CONSTRAINT
      xConfirmPara( (m_iSourceWidth  % (std::max(8, int(m_uiMaxCUWidth  >> (m_uiMaxCUDepth - 1))))) != 0, "Resulting coded frame width must be a multiple of Max(8, the minimum CU size)");
      xConfirmPara( (m_iSourceHeight % (std::max(8, int(m_uiMaxCUHeight >> (m_uiMaxCUDepth - 1))))) != 0, "Resulting coded frame height must be a multiple of Max(8, the minimum CU size)");
    #else
    
      xConfirmPara( (m_iSourceWidth  % (m_uiMaxCUWidth  >> (m_uiMaxCUDepth-1)))!=0,             "Resulting coded frame width must be a multiple of the minimum CU size");
      xConfirmPara( (m_iSourceHeight % (m_uiMaxCUHeight >> (m_uiMaxCUDepth-1)))!=0,             "Resulting coded frame height must be a multiple of the minimum CU size");
    
    #if MAX_TB_SIZE_SIGNALLING
      xConfirmPara( m_log2MaxTbSize > 6, "Log2MaxTbSize must be 6 or smaller." );
    
    Yan Zhang's avatar
    Yan Zhang committed
    #endif
    #if JVET_O0545_MAX_TB_SIGNALLING
      xConfirmPara( m_log2MaxTbSize < 5,  "Log2MaxTbSize must be 5 or greater." );
    
      xConfirmPara( m_maxNumMergeCand < 1,  "MaxNumMergeCand must be 1 or greater.");
      xConfirmPara( m_maxNumMergeCand > MRG_MAX_NUM_CANDS, "MaxNumMergeCand must be no more than MRG_MAX_NUM_CANDS." );
    
      xConfirmPara( m_maxNumTriangleCand > TRIANGLE_MAX_NUM_UNI_CANDS, "MaxNumTriangleCand must be no more than TRIANGLE_MAX_NUM_UNI_CANDS." );
      xConfirmPara( m_maxNumTriangleCand > m_maxNumMergeCand, "MaxNumTriangleCand must be no more than MaxNumMergeCand." );
      xConfirmPara( 0 < m_maxNumTriangleCand && m_maxNumTriangleCand < 2, "MaxNumTriangleCand must be no less than 2 unless MaxNumTriangleCand is 0." );
    
    Yan Zhang's avatar
    Yan Zhang committed
    #if JVET_O0455_IBC_MAX_MERGE_NUM
      xConfirmPara( m_maxNumIBCMergeCand < 1, "MaxNumIBCMergeCand must be 1 or greater." );
      xConfirmPara( m_maxNumIBCMergeCand > IBC_MRG_MAX_NUM_CANDS, "MaxNumIBCMergeCand must be no more than IBC_MRG_MAX_NUM_CANDS." );
    
      xConfirmPara( m_maxNumAffineMergeCand < 1, "MaxNumAffineMergeCand must be 1 or greater." );
    
      xConfirmPara( m_maxNumAffineMergeCand > AFFINE_MRG_MAX_NUM_CANDS, "MaxNumAffineMergeCand must be no more than AFFINE_MRG_MAX_NUM_CANDS." );
    
      if ( m_Affine == 0 )
      {
        m_maxNumAffineMergeCand = m_SubPuMvpMode;
    
    #if JVET_O0070_PROF
        if (m_PROF) msg(WARNING, "PROF is forcefully disabled when Affine is off \n");
        m_PROF = false;
    #endif
    
    Tung Nguyen's avatar
    Tung Nguyen committed
      xConfirmPara( m_MTS < 0 || m_MTS > 3, "MTS must be greater than 0 smaller than 4" );
      xConfirmPara( m_MTSIntraMaxCand < 0 || m_MTSIntraMaxCand > 5, "m_MTSIntraMaxCand must be greater than 0 and smaller than 6" );
      xConfirmPara( m_MTSInterMaxCand < 0 || m_MTSInterMaxCand > 5, "m_MTSInterMaxCand must be greater than 0 and smaller than 6" );
    
    Jani Lainema's avatar
    Jani Lainema committed
      xConfirmPara( m_MTS != 0 && m_MTSImplicit != 0, "Both explicit and implicit MTS cannot be enabled at the same time" );
    
      if( m_usePCM)
      {
        for (uint32_t channelType = 0; channelType < MAX_NUM_CHANNEL_TYPE; channelType++)
        {
          xConfirmPara(((m_MSBExtendedBitDepth[channelType] > m_internalBitDepth[channelType]) && m_bPCMInputBitDepthFlag), "PCM bit depth cannot be greater than internal bit depth (PCMInputBitDepthFlag cannot be used when InputBitDepth or MSBExtendedBitDepth > InternalBitDepth)");
        }
        xConfirmPara(  m_uiPCMLog2MinSize < 3,                                      "PCMLog2MinSize must be 3 or greater.");
        xConfirmPara(  m_uiPCMLog2MinSize > 5,                                      "PCMLog2MinSize must be 5 or smaller.");
        xConfirmPara(  m_pcmLog2MaxSize > 5,                                        "PCMLog2MaxSize must be 5 or smaller.");
        xConfirmPara(  m_pcmLog2MaxSize < m_uiPCMLog2MinSize,                       "PCMLog2MaxSize must be equal to or greater than m_uiPCMLog2MinSize.");
      }
    
      if (m_sliceMode!=NO_SLICES)
      {
        xConfirmPara( m_sliceArgument < 1 ,         "SliceArgument should be larger than or equal to 1" );
      }
    
    
      bool tileFlag = (m_numTileColumnsMinus1 > 0 || m_numTileRowsMinus1 > 0 );
      if (m_profile!=Profile::HIGHTHROUGHPUTREXT)
      {
        xConfirmPara( tileFlag && m_entropyCodingSyncEnabledFlag, "Tiles and entropy-coding-sync (Wavefronts) can not be applied together, except in the High Throughput Intra 4:4:4 16 profile");
      }
    
      xConfirmPara( m_iSourceWidth  % SPS::getWinUnitX(m_chromaFormatIDC) != 0, "Picture width must be an integer multiple of the specified chroma subsampling");
      xConfirmPara( m_iSourceHeight % SPS::getWinUnitY(m_chromaFormatIDC) != 0, "Picture height must be an integer multiple of the specified chroma subsampling");
    
      xConfirmPara( m_aiPad[0] % SPS::getWinUnitX(m_chromaFormatIDC) != 0, "Horizontal padding must be an integer multiple of the specified chroma subsampling");
      xConfirmPara( m_aiPad[1] % SPS::getWinUnitY(m_chromaFormatIDC) != 0, "Vertical padding must be an integer multiple of the specified chroma subsampling");
    
      xConfirmPara( m_confWinLeft   % SPS::getWinUnitX(m_chromaFormatIDC) != 0, "Left conformance window offset must be an integer multiple of the specified chroma subsampling");
      xConfirmPara( m_confWinRight  % SPS::getWinUnitX(m_chromaFormatIDC) != 0, "Right conformance window offset must be an integer multiple of the specified chroma subsampling");
      xConfirmPara( m_confWinTop    % SPS::getWinUnitY(m_chromaFormatIDC) != 0, "Top conformance window offset must be an integer multiple of the specified chroma subsampling");
      xConfirmPara( m_confWinBottom % SPS::getWinUnitY(m_chromaFormatIDC) != 0, "Bottom conformance window offset must be an integer multiple of the specified chroma subsampling");
    
    
      // max CU width and height should be power of 2
      uint32_t ui = m_uiMaxCUWidth;
      while(ui)
      {
        ui >>= 1;
        if( (ui & 1) == 1)
        {
          xConfirmPara( ui != 1 , "Width should be 2^n");
        }
      }
      ui = m_uiMaxCUHeight;
      while(ui)
      {
        ui >>= 1;
        if( (ui & 1) == 1)
        {
          xConfirmPara( ui != 1 , "Height should be 2^n");
        }
      }
    
      /* if this is an intra-only sequence, ie IntraPeriod=1, don't verify the GOP structure
       * This permits the ability to omit a GOP structure specification */
      if (m_iIntraPeriod == 1 && m_GOPList[0].m_POC == -1)
      {
        m_GOPList[0] = GOPEntry();
        m_GOPList[0].m_QPFactor = 1;
        m_GOPList[0].m_betaOffsetDiv2 = 0;
        m_GOPList[0].m_tcOffsetDiv2 = 0;
        m_GOPList[0].m_POC = 1;
    
    Hendry's avatar
    Hendry committed
        m_RPLList0[0] = RPLEntry();
        m_RPLList1[0] = RPLEntry();
        m_RPLList0[0].m_POC = m_RPLList1[0].m_POC = 1;
        m_RPLList0[0].m_numRefPicsActive = 4;
        m_GOPList[0].m_numRefPicsActive0 = 4;
    
      }
      else
      {
        xConfirmPara( m_intraConstraintFlag, "IntraConstraintFlag cannot be 1 for inter sequences");
      }
    
    
      int multipleFactor = m_compositeRefEnabled ? 2 : 1;
    
      bool verifiedGOP=false;
      bool errorGOP=false;
      int checkGOP=1;
      int numRefs = m_isField ? 2 : 1;
    
      int refList[MAX_NUM_REF_PICS+1] = {0};
    
      if(m_isField)
      {
        refList[1] = 1;
      }
      bool isOK[MAX_GOP];
      for(int i=0; i<MAX_GOP; i++)
      {
        isOK[i]=false;
      }
      int numOK=0;
      xConfirmPara( m_iIntraPeriod >=0&&(m_iIntraPeriod%m_iGOPSize!=0), "Intra period must be a multiple of GOPSize, or -1" );
    
      for(int i=0; i<m_iGOPSize; i++)
      {
    
        if (m_GOPList[i].m_POC == m_iGOPSize * multipleFactor)
    
        {
          xConfirmPara( m_GOPList[i].m_temporalId!=0 , "The last frame in each GOP must have temporal ID = 0 " );
        }
      }
    
      if ( (m_iIntraPeriod != 1) && !m_loopFilterOffsetInPPS && (!m_bLoopFilterDisable) )
      {
        for(int i=0; i<m_iGOPSize; i++)
        {
          xConfirmPara( (m_GOPList[i].m_betaOffsetDiv2 + m_loopFilterBetaOffsetDiv2) < -6 || (m_GOPList[i].m_betaOffsetDiv2 + m_loopFilterBetaOffsetDiv2) > 6, "Loop Filter Beta Offset div. 2 for one of the GOP entries exceeds supported range (-6 to 6)" );
          xConfirmPara( (m_GOPList[i].m_tcOffsetDiv2 + m_loopFilterTcOffsetDiv2) < -6 || (m_GOPList[i].m_tcOffsetDiv2 + m_loopFilterTcOffsetDiv2) > 6, "Loop Filter Tc Offset div. 2 for one of the GOP entries exceeds supported range (-6 to 6)" );
        }
      }
    
    #if W0038_CQP_ADJ
      for(int i=0; i<m_iGOPSize; i++)
      {
        xConfirmPara( abs(m_GOPList[i].m_CbQPoffset               ) > 12, "Cb QP Offset for one of the GOP entries exceeds supported range (-12 to 12)" );
        xConfirmPara( abs(m_GOPList[i].m_CbQPoffset + m_cbQpOffset) > 12, "Cb QP Offset for one of the GOP entries, when combined with the PPS Cb offset, exceeds supported range (-12 to 12)" );
        xConfirmPara( abs(m_GOPList[i].m_CrQPoffset               ) > 12, "Cr QP Offset for one of the GOP entries exceeds supported range (-12 to 12)" );
        xConfirmPara( abs(m_GOPList[i].m_CrQPoffset + m_crQpOffset) > 12, "Cr QP Offset for one of the GOP entries, when combined with the PPS Cr offset, exceeds supported range (-12 to 12)" );
      }
      xConfirmPara( abs(m_sliceChromaQpOffsetIntraOrPeriodic[0]                 ) > 12, "Intra/periodic Cb QP Offset exceeds supported range (-12 to 12)" );
      xConfirmPara( abs(m_sliceChromaQpOffsetIntraOrPeriodic[0]  + m_cbQpOffset ) > 12, "Intra/periodic Cb QP Offset, when combined with the PPS Cb offset, exceeds supported range (-12 to 12)" );
      xConfirmPara( abs(m_sliceChromaQpOffsetIntraOrPeriodic[1]                 ) > 12, "Intra/periodic Cr QP Offset exceeds supported range (-12 to 12)" );
      xConfirmPara( abs(m_sliceChromaQpOffsetIntraOrPeriodic[1]  + m_crQpOffset ) > 12, "Intra/periodic Cr QP Offset, when combined with the PPS Cr offset, exceeds supported range (-12 to 12)" );
    #endif
    
    
    Hendry's avatar
    Hendry committed
      int extraRPLs = 0;
      //start looping through frames in coding order until we can verify that the GOP structure is correct.
      while (!verifiedGOP && !errorGOP)
      {
        int curGOP = (checkGOP - 1) % m_iGOPSize;
        int curPOC = ((checkGOP - 1) / m_iGOPSize)*m_iGOPSize * multipleFactor + m_RPLList0[curGOP].m_POC;
        if (m_RPLList0[curGOP].m_POC < 0 || m_RPLList1[curGOP].m_POC < 0)
        {
          msg(WARNING, "\nError: found fewer Reference Picture Sets than GOPSize\n");
          errorGOP = true;
        }
        else
        {
          //check that all reference pictures are available, or have a POC < 0 meaning they might be available in the next GOP.
          bool beforeI = false;
          for (int i = 0; i< m_RPLList0[curGOP].m_numRefPics; i++)
          {
            int absPOC = curPOC - m_RPLList0[curGOP].m_deltaRefPics[i];
            if (absPOC < 0)
            {
              beforeI = true;
            }
            else
            {
              bool found = false;
              for (int j = 0; j<numRefs; j++)
              {
                if (refList[j] == absPOC)
                {
                  found = true;
                  for (int k = 0; k<m_iGOPSize; k++)
                  {
                    if (absPOC % (m_iGOPSize * multipleFactor) == m_RPLList0[k].m_POC % (m_iGOPSize * multipleFactor))
                    {
                      if (m_RPLList0[k].m_temporalId == m_RPLList0[curGOP].m_temporalId)
                      {
                        m_RPLList0[k].m_refPic = true;
                      }
                    }
                  }
                }
              }
              if (!found)
              {
                msg(WARNING, "\nError: ref pic %d is not available for GOP frame %d\n", m_RPLList0[curGOP].m_deltaRefPics[i], curGOP + 1);
                errorGOP = true;
              }
            }
          }
          if (!beforeI && !errorGOP)
          {
            //all ref frames were present
            if (!isOK[curGOP])
            {
              numOK++;
              isOK[curGOP] = true;
              if (numOK == m_iGOPSize)
              {
                verifiedGOP = true;
              }
            }
          }
          else
          {
            //create a new RPLEntry for this frame containing all the reference pictures that were available (POC > 0)
            m_RPLList0[m_iGOPSize + extraRPLs] = m_RPLList0[curGOP];
            m_RPLList1[m_iGOPSize + extraRPLs] = m_RPLList1[curGOP];
            int newRefs0 = 0;
            for (int i = 0; i< m_RPLList0[curGOP].m_numRefPics; i++)
            {
              int absPOC = curPOC - m_RPLList0[curGOP].m_deltaRefPics[i];
              if (absPOC >= 0)
              {
                m_RPLList0[m_iGOPSize + extraRPLs].m_deltaRefPics[newRefs0] = m_RPLList0[curGOP].m_deltaRefPics[i];
                newRefs0++;
              }
            }
            int numPrefRefs0 = m_RPLList0[curGOP].m_numRefPicsActive;
    
            int newRefs1 = 0;
            for (int i = 0; i< m_RPLList1[curGOP].m_numRefPics; i++)
            {
              int absPOC = curPOC - m_RPLList1[curGOP].m_deltaRefPics[i];
              if (absPOC >= 0)
              {
                m_RPLList1[m_iGOPSize + extraRPLs].m_deltaRefPics[newRefs1] = m_RPLList1[curGOP].m_deltaRefPics[i];
                newRefs1++;
              }
            }
            int numPrefRefs1 = m_RPLList1[curGOP].m_numRefPicsActive;
    
            for (int offset = -1; offset>-checkGOP; offset--)
            {
              //step backwards in coding order and include any extra available pictures we might find useful to replace the ones with POC < 0.
              int offGOP = (checkGOP - 1 + offset) % m_iGOPSize;
              int offPOC = ((checkGOP - 1 + offset) / m_iGOPSize)*(m_iGOPSize * multipleFactor) + m_RPLList0[offGOP].m_POC;
              if (offPOC >= 0 && m_RPLList0[offGOP].m_temporalId <= m_RPLList0[curGOP].m_temporalId)
              {
                bool newRef = false;
                for (int i = 0; i<(newRefs0 + newRefs1); i++)
                {
                  if (refList[i] == offPOC)
                  {
                    newRef = true;
                  }
                }
                for (int i = 0; i<newRefs0; i++)
                {
                  if (m_RPLList0[m_iGOPSize + extraRPLs].m_deltaRefPics[i] == curPOC - offPOC)
                  {
                    newRef = false;
                  }
                }
                if (newRef)
                {
                  int insertPoint = newRefs0;
                  //this picture can be added, find appropriate place in list and insert it.
                  if (m_RPLList0[offGOP].m_temporalId == m_RPLList0[curGOP].m_temporalId)
                  {
                    m_RPLList0[offGOP].m_refPic = true;
                  }
                  for (int j = 0; j<newRefs0; j++)
                  {
                    if (m_RPLList0[m_iGOPSize + extraRPLs].m_deltaRefPics[j] > curPOC - offPOC && curPOC - offPOC > 0)
                    {
                      insertPoint = j;
                      break;
                    }
                  }
                  int prev = curPOC - offPOC;
                  for (int j = insertPoint; j<newRefs0 + 1; j++)
                  {
                    int newPrev = m_RPLList0[m_iGOPSize + extraRPLs].m_deltaRefPics[j];
                    m_RPLList0[m_iGOPSize + extraRPLs].m_deltaRefPics[j] = prev;
                    prev = newPrev;
                  }
                  newRefs0++;
                }
              }
              if (newRefs0 >= numPrefRefs0)
              {
                break;
              }
            }
    
            for (int offset = -1; offset>-checkGOP; offset--)
            {
              //step backwards in coding order and include any extra available pictures we might find useful to replace the ones with POC < 0.
              int offGOP = (checkGOP - 1 + offset) % m_iGOPSize;
              int offPOC = ((checkGOP - 1 + offset) / m_iGOPSize)*(m_iGOPSize * multipleFactor) + m_RPLList1[offGOP].m_POC;
              if (offPOC >= 0 && m_RPLList1[offGOP].m_temporalId <= m_RPLList1[curGOP].m_temporalId)
              {
                bool newRef = false;
                for (int i = 0; i<(newRefs0 + newRefs1); i++)
                {
                  if (refList[i] == offPOC)
                  {
                    newRef = true;
                  }
                }
                for (int i = 0; i<newRefs1; i++)
                {
                  if (m_RPLList1[m_iGOPSize + extraRPLs].m_deltaRefPics[i] == curPOC - offPOC)
                  {
                    newRef = false;
                  }
                }
                if (newRef)
                {
                  int insertPoint = newRefs1;