public void Initialize() { Util.Verify(endAddress - startAddress >= 1, startAddress, "Bitstream is empty"); this.input.BaseStream.Seek(endAddress - 1, SeekOrigin.Begin); int lastByte = this.input.ReadByte() & 0xFF; Util.Verify(lastByte != 0, endAddress, "Bitstream end mark not present"); bitsConsumed = Constants.SIZE_OF_LONG - Util.HighestBit(lastByte); int inputSize = (int)(endAddress - startAddress); if (inputSize >= Constants.SIZE_OF_LONG) { /* normal case */ this.currentAddress = this.endAddress - Constants.SIZE_OF_LONG; this.input.BaseStream.Seek(this.currentAddress, SeekOrigin.Begin); this.bits = this.input.ReadInt64(); } else { this.currentAddress = this.startAddress; bits = BitInputStream.ReadTail(this.input, this.startAddress, inputSize); bitsConsumed += (Constants.SIZE_OF_LONG - inputSize) * 8; } }
private void DecodeTail(BinaryReader inputReader, long startAddress, long currentAddress, int bitsConsumed, long bits, BinaryWriter outputWriter, long outputAddress, long outputLimit) { int tableLog = this.tableLog; byte[] numbersOfBits = this.numbersOfBits; byte[] symbols = this.symbols; // closer to the end while (outputAddress < outputLimit) { BitInputStreamLoader loader = new BitInputStreamLoader(inputReader, startAddress, currentAddress, bits, bitsConsumed); bool done = loader.Load(); bitsConsumed = loader.GetBitsConsumed(); bits = loader.GetBits(); currentAddress = loader.GetCurrentAddress(); if (done) { break; } bitsConsumed = DecodeSymbol(outputWriter, outputAddress++, bits, bitsConsumed, tableLog, numbersOfBits, symbols); } // not more data in bit stream, so no need to reload while (outputAddress < outputLimit) { bitsConsumed = DecodeSymbol(outputWriter, outputAddress++, bits, bitsConsumed, tableLog, numbersOfBits, symbols); } Util.Verify(BitInputStream.IsEndOfStream(startAddress, currentAddress, bitsConsumed), startAddress, "Bit stream is not fully consumed"); }
private static int DecodeSymbol(BinaryWriter outputWriter, long outputAddress, long bitContainer, int bitsConsumed, int tableLog, byte[] numbersOfBits, byte[] symbols) { int value = (int)BitInputStream.PeekBitsFast(bitsConsumed, bitContainer, tableLog); outputWriter.BaseStream.Seek(outputAddress, SeekOrigin.Begin); outputWriter.Write(symbols[value]); return(bitsConsumed + numbersOfBits[value]); }
public static int Decompress(FiniteStateEntropyTable table, BinaryReader inputReader, long inputAddress, long inputLimit, byte[] outputBuffer) { BinaryWriter outputWriter = new BinaryWriter(new MemoryStream(outputBuffer)); long outputAddress = 0; long outputLimit = outputAddress + outputBuffer.Length; long input = inputAddress; long output = outputAddress; // initialize bit stream BitInputStreamInitializer initializer = new BitInputStreamInitializer(inputReader, input, inputLimit); initializer.Initialize(); int bitsConsumed = initializer.GetBitsConsumed(); long currentAddress = initializer.GetCurrentAddress(); long bits = initializer.GetBits(); // initialize first FSE stream int state1 = (int)BitInputStream.PeekBits(bitsConsumed, bits, table.log2Size); bitsConsumed += table.log2Size; BitInputStreamLoader loader = new BitInputStreamLoader(inputReader, input, currentAddress, bits, bitsConsumed); loader.Load(); bits = loader.GetBits(); bitsConsumed = loader.GetBitsConsumed(); currentAddress = loader.GetCurrentAddress(); // initialize second FSE stream int state2 = (int)BitInputStream.PeekBits(bitsConsumed, bits, table.log2Size); bitsConsumed += table.log2Size; loader = new BitInputStreamLoader(inputReader, input, currentAddress, bits, bitsConsumed); loader.Load(); bits = loader.GetBits(); bitsConsumed = loader.GetBitsConsumed(); currentAddress = loader.GetCurrentAddress(); byte[] symbols = table.symbol; byte[] numbersOfBits = table.numberOfBits; int[] newStates = table.newState; // decode 4 symbols per loop while (output <= outputLimit - 4) { int numberOfBits; outputWriter.BaseStream.Seek(output, SeekOrigin.Begin); outputWriter.Write(symbols[state1]); numberOfBits = numbersOfBits[state1]; state1 = (int)(newStates[state1] + BitInputStream.PeekBits(bitsConsumed, bits, numberOfBits)); bitsConsumed += numberOfBits; outputWriter.BaseStream.Seek(output + 1, SeekOrigin.Begin); outputWriter.Write(symbols[state2]); numberOfBits = numbersOfBits[state2]; state2 = (int)(newStates[state2] + BitInputStream.PeekBits(bitsConsumed, bits, numberOfBits)); bitsConsumed += numberOfBits; outputWriter.BaseStream.Seek(output + 2, SeekOrigin.Begin); outputWriter.Write(symbols[state1]); numberOfBits = numbersOfBits[state1]; state1 = (int)(newStates[state1] + BitInputStream.PeekBits(bitsConsumed, bits, numberOfBits)); bitsConsumed += numberOfBits; outputWriter.BaseStream.Seek(output + 3, SeekOrigin.Begin); outputWriter.Write(symbols[state2]); numberOfBits = numbersOfBits[state2]; state2 = (int)(newStates[state2] + BitInputStream.PeekBits(bitsConsumed, bits, numberOfBits)); bitsConsumed += numberOfBits; output += Constants.SIZE_OF_INT; loader = new BitInputStreamLoader(inputReader, input, currentAddress, bits, bitsConsumed); bool done = loader.Load(); bitsConsumed = loader.GetBitsConsumed(); bits = loader.GetBits(); currentAddress = loader.GetCurrentAddress(); if (done) { break; } } while (true) { Util.Verify(output <= outputLimit - 2, input, "Output buffer is too small"); outputWriter.BaseStream.Seek(output++, SeekOrigin.Begin); outputWriter.Write(symbols[state1]); int numberOfBits = numbersOfBits[state1]; state1 = (int)(newStates[state1] + BitInputStream.PeekBits(bitsConsumed, bits, numberOfBits)); bitsConsumed += numberOfBits; loader = new BitInputStreamLoader(inputReader, input, currentAddress, bits, bitsConsumed); loader.Load(); bitsConsumed = loader.GetBitsConsumed(); bits = loader.GetBits(); currentAddress = loader.GetCurrentAddress(); if (loader.IsOverflow()) { outputWriter.BaseStream.Seek(output++, SeekOrigin.Begin); outputWriter.Write(symbols[state2]); break; } Util.Verify(output <= outputLimit - 2, input, "Output buffer is too small"); outputWriter.BaseStream.Seek(output++, SeekOrigin.Begin); outputWriter.Write(symbols[state2]); int numberOfBits1 = numbersOfBits[state2]; state2 = (int)(newStates[state2] + BitInputStream.PeekBits(bitsConsumed, bits, numberOfBits1)); bitsConsumed += numberOfBits1; loader = new BitInputStreamLoader(inputReader, input, currentAddress, bits, bitsConsumed); loader.Load(); bitsConsumed = loader.GetBitsConsumed(); bits = loader.GetBits(); currentAddress = loader.GetCurrentAddress(); if (loader.IsOverflow()) { outputWriter.BaseStream.Seek(output++, SeekOrigin.Begin); outputWriter.Write(symbols[state1]); break; } } return((int)(output - outputAddress)); }