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