Beispiel #1
0
        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");
        }
Beispiel #2
0
        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);
        }
Beispiel #3
0
        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));
        }