Skip to content
Snippets Groups Projects
VLCWriter.cpp 85.1 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     VLCWriter.cpp
     *  \brief    Writer for high level syntax
     */
    
    #include "VLCWriter.h"
    #include "SEIwrite.h"
    
    #include "CommonLib/CommonDef.h"
    #include "CommonLib/Unit.h"
    #include "CommonLib/Picture.h" // th remove this
    #include "CommonLib/dtrace_next.h"
    #include "EncAdaptiveLoopFilter.h"
    #include "CommonLib/AdaptiveLoopFilter.h"
    
    //! \ingroup EncoderLib
    //! \{
    
    #if ENABLE_TRACING
    
    void  VLCWriter::xWriteCodeTr (uint32_t value, uint32_t  length, const char *pSymbolName)
    {
      xWriteCode (value,length);
    
      if( g_HLSTraceEnable )
      {
        if( length < 10 )
        {
          DTRACE( g_trace_ctx, D_HEADER, "%-50s u(%d)  : %d\n", pSymbolName, length, value );
        }
        else
        {
          DTRACE( g_trace_ctx, D_HEADER, "%-50s u(%d) : %d\n", pSymbolName, length, value );
        }
      }
    }
    
    void  VLCWriter::xWriteUvlcTr (uint32_t value, const char *pSymbolName)
    {
      xWriteUvlc (value);
      if( g_HLSTraceEnable )
      {
        DTRACE( g_trace_ctx, D_HEADER, "%-50s ue(v) : %d\n", pSymbolName, value );
      }
    }
    
    void  VLCWriter::xWriteSvlcTr (int value, const char *pSymbolName)
    {
      xWriteSvlc(value);
      if( g_HLSTraceEnable )
      {
        DTRACE( g_trace_ctx, D_HEADER, "%-50s se(v) : %d\n", pSymbolName, value );
      }
    }
    
    void  VLCWriter::xWriteFlagTr(uint32_t value, const char *pSymbolName)
    {
      xWriteFlag(value);
      if( g_HLSTraceEnable )
      {
        DTRACE( g_trace_ctx, D_HEADER, "%-50s u(1)  : %d\n", pSymbolName, value );
      }
    }
    
    bool g_HLSTraceEnable = true;
    
    #endif
    
    
    void VLCWriter::xWriteCode     ( uint32_t uiCode, uint32_t uiLength )
    {
      CHECK( uiLength == 0, "Code of lenght '0' not supported" );
      m_pcBitIf->write( uiCode, uiLength );
    }
    
    void VLCWriter::xWriteUvlc     ( uint32_t uiCode )
    {
      uint32_t uiLength = 1;
      uint32_t uiTemp = ++uiCode;
    
      CHECK( !uiTemp, "Integer overflow" );
    
      while( 1 != uiTemp )
      {
        uiTemp >>= 1;
        uiLength += 2;
      }
      // Take care of cases where uiLength > 32
      m_pcBitIf->write( 0, uiLength >> 1);
      m_pcBitIf->write( uiCode, (uiLength+1) >> 1);
    }
    
    void VLCWriter::xWriteSvlc     ( int iCode )
    {
      uint32_t uiCode = uint32_t( iCode <= 0 ? (-iCode)<<1 : (iCode<<1)-1);
      xWriteUvlc( uiCode );
    }
    
    void VLCWriter::xWriteFlag( uint32_t uiCode )
    {
      m_pcBitIf->write( uiCode, 1 );
    }
    
    void VLCWriter::xWriteRbspTrailingBits()
    {
      WRITE_FLAG( 1, "rbsp_stop_one_bit");
      int cnt = 0;
      while (m_pcBitIf->getNumBitsUntilByteAligned())
      {
        WRITE_FLAG( 0, "rbsp_alignment_zero_bit");
        cnt++;
      }
      CHECK(cnt>=8, "More than '8' alignment bytes read");
    }
    
    void AUDWriter::codeAUD(OutputBitstream& bs, const int pictureType)
    {
    #if ENABLE_TRACING
      xTraceAccessUnitDelimiter();
    #endif
    
      CHECK(pictureType >= 3, "Invalid picture type");
      setBitstream(&bs);
      WRITE_CODE(pictureType, 3, "pic_type");
      xWriteRbspTrailingBits();
    }
    
    void HLSWriter::xCodeShortTermRefPicSet( const ReferencePictureSet* rps, bool calledFromSliceHeader, int idx)
    {
      //int lastBits = getNumberOfWrittenBits();
    
      if (idx > 0)
      {
        WRITE_FLAG( rps->getInterRPSPrediction(), "inter_ref_pic_set_prediction_flag" ); // inter_RPS_prediction_flag
      }
      if (rps->getInterRPSPrediction())
      {
        int deltaRPS = rps->getDeltaRPS();
        if(calledFromSliceHeader)
        {
          WRITE_UVLC( rps->getDeltaRIdxMinus1(), "delta_idx_minus1" ); // delta index of the Reference Picture Set used for prediction minus 1
        }
    
        WRITE_CODE( (deltaRPS >=0 ? 0: 1), 1, "delta_rps_sign" ); //delta_rps_sign
        WRITE_UVLC( abs(deltaRPS) - 1, "abs_delta_rps_minus1"); // absolute delta RPS minus 1
    
        for(int j=0; j < rps->getNumRefIdc(); j++)
        {
          int refIdc = rps->getRefIdc(j);
          WRITE_CODE( (refIdc==1? 1: 0), 1, "used_by_curr_pic_flag" ); //first bit is "1" if Idc is 1
          if (refIdc != 1)
          {
            WRITE_CODE( refIdc>>1, 1, "use_delta_flag" ); //second bit is "1" if Idc is 2, "0" otherwise.
          }
        }
      }
      else
      {
        WRITE_UVLC( rps->getNumberOfNegativePictures(), "num_negative_pics" );
        WRITE_UVLC( rps->getNumberOfPositivePictures(), "num_positive_pics" );
        int prev = 0;
        for(int j=0 ; j < rps->getNumberOfNegativePictures(); j++)
        {
          WRITE_UVLC( prev-rps->getDeltaPOC(j)-1, "delta_poc_s0_minus1" );
          prev = rps->getDeltaPOC(j);
          WRITE_FLAG( rps->getUsed(j), "used_by_curr_pic_s0_flag");
        }
        prev = 0;
        for(int j=rps->getNumberOfNegativePictures(); j < rps->getNumberOfNegativePictures()+rps->getNumberOfPositivePictures(); j++)
        {
          WRITE_UVLC( rps->getDeltaPOC(j)-prev-1, "delta_poc_s1_minus1" );
          prev = rps->getDeltaPOC(j);
          WRITE_FLAG( rps->getUsed(j), "used_by_curr_pic_s1_flag" );
        }
      }
    
      //DTRACE( g_trace_ctx, D_RPSINFO, "irps=%d (%2d bits) ", rps->getInterRPSPrediction(), getNumberOfWrittenBits() - lastBits );
      rps->printDeltaPOC();
    }
    
    void HLSWriter::codePPS( const PPS* pcPPS )
    {
    #if ENABLE_TRACING
      xTracePPSHeader ();
    #endif
    
      WRITE_UVLC( pcPPS->getPPSId(),                             "pps_pic_parameter_set_id" );
      WRITE_UVLC( pcPPS->getSPSId(),                             "pps_seq_parameter_set_id" );
    #if HEVC_DEPENDENT_SLICES
      WRITE_FLAG( pcPPS->getDependentSliceSegmentsEnabledFlag()    ? 1 : 0, "dependent_slice_segments_enabled_flag" );
    #endif
      WRITE_FLAG( pcPPS->getOutputFlagPresentFlag() ? 1 : 0,     "output_flag_present_flag" );
      WRITE_CODE( pcPPS->getNumExtraSliceHeaderBits(), 3,        "num_extra_slice_header_bits");
      WRITE_FLAG( pcPPS->getCabacInitPresentFlag() ? 1 : 0,   "cabac_init_present_flag" );
      WRITE_UVLC( pcPPS->getNumRefIdxL0DefaultActive()-1,     "num_ref_idx_l0_default_active_minus1");
      WRITE_UVLC( pcPPS->getNumRefIdxL1DefaultActive()-1,     "num_ref_idx_l1_default_active_minus1");
    
      WRITE_SVLC( pcPPS->getPicInitQPMinus26(),                  "init_qp_minus26");
      WRITE_FLAG( pcPPS->getConstrainedIntraPred() ? 1 : 0,      "constrained_intra_pred_flag" );
      WRITE_FLAG( pcPPS->getUseTransformSkip() ? 1 : 0,  "transform_skip_enabled_flag" );
      WRITE_FLAG( pcPPS->getUseDQP() ? 1 : 0, "cu_qp_delta_enabled_flag" );
      if ( pcPPS->getUseDQP() )
      {
    
        WRITE_UVLC( pcPPS->getCuQpDeltaSubdiv(), "cu_qp_delta_subdiv" );
    
      }
    
      WRITE_SVLC( pcPPS->getQpOffset(COMPONENT_Cb), "pps_cb_qp_offset" );
      WRITE_SVLC( pcPPS->getQpOffset(COMPONENT_Cr), "pps_cr_qp_offset" );
    
      WRITE_FLAG( pcPPS->getSliceChromaQpFlag() ? 1 : 0,          "pps_slice_chroma_qp_offsets_present_flag" );
    
      WRITE_FLAG( pcPPS->getUseWP() ? 1 : 0,  "weighted_pred_flag" );   // Use of Weighting Prediction (P_SLICE)
      WRITE_FLAG( pcPPS->getWPBiPred() ? 1 : 0, "weighted_bipred_flag" );  // Use of Weighting Bi-Prediction (B_SLICE)
      WRITE_FLAG( pcPPS->getTransquantBypassEnabledFlag()  ? 1 : 0, "transquant_bypass_enabled_flag" );
      WRITE_FLAG( pcPPS->getTilesEnabledFlag() ? 1 : 0, "tiles_enabled_flag" );
      WRITE_FLAG( pcPPS->getEntropyCodingSyncEnabledFlag() ? 1 : 0, "entropy_coding_sync_enabled_flag" );
      if( pcPPS->getTilesEnabledFlag() )
      {
        WRITE_UVLC( pcPPS->getNumTileColumnsMinus1(),                                    "num_tile_columns_minus1" );
        WRITE_UVLC( pcPPS->getNumTileRowsMinus1(),                                       "num_tile_rows_minus1" );
        WRITE_FLAG( pcPPS->getTileUniformSpacingFlag(),                                  "uniform_spacing_flag" );
        if( !pcPPS->getTileUniformSpacingFlag() )
        {
          for(uint32_t i=0; i<pcPPS->getNumTileColumnsMinus1(); i++)
          {
            WRITE_UVLC( pcPPS->getTileColumnWidth(i)-1,                                  "column_width_minus1" );
          }
          for(uint32_t i=0; i<pcPPS->getNumTileRowsMinus1(); i++)
          {
            WRITE_UVLC( pcPPS->getTileRowHeight(i)-1,                                    "row_height_minus1" );
          }
        }
        CHECK ((pcPPS->getNumTileColumnsMinus1() + pcPPS->getNumTileRowsMinus1()) == 0, "Invalid tile parameters read");
        WRITE_FLAG( pcPPS->getLoopFilterAcrossTilesEnabledFlag()?1 : 0,       "loop_filter_across_tiles_enabled_flag");
      }
      WRITE_FLAG( pcPPS->getLoopFilterAcrossSlicesEnabledFlag()?1 : 0,        "pps_loop_filter_across_slices_enabled_flag");
      WRITE_FLAG( pcPPS->getDeblockingFilterControlPresentFlag()?1 : 0,       "deblocking_filter_control_present_flag");
      if(pcPPS->getDeblockingFilterControlPresentFlag())
      {
        WRITE_FLAG( pcPPS->getDeblockingFilterOverrideEnabledFlag() ? 1 : 0,  "deblocking_filter_override_enabled_flag" );
        WRITE_FLAG( pcPPS->getPPSDeblockingFilterDisabledFlag() ? 1 : 0,      "pps_deblocking_filter_disabled_flag" );
        if(!pcPPS->getPPSDeblockingFilterDisabledFlag())
        {
          WRITE_SVLC( pcPPS->getDeblockingFilterBetaOffsetDiv2(),             "pps_beta_offset_div2" );
          WRITE_SVLC( pcPPS->getDeblockingFilterTcOffsetDiv2(),               "pps_tc_offset_div2" );
        }
      }
    #if HEVC_USE_SCALING_LISTS
      WRITE_FLAG( pcPPS->getScalingListPresentFlag() ? 1 : 0,                          "pps_scaling_list_data_present_flag" );
      if( pcPPS->getScalingListPresentFlag() )
      {
        codeScalingList( pcPPS->getScalingList() );
      }
    #endif
      WRITE_FLAG( pcPPS->getListsModificationPresentFlag(), "lists_modification_present_flag");
      WRITE_UVLC( pcPPS->getLog2ParallelMergeLevelMinus2(), "log2_parallel_merge_level_minus2");
      WRITE_FLAG( pcPPS->getSliceHeaderExtensionPresentFlag() ? 1 : 0, "slice_segment_header_extension_present_flag");
    
      bool pps_extension_present_flag=false;
      bool pps_extension_flags[NUM_PPS_EXTENSION_FLAGS]={false};
    
      pps_extension_flags[PPS_EXT__REXT] = pcPPS->getPpsRangeExtension().settingsDifferFromDefaults(pcPPS->getUseTransformSkip());
    
      // Other PPS extension flags checked here.
    
      for(int i=0; i<NUM_PPS_EXTENSION_FLAGS; i++)
      {
        pps_extension_present_flag|=pps_extension_flags[i];
      }
    
      WRITE_FLAG( (pps_extension_present_flag?1:0), "pps_extension_present_flag" );
    
      if (pps_extension_present_flag)
      {
    #if ENABLE_TRACING /*|| RExt__DECODER_DEBUG_BIT_STATISTICS*/
        static const char *syntaxStrings[]={ "pps_range_extension_flag",
          "pps_multilayer_extension_flag",
          "pps_extension_6bits[0]",
          "pps_extension_6bits[1]",
          "pps_extension_6bits[2]",
          "pps_extension_6bits[3]",
          "pps_extension_6bits[4]",
          "pps_extension_6bits[5]" };
    #endif
    
        for(int i=0; i<NUM_PPS_EXTENSION_FLAGS; i++)
        {
          WRITE_FLAG( pps_extension_flags[i]?1:0, syntaxStrings[i] );
        }
    
        for(int i=0; i<NUM_PPS_EXTENSION_FLAGS; i++) // loop used so that the order is determined by the enum.
        {
          if (pps_extension_flags[i])
          {
            switch (PPSExtensionFlagIndex(i))
            {
            case PPS_EXT__REXT:
            {
              const PPSRExt &ppsRangeExtension = pcPPS->getPpsRangeExtension();
              if (pcPPS->getUseTransformSkip())
              {
                WRITE_UVLC( ppsRangeExtension.getLog2MaxTransformSkipBlockSize()-2,            "log2_max_transform_skip_block_size_minus2");
              }
    
              WRITE_FLAG((ppsRangeExtension.getCrossComponentPredictionEnabledFlag() ? 1 : 0), "cross_component_prediction_enabled_flag" );
    
              WRITE_FLAG(uint32_t(ppsRangeExtension.getChromaQpOffsetListEnabledFlag()),           "chroma_qp_offset_list_enabled_flag" );
              if (ppsRangeExtension.getChromaQpOffsetListEnabledFlag())
              {
    
                WRITE_UVLC(ppsRangeExtension.getCuChromaQpOffsetSubdiv(),                      "cu_chroma_qp_offset_subdiv");
    
                WRITE_UVLC(ppsRangeExtension.getChromaQpOffsetListLen() - 1,                   "chroma_qp_offset_list_len_minus1");
                /* skip zero index */
                for (int cuChromaQpOffsetIdx = 0; cuChromaQpOffsetIdx < ppsRangeExtension.getChromaQpOffsetListLen(); cuChromaQpOffsetIdx++)
                {
                  WRITE_SVLC(ppsRangeExtension.getChromaQpOffsetListEntry(cuChromaQpOffsetIdx+1).u.comp.CbOffset,     "cb_qp_offset_list[i]");
                  WRITE_SVLC(ppsRangeExtension.getChromaQpOffsetListEntry(cuChromaQpOffsetIdx+1).u.comp.CrOffset,     "cr_qp_offset_list[i]");
                }
              }
    
              WRITE_UVLC( ppsRangeExtension.getLog2SaoOffsetScale(CHANNEL_TYPE_LUMA),           "log2_sao_offset_scale_luma"   );
              WRITE_UVLC( ppsRangeExtension.getLog2SaoOffsetScale(CHANNEL_TYPE_CHROMA),         "log2_sao_offset_scale_chroma" );
            }
            break;
            default:
              CHECK(pps_extension_flags[i]==false, "Unknown PPS extension signalled"); // Should never get here with an active PPS extension flag.
              break;
            } // switch
          } // if flag present
        } // loop over PPS flags
      } // pps_extension_present_flag is non-zero
      xWriteRbspTrailingBits();
    }
    
    
    Hendry's avatar
    Hendry committed
    void HLSWriter::codeAPS( APS* pcAPS)
    {
    
    #if ENABLE_TRACING
      xTraceAPSHeader();
    #endif
    
    
    Hendry's avatar
    Hendry committed
      AlfSliceParam param = pcAPS->getAlfAPSParam();
      WRITE_CODE(pcAPS->getAPSId(), 5, "adaptation_parameter_set_id");
    
      const int alfChromaIdc = param.enabledFlag[COMPONENT_Cb] * 2 + param.enabledFlag[COMPONENT_Cr];
      truncatedUnaryEqProb(alfChromaIdc, 3);   // alf_chroma_idc
    
    
    #if JVET_N0242_NON_LINEAR_ALF
      WRITE_FLAG( param.nonLinearFlag[CHANNEL_TYPE_LUMA], "alf_luma_clip" );
      if( alfChromaIdc )
      {
        WRITE_FLAG( param.nonLinearFlag[CHANNEL_TYPE_CHROMA], "alf_chroma_clip" );
      }
    #endif
    
    
    Hendry's avatar
    Hendry committed
      xWriteTruncBinCode(param.numLumaFilters - 1, MAX_NUM_ALF_CLASSES);  //number_of_filters_minus1
      if (param.numLumaFilters > 1)
      {
        for (int i = 0; i < MAX_NUM_ALF_CLASSES; i++)
        {
          xWriteTruncBinCode((uint32_t)param.filterCoeffDeltaIdx[i], param.numLumaFilters);  //filter_coeff_delta[i]
        }
      }
    
      alfFilter(param, false);
    
      if (alfChromaIdc)
      {
        alfFilter(param, true);
      }
      xWriteRbspTrailingBits();
    }
    
    void HLSWriter::codeVUI( const VUI *pcVUI, const SPS* pcSPS )
    {
    #if ENABLE_TRACING
      DTRACE( g_trace_ctx, D_HEADER, "----------- vui_parameters -----------\n");
    #endif
      WRITE_FLAG(pcVUI->getAspectRatioInfoPresentFlag(),            "aspect_ratio_info_present_flag");
      if (pcVUI->getAspectRatioInfoPresentFlag())
      {
        WRITE_CODE(pcVUI->getAspectRatioIdc(), 8,                   "aspect_ratio_idc" );
        if (pcVUI->getAspectRatioIdc() == 255)
        {
          WRITE_CODE(pcVUI->getSarWidth(), 16,                      "sar_width");
          WRITE_CODE(pcVUI->getSarHeight(), 16,                     "sar_height");
        }
      }
      WRITE_FLAG(pcVUI->getOverscanInfoPresentFlag(),               "overscan_info_present_flag");
      if (pcVUI->getOverscanInfoPresentFlag())
      {
        WRITE_FLAG(pcVUI->getOverscanAppropriateFlag(),             "overscan_appropriate_flag");
      }
      WRITE_FLAG(pcVUI->getVideoSignalTypePresentFlag(),            "video_signal_type_present_flag");
      if (pcVUI->getVideoSignalTypePresentFlag())
      {
        WRITE_CODE(pcVUI->getVideoFormat(), 3,                      "video_format");
        WRITE_FLAG(pcVUI->getVideoFullRangeFlag(),                  "video_full_range_flag");
        WRITE_FLAG(pcVUI->getColourDescriptionPresentFlag(),        "colour_description_present_flag");
        if (pcVUI->getColourDescriptionPresentFlag())
        {
          WRITE_CODE(pcVUI->getColourPrimaries(), 8,                "colour_primaries");
          WRITE_CODE(pcVUI->getTransferCharacteristics(), 8,        "transfer_characteristics");
          WRITE_CODE(pcVUI->getMatrixCoefficients(), 8,             "matrix_coeffs");
        }
      }
    
      WRITE_FLAG(pcVUI->getChromaLocInfoPresentFlag(),              "chroma_loc_info_present_flag");
      if (pcVUI->getChromaLocInfoPresentFlag())
      {
        WRITE_UVLC(pcVUI->getChromaSampleLocTypeTopField(),         "chroma_sample_loc_type_top_field");
        WRITE_UVLC(pcVUI->getChromaSampleLocTypeBottomField(),      "chroma_sample_loc_type_bottom_field");
      }
    
      WRITE_FLAG(pcVUI->getNeutralChromaIndicationFlag(),           "neutral_chroma_indication_flag");
      WRITE_FLAG(pcVUI->getFieldSeqFlag(),                          "field_seq_flag");
      WRITE_FLAG(pcVUI->getFrameFieldInfoPresentFlag(),             "frame_field_info_present_flag");
    
      Window defaultDisplayWindow = pcVUI->getDefaultDisplayWindow();
      WRITE_FLAG(defaultDisplayWindow.getWindowEnabledFlag(),       "default_display_window_flag");
      if( defaultDisplayWindow.getWindowEnabledFlag() )
      {
        WRITE_UVLC(defaultDisplayWindow.getWindowLeftOffset()  / SPS::getWinUnitX(pcSPS->getChromaFormatIdc()), "def_disp_win_left_offset");
        WRITE_UVLC(defaultDisplayWindow.getWindowRightOffset() / SPS::getWinUnitX(pcSPS->getChromaFormatIdc()), "def_disp_win_right_offset");
        WRITE_UVLC(defaultDisplayWindow.getWindowTopOffset()   / SPS::getWinUnitY(pcSPS->getChromaFormatIdc()), "def_disp_win_top_offset");
        WRITE_UVLC(defaultDisplayWindow.getWindowBottomOffset()/ SPS::getWinUnitY(pcSPS->getChromaFormatIdc()), "def_disp_win_bottom_offset");
      }
      const TimingInfo *timingInfo = pcVUI->getTimingInfo();
      WRITE_FLAG(timingInfo->getTimingInfoPresentFlag(),          "vui_timing_info_present_flag");
      if(timingInfo->getTimingInfoPresentFlag())
      {
        WRITE_CODE(timingInfo->getNumUnitsInTick(), 32,           "vui_num_units_in_tick");
        WRITE_CODE(timingInfo->getTimeScale(),      32,           "vui_time_scale");
        WRITE_FLAG(timingInfo->getPocProportionalToTimingFlag(),  "vui_poc_proportional_to_timing_flag");
        if(timingInfo->getPocProportionalToTimingFlag())
        {
          WRITE_UVLC(timingInfo->getNumTicksPocDiffOneMinus1(),   "vui_num_ticks_poc_diff_one_minus1");
        }
        WRITE_FLAG(pcVUI->getHrdParametersPresentFlag(),              "vui_hrd_parameters_present_flag");
        if( pcVUI->getHrdParametersPresentFlag() )
        {
          codeHrdParameters(pcVUI->getHrdParameters(), 1, pcSPS->getMaxTLayers() - 1 );
        }
      }
    
      WRITE_FLAG(pcVUI->getBitstreamRestrictionFlag(),              "bitstream_restriction_flag");
      if (pcVUI->getBitstreamRestrictionFlag())
      {
        WRITE_FLAG(pcVUI->getTilesFixedStructureFlag(),             "tiles_fixed_structure_flag");
        WRITE_FLAG(pcVUI->getMotionVectorsOverPicBoundariesFlag(),  "motion_vectors_over_pic_boundaries_flag");
        WRITE_FLAG(pcVUI->getRestrictedRefPicListsFlag(),           "restricted_ref_pic_lists_flag");
        WRITE_UVLC(pcVUI->getMinSpatialSegmentationIdc(),           "min_spatial_segmentation_idc");
        WRITE_UVLC(pcVUI->getMaxBytesPerPicDenom(),                 "max_bytes_per_pic_denom");
        WRITE_UVLC(pcVUI->getMaxBitsPerMinCuDenom(),                "max_bits_per_min_cu_denom");
        WRITE_UVLC(pcVUI->getLog2MaxMvLengthHorizontal(),           "log2_max_mv_length_horizontal");
        WRITE_UVLC(pcVUI->getLog2MaxMvLengthVertical(),             "log2_max_mv_length_vertical");
      }
    }
    
    void HLSWriter::codeHrdParameters( const HRD *hrd, bool commonInfPresentFlag, uint32_t maxNumSubLayersMinus1 )
    {
      if( commonInfPresentFlag )
      {
        WRITE_FLAG( hrd->getNalHrdParametersPresentFlag() ? 1 : 0 ,  "nal_hrd_parameters_present_flag" );
        WRITE_FLAG( hrd->getVclHrdParametersPresentFlag() ? 1 : 0 ,  "vcl_hrd_parameters_present_flag" );
        if( hrd->getNalHrdParametersPresentFlag() || hrd->getVclHrdParametersPresentFlag() )
        {
          WRITE_FLAG( hrd->getSubPicCpbParamsPresentFlag() ? 1 : 0,  "sub_pic_hrd_params_present_flag" );
          if( hrd->getSubPicCpbParamsPresentFlag() )
          {
            WRITE_CODE( hrd->getTickDivisorMinus2(), 8,              "tick_divisor_minus2" );
            WRITE_CODE( hrd->getDuCpbRemovalDelayLengthMinus1(), 5,  "du_cpb_removal_delay_increment_length_minus1" );
            WRITE_FLAG( hrd->getSubPicCpbParamsInPicTimingSEIFlag() ? 1 : 0, "sub_pic_cpb_params_in_pic_timing_sei_flag" );
            WRITE_CODE( hrd->getDpbOutputDelayDuLengthMinus1(), 5,   "dpb_output_delay_du_length_minus1"  );
          }
          WRITE_CODE( hrd->getBitRateScale(), 4,                     "bit_rate_scale" );
          WRITE_CODE( hrd->getCpbSizeScale(), 4,                     "cpb_size_scale" );
          if( hrd->getSubPicCpbParamsPresentFlag() )
          {
            WRITE_CODE( hrd->getDuCpbSizeScale(), 4,                "du_cpb_size_scale" );
          }
          WRITE_CODE( hrd->getInitialCpbRemovalDelayLengthMinus1(), 5, "initial_cpb_removal_delay_length_minus1" );
          WRITE_CODE( hrd->getCpbRemovalDelayLengthMinus1(),        5, "au_cpb_removal_delay_length_minus1" );
          WRITE_CODE( hrd->getDpbOutputDelayLengthMinus1(),         5, "dpb_output_delay_length_minus1" );
        }
      }
      int i, j, nalOrVcl;
      for( i = 0; i <= maxNumSubLayersMinus1; i ++ )
      {
        WRITE_FLAG( hrd->getFixedPicRateFlag( i ) ? 1 : 0,          "fixed_pic_rate_general_flag");
        bool fixedPixRateWithinCvsFlag = true;
        if( !hrd->getFixedPicRateFlag( i ) )
        {
          fixedPixRateWithinCvsFlag = hrd->getFixedPicRateWithinCvsFlag( i );
          WRITE_FLAG( hrd->getFixedPicRateWithinCvsFlag( i ) ? 1 : 0, "fixed_pic_rate_within_cvs_flag");
        }
        if( fixedPixRateWithinCvsFlag )
        {
          WRITE_UVLC( hrd->getPicDurationInTcMinus1( i ),           "elemental_duration_in_tc_minus1");
        }
        else
        {
          WRITE_FLAG( hrd->getLowDelayHrdFlag( i ) ? 1 : 0,           "low_delay_hrd_flag");
        }
        if (!hrd->getLowDelayHrdFlag( i ))
        {
          WRITE_UVLC( hrd->getCpbCntMinus1( i ),                      "cpb_cnt_minus1");
        }
    
        for( nalOrVcl = 0; nalOrVcl < 2; nalOrVcl ++ )
        {
          if( ( ( nalOrVcl == 0 ) && ( hrd->getNalHrdParametersPresentFlag() ) ) ||
              ( ( nalOrVcl == 1 ) && ( hrd->getVclHrdParametersPresentFlag() ) ) )
          {
            for( j = 0; j <= ( hrd->getCpbCntMinus1( i ) ); j ++ )
            {
              WRITE_UVLC( hrd->getBitRateValueMinus1( i, j, nalOrVcl ), "bit_rate_value_minus1");
              WRITE_UVLC( hrd->getCpbSizeValueMinus1( i, j, nalOrVcl ), "cpb_size_value_minus1");
              if( hrd->getSubPicCpbParamsPresentFlag() )
              {
                WRITE_UVLC( hrd->getDuCpbSizeValueMinus1( i, j, nalOrVcl ), "cpb_size_du_value_minus1");
                WRITE_UVLC( hrd->getDuBitRateValueMinus1( i, j, nalOrVcl ), "bit_rate_du_value_minus1");
              }
              WRITE_FLAG( hrd->getCbrFlag( i, j, nalOrVcl ) ? 1 : 0, "cbr_flag");
            }
          }
        }
      }
    }
    
    
    Taoran Lu's avatar
    Taoran Lu committed
    void HLSWriter::codeReshaper(const SliceReshapeInfo& pSliceReshaperInfo, const SPS* pcSPS, const bool isIntra)
    
    Taoran Lu's avatar
    Taoran Lu committed
      WRITE_FLAG(pSliceReshaperInfo.getSliceReshapeModelPresentFlag() ? 1 : 0, "tile_group_reshaper_model_present_flag");
    
    Taoran Lu's avatar
    Taoran Lu committed
      if (pSliceReshaperInfo.getSliceReshapeModelPresentFlag())
      {
    
    Taoran Lu's avatar
    Taoran Lu committed
        WRITE_UVLC(pSliceReshaperInfo.reshaperModelMinBinIdx, "reshaper_model_min_bin_idx");
        WRITE_UVLC(PIC_CODE_CW_BINS - 1 - pSliceReshaperInfo.reshaperModelMaxBinIdx, "reshaper_model_delta_max_bin_idx");
    
    Taoran Lu's avatar
    Taoran Lu committed
        assert(pSliceReshaperInfo.maxNbitsNeededDeltaCW > 0);
    
        WRITE_UVLC(pSliceReshaperInfo.maxNbitsNeededDeltaCW - 1, "reshaper_model_bin_delta_abs_cw_prec_minus1");
    
    
    Taoran Lu's avatar
    Taoran Lu committed
        for (int i = pSliceReshaperInfo.reshaperModelMinBinIdx; i <= pSliceReshaperInfo.reshaperModelMaxBinIdx; i++)
    
    Taoran Lu's avatar
    Taoran Lu committed
          int deltaCW = pSliceReshaperInfo.reshaperModelBinCWDelta[i];
    
          int signCW = (deltaCW < 0) ? 1 : 0;
          int absCW = (deltaCW < 0) ? (-deltaCW) : deltaCW;
    
    Taoran Lu's avatar
    Taoran Lu committed
          WRITE_CODE(absCW, pSliceReshaperInfo.maxNbitsNeededDeltaCW, "reshaper_model_bin_delta_abs_CW");
    
          if (absCW > 0)
    
    Taoran Lu's avatar
    Taoran Lu committed
          {
            WRITE_FLAG(signCW, "reshaper_model_bin_delta_sign_CW_flag");
          }
    
    Taoran Lu's avatar
    Taoran Lu committed
      WRITE_FLAG(pSliceReshaperInfo.getUseSliceReshaper() ? 1 : 0, "tile_group_reshaper_enable_flag");
    
    Taoran Lu's avatar
    Taoran Lu committed
    
      if (!pSliceReshaperInfo.getUseSliceReshaper())
        return;
    
      if (!(pcSPS->getUseDualITree() && isIntra))
    
    Taoran Lu's avatar
    Taoran Lu committed
        WRITE_FLAG(pSliceReshaperInfo.getSliceReshapeChromaAdj(), "tile_group_reshaper_chroma_residual_scale_flag");
    
    #if ENABLE_TRACING
      xTraceSPSHeader ();
    #endif
    #if HEVC_VPS
      WRITE_CODE( pcSPS->getVPSId (),          4,       "sps_video_parameter_set_id" );
    #endif
    
    #if !JVET_M0101_HLS
    
      WRITE_UVLC( pcSPS->getSPSId (),                   "sps_seq_parameter_set_id" );
    
      WRITE_FLAG(pcSPS->getIntraOnlyConstraintFlag() ? 1 : 0, "intra_only_constraint_flag");
      WRITE_CODE(pcSPS->getMaxBitDepthConstraintIdc(), 4, "max_bitdepth_constraint_idc");
      WRITE_CODE(pcSPS->getMaxChromaFormatConstraintIdc(), 2, "max_chroma_format_constraint_idc");
    
      WRITE_FLAG(pcSPS->getFrameConstraintFlag() ? 1 : 0, "frame_only_constraint_flag");
    
      WRITE_FLAG(pcSPS->getNoQtbttDualTreeIntraConstraintFlag() ? 1 : 0, "no_qtbtt_dual_tree_intra_constraint_flag");
    
      WRITE_FLAG(pcSPS->getNoSaoConstraintFlag() ? 1 : 0, "no_sao_constraint_flag");
      WRITE_FLAG(pcSPS->getNoAlfConstraintFlag() ? 1 : 0, "no_alf_constraint_flag");
      WRITE_FLAG(pcSPS->getNoPcmConstraintFlag() ? 1 : 0, "no_pcm_constraint_flag");
    
      WRITE_FLAG(pcSPS->getNoRefWraparoundConstraintFlag() ? 1 : 0, "no_ref_wraparound_constraint_flag");
    
      WRITE_FLAG(pcSPS->getNoTemporalMvpConstraintFlag() ? 1 : 0, "no_temporal_mvp_constraint_flag");
      WRITE_FLAG(pcSPS->getNoSbtmvpConstraintFlag() ? 1 : 0, "no_sbtmvp_constraint_flag");
      WRITE_FLAG(pcSPS->getNoAmvrConstraintFlag() ? 1 : 0, "no_amvr_constraint_flag");
    
      WRITE_FLAG(pcSPS->getNoBdofConstraintFlag() ? 1 : 0, "no_bdof_constraint_flag");
      WRITE_FLAG(pcSPS->getNoCclmConstraintFlag() ? 1 : 0, "no_cclm_constraint_flag");
    
      WRITE_FLAG(pcSPS->getNoMtsConstraintFlag() ? 1 : 0, "no_mts_constraint_flag");
    
      WRITE_FLAG(pcSPS->getNoAffineMotionConstraintFlag() ? 1 : 0, "no_affine_motion_constraint_flag");
      WRITE_FLAG(pcSPS->getNoGbiConstraintFlag() ? 1 : 0, "no_gbi_constraint_flag");
      WRITE_FLAG(pcSPS->getNoMhIntraConstraintFlag() ? 1 : 0, "no_mh_intra_constraint_flag");
      WRITE_FLAG(pcSPS->getNoTriangleConstraintFlag() ? 1 : 0, "no_triangle_constraint_flag");
    
      WRITE_FLAG(pcSPS->getNoLadfConstraintFlag() ? 1 : 0, "no_ladf_constraint_flag");
    
      WRITE_FLAG(pcSPS->getNoCurrPicRefConstraintFlag() ? 1 : 0, "no_curr_pic_ref_constraint_flag");
      WRITE_FLAG(pcSPS->getNoQpDeltaConstraintFlag() ? 1 : 0, "no_qp_delta_constraint_flag");
    
      WRITE_FLAG(pcSPS->getNoDepQuantConstraintFlag() ? 1 : 0, "no_dep_quant_constraint_flag");
      WRITE_FLAG(pcSPS->getNoSignDataHidingConstraintFlag() ? 1 : 0, "no_sign_data_hiding_constraint_flag");
    
    
      CHECK( pcSPS->getMaxTLayers() == 0, "Maximum number of temporal sub-layers is '0'" );
    
      WRITE_CODE( pcSPS->getMaxTLayers() - 1,  3,       "sps_max_sub_layers_minus1" );
    
      WRITE_FLAG( pcSPS->getTemporalIdNestingFlag() ? 1 : 0, "sps_temporal_id_nesting_flag" );
      codePTL( pcSPS->getPTL(), true, pcSPS->getMaxTLayers() - 1 );
    
    #else
      CHECK(pcSPS->getMaxTLayers() == 0, "Maximum number of temporal sub-layers is '0'");
    
      WRITE_CODE(pcSPS->getMaxTLayers() - 1, 3, "sps_max_sub_layers_minus1");
      WRITE_CODE(0,                          5, "sps_reserved_zero_5bits");
    
      codeProfileTierLevel( pcSPS->getProfileTierLevel(), pcSPS->getMaxTLayers() - 1 );
    
      WRITE_UVLC(pcSPS->getSPSId (), "sps_seq_parameter_set_id");
    #endif
    
      WRITE_UVLC( int(pcSPS->getChromaFormatIdc ()),    "chroma_format_idc" );
    
    
      const ChromaFormat format                = pcSPS->getChromaFormatIdc();
    
      if( format == CHROMA_444 )
      {
        WRITE_FLAG( 0,                                  "separate_colour_plane_flag");
      }
    
      WRITE_UVLC( pcSPS->getPicWidthInLumaSamples (),   "pic_width_in_luma_samples" );
      WRITE_UVLC( pcSPS->getPicHeightInLumaSamples(),   "pic_height_in_luma_samples" );
      Window conf = pcSPS->getConformanceWindow();
    
    
      // KJS: not removing yet
    
      WRITE_FLAG( conf.getWindowEnabledFlag(),          "conformance_window_flag" );
      if (conf.getWindowEnabledFlag())
      {
        WRITE_UVLC( conf.getWindowLeftOffset()   / SPS::getWinUnitX(pcSPS->getChromaFormatIdc() ), "conf_win_left_offset" );
        WRITE_UVLC( conf.getWindowRightOffset()  / SPS::getWinUnitX(pcSPS->getChromaFormatIdc() ), "conf_win_right_offset" );
        WRITE_UVLC( conf.getWindowTopOffset()    / SPS::getWinUnitY(pcSPS->getChromaFormatIdc() ), "conf_win_top_offset" );
        WRITE_UVLC( conf.getWindowBottomOffset() / SPS::getWinUnitY(pcSPS->getChromaFormatIdc() ), "conf_win_bottom_offset" );
      }
    
      WRITE_UVLC( pcSPS->getBitDepth(CHANNEL_TYPE_LUMA) - 8,                      "bit_depth_luma_minus8" );
    
      const bool         chromaEnabled         = isChromaEnabled(format);
    
      WRITE_UVLC( chromaEnabled ? (pcSPS->getBitDepth(CHANNEL_TYPE_CHROMA) - 8):0,  "bit_depth_chroma_minus8" );
    
      WRITE_UVLC( pcSPS->getBitsForPOC()-4,                 "log2_max_pic_order_cnt_lsb_minus4" );
    
    
      // KJS: Marakech decision: sub-layers added back
    
      const bool subLayerOrderingInfoPresentFlag = 1;
      WRITE_FLAG(subLayerOrderingInfoPresentFlag,       "sps_sub_layer_ordering_info_present_flag");
      for(uint32_t i=0; i <= pcSPS->getMaxTLayers()-1; i++)
      {
        WRITE_UVLC( pcSPS->getMaxDecPicBuffering(i) - 1,       "sps_max_dec_pic_buffering_minus1[i]" );
        WRITE_UVLC( pcSPS->getNumReorderPics(i),               "sps_max_num_reorder_pics[i]" );
        WRITE_UVLC( pcSPS->getMaxLatencyIncreasePlus1(i),      "sps_max_latency_increase_plus1[i]" );
        if (!subLayerOrderingInfoPresentFlag)
        {
          break;
        }
      }
      CHECK( pcSPS->getMaxCUWidth() != pcSPS->getMaxCUHeight(),                          "Rectangular CTUs not supported" );
    
      WRITE_FLAG(pcSPS->getUseDualITree(), "qtbtt_dual_tree_intra_flag");
      WRITE_UVLC(g_aucLog2[pcSPS->getCTUSize()] - MIN_CU_LOG2, "log2_ctu_size_minus2");
    
      WRITE_UVLC(pcSPS->getLog2MinCodingBlockSize() - 2, "log2_min_luma_coding_block_size_minus2");
    
      WRITE_FLAG(pcSPS->getSplitConsOverrideEnabledFlag(), "partition_constraints_override_enabled_flag");
      WRITE_UVLC(g_aucLog2[pcSPS->getMinQTSize(I_SLICE)] - pcSPS->getLog2MinCodingBlockSize(), "sps_log2_diff_min_qt_min_cb_intra_tile_group_luma");
      WRITE_UVLC(g_aucLog2[pcSPS->getMinQTSize(B_SLICE)] - pcSPS->getLog2MinCodingBlockSize(), "sps_log2_diff_min_qt_min_cb_inter_tile_group");
      WRITE_UVLC(pcSPS->getMaxBTDepth(), "sps_max_mtt_hierarchy_depth_inter_tile_group");
      WRITE_UVLC(pcSPS->getMaxBTDepthI(), "sps_max_mtt_hierarchy_depth_intra_tile_group_luma");
    
      if (pcSPS->getMaxBTDepthI() != 0)
      {
    
        WRITE_UVLC(g_aucLog2[pcSPS->getMaxBTSizeI()] - g_aucLog2[pcSPS->getMinQTSize(I_SLICE)], "sps_log2_diff_max_bt_min_qt_intra_tile_group_luma");
        WRITE_UVLC(g_aucLog2[pcSPS->getMaxTTSizeI()] - g_aucLog2[pcSPS->getMinQTSize(I_SLICE)], "sps_log2_diff_max_tt_min_qt_intra_tile_group_luma");
    
      }
      if (pcSPS->getMaxBTDepth() != 0)
      {
    
        WRITE_UVLC(g_aucLog2[pcSPS->getMaxBTSize()] - g_aucLog2[pcSPS->getMinQTSize(B_SLICE)], "sps_log2_diff_max_bt_min_qt_inter_tile_group");
        WRITE_UVLC(g_aucLog2[pcSPS->getMaxTTSize()] - g_aucLog2[pcSPS->getMinQTSize(B_SLICE)], "sps_log2_diff_max_tt_min_qt_inter_tile_group");
    
      }
      if (pcSPS->getUseDualITree())
      {
    
        WRITE_UVLC(g_aucLog2[pcSPS->getMinQTSize(I_SLICE, CHANNEL_TYPE_CHROMA)] - pcSPS->getLog2MinCodingBlockSize(), "sps_log2_diff_min_qt_min_cb_intra_tile_group_chroma");
        WRITE_UVLC(pcSPS->getMaxBTDepthIChroma(), "sps_max_mtt_hierarchy_depth_intra_tile_group_chroma");
    
        if (pcSPS->getMaxBTDepthIChroma() != 0)
        {
    
          WRITE_UVLC(g_aucLog2[pcSPS->getMaxBTSizeIChroma()] - g_aucLog2[pcSPS->getMinQTSize(I_SLICE, CHANNEL_TYPE_CHROMA)], "sps_log2_diff_max_bt_min_qt_intra_tile_group_chroma");
          WRITE_UVLC(g_aucLog2[pcSPS->getMaxTTSizeIChroma()] - g_aucLog2[pcSPS->getMinQTSize(I_SLICE, CHANNEL_TYPE_CHROMA)], "sps_log2_diff_max_tt_min_qt_intra_tile_group_chroma");
    
    #if MAX_TB_SIZE_SIGNALLING
      // KJS: Not in syntax
      WRITE_UVLC( pcSPS->getLog2MaxTbSize() - 2,                                 "log2_max_luma_transform_block_size_minus2" );
    #endif
    
      WRITE_FLAG( pcSPS->getSAOEnabledFlag(),                                            "sps_sao_enabled_flag");
      WRITE_FLAG( pcSPS->getALFEnabledFlag(),                                            "sps_alf_enabled_flag" );
    
    
      WRITE_FLAG( pcSPS->getPCMEnabledFlag() ? 1 : 0,                                    "sps_pcm_enabled_flag");
    
      if( pcSPS->getPCMEnabledFlag() )
    
      {
        WRITE_CODE( pcSPS->getPCMBitDepth(CHANNEL_TYPE_LUMA) - 1, 4,                            "pcm_sample_bit_depth_luma_minus1" );
        WRITE_CODE( chromaEnabled ? (pcSPS->getPCMBitDepth(CHANNEL_TYPE_CHROMA) - 1) : 0, 4,    "pcm_sample_bit_depth_chroma_minus1" );
        WRITE_UVLC( pcSPS->getPCMLog2MinSize() - 3,                                      "log2_min_pcm_luma_coding_block_size_minus3" );
        WRITE_UVLC( pcSPS->getPCMLog2MaxSize() - pcSPS->getPCMLog2MinSize(),             "log2_diff_max_min_pcm_luma_coding_block_size" );
        WRITE_FLAG( pcSPS->getPCMFilterDisableFlag()?1 : 0,                              "pcm_loop_filter_disable_flag");
      }
    
    
      WRITE_FLAG( pcSPS->getWrapAroundEnabledFlag() ? 1 : 0,                              "sps_ref_wraparound_enabled_flag" );
      if( pcSPS->getWrapAroundEnabledFlag() )
    
        WRITE_UVLC( (pcSPS->getWrapAroundOffset()/(1 <<  pcSPS->getLog2MinCodingBlockSize()))-1,  "sps_ref_wraparound_offset_minus1" );
    
      WRITE_FLAG( pcSPS->getSPSTemporalMVPEnabledFlag()  ? 1 : 0,                        "sps_temporal_mvp_enabled_flag" );
    
      if ( pcSPS->getSPSTemporalMVPEnabledFlag() )
      {
        WRITE_FLAG( pcSPS->getSBTMVPEnabledFlag() ? 1 : 0,                               "sps_sbtmvp_enabled_flag");
      }
    
    
      WRITE_FLAG( pcSPS->getAMVREnabledFlag() ? 1 : 0,                                   "sps_amvr_enabled_flag" );
    
      WRITE_FLAG( pcSPS->getBDOFEnabledFlag() ? 1 : 0,                                   "sps_bdof_enabled_flag" );
    
      WRITE_FLAG( pcSPS->getAffineAmvrEnabledFlag() ? 1 : 0,                             "sps_affine_amvr_enabled_flag" );
    
    
      WRITE_FLAG( pcSPS->getUseDMVR() ? 1 : 0,                                            "sps_dmvr_enable_flag" );
    
      // KJS: sps_cclm_enabled_flag
      WRITE_FLAG( pcSPS->getUseLMChroma() ? 1 : 0,                                                 "lm_chroma_enabled_flag" );
      if ( pcSPS->getUseLMChroma() && pcSPS->getChromaFormatIdc() == CHROMA_420 )
    
        WRITE_FLAG( pcSPS->getCclmCollocatedChromaFlag() ? 1 : 0,                                  "sps_cclm_collocated_chroma_flag" );
      }
    
      WRITE_FLAG( pcSPS->getUseMTS() ? 1 : 0,                                                      "mts_enabled_flag" );
      if ( pcSPS->getUseMTS() )
      {
        WRITE_FLAG( pcSPS->getUseIntraMTS() ? 1 : 0,                                               "mts_intra_enabled_flag" );
        WRITE_FLAG( pcSPS->getUseInterMTS() ? 1 : 0,                                               "mts_inter_enabled_flag" );
    
      // KJS: sps_affine_enabled_flag
      WRITE_FLAG( pcSPS->getUseAffine() ? 1 : 0,                                                   "affine_flag" );
      if ( pcSPS->getUseAffine() )
      {
        WRITE_FLAG( pcSPS->getUseAffineType() ? 1 : 0,                                             "affine_type_flag" );
      }
      WRITE_FLAG( pcSPS->getUseGBi() ? 1 : 0,                                                      "gbi_flag" );
      WRITE_FLAG(pcSPS->getIBCFlag() ? 1 : 0,                                                      "ibc_flag");
    
      // KJS: sps_ciip_enabled_flag
      WRITE_FLAG( pcSPS->getUseMHIntra() ? 1 : 0,                                                  "mhintra_flag" );
    
      WRITE_FLAG( pcSPS->getUseTriangle() ? 1: 0,                                                  "triangle_flag" );
    
      // KJS: not in draft yet
      WRITE_FLAG( pcSPS->getDisFracMmvdEnabledFlag() ? 1 : 0,                            "sps_fracmmvd_disabled_flag" );
      // KJS: not in draft yet
    
      WRITE_FLAG( pcSPS->getUseSBT() ? 1 : 0,                                             "sbt_enable_flag");
      if( pcSPS->getUseSBT() )
      {
        WRITE_FLAG(pcSPS->getMaxSbtSize() == 64 ? 1 : 0,                                  "max_sbt_size_64_flag");
      }
    
      // KJS: not in draft yet
      WRITE_FLAG(pcSPS->getUseReshaper() ? 1 : 0, "sps_reshaper_enable_flag");
    
    #if LUMA_ADAPTIVE_DEBLOCKING_FILTER_QP_OFFSET
      WRITE_FLAG( pcSPS->getLadfEnabled() ? 1 : 0,                                                 "sps_ladf_enabled_flag" );
      if ( pcSPS->getLadfEnabled() )
      {
        WRITE_CODE( pcSPS->getLadfNumIntervals() - 2, 2,                                           "sps_num_ladf_intervals_minus2" );
        WRITE_SVLC( pcSPS->getLadfQpOffset( 0 ),                                                   "sps_ladf_lowest_interval_qp_offset");
        for ( int k = 1; k< pcSPS->getLadfNumIntervals(); k++ )
        {
          WRITE_SVLC( pcSPS->getLadfQpOffset( k ),                                                 "sps_ladf_qp_offset" );
          WRITE_UVLC( pcSPS->getLadfIntervalLowerBound( k ) - pcSPS->getLadfIntervalLowerBound( k - 1 ) - 1, "sps_ladf_delta_threshold_minus1" );
        }
      }
    #endif
    
    
      // KJS: reference picture sets to be replaced
    
      const RPSList* rpsList = pcSPS->getRPSList();
    
      WRITE_UVLC(rpsList->getNumberOfReferencePictureSets(), "num_short_term_ref_pic_sets" );
      for(int i=0; i < rpsList->getNumberOfReferencePictureSets(); i++)
      {
        const ReferencePictureSet*rps = rpsList->getReferencePictureSet(i);
        xCodeShortTermRefPicSet( rps,false, i);
      }
      WRITE_FLAG( pcSPS->getLongTermRefsPresent() ? 1 : 0,         "long_term_ref_pics_present_flag" );
      if (pcSPS->getLongTermRefsPresent())
      {
        WRITE_UVLC(pcSPS->getNumLongTermRefPicSPS(), "num_long_term_ref_pics_sps" );
        for (uint32_t k = 0; k < pcSPS->getNumLongTermRefPicSPS(); k++)
        {
          WRITE_CODE( pcSPS->getLtRefPicPocLsbSps(k), pcSPS->getBitsForPOC(), "lt_ref_pic_poc_lsb_sps");
          WRITE_FLAG( pcSPS->getUsedByCurrPicLtSPSFlag(k), "used_by_curr_pic_lt_sps_flag[i]");
        }
      }
    
    #if HEVC_USE_INTRA_SMOOTHING_T32 || HEVC_USE_INTRA_SMOOTHING_T64
      WRITE_FLAG( pcSPS->getUseStrongIntraSmoothing(),             "strong_intra_smoothing_enable_flag" );
    
    #endif
    
    
      // KJS: remove scaling lists?
    #if HEVC_USE_SCALING_LISTS
      WRITE_FLAG( pcSPS->getScalingListFlag() ? 1 : 0,                                   "scaling_list_enabled_flag" );
      if(pcSPS->getScalingListFlag())
      {
        WRITE_FLAG( pcSPS->getScalingListPresentFlag() ? 1 : 0,                          "sps_scaling_list_data_present_flag" );
        if(pcSPS->getScalingListPresentFlag())
        {
          codeScalingList( pcSPS->getScalingList() );
        }
      }
    #endif
    
      // KJS: no VUI defined yet
    
      WRITE_FLAG( pcSPS->getVuiParametersPresentFlag(),            "vui_parameters_present_flag" );
      if (pcSPS->getVuiParametersPresentFlag())
      {
        codeVUI(pcSPS->getVuiParameters(), pcSPS);
      }
    
      bool sps_extension_present_flag=false;
      bool sps_extension_flags[NUM_SPS_EXTENSION_FLAGS]={false};
    
      sps_extension_flags[SPS_EXT__REXT] = pcSPS->getSpsRangeExtension().settingsDifferFromDefaults();
    
      // Other SPS extension flags checked here.
    
      for(int i=0; i<NUM_SPS_EXTENSION_FLAGS; i++)
      {
        sps_extension_present_flag|=sps_extension_flags[i];
      }
    
      WRITE_FLAG( (sps_extension_present_flag?1:0), "sps_extension_present_flag" );
    
      if (sps_extension_present_flag)
      {
    #if ENABLE_TRACING /*|| RExt__DECODER_DEBUG_BIT_STATISTICS*/
        static const char *syntaxStrings[]={ "sps_range_extension_flag",
          "sps_multilayer_extension_flag",
          "sps_extension_6bits[0]",
          "sps_extension_6bits[1]",
          "sps_extension_6bits[2]",
          "sps_extension_6bits[3]",
          "sps_extension_6bits[4]",
          "sps_extension_6bits[5]" };
    #endif
    
        for(int i=0; i<NUM_SPS_EXTENSION_FLAGS; i++)
        {
          WRITE_FLAG( sps_extension_flags[i]?1:0, syntaxStrings[i] );
        }
    
        for(int i=0; i<NUM_SPS_EXTENSION_FLAGS; i++) // loop used so that the order is determined by the enum.
        {
          if (sps_extension_flags[i])
          {
            switch (SPSExtensionFlagIndex(i))
            {
            case SPS_EXT__REXT:
            {
              const SPSRExt &spsRangeExtension=pcSPS->getSpsRangeExtension();
    
              WRITE_FLAG( (spsRangeExtension.getTransformSkipRotationEnabledFlag() ? 1 : 0),      "transform_skip_rotation_enabled_flag");
              WRITE_FLAG( (spsRangeExtension.getTransformSkipContextEnabledFlag() ? 1 : 0),       "transform_skip_context_enabled_flag");
              WRITE_FLAG( (spsRangeExtension.getRdpcmEnabledFlag(RDPCM_SIGNAL_IMPLICIT) ? 1 : 0), "implicit_rdpcm_enabled_flag" );
              WRITE_FLAG( (spsRangeExtension.getRdpcmEnabledFlag(RDPCM_SIGNAL_EXPLICIT) ? 1 : 0), "explicit_rdpcm_enabled_flag" );
              WRITE_FLAG( (spsRangeExtension.getExtendedPrecisionProcessingFlag() ? 1 : 0),       "extended_precision_processing_flag" );
              WRITE_FLAG( (spsRangeExtension.getIntraSmoothingDisabledFlag() ? 1 : 0),            "intra_smoothing_disabled_flag" );
              WRITE_FLAG( (spsRangeExtension.getHighPrecisionOffsetsEnabledFlag() ? 1 : 0),       "high_precision_offsets_enabled_flag" );
              WRITE_FLAG( (spsRangeExtension.getPersistentRiceAdaptationEnabledFlag() ? 1 : 0),   "persistent_rice_adaptation_enabled_flag" );
              WRITE_FLAG( (spsRangeExtension.getCabacBypassAlignmentEnabledFlag() ? 1 : 0),       "cabac_bypass_alignment_enabled_flag" );
              break;
            }
            default:
              CHECK(sps_extension_flags[i]!=false, "Unknown PPS extension signalled"); // Should never get here with an active SPS extension flag.
              break;
            }
          }
        }
      }
      xWriteRbspTrailingBits();
    }
    
    #if HEVC_VPS
    void HLSWriter::codeVPS( const VPS* pcVPS )
    {
    #if ENABLE_TRACING
      xTraceVPSHeader();
    #endif
      WRITE_CODE( pcVPS->getVPSId(),                    4,        "vps_video_parameter_set_id" );
      WRITE_FLAG(                                       1,        "vps_base_layer_internal_flag" );
      WRITE_FLAG(                                       1,        "vps_base_layer_available_flag" );
      WRITE_CODE( 0,                                    6,        "vps_max_layers_minus1" );
      WRITE_CODE( pcVPS->getMaxTLayers() - 1,           3,        "vps_max_sub_layers_minus1" );
      WRITE_FLAG( pcVPS->getTemporalNestingFlag(),                "vps_temporal_id_nesting_flag" );
      CHECK(pcVPS->getMaxTLayers()<=1&&!pcVPS->getTemporalNestingFlag(), "Invalud parameters");
      WRITE_CODE( 0xffff,                              16,        "vps_reserved_0xffff_16bits" );
      codePTL( pcVPS->getPTL(), true, pcVPS->getMaxTLayers() - 1 );
      const bool subLayerOrderingInfoPresentFlag = 1;
      WRITE_FLAG(subLayerOrderingInfoPresentFlag,              "vps_sub_layer_ordering_info_present_flag");
      for(uint32_t i=0; i <= pcVPS->getMaxTLayers()-1; i++)
      {
        WRITE_UVLC( pcVPS->getMaxDecPicBuffering(i) - 1,       "vps_max_dec_pic_buffering_minus1[i]" );
        WRITE_UVLC( pcVPS->getNumReorderPics(i),               "vps_max_num_reorder_pics[i]" );
        WRITE_UVLC( pcVPS->getMaxLatencyIncrease(i),           "vps_max_latency_increase_plus1[i]" );
        if (!subLayerOrderingInfoPresentFlag)
        {
          break;
        }
      }
    
      CHECK( pcVPS->getNumHrdParameters() > MAX_VPS_NUM_HRD_PARAMETERS, "Too many HRD parameters" );
      CHECK( pcVPS->getMaxNuhReservedZeroLayerId() >= MAX_VPS_NUH_RESERVED_ZERO_LAYER_ID_PLUS1, "Invalid parameters read" );
      WRITE_CODE( pcVPS->getMaxNuhReservedZeroLayerId(), 6,     "vps_max_layer_id" );
      WRITE_UVLC( pcVPS->getMaxOpSets() - 1,                    "vps_num_layer_sets_minus1" );
      for( uint32_t opsIdx = 1; opsIdx <= ( pcVPS->getMaxOpSets() - 1 ); opsIdx ++ )
      {
        // Operation point set
        for( uint32_t i = 0; i <= pcVPS->getMaxNuhReservedZeroLayerId(); i ++ )
        {
          // Only applicable for version 1
          // pcVPS->setLayerIdIncludedFlag( true, opsIdx, i );
          WRITE_FLAG( pcVPS->getLayerIdIncludedFlag( opsIdx, i ) ? 1 : 0, "layer_id_included_flag[opsIdx][i]" );
        }
      }
      const TimingInfo *timingInfo = pcVPS->getTimingInfo();
      WRITE_FLAG(timingInfo->getTimingInfoPresentFlag(),          "vps_timing_info_present_flag");
      if(timingInfo->getTimingInfoPresentFlag())
      {
        WRITE_CODE(timingInfo->getNumUnitsInTick(), 32,           "vps_num_units_in_tick");
        WRITE_CODE(timingInfo->getTimeScale(),      32,           "vps_time_scale");
        WRITE_FLAG(timingInfo->getPocProportionalToTimingFlag(),  "vps_poc_proportional_to_timing_flag");
        if(timingInfo->getPocProportionalToTimingFlag())
        {
          WRITE_UVLC(timingInfo->getNumTicksPocDiffOneMinus1(),   "vps_num_ticks_poc_diff_one_minus1");
        }
        WRITE_UVLC( pcVPS->getNumHrdParameters(),                 "vps_num_hrd_parameters" );
    
        if( pcVPS->getNumHrdParameters() > 0 )
        {
          for( uint32_t i = 0; i < pcVPS->getNumHrdParameters(); i ++ )
          {
            // Only applicable for version 1
            WRITE_UVLC( pcVPS->getHrdOpSetIdx( i ),                "hrd_layer_set_idx" );
            if( i > 0 )
            {
              WRITE_FLAG( pcVPS->getCprmsPresentFlag( i ) ? 1 : 0, "cprms_present_flag[i]" );
            }
            codeHrdParameters(pcVPS->getHrdParameters(i), pcVPS->getCprmsPresentFlag( i ), pcVPS->getMaxTLayers() - 1);
          }
        }
      }
      WRITE_FLAG( 0,                     "vps_extension_flag" );
    
      //future extensions here..
      xWriteRbspTrailingBits();
    }
    #endif
    
    void HLSWriter::codeSliceHeader         ( Slice* pcSlice )
    {
    #if ENABLE_TRACING
      xTraceSliceHeader ();
    #endif
    
      CodingStructure& cs = *pcSlice->getPic()->cs;
      const ChromaFormat format                = pcSlice->getSPS()->getChromaFormatIdc();
      const uint32_t         numberValidComponents = getNumberValidComponents(format);
      const bool         chromaEnabled         = isChromaEnabled(format);