[Encoder MD] Add Inter Psub16 MD for screen content coding

This commit is contained in:
sijchen 2014-05-12 14:21:40 +08:00
parent 6a295d5e8e
commit 4bd6a3a6e8
4 changed files with 93 additions and 0 deletions

View File

@ -66,6 +66,15 @@ namespace WelsSVCEnc {
#define NO_BEST_FRAC_PIX 1 // REFINE_ME_NO_BEST_HALF_PIXEL + ME_NO_BEST_QUAR_PIXEL
//for vaa constants
#define MBVAASIGN_FLAT 15
#define MBVAASIGN_HOR1 3
#define MBVAASIGN_HOR2 12
#define MBVAASIGN_VER1 5
#define MBVAASIGN_VER2 10
#define MBVAASIGN_CMPX1 6
#define MBVAASIGN_CMPX2 9
extern const int32_t g_kiQpCostTable[52];
extern const int8_t g_kiMapModeI16x16[7];
//extern const int8_t g_kiMapModeI4x4[14];

View File

@ -66,6 +66,8 @@ int32_t WelsMdP8x8 (SWelsFuncPtrList* pFunc, SDqLayer* pCurDqLayer, SWelsMD* pWe
/*static*/ void WelsMdInterInit (sWelsEncCtx* pEncCtx, SSlice* pSlice, SMB* pCurMb, const int32_t kiSliceFirstMbXY);
/*static*/ void WelsMdInterFinePartition (void* pEnc, void* pMd, SSlice* pSlice, SMB* pCurMb, int32_t bestCost);
/*static*/ void WelsMdInterFinePartitionVaa (void* pEnc, void* pMd, SSlice* pSlice, SMB* pCurMb, int32_t bestCost);
/*static*/ void WelsMdInterFinePartitionVaaOnScreen (void* pEnc, void* pMd, SSlice* pSlice, SMB* pCurMb,
int32_t bestCost);
void WelsMdInterMbRefinement (sWelsEncCtx* pEncCtx, SWelsMD* pWelsMd, SMB* pCurMb, SMbCache* pMbCache);
bool WelsMdFirstIntraMode (void* pEnc, void* pMd, SMB* pCurMb, SMbCache* pMbCache);
//bool svc_md_first_intra_mode_constrained(void* pEnc, void* pMd, SMB* pCurMb, SMbCache *pMbCache);

View File

@ -2457,6 +2457,9 @@ void PreprocessSliceCoding (sWelsEncCtx* pCtx) {
pFeatureSearchPreparation->iHighFreMbCount = 0;
if (P_SLICE == pCtx->eSliceType) {
//MD related func pointers
pFuncList->pfInterFineMd = WelsMdInterFinePartitionVaaOnScreen;
//calculate bFMESwitchFlag
SVAAFrameInfoExt* pVaaExt = static_cast<SVAAFrameInfoExt*> (pCtx->pVaa);
const int32_t kiMbSize = pCurLayer->iMbHeight * pCurLayer->iMbWidth;

View File

@ -1868,7 +1868,86 @@ void WelsMdIntraSecondaryModesEnc (sWelsEncCtx* pEncCtx, SWelsMD* pWelsMd, SMB*
pCurMb->pSadCost[0] = 0;
}
//
//func pointer of inter MD for sub16x16 INTER MD for screen content coding
//
static inline void MergeSub16Me (const SWelsME& sSrcMe0, const SWelsME& sSrcMe1, SWelsME* pTarMe) {
memcpy (pTarMe, &sSrcMe0, sizeof (sSrcMe0)); // confirmed_safe_unsafe_usage
pTarMe->uiSadCost = sSrcMe0.uiSadCost + sSrcMe1.uiSadCost;//not precise cost since MVD cost is not the same
pTarMe->uiSatdCost = sSrcMe0.uiSatdCost + sSrcMe1.uiSatdCost;//not precise cost since MVD cost is not the same
}
static inline bool IsSameMv (const SMVUnitXY& sMv0, const SMVUnitXY& sMv1) {
return ((sMv0.iMvX == sMv1.iMvX) && (sMv0.iMvY == sMv1.iMvY));
}
static inline int32_t Mvd (const SMVUnitXY& sMv, const SMVUnitXY& sMvp) {
return (WELS_ABS (sMv.iMvX - sMvp.iMvX) + WELS_ABS (sMv.iMvY - sMvp.iMvY));
}
bool TryModeMerge (SMbCache* pMbCache, SWelsMD* pWelsMd, SMB* pCurMb) {
SWelsME* pMe8x8 = & (pWelsMd->sMe.sMe8x8[0]);
const bool bSameMv16x8_0 = IsSameMv (pMe8x8[0].sMv, pMe8x8[1].sMv);
const bool bSameMv16x8_1 = IsSameMv (pMe8x8[2].sMv, pMe8x8[3].sMv);
const bool bSameMv8x16_0 = IsSameMv (pMe8x8[0].sMv, pMe8x8[2].sMv);
const bool bSameMv8x16_1 = IsSameMv (pMe8x8[1].sMv, pMe8x8[3].sMv);
//need to consider iRefIdx when multi ref is available
const bool bSameRefIdx16x8_0 = true; //pMe8x8[0].iRefIdx == pMe8x8[1].iRefIdx;
const bool bSameRefIdx16x8_1 = true; //pMe8x8[2].iRefIdx == pMe8x8[3].iRefIdx;
const bool bSameRefIdx8x16_0 = true; //pMe8x8[0].iRefIdx == pMe8x8[2].iRefIdx;
const bool bSameRefIdx8x16_1 = true; //pMe8x8[1].iRefIdx == pMe8x8[3].iRefIdx;
const int32_t iSameMv = (bSameMv16x8_0 << 7) | (bSameRefIdx16x8_0 << 6) | (bSameMv16x8_1 << 5) |
(bSameRefIdx16x8_1 << 4) |
(bSameMv8x16_0 << 3) | (bSameRefIdx8x16_0 << 2) | (bSameMv8x16_1 << 1) | (bSameRefIdx8x16_1);
switch (iSameMv) {
case 0xF0:
pCurMb->uiMbType = MB_TYPE_16x8;
MergeSub16Me (pMe8x8[0], pMe8x8[1], & (pWelsMd->sMe.sMe16x8[0]));
MergeSub16Me (pMe8x8[2], pMe8x8[3], & (pWelsMd->sMe.sMe16x8[1]));
PredInter16x8Mv (pMbCache, 0, 0, & (pWelsMd->sMe.sMe16x8[0].sMvp));
PredInter16x8Mv (pMbCache, 8, 0, & (pWelsMd->sMe.sMe16x8[1].sMvp));
break;
case 0x0F:
pCurMb->uiMbType = MB_TYPE_8x16;
MergeSub16Me (pMe8x8[0], pMe8x8[2], & (pWelsMd->sMe.sMe8x16[0]));
MergeSub16Me (pMe8x8[1], pMe8x8[3], & (pWelsMd->sMe.sMe8x16[1]));
PredInter8x16Mv (pMbCache, 0, 0, & (pWelsMd->sMe.sMe8x16[0].sMvp));
PredInter8x16Mv (pMbCache, 4, 0, & (pWelsMd->sMe.sMe8x16[1].sMvp));
break;
case 0xFF:
//MERGE_16x16
//from test results of multiple sequences show that using the following 0x0F to merge 16x16
//for some seq there is BR saving some loss
//on the whole the BR will increase little bit
//to save complexity we decided not to merge 16x16 at present (10/12/2012)
default:
break;
}
return (MB_TYPE_8x8 != pCurMb->uiMbType);
}
void WelsMdInterFinePartitionVaaOnScreen (void* pEnc, void* pMd, SSlice* pSlice, SMB* pCurMb, int32_t iBestCost) {
sWelsEncCtx* pEncCtx = (sWelsEncCtx*)pEnc;
SWelsMD* pWelsMd = (SWelsMD*)pMd;
SMbCache* pMbCache = &pSlice->sMbCacheInfo;
SDqLayer* pCurDqLayer = pEncCtx->pCurDqLayer;
int32_t iCostP8x8;
uint8_t uiMbSign = pEncCtx->pFuncList->pfGetMbSignFromInterVaa (&pEncCtx->pVaa->sVaaCalcInfo.pSad8x8[pCurMb->iMbXY][0]);
if (MBVAASIGN_FLAT == uiMbSign) {
return;
}
iCostP8x8 = WelsMdP8x8 (pEncCtx->pFuncList, pCurDqLayer, pWelsMd, pSlice);
if (iCostP8x8 < iBestCost) {
iBestCost = iCostP8x8;
pCurMb->uiMbType = MB_TYPE_8x8;
TryModeMerge (pMbCache, pWelsMd, pCurMb);
}
pWelsMd->iCostLuma = iBestCost;
}
} // namespace WelsSVCEnc