public void SendVP8Frame(byte[] frame, int payloadType)
{
try
{
if (_closed)
{
logger.Warn("SendVP8Frame cannot be called on a closed session.");
}
else if (_rtpSocketError != SocketError.Success)
{
logger.Warn("SendVP8Frame was called for an RTP socket in an error state of " + _rtpSocketError + ".");
}
else if (_remoteEndPoint == null)
{
// logger.Warn("SendVP8Frame frame not sent as remote end point is not yet set.");
}
else
{
//RecalculateTimestampStep();
//_timestamp += _timestampStep;
_timestamp = DateTimeToNptTimestamp90K(DateTime.Now);
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) };
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 (RtpProtect != null)
{
rtpBytes = RtpProtect(rtpBytes);
}
//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);
//SocketAsyncEventArgs socketSendArgs = new SocketAsyncEventArgs();
//socketSendArgs.SetBuffer(rtpBytes, 0, rtpBytes.Length);
//socketSendArgs.RemoteEndPoint = _remoteEndPoint;
//_rtpSocket.SendToAsync(socketSendArgs);
_rtpSocket.BeginSendTo(rtpBytes, 0, rtpBytes.Length, SocketFlags.None, _remoteEndPoint, null, null);
//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 (!_closed)
{
logger.Warn("Exception RTSPSession.SendVP8Frame attempting to send to the RTP socket at " + _remoteEndPoint + ". " + excp);
if (OnRTPSocketDisconnected != null)
{
OnRTPSocketDisconnected(_sessionID);
}
}
}
}