1 /*! 2 * \copy 3 * Copyright (c) 2011-2013, Cisco Systems 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 10 * * Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 13 * * Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in 15 * the documentation and/or other materials provided with the 16 * distribution. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 21 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 22 * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 24 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 26 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 28 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 * 31 * \file : SceneChangeDetection.h 32 * 33 * \brief : scene change detection class of wels video processor class 34 * 35 * \date : 2011/03/14 36 * 37 * \description : 1. rewrite the package code of scene change detection class 38 * 39 ************************************************************************************* 40 */ 41 42 #ifndef WELSVP_SCENECHANGEDETECTION_H 43 #define WELSVP_SCENECHANGEDETECTION_H 44 45 #include "util.h" 46 #include "memory.h" 47 #include "cpu.h" 48 #include "WelsFrameWork.h" 49 #include "IWelsVP.h" 50 #include "common.h" 51 52 #define HIGH_MOTION_BLOCK_THRESHOLD 320 53 #define SCENE_CHANGE_MOTION_RATIO_LARGE_VIDEO 0.85f 54 #define SCENE_CHANGE_MOTION_RATIO_MEDIUM 0.50f 55 #define SCENE_CHANGE_MOTION_RATIO_LARGE_SCREEN 0.80f 56 57 WELSVP_NAMESPACE_BEGIN 58 59 typedef struct { 60 int32_t iWidth; 61 int32_t iHeight; 62 int32_t iBlock8x8Width; 63 int32_t iBlock8x8Height; 64 uint8_t* pRefY; 65 uint8_t* pCurY; 66 int32_t iRefStride; 67 int32_t iCurStride; 68 uint8_t* pStaticBlockIdc; 69 } SLocalParam; 70 71 class CSceneChangeDetectorVideo { 72 public: CSceneChangeDetectorVideo(SSceneChangeResult & sParam,int32_t iCpuFlag)73 CSceneChangeDetectorVideo (SSceneChangeResult& sParam, int32_t iCpuFlag) : m_sParam (sParam) { 74 m_pfSad = WelsSampleSad8x8_c; 75 #ifdef X86_ASM 76 if (iCpuFlag & WELS_CPU_SSE2) { 77 m_pfSad = WelsSampleSad8x8_sse21; 78 } 79 #endif 80 #ifdef HAVE_NEON 81 if (iCpuFlag & WELS_CPU_NEON) { 82 m_pfSad = WelsProcessingSampleSad8x8_neon; 83 } 84 #endif 85 86 #ifdef HAVE_NEON_AARCH64 87 if (iCpuFlag & WELS_CPU_NEON) { 88 m_pfSad = WelsProcessingSampleSad8x8_AArch64_neon; 89 } 90 #endif 91 92 #ifdef HAVE_MMI 93 if (iCpuFlag & WELS_CPU_MMI) { 94 m_pfSad = WelsSampleSad8x8_mmi; 95 } 96 #endif 97 98 #ifdef HAVE_LASX 99 if (iCpuFlag & WELS_CPU_LASX) { 100 m_pfSad = WelsSampleSad8x8_lasx; 101 } 102 #endif 103 104 m_fSceneChangeMotionRatioLarge = SCENE_CHANGE_MOTION_RATIO_LARGE_VIDEO; 105 m_fSceneChangeMotionRatioMedium = SCENE_CHANGE_MOTION_RATIO_MEDIUM; 106 } ~CSceneChangeDetectorVideo()107 virtual ~CSceneChangeDetectorVideo() { 108 } operator()109 void operator() (SLocalParam& sLocalParam) { 110 int32_t iRefRowStride = 0, iCurRowStride = 0; 111 uint8_t* pRefY = sLocalParam.pRefY; 112 uint8_t* pCurY = sLocalParam.pCurY; 113 uint8_t* pRefTmp = NULL, *pCurTmp = NULL; 114 115 iRefRowStride = sLocalParam.iRefStride << 3; 116 iCurRowStride = sLocalParam.iCurStride << 3; 117 118 for (int32_t j = 0; j < sLocalParam.iBlock8x8Height; j++) { 119 pRefTmp = pRefY; 120 pCurTmp = pCurY; 121 for (int32_t i = 0; i < sLocalParam.iBlock8x8Width; i++) { 122 int32_t iSad = m_pfSad (pCurTmp, sLocalParam.iCurStride, pRefTmp, sLocalParam.iRefStride); 123 m_sParam.iMotionBlockNum += iSad > HIGH_MOTION_BLOCK_THRESHOLD; 124 pRefTmp += 8; 125 pCurTmp += 8; 126 } 127 pRefY += iRefRowStride; 128 pCurY += iCurRowStride; 129 } 130 } GetSceneChangeMotionRatioLarge()131 float GetSceneChangeMotionRatioLarge() const { 132 return m_fSceneChangeMotionRatioLarge; 133 } GetSceneChangeMotionRatioMedium()134 float GetSceneChangeMotionRatioMedium() const { 135 return m_fSceneChangeMotionRatioMedium; 136 } 137 protected: 138 SadFuncPtr m_pfSad; 139 SSceneChangeResult& m_sParam; 140 float m_fSceneChangeMotionRatioLarge; 141 float m_fSceneChangeMotionRatioMedium; 142 }; 143 144 class CSceneChangeDetectorScreen : public CSceneChangeDetectorVideo { 145 public: CSceneChangeDetectorScreen(SSceneChangeResult & sParam,int32_t iCpuFlag)146 CSceneChangeDetectorScreen (SSceneChangeResult& sParam, int32_t iCpuFlag) : CSceneChangeDetectorVideo (sParam, 147 iCpuFlag) { 148 m_fSceneChangeMotionRatioLarge = SCENE_CHANGE_MOTION_RATIO_LARGE_SCREEN; 149 m_fSceneChangeMotionRatioMedium = SCENE_CHANGE_MOTION_RATIO_MEDIUM; 150 } ~CSceneChangeDetectorScreen()151 virtual ~CSceneChangeDetectorScreen() { 152 } operator()153 void operator() (SLocalParam& sLocalParam) { 154 bool bScrollDetectFlag = m_sParam.sScrollResult.bScrollDetectFlag; 155 int32_t iScrollMvX = m_sParam.sScrollResult.iScrollMvX; 156 int32_t iScrollMvY = m_sParam.sScrollResult.iScrollMvY; 157 158 int32_t iRefRowStride = 0, iCurRowStride = 0; 159 uint8_t* pRefY = sLocalParam.pRefY; 160 uint8_t* pCurY = sLocalParam.pCurY; 161 uint8_t* pRefTmp = NULL, *pCurTmp = NULL; 162 int32_t iWidth = sLocalParam.iWidth; 163 int32_t iHeight = sLocalParam.iHeight; 164 165 iRefRowStride = sLocalParam.iRefStride << 3; 166 iCurRowStride = sLocalParam.iCurStride << 3; 167 168 for (int32_t j = 0; j < sLocalParam.iBlock8x8Height; j++) { 169 pRefTmp = pRefY; 170 pCurTmp = pCurY; 171 for (int32_t i = 0; i < sLocalParam.iBlock8x8Width; i++) { 172 int32_t iBlockPointX = i << 3; 173 int32_t iBlockPointY = j << 3; 174 uint8_t uiBlockIdcTmp = NO_STATIC; 175 int32_t iSad = m_pfSad (pCurTmp, sLocalParam.iCurStride, pRefTmp, sLocalParam.iRefStride); 176 if (iSad == 0) { 177 uiBlockIdcTmp = COLLOCATED_STATIC; 178 } else if (bScrollDetectFlag && (!iScrollMvX || !iScrollMvY) && (iBlockPointX + iScrollMvX >= 0) 179 && (iBlockPointX + iScrollMvX <= iWidth - 8) && 180 (iBlockPointY + iScrollMvY >= 0) && (iBlockPointY + iScrollMvY <= iHeight - 8)) { 181 uint8_t* pRefTmpScroll = pRefTmp + iScrollMvY * sLocalParam.iRefStride + iScrollMvX; 182 int32_t iSadScroll = m_pfSad (pCurTmp, sLocalParam.iCurStride, pRefTmpScroll, sLocalParam.iRefStride); 183 184 if (iSadScroll == 0) { 185 uiBlockIdcTmp = SCROLLED_STATIC; 186 } else { 187 m_sParam.iFrameComplexity += iSad; 188 m_sParam.iMotionBlockNum += iSad > HIGH_MOTION_BLOCK_THRESHOLD; 189 } 190 } else { 191 m_sParam.iFrameComplexity += iSad; 192 m_sParam.iMotionBlockNum += iSad > HIGH_MOTION_BLOCK_THRESHOLD; 193 } 194 * (sLocalParam.pStaticBlockIdc) ++ = uiBlockIdcTmp; 195 pRefTmp += 8; 196 pCurTmp += 8; 197 } 198 pRefY += iRefRowStride; 199 pCurY += iCurRowStride; 200 } 201 } 202 }; 203 204 template<typename T> 205 class CSceneChangeDetection : public IStrategy { 206 public: CSceneChangeDetection(EMethods eMethod,int32_t iCpuFlag)207 CSceneChangeDetection (EMethods eMethod, int32_t iCpuFlag): m_cDetector (m_sSceneChangeParam, iCpuFlag) { 208 m_eMethod = eMethod; 209 WelsMemset (&m_sSceneChangeParam, 0, sizeof (m_sSceneChangeParam)); 210 } 211 ~CSceneChangeDetection()212 ~CSceneChangeDetection() { 213 } 214 Process(int32_t iType,SPixMap * pSrcPixMap,SPixMap * pRefPixMap)215 EResult Process (int32_t iType, SPixMap* pSrcPixMap, SPixMap* pRefPixMap) { 216 EResult eReturn = RET_INVALIDPARAM; 217 218 m_sLocalParam.iWidth = pSrcPixMap->sRect.iRectWidth; 219 m_sLocalParam.iHeight = pSrcPixMap->sRect.iRectHeight; 220 m_sLocalParam.iBlock8x8Width = m_sLocalParam.iWidth >> 3; 221 m_sLocalParam.iBlock8x8Height = m_sLocalParam.iHeight >> 3; 222 m_sLocalParam.pRefY = (uint8_t*)pRefPixMap->pPixel[0]; 223 m_sLocalParam.pCurY = (uint8_t*)pSrcPixMap->pPixel[0]; 224 m_sLocalParam.iRefStride = pRefPixMap->iStride[0]; 225 m_sLocalParam.iCurStride = pSrcPixMap->iStride[0]; 226 m_sLocalParam.pStaticBlockIdc = m_sSceneChangeParam.pStaticBlockIdc; 227 228 int32_t iBlock8x8Num = m_sLocalParam.iBlock8x8Width * m_sLocalParam.iBlock8x8Height; 229 int32_t iSceneChangeThresholdLarge = WelsStaticCast (int32_t, 230 m_cDetector.GetSceneChangeMotionRatioLarge() * iBlock8x8Num + 0.5f + PESN); 231 int32_t iSceneChangeThresholdMedium = WelsStaticCast (int32_t, 232 m_cDetector.GetSceneChangeMotionRatioMedium() * iBlock8x8Num + 0.5f + PESN); 233 234 m_sSceneChangeParam.iMotionBlockNum = 0; 235 m_sSceneChangeParam.iFrameComplexity = 0; 236 m_sSceneChangeParam.eSceneChangeIdc = SIMILAR_SCENE; 237 238 m_cDetector (m_sLocalParam); 239 240 if (m_sSceneChangeParam.iMotionBlockNum >= iSceneChangeThresholdLarge) { 241 m_sSceneChangeParam.eSceneChangeIdc = LARGE_CHANGED_SCENE; 242 } else if (m_sSceneChangeParam.iMotionBlockNum >= iSceneChangeThresholdMedium) { 243 m_sSceneChangeParam.eSceneChangeIdc = MEDIUM_CHANGED_SCENE; 244 } 245 246 eReturn = RET_SUCCESS; 247 248 return eReturn; 249 } 250 Get(int32_t iType,void * pParam)251 EResult Get (int32_t iType, void* pParam) { 252 if (pParam == NULL) { 253 return RET_INVALIDPARAM; 254 } 255 * (SSceneChangeResult*)pParam = m_sSceneChangeParam; 256 return RET_SUCCESS; 257 } 258 Set(int32_t iType,void * pParam)259 EResult Set (int32_t iType, void* pParam) { 260 if (pParam == NULL) { 261 return RET_INVALIDPARAM; 262 } 263 m_sSceneChangeParam = * (SSceneChangeResult*)pParam; 264 return RET_SUCCESS; 265 } 266 private: 267 SSceneChangeResult m_sSceneChangeParam; 268 SLocalParam m_sLocalParam; 269 T m_cDetector; 270 }; 271 272 IStrategy* BuildSceneChangeDetection (EMethods eMethod, int32_t iCpuFlag); 273 274 WELSVP_NAMESPACE_END 275 276 #endif 277