shithub: openh264

Download patch

ref: 3238c913cc1ed0cc52a2d5dce5d2eed41d2fed3e
parent: 37e1c293e51b40f24f0a07c21cdfb9bf8d2ae451
parent: af522899bdecb3b770539dff222fd3b42885ec75
author: ruil2 <[email protected]>
date: Wed Mar 19 10:52:08 EDT 2014

Merge pull request #535 from volvet/add-scene-change-detector

Add scene change detector

--- a/codec/encoder/core/src/wels_preprocess.cpp
+++ b/codec/encoder/core/src/wels_preprocess.cpp
@@ -603,7 +603,7 @@
 
 bool CWelsPreProcess::DetectSceneChange (SPicture* pCurPicture, SPicture* pRefPicture) {
   bool bSceneChangeFlag = false;
-  int32_t iMethodIdx = METHOD_SCENE_CHANGE_DETECTION;
+  int32_t iMethodIdx = METHOD_SCENE_CHANGE_DETECTION_VIDEO;
   SSceneChangeResult sSceneChangeDetectResult = { SIMILAR_SCENE };
   SPixMap sSrcPixMap = {0};
   SPixMap sRefPixMap = {0};
--- a/codec/processing/interface/IWelsVP.h
+++ b/codec/processing/interface/IWelsVP.h
@@ -122,7 +122,8 @@
   METHOD_NULL              = 0,
   METHOD_COLORSPACE_CONVERT    ,//not support yet
   METHOD_DENOISE              ,
-  METHOD_SCENE_CHANGE_DETECTION ,
+  METHOD_SCENE_CHANGE_DETECTION_VIDEO ,
+  METHOD_SCENE_CHANGE_DETECTION_SCREEN ,
   METHOD_DOWNSAMPLE			  ,
   METHOD_VAA_STATISTICS        ,
   METHOD_BACKGROUND_DETECTION  ,
--- a/codec/processing/src/common/WelsFrameWork.cpp
+++ b/codec/processing/src/common/WelsFrameWork.cpp
@@ -265,8 +265,9 @@
   case METHOD_DENOISE:
     pStrategy = WelsDynamicCast (IStrategy*, new CDenoiser (iCpuFlag));
     break;
-  case METHOD_SCENE_CHANGE_DETECTION:
-    pStrategy = WelsDynamicCast (IStrategy*, new CSceneChangeDetection (iCpuFlag));
+  case METHOD_SCENE_CHANGE_DETECTION_VIDEO:
+  case METHOD_SCENE_CHANGE_DETECTION_SCREEN:
+    pStrategy = BuildSceneChangeDetection(m_eMethod, iCpuFlag);
     break;
   case METHOD_DOWNSAMPLE:
     pStrategy = WelsDynamicCast (IStrategy*, new CDownsampling (iCpuFlag));
--- a/codec/processing/src/scenechangedetection/SceneChangeDetection.cpp
+++ b/codec/processing/src/scenechangedetection/SceneChangeDetection.cpp
@@ -35,108 +35,17 @@
 
 WELSVP_NAMESPACE_BEGIN
 
-#define HIGH_MOTION_BLOCK_THRESHOLD 320
-#define SCENE_CHANGE_MOTION_RATIO	0.85f
-
-
-
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////
-
-CSceneChangeDetection::CSceneChangeDetection (int32_t iCpuFlag) {
-  m_iCpuFlag = iCpuFlag;
-  m_eMethod   = METHOD_SCENE_CHANGE_DETECTION;
-  m_pfSad   = NULL;
-  WelsMemset (&m_sSceneChangeParam, 0, sizeof (m_sSceneChangeParam));
-  InitSadFuncs (m_pfSad, m_iCpuFlag);
-}
-
-CSceneChangeDetection::~CSceneChangeDetection() {
-}
-
-EResult CSceneChangeDetection::Process (int32_t iType, SPixMap* pSrcPixMap, SPixMap* pRefPixMap) {
-  EResult eReturn = RET_INVALIDPARAM;
-
-  int32_t iWidth                  = pSrcPixMap->sRect.iRectWidth;
-  int32_t iHeight                 = pSrcPixMap->sRect.iRectHeight;
-  int32_t iBlock8x8Width      = iWidth  >> 3;
-  int32_t iBlock8x8Height	 = iHeight >> 3;
-  int32_t iBlock8x8Num       = iBlock8x8Width * iBlock8x8Height;
-  int32_t iSceneChangeThreshold = WelsStaticCast (int32_t, SCENE_CHANGE_MOTION_RATIO * iBlock8x8Num + 0.5f + PESN);
-
-  int32_t iBlockSad = 0;
-  int32_t iMotionBlockNum = 0;
-
-  uint8_t* pRefY = NULL, *pCurY = NULL;
-  int32_t iRefStride = 0, iCurStride = 0;
-  int32_t iRefRowStride = 0, iCurRowStride = 0;
-
-  uint8_t* pRefTmp = NULL, *pCurTmp = NULL;
-
-  pRefY = (uint8_t*)pRefPixMap->pPixel[0];
-  pCurY = (uint8_t*)pSrcPixMap->pPixel[0];
-
-  iRefStride  = pRefPixMap->iStride[0];
-  iCurStride  = pSrcPixMap->iStride[0];
-
-  iRefRowStride  = pRefPixMap->iStride[0] << 3;
-  iCurRowStride  = pSrcPixMap->iStride[0] << 3;
-
-  m_sSceneChangeParam.eSceneChangeIdc = SIMILAR_SCENE;
-
-  for (int32_t j = 0; j < iBlock8x8Height; j ++) {
-    pRefTmp	= pRefY;
-    pCurTmp 	= pCurY;
-
-    for (int32_t i = 0; i < iBlock8x8Width; i++) {
-      iBlockSad = m_pfSad (pRefTmp, iRefStride, pCurTmp, iCurStride);
-
-      iMotionBlockNum += (iBlockSad > HIGH_MOTION_BLOCK_THRESHOLD);
-
-      pRefTmp += 8;
-      pCurTmp += 8;
-    }
-
-    pRefY += iRefRowStride;
-    pCurY += iCurRowStride;
+IStrategy * BuildSceneChangeDetection(EMethods eMethod, int32_t iCpuFlag){
+  switch(eMethod){
+  case METHOD_SCENE_CHANGE_DETECTION_VIDEO:
+    return new CSceneChangeDetection<CSceneChangeDetectorVideo>(eMethod, iCpuFlag);
+    break;
+  case METHOD_SCENE_CHANGE_DETECTION_SCREEN:
+  default:
+    // not support yet
+    return NULL;
   }
-
-  if (iMotionBlockNum >= iSceneChangeThreshold) {
-    m_sSceneChangeParam.eSceneChangeIdc = LARGE_CHANGED_SCENE;
-  }
-
-  eReturn = RET_SUCCESS;
-
-  return eReturn;
 }
 
-
-EResult CSceneChangeDetection::Get (int32_t iType, void* pParam) {
-  if (pParam == NULL) {
-    return RET_INVALIDPARAM;
-  }
-
-  * (SSceneChangeResult*)pParam = m_sSceneChangeParam;
-
-  return RET_SUCCESS;
-}
-
-///////////////////////////////////////////////////////////////////////////////////////////////
-
-void CSceneChangeDetection::InitSadFuncs (SadFuncPtr& pfSad,  int32_t iCpuFlag) {
-  pfSad = WelsSampleSad8x8_c;
-
-#ifdef X86_ASM
-  if (iCpuFlag & WELS_CPU_SSE2) {
-    pfSad = WelsSampleSad8x8_sse21;
-  }
-#endif
-
-#ifdef HAVE_NEON
-  if (iCpuFlag & WELS_CPU_NEON) {
-    pfSad = WelsProcessingSampleSad8x8_neon;
-  }
-#endif
-}
-
-
 WELSVP_NAMESPACE_END
+
--- a/codec/processing/src/scenechangedetection/SceneChangeDetection.h
+++ b/codec/processing/src/scenechangedetection/SceneChangeDetection.h
@@ -44,28 +44,116 @@
 
 #include "util.h"
 #include "memory.h"
+#include "cpu.h"
 #include "WelsFrameWork.h"
 #include "IWelsVP.h"
 #include "SceneChangeDetectionCommon.h"
 
+#define HIGH_MOTION_BLOCK_THRESHOLD 320
+#define SCENE_CHANGE_MOTION_RATIO   0.85f
+
 WELSVP_NAMESPACE_BEGIN
 
+class CSceneChangeDetectorVideo {
+public:
+  CSceneChangeDetectorVideo(int32_t iCpuFlag) {
+    m_pfSad = WelsSampleSad8x8_c;
+#ifdef X86_ASM
+    if (iCpuFlag & WELS_CPU_SSE2){
+      m_pfSad = WelsSampleSad8x8_sse21;
+    }
+#endif
+#ifdef HAVE_NEON
+    if (iCpuFlag & WELS_CPU_NEON){
+      m_pfSad = WelsProcessingSampleSad8x8_neon;
+    }
+#endif
+  }
+  virtual ~CSceneChangeDetectorVideo() {
+  }
+  virtual int32_t operator () (uint8_t* pSrcY, int32_t iSrcStrideY, uint8_t* pRefY, int32_t iRefStrideY) {
+    return m_pfSad(pSrcY, iSrcStrideY, pRefY, iSrcStrideY);
+  }
+protected:
+  SadFuncPtr m_pfSad;
+};
+
+template<typename T>
 class CSceneChangeDetection : public IStrategy {
  public:
-  CSceneChangeDetection (int32_t iCpuFlag);
-  ~CSceneChangeDetection();
+  CSceneChangeDetection (EMethods eMethod, int32_t iCpuFlag): m_cDetector(iCpuFlag) {
+    m_eMethod   = eMethod;
+    WelsMemset (&m_sSceneChangeParam, 0, sizeof (m_sSceneChangeParam));
+  }
 
-  EResult Process (int32_t iType, SPixMap* pSrc, SPixMap* pRef);
-  EResult Get (int32_t iType, void* pParam);
+  ~CSceneChangeDetection(){
+  }
 
- private:
-  void InitSadFuncs (SadFuncPtr& pfSadFunc, int32_t iCpuFlag);
+  EResult Process (int32_t iType, SPixMap* pSrcPixMap, SPixMap* pRefPixMap){
+    EResult eReturn = RET_INVALIDPARAM;
+    int32_t iWidth                  = pSrcPixMap->sRect.iRectWidth;
+    int32_t iHeight                 = pSrcPixMap->sRect.iRectHeight;
+    int32_t iBlock8x8Width      = iWidth  >> 3;
+    int32_t iBlock8x8Height	 = iHeight >> 3;
+    int32_t iBlock8x8Num       = iBlock8x8Width * iBlock8x8Height;
+    int32_t iSceneChangeThreshold = WelsStaticCast (int32_t, SCENE_CHANGE_MOTION_RATIO * iBlock8x8Num + 0.5f + PESN);
+    int32_t iBlockSad = 0;
+    int32_t iMotionBlockNum = 0;
+    uint8_t* pRefY = NULL, *pCurY = NULL;
+    int32_t iRefStride = 0, iCurStride = 0;
+    int32_t iRefRowStride = 0, iCurRowStride = 0;
+    uint8_t* pRefTmp = NULL, *pCurTmp = NULL;
 
+    pRefY = (uint8_t*)pRefPixMap->pPixel[0];
+    pCurY = (uint8_t*)pSrcPixMap->pPixel[0];
+
+    iRefStride  = pRefPixMap->iStride[0];
+    iCurStride  = pSrcPixMap->iStride[0];
+
+    iRefRowStride  = pRefPixMap->iStride[0] << 3;
+    iCurRowStride  = pSrcPixMap->iStride[0] << 3;
+
+    m_sSceneChangeParam.eSceneChangeIdc = SIMILAR_SCENE;
+
+    for (int32_t j = 0; j < iBlock8x8Height; j ++) {
+      pRefTmp	= pRefY;
+      pCurTmp   = pCurY;
+
+      for (int32_t i = 0; i < iBlock8x8Width; i++) {
+        iBlockSad = m_cDetector(pRefTmp, iRefStride, pCurTmp, iCurStride);
+        iMotionBlockNum += (iBlockSad > HIGH_MOTION_BLOCK_THRESHOLD);
+
+        pRefTmp += 8;
+        pCurTmp += 8;
+      }
+
+      pRefY += iRefRowStride;
+      pCurY += iCurRowStride;
+    }
+
+    if (iMotionBlockNum >= iSceneChangeThreshold) {
+      m_sSceneChangeParam.eSceneChangeIdc = LARGE_CHANGED_SCENE;
+    }
+
+    eReturn = RET_SUCCESS;
+
+    return eReturn;
+  }
+
+  EResult Get (int32_t iType, void* pParam) {
+    if (pParam == NULL) {
+      return RET_INVALIDPARAM;
+    }
+    * (SSceneChangeResult*)pParam = m_sSceneChangeParam;
+    return RET_SUCCESS;
+  }
+
  private:
-  SadFuncPtr m_pfSad;
-  int32_t    m_iCpuFlag;
   SSceneChangeResult m_sSceneChangeParam;
+  T          m_cDetector;
 };
+
+IStrategy * BuildSceneChangeDetection(EMethods eMethod, int32_t iCpuFlag);
 
 WELSVP_NAMESPACE_END