VideoCodec/Encoder/BinaryStreamBuilder.cpp
#include "BinaryStreamBuilder.h"
namespace VideoCodec
{
BinaryStreamBuilder::BinaryStreamBuilder()
{
this->isInitialized = false;
}
BinaryStreamBuilder::~BinaryStreamBuilder()
{
}
void BinaryStreamBuilder::AllocateStream(FrameDataBitLength streamSizeBits)
{
if (this->isInitialized)
{
Logger::LogMessage("Warning: The binary stream builder has already been initialized.");
delete this->data;
}
// There are eight bits for each unsigned char in the underlying array.
this->data = new unsigned char[streamSizeBits % 8 != 0 ? (streamSizeBits >> 3) + 1 : streamSizeBits >> 3];
this->dataIndex = 0;
this->workingPosition = 0;
this->workingValue = 0;
this->writtenBitCount = 0;
this->streamCapacity = streamSizeBits;
this->isInitialized = true;
}
void BinaryStreamBuilder::PutValue(unsigned short int value, unsigned char bitCount)
{
if (!this->isInitialized)
{
Logger::LogMessage("Warning: Binary stream was not initialized.");
return;
}
// If bitCount exceeds the size of the data type for the value being put into the stream,
// we put zeros in for the first bits which overhang the edge of the value.
if (bitCount > 16)
this->PutValue(0x0000, bitCount - 16);
// Move the MSB so that it is at the highest position.
// The value is then copied in by shifting the input value and the working value to the left
// and copying bits.
value <<= (16 - bitCount);
// Write bits into the working value until we run out of bits or the working value has no more bits left.
while (bitCount != 0)
{
this->workingValue |= ((value & 0x8000) >> 15);
if (this->workingPosition == 7)
{
// Flush the working value into the data array and move onto the next one.
this->data[this->dataIndex] = this->workingValue;
this->dataIndex++;
this->workingValue = 0;
this->workingPosition = 0;
}
else
{
this->workingValue <<= 1;
this->workingPosition++;
}
value <<= 1;
bitCount--;
this->writtenBitCount++;
}
}
void BinaryStreamBuilder::AlignStream()
{
// If some bits are outstanding in the working data, write them and advance the current index.
if (this->workingPosition != 0)
{
this->workingValue <<= 7 - this->workingPosition;
this->data[this->dataIndex] = this->workingValue;
this->workingValue = 0x00;
this->writtenBitCount += 8 - this->workingPosition;
this->workingPosition = 0;
this->dataIndex++;
}
}
unsigned char* BinaryStreamBuilder::GetStream()
{
if (!this->workingPosition == 0)
{
Logger::LogMessage("Warning: AlignStream() was not called before retrieving the underlying binary data. Unalign bits may have been lost.");
}
return this->data;
}
long int BinaryStreamBuilder::GetWrittenBitCount()
{
return this->writtenBitCount;
}
long int BinaryStreamBuilder::GetStreamCapacity()
{
return this->streamCapacity;
}
}