Luski.Net/Luski.net/Sound/RTPPacket.cs

140 lines
4.8 KiB
C#
Raw Normal View History

2023-01-01 22:50:39 -05:00
using System;
using System.Linq;
namespace Luski.net.Sound
{
internal class RTPPacket
{
internal RTPPacket()
{
}
internal RTPPacket(byte[] data)
{
Parse(data);
}
internal static int MinHeaderLength = 12;
internal int HeaderLength = MinHeaderLength;
internal int Version = 0;
internal bool Padding = false;
internal bool Extension = false;
internal int CSRCCount = 0;
internal bool Marker = false;
internal int PayloadType = 0;
internal ushort SequenceNumber = 0;
internal uint Timestamp = 0;
internal uint SourceId = 0;
internal byte[]? Data;
internal ushort ExtensionHeaderId = 0;
internal ushort ExtensionLengthAsCount = 0;
internal int ExtensionLengthInBytes = 0;
private void Parse(byte[] data)
{
if (data.Length >= MinHeaderLength)
{
Version = ValueFromByte(data[0], 6, 2);
Padding = Convert.ToBoolean(ValueFromByte(data[0], 5, 1));
Extension = Convert.ToBoolean(ValueFromByte(data[0], 4, 1));
CSRCCount = ValueFromByte(data[0], 0, 4);
Marker = Convert.ToBoolean(ValueFromByte(data[1], 7, 1));
PayloadType = ValueFromByte(data[1], 0, 7);
HeaderLength = MinHeaderLength + (CSRCCount * 4);
//Sequence Nummer
byte[] seqNum = new byte[2];
seqNum[0] = data[3];
seqNum[1] = data[2];
SequenceNumber = BitConverter.ToUInt16(seqNum, 0);
//TimeStamp
byte[] timeStmp = new byte[4];
timeStmp[0] = data[7];
timeStmp[1] = data[6];
timeStmp[2] = data[5];
timeStmp[3] = data[4];
Timestamp = BitConverter.ToUInt32(timeStmp, 0);
//SourceId
byte[] srcId = new byte[4];
srcId[0] = data[8];
srcId[1] = data[9];
srcId[2] = data[10];
srcId[3] = data[11];
SourceId = BitConverter.ToUInt32(srcId, 0);
if (Extension)
{
byte[] extHeaderId = new byte[2];
extHeaderId[1] = data[HeaderLength + 0];
extHeaderId[0] = data[HeaderLength + 1];
ExtensionHeaderId = BitConverter.ToUInt16(extHeaderId, 0);
byte[] extHeaderLength16 = new byte[2];
extHeaderLength16[1] = data[HeaderLength + 2];
extHeaderLength16[0] = data[HeaderLength + 3];
ExtensionLengthAsCount = BitConverter.ToUInt16(extHeaderLength16.ToArray(), 0);
ExtensionLengthInBytes = ExtensionLengthAsCount * 4;
HeaderLength += ExtensionLengthInBytes + 4;
}
Data = new byte[data.Length - HeaderLength];
Array.Copy(data, HeaderLength, Data, 0, data.Length - HeaderLength);
}
}
private static int ValueFromByte(byte value, int startPos, int length)
{
byte mask = 0;
for (int i = 0; i < length; i++)
{
mask = (byte)(mask | 0x1 << startPos + i);
}
byte result = (byte)((value & mask) >> startPos);
return Convert.ToInt32(result);
}
internal byte[] ToBytes()
{
byte[] bytes = new byte[HeaderLength + Data.Length];
//Byte 0
bytes[0] = (byte)(Version << 6);
bytes[0] |= (byte)(Convert.ToInt32(Padding) << 5);
bytes[0] |= (byte)(Convert.ToInt32(Extension) << 4);
bytes[0] |= (byte)(Convert.ToInt32(CSRCCount));
//Byte 1
bytes[1] = (byte)(Convert.ToInt32(Marker) << 7);
bytes[1] |= (byte)(Convert.ToInt32(PayloadType));
//Byte 2 + 3
byte[] bytesSequenceNumber = BitConverter.GetBytes(SequenceNumber);
bytes[2] = bytesSequenceNumber[1];
bytes[3] = bytesSequenceNumber[0];
//Byte 4 bis 7
byte[] bytesTimeStamp = BitConverter.GetBytes(Timestamp);
bytes[4] = bytesTimeStamp[3];
bytes[5] = bytesTimeStamp[2];
bytes[6] = bytesTimeStamp[1];
bytes[7] = bytesTimeStamp[0];
//Byte 8 bis 11
byte[] bytesSourceId = BitConverter.GetBytes(SourceId);
bytes[8] = bytesSourceId[3];
bytes[9] = bytesSourceId[2];
bytes[10] = bytesSourceId[1];
bytes[11] = bytesSourceId[0];
Array.Copy(Data, 0, bytes, HeaderLength, Data.Length);
return bytes;
}
}
}