/// <summary> /// Does the video job. /// </summary> private void DoWorkerJob(System.Net.Sockets.UdpClient socket, int data_port) { IPEndPoint ipEndPoint = new IPEndPoint(IPAddress.Any, data_port); try { // loop until we get an exception eg the socket closed while (true) { byte[] frame = socket.Receive(ref ipEndPoint); // We have an RTP frame. // Fire the DataReceived event with 'frame' Console.WriteLine("Received RTP data on port " + data_port); Rtsp.Messages.RtspChunk currentMessage = new Rtsp.Messages.RtspData(); // aMessage.SourcePort = ?? currentMessage.Data = frame; ((Rtsp.Messages.RtspData)currentMessage).Channel = data_port; OnDataReceived(new Rtsp.RtspChunkEventArgs(currentMessage)); } } catch (ObjectDisposedException) { } catch (SocketException) { } }
/// <summary> /// Clones this instance. /// <remarks>Listner is not cloned</remarks> /// </summary> /// <returns>a clone of this instance</returns> public override object Clone() { RtspData result = new RtspData(); result.Channel = this.Channel; if (this.Data != null) result.Data = this.Data.Clone() as byte[]; result.SourcePort = this.SourcePort; return result; }
/// <summary> /// Clones this instance. /// <remarks>Listner is not cloned</remarks> /// </summary> /// <returns>a clone of this instance</returns> public override object Clone() { RtspData result = new RtspData(); result.Channel = this.Channel; if (this.Data != null) { result.Data = this.Data.Clone() as byte[]; } result.SourcePort = this.SourcePort; return(result); }
public void Clone() { RtspData testObject = new RtspData(); testObject.Channel = 1234; testObject.Data = new byte[] { 45, 63, 36, 42, 65, 00, 99 }; testObject.SourcePort = new RtspListener(Substitute.For<IRtspTransport>()); RtspData cloneObject = testObject.Clone() as RtspData; Assert.IsNotNull(cloneObject); Assert.AreEqual(testObject.Channel, cloneObject.Channel); Assert.AreEqual(testObject.Data, cloneObject.Data); Assert.AreSame(testObject.SourcePort, cloneObject.SourcePort); }
/// <summary> /// Reads one message. /// </summary> /// <param name="commandStream">The Rtsp stream.</param> /// <returns>Message readen</returns> public RtspChunk ReadOneMessage(Stream commandStream) { if (commandStream == null) throw new ArgumentNullException("commandStream"); Contract.EndContractBlock(); ReadingState currentReadingState = ReadingState.NewCommand; // current decode message , create a fake new to permit compile. RtspChunk currentMessage = null; int size = 0; int byteReaden = 0; List<byte> buffer = new List<byte>(256); string oneLine = String.Empty; while (currentReadingState != ReadingState.End) { // if the system is not reading binary data. if (currentReadingState != ReadingState.Data && currentReadingState != ReadingState.MoreInterleavedData) { oneLine = String.Empty; bool needMoreChar = true; // I do not know to make readline blocking while (needMoreChar) { int currentByte = commandStream.ReadByte(); switch (currentByte) { case -1: // the read is blocking, so if we got -1 it is because the client close; currentReadingState = ReadingState.End; needMoreChar = false; break; case '\n': oneLine = ASCIIEncoding.UTF8.GetString(buffer.ToArray()); buffer.Clear(); needMoreChar = false; break; case '\r': // simply ignore this break; case '$': // if first caracter of packet is $ it is an interleaved data packet if (currentReadingState == ReadingState.NewCommand && buffer.Count == 0) { currentReadingState = ReadingState.InterleavedData; needMoreChar = false; } else goto default; break; default: buffer.Add((byte)currentByte); break; } } } switch (currentReadingState) { case ReadingState.NewCommand: currentMessage = RtspMessage.GetRtspMessage(oneLine); currentReadingState = ReadingState.Headers; break; case ReadingState.Headers: string line = oneLine; if (string.IsNullOrEmpty(line)) { currentReadingState = ReadingState.Data; ((RtspMessage)currentMessage).InitialiseDataFromContentLength(); } else { ((RtspMessage)currentMessage).AddHeader(line); } break; case ReadingState.Data: if (currentMessage.Data.Length > 0) { // Read the remaning data byteReaden += commandStream.Read(currentMessage.Data, byteReaden, currentMessage.Data.Length - byteReaden); _logger.Debug(CultureInfo.InvariantCulture, "Readen {0} byte of data", byteReaden); } // if we haven't read all go there again else go to end. if (byteReaden >= currentMessage.Data.Length) currentReadingState = ReadingState.End; break; case ReadingState.InterleavedData: currentMessage = new RtspData(); ((RtspData)currentMessage).Channel = commandStream.ReadByte(); size = (commandStream.ReadByte() << 8) + commandStream.ReadByte(); currentMessage.Data = new byte[size]; currentReadingState = ReadingState.MoreInterleavedData; break; case ReadingState.MoreInterleavedData: // apparently non blocking byteReaden += commandStream.Read(currentMessage.Data, byteReaden, size - byteReaden); if (byteReaden < size) currentReadingState = ReadingState.MoreInterleavedData; else currentReadingState = ReadingState.End; break; default: break; } } if (currentMessage != null) currentMessage.SourcePort = this; return currentMessage; }
/// <summary> /// Begins the send data. /// </summary> /// <param name="aRtspData">A Rtsp data.</param> /// <param name="asyncCallback">The async callback.</param> /// <param name="aState">A state.</param> public IAsyncResult BeginSendData(RtspData aRtspData, AsyncCallback asyncCallback, object state) { if (aRtspData == null) throw new ArgumentNullException("aRtspData"); Contract.EndContractBlock(); return BeginSendData(aRtspData.Channel, aRtspData.Data, asyncCallback, state); }
int rtp_count = 0; // used for statistics // RTP packet (or RTCP packet) has been received. private void Rtp_DataReceived(object sender, Rtsp.RtspChunkEventArgs e) { Rtsp.Messages.RtspData data_received = e.Message as Rtsp.Messages.RtspData; // Check which channel the Data was received on. // eg the Video Channel, the Video Control Channel (RTCP) // In the future would also check the Audio Channel and Audio Control Channel if (data_received.Channel == video_rtcp_channel) { Console.WriteLine("Received a RTCP message on channel " + data_received.Channel); return; } if (data_received.Channel == video_data_channel) { // Received some Video Data on the correct channel. // RTP Packet Header // 0 - Version, P, X, CC, M, PT and Sequence Number //32 - Timestamp //64 - SSRC //96 - CSRCs (optional) //nn - Extension ID and Length //nn - Extension header int rtp_version = (e.Message.Data[0] >> 6); int rtp_padding = (e.Message.Data[0] >> 5) & 0x01; int rtp_extension = (e.Message.Data[0] >> 4) & 0x01; int rtp_csrc_count = (e.Message.Data[0] >> 0) & 0x0F; int rtp_marker = (e.Message.Data[1] >> 7) & 0x01; int rtp_payload_type = (e.Message.Data[1] >> 0) & 0x7F; uint rtp_sequence_number = ((uint)e.Message.Data[2] << 8) + (uint)(e.Message.Data[3]); uint rtp_timestamp = ((uint)e.Message.Data[4] << 24) + (uint)(e.Message.Data[5] << 16) + (uint)(e.Message.Data[6] << 8) + (uint)(e.Message.Data[7]); uint rtp_ssrc = ((uint)e.Message.Data[8] << 24) + (uint)(e.Message.Data[9] << 16) + (uint)(e.Message.Data[10] << 8) + (uint)(e.Message.Data[11]); int rtp_payload_start = 4 // V,P,M,SEQ + 4 // time stamp + 4 // ssrc + (4 * rtp_csrc_count); // zero or more csrcs uint rtp_extension_id = 0; uint rtp_extension_size = 0; if (rtp_extension == 1) { rtp_extension_id = ((uint)e.Message.Data[rtp_payload_start + 0] << 8) + (uint)(e.Message.Data[rtp_payload_start + 1] << 0); rtp_extension_size = ((uint)e.Message.Data[rtp_payload_start + 2] << 8) + (uint)(e.Message.Data[rtp_payload_start + 3] << 0) * 4; // units of extension_size is 4-bytes rtp_payload_start += 4 + (int)rtp_extension_size; // extension header and extension payload } Console.WriteLine("RTP Data" + " V=" + rtp_version + " P=" + rtp_padding + " X=" + rtp_extension + " CC=" + rtp_csrc_count + " M=" + rtp_marker + " PT=" + rtp_payload_type + " Seq=" + rtp_sequence_number + " Time (MS)=" + rtp_timestamp / 90 // convert from 90kHZ clock to ms + " SSRC=" + rtp_ssrc + " Size=" + e.Message.Data.Length); String msg = "RTP Data " + rtp_count++ + " V=" + rtp_version + " P=" + rtp_padding + " X=" + rtp_extension + " CC=" + rtp_csrc_count + " M=" + rtp_marker + " PT=" + rtp_payload_type // + " Seq=" + rtp_sequence_number // + " Time=" + rtp_timestamp // + " SSRC=" + rtp_ssrc + " Size=" + e.Message.Data.Length; if (fs2 != null) { fs2.WriteLine(msg); } if (fs2 != null) { fs2.Flush(); } // Check the payload type in the RTP packet matches the Payload Type value from the SDP if (rtp_payload_type != video_payload) { Console.WriteLine("Ignoring this RTP payload"); return; // ignore this data } if (rtp_payload_type >= 96 && rtp_payload_type <= 127 && video_codec.Equals("H264")) { // H264 RTP Packet // If rtp_marker is '1' then this is the final transmission for this packet. // If rtp_marker is '0' we need to accumulate data with the same timestamp // ToDo - Check Timestamp // Add the RTP packet to the tempoary_rtp list until we have a complete 'Frame' byte[] rtp_payload = new byte[e.Message.Data.Length - rtp_payload_start]; // payload with RTP header removed System.Array.Copy(e.Message.Data, rtp_payload_start, rtp_payload, 0, rtp_payload.Length); // copy payload List <byte[]> nal_units = h264Payload.Process_H264_RTP_Packet(rtp_payload, rtp_marker); // this will cache the Packets until there is a Frame if (nal_units == null) { // we have not passed in enough RTP packets to make a Frame of video } else { // we have a frame of NAL Units. Write them to the file Output_NAL(nal_units); } } else if (rtp_payload_type == 26) { Console.WriteLine("No parser for JPEG RTP packets"); } else { Console.WriteLine("No parser for this RTP payload"); } } }
int rtp_count = 0; // used for statistics // RTP packet (or RTCP packet) has been received. public void Rtp_DataReceived(object sender, Rtsp.RtspChunkEventArgs e) { Rtsp.Messages.RtspData data_received = e.Message as Rtsp.Messages.RtspData; // Check which channel the Data was received on. // eg the Video Channel, the Video Control Channel (RTCP) // the Audio Channel or the Audio Control Channel (RTCP) if (data_received.Channel == video_rtcp_channel || data_received.Channel == audio_rtcp_channel) { Console.WriteLine("Received a RTCP message on channel " + data_received.Channel); // RTCP Packet // - Version, Padding and Receiver Report Count // - Packet Type // - Length // - SSRC // - payload // There can be multiple RTCP packets transmitted together. Loop ever each one long packetIndex = 0; while (packetIndex < e.Message.Data.Length) { int rtcp_version = (e.Message.Data[packetIndex + 0] >> 6); int rtcp_padding = (e.Message.Data[packetIndex + 0] >> 5) & 0x01; int rtcp_reception_report_count = (e.Message.Data[packetIndex + 0] & 0x1F); byte rtcp_packet_type = e.Message.Data[packetIndex + 1]; // Values from 200 to 207 uint rtcp_length = ((uint)e.Message.Data[packetIndex + 2] << 8) + (uint)(e.Message.Data[packetIndex + 3]); // number of 32 bit words uint rtcp_ssrc = ((uint)e.Message.Data[packetIndex + 4] << 24) + (uint)(e.Message.Data[packetIndex + 5] << 16) + (uint)(e.Message.Data[packetIndex + 6] << 8) + (uint)(e.Message.Data[packetIndex + 7]); // 200 = SR = Sender Report // 201 = RR = Receiver Report // 202 = SDES = Source Description // 203 = Bye = Goodbye // 204 = APP = Application Specific Method // 207 = XR = Extended Reports Console.WriteLine("RTCP Data. PacketType=" + rtcp_packet_type + " SSRC=" + rtcp_ssrc); if (rtcp_packet_type == 200) { // Send a Receiver Report try { byte[] rtcp_receiver_report = new byte[8]; int version = 2; int paddingBit = 0; int reportCount = 0; // an empty report int packetType = 201; // Receiver Report int length = (rtcp_receiver_report.Length / 4) - 1; // num 32 bit words minus 1 rtcp_receiver_report[0] = (byte)((version << 6) + (paddingBit << 5) + reportCount); rtcp_receiver_report[1] = (byte)(packetType); rtcp_receiver_report[2] = (byte)((length >> 8) & 0xFF); rtcp_receiver_report[3] = (byte)((length >> 0) & 0XFF); rtcp_receiver_report[4] = (byte)((ssrc >> 24) & 0xFF); rtcp_receiver_report[5] = (byte)((ssrc >> 16) & 0xFF); rtcp_receiver_report[6] = (byte)((ssrc >> 8) & 0xFF); rtcp_receiver_report[7] = (byte)((ssrc >> 0) & 0xFF); if (rtp_transport == RTP_TRANSPORT.TCP) { // Send it over via the RTSP connection rtsp_client.SendData(video_rtcp_channel, rtcp_receiver_report); } if (rtp_transport == RTP_TRANSPORT.UDP || rtp_transport == RTP_TRANSPORT.MULTICAST) { // Send it via a UDP Packet Console.WriteLine("TODO - Need to implement RTCP over UDP"); } } catch { Console.WriteLine("Error writing RTCP packet"); } } packetIndex = packetIndex + ((rtcp_length + 1) * 4); } return; } if (data_received.Channel == video_data_channel || data_received.Channel == audio_data_channel) { // Received some Video or Audio Data on the correct channel. // RTP Packet Header // 0 - Version, P, X, CC, M, PT and Sequence Number //32 - Timestamp //64 - SSRC //96 - CSRCs (optional) //nn - Extension ID and Length //nn - Extension header int rtp_version = (e.Message.Data[0] >> 6); int rtp_padding = (e.Message.Data[0] >> 5) & 0x01; int rtp_extension = (e.Message.Data[0] >> 4) & 0x01; int rtp_csrc_count = (e.Message.Data[0] >> 0) & 0x0F; int rtp_marker = (e.Message.Data[1] >> 7) & 0x01; int rtp_payload_type = (e.Message.Data[1] >> 0) & 0x7F; uint rtp_sequence_number = ((uint)e.Message.Data[2] << 8) + (uint)(e.Message.Data[3]); uint rtp_timestamp = ((uint)e.Message.Data[4] << 24) + (uint)(e.Message.Data[5] << 16) + (uint)(e.Message.Data[6] << 8) + (uint)(e.Message.Data[7]); uint rtp_ssrc = ((uint)e.Message.Data[8] << 24) + (uint)(e.Message.Data[9] << 16) + (uint)(e.Message.Data[10] << 8) + (uint)(e.Message.Data[11]); int rtp_payload_start = 4 // V,P,M,SEQ + 4 // time stamp + 4 // ssrc + (4 * rtp_csrc_count); // zero or more csrcs uint rtp_extension_id = 0; uint rtp_extension_size = 0; if (rtp_extension == 1) { rtp_extension_id = ((uint)e.Message.Data[rtp_payload_start + 0] << 8) + (uint)(e.Message.Data[rtp_payload_start + 1] << 0); rtp_extension_size = ((uint)e.Message.Data[rtp_payload_start + 2] << 8) + (uint)(e.Message.Data[rtp_payload_start + 3] << 0) * 4; // units of extension_size is 4-bytes rtp_payload_start += 4 + (int)rtp_extension_size; // extension header and extension payload } Console.WriteLine("RTP Data" + " V=" + rtp_version + " P=" + rtp_padding + " X=" + rtp_extension + " CC=" + rtp_csrc_count + " M=" + rtp_marker + " PT=" + rtp_payload_type + " Seq=" + rtp_sequence_number + " Time (MS)=" + rtp_timestamp / 90 // convert from 90kHZ clock to ms + " SSRC=" + rtp_ssrc + " Size=" + e.Message.Data.Length); // Check the payload type in the RTP packet matches the Payload Type value from the SDP if (data_received.Channel == video_data_channel && rtp_payload_type != video_payload) { Console.WriteLine("Ignoring this Video RTP payload"); return; // ignore this data } // Check the payload type in the RTP packet matches the Payload Type value from the SDP else if (data_received.Channel == audio_data_channel && rtp_payload_type != audio_payload) { Console.WriteLine("Ignoring this Audio RTP payload"); return; // ignore this data } else if (data_received.Channel == video_data_channel && rtp_payload_type >= 96 && rtp_payload_type <= 127 && video_codec.Equals("H264")) { // H264 RTP Packet // If rtp_marker is '1' then this is the final transmission for this packet. // If rtp_marker is '0' we need to accumulate data with the same timestamp // ToDo - Check Timestamp // Add the RTP packet to the tempoary_rtp list until we have a complete 'Frame' byte[] rtp_payload = new byte[e.Message.Data.Length - rtp_payload_start]; // payload with RTP header removed System.Array.Copy(e.Message.Data, rtp_payload_start, rtp_payload, 0, rtp_payload.Length); // copy payload List <byte[]> nal_units = h264Payload.Process_H264_RTP_Packet(rtp_payload, rtp_marker); // this will cache the Packets until there is a Frame if (nal_units == null) { // we have not passed in enough RTP packets to make a Frame of video } else { // we have a frame of NAL Units. Write them to the file if (Received_NALs != null) { Received_NALs(nal_units); } } } else if (data_received.Channel == audio_data_channel && (rtp_payload_type == 0 || rtp_payload_type == 8 || audio_codec.Equals("PCMA") || audio_codec.Equals("PCMU"))) { // G711 PCMA or G711 PCMU byte[] rtp_payload = new byte[e.Message.Data.Length - rtp_payload_start]; // payload with RTP header removed System.Array.Copy(e.Message.Data, rtp_payload_start, rtp_payload, 0, rtp_payload.Length); // copy payload List <byte[]> audio_frames = g711Payload.Process_G711_RTP_Packet(rtp_payload, rtp_marker); if (audio_frames == null) { // some error } else { // Write the audio frames to the file if (Received_G711 != null) { Received_G711(audio_codec, audio_frames); } } } else if (data_received.Channel == video_data_channel && rtp_payload_type == 26) { Console.WriteLine("No parser has been written for JPEG RTP packets. Please help write one"); return; // ignore this data } else { Console.WriteLine("No parser for RTP payload " + rtp_payload_type); } } }
int rtp_count = 0; // used for statistics // RTP packet (or RTCP packet) has been received. public void Rtp_DataReceived(object sender, Rtsp.RtspChunkEventArgs e) { Rtsp.Messages.RtspData data_received = e.Message as Rtsp.Messages.RtspData; // Check which channel the Data was received on. // eg the Video Channel, the Video Control Channel (RTCP) // In the future would also check the Audio Channel and Audio Control Channel if (data_received.Channel == video_rtcp_channel) { Console.WriteLine("Received a RTCP message on channel " + data_received.Channel); return; } if (data_received.Channel == video_data_channel) { // Received some Video Data on the correct channel. // RTP Packet Header // 0 - Version, P, X, CC, M, PT and Sequence Number //32 - Timestamp //64 - SSRC //96 - CSRCs (optional) //nn - Extension ID and Length //nn - Extension header int rtp_version = (e.Message.Data[0] >> 6); int rtp_padding = (e.Message.Data[0] >> 5) & 0x01; int rtp_extension = (e.Message.Data[0] >> 4) & 0x01; int rtp_csrc_count = (e.Message.Data[0] >> 0) & 0x0F; int rtp_marker = (e.Message.Data[1] >> 7) & 0x01; int rtp_payload_type = (e.Message.Data[1] >> 0) & 0x7F; uint rtp_sequence_number = ((uint)e.Message.Data[2] << 8) + (uint)(e.Message.Data[3]); uint rtp_timestamp = ((uint)e.Message.Data[4] << 24) + (uint)(e.Message.Data[5] << 16) + (uint)(e.Message.Data[6] << 8) + (uint)(e.Message.Data[7]); uint rtp_ssrc = ((uint)e.Message.Data[8] << 24) + (uint)(e.Message.Data[9] << 16) + (uint)(e.Message.Data[10] << 8) + (uint)(e.Message.Data[11]); int rtp_payload_start = 4 // V,P,M,SEQ + 4 // time stamp + 4 // ssrc + (4 * rtp_csrc_count); // zero or more csrcs uint rtp_extension_id = 0; uint rtp_extension_size = 0; if (rtp_extension == 1) { rtp_extension_id = ((uint)e.Message.Data[rtp_payload_start + 0] << 8) + (uint)(e.Message.Data[rtp_payload_start + 1] << 0); rtp_extension_size = ((uint)e.Message.Data[rtp_payload_start + 2] << 8) + (uint)(e.Message.Data[rtp_payload_start + 3] << 0) * 4; // units of extension_size is 4-bytes rtp_payload_start += 4 + (int)rtp_extension_size; // extension header and extension payload } Console.WriteLine("RTP Data" + " V=" + rtp_version + " P=" + rtp_padding + " X=" + rtp_extension + " CC=" + rtp_csrc_count + " M=" + rtp_marker + " PT=" + rtp_payload_type + " Seq=" + rtp_sequence_number + " Time (MS)=" + rtp_timestamp / 90 // convert from 90kHZ clock to ms + " SSRC=" + rtp_ssrc + " Size=" + e.Message.Data.Length); String msg = "RTP Data " + rtp_count++ + " V=" + rtp_version + " P=" + rtp_padding + " X=" + rtp_extension + " CC=" + rtp_csrc_count + " M=" + rtp_marker + " PT=" + rtp_payload_type // + " Seq=" + rtp_sequence_number // + " Time=" + rtp_timestamp // + " SSRC=" + rtp_ssrc + " Size=" + e.Message.Data.Length; fs2.WriteLine(msg); fs2.Flush(); // Check the payload type in the RTP packet matches the Payload Type value from the SDP if (rtp_payload_type != video_payload) { Console.WriteLine("Ignoring this RTP payload"); return; // ignore this data } // If rtp_marker is '1' then this is the final transmission for this packet. // If rtp_marker is '0' we need to accumulate data with the same timestamp // ToDo - Check Timestamp // ToDo - Could avoid a copy if there is only one RTP frame for the data (temp list is zero) // Add the RTP packet to the tempoary_rtp list byte[] rtp_payload = new byte[e.Message.Data.Length - rtp_payload_start]; // payload with RTP header removed System.Array.Copy(e.Message.Data, rtp_payload_start, rtp_payload, 0, rtp_payload.Length); // copy payload temporary_rtp_payloads.Add(rtp_payload); if (rtp_marker == 1) { // End Marker is set. Process the RTP frame Process_RTP_Frame(temporary_rtp_payloads); temporary_rtp_payloads.Clear(); } } }
public void SendDataTooLarge() { const int dataLenght = 0x10001; MemoryStream stream = new MemoryStream(); _mockTransport.GetStream().Returns(stream); // Setup test object. RtspListener testedListener = new RtspListener(_mockTransport); testedListener.MessageReceived += new EventHandler<RtspChunkEventArgs>(MessageReceived); testedListener.DataReceived += new EventHandler<RtspChunkEventArgs>(DataReceived); RtspData data = new RtspData(); data.Channel = 12; data.Data = new byte[dataLenght]; ActualValueDelegate<object> test = () => testedListener.BeginSendData(data,null,null); Assert.That(test, Throws.InstanceOf<ArgumentException>()); }
public void SendData() { const int dataLenght = 45; MemoryStream stream = new MemoryStream(); _mockTransport.GetStream().Returns(stream); // Setup test object. RtspListener testedListener = new RtspListener(_mockTransport); testedListener.MessageReceived += new EventHandler<RtspChunkEventArgs>(MessageReceived); testedListener.DataReceived += new EventHandler<RtspChunkEventArgs>(DataReceived); RtspData data = new RtspData(); data.Channel = 12; data.Data = new byte[dataLenght]; for (int i = 0; i < dataLenght; i++) { data.Data[i] = (byte)i; } // Run var asyncResult = testedListener.BeginSendData(data, null, null); testedListener.EndSendData(asyncResult); var result = stream.GetBuffer(); int index = 0; Assert.That(result[index++], Is.EqualTo((byte)'$')); Assert.That(result[index++], Is.EqualTo(data.Channel)); Assert.That(result[index++], Is.EqualTo((dataLenght & 0xFF00) >> 8)); Assert.That(result[index++], Is.EqualTo(dataLenght & 0x00FF)); for (int i = 0; i < dataLenght; i++) { Assert.That(result[index++], Is.EqualTo(data.Data[i])); } }