Coverage Report

Created: 2026-10-28 07:26

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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