Skip to content
Snippets Groups Projects
EncAppCfg.cpp 371 KiB
Newer Older
  • Learn to ignore specific revisions
  •   xConfirmPara( m_sourcePadding[1] % SPS::getWinUnitY(m_chromaFormatIDC) != 0, "Vertical padding must be an integer multiple of the specified chroma subsampling");
    
    
      xConfirmPara( m_confWinLeft   % SPS::getWinUnitX(m_chromaFormatIDC) != 0, "Left conformance window offset must be an integer multiple of the specified chroma subsampling");
      xConfirmPara( m_confWinRight  % SPS::getWinUnitX(m_chromaFormatIDC) != 0, "Right conformance window offset must be an integer multiple of the specified chroma subsampling");
      xConfirmPara( m_confWinTop    % SPS::getWinUnitY(m_chromaFormatIDC) != 0, "Top conformance window offset must be an integer multiple of the specified chroma subsampling");
      xConfirmPara( m_confWinBottom % SPS::getWinUnitY(m_chromaFormatIDC) != 0, "Bottom conformance window offset must be an integer multiple of the specified chroma subsampling");
    
    
      // max CU width and height should be power of 2
    
    Frank Bossen's avatar
    Frank Bossen committed
      uint32_t ui = m_maxCuWidth;
    
      while(ui)
      {
        ui >>= 1;
        if( (ui & 1) == 1)
        {
          xConfirmPara( ui != 1 , "Width should be 2^n");
        }
      }
    
    Frank Bossen's avatar
    Frank Bossen committed
      ui = m_maxCuHeight;
    
      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 */
    
    Frank Bossen's avatar
    Frank Bossen committed
      if (m_intraPeriod == 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_CbBetaOffsetDiv2 = 0;
        m_GOPList[0].m_CbTcOffsetDiv2 = 0;
        m_GOPList[0].m_CrBetaOffsetDiv2 = 0;
        m_GOPList[0].m_CrTcOffsetDiv2 = 0;
    
    Hendry's avatar
    Hendry committed
        m_RPLList0[0] = RPLEntry();
        m_RPLList1[0] = RPLEntry();
        m_RPLList0[0].m_POC = m_RPLList1[0].m_POC = 1;
        m_RPLList0[0].m_numRefPicsActive = 4;
        m_GOPList[0].m_numRefPicsActive0 = 4;
    
        xConfirmPara( m_intraOnlyConstraintFlag, "IntraOnlyConstraintFlag cannot be 1 for inter sequences");
    
      int multipleFactor = m_compositeRefEnabled ? 2 : 1;
    
      bool verifiedGOP=false;
      bool errorGOP=false;
      int checkGOP=1;
      int numRefs = m_isField ? 2 : 1;
    
      int refList[MAX_NUM_REF_PICS+1] = {0};
    
      if(m_isField)
      {
        refList[1] = 1;
      }
      bool isOK[MAX_GOP];
      for(int i=0; i<MAX_GOP; i++)
      {
        isOK[i]=false;
      }
      int numOK=0;
    
    Frank Bossen's avatar
    Frank Bossen committed
      xConfirmPara(m_intraPeriod >= 0 && (m_intraPeriod % m_gopSize != 0),
                   "Intra period must be a multiple of GOPSize, or -1");
    
    Frank Bossen's avatar
    Frank Bossen committed
      for (int i = 0; i < m_gopSize; i++)
    
    Frank Bossen's avatar
    Frank Bossen committed
        if (m_GOPList[i].m_POC == m_gopSize * multipleFactor)
    
        {
          xConfirmPara( m_GOPList[i].m_temporalId!=0 , "The last frame in each GOP must have temporal ID = 0 " );
        }
      }
    
    
    Frank Bossen's avatar
    Frank Bossen committed
      if ((m_intraPeriod != 1) && !m_deblockingFilterOffsetInPPS && (!m_deblockingFilterDisable))
    
    Frank Bossen's avatar
    Frank Bossen committed
        for (int i = 0; i < m_gopSize; i++)
    
          xConfirmPara( (m_GOPList[i].m_betaOffsetDiv2 + m_deblockingFilterBetaOffsetDiv2) < -12 || (m_GOPList[i].m_betaOffsetDiv2 + m_deblockingFilterBetaOffsetDiv2) > 12, "Loop Filter Beta Offset div. 2 for one of the GOP entries exceeds supported range (-12 to 12)" );
          xConfirmPara( (m_GOPList[i].m_tcOffsetDiv2 + m_deblockingFilterTcOffsetDiv2) < -12 || (m_GOPList[i].m_tcOffsetDiv2 + m_deblockingFilterTcOffsetDiv2) > 12, "Loop Filter Tc Offset div. 2 for one of the GOP entries exceeds supported range (-12 to 12)" );
          xConfirmPara( (m_GOPList[i].m_CbBetaOffsetDiv2 + m_deblockingFilterCbBetaOffsetDiv2) < -12 || (m_GOPList[i].m_CbBetaOffsetDiv2 + m_deblockingFilterCbBetaOffsetDiv2) > 12, "Loop Filter Beta Offset div. 2 for one of the GOP entries exceeds supported range (-12 to 12)" );
          xConfirmPara( (m_GOPList[i].m_CbTcOffsetDiv2 + m_deblockingFilterCbTcOffsetDiv2) < -12 || (m_GOPList[i].m_CbTcOffsetDiv2 + m_deblockingFilterCbTcOffsetDiv2) > 12, "Loop Filter Tc Offset div. 2 for one of the GOP entries exceeds supported range (-12 to 12)" );
          xConfirmPara( (m_GOPList[i].m_CrBetaOffsetDiv2 + m_deblockingFilterCrBetaOffsetDiv2) < -12 || (m_GOPList[i].m_CrBetaOffsetDiv2 + m_deblockingFilterCrBetaOffsetDiv2) > 12, "Loop Filter Beta Offset div. 2 for one of the GOP entries exceeds supported range (-12 to 12)" );
          xConfirmPara( (m_GOPList[i].m_CrTcOffsetDiv2 + m_deblockingFilterCrTcOffsetDiv2) < -12 || (m_GOPList[i].m_CrTcOffsetDiv2 + m_deblockingFilterCrTcOffsetDiv2) > 12, "Loop Filter Tc Offset div. 2 for one of the GOP entries exceeds supported range (-12 to 12)" );
    
    Frank Bossen's avatar
    Frank Bossen committed
      for (int i = 0; i < m_gopSize; 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
    
    
      xConfirmPara( m_maxSublayers < 1 || m_maxSublayers > 7, "MaxSublayers must be in range [1..7]" );
    
    
    
      xConfirmPara( m_fastLocalDualTreeMode < 0 || m_fastLocalDualTreeMode > 2, "FastLocalDualTreeMode must be in range [0..2]" );
    
    
      xConfirmPara( m_fastAdaptCostPredMode < 0 || m_fastAdaptCostPredMode > 2, "FastAdaptCostPredMode must be in range [0..2]" );
    
    
    Hendry's avatar
    Hendry committed
      int extraRPLs = 0;
    
    Hendry's avatar
    Hendry committed
      //start looping through frames in coding order until we can verify that the GOP structure is correct.
      while (!verifiedGOP && !errorGOP)
      {
    
    Frank Bossen's avatar
    Frank Bossen committed
        int curGOP = (checkGOP - 1) % m_gopSize;
        int curPOC = ((checkGOP - 1) / m_gopSize) * m_gopSize * multipleFactor + m_RPLList0[curGOP].m_POC;
    
    Hendry's avatar
    Hendry committed
        if (m_RPLList0[curGOP].m_POC < 0 || m_RPLList1[curGOP].m_POC < 0)
        {
          msg(WARNING, "\nError: found fewer Reference Picture Sets than GOPSize\n");
          errorGOP = true;
        }
        else
        {
          //check that all reference pictures are available, or have a POC < 0 meaning they might be available in the next GOP.
          bool beforeI = false;
          for (int i = 0; i< m_RPLList0[curGOP].m_numRefPics; i++)
          {
            int absPOC = curPOC - m_RPLList0[curGOP].m_deltaRefPics[i];
            if (absPOC < 0)
            {
              beforeI = true;
            }
            else
            {
              bool found = false;
              for (int j = 0; j<numRefs; j++)
              {
                if (refList[j] == absPOC)
                {
                  found = true;
    
    Frank Bossen's avatar
    Frank Bossen committed
                  for (int k = 0; k < m_gopSize; k++)
    
    Frank Bossen's avatar
    Frank Bossen committed
                    if (absPOC % (m_gopSize * multipleFactor) == m_RPLList0[k].m_POC % (m_gopSize * multipleFactor))
    
    Hendry's avatar
    Hendry committed
                    {
                      if (m_RPLList0[k].m_temporalId == m_RPLList0[curGOP].m_temporalId)
                      {
                        m_RPLList0[k].m_refPic = true;
                      }
                    }
                  }
                }
              }
              if (!found)
              {
                msg(WARNING, "\nError: ref pic %d is not available for GOP frame %d\n", m_RPLList0[curGOP].m_deltaRefPics[i], curGOP + 1);
                errorGOP = true;
              }
            }
          }
          if (!beforeI && !errorGOP)
          {
            //all ref frames were present
            if (!isOK[curGOP])
            {
              numOK++;
              isOK[curGOP] = true;
    
    Frank Bossen's avatar
    Frank Bossen committed
              if (numOK == m_gopSize)
    
    Hendry's avatar
    Hendry committed
              {
                verifiedGOP = true;
              }
            }
          }
          else
          {
            //create a new RPLEntry for this frame containing all the reference pictures that were available (POC > 0)
    
    Frank Bossen's avatar
    Frank Bossen committed
            m_RPLList0[m_gopSize + extraRPLs] = m_RPLList0[curGOP];
            m_RPLList1[m_gopSize + extraRPLs] = m_RPLList1[curGOP];
    
    Hendry's avatar
    Hendry committed
            int newRefs0 = 0;
            for (int i = 0; i< m_RPLList0[curGOP].m_numRefPics; i++)
            {
              int absPOC = curPOC - m_RPLList0[curGOP].m_deltaRefPics[i];
              if (absPOC >= 0)
              {
    
    Frank Bossen's avatar
    Frank Bossen committed
                m_RPLList0[m_gopSize + extraRPLs].m_deltaRefPics[newRefs0] = m_RPLList0[curGOP].m_deltaRefPics[i];
    
    Hendry's avatar
    Hendry committed
                newRefs0++;
              }
            }
            int numPrefRefs0 = m_RPLList0[curGOP].m_numRefPicsActive;
    
            int newRefs1 = 0;
            for (int i = 0; i< m_RPLList1[curGOP].m_numRefPics; i++)
            {
              int absPOC = curPOC - m_RPLList1[curGOP].m_deltaRefPics[i];
              if (absPOC >= 0)
              {
    
    Frank Bossen's avatar
    Frank Bossen committed
                m_RPLList1[m_gopSize + extraRPLs].m_deltaRefPics[newRefs1] = m_RPLList1[curGOP].m_deltaRefPics[i];
    
    Hendry's avatar
    Hendry committed
                newRefs1++;
              }
            }
            int numPrefRefs1 = m_RPLList1[curGOP].m_numRefPicsActive;
    
            for (int offset = -1; offset>-checkGOP; offset--)
            {
              //step backwards in coding order and include any extra available pictures we might find useful to replace the ones with POC < 0.
    
    Frank Bossen's avatar
    Frank Bossen committed
              int offGOP = (checkGOP - 1 + offset) % m_gopSize;
              int offPOC = ((checkGOP - 1 + offset) / m_gopSize) * (m_gopSize * multipleFactor) + m_RPLList0[offGOP].m_POC;
    
    Hendry's avatar
    Hendry committed
              if (offPOC >= 0 && m_RPLList0[offGOP].m_temporalId <= m_RPLList0[curGOP].m_temporalId)
              {
                bool newRef = false;
                for (int i = 0; i<(newRefs0 + newRefs1); i++)
                {
                  if (refList[i] == offPOC)
                  {
                    newRef = true;
                  }
                }
                for (int i = 0; i<newRefs0; i++)
                {
    
    Frank Bossen's avatar
    Frank Bossen committed
                  if (m_RPLList0[m_gopSize + extraRPLs].m_deltaRefPics[i] == curPOC - offPOC)
    
    Hendry's avatar
    Hendry committed
                  {
                    newRef = false;
                  }
                }
                if (newRef)
                {
                  int insertPoint = newRefs0;
                  //this picture can be added, find appropriate place in list and insert it.
                  if (m_RPLList0[offGOP].m_temporalId == m_RPLList0[curGOP].m_temporalId)
                  {
                    m_RPLList0[offGOP].m_refPic = true;
                  }
                  for (int j = 0; j<newRefs0; j++)
                  {
    
    Frank Bossen's avatar
    Frank Bossen committed
                    if (m_RPLList0[m_gopSize + extraRPLs].m_deltaRefPics[j] > curPOC - offPOC && curPOC - offPOC > 0)
    
    Hendry's avatar
    Hendry committed
                    {
                      insertPoint = j;
                      break;
                    }
                  }
                  int prev = curPOC - offPOC;
                  for (int j = insertPoint; j<newRefs0 + 1; j++)
                  {
    
    Frank Bossen's avatar
    Frank Bossen committed
                    int newPrev = m_RPLList0[m_gopSize + extraRPLs].m_deltaRefPics[j];
                    m_RPLList0[m_gopSize + extraRPLs].m_deltaRefPics[j] = prev;
    
    Hendry's avatar
    Hendry committed
                    prev = newPrev;
                  }
                  newRefs0++;
                }
              }
              if (newRefs0 >= numPrefRefs0)
              {
                break;
              }
            }
    
            for (int offset = -1; offset>-checkGOP; offset--)
            {
              //step backwards in coding order and include any extra available pictures we might find useful to replace the ones with POC < 0.
    
    Frank Bossen's avatar
    Frank Bossen committed
              int offGOP = (checkGOP - 1 + offset) % m_gopSize;
              int offPOC = ((checkGOP - 1 + offset) / m_gopSize) * (m_gopSize * multipleFactor) + m_RPLList1[offGOP].m_POC;
    
    Hendry's avatar
    Hendry committed
              if (offPOC >= 0 && m_RPLList1[offGOP].m_temporalId <= m_RPLList1[curGOP].m_temporalId)
              {
                bool newRef = false;
                for (int i = 0; i<(newRefs0 + newRefs1); i++)
                {
                  if (refList[i] == offPOC)
                  {
                    newRef = true;
                  }
                }
                for (int i = 0; i<newRefs1; i++)
                {
    
    Frank Bossen's avatar
    Frank Bossen committed
                  if (m_RPLList1[m_gopSize + extraRPLs].m_deltaRefPics[i] == curPOC - offPOC)
    
    Hendry's avatar
    Hendry committed
                  {
                    newRef = false;
                  }
                }
                if (newRef)
                {
                  int insertPoint = newRefs1;
                  //this picture can be added, find appropriate place in list and insert it.
                  if (m_RPLList1[offGOP].m_temporalId == m_RPLList1[curGOP].m_temporalId)
                  {
                    m_RPLList1[offGOP].m_refPic = true;
                  }
                  for (int j = 0; j<newRefs1; j++)
                  {
    
    Frank Bossen's avatar
    Frank Bossen committed
                    if (m_RPLList1[m_gopSize + extraRPLs].m_deltaRefPics[j] > curPOC - offPOC && curPOC - offPOC > 0)
    
    Hendry's avatar
    Hendry committed
                    {
                      insertPoint = j;
                      break;
                    }
                  }
                  int prev = curPOC - offPOC;
                  for (int j = insertPoint; j<newRefs1 + 1; j++)
                  {
    
    Frank Bossen's avatar
    Frank Bossen committed
                    int newPrev = m_RPLList1[m_gopSize + extraRPLs].m_deltaRefPics[j];
                    m_RPLList1[m_gopSize + extraRPLs].m_deltaRefPics[j] = prev;
    
    Hendry's avatar
    Hendry committed
                    prev = newPrev;
                  }
                  newRefs1++;
                }
              }
              if (newRefs1 >= numPrefRefs1)
              {
                break;
              }
            }
    
    
    Frank Bossen's avatar
    Frank Bossen committed
            m_RPLList0[m_gopSize + extraRPLs].m_numRefPics = newRefs0;
    
            m_RPLList0[m_gopSize + extraRPLs].m_numRefPicsActive = std::min(
              m_RPLList0[m_gopSize + extraRPLs].m_numRefPics, m_RPLList0[m_gopSize + extraRPLs].m_numRefPicsActive);
    
    Frank Bossen's avatar
    Frank Bossen committed
            m_RPLList1[m_gopSize + extraRPLs].m_numRefPics = newRefs1;
    
            m_RPLList1[m_gopSize + extraRPLs].m_numRefPicsActive = std::min(
              m_RPLList1[m_gopSize + extraRPLs].m_numRefPics, m_RPLList1[m_gopSize + extraRPLs].m_numRefPicsActive);
    
    Frank Bossen's avatar
    Frank Bossen committed
            curGOP = m_gopSize + extraRPLs;
    
    Hendry's avatar
    Hendry committed
            extraRPLs++;
          }
          numRefs = 0;
          for (int i = 0; i< m_RPLList0[curGOP].m_numRefPics; i++)
          {
            int absPOC = curPOC - m_RPLList0[curGOP].m_deltaRefPics[i];
    
            hasFutureRef |= (m_RPLList0[curGOP].m_deltaRefPics[i] < 0);
    
    Hendry's avatar
    Hendry committed
            if (absPOC >= 0)
            {
              refList[numRefs] = absPOC;
              numRefs++;
            }
          }
          for (int i = 0; i< m_RPLList1[curGOP].m_numRefPics; i++)
          {
            int absPOC = curPOC - m_RPLList1[curGOP].m_deltaRefPics[i];
    
            hasFutureRef |= (m_RPLList1[curGOP].m_deltaRefPics[i] < 0);
    
    Hendry's avatar
    Hendry committed
            if (absPOC >= 0)
            {
              bool alreadyExist = false;
              for (int j = 0; !alreadyExist && j < numRefs; j++)
              {
                if (refList[j] == absPOC)
                {
                  alreadyExist = true;
                }
              }
              if (!alreadyExist)
              {
                refList[numRefs] = absPOC;
                numRefs++;
              }
            }
          }
          refList[numRefs] = curPOC;
          numRefs++;
        }
        checkGOP++;
      }
    
    Frank Bossen's avatar
    Frank Bossen committed
      m_isLowDelay = !hasFutureRef && m_intraPeriod != 1;
    
    Hendry's avatar
    Hendry committed
      xConfirmPara(errorGOP, "Invalid GOP structure given");
    
    
    Frank Bossen's avatar
    Frank Bossen committed
      for (int i = 0; i < m_gopSize; 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++)
      {
    
    Frank Bossen's avatar
    Frank Bossen committed
      for (int i = 0; i < m_gopSize; i++)
    
    Hendry's avatar
    Hendry committed
        int numRefPic = m_RPLList0[i].m_numRefPics;
        for (int tmp = 0; tmp < m_RPLList1[i].m_numRefPics; tmp++)
        {
          bool notSame = true;
          for (int jj = 0; notSame && jj < m_RPLList0[i].m_numRefPics; jj++)
          {
            if (m_RPLList1[i].m_deltaRefPics[tmp] == m_RPLList0[i].m_deltaRefPics[jj]) notSame = false;
          }
          if (notSame) numRefPic++;
        }
        if (numRefPic + 1 > m_maxDecPicBuffering[m_GOPList[i].m_temporalId])
        {
          m_maxDecPicBuffering[m_GOPList[i].m_temporalId] = numRefPic + 1;
        }
    
    Frank Bossen's avatar
    Frank Bossen committed
        for (int j = 0; j < m_gopSize; 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_maxNumReorderPics[m_GOPList[i].m_temporalId])
    
          m_maxNumReorderPics[m_GOPList[i].m_temporalId] = numReorder;
    
        // a lower layer can not have higher value of m_maxNumReorderPics than a higher layer
        if(m_maxNumReorderPics[i+1] < m_maxNumReorderPics[i])
    
          m_maxNumReorderPics[i+1] = m_maxNumReorderPics[i];
    
        // the value of dpb_max_num_reorder_pics[ i ] shall be in the range of 0 to max_dec_pic_buffering[ i ] - 1, inclusive
        if(m_maxNumReorderPics[i] > m_maxDecPicBuffering[i] - 1)
    
          m_maxDecPicBuffering[i] = m_maxNumReorderPics[i] + 1;
    
    Frank Bossen's avatar
    Frank Bossen committed
        // a lower layer can not have higher value of m_maxDecPicBuffering than a higher layer
    
        if(m_maxDecPicBuffering[i+1] < m_maxDecPicBuffering[i])
        {
          m_maxDecPicBuffering[i+1] = m_maxDecPicBuffering[i];
        }
      }
    
    
      // the value of dpb_max_num_reorder_pics[ i ] shall be in the range of 0 to max_dec_pic_buffering[ i ] -  1, inclusive
      if(m_maxNumReorderPics[MAX_TLAYER-1] > m_maxDecPicBuffering[MAX_TLAYER-1] - 1)
    
        m_maxDecPicBuffering[MAX_TLAYER-1] = m_maxNumReorderPics[MAX_TLAYER-1] + 1;
    
      if( m_picPartitionFlag )
    
      {
        PPS pps;
        uint32_t colIdx, rowIdx;
        uint32_t remSize;
    
        pps.setPicWidthInLumaSamples( m_sourceWidth );
        pps.setPicHeightInLumaSamples( m_sourceHeight );
    
    Frank Bossen's avatar
    Frank Bossen committed
        pps.setLog2CtuSize(floorLog2(m_ctuSize));
    
    
        // set default tile column if not provided
    
        if( m_tileColumnWidth.size() == 0 )
    
        {
          m_tileColumnWidth.push_back( pps.getPicWidthInCtu() );
        }
        // set default tile row if not provided
    
        if( m_tileRowHeight.size() == 0 )
    
        {
          m_tileRowHeight.push_back( pps.getPicHeightInCtu() );
        }
    
        // remove any tile columns that can be specified implicitly
        while( m_tileColumnWidth.size() > 1 && m_tileColumnWidth.end()[-1] == m_tileColumnWidth.end()[-2] )
        {
          m_tileColumnWidth.pop_back();
        }
    
        // remove any tile rows that can be specified implicitly
        while( m_tileRowHeight.size() > 1 && m_tileRowHeight.end()[-1] == m_tileRowHeight.end()[-2] )
        {
          m_tileRowHeight.pop_back();
        }
    
        // setup tiles in temporary PPS structure
        remSize = pps.getPicWidthInCtu();
        for( colIdx=0; remSize > 0 && colIdx<m_tileColumnWidth.size(); colIdx++ )
        {
          xConfirmPara(m_tileColumnWidth[ colIdx ] == 0, "Tile column widths cannot be equal to 0");
          m_tileColumnWidth[ colIdx ] = std::min( remSize, m_tileColumnWidth[ colIdx ]);
          pps.addTileColumnWidth( m_tileColumnWidth[ colIdx ] );
          remSize -= m_tileColumnWidth[ colIdx ];
        }
        m_tileColumnWidth.resize( colIdx );
    
        pps.setNumExpTileColumns( (uint32_t)m_tileColumnWidth.size() );
    
        remSize = pps.getPicHeightInCtu();
        for( rowIdx=0; remSize > 0 && rowIdx<m_tileRowHeight.size(); rowIdx++ )
        {
          xConfirmPara(m_tileRowHeight[ rowIdx ] == 0, "Tile row heights cannot be equal to 0");
          m_tileRowHeight[ rowIdx ] = std::min( remSize, m_tileRowHeight[ rowIdx ]);
          pps.addTileRowHeight( m_tileRowHeight[ rowIdx ] );
          remSize -= m_tileRowHeight[ rowIdx ];
        }
        m_tileRowHeight.resize( rowIdx );
        pps.setNumExpTileRows( (uint32_t)m_tileRowHeight.size() );
        pps.initTiles();
        xConfirmPara(pps.getNumTileColumns() > getMaxTileColsByLevel( m_level ), "Number of tile columns exceeds maximum number allowed according to specified level");
        xConfirmPara(pps.getNumTileRows()    > getMaxTileRowsByLevel( m_level ), "Number of tile rows exceeds maximum number allowed according to specified level");
        m_numTileCols = pps.getNumTileColumns();
        m_numTileRows = pps.getNumTileRows();
    
        // rectangular slices
        if( !m_rasterSliceFlag )
        {
    
            // generate slice list for the simplified fixed-rectangular-slice-size config option
            if( m_rectSliceFixedWidth > 0 && m_rectSliceFixedHeight > 0 )
            {
              int tileIdx = 0;
              m_rectSlicePos.clear();
              while( tileIdx < pps.getNumTiles() )
    
                uint32_t startTileX = tileIdx % pps.getNumTileColumns();
                uint32_t startTileY = tileIdx / pps.getNumTileColumns();
                uint32_t startCtuX  = pps.getTileColumnBd( startTileX );
                uint32_t startCtuY  = pps.getTileRowBd( startTileY );
                uint32_t stopCtuX   = (startTileX + m_rectSliceFixedWidth)  >= pps.getNumTileColumns() ? pps.getPicWidthInCtu() - 1  : pps.getTileColumnBd( startTileX + m_rectSliceFixedWidth ) - 1;
                uint32_t stopCtuY   = (startTileY + m_rectSliceFixedHeight) >= pps.getNumTileRows()    ? pps.getPicHeightInCtu() - 1 : pps.getTileRowBd( startTileY + m_rectSliceFixedHeight ) - 1;
                uint32_t stopTileX  = pps.ctuToTileCol( stopCtuX );
                uint32_t stopTileY  = pps.ctuToTileRow( stopCtuY );
    
                // add rectangular slice to list
                m_rectSlicePos.push_back( startCtuY * pps.getPicWidthInCtu() + startCtuX );
                m_rectSlicePos.push_back( stopCtuY  * pps.getPicWidthInCtu() + stopCtuX  );
    
                // get slice size in tiles
                uint32_t sliceWidth  = stopTileX - startTileX + 1;
                uint32_t sliceHeight = stopTileY - startTileY + 1;
    
                // move to next tile in raster scan order
                tileIdx += sliceWidth;
                if( tileIdx % pps.getNumTileColumns() == 0 )
                {
                  tileIdx += (sliceHeight - 1) * pps.getNumTileColumns();
                }
    
            xConfirmPara( m_rectSlicePos.size() & 1, "Odd number of rectangular slice positions provided. Rectangular slice positions must be specified in pairs of (top-left / bottom-right) raster-scan CTU addresses.");
    
            // set default slice size if not provided
            if( m_rectSlicePos.size() == 0 )
    
              m_rectSlicePos.push_back( 0 );
              m_rectSlicePos.push_back( pps.getPicWidthInCtu() * pps.getPicHeightInCtu() - 1 );
    
            pps.setNumSlicesInPic( (uint32_t)(m_rectSlicePos.size() >> 1) );
            xConfirmPara(pps.getNumSlicesInPic() > getMaxSlicesByLevel( m_level ), "Number of rectangular slices exceeds maximum number allowed according to specified level");
            pps.initRectSlices();
    
            // set slice parameters from CTU addresses
            for( sliceIdx = 0; sliceIdx < pps.getNumSlicesInPic(); sliceIdx++ )
    
              xConfirmPara( m_rectSlicePos[2*sliceIdx]     >= pps.getPicWidthInCtu() * pps.getPicHeightInCtu(), "Rectangular slice position exceeds total number of CTU in picture.");
              xConfirmPara( m_rectSlicePos[2*sliceIdx + 1] >= pps.getPicWidthInCtu() * pps.getPicHeightInCtu(), "Rectangular slice position exceeds total number of CTU in picture.");
    
              // map raster scan CTU address to X/Y position
              uint32_t startCtuX = m_rectSlicePos[2*sliceIdx]     % pps.getPicWidthInCtu();
              uint32_t startCtuY = m_rectSlicePos[2*sliceIdx]     / pps.getPicWidthInCtu();
              uint32_t stopCtuX  = m_rectSlicePos[2*sliceIdx + 1] % pps.getPicWidthInCtu();
              uint32_t stopCtuY  = m_rectSlicePos[2*sliceIdx + 1] / pps.getPicWidthInCtu();
    
              // get corresponding tile index
              uint32_t startTileX = pps.ctuToTileCol( startCtuX );
              uint32_t startTileY = pps.ctuToTileRow( startCtuY );
              uint32_t stopTileX  = pps.ctuToTileCol( stopCtuX );
              uint32_t stopTileY  = pps.ctuToTileRow( stopCtuY );
              uint32_t tileIdx    = startTileY * pps.getNumTileColumns() + startTileX;
    
              // get slice size in tiles
              uint32_t sliceWidth  = stopTileX - startTileX + 1;
              uint32_t sliceHeight = stopTileY - startTileY + 1;
    
              // check for slice / tile alignment
              xConfirmPara( startCtuX != pps.getTileColumnBd( startTileX ), "Rectangular slice position does not align with a left tile edge.");
              xConfirmPara( stopCtuX  != (pps.getTileColumnBd( stopTileX + 1 ) - 1), "Rectangular slice position does not align with a right tile edge.");
              if( sliceWidth > 1 || sliceHeight > 1 )
    
                xConfirmPara( startCtuY != pps.getTileRowBd( startTileY ), "Rectangular slice position does not align with a top tile edge.");
                xConfirmPara( stopCtuY  != (pps.getTileRowBd( stopTileY + 1 ) - 1), "Rectangular slice position does not align with a bottom tile edge.");
    
    
              // set slice size and tile index
              pps.setSliceWidthInTiles( sliceIdx, sliceWidth );
              pps.setSliceHeightInTiles( sliceIdx, sliceHeight );
              pps.setSliceTileIdx( sliceIdx, tileIdx );
              if( sliceIdx > 0 && !needTileIdxDelta )
    
                uint32_t lastTileIdx = pps.getSliceTileIdx( sliceIdx-1 );
                lastTileIdx += pps.getSliceWidthInTiles( sliceIdx-1 );
                if( lastTileIdx % pps.getNumTileColumns() == 0)
                {
                  lastTileIdx += (pps.getSliceHeightInTiles( sliceIdx-1 ) - 1) * pps.getNumTileColumns();
                }
                if( lastTileIdx != tileIdx )
                {
                  needTileIdxDelta = true;
                }
    
              // special case for multiple slices within a single tile
              if( sliceWidth == 1 && sliceHeight == 1 )
    
                uint32_t firstSliceIdx = sliceIdx;
                uint32_t numSlicesInTile = 1;
                pps.setSliceHeightInCtu( sliceIdx, stopCtuY - startCtuY + 1 );
    
                while( sliceIdx < pps.getNumSlicesInPic()-1 )
    
                  uint32_t nextTileIdx;
                  startCtuX   = m_rectSlicePos[2*(sliceIdx+1)]     % pps.getPicWidthInCtu();
                  startCtuY   = m_rectSlicePos[2*(sliceIdx+1)]     / pps.getPicWidthInCtu();
                  stopCtuX    = m_rectSlicePos[2*(sliceIdx+1) + 1] % pps.getPicWidthInCtu();
                  stopCtuY    = m_rectSlicePos[2*(sliceIdx+1) + 1] / pps.getPicWidthInCtu();
                  startTileX  = pps.ctuToTileCol( startCtuX );
                  startTileY  = pps.ctuToTileRow( startCtuY );
                  stopTileX   = pps.ctuToTileCol( stopCtuX );
                  stopTileY   = pps.ctuToTileRow( stopCtuY );
                  nextTileIdx = startTileY * pps.getNumTileColumns() + startTileX;
                  sliceWidth  = stopTileX - startTileX + 1;
                  sliceHeight = stopTileY - startTileY + 1;
                  if(nextTileIdx != tileIdx || sliceWidth != 1 || sliceHeight != 1)
                  {
                    break;
                  }
                  numSlicesInTile++;
                  sliceIdx++;
                  pps.setSliceWidthInTiles( sliceIdx, 1 );
                  pps.setSliceHeightInTiles( sliceIdx, 1 );
                  pps.setSliceTileIdx( sliceIdx, tileIdx );
                  pps.setSliceHeightInCtu( sliceIdx, stopCtuY - startCtuY + 1 );
    
                pps.setNumSlicesInTile( firstSliceIdx, numSlicesInTile );
    
            pps.setTileIdxDeltaPresentFlag( needTileIdxDelta );
            m_tileIdxDeltaPresentFlag = needTileIdxDelta;
    
            // check rectangular slice mapping and full picture CTU coverage
            pps.initRectSliceMap(nullptr);
    
            // store rectangular slice parameters from temporary PPS structure
            m_numSlicesInPic = pps.getNumSlicesInPic();
            m_rectSlices.resize( pps.getNumSlicesInPic() );
            for( sliceIdx = 0; sliceIdx < pps.getNumSlicesInPic(); sliceIdx++ )
            {
              m_rectSlices[sliceIdx].setSliceWidthInTiles( pps.getSliceWidthInTiles(sliceIdx) );
              m_rectSlices[sliceIdx].setSliceHeightInTiles( pps.getSliceHeightInTiles(sliceIdx) );
              m_rectSlices[sliceIdx].setNumSlicesInTile( pps.getNumSlicesInTile(sliceIdx) );
              m_rectSlices[sliceIdx].setSliceHeightInCtu( pps.getSliceHeightInCtu(sliceIdx) );
              m_rectSlices[sliceIdx].setTileIdx( pps.getSliceTileIdx(sliceIdx) );
            }
    
          }
        }
        // raster-scan slices
        else
        {
          uint32_t listIdx = 0;
          uint32_t remTiles = pps.getNumTiles();
    
          // set default slice size if not provided
    
          if( m_rasterSliceSize.size() == 0 )
    
          {
            m_rasterSliceSize.push_back( remTiles );
          }
    
          // set raster slice sizes
          while( remTiles > 0 )
          {
            // truncate if size exceeds number of remaining tiles
            if( listIdx < m_rasterSliceSize.size() )
            {
              m_rasterSliceSize[listIdx] = std::min( remTiles, m_rasterSliceSize[listIdx] );
              remTiles -= m_rasterSliceSize[listIdx];
            }
            // replicate last size uniformly as needed to cover the remainder of the picture
            else
            {
              m_rasterSliceSize.push_back( std::min( remTiles, m_rasterSliceSize.back() ) );
              remTiles -= m_rasterSliceSize.back();
            }
            listIdx++;
          }
          // shrink list if too many sizes were provided
          m_rasterSliceSize.resize( listIdx );
    
          m_numSlicesInPic = (uint32_t)m_rasterSliceSize.size();
          xConfirmPara(m_rasterSliceSize.size() > getMaxSlicesByLevel( m_level ), "Number of raster-scan slices exceeds maximum number allowed according to specified level");
        }
      }
    
      {
        m_numTileCols = 1;
        m_numTileRows = 1;
        m_numSlicesInPic = 1;
      }
    
      if ((m_MCTSEncConstraint) && (!m_disableLFCrossTileBoundaryFlag))
    
    Valeri George's avatar
    Valeri George committed
      {
        printf("Warning: Constrained Encoding for Motion Constrained Tile Sets (MCTS) is enabled. Disabling filtering across tile boundaries!\n");
    
        m_disableLFCrossTileBoundaryFlag = true;
    
    Valeri George's avatar
    Valeri George committed
      }
      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;
      }
    
      xConfirmPara( m_sariAspectRatioIdc < 0 || m_sariAspectRatioIdc > 255, "SEISARISampleAspectRatioIdc must be in the range of 0 to 255");
    
      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 ((m_RCCpbSaturationEnabled) && (m_level!=Level::NONE) && (m_profile!=Profile::NONE))
        {
    
          uint32_t uiLevelIdx = (m_level / 16) * 4 + (uint32_t)((m_level % 16) / 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");
        }
      }
      else
      {
        xConfirmPara( m_RCCpbSaturationEnabled != 0, "Target bits saturation cannot be processed without Rate control" );
      }
    
      if (m_framePackingSEIEnabled)
      {
        xConfirmPara(m_framePackingSEIType < 3 || m_framePackingSEIType > 5 , "SEIFramePackingType must be in rage 3 to 5");
      }
    
    yonghe's avatar
    yonghe committed
      if (m_doSEIEnabled)
      {
        xConfirmPara(m_doSEITransformType < 0 || m_doSEITransformType > 7, "SEIDisplayOrientationTransformType must be in rage 0 to 7");
      }
    
    
      if( m_erpSEIEnabled && !m_erpSEICancelFlag )
      {
        xConfirmPara( m_erpSEIGuardBandType < 0 || m_erpSEIGuardBandType > 8, "SEIEquirectangularprojectionGuardBandType must be in the range of 0 to 7");
        xConfirmPara( (m_chromaFormatIDC == CHROMA_420 || m_chromaFormatIDC == CHROMA_422) && (m_erpSEILeftGuardBandWidth%2 == 1), "SEIEquirectangularprojectionLeftGuardBandWidth must be an even number for 4:2:0 or 4:2:2 chroma format");
        xConfirmPara( (m_chromaFormatIDC == CHROMA_420 || m_chromaFormatIDC == CHROMA_422) && (m_erpSEIRightGuardBandWidth%2 == 1), "SEIEquirectangularprojectionRightGuardBandWidth must be an even number for 4:2:0 or 4:2:2 chroma format");
      }
    
      if( m_sphereRotationSEIEnabled && !m_sphereRotationSEICancelFlag )
      {
        xConfirmPara( m_sphereRotationSEIYaw  < -(180<<16) || m_sphereRotationSEIYaw > (180<<16)-1, "SEISphereRotationYaw must be in the range of -11 796 480 to 11 796 479");
        xConfirmPara( m_sphereRotationSEIPitch < -(90<<16) || m_sphereRotationSEIYaw > (90<<16),    "SEISphereRotationPitch must be in the range of -5 898 240 to 5 898 240");
        xConfirmPara( m_sphereRotationSEIRoll < -(180<<16) || m_sphereRotationSEIYaw > (180<<16)-1, "SEISphereRotationRoll must be in the range of -11 796 480 to 11 796 479");
      }
    
      if ( m_omniViewportSEIEnabled && !m_omniViewportSEICancelFlag )
      {
        xConfirmPara( m_omniViewportSEIId < 0 || m_omniViewportSEIId > 1023, "SEIomniViewportId must be in the range of 0 to 1023");
        xConfirmPara( m_omniViewportSEICntMinus1 < 0 || m_omniViewportSEICntMinus1 > 15, "SEIomniViewportCntMinus1 must be in the range of 0 to 15");
        for ( uint32_t i=0; i<=m_omniViewportSEICntMinus1; i++ )
        {
          xConfirmPara( m_omniViewportSEIAzimuthCentre[i] < -(180<<16)  || m_omniViewportSEIAzimuthCentre[i] > (180<<16)-1, "SEIOmniViewportAzimuthCentre must be in the range of -11 796 480 to 11 796 479");
          xConfirmPara( m_omniViewportSEIElevationCentre[i] < -(90<<16) || m_omniViewportSEIElevationCentre[i] > (90<<16),  "SEIOmniViewportSEIElevationCentre must be in the range of -5 898 240 to 5 898 240");
          xConfirmPara( m_omniViewportSEITiltCentre[i] < -(180<<16)     || m_omniViewportSEITiltCentre[i] > (180<<16)-1,    "SEIOmniViewportTiltCentre must be in the range of -11 796 480 to 11 796 479");
          xConfirmPara( m_omniViewportSEIHorRange[i] < 1 || m_omniViewportSEIHorRange[i] > (360<<16), "SEIOmniViewportHorRange must be in the range of 1 to 360*2^16");
          xConfirmPara( m_omniViewportSEIVerRange[i] < 1 || m_omniViewportSEIVerRange[i] > (180<<16), "SEIOmniViewportVerRange must be in the range of 1 to 180*2^16");
        }
      }
    
    
      if (m_gcmpSEIEnabled && !m_gcmpSEICancelFlag)
      {
        xConfirmPara( m_gcmpSEIMappingFunctionType < 0 || m_gcmpSEIMappingFunctionType > 2, "SEIGcmpMappingFunctionType must be in the range of 0 to 2");
        int numFace = m_gcmpSEIPackingType == 4 || m_gcmpSEIPackingType == 5 ? 5 : 6;
        for ( int i = 0; i < numFace; i++ )
        {
          xConfirmPara( m_gcmpSEIFaceIndex[i] < 0 || m_gcmpSEIFaceIndex[i] > 5,       "SEIGcmpFaceIndex must be in the range of 0 to 5");
          xConfirmPara( m_gcmpSEIFaceRotation[i] < 0 || m_gcmpSEIFaceRotation[i] > 3, "SEIGcmpFaceRotation must be in the range of 0 to 3");
          if (m_gcmpSEIMappingFunctionType == 2)
          {
            xConfirmPara( m_gcmpSEIFunctionCoeffU[i] <= 0.0 || m_gcmpSEIFunctionCoeffU[i] > 1.0, "SEIGcmpFunctionCoeffU must be in the range (0, 1]");
            xConfirmPara( m_gcmpSEIFunctionCoeffV[i] <= 0.0 || m_gcmpSEIFunctionCoeffV[i] > 1.0, "SEIGcmpFunctionCoeffV must be in the range (0, 1]");
          }
    
          if (i != 2 && (m_gcmpSEIPackingType == 4 || m_gcmpSEIPackingType == 5))
          {
            if (m_gcmpSEIFaceIndex[2] == 0 || m_gcmpSEIFaceIndex[2] == 1)
            {
              xConfirmPara( m_gcmpSEIFaceIndex[i] == 0 || m_gcmpSEIFaceIndex[i] == 1, "SEIGcmpFaceIndex[i] must be in the range of 2 to 5 for i equal to 0, 1, 3, or 4 when SEIGcmpFaceIndex[2] is equal to 0 or 1");
              if (m_gcmpSEIPackingType == 4)
              {
                xConfirmPara( m_gcmpSEIFaceRotation[i] != 0 && m_gcmpSEIFaceRotation[i] != 2, "SEIGcmpFaceRotation[i] must be 0 or 2 for i equal to 0, 1, 3, or 4 when SEIGcmpFaceIndex[2] is equal to 0 or 1");
              }
              else
              {
                xConfirmPara( m_gcmpSEIFaceRotation[i] != 1 && m_gcmpSEIFaceRotation[i] != 3, "SEIGcmpFaceRotation[i] must be 1 or 3 for i equal to 0, 1, 3, or 4 when SEIGcmpFaceIndex[2] is equal to 0 or 1");
              }
            }
            else if (m_gcmpSEIFaceIndex[2] == 2 || m_gcmpSEIFaceIndex[2] == 3)
            {
              xConfirmPara( m_gcmpSEIFaceIndex[i] == 2 || m_gcmpSEIFaceIndex[i] == 3, "SEIGcmpFaceIndex[i] must be 0, 1, 4 or 5 for i equal to 0, 1, 3, or 4 when SEIGcmpFaceIndex[2] is equal to 2 or 3");
              if (m_gcmpSEIPackingType == 4)
              {
                if (m_gcmpSEIFaceIndex[i] == 1)
    
    Ya-Hsuan Lee's avatar
    Ya-Hsuan Lee committed
                {
    
                  xConfirmPara( m_gcmpSEIFaceRotation[i] != 0 && m_gcmpSEIFaceRotation[i] != 2, "SEIGcmpFaceRotation[i] must be 0 or 2 when SEIGcmpFaceIndex[2] is equal to 2 or 3 and SEIGcmpFaceIndex[i] is equal to 1");
    
    Ya-Hsuan Lee's avatar
    Ya-Hsuan Lee committed
                }
    
    Ya-Hsuan Lee's avatar
    Ya-Hsuan Lee committed
                {
    
                  xConfirmPara( m_gcmpSEIFaceRotation[i] != 1 && m_gcmpSEIFaceRotation[i] != 3, "SEIGcmpFaceRotation[i] must be 1 or 3 when SEIGcmpFaceIndex[2] is equal to 2 or 3 and SEIGcmpFaceIndex[i] is equal to 0, 4 or 5");
    
    Ya-Hsuan Lee's avatar
    Ya-Hsuan Lee committed
                }
    
              }
              else
              {
                if (m_gcmpSEIFaceIndex[i] == 1)
    
    Ya-Hsuan Lee's avatar
    Ya-Hsuan Lee committed
                {
    
                  xConfirmPara( m_gcmpSEIFaceRotation[i] != 1 && m_gcmpSEIFaceRotation[i] != 3, "SEIGcmpFaceRotation[i] must be 1 or 3 when SEIGcmpFaceIndex[2] is equal to 2 or 3 and SEIGcmpFaceIndex[i] is equal to 1");
    
    Ya-Hsuan Lee's avatar
    Ya-Hsuan Lee committed
                }
    
    Ya-Hsuan Lee's avatar
    Ya-Hsuan Lee committed
                {
    
                  xConfirmPara( m_gcmpSEIFaceRotation[i] != 0 && m_gcmpSEIFaceRotation[i] != 2, "SEIGcmpFaceRotation[i] must be 0 or 2 when SEIGcmpFaceIndex[2] is equal to 2 or 3 and SEIGcmpFaceIndex[i] is equal to 0, 4 or 5");
    
    Ya-Hsuan Lee's avatar
    Ya-Hsuan Lee committed
                }
    
              }
            }
            else if (m_gcmpSEIFaceIndex[2] == 4 || m_gcmpSEIFaceIndex[2] == 5)
            {
              xConfirmPara( m_gcmpSEIFaceIndex[i] == 4 || m_gcmpSEIFaceIndex[i] == 5, "SEIGcmpFaceIndex[i] must be in the range of 0 to 3 for i equal to 0, 1, 3, or 4 when SEIGcmpFaceIndex[2] is equal to 4 or 5");
              if (m_gcmpSEIPackingType == 4)
              {
                if (m_gcmpSEIFaceIndex[i] == 0)
    
    Ya-Hsuan Lee's avatar
    Ya-Hsuan Lee committed
                {
    
                  xConfirmPara( m_gcmpSEIFaceRotation[i] != 0 && m_gcmpSEIFaceRotation[i] != 2, "SEIGcmpFaceRotation[i] must be 0 or 2 when SEIGcmpFaceIndex[2] is equal to 4 or 5 and SEIGcmpFaceIndex[i] is equal to 0");
    
    Ya-Hsuan Lee's avatar
    Ya-Hsuan Lee committed
                }
    
    Ya-Hsuan Lee's avatar
    Ya-Hsuan Lee committed
                {
    
                  xConfirmPara( m_gcmpSEIFaceRotation[i] != 1 && m_gcmpSEIFaceRotation[i] != 3, "SEIGcmpFaceRotation[i] must be 1 or 3 when SEIGcmpFaceIndex[2] is equal to 4 or 5 and SEIGcmpFaceIndex[i] is equal to 1, 2 or 3");
    
    Ya-Hsuan Lee's avatar
    Ya-Hsuan Lee committed
                }
    
              }
              else
              {
                if (m_gcmpSEIFaceIndex[i] == 0)
    
    Ya-Hsuan Lee's avatar
    Ya-Hsuan Lee committed
                {
    
                  xConfirmPara( m_gcmpSEIFaceRotation[i] != 1 && m_gcmpSEIFaceRotation[i] != 3, "SEIGcmpFaceRotation[i] must be 1 or 3 when SEIGcmpFaceIndex[2] is equal to 4 or 5 and SEIGcmpFaceIndex[i] is equal to 0");
    
    Ya-Hsuan Lee's avatar
    Ya-Hsuan Lee committed
                }
    
    Ya-Hsuan Lee's avatar
    Ya-Hsuan Lee committed
                {
    
                  xConfirmPara( m_gcmpSEIFaceRotation[i] != 0 && m_gcmpSEIFaceRotation[i] != 2, "SEIGcmpFaceRotation[i] must be 0 or 2 when SEIGcmpFaceIndex[2] is equal to 4 or 5 and SEIGcmpFaceIndex[i] is equal to 1, 2 or 3");
    
    Ya-Hsuan Lee's avatar
    Ya-Hsuan Lee committed
                }
    
        }
        if (m_gcmpSEIGuardBandFlag)
        {
          xConfirmPara( m_gcmpSEIGuardBandSamplesMinus1 < 0 || m_gcmpSEIGuardBandSamplesMinus1 > 15, "SEIGcmpGuardBandSamplesMinus1 must be in the range of 0 to 15");
        }
      }
    
    
    #if JVET_Z0120_SII_SEI_PROCESSING
      if (m_siiSEIEnabled && m_ShutterFilterEnable)
      {
        xConfirmPara(m_maxTempLayer == 1 || m_maxDecPicBuffering[0] == 1,"Shutter Interval SEI message processing is disabled for single TempLayer and single frame in DPB\n");
      }
    #endif
    
    
      if (m_nnPostFilterSEICharacteristicsEnabled)
      {
        for (int i = 0; i < m_nnPostFilterSEICharacteristicsNumFilters; i++)
        {
    
          xConfirmPara(m_nnPostFilterSEICharacteristicsId[i] > MAX_NNPFC_ID, "SEINNPostFilterCharacteristicsId must be in the range of 0 to 2^32-2");
    
          xConfirmPara(m_nnPostFilterSEICharacteristicsModeIdc[i] > 255, "SEINNPostFilterCharacteristicsModeIdc must be in the range of 0 to 255");
    
          xConfirmPara(m_nnPostFilterSEICharacteristicsPurpose[i] > 1023, "SEINNPostFilterCharacteristicsPurpose must be in the range of 0 to 1023");
    
          xConfirmPara(m_nnPostFilterSEICharacteristicsInpTensorBitDepthMinus8[i] > 24, "SEINNPostFilterCharacteristicsInpTensorBitDepthMinus8 must be in the range of 0 to 24");
          xConfirmPara(m_nnPostFilterSEICharacteristicsOutTensorBitDepthMinus8[i] > 24, "SEINNPostFilterCharacteristicsOutTensorBitDepthMinus8 must be in the range of 0 to 24");
    
          xConfirmPara(m_nnPostFilterSEICharacteristicsInpFormatIdc[i] > 255, "SEINNPostFilterCharacteristicsInpFormatIdc must be in the range of 0 to 255");
    
          xConfirmPara(m_nnPostFilterSEICharacteristicsInpOrderIdc[i] > 255, "SEINNPostFilterCharacteristicsInpOrderIdc must be in the range of  0 to 255");
    
          xConfirmPara(m_nnPostFilterSEICharacteristicsColPrimaries[i] > 255, "m_nnPostFilterSEICharacteristicsColPrimaries must in the range 0 to 255");
          xConfirmPara(m_nnPostFilterSEICharacteristicsTransCharacteristics[i] > 255, "m_nnPostFilterSEICharacteristicsTransCharacteristics must in the range 0 to 255");
          xConfirmPara(m_nnPostFilterSEICharacteristicsMatrixCoeffs[i] > 255, "m_nnPostFilterSEICharacteristicsMatrixCoeffs must in the range 0 to 255");
    
          xConfirmPara(m_nnPostFilterSEICharacteristicsOutFormatIdc[i] > 255, "SEINNPostFilterCharacteristicsOutFormatIdc must be in the range of 0 to 255");
    
          xConfirmPara(m_nnPostFilterSEICharacteristicsOutOrderIdc[i] > 255, "SEINNPostFilterCharacteristicsOutOrderIdc must be in the range of 0 to 255");
          xConfirmPara(m_nnPostFilterSEICharacteristicsPatchWidthMinus1[i] > 32766, "SEINNPostFilterCharacteristicsPatchWidthMinus1 must be in the range of 0 to 32766");
          xConfirmPara(m_nnPostFilterSEICharacteristicsPatchHeightMinus1[i] > 32766, "SEINNPostFilterCharacteristicsPatchHeightMinus1 must be in the range of 0 to 32766");
          xConfirmPara(m_nnPostFilterSEICharacteristicsOverlap[i] > 16383, "SEINNPostFilterCharacteristicsOverlap must be in the range of 0 to 16383");
          xConfirmPara(m_nnPostFilterSEICharacteristicsPaddingType[i] > (1 << 4) - 1, "SEINNPostFilterPaddingType must be in the range of 0 to 2^4-1");
          xConfirmPara(m_nnPostFilterSEICharacteristicsLog2ParameterBitLengthMinus3[i] > 3, "SEINNPostFilterCharacteristicsLog2ParameterBitLengthMinus3 must be in the range of 0 to 3");
    
          xConfirmPara(m_nnPostFilterSEICharacteristicsNumParametersIdc[i] > 52, "SEINNPostFilterCharacteristicsNumParametersIdc must be in the range of 0 to 52");
    
          xConfirmPara(m_nnPostFilterSEICharacteristicsTotalKilobyteSize[i] > (uint32_t) (((uint64_t) 1 << 32) - 1), "SEINNPostFilterCharacteristicsTotalKilobyteSize must be in the range of 0 to 2^32-1");
    
        }
      }
    
      if (m_nnPostFilterSEIActivationEnabled)
      {
    
        xConfirmPara(m_nnPostFilterSEIActivationId > MAX_NNPFA_ID, "SEINNPostFilterActivationId must be in the range of 0 to 2^32-2");
    
      if (m_phaseIndicationSEIEnabledFullResolution)
      {
        xConfirmPara(m_piHorPhaseNumFullResolution < 0, "m_piHorPhaseNumFullResolution must be in the range of 0 to 511, inclusive");
        xConfirmPara(m_piHorPhaseDenMinus1FullResolution < 0, "m_piHorPhaseDenMinus1FullResolution must be in the range of 0 to 511, inclusive");
        xConfirmPara(m_piVerPhaseNumFullResolution < 0, "m_piVerPhaseNumFullResolution must be in the range of 0 to 511, inclusive");
        xConfirmPara(m_piVerPhaseDenMinus1FullResolution < 0, "m_piVerPhaseDenMinus1FullResolution must be in the range of 0 to 511, inclusive");
        xConfirmPara(m_piHorPhaseDenMinus1FullResolution > 511, "m_piHorPhaseDenMinus1FullResolution must be in the range of 0 to 511, inclusive");
        xConfirmPara(m_piHorPhaseNumFullResolution > m_piHorPhaseDenMinus1FullResolution + 1, "m_piHorPhaseNumFullResolution must be in the range of 0 to m_piHorPhaseDenMinus1FullResolution + 1, inclusive");
        xConfirmPara(m_piVerPhaseDenMinus1FullResolution > 511, "m_piVerPhaseDenMinus1FullResolution must be in the range of 0 to 511, inclusive");
        xConfirmPara(m_piVerPhaseNumFullResolution > m_piVerPhaseDenMinus1FullResolution + 1, "m_piVerPhaseNumFullResolution must be in the range of 0 to m_piVerPhaseDenMinus1FullResolution + 1, inclusive");
      }
      if (m_phaseIndicationSEIEnabledReducedResolution)
      {
        xConfirmPara(m_piHorPhaseNumReducedResolution < 0, "m_piHorPhaseNumReducedResolution must be in the range of 0 to 511, inclusive");
        xConfirmPara(m_piHorPhaseDenMinus1ReducedResolution < 0, "m_piHorPhaseDenMinus1ReducedResolution must be in the range of 0 to 511, inclusive");
        xConfirmPara(m_piVerPhaseNumReducedResolution < 0, "m_piVerPhaseNumReducedResolution must be in the range of 0 to 511, inclusive");
        xConfirmPara(m_piVerPhaseDenMinus1ReducedResolution < 0, "m_piVerPhaseDenMinus1ReducedResolution must be in the range of 0 to 511, inclusive");
        xConfirmPara(m_piHorPhaseDenMinus1ReducedResolution > 511, "m_piHorPhaseDenMinus1ReducedResolution must be in the range of 0 to 511, inclusive");
        xConfirmPara(m_piHorPhaseNumReducedResolution > m_piHorPhaseDenMinus1ReducedResolution + 1, "m_piHorPhaseNumReducedResolution must be in the range of 0 to m_piHorPhaseDenMinus1ReducedResolution + 1, inclusive");
        xConfirmPara(m_piVerPhaseDenMinus1ReducedResolution > 511, "m_piVerPhaseDenMinus1ReducedResolution must be in the range of 0 to 511, inclusive");
        xConfirmPara(m_piVerPhaseNumReducedResolution > m_piVerPhaseDenMinus1ReducedResolution + 1, "m_piVerPhaseNumReducedResolution must be in the range of 0 to m_piVerPhaseDenMinus1ReducedResolution + 1, inclusive");
      }
    
    
      xConfirmPara(m_log2ParallelMergeLevel < 2, "Log2ParallelMergeLevel should be larger than or equal to 2");
    
    Frank Bossen's avatar
    Frank Bossen committed
      xConfirmPara(m_log2ParallelMergeLevel > m_ctuSize, "Log2ParallelMergeLevel should be less than or equal to CTU size");
    
      xConfirmPara(m_preferredTransferCharacteristics > 255, "transfer_characteristics_idc should not be greater than 255.");
    
      xConfirmPara( unsigned(m_ImvMode) > 1, "ImvMode exceeds range (0 to 1)" );
    
      if (m_AffineAmvr)
      {
        xConfirmPara(!m_ImvMode, "AffineAmvr cannot be used when IMV is disabled.");
      }
    
      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 (m_gopBasedTemporalFilterEnabled)
      {
        xConfirmPara(m_temporalSubsampleRatio != 1, "GOP Based Temporal Filter only support Temporal sub-sample ratio 1");
    
        xConfirmPara(
          m_gopBasedTemporalFilterPastRefs <= 0 && m_gopBasedTemporalFilterFutureRefs <= 0,
          "Either TemporalFilterPastRefs or TemporalFilterFutureRefs must be larger than 0 when TemporalFilter is enabled");
    
        if ((m_gopBasedTemporalFilterPastRefs != 0 && m_gopBasedTemporalFilterPastRefs != TF_DEFAULT_REFS)
            || (m_gopBasedTemporalFilterFutureRefs != 0 && m_gopBasedTemporalFilterFutureRefs != TF_DEFAULT_REFS))
        {
          msg(WARNING, "Number of frames used for temporal prefilter is different from default.\n");
        }
    
      if (m_bimEnabled)
      {
        xConfirmPara(m_temporalSubsampleRatio != 1, "Block Importance Mapping only support Temporal sub-sample ratio 1");
        xConfirmPara(
          m_gopBasedTemporalFilterPastRefs <= 0 && m_gopBasedTemporalFilterFutureRefs <= 0,
          "Either TemporalFilterPastRefs or TemporalFilterFutureRefs must be larger than 0 when Block Importance Mapping is enabled" );
    
    #if EXTENSION_360_VIDEO
      check_failed |= m_ext360.verifyParameters();
    #endif
    
    
      xConfirmPara(m_useColorTrans && (m_log2MaxTbSize == 6), "Log2MaxTbSize must be less than 6 when ACT is enabled, otherwise ACT needs to be disabled");
    
    Frank Bossen's avatar
    Frank Bossen committed
      xConfirmPara(m_ctuSize <= 32 && (m_log2MaxTbSize == 6), "Log2MaxTbSize must be less than 6 when CTU size is 32");
    
    #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() );