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 41 OSCL_EXPORT_REF BitStreamParser::BitStreamParser(uint8* stream, uint32 size) 42 { 43 ResetBitStreamParser(stream, size); 44 } 45 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 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 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 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 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 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 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 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 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 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