/* -----------------------------------------------------------------------------
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-2024, 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<PreCalcValues>( *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<bool> 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<bool> 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 <pcSPS->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 <pcSPS->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<<ctbLog2SizeY ), "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" );
READ_UVLC( uiCode, "sps_max_mtt_hierarchy_depth_intra_slice_luma"); maxBTD[0] = uiCode;
CHECK_RECOVERABLE( uiCode > 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<int> deltaQpInValMinus1( chromaQpMappingTableParams.getNumPtsInCQPTableMinus1( i ) + 1 );
std::vector<int> 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<ProfileTierLevel> 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<bool> 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<ProfileTierLevel> 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<bool> 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<bool> isHRDParamReferred( uiCode + 1, false );
pcVPS->m_olsHrdParams.clear();
pcVPS->m_olsHrdParams.resize( pcVPS->getNumOlsHrdParamsMinus1(), std::vector<OlsHrdParams>( 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<bool> 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<int> 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<int>& 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>& 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<bool> 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<int> 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; iRefIdx<pcSlice->getNumRefIdx( 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<uint32_t> 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; curByteIdx<m_pcBitstream->numEmulationPreventionBytesRead(); 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; curByteIdx<m_pcBitstream->numEmulationPreventionBytesRead(); 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<typename HeaderT>
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<RefPicList>( 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 ; iRefIdx<pcSlice->getNumRefIdx( 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 ; iRefIdx<pcSlice->getNumRefIdx( 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<<wp[j].uiLog2WeightDenom));
int iDeltaChroma;
READ_SVLC( iDeltaChroma, iNumRef == 0 ? "delta_chroma_offset_l0[i]" : "delta_chroma_offset_l1[i]" );
CHECK_RECOVERABLE( iDeltaChroma < -4*range, "Invalid code" );
CHECK_RECOVERABLE( iDeltaChroma >= 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 );
}
}
}
}
↑ V547 Expression 'length >= 32' is always false.
↑ V555 The expression 'pcSPS->getMaxTLayers() - 1 > 0' will work as 'pcSPS->getMaxTLayers() != 1'.
↑ V555 The expression '(pcSPS->getMaxTLayers() - 1) > 0' will work as 'pcSPS->getMaxTLayers() != 1'.
↑ V555 The expression '(pcVPS->getMaxSubLayers() - 1) > 0' will work as 'pcVPS->getMaxSubLayers() != 1'.