您最多选择25个主题
主题必须以中文或者字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
130 行
4.0 KiB
130 行
4.0 KiB
using UnityEngine;
|
|
|
|
namespace NetworkCompression
|
|
{
|
|
public struct HuffmanInputStream : IInputStream
|
|
{
|
|
public HuffmanInputStream(NetworkCompressionModel model, byte[] buffer, int bufferOffset)
|
|
{
|
|
m_Model = model;
|
|
m_Buffer = buffer;
|
|
m_CurrentBitIndex = 0;
|
|
m_CurrentByteIndex = bufferOffset;
|
|
m_BitBuffer = 0;
|
|
}
|
|
|
|
public void Initialize(NetworkCompressionModel model, byte[] buffer, int bufferOffset)
|
|
{
|
|
this = new HuffmanInputStream(model, buffer, bufferOffset);
|
|
}
|
|
|
|
public uint ReadRawBits(int numbits)
|
|
{
|
|
FillBitBuffer();
|
|
return ReadRawBitsInternal(numbits);
|
|
}
|
|
|
|
public void ReadRawBytes(byte[] dstBuffer, int dstIndex, int count)
|
|
{
|
|
for (int i = 0; i < count; i++)
|
|
dstBuffer[dstIndex + i] = (byte)ReadRawBits(8);
|
|
}
|
|
|
|
public void SkipRawBits(int numbits)
|
|
{
|
|
// TODO: implement this properly
|
|
while (numbits >= 32)
|
|
{
|
|
ReadRawBits(32);
|
|
numbits -= 32;
|
|
}
|
|
ReadRawBits(numbits);
|
|
}
|
|
|
|
public void SkipRawBytes(int count)
|
|
{
|
|
SkipRawBits(count * 8);
|
|
}
|
|
|
|
public uint ReadPackedNibble(int context)
|
|
{
|
|
FillBitBuffer();
|
|
uint peekMask = (1u << NetworkCompressionConstants.k_MaxHuffmanSymbolLength) - 1u;
|
|
uint peekBits = (uint)m_BitBuffer & peekMask;
|
|
ushort huffmanEntry = m_Model.decodeTable[context, peekBits];
|
|
int symbol = huffmanEntry >> 8;
|
|
int length = huffmanEntry & 0xFF;
|
|
|
|
// Skip Huffman bits
|
|
m_BitBuffer >>= length;
|
|
m_CurrentBitIndex -= length;
|
|
return (uint)symbol;
|
|
}
|
|
|
|
public uint ReadPackedUInt(int context)
|
|
{
|
|
FillBitBuffer();
|
|
uint peekMask = (1u << NetworkCompressionConstants.k_MaxHuffmanSymbolLength) - 1u;
|
|
uint peekBits = (uint)m_BitBuffer & peekMask;
|
|
ushort huffmanEntry = m_Model.decodeTable[context, peekBits];
|
|
int symbol = huffmanEntry >> 8;
|
|
int length = huffmanEntry & 0xFF;
|
|
|
|
// Skip Huffman bits
|
|
m_BitBuffer >>= length;
|
|
m_CurrentBitIndex -= length;
|
|
|
|
uint offset = NetworkCompressionConstants.k_BucketOffsets[symbol];
|
|
int bits = NetworkCompressionConstants.k_BucketSizes[symbol];
|
|
return ReadRawBitsInternal(bits) + offset;
|
|
}
|
|
|
|
public int ReadPackedIntDelta(int baseline, int context)
|
|
{
|
|
return (int)ReadPackedUIntDelta((uint)baseline, context);
|
|
}
|
|
|
|
public uint ReadPackedUIntDelta(uint baseline, int context)
|
|
{
|
|
uint folded = ReadPackedUInt(context);
|
|
uint delta = (folded >> 1) ^ (uint)-(int)(folded & 1); // Deinterleave values from [0, -1, 1, -2, 2...] to [..., -2, -1, -0, 1, 2, ...]
|
|
return baseline - delta;
|
|
}
|
|
|
|
public int GetBitPosition2()
|
|
{
|
|
return m_CurrentByteIndex * 8 - m_CurrentBitIndex;
|
|
}
|
|
|
|
public NetworkCompressionModel GetModel()
|
|
{
|
|
return m_Model;
|
|
}
|
|
|
|
|
|
uint ReadRawBitsInternal(int numbits)
|
|
{
|
|
Debug.Assert(numbits >= 0 && numbits <= 32); //TODO: change back to Debug.Assert
|
|
Debug.Assert(m_CurrentBitIndex >= numbits);
|
|
uint res = (uint)(m_BitBuffer & ((1UL << numbits) - 1UL));
|
|
m_BitBuffer >>= numbits;
|
|
m_CurrentBitIndex -= numbits;
|
|
return res;
|
|
}
|
|
|
|
void FillBitBuffer()
|
|
{
|
|
while (m_CurrentBitIndex <= 56)
|
|
{
|
|
m_BitBuffer |= (ulong)m_Buffer[m_CurrentByteIndex++] << m_CurrentBitIndex;
|
|
m_CurrentBitIndex += 8;
|
|
}
|
|
}
|
|
|
|
NetworkCompressionModel m_Model;
|
|
byte[] m_Buffer;
|
|
ulong m_BitBuffer;
|
|
int m_CurrentBitIndex;
|
|
int m_CurrentByteIndex;
|
|
}
|
|
}
|