1 /*!
2 * \copy
3 * Copyright (c) 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 */
32
33 #include "WelsFrameWork.h"
34 #include "../denoise/denoise.h"
35 #include "../downsample/downsample.h"
36 #include "../scrolldetection/ScrollDetection.h"
37 #include "../scenechangedetection/SceneChangeDetection.h"
38 #include "../vaacalc/vaacalculation.h"
39 #include "../backgrounddetection/BackgroundDetection.h"
40 #include "../adaptivequantization/AdaptiveQuantization.h"
41 #include "../complexityanalysis/ComplexityAnalysis.h"
42 #include "../imagerotate/imagerotate.h"
43 #include "util.h"
44
45 /* interface API implement */
46
WelsCreateVpInterface(void ** ppCtx,int iVersion)47 EResult WelsCreateVpInterface (void** ppCtx, int iVersion) {
48 if (iVersion & 0x8000)
49 return WelsVP::CreateSpecificVpInterface ((IWelsVP**)ppCtx);
50 else if (iVersion & 0x7fff)
51 return WelsVP::CreateSpecificVpInterface ((IWelsVPc**)ppCtx);
52 else
53 return RET_INVALIDPARAM;
54 }
55
WelsDestroyVpInterface(void * pCtx,int iVersion)56 EResult WelsDestroyVpInterface (void* pCtx, int iVersion) {
57 if (iVersion & 0x8000)
58 return WelsVP::DestroySpecificVpInterface ((IWelsVP*)pCtx);
59 else if (iVersion & 0x7fff)
60 return WelsVP::DestroySpecificVpInterface ((IWelsVPc*)pCtx);
61 else
62 return RET_INVALIDPARAM;
63 }
64
65 WELSVP_NAMESPACE_BEGIN
66
67 ///////////////////////////////////////////////////////////////////////
68
CreateSpecificVpInterface(IWelsVP ** ppCtx)69 EResult CreateSpecificVpInterface (IWelsVP** ppCtx) {
70 EResult eReturn = RET_FAILED;
71
72 CVpFrameWork* pFr = new CVpFrameWork (1, eReturn);
73 if (pFr) {
74 *ppCtx = (IWelsVP*)pFr;
75 eReturn = RET_SUCCESS;
76 }
77
78 return eReturn;
79 }
80
DestroySpecificVpInterface(IWelsVP * pCtx)81 EResult DestroySpecificVpInterface (IWelsVP* pCtx) {
82 delete pCtx;
83
84 return RET_SUCCESS;
85 }
86
87 ///////////////////////////////////////////////////////////////////////////////
88
CVpFrameWork(uint32_t uiThreadsNum,EResult & eReturn)89 CVpFrameWork::CVpFrameWork (uint32_t uiThreadsNum, EResult& eReturn) {
90 int32_t iCoreNum = 1;
91 uint32_t uiCPUFlag = WelsCPUFeatureDetect (&iCoreNum);
92
93 for (int32_t i = 0; i < MAX_STRATEGY_NUM; i++) {
94 m_pStgChain[i] = CreateStrategy (WelsStaticCast (EMethods, i + 1), uiCPUFlag);
95 }
96
97 WelsMutexInit (&m_mutes);
98
99 eReturn = RET_SUCCESS;
100 }
101
~CVpFrameWork()102 CVpFrameWork::~CVpFrameWork() {
103 for (int32_t i = 0; i < MAX_STRATEGY_NUM; i++) {
104 if (m_pStgChain[i]) {
105 Uninit (m_pStgChain[i]->m_eMethod);
106 delete m_pStgChain[i];
107 }
108 }
109
110 WelsMutexDestroy (&m_mutes);
111 }
112
Init(int32_t iType,void * pCfg)113 EResult CVpFrameWork::Init (int32_t iType, void* pCfg) {
114 EResult eReturn = RET_SUCCESS;
115 int32_t iCurIdx = WelsStaticCast (int32_t, WelsVpGetValidMethod (iType)) - 1;
116
117 Uninit (iType);
118
119 WelsMutexLock (&m_mutes);
120
121 IStrategy* pStrategy = m_pStgChain[iCurIdx];
122 if (pStrategy)
123 eReturn = pStrategy->Init (0, pCfg);
124
125 WelsMutexUnlock (&m_mutes);
126
127 return eReturn;
128 }
129
Uninit(int32_t iType)130 EResult CVpFrameWork::Uninit (int32_t iType) {
131 EResult eReturn = RET_SUCCESS;
132 int32_t iCurIdx = WelsStaticCast (int32_t, WelsVpGetValidMethod (iType)) - 1;
133
134 WelsMutexLock (&m_mutes);
135
136 IStrategy* pStrategy = m_pStgChain[iCurIdx];
137 if (pStrategy)
138 eReturn = pStrategy->Uninit (0);
139
140 WelsMutexUnlock (&m_mutes);
141
142 return eReturn;
143 }
144
Flush(int32_t iType)145 EResult CVpFrameWork::Flush (int32_t iType) {
146 EResult eReturn = RET_SUCCESS;
147
148 return eReturn;
149 }
150
Process(int32_t iType,SPixMap * pSrcPixMap,SPixMap * pDstPixMap)151 EResult CVpFrameWork::Process (int32_t iType, SPixMap* pSrcPixMap, SPixMap* pDstPixMap) {
152 EResult eReturn = RET_NOTSUPPORTED;
153 EMethods eMethod = WelsVpGetValidMethod (iType);
154 int32_t iCurIdx = WelsStaticCast (int32_t, eMethod) - 1;
155 SPixMap sSrcPic;
156 SPixMap sDstPic;
157 memset (&sSrcPic, 0, sizeof (sSrcPic)); // confirmed_safe_unsafe_usage
158 memset (&sDstPic, 0, sizeof (sDstPic)); // confirmed_safe_unsafe_usage
159
160 if (pSrcPixMap) sSrcPic = *pSrcPixMap;
161 if (pDstPixMap) sDstPic = *pDstPixMap;
162 if (!CheckValid (eMethod, sSrcPic, sDstPic))
163 return RET_INVALIDPARAM;
164
165 WelsMutexLock (&m_mutes);
166
167 IStrategy* pStrategy = m_pStgChain[iCurIdx];
168 if (pStrategy)
169 eReturn = pStrategy->Process (0, &sSrcPic, &sDstPic);
170
171 WelsMutexUnlock (&m_mutes);
172
173 return eReturn;
174 }
175
Get(int32_t iType,void * pParam)176 EResult CVpFrameWork::Get (int32_t iType, void* pParam) {
177 EResult eReturn = RET_SUCCESS;
178 int32_t iCurIdx = WelsStaticCast (int32_t, WelsVpGetValidMethod (iType)) - 1;
179
180 if (!pParam)
181 return RET_INVALIDPARAM;
182
183 WelsMutexLock (&m_mutes);
184
185 IStrategy* pStrategy = m_pStgChain[iCurIdx];
186 if (pStrategy)
187 eReturn = pStrategy->Get (0, pParam);
188
189 WelsMutexUnlock (&m_mutes);
190
191 return eReturn;
192 }
193
Set(int32_t iType,void * pParam)194 EResult CVpFrameWork::Set (int32_t iType, void* pParam) {
195 EResult eReturn = RET_SUCCESS;
196 int32_t iCurIdx = WelsStaticCast (int32_t, WelsVpGetValidMethod (iType)) - 1;
197
198 if (!pParam)
199 return RET_INVALIDPARAM;
200
201 WelsMutexLock (&m_mutes);
202
203 IStrategy* pStrategy = m_pStgChain[iCurIdx];
204 if (pStrategy)
205 eReturn = pStrategy->Set (0, pParam);
206
207 WelsMutexUnlock (&m_mutes);
208
209 return eReturn;
210 }
211
SpecialFeature(int32_t iType,void * pIn,void * pOut)212 EResult CVpFrameWork::SpecialFeature (int32_t iType, void* pIn, void* pOut) {
213 EResult eReturn = RET_SUCCESS;
214
215 return eReturn;
216 }
217
CheckValid(EMethods eMethod,SPixMap & pSrcPixMap,SPixMap & pDstPixMap)218 bool CVpFrameWork::CheckValid (EMethods eMethod, SPixMap& pSrcPixMap, SPixMap& pDstPixMap) {
219 bool eReturn = false;
220
221 if (eMethod == METHOD_NULL)
222 goto exit;
223
224 if (eMethod != METHOD_COLORSPACE_CONVERT) {
225 if (pSrcPixMap.pPixel[0]) {
226 if (pSrcPixMap.eFormat != VIDEO_FORMAT_I420 && pSrcPixMap.eFormat != VIDEO_FORMAT_YV12)
227 goto exit;
228 }
229 if (pSrcPixMap.pPixel[0] && pDstPixMap.pPixel[0]) {
230 if (pDstPixMap.eFormat != pSrcPixMap.eFormat)
231 goto exit;
232 }
233 }
234
235 if (pSrcPixMap.pPixel[0]) {
236 if (pSrcPixMap.sRect.iRectWidth <= 0 || pSrcPixMap.sRect.iRectHeight <= 0
237 || pSrcPixMap.sRect.iRectWidth * pSrcPixMap.sRect.iRectHeight > (MAX_MBS_PER_FRAME << 8))
238 goto exit;
239 if (pSrcPixMap.sRect.iRectTop >= pSrcPixMap.sRect.iRectHeight
240 || pSrcPixMap.sRect.iRectLeft >= pSrcPixMap.sRect.iRectWidth || pSrcPixMap.sRect.iRectWidth > pSrcPixMap.iStride[0])
241 goto exit;
242 }
243 if (pDstPixMap.pPixel[0]) {
244 if (pDstPixMap.sRect.iRectWidth <= 0 || pDstPixMap.sRect.iRectHeight <= 0
245 || pDstPixMap.sRect.iRectWidth * pDstPixMap.sRect.iRectHeight > (MAX_MBS_PER_FRAME << 8))
246 goto exit;
247 if (pDstPixMap.sRect.iRectTop >= pDstPixMap.sRect.iRectHeight
248 || pDstPixMap.sRect.iRectLeft >= pDstPixMap.sRect.iRectWidth || pDstPixMap.sRect.iRectWidth > pDstPixMap.iStride[0])
249 goto exit;
250 }
251 eReturn = true;
252
253 exit:
254 return eReturn;
255 }
256
CreateStrategy(EMethods m_eMethod,int32_t iCpuFlag)257 IStrategy* CVpFrameWork::CreateStrategy (EMethods m_eMethod, int32_t iCpuFlag) {
258 IStrategy* pStrategy = NULL;
259
260 switch (m_eMethod) {
261 case METHOD_COLORSPACE_CONVERT:
262 //not support yet
263 break;
264 case METHOD_DENOISE:
265 pStrategy = WelsDynamicCast (IStrategy*, new CDenoiser (iCpuFlag));
266 break;
267 case METHOD_SCROLL_DETECTION:
268 pStrategy = WelsDynamicCast (IStrategy*, new CScrollDetection (iCpuFlag));
269 break;
270 case METHOD_SCENE_CHANGE_DETECTION_VIDEO:
271 case METHOD_SCENE_CHANGE_DETECTION_SCREEN:
272 pStrategy = BuildSceneChangeDetection (m_eMethod, iCpuFlag);
273 break;
274 case METHOD_DOWNSAMPLE:
275 pStrategy = WelsDynamicCast (IStrategy*, new CDownsampling (iCpuFlag));
276 break;
277 case METHOD_VAA_STATISTICS:
278 pStrategy = WelsDynamicCast (IStrategy*, new CVAACalculation (iCpuFlag));
279 break;
280 case METHOD_BACKGROUND_DETECTION:
281 pStrategy = WelsDynamicCast (IStrategy*, new CBackgroundDetection (iCpuFlag));
282 break;
283 case METHOD_ADAPTIVE_QUANT:
284 pStrategy = WelsDynamicCast (IStrategy*, new CAdaptiveQuantization (iCpuFlag));
285 break;
286 case METHOD_COMPLEXITY_ANALYSIS:
287 pStrategy = WelsDynamicCast (IStrategy*, new CComplexityAnalysis (iCpuFlag));
288 break;
289 case METHOD_COMPLEXITY_ANALYSIS_SCREEN:
290 pStrategy = WelsDynamicCast (IStrategy*, new CComplexityAnalysisScreen (iCpuFlag));
291 break;
292 case METHOD_IMAGE_ROTATE:
293 pStrategy = WelsDynamicCast (IStrategy*, new CImageRotating (iCpuFlag));
294 break;
295 default:
296 break;
297 }
298
299 return pStrategy;
300 }
301
302 WELSVP_NAMESPACE_END
303