/src/openh264/codec/processing/src/backgrounddetection/BackgroundDetection.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 "BackgroundDetection.h" |
34 | | |
35 | | WELSVP_NAMESPACE_BEGIN |
36 | | |
37 | 0 | #define LOG2_BGD_OU_SIZE (4) |
38 | 0 | #define LOG2_BGD_OU_SIZE_UV (LOG2_BGD_OU_SIZE-1) |
39 | 0 | #define BGD_OU_SIZE (1<<LOG2_BGD_OU_SIZE) |
40 | 0 | #define BGD_OU_SIZE_UV (BGD_OU_SIZE>>1) |
41 | 0 | #define BGD_THD_SAD (2*BGD_OU_SIZE*BGD_OU_SIZE) |
42 | 0 | #define BGD_THD_ASD_UV (4*BGD_OU_SIZE_UV) |
43 | 0 | #define LOG2_MB_SIZE (4) |
44 | 0 | #define OU_SIZE_IN_MB (BGD_OU_SIZE >> 4) |
45 | 0 | #define Q_FACTOR (8) |
46 | | #define BGD_DELTA_QP_THD (3) |
47 | | |
48 | 0 | #define OU_LEFT (0x01) |
49 | 0 | #define OU_RIGHT (0x02) |
50 | 0 | #define OU_TOP (0x04) |
51 | 0 | #define OU_BOTTOM (0x08) |
52 | | |
53 | 0 | CBackgroundDetection::CBackgroundDetection (int32_t iCpuFlag) { |
54 | 0 | m_eMethod = METHOD_BACKGROUND_DETECTION; |
55 | 0 | WelsMemset (&m_BgdParam, 0, sizeof (m_BgdParam)); |
56 | 0 | m_iLargestFrameSize = 0; |
57 | 0 | } |
58 | | |
59 | 0 | CBackgroundDetection::~CBackgroundDetection() { |
60 | 0 | WelsFree (m_BgdParam.pOU_array); |
61 | 0 | } |
62 | | |
63 | 0 | EResult CBackgroundDetection::Process (int32_t iType, SPixMap* pSrcPixMap, SPixMap* pRefPixMap) { |
64 | 0 | EResult eReturn = RET_INVALIDPARAM; |
65 | |
|
66 | 0 | if (pSrcPixMap == NULL || pRefPixMap == NULL) |
67 | 0 | return eReturn; |
68 | | |
69 | 0 | m_BgdParam.pCur[0] = (uint8_t*)pSrcPixMap->pPixel[0]; |
70 | 0 | m_BgdParam.pCur[1] = (uint8_t*)pSrcPixMap->pPixel[1]; |
71 | 0 | m_BgdParam.pCur[2] = (uint8_t*)pSrcPixMap->pPixel[2]; |
72 | 0 | m_BgdParam.pRef[0] = (uint8_t*)pRefPixMap->pPixel[0]; |
73 | 0 | m_BgdParam.pRef[1] = (uint8_t*)pRefPixMap->pPixel[1]; |
74 | 0 | m_BgdParam.pRef[2] = (uint8_t*)pRefPixMap->pPixel[2]; |
75 | 0 | m_BgdParam.iBgdWidth = pSrcPixMap->sRect.iRectWidth; |
76 | 0 | m_BgdParam.iBgdHeight = pSrcPixMap->sRect.iRectHeight; |
77 | 0 | m_BgdParam.iStride[0] = pSrcPixMap->iStride[0]; |
78 | 0 | m_BgdParam.iStride[1] = pSrcPixMap->iStride[1]; |
79 | 0 | m_BgdParam.iStride[2] = pSrcPixMap->iStride[2]; |
80 | |
|
81 | 0 | int32_t iCurFrameSize = m_BgdParam.iBgdWidth * m_BgdParam.iBgdHeight; |
82 | 0 | if (m_BgdParam.pOU_array == NULL || iCurFrameSize > m_iLargestFrameSize) { |
83 | 0 | WelsFree (m_BgdParam.pOU_array); |
84 | 0 | m_BgdParam.pOU_array = AllocateOUArrayMemory (m_BgdParam.iBgdWidth, m_BgdParam.iBgdHeight); |
85 | 0 | m_iLargestFrameSize = iCurFrameSize; |
86 | 0 | } |
87 | |
|
88 | 0 | if (m_BgdParam.pOU_array == NULL) |
89 | 0 | return eReturn; |
90 | | |
91 | 0 | BackgroundDetection (&m_BgdParam); |
92 | |
|
93 | 0 | return RET_SUCCESS; |
94 | 0 | } |
95 | | |
96 | 0 | EResult CBackgroundDetection::Set (int32_t iType, void* pParam) { |
97 | 0 | if (pParam == NULL) { |
98 | 0 | return RET_INVALIDPARAM; |
99 | 0 | } |
100 | | |
101 | 0 | SBGDInterface* pInterface = (SBGDInterface*)pParam; |
102 | |
|
103 | 0 | m_BgdParam.pBackgroundMbFlag = (int8_t*)pInterface->pBackgroundMbFlag; |
104 | 0 | m_BgdParam.pCalcRes = pInterface->pCalcRes; |
105 | |
|
106 | 0 | return RET_SUCCESS; |
107 | 0 | } |
108 | | |
109 | 0 | inline SBackgroundOU* CBackgroundDetection::AllocateOUArrayMemory (int32_t iWidth, int32_t iHeight) { |
110 | 0 | int32_t iMaxOUWidth = (BGD_OU_SIZE - 1 + iWidth) >> LOG2_BGD_OU_SIZE; |
111 | 0 | int32_t iMaxOUHeight = (BGD_OU_SIZE - 1 + iHeight) >> LOG2_BGD_OU_SIZE; |
112 | 0 | return (SBackgroundOU*)WelsMalloc (iMaxOUWidth * iMaxOUHeight * sizeof (SBackgroundOU)); |
113 | 0 | } |
114 | | |
115 | | void CBackgroundDetection::GetOUParameters (SVAACalcResult* sVaaCalcInfo, int32_t iMbIndex, int32_t iMbWidth, |
116 | 0 | SBackgroundOU* pBgdOU) { |
117 | 0 | int32_t iSubSD[4]; |
118 | 0 | uint8_t iSubMAD[4]; |
119 | 0 | int32_t iSubSAD[4]; |
120 | |
|
121 | 0 | uint8_t (*pMad8x8)[4]; |
122 | 0 | int32_t (*pSad8x8)[4]; |
123 | 0 | int32_t (*pSd8x8)[4]; |
124 | |
|
125 | 0 | pSad8x8 = sVaaCalcInfo->pSad8x8; |
126 | 0 | pMad8x8 = sVaaCalcInfo->pMad8x8; |
127 | 0 | pSd8x8 = sVaaCalcInfo->pSumOfDiff8x8; |
128 | |
|
129 | 0 | iSubSAD[0] = pSad8x8[iMbIndex][0]; |
130 | 0 | iSubSAD[1] = pSad8x8[iMbIndex][1]; |
131 | 0 | iSubSAD[2] = pSad8x8[iMbIndex][2]; |
132 | 0 | iSubSAD[3] = pSad8x8[iMbIndex][3]; |
133 | |
|
134 | 0 | iSubSD[0] = pSd8x8[iMbIndex][0]; |
135 | 0 | iSubSD[1] = pSd8x8[iMbIndex][1]; |
136 | 0 | iSubSD[2] = pSd8x8[iMbIndex][2]; |
137 | 0 | iSubSD[3] = pSd8x8[iMbIndex][3]; |
138 | |
|
139 | 0 | iSubMAD[0] = pMad8x8[iMbIndex][0]; |
140 | 0 | iSubMAD[1] = pMad8x8[iMbIndex][1]; |
141 | 0 | iSubMAD[2] = pMad8x8[iMbIndex][2]; |
142 | 0 | iSubMAD[3] = pMad8x8[iMbIndex][3]; |
143 | |
|
144 | 0 | pBgdOU->iSD = iSubSD[0] + iSubSD[1] + iSubSD[2] + iSubSD[3]; |
145 | 0 | pBgdOU->iSAD = iSubSAD[0] + iSubSAD[1] + iSubSAD[2] + iSubSAD[3]; |
146 | 0 | pBgdOU->iSD = WELS_ABS (pBgdOU->iSD); |
147 | | |
148 | | // get the max absolute difference (MAD) of OU and min value of the MAD of sub-blocks of OU |
149 | 0 | pBgdOU->iMAD = WELS_MAX (WELS_MAX (iSubMAD[0], iSubMAD[1]), WELS_MAX (iSubMAD[2], iSubMAD[3])); |
150 | 0 | pBgdOU->iMinSubMad = WELS_MIN (WELS_MIN (iSubMAD[0], iSubMAD[1]), WELS_MIN (iSubMAD[2], iSubMAD[3])); |
151 | | |
152 | | // get difference between the max and min SD of the SDs of sub-blocks of OU |
153 | 0 | pBgdOU->iMaxDiffSubSd = WELS_MAX (WELS_MAX (iSubSD[0], iSubSD[1]), WELS_MAX (iSubSD[2], iSubSD[3])) - |
154 | 0 | WELS_MIN (WELS_MIN (iSubSD[0], iSubSD[1]), WELS_MIN (iSubSD[2], iSubSD[3])); |
155 | 0 | } |
156 | | |
157 | 0 | void CBackgroundDetection::ForegroundBackgroundDivision (vBGDParam* pBgdParam) { |
158 | 0 | int32_t iPicWidthInOU = pBgdParam->iBgdWidth >> LOG2_BGD_OU_SIZE; |
159 | 0 | int32_t iPicHeightInOU = pBgdParam->iBgdHeight >> LOG2_BGD_OU_SIZE; |
160 | 0 | int32_t iPicWidthInMb = (15 + pBgdParam->iBgdWidth) >> 4; |
161 | |
|
162 | 0 | SBackgroundOU* pBackgroundOU = pBgdParam->pOU_array; |
163 | |
|
164 | 0 | for (int32_t j = 0; j < iPicHeightInOU; j ++) { |
165 | 0 | for (int32_t i = 0; i < iPicWidthInOU; i++) { |
166 | 0 | GetOUParameters (pBgdParam->pCalcRes, (j * iPicWidthInMb + i) << (LOG2_BGD_OU_SIZE - LOG2_MB_SIZE), iPicWidthInMb, |
167 | 0 | pBackgroundOU); |
168 | |
|
169 | 0 | pBackgroundOU->iBackgroundFlag = 0; |
170 | 0 | if (pBackgroundOU->iMAD > 63) { |
171 | 0 | pBackgroundOU++; |
172 | 0 | continue; |
173 | 0 | } |
174 | 0 | if ((pBackgroundOU->iMaxDiffSubSd <= pBackgroundOU->iSAD >> 3 |
175 | 0 | || pBackgroundOU->iMaxDiffSubSd <= (BGD_OU_SIZE * Q_FACTOR)) |
176 | 0 | && pBackgroundOU->iSAD < (BGD_THD_SAD << 1)) { //BGD_OU_SIZE*BGD_OU_SIZE>>2 |
177 | 0 | if (pBackgroundOU->iSAD <= BGD_OU_SIZE * Q_FACTOR) { |
178 | 0 | pBackgroundOU->iBackgroundFlag = 1; |
179 | 0 | } else { |
180 | 0 | pBackgroundOU->iBackgroundFlag = pBackgroundOU->iSAD < BGD_THD_SAD ? |
181 | 0 | (pBackgroundOU->iSD < (pBackgroundOU->iSAD * 3) >> 2) : |
182 | 0 | (pBackgroundOU->iSD << 1 < pBackgroundOU->iSAD); |
183 | 0 | } |
184 | 0 | } |
185 | 0 | pBackgroundOU++; |
186 | 0 | } |
187 | 0 | } |
188 | 0 | } |
189 | 0 | inline int32_t CBackgroundDetection::CalculateAsdChromaEdge (uint8_t* pOriRef, uint8_t* pOriCur, int32_t iStride) { |
190 | 0 | int32_t ASD = 0; |
191 | 0 | int32_t idx; |
192 | 0 | for (idx = 0; idx < BGD_OU_SIZE_UV; idx++) { |
193 | 0 | ASD += *pOriCur - *pOriRef; |
194 | 0 | pOriRef += iStride; |
195 | 0 | pOriCur += iStride; |
196 | 0 | } |
197 | 0 | return WELS_ABS (ASD); |
198 | 0 | } |
199 | | |
200 | | inline bool CBackgroundDetection::ForegroundDilation23Luma (SBackgroundOU* pBackgroundOU, |
201 | 0 | SBackgroundOU* pOUNeighbours[]) { |
202 | 0 | SBackgroundOU* pOU_L = pOUNeighbours[0]; |
203 | 0 | SBackgroundOU* pOU_R = pOUNeighbours[1]; |
204 | 0 | SBackgroundOU* pOU_U = pOUNeighbours[2]; |
205 | 0 | SBackgroundOU* pOU_D = pOUNeighbours[3]; |
206 | |
|
207 | 0 | if (pBackgroundOU->iMAD > pBackgroundOU->iMinSubMad << 1) { |
208 | 0 | int32_t iMaxNbrForegroundMad; |
209 | 0 | int32_t iMaxNbrBackgroundMad; |
210 | 0 | int32_t aBackgroundMad[4]; |
211 | 0 | int32_t aForegroundMad[4]; |
212 | |
|
213 | 0 | aForegroundMad[0] = (pOU_L->iBackgroundFlag - 1) & pOU_L->iMAD; |
214 | 0 | aForegroundMad[1] = (pOU_R->iBackgroundFlag - 1) & pOU_R->iMAD; |
215 | 0 | aForegroundMad[2] = (pOU_U->iBackgroundFlag - 1) & pOU_U->iMAD; |
216 | 0 | aForegroundMad[3] = (pOU_D->iBackgroundFlag - 1) & pOU_D->iMAD; |
217 | 0 | iMaxNbrForegroundMad = WELS_MAX (WELS_MAX (aForegroundMad[0], aForegroundMad[1]), WELS_MAX (aForegroundMad[2], |
218 | 0 | aForegroundMad[3])); |
219 | |
|
220 | 0 | aBackgroundMad[0] = ((!pOU_L->iBackgroundFlag) - 1) & pOU_L->iMAD; |
221 | 0 | aBackgroundMad[1] = ((!pOU_R->iBackgroundFlag) - 1) & pOU_R->iMAD; |
222 | 0 | aBackgroundMad[2] = ((!pOU_U->iBackgroundFlag) - 1) & pOU_U->iMAD; |
223 | 0 | aBackgroundMad[3] = ((!pOU_D->iBackgroundFlag) - 1) & pOU_D->iMAD; |
224 | 0 | iMaxNbrBackgroundMad = WELS_MAX (WELS_MAX (aBackgroundMad[0], aBackgroundMad[1]), WELS_MAX (aBackgroundMad[2], |
225 | 0 | aBackgroundMad[3])); |
226 | |
|
227 | 0 | return ((iMaxNbrForegroundMad > pBackgroundOU->iMinSubMad << 2) || (pBackgroundOU->iMAD > iMaxNbrBackgroundMad << 1 |
228 | 0 | && pBackgroundOU->iMAD <= (iMaxNbrForegroundMad * 3) >> 1)); |
229 | 0 | } |
230 | 0 | return 0; |
231 | 0 | } |
232 | | |
233 | | inline bool CBackgroundDetection::ForegroundDilation23Chroma (int8_t iNeighbourForegroundFlags, |
234 | 0 | int32_t iStartSamplePos, int32_t iPicStrideUV, vBGDParam* pBgdParam) { |
235 | 0 | static const int8_t kaOUPos[4] = {OU_LEFT, OU_RIGHT, OU_TOP, OU_BOTTOM}; |
236 | 0 | int32_t aEdgeOffset[4] = {0, BGD_OU_SIZE_UV - 1, 0, iPicStrideUV* (BGD_OU_SIZE_UV - 1)}; |
237 | 0 | int32_t iStride[4] = {iPicStrideUV, iPicStrideUV, 1, 1}; |
238 | | |
239 | | // V component first, high probability because V stands for red color and human skin colors have more weight on this component |
240 | 0 | for (int32_t i = 0; i < 4; i++) { |
241 | 0 | if (iNeighbourForegroundFlags & kaOUPos[i]) { |
242 | 0 | uint8_t* pRefC = pBgdParam->pRef[2] + iStartSamplePos + aEdgeOffset[i]; |
243 | 0 | uint8_t* pCurC = pBgdParam->pCur[2] + iStartSamplePos + aEdgeOffset[i]; |
244 | 0 | if (CalculateAsdChromaEdge (pRefC, pCurC, iStride[i]) > BGD_THD_ASD_UV) { |
245 | 0 | return 1; |
246 | 0 | } |
247 | 0 | } |
248 | 0 | } |
249 | | // U component, which stands for blue color, low probability |
250 | 0 | for (int32_t i = 0; i < 4; i++) { |
251 | 0 | if (iNeighbourForegroundFlags & kaOUPos[i]) { |
252 | 0 | uint8_t* pRefC = pBgdParam->pRef[1] + iStartSamplePos + aEdgeOffset[i]; |
253 | 0 | uint8_t* pCurC = pBgdParam->pCur[1] + iStartSamplePos + aEdgeOffset[i]; |
254 | 0 | if (CalculateAsdChromaEdge (pRefC, pCurC, iStride[i]) > BGD_THD_ASD_UV) { |
255 | 0 | return 1; |
256 | 0 | } |
257 | 0 | } |
258 | 0 | } |
259 | | |
260 | 0 | return 0; |
261 | 0 | } |
262 | | |
263 | | inline void CBackgroundDetection::ForegroundDilation (SBackgroundOU* pBackgroundOU, SBackgroundOU* pOUNeighbours[], |
264 | 0 | vBGDParam* pBgdParam, int32_t iChromaSampleStartPos) { |
265 | 0 | int32_t iPicStrideUV = pBgdParam->iStride[1]; |
266 | 0 | int32_t iSumNeighBackgroundFlags = pOUNeighbours[0]->iBackgroundFlag + pOUNeighbours[1]->iBackgroundFlag + |
267 | 0 | pOUNeighbours[2]->iBackgroundFlag + pOUNeighbours[3]->iBackgroundFlag; |
268 | |
|
269 | 0 | if (pBackgroundOU->iSAD > BGD_OU_SIZE * Q_FACTOR) { |
270 | 0 | switch (iSumNeighBackgroundFlags) { |
271 | 0 | case 0: |
272 | 0 | case 1: |
273 | 0 | pBackgroundOU->iBackgroundFlag = 0; |
274 | 0 | break; |
275 | 0 | case 2: |
276 | 0 | case 3: |
277 | 0 | pBackgroundOU->iBackgroundFlag = !ForegroundDilation23Luma (pBackgroundOU, pOUNeighbours); |
278 | | |
279 | | // chroma component check |
280 | 0 | if (pBackgroundOU->iBackgroundFlag == 1) { |
281 | 0 | int8_t iNeighbourForegroundFlags = (!pOUNeighbours[0]->iBackgroundFlag) | ((!pOUNeighbours[1]->iBackgroundFlag) << 1) |
282 | 0 | | ((!pOUNeighbours[2]->iBackgroundFlag) << 2) | ((!pOUNeighbours[3]->iBackgroundFlag) << 3); |
283 | 0 | pBackgroundOU->iBackgroundFlag = !ForegroundDilation23Chroma (iNeighbourForegroundFlags, iChromaSampleStartPos, |
284 | 0 | iPicStrideUV, pBgdParam); |
285 | 0 | } |
286 | 0 | break; |
287 | 0 | default: |
288 | 0 | break; |
289 | 0 | } |
290 | 0 | } |
291 | 0 | } |
292 | 0 | inline void CBackgroundDetection::BackgroundErosion (SBackgroundOU* pBackgroundOU, SBackgroundOU* pOUNeighbours[]) { |
293 | 0 | if (pBackgroundOU->iMaxDiffSubSd <= (BGD_OU_SIZE * Q_FACTOR)) { //BGD_OU_SIZE*BGD_OU_SIZE>>2 |
294 | 0 | int32_t iSumNeighBackgroundFlags = pOUNeighbours[0]->iBackgroundFlag + pOUNeighbours[1]->iBackgroundFlag + |
295 | 0 | pOUNeighbours[2]->iBackgroundFlag + pOUNeighbours[3]->iBackgroundFlag; |
296 | 0 | int32_t sumNbrBGsad = (pOUNeighbours[0]->iSAD & (-pOUNeighbours[0]->iBackgroundFlag)) + (pOUNeighbours[2]->iSAD & |
297 | 0 | (-pOUNeighbours[2]->iBackgroundFlag)) |
298 | 0 | + (pOUNeighbours[1]->iSAD & (-pOUNeighbours[1]->iBackgroundFlag)) + (pOUNeighbours[3]->iSAD & |
299 | 0 | (-pOUNeighbours[3]->iBackgroundFlag)); |
300 | 0 | if (pBackgroundOU->iSAD * iSumNeighBackgroundFlags <= (3 * sumNbrBGsad) >> 1) { |
301 | 0 | if (iSumNeighBackgroundFlags == 4) { |
302 | 0 | pBackgroundOU->iBackgroundFlag = 1; |
303 | 0 | } else { |
304 | 0 | if ((pOUNeighbours[0]->iBackgroundFlag & pOUNeighbours[1]->iBackgroundFlag) |
305 | 0 | || (pOUNeighbours[2]->iBackgroundFlag & pOUNeighbours[3]->iBackgroundFlag)) { |
306 | 0 | pBackgroundOU->iBackgroundFlag = !ForegroundDilation23Luma (pBackgroundOU, pOUNeighbours); |
307 | 0 | } |
308 | 0 | } |
309 | 0 | } |
310 | 0 | } |
311 | 0 | } |
312 | | |
313 | | inline void CBackgroundDetection::SetBackgroundMbFlag (int8_t* pBackgroundMbFlag, int32_t iPicWidthInMb, |
314 | 0 | int32_t iBackgroundMbFlag) { |
315 | 0 | *pBackgroundMbFlag = iBackgroundMbFlag; |
316 | 0 | } |
317 | | |
318 | | inline void CBackgroundDetection::UpperOUForegroundCheck (SBackgroundOU* pCurOU, int8_t* pBackgroundMbFlag, |
319 | 0 | int32_t iPicWidthInOU, int32_t iPicWidthInMb) { |
320 | 0 | if (pCurOU->iSAD > BGD_OU_SIZE * Q_FACTOR) { |
321 | 0 | SBackgroundOU* pOU_L = pCurOU - 1; |
322 | 0 | SBackgroundOU* pOU_R = pCurOU + 1; |
323 | 0 | SBackgroundOU* pOU_U = pCurOU - iPicWidthInOU; |
324 | 0 | SBackgroundOU* pOU_D = pCurOU + iPicWidthInOU; |
325 | 0 | if (pOU_L->iBackgroundFlag + pOU_R->iBackgroundFlag + pOU_U->iBackgroundFlag + pOU_D->iBackgroundFlag <= 1) { |
326 | 0 | SetBackgroundMbFlag (pBackgroundMbFlag, iPicWidthInMb, 0); |
327 | 0 | pCurOU->iBackgroundFlag = 0; |
328 | 0 | } |
329 | 0 | } |
330 | 0 | } |
331 | | |
332 | 0 | void CBackgroundDetection::ForegroundDilationAndBackgroundErosion (vBGDParam* pBgdParam) { |
333 | 0 | int32_t iPicStrideUV = pBgdParam->iStride[1]; |
334 | 0 | int32_t iPicWidthInOU = pBgdParam->iBgdWidth >> LOG2_BGD_OU_SIZE; |
335 | 0 | int32_t iPicHeightInOU = pBgdParam->iBgdHeight >> LOG2_BGD_OU_SIZE; |
336 | 0 | int32_t iOUStrideUV = iPicStrideUV << (LOG2_BGD_OU_SIZE - 1); |
337 | 0 | int32_t iPicWidthInMb = (15 + pBgdParam->iBgdWidth) >> 4; |
338 | |
|
339 | 0 | SBackgroundOU* pBackgroundOU = pBgdParam->pOU_array; |
340 | 0 | int8_t* pVaaBackgroundMbFlag = (int8_t*)pBgdParam->pBackgroundMbFlag; |
341 | 0 | SBackgroundOU* pOUNeighbours[4];//0: left; 1: right; 2: top; 3: bottom |
342 | |
|
343 | 0 | pOUNeighbours[2] = pBackgroundOU;//top OU |
344 | 0 | for (int32_t j = 0; j < iPicHeightInOU; j ++) { |
345 | 0 | int8_t* pRowSkipFlag = pVaaBackgroundMbFlag; |
346 | 0 | pOUNeighbours[0] = pBackgroundOU;//left OU |
347 | 0 | pOUNeighbours[3] = pBackgroundOU + (iPicWidthInOU & ((j == iPicHeightInOU - 1) - 1)); //bottom OU |
348 | 0 | for (int32_t i = 0; i < iPicWidthInOU; i++) { |
349 | 0 | pOUNeighbours[1] = pBackgroundOU + (i < iPicWidthInOU - 1); //right OU |
350 | |
|
351 | 0 | if (pBackgroundOU->iBackgroundFlag) |
352 | 0 | ForegroundDilation (pBackgroundOU, pOUNeighbours, pBgdParam, j * iOUStrideUV + (i << LOG2_BGD_OU_SIZE_UV)); |
353 | 0 | else |
354 | 0 | BackgroundErosion (pBackgroundOU, pOUNeighbours); |
355 | | |
356 | | // check the up OU |
357 | 0 | if (j > 1 && i > 0 && i < iPicWidthInOU - 1 && pOUNeighbours[2]->iBackgroundFlag == 1) { |
358 | 0 | UpperOUForegroundCheck (pOUNeighbours[2], pRowSkipFlag - OU_SIZE_IN_MB * iPicWidthInMb, iPicWidthInOU, iPicWidthInMb); |
359 | 0 | } |
360 | |
|
361 | 0 | SetBackgroundMbFlag (pRowSkipFlag, iPicWidthInMb, pBackgroundOU->iBackgroundFlag); |
362 | | |
363 | | // preparation for the next OU |
364 | 0 | pRowSkipFlag += OU_SIZE_IN_MB; |
365 | 0 | pOUNeighbours[0] = pBackgroundOU; |
366 | 0 | pOUNeighbours[2]++; |
367 | 0 | pOUNeighbours[3]++; |
368 | 0 | pBackgroundOU++; |
369 | 0 | } |
370 | 0 | pOUNeighbours[2] = pBackgroundOU - iPicWidthInOU; |
371 | 0 | pVaaBackgroundMbFlag += OU_SIZE_IN_MB * iPicWidthInMb; |
372 | 0 | } |
373 | 0 | } |
374 | | |
375 | 0 | void CBackgroundDetection::BackgroundDetection (vBGDParam* pBgdParam) { |
376 | | // 1st step: foreground/background coarse division |
377 | 0 | ForegroundBackgroundDivision (pBgdParam); |
378 | | |
379 | | // 2nd step: foreground dilation and background erosion |
380 | 0 | ForegroundDilationAndBackgroundErosion (pBgdParam); |
381 | 0 | } |
382 | | |
383 | | WELSVP_NAMESPACE_END |