• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* ------------------------------------------------------------------
2  * Copyright (C) 1998-2009 PacketVideo
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
13  * express or implied.
14  * See the License for the specific language governing permissions
15  * and limitations under the License.
16  * -------------------------------------------------------------------
17  */
18 #ifndef   BITSTREAMPARSER_H_INCLUDED
19 #include "bitstreamparser.h"
20 #endif
21 #ifndef   OSCL_ASSERT_H_INCLUDED
22 #include "oscl_assert.h"
23 #endif
24 #ifndef   OSCL_BYTE_ORDER_H_INCLUDED
25 #include "oscl_byte_order.h"
26 #endif
27 #ifndef   OSCL_DLL_H_INCLUDED
28 #include "oscl_dll.h"
29 #endif
30 #ifndef   OSCL_ERROR_H_INCLUDED
31 #include "oscl_error.h"
32 #endif
33 #ifndef   OSCL_ERROR_CODES_H_INCLUDED
34 #include "oscl_error_codes.h"
35 #endif
36 #ifndef   OSCL_EXCEPTION_H_INCLUDED
37 #include "oscl_exception.h"
38 #endif
39 
40 
BitStreamParser(uint8 * stream,uint32 size)41 OSCL_EXPORT_REF BitStreamParser::BitStreamParser(uint8* stream, uint32 size)
42 {
43     ResetBitStreamParser(stream, size);
44 }
45 
ResetBitStreamParser(uint8 * stream,uint32 size)46 OSCL_EXPORT_REF void BitStreamParser::ResetBitStreamParser(uint8* stream, uint32 size)
47 {
48     this->size = size;
49     start   = OSCL_STATIC_CAST(uint8*, stream);
50     bytepos = OSCL_STATIC_CAST(uint8*, start);
51     bitpos  = MOST_SIG_BIT;
52 }
53 
ReadBits(uint8 numberOfBits)54 OSCL_EXPORT_REF uint32 BitStreamParser::ReadBits(uint8 numberOfBits)
55 {
56     //Initialize output to zero before shifting out bits.
57     uint32 output = 0;
58 
59     OSCL_ASSERT(numberOfBits <= BITS_PER_UINT32);
60     //In case OSCL_ASSERT is defined to do nothing, set the max size.
61     if (numberOfBits > BITS_PER_UINT32) numberOfBits = BITS_PER_UINT32;
62 
63     //Note: Using the host's native shift operator will automatically
64     //convert from big endian to host's endianness.
65     while (numberOfBits)
66     {
67         // Make sure bytepos won't exceed the size of the buffer while reading
68         if (bytepos >= (start + size))
69         {
70             OSCL_LEAVE(OsclErrOverflow);
71         }
72 
73         //Optimize reads for special cases such as byte-aligned reads and
74         //processing multiple bits at a time.
75         if ((numberOfBits >= BITS_PER_UINT8) && (bitpos == MOST_SIG_BIT))
76         {
77             //This is the special case where a read is a whole byte (aligned).
78             //Shift the output over 8 bits.
79             output <<= BITS_PER_UINT8;
80             //OR the current byte from the stream into the output.
81             output |= *bytepos;
82             //Advance the stream byte pointer.
83             bytepos++;
84             //Decrement the number of bits left to read.
85             numberOfBits -= BITS_PER_UINT8;
86         }
87         else    //Read one or more bits at a time.
88         {
89             //Define the bitmask corresponding to the number of bits
90             //to read from the current byte.
91             //This is implemented as a static look-up table for efficiency.
92             static const uint8 bitmask[] =
93             {
94                 0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff
95             };
96 
97             //Process the bits in the current byte...
98 
99             //Determine the number of bits remaining in the current byte of the stream.
100             //This is the upper limit on the number of bits we will read
101             //this through the loop.
102             uint8 bitsFromThisByte = bitpos + 1;
103             //If more bits remain then we need, only take what we need.
104             if (bitsFromThisByte > numberOfBits) bitsFromThisByte = numberOfBits;
105 
106             //Shift the output value over to make room for the new bits to read.
107             output <<= bitsFromThisByte;
108             //OR in the bits from the stream.
109             //This reads the current byte from the stream,
110             //shifts it over so the bits we want are at the LS end,
111             //and masks off all of the bits except the ones we want.
112             output |= ((*bytepos) >> (bitpos - (bitsFromThisByte - 1))) & bitmask[bitsFromThisByte];
113 
114             //Decrement the numberOfBits remaining...
115             numberOfBits -= bitsFromThisByte;
116             //...and advance the bitpos and bytepos pointers.
117             NextBits(bitsFromThisByte);
118         }
119     }
120 
121     return output;
122 }
123 
124 
ReadUInt8(void)125 OSCL_EXPORT_REF uint8 BitStreamParser::ReadUInt8(void)
126 {
127     //If bitpos is not on a byte boundary, have to use ReadBits...
128     if (bitpos != MOST_SIG_BIT) return ReadBits(BITS_PER_UINT8);
129 
130     // Make sure the current bytepos doesn't exceed the size of the buffer
131     if (bytepos >= (start + size))
132     {
133         OSCL_LEAVE(OsclErrOverflow);
134     }
135     uint8 read = *bytepos;
136     bytepos++;
137 
138     return read;
139 }
140 
141 
ReadUInt16(void)142 OSCL_EXPORT_REF uint16 BitStreamParser::ReadUInt16(void)
143 {
144     uint16 read;
145     ((uint8*)&read)[0] = ReadUInt8();
146     ((uint8*)&read)[1] = ReadUInt8();
147     big_endian_to_host((char*)&read, sizeof(read));
148     return read;
149 }
150 
151 
ReadUInt32(void)152 OSCL_EXPORT_REF uint32 BitStreamParser::ReadUInt32(void)
153 {
154     uint32 read;
155     ((uint8*)&read)[0] = ReadUInt8();
156     ((uint8*)&read)[1] = ReadUInt8();
157     ((uint8*)&read)[2] = ReadUInt8();
158     ((uint8*)&read)[3] = ReadUInt8();
159     big_endian_to_host((char*)&read, sizeof(read));
160     return read;
161 }
162 
163 
WriteBits(uint8 numberOfBits,const uint8 * data)164 OSCL_EXPORT_REF void BitStreamParser::WriteBits(uint8 numberOfBits, const uint8* data)
165 {
166     //This is not the most efficient algorithm, but it is the least complex.
167     //Treat "data" as an input stream.
168     BitStreamParser input(const_cast<uint8*>(data), BITS_TO_BYTES(numberOfBits));
169     //Skip over the unused bits.
170     input.NextBits(input.BitsLeft() - numberOfBits);
171     //Loop through each bit to process...
172     while (numberOfBits)
173     {
174         uint8 bitmask = 1 << bitpos;
175         //READ
176         uint8 byte = *bytepos;
177         //MODIFY
178         byte &= ~(bitmask);                      //Clear the bit being written.
179         byte |= (input.ReadBits(1) << bitpos); //Write the bit.
180         //WRITE
181         *bytepos = byte;
182         //Advance the bit pointer
183         NextBit();
184         numberOfBits--;
185     }
186 }
187 
188 
WriteUInt8(uint8 data)189 OSCL_EXPORT_REF void BitStreamParser::WriteUInt8(uint8 data)
190 {
191     if (bitpos != MOST_SIG_BIT)
192     {
193         WriteBits(BITS_PER_BYTE, &data);
194     }
195     else
196     {
197         if (bytepos >= (start + size))
198         {
199             OSCL_LEAVE(OsclErrOverflow);
200         }
201         *bytepos = data;
202         bytepos++;
203     }
204 }
205 
206 
WriteUInt16(uint16 data)207 OSCL_EXPORT_REF void BitStreamParser::WriteUInt16(uint16 data)
208 {
209     uint16 be = data;
210     host_to_big_endian((char*)&be, sizeof(be));
211     WriteUInt8(((uint8*)&be)[0]);
212     WriteUInt8(((uint8*)&be)[1]);
213 }
214 
215 
WriteUInt32(uint32 data)216 OSCL_EXPORT_REF void BitStreamParser::WriteUInt32(uint32 data)
217 {
218     uint32 be = data;
219     host_to_big_endian((char*)&be, sizeof(be));
220     WriteUInt8(((uint8*)&be)[0]);
221     WriteUInt8(((uint8*)&be)[1]);
222     WriteUInt8(((uint8*)&be)[2]);
223     WriteUInt8(((uint8*)&be)[3]);
224 }
225 
226 
NextBits(uint32 numberOfBits)227 OSCL_EXPORT_REF void BitStreamParser::NextBits(uint32 numberOfBits)
228 {
229     //bitpos counts down from 7 to 0, so subtract it from 7 to get the ascending position.
230     uint32 newbitpos = numberOfBits  + (MOST_SIG_BIT - bitpos);
231     //Convert the ascending bit position to a descending position using only the least-significant bits.
232     bitpos = MOST_SIG_BIT - (newbitpos & LEAST_SIG_3_BITS_MASK);
233     //Calculate the number of bytes advanced.
234     bytepos += (newbitpos / BITS_PER_BYTE);
235     // Make sure bytepos won't exceed the size of the buffer while reading
236     if (bytepos >= (start + size))
237     {
238         OSCL_LEAVE(OsclErrOverflow);
239     }
240 }
241 
242