/* ----------------------------------------------------------------------------- The copyright in this software is being made available under the Clear BSD License, included below. No patent rights, trademark rights and/or other Intellectual Property Rights other than the copyrights concerning the Software are granted under this license. The Clear BSD License Copyright (c) 2018-2023, Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. & The VVdeC Authors. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted (subject to the limitations in the disclaimer below) 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 copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY THIS LICENSE. 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 VLCWReader.cpp * \brief Reader for high level syntax */ //! \ingroup DecoderLib //! \{ #include "VLCReader.h" #include "CommonLib/CommonDef.h" #include "CommonLib/dtrace_next.h" #include "CommonLib/AdaptiveLoopFilter.h" #include "CommonLib/ParameterSetManager.h" namespace vvdec { #if ENABLE_TRACING void VLCReader::xReadCodeTr( uint32_t length, uint32_t& rValue, const char *pSymbolName ) { xReadCode( length, rValue ); if( length < 10 ) { DTRACE( g_trace_ctx, D_HEADER, "%-50s u(%d) : %u\n", pSymbolName, length, rValue ); } else { DTRACE( g_trace_ctx, D_HEADER, "%-50s u(%d) : %u\n", pSymbolName, length, rValue ); } } void VLCReader::xReadUvlcTr( uint32_t& rValue, const char *pSymbolName ) { xReadUvlc( rValue ); DTRACE( g_trace_ctx, D_HEADER, "%-50s ue(v) : %u\n", pSymbolName, rValue ); } void VLCReader::xReadSvlcTr( int& rValue, const char *pSymbolName ) { xReadSvlc( rValue ); DTRACE( g_trace_ctx, D_HEADER, "%-50s se(v) : %d\n", pSymbolName, rValue ); } void VLCReader::xReadFlagTr( uint32_t& rValue, const char *pSymbolName ) { xReadFlag( rValue ); DTRACE( g_trace_ctx, D_HEADER, "%-50s u(1) : %d\n", pSymbolName, rValue ); } void xTraceFillerData() { DTRACE( g_trace_ctx, D_HEADER, "=========== Filler Data ===========\n"); } #endif #if ENABLE_TRACING void VLCReader::xReadSCode( uint32_t length, int& value, const char *pSymbolName ) #else void VLCReader::xReadSCode( uint32_t length, int& value ) #endif { uint32_t val; CHECK_RECOVERABLE( length == 0 || length > 31, "wrong" ); m_pcBitstream->read( length, val ); value = length >= 32 ? int( val ) : ( ( -int( val & ( uint32_t( 1 ) << ( length - 1 ) ) ) ) | int( val ) ); #if ENABLE_TRACING if( length < 10 ) { DTRACE( g_trace_ctx, D_HEADER, "%-50s i(%d) : %d\n", pSymbolName, length, value ); } else { DTRACE( g_trace_ctx, D_HEADER, "%-50s i(%d) : %d\n", pSymbolName, length, value ); } #endif } // ==================================================================================================================== // Protected member functions // ==================================================================================================================== void VLCReader::xReadCode( uint32_t uiLength, uint32_t& ruiCode ) { CHECK_RECOVERABLE( uiLength == 0, "Reading a code of lenght '0'" ); m_pcBitstream->read( uiLength, ruiCode ); } void VLCReader::xReadUvlc( uint32_t& ruiVal ) { uint32_t uiVal = 0; uint32_t uiCode = 0; uint32_t uiLength; m_pcBitstream->read( 1, uiCode ); if( 0 == uiCode ) { uiLength = 0; while( ! ( uiCode & 1 ) ) { m_pcBitstream->read( 1, uiCode ); uiLength++; } m_pcBitstream->read( uiLength, uiVal ); uiVal += ( 1 << uiLength ) - 1; } ruiVal = uiVal; } void VLCReader::xReadSvlc( int& riVal ) { uint32_t uiBits = 0; m_pcBitstream->read( 1, uiBits ); if( 0 == uiBits ) { uint32_t uiLength = 0; while( ! ( uiBits & 1 ) ) { m_pcBitstream->read( 1, uiBits ); uiLength++; } m_pcBitstream->read( uiLength, uiBits ); uiBits += ( 1 << uiLength ); riVal = ( uiBits & 1 ) ? -(int)( uiBits>>1 ) : (int)( uiBits>>1 ); } else { riVal = 0; } } void VLCReader::xReadFlag( uint32_t& ruiCode ) { m_pcBitstream->read( 1, ruiCode ); } void VLCReader::xReadRbspTrailingBits() { uint32_t bit; READ_FLAG( bit, "rbsp_stop_one_bit" ); CHECK_RECOVERABLE( bit!=1, "Trailing bit not '1'" ); int cnt = 0; while( m_pcBitstream->getNumBitsUntilByteAligned() ) { READ_FLAG( bit, "rbsp_alignment_zero_bit" ); CHECK_RECOVERABLE( bit!=0, "Alignment bit is not '0'" ); cnt++; } CHECK_RECOVERABLE( cnt >= 8, "Read more than '8' trailing bits" ); } void AUDReader::parseAccessUnitDelimiter( InputBitstream* bs, uint32_t &picType ) { setBitstream( bs ); #if ENABLE_TRACING xTraceAccessUnitDelimiter(); #endif uint32_t audIrapOrGdrAuFlag; READ_FLAG( audIrapOrGdrAuFlag, "aud_irap_or_gdr_au_flag" ); //just a parsing fix, but not used TODO: check m_audIrapOrGdrAuFlag in VTM-10.0 reference software READ_CODE( 3, picType, "aud_pic_type" ); xReadRbspTrailingBits(); } void FDReader::parseFillerData( InputBitstream* bs, uint32_t &fdSize ) { setBitstream( bs ); #if ENABLE_TRACING xTraceFillerData(); #endif uint32_t ffByte; fdSize = 0; while( m_pcBitstream->getNumBitsLeft() > 8 ) { READ_CODE( 8, ffByte, "fd_ff_byte" ); CHECK_RECOVERABLE( ffByte != 0xff, "Invalid fillter data not '0xff'" ); fdSize++; } xReadRbspTrailingBits(); } // ==================================================================================================================== // Public member functions // ==================================================================================================================== void HLSyntaxReader::copyRefPicList( const SPS* sps, const ReferencePictureList* source_rpl, ReferencePictureList* dest_rp ) { memcpy( dest_rp, source_rpl, sizeof( ReferencePictureList ) ); if( !sps->getLongTermRefsPresent() ) { dest_rp->setNumberOfLongtermPictures( 0 ); } } void HLSyntaxReader::parseRefPicList( ReferencePictureList* rpl, int rplIdx, const SPS* sps ) { uint32_t code; READ_UVLC( code, "num_ref_entries[ listIdx ][ rplsIdx ]" ); uint32_t numRefPic = code; uint32_t numStrp = 0; uint32_t numLtrp = 0; uint32_t numIlrp = 0; if( sps->getLongTermRefsPresent() && numRefPic > 0 && rplIdx != -1 ) { READ_FLAG( code, "ltrp_in_header_flag[ listIdx ][ rplsIdx ]" ); rpl->setLtrpInSliceHeaderFlag( code ); } else if( sps->getLongTermRefsPresent() ) { rpl->setLtrpInSliceHeaderFlag( 1 ); } int prevDelta = MAX_INT; int deltaValue = 0; bool firstSTRP = true; rpl->setInterLayerPresentFlag( sps->getInterLayerPresentFlag() ); for( int ii = 0; ii < numRefPic; ii++ ) { uint32_t isInterLayerRefPic = 0; if( rpl->getInterLayerPresentFlag() ) { READ_FLAG( isInterLayerRefPic, "inter_layer_ref_pic_flag[ listIdx ][ rplsIdx ][ i ]" ); if( isInterLayerRefPic ) { READ_UVLC( code, "ilrp_idx[ listIdx ][ rplsIdx ][ i ]" ); rpl->setRefPicIdentifier( ii, 0, true, true, code ); numIlrp++; } } if( !isInterLayerRefPic ) { bool isLongTerm = false; if( sps->getLongTermRefsPresent() ) { READ_FLAG( code, "st_ref_pic_flag[ listIdx ][ rplsIdx ][ i ]" ); isLongTerm = ( code == 1 ) ? false : true; } if( !isLongTerm ) { READ_UVLC( code, "abs_delta_poc_st[ listIdx ][ rplsIdx ][ i ]" ); if( ( !sps->getUseWP() && !sps->getUseWPBiPred() ) || ii == 0 ) { code++; } int readValue = code; if( readValue > 0 ) { READ_FLAG( code, "strp_entry_sign_flag[ listIdx ][ rplsIdx ][ i ]" ); if( code ) { readValue = -readValue; } } if( firstSTRP ) { firstSTRP = false; prevDelta = deltaValue = readValue; } else { deltaValue = prevDelta + readValue; prevDelta = deltaValue; } rpl->setRefPicIdentifier( ii, deltaValue, isLongTerm, false, 0 ); numStrp++; } else { if( !rpl->getLtrpInSliceHeaderFlag() ) { READ_CODE( sps->getBitsForPOC(), code, "rpls_poc_lsb_lt[listIdx][rplsIdx][i]" ); } rpl->setRefPicIdentifier( ii, code, isLongTerm, false, 0 ); numLtrp++; } } } rpl->setNumberOfShorttermPictures( numStrp ); rpl->setNumberOfLongtermPictures( numLtrp ); rpl->setNumberOfInterLayerPictures( numIlrp ); } void HLSyntaxReader::parsePPS( PPS* pcPPS, const ParameterSetManager *parameterSetManager ) { #if ENABLE_TRACING xTracePPSHeader (); #endif uint32_t uiCode; int iCode; READ_CODE( 6, uiCode, "pps_pic_parameter_set_id" ); pcPPS->setPPSId( uiCode ); CHECK_RECOVERABLE( uiCode > 63, "PPS id exceeds boundary (63)" ); READ_CODE( 4, uiCode, "pps_seq_parameter_set_id" ); pcPPS->setSPSId( uiCode ); const SPS* pcSPS = parameterSetManager->getSPS( pcPPS->getSPSId() ); CHECK_RECOVERABLE( !pcSPS, "SPS with id " << pcPPS->getSPSId() << " missing." ); READ_FLAG( uiCode, "pps_mixed_nalu_types_in_pic_flag" ); pcPPS->setMixedNaluTypesInPicFlag( uiCode == 1 ); READ_UVLC( uiCode, "pps_pic_width_in_luma_samples" ); pcPPS->setPicWidthInLumaSamples( uiCode ); READ_UVLC( uiCode, "pps_pic_height_in_luma_samples" ); pcPPS->setPicHeightInLumaSamples( uiCode ); READ_FLAG(uiCode, "pps_conformance_window_flag"); pcPPS->setConformanceWindowPresentFlag( uiCode ); if( uiCode != 0 ) { Window &conf = pcPPS->getConformanceWindow(); READ_UVLC( uiCode, "pps_conf_win_left_offset" ); conf.setWindowLeftOffset( uiCode ); READ_UVLC( uiCode, "pps_conf_win_right_offset" ); conf.setWindowRightOffset( uiCode ); READ_UVLC( uiCode, "pps_conf_win_top_offset" ); conf.setWindowTopOffset( uiCode ); READ_UVLC( uiCode, "pps_conf_win_bottom_offset" ); conf.setWindowBottomOffset( uiCode ); } READ_FLAG( uiCode, "pps_scaling_window_explicit_signalling_flag" ); if( uiCode != 0 ) { Window &scalingWindow = pcPPS->getScalingWindow(); READ_SVLC( iCode, "pps_scaling_win_left_offset" ); scalingWindow.setWindowLeftOffset( iCode ); READ_SVLC( iCode, "pps_scaling_win_right_offset" ); scalingWindow.setWindowRightOffset( iCode ); READ_SVLC( iCode, "pps_scaling_win_top_offset" ); scalingWindow.setWindowTopOffset( iCode ); READ_SVLC( iCode, "pps_scaling_win_bottom_offset" ); scalingWindow.setWindowBottomOffset( iCode ); } else { pcPPS->setScalingWindow( pcPPS->getConformanceWindow() ); } READ_FLAG( uiCode, "pps_output_flag_present_flag" ); pcPPS->setOutputFlagPresentFlag( uiCode==1 ); READ_FLAG( uiCode, "pps_no_pic_partition_flag"); pcPPS->setNoPicPartitionFlag( uiCode == 1 ); READ_FLAG( uiCode, "pps_subpic_id_mapping_present_flag" ); pcPPS->setSubPicIdMappingInPpsFlag( uiCode != 0 ); if( pcPPS->getSubPicIdMappingInPpsFlag() ) { if( !pcPPS->getNoPicPartitionFlag() ) { READ_UVLC( uiCode, "pps_num_subpics_minus1" ); pcPPS->setNumSubPics( uiCode + 1 ); } else { pcPPS->setNumSubPics( 1 ); } CHECK_RECOVERABLE( uiCode > MAX_NUM_SUB_PICS-1, "Number of sub-pictures exceeds limit" ); READ_UVLC( uiCode, "pps_subpic_id_len_minus1" ); pcPPS->setSubPicIdLen( uiCode + 1 ); CHECK_RECOVERABLE( uiCode > 15, "Invalid pps_subpic_id_len_minus1 signalled"); CHECK_RECOVERABLE( ( 1 << pcPPS->getSubPicIdLen() ) < pcPPS->getNumSubPics(), "pps_subpic_id_len exceeds valid range" ); for( int picIdx = 0; picIdx < pcPPS->getNumSubPics( ); picIdx++ ) { READ_CODE( pcPPS->getSubPicIdLen(), uiCode, "pps_subpic_id[i]" ); pcPPS->setSubPicId( picIdx, uiCode ); } } else { for( int picIdx = 0; picIdx < MAX_NUM_SUB_PICS; picIdx++ ) { pcPPS->setSubPicId( picIdx, picIdx ); } } if( !pcPPS->getNoPicPartitionFlag() ) { int colIdx, rowIdx; pcPPS->resetTileSliceInfo(); //TODO: tbd // CTU size - required to match size in SPS READ_CODE( 2, uiCode, "pps_log2_ctu_size_minus5"); pcPPS->setLog2CtuSize( uiCode + 5 ); CHECK_RECOVERABLE( uiCode > 2, "pps_log2_ctu_size_minus5 must be less than or equal to 2" ); // number of explicit tile columns/rows READ_UVLC( uiCode, "pps_num_exp_tile_columns_minus1" ); pcPPS->setNumExpTileColumns( uiCode + 1 ); READ_UVLC( uiCode, "pps_num_exp_tile_rows_minus1" ); pcPPS->setNumExpTileRows( uiCode + 1 ); CHECK_RECOVERABLE( pcPPS->getNumExpTileColumns() > MAX_TILE_COLS, "Number of explicit tile columns exceeds valid range" ); // tile sizes for( colIdx = 0; colIdx < pcPPS->getNumExpTileColumns(); colIdx++ ) { READ_UVLC( uiCode, "pps_tile_column_width_minus1[i]" ); pcPPS->addTileColumnWidth( uiCode + 1 ); CHECK_RECOVERABLE( uiCode > ( pcPPS->getPicWidthInCtu() - 1 ), "The value of pps_tile_column_width_minus1[i] shall be in the range of 0 to PicWidthInCtbY-1, inclusive" ); } for( rowIdx = 0; rowIdx < pcPPS->getNumExpTileRows(); rowIdx++ ) { READ_UVLC( uiCode, "pps_tile_row_height_minus1[i]" ); pcPPS->addTileRowHeight( uiCode + 1 ); CHECK_RECOVERABLE( uiCode > ( pcPPS->getPicHeightInCtu() - 1 ), "The value of pps_tile_row_height_minus shall be in the range of 0 to PicHeightInCtbY-1, inclusive" ); } pcPPS->initTiles(); //TODO: tbd // rectangular slice signalling if( pcPPS->getNumTiles() > 1 ) { READ_CODE( 1, uiCode, "pps_loop_filter_across_tiles_enabled_flag" ); pcPPS->setLoopFilterAcrossTilesEnabledFlag( uiCode == 1 ); READ_CODE( 1, uiCode, "pps_rect_slice_flag" ); pcPPS->setRectSliceFlag( uiCode == 1 ) ; } else { pcPPS->setLoopFilterAcrossTilesEnabledFlag( false ); pcPPS->setRectSliceFlag( true ); } if( pcPPS->getRectSliceFlag() ) { READ_FLAG( uiCode, "pps_single_slice_per_subpic_flag" ); pcPPS->setSingleSlicePerSubPicFlag( uiCode == 1 ); } if( pcPPS->getRectSliceFlag() && !pcPPS->getSingleSlicePerSubPicFlag() ) { int32_t tileIdx = 0; READ_UVLC( uiCode, "pps_num_slices_in_pic_minus1" ); pcPPS->setNumSlicesInPic( uiCode + 1 ); CHECK_RECOVERABLE( pcPPS->getNumSlicesInPic() > MAX_SLICES, "Number of slices in picture exceeds valid range"); if( ( pcPPS->getNumSlicesInPic() - 1 ) > 1 ) { READ_CODE( 1, uiCode, "pps_tile_idx_delta_present_flag" ); pcPPS->setTileIdxDeltaPresentFlag( uiCode == 1 ) ; } else { pcPPS->setTileIdxDeltaPresentFlag( 0 ); } pcPPS->initRectSlices(); //TODO: tbd // read rectangular slice parameters for( int i = 0; i < pcPPS->getNumSlicesInPic()-1; i++ ) { pcPPS->setSliceTileIdx( i, tileIdx ); // complete tiles within a single slice if( ( tileIdx % pcPPS->getNumTileColumns() ) != pcPPS->getNumTileColumns() - 1 ) { READ_UVLC( uiCode, "pps_slice_width_in_tiles_minus1[i]" ); pcPPS->setSliceWidthInTiles ( i, uiCode + 1 ); } else { pcPPS->setSliceWidthInTiles( i, 1 ); } if( tileIdx / pcPPS->getNumTileColumns() != pcPPS->getNumTileRows() - 1 && ( pcPPS->getTileIdxDeltaPresentFlag() || tileIdx % pcPPS->getNumTileColumns() == 0 ) ) { READ_UVLC( uiCode, "pps_slice_height_in_tiles_minus1[i]" ); pcPPS->setSliceHeightInTiles( i, uiCode + 1 ); } else { if( ( tileIdx / pcPPS->getNumTileColumns() ) == pcPPS->getNumTileRows() - 1 ) { pcPPS->setSliceHeightInTiles( i, 1 ); } else { pcPPS->setSliceHeightInTiles( i, pcPPS->getSliceHeightInTiles( i - 1 ) ); } } // multiple slices within a single tile special case if( pcPPS->getSliceWidthInTiles(i) == 1 && pcPPS->getSliceHeightInTiles(i) == 1 ) { if( pcPPS->getTileRowHeight(tileIdx / pcPPS->getNumTileColumns()) > 1 ) { READ_UVLC(uiCode, "pps_num_exp_slices_in_tile[i]"); if( uiCode == 0 ) { pcPPS->setNumSlicesInTile( i, 1 ); pcPPS->setSliceHeightInCtu( i, pcPPS->getTileRowHeight( tileIdx / pcPPS->getNumTileColumns() ) ); } else { uint32_t numExpSliceInTile = uiCode; uint32_t remTileRowHeight = pcPPS->getTileRowHeight( tileIdx / pcPPS->getNumTileColumns() ); int j = 0; for( ; j < numExpSliceInTile; j++ ) { READ_UVLC( uiCode, "pps_exp_slice_height_in_ctus_minus1[i]" ); pcPPS->setSliceHeightInCtu( i + j, uiCode + 1 ); remTileRowHeight -= ( uiCode + 1 ); } uint32_t uniformSliceHeight = uiCode + 1; while( remTileRowHeight >= uniformSliceHeight ) { pcPPS->setSliceHeightInCtu( i + j, uniformSliceHeight ); remTileRowHeight -= uniformSliceHeight; j++; } if( remTileRowHeight > 0 ) { pcPPS->setSliceHeightInCtu( i + j, remTileRowHeight ); j++; } for( int k = 0; k < j; k++ ) { pcPPS->setNumSlicesInTile( i + k, j ); pcPPS->setSliceWidthInTiles( i + k, 1 ); pcPPS->setSliceHeightInTiles( i + k, 1 ); pcPPS->setSliceTileIdx( i + k, tileIdx ); } i += (j - 1); } } else { pcPPS->setNumSlicesInTile( i, 1 ); pcPPS->setSliceHeightInCtu( i, pcPPS->getTileRowHeight( tileIdx / pcPPS->getNumTileColumns() ) ); } } // tile index offset to start of next slice if( i < pcPPS->getNumSlicesInPic()-1 ) { if( pcPPS->getTileIdxDeltaPresentFlag() ) { int32_t tileIdxDelta; READ_SVLC( tileIdxDelta, "pps_tile_idx_delta_val[i]" ); tileIdx += tileIdxDelta; CHECK_RECOVERABLE( tileIdx < 0 || tileIdx >= pcPPS->getNumTiles(), "Invalid tile_idx_delta." ); } else { tileIdx += pcPPS->getSliceWidthInTiles( i ); if( tileIdx % pcPPS->getNumTileColumns() == 0) { tileIdx += (pcPPS->getSliceHeightInTiles( i ) - 1) * pcPPS->getNumTileColumns(); } } } } pcPPS->setSliceTileIdx(pcPPS->getNumSlicesInPic()-1, tileIdx ); // initialize mapping between rectangular slices and CTUs // pcPPS->initRectSliceMap(); //TODO: tbd } if (pcPPS->getRectSliceFlag() == 0 || pcPPS->getSingleSlicePerSubPicFlag() || pcPPS->getNumSlicesInPic() > 1) { READ_CODE( 1, uiCode, "pps_loop_filter_across_slices_enabled_flag"); pcPPS->setLoopFilterAcrossSlicesEnabledFlag( uiCode == 1 ); } else { pcPPS->setLoopFilterAcrossSlicesEnabledFlag( false ); } } else { pcPPS->setSingleSlicePerSubPicFlag(1); } READ_FLAG( uiCode, "pps_cabac_init_present_flag" ); pcPPS->setCabacInitPresentFlag( uiCode ? true : false ); READ_UVLC( uiCode, "pps_num_ref_idx_default_active_minus1[0]" ); pcPPS->setNumRefIdxL0DefaultActive( uiCode + 1 ); CHECK_RECOVERABLE( uiCode > 14, "Invalid code read" ); READ_UVLC( uiCode, "pps_num_ref_idx_default_active_minus1[1]" ); pcPPS->setNumRefIdxL1DefaultActive( uiCode + 1 ); CHECK_RECOVERABLE( uiCode > 14, "Invalid code read" ); READ_FLAG( uiCode, "pps_rpl1_idx_present_flag" ); pcPPS->setRpl1IdxPresentFlag( uiCode ); READ_FLAG( uiCode, "pps_weighted_pred_flag" ); pcPPS->setUseWP( uiCode == 1 ); READ_FLAG( uiCode, "pps_weighted_bipred_flag" ); pcPPS->setWPBiPred( uiCode == 1 ); READ_FLAG( uiCode, "pps_ref_wraparound_enabled_flag" ); pcPPS->setUseWrapAround( uiCode ? true : false ); if( pcPPS->getUseWrapAround() ) { READ_UVLC( uiCode, "pps_pic_width_minus_wraparound_offset" ); pcPPS->setPicWidthMinusWrapAroundOffset( uiCode ); } else { pcPPS->setPicWidthMinusWrapAroundOffset( 0 ); } READ_SVLC( iCode, "pps_init_qp_minus26" ); pcPPS->setPicInitQPMinus26( iCode ); READ_FLAG( uiCode, "pps_cu_qp_delta_enabled_flag" ); pcPPS->setUseDQP( uiCode ? true : false ); READ_FLAG( uiCode, "pps_chroma_tool_offsets_present_flag" ); pcPPS->setPPSChromaToolFlag( uiCode ? true : false ); if( pcPPS->getPPSChromaToolFlag() ) { READ_SVLC( iCode, "pps_cb_qp_offset" ); pcPPS->setQpOffset( COMPONENT_Cb, iCode ); CHECK_RECOVERABLE( pcPPS->getQpOffset( COMPONENT_Cb ) < -12, "Invalid Cb QP offset" ); CHECK_RECOVERABLE( pcPPS->getQpOffset( COMPONENT_Cb ) > 12, "Invalid Cb QP offset" ); READ_SVLC( iCode, "pps_cr_qp_offset" ); pcPPS->setQpOffset( COMPONENT_Cr, iCode ); CHECK_RECOVERABLE( pcPPS->getQpOffset( COMPONENT_Cr ) < -12, "Invalid Cr QP offset" ); CHECK_RECOVERABLE( pcPPS->getQpOffset( COMPONENT_Cr ) > 12, "Invalid Cr QP offset" ); READ_FLAG( uiCode, "pps_joint_cbcr_qp_offset_present_flag" ); pcPPS->setJointCbCrQpOffsetPresentFlag( uiCode ? true : false ); if( pcPPS->getJointCbCrQpOffsetPresentFlag() ) { READ_SVLC( iCode, "pps_joint_cbcr_qp_offset_value" ); } else { iCode = 0; } pcPPS->setQpOffset( JOINT_CbCr, iCode ); CHECK_RECOVERABLE( pcPPS->getQpOffset( JOINT_CbCr ) < -12, "Invalid CbCr QP offset" ); CHECK_RECOVERABLE( pcPPS->getQpOffset( JOINT_CbCr ) > 12, "Invalid CbCr QP offset" ); CHECK_RECOVERABLE( MAX_NUM_COMPONENT > 3, "Invalid maximal number of components" ); READ_FLAG( uiCode, "pps_slice_chroma_qp_offsets_present_flag" ); pcPPS->setSliceChromaQpFlag( uiCode ? true : false ); READ_FLAG( uiCode, "pps_cu_chroma_qp_offset_list_enabled_flag" ); if( uiCode == 0 ) { pcPPS->clearChromaQpOffsetList(); } else { uint32_t tableSizeMinus1 = 0; READ_UVLC( tableSizeMinus1, "pps_chroma_qp_offset_list_len_minus1" ); CHECK_RECOVERABLE( tableSizeMinus1 >= MAX_QP_OFFSET_LIST_SIZE, "Table size exceeds maximum" ); for( int cuChromaQpOffsetIdx = 0; cuChromaQpOffsetIdx <= (tableSizeMinus1); cuChromaQpOffsetIdx++ ) { int cbOffset; int crOffset; int jointCbCrOffset; READ_SVLC( cbOffset, "pps_cb_qp_offset_list[i] "); CHECK_RECOVERABLE( cbOffset < -12 || cbOffset > 12, "Invalid chroma QP offset" ); READ_SVLC( crOffset, "pps_cr_qp_offset_list[i]" ); CHECK_RECOVERABLE( crOffset < -12 || crOffset > 12, "Invalid chroma QP offset" ); if( pcPPS->getJointCbCrQpOffsetPresentFlag() ) { READ_SVLC( jointCbCrOffset, "pps_joint_cbcr_qp_offset_list[i]" ); } else { jointCbCrOffset = 0; } CHECK_RECOVERABLE( jointCbCrOffset < -12 || jointCbCrOffset > 12, "Invalid chroma QP offset" ); // table uses +1 for index (see comment inside the function) pcPPS->setChromaQpOffsetListEntry( cuChromaQpOffsetIdx + 1, cbOffset, crOffset, jointCbCrOffset ); } CHECK_RECOVERABLE( pcPPS->getChromaQpOffsetListLen() != tableSizeMinus1 + 1, "Invalid chroma QP offset list length" ); } } else { pcPPS->setQpOffset( COMPONENT_Cb, 0 ); pcPPS->setQpOffset( COMPONENT_Cr, 0 ); pcPPS->setJointCbCrQpOffsetPresentFlag( 0 ); pcPPS->setSliceChromaQpFlag( 0 ); pcPPS->clearChromaQpOffsetList(); } READ_FLAG( uiCode, "pps_deblocking_filter_control_present_flag" ); pcPPS->setDeblockingFilterControlPresentFlag( uiCode ? true : false ); if( pcPPS->getDeblockingFilterControlPresentFlag() ) { READ_FLAG( uiCode, "pps_deblocking_filter_override_enabled_flag" ); pcPPS->setDeblockingFilterOverrideEnabledFlag( uiCode ? true : false ); READ_FLAG( uiCode, "pps_deblocking_filter_disabled_flag" ); pcPPS->setPPSDeblockingFilterDisabledFlag( uiCode ? true : false ); if( !pcPPS->getNoPicPartitionFlag() && pcPPS->getDeblockingFilterOverrideEnabledFlag() ) { READ_FLAG( uiCode, "pps_dbf_info_in_ph_flag" ); pcPPS->setDbfInfoInPhFlag( uiCode ? true : false ); } else { pcPPS->setDbfInfoInPhFlag( false ); } if( !pcPPS->getPPSDeblockingFilterDisabledFlag() ) { READ_SVLC( iCode, "pps_luma_beta_offset_div2" ); pcPPS->setDeblockingFilterBetaOffsetDiv2( iCode ); CHECK_RECOVERABLE( pcPPS->getDeblockingFilterBetaOffsetDiv2() < -12 || pcPPS->getDeblockingFilterBetaOffsetDiv2() > 12, "Invalid deblocking filter configuration" ); READ_SVLC( iCode, "pps_luma tc_offset_div2" ); pcPPS->setDeblockingFilterTcOffsetDiv2( iCode ); CHECK_RECOVERABLE( pcPPS->getDeblockingFilterTcOffsetDiv2() < -12 || pcPPS->getDeblockingFilterTcOffsetDiv2() > 12, "Invalid deblocking filter configuration" ); if( pcPPS->getPPSChromaToolFlag() ) { READ_SVLC( iCode, "pps_cb_beta_offset_div2" ); pcPPS->setDeblockingFilterCbBetaOffsetDiv2( iCode ); CHECK_RECOVERABLE( pcPPS->getDeblockingFilterCbBetaOffsetDiv2() < -12 || pcPPS->getDeblockingFilterCbBetaOffsetDiv2() > 12, "Invalid deblocking filter configuration" ); READ_SVLC( iCode, "pps_cb_tc_offset_div2" ); pcPPS->setDeblockingFilterCbTcOffsetDiv2( iCode ); CHECK_RECOVERABLE( pcPPS->getDeblockingFilterCbTcOffsetDiv2() < -12 || pcPPS->getDeblockingFilterCbTcOffsetDiv2() > 12, "Invalid deblocking filter configuration" ); READ_SVLC( iCode, "pps_cr_beta_offset_div2" ); pcPPS->setDeblockingFilterCrBetaOffsetDiv2( iCode ); CHECK_RECOVERABLE( pcPPS->getDeblockingFilterCrBetaOffsetDiv2() < -12 || pcPPS->getDeblockingFilterCrBetaOffsetDiv2() > 12, "Invalid deblocking filter configuration" ); READ_SVLC( iCode, "pps_cr_tc_offset_div2" ); pcPPS->setDeblockingFilterCrTcOffsetDiv2( iCode ); CHECK_RECOVERABLE( pcPPS->getDeblockingFilterCrTcOffsetDiv2() < -12 || pcPPS->getDeblockingFilterCrTcOffsetDiv2() > 12, "Invalid deblocking filter configuration" ); } else { pcPPS->setDeblockingFilterCbBetaOffsetDiv2 ( pcPPS->getDeblockingFilterBetaOffsetDiv2() ); pcPPS->setDeblockingFilterCbTcOffsetDiv2 ( pcPPS->getDeblockingFilterTcOffsetDiv2() ); pcPPS->setDeblockingFilterCrBetaOffsetDiv2 ( pcPPS->getDeblockingFilterBetaOffsetDiv2() ); pcPPS->setDeblockingFilterCrTcOffsetDiv2 ( pcPPS->getDeblockingFilterTcOffsetDiv2() ); } } } else { pcPPS->setDeblockingFilterOverrideEnabledFlag( false ); pcPPS->setDbfInfoInPhFlag( false ); } if( !pcPPS->getNoPicPartitionFlag() ) { READ_FLAG( uiCode, "pps_rpl_info_in_ph_flag" ); pcPPS->setRplInfoInPhFlag( uiCode ? true : false ); READ_FLAG( uiCode, "pps_sao_info_in_ph_flag" ); pcPPS->setSaoInfoInPhFlag( uiCode ? true : false ); READ_FLAG( uiCode, "pps_alf_info_in_ph_flag" ); pcPPS->setAlfInfoInPhFlag( uiCode ? true : false ); if( (pcPPS->getUseWP() || pcPPS->getWPBiPred()) && pcPPS->getRplInfoInPhFlag() ) { READ_FLAG( uiCode, "pps_wp_info_in_ph_flag" ); pcPPS->setWpInfoInPhFlag( uiCode ? true : false ); } else { pcPPS->setWpInfoInPhFlag( false ); } READ_FLAG( uiCode, "pps_qp_delta_info_in_ph_flag" ); pcPPS->setQpDeltaInfoInPhFlag( uiCode ? true : false ); } else { pcPPS->setRplInfoInPhFlag( false ); pcPPS->setSaoInfoInPhFlag( false ); pcPPS->setAlfInfoInPhFlag( false ); pcPPS->setWpInfoInPhFlag( false ); pcPPS->setQpDeltaInfoInPhFlag( false ); } READ_FLAG( uiCode, "pps_picture_header_extension_present_flag" ); pcPPS->setPictureHeaderExtensionPresentFlag( uiCode ); READ_FLAG( uiCode, "pps_slice_header_extension_present_flag" ); pcPPS->setSliceHeaderExtensionPresentFlag( uiCode ); READ_FLAG( uiCode, "pps_extension_flag" ); if( uiCode ) { while( xMoreRbspData() ) { READ_FLAG( uiCode, "pps_extension_data_flag" ); } } xReadRbspTrailingBits(); if( pcPPS->getPicWidthInLumaSamples() == pcSPS->getMaxPicWidthInLumaSamples() && pcPPS->getPicHeightInLumaSamples() == pcSPS->getMaxPicHeightInLumaSamples() ) { CHECK_RECOVERABLE( pcPPS->getConformanceWindowPresentFlag(), "When pps_pic_width_in_luma_samples is equal to sps_pic_width_max_in_luma_samples and " "pps_pic_height_in_luma_samples is equal to sps_pic_height_max_in_luma_samples, the value of " "pps_conformance_window_flag shall be equal to 0" ); pcPPS->setConformanceWindow( pcSPS->getConformanceWindow() ); if( !pcPPS->getScalingWindow().getWindowEnabledFlag() ) { pcPPS->setScalingWindow( pcPPS->getConformanceWindow() ); } } pcPPS->finalizePPSPartitioning( pcSPS ); // set wraparound offset from PPS and SPS info int minCbSizeY = ( 1 << pcSPS->getLog2MinCodingBlockSize() ); CHECK_RECOVERABLE( !pcSPS->getUseWrapAround() && pcPPS->getUseWrapAround(), "When sps_ref_wraparound_enabled_flag is equal to 0, the value of pps_ref_wraparound_enabled_flag shall be equal to 0." ); CHECK_RECOVERABLE( ( ( ( pcSPS->getCTUSize() / minCbSizeY ) + 1 ) > ( ( pcPPS->getPicWidthInLumaSamples() / minCbSizeY ) - 1 ) ) && pcPPS->getUseWrapAround(), "When the value of CtbSizeY / MinCbSizeY + 1 is greater than pic_width_in_luma_samples / MinCbSizeY - 1, the value of pps_ref_wraparound_enabled_flag shall be equal to 0." ); if( pcPPS->getUseWrapAround() ) { CHECK_RECOVERABLE( ( pcPPS->getPicWidthMinusWrapAroundOffset() > ( pcPPS->getPicWidthInLumaSamples() / minCbSizeY - pcSPS->getCTUSize() / minCbSizeY - 2 ) ), "pps_pic_width_minus_wraparound_ofsfet shall be less than or equal to pps_pic_width_in_luma_samples/MinCbSizeY - CtbSizeY/MinCbSizeY-2" ); pcPPS->setWrapAroundOffset( minCbSizeY * ( pcPPS->getPicWidthInLumaSamples() / minCbSizeY - pcPPS->getPicWidthMinusWrapAroundOffset() ) ); } else { pcPPS->setWrapAroundOffset( 0 ); } pcPPS->pcv = std::make_unique( *pcSPS, *pcPPS ); } void HLSyntaxReader::parseAPS( APS* aps ) { #if ENABLE_TRACING xTraceAPSHeader(); #endif uint32_t code; READ_CODE( 3, code, "aps_params_type" ); aps->setAPSType( code ); READ_CODE( 5, code, "adaptation_parameter_set_id" ); aps->setAPSId( code ); READ_FLAG( code, "aps_chroma_present_flag" ); aps->chromaPresentFlag = code; const int apsType = aps->getAPSType(); if( apsType == ALF_APS ) { parseAlfAps( aps ); } else if( apsType == LMCS_APS ) { parseLmcsAps( aps ); } else if( apsType == SCALING_LIST_APS ) { parseScalingListAps( aps ); } READ_FLAG( code, "aps_extension_flag" ); if( code ) { while( xMoreRbspData() ) { READ_FLAG( code, "aps_extension_data_flag" ); } } xReadRbspTrailingBits(); } void HLSyntaxReader::parseAlfAps( APS* aps ) { uint32_t code; AlfSliceParam& param = aps->getAlfAPSParam(); param.reset(); param.enabledFlag[COMPONENT_Y] = param.enabledFlag[COMPONENT_Cb] = param.enabledFlag[COMPONENT_Cr] = true; READ_FLAG( code, "alf_luma_new_filter" ); param.newFilterFlag[CHANNEL_TYPE_LUMA] = code; if( aps->chromaPresentFlag ) { READ_FLAG( code, "alf_chroma_new_filter" ); param.newFilterFlag[CHANNEL_TYPE_CHROMA] = code; } else { param.newFilterFlag[CHANNEL_TYPE_CHROMA] = 0; } CcAlfFilterParam ccAlfParam = aps->getCcAlfAPSParam(); if( aps->chromaPresentFlag ) { READ_FLAG( code, "alf_cc_cb_filter_signal_flag" ); ccAlfParam.newCcAlfFilter[COMPONENT_Cb - 1] = code; } else { ccAlfParam.newCcAlfFilter[COMPONENT_Cb - 1] = 0; } if( aps->chromaPresentFlag ) { READ_FLAG( code, "alf_cc_cr_filter_signal_flag" ); ccAlfParam.newCcAlfFilter[COMPONENT_Cr - 1] = code; } else { ccAlfParam.newCcAlfFilter[COMPONENT_Cr - 1] = 0; } CHECK_RECOVERABLE( param.newFilterFlag[CHANNEL_TYPE_LUMA] == 0 && param.newFilterFlag[CHANNEL_TYPE_CHROMA] == 0 && ccAlfParam.newCcAlfFilter[COMPONENT_Cb - 1] == 0 && ccAlfParam.newCcAlfFilter[COMPONENT_Cr - 1] == 0, "bitstream conformance error: one of alf_luma_filter_signal_flag, alf_chroma_filter_signal_flag, " "alf_cross_component_cb_filter_signal_flag, and alf_cross_component_cr_filter_signal_flag shall be nonzero" ); if( param.newFilterFlag[CHANNEL_TYPE_LUMA] ) { READ_FLAG( code, "alf_luma_clip" ); param.nonLinearFlagLuma = code ? true : false; READ_UVLC( code, "alf_luma_num_filters_signalled_minus1" ); param.numLumaFilters = code + 1; if( param.numLumaFilters > 1 ) { const int length = (int)ceil( log2( param.numLumaFilters ) ); for( int i = 0; i < MAX_NUM_ALF_CLASSES; i++ ) { READ_CODE( length, code, "alf_luma_coeff_delta_idx" ); param.filterCoeffDeltaIdx[i] = code; } } else { memset( param.filterCoeffDeltaIdx, 0, sizeof( param.filterCoeffDeltaIdx ) ); } alfFilter( param, false, 0 ); } if( param.newFilterFlag[CHANNEL_TYPE_CHROMA] ) { READ_FLAG( code, "alf_nonlinear_enable_flag_chroma" ); param.nonLinearFlagChroma = code ? true : false; if( MAX_NUM_ALF_ALTERNATIVES_CHROMA > 1 ) { READ_UVLC( code, "alf_chroma_num_alts_minus1" ); } else { code = 0; } param.numAlternativesChroma = code + 1; for( int altIdx=0; altIdx < param.numAlternativesChroma; ++altIdx ) { alfFilter( param, true, altIdx ); } } for( int ccIdx = 0; ccIdx < 2; ccIdx++ ) { if( ccAlfParam.newCcAlfFilter[ccIdx] ) { if( MAX_NUM_CC_ALF_FILTERS > 1 ) { READ_UVLC( code, ccIdx == 0 ? "alf_cc_cb_filters_signalled_minus1" : "alf_cc_cr_filters_signalled_minus1" ); } else { code = 0; } ccAlfParam.ccAlfFilterCount[ccIdx] = code + 1; for( int filterIdx = 0; filterIdx < ccAlfParam.ccAlfFilterCount[ccIdx]; filterIdx++ ) { ccAlfParam.ccAlfFilterIdxEnabled[ccIdx][filterIdx] = true; const int numCoeff = g_alfNumCoeff[CC_ALF]; short *coeff = ccAlfParam.ccAlfCoeff[ccIdx][filterIdx]; // Filter coefficients for( int i = 0; i < numCoeff - 1; i++ ) { READ_CODE( CCALF_BITS_PER_COEFF_LEVEL, code, ccIdx == 0 ? "alf_cc_cb_mapped_coeff_abs" : "alf_cc_cr_mapped_coeff_abs" ); if( code == 0 ) { coeff[i] = 0; } else { coeff[i] = 1 << (code - 1); READ_FLAG( code, ccIdx == 0 ? "alf_cc_cb_coeff_sign" : "alf_cc_cr_coeff_sign" ); coeff[i] *= 1 - 2 * code; } } DTRACE( g_trace_ctx, D_SYNTAX, "%s coeff filterIdx %d: ", ccIdx == 0 ? "Cb" : "Cr", filterIdx ); for( int i = 0; i < numCoeff; i++ ) { DTRACE( g_trace_ctx, D_SYNTAX, "%d ", coeff[i] ); } DTRACE( g_trace_ctx, D_SYNTAX, "\n" ); } for( int filterIdx = ccAlfParam.ccAlfFilterCount[ccIdx]; filterIdx < MAX_NUM_CC_ALF_FILTERS; filterIdx++ ) { ccAlfParam.ccAlfFilterIdxEnabled[ccIdx][filterIdx] = false; } } } aps->setCcAlfAPSParam( ccAlfParam ); } void HLSyntaxReader::parseLmcsAps( APS* aps ) { uint32_t code; SliceReshapeInfo& info = aps->getReshaperAPSInfo(); memset( info.reshaperModelBinCWDelta, 0, PIC_CODE_CW_BINS * sizeof(int) ); READ_UVLC( code, "lmcs_min_bin_idx" ); info.reshaperModelMinBinIdx = code; READ_UVLC( code, "lmcs_delta_max_bin_idx" ); info.reshaperModelMaxBinIdx = PIC_CODE_CW_BINS - 1 - code; READ_UVLC( code, "lmcs_delta_cw_prec_minus1" ); info.maxNbitsNeededDeltaCW = code + 1; CHECK_RECOVERABLE( info.maxNbitsNeededDeltaCW == 0, "wrong" ); for( uint32_t i = info.reshaperModelMinBinIdx; i <= info.reshaperModelMaxBinIdx; i++ ) { READ_CODE( info.maxNbitsNeededDeltaCW, code, "lmcs_delta_abs_cw[ i ]" ); int absCW = code; if( absCW > 0 ) { READ_CODE( 1, code, "lmcs_delta_sign_cw_flag[ i ]" ); } int signCW = code; info.reshaperModelBinCWDelta[i] = ( 1 - 2 * signCW ) * absCW; } if( aps->chromaPresentFlag ) { READ_CODE( 3, code, "lmcs_delta_abs_crs" ); } int absCW = aps->chromaPresentFlag ? code : 0; if( absCW > 0 ) { READ_CODE( 1, code, "lmcs_delta_sign_crs_flag" ); } int signCW = code; info.chrResScalingOffset = ( 1 - 2 * signCW ) * absCW; aps->setReshaperAPSInfo( info ); } void HLSyntaxReader::parseScalingListAps( APS* aps ) { ScalingList& info = aps->getScalingList(); parseScalingList( &info, aps->chromaPresentFlag ); } void HLSyntaxReader::parseVUI( VUI* pcVUI, SPS *pcSPS ) { #if ENABLE_TRACING DTRACE( g_trace_ctx, D_HEADER, "----------- vui_parameters -----------\n"); #endif unsigned vuiPayloadSize = pcSPS->getVuiPayloadSize(); InputBitstream *bs = getBitstream(); setBitstream( bs->extractSubstream( vuiPayloadSize * 8 ) ); uint32_t symbol; READ_FLAG( symbol, "vui_general_progressive_source_flag" ); pcVUI->setProgressiveSourceFlag( symbol ? true : false ); READ_FLAG( symbol, "vui_general_interlaced_source_flag" ); pcVUI->setInterlacedSourceFlag( symbol ? true : false ); READ_FLAG( symbol, "vui_non_packed_constraint_flag" ); pcVUI->setNonPackedFlag( symbol ? true : false ); READ_FLAG( symbol, "vui_non_projected_constraint_flag" ); pcVUI->setNonProjectedFlag( symbol ? true : false ); READ_FLAG( symbol, "vui_aspect_ratio_info_present_flag" ); pcVUI->setAspectRatioInfoPresentFlag( symbol ); if( pcVUI->getAspectRatioInfoPresentFlag() ) { READ_FLAG( symbol, "vui_aspect_ratio_constant_flag" ); pcVUI->setAspectRatioConstantFlag( symbol ); READ_CODE( 8, symbol, "vui_aspect_ratio_idc" ); pcVUI->setAspectRatioIdc( symbol ); if( pcVUI->getAspectRatioIdc() == 255 ) { READ_CODE( 16, symbol, "vui_sar_width" ); pcVUI->setSarWidth( symbol ); READ_CODE( 16, symbol, "vui_sar_height" ); pcVUI->setSarHeight( symbol ); } } READ_FLAG( symbol, "vui_overscan_info_present_flag" ); pcVUI->setOverscanInfoPresentFlag( symbol ); if( pcVUI->getOverscanInfoPresentFlag() ) { READ_FLAG( symbol, "vui_overscan_appropriate_flag" ); pcVUI->setOverscanAppropriateFlag( symbol ); } READ_FLAG( symbol, "vui_colour_description_present_flag" ); pcVUI->setColourDescriptionPresentFlag( symbol ); if( pcVUI->getColourDescriptionPresentFlag() ) { READ_CODE (8, symbol, "vui_colour_primaries" ); pcVUI->setColourPrimaries( symbol ); READ_CODE (8, symbol, "vui_transfer_characteristics" ); pcVUI->setTransferCharacteristics( symbol ); READ_CODE( 8, symbol, "vui_matrix_coeffs" ); pcVUI->setMatrixCoefficients( symbol ); READ_FLAG( symbol, "vui_video_full_range_flag" ); pcVUI->setVideoFullRangeFlag( symbol); } READ_FLAG( symbol, "vui_chroma_loc_info_present_flag" ); pcVUI->setChromaLocInfoPresentFlag( symbol ); if( pcVUI->getChromaLocInfoPresentFlag() ) { if( pcVUI->getProgressiveSourceFlag() && !pcVUI->getInterlacedSourceFlag() ) { READ_UVLC( symbol, "vui_chroma_sample_loc_type" ); pcVUI->setChromaSampleLocType( symbol ); } else { READ_UVLC( symbol, "vui_chroma_sample_loc_type_top_field" ); pcVUI->setChromaSampleLocTypeTopField( symbol ); READ_UVLC( symbol, "vui_chroma_sample_loc_type_bottom_field" ); pcVUI->setChromaSampleLocTypeBottomField( symbol ); } } int payloadBitsRem = getBitstream()->getNumBitsLeft(); if( payloadBitsRem ) //Corresponds to more_data_in_payload() { while( payloadBitsRem > 9 ) //payload_extension_present() { READ_CODE( 1, symbol, "vui_reserved_payload_extension_data" ); payloadBitsRem--; } int finalBits = getBitstream()->peekBits( payloadBitsRem ); int numFinalZeroBits = 0; int mask = 0xff; while( finalBits & (mask >> numFinalZeroBits) ) { numFinalZeroBits++; } while( payloadBitsRem > 9-numFinalZeroBits ) //payload_extension_present() { READ_CODE( 1, symbol, "vui_reserved_payload_extension_data" ); payloadBitsRem--; } READ_FLAG( symbol, "vui_payload_bit_equal_to_one" ); CHECK_RECOVERABLE( symbol != 1, "vui_payload_bit_equal_to_one not equal to 1" ); payloadBitsRem--; while( payloadBitsRem ) { READ_FLAG( symbol, "vui_payload_bit_equal_to_zero" ); CHECK_RECOVERABLE( symbol != 0, "vui_payload_bit_equal_to_zero not equal to 0" ); payloadBitsRem--; } } delete getBitstream(); setBitstream(bs); } void HLSyntaxReader::parseGeneralHrdParameters( GeneralHrdParams *hrd ) { uint32_t symbol; READ_CODE( 32, symbol, "num_units_in_tick" ); hrd->setNumUnitsInTick( symbol ); READ_CODE( 32, symbol, "time_scale" ); hrd->setTimeScale( symbol ); READ_FLAG( symbol, "general_nal_hrd_parameters_present_flag" ); hrd->setGeneralNalHrdParametersPresentFlag( symbol == 1 ? true : false ); READ_FLAG( symbol, "general_vcl_hrd_parameters_present_flag" ); hrd->setGeneralVclHrdParametersPresentFlag( symbol == 1 ? true : false ); if( hrd->getGeneralNalHrdParametersPresentFlag() || hrd->getGeneralVclHrdParametersPresentFlag() ) { READ_FLAG( symbol, "general_same_pic_timing_in_all_ols_flag" ); hrd->setGeneralSamePicTimingInAllOlsFlag( symbol == 1 ? true : false ); READ_FLAG( symbol, "general_decoding_unit_hrd_params_present_flag" ); hrd->setGeneralDecodingUnitHrdParamsPresentFlag( symbol == 1 ? true : false ); if( hrd->getGeneralDecodingUnitHrdParamsPresentFlag() ) { READ_CODE( 8, symbol, "tick_divisor_minus2" ); hrd->setTickDivisorMinus2( symbol ); } READ_CODE( 4, symbol, "bit_rate_scale" ); hrd->setBitRateScale( symbol ); READ_CODE( 4, symbol, "cpb_size_scale" ); hrd->setCpbSizeScale( symbol ); if( hrd->getGeneralDecodingUnitHrdParamsPresentFlag() ) { READ_CODE( 4, symbol, "cpb_size_du_scale" ); hrd->setCpbSizeDuScale( symbol ); } READ_UVLC( symbol, "hrd_cpb_cnt_minus1" ); hrd->setHrdCpbCntMinus1( symbol ); CHECK_RECOVERABLE( symbol > 31, "The value of hrd_cpb_cnt_minus1 shall be in the range of 0 to 31, inclusive" ); } } void HLSyntaxReader::parseOlsHrdParameters( GeneralHrdParams * generalHrd, OlsHrdParams *olsHrd, uint32_t firstSubLayer, uint32_t maxNumSubLayersMinus1 ) { uint32_t symbol; for( int i = firstSubLayer; i <= maxNumSubLayersMinus1; i ++ ) { OlsHrdParams *hrd = &(olsHrd[i]); READ_FLAG( symbol, "fixed_pic_rate_general_flag" ); hrd->setFixedPicRateGeneralFlag( symbol == 1 ? true : false ); if( !hrd->getFixedPicRateGeneralFlag() ) { READ_FLAG( symbol, "fixed_pic_rate_within_cvs_flag" ); hrd->setFixedPicRateWithinCvsFlag( symbol == 1 ? true : false ); } else { hrd->setFixedPicRateWithinCvsFlag( true ); } hrd->setLowDelayHrdFlag( false ); // Inferred to be 0 when not present if( hrd->getFixedPicRateWithinCvsFlag() ) { READ_UVLC( symbol, "elemental_duration_in_tc_minus1" ); hrd->setElementDurationInTcMinus1( symbol ); } else if( generalHrd->getHrdCpbCntMinus1() == 0 ) { READ_FLAG(symbol, "low_delay_hrd_flag"); hrd->setLowDelayHrdFlag( symbol == 1 ? true : false ); } for( int nalOrVcl = 0; nalOrVcl < 2; nalOrVcl ++ ) { if( ( nalOrVcl == 0 && generalHrd->getGeneralNalHrdParametersPresentFlag() ) || ( nalOrVcl == 1 && generalHrd->getGeneralVclHrdParametersPresentFlag() ) ) { for( int j = 0; j <= generalHrd->getHrdCpbCntMinus1(); j++ ) { READ_UVLC( symbol, "bit_rate_value_minus1"); hrd->setBitRateValueMinus1( j, nalOrVcl, symbol ); READ_UVLC( symbol, "cpb_size_value_minus1"); hrd->setCpbSizeValueMinus1( j, nalOrVcl, symbol ); if( generalHrd->getGeneralDecodingUnitHrdParamsPresentFlag() ) { READ_UVLC( symbol, "cpb_size_du_value_minus1" ); hrd->setDuCpbSizeValueMinus1( j, nalOrVcl, symbol ); READ_UVLC( symbol, "bit_rate_du_value_minus1" ); hrd->setDuBitRateValueMinus1( j, nalOrVcl, symbol ); } READ_FLAG( symbol, "cbr_flag" ); hrd->setCbrFlag( j, nalOrVcl, symbol == 1 ? true : false ); } } } } for( int i = 0; i < firstSubLayer; i++ ) { OlsHrdParams* hrdHighestTLayer = &( olsHrd[maxNumSubLayersMinus1] ); OlsHrdParams* hrdTemp = &( olsHrd[i] ); bool tempFlag = hrdHighestTLayer->getFixedPicRateGeneralFlag(); hrdTemp->setFixedPicRateGeneralFlag( tempFlag ); tempFlag = hrdHighestTLayer->getFixedPicRateWithinCvsFlag(); hrdTemp->setFixedPicRateWithinCvsFlag( tempFlag ); uint32_t tempElementDurationInTcMinus1 = hrdHighestTLayer->getElementDurationInTcMinus1(); hrdTemp->setElementDurationInTcMinus1( tempElementDurationInTcMinus1 ); for( int nalOrVcl = 0; nalOrVcl < 2; nalOrVcl++ ) { if( ( nalOrVcl == 0 && generalHrd->getGeneralNalHrdParametersPresentFlag() ) || ( nalOrVcl == 1 && generalHrd->getGeneralVclHrdParametersPresentFlag() ) ) { for( int j = 0; j <= (generalHrd->getHrdCpbCntMinus1()); j++ ) { uint32_t bitRate = hrdHighestTLayer->getBitRateValueMinus1( j, nalOrVcl ); hrdTemp->setBitRateValueMinus1( j, nalOrVcl, bitRate ); uint32_t cpbSize = hrdHighestTLayer->getCpbSizeValueMinus1( j, nalOrVcl ); hrdTemp->setCpbSizeValueMinus1( j, nalOrVcl, cpbSize ); if( generalHrd->getGeneralDecodingUnitHrdParamsPresentFlag() ) { uint32_t bitRateDu = hrdHighestTLayer->getDuBitRateValueMinus1( j, nalOrVcl ); hrdTemp->setDuBitRateValueMinus1(j, nalOrVcl, bitRateDu); uint32_t cpbSizeDu = hrdHighestTLayer->getDuCpbSizeValueMinus1( j, nalOrVcl ); hrdTemp->setDuCpbSizeValueMinus1( j, nalOrVcl, cpbSizeDu ); } bool flag = hrdHighestTLayer->getCbrFlag( j, nalOrVcl ); hrdTemp->setCbrFlag( j, nalOrVcl, flag ); } } } } } void HLSyntaxReader::dpb_parameters( int maxSubLayersMinus1, bool subLayerInfoFlag, SPS *pcSPS ) { uint32_t code; for( int i = ( subLayerInfoFlag ? 0 : maxSubLayersMinus1 ); i <= maxSubLayersMinus1; i++ ) { READ_UVLC( code, "dpb_max_dec_pic_buffering_minus1[i]" ); pcSPS->setMaxDecPicBuffering( code + 1, i ); READ_UVLC( code, "dpb_max_num_reorder_pics[i]" ); pcSPS->setNumReorderPics( code, i ); CHECK_RECOVERABLE( pcSPS->getNumReorderPics( i ) >= pcSPS->getMaxDecPicBuffering( i ), "The value of dpb_max_num_reorder_pics[ i ] shall be in the range of 0 to dpb_max_dec_pic_buffering_minus1[ i ], inclusive" ); READ_UVLC( code, "dpb_max_latency_increase_plus1[i]" ); pcSPS->setMaxLatencyIncreasePlus1( code, i ); } } void HLSyntaxReader::parseExtraPHBitsStruct( SPS *sps, int numBytes ) { uint32_t symbol; std::vector presentFlags; presentFlags.resize ( 8 * numBytes ); for( int i = 0; i < 8 * numBytes; i++ ) { READ_FLAG( symbol, "sps_extra_ph_bit_present_flag[i]" ); presentFlags[i] = symbol; } sps->setExtraPHBitPresentFlags( presentFlags ); } void HLSyntaxReader::parseExtraSHBitsStruct( SPS *sps, int numBytes ) { uint32_t symbol; std::vector presentFlags; presentFlags.resize ( 8 * numBytes ); for( int i = 0; i < 8 * numBytes; i++ ) { READ_FLAG( symbol, "sps_extra_sh_bit_present_flag[i]" ); presentFlags[i] = symbol; } sps->setExtraSHBitPresentFlags( presentFlags ); } void HLSyntaxReader::parseSPS( SPS* pcSPS, const ParameterSetManager *parameterSetManager ) { #if ENABLE_TRACING xTraceSPSHeader (); #endif uint32_t uiCode = 0; READ_CODE( 4, uiCode, "sps_seq_parameter_set_id" ); pcSPS->setSPSId( uiCode ); READ_CODE( 4, uiCode, "sps_video_parameter_set_id" ); int vpsId = uiCode; //pcSPS->setVPSId( vpsId ); // TODO: change to support VPS READ_CODE( 3, uiCode, "sps_max_sub_layers_minus1" ); pcSPS->setMaxTLayers( uiCode + 1 ); CHECK_RECOVERABLE( uiCode > 6, "Invalid maximum number of T-layer signalled" ); READ_CODE( 2, uiCode, "sps_chroma_format_idc" ); pcSPS->setChromaFormatIdc( ChromaFormat( uiCode ) ); READ_CODE( 2, uiCode, "sps_log2_ctu_size_minus5" ); pcSPS->setCTUSize( 1 << ( uiCode + 5 ) ); CHECK_RECOVERABLE( uiCode > 2, "sps_log2_ctu_size_minus5 must be less than or equal to 2" ); unsigned ctbLog2SizeY = uiCode + 5; pcSPS->setMaxCUWidth( pcSPS->getCTUSize() ); pcSPS->setMaxCUHeight( pcSPS->getCTUSize() ); READ_FLAG( uiCode, "sps_ptl_dpb_hrd_params_present_flag" ); pcSPS->setPtlDpbHrdParamsPresentFlag( uiCode ); if( !vpsId ) { CHECK_RECOVERABLE( !pcSPS->getPtlDpbHrdParamsPresentFlag(), "When sps_video_parameter_set_id is equal to 0, the value of sps_ptl_dpb_hrd_params_present_flag shall be equal to 1" ); } if( pcSPS->getPtlDpbHrdParamsPresentFlag() ) { parseProfileTierLevel( pcSPS->getProfileTierLevel(), true, pcSPS->getMaxTLayers() - 1 ); } READ_FLAG( uiCode, "sps_gdr_enabled_flag" ); pcSPS->setGDREnabledFlag( uiCode ); if( pcSPS->getProfileTierLevel()->getConstraintInfo()->getNoGdrConstraintFlag() ) { CHECK_RECOVERABLE( uiCode != 0, "When gci_no_gdr_constraint_flag equal to 1 , the value of sps_gdr_enabled_flag shall be equal to 0" ); } READ_FLAG( uiCode, "sps_ref_pic_resampling_enabled_flag" ); pcSPS->setRprEnabledFlag( uiCode ); if( pcSPS->getProfileTierLevel()->getConstraintInfo()->getNoRprConstraintFlag() ) { CHECK_RECOVERABLE( uiCode != 0, "When gci_no_ref_pic_resampling_constraint_flag is equal to 1, sps_ref_pic_resampling_enabled_flag shall be equal to 0" ); } if( uiCode ) { READ_FLAG( uiCode, "sps_res_change_in_clvs_allowed_flag" ); pcSPS->setResChangeInClvsEnabledFlag( uiCode ); } else { pcSPS->setResChangeInClvsEnabledFlag( 0 ); } if( pcSPS->getProfileTierLevel()->getConstraintInfo()->getNoResChangeInClvsConstraintFlag() ) { CHECK_RECOVERABLE( uiCode != 0, "When no_res_change_in_clvs_constraint_flag is equal to 1, res_change_in_clvs_allowed_flag shall be equal to 0" ); } READ_UVLC( uiCode, "sps_pic_width_max_in_luma_samples" ); pcSPS->setMaxPicWidthInLumaSamples( uiCode ); READ_UVLC( uiCode, "sps_pic_height_max_in_luma_samples" ); pcSPS->setMaxPicHeightInLumaSamples( uiCode ); READ_FLAG( uiCode, "sps_conformance_window_flag" ); pcSPS->setConformanceWindowPresentFlag( uiCode ); if( uiCode != 0 ) { Window& conf = pcSPS->getConformanceWindow(); READ_UVLC( uiCode, "sps_conf_win_left_offset" ); conf.setWindowLeftOffset( uiCode ); READ_UVLC( uiCode, "sps_conf_win_right_offset" ); conf.setWindowRightOffset( uiCode ); READ_UVLC( uiCode, "sps_conf_win_top_offset" ); conf.setWindowTopOffset( uiCode ); READ_UVLC( uiCode, "sps_conf_win_bottom_offset" ); conf.setWindowBottomOffset( uiCode ); } READ_FLAG( uiCode, "sps_subpic_info_present_flag" ); pcSPS->setSubPicInfoPresentFlag( uiCode ); if( pcSPS->getProfileTierLevel()->getConstraintInfo()->getNoSubpicInfoConstraintFlag() ) { CHECK_RECOVERABLE( uiCode != 0, "When gci_no_subpic_info_constraint_flag is equal to 1, the value of subpic_info_present_flag shall be equal to 0" ); } if( pcSPS->getSubPicInfoPresentFlag() ) { READ_UVLC( uiCode, "sps_num_subpics_minus1" ); pcSPS->setNumSubPics( uiCode + 1 ); CHECK_RECOVERABLE( uiCode > ( ( pcSPS->getMaxPicWidthInLumaSamples() + pcSPS->getCTUSize() - 1 ) / ( pcSPS->getCTUSize() ) ) * ( ( pcSPS->getMaxPicHeightInLumaSamples() + pcSPS->getCTUSize() - 1 ) / ( pcSPS->getCTUSize() ) ) - 1, "Invalid sps_num_subpics_minus1 value" ); if( pcSPS->getNumSubPics() == 1 ) { pcSPS->setSubPicCtuTopLeftX( 0, 0 ); pcSPS->setSubPicCtuTopLeftY( 0, 0 ); pcSPS->setSubPicWidth( 0, ( pcSPS->getMaxPicWidthInLumaSamples() + pcSPS->getCTUSize() - 1 ) >> getLog2( pcSPS->getCTUSize() ) ); pcSPS->setSubPicHeight( 0, ( pcSPS->getMaxPicHeightInLumaSamples() + pcSPS->getCTUSize() - 1 ) >> getLog2( pcSPS->getCTUSize() ) ); pcSPS->setIndependentSubPicsFlag( 1 ); pcSPS->setSubPicSameSizeFlag( 0 ); pcSPS->setSubPicTreatedAsPicFlag( 0, 1 ); pcSPS->setLoopFilterAcrossSubpicEnabledFlag( 0, 0 ); } else { READ_FLAG( uiCode, "sps_independent_subpics_flag" ); pcSPS->setIndependentSubPicsFlag( uiCode != 0 ); READ_FLAG( uiCode, "sps_subpic_same_size_flag" ); pcSPS->setSubPicSameSizeFlag( uiCode ); uint32_t tmpWidthVal = ( pcSPS->getMaxPicWidthInLumaSamples() + pcSPS->getCTUSize() - 1 ) / pcSPS->getCTUSize(); uint32_t tmpHeightVal = ( pcSPS->getMaxPicHeightInLumaSamples() + pcSPS->getCTUSize() - 1 ) / pcSPS->getCTUSize(); uint32_t numSubpicCols = 1; for( int picIdx = 0; picIdx < pcSPS->getNumSubPics(); picIdx++ ) { if( !pcSPS->getSubPicSameSizeFlag() || picIdx == 0 ) { if( ( picIdx > 0 ) && ( pcSPS->getMaxPicWidthInLumaSamples() > pcSPS->getCTUSize() ) ) { READ_CODE( (int)ceil( log2( tmpWidthVal ) ), uiCode, "sps_subpic_ctu_top_left_x[i]" ); pcSPS->setSubPicCtuTopLeftX( picIdx, uiCode ); } else { pcSPS->setSubPicCtuTopLeftX( picIdx, 0 ); } if( ( picIdx > 0 ) && ( pcSPS->getMaxPicHeightInLumaSamples() > pcSPS->getCTUSize() ) ) { READ_CODE( (int)ceil( log2( tmpHeightVal ) ), uiCode, "sps_subpic_ctu_top_left_y[i]" ); pcSPS->setSubPicCtuTopLeftY( picIdx, uiCode ); } else { pcSPS->setSubPicCtuTopLeftY( picIdx, 0 ); } if( picIdx getNumSubPics() - 1 && pcSPS->getMaxPicWidthInLumaSamples() > pcSPS->getCTUSize() ) { READ_CODE( (int)ceil( log2( tmpWidthVal ) ), uiCode, "sps_subpic_width_minus1[i]" ); pcSPS->setSubPicWidth( picIdx, uiCode + 1 ); } else { pcSPS->setSubPicWidth( picIdx, tmpWidthVal - pcSPS->getSubPicCtuTopLeftX( picIdx ) ); } if( picIdx getNumSubPics() - 1 && pcSPS->getMaxPicHeightInLumaSamples() > pcSPS->getCTUSize() ) { READ_CODE( (int)ceil( log2( tmpHeightVal ) ), uiCode, "sps_subpic_height_minus1[i]" ); pcSPS->setSubPicHeight(picIdx, uiCode + 1); } else { pcSPS->setSubPicHeight( picIdx, tmpHeightVal - pcSPS->getSubPicCtuTopLeftY(picIdx) ); } if( pcSPS->getSubPicSameSizeFlag() ) { numSubpicCols = tmpWidthVal / pcSPS->getSubPicWidth( 0 ); CHECK_RECOVERABLE( !( tmpWidthVal % pcSPS->getSubPicWidth(0) == 0 ), "subpic_width_minus1[0] is invalid." ); CHECK_RECOVERABLE( !( tmpHeightVal % pcSPS->getSubPicHeight(0) == 0 ), "subpic_height_minus1[0] is invalid." ); CHECK_RECOVERABLE( !( numSubpicCols * ( tmpHeightVal / pcSPS->getSubPicHeight(0) ) == pcSPS->getNumSubPics() ), "when sps_subpic_same_size_flag is equal to, sps_num_subpics_minus1 is invalid" ); } } else { pcSPS->setSubPicCtuTopLeftX( picIdx, ( picIdx % numSubpicCols ) * pcSPS->getSubPicWidth( 0 ) ); pcSPS->setSubPicCtuTopLeftY( picIdx, ( picIdx / numSubpicCols ) * pcSPS->getSubPicHeight( 0 ) ); pcSPS->setSubPicWidth( picIdx, pcSPS->getSubPicWidth( 0 ) ); pcSPS->setSubPicHeight( picIdx, pcSPS->getSubPicHeight( 0 ) ); } if( !pcSPS->getIndependentSubPicsFlag() ) { READ_FLAG( uiCode, "sps_subpic_treated_as_pic_flag[i]" ); pcSPS->setSubPicTreatedAsPicFlag( picIdx, uiCode ); READ_FLAG( uiCode, "sps_loop_filter_across_subpic_enabled_flag[i]" ); pcSPS->setLoopFilterAcrossSubpicEnabledFlag( picIdx, uiCode ); } } } READ_UVLC( uiCode, "sps_subpic_id_len_minus1" ); pcSPS->setSubPicIdLen( uiCode + 1 ); CHECK_RECOVERABLE( uiCode > 15, "Invalid sps_subpic_id_len_minus1 value" ); CHECK_RECOVERABLE( ( 1 << ( uiCode + 1 ) ) < pcSPS->getNumSubPics(), "Invalid sps_subpic_id_len_minus1 value" ); READ_FLAG( uiCode, "sps_subpic_id_mapping_explicitly_signalled_flag" ); pcSPS->setSubPicIdMappingExplicitlySignalledFlag( uiCode != 0 ); if( pcSPS->getSubPicIdMappingExplicitlySignalledFlag() ) { READ_FLAG( uiCode, "sps_subpic_id_mapping_present_flag" ); pcSPS->setSubPicIdMappingInSpsFlag( uiCode != 0 ); if( pcSPS->getSubPicIdMappingInSpsFlag() ) { for( int picIdx = 0; picIdx < pcSPS->getNumSubPics(); picIdx++ ) { READ_CODE( pcSPS->getSubPicIdLen(), uiCode, "sps_subpic_id[ i ]" ); pcSPS->setSubPicId( picIdx, uiCode ); } } } } else { pcSPS->setSubPicIdMappingExplicitlySignalledFlag( 0 ); pcSPS->setNumSubPics( 1 ); pcSPS->setSubPicCtuTopLeftX( 0, 0 ); pcSPS->setSubPicCtuTopLeftY( 0, 0 ); pcSPS->setSubPicWidth( 0, ( pcSPS->getMaxPicWidthInLumaSamples() + pcSPS->getCTUSize() - 1 ) >> getLog2( pcSPS->getCTUSize() ) ); pcSPS->setSubPicHeight( 0, ( pcSPS->getMaxPicHeightInLumaSamples() + pcSPS->getCTUSize() - 1 ) >> getLog2( pcSPS->getCTUSize() ) ); pcSPS->setSubPicTreatedAsPicFlag( 0, false ); pcSPS->setLoopFilterAcrossSubpicEnabledFlag( 0, true ); } if( !pcSPS->getSubPicIdMappingExplicitlySignalledFlag() || !pcSPS->getSubPicIdMappingInSpsFlag() ) { for( int picIdx = 0; picIdx < pcSPS->getNumSubPics(); picIdx++ ) { pcSPS->setSubPicId( picIdx, picIdx ); } } READ_UVLC( uiCode, "sps_bitdepth_minus8" ); CHECK_RECOVERABLE( uiCode > 8, "Invalid bit depth signalled" ); const Profile::Name profile = pcSPS->getProfileTierLevel()->getProfileIdc(); if( profile != Profile::NONE ) { CHECK_RECOVERABLE( uiCode + 8 > ProfileFeatures::getProfileFeatures( profile )->maxBitDepth, "sps_bitdepth_minus8 exceeds range supported by signalled profile" ); } pcSPS->setBitDepth( CHANNEL_TYPE_LUMA, 8 + uiCode ); pcSPS->setBitDepth( CHANNEL_TYPE_CHROMA, 8 + uiCode); pcSPS->setQpBDOffset( CHANNEL_TYPE_LUMA, (int) (6*uiCode) ); pcSPS->setQpBDOffset( CHANNEL_TYPE_CHROMA, (int) (6*uiCode) ); READ_FLAG( uiCode, "sps_entropy_coding_sync_enabled_flag" ); pcSPS->setEntropyCodingSyncEnabledFlag( uiCode == 1 ); READ_FLAG( uiCode, "sps_entry_point_offsets_present_flag" ); pcSPS->setEntryPointsPresentFlag( uiCode == 1 ); READ_CODE( 4, uiCode, "sps_log2_max_pic_order_cnt_lsb_minus4" ); pcSPS->setBitsForPOC( 4 + uiCode ); CHECK_RECOVERABLE( uiCode > 12, "log2_max_pic_order_cnt_lsb_minus4 shall be in the range of 0 to 12" ); READ_FLAG( uiCode, "sps_poc_msb_cycle_flag" ); pcSPS->setPocMsbFlag( uiCode ? true : false ); if( pcSPS->getPocMsbFlag() ) { READ_UVLC( uiCode, "sps_poc_msb_cycle_len_minus1" ); pcSPS->setPocMsbLen( 1 + uiCode ); CHECK_RECOVERABLE( uiCode > ( 32 - ( pcSPS->getBitsForPOC() - 4 ) - 5 ), "The value of poc_msb_len_minus1 shall be in the range of 0 to 32 - log2_max_pic_order_cnt_lsb_minus4 - 5, inclusive" ); } // extra bits are for future extensions, we will read, but ignore them, // unless a meaning is specified in the spec READ_CODE( 2, uiCode, "sps_num_extra_ph_bytes" ); pcSPS->setNumExtraPHBitsBytes( uiCode ); parseExtraPHBitsStruct( pcSPS, uiCode ); READ_CODE( 2, uiCode, "sps_num_extra_sh_bytes"); pcSPS->setNumExtraSHBitsBytes( uiCode ); parseExtraSHBitsStruct( pcSPS, uiCode ); if( pcSPS->getPtlDpbHrdParamsPresentFlag() ) { if( pcSPS->getMaxTLayers() - 1 > 0 ) { READ_FLAG( uiCode, "sps_sublayer_dpb_params_flag" ); pcSPS->setSubLayerDpbParamsFlag( uiCode ? true : false ); } dpb_parameters( pcSPS->getMaxTLayers() - 1, pcSPS->getSubLayerDpbParamsFlag(), pcSPS ); } unsigned minQT[3] = { 0, 0, 0 }; unsigned maxBTD[3] = { 0, 0, 0 }; unsigned maxBTSize[3] = { 0, 0, 0 }; unsigned maxTTSize[3] = { 0, 0, 0 }; READ_UVLC( uiCode, "sps_log2_min_luma_coding_block_size_minus2" ); int log2MinCUSize = uiCode + 2; pcSPS->setLog2MinCodingBlockSize( log2MinCUSize ); CHECK_RECOVERABLE( uiCode > ctbLog2SizeY - 2, "Invalid log2_min_luma_coding_block_size_minus2 signalled" ); CHECK_RECOVERABLE( log2MinCUSize > std::min( 6, (int)(ctbLog2SizeY) ), "log2_min_luma_coding_block_size_minus2 shall be in the range of 0 to min (4, log2_ctu_size - 2)" ); const int minCuSize = 1 << pcSPS->getLog2MinCodingBlockSize(); CHECK_RECOVERABLE( ( pcSPS->getMaxPicWidthInLumaSamples() % ( std::max( 8, minCuSize ) ) ) != 0, "Coded frame width must be a multiple of Max(8, the minimum unit size)" ); CHECK_RECOVERABLE( ( pcSPS->getMaxPicHeightInLumaSamples() % ( std::max( 8, minCuSize ) ) ) != 0, "Coded frame height must be a multiple of Max(8, the minimum unit size)" ); READ_FLAG( uiCode, "sps_partition_constraints_override_enabled_flag"); pcSPS->setSplitConsOverrideEnabledFlag( uiCode ); READ_UVLC( uiCode, "sps_log2_diff_min_qt_min_cb_intra_slice_luma"); minQT[0] = 1 << ( uiCode + pcSPS->getLog2MinCodingBlockSize() ); CHECK_RECOVERABLE( minQT[0] > 64, "The value of sps_log2_diff_min_qt_min_cb_intra_slice_luma shall be in the range of 0 to min(6,CtbLog2SizeY) - MinCbLog2Size" ); CHECK_RECOVERABLE( minQT[0] > ( 1< 2 * ( ctbLog2SizeY - log2MinCUSize ), "sps_max_mtt_hierarchy_depth_intra_slice_luma shall be in the range 0 to 2*(ctbLog2SizeY - log2MinCUSize)" ); maxTTSize[0] = maxBTSize[0] = minQT[0]; if( maxBTD[0] != 0 ) { READ_UVLC( uiCode, "sps_log2_diff_max_bt_min_qt_intra_slice_luma" ); maxBTSize[0] <<= uiCode; READ_UVLC( uiCode, "sps_log2_diff_max_tt_min_qt_intra_slice_luma" ); maxTTSize[0] <<= uiCode; } if( pcSPS->getChromaFormatIdc() != CHROMA_400 ) { READ_FLAG( uiCode, "sps_qtbtt_dual_tree_intra_flag" ); pcSPS->setUseDualITree( uiCode ); } else { pcSPS->setUseDualITree( 0 ); } if( pcSPS->getUseDualITree() ) { READ_UVLC( uiCode, "sps_log2_diff_min_qt_min_cb_intra_slice_chroma" ); minQT[2] = 1 << ( uiCode + pcSPS->getLog2MinCodingBlockSize() ); READ_UVLC( uiCode, "sps_max_mtt_hierarchy_depth_intra_slice_chroma" ); maxBTD[2] = uiCode; CHECK_RECOVERABLE( uiCode > 2 * ( ctbLog2SizeY - log2MinCUSize ), "sps_max_mtt_hierarchy_depth_intra_slice_chroma shall be in the range 0 to 2*(ctbLog2SizeY - log2MinCUSize)" ); maxTTSize[2] = maxBTSize[2] = minQT[2]; if( maxBTD[2] != 0 ) { READ_UVLC( uiCode, "sps_log2_diff_max_bt_min_qt_intra_slice_chroma" ); maxBTSize[2] <<= uiCode; READ_UVLC( uiCode, "sps_log2_diff_max_tt_min_qt_intra_slice_chroma" ); maxTTSize[2] <<= uiCode; CHECK_RECOVERABLE( maxTTSize[2] > 64, "The value of sps_log2_diff_max_tt_min_qt_intra_slice_chroma shall be in the range of 0 to min(6,CtbLog2SizeY) - MinQtLog2SizeIntraChroma" ); CHECK_RECOVERABLE( maxBTSize[2] > 64, "The value of sps_log2_diff_max_bt_min_qt_intra_slice_chroma shall be in the range of 0 to min(6,CtbLog2SizeY) - MinQtLog2SizeIntraChroma" ); } } READ_UVLC( uiCode, "sps_log2_diff_min_qt_min_cb_inter_slice" ); minQT[1] = 1 << ( uiCode + pcSPS->getLog2MinCodingBlockSize() ); CHECK_RECOVERABLE( maxTTSize[0] > 64, "The value of sps_log2_diff_max_tt_min_qt_intra_slice_luma shall be in the range of 0 to min(6,CtbLog2SizeY) - MinQtLog2SizeIntraY" ); READ_UVLC( uiCode, "sps_max_mtt_hierarchy_depth_inter_slice"); maxBTD[1] = uiCode; CHECK_RECOVERABLE( uiCode > 2 * ( ctbLog2SizeY - log2MinCUSize ), "sps_max_mtt_hierarchy_depth_inter_slice shall be in the range 0 to 2*(ctbLog2SizeY - log2MinCUSize)" ); maxTTSize[1] = maxBTSize[1] = minQT[1]; if( maxBTD[1] != 0 ) { READ_UVLC( uiCode, "sps_log2_diff_max_bt_min_qt_inter_slice" ); maxBTSize[1] <<= uiCode; READ_UVLC( uiCode, "sps_log2_diff_max_tt_min_qt_inter_slice" ); maxTTSize[1] <<= uiCode; CHECK_RECOVERABLE( maxTTSize[1] > 64, "The value of sps_log2_diff_max_tt_min_qt_inter_slice shall be in the range of 0 to min(6,CtbLog2SizeY) - MinQtLog2SizeInterY" ); } pcSPS->setMinQTSizes( minQT ); pcSPS->setMaxBTDepth( maxBTD[1], maxBTD[0], maxBTD[2] ); pcSPS->setMaxBTSize( maxBTSize[1], maxBTSize[0], maxBTSize[2] ); pcSPS->setMaxTTSize( maxTTSize[1], maxTTSize[0], maxTTSize[2] ); if( pcSPS->getCTUSize() > 32 ) { READ_FLAG( uiCode, "sps_max_luma_transform_size_64_flag" ); pcSPS->setLog2MaxTbSize( ( uiCode ? 1 : 0 ) + 5 ); } else { pcSPS->setLog2MaxTbSize( 5 ); } READ_FLAG( uiCode, "sps_transform_skip_enabled_flag" ); pcSPS->setTransformSkipEnabledFlag( uiCode ? true : false ); if( pcSPS->getTransformSkipEnabledFlag() ) { READ_UVLC( uiCode, "sps_log2_transform_skip_max_size_minus2" ); pcSPS->setLog2MaxTransformSkipBlockSize( uiCode + 2 ); READ_FLAG( uiCode, "sps_bdpcm_enabled_flag" ); pcSPS->setBDPCMEnabledFlag( uiCode ? true : false ); } READ_FLAG( uiCode, "sps_mts_enabled_flag" ); pcSPS->setUseMTS( uiCode != 0 ); if( pcSPS->getUseMTS() ) { READ_FLAG( uiCode, "sps_explicit_mts_intra_enabled_flag" ); pcSPS->setUseIntraMTS( uiCode != 0 ); READ_FLAG( uiCode, "sps_explicit_mts_inter_enabled_flag" ); pcSPS->setUseInterMTS( uiCode != 0 ); } READ_FLAG( uiCode, "sps_lfnst_enabled_flag" ); pcSPS->setUseLFNST( uiCode != 0 ); if( pcSPS->getChromaFormatIdc() != CHROMA_400 ) { READ_FLAG( uiCode, "sps_joint_cbcr_enabled_flag" ); pcSPS->setJointCbCrEnabledFlag( uiCode ? true : false ); ChromaQpMappingTableParams chromaQpMappingTableParams; READ_FLAG( uiCode, "sps_same_qp_table_for_chroma_flag" ); chromaQpMappingTableParams.setSameCQPTableForAllChromaFlag( uiCode ); int numQpTables = chromaQpMappingTableParams.getSameCQPTableForAllChromaFlag() ? 1 : ( pcSPS->getJointCbCrEnabledFlag() ? 3 : 2 ); chromaQpMappingTableParams.setNumQpTables( numQpTables ); for( int i = 0; i < numQpTables; i++ ) { int32_t qpTableStart = 0; READ_SVLC( qpTableStart, "sps_qp_table_starts_minus26" ); chromaQpMappingTableParams.setQpTableStartMinus26( i, qpTableStart ); CHECK_RECOVERABLE( qpTableStart < -26 - pcSPS->getQpBDOffset( CHANNEL_TYPE_LUMA ) || qpTableStart > 36, "The value of sps_qp_table_start_minus26[ i ] shall be in the range of -26 - QpBdOffset to 36 inclusive" ); READ_UVLC( uiCode, "sps_num_points_in_qp_table_minus1" ); chromaQpMappingTableParams.setNumPtsInCQPTableMinus1( i, uiCode ); CHECK_RECOVERABLE( uiCode > 36 - qpTableStart, "The value of sps_num_points_in_qp_table_minus1[ i ] shall be in the range of 0 to 36 - sps_qp_table_start_minus26[ i ], inclusive" ); std::vector deltaQpInValMinus1( chromaQpMappingTableParams.getNumPtsInCQPTableMinus1( i ) + 1 ); std::vector deltaQpOutVal( chromaQpMappingTableParams.getNumPtsInCQPTableMinus1( i ) + 1 ); for( int j = 0; j <= chromaQpMappingTableParams.getNumPtsInCQPTableMinus1( i ); j++ ) { READ_UVLC( uiCode, "sps_delta_qp_in_val_minus1" ); deltaQpInValMinus1[j] = uiCode; READ_UVLC( uiCode, "sps_delta_qp_diff_val" ); deltaQpOutVal[j] = uiCode ^ deltaQpInValMinus1[j]; } chromaQpMappingTableParams.setDeltaQpInValMinus1( i, deltaQpInValMinus1 ); chromaQpMappingTableParams.setDeltaQpOutVal( i, deltaQpOutVal ); } pcSPS->setChromaQpMappingTableFromParams( chromaQpMappingTableParams, pcSPS->getQpBDOffset( CHANNEL_TYPE_CHROMA ) ); pcSPS->derivedChromaQPMappingTables(); } READ_FLAG( uiCode, "sps_sao_enabled_flag" ); pcSPS->setUseSAO ( uiCode ); READ_FLAG( uiCode, "sps_alf_enabled_flag" ); pcSPS->setUseALF( uiCode ); if( pcSPS->getUseALF() && pcSPS->getChromaFormatIdc() != CHROMA_400 ) { READ_FLAG( uiCode, "sps_ccalf_enabled_flag" ); pcSPS->setUseCCALF( uiCode ); } else { pcSPS->setUseCCALF( false ); } READ_FLAG( uiCode, "sps_lmcs_enable_flag" ); pcSPS->setUseReshaper( uiCode == 1 ); READ_FLAG( uiCode, "sps_weighted_pred_flag" ); pcSPS->setUseWP( uiCode ? true : false ); READ_FLAG( uiCode, "sps_weighted_bipred_flag" ); pcSPS->setUseWPBiPred( uiCode ? true : false ); READ_FLAG( uiCode, "sps_long_term_ref_pics_flag" ); pcSPS->setLongTermRefsPresent( uiCode ); if( vpsId > 0 ) { READ_FLAG( uiCode, "sps_inter_layer_ref_pics_present_flag" ); pcSPS->setInterLayerPresentFlag( uiCode ); } else { pcSPS->setInterLayerPresentFlag( 0 ); } READ_FLAG( uiCode, "sps_idr_rpl_present_flag" ); pcSPS->setIDRRefParamListPresent( (bool) uiCode ); if( pcSPS->getProfileTierLevel()->getConstraintInfo()->getNoIdrRplConstraintFlag() ) { CHECK_RECOVERABLE( uiCode != 0, "When gci_no_idr_rpl_constraint_flag equal to 1 , the value of sps_idr_rpl_present_flag shall be equal to 0" ); } READ_FLAG( uiCode, "sps_rpl1_same_as_rpl0_flag" ); pcSPS->setRPL1CopyFromRPL0Flag( uiCode ); //Read candidate for List0 READ_UVLC( uiCode, "sps_num_ref_pic_lists[0]" ); uint32_t numberOfRPL = uiCode; RPLList& rplList = pcSPS->createRPLList( 0, numberOfRPL ); for( uint32_t ii = 0; ii < numberOfRPL; ii++ ) { parseRefPicList( &rplList[ii], ii, pcSPS ); } //Read candidate for List1 if( !pcSPS->getRPL1CopyFromRPL0Flag() ) { READ_UVLC( uiCode, "sps_num_ref_pic_lists[1]" ); numberOfRPL = uiCode; RPLList& rplList = pcSPS->createRPLList( 1, numberOfRPL ); for( uint32_t ii = 0; ii < numberOfRPL; ii++ ) { parseRefPicList( &rplList[ii], ii, pcSPS ); } } else { numberOfRPL = ( uint32_t ) pcSPS->getNumRPL( 0 ); const RPLList& rplListSource = pcSPS->getRPLList( 0 ); RPLList& rplListDest = pcSPS->createRPLList( 1, numberOfRPL ); for( uint32_t ii = 0; ii < numberOfRPL; ii++ ) { copyRefPicList( pcSPS, &rplListSource[ii], &rplListDest[ii] ); } } { READ_FLAG( uiCode, "sps_ref_wraparound_enabled_flag" ); pcSPS->setUseWrapAround( uiCode ? true : false ); } READ_FLAG( uiCode, "sps_temporal_mvp_enabled_flag" ); pcSPS->setSPSTemporalMVPEnabledFlag( uiCode ); if( pcSPS->getSPSTemporalMVPEnabledFlag() ) { READ_FLAG( uiCode, "sps_sbtmvp_enabled_flag" ); pcSPS->setSBTMVPEnabledFlag( uiCode != 0 ); } else { pcSPS->setSBTMVPEnabledFlag( false ); } READ_FLAG( uiCode, "sps_amvr_enabled_flag" ); pcSPS->setAMVREnabledFlag ( uiCode != 0 ); READ_FLAG( uiCode, "sps_bdof_enabled_flag" ); pcSPS->setUseBIO ( uiCode != 0 ); if( pcSPS->getUseBIO() ) { READ_FLAG( uiCode, "sps_bdof_control_present_in_ph_flag" ); pcSPS->setBdofControlPresentFlag( uiCode != 0 ); } READ_FLAG( uiCode, "sps_smvd_enabled_flag" ); pcSPS->setUseSMVD( uiCode != 0 ); READ_FLAG( uiCode, "sps_dmvr_enabled_flag" ); pcSPS->setUseDMVR( uiCode != 0 ); if( pcSPS->getUseDMVR() ) { READ_FLAG( uiCode, "sps_dmvr_control_present_in_ph_flag" ); pcSPS->setDmvrControlPresentFlag( uiCode != 0 ); } READ_FLAG( uiCode, "sps_mmvd_enabled_flag" ); pcSPS->setUseMMVD( uiCode != 0 ); if( pcSPS->getUseMMVD() ) { READ_FLAG( uiCode, "sps_mmvd_fullpel_only_flag" ); pcSPS->setFpelMmvdEnabledFlag( uiCode != 0 ); } else { pcSPS->setFpelMmvdEnabledFlag( false ); } READ_UVLC( uiCode, "sps_six_minus_max_num_merge_cand" ); pcSPS->setMaxNumMergeCand( MRG_MAX_NUM_CANDS - uiCode ); CHECK_RECOVERABLE( MRG_MAX_NUM_CANDS <= uiCode, "Incorrrect max number of merge candidates!" ); READ_FLAG( uiCode, "sps_sbt_enabled_flag" ); pcSPS->setUseSBT( uiCode != 0 ); READ_FLAG( uiCode, "sps_affine_enabled_flag" ); pcSPS->setUseAffine( uiCode != 0 ); if( pcSPS->getUseAffine() ) { READ_UVLC( uiCode, "sps_five_minus_max_num_subblock_merge_cand" ); pcSPS->setMaxNumAffineMergeCand( AFFINE_MRG_MAX_NUM_CANDS - uiCode ); CHECK_RECOVERABLE( AFFINE_MRG_MAX_NUM_CANDS < uiCode, "The value of sps_five_minus_max_num_subblock_merge_cand shall be in the " "range of 0 to 5 - sps_sbtmvp_enabled_flag" ); READ_FLAG( uiCode, "sps_affine_type_flag" ); pcSPS->setUseAffineType( uiCode != 0 ); if( pcSPS->getAMVREnabledFlag() ) { READ_FLAG( uiCode, "sps_affine_amvr_enabled_flag" ); pcSPS->setAffineAmvrEnabledFlag( uiCode != 0 ); } READ_FLAG( uiCode, "sps_affine_prof_enabled_flag" ); pcSPS->setUsePROF( uiCode != 0 ); if( pcSPS->getUsePROF() ) { READ_FLAG( uiCode, "sps_prof_control_present_in_ph_flag" ); pcSPS->setProfControlPresentFlag( uiCode != 0 ); } else { pcSPS->setProfControlPresentFlag( false ); } } READ_FLAG( uiCode, "sps_bcw_enabled_flag" ); pcSPS->setUseBcw( uiCode != 0 ); READ_FLAG( uiCode, "sps_ciip_enabled_flag" ); pcSPS->setUseCiip( uiCode != 0 ); if( pcSPS->getMaxNumMergeCand() >= 2 ) { READ_FLAG( uiCode, "sps_gpm_enabled_flag" ); pcSPS->setUseGeo( uiCode != 0 ); if( pcSPS->getUseGeo() && pcSPS->getMaxNumMergeCand() >= 3 ) { READ_UVLC( uiCode, "sps_max_num_merge_cand_minus_max_num_gpm_cand" ); pcSPS->setMaxNumGeoCand( (uint32_t)( pcSPS->getMaxNumMergeCand() - uiCode ) ); CHECK_RECOVERABLE( pcSPS->getMaxNumMergeCand() - 2 < uiCode, "sps_max_num_merge_cand_minus_max_num_gpm_cand must not be " "greater than the number of merge candidates minus 2" ); } else if( pcSPS->getUseGeo() ) { pcSPS->setMaxNumGeoCand( 2 ); } } else { pcSPS->setUseGeo( 0 ); pcSPS->setMaxNumGeoCand( 0 ); } READ_UVLC( uiCode, "sps_log2_parallel_merge_level_minus2" ); pcSPS->setLog2ParallelMergeLevelMinus2( uiCode ); CHECK_RECOVERABLE( uiCode + 2 > ctbLog2SizeY, "The value of sps_log2_parallel_merge_level_minus2 shall be in the range of 0 to ctbLog2SizeY - 2" ); READ_FLAG( uiCode, "sps_isp_enabled_flag" ); pcSPS->setUseISP( uiCode != 0 ); READ_FLAG( uiCode, "sps_mrl_enabled_flag" ); pcSPS->setUseMRL( uiCode != 0 ); READ_FLAG( uiCode, "sps_mip_enabled_flag" ); pcSPS->setUseMIP( uiCode != 0 ); if( pcSPS->getChromaFormatIdc() != CHROMA_400 ) { READ_FLAG( uiCode, "sps_cclm_enabled_flag" ); pcSPS->setUseLMChroma( uiCode != 0 ); } else { pcSPS->setUseLMChroma( 0 ); } if( pcSPS->getChromaFormatIdc() == CHROMA_420 ) { READ_FLAG( uiCode, "sps_chroma_horizontal_collocated_flag" ); pcSPS->setHorCollocatedChromaFlag( uiCode != 0 ); READ_FLAG( uiCode, "sps_chroma_vertical_collocated_flag" ); pcSPS->setVerCollocatedChromaFlag( uiCode != 0 ); } READ_FLAG( uiCode, "sps_palette_enabled_flag" ); CHECK_RECOVERABLE( uiCode != 0, "palette mode is not yet supported" ); if( pcSPS->getChromaFormatIdc() == CHROMA_444 && pcSPS->getLog2MaxTbSize() != 6 ) { READ_FLAG( uiCode, "sps_act_enabled_flag" ); pcSPS->setUseColorTrans( uiCode != 0 ); } else { pcSPS->setUseColorTrans( false ); } // if( pcSPS->getTransformSkipEnabledFlag() || pcSPS->getPLTMode() ) //palette mode not in here if( pcSPS->getTransformSkipEnabledFlag() ) { READ_UVLC( uiCode, "sps_internal_bit_depth_minus_input_bit_depth" ); pcSPS->setInternalMinusInputBitDepth( CHANNEL_TYPE_LUMA, uiCode ); CHECK_RECOVERABLE( uiCode > 8, "Invalid sps_internal_bit_depth_minus_input_bit_depth signalled" ); pcSPS->setInternalMinusInputBitDepth( CHANNEL_TYPE_CHROMA, uiCode ); } READ_FLAG( uiCode, "sps_ibc_enabled_flag" ); pcSPS->setIBCFlag( uiCode ); if( pcSPS->getIBCFlag() ) { READ_UVLC( uiCode, "sps_six_minus_max_num_ibc_merge_cand" ); pcSPS->setMaxNumIBCMergeCand( IBC_MRG_MAX_NUM_CANDS - uiCode ); CHECK_RECOVERABLE( IBC_MRG_MAX_NUM_CANDS <= uiCode, "Incorrect max number of IBC merge candidates!" ); } else { pcSPS->setMaxNumIBCMergeCand( 0 ); } #if LUMA_ADAPTIVE_DEBLOCKING_FILTER_QP_OFFSET READ_FLAG( uiCode, "sps_ladf_enabled_flag" ); pcSPS->setLadfEnabled( uiCode != 0 ); if( pcSPS->getLadfEnabled() ) { int signedSymbol = 0; READ_CODE( 2, uiCode, "sps_num_ladf_intervals_minus2" ); pcSPS->setLadfNumIntervals( uiCode + 2 ); READ_SVLC( signedSymbol, "sps_ladf_lowest_interval_qp_offset" ); pcSPS->setLadfQpOffset( signedSymbol, 0 ); for( int k = 1; k < pcSPS->getLadfNumIntervals(); k++ ) { READ_SVLC( signedSymbol, "sps_ladf_qp_offset[i]" ); pcSPS->setLadfQpOffset( signedSymbol, k ); READ_UVLC( uiCode, "sps_ladf_delta_threshold_minus1[i]" ); pcSPS->setLadfIntervalLowerBound( uiCode + pcSPS->getLadfIntervalLowerBound( k - 1 ) + 1, k ); } } #endif READ_FLAG( uiCode, "sps_explicit_scaling_list_enabled_flag" ); pcSPS->setScalingListFlag ( uiCode ); if( pcSPS->getProfileTierLevel()->getConstraintInfo()->getNoExplicitScaleListConstraintFlag() ) { CHECK_RECOVERABLE( uiCode != 0, "When gci_no_explicit_scaling_list_constraint_flag is equal to 1, sps_explicit_scaling_list_enabled_flag shall be equal to 0" ); } if( pcSPS->getUseLFNST() && pcSPS->getScalingListFlag() ) { READ_FLAG( uiCode, "sps_scaling_matrix_for_lfnst_disabled_flag" ); pcSPS->setDisableScalingMatrixForLfnstBlks( uiCode ? true : false ); } if( pcSPS->getUseColorTrans() && pcSPS->getScalingListFlag() ) { READ_FLAG( uiCode, "sps_scaling_matrix_for_alternative_colour_space_disabled_flag"); pcSPS->setScalingMatrixForAlternativeColourSpaceDisabledFlag( uiCode ); } if( pcSPS->getScalingMatrixForAlternativeColourSpaceDisabledFlag() ) { READ_FLAG(uiCode, "sps_scaling_matrix_designated_colour_space_flag"); pcSPS->setScalingMatrixDesignatedColourSpaceFlag( uiCode ); } READ_FLAG( uiCode, "sps_dep_quant_enabled_flag" ); pcSPS->setDepQuantEnabledFlag( uiCode ); READ_FLAG( uiCode, "sps_sign_data_hiding_enabled_flag" ); pcSPS->setSignDataHidingEnabledFlag( uiCode ); READ_FLAG( uiCode, "sps_virtual_boundaries_enabled_flag" ); pcSPS->setVirtualBoundariesEnabledFlag( uiCode != 0 ); if( pcSPS->getProfileTierLevel()->getConstraintInfo()->getNoVirtualBoundaryConstraintFlag() ) { CHECK_RECOVERABLE( uiCode != 0, "When gci_no_virtual_boundaries_constraint_flag is equal to 1, sps_virtual_boundaries_enabled_flag shall be equal to 0" ); } if( pcSPS->getVirtualBoundariesEnabledFlag() ) { READ_FLAG( uiCode, "sps_loop_filter_across_virtual_boundaries_present_flag" ); pcSPS->setVirtualBoundariesPresentFlag( uiCode != 0 ); if( pcSPS->getVirtualBoundariesPresentFlag() ) { READ_UVLC( uiCode, "sps_num_ver_virtual_boundaries" ); pcSPS->setNumVerVirtualBoundaries( uiCode ); if( pcSPS->getMaxPicWidthInLumaSamples() <= 8 ) { CHECK_RECOVERABLE( pcSPS->getNumVerVirtualBoundaries() != 0, "SPS: When picture width is less than or equal to 8, the number of vertical virtual boundaries shall be equal to 0" ); } else { CHECK_RECOVERABLE( pcSPS->getNumVerVirtualBoundaries() > 3, "SPS: The number of vertical virtual boundaries shall be in the range of 0 to 3" ); } for( unsigned i = 0; i < pcSPS->getNumVerVirtualBoundaries(); i++ ) { READ_UVLC( uiCode, "sps_virtual_boundary_pos_x_minus1[i]" ); pcSPS->setVirtualBoundariesPosX( (uiCode + 1) << 3, i ); CHECK_RECOVERABLE( uiCode > ( ( ( pcSPS->getMaxPicWidthInLumaSamples() + 7 ) >> 3 ) - 2 ), "The value of sps_virtual_boundary_pos_x_minus1[ i ] shall be in the range of 0 to Ceil( sps_pic_width_max_in_luma_samples / 8 ) - 2, inclusive." ); } READ_UVLC( uiCode, "sps_num_hor_virtual_boundaries" ); pcSPS->setNumHorVirtualBoundaries( uiCode ); if( pcSPS->getMaxPicHeightInLumaSamples() <= 8 ) { CHECK_RECOVERABLE( pcSPS->getNumHorVirtualBoundaries() != 0, "SPS: When picture height is less than or equal to 8, the number of horizontal virtual boundaries shall be equal to 0" ); } else { CHECK_RECOVERABLE( pcSPS->getNumHorVirtualBoundaries() > 3, "SPS: The number of horizontal virtual boundaries shall be in the range of 0 to 3" ); } for( unsigned i = 0; i < pcSPS->getNumHorVirtualBoundaries(); i++ ) { READ_UVLC( uiCode, "sps_virtual_boundary_pos_y_minus1[i]" ); pcSPS->setVirtualBoundariesPosY( (uiCode + 1) << 3, i ); CHECK_RECOVERABLE( uiCode > ( ( ( pcSPS->getMaxPicHeightInLumaSamples() + 7 ) >> 3 ) - 2 ), "The value of sps_virtual_boundary_pos_y_minus1[ i ] shall be in the range of 0 to Ceil( sps_pic_height_max_in_luma_samples / 8 ) - 2, inclusive." ); } } else { pcSPS->setNumVerVirtualBoundaries( 0 ); pcSPS->setNumHorVirtualBoundaries( 0 ); } } else { pcSPS->setVirtualBoundariesPresentFlag( false ); } if( pcSPS->getPtlDpbHrdParamsPresentFlag() ) { READ_FLAG( uiCode, "sps_timing_hrd_params_present_flag" ); pcSPS->setGeneralHrdParametersPresentFlag( uiCode ); if( pcSPS->getGeneralHrdParametersPresentFlag() ) { parseGeneralHrdParameters( pcSPS->getGeneralHrdParameters() ); if( ( pcSPS->getMaxTLayers() - 1 ) > 0 ) { READ_FLAG( uiCode, "sps_sublayer_cpb_params_present_flag" ); pcSPS->setSubLayerParametersPresentFlag( uiCode ); } else if( ( pcSPS->getMaxTLayers() - 1 ) == 0 ) { pcSPS->setSubLayerParametersPresentFlag( 0 ); } uint32_t firstSubLayer = pcSPS->getSubLayerParametersPresentFlag() ? 0 : ( pcSPS->getMaxTLayers() - 1 ); parseOlsHrdParameters( pcSPS->getGeneralHrdParameters(), pcSPS->getOlsHrdParameters(), firstSubLayer, pcSPS->getMaxTLayers() - 1 ); } } READ_FLAG( uiCode, "sps_field_seq_flag"); pcSPS->setFieldSeqFlag( uiCode ); CHECK_RECOVERABLE( pcSPS->getProfileTierLevel()->getFrameOnlyConstraintFlag() && uiCode, "When ptl_frame_only_constraint_flag equal to 1 , the value of sps_field_seq_flag shall be equal to 0" ); READ_FLAG( uiCode, "sps_vui_parameters_present_flag" ); pcSPS->setVuiParametersPresentFlag( uiCode ); if( pcSPS->getVuiParametersPresentFlag() ) { READ_UVLC( uiCode, "sps_vui_payload_size_minus1" ); pcSPS->setVuiPayloadSize( uiCode+1 ); while( !isByteAligned() ) { READ_FLAG( uiCode, "sps_vui_alignment_zero_bit" ); CHECK_RECOVERABLE( uiCode != 0, "sps_vui_alignment_zero_bit not equal to 0" ); } parseVUI( pcSPS->getVuiParameters(), pcSPS ); } READ_FLAG( uiCode, "sps_extension_present_flag" ); if( uiCode ) { while( xMoreRbspData() ) { READ_FLAG( uiCode, "sps_extension_data_flag" ); } } xReadRbspTrailingBits(); } void HLSyntaxReader::parseDCI( DCI* dci ) { #if ENABLE_TRACING xTraceDCIHeader(); #endif uint32_t symbol; READ_CODE( 4, symbol, "dci_reserved_zero_4bits" ); uint32_t numPTLs; READ_CODE( 4, numPTLs, "dci_num_ptls_minus1" ); numPTLs += 1; std::vector ptls; ptls.resize(numPTLs); for( int i = 0; i < numPTLs; i++ ) { parseProfileTierLevel( &ptls[i], true, 0 ); } dci->setProfileTierLevel( ptls ); READ_FLAG( symbol, "dci_extension_flag" ); if( symbol ) { while( xMoreRbspData() ) { READ_FLAG( symbol, "dci_extension_data_flag" ); } } xReadRbspTrailingBits(); } void HLSyntaxReader::parseVPS( VPS* pcVPS ) { #if ENABLE_TRACING xTraceVPSHeader(); #endif uint32_t uiCode; //CHECK_RECOVERABLE( true, "needs to be adjusted, e.g. sublayer and independent layer stuff -> see VTM-9.0" ); READ_CODE( 4, uiCode, "vps_video_parameter_set_id" ); pcVPS->setVPSId( uiCode ); CHECK_RECOVERABLE( uiCode == 0, "vps_video_parameter_set_id equal to zero is reserved and shall not be used in a bitstream" ); READ_CODE( 6, uiCode, "vps_max_layers_minus1" ); pcVPS->setMaxLayers( uiCode + 1 ); CHECK_RECOVERABLE( uiCode + 1 > MAX_VPS_LAYERS, "Signalled number of layers larger than MAX_VPS_LAYERS." ); if( pcVPS->getMaxLayers() - 1 == 0 ) { pcVPS->setEachLayerIsAnOlsFlag( 1 ); } READ_CODE( 3, uiCode, "vps_max_sublayers_minus1" ); pcVPS->setMaxSubLayers( uiCode + 1 ); CHECK_RECOVERABLE( uiCode + 1 > MAX_VPS_SUBLAYERS, "Signalled number of sublayers larger than MAX_VPS_SUBLAYERS." ); if( pcVPS->getMaxLayers() > 1 && pcVPS->getMaxSubLayers() > 1 ) { READ_FLAG( uiCode, "vps_default_ptl_dpb_hrd_max_tid_flag" ); pcVPS->setAllLayersSameNumSublayersFlag( uiCode ); } else { pcVPS->setAllLayersSameNumSublayersFlag( 1 ); } if( pcVPS->getMaxLayers() > 1 ) { READ_FLAG( uiCode, "vps_all_independent_layers_flag" ); pcVPS->setAllIndependentLayersFlag( uiCode ); if( pcVPS->getAllIndependentLayersFlag() == 0 ) { pcVPS->setEachLayerIsAnOlsFlag( 0 ); } } for( uint32_t i = 0; i < pcVPS->getMaxLayers(); i++ ) { READ_CODE( 6, uiCode, "vps_layer_id[i]" ); pcVPS->setLayerId( i, uiCode ); pcVPS->setGeneralLayerIdx( uiCode, i ); if( i > 0 && !pcVPS->getAllIndependentLayersFlag() ) { READ_FLAG( uiCode, "vps_independent_layer_flag[i]" ); pcVPS->setIndependentLayerFlag( i, uiCode ); if( !pcVPS->getIndependentLayerFlag( i ) ) { READ_FLAG( uiCode, "vps_max_tid_ref_present_flag[i]" ); bool vpsMaxTidRefPresentFlag = ( uiCode == 1 ); uint16_t sumUiCode = 0; for( int j = 0, k = 0; j < i; j++ ) { READ_FLAG( uiCode, "vps_direct_ref_layer_flag[ i ][ j ]" ); pcVPS->setDirectRefLayerFlag( i, j, uiCode ); if( uiCode ) { pcVPS->setInterLayerRefIdc( i, j, k ); pcVPS->setDirectRefLayerIdx( i, k++, j ); sumUiCode++; if( vpsMaxTidRefPresentFlag ) { READ_CODE( 3, uiCode, "vps_max_tid_il_ref_pics_plus1[i][ j ]" ); // pcVPS->setMaxTidIlRefPicsPlus1( i, uiCode ); } } } CHECK_RECOVERABLE(sumUiCode == 0, "There has to be at least one value of j such that the value of vps_direct_dependency_flag[i][ j ] is equal to 1,when vps_independent_layer_flag[i] is equal to 0 " ); // if( uiCode ) // { // READ_CODE( 3, uiCode, "max_tid_il_ref_pics_plus1[i]" ); pcVPS->setMaxTidIlRefPicsPlus1( i, uiCode ); // } // else // { // pcVPS->setMaxTidIlRefPicsPlus1( i, 7) ; // } } } } if( pcVPS->getMaxLayers() > 1 ) { if( pcVPS->getAllIndependentLayersFlag() ) { READ_FLAG( uiCode, "vps_each_layer_is_an_ols_flag" ); pcVPS->setEachLayerIsAnOlsFlag( uiCode ); if( pcVPS->getEachLayerIsAnOlsFlag() == 0 ) { pcVPS->setOlsModeIdc( 2 ); } } if( !pcVPS->getEachLayerIsAnOlsFlag() ) { if( !pcVPS->getAllIndependentLayersFlag() ) { READ_CODE( 2, uiCode, "vps_ols_mode_idc" ); pcVPS->setOlsModeIdc( uiCode ); CHECK_RECOVERABLE( uiCode > MAX_VPS_OLS_MODE_IDC, "ols_mode_idc shall be in the rage of 0 to 2" ); } if( pcVPS->getOlsModeIdc() == 2 ) { READ_CODE( 8, uiCode, "vps_num_output_layer_sets_minus2" ); pcVPS->setNumOutputLayerSets( uiCode + 2 ); for( uint32_t i = 1; i <= pcVPS->getNumOutputLayerSets() - 1; i++ ) { for( uint32_t j = 0; j < pcVPS->getMaxLayers(); j++ ) { READ_FLAG( uiCode, "vps_ols_output_layer_flag[i][ j ]" ); pcVPS->setOlsOutputLayerFlag( i, j, uiCode ); } } } } READ_CODE( 8, uiCode, "vps_num_ptls_minus1" ); pcVPS->setNumPtls( uiCode + 1 ); } else { pcVPS->setNumPtls( 1 ); } pcVPS->deriveOutputLayerSets(); CHECK_RECOVERABLE( uiCode >= pcVPS->getTotalNumOLSs(), "The value of vps_num_ptls_minus1 shall be less than TotalNumOlss" ); std::vector isPTLReferred( pcVPS->getNumPtls(), false ); for( int i = 0; i < pcVPS->getNumPtls(); i++ ) { if( i > 0 ) { READ_FLAG( uiCode, "pt_present_flag[i]" ); pcVPS->setPtPresentFlag( i, uiCode ); } else { pcVPS->setPtPresentFlag( 0, 1 ); } if( !pcVPS->getAllLayersSameNumSublayersFlag() ) { READ_CODE( 3, uiCode, "ptl_max_tid[i]" ); pcVPS->setPtlMaxTemporalId( i, uiCode ); } else { pcVPS->setPtlMaxTemporalId( i, pcVPS->getMaxSubLayers() - 1 ); } } int cnt = 0; while( m_pcBitstream->getNumBitsUntilByteAligned() ) { READ_FLAG( uiCode, "vps_ptl_reserved_zero_bit" ); CHECK_RECOVERABLE( uiCode!=0, "Alignment bit is not '0'" ); cnt++; } CHECK_RECOVERABLE( cnt >= 8, "Read more than '8' alignment bits" ); std::vector ptls; ptls.resize( pcVPS->getNumPtls() ); for( int i = 0; i < pcVPS->getNumPtls(); i++ ) { parseProfileTierLevel( &ptls[i], pcVPS->getPtPresentFlag( i ), pcVPS->getPtlMaxTemporalId( i ) ); } pcVPS->setProfileTierLevel( ptls ); for( int i = 0; i < pcVPS->getTotalNumOLSs(); i++ ) { if( pcVPS->getNumPtls() > 1 && pcVPS->getNumPtls() != pcVPS->getTotalNumOLSs() ) { READ_CODE( 8, uiCode, "vps_ols_ptl_idx[i]" ); pcVPS->setOlsPtlIdx( i, uiCode ); } else if( pcVPS->getNumPtls() == pcVPS->getTotalNumOLSs() ) { pcVPS->setOlsPtlIdx( i, i ); } else { pcVPS->setOlsPtlIdx( i, 0 ); } isPTLReferred[pcVPS->getOlsPtlIdx( i )] = true; } for( int i = 0; i < pcVPS->getNumPtls(); i++ ) { CHECK_RECOVERABLE( !isPTLReferred[i],"Each profile_tier_level( ) syntax structure in the VPS shall be referred to by at least one value of vps_ols_ptl_idx[i] for i in the range of 0 to TotalNumOlss ? 1, inclusive" ); } if( !pcVPS->getEachLayerIsAnOlsFlag() ) { READ_UVLC( uiCode, "vps_num_dpb_params_minus1" ); pcVPS->m_numDpbParams = uiCode + 1; CHECK_RECOVERABLE( pcVPS->m_numDpbParams > pcVPS->getNumMultiLayeredOlss(), "The value of vps_num_dpb_params_minus1 shall be in the range of 0 to NumMultiLayerOlss - 1, inclusive" ); std::vector isDPBParamReferred( pcVPS->m_numDpbParams, false ); if( pcVPS->m_numDpbParams > 0 && pcVPS->getMaxSubLayers() > 1 ) { READ_FLAG( uiCode, "vps_sublayer_dpb_params_present_flag" ); pcVPS->m_sublayerDpbParamsPresentFlag = uiCode; } pcVPS->m_dpbParameters.resize( pcVPS->m_numDpbParams ); for( int i = 0; i < pcVPS->m_numDpbParams; i++ ) { if( !pcVPS->getAllLayersSameNumSublayersFlag() ) { READ_CODE( 3, uiCode, "vps_dpb_max_tid[i]" ); pcVPS->m_dpbMaxTemporalId.push_back( uiCode ); CHECK_RECOVERABLE( uiCode > ( pcVPS->getMaxSubLayers() - 1 ), "The value of vps_dpb_max_tid[i] shall be in the range of 0 to vps_max_sublayers_minus1, inclusive." ) } else { pcVPS->m_dpbMaxTemporalId.push_back( pcVPS->getMaxSubLayers() - 1 ); } for( int j = ( pcVPS->m_sublayerDpbParamsPresentFlag ? 0 : pcVPS->m_dpbMaxTemporalId[i] ); j <= pcVPS->m_dpbMaxTemporalId[i]; j++ ) { READ_UVLC( uiCode, "dpb_max_dec_pic_buffering_minus1[i]" ); pcVPS->m_dpbParameters[i].m_maxDecPicBuffering[j] = uiCode + 1; READ_UVLC( uiCode, "dpb_max_num_reorder_pics[i]" ); pcVPS->m_dpbParameters[i].m_numReorderPics[j] = uiCode; READ_UVLC( uiCode, "dpb_max_latency_increase_plus1[i]" ); pcVPS->m_dpbParameters[i].m_maxLatencyIncreasePlus1[j] = uiCode; } for( int j = ( pcVPS->m_sublayerDpbParamsPresentFlag ? pcVPS->m_dpbMaxTemporalId[i] : 0 ); j < pcVPS->m_dpbMaxTemporalId[i]; j++ ) { // When max_dec_pic_buffering_minus1[i] is not present for i in the range of 0 to maxSubLayersMinus1 - 1, inclusive, due to subLayerInfoFlag being equal to 0, it is inferred to be equal to max_dec_pic_buffering_minus1[ maxSubLayersMinus1 ]. pcVPS->m_dpbParameters[i].m_maxDecPicBuffering[j] = pcVPS->m_dpbParameters[i].m_maxDecPicBuffering[pcVPS->m_dpbMaxTemporalId[i]]; // When max_num_reorder_pics[i] is not present for i in the range of 0 to maxSubLayersMinus1 - 1, inclusive, due to subLayerInfoFlag being equal to 0, it is inferred to be equal to max_num_reorder_pics[ maxSubLayersMinus1 ]. pcVPS->m_dpbParameters[i].m_numReorderPics[j] = pcVPS->m_dpbParameters[i].m_numReorderPics[pcVPS->m_dpbMaxTemporalId[i]]; // When max_latency_increase_plus1[i] is not present for i in the range of 0 to maxSubLayersMinus1 - 1, inclusive, due to subLayerInfoFlag being equal to 0, it is inferred to be equal to max_latency_increase_plus1[ maxSubLayersMinus1 ]. pcVPS->m_dpbParameters[i].m_maxLatencyIncreasePlus1[j] = pcVPS->m_dpbParameters[i].m_maxLatencyIncreasePlus1[pcVPS->m_dpbMaxTemporalId[i]]; } } for( int i = 0, j=0; i < pcVPS->getTotalNumOLSs(); i++ ) { if( pcVPS->m_numLayersInOls[i] > 1 ) { READ_UVLC( uiCode, "vps_ols_dpb_pic_width[i]" ); pcVPS->setOlsDpbPicWidth( i, uiCode ); READ_UVLC( uiCode, "vps_ols_dpb_pic_height[i]" ); pcVPS->setOlsDpbPicHeight( i, uiCode ); READ_CODE( 2, uiCode, "vps_ols_dpb_chroma_format[i]" ); pcVPS->setOlsDpbChromaFormatIdc( i, uiCode ); READ_UVLC( uiCode, "vps_ols_dpb_bitdepth_minus8[i]" ); pcVPS->setOlsDpbBitDepthMinus8( i, uiCode ); const Profile::Name profile = pcVPS->getProfileTierLevel( pcVPS->getOlsPtlIdx( i ) ).getProfileIdc(); if( profile != Profile::NONE ) { CHECK_RECOVERABLE( uiCode + 8 > ProfileFeatures::getProfileFeatures( profile )->maxBitDepth, "vps_ols_dpb_bitdepth_minus8[ i ] exceeds range supported by signalled profile" ); } if( ( pcVPS->m_numDpbParams > 1 ) && ( pcVPS->m_numDpbParams != pcVPS->m_numMultiLayeredOlss) ) { READ_UVLC( uiCode, "vps_ols_dpb_params_idx[i]" ); pcVPS->setOlsDpbParamsIdx( i, uiCode ); } else if( pcVPS->m_numDpbParams == 1 ) { pcVPS->setOlsDpbParamsIdx( i, 0 ); } else { pcVPS->setOlsDpbParamsIdx( i, j ); } j += 1; isDPBParamReferred[pcVPS->getOlsDpbParamsIdx( i )] = true; } } for( int i = 0; i < pcVPS->m_numDpbParams; i++ ) { CHECK_RECOVERABLE( !isDPBParamReferred[i], "Each dpb_parameters() syntax structure in the VPS shall be referred to by at least one value of vps_ols_dpb_params_idx[i] for i in the range of 0 to NumMultiLayerOlss - 1, inclusive" ); } } if( !pcVPS->getEachLayerIsAnOlsFlag() ) { READ_FLAG( uiCode, "vps_general_hrd_params_present_flag" ); pcVPS->setVPSGeneralHrdParamsPresentFlag( uiCode ); } if( pcVPS->getVPSGeneralHrdParamsPresentFlag() ) { parseGeneralHrdParameters( pcVPS->getGeneralHrdParameters() ); if( ( pcVPS->getMaxSubLayers() - 1 ) > 0 ) { READ_FLAG( uiCode, "vps_sublayer_cpb_params_present_flag" ); pcVPS->setVPSSublayerCpbParamsPresentFlag( uiCode ); } else { pcVPS->setVPSSublayerCpbParamsPresentFlag( 0 ); } READ_UVLC( uiCode, "vps_num_ols_hrd_params_minus1" ); pcVPS->setNumOlsHrdParamsMinus1( uiCode ); CHECK_RECOVERABLE( uiCode >= pcVPS->getNumMultiLayeredOlss(), "The value of vps_num_ols_hrd_params_minus1 shall be in the range of 0 to NumMultiLayerOlss - 1, inclusive" ); std::vector isHRDParamReferred( uiCode + 1, false ); pcVPS->m_olsHrdParams.clear(); pcVPS->m_olsHrdParams.resize( pcVPS->getNumOlsHrdParamsMinus1(), std::vector( pcVPS->getMaxSubLayers() ) ); for( int i = 0; i <= pcVPS->getNumOlsHrdParamsMinus1(); i++ ) { if( !pcVPS->getAllLayersSameNumSublayersFlag() ) { READ_CODE( 3, uiCode, "vps_hrd_max_tid[i]" ); pcVPS->setHrdMaxTid(i, uiCode ); CHECK_RECOVERABLE( uiCode > ( pcVPS->getMaxSubLayers() - 1 ), "The value of vps_hrd_max_tid[i] shall be in the range of 0 to vps_max_sublayers_minus1, inclusive." ); } else { pcVPS->setHrdMaxTid( i, pcVPS->getMaxSubLayers() - 1 ); } uint32_t firstSublayer = pcVPS->getVPSSublayerCpbParamsPresentFlag() ? 0 : pcVPS->getHrdMaxTid( i ); parseOlsHrdParameters( pcVPS->getGeneralHrdParameters(),pcVPS->getOlsHrdParameters( i ), firstSublayer, pcVPS->getHrdMaxTid( i ) ); } for( int i = pcVPS->getNumOlsHrdParamsMinus1() + 1; i < pcVPS->getTotalNumOLSs(); i++ ) { pcVPS->setHrdMaxTid( i, pcVPS->getMaxSubLayers() - 1 ); } for( int i = 0; i < pcVPS->m_numMultiLayeredOlss; i++ ) { if( ( ( pcVPS->getNumOlsHrdParamsMinus1() + 1 ) != pcVPS->m_numMultiLayeredOlss ) && ( pcVPS->getNumOlsHrdParamsMinus1() > 0 ) ) { READ_UVLC( uiCode, "vps_ols_hrd_idx[i]" ); pcVPS->setOlsHrdIdx( i, uiCode ); CHECK_RECOVERABLE( uiCode > pcVPS->getNumOlsHrdParamsMinus1(), "The value of ols_hrd_idx[[i] shall be in the range of 0 to num_ols_hrd_params_minus1, inclusive." ); } else if( pcVPS->getNumOlsHrdParamsMinus1() == 0 ) { pcVPS->setOlsHrdIdx( i, 0 ); } else { pcVPS->setOlsHrdIdx( i, i ); } isHRDParamReferred[pcVPS->getOlsHrdIdx( i )] = true; } for( int i = 0; i <= pcVPS->getNumOlsHrdParamsMinus1(); i++ ) { CHECK_RECOVERABLE( !isHRDParamReferred[i], "Each ols_hrd_parameters( ) syntax structure in the VPS shall be referred to by at least one value of vps_ols_hrd_idx[i] for i in the range of 1 to NumMultiLayerOlss - 1, inclusive"); } } else { for( int i = 0; i < pcVPS->getTotalNumOLSs(); i++ ) { pcVPS->setHrdMaxTid( i, pcVPS->getMaxSubLayers() - 1 ); } } READ_FLAG( uiCode, "vps_extension_flag" ); if( uiCode ) { while( xMoreRbspData() ) { READ_FLAG( uiCode, "vps_extension_data_flag" ); } } pcVPS->checkVPS(); xReadRbspTrailingBits(); } void HLSyntaxReader::parsePictureHeader( PicHeader* picHeader, const ParameterSetManager *parameterSetManager, bool readRbspTrailingBits ) { uint32_t uiCode = 0; int iCode = 0; #if ENABLE_TRACING xTracePictureHeader(); #endif READ_FLAG( uiCode, "ph_gdr_or_irap_pic_flag" ); picHeader->setGdrOrIrapPicFlag( uiCode != 0 ); READ_FLAG( uiCode, "ph_non_ref_pic_flag" ); picHeader->setNonReferencePictureFlag( uiCode != 0 ); if( picHeader->getGdrOrIrapPicFlag() ) { READ_FLAG( uiCode, "ph_gdr_pic_flag" ); picHeader->setGdrPicFlag( uiCode != 0 ); } else { picHeader->setGdrPicFlag( false ); } READ_FLAG( uiCode, "ph_inter_slice_allowed_flag" ); picHeader->setPicInterSliceAllowedFlag( uiCode != 0 ); if( picHeader->getPicInterSliceAllowedFlag() ) { READ_FLAG( uiCode, "ph_intra_slice_allowed_flag" ); picHeader->setPicIntraSliceAllowedFlag( uiCode != 0 ); } else { picHeader->setPicIntraSliceAllowedFlag( true ); } CHECK_RECOVERABLE( picHeader->getPicInterSliceAllowedFlag() == 0 && picHeader->getPicIntraSliceAllowedFlag() == 0, "Invalid picture without intra or inter slice" ); // parameter sets READ_UVLC( uiCode, "ph_pic_parameter_set_id" ); picHeader->setPPSId( uiCode ); const PPS* pps = parameterSetManager->getPPS( picHeader->getPPSId() ); CHECK_RECOVERABLE( pps == 0, "Invalid PPS" ); picHeader->setSPSId( pps->getSPSId() ); const SPS* sps = parameterSetManager->getSPS( picHeader->getSPSId() ); CHECK_RECOVERABLE( sps == 0, "Invalid SPS" ); READ_CODE( sps->getBitsForPOC(), uiCode, "ph_pic_order_cnt_lsb" ); picHeader->setPocLsb( uiCode ); if( picHeader->getGdrPicFlag() ) { READ_UVLC( uiCode, "ph_recovery_poc_cnt" ); picHeader->setRecoveryPocCnt( uiCode ); } else { picHeader->setRecoveryPocCnt( -1 ); } std::vector phExtraBitsPresent = sps->getExtraPHBitPresentFlags(); for( int i=0; i< sps->getNumExtraPHBitsBytes() * 8; i++ ) { // extra bits are ignored (when present) if( phExtraBitsPresent[i] ) { READ_FLAG( uiCode, "ph_extra_bit[i]" ); } } if( sps->getPocMsbFlag() ) { READ_FLAG( uiCode, "ph_poc_msb_cycle_present_flag" ); picHeader->setPocMsbPresentFlag( uiCode != 0 ); if( picHeader->getPocMsbPresentFlag() ) { READ_CODE( sps->getPocMsbLen(), uiCode, "ph_poc_msb_cycle_val" ); picHeader->setPocMsbVal( uiCode ); } } // alf enable flags and aps IDs picHeader->setCcAlfEnabledFlag( COMPONENT_Cb, false ); picHeader->setCcAlfEnabledFlag( COMPONENT_Cr, false ); if( sps->getUseALF() ) { if( pps->getAlfInfoInPhFlag() ) { READ_FLAG( uiCode, "ph_alf_enabled_flag" ); picHeader->setAlfEnabledFlag( COMPONENT_Y, uiCode ); int alfCbEnabledFlag = 0; int alfCrEnabledFlag = 0; if( uiCode ) { READ_CODE( 3, uiCode, "ph_num_alf_aps_ids_luma" ); int numAps = uiCode; picHeader->setNumAlfAps( numAps ); std::vector apsId( numAps, -1 ); for( int i = 0; i < numAps; i++ ) { READ_CODE( 3, uiCode, "ph_alf_aps_id_luma[i]" ); apsId[i] = uiCode; } picHeader->setAlfAPSIds( std::move( apsId ) ); if( sps->getChromaFormatIdc() != CHROMA_400 ) { READ_CODE( 1, uiCode, "ph_alf_cb_enabled_flag" ); alfCbEnabledFlag = uiCode; READ_CODE( 1, uiCode, "ph_alf_cr_enabled_flag" ); alfCrEnabledFlag = uiCode; } else { alfCbEnabledFlag = 0; alfCrEnabledFlag = 0; } if( alfCbEnabledFlag || alfCrEnabledFlag ) { READ_CODE( 3, uiCode, "ph_alf_aps_id_chroma" ); picHeader->setAlfApsIdChroma( uiCode ); } if( sps->getUseCCALF() ) { READ_FLAG( uiCode, "ph_cc_alf_cb_enabled_flag" ); picHeader->setCcAlfEnabledFlag( COMPONENT_Cb, uiCode != 0 ); picHeader->setCcAlfCbApsId( -1 ); if( picHeader->getCcAlfEnabledFlag( COMPONENT_Cb ) ) { // parse APS ID READ_CODE( 3, uiCode, "ph_cc_alf_cb_aps_id" ); picHeader->setCcAlfCbApsId( uiCode ); } // Cr READ_FLAG( uiCode, "ph_cc_alf_cr_enabled_flag" ); picHeader->setCcAlfEnabledFlag( COMPONENT_Cr, uiCode != 0 ); picHeader->setCcAlfCrApsId( -1 ); if( picHeader->getCcAlfEnabledFlag( COMPONENT_Cr ) ) { // parse APS ID READ_CODE( 3, uiCode, "ph_cc_alf_cr_aps_id" ); picHeader->setCcAlfCrApsId( uiCode ); } } } else { picHeader->setNumAlfAps( 0 ); } picHeader->setAlfEnabledFlag( COMPONENT_Cb, alfCbEnabledFlag ); picHeader->setAlfEnabledFlag( COMPONENT_Cr, alfCrEnabledFlag ); } else { picHeader->setAlfEnabledFlag( COMPONENT_Y, true ); picHeader->setAlfEnabledFlag( COMPONENT_Cb, true ); picHeader->setAlfEnabledFlag( COMPONENT_Cr, true ); } } else { picHeader->setAlfEnabledFlag( COMPONENT_Y, false ); picHeader->setAlfEnabledFlag( COMPONENT_Cb, false ); picHeader->setAlfEnabledFlag( COMPONENT_Cr, false ); } // luma mapping / chroma scaling controls if( sps->getUseReshaper() ) { READ_FLAG( uiCode, "ph_lmcs_enabled_flag" ); picHeader->setLmcsEnabledFlag( uiCode != 0 ); if( picHeader->getLmcsEnabledFlag() ) { READ_CODE( 2, uiCode, "ph_lmcs_aps_id" ); picHeader->setLmcsAPSId( uiCode ); if( sps->getChromaFormatIdc() != CHROMA_400 ) { READ_FLAG( uiCode, "ph_chroma_residual_scale_flag" ); picHeader->setLmcsChromaResidualScaleFlag( uiCode != 0 ); } else { picHeader->setLmcsChromaResidualScaleFlag( false ); } } } else { picHeader->setLmcsEnabledFlag( false ); picHeader->setLmcsChromaResidualScaleFlag( false ); } // quantization scaling lists if( sps->getScalingListFlag() ) { READ_FLAG( uiCode, "ph_explicit_scaling_list_enabled_flag" ); picHeader->setExplicitScalingListEnabledFlag( uiCode ); if( picHeader->getExplicitScalingListEnabledFlag() ) { READ_CODE( 3, uiCode, "ph_scaling_list_aps_id" ); picHeader->setScalingListAPSId( uiCode ); } } else { picHeader->setExplicitScalingListEnabledFlag( false ); } // virtual boundaries if( sps->getVirtualBoundariesEnabledFlag() && !sps->getVirtualBoundariesPresentFlag() ) { READ_FLAG( uiCode, "ph_virtual_boundaries_present_flag" ); picHeader->setVirtualBoundariesPresentFlag( uiCode != 0 ); if( picHeader->getVirtualBoundariesPresentFlag() ) { READ_UVLC( uiCode, "ph_num_ver_virtual_boundaries" ); picHeader->setNumVerVirtualBoundaries( uiCode ); if( pps->getPicWidthInLumaSamples() <= 8 ) { CHECK_RECOVERABLE( picHeader->getNumVerVirtualBoundaries() != 0, "PH: When picture width is less than or equal to 8, the number of vertical virtual boundaries shall be equal to 0" ); } else { CHECK_RECOVERABLE( picHeader->getNumVerVirtualBoundaries() > 3, "PH: The number of vertical virtual boundaries shall be in the range of 0 to 3" ); } for( unsigned i = 0; i < picHeader->getNumVerVirtualBoundaries(); i++ ) { READ_UVLC( uiCode, "ph_virtual_boundary_pos_x_minus1[ i ]" ); picHeader->setVirtualBoundariesPosX( (uiCode + 1) << 3, i ); CHECK_RECOVERABLE( uiCode > ( ( ( pps->getPicWidthInLumaSamples() + 7 ) >> 3 ) - 2 ), "The value of ph_virtual_boundary_pos_x_minus1[ i ] shall be in the range of 0 to Ceil( pps_pic_width_in_luma_samples / 8 ) - 2, inclusive." ); } READ_UVLC( uiCode, "ph_num_hor_virtual_boundaries" ); picHeader->setNumHorVirtualBoundaries( uiCode ); if( pps->getPicHeightInLumaSamples() <= 8 ) { CHECK_RECOVERABLE( picHeader->getNumHorVirtualBoundaries() != 0, "PH: When picture width is less than or equal to 8, the number of horizontal virtual boundaries shall be equal to 0" ); } else { CHECK_RECOVERABLE( picHeader->getNumHorVirtualBoundaries() > 3, "PH: The number of horizontal virtual boundaries shall be in the range of 0 to 3" ); } for( unsigned i = 0; i < picHeader->getNumHorVirtualBoundaries(); i++ ) { READ_UVLC( uiCode, "ph_virtual_boundary_pos_y_minus1[ i ]" ); picHeader->setVirtualBoundariesPosY( (uiCode + 1) << 3, i ); CHECK_RECOVERABLE( uiCode > ( ( ( pps->getPicHeightInLumaSamples() + 7 ) >> 3 ) - 2 ), "The value of ph_virtual_boundary_pos_y_minus1[ i ] shall be in the range of 0 to Ceil( pps_pic_height_in_luma_samples / 8 ) - 2, inclusive." ); } } else { picHeader->setNumVerVirtualBoundaries( 0 ); picHeader->setNumHorVirtualBoundaries( 0 ); } } else { picHeader->setVirtualBoundariesPresentFlag( sps->getVirtualBoundariesPresentFlag() ); if( picHeader->getVirtualBoundariesPresentFlag() ) { picHeader->setNumVerVirtualBoundaries( sps->getNumVerVirtualBoundaries() ); picHeader->setNumHorVirtualBoundaries( sps->getNumHorVirtualBoundaries() ); for( unsigned i = 0; i < 3; i++ ) { picHeader->setVirtualBoundariesPosX( sps->getVirtualBoundariesPosX( i ), i ); picHeader->setVirtualBoundariesPosY( sps->getVirtualBoundariesPosY( i ), i ); } } } // picture output flag if( pps->getOutputFlagPresentFlag() && !picHeader->getNonReferencePictureFlag() ) { READ_FLAG( uiCode, "ph_pic_output_flag" ); picHeader->setPicOutputFlag( uiCode != 0 ); } else { picHeader->setPicOutputFlag( true ); } // reference picture lists if( pps->getRplInfoInPhFlag() ) { parsePicOrSliceHeaderRPL( picHeader, sps, pps ); } // partitioning constraint overrides if( sps->getSplitConsOverrideEnabledFlag() ) { READ_FLAG( uiCode, "ph_partition_constraints_override_flag" ); picHeader->setSplitConsOverrideFlag( uiCode != 0 ); } else { picHeader->setSplitConsOverrideFlag( 0 ); } // Q0781, two-flags unsigned minQT[3] = { 0, 0, 0 }; unsigned maxBTD[3] = { 0, 0, 0 }; unsigned maxBTSize[3] = { 0, 0, 0 }; unsigned maxTTSize[3] = { 0, 0, 0 }; if( picHeader->getPicIntraSliceAllowedFlag() ) { if( picHeader->getSplitConsOverrideFlag() ) { READ_UVLC( uiCode, "ph_log2_diff_min_qt_min_cb_intra_slice_luma" ); unsigned minQtLog2SizeIntraY = uiCode + sps->getLog2MinCodingBlockSize(); minQT[0] = 1 << minQtLog2SizeIntraY; CHECK_RECOVERABLE( minQT[0] > 64, "The value of ph_log2_diff_min_qt_min_cb_intra_slice_luma shall be in the range of 0 to min(6,CtbLog2SizeY) - MinCbLog2Size" ); READ_UVLC( uiCode, "ph_max_mtt_hierarchy_depth_intra_slice_luma" ); maxBTD[0] = uiCode; maxTTSize[0] = maxBTSize[0] = minQT[0]; if( maxBTD[0] != 0 ) { READ_UVLC( uiCode, "ph_log2_diff_max_bt_min_qt_intra_slice_luma" ); maxBTSize[0] <<= uiCode; READ_UVLC( uiCode, "ph_log2_diff_max_tt_min_qt_intra_slice_luma" ); maxTTSize[0] <<= uiCode; } if( sps->getUseDualITree() ) { READ_UVLC( uiCode, "ph_log2_diff_min_qt_min_cb_intra_slice_chroma" ); minQT[2] = 1 << (uiCode + sps->getLog2MinCodingBlockSize()); CHECK_RECOVERABLE( minQT[2] > 64, "The value of ph_log2_diff_min_qt_min_cb_intra_slice_chroma shall be in the range of 0 to min(6,CtbLog2SizeY) - MinCbLog2Size" ); READ_UVLC( uiCode, "ph_max_mtt_hierarchy_depth_intra_slice_chroma" ); maxBTD[2] = uiCode; maxTTSize[2] = maxBTSize[2] = minQT[2]; if( maxBTD[2] != 0 ) { READ_UVLC( uiCode, "ph_log2_diff_max_bt_min_qt_intra_slice_chroma" ); maxBTSize[2] <<= uiCode; READ_UVLC( uiCode, "ph_log2_diff_max_tt_min_qt_intra_slice_chroma" ); maxTTSize[2] <<= uiCode; CHECK_RECOVERABLE( maxBTSize[2] > 64, "The value of ph_log2_diff_max_bt_min_qt_intra_slice_chroma shall be in the range of 0 to min(6,CtbLog2SizeY) - MinQtLog2SizeIntraChroma" ); CHECK_RECOVERABLE( maxTTSize[2] > 64, "The value of ph_log2_diff_max_tt_min_qt_intra_slice_chroma shall be in the range of 0 to min(6,CtbLog2SizeY) - MinQtLog2SizeIntraChroma" ); } } } } if( picHeader->getPicIntraSliceAllowedFlag() ) { // delta quantization and chrom and chroma offset if( pps->getUseDQP() ) { READ_UVLC( uiCode, "ph_cu_qp_delta_subdiv_intra_slice" ); picHeader->setCuQpDeltaSubdivIntra( uiCode ); } else { picHeader->setCuQpDeltaSubdivIntra( 0 ); } if( pps->getCuChromaQpOffsetEnabledFlag() ) { READ_UVLC( uiCode, "ph_cu_chroma_qp_offset_subdiv_intra_slice" ); picHeader->setCuChromaQpOffsetSubdivIntra( uiCode ); } else { picHeader->setCuChromaQpOffsetSubdivIntra( 0 ); } } if( picHeader->getPicInterSliceAllowedFlag() ) { if( picHeader->getSplitConsOverrideFlag() ) { READ_UVLC( uiCode, "ph_log2_diff_min_qt_min_cb_inter_slice" ); unsigned minQtLog2SizeInterY = uiCode + sps->getLog2MinCodingBlockSize(); minQT[1] = 1 << minQtLog2SizeInterY; READ_UVLC( uiCode, "ph_max_mtt_hierarchy_depth_inter_slice" ); maxBTD[1] = uiCode; maxTTSize[1] = maxBTSize[1] = minQT[1]; if( maxBTD[1] != 0 ) { READ_UVLC( uiCode, "ph_log2_diff_max_bt_min_qt_inter_slice" ); maxBTSize[1] <<= uiCode; READ_UVLC( uiCode, "ph_log2_diff_max_tt_min_qt_inter_slice" ); maxTTSize[1] <<= uiCode; } } // delta quantization and chrom and chroma offset if( pps->getUseDQP() ) { READ_UVLC( uiCode, "ph_cu_qp_delta_subdiv_inter_slice" ); picHeader->setCuQpDeltaSubdivInter( uiCode ); } else { picHeader->setCuQpDeltaSubdivInter( 0 ); } if( pps->getCuChromaQpOffsetEnabledFlag() ) { READ_UVLC( uiCode, "ph_cu_chroma_qp_offset_subdiv_inter_slice" ); picHeader->setCuChromaQpOffsetSubdivInter( uiCode ); } else { picHeader->setCuChromaQpOffsetSubdivInter( 0 ); } // temporal motion vector prediction if( sps->getSPSTemporalMVPEnabledFlag() ) { READ_FLAG( uiCode, "ph_temporal_mvp_enabled_flag" ); picHeader->setEnableTMVPFlag( uiCode != 0 ); } else { picHeader->setEnableTMVPFlag( false) ; } if( picHeader->getEnableTMVPFlag() && pps->getRplInfoInPhFlag() ) { if( picHeader->getRPL(REF_PIC_LIST_1)->getNumRefEntries() > 0 ) { READ_CODE( 1, uiCode, "ph_collocated_from_l0_flag" ); picHeader->setPicColFromL0Flag( uiCode ); } else { picHeader->setPicColFromL0Flag(1); } if( ( picHeader->getPicColFromL0Flag() == 1 && picHeader->getRPL( REF_PIC_LIST_0 )->getNumRefEntries() > 1 ) || ( picHeader->getPicColFromL0Flag() == 0 && picHeader->getRPL( REF_PIC_LIST_1 )->getNumRefEntries() > 1 ) ) { READ_UVLC( uiCode, "ph_collocated_ref_idx" ); picHeader->setColRefIdx( uiCode ); } else { picHeader->setColRefIdx( 0 ); } } else { picHeader->setPicColFromL0Flag( 0 ); } // merge candidate list size // subblock merge candidate list size if( sps->getUseAffine() ) { picHeader->setMaxNumAffineMergeCand( sps->getMaxNumAffineMergeCand() ); } else { picHeader->setMaxNumAffineMergeCand( sps->getSBTMVPEnabledFlag() && picHeader->getEnableTMVPFlag() ); } // full-pel MMVD flag if( sps->getFpelMmvdEnabledFlag() ) { READ_FLAG( uiCode, "ph_fpel_mmvd_enabled_flag" ); picHeader->setDisFracMMVD( uiCode != 0 ); } else { picHeader->setDisFracMMVD( false ); } // mvd L1 zero flag if( !pps->getRplInfoInPhFlag() || picHeader->getRPL( REF_PIC_LIST_1 )->getNumRefEntries() > 0 ) { READ_FLAG( uiCode, "ph_mvd_l1_zero_flag" ); picHeader->setMvdL1ZeroFlag( uiCode != 0 ); } else { picHeader->setMvdL1ZeroFlag( true ); } // picture level BDOF disable flags if( sps->getBdofControlPresentFlag() && ( !pps->getRplInfoInPhFlag() || picHeader->getRPL( REF_PIC_LIST_1 )->getNumRefEntries() > 0 ) ) { READ_FLAG( uiCode, "ph_bdof_disabled_flag" ); picHeader->setDisBdofFlag( uiCode != 0 ); } else { if( sps->getBdofControlPresentFlag() == 0 ) { picHeader->setDisBdofFlag( 1 - (int)( sps->getUseBIO() ) ); } else { picHeader->setDisBdofFlag( 1 ); } } // picture level DMVR disable flags if( sps->getDmvrControlPresentFlag() && ( !pps->getRplInfoInPhFlag() || picHeader->getRPL( REF_PIC_LIST_1 )->getNumRefEntries() > 0 ) ) { READ_FLAG( uiCode, "ph_dmvr_disabled_flag" ); picHeader->setDisDmvrFlag( uiCode != 0 ); } else { if( sps->getDmvrControlPresentFlag() == 0 ) { picHeader->setDisDmvrFlag( 1 - (int)( sps->getUseDMVR() ) ); } else { picHeader->setDisDmvrFlag( 1 ); } } // picture level PROF disable flags if( sps->getProfControlPresentFlag() ) { READ_FLAG( uiCode, "ph_prof_disabled_flag" ); picHeader->setDisProfFlag( uiCode != 0 ); } else { picHeader->setDisProfFlag(0); } if( ( pps->getUseWP() || pps->getWPBiPred() ) && pps->getWpInfoInPhFlag() ) { parsePredWeightTable( picHeader, sps ); } } // if( picHeader->getPicInterSliceAllowedFlag() ) // inherit constraint values from SPS if( !sps->getSplitConsOverrideEnabledFlag() || !picHeader->getSplitConsOverrideFlag() ) { picHeader->setMinQTSizes( sps->getMinQTSizes() ); picHeader->setMaxMTTHierarchyDepths( sps->getMaxBTSizes() ); picHeader->setMaxBTSizes( sps->getMaxBTSizes() ); picHeader->setMaxTTSizes( sps->getMaxTTSizes() ); } else { picHeader->setMinQTSizes( minQT ); picHeader->setMaxMTTHierarchyDepths( maxBTD ); picHeader->setMaxBTSizes( maxBTSize ); picHeader->setMaxTTSizes( maxTTSize ); } // ibc merge candidate list size if( pps->getQpDeltaInfoInPhFlag() ) { int iCode = 0; READ_SVLC( iCode, "ph_qp_delta" ); picHeader->setQpDelta( iCode ); } // joint Cb/Cr sign flag if( sps->getJointCbCrEnabledFlag() ) { READ_FLAG( uiCode, "ph_joint_cbcr_sign_flag" ); picHeader->setJointCbCrSignFlag( uiCode != 0 ); } else { picHeader->setJointCbCrSignFlag( false ); } // sao enable flags if( sps->getUseSAO() ) { if( pps->getSaoInfoInPhFlag() ) { READ_FLAG( uiCode, "ph_sao_luma_enabled_flag" ); picHeader->setSaoEnabledFlag( CHANNEL_TYPE_LUMA, uiCode != 0 ); if( sps->getChromaFormatIdc() != CHROMA_400 ) { READ_FLAG( uiCode, "ph_sao_chroma_enabled_flag" ); picHeader->setSaoEnabledFlag( CHANNEL_TYPE_CHROMA, uiCode != 0 ); } } else { picHeader->setSaoEnabledFlag( CHANNEL_TYPE_LUMA, true) ; picHeader->setSaoEnabledFlag( CHANNEL_TYPE_CHROMA, sps->getChromaFormatIdc() != CHROMA_400 ); } } else { picHeader->setSaoEnabledFlag( CHANNEL_TYPE_LUMA, false ); picHeader->setSaoEnabledFlag( CHANNEL_TYPE_CHROMA, false ); } // deblocking filter controls if( pps->getDeblockingFilterControlPresentFlag() ) { if( pps->getDeblockingFilterOverrideEnabledFlag() ) { if( pps->getDbfInfoInPhFlag() ) { READ_FLAG ( uiCode, "ph_deblocking_params_present_flag" ); picHeader->setDeblockingFilterOverrideFlag( uiCode != 0 ); } else { picHeader->setDeblockingFilterOverrideFlag( false ); } } else { picHeader->setDeblockingFilterOverrideFlag( false ); } if( picHeader->getDeblockingFilterOverrideFlag() ) { if( !pps->getPPSDeblockingFilterDisabledFlag() ) { READ_FLAG( uiCode, "ph_deblocking_filter_disabled_flag" ); picHeader->setDeblockingFilterDisable( uiCode != 0 ); } else { picHeader->setDeblockingFilterDisable( false ); } if( !picHeader->getDeblockingFilterDisable() ) { READ_SVLC( iCode, "ph_luma_beta_offset_div2" ); picHeader->setDeblockingFilterBetaOffsetDiv2( iCode ); CHECK_RECOVERABLE( picHeader->getDeblockingFilterBetaOffsetDiv2() < -12 || picHeader->getDeblockingFilterBetaOffsetDiv2() > 12, "Invalid deblocking filter configuration" ); READ_SVLC( iCode, "ph_luma_tc_offset_div2" ); picHeader->setDeblockingFilterTcOffsetDiv2( iCode ); CHECK_RECOVERABLE( picHeader->getDeblockingFilterTcOffsetDiv2() < -12 || picHeader->getDeblockingFilterTcOffsetDiv2() > 12, "Invalid deblocking filter configuration" ); if( pps->getPPSChromaToolFlag() ) { READ_SVLC( iCode, "ph_cb_beta_offset_div2" ); picHeader->setDeblockingFilterCbBetaOffsetDiv2( iCode ); CHECK_RECOVERABLE( picHeader->getDeblockingFilterCbBetaOffsetDiv2() < -12 || picHeader->getDeblockingFilterCbBetaOffsetDiv2() > 12, "Invalid deblocking filter configuration" ); READ_SVLC( iCode, "ph_cb_tc_offset_div2" ); picHeader->setDeblockingFilterCbTcOffsetDiv2( iCode ); CHECK_RECOVERABLE( picHeader->getDeblockingFilterCbTcOffsetDiv2() < -12 || picHeader->getDeblockingFilterCbTcOffsetDiv2() > 12, "Invalid deblocking filter configuration" ); READ_SVLC( iCode, "ph_cr_beta_offset_div2" ); picHeader->setDeblockingFilterCrBetaOffsetDiv2( iCode ); CHECK_RECOVERABLE( picHeader->getDeblockingFilterCrBetaOffsetDiv2() < -12 || picHeader->getDeblockingFilterCrBetaOffsetDiv2() > 12, "Invalid deblocking filter configuration" ); READ_SVLC( iCode, "ph_cr_tc_offset_div2" ); picHeader->setDeblockingFilterCrTcOffsetDiv2( iCode ); CHECK_RECOVERABLE( picHeader->getDeblockingFilterCrTcOffsetDiv2() < -12 || picHeader->getDeblockingFilterCrTcOffsetDiv2() > 12, "Invalid deblocking filter configuration" ); } else { picHeader->setDeblockingFilterCbBetaOffsetDiv2 ( picHeader->getDeblockingFilterBetaOffsetDiv2() ); picHeader->setDeblockingFilterCbTcOffsetDiv2 ( picHeader->getDeblockingFilterTcOffsetDiv2() ); picHeader->setDeblockingFilterCrBetaOffsetDiv2 ( picHeader->getDeblockingFilterBetaOffsetDiv2() ); picHeader->setDeblockingFilterCrTcOffsetDiv2 ( picHeader->getDeblockingFilterTcOffsetDiv2() ); } } } else { picHeader->setDeblockingFilterDisable ( pps->getPPSDeblockingFilterDisabledFlag() ); picHeader->setDeblockingFilterBetaOffsetDiv2( pps->getDeblockingFilterBetaOffsetDiv2() ); picHeader->setDeblockingFilterTcOffsetDiv2 ( pps->getDeblockingFilterTcOffsetDiv2() ); picHeader->setDeblockingFilterCbBetaOffsetDiv2( pps->getDeblockingFilterCbBetaOffsetDiv2() ); picHeader->setDeblockingFilterCbTcOffsetDiv2 ( pps->getDeblockingFilterCbTcOffsetDiv2() ); picHeader->setDeblockingFilterCrBetaOffsetDiv2( pps->getDeblockingFilterCrBetaOffsetDiv2() ); picHeader->setDeblockingFilterCrTcOffsetDiv2 ( pps->getDeblockingFilterCrTcOffsetDiv2() ); } } else { picHeader->setDeblockingFilterDisable ( false ); picHeader->setDeblockingFilterBetaOffsetDiv2( 0 ); picHeader->setDeblockingFilterTcOffsetDiv2 ( 0 ); picHeader->setDeblockingFilterCbBetaOffsetDiv2( 0 ); picHeader->setDeblockingFilterCbTcOffsetDiv2 ( 0 ); picHeader->setDeblockingFilterCrBetaOffsetDiv2( 0 ); picHeader->setDeblockingFilterCrTcOffsetDiv2( 0 ); } // picture header extension if( pps->getPictureHeaderExtensionPresentFlag() ) { READ_UVLC( uiCode, "ph_extension_length" ); for( int i = 0; i < uiCode; i++ ) { uint32_t ignore_; READ_CODE( 8, ignore_, "ph_extension_data_byte[i]" ); } } if( readRbspTrailingBits ) { xReadRbspTrailingBits(); } picHeader->setValid(); } void HLSyntaxReader::checkAlfNaluTidAndPicTid( const Slice* pcSlice, const PicHeader* picHeader, const ParameterSetManager *parameterSetManager ) { const SPS* sps = parameterSetManager->getSPS(picHeader->getSPSId()); const PPS* pps = parameterSetManager->getPPS(picHeader->getPPSId()); int curPicTid = pcSlice->getTLayer(); const APS* aps = nullptr; if( sps->getUseALF() && pps->getAlfInfoInPhFlag() && picHeader->getAlfEnabledFlag( COMPONENT_Y ) ) { const std::vector& apsIds = picHeader->getAlfAPSIds(); //luma for( int i = 0; i < picHeader->getNumAlfAps(); i++ ) { aps = parameterSetManager->getAPS( apsIds[i], ALF_APS ); CHECK_RECOVERABLE( aps->getTemporalId() > curPicTid, "The TemporalId of the APS NAL unit having aps_params_type equal to ALF_APS and adaptation_parameter_set_id equal to ph_alf_aps_id_luma[i] shall be less than or equal to the TemporalId of the picture associated with the PH." ); if( pcSlice->getNalUnitLayerId() != aps->getLayerId() ) { CHECK_RECOVERABLE( aps->getLayerId() > pcSlice->getNalUnitLayerId(), "Layer Id of APS cannot be greater than layer Id of VCL NAL unit the refer to it" ); CHECK_RECOVERABLE( pcSlice->getSPS()->getVPSId() == 0, "VPSId of the referred SPS cannot be 0 when layer Id of APS and layer Id of current slice are different" ); for( int i = 0; i < pcSlice->getVPS()->getNumOutputLayerSets(); i++ ) { bool isCurrLayerInOls = false; bool isRefLayerInOls = false; for( int j = pcSlice->getVPS()->getNumLayersInOls(i) - 1; j >= 0; j-- ) { if( pcSlice->getVPS()->getLayerIdInOls(i, j) == pcSlice->getNalUnitLayerId() ) { isCurrLayerInOls = true; } if( pcSlice->getVPS()->getLayerIdInOls(i, j) == aps->getLayerId() ) { isRefLayerInOls = true; } } CHECK_RECOVERABLE( isCurrLayerInOls && !isRefLayerInOls, "When VCL NAl unit in layer A refers to APS in layer B, all OLS that contains layer A shall also contains layer B" ); } } } //chroma if( picHeader->getAlfEnabledFlag(COMPONENT_Cb) || picHeader->getAlfEnabledFlag( COMPONENT_Cr ) ) { int chromaAlfApsId = picHeader->getAlfApsIdChroma(); aps = parameterSetManager->getAPS( chromaAlfApsId, ALF_APS ); CHECK_RECOVERABLE( aps->getTemporalId() > curPicTid, "The TemporalId of the APS NAL unit having aps_params_type equal to ALF_APS and adaptation_parameter_set_id equal to ph_alf_aps_id_chroma shall be less than or equal to the TemporalId of the picture associated with the PH.") ; if( pcSlice->getNalUnitLayerId() != aps->getLayerId() ) { CHECK_RECOVERABLE( aps->getLayerId() > pcSlice->getNalUnitLayerId(), "Layer Id of APS cannot be greater than layer Id of VCL NAL unit the refer to it" ); CHECK_RECOVERABLE( pcSlice->getSPS()->getVPSId() == 0, "VPSId of the referred SPS cannot be 0 when layer Id of APS and layer Id of current slice are different" ); for( int i = 0; i < pcSlice->getVPS()->getNumOutputLayerSets(); i++ ) { bool isCurrLayerInOls = false; bool isRefLayerInOls = false; for( int j = pcSlice->getVPS()->getNumLayersInOls(i) - 1; j >= 0; j-- ) { if( pcSlice->getVPS()->getLayerIdInOls(i, j) == pcSlice->getNalUnitLayerId() ) { isCurrLayerInOls = true; } if( pcSlice->getVPS()->getLayerIdInOls(i, j) == aps->getLayerId() ) { isRefLayerInOls = true; } } CHECK_RECOVERABLE( isCurrLayerInOls && !isRefLayerInOls, "When VCL NAl unit in layer A refers to APS in layer B, all OLS that contains layer A shall also contains layer B" ); } } } } } void HLSyntaxReader::parseSliceHeader( Slice* pcSlice, std::shared_ptr& picHeader, const ParameterSetManager* parameterSetManager, const int prevTid0POC, bool& firstSliceInPic ) { uint32_t uiCode = 0; int iCode = 0; #if ENABLE_TRACING xTraceSliceHeader(); #endif READ_FLAG( uiCode, "sh_picture_header_in_slice_header_flag" ); if( uiCode ) { pcSlice->setPictureHeaderInSliceHeader( true ); picHeader.reset( new PicHeader ); parsePictureHeader( picHeader.get(), parameterSetManager, false ); } CHECK ( !picHeader, "Picture Header not allocated" ); // should always be allocated, even if it is not valid CHECK_RECOVERABLE( !picHeader->isValid(), "Picture Header missing" ); checkAlfNaluTidAndPicTid( pcSlice, picHeader.get(), parameterSetManager ); const PPS* pps = parameterSetManager->getPPS( picHeader->getPPSId() ); CHECK_RECOVERABLE( pps==0, "Invalid PPS" ); const SPS* sps = parameterSetManager->getSPS( pps->getSPSId() ); CHECK_RECOVERABLE( sps==0, "Invalid SPS" ); if( sps->getProfileTierLevel()->getConstraintInfo()->getPicHeaderInSliceHeaderConstraintFlag() ) { CHECK_RECOVERABLE( pcSlice->getPictureHeaderInSliceHeader() == false, "PH shall be present in SH, when pic_header_in_slice_header_constraint_flag is equal to 1" ); } if( pcSlice->getPictureHeaderInSliceHeader() ) { CHECK_RECOVERABLE( pps->getRplInfoInPhFlag() == 1, "When sh_picture_header_in_slice_header_flag is equal to 1, rpl_info_in_ph_flag shall be equal to 0" ); CHECK_RECOVERABLE( pps->getDbfInfoInPhFlag() == 1, "When sh_picture_header_in_slice_header_flag is equal to 1, dbf_info_in_ph_flag shall be equal to 0" ); CHECK_RECOVERABLE( pps->getSaoInfoInPhFlag() == 1, "When sh_picture_header_in_slice_header_flag is equal to 1, sao_info_in_ph_flag shall be equal to 0" ); CHECK_RECOVERABLE( pps->getAlfInfoInPhFlag() == 1, "When sh_picture_header_in_slice_header_flag is equal to 1, alf_info_in_ph_flag shall be equal to 0" ); CHECK_RECOVERABLE( pps->getWpInfoInPhFlag() == 1, "When sh_picture_header_in_slice_header_flag is equal to 1, wp_info_in_ph_flag shall be equal to 0" ); CHECK_RECOVERABLE( pps->getQpDeltaInfoInPhFlag() == 1, "When sh_picture_header_in_slice_header_flag is equal to 1, qp_delta_info_in_ph_flag shall be equal to 0" ); CHECK_RECOVERABLE( sps->getSubPicInfoPresentFlag() == 1, "When sps_subpic_info_present_flag is equal to 1, the value of sh_picture_header_in_slice_header_flag shall be equal to 0" ); } CHECK_RECOVERABLE( sps->getSubPicInfoPresentFlag() == 1 && sps->getVirtualBoundariesEnabledFlag() == 1 && sps->getVirtualBoundariesPresentFlag() == 0, "when sps_subpic_info_present_flag is equal to 1 and sps_virtual_boundaries_enabled_flag is equal to 1, sps_virtual_boundaries_present_flag shall be equal 1" ); const ChromaFormat chFmt = sps->getChromaFormatIdc(); const uint32_t numValidComp = getNumberValidComponents( chFmt ); const bool bChroma = ( chFmt != CHROMA_400 ); // picture order count uiCode = picHeader->getPocLsb(); int iPOClsb = uiCode; int iMaxPOClsb = 1 << sps->getBitsForPOC(); int iPOCmsb; if( pcSlice->getIdrPicFlag() ) { if( picHeader->getPocMsbPresentFlag() ) { iPOCmsb = picHeader->getPocMsbVal() * iMaxPOClsb; } else { iPOCmsb = 0; } pcSlice->setPOC( iPOCmsb + iPOClsb ); } else { int iPrevPOC = prevTid0POC; int iPrevPOClsb = iPrevPOC & ( iMaxPOClsb - 1 ); int iPrevPOCmsb = iPrevPOC - iPrevPOClsb; if( picHeader->getPocMsbPresentFlag() ) { iPOCmsb = picHeader->getPocMsbVal() * iMaxPOClsb; } else { if( ( iPOClsb < iPrevPOClsb ) && ( ( iPrevPOClsb - iPOClsb ) >= ( iMaxPOClsb / 2 ) ) ) { iPOCmsb = iPrevPOCmsb + iMaxPOClsb; } else if( ( iPOClsb > iPrevPOClsb ) && ( ( iPOClsb - iPrevPOClsb ) > ( iMaxPOClsb / 2 ) ) ) { iPOCmsb = iPrevPOCmsb - iMaxPOClsb; } else { iPOCmsb = iPrevPOCmsb; } } pcSlice->setPOC( iPOCmsb + iPOClsb ); } if( sps->getSubPicInfoPresentFlag() ) { uint32_t bitsSubPicId; bitsSubPicId = sps->getSubPicIdLen(); READ_CODE( bitsSubPicId, uiCode, "sh_subpic_id" ); pcSlice->setSliceSubPicId( uiCode ); } else { pcSlice->setSliceSubPicId( 0 ); } // raster scan slices uint32_t sliceAddr = 0; if( pps->getRectSliceFlag() == 0 ) { // slice address is the raster scan tile index of first tile in slice if( pps->getNumTiles() > 1 ) { int bitsSliceAddress = (int)ceil( log2( pps->getNumTiles() ) ); READ_CODE( bitsSliceAddress, uiCode, "sh_slice_address" ); sliceAddr = uiCode; } } // rectangular slices else { // slice address is the index of the slice within the current sub-picture uint32_t currSubPicIdx = pps->getSubPicIdxFromSubPicId( pcSlice->getSliceSubPicId() ); const SubPic& currSubPic = pps->getSubPic( currSubPicIdx ); if( currSubPic.getNumSlicesInSubPic() > 1 ) { int bitsSliceAddress = (int)ceil( log2( currSubPic.getNumSlicesInSubPic() ) ); READ_CODE( bitsSliceAddress, uiCode, "sh_slice_address" ); sliceAddr = uiCode; } uint32_t picLevelSliceIdx = sliceAddr; for( int subpic = 0; subpic < currSubPicIdx; subpic++ ) { picLevelSliceIdx += pps->getSubPic( subpic ).getNumSlicesInSubPic(); } pcSlice->setSliceMap( pps->getSliceMap( picLevelSliceIdx ) ); pcSlice->setSliceID( picLevelSliceIdx ); } std::vector shExtraBitsPresent = sps->getExtraSHBitPresentFlags(); for( int i=0; i< sps->getNumExtraSHBitsBytes() * 8; i++ ) { // extra bits are ignored (when present) if( shExtraBitsPresent[i] ) { READ_FLAG( uiCode, "sh_extra_bit[i]" ); } } if( pps->getRectSliceFlag() == 0 ) { uint32_t numTilesInSlice = 1; if( pps->getNumTiles() > 1 ) { if( ( (int)pps->getNumTiles() - (int)sliceAddr ) > 1) { READ_UVLC( uiCode, "sh_num_tiles_in_slice_minus1" ); numTilesInSlice = uiCode + 1; } if( !pps->getRectSliceFlag() && sps->getProfileTierLevel()->getConstraintInfo()->getOneSlicePerPicConstraintFlag() ) { CHECK_RECOVERABLE( pps->getNumTiles() != uiCode + 1, "When rect_slice_flag is equal to 0 and one_slice_per_pic_constraint_flag equal to 1, the value of num_tiles_in_slice_minus1 present in each slice header shall be equal to NumTilesInPic - 1" ); } } CHECK_RECOVERABLE( sliceAddr >= pps->getNumTiles(), "Invalid slice address" ); pcSlice->resetSliceMap(); pcSlice->setSliceID( sliceAddr ); for( uint32_t tileIdx = sliceAddr; tileIdx < sliceAddr + numTilesInSlice; tileIdx++ ) { uint32_t tileX = tileIdx % pps->getNumTileColumns(); uint32_t tileY = tileIdx / pps->getNumTileColumns(); CHECK_RECOVERABLE( tileY >= pps->getNumTileRows(), "Number of tiles in slice exceeds the remaining number of tiles in picture" ); pcSlice->addCtusToSlice( pps->getTileColumnBd( tileX ), pps->getTileColumnBd( tileX + 1 ), pps->getTileRowBd( tileY ), pps->getTileRowBd( tileY + 1 ), pps->getPicWidthInCtu() ); } } if( firstSliceInPic != ( pcSlice->getCtuAddrInSlice( 0 ) == 0 ) ) { // exit early, because we need to start again with some fields copied from previous slice firstSliceInPic = false; return; } if( picHeader->getPicInterSliceAllowedFlag() ) { READ_UVLC( uiCode, "sh_slice_type" ); pcSlice->setSliceType( (SliceType)uiCode ); } else { pcSlice->setSliceType( I_SLICE ); } if( !picHeader->getPicIntraSliceAllowedFlag() ) { CHECK_RECOVERABLE( pcSlice->getSliceType() == I_SLICE, "when pic_intra_slice_allowed_flag = 0, no I_Slice is allowed" ); } if( pcSlice->getNalUnitType() == NAL_UNIT_CODED_SLICE_CRA || pcSlice->getNalUnitType() == NAL_UNIT_CODED_SLICE_IDR_N_LP || pcSlice->getNalUnitType() == NAL_UNIT_CODED_SLICE_IDR_W_RADL || pcSlice->getNalUnitType() == NAL_UNIT_CODED_SLICE_GDR ) { READ_FLAG(uiCode, "sh_no_output_of_prior_pics_flag" ); pcSlice->setNoOutputOfPriorPicsFlag( uiCode != 0 ); } // inherit values from picture header // set default values in case slice overrides are disabled pcSlice->inheritFromPicHeader( picHeader.get(), pps, sps ); if( sps->getUseALF() && !pps->getAlfInfoInPhFlag() ) { READ_FLAG( uiCode, "sh_alf_enabled_flag" ); pcSlice->setAlfEnabledFlag( COMPONENT_Y, uiCode ); int alfCbEnabledFlag = 0; int alfCrEnabledFlag = 0; if( uiCode ) { READ_CODE( 3, uiCode, "sh_num_alf_aps_ids_luma" ); int numAps = uiCode; pcSlice->setNumAlfAps( numAps ); std::vector apsId( numAps, -1) ; for( int i = 0; i < numAps; i++ ) { READ_CODE( 3, uiCode, "sh_alf_aps_id_luma[i]" ); apsId[i] = uiCode; const APS* APStoCheckLuma = parameterSetManager->getAPS( apsId[i], ALF_APS ); CHECK_RECOVERABLE( APStoCheckLuma == nullptr, "referenced APS not found" ); CHECK_RECOVERABLE( APStoCheckLuma->getAlfAPSParam().newFilterFlag[CHANNEL_TYPE_LUMA] != 1, "bitstream conformance error, alf_luma_filter_signal_flag shall be equal to 1" ); } pcSlice->setAlfApsIdLuma( apsId ); if( bChroma ) { READ_CODE( 1, uiCode, "sh_alf_cb_enabled_flag" ); alfCbEnabledFlag = uiCode; READ_CODE( 1, uiCode, "sh_alf_cr_enabled_flag" ); alfCrEnabledFlag = uiCode; } else { alfCbEnabledFlag = 0; alfCrEnabledFlag = 0; } if( alfCbEnabledFlag || alfCrEnabledFlag ) { READ_CODE( 3, uiCode, "sh_alf_aps_id_chroma" ); pcSlice->setAlfApsIdChroma( uiCode ); const APS* APStoCheckChroma = parameterSetManager->getAPS( uiCode, ALF_APS ); CHECK_RECOVERABLE( APStoCheckChroma == nullptr, "referenced APS not found" ); CHECK_RECOVERABLE( APStoCheckChroma->getAlfAPSParam().newFilterFlag[CHANNEL_TYPE_CHROMA] != 1, "bitstream conformance error, alf_chroma_filter_signal_flag shall be equal to 1" ); } } else { pcSlice->setNumAlfAps( 0 ); } pcSlice->setAlfEnabledFlag( COMPONENT_Cb, alfCbEnabledFlag ); pcSlice->setAlfEnabledFlag( COMPONENT_Cr, alfCrEnabledFlag ); if( sps->getUseCCALF() && pcSlice->getAlfEnabledFlag( COMPONENT_Y ) ) { READ_FLAG( uiCode, "sh_alf_cc_cb_enabled_flag" ); pcSlice->setCcAlfCbEnabledFlag( uiCode ); pcSlice->setCcAlfCbApsId( -1 ); if( uiCode ) { // parse APS ID READ_CODE( 3, uiCode, "sh_cc_alf_cb_aps_id" ); pcSlice->setCcAlfCbApsId( uiCode ); } // Cr READ_FLAG(uiCode, "sh_alf_cc_cr_enabled_flag" ); pcSlice->setCcAlfCrEnabledFlag( uiCode ); pcSlice->setCcAlfCrApsId(-1); if( uiCode ) { // parse APS ID READ_CODE( 3, uiCode, "sh_cc_alf_cr_aps_id" ); pcSlice->setCcAlfCrApsId( uiCode ); } } else { pcSlice->setCcAlfCbEnabledFlag( 0 ); pcSlice->setCcAlfCrEnabledFlag( 0 ); pcSlice->setCcAlfCbApsId( -1 ); pcSlice->setCcAlfCrApsId( -1 ); } } if( picHeader->getLmcsEnabledFlag() && !pcSlice->getPictureHeaderInSliceHeader() ) { READ_FLAG( uiCode, "sh_lmcs_used_flag" ); pcSlice->setLmcsEnabledFlag( uiCode ); } else { pcSlice->setLmcsEnabledFlag( pcSlice->getPictureHeaderInSliceHeader() ? picHeader->getLmcsEnabledFlag() : false ); } if( picHeader->getExplicitScalingListEnabledFlag() && !pcSlice->getPictureHeaderInSliceHeader() ) { READ_FLAG( uiCode, "sh_explicit_scaling_list_used_flag" ); pcSlice->setExplicitScalingListUsed( uiCode ); } else { pcSlice->setExplicitScalingListUsed( pcSlice->getPictureHeaderInSliceHeader() ? picHeader->getExplicitScalingListEnabledFlag() : false ); } if( pps->getRplInfoInPhFlag() ) { pcSlice->setRPL( REF_PIC_LIST_0, *picHeader->getRPL( REF_PIC_LIST_0 ) ); pcSlice->setRPL( REF_PIC_LIST_1, *picHeader->getRPL( REF_PIC_LIST_1 ) ); } else if( pcSlice->getIdrPicFlag() && !sps->getIDRRefParamListPresent() ) { pcSlice->clearRPL( REF_PIC_LIST_0 ); pcSlice->clearRPL( REF_PIC_LIST_1 ); } else { parsePicOrSliceHeaderRPL( pcSlice, sps, pps ); } if( !pps->getRplInfoInPhFlag() && pcSlice->getIdrPicFlag() && !(sps->getIDRRefParamListPresent()) ) { pcSlice->setNumRefIdx(REF_PIC_LIST_0, 0); pcSlice->setNumRefIdx(REF_PIC_LIST_1, 0); } if( ( !pcSlice->isIntra() && pcSlice->getRPL( REF_PIC_LIST_0 )->getNumRefEntries() > 1 ) || ( pcSlice->isInterB() && pcSlice->getRPL( REF_PIC_LIST_1 )->getNumRefEntries() > 1 ) ) { READ_FLAG( uiCode, "sh_num_ref_idx_active_override_flag" ); if( uiCode ) { if( pcSlice->getRPL( REF_PIC_LIST_0 )->getNumRefEntries() > 1 ) { READ_UVLC( uiCode, "sh_num_ref_idx_active_minus1[ 0 ]" ); } else { uiCode = 0; } pcSlice->setNumRefIdx( REF_PIC_LIST_0, uiCode + 1 ); if( pcSlice->isInterB() ) { if( pcSlice->getRPL( REF_PIC_LIST_1 )->getNumRefEntries() > 1 ) { READ_UVLC( uiCode, "sh_num_ref_idx_active_minus1[ 1 ]" ); } else { uiCode = 0; } pcSlice->setNumRefIdx( REF_PIC_LIST_1, uiCode + 1 ); } else { pcSlice->setNumRefIdx( REF_PIC_LIST_1, 0 ); } } else { if( pcSlice->getRPL( REF_PIC_LIST_0 )->getNumRefEntries() >= pps->getNumRefIdxL0DefaultActive() ) { pcSlice->setNumRefIdx( REF_PIC_LIST_0, pps->getNumRefIdxL0DefaultActive() ); } else { pcSlice->setNumRefIdx( REF_PIC_LIST_0, pcSlice->getRPL( REF_PIC_LIST_0 )->getNumRefEntries() ); } if( pcSlice->isInterB() ) { if( pcSlice->getRPL( REF_PIC_LIST_1 )->getNumRefEntries() >= pps->getNumRefIdxL1DefaultActive() ) { pcSlice->setNumRefIdx( REF_PIC_LIST_1, pps->getNumRefIdxL1DefaultActive() ); } else { pcSlice->setNumRefIdx( REF_PIC_LIST_1, pcSlice->getRPL( REF_PIC_LIST_1 )->getNumRefEntries() ); } } else { pcSlice->setNumRefIdx( REF_PIC_LIST_1, 0 ); } } } else { if( !pcSlice->isIntra() ) { pcSlice->setNumRefIdx( REF_PIC_LIST_0, pcSlice->getRPL( REF_PIC_LIST_0 )->getNumRefEntries() ); } if( pcSlice->isInterB() ) { pcSlice->setNumRefIdx( REF_PIC_LIST_1, pcSlice->getRPL( REF_PIC_LIST_1 )->getNumRefEntries() ); } } if( pcSlice->isInterP() || pcSlice->isInterB() ) { CHECK_RECOVERABLE( pcSlice->getNumRefIdx(REF_PIC_LIST_0) == 0, "Number of active entries in RPL0 of P or B picture shall be greater than 0" ); if( pcSlice->isInterB() ) { CHECK_RECOVERABLE( pcSlice->getNumRefIdx(REF_PIC_LIST_1) == 0, "Number of active entries in RPL1 of B picture shall be greater than 0" ); } } pcSlice->setCabacInitFlag( false ); // default if( pps->getCabacInitPresentFlag() && !pcSlice->isIntra() ) { READ_FLAG( uiCode, "sh_cabac_init_flag" ); pcSlice->setCabacInitFlag( uiCode ? true : false ); } if( picHeader->getEnableTMVPFlag() ) { if( pcSlice->getSliceType() == P_SLICE ) { pcSlice->setColFromL0Flag( true ); } else if( !pps->getRplInfoInPhFlag() && pcSlice->getSliceType() == B_SLICE ) { READ_FLAG( uiCode, "sh_collocated_from_l0_flag" ); pcSlice->setColFromL0Flag( uiCode ); } else { pcSlice->setColFromL0Flag( picHeader->getPicColFromL0Flag() ); } if( !pps->getRplInfoInPhFlag() ) { if( pcSlice->getSliceType() != I_SLICE && ( ( pcSlice->getColFromL0Flag() == 1 && pcSlice->getNumRefIdx( REF_PIC_LIST_0 ) > 1 ) || ( pcSlice->getColFromL0Flag() == 0 && pcSlice->getNumRefIdx( REF_PIC_LIST_1 ) > 1 ) ) ) { READ_UVLC( uiCode, "sh_collocated_ref_idx" ); pcSlice->setColRefIdx( uiCode ); } else { pcSlice->setColRefIdx( 0 ); } } else { pcSlice->setColRefIdx( picHeader->getColRefIdx() ); } } if( ( pps->getUseWP() && pcSlice->getSliceType() == P_SLICE ) || ( pps->getWPBiPred() && pcSlice->getSliceType() == B_SLICE ) ) { if( pps->getWpInfoInPhFlag() ) { CHECK_RECOVERABLE( pcSlice->getNumRefIdx(REF_PIC_LIST_0) > picHeader->getNumL0Weights(), "ERROR: Number of active reference picture L0 is greater than the number of weighted prediction signalled in Picture Header" ); CHECK_RECOVERABLE( pcSlice->getNumRefIdx(REF_PIC_LIST_1) > picHeader->getNumL1Weights(), "ERROR: Number of active reference picture L1 is greater than the number of weighted prediction signalled in Picture Header" ); pcSlice->setWpScaling( picHeader->getWpScalingAll() ); } else { parsePredWeightTable( pcSlice, sps ); } pcSlice->initWpScaling( sps ); } else { WPScalingParam *wp; for( int iNumRef = 0 ; iNumRef < ( ( pcSlice->getSliceType() == B_SLICE ) ? 2 : 1 ); iNumRef++ ) { RefPicList eRefPicList = ( iNumRef ? REF_PIC_LIST_1 : REF_PIC_LIST_0 ); for( int iRefIdx=0; iRefIdxgetNumRefIdx( eRefPicList ); iRefIdx++ ) { pcSlice->getWpScaling( eRefPicList, iRefIdx, wp ); wp[0].bPresentFlag = false; wp[1].bPresentFlag = false; wp[2].bPresentFlag = false; } } } int qpDelta = 0; if( pps->getQpDeltaInfoInPhFlag() ) { qpDelta = picHeader->getQpDelta(); } else { READ_SVLC( iCode, "sh_qp_delta" ); qpDelta = iCode; } pcSlice->setSliceQp( 26 + pps->getPicInitQPMinus26() + qpDelta ); pcSlice->setSliceQpBase( pcSlice->getSliceQp() ); CHECK_RECOVERABLE( pcSlice->getSliceQp() < -sps->getQpBDOffset( CHANNEL_TYPE_LUMA ), "Invalid slice QP delta" ); CHECK_RECOVERABLE( pcSlice->getSliceQp() > MAX_QP, "Invalid slice QP" ); if( pps->getSliceChromaQpFlag() ) { if( numValidComp > COMPONENT_Cb ) { READ_SVLC( iCode, "sh_cb_qp_offset" ); pcSlice->setSliceChromaQpDelta( COMPONENT_Cb, iCode ); CHECK_RECOVERABLE( pcSlice->getSliceChromaQpDelta( COMPONENT_Cb ) < -12, "Invalid chroma QP offset" ); CHECK_RECOVERABLE( pcSlice->getSliceChromaQpDelta( COMPONENT_Cb ) > 12, "Invalid chroma QP offset" ); CHECK_RECOVERABLE( ( pps->getQpOffset( COMPONENT_Cb ) + pcSlice->getSliceChromaQpDelta( COMPONENT_Cb ) ) < -12, "Invalid chroma QP offset" ); CHECK_RECOVERABLE( ( pps->getQpOffset( COMPONENT_Cb ) + pcSlice->getSliceChromaQpDelta( COMPONENT_Cb ) ) > 12, "Invalid chroma QP offset" ); } if( numValidComp > COMPONENT_Cr ) { READ_SVLC( iCode, "sh_cr_qp_offset" ); pcSlice->setSliceChromaQpDelta( COMPONENT_Cr, iCode ); CHECK_RECOVERABLE( pcSlice->getSliceChromaQpDelta( COMPONENT_Cr ) < -12, "Invalid chroma QP offset" ); CHECK_RECOVERABLE( pcSlice->getSliceChromaQpDelta( COMPONENT_Cr ) > 12, "Invalid chroma QP offset" ); CHECK_RECOVERABLE( ( pps->getQpOffset( COMPONENT_Cr ) + pcSlice->getSliceChromaQpDelta( COMPONENT_Cr ) ) < -12, "Invalid chroma QP offset" ); CHECK_RECOVERABLE( ( pps->getQpOffset( COMPONENT_Cr ) + pcSlice->getSliceChromaQpDelta( COMPONENT_Cr ) ) > 12, "Invalid chroma QP offset" ); if( sps->getJointCbCrEnabledFlag() ) { READ_SVLC( iCode, "sh_joint_cbcr_qp_offset" ); pcSlice->setSliceChromaQpDelta( JOINT_CbCr, iCode ); CHECK_RECOVERABLE( pcSlice->getSliceChromaQpDelta( JOINT_CbCr ) < -12, "Invalid chroma QP offset" ); CHECK_RECOVERABLE( pcSlice->getSliceChromaQpDelta( JOINT_CbCr ) > 12, "Invalid chroma QP offset" ); CHECK_RECOVERABLE( ( pps->getQpOffset( JOINT_CbCr ) + pcSlice->getSliceChromaQpDelta( JOINT_CbCr ) ) < -12, "Invalid chroma QP offset" ); CHECK_RECOVERABLE( ( pps->getQpOffset( JOINT_CbCr ) + pcSlice->getSliceChromaQpDelta( JOINT_CbCr ) ) > 12, "Invalid chroma QP offset" ); } } } if( pps->getCuChromaQpOffsetEnabledFlag() ) { READ_FLAG( uiCode, "sh_cu_chroma_qp_offset_enabled_flag"); pcSlice->setUseChromaQpAdj( uiCode != 0 ); } else { pcSlice->setUseChromaQpAdj( false ); } if( sps->getUseSAO() && !pps->getSaoInfoInPhFlag() ) { READ_FLAG( uiCode, "sh_sao_luma_used_flag" ); pcSlice->setSaoEnabledFlag( CHANNEL_TYPE_LUMA, (bool)uiCode ); if( bChroma ) { READ_FLAG( uiCode, "sh_sao_chroma_used_flag" ); pcSlice->setSaoEnabledFlag( CHANNEL_TYPE_CHROMA, (bool)uiCode ); } } if( pps->getDeblockingFilterControlPresentFlag() ) { if( pps->getDeblockingFilterOverrideEnabledFlag() && !pps->getDbfInfoInPhFlag() ) { READ_FLAG ( uiCode, "sh_deblocking_params_present_flag" ); pcSlice->setDeblockingFilterOverrideFlag( uiCode ? true : false ); } else { pcSlice->setDeblockingFilterOverrideFlag( 0 ); } if(pcSlice->getDeblockingFilterOverrideFlag()) { if (!pps->getPPSDeblockingFilterDisabledFlag()) { READ_FLAG ( uiCode, "sh_deblocking_filter_disabled_flag" ); pcSlice->setDeblockingFilterDisable( uiCode ? 1 : 0 ); } else { pcSlice->setDeblockingFilterDisable( false ); } if( !pcSlice->getDeblockingFilterDisable() ) { READ_SVLC( iCode, "sh_luma_beta_offset_div2" ); pcSlice->setDeblockingFilterBetaOffsetDiv2( iCode ); CHECK_RECOVERABLE( pcSlice->getDeblockingFilterBetaOffsetDiv2() < -12 || pcSlice->getDeblockingFilterBetaOffsetDiv2() > 12, "Invalid deblocking filter configuration" ); READ_SVLC( iCode, "sh_luma_tc_offset_div2" ); pcSlice->setDeblockingFilterTcOffsetDiv2( iCode ); CHECK_RECOVERABLE( pcSlice->getDeblockingFilterTcOffsetDiv2() < -12 || pcSlice->getDeblockingFilterTcOffsetDiv2() > 12, "Invalid deblocking filter configuration" ); if( pps->getPPSChromaToolFlag() ) { READ_SVLC( iCode, "sh_cb_beta_offset_div2" ); pcSlice->setDeblockingFilterCbBetaOffsetDiv2( iCode ); CHECK_RECOVERABLE( pcSlice->getDeblockingFilterCbBetaOffsetDiv2() < -12 || pcSlice->getDeblockingFilterCbBetaOffsetDiv2() > 12, "Invalid deblocking filter configuration" ); READ_SVLC( iCode, "sh_cb_tc_offset_div2" ); pcSlice->setDeblockingFilterCbTcOffsetDiv2( iCode ); CHECK_RECOVERABLE( pcSlice->getDeblockingFilterCbTcOffsetDiv2() < -12 || pcSlice->getDeblockingFilterCbTcOffsetDiv2() > 12, "Invalid deblocking filter configuration" ); READ_SVLC( iCode, "sh_cr_beta_offset_div2" ); pcSlice->setDeblockingFilterCrBetaOffsetDiv2( iCode ); CHECK_RECOVERABLE( pcSlice->getDeblockingFilterCrBetaOffsetDiv2() < -12 || pcSlice->getDeblockingFilterCrBetaOffsetDiv2() > 12, "Invalid deblocking filter configuration" ); READ_SVLC( iCode, "sh_cr_tc_offset_div2" ); pcSlice->setDeblockingFilterCrTcOffsetDiv2( iCode ); CHECK_RECOVERABLE( pcSlice->getDeblockingFilterCrTcOffsetDiv2() < -12 || pcSlice->getDeblockingFilterCrTcOffsetDiv2() > 12, "Invalid deblocking filter configuration" ); } else { pcSlice->setDeblockingFilterCbBetaOffsetDiv2 ( pcSlice->getDeblockingFilterBetaOffsetDiv2() ); pcSlice->setDeblockingFilterCbTcOffsetDiv2 ( pcSlice->getDeblockingFilterTcOffsetDiv2() ); pcSlice->setDeblockingFilterCrBetaOffsetDiv2 ( pcSlice->getDeblockingFilterBetaOffsetDiv2() ); pcSlice->setDeblockingFilterCrTcOffsetDiv2 ( pcSlice->getDeblockingFilterTcOffsetDiv2() ); } } } else { pcSlice->setDeblockingFilterDisable ( picHeader->getDeblockingFilterDisable() ); pcSlice->setDeblockingFilterBetaOffsetDiv2 ( picHeader->getDeblockingFilterBetaOffsetDiv2() ); pcSlice->setDeblockingFilterTcOffsetDiv2 ( picHeader->getDeblockingFilterTcOffsetDiv2() ); pcSlice->setDeblockingFilterCbBetaOffsetDiv2( picHeader->getDeblockingFilterCbBetaOffsetDiv2() ); pcSlice->setDeblockingFilterCbTcOffsetDiv2 ( picHeader->getDeblockingFilterCbTcOffsetDiv2() ); pcSlice->setDeblockingFilterCrBetaOffsetDiv2( picHeader->getDeblockingFilterCrBetaOffsetDiv2() ); pcSlice->setDeblockingFilterCrTcOffsetDiv2 ( picHeader->getDeblockingFilterCrTcOffsetDiv2() ); } } else { pcSlice->setDeblockingFilterDisable ( false ); pcSlice->setDeblockingFilterBetaOffsetDiv2( 0 ); pcSlice->setDeblockingFilterTcOffsetDiv2 ( 0 ); pcSlice->setDeblockingFilterCbBetaOffsetDiv2( 0 ); pcSlice->setDeblockingFilterCbTcOffsetDiv2 ( 0 ); pcSlice->setDeblockingFilterCrBetaOffsetDiv2( 0 ); pcSlice->setDeblockingFilterCrTcOffsetDiv2 ( 0 ); } // dependent quantization if( sps->getDepQuantEnabledFlag() ) { READ_FLAG( uiCode, "sh_dep_quant_used_flag" ); pcSlice->setDepQuantEnabledFlag( uiCode != 0 ); } else { pcSlice->setDepQuantEnabledFlag( false ); } // sign data hiding if( sps->getSignDataHidingEnabledFlag() && !pcSlice->getDepQuantEnabledFlag() ) { READ_FLAG( uiCode, "sh_sign_data_hiding_used_flag" ); pcSlice->setSignDataHidingEnabledFlag( uiCode != 0 ); } else { pcSlice->setSignDataHidingEnabledFlag( false ); } // signal TS residual coding disabled flag if( sps->getTransformSkipEnabledFlag() && !pcSlice->getDepQuantEnabledFlag() && !pcSlice->getSignDataHidingEnabledFlag() ) { READ_FLAG( uiCode, "sh_ts_residual_coding_disabled_flag" ); pcSlice->setTSResidualCodingDisabledFlag( uiCode != 0 ); } else { pcSlice->setTSResidualCodingDisabledFlag( false ); } if( pcSlice->getFirstCtuRsAddrInSlice() == 0 ) { pcSlice->setDefaultClpRng( *sps ); } if( pps->getSliceHeaderExtensionPresentFlag() ) { READ_UVLC( uiCode, "sh_slice_header_extension_length "); for( int i = 0; i < uiCode; i++ ) { uint32_t ignore_; READ_CODE( 8, ignore_, "sh_slice_header_extension_data_byte[ i ]" ); } } std::vector entryPointOffset; pcSlice->setNumEntryPoints( sps, pps ); if( pcSlice->getNumEntryPoints() > 0 ) { uint32_t offsetLenMinus1; READ_UVLC( offsetLenMinus1, "sh_offset_len_minus1" ); entryPointOffset.resize( pcSlice->getNumEntryPoints() ); for( uint32_t idx = 0; idx < pcSlice->getNumEntryPoints(); idx++ ) { READ_CODE( offsetLenMinus1 + 1, uiCode, "sh_entry_point_offset_minus1[i]" ); entryPointOffset[idx] = uiCode + 1; } } #if RExt__DECODER_DEBUG_BIT_STATISTICS CodingStatistics::IncrementStatisticEP(STATS__BYTE_ALIGNMENT_BITS,m_pcBitstream->readByteAlignment(),0); #else m_pcBitstream->readByteAlignment(); #endif pcSlice->clearSubstreamSizes(); if( pcSlice->getNumEntryPoints() > 0 ) { int endOfSliceHeaderLocation = m_pcBitstream->getByteLocation(); // Adjust endOfSliceHeaderLocation to account for emulation prevention bytes in the slice segment header for( uint32_t curByteIdx = 0; curByteIdxnumEmulationPreventionBytesRead(); curByteIdx++ ) { if( m_pcBitstream->getEmulationPreventionByteLocation( curByteIdx ) < endOfSliceHeaderLocation ) { endOfSliceHeaderLocation++; } } int curEntryPointOffset = 0; int prevEntryPointOffset = 0; for( uint32_t idx = 0; idx < entryPointOffset.size(); idx++ ) { curEntryPointOffset += entryPointOffset[ idx ]; int emulationPreventionByteCount = 0; for( uint32_t curByteIdx = 0; curByteIdxnumEmulationPreventionBytesRead(); curByteIdx++ ) { if( m_pcBitstream->getEmulationPreventionByteLocation( curByteIdx ) >= ( prevEntryPointOffset + endOfSliceHeaderLocation ) && m_pcBitstream->getEmulationPreventionByteLocation( curByteIdx ) < ( curEntryPointOffset + endOfSliceHeaderLocation ) ) { emulationPreventionByteCount++; } } entryPointOffset[ idx ] -= emulationPreventionByteCount; prevEntryPointOffset = curEntryPointOffset; pcSlice->addSubstreamSize(entryPointOffset [ idx ] ); } } return; } template void HLSyntaxReader::parsePicOrSliceHeaderRPL( HeaderT* header, const SPS* sps, const PPS* pps ) { uint32_t uiCode; // List0 and List1 for( int iListIdx = 0; iListIdx < 2; iListIdx++ ) { const RefPicList listIdx = static_cast( iListIdx ); bool readExplicitRPL = false; // copy L1 index from L0 index if( listIdx == REF_PIC_LIST_1 && !pps->getRpl1IdxPresentFlag() ) { const int rpl0idx = header->getRPLIdx( REF_PIC_LIST_0 ); header->setRPLIdx( REF_PIC_LIST_1, rpl0idx ); readExplicitRPL = ( rpl0idx == -1 ); } // RPL in picture header or SPS else if( sps->getNumRPL( listIdx ) == 0 ) { readExplicitRPL = true; } else { READ_FLAG( uiCode, "ref_pic_list_sps_flag[ listidx ]" ); readExplicitRPL = !uiCode; } // explicitly carried in this PH or SH if( readExplicitRPL ) { header->clearRPL( listIdx ); parseRefPicList( header->getRPL( listIdx ), -1, sps ); header->setRPLIdx( listIdx, -1 ); } // use list from SPS else { if( listIdx == REF_PIC_LIST_1 && !pps->getRpl1IdxPresentFlag() ) { header->setRPL( listIdx, sps->getRPLList( listIdx )[header->getRPLIdx( listIdx )] ); } else if( sps->getNumRPL( listIdx ) > 1 ) { int numBits = (int)ceil( log2( sps->getNumRPL( listIdx ) ) ); READ_CODE( numBits, uiCode, "ref_pic_list_idx[ listIdx ]" ); header->setRPLIdx( listIdx, uiCode ); header->setRPL( listIdx, sps->getRPLList( listIdx )[uiCode] ); } else { header->setRPLIdx( listIdx, 0 ); header->setRPL( listIdx, sps->getRPLList( listIdx )[0] ); } } // Deal POC Msb cycle signalling for LTRP auto* rpl = header->getRPL( listIdx ); for( int i = 0; i < rpl->getNumberOfLongtermPictures() +rpl->getNumberOfShorttermPictures(); i++ ) { rpl->setDeltaPocMSBPresentFlag( i, false ); rpl->setDeltaPocMSBCycleLT( i, 0 ); } if( rpl->getNumberOfLongtermPictures() ) { for( int i = 0; i < rpl->getNumberOfLongtermPictures() + rpl->getNumberOfShorttermPictures(); i++ ) { if( rpl->isRefPicLongterm( i ) ) { if( rpl->getLtrpInSliceHeaderFlag() ) { READ_CODE( sps->getBitsForPOC(), uiCode, "poc_lsb_lt[i][j]" ); rpl->setRefPicIdentifier( i, uiCode, true, false, 0 ); } READ_FLAG( uiCode, "delta_poc_msb_present_flag[i][j]" ); rpl->setDeltaPocMSBPresentFlag( i, uiCode ? true : false ); if( uiCode ) { READ_UVLC( uiCode, "delta_poc_msb_cycle_lt[i][j]" ); rpl->setDeltaPocMSBCycleLT( i, uiCode ); } } } } } } void HLSyntaxReader::parseConstraintInfo( ConstraintInfo *cinfo ) { uint32_t symbol; READ_FLAG( symbol, "gci_present_flag" ); cinfo->setGciPresentFlag( symbol ? true : false ); if( cinfo->getGciPresentFlag() ) { /* general */ READ_FLAG( symbol, "gci_intra_only_constraint_flag" ); cinfo->setIntraOnlyConstraintFlag( symbol ? true : false ); READ_FLAG( symbol, "gci_all_layers_independent_constraint_flag" ); cinfo->setAllLayersIndependentConstraintFlag( symbol ? true : false ); READ_FLAG( symbol, "gci_one_au_only_constraint_flag" ); cinfo->setOnePictureOnlyConstraintFlag( symbol ? true : false ); /* picture format */ READ_CODE( 4, symbol, "gci_sixteen_minus_max_bitdepth_constraint_idc" ); cinfo->setMaxBitDepthConstraintIdc( symbol>8 ? 16 : ( 16 - symbol ) ); CHECK_RECOVERABLE(symbol>8, "gci_sixteen_minus_max_bitdepth_constraint_idc shall be in the range 0 to 8, inclusive"); READ_CODE( 2, symbol, "gci_three_minus_max_chroma_format_constraint_idc" ); cinfo->setMaxChromaFormatConstraintIdc( (ChromaFormat)( 3 - symbol ) ); /* NAL unit type related */ READ_FLAG( symbol, "gci_no_mixed_nalu_types_in_pic_constraint_flag" ); cinfo->setNoMixedNaluTypesInPicConstraintFlag( symbol > 0 ? true : false ); READ_FLAG( symbol, "gci_no_trail_constraint_flag" ); cinfo->setNoTrailConstraintFlag( symbol > 0 ? true : false ); READ_FLAG( symbol, "gci_no_stsa_constraint_flag" ); cinfo->setNoStsaConstraintFlag( symbol > 0 ? true : false ); READ_FLAG( symbol, "gci_no_rasl_constraint_flag" ); cinfo->setNoRaslConstraintFlag( symbol > 0 ? true : false ); READ_FLAG( symbol, "gci_no_radl_constraint_flag" ); cinfo->setNoRadlConstraintFlag( symbol > 0 ? true : false ); READ_FLAG( symbol, "gci_no_idr_constraint_flag" ); cinfo->setNoIdrConstraintFlag( symbol > 0 ? true : false ); READ_FLAG( symbol, "gci_no_cra_constraint_flag" ); cinfo->setNoCraConstraintFlag( symbol > 0 ? true : false ); READ_FLAG( symbol, "gci_no_gdr_constraint_flag" ); cinfo->setNoGdrConstraintFlag( symbol > 0 ? true : false ); READ_FLAG( symbol, "gci_no_aps_constraint_flag" ); cinfo->setNoApsConstraintFlag( symbol > 0 ? true : false ); READ_FLAG( symbol, "gci_no_idr_rpl_constraint_flag" ); cinfo->setNoIdrRplConstraintFlag( symbol > 0 ? true : false ); /* tile, slice, subpicture partitioning */ READ_FLAG( symbol, "gci_one_tile_per_pic_constraint_flag" ); cinfo->setOneTilePerPicConstraintFlag( symbol > 0 ? true : false ); READ_FLAG( symbol, "gci_pic_header_in_slice_header_constraint_flag" ); cinfo->setPicHeaderInSliceHeaderConstraintFlag( symbol > 0 ? true : false ); READ_FLAG( symbol, "gci_one_slice_per_pic_constraint_flag" ); cinfo->setOneSlicePerPicConstraintFlag( symbol > 0 ? true : false ); READ_FLAG( symbol, "gci_no_rectangular_slice_constraint_flag" ); cinfo->setNoRectSliceConstraintFlag( symbol > 0 ? true : false ); READ_FLAG( symbol, "gci_one_slice_per_subpic_constraint_flag" ); cinfo->setOneSlicePerSubpicConstraintFlag( symbol > 0 ? true : false ); READ_FLAG( symbol, "gci_no_subpic_info_constraint_flag" ); cinfo->setNoSubpicInfoConstraintFlag( symbol > 0 ? true : false ); /* CTU and block partitioning */ READ_CODE( 2, symbol, "gci_three_minus_max_log2_ctu_size_constraint_idc"); cinfo->setMaxLog2CtuSizeConstraintIdc( ( ( 3 - symbol ) + 5 ) ); READ_FLAG( symbol, "gci_no_partition_constraints_override_constraint_flag"); cinfo->setNoPartitionConstraintsOverrideConstraintFlag( symbol > 0 ? true : false ); READ_FLAG( symbol, "gci_no_mtt_constraint_flag"); cinfo->setNoMttConstraintFlag( symbol > 0 ? true : false); READ_FLAG( symbol, "gci_no_qtbtt_dual_tree_intra_constraint_flag"); cinfo->setNoQtbttDualTreeIntraConstraintFlag( symbol > 0 ? true : false ); /* intra */ READ_FLAG( symbol, "gci_no_palette_constraint_flag" ); cinfo->setNoPaletteConstraintFlag( symbol > 0 ? true : false ); READ_FLAG( symbol, "gci_no_ibc_constraint_flag" ); cinfo->setNoIbcConstraintFlag( symbol > 0 ? true : false ); READ_FLAG( symbol, "gci_no_isp_constraint_flag" ); cinfo->setNoIspConstraintFlag( symbol > 0 ? true : false ); READ_FLAG( symbol, "gci_no_mrl_constraint_flag" ); cinfo->setNoMrlConstraintFlag( symbol > 0 ? true : false ); READ_FLAG( symbol, "gci_no_mip_constraint_flag" ); cinfo->setNoMipConstraintFlag( symbol > 0 ? true : false ); READ_FLAG( symbol, "gci_no_cclm_constraint_flag" ); cinfo->setNoCclmConstraintFlag( symbol > 0 ? true : false ); /* inter */ READ_FLAG( symbol, "gci_no_ref_pic_resampling_constraint_flag" ); cinfo->setNoRprConstraintFlag( symbol > 0 ? true : false ); READ_FLAG( symbol, "gci_no_res_change_in_clvs_constraint_flag" ); cinfo->setNoResChangeInClvsConstraintFlag( symbol > 0 ? true : false ); READ_FLAG( symbol, "gci_no_weighted_prediction_constraint_flag" ); cinfo->setNoWeightedPredictionConstraintFlag( symbol > 0 ? true : false ); READ_FLAG( symbol, "gci_no_ref_wraparound_constraint_flag" ); cinfo->setNoRefWraparoundConstraintFlag( symbol > 0 ? true : false ); READ_FLAG( symbol, "gci_no_temporal_mvp_constraint_flag" ); cinfo->setNoTemporalMvpConstraintFlag( symbol > 0 ? true : false ); READ_FLAG( symbol, "gci_no_sbtmvp_constraint_flag" ); cinfo->setNoSbtmvpConstraintFlag( symbol > 0 ? true : false ); READ_FLAG( symbol, "gci_no_amvr_constraint_flag" ); cinfo->setNoAmvrConstraintFlag( symbol > 0 ? true : false ); READ_FLAG( symbol, "gci_no_bdof_constraint_flag" ); cinfo->setNoBdofConstraintFlag( symbol > 0 ? true : false ); READ_FLAG( symbol, "gci_no_smvd_constraint_flag" ); cinfo->setNoSmvdConstraintFlag( symbol > 0 ? true : false ); READ_FLAG( symbol, "gci_no_dmvr_constraint_flag" ); cinfo->setNoDmvrConstraintFlag( symbol > 0 ? true : false ); READ_FLAG( symbol, "gci_no_mmvd_constraint_flag" ); cinfo->setNoMmvdConstraintFlag( symbol > 0 ? true : false ); READ_FLAG( symbol, "gci_no_affine_motion_constraint_flag" ); cinfo->setNoAffineMotionConstraintFlag( symbol > 0 ? true : false ); READ_FLAG( symbol, "gci_no_prof_constraint_flag" ); cinfo->setNoProfConstraintFlag( symbol > 0 ? true : false ); READ_FLAG( symbol, "gci_no_bcw_constraint_flag" ); cinfo->setNoBcwConstraintFlag( symbol > 0 ? true : false ); READ_FLAG( symbol, "gci_no_ciip_constraint_flag" ); cinfo->setNoCiipConstraintFlag( symbol > 0 ? true : false ); READ_FLAG( symbol, "gci_no_gpm_constraint_flag" ); cinfo->setNoGeoConstraintFlag( symbol > 0 ? true : false ); /* transform, quantization, residual */ READ_FLAG( symbol, "gci_no_luma_transform_size_64_constraint_flag" ); cinfo->setNoLumaTransformSize64ConstraintFlag( symbol > 0 ? true : false ); READ_FLAG( symbol, "gci_no_transform_skip_constraint_flag" ); cinfo->setNoTransformSkipConstraintFlag( symbol > 0 ? true : false ); READ_FLAG( symbol, "gci_no_bdpcm_constraint_flag" ); cinfo->setNoBDPCMConstraintFlag( symbol > 0 ? true : false ); READ_FLAG( symbol, "gci_no_mts_constraint_flag" ); cinfo->setNoMtsConstraintFlag( symbol > 0 ? true : false ); READ_FLAG( symbol, "gci_no_lfnst_constraint_flag" ); cinfo->setNoLfnstConstraintFlag( symbol > 0 ? true : false ); READ_FLAG( symbol, "gci_no_joint_cbcr_constraint_flag" ); cinfo->setNoJointCbCrConstraintFlag( symbol > 0 ? true : false ); READ_FLAG( symbol, "gci_no_sbt_constraint_flag" ); cinfo->setNoSbtConstraintFlag( symbol > 0 ? true : false ); READ_FLAG( symbol, "gci_no_act_constraint_flag" ); cinfo->setNoActConstraintFlag( symbol > 0 ? true : false ); READ_FLAG( symbol, "gci_no_explicit_scaling_list_constraint_flag" ); cinfo->setNoExplicitScaleListConstraintFlag( symbol > 0 ? true : false ); READ_FLAG( symbol, "gci_no_dep_quant_constraint_flag" ); cinfo->setNoDepQuantConstraintFlag( symbol > 0 ? true : false ); READ_FLAG( symbol, "gci_no_sign_data_hiding_constraint_flag" ); cinfo->setNoSignDataHidingConstraintFlag( symbol > 0 ? true : false) ; READ_FLAG( symbol, "gci_no_cu_qp_delta_constraint_flag" ); cinfo->setNoQpDeltaConstraintFlag( symbol > 0 ? true : false ); READ_FLAG( symbol, "gci_no_chroma_qp_offset_constraint_flag" ); cinfo->setNoChromaQpOffsetConstraintFlag( symbol > 0 ? true : false ); /* loop filter */ READ_FLAG( symbol, "gci_no_sao_constraint_flag" ); cinfo->setNoSaoConstraintFlag( symbol > 0 ? true : false ); READ_FLAG( symbol, "gci_no_alf_constraint_flag" ); cinfo->setNoAlfConstraintFlag( symbol > 0 ? true : false ); READ_FLAG( symbol, "gci_no_ccalf_constraint_flag" ); cinfo->setNoCCAlfConstraintFlag( symbol > 0 ? true : false ); READ_FLAG( symbol, "gci_no_lmcs_constraint_flag" ); cinfo->setNoLmcsConstraintFlag( symbol > 0 ? true : false ); READ_FLAG( symbol, "gci_no_ladf_constraint_flag" ); cinfo->setNoLadfConstraintFlag( symbol > 0 ? true : false ); READ_FLAG( symbol, "gci_no_virtual_boundaries_constraint_flag" ); cinfo->setNoVirtualBoundaryConstraintFlag( symbol > 0 ? true : false ); READ_CODE( 8, symbol, "gci_num_reserved_bits" ); uint32_t const numReservedBits = symbol; for (int i = 0; i < numReservedBits; i++) { READ_FLAG( symbol, "gci_reserved_zero_bit" ); CHECK_RECOVERABLE( symbol != 0, "gci_reserved_zero_bit not equal to zero" ); } } while( !isByteAligned() ) { READ_FLAG( symbol, "gci_alignment_zero_bit" ); CHECK_RECOVERABLE( symbol != 0, "gci_alignment_zero_bit not equal to zero" ); } } void HLSyntaxReader::parseProfileTierLevel( ProfileTierLevel *ptl, bool profileTierPresentFlag, int maxNumSubLayersMinus1 ) { uint32_t symbol; if( profileTierPresentFlag ) { READ_CODE( 7, symbol, "general_profile_idc" ); ptl->setProfileIdc( Profile::Name( symbol ) ); READ_FLAG( symbol, "general_tier_flag" ); ptl->setTierFlag( symbol ? Tier::HIGH : Tier::MAIN ); } READ_CODE( 8, symbol, "general_level_idc" ); ptl->setLevelIdc( vvdecLevel( symbol ) ); READ_FLAG( symbol, "ptl_frame_only_constraint_flag" ); ptl->setFrameOnlyConstraintFlag( symbol ); READ_FLAG( symbol, "ptl_multilayer_enabled_flag" ); ptl->setMultiLayerEnabledFlag( symbol ); CHECK_RECOVERABLE( ( ptl->getProfileIdc() == Profile::MAIN_10 || ptl->getProfileIdc() == Profile::MAIN_10_444 || ptl->getProfileIdc() == Profile::MAIN_10_STILL_PICTURE || ptl->getProfileIdc() == Profile::MAIN_10_444_STILL_PICTURE ) && symbol, "ptl_multilayer_enabled_flag shall be equal to 0 for non-multilayer profiles"); CHECK_UNSUPPORTED( ptl->getProfileIdc() == Profile::MULTILAYER_MAIN_10 || ptl->getProfileIdc() == Profile::MULTILAYER_MAIN_10_STILL_PICTURE || ptl->getProfileIdc() == Profile::MULTILAYER_MAIN_10_444 || ptl->getProfileIdc() == Profile::MULTILAYER_MAIN_10_444_STILL_PICTURE, "Multilayer profiles not yet supported" ); if( ptl->getProfileIdc() == Profile::MAIN_10_444 || ptl->getProfileIdc() == Profile::MAIN_10_444_STILL_PICTURE ) { msg( WARNING, "Warning: MAIN_10_444 and MAIN_10_444_STILL_PICTURE is still experimental.\n" ); } if( profileTierPresentFlag ) { parseConstraintInfo( ptl->getConstraintInfo() ); } for( int i = maxNumSubLayersMinus1 - 1; i >= 0; i-- ) { READ_FLAG( symbol, "sub_layer_level_present_flag[i]" ); ptl->setSubLayerLevelPresentFlag( i, symbol ); } while( !isByteAligned() ) { READ_FLAG( symbol, "ptl_reserved_zero_bit" ); CHECK_RECOVERABLE( symbol != 0, "ptl_reserved_zero_bit not equal to zero" ); } for( int i = maxNumSubLayersMinus1 - 1; i >= 0; i-- ) { if( ptl->getSubLayerLevelPresentFlag( i ) ) { READ_CODE( 8, symbol, "sub_layer_level_idc[i]" ); ptl->setSubLayerLevelIdc( i, vvdecLevel( symbol ) ); } } ptl->setSubLayerLevelIdc( maxNumSubLayersMinus1, ptl->getLevelIdc() ); for( int i = maxNumSubLayersMinus1 - 1; i >= 0; i-- ) { if( !ptl->getSubLayerLevelPresentFlag( i ) ) { ptl->setSubLayerLevelIdc( i, ptl->getSubLayerLevelIdc( i + 1 ) ); } } if( profileTierPresentFlag ) { READ_CODE( 8, symbol, "ptl_num_sub_profiles" ); uint8_t numSubProfiles = symbol; ptl->setNumSubProfile( numSubProfiles ); for( int i = 0; i < numSubProfiles; i++ ) { READ_CODE( 32, symbol, "general_sub_profile_idc[i]" ); ptl->setSubProfileIdc( i, symbol ); } } } // ==================================================================================================================== // Protected member functions // ==================================================================================================================== //! parse explicit wp tables void HLSyntaxReader::parsePredWeightTable( Slice* pcSlice, const SPS *sps ) { WPScalingParam* wp; const ChromaFormat chFmt = sps->getChromaFormatIdc(); const int numValidComp = int( getNumberValidComponents( chFmt ) ); const bool bChroma = ( chFmt != CHROMA_400 ); const SliceType eSliceType = pcSlice->getSliceType(); const int iNbRef = ( eSliceType == B_SLICE ) ? 2 : 1; uint32_t uiLog2WeightDenomLuma = 0, uiLog2WeightDenomChroma = 0; uint32_t uiTotalSignalledWeightFlags = 0; int iDeltaDenom; // decode delta_luma_log2_weight_denom : READ_UVLC( uiLog2WeightDenomLuma, "luma_log2_weight_denom" ); CHECK_RECOVERABLE( uiLog2WeightDenomLuma > 7, "Invalid code" ); if( bChroma ) { READ_SVLC( iDeltaDenom, "delta_chroma_log2_weight_denom" ); CHECK_RECOVERABLE( ( iDeltaDenom + (int)uiLog2WeightDenomLuma ) < 0, "Invalid code" ); CHECK_RECOVERABLE( ( iDeltaDenom + (int)uiLog2WeightDenomLuma ) > 7, "Invalid code" ); uiLog2WeightDenomChroma = (uint32_t)( iDeltaDenom + uiLog2WeightDenomLuma ); } for( int iNumRef=0 ; iNumRef < iNbRef ; iNumRef++ ) // loop over l0 and l1 syntax elements { RefPicList eRefPicList = ( iNumRef ? REF_PIC_LIST_1 : REF_PIC_LIST_0 ); for ( int iRefIdx=0 ; iRefIdxgetNumRefIdx( eRefPicList ) ; iRefIdx++ ) { pcSlice->getWpScaling( eRefPicList, iRefIdx, wp ); wp[COMPONENT_Y].uiLog2WeightDenom = uiLog2WeightDenomLuma; for( int j = 1; j < numValidComp; j++ ) { wp[j].uiLog2WeightDenom = uiLog2WeightDenomChroma; } uint32_t uiCode; READ_FLAG( uiCode, iNumRef == 0 ? "luma_weight_l0_flag[i]" : "luma_weight_l1_flag[i]" ); wp[COMPONENT_Y].bPresentFlag = ( uiCode == 1 ); uiTotalSignalledWeightFlags += wp[COMPONENT_Y].bPresentFlag; } if( bChroma ) { uint32_t uiCode; for( int iRefIdx=0 ; iRefIdx < pcSlice->getNumRefIdx( eRefPicList ) ; iRefIdx++ ) { pcSlice->getWpScaling( eRefPicList, iRefIdx, wp ); READ_FLAG( uiCode, iNumRef == 0 ? "chroma_weight_l0_flag[i]" : "chroma_weight_l1_flag[i]" ); for( int j = 1; j < numValidComp; j++ ) { wp[j].bPresentFlag = ( uiCode == 1 ); } uiTotalSignalledWeightFlags += 2 * wp[COMPONENT_Cb].bPresentFlag; } } for( int iRefIdx=0 ; iRefIdxgetNumRefIdx( eRefPicList ) ; iRefIdx++ ) { pcSlice->getWpScaling( eRefPicList, iRefIdx, wp ); if ( wp[COMPONENT_Y].bPresentFlag ) { int iDeltaWeight; READ_SVLC( iDeltaWeight, iNumRef == 0 ? "delta_luma_weight_l0[i]" : "delta_luma_weight_l1[i]" ); CHECK_RECOVERABLE( iDeltaWeight < -128, "Invalid code" ); CHECK_RECOVERABLE( iDeltaWeight > 127, "Invalid code" ); wp[COMPONENT_Y].iWeight = ( iDeltaWeight + ( 1 << wp[COMPONENT_Y].uiLog2WeightDenom ) ); READ_SVLC( wp[COMPONENT_Y].iOffset, iNumRef == 0? "luma_offset_l0[i]" : "luma_offset_l1[i]" ); const int range = /* sps->getSpsRangeExtension().getHighPrecisionOffsetsEnabledFlag() ? ( 1 << sps->getBitDepth(CHANNEL_TYPE_LUMA ) ) / 2 :*/ 128; if( wp[0].iOffset < -range ) { THROW( "Offset out of range" ); } if( wp[0].iOffset >= range ) { THROW( "Offset out of range" ); } } else { wp[COMPONENT_Y].iWeight = ( 1 << wp[COMPONENT_Y].uiLog2WeightDenom ); wp[COMPONENT_Y].iOffset = 0; } if( bChroma ) { if( wp[COMPONENT_Cb].bPresentFlag ) { int range = /*sps->getSpsRangeExtension().getHighPrecisionOffsetsEnabledFlag() ? ( 1 << sps->getBitDepth( CHANNEL_TYPE_CHROMA ) ) / 2 :*/ 128 ; for( int j = 1 ; j < numValidComp ; j++ ) { int iDeltaWeight; READ_SVLC( iDeltaWeight, iNumRef == 0 ? "delta_chroma_weight_l0[i]" : "delta_chroma_weight_l1[i]" ); CHECK_RECOVERABLE( iDeltaWeight < -128, "Invalid code" ); CHECK_RECOVERABLE( iDeltaWeight > 127, "Invalid code" ); wp[j].iWeight = (iDeltaWeight + (1<= 4*range, "Invalid code" ); int pred = ( range - ( ( range * wp[j].iWeight ) >> ( wp[j].uiLog2WeightDenom ) ) ); wp[j].iOffset = Clip3( -range, range - 1, iDeltaChroma + pred ); } } else { for( int j = 1 ; j < numValidComp ; j++ ) { wp[j].iWeight = ( 1 << wp[j].uiLog2WeightDenom ); wp[j].iOffset = 0; } } } } for( int iRefIdx = pcSlice->getNumRefIdx( eRefPicList ); iRefIdx < MAX_NUM_REF; iRefIdx++ ) { pcSlice->getWpScaling( eRefPicList, iRefIdx, wp ); wp[0].bPresentFlag = false; wp[1].bPresentFlag = false; wp[2].bPresentFlag = false; } } CHECK_RECOVERABLE( uiTotalSignalledWeightFlags > 24, "Too many weight flag signalled" ); } void HLSyntaxReader::parsePredWeightTable( PicHeader *picHeader, const SPS *sps ) { WPScalingParam * wp; const ChromaFormat chFmt = sps->getChromaFormatIdc(); const int numValidComp = int( getNumberValidComponents( chFmt ) ); const bool chroma = ( chFmt != CHROMA_400 ); uint32_t log2WeightDenomLuma = 0; uint32_t log2WeightDenomChroma = 0; uint32_t totalSignalledWeightFlags = 0; int deltaDenom; READ_UVLC( log2WeightDenomLuma, "luma_log2_weight_denom" ); CHECK_RECOVERABLE( log2WeightDenomLuma > 7, "Invalid code" ); if( chroma ) { READ_SVLC( deltaDenom, "delta_chroma_log2_weight_denom" ); CHECK_RECOVERABLE( ( deltaDenom + (int) log2WeightDenomLuma ) < 0, "Invalid code" ); CHECK_RECOVERABLE( ( deltaDenom + (int) log2WeightDenomLuma ) > 7, "Invalid code" ); log2WeightDenomChroma = (uint32_t)( deltaDenom + log2WeightDenomLuma ); } uint32_t numLxWeights; READ_UVLC( numLxWeights, "num_l0_weights" ); picHeader->setNumL0Weights( numLxWeights ); picHeader->setNumL1Weights( 0 ); bool moreSyntaxToBeParsed = true; for( int numRef = 0; numRef < NUM_REF_PIC_LIST_01 && moreSyntaxToBeParsed; numRef++ ) { RefPicList refPicList = ( numRef ? REF_PIC_LIST_1 : REF_PIC_LIST_0 ); for( int refIdx = 0; refIdx < numLxWeights; refIdx++ ) { picHeader->getWpScaling( refPicList, refIdx, wp ); wp[COMPONENT_Y].uiLog2WeightDenom = log2WeightDenomLuma; for (int j = 1; j < numValidComp; j++) { wp[j].uiLog2WeightDenom = log2WeightDenomChroma; } uint32_t uiCode; READ_FLAG(uiCode, numRef == 0 ? "luma_weight_l0_flag[i]" : "luma_weight_l1_flag[i]"); wp[COMPONENT_Y].bPresentFlag = ( uiCode == 1 ); totalSignalledWeightFlags += wp[COMPONENT_Y].bPresentFlag; } if( chroma ) { uint32_t uiCode; for( int refIdx = 0; refIdx < numLxWeights; refIdx++ ) { picHeader->getWpScaling( refPicList, refIdx, wp ); READ_FLAG( uiCode, numRef == 0 ? "chroma_weight_l0_flag[i]" : "chroma_weight_l1_flag[i]" ); for( int j = 1; j < numValidComp; j++ ) { wp[j].bPresentFlag = ( uiCode == 1 ); } totalSignalledWeightFlags += 2 * wp[COMPONENT_Cb].bPresentFlag; } } else { for( int refIdx = 0; refIdx < MAX_NUM_REF; refIdx++ ) { picHeader->getWpScaling( refPicList, refIdx, wp ); wp[1].bPresentFlag = false; wp[2].bPresentFlag = false; } } for( int refIdx = 0; refIdx < numLxWeights; refIdx++ ) { picHeader->getWpScaling( refPicList, refIdx, wp ); if( wp[COMPONENT_Y].bPresentFlag ) { int deltaWeight; READ_SVLC( deltaWeight, numRef == 0 ? "delta_luma_weight_l0[i]" : "delta_luma_weight_l1[i]" ); wp[COMPONENT_Y].iWeight = ( deltaWeight + ( 1 << wp[COMPONENT_Y].uiLog2WeightDenom ) ); READ_SVLC( wp[COMPONENT_Y].iOffset, numRef == 0 ? "luma_offset_l0[i]" : "luma_offset_l1[i]" ); const int range = /*sps->getSpsRangeExtension().getHighPrecisionOffsetsEnabledFlag() ? ( 1 << sps->getBitDepth( CHANNEL_TYPE_LUMA ) ) / 2 :*/ 128; if( wp[0].iOffset < -range ) { THROW( "Offset out of range" ); } if( wp[0].iOffset >= range ) { THROW( "Offset out of range" ); } } else { wp[COMPONENT_Y].iWeight = ( 1 << wp[COMPONENT_Y].uiLog2WeightDenom ); wp[COMPONENT_Y].iOffset = 0; } if( chroma ) { if( wp[COMPONENT_Cb].bPresentFlag ) { int range = /*sps->getSpsRangeExtension().getHighPrecisionOffsetsEnabledFlag() ? ( 1 << sps->getBitDepth( CHANNEL_TYPE_CHROMA ) ) / 2 :*/ 128; for( int j = 1; j < numValidComp; j++ ) { int deltaWeight; READ_SVLC( deltaWeight, numRef == 0 ? "delta_chroma_weight_l0[i]" : "delta_chroma_weight_l1[i]" ); wp[j].iWeight = ( deltaWeight + (1 << wp[j].uiLog2WeightDenom ) ); int deltaChroma; READ_SVLC( deltaChroma, numRef == 0 ? "delta_chroma_offset_l0[i]" : "delta_chroma_offset_l1[i]"); int pred = ( range - ( ( range * wp[j].iWeight ) >> ( wp[j].uiLog2WeightDenom ) ) ); wp[j].iOffset = Clip3( -range, range - 1, ( deltaChroma + pred ) ); } } else { for( int j = 1; j < numValidComp; j++ ) { wp[j].iWeight = ( 1 << wp[j].uiLog2WeightDenom ); wp[j].iOffset = 0; } } } } for( int refIdx = numLxWeights; refIdx < MAX_NUM_REF; refIdx++ ) { picHeader->getWpScaling( refPicList, refIdx, wp ); wp[0].bPresentFlag = false; wp[1].bPresentFlag = false; wp[2].bPresentFlag = false; } if( numRef == 0 ) { if( picHeader->getRPL( REF_PIC_LIST_1 )->getNumRefEntries() > 0 ) { READ_UVLC( numLxWeights, "num_l1_weights" ); } else { numLxWeights = 0; } moreSyntaxToBeParsed = ( numLxWeights == 0 ) ? false : true; picHeader->setNumL1Weights( numLxWeights ); } } CHECK_RECOVERABLE( totalSignalledWeightFlags > 24, "Too many weight flag signalled" ); } /** decode quantization matrix * \param scalingList quantization matrix information */ void HLSyntaxReader::parseScalingList( ScalingList *scalingList, bool aps_chromaPrsentFlag ) { uint32_t code; bool scalingListCopyModeFlag; scalingList->setChromaScalingListPresentFlag( aps_chromaPrsentFlag ); for( int scalingListId = 0; scalingListId < 28; scalingListId++ ) { if( aps_chromaPrsentFlag || scalingList->isLumaScalingList( scalingListId ) ) { READ_FLAG( code, "scaling_list_copy_mode_flag" ); scalingListCopyModeFlag = ( code ) ? true : false; scalingList->setScalingListCopyModeFlag( scalingListId, scalingListCopyModeFlag ); scalingList->setScalingListPreditorModeFlag( scalingListId, false ); if( !scalingListCopyModeFlag ) { READ_FLAG( code, "scaling_list_pred_mode_flag" ); scalingList->setScalingListPreditorModeFlag( scalingListId, code ); } if( ( scalingListCopyModeFlag || scalingList->getScalingListPreditorModeFlag( scalingListId ) ) && scalingListId != SCALING_LIST_1D_START_2x2 && scalingListId != SCALING_LIST_1D_START_4x4 && scalingListId != SCALING_LIST_1D_START_8x8 ) //Copy Mode { READ_UVLC( code, "scaling_list_pred_id_delta" ); scalingList->setRefMatrixId( scalingListId, (uint32_t)( (int)( scalingListId ) - ( code ) ) ); } else if( scalingListCopyModeFlag || scalingList->getScalingListPreditorModeFlag( scalingListId ) ) { scalingList->setRefMatrixId( scalingListId, (uint32_t)( (int)( scalingListId ) ) ); } if( scalingListCopyModeFlag )//copy { if( scalingListId >= SCALING_LIST_1D_START_16x16 ) { scalingList->setScalingListDC( scalingListId, ( ( scalingListId == scalingList->getRefMatrixId( scalingListId ) ) ? 16 : ( scalingList->getRefMatrixId( scalingListId ) < SCALING_LIST_1D_START_16x16 ) ? scalingList->getScalingListAddress( scalingList->getRefMatrixId( scalingListId ) )[0] : scalingList->getScalingListDC( scalingList->getRefMatrixId( scalingListId ) ) ) ); } scalingList->processRefMatrix( scalingListId, scalingList->getRefMatrixId( scalingListId ) ); } else { decodeScalingList( scalingList, scalingListId, scalingList->getScalingListPreditorModeFlag( scalingListId ) ); } } else { scalingListCopyModeFlag = true; scalingList->setScalingListCopyModeFlag( scalingListId, scalingListCopyModeFlag ); scalingList->setRefMatrixId(scalingListId, (uint32_t)( (int)( scalingListId ) ) ); if (scalingListId >= SCALING_LIST_1D_START_16x16) { scalingList->setScalingListDC( scalingListId, 16 ); } scalingList->processRefMatrix( scalingListId, scalingList->getRefMatrixId( scalingListId ) ); } } return; } /** decode DPCM * \param scalingList quantization matrix information * \param sizeId size index * \param listId list index */ void HLSyntaxReader::decodeScalingList( ScalingList *scalingList, uint32_t scalingListId, bool isPredictor ) { int matrixSize = ( scalingListId < SCALING_LIST_1D_START_4x4 ) ? 2 : ( scalingListId < SCALING_LIST_1D_START_8x8 ) ? 4 : 8; int i, coefNum = matrixSize * matrixSize; int data; int scalingListDcCoefMinus8 = 0; int nextCoef = ( isPredictor ) ? 0 : SCALING_LIST_START_VALUE; const uint16_t *scan = g_scanOrder[SCAN_UNGROUPED][g_sizeIdxInfo.idxFrom( matrixSize )][g_sizeIdxInfo.idxFrom( matrixSize )]; int *dst = scalingList->getScalingListAddress( scalingListId ); int PredListId = scalingList->getRefMatrixId( scalingListId ); CHECK_RECOVERABLE( isPredictor && PredListId > scalingListId, "Scaling List error predictor!" ); const int *srcPred = isPredictor ? ( ( scalingListId == PredListId ) ? scalingList->getScalingListDefaultAddress( scalingListId ) : scalingList->getScalingListAddress( PredListId ) ) : NULL; int predCoef = 0; if( scalingListId >= SCALING_LIST_1D_START_16x16 ) { READ_SVLC( scalingListDcCoefMinus8, "scaling_list_dc_coef" ); nextCoef += scalingListDcCoefMinus8; if( isPredictor ) { predCoef = ( PredListId >= SCALING_LIST_1D_START_16x16 ) ? scalingList->getScalingListDC( PredListId ) : srcPred[0]; } scalingList->setScalingListDC( scalingListId, ( nextCoef + predCoef + 256 ) % 256 ); } for( i = 0; i < coefNum; i++ ) { int blkPos = scan[i]; int posX = blkPos & ( ( 1 << g_sizeIdxInfo.idxFrom( matrixSize ) ) - 1 ); int posY = blkPos >> g_sizeIdxInfo.idxFrom( matrixSize ); if( scalingListId >= SCALING_LIST_1D_START_64x64 && posX >= 4 && posY >= 4 ) { dst[scan[i]] = 0; continue; } READ_SVLC( data, "scaling_list_delta_coef[i]" ); nextCoef += data; predCoef = ( isPredictor ) ? srcPred[scan[i]] : 0; dst[scan[i]] = (nextCoef + predCoef + 256) % 256; } } bool HLSyntaxReader::xMoreRbspData() { int bitsLeft = m_pcBitstream->getNumBitsLeft(); // if there are more than 8 bits, it cannot be rbsp_trailing_bits if( bitsLeft > 8 ) { return true; } uint8_t lastByte = m_pcBitstream->peekBits( bitsLeft ); int cnt = bitsLeft; // remove trailing bits equal to zero while( ( cnt > 0 ) && ( ( lastByte & 1 ) == 0 ) ) { lastByte >>= 1; cnt--; } // remove bit equal to one cnt--; // we should not have a negative number of bits CHECK_RECOVERABLE( cnt<0, "Negative number of bits") ; // we have more data, if cnt is not zero return ( cnt>0 ); } void HLSyntaxReader::alfFilter( AlfSliceParam& alfSliceParam, const bool isChroma, const int altIdx ) { const bool isLuma = !isChroma; uint32_t code; // derive maxGolombIdx const int numCoeff = g_alfNumCoeff[isChroma ? 0 : 1]; // READ_UVLC( code, "min_golomb_order" ); const int numFilters = isChroma ? 1 : alfSliceParam.numLumaFilters; short* coeff = isChroma ? alfSliceParam.chromaCoeff + altIdx*MAX_NUM_ALF_CHROMA_COEFF : alfSliceParam.lumaCoeff; short* clipp = isChroma ? alfSliceParam.chromaClipp + altIdx*MAX_NUM_ALF_CHROMA_COEFF : alfSliceParam.lumaClipp; // Filter coefficients for( int ind = 0; ind < numFilters; ++ind ) { for( int i = 0; i < numCoeff - 1; i++ ) { READ_UVLC( code, isLuma ? "alf_luma_coeff_abs" : "alf_chroma_coeff_abs" ); coeff[ ind * MAX_NUM_ALF_LUMA_COEFF + i ] = code; if( coeff[ ind * MAX_NUM_ALF_LUMA_COEFF + i ] != 0 ) { READ_FLAG( code, isLuma ? "alf_luma_coeff_sign" : "alf_chroma_coeff_sign" ); coeff[ ind * MAX_NUM_ALF_LUMA_COEFF + i ] = ( code ) ? -coeff[ ind * MAX_NUM_ALF_LUMA_COEFF + i ] : coeff[ ind * MAX_NUM_ALF_LUMA_COEFF + i ]; } } if( isLuma ) { alfSliceParam.lumaCoeffSummed = false; } const int factor = 1 << ( AdaptiveLoopFilter::m_NUM_BITS - 1 ); coeff[ind * MAX_NUM_ALF_LUMA_COEFF + numCoeff - 1] = factor; } // Clipping values coding bool nonLinFlag = isChroma ? alfSliceParam.nonLinearFlagChroma : alfSliceParam.nonLinearFlagLuma; if( nonLinFlag ) { // Filter coefficients for( int ind = 0; ind < numFilters; ++ind ) { for( int i = 0; i < numCoeff - 1; i++ ) { READ_CODE( 2, code, isLuma ? "alf_luma_clip_idx" : "alf_chroma_clip_idx" ); clipp[ind * MAX_NUM_ALF_LUMA_COEFF + i] = code; } } } else { for( int ind = 0; ind < numFilters; ++ind ) { std::fill_n( clipp + ind * MAX_NUM_ALF_LUMA_COEFF, numCoeff, 0 ); } } } }