Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow calculating PSNR for Y/U/V components #3824

Merged
merged 2 commits into from
Jan 6, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions codec/api/wels/codec_app_def.h
Original file line number Diff line number Diff line change
Expand Up @@ -592,6 +592,9 @@ typedef struct TagEncParamExt {
bool bIsLosslessLink; ///< LTR advanced setting
bool bFixRCOverShoot; ///< fix rate control overshooting
int iIdrBitrateRatio; ///< the target bits of IDR is (idr_bitrate_ratio/100) * average target bit per frame.
bool bPsnrY; ///< get Y PSNR stats for the whole video sequence
bool bPsnrU; ///< get U PSNR stats for the whole video sequence
bool bPsnrV; ///< get V PSNR stats for the whole video sequence
} SEncParamExt;

/**
Expand Down Expand Up @@ -635,6 +638,7 @@ typedef struct {
int iNalCount; ///< count number of NAL coded already
int* pNalLengthInByte; ///< length of NAL size in byte from 0 to iNalCount-1
unsigned char* pBsBuf; ///< buffer of bitstream contained
float rPsnr[3]; ///< PSNR values for Y/U/V
} SLayerBSInfo, *PLayerBSInfo;

/**
Expand All @@ -659,7 +663,11 @@ typedef struct Source_Picture_s {
int iPicWidth; ///< luma picture width in x coordinate
int iPicHeight; ///< luma picture height in y coordinate
long long uiTimeStamp; ///< timestamp of the source picture, unit: millisecond
bool bPsnrY; ///< get Y PSNR for this frame
bool bPsnrU; ///< get U PSNR for this frame
bool bPsnrV; ///< get V PSNR for this frame
} SSourcePicture;

/**
* @brief Structure for bit rate info
*/
Expand Down
5 changes: 0 additions & 5 deletions codec/encoder/core/inc/as264_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,6 @@
#endif//ENABLE_FRAME_DUMP
#endif//__UNITTEST__

//#define ENABLE_PSNR_CALC
//#define STAT_OUTPUT
//#define MB_TYPES_CHECK
//
Expand All @@ -88,10 +87,6 @@
//@if !FRAME_INFO_OUTPUT
#if !defined(FRAME_INFO_OUTPUT)

#if defined(ENABLE_PSNR_CALC)
#undef ENABLE_PSNR_CALC
#endif//ENABLE_PSNR_CALC

