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