void CComplexityAnalysis::AnalyzeGomComplexityViaVar (SPixMap* pSrcPixMap, SPixMap* pRefPixMap) { int32_t iWidth = pSrcPixMap->sRect.iRectWidth; int32_t iHeight = pSrcPixMap->sRect.iRectHeight; int32_t iMbWidth = iWidth >> 4; int32_t iMbHeight = iHeight >> 4; int32_t iMbNum = iMbWidth * iMbHeight; int32_t iMbNumInGom = m_sComplexityAnalysisParam.iMbNumInGom; int32_t iGomMbNum = (iMbNum + iMbNumInGom - 1) / iMbNumInGom; int32_t iGomSampleNum = 0; int32_t iGomMbStartIndex = 0, iGomMbEndIndex = 0, iGomMbRowNum = 0; int32_t iMbStartIndex = 0, iMbEndIndex = 0; int32_t iStartSampleIndex = 0; SVAACalcResult* pVaaCalcResults = m_sComplexityAnalysisParam.pCalcResult; int32_t* pGomComplexity = (int32_t*)m_sComplexityAnalysisParam.pGomComplexity; uint8_t* pSrcY = NULL; int32_t iCurStride = 0; uint8_t* pCurTmp = NULL; uint32_t uiSampleSum = 0, uiSquareSum = 0; pSrcY = (uint8_t*)pSrcPixMap->pPixel[0]; iCurStride = pSrcPixMap->iStride[0]; for (int32_t j = 0; j < iGomMbNum; j ++) { uiSampleSum = 0; uiSquareSum = 0; iGomMbStartIndex = j * iMbNumInGom; iGomMbEndIndex = WELS_MIN ((j + 1) * iMbNumInGom, iMbNum); iGomMbRowNum = (iGomMbEndIndex + iMbWidth - 1) / iMbWidth - iGomMbStartIndex / iMbWidth; iMbStartIndex = iGomMbStartIndex; iMbEndIndex = WELS_MIN ((iMbStartIndex / iMbWidth + 1) * iMbWidth, iGomMbEndIndex); iStartSampleIndex = (iMbStartIndex / iMbWidth) * MB_WIDTH_LUMA * iCurStride + (iMbStartIndex % iMbWidth) * MB_WIDTH_LUMA; iGomSampleNum = (iMbEndIndex - iMbStartIndex) * MB_WIDTH_LUMA * MB_WIDTH_LUMA; do { pCurTmp = pSrcY + iStartSampleIndex; for (int32_t i = iMbStartIndex; i < iMbEndIndex; i ++) { uiSampleSum += pVaaCalcResults->pSum16x16[i]; uiSquareSum += pVaaCalcResults->pSumOfSquare16x16[i]; } iMbStartIndex = iMbEndIndex; iMbEndIndex = WELS_MIN (iMbEndIndex + iMbWidth, iGomMbEndIndex); iStartSampleIndex = (iMbStartIndex / iMbWidth) * MB_WIDTH_LUMA * iCurStride + (iMbStartIndex % iMbWidth) * MB_WIDTH_LUMA; } while (--iGomMbRowNum); pGomComplexity[j] = uiSquareSum - (uiSampleSum * uiSampleSum / iGomSampleNum); } }
void CComplexityAnalysis::AnalyzeGomComplexityViaSad (SPixMap* pSrcPixMap, SPixMap* pRefPixMap) { int32_t iWidth = pSrcPixMap->sRect.iRectWidth; int32_t iHeight = pSrcPixMap->sRect.iRectHeight; int32_t iMbWidth = iWidth >> 4; int32_t iMbHeight = iHeight >> 4; int32_t iMbNum = iMbWidth * iMbHeight; int32_t iMbNumInGom = m_sComplexityAnalysisParam.iMbNumInGom; int32_t iGomMbNum = (iMbNum + iMbNumInGom - 1) / iMbNumInGom; int32_t iGomMbStartIndex = 0, iGomMbEndIndex = 0, iGomMbRowNum = 0; int32_t iMbStartIndex = 0, iMbEndIndex = 0; uint8_t* pBackgroundMbFlag = (uint8_t*)m_sComplexityAnalysisParam.pBackgroundMbFlag; uint32_t* uiRefMbType = (uint32_t*)m_sComplexityAnalysisParam.uiRefMbType; SVAACalcResult* pVaaCalcResults = m_sComplexityAnalysisParam.pCalcResult; int32_t* pGomForegroundBlockNum = (int32_t*)m_sComplexityAnalysisParam.pGomForegroundBlockNum; int32_t* pGomComplexity = (int32_t*)m_sComplexityAnalysisParam.pGomComplexity; uint32_t uiGomSad = 0, uiFrameSad = 0; InitGomSadFunc (m_pfGomSad, m_sComplexityAnalysisParam.iCalcBgd); for (int32_t j = 0; j < iGomMbNum; j ++) { uiGomSad = 0; iGomMbStartIndex = j * iMbNumInGom; iGomMbEndIndex = WELS_MIN ((j + 1) * iMbNumInGom, iMbNum); iGomMbRowNum = (iGomMbEndIndex + iMbWidth - 1) / iMbWidth - iGomMbStartIndex / iMbWidth; iMbStartIndex = iGomMbStartIndex; iMbEndIndex = WELS_MIN ((iMbStartIndex / iMbWidth + 1) * iMbWidth, iGomMbEndIndex); do { for (int32_t i = iMbStartIndex; i < iMbEndIndex; i ++) { m_pfGomSad (&uiGomSad, pGomForegroundBlockNum + j, pVaaCalcResults->pSad8x8[i], pBackgroundMbFlag[i] && !IS_INTRA (uiRefMbType[i])); } iMbStartIndex = iMbEndIndex; iMbEndIndex = WELS_MIN (iMbEndIndex + iMbWidth , iGomMbEndIndex); } while (--iGomMbRowNum); pGomComplexity[j] = uiGomSad; uiFrameSad += pGomComplexity[j]; } m_sComplexityAnalysisParam.iFrameComplexity = uiFrameSad; }
void CComplexityAnalysis::AnalyzeGomComplexityViaVar (SPixMap* pSrcPixMap, SPixMap* pRefPixMap) { int32_t iWidth = pSrcPixMap->sRect.iRectWidth; int32_t iHeight = pSrcPixMap->sRect.iRectHeight; int32_t iMbWidth = iWidth >> 4; int32_t iMbHeight = iHeight >> 4; int32_t iMbNum = iMbWidth * iMbHeight; int32_t iMbNumInGom = m_sComplexityAnalysisParam.iMbNumInGom; int32_t iGomMbNum = (iMbNum + iMbNumInGom - 1) / iMbNumInGom; int32_t iGomSampleNum = 0; int32_t iGomMbStartIndex = 0, iGomMbEndIndex = 0, iGomMbRowNum = 0; int32_t iMbStartIndex = 0, iMbEndIndex = 0; SVAACalcResult* pVaaCalcResults = m_sComplexityAnalysisParam.pCalcResult; int32_t* pGomComplexity = (int32_t*)m_sComplexityAnalysisParam.pGomComplexity; uint32_t uiFrameSad = 0; uint32_t uiSampleSum = 0, uiSquareSum = 0; for (int32_t j = 0; j < iGomMbNum; j ++) { uiSampleSum = 0; uiSquareSum = 0; iGomMbStartIndex = j * iMbNumInGom; iGomMbEndIndex = WELS_MIN ((j + 1) * iMbNumInGom, iMbNum); iGomMbRowNum = (iGomMbEndIndex + iMbWidth - 1) / iMbWidth - iGomMbStartIndex / iMbWidth; iMbStartIndex = iGomMbStartIndex; iMbEndIndex = WELS_MIN ((iMbStartIndex / iMbWidth + 1) * iMbWidth, iGomMbEndIndex); iGomSampleNum = (iMbEndIndex - iMbStartIndex) * MB_WIDTH_LUMA * MB_WIDTH_LUMA; do { for (int32_t i = iMbStartIndex; i < iMbEndIndex; i ++) { uiSampleSum += pVaaCalcResults->pSum16x16[i]; uiSquareSum += pVaaCalcResults->pSumOfSquare16x16[i]; } iMbStartIndex = iMbEndIndex; iMbEndIndex = WELS_MIN (iMbEndIndex + iMbWidth, iGomMbEndIndex); } while (--iGomMbRowNum); pGomComplexity[j] = uiSquareSum - (uiSampleSum * uiSampleSum / iGomSampleNum); uiFrameSad += pGomComplexity[j]; } m_sComplexityAnalysisParam.iFrameComplexity = uiFrameSad; }
int32_t CComplexityAnalysis::GetFrameSadExcludeBackground (SPixMap* pSrcPixMap, SPixMap* pRefPixMap) { int32_t iWidth = pSrcPixMap->sRect.iRectWidth; int32_t iHeight = pSrcPixMap->sRect.iRectHeight; int32_t iMbWidth = iWidth >> 4; int32_t iMbHeight = iHeight >> 4; int32_t iMbNum = iMbWidth * iMbHeight; int32_t iMbNumInGom = m_sComplexityAnalysisParam.iMbNumInGom; int32_t iGomMbNum = (iMbNum + iMbNumInGom - 1) / iMbNumInGom; int32_t iGomMbStartIndex = 0, iGomMbEndIndex = 0; uint8_t* pBackgroundMbFlag = (uint8_t*)m_sComplexityAnalysisParam.pBackgroundMbFlag; uint32_t* uiRefMbType = (uint32_t*)m_sComplexityAnalysisParam.uiRefMbType; SVAACalcResult* pVaaCalcResults = m_sComplexityAnalysisParam.pCalcResult; int32_t* pGomForegroundBlockNum = m_sComplexityAnalysisParam.pGomForegroundBlockNum; uint32_t uiFrameSad = 0; for (int32_t j = 0; j < iGomMbNum; j ++) { iGomMbStartIndex = j * iMbNumInGom; iGomMbEndIndex = WELS_MIN ((j + 1) * iMbNumInGom, iMbNum); for (int32_t i = iGomMbStartIndex; i < iGomMbEndIndex; i ++) { if (pBackgroundMbFlag[i] == 0 || IS_INTRA (uiRefMbType[i])) { pGomForegroundBlockNum[j]++; uiFrameSad += pVaaCalcResults->pSad8x8[i][0]; uiFrameSad += pVaaCalcResults->pSad8x8[i][1]; uiFrameSad += pVaaCalcResults->pSad8x8[i][2]; uiFrameSad += pVaaCalcResults->pSad8x8[i][3]; } } } return (uiFrameSad); }
void CComplexityAnalysisScreen::GomComplexityAnalysisIntra (SPixMap* pSrc) { int32_t iWidth = pSrc->sRect.iRectWidth; int32_t iHeight = pSrc->sRect.iRectHeight; int32_t iBlockWidth = iWidth >> 4; int32_t iBlockHeight = iHeight >> 4; int32_t iBlockSadH, iBlockSadV, iGomSad = 0; int32_t iIdx = 0; uint8_t* pPtrY = NULL; int32_t iStrideY = 0; int32_t iRowStrideY = 0; uint8_t* pTmpCur = NULL; ENFORCE_STACK_ALIGN_1D (uint8_t, iMemPredMb, 256, 16) pPtrY = (uint8_t*)pSrc->pPixel[0]; iStrideY = pSrc->iStride[0]; iRowStrideY = iStrideY << 4; m_ComplexityAnalysisParam.iFrameComplexity = 0; for (int32_t j = 0; j < iBlockHeight; j ++) { pTmpCur = pPtrY; for (int32_t i = 0; i < iBlockWidth; i++) { iBlockSadH = iBlockSadV = 0x7fffffff; // INT_MAX if (j > 0) { m_pIntraFunc[0] (iMemPredMb, pTmpCur, iStrideY); iBlockSadH = m_pSadFunc (pTmpCur, iStrideY, iMemPredMb, 16); } if (i > 0) { m_pIntraFunc[1] (iMemPredMb, pTmpCur, iStrideY); iBlockSadV = m_pSadFunc (pTmpCur, iStrideY, iMemPredMb, 16); } if (i || j) iGomSad += WELS_MIN (iBlockSadH, iBlockSadV); pTmpCur += 16; if (i == iBlockWidth - 1 && ((j + 1) % m_ComplexityAnalysisParam.iMbRowInGom == 0 || j == iBlockHeight - 1)) { m_ComplexityAnalysisParam.pGomComplexity[iIdx] = iGomSad; m_ComplexityAnalysisParam.iFrameComplexity += iGomSad; iIdx++; iGomSad = 0; } } pPtrY += iRowStrideY; } m_ComplexityAnalysisParam.iGomNumInFrame = iIdx; }
int32_t PredIntra4x4Mode (int8_t* pIntraPredMode, int32_t iIdx4) { int8_t iTopMode = pIntraPredMode[g_kuiScan8[iIdx4] - 8]; int8_t iLeftMode = pIntraPredMode[g_kuiScan8[iIdx4] - 1]; int8_t iBestMode; if (-1 == iLeftMode || -1 == iTopMode) { iBestMode = 2; } else { iBestMode = WELS_MIN (iLeftMode, iTopMode); } return iBestMode; }
void ScrollDetectionCore (SPixMap* pSrcPixMap, SPixMap* pRefPixMap, int32_t iWidth, int32_t iHeight, int32_t iOffsetX, int32_t iOffsetY, SScrollDetectionParam& sScrollDetectionParam) { bool bScrollDetected = 0; uint8_t* pYLine; uint8_t* pYTmp; int32_t iTestPos, iSearchPos = 0, iOffsetAbs, iMaxAbs; int32_t iPicHeight = pRefPixMap->sRect.iRectHeight; int32_t iMinHeight = WELS_MAX (iOffsetY, 0); int32_t iMaxHeight = WELS_MIN (iOffsetY + iHeight - 1, iPicHeight - 1) ; //offset_y + height - 1;// uint8_t* pYRef, *pYSrc; int32_t iYStride; pYRef = (uint8_t*)pRefPixMap->pPixel[0]; pYSrc = (uint8_t*)pSrcPixMap->pPixel[0]; iYStride = pRefPixMap->iStride[0]; iTestPos = SelectTestLine (pYSrc, iWidth, iHeight, iPicHeight, iYStride, iOffsetX, iOffsetY); if (iTestPos == -1) { sScrollDetectionParam.bScrollDetectFlag = 0; return; } pYLine = pYSrc + iYStride * iTestPos + iOffsetX; iMaxAbs = WELS_MIN (WELS_MAX (iTestPos - iMinHeight - 1, iMaxHeight - iTestPos), MAX_SCROLL_MV_Y); iSearchPos = iTestPos; for (iOffsetAbs = 0; iOffsetAbs <= iMaxAbs; iOffsetAbs++) { iSearchPos = iTestPos + iOffsetAbs; if (iSearchPos <= iMaxHeight) { pYTmp = pYRef + iSearchPos * iYStride + iOffsetX; if (!CompareLine (pYLine, pYTmp, iWidth)) { uint8_t* pYUpper, *pYLineUpper; int32_t iCheckedLines; int32_t iLowOffset = WELS_MIN (iMaxHeight - iSearchPos, CHECK_OFFSET); int32_t i; iCheckedLines = WELS_MIN (iTestPos - iMinHeight + iLowOffset, 2 * CHECK_OFFSET); pYUpper = pYTmp - (iCheckedLines - iLowOffset) * iYStride; pYLineUpper = pYLine - (iCheckedLines - iLowOffset) * iYStride; for (i = 0; i < iCheckedLines; i ++) { if (CompareLine (pYLineUpper, pYUpper, iWidth)) { break; } pYUpper += iYStride; pYLineUpper += iYStride; } if (i == iCheckedLines) { bScrollDetected = 1; break; } } } iSearchPos = iTestPos - iOffsetAbs - 1; if (iSearchPos >= iMinHeight) { pYTmp = pYRef + iSearchPos * iYStride + iOffsetX; if (!CompareLine (pYLine, pYTmp, iWidth)) { uint8_t* pYUpper, *pYLineUpper; int32_t iCheckedLines; int32_t iUpOffset = WELS_MIN (iSearchPos - iMinHeight, CHECK_OFFSET); int32_t i; pYUpper = pYTmp - iUpOffset * iYStride; pYLineUpper = pYLine - iUpOffset * iYStride; iCheckedLines = WELS_MIN (iMaxHeight - iTestPos + iUpOffset, 2 * CHECK_OFFSET); for (i = 0; i < iCheckedLines; i ++) { if (CompareLine (pYLineUpper, pYUpper, iWidth)) { break; } pYUpper += iYStride; pYLineUpper += iYStride; } if (i == iCheckedLines) { bScrollDetected = 1; break; } } } } if (!bScrollDetected) { sScrollDetectionParam.bScrollDetectFlag = 0; } else { sScrollDetectionParam.bScrollDetectFlag = 1; sScrollDetectionParam.iScrollMvY = iSearchPos - iTestPos; // pre_pos - cur_pos, change to mv sScrollDetectionParam.iScrollMvX = 0; } }
void CComplexityAnalysisScreen::GomComplexityAnalysisInter (SPixMap* pSrc, SPixMap* pRef, bool bScrollFlag) { int32_t iWidth = pSrc->sRect.iRectWidth; int32_t iHeight = pSrc->sRect.iRectHeight; int32_t iBlockWidth = iWidth >> 4; int32_t iBlockHeight = iHeight >> 4; int32_t iInterSad, iScrollSad, iBlockSadH, iBlockSadV, iGomSad = 0; int32_t iIdx = 0; int32_t iScrollMvX = m_ComplexityAnalysisParam.sScrollResult.iScrollMvX; int32_t iScrollMvY = m_ComplexityAnalysisParam.sScrollResult.iScrollMvY; uint8_t* pPtrX = NULL, *pPtrY = NULL; int32_t iStrideX = 0, iStrideY = 0; int32_t iRowStrideX = 0, iRowStrideY = 0; uint8_t* pTmpRef = NULL, *pTmpCur = NULL, *pTmpRefScroll = NULL; ENFORCE_STACK_ALIGN_1D (uint8_t, iMemPredMb, 256, 16) pPtrX = (uint8_t*)pRef->pPixel[0]; pPtrY = (uint8_t*)pSrc->pPixel[0]; iStrideX = pRef->iStride[0]; iStrideY = pSrc->iStride[0]; iRowStrideX = pRef->iStride[0] << 4; iRowStrideY = pSrc->iStride[0] << 4; m_ComplexityAnalysisParam.iFrameComplexity = 0; for (int32_t j = 0; j < iBlockHeight; j ++) { pTmpRef = pPtrX; pTmpCur = pPtrY; for (int32_t i = 0; i < iBlockWidth; i++) { int32_t iBlockPointX = i << 4; int32_t iBlockPointY = j << 4; iInterSad = m_pSadFunc (pTmpCur, iStrideY, pTmpRef, iStrideX); if (bScrollFlag) { if ((iInterSad != 0) && (iBlockPointX + iScrollMvX >= 0) && (iBlockPointX + iScrollMvX <= iWidth - 8) && (iBlockPointY + iScrollMvY >= 0) && (iBlockPointY + iScrollMvY <= iHeight - 8)) { pTmpRefScroll = pTmpRef - iScrollMvY * iStrideX + iScrollMvX; iScrollSad = m_pSadFunc (pTmpCur, iStrideY, pTmpRefScroll, iStrideX); if (iScrollSad < iInterSad) { iInterSad = iScrollSad; } } } iBlockSadH = iBlockSadV = 0x7fffffff; // INT_MAX if (j > 0) { m_pIntraFunc[0] (iMemPredMb, pTmpCur, iStrideY); iBlockSadH = m_pSadFunc (pTmpCur, iStrideY, iMemPredMb, 16); } if (i > 0) { m_pIntraFunc[1] (iMemPredMb, pTmpCur, iStrideY); iBlockSadV = m_pSadFunc (pTmpCur, iStrideY, iMemPredMb, 16); } iGomSad += WELS_MIN (WELS_MIN (iBlockSadH, iBlockSadV), iInterSad); if (i == iBlockWidth - 1 && ((j + 1) % m_ComplexityAnalysisParam.iMbRowInGom == 0 || j == iBlockHeight - 1)) { m_ComplexityAnalysisParam.pGomComplexity[iIdx] = iGomSad; m_ComplexityAnalysisParam.iFrameComplexity += iGomSad; iIdx++; iGomSad = 0; } pTmpRef += 16; pTmpCur += 16; } pPtrX += iRowStrideX; pPtrY += iRowStrideY; } m_ComplexityAnalysisParam.iGomNumInFrame = iIdx; }