Skip to content
Snippets Groups Projects
EncAppCfg.cpp 287 KiB
Newer Older
  • Learn to ignore specific revisions
  • /* The copyright in this software is being made available under the BSD
     * License, included below. This software may be subject to other third party
     * and contributor rights, including patent rights, and no such rights are
     * granted under this license.
     *
    
     * Copyright (c) 2010-2019, ITU/ISO/IEC
    
     * All rights reserved.
     *
     * Redistribution and use in source and binary forms, with or without
     * modification, are permitted provided that the following conditions are met:
     *
     *  * Redistributions of source code must retain the above copyright notice,
     *    this list of conditions and the following disclaimer.
     *  * Redistributions in binary form must reproduce the above copyright notice,
     *    this list of conditions and the following disclaimer in the documentation
     *    and/or other materials provided with the distribution.
     *  * Neither the name of the ITU/ISO/IEC nor the names of its contributors may
     *    be used to endorse or promote products derived from this software without
     *    specific prior written permission.
     *
     * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
     * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS
     * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
     * THE POSSIBILITY OF SUCH DAMAGE.
     */
    
    /** \file     EncAppCfg.cpp
        \brief    Handle encoder configuration parameters
    */
    
    #include "EncAppCfg.h"
    
    #include <stdio.h>
    #include <stdlib.h>
    #include <cstring>
    #include <string>
    #include <fstream>
    #include <limits>
    
    #include "Utilities/program_options_lite.h"
    #include "CommonLib/Rom.h"
    #include "EncoderLib/RateCtrl.h"
    
    #include "CommonLib/dtrace_next.h"
    
    #define MACRO_TO_STRING_HELPER(val) #val
    #define MACRO_TO_STRING(val) MACRO_TO_STRING_HELPER(val)
    
    using namespace std;
    namespace po = df::program_options_lite;
    
    
    
    enum ExtendedProfileName // this is used for determining profile strings, where multiple profiles map to a single profile idc with various constraint flag combinations
    {
      NONE = 0,
      MAIN = 1,
      MAIN10 = 2,
      MAINSTILLPICTURE = 3,
      MAINREXT = 4,
      HIGHTHROUGHPUTREXT = 5, // Placeholder profile for development
      // The following are RExt profiles, which would map to the MAINREXT profile idc.
      // The enumeration indicates the bit-depth constraint in the bottom 2 digits
      //                           the chroma format in the next digit
      //                           the intra constraint in the next digit
      //                           If it is a RExt still picture, there is a '1' for the top digit.
      MONOCHROME_8      = 1008,
      MONOCHROME_12     = 1012,
      MONOCHROME_16     = 1016,
      MAIN_12           = 1112,
      MAIN_422_10       = 1210,
      MAIN_422_12       = 1212,
      MAIN_444          = 1308,
      MAIN_444_10       = 1310,
      MAIN_444_12       = 1312,
      MAIN_444_16       = 1316, // non-standard profile definition, used for development purposes
      MAIN_INTRA        = 2108,
      MAIN_10_INTRA     = 2110,
      MAIN_12_INTRA     = 2112,
      MAIN_422_10_INTRA = 2210,
      MAIN_422_12_INTRA = 2212,
      MAIN_444_INTRA    = 2308,
      MAIN_444_10_INTRA = 2310,
      MAIN_444_12_INTRA = 2312,
      MAIN_444_16_INTRA = 2316,
      MAIN_444_STILL_PICTURE = 11308,
      MAIN_444_16_STILL_PICTURE = 12316,
      NEXT          = 6
    };
    
    
    //! \ingroup EncoderApp
    //! \{
    
    // ====================================================================================================================
    // Constructor / destructor / initialization / destroy
    // ====================================================================================================================
    
    EncAppCfg::EncAppCfg()
    : m_inputColourSpaceConvert(IPCOLOURSPACE_UNCHANGED)
    , m_snrInternalColourSpace(false)
    , m_outputInternalColourSpace(false)
    
    Zhipin Deng's avatar
    Zhipin Deng committed
    , m_bIntraOnlyConstraintFlag(false)
    , m_maxBitDepthConstraintIdc(0)
    , m_maxChromaFormatConstraintIdc(CHROMA_420)
    , m_bFrameConstraintFlag(false)
    , m_bNoQtbttDualTreeIntraConstraintFlag(false)
    
    , m_noPartitionConstraintsOverrideConstraintFlag(false)
    
    Zhipin Deng's avatar
    Zhipin Deng committed
    , m_bNoSaoConstraintFlag(false)
    , m_bNoAlfConstraintFlag(false)
    , m_bNoRefWraparoundConstraintFlag(false)
    , m_bNoTemporalMvpConstraintFlag(false)
    , m_bNoSbtmvpConstraintFlag(false)
    , m_bNoAmvrConstraintFlag(false)
    , m_bNoBdofConstraintFlag(false)
    
    , m_noDmvrConstraintFlag(false)
    
    Zhipin Deng's avatar
    Zhipin Deng committed
    , m_bNoCclmConstraintFlag(false)
    , m_bNoMtsConstraintFlag(false)
    
    , m_noSbtConstraintFlag(false)
    
    Zhipin Deng's avatar
    Zhipin Deng committed
    , m_bNoAffineMotionConstraintFlag(false)
    
    , m_bNoBcwConstraintFlag(false)
    
    , m_noIbcConstraintFlag(false)
    
    , m_bNoCiipConstraintFlag(false)
    
    , m_noFPelMmvdConstraintFlag(false)
    
    Zhipin Deng's avatar
    Zhipin Deng committed
    , m_bNoTriangleConstraintFlag(false)
    , m_bNoLadfConstraintFlag(false)
    
    , m_noTransformSkipConstraintFlag(false)
    
    , m_noJointCbCrConstraintFlag(false)
    
    Zhipin Deng's avatar
    Zhipin Deng committed
    , m_bNoQpDeltaConstraintFlag(false)
    , m_bNoDepQuantConstraintFlag(false)
    , m_bNoSignDataHidingConstraintFlag(false)
    
    #if JVET_P0366_NUT_CONSTRAINT_FLAGS
    , m_noTrailConstraintFlag(false)
    , m_noStsaConstraintFlag(false)
    , m_noRaslConstraintFlag(false)
    , m_noRadlConstraintFlag(false)
    , m_noIdrConstraintFlag(false)
    , m_noCraConstraintFlag(false)
    , m_noGdrConstraintFlag(false)
    , m_noApsConstraintFlag(false)
    #endif
    
    
    #if EXTENSION_360_VIDEO
    , m_ext360(*this)
    #endif
    {
      m_aidQP = NULL;
    
      m_startOfCodedInterval = NULL;
      m_codedPivotValue = NULL;
      m_targetPivotValue = NULL;
    
      if ( m_startOfCodedInterval )
      {
        delete[] m_startOfCodedInterval;
        m_startOfCodedInterval = NULL;
      }
       if ( m_codedPivotValue )
      {
        delete[] m_codedPivotValue;
        m_codedPivotValue = NULL;
      }
      if ( m_targetPivotValue )
      {
        delete[] m_targetPivotValue;
        m_targetPivotValue = NULL;
      }
    
    #if ENABLE_TRACING
      tracing_uninit(g_trace_ctx);
    #endif
    }
    
    void EncAppCfg::create()
    {
    }
    
    void EncAppCfg::destroy()
    {
    }
    
    std::istringstream &operator>>(std::istringstream &in, GOPEntry &entry)     //input
    {
      in>>entry.m_sliceType;
      in>>entry.m_POC;
      in>>entry.m_QPOffset;
    #if X0038_LAMBDA_FROM_QP_CAPABILITY
      in>>entry.m_QPOffsetModelOffset;
      in>>entry.m_QPOffsetModelScale;
    #endif
    #if W0038_CQP_ADJ
      in>>entry.m_CbQPoffset;
      in>>entry.m_CrQPoffset;
    #endif
      in>>entry.m_QPFactor;
      in>>entry.m_tcOffsetDiv2;
      in>>entry.m_betaOffsetDiv2;
      in>>entry.m_temporalId;
    
    Hendry's avatar
    Hendry committed
      in >> entry.m_numRefPicsActive0;
      in >> entry.m_numRefPics0;
      for (int i = 0; i < entry.m_numRefPics0; i++)
      {
        in >> entry.m_deltaRefPics0[i];
      }
      in >> entry.m_numRefPicsActive1;
      in >> entry.m_numRefPics1;
      for (int i = 0; i < entry.m_numRefPics1; i++)
      {
        in >> entry.m_deltaRefPics1[i];
      }
    
    #if !JVET_P1004_REMOVE_BRICKS
    
    Karsten Suehring's avatar
    Karsten Suehring committed
    std::istringstream &operator>>(std::istringstream &in, BrickSplit &entry)     //input
    {
      in>>entry.m_tileIdx;
      in>>entry.m_uniformSplit;
      if (entry.m_uniformSplit)
      {
        in>>entry.m_uniformHeight;
      }
      else
      {
        in>>entry.m_numSplits;
        for ( int i = 0; i < entry.m_numSplits; i++ )
        {
          in>>entry.m_brickHeight[i];
        }
      }
      return in;
    }
    
    #endif
    
    bool confirmPara(bool bflag, const char* message);
    
    static inline ChromaFormat numberToChromaFormat(const int val)
    {
      switch (val)
      {
        case 400: return CHROMA_400; break;
        case 420: return CHROMA_420; break;
        case 422: return CHROMA_422; break;
        case 444: return CHROMA_444; break;
        default:  return NUM_CHROMA_FORMAT;
      }
    }
    
    static const struct MapStrToProfile
    {
      const char* str;
      Profile::Name value;
    }
    strToProfile[] =
    {
      {"none",                 Profile::NONE               },
      {"main",                 Profile::MAIN               },
      {"main10",               Profile::MAIN10             },
      {"main-still-picture",   Profile::MAINSTILLPICTURE   },
      {"main-RExt",            Profile::MAINREXT           },
      {"high-throughput-RExt", Profile::HIGHTHROUGHPUTREXT },
      {"next",                 Profile::NEXT           }
    };
    
    static const struct MapStrToExtendedProfile
    {
      const char* str;
      ExtendedProfileName value;
    }
    strToExtendedProfile[] =
    {
        {"none",                      NONE             },
        {"main",                      MAIN             },
        {"main10",                    MAIN10           },
        {"main_still_picture",        MAINSTILLPICTURE },
        {"main-still-picture",        MAINSTILLPICTURE },
        {"main_RExt",                 MAINREXT         },
        {"main-RExt",                 MAINREXT         },
        {"main_rext",                 MAINREXT         },
        {"main-rext",                 MAINREXT         },
        {"high_throughput_RExt",      HIGHTHROUGHPUTREXT },
        {"high-throughput-RExt",      HIGHTHROUGHPUTREXT },
        {"high_throughput_rext",      HIGHTHROUGHPUTREXT },
        {"high-throughput-rext",      HIGHTHROUGHPUTREXT },
        {"monochrome",                MONOCHROME_8     },
        {"monochrome12",              MONOCHROME_12    },
        {"monochrome16",              MONOCHROME_16    },
        {"main12",                    MAIN_12          },
        {"main_422_10",               MAIN_422_10      },
        {"main_422_12",               MAIN_422_12      },
        {"main_444",                  MAIN_444         },
        {"main_444_10",               MAIN_444_10      },
        {"main_444_12",               MAIN_444_12      },
        {"main_444_16",               MAIN_444_16      },
        {"main_intra",                MAIN_INTRA       },
        {"main_10_intra",             MAIN_10_INTRA    },
        {"main_12_intra",             MAIN_12_INTRA    },
        {"main_422_10_intra",         MAIN_422_10_INTRA},
        {"main_422_12_intra",         MAIN_422_12_INTRA},
        {"main_444_intra",            MAIN_444_INTRA   },
        {"main_444_still_picture",    MAIN_444_STILL_PICTURE },
        {"main_444_10_intra",         MAIN_444_10_INTRA},
        {"main_444_12_intra",         MAIN_444_12_INTRA},
        {"main_444_16_intra",         MAIN_444_16_INTRA},
        {"main_444_16_still_picture", MAIN_444_16_STILL_PICTURE },
        {"next",                      NEXT }
    };
    
    static const ExtendedProfileName validRExtProfileNames[2/* intraConstraintFlag*/][4/* bit depth constraint 8=0, 10=1, 12=2, 16=3*/][4/*chroma format*/]=
    {
        {
            { MONOCHROME_8,  NONE,          NONE,              MAIN_444          }, // 8-bit  inter for 400, 420, 422 and 444
            { NONE,          NONE,          MAIN_422_10,       MAIN_444_10       }, // 10-bit inter for 400, 420, 422 and 444
            { MONOCHROME_12, MAIN_12,       MAIN_422_12,       MAIN_444_12       }, // 12-bit inter for 400, 420, 422 and 444
            { MONOCHROME_16, NONE,          NONE,              MAIN_444_16       }  // 16-bit inter for 400, 420, 422 and 444 (the latter is non standard used for development)
        },
        {
            { NONE,          MAIN_INTRA,    NONE,              MAIN_444_INTRA    }, // 8-bit  intra for 400, 420, 422 and 444
            { NONE,          MAIN_10_INTRA, MAIN_422_10_INTRA, MAIN_444_10_INTRA }, // 10-bit intra for 400, 420, 422 and 444
            { NONE,          MAIN_12_INTRA, MAIN_422_12_INTRA, MAIN_444_12_INTRA }, // 12-bit intra for 400, 420, 422 and 444
            { NONE,          NONE,          NONE,              MAIN_444_16_INTRA }  // 16-bit intra for 400, 420, 422 and 444
        }
    };
    
    static const struct MapStrToTier
    {
      const char* str;
      Level::Tier value;
    }
    strToTier[] =
    {
      {"main", Level::MAIN},
      {"high", Level::HIGH},
    };
    
    static const struct MapStrToLevel
    {
      const char* str;
      Level::Name value;
    }
    strToLevel[] =
    {
      {"none",Level::NONE},
      {"1",   Level::LEVEL1},
      {"2",   Level::LEVEL2},
      {"2.1", Level::LEVEL2_1},
      {"3",   Level::LEVEL3},
      {"3.1", Level::LEVEL3_1},
      {"4",   Level::LEVEL4},
      {"4.1", Level::LEVEL4_1},
      {"5",   Level::LEVEL5},
      {"5.1", Level::LEVEL5_1},
      {"5.2", Level::LEVEL5_2},
      {"6",   Level::LEVEL6},
      {"6.1", Level::LEVEL6_1},
      {"6.2", Level::LEVEL6_2},
      {"8.5", Level::LEVEL8_5},
    };
    
    #if U0132_TARGET_BITS_SATURATION
    uint32_t g_uiMaxCpbSize[2][21] =
    {
      //         LEVEL1,        LEVEL2,LEVEL2_1,     LEVEL3, LEVEL3_1,      LEVEL4, LEVEL4_1,       LEVEL5,  LEVEL5_1,  LEVEL5_2,    LEVEL6,  LEVEL6_1,  LEVEL6_2
      { 0, 0, 0, 350000, 0, 0, 1500000, 3000000, 0, 6000000, 10000000, 0, 12000000, 20000000, 0,  25000000,  40000000,  60000000,  60000000, 120000000, 240000000 },
      { 0, 0, 0,      0, 0, 0,       0,       0, 0,       0,        0, 0, 30000000, 50000000, 0, 100000000, 160000000, 240000000, 240000000, 480000000, 800000000 }
    };
    #endif
    
    static const struct MapStrToCostMode
    {
      const char* str;
      CostMode    value;
    }
    strToCostMode[] =
    {
      {"lossy",                     COST_STANDARD_LOSSY},
      {"sequence_level_lossless",   COST_SEQUENCE_LEVEL_LOSSLESS},
      {"lossless",                  COST_LOSSLESS_CODING},
      {"mixed_lossless_lossy",      COST_MIXED_LOSSLESS_LOSSY_CODING}
    };
    
    static const struct MapStrToScalingListMode
    {
      const char* str;
      ScalingListMode value;
    }
    strToScalingListMode[] =
    {
      {"0",       SCALING_LIST_OFF},
      {"1",       SCALING_LIST_DEFAULT},
      {"2",       SCALING_LIST_FILE_READ},
      {"off",     SCALING_LIST_OFF},
      {"default", SCALING_LIST_DEFAULT},
      {"file",    SCALING_LIST_FILE_READ}
    };
    
    template<typename T, typename P>
    static std::string enumToString(P map[], uint32_t mapLen, const T val)
    {
      for (uint32_t i = 0; i < mapLen; i++)
      {
        if (val == map[i].value)
        {
          return map[i].str;
        }
      }
      return std::string();
    }
    
    template<typename T, typename P>
    static istream& readStrToEnum(P map[], uint32_t mapLen, istream &in, T &val)
    {
      string str;
      in >> str;
    
      for (uint32_t i = 0; i < mapLen; i++)
      {
        if (str == map[i].str)
        {
          val = map[i].value;
          goto found;
        }
      }
      /* not found */
      in.setstate(ios::failbit);
    found:
      return in;
    }
    
    //inline to prevent compiler warnings for "unused static function"
    
    static inline istream& operator >> (istream &in, ExtendedProfileName &profile)
    {
      return readStrToEnum(strToExtendedProfile, sizeof(strToExtendedProfile)/sizeof(*strToExtendedProfile), in, profile);
    }
    
    namespace Level
    {
      static inline istream& operator >> (istream &in, Tier &tier)
      {
        return readStrToEnum(strToTier, sizeof(strToTier)/sizeof(*strToTier), in, tier);
      }
    
      static inline istream& operator >> (istream &in, Name &level)
      {
        return readStrToEnum(strToLevel, sizeof(strToLevel)/sizeof(*strToLevel), in, level);
      }
    }
    
    static inline istream& operator >> (istream &in, CostMode &mode)
    {
      return readStrToEnum(strToCostMode, sizeof(strToCostMode)/sizeof(*strToCostMode), in, mode);
    }
    
    static inline istream& operator >> (istream &in, ScalingListMode &mode)
    {
      return readStrToEnum(strToScalingListMode, sizeof(strToScalingListMode)/sizeof(*strToScalingListMode), in, mode);
    }
    
    template <class T>
    struct SMultiValueInput
    {
      const T              minValIncl;
      const T              maxValIncl;
      const std::size_t    minNumValuesIncl;
      const std::size_t    maxNumValuesIncl; // Use 0 for unlimited
            std::vector<T> values;
      SMultiValueInput() : minValIncl(0), maxValIncl(0), minNumValuesIncl(0), maxNumValuesIncl(0), values() { }
      SMultiValueInput(std::vector<T> &defaults) : minValIncl(0), maxValIncl(0), minNumValuesIncl(0), maxNumValuesIncl(0), values(defaults) { }
      SMultiValueInput(const T &minValue, const T &maxValue, std::size_t minNumberValues=0, std::size_t maxNumberValues=0)
        : minValIncl(minValue), maxValIncl(maxValue), minNumValuesIncl(minNumberValues), maxNumValuesIncl(maxNumberValues), values()  { }
      SMultiValueInput(const T &minValue, const T &maxValue, std::size_t minNumberValues, std::size_t maxNumberValues, const T* defValues, const uint32_t numDefValues)
        : minValIncl(minValue), maxValIncl(maxValue), minNumValuesIncl(minNumberValues), maxNumValuesIncl(maxNumberValues), values(defValues, defValues+numDefValues)  { }
      SMultiValueInput<T> &operator=(const std::vector<T> &userValues) { values=userValues; return *this; }
      SMultiValueInput<T> &operator=(const SMultiValueInput<T> &userValues) { values=userValues.values; return *this; }
    
      T readValue(const char *&pStr, bool &bSuccess);
    
      istream& readValues(std::istream &in);
    };
    
    template <class T>
    static inline istream& operator >> (std::istream &in, SMultiValueInput<T> &values)
    {
      return values.readValues(in);
    }
    
    template<>
    uint32_t SMultiValueInput<uint32_t>::readValue(const char *&pStr, bool &bSuccess)
    {
      char *eptr;
      uint32_t val=strtoul(pStr, &eptr, 0);
      pStr=eptr;
      bSuccess=!(*eptr!=0 && !isspace(*eptr) && *eptr!=',') && !(val<minValIncl || val>maxValIncl);
      return val;
    }
    
    
    template<>
    uint8_t SMultiValueInput<uint8_t>::readValue(const char *&pStr, bool &bSuccess)
    {
      char *eptr;
      uint32_t val = strtoul(pStr, &eptr, 0);
      pStr = eptr;
      bSuccess = !(*eptr != 0 && !isspace(*eptr) && *eptr != ',') && !(val<minValIncl || val>maxValIncl);
      return val;
    }
    
    
    template<>
    int SMultiValueInput<int>::readValue(const char *&pStr, bool &bSuccess)
    {
      char *eptr;
      int val=strtol(pStr, &eptr, 0);
      pStr=eptr;
      bSuccess=!(*eptr!=0 && !isspace(*eptr) && *eptr!=',') && !(val<minValIncl || val>maxValIncl);
      return val;
    }
    
    template<>
    double SMultiValueInput<double>::readValue(const char *&pStr, bool &bSuccess)
    {
      char *eptr;
      double val=strtod(pStr, &eptr);
      pStr=eptr;
      bSuccess=!(*eptr!=0 && !isspace(*eptr) && *eptr!=',') && !(val<minValIncl || val>maxValIncl);
      return val;
    }
    
    template<>
    bool SMultiValueInput<bool>::readValue(const char *&pStr, bool &bSuccess)
    {
      char *eptr;
      int val=strtol(pStr, &eptr, 0);
      pStr=eptr;
      bSuccess=!(*eptr!=0 && !isspace(*eptr) && *eptr!=',') && !(val<int(minValIncl) || val>int(maxValIncl));
      return val!=0;
    }
    
    template <class T>
    istream& SMultiValueInput<T>::readValues(std::istream &in)
    {
      values.clear();
      string str;
      while (!in.eof())
      {
        string tmp; in >> tmp; str+=" " + tmp;
      }
      if (!str.empty())
      {
        const char *pStr=str.c_str();
        // soak up any whitespace
        for(;isspace(*pStr);pStr++);
    
        while (*pStr != 0)
        {
          bool bSuccess=true;
          T val=readValue(pStr, bSuccess);
          if (!bSuccess)
          {
            in.setstate(ios::failbit);
            break;
          }
    
          if (maxNumValuesIncl != 0 && values.size() >= maxNumValuesIncl)
          {
            in.setstate(ios::failbit);
            break;
          }
          values.push_back(val);
          // soak up any whitespace and up to 1 comma.
          for(;isspace(*pStr);pStr++);
          if (*pStr == ',')
          {
            pStr++;
          }
          for(;isspace(*pStr);pStr++);
        }
      }
      if (values.size() < minNumValuesIncl)
      {
        in.setstate(ios::failbit);
      }
      return in;
    }
    
    #if QP_SWITCHING_FOR_PARALLEL
    template <class T>
    static inline istream& operator >> (std::istream &in, EncAppCfg::OptionalValue<T> &value)
    {
      in >> std::ws;
      if (in.eof())
      {
        value.bPresent = false;
      }
      else
      {
        in >> value.value;
        value.bPresent = true;
      }
      return in;
    }
    #endif
    
    
    #if JVET_O0549_ENCODER_ONLY_FILTER
    template <class T1, class T2>
    static inline istream& operator >> (std::istream& in, std::map<T1, T2>& map)
    {
      T1 key;
      T2 value;
      try
      {
        in >> key;
        in >> value;
      }
      catch (...)
      {
        in.setstate(ios::failbit);
      }
    
      map[key] = value;
      return in;
    }
    #endif
    
    
    static void
    automaticallySelectRExtProfile(const bool bUsingGeneralRExtTools,
                                   const bool bUsingChromaQPAdjustment,
                                   const bool bUsingExtendedPrecision,
                                   const bool bIntraConstraintFlag,
                                   uint32_t &bitDepthConstraint,
                                   ChromaFormat &chromaFormatConstraint,
                                   const int  maxBitDepth,
                                   const ChromaFormat chromaFormat)
    {
      // Try to choose profile, according to table in Q1013.
      uint32_t trialBitDepthConstraint=maxBitDepth;
      if (trialBitDepthConstraint<8)
      {
        trialBitDepthConstraint=8;
      }
      else if (trialBitDepthConstraint==9 || trialBitDepthConstraint==11)
      {
        trialBitDepthConstraint++;
      }
      else if (trialBitDepthConstraint>12)
      {
        trialBitDepthConstraint=16;
      }
    
      // both format and bit depth constraints are unspecified
      if (bUsingExtendedPrecision || trialBitDepthConstraint==16)
      {
        bitDepthConstraint = 16;
        chromaFormatConstraint = (!bIntraConstraintFlag && chromaFormat==CHROMA_400) ? CHROMA_400 : CHROMA_444;
      }
      else if (bUsingGeneralRExtTools)
      {
        if (chromaFormat == CHROMA_400 && !bIntraConstraintFlag)
        {
          bitDepthConstraint = 16;
          chromaFormatConstraint = CHROMA_400;
        }
        else
        {
          bitDepthConstraint = trialBitDepthConstraint;
          chromaFormatConstraint = CHROMA_444;
        }
      }
      else if (chromaFormat == CHROMA_400)
      {
        if (bIntraConstraintFlag)
        {
          chromaFormatConstraint = CHROMA_420; // there is no intra 4:0:0 profile.
          bitDepthConstraint     = trialBitDepthConstraint;
        }
        else
        {
          chromaFormatConstraint = CHROMA_400;
          bitDepthConstraint     = trialBitDepthConstraint == 8 ? 8 : 12;
        }
      }
      else
      {
        bitDepthConstraint = trialBitDepthConstraint;
        chromaFormatConstraint = chromaFormat;
        if (bUsingChromaQPAdjustment && chromaFormat == CHROMA_420)
        {
          chromaFormatConstraint = CHROMA_422; // 4:2:0 cannot use the chroma qp tool.
        }
        if (chromaFormatConstraint == CHROMA_422 && bitDepthConstraint == 8)
        {
          bitDepthConstraint = 10; // there is no 8-bit 4:2:2 profile.
        }
        if (chromaFormatConstraint == CHROMA_420 && !bIntraConstraintFlag)
        {
          bitDepthConstraint = 12; // there is no 8 or 10-bit 4:2:0 inter RExt profile.
        }
      }
    }
    
    #if JVET_P1004_REMOVE_BRICKS
    
    static uint32_t getMaxTileColsByLevel( Level::Name level )
    {
      switch( level ) 
      {
        case Level::LEVEL1:
        case Level::LEVEL2:
        case Level::LEVEL2_1:
          return 1;
        case Level::LEVEL3:
          return 2;
        case Level::LEVEL3_1:
          return 3;
        case Level::LEVEL4:
        case Level::LEVEL4_1:
          return 5;
        case Level::LEVEL5:
        case Level::LEVEL5_1:
        case Level::LEVEL5_2:
          return 10;
        case Level::LEVEL6:
        case Level::LEVEL6_1:
        case Level::LEVEL6_2:
        default:
          return 20;
      }
    }
    
    static uint32_t getMaxTileRowsByLevel( Level::Name level )
    {
      switch( level ) 
      {
        case Level::LEVEL1:
        case Level::LEVEL2:
        case Level::LEVEL2_1:
          return 1;
        case Level::LEVEL3:
          return 2;
        case Level::LEVEL3_1:
          return 3;
        case Level::LEVEL4:
        case Level::LEVEL4_1:
          return 5;
        case Level::LEVEL5:
        case Level::LEVEL5_1:
        case Level::LEVEL5_2:
          return 11;
        case Level::LEVEL6:
        case Level::LEVEL6_1:
        case Level::LEVEL6_2:
        default:
          return 21;
      }
    }
    
    static uint32_t getMaxSlicesByLevel( Level::Name level )
    {
      switch( level ) 
      {
        case Level::LEVEL1:
        case Level::LEVEL2:
          return 16;
        case Level::LEVEL2_1:
          return 20;
        case Level::LEVEL3:
          return 30;
        case Level::LEVEL3_1:
          return 40;
        case Level::LEVEL4:
        case Level::LEVEL4_1:
          return 75;
        case Level::LEVEL5:
        case Level::LEVEL5_1:
        case Level::LEVEL5_2:
          return 200;
        case Level::LEVEL6:
        case Level::LEVEL6_1:
        case Level::LEVEL6_2:
        default:
          return 600;
      }
    }
    
    #endif
    
    // ====================================================================================================================
    // Public member functions
    // ====================================================================================================================
    
    /** \param  argc        number of arguments
        \param  argv        array of arguments
        \retval             true when success
     */
    bool EncAppCfg::parseCfg( int argc, char* argv[] )
    {
      bool do_help = false;
    
      int tmpChromaFormat;
      int tmpInputChromaFormat;
      int tmpConstraintChromaFormat;
      int tmpWeightedPredictionMethod;
      int tmpFastInterSearchMode;
      int tmpMotionEstimationSearchMethod;
    
    #if !JVET_P1004_REMOVE_BRICKS 
    
    #endif
    
      int tmpDecodedPictureHashSEIMappedType;
      string inputColourSpaceConvert;
      string inputPathPrefix;
      ExtendedProfileName extendedProfile;
      int saoOffsetBitShift[MAX_NUM_CHANNEL_TYPE];
    
      // Multi-value input fields:                                // minval, maxval (incl), min_entries, max_entries (incl) [, default values, number of default values]
    
    #if JVET_P1004_REMOVE_BRICKS  
      SMultiValueInput<uint32_t>  cfgTileColumnWidth              (0, std::numeric_limits<uint32_t>::max(), 0, std::numeric_limits<uint32_t>::max());
      SMultiValueInput<uint32_t>  cfgTileRowHeight                (0, std::numeric_limits<uint32_t>::max(), 0, std::numeric_limits<uint32_t>::max());
      SMultiValueInput<uint32_t>  cfgRectSlicePos                 (0, std::numeric_limits<uint32_t>::max(), 0, std::numeric_limits<uint32_t>::max());
      SMultiValueInput<uint32_t>  cfgRasterSliceSize              (0, std::numeric_limits<uint32_t>::max(), 0, std::numeric_limits<uint32_t>::max());
    #else  
    
      SMultiValueInput<uint32_t> cfg_ColumnWidth                     (0, std::numeric_limits<uint32_t>::max(), 0, std::numeric_limits<uint32_t>::max());
      SMultiValueInput<uint32_t> cfg_RowHeight                       (0, std::numeric_limits<uint32_t>::max(), 0, std::numeric_limits<uint32_t>::max());
    
    #endif
    
      SMultiValueInput<int>  cfg_startOfCodedInterval            (std::numeric_limits<int>::min(), std::numeric_limits<int>::max(), 0, 1<<16);
      SMultiValueInput<int>  cfg_codedPivotValue                 (std::numeric_limits<int>::min(), std::numeric_limits<int>::max(), 0, 1<<16);
      SMultiValueInput<int>  cfg_targetPivotValue                (std::numeric_limits<int>::min(), std::numeric_limits<int>::max(), 0, 1<<16);
    
    
    #if !JVET_P1004_REMOVE_BRICKS 
    
      SMultiValueInput<uint32_t> cfg_SliceIdx                    (0, std::numeric_limits<uint32_t>::max(), 0, std::numeric_limits<uint32_t>::max());
      SMultiValueInput<uint32_t> cfg_SignalledSliceId            (0, std::numeric_limits<uint32_t>::max(), 0, std::numeric_limits<uint32_t>::max());
    
    #endif
    
      SMultiValueInput<double> cfg_adIntraLambdaModifier         (0, std::numeric_limits<double>::max(), 0, MAX_TLAYER); ///< Lambda modifier for Intra pictures, one for each temporal layer. If size>temporalLayer, then use [temporalLayer], else if size>0, use [size()-1], else use m_adLambdaModifier.
    
    #if SHARP_LUMA_DELTA_QP
      const int defaultLumaLevelTodQp_QpChangePoints[]   =  {-3,  -2,  -1,   0,   1,   2,   3,   4,   5,   6};
      const int defaultLumaLevelTodQp_LumaChangePoints[] =  { 0, 301, 367, 434, 501, 567, 634, 701, 767, 834};
      SMultiValueInput<int>  cfg_lumaLeveltoDQPMappingQP         (-MAX_QP, MAX_QP,                    0, LUMA_LEVEL_TO_DQP_LUT_MAXSIZE, defaultLumaLevelTodQp_QpChangePoints,   sizeof(defaultLumaLevelTodQp_QpChangePoints  )/sizeof(int));
      SMultiValueInput<int>  cfg_lumaLeveltoDQPMappingLuma       (0, std::numeric_limits<int>::max(), 0, LUMA_LEVEL_TO_DQP_LUT_MAXSIZE, defaultLumaLevelTodQp_LumaChangePoints, sizeof(defaultLumaLevelTodQp_LumaChangePoints)/sizeof(int));
      uint32_t lumaLevelToDeltaQPMode;
    #endif
    
      const int qpInVals[] = { 25, 33, 43 };                // qpInVal values used to derive the chroma QP mapping table used in VTM-5.0
      const int qpOutVals[] = { 25, 32, 37 };               // qpOutVal values used to derive the chroma QP mapping table used in VTM-5.0
      SMultiValueInput<int> cfg_qpInValCb                   (MIN_QP_VALUE_FOR_16_BIT, MAX_QP, 0, MAX_NUM_QP_VALUES, qpInVals, sizeof(qpInVals)/sizeof(int));
      SMultiValueInput<int> cfg_qpOutValCb                  (MIN_QP_VALUE_FOR_16_BIT, MAX_QP, 0, MAX_NUM_QP_VALUES, qpOutVals, sizeof(qpOutVals) / sizeof(int));
    
      SMultiValueInput<int> cfg_qpInValCr                   (MIN_QP_VALUE_FOR_16_BIT, MAX_QP, 0, MAX_NUM_QP_VALUES, zeroVector, 1);
      SMultiValueInput<int> cfg_qpOutValCr                  (MIN_QP_VALUE_FOR_16_BIT, MAX_QP, 0, MAX_NUM_QP_VALUES, zeroVector, 1);
      SMultiValueInput<int> cfg_qpInValCbCr                 (MIN_QP_VALUE_FOR_16_BIT, MAX_QP, 0, MAX_NUM_QP_VALUES, zeroVector, 1);
      SMultiValueInput<int> cfg_qpOutValCbCr                (MIN_QP_VALUE_FOR_16_BIT, MAX_QP, 0, MAX_NUM_QP_VALUES, zeroVector, 1);
    
      const uint32_t defaultInputKneeCodes[3]  = { 600, 800, 900 };
      const uint32_t defaultOutputKneeCodes[3] = { 100, 250, 450 };
      SMultiValueInput<uint32_t> cfg_kneeSEIInputKneePointValue      (1,  999, 0, 999, defaultInputKneeCodes,  sizeof(defaultInputKneeCodes )/sizeof(uint32_t));
      SMultiValueInput<uint32_t> cfg_kneeSEIOutputKneePointValue     (0, 1000, 0, 999, defaultOutputKneeCodes, sizeof(defaultOutputKneeCodes)/sizeof(uint32_t));
      const int defaultPrimaryCodes[6]     = { 0,50000, 0,0, 50000,0 };
      const int defaultWhitePointCode[2]   = { 16667, 16667 };
      SMultiValueInput<int>  cfg_DisplayPrimariesCode            (0, 50000, 6, 6, defaultPrimaryCodes,   sizeof(defaultPrimaryCodes  )/sizeof(int));
      SMultiValueInput<int>  cfg_DisplayWhitePointCode           (0, 50000, 2, 2, defaultWhitePointCode, sizeof(defaultWhitePointCode)/sizeof(int));
    
      SMultiValueInput<bool> cfg_timeCodeSeiTimeStampFlag        (0,  1, 0, MAX_TIMECODE_SEI_SETS);
      SMultiValueInput<bool> cfg_timeCodeSeiNumUnitFieldBasedFlag(0,  1, 0, MAX_TIMECODE_SEI_SETS);
      SMultiValueInput<int>  cfg_timeCodeSeiCountingType         (0,  6, 0, MAX_TIMECODE_SEI_SETS);
      SMultiValueInput<bool> cfg_timeCodeSeiFullTimeStampFlag    (0,  1, 0, MAX_TIMECODE_SEI_SETS);
      SMultiValueInput<bool> cfg_timeCodeSeiDiscontinuityFlag    (0,  1, 0, MAX_TIMECODE_SEI_SETS);
      SMultiValueInput<bool> cfg_timeCodeSeiCntDroppedFlag       (0,  1, 0, MAX_TIMECODE_SEI_SETS);
      SMultiValueInput<int>  cfg_timeCodeSeiNumberOfFrames       (0,511, 0, MAX_TIMECODE_SEI_SETS);
      SMultiValueInput<int>  cfg_timeCodeSeiSecondsValue         (0, 59, 0, MAX_TIMECODE_SEI_SETS);
      SMultiValueInput<int>  cfg_timeCodeSeiMinutesValue         (0, 59, 0, MAX_TIMECODE_SEI_SETS);
      SMultiValueInput<int>  cfg_timeCodeSeiHoursValue           (0, 23, 0, MAX_TIMECODE_SEI_SETS);
      SMultiValueInput<bool> cfg_timeCodeSeiSecondsFlag          (0,  1, 0, MAX_TIMECODE_SEI_SETS);
      SMultiValueInput<bool> cfg_timeCodeSeiMinutesFlag          (0,  1, 0, MAX_TIMECODE_SEI_SETS);
      SMultiValueInput<bool> cfg_timeCodeSeiHoursFlag            (0,  1, 0, MAX_TIMECODE_SEI_SETS);
      SMultiValueInput<int>  cfg_timeCodeSeiTimeOffsetLength     (0, 31, 0, MAX_TIMECODE_SEI_SETS);
      SMultiValueInput<int>  cfg_timeCodeSeiTimeOffsetValue      (std::numeric_limits<int>::min(), std::numeric_limits<int>::max(), 0, MAX_TIMECODE_SEI_SETS);
    
    #if JVET_P0462_SEI360
      SMultiValueInput<int>      cfg_omniViewportSEIAzimuthCentre    (-11796480, 11796479, 0, 15);
      SMultiValueInput<int>      cfg_omniViewportSEIElevationCentre  ( -5898240,  5898240, 0, 15);
      SMultiValueInput<int>      cfg_omniViewportSEITiltCentre       (-11796480, 11796479, 0, 15);
      SMultiValueInput<uint32_t> cfg_omniViewportSEIHorRange         (        1, 23592960, 0, 15);
      SMultiValueInput<uint32_t> cfg_omniViewportSEIVerRange         (        1, 11796480, 0, 15);
      SMultiValueInput<uint32_t>   cfg_rwpSEIRwpTransformType                 (0, 7, 0, std::numeric_limits<uint8_t>::max());
      SMultiValueInput<bool>       cfg_rwpSEIRwpGuardBandFlag                 (0, 1, 0, std::numeric_limits<uint8_t>::max()); 
      SMultiValueInput<uint32_t>   cfg_rwpSEIProjRegionWidth                  (0, std::numeric_limits<uint32_t>::max(), 0, std::numeric_limits<uint8_t>::max());
      SMultiValueInput<uint32_t>   cfg_rwpSEIProjRegionHeight                 (0, std::numeric_limits<uint32_t>::max(), 0, std::numeric_limits<uint8_t>::max());
      SMultiValueInput<uint32_t>   cfg_rwpSEIRwpSEIProjRegionTop              (0, std::numeric_limits<uint32_t>::max(), 0, std::numeric_limits<uint8_t>::max());
      SMultiValueInput<uint32_t>   cfg_rwpSEIProjRegionLeft                   (0, std::numeric_limits<uint32_t>::max(), 0, std::numeric_limits<uint8_t>::max());
      SMultiValueInput<uint32_t>   cfg_rwpSEIPackedRegionWidth                (0, std::numeric_limits<uint16_t>::max(), 0, std::numeric_limits<uint8_t>::max());
      SMultiValueInput<uint32_t>   cfg_rwpSEIPackedRegionHeight               (0, std::numeric_limits<uint16_t>::max(), 0, std::numeric_limits<uint8_t>::max());
      SMultiValueInput<uint32_t>   cfg_rwpSEIPackedRegionTop                  (0, std::numeric_limits<uint16_t>::max(), 0, std::numeric_limits<uint8_t>::max());
      SMultiValueInput<uint32_t>   cfg_rwpSEIPackedRegionLeft                 (0, std::numeric_limits<uint16_t>::max(), 0, std::numeric_limits<uint8_t>::max());
      SMultiValueInput<uint32_t>   cfg_rwpSEIRwpLeftGuardBandWidth            (0, std::numeric_limits<uint8_t>::max(), 0, std::numeric_limits<uint8_t>::max());
      SMultiValueInput<uint32_t>   cfg_rwpSEIRwpRightGuardBandWidth           (0, std::numeric_limits<uint8_t>::max(), 0, std::numeric_limits<uint8_t>::max());
      SMultiValueInput<uint32_t>   cfg_rwpSEIRwpTopGuardBandHeight            (0, std::numeric_limits<uint8_t>::max(), 0, std::numeric_limits<uint8_t>::max());
      SMultiValueInput<uint32_t>   cfg_rwpSEIRwpBottomGuardBandHeight         (0, std::numeric_limits<uint8_t>::max(), 0, std::numeric_limits<uint8_t>::max());
      SMultiValueInput<bool>       cfg_rwpSEIRwpGuardBandNotUsedForPredFlag   (0, 1,   0, std::numeric_limits<uint8_t>::max());
      SMultiValueInput<uint32_t>   cfg_rwpSEIRwpGuardBandType                 (0, 7,   0, 4*std::numeric_limits<uint8_t>::max());
    #endif
    
    #if LUMA_ADAPTIVE_DEBLOCKING_FILTER_QP_OFFSET
      const int defaultLadfQpOffset[3] = { 1, 0, 1 };
      const int defaultLadfIntervalLowerBound[2] = { 350, 833 };
      SMultiValueInput<int>  cfg_LadfQpOffset                    ( -MAX_QP, MAX_QP, 2, MAX_LADF_INTERVALS, defaultLadfQpOffset, 3 );
      SMultiValueInput<int>  cfg_LadfIntervalLowerBound          ( 0, std::numeric_limits<int>::max(), 1, MAX_LADF_INTERVALS - 1, defaultLadfIntervalLowerBound, 2 );
    
    #endif
      SMultiValueInput<unsigned> cfg_virtualBoundariesPosX       (0, std::numeric_limits<uint32_t>::max(), 0, 3);
      SMultiValueInput<unsigned> cfg_virtualBoundariesPosY       (0, std::numeric_limits<uint32_t>::max(), 0, 3);
    
    
      SMultiValueInput<uint8_t> cfg_SubProfile(0, std::numeric_limits<uint8_t>::max(), 0, std::numeric_limits<uint8_t>::max());
    
    
      int warnUnknowParameter = 0;
    
    #if ENABLE_TRACING
      string sTracingRule;
      string sTracingFile;
      bool   bTracingChannelsList = false;
    #endif
    #if ENABLE_SIMD_OPT
      std::string ignore;
    #endif
    
      bool sdr = false;
    
      po::Options opts;
      opts.addOptions()
      ("help",                                            do_help,                                          false, "this help text")
      ("c",    po::parseConfigFile, "configuration file name")
      ("WarnUnknowParameter,w",                           warnUnknowParameter,                                  0, "warn for unknown configuration parameters instead of failing")
      ("isSDR",                                           sdr,                                              false, "compatibility")
    #if ENABLE_SIMD_OPT
      ("SIMD",                                            ignore,                                      string(""), "SIMD extension to use (SCALAR, SSE41, SSE42, AVX, AVX2, AVX512), default: the highest supported extension\n")
    #endif
      // File, I/O and source parameters
      ("InputFile,i",                                     m_inputFileName,                             string(""), "Original YUV input file name")
      ("InputPathPrefix,-ipp",                            inputPathPrefix,                             string(""), "pathname to prepend to input filename")
      ("BitstreamFile,b",                                 m_bitstreamFileName,                         string(""), "Bitstream output file name")
      ("ReconFile,o",                                     m_reconFileName,                             string(""), "Reconstructed YUV output file name")
      ("SourceWidth,-wdt",                                m_iSourceWidth,                                       0, "Source picture width")
      ("SourceHeight,-hgt",                               m_iSourceHeight,                                      0, "Source picture height")
      ("InputBitDepth",                                   m_inputBitDepth[CHANNEL_TYPE_LUMA],                   8, "Bit-depth of input file")
      ("OutputBitDepth",                                  m_outputBitDepth[CHANNEL_TYPE_LUMA],                  0, "Bit-depth of output file (default:InternalBitDepth)")
      ("MSBExtendedBitDepth",                             m_MSBExtendedBitDepth[CHANNEL_TYPE_LUMA],             0, "bit depth of luma component after addition of MSBs of value 0 (used for synthesising High Dynamic Range source material). (default:InputBitDepth)")
      ("InternalBitDepth",                                m_internalBitDepth[CHANNEL_TYPE_LUMA],                0, "Bit-depth the codec operates at. (default: MSBExtendedBitDepth). If different to MSBExtendedBitDepth, source data will be converted")
      ("InputBitDepthC",                                  m_inputBitDepth[CHANNEL_TYPE_CHROMA],                 0, "As per InputBitDepth but for chroma component. (default:InputBitDepth)")
      ("OutputBitDepthC",                                 m_outputBitDepth[CHANNEL_TYPE_CHROMA],                0, "As per OutputBitDepth but for chroma component. (default: use luma output bit-depth)")
      ("MSBExtendedBitDepthC",                            m_MSBExtendedBitDepth[CHANNEL_TYPE_CHROMA],           0, "As per MSBExtendedBitDepth but for chroma component. (default:MSBExtendedBitDepth)")
    
    #if !JVET_P0243_SINGLE_BIT_DEPTH
    
      ("InternalBitDepthC",                               m_internalBitDepth[CHANNEL_TYPE_CHROMA],              0, "As per InternalBitDepth but for chroma component. (default:InternalBitDepth)")
    
    #endif
    
      ("ExtendedPrecision",                               m_extendedPrecisionProcessingFlag,                false, "Increased internal accuracies to support high bit depths (not valid in V1 profiles)")
      ("HighPrecisionPredictionWeighting",                m_highPrecisionOffsetsEnabledFlag,                false, "Use high precision option for weighted prediction (not valid in V1 profiles)")
      ("InputColourSpaceConvert",                         inputColourSpaceConvert,                     string(""), "Colour space conversion to apply to input video. Permitted values are (empty string=UNCHANGED) " + getListOfColourSpaceConverts(true))
      ("SNRInternalColourSpace",                          m_snrInternalColourSpace,                         false, "If true, then no colour space conversion is applied prior to SNR, otherwise inverse of input is applied.")
      ("OutputInternalColourSpace",                       m_outputInternalColourSpace,                      false, "If true, then no colour space conversion is applied for reconstructed video, otherwise inverse of input is applied.")
      ("InputChromaFormat",                               tmpInputChromaFormat,                               420, "InputChromaFormatIDC")
      ("MSEBasedSequencePSNR",                            m_printMSEBasedSequencePSNR,                      false, "0 (default) emit sequence PSNR only as a linear average of the frame PSNRs, 1 = also emit a sequence PSNR based on an average of the frame MSEs")
      ("PrintHexPSNR",                                    m_printHexPsnr,                                   false, "0 (default) don't emit hexadecimal PSNR for each frame, 1 = also emit hexadecimal PSNR values")
      ("PrintFrameMSE",                                   m_printFrameMSE,                                  false, "0 (default) emit only bit count and PSNRs for each frame, 1 = also emit MSE values")
      ("PrintSequenceMSE",                                m_printSequenceMSE,                               false, "0 (default) emit only bit rate and PSNRs for the whole sequence, 1 = also emit MSE values")
      ("CabacZeroWordPaddingEnabled",                     m_cabacZeroWordPaddingEnabled,                     true, "0 do not add conforming cabac-zero-words to bit streams, 1 (default) = add cabac-zero-words as required")
      ("ChromaFormatIDC,-cf",                             tmpChromaFormat,                                      0, "ChromaFormatIDC (400|420|422|444 or set 0 (default) for same as InputChromaFormat)")
      ("ConformanceMode",                                 m_conformanceWindowMode,                              0, "Deprecated alias of ConformanceWindowMode")
      ("ConformanceWindowMode",                           m_conformanceWindowMode,                              0, "Window conformance mode (0: no window, 1:automatic padding, 2:padding, 3:conformance")
      ("HorizontalPadding,-pdx",                          m_aiPad[0],                                           0, "Horizontal source padding for conformance window mode 2")
      ("VerticalPadding,-pdy",                            m_aiPad[1],                                           0, "Vertical source padding for conformance window mode 2")
      ("ConfLeft",                                        m_confWinLeft,                                        0, "Deprecated alias of ConfWinLeft")
      ("ConfRight",                                       m_confWinRight,                                       0, "Deprecated alias of ConfWinRight")
      ("ConfTop",                                         m_confWinTop,                                         0, "Deprecated alias of ConfWinTop")
      ("ConfBottom",                                      m_confWinBottom,                                      0, "Deprecated alias of ConfWinBottom")
      ("ConfWinLeft",                                     m_confWinLeft,                                        0, "Left offset for window conformance mode 3")
      ("ConfWinRight",                                    m_confWinRight,                                       0, "Right offset for window conformance mode 3")
      ("ConfWinTop",                                      m_confWinTop,                                         0, "Top offset for window conformance mode 3")
      ("ConfWinBottom",                                   m_confWinBottom,                                      0, "Bottom offset for window conformance mode 3")
    
    Brian Heng's avatar
    Brian Heng committed
    #if JVET_P1006_PICTURE_HEADER
      ("AccessUnitDelimiter",                             m_AccessUnitDelimiter,                            false, "Enable Access Unit Delimiter NALUs")
    #else
    
      ("AccessUnitDelimiter",                             m_AccessUnitDelimiter,                             true, "Enable Access Unit Delimiter NALUs")
    
    Brian Heng's avatar
    Brian Heng committed
    #endif
    
      ("FrameRate,-fr",                                   m_iFrameRate,                                         0, "Frame rate")
      ("FrameSkip,-fs",                                   m_FrameSkip,                                         0u, "Number of frames to skip at start of input YUV")
      ("TemporalSubsampleRatio,-ts",                      m_temporalSubsampleRatio,                            1u, "Temporal sub-sample ratio when reading input YUV")
      ("FramesToBeEncoded,f",                             m_framesToBeEncoded,                                  0, "Number of frames to be encoded (default=all)")
      ("ClipInputVideoToRec709Range",                     m_bClipInputVideoToRec709Range,                   false, "If true then clip input video to the Rec. 709 Range on loading when InternalBitDepth is less than MSBExtendedBitDepth")
      ("ClipOutputVideoToRec709Range",                    m_bClipOutputVideoToRec709Range,                  false, "If true then clip output video to the Rec. 709 Range on saving when OutputBitDepth is less than InternalBitDepth")