diff -r f5a5d9237d69 -r e8d6255306f8 src/jlibrtp/Participant.java --- a/src/jlibrtp/Participant.java Sat Jan 23 21:48:58 2010 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,464 +0,0 @@ -/** - * Java RTP Library (jlibrtp) - * Copyright (C) 2006 Arne Kepp - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ -package jlibrtp; - -import java.net.InetSocketAddress; - -/** - * A participant represents a peer in an RTPSession. Based on the information - * stored on these objects, packets are processed and statistics generated for - * RTCP. - */ -public class Participant { - /** - * Whether the participant is unexpected, e.g. arrived through unicast with - * SDES - */ - protected boolean unexpected = false; - /** Where to send RTP packets (unicast) */ - protected InetSocketAddress rtpAddress = null; - /** Where to send RTCP packets (unicast) */ - protected InetSocketAddress rtcpAddress = null; - /** Where the first RTP packet was received from */ - protected InetSocketAddress rtpReceivedFromAddress = null; - /** Where the first RTCP packet was received from */ - protected InetSocketAddress rtcpReceivedFromAddress = null; - - /** SSRC of participant */ - protected long ssrc = -1; - /** SDES CNAME */ - protected String cname = null; - /** SDES The participant's real name */ - protected String name = null; - /** SDES The participant's email */ - protected String email = null; - /** SDES The participant's phone number */ - protected String phone = null; - /** SDES The participant's location */ - protected String loc = null; - /** SDES The tool the participants is using */ - protected String tool = null; - /** SDES A note */ - protected String note = null; - /** SDES A priv string, loosely defined */ - protected String priv = null; - - // Receiver Report Items - /** RR First sequence number */ - protected int firstSeqNumber = -1; - /** RR Last sequence number */ - protected int lastSeqNumber = 0; - /** RR Number of times sequence number has rolled over */ - protected long seqRollOverCount = 0; - /** RR Number of packets received */ - protected long receivedPkts = 0; - /** RR Number of octets received */ - protected long receivedOctets = 0; - /** RR Number of packets received since last SR */ - protected int receivedSinceLastSR = 0; - /** RR Sequence number associated with last SR */ - protected int lastSRRseqNumber = 0; - /** RR Interarrival jitter */ - protected double interArrivalJitter = -1.0; - /** RR Last received RTP Timestamp */ - protected long lastRtpTimestamp = 0; - - /** RR Middle 32 bits of the NTP timestamp in the last SR */ - protected long timeStampLSR = 0; - /** RR The time when we actually got the last SR */ - protected long timeReceivedLSR = 0; - - /** Gradient where UNIX timestamp = ntpGradient*RTPTimestamp * ntpOffset */ - protected double ntpGradient = -1; - /** Offset where UNIX timestamp = ntpGradient*RTPTimestamp * ntpOffset */ - protected long ntpOffset = -1; - /** Last NTP received in SR packet, MSB */ - protected long lastNtpTs1 = 0; // 32 bits - /** Last NTP received in SR packet, LSB */ - protected long lastNtpTs2 = 0; // 32 bits - /** RTP Timestamp in last SR packet */ - protected long lastSRRtpTs = 0; // 32 bits - - /** UNIX time when a BYE was received from this participant, for pruning */ - protected long timestampBYE = -1; // The user said BYE at this time - - /** Store the packets received from this participant */ - protected PktBuffer pktBuffer = null; - - /** - * UNIX time of last RTP packet, to check whether this participant has sent - * anything recently - */ - protected long lastRtpPkt = -1; // Time of last RTP packet - /** - * UNIX time of last RTCP packet, to check whether this participant has sent - * anything recently - */ - protected long lastRtcpPkt = -1; // Time of last RTCP packet - /** - * UNIX time this participant was added by application, to check whether we - * ever heard back - */ - protected long addedByApp = -1; // Time the participant was added by - // application - /** UNIX time of last time we sent an RR to this user */ - protected long lastRtcpRRPkt = -1; // Timestamp of last time we sent this - // person an RR packet - /** Unix time of second to last time we sent and RR to this user */ - protected long secondLastRtcpRRPkt = -1; // Timestamp of 2nd to last time we - // sent this person an RR Packet - - /** - * Create a basic participant. If this is a unicast session you must - * provide network address (ipv4 or ipv6) and ports for RTP and RTCP, as - * well as a cname for this contact. These things should be negotiated - * through SIP or a similar protocol. - * - * jlibrtp will listen for RTCP packets to obtain a matching SSRC for this - * participant, based on cname. - * - * @param networkAddress - * string representation of network address (ipv4 or ipv6). Use - * "127.0.0.1" for multicast session. - * @param rtpPort - * port on which peer expects RTP packets. Use 0 if this is a - * sender-only, or this is a multicast session. - * @param rtcpPort - * port on which peer expects RTCP packets. Use 0 if this is a - * sender-only, or this is a multicast session. - */ - public Participant(String networkAddress, int rtpPort, int rtcpPort) { - if (RTPSession.rtpDebugLevel > 6) { - System.out.println("Creating new participant: " + networkAddress); - } - - // RTP - if (rtpPort > 0) { - try { - rtpAddress = new InetSocketAddress(networkAddress, rtpPort); - } catch (Exception e) { - System.out.println("Couldn't resolve " + networkAddress); - } - // isReceiver = true; - } - - // RTCP - if (rtcpPort > 0) { - try { - rtcpAddress = new InetSocketAddress(networkAddress, rtcpPort); - } catch (Exception e) { - System.out.println("Couldn't resolve " + networkAddress); - } - } - - // By default this is a sender - // isSender = true; - } - - // We got a packet, but we don't know this person yet. - protected Participant(InetSocketAddress rtpAdr, InetSocketAddress rtcpAdr, - long SSRC) { - rtpReceivedFromAddress = rtpAdr; - rtcpReceivedFromAddress = rtcpAdr; - ssrc = SSRC; - unexpected = true; - } - - // Dummy constructor to ease testing - protected Participant() { - System.out.println("Don't use the Participan(void) Constructor!"); - } - - /** - * RTP Address registered with this participant. - * - * @return address of participant - */ - InetSocketAddress getRtpSocketAddress() { - return rtpAddress; - } - - /** - * RTCP Address registered with this participant. - * - * @return address of participant - */ - InetSocketAddress getRtcpSocketAddress() { - return rtcpAddress; - } - - /** - * InetSocketAddress this participant has used to send us RTP packets. - * - * @return address of participant - */ - InetSocketAddress getRtpReceivedFromAddress() { - return rtpAddress; - } - - /** - * InetSocketAddress this participant has used to send us RTCP packets. - * - * @return address of participant - */ - InetSocketAddress getRtcpReceivedFromAddress() { - return rtcpAddress; - } - - /** - * CNAME registered for this participant. - * - * @return the cname - */ - public String getCNAME() { - return cname; - } - - /** - * NAME registered for this participant. - * - * @return the name - */ - public String getNAME() { - return name; - } - - /** - * EMAIL registered for this participant. - * - * @return the email address - */ - public String getEmail() { - return email; - } - - /** - * PHONE registered for this participant. - * - * @return the phone number - */ - public String getPhone() { - return phone; - } - - /** - * LOCATION registered for this participant. - * - * @return the location - */ - public String getLocation() { - return loc; - } - - /** - * NOTE registered for this participant. - * - * @return the note - */ - public String getNote() { - return note; - } - - /** - * PRIVATE something registered for this participant. - * - * @return the private-string - */ - public String getPriv() { - return priv; - } - - /** - * TOOL something registered for this participant. - * - * @return the tool - */ - public String getTool() { - return tool; - } - - /** - * SSRC for participant, determined through RTCP SDES - * - * @return SSRC (32 bit unsigned integer as long) - */ - public long getSSRC() { - return this.ssrc; - } - - /** - * Updates the participant with information for receiver reports. - * - * @param packetLength - * to keep track of received octets - * @param pkt - * the most recently received packet - */ - protected void updateRRStats(int packetLength, RtpPkt pkt) { - int curSeqNum = pkt.getSeqNumber(); - - if (firstSeqNumber < 0) { - firstSeqNumber = curSeqNum; - } - - receivedOctets += packetLength; - receivedSinceLastSR++; - receivedPkts++; - - long curTime = System.currentTimeMillis(); - - if (this.lastSeqNumber < curSeqNum) { - // In-line packet, best thing you could hope for - this.lastSeqNumber = curSeqNum; - - } else if (this.lastSeqNumber - this.lastSeqNumber < -100) { - // Sequence counter rolled over - this.lastSeqNumber = curSeqNum; - seqRollOverCount++; - - } else { - // This was probably a duplicate or a late arrival. - } - - // Calculate jitter - if (this.lastRtpPkt > 0) { - - long D = (pkt.getTimeStamp() - curTime) - - (this.lastRtpTimestamp - this.lastRtpPkt); - if (D < 0) - D = (-1) * D; - - this.interArrivalJitter += ((double) D - this.interArrivalJitter) / 16.0; - } - - lastRtpPkt = curTime; - lastRtpTimestamp = pkt.getTimeStamp(); - } - - /** - * Calculates the extended highest sequence received by adding the last - * sequence number to 65536 times the number of times the sequence counter - * has rolled over. - * - * @return extended highest sequence - */ - protected long getExtHighSeqRecv() { - return (65536 * seqRollOverCount + lastSeqNumber); - } - - /** - * Get the fraction of lost packets, calculated as described in RFC 3550 as - * a fraction of 256. - * - * @return the fraction of lost packets since last SR received - */ - protected int getFractionLost() { - int expected = (lastSeqNumber - lastSRRseqNumber); - if (expected < 0) - expected = 65536 + expected; - - int fraction = 256 * (expected - receivedSinceLastSR); - if (expected > 0) { - fraction = (fraction / expected); - } else { - fraction = 0; - } - - // Clear counters - receivedSinceLastSR = 0; - lastSRRseqNumber = lastSeqNumber; - - return fraction; - } - - /** - * The total number of packets lost during the session. - * - * Returns zero if loss is negative, i.e. duplicates have been received. - * - * @return number of lost packets, or zero. - */ - protected long getLostPktCount() { - long lost = (this.getExtHighSeqRecv() - this.firstSeqNumber) - - receivedPkts; - - if (lost < 0) - lost = 0; - return lost; - } - - /** - * - * @return the interArrivalJitter, calculated continuously - */ - protected double getInterArrivalJitter() { - return this.interArrivalJitter; - } - - /** - * Set the timestamp for last sender report - * - * @param ntp1 - * high order bits - * @param ntp2 - * low order bits - */ - protected void setTimeStampLSR(long ntp1, long ntp2) { - // Use what we've got - byte[] high = StaticProcs.uIntLongToByteWord(ntp1); - byte[] low = StaticProcs.uIntLongToByteWord(ntp2); - low[3] = low[1]; - low[2] = low[0]; - low[1] = high[3]; - low[0] = high[2]; - - this.timeStampLSR = StaticProcs.bytesToUIntLong(low, 0); - } - - /** - * Calculate the delay between the last received sender report and now. - * - * @return the delay in units of 1/65.536ms - */ - protected long delaySinceLastSR() { - if (this.timeReceivedLSR < 1) - return 0; - - long delay = System.currentTimeMillis() - this.timeReceivedLSR; - - // Convert ms into 1/65536s = 1/65.536ms - return (long) ((double) delay * 65.536); - } - - /** - * Only for debugging purposes - */ - public void debugPrint() { - System.out.print(" Participant.debugPrint() SSRC:" + this.ssrc - + " CNAME:" + this.cname); - if (this.rtpAddress != null) - System.out.print(" RTP:" + this.rtpAddress.toString()); - if (this.rtcpAddress != null) - System.out.print(" RTCP:" + this.rtcpAddress.toString()); - System.out.println(""); - - System.out.println(" Packets received:" - + this.receivedPkts); - } -}