ref: c6e7814b57657d79607129b7c5711bd7d7820a12
parent: 51b2ff84fc7845e211d76561453637694b91e93c
author: lyao2 <[email protected]>
date: Fri Jun 6 09:51:32 EDT 2014
add pskip MD functions
--- a/codec/encoder/core/inc/svc_base_layer_md.h
+++ b/codec/encoder/core/inc/svc_base_layer_md.h
@@ -104,7 +104,7 @@
//typedef void (*MD_INTRA_MB_BASE) (sWelsEncCtx* pEncCtx, SWelsMD* pWelsMd, SMB* pCurMb);
-void WelsInitScrollingSkipFunc (SWelsFuncPtrList* pFuncList, const bool bScrollingDetection);
+void WelsInitSCDPskipFunc (SWelsFuncPtrList* pFuncList, const bool bScrollingDetection);
}
#endif//WELS_MACROBLOCK_MODE_DECISION_H__
--- a/codec/encoder/core/inc/svc_enc_frame.h
+++ b/codec/encoder/core/inc/svc_enc_frame.h
@@ -103,6 +103,7 @@
SPicture* pRefPic; // reference picture pointer
SPicture* pDecPic; // reconstruction picture pointer for layer
+ SPicture* pRefOri;
SSliceCtx* pSliceEncCtx; // current slice context
--- a/codec/encoder/core/inc/svc_mode_decision.h
+++ b/codec/encoder/core/inc/svc_mode_decision.h
@@ -41,6 +41,8 @@
#ifndef SVC_MODE_DECISION_H
#define SVC_MODE_DECISION_H
#include "encoder_context.h"
+#include "svc_encode_mb.h"
+#include "svc_encode_slice.h"
#include "svc_enc_macroblock.h"
#include "md.h"
@@ -49,14 +51,23 @@
////////////////////////
// INTERFACE, called by svc_encode_slice.c
///////////////////////
+#define DELTA_QP_SCD_THD 5
+typedef enum {
+ STATIC,
+ SCROLLED,
+} ESkipModes;
+
// NOILP ILFMD ENTRANCE
void WelsMdSpatialelInterMbIlfmdNoilp (sWelsEncCtx* pEncCtx, SWelsMD* pWelsMd, SSlice* pSlice, SMB* pCurMb,
const Mb_Type kuiRefMbType);
void WelsMdInterMbEnhancelayer (void* pEnc, void* pMd, SSlice* pSlice, SMB* pCurMb, SMbCache* pMbCache);
-
SMB* GetRefMb (SDqLayer* pCurLayer, SMB* pCurMb);
void SetMvBaseEnhancelayer (SWelsMD* pMd, SMB* pCurMb, const SMB* kpRefMb);
+bool MdInterSCDPskipProcess (sWelsEncCtx* pEncCtx, SWelsMD* pMd, SSlice* pSlice, SMB* pCurMb, SMbCache* pMbCache,
+ ESkipModes eSkipMode);
+
+typedef bool (*pJudgeSkipFun) (sWelsEncCtx* pEncCtx, SMB* pCurMb, SMbCache* pMbCache, SWelsMD* pWelsMd);
void SetBlockStaticIdcToMd (void* pVaa, void* pMd, SMB* pCurMb, void* pDqLay);
}
#endif //SVC_MODE_DECISION_H
--- a/codec/encoder/core/inc/wels_func_ptr_def.h
+++ b/codec/encoder/core/inc/wels_func_ptr_def.h
@@ -207,7 +207,7 @@
PInterMdBackgroundDecisionFunc pfInterMdBackgroundDecision;
PInterMdBackgroundInfoUpdateFunc pfInterMdBackgroundInfoUpdate;
- PInterMdScrollingPSkipDecisionFunc pfScrollingPSkipDecision;
+ PInterMdScrollingPSkipDecisionFunc pfSCDPSkipDecision;
SMcFunc sMcFuncs;
SSampleDealingFunc sSampleDealingFuncs;
--- a/codec/encoder/core/src/encoder.cpp
+++ b/codec/encoder/core/src/encoder.cpp
@@ -192,7 +192,7 @@
//
WelsInitBGDFunc (pFuncList, pParam->bEnableBackgroundDetection);
- WelsInitScrollingSkipFunc (pFuncList, bScreenContent && (pParam->bEnableSceneChangeDetect));
+ WelsInitSCDPskipFunc (pFuncList, bScreenContent && (pParam->bEnableSceneChangeDetect));
// for pfGetVarianceFromIntraVaa function ptr adaptive by CPU features, 6/7/2010
InitIntraAnalysisVaaInfo (pFuncList, uiCpuFlag);
--- a/codec/encoder/core/src/svc_base_layer_md.cpp
+++ b/codec/encoder/core/src/svc_base_layer_md.cpp
@@ -1647,7 +1647,7 @@
}
//try static or scrolled Pskip
- if (pEncCtx->pFuncList->pfScrollingPSkipDecision (pEncCtx, pWelsMd, pSlice, pCurMb, pMbCache)) {
+ if (pEncCtx->pFuncList->pfSCDPSkipDecision (pEncCtx, pWelsMd, pSlice, pCurMb, pMbCache)) {
return;
}
--- a/codec/encoder/core/src/svc_mode_decision.cpp
+++ b/codec/encoder/core/src/svc_mode_decision.cpp
@@ -40,8 +40,9 @@
**************************************************************************************
*/
+#include "mv_pred.h"
+#include "ls_defines.h"
#include "svc_base_layer_md.h"
-
#include "svc_mode_decision.h"
namespace WelsSVCEnc {
@@ -49,6 +50,36 @@
//
// md in enhancement layer
///
+
+inline bool IsMbStatic (int32_t* pBlockType, EStaticBlockIdc eType) {
+ return (pBlockType != NULL &&
+ eType == pBlockType[0] &&
+ eType == pBlockType[1] &&
+ eType == pBlockType[2] &&
+ eType == pBlockType[3]);
+}
+inline bool IsMbCollocatedStatic (int32_t* pBlockType) {
+ return IsMbStatic (pBlockType, COLLOCATED_STATIC);
+}
+
+inline bool IsMbScrolledStatic (int32_t* pBlockType) {
+ return IsMbStatic (pBlockType, SCROLLED_STATIC);
+}
+
+inline int32_t CalUVSadCost (SWelsFuncPtrList* pFunc, uint8_t* pEncOri, int32_t iStrideUV, uint8_t* pRefOri,
+ int32_t iRefLineSize) {
+ return pFunc->sSampleDealingFuncs.pfSampleSad[BLOCK_8x8] (pEncOri, iStrideUV, pRefOri, iRefLineSize);
+}
+
+inline bool CheckBorder (int32_t iMbX, int32_t iMbY, int32_t iScrollMvX, int32_t iScrollMvY, int32_t iMbWidth,
+ int32_t iMbHeight) {
+ return ((iMbX << 4) + iScrollMvX < 0 ||
+ (iMbX << 4) + iScrollMvX > (iMbWidth - 1) << 4 ||
+ (iMbY << 4) + iScrollMvY < 0 ||
+ (iMbY << 4) + iScrollMvY > (iMbHeight - 1) << 4
+ ); //border check for safety
+}
+
void WelsMdSpatialelInterMbIlfmdNoilp (sWelsEncCtx* pEncCtx, SWelsMD* pWelsMd, SSlice* pSlice,
SMB* pCurMb, const Mb_Type kuiRefMbType) {
SDqLayer* pCurDqLayer = pEncCtx->pCurDqLayer;
@@ -153,7 +184,181 @@
}
}
-void SetBlockStaticIdcToMd (void* pVaa, void* pMd, SMB* pCurMb, void* pDqLay) { //TODO: OPT?
+bool JudgeStaticSkip (sWelsEncCtx* pEncCtx, SMB* pCurMb, SMbCache* pMbCache, SWelsMD* pWelsMd) {
+ SDqLayer* pCurDqLayer = pEncCtx->pCurDqLayer;
+ const int32_t kiMbX = pCurMb->iMbX;
+ const int32_t kiMbY = pCurMb->iMbY;
+
+ bool bTryStaticSkip = IsMbCollocatedStatic (pWelsMd->iBlock8x8StaticIdc);
+
+ if (bTryStaticSkip) {
+ int32_t iStrideUV, iOffsetUV;
+ SWelsFuncPtrList* pFunc = pEncCtx->pFuncList;
+ SPicture* pRefOri = pCurDqLayer->pRefOri;
+ if (pRefOri != NULL) {
+ iStrideUV = pCurDqLayer->iEncStride[1];
+ iOffsetUV = (kiMbX + kiMbY * iStrideUV) << 3;
+
+ int32_t iSadCostCb = CalUVSadCost (pFunc, pMbCache->SPicData.pEncMb[1], iStrideUV, pRefOri->pData[1] + iOffsetUV,
+ pRefOri->iLineSize[1]);
+ if (iSadCostCb == 0) {
+ int32_t iSadCostCr = CalUVSadCost (pFunc, pMbCache->SPicData.pEncMb[2], iStrideUV, pRefOri->pData[2] + iOffsetUV,
+ pRefOri->iLineSize[1]);
+ bTryStaticSkip = (0 == iSadCostCr);
+ } else bTryStaticSkip = false;
+ }
+ }
+ return bTryStaticSkip;
+}
+
+bool JudgeScrollSkip (sWelsEncCtx* pEncCtx, SMB* pCurMb, SMbCache* pMbCache, SWelsMD* pWelsMd) {
+ SDqLayer* pCurDqLayer = pEncCtx->pCurDqLayer;
+ const int32_t kiMbX = pCurMb->iMbX;
+ const int32_t kiMbY = pCurMb->iMbY;
+ const int32_t kiMbWidth = pCurDqLayer->iMbWidth;
+ const int32_t kiMbHeight = pCurDqLayer->iMbHeight;
+ // const int32_t block_width = mb_width << 1;
+ SVAAFrameInfoExt_t* pVaaExt = static_cast<SVAAFrameInfoExt_t*> (pEncCtx->pVaa);
+
+ bool bTryScrollSkip = false;
+
+ if (pVaaExt->sScrollDetectInfo.bScrollDetectFlag)
+ bTryScrollSkip = IsMbCollocatedStatic (pWelsMd->iBlock8x8StaticIdc);
+ else return 0;
+
+ if (bTryScrollSkip) {
+ int32_t iStrideUV, iOffsetUV;
+ SWelsFuncPtrList* pFunc = pEncCtx->pFuncList;
+ SPicture* pRefOri = pCurDqLayer->pRefOri;
+ if (pRefOri != NULL) {
+ int32_t iScrollMvX = pVaaExt->sScrollDetectInfo.iScrollMvX;
+ int32_t iScrollMvY = pVaaExt->sScrollDetectInfo.iScrollMvY;
+ if (CheckBorder (kiMbX, kiMbY, iScrollMvX, iScrollMvY, kiMbWidth, kiMbHeight)) {
+ bTryScrollSkip = false;
+ } else {
+ iStrideUV = pCurDqLayer->iEncStride[1];
+ iOffsetUV = (kiMbX << 3) + (iScrollMvX >> 1) + ((kiMbX << 3) + (iScrollMvY >> 1)) * iStrideUV;
+
+ int32_t iSadCostCb = CalUVSadCost (pFunc, pMbCache->SPicData.pEncMb[1], iStrideUV, pRefOri->pData[1] + iOffsetUV,
+ pRefOri->iLineSize[1]);
+ if (iSadCostCb == 0) {
+ int32_t iSadCostCr = CalUVSadCost (pFunc, pMbCache->SPicData.pEncMb[2], iStrideUV, pRefOri->pData[2] + iOffsetUV,
+ pRefOri->iLineSize[1]);
+ bTryScrollSkip = (0 == iSadCostCr);
+ } else bTryScrollSkip = false;
+ }
+ }
+ }
+ return bTryScrollSkip;
+}
+
+void SvcMdSCDMbEnc (sWelsEncCtx* pEncCtx, SWelsMD* pWelsMd, SMB* pCurMb, SMbCache* pMbCache, SSlice* pSlice,
+ bool bQpSimilarFlag,
+ bool bMbSkipFlag, SMVUnitXY sCurMbMv[], ESkipModes eSkipMode) {
+ SDqLayer* pCurDqLayer = pEncCtx->pCurDqLayer;
+ SWelsFuncPtrList* pFunc = pEncCtx->pFuncList;
+ SMVUnitXY sMvp = { 0};
+ ST16 (&sMvp.iMvX, sCurMbMv[eSkipMode].iMvX);
+ ST16 (&sMvp.iMvY, sCurMbMv[eSkipMode].iMvY);
+ uint8_t* pRefLuma = pMbCache->SPicData.pRefMb[0];
+ uint8_t* pRefCb = pMbCache->SPicData.pRefMb[1];
+ uint8_t* pRefCr = pMbCache->SPicData.pRefMb[2];
+ int32_t iLineSizeY = pCurDqLayer->pRefPic->iLineSize[0];
+ int32_t iLineSizeUV = pCurDqLayer->pRefPic->iLineSize[1];
+ uint8_t* pDstLuma = pMbCache->pSkipMb;
+ uint8_t* pDstCb = pMbCache->pSkipMb + 256;
+ uint8_t* pDstCr = pMbCache->pSkipMb + 256 + 64;
+
+ const int32_t iOffsetY = (sCurMbMv[eSkipMode].iMvX >> 2) + (sCurMbMv[eSkipMode].iMvY >> 2) * iLineSizeY;
+ const int32_t iOffsetUV = (sCurMbMv[eSkipMode].iMvX >> 3) + (sCurMbMv[eSkipMode].iMvY >> 3) * iLineSizeUV;
+
+ if (!bQpSimilarFlag || !bMbSkipFlag) {
+ pDstLuma = pMbCache->pMemPredLuma;
+ pDstCb = pMbCache->pMemPredChroma;
+ pDstCr = pMbCache->pMemPredChroma + 64;
+ }
+ //MC
+ pFunc->sMcFuncs.pfLumaQuarpelMc[0] (pRefLuma + iOffsetY, iLineSizeY, pDstLuma, 16, 16);
+ pFunc->sMcFuncs.pfChromaMc (pRefCb + iOffsetUV, iLineSizeUV, pDstCb, 8, sMvp, 8, 8);
+ pFunc->sMcFuncs.pfChromaMc (pRefCr + iOffsetUV, iLineSizeUV, pDstCr, 8, sMvp, 8, 8);
+
+ pCurMb->uiCbp = 0;
+ pWelsMd->iCostLuma = 0;
+ pCurMb->pSadCost[0] = pFunc->sSampleDealingFuncs.pfSampleSad[BLOCK_16x16] (pMbCache->SPicData.pEncMb[0],
+ pCurDqLayer->iEncStride[0], pRefLuma + iOffsetY, iLineSizeY);
+
+ pWelsMd->iCostSkipMb = pCurMb->pSadCost[0];
+
+ ST16 (& (pCurMb->sP16x16Mv.iMvX), sCurMbMv[eSkipMode].iMvX);
+ ST16 (& (pCurMb->sP16x16Mv.iMvY), sCurMbMv[eSkipMode].iMvY);
+
+ ST16 (& (pCurDqLayer->pDecPic->sMvList[pCurMb->iMbXY].iMvX), sCurMbMv[eSkipMode].iMvX);
+ ST16 (& (pCurDqLayer->pDecPic->sMvList[pCurMb->iMbXY].iMvY), sCurMbMv[eSkipMode].iMvY);
+
+ if (bQpSimilarFlag && bMbSkipFlag) {
+ //update motion info to current MB
+ ST32 (pCurMb->pRefIndex, 0);
+ pFunc->pfUpdateMbMv (pCurMb->sMv, sMvp);
+ pCurMb->uiMbType = MB_TYPE_SKIP;
+ WelsRecPskip (pCurDqLayer, pEncCtx->pFuncList, pCurMb, pMbCache);
+ WelsMdInterUpdatePskip (pCurDqLayer, pSlice, pCurMb, pMbCache);
+ return;
+ }
+
+ pCurMb->uiMbType = MB_TYPE_16x16;
+
+ pWelsMd->sMe.sMe16x16.sMv.iMvX = sCurMbMv[eSkipMode].iMvX;
+ pWelsMd->sMe.sMe16x16.sMv.iMvY = sCurMbMv[eSkipMode].iMvY;
+ PredMv (&pMbCache->sMvComponents, 0, 4, 0, &pWelsMd->sMe.sMe16x16.sMvp);
+ pMbCache->sMbMvp[0] = pWelsMd->sMe.sMe16x16.sMvp;
+
+ UpdateP16x16MotionInfo (pMbCache, pCurMb, 0, &pWelsMd->sMe.sMe16x16.sMv);
+
+ if (pWelsMd->bMdUsingSad)
+ pWelsMd->iCostLuma = pCurMb->pSadCost[0];
+ else
+ pWelsMd->iCostLuma = pFunc->sSampleDealingFuncs.pfSampleSad[BLOCK_16x16] (pMbCache->SPicData.pEncMb[0],
+ pCurDqLayer->iEncStride[0], pRefLuma, iLineSizeY);
+
+ WelsInterMbEncode (pEncCtx, pSlice, pCurMb);
+ WelsPMbChromaEncode (pEncCtx, pSlice, pCurMb);
+
+ pFunc->pfCopy16x16Aligned (pMbCache->SPicData.pCsMb[0], pCurDqLayer->iCsStride[0], pMbCache->pMemPredLuma, 16);
+ pFunc->pfCopy8x8Aligned (pMbCache->SPicData.pCsMb[1], pCurDqLayer->iCsStride[1], pMbCache->pMemPredChroma, 8);
+ pFunc->pfCopy8x8Aligned (pMbCache->SPicData.pCsMb[2], pCurDqLayer->iCsStride[1], pMbCache->pMemPredChroma + 64, 8);
+}
+
+bool MdInterSCDPskipProcess (sWelsEncCtx* pEncCtx, SWelsMD* pWelsMd, SSlice* pSlice, SMB* pCurMb, SMbCache* pMbCache,
+ ESkipModes eSkipMode) {
+ SVAAFrameInfoExt_t* pVaaExt = static_cast<SVAAFrameInfoExt_t*> (pEncCtx->pVaa);
+ SDqLayer* pCurDqLayer = pEncCtx->pCurDqLayer;
+
+ const int32_t kiRefMbQp = pCurDqLayer->pRefPic->pRefMbQp[pCurMb->iMbXY];
+ const int32_t kiCurMbQp = pCurMb->uiLumaQp;// unsigned -> signed
+
+ pJudgeSkipFun pJudeSkip[2] = {JudgeStaticSkip, JudgeScrollSkip};
+ bool bSkipFlag = pJudeSkip[eSkipMode] (pEncCtx, pCurMb, pMbCache, pWelsMd);
+
+ if (bSkipFlag) {
+ bool bQpSimilarFlag = (kiRefMbQp - kiCurMbQp <= DELTA_QP_SCD_THD || kiRefMbQp <= 26);
+ SMVUnitXY sVaaPredSkipMv = { 0 }, sCurMbMv[2] = {0, 0, 0, 0};
+ PredSkipMv (pMbCache, &sVaaPredSkipMv);
+
+ if (eSkipMode == SCROLLED) {
+ sCurMbMv[1].iMvX = static_cast<int16_t> (pVaaExt->sScrollDetectInfo.iScrollMvX << 2);
+ sCurMbMv[1].iMvY = static_cast<int16_t> (pVaaExt->sScrollDetectInfo.iScrollMvY << 2);
+ }
+
+ bool bMbSkipFlag = (LD32 (&sVaaPredSkipMv) == LD32 (&sCurMbMv[eSkipMode])) ;
+ SvcMdSCDMbEnc (pEncCtx, pWelsMd, pCurMb, pMbCache, pSlice, bQpSimilarFlag, bMbSkipFlag, sCurMbMv, eSkipMode);
+
+ return true;
+ }
+
+ return false;
+}
+
+void SetBlockStaticIdcToMd (void* pVaa, void* pMd, SMB* pCurMb, void* pDqLay) {
SVAAFrameInfoExt_t* pVaaExt = static_cast<SVAAFrameInfoExt_t*> (pVaa);
SWelsMD* pWelsMd = static_cast<SWelsMD*> (pMd);
SDqLayer* pDqLayer = static_cast<SDqLayer*> (pDqLay);
@@ -177,12 +382,12 @@
///////////////////////
// Scene Change Detection (SCD) PSkip Decision for screen content
////////////////////////
-bool WelsMdInterJudgeSCDPskip (void* pEncCtx, void* pWelsMd, SSlice* slice, SMB* pCurMb, SMbCache* pMbCache) {
- sWelsEncCtx* pCtx = (sWelsEncCtx*)pEncCtx;
- SWelsMD* pMd = (SWelsMD*)pWelsMd;
- SDqLayer* pCurDqLayer = pCtx->pCurDqLayer;
+bool WelsMdInterJudgeSCDPskip (void* pCtx, void* pMd, SSlice* slice, SMB* pCurMb, SMbCache* pMbCache) {
+ sWelsEncCtx* pEncCtx = (sWelsEncCtx*)pCtx;
+ SWelsMD* pWelsMd = (SWelsMD*)pMd;
+ SDqLayer* pCurDqLayer = pEncCtx->pCurDqLayer;
- SetBlockStaticIdcToMd (pCtx->pVaa, pMd, pCurMb, pCurDqLayer);
+ SetBlockStaticIdcToMd (pEncCtx->pVaa, pWelsMd, pCurMb, pCurDqLayer);
//try static Pskip;
@@ -191,17 +396,16 @@
return false;
}
-bool WelsMdInterJudgeSCDPskipFalse (void* pEncCtx, void* pWelsMd, SSlice* slice, SMB* pCurMb,
- SMbCache* pMbCache) {
+bool WelsMdInterJudgeSCDPskipFalse (void* pEncCtx, void* pWelsMd, SSlice* slice, SMB* pCurMb, SMbCache* pMbCache) {
return false;
}
-void WelsInitScrollingSkipFunc (SWelsFuncPtrList* pFuncList, const bool bScrollingDetection) {
+void WelsInitSCDPskipFunc (SWelsFuncPtrList* pFuncList, const bool bScrollingDetection) {
if (bScrollingDetection) {
- pFuncList->pfScrollingPSkipDecision = WelsMdInterJudgeSCDPskip;
+ pFuncList->pfSCDPSkipDecision = WelsMdInterJudgeSCDPskip;
} else {
- pFuncList->pfScrollingPSkipDecision = WelsMdInterJudgeSCDPskipFalse;
+ pFuncList->pfSCDPSkipDecision = WelsMdInterJudgeSCDPskipFalse;
}
}