/* 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/. */ #include "BitWriter.h" #include "MediaData.h" #include "mozilla/MathAlgorithms.h" namespace mozilla { constexpr uint8_t golombLen[256] = { 1, 3, 3, 5, 5, 5, 5, 7, 7, 7, 7, 7, 7, 7, 7, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 17, }; BitWriter::BitWriter(MediaByteBuffer* aBuffer) : mBuffer(aBuffer) {} BitWriter::~BitWriter() = default; void BitWriter::WriteBits(uint64_t aValue, size_t aBits) { MOZ_ASSERT(aBits <= sizeof(uint64_t) * 8); while (aBits) { if (mBitIndex == 0) { mBuffer->AppendElement(0); } const uint8_t clearMask = ~(~0u << (8 - mBitIndex)); uint8_t mask = 0; if (mBitIndex + aBits > 8) { // Not enough bits in the current byte to write all the bits // required, we'll process what we can and continue with the left over. const uint8_t leftOverBits = mBitIndex + aBits - 8; const uint64_t leftOver = aValue & (~uint64_t(0) >> (8 - mBitIndex)); mask = aValue >> leftOverBits; mBitIndex = 8; aValue = leftOver; aBits = leftOverBits; } else { const uint8_t offset = 8 - mBitIndex - aBits; mask = aValue << offset; mBitIndex += aBits; aBits = 0; } mBuffer->ElementAt(mPosition) |= mask & clearMask; if (mBitIndex == 8) { mPosition++; mBitIndex = 0; } } } void BitWriter::WriteUE(uint32_t aValue) { MOZ_ASSERT(aValue <= (UINT32_MAX - 1)); if (aValue < 256) { WriteBits(aValue + 1, golombLen[aValue]); } else { const uint32_t e = FloorLog2(aValue + 1); WriteBits(aValue + 1, e * 2 + 1); } } void BitWriter::WriteULEB128(uint64_t aValue) { // See https://en.wikipedia.org/wiki/LEB128#Encode_unsigned_integer do { uint8_t byte = aValue & 0x7F; aValue >>= 7; WriteBit(aValue != 0); WriteBits(byte, 7); } while (aValue != 0); } void BitWriter::CloseWithRbspTrailing() { WriteBit(true); WriteBits(0, (8 - mBitIndex) & 7); } } // namespace mozilla