1 /*!
2 * \copy
3 * Copyright (c) 2009-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 * \file set_mb_syn_cavlc.h
33 *
34 * \brief Seting all syntax elements of mb and decoding residual with cavlc
35 *
36 * \date 05/19/2009 Created
37 *
38 *************************************************************************************
39 */
40
41 #include "svc_set_mb_syn.h"
42 #include "vlc_encoder.h"
43 #include "cpu_core.h"
44 #include "wels_const.h"
45
46 namespace WelsEnc {
47
48 const ALIGNED_DECLARE (uint8_t, g_kuiZeroLeftMap[16], 16) = {
49 0, 1, 2, 3, 4, 5, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7
50 };
51
52
53 /*
54 * Exponential Golomb codes encoding routines
55 */
56
57 #define CAVLC_BS_INIT( pBs ) \
58 uint8_t * pBufPtr = pBs->pCurBuf; \
59 uint32_t uiCurBits = pBs->uiCurBits; \
60 int32_t iLeftBits = pBs->iLeftBits;
61
62 #define CAVLC_BS_UNINIT( pBs ) \
63 pBs->pCurBuf = pBufPtr; \
64 pBs->uiCurBits = uiCurBits; \
65 pBs->iLeftBits = iLeftBits;
66
67 #define CAVLC_BS_WRITE( n, v ) \
68 { \
69 if ( (n) < iLeftBits ) {\
70 uiCurBits = (uiCurBits<<(n))|(v);\
71 iLeftBits -= (n);\
72 }\
73 else {\
74 (n) -= iLeftBits;\
75 uiCurBits = (uiCurBits<<iLeftBits) | ((v)>>(n));\
76 WRITE_BE_32(pBufPtr, uiCurBits);\
77 pBufPtr += 4;\
78 uiCurBits = (v) & ((1<<(n))-1);\
79 iLeftBits = 32 - (n);\
80 }\
81 } ;
82
83
CavlcParamCal_c(int16_t * pCoffLevel,uint8_t * pRun,int16_t * pLevel,int32_t * pTotalCoeff,int32_t iLastIndex)84 int32_t CavlcParamCal_c (int16_t* pCoffLevel, uint8_t* pRun, int16_t* pLevel, int32_t* pTotalCoeff ,
85 int32_t iLastIndex) {
86 int32_t iTotalZeros = 0;
87 int32_t iTotalCoeffs = 0;
88
89 while (iLastIndex >= 0 && pCoffLevel[iLastIndex] == 0) {
90 -- iLastIndex;
91 }
92
93 while (iLastIndex >= 0) {
94 int32_t iCountZero = 0;
95 pLevel[iTotalCoeffs] = pCoffLevel[iLastIndex--];
96
97 while (iLastIndex >= 0 && pCoffLevel[iLastIndex] == 0) {
98 ++ iCountZero;
99 -- iLastIndex;
100 }
101 iTotalZeros += iCountZero;
102 pRun[iTotalCoeffs++] = iCountZero;
103 }
104 *pTotalCoeff = iTotalCoeffs;
105 return iTotalZeros;
106 }
107
WriteBlockResidualCavlc(SWelsFuncPtrList * pFuncList,int16_t * pCoffLevel,int32_t iEndIdx,int32_t iCalRunLevelFlag,int32_t iResidualProperty,int8_t iNC,SBitStringAux * pBs)108 int32_t WriteBlockResidualCavlc (SWelsFuncPtrList* pFuncList, int16_t* pCoffLevel, int32_t iEndIdx,
109 int32_t iCalRunLevelFlag,
110 int32_t iResidualProperty, int8_t iNC, SBitStringAux* pBs) {
111 ENFORCE_STACK_ALIGN_1D (int16_t, iLevel, 16, 16)
112 ENFORCE_STACK_ALIGN_1D (uint8_t, uiRun, 16, 16)
113
114 int32_t iTotalCoeffs = 0;
115 int32_t iTrailingOnes = 0;
116 int32_t iTotalZeros = 0, iZerosLeft = 0;
117 uint32_t uiSign = 0;
118 int32_t iLevelCode = 0, iLevelPrefix = 0, iLevelSuffix = 0, uiSuffixLength = 0, iLevelSuffixSize = 0;
119 int32_t iValue = 0, iThreshold, iZeroLeft;
120 int32_t n = 0;
121 int32_t i = 0;
122
123
124 CAVLC_BS_INIT (pBs);
125
126 /*Step 1: calculate iLevel and iRun and total */
127
128 if (iCalRunLevelFlag) {
129 int32_t iCount = 0;
130 iTotalZeros = pFuncList->pfCavlcParamCal (pCoffLevel, uiRun, iLevel, &iTotalCoeffs, iEndIdx);
131 iCount = (iTotalCoeffs > 3) ? 3 : iTotalCoeffs;
132 for (i = 0; i < iCount ; i++) {
133 if (WELS_ABS (iLevel[i]) == 1) {
134 iTrailingOnes ++;
135 uiSign <<= 1;
136 if (iLevel[i] < 0)
137 uiSign |= 1;
138 } else {
139 break;
140
141 }
142 }
143 }
144 /*Step 3: coeff token */
145 const uint8_t* upCoeffToken = &g_kuiVlcCoeffToken[g_kuiEncNcMapTable[iNC]][iTotalCoeffs][iTrailingOnes][0];
146 iValue = upCoeffToken[0];
147 n = upCoeffToken[1];
148
149 if (iTotalCoeffs == 0) {
150 CAVLC_BS_WRITE (n, iValue);
151
152 CAVLC_BS_UNINIT (pBs);
153 return ENC_RETURN_SUCCESS;
154 }
155
156 /* Step 4: */
157 /* trailing */
158 n += iTrailingOnes;
159 iValue = (iValue << iTrailingOnes) + uiSign;
160 CAVLC_BS_WRITE (n, iValue);
161
162 /* levels */
163 uiSuffixLength = (iTotalCoeffs > 10 && iTrailingOnes < 3) ? 1 : 0;
164
165 for (i = iTrailingOnes; i < iTotalCoeffs; i++) {
166 int32_t iVal = iLevel[i];
167
168 iLevelCode = (iVal - 1) * (1 << 1);
169 uiSign = (iLevelCode >> 31);
170 iLevelCode = (iLevelCode ^ uiSign) + (uiSign << 1);
171 iLevelCode -= ((i == iTrailingOnes) && (iTrailingOnes < 3)) << 1;
172
173 iLevelPrefix = iLevelCode >> uiSuffixLength;
174 iLevelSuffixSize = uiSuffixLength;
175 iLevelSuffix = iLevelCode - (iLevelPrefix << uiSuffixLength);
176
177 if (iLevelPrefix >= 14 && iLevelPrefix < 30 && uiSuffixLength == 0) {
178 iLevelPrefix = 14;
179 iLevelSuffix = iLevelCode - iLevelPrefix;
180 iLevelSuffixSize = 4;
181 } else if (iLevelPrefix >= 15) {
182 iLevelPrefix = 15;
183 iLevelSuffix = iLevelCode - (iLevelPrefix << uiSuffixLength);
184 //for baseline profile,overflow when the length of iLevelSuffix is larger than 11.
185 if (iLevelSuffix >> 11)
186 return ENC_RETURN_VLCOVERFLOWFOUND;
187 if (uiSuffixLength == 0) {
188 iLevelSuffix -= 15;
189 }
190 iLevelSuffixSize = 12;
191 }
192
193 n = iLevelPrefix + 1 + iLevelSuffixSize;
194 iValue = ((1 << iLevelSuffixSize) | iLevelSuffix);
195 CAVLC_BS_WRITE (n, iValue);
196
197 uiSuffixLength += !uiSuffixLength;
198 iThreshold = 3 << (uiSuffixLength - 1);
199 uiSuffixLength += ((iVal > iThreshold) || (iVal < -iThreshold)) && (uiSuffixLength < 6);
200
201 }
202
203 /* Step 5: total zeros */
204
205 if (iTotalCoeffs < iEndIdx + 1) {
206 if (CHROMA_DC != iResidualProperty) {
207 const uint8_t* upTotalZeros = &g_kuiVlcTotalZeros[iTotalCoeffs][iTotalZeros][0];
208 n = upTotalZeros[1];
209 iValue = upTotalZeros[0];
210 CAVLC_BS_WRITE (n, iValue);
211 } else {
212 const uint8_t* upTotalZeros = &g_kuiVlcTotalZerosChromaDc[iTotalCoeffs][iTotalZeros][0];
213 n = upTotalZeros[1];
214 iValue = upTotalZeros[0];
215 CAVLC_BS_WRITE (n, iValue);
216 }
217 }
218
219 /* Step 6: pRun before */
220 iZerosLeft = iTotalZeros;
221 for (i = 0; i + 1 < iTotalCoeffs && iZerosLeft > 0; ++ i) {
222 const uint8_t uirun = uiRun[i];
223 iZeroLeft = g_kuiZeroLeftMap[iZerosLeft];
224 n = g_kuiVlcRunBefore[iZeroLeft][uirun][1];
225 iValue = g_kuiVlcRunBefore[iZeroLeft][uirun][0];
226 CAVLC_BS_WRITE (n, iValue);
227 iZerosLeft -= uirun;
228 }
229
230 CAVLC_BS_UNINIT (pBs);
231 return ENC_RETURN_SUCCESS;
232 }
233
StashMBStatusCavlc(SDynamicSlicingStack * pDss,SSlice * pSlice,int32_t iMbSkipRun)234 void StashMBStatusCavlc (SDynamicSlicingStack* pDss, SSlice* pSlice, int32_t iMbSkipRun) {
235 SBitStringAux* pBs = pSlice->pSliceBsa;
236 pDss->pBsStackBufPtr = pBs->pCurBuf;
237 pDss->uiBsStackCurBits = pBs->uiCurBits;
238 pDss->iBsStackLeftBits = pBs->iLeftBits;
239 pDss->uiLastMbQp = pSlice->uiLastMbQp;
240 pDss->iMbSkipRunStack = iMbSkipRun;
241 }
StashPopMBStatusCavlc(SDynamicSlicingStack * pDss,SSlice * pSlice)242 int32_t StashPopMBStatusCavlc (SDynamicSlicingStack* pDss, SSlice* pSlice) {
243 SBitStringAux* pBs = pSlice->pSliceBsa;
244 pBs->pCurBuf = pDss->pBsStackBufPtr;
245 pBs->uiCurBits = pDss->uiBsStackCurBits;
246 pBs->iLeftBits = pDss->iBsStackLeftBits;
247 pSlice->uiLastMbQp = pDss->uiLastMbQp;
248 return pDss->iMbSkipRunStack;
249 }
StashMBStatusCabac(SDynamicSlicingStack * pDss,SSlice * pSlice,int32_t iMbSkipRun)250 void StashMBStatusCabac (SDynamicSlicingStack* pDss, SSlice* pSlice, int32_t iMbSkipRun) {
251 SCabacCtx* pCtx = &pSlice->sCabacCtx;
252 memcpy (&pDss->sStoredCabac, pCtx, sizeof (SCabacCtx));
253 if (pDss->pRestoreBuffer) {
254 int32_t iPosBitOffset = GetBsPosCabac (pSlice) - pDss->iStartPos;
255 int32_t iLen = ((iPosBitOffset >> 3) + ((iPosBitOffset & 0x07) ? 1 : 0));
256 memcpy (pDss->pRestoreBuffer, pCtx->m_pBufStart, iLen);
257 }
258 pDss->uiLastMbQp = pSlice->uiLastMbQp;
259 pDss->iMbSkipRunStack = iMbSkipRun;
260 }
StashPopMBStatusCabac(SDynamicSlicingStack * pDss,SSlice * pSlice)261 int32_t StashPopMBStatusCabac (SDynamicSlicingStack* pDss, SSlice* pSlice) {
262 SCabacCtx* pCtx = &pSlice->sCabacCtx;
263 memcpy (pCtx, &pDss->sStoredCabac, sizeof (SCabacCtx));
264 if (pDss->pRestoreBuffer) {
265 int32_t iPosBitOffset = GetBsPosCabac (pSlice) - pDss->iStartPos;
266 int32_t iLen = ((iPosBitOffset >> 3) + ((iPosBitOffset & 0x07) ? 1 : 0));
267 memcpy (pCtx->m_pBufStart, pDss->pRestoreBuffer, iLen);
268 }
269 pSlice->uiLastMbQp = pDss->uiLastMbQp;
270 return pDss->iMbSkipRunStack;
271 }
GetBsPosCavlc(SSlice * pSlice)272 int32_t GetBsPosCavlc (SSlice* pSlice) {
273 return BsGetBitsPos (pSlice->pSliceBsa);
274 }
GetBsPosCabac(SSlice * pSlice)275 int32_t GetBsPosCabac (SSlice* pSlice) {
276 return (int32_t) ((pSlice->sCabacCtx.m_pBufCur - pSlice->sCabacCtx.m_pBufStart) << 3) +
277 (pSlice->sCabacCtx.m_iLowBitCnt - 9);
278 }
WelsWriteSliceEndSyn(SSlice * pSlice,bool bEntropyCodingModeFlag)279 void WelsWriteSliceEndSyn (SSlice* pSlice, bool bEntropyCodingModeFlag) {
280 SBitStringAux* pBs = pSlice->pSliceBsa;
281 if (bEntropyCodingModeFlag) {
282 WelsCabacEncodeFlush (&pSlice->sCabacCtx);
283 pBs->pCurBuf = WelsCabacEncodeGetPtr (&pSlice->sCabacCtx);
284
285 } else {
286 BsRbspTrailingBits (pBs);
287 BsFlush (pBs);
288 }
289 }
InitCoeffFunc(SWelsFuncPtrList * pFuncList,const uint32_t uiCpuFlag,int32_t iEntropyCodingModeFlag)290 void InitCoeffFunc (SWelsFuncPtrList* pFuncList, const uint32_t uiCpuFlag, int32_t iEntropyCodingModeFlag) {
291 pFuncList->pfCavlcParamCal = CavlcParamCal_c;
292
293 #if defined(X86_32_ASM)
294 if (uiCpuFlag & WELS_CPU_SSE2) {
295 pFuncList->pfCavlcParamCal = CavlcParamCal_sse2;
296 }
297 #endif
298
299 #ifdef X86_ASM
300 if (uiCpuFlag & WELS_CPU_SSE42) {
301 pFuncList->pfCavlcParamCal = CavlcParamCal_sse42;
302 }
303 #endif
304 if (iEntropyCodingModeFlag) {
305 pFuncList->pfStashMBStatus = StashMBStatusCabac;
306 pFuncList->pfStashPopMBStatus = StashPopMBStatusCabac;
307 pFuncList->pfWelsSpatialWriteMbSyn = WelsSpatialWriteMbSynCabac;
308 pFuncList->pfGetBsPosition = GetBsPosCabac;
309 } else {
310 pFuncList->pfStashMBStatus = StashMBStatusCavlc;
311 pFuncList->pfStashPopMBStatus = StashPopMBStatusCavlc;
312 pFuncList->pfWelsSpatialWriteMbSyn = WelsSpatialWriteMbSyn;
313 pFuncList->pfGetBsPosition = GetBsPosCavlc;
314 }
315 }
316
317
318 } // namespace WelsEnc
319