/*! * \copy * Copyright (c) 2009-2013, Cisco Systems * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * * * \file md.c * * \brief mode decision * * \date 2009.05.14 Created * ************************************************************************************* */ #include "ls_defines.h"#include "md.h"#include "cpu_core.h"#include "svc_enc_golomb.h" namespace WelsEnc {#define INTRA_VARIANCE_SAD_THRESHOLD 150#define INTER_VARIANCE_SAD_THRESHOLD 20 //fill cache of neighbor MB, containing pNonZeroCount, sample_avail, pIntra4x4PredModevoid FillNeighborCacheIntra (SMbCache* pMbCache, SMB* pCurMb, int32_t iMbWidth) { uint32_t uiNeighborAvail = pCurMb->uiNeighborAvail; uint32_t uiNeighborIntra = 0; if (uiNeighborAvail & LEFT_MB_POS) { //LEFT MB int8_t* pLeftMbNonZeroCount = pCurMb->pNonZeroCount - MB_LUMA_CHROMA_BLOCK4x4_NUM; pMbCache->iNonZeroCoeffCount[8] = pLeftMbNonZeroCount[ 3]; pMbCache->iNonZeroCoeffCount[16] = pLeftMbNonZeroCount[ 7]; pMbCache->iNonZeroCoeffCount[24] = pLeftMbNonZeroCount[11]; pMbCache->iNonZeroCoeffCount[32] = pLeftMbNonZeroCount[15]; pMbCache->iNonZeroCoeffCount[ 13] = pLeftMbNonZeroCount[17]; pMbCache->iNonZeroCoeffCount[21] = pLeftMbNonZeroCount[21]; pMbCache->iNonZeroCoeffCount[37] = pLeftMbNonZeroCount[19]; pMbCache->iNonZeroCoeffCount[45] = pLeftMbNonZeroCount[23]; uiNeighborIntra |= LEFT_MB_POS; if (IS_INTRA4x4 ((pCurMb - 1)->uiMbType)) { int8_t* pLeftMbIntra4x4PredMode = pCurMb->pIntra4x4PredMode - INTRA_4x4_MODE_NUM; pMbCache->iIntraPredMode[8] = pLeftMbIntra4x4PredMode[4]; pMbCache->iIntraPredMode[16] = pLeftMbIntra4x4PredMode[5]; pMbCache->iIntraPredMode[24] = pLeftMbIntra4x4PredMode[6]; pMbCache->iIntraPredMode[32] = pLeftMbIntra4x4PredMode[3]; } else { // if ( 0 == constrained_intra_pred_flag || IS_INTRA16x16((pCurMb-1)->uiMbType )) pMbCache->iIntraPredMode[8] = pMbCache->iIntraPredMode[16] = pMbCache->iIntraPredMode[24] = pMbCache->iIntraPredMode[32] = 2; //DC } } else { pMbCache->iNonZeroCoeffCount[ 8] = pMbCache->iNonZeroCoeffCount[16] = pMbCache->iNonZeroCoeffCount[24] = pMbCache->iNonZeroCoeffCount[32] = -1;//unavailable pMbCache->iNonZeroCoeffCount[13] = pMbCache->iNonZeroCoeffCount[21] = pMbCache->iNonZeroCoeffCount[37] = pMbCache->iNonZeroCoeffCount[45] = -1;//unavailable pMbCache->iIntraPredMode[8] = pMbCache->iIntraPredMode[16] = pMbCache->iIntraPredMode[24] = pMbCache->iIntraPredMode[32] = -1;//unavailable } if (uiNeighborAvail & TOP_MB_POS) { //TOP MB SMB* pTopMb = pCurMb - iMbWidth; ST32 (&pMbCache->iNonZeroCoeffCount[1], LD32 (&pTopMb->pNonZeroCount[12])); ST16 (&pMbCache->iNonZeroCoeffCount[6], LD16 (&pTopMb->pNonZeroCount[20])); ST16 (&pMbCache->iNonZeroCoeffCount[30], LD16 (&pTopMb->pNonZeroCount[22])); uiNeighborIntra |= TOP_MB_POS; if (IS_INTRA4x4 (pTopMb->uiMbType)) { ST32 (pMbCache->iIntraPredMode + 1, LD32 (&pTopMb->pIntra4x4PredMode[0])); } else { // if ( 0 == constrained_intra_pred_flag || IS_INTRA16x16( pTopMb->uiMbType )) const uint32_t kuiDc32 = 0x02020202; ST32 (pMbCache->iIntraPredMode + 1 , kuiDc32); } } else { const uint32_t kuiUnavail32 = 0xffffffff; ST32 (pMbCache->iIntraPredMode + 1 , kuiUnavail32); ST32 (&pMbCache->iNonZeroCoeffCount[1], kuiUnavail32); ST16 (&pMbCache->iNonZeroCoeffCount[6], 0xffff); ST16 (&pMbCache->iNonZeroCoeffCount[30], 0xffff); } if (uiNeighborAvail & TOPLEFT_MB_POS) { uiNeighborIntra |= 0x04; } if (uiNeighborAvail & TOPRIGHT_MB_POS) { uiNeighborIntra |= 0x08; } pMbCache->uiNeighborIntra = uiNeighborIntra;}//fill cache of neighbor MB, containing motion_vector and uiRefIndexvoid FillNeighborCacheInterWithoutBGD (SMbCache* pMbCache, SMB* pCurMb, int32_t iMbWidth, int8_t* pVaaBgMbFlag) { uint32_t uiNeighborAvail = pCurMb->uiNeighborAvail; SMB* pLeftMb = pCurMb - 1 ; SMB* pTopMb = pCurMb - iMbWidth; SMB* pLeftTopMb = pCurMb - iMbWidth - 1 ; SMB* iRightTopMb = pCurMb - iMbWidth + 1 ; SMVComponentUnit* pMvComp = &pMbCache->sMvComponents; if ((uiNeighborAvail & LEFT_MB_POS) && IS_SVC_INTER (pLeftMb->uiMbType)) { pMvComp->sMotionVectorCache[ 6] = pLeftMb->sMv[ 3]; pMvComp->sMotionVectorCache[12] = pLeftMb->sMv[ 7]; pMvComp->sMotionVectorCache[18] = pLeftMb->sMv[11]; pMvComp->sMotionVectorCache[24] = pLeftMb->sMv[15]; pMvComp->iRefIndexCache[ 6] = pLeftMb->pRefIndex[1]; pMvComp->iRefIndexCache[12] = pLeftMb->pRefIndex[1]; pMvComp->iRefIndexCache[18] = pLeftMb->pRefIndex[3]; pMvComp->iRefIndexCache[24] = pLeftMb->pRefIndex[3]; pMbCache->iSadCost[3] = pLeftMb->pSadCost[0]; if (pLeftMb->uiMbType == MB_TYPE_SKIP) { pMbCache->bMbTypeSkip[3] = 1; pMbCache->iSadCostSkip[3] = pMbCache->pEncSad[-1]; } else { pMbCache->bMbTypeSkip[3] = 0; pMbCache->iSadCostSkip[3] = 0; } } else { //avail or non-inter ST32 (&pMvComp->sMotionVectorCache[ 6], 0); ST32 (&pMvComp->sMotionVectorCache[12], 0); ST32 (&pMvComp->sMotionVectorCache[18], 0); ST32 (&pMvComp->sMotionVectorCache[24], 0); pMvComp->iRefIndexCache[ 6] = pMvComp->iRefIndexCache[12] = pMvComp->iRefIndexCache[18] = pMvComp->iRefIndexCache[24] = (uiNeighborAvail & LEFT_MB_POS) ? REF_NOT_IN_LIST : REF_NOT_AVAIL; pMbCache->iSadCost[3] = 0; pMbCache->bMbTypeSkip[3] = 0; pMbCache->iSadCostSkip[3] = 0; } if ((uiNeighborAvail & TOP_MB_POS) && IS_SVC_INTER (pTopMb->uiMbType)) { //TOP MB ST64 (&pMvComp->sMotionVectorCache[1], LD64 (&pTopMb->sMv[12])); ST64 (&pMvComp->sMotionVectorCache[3], LD64 (&pTopMb->sMv[14])); pMvComp->iRefIndexCache[1] = pTopMb->pRefIndex[2]; pMvComp->iRefIndexCache[2] = pTopMb->pRefIndex[2]; pMvComp->iRefIndexCache[3] = pTopMb->pRefIndex[3]; pMvComp->iRefIndexCache[4] = pTopMb->pRefIndex[3]; pMbCache->iSadCost[1] = pTopMb->pSadCost[0]; if (pTopMb->uiMbType == MB_TYPE_SKIP) { pMbCache->bMbTypeSkip[1] = 1; pMbCache->iSadCostSkip[1] = pMbCache->pEncSad[-iMbWidth]; } else { pMbCache->bMbTypeSkip[1] = 0; pMbCache->iSadCostSkip[1] = 0; } } else { //unavail ST64 (&pMvComp->sMotionVectorCache[1], 0); ST64 (&pMvComp->sMotionVectorCache[3], 0); pMvComp->iRefIndexCache[1] = pMvComp->iRefIndexCache[2] = pMvComp->iRefIndexCache[3] = pMvComp->iRefIndexCache[4] = (uiNeighborAvail & TOP_MB_POS) ? REF_NOT_IN_LIST : REF_NOT_AVAIL; pMbCache->iSadCost[1] = 0; pMbCache->bMbTypeSkip[1] = 0; pMbCache->iSadCostSkip[1] = 0; } if ((uiNeighborAvail & TOPLEFT_MB_POS) && IS_SVC_INTER (pLeftTopMb->uiMbType)) { //LEFT_TOP MB pMvComp->sMotionVectorCache[0] = pLeftTopMb->sMv[15]; pMvComp->iRefIndexCache[0] = pLeftTopMb->pRefIndex[3]; pMbCache->iSadCost[0] = pLeftTopMb->pSadCost[0]; if (pLeftTopMb->uiMbType == MB_TYPE_SKIP) { pMbCache->bMbTypeSkip[0] = 1; pMbCache->iSadCostSkip[0] = pMbCache->pEncSad[-iMbWidth - 1]; } else { pMbCache->bMbTypeSkip[0] = 0; pMbCache->iSadCostSkip[0] = 0; } } else { //unavail ST32 (&pMvComp->sMotionVectorCache[0], 0); pMvComp->iRefIndexCache[0] = (uiNeighborAvail & TOPLEFT_MB_POS) ? REF_NOT_IN_LIST : REF_NOT_AVAIL; pMbCache->iSadCost[0] = 0; pMbCache->bMbTypeSkip[0] = 0; pMbCache->iSadCostSkip[0] = 0; } if ((uiNeighborAvail & TOPRIGHT_MB_POS) && IS_SVC_INTER (iRightTopMb->uiMbType)) { //RIGHT_TOP MB pMvComp->sMotionVectorCache[5] = iRightTopMb->sMv[12]; pMvComp->iRefIndexCache[5] = iRightTopMb->pRefIndex[2]; pMbCache->iSadCost[2] = iRightTopMb->pSadCost[0]; if (iRightTopMb->uiMbType == MB_TYPE_SKIP) { pMbCache->bMbTypeSkip[2] = 1; pMbCache->iSadCostSkip[2] = pMbCache->pEncSad[-iMbWidth + 1]; } else { pMbCache->bMbTypeSkip[2] = 0; pMbCache->iSadCostSkip[2] = 0; } } else { //unavail ST32 (&pMvComp->sMotionVectorCache[5], 0); pMvComp->iRefIndexCache[5] = (uiNeighborAvail & TOPRIGHT_MB_POS) ? REF_NOT_IN_LIST : REF_NOT_AVAIL; pMbCache->iSadCost[2] = 0; pMbCache->bMbTypeSkip[2] = 0; pMbCache->iSadCostSkip[2] = 0; } //right-top 4*4 pBlock unavailable ST32 (&pMvComp->sMotionVectorCache[ 9], 0); ST32 (&pMvComp->sMotionVectorCache[21], 0); ST32 (&pMvComp->sMotionVectorCache[11], 0); ST32 (&pMvComp->sMotionVectorCache[17], 0); ST32 (&pMvComp->sMotionVectorCache[23], 0); pMvComp->iRefIndexCache[ 9] = pMvComp->iRefIndexCache[11] = pMvComp->iRefIndexCache[17] = pMvComp->iRefIndexCache[21] = pMvComp->iRefIndexCache[23] = REF_NOT_AVAIL;} void FillNeighborCacheInterWithBGD (SMbCache* pMbCache, SMB* pCurMb, int32_t iMbWidth, int8_t* pVaaBgMbFlag) { uint32_t uiNeighborAvail = pCurMb->uiNeighborAvail; SMB* pLeftMb = pCurMb - 1 ; SMB* pTopMb = pCurMb - iMbWidth; SMB* pLeftTopMb = pCurMb - iMbWidth - 1 ; SMB* iRightTopMb = pCurMb - iMbWidth + 1 ; SMVComponentUnit* pMvComp = &pMbCache->sMvComponents; if ((uiNeighborAvail & LEFT_MB_POS) && IS_SVC_INTER (pLeftMb->uiMbType)) { pMvComp->sMotionVectorCache[ 6] = pLeftMb->sMv[ 3]; pMvComp->sMotionVectorCache[12] = pLeftMb->sMv[ 7]; pMvComp->sMotionVectorCache[18] = pLeftMb->sMv[11]; pMvComp->sMotionVectorCache[24] = pLeftMb->sMv[15]; pMvComp->iRefIndexCache[ 6] = pLeftMb->pRefIndex[1]; pMvComp->iRefIndexCache[12] = pLeftMb->pRefIndex[1]; pMvComp->iRefIndexCache[18] = pLeftMb->pRefIndex[3]; pMvComp->iRefIndexCache[24] = pLeftMb->pRefIndex[3]; pMbCache->iSadCost[3] = pLeftMb->pSadCost[0]; if (pLeftMb->uiMbType == MB_TYPE_SKIP && pVaaBgMbFlag[-1] == 0) { pMbCache->bMbTypeSkip[3] = 1; pMbCache->iSadCostSkip[3] = pMbCache->pEncSad[-1]; } else { pMbCache->bMbTypeSkip[3] = 0; pMbCache->iSadCostSkip[3] = 0; } } else { //avail or non-inter ST32 (&pMvComp->sMotionVectorCache[ 6], 0); ST32 (&pMvComp->sMotionVectorCache[12], 0); ST32 (&pMvComp->sMotionVectorCache[18], 0); ST32 (&pMvComp->sMotionVectorCache[24], 0); pMvComp->iRefIndexCache[ 6] = pMvComp->iRefIndexCache[12] = pMvComp->iRefIndexCache[18] = pMvComp->iRefIndexCache[24] = (uiNeighborAvail & LEFT_MB_POS) ? REF_NOT_IN_LIST : REF_NOT_AVAIL; pMbCache->iSadCost[3] = 0; pMbCache->bMbTypeSkip[3] = 0; pMbCache->iSadCostSkip[3] = 0; } if ((uiNeighborAvail & TOP_MB_POS) && IS_SVC_INTER (pTopMb->uiMbType)) { //TOP MB ST64 (&pMvComp->sMotionVectorCache[1], LD64 (&pTopMb->sMv[12])); ST64 (&pMvComp->sMotionVectorCache[3], LD64 (&pTopMb->sMv[14])); pMvComp->iRefIndexCache[1] = pTopMb->pRefIndex[2]; pMvComp->iRefIndexCache[2] = pTopMb->pRefIndex[2]; pMvComp->iRefIndexCache[3] = pTopMb->pRefIndex[3]; pMvComp->iRefIndexCache[4] = pTopMb->pRefIndex[3]; pMbCache->iSadCost[1] = pTopMb->pSadCost[0]; if (pTopMb->uiMbType == MB_TYPE_SKIP && pVaaBgMbFlag[-iMbWidth] == 0) { pMbCache->bMbTypeSkip[1] = 1; pMbCache->iSadCostSkip[1] = pMbCache->pEncSad[-iMbWidth]; } else { pMbCache->bMbTypeSkip[1] = 0; pMbCache->iSadCostSkip[1] = 0; } } else { //unavail ST64 (&pMvComp->sMotionVectorCache[1], 0); ST64 (&pMvComp->sMotionVectorCache[3], 0); pMvComp->iRefIndexCache[1] = pMvComp->iRefIndexCache[2] = pMvComp->iRefIndexCache[3] = pMvComp->iRefIndexCache[4] = (uiNeighborAvail & TOP_MB_POS) ? REF_NOT_IN_LIST : REF_NOT_AVAIL; pMbCache->iSadCost[1] = 0; pMbCache->bMbTypeSkip[1] = 0; pMbCache->iSadCostSkip[1] = 0; } if ((uiNeighborAvail & TOPLEFT_MB_POS) && IS_SVC_INTER (pLeftTopMb->uiMbType)) { //LEFT_TOP MB pMvComp->sMotionVectorCache[0] = pLeftTopMb->sMv[15]; pMvComp->iRefIndexCache[0] = pLeftTopMb->pRefIndex[3]; pMbCache->iSadCost[0] = pLeftTopMb->pSadCost[0]; if (pLeftTopMb->uiMbType == MB_TYPE_SKIP && pVaaBgMbFlag[-iMbWidth - 1] == 0) { pMbCache->bMbTypeSkip[0] = 1; pMbCache->iSadCostSkip[0] = pMbCache->pEncSad[-iMbWidth - 1]; } else { pMbCache->bMbTypeSkip[0] = 0; pMbCache->iSadCostSkip[0] = 0; } } else { //unavail ST32 (&pMvComp->sMotionVectorCache[0], 0); pMvComp->iRefIndexCache[0] = (uiNeighborAvail & TOPLEFT_MB_POS) ? REF_NOT_IN_LIST : REF_NOT_AVAIL; pMbCache->iSadCost[0] = 0; pMbCache->bMbTypeSkip[0] = 0; pMbCache->iSadCostSkip[0] = 0; } if ((uiNeighborAvail & TOPRIGHT_MB_POS) && IS_SVC_INTER (iRightTopMb->uiMbType)) { //RIGHT_TOP MB pMvComp->sMotionVectorCache[5] = iRightTopMb->sMv[12]; pMvComp->iRefIndexCache[5] = iRightTopMb->pRefIndex[2]; pMbCache->iSadCost[2] = iRightTopMb->pSadCost[0]; if (iRightTopMb->uiMbType == MB_TYPE_SKIP && pVaaBgMbFlag[-iMbWidth + 1] == 0) { pMbCache->bMbTypeSkip[2] = 1; pMbCache->iSadCostSkip[2] = pMbCache->pEncSad[-iMbWidth + 1]; } else { pMbCache->bMbTypeSkip[2] = 0; pMbCache->iSadCostSkip[2] = 0; } } else { //unavail ST32 (&pMvComp->sMotionVectorCache[5], 0); pMvComp->iRefIndexCache[5] = (uiNeighborAvail & TOPRIGHT_MB_POS) ? REF_NOT_IN_LIST : REF_NOT_AVAIL; pMbCache->iSadCost[2] = 0; pMbCache->bMbTypeSkip[2] = 0; pMbCache->iSadCostSkip[2] = 0; } //right-top 4*4 pBlock unavailable ST32 (&pMvComp->sMotionVectorCache[ 9], 0); ST32 (&pMvComp->sMotionVectorCache[21], 0); ST32 (&pMvComp->sMotionVectorCache[11], 0); ST32 (&pMvComp->sMotionVectorCache[17], 0); ST32 (&pMvComp->sMotionVectorCache[23], 0); pMvComp->iRefIndexCache[ 9] = pMvComp->iRefIndexCache[11] = pMvComp->iRefIndexCache[17] = pMvComp->iRefIndexCache[21] = pMvComp->iRefIndexCache[23] = REF_NOT_AVAIL;} void InitFillNeighborCacheInterFunc (SWelsFuncPtrList* pFuncList, const int32_t kiFlag) { pFuncList->pfFillInterNeighborCache = kiFlag ? FillNeighborCacheInterWithBGD : FillNeighborCacheInterWithoutBGD;} void UpdateMbMv_c (SMVUnitXY* pMvBuffer, const SMVUnitXY ksMv) { int32_t k = 0; for (; k < MB_BLOCK4x4_NUM; k += 4) { pMvBuffer[k ] = pMvBuffer[k + 1] = pMvBuffer[k + 2] = pMvBuffer[k + 3] = ksMv; }} uint8_t MdInterAnalysisVaaInfo_c (int32_t* pSad8x8) { int32_t iSadBlock[4], iAverageSadBlock[4]; int32_t iAverageSad, iVarianceSad; iSadBlock[0] = pSad8x8[0]; iAverageSad = iSadBlock[0]; iSadBlock[1] = pSad8x8[1]; iAverageSad += iSadBlock[1]; iSadBlock[2] = pSad8x8[2]; iAverageSad += iSadBlock[2]; iSadBlock[3] = pSad8x8[3]; iAverageSad += iSadBlock[3]; iAverageSad = iAverageSad >> 2; iAverageSadBlock[0] = (iSadBlock[0] >> 6) - (iAverageSad >> 6); iVarianceSad = iAverageSadBlock[0] * iAverageSadBlock[0]; iAverageSadBlock[1] = (iSadBlock[1] >> 6) - (iAverageSad >> 6); iVarianceSad += iAverageSadBlock[1] * iAverageSadBlock[1]; iAverageSadBlock[2] = (iSadBlock[2] >> 6) - (iAverageSad >> 6); iVarianceSad += iAverageSadBlock[2] * iAverageSadBlock[2]; iAverageSadBlock[3] = (iSadBlock[3] >> 6) - (iAverageSad >> 6); iVarianceSad += iAverageSadBlock[3] * iAverageSadBlock[3]; if (iVarianceSad < INTER_VARIANCE_SAD_THRESHOLD) { return 15; } uint8_t uiMbSign = 0; if (iSadBlock[0] > iAverageSad) uiMbSign |= 0x08; if (iSadBlock[1] > iAverageSad) uiMbSign |= 0x04; if (iSadBlock[2] > iAverageSad) uiMbSign |= 0x02; if (iSadBlock[3] > iAverageSad) uiMbSign |= 0x01; return (uiMbSign);} int32_t AnalysisVaaInfoIntra_c (uint8_t* pDataY, const int32_t kiLineSize) { ENFORCE_STACK_ALIGN_1D (uint16_t, uiAvgBlock, 16, 16) uint16_t* pBlock = &uiAvgBlock[0]; uint8_t* pEncData = pDataY; const int32_t kiLineSize2 = kiLineSize << 1; const int32_t kiLineSize3 = kiLineSize + kiLineSize2; const int32_t kiLineSize4 = kiLineSize << 2; int32_t i = 0, j = 0, num = 0; int32_t iSumAvg = 0, iSumSqr = 0; // analysis_vaa_info_intra_core_c( pDataY, iLineSize, pBlock ); for (; j < 16; j += 4) { num = 0; for (i = 0; i < 16; i += 4, num ++) { pBlock[num] = pEncData[i ] + pEncData[i + 1 ] + pEncData[i + 2 ] + pEncData[i + 3 ]; pBlock[num] += pEncData[i + kiLineSize ] + pEncData[i + kiLineSize + 1] + pEncData[i + kiLineSize + 2] + pEncData[i + kiLineSize + 3]; pBlock[num] += pEncData[i + kiLineSize2] + pEncData[i + kiLineSize2 + 1] + pEncData[i + kiLineSize2 + 2] + pEncData[i + kiLineSize2 + 3]; pBlock[num] += pEncData[i + kiLineSize3] + pEncData[i + kiLineSize3 + 1] + pEncData[i + kiLineSize3 + 2] + pEncData[i + kiLineSize3 + 3]; pBlock[num] >>= 4; } pBlock += 4; pEncData += kiLineSize4; } pBlock = &uiAvgBlock[0]; i = 4; for (; i > 0; --i) { iSumAvg += pBlock[0] + pBlock[1] + pBlock[2] + pBlock[3]; iSumSqr += pBlock[0] * pBlock[0] + pBlock[1] * pBlock[1] + pBlock[2] * pBlock[2] + pBlock[3] * pBlock[3]; pBlock += 4; } return /*variance =*/ (iSumSqr - ((iSumAvg * iSumAvg) >> 4));} // for pfGetVarianceFromIntraVaa function ptr adaptive by CPU features, 6/7/2010void InitIntraAnalysisVaaInfo (SWelsFuncPtrList* pFuncList, const uint32_t kuiCpuFlag) { pFuncList->pfGetVarianceFromIntraVaa = AnalysisVaaInfoIntra_c; pFuncList->pfGetMbSignFromInterVaa = MdInterAnalysisVaaInfo_c; pFuncList->pfUpdateMbMv = UpdateMbMv_c; #if defined(X86_ASM) if ((kuiCpuFlag & WELS_CPU_SSE2) == WELS_CPU_SSE2) { pFuncList->pfGetVarianceFromIntraVaa = AnalysisVaaInfoIntra_sse2; pFuncList->pfGetMbSignFromInterVaa = MdInterAnalysisVaaInfo_sse2; pFuncList->pfUpdateMbMv = UpdateMbMv_sse2; } if ((kuiCpuFlag & WELS_CPU_SSSE3) == WELS_CPU_SSSE3) { pFuncList->pfGetVarianceFromIntraVaa = AnalysisVaaInfoIntra_ssse3; } if ((kuiCpuFlag & WELS_CPU_SSE41) == WELS_CPU_SSE41) { pFuncList->pfGetMbSignFromInterVaa = MdInterAnalysisVaaInfo_sse41; }#endif//X86_ASM} bool MdIntraAnalysisVaaInfo (sWelsEncCtx* pEncCtx, uint8_t* pEncMb) { SDqLayer* pCurDqLayer = pEncCtx->pCurDqLayer; const int32_t kiLineSize = pCurDqLayer->iEncStride[0]; const int32_t kiVariance = pEncCtx->pFuncList->pfGetVarianceFromIntraVaa (pEncMb, kiLineSize); return (kiVariance >= INTRA_VARIANCE_SAD_THRESHOLD);} Lines 1–500 of 906. Load more
/*! * \copy * Copyright (c) 2009-2013, Cisco Systems * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * * * \file md.c * * \brief mode decision * * \date 2009.05.14 Created * ************************************************************************************* */ #include "ls_defines.h" #include "md.h" #include "cpu_core.h" #include "svc_enc_golomb.h" namespace WelsEnc { #define INTRA_VARIANCE_SAD_THRESHOLD 150 #define INTER_VARIANCE_SAD_THRESHOLD 20 //fill cache of neighbor MB, containing pNonZeroCount, sample_avail, pIntra4x4PredMode void FillNeighborCacheIntra (SMbCache* pMbCache, SMB* pCurMb, int32_t iMbWidth) { uint32_t uiNeighborAvail = pCurMb->uiNeighborAvail; uint32_t uiNeighborIntra = 0; if (uiNeighborAvail & LEFT_MB_POS) { //LEFT MB int8_t* pLeftMbNonZeroCount = pCurMb->pNonZeroCount - MB_LUMA_CHROMA_BLOCK4x4_NUM; pMbCache->iNonZeroCoeffCount[8] = pLeftMbNonZeroCount[ 3]; pMbCache->iNonZeroCoeffCount[16] = pLeftMbNonZeroCount[ 7]; pMbCache->iNonZeroCoeffCount[24] = pLeftMbNonZeroCount[11]; pMbCache->iNonZeroCoeffCount[32] = pLeftMbNonZeroCount[15]; pMbCache->iNonZeroCoeffCount[ 13] = pLeftMbNonZeroCount[17]; pMbCache->iNonZeroCoeffCount[21] = pLeftMbNonZeroCount[21]; pMbCache->iNonZeroCoeffCount[37] = pLeftMbNonZeroCount[19]; pMbCache->iNonZeroCoeffCount[45] = pLeftMbNonZeroCount[23]; uiNeighborIntra |= LEFT_MB_POS; if (IS_INTRA4x4 ((pCurMb - 1)->uiMbType)) { int8_t* pLeftMbIntra4x4PredMode = pCurMb->pIntra4x4PredMode - INTRA_4x4_MODE_NUM; pMbCache->iIntraPredMode[8] = pLeftMbIntra4x4PredMode[4]; pMbCache->iIntraPredMode[16] = pLeftMbIntra4x4PredMode[5]; pMbCache->iIntraPredMode[24] = pLeftMbIntra4x4PredMode[6]; pMbCache->iIntraPredMode[32] = pLeftMbIntra4x4PredMode[3]; } else { // if ( 0 == constrained_intra_pred_flag || IS_INTRA16x16((pCurMb-1)->uiMbType )) pMbCache->iIntraPredMode[8] = pMbCache->iIntraPredMode[16] = pMbCache->iIntraPredMode[24] = pMbCache->iIntraPredMode[32] = 2; //DC } } else { pMbCache->iNonZeroCoeffCount[ 8] = pMbCache->iNonZeroCoeffCount[16] = pMbCache->iNonZeroCoeffCount[24] = pMbCache->iNonZeroCoeffCount[32] = -1;//unavailable pMbCache->iNonZeroCoeffCount[13] = pMbCache->iNonZeroCoeffCount[21] = pMbCache->iNonZeroCoeffCount[37] = pMbCache->iNonZeroCoeffCount[45] = -1;//unavailable pMbCache->iIntraPredMode[8] = pMbCache->iIntraPredMode[16] = pMbCache->iIntraPredMode[24] = pMbCache->iIntraPredMode[32] = -1;//unavailable } if (uiNeighborAvail & TOP_MB_POS) { //TOP MB SMB* pTopMb = pCurMb - iMbWidth; ST32 (&pMbCache->iNonZeroCoeffCount[1], LD32 (&pTopMb->pNonZeroCount[12])); ST16 (&pMbCache->iNonZeroCoeffCount[6], LD16 (&pTopMb->pNonZeroCount[20])); ST16 (&pMbCache->iNonZeroCoeffCount[30], LD16 (&pTopMb->pNonZeroCount[22])); uiNeighborIntra |= TOP_MB_POS; if (IS_INTRA4x4 (pTopMb->uiMbType)) { ST32 (pMbCache->iIntraPredMode + 1, LD32 (&pTopMb->pIntra4x4PredMode[0])); } else { // if ( 0 == constrained_intra_pred_flag || IS_INTRA16x16( pTopMb->uiMbType )) const uint32_t kuiDc32 = 0x02020202; ST32 (pMbCache->iIntraPredMode + 1 , kuiDc32); } } else { const uint32_t kuiUnavail32 = 0xffffffff; ST32 (pMbCache->iIntraPredMode + 1 , kuiUnavail32); ST32 (&pMbCache->iNonZeroCoeffCount[1], kuiUnavail32); ST16 (&pMbCache->iNonZeroCoeffCount[6], 0xffff); ST16 (&pMbCache->iNonZeroCoeffCount[30], 0xffff); } if (uiNeighborAvail & TOPLEFT_MB_POS) { uiNeighborIntra |= 0x04; } if (uiNeighborAvail & TOPRIGHT_MB_POS) { uiNeighborIntra |= 0x08; } pMbCache->uiNeighborIntra = uiNeighborIntra; } //fill cache of neighbor MB, containing motion_vector and uiRefIndex void FillNeighborCacheInterWithoutBGD (SMbCache* pMbCache, SMB* pCurMb, int32_t iMbWidth, int8_t* pVaaBgMbFlag) { uint32_t uiNeighborAvail = pCurMb->uiNeighborAvail; SMB* pLeftMb = pCurMb - 1 ; SMB* pTopMb = pCurMb - iMbWidth; SMB* pLeftTopMb = pCurMb - iMbWidth - 1 ; SMB* iRightTopMb = pCurMb - iMbWidth + 1 ; SMVComponentUnit* pMvComp = &pMbCache->sMvComponents; if ((uiNeighborAvail & LEFT_MB_POS) && IS_SVC_INTER (pLeftMb->uiMbType)) { pMvComp->sMotionVectorCache[ 6] = pLeftMb->sMv[ 3]; pMvComp->sMotionVectorCache[12] = pLeftMb->sMv[ 7]; pMvComp->sMotionVectorCache[18] = pLeftMb->sMv[11]; pMvComp->sMotionVectorCache[24] = pLeftMb->sMv[15]; pMvComp->iRefIndexCache[ 6] = pLeftMb->pRefIndex[1]; pMvComp->iRefIndexCache[12] = pLeftMb->pRefIndex[1]; pMvComp->iRefIndexCache[18] = pLeftMb->pRefIndex[3]; pMvComp->iRefIndexCache[24] = pLeftMb->pRefIndex[3]; pMbCache->iSadCost[3] = pLeftMb->pSadCost[0]; if (pLeftMb->uiMbType == MB_TYPE_SKIP) { pMbCache->bMbTypeSkip[3] = 1; pMbCache->iSadCostSkip[3] = pMbCache->pEncSad[-1]; } else { pMbCache->bMbTypeSkip[3] = 0; pMbCache->iSadCostSkip[3] = 0; } } else { //avail or non-inter ST32 (&pMvComp->sMotionVectorCache[ 6], 0); ST32 (&pMvComp->sMotionVectorCache[12], 0); ST32 (&pMvComp->sMotionVectorCache[18], 0); ST32 (&pMvComp->sMotionVectorCache[24], 0); pMvComp->iRefIndexCache[ 6] = pMvComp->iRefIndexCache[12] = pMvComp->iRefIndexCache[18] = pMvComp->iRefIndexCache[24] = (uiNeighborAvail & LEFT_MB_POS) ? REF_NOT_IN_LIST : REF_NOT_AVAIL; pMbCache->iSadCost[3] = 0; pMbCache->bMbTypeSkip[3] = 0; pMbCache->iSadCostSkip[3] = 0; } if ((uiNeighborAvail & TOP_MB_POS) && IS_SVC_INTER (pTopMb->uiMbType)) { //TOP MB ST64 (&pMvComp->sMotionVectorCache[1], LD64 (&pTopMb->sMv[12])); ST64 (&pMvComp->sMotionVectorCache[3], LD64 (&pTopMb->sMv[14])); pMvComp->iRefIndexCache[1] = pTopMb->pRefIndex[2]; pMvComp->iRefIndexCache[2] = pTopMb->pRefIndex[2]; pMvComp->iRefIndexCache[3] = pTopMb->pRefIndex[3]; pMvComp->iRefIndexCache[4] = pTopMb->pRefIndex[3]; pMbCache->iSadCost[1] = pTopMb->pSadCost[0]; if (pTopMb->uiMbType == MB_TYPE_SKIP) { pMbCache->bMbTypeSkip[1] = 1; pMbCache->iSadCostSkip[1] = pMbCache->pEncSad[-iMbWidth]; } else { pMbCache->bMbTypeSkip[1] = 0; pMbCache->iSadCostSkip[1] = 0; } } else { //unavail ST64 (&pMvComp->sMotionVectorCache[1], 0); ST64 (&pMvComp->sMotionVectorCache[3], 0); pMvComp->iRefIndexCache[1] = pMvComp->iRefIndexCache[2] = pMvComp->iRefIndexCache[3] = pMvComp->iRefIndexCache[4] = (uiNeighborAvail & TOP_MB_POS) ? REF_NOT_IN_LIST : REF_NOT_AVAIL; pMbCache->iSadCost[1] = 0; pMbCache->bMbTypeSkip[1] = 0; pMbCache->iSadCostSkip[1] = 0; } if ((uiNeighborAvail & TOPLEFT_MB_POS) && IS_SVC_INTER (pLeftTopMb->uiMbType)) { //LEFT_TOP MB pMvComp->sMotionVectorCache[0] = pLeftTopMb->sMv[15]; pMvComp->iRefIndexCache[0] = pLeftTopMb->pRefIndex[3]; pMbCache->iSadCost[0] = pLeftTopMb->pSadCost[0]; if (pLeftTopMb->uiMbType == MB_TYPE_SKIP) { pMbCache->bMbTypeSkip[0] = 1; pMbCache->iSadCostSkip[0] = pMbCache->pEncSad[-iMbWidth - 1]; } else { pMbCache->bMbTypeSkip[0] = 0; pMbCache->iSadCostSkip[0] = 0; } } else { //unavail ST32 (&pMvComp->sMotionVectorCache[0], 0); pMvComp->iRefIndexCache[0] = (uiNeighborAvail & TOPLEFT_MB_POS) ? REF_NOT_IN_LIST : REF_NOT_AVAIL; pMbCache->iSadCost[0] = 0; pMbCache->bMbTypeSkip[0] = 0; pMbCache->iSadCostSkip[0] = 0; } if ((uiNeighborAvail & TOPRIGHT_MB_POS) && IS_SVC_INTER (iRightTopMb->uiMbType)) { //RIGHT_TOP MB pMvComp->sMotionVectorCache[5] = iRightTopMb->sMv[12]; pMvComp->iRefIndexCache[5] = iRightTopMb->pRefIndex[2]; pMbCache->iSadCost[2] = iRightTopMb->pSadCost[0]; if (iRightTopMb->uiMbType == MB_TYPE_SKIP) { pMbCache->bMbTypeSkip[2] = 1; pMbCache->iSadCostSkip[2] = pMbCache->pEncSad[-iMbWidth + 1]; } else { pMbCache->bMbTypeSkip[2] = 0; pMbCache->iSadCostSkip[2] = 0; } } else { //unavail ST32 (&pMvComp->sMotionVectorCache[5], 0); pMvComp->iRefIndexCache[5] = (uiNeighborAvail & TOPRIGHT_MB_POS) ? REF_NOT_IN_LIST : REF_NOT_AVAIL; pMbCache->iSadCost[2] = 0; pMbCache->bMbTypeSkip[2] = 0; pMbCache->iSadCostSkip[2] = 0; } //right-top 4*4 pBlock unavailable ST32 (&pMvComp->sMotionVectorCache[ 9], 0); ST32 (&pMvComp->sMotionVectorCache[21], 0); ST32 (&pMvComp->sMotionVectorCache[11], 0); ST32 (&pMvComp->sMotionVectorCache[17], 0); ST32 (&pMvComp->sMotionVectorCache[23], 0); pMvComp->iRefIndexCache[ 9] = pMvComp->iRefIndexCache[11] = pMvComp->iRefIndexCache[17] = pMvComp->iRefIndexCache[21] = pMvComp->iRefIndexCache[23] = REF_NOT_AVAIL; } void FillNeighborCacheInterWithBGD (SMbCache* pMbCache, SMB* pCurMb, int32_t iMbWidth, int8_t* pVaaBgMbFlag) { uint32_t uiNeighborAvail = pCurMb->uiNeighborAvail; SMB* pLeftMb = pCurMb - 1 ; SMB* pTopMb = pCurMb - iMbWidth; SMB* pLeftTopMb = pCurMb - iMbWidth - 1 ; SMB* iRightTopMb = pCurMb - iMbWidth + 1 ; SMVComponentUnit* pMvComp = &pMbCache->sMvComponents; if ((uiNeighborAvail & LEFT_MB_POS) && IS_SVC_INTER (pLeftMb->uiMbType)) { pMvComp->sMotionVectorCache[ 6] = pLeftMb->sMv[ 3]; pMvComp->sMotionVectorCache[12] = pLeftMb->sMv[ 7]; pMvComp->sMotionVectorCache[18] = pLeftMb->sMv[11]; pMvComp->sMotionVectorCache[24] = pLeftMb->sMv[15]; pMvComp->iRefIndexCache[ 6] = pLeftMb->pRefIndex[1]; pMvComp->iRefIndexCache[12] = pLeftMb->pRefIndex[1]; pMvComp->iRefIndexCache[18] = pLeftMb->pRefIndex[3]; pMvComp->iRefIndexCache[24] = pLeftMb->pRefIndex[3]; pMbCache->iSadCost[3] = pLeftMb->pSadCost[0]; if (pLeftMb->uiMbType == MB_TYPE_SKIP && pVaaBgMbFlag[-1] == 0) { pMbCache->bMbTypeSkip[3] = 1; pMbCache->iSadCostSkip[3] = pMbCache->pEncSad[-1]; } else { pMbCache->bMbTypeSkip[3] = 0; pMbCache->iSadCostSkip[3] = 0; } } else { //avail or non-inter ST32 (&pMvComp->sMotionVectorCache[ 6], 0); ST32 (&pMvComp->sMotionVectorCache[12], 0); ST32 (&pMvComp->sMotionVectorCache[18], 0); ST32 (&pMvComp->sMotionVectorCache[24], 0); pMvComp->iRefIndexCache[ 6] = pMvComp->iRefIndexCache[12] = pMvComp->iRefIndexCache[18] = pMvComp->iRefIndexCache[24] = (uiNeighborAvail & LEFT_MB_POS) ? REF_NOT_IN_LIST : REF_NOT_AVAIL; pMbCache->iSadCost[3] = 0; pMbCache->bMbTypeSkip[3] = 0; pMbCache->iSadCostSkip[3] = 0; } if ((uiNeighborAvail & TOP_MB_POS) && IS_SVC_INTER (pTopMb->uiMbType)) { //TOP MB ST64 (&pMvComp->sMotionVectorCache[1], LD64 (&pTopMb->sMv[12])); ST64 (&pMvComp->sMotionVectorCache[3], LD64 (&pTopMb->sMv[14])); pMvComp->iRefIndexCache[1] = pTopMb->pRefIndex[2]; pMvComp->iRefIndexCache[2] = pTopMb->pRefIndex[2]; pMvComp->iRefIndexCache[3] = pTopMb->pRefIndex[3]; pMvComp->iRefIndexCache[4] = pTopMb->pRefIndex[3]; pMbCache->iSadCost[1] = pTopMb->pSadCost[0]; if (pTopMb->uiMbType == MB_TYPE_SKIP && pVaaBgMbFlag[-iMbWidth] == 0) { pMbCache->bMbTypeSkip[1] = 1; pMbCache->iSadCostSkip[1] = pMbCache->pEncSad[-iMbWidth]; } else { pMbCache->bMbTypeSkip[1] = 0; pMbCache->iSadCostSkip[1] = 0; } } else { //unavail ST64 (&pMvComp->sMotionVectorCache[1], 0); ST64 (&pMvComp->sMotionVectorCache[3], 0); pMvComp->iRefIndexCache[1] = pMvComp->iRefIndexCache[2] = pMvComp->iRefIndexCache[3] = pMvComp->iRefIndexCache[4] = (uiNeighborAvail & TOP_MB_POS) ? REF_NOT_IN_LIST : REF_NOT_AVAIL; pMbCache->iSadCost[1] = 0; pMbCache->bMbTypeSkip[1] = 0; pMbCache->iSadCostSkip[1] = 0; } if ((uiNeighborAvail & TOPLEFT_MB_POS) && IS_SVC_INTER (pLeftTopMb->uiMbType)) { //LEFT_TOP MB pMvComp->sMotionVectorCache[0] = pLeftTopMb->sMv[15]; pMvComp->iRefIndexCache[0] = pLeftTopMb->pRefIndex[3]; pMbCache->iSadCost[0] = pLeftTopMb->pSadCost[0]; if (pLeftTopMb->uiMbType == MB_TYPE_SKIP && pVaaBgMbFlag[-iMbWidth - 1] == 0) { pMbCache->bMbTypeSkip[0] = 1; pMbCache->iSadCostSkip[0] = pMbCache->pEncSad[-iMbWidth - 1]; } else { pMbCache->bMbTypeSkip[0] = 0; pMbCache->iSadCostSkip[0] = 0; } } else { //unavail ST32 (&pMvComp->sMotionVectorCache[0], 0); pMvComp->iRefIndexCache[0] = (uiNeighborAvail & TOPLEFT_MB_POS) ? REF_NOT_IN_LIST : REF_NOT_AVAIL; pMbCache->iSadCost[0] = 0; pMbCache->bMbTypeSkip[0] = 0; pMbCache->iSadCostSkip[0] = 0; } if ((uiNeighborAvail & TOPRIGHT_MB_POS) && IS_SVC_INTER (iRightTopMb->uiMbType)) { //RIGHT_TOP MB pMvComp->sMotionVectorCache[5] = iRightTopMb->sMv[12]; pMvComp->iRefIndexCache[5] = iRightTopMb->pRefIndex[2]; pMbCache->iSadCost[2] = iRightTopMb->pSadCost[0]; if (iRightTopMb->uiMbType == MB_TYPE_SKIP && pVaaBgMbFlag[-iMbWidth + 1] == 0) { pMbCache->bMbTypeSkip[2] = 1; pMbCache->iSadCostSkip[2] = pMbCache->pEncSad[-iMbWidth + 1]; } else { pMbCache->bMbTypeSkip[2] = 0; pMbCache->iSadCostSkip[2] = 0; } } else { //unavail ST32 (&pMvComp->sMotionVectorCache[5], 0); pMvComp->iRefIndexCache[5] = (uiNeighborAvail & TOPRIGHT_MB_POS) ? REF_NOT_IN_LIST : REF_NOT_AVAIL; pMbCache->iSadCost[2] = 0; pMbCache->bMbTypeSkip[2] = 0; pMbCache->iSadCostSkip[2] = 0; } //right-top 4*4 pBlock unavailable ST32 (&pMvComp->sMotionVectorCache[ 9], 0); ST32 (&pMvComp->sMotionVectorCache[21], 0); ST32 (&pMvComp->sMotionVectorCache[11], 0); ST32 (&pMvComp->sMotionVectorCache[17], 0); ST32 (&pMvComp->sMotionVectorCache[23], 0); pMvComp->iRefIndexCache[ 9] = pMvComp->iRefIndexCache[11] = pMvComp->iRefIndexCache[17] = pMvComp->iRefIndexCache[21] = pMvComp->iRefIndexCache[23] = REF_NOT_AVAIL; } void InitFillNeighborCacheInterFunc (SWelsFuncPtrList* pFuncList, const int32_t kiFlag) { pFuncList->pfFillInterNeighborCache = kiFlag ? FillNeighborCacheInterWithBGD : FillNeighborCacheInterWithoutBGD; } void UpdateMbMv_c (SMVUnitXY* pMvBuffer, const SMVUnitXY ksMv) { int32_t k = 0; for (; k < MB_BLOCK4x4_NUM; k += 4) { pMvBuffer[k ] = pMvBuffer[k + 1] = pMvBuffer[k + 2] = pMvBuffer[k + 3] = ksMv; } } uint8_t MdInterAnalysisVaaInfo_c (int32_t* pSad8x8) { int32_t iSadBlock[4], iAverageSadBlock[4]; int32_t iAverageSad, iVarianceSad; iSadBlock[0] = pSad8x8[0]; iAverageSad = iSadBlock[0]; iSadBlock[1] = pSad8x8[1]; iAverageSad += iSadBlock[1]; iSadBlock[2] = pSad8x8[2]; iAverageSad += iSadBlock[2]; iSadBlock[3] = pSad8x8[3]; iAverageSad += iSadBlock[3]; iAverageSad = iAverageSad >> 2; iAverageSadBlock[0] = (iSadBlock[0] >> 6) - (iAverageSad >> 6); iVarianceSad = iAverageSadBlock[0] * iAverageSadBlock[0]; iAverageSadBlock[1] = (iSadBlock[1] >> 6) - (iAverageSad >> 6); iVarianceSad += iAverageSadBlock[1] * iAverageSadBlock[1]; iAverageSadBlock[2] = (iSadBlock[2] >> 6) - (iAverageSad >> 6); iVarianceSad += iAverageSadBlock[2] * iAverageSadBlock[2]; iAverageSadBlock[3] = (iSadBlock[3] >> 6) - (iAverageSad >> 6); iVarianceSad += iAverageSadBlock[3] * iAverageSadBlock[3]; if (iVarianceSad < INTER_VARIANCE_SAD_THRESHOLD) { return 15; } uint8_t uiMbSign = 0; if (iSadBlock[0] > iAverageSad) uiMbSign |= 0x08; if (iSadBlock[1] > iAverageSad) uiMbSign |= 0x04; if (iSadBlock[2] > iAverageSad) uiMbSign |= 0x02; if (iSadBlock[3] > iAverageSad) uiMbSign |= 0x01; return (uiMbSign); } int32_t AnalysisVaaInfoIntra_c (uint8_t* pDataY, const int32_t kiLineSize) { ENFORCE_STACK_ALIGN_1D (uint16_t, uiAvgBlock, 16, 16) uint16_t* pBlock = &uiAvgBlock[0]; uint8_t* pEncData = pDataY; const int32_t kiLineSize2 = kiLineSize << 1; const int32_t kiLineSize3 = kiLineSize + kiLineSize2; const int32_t kiLineSize4 = kiLineSize << 2; int32_t i = 0, j = 0, num = 0; int32_t iSumAvg = 0, iSumSqr = 0; // analysis_vaa_info_intra_core_c( pDataY, iLineSize, pBlock ); for (; j < 16; j += 4) { num = 0; for (i = 0; i < 16; i += 4, num ++) { pBlock[num] = pEncData[i ] + pEncData[i + 1 ] + pEncData[i + 2 ] + pEncData[i + 3 ]; pBlock[num] += pEncData[i + kiLineSize ] + pEncData[i + kiLineSize + 1] + pEncData[i + kiLineSize + 2] + pEncData[i + kiLineSize + 3]; pBlock[num] += pEncData[i + kiLineSize2] + pEncData[i + kiLineSize2 + 1] + pEncData[i + kiLineSize2 + 2] + pEncData[i + kiLineSize2 + 3]; pBlock[num] += pEncData[i + kiLineSize3] + pEncData[i + kiLineSize3 + 1] + pEncData[i + kiLineSize3 + 2] + pEncData[i + kiLineSize3 + 3]; pBlock[num] >>= 4; } pBlock += 4; pEncData += kiLineSize4; } pBlock = &uiAvgBlock[0]; i = 4; for (; i > 0; --i) { iSumAvg += pBlock[0] + pBlock[1] + pBlock[2] + pBlock[3]; iSumSqr += pBlock[0] * pBlock[0] + pBlock[1] * pBlock[1] + pBlock[2] * pBlock[2] + pBlock[3] * pBlock[3]; pBlock += 4; } return /*variance =*/ (iSumSqr - ((iSumAvg * iSumAvg) >> 4)); } // for pfGetVarianceFromIntraVaa function ptr adaptive by CPU features, 6/7/2010 void InitIntraAnalysisVaaInfo (SWelsFuncPtrList* pFuncList, const uint32_t kuiCpuFlag) { pFuncList->pfGetVarianceFromIntraVaa = AnalysisVaaInfoIntra_c; pFuncList->pfGetMbSignFromInterVaa = MdInterAnalysisVaaInfo_c; pFuncList->pfUpdateMbMv = UpdateMbMv_c; #if defined(X86_ASM) if ((kuiCpuFlag & WELS_CPU_SSE2) == WELS_CPU_SSE2) { pFuncList->pfGetVarianceFromIntraVaa = AnalysisVaaInfoIntra_sse2; pFuncList->pfGetMbSignFromInterVaa = MdInterAnalysisVaaInfo_sse2; pFuncList->pfUpdateMbMv = UpdateMbMv_sse2; } if ((kuiCpuFlag & WELS_CPU_SSSE3) == WELS_CPU_SSSE3) { pFuncList->pfGetVarianceFromIntraVaa = AnalysisVaaInfoIntra_ssse3; } if ((kuiCpuFlag & WELS_CPU_SSE41) == WELS_CPU_SSE41) { pFuncList->pfGetMbSignFromInterVaa = MdInterAnalysisVaaInfo_sse41; } #endif//X86_ASM } bool MdIntraAnalysisVaaInfo (sWelsEncCtx* pEncCtx, uint8_t* pEncMb) { SDqLayer* pCurDqLayer = pEncCtx->pCurDqLayer; const int32_t kiLineSize = pCurDqLayer->iEncStride[0]; const int32_t kiVariance = pEncCtx->pFuncList->pfGetVarianceFromIntraVaa (pEncMb, kiLineSize); return (kiVariance >= INTRA_VARIANCE_SAD_THRESHOLD); }