public void SendVP8Frame(byte[] frame, uint frameSpacing, int payloadType)
{
try
{
if (_isClosed)
{
logger.Warn("SendVP8Frame cannot be called on a closed RTP channel.");
}
else if (_rtpSocketError != SocketError.Success)
{
logger.Warn("SendVP8Frame was called for an RTP socket in an error state of " + _rtpSocketError + ".");
}
else
{
_timestamp = (_timestamp == 0) ? DateTimeToNptTimestamp32(DateTime.Now) : (_timestamp + frameSpacing) % UInt32.MaxValue;
//System.Diagnostics.Debug.WriteLine("Sending " + frame.Length + " encoded bytes to client, timestamp " + _timestamp + ", starting sequence number " + _sequenceNumber + ".");
for (int index = 0; index * RTP_MAX_PAYLOAD < frame.Length; index++)
{
//byte[] vp8HeaderBytes = (index == 0) ? new byte[VP8_RTP_HEADER_LENGTH] { 0x90, 0x80, (byte)(_sequenceNumber % 128) } : new byte[VP8_RTP_HEADER_LENGTH] { 0x80, 0x80, (byte)(_sequenceNumber % 128) };
byte[] vp8HeaderBytes = (index == 0) ? new byte[VP8_RTP_HEADER_LENGTH] { 0x10 } : new byte[VP8_RTP_HEADER_LENGTH] { 0x00 };
int offset = index * RTP_MAX_PAYLOAD;
int payloadLength = ((index + 1) * RTP_MAX_PAYLOAD < frame.Length) ? RTP_MAX_PAYLOAD : frame.Length - index * RTP_MAX_PAYLOAD;
// RTPPacket rtpPacket = new RTPPacket(payloadLength + VP8_RTP_HEADER_LENGTH + ((_srtp != null) ? SRTP_SIGNATURE_LENGTH : 0));
RTPPacket rtpPacket = new RTPPacket(payloadLength + VP8_RTP_HEADER_LENGTH);
rtpPacket.Header.SyncSource = _syncSource;
rtpPacket.Header.SequenceNumber = _sequenceNumber++;
rtpPacket.Header.Timestamp = _timestamp;
rtpPacket.Header.MarkerBit = (offset + payloadLength >= frame.Length) ? 1 : 0;
rtpPacket.Header.PayloadType = payloadType;
Buffer.BlockCopy(vp8HeaderBytes, 0, rtpPacket.Payload, 0, vp8HeaderBytes.Length);
Buffer.BlockCopy(frame, offset, rtpPacket.Payload, vp8HeaderBytes.Length, payloadLength);
byte[] rtpBytes = rtpPacket.GetBytes();
//if (_srtp != null)
//{
// int rtperr = _srtp.ProtectRTP(rtpBytes, rtpBytes.Length - SRTP_SIGNATURE_LENGTH);
// if (rtperr != 0)
// {
// logger.Warn("An error was returned attempting to sign an SRTP packet for " + _remoteEndPoint + ", error code " + rtperr + ".");
// }
//}
//System.Diagnostics.Debug.WriteLine(" offset " + (index * RTP_MAX_PAYLOAD) + ", payload length " + payloadLength + ", sequence number " + rtpPacket.Header.SequenceNumber + ", marker " + rtpPacket.Header .MarkerBit + ".");
//Stopwatch sw = new Stopwatch();
//sw.Start();
_rtpSocket.SendTo(rtpBytes, rtpBytes.Length, SocketFlags.None, _remoteEndPoint);
//sw.Stop();
//if (sw.ElapsedMilliseconds > 15)
//{
// logger.Warn(" SendVP8Frame offset " + offset + ", payload length " + payloadLength + ", sequence number " + rtpPacket.Header.SequenceNumber + ", marker " + rtpPacket.Header.MarkerBit + ", took " + sw.ElapsedMilliseconds + "ms.");
//}
}
}
}
catch (Exception excp)
{
if (!_isClosed)
{
logger.Warn("Exception RTPChannel.SendVP8Frame attempting to send to the RTP socket at " + _remoteEndPoint + ". " + excp);
OnRTPSocketDisconnected?.Invoke();
}
}
}