public void DecodeSingleStream(BinaryReader inputReader, long inputAddress, long inputLimit, BinaryWriter outputWriter, long outputAddress, long outputLimit) { BitInputStreamInitializer initializer = new BitInputStreamInitializer(inputReader, inputAddress, inputLimit); initializer.Initialize(); long bits = initializer.GetBits(); int bitsConsumed = initializer.GetBitsConsumed(); long currentAddress = initializer.GetCurrentAddress(); int tableLog = this.tableLog; byte[] numbersOfBits = this.numbersOfBits; byte[] symbols = this.symbols; // 4 symbols at a time long output = outputAddress; long fastOutputLimit = outputLimit - 4; while (output < fastOutputLimit) { BitInputStreamLoader loader = new BitInputStreamLoader(inputReader, inputAddress, currentAddress, bits, bitsConsumed); bool done = loader.Load(); bits = loader.GetBits(); bitsConsumed = loader.GetBitsConsumed(); currentAddress = loader.GetCurrentAddress(); if (done) { break; } bitsConsumed = DecodeSymbol(outputWriter, output, bits, bitsConsumed, tableLog, numbersOfBits, symbols); bitsConsumed = DecodeSymbol(outputWriter, output + 1, bits, bitsConsumed, tableLog, numbersOfBits, symbols); bitsConsumed = DecodeSymbol(outputWriter, output + 2, bits, bitsConsumed, tableLog, numbersOfBits, symbols); bitsConsumed = DecodeSymbol(outputWriter, output + 3, bits, bitsConsumed, tableLog, numbersOfBits, symbols); output += Constants.SIZE_OF_INT; } DecodeTail(inputReader, inputAddress, currentAddress, bitsConsumed, bits, outputWriter, output, outputLimit); }
public void Decode4Streams(BinaryReader inputReader, long inputAddress, long inputLimit, BinaryWriter outputWriter, long outputAddress, long outputLimit) { Util.Verify(inputLimit - inputAddress >= 10, inputAddress, "Input is corrupted"); // jump table + 1 byte per stream long start1 = inputAddress + 3 * Constants.SIZE_OF_SHORT; // for the shorts we read below inputReader.BaseStream.Seek(inputAddress, SeekOrigin.Begin); long start2 = start1 + (inputReader.ReadInt16() & 0xFFFF); inputReader.BaseStream.Seek(inputAddress + 2, SeekOrigin.Begin); long start3 = start2 + (inputReader.ReadInt16() & 0xFFFF); inputReader.BaseStream.Seek(inputAddress + 4, SeekOrigin.Begin); long start4 = start3 + (inputReader.ReadInt16() & 0xFFFF); BitInputStreamInitializer initializer = new BitInputStreamInitializer(inputReader, start1, start2); initializer.Initialize(); int stream1bitsConsumed = initializer.GetBitsConsumed(); long stream1currentAddress = initializer.GetCurrentAddress(); long stream1bits = initializer.GetBits(); initializer = new BitInputStreamInitializer(inputReader, start2, start3); initializer.Initialize(); int stream2bitsConsumed = initializer.GetBitsConsumed(); long stream2currentAddress = initializer.GetCurrentAddress(); long stream2bits = initializer.GetBits(); initializer = new BitInputStreamInitializer(inputReader, start3, start4); initializer.Initialize(); int stream3bitsConsumed = initializer.GetBitsConsumed(); long stream3currentAddress = initializer.GetCurrentAddress(); long stream3bits = initializer.GetBits(); initializer = new BitInputStreamInitializer(inputReader, start4, inputLimit); initializer.Initialize(); int stream4bitsConsumed = initializer.GetBitsConsumed(); long stream4currentAddress = initializer.GetCurrentAddress(); long stream4bits = initializer.GetBits(); int segmentSize = (int)((outputLimit - outputAddress + 3) / 4); long outputStart2 = outputAddress + segmentSize; long outputStart3 = outputStart2 + segmentSize; long outputStart4 = outputStart3 + segmentSize; long output1 = outputAddress; long output2 = outputStart2; long output3 = outputStart3; long output4 = outputStart4; long fastOutputLimit = outputLimit - 7; int tableLog = this.tableLog; byte[] numbersOfBits = this.numbersOfBits; byte[] symbols = this.symbols; while (output4 < fastOutputLimit) { stream1bitsConsumed = DecodeSymbol(outputWriter, output1, stream1bits, stream1bitsConsumed, tableLog, numbersOfBits, symbols); stream2bitsConsumed = DecodeSymbol(outputWriter, output2, stream2bits, stream2bitsConsumed, tableLog, numbersOfBits, symbols); stream3bitsConsumed = DecodeSymbol(outputWriter, output3, stream3bits, stream3bitsConsumed, tableLog, numbersOfBits, symbols); stream4bitsConsumed = DecodeSymbol(outputWriter, output4, stream4bits, stream4bitsConsumed, tableLog, numbersOfBits, symbols); stream1bitsConsumed = DecodeSymbol(outputWriter, output1 + 1, stream1bits, stream1bitsConsumed, tableLog, numbersOfBits, symbols); stream2bitsConsumed = DecodeSymbol(outputWriter, output2 + 1, stream2bits, stream2bitsConsumed, tableLog, numbersOfBits, symbols); stream3bitsConsumed = DecodeSymbol(outputWriter, output3 + 1, stream3bits, stream3bitsConsumed, tableLog, numbersOfBits, symbols); stream4bitsConsumed = DecodeSymbol(outputWriter, output4 + 1, stream4bits, stream4bitsConsumed, tableLog, numbersOfBits, symbols); stream1bitsConsumed = DecodeSymbol(outputWriter, output1 + 2, stream1bits, stream1bitsConsumed, tableLog, numbersOfBits, symbols); stream2bitsConsumed = DecodeSymbol(outputWriter, output2 + 2, stream2bits, stream2bitsConsumed, tableLog, numbersOfBits, symbols); stream3bitsConsumed = DecodeSymbol(outputWriter, output3 + 2, stream3bits, stream3bitsConsumed, tableLog, numbersOfBits, symbols); stream4bitsConsumed = DecodeSymbol(outputWriter, output4 + 2, stream4bits, stream4bitsConsumed, tableLog, numbersOfBits, symbols); stream1bitsConsumed = DecodeSymbol(outputWriter, output1 + 3, stream1bits, stream1bitsConsumed, tableLog, numbersOfBits, symbols); stream2bitsConsumed = DecodeSymbol(outputWriter, output2 + 3, stream2bits, stream2bitsConsumed, tableLog, numbersOfBits, symbols); stream3bitsConsumed = DecodeSymbol(outputWriter, output3 + 3, stream3bits, stream3bitsConsumed, tableLog, numbersOfBits, symbols); stream4bitsConsumed = DecodeSymbol(outputWriter, output4 + 3, stream4bits, stream4bitsConsumed, tableLog, numbersOfBits, symbols); output1 += Constants.SIZE_OF_INT; output2 += Constants.SIZE_OF_INT; output3 += Constants.SIZE_OF_INT; output4 += Constants.SIZE_OF_INT; BitInputStreamLoader loader = new BitInputStreamLoader(inputReader, start1, stream1currentAddress, stream1bits, stream1bitsConsumed); bool done = loader.Load(); stream1bitsConsumed = loader.GetBitsConsumed(); stream1bits = loader.GetBits(); stream1currentAddress = loader.GetCurrentAddress(); if (done) { break; } loader = new BitInputStreamLoader(inputReader, start2, stream2currentAddress, stream2bits, stream2bitsConsumed); done = loader.Load(); stream2bitsConsumed = loader.GetBitsConsumed(); stream2bits = loader.GetBits(); stream2currentAddress = loader.GetCurrentAddress(); if (done) { break; } loader = new BitInputStreamLoader(inputReader, start3, stream3currentAddress, stream3bits, stream3bitsConsumed); done = loader.Load(); stream3bitsConsumed = loader.GetBitsConsumed(); stream3bits = loader.GetBits(); stream3currentAddress = loader.GetCurrentAddress(); if (done) { break; } loader = new BitInputStreamLoader(inputReader, start4, stream4currentAddress, stream4bits, stream4bitsConsumed); done = loader.Load(); stream4bitsConsumed = loader.GetBitsConsumed(); stream4bits = loader.GetBits(); stream4currentAddress = loader.GetCurrentAddress(); if (done) { break; } } Util.Verify(output1 <= outputStart2 && output2 <= outputStart3 && output3 <= outputStart4, inputAddress, "Input is corrupted"); /// finish streams one by one DecodeTail(inputReader, start1, stream1currentAddress, stream1bitsConsumed, stream1bits, outputWriter, output1, outputStart2); DecodeTail(inputReader, start2, stream2currentAddress, stream2bitsConsumed, stream2bits, outputWriter, output2, outputStart3); DecodeTail(inputReader, start3, stream3currentAddress, stream3bitsConsumed, stream3bits, outputWriter, output3, outputStart4); DecodeTail(inputReader, start4, stream4currentAddress, stream4bitsConsumed, stream4bits, outputWriter, output4, outputLimit); }
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)); }