/// <summary> /// Sends specified packet to the RTP session remote party. /// </summary> /// <param name="packet">RTP packet.</param> /// <exception cref="ObjectDisposedException">Is raised when this class is Disposed and this method is accessed.</exception> /// <exception cref="ArgumentNullException">Is raised when <b>packet</b> is null reference.</exception> /// <remarks>Properties <b>packet.SSRC</b>,<b>packet.SeqNo</b>,<b>packet.PayloadType</b> filled by this method automatically.</remarks> public void Send(RTP_Packet packet) { if (m_IsDisposed) { throw new ObjectDisposedException(this.GetType().Name); } if (packet == null) { throw new ArgumentNullException("packet"); } if (this.Session.StreamMode == RTP_StreamMode.Inactive || this.Session.StreamMode == RTP_StreamMode.Receive) { return; } // RTP was designed around the concept of Application Level Framing (ALF), // because of it we only allow to send packets and don't deal with breaking frames into packets. packet.SSRC = this.Source.SSRC; packet.SeqNo = NextSeqNo(); packet.PayloadType = this.Session.Payload; // Send RTP packet. m_RtpBytesSent += m_pSource.SendRtpPacket(packet); m_RtpPacketsSent++; m_RtpDataBytesSent += packet.Data.Length; m_LastPacketTime = DateTime.Now; m_LastPacketRtpTimestamp = packet.Timestamp; m_RtcpCyclesSinceWeSent = 0; }
/// <summary> /// Raises <b>PacketReceived</b> event. /// </summary> /// <param name="packet">RTP packet.</param> private void OnPacketReceived(RTP_Packet packet) { if (this.PacketReceived != null) { this.PacketReceived(this, new RTP_PacketEventArgs(packet)); } }
/// <summary> /// Parses RTP packet. /// </summary> /// <param name="buffer">Buffer containing RTP packet.</param> /// <param name="size">Number of bytes used in buffer.</param> /// <returns>Returns parsed RTP packet.</returns> public static RTP_Packet Parse(byte[] buffer, int size) { RTP_Packet packet = new RTP_Packet(); packet.ParseInternal(buffer, size); return(packet); }
/// <summary> /// Default constructor. /// </summary> /// <param name="packet">RTP packet.</param> public RTP_PacketEventArgs(RTP_Packet packet) { if (packet == null) { throw new ArgumentNullException("packet"); } m_pPacket = packet; }
/// <summary> /// Processes specified RTP packet thorugh this stream. /// </summary> /// <param name="packet">RTP packet.</param> /// <param name="size">RTP packet size in bytes.</param> /// <exception cref="ArgumentNullException">Is raised when <b>packet</b> is null reference.</exception> internal void Process(RTP_Packet packet, int size) { if (packet == null) { throw new ArgumentNullException("packet"); } m_BytesReceived += size; if (UpdateSeq(packet.SeqNo)) { OnPacketReceived(packet); /* RFC 3550 A.8 Estimating the Interarrival Jitter. * The code fragments below implement the algorithm given in Section * 6.4.1 for calculating an estimate of the statistical variance of the * RTP data interarrival time to be inserted in the interarrival jitter * field of reception reports. The inputs are r->ts, the timestamp from * the incoming packet, and arrival, the current time in the same units. * Here s points to state for the source; s->transit holds the relative * transit time for the previous packet, and s->jitter holds the * estimated jitter. The jitter field of the reception report is * measured in timestamp units and expressed as an unsigned integer, but * the jitter estimate is kept in a floating point. As each data packet * arrives, the jitter estimate is updated: * * int transit = arrival - r->ts; * int d = transit - s->transit; * s->transit = transit; * if (d < 0) d = -d; * s->jitter += (1./16.) * ((double)d - s->jitter); * * When a reception report block (to which rr points) is generated for * this member, the current jitter estimate is returned: * * rr->jitter = (u_int32) s->jitter; * */ uint arrival = RTP_Utils.DateTimeToNTP32(DateTime.Now); int transit = (int)(arrival - packet.Timestamp); int d = transit - m_Transit; m_Transit = transit; if (d < 0) { d = -d; } m_Jitter += (1.0 / 16.0) * ((double)d - m_Jitter); } // else Packet not valid, skip it. }
/// <summary> /// Sends specified RTP packet to the session remote party. /// </summary> /// <param name="packet">RTP packet.</param> /// <returns>Returns packet size in bytes.</returns> /// <exception cref="ObjectDisposedException">Is raised when this class is Disposed and this method is accessed.</exception> /// <exception cref="ArgumentNullException">Is raised when <b>packet</b> is null reference.</exception> /// <exception cref="InvalidOperationException">Is raised when <b>CreateStream</b> method has been not called.</exception> internal int SendRtpPacket(RTP_Packet packet) { if (packet == null) { throw new ArgumentNullException("packet"); } if (m_pStream == null) { throw new InvalidOperationException("RTP stream is not created by CreateStream method."); } SetLastRtpPacket(DateTime.Now); SetState(RTP_SourceState.Active); return(this.Session.SendRtpPacket(m_pStream, packet)); }
/// <summary> /// Is called when RTP session receives new RTP packet. /// </summary> /// <param name="packet">RTP packet.</param> /// <param name="size">Packet size in bytes.</param> /// <exception cref="ArgumentNullException">Is raised when <b>packet</b> is null reference.</exception> internal void OnRtpPacketReceived(RTP_Packet packet, int size) { if (packet == null) { throw new ArgumentNullException("packet"); } SetLastRtpPacket(DateTime.Now); // Passive source and first RTP packet. if (m_pStream == null) { m_pStream = new RTP_ReceiveStream(this.Session, this, packet.SeqNo); SetState(RTP_SourceState.Active); } m_pStream.Process(packet, size); }