1:  //------------------------------------------------------------------------------
   2:  // Copyright (c) Microsoft Corporation. All rights reserved.
   3:  //------------------------------------------------------------------------------
   4:   
   5:  using System;
   6:  using System.Collections.Generic;
   7:  using Microsoft.Protocols.TestTools.StackSdk.RemoteDesktop.Rdprfx;
   8:  using System.Drawing;
   9:  using System.Collections;
  10:   
  11:  namespace Microsoft.Protocols.TestTools.StackSdk.RemoteDesktop.Rdpegfx
  12:  {
  13:      /// <summary>
  14:      /// The RemoteFX Progressive encoder
  15:      /// </summary>
  16:      public class RfxProgressiveEncoder
  17:      {
  18:          const int TileSize = 64;
  19:   
  20:          /// <summary>
  21:          /// Encode a Tile
  22:          /// </summary>
  23:          /// <param name="encodingContext">The tile encoding context</param>
  24:          /// <param name="enTileInfo">The tile to be encoded</param>
  25:          /// <returns>A array of CompressedTile which contains the encoded tiles</returns>
  26:          public static EncodedTile[] EncodeTile(RfxProgressiveCodecContext encodingContext, TileState enTileInfo)
  27:          {
  28:              EncodedTileType targetType = encodingContext.UseProgressive ? EncodedTileType.FirstPass : EncodedTileType.Simple;
  29:   
  30:              //File RGB
  31:              FillRgbData(encodingContext, enTileInfo.GetRgb());
  32:   
  33:              //Do color conversion
  34:              RemoteFXEncoder.RGBToYCbCr(encodingContext);
  35:   
  36:              //Do DWT
  37:              if (encodingContext.UseReduceExtrapolate)
  38:              {
  39:                  //Do DWT using UseReduce Extrapolate method
  40:                  DWT(encodingContext);
  41:              }
  42:              else
  43:              {
  44:                  RemoteFXEncoder.DWT(encodingContext);
  45:              }
  46:   
  47:              //Do quantiztion
  48:              Quantization(encodingContext);
  49:   
  50:              //Do linearization (LL3 delta not computed)
  51:              Linearization_NoLL3Delta(encodingContext);
  52:   
  53:              //Update new DWT to tile
  54:              DwtTile dwt = new DwtTile(
  55:                  (short[])encodingContext.YComponent.Clone(),
  56:                  (short[])encodingContext.CbComponent.Clone(),
  57:                  (short[])encodingContext.CrComponent.Clone(),
  58:                  encodingContext.CodecQuantVals,
  59:                  encodingContext.QuantIdxY,
  60:                  encodingContext.QuantIdxCb,
  61:                  encodingContext.QuantIdxCr,
  62:                  encodingContext.UseReduceExtrapolate
  63:                  );
  64:              enTileInfo.UpdateDwt(dwt);
  65:              
  66:   
  67:              //Sub-Band Diffing
  68:              if (encodingContext.UseDifferenceTile)
  69:              {
  70:                  SubBandDiffing_DT(encodingContext, enTileInfo);
  71:              }
  72:   
  73:              if (targetType == EncodedTileType.Simple)
  74:              {
  75:                  ComputeLL3Deltas(encodingContext);
  76:   
  77:                  RemoteFXEncoder.RLGREncode(encodingContext);
  78:                  EncodedTile cpTile = new EncodedTile();
  79:                  cpTile.YEncodedData = (byte[])encodingContext.YData.Clone();
  80:                  cpTile.CbEncodedData = (byte[])encodingContext.CbData.Clone();
  81:                  cpTile.CrEncodedData = (byte[])encodingContext.CrData.Clone();
  82:                  cpTile.DataType = EncodedTileType.Simple;
  83:                  cpTile.IsDifferenceTile = encodingContext.UseDifferenceTile;
  84:                  cpTile.UseReduceExtrapolate = encodingContext.UseReduceExtrapolate;
  85:                  cpTile.CodecQuantVals = encodingContext.CodecQuantVals;
  86:                  cpTile.QuantIdxY = encodingContext.QuantIdxY;
  87:                  cpTile.QuantIdxCb = encodingContext.QuantIdxCb;
  88:                  cpTile.QuantIdxCr = encodingContext.QuantIdxCr;
  89:                  cpTile.ProgCodecQuant = null;
  90:                  return new EncodedTile[] { cpTile };
  91:              }
  92:              else
  93:              {
  94:                  List<EncodedTile> progCTileList = new List<EncodedTile>();
  95:                  //Init DRS, DAS
  96:                  encodingContext.DRS = new DwtTile(encodingContext.YComponent, encodingContext.CbComponent, encodingContext.CrComponent);
  97:                  encodingContext.DAS = new DwtTile(new short[RdpegfxTileUtils.ComponentElementCount], new short[RdpegfxTileUtils.ComponentElementCount], new short[RdpegfxTileUtils.ComponentElementCount]);
  98:   
  99:                  #region Chunk 25, first pass
 100:   
 101:                  ProgressiveQuantization(encodingContext, ProgressiveChunk_Values.kChunk_25);
 102:   
 103:                  //Compute ProgQ LL3 deltas
 104:                  encodingContext.YComponent = encodingContext.ProgQ.Y_DwtQ;
 105:                  encodingContext.CbComponent = encodingContext.ProgQ.Cb_DwtQ;
 106:                  encodingContext.CrComponent = encodingContext.ProgQ.Cr_DwtQ;          
 107:   
 108:                  ComputeLL3Deltas(encodingContext);
 109:   
 110:                  RemoteFXEncoder.RLGREncode(encodingContext);
 111:                  EncodedTile firstPassTile = new EncodedTile();
 112:                  firstPassTile.YEncodedData = (byte[])encodingContext.YData.Clone();
 113:                  firstPassTile.CbEncodedData = (byte[])encodingContext.CbData.Clone();
 114:                  firstPassTile.CrEncodedData = (byte[])encodingContext.CrData.Clone();
 115:                  firstPassTile.DataType = EncodedTileType.FirstPass;
 116:                  firstPassTile.IsDifferenceTile = encodingContext.UseDifferenceTile;
 117:                  firstPassTile.UseReduceExtrapolate = encodingContext.UseReduceExtrapolate;
 118:                  firstPassTile.CodecQuantVals = encodingContext.CodecQuantVals;
 119:                  firstPassTile.QuantIdxY = encodingContext.QuantIdxY;
 120:                  firstPassTile.QuantIdxCb = encodingContext.QuantIdxCb;
 121:                  firstPassTile.QuantIdxCr = encodingContext.QuantIdxCr;
 122:                  firstPassTile.ProgCodecQuant = RdpegfxTileUtils.GetProgCodecQuant(ProgressiveChunk_Values.kChunk_25);
 123:                  progCTileList.Add(firstPassTile);
 124:                  encodingContext.prevProgQuant = RdpegfxTileUtils.GetProgCodecQuant(ProgressiveChunk_Values.kChunk_25);
 125:   
 126:                  //Update DRS
 127:                  encodingContext.DRS.Sub(encodingContext.DTS);
 128:                  //Update DAS
 129:                  encodingContext.DAS.Add(encodingContext.DTS);
 130:                  #endregion
 131:   
 132:                  #region Chunk 50,75,100, upgrade pass
 133:                  ProgressiveChunk_Values[] upgradeChunks = { ProgressiveChunk_Values.kChunk_50, ProgressiveChunk_Values.kChunk_75, ProgressiveChunk_Values.kChunk_100 };
 134:   
 135:                  foreach (ProgressiveChunk_Values tChunk in upgradeChunks)
 136:                  {
 137:                      ProgressiveQuantization(encodingContext, tChunk);
 138:   
 139:                      RFX_PROGRESSIVE_CODEC_QUANT progquant = RdpegfxTileUtils.GetProgCodecQuant(tChunk);
 140:   
 141:                      progCTileList.Add(SRLEncode(encodingContext, progquant));
 142:   
 143:                      //Update DRS
 144:                      encodingContext.DRS.Sub(encodingContext.DTS);
 145:                      //Update DAS
 146:                      encodingContext.DAS.Add(encodingContext.DTS);
 147:   
 148:                      encodingContext.prevProgQuant = progquant;
 149:                  }
 150:   
 151:                  return progCTileList.ToArray();
 152:   
 153:                  #endregion
 154:   
 155:              }
 156:          }
 157:   
 158:          #region File RGB Data
 159:   
 160:          static void FillRgbData(RfxProgressiveCodecContext encodingContext, RgbTile rgbTile)
 161:          {
 162:              encodingContext.RSet = rgbTile.RSet;
 163:              encodingContext.GSet = rgbTile.GSet;
 164:              encodingContext.BSet = rgbTile.BSet;
 165:          }
 166:   
 167:          #endregion
 168:   
 169:          #region DWT
 170:   
 171:          //DWT
 172:          internal static void DWT(RfxProgressiveCodecContext encodingContext)
 173:          {
 174:              DWT_Component(encodingContext.YSet);
 175:              DWT_Component(encodingContext.CbSet);
 176:              DWT_Component(encodingContext.CrSet);
 177:          }
 178:   
 179:          private static short DWT_H(short[] dataArr, int n)
 180:          {
 181:              //n < dataArr.length/2
 182:              short x2n, x2n1, x2n2;
 183:              int maxIdx = dataArr.Length - 1;
 184:              if (n == -1)
 185:              {
 186:                  x2n = dataArr[2];
 187:                  x2n1 = dataArr[1];
 188:                  x2n2 = dataArr[0];
 189:              }
 190:              else
 191:              {
 192:                  x2n = dataArr[2 * n];
 193:   
 194:                  if (2 * n + 1 > maxIdx)
 195:                  {
 196:                      x2n1 = dataArr[2 * maxIdx - (2 * n + 1)];
 197:                  }
 198:                  else
 199:                  {
 200:                      x2n1 = dataArr[2 * n + 1];
 201:                  }
 202:   
 203:                  if (2 * n + 2 >= maxIdx)
 204:                  {
 205:                      x2n2 = dataArr[2 * maxIdx - (2 * n + 2)];
 206:                  }
 207:                  else
 208:                  {
 209:                      x2n2 = dataArr[2 * n + 2];
 210:                  }
 211:              }
 212:   
 213:              //short result = (short)((x2n1 - (x2n + x2n2 + 0.0f) / 2) / 2);
 214:              short result = (short)((x2n1 - (((x2n + x2n2) >> 1))) >> 1);
 215:              return result;
 216:          }
 217:   
 218:          private static short DWT_L(short[] dataArr, int n)
 219:          {
 220:              //short result = (short)(dataArr[2 * n] + (DWT_H(dataArr, n - 1) + DWT_H(dataArr, n)) / 2);
 221:              short result = (short)(dataArr[2 * n] + ((DWT_H(dataArr, n - 1) + DWT_H(dataArr, n)) >> 1));
 222:              return result;
 223:          }
 224:   
 225:          public static void DWT(short[] dataArr)
 226:          {
 227:              int N = dataArr.Length / 2;
 228:              int hLen, lLen;
 229:              short[] data2Dwt;
 230:              lLen = dataArr.Length / 2 + 1;
 231:              hLen = dataArr.Length - lLen;
 232:   
 233:              short[] hResult = new short[hLen];
 234:              short[] lResult = new short[lLen];
 235:   
 236:              if (dataArr.Length == TileSize)
 237:              {
 238:                  //First pass
 239:                  data2Dwt = new short[TileSize + 1];
 240:                  Array.Copy(dataArr, data2Dwt, TileSize);
 241:                  data2Dwt[TileSize] = (short)(2 * data2Dwt[TileSize - 1] - data2Dwt[TileSize - 2]);
 242:              }
 243:              else
 244:              {
 245:                  //Second and Third pass
 246:                  data2Dwt = dataArr;
 247:              }
 248:   
 249:              for (int i = 0; i < hLen; i++)
 250:              {
 251:                  hResult[i] = DWT_H(data2Dwt, i);
 252:              }
 253:   
 254:              for (int i = 0; i < lLen; i++)
 255:              {
 256:                  lResult[i] = DWT_L(data2Dwt, i);
 257:              }
 258:   
 259:              for (int i = 0; i < lLen; i++)
 260:              {
 261:                  dataArr[i] = lResult[i];
 262:              }
 263:   
 264:              for (int i = 0; i < hLen; i++)
 265:              {
 266:                  dataArr[lLen + i] = hResult[i];
 267:              }
 268:          }
 269:   
 270:          private static void DWT_Pass(short[,] data2D, int pass)
 271:          {
 272:              //level > 0
 273:              //data2D.Length % (1<<(level - 1)) == 0
 274:              //int inScopelen = TileSize >> (level - 1);
 275:              int inScopelen;
 276:              switch (pass)
 277:              {
 278:                  case 1:
 279:                      {
 280:                          // First pass
 281:                          inScopelen = 64;
 282:                          break;
 283:                      }
 284:                  case 2:
 285:                      {
 286:                          // Second pass
 287:                          inScopelen = 33;
 288:                          break;
 289:                      }
 290:                  case 3:
 291:                      {
 292:                          // Third pass
 293:                          inScopelen = 17;
 294:                          break;
 295:                      }
 296:                  default:
 297:                      {
 298:                          throw new InvalidOperationException("DWT_2D: the parameter level should only be 1, 2, or 3.");
 299:                      }
 300:              }
 301:   
 302:              //Vertical DWT
 303:              for (int x = 0; x < inScopelen; x++)
 304:              {
 305:                  short[] col;
 306:                  RemoteFXEncoder.getColFrom2DArr<short>(data2D, out col, x, inScopelen);
 307:                  DWT(col);
 308:                  for (int y = 0; y < inScopelen; y++)
 309:                  {
 310:                      data2D[x, y] = col[y];
 311:                  }
 312:              }
 313:              //Horizontal DWT
 314:              for (int y = 0; y < inScopelen; y++)
 315:              {
 316:                  short[] row;
 317:                  RemoteFXEncoder.getRowFrom2DArr<short>(data2D, out row, y, inScopelen);
 318:                  DWT(row);
 319:                  for (int x = 0; x < inScopelen; x++)
 320:                  {
 321:                      data2D[x, y] = row[x];
 322:                  }
 323:              }
 324:          }
 325:   
 326:          protected static void DWT_Component(short[,] component)
 327:          {
 328:              DWT_Pass(component, 1);
 329:              DWT_Pass(component, 2);
 330:              DWT_Pass(component, 3);
 331:          }
 332:   
 333:          #endregion
 334:   
 335:          #region Quantization
 336:   
 337:          public static void Quantization(RfxProgressiveCodecContext encodingContext)
 338:          {
 339:              doQuantization_Component(encodingContext.YSet, encodingContext.CodecQuantVals[encodingContext.QuantIdxY], encodingContext.UseReduceExtrapolate);
 340:              doQuantization_Component(encodingContext.CbSet, encodingContext.CodecQuantVals[encodingContext.QuantIdxCb], encodingContext.UseReduceExtrapolate);
 341:              doQuantization_Component(encodingContext.CrSet, encodingContext.CodecQuantVals[encodingContext.QuantIdxCr], encodingContext.UseReduceExtrapolate);
 342:          }
 343:   
 344:          protected static void doQuantization_Component(short[,] component, TS_RFX_CODEC_QUANT tsRfxCodecQuant, bool useReduceExtrapolate)
 345:          {
 346:              // Quantization factor: HL1, LH1, HH1, HL2, LH2, HH2, HL3, LH3, HH3, LL3            
 347:              Hashtable scaleValueTable = new Hashtable();
 348:              int HL1_Factor = tsRfxCodecQuant.HL1_HH1 & 0x0f;
 349:              int LH1_Factor = (tsRfxCodecQuant.HH2_LH1 & 0xf0) >> 4;
 350:              int HH1_Factor = (tsRfxCodecQuant.HL1_HH1 & 0xf0) >> 4;
 351:              int HL2_Factor = (tsRfxCodecQuant.LH2_HL2 & 0xf0) >> 4;
 352:              int LH2_Factor = tsRfxCodecQuant.LH2_HL2 & 0x0f;
 353:              int HH2_Factor = tsRfxCodecQuant.HH2_LH1 & 0x0f;
 354:              int HL3_Factor = tsRfxCodecQuant.HL3_HH3 & 0x0f;
 355:              int LH3_Factor = (tsRfxCodecQuant.LL3_LH3 & 0xf0) >> 4;
 356:              int HH3_Factor = (tsRfxCodecQuant.HL3_HH3 & 0xf0) >> 4;
 357:              int LL3_Factor = tsRfxCodecQuant.LL3_LH3 & 0x0f;
 358:   
 359:              BandType_Values[] bandArr = new BandType_Values[] { BandType_Values.HL1, BandType_Values.LH1, BandType_Values.HH1, BandType_Values.HL2, BandType_Values.LH2, BandType_Values.HH2, BandType_Values.HL3, BandType_Values.LH3, BandType_Values.HH3, BandType_Values.LL3 };
 360:              int[] bandFactor = new int[] { HL1_Factor, LH1_Factor, HH1_Factor, HL2_Factor, LH2_Factor, HH2_Factor, HL3_Factor, LH3_Factor, HH3_Factor, LL3_Factor };
 361:   
 362:              for (int i = 0; i < bandArr.Length; i++)
 363:              {
 364:                  BandRect br = RdpegfxTileUtils.GetBandRect(bandArr[i], useReduceExtrapolate);
 365:                  doQuantization_Subband(component, br.left, br.top, br.right, br.bottom, bandFactor[i]);
 366:              }
 367:          }
 368:   
 369:          private static void doQuantization_Subband(short[,] input, int left, int top, int right, int bottom, int factor)
 370:          {
 371:              for (int x = left; x <= right; x++)
 372:              {
 373:                  for (int y = top; y <= bottom; y++)
 374:                  {
 375:                      input[x, y] = quant(input[x, y], factor);
 376:                  }
 377:              }
 378:          }
 379:   
 380:          private static short quant(short input, int factor)
 381:          {
 382:              short output;
 383:              output = (short)(Math.Abs(input) >> (factor - 6));
 384:              if (input < 0) output *= -1;
 385:              return output;
 386:          }
 387:          #endregion
 388:   
 389:          #region Linearization
 390:   
 391:          public static void Linearization_NoLL3Delta(RfxProgressiveCodecContext encodingContext)
 392:          {
 393:               linearization_Compontent(encodingContext.YSet, encodingContext.UseReduceExtrapolate, out encodingContext.YComponent);
 394:               linearization_Compontent(encodingContext.CbSet, encodingContext.UseReduceExtrapolate, out encodingContext.CbComponent);
 395:               linearization_Compontent(encodingContext.CrSet, encodingContext.UseReduceExtrapolate, out encodingContext.CrComponent);
 396:          }
 397:   
 398:          public static void ComputeLL3Deltas(RfxProgressiveCodecContext encodingContext)
 399:          {
 400:              int ll3Len = RdpegfxTileUtils.GetBandSize(BandType_Values.LL3, encodingContext.UseReduceExtrapolate);
 401:              int ll3Idx = RdpegfxTileUtils.ComponentElementCount - ll3Len;
 402:   
 403:              //for (int i = ll3Idx + 1; i < TileUtils.ComponentElementCount; i++)
 404:              for (int i = RdpegfxTileUtils.ComponentElementCount - 1; i >= ll3Idx + 1; i--)
 405:              {
 406:                  encodingContext.YComponent[i] = (short)(encodingContext.YComponent[i] - encodingContext.YComponent[i - 1]);
 407:                  encodingContext.CbComponent[i] = (short)(encodingContext.CbComponent[i] - encodingContext.CbComponent[i - 1]);
 408:                  encodingContext.CrComponent[i] = (short)(encodingContext.CrComponent[i] - encodingContext.CrComponent[i - 1]);
 409:              }
 410:   
 411:          }
 412:   
 413:          protected static void linearization_Compontent(short[,] compontent, bool useReduceExtrapolate, out short[] lineOutput)
 414:          {
 415:              //sequence: HL1, LH1, HH1, HL2, LH2, HH2, HL3, LH3, HH3, and LL3
 416:              lineOutput = new short[TileSize * TileSize];
 417:              int curIdx = 0;
 418:   
 419:              BandType_Values[] bandArr = new BandType_Values[] { BandType_Values.HL1, BandType_Values.LH1, BandType_Values.HH1, BandType_Values.HL2, BandType_Values.LH2, BandType_Values.HH2, BandType_Values.HL3, BandType_Values.LH3, BandType_Values.HH3, BandType_Values.LL3 };
 420:              short[] bandOutput;
 421:              BandRect curBand;
 422:   
 423:              for (int i = 0; i < bandArr.Length; i++)
 424:              {
 425:                  curBand = RdpegfxTileUtils.GetBandRect(bandArr[i], useReduceExtrapolate);
 426:                  linearization_SubBand(compontent, curBand.left, curBand.top, curBand.right, curBand.bottom, out bandOutput);
 427:                  Array.Copy(bandOutput, 0, lineOutput, curIdx, bandOutput.Length);
 428:                  curIdx += bandOutput.Length;
 429:              }
 430:              
 431:          }
 432:   
 433:          private static void linearization_SubBand(short[,] input, int left, int top, int right, int bottom, out short[] bandOutput)
 434:          {
 435:              int totalNum = (right - left + 1) * (bottom - top + 1);
 436:              bandOutput = new short[totalNum];
 437:              int curIdx = 0;
 438:              for (int y = top; y <= bottom; y++)
 439:              {
 440:                  for (int x = left; x <= right; x++)
 441:                  {
 442:                      bandOutput[curIdx++] = input[x, y];
 443:                  }
 444:              }
 445:          }
 446:   
 447:   
 448:   
 449:          #endregion
 450:   
 451:          #region SRL Encoder
 452:   
 453:          //SRLEncode
 454:          public static EncodedTile SRLEncode(RfxProgressiveCodecContext encodingContext, Rdpegfx.RFX_PROGRESSIVE_CODEC_QUANT progQuant)
 455:          {
 456:              SRLEncoder encoder = new SRLEncoder();
 457:   
 458:              List<short> yDataToSrl = new List<short>();
 459:              List<short> cbDataToSrl = new List<short>();
 460:              List<short> crDataToSrl = new List<short>();
 461:   
 462:              List<int> yDataToSrlBitLen = new List<int>();
 463:              List<int> cbDataToSrlBitLen = new List<int>();
 464:              List<int> crDataToSrlBitLen = new List<int>();
 465:   
 466:              BitStream yRawBitStream = new BitStream();
 467:              BitStream cbRawBitStream = new BitStream();
 468:              BitStream crRawBitStream = new BitStream();
 469:   
 470:              int nonLL3Len = RdpegfxTileUtils.ComponentElementCount - RdpegfxTileUtils.GetBandSize(BandType_Values.LL3, encodingContext.UseReduceExtrapolate);
 471:              Rdpegfx.RFX_PROGRESSIVE_CODEC_QUANT prevProgQuant = encodingContext.prevProgQuant;
 472:              Rdpegfx.RFX_PROGRESSIVE_CODEC_QUANT curProgQuant = progQuant;
 473:   
 474:              for (int i = 0; i < RdpegfxTileUtils.ComponentElementCount; i++)
 475:              {
 476:                  BandType_Values band = RdpegfxTileUtils.GetBandByIndex(i, encodingContext.UseReduceExtrapolate);
 477:   
 478:                  int targetBitPos = RdpegfxTileUtils.GetBitPosFromQuant(curProgQuant.yQuantValues, band);
 479:                  int prevBitPos = RdpegfxTileUtils.GetBitPosFromQuant(prevProgQuant.yQuantValues, band);
 480:                  int bitCount = prevBitPos - targetBitPos;
 481:                  if (bitCount > 0)
 482:                  {
 483:                      if (encodingContext.DAS.Y_DwtQ[i] == 0 && i < nonLL3Len)
 484:                      {
 485:                          yDataToSrl.Add(encodingContext.ProgQ.Y_DwtQ[i]);
 486:                          yDataToSrlBitLen.Add(bitCount);
 487:                      }
 488:                      else
 489:                      {
 490:                          //Add raw data
 491:                          yRawBitStream.WriteBits(bitCount, Math.Abs(encodingContext.ProgQ.Y_DwtQ[i]));
 492:                      }
 493:                  }
 494:   
 495:                  targetBitPos = RdpegfxTileUtils.GetBitPosFromQuant(curProgQuant.cbQuantValues, band);
 496:                  prevBitPos = RdpegfxTileUtils.GetBitPosFromQuant(prevProgQuant.cbQuantValues, band);
 497:                  bitCount = prevBitPos - targetBitPos;
 498:                  if (bitCount > 0)
 499:                  {
 500:                      if (encodingContext.DAS.Cb_DwtQ[i] == 0 && i < nonLL3Len)
 501:                      {
 502:                          cbDataToSrl.Add(encodingContext.ProgQ.Cb_DwtQ[i]);
 503:                          cbDataToSrlBitLen.Add(bitCount);
 504:                      }
 505:                      else
 506:                      {
 507:                          //Add raw data
 508:                          cbRawBitStream.WriteBits(bitCount, Math.Abs(encodingContext.ProgQ.Cb_DwtQ[i]));
 509:                      }
 510:                  }
 511:   
 512:                  targetBitPos = RdpegfxTileUtils.GetBitPosFromQuant(curProgQuant.crQuantValues, band);
 513:                  prevBitPos = RdpegfxTileUtils.GetBitPosFromQuant(curProgQuant.crQuantValues, band);
 514:                  bitCount = prevBitPos - targetBitPos;
 515:                  if (bitCount > 0)
 516:                  {
 517:                      if (encodingContext.DAS.Cr_DwtQ[i] == 0 && i < nonLL3Len)
 518:                      {
 519:                          crDataToSrl.Add(encodingContext.ProgQ.Cr_DwtQ[i]);
 520:                          crDataToSrlBitLen.Add(bitCount);
 521:                      }
 522:                      else
 523:                      {
 524:                          //Add raw data
 525:                          crRawBitStream.WriteBits(bitCount, Math.Abs(encodingContext.ProgQ.Cr_DwtQ[i]));
 526:                      }
 527:                  }
 528:              }
 529:   
 530:              encodingContext.YData = encoder.Encode(yDataToSrl.ToArray(), yDataToSrlBitLen.ToArray());
 531:              encodingContext.CbData = encoder.Encode(cbDataToSrl.ToArray(), cbDataToSrlBitLen.ToArray());
 532:              encodingContext.CrData = encoder.Encode(crDataToSrl.ToArray(), crDataToSrlBitLen.ToArray());
 533:   
 534:              EncodedTile ugTile = new EncodedTile();
 535:              ugTile.YEncodedData = (byte[])encodingContext.YData.Clone();
 536:              ugTile.CbEncodedData = (byte[])encodingContext.CbData.Clone();
 537:              ugTile.CrEncodedData = (byte[])encodingContext.CrData.Clone();
 538:              ugTile.YRawData = yRawBitStream.ToBytes();
 539:              ugTile.CbRawData = cbRawBitStream.ToBytes();
 540:              ugTile.CrRawData = crRawBitStream.ToBytes();
 541:              ugTile.DataType = EncodedTileType.UpgradePass;
 542:              ugTile.IsDifferenceTile = encodingContext.UseDifferenceTile;
 543:              ugTile.UseReduceExtrapolate = encodingContext.UseReduceExtrapolate;
 544:              ugTile.CodecQuantVals = encodingContext.CodecQuantVals;
 545:              ugTile.QuantIdxY = encodingContext.QuantIdxY;
 546:              ugTile.QuantIdxCb = encodingContext.QuantIdxCb;
 547:              ugTile.QuantIdxCr = encodingContext.QuantIdxCr;
 548:              ugTile.ProgCodecQuant = curProgQuant;
 549:   
 550:              return ugTile;
 551:              
 552:          }
 553:   
 554:          #endregion
 555:   
 556:          #region Sub-Band Diffing
 557:          //Compute the difference tile dwt
 558:          public static void SubBandDiffing_DT(RfxProgressiveCodecContext encodingContext, TileState enTileInfo)
 559:          {
 560:              if (encodingContext.UseDifferenceTile)
 561:              {
 562:                  DwtTile oldDwt = enTileInfo.GetOldDwt();
 563:                  if (oldDwt != null)
 564:                  {
 565:                      short[] yDiffDwt, cbDiffDwt, crDiffDwt;
 566:                      int lenOfNonLL3Band = (RdpegfxTileUtils.ComponentElementCount - RdpegfxTileUtils.GetBandSize(BandType_Values.LL3, encodingContext.UseReduceExtrapolate));// ? 81 : 64;
 567:                      int yNewZeroCount, cbNewZeroCount, crNewZeroCount;
 568:                      int yDiffZeroCount, cbDiffZeroCount, crDiffZeroCount;
 569:                      yDiffDwt = RdpegfxTileUtils.SubDiffingDwt(encodingContext.YComponent, oldDwt.Y_DwtQ, lenOfNonLL3Band, out yNewZeroCount, out yDiffZeroCount);
 570:                      cbDiffDwt = RdpegfxTileUtils.SubDiffingDwt(encodingContext.CbComponent, oldDwt.Cb_DwtQ, lenOfNonLL3Band, out cbNewZeroCount, out cbDiffZeroCount);
 571:                      crDiffDwt = RdpegfxTileUtils.SubDiffingDwt(encodingContext.CrComponent, oldDwt.Cr_DwtQ, lenOfNonLL3Band, out crNewZeroCount, out crDiffZeroCount);
 572:                      if ((yDiffDwt != null && cbDiffDwt != null && crDiffDwt != null) &&
 573:                          (yNewZeroCount + cbNewZeroCount + crNewZeroCount < yDiffZeroCount + cbDiffZeroCount + crDiffZeroCount))
 574:                      {//use difference tile
 575:                          encodingContext.YComponent = yDiffDwt;
 576:                          encodingContext.CbComponent = cbDiffDwt;
 577:                          encodingContext.CrComponent = crDiffDwt;
 578:                          return;
 579:                      }
 580:                  }
 581:              }
 582:              encodingContext.UseDifferenceTile = false;//use orginal tile
 583:          }
 584:   
 585:          #endregion
 586:   
 587:          #region Extra(Progressive) Quantization 
 588:   
 589:          public static void ProgressiveQuantization(RfxProgressiveCodecContext encodingContext, ProgressiveChunk_Values chunk)
 590:          {
 591:              DwtBands yBD = DwtBands.GetFromLinearizationResult(encodingContext.DRS.Y_DwtQ, encodingContext.UseReduceExtrapolate);
 592:              DwtBands cbBD = DwtBands.GetFromLinearizationResult(encodingContext.DRS.Cb_DwtQ, encodingContext.UseReduceExtrapolate);
 593:              DwtBands crBD = DwtBands.GetFromLinearizationResult(encodingContext.DRS.Cr_DwtQ, encodingContext.UseReduceExtrapolate);
 594:   
 595:              ProgressiveQuantization_Component(yBD, TileComponents.Y, chunk);
 596:              ProgressiveQuantization_Component(cbBD, TileComponents.Cb, chunk);
 597:              ProgressiveQuantization_Component(crBD, TileComponents.Cr, chunk);
 598:   
 599:              DwtTile dwtDts = new DwtTile(yBD.GetLinearizationData(), cbBD.GetLinearizationData(), crBD.GetLinearizationData());
 600:              encodingContext.ProgQ = dwtDts;
 601:   
 602:              //Compute DTS
 603:              encodingContext.DTS = GetDTS(encodingContext, chunk);
 604:          }
 605:   
 606:          protected static void ProgressiveQuantization_Component(DwtBands dwt, TileComponents component, ProgressiveChunk_Values chunk)
 607:          {
 608:              //HL1, LH1, HH1, HL2, LH2, HH2, HL3, LH3, HH3, and LL3
 609:              ProgressiveQuantization_Band(dwt.HL1, BandType_Values.HL1, component, chunk);
 610:              ProgressiveQuantization_Band(dwt.LH1, BandType_Values.LH1, component, chunk);
 611:              ProgressiveQuantization_Band(dwt.HH1, BandType_Values.HH1, component, chunk);
 612:              ProgressiveQuantization_Band(dwt.HL2, BandType_Values.HL2, component, chunk);
 613:              ProgressiveQuantization_Band(dwt.LH2, BandType_Values.LH2, component, chunk);
 614:              ProgressiveQuantization_Band(dwt.HH2, BandType_Values.HH2, component, chunk);
 615:              ProgressiveQuantization_Band(dwt.HL3, BandType_Values.HL3, component, chunk);
 616:              ProgressiveQuantization_Band(dwt.LH3, BandType_Values.LH3, component, chunk);
 617:              ProgressiveQuantization_Band(dwt.HH3, BandType_Values.HH3, component, chunk);
 618:              ProgressiveQuantization_Band(dwt.LL3, BandType_Values.LL3, component, chunk);
 619:   
 620:          }
 621:   
 622:          protected static void ProgressiveQuantization_Component(DwtBands dwt, TileComponents component, RFX_PROGRESSIVE_CODEC_QUANT quants)
 623:          {
 624:              //HL1, LH1, HH1, HL2, LH2, HH2, HL3, LH3, HH3, and LL3
 625:              ProgressiveQuantization_Band(dwt.HL1, BandType_Values.HL1, component, quants);
 626:              ProgressiveQuantization_Band(dwt.LH1, BandType_Values.LH1, component, quants);
 627:              ProgressiveQuantization_Band(dwt.HH1, BandType_Values.HH1, component, quants);
 628:              ProgressiveQuantization_Band(dwt.HL2, BandType_Values.HL2, component, quants);
 629:              ProgressiveQuantization_Band(dwt.LH2, BandType_Values.LH2, component, quants);
 630:              ProgressiveQuantization_Band(dwt.HH2, BandType_Values.HH2, component, quants);
 631:              ProgressiveQuantization_Band(dwt.HL3, BandType_Values.HL3, component, quants);
 632:              ProgressiveQuantization_Band(dwt.LH3, BandType_Values.LH3, component, quants);
 633:              ProgressiveQuantization_Band(dwt.HH3, BandType_Values.HH3, component, quants);
 634:              ProgressiveQuantization_Band(dwt.LL3, BandType_Values.LL3, component, quants);
 635:          }
 636:   
 637:          static void ProgressiveQuantization_Band(short[] bandData, BandType_Values band, TileComponents component, ProgressiveChunk_Values chunk)
 638:          {
 639:              int bitPos = RdpegfxTileUtils.GetBitPosForChunk(chunk, component, band);
 640:              for (int i = 0; i < bandData.Length; i++)
 641:              {
 642:                  bandData[i] = FunProgQ(bandData[i], bitPos, band);
 643:              }
 644:   
 645:          }
 646:   
 647:          static void ProgressiveQuantization_Band(short[] bandData, BandType_Values band, TileComponents component, RFX_PROGRESSIVE_CODEC_QUANT quants)
 648:          {
 649:              int bitPos = RdpegfxTileUtils.GetBitPosForQuant(quants, component, band);
 650:              for (int i = 0; i < bandData.Length; i++)
 651:              {
 652:                  bandData[i] = FunProgQ(bandData[i], bitPos, band);
 653:              }
 654:          }
 655:   
 656:          static short FunProgQ(short v, int bitPos, BandType_Values band)
 657:          {
 658:              if (band != BandType_Values.LL3)
 659:              {
 660:                  if (v >= 0) return (short)(v >> bitPos);
 661:                  return (short)-((-v) >> bitPos);
 662:              }
 663:              else
 664:              {
 665:                  return (short)(v >> bitPos);
 666:              }
 667:          }
 668:   
 669:          static DwtTile GetDTS(RfxProgressiveCodecContext encodingContext, ProgressiveChunk_Values chunk)
 670:          {
 671:              DwtBands yBD = DwtBands.GetFromLinearizationResult(encodingContext.DRS.Y_DwtQ, encodingContext.UseReduceExtrapolate);
 672:              DwtBands cbBD = DwtBands.GetFromLinearizationResult(encodingContext.DRS.Cb_DwtQ, encodingContext.UseReduceExtrapolate);
 673:              DwtBands crBD = DwtBands.GetFromLinearizationResult(encodingContext.DRS.Cr_DwtQ, encodingContext.UseReduceExtrapolate);
 674:   
 675:              DTS_Component(yBD, TileComponents.Y, chunk);
 676:              DTS_Component(cbBD, TileComponents.Cb, chunk);
 677:              DTS_Component(crBD, TileComponents.Cr, chunk);
 678:   
 679:              DwtTile dwtDts = new DwtTile(yBD.GetLinearizationData(), cbBD.GetLinearizationData(), crBD.GetLinearizationData());
 680:              return dwtDts;
 681:          }
 682:   
 683:          protected static void DTS_Component(DwtBands dwt, TileComponents component, ProgressiveChunk_Values chunk)
 684:          {
 685:              //HL1, LH1, HH1, HL2, LH2, HH2, HL3, LH3, HH3, and LL3
 686:              DTS_Band(dwt.HL1, BandType_Values.HL1, component, chunk);
 687:              DTS_Band(dwt.LH1, BandType_Values.LH1, component, chunk);
 688:              DTS_Band(dwt.HH1, BandType_Values.HH1, component, chunk);
 689:              DTS_Band(dwt.HL2, BandType_Values.HL2, component, chunk);
 690:              DTS_Band(dwt.LH2, BandType_Values.LH2, component, chunk);
 691:              DTS_Band(dwt.HH2, BandType_Values.HH2, component, chunk);
 692:              DTS_Band(dwt.HL3, BandType_Values.HL3, component, chunk);
 693:              DTS_Band(dwt.LH3, BandType_Values.LH3, component, chunk);
 694:              DTS_Band(dwt.HH3, BandType_Values.HH3, component, chunk);
 695:              DTS_Band(dwt.LL3, BandType_Values.LL3, component, chunk);
 696:   
 697:          }
 698:   
 699:          protected static void DTS_Component(DwtBands dwt, TileComponents component, RFX_PROGRESSIVE_CODEC_QUANT quants)
 700:          {
 701:              //HL1, LH1, HH1, HL2, LH2, HH2, HL3, LH3, HH3, and LL3
 702:              DTS_Band(dwt.HL1, BandType_Values.HL1, component, quants);
 703:              DTS_Band(dwt.LH1, BandType_Values.LH1, component, quants);
 704:              DTS_Band(dwt.HH1, BandType_Values.HH1, component, quants);
 705:              DTS_Band(dwt.HL2, BandType_Values.HL2, component, quants);
 706:              DTS_Band(dwt.LH2, BandType_Values.LH2, component, quants);
 707:              DTS_Band(dwt.HH2, BandType_Values.HH2, component, quants);
 708:              DTS_Band(dwt.HL3, BandType_Values.HL3, component, quants);
 709:              DTS_Band(dwt.LH3, BandType_Values.LH3, component, quants);
 710:              DTS_Band(dwt.HH3, BandType_Values.HH3, component, quants);
 711:              DTS_Band(dwt.LL3, BandType_Values.LL3, component, quants);
 712:   
 713:          }
 714:   
 715:          static void DTS_Band(short[] bandData, BandType_Values band, TileComponents component, ProgressiveChunk_Values chunk)
 716:          {
 717:              int bitPos = RdpegfxTileUtils.GetBitPosForChunk(chunk, component, band);
 718:              for (int i = 0; i < bandData.Length; i++)
 719:              {
 720:                  bandData[i] = FunDTS(bandData[i], bitPos, band);
 721:              }
 722:   
 723:          }
 724:   
 725:          static void DTS_Band(short[] bandData, BandType_Values band, TileComponents component, RFX_PROGRESSIVE_CODEC_QUANT quants)
 726:          {
 727:              int bitPos = RdpegfxTileUtils.GetBitPosForQuant(quants, component, band);
 728:              for (int i = 0; i < bandData.Length; i++)
 729:              {
 730:                  bandData[i] = FunDTS(bandData[i], bitPos, band);
 731:              }
 732:   
 733:          }
 734:   
 735:          static short FunDTS(short v, int bitPos, BandType_Values band)
 736:          {
 737:              if (band != BandType_Values.LL3)
 738:              {
 739:                  if (v >= 0) return (short)((v >> bitPos) << bitPos);
 740:                  return (short)-(((-v) >> bitPos) << bitPos);
 741:              }
 742:              else
 743:              {
 744:                  return (short)(v >> bitPos << bitPos);
 745:              }
 746:          }
 747:   
 748:          #endregion
 749:   
 750:          static void SetTriState(DwtTile inputTile, bool useReduceExtrapolate)
 751:          {
 752:              int ll3Len = RdpegfxTileUtils.GetBandSize(BandType_Values.LL3, useReduceExtrapolate);
 753:              int ll3Idx = RdpegfxTileUtils.ComponentElementCount - ll3Len;
 754:   
 755:              DwtTile stateTile = new DwtTile(
 756:                  new short[RdpegfxTileUtils.ComponentElementCount], //y state
 757:                  new short[RdpegfxTileUtils.ComponentElementCount], //cb state
 758:                  new short[RdpegfxTileUtils.ComponentElementCount]); //cr state
 759:   
 760:              for (int i = 0; i < RdpegfxTileUtils.ComponentElementCount; i++)
 761:              {
 762:                  if (i < ll3Idx)
 763:                  {
 764:                      if (inputTile.Y_DwtQ[i] == 0)
 765:                      {
 766:                          stateTile.Y_DwtQ[i] = 0;
 767:                      }
 768:                      else if (inputTile.Y_DwtQ[i] > 0)
 769:                      {
 770:                          stateTile.Y_DwtQ[i] = 1;
 771:                      } if (inputTile.Y_DwtQ[i] < 0)
 772:                      {
 773:                          stateTile.Y_DwtQ[i] = -1;
 774:                      }
 775:   
 776:                      if (inputTile.Cb_DwtQ[i] == 0)
 777:                      {
 778:                          stateTile.Cb_DwtQ[i] = 0;
 779:                      }
 780:                      else if (inputTile.Cb_DwtQ[i] > 0)
 781:                      {
 782:                          stateTile.Cb_DwtQ[i] = 1;
 783:                      } if (inputTile.Cb_DwtQ[i] < 0)
 784:                      {
 785:                          stateTile.Cb_DwtQ[i] = -1;
 786:                      }
 787:   
 788:                      if (inputTile.Cr_DwtQ[i] == 0)
 789:                      {
 790:                          stateTile.Cr_DwtQ[i] = 0;
 791:                      }
 792:                      else if (inputTile.Cr_DwtQ[i] > 0)
 793:                      {
 794:                          stateTile.Cr_DwtQ[i] = 1;
 795:                      } if (inputTile.Cr_DwtQ[i] < 0)
 796:                      {
 797:                          stateTile.Cr_DwtQ[i] = -1;
 798:                      }
 799:                  }
 800:                  else
 801:                  {
 802:                      stateTile.Y_DwtQ[i] = 1;
 803:                      stateTile.Cb_DwtQ[i] = 1;
 804:                      stateTile.Cr_DwtQ[i] = 1;
 805:                  }
 806:              }
 807:          }
 808:      }
 809:  }