armCOMM_Bitstream.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 * File Name:  armCOMM_Bitstream.c
20 * OpenMAX DL: v1.0.2
21 * Revision:   9641
22 * Date:       Thursday, February 7, 2008
23 *
24 *
25 *
26 *
27 * Defines bitstream encode and decode functions common to all codecs
28 */
29
30#include "omxtypes.h"
31#include "armCOMM.h"
32#include "armCOMM_Bitstream.h"
33
34/***************************************
35 * Fixed bit length Decode
36 ***************************************/
37
38/**
39 * Function: armLookAheadBits()
40 *
41 * Description:
42 * Get the next N bits from the bitstream without advancing the bitstream pointer
43 *
44 * Parameters:
45 * [in]     **ppBitStream
46 * [in]     *pOffset
47 * [in]     N=1...32
48 *
49 * Returns  Value
50 */
51
52OMX_U32 armLookAheadBits(const OMX_U8 **ppBitStream, OMX_INT *pOffset, OMX_INT N)
53{
54    const OMX_U8 *pBitStream = *ppBitStream;
55    OMX_INT Offset = *pOffset;
56    OMX_U32 Value;
57
58    armAssert(Offset>=0 && Offset<=7);
59    armAssert(N>=1 && N<=32);
60
61    /* Read next 32 bits from stream */
62    Value = (pBitStream[0] << 24 ) | ( pBitStream[1] << 16)  | (pBitStream[2] << 8 ) | (pBitStream[3]) ;
63    Value = (Value << Offset ) | (pBitStream[4] >> (8-Offset));
64
65    /* Return N bits */
66    return Value >> (32-N);
67}
68
69
70/**
71 * Function: armGetBits()
72 *
73 * Description:
74 * Read N bits from the bitstream
75 *
76 * Parameters:
77 * [in]     *ppBitStream
78 * [in]     *pOffset
79 * [in]     N=1..32
80 *
81 * [out]    *ppBitStream
82 * [out]    *pOffset
83 * Returns  Value
84 */
85
86
87OMX_U32 armGetBits(const OMX_U8 **ppBitStream, OMX_INT *pOffset, OMX_INT N)
88{
89    const OMX_U8 *pBitStream = *ppBitStream;
90    OMX_INT Offset = *pOffset;
91    OMX_U32 Value;
92
93    if(N == 0)
94    {
95      return 0;
96    }
97
98    armAssert(Offset>=0 && Offset<=7);
99    armAssert(N>=1 && N<=32);
100
101    /* Read next 32 bits from stream */
102    Value = (pBitStream[0] << 24 ) | ( pBitStream[1] << 16)  | (pBitStream[2] << 8 ) | (pBitStream[3]) ;
103    Value = (Value << Offset ) | (pBitStream[4] >> (8-Offset));
104
105    /* Advance bitstream pointer by N bits */
106    Offset += N;
107    *ppBitStream = pBitStream + (Offset>>3);
108    *pOffset = Offset & 7;
109
110    /* Return N bits */
111    return Value >> (32-N);
112}
113
114/**
115 * Function: armByteAlign()
116 *
117 * Description:
118 * Align the pointer *ppBitStream to the next byte boundary
119 *
120 * Parameters:
121 * [in]     *ppBitStream
122 * [in]     *pOffset
123 *
124 * [out]    *ppBitStream
125 * [out]    *pOffset
126 *
127 **/
128
129OMXVoid armByteAlign(const OMX_U8 **ppBitStream,OMX_INT *pOffset)
130{
131    if(*pOffset > 0)
132    {
133        *ppBitStream += 1;
134        *pOffset = 0;
135    }
136}
137
138/**
139 * Function: armSkipBits()
140 *
141 * Description:
142 * Skip N bits from the value at *ppBitStream
143 *
144 * Parameters:
145 * [in]     *ppBitStream
146 * [in]     *pOffset
147 * [in]     N
148 *
149 * [out]    *ppBitStream
150 * [out]    *pOffset
151 *
152 **/
153
154
155OMXVoid armSkipBits(const OMX_U8 **ppBitStream,OMX_INT *pOffset,OMX_INT N)
156{
157    OMX_INT Offset = *pOffset;
158    const OMX_U8 *pBitStream = *ppBitStream;
159
160    /* Advance bitstream pointer by N bits */
161    Offset += N;
162    *ppBitStream = pBitStream + (Offset>>3);
163    *pOffset = Offset & 7;
164}
165
166/***************************************
167 * Variable bit length Decode
168 ***************************************/
169
170/**
171 * Function: armUnPackVLC32()
172 *
173 * Description:
174 * Variable length decode of variable length symbol (max size 32 bits) read from
175 * the bit stream pointed by *ppBitStream at *pOffset by using the table
176 * pointed by pCodeBook
177 *
178 * Parameters:
179 * [in]     *pBitStream
180 * [in]     *pOffset
181 * [in]     pCodeBook
182 *
183 * [out]    *pBitStream
184 * [out]    *pOffset
185 *
186 * Returns : Code Book Index if successfull.
187 *         : ARM_NO_CODEBOOK_INDEX = -1 if search fails.
188 **/
189#ifndef C_OPTIMIZED_IMPLEMENTATION
190
191OMX_U16 armUnPackVLC32(
192    const OMX_U8 **ppBitStream,
193    OMX_INT *pOffset,
194    const ARM_VLC32 *pCodeBook
195)
196{
197    const OMX_U8 *pBitStream = *ppBitStream;
198    OMX_INT Offset = *pOffset;
199    OMX_U32 Value;
200    OMX_INT Index;
201
202    armAssert(Offset>=0 && Offset<=7);
203
204    /* Read next 32 bits from stream */
205    Value = (pBitStream[0] << 24 ) | ( pBitStream[1] << 16)  | (pBitStream[2] << 8 ) | (pBitStream[3]) ;
206    Value = (Value << Offset ) | (pBitStream[4] >> (8-Offset));
207
208    /* Search through the codebook */
209    for (Index=0; pCodeBook->codeLen != 0; Index++)
210    {
211        if (pCodeBook->codeWord == (Value >> (32 - pCodeBook->codeLen)))
212        {
213            Offset       = Offset + pCodeBook->codeLen;
214            *ppBitStream = pBitStream + (Offset >> 3) ;
215            *pOffset     = Offset & 7;
216
217            return Index;
218        }
219        pCodeBook++;
220    }
221
222    /* No code match found */
223    return ARM_NO_CODEBOOK_INDEX;
224}
225
226#endif
227
228/***************************************
229 * Fixed bit length Encode
230 ***************************************/
231
232/**
233 * Function: armPackBits
234 *
235 * Description:
236 * Pack a VLC code word into the bitstream
237 *
238 * Remarks:
239 *
240 * Parameters:
241 * [in] ppBitStream     pointer to the pointer to the current byte
242 *                      in the bit stream.
243 * [in] pOffset         pointer to the bit position in the byte
244 *                      pointed by *ppBitStream. Valid within 0
245 *                      to 7.
246 * [in] codeWord        Code word that need to be inserted in to the
247 *                          bitstream
248 * [in] codeLength      Length of the code word valid range 1...32
249 *
250 * [out] ppBitStream    *ppBitStream is updated after the block is encoded,
251 *                          so that it points to the current byte in the bit
252 *                          stream buffer.
253 * [out] pBitOffset     *pBitOffset is updated so that it points to the
254 *                          current bit position in the byte pointed by
255 *                          *ppBitStream.
256 *
257 * Return Value:
258 * Standard OMX_RESULT result. See enumeration for possible result codes.
259 *
260 */
261
262OMXResult armPackBits (
263    OMX_U8  **ppBitStream,
264    OMX_INT *pOffset,
265    OMX_U32 codeWord,
266    OMX_INT codeLength
267)
268{
269    OMX_U8  *pBitStream = *ppBitStream;
270    OMX_INT Offset = *pOffset;
271    OMX_U32 Value;
272
273    /* checking argument validity */
274    armRetArgErrIf(Offset < 0, OMX_Sts_BadArgErr);
275    armRetArgErrIf(Offset > 7, OMX_Sts_BadArgErr);
276    armRetArgErrIf(codeLength < 1, OMX_Sts_BadArgErr);
277    armRetArgErrIf(codeLength > 32, OMX_Sts_BadArgErr);
278
279    /* Prepare the first byte */
280    codeWord = codeWord << (32-codeLength);
281    Value = (pBitStream[0] >> (8-Offset)) << (8-Offset);
282    Value = Value | (codeWord >> (24+Offset));
283
284    /* Write out whole bytes */
285    while (8-Offset <= codeLength)
286    {
287        *pBitStream++ = (OMX_U8)Value;
288        codeWord   = codeWord  << (8-Offset);
289        codeLength = codeLength - (8-Offset);
290        Offset = 0;
291        Value = codeWord >> 24;
292    }
293
294    /* Write out final partial byte */
295    *pBitStream  = (OMX_U8)Value;
296    *ppBitStream = pBitStream;
297    *pOffset = Offset + codeLength;
298
299    return  OMX_Sts_NoErr;
300}
301
302/***************************************
303 * Variable bit length Encode
304 ***************************************/
305
306/**
307 * Function: armPackVLC32
308 *
309 * Description:
310 * Pack a VLC code word into the bitstream
311 *
312 * Remarks:
313 *
314 * Parameters:
315 * [in]	ppBitStream		pointer to the pointer to the current byte
316 *                      in the bit stream.
317 * [in]	pBitOffset	    pointer to the bit position in the byte
318 *                      pointed by *ppBitStream. Valid within 0
319 *                      to 7.
320 * [in]	 code     		VLC code word that need to be inserted in to the
321 *                      bitstream
322 *
323 * [out] ppBitStream	*ppBitStream is updated after the block is encoded,
324 *	                    so that it points to the current byte in the bit
325 *						stream buffer.
326 * [out] pBitOffset		*pBitOffset is updated so that it points to the
327 *						current bit position in the byte pointed by
328 *						*ppBitStream.
329 *
330 * Return Value:
331 * Standard OMX_RESULT result. See enumeration for possible result codes.
332 *
333 */
334
335OMXResult armPackVLC32 (
336    OMX_U8 **ppBitStream,
337    OMX_INT *pBitOffset,
338    ARM_VLC32 code
339)
340{
341    return (armPackBits(ppBitStream, pBitOffset, code.codeWord, code.codeLen));
342}
343
344/*End of File*/
345