Skip to content
Snippets Groups Projects
EncAppCfg.cpp 199 KiB
Newer Older
  • Learn to ignore specific revisions
  •   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)");
    
    #if !JVET_N0671_SUPPRESS_WARNINGS
    
      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");
    #endif // !JVET_N0671_SUPPRESS_WARNINGS
    
    
      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.");
      }
    
    #if !JVET_N0671_CHROMA_FORMAT_422
      xConfirmPara(m_chromaFormatIDC == CHROMA_422, "4:2:2 chroma sampling format not supported with current compiler setting. Set compiler flag \"JVET_N0671_CHROMA_FORMAT_422\" equal to 1 for enabling 4:2:2.\n\n");
    #endif // !JVET_N0671_CHROMA_FORMAT_422
    
    
    
      // 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;
    
    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;
    
    
      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_N0054_JOINT_CHROMA
      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" );
    #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");
      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");
      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");
      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." );
    #endif
    
      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_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;
      }
    
    
    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" );
      }
    
    #if HEVC_DEPENDENT_SLICES
      if (m_sliceSegmentMode!=NO_SLICES)
      {
        xConfirmPara( m_sliceSegmentArgument < 1 ,         "SliceSegmentArgument should be larger than or equal to 1" );
      }
    #endif
    
      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");
    
      xConfirmPara( m_defaultDisplayWindowFlag && !m_vuiParametersPresentFlag, "VUI needs to be enabled for default display window");
    
      if (m_defaultDisplayWindowFlag)
      {
        xConfirmPara( m_defDispWinLeftOffset   % SPS::getWinUnitX(m_chromaFormatIDC) != 0, "Left default display window offset must be an integer multiple of the specified chroma subsampling");
        xConfirmPara( m_defDispWinRightOffset  % SPS::getWinUnitX(m_chromaFormatIDC) != 0, "Right default display window offset must be an integer multiple of the specified chroma subsampling");
        xConfirmPara( m_defDispWinTopOffset    % SPS::getWinUnitY(m_chromaFormatIDC) != 0, "Top default display window offset must be an integer multiple of the specified chroma subsampling");
        xConfirmPara( m_defDispWinBottomOffset % SPS::getWinUnitY(m_chromaFormatIDC) != 0, "Bottom default display 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;
        m_GOPList[0].m_numRefPicsActive = 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];
      refList[0]=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
    
      m_extraRPSs=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_GOPList[curGOP].m_POC;
    
        if(m_GOPList[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_GOPList[curGOP].m_numRefPics; i++)
          {
            int absPOC = curPOC+m_GOPList[curGOP].m_referencePics[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_GOPList[k].m_POC % (m_iGOPSize * multipleFactor))
    
                    {
                      if(m_GOPList[k].m_temporalId==m_GOPList[curGOP].m_temporalId)
                      {
                        m_GOPList[k].m_refPic = true;
                      }
                      m_GOPList[curGOP].m_usedByCurrPic[i]=m_GOPList[k].m_temporalId<=m_GOPList[curGOP].m_temporalId;
                    }
                  }
                }
              }
              if(!found)
              {
                msg( WARNING, "\nError: ref pic %d is not available for GOP frame %d\n",m_GOPList[curGOP].m_referencePics[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 GOPEntry for this frame containing all the reference pictures that were available (POC > 0)
            m_GOPList[m_iGOPSize+m_extraRPSs]=m_GOPList[curGOP];
            int newRefs=0;
            for(int i = 0; i< m_GOPList[curGOP].m_numRefPics; i++)
            {
              int absPOC = curPOC+m_GOPList[curGOP].m_referencePics[i];
              if(absPOC>=0)
              {
                m_GOPList[m_iGOPSize+m_extraRPSs].m_referencePics[newRefs]=m_GOPList[curGOP].m_referencePics[i];
                m_GOPList[m_iGOPSize+m_extraRPSs].m_usedByCurrPic[newRefs]=m_GOPList[curGOP].m_usedByCurrPic[i];
                newRefs++;
              }
            }
            int numPrefRefs = m_GOPList[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_GOPList[offGOP].m_POC;
    
              if(offPOC>=0&&m_GOPList[offGOP].m_temporalId<=m_GOPList[curGOP].m_temporalId)
              {
                bool newRef=false;
                for(int i=0; i<numRefs; i++)
                {
                  if(refList[i]==offPOC)
                  {
                    newRef=true;
                  }
                }
                for(int i=0; i<newRefs; i++)
                {
                  if(m_GOPList[m_iGOPSize+m_extraRPSs].m_referencePics[i]==offPOC-curPOC)
                  {
                    newRef=false;
                  }
                }
                if(newRef)
                {
                  int insertPoint=newRefs;
                  //this picture can be added, find appropriate place in list and insert it.
                  if(m_GOPList[offGOP].m_temporalId==m_GOPList[curGOP].m_temporalId)
                  {
                    m_GOPList[offGOP].m_refPic = true;
                  }
                  for(int j=0; j<newRefs; j++)
                  {
                    if(m_GOPList[m_iGOPSize+m_extraRPSs].m_referencePics[j]<offPOC-curPOC||m_GOPList[m_iGOPSize+m_extraRPSs].m_referencePics[j]>0)
                    {
                      insertPoint = j;
                      break;
                    }
                  }
                  int prev = offPOC-curPOC;
                  int prevUsed = m_GOPList[offGOP].m_temporalId<=m_GOPList[curGOP].m_temporalId;
                  for(int j=insertPoint; j<newRefs+1; j++)
                  {
                    int newPrev = m_GOPList[m_iGOPSize+m_extraRPSs].m_referencePics[j];
                    int newUsed = m_GOPList[m_iGOPSize+m_extraRPSs].m_usedByCurrPic[j];
                    m_GOPList[m_iGOPSize+m_extraRPSs].m_referencePics[j]=prev;
                    m_GOPList[m_iGOPSize+m_extraRPSs].m_usedByCurrPic[j]=prevUsed;
                    prevUsed=newUsed;
                    prev=newPrev;
                  }
                  newRefs++;
                }
              }
              if(newRefs>=numPrefRefs)
              {
                break;
              }
            }
            m_GOPList[m_iGOPSize+m_extraRPSs].m_numRefPics=newRefs;
            m_GOPList[m_iGOPSize+m_extraRPSs].m_POC = curPOC;
            if (m_extraRPSs == 0)
            {
              m_GOPList[m_iGOPSize+m_extraRPSs].m_interRPSPrediction = 0;
              m_GOPList[m_iGOPSize+m_extraRPSs].m_numRefIdc = 0;
            }
            else
            {
              int rIdx =  m_iGOPSize + m_extraRPSs - 1;
              int refPOC = m_GOPList[rIdx].m_POC;
              int refPics = m_GOPList[rIdx].m_numRefPics;
              int newIdc=0;
              for(int i = 0; i<= refPics; i++)
              {
                int deltaPOC = ((i != refPics)? m_GOPList[rIdx].m_referencePics[i] : 0);  // check if the reference abs POC is >= 0
                int absPOCref = refPOC+deltaPOC;
                int refIdc = 0;
                for (int j = 0; j < m_GOPList[m_iGOPSize+m_extraRPSs].m_numRefPics; j++)
                {
                  if ( (absPOCref - curPOC) == m_GOPList[m_iGOPSize+m_extraRPSs].m_referencePics[j])
                  {
                    if (m_GOPList[m_iGOPSize+m_extraRPSs].m_usedByCurrPic[j])
                    {
                      refIdc = 1;
                    }
                    else
                    {
                      refIdc = 2;
                    }
                  }
                }
                m_GOPList[m_iGOPSize+m_extraRPSs].m_refIdc[newIdc]=refIdc;
                newIdc++;
              }
              m_GOPList[m_iGOPSize+m_extraRPSs].m_interRPSPrediction = 1;
              m_GOPList[m_iGOPSize+m_extraRPSs].m_numRefIdc = newIdc;
              m_GOPList[m_iGOPSize+m_extraRPSs].m_deltaRPS = refPOC - m_GOPList[m_iGOPSize+m_extraRPSs].m_POC;
            }
            curGOP=m_iGOPSize+m_extraRPSs;
            m_extraRPSs++;
          }
          numRefs=0;
          for(int i = 0; i< m_GOPList[curGOP].m_numRefPics; i++)
          {
            int absPOC = curPOC+m_GOPList[curGOP].m_referencePics[i];
            if(absPOC >= 0)
            {
              refList[numRefs]=absPOC;
              numRefs++;
            }
          }
          refList[numRefs]=curPOC;
          numRefs++;
        }
        checkGOP++;
      }
      xConfirmPara(errorGOP,"Invalid GOP structure given");
      m_maxTempLayer = 1;
      for(int i=0; i<m_iGOPSize; i++)
      {
        if(m_GOPList[i].m_temporalId >= m_maxTempLayer)
        {
          m_maxTempLayer = m_GOPList[i].m_temporalId+1;
        }
        xConfirmPara(m_GOPList[i].m_sliceType!='B' && m_GOPList[i].m_sliceType!='P' && m_GOPList[i].m_sliceType!='I', "Slice type must be equal to B or P or I");
      }
      for(int i=0; i<MAX_TLAYER; i++)
      {
        m_numReorderPics[i] = 0;
        m_maxDecPicBuffering[i] = 1;
      }
      for(int i=0; i<m_iGOPSize; i++)
      {
        if(m_GOPList[i].m_numRefPics+1 > m_maxDecPicBuffering[m_GOPList[i].m_temporalId])
        {
          m_maxDecPicBuffering[m_GOPList[i].m_temporalId] = m_GOPList[i].m_numRefPics + 1;
        }
        int highestDecodingNumberWithLowerPOC = 0;
        for(int j=0; j<m_iGOPSize; j++)
        {
          if(m_GOPList[j].m_POC <= m_GOPList[i].m_POC)
          {
            highestDecodingNumberWithLowerPOC = j;
          }
        }
        int numReorder = 0;
        for(int j=0; j<highestDecodingNumberWithLowerPOC; j++)
        {
          if(m_GOPList[j].m_temporalId <= m_GOPList[i].m_temporalId &&
            m_GOPList[j].m_POC > m_GOPList[i].m_POC)
          {
            numReorder++;
          }
        }
        if(numReorder > m_numReorderPics[m_GOPList[i].m_temporalId])
        {
          m_numReorderPics[m_GOPList[i].m_temporalId] = numReorder;
        }
      }
      for(int i=0; i<MAX_TLAYER-1; i++)
      {
        // a lower layer can not have higher value of m_numReorderPics than a higher layer
        if(m_numReorderPics[i+1] < m_numReorderPics[i])
        {
          m_numReorderPics[i+1] = m_numReorderPics[i];
        }
        // the value of num_reorder_pics[ i ] shall be in the range of 0 to max_dec_pic_buffering[ i ] - 1, inclusive
        if(m_numReorderPics[i] > m_maxDecPicBuffering[i] - 1)
        {
          m_maxDecPicBuffering[i] = m_numReorderPics[i] + 1;
        }
        // a lower layer can not have higher value of m_uiMaxDecPicBuffering than a higher layer
        if(m_maxDecPicBuffering[i+1] < m_maxDecPicBuffering[i])
        {
          m_maxDecPicBuffering[i+1] = m_maxDecPicBuffering[i];
        }
      }
    
      // the value of num_reorder_pics[ i ] shall be in the range of 0 to max_dec_pic_buffering[ i ] -  1, inclusive
      if(m_numReorderPics[MAX_TLAYER-1] > m_maxDecPicBuffering[MAX_TLAYER-1] - 1)
      {
        m_maxDecPicBuffering[MAX_TLAYER-1] = m_numReorderPics[MAX_TLAYER-1] + 1;
      }
    
      if(m_vuiParametersPresentFlag && m_bitstreamRestrictionFlag)
      {
        int PicSizeInSamplesY =  m_iSourceWidth * m_iSourceHeight;
        if(tileFlag)
        {
          int maxTileWidth = 0;
          int maxTileHeight = 0;
          int widthInCU = (m_iSourceWidth % m_uiMaxCUWidth) ? m_iSourceWidth/m_uiMaxCUWidth + 1: m_iSourceWidth/m_uiMaxCUWidth;
          int heightInCU = (m_iSourceHeight % m_uiMaxCUHeight) ? m_iSourceHeight/m_uiMaxCUHeight + 1: m_iSourceHeight/m_uiMaxCUHeight;
          if(m_tileUniformSpacingFlag)
          {
            maxTileWidth = m_uiMaxCUWidth*((widthInCU+m_numTileColumnsMinus1)/(m_numTileColumnsMinus1+1));
            maxTileHeight = m_uiMaxCUHeight*((heightInCU+m_numTileRowsMinus1)/(m_numTileRowsMinus1+1));
            // if only the last tile-row is one treeblock higher than the others
            // the maxTileHeight becomes smaller if the last row of treeblocks has lower height than the others
            if(!((heightInCU-1)%(m_numTileRowsMinus1+1)))
            {
              maxTileHeight = maxTileHeight - m_uiMaxCUHeight + (m_iSourceHeight % m_uiMaxCUHeight);
            }
            // if only the last tile-column is one treeblock wider than the others
            // the maxTileWidth becomes smaller if the last column of treeblocks has lower width than the others
            if(!((widthInCU-1)%(m_numTileColumnsMinus1+1)))
            {
              maxTileWidth = maxTileWidth - m_uiMaxCUWidth + (m_iSourceWidth % m_uiMaxCUWidth);
            }
          }
          else // not uniform spacing
          {
            if(m_numTileColumnsMinus1<1)
            {
              maxTileWidth = m_iSourceWidth;
            }
            else
            {
              int accColumnWidth = 0;
              for(int col=0; col<(m_numTileColumnsMinus1); col++)
              {
                maxTileWidth = m_tileColumnWidth[col]>maxTileWidth ? m_tileColumnWidth[col]:maxTileWidth;
                accColumnWidth += m_tileColumnWidth[col];
              }
              maxTileWidth = (widthInCU-accColumnWidth)>maxTileWidth ? m_uiMaxCUWidth*(widthInCU-accColumnWidth):m_uiMaxCUWidth*maxTileWidth;
            }
            if(m_numTileRowsMinus1<1)
            {
              maxTileHeight = m_iSourceHeight;
            }
            else
            {
              int accRowHeight = 0;
              for(int row=0; row<(m_numTileRowsMinus1); row++)
              {
                maxTileHeight = m_tileRowHeight[row]>maxTileHeight ? m_tileRowHeight[row]:maxTileHeight;
                accRowHeight += m_tileRowHeight[row];
              }
              maxTileHeight = (heightInCU-accRowHeight)>maxTileHeight ? m_uiMaxCUHeight*(heightInCU-accRowHeight):m_uiMaxCUHeight*maxTileHeight;
            }
          }
          int maxSizeInSamplesY = maxTileWidth*maxTileHeight;
          m_minSpatialSegmentationIdc = 4*PicSizeInSamplesY/maxSizeInSamplesY-4;
        }
        else if(m_entropyCodingSyncEnabledFlag)
        {
          m_minSpatialSegmentationIdc = 4*PicSizeInSamplesY/((2*m_iSourceHeight+m_iSourceWidth)*m_uiMaxCUHeight)-4;
        }
        else if(m_sliceMode == FIXED_NUMBER_OF_CTU)
        {
          m_minSpatialSegmentationIdc = 4*PicSizeInSamplesY/(m_sliceArgument*m_uiMaxCUWidth*m_uiMaxCUHeight)-4;
        }
        else
        {
          m_minSpatialSegmentationIdc = 0;
        }
      }
    
    
    Valeri George's avatar
    Valeri George committed
      if ((m_MCTSEncConstraint) && (m_bLFCrossTileBoundaryFlag))
      {
        printf("Warning: Constrained Encoding for Motion Constrained Tile Sets (MCTS) is enabled. Disabling filtering across tile boundaries!\n");
        m_bLFCrossTileBoundaryFlag = false;
      }
      if ((m_MCTSEncConstraint) && (m_TMVPModeId))
      {
        printf("Warning: Constrained Encoding for Motion Constrained Tile Sets (MCTS) is enabled. Disabling TMVP!\n");
        m_TMVPModeId = 0;
      }
    
      if ((m_MCTSEncConstraint) && ( m_alf ))
      {
        printf("Warning: Constrained Encoding for Motion Constrained Tile Sets (MCTS) is enabled. Disabling ALF!\n");
        m_alf = false;
      }
      if( ( m_MCTSEncConstraint ) && ( m_BIO ) )
      {
        printf( "Warning: Constrained Encoding for Motion Constrained Tile Sets (MCTS) is enabled. Disabling BIO!\n" );
        m_BIO = false;
      }
    
    
      if (m_toneMappingInfoSEIEnabled)
      {
        xConfirmPara( m_toneMapCodedDataBitDepth < 8 || m_toneMapCodedDataBitDepth > 14 , "SEIToneMapCodedDataBitDepth must be in rage 8 to 14");
        xConfirmPara( m_toneMapTargetBitDepth < 1 || (m_toneMapTargetBitDepth > 16 && m_toneMapTargetBitDepth < 255) , "SEIToneMapTargetBitDepth must be in rage 1 to 16 or equal to 255");
        xConfirmPara( m_toneMapModelId < 0 || m_toneMapModelId > 4 , "SEIToneMapModelId must be in rage 0 to 4");
        xConfirmPara( m_cameraIsoSpeedValue == 0, "SEIToneMapCameraIsoSpeedValue shall not be equal to 0");
        xConfirmPara( m_exposureIndexValue  == 0, "SEIToneMapExposureIndexValue shall not be equal to 0");
        xConfirmPara( m_extendedRangeWhiteLevel < 100, "SEIToneMapExtendedRangeWhiteLevel should be greater than or equal to 100");
        xConfirmPara( m_nominalBlackLevelLumaCodeValue >= m_nominalWhiteLevelLumaCodeValue, "SEIToneMapNominalWhiteLevelLumaCodeValue shall be greater than SEIToneMapNominalBlackLevelLumaCodeValue");
        xConfirmPara( m_extendedWhiteLevelLumaCodeValue < m_nominalWhiteLevelLumaCodeValue, "SEIToneMapExtendedWhiteLevelLumaCodeValue shall be greater than or equal to SEIToneMapNominalWhiteLevelLumaCodeValue");
      }
    
      if (m_kneeSEIEnabled && !m_kneeSEICancelFlag)
      {
        xConfirmPara( m_kneeSEINumKneePointsMinus1 < 0 || m_kneeSEINumKneePointsMinus1 > 998, "SEIKneeFunctionNumKneePointsMinus1 must be in the range of 0 to 998");
        for ( uint32_t i=0; i<=m_kneeSEINumKneePointsMinus1; i++ )
        {
          xConfirmPara( m_kneeSEIInputKneePoint[i] < 1 || m_kneeSEIInputKneePoint[i] > 999, "SEIKneeFunctionInputKneePointValue must be in the range of 1 to 999");
          xConfirmPara( m_kneeSEIOutputKneePoint[i] < 0 || m_kneeSEIOutputKneePoint[i] > 1000, "SEIKneeFunctionInputKneePointValue must be in the range of 0 to 1000");
          if ( i > 0 )
          {
            xConfirmPara( m_kneeSEIInputKneePoint[i-1] >= m_kneeSEIInputKneePoint[i],  "The i-th SEIKneeFunctionInputKneePointValue must be greater than the (i-1)-th value");
            xConfirmPara( m_kneeSEIOutputKneePoint[i-1] > m_kneeSEIOutputKneePoint[i],  "The i-th SEIKneeFunctionOutputKneePointValue must be greater than or equal to the (i-1)-th value");
          }
        }
      }
    
      if (m_chromaResamplingFilterSEIenabled)
      {
        xConfirmPara( (m_chromaFormatIDC == CHROMA_400 ), "chromaResamplingFilterSEI is not allowed to be present when ChromaFormatIDC is equal to zero (4:0:0)" );
        xConfirmPara(m_vuiParametersPresentFlag && m_chromaLocInfoPresentFlag && (m_chromaSampleLocTypeTopField != m_chromaSampleLocTypeBottomField ), "When chromaResamplingFilterSEI is enabled, ChromaSampleLocTypeTopField has to be equal to ChromaSampleLocTypeBottomField" );
      }
    
      if ( m_RCEnableRateControl )
      {
        if ( m_RCForceIntraQP )
        {
          if ( m_RCInitialQP == 0 )
          {
            msg( WARNING, "\nInitial QP for rate control is not specified. Reset not to use force intra QP!" );
            m_RCForceIntraQP = false;
          }
        }
        xConfirmPara( m_uiDeltaQpRD > 0, "Rate control cannot be used together with slice level multiple-QP optimization!\n" );
    #if U0132_TARGET_BITS_SATURATION
        if ((m_RCCpbSaturationEnabled) && (m_level!=Level::NONE) && (m_profile!=Profile::NONE))
        {
          uint32_t uiLevelIdx = (m_level / 10) + (uint32_t)((m_level % 10) / 3);    // (m_level / 30)*3 + ((m_level % 10) / 3);
          xConfirmPara(m_RCCpbSize > g_uiMaxCpbSize[m_levelTier][uiLevelIdx], "RCCpbSize should be smaller than or equal to Max CPB size according to tier and level");
          xConfirmPara(m_RCInitialCpbFullness > 1, "RCInitialCpbFullness should be smaller than or equal to 1");
        }
    #endif
      }
    #if U0132_TARGET_BITS_SATURATION
      else
      {
        xConfirmPara( m_RCCpbSaturationEnabled != 0, "Target bits saturation cannot be processed without Rate control" );
      }
      if (m_vuiParametersPresentFlag)
      {
        xConfirmPara(m_RCTargetBitrate == 0, "A target bit rate is required to be set for VUI/HRD parameters.");
        if (m_RCCpbSize == 0)
        {
          msg( WARNING, "Warning: CPB size is set equal to zero. Adjusting value to be equal to TargetBitrate!\n");
          m_RCCpbSize = m_RCTargetBitrate;
        }
      }
    #endif
    
      xConfirmPara(!m_TransquantBypassEnabledFlag && m_CUTransquantBypassFlagForce, "CUTransquantBypassFlagForce cannot be 1 when TransquantBypassEnableFlag is 0");
    
      xConfirmPara(m_log2ParallelMergeLevel < 2, "Log2ParallelMergeLevel should be larger than or equal to 2");
    
      if (m_framePackingSEIEnabled)
      {
        xConfirmPara(m_framePackingSEIType < 3 || m_framePackingSEIType > 5 , "SEIFramePackingType must be in rage 3 to 5");
      }
    
      if (m_segmentedRectFramePackingSEIEnabled)
      {
        xConfirmPara(m_framePackingSEIEnabled , "SEISegmentedRectFramePacking must be 0 when SEIFramePacking is 1");
      }
    
      if((m_numTileColumnsMinus1 <= 0) && (m_numTileRowsMinus1 <= 0) && m_tmctsSEIEnabled)
      {
        msg( WARNING, "Warning: SEITempMotionConstrainedTileSets is set to false to disable temporal motion-constrained tile sets SEI message because there are no tiles enabled.\n");
        m_tmctsSEIEnabled = false;
      }
    
      if(m_timeCodeSEIEnabled)
      {
        xConfirmPara(m_timeCodeSEINumTs > MAX_TIMECODE_SEI_SETS, "Number of time sets cannot exceed 3");
      }
    
    #if U0033_ALTERNATIVE_TRANSFER_CHARACTERISTICS_SEI
      xConfirmPara(m_preferredTransferCharacteristics > 255, "transfer_characteristics_idc should not be greater than 255.");
    #endif
    
      xConfirmPara( unsigned(m_ImvMode) > 1, "ImvMode exceeds range (0 to 1)" );
    
      xConfirmPara( m_decodeBitstreams[0] == m_bitstreamFileName, "Debug bitstream and the output bitstream cannot be equal.\n" );
      xConfirmPara( m_decodeBitstreams[1] == m_bitstreamFileName, "Decode2 bitstream and the output bitstream cannot be equal.\n" );
      xConfirmPara(unsigned(m_LMChroma) > 1, "LMMode exceeds range (0 to 1)");
    #if EXTENSION_360_VIDEO
      check_failed |= m_ext360.verifyParameters();
    #endif
    
    #undef xConfirmPara
      return check_failed;
    }
    
    const char *profileToString(const Profile::Name profile)
    {
      static const uint32_t numberOfProfiles = sizeof(strToProfile)/sizeof(*strToProfile);
    
      for (uint32_t profileIndex = 0; profileIndex < numberOfProfiles; profileIndex++)
      {
        if (strToProfile[profileIndex].value == profile)
        {
          return strToProfile[profileIndex].str;
        }
      }
    
      //if we get here, we didn't find this profile in the list - so there is an error
      EXIT( "ERROR: Unknown profile \"" << profile << "\" in profileToString" );
      return "";
    }
    
    void EncAppCfg::xPrintParameter()
    {
      //msg( DETAILS, "\n" );
      msg( DETAILS, "Input          File                    : %s\n", m_inputFileName.c_str() );
      msg( DETAILS, "Bitstream      File                    : %s\n", m_bitstreamFileName.c_str() );
      msg( DETAILS, "Reconstruction File                    : %s\n", m_reconFileName.c_str() );
      msg( DETAILS, "Real     Format                        : %dx%d %gHz\n", m_iSourceWidth - m_confWinLeft - m_confWinRight, m_iSourceHeight - m_confWinTop - m_confWinBottom, (double)m_iFrameRate / m_temporalSubsampleRatio );
      msg( DETAILS, "Internal Format                        : %dx%d %gHz\n", m_iSourceWidth, m_iSourceHeight, (double)m_iFrameRate / m_temporalSubsampleRatio );
      msg( DETAILS, "Sequence PSNR output                   : %s\n", ( m_printMSEBasedSequencePSNR ? "Linear average, MSE-based" : "Linear average only" ) );
    
      msg( DETAILS, "Hexadecimal PSNR output                : %s\n", ( m_printHexPsnr ? "Enabled" : "Disabled" ) );
    
      msg( DETAILS, "Sequence MSE output                    : %s\n", ( m_printSequenceMSE ? "Enabled" : "Disabled" ) );
      msg( DETAILS, "Frame MSE output                       : %s\n", ( m_printFrameMSE ? "Enabled" : "Disabled" ) );
      msg( DETAILS, "Cabac-zero-word-padding                : %s\n", ( m_cabacZeroWordPaddingEnabled ? "Enabled" : "Disabled" ) );
      if (m_isField)
      {
        msg( DETAILS, "Frame/Field                            : Field based coding\n" );
        msg( DETAILS, "Field index                            : %u - %d (%d fields)\n", m_FrameSkip, m_FrameSkip + m_framesToBeEncoded - 1, m_framesToBeEncoded );
        msg( DETAILS, "Field Order                            : %s field first\n", m_isTopFieldFirst ? "Top" : "Bottom" );
    
      }
      else
      {
        msg( DETAILS, "Frame/Field                            : Frame based coding\n" );
        msg( DETAILS, "Frame index                            : %u - %d (%d frames)\n", m_FrameSkip, m_FrameSkip + m_framesToBeEncoded - 1, m_framesToBeEncoded );
      }
      if (m_profile == Profile::MAINREXT)
      {
        ExtendedProfileName validProfileName;
        if (m_onePictureOnlyConstraintFlag)
        {
          validProfileName = m_bitDepthConstraint == 8 ? MAIN_444_STILL_PICTURE : (m_bitDepthConstraint == 16 ? MAIN_444_16_STILL_PICTURE : NONE);
        }
        else
        {
          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);
          validProfileName = (bitDepthIdx > 3 || chromaFormatIdx>3) ? NONE : validRExtProfileNames[intraIdx][bitDepthIdx][chromaFormatIdx];
        }
        std::string rextSubProfile;
        if (validProfileName!=NONE)
        {
          rextSubProfile=enumToString(strToExtendedProfile, sizeof(strToExtendedProfile)/sizeof(*strToExtendedProfile), validProfileName);
        }
        if (rextSubProfile == "main_444_16")
        {
          rextSubProfile="main_444_16 [NON STANDARD]";
        }
        msg( DETAILS, "Profile                                : %s (%s)\n", profileToString(m_profile), (rextSubProfile.empty())?"INVALID REXT PROFILE":rextSubProfile.c_str() );
      }
      else
      {
        msg( DETAILS, "Profile                                : %s\n", profileToString(m_profile) );
      }
      msg( DETAILS, "CU size / depth / total-depth          : %d / %d / %d\n", m_uiMaxCUWidth, m_uiMaxCUDepth, m_uiMaxCodingDepth );
    
    #if MAX_TB_SIZE_SIGNALLING
      msg( DETAILS, "Max TB size                            : %d \n", 1 << m_log2MaxTbSize );
    #endif
    
      msg( DETAILS, "Min PCM size                           : %d\n", 1 << m_uiPCMLog2MinSize);
      msg( DETAILS, "Motion search range                    : %d\n", m_iSearchRange );
      msg( DETAILS, "Intra period                           : %d\n", m_iIntraPeriod );
      msg( DETAILS, "Decoding refresh type                  : %d\n", m_iDecodingRefreshType );
    #if QP_SWITCHING_FOR_PARALLEL
      if (m_qpIncrementAtSourceFrame.bPresent)
      {
        msg( DETAILS, "QP                                     : %d (incrementing internal QP at source frame %d)\n", m_iQP, m_qpIncrementAtSourceFrame.value);
      }
      else
      {
        msg( DETAILS, "QP                                     : %d\n", m_iQP);
      }
    #else
      msg( DETAILS, "QP                                     : %5.2f\n", m_fQP );
    #endif
    
      msg( DETAILS, "Max dQP signaling subdiv               : %d\n", m_cuQpDeltaSubdiv);