1: //------------------------------------------------------------------------------
2: // Copyright (c) Microsoft Corporation. All rights reserved.
3: //------------------------------------------------------------------------------
4:
5: using System;
6: using System.Collections.Generic;
7:
8: namespace Microsoft.Protocols.TestTools.StackSdk.RemoteDesktop.Rdpegfx
9: {
10: /// <summary>
11: /// Simplified Run-Length (SRL) Decoder
12: /// </summary>
13: public class SRLDecoder
14: {
15: // Constants used within the RLGR1/RLGR3 algorithm
16: const int KPMAX = 80; // max value for kp or krp
17: const int LSGR = 3; // shift count to convert kp to k
18: const int UP_GR = 4; // increase in kp after a zero run in RL mode
19: const int DN_GR = 6; // decrease in kp after a nonzero symbol in RL mode
20: const int UQ_GR = 3; // increase in kp after nonzero symbol in GR mode
21: const int DQ_GR = 3; // decrease in kp after zero symbol in GR mode
22:
23: List<short> decodedList;
24: byte[] encodedBytes = null;
25: //BitArray bitsToDecode = null;
26: int dataOffset = 0;
27:
28: int k = 1;
29: int kp = 8; // k << LSGR;
30: int termsToDecode = RdpegfxTileUtils.ComponentElementCount;
31: bool zeroRLTerminated;
32:
33: /// <summary>
34: /// SRL decode the input data.
35: /// </summary>
36: /// <param name="encodedData">The input data to be decoded.</param>
37: public SRLDecoder(byte[] encodedData)
38: {
39: encodedBytes = encodedData;
40: //bitsToDecode = new BitArray(encodedData);
41: decodedList = new List<short>();
42: dataOffset = 0;
43: zeroRLTerminated = false;
44: }
45:
46: //
47: // Gets (returns) the next nBits from the bitstream
48: // The layout of N bits in the bitstream with regard to a byte array is:
49: // [0..N] -> [0..7](MSB..LSB),[8..15](MSB..LSB) ...,
50: // where (MSB..LSB) denotes a byte.
51: //
52: uint GetBits(uint nBits)
53: {
54: uint output = 0;
55: int outOffset = (int)nBits - 1;
56: while (outOffset >= 0)
57: {
58: int bitOffset = dataOffset & 7;
59: int byteOffset = dataOffset >> 3;
60: //uint outBit = (uint)(bitsToDecode.Get(bitOffset++) ? 1:0);
61: uint outBit = (uint)((encodedBytes[byteOffset] & (byte)(1 << (7 - bitOffset))) == 0 ? 0 : 1);
62: output |= (outBit << outOffset--);
63: dataOffset++;
64: }
65: return output;
66: }
67:
68: bool hasMoreBits(int bitCount)
69: {
70: int targetOffset = dataOffset + bitCount;
71:
72: int bitOffset = targetOffset & 7;
73: int byteOffset = targetOffset >> 3;
74: if (byteOffset < encodedBytes.Length) return true;
75: return false;
76: }
77:
78: //
79: // From current output pointer, write "value", check and update *termsToDecode
80: //
81: void WriteValue(
82: int value,
83: ref int termsToDecode
84: )
85: {
86: if (termsToDecode > 0)
87: {
88: this.decodedList.Add((short)value);
89: termsToDecode--;
90: }
91: }
92:
93:
94: //
95: // From current output pointer, write next nZeroes terms with value 0;
96: // check and update *termsToDecode
97: //
98: void WriteZeroes(
99: uint nZeroes,
100: ref int termsToDecode
101: )
102: {
103: for (int i = 0; i < nZeroes && termsToDecode > 0; i++)
104: {
105: WriteValue(0, ref termsToDecode);
106: }
107: }
108:
109:
110: //
111: // Update the passed parameter and clamp it to the range [0,KPMAX]
112: // Return the value of parameter right-shifted by LSGR
113: //
114: int UpdateParam(
115: ref int param, // parameter to update
116: int deltaP // update delta
117: )
118: {
119: param += deltaP;// adjust parameter
120: if (param > KPMAX) param = KPMAX;// max clamp
121: if (param < 0) param = 0;// min clamp
122: return (param >> LSGR);
123: }
124:
125:
126: /// <summary>
127: /// Decode one element from the given data
128: /// </summary>
129: /// <param name="bitCount">The count of bits to be decoded.</param>
130: /// <returns>The decoded element.</returns>
131: public short? DecodeOne(int bitCount)
132: {
133: short? decodedValue = null;
134: if (this.decodedList.Count > 0)
135: {
136: decodedValue = this.decodedList[0];
137: this.decodedList.RemoveAt(0);
138: return decodedValue;
139: }
140:
141: if (hasMoreBits(1))
142: {
143: if (!zeroRLTerminated)
144: {
145: int run;
146: // RL MODE
147: while (hasMoreBits(1) && GetBits(1) == 0)
148: {
149: // we have an RL escape "0", which translates to a run (1<<k) of zeros
150: WriteZeroes((uint)(1 << k), ref termsToDecode);
151: k = UpdateParam(ref kp, UP_GR); // raise k and kp up because of zero run
152: }
153:
154: if (hasMoreBits(k))
155: {
156: // next k bits will contain remaining run of zeros
157: run = (int)GetBits((uint)k);
158: WriteZeroes((uint)run, ref termsToDecode);
159: k = UpdateParam(ref kp, -DN_GR);
160: }
161:
162: zeroRLTerminated = true;
163: }
164: else
165: {
166: // get nonzero value, starting with sign bit and
167: // then Unary Code for magnitude - 1
168: uint sign = GetBits(1);
169:
170: int mag = 0;
171: int maxReadBits = (1 << bitCount) - 2;
172:
173: while (hasMoreBits(1) && maxReadBits > 0 && GetBits(1) == 0)
174: {
175: maxReadBits--;
176: mag++;
177: }
178:
179: mag += 1;
180: WriteValue(sign != 0 ? -mag : mag, ref termsToDecode);
181:
182: zeroRLTerminated = false;
183: }
184:
185: }
186:
187: if (this.decodedList.Count > 0)
188: {
189: decodedValue = this.decodedList[0];
190: this.decodedList.RemoveAt(0);
191: }
192: else if (hasMoreBits(1))
193: {
194: decodedValue = DecodeOne(bitCount);
195: }
196:
197: return decodedValue;
198: }
199: }
200: }