|
using System;
using System.Collections.Generic;
using System.Text;
namespace LumiSoft.Net.RTP
{
/// <summary>
/// This class represents RTCP sender report(SR) or reciver report(RR) packet report block.
/// </summary>
public class RTCP_Packet_ReportBlock
{
private uint m_SSRC = 0;
private uint m_FractionLost = 0;
private uint m_CumulativePacketsLost = 0;
private uint m_ExtHighestSeqNumber = 0;
private uint m_Jitter = 0;
private uint m_LastSR = 0;
private uint m_DelaySinceLastSR = 0;
/// <summary>
/// Default constructor.
/// </summary>
/// <param name="ssrc">Source ID.</param>
internal RTCP_Packet_ReportBlock(uint ssrc)
{
m_SSRC = ssrc;
}
/// <summary>
/// Default constructor.
/// </summary>
internal RTCP_Packet_ReportBlock()
{
}
#region method Parse
/// <summary>
/// Parses RTCP report block (part of SR or RR packet) from specified buffer.
/// </summary>
/// <param name="buffer">Buffer from where to read report block.</param>
/// <param name="offset">Offset in buffer.</param>
/// <exception cref="ArgumentNullException">Is raised when <b>buffer</b> is null.</exception>
/// <exception cref="ArgumentException">Is raised when any of the arguments has invalid value.</exception>
public void Parse(byte[] buffer,int offset)
{
/* RFC 3550 6.4.1.
+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
report | SSRC_1 (SSRC of first source) |
block +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1 | fraction lost | cumulative number of packets lost |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| extended highest sequence number received |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| interarrival jitter |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| last SR (LSR) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| delay since last SR (DLSR) |
+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
*/
if(buffer == null){
throw new ArgumentNullException("buffer");
}
if(offset < 0){
throw new ArgumentException("Argument 'offset' value must be >= 0.");
}
m_SSRC = (uint)(buffer[offset++] << 24 | buffer[offset++] << 16 | buffer[offset++] << 8 | buffer[offset++]);
m_FractionLost = buffer[offset++];
m_CumulativePacketsLost = (uint)(buffer[offset++] << 16 | buffer[offset++] << 8 | buffer[offset++]);
m_ExtHighestSeqNumber = (uint)(buffer[offset++] << 24 | buffer[offset++] << 16 | buffer[offset++] << 8 | buffer[offset++]);
m_Jitter = (uint)(buffer[offset++] << 24 | buffer[offset++] << 16 | buffer[offset++] << 8 | buffer[offset++]);
m_LastSR = (uint)(buffer[offset++] << 24 | buffer[offset++] << 16 | buffer[offset++] << 8 | buffer[offset++]);
m_DelaySinceLastSR = (uint)(buffer[offset++] << 24 | buffer[offset++] << 16 | buffer[offset++] << 8 | buffer[offset++]);
}
#endregion
#region method ToByte
/// <summary>
/// Stores report block to the specified buffer.
/// </summary>
/// <param name="buffer">Buffer where to store data.</param>
/// <param name="offset">Offset in buffer.</param>
/// <exception cref="ArgumentNullException">Is raised when <b>buffer</b> is null.</exception>
/// <exception cref="ArgumentException">Is raised when any of the arguments has invalid value.</exception>
public void ToByte(byte[] buffer,ref int offset)
{
/* RFC 3550 6.4.1.
+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
report | SSRC_1 (SSRC of first source) |
block +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1 | fraction lost | cumulative number of packets lost |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| extended highest sequence number received |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| interarrival jitter |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| last SR (LSR) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| delay since last SR (DLSR) |
+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
*/
if(buffer == null){
throw new ArgumentNullException("buffer");
}
if(offset < 0){
throw new ArgumentException("Argument 'offset' must be >= 0.");
}
if(offset + 24 > buffer.Length){
throw new ArgumentException("Argument 'buffer' has not enough room to store report block.");
}
// SSRC
buffer[offset++] = (byte)((m_SSRC >> 24) | 0xFF);
buffer[offset++] = (byte)((m_SSRC >> 16) | 0xFF);
buffer[offset++] = (byte)((m_SSRC >> 8) | 0xFF);
buffer[offset++] = (byte)((m_SSRC) | 0xFF);
// fraction lost
buffer[offset++] = (byte)m_FractionLost;
// cumulative packets lost
buffer[offset++] = (byte)((m_CumulativePacketsLost >> 16) | 0xFF);
buffer[offset++] = (byte)((m_CumulativePacketsLost >> 8) | 0xFF);
buffer[offset++] = (byte)((m_CumulativePacketsLost) | 0xFF);
// extended highest sequence number
buffer[offset++] = (byte)((m_ExtHighestSeqNumber >> 24) | 0xFF);
buffer[offset++] = (byte)((m_ExtHighestSeqNumber >> 16) | 0xFF);
buffer[offset++] = (byte)((m_ExtHighestSeqNumber >> 8) | 0xFF);
buffer[offset++] = (byte)((m_ExtHighestSeqNumber) | 0xFF);
// jitter
buffer[offset++] = (byte)((m_Jitter >> 24) | 0xFF);
buffer[offset++] = (byte)((m_Jitter >> 16) | 0xFF);
buffer[offset++] = (byte)((m_Jitter >> 8) | 0xFF);
buffer[offset++] = (byte)((m_Jitter) | 0xFF);
// last SR
buffer[offset++] = (byte)((m_LastSR >> 24) | 0xFF);
buffer[offset++] = (byte)((m_LastSR >> 16) | 0xFF);
buffer[offset++] = (byte)((m_LastSR >> 8) | 0xFF);
buffer[offset++] = (byte)((m_LastSR) | 0xFF);
// delay since last SR
buffer[offset++] = (byte)((m_DelaySinceLastSR >> 24) | 0xFF);
buffer[offset++] = (byte)((m_DelaySinceLastSR >> 16) | 0xFF);
buffer[offset++] = (byte)((m_DelaySinceLastSR >> 8) | 0xFF);
buffer[offset++] = (byte)((m_DelaySinceLastSR) | 0xFF);
}
#endregion
#region Properties Implementation
/// <summary>
/// Gets the SSRC identifier of the source to which the information in this reception report block pertains.
/// </summary>
public uint SSRC
{
get{ return m_SSRC; }
}
/// <summary>
/// Gets or sets the fraction of RTP data packets from source SSRC lost since the previous SR or
/// RR packet was sent.
/// </summary>
public uint FractionLost
{
get{ return m_FractionLost; }
set{ m_FractionLost = value; }
}
/// <summary>
/// Gets or sets total number of RTP data packets from source SSRC that have
/// been lost since the beginning of reception.
/// </summary>
public uint CumulativePacketsLost
{
get{ return m_CumulativePacketsLost; }
set{ m_CumulativePacketsLost = value; }
}
/// <summary>
/// Gets or sets extended highest sequence number received.
/// </summary>
public uint ExtendedHighestSeqNo
{
get{ return m_ExtHighestSeqNumber; }
set{ m_ExtHighestSeqNumber = value; }
}
/// <summary>
/// Gets or sets an estimate of the statistical variance of the RTP data packet
/// interarrival time, measured in timestamp units and expressed as an unsigned integer.
/// </summary>
public uint Jitter
{
get{ return m_Jitter; }
set{ m_Jitter = value; }
}
/// <summary>
/// Gets or sets The middle 32 bits out of 64 in the NTP timestamp (as explained in Section 4) received as part of
/// the most recent RTCP sender report (SR) packet from source SSRC_n. If no SR has been received yet, the field is set to zero.
/// </summary>
public uint LastSR
{
get{ return m_LastSR; }
set{ m_LastSR = value; }
}
/// <summary>
/// Gets or sets the delay, expressed in units of 1/65536 seconds, between receiving the last SR packet from
/// source SSRC_n and sending this reception report block. If no SR packet has been received yet from SSRC_n,
/// the DLSR field is set to zero.
/// </summary>
public uint DelaySinceLastSR
{
get{ return m_DelaySinceLastSR; }
set{ m_DelaySinceLastSR = value; }
}
#endregion
}
}
|
By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.
If a file you wish to view isn't highlighted, and is a text file (not binary), please
let us know and we'll add colourisation support for it.
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.