Newer
Older

Karsten Suehring
committed
}
m_pcCfg->setEncodedFlag(iGOPid, true);
double PSNR_Y;
xCalculateAddPSNRs(isField, isTff, iGOPid, pcPic, accessUnit, rcListPic, encTime, snr_conversion, printFrameMSE, &PSNR_Y
, isEncodeLtRef
);

Karsten Suehring
committed
#if HEVC_SEI

Karsten Suehring
committed
// Only produce the Green Metadata SEI message with the last picture.
if( m_pcCfg->getSEIGreenMetadataInfoSEIEnable() && pcSlice->getPOC() == ( m_pcCfg->getFramesToBeEncoded() - 1 ) )
{
SEIGreenMetadataInfo *seiGreenMetadataInfo = new SEIGreenMetadataInfo;
m_seiEncoder.initSEIGreenMetadataInfo(seiGreenMetadataInfo, (uint32_t)(PSNR_Y * 100 + 0.5));
trailingSeiMessages.push_back(seiGreenMetadataInfo);
}
#endif

Karsten Suehring
committed
xWriteTrailingSEIMessages(trailingSeiMessages, accessUnit, pcSlice->getTLayer(), pcSlice->getSPS());
printHash(m_pcCfg->getDecodedPictureHashSEIType(), digestStr);
if ( m_pcCfg->getUseRateCtrl() )
{
double avgQP = m_pcRateCtrl->getRCPic()->calAverageQP();
double avgLambda = m_pcRateCtrl->getRCPic()->calAverageLambda();
if ( avgLambda < 0.0 )
{
avgLambda = lambda;
}
m_pcRateCtrl->getRCPic()->updateAfterPicture( actualHeadBits, actualTotalBits, avgQP, avgLambda, pcSlice->isIRAP());

Karsten Suehring
committed
m_pcRateCtrl->getRCPic()->addToPictureLsit( m_pcRateCtrl->getPicList() );
m_pcRateCtrl->getRCSeq()->updateAfterPic( actualTotalBits );

Karsten Suehring
committed
{
m_pcRateCtrl->getRCGOP()->updateAfterPicture( actualTotalBits );
}
else // for intra picture, the estimated bits are used to update the current status in the GOP
{
m_pcRateCtrl->getRCGOP()->updateAfterPicture( estimatedBits );
}
#if U0132_TARGET_BITS_SATURATION
if (m_pcRateCtrl->getCpbSaturationEnabled())
{
m_pcRateCtrl->updateCpbState(actualTotalBits);
msg( NOTICE, " [CPB %6d bits]", m_pcRateCtrl->getCpbState() );
}
#endif
}
xCreatePictureTimingSEI( m_pcCfg->getEfficientFieldIRAPEnabled() ? effFieldIRAPMap.GetIRAPGOPid() : 0, leadingSeiMessages, nestedSeiMessages, duInfoSeiMessages, pcSlice, isField, duData );
#if HEVC_SEI
if( m_pcCfg->getScalableNestingSEIEnabled() )

Karsten Suehring
committed
{
xCreateScalableNestingSEI( leadingSeiMessages, nestedSeiMessages );
}
#endif

Karsten Suehring
committed
xWriteLeadingSEIMessages( leadingSeiMessages, duInfoSeiMessages, accessUnit, pcSlice->getTLayer(), pcSlice->getSPS(), duData );
xWriteDuSEIMessages( duInfoSeiMessages, accessUnit, pcSlice->getTLayer(), pcSlice->getSPS(), duData );
m_AUWriterIf->outputAU( accessUnit );
msg( NOTICE, "\n" );
fflush( stdout );
}
DTRACE_UPDATE( g_trace_ctx, ( std::make_pair( "final", 0 ) ) );
pcPic->reconstructed = true;
m_bFirst = false;
m_iNumPicCoded++;
if (!(m_pcCfg->getUseCompositeRef() && isEncodeLtRef))
m_totalCoded ++;

Karsten Suehring
committed
/* logging: insert a newline at end of picture period */
if (m_pcCfg->getEfficientFieldIRAPEnabled())
{
iGOPid=effFieldIRAPMap.restoreGOPid(iGOPid);
}
pcPic->destroyTempBuffers();
pcPic->cs->destroyCoeffs();
pcPic->cs->releaseIntermediateData();
} // iGOPid-loop
delete pcBitstreamRedirect;
CHECK(!( (m_iNumPicCoded == iNumPicRcvd) ), "Unspecified error");
}
#if RPR_CTC_PRINT
void EncGOP::printOutSummary( uint32_t uiNumAllPicCoded, bool isField, const bool printMSEBasedSNR, const bool printSequenceMSE, const bool printHexPsnr, const bool printRprPSNR, const BitDepths &bitDepths )
#else
void EncGOP::printOutSummary(uint32_t uiNumAllPicCoded, bool isField, const bool printMSEBasedSNR, const bool printSequenceMSE, const bool printHexPsnr, const BitDepths &bitDepths)
#endif