//#if defined(STAT_OUTPUT)
//#undef STAT_OUTPUT
//#endif//STAT_OUTPUT
Expand Down
6 changes: 6 additions & 0 deletions codec/encoder/core/inc/param_svc.h
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,9 @@ typedef struct TagWelsSvcCodingParam: SEncParamExt {
param.bIsLosslessLink = false;
param.bFixRCOverShoot = true;
param.iIdrBitrateRatio = IDR_BITRATE_RATIO * 100;
param.bPsnrY = false;
param.bPsnrU = false;
param.bPsnrV = false;
for (int32_t iLayer = 0; iLayer < MAX_SPATIAL_LAYER_NUM; iLayer++) {
param.sSpatialLayers[iLayer].uiProfileIdc = PRO_UNKNOWN;
param.sSpatialLayers[iLayer].uiLevelIdc = LEVEL_UNKNOWN;
Expand Down Expand Up @@ -345,6 +348,9 @@ typedef struct TagWelsSvcCodingParam: SEncParamExt {
bIsLosslessLink = pCodingParam.bIsLosslessLink;
bFixRCOverShoot = pCodingParam.bFixRCOverShoot;
iIdrBitrateRatio = pCodingParam.iIdrBitrateRatio;
bPsnrY = pCodingParam.bPsnrY;
bPsnrU = pCodingParam.bPsnrU;
bPsnrV = pCodingParam.bPsnrV;
if (iUsageType == SCREEN_CONTENT_REAL_TIME && !bIsLosslessLink && bEnableLongTermReference) {
bEnableLongTermReference = false;
}
Expand Down
79 changes: 47 additions & 32 deletions codec/encoder/core/src/encoder_ext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2186,7 +2186,7 @@ void StatOverallEncodingExt (sWelsEncCtx* pCtx) {

}
}
#endif
#endif //#if defined(STAT_OUTPUT)


int32_t GetMultipleThreadIdc (SLogContext* pLogCtx, SWelsSvcCodingParam* pCodingParam, int16_t& iSliceNum,
Expand Down Expand Up @@ -3445,9 +3445,7 @@ int32_t WelsEncoderEncodeExt (sWelsEncCtx* pCtx, SFrameBSInfo* pFbi, const SSour
SLayerBSInfo* pLayerBsInfo = &pFbi->sLayerInfo[0];
SWelsSvcCodingParam* pSvcParam = pCtx->pSvcParam;
SSpatialPicIndex* pSpatialIndexMap = &pCtx->sSpatialIndexMap[0];
#if defined(ENABLE_FRAME_DUMP) || defined(ENABLE_PSNR_CALC)
SPicture* fsnr = NULL;
#endif//ENABLE_FRAME_DUMP || ENABLE_PSNR_CALC
SPicture* pEncPic = NULL; // to be decided later
#if defined(MT_DEBUG)
int32_t iDidList[MAX_DEPENDENCY_LAYER] = {0};
Expand All @@ -3469,9 +3467,7 @@ int32_t WelsEncoderEncodeExt (sWelsEncCtx* pCtx, SFrameBSInfo* pFbi, const SSour
int32_t iCurTid = 0;
bool bAvcBased = false;
SLogContext* pLogCtx = & (pCtx->sLogCtx);
#if defined(ENABLE_PSNR_CALC)
float fSnrY = .0f, fSnrU = .0f, fSnrV = .0f;
#endif//ENABLE_PSNR_CALC

#if defined(_DEBUG)
int32_t i = 0, j = 0, k = 0;
Expand Down Expand Up @@ -3624,9 +3620,7 @@ int32_t WelsEncoderEncodeExt (sWelsEncCtx* pCtx, SFrameBSInfo* pFbi, const SSour
pCtx->eNalPriority = eNalRefIdc;

pCtx->pDecPic = pCtx->ppRefPicListExt[iCurDid]->pNextBuffer;
#if defined(ENABLE_FRAME_DUMP) || defined(ENABLE_PSNR_CALC)
fsnr = pCtx->pDecPic;
#endif//#if defined(ENABLE_FRAME_DUMP) || defined(ENABLE_PSNR_CALC)
pCtx->pDecPic->iPictureType = pCtx->eSliceType;
pCtx->pDecPic->iFramePoc = pParamInternal->iPOC;

Expand Down Expand Up @@ -3921,26 +3915,30 @@ int32_t WelsEncoderEncodeExt (sWelsEncCtx* pCtx, SFrameBSInfo* pFbi, const SSour
}
#endif//ENABLE_FRAME_DUMP

#if defined(ENABLE_PSNR_CALC)
fSnrY = WelsCalcPsnr (fsnr->pData[0],
fsnr->iLineSize[0],
pEncPic->pData[0],
pEncPic->iLineSize[0],
iCurWidth,
iCurHeight);
fSnrU = WelsCalcPsnr (fsnr->pData[1],
fsnr->iLineSize[1],
pEncPic->pData[1],
pEncPic->iLineSize[1],
(iCurWidth >> 1),
(iCurHeight >> 1));
fSnrV = WelsCalcPsnr (fsnr->pData[2],
fsnr->iLineSize[2],
pEncPic->pData[2],
pEncPic->iLineSize[2],
(iCurWidth >> 1),
(iCurHeight >> 1));
#endif//ENABLE_PSNR_CALC
if (fsnr && (pSvcParam->bPsnrY || pSrcPic->bPsnrY)) {
fSnrY = WelsCalcPsnr (fsnr->pData[0],
fsnr->iLineSize[0],
pEncPic->pData[0],
pEncPic->iLineSize[0],
iCurWidth,
iCurHeight);
}
if (fsnr && (pSvcParam->bPsnrU || pSrcPic->bPsnrU)) {
fSnrU = WelsCalcPsnr (fsnr->pData[1],
fsnr->iLineSize[1],
pEncPic->pData[1],
pEncPic->iLineSize[1],
(iCurWidth >> 1),
(iCurHeight >> 1));
}
if (fsnr && (pSvcParam->bPsnrV || pSrcPic->bPsnrV)) {
fSnrV = WelsCalcPsnr (fsnr->pData[2],
fsnr->iLineSize[2],
pEncPic->pData[2],
pEncPic->iLineSize[2],
(iCurWidth >> 1),
(iCurHeight >> 1));
}

#if defined(LAYER_INFO_OUTPUT)
fprintf (stderr, "%2s %5d: %-5d %2s T%1d D%1d Q%-2d QP%3d Y%2.2f U%2.2f V%2.2f %8d bits\n",
Expand All @@ -3958,15 +3956,32 @@ int32_t WelsEncoderEncodeExt (sWelsEncCtx* pCtx, SFrameBSInfo* pFbi, const SSour
(iLayerSize << 3));
#endif//LAYER_INFO_OUTPUT

pLayerBsInfo->rPsnr[0] = NAN;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change broke compiling with MSVC 2010 and 2012; they lack the NAN constant in math.h.

Not sure if MSVC 2012 really is within the scope of targets we need to support - but it did compile fine before this.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or put another way - does this strictly need to be NAN, or could we initialize it to some other trivial value, like 0 or -1 or something like that?

Copy link
Collaborator

@BenzhengZhang BenzhengZhang Jan 15, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @fippo,
As @mstorsjo mentioned, this patch broke the build for older versions of MSVC. Could you look into making it compatible with those versions?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think setting it to 0.0 should work, will do a PR

pLayerBsInfo->rPsnr[1] = NAN;
pLayerBsInfo->rPsnr[2] = NAN;
if (pSrcPic->bPsnrY) {
pLayerBsInfo->rPsnr[0] = fSnrY;
}
if (pSrcPic->bPsnrU) {
pLayerBsInfo->rPsnr[1] = fSnrU;
}
if (pSrcPic->bPsnrV) {
pLayerBsInfo->rPsnr[2] = fSnrV;
}

#if defined(STAT_OUTPUT)

#if defined(ENABLE_PSNR_CALC)
{
pCtx->sStatData[iCurDid][0].sQualityStat.rYPsnr[pCtx->eSliceType] += fSnrY;
pCtx->sStatData[iCurDid][0].sQualityStat.rUPsnr[pCtx->eSliceType] += fSnrU;
pCtx->sStatData[iCurDid][0].sQualityStat.rVPsnr[pCtx->eSliceType] += fSnrV;
if (pSvcParam->bPsnrY) {
pCtx->sStatData[iCurDid][0].sQualityStat.rYPsnr[pCtx->eSliceType] += fSnrY;
}
if (pSvcParam->bPsnrU) {
pCtx->sStatData[iCurDid][0].sQualityStat.rUPsnr[pCtx->eSliceType] += fSnrU;
}
if (pSvcParam->bPsnrV) {
pCtx->sStatData[iCurDid][0].sQualityStat.rVPsnr[pCtx->eSliceType] += fSnrV;
}
}
#endif//ENABLE_PSNR_CALC

#if defined(MB_TYPES_CHECK) //091025, frame output
if (pCtx->eSliceType == P_SLICE) {
Expand Down
Loading