Пример #1
0
 /// <summary>
 /// Sets property LastRR value.
 /// </summary>
 /// <param name="rr">RTCP RR report.</param>
 /// <exception cref="ArgumentNullException">Is raised when <b>rr</b> is null reference.</exception>
 internal void SetRR(RTCP_Packet_ReportBlock rr)
 {
     if (rr == null)
     {
         throw new ArgumentNullException("rr");
     }
 }
Пример #2
0
        /// <summary>
        /// Parses receiver report(RR) from byte buffer.
        /// </summary>
        /// <param name="buffer">Buffer wihich contains receiver report.</param>
        /// <param name="offset">Offset in buufer.</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>
        protected override void ParseInternal(byte[] buffer, ref int offset)
        {
            /* RFC 3550 6.4.2 RR: Receiver Report RTCP Packet.
             *      0                   1                   2                   3
             *      0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
             +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
             * header |V=2|P|    RC   |   PT=RR=201   |             length            |
             +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
             |                     SSRC of packet sender                     |
             +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
             | 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)                  |
             +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
             | report |                 SSRC_2 (SSRC of second source)                |
             | block  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
             | 2    :                               ...                             :
             +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
             |                  profile-specific extensions                  |
             +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
             */

            if (buffer == null)
            {
                throw new ArgumentNullException("buffer");
            }
            if (offset < 0)
            {
                throw new ArgumentException("Argument 'offset' value must be >= 0.");
            }

            m_Version = buffer[offset] >> 6;
            bool isPadded         = Convert.ToBoolean((buffer[offset] >> 5) & 0x1);
            int  reportBlockCount = buffer[offset++] & 0x1F;
            int  type             = buffer[offset++];
            int  length           = buffer[offset++] << 8 | buffer[offset++];

            if (isPadded)
            {
                this.PaddBytesCount = buffer[offset + length];
            }

            m_SSRC = (uint)(buffer[offset++] << 24 | buffer[offset++] << 16 | buffer[offset++] << 8 | buffer[offset++]);
            for (int i = 0; i < reportBlockCount; i++)
            {
                RTCP_Packet_ReportBlock reportBlock = new RTCP_Packet_ReportBlock();
                reportBlock.Parse(buffer, offset);
                m_pReportBlocks.Add(reportBlock);
                offset += 24;
            }
            // TODO: profile-specific extensions
        }
Пример #3
0
        /// <summary>
        /// Default constructor.
        /// </summary>
        /// <param name="rr">RTCP RR report.</param>
        /// <exception cref="ArgumentNullException">Is raised when <b>rr</b> is null reference.</exception>
        internal RTCP_Report_Receiver(RTCP_Packet_ReportBlock rr)
        {
            if(rr == null){
                throw new ArgumentNullException("rr");
            }

            m_FractionLost          = rr.FractionLost;
            m_CumulativePacketsLost = rr.CumulativePacketsLost;
            m_ExtHigestSeqNumber    = rr.ExtendedHighestSeqNo;
            m_Jitter                = rr.Jitter;
            m_LastSR                = rr.LastSR;
            m_DelaySinceLastSR      = rr.DelaySinceLastSR;
        }
Пример #4
0
        /// <summary>
        /// Default constructor.
        /// </summary>
        /// <param name="rr">RTCP RR report.</param>
        /// <exception cref="ArgumentNullException">Is raised when <b>rr</b> is null reference.</exception>
        internal RTCP_Report_Receiver(RTCP_Packet_ReportBlock rr)
        {
            if (rr == null)
            {
                throw new ArgumentNullException("rr");
            }

            m_FractionLost          = rr.FractionLost;
            m_CumulativePacketsLost = rr.CumulativePacketsLost;
            m_ExtHigestSeqNumber    = rr.ExtendedHighestSeqNo;
            m_Jitter           = rr.Jitter;
            m_LastSR           = rr.LastSR;
            m_DelaySinceLastSR = rr.DelaySinceLastSR;
        }
Пример #5
0
        /// <summary>
        /// Sets property LastRR value.
        /// </summary>
        /// <param name="rr">RTCP RR report.</param>
        /// <exception cref="ArgumentNullException">Is raised when <b>rr</b> is null reference.</exception>
        internal void SetRR(RTCP_Packet_ReportBlock rr)
        {
            if(rr == null){
                throw new ArgumentNullException("rr");
            }

        }
