Commit d020de2a authored by Yu-Chi Su's avatar Yu-Chi Su

JVET_L0646 GBi Merge Commit

parents 378acb66 9736275f
......@@ -104,7 +104,9 @@ void AdaptiveLoopFilter::ALFProcess( CodingStructure& cs, AlfSliceParam& alfSlic
{
Area blk( xPos, yPos, width, height );
deriveClassification( m_classifier, tmpYuv.get( COMPONENT_Y ), blk );
#if JVET_L0664_ALF_REMOVE_LUMA_5x5
m_filter7x7Blk(m_classifier, recYuv, tmpYuv, blk, COMPONENT_Y, m_coeffFinal, m_clpRngs.comp[COMPONENT_Y]);
#else
if( alfSliceParam.lumaFilterType == ALF_FILTER_5 )
{
m_filter5x5Blk( m_classifier, recYuv, tmpYuv, blk, COMPONENT_Y, m_coeffFinal, m_clpRngs.comp[COMPONENT_Y] );
......@@ -117,6 +119,7 @@ void AdaptiveLoopFilter::ALFProcess( CodingStructure& cs, AlfSliceParam& alfSlic
{
CHECK( 0, "Wrong ALF filter type" );
}
#endif
}
for( int compIdx = 1; compIdx < MAX_NUM_COMPONENT; compIdx++ )
......@@ -140,8 +143,11 @@ void AdaptiveLoopFilter::ALFProcess( CodingStructure& cs, AlfSliceParam& alfSlic
void AdaptiveLoopFilter::reconstructCoeff( AlfSliceParam& alfSliceParam, ChannelType channel, const bool bRedo )
{
int factor = ( 1 << ( m_NUM_BITS - 1 ) );
#if JVET_L0664_ALF_REMOVE_LUMA_5x5
AlfFilterType filterType = isLuma( channel ) ? ALF_FILTER_7 : ALF_FILTER_5;
#else
AlfFilterType filterType = isLuma( channel ) ? alfSliceParam.lumaFilterType : ALF_FILTER_5;
#endif
int numClasses = isLuma( channel ) ? MAX_NUM_ALF_CLASSES : 1;
int numCoeff = filterType == ALF_FILTER_5 ? 7 : 13;
int numCoeffMinus1 = numCoeff - 1;
......@@ -205,8 +211,9 @@ void AdaptiveLoopFilter::create( const int picWidth, const int picHeight, const
m_numCTUsInWidth = ( m_picWidth / m_maxCUWidth ) + ( ( m_picWidth % m_maxCUWidth ) ? 1 : 0 );
m_numCTUsInHeight = ( m_picHeight / m_maxCUHeight ) + ( ( m_picHeight % m_maxCUHeight ) ? 1 : 0 );
m_numCTUsInPic = m_numCTUsInHeight * m_numCTUsInWidth;
#if !JVET_L0664_ALF_REMOVE_LUMA_5x5
m_filterShapes[CHANNEL_TYPE_LUMA].push_back( AlfFilterShape( 5 ) );
#endif
m_filterShapes[CHANNEL_TYPE_LUMA].push_back( AlfFilterShape( 7 ) );
m_filterShapes[CHANNEL_TYPE_CHROMA].push_back( AlfFilterShape( 5 ) );
......@@ -489,7 +496,12 @@ void AdaptiveLoopFilter::filterBlk( AlfClassifier** classifier, const PelUnitBuf
short *coef = filterSet;
#if JVET_L0083_ALF_FRAC_BIT
const int shift = m_NUM_BITS - 1;
#else
const int shift = 9;
#endif
const int offset = 1 << ( shift - 1 );
int transposeIdx = 0;
......
......@@ -66,7 +66,11 @@ enum Direction
class AdaptiveLoopFilter
{
public:
#if JVET_L0083_ALF_FRAC_BIT
static constexpr int m_NUM_BITS = 8;
#else
static constexpr int m_NUM_BITS = 10;
#endif
static constexpr int m_CLASSIFICATION_BLK_SIZE = 32; //non-normative, local buffer size
AdaptiveLoopFilter();
......
......@@ -50,6 +50,12 @@
#include <assert.h>
#include <cassert>
#define JVET_L0664_ALF_REMOVE_LUMA_5x5 1
#define JVET_L0083_ALF_FRAC_BIT 1 // Reduce number of ALF fractional bit to 7
#define JVET_L0082_ALF_COEF_BITS 1 // ALF filter coefficient bitwidth constraints
#define JVET_L0646_GBI 1 // Generalized bi-prediction (GBi)
#define REUSE_CU_RESULTS 1
......@@ -1411,7 +1417,9 @@ struct AlfFilterShape
struct AlfSliceParam
{
bool enabledFlag[MAX_NUM_COMPONENT]; // alf_slice_enable_flag, alf_chroma_idc
#if !JVET_L0664_ALF_REMOVE_LUMA_5x5
AlfFilterType lumaFilterType; // filter_type_flag
#endif
bool chromaCtbPresentFlag; // alf_chroma_ctb_present_flag
short lumaCoeff[MAX_NUM_ALF_CLASSES * MAX_NUM_ALF_LUMA_COEFF]; // alf_coeff_luma_delta[i][j]
short chromaCoeff[MAX_NUM_ALF_CHROMA_COEFF]; // alf_coeff_chroma[i]
......@@ -1425,7 +1433,9 @@ struct AlfSliceParam
void reset()
{
std::memset( enabledFlag, false, sizeof( enabledFlag ) );
#if !JVET_L0664_ALF_REMOVE_LUMA_5x5
lumaFilterType = ALF_FILTER_5;
#endif
std::memset( lumaCoeff, 0, sizeof( lumaCoeff ) );
std::memset( chromaCoeff, 0, sizeof( chromaCoeff ) );
std::memset( filterCoeffDeltaIdx, 0, sizeof( filterCoeffDeltaIdx ) );
......@@ -1439,7 +1449,9 @@ struct AlfSliceParam
const AlfSliceParam& operator = ( const AlfSliceParam& src )
{
std::memcpy( enabledFlag, src.enabledFlag, sizeof( enabledFlag ) );
#if !JVET_L0664_ALF_REMOVE_LUMA_5x5
lumaFilterType = src.lumaFilterType;
#endif
std::memcpy( lumaCoeff, src.lumaCoeff, sizeof( lumaCoeff ) );
std::memcpy( chromaCoeff, src.chromaCoeff, sizeof( chromaCoeff ) );
std::memcpy( filterCoeffDeltaIdx, src.filterCoeffDeltaIdx, sizeof( filterCoeffDeltaIdx ) );
......
......@@ -2272,10 +2272,10 @@ void HLSyntaxReader::alf( AlfSliceParam& alfSliceParam )
xReadTruncBinCode( code, MAX_NUM_ALF_CLASSES ); //number_of_filters_minus1
alfSliceParam.numLumaFilters = code + 1;
#if !JVET_L0664_ALF_REMOVE_LUMA_5x5
READ_FLAG( code, "filter_type_flag" );
alfSliceParam.lumaFilterType = code ? ALF_FILTER_5 : ALF_FILTER_7;
#endif
if( alfSliceParam.numLumaFilters > 1 )
{
for( int i = 0; i < MAX_NUM_ALF_CLASSES; i++ )
......@@ -2372,7 +2372,11 @@ void HLSyntaxReader::alfFilter( AlfSliceParam& alfSliceParam, const bool isChrom
}
// derive maxGolombIdx
#if JVET_L0664_ALF_REMOVE_LUMA_5x5
AlfFilterShape alfShape( isChroma ? 5 : 7 );
#else
AlfFilterShape alfShape( isChroma ? 5 : ( alfSliceParam.lumaFilterType == ALF_FILTER_5 ? 5 : 7 ) );
#endif
const int maxGolombIdx = AdaptiveLoopFilter::getMaxGolombIdx( alfShape.filterType );
READ_UVLC( code, "min_golomb_order" );
......
......@@ -340,11 +340,12 @@ void EncAdaptiveLoopFilter::alfEncoder( CodingStructure& cs, AlfSliceParam& alfS
for( int iShapeIdx = 0; iShapeIdx < alfFilterShape.size(); iShapeIdx++ )
{
m_alfSliceParamTemp = alfSliceParam;
#if !JVET_L0664_ALF_REMOVE_LUMA_5x5
if( isLuma( channel ) )
{
m_alfSliceParamTemp.lumaFilterType = alfFilterShape[iShapeIdx].filterType;
}
#endif
//1. get unfiltered distortion
double cost = getUnfilteredDistortion( m_alfCovarianceFrame[channel][iShapeIdx], channel );
cost /= 1.001; // slight preference for unfiltered choice
......@@ -382,7 +383,11 @@ void EncAdaptiveLoopFilter::alfEncoder( CodingStructure& cs, AlfSliceParam& alfS
//3. CTU decision
double distUnfilter = 0;
#if JVET_L0664_ALF_REMOVE_LUMA_5x5
const int iterNum = isLuma(channel) ? (2 * 4 + 1) : (2 * 2 + 1);
#else
const int iterNum = 2 * 2 + 1;
#endif
for( int iter = 0; iter < iterNum; iter++ )
{
......@@ -421,7 +426,11 @@ void EncAdaptiveLoopFilter::alfEncoder( CodingStructure& cs, AlfSliceParam& alfS
int ctuIdx = 0;
const int chromaScaleX = getComponentScaleX( compID, recBuf.chromaFormat );
const int chromaScaleY = getComponentScaleY( compID, recBuf.chromaFormat );
#if JVET_L0664_ALF_REMOVE_LUMA_5x5
AlfFilterType filterType = isLuma( compID ) ? ALF_FILTER_7 : ALF_FILTER_5;
#else
AlfFilterType filterType = isLuma( compID ) ? alfSliceParam.lumaFilterType : ALF_FILTER_5;
#endif
short* coeff = isLuma( compID ) ? m_coeffFinal : alfSliceParam.chromaCoeff;
for( int yPos = 0; yPos < pcv.lumaHeight; yPos += pcv.maxCUHeight )
......@@ -535,7 +544,11 @@ int EncAdaptiveLoopFilter::getCoeffRate( AlfSliceParam& alfSliceParam, bool isCh
}
memset( m_bitsCoeffScan, 0, sizeof( m_bitsCoeffScan ) );
#if JVET_L0664_ALF_REMOVE_LUMA_5x5
AlfFilterShape alfShape( isChroma ? 5 : 7 );
#else
AlfFilterShape alfShape( isChroma ? 5 : ( alfSliceParam.lumaFilterType == ALF_FILTER_5 ? 5 : 7 ) );
#endif
const int maxGolombIdx = AdaptiveLoopFilter::getMaxGolombIdx( alfShape.filterType );
const short* coeff = isChroma ? alfSliceParam.chromaCoeff : alfSliceParam.lumaCoeff;
const int numFilters = isChroma ? 1 : alfSliceParam.numLumaFilters;
......@@ -1126,9 +1139,15 @@ double EncAdaptiveLoopFilter::deriveCoeffQuant( int *filterCoeffQuant, double **
memset( filterCoeffQuant, 0, sizeof( int ) * numCoeff );
}
#if JVET_L0082_ALF_COEF_BITS
int max_value = factor - 1;
int min_value = -factor;
#else
//512 -> 1, (64+32+4+2)->0.199
int max_value = 512 + 64 + 32 + 4 + 2;
int min_value = -max_value;
#endif
for ( int i = 0; i < numCoeff - 1; i++ )
{
filterCoeffQuant[i] = std::min( max_value, std::max( min_value, filterCoeffQuant[i] ) );
......@@ -1144,6 +1163,74 @@ double EncAdaptiveLoopFilter::deriveCoeffQuant( int *filterCoeffQuant, double **
filterCoeffQuant[numCoeff - 1] = -quantCoeffSum;
filterCoeff[numCoeff - 1] = filterCoeffQuant[numCoeff - 1] / double(factor);
#if JVET_L0082_ALF_COEF_BITS
//Restrict the range of the center coefficient
int max_value_center = (2 * factor - 1) - factor;
int min_value_center = 0 - factor;
filterCoeffQuant[numCoeff - 1] = std::min(max_value_center, std::max(min_value_center, filterCoeffQuant[numCoeff - 1]));
filterCoeff[numCoeff - 1] = filterCoeffQuant[numCoeff - 1] / double(factor);
int coeffQuantAdjust[MAX_NUM_ALF_LUMA_COEFF];
int adjustedTotalCoeff = (numCoeff - 1) << 1;
count = 0;
quantCoeffSum += filterCoeffQuant[numCoeff - 1];
while (quantCoeffSum != targetCoeffSumInt && count < 15)
{
int sign = quantCoeffSum > targetCoeffSumInt ? 1 : -1;
int diff = (quantCoeffSum - targetCoeffSumInt) * sign;
if (diff > 4 * adjustedTotalCoeff) sign = sign * 8;
else if (diff > 2 * adjustedTotalCoeff) sign = sign * 4;
else if (diff > adjustedTotalCoeff) sign = sign * 2;
double errMin = MAX_DOUBLE;
int minInd = -1;
for (int k = 0; k < numCoeff - 1; k++)
{
memcpy(coeffQuantAdjust, filterCoeffQuant, sizeof(int) * numCoeff);
coeffQuantAdjust[k] -= sign;
if (coeffQuantAdjust[k] <= max_value && coeffQuantAdjust[k] >= min_value)
{
double error = calcErrorForCoeffs(E, y, coeffQuantAdjust, numCoeff, bitDepth);
if (error < errMin)
{
errMin = error;
minInd = k;
}
}
}
if (minInd != -1)
{
filterCoeffQuant[minInd] -= sign;
quantCoeffSum -= (weights[minInd] * sign);
}
++count;
}
if (quantCoeffSum != targetCoeffSumInt)
{
memset(filterCoeffQuant, 0, sizeof(int) * numCoeff);
}
for (int i = 0; i < numCoeff - 1; i++)
{
CHECK(filterCoeffQuant[i] > max_value || filterCoeffQuant[i] < min_value, "filterCoeffQuant[i]>max_value || filterCoeffQuant[i]<min_value");
filterCoeff[i] = filterCoeffQuant[i] / double(factor);
}
CHECK(filterCoeffQuant[numCoeff - 1] > max_value_center || filterCoeffQuant[numCoeff - 1] < min_value_center, "filterCoeffQuant[numCoeff-1]>max_value_center || filterCoeffQuant[numCoeff-1]<min_value_center");
filterCoeff[numCoeff - 1] = filterCoeffQuant[numCoeff - 1] / double(factor);
#endif
double error = calcErrorForCoeffs( E, y, filterCoeffQuant, numCoeff, bitDepth );
return error;
}
......
......@@ -1571,8 +1571,9 @@ void HLSWriter::alf( const AlfSliceParam& alfSliceParam )
truncatedUnaryEqProb( alfChromaIdc, 3 ); // alf_chroma_idc
xWriteTruncBinCode( alfSliceParam.numLumaFilters - 1, MAX_NUM_ALF_CLASSES ); //number_of_filters_minus1
#if !JVET_L0664_ALF_REMOVE_LUMA_5x5
WRITE_FLAG( alfSliceParam.lumaFilterType == ALF_FILTER_5 ? 1 : 0, "filter_type_flag" );
#endif
if( alfSliceParam.numLumaFilters > 1 )
{
for( int i = 0; i < MAX_NUM_ALF_CLASSES; i++ )
......@@ -1633,7 +1634,11 @@ void HLSWriter::alfFilter( const AlfSliceParam& alfSliceParam, const bool isChro
static int bitsCoeffScan[EncAdaptiveLoopFilter::m_MAX_SCAN_VAL][EncAdaptiveLoopFilter::m_MAX_EXP_GOLOMB];
memset( bitsCoeffScan, 0, sizeof( bitsCoeffScan ) );
#if JVET_L0664_ALF_REMOVE_LUMA_5x5
AlfFilterShape alfShape( isChroma ? 5 : 7 );
#else
AlfFilterShape alfShape( isChroma ? 5 : ( alfSliceParam.lumaFilterType == ALF_FILTER_5 ? 5 : 7 ) );
#endif
const int maxGolombIdx = AdaptiveLoopFilter::getMaxGolombIdx( alfShape.filterType );
const short* coeff = isChroma ? alfSliceParam.chromaCoeff : alfSliceParam.lumaCoeff;
const int numFilters = isChroma ? 1 : alfSliceParam.numLumaFilters;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment