• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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