shithub: openh264

Download patch

ref: 369f2fb88aac2bc6db6ee6eee1a7437efdadfa84
parent: b1b6bdc3b809a3442a6208da0578e217650a134a
parent: 4ced8a9edd02d044204d717cd5cb48affd4f53db
author: Licai Guo <[email protected]>
date: Wed Mar 26 06:24:35 EDT 2014

Merge pull request #582 from ruil2/vp_complexity

    add complexity calculation for screen content

--- a/codec/processing/interface/IWelsVP.h
+++ b/codec/processing/interface/IWelsVP.h
@@ -129,6 +129,7 @@
   METHOD_BACKGROUND_DETECTION  ,
   METHOD_ADAPTIVE_QUANT ,
   METHOD_COMPLEXITY_ANALYSIS   ,
+  METHOD_COMPLEXITY_ANALYSIS_SCREEN,
   METHOD_IMAGE_ROTATE		  ,
   METHOD_MASK
 } EMethods;
--- a/codec/processing/src/complexityanalysis/ComplexityAnalysis.cpp
+++ b/codec/processing/src/complexityanalysis/ComplexityAnalysis.cpp
@@ -31,6 +31,8 @@
  */
 
 #include "ComplexityAnalysis.h"
+#include "cpu.h"
+#include "macros.h"
 
 WELSVP_NAMESPACE_BEGIN
 
@@ -267,5 +269,202 @@
   }
 }
 
+
+CComplexityAnalysisScreen::CComplexityAnalysisScreen (int32_t iCpuFlag) {
+  m_eMethod   = METHOD_COMPLEXITY_ANALYSIS_SCREEN;
+  WelsMemset (&m_ComplexityAnalysisParam, 0, sizeof (m_ComplexityAnalysisParam));
+
+  m_pSadFunc = WelsSampleSad16x16_c;
+  m_pIntraFunc[0] = WelsI16x16LumaPredV_c;
+  m_pIntraFunc[1] = WelsI16x16LumaPredH_c;
+#ifdef X86_ASM
+  if (iCpuFlag & WELS_CPU_SSE2) {
+    m_pSadFunc = WelsSampleSad16x16_sse2;
+  }
+#endif
+}
+
+CComplexityAnalysisScreen::~CComplexityAnalysisScreen() {
+}
+
+EResult CComplexityAnalysisScreen::Process (int32_t nType, SPixMap* pSrc, SPixMap* pRef) {
+  bool bScrollFlag = m_ComplexityAnalysisParam.sScrollResult.bScrollDetectFlag;
+  int32_t iIdrFlag    = m_ComplexityAnalysisParam.iIdrFlag;
+  int32_t iScrollMvX = m_ComplexityAnalysisParam.sScrollResult.iScrollMvX;
+  int32_t iScrollMvY = m_ComplexityAnalysisParam.sScrollResult.iScrollMvY;
+
+  if (m_ComplexityAnalysisParam.iMbRowInGom <= 0)
+    return RET_INVALIDPARAM;
+  if (!iIdrFlag && pRef == NULL)
+    return RET_INVALIDPARAM;
+
+  if (iIdrFlag || pRef == NULL) {
+    GomComplexityAnalysisIntra (pSrc);
+  } else if (!bScrollFlag || ((iScrollMvX == 0) && (iScrollMvY == 0))) {
+    GomComplexityAnalysisInter (pSrc, pRef, 0);
+  } else {
+    GomComplexityAnalysisInter (pSrc, pRef, 1);;
+  }
+
+  return RET_SUCCESS;
+}
+
+
+EResult CComplexityAnalysisScreen::Set (int32_t nType, void* pParam) {
+  if (pParam == NULL)
+    return RET_INVALIDPARAM;
+
+  m_ComplexityAnalysisParam = * (SComplexityAnalysisScreenParam*)pParam;
+
+  return RET_SUCCESS;
+}
+
+EResult CComplexityAnalysisScreen::Get (int32_t nType, void* pParam) {
+  if (pParam == NULL)
+    return RET_INVALIDPARAM;
+
+  * (SComplexityAnalysisScreenParam*)pParam = m_ComplexityAnalysisParam;
+
+  return RET_SUCCESS;
+}
+
+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;
+}
+
+
+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;
+}
 
 WELSVP_NAMESPACE_END
--- a/codec/processing/src/complexityanalysis/ComplexityAnalysis.h
+++ b/codec/processing/src/complexityanalysis/ComplexityAnalysis.h
@@ -46,6 +46,7 @@
 #include "memory.h"
 #include "WelsFrameWork.h"
 #include "IWelsVP.h"
+#include "common.h"
 
 WELSVP_NAMESPACE_BEGIN
 
@@ -77,6 +78,30 @@
   PGOMSadFunc m_pfGomSad;
   SComplexityAnalysisParam m_sComplexityAnalysisParam;
 };
+
+
+//for screen content
+
+class CComplexityAnalysisScreen : public IStrategy
+{
+public:
+  CComplexityAnalysisScreen(int32_t cpu_flag);
+  ~CComplexityAnalysisScreen();
+
+  EResult Process(int32_t nType, SPixMap *src, SPixMap *ref);
+  EResult Set(int32_t nType, void *pParam);
+  EResult Get(int32_t nType, void *pParam);
+
+private:
+  void GomComplexityAnalysisIntra( SPixMap *pSrc );
+  void GomComplexityAnalysisInter( SPixMap *pSrc, SPixMap *pRef,bool bScrollFlag);
+
+private:
+  PSad16x16Func m_pSadFunc;
+  GetIntraPredPtr m_pIntraFunc[2];
+  SComplexityAnalysisScreenParam m_ComplexityAnalysisParam;
+};
+
 
 WELSVP_NAMESPACE_END