Karsten Suehring
committed
{
#if ENABLE_QPA
const bool useWPSNR = m_pcEncLib->getUseWPSNR();
#endif
#if WCG_WPSNR
const bool useLumaWPSNR = m_pcEncLib->getLumaLevelToDeltaQPMapping().isEnabled() || (m_pcCfg->getReshaper() && m_pcCfg->getReshapeSignalType() == RESHAPE_SIGNAL_PQ);

Karsten Suehring
committed
#endif
if( m_pcCfg->getDecodeBitstream(0).empty() && m_pcCfg->getDecodeBitstream(1).empty() && !m_pcCfg->useFastForwardToPOC() )
{
CHECK( !( uiNumAllPicCoded == m_gcAnalyzeAll.getNumPic() ), "Unspecified error" );
}
//--CFG_KDY
const int rateMultiplier=(isField?2:1);
m_gcAnalyzeAll.setFrmRate( m_pcCfg->getFrameRate()*rateMultiplier / (double)m_pcCfg->getTemporalSubsampleRatio());
m_gcAnalyzeI.setFrmRate( m_pcCfg->getFrameRate()*rateMultiplier / (double)m_pcCfg->getTemporalSubsampleRatio());
m_gcAnalyzeP.setFrmRate( m_pcCfg->getFrameRate()*rateMultiplier / (double)m_pcCfg->getTemporalSubsampleRatio());
m_gcAnalyzeB.setFrmRate( m_pcCfg->getFrameRate()*rateMultiplier / (double)m_pcCfg->getTemporalSubsampleRatio());
#if WCG_WPSNR
if (useLumaWPSNR)
{
m_gcAnalyzeWPSNR.setFrmRate(m_pcCfg->getFrameRate()*rateMultiplier / (double)m_pcCfg->getTemporalSubsampleRatio());
}
#endif

Karsten Suehring
committed
const ChromaFormat chFmt = m_pcCfg->getChromaFormatIdc();
//-- all
msg( INFO, "\n" );
msg( DETAILS,"\nSUMMARY --------------------------------------------------------\n" );
Dominik Mehlem
committed
#if JVET_O0756_CALCULATE_HDRMETRICS
const bool calculateHdrMetrics = m_pcEncLib->getCalcluateHdrMetrics();
#endif

Karsten Suehring
committed
#if ENABLE_QPA
#if RPR_CTC_PRINT
Vadim Seregin
committed
m_gcAnalyzeAll.printOut( 'a', chFmt, printMSEBasedSNR, printSequenceMSE, printHexPsnr, printRprPSNR, bitDepths, useWPSNR
Dominik Mehlem
committed
#if JVET_O0756_CALCULATE_HDRMETRICS
, calculateHdrMetrics
#endif
);
#else
Vadim Seregin
committed
m_gcAnalyzeAll.printOut('a', chFmt, printMSEBasedSNR, printSequenceMSE, printHexPsnr, bitDepths, useWPSNR
#if JVET_O0756_CALCULATE_HDRMETRICS
, calculateHdrMetrics
#endif
#endif

Karsten Suehring
committed
#else
Dominik Mehlem
committed
m_gcAnalyzeAll.printOut('a', chFmt, printMSEBasedSNR, printSequenceMSE, printHexPsnr, bitDepths
#if JVET_O0756_CALCULATE_HDRMETRICS
, calculateHdrMetrics
#endif
);

Karsten Suehring
committed
#endif
#if RPR_CTC_PRINT
msg( DETAILS, "\n\nI Slices--------------------------------------------------------\n" );
m_gcAnalyzeI.printOut( 'i', chFmt, printMSEBasedSNR, printSequenceMSE, printHexPsnr, printRprPSNR, bitDepths );
msg( DETAILS, "\n\nP Slices--------------------------------------------------------\n" );
m_gcAnalyzeP.printOut( 'p', chFmt, printMSEBasedSNR, printSequenceMSE, printHexPsnr, printRprPSNR, bitDepths );
msg( DETAILS, "\n\nB Slices--------------------------------------------------------\n" );
m_gcAnalyzeB.printOut( 'b', chFmt, printMSEBasedSNR, printSequenceMSE, printHexPsnr, printRprPSNR, bitDepths );
#else

Karsten Suehring
committed
msg( DETAILS,"\n\nI Slices--------------------------------------------------------\n" );
m_gcAnalyzeI.printOut('i', chFmt, printMSEBasedSNR, printSequenceMSE, printHexPsnr, bitDepths);

Karsten Suehring
committed
msg( DETAILS,"\n\nP Slices--------------------------------------------------------\n" );
m_gcAnalyzeP.printOut('p', chFmt, printMSEBasedSNR, printSequenceMSE, printHexPsnr, bitDepths);

Karsten Suehring
committed
msg( DETAILS,"\n\nB Slices--------------------------------------------------------\n" );
m_gcAnalyzeB.printOut('b', chFmt, printMSEBasedSNR, printSequenceMSE, printHexPsnr, bitDepths);
#endif

Karsten Suehring
committed
#if WCG_WPSNR
if (useLumaWPSNR)
{
msg(DETAILS, "\nWPSNR SUMMARY --------------------------------------------------------\n");
#if RPR_CTC_PRINT
m_gcAnalyzeWPSNR.printOut( 'w', chFmt, printMSEBasedSNR, printSequenceMSE, printHexPsnr, printRprPSNR, bitDepths, useLumaWPSNR );
#else
m_gcAnalyzeWPSNR.printOut('w', chFmt, printMSEBasedSNR, printSequenceMSE, printHexPsnr, bitDepths, useLumaWPSNR);
#endif

Karsten Suehring
committed
}
#endif
if (!m_pcCfg->getSummaryOutFilename().empty())
{
m_gcAnalyzeAll.printSummary(chFmt, printSequenceMSE, printHexPsnr, bitDepths, m_pcCfg->getSummaryOutFilename());

Karsten Suehring
committed
}
if (!m_pcCfg->getSummaryPicFilenameBase().empty())
{
m_gcAnalyzeI.printSummary(chFmt, printSequenceMSE, printHexPsnr, bitDepths, m_pcCfg->getSummaryPicFilenameBase()+"I.txt");
m_gcAnalyzeP.printSummary(chFmt, printSequenceMSE, printHexPsnr, bitDepths, m_pcCfg->getSummaryPicFilenameBase()+"P.txt");
m_gcAnalyzeB.printSummary(chFmt, printSequenceMSE, printHexPsnr, bitDepths, m_pcCfg->getSummaryPicFilenameBase()+"B.txt");

Karsten Suehring
committed
}
#if WCG_WPSNR
if (!m_pcCfg->getSummaryOutFilename().empty() && useLumaWPSNR)
{
m_gcAnalyzeWPSNR.printSummary(chFmt, printSequenceMSE, printHexPsnr, bitDepths, m_pcCfg->getSummaryOutFilename());

Karsten Suehring
committed
}
#endif
if(isField)
{
//-- interlaced summary
m_gcAnalyzeAll_in.setFrmRate( m_pcCfg->getFrameRate() / (double)m_pcCfg->getTemporalSubsampleRatio());
m_gcAnalyzeAll_in.setBits(m_gcAnalyzeAll.getBits());
// prior to the above statement, the interlace analyser does not contain the correct total number of bits.
msg( DETAILS,"\n\nSUMMARY INTERLACED ---------------------------------------------\n" );
#if ENABLE_QPA
#if RPR_CTC_PRINT
m_gcAnalyzeAll_in.printOut( 'a', chFmt, printMSEBasedSNR, printSequenceMSE, printHexPsnr, printRprPSNR, bitDepths, useWPSNR );
#else
m_gcAnalyzeAll_in.printOut('a', chFmt, printMSEBasedSNR, printSequenceMSE, printHexPsnr, bitDepths, useWPSNR);
#endif

Karsten Suehring
committed
#else
m_gcAnalyzeAll_in.printOut('a', chFmt, printMSEBasedSNR, printSequenceMSE, printHexPsnr, bitDepths);

Karsten Suehring
committed
#endif
if (!m_pcCfg->getSummaryOutFilename().empty())
{
m_gcAnalyzeAll_in.printSummary(chFmt, printSequenceMSE, printHexPsnr, bitDepths, m_pcCfg->getSummaryOutFilename());

Karsten Suehring
committed
#if WCG_WPSNR
if (useLumaWPSNR)
{
m_gcAnalyzeWPSNR.printSummary(chFmt, printSequenceMSE, printHexPsnr, bitDepths, m_pcCfg->getSummaryOutFilename());

Karsten Suehring
committed
3229
3230
3231
3232
3233
3234
3235
3236
3237
3238
3239
3240
3241
3242
3243
3244
3245
3246
3247
3248
3249
3250
3251
3252
3253
3254
3255
3256
3257
3258
3259
3260
3261
3262
}
#endif
}
}
msg( DETAILS,"\nRVM: %.3lf\n", xCalculateRVM() );
}
#if W0038_DB_OPT
uint64_t EncGOP::preLoopFilterPicAndCalcDist( Picture* pcPic )
{
CodingStructure& cs = *pcPic->cs;
m_pcLoopFilter->loopFilterPic( cs );
const CPelUnitBuf picOrg = pcPic->getRecoBuf();
const CPelUnitBuf picRec = cs.getRecoBuf();
uint64_t uiDist = 0;
for( uint32_t comp = 0; comp < (uint32_t)picRec.bufs.size(); comp++)
{
const ComponentID compID = ComponentID(comp);
const uint32_t rshift = 2 * DISTORTION_PRECISION_ADJUSTMENT(cs.sps->getBitDepth(toChannelType(compID)));
#if ENABLE_QPA
CHECK( rshift >= 8, "shifts greater than 7 are not supported." );
#endif
uiDist += xFindDistortionPlane( picOrg.get(compID), picRec.get(compID), rshift );
}
return uiDist;
}
#endif
// ====================================================================================================================
// Protected member functions
// ====================================================================================================================
void EncGOP::xInitGOP( int iPOCLast, int iNumPicRcvd, bool isField
, bool isEncodeLtRef
)

Karsten Suehring
committed
{
CHECK(!( iNumPicRcvd > 0 ), "Unspecified error");
// Exception for the first frames
if ((isField && (iPOCLast == 0 || iPOCLast == 1)) || (!isField && (iPOCLast == 0)) || isEncodeLtRef)

Karsten Suehring
committed
3270
3271
3272
3273
3274
3275
3276
3277
3278
3279
3280
3281
3282
3283
3284
3285
3286
3287
3288
3289
3290
3291
3292
3293
3294
3295
3296
3297
3298
3299
{
m_iGopSize = 1;
}
else
{
m_iGopSize = m_pcCfg->getGOPSize();
}
CHECK(!(m_iGopSize > 0), "Unspecified error");
return;
}
void EncGOP::xGetBuffer( PicList& rcListPic,
std::list<PelUnitBuf*>& rcListPicYuvRecOut,
int iNumPicRcvd,
int iTimeOffset,
Picture*& rpcPic,
int pocCurr,
bool isField )
{
int i;
// Rec. output
std::list<PelUnitBuf*>::iterator iterPicYuvRec = rcListPicYuvRecOut.end();
if (isField && pocCurr > 1 && m_iGopSize!=1)
{
iTimeOffset--;
}
int multipleFactor = m_pcCfg->getUseCompositeRef() ? 2 : 1;
for (i = 0; i < (iNumPicRcvd * multipleFactor - iTimeOffset + 1); i += multipleFactor)

Karsten Suehring
committed
3302
3303
3304
3305
3306
3307
3308
3309
3310
3311
3312
3313
3314
3315
3316
3317
3318
3319
3320
3321
3322
3323
3324
3325
3326
3327
{
iterPicYuvRec--;
}
// Current pic.
PicList::iterator iterPic = rcListPic.begin();
while (iterPic != rcListPic.end())
{
rpcPic = *(iterPic);
if (rpcPic->getPOC() == pocCurr)
{
break;
}
iterPic++;
}
CHECK(!(rpcPic != NULL), "Unspecified error");
CHECK(!(rpcPic->getPOC() == pocCurr), "Unspecified error");
(**iterPicYuvRec) = rpcPic->getRecoBuf();
return;
}
#if ENABLE_QPA
#ifndef BETA
#define BETA 0.5 // value between 0.0 and 1; use 0.0 to obtain traditional PSNR

Karsten Suehring
committed
#endif
static inline double calcWeightedSquaredError(const CPelBuf& org, const CPelBuf& rec,
double &sumAct, const uint32_t bitDepth,
const uint32_t imageWidth, const uint32_t imageHeight,
const uint32_t offsetX, const uint32_t offsetY,
int blockWidth, int blockHeight)

Karsten Suehring
committed
{
const int O = org.stride;
const int R = rec.stride;
const Pel *o = org.bufAt(offsetX, offsetY);
const Pel *r = rec.bufAt(offsetX, offsetY);
const int yAct = offsetY > 0 ? 0 : 1;
const int xAct = offsetX > 0 ? 0 : 1;
if (offsetY + (uint32_t)blockHeight > imageHeight) blockHeight = imageHeight - offsetY;
if (offsetX + (uint32_t)blockWidth > imageWidth ) blockWidth = imageWidth - offsetX;
const int hAct = offsetY + (uint32_t)blockHeight < imageHeight ? blockHeight : blockHeight - 1;
const int wAct = offsetX + (uint32_t)blockWidth < imageWidth ? blockWidth : blockWidth - 1;
uint64_t ssErr = 0; // sum of squared diffs
uint64_t saAct = 0; // sum of abs. activity

Karsten Suehring
committed
double msAct;
int x, y;
// calculate image differences and activity
for (y = 0; y < blockHeight; y++) // error
{
for (x = 0; x < blockWidth; x++)
{
const int64_t iDiff = (int64_t)o[y*O + x] - (int64_t)r[y*R + x];

Karsten Suehring
committed
ssErr += uint64_t(iDiff * iDiff);
}
}
if (wAct <= xAct || hAct <= yAct) return (double)ssErr;
for (y = yAct; y < hAct; y++) // activity
{
for (x = xAct; x < wAct; x++)
{
const int f = 12 * (int)o[y*O + x] - 2 * ((int)o[y*O + x-1] + (int)o[y*O + x+1] + (int)o[(y-1)*O + x] + (int)o[(y+1)*O + x])
- (int)o[(y-1)*O + x-1] - (int)o[(y-1)*O + x+1] - (int)o[(y+1)*O + x-1] - (int)o[(y+1)*O + x+1];
saAct += abs(f);

Karsten Suehring
committed
}
}
// calculate weight (mean squared activity)
msAct = (double)saAct / (double(wAct - xAct) * double(hAct - yAct));
// lower limit, accounts for high-pass gain
if (msAct < double(1 << (bitDepth - 4))) msAct = double(1 << (bitDepth - 4));

Karsten Suehring
committed
msAct *= msAct; // because ssErr is squared
sumAct += msAct; // includes high-pass gain
// calculate activity weighted error square
return (double)ssErr * pow(msAct, -1.0 * BETA);
}
#endif // ENABLE_QPA
uint64_t EncGOP::xFindDistortionPlane(const CPelBuf& pic0, const CPelBuf& pic1, const uint32_t rshift
#if ENABLE_QPA
, const uint32_t chromaShift /*= 0*/

Karsten Suehring
committed
#endif

Karsten Suehring
committed
{
uint64_t uiTotalDiff;
const Pel* pSrc0 = pic0.bufAt(0, 0);
const Pel* pSrc1 = pic1.bufAt(0, 0);
CHECK(pic0.width != pic1.width , "Unspecified error");
CHECK(pic0.height != pic1.height, "Unspecified error");
if( rshift > 0 )
{
#if ENABLE_QPA
const uint32_t BD = rshift; // image bit-depth
if (BD >= 8)
{
const uint32_t W = pic0.width; // image width
const uint32_t H = pic0.height; // image height
const double R = double(W * H) / (1920.0 * 1080.0);

Karsten Suehring
committed
const uint32_t B = Clip3<uint32_t>(0, 128 >> chromaShift, 4 * uint32_t(16.0 * sqrt(R) + 0.5)); // WPSNR block size in integer multiple of 4 (for SIMD, = 64 at full-HD)
uint32_t x, y;
if (B < 4) // image is too small to use WPSNR, resort to traditional PSNR
{
uiTotalDiff = 0;
for (y = 0; y < H; y++)
{
for (x = 0; x < W; x++)
{
const int64_t iDiff = (int64_t)pSrc0[x] - (int64_t)pSrc1[x];

Karsten Suehring
committed
uiTotalDiff += uint64_t(iDiff * iDiff);
}
pSrc0 += pic0.stride;
pSrc1 += pic1.stride;
}
return uiTotalDiff;
}
double wmse = 0.0, sumAct = 0.0; // compute activity normalized SNR value

Christian Helmrich
committed

Karsten Suehring
committed
for (y = 0; y < H; y += B)
{
for (x = 0; x < W; x += B)
{
wmse += calcWeightedSquaredError(pic1, pic0,
sumAct, BD,
W, H,
x, y,
B, B);

Karsten Suehring
committed
}
}
// integer weighted distortion

Christian Helmrich
committed
sumAct = 16.0 * sqrt ((3840.0 * 2160.0) / double((W << chromaShift) * (H << chromaShift))) * double(1 << BD);

Karsten Suehring
committed
3449
3450
3451
3452
3453
3454
3455
3456
3457
3458
3459
3460
3461
3462
3463
3464
3465
3466
3467
3468
3469
3470
3471
3472
3473
3474
3475
3476
3477
3478
3479
3480
3481
return (wmse <= 0.0) ? 0 : uint64_t(wmse * pow(sumAct, BETA) + 0.5);
}
#endif // ENABLE_QPA
uiTotalDiff = 0;
for (int y = 0; y < pic0.height; y++)
{
for (int x = 0; x < pic0.width; x++)
{
Intermediate_Int iTemp = pSrc0[x] - pSrc1[x];
uiTotalDiff += uint64_t((iTemp * iTemp) >> rshift);
}
pSrc0 += pic0.stride;
pSrc1 += pic1.stride;
}
}
else
{
uiTotalDiff = 0;
for (int y = 0; y < pic0.height; y++)
{
for (int x = 0; x < pic0.width; x++)
{
Intermediate_Int iTemp = pSrc0[x] - pSrc1[x];
uiTotalDiff += uint64_t(iTemp * iTemp);
}
pSrc0 += pic0.stride;
pSrc1 += pic1.stride;
}
}
return uiTotalDiff;
}
#if WCG_WPSNR
double EncGOP::xFindDistortionPlaneWPSNR(const CPelBuf& pic0, const CPelBuf& pic1, const uint32_t rshift, const CPelBuf& picLuma0,

Karsten Suehring
committed
ComponentID compID, const ChromaFormat chfmt )
{
const bool useLumaWPSNR = m_pcEncLib->getLumaLevelToDeltaQPMapping().isEnabled() || (m_pcCfg->getReshaper() && m_pcCfg->getReshapeSignalType() == RESHAPE_SIGNAL_PQ);

Karsten Suehring
committed
3486
3487
3488
3489
3490
3491
3492
3493
3494
3495
3496
3497
3498
3499
3500
3501
3502
3503
3504
3505
3506
3507
3508
3509
3510
3511
3512
3513
3514
3515
3516
3517
3518
3519
3520
3521
3522
3523
3524
3525
3526
3527
3528
3529
3530
3531
3532
3533
3534
if (!useLumaWPSNR)
{
return 0;
}
double uiTotalDiffWPSNR;
const Pel* pSrc0 = pic0.bufAt(0, 0);
const Pel* pSrc1 = pic1.bufAt(0, 0);
const Pel* pSrcLuma = picLuma0.bufAt(0, 0);
CHECK(pic0.width != pic1.width , "Unspecified error");
CHECK(pic0.height != pic1.height, "Unspecified error");
if( rshift > 0 )
{
uiTotalDiffWPSNR = 0;
for (int y = 0; y < pic0.height; y++)
{
for (int x = 0; x < pic0.width; x++)
{
Intermediate_Int iTemp = pSrc0[x] - pSrc1[x];
double dW = m_pcEncLib->getRdCost()->getWPSNRLumaLevelWeight(pSrcLuma[(x << getComponentScaleX(compID, chfmt))]);
uiTotalDiffWPSNR += ((dW * (double)iTemp * (double)iTemp)) * (double)(1 >> rshift);
}
pSrc0 += pic0.stride;
pSrc1 += pic1.stride;
pSrcLuma += picLuma0.stride << getComponentScaleY(compID, chfmt);
}
}
else
{
uiTotalDiffWPSNR = 0;
for (int y = 0; y < pic0.height; y++)
{
for (int x = 0; x < pic0.width; x++)
{
Intermediate_Int iTemp = pSrc0[x] - pSrc1[x];
double dW = m_pcEncLib->getRdCost()->getWPSNRLumaLevelWeight(pSrcLuma[x << getComponentScaleX(compID, chfmt)]);
uiTotalDiffWPSNR += dW * (double)iTemp * (double)iTemp;
}
pSrc0 += pic0.stride;
pSrc1 += pic1.stride;
pSrcLuma += picLuma0.stride << getComponentScaleY(compID, chfmt);
}
}
return uiTotalDiffWPSNR;
}
#endif
void EncGOP::xCalculateAddPSNRs( const bool isField, const bool isFieldTopFieldFirst, const int iGOPid, Picture* pcPic, const AccessUnit&accessUnit, PicList &rcListPic, const int64_t dEncTime, const InputColourSpaceConversion snr_conversion, const bool printFrameMSE, double* PSNR_Y
, bool isEncodeLtRef
)

Karsten Suehring
committed
{
xCalculateAddPSNR(pcPic, pcPic->getRecoBuf(), accessUnit, (double)dEncTime, snr_conversion, printFrameMSE, PSNR_Y
, isEncodeLtRef
);

Karsten Suehring
committed
3542
3543
3544
3545
3546
3547
3548
3549
3550
3551
3552
3553
3554
3555
3556
3557
3558
3559
3560
3561
3562
3563
3564
3565
3566
3567
3568
3569
3570
3571
3572
3573
3574
3575
3576
3577
3578
3579
3580
3581
3582
3583
3584
3585
3586
3587
3588
3589
3590
3591
3592
3593
//In case of field coding, compute the interlaced PSNR for both fields
if(isField)
{
bool bothFieldsAreEncoded = false;
int correspondingFieldPOC = pcPic->getPOC();
int currentPicGOPPoc = m_pcCfg->getGOPEntry(iGOPid).m_POC;
if(pcPic->getPOC() == 0)
{
// particular case for POC 0 and 1.
// If they are not encoded first and separately from other pictures, we need to change this
// POC 0 is always encoded first then POC 1 is encoded
bothFieldsAreEncoded = false;
}
else if(pcPic->getPOC() == 1)
{
// if we are at POC 1, POC 0 has been encoded for sure
correspondingFieldPOC = 0;
bothFieldsAreEncoded = true;
}
else
{
if(pcPic->getPOC()%2 == 1)
{
correspondingFieldPOC -= 1; // all odd POC are associated with the preceding even POC (e.g poc 1 is associated to poc 0)
currentPicGOPPoc -= 1;
}
else
{
correspondingFieldPOC += 1; // all even POC are associated with the following odd POC (e.g poc 0 is associated to poc 1)
currentPicGOPPoc += 1;
}
for(int i = 0; i < m_iGopSize; i ++)
{
if(m_pcCfg->getGOPEntry(i).m_POC == currentPicGOPPoc)
{
bothFieldsAreEncoded = m_pcCfg->getGOPEntry(i).m_isEncoded;
break;
}
}
}
if(bothFieldsAreEncoded)
{
//get complementary top field
PicList::iterator iterPic = rcListPic.begin();
while ((*iterPic)->getPOC() != correspondingFieldPOC)
{
iterPic ++;
}
Picture* correspondingFieldPic = *(iterPic);
if ((pcPic->topField && isFieldTopFieldFirst) || (!pcPic->topField && !isFieldTopFieldFirst))

Karsten Suehring
committed
{
xCalculateInterlacedAddPSNR(pcPic, correspondingFieldPic, pcPic->getRecoBuf(), correspondingFieldPic->getRecoBuf(), snr_conversion, printFrameMSE, PSNR_Y
, isEncodeLtRef
);

Karsten Suehring
committed
}
else
{
xCalculateInterlacedAddPSNR(correspondingFieldPic, pcPic, correspondingFieldPic->getRecoBuf(), pcPic->getRecoBuf(), snr_conversion, printFrameMSE, PSNR_Y
, isEncodeLtRef
);

Karsten Suehring
committed
}
}
}
}
void EncGOP::xCalculateAddPSNR(Picture* pcPic, PelUnitBuf cPicD, const AccessUnit& accessUnit, double dEncTime, const InputColourSpaceConversion conversion, const bool printFrameMSE, double* PSNR_Y
, bool isEncodeLtRef
)

Karsten Suehring
committed
{
const SPS& sps = *pcPic->cs->sps;
const CPelUnitBuf& pic = cPicD;
CHECK(!(conversion == IPCOLOURSPACE_UNCHANGED), "Unspecified error");
// const CPelUnitBuf& org = (conversion != IPCOLOURSPACE_UNCHANGED) ? pcPic->getPicYuvTrueOrg()->getBuf() : pcPic->getPicYuvOrg()->getBuf();
const CPelUnitBuf& org = sps.getUseReshaper() ? pcPic->getTrueOrigBuf() : pcPic->getOrigBuf();

Karsten Suehring
committed
#if ENABLE_QPA
const bool useWPSNR = m_pcEncLib->getUseWPSNR();
#endif
double dPSNR[MAX_NUM_COMPONENT];
#if WCG_WPSNR
const bool useLumaWPSNR = m_pcEncLib->getLumaLevelToDeltaQPMapping().isEnabled() || (m_pcCfg->getReshaper() && m_pcCfg->getReshapeSignalType() == RESHAPE_SIGNAL_PQ);

Karsten Suehring
committed
double dPSNRWeighted[MAX_NUM_COMPONENT];
double MSEyuvframeWeighted[MAX_NUM_COMPONENT];
#endif
#if RPR_CTC_PRINT
double upscaledPSNR[MAX_NUM_COMPONENT];

Karsten Suehring
committed
#endif
for(int i=0; i<MAX_NUM_COMPONENT; i++)
{
dPSNR[i]=0.0;
#if WCG_WPSNR
dPSNRWeighted[i]=0.0;
MSEyuvframeWeighted[i] = 0.0;
#endif
#if RPR_CTC_PRINT
upscaledPSNR[i] = 0.0;

Karsten Suehring
committed
#endif
}
#if JVET_O0756_CALCULATE_HDRMETRICS
double deltaE[hdrtoolslib::NB_REF_WHITE];
double psnrL[hdrtoolslib::NB_REF_WHITE];
for (int i=0; i<hdrtoolslib::NB_REF_WHITE; i++)
{
deltaE[i] = 0.0;
psnrL[i] = 0.0;

Karsten Suehring
committed
PelStorage interm;
if (conversion != IPCOLOURSPACE_UNCHANGED)
{
interm.create(pic.chromaFormat, Area(Position(), pic.Y()));
VideoIOYuv::ColourSpaceConvert(pic, interm, conversion, false);
}
const CPelUnitBuf& picC = (conversion == IPCOLOURSPACE_UNCHANGED) ? pic : interm;
//===== calculate PSNR =====
double MSEyuvframe[MAX_NUM_COMPONENT] = {0, 0, 0};
const ChromaFormat formatD = pic.chromaFormat;
const ChromaFormat format = sps.getChromaFormatIdc();
const bool bPicIsField = pcPic->fieldPic;
const Slice* pcSlice = pcPic->slices[0];
#if RPR_CTC_PRINT
PelStorage upscaledRec;
if( m_pcEncLib->isRPREnabled() )
{
const CPelBuf& upscaledOrg = sps.getUseReshaper() ? pcPic->M_BUFS( 0, PIC_TRUE_ORIGINAL_INPUT).get( COMPONENT_Y ) : pcPic->M_BUFS( 0, PIC_ORIGINAL_INPUT).get( COMPONENT_Y );
upscaledRec.create( pic.chromaFormat, Area( Position(), upscaledOrg ) );
// the input source picture has a conformance window derived at encoder
Window& conformanceWindow = m_pcEncLib->getConformanceWindow();
Picture::rescalePicture( picC, pcPic->cs->pps->getConformanceWindow(), upscaledRec, conformanceWindow, format, sps.getBitDepths(), false );
#else
Picture::rescalePicture(picC, upscaledRec, format, sps.getBitDepths(), false);
#endif
}
#endif

Karsten Suehring
committed
3687
3688
3689
3690
3691
3692
3693
3694
3695
3696
3697
3698
3699
3700
3701
3702
3703
3704
3705
3706
3707
for (int comp = 0; comp < ::getNumberValidComponents(formatD); comp++)
{
const ComponentID compID = ComponentID(comp);
const CPelBuf& p = picC.get(compID);
const CPelBuf& o = org.get(compID);
CHECK(!( p.width == o.width), "Unspecified error");
CHECK(!( p.height == o.height), "Unspecified error");
const uint32_t width = p.width - (m_pcEncLib->getPad(0) >> ::getComponentScaleX(compID, format));
const uint32_t height = p.height - (m_pcEncLib->getPad(1) >> (!!bPicIsField+::getComponentScaleY(compID,format)));
// create new buffers with correct dimensions
const CPelBuf recPB(p.bufAt(0, 0), p.stride, width, height);
const CPelBuf orgPB(o.bufAt(0, 0), o.stride, width, height);
const uint32_t bitDepth = sps.getBitDepth(toChannelType(compID));
#if ENABLE_QPA
const uint64_t uiSSDtemp = xFindDistortionPlane(recPB, orgPB, useWPSNR ? bitDepth : 0, ::getComponentScaleX(compID, format));
#else
const uint64_t uiSSDtemp = xFindDistortionPlane(recPB, orgPB, 0);
#endif

Christian Helmrich
committed
const uint32_t maxval = 255 << (bitDepth - 8);

Karsten Suehring
committed
const uint32_t size = width * height;
const double fRefValue = (double)maxval * maxval * size;
dPSNR[comp] = uiSSDtemp ? 10.0 * log10(fRefValue / (double)uiSSDtemp) : 999.99;
MSEyuvframe[comp] = (double)uiSSDtemp / size;
#if WCG_WPSNR
const double uiSSDtempWeighted = xFindDistortionPlaneWPSNR(recPB, orgPB, 0, org.get(COMPONENT_Y), compID, format);

Karsten Suehring
committed
if (useLumaWPSNR)
{
dPSNRWeighted[comp] = uiSSDtempWeighted ? 10.0 * log10(fRefValue / (double)uiSSDtempWeighted) : 999.99;
MSEyuvframeWeighted[comp] = (double)uiSSDtempWeighted / size;
}
#endif
#if RPR_CTC_PRINT
if( m_pcEncLib->isRPREnabled() )
{
const CPelBuf& upscaledOrg = sps.getUseReshaper() ? pcPic->M_BUFS( 0, PIC_TRUE_ORIGINAL_INPUT ).get( compID ) : pcPic->M_BUFS( 0, PIC_ORIGINAL_INPUT ).get( compID );
#if ENABLE_QPA
const uint64_t upscaledSSD = xFindDistortionPlane( upscaledRec.get( compID ), upscaledOrg, useWPSNR ? bitDepth : 0, ::getComponentScaleX( compID, format ) );
#else
const uint64_t scaledSSD = xFindDistortionPlane( upscaledRec.get( compID ), upscaledOrg, 0 );
#endif
upscaledPSNR[comp] = upscaledSSD ? 10.0 * log10( (double)maxval * maxval * upscaledOrg.width * upscaledOrg.height / (double)upscaledSSD ) : 999.99;
}
#endif

Karsten Suehring
committed
}
#if EXTENSION_360_VIDEO
m_ext360.calculatePSNRs(pcPic);
#endif
#if JVET_O0756_CALCULATE_HDRMETRICS
const bool calculateHdrMetrics = m_pcEncLib->getCalcluateHdrMetrics();
if (calculateHdrMetrics)
{
auto beforeTime = std::chrono::steady_clock::now();
xCalculateHDRMetrics(pcPic, deltaE, psnrL);
auto elapsed = std::chrono::steady_clock::now() - beforeTime;
m_metricTime += elapsed;
}
#endif

Karsten Suehring
committed
/* calculate the size of the access unit, excluding:
* - any AnnexB contributions (start_code_prefix, zero_byte, etc.,)
* - SEI NAL units
*/
uint32_t numRBSPBytes = 0;
for (AccessUnit::const_iterator it = accessUnit.begin(); it != accessUnit.end(); it++)
{
uint32_t numRBSPBytes_nal = uint32_t((*it)->m_nalUnitData.str().size());
if (m_pcCfg->getSummaryVerboseness() > 0)
{
msg( NOTICE, "*** %6s numBytesInNALunit: %u\n", nalUnitTypeToString((*it)->m_nalUnitType), numRBSPBytes_nal);
}
if( ( *it )->m_nalUnitType != NAL_UNIT_PREFIX_SEI && ( *it )->m_nalUnitType != NAL_UNIT_SUFFIX_SEI )
{
numRBSPBytes += numRBSPBytes_nal;
if (it == accessUnit.begin() || (*it)->m_nalUnitType == NAL_UNIT_VPS || (*it)->m_nalUnitType == NAL_UNIT_DPS || (*it)->m_nalUnitType == NAL_UNIT_SPS || (*it)->m_nalUnitType == NAL_UNIT_PPS)

Karsten Suehring
committed
{
numRBSPBytes += 4;
}
else
{
numRBSPBytes += 3;
}
}
}
uint32_t uibits = numRBSPBytes * 8;
m_vRVM_RP.push_back( uibits );
//===== add PSNR =====
m_gcAnalyzeAll.addResult(dPSNR, (double)uibits, MSEyuvframe
#if RPR_CTC_PRINT
, upscaledPSNR
#endif
, isEncodeLtRef
);

Karsten Suehring
committed
#if EXTENSION_360_VIDEO
m_ext360.addResult(m_gcAnalyzeAll);
#endif
#if JVET_O0756_CALCULATE_HDRMETRICS
if (calculateHdrMetrics)
{
m_gcAnalyzeAll.addHDRMetricsResult(deltaE, psnrL);

Karsten Suehring
committed
#endif
if (pcSlice->isIntra())
{
m_gcAnalyzeI.addResult(dPSNR, (double)uibits, MSEyuvframe
#if RPR_CTC_PRINT
, upscaledPSNR
#endif
, isEncodeLtRef
);

Karsten Suehring
committed
*PSNR_Y = dPSNR[COMPONENT_Y];
#if EXTENSION_360_VIDEO
m_ext360.addResult(m_gcAnalyzeI);
#endif
#if JVET_O0756_CALCULATE_HDRMETRICS
if (calculateHdrMetrics)
{
m_gcAnalyzeI.addHDRMetricsResult(deltaE, psnrL);

Karsten Suehring
committed
#endif
}
if (pcSlice->isInterP())
{
m_gcAnalyzeP.addResult(dPSNR, (double)uibits, MSEyuvframe
#if RPR_CTC_PRINT
, upscaledPSNR
#endif
, isEncodeLtRef
);

Karsten Suehring
committed
*PSNR_Y = dPSNR[COMPONENT_Y];
#if EXTENSION_360_VIDEO
m_ext360.addResult(m_gcAnalyzeP);
#endif
#if JVET_O0756_CALCULATE_HDRMETRICS
if (calculateHdrMetrics)
{
m_gcAnalyzeP.addHDRMetricsResult(deltaE, psnrL);

Karsten Suehring
committed
#endif
}
if (pcSlice->isInterB())
{
m_gcAnalyzeB.addResult(dPSNR, (double)uibits, MSEyuvframe
#if RPR_CTC_PRINT
, upscaledPSNR
#endif
, isEncodeLtRef
);

Karsten Suehring
committed
*PSNR_Y = dPSNR[COMPONENT_Y];
#if EXTENSION_360_VIDEO
m_ext360.addResult(m_gcAnalyzeB);
#endif
#if JVET_O0756_CALCULATE_HDRMETRICS
if (calculateHdrMetrics)
{
m_gcAnalyzeB.addHDRMetricsResult(deltaE, psnrL);

Karsten Suehring
committed
#endif
}
#if WCG_WPSNR
if (useLumaWPSNR)
{
#if RPR_CTC_PRINT
m_gcAnalyzeWPSNR.addResult( dPSNRWeighted, (double)uibits, MSEyuvframeWeighted, upscaledPSNR, isEncodeLtRef );
#else
m_gcAnalyzeWPSNR.addResult(dPSNRWeighted, (double)uibits, MSEyuvframeWeighted, isEncodeLtRef);
#endif

Karsten Suehring
committed
}
#endif
char c = (pcSlice->isIntra() ? 'I' : pcSlice->isInterP() ? 'P' : 'B');
if (! pcPic->referenced)
{
c += 32;
}
if( g_verbosity >= NOTICE )
{
msg( NOTICE, "POC %4d TId: %1d ( %c-SLICE, QP %d ) %10d bits",

Karsten Suehring
committed
pcSlice->getTLayer(),
c,
pcSlice->getSliceQp(),
uibits );
msg( NOTICE, " [Y %6.4lf dB U %6.4lf dB V %6.4lf dB]", dPSNR[COMPONENT_Y], dPSNR[COMPONENT_Cb], dPSNR[COMPONENT_Cr] );
#if EXTENSION_360_VIDEO
m_ext360.printPerPOCInfo(NOTICE);
#endif

Karsten Suehring
committed
if (m_pcEncLib->getPrintHexPsnr())
{
uint64_t xPsnr[MAX_NUM_COMPONENT];
for (int i = 0; i < MAX_NUM_COMPONENT; i++)
{
copy(reinterpret_cast<uint8_t *>(&dPSNR[i]),
reinterpret_cast<uint8_t *>(&dPSNR[i]) + sizeof(dPSNR[i]),
reinterpret_cast<uint8_t *>(&xPsnr[i]));
}
msg(NOTICE, " [xY %16" PRIx64 " xU %16" PRIx64 " xV %16" PRIx64 "]", xPsnr[COMPONENT_Y], xPsnr[COMPONENT_Cb], xPsnr[COMPONENT_Cr]);
#if EXTENSION_360_VIDEO
m_ext360.printPerPOCInfo(NOTICE, true);

Karsten Suehring
committed
#endif

Karsten Suehring
committed
if( printFrameMSE )
{
msg( NOTICE, " [Y MSE %6.4lf U MSE %6.4lf V MSE %6.4lf]", MSEyuvframe[COMPONENT_Y], MSEyuvframe[COMPONENT_Cb], MSEyuvframe[COMPONENT_Cr] );
}
#if WCG_WPSNR
if (useLumaWPSNR)
{
msg(NOTICE, " [WY %6.4lf dB WU %6.4lf dB WV %6.4lf dB]", dPSNRWeighted[COMPONENT_Y], dPSNRWeighted[COMPONENT_Cb], dPSNRWeighted[COMPONENT_Cr]);
if (m_pcEncLib->getPrintHexPsnr())
{
uint64_t xPsnrWeighted[MAX_NUM_COMPONENT];
for (int i = 0; i < MAX_NUM_COMPONENT; i++)
{
copy(reinterpret_cast<uint8_t *>(&dPSNRWeighted[i]),
reinterpret_cast<uint8_t *>(&dPSNRWeighted[i]) + sizeof(dPSNRWeighted[i]),
reinterpret_cast<uint8_t *>(&xPsnrWeighted[i]));
}
msg(NOTICE, " [xWY %16" PRIx64 " xWU %16" PRIx64 " xWV %16" PRIx64 "]", xPsnrWeighted[COMPONENT_Y], xPsnrWeighted[COMPONENT_Cb], xPsnrWeighted[COMPONENT_Cr]);
}

Karsten Suehring
committed
}
#endif
#if JVET_O0756_CALCULATE_HDRMETRICS
if(calculateHdrMetrics)
{
for (int i=0; i<1; i++)
{
msg(NOTICE, " [DeltaE%d %6.4lf dB]", (int)m_pcCfg->getWhitePointDeltaE(i), deltaE[i]);
if (m_pcEncLib->getPrintHexPsnr())
{
int64_t xdeltaE[MAX_NUM_COMPONENT];
for (int i = 0; i < 1; i++)
{
copy(reinterpret_cast<uint8_t *>(&deltaE[i]),
reinterpret_cast<uint8_t *>(&deltaE[i]) + sizeof(deltaE[i]),
reinterpret_cast<uint8_t *>(&xdeltaE[i]));
}
msg(NOTICE, " [xDeltaE%d %16" PRIx64 "]", (int)m_pcCfg->getWhitePointDeltaE(i), xdeltaE[0]);
}
}
for (int i=0; i<1; i++)
{
msg(NOTICE, " [PSNRL%d %6.4lf dB]", (int)m_pcCfg->getWhitePointDeltaE(i), psnrL[i]);
if (m_pcEncLib->getPrintHexPsnr())
{
int64_t xpsnrL[MAX_NUM_COMPONENT];
for (int i = 0; i < 1; i++)
{
copy(reinterpret_cast<uint8_t *>(&psnrL[i]),
reinterpret_cast<uint8_t *>(&psnrL[i]) + sizeof(psnrL[i]),
reinterpret_cast<uint8_t *>(&xpsnrL[i]));
}
msg(NOTICE, " [xPSNRL%d %16" PRIx64 "]", (int)m_pcCfg->getWhitePointDeltaE(i), xpsnrL[0]);
}

Karsten Suehring
committed
#endif
msg( NOTICE, " [ET %5.0f ]", dEncTime );
// msg( SOME, " [WP %d]", pcSlice->getUseWeightedPrediction());
for( int iRefList = 0; iRefList < 2; iRefList++ )
{
msg( NOTICE, " [L%d ", iRefList );
for( int iRefIndex = 0; iRefIndex < pcSlice->getNumRefIdx( RefPicList( iRefList ) ); iRefIndex++ )
{
#if RPR_CTC_PRINT
if( m_pcEncLib->isRPREnabled() )
{
const std::pair<int, int>& scaleRatio = pcSlice->getScalingRatio( RefPicList( iRefList ), iRefIndex );
if( pcSlice->getEnableTMVPFlag() && pcSlice->getColFromL0Flag() == bool( 1 - iRefList ) && pcSlice->getColRefIdx() == iRefIndex )
{
msg( NOTICE, "%dc(%1.2lfx, %1.2lfx) ", pcSlice->getRefPOC( RefPicList( iRefList ), iRefIndex ), double( scaleRatio.first ) / ( 1 << SCALE_RATIO_BITS ), double( scaleRatio.second ) / ( 1 << SCALE_RATIO_BITS ) );
}
else
{
msg( NOTICE, "%d(%1.2lfx, %1.2lfx) ", pcSlice->getRefPOC( RefPicList( iRefList ), iRefIndex ), double( scaleRatio.first ) / ( 1 << SCALE_RATIO_BITS ), double( scaleRatio.second ) / ( 1 << SCALE_RATIO_BITS ) );
}
}
else
#endif
msg( NOTICE, "%d ", pcSlice->getRefPOC( RefPicList( iRefList ), iRefIndex ) );

Karsten Suehring
committed
}
msg( NOTICE, "]" );
}
#if RPR_CTC_PRINT
if( m_pcEncLib->isRPREnabled() )
{
msg( NOTICE, "\nPSNR2: [Y %6.4lf dB U %6.4lf dB V %6.4lf dB]", upscaledPSNR[COMPONENT_Y], upscaledPSNR[COMPONENT_Cb], upscaledPSNR[COMPONENT_Cr] );
}
#endif

Karsten Suehring
committed
}
else if( g_verbosity >= INFO )
{
std::cout << "\r\t" << pcSlice->getPOC();