/* * 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 WebRtc_UWord8* data, const WebRtc_UWord32 dataLength) : _data(data), _dataLength(dataLength), _byteOffset(0), _bitOffset(0) { } // todo should we have any error codes from this? WebRtc_UWord8 BitstreamParser::Get1Bit() { WebRtc_UWord8 retVal = 0x1 & (_data[_byteOffset] >> (7-_bitOffset++)); // prepare next byte if(_bitOffset == 8) { _bitOffset = 0; _byteOffset++; } return retVal; } WebRtc_UWord8 BitstreamParser::Get2Bits() { WebRtc_UWord8 retVal = (Get1Bit() << 1); retVal += Get1Bit(); return retVal; } WebRtc_UWord8 BitstreamParser::Get3Bits() { WebRtc_UWord8 retVal = (Get1Bit() << 2); retVal += (Get1Bit() << 1); retVal += Get1Bit(); return retVal; } WebRtc_UWord8 BitstreamParser::Get4Bits() { WebRtc_UWord8 retVal = (Get1Bit() << 3); retVal += (Get1Bit() << 2); retVal += (Get1Bit() << 1); retVal += Get1Bit(); return retVal; } WebRtc_UWord8 BitstreamParser::Get5Bits() { WebRtc_UWord8 retVal = (Get1Bit() << 4); retVal += (Get1Bit() << 3); retVal += (Get1Bit() << 2); retVal += (Get1Bit() << 1); retVal += Get1Bit(); return retVal; } WebRtc_UWord8 BitstreamParser::Get6Bits() { WebRtc_UWord8 retVal = (Get1Bit() << 5); retVal += (Get1Bit() << 4); retVal += (Get1Bit() << 3); retVal += (Get1Bit() << 2); retVal += (Get1Bit() << 1); retVal += Get1Bit(); return retVal; } WebRtc_UWord8 BitstreamParser::Get7Bits() { WebRtc_UWord8 retVal = (Get1Bit() << 6); retVal += (Get1Bit() << 5); retVal += (Get1Bit() << 4); retVal += (Get1Bit() << 3); retVal += (Get1Bit() << 2); retVal += (Get1Bit() << 1); retVal += Get1Bit(); return retVal; } WebRtc_UWord8 BitstreamParser::Get8Bits() { WebRtc_UWord16 retVal; if(_bitOffset != 0) { // read 16 bits retVal = (_data[_byteOffset] << 8)+ (_data[_byteOffset+1]) ; retVal = retVal >> (8-_bitOffset); } else { retVal = _data[_byteOffset]; } _byteOffset++; return (WebRtc_UWord8)retVal; } WebRtc_UWord16 BitstreamParser::Get16Bits() { WebRtc_UWord32 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 (WebRtc_UWord16)retVal; } WebRtc_UWord32 BitstreamParser::Get24Bits() { WebRtc_UWord32 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 } WebRtc_UWord32 BitstreamParser::Get32Bits() { WebRtc_UWord32 retVal; if(_bitOffset != 0) { // read 40 bits WebRtc_UWord64 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 = WebRtc_UWord32(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 */ WebRtc_UWord32 BitstreamParser::GetUE() { WebRtc_UWord32 retVal = 0; WebRtc_UWord8 numLeadingZeros = 0; while (Get1Bit() != 1) { numLeadingZeros++; } // prefix retVal = (1 << numLeadingZeros) - 1; // suffix while (numLeadingZeros) { retVal += (Get1Bit() << --numLeadingZeros); } return retVal; } } // namespace webrtc