private static void SendRTPFromVP8FramesFile(string file) { try { StreamReader sr = new StreamReader(file); List<string> samples = new List<string>(); while (!sr.EndOfStream) { string sample = sr.ReadLine(); samples.Add(sample); //Console.WriteLine(sample); //string[] sampleFields = sample.Split(','); //RTPVP8Header frameVP8Header = RTPVP8Header.GetVP8Header(Convert.FromBase64String(sampleFields[0])); //byte[] rtpPaylaod = Convert.FromBase64String(sampleFields[1]); //Console.WriteLine((frameVP8Header.IsKeyFrame) ? "K" : "." + " " + frameVP8Header.FirstPartitionSize + " " + rtpPaylaod.Length + "."); } sr.Close(); logger.Debug(samples.Count + " encoded samples loaded."); //_newRTPReceiverSRTP = new SRTPManaged(Convert.FromBase64String(_sourceSRTPKey)); //_newRTPReceiverSRTP = new SRTPManaged(); int sampleIndex = 0; while (true) { if (_webRTCClients.Count != 0) { var sampleItem = samples[sampleIndex]; string[] sampleFields = sampleItem.Split(','); RTPVP8Header frameVP8Header = RTPVP8Header.GetVP8Header(Convert.FromBase64String(sampleFields[0])); byte[] sample = Convert.FromBase64String(sampleFields[1]); if (frameVP8Header.IsKeyFrame) { Console.WriteLine("Key frame."); } lock (_webRTCClients) { foreach (var client in _webRTCClients.Where(x => x.STUNExchangeComplete)) { try { if (client.LastTimestamp == 0) { client.LastTimestamp = RTSPSession.DateTimeToNptTimestamp32(DateTime.Now); } for (int index = 0; index * RTP_MAX_PAYLOAD < sample.Length; index++) { int offset = (index == 0) ? 0 : (index * RTP_MAX_PAYLOAD); int payloadLength = (offset + RTP_MAX_PAYLOAD < sample.Length) ? RTP_MAX_PAYLOAD : sample.Length - offset; RTPVP8Header packetVP8Header = new RTPVP8Header() { ExtendedControlBitsPresent = true, IsPictureIDPresent = true, ShowFrame = true, }; if (index == 0) { packetVP8Header.StartOfVP8Partition = true; //packetVP8Header.FirstPartitionSize = frameVP8Header.FirstPartitionSize; packetVP8Header.IsKeyFrame = frameVP8Header.IsKeyFrame; packetVP8Header.PictureID = (frameVP8Header.IsKeyFrame) ? (byte)0x00 : frameVP8Header.PictureID; } byte[] vp8HeaderBytes = packetVP8Header.GetBytes(); RTPPacket rtpPacket = new RTPPacket(packetVP8Header.Length + payloadLength + SRTP_AUTH_KEY_LENGTH); rtpPacket.Header.SyncSource = client.SSRC; rtpPacket.Header.SequenceNumber = client.SequenceNumber++; rtpPacket.Header.Timestamp = client.LastTimestamp; rtpPacket.Header.MarkerBit = ((offset + payloadLength) >= sample.Length) ? 1 : 0; rtpPacket.Header.PayloadType = 100; Buffer.BlockCopy(vp8HeaderBytes, 0, rtpPacket.Payload, 0, packetVP8Header.Length); Buffer.BlockCopy(sample, offset, rtpPacket.Payload, packetVP8Header.Length, payloadLength); var rtpBuffer = rtpPacket.GetBytes(); _webRTCReceiverClient.Send(rtpBuffer, rtpBuffer.Length - SRTP_AUTH_KEY_LENGTH, _wiresharpEP); int rtperr = client.SrtpContext.ProtectRTP(rtpBuffer, rtpBuffer.Length - SRTP_AUTH_KEY_LENGTH); if (rtperr != 0) { logger.Debug("New RTP packet protect result " + rtperr + "."); } logger.Debug("Sending RTP " + sample.Length + " bytes to " + client.SocketAddress + ", timestamp " + client.LastTimestamp + ", marker " + rtpPacket.Header.MarkerBit + "."); _webRTCReceiverClient.Send(rtpBuffer, rtpBuffer.Length, client.SocketAddress); } client.LastTimestamp += TIMESTAMP_SPACING; } catch (Exception sendExcp) { logger.Error("SendRTPFromVP8FramesFile exception sending to " + client.SocketAddress + ". " + sendExcp.Message); } } } sampleIndex++; if (sampleIndex >= samples.Count - 1) { sampleIndex = 0; } Thread.Sleep(30); } } } catch (Exception excp) { Console.WriteLine("Exception SendRTPFromVP8FramesFile. " + excp); } }