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.Collections;
9:
10: namespace Microsoft.Protocols.TestTools.StackSdk.RemoteDesktop.Rdpegfx
11: {
12: /// <summary>
13: /// The RemoteFX Progressive Decoder
14: /// </summary>
15: public class RfxProgressiveDecoder
16: {
17: /// <summary>
18: /// Decode a encoded tile
19: /// </summary>
20: /// <param name="enTile">Represents a encoded tile.</param>
21: /// <param name="tState">The context state of the tile that going to be decoded.</param>
22: public static void DecodeTile(EncodedTile enTile, TileState tState)
23: {
24: RfxProgressiveCodecContext codecContext = new RfxProgressiveCodecContext(
25: enTile.CodecQuantVals,
26: enTile.QuantIdxY,
27: enTile.QuantIdxCb,
28: enTile.QuantIdxCr,
29: enTile.DataType == EncodedTileType.Simple ? false : true,
30: enTile.IsDifferenceTile,
31: enTile.UseReduceExtrapolate);
32:
33: //RLGR/SRL Decode
34: if (enTile.DataType == EncodedTileType.FirstPass || enTile.DataType == EncodedTileType.Simple)
35: { //first pass or simple
36: codecContext.YData = enTile.YEncodedData;
37: codecContext.CbData = enTile.CbEncodedData;
38: codecContext.CrData = enTile.CrEncodedData;
39: RemoteFXDecoder.RLGRDecode(codecContext);
40: ComputeOriginalLL3FromDeltas(codecContext);
41: }
42: else
43: {
44: SRLDecode(codecContext, enTile, tState);
45: }
46:
47: //Progressive Dequantization
48: if (enTile.DataType != EncodedTileType.Simple)
49: {
50: ProgressiveDeQuantization(codecContext, enTile.ProgCodecQuant);
51: }
52:
53: // Create a DwtTile instance for tri-state
54: DwtTile triStateDwt = new DwtTile(codecContext.YComponent, codecContext.CbComponent, codecContext.CrComponent,
55: enTile.CodecQuantVals, enTile.QuantIdxY, enTile.QuantIdxCb, enTile.QuantIdxCr, enTile.UseReduceExtrapolate, enTile.ProgCodecQuant);
56:
57: //Set Tri-State for progressive codec
58: if (enTile.DataType == EncodedTileType.FirstPass)
59: {
60: //DwtTile tileTriStat = SetTriState(diffDwt, enTile.UseReduceExtrapolate);
61: tState.UpdateTriState(triStateDwt);
62: }
63: else if (enTile.DataType == EncodedTileType.UpgradePass)
64: {
65: DwtTile prvStat = tState.GetTriState();
66: prvStat.Add(triStateDwt);
67: // update ProCodecQuant
68: prvStat.ProgCodecQuant = triStateDwt.ProgCodecQuant;
69: tState.UpdateTriState(prvStat);
70: }
71:
72: // Create another DwtTile instance for DWT Data.
73: // The data in diffDwt is the same as triStateDwt, this will makesure the DWT data and tri-state not share the same DWT tile instance
74: DwtTile diffDwt = new DwtTile(codecContext.YComponent, codecContext.CbComponent, codecContext.CrComponent,
75: enTile.CodecQuantVals, enTile.QuantIdxY, enTile.QuantIdxCb, enTile.QuantIdxCr, enTile.UseReduceExtrapolate, enTile.ProgCodecQuant);
76:
77: //Sum difference
78: if ( enTile.IsDifferenceTile || enTile.DataType == EncodedTileType.UpgradePass)
79: {
80: tState.AddDwt(diffDwt);
81: }
82: else
83: {
84: tState.UpdateDwt(diffDwt);
85: }
86: }
87:
88: /// <summary>
89: /// Decode a tile from DWT
90: /// </summary>
91: /// <param name="codecContext">The codec context which contians the DWT data of a tile.</param>
92: public static void DecodeTileFromDwtQ(RfxProgressiveCodecContext codecContext)
93: {
94: //Sub Band Reconstruction
95: SubBandReconstruction(codecContext);
96:
97: //De-quantization
98: Dequantization(codecContext);
99:
100: //Inverse DWT
101: if (codecContext.UseReduceExtrapolate)
102: {
103: InverseDWT(codecContext);
104: }
105: else
106: {
107: RemoteFXDecoder.InverseDWT(codecContext);
108: }
109:
110: //(Y, U, V) to (R, G, B)
111: RemoteFXDecoder.YCbCrToRGB(codecContext);
112: }
113:
114: #region SRL Decode
115:
116: public static void SRLDecode(RfxProgressiveCodecContext codecContext, EncodedTile enTile, TileState tState)
117: {
118: SRLDecoder yDecoder = null;
119: SRLDecoder cbDecoder = null;
120: SRLDecoder crDecoder = null;
121:
122: List<short> yData = new List<short>();
123: List<short> cbData = new List<short>();
124: List<short> crData = new List<short>();
125: DwtTile triState = tState.GetTriState();
126: RFX_PROGRESSIVE_CODEC_QUANT prvProgQuant = tState.GetDwt().ProgCodecQuant;
127: int nonLL3Len = RdpegfxTileUtils.ComponentElementCount - RdpegfxTileUtils.GetBandSize(BandType_Values.LL3, enTile.UseReduceExtrapolate);
128:
129: if (enTile.YEncodedData != null)
130: {
131: yDecoder = new SRLDecoder(enTile.YEncodedData);
132: }
133:
134: if (enTile.CbEncodedData != null)
135: {
136: cbDecoder = new SRLDecoder(enTile.CbEncodedData);
137: }
138:
139: if (enTile.CrEncodedData != null)
140: {
141: crDecoder = new SRLDecoder(enTile.CrEncodedData);
142: }
143:
144: BitStream yRaw = BitStream.GetFromBytes(enTile.YRawData);
145: BitStream cbRaw = BitStream.GetFromBytes(enTile.CbRawData);
146: BitStream crRaw = BitStream.GetFromBytes(enTile.CrRawData);
147:
148: for (int i = 0; i < RdpegfxTileUtils.ComponentElementCount; i++)
149: {
150: BandType_Values band = RdpegfxTileUtils.GetBandByIndex(i, enTile.UseReduceExtrapolate);
151:
152: //Y
153: int curBitPos = RdpegfxTileUtils.GetBitPosFromQuant(enTile.ProgCodecQuant.yQuantValues, band);
154: int prvBitPos = RdpegfxTileUtils.GetBitPosFromQuant(prvProgQuant.yQuantValues, band);
155: int bitCount = prvBitPos - curBitPos;
156: int sign = triState.Y_DwtQ[i];
157: if (bitCount > 0)
158: {
159: if (sign == 0 && i < nonLL3Len)
160: {
161: if (yDecoder != null)
162: {
163: short? decodedValue = yDecoder.DecodeOne(bitCount);
164: if (decodedValue.HasValue)
165: {
166: yData.Add(decodedValue.Value);
167: }
168: else
169: {
170: yData.Add(0);
171: }
172: }
173: else
174: {
175: yData.Add(0);
176: }
177: }
178: else
179: {
180: int output;
181: if (yRaw.ReadInt32(bitCount, out output))
182: {
183: if (sign < 0 && i < nonLL3Len) output = -output;
184: yData.Add((short)output);
185: }
186: else
187: {
188: yData.Add(0);
189: }
190: }
191: }
192: else
193: {
194: yData.Add(0);
195: }
196:
197: //Cb
198: curBitPos = RdpegfxTileUtils.GetBitPosFromQuant(enTile.ProgCodecQuant.cbQuantValues, band);
199: prvBitPos = RdpegfxTileUtils.GetBitPosFromQuant(prvProgQuant.cbQuantValues, band);
200: bitCount = prvBitPos - curBitPos;
201: sign = triState.Cb_DwtQ[i];
202: if (bitCount > 0)
203: {
204: if (sign == 0 && i < nonLL3Len)
205: {
206: if (cbDecoder != null)
207: {
208: short? decodedValue = cbDecoder.DecodeOne(bitCount);
209: if (decodedValue.HasValue)
210: {
211: cbData.Add(decodedValue.Value);
212: }
213: else
214: {
215: cbData.Add(0);
216: }
217: }
218: else
219: {
220: cbData.Add(0);
221: }
222: }
223: else
224: {
225: int output;
226: if (cbRaw.ReadInt32(bitCount, out output))
227: {
228: if (sign < 0 && i < nonLL3Len) output = -output;
229: cbData.Add((short)output);
230: }
231: else
232: {
233: cbData.Add(0);
234: }
235: }
236: }
237: else
238: {
239: cbData.Add(0);
240: }
241:
242: //cr
243: curBitPos = RdpegfxTileUtils.GetBitPosFromQuant(enTile.ProgCodecQuant.crQuantValues, band);
244: prvBitPos = RdpegfxTileUtils.GetBitPosFromQuant(prvProgQuant.crQuantValues, band);
245: bitCount = prvBitPos - curBitPos;
246: sign = triState.Cr_DwtQ[i];
247: if (bitCount > 0)
248: {
249: if (sign == 0 && i < nonLL3Len)
250: {
251: if (crDecoder != null)
252: {
253: short? decodedValue = crDecoder.DecodeOne(bitCount);
254: if (decodedValue.HasValue)
255: {
256: crData.Add(decodedValue.Value);
257: }
258: else
259: {
260: crData.Add(0);
261: }
262: }
263: else
264: {
265: crData.Add(0);
266: }
267: }
268: else
269: {
270: int output;
271: if (crRaw.ReadInt32(bitCount, out output))
272: {
273: if (sign < 0 && i < nonLL3Len) output = -output;
274: crData.Add((short)output);
275: }
276: else
277: {
278: crData.Add(0);
279: }
280: }
281: }
282: else
283: {
284: crData.Add(0);
285: }
286: }
287:
288: codecContext.YComponent = yData.ToArray();
289: codecContext.CbComponent = cbData.ToArray();
290: codecContext.CrComponent = crData.ToArray();
291: }
292:
293: #endregion
294:
295: #region Sub-Band Reconstruction
296: public static void SubBandReconstruction(RfxProgressiveCodecContext codecContext)
297: {
298: reconstruction_Component(codecContext.YComponent, out codecContext.YSet, codecContext.UseReduceExtrapolate);
299: reconstruction_Component(codecContext.CbComponent, out codecContext.CbSet, codecContext.UseReduceExtrapolate);
300: reconstruction_Component(codecContext.CrComponent, out codecContext.CrSet, codecContext.UseReduceExtrapolate);
301: }
302:
303: public static void ComputeOriginalLL3FromDeltas(RfxProgressiveCodecContext codecContext)
304: {
305: int ll3Len = RdpegfxTileUtils.GetBandSize(BandType_Values.LL3, codecContext.UseReduceExtrapolate);
306: int ll3Idx = RdpegfxTileUtils.ComponentElementCount - ll3Len;
307:
308: for (int i = ll3Idx + 1; i < RdpegfxTileUtils.ComponentElementCount; i++)
309: {
310: codecContext.YComponent[i] = (short)(codecContext.YComponent[i] + codecContext.YComponent[i - 1]);
311: codecContext.CbComponent[i] = (short)(codecContext.CbComponent[i] + codecContext.CbComponent[i - 1]);
312: codecContext.CrComponent[i] = (short)(codecContext.CrComponent[i] + codecContext.CrComponent[i - 1]);
313: }
314:
315: }
316:
317: public static void reconstruction_Component(short[] component1D, out short[,] compontent2D, bool useReduceExtrapolate)
318: {
319: //sequence: HL1, LH1, HH1, HL2, LH2, HH2, HL3, LH3, HH3, and LL3
320: //lineOutput = new short[TileSize * TileSize];
321: compontent2D = new short[RdpegfxTileUtils.TileSize, RdpegfxTileUtils.TileSize];
322: 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 };
323:
324: int offset = 0;
325: BandRect curBand;
326:
327: for (int i = 0; i < bandArr.Length; i++)
328: {
329: curBand = RdpegfxTileUtils.GetBandRect(bandArr[i], useReduceExtrapolate);
330: reconstruction_SubBand(compontent2D, curBand.left, curBand.top, curBand.right, curBand.bottom, component1D, ref offset);
331: }
332: }
333:
334: public static void reconstruction_SubBand(short[,] input, int left, int top, int right, int bottom, short[] bandOutput, ref int offset)
335: {
336: //int totalNum = (right - left + 1) * (bottom - top + 1);
337: //bandOutput = new short[totalNum];
338: for (int y = top; y <= bottom; y++)
339: {
340: for (int x = left; x <= right; x++)
341: {
342: input[x, y] = bandOutput[offset++];
343: }
344: }
345: }
346:
347: #endregion
348:
349: #region Inverse DWT
350:
351: //InverseDWT
352: public static void InverseDWT(RfxProgressiveCodecContext codecContext)
353: {
354: InverseDWT_Component(codecContext.YSet);
355: InverseDWT_Component(codecContext.CbSet);
356: InverseDWT_Component(codecContext.CrSet);
357: }
358:
359: protected static void InverseDWT_Component(short[,] component)
360: {
361: //Level 3, 2, 1
362: InverseDWT_2D(component, 3);
363: InverseDWT_2D(component, 2);
364: InverseDWT_2D(component, 1);
365: }
366:
367: private static void InverseDWT_2D(short[,] data2D, int pass)
368: {
369: //level > 0
370: //data2D.Length % (1<<(level - 1)) == 0
371: int inScopelen;
372: switch (pass)
373: {
374: case 1:
375: {
376: // First pass
377: inScopelen = 64;
378: break;
379: }
380: case 2:
381: {
382: // Second pass
383: inScopelen = 33;
384: break;
385: }
386: case 3:
387: {
388: // Third pass
389: inScopelen = 17;
390: break;
391: }
392: default:
393: {
394: throw new InvalidOperationException("DWT_2D: the parameter level should only be 1, 2, or 3.");
395: }
396: }
397:
398: //Horizontal DWT
399: for (int y = 0; y < inScopelen; y++)
400: {
401: short[] row;
402: RemoteFXDecoder.getRowFrom2DArr<short>(data2D, out row, y, inScopelen);
403: row = InverseDWT_1D(row);
404: for (int x = 0; x < inScopelen; x++)
405: {
406: data2D[x, y] = row[x];
407: }
408: }
409:
410: //Vertical DWT
411: for (int x = 0; x < inScopelen; x++)
412: {
413: short[] col;
414: RemoteFXDecoder.getColFrom2DArr<short>(data2D, out col, x, inScopelen);
415: col = InverseDWT_1D(col);
416: for (int y = 0; y < inScopelen; y++)
417: {
418: data2D[x, y] = col[y];
419: }
420: }
421: }
422:
423: public static short[] InverseDWT_1D(short[] elements)
424: {
425: int hOffset = elements.Length / 2 + 1;
426: short[] encodedData;
427: if (elements.Length == RdpegfxTileUtils.TileSize)
428: {
429: //first pass
430: encodedData = new short[elements.Length + 1];
431: Array.Copy(elements, encodedData, elements.Length);
432: encodedData[elements.Length] = 0;
433: }
434: else
435: {
436: encodedData = elements;
437: }
438: int hLen = encodedData.Length - hOffset;
439: short[] decodedData = new short[encodedData.Length];
440: for (int i = 1; 2 * i < encodedData.Length - 1; i++)
441: {
442: //X[2n] = L[n] - (H[n-1] + H[n] + 1) / 2
443: //decodedData[2 * i] = (short)Math.Round(encodedData[i] - (encodedData[hOffset + i - 1] + encodedData[hOffset + i] + 1.0f) / 2);
444: decodedData[2 * i] = (short)(encodedData[i] - ((encodedData[hOffset + i - 1] + encodedData[hOffset + i] + 1) >> 1));
445: }
446:
447: //decodedData[decodedData.Length - 1] = (short)Math.Round(2 * decodedData[decodedData.Length - 2] - 4 * encodedData[hOffset + hLen - 1] - decodedData[decodedData.Length - 3] + 0.0f);
448: decodedData[decodedData.Length - 1] = (short)Math.Round(encodedData[hOffset - 1] - encodedData[hOffset + hLen - 1] - 0.5f);
449: for (int i = 1; 2 * i + 2 < encodedData.Length; i++)
450: {
451: //X[2n + 1] = 2*H[n] + (X[2n] + X[2n + 2])/2
452: //decodedData[2 * i + 1] = (short)Math.Round(2 * encodedData[hOffset + i] + (decodedData[2 * i] + decodedData[2 * i + 2] + 0.0f) / 2);
453: decodedData[2 * i + 1] = (short)(2 * encodedData[hOffset + i] + ((decodedData[2 * i] + decodedData[2 * i + 2]) >> 1));
454: }
455:
456: //Handle X[0], [1], [len-1]
457: //H(-1) = H[0]
458: decodedData[0] = (short)Math.Round(encodedData[0] - (encodedData[hOffset] + encodedData[hOffset] + 1.0f) / 2);
459: decodedData[1] = (short)Math.Round(2 * encodedData[hOffset] + (decodedData[0] + decodedData[2] + 0.0f) / 2);
460: //decodedData[decodedData.Length - 1] = (short)(2 * encodedData[hOffset + hLen - 1] + decodedData[decodedData.Length - 2]);
461: //decodedData[decodedData.Length - 1] = (short)Math.Round(encodedData[hOffset - 1] - (2 * encodedData[hOffset + hLen - 1] + 1.0f) / 2);
462:
463: short[] reElements;
464: if (decodedData.Length > elements.Length)
465: {
466: reElements = new short[elements.Length];
467: Array.Copy(decodedData, reElements, reElements.Length);
468: }
469: else
470: {
471: reElements = decodedData;
472: }
473: return reElements;
474: }
475:
476: #endregion
477:
478: #region Dequantization
479: public static void Dequantization(RfxProgressiveCodecContext codecContext)
480: {
481: dequantization_Component(codecContext.YSet, codecContext.CodecQuantVals[codecContext.QuantIdxY], codecContext.UseReduceExtrapolate);
482: dequantization_Component(codecContext.CbSet, codecContext.CodecQuantVals[codecContext.QuantIdxCb], codecContext.UseReduceExtrapolate);
483: dequantization_Component(codecContext.CrSet, codecContext.CodecQuantVals[codecContext.QuantIdxCr], codecContext.UseReduceExtrapolate);
484: }
485:
486: protected static void dequantization_Component(short[,] compontent, TS_RFX_CODEC_QUANT tsRfxCodecQuant, bool useReduceExtrapolate)
487: {
488: // Quantization factor: HL1, LH1, HH1, HL2, LH2, HH2, HL3, LH3, HH3, LL3
489: Hashtable scaleValueTable = new Hashtable();
490: int HL1_Factor = tsRfxCodecQuant.HL1_HH1 & 0x0f;
491: int LH1_Factor = (tsRfxCodecQuant.HH2_LH1 & 0xf0) >> 4;
492: int HH1_Factor = (tsRfxCodecQuant.HL1_HH1 & 0xf0) >> 4;
493: int HL2_Factor = (tsRfxCodecQuant.LH2_HL2 & 0xf0) >> 4;
494: int LH2_Factor = tsRfxCodecQuant.LH2_HL2 & 0x0f;
495: int HH2_Factor = tsRfxCodecQuant.HH2_LH1 & 0x0f;
496: int HL3_Factor = tsRfxCodecQuant.HL3_HH3 & 0x0f;
497: int LH3_Factor = (tsRfxCodecQuant.LL3_LH3 & 0xf0) >> 4;
498: int HH3_Factor = (tsRfxCodecQuant.HL3_HH3 & 0xf0) >> 4;
499: int LL3_Factor = tsRfxCodecQuant.LL3_LH3 & 0x0f;
500: int[] HL_Factor = { HL1_Factor, HL2_Factor, HL3_Factor };
501: int[] LH_Factor = { LH1_Factor, LH2_Factor, LH3_Factor };
502: int[] HH_Factor = { HH1_Factor, HH2_Factor, HH3_Factor };
503:
504: 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 };
505: int[] bandFactor = new int[] { HL1_Factor, LH1_Factor, HH1_Factor, HL2_Factor, LH2_Factor, HH2_Factor, HL3_Factor, LH3_Factor, HH3_Factor, LL3_Factor };
506:
507: for (int i = 0; i < bandArr.Length; i++)
508: {
509: BandRect br = RdpegfxTileUtils.GetBandRect(bandArr[i], useReduceExtrapolate);
510: doDequantization_Subband(compontent, br.left, br.top, br.right, br.bottom, bandFactor[i]);
511: }
512: }
513:
514: private static void doDequantization_Subband(short[,] input, int left, int top, int right, int bottom, int factor)
515: {
516: for (int x = left; x <= right; x++)
517: {
518: for (int y = top; y <= bottom; y++)
519: {
520: input[x, y] = (short)(input[x, y] << (factor - 6));//<< DWT_PREC);
521: }
522: }
523: }
524: #endregion
525:
526: #region Progressive Dequantization
527:
528: public static void ProgressiveDeQuantization(RfxProgressiveCodecContext codecContext, RFX_PROGRESSIVE_CODEC_QUANT progCodecQuant )
529: {
530: ProgressiveDeQuantization_Component(codecContext.YComponent, progCodecQuant.yQuantValues, codecContext.UseReduceExtrapolate);
531: ProgressiveDeQuantization_Component(codecContext.CbComponent, progCodecQuant.cbQuantValues, codecContext.UseReduceExtrapolate);
532: ProgressiveDeQuantization_Component(codecContext.CrComponent, progCodecQuant.crQuantValues, codecContext.UseReduceExtrapolate);
533: }
534:
535: protected static void ProgressiveDeQuantization_Component(short[] data, RFX_COMPONMENT_CODEC_QUANT quant, bool useReduceExtrapolate)
536: {
537: int bitPos = 0;
538: for (int i = 0; i < RdpegfxTileUtils.ComponentElementCount; i++)
539: {
540: BandType_Values band = RdpegfxTileUtils.GetBandByIndex(i, useReduceExtrapolate);
541: bitPos = RdpegfxTileUtils.GetBitPosFromQuant(quant, band);
542: data[i] = FunProgDeQ(data[i], bitPos, band);
543: }
544: }
545:
546: static short FunProgDeQ(short v, int bitPos, BandType_Values band)
547: {
548: if (band != BandType_Values.LL3)
549: {
550: if (v >= 0) return (short)(v << bitPos);
551: return (short)-((-v) << bitPos);
552: }
553: else
554: {
555: return (short)(v << bitPos);
556: }
557: }
558: #endregion
559:
560: static DwtTile SetTriState(DwtTile inputTile, bool useReduceExtrapolate)
561: {
562: int ll3Len = RdpegfxTileUtils.GetBandSize(BandType_Values.LL3, useReduceExtrapolate);
563: int ll3Idx = RdpegfxTileUtils.ComponentElementCount - ll3Len;
564:
565: DwtTile stateTile = new DwtTile(
566: new short[RdpegfxTileUtils.ComponentElementCount], //y state
567: new short[RdpegfxTileUtils.ComponentElementCount], //cb state
568: new short[RdpegfxTileUtils.ComponentElementCount]); //cr state
569:
570: for (int i = 0; i < RdpegfxTileUtils.ComponentElementCount; i++)
571: {
572: if (i < ll3Idx)
573: {
574: stateTile.Y_DwtQ[i] = (short)Math.Sign(inputTile.Y_DwtQ[i]);
575: stateTile.Cb_DwtQ[i] = (short)Math.Sign(inputTile.Cb_DwtQ[i]);
576: stateTile.Cr_DwtQ[i] = (short)Math.Sign(inputTile.Cr_DwtQ[i]);
577: }
578: else
579: {
580: stateTile.Y_DwtQ[i] = 1;
581: stateTile.Cb_DwtQ[i] = 1;
582: stateTile.Cr_DwtQ[i] = 1;
583: }
584: }
585: return stateTile;
586: }
587: }
588: }