/work/openh264/codec/processing/src/scenechangedetection/SceneChangeDetection.h
Line | Count | Source |
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 | 0 | #define HIGH_MOTION_BLOCK_THRESHOLD 320 |
53 | 0 | #define SCENE_CHANGE_MOTION_RATIO_LARGE_VIDEO 0.85f |
54 | 0 | #define SCENE_CHANGE_MOTION_RATIO_MEDIUM 0.50f |
55 | 0 | #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: |
73 | 0 | CSceneChangeDetectorVideo (SSceneChangeResult& sParam, int32_t iCpuFlag) : m_sParam (sParam) { |
74 | 0 | 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 | | #if defined(HAVE_NEON_AARCH64) && defined(__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 | 0 | m_fSceneChangeMotionRatioLarge = SCENE_CHANGE_MOTION_RATIO_LARGE_VIDEO; |
105 | 0 | m_fSceneChangeMotionRatioMedium = SCENE_CHANGE_MOTION_RATIO_MEDIUM; |
106 | 0 | } |
107 | 0 | virtual ~CSceneChangeDetectorVideo() { |
108 | 0 | } |
109 | 0 | void operator() (SLocalParam& sLocalParam) { |
110 | 0 | int32_t iRefRowStride = 0, iCurRowStride = 0; |
111 | 0 | uint8_t* pRefY = sLocalParam.pRefY; |
112 | 0 | uint8_t* pCurY = sLocalParam.pCurY; |
113 | 0 | uint8_t* pRefTmp = NULL, *pCurTmp = NULL; |
114 | |
|
115 | 0 | iRefRowStride = sLocalParam.iRefStride << 3; |
116 | 0 | iCurRowStride = sLocalParam.iCurStride << 3; |
117 | |
|
118 | 0 | for (int32_t j = 0; j < sLocalParam.iBlock8x8Height; j++) { |
119 | 0 | pRefTmp = pRefY; |
120 | 0 | pCurTmp = pCurY; |
121 | 0 | for (int32_t i = 0; i < sLocalParam.iBlock8x8Width; i++) { |
122 | 0 | int32_t iSad = m_pfSad (pCurTmp, sLocalParam.iCurStride, pRefTmp, sLocalParam.iRefStride); |
123 | 0 | m_sParam.iMotionBlockNum += iSad > HIGH_MOTION_BLOCK_THRESHOLD; |
124 | 0 | pRefTmp += 8; |
125 | 0 | pCurTmp += 8; |
126 | 0 | } |
127 | 0 | pRefY += iRefRowStride; |
128 | 0 | pCurY += iCurRowStride; |
129 | 0 | } |
130 | 0 | } |
131 | 0 | float GetSceneChangeMotionRatioLarge() const { |
132 | 0 | return m_fSceneChangeMotionRatioLarge; |
133 | 0 | } |
134 | 0 | float GetSceneChangeMotionRatioMedium() const { |
135 | 0 | return m_fSceneChangeMotionRatioMedium; |
136 | 0 | } |
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: |
146 | 0 | CSceneChangeDetectorScreen (SSceneChangeResult& sParam, int32_t iCpuFlag) : CSceneChangeDetectorVideo (sParam, |
147 | 0 | iCpuFlag) { |
148 | 0 | m_fSceneChangeMotionRatioLarge = SCENE_CHANGE_MOTION_RATIO_LARGE_SCREEN; |
149 | 0 | m_fSceneChangeMotionRatioMedium = SCENE_CHANGE_MOTION_RATIO_MEDIUM; |
150 | 0 | } |
151 | 0 | virtual ~CSceneChangeDetectorScreen() { |
152 | 0 | } |
153 | 0 | void operator() (SLocalParam& sLocalParam) { |
154 | 0 | bool bScrollDetectFlag = m_sParam.sScrollResult.bScrollDetectFlag; |
155 | 0 | int32_t iScrollMvX = m_sParam.sScrollResult.iScrollMvX; |
156 | 0 | int32_t iScrollMvY = m_sParam.sScrollResult.iScrollMvY; |
157 | |
|
158 | 0 | int32_t iRefRowStride = 0, iCurRowStride = 0; |
159 | 0 | uint8_t* pRefY = sLocalParam.pRefY; |
160 | 0 | uint8_t* pCurY = sLocalParam.pCurY; |
161 | 0 | uint8_t* pRefTmp = NULL, *pCurTmp = NULL; |
162 | 0 | int32_t iWidth = sLocalParam.iWidth; |
163 | 0 | int32_t iHeight = sLocalParam.iHeight; |
164 | |
|
165 | 0 | iRefRowStride = sLocalParam.iRefStride << 3; |
166 | 0 | iCurRowStride = sLocalParam.iCurStride << 3; |
167 | |
|
168 | 0 | for (int32_t j = 0; j < sLocalParam.iBlock8x8Height; j++) { |
169 | 0 | pRefTmp = pRefY; |
170 | 0 | pCurTmp = pCurY; |
171 | 0 | for (int32_t i = 0; i < sLocalParam.iBlock8x8Width; i++) { |
172 | 0 | int32_t iBlockPointX = i << 3; |
173 | 0 | int32_t iBlockPointY = j << 3; |
174 | 0 | uint8_t uiBlockIdcTmp = NO_STATIC; |
175 | 0 | int32_t iSad = m_pfSad (pCurTmp, sLocalParam.iCurStride, pRefTmp, sLocalParam.iRefStride); |
176 | 0 | if (iSad == 0) { |
177 | 0 | uiBlockIdcTmp = COLLOCATED_STATIC; |
178 | 0 | } else if (bScrollDetectFlag && (!iScrollMvX || !iScrollMvY) && (iBlockPointX + iScrollMvX >= 0) |
179 | 0 | && (iBlockPointX + iScrollMvX <= iWidth - 8) && |
180 | 0 | (iBlockPointY + iScrollMvY >= 0) && (iBlockPointY + iScrollMvY <= iHeight - 8)) { |
181 | 0 | uint8_t* pRefTmpScroll = pRefTmp + iScrollMvY * sLocalParam.iRefStride + iScrollMvX; |
182 | 0 | int32_t iSadScroll = m_pfSad (pCurTmp, sLocalParam.iCurStride, pRefTmpScroll, sLocalParam.iRefStride); |
183 | |
|
184 | 0 | if (iSadScroll == 0) { |
185 | 0 | uiBlockIdcTmp = SCROLLED_STATIC; |
186 | 0 | } else { |
187 | 0 | m_sParam.iFrameComplexity += iSad; |
188 | 0 | m_sParam.iMotionBlockNum += iSad > HIGH_MOTION_BLOCK_THRESHOLD; |
189 | 0 | } |
190 | 0 | } else { |
191 | 0 | m_sParam.iFrameComplexity += iSad; |
192 | 0 | m_sParam.iMotionBlockNum += iSad > HIGH_MOTION_BLOCK_THRESHOLD; |
193 | 0 | } |
194 | 0 | * (sLocalParam.pStaticBlockIdc) ++ = uiBlockIdcTmp; |
195 | 0 | pRefTmp += 8; |
196 | 0 | pCurTmp += 8; |
197 | 0 | } |
198 | 0 | pRefY += iRefRowStride; |
199 | 0 | pCurY += iCurRowStride; |
200 | 0 | } |
201 | 0 | } |
202 | | }; |
203 | | |
204 | | template<typename T> |
205 | | class CSceneChangeDetection : public IStrategy { |
206 | | public: |
207 | 0 | CSceneChangeDetection (EMethods eMethod, int32_t iCpuFlag): m_cDetector (m_sSceneChangeParam, iCpuFlag) { |
208 | 0 | m_eMethod = eMethod; |
209 | 0 | WelsMemset (&m_sSceneChangeParam, 0, sizeof (m_sSceneChangeParam)); |
210 | 0 | } Unexecuted instantiation: WelsVP::CSceneChangeDetection<WelsVP::CSceneChangeDetectorVideo>::CSceneChangeDetection(EMethods, int) Unexecuted instantiation: WelsVP::CSceneChangeDetection<WelsVP::CSceneChangeDetectorScreen>::CSceneChangeDetection(EMethods, int) |
211 | | |
212 | 0 | ~CSceneChangeDetection() { |
213 | 0 | } Unexecuted instantiation: WelsVP::CSceneChangeDetection<WelsVP::CSceneChangeDetectorVideo>::~CSceneChangeDetection() Unexecuted instantiation: WelsVP::CSceneChangeDetection<WelsVP::CSceneChangeDetectorScreen>::~CSceneChangeDetection() |
214 | | |
215 | 0 | EResult Process (int32_t iType, SPixMap* pSrcPixMap, SPixMap* pRefPixMap) { |
216 | 0 | EResult eReturn = RET_INVALIDPARAM; |
217 | |
|
218 | 0 | m_sLocalParam.iWidth = pSrcPixMap->sRect.iRectWidth; |
219 | 0 | m_sLocalParam.iHeight = pSrcPixMap->sRect.iRectHeight; |
220 | 0 | m_sLocalParam.iBlock8x8Width = m_sLocalParam.iWidth >> 3; |
221 | 0 | m_sLocalParam.iBlock8x8Height = m_sLocalParam.iHeight >> 3; |
222 | 0 | m_sLocalParam.pRefY = (uint8_t*)pRefPixMap->pPixel[0]; |
223 | 0 | m_sLocalParam.pCurY = (uint8_t*)pSrcPixMap->pPixel[0]; |
224 | 0 | m_sLocalParam.iRefStride = pRefPixMap->iStride[0]; |
225 | 0 | m_sLocalParam.iCurStride = pSrcPixMap->iStride[0]; |
226 | 0 | m_sLocalParam.pStaticBlockIdc = m_sSceneChangeParam.pStaticBlockIdc; |
227 | |
|
228 | 0 | int32_t iBlock8x8Num = m_sLocalParam.iBlock8x8Width * m_sLocalParam.iBlock8x8Height; |
229 | 0 | int32_t iSceneChangeThresholdLarge = WelsStaticCast (int32_t, |
230 | 0 | m_cDetector.GetSceneChangeMotionRatioLarge() * iBlock8x8Num + 0.5f + PESN); |
231 | 0 | int32_t iSceneChangeThresholdMedium = WelsStaticCast (int32_t, |
232 | 0 | m_cDetector.GetSceneChangeMotionRatioMedium() * iBlock8x8Num + 0.5f + PESN); |
233 | |
|
234 | 0 | m_sSceneChangeParam.iMotionBlockNum = 0; |
235 | 0 | m_sSceneChangeParam.iFrameComplexity = 0; |
236 | 0 | m_sSceneChangeParam.eSceneChangeIdc = SIMILAR_SCENE; |
237 | |
|
238 | 0 | m_cDetector (m_sLocalParam); |
239 | |
|
240 | 0 | if (m_sSceneChangeParam.iMotionBlockNum >= iSceneChangeThresholdLarge) { |
241 | 0 | m_sSceneChangeParam.eSceneChangeIdc = LARGE_CHANGED_SCENE; |
242 | 0 | } else if (m_sSceneChangeParam.iMotionBlockNum >= iSceneChangeThresholdMedium) { |
243 | 0 | m_sSceneChangeParam.eSceneChangeIdc = MEDIUM_CHANGED_SCENE; |
244 | 0 | } |
245 | |
|
246 | 0 | eReturn = RET_SUCCESS; |
247 | |
|
248 | 0 | return eReturn; |
249 | 0 | } Unexecuted instantiation: WelsVP::CSceneChangeDetection<WelsVP::CSceneChangeDetectorVideo>::Process(int, SPixMap*, SPixMap*) Unexecuted instantiation: WelsVP::CSceneChangeDetection<WelsVP::CSceneChangeDetectorScreen>::Process(int, SPixMap*, SPixMap*) |
250 | | |
251 | 0 | EResult Get (int32_t iType, void* pParam) { |
252 | 0 | if (pParam == NULL) { |
253 | 0 | return RET_INVALIDPARAM; |
254 | 0 | } |
255 | 0 | * (SSceneChangeResult*)pParam = m_sSceneChangeParam; |
256 | 0 | return RET_SUCCESS; |
257 | 0 | } Unexecuted instantiation: WelsVP::CSceneChangeDetection<WelsVP::CSceneChangeDetectorVideo>::Get(int, void*) Unexecuted instantiation: WelsVP::CSceneChangeDetection<WelsVP::CSceneChangeDetectorScreen>::Get(int, void*) |
258 | | |
259 | 0 | EResult Set (int32_t iType, void* pParam) { |
260 | 0 | if (pParam == NULL) { |
261 | 0 | return RET_INVALIDPARAM; |
262 | 0 | } |
263 | 0 | m_sSceneChangeParam = * (SSceneChangeResult*)pParam; |
264 | 0 | return RET_SUCCESS; |
265 | 0 | } Unexecuted instantiation: WelsVP::CSceneChangeDetection<WelsVP::CSceneChangeDetectorVideo>::Set(int, void*) Unexecuted instantiation: WelsVP::CSceneChangeDetection<WelsVP::CSceneChangeDetectorScreen>::Set(int, void*) |
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 |