mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-25 22:01:30 +00:00
d6a0eb9d74
MozReview-Commit-ID: 9fM2VjY4Ckk --HG-- extra : rebase_source : 24d971d44e1d9bd8b1589b4b542d792f75df376d
161 lines
2.9 KiB
C++
161 lines
2.9 KiB
C++
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
// Derived from Stagefright's ABitReader.
|
|
|
|
#include "BitReader.h"
|
|
|
|
namespace mozilla
|
|
{
|
|
|
|
BitReader::BitReader(const mozilla::MediaByteBuffer* aBuffer)
|
|
: BitReader(aBuffer->Elements(), aBuffer->Length() * 8)
|
|
{
|
|
}
|
|
|
|
BitReader::BitReader(const mozilla::MediaByteBuffer* aBuffer, size_t aBits)
|
|
: BitReader(aBuffer->Elements(), aBits)
|
|
{
|
|
}
|
|
|
|
BitReader::BitReader(const uint8_t* aBuffer, size_t aBits)
|
|
: mData(aBuffer)
|
|
, mOriginalBitSize(aBits)
|
|
, mTotalBitsLeft(aBits)
|
|
, mSize((aBits + 7) / 8)
|
|
, mReservoir(0)
|
|
, mNumBitsLeft(0)
|
|
{
|
|
}
|
|
|
|
BitReader::~BitReader() { }
|
|
|
|
uint32_t
|
|
BitReader::ReadBits(size_t aNum)
|
|
{
|
|
MOZ_ASSERT(aNum <= 32);
|
|
if (mTotalBitsLeft < aNum) {
|
|
NS_ASSERTION(false, "Reading past end of buffer");
|
|
return 0;
|
|
}
|
|
uint32_t result = 0;
|
|
while (aNum > 0) {
|
|
if (mNumBitsLeft == 0) {
|
|
FillReservoir();
|
|
}
|
|
|
|
size_t m = aNum;
|
|
if (m > mNumBitsLeft) {
|
|
m = mNumBitsLeft;
|
|
}
|
|
|
|
result = (result << m) | (mReservoir >> (32 - m));
|
|
mReservoir <<= m;
|
|
mNumBitsLeft -= m;
|
|
mTotalBitsLeft -= m;
|
|
|
|
aNum -= m;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
// Read unsigned integer Exp-Golomb-coded.
|
|
uint32_t
|
|
BitReader::ReadUE()
|
|
{
|
|
uint32_t i = 0;
|
|
|
|
while (ReadBit() == 0 && i < 32) {
|
|
i++;
|
|
}
|
|
if (i == 32) {
|
|
// This can happen if the data is invalid, or if it's
|
|
// short, since ReadBit() will return 0 when it runs
|
|
// off the end of the buffer.
|
|
NS_WARNING("Invalid H.264 data");
|
|
return 0;
|
|
}
|
|
uint32_t r = ReadBits(i);
|
|
r += (1 << i) - 1;
|
|
return r;
|
|
}
|
|
|
|
// Read signed integer Exp-Golomb-coded.
|
|
int32_t
|
|
BitReader::ReadSE()
|
|
{
|
|
int32_t r = ReadUE();
|
|
if (r & 1) {
|
|
return (r+1) / 2;
|
|
} else {
|
|
return -r / 2;
|
|
}
|
|
}
|
|
|
|
uint64_t
|
|
BitReader::ReadU64()
|
|
{
|
|
uint64_t hi = ReadU32();
|
|
uint32_t lo = ReadU32();
|
|
return (hi << 32) | lo;
|
|
}
|
|
|
|
uint64_t
|
|
BitReader::ReadUTF8()
|
|
{
|
|
int64_t val = ReadBits(8);
|
|
uint32_t top = (val & 0x80) >> 1;
|
|
|
|
if ((val & 0xc0) == 0x80 || val >= 0xFE) {
|
|
// error.
|
|
return -1;
|
|
}
|
|
while (val & top) {
|
|
int tmp = ReadBits(8) - 128;
|
|
if (tmp >> 6) {
|
|
// error.
|
|
return -1;
|
|
}
|
|
val = (val << 6) + tmp;
|
|
top <<= 5;
|
|
}
|
|
val &= (top << 1) - 1;
|
|
return val;
|
|
}
|
|
|
|
size_t
|
|
BitReader::BitCount() const
|
|
{
|
|
return mOriginalBitSize - mTotalBitsLeft;
|
|
}
|
|
|
|
size_t
|
|
BitReader::BitsLeft() const
|
|
{
|
|
return mTotalBitsLeft;
|
|
}
|
|
|
|
void
|
|
BitReader::FillReservoir()
|
|
{
|
|
if (mSize == 0) {
|
|
NS_ASSERTION(false, "Attempting to fill reservoir from past end of data");
|
|
return;
|
|
}
|
|
|
|
mReservoir = 0;
|
|
size_t i;
|
|
for (i = 0; mSize > 0 && i < 4; i++) {
|
|
mReservoir = (mReservoir << 8) | *mData;
|
|
mData++;
|
|
mSize--;
|
|
}
|
|
|
|
mNumBitsLeft = 8 * i;
|
|
mReservoir <<= 32 - mNumBitsLeft;
|
|
}
|
|
|
|
} // namespace mozilla
|