Newer
Older

Karsten Suehring
committed
/* The copyright in this software is being made available under the BSD
* License, included below. This software may be subject to other third party
* and contributor rights, including patent rights, and no such rights are
* granted under this license.
*
* Copyright (c) 2010-2020, ITU/ISO/IEC

Karsten Suehring
committed
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* * Neither the name of the ITU/ISO/IEC nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
/** \file EncLib.cpp
\brief encoder class
*/
#include "EncLib.h"
#include "EncModeCtrl.h"
#include "AQp.h"
#include "EncCu.h"
#include "CommonLib/Picture.h"
#include "CommonLib/CommonDef.h"
#include "CommonLib/ChromaFormat.h"
#if ENABLE_SPLIT_PARALLELISM
#include <omp.h>
#endif
#if JVET_Q0814_DPB
#include "CommonLib/ProfileLevelTier.h"
#endif

Karsten Suehring
committed
//! \ingroup EncoderLib
//! \{
// ====================================================================================================================
// Constructor / destructor / create / destroy
// ====================================================================================================================
EncLib::EncLib( EncLibCommon* encLibCommon )
: m_cListPic( encLibCommon->getPictureBuffer() )
, m_cEncALF( encLibCommon->getApsIdStart() )
, m_spsMap( encLibCommon->getSpsMap() )
, m_ppsMap( encLibCommon->getPpsMap() )
, m_apsMap( encLibCommon->getApsMap() )
, m_AUWriterIf( nullptr )

Karsten Suehring
committed
#if JVET_J0090_MEMORY_BANDWITH_MEASURE
, m_cacheModel()
#endif
, m_scalinglistAPS( nullptr )
, m_doPlt( true )
#if JVET_Q0814_DPB
, m_vps( encLibCommon->getVPS() )
#endif

Karsten Suehring
committed
{
m_iPOCLast = -1;
m_iNumPicRcvd = 0;
m_uiNumAllPicCoded = 0;
m_iMaxRefPicNum = 0;
#if ENABLE_SIMD_OPT_BUFFER
g_pelBufOP.initPelBufOpsX86();
#endif
#if JVET_O0756_CALCULATE_HDRMETRICS
m_metricTime = std::chrono::milliseconds(0);
#endif
memset(m_apss, 0, sizeof(m_apss));

Karsten Suehring
committed
}
EncLib::~EncLib()
{
}

