/// <summary> /// Decode this PDU from the PduMarshaler. /// </summary> /// <param name="marshaler">This is used to encode the fields of this PDU.</param> public override bool Decode(PduMarshaler marshaler) { try { this.Header.cbSize = marshaler.ReadUInt32(); this.Header.PacketType = (PacketTypeValues)marshaler.ReadUInt32(); this.PresentatioinId = marshaler.ReadByte(); this.Version = (RdpevorVersionValues)marshaler.ReadByte(); this.Flags = (TsmmVideoData_FlagsValues)marshaler.ReadByte(); this.Reserved = marshaler.ReadByte(); this.HnsTimestamp = marshaler.ReadUInt64(); this.HnsDuration = marshaler.ReadUInt64(); this.CurrentPacketIndex = marshaler.ReadUInt16(); this.PacketsInSample = marshaler.ReadUInt16(); this.SampleNumber = marshaler.ReadUInt32(); this.cbSample = marshaler.ReadUInt32(); this.pSample = marshaler.ReadBytes((int)this.cbSample); this.Reserved2 = marshaler.ReadByte(); return(true); } catch { marshaler.Reset(); throw new PDUDecodeException(this.GetType(), marshaler.ReadToEnd()); } }
/// <summary> /// Method to sent a sample to client. /// </summary> /// <param name="presentationId">This is the same number as the PresentationId field in the TSMM_PRESENTATION_REQUEST message.</param> /// <param name="isKeyFrame">Is the sample a key frame.</param> /// <param name="SampleNumber">The number of sample in the video stream.</param> /// <param name="sampleData">The sample data in bytes which to be sent.</param> public void SendVideoSample(byte presentationId, bool isKeyFrame, uint SampleNumber, byte[] sampleData, ulong timeStamp) { if (sampleData == null) { return; } ushort totalPackets = (ushort)(((sampleData.Length - 1) / LargestSampleSize) + 1); for (ushort packetIndex = 1; packetIndex <= totalPackets; packetIndex++) { TsmmVideoData_FlagsValues flags = TsmmVideoData_FlagsValues.None; if (isKeyFrame) { flags |= TsmmVideoData_FlagsValues.TSMM_VIDEO_DATA_FLAG_KEYFRAME; } int packetSize = LargestSampleSize; if (packetIndex == totalPackets) { packetSize = sampleData.Length % LargestSampleSize; flags |= TsmmVideoData_FlagsValues.TSMM_VIDEO_DATA_FLAG_HAS_TIMESTAMPS; } byte[] packetData = new byte[packetSize]; Array.Copy(sampleData, (packetIndex - 1) * LargestSampleSize, packetData, 0, packetSize); SendVideoPacket(presentationId, flags, packetIndex, totalPackets, SampleNumber, packetData, timeStamp); //System.Threading.Thread.Sleep(100);//Sleep 0.1 second to avoid this packet is merged with next one in TCP layer. } }
/// <summary> /// Method to send a TSMM_VIDEO_DATA to client. /// </summary> /// <param name="presentationId">This is the same number as the PresentationId field in the TSMM_PRESENTATION_REQUEST message.</param> /// <param name="flags">The bits of this integer indicate attributes of this message. </param> /// <param name="packetIndex">This field contains the index of the current packet within the larger sample. </param> /// <param name="totalPacketsInSample">This field contains the number of packets that make up the current sample.</param> /// <param name="SampleNumber">This field contains the index of current sample in current presentation.</param> /// <param name="packetData">The video data in bytes which to be sent.</param> public void SendVideoPacket(byte presentationId, TsmmVideoData_FlagsValues flags, ushort packetIndex, ushort totalPacketsInSample, uint SampleNumber, byte[] packetData, ulong timeStamp) { TSMM_VIDEO_DATA videoDataPacket = rdpevorServer.CreateVideoDataPacket(presentationId, flags, packetIndex, totalPacketsInSample, SampleNumber, packetData, timeStamp); if (this.testType == RdpevorNegativeType.VideoData_InvalidPacketLength) { //Set the packet length to an invalid value. videoDataPacket.Header.cbSize = (uint)(videoDataPacket.Header.cbSize - 1); } else if (this.testType == RdpevorNegativeType.VideoData_InvalidVersion) { //Set version to an invalid value. videoDataPacket.Version = RdpevorVersionValues.InvalidValue; } rdpevorServer.SendRdpevorDataPdu(videoDataPacket); }
/// <summary> /// Method to create a TSMM_VIDEO_DATA packet. /// </summary> /// <param name="presentationId">This is the same number as the PresentationId field in the TSMM_PRESENTATION_REQUEST message.</param> /// <param name="flags">The bits of this integer indicate attributes of this message. </param> /// <param name="packetIndex">This field contains the index of the current packet within the larger sample. </param> /// <param name="totalPacketsInSample">This field contains the number of packets that make up the current sample.</param> /// <param name="SampleNumber">The sample index in this presentation.</param> /// <param name="videoData">The video data to be sent.</param> public TSMM_VIDEO_DATA CreateVideoDataPacket(byte presentationId, TsmmVideoData_FlagsValues flags, ushort packetIndex, ushort totalPacketsInSample, uint SampleNumber, byte[] videoRawData, ulong timeStamp) { TSMM_VIDEO_DATA videoData = new TSMM_VIDEO_DATA(); videoData.Header.PacketType = PacketTypeValues.TSMM_PACKET_TYPE_VIDEO_DATA; videoData.PresentatioinId = presentationId; videoData.Version = RdpevorVersionValues.RDP8; videoData.Flags = flags; videoData.Reserved = 0; if (packetIndex != totalPacketsInSample) { //HnsTimestamp and HnsDuration are only effective in the last packet of a sample. videoData.HnsTimestamp = 0; videoData.HnsDuration = 0; } else { videoData.HnsTimestamp = timeStamp; videoData.HnsDuration = timeStamp - lastPacketTimestamp; lastPacketTimestamp = videoData.HnsTimestamp; } videoData.CurrentPacketIndex = packetIndex; videoData.PacketsInSample = totalPacketsInSample; videoData.SampleNumber = SampleNumber; if (videoRawData != null) { videoData.pSample = new byte[videoRawData.Length]; Array.Copy(videoRawData, videoData.pSample, videoRawData.Length); videoData.Header.cbSize = (uint)(sizeOfVideoPacketFixedFields + videoData.pSample.Length); videoData.cbSample = (uint)videoData.pSample.Length; } else { videoData.pSample = null; videoData.Header.cbSize = sizeOfVideoPacketFixedFields; videoData.cbSample = 0; } videoData.Reserved2 = 0; return(videoData); }
/// <summary> /// Decode this PDU from the PduMarshaler. /// </summary> /// <param name="marshaler">This is used to encode the fields of this PDU.</param> public override bool Decode(PduMarshaler marshaler) { try { this.Header.cbSize = marshaler.ReadUInt32(); this.Header.PacketType = (PacketTypeValues)marshaler.ReadUInt32(); this.PresentatioinId = marshaler.ReadByte(); this.Version = (RdpevorVersionValues)marshaler.ReadByte(); this.Flags = (TsmmVideoData_FlagsValues)marshaler.ReadByte(); this.Reserved = marshaler.ReadByte(); this.HnsTimestamp = marshaler.ReadUInt64(); this.HnsDuration = marshaler.ReadUInt64(); this.CurrentPacketIndex = marshaler.ReadUInt16(); this.PacketsInSample = marshaler.ReadUInt16(); this.SampleNumber = marshaler.ReadUInt32(); this.cbSample = marshaler.ReadUInt32(); this.pSample = marshaler.ReadBytes((int)this.cbSample); this.Reserved2 = marshaler.ReadByte(); return true; } catch { marshaler.Reset(); throw new PDUDecodeException(this.GetType(), marshaler.ReadToEnd()); } }