/// <summary> /// RTP数据包类 /// </summary> public class RTPPacket { /// <summary> /// 获取数据包头信息V /// </summary> public int V { get; private set; } /// <summary> /// 获取数据包头信息P /// </summary> public bool P { get; private set; } /// <summary> /// 获取数据包头信息X /// </summary> public bool X { get; private set; } /// <summary> /// 获取数据包头信息CC /// </summary> public int CC { get; private set; } /// <summary> /// 获取数据包头信息M /// </summary> public bool M { get; private set; } /// <summary> /// 获取数据包头信息PT /// </summary> public int PT { get; private set; } /// <summary> /// 获取数据包头信息SequenceNumber /// </summary> public ushort SequenceNumber { get; private set; } /// <summary> /// 获取数据包头信息Timestamp /// </summary> public uint Timestamp { get; private set; } /// <summary> /// 获取数据包头信息SSRC /// </summary> public uint SSRC { get; private set; } /// <summary> /// 获取数据包头信息CSRC /// </summary> public List<uint> CSRC { get; private set; } /// <summary> /// 获取数据包有效数据 /// </summary> public byte[] Payload { get; private set; } /// <summary> /// 获取数据包有效数据长度 /// </summary> public uint PayloadSize { get; private set; } /// <summary> /// 获取数据包头信息长度 /// </summary> public uint HeaderSize { get; private set; } /// <summary> /// 构造RTP数据包类 /// </summary> /// <param name="buffer">RTP数据包数据</param> public RTPPacket(byte[] buffer) { // 判断数据长度是否有效 if (buffer.LongLength > 12) { // 根据RTP数据包头信息解析数据 byte item = buffer[0]; V = item >> 6; P = Convert.ToBoolean((item >> 5) & 1); X = Convert.ToBoolean((item >> 4) & 1); CC = item & 15; item = buffer[1]; M = Convert.ToBoolean((item >> 7) & 1); PT = item & 127; SequenceNumber = ReadUInt16(buffer[2], buffer[3]); Timestamp = ReadUInt32(buffer[4], buffer[5], buffer[6], buffer[7]); SSRC = ReadUInt32(buffer[8], buffer[9], buffer[10], buffer[11]); int index = 12; CSRC = new List<uint>(); for (var i = 0; i < CC; i++) { index = i * 4 + index; uint csrc = ReadUInt32(buffer[index], buffer[index + 1], buffer[index + 2], buffer[index + 3]); CSRC.Add(csrc); } index = CC * 4 + index; if (X) { index++; index += buffer[index]; } Payload = buffer.Skip(index).ToArray(); PayloadSize = (uint)Payload.LongLength; HeaderSize = (uint)(CSRC.Count * 4 + 12); } } /// <summary> /// 构造RTP数据包类 /// </summary> /// <param name="packet">RTP数据包</param> public RTPPacket(RTPPacket packet) { // 复制RTP数据包成员 V = packet.V; P = packet.P; X = packet.X; CC = packet.CC; M = packet.M; PT = packet.PT; SequenceNumber = packet.SequenceNumber; Timestamp = packet.Timestamp; SSRC = packet.SSRC; CSRC = packet.CSRC; Payload = packet.Payload; PayloadSize = packet.PayloadSize; HeaderSize = packet.HeaderSize; Debug.WriteLine(ToString()); } /// <summary> /// 根据四个字节读取UInt32数据 /// </summary> /// <param name="byte1">字节1</param> /// <param name="byte2">字节2</param> /// <param name="byte3">字节3</param> /// <param name="byte4">字节4</param> /// <returns>返回UInt32数据</returns> private uint ReadUInt32(byte byte1, byte byte2, byte byte3, byte byte4) { uint uint1 = (uint)(byte1 << 24); uint uint2 = (uint)(byte2 << 16); uint uint3 = (uint)(byte3 << 8); uint uint4 = (uint)byte4; return (uint)(((uint1 | uint2) | uint3) | uint4); } /// <summary> /// 根据两个字节读取UInt16数据 /// </summary> /// <param name="byte1">字节1</param> /// <param name="byte2">字节2</param> /// <returns>返回UInt16数据</returns> private ushort ReadUInt16(byte byte1, byte byte2) { ushort ushort1 = (ushort)(byte1 << 8); ushort ushort2 = (ushort)byte2; return (ushort)(ushort1 | ushort2); } /// <summary> /// 重载获取字符串方法 /// </summary> /// <returns>返回RTP数据包对象的字符串表现形式</returns> public override string ToString() { StringBuilder builder = new StringBuilder(); builder.Append(string.Format("V: {0}, ", V)); builder.Append(string.Format("P: {0}, ", P)); builder.Append(string.Format("X: {0}, ", X)); builder.Append(string.Format("CC: {0}, ", CC)); builder.Append(string.Format("M: {0}, ", M)); builder.Append(string.Format("PT: {0}, ", PT)); builder.Append(string.Format("SequenceNumber: {0}, ", SequenceNumber)); builder.Append(string.Format("Timestamp: {0}, ", Timestamp)); builder.Append(string.Format("SSRC: {0}, ", SSRC)); builder.Append(string.Format("CSRC: {0}, ", string.Join(" ", CSRC))); builder.Append(string.Format("PayloadSize: {0};", PayloadSize)); return builder.ToString(); } /// <summary> /// 重载对象是否相同 /// </summary> /// <param name="obj">要比较的对象</param> /// <returns>返回对象是否相同</returns> public override bool Equals(object obj) { RTPPacket packet = obj as RTPPacket; if (packet == null) { return false; } else { return SequenceNumber == packet.SequenceNumber; } } /// <summary> /// 重载获取HashCode /// </summary> /// <returns>返回SequenceNumber</returns> public override int GetHashCode() { return SequenceNumber; } /// <summary> /// ==运算符重载 /// </summary> /// <param name="packet1">左边RTP数据包对象</param> /// <param name="packet2">右边RTP数据包对象</param> /// <returns>返回是否相等</returns> public static bool operator ==(RTPPacket packet1, RTPPacket packet2) { if (ReferenceEquals(packet1, packet2)) { return true; } else if (ReferenceEquals(packet1, null) || ReferenceEquals(packet2, null)) { return false; } else { return packet1.Equals(packet2); } } /// <summary> /// !=运算符重载 /// </summary> /// <param name="packet1">左边RTP数据包对象</param> /// <param name="packet2">右边RTP数据包对象</param> /// <returns>返回是否不相等</returns> public static bool operator !=(RTPPacket packet1, RTPPacket packet2) { return !(packet1 == packet2); } }