Karsten Suehring
committed
{
m_iPOCLast = m_compositeRefEnabled ? -2 : -1;

Karsten Suehring
committed
// create processing unit classes
m_cGOPEncoder. create( );

Karsten Suehring
committed
#if ENABLE_SPLIT_PARALLELISM
m_numCuEncStacks = m_numSplitThreads == 1 ? 1 : NUM_RESERVERD_SPLIT_JOBS;
#else
m_numCuEncStacks = 1;
#endif
m_cCuEncoder = new EncCu [m_numCuEncStacks];
m_cInterSearch = new InterSearch [m_numCuEncStacks];
m_cIntraSearch = new IntraSearch [m_numCuEncStacks];
m_cTrQuant = new TrQuant [m_numCuEncStacks];
m_CABACEncoder = new CABACEncoder [m_numCuEncStacks];
m_cRdCost = new RdCost [m_numCuEncStacks];
m_CtxCache = new CtxCache [m_numCuEncStacks];
for( int jId = 0; jId < m_numCuEncStacks; jId++ )
{
m_cCuEncoder[jId]. create( this );
}
#else
m_cCuEncoder. create( this );
#endif
#if JVET_J0090_MEMORY_BANDWITH_MEASURE
m_cInterSearch.cacheAssign( &m_cacheModel );
#endif
#if JVET_Q0468_Q0469_MIN_LUMA_CB_AND_MIN_QT_FIX
m_cLoopFilter.create(floorLog2(m_maxCUWidth) - MIN_CU_LOG2);
#else

Karsten Suehring
committed
m_cLoopFilter.create( m_maxTotalCUDepth );
#endif

Karsten Suehring
committed
m_cReshaper = new EncReshape[m_numCuEncStacks];
#endif
if (m_lmcsEnabled)
for (int jId = 0; jId < m_numCuEncStacks; jId++)
{
m_cReshaper[jId].createEnc(getSourceWidth(), getSourceHeight(), m_maxCUWidth, m_maxCUHeight, m_bitDepth[COMPONENT_Y]);
}
#else
m_cReshaper.createEnc( getSourceWidth(), getSourceHeight(), m_maxCUWidth, m_maxCUHeight, m_bitDepth[COMPONENT_Y]);

Karsten Suehring
committed
if ( m_RCEnableRateControl )
{
m_cRateCtrl.init(m_framesToBeEncoded, m_RCTargetBitrate, (int)((double)m_iFrameRate / m_temporalSubsampleRatio + 0.5), m_iGOPSize, m_iSourceWidth, m_iSourceHeight,
m_maxCUWidth, m_maxCUHeight, getBitDepth(CHANNEL_TYPE_LUMA), m_RCKeepHierarchicalBit, m_RCUseLCUSeparateModel, m_GOPList);

Karsten Suehring
committed
}
}
void EncLib::destroy ()
{
// destroy processing unit classes
m_cGOPEncoder. destroy();
m_cSliceEncoder. destroy();

Karsten Suehring
committed
for( int jId = 0; jId < m_numCuEncStacks; jId++ )
{
m_cCuEncoder[jId].destroy();
}
#else
m_cCuEncoder. destroy();
#endif
if( m_alf )
{
m_cEncALF.destroy();
}
m_cEncSAO. destroyEncData();
m_cEncSAO. destroy();
m_cLoopFilter. destroy();
m_cRateCtrl. destroy();
for (int jId = 0; jId < m_numCuEncStacks; jId++)
{
m_cReshaper[jId]. destroy();
}
#else

Karsten Suehring
committed
for( int jId = 0; jId < m_numCuEncStacks; jId++ )
{
m_cInterSearch[jId]. destroy();
m_cIntraSearch[jId]. destroy();
}
#else
m_cInterSearch. destroy();
m_cIntraSearch. destroy();
#endif

Karsten Suehring
committed
delete[] m_cCuEncoder;
delete[] m_cInterSearch;
delete[] m_cIntraSearch;
delete[] m_cTrQuant;
delete[] m_CABACEncoder;
delete[] m_cRdCost;
delete[] m_CtxCache;
#endif
return;
}
void EncLib::init( bool isFieldCoding, AUWriterIf* auWriterIf )
{
m_AUWriterIf = auWriterIf;
#if ENABLING_MULTI_SPS
SPS &sps0 = *(m_spsMap.allocatePS(m_layerId)); // NOTE: implementations that use more than 1 SPS need to be aware of activation issues.
#else
SPS &sps0 = *(m_spsMap.allocatePS(0)); // NOTE: implementations that use more than 1 SPS need to be aware of activation issues.
#endif
PPS &pps0 = *( m_ppsMap.allocatePS( m_layerId ) );
APS &aps0 = *( m_apsMap.allocatePS( SCALING_LIST_APS ) );
aps0.setAPSId( 0 );
aps0.setAPSType( SCALING_LIST_APS );

Karsten Suehring
committed
// initialize SPS
#if JVET_Q0814_DPB
xInitSPS( sps0 );
xInitVPS( sps0 );
#else
Philip Cowan
committed
xInitVPS(m_cVPS, sps0);

Karsten Suehring
committed
int dpsId = getDecodingParameterSetEnabled() ? 1 : 0;
xInitDPS(m_dps, sps0, dpsId);
sps0.setDecodingParameterSetId(m_dps.getDecodingParameterSetId());

Karsten Suehring
committed
#if ENABLE_SPLIT_PARALLELISM
if( omp_get_dynamic() )
{
omp_set_dynamic( false );
}
omp_set_nested( true );
#endif
if (getUseCompositeRef() || getDependentRAPIndicationSEIEnabled())
{
sps0.setLongTermRefsPresent(true);
}

Karsten Suehring
committed
#if U0132_TARGET_BITS_SATURATION
if (m_RCCpbSaturationEnabled)
{
m_cRateCtrl.initHrdParam(sps0.getHrdParameters(), m_iFrameRate, m_RCInitialCpbFullness);

Karsten Suehring
committed
}
#endif

Karsten Suehring
committed
for( int jId = 0; jId < m_numCuEncStacks; jId++ )
{
m_cRdCost[jId].setCostMode ( m_costMode );
}
#else
m_cRdCost.setCostMode ( m_costMode );
#endif
// initialize PPS
pps0.setPicWidthInLumaSamples( m_iSourceWidth );
pps0.setPicHeightInLumaSamples( m_iSourceHeight );
pps0.setConformanceWindow( m_conformanceWindow );

Karsten Suehring
committed
xInitPPS(pps0, sps0);

Karsten Suehring
committed
if( m_rprEnabled )
{
PPS &pps = *( m_ppsMap.allocatePS( ENC_PPS_ID_RPR ) );
Window& inputScalingWindow = pps0.getScalingWindow();
#if JVET_Q0487_SCALING_WINDOW_ISSUES
int scaledWidth = int( ( pps0.getPicWidthInLumaSamples() - SPS::getWinUnitX( sps0.getChromaFormatIdc() ) * ( inputScalingWindow.getWindowLeftOffset() + inputScalingWindow.getWindowRightOffset() ) ) / m_scalingRatioHor );
#else
int scaledWidth = int( ( pps0.getPicWidthInLumaSamples() - inputScalingWindow.getWindowLeftOffset() - inputScalingWindow.getWindowRightOffset() ) / m_scalingRatioHor );
#if JVET_Q0468_Q0469_MIN_LUMA_CB_AND_MIN_QT_FIX
int minSizeUnit = std::max(8, 1 << sps0.getLog2MinCodingBlockSize());
#else
int minSizeUnit = std::max(8, (int)(sps0.getMaxCUHeight() >> (sps0.getMaxCodingDepth() - 1)));
#endif
int temp = scaledWidth / minSizeUnit;
int width = ( scaledWidth - ( temp * minSizeUnit) > 0 ? temp + 1 : temp ) * minSizeUnit;
#if JVET_Q0487_SCALING_WINDOW_ISSUES
int scaledHeight = int( ( pps0.getPicHeightInLumaSamples() - SPS::getWinUnitY( sps0.getChromaFormatIdc() ) * ( inputScalingWindow.getWindowTopOffset() + inputScalingWindow.getWindowBottomOffset() ) ) / m_scalingRatioVer );
#else
int scaledHeight = int( ( pps0.getPicHeightInLumaSamples() - inputScalingWindow.getWindowTopOffset() - inputScalingWindow.getWindowBottomOffset() ) / m_scalingRatioVer );
temp = scaledHeight / minSizeUnit;
int height = ( scaledHeight - ( temp * minSizeUnit) > 0 ? temp + 1 : temp ) * minSizeUnit;
pps.setPicWidthInLumaSamples( width );
pps.setPicHeightInLumaSamples( height );
Window conformanceWindow;
conformanceWindow.setWindow( 0, ( width - scaledWidth ) / SPS::getWinUnitX( sps0.getChromaFormatIdc() ), 0, ( height - scaledHeight ) / SPS::getWinUnitY( sps0.getChromaFormatIdc() ) );
pps.setConformanceWindow( conformanceWindow );
Window scalingWindow;
scalingWindow.setWindow( 0, width - scaledWidth, 0, height - scaledHeight );
pps.setScalingWindow( scalingWindow );
Peter Chuang
committed
#if JVET_Q0179_SCALING_WINDOW_SIZE_CONSTRAINT
//register the width/height of the current pic into reference SPS
if (!sps0.getPPSValidFlag(pps.getPPSId()))
{
sps0.setPPSValidFlag(pps.getPPSId(), true);
sps0.setScalingWindowSizeInPPS(pps.getPPSId(), scaledWidth, scaledHeight);
}
int curSeqMaxPicWidthY = sps0.getMaxPicWidthInLumaSamples(); // pic_width_max_in_luma_samples
int curSeqMaxPicHeightY = sps0.getMaxPicHeightInLumaSamples(); // pic_height_max_in_luma_samples
int curPicWidthY = width; // pic_width_in_luma_samples
int curPicHeightY = height; // pic_height_in_luma_samples
int max8MinCbSizeY = std::max((int)8, (1 << sps0.getLog2MinCodingBlockSize())); // Max(8, MinCbSizeY)
Peter Chuang
committed
//Warning message of potential scaling window size violation
Peter Chuang
committed
for (int i = 0; i < 64; i++)
{
if (sps0.getPPSValidFlag(i))
{
if ((scaledWidth * curSeqMaxPicWidthY) < sps0.getScalingWindowSizeInPPS(i).width * (curPicWidthY - max8MinCbSizeY))
printf("Potential violation: (curScaledWIdth * curSeqMaxPicWidthY) should be greater than or equal to refScaledWidth * (curPicWidthY - max(8, MinCbSizeY)\n");
if ((scaledHeight * curSeqMaxPicHeightY) < sps0.getScalingWindowSizeInPPS(i).height * (curPicHeightY - max8MinCbSizeY))
printf("Potential violation: (curScaledHeight * curSeqMaxPicHeightY) should be greater than or equal to refScaledHeight * (curPicHeightY - max(8, MinCbSizeY)\n");
}
}
#endif
// disable picture partitioning for scaled RPR pictures (slice/tile config only provided for the original resolution)
m_noPicPartitionFlag = true;
xInitPPS( pps, sps0 ); // will allocate memory for and initialize pps.pcv inside
}

Karsten Suehring
committed
#if ER_CHROMA_QP_WCG_PPS
if (m_wcgChromaQpControl.isEnabled())
{
PPS &pps1=*(m_ppsMap.allocatePS(1));
xInitPPS(pps1, sps0);
}
#endif
if (getUseCompositeRef())
{
PPS &pps2 = *(m_ppsMap.allocatePS(2));
xInitPPS(pps2, sps0);
xInitPPSforLT(pps2);
}

Karsten Suehring
committed
// initialize processing unit classes
m_cGOPEncoder. init( this );
m_cSliceEncoder.init( this, sps0 );

Karsten Suehring
committed
for( int jId = 0; jId < m_numCuEncStacks; jId++ )
{
// precache a few objects
for( int i = 0; i < 10; i++ )
{
auto x = m_CtxCache[jId].get();
m_CtxCache[jId].cache( x );
}
m_cCuEncoder[jId].init( this, sps0, jId );
// initialize transform & quantization class
m_cTrQuant[jId].init( jId == 0 ? nullptr : m_cTrQuant[0].getQuant(),
1 << m_log2MaxTbSize,

Karsten Suehring
committed
m_useRDOQ,
m_useRDOQTS,
#if T0196_SELECTIVE_RDOQ
m_useSelectiveRDOQ,
#endif

Karsten Suehring
committed
);
// initialize encoder search class
CABACWriter* cabacEstimator = m_CABACEncoder[jId].getCABACEstimator( &sps0 );
m_cIntraSearch[jId].init( this,
&m_cTrQuant[jId],
&m_cRdCost[jId],
cabacEstimator,
#if JVET_Q0468_Q0469_MIN_LUMA_CB_AND_MIN_QT_FIX
getCtxCache( jId ), m_maxCUWidth, m_maxCUHeight, floorLog2(m_maxCUWidth) - m_log2MinCUSize
#else
getCtxCache( jId ), m_maxCUWidth, m_maxCUHeight, m_maxTotalCUDepth
, sps0.getBitDepth(CHANNEL_TYPE_LUMA)

Karsten Suehring
committed
m_cInterSearch[jId].init( this,
&m_cTrQuant[jId],
m_iSearchRange,
m_bipredSearchRange,
m_motionEstimationSearchMethod,
#if JVET_Q0468_Q0469_MIN_LUMA_CB_AND_MIN_QT_FIX
m_maxCUWidth, m_maxCUHeight, floorLog2(m_maxCUWidth) - m_log2MinCUSize, &m_cRdCost[jId], cabacEstimator, getCtxCache( jId )
#else
m_maxCUWidth, m_maxCUHeight, m_maxTotalCUDepth, &m_cRdCost[jId], cabacEstimator, getCtxCache( jId )

Karsten Suehring
committed
// link temporary buffets from intra search with inter search to avoid unnecessary memory overhead
m_cInterSearch[jId].setTempBuffers( m_cIntraSearch[jId].getSplitCSBuf(), m_cIntraSearch[jId].getFullCSBuf(), m_cIntraSearch[jId].getSaveCSBuf() );
}
#else // ENABLE_SPLIT_PARALLELISM || ENABLE_WPP_PARALLELISM

Karsten Suehring
committed
// initialize transform & quantization class
m_cTrQuant.init( nullptr,

Karsten Suehring
committed
m_useRDOQ,
m_useRDOQTS,
#if T0196_SELECTIVE_RDOQ
m_useSelectiveRDOQ,
#endif

Karsten Suehring
committed
);
// initialize encoder search class
CABACWriter* cabacEstimator = m_CABACEncoder.getCABACEstimator(&sps0);
m_cIntraSearch.init( this,
&m_cTrQuant,
&m_cRdCost,
cabacEstimator,
#if JVET_Q0468_Q0469_MIN_LUMA_CB_AND_MIN_QT_FIX
getCtxCache(), m_maxCUWidth, m_maxCUHeight, floorLog2(m_maxCUWidth) - m_log2MinCUSize
#else
getCtxCache(), m_maxCUWidth, m_maxCUHeight, m_maxTotalCUDepth
#endif
, sps0.getBitDepth(CHANNEL_TYPE_LUMA)

Karsten Suehring
committed
m_cInterSearch.init( this,
&m_cTrQuant,
m_iSearchRange,
m_bipredSearchRange,
m_motionEstimationSearchMethod,
#if JVET_Q0468_Q0469_MIN_LUMA_CB_AND_MIN_QT_FIX
m_maxCUWidth, m_maxCUHeight, floorLog2(m_maxCUWidth) - m_log2MinCUSize, &m_cRdCost, cabacEstimator, getCtxCache()
#else
m_maxCUWidth, m_maxCUHeight, m_maxTotalCUDepth, &m_cRdCost, cabacEstimator, getCtxCache()
#endif

Karsten Suehring
committed
// link temporary buffets from intra search with inter search to avoid unneccessary memory overhead
m_cInterSearch.setTempBuffers( m_cIntraSearch.getSplitCSBuf(), m_cIntraSearch.getFullCSBuf(), m_cIntraSearch.getSaveCSBuf() );
#endif // ENABLE_SPLIT_PARALLELISM || ENABLE_WPP_PARALLELISM
m_iMaxRefPicNum = 0;
#if ER_CHROMA_QP_WCG_PPS
if( m_wcgChromaQpControl.isEnabled() )
{
xInitScalingLists( sps0, *m_apsMap.getPS( 1 ) );
xInitScalingLists( sps0, aps0 );

Karsten Suehring
committed
}
else
#endif
{
xInitScalingLists( sps0, aps0 );

Karsten Suehring
committed
}
if( m_rprEnabled )
{
xInitScalingLists( sps0, *m_apsMap.getPS( ENC_PPS_ID_RPR ) );
if (getUseCompositeRef())
{
Picture *picBg = new Picture;
picBg->create( sps0.getChromaFormatIdc(), Size( pps0.getPicWidthInLumaSamples(), pps0.getPicHeightInLumaSamples() ), sps0.getMaxCUWidth(), sps0.getMaxCUWidth() + 16, false, m_layerId );
picBg->getRecoBuf().fill(0);
#if JVET_Q0814_DPB
picBg->finalInit( m_vps, sps0, pps0, &m_picHeader, m_apss, m_lmcsAPS, m_scalinglistAPS );
#else
picBg->finalInit( &m_cVPS, sps0, pps0, &m_picHeader, m_apss, m_lmcsAPS, m_scalinglistAPS );
picBg->allocateNewSlice();
picBg->createSpliceIdx(pps0.pcv->sizeInCtus);
m_cGOPEncoder.setPicBg(picBg);
Picture *picOrig = new Picture;
picOrig->create( sps0.getChromaFormatIdc(), Size( pps0.getPicWidthInLumaSamples(), pps0.getPicHeightInLumaSamples() ), sps0.getMaxCUWidth(), sps0.getMaxCUWidth() + 16, false, m_layerId );
picOrig->getOrigBuf().fill(0);
m_cGOPEncoder.setPicOrig(picOrig);
}

Karsten Suehring
committed
}
void EncLib::xInitScalingLists( SPS &sps, APS &aps )

Karsten Suehring
committed
{
// Initialise scaling lists
// The encoder will only use the SPS scaling lists. The PPS will never be marked present.
const int maxLog2TrDynamicRange[MAX_NUM_CHANNEL_TYPE] =
{
sps.getMaxLog2TrDynamicRange(CHANNEL_TYPE_LUMA),
sps.getMaxLog2TrDynamicRange(CHANNEL_TYPE_CHROMA)

Karsten Suehring
committed
};
Quant* quant = getTrQuant()->getQuant();
if(getUseScalingListId() == SCALING_LIST_OFF)
{
quant->setFlatScalingList(maxLog2TrDynamicRange, sps.getBitDepths());
quant->setUseScalingList(false);

Karsten Suehring
committed
for( int jId = 1; jId < m_numCuEncStacks; jId++ )
{
getTrQuant( jId )->getQuant()->setFlatScalingList( maxLog2TrDynamicRange, sps.getBitDepths() );
getTrQuant( jId )->getQuant()->setUseScalingList( false );
}
#endif

Karsten Suehring
committed
}
else if(getUseScalingListId() == SCALING_LIST_DEFAULT)
{
aps.getScalingList().setDefaultScalingList ();
quant->setScalingList( &( aps.getScalingList() ), maxLog2TrDynamicRange, sps.getBitDepths() );

Karsten Suehring
committed
quant->setUseScalingList(true);

Karsten Suehring
committed
for( int jId = 1; jId < m_numCuEncStacks; jId++ )
{
getTrQuant( jId )->getQuant()->setUseScalingList( true );
}
Adarsh Krishnan Ramasubramonian
committed
aps.getScalingList().setDisableScalingMatrixForLfnstBlks(getDisableScalingMatrixForLfnstBlks());

Karsten Suehring
committed
#endif
}
else if(getUseScalingListId() == SCALING_LIST_FILE_READ)
{
aps.getScalingList().setDefaultScalingList();
CHECK( aps.getScalingList().xParseScalingList( getScalingListFileName() ), "Error Parsing Scaling List Input File" );
aps.getScalingList().checkDcOfMatrix();
if( aps.getScalingList().isNotDefaultScalingList() == false )
{
setUseScalingListId( SCALING_LIST_DEFAULT );
}
#if JVET_Q0505_CHROAM_QM_SIGNALING_400
aps.getScalingList().setChromaScalingListPresentFlag((sps.getChromaFormatIdc()!=CHROMA_400));
#endif
quant->setScalingList( &( aps.getScalingList() ), maxLog2TrDynamicRange, sps.getBitDepths() );

Karsten Suehring
committed
quant->setUseScalingList(true);

Karsten Suehring
committed
for( int jId = 1; jId < m_numCuEncStacks; jId++ )
{
getTrQuant( jId )->getQuant()->setUseScalingList( true );
}
Adarsh Krishnan Ramasubramonian
committed
#endif
aps.getScalingList().setDisableScalingMatrixForLfnstBlks(getDisableScalingMatrixForLfnstBlks());

Karsten Suehring
committed
}
else
{
THROW("error : ScalingList == " << getUseScalingListId() << " not supported\n");
}
if( getUseScalingListId() == SCALING_LIST_FILE_READ )

Karsten Suehring
committed
{
// Prepare delta's:
Chen-Yen Lai
committed
for (uint32_t scalingListId = 0; scalingListId < 28; scalingListId++)
{
#if JVET_Q0505_CHROAM_QM_SIGNALING_400
Hongbin Zhang
committed
if (aps.getScalingList().getChromaScalingListPresentFlag()||aps.getScalingList().isLumaScalingList(scalingListId))
#endif
Chen-Yen Lai
committed
aps.getScalingList().checkPredMode(scalingListId);
#if JVET_Q0505_CHROAM_QM_SIGNALING_400
}
#endif
Chen-Yen Lai
committed
}

Karsten Suehring
committed
}
}
void EncLib::xInitPPSforLT(PPS& pps)
{
pps.setOutputFlagPresentFlag(true);
pps.setDeblockingFilterControlPresentFlag(true);
pps.setPPSDeblockingFilterDisabledFlag(true);
}

Karsten Suehring
committed
// ====================================================================================================================
// Public member functions
// ====================================================================================================================
void EncLib::deletePicBuffer()
{
PicList::iterator iterPic = m_cListPic.begin();
int iSize = int( m_cListPic.size() );
for ( int i = 0; i < iSize; i++ )
{
Picture* pcPic = *(iterPic++);
pcPic->destroy();
// get rid of the qpadaption layer
while( pcPic->aqlayer.size() )
{
delete pcPic->aqlayer.back(); pcPic->aqlayer.pop_back();
}
delete pcPic;
pcPic = NULL;
}

Karsten Suehring
committed
}
bool EncLib::encodePrep( bool flush, PelStorage* pcPicYuvOrg, PelStorage* cPicYuvTrueOrg, const InputColourSpaceConversion snrCSC, std::list<PelUnitBuf*>& rcListPicYuvRecOut, int& iNumEncoded )
{
if( m_compositeRefEnabled && m_cGOPEncoder.getPicBg()->getSpliceFull() && m_iPOCLast >= 10 && m_iNumPicRcvd == 0 && m_cGOPEncoder.getEncodedLTRef() == false )
{
Picture* picCurr = NULL;
xGetNewPicBuffer( rcListPicYuvRecOut, picCurr, 2 );
const PPS *pps = m_ppsMap.getPS( 2 );
const SPS *sps = m_spsMap.getPS( pps->getSPSId() );
picCurr->M_BUFS( 0, PIC_ORIGINAL ).copyFrom( m_cGOPEncoder.getPicBg()->getRecoBuf() );
#if JVET_Q0814_DPB
picCurr->finalInit( m_vps, *sps, *pps, &m_picHeader, m_apss, m_lmcsAPS, m_scalinglistAPS );
#else
picCurr->finalInit( &m_cVPS, *sps, *pps, &m_picHeader, m_apss, m_lmcsAPS, m_scalinglistAPS );
picCurr->poc = m_iPOCLast - 1;
m_iPOCLast -= 2;
if( getUseAdaptiveQP() )
{
AQpPreanalyzer::preanalyze( picCurr );
}
if( m_RCEnableRateControl )
{
m_cRateCtrl.initRCGOP( m_iNumPicRcvd );
}
m_cGOPEncoder.compressGOP( m_iPOCLast, m_iNumPicRcvd, m_cListPic, rcListPicYuvRecOut, false, false, snrCSC, m_printFrameMSE, true, 0 );
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
#if JVET_O0756_CALCULATE_HDRMETRICS
m_metricTime = m_cGOPEncoder.getMetricTime();
#endif
m_cGOPEncoder.setEncodedLTRef( true );
if( m_RCEnableRateControl )
{
m_cRateCtrl.destroyRCGOP();
}
iNumEncoded = 0;
m_iNumPicRcvd = 0;
}
//PROF_ACCUM_AND_START_NEW_SET( getProfilerPic(), P_GOP_LEVEL );
if( pcPicYuvOrg != NULL )
{
// get original YUV
Picture* pcPicCurr = NULL;
int ppsID = -1; // Use default PPS ID
#if ER_CHROMA_QP_WCG_PPS
if( getWCGChromaQPControl().isEnabled() )
{
ppsID = getdQPs()[m_iPOCLast / ( m_compositeRefEnabled ? 2 : 1 ) + 1];
ppsID += ( getSwitchPOC() != -1 && ( m_iPOCLast + 1 >= getSwitchPOC() ) ? 1 : 0 );
}
#endif
if( m_rprEnabled && m_uiIntraPeriod == -1 )
{
const int poc = m_iPOCLast + ( m_compositeRefEnabled ? 2 : 1 );
if( poc / m_switchPocPeriod % 2 )
{
ppsID = ENC_PPS_ID_RPR;
}
else
{
ppsID = 0;
}
}
#if JVET_Q0814_DPB
if( m_vps->getMaxLayers() > 1 )
#else
if( m_cVPS.getMaxLayers() > 1 )
{
ppsID = m_layerId;
}
xGetNewPicBuffer( rcListPicYuvRecOut, pcPicCurr, ppsID );
const PPS *pPPS = ( ppsID < 0 ) ? m_ppsMap.getFirstPS() : m_ppsMap.getPS( ppsID );
const SPS *pSPS = m_spsMap.getPS( pPPS->getSPSId() );
if( m_rprEnabled )
{
pcPicCurr->M_BUFS( 0, PIC_ORIGINAL_INPUT ).getBuf( COMPONENT_Y ).copyFrom( pcPicYuvOrg->getBuf( COMPONENT_Y ) );
pcPicCurr->M_BUFS( 0, PIC_ORIGINAL_INPUT ).getBuf( COMPONENT_Cb ).copyFrom( pcPicYuvOrg->getBuf( COMPONENT_Cb ) );
pcPicCurr->M_BUFS( 0, PIC_ORIGINAL_INPUT ).getBuf( COMPONENT_Cr ).copyFrom( pcPicYuvOrg->getBuf( COMPONENT_Cr ) );
pcPicCurr->M_BUFS( 0, PIC_TRUE_ORIGINAL_INPUT ).getBuf( COMPONENT_Y ).copyFrom( cPicYuvTrueOrg->getBuf( COMPONENT_Y ) );
pcPicCurr->M_BUFS( 0, PIC_TRUE_ORIGINAL_INPUT ).getBuf( COMPONENT_Cb ).copyFrom( cPicYuvTrueOrg->getBuf( COMPONENT_Cb ) );
pcPicCurr->M_BUFS( 0, PIC_TRUE_ORIGINAL_INPUT ).getBuf( COMPONENT_Cr ).copyFrom( cPicYuvTrueOrg->getBuf( COMPONENT_Cr ) );
const ChromaFormat chromaFormatIDC = pSPS->getChromaFormatIdc();
const PPS *refPPS = m_ppsMap.getPS( 0 );
Vadim Seregin
committed
const Window& curScalingWindow = pPPS->getScalingWindow();
#if JVET_Q0487_SCALING_WINDOW_ISSUES
int curPicWidth = pPPS->getPicWidthInLumaSamples() - SPS::getWinUnitX( pSPS->getChromaFormatIdc() ) * ( curScalingWindow.getWindowLeftOffset() + curScalingWindow.getWindowRightOffset() );
int curPicHeight = pPPS->getPicHeightInLumaSamples() - SPS::getWinUnitY( pSPS->getChromaFormatIdc() ) * ( curScalingWindow.getWindowTopOffset() + curScalingWindow.getWindowBottomOffset() );
#else
Vadim Seregin
committed
int curPicWidth = pPPS->getPicWidthInLumaSamples() - curScalingWindow.getWindowLeftOffset() - curScalingWindow.getWindowRightOffset();
int curPicHeight = pPPS->getPicHeightInLumaSamples() - curScalingWindow.getWindowTopOffset() - curScalingWindow.getWindowBottomOffset();
Vadim Seregin
committed
const Window& refScalingWindow = refPPS->getScalingWindow();
#if JVET_Q0487_SCALING_WINDOW_ISSUES
int refPicWidth = refPPS->getPicWidthInLumaSamples() - SPS::getWinUnitX( pSPS->getChromaFormatIdc() ) * ( refScalingWindow.getWindowLeftOffset() + refScalingWindow.getWindowRightOffset() );
int refPicHeight = refPPS->getPicHeightInLumaSamples() - SPS::getWinUnitY( pSPS->getChromaFormatIdc() ) * ( refScalingWindow.getWindowTopOffset() + refScalingWindow.getWindowBottomOffset() );
#else
Vadim Seregin
committed
int refPicWidth = refPPS->getPicWidthInLumaSamples() - refScalingWindow.getWindowLeftOffset() - refScalingWindow.getWindowRightOffset();
int refPicHeight = refPPS->getPicHeightInLumaSamples() - refScalingWindow.getWindowTopOffset() - refScalingWindow.getWindowBottomOffset();
Vadim Seregin
committed
int xScale = ( ( refPicWidth << SCALE_RATIO_BITS ) + ( curPicWidth >> 1 ) ) / curPicWidth;
int yScale = ( ( refPicHeight << SCALE_RATIO_BITS ) + ( curPicHeight >> 1 ) ) / curPicHeight;
std::pair<int, int> scalingRatio = std::pair<int, int>( xScale, yScale );
Picture::rescalePicture( scalingRatio, *pcPicYuvOrg, refPPS->getScalingWindow(), pcPicCurr->getOrigBuf(), pPPS->getScalingWindow(), chromaFormatIDC, pSPS->getBitDepths(), true, true,
pSPS->getHorCollocatedChromaFlag(), pSPS->getVerCollocatedChromaFlag() );
Picture::rescalePicture( scalingRatio, *cPicYuvTrueOrg, refPPS->getScalingWindow(), pcPicCurr->getTrueOrigBuf(), pPPS->getScalingWindow(), chromaFormatIDC, pSPS->getBitDepths(), true, true,
pSPS->getHorCollocatedChromaFlag(), pSPS->getVerCollocatedChromaFlag() );
}
else
{
pcPicCurr->M_BUFS( 0, PIC_ORIGINAL ).swap( *pcPicYuvOrg );
pcPicCurr->M_BUFS( 0, PIC_TRUE_ORIGINAL ).swap( *cPicYuvTrueOrg );
}
#if JVET_Q0814_DPB
pcPicCurr->finalInit( m_vps, *pSPS, *pPPS, &m_picHeader, m_apss, m_lmcsAPS, m_scalinglistAPS );
#else
pcPicCurr->finalInit( &m_cVPS, *pSPS, *pPPS, &m_picHeader, m_apss, m_lmcsAPS, m_scalinglistAPS );
pcPicCurr->poc = m_iPOCLast;
// compute image characteristics
if( getUseAdaptiveQP() )
{
AQpPreanalyzer::preanalyze( pcPicCurr );
}
}
if( ( m_iNumPicRcvd == 0 ) || ( !flush && ( m_iPOCLast != 0 ) && ( m_iNumPicRcvd != m_iGOPSize ) && ( m_iGOPSize != 0 ) ) )
{
iNumEncoded = 0;
return true;
}
if( m_RCEnableRateControl )
{
m_cRateCtrl.initRCGOP( m_iNumPicRcvd );
}
m_picIdInGOP = 0;
return false;

Karsten Suehring
committed
}
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
/**
- Application has picture buffer list with size of GOP + 1
- Picture buffer list acts like as ring buffer
- End of the list has the latest picture
.
\param flush cause encoder to encode a partial GOP
\param pcPicYuvOrg original YUV picture
\param pcPicYuvTrueOrg
\param snrCSC
\retval rcListPicYuvRecOut list of reconstruction YUV pictures
\retval accessUnitsOut list of output access units
\retval iNumEncoded number of encoded pictures
*/
bool EncLib::encode( const InputColourSpaceConversion snrCSC, std::list<PelUnitBuf*>& rcListPicYuvRecOut, int& iNumEncoded )
{
// compress GOP
m_cGOPEncoder.compressGOP( m_iPOCLast, m_iNumPicRcvd, m_cListPic, rcListPicYuvRecOut,
false, false, snrCSC, m_printFrameMSE, false, m_picIdInGOP );
m_picIdInGOP++;
// go over all pictures in a GOP excluding the first IRAP
if( m_picIdInGOP != m_iGOPSize && m_iPOCLast )
{
return true;
}
#if JVET_O0756_CALCULATE_HDRMETRICS
m_metricTime = m_cGOPEncoder.getMetricTime();
#endif
if( m_RCEnableRateControl )
{
m_cRateCtrl.destroyRCGOP();
}
iNumEncoded = m_iNumPicRcvd;
m_iNumPicRcvd = 0;
m_uiNumAllPicCoded += iNumEncoded;
return false;
}

Karsten Suehring
committed
/**------------------------------------------------
Separate interlaced frame into two fields
-------------------------------------------------**/
void separateFields(Pel* org, Pel* dstField, uint32_t stride, uint32_t width, uint32_t height, bool isTop)
{
if (!isTop)
{
org += stride;
}
for (int y = 0; y < height>>1; y++)
{
for (int x = 0; x < width; x++)
{
dstField[x] = org[x];
}
dstField += stride;
org += stride*2;
}
}
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
bool EncLib::encodePrep( bool flush, PelStorage* pcPicYuvOrg, PelStorage* pcPicYuvTrueOrg, const InputColourSpaceConversion snrCSC, std::list<PelUnitBuf*>& rcListPicYuvRecOut,
int& iNumEncoded, bool isTff )
{
iNumEncoded = 0;
bool keepDoing = true;
for( int fieldNum = 0; fieldNum < 2; fieldNum++ )
{
if( pcPicYuvOrg )
{
/* -- field initialization -- */
const bool isTopField = isTff == ( fieldNum == 0 );
Picture *pcField;
xGetNewPicBuffer( rcListPicYuvRecOut, pcField, -1 );
for( uint32_t comp = 0; comp < ::getNumberValidComponents( pcPicYuvOrg->chromaFormat ); comp++ )
{
const ComponentID compID = ComponentID( comp );
{
PelBuf compBuf = pcPicYuvOrg->get( compID );
separateFields( compBuf.buf,
pcField->getOrigBuf().get( compID ).buf,
compBuf.stride,
compBuf.width,
compBuf.height,
isTopField );
// to get fields of true original buffer to avoid wrong PSNR calculation in summary
compBuf = pcPicYuvTrueOrg->get( compID );
separateFields( compBuf.buf,
pcField->getTrueOrigBuf().get(compID).buf,
compBuf.stride,
compBuf.width,
compBuf.height,
isTopField);
int ppsID = -1; // Use default PPS ID
const PPS *pPPS = ( ppsID < 0 ) ? m_ppsMap.getFirstPS() : m_ppsMap.getPS( ppsID );
const SPS *pSPS = m_spsMap.getPS( pPPS->getSPSId() );
#if JVET_Q0814_DPB
pcField->finalInit( m_vps, *pSPS, *pPPS, &m_picHeader, m_apss, m_lmcsAPS, m_scalinglistAPS );
#else
pcField->finalInit( &m_cVPS, *pSPS, *pPPS, &m_picHeader, m_apss, m_lmcsAPS, m_scalinglistAPS );
#endif
pcField->poc = m_iPOCLast;
pcField->reconstructed = false;
pcField->setBorderExtension( false );// where is this normally?
pcField->topField = isTopField; // interlaced requirement
// compute image characteristics
if( getUseAdaptiveQP() )
{
AQpPreanalyzer::preanalyze( pcField );
}
}
}
if( m_iNumPicRcvd && ( flush || m_iPOCLast == 1 || m_iNumPicRcvd == m_iGOPSize ) )
{
m_picIdInGOP = 0;
m_iPOCLast -= 2;
keepDoing = false;
}
return keepDoing;
}
bool EncLib::encode( const InputColourSpaceConversion snrCSC, std::list<PelUnitBuf*>& rcListPicYuvRecOut, int& iNumEncoded, bool isTff )
{
iNumEncoded = 0;
for( int fieldNum = 0; fieldNum < 2; fieldNum++ )
{
m_iPOCLast = ( m_iNumPicRcvd == m_iGOPSize ) ? m_uiNumAllPicCoded + m_iNumPicRcvd - 1 : m_iPOCLast + 1;
// compress GOP
m_cGOPEncoder.compressGOP( m_iPOCLast, m_iPOCLast < 2 ? m_iPOCLast + 1 : m_iNumPicRcvd, m_cListPic, rcListPicYuvRecOut, true, isTff, snrCSC, m_printFrameMSE, false, m_picIdInGOP );
#if JVET_O0756_CALCULATE_HDRMETRICS
m_metricTime = m_cGOPEncoder.getMetricTime();
#endif
m_picIdInGOP++;
}
// go over all pictures in a GOP excluding first top field and first bottom field
if( m_picIdInGOP != m_iGOPSize && m_iPOCLast > 1 )
{
return true;
}
iNumEncoded += m_iNumPicRcvd;
m_uiNumAllPicCoded += m_iNumPicRcvd;
m_iNumPicRcvd = 0;
return false;

Karsten Suehring
committed
// ====================================================================================================================
// Protected member functions
// ====================================================================================================================
/**
- Application has picture buffer list with size of GOP + 1
- Picture buffer list acts like as ring buffer
- End of the list has the latest picture
.
\retval rpcPic obtained picture buffer
*/
void EncLib::xGetNewPicBuffer ( std::list<PelUnitBuf*>& rcListPicYuvRecOut, Picture*& rpcPic, int ppsId )
{

Karsten Suehring
committed
rcListPicYuvRecOut.push_back( rcListPicYuvRecOut.front() ); rcListPicYuvRecOut.pop_front();
rpcPic=0;
// At this point, the SPS and PPS can be considered activated - they are copied to the new Pic.
const PPS *pPPS=(ppsId<0) ? m_ppsMap.getFirstPS() : m_ppsMap.getPS(ppsId);
CHECK(!(pPPS!=0), "Unspecified error");
const PPS &pps=*pPPS;
const SPS *pSPS=m_spsMap.getPS(pps.getSPSId());
CHECK(!(pSPS!=0), "Unspecified error");
const SPS &sps=*pSPS;
Slice::sortPicList(m_cListPic);
// use an entry in the buffered list if the maximum number that need buffering has been reached:
#if JVET_Q0814_DPB
int maxDecPicBuffering = ( m_vps == nullptr || m_vps->m_numLayersInOls[m_vps->m_targetOlsIdx] == 1 ) ? sps.getMaxDecPicBuffering( MAX_TLAYER - 1 ) : m_vps->getMaxDecPicBuffering( MAX_TLAYER - 1 );
if( m_cListPic.size() >= (uint32_t)( m_iGOPSize + maxDecPicBuffering + 2 ) )
#else
if( m_cListPic.size() >= (uint32_t)( m_iGOPSize + getMaxDecPicBuffering( MAX_TLAYER - 1 ) + 2 ) )

Karsten Suehring
committed
{
PicList::iterator iterPic = m_cListPic.begin();

Karsten Suehring
committed
int iSize = int( m_cListPic.size() );

Karsten Suehring
committed
{
rpcPic = *iterPic;
if( !rpcPic->referenced && rpcPic->layerId == m_layerId )

Karsten Suehring
committed
{
break;
}

Karsten Suehring
committed
iterPic++;
}