Пример #6
0
        /// <summary>
        /// Parses RTCP sender report(SR) from specified data buffer.
        /// </summary>
        /// <param name="buffer">Buffer which contains sender report.</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>
        protected override void ParseInternal(byte[] buffer,ref int offset)
        {
            /* RFC 3550 6.4.1 SR: Sender Report RTCP Packet.
                    0                   1                   2                   3
                    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
                   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
            header |V=2|P|    RC   |   PT=SR=200   |             length            |
                   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
                   |                         SSRC of sender                        |
                   +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
            sender |              NTP timestamp, most significant word             |
            info   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
                   |             NTP timestamp, least significant word             |
                   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
                   |                         RTP timestamp                         |
                   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
                   |                     sender's packet count                     |
                   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
                   |                      sender's octet count                     |
                   +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
            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)                  |
                   +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
            report |                 SSRC_2 (SSRC of second source)                |
            block  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
              2    :                               ...                             :
                   +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
                   |                  profile-specific extensions                  |
                   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
            */

            if(buffer == null){
                throw new ArgumentNullException("buffer");
            }
            if(offset < 0){
                throw new ArgumentException("Argument 'offset' value must be >= 0.");
            }

                 m_Version        = buffer[offset] >> 6;
            bool isPadded         = Convert.ToBoolean((buffer[offset] >> 5) & 0x1);
            int  reportBlockCount = buffer[offset++] & 0x1F;
            int  type             = buffer[offset++];
            int  length           = buffer[offset++] << 8 | buffer[offset++];
            if(isPadded){
                this.PaddBytesCount = buffer[offset + length];
            }

            m_SSRC              = (uint)(buffer[offset++] << 24 | buffer[offset++] << 16 | buffer[offset++] << 8 | buffer[offset++]);
            m_NtpTimestamp      = (ulong)(buffer[offset++] << 56 | buffer[offset++] << 48 | buffer[offset++] << 40 |buffer[offset++] << 32 | buffer[offset++] << 24 | buffer[offset++] << 16 | buffer[offset++] << 8 | buffer[offset++]);
            m_RtpTimestamp      = (uint)(buffer[offset++] << 24 | buffer[offset++] << 16 | buffer[offset++] << 8 | buffer[offset++]);
            m_SenderPacketCount = (uint)(buffer[offset++] << 24 | buffer[offset++] << 16 | buffer[offset++] << 8 | buffer[offset++]);
            m_SenderOctetCount  = (uint)(buffer[offset++] << 24 | buffer[offset++] << 16 | buffer[offset++] << 8 | buffer[offset++]);

            for(int i=0;i<reportBlockCount;i++){
                RTCP_Packet_ReportBlock reportBlock = new RTCP_Packet_ReportBlock();
                reportBlock.Parse(buffer,offset);
                m_pReportBlocks.Add(reportBlock);
                offset += 24;
            }
        }
