add scene change detector for further extension

This commit is contained in:
volvet 2014-03-18 17:54:58 +08:00
parent 62be92cb08
commit d7b7419040
5 changed files with 113 additions and 114 deletions

View File

@ -604,7 +604,7 @@ void CWelsPreProcess::BilateralDenoising (SPicture* pSrc, const int32_t kiWidth,
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};

View File

@ -122,7 +122,8 @@ typedef enum {
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 ,

View File

@ -265,8 +265,9 @@ IStrategy* CVpFrameWork::CreateStrategy (EMethods m_eMethod, int32_t iCpuFlag) {
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));

View File

@ -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

View File

@ -44,29 +44,117 @@
#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);
}
private:
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(){
}
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:
void InitSadFuncs (SadFuncPtr& pfSadFunc, int32_t iCpuFlag);
private:
SadFuncPtr m_pfSad;
int32_t m_iCpuFlag;
SSceneChangeResult m_sSceneChangeParam;
T m_cDetector;
};
IStrategy * BuildSceneChangeDetection(EMethods eMethod, int32_t iCpuFlag);
WELSVP_NAMESPACE_END
#endif