armVCM4P10_DecodeCoeffsToPair.c revision 78e52bfac041d71ce53b5b13c2abf78af742b09d
1/*
2 * Copyright (C) 2007-2008 ARM Limited
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *
16 */
17/* ----------------------------------------------------------------
18 *
19 *
20 * File Name:  armVCM4P10_DecodeCoeffsToPair.c
21 * OpenMAX DL: v1.0.2
22 * Revision:   9641
23 * Date:       Thursday, February 7, 2008
24 *
25 *
26 *
27 *
28 * H.264 decode coefficients module
29 *
30 */
31
32#ifdef DEBUG_ARMVCM4P10_DECODECOEFFSTOPAIR
33#undef DEBUG_ON
34#define DEBUG_ON
35#endif
36
37#include "omxtypes.h"
38#include "armOMX.h"
39#include "omxVC.h"
40
41#include "armCOMM.h"
42#include "armCOMM_Bitstream.h"
43#include "armVCM4P10_CAVLCTables.h"
44
45/* 4x4 DeZigZag table */
46
47static const OMX_U8 armVCM4P10_ZigZag[16] =
48{
49    0, 1, 4, 8, 5, 2, 3, 6, 9, 12, 13, 10, 7, 11, 14, 15
50};
51
52/*
53 * Description:
54 * This function perform the work required by the OpenMAX
55 * DecodeCoeffsToPair function and DecodeChromaDCCoeffsToPair.
56 * Since most of the code is common we share it here.
57 *
58 * Parameters:
59 * [in]	ppBitStream		Double pointer to current byte in bit stream buffer
60 * [in]	pOffset			Pointer to current bit position in the byte pointed
61 *								to by *ppBitStream
62 * [in]	sMaxNumCoeff	Maximum number of non-zero coefficients in current
63 *								block (4,15 or 16)
64 * [in]	nTable          Table number (0 to 4) according to the five columns
65 *                      of Table 9-5 in the H.264 spec
66 * [out]	ppBitStream		*ppBitStream is updated after each block is decoded
67 * [out]	pOffset			*pOffset is updated after each block is decoded
68 * [out]	pNumCoeff		Pointer to the number of nonzero coefficients in
69 *								this block
70 * [out]	ppPosCoefbuf	Double pointer to destination residual
71 *								coefficient-position pair buffer
72 * Return Value:
73 * Standard omxError result. See enumeration for possible result codes.
74
75 */
76
77OMXResult armVCM4P10_DecodeCoeffsToPair(
78     const OMX_U8** ppBitStream,
79     OMX_S32* pOffset,
80     OMX_U8* pNumCoeff,
81     OMX_U8  **ppPosCoefbuf,
82     OMX_INT nTable,
83     OMX_INT sMaxNumCoeff
84 )
85{
86    int CoeffToken, TotalCoeff, TrailingOnes;
87    int Level, LevelCode, LevelPrefix, LevelSuffix, LevelSuffixSize;
88    int SuffixLength, Run, ZerosLeft,CoeffNum;
89    int i, Flags;
90    OMX_U8 *pPosCoefbuf = *ppPosCoefbuf;
91    OMX_S16 pLevel[16];
92    OMX_U8  pRun[16];
93
94    CoeffToken = armUnPackVLC32(ppBitStream, pOffset, armVCM4P10_CAVLCCoeffTokenTables[nTable]);
95    armRetDataErrIf(CoeffToken == ARM_NO_CODEBOOK_INDEX, OMX_Sts_Err);
96
97    TrailingOnes = armVCM4P10_CAVLCTrailingOnes[CoeffToken];
98    TotalCoeff   = armVCM4P10_CAVLCTotalCoeff[CoeffToken];
99    *pNumCoeff   = (OMX_U8)TotalCoeff;
100
101    DEBUG_PRINTF_2("TotalCoeff = %d, TrailingOnes = %d\n", TotalCoeff, TrailingOnes);
102
103    if (TotalCoeff == 0)
104    {
105        /* Nothing to do */
106        return OMX_Sts_NoErr;
107    }
108
109    /* Decode trailing ones */
110    for (i=TotalCoeff-1; i>=TotalCoeff-TrailingOnes; i--)
111    {
112        if (armGetBits(ppBitStream, pOffset, 1))
113        {
114            Level = -1;
115        }
116        else
117        {
118            Level = +1;
119        }
120        pLevel[i] = (OMX_S16)Level;
121
122        DEBUG_PRINTF_2("Level[%d] = %d\n", i, pLevel[i]);
123    }
124
125    /* Decode (non zero) level values */
126    SuffixLength = 0;
127    if (TotalCoeff>10 && TrailingOnes<3)
128    {
129        SuffixLength=1;
130    }
131    for ( ; i>=0; i--)
132    {
133        LevelPrefix = armUnPackVLC32(ppBitStream, pOffset, armVCM4P10_CAVLCLevelPrefix);
134        armRetDataErrIf(LevelPrefix == ARM_NO_CODEBOOK_INDEX, OMX_Sts_Err);
135
136        LevelSuffixSize = SuffixLength;
137        if (LevelPrefix==14 && SuffixLength==0)
138        {
139            LevelSuffixSize = 4;
140        }
141        if (LevelPrefix==15)
142        {
143            LevelSuffixSize = 12;
144        }
145
146        LevelSuffix = 0;
147        if (LevelSuffixSize > 0)
148        {
149            LevelSuffix = armGetBits(ppBitStream, pOffset, LevelSuffixSize);
150        }
151
152        LevelCode = (LevelPrefix << SuffixLength) + LevelSuffix;
153
154
155        if (LevelPrefix==15 && SuffixLength==0)
156        {
157            LevelCode += 15;
158        }
159
160        /* LevelCode = 2*(magnitude-1) + sign */
161
162        if (i==TotalCoeff-1-TrailingOnes && TrailingOnes<3)
163        {
164            /* Level magnitude can't be 1 */
165            LevelCode += 2;
166        }
167        if (LevelCode & 1)
168        {
169            /* 2a+1 maps to -a-1 */
170            Level = (-LevelCode-1)>>1;
171        }
172        else
173        {
174            /* 2a+0 maps to +a+1 */
175            Level = (LevelCode+2)>>1;
176        }
177        pLevel[i] = (OMX_S16)Level;
178
179        DEBUG_PRINTF_2("Level[%d] = %d\n", i, pLevel[i]);
180
181        if (SuffixLength==0)
182        {
183            SuffixLength=1;
184        }
185        if ( ((LevelCode>>1)+1)>(3<<(SuffixLength-1)) && SuffixLength<6 )
186        {
187            SuffixLength++;
188        }
189    }
190
191    /* Decode run values */
192    ZerosLeft = 0;
193    if (TotalCoeff < sMaxNumCoeff)
194    {
195        /* Decode TotalZeros VLC */
196        if (sMaxNumCoeff==4)
197        {
198            ZerosLeft = armUnPackVLC32(ppBitStream, pOffset, armVCM4P10_CAVLCTotalZeros2x2Tables[TotalCoeff-1]);
199            armRetDataErrIf(ZerosLeft ==ARM_NO_CODEBOOK_INDEX , OMX_Sts_Err);
200        }
201        else
202        {
203            ZerosLeft = armUnPackVLC32(ppBitStream, pOffset, armVCM4P10_CAVLCTotalZeroTables[TotalCoeff-1]);
204             armRetDataErrIf(ZerosLeft ==ARM_NO_CODEBOOK_INDEX , OMX_Sts_Err);
205	    }
206    }
207
208    DEBUG_PRINTF_1("TotalZeros = %d\n", ZerosLeft);
209
210	CoeffNum=ZerosLeft+TotalCoeff-1;
211
212    for (i=TotalCoeff-1; i>0; i--)
213    {
214        Run = 0;
215        if (ZerosLeft > 0)
216        {
217            int Table = ZerosLeft;
218            if (Table > 6)
219            {
220                Table = 7;
221            }
222            Run = armUnPackVLC32(ppBitStream, pOffset, armVCM4P10_CAVLCRunBeforeTables[Table-1]);
223            armRetDataErrIf(Run == ARM_NO_CODEBOOK_INDEX, OMX_Sts_Err);
224        }
225        pRun[i] = (OMX_U8)Run;
226
227        DEBUG_PRINTF_2("Run[%d] = %d\n", i, pRun[i]);
228
229        ZerosLeft -= Run;
230    }
231    pRun[0] = (OMX_U8)ZerosLeft;
232
233    DEBUG_PRINTF_1("Run[0] = %d\n", pRun[i]);
234
235
236    /* Fill in coefficients */
237
238    if (sMaxNumCoeff==15)
239    {
240        CoeffNum++; /* Skip the DC position */
241    }
242
243	/*for (i=0;i<TotalCoeff;i++)
244		CoeffNum += pRun[i]+1;*/
245
246	for (i=(TotalCoeff-1); i>=0; i--)
247    {
248        /*CoeffNum += pRun[i]+1;*/
249        Level     = pLevel[i];
250
251        DEBUG_PRINTF_2("Coef[%d] = %d\n", CoeffNum, Level);
252
253        Flags = CoeffNum;
254		CoeffNum -= (pRun[i]+1);
255        if (sMaxNumCoeff>4)
256        {
257            /* Perform 4x4 DeZigZag */
258            Flags = armVCM4P10_ZigZag[Flags];
259        }
260        if (i==0)
261        {
262            /* End of block flag */
263            Flags += 0x20;
264        }
265        if (Level<-128 || Level>127)
266        {
267            /* Overflow flag */
268            Flags += 0x10;
269        }
270
271        *pPosCoefbuf++ = (OMX_U8)(Flags);
272        *pPosCoefbuf++ = (OMX_U8)(Level & 0xFF);
273        if (Flags & 0x10)
274        {
275            *pPosCoefbuf++ = (OMX_U8)(Level>>8);
276        }
277    }
278
279    *ppPosCoefbuf = pPosCoefbuf;
280
281    return OMX_Sts_NoErr;
282}
283