Пример #7
0
        /// <summary>
        /// Creates receiver report.
        /// </summary>
        /// <returns>Returns created receiver report.</returns>
        internal RTCP_Packet_ReportBlock CreateReceiverReport()
        {
            /* RFC 3550 A.3 Determining Number of Packets Expected and Lost.
                In order to compute packet loss rates, the number of RTP packets
                expected and actually received from each source needs to be known,
                using per-source state information defined in struct source
                referenced via pointer s in the code below.  The number of packets
                received is simply the count of packets as they arrive, including any
                late or duplicate packets.  The number of packets expected can be
                computed by the receiver as the difference between the highest
                sequence number received (s->max_seq) and the first sequence number
                received (s->base_seq).  Since the sequence number is only 16 bits
                and will wrap around, it is necessary to extend the highest sequence
                number with the (shifted) count of sequence number wraparounds
                (s->cycles).  Both the received packet count and the count of cycles
                are maintained the RTP header validity check routine in Appendix A.1.

                    extended_max = s->cycles + s->max_seq;
                    expected = extended_max - s->base_seq + 1;

                The number of packets lost is defined to be the number of packets
                expected less the number of packets actually received:

                    lost = expected - s->received;

                Since this signed number is carried in 24 bits, it should be clamped
                at 0x7fffff for positive loss or 0x800000 for negative loss rather
                than wrapping around.

                The fraction of packets lost during the last reporting interval
                (since the previous SR or RR packet was sent) is calculated from
                differences in the expected and received packet counts across the
                interval, where expected_prior and received_prior are the values
                saved when the previous reception report was generated:

                    expected_interval = expected - s->expected_prior;
                    s->expected_prior = expected;
                    received_interval = s->received - s->received_prior;
                    s->received_prior = s->received;
                    lost_interval = expected_interval - received_interval;
                    if(expected_interval == 0 || lost_interval <= 0)
                        fraction = 0;
                    else
                        fraction = (lost_interval << 8) / expected_interval;

                The resulting fraction is an 8-bit fixed point number with the binary
                point at the left edge.
            */

            uint extHighestSeqNo = (uint)(m_SeqNoWrapCount << 16 + m_MaxSeqNo);
            uint expected        = extHighestSeqNo - m_BaseSeq + 1;  
         
            int expected_interval = (int)(expected - m_ExpectedPrior);
            m_ExpectedPrior = expected;
            int received_interval = (int)(m_PacketsReceived - m_ReceivedPrior);
            m_ReceivedPrior = m_PacketsReceived;
            int lost_interval = expected_interval - received_interval;
            int fraction = 0;
            if(expected_interval == 0 || lost_interval <= 0){
                fraction = 0;
            }
            else{
                fraction = (lost_interval << 8) / expected_interval;
            }

            RTCP_Packet_ReportBlock rr = new RTCP_Packet_ReportBlock(this.SSRC.SSRC);
            rr.FractionLost            = (uint)fraction;
            rr.CumulativePacketsLost   = (uint)this.PacketsLost;
            rr.ExtendedHighestSeqNo    = extHighestSeqNo;
            rr.Jitter                  = (uint)m_Jitter;
            rr.LastSR                  = (m_pLastSR == null ? 0 : ((uint)((long)m_pLastSR.NtpTimestamp >> 8) & 0xFFFF));
            rr.DelaySinceLastSR        = (uint)Math.Max(0,this.DelaySinceLastSR / 65.536);

            return rr;
        }
        /// <summary>
        /// Creates receiver report.
        /// </summary>
        /// <returns>Returns created receiver report.</returns>
        internal RTCP_Packet_ReportBlock CreateReceiverReport()
        {
            /* RFC 3550 A.3 Determining Number of Packets Expected and Lost.
             *  In order to compute packet loss rates, the number of RTP packets
             *  expected and actually received from each source needs to be known,
             *  using per-source state information defined in struct source
             *  referenced via pointer s in the code below.  The number of packets
             *  received is simply the count of packets as they arrive, including any
             *  late or duplicate packets.  The number of packets expected can be
             *  computed by the receiver as the difference between the highest
             *  sequence number received (s->max_seq) and the first sequence number
             *  received (s->base_seq).  Since the sequence number is only 16 bits
             *  and will wrap around, it is necessary to extend the highest sequence
             *  number with the (shifted) count of sequence number wraparounds
             *  (s->cycles).  Both the received packet count and the count of cycles
             *  are maintained the RTP header validity check routine in Appendix A.1.
             *
             *      extended_max = s->cycles + s->max_seq;
             *      expected = extended_max - s->base_seq + 1;
             *
             *  The number of packets lost is defined to be the number of packets
             *  expected less the number of packets actually received:
             *
             *      lost = expected - s->received;
             *
             *  Since this signed number is carried in 24 bits, it should be clamped
             *  at 0x7fffff for positive loss or 0x800000 for negative loss rather
             *  than wrapping around.
             *
             *  The fraction of packets lost during the last reporting interval
             *  (since the previous SR or RR packet was sent) is calculated from
             *  differences in the expected and received packet counts across the
             *  interval, where expected_prior and received_prior are the values
             *  saved when the previous reception report was generated:
             *
             *      expected_interval = expected - s->expected_prior;
             *      s->expected_prior = expected;
             *      received_interval = s->received - s->received_prior;
             *      s->received_prior = s->received;
             *      lost_interval = expected_interval - received_interval;
             *      if(expected_interval == 0 || lost_interval <= 0)
             *          fraction = 0;
             *      else
             *          fraction = (lost_interval << 8) / expected_interval;
             *
             *  The resulting fraction is an 8-bit fixed point number with the binary
             *  point at the left edge.
             */

            uint extHighestSeqNo = (uint)(m_SeqNoWrapCount << 16 + m_MaxSeqNo);
            uint expected        = extHighestSeqNo - m_BaseSeq + 1;

            int expected_interval = (int)(expected - m_ExpectedPrior);

            m_ExpectedPrior = expected;
            int received_interval = (int)(m_PacketsReceived - m_ReceivedPrior);

            m_ReceivedPrior = m_PacketsReceived;
            int lost_interval = expected_interval - received_interval;
            int fraction      = 0;

            if (expected_interval == 0 || lost_interval <= 0)
            {
                fraction = 0;
            }
            else
            {
                fraction = (lost_interval << 8) / expected_interval;
            }

            RTCP_Packet_ReportBlock rr = new RTCP_Packet_ReportBlock(this.SSRC.SSRC);

            rr.FractionLost          = (uint)fraction;
            rr.CumulativePacketsLost = (uint)this.PacketsLost;
            rr.ExtendedHighestSeqNo  = extHighestSeqNo;
            rr.Jitter           = (uint)m_Jitter;
            rr.LastSR           = (m_pLastSR == null ? 0 : ((uint)((long)m_pLastSR.NtpTimestamp >> 8) & 0xFFFF));
            rr.DelaySinceLastSR = (uint)Math.Max(0, this.DelaySinceLastSR / 65.536);

            return(rr);
        }