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) Eecoder 
  12:      /// </summary>
  13:      public class SRLEncoder
  14:      {
  15:          // Constants used within the RLGR1/RLGR3 algorithm
  16:   
  17:          const int KPMAX = 80;  // max value for kp or krp
  18:          const int LSGR = 3;  // shift count to convert kp to k
  19:          const int UP_GR = 4;  // increase in kp after a zero run in RL mode
  20:          const int DN_GR = 6;  // decrease in kp after a nonzero symbol in RL mode
  21:          const int UQ_GR = 3;   // increase in kp after nonzero symbol in GR mode
  22:          const int DQ_GR = 3;   // decrease in kp after zero symbol in GR mode
  23:   
  24:          short[] inputData;
  25:          int[] InputDataBitLen;
  26:          int nextInputIdx;
  27:          int bufferOffset = 0;
  28:          byte[] pBuffer;
  29:   
  30:          /// <summary>
  31:          /// Do ALGR encode to the input data.
  32:          /// </summary>
  33:          /// <param name="inputArr">Input data to be encoded.</param>
  34:          /// <param name="mode">The ALGR mode, can be RLGR1 or RLGR3.</param>
  35:          /// <returns>The encoded data.</returns>
  36:          public byte[] Encode(short[] inputArr, int[] bitLenArr)
  37:          {
  38:              inputData = inputArr;
  39:              InputDataBitLen = bitLenArr;
  40:              nextInputIdx = 0;
  41:              bufferOffset = 0; //offset&0xFFFFFFF8 = byte offset, offset&0x7 = bit offset
  42:              pBuffer = new byte[inputArr.Length];
  43:              //bitStrm = new BitStream();
  44:   
  45:              SRL_Encode();
  46:   
  47:   
  48:              int numbytes = bufferOffset >> 3;
  49:              int bitOffset = bufferOffset & 7;
  50:              if (bitOffset != 0) numbytes++;
  51:   
  52:              byte[] encodedBytes = new byte[numbytes];
  53:              Array.Copy(pBuffer, encodedBytes, encodedBytes.Length);
  54:              return encodedBytes;
  55:   
  56:              //return bitStrm.ToBytes();
  57:          }
  58:   
  59:          //
  60:          // Returns the next coefficient (a signed int) to encode, from the input stream
  61:          //
  62:          int GetNextInput(out int bitLen)
  63:          {
  64:              bitLen = InputDataBitLen[nextInputIdx];
  65:              return (int)inputData[nextInputIdx++];
  66:          }
  67:   
  68:          bool hasMoreData()
  69:          {
  70:              return (nextInputIdx <= inputData.Length - 1);
  71:          }
  72:   
  73:          //
  74:          // Emit bitPattern to the output bitstream.
  75:          // The bitPattern value represents a bit sequence that is generated by shifting 
  76:          // new bits in from the right. If we take the binary representation of bitPattern, 
  77:          // with N(numBits-1) being the leftmost bit position and 0 being the rightmost bit position, 
  78:          // the mapping of bitPattern to the output bytes is as follows:
  79:          //
  80:          //     bitPattern[N..0] -> byte[MSB..LSB] .. byte[MSB..LSB]
  81:          //
  82:          public void OutputBits(
  83:              int numBits,      // number of bits in bitPattern
  84:              int bitPattern   // bit pattern
  85:              )
  86:          {
  87:              int patternOffset = numBits - 1;
  88:   
  89:              while (patternOffset >= 0)
  90:              {
  91:                  int bit = ((bitPattern & (1 << patternOffset)) != 0) ? 1 : 0;
  92:                  OutputBit(1, bit);
  93:                  patternOffset--;
  94:              }
  95:   
  96:          }
  97:   
  98:          //
  99:          // Emit a bit (0 or 1), count number of times, to the output bitstream
 100:          //
 101:          void OutputBit(
 102:              int count,     // number of times to emit the bit
 103:              int bit        // 0 or 1
 104:              )
 105:          {
 106:              if (count == 0) return;
 107:   
 108:              //bitStrm.WriteBits(count, bit == 1 ? true : false);
 109:   
 110:   
 111:              for (int i = 0; i < count; i++)
 112:              {
 113:                  int bitOffset = bufferOffset & 7;
 114:                  int bufferBoundary = bufferOffset >> 3;
 115:                  if (bit != 0) // bit 1
 116:                  {
 117:                      pBuffer[bufferBoundary] |= (byte)(1 << (7 - bitOffset));
 118:                  }
 119:                  else
 120:                  {
 121:                      pBuffer[bufferBoundary] &= (byte)(0xFF - ((byte)(1 << (7 - bitOffset))));
 122:                  }
 123:                  bufferOffset++;
 124:              }
 125:   
 126:          }
 127:   
 128:          //
 129:          // Update the passed parameter and clamp it to the range [0,KPMAX]
 130:          // Return the value of parameter right-shifted by LSGR
 131:          //
 132:          int UpdateParam(
 133:              ref int param,    // parameter to update
 134:              int deltaP    // update delta
 135:              )
 136:          {
 137:              param += deltaP;
 138:              if (param > KPMAX) param = KPMAX;
 139:              if (param < 0) param = 0;
 140:              return (param >> LSGR);
 141:          }
 142:   
 143:          //
 144:          // Routine that outputs a stream of RLGR1/RLGR3-encoded bits
 145:          //
 146:          void SRL_Encode(  
 147:              )
 148:          {
 149:              // initialize the parameters
 150:              int k = 1;
 151:              int kp = 1 << LSGR;
 152:              //int kr = 1;
 153:              //int krp = 1 << LSGR;
 154:   
 155:              // process all the input coefficients
 156:              while (hasMoreData())
 157:              {
 158:                  int input;
 159:                  int bitLen;
 160:   
 161:                  //if (k != 0)
 162:                  {
 163:                      // RUN-LENGTH MODE
 164:   
 165:                      // collect the run of zeros in the input stream
 166:                      int numZeros = 0;
 167:                      while ((input = GetNextInput(out bitLen)) == 0)
 168:                      {
 169:                          ++numZeros;
 170:                          if (!hasMoreData()) break;
 171:                      }
 172:   
 173:                      // emit output zebros
 174:                      int runmax = 1 << k;
 175:                      while (numZeros >= runmax)
 176:                      {
 177:                          OutputBit(1, 0);             // output a zero bit
 178:                          numZeros -= runmax;
 179:                          k = UpdateParam(ref kp, UP_GR);  // update kp, k 
 180:                          runmax = 1 << k;
 181:                      }
 182:   
 183:                      // output a 1 to terminate runs
 184:                      OutputBit(1, 1);
 185:   
 186:                      // output the remaining run length using k bits
 187:                      OutputBits(k, numZeros);
 188:   
 189:                      k = UpdateParam(ref kp, -DN_GR);
 190:   
 191:                      if (input != 0)
 192:                      {
 193:                          // encode the nonzero value using Unary Encoding
 194:   
 195:                          int mag = Math.Abs(input);            // absolute value of input coefficient
 196:                          int sign = (input < 0 ? 1 : 0);  // sign of input coefficient
 197:                          int maxM = (1 << bitLen) - 1;
 198:   
 199:                          OutputBit(1, sign);      // output the sign bit
 200:   
 201:                          //a sequence of "magnitude - 1" zeros is written.
 202:                          OutputBit(mag - 1, 0);
 203:   
 204:                          if (mag < maxM)
 205:                          {
 206:                              OutputBit(1, 1);
 207:                          }
 208:                      }
 209:                  }
 210:              }
 211:          }
 212:   
 213:      }
 214:  }