blob: d6505d2139c62184dbeaf395136d1667c54354e4 [file] [log] [blame]
/*
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "bitstream_parser.h"
namespace webrtc {
BitstreamParser::BitstreamParser(const uint8_t* data, const uint32_t dataLength) :
_data(data),
_dataLength(dataLength),
_byteOffset(0),
_bitOffset(0)
{
}
// todo should we have any error codes from this?
uint8_t
BitstreamParser::Get1Bit()
{
uint8_t retVal = 0x1 & (_data[_byteOffset] >> (7-_bitOffset++));
// prepare next byte
if(_bitOffset == 8)
{
_bitOffset = 0;
_byteOffset++;
}
return retVal;
}
uint8_t
BitstreamParser::Get2Bits()
{
uint8_t retVal = (Get1Bit() << 1);
retVal += Get1Bit();
return retVal;
}
uint8_t
BitstreamParser::Get3Bits()
{
uint8_t retVal = (Get1Bit() << 2);
retVal += (Get1Bit() << 1);
retVal += Get1Bit();
return retVal;
}
uint8_t
BitstreamParser::Get4Bits()
{
uint8_t retVal = (Get1Bit() << 3);
retVal += (Get1Bit() << 2);
retVal += (Get1Bit() << 1);
retVal += Get1Bit();
return retVal;
}
uint8_t
BitstreamParser::Get5Bits()
{
uint8_t retVal = (Get1Bit() << 4);
retVal += (Get1Bit() << 3);
retVal += (Get1Bit() << 2);
retVal += (Get1Bit() << 1);
retVal += Get1Bit();
return retVal;
}
uint8_t
BitstreamParser::Get6Bits()
{
uint8_t retVal = (Get1Bit() << 5);
retVal += (Get1Bit() << 4);
retVal += (Get1Bit() << 3);
retVal += (Get1Bit() << 2);
retVal += (Get1Bit() << 1);
retVal += Get1Bit();
return retVal;
}
uint8_t
BitstreamParser::Get7Bits()
{
uint8_t retVal = (Get1Bit() << 6);
retVal += (Get1Bit() << 5);
retVal += (Get1Bit() << 4);
retVal += (Get1Bit() << 3);
retVal += (Get1Bit() << 2);
retVal += (Get1Bit() << 1);
retVal += Get1Bit();
return retVal;
}
uint8_t
BitstreamParser::Get8Bits()
{
uint16_t retVal;
if(_bitOffset != 0)
{
// read 16 bits
retVal = (_data[_byteOffset] << 8)+ (_data[_byteOffset+1]) ;
retVal = retVal >> (8-_bitOffset);
} else
{
retVal = _data[_byteOffset];
}
_byteOffset++;
return (uint8_t)retVal;
}
uint16_t
BitstreamParser::Get16Bits()
{
uint32_t retVal;
if(_bitOffset != 0)
{
// read 24 bits
retVal = (_data[_byteOffset] << 16) + (_data[_byteOffset+1] << 8) + (_data[_byteOffset+2]);
retVal = retVal >> (8-_bitOffset);
}else
{
// read 16 bits
retVal = (_data[_byteOffset] << 8) + (_data[_byteOffset+1]) ;
}
_byteOffset += 2;
return (uint16_t)retVal;
}
uint32_t
BitstreamParser::Get24Bits()
{
uint32_t retVal;
if(_bitOffset != 0)
{
// read 32 bits
retVal = (_data[_byteOffset] << 24) + (_data[_byteOffset+1] << 16) + (_data[_byteOffset+2] << 8) + (_data[_byteOffset+3]);
retVal = retVal >> (8-_bitOffset);
}else
{
// read 24 bits
retVal = (_data[_byteOffset] << 16) + (_data[_byteOffset+1] << 8) + (_data[_byteOffset+2]) ;
}
_byteOffset += 3;
return retVal & 0x00ffffff; // we need to clean up the high 8 bits
}
uint32_t
BitstreamParser::Get32Bits()
{
uint32_t retVal;
if(_bitOffset != 0)
{
// read 40 bits
uint64_t tempVal = _data[_byteOffset];
tempVal <<= 8;
tempVal += _data[_byteOffset+1];
tempVal <<= 8;
tempVal += _data[_byteOffset+2];
tempVal <<= 8;
tempVal += _data[_byteOffset+3];
tempVal <<= 8;
tempVal += _data[_byteOffset+4];
tempVal >>= (8-_bitOffset);
retVal = uint32_t(tempVal);
}else
{
// read 32 bits
retVal = (_data[_byteOffset]<< 24) + (_data[_byteOffset+1] << 16) + (_data[_byteOffset+2] << 8) + (_data[_byteOffset+3]) ;
}
_byteOffset += 4;
return retVal;
}
// Exp-Golomb codes
/*
with "prefix" and "suffix" bits and assignment to codeNum ranges (informative)
Bit string form Range of codeNum
1 0
0 1 x0 1..2
0 0 1 x1 x0 3..6
0 0 0 1 x2 x1 x0 7..14
0 0 0 0 1 x3 x2 x1 x0 15..30
0 0 0 0 0 1 x4 x3 x2 x1 x0 31..62
*/
uint32_t
BitstreamParser::GetUE()
{
uint32_t retVal = 0;
uint8_t numLeadingZeros = 0;
while (Get1Bit() != 1)
{
numLeadingZeros++;
}
// prefix
retVal = (1 << numLeadingZeros) - 1;
// suffix
while (numLeadingZeros)
{
retVal += (Get1Bit() << --numLeadingZeros);
}
return retVal;
}
} // namespace webrtc