/// <summary> /// Constructor /// </summary> /// <param name="tsRfxCodecQuant"></param> /// <param name="mode"></param> public RemoteFXCodecContext(TS_RFX_CODEC_QUANT tsRfxCodecQuant, EntropyAlgorithm mode) { this.CodecQuantVals = new TS_RFX_CODEC_QUANT[] { tsRfxCodecQuant }; this.QuantIdxY = 0; this.QuantIdxCb = 0; this.QuantIdxCr = 0; this.Mode = mode; }
/// <summary> /// Set the default Codec Quant /// </summary> private void initCodecQuant() { codecQuant = new TS_RFX_CODEC_QUANT(); codecQuant.LL3_LH3 = 0x66; codecQuant.HL3_HH3 = 0x66; codecQuant.LH2_HL2 = 0x77; codecQuant.HH2_LH1 = 0x88; codecQuant.HL1_HH1 = 0x98; }
/// <summary> /// Quantization /// </summary> /// <param name="component">Y_Set, Cb_Set, Cr_Set</param> /// <param name="tsRfxCodecQuant">TS_RFX_CODEC_QUANT struct stored quantization factor</param> protected static void doQuantization_Component(short[,] component, TS_RFX_CODEC_QUANT tsRfxCodecQuant) { // Quantization factor: HL1, LH1, HH1, HL2, LH2, HH2, HL3, LH3, HH3, LL3 Hashtable scaleValueTable = new Hashtable(); int HL1_Factor = tsRfxCodecQuant.HL1_HH1 & 0x0f; int LH1_Factor = (tsRfxCodecQuant.HH2_LH1 & 0xf0) >> 4; int HH1_Factor = (tsRfxCodecQuant.HL1_HH1 & 0xf0) >> 4; int HL2_Factor = (tsRfxCodecQuant.LH2_HL2 & 0xf0) >> 4; int LH2_Factor = tsRfxCodecQuant.LH2_HL2 & 0x0f; int HH2_Factor = tsRfxCodecQuant.HH2_LH1 & 0x0f; int HL3_Factor = tsRfxCodecQuant.HL3_HH3 & 0x0f; int LH3_Factor = (tsRfxCodecQuant.LL3_LH3 & 0xf0) >> 4; int HH3_Factor = (tsRfxCodecQuant.HL3_HH3 & 0xf0) >> 4; int LL3_Factor = tsRfxCodecQuant.LL3_LH3 & 0x0f; int[] HL_Factor = { HL1_Factor, HL2_Factor, HL3_Factor }; int[] LH_Factor = { LH1_Factor, LH2_Factor, LH3_Factor }; int[] HH_Factor = { HH1_Factor, HH2_Factor, HH3_Factor }; int top, left, right, bottom; //Level 1, 2, 3 for (int i = 0; i <= 2; i++) { int levelSize = TileSize >> i; //HL1,2,3 top = 0; left = levelSize / 2; right = levelSize - 1; bottom = levelSize / 2 - 1; doQuantization_Subband(component, left, top, right, bottom, HL_Factor[i]); //LH1,2,3 top = levelSize / 2; left = 0; right = levelSize / 2 - 1; bottom = levelSize - 1; doQuantization_Subband(component, left, top, right, bottom, LH_Factor[i]); //HH1,2,3 top = levelSize / 2; left = levelSize / 2; right = levelSize - 1; bottom = levelSize - 1; doQuantization_Subband(component, left, top, right, bottom, HH_Factor[i]); } //LL3 top = 0; left = 0; right = TileSize / 8 - 1; bottom = TileSize / 8 - 1; doQuantization_Subband(component, left, top, right, bottom, LL3_Factor); }
/// <summary> /// Consturctor /// </summary> /// <param name="tsRfxCodecQuantVals">Codec quantity values array</param> /// <param name="quantIdxY">Index of Y component in quantity array</param> /// <param name="quantIdxCb">Index of Cb component in quantity array</param> /// <param name="quantIdxCr">Index of Cr component in quantity array</param> /// <param name="bProgressive">indicates if use progressive codec</param> /// <param name="bTileDiff">indicates if sub-diffing</param> /// <param name="bReduceExtrapolate">Indicates if use Reduce-Extrapolate method in DWT</param> public RfxProgressiveCodecContext( TS_RFX_CODEC_QUANT[] tsRfxCodecQuantVals, byte quantIdxY, byte quantIdxCb, byte quantIdxCr, bool bProgressive = false, bool bTileDiff = true, bool bReduceExtrapolate = true) : base(tsRfxCodecQuantVals, quantIdxY, quantIdxCb, quantIdxCr, EntropyAlgorithm.CLW_ENTROPY_RLGR1) { UseProgressive = bProgressive; UseDifferenceTile = bTileDiff; UseReduceExtrapolate = bReduceExtrapolate; prevProgQuant = RdpegfxTileUtils.GetProgCodecQuant(ProgressiveChunk_Values.kChunk_None); }
protected static void doQuantization_Component(short[,] component, TS_RFX_CODEC_QUANT tsRfxCodecQuant, bool useReduceExtrapolate) { // Quantization factor: HL1, LH1, HH1, HL2, LH2, HH2, HL3, LH3, HH3, LL3 Hashtable scaleValueTable = new Hashtable(); int HL1_Factor = tsRfxCodecQuant.HL1_HH1 & 0x0f; int LH1_Factor = (tsRfxCodecQuant.HH2_LH1 & 0xf0) >> 4; int HH1_Factor = (tsRfxCodecQuant.HL1_HH1 & 0xf0) >> 4; int HL2_Factor = (tsRfxCodecQuant.LH2_HL2 & 0xf0) >> 4; int LH2_Factor = tsRfxCodecQuant.LH2_HL2 & 0x0f; int HH2_Factor = tsRfxCodecQuant.HH2_LH1 & 0x0f; int HL3_Factor = tsRfxCodecQuant.HL3_HH3 & 0x0f; int LH3_Factor = (tsRfxCodecQuant.LL3_LH3 & 0xf0) >> 4; int HH3_Factor = (tsRfxCodecQuant.HL3_HH3 & 0xf0) >> 4; int LL3_Factor = tsRfxCodecQuant.LL3_LH3 & 0x0f; 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 }; int[] bandFactor = new int[] { HL1_Factor, LH1_Factor, HH1_Factor, HL2_Factor, LH2_Factor, HH2_Factor, HL3_Factor, LH3_Factor, HH3_Factor, LL3_Factor }; for (int i = 0; i < bandArr.Length; i++) { BandRect br = RdpegfxTileUtils.GetBandRect(bandArr[i], useReduceExtrapolate); doQuantization_Subband(component, br.left, br.top, br.right, br.bottom, bandFactor[i]); } }
/// <summary> /// Get codec quant with the specified quality /// </summary> /// <param name="quality">the encoding quality</param> /// <returns>The codec quant</returns> public static TS_RFX_CODEC_QUANT GetCodecQuant(ImageQuality_Values quality) { TS_RFX_CODEC_QUANT quant = new TS_RFX_CODEC_QUANT(); quant.LL3_LH3 = (byte)(GetQuantValue(quality, BandType_Values.LL3) | (GetQuantValue(quality, BandType_Values.LH3) << 4)); quant.HL3_HH3 = (byte)(GetQuantValue(quality, BandType_Values.HL3) | (GetQuantValue(quality, BandType_Values.HH3) << 4)); quant.LH2_HL2 = (byte)(GetQuantValue(quality, BandType_Values.LH2) | (GetQuantValue(quality, BandType_Values.HL2) << 4)); quant.HH2_LH1 = (byte)(GetQuantValue(quality, BandType_Values.HH2) | (GetQuantValue(quality, BandType_Values.LH1) << 4)); quant.HL1_HH1 = (byte)(GetQuantValue(quality, BandType_Values.HL1) | (GetQuantValue(quality, BandType_Values.HH1) << 4)); return quant; }
private TS_RFX_CODEC_QUANT[] GenerateCodecQuantVals() { TS_RFX_CODEC_QUANT[] quantVals = new TS_RFX_CODEC_QUANT[3]; quantVals[0].LL3_LH3 = 0x66; quantVals[0].HL3_HH3 = 0x66; quantVals[0].LH2_HL2 = 0x77; quantVals[0].HH2_LH1 = 0x88; quantVals[0].HL1_HH1 = 0x98; quantVals[1].LL3_LH3 = 0x66; quantVals[1].HL3_HH3 = 0x66; quantVals[1].LH2_HL2 = 0x99; quantVals[1].HH2_LH1 = 0x99; quantVals[1].HL1_HH1 = 0x99; quantVals[2].LL3_LH3 = 0x66; quantVals[2].HL3_HH3 = 0x88; quantVals[2].LH2_HL2 = 0x77; quantVals[2].HH2_LH1 = 0x88; quantVals[2].HL1_HH1 = 0x98; return quantVals; }
/// <summary> /// Consturctor /// </summary> /// <param name="tsRfxCodecQuantVals">Codec quantity values array</param> /// <param name="quantIdxY">Index of Y component in quantity array</param> /// <param name="quantIdxCb">Index of Cb component in quantity array</param> /// <param name="quantIdxCr">Index of Cr component in quantity array</param> /// <param name="useReduceExtrapolate">Indicates if used Reduce-Extrapolate method in DWT</param> public RfxProgressiveCodecContext( TS_RFX_CODEC_QUANT[] tsRfxCodecQuantVals, byte quantIdxY, byte quantIdxCb, byte quantIdxCr, bool useReduceExtrapolate = true) : base(tsRfxCodecQuantVals, quantIdxY, quantIdxCb, quantIdxCr, EntropyAlgorithm.CLW_ENTROPY_RLGR1) { UseReduceExtrapolate = useReduceExtrapolate; }
/// <summary> /// Method to send TS_RFX_TILESET to client. /// </summary> /// <param name="opMode">Indicates the operational mode.</param> /// <param name="entropy">Indicates the entropy algorithm.</param> /// <param name="tileImages">The image array for tiles to be sent. The width and height must be less than or equals with 64.</param> /// <param name="positions">A TILE_POSITION array indicating the positions of each tile images</param> /// <param name="codecQuantVals">Quant values array</param> /// <param name="quantIdxYs">Index array of Y component in Quant value array</param> /// <param name="quantIdxCbs">Index array of Cb component in Quant value array</param> /// <param name="quantIdxCrs">Index array of Cr component in Quant value array</param> public void SendTsRfxTileSet(OperationalMode opMode, EntropyAlgorithm entropy, Image[] tileImages, TILE_POSITION[] positions, TS_RFX_CODEC_QUANT[] codecQuantVals = null, byte[] quantIdxYs = null, byte[] quantIdxCbs = null, byte[] quantIdxCrs = null) { this.admEntropyAlgorithm = entropy; this.admOperationMode = opMode; TS_RFX_TILESET rfxTileSet = rdprfxServer.CreateTsRfxTileSet(opMode, entropy, tileImages, positions, codecQuantVals, quantIdxYs, quantIdxCbs, quantIdxCrs); if (this.currentTestType == RdprfxNegativeType.TsRfxTileSet_InvalidIdx) { rfxTileSet.idx = 0x0001; //set to an invalid value other than 0x0000. } else if (this.currentTestType == RdprfxNegativeType.TsRfxTileSet_InvalidLt) { rfxTileSet.properties &= 0xFFFE; //set "lt" to an invalid value: 0x0. } else if (this.currentTestType == RdprfxNegativeType.TsRfxTileSet_InvalidCct) { rfxTileSet.properties &= 0xFFCF; //set "cct" to an invalid value: 0x0. } else if (this.currentTestType == RdprfxNegativeType.TsRfxTileSet_InvalidXft) { rfxTileSet.properties &= 0xFC3F; //set "xft" to an invalid value: 0x0. } else if (this.currentTestType == RdprfxNegativeType.TsRfxTileSet_InvalidQt) { rfxTileSet.properties &= 0x3FFF; //set "xft" to an invalid value: 0x0. } else if (this.currentTestType == RdprfxNegativeType.TsRfxTileSet_InvalidTileSize) { rfxTileSet.tileSize = 0x80; //set to an invalid value other than 0x40. } if (this.rdpbcgrAdapter.SimulatedScreen != null) { this.rdpbcgrAdapter.SimulatedScreen.SetRemoteFXTileSet(rfxTileSet, entropy); } AddToPendingList(rfxTileSet); if (!CheckIfClientSupports(opMode, entropy)) { Site.Log.Add(LogEntryKind.Debug, "The client Cap is not supported: OperationalMode = {0}, EntropyAlgorithm = {1}", opMode.ToString(), entropy.ToString()); } }
/// <summary> /// Constructor /// </summary> /// <param name="tsRfxCodecQuantVals"></param> /// <param name="quantIdxY"></param> /// <param name="quantIdxCb"></param> /// <param name="quantIdxCr"></param> /// <param name="mode"></param> public RemoteFXCodecContext(TS_RFX_CODEC_QUANT[] tsRfxCodecQuantVals, byte quantIdxY, byte quantIdxCb, byte quantIdxCr, EntropyAlgorithm mode) { if(tsRfxCodecQuantVals == null || tsRfxCodecQuantVals.Length == 0) { throw new ArgumentException("Parameter tsRfxCodecQuantVals cannot be null and its length must larger than 0."); } int maxIndex = tsRfxCodecQuantVals.Length -1; if (quantIdxY > maxIndex || quantIdxCb > maxIndex || quantIdxCr > maxIndex) { throw new ArgumentException("Quant index for Y , Cb or Cr is/are larger than the size of tsRfxCodecQuantVals."); } this.CodecQuantVals = tsRfxCodecQuantVals; this.QuantIdxY = quantIdxY; this.QuantIdxCb = quantIdxCb; this.QuantIdxCr = quantIdxCr; this.Mode = mode; }
/// <summary> /// Method to create TS_RFX_TILESET. /// </summary> /// <param name="opMode">Indicates the operational mode.</param> /// <param name="entropy">Indicates the entropy algorithm.</param> /// <param name="tileImages">An array of bitmaps in Image type for a tile. The width and heigth must be less than or equals with 64.</param> /// <param name="positions">A TILE_POSITION array indicating the positions of each tile images</param> /// <param name="codecQuantVals">Quant values array</param> /// <param name="quantIdxYs">Index array of Y component in Quant value array</param> /// <param name="quantIdxCbs">Index array of Cb component in Quant value array</param> /// <param name="quantIdxCrs">Index array of Cr component in Quant value array</param> /// <returns></returns> public TS_RFX_TILESET CreateTsRfxTileSet( OperationalMode opMode, EntropyAlgorithm entropy, Image[] tileImages, TILE_POSITION[] positions, TS_RFX_CODEC_QUANT[] codecQuantVals = null, byte[] quantIdxYs = null, byte[] quantIdxCbs = null, byte[] quantIdxCrs = null ) { if (codecQuantVals == null) { codecQuantVals = new TS_RFX_CODEC_QUANT[1]; codecQuantVals[0] = codecQuant; } TS_RFX_TILESET rfxTileSet = new TS_RFX_TILESET(); rfxTileSet.CodecChannelT = new TS_RFX_CODEC_CHANNELT(); rfxTileSet.CodecChannelT.blockType = blockType_Value.WBT_EXTENSION; rfxTileSet.CodecChannelT.blockLen = 22 + 5; rfxTileSet.CodecChannelT.codecId = 0x01; rfxTileSet.CodecChannelT.channelId = 0x00; rfxTileSet.subtype = 0xCAC2; rfxTileSet.idx = 0x0000; ushort lt = 0x0001; ushort flags = 0x0002; if (opMode == OperationalMode.VideoMode) { flags = 0x0000; } ushort cct = 0x0001; ushort xft = 0x0001; ushort et = 0x0001; if (entropy == EntropyAlgorithm.CLW_ENTROPY_RLGR3) { et = 0x0004; } ushort qt = 0x0001; rfxTileSet.properties = lt; rfxTileSet.properties |= (ushort)(flags << 1); rfxTileSet.properties |= (ushort)(cct << 4); rfxTileSet.properties |= (ushort)(xft << 6); rfxTileSet.properties |= (ushort)(et << 10); rfxTileSet.properties |= (ushort)(qt << 14); rfxTileSet.numQuant = (byte)codecQuantVals.Length; rfxTileSet.tileSize = RdprfxServer.TileSize; rfxTileSet.numTiles = 1; rfxTileSet.quantVals = codecQuantVals; byte[] yData, cbData, crData; rfxTileSet.tiles = new TS_RFX_TILE[tileImages.Length]; rfxTileSet.numTiles = (ushort)rfxTileSet.tiles.Length; for (int i = 0; i < tileImages.Length; i++) { byte quantIdxY = quantIdxYs == null ? (byte)0 : (quantIdxYs.Length > i ? quantIdxYs[i] : (byte)0); byte quantIdxCb = quantIdxCbs == null ? (byte)0 : (quantIdxCbs.Length > i ? quantIdxCbs[i] : (byte)0); byte quantIdxCr = quantIdxCrs == null ? (byte)0 : (quantIdxCrs.Length > i ? quantIdxCrs[i] : (byte)0); RemoteFXCodecContext encodingContext = new RemoteFXCodecContext(codecQuantVals, quantIdxY, quantIdxCb, quantIdxCr, entropy); RemoteFXEncoder.EncodeTile(tileImages[i], 0, 0, encodingContext); yData = encodingContext.YData; cbData = encodingContext.CbData; crData = encodingContext.CrData; rfxTileSet.tiles[i].BlockT.blockType = blockType_Value.CBT_TILE; rfxTileSet.tiles[i].BlockT.blockLen = (uint)(19 + yData.Length + cbData.Length + crData.Length); rfxTileSet.tiles[i].quantIdxY = quantIdxY; rfxTileSet.tiles[i].quantIdxCb = quantIdxCb; rfxTileSet.tiles[i].quantIdxCr = quantIdxCr; rfxTileSet.tiles[i].xIdx = positions[i].xIdx; rfxTileSet.tiles[i].yIdx = positions[i].yIdx; rfxTileSet.tiles[i].YLen = (ushort)yData.Length; rfxTileSet.tiles[i].CbLen = (ushort)cbData.Length; rfxTileSet.tiles[i].CrLen = (ushort)crData.Length; rfxTileSet.tiles[i].YData = yData; rfxTileSet.tiles[i].CbData = cbData; rfxTileSet.tiles[i].CrData = crData; rfxTileSet.tilesDataSize += rfxTileSet.tiles[i].BlockT.blockLen; rfxTileSet.CodecChannelT.blockLen = (uint)(22 + 5 * rfxTileSet.numQuant + rfxTileSet.tilesDataSize); } return(rfxTileSet); }
/// <summary> /// Method to create TS_RFX_TILESET. /// </summary> /// <param name="opMode">Indicates the operational mode.</param> /// <param name="entropy">Indicates the entropy algorithm.</param> /// <param name="tileImages">An array of bitmaps in Image type for a tile. The width and heigth must be less than or equals with 64.</param> /// <param name="positions">A TILE_POSITION array indicating the positions of each tile images</param> /// <param name="codecQuantVals">Quant values array</param> /// <param name="quantIdxYs">Index array of Y component in Quant value array</param> /// <param name="quantIdxCbs">Index array of Cb component in Quant value array</param> /// <param name="quantIdxCrs">Index array of Cr component in Quant value array</param> /// <returns></returns> public TS_RFX_TILESET CreateTsRfxTileSet( OperationalMode opMode, EntropyAlgorithm entropy, Image[] tileImages, TILE_POSITION[] positions, TS_RFX_CODEC_QUANT[] codecQuantVals = null, byte[] quantIdxYs = null, byte[] quantIdxCbs = null, byte[] quantIdxCrs = null ) { if (codecQuantVals == null) { codecQuantVals = new TS_RFX_CODEC_QUANT[1]; codecQuantVals[0] = codecQuant; } TS_RFX_TILESET rfxTileSet = new TS_RFX_TILESET(); rfxTileSet.CodecChannelT = new TS_RFX_CODEC_CHANNELT(); rfxTileSet.CodecChannelT.blockType = blockType_Value.WBT_EXTENSION; rfxTileSet.CodecChannelT.blockLen = 22 + 5; rfxTileSet.CodecChannelT.codecId = 0x01; rfxTileSet.CodecChannelT.channelId = 0x00; rfxTileSet.subtype = 0xCAC2; rfxTileSet.idx = 0x0000; ushort lt = 0x0001; ushort flags = 0x0002; if (opMode == OperationalMode.VideoMode) flags = 0x0000; ushort cct = 0x0001; ushort xft = 0x0001; ushort et = 0x0001; if (entropy == EntropyAlgorithm.CLW_ENTROPY_RLGR3) et = 0x0004; ushort qt = 0x0001; rfxTileSet.properties = lt; rfxTileSet.properties |= (ushort)(flags << 1); rfxTileSet.properties |= (ushort)(cct << 4); rfxTileSet.properties |= (ushort)(xft << 6); rfxTileSet.properties |= (ushort)(et << 10); rfxTileSet.properties |= (ushort)(qt << 14); rfxTileSet.numQuant = (byte)codecQuantVals.Length; rfxTileSet.tileSize = RdprfxServer.TileSize; rfxTileSet.numTiles = 1; rfxTileSet.quantVals = codecQuantVals; byte[] yData, cbData, crData; rfxTileSet.tiles = new TS_RFX_TILE[tileImages.Length]; rfxTileSet.numTiles = (ushort) rfxTileSet.tiles.Length; for (int i = 0; i < tileImages.Length; i++) { byte quantIdxY = quantIdxYs == null ? (byte)0 : (quantIdxYs.Length > i ? quantIdxYs[i] : (byte)0); byte quantIdxCb = quantIdxCbs == null ? (byte)0 : (quantIdxCbs.Length > i ? quantIdxCbs[i] : (byte)0); byte quantIdxCr = quantIdxCrs == null ? (byte)0 : (quantIdxCrs.Length > i ? quantIdxCrs[i] : (byte)0); RemoteFXCodecContext encodingContext = new RemoteFXCodecContext(codecQuantVals, quantIdxY, quantIdxCb, quantIdxCr, entropy); RemoteFXEncoder.EncodeTile(tileImages[i], 0, 0, encodingContext); yData = encodingContext.YData; cbData = encodingContext.CbData; crData = encodingContext.CrData; rfxTileSet.tiles[i].BlockT.blockType = blockType_Value.CBT_TILE; rfxTileSet.tiles[i].BlockT.blockLen = (uint)(19 + yData.Length + cbData.Length + crData.Length); rfxTileSet.tiles[i].quantIdxY = quantIdxY; rfxTileSet.tiles[i].quantIdxCb = quantIdxCb; rfxTileSet.tiles[i].quantIdxCr = quantIdxCr; rfxTileSet.tiles[i].xIdx = positions[i].xIdx; rfxTileSet.tiles[i].yIdx = positions[i].yIdx; rfxTileSet.tiles[i].YLen = (ushort)yData.Length; rfxTileSet.tiles[i].CbLen = (ushort)cbData.Length; rfxTileSet.tiles[i].CrLen = (ushort)crData.Length; rfxTileSet.tiles[i].YData = yData; rfxTileSet.tiles[i].CbData = cbData; rfxTileSet.tiles[i].CrData = crData; rfxTileSet.tilesDataSize += rfxTileSet.tiles[i].BlockT.blockLen; rfxTileSet.CodecChannelT.blockLen = (uint)(22 + 5 * rfxTileSet.numQuant + rfxTileSet.tilesDataSize); } return rfxTileSet; }
/// <summary> /// Constructor /// </summary> /// <param name="y">Y component data</param> /// <param name="cb">Cb component data</param> /// <param name="cr">Cr component data</param> /// <param name="quant">Codec quantity</param> /// <param name="bReduceExtrapolate">Indicates if used Reduce-Extrapolate method in DWT</param> /// <param name="progQuant">The progressive codec quantity</param> public DwtTile(short[] y, short[] cb, short[] cr, TS_RFX_CODEC_QUANT[] quantVals, byte quantIdxY, byte quantIdxCb, byte quantIdxCr, bool bReduceExtrapolate, RFX_PROGRESSIVE_CODEC_QUANT progQuant = null) { // Clone the array, make sure different DwtTitle cannot hold the same array reference Y_DwtQ = (short[])y.Clone(); Cb_DwtQ = (short[])cb.Clone(); Cr_DwtQ = (short[])cr.Clone(); CodecQuantVals = quantVals; this.QuantIdxY = quantIdxY; this.QuantIdxCb = quantIdxCb; this.QuantIdxCr = quantIdxCr; UseReduceExtrapolate = bReduceExtrapolate; ProgCodecQuant = progQuant; }