--- a/res/menu/contactlistmenu.xml Thu May 28 14:26:06 2009 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,6 +0,0 @@
-<menu xmlns:android="http://schemas.android.com/apk/res/android">
- <item android:title="@string/MenuConnection" android:id="@+id/account_edit" android:icon="@drawable/xmpp"/>
- <item android:title="@string/MenuAddContact" android:id="@+id/add_contact" android:icon="@drawable/buddie_robot"/>
- <item android:title="@string/MenuAccountAbout" android:id="@+id/account_about" android:icon="@drawable/signal"/>
- <item android:title="@string/MenuAccountCreate" android:id="@+id/account_create"/>
-</menu>
--- a/res/values/style.xml Thu May 28 14:26:06 2009 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
- <style name="customtheme" parent="android:Theme">
- </style>
-
- <style name="customtheme.contactList">
- <item name="android:windowBackground">@drawable/background</item>
- <item name="android:windowNoTitle">true</item>
- <item name="android:textColor">#000000</item>
- <item name="android:typeface">sans</item>
- <item name="android:textSize">18sp</item>
-
- </style>
-
- <style name="customtheme.jungle">
- <item name="android:windowBackground">@drawable/background</item>
- <item name="android:windowNoTitle">true</item>
- <item name="android:textColor">#FFFFFF</item>
- <item name="android:typeface">sans</item>
- <item name="android:textSize">18sp</item>
- </style>
-
- <style name="customtheme.spinner">
- <item name="android:windowBackground">@drawable/background</item>
- <item name="android:windowNoTitle">true</item>
- <item name="android:textColor">#FF0000</item>
- <item name="android:typeface">sans</item>
- <item name="android:textSize">18sp</item>
- </style>
-
-</resources>
\ No newline at end of file
--- a/res/values/styles.xml Thu May 28 14:26:06 2009 +0200
+++ b/res/values/styles.xml Thu May 28 15:00:07 2009 +0200
@@ -1,29 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
- <style name="customtheme" parent="android:Theme">
- </style>
- <style name="customtheme.contactList">
- <item name="android:windowBackground">@drawable/background</item>
- <item name="android:windowNoTitle">true</item>
- <item name="android:textColor">#000000</item>
- <item name="android:typeface">sans</item>
- <item name="android:textSize">18sp</item>
-
- </style>
- <style name="customtheme.jungle">
- <item name="android:windowBackground">@drawable/background</item>
- <item name="android:windowNoTitle">true</item>
- <item name="android:textColor">#FFFFFF</item>
- <item name="android:typeface">sans</item>
- <item name="android:textSize">18sp</item>
- </style>
- <style name="customtheme.spinner">
- <item name="android:windowBackground">@drawable/background</item>
- <item name="android:windowNoTitle">true</item>
- <item name="android:textColor">#FF0000</item>
- <item name="android:typeface">sans</item>
- <item name="android:textSize">18sp</item>
- </style>
<style name="Label">
<item name="android:textSize">16sp</item>
<item name="android:textStyle">bold</item>
@@ -34,4 +10,4 @@
<style name="Theme.BEEM.Default" parent="@android:style/Theme">
<item name="android:windowBackground">@drawable/background</item>
</style>
-</resources>
\ No newline at end of file
+</resources>
--- a/src/jlibrtp/AppCallerThread.java Thu May 28 14:26:06 2009 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,110 +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.util.Enumeration;
-
-/**
- * The purpose of this thread is to check whether there are packets ready from
- * any participants.
- *
- * It should sleep when not in use, and be woken up by a condition variable.
- *
- * Optionally, if we do jitter-control, the condition variable should have a max waiting period
- * equal to how often we need to push data.
- *
- * @author Arne Kepp
- */
-public class AppCallerThread extends Thread {
- /** The parent RTP Session */
- RTPSession rtpSession;
- /** The applications interface, where the callback methods are called */
- RTPAppIntf appl;
-
- /**
- * Instatiates the AppCallerThread
- *
- * @param session the RTPSession with participants etc
- * @param rtpApp the interface to which data is given
- */
- protected AppCallerThread(RTPSession session, RTPAppIntf rtpApp) {
- rtpSession = session;
- appl = rtpApp;
- if(RTPSession.rtpDebugLevel > 1) {
- System.out.println("<-> AppCallerThread created");
- }
- }
-
- /**
- * The AppCallerThread will run in this loop until the RTPSession
- * is terminated.
- *
- * Whenever an RTP packet is received it will loop over the
- * participants to check for packet buffers that have available
- * frame.
- */
- public void run() {
- if(RTPSession.rtpDebugLevel > 3) {
- System.out.println("-> AppCallerThread.run()");
- }
-
- while(rtpSession.endSession == false) {
-
- rtpSession.pktBufLock.lock();
- try {
- if(RTPSession.rtpDebugLevel > 4) {
- System.out.println("<-> AppCallerThread going to Sleep");
- }
-
- try { rtpSession.pktBufDataReady.await(); }
- catch (Exception e) { System.out.println("AppCallerThread:" + e.getMessage());}
-
- // Next loop over all participants and check whether they have anything for us.
- Enumeration<Participant> enu = rtpSession.partDb.getParticipants();
-
- while(enu.hasMoreElements()) {
- Participant p = enu.nextElement();
-
- boolean done = false;
- //System.out.println(p.ssrc + " " + !done +" " + p.rtpAddress
- // + " " + rtpSession.naiveReception + " " + p.pktBuffer);
- //System.out.println("done: " + done + " p.unexpected: " + p.unexpected);
- while(!done && (!p.unexpected || rtpSession.naiveReception)
- && p.pktBuffer != null && p.pktBuffer.length > 0) {
-
- DataFrame aFrame = p.pktBuffer.popOldestFrame();
- if(aFrame == null) {
- done = true;
- } else {
- appl.receiveData(aFrame, p);
- }
- }
- }
-
- } finally {
- rtpSession.pktBufLock.unlock();
- }
-
- }
- if(RTPSession.rtpDebugLevel > 3) {
- System.out.println("<- AppCallerThread.run() terminating");
- }
- }
-
-}
--- a/src/jlibrtp/CompRtcpPkt.java Thu May 28 14:26:06 2009 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,234 +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.util.*;
-import java.net.InetSocketAddress;
-
-/**
- * Compound RTCP packet class.
- *
- * It basically holds a list of packets. This list can either be constructed
- * by providing a byte[] of a compound packet, or by adding individual packets.
- *
- * Upon encode(), the packet will call encode on all the added packets.
- *
- * problem == 0 indicates the parsing succeeded.
- *
- *
- * @author Arne Kepp
- */
-
-public class CompRtcpPkt {
- /** Problem indicator, negative values denote packet type that cause problem */
- protected int problem = 0;
- /** Stores the different subclasses of RtcpPkt that make up the compound packet */
- protected LinkedList<RtcpPkt> rtcpPkts = new LinkedList<RtcpPkt>();
-
- /**
- * Instantiates an empty Compound RTCP packet to which you can add RTCP packets
- */
- protected CompRtcpPkt() {
- // Will have to add packets directly to rtcpPkts.
- if(RTPSession.rtpDebugLevel > 7) {
- System.out.println("<-> CompRtcpPkt()");
- }
- }
-
- /**
- * Add a RTCP packet to the compound packet. Pakcets are added in order,
- * so you have to ensure that a Sender Report or Receiver Report is
- * added first.
- *
- * @param aPkt the packet to be added
- */
- protected void addPacket(RtcpPkt aPkt) {
- if(RTPSession.rtpDebugLevel > 11) {
- System.out.println(" <-> CompRtcpPkt.addPacket( "+ aPkt.getClass() + " )");
- }
-
- if(aPkt.problem == 0) {
- rtcpPkts.add(aPkt);
- } else {
- this.problem = aPkt.problem;
- }
- }
-
- /**
- * Picks a received Compound RTCP packet apart.
- *
- * Only SDES packets are processed directly, other packets are
- * parsed and put into aComptRtcpPkt.rtcpPkts, but not
- *
- * Check the aComptRtcpPkt.problem , if the value is non-zero
- * the packets should probably be discarded.
- *
- * @param rawPkt the byte array received from the socket
- * @param packetSize the actual number of used bytes
- * @param adr the socket address from which the packet was received
- * @param rtpSession the RTPSession with the participant database
- */
- protected CompRtcpPkt(byte[] rawPkt, int packetSize, InetSocketAddress adr, RTPSession rtpSession) {
- if(RTPSession.rtcpDebugLevel > 7) {
- System.out.println("-> CompRtcpPkt(" + rawPkt.getClass() + ", size " + packetSize + ", from " + adr.toString() + ", " + rtpSession.getClass() + ")");
- }
- //System.out.println("rawPkt.length:" + rawPkt.length + " packetSize:" + packetSize);
-
- // Chop it up
- int start = 0;
-
- while(start < packetSize && problem == 0) {
- int length = (StaticProcs.bytesToUIntInt(rawPkt, start + 2)) + 1;
-
- if(length*4 + start > rawPkt.length) {
- System.out.println("!!!! CompRtcpPkt.(rawPkt,..,..) length ("+ (length*4+start)
- + ") exceeds size of raw packet ("+rawPkt.length+") !");
- this.problem = -3;
- }
-
- int pktType = (int) rawPkt[start + 1];
-
- if(pktType < 0) {
- pktType += 256;
- }
-
-
- if(start == 0) {
- // Compound packets need to start with SR or RR
- if(pktType != 200 && pktType != 201 ) {
- if(RTPSession.rtcpDebugLevel > 3) {
- System.out.println("!!!! CompRtcpPkt(rawPkt...) packet did not start with SR or RR");
- }
- this.problem = -1;
- }
-
- // Padding bit should be zero for the first packet
- if(((rawPkt[start] & 0x20) >>> 5) == 1) {
- if(RTPSession.rtcpDebugLevel > 3) {
- System.out.println("!!!! CompRtcpPkt(rawPkt...) first packet was padded");
- }
- this.problem = -2;
- }
- }
-
- //System.out.println("start: " + start + " pktType: " + pktType + " length:" + length );
- if(pktType == 200) {
- addPacket(new RtcpPktSR(rawPkt,start,length*4));
- } else if(pktType == 201 ) {
- addPacket(new RtcpPktRR(rawPkt,start, -1));
- } else if(pktType == 202) {
- addPacket(new RtcpPktSDES(rawPkt,start, adr, rtpSession.partDb));
- } else if(pktType == 203 ) {
- addPacket(new RtcpPktBYE(rawPkt,start));
- } else if(pktType == 204) {
- addPacket(new RtcpPktAPP(rawPkt,start));
- } else if(pktType == 205) {
- addPacket(new RtcpPktRTPFB(rawPkt,start, rtpSession));
- } else if(pktType == 206) {
- addPacket(new RtcpPktPSFB(rawPkt,start,rtpSession));
- } else {
- System.out.println("!!!! CompRtcpPkt(byte[] rawPkt, int packetSize...) "
- +"UNKNOWN RTCP PACKET TYPE:" + pktType);
- }
-
- //System.out.println(" start:" + start + " pktType:" + pktType + " length:" + length);
-
- start += length*4;
-
- if(RTPSession.rtcpDebugLevel > 12) {
- System.out.println(" start:"+start+" parsing pktType "+pktType+" length: "+length);
- }
- }
- if(RTPSession.rtcpDebugLevel > 7) {
- System.out.println("<- CompRtcpPkt(rawPkt....)");
- }
- }
-
- /**
- * Encode combines the RTCP packets in this.rtcpPkts into a byte[]
- * by calling the encode() function on each of them individually.
- *
- * The order of rtcpPkts is preserved, so a RR or SR packet must be first.
- *
- * @return the trimmed byte[] representation of the packet, ready to go into a UDP packet.
- */
- protected byte[] encode() {
- if(RTPSession.rtpDebugLevel > 9) {
- System.out.println(" <- CompRtcpPkt.encode()");
- }
-
- ListIterator<RtcpPkt> iter = rtcpPkts.listIterator();
-
- byte[] rawPkt = new byte[1500];
- int index = 0;
-
- while(iter.hasNext()) {
- RtcpPkt aPkt = (RtcpPkt) iter.next();
-
- if(aPkt.packetType == 200) {
- RtcpPktSR pkt = (RtcpPktSR) aPkt;
- pkt.encode();
- System.arraycopy(pkt.rawPkt, 0, rawPkt, index, pkt.rawPkt.length);
- index += pkt.rawPkt.length;
- } else if(aPkt.packetType == 201 ) {
- RtcpPktRR pkt = (RtcpPktRR) aPkt;
- pkt.encode();
- System.arraycopy(pkt.rawPkt, 0, rawPkt, index, pkt.rawPkt.length);
- index += pkt.rawPkt.length;
- } else if(aPkt.packetType == 202) {
- RtcpPktSDES pkt = (RtcpPktSDES) aPkt;
- pkt.encode();
- //System.out.println(" ENCODE SIZE: " + pkt.rawPkt.length);
- System.arraycopy(pkt.rawPkt, 0, rawPkt, index, pkt.rawPkt.length);
- index += pkt.rawPkt.length;
- } else if(aPkt.packetType == 203) {
- RtcpPktBYE pkt = (RtcpPktBYE) aPkt;
- pkt.encode();
- System.arraycopy(pkt.rawPkt, 0, rawPkt, index, pkt.rawPkt.length);
- index += pkt.rawPkt.length;
- } else if(aPkt.packetType == 204) {
- RtcpPktAPP pkt = (RtcpPktAPP) aPkt;
- pkt.encode();
- System.arraycopy(pkt.rawPkt, 0, rawPkt, index, pkt.rawPkt.length);
- index += pkt.rawPkt.length;
- } else if(aPkt.packetType == 205) {
- RtcpPktRTPFB pkt = (RtcpPktRTPFB) aPkt;
- pkt.encode();
- System.arraycopy(pkt.rawPkt, 0, rawPkt, index, pkt.rawPkt.length);
- index += pkt.rawPkt.length;
- } else if(aPkt.packetType == 206) {
- RtcpPktPSFB pkt = (RtcpPktPSFB) aPkt;
- pkt.encode();
- System.arraycopy(pkt.rawPkt, 0, rawPkt, index, pkt.rawPkt.length);
- index += pkt.rawPkt.length;
- } else {
- System.out.println("CompRtcpPkt aPkt.packetType:" + aPkt.packetType);
- }
- //System.out.println(" packetType:" + aPkt.packetType + " length:" + aPkt.rawPkt.length + " index:" + index);
- }
-
- byte[] output = new byte[index];
-
- System.arraycopy(rawPkt, 0, output, 0, index);
-
- if(RTPSession.rtpDebugLevel > 9) {
- System.out.println(" -> CompRtcpPkt.encode()");
- }
- return output;
- }
-}
\ No newline at end of file
--- a/src/jlibrtp/DataFrame.java Thu May 28 14:26:06 2009 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,273 +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;
-
-
-/**
- * Data structure to hold a complete frame if frame reconstruction
- * is enabled, or the data from an individual packet if it is not
- *
- * It also contains most of the data from the individual packets
- * that it is based on.
- *
- * @author Arne Kepp
- */
-public class DataFrame {
- /** The share RTP timestamp */
- private long rtpTimestamp;
- /** The calculated UNIX timestamp, guessed after 2 Sender Reports */
- private long timestamp = -1;
- /** the SSRC from which this frame originated */
- private long SSRC;
- /** contributing CSRCs, only read from the first packet */
- private long[] CSRCs;
- /** RTP payload type */
- private int payloadType;
- /** The marks on individual packets, ordered */
- private boolean[] marks;
- /** Whether any packets were marked or not */
- private boolean anyMarked = false;
- /** Whether the frame contains the expected number of packets */
- private int isComplete = 0;
- //private int dataLength;
- /** The data from the individual packets, ordered */
- private byte[][] data;
- /** The sequence numbers of the individual packets, ordered */
- private int[] seqNum;
- /** The total amount of data bytes in this frame */
- private int totalLength = 0;
- /** The last sequence number in this frame */
- protected int lastSeqNum;
- /** The first sequence number in this frame */
- protected int firstSeqNum;
- /** The number of packets expected for a complete frame */
- protected int noPkts;
-
- /**
- * The usual way to construct a frame is by giving it a PktBufNode,
- * which contains links to all the other pkts that make it up.
- */
- protected DataFrame(PktBufNode aBufNode, Participant p, int noPkts) {
- if(RTPSession.rtpDebugLevel > 6) {
- System.out.println("-> DataFrame(PktBufNode, noPkts = " + noPkts +")");
- }
- this.noPkts = noPkts;
- RtpPkt aPkt = aBufNode.pkt;
- int pktCount = aBufNode.pktCount;
- firstSeqNum = aBufNode.pktCount;
-
- // All this data should be shared, so we just get it from the first one
- this.rtpTimestamp = aBufNode.timeStamp;
- SSRC = aPkt.getSsrc();
- CSRCs = aPkt.getCsrcArray();
-
- // Check whether we can compute an NTPish timestamp? Requires two SR reports
- if(p.ntpGradient > 0) {
- //System.out.print(Long.toString(p.ntpOffset)+" "
- timestamp = p.ntpOffset + (long) (p.ntpGradient*(double)(this.rtpTimestamp-p.lastSRRtpTs));
- }
-
- // Make data the right length
- int payloadLength = aPkt.getPayloadLength();
- //System.out.println("aBufNode.pktCount " + aBufNode.pktCount);
- data = new byte[aBufNode.pktCount][payloadLength];
- seqNum = new int[aBufNode.pktCount];
- marks = new boolean[aBufNode.pktCount];
-
- // Concatenate the data of the packets
- int i;
- for(i=0; i< pktCount; i++) {
- aPkt = aBufNode.pkt;
- byte[] temp = aPkt.getPayload();
- totalLength += temp.length;
- if(temp.length == payloadLength) {
- data[i] = temp;
- } else if(temp.length < payloadLength){
- System.arraycopy(temp, 0, data[i], 0, temp.length);
- } else {
- System.out.println("DataFrame() received node structure with increasing packet payload size.");
- }
- //System.out.println("i " + i + " seqNum[i] " + seqNum[i] + " aBufNode" + aBufNode);
- seqNum[i] = aBufNode.seqNum;
- marks[i] = aBufNode.pkt.isMarked();
- if(marks[i])
- anyMarked = true;
-
- // Get next node
- aBufNode = aBufNode.nextFrameNode;
- }
-
- lastSeqNum = seqNum[i - 1];
-
- if(noPkts > 0) {
- int seqDiff = firstSeqNum - lastSeqNum;
- if(seqDiff < 0)
- seqDiff = (Integer.MAX_VALUE - firstSeqNum) + lastSeqNum;
- if(seqDiff == pktCount && pktCount == noPkts)
- isComplete = 1;
- } else {
- isComplete = -1;
- }
-
- if(RTPSession.rtpDebugLevel > 6) {
- System.out.println("<- DataFrame(PktBufNode, noPkt), data length: " + data.length);
- }
- }
-
- /**
- * Returns a two dimensial array where the first dimension represents individual
- * packets, from which the frame is made up, in order of increasing sequence number.
- * These indeces can be matched to the sequence numbers returned by sequenceNumbers().
- *
- * @return 2-dim array with raw data from packets
- */
- public byte[][] getData() {
- return this.data;
- }
-
- /**
- * Returns a concatenated version of the data from getData()
- * It ignores missing sequence numbers, but then isComplete()
- * will return false provided that RTPAppIntf.frameSize()
- * provides a non-negative number for this payload type.
- *
- * @return byte[] with all the data concatenated
- */
- public byte[] getConcatenatedData() {
- if(this.noPkts < 2) {
- byte[] ret = new byte[this.totalLength];
- int pos = 0;
-
- for(int i=0; i<data.length; i++) {
- int length = data[i].length;
-
- // Last packet may be shorter
- if(pos + length > totalLength)
- length = totalLength - pos;
-
- System.arraycopy(data[i], 0, ret, pos, length);
- pos += data[i].length;
- }
- return ret;
- } else {
- return data[0];
- }
- }
-
- /**
- * If two SR packet have been received jlibrtp will attempt to calculate
- * the local UNIX timestamp (in milliseconds) of all packets received.
- *
- * This value should ideally correspond to the local time when the
- * SSRC sent the packet. Note that the source may not be reliable.
- *
- * Returns -1 if less than two SRs have been received
- *
- * @return the UNIX timestamp, similar to System.currentTimeMillis() or -1;
- */
- public long timestamp() {
- return this.timestamp;
-
- }
-
- /**
- * Returns the RTP timestamp of all the packets in the frame.
- *
- * @return unmodified RTP timestamp
- */
- public long rtpTimestamp() {
- return this.rtpTimestamp;
- }
-
- /**
- * Returns the payload type of the packets
- *
- * @return the payload type of the packets
- */
- public int payloadType() {
- return this.payloadType;
- }
-
- /**
- * Returns an array whose values, for the same index, correpond to the
- * sequence number of the packet from which the data came.
- *
- * This information can be valuable in conjunction with getData(),
- * to identify what parts of a frame are missing.
- *
- * @return array with sequence numbers
- */
- public int[] sequenceNumbers() {
- return seqNum;
- }
-
- /**
- * Returns an array whose values, for the same index, correpond to
- * whether the data was marked or not.
- *
- * This information can be valuable in conjunction with getData().
- *
- * @return array of booleans
- */
- public boolean[] marks() {
- return this.marks;
- }
-
- /**
- * Returns true if any packet in the frame was marked.
- *
- * This function should be used if all your frames fit
- * into single packets.
- *
- * @return true if any packet was marked, false otherwise
- */
- public boolean marked() {
- return this.anyMarked;
- }
-
- /**
- * The SSRC associated with this frame.
- *
- * @return the ssrc that created this frame
- */
- public long ssrc() {
- return this.SSRC;
- }
-
- /**
- * The SSRCs that contributed to this frame
- *
- * @return an array of contributing SSRCs, or null
- */
- public long[] csrcs() {
- return this.CSRCs;
- }
-
- /**
- * Checks whether the difference in sequence numbers corresponds
- * to the number of packets received for the current timestamp,
- * and whether this value corresponds to the expected number of
- * packets.
- *
- * @return true if the right number of packets make up the frame
- */
- public int complete() {
- return this.isComplete;
- }
-}
--- a/src/jlibrtp/DebugAppIntf.java Thu May 28 14:26:06 2009 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,83 +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;
-
-/**
- * DebugAppIntf can be registered on RTPSession to provide simple
- * debugging functionality. This is particularly useful to determine
- * whether the client is receing any data at all.
- *
- * @author Arne Kepp
- *
- */
-
-public interface DebugAppIntf {
- /**
- * This function wil notify you of any packets received, valid or not.
- * Useful for network debugging, and finding bugs in jlibrtp.
- *
- * Type is an integer describing the type of event
- * -2 - Invalid RTCP packet received
- * -1 - Invalid RTP packet received
- * 0 - RTP packet received
- * 1 - RTCP packet received
- *
- * Description is a string that should be meaningful to advanced users, such as
- * "RTP packet received from 127.0.0.1:12312, SSRC: 1380912 , payload type 1, packet size 16 octets"
- * or
- * "Invalid RTP packet received from 127.0.0.1:12312"
- *
- * This function is synchonous and should return quickly.
- *
- * @param type , the type of event, see above.
- * @param socket , taken directly from the UDP packet
- * @param description , see above.
- */
- public void packetReceived(int type, InetSocketAddress socket, String description);
-
- /**
- * This function will notify you of any packets sent from this instance of RTPSession.
- * Useful for network debugging, and finding bugs in jlibrtp.
- *
- * Type is an integer describing the type of event
- * 0 - RTP unicast packet sent
- * 1 - RTP multicast packet sent
- * 2 - RTCP unicast packet sent
- * 3 - RTCP multicast packet sent
- *
- * Description is a string that should be meaningful to advanced users, such as
- *
- * This function is synchonous and should return quickly.
- *
- * @param type , the type of event, see above
- * @param socket , taken directly from the UDP packet
- * @param description , see above
- */
- public void packetSent(int type, InetSocketAddress socket, String description);
-
- /**
- * Other important events that can occur in session
- * -1 SSRC conflict
- * 0 Session is terminating
- * @param type see above
- * @param description , see above
- */
- public void importantEvent(int type, String description);
-}
--- a/src/jlibrtp/LICENSE.txt Thu May 28 14:26:06 2009 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,490 +0,0 @@
- GNU LESSER GENERAL PUBLIC LICENSE
- Version 2.1, February 1999
-
- Copyright (C) 1991, 1999 Free Software Foundation, Inc.
- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
-[This is the first released version of the Lesser GPL. It also counts
- as the successor of the GNU Library Public License, version 2, hence
- the version number 2.1.]
-
- Preamble
-
- The licenses for most software are designed to take away your
-freedom to share and change it. By contrast, the GNU General Public
-Licenses are intended to guarantee your freedom to share and change
-free software--to make sure the software is free for all its users.
-
- This license, the Lesser General Public License, applies to some
-specially designated software packages--typically libraries--of the
-Free Software Foundation and other authors who decide to use it. You
-can use it too, but we suggest you first think carefully about whether
-this license or the ordinary General Public License is the better
-strategy to use in any particular case, based on the explanations below.
-
- When we speak of free software, we are referring to freedom of use,
-not price. Our General Public Licenses are designed to make sure that
-you have the freedom to distribute copies of free software (and charge
-for this service if you wish); that you receive source code or can get
-it if you want it; that you can change the software and use pieces of
-it in new free programs; and that you are informed that you can do
-these things.
-
- To protect your rights, we need to make restrictions that forbid
-distributors to deny you these rights or to ask you to surrender these
-rights. These restrictions translate to certain responsibilities for
-you if you distribute copies of the library or if you modify it.
-
- For example, if you distribute copies of the library, whether gratis
-or for a fee, you must give the recipients all the rights that we gave
-you. You must make sure that they, too, receive or can get the source
-code. If you link other code with the library, you must provide
-complete object files to the recipients, so that they can relink them
-with the library after making changes to the library and recompiling
-it. And you must show them these terms so they know their rights.
-
- We protect your rights with a two-step method: (1) we copyright the
-library, and (2) we offer you this license, which gives you legal
-permission to copy, distribute and/or modify the library.
-
- To protect each distributor, we want to make it very clear that
-there is no warranty for the free library. Also, if the library is
-modified by someone else and passed on, the recipients should know
-that what they have is not the original version, so that the original
-author's reputation will not be affected by problems that might be
-introduced by others.
-
- Finally, software patents pose a constant threat to the existence of
-any free program. We wish to make sure that a company cannot
-effectively restrict the users of a free program by obtaining a
-restrictive license from a patent holder. Therefore, we insist that
-any patent license obtained for a version of the library must be
-consistent with the full freedom of use specified in this license.
-
- Most GNU software, including some libraries, is covered by the
-ordinary GNU General Public License. This license, the GNU Lesser
-General Public License, applies to certain designated libraries, and
-is quite different from the ordinary General Public License. We use
-this license for certain libraries in order to permit linking those
-libraries into non-free programs.
-
- When a program is linked with a library, whether statically or using
-a shared library, the combination of the two is legally speaking a
-combined work, a derivative of the original library. The ordinary
-General Public License therefore permits such linking only if the
-entire combination fits its criteria of freedom. The Lesser General
-Public License permits more lax criteria for linking other code with
-the library.
-
- We call this license the "Lesser" General Public License because it
-does Less to protect the user's freedom than the ordinary General
-Public License. It also provides other free software developers Less
-of an advantage over competing non-free programs. These disadvantages
-are the reason we use the ordinary General Public License for many
-libraries. However, the Lesser license provides advantages in certain
-special circumstances.
-
- For example, on rare occasions, there may be a special need to
-encourage the widest possible use of a certain library, so that it becomes
-a de-facto standard. To achieve this, non-free programs must be
-allowed to use the library. A more frequent case is that a free
-library does the same job as widely used non-free libraries. In this
-case, there is little to gain by limiting the free library to free
-software only, so we use the Lesser General Public License.
-
- In other cases, permission to use a particular library in non-free
-programs enables a greater number of people to use a large body of
-free software. For example, permission to use the GNU C Library in
-non-free programs enables many more people to use the whole GNU
-operating system, as well as its variant, the GNU/Linux operating
-system.
-
- Although the Lesser General Public License is Less protective of the
-users' freedom, it does ensure that the user of a program that is
-linked with the Library has the freedom and the wherewithal to run
-that program using a modified version of the Library.
-
- The precise terms and conditions for copying, distribution and
-modification follow. Pay close attention to the difference between a
-"work based on the library" and a "work that uses the library". The
-former contains code derived from the library, whereas the latter must
-be combined with the library in order to run.
-
- GNU LESSER GENERAL PUBLIC LICENSE
- TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
-
- 0. This License Agreement applies to any software library or other
-program which contains a notice placed by the copyright holder or
-other authorized party saying it may be distributed under the terms of
-this Lesser General Public License (also called "this License").
-Each licensee is addressed as "you".
-
- A "library" means a collection of software functions and/or data
-prepared so as to be conveniently linked with application programs
-(which use some of those functions and data) to form executables.
-
- The "Library", below, refers to any such software library or work
-which has been distributed under these terms. A "work based on the
-Library" means either the Library or any derivative work under
-copyright law: that is to say, a work containing the Library or a
-portion of it, either verbatim or with modifications and/or translated
-straightforwardly into another language. (Hereinafter, translation is
-included without limitation in the term "modification".)
-
- "Source code" for a work means the preferred form of the work for
-making modifications to it. For a library, complete source code means
-all the source code for all modules it contains, plus any associated
-interface definition files, plus the scripts used to control compilation
-and installation of the library.
-
- Activities other than copying, distribution and modification are not
-covered by this License; they are outside its scope. The act of
-running a program using the Library is not restricted, and output from
-such a program is covered only if its contents constitute a work based
-on the Library (independent of the use of the Library in a tool for
-writing it). Whether that is true depends on what the Library does
-and what the program that uses the Library does.
-
- 1. You may copy and distribute verbatim copies of the Library's
-complete source code as you receive it, in any medium, provided that
-you conspicuously and appropriately publish on each copy an
-appropriate copyright notice and disclaimer of warranty; keep intact
-all the notices that refer to this License and to the absence of any
-warranty; and distribute a copy of this License along with the
-Library.
-
- You may charge a fee for the physical act of transferring a copy,
-and you may at your option offer warranty protection in exchange for a
-fee.
-
- 2. You may modify your copy or copies of the Library or any portion
-of it, thus forming a work based on the Library, and copy and
-distribute such modifications or work under the terms of Section 1
-above, provided that you also meet all of these conditions:
-
- a) The modified work must itself be a software library.
-
- b) You must cause the files modified to carry prominent notices
- stating that you changed the files and the date of any change.
-
- c) You must cause the whole of the work to be licensed at no
- charge to all third parties under the terms of this License.
-
- d) If a facility in the modified Library refers to a function or a
- table of data to be supplied by an application program that uses
- the facility, other than as an argument passed when the facility
- is invoked, then you must make a good faith effort to ensure that,
- in the event an application does not supply such function or
- table, the facility still operates, and performs whatever part of
- its purpose remains meaningful.
-
- (For example, a function in a library to compute square roots has
- a purpose that is entirely well-defined independent of the
- application. Therefore, Subsection 2d requires that any
- application-supplied function or table used by this function must
- be optional: if the application does not supply it, the square
- root function must still compute square roots.)
-
-These requirements apply to the modified work as a whole. If
-identifiable sections of that work are not derived from the Library,
-and can be reasonably considered independent and separate works in
-themselves, then this License, and its terms, do not apply to those
-sections when you distribute them as separate works. But when you
-distribute the same sections as part of a whole which is a work based
-on the Library, the distribution of the whole must be on the terms of
-this License, whose permissions for other licensees extend to the
-entire whole, and thus to each and every part regardless of who wrote
-it.
-
-Thus, it is not the intent of this section to claim rights or contest
-your rights to work written entirely by you; rather, the intent is to
-exercise the right to control the distribution of derivative or
-collective works based on the Library.
-
-In addition, mere aggregation of another work not based on the Library
-with the Library (or with a work based on the Library) on a volume of
-a storage or distribution medium does not bring the other work under
-the scope of this License.
-
- 3. You may opt to apply the terms of the ordinary GNU General Public
-License instead of this License to a given copy of the Library. To do
-this, you must alter all the notices that refer to this License, so
-that they refer to the ordinary GNU General Public License, version 2,
-instead of to this License. (If a newer version than version 2 of the
-ordinary GNU General Public License has appeared, then you can specify
-that version instead if you wish.) Do not make any other change in
-these notices.
-
- Once this change is made in a given copy, it is irreversible for
-that copy, so the ordinary GNU General Public License applies to all
-subsequent copies and derivative works made from that copy.
-
- This option is useful when you wish to copy part of the code of
-the Library into a program that is not a library.
-
- 4. You may copy and distribute the Library (or a portion or
-derivative of it, under Section 2) in object code or executable form
-under the terms of Sections 1 and 2 above provided that you accompany
-it with the complete corresponding machine-readable source code, which
-must be distributed under the terms of Sections 1 and 2 above on a
-medium customarily used for software interchange.
-
- If distribution of object code is made by offering access to copy
-from a designated place, then offering equivalent access to copy the
-source code from the same place satisfies the requirement to
-distribute the source code, even though third parties are not
-compelled to copy the source along with the object code.
-
- 5. A program that contains no derivative of any portion of the
-Library, but is designed to work with the Library by being compiled or
-linked with it, is called a "work that uses the Library". Such a
-work, in isolation, is not a derivative work of the Library, and
-therefore falls outside the scope of this License.
-
- However, linking a "work that uses the Library" with the Library
-creates an executable that is a derivative of the Library (because it
-contains portions of the Library), rather than a "work that uses the
-library". The executable is therefore covered by this License.
-Section 6 states terms for distribution of such executables.
-
- When a "work that uses the Library" uses material from a header file
-that is part of the Library, the object code for the work may be a
-derivative work of the Library even though the source code is not.
-Whether this is true is especially significant if the work can be
-linked without the Library, or if the work is itself a library. The
-threshold for this to be true is not precisely defined by law.
-
- If such an object file uses only numerical parameters, data
-structure layouts and accessors, and small macros and small inline
-functions (ten lines or less in length), then the use of the object
-file is unrestricted, regardless of whether it is legally a derivative
-work. (Executables containing this object code plus portions of the
-Library will still fall under Section 6.)
-
- Otherwise, if the work is a derivative of the Library, you may
-distribute the object code for the work under the terms of Section 6.
-Any executables containing that work also fall under Section 6,
-whether or not they are linked directly with the Library itself.
-
- 6. As an exception to the Sections above, you may also combine or
-link a "work that uses the Library" with the Library to produce a
-work containing portions of the Library, and distribute that work
-under terms of your choice, provided that the terms permit
-modification of the work for the customer's own use and reverse
-engineering for debugging such modifications.
-
- You must give prominent notice with each copy of the work that the
-Library is used in it and that the Library and its use are covered by
-this License. You must supply a copy of this License. If the work
-during execution displays copyright notices, you must include the
-copyright notice for the Library among them, as well as a reference
-directing the user to the copy of this License. Also, you must do one
-of these things:
-
- a) Accompany the work with the complete corresponding
- machine-readable source code for the Library including whatever
- changes were used in the work (which must be distributed under
- Sections 1 and 2 above); and, if the work is an executable linked
- with the Library, with the complete machine-readable "work that
- uses the Library", as object code and/or source code, so that the
- user can modify the Library and then relink to produce a modified
- executable containing the modified Library. (It is understood
- that the user who changes the contents of definitions files in the
- Library will not necessarily be able to recompile the application
- to use the modified definitions.)
-
- b) Use a suitable shared library mechanism for linking with the
- Library. A suitable mechanism is one that (1) uses at run time a
- copy of the library already present on the user's computer system,
- rather than copying library functions into the executable, and (2)
- will operate properly with a modified version of the library, if
- the user installs one, as long as the modified version is
- interface-compatible with the version that the work was made with.
-
- c) Accompany the work with a written offer, valid for at
- least three years, to give the same user the materials
- specified in Subsection 6a, above, for a charge no more
- than the cost of performing this distribution.
-
- d) If distribution of the work is made by offering access to copy
- from a designated place, offer equivalent access to copy the above
- specified materials from the same place.
-
- e) Verify that the user has already received a copy of these
- materials or that you have already sent this user a copy.
-
- For an executable, the required form of the "work that uses the
-Library" must include any data and utility programs needed for
-reproducing the executable from it. However, as a special exception,
-the materials to be distributed need not include anything that is
-normally distributed (in either source or binary form) with the major
-components (compiler, kernel, and so on) of the operating system on
-which the executable runs, unless that component itself accompanies
-the executable.
-
- It may happen that this requirement contradicts the license
-restrictions of other proprietary libraries that do not normally
-accompany the operating system. Such a contradiction means you cannot
-use both them and the Library together in an executable that you
-distribute.
-
- 7. You may place library facilities that are a work based on the
-Library side-by-side in a single library together with other library
-facilities not covered by this License, and distribute such a combined
-library, provided that the separate distribution of the work based on
-the Library and of the other library facilities is otherwise
-permitted, and provided that you do these two things:
-
- a) Accompany the combined library with a copy of the same work
- based on the Library, uncombined with any other library
- facilities. This must be distributed under the terms of the
- Sections above.
-
- b) Give prominent notice with the combined library of the fact
- that part of it is a work based on the Library, and explaining
- where to find the accompanying uncombined form of the same work.
-
- 8. You may not copy, modify, sublicense, link with, or distribute
-the Library except as expressly provided under this License. Any
-attempt otherwise to copy, modify, sublicense, link with, or
-distribute the Library is void, and will automatically terminate your
-rights under this License. However, parties who have received copies,
-or rights, from you under this License will not have their licenses
-terminated so long as such parties remain in full compliance.
-
- 9. You are not required to accept this License, since you have not
-signed it. However, nothing else grants you permission to modify or
-distribute the Library or its derivative works. These actions are
-prohibited by law if you do not accept this License. Therefore, by
-modifying or distributing the Library (or any work based on the
-Library), you indicate your acceptance of this License to do so, and
-all its terms and conditions for copying, distributing or modifying
-the Library or works based on it.
-
- 10. Each time you redistribute the Library (or any work based on the
-Library), the recipient automatically receives a license from the
-original licensor to copy, distribute, link with or modify the Library
-subject to these terms and conditions. You may not impose any further
-restrictions on the recipients' exercise of the rights granted herein.
-You are not responsible for enforcing compliance by third parties with
-this License.
-
- 11. If, as a consequence of a court judgment or allegation of patent
-infringement or for any other reason (not limited to patent issues),
-conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License. If you cannot
-distribute so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you
-may not distribute the Library at all. For example, if a patent
-license would not permit royalty-free redistribution of the Library by
-all those who receive copies directly or indirectly through you, then
-the only way you could satisfy both it and this License would be to
-refrain entirely from distribution of the Library.
-
-If any portion of this section is held invalid or unenforceable under any
-particular circumstance, the balance of the section is intended to apply,
-and the section as a whole is intended to apply in other circumstances.
-
-It is not the purpose of this section to induce you to infringe any
-patents or other property right claims or to contest validity of any
-such claims; this section has the sole purpose of protecting the
-integrity of the free software distribution system which is
-implemented by public license practices. Many people have made
-generous contributions to the wide range of software distributed
-through that system in reliance on consistent application of that
-system; it is up to the author/donor to decide if he or she is willing
-to distribute software through any other system and a licensee cannot
-impose that choice.
-
-This section is intended to make thoroughly clear what is believed to
-be a consequence of the rest of this License.
-
- 12. If the distribution and/or use of the Library is restricted in
-certain countries either by patents or by copyrighted interfaces, the
-original copyright holder who places the Library under this License may add
-an explicit geographical distribution limitation excluding those countries,
-so that distribution is permitted only in or among countries not thus
-excluded. In such case, this License incorporates the limitation as if
-written in the body of this License.
-
- 13. The Free Software Foundation may publish revised and/or new
-versions of the Lesser General Public License from time to time.
-Such new versions will be similar in spirit to the present version,
-but may differ in detail to address new problems or concerns.
-
-Each version is given a distinguishing version number. If the Library
-specifies a version number of this License which applies to it and
-"any later version", you have the option of following the terms and
-conditions either of that version or of any later version published by
-the Free Software Foundation. If the Library does not specify a
-license version number, you may choose any version ever published by
-the Free Software Foundation.
-
- 14. If you wish to incorporate parts of the Library into other free
-programs whose distribution conditions are incompatible with these,
-write to the author to ask for permission. For software which is
-copyrighted by the Free Software Foundation, write to the Free
-Software Foundation; we sometimes make exceptions for this. Our
-decision will be guided by the two goals of preserving the free status
-of all derivatives of our free software and of promoting the sharing
-and reuse of software generally.
-
- NO WARRANTY
-
- 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
-WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
-EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
-OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
-KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
-LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
-THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
-
- 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
-WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
-AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
-FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
-CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
-LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
-RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
-FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
-SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
-DAMAGES.
-
- END OF TERMS AND CONDITIONS
-
- How to Apply These Terms to Your New Libraries
-
- If you develop a new library, and you want it to be of the greatest
-possible use to the public, we recommend making it free software that
-everyone can redistribute and change. You can do so by permitting
-redistribution under these terms (or, alternatively, under the terms of the
-ordinary General Public License).
-
- To apply these terms, attach the following notices to the library. It is
-safest to attach them to the start of each source file to most effectively
-convey the exclusion of warranty; and each file should have at least the
-"copyright" line and a pointer to where the full notice is found.
-
- <one line to give the library's name and a brief idea of what it does.>
- Copyright (C) <year> <name of author>
-
- 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
-
-
--- a/src/jlibrtp/Participant.java Thu May 28 14:26:06 2009 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,437 +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 <b>unicast</b> 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);
- }
-}
--- a/src/jlibrtp/ParticipantDatabase.java Thu May 28 14:26:06 2009 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,256 +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.util.*;
-import java.util.concurrent.*;
-
-/**
- * The participant database maintains three hashtables with participants.
- *
- * The key issue is to be fast for operations that happen every time an
- * RTP packet is sent or received. We allow linear searching in cases
- * where we need to update participants with information.
- *
- * The keying is therefore usually the SSRC. In cases where we have the
- * cname, but no SSRC is known (no SDES packet has been received), a
- * simple hash i calculated based on the CNAME. The RTCP code should,
- * when receiving SDES packets, check whether the participant is known
- * and update the copy in this database with SSRC if needed.
- *
- * @author Arne Kepp
- */
-public class ParticipantDatabase {
- /** The parent RTP Session */
- RTPSession rtpSession = null;
- /**
- * A linked list to hold participants explicitly added by the application
- * In unicast mode this is the list used for RTP and RTCP transmission,
- * in multicast it should not be in use.
- */
- LinkedList<Participant> receivers = new LinkedList<Participant>();
- /**
- * The hashtable holds participants added through received RTP and RTCP packets,
- * as well as participants that have been linked to an SSRC by ip address (in unicast mode).
- */
- ConcurrentHashMap<Long,Participant> ssrcTable = new ConcurrentHashMap<Long,Participant>();
-
- /**
- * Simple constructor
- *
- * @param parent parent RTPSession
- */
- protected ParticipantDatabase(RTPSession parent) {
- rtpSession = parent;
- }
-
- /**
- *
- * @param cameFrom 0: Application, 1: RTP packet, 2: RTCP
- * @param p the participant
- * @return 0 if okay, -1 if not
- */
- protected int addParticipant(int cameFrom, Participant p) {
- //Multicast or not?
- if(this.rtpSession.mcSession) {
- return this.addParticipantMulticast(cameFrom, p);
- } else {
- return this.addParticipantUnicast(cameFrom, p);
- }
-
- }
-
- /**
- * Add a multicast participant to the database
- *
- * @param cameFrom 0: Application, 1,2: discovered through RTP or RTCP
- * @param p the participant to add
- * @return 0 if okay, -2 if redundant, -1 if adding participant to multicast
- */
- private int addParticipantMulticast(int cameFrom, Participant p) {
- if( cameFrom == 0) {
- System.out.println("ParticipantDatabase.addParticipant() doesnt expect"
- + " application to add participants to multicast session.");
- return -1;
- } else {
- // Check this one is not redundant
- if(this.ssrcTable.contains(p.ssrc)) {
- System.out.println("ParticipantDatabase.addParticipant() SSRC "
- +"already known " + Long.toString(p.ssrc));
- return -2;
- } else {
- this.ssrcTable.put(p.ssrc, p);
- return 0;
- }
- }
- }
-
- /**
- * Add a unicast participant to the database
- *
- * Result will be reported back through tpSession.appIntf.userEvent
- *
- * @param cameFrom 0: Application, 1,2: discovered through RTP or RTCP
- * @param p the participant to add
- * @return 0 if new, 1 if
- */
- private int addParticipantUnicast(int cameFrom, Participant p) {
- if(cameFrom == 0) {
- //Check whether there is a match in the ssrcTable
- boolean notDone = true;
-
- Enumeration<Participant> enu = this.ssrcTable.elements();
- while(notDone && enu.hasMoreElements()) {
- Participant part = enu.nextElement();
- if(part.unexpected &&
- (part.rtcpReceivedFromAddress.equals(part.rtcpAddress.getAddress())
- || part.rtpReceivedFromAddress.equals(part.rtpAddress.getAddress()))) {
-
- part.rtpAddress = p.rtpAddress;
- part.rtcpAddress = p.rtcpAddress;
- part.unexpected = false;
-
- //Report the match back to the application
- Participant[] partArray = {part};
- this.rtpSession.appIntf.userEvent(5, partArray);
-
- notDone = false;
- p = part;
- }
- }
-
- //Add to the table of people that we send packets to
- this.receivers.add(p);
- return 0;
-
- } else {
- //Check whether there's a match in the receivers table
- boolean notDone = true;
- //System.out.println("GOT " + p.cname);
- Iterator<Participant> iter = this.receivers.iterator();
-
- while(notDone && iter.hasNext()) {
- Participant part = iter.next();
-
- //System.out.println(part.rtpAddress.getAddress().toString()
- // + " " + part.rtcpAddress.getAddress().toString()
- // + " " + p.rtpReceivedFromAddress.getAddress().toString()
- // + " " + p.rtcpReceivedFromAddress.getAddress().toString());
-
- //System.out.println(" HUUHHHH? " + p.rtcpReceivedFromAddress.getAddress().equals(part.rtcpAddress.getAddress()));
- if((cameFrom == 1 && p.rtpReceivedFromAddress.getAddress().equals(part.rtpAddress.getAddress()))
- || (cameFrom == 2 && p.rtcpReceivedFromAddress.getAddress().equals(part.rtcpAddress.getAddress()))) {
-
- part.rtpReceivedFromAddress = p.rtpReceivedFromAddress;
- part.rtcpReceivedFromAddress = p.rtcpReceivedFromAddress;
-
- // Move information
- part.ssrc = p.ssrc;
- part.cname = p.cname;
- part.name = p.name;
- part.loc = p.loc;
- part.phone = p.phone;
- part.email = p.email;
- part.note = p.note;
- part.tool = p.tool;
- part.priv = p.priv;
-
- this.ssrcTable.put(part.ssrc, part);
-
- //Report the match back to the application
- Participant[] partArray = {part};
- this.rtpSession.appIntf.userEvent(5, partArray);
- return 0;
- }
- }
-
- // No match? ok
- this.ssrcTable.put(p.ssrc, p);
- return 0;
- }
- }
-
- /**
- * Remove a participant from all tables
- *
- * @param p the participant to be removed
- */
- protected void removeParticipant(Participant p) {
- if(! this.rtpSession.mcSession)
- this.receivers.remove(p);
-
- this.ssrcTable.remove(p.ssrc, p);
- }
-
- /**
- * Find a participant based on the ssrc
- *
- * @param ssrc of the participant to be found
- * @return the participant, null if unknonw
- */
- protected Participant getParticipant(long ssrc) {
- Participant p = null;
- p = ssrcTable.get(ssrc);
- return p;
- }
-
- /**
- * Iterator for all the unicast receivers.
- *
- * This one is used by both RTP for sending packets, as well as RTCP.
- *
- * @return iterator for unicast participants
- */
- protected Iterator<Participant> getUnicastReceivers() {
- if(! this.rtpSession.mcSession) {
- return this.receivers.iterator();
- } else {
- System.out.println("Request for ParticipantDatabase.getUnicastReceivers in multicast session");
- return null;
- }
- }
-
- /**
- * Enumeration of all the participants with known ssrcs.
- *
- * This is primarily used for sending packets in multicast sessions.
- *
- * @return enumerator with all the participants with known SSRCs
- */
- protected Enumeration<Participant> getParticipants() {
- return this.ssrcTable.elements();
- }
-
- protected void debugPrint() {
- System.out.println(" ParticipantDatabase.debugPrint()");
- Participant p;
- Enumeration enu = ssrcTable.elements();
- while(enu.hasMoreElements()) {
- p = (Participant) enu.nextElement();
- System.out.println(" ssrcTable ssrc:"+p.ssrc+" cname:"+p.cname
- +" loc:"+p.loc+" rtpAddress:"+p.rtpAddress+" rtcpAddress:"+p.rtcpAddress);
- }
-
- Iterator<Participant> iter = receivers.iterator();
- while(iter.hasNext()) {
- p = iter.next();
- System.out.println(" receivers: "+p.rtpAddress.toString());
- }
- }
-}
--- a/src/jlibrtp/PktBufNode.java Thu May 28 14:26:06 2009 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,57 +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;
-
-/**
- * This is a four-directional data structures used for
- * the frame buffer, i.e. buffer for pkts that need
- * to be assimilated into complete frames.
- *
- * All the actual work is done by PktBuffer.
- *
- * @author Arne Kepp
- *
- */
-public class PktBufNode {
- /** The next node (RTP Timestamp), looking from the back -> next means older */
- protected PktBufNode nextFrameQueueNode = null;
- /** The previous node (RTP Timestmap), looking from the back -> prev means newer */
- protected PktBufNode prevFrameQueueNode = null;
- /** The next node within the frame, i.e. higher sequence number, same RTP timestamp */
- protected PktBufNode nextFrameNode = null;
- /** Number of packets with the same RTP timestamp */
- protected int pktCount;
- /** The RTP timeStamp associated with this node */
- protected long timeStamp;
- /** The sequence number associated with this node */
- protected int seqNum;
- /** The payload, a parsed RTP Packet */
- protected RtpPkt pkt = null;
-
- /**
- * Create a new packet buffer node based on a packet
- * @param aPkt the packet
- */
- protected PktBufNode(RtpPkt aPkt) {
- pkt = aPkt;
- timeStamp = aPkt.getTimeStamp();
- seqNum = aPkt.getSeqNumber();
- pktCount = 1;
- }
-}
--- a/src/jlibrtp/PktBuffer.java Thu May 28 14:26:06 2009 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,473 +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;
-
-/**
- * A PktBuffer stores packets either for buffering purposes,
- * or because they need to be assimilated to create a complete frame.
- *
- * This behavior can be controlled through rtpSession.pktBufBehavior()
- *
- * It optionally drops duplicate packets.
- *
- * Note that newest is the most recently received, i.e. highest timeStamp
- * Next means new to old (from recently received to previously received)
- *
- * @author Arne Kepp
- */
-public class PktBuffer {
- /** The RTPSession holds information common to all packetBuffers, such as max size */
- RTPSession rtpSession;
- /** SSRC of the the participant that this buffer is for */
- long SSRC;
- /** The parent participant */
- Participant p;
- /** The length of the buffer */
- int length = 0;
- /** The oldest, least recently received, packet */
- PktBufNode oldest = null;
- /** The newest, most recently received, packet */
- PktBufNode newest = null;
-
- /** The last sequence number received */
- int lastSeqNumber = -1;
- /** The last timestamp */
- long lastTimestamp = -1;
-
- /**
- * Creates a new PktBuffer, a linked list of PktBufNode
- *
- * @param rtpSession the parent RTPSession
- * @param p the participant to which this packetbuffer belongs.
- * @param aPkt The first RTP packet, to be added to the buffer
- */
- protected PktBuffer(RTPSession rtpSession, Participant p, RtpPkt aPkt) {
- this.rtpSession = rtpSession;
- this.p = p;
- SSRC = aPkt.getSsrc();
- PktBufNode newNode = new PktBufNode(aPkt);
- oldest = newNode;
- newest = newNode;
- //lastSeqNumber = (aPkt.getSeqNumber() - 1);
- //lastTimestamp = aPkt.getTimeStamp();
- length = 1;
- }
-
- /**
- * Adds a packet, this happens in constant time if they arrive in order.
- * Optimized for the case where each pkt is a complete frame.
- *
- * @param aPkt the packet to be added to the buffer.
- * @return integer, negative if operation failed (see code)
- */
- protected synchronized int addPkt(RtpPkt aPkt) {
- if(aPkt == null) {
- System.out.println("! PktBuffer.addPkt(aPkt) aPkt was null");
- return -5;
- }
-
- long timeStamp = aPkt.getTimeStamp();
- if(RTPSession.rtpDebugLevel > 7) {
- System.out.println("-> PktBuffer.addPkt() , length:" + length + " , timeStamp of Pkt: " + Long.toString(timeStamp));
- }
-
-
- PktBufNode newNode = new PktBufNode(aPkt);
- if(aPkt.getSsrc() != SSRC) {
- System.out.println("PktBuffer.addPkt() SSRCs don't match!");
- }
-
- int retVal = 0;
- if(this.rtpSession.pktBufBehavior > 0) {
- retVal = bufferedAddPkt(newNode);
- } else if(this.rtpSession.pktBufBehavior == 0) {
- retVal = filteredAddPkt(newNode);
- } else if(this.rtpSession.pktBufBehavior == -1) {
- retVal = unfilteredAddPkt(newNode);
- }
-
-
- if(RTPSession.rtpDebugLevel > 7) {
- if(RTPSession.rtpDebugLevel > 10) {
- this.debugPrint();
- }
- System.out.println("<- PktBuffer.addPkt() , length:" + length + " returning " + retVal);
- }
- return retVal;
- }
-
- /**
- * Adds packets in the same order that they arrive,
- * doesn't do any filering or processing.
- *
- * @param newNode the node to add to the packet buffer
- * @return 0 if everything is okay, -1 otherwise
- */
- private int unfilteredAddPkt(PktBufNode newNode) {
- if(RTPSession.rtpDebugLevel > 8) {
- System.out.println("<-> PktBuffer.unfilteredAddPkt()");
- }
- //No magic, just add to the end
- if(oldest != null) {
- oldest.nextFrameQueueNode = newNode;
- newNode.prevFrameQueueNode = oldest;
- oldest = newNode;
- } else {
- oldest = newNode;
- newest = newNode;
- }
- return 0;
- }
-
- /**
- * Takes care of duplicate packets
- *
- * @param newNode the node to add to the packet buffer
- * @return 0 if everything is okay, -1 otherwise
- */
- private int filteredAddPkt(PktBufNode newNode) {
- if(RTPSession.rtpDebugLevel > 8) {
- System.out.println("<-> PktBuffer.filteredAddPkt()");
- }
-
- if(length == 0) {
- // The buffer was empty, this packet is the one and only.
- newest = newNode;
- oldest = newNode;
- length = 1;
- } else {
- // The packetbuffer is not empty.
- if(newNode.timeStamp > newest.timeStamp || newNode.seqNum > newest.seqNum && (newNode.seqNum - newest.seqNum) < 10) {
- // Packet came in order
- newNode.nextFrameQueueNode = newest;
- newest.prevFrameQueueNode = newNode;
- newest = newNode;
- length++;
- } else {
- if(RTPSession.rtpDebugLevel > 2) {
- System.out.println("PktBuffer.filteredAddPkt Dropped a packet due to lag! " + newNode.timeStamp + " "
- + newNode.seqNum + " vs "+ oldest.timeStamp + " " + oldest.seqNum);
- }
- return -1;
- }
- }
-
- return 0;
- }
-
- /**
- * Does most of the packet organization for the application.
- * Packets are put in order, duplicate packets or late arrivals are discarded
- *
- * If multiple packets make up a frame, these will also be organized
- * by RTP timestamp and sequence number, and returned as a complete frame.
- *
- * @param newNode the node to add to the packet buffer
- * @return 0 if everything is okay, -1 otherwise
- */
- private int bufferedAddPkt(PktBufNode newNode) {
- if(RTPSession.rtpDebugLevel > 8) {
- System.out.println("<-> PktBuffer.bufferedAddPkt()");
- }
- if(length == 0) {
- // The buffer was empty, this packet is the one and only.
- newest = newNode;
- oldest = newNode;
- } else {
- // The packetbuffer is not empty.
- if(newNode.timeStamp > newest.timeStamp || newNode.seqNum > newest.seqNum) {
- // Packet came in order
- newNode.nextFrameQueueNode = newest;
- newest.prevFrameQueueNode = newNode;
- newest = newNode;
- } else {
- //There are packets, we need to order this one right.
- if(! pktOnTime(newNode.timeStamp, newNode.seqNum) && rtpSession.pktBufBehavior > -1) {
- // We got this too late, can't put it in order anymore.
- if(RTPSession.rtpDebugLevel > 2) {
- System.out.println("PktBuffer.addPkt Dropped a packet due to lag! " + newNode.timeStamp + " "
- + newNode.seqNum + " vs "+ oldest.timeStamp + " " + oldest.seqNum);
- }
- return -1;
- }
-
- //Need to do some real work, find out where it belongs (linear search from the back).
- PktBufNode tmpNode = newest;
- while(tmpNode.timeStamp > newNode.timeStamp) {
- tmpNode = tmpNode.nextFrameQueueNode;
- }
-
- if( tmpNode.timeStamp == newNode.timeStamp
- && rtpSession.frameReconstruction
- && newNode.seqNum != tmpNode.seqNum) {
- //Packet has same timestamp, presumably belongs to frame. Need to order within frame.
- if(RTPSession.rtpDebugLevel > 8) {
- System.out.println("Found pkt with existing timeStamp: " + newNode.timeStamp);
- }
- int ret = addToFrame(tmpNode, newNode);
- if(ret != 0) {
- return ret;
- }
- } else {
-
- // Check that it's not a duplicate
- if(tmpNode.timeStamp == newNode.timeStamp && newNode.seqNum == tmpNode.seqNum) {
- if(RTPSession.rtpDebugLevel > 2) {
- System.out.println("PktBuffer.addPkt Dropped a duplicate packet! "
- + newNode.timeStamp + " " + newNode.seqNum );
- }
- return -1;
- }
-
- // Insert into buffer
- newNode.nextFrameQueueNode = tmpNode;
- newNode.prevFrameQueueNode = tmpNode.prevFrameQueueNode;
-
- // Update the node behind
- if(newNode.prevFrameQueueNode != null) {
- newNode.prevFrameQueueNode.nextFrameQueueNode = newNode;
- }
- tmpNode.prevFrameQueueNode = newNode;
-
- if(newNode.timeStamp > newest.timeStamp) {
- newest = newNode;
- }
- }
- }
- }
- // Update the length of this buffer
- length++;
- return 0;
- }
-
- /**
- *
- * @param frameNode the node currently representing the frame in the packet buffer
- * @param newNode the new node to be added to the frame
- * @return 0 if no error, -2 if this is a duplicate packet
- */
- private int addToFrame(PktBufNode frameNode, PktBufNode newNode) {
- // Node has same timeStamp, assume pkt belongs to frame
-
- if(frameNode.seqNum < newNode.seqNum) {
- // this is not the first packet in the frame
- frameNode.pktCount++;
-
- // Find the right spot
- while( frameNode.nextFrameNode != null
- && frameNode.nextFrameNode.seqNum < newNode.seqNum) {
- frameNode = frameNode.nextFrameNode;
- }
-
- // Check whether packet is duplicate
- if(frameNode.nextFrameNode != null
- && frameNode.nextFrameNode.seqNum == newNode.seqNum) {
- if(RTPSession.rtpDebugLevel > 2) {
- System.out.println("PktBuffer.addPkt Dropped a duplicate packet!");
- }
- return -2;
- }
-
- newNode.nextFrameNode = frameNode.nextFrameNode;
- frameNode.nextFrameNode = newNode;
-
- } else {
- // newNode has the lowest sequence number
- newNode.nextFrameNode = frameNode;
- newNode.pktCount = frameNode.pktCount + 1;
-
- //Update the queue
- if(frameNode.nextFrameQueueNode != null) {
- frameNode.nextFrameQueueNode.prevFrameQueueNode = newNode;
- newNode.nextFrameQueueNode = frameNode.nextFrameQueueNode;
- frameNode.nextFrameQueueNode = null;
- }
- if(frameNode.prevFrameQueueNode != null) {
- frameNode.prevFrameQueueNode.nextFrameQueueNode = newNode;
- newNode.prevFrameQueueNode = frameNode.prevFrameQueueNode;
- frameNode.prevFrameQueueNode = null;
- }
- if(newest.timeStamp == newNode.timeStamp) {
- newest = newNode;
- }
- }
-
- return 0;
- }
-
- /**
- * Checks the oldest frame, if there is one, sees whether it is complete.
- * @return Returns null if there are no complete frames available.
- */
- protected synchronized DataFrame popOldestFrame() {
- if(RTPSession.rtpDebugLevel > 7) {
- System.out.println("-> PktBuffer.popOldestFrame()");
- }
- if(RTPSession.rtpDebugLevel > 10) {
- this.debugPrint();
- }
-
- if(this.rtpSession.pktBufBehavior > 0) {
- return this.bufferedPopFrame();
- } else {
- return this.unbufferedPopFrame();
- }
- }
-
- /**
- * Will return the oldest frame without checking whether it is in
- * the right order, or whether we should wate for late arrivals.
- *
- * @return the first frame on the queue, null otherwise
- */
- private DataFrame unbufferedPopFrame() {
- if(oldest != null) {
- PktBufNode retNode = oldest;
-
- popFrameQueueCleanup(retNode, retNode.seqNum);
-
- return new DataFrame(retNode, this.p,
- rtpSession.appIntf.frameSize(retNode.pkt.getPayloadType()));
- } else {
- return null;
- }
- }
-
- /**
- * Only returns if the buffer is full, i.e. length exceeds
- * rtpSession.pktBufBehavior, or if the next packet directly
- * follows the previous one returned to the application.
- *
- * @return first frame in order, null otherwise
- */
- private DataFrame bufferedPopFrame() {
- PktBufNode retNode = oldest;
- /**
- * Three scenarios:
- * 1) There are no packets available
- * 2) The first packet is vailable and in order
- * 3) The first packet is not the next on in the sequence
- * a) We have exceeded the wait buffer
- * b) We wait
- */
- //System.out.println(" Debug:" +(retNode != null) + " " + (retNode.seqNum == this.lastSeqNumber + 1)
- // + " " + ( retNode.seqNum == 0 ) + " " + (this.length > this.rtpSession.maxReorderBuffer)
- // + " " + (this.lastSeqNumber < 0));
-
- // Pop it off, null all references.
- if( retNode != null && (retNode.seqNum == this.lastSeqNumber + 1 || retNode.seqNum == 0
- || this.length > this.rtpSession.pktBufBehavior || this.lastSeqNumber < 0)) {
-
-
- //if(tmpNode.pktCount == compLen) {
- if(RTPSession.rtpDebugLevel > 7) {
- System.out.println("<- PktBuffer.popOldestFrame() returns frame");
- }
-
- DataFrame df = new DataFrame(retNode, this.p,
- rtpSession.appIntf.frameSize(oldest.pkt.getPayloadType()));
-
- //DataFrame df = new DataFrame(retNode, this.p, 1);
- popFrameQueueCleanup(retNode, df.lastSeqNum);
-
- return df;
-
- } else {
- // If we get here we have little to show for.
- if(RTPSession.rtpDebugLevel > 2) {
- System.out.println("<- PktBuffer.popOldestFrame() returns null " + retNode.seqNum + " " + this.lastSeqNumber);
- this.debugPrint();
- }
- return null;
- }
- }
-
- /**
- * Cleans the packet buffer before returning the frame,
- * i.e. making sure the queue has a head etc.
- *
- * @param retNode the node that is about to be popped
- * @param highestSeq the highest sequence number returned to the application
- */
- private void popFrameQueueCleanup(PktBufNode retNode, int highestSeq) {
- if(1 == length) {
- //There's only one frame
- newest = null;
- oldest = null;
- } else {
- //There are more frames
- oldest = oldest.prevFrameQueueNode;
- oldest.nextFrameQueueNode = null;
- }
-
- // Update counters
- length--;
-
- //Find the highest sequence number associated with this timestamp
- this.lastSeqNumber = highestSeq;
- this.lastTimestamp = retNode.timeStamp;
- }
-
- /**
- * Returns the length of the packetbuffer.
- * @return number of frames (complete or not) in packetbuffer.
- */
- protected int getLength() {
- return length;
- }
-
- /**
- * Checks whether a packet is not too late, i.e. the next packet has already been returned.
- * @param timeStamp the RTP timestamp of the packet under consideration
- * @param seqNum the sequence number of the packet under consideration
- * @return true if newer packets have not been handed to the application
- */
- protected boolean pktOnTime(long timeStamp, int seqNum) {
- if(this.lastSeqNumber == -1) {
- // First packet
- return true;
- } else {
- if(seqNum >= this.lastSeqNumber) {
- if(this.lastSeqNumber < 3 && timeStamp < this.lastTimestamp ) {
- return false;
- }
- } else {
- if(seqNum > 3 || timeStamp < this.lastTimestamp) {
- return false;
- }
- }
- }
- return true;
- }
-
- /**
- * Prints out the packet buffer, oldest node first (on top).
- */
- protected void debugPrint() {
- System.out.println("PktBuffer.debugPrint() : length "+length+" SSRC "+SSRC+" lastSeqNum:"+lastSeqNumber);
- PktBufNode tmpNode = oldest;
- int i = 0;
- while(tmpNode != null) {
- //String str = tmpNode.timeStamp.toString();
- System.out.println(" " + i + " seqNum:"+tmpNode.seqNum+" timeStamp: " + tmpNode.timeStamp + " pktCount:" + tmpNode.pktCount );
- i++;
- tmpNode = tmpNode.prevFrameQueueNode;
- }
- }
-}
--- a/src/jlibrtp/README.txt Thu May 28 14:26:06 2009 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,39 +0,0 @@
-jlibrtp - Java RTP Library
-
-Kepp, Arne
-ak2618@columbia.edu
-
-Columbia University
-New York, NY 10027
-USA
-
-This library was started as a term project in VoIP Security, a class taught by
-Prof. Henning Schulzrinne at Columbia University. Version 0.1 (not released as such)
-was written by Vaishnav Janardhan (vj2135@columbia.edu) and Arne Kepp (ak2618@columbia.edu).
-
-This version was rewritten by Arne Kepp, as a student project under the supervision of
-Prof. Henning Schulzrinne, Columbia University.
-
-------Abstract
-jlibrtp is a library that implements the Real-Time Transport Protocol (RTP),
-a well-established standard for streaming media across IP-based networks, in Java.
-The purpose of this library is to make it easy for application developers to
-create applications for peer to peer streaming of audio, video and other data.
-In addition, developers will need a protocol to establish contact with peers,
-such as Session Initialization Protocol (SIP) and/or SDP.
-
-The library accepts any kind of binary data, handles packet parsing and reordering,
-maintains a participant database and the control connection associated with the
-protocol. The application is notified of received data through a callback-interface.
-The library supports IPv4, IPv6 and multicast. It does currently not support encryption,
-and should not be used in cases where confidentiality is important before this has
-been remedied.
-
-Please refer to http://jlibrtp.org for more information and newer versions.
-
-The library requires Sun Microsystems Java 1.5.0 or greater, or equivalent.
-
-The Library is licensed under the GNU Lesser General Public License, see LICENSE.txt
-
-The demonstration programs can be compiled as follows:
-javac ./jlibrtpDemos/SoundSenderDemo.java jlibrtp/*.java
\ No newline at end of file
--- a/src/jlibrtp/RTCPAVPFIntf.java Thu May 28 14:26:06 2009 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,96 +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;
-
-
-/**
- * This is the callback interface for the AVPF profile (RFC 4585)
- *
- * It is optional, you do not have to register it.
- *
- * If there are specific events you wish to ignore,
- * you can simply implement empty functions.
- *
- * These are all syncrhonous, make sure to return quickly
- * or do the handling in a new thread.
- *
- * @author Arne Kepp
- */
-public interface RTCPAVPFIntf {
-
- /**
- * This function is called when a
- * Picture Loss Indication (PLI, FMT = 1) is received
- *
- * @param ssrcPacketSender the SSRC of the participant reporting loss of picture
- */
- public void PSFBPktPictureLossReceived(
- long ssrcPacketSender);
-
- /**
- * This function is called when a
- * Slice Loss Indication (SLI, FMT=2) is received
- *
- * @param ssrcPacketSender the SSRC of the participant reporting loss of slice(s)
- * @param sliceFirst macroblock address of first macroblock
- * @param sliceNumber number of lost macroblocks, in scan order
- * @param slicePictureId the six least significant bits of the picture identifier
- */
- public void PSFBPktSliceLossIndic(
- long ssrcPacketSender,
- int[] sliceFirst, int[] sliceNumber, int[] slicePictureId);
-
- /**
- * This function is called when a
- * Reference Picture Selection Indication (RPSI, FMT=3) is received
- *
- * @param ssrcPacketSender the SSRC of the participant reporting the selection
- * @param rpsiPayloadType the RTP payload type related to the RPSI bit string
- * @param rpsiBitString the RPSI information as natively defined by the video codec
- * @param rpsiPaddingBits the number of padding bits at the end of the string
- */
- public void PSFBPktRefPictureSelIndic(
- long ssrcPacketSender,
- int rpsiPayloadType, byte[] rpsiBitString, int rpsiPaddingBits);
-
- /**
- * This function is called when a
- * Transport Layer Feedback Messages is received
- *
- * @param ssrcPacketSender
- * @param alfBitString
- */
- public void PSFBPktAppLayerFBReceived(
- long ssrcPacketSender,
- byte[] alfBitString);
-
- /**
- * This function is called when a
- * Transport Layer Feedback Messages is received
- *
- * @param ssrcPacketSender
- * @param FMT 1: NACK, 0,2-30: unassigned, 31: reserved
- * @param packetID the RTP sequence number of the lost packet
- * @param bitmaskLostPackets the bitmask of following lost packets
- */
- public void RTPFBPktReceived(
- long ssrcPacketSender,
- int FMT, int[] packetID, int[] bitmaskLostPackets);
-}
\ No newline at end of file
--- a/src/jlibrtp/RTCPAppIntf.java Thu May 28 14:26:06 2009 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,118 +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;
-
-
-/**
- * This is the callback interface for RTCP packets.
- *
- * It is optional, you do not have to register it.
- *
- * If there are specific events you wish to ignore,
- * you can simply implement empty functions.
- *
- * These are all syncrhonous, make sure to return quickly
- * or do the handling in a new thread.
- *
- * @author Arne Kepp
- */
-public interface RTCPAppIntf {
-
- /**
- * This function is called whenever a Sender Report (SR) packet is received
- * and returns unmodified values.
- *
- * A sender report may optionally include Receiver Reports (RR),
- * which are returned as arrays. Index i corresponds to the same report
- * throughout all of the arrays.
- *
- * @param ssrc the (SR) SSRC of the sender
- * @param ntpHighOrder (SR) NTP high order
- * @param ntpLowOrder (SR) NTP low order
- * @param rtpTimestamp (SR) RTP timestamp corresponding to the NTP timestamp
- * @param packetCount (SR) Packets sent since start of session
- * @param octetCount (SR) Octets sent since start of session
- * @param reporteeSsrc (RR) SSRC of sender the receiver is reporting in
- * @param lossFraction (RR) Loss fraction, see RFC 3550
- * @param cumulPacketsLost (RR) Cumulative number of packets lost
- * @param extHighSeq (RR) Extended highest sequence RTP packet received
- * @param interArrivalJitter (RR) Interarrival jitter, see RFC 3550
- * @param lastSRTimeStamp (RR) RTP timestamp when last SR was received
- * @param delayLastSR (RR) Delay, in RTP, since last SR was received
- */
- public void SRPktReceived(long ssrc, long ntpHighOrder, long ntpLowOrder,
- long rtpTimestamp, long packetCount, long octetCount,
- // Get the receiver reports, if any
- long[] reporteeSsrc, int[] lossFraction, int[] cumulPacketsLost, long[] extHighSeq,
- long[] interArrivalJitter, long[] lastSRTimeStamp, long[] delayLastSR);
-
- /**
- * This function is called whenever a Receiver Report (SR) packet is received
- * and returns unmodified values.
- *
- * A receiver report may optionally include report blocks,
- * which are returned as arrays. Index i corresponds to the same report
- * throughout all of the arrays.
- *
- * @param reporterSsrc SSRC of the receiver reporting
- * @param reporteeSsrc (RR) SSRC of sender the receiver is reporting in
- * @param lossFraction (RR) Loss fraction, see RFC 3550
- * @param cumulPacketsLost (RR) Cumulative number of packets lost
- * @param extHighSeq (RR) Extended highest sequence RTP packet received
- * @param interArrivalJitter (RR) Interarrival jitter, see RFC 3550
- * @param lastSRTimeStamp (RR) RTP timestamp when last SR was received
- * @param delayLastSR (RR) Delay, in RTP, since last SR was received
- */
- public void RRPktReceived(long reporterSsrc, long[] reporteeSsrc,
- int[] lossFraction, int[] cumulPacketsLost, long[] extHighSeq,
- long[] interArrivalJitter, long[] lastSRTimeStamp, long[] delayLastSR);
-
- /**
- * This function is called whenever a Source Description (SDES) packet is received.
- *
- * It currently returns the updated participants AFTER they have been updated.
- *
- * @param relevantParticipants participants mentioned in the SDES packet
- */
- public void SDESPktReceived(Participant[] relevantParticipants);
-
- /**
- * This function is called whenever a Bye (BYE) packet is received.
- *
- * The participants will automatically be deleted from the participant
- * database after some time, but in the mean time the application may
- * still receive RTP packets from this source.
- *
- * @param relevantParticipants participants whose SSRC was in the packet
- * @param reason the reason provided in the packet
- */
- public void BYEPktReceived(Participant[] relevantParticipants, String reason);
-
-
- /**
- * This function is called whenever an Application (APP) packet is received.
- *
- * @param part the participant associated with the SSRC
- * @param subtype specified in the packet
- * @param name ASCII description of packet
- * @param data in the packet
- */
- public void APPPktReceived(Participant part, int subtype, byte[] name, byte[] data);
-}
\ No newline at end of file
--- a/src/jlibrtp/RTCPReceiverThread.java Thu May 28 14:26:06 2009 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,369 +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.io.IOException;
-import java.net.DatagramPacket;
-import java.net.InetSocketAddress;
-import java.util.Enumeration;
-import java.util.Iterator;
-
-/**
- * This thread hangs on the RTCP socket and waits for new packets
- *
- * @author Arne Kepp
- *
- */
-public class RTCPReceiverThread extends Thread {
- /** Parent RTP Session */
- private RTPSession rtpSession = null;
- /** Parent RTCP Session */
- private RTCPSession rtcpSession = null;
-
- /**
- * Constructor for new thread
- * @param rtcpSession parent RTCP session
- * @param rtpSession parent RTP session
- */
- RTCPReceiverThread(RTCPSession rtcpSession, RTPSession rtpSession) {
- this.rtpSession = rtpSession;
- this.rtcpSession = rtcpSession;
-
- if(RTPSession.rtpDebugLevel > 1) {
- System.out.println("<-> RTCPReceiverThread created");
- }
-
- }
-
- /**
- * Find out whether a participant with this SSRC is known.
- *
- * If the user is unknown, and the system is operating in unicast mode,
- * try to match the ip-address of the sender to the ip address of a
- * previously unmatched target
- *
- * @param ssrc the SSRC of the participant
- * @param packet the packet that notified us
- * @return the relevant participant, possibly newly created
- */
- private Participant findParticipant(long ssrc, DatagramPacket packet) {
- Participant p = rtpSession.partDb.getParticipant(ssrc);
- if(p == null) {
- Enumeration<Participant> enu = rtpSession.partDb.getParticipants();
- while(enu.hasMoreElements()) {
- Participant tmp = (Participant) enu.nextElement();
- if(tmp.ssrc < 0 &&
- (tmp.rtcpAddress.getAddress().equals(packet.getAddress())
- || tmp.rtpAddress.getAddress().equals(packet.getAddress()))) {
-
- // Best guess
- System.out.println("RTCPReceiverThread: Got an unexpected packet from SSRC:"
- + ssrc + " @" + packet.getAddress().toString() + ", WAS able to match it." );
-
- tmp.ssrc = ssrc;
- return tmp;
- }
- }
- // Create an unknown sender
- System.out.println("RTCPReceiverThread: Got an unexpected packet from SSRC:"
- + ssrc + " @" + packet.getAddress().toString() + ", was NOT able to match it." );
- p = new Participant((InetSocketAddress) null, (InetSocketAddress) packet.getSocketAddress(), ssrc);
- rtpSession.partDb.addParticipant(2,p);
- }
- return p;
- }
-
-
- /**
- * Parse a received UDP packet
- *
- * Perform the header checks and extract the RTCP packets in it
- *
- * @param packet the packet to be parsed
- * @return -1 if there was a problem, 0 if successfully parsed
- */
- private int parsePacket(DatagramPacket packet) {
-
- if(packet.getLength() % 4 != 0) {
- if(RTPSession.rtcpDebugLevel > 2) {
- System.out.println("RTCPReceiverThread.parsePacket got packet that had length " + packet.getLength());
- }
- return -1;
- } else {
- byte[] rawPkt = packet.getData();
-
- // Parse the received compound RTCP (?) packet
- CompRtcpPkt compPkt = new CompRtcpPkt(rawPkt, packet.getLength(),
- (InetSocketAddress) packet.getSocketAddress(), rtpSession);
-
- if(this.rtpSession.debugAppIntf != null) {
- String intfStr;
-
- if(rtpSession.mcSession) {
- intfStr = this.rtcpSession.rtcpMCSock.getLocalSocketAddress().toString();
- } else {
- intfStr = this.rtpSession.rtpSock.getLocalSocketAddress().toString();
- }
-
- if( compPkt.problem == 0) {
- String str = new String("Received compound RTCP packet of size " + packet.getLength() +
- " from " + packet.getSocketAddress().toString() + " via " + intfStr
- + " containing " + compPkt.rtcpPkts.size() + " packets" );
-
- this.rtpSession.debugAppIntf.packetReceived(1,
- (InetSocketAddress) packet.getSocketAddress(), str);
- } else {
- String str = new String("Received invalid RTCP packet of size " + packet.getLength() +
- " from " + packet.getSocketAddress().toString() + " via " + intfStr
- + ": " + this.debugErrorString(compPkt.problem) );
-
- this.rtpSession.debugAppIntf.packetReceived(-2,
- (InetSocketAddress) packet.getSocketAddress(), str);
- }
- }
-
- if(RTPSession.rtcpDebugLevel > 5) {
- Iterator<RtcpPkt> iter = compPkt.rtcpPkts.iterator();
- String str = " ";
- while(iter.hasNext()) {
- RtcpPkt aPkt = iter.next();
- str += (aPkt.getClass().toString() + ":"+aPkt.itemCount+ ", ");
- }
- System.out.println("<-> RTCPReceiverThread.parsePacket() from " + packet.getSocketAddress().toString() + str);
- }
-
-
- //Loop over the information
- Iterator iter = compPkt.rtcpPkts.iterator();
-
- long curTime = System.currentTimeMillis();
-
- while(iter.hasNext()) {
- RtcpPkt aPkt = (RtcpPkt) iter.next();
-
- // Our own packets should already have been filtered out.
- if(aPkt.ssrc == rtpSession.ssrc) {
- System.out.println("RTCPReceiverThread() received RTCP packet"
- + " with conflicting SSRC from " + packet.getSocketAddress().toString());
- rtpSession.resolveSsrcConflict();
- return -1;
- }
-
- /** Receiver Reports **/
- if( aPkt.getClass() == RtcpPktRR.class) {
- RtcpPktRR rrPkt = (RtcpPktRR) aPkt;
-
- Participant p = findParticipant(rrPkt.ssrc, packet);
- p.lastRtcpPkt = curTime;
-
- if(rtpSession.rtcpAppIntf != null) {
- rtpSession.rtcpAppIntf.RRPktReceived(rrPkt.ssrc, rrPkt.reporteeSsrc,
- rrPkt.lossFraction, rrPkt.lostPktCount, rrPkt.extHighSeqRecv,
- rrPkt.interArvJitter, rrPkt.timeStampLSR, rrPkt.delaySR);
- }
-
- /** Sender Reports **/
- } else if(aPkt.getClass() == RtcpPktSR.class) {
- RtcpPktSR srPkt = (RtcpPktSR) aPkt;
-
- Participant p = findParticipant(srPkt.ssrc, packet);
- p.lastRtcpPkt = curTime;
-
- if(p != null) {
-
- if(p.ntpGradient < 0 && p.lastNtpTs1 > -1) {
- //Calculate gradient NTP vs RTP
- long newTime = StaticProcs.undoNtpMess(srPkt.ntpTs1, srPkt.ntpTs2);
- p.ntpGradient = ((double) (newTime - p.ntpOffset))/((double) srPkt.rtpTs - p.lastSRRtpTs);
- if(RTPSession.rtcpDebugLevel > 4) {
- System.out.println("RTCPReceiverThread calculated NTP vs RTP gradient: " + Double.toString(p.ntpGradient));
- }
- } else {
- // Calculate sum of ntpTs1 and ntpTs2 in milliseconds
- p.ntpOffset = StaticProcs.undoNtpMess(srPkt.ntpTs1, srPkt.ntpTs2);
- p.lastNtpTs1 = srPkt.ntpTs1;
- p.lastNtpTs2 = srPkt.ntpTs2;
- p.lastSRRtpTs = srPkt.rtpTs;
- }
-
- // For the next RR
- p.timeReceivedLSR = curTime;
- p.setTimeStampLSR(srPkt.ntpTs1,srPkt.ntpTs2);
-
- }
-
-
- if(rtpSession.rtcpAppIntf != null) {
- if(srPkt.rReports != null) {
- rtpSession.rtcpAppIntf.SRPktReceived(srPkt.ssrc, srPkt.ntpTs1, srPkt.ntpTs2,
- srPkt.rtpTs, srPkt.sendersPktCount, srPkt.sendersPktCount,
- srPkt.rReports.reporteeSsrc, srPkt.rReports.lossFraction, srPkt.rReports.lostPktCount,
- srPkt.rReports.extHighSeqRecv, srPkt.rReports.interArvJitter, srPkt.rReports.timeStampLSR,
- srPkt.rReports.delaySR);
- } else {
- rtpSession.rtcpAppIntf.SRPktReceived(srPkt.ssrc, srPkt.ntpTs1, srPkt.ntpTs2,
- srPkt.rtpTs, srPkt.sendersPktCount, srPkt.sendersPktCount,
- null, null, null,
- null, null, null,
- null);
- }
- }
-
- /** Source Descriptions **/
- } else if(aPkt.getClass() == RtcpPktSDES.class) {
- RtcpPktSDES sdesPkt = (RtcpPktSDES) aPkt;
-
- // The the participant database is updated
- // when the SDES packet is reconstructed by CompRtcpPkt
- if(rtpSession.rtcpAppIntf != null) {
- rtpSession.rtcpAppIntf.SDESPktReceived(sdesPkt.participants);
- }
-
- /** Bye Packets **/
- } else if(aPkt.getClass() == RtcpPktBYE.class) {
- RtcpPktBYE byePkt = (RtcpPktBYE) aPkt;
-
- long time = System.currentTimeMillis();
- Participant[] partArray = new Participant[byePkt.ssrcArray.length];
-
- for(int i=0; i<byePkt.ssrcArray.length; i++) {
- partArray[i] = rtpSession.partDb.getParticipant(byePkt.ssrcArray[i]);
- if(partArray[i] != null)
- partArray[i].timestampBYE = time;
- }
-
- if(rtpSession.rtcpAppIntf != null) {
- rtpSession.rtcpAppIntf.BYEPktReceived(partArray, new String(byePkt.reason));
- }
-
- /** Application specific Packets **/
- } else if(aPkt.getClass() == RtcpPktAPP.class) {
- RtcpPktAPP appPkt = (RtcpPktAPP) aPkt;
-
- Participant part = findParticipant(appPkt.ssrc, packet);
-
- if(rtpSession.rtcpAppIntf != null) {
- rtpSession.rtcpAppIntf.APPPktReceived(part, appPkt.itemCount, appPkt.pktName, appPkt.pktData);
- }
- }
-
-
-
- }
- }
- return 0;
- }
-
- /**
- * Returns a legible message when an error occurs
- *
- * @param errorCode the internal error code, commonly negative of packet type
- * @return a string that is hopefully somewhat informative
- */
- private String debugErrorString(int errorCode) {
- String aStr = "";
- switch(errorCode) {
- case -1: aStr = "The first packet was not of type SR or RR."; break;
- case -2: aStr = "The padding bit was set for the first packet."; break;
- case -200: aStr = " Error parsing Sender Report packet."; break;
- case -201: aStr = " Error parsing Receiver Report packet."; break;
- case -202: aStr = " Error parsing SDES packet"; break;
- case -203: aStr = " Error parsing BYE packet."; break;
- case -204: aStr = " Error parsing Application specific packet."; break;
- case -205: aStr = " Error parsing RTP Feedback packet."; break;
- case -206: aStr = " Error parsing Payload-Specific Feedback packet."; break;
- default:
- aStr = "Unknown error code " + errorCode + ".";
- }
-
- return aStr;
- }
-
- /**
- * Start the RTCP receiver thread.
- *
- * It will
- * 1) run when it receives a packet
- * 2) parse the packet
- * 3) call any relevant callback functions, update database
- * 4) block until the next one arrives.
- */
- public void run() {
- if(RTPSession.rtcpDebugLevel > 1) {
- if(rtpSession.mcSession) {
- System.out.println("-> RTCPReceiverThread.run() starting on MC " + rtcpSession.rtcpMCSock.getLocalPort() );
- } else {
- System.out.println("-> RTCPReceiverThread.run() starting on " + rtcpSession.rtcpSock.getLocalPort() );
- }
- }
-
- while(!rtpSession.endSession) {
-
- if(RTPSession.rtcpDebugLevel > 4) {
- if(rtpSession.mcSession) {
- System.out.println("-> RTCPReceiverThread.run() waiting for packet on MC " + rtcpSession.rtcpMCSock.getLocalPort() );
- } else {
- System.out.println("-> RTCPReceiverThread.run() waiting for packet on " + rtcpSession.rtcpSock.getLocalPort() );
- }
- }
-
- // Prepare a packet
- byte[] rawPkt = new byte[1500];
- DatagramPacket packet = new DatagramPacket(rawPkt, rawPkt.length);
-
- // Wait for it to arrive
- if(! rtpSession.mcSession) {
- //Unicast
- try {
- rtcpSession.rtcpSock.receive(packet);
- } catch (IOException e) {
- if(!rtpSession.endSession) {
- e.printStackTrace();
- } else {
- continue;
- }
- }
- } else {
- //Multicast
- try {
- rtcpSession.rtcpMCSock.receive(packet);
- } catch (IOException e) {
- if(!rtpSession.endSession) {
- e.printStackTrace();
- } else {
- continue;
- }
- }
- }
-
- // Check whether this is one of our own
- if( (rtpSession.mcSession && ! packet.getSocketAddress().equals(rtcpSession.rtcpMCSock) )
- || ! packet.getSocketAddress().equals(rtcpSession.rtcpSock) ) {
- //System.out.println("Packet received from: " + packet.getSocketAddress().toString());
- parsePacket(packet);
- //rtpSession.partDb.debugPrint();
- }
- }
-
- if(RTPSession.rtcpDebugLevel > 1) {
- System.out.println("<-> RTCPReceiverThread terminating");
- }
- }
-
-}
--- a/src/jlibrtp/RTCPSenderThread.java Thu May 28 14:26:06 2009 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,457 +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.DatagramPacket;
-import java.net.InetSocketAddress;
-import java.util.*;
-
-/**
- * This thread sends scheduled RTCP packets
- *
- * It also performs maintenance of various queues and the participant
- * database.
- *
- * @author Arne Kepp
- *
- */
-public class RTCPSenderThread extends Thread {
- /** Parent RTP Session */
- private RTPSession rtpSession = null;
- /** Parent RTCP Session */
- private RTCPSession rtcpSession = null;
-
- /** Whether we have sent byes for the last conflict */
- private boolean byesSent = false;
-
- /**
- * Constructor for new thread
- * @param rtcpSession parent RTCP session
- * @param rtpSession parent RTP session
- */
- protected RTCPSenderThread(RTCPSession rtcpSession, RTPSession rtpSession) {
- this.rtpSession = rtpSession;
- this.rtcpSession = rtcpSession;
- if(RTPSession.rtpDebugLevel > 1) {
- System.out.println("<-> RTCPSenderThread created");
- }
- }
-
- /**
- * Send BYE messages to all the relevant participants
- *
- */
- protected void sendByes() {
- // Create the packet
- CompRtcpPkt compPkt = new CompRtcpPkt();
-
- //Need a SR for validation
- RtcpPktSR srPkt = new RtcpPktSR(this.rtpSession.ssrc,
- this.rtpSession.sentPktCount, this.rtpSession.sentOctetCount, null);
- compPkt.addPacket(srPkt);
-
- byte[] reasonBytes;
-
- //Add the actualy BYE Pkt
- long[] ssrcArray = {this.rtpSession.ssrc};
- if(rtpSession.conflict) {
- reasonBytes = "SSRC collision".getBytes();
- } else {
- reasonBytes = "jlibrtp says bye bye!".getBytes();
- }
- RtcpPktBYE byePkt = new RtcpPktBYE( ssrcArray, reasonBytes);
-
- compPkt.addPacket(byePkt);
-
- // Send it off
- if(rtpSession.mcSession) {
- mcSendCompRtcpPkt(compPkt);
- } else {
- Iterator<Participant> iter = rtpSession.partDb.getUnicastReceivers();
-
- while(iter.hasNext()) {
- Participant part = (Participant) iter.next();
- if(part.rtcpAddress != null)
- sendCompRtcpPkt(compPkt, part.rtcpAddress);
- }
- //System.out.println("SENT BYE PACKETS!!!!!");
- }
- }
-
- /**
- * Multicast version of sending a Compound RTCP packet
- *
- * @param pkt the packet to best
- * @return 0 is successful, -1 otherwise
- */
- protected int mcSendCompRtcpPkt(CompRtcpPkt pkt) {
- byte[] pktBytes = pkt.encode();
- DatagramPacket packet;
-
- // Create datagram
- try {
- packet = new DatagramPacket(pktBytes,pktBytes.length,rtpSession.mcGroup,rtcpSession.rtcpMCSock.getPort());
- } catch (Exception e) {
- System.out.println("RCTPSenderThread.MCSendCompRtcpPkt() packet creation failed.");
- e.printStackTrace();
- return -1;
- }
-
- // Send packet
- if(RTPSession.rtcpDebugLevel > 5) {
- System.out.println("<-> RTCPSenderThread.SendCompRtcpPkt() multicast");
- }
- try {
- rtcpSession.rtcpMCSock.send(packet);
- //Debug
- if(this.rtpSession.debugAppIntf != null) {
- this.rtpSession.debugAppIntf.packetSent(3, (InetSocketAddress) packet.getSocketAddress(),
- new String("Sent multicast RTCP packet of size " + packet.getLength() +
- " to " + packet.getSocketAddress().toString() + " via "
- + this.rtcpSession.rtcpMCSock.getLocalSocketAddress().toString()));
- }
- } catch (Exception e) {
- System.out.println("RCTPSenderThread.MCSendCompRtcpPkt() multicast failed.");
- e.printStackTrace();
- return -1;
- }
- return packet.getLength();
- }
-
- /**
- * Unicast version of sending a Compound RTCP packet
- *
- * @param pkt the packet to best
- * @param receiver the socket address of the recipient
- * @return 0 is successful, -1 otherwise
- */
- protected int sendCompRtcpPkt(CompRtcpPkt pkt, InetSocketAddress receiver) {
- byte[] pktBytes = pkt.encode();
- DatagramPacket packet;
-
- //Create datagram
- try {
- //System.out.println("receiver: " + receiver);
- packet = new DatagramPacket(pktBytes,pktBytes.length,receiver);
- } catch (Exception e) {
- System.out.println("RCTPSenderThread.SendCompRtcpPkt() packet creation failed.");
- e.printStackTrace();
- return -1;
- }
-
- //Send packet
- if(RTPSession.rtcpDebugLevel > 5) {
- Iterator<RtcpPkt> iter = pkt.rtcpPkts.iterator();
- String str = " ";
- while(iter.hasNext()) {
- RtcpPkt aPkt = iter.next();
- str += (aPkt.getClass().toString() + ":"+aPkt.itemCount+ ", ");
- }
- System.out.println("<-> RTCPSenderThread.SendCompRtcpPkt() unicast to " + receiver + str);
- }
- try {
- rtcpSession.rtcpSock.send(packet);
- //Debug
- if(this.rtpSession.debugAppIntf != null) {
- this.rtpSession.debugAppIntf.packetSent(2, (InetSocketAddress) packet.getSocketAddress(),
- new String("Sent unicast RTCP packet of size " + packet.getLength() +
- " to " + packet.getSocketAddress().toString() + " via "
- + this.rtcpSession.rtcpSock.getLocalSocketAddress().toString()));
- }
- } catch (Exception e) {
- System.out.println("RTCPSenderThread.SendCompRtcpPkt() unicast failed.");
- e.printStackTrace();
- return -1;
- }
- return packet.getLength();
- }
-
- /**
- * Check whether we can send an immediate feedback packet to this person
- * @param ssrc SSRC of participant
- */
- protected void reconsiderTiming(long ssrc) {
- Participant part = this.rtpSession.partDb.getParticipant(ssrc);
-
- if( part != null && this.rtcpSession.fbSendImmediately()) {
- CompRtcpPkt compPkt = preparePacket(part, false);
- /*********** Send the packet ***********/
- // Keep track of sent packet length for average;
- int datagramLength;
- if(rtpSession.mcSession) {
- datagramLength = this.mcSendCompRtcpPkt(compPkt);
- } else {
- //part.debugPrint();
- datagramLength = this.sendCompRtcpPkt(compPkt, part.rtcpAddress);
- }
- /*********** Administrative tasks ***********/
- //Update average packet size
- if(datagramLength > 0) {
- rtcpSession.updateAvgPacket(datagramLength);
- }
- } else if(part != null
- && this.rtcpSession.fbAllowEarly
- && this.rtcpSession.fbSendEarly()) {
-
- // Make sure we dont do it too often
- this.rtcpSession.fbAllowEarly = false;
-
- CompRtcpPkt compPkt = preparePacket(part, true);
- /*********** Send the packet ***********/
- // Keep track of sent packet length for average;
- int datagramLength;
- if(rtpSession.mcSession) {
- datagramLength = this.mcSendCompRtcpPkt(compPkt);
- } else {
- //part.debugPrint();
- datagramLength = this.sendCompRtcpPkt(compPkt, part.rtcpAddress);
- }
- /*********** Administrative tasks ***********/
- //Update average packet size
- if(datagramLength > 0) {
- rtcpSession.updateAvgPacket(datagramLength);
- }
- rtcpSession.calculateDelay();
- }
-
- //Out of luck, fb message will have to go with next regular packet
- //Sleep for the remaining time.
- this.rtcpSession.nextDelay -= System.currentTimeMillis() - this.rtcpSession.prevTime;
- if(this.rtcpSession.nextDelay < 0)
- this.rtcpSession.nextDelay = 0;
-
- }
-
- /**
- * Prepare a packet. The output depends on the participant and how the
- * packet is scheduled.
- *
- * @param part the participant to report to
- * @param regular whether this is a regularly, or early scheduled RTCP packet
- * @return compound RTCP packet
- */
- protected CompRtcpPkt preparePacket(Participant part, boolean regular) {
- /*********** Figure out what we are going to send ***********/
- // Check whether this person has sent RTP packets since the last RR.
- boolean incRR = false;
- if(part.secondLastRtcpRRPkt > part.lastRtcpRRPkt) {
- incRR = true;
- part.secondLastRtcpRRPkt = part.lastRtcpRRPkt;
- part.lastRtcpRRPkt = System.currentTimeMillis();
- }
-
- // Are we sending packets? -> add SR
- boolean incSR = false;
- if(rtpSession.sentPktCount > 0 && regular) {
- incSR = true;
- }
-
-
- /*********** Actually create the packet ***********/
- // Create compound packet
- CompRtcpPkt compPkt = new CompRtcpPkt();
-
- //If we're sending packets we'll use a SR for header
- if(incSR) {
- RtcpPktSR srPkt = new RtcpPktSR(this.rtpSession.ssrc,
- this.rtpSession.sentPktCount, this.rtpSession.sentOctetCount, null);
- compPkt.addPacket(srPkt);
-
-
- if(part.ssrc > 0) {
- RtcpPkt[] ar = this.rtcpSession.getFromFbQueue(part.ssrc);
- if(ar != null) {
- for(int i=0; i<ar.length; i++) {
- compPkt.addPacket(ar[i]);
- }
- }
- }
-
- }
-
- //If we got anything from this participant since we sent the 2nd to last RtcpPkt
- if(incRR || !incSR) {
- Participant[] partArray = {part};
-
- if(part.receivedPkts < 1)
- partArray = null;
-
- RtcpPktRR rrPkt = new RtcpPktRR(partArray, rtpSession.ssrc);
- compPkt.addPacket(rrPkt);
-
- if( !incSR && part.ssrc > 0) {
- RtcpPkt[] ar = this.rtcpSession.getFromFbQueue(part.ssrc);
- if(ar != null) {
- for(int i=0; i<ar.length; i++) {
- compPkt.addPacket(ar[i]);
- }
- }
- }
- }
-
- // APP packets
- if(regular && part.ssrc > 0) {
- RtcpPkt[] ar = this.rtcpSession.getFromAppQueue(part.ssrc);
- if(ar != null) {
- for(int i=0; i<ar.length; i++) {
- compPkt.addPacket(ar[i]);
- }
- } else {
- //Nope
- }
- }
-
-
- // For now we'll stick the SDES on every time, and only for us
- //if(regular) {
- RtcpPktSDES sdesPkt = new RtcpPktSDES(true, this.rtpSession, null);
- compPkt.addPacket(sdesPkt);
- //}
-
- return compPkt;
- }
-
- /**
- * Start the RTCP sender thread.
- *
- * RFC 4585 is more complicated, but in general it will
- * 1) Wait a precalculated amount of time
- * 2) Determine the next RTCP recipient
- * 3) Construct a compound packet with all the relevant information
- * 4) Send the packet
- * 5) Calculate next delay before going to sleep
- */
- public void run() {
- if(RTPSession.rtcpDebugLevel > 1) {
- System.out.println("<-> RTCPSenderThread running");
- }
-
- // Give the application a chance to register some participants
- try { Thread.sleep(10); }
- catch (Exception e) { System.out.println("RTCPSenderThread didn't get any initial rest."); }
-
- // Set up an iterator for the member list
- Enumeration<Participant> enu = null;
- Iterator<Participant> iter = null;
-
- // TODO Change to rtcpReceivers
- if(rtpSession.mcSession) {
- enu = rtpSession.partDb.getParticipants();
- } else {
- iter = rtpSession.partDb.getUnicastReceivers();
- }
- while(! rtpSession.endSession) {
- if(RTPSession.rtcpDebugLevel > 5) {
- System.out.println("<-> RTCPSenderThread sleeping for " +rtcpSession.nextDelay+" ms");
- }
-
- try { Thread.sleep(rtcpSession.nextDelay); }
- catch (Exception e) {
- System.out.println("RTCPSenderThread Exception message:" + e.getMessage());
- // Is the party over?
- if(this.rtpSession.endSession) {
- continue;
- }
-
- if(rtcpSession.fbWaiting != -1) {
- reconsiderTiming(rtcpSession.fbWaiting);
- continue;
- }
- }
-
- /** Came here the regular way */
- this.rtcpSession.fbAllowEarly = true;
-
-
- if(RTPSession.rtcpDebugLevel > 5) {
- System.out.println("<-> RTCPSenderThread waking up");
- }
-
- // Regenerate nextDelay, before anything happens.
- rtcpSession.calculateDelay();
-
- // We'll wait here until a conflict (if any) has been resolved,
- // so that the bye packets for our current SSRC can be sent.
- if(rtpSession.conflict) {
- if(! this.byesSent) {
- sendByes();
- this.byesSent = true;
- }
- continue;
- }
- this.byesSent = false;
-
- //Grab the next person
- Participant part = null;
-
- //Multicast
- if(this.rtpSession.mcSession) {
- if(! enu.hasMoreElements())
- enu = rtpSession.partDb.getParticipants();
-
- if( enu.hasMoreElements() ) {
- part = enu.nextElement();
- } else {
- continue;
- }
-
- //Unicast
- } else {
- if(! iter.hasNext()) {
- iter = rtpSession.partDb.getUnicastReceivers();
- }
-
- if(iter.hasNext() ) {
- while( iter.hasNext() && (part == null || part.rtcpAddress == null)) {
- part = iter.next();
- }
- }
-
- if(part == null || part.rtcpAddress == null)
- continue;
- }
-
- CompRtcpPkt compPkt = preparePacket(part, true);
-
- /*********** Send the packet ***********/
- // Keep track of sent packet length for average;
- int datagramLength;
- if(rtpSession.mcSession) {
- datagramLength = this.mcSendCompRtcpPkt(compPkt);
- } else {
- //part.debugPrint();
- datagramLength = this.sendCompRtcpPkt(compPkt, part.rtcpAddress);
- }
-
- /*********** Administrative tasks ***********/
- //Update average packet size
- if(datagramLength > 0) {
- rtcpSession.updateAvgPacket(datagramLength);
- }
- }
-
- // Be polite, say Bye to everone
- sendByes();
- try { Thread.sleep(200);} catch(Exception e) {}
-
- if(RTPSession.rtcpDebugLevel > 0) {
- System.out.println("<-> RTCPSenderThread terminating");
- }
- }
-}
--- a/src/jlibrtp/RTCPSession.java Thu May 28 14:26:06 2009 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,527 +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.util.Enumeration;
-import java.net.DatagramSocket;
-import java.net.InetAddress;
-import java.net.MulticastSocket;
-import java.util.LinkedList;
-import java.util.Hashtable;
-import java.util.ListIterator;
-import java.util.Arrays;
-
-
-/**
- * This class acts as an organizer for most of the information
- * and functions pertaining to RTCP packet generation and reception
- *
- * @author Arne Kepp
- *
- */
-public class RTCPSession {
- /** Parent session */
- protected RTPSession rtpSession = null;
-
- /** Unicast socket */
- protected DatagramSocket rtcpSock = null;
- /** Multicast socket */
- protected MulticastSocket rtcpMCSock = null;
- /** Multicast group */
- protected InetAddress mcGroup = null;
-
- /** RTCP Receiver thread */
- protected RTCPReceiverThread recvThrd = null;
- /** RTCP Sender thread */
- protected RTCPSenderThread senderThrd = null;
-
- /** Previous time a delay was calculated */
- protected long prevTime = System.currentTimeMillis();
- /** Delay between RTCP transmissions, in ms. Initialized in start() */
- protected int nextDelay = -1; //
- /** The average compound RTCP packet size, in octets, including UDP and IP headers */
- protected int avgPktSize = 200; //
- /** Pessimistic case estimate of the current number of senders */
- protected int senderCount = 1;
- /** Whether next RTCP packet can be sent early */
- protected boolean fbAllowEarly = false;
- /** Feedback queue , index is SSRC of target */
- protected Hashtable<Long, LinkedList<RtcpPkt>> fbQueue = null;
- /** APP queue , index is SSRC of target */
- protected Hashtable<Long, LinkedList<RtcpPktAPP>> appQueue = null;
- /** Are we just starting up? */
- protected boolean initial = true;
- /** Is there a feedback packet waiting? SSRC of destination */
- protected long fbWaiting = -1;
-
- /**
- * Constructor for unicast sessions
- *
- * @param parent RTPSession that started this
- * @param rtcpSocket the socket to use for listening and sending
- */
- protected RTCPSession(RTPSession parent, DatagramSocket rtcpSocket) {
- this.rtcpSock = rtcpSocket;
- rtpSession = parent;
- }
-
- /**
- * Constructor for multicast sessions
- *
- * @param parent parent RTPSession
- * @param rtcpSocket parent RTPSession that started this
- * @param multicastGroup multicast group to bind the socket to
- */
- protected RTCPSession(RTPSession parent, MulticastSocket rtcpSocket, InetAddress multicastGroup) {
- mcGroup = multicastGroup;
- this.rtcpSock = rtcpSocket;
- rtpSession = parent;
- }
-
- /**
- * Starts the session, calculates delays and fires up the threads.
- *
- */
- protected void start() {
- //nextDelay = 2500 + rtpSession.random.nextInt(1000) - 500;
- this.calculateDelay();
- recvThrd = new RTCPReceiverThread(this, this.rtpSession);
- senderThrd = new RTCPSenderThread(this, this.rtpSession);
- recvThrd.start();
- senderThrd.start();
- }
-
- /**
- * Send bye packets, handled by RTCP Sender thread
- *
- */
- protected void sendByes() {
- senderThrd.sendByes();
- }
-
- /**
- * Calculate the delay before the next RTCP packet can be sent
- *
- */
- protected void calculateDelay() {
- switch(rtpSession.rtcpMode) {
- case 0: calculateRegularDelay(); break;
- default:
- System.out.println("RTCPSession.calculateDelay() unknown .mode");
- }
- }
-
- /**
- * Calculates a delay value in accordance with RFC 3550
- *
- */
- protected void calculateRegularDelay() {
- long curTime = System.currentTimeMillis();
-
- if(rtpSession.bandwidth != 0 && ! this.initial && rtpSession.partDb.ssrcTable.size() > 4) {
- // RTPs mechanisms for RTCP scalability
- int rand = rtpSession.random.nextInt(10000) - 5000; //between -500 and +500
- double randDouble = ((double) 1000 + rand)/1000.0;
-
-
- Enumeration<Participant> enu = rtpSession.partDb.getParticipants();
- while(enu.hasMoreElements()) {
- Participant part = enu.nextElement();
- if(part.lastRtpPkt > this.prevTime)
- senderCount++;
- }
-
- double bw;
- if(rtpSession.rtcpBandwidth > -1) {
- bw = rtpSession.rtcpBandwidth;
- }else {
- bw = rtpSession.bandwidth*0.05;
- }
- if(senderCount*2 > rtpSession.partDb.ssrcTable.size()) {
- if(rtpSession.lastTimestamp > this.prevTime) {
- //We're a sender
- double numerator = ((double) this.avgPktSize)*((double) senderCount);
- double denominator = 0.25*bw;
- this.nextDelay = (int) Math.round((numerator/denominator)*randDouble);
- } else {
- //We're a receiver
- double numerator = ((double) this.avgPktSize)*((double) rtpSession.partDb.ssrcTable.size());
- double denominator = 0.75*bw;
- this.nextDelay = (int) Math.round((numerator/denominator)*randDouble);
- }
- } else {
- double numerator = ((double) this.avgPktSize)*((double) rtpSession.partDb.ssrcTable.size());;
- double denominator = bw;
- this.nextDelay = (int) Math.round(1000.0*(numerator/denominator)) * (1000 + rand);
- }
- } else {
- // Not enough data to scale, use random values
- int rand = rtpSession.random.nextInt(1000) - 500; //between -500 and +500
- if(this.initial) {
- // 2.5 to 3.5 seconds, randomly
- this.nextDelay = 3000 + rand;
- this.initial = false;
- } else {
- // 4.5 to 5.5 seconds, randomly
- this.nextDelay = 5500 + rand;
- }
-
- }
-
- // preflight check
- if(this.nextDelay < 1000) {
- int rand = rtpSession.random.nextInt(1000) - 500; //between -500 and +500
- System.out.println("RTCPSession.calculateDelay() nextDelay was too short ("
- +this.nextDelay+"ms), setting to "+(this.nextDelay = 2000 + rand));
- }
- this.prevTime = curTime;
- }
-
- /**
- * Update the average packet size
- * @param length of latest packet
- */
- synchronized protected void updateAvgPacket(int length) {
- double tempAvg = (double) this.avgPktSize;
- tempAvg = (15*tempAvg + ((double) length))/16;
- this.avgPktSize = (int) tempAvg;
- }
-
-
- /**
- * Adds an RTCP APP (application) packet to the queue
- *
- * @param targetSsrc the SSRC of the recipient
- * @param aPkt
- */
- synchronized protected void addToAppQueue(long targetSsrc, RtcpPktAPP aPkt) {
- aPkt.time = System.currentTimeMillis();
-
- if(this.appQueue == null)
- this.appQueue = new Hashtable<Long, LinkedList<RtcpPktAPP>>();
-
- LinkedList<RtcpPktAPP> ll = this.appQueue.get(targetSsrc);
- if(ll == null) {
- // No list, create and add
- ll = new LinkedList<RtcpPktAPP>();
- this.appQueue.put(targetSsrc, ll);
- }
-
- ll.add(aPkt);
- }
-
-
- /**
- * Adds an RTCP APP (application) packet to the queue
- *
- * @param targetSsrc the SSRC of the recipient
- * @return array of RTCP Application packets
- */
- synchronized protected RtcpPktAPP[] getFromAppQueue(long targetSsrc) {
- if(this.appQueue == null)
- return null;
-
- LinkedList<RtcpPktAPP> ll = this.appQueue.get(targetSsrc);
- if(ll == null || ll.isEmpty()) {
- return null;
- } else {
- RtcpPktAPP[] ret = new RtcpPktAPP[ll.size()];
- ListIterator<RtcpPktAPP> li = ll.listIterator();
- int i = 0;
- while(li.hasNext()) {
- ret[i] = li.next();
- i++;
- }
- return ret;
- }
- }
-
-
- /**
- * Cleans the TCP APP (application) packet queues of any packets that are
- * too old, defined as 60 seconds since insertion.
- *
- * @param ssrc The SSRC of the user who has left, negative value -> general cleanup
- */
- synchronized protected void cleanAppQueue(long ssrc) {
- if(this.appQueue == null)
- return;
-
- if(ssrc > 0) {
- this.appQueue.remove(ssrc);
- } else {
- Enumeration<LinkedList<RtcpPktAPP>> enu = this.appQueue.elements();
- long curTime = System.currentTimeMillis();
-
-
- while(enu.hasMoreElements()) {
- ListIterator<RtcpPktAPP> li = enu.nextElement().listIterator();
- while(li.hasNext()) {
- RtcpPkt aPkt = li.next();
- //Remove after 60 seconds
- if(curTime - aPkt.time > 60000) {
- li.remove();
- }
- }
- }
- }
- }
-
-
-
- /**
- * Check the feedback queue for similar packets and adds
- * the new packet if it is not redundant
- *
- * @param aPkt
- * @return 0 if the packet was added, 1 if it was dropped
- */
- synchronized protected int addToFbQueue(long targetSsrc, RtcpPkt aPkt) {
- if(this.fbQueue == null)
- this.fbQueue = new Hashtable<Long, LinkedList<RtcpPkt>>();
-
- LinkedList<RtcpPkt> ll = this.fbQueue.get(targetSsrc);
- if(ll == null) {
- // No list, create and add
- ll = new LinkedList<RtcpPkt>();
- ll.add(aPkt);
- this.fbQueue.put(targetSsrc, ll);
- } else {
- // Check for matching packets, else add to end
- ListIterator<RtcpPkt> li = ll.listIterator();
- while(li.hasNext()) {
- RtcpPkt tmp = li.next();
- if(equivalent(tmp, aPkt))
- return -1;
- }
- ll.addLast(aPkt);
- }
- return 0;
- }
-
- /**
- * Checks whether there are ny feedback packets waiting
- * to be sent.
- *
- * @param ssrc of the participant we are notifying
- * @return all relevant feedback packets, or null
- */
- synchronized protected RtcpPkt[] getFromFbQueue(long ssrc) {
- if(this.fbQueue == null)
- return null;
-
- LinkedList<RtcpPkt> ll = this.fbQueue.get(ssrc);
-
- if(ll == null)
- return null;
-
- ListIterator<RtcpPkt> li = ll.listIterator();
- if(li.hasNext()) {
- long curTime = System.currentTimeMillis();
- long maxDelay = curTime - rtpSession.fbMaxDelay;
- long keepDelay = curTime - 2000;
- int count = 0;
-
- //TODO below the indeces should be collected instead of looping twice
-
- // Clean out what we dont want and count what we want
- while(li.hasNext()) {
- RtcpPkt aPkt = li.next();
- if(aPkt.received) {
- //This is a packet received, we keep these for
- // 2000ms to avoid redundant feedback
- if(aPkt.time < keepDelay)
- li.remove();
- } else {
- //This is a packet we havent sent yet
- if(aPkt.time < maxDelay) {
- li.remove();
- } else {
- count++;
- }
- }
- }
-
- // Gather what we want to return
- if(count != 0) {
- li = ll.listIterator();
- RtcpPkt[] ret = new RtcpPkt[count];
-
- while(count > 0) {
- RtcpPkt aPkt = li.next();
- if(! aPkt.received) {
- ret[ret.length - count] = aPkt;
- count--;
- }
- }
- return ret;
- }
- }
-
- return null;
- }
-
- /**
- * Cleans the feeback queue of any packets that have expired,
- * ie feedback packet that are no longer relevant.
- *
- * @param ssrc The SSRC of the user who has left, negative value -> general cleanup
- */
- synchronized protected void cleanFbQueue(long ssrc) {
- if(this.fbQueue == null)
- return;
-
- if(ssrc > 0) {
- this.fbQueue.remove(ssrc);
- } else {
- Enumeration<LinkedList<RtcpPkt>> enu = this.fbQueue.elements();
- long curTime = System.currentTimeMillis();
- long maxDelay = curTime - rtpSession.fbMaxDelay;
- long keepDelay = curTime - 2000;
-
- while(enu.hasMoreElements()) {
- ListIterator<RtcpPkt> li = enu.nextElement().listIterator();
- while(li.hasNext()) {
- RtcpPkt aPkt = li.next();
- if(aPkt.received) {
- //This is a packet received, we keep these for
- // 2000ms to avoid redundant feedback
- if(aPkt.time < keepDelay)
- li.remove();
- } else {
- //This is a packet we havent sent yet
- if(aPkt.time < maxDelay)
- li.remove();
- }
- }
- }
- }
- }
-
- /**
- * Check whether the conditions are satisfied to send a feedbkac packet immediately.
- *
- * @return true if they are, false otherwise
- */
- protected boolean fbSendImmediately() {
- if(rtpSession.partDb.ssrcTable.size() > this.rtpSession.fbEarlyThreshold
- && rtpSession.partDb.receivers.size() > this.rtpSession.fbEarlyThreshold)
- return false;
-
- return true;
- }
-
-
- /**
- * Check whether the conditions are satisfied to send a feedbkac packet immediately.
- *
- * @return true if they are, false otherwise
- */
- protected boolean fbSendEarly() {
- if(rtpSession.partDb.ssrcTable.size() > this.rtpSession.fbRegularThreshold
- && rtpSession.partDb.receivers.size() > this.rtpSession.fbRegularThreshold)
- return false;
-
- return true;
- }
-
- /**
- * Wake the sender thread because of this ssrc
- *
- * @param ssrc that has feedback waiting.
- */
- protected void wakeSenderThread(long ssrc) {
- this.fbWaiting = ssrc;
- this.senderThrd.interrupt();
-
- // Give it a chance to catch up
- try { Thread.sleep(0,1); } catch (Exception e){ };
- }
-
- /**
- * Compares two packets to check whether they are equivalent feedback messages,
- * to avoid sending the same feedback to a host twice.
- *
- * Expect false negatives, but not false positives.
- *
- * @param one packet
- * @param two packet
- * @return true if they are equivalent, false otherwise
- */
- private boolean equivalent(RtcpPkt one, RtcpPkt two) {
- // Cheap checks
- if(one.packetType != two.packetType)
- return false;
-
- if(one.itemCount != two.itemCount)
- return false;
-
- if(one.packetType == 205) {
- // RTP Feedback, i.e. a NACK
- RtcpPktRTPFB pktone = (RtcpPktRTPFB) one;
- RtcpPktRTPFB pkttwo = (RtcpPktRTPFB) two;
-
- if(pktone.ssrcMediaSource != pkttwo.ssrcMediaSource)
- return false;
-
- if(Arrays.equals(pktone.BLP,pkttwo.BLP)
- && Arrays.equals(pktone.BLP,pkttwo.BLP))
- return true;
-
- return true;
- } else if(one.packetType == 206) {
- RtcpPktPSFB pktone = (RtcpPktPSFB) one;
- RtcpPktPSFB pkttwo = (RtcpPktPSFB) two;
-
- if(pktone.ssrcMediaSource != pkttwo.ssrcMediaSource)
- return false;
-
- switch(one.itemCount) {
- case 1: // Picture Loss Indication
- return true;
-
- case 2: // Slice Loss Indication
- // This will not work if the slice loss indicators are in different order
- if(pktone.sliFirst.length == pkttwo.sliFirst.length
- && Arrays.equals(pktone.sliFirst, pkttwo.sliFirst)
- && Arrays.equals(pktone.sliNumber, pkttwo.sliNumber)
- && Arrays.equals(pktone.sliPictureId, pkttwo.sliPictureId))
- return true;
- break;
- case 3: // Reference Picture Selection Indication
- if(Arrays.equals(pktone.rpsiBitString, pkttwo.rpsiBitString))
- return true;
- break;
- case 15: // Application Layer Feedback Messages
- // This will not work if the padding scheme is different
- if(pktone.sliFirst.length == pkttwo.sliFirst.length
- && Arrays.equals(pktone.alfBitString, pkttwo.alfBitString))
- return true;
- break;
- default:
-
- }
- return true;
- } else {
- System.out.println("!!!! RTCPSession.equivalentPackets() encountered unexpected packet type!");
- }
- return false;
- }
-}
-
--- a/src/jlibrtp/RTPAppIntf.java Thu May 28 14:26:06 2009 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,74 +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;
-
-
-/**
- * This is the callback interface for RTP packets.
- *
- * It is mandatory, but you can inore the data if you like.
- *
- * @author Arne Kepp
- */
-public interface RTPAppIntf {
-
- /**
- * The callback method through which the application will receive
- * data from jlibrtp. These calls are synchronous, so you will not
- * receive any new packets until this call returns.
- *
- * @param frame the frame containing the data
- * @param participant the participant from which the data came
- */
- public void receiveData(DataFrame frame, Participant participant);
-
-
- /**
- * The callback method through which the application will receive
- * notifications about user updates, additions and byes.
- * Types:
- * 1 - Bye
- * 2 - New through RTP, check .getRtpSendSock()
- * 3 - New through RTCP, check .getRtcpSendSock()
- * 4 - SDES packet received, check the getCname() etc methods
- * 5 - Matched SSRC to ip-address provided by application
- *
- * @param type the type of event
- * @param participant the participants in question
- */
- public void userEvent(int type, Participant[] participant);
-
- /**
- * The callback method through which the application can specify
- * the number of packets that make up a frame for a given payload type.
- *
- * A negative value denotes frames of variable length, so jlibrtp
- * will return whatever it has at the time.
- *
- * In most applications, this function can simply return 1.
- *
- * This should be implemented as something fast, such as an
- * integer array with the indeces being the payload type.
- *
- * @param payloadType the payload type specified in the RTP packet
- * @return the number of packets that make up a frame
- */
- public int frameSize(int payloadType);
-}
--- a/src/jlibrtp/RTPReceiverThread.java Thu May 28 14:26:06 2009 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,169 +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.io.IOException;
-import java.net.DatagramPacket;
-import java.net.InetSocketAddress;
-
-/**
- * The RTP receiver thread waits on the designated UDP socket for new packets.
- *
- * Once one arrives, it is parsed and tested. We also check the ip-address of the sender.
- * If accepted, the packet is added onto the packet buffer of the participant.
- *
- * A separate thread moves the packet from the packet buffer to the application.
- *
- * @author Arne Kepp
- */
-public class RTPReceiverThread extends Thread {
- /** Parent RTP Session */
- RTPSession rtpSession = null;
-
- RTPReceiverThread(RTPSession session) {
- rtpSession = session;
- if(RTPSession.rtpDebugLevel > 1) {
- System.out.println("<-> RTPReceiverThread created");
- }
- }
-
- public void run() {
- if(RTPSession.rtpDebugLevel > 1) {
- if(rtpSession.mcSession) {
- System.out.println("-> RTPReceiverThread.run() starting on MC " + rtpSession.rtpMCSock.getLocalPort() );
- } else {
- System.out.println("-> RTPReceiverThread.run() starting on " + rtpSession.rtpSock.getLocalPort() );
- }
- }
-
- while(!rtpSession.endSession) {
- if(RTPSession.rtpDebugLevel > 6) {
- if(rtpSession.mcSession) {
- System.out.println("-> RTPReceiverThread.run() waiting for MC packet on " + rtpSession.rtpMCSock.getLocalPort() );
- } else {
- System.out.println("-> RTPReceiverThread.run() waiting for packet on " + rtpSession.rtpSock.getLocalPort() );
- }
- }
-
- // Prepare a packet
- byte[] rawPkt = new byte[1500];
- DatagramPacket packet = new DatagramPacket(rawPkt, rawPkt.length);
- // Wait for it to arrive
- if(! rtpSession.mcSession) {
- //Unicast
- try {
- rtpSession.rtpSock.receive(packet);
- } catch (IOException e) {
- if(!rtpSession.endSession) {
- e.printStackTrace();
- } else {
- continue;
- }
- }
- } else {
- //Multicast
- try {
- rtpSession.rtpMCSock.receive(packet);
- } catch (IOException e) {
- if(!rtpSession.endSession) {
- e.printStackTrace();
- } else {
- continue;
- }
- }
- }
-
- // Parse the received RTP (?) packet
- RtpPkt pkt = new RtpPkt(rawPkt, packet.getLength());
-
- // Check whether it was valid.
- if(pkt == null) {
- System.out.println("Received invalid RTP packet. Ignoring");
- continue;
- }
-
- long pktSsrc = pkt.getSsrc();
-
- // Check for loops and SSRC collisions
- if( rtpSession.ssrc == pktSsrc )
- rtpSession.resolveSsrcConflict();
-
- long[] csrcArray = pkt.getCsrcArray();
- if( csrcArray != null) {
- for(int i=0; i< csrcArray.length; i++) {
- if(csrcArray[i] == rtpSession.ssrc);
- rtpSession.resolveSsrcConflict();
- }
- }
-
- if(RTPSession.rtpDebugLevel > 17) {
- System.out.println("-> RTPReceiverThread.run() rcvd packet, seqNum " + pktSsrc );
- if(RTPSession.rtpDebugLevel > 10) {
- String str = new String(pkt.getPayload());
- System.out.println("-> RTPReceiverThread.run() payload is " + str );
- }
- }
-
- //Find the participant in the database based on SSRC
- Participant part = rtpSession.partDb.getParticipant(pktSsrc);
-
- if(part == null) {
- InetSocketAddress nullSocket = null;
- part = new Participant((InetSocketAddress) packet.getSocketAddress(), nullSocket, pkt.getSsrc());
- part.unexpected = true;
- rtpSession.partDb.addParticipant(1,part);
- }
-
- // Do checks on whether the datagram came from the expected source for that SSRC.
- if(part.rtpAddress == null || packet.getAddress().equals(part.rtpAddress.getAddress())) {
- PktBuffer pktBuffer = part.pktBuffer;
-
- if(pktBuffer != null) {
- //A buffer already exists, append to it
- pktBuffer.addPkt(pkt);
- } else {
- // Create a new packet/frame buffer
- pktBuffer = new PktBuffer(this.rtpSession, part,pkt);
- part.pktBuffer = pktBuffer;
- }
- } else {
- System.out.println("RTPReceiverThread: Got an unexpected packet from " + pkt.getSsrc()
- + " the sending ip-address was " + packet.getAddress().toString()
- + ", we expected from " + part.rtpAddress.toString());
- }
-
- // Statistics for receiver report.
- part.updateRRStats(packet.getLength(), pkt);
- // Upate liveness
- part.lastRtpPkt = System.currentTimeMillis();
-
- if(RTPSession.rtpDebugLevel > 5) {
- System.out.println("<-> RTPReceiverThread signalling pktBufDataReady");
- }
-
- // Signal the thread that pushes data to application
- rtpSession.pktBufLock.lock();
- try { rtpSession.pktBufDataReady.signalAll(); } finally {
- rtpSession.pktBufLock.unlock();
- }
-
- }
- }
-
-}
--- a/src/jlibrtp/RTPSession.java Thu May 28 14:26:06 2009 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,1053 +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.DatagramSocket;
-import java.net.MulticastSocket;
-import java.net.DatagramPacket;
-import java.net.InetAddress;
-import java.net.InetSocketAddress;
-import java.util.Iterator;
-import java.util.concurrent.locks.*;
-import java.util.Random;
-import java.util.Enumeration;
-/**
- * The RTPSession object is the core of jlibrtp.
- *
- * One should be instantiated for every communication channel, i.e. if you send voice and video, you should create one for each.
- *
- * The instance holds a participant database, as well as other information about the session. When the application registers with the session, the necessary threads for receiving and processing RTP packets are spawned.
- *
- * RTP Packets are sent synchronously, all other operations are asynchronous.
- *
- * @author Arne Kepp
- */
-public class RTPSession {
- /**
- * The debug level is final to avoid compilation of if-statements.</br>
- * 0 provides no debugging information, 20 provides everything </br>
- * Debug output is written to System.out</br>
- * Debug level for RTP related things.
- */
- final static public int rtpDebugLevel = 0;
- /**
- * The debug level is final to avoid compilation of if-statements.</br>
- * 0 provides no debugging information, 20 provides everything </br>
- * Debug output is written to System.out</br>
- * Debug level for RTCP related things.
- */
- final static public int rtcpDebugLevel = 0;
-
- /** RTP unicast socket */
- protected DatagramSocket rtpSock = null;
- /** RTP multicast socket */
- protected MulticastSocket rtpMCSock = null;
- /** RTP multicast group */
- protected InetAddress mcGroup = null;
-
- // Internal state
- /** Whether this session is a multicast session or not */
- protected boolean mcSession = false;
- /** Current payload type, can be changed by application */
- protected int payloadType = 0;
- /** SSRC of this session */
- protected long ssrc;
- /** The last timestamp when we sent something */
- protected long lastTimestamp = 0;
- /** Current sequence number */
- protected int seqNum = 0;
- /** Number of packets sent by this session */
- protected int sentPktCount = 0;
- /** Number of octets sent by this session */
- protected int sentOctetCount = 0;
-
- /** The random seed */
- protected Random random = null;
-
- /** Session bandwidth in BYTES per second */
- protected int bandwidth = 8000;
-
- /** By default we do not return packets from strangers in unicast mode */
- protected boolean naiveReception = false;
-
- /** Should the library attempt frame reconstruction? */
- protected boolean frameReconstruction = true;
-
- /** Maximum number of packets used for reordering */
- protected int pktBufBehavior = 3;
-
- /** Participant database */
- protected ParticipantDatabase partDb = new ParticipantDatabase(this);
- /** Handle to application interface for RTP */
- protected RTPAppIntf appIntf = null;
- /** Handle to application interface for RTCP (optional) */
- protected RTCPAppIntf rtcpAppIntf = null;
- /** Handle to application interface for AVPF, RFC 4585 (optional) */
- protected RTCPAVPFIntf rtcpAVPFIntf = null;
- /** Handle to application interface for debugging */
- protected DebugAppIntf debugAppIntf = null;
-
- /** The RTCP session associated with this RTP Session */
- protected RTCPSession rtcpSession = null;
- /** The thread for receiving RTP packets */
- protected RTPReceiverThread recvThrd = null;
- /** The thread for invoking callbacks for RTP packets */
- protected AppCallerThread appCallerThrd = null;
-
- /** Lock to protect the packet buffers */
- final protected Lock pktBufLock = new ReentrantLock();
- /** Condition variable, to tell the */
- final protected Condition pktBufDataReady = pktBufLock.newCondition();
-
- /** Enough is enough, set to true when you want to quit. */
- protected boolean endSession = false;
- /** Only one registered application, please */
- protected boolean registered = false;
- /** We're busy resolving a SSRC conflict, please try again later */
- protected boolean conflict = false;
- /** Number of conflicts observed, exessive number suggests loop in network */
- protected int conflictCount = 0;
-
- /** SDES CNAME */
- protected String cname = null;
- /** SDES The participant's real name */
- public String name = null;
- /** SDES The participant's email */
- public String email = null;
- /** SDES The participant's phone number */
- public String phone = null;
- /** SDES The participant's location*/
- public String loc = null;
- /** SDES The tool the participants is using */
- public String tool = null;
- /** SDES A note */
- public String note = null;
- /** SDES A priv string, loosely defined */
- public String priv = null;
-
- // RFC 4585 stuff. This should live on RTCPSession, but we need to have this
- // infromation ready by the time the RTCP Session starts
- // 0 = RFC 3550 , -1 = ACK , 1 = Immediate feedback, 2 = Early RTCP,
- protected int rtcpMode = 0;
- protected int fbEarlyThreshold = -1; // group size, immediate -> early transition point
- protected int fbRegularThreshold = -1; // group size, early -> regular transition point
- protected int minInterval = 5000; // minimum interval
- protected int fbMaxDelay = 1000; // how long the information is useful
- // RTCP bandwidth
- protected int rtcpBandwidth = -1;
-
-
- /**
- * Returns an instance of a <b>unicast</b> RTP session.
- * Following this you should adjust any settings and then register your application.
- *
- * The sockets should have external ip addresses, else your CNAME automatically
- * generated CNAMe will be bad.
- *
- * @param rtpSocket UDP socket to receive RTP communication on
- * @param rtcpSocket UDP socket to receive RTCP communication on, null if none.
- */
- public RTPSession(DatagramSocket rtpSocket, DatagramSocket rtcpSocket) {
- mcSession = false;
- rtpSock = rtpSocket;
- this.generateCNAME();
- this.generateSsrc();
- this.rtcpSession = new RTCPSession(this,rtcpSocket);
-
- // The sockets are not always imediately available?
- try { Thread.sleep(1); } catch (InterruptedException e) { System.out.println("RTPSession sleep failed"); }
- }
-
- /**
- * Returns an instance of a <b>multicast</b> RTP session.
- * Following this you should register your application.
- *
- * The sockets should have external ip addresses, else your CNAME automatically
- * generated CNAMe will be bad.
- *
- * @param rtpSock a multicast socket to receive RTP communication on
- * @param rtcpSock a multicast socket to receive RTP communication on
- * @param multicastGroup the multicast group that we want to communicate with.
- */
- public RTPSession(MulticastSocket rtpSock, MulticastSocket rtcpSock, InetAddress multicastGroup) throws Exception {
- mcSession = true;
- rtpMCSock =rtpSock;
- mcGroup = multicastGroup;
- rtpMCSock.joinGroup(mcGroup);
- rtcpSock.joinGroup(mcGroup);
- this.generateCNAME();
- this.generateSsrc();
- this.rtcpSession = new RTCPSession(this,rtcpSock,mcGroup);
-
- // The sockets are not always imediately available?
- try { Thread.sleep(1); } catch (InterruptedException e) { System.out.println("RTPSession sleep failed"); }
- }
-
- /**
- * Registers an application (RTPAppIntf) with the RTP session.
- * The session will call receiveData() on the supplied instance whenever data has been received.
- *
- * Following this you should set the payload type and add participants to the session.
- *
- * @param rtpApp an object that implements the RTPAppIntf-interface
- * @param rtcpApp an object that implements the RTCPAppIntf-interface (optional)
- * @return -1 if this RTPSession-instance already has an application registered.
- */
- public int RTPSessionRegister(RTPAppIntf rtpApp, RTCPAppIntf rtcpApp, DebugAppIntf debugApp) {
- if(registered) {
- System.out.println("RTPSessionRegister(): Can\'t register another application!");
- return -1;
- } else {
- registered = true;
- generateSeqNum();
- if(RTPSession.rtpDebugLevel > 0) {
- System.out.println("-> RTPSessionRegister");
- }
- this.appIntf = rtpApp;
- this.rtcpAppIntf = rtcpApp;
- this.debugAppIntf = debugApp;
-
- recvThrd = new RTPReceiverThread(this);
- appCallerThrd = new AppCallerThread(this, rtpApp);
- recvThrd.start();
- appCallerThrd.start();
- rtcpSession.start();
- return 0;
- }
- }
-
- /**
- * Send data to all participants registered as receivers, using the current timeStamp,
- * dynamic sequence number and the current payload type specified for the session.
- *
- * @param buf A buffer of bytes, less than 1496 bytes
- * @return null if there was a problem, {RTP Timestamp, Sequence number} otherwise
- */
- public long[] sendData(byte[] buf) {
- byte[][] tmp = {buf};
- long[][] ret = this.sendData(tmp, null, null, -1, null);
-
- if(ret != null)
- return ret[0];
-
- return null;
- }
-
- /**
- * Send data to all participants registered as receivers, using the specified timeStamp,
- * sequence number and the current payload type specified for the session.
- *
- * @param buf A buffer of bytes, less than 1496 bytes
- * @param rtpTimestamp the RTP timestamp to be used in the packet
- * @param seqNum the sequence number to be used in the packet
- * @return null if there was a problem, {RTP Timestamp, Sequence number} otherwise
- */
- public long[] sendData(byte[] buf, long rtpTimestamp, long seqNum) {
- byte[][] tmp = {buf};
- long[][] ret = this.sendData(tmp, null, null, -1, null);
-
- if(ret != null)
- return ret[0];
-
- return null;
- }
-
- /**
- * Send data to all participants registered as receivers, using the current timeStamp and
- * payload type. The RTP timestamp will be the same for all the packets.
- *
- * @param buffers A buffer of bytes, should not bed padded and less than 1500 bytes on most networks.
- * @param csrcArray an array with the SSRCs of contributing sources
- * @param markers An array indicating what packets should be marked. Rarely anything but the first one
- * @param rtpTimestamp The RTP timestamp to be applied to all packets
- * @param seqNumbers An array with the sequence number associated with each byte[]
- * @return null if there was a problem sending the packets, 2-dim array with {RTP Timestamp, Sequence number}
- */
- public long[][] sendData(byte[][] buffers, long[] csrcArray, boolean[] markers, long rtpTimestamp, long[] seqNumbers) {
- if(RTPSession.rtpDebugLevel > 5) {
- System.out.println("-> RTPSession.sendData(byte[])");
- }
-
- // Same RTP timestamp for all
- if(rtpTimestamp < 0)
- rtpTimestamp = System.currentTimeMillis();
-
- // Return values
- long[][] ret = new long[buffers.length][2];
-
- for(int i=0; i<buffers.length; i++) {
- byte[] buf = buffers[i];
-
- boolean marker = false;
- if(markers != null)
- marker = markers[i];
-
- if(buf.length > 1500) {
- System.out.println("RTPSession.sendData() called with buffer exceeding 1500 bytes ("+buf.length+")");
- }
-
- // Get the return values
- ret[i][0] = rtpTimestamp;
- if(seqNumbers == null) {
- ret[i][1] = getNextSeqNum();
- } else {
- ret[i][1] = seqNumbers[i];
- }
- // Create a new RTP Packet
- RtpPkt pkt = new RtpPkt(rtpTimestamp,this.ssrc,(int) ret[i][1],this.payloadType,buf);
-
- if(csrcArray != null)
- pkt.setCsrcs(csrcArray);
-
- pkt.setMarked(marker);
-
- // Creates a raw packet
- byte[] pktBytes = pkt.encode();
-
- //System.out.println(Integer.toString(StaticProcs.bytesToUIntInt(pktBytes, 2)));
-
- // Pre-flight check, are resolving an SSRC conflict?
- if(this.conflict) {
- System.out.println("RTPSession.sendData() called while trying to resolve conflict.");
- return null;
- }
-
-
- if(this.mcSession) {
- DatagramPacket packet = null;
-
-
- try {
- packet = new DatagramPacket(pktBytes,pktBytes.length,this.mcGroup,this.rtpMCSock.getPort());
- } catch (Exception e) {
- System.out.println("RTPSession.sendData() packet creation failed.");
- e.printStackTrace();
- return null;
- }
-
- try {
- rtpMCSock.send(packet);
- //Debug
- if(this.debugAppIntf != null) {
- this.debugAppIntf.packetSent(1, (InetSocketAddress) packet.getSocketAddress(),
- new String("Sent multicast RTP packet of size " + packet.getLength() +
- " to " + packet.getSocketAddress().toString() + " via "
- + rtpMCSock.getLocalSocketAddress().toString()));
- }
- } catch (Exception e) {
- System.out.println("RTPSession.sendData() multicast failed.");
- e.printStackTrace();
- return null;
- }
-
- } else {
- // Loop over recipients
- Iterator<Participant> iter = partDb.getUnicastReceivers();
- while(iter.hasNext()) {
- InetSocketAddress receiver = iter.next().rtpAddress;
- DatagramPacket packet = null;
-
- if(RTPSession.rtpDebugLevel > 15) {
- System.out.println(" Sending to " + receiver.toString());
- }
-
- try {
- packet = new DatagramPacket(pktBytes,pktBytes.length,receiver);
- } catch (Exception e) {
- System.out.println("RTPSession.sendData() packet creation failed.");
- e.printStackTrace();
- return null;
- }
-
- //Actually send the packet
- try {
- rtpSock.send(packet);
- //Debug
- if(this.debugAppIntf != null) {
- this.debugAppIntf.packetSent(0, (InetSocketAddress) packet.getSocketAddress(),
- new String("Sent unicast RTP packet of size " + packet.getLength() +
- " to " + packet.getSocketAddress().toString() + " via "
- + rtpSock.getLocalSocketAddress().toString()));
- }
- } catch (Exception e) {
- System.out.println("RTPSession.sendData() unicast failed.");
- e.printStackTrace();
- return null;
- }
- }
- }
-
- //Update our stats
- this.sentPktCount++;
- this.sentOctetCount++;
-
- if(RTPSession.rtpDebugLevel > 5) {
- System.out.println("<- RTPSession.sendData(byte[]) " + pkt.getSeqNumber());
- }
- }
-
- return ret;
- }
-
- /**
- * Send RTCP App packet to receiver specified by ssrc
- *
- *
- *
- * Return values:
- * 0 okay
- * -1 no RTCP session established
- * -2 name is not byte[4];
- * -3 data is not byte[x], where x = 4*y for syme y
- * -4 type is not a 5 bit unsigned integer
- *
- * Note that a return value of 0 does not guarantee delivery.
- * The participant must also exist in the participant database,
- * otherwise the message will eventually be deleted.
- *
- * @param ssrc of the participant you want to reach
- * @param type the RTCP App packet subtype, default 0
- * @param name the ASCII (in byte[4]) representation
- * @param data the data itself
- * @return 0 if okay, negative value otherwise (see above)
- */
-
- public int sendRTCPAppPacket(long ssrc, int type, byte[] name, byte[] data) {
- if(this.rtcpSession == null)
- return -1;
-
- if(name.length != 4)
- return -2;
-
- if(data.length % 4 != 0)
- return -3;
-
- if(type > 63 || type < 0 )
- return -4;
-
- RtcpPktAPP pkt = new RtcpPktAPP(ssrc, type, name, data);
- this.rtcpSession.addToAppQueue(ssrc, pkt);
-
- return 0;
- }
- /**
- * Add a participant object to the participant database.
- *
- * If packets have already been received from this user, we will try to update the automatically inserted participant with the information provided here.
- *
- * @param p A participant.
- */
- public int addParticipant(Participant p) {
- //For now we make all participants added this way persistent
- p.unexpected = false;
- return this.partDb.addParticipant(0, p);
- }
-
- /**
- * Remove a participant from the database. All buffered packets will be destroyed.
- *
- * @param p A participant.
- */
- public void removeParticipant(Participant p) {
- partDb.removeParticipant(p);
- }
-
- public Iterator<Participant> getUnicastReceivers() {
- return partDb.getUnicastReceivers();
- }
-
- public Enumeration<Participant> getParticipants() {
- return partDb.getParticipants();
- }
-
- /**
- * End the RTP Session. This will halt all threads and send bye-messages to other participants.
- *
- * RTCP related threads may require several seconds to wake up and terminate.
- */
- public void endSession() {
- this.endSession = true;
-
- // No more RTP packets, please
- if(this.mcSession) {
- this.rtpMCSock.close();
- } else {
- this.rtpSock.close();
- }
-
- // Signal the thread that pushes data to application
- this.pktBufLock.lock();
- try { this.pktBufDataReady.signalAll(); } finally {
- this.pktBufLock.unlock();
- }
- // Interrupt what may be sleeping
- this.rtcpSession.senderThrd.interrupt();
-
- // Give things a chance to cool down.
- try { Thread.sleep(50); } catch (Exception e){ };
-
- this.appCallerThrd.interrupt();
-
- // Give things a chance to cool down.
- try { Thread.sleep(50); } catch (Exception e){ };
-
- if(this.rtcpSession != null) {
- // No more RTP packets, please
- if(this.mcSession) {
- this.rtcpSession.rtcpMCSock.close();
- } else {
- this.rtcpSession.rtcpSock.close();
- }
- }
- }
-
-
- /**
- * Check whether this session is ending.
- *
- * @return true if session and associated threads are terminating.
- */
- boolean isEnding() {
- return this.endSession;
- }
-
- /**
- * Overrides CNAME, used for outgoing RTCP packets.
- *
- * @param cname a string, e.g. username@hostname. Must be unique for session.
- */
- public void CNAME(String cname) {
- this.cname = cname;
- }
-
- /**
- * Get the current CNAME, used for outgoing SDES packets
- */
- public String CNAME() {
- return this.cname;
- }
-
- public long getSsrc() {
- return this.ssrc;
- }
-
- private void generateCNAME() {
- String hostname;
-
- if(this.mcSession) {
- hostname = this.rtpMCSock.getLocalAddress().getCanonicalHostName();
- } else {
- hostname = this.rtpSock.getLocalAddress().getCanonicalHostName();
- }
-
- //if(hostname.equals("0.0.0.0") && System.getenv("HOSTNAME") != null) {
- // hostname = System.getenv("HOSTNAME");
- //}
-
- cname = System.getProperty("user.name") + "@" + hostname;
- }
-
- /**
- * Change the RTP socket of the session.
- * Peers must be notified through SIP or other signalling protocol.
- * Only valid if this is a unicast session to begin with.
- *
- * @param newSock integer for new port number, check it is free first.
- */
- public int updateRTPSock(DatagramSocket newSock) {
- if(!mcSession) {
- rtpSock = newSock;
- return 0;
- } else {
- System.out.println("Can't switch from multicast to unicast.");
- return -1;
- }
- }
-
- /**
- * Change the RTCP socket of the session.
- * Peers must be notified through SIP or other signalling protocol.
- * Only valid if this is a unicast session to begin with.
- *
- * @param newSock the new unicast socket for RTP communication.
- */
- public int updateRTCPSock(DatagramSocket newSock) {
- if(!mcSession) {
- this.rtcpSession.rtcpSock = newSock;
- return 0;
- } else {
- System.out.println("Can't switch from multicast to unicast.");
- return -1;
- }
- }
-
- /**
- * Change the RTP multicast socket of the session.
- * Peers must be notified through SIP or other signalling protocol.
- * Only valid if this is a multicast session to begin with.
- *
- * @param newSock the new multicast socket for RTP communication.
- */
- public int updateRTPSock(MulticastSocket newSock) {
- if(mcSession) {
- this.rtpMCSock = newSock;
- return 0;
- } else {
- System.out.println("Can't switch from unicast to multicast.");
- return -1;
- }
- }
-
- /**
- * Change the RTCP multicast socket of the session.
- * Peers must be notified through SIP or other signalling protocol.
- * Only valid if this is a multicast session to begin with.
- *
- * @param newSock the new multicast socket for RTCP communication.
- */
- public int updateRTCPSock(MulticastSocket newSock) {
- if(mcSession) {
- this.rtcpSession.rtcpMCSock = newSock;
- return 0;
- } else {
- System.out.println("Can't switch from unicast to multicast.");
- return -1;
- }
- }
-
- /**
- * Update the payload type used for the session. It is represented as a 7 bit integer, whose meaning must be negotiated elsewhere (see IETF RFCs <a href="http://www.ietf.org/rfc/rfc3550.txt">3550</a> and <a href="http://www.ietf.org/rfc/rfc3550.txt">3551</a>)
- *
- * @param payloadT an integer representing the payload type of any subsequent packets that are sent.
- */
- public int payloadType(int payloadT) {
- if(payloadT > 128 || payloadT < 0) {
- return -1;
- } else {
- this.payloadType = payloadT;
- return this.payloadType;
- }
- }
-
- /**
- * Get the payload type that is currently used for outgoing RTP packets.
- *
- * @return payload type as integer
- */
- public int payloadType() {
- return this.payloadType;
- }
-
- /**
- * Should packets from unknown participants be returned to the application? This can be dangerous.
- *
- * @param doAccept packets from participants not added by the application.
- */
- public void naivePktReception(boolean doAccept) {
- naiveReception = doAccept;
- }
-
- /**
- * Are packets from unknown participants returned to the application?
- *
- * @return whether we accept packets from participants not added by the application.
- */
- public boolean naivePktReception() {
- return naiveReception;
- }
-
- /**
- * Set the number of RTP packets that should be buffered when a packet is
- * missing or received out of order. Setting this number high increases
- * the chance of correctly reordering packets, but increases latency when
- * a packet is dropped by the network.
- *
- * Packets that arrive in order are not affected, they are passed straight
- * to the application.
- *
- * The maximum delay is numberofPackets * packet rate , where the packet rate
- * depends on the codec and profile used by the sender.
- *
- * Valid values:
- * >0 - The maximum number of packets (based on RTP Timestamp) that may accumulate
- * 0 - All valid packets received in order will be given to the application
- * -1 - All valid packets will be given to the application
- *
- * @param behavior the be
- * @return the behavior set, unchanged in the case of a erroneous value
- */
- public int packetBufferBehavior(int behavior) {
- if(behavior > -2) {
- this.pktBufBehavior = behavior;
- // Signal the thread that pushes data to application
- this.pktBufLock.lock();
- try { this.pktBufDataReady.signalAll(); } finally {
- this.pktBufLock.unlock();
- }
- return this.pktBufBehavior;
- } else {
- return this.pktBufBehavior;
- }
- }
-
- /**
- * The number of RTP packets that should be buffered when a packet is
- * missing or received out of order. A high number increases the chance
- * of correctly reordering packets, but increases latency when a packet is
- * dropped by the network.
- *
- * A negative value disables the buffering, out of order packets will simply be dropped.
- *
- * @return the maximum number of packets that can accumulate before the first is returned
- */
- public int packetBufferBehavior() {
- return this.pktBufBehavior;
- }
-
- /**
- * Set whether the stack should operate in RFC 4585 mode.
- *
- * This will automatically call adjustPacketBufferBehavior(-1),
- * i.e. disable all RTP packet buffering in jlibrtp,
- * and disable frame reconstruction
- *
- * @param rtcpAVPFIntf the in
- */
- public int registerAVPFIntf(RTCPAVPFIntf rtcpAVPFIntf, int maxDelay, int earlyThreshold, int regularThreshold ) {
- if(this.rtcpSession != null) {
- this.packetBufferBehavior(-1);
- this.frameReconstruction = false;
- this.rtcpAVPFIntf = rtcpAVPFIntf;
- this.fbEarlyThreshold = earlyThreshold;
- this.fbRegularThreshold = regularThreshold;
- return 0;
- } else {
- return -1;
- }
- }
-
- /**
- * Unregisters the RTCP AVPF interface, thereby going from
- * RFC 4585 mode to RFC 3550
- *
- * You still have to adjust packetBufferBehavior() and
- * frameReconstruction.
- *
- */
- public void unregisterAVPFIntf() {
- this.fbEarlyThreshold = -1;
- this.fbRegularThreshold = -1;
- this.rtcpAVPFIntf = null;
- }
-
- /**
- * Enable / disable frame reconstruction in the packet buffers.
- * This is only relevant if getPacketBufferBehavior > 0;
- *
- * Default is true.
- */
- public void frameReconstruction(boolean toggle) {
- this.frameReconstruction = toggle;
- }
-
- /**
- * Whether the packet buffer will attempt to reconstruct
- * packet automatically.
- *
- * @return the status
- */
- public boolean frameReconstruction() {
- return this.frameReconstruction;
- }
-
- /**
- * The bandwidth currently allocated to the session,
- * in bytes per second. The default is 8000.
- *
- * This value is not enforced and currently only
- * used to calculate the RTCP interval to ensure the
- * control messages do not exceed 5% of the total bandwidth
- * described here.
- *
- * Since the actual value may change a conservative
- * estimate should be used to avoid RTCP flooding.
- *
- * see rtcpBandwidth(void)
- *
- * @return current bandwidth setting
- */
- public int sessionBandwidth() {
- return this.bandwidth;
- }
-
- /**
- * Set the bandwidth of the session.
- *
- * See sessionBandwidth(void) for details.
- *
- * @param bandwidth the new value requested, in bytes per second
- * @return the actual value set
- */
- public int sessionBandwidth(int bandwidth) {
- if(bandwidth < 1) {
- this.bandwidth = 8000;
- } else {
- this.bandwidth = bandwidth;
- }
- return this.bandwidth;
- }
-
-
- /**
- * RFC 3550 dictates that 5% of the total bandwidth,
- * as set by sessionBandwidth, should be dedicated
- * to RTCP traffic. This
- *
- * This should normally not be done, but is permissible in
- * conjunction with feedback (RFC 4585) and possibly
- * other profiles.
- *
- * Also see sessionBandwidth(void)
- *
- * @return current RTCP bandwidth setting, -1 means not in use
- */
- public int rtcpBandwidth() {
- return this.rtcpBandwidth;
- }
-
- /**
- * Set the RTCP bandwidth, see rtcpBandwidth(void) for details.
- *
- * This function must be
- *
- * @param bandwidth the new value requested, in bytes per second or -1 to disable
- * @return the actual value set
- */
- public int rtcpBandwidth(int bandwidth) {
- if(bandwidth < -1) {
- this.rtcpBandwidth = -1;
- } else {
- this.rtcpBandwidth = bandwidth;
- }
- return this.rtcpBandwidth;
- }
-
- /********************************************* Feedback message stuff ***************************************/
-
- /**
- * Adds a Picture Loss Indication to the feedback queue
- *
- * @param ssrcMediaSource
- * @return 0 if packet was queued, -1 if no feedback support, 1 if redundant
- */
- public int fbPictureLossIndication(long ssrcMediaSource) {
- int ret = 0;
-
- if(this.rtcpAVPFIntf == null)
- return -1;
-
- RtcpPktPSFB pkt = new RtcpPktPSFB(this.ssrc, ssrcMediaSource);
- pkt.makePictureLossIndication();
- ret = this.rtcpSession.addToFbQueue(ssrcMediaSource, pkt);
- if(ret == 0)
- this.rtcpSession.wakeSenderThread(ssrcMediaSource);
- return ret;
- }
-
- /**
- * Adds a Slice Loss Indication to the feedback queue
- *
- * @param ssrcMediaSource
- * @param sliFirst macroblock (MB) address of the first lost macroblock
- * @param sliNumber number of lost macroblocks
- * @param sliPictureId six least significant bits of the codec-specific identif
- * @return 0 if packet was queued, -1 if no feedback support, 1 if redundant
- */
- public int fbSlicLossIndication(long ssrcMediaSource, int[] sliFirst, int[] sliNumber, int[] sliPictureId) {
- int ret = 0;
- if(this.rtcpAVPFIntf == null)
- return -1;
-
- RtcpPktPSFB pkt = new RtcpPktPSFB(this.ssrc, ssrcMediaSource);
- pkt.makeSliceLossIndication(sliFirst, sliNumber, sliPictureId);
-
- ret = this.rtcpSession.addToFbQueue(ssrcMediaSource, pkt);
- if(ret == 0)
- this.rtcpSession.wakeSenderThread(ssrcMediaSource);
- return ret;
- }
-
- /**
- * Adds a Reference Picture Selection Indication to the feedback queue
- *
- * @param ssrcMediaSource
- * @param bitPadding number of padded bits at end of bitString
- * @param payloadType RTP payload type for codec
- * @param bitString RPSI information as natively defined by the video codec
- * @return 0 if packet was queued, -1 if no feedback support, 1 if redundant
- */
- public int fbRefPictureSelIndic(long ssrcMediaSource, int bitPadding, int payloadType, byte[] bitString) {
- int ret = 0;
-
- if(this.rtcpAVPFIntf == null)
- return -1;
-
- RtcpPktPSFB pkt = new RtcpPktPSFB(this.ssrc, ssrcMediaSource);
- pkt.makeRefPictureSelIndic(bitPadding, payloadType, bitString);
- ret = this.rtcpSession.addToFbQueue(ssrcMediaSource, pkt);
- if(ret == 0)
- this.rtcpSession.wakeSenderThread(ssrcMediaSource);
- return ret;
- }
-
- /**
- * Adds a Picture Loss Indication to the feedback queue
- *
- * @param ssrcMediaSource
- * @param bitString the original application message
- * @return 0 if packet was queued, -1 if no feedback support, 1 if redundant
- */
- public int fbAppLayerFeedback(long ssrcMediaSource, byte[] bitString) {
- int ret = 0;
-
- if(this.rtcpAVPFIntf == null)
- return -1;
-
- RtcpPktPSFB pkt = new RtcpPktPSFB(this.ssrc, ssrcMediaSource);
- pkt.makeAppLayerFeedback(bitString);
- ret = this.rtcpSession.addToFbQueue(ssrcMediaSource, pkt);
- if(ret == 0)
- this.rtcpSession.wakeSenderThread(ssrcMediaSource);
- return ret;
- }
-
-
- /**
- * Adds a RTP Feedback packet to the feedback queue.
- *
- * These are mostly used for NACKs.
- *
- * @param ssrcMediaSource
- * @param FMT the Feedback Message Subtype
- * @param PID RTP sequence numbers of lost packets
- * @param BLP bitmask of following lost packets, shared index with PID
- * @return 0 if packet was queued, -1 if no feedback support, 1 if redundant
- */
- public int fbPictureLossIndication(long ssrcMediaSource, int FMT, int[] PID, int[] BLP) {
- int ret = 0;
-
- if(this.rtcpAVPFIntf == null)
- return -1;
-
- RtcpPktRTPFB pkt = new RtcpPktRTPFB(this.ssrc, ssrcMediaSource, FMT, PID, BLP);
- ret = this.rtcpSession.addToFbQueue(ssrcMediaSource, pkt);
- if(ret == 0)
- this.rtcpSession.wakeSenderThread(ssrcMediaSource);
- return ret;
- }
-
- /**
- * Fetches the next sequence number for RTP packets.
- * @return the next sequence number
- */
- private int getNextSeqNum() {
- seqNum++;
- // 16 bit number
- if(seqNum > 65536) {
- seqNum = 0;
- }
- return seqNum;
- }
-
- /**
- * Initializes a random variable
- *
- */
- private void createRandom() {
- this.random = new Random(System.currentTimeMillis() + Thread.currentThread().getId()
- - Thread.currentThread().hashCode() + this.cname.hashCode());
- }
-
-
- /**
- * Generates a random sequence number
- */
- private void generateSeqNum() {
- if(this.random == null)
- createRandom();
-
- seqNum = this.random.nextInt();
- if(seqNum < 0)
- seqNum = -seqNum;
- while(seqNum > 65535) {
- seqNum = seqNum / 10;
- }
- }
-
- /**
- * Generates a random SSRC
- */
- private void generateSsrc() {
- if(this.random == null)
- createRandom();
-
- // Set an SSRC
- this.ssrc = this.random.nextInt();
- if(this.ssrc < 0) {
- this.ssrc = this.ssrc * -1;
- }
- }
-
- /**
- * Resolve an SSRC conflict.
- *
- * Also increments the SSRC conflict counter, after 5 conflicts
- * it is assumed there is a loop somewhere and the session will
- * terminate.
- *
- */
- protected void resolveSsrcConflict() {
- System.out.println("!!!!!!! Beginning SSRC conflict resolution !!!!!!!!!");
- this.conflictCount++;
-
- if(this.conflictCount < 5) {
- //Don't send any more regular packets out until we have this sorted out.
- this.conflict = true;
-
- //Send byes
- rtcpSession.sendByes();
-
- //Calculate the next delay
- rtcpSession.calculateDelay();
-
- //Generate a new Ssrc for ourselves
- generateSsrc();
-
- //Get the SDES packets out faster
- rtcpSession.initial = true;
-
- this.conflict = false;
- System.out.println("SSRC conflict resolution complete");
-
- } else {
- System.out.println("Too many conflicts. There is probably a loop in the network.");
- this.endSession();
- }
- }
-}
--- a/src/jlibrtp/RtcpPkt.java Thu May 28 14:26:06 2009 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,134 +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.InetAddress;
-/**
- * Common RTCP packet headers.
- *
- * @author Arne Kepp
- */
-public class RtcpPkt {
- /** Whether a problem has been encountered during parsing */
- protected int problem = 0;
- /** The version, always 2, 2 bits */
- protected int version = 2;
- /** Padding , 1 bit */
- protected int padding = 0;
- /** Number of items, e.g. receiver report blocks. Usage may vary. 5 bits */
- protected int itemCount = 0;
- /** The type of RTCP packet, 8 bits */
- protected int packetType = -1;
- /** The length of the RTCP packet, in 32 bit blocks minus 1. 16 bits*/
- protected int length = -1;
- /** The ssrc that sent this, usually dictated by RTP Session */
- protected long ssrc = -1;
-
- /** Contains the actual data (eventually) */
- protected byte[] rawPkt = null;
-
- /** Only used for feedback messages: Time message was generated */
- protected long time = -1;
- /** Only used for feedback message: Whether this packet was received */
- protected boolean received = false;
-
-
- /**
- * Parses the common header of an RTCP packet
- *
- * @param start where in this.rawPkt the headers start
- * @return true if parsing succeeded and header cheks
- */
- protected boolean parseHeaders(int start) {
- version = ((rawPkt[start+0] & 0xC0) >>> 6);
- padding = ((rawPkt[start+0] & 0x20) >>> 5);
- itemCount = (rawPkt[start+0] & 0x1F);
- packetType = (int) rawPkt[start+1];
- if(packetType < 0) {
- packetType += 256;
- }
- length = StaticProcs.bytesToUIntInt(rawPkt, start+2);
-
- if(RTPSession.rtpDebugLevel > 9) {
- System.out.println(" <-> RtcpPkt.parseHeaders() version:"+version+" padding:"+padding+" itemCount:"+itemCount
- +" packetType:"+packetType+" length:"+length);
- }
-
- if(packetType > 207 || packetType < 200)
- System.out.println("RtcpPkt.parseHeaders problem discovered, packetType " + packetType);
-
- if(version == 2 && length < 65536) {
- return true;
- } else {
- System.out.println("RtcpPkt.parseHeaders() failed header checks, check size and version");
- this.problem = -1;
- return false;
- }
- }
- /**
- * Writes the common header of RTCP packets.
- * The values should be filled in when the packet is initiliazed and this function
- * called at the very end of .encode()
- */
- protected void writeHeaders() {
- byte aByte = 0;
- aByte |=(version << 6);
- aByte |=(padding << 5);
- aByte |=(itemCount);
- rawPkt[0] = aByte;
- aByte = 0;
- aByte |= packetType;
- rawPkt[1] = aByte;
- if(rawPkt.length % 4 != 0)
- System.out.println("!!!! RtcpPkt.writeHeaders() rawPkt was not a multiple of 32 bits / 4 octets!");
- byte[] someBytes = StaticProcs.uIntIntToByteWord((rawPkt.length / 4) - 1);
- rawPkt[2] = someBytes[0];
- rawPkt[3] = someBytes[1];
- }
-
- /**
- * This is just a dummy to make Eclipse complain less.
- */
- protected void encode() {
- System.out.println("RtcpPkt.encode() should never be invoked!! " + this.packetType);
- }
-
- /**
- * Check whether this packet came from the source we expected.
- *
- * Not currently used!
- *
- * @param adr address that packet came from
- * @param partDb the participant database for the session
- * @return true if this packet came from the expected source
- */
- protected boolean check(InetAddress adr, ParticipantDatabase partDb) {
- //Multicast -> We have to be naive
- if (partDb.rtpSession.mcSession && adr.equals(partDb.rtpSession.mcGroup))
- return true;
-
- //See whether this participant is known
- Participant part = partDb.getParticipant(this.ssrc);
- if(part != null && part.rtcpAddress.getAddress().equals(adr))
- return true;
-
- //If not, we should look for someone without SSRC with his ip-address?
- return false;
- }
-}
--- a/src/jlibrtp/RtcpPktAPP.java Thu May 28 14:26:06 2009 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,91 +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;
-
-/**
- * Application specific RTCP packets
- *
- * @author Arne Kepp
- */
-public class RtcpPktAPP extends RtcpPkt {
- /** Name of packet, 4 bytes ASCII */
- protected byte[] pktName = null;
- /** Data of packet */
- protected byte[] pktData = null;
-
- /**
- * Constructor for a new Application RTCP packet
- *
- * @param ssrc the SSRC of the sender, presumably taken from RTPSession
- * @param subtype the subtype of packet, application specific
- * @param pktName byte[4] representing ASCII name of packet
- * @param pktData the byte[4x] data that represents the message itself
- */
- protected RtcpPktAPP(long ssrc, int subtype, byte[] pktName, byte[] pktData) {
- // Fetch all the right stuff from the database
- super.ssrc = ssrc;
- super.packetType = 204;
- super.itemCount = subtype;
- this.pktName = pktName;
- this.pktData = pktData;
- }
-
- /**
- * Constructor that parses a received Application RTCP packet
- *
- * @param aRawPkt the raw packet containing the date
- * @param start where in the raw packet this packet starts
- */
- protected RtcpPktAPP(byte[] aRawPkt, int start) {
- super.ssrc = StaticProcs.bytesToUIntLong(aRawPkt,4);
- super.rawPkt = aRawPkt;
-
- if(!super.parseHeaders(start) || packetType != 204 ) {
- if(RTPSession.rtpDebugLevel > 2) {
- System.out.println(" <-> RtcpPktAPP.parseHeaders() etc. problem");
- }
- super.problem = -204;
- } else {
- //System.out.println("super.length: " + super.length);
- if(super.length > 1) {
- pktName = new byte[4];
- System.arraycopy(aRawPkt, 8, pktName, 0, 4);
- }
- if(super.length > 2) {
- pktData = new byte[(super.length+1)*4 - 12];
- System.arraycopy(aRawPkt, 12, pktData, 0, pktData.length);
- }
- }
- }
-
- /**
- * Encode the packet into a byte[], saved in .rawPkt
- *
- * CompRtcpPkt will call this automatically
- */
- protected void encode() {
- super.rawPkt = new byte[12 + this.pktData.length];
- byte[] tmp = StaticProcs.uIntLongToByteWord(super.ssrc);
- System.arraycopy(tmp, 0, super.rawPkt, 4, 4);
- System.arraycopy(this.pktName, 0, super.rawPkt, 8, 4);
- System.arraycopy(this.pktData, 0, super.rawPkt, 12, this.pktData.length);
- writeHeaders();
- //System.out.println("ENCODE: " + super.length + " " + rawPkt.length + " " + pktData.length);
- }
-}
--- a/src/jlibrtp/RtcpPktBYE.java Thu May 28 14:26:06 2009 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,107 +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;
-
-/**
- * RTCP packets for sending Bye messages
- *
- * @author Arne Kepp
- */
-public class RtcpPktBYE extends RtcpPkt {
- /** SSRCs saying bye, 32xn bits, n<16 */
- protected long[] ssrcArray = null;
- /** Optional reason */
- protected byte[] reason = null;
-
- protected RtcpPktBYE(long[] ssrcs,byte[] aReason) {
- super.packetType = 203;
- // Fetch all the right stuff from the database
- reason = aReason;
- ssrcArray = ssrcs;
- if(ssrcs.length < 1) {
- System.out.println("RtcpBYE.RtcpPktBYE(long[] ssrcs, byte[] aReason) requires at least one SSRC!");
- }
- }
-
- protected RtcpPktBYE(byte[] aRawPkt, int start) {
- rawPkt = aRawPkt;
- if(!super.parseHeaders(start) || packetType != 203 ) {
- if(RTPSession.rtpDebugLevel > 2) {
- System.out.println(" <-> RtcpPktBYE.parseHeaders() etc. problem");
- }
- super.problem = -203;
- } else {
- ssrcArray = new long[super.itemCount];
-
- for(int i=0; i<super.itemCount; i++) {
- ssrcArray[i] = StaticProcs.bytesToUIntLong(aRawPkt, start + (i+1)*4);
- }
- if(super.length > (super.itemCount + 1)) {
- int reasonLength = (int) aRawPkt[start + (super.itemCount+1)*4];
- //System.out.println("super.itemCount:"+super.itemCount+" reasonLength:"+reasonLength+" start:"+(super.itemCount*4 + 4 + 1));
- reason = new byte[reasonLength];
- System.arraycopy(aRawPkt, start + (super.itemCount + 1)*4 + 1, reason, 0, reasonLength);
- //System.out.println("test:" + new String(reason));
- }
- }
- }
-
- protected void encode() {
- itemCount = ssrcArray.length;
- length = 4*ssrcArray.length;
-
- if(reason != null) {
- length += (reason.length + 1)/4;
- if((reason.length + 1) % 4 != 0) {
- length +=1;
- }
- }
- rawPkt = new byte[length*4 + 4];
-
- int i;
- byte[] someBytes;
-
- // SSRCs
- for(i=0; i<ssrcArray.length; i++ ) {
- someBytes = StaticProcs.uIntLongToByteWord(ssrcArray[i]);
- System.arraycopy(someBytes, 0, rawPkt, 4 + 4*i, 4);
- }
-
- // Reason for leaving
- if(reason != null) {
- //System.out.println("Writing to:"+(4+4*ssrcArray.length)+ " reason.length:"+reason.length );
- rawPkt[(4 + 4*ssrcArray.length)] = (byte) reason.length;
- System.arraycopy(reason, 0, rawPkt, 4+4*i +1, reason.length);
- }
- super.writeHeaders();
- }
-
- public void debugPrint() {
- System.out.println("RtcpPktBYE.debugPrint() ");
- if(ssrcArray != null) {
- for(int i= 0; i<ssrcArray.length; i++) {
- long anSsrc = ssrcArray[i];
- System.out.println(" ssrc: " + anSsrc);
- }
- }
- if(reason != null) {
- System.out.println(" Reason: " + new String(reason));
- }
- }
-}
\ No newline at end of file
--- a/src/jlibrtp/RtcpPktPSFB.java Thu May 28 14:26:06 2009 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,395 +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;
-
-/**
- * RTCP packets for Payload-Specific Feedback Messages
- *
- * @author Arne Kepp
- */
-public class RtcpPktPSFB extends RtcpPkt {
- /** If this packet was for a different SSRC */
- protected boolean notRelevant = false;
- /** Parent RTP Session */
- private RTPSession rtpSession;
- /** SSRC we are sending feeback to */
- protected long ssrcMediaSource = -1;
-
- /** SLI macroblock (MB) address of the first lost macroblock number */
- protected int[] sliFirst;
- /** SLI number of lost macroblocks */
- protected int[] sliNumber;
- /** SLI six least significant bits of the codec-specific identifier */
- protected int[] sliPictureId;
-
- // Picture loss indication
- /** RPSI number of padded bits at end of bitString */
- protected int rpsiPadding = -1;
- /** RPSI payloadType RTP payload type */
- protected int rpsiPayloadType = -1;
- /** RPSI information as natively defined by the video codec */
- protected byte[] rpsiBitString;
-
- /** Application Layer Feedback Message */
- protected byte[] alfBitString;
-
- /**
- * Generic constructor, then call make<something>
- *
- * @param ssrcPacketSender
- * @param ssrcMediaSource
- */
- protected RtcpPktPSFB(long ssrcPacketSender, long ssrcMediaSource) {
- super.ssrc = ssrcPacketSender;
- this.ssrcMediaSource = ssrcMediaSource;
- super.packetType = 206; //PSFB
- }
-
- /**
- * Make this packet a Picture loss indication
- */
- protected void makePictureLossIndication() {
- super.itemCount = 1; //FMT
- }
-
- /**
- * Make this packet a Slice Loss Indication
- *
- * @param sliFirst macroblock (MB) address of the first lost macroblock
- * @param sliNumber number of lost macroblocks
- * @param sliPictureId six least significant bits of the codec-specific identifier
- */
- protected void makeSliceLossIndication(int[] sliFirst, int[] sliNumber, int[] sliPictureId) {
- super.itemCount = 2; //FMT
- this.sliFirst = sliFirst;
- this.sliNumber = sliNumber;
- this.sliPictureId = sliPictureId;
- }
-
- /**
- * Make this packet a Reference Picture Selection Indication
- *
- * @param bitPadding number of padded bits at end of bitString
- * @param payloadType RTP payload type for codec
- * @param bitString RPSI information as natively defined by the video codec
- */
- protected void makeRefPictureSelIndic(int bitPadding, int payloadType, byte[] bitString) {
- super.itemCount = 3; //FMT
- this.rpsiPadding = bitPadding;
- this.rpsiPayloadType = payloadType;
- this.rpsiBitString = bitString;
- }
-
- /**
- * Make this packet an Application specific feedback message
- *
- * @param bitString the original application message
- */
- protected void makeAppLayerFeedback(byte[] bitString) {
- super.itemCount = 15; //FMT
- this.alfBitString = bitString;
- }
-
- /**
- * Constructor that parses a raw packet to retrieve information
- *
- * @param aRawPkt the raw packet to be parsed
- * @param start the start of the packet, in bytes
- * @param rtpSession the session on which the callback interface resides
- */
- protected RtcpPktPSFB(byte[] aRawPkt, int start, RTPSession rtpSession) {
- if(RTPSession.rtpDebugLevel > 8) {
- System.out.println(" -> RtcpPktPSFB(byte[], int start)");
- }
- this.rtpSession = rtpSession;
-
- rawPkt = aRawPkt;
-
- if(! super.parseHeaders(start) || packetType != 206 || super.length < 2 ) {
- if(RTPSession.rtpDebugLevel > 2) {
- System.out.println(" <-> RtcpPktRTPFB.parseHeaders() etc. problem");
- }
- super.problem = -206;
- } else {
- //FMT = super.itemCount;
- ssrcMediaSource = StaticProcs.bytesToUIntLong(aRawPkt,8+start);
-
- if(ssrcMediaSource == rtpSession.ssrc) {
- super.ssrc = StaticProcs.bytesToUIntLong(aRawPkt,4+start);
-
- switch(super.itemCount) {
- case 1: // Picture Loss Indication
- decPictureLossIndic();
- break;
- case 2: // Slice Loss Indication
- decSliceLossIndic(aRawPkt, start + 12);
- break;
- case 3: // Reference Picture Selection Indication
- decRefPictureSelIndic(aRawPkt, start + 12);
- break;
- case 15: // Application Layer Feedback Messages
- decAppLayerFB(aRawPkt, start + 12);
- break;
- default:
- System.out.println("!!!! RtcpPktPSFB(byte[], int start) unexpected FMT " + super.itemCount);
- }
- } else {
- this.notRelevant = true;
- }
- }
- if(RTPSession.rtpDebugLevel > 8) {
- System.out.println(" <- RtcpPktPSFB()");
- }
- }
-
- /**
- * Decode Picture Loss indication
- *
- */
- private void decPictureLossIndic() {
- if(this.rtpSession.rtcpAVPFIntf != null) {
- this.rtpSession.rtcpAVPFIntf.PSFBPktPictureLossReceived(
- super.ssrc);
- }
- }
-
- /**
- * Decode Slice Loss Indication
- *
- * @param aRawPkt
- * @param start
- */
- private void decSliceLossIndic(byte[] aRawPkt, int start) {
- // 13 bit off-boundary numbers? That's rather cruel
- // 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
- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- // | First | Number | PictureID |
- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-
- int count = super.length - 2;
-
- sliFirst = new int[count];
- sliNumber = new int[count];
- sliPictureId = new int[count];
-
- // Loop over the FCI lines
- for(int i=0; i < count; i++) {
- sliFirst[i] = StaticProcs.bytesToUIntInt(aRawPkt, start) >> 3;
- sliNumber[i] = (int) (StaticProcs.bytesToUIntInt(aRawPkt, start) & 0x0007FFC0) >> 6;
- sliPictureId[i] = (StaticProcs.bytesToUIntInt(aRawPkt, start + 2) & 0x003F);
- start += 4;
- }
-
- if(this.rtpSession.rtcpAVPFIntf != null) {
- this.rtpSession.rtcpAVPFIntf.PSFBPktSliceLossIndic(
- super.ssrc,
- sliFirst, sliNumber, sliPictureId);
- }
- }
-
- /**
- * Decode Reference Picture Selection Indication
- *
- * @param aRawPkt
- * @param start
- */
- private void decRefPictureSelIndic(byte[] aRawPkt, int start) {
- // 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
- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- // | PB |0| Payload Type| Native RPSI bit string |
- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- // | defined per codec ... | Padding (0) |
- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-
- rpsiPadding = aRawPkt[start];
-
- if(rpsiPadding > 32) {
- System.out.println("!!!! RtcpPktPSFB.decRefPictureSelcIndic paddingBits: "
- + rpsiPadding);
- }
-
- rpsiPayloadType = (int) rawPkt[start];
- if(rpsiPayloadType < 0) {
- System.out.println("!!!! RtcpPktPSFB.decRefPictureSelcIndic 8th bit not zero: "
- + rpsiPayloadType);
- }
-
- rpsiBitString = new byte[(super.length - 2)*4 - 2];
- System.arraycopy(aRawPkt, start + 2, rpsiBitString, 0, rpsiBitString.length);
-
- if(this.rtpSession.rtcpAVPFIntf != null) {
- this.rtpSession.rtcpAVPFIntf.PSFBPktRefPictureSelIndic(
- super.ssrc,
- rpsiPayloadType, rpsiBitString, rpsiPadding);
- }
-
- }
-
- /**
- * Decode Application specific feedback message
- *
- * @param aRawPkt
- * @param start
- */
- private void decAppLayerFB(byte[] aRawPkt, int start) {
- //Application Message (FCI): variable length
- int stringLength = (super.length - 2)*4;
-
- alfBitString = new byte[stringLength];
-
- System.arraycopy(aRawPkt, start, alfBitString, 0, stringLength);
-
- if(this.rtpSession.rtcpAVPFIntf != null) {
- this.rtpSession.rtcpAVPFIntf.PSFBPktAppLayerFBReceived(
- super.ssrc, alfBitString);
- }
- }
-
-
-
- /**
- * Encode a Slice Loss Indication
- */
- private void encSliceLossIndic() {
- byte[] firstBytes;
- byte[] numbBytes;
- byte[] picBytes;
-
- int offset = 8;
- // Loop over the FCI lines
- for(int i=0; i < sliFirst.length; i++) {
- offset = 8 + 8*i;
- firstBytes = StaticProcs.uIntLongToByteWord(sliFirst[i] << 3);
- numbBytes = StaticProcs.uIntLongToByteWord(sliNumber[i] << 2);
- picBytes = StaticProcs.uIntIntToByteWord(sliPictureId[i]);
-
- super.rawPkt[offset] = firstBytes[2];
- super.rawPkt[offset+1] = (byte) (firstBytes[3] | numbBytes[2]);
- super.rawPkt[offset+2] = numbBytes[3];
- super.rawPkt[offset+3] = (byte) (numbBytes[3] | picBytes[1]);
- }
- }
-
- /**
- * Encode a Reference Picture Selection Indication
- *
- */
- private void encRefPictureSelIndic() {
- byte[] someBytes;
- someBytes = StaticProcs.uIntIntToByteWord(rpsiPadding);
- super.rawPkt[8] = someBytes[1];
- someBytes = StaticProcs.uIntIntToByteWord(rpsiPayloadType);
- super.rawPkt[9] = someBytes[1];
-
- System.arraycopy(rpsiBitString, 0, super.rawPkt, 10, rpsiBitString.length);
- }
-
-
- /**
- * Encode Application Layer Feedback
- *
- */
- private void encAppLayerFB() {
- //Application Message (FCI): variable length
- System.arraycopy(alfBitString, 0, super.rawPkt, 8, alfBitString.length);
- }
-
- /**
- * Get the FMT (Feedback Message Type)
- * @return value stored in .itemcount, same field
- */
- protected int getFMT() {
- return this.itemCount;
- }
-
- /**
- * Encode the packet into a byte[], saved in .rawPkt
- *
- * CompRtcpPkt will call this automatically
- */
- protected void encode() {
- switch(super.itemCount) {
- case 1: // Picture Loss Indication
- //Nothing to do really
- super.rawPkt = new byte[24];
- break;
- case 2: // Slice Loss Indication
- super.rawPkt = new byte[24 + 4*this.sliFirst.length];
- encSliceLossIndic();
- break;
- case 3: // Reference Picture Selection Indication
- super.rawPkt = new byte[24 + 2 + this.rpsiBitString.length/4];
- encRefPictureSelIndic();
- break;
- case 15: // Application Layer Feedback Messages
- super.rawPkt = new byte[24 + this.alfBitString.length/4];
- encAppLayerFB();
- break;
- }
-
- byte[] someBytes = StaticProcs.uIntLongToByteWord(super.ssrc);
- System.arraycopy(someBytes, 0, super.rawPkt, 4, 4);
- someBytes = StaticProcs.uIntLongToByteWord(this.ssrcMediaSource);
- System.arraycopy(someBytes, 0, super.rawPkt, 8, 4);
-
- writeHeaders();
- }
-
- /**
- * Debug purposes only
- */
- public void debugPrint() {
- System.out.println("->RtcpPktPSFB.debugPrint() ");
-
- String str;
- switch(super.itemCount) {
- case 1: // Picture Loss Indication
- System.out.println(" FMT: Picture Loss Indication");
- break;
- case 2: // Slice Loss Indication
- if(sliFirst != null) {
- str = "sliFirst[].length: " + sliFirst.length;
- } else {
- str = "sliFirst[] is null";
- }
- System.out.println(" FMT: Slice Loss Indication, " + str);
- break;
- case 3: // Reference Picture Selection Indication
- if(rpsiBitString != null) {
- str = "rpsiBitString[].length: " + rpsiBitString.length;
- } else {
- str = "rpsiBitString[] is null";
- }
- System.out.println(" FMT: Reference Picture Selection Indication, "
- + str + " payloadType: " + this.rpsiPayloadType);
- break;
- case 15: // Application Layer Feedback Messages
- if(alfBitString != null) {
- str = "alfBitString[].length: " + alfBitString.length;
- } else {
- str = "alfBitString[] is null";
- }
- System.out.println(" FMT: Application Layer Feedback Messages, " + str);
- break;
- }
-
- System.out.println("<-RtcpPktPSFB.debugPrint() ");
- }
-}
--- a/src/jlibrtp/RtcpPktRR.java Thu May 28 14:26:06 2009 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,222 +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;
-
-/**
- * RTCP packets for Receiver Reports
- *
- * @author Arne Kepp
- */
-public class RtcpPktRR extends RtcpPkt {
- /** Array of participants to send Receiver Reports to */
- protected Participant[] reportees = null;
- /** SSRC of participants the reports are for */
- protected long[] reporteeSsrc = null;// -1; //32 bits
- /** Fraction (over 256) of packets lost */
- protected int[] lossFraction = null;//-1; //8 bits
- /** Number of lost packets */
- protected int[] lostPktCount = null;//-1; //24 bits
- /** Extended highest sequence received */
- protected long[] extHighSeqRecv = null;//-1; //32 bits
- /** Interarrival jitter*/
- protected long[] interArvJitter = null;//-1; //32 bits
- /** Middle 32 bits of NTP when last SR was received */
- protected long[] timeStampLSR = null;//-1; //32 bits
- /** Delay on last SRC */
- protected long[] delaySR = null;//-1; //32 bits
-
- /**
- * Constructor for a packet with receiver reports
- *
- * @param reportees the participants on which to generate reports
- * @param ssrc the SSRC of the sender, from the RTPSession
- */
- protected RtcpPktRR(Participant[] reportees, long ssrc) {
- super.packetType = 201;
- // Fetch all the right stuff from the database
- super.ssrc = ssrc;
- this.reportees = reportees;
- }
-
-
- /**
- *
- *
- * If rcount < 0 we assume we have to parse the entire packet,
- * otherwise we'll just parse the receiver report blocks
- * (ie. the data came from a Sender Report packet)
- *
- * @param aRawPkt the byte[] with the report(s)
- * @param start where in the raw packet to start reading
- * @param rrCount the number of receiver reports, -1 if this does not come from an SR
- */
- protected RtcpPktRR(byte[] aRawPkt, int start, int rrCount) {
- //System.out.println("RtcpPktRR: " + rrCount + " start: " + start);
- super.rawPkt = aRawPkt;
-
- if(rrCount < 0 && (!super.parseHeaders(start) || packetType != 201 || super.length < 1)) {
- if(RTPSession.rtpDebugLevel > 2) {
- System.out.println(" <-> RtcpPktRR.parseHeaders() etc. problem: "+(!super.parseHeaders(start))+" "+packetType+" "+super.length);
- }
- super.problem = -201;
- }
-
- int base;
- if(rrCount > 0) {
- base = start + 28;
- } else {
- base = start + 8;
- rrCount = super.itemCount;
- super.ssrc = StaticProcs.bytesToUIntLong(aRawPkt, start + 4);
- }
-
- if(rrCount > 0) {
- reporteeSsrc = new long[rrCount];
- lossFraction = new int[rrCount];
- lostPktCount = new int[rrCount];
- extHighSeqRecv = new long[rrCount];
- interArvJitter = new long[rrCount];
- timeStampLSR = new long[rrCount];
- delaySR = new long[rrCount];
-
- for(int i=0; i<rrCount; i++ ) {
- int pos = base + i*24;
- reporteeSsrc[i] = StaticProcs.bytesToUIntLong(aRawPkt, pos);
- lossFraction[i] = (int) aRawPkt[pos + 4];
- aRawPkt[pos + 4] = (byte) 0;
- lostPktCount[i] = (int) StaticProcs.bytesToUIntLong(aRawPkt, pos + 4);
- extHighSeqRecv[i] = StaticProcs.bytesToUIntLong(aRawPkt, pos + 8);
- interArvJitter[i] = StaticProcs.bytesToUIntLong(aRawPkt, pos + 12);
- timeStampLSR[i] = StaticProcs.bytesToUIntLong(aRawPkt, pos + 16);
- delaySR[i] = StaticProcs.bytesToUIntLong(aRawPkt, pos + 20);
- }
- }
- }
-
- /**
- * Encode the packet into a byte[], saved in .rawPkt
- *
- * CompRtcpPkt will call this automatically
- */
- protected void encode() {
- if(RTPSession.rtpDebugLevel > 9) {
- System.out.println(" -> RtcpPktRR.encode()");
- }
-
- byte[] rRs = null;
- //Gather up the actual receiver reports
- if(this.reportees != null) {
- rRs = this.encodeRR();
- super.rawPkt = new byte[rRs.length + 8];
- System.arraycopy(rRs, 0, super.rawPkt, 8, rRs.length);
- super.itemCount = reportees.length;
- } else {
- super.rawPkt = new byte[8];
- super.itemCount = 0;
- }
-
- //Write the common header
- super.writeHeaders();
-
- //Add our SSRC (as sender)
- byte[] someBytes;
- someBytes = StaticProcs.uIntLongToByteWord(super.ssrc);
- System.arraycopy(someBytes, 0, super.rawPkt, 4, 4);
-
- if(RTPSession.rtpDebugLevel > 9) {
- System.out.println(" <- RtcpPktRR.encode()");
- }
-
- }
-
- /**
- * Encodes the individual Receiver Report blocks,
- *
- * so they can be used either in RR packets or appended to SR
- *
- * @return the encoded packets
- */
- protected byte[] encodeRR() {
- if(RTPSession.rtpDebugLevel > 10) {
- System.out.println(" -> RtcpPktRR.encodeRR()");
- }
- //assuming we will always create complete reports:
- byte[] ret = new byte[24*reportees.length];
-
- //Write SR stuff
- for(int i = 0; i<reportees.length; i++) {
- int offset = 24*i;
- byte[] someBytes = StaticProcs.uIntLongToByteWord(reportees[i].ssrc);
- System.arraycopy(someBytes, 0, ret, offset, 4);
-
- //Cumulative number of packets lost
- someBytes = StaticProcs.uIntLongToByteWord(reportees[i].getLostPktCount());
-
- someBytes[0] = (byte) reportees[i].getFractionLost();
-
- //Write Cumulative number of packets lost and loss fraction to packet:
- System.arraycopy(someBytes, 0, ret, 4 + offset, 4);
-
- // Extended highest sequence received
- someBytes = StaticProcs.uIntLongToByteWord(reportees[i].getExtHighSeqRecv());
- System.arraycopy(someBytes, 0, ret, 8 + offset, 4);
-
- // Interarrival jitter
- if(reportees[i].interArrivalJitter >= 0) {
- someBytes = StaticProcs.uIntLongToByteWord((long)reportees[i].interArrivalJitter);
- } else {
- someBytes = StaticProcs.uIntLongToByteWord((long) 0);
- }
- System.arraycopy(someBytes, 0, ret, 12 + offset, 4);
-
- // Timestamp last sender report received
- someBytes = StaticProcs.uIntLongToByteWord(reportees[i].timeStampLSR);
- System.arraycopy(someBytes, 0, ret, 16 + offset, 4);
-
- // Delay since last sender report received, in terms of 1/655536 s = 0.02 ms
- if(reportees[i].timeReceivedLSR > 0) {
- someBytes = StaticProcs.uIntLongToByteWord(reportees[i].delaySinceLastSR());
- } else {
- someBytes = StaticProcs.uIntLongToByteWord(0);
- }
- System.arraycopy(someBytes, 0, ret, 20 + offset, 4);
- }
- if(RTPSession.rtpDebugLevel > 10) {
- System.out.println(" <- RtcpPktRR.encodeRR()");
- }
- return ret;
- }
-
- /**
- * Debug purposes only
- */
- public void debugPrint() {
- System.out.println("RtcpPktRR.debugPrint() ");
- if(reportees != null) {
- for(int i= 0; i<reportees.length; i++) {
- Participant part = reportees[i];
- System.out.println(" part.ssrc: " + part.ssrc + " part.cname: " + part.cname);
- }
- } else {
- for(int i=0;i<reporteeSsrc.length; i++) {
- System.out.println(" reporteeSSRC: " + reporteeSsrc[i] + " timeStampLSR: " + timeStampLSR[i]);
- }
- }
- }
-}
--- a/src/jlibrtp/RtcpPktRTPFB.java Thu May 28 14:26:06 2009 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,154 +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;
-
-/**
- * RTCP packets for RTP Feedback Messages
- *
- * In line with RFC 4585, this packet currently only supports NACKs
- *
- * @author Arne Kepp
- */
-public class RtcpPktRTPFB extends RtcpPkt {
- /** If this packet was for a different SSRC */
- protected boolean notRelevant = false;
- /** SSRC we are sending feeback to */
- protected long ssrcMediaSource = -1;
- /** RTP sequence numbers of lost packets */
- protected int PID[];
- /** bitmask of following lost packets, shared index with PID */
- protected int BLP[];
-
- /**
- * Constructor for RTP Feedback Message
- *
- * @param ssrcPacketSender SSRC of sender, taken from RTPSession
- * @param ssrcMediaSource SSRC of recipient of this message
- * @param FMT the Feedback Message Subtype
- * @param PID RTP sequence numbers of lost packets
- * @param BLP bitmask of following lost packets, shared index with PID
- */
- protected RtcpPktRTPFB(long ssrcPacketSender, long ssrcMediaSource, int FMT, int[] PID, int[] BLP) {
- super.packetType = 205; //RTPFB
- super.itemCount = FMT;
- this.PID = PID;
- this.BLP = BLP;
- }
-
- /**
- * Constructor that parses a raw packet to retrieve information
- *
- * @param aRawPkt the raw packet to be parsed
- * @param start the start of the packet, in bytes
- * @param rtpSession the session on which the callback interface resides
- */
- protected RtcpPktRTPFB(byte[] aRawPkt, int start, RTPSession rtpSession) {
- if(RTPSession.rtpDebugLevel > 8) {
- System.out.println(" -> RtcpPktRTPFB(byte[], int start)");
- }
-
- rawPkt = aRawPkt;
-
- if(! super.parseHeaders(start) || packetType != 205 || super.length < 2) {
- if(RTPSession.rtpDebugLevel > 2) {
- System.out.println(" <-> RtcpPktRTPFB.parseHeaders() etc. problem");
- }
- super.problem = -205;
- } else {
- //FMT = super.itemCount;
-
- ssrcMediaSource = StaticProcs.bytesToUIntLong(aRawPkt,8+start);
-
- if(ssrcMediaSource == rtpSession.ssrc) {
- super.ssrc = StaticProcs.bytesToUIntLong(aRawPkt,4+start);
- int loopStop = super.length - 2;
- PID = new int[loopStop];
- BLP = new int[loopStop];
- int curStart = 12;
-
- // Loop over Feedback Control Information (FCI) fields
- for(int i=0; i< loopStop; i++) {
- PID[i] = StaticProcs.bytesToUIntInt(aRawPkt, curStart);
- BLP[i] = StaticProcs.bytesToUIntInt(aRawPkt, curStart + 2);
- curStart += 4;
- }
-
- rtpSession.rtcpAVPFIntf.RTPFBPktReceived(
- super.ssrc, super.itemCount, PID, BLP);
- }
- }
-
-
-
- if(RTPSession.rtpDebugLevel > 8) {
- System.out.println(" <- RtcpPktRTPFB()");
- }
- }
-
- /**
- * Encode the packet into a byte[], saved in .rawPkt
- *
- * CompRtcpPkt will call this automatically
- */
- protected void encode() {
- super.rawPkt = new byte[12 + this.PID.length*4];
-
- byte[] someBytes = StaticProcs.uIntLongToByteWord(super.ssrc);
- System.arraycopy(someBytes, 0, super.rawPkt, 4, 4);
- someBytes = StaticProcs.uIntLongToByteWord(this.ssrcMediaSource);
- System.arraycopy(someBytes, 0, super.rawPkt, 8, 4);
-
- // Loop over Feedback Control Information (FCI) fields
- int curStart = 12;
- for(int i=0; i < this.PID.length; i++ ) {
- someBytes = StaticProcs.uIntIntToByteWord(PID[i]);
- super.rawPkt[curStart++] = someBytes[0];
- super.rawPkt[curStart++] = someBytes[1];
- someBytes = StaticProcs.uIntIntToByteWord(BLP[i]);
- super.rawPkt[curStart++] = someBytes[0];
- super.rawPkt[curStart++] = someBytes[1];
- }
- writeHeaders();
- }
-
- /**
- * Get the FMT (Feedback Message Type)
- * @return value stored in .itemcount, same field
- */
- protected int getFMT() {
- return this.itemCount;
- }
-
- /**
- * Debug purposes only
- */
- protected void debugPrint() {
- System.out.println("->RtcpPktRTPFB.debugPrint() ");
- System.out.println(" ssrcPacketSender: " + super.ssrc + " ssrcMediaSource: " + ssrcMediaSource);
-
- if(this.PID != null && this.PID.length < 1) {
- System.out.println(" No Feedback Control Information (FCI) fields");
- }
-
- for(int i=0; i < this.PID.length; i++ ) {
- System.out.println(" FCI -> PID: " + PID[i] + " BLP: " + BLP[i]);
- }
- System.out.println("<-RtcpPktRTPFB.debugPrint() ");
- }
-}
--- a/src/jlibrtp/RtcpPktSDES.java Thu May 28 14:26:06 2009 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,237 +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;
-
-/**
- * RTCP packets for Source Descriptions
- *
- * @author Arne Kepp
- */
-public class RtcpPktSDES extends RtcpPkt {
- /** Whether the RTP Session object should be inclduded */
- boolean reportSelf = true;
- /** The parent RTP Session object, holds participant database */
- RTPSession rtpSession = null;
- /** The participants to create SDES packets for */
- protected Participant[] participants = null;
-
- /**
- * Constructor to create a new SDES packet
- *
- * TODO:
- * Currently the added participants are not actually encoded
- * because the library lacks some support for acting as mixer or
- * relay in other areas.
- *
- * @param reportThisSession include information from RTPSession as a participant
- * @param rtpSession the session itself
- * @param additionalParticipants additional participants to include
- */
- protected RtcpPktSDES(boolean reportThisSession, RTPSession rtpSession, Participant[] additionalParticipants) {
- super.packetType = 202;
- // Fetch all the right stuff from the database
- reportSelf = reportThisSession;
- participants = additionalParticipants;
- this.rtpSession = rtpSession;
- }
-
- /**
- * Constructor that parses a received packet
- *
- * @param aRawPkt the byte[] containing the packet
- * @param start where in the byte[] this packet starts
- * @param socket the address from which the packet was received
- * @param partDb the participant database
- */
- protected RtcpPktSDES(byte[] aRawPkt,int start, InetSocketAddress socket, ParticipantDatabase partDb) {
- if(RTPSession.rtcpDebugLevel > 8) {
- System.out.println(" -> RtcpPktSDES(byte[], ParticipantDabase)");
- }
- rawPkt = aRawPkt;
-
- if(! super.parseHeaders(start) || packetType != 202 ) {
- if(RTPSession.rtpDebugLevel > 2) {
- System.out.println(" <-> RtcpPktSDES.parseHeaders() etc. problem");
- }
- super.problem = -202;
- } else {
- //System.out.println(" DECODE SIZE: " + super.length + " itemcount " + itemCount );
-
- int curPos = 4 + start;
- int curLength;
- int curType;
- long ssrc;
- boolean endReached = false;
- boolean newPart;
- this.participants = new Participant[itemCount];
-
- // Loop over SSRC SDES chunks
- for(int i=0; i< itemCount; i++) {
- ssrc = StaticProcs.bytesToUIntLong(aRawPkt, curPos);
- Participant part = partDb.getParticipant(ssrc);
- if(part == null) {
- if(RTPSession.rtcpDebugLevel > 1) {
- System.out.println("RtcpPktSDES(byte[], ParticipantDabase) adding new participant, ssrc:"+ssrc+" "+socket);
- }
-
- part = new Participant(socket, socket , ssrc);
- newPart = true;
- } else {
- newPart = false;
- }
-
- curPos += 4;
-
- //System.out.println("PRE endReached " + endReached + " curPos: " + curPos + " length:" + this.length + (!endReached && (curPos/4) < this.length));
-
- while(!endReached && (curPos/4) <= this.length) {
- //System.out.println("endReached " + endReached + " curPos: " + curPos + " length:" + this.length);
- curType = (int) aRawPkt[curPos];
-
- if(curType == 0) {
- curPos += 4 - (curPos % 4);
- endReached = true;
- } else {
- curLength = (int) aRawPkt[curPos + 1];
- //System.out.println("curPos:"+curPos+" curType:"+curType+" curLength:"+curLength+" read from:"+(curPos + 1));
-
- if(curLength > 0) {
- byte[] item = new byte[curLength];
- //System.out.println("curPos:"+curPos+" arawPkt.length:"+aRawPkt.length+" curLength:"+curLength);
- System.arraycopy(aRawPkt, curPos + 2, item, 0, curLength);
-
- switch(curType) {
- case 1: part.cname = new String(item); break;
- case 2: part.name = new String(item); break;
- case 3: part.email = new String(item); break;
- case 4: part.phone = new String(item); break;
- case 5: part.loc = new String(item); break;
- case 6: part.tool = new String(item); break;
- case 7: part.note = new String(item); break;
- case 8: part.priv = new String(item); break;
- }
- //System.out.println("TYPE " + curType + " value:" + new String(item) );
-
- } else {
- switch(curType) {
- case 1: part.cname = null; break;
- case 2: part.name = null; break;
- case 3: part.email = null; break;
- case 4: part.phone = null; break;
- case 5: part.loc = null; break;
- case 6: part.tool = null; break;
- case 7: part.note = null; break;
- case 8: part.priv = null; break;
- }
-
- }
- curPos = curPos + curLength + 2;
- }
- }
-
- // Save the participant
- this.participants[i] = part;
- if(newPart)
- partDb.addParticipant(2,part);
-
- //System.out.println("HEPPPPPP " + participants[i].cname );
- }
- }
- if(RTPSession.rtcpDebugLevel > 8) {
- System.out.println(" <- RtcpPktSDES()");
- }
- }
-
- /**
- * Encode the packet into a byte[], saved in .rawPkt
- *
- * CompRtcpPkt will call this automatically
- */
- protected void encode() {
- byte[] temp = new byte[1450];
- byte[] someBytes = StaticProcs.uIntLongToByteWord(this.rtpSession.ssrc);
- System.arraycopy(someBytes, 0, temp, 4, 4);
- int pos = 8;
-
- String tmpString = null;
- for(int i=1; i<9;i++) {
- switch(i) {
- case 1: tmpString = this.rtpSession.cname; break;
- case 2: tmpString = this.rtpSession.name; break;
- case 3: tmpString = this.rtpSession.email; break;
- case 4: tmpString = this.rtpSession.phone; break;
- case 5: tmpString = this.rtpSession.loc; break;
- case 6: tmpString = this.rtpSession.tool; break;
- case 7: tmpString = this.rtpSession.note; break;
- case 8: tmpString = this.rtpSession.priv; break;
- }
-
- if(tmpString != null) {
- someBytes = tmpString.getBytes();
- temp[pos] = (byte) i;
- temp[pos+1] = (byte) someBytes.length;
- System.arraycopy(someBytes, 0, temp, pos + 2, someBytes.length);
- //System.out.println("i: "+i+" pos:"+pos+" someBytes.length:"+someBytes.length);
- pos = pos + someBytes.length + 2;
- //if(i == 1 ) {
- // System.out.println("trueeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee" + tmpString);
- //}
- }
- }
- int leftover = pos % 4;
- if(leftover == 1) {
- temp[pos] = (byte) 0;
- temp[pos + 1] = (byte) 1;
- pos += 3;
- } else if(leftover == 2) {
- temp[pos] = (byte) 0;
- temp[pos + 1] = (byte) 0;
- pos += 2;
- } else if(leftover == 3) {
- temp[pos] = (byte) 0;
- temp[pos + 1] = (byte) 3;
- pos += 5;
- }
-
- // TODO Here we ought to loop over participants, if we're doing SDES for other participants.
-
- super.rawPkt = new byte[pos];
- itemCount = 1;
- //This looks wrong, but appears to be fine..
- System.arraycopy(temp, 0, super.rawPkt, 0, pos);
- writeHeaders();
- }
-
- /**
- * Debug purposes only
- */
- public void debugPrint() {
- System.out.println("RtcpPktSDES.debugPrint() ");
- if(participants != null) {
- for(int i= 0; i<participants.length; i++) {
- Participant part = participants[i];
- System.out.println(" part.ssrc: " + part.ssrc + " part.cname: " + part.cname + " part.loc: " + part.loc);
- }
- } else {
- System.out.println(" nothing to report (only valid for received packets)");
- }
- }
-}
--- a/src/jlibrtp/RtcpPktSR.java Thu May 28 14:26:06 2009 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,178 +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;
-
-/**
- * RTCP packets for Sender Reports
- *
- * @author Arne Kepp
- */
-public class RtcpPktSR extends RtcpPkt {
- /** NTP timestamp, MSB */
- protected long ntpTs1 = -1; //32 bits
- /** NTP timestamp, LSB */
- protected long ntpTs2 = -1; //32 bits
- /** RTP timestamp */
- protected long rtpTs = -1; //32 bits
- /** Senders packet count */
- protected long sendersPktCount = -1; //32 bits
- /** Senders octet count */
- protected long sendersOctCount = -1; //32 bits
- /** RR packet with receiver reports that we can append */
- protected RtcpPktRR rReports = null;
-
- /**
- * Constructor for a new Sender Report packet
- *
- * @param ssrc the senders SSRC, presumably from RTPSession
- * @param pktCount packets sent in this session
- * @param octCount octets sent in this session
- * @param rReports receiver reports, as RR packets, to be included in this packet
- */
- protected RtcpPktSR(long ssrc, long pktCount, long octCount, RtcpPktRR rReports) {
- // Fetch all the right stuff from the database
- super.ssrc = ssrc;
- super.packetType = 200;
- sendersPktCount = pktCount;
- sendersOctCount = octCount;
- this.rReports = rReports;
- }
-
- /**
- * Constructor that parses a received packet
- *
- * @param aRawPkt the raw packet
- * @param start the position at which SR starts
- * @param length used to determine number of included receiver reports
- */
- protected RtcpPktSR(byte[] aRawPkt, int start, int length) {
- if(RTPSession.rtpDebugLevel > 9) {
- System.out.println(" -> RtcpPktSR(rawPkt)");
- }
-
- super.rawPkt = aRawPkt;
-
- if(!super.parseHeaders(start) || packetType != 200 ) {
- if(RTPSession.rtpDebugLevel > 2) {
- System.out.println(" <-> RtcpPktSR.parseHeaders() etc. problem: "+ (!super.parseHeaders(start) ) + " " + packetType + " " + super.length);
- }
- super.problem = -200;
- } else {
- super.ssrc = StaticProcs.bytesToUIntLong(aRawPkt,4+start);
- if(length > 11)
- ntpTs1 = StaticProcs.bytesToUIntLong(aRawPkt,8+start);
- if(length > 15)
- ntpTs2 = StaticProcs.bytesToUIntLong(aRawPkt,12+start);
- if(length > 19)
- rtpTs = StaticProcs.bytesToUIntLong(aRawPkt,16+start);
- if(length > 23)
- sendersPktCount = StaticProcs.bytesToUIntLong(aRawPkt,20+start);
- if(length > 27)
- sendersOctCount = StaticProcs.bytesToUIntLong(aRawPkt,24+start);
-
- // RRs attached?
- if(itemCount > 0) {
- rReports = new RtcpPktRR(rawPkt,start,itemCount);
- }
- }
-
- if(RTPSession.rtpDebugLevel > 9) {
- System.out.println(" <- RtcpPktSR(rawPkt)");
- }
- }
-
- /**
- * Encode the packet into a byte[], saved in .rawPkt
- *
- * CompRtcpPkt will call this automatically
- */
- protected void encode() {
- if(RTPSession.rtpDebugLevel > 9) {
- if(this.rReports != null) {
- System.out.println(" -> RtcpPktSR.encode() receptionReports.length: " + this.rReports.length );
- } else {
- System.out.println(" -> RtcpPktSR.encode() receptionReports: null");
- }
- }
-
- if(this.rReports != null) {
- super.itemCount = this.rReports.reportees.length;
-
- byte[] tmp = this.rReports.encodeRR();
- super.rawPkt = new byte[tmp.length+28];
- //super.length = (super.rawPkt.length / 4) - 1;
-
- System.arraycopy(tmp, 0, super.rawPkt, 28, tmp.length);
-
- } else {
- super.itemCount = 0;
- super.rawPkt = new byte[28];
- //super.length = 6;
- }
- //Write the common header
- super.writeHeaders();
-
- // Convert to NTP and chop up
- long timeNow = System.currentTimeMillis();
- ntpTs1 = 2208988800L + (timeNow/1000);
- long ms = timeNow % 1000;
- double tmp = ((double)ms) / 1000.0;
- tmp = tmp * (double)4294967295L;
- ntpTs2 = (long) tmp;
- rtpTs = System.currentTimeMillis();
-
- //Write SR stuff
- byte[] someBytes;
- someBytes = StaticProcs.uIntLongToByteWord(super.ssrc);
- System.arraycopy(someBytes, 0, super.rawPkt, 4, 4);
- someBytes = StaticProcs.uIntLongToByteWord(ntpTs1);
- System.arraycopy(someBytes, 0, super.rawPkt, 8, 4);
- someBytes = StaticProcs.uIntLongToByteWord(ntpTs2);
- System.arraycopy(someBytes, 0, super.rawPkt, 12, 4);
- someBytes = StaticProcs.uIntLongToByteWord(rtpTs);
- System.arraycopy(someBytes, 0, super.rawPkt, 16, 4);
- someBytes = StaticProcs.uIntLongToByteWord(sendersPktCount);
- System.arraycopy(someBytes, 0, super.rawPkt, 20, 4);
- someBytes = StaticProcs.uIntLongToByteWord(sendersOctCount);
- System.arraycopy(someBytes, 0, super.rawPkt, 24, 4);
-
- if(RTPSession.rtpDebugLevel > 9) {
- System.out.println(" <- RtcpPktSR.encode() ntpTs1: "
- + Long.toString(ntpTs1) + " ntpTs2: " + Long.toString(ntpTs2));
- }
- }
-
- /**
- * Debug purposes only
- */
- public void debugPrint() {
- System.out.println("RtcpPktSR.debugPrint() ");
- System.out.println(" SSRC:"+Long.toString(super.ssrc) +" ntpTs1:"+Long.toString(ntpTs1)
- +" ntpTS2:"+Long.toString(ntpTs2)+" rtpTS:"+Long.toString(rtpTs)
- +" senderPktCount:"+Long.toString(sendersPktCount)+" sendersOctetCount:"
- +Long.toString(sendersOctCount));
- if(this.rReports != null) {
- System.out.print(" Part of Sender Report: ");
- this.rReports.debugPrint();
- System.out.println(" End Sender Report");
- } else {
- System.out.println("No Receiver Reports associated with this Sender Report.");
- }
- }
-}
--- a/src/jlibrtp/RtpPkt.java Thu May 28 14:26:06 2009 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,370 +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;
-
-/**
- * RtpPkt is the basic class for creating and parsing RTP packets.
- *
- * There are two ways of instantiating an RtpPkt. One is for packets that you wish to send,
- * which requires that you provide basic information about the packet and a payload. Upon calling
- * encode() the fields of the structure are written into a bytebuffer, in the form that it would
- * sent across the network, excluding the UDP headers.
- *
- * The other way is by passing a bytebuffer. The assumption is that this is a packet
- * that has been received from the network, excluding UDP headers, and the bytebuffer will
- * be parsed into the correct fields.
- *
- * The class keeps track of changes. Therefore, modifications are possible after calling encode(),
- * if necessary, the raw version of the packet will be regenerated on subsequent requests.
- *
- * @author Arne Kepp
- */
-public class RtpPkt {
- /** Whether the packet has been changed since encode() */
- private boolean rawPktCurrent = false;
- /** The version, always 2, 2 bits */
- private int version = 2; //2 bits
- /** Whether the packet is padded, 1 bit */
- private int padding; //1 bit
- /** Whether and extension is used, 1 bit */
- private int extension = 0; //1 bit
- /** Whether the packet is marked, 1 bit */
- private int marker = 0; //1 bit
- /** What payload type is used, 7 bits */
- private int payloadType; //
- /** The sequence number, taken from RTP Session, 16 bits */
- private int seqNumber; //16 bits
- /** The RTP timestamp, 32bits */
- private long timeStamp; //32 bits
- /** The SSRC of the packet sender, 32 bits*/
- private long ssrc; //32 bits
- /** SSRCs of contributing sources, 32xn bits, n<16 */
- private long[] csrcArray = null;//
-
- /** Contains the actual data (eventually) */
- private byte[] rawPkt = null;
- /** The actual data, without any RTP stuff */
- private byte[] payload = null;
-
- /**
- * Construct a packet-instance. The ByteBuffer required for UDP transmission can afterwards be obtained from getRawPkt(). If you need to set additional parameters, such as the marker bit or contributing sources, you should do so before calling getRawPkt;
- *
- * @param aTimeStamp RTP timestamp for data
- * @param syncSource the SSRC, usually taken from RTPSession
- * @param seqNum Sequency number
- * @param plt Type of payload
- * @param pl Payload, the actual data
- */
- protected RtpPkt(long aTimeStamp, long syncSource, int seqNum, int plt, byte[] pl){
- int test = 0;
- test += setTimeStamp(aTimeStamp);
- test += setSsrc(syncSource);
- test += setSeqNumber(seqNum);
- test += setPayloadType(plt);
- test += setPayload(pl);
- if(test != 0) {
- System.out.println("RtpPkt() failed, check with checkPkt()");
- }
- rawPktCurrent = true;
- if( RTPSession.rtpDebugLevel > 5) {
- System.out.println("<--> RtpPkt(aTimeStamp, syncSource, seqNum, plt, pl)");
- }
- }
- /**
- * Construct a packet-instance from an raw packet (believed to be RTP). The UDP-headers must be removed before invoking this method. Call checkPkt on the instance to verify that it was successfully parsed.
- *
- * @param aRawPkt The data-part of a UDP-packet believed to be RTP
- * @param packetSize the number of valid octets in the packet, should be aRawPkt.length
- */
- protected RtpPkt(byte[] aRawPkt, int packetSize){
- if( RTPSession.rtpDebugLevel > 5) {
- System.out.println("-> RtpPkt(aRawPkt)");
- }
- //Check size, need to have at least a complete header
- if(aRawPkt == null) {
- System.out.println("RtpPkt(byte[]) Packet null");
- }
-
- int remOct = packetSize - 12;
- if(remOct >= 0) {
- rawPkt = aRawPkt; //Store it
- //Interrogate the packet
- sliceFirstLine();
- if(version == 2) {
- sliceTimeStamp();
- sliceSSRC();
- if(remOct > 4 && getCsrcCount() > 0) {
- sliceCSRCs();
- remOct -= csrcArray.length * 4; //4 octets per CSRC
- }
- // TODO Extension
- if(remOct > 0) {
- slicePayload(remOct);
- }
-
- //Sanity checks
- checkPkt();
-
- //Mark the buffer as current
- rawPktCurrent = true;
- } else {
- System.out.println("RtpPkt(byte[]) Packet is not version 2, giving up.");
- }
- } else {
- System.out.println("RtpPkt(byte[]) Packet too small to be sliced");
- }
- rawPktCurrent = true;
- if( RTPSession.rtpDebugLevel > 5) {
- System.out.println("<- RtpPkt(aRawPkt)");
- }
- }
-
- /*********************************************************************************************************
- * Reading stuff
- *********************************************************************************************************/
- protected int checkPkt() {
- //TODO, check for version 2 etc
- return 0;
- }
- protected int getHeaderLength() {
- //TODO include extension
- return 12 + 4*getCsrcCount();
- }
- protected int getPayloadLength() {
- return payload.length;
- }
- //public int getPaddingLength() {
- // return lenPadding;
- //}
- protected int getVersion() {
- return version;
- }
- //public boolean isPadded() {
- // if(lenPadding > 0) {
- // return true;
- // }else {
- // return false;
- // }
- //}
- //public int getHeaderExtension() {
- //TODO
- //}
- protected boolean isMarked() {
- return (marker != 0);
- }
- protected int getPayloadType() {
- return payloadType;
- }
-
- protected int getSeqNumber() {
- return seqNumber;
- }
- protected long getTimeStamp() {
- return timeStamp;
- }
- protected long getSsrc() {
- return ssrc;
- }
-
- protected int getCsrcCount() {
- if(csrcArray != null) {
- return csrcArray.length;
- }else{
- return 0;
- }
- }
- protected long[] getCsrcArray() {
- return csrcArray;
- }
-
- /**
- * Encodes the a
- */
- protected byte[] encode() {
- if(! rawPktCurrent || rawPkt == null) {
- writePkt();
- }
- return rawPkt;
- }
-
- /* For debugging purposes */
- protected void printPkt() {
- System.out.print("V:" + version + " P:" + padding + " EXT:" + extension);
- System.out.println(" CC:" + getCsrcCount() + " M:"+ marker +" PT:" + payloadType + " SN: "+ seqNumber);
- System.out.println("Timestamp:" + timeStamp + "(long output as int, may be 2s complement)");
- System.out.println("SSRC:" + ssrc + "(long output as int, may be 2s complement)");
- for(int i=0;i<getCsrcCount();i++) {
- System.out.println("CSRC:" + csrcArray[i] + "(long output as int, may be 2s complement)");
- }
- //TODO Extension
- System.out.println("Payload, first four bytes: " + payload[0] + " " + payload[1] + " " + payload[2] + " " + payload[3]);
- }
- /*********************************************************************************************************
- * Setting stuff
- *********************************************************************************************************/
- protected void setMarked(boolean mark) {
- rawPktCurrent = false;
- if(mark) {
- marker = 1;
- } else {
- marker = 0;
- }
- }
- //public int setHeaderExtension() {
- //TODO
- //}
- protected int setPayloadType(int plType) {
- int temp = (plType & 0x0000007F); // 7 bits, checks in RTPSession as well.
- if(temp == plType) {
- rawPktCurrent = false;
- payloadType = temp;
- return 0;
- } else {
- return -1;
- }
- }
-
- protected int setSeqNumber(int number) {
- if(number <= 65536 && number >= 0) {
- rawPktCurrent = false;
- seqNumber = number;
- return 0;
- } else {
- System.out.println("RtpPkt.setSeqNumber: invalid number");
- return -1;
- }
- }
-
- protected int setTimeStamp(long time) {
- rawPktCurrent = false;
- timeStamp = time;
- return 0; //Naive for now
- }
-
- protected int setSsrc(long source) {
- rawPktCurrent = false;
- ssrc = source;
- return 0; //Naive for now
- }
-
- protected int setCsrcs(long[] contributors) {
- if(contributors.length <= 16) {
- csrcArray = contributors;
- return 0;
- } else {
- System.out.println("RtpPkt.setCsrcs: Cannot have more than 16 CSRCs");
- return -1;
- }
- }
-
- protected int setPayload(byte[] data) {
- // TODO Padding
- if(data.length < (1500 - 12)) {
- rawPktCurrent = false;
- payload = data;
- return 0;
- } else {
- System.out.println("RtpPkt.setPayload: Cannot carry more than 1480 bytes for now.");
- return -1;
- }
- }
- protected byte[] getPayload() {
- return payload;
- }
-
- /*********************************************************************************************************
- * Private functions
- *********************************************************************************************************/
- //Generate a bytebyffer representing the packet, store it.
- private void writePkt() {
- int bytes = getPayloadLength();
- int headerLen = getHeaderLength();
- int csrcLen = getCsrcCount();
- rawPkt = new byte[headerLen + bytes];
-
- // The first line contains, version and various bits
- writeFirstLine();
- byte[] someBytes = StaticProcs.uIntLongToByteWord(timeStamp);
- for(int i=0;i<4;i++) {
- rawPkt[i + 4] = someBytes[i];
- }
- //System.out.println("writePkt timeStamp:" + rawPkt[7]);
-
- someBytes = StaticProcs.uIntLongToByteWord(ssrc);
- System.arraycopy(someBytes, 0, rawPkt, 8, 4);
- //System.out.println("writePkt ssrc:" + rawPkt[11]);
-
- for(int i=0; i<csrcLen ; i++) {
- someBytes = StaticProcs.uIntLongToByteWord(csrcArray[i]);
- System.arraycopy(someBytes, 0, rawPkt, 12 + 4*i, 4);
- }
- // TODO Extension
-
- //Payload
- System.arraycopy(payload, 0, rawPkt, headerLen, bytes);
- rawPktCurrent = true;
- }
- //Writes the first 4 octets of the RTP packet
- private void writeFirstLine() {
- byte aByte = 0;
- aByte |=(version << 6);
- aByte |=(padding << 5);
- aByte |=(extension << 4);
- aByte |=(getCsrcCount());
- rawPkt[0] = aByte;
- aByte = 0;
- aByte |=(marker << 7);
- aByte |= payloadType;
- rawPkt[1] = aByte;
- byte[] someBytes = StaticProcs.uIntIntToByteWord(seqNumber);
- rawPkt[2] = someBytes[0];
- rawPkt[3] = someBytes[1];
- }
- //Picks apart the first 4 octets of an RTP packet
- private void sliceFirstLine() {
- version = ((rawPkt[0] & 0xC0) >>> 6);
- padding = ((rawPkt[0] & 0x20) >>> 5);
- extension = ((rawPkt[0] & 0x10) >>> 4);
- csrcArray = new long[(rawPkt[0] & 0x0F)];
- marker = ((rawPkt[1] & 0x80) >> 7);
- payloadType = (rawPkt[1] & 0x7F);
- seqNumber = StaticProcs.bytesToUIntInt(rawPkt, 2);
- }
- //Takes the 4 octets representing the timestamp
- private void sliceTimeStamp() {
- timeStamp = StaticProcs.bytesToUIntLong(rawPkt, 4);
- }
- //Takes the 4 octets representing the SSRC
- private void sliceSSRC() {
- ssrc = StaticProcs.bytesToUIntLong(rawPkt,8);
- }
- //Check the length of the csrcArray (set during sliceFirstLine)
- private void sliceCSRCs() {
- for(int i=0; i< csrcArray.length; i++) {
- ssrc = StaticProcs.bytesToUIntLong(rawPkt, i*4 + 12);
- }
- }
- //Extensions //TODO
- private void slicePayload(int bytes) {
- payload = new byte[bytes];
- int headerLen = getHeaderLength();
-
- System.arraycopy(rawPkt, headerLen, payload, 0, bytes);
- }
-}
\ No newline at end of file
--- a/src/jlibrtp/StaticProcs.java Thu May 28 14:26:06 2009 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,270 +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;
-
-/**
- * Generic functions for converting between unsigned integers and byte[]s.
- *
- * @author Arne Kepp
- */
-public class StaticProcs {
-
- /**
- * Converts an integer into an array of bytes.
- * Primarily used for 16 bit unsigned integers, ignore the first two octets.
- *
- * @param i a 16 bit unsigned integer in an int
- * @return byte[2] representing the integer as unsigned, most significant bit first.
- */
- public static byte[] uIntIntToByteWord(int i) {
- byte[] byteWord = new byte[2];
- byteWord[0] = (byte) ((i >> 8) & 0x000000FF);
- byteWord[1] = (byte) (i & 0x00FF);
- return byteWord;
- }
-
- /**
- * Converts an unsigned 32 bit integer, stored in a long, into an array of bytes.
- *
- * @param j a long
- * @return byte[4] representing the unsigned integer, most significant bit first.
- */
- public static byte[] uIntLongToByteWord(long j) {
- int i = (int) j;
- byte[] byteWord = new byte[4];
- byteWord[0] = (byte) ((i >>> 24) & 0x000000FF);
- byteWord[1] = (byte) ((i >> 16) & 0x000000FF);
- byteWord[2] = (byte) ((i >> 8) & 0x000000FF);
- byteWord[3] = (byte) (i & 0x00FF);
- return byteWord;
- }
-
- /**
- * Combines two bytes (most significant bit first) into a 16 bit unsigned integer.
- *
- * @param index of most significant byte
- * @return int with the 16 bit unsigned integer
- */
- public static int bytesToUIntInt(byte[] bytes, int index) {
- int accum = 0;
- int i = 1;
- for (int shiftBy = 0; shiftBy < 16; shiftBy += 8 ) {
- accum |= ( (long)( bytes[index + i] & 0xff ) ) << shiftBy;
- i--;
- }
- return accum;
- }
-
- /**
- * Combines four bytes (most significant bit first) into a 32 bit unsigned integer.
- *
- * @param bytes
- * @param index of most significant byte
- * @return long with the 32 bit unsigned integer
- */
- public static long bytesToUIntLong(byte[] bytes, int index) {
- long accum = 0;
- int i = 3;
- for (int shiftBy = 0; shiftBy < 32; shiftBy += 8 ) {
- accum |= ( (long)( bytes[index + i] & 0xff ) ) << shiftBy;
- i--;
- }
- return accum;
- }
-
- /**
- * Converts an arbitrary number of bytes, assumed to represent an unsigned integer,
- * to a Java long
- */
- /*public static long bytesToUintLong(byte[] bytes, int firstByte, int lastByte) {
- long accum = 0;
- int i = lastByte - firstByte;
- if(i > 7) {
- System.out.println("!!!! StaticProcs.bytesToUintLong() Can't convert more than 63 bits!");
- return -1;
- }
- int stop = (i+1)*8;
-
- for (int shiftBy = 0; shiftBy < stop; shiftBy += 8 ) {
- accum |= ( (long)( bytes[firstByte + i] & 0xff ) ) << shiftBy;
- i--;
- }
- return accum;
- }*/
-
- /**
- * Converts an arbitrary number of bytes, assumed to represent an unsigned integer,
- * to a Java int
- */
- /* public static int bytesToUintInt(byte[] bytes, int firstByte, int lastByte) {
- int accum = 0;
- int i = lastByte - firstByte;
- if(i > 3) {
- System.out.println("!!!! StaticProcs.bytesToUintLong() Can't convert more than 31 bits!");
- return -1;
- }
- int stop = (i+1)*8;
-
- for (int shiftBy = 0; shiftBy < stop; shiftBy += 8 ) {
- accum |= ( (long)( bytes[firstByte + i] & 0xff ) ) << shiftBy;
- i--;
- }
- return accum;
- }*/
-
- /**
- * Recreates a UNIX timestamp based on the NTP representation used
- * in RTCP SR packets
- *
- * @param ntpTs1 from RTCP SR packet
- * @param ntpTs2 from RTCP SR packet
- * @return the UNIX timestamp
- */
- public static long undoNtpMess(long ntpTs1, long ntpTs2) {
- long timeVal = (ntpTs1 - 2208988800L)*1000;
-
- double tmp = (1000.0*(double)ntpTs2)/((double)4294967295L);
- long ms = (long) tmp;
- //System.out.println(" timeVal: " +Long.toString(timeVal)+ " ms " + Long.toString(ms));
- timeVal += ms;
-
- return timeVal;
- }
-
-
-
- /**
- * Get the bits of a byte
- *
- * @param aByte the byte you wish to convert
- * @return a String of 1's and 0's
- */
- public static String bitsOfByte(byte aByte) {
- int temp;
- String out = "";
- for(int i=7; i>=0; i--) {
- temp = (aByte >>> i);
- temp &= 0x0001;
- out += (""+temp);
- }
- return out;
- }
-
- /**
- * Get the hex representation of a byte
- *
- * @param aByte the byte you wish to convert
- * @return a String of two chars 0-1,A-F
- */
- public static String hexOfByte(byte aByte) {
- String out = "";
-
- for(int i=0; i<2; i++) {
- int temp = (int) aByte;
- if(temp < 0) {
- temp +=256;
- }
- if(i == 0) {
- temp = temp/16;
- } else {
- temp = temp%16;
- }
-
- if( temp > 9) {
- switch(temp) {
- case 10: out += "A"; break;
- case 11: out += "B"; break;
- case 12: out += "C"; break;
- case 13: out += "D"; break;
- case 14: out += "E"; break;
- case 15: out += "F"; break;
- }
- } else {
- out += Integer.toString(temp);
- }
- }
- return out;
- }
-
- /**
- * Get the hex representation of a byte
- *
- * @param hex 4 bytes the byte you wish to convert
- * @return a String of two chars 0-1,A-F
- */
- public static byte byteOfHex(byte[] hex) {
- byte retByte = 0;
- Byte tmp;
- int val = 0;
-
- // First 4 bits
- tmp = hex[0];
- val = tmp.intValue();
- if(val > 64) {
- // Letter
- val -= 55;
- } else {
- // Number
- val -= 48;
- }
- retByte = ((byte) (val << 4));
-
- // Last 4 bits
- tmp = hex[1];
- val = tmp.intValue();
- if(val > 64) {
- // Letter
- val -= 55;
- } else {
- // Number
- val -= 48;
- }
- retByte |= ((byte) val);
-
- return retByte;
- }
-
-
- /**
- * Print the bits of a byte to standard out. For debugging.
- *
- * @param aByte the byte you wish to print out.
- */
- public static void printBits(byte aByte) {
- int temp;
- for(int i=7; i>=0; i--) {
- temp = (aByte >>> i);
- temp &= 0x0001;
- System.out.print(""+temp);
- }
- System.out.println();
- }
-
- public static String bitsOfBytes(byte[] bytes) {
- String str = "";
- //Expensive, but who cares
- for(int i=0; i<bytes.length; i++ ) {
- str += bitsOfByte(bytes[i]) + " ";
- if((i + 1) % 4 == 0)
- str += "\n";
- }
-
- return str;
- }
-}
\ No newline at end of file
--- a/src/jlibrtp/ValidateParticipantDatabase.java Thu May 28 14:26:06 2009 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,68 +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.DatagramSocket;
-import java.net.InetAddress;
-
-public class ValidateParticipantDatabase {
-
- /**
- * @param args
- */
- public static void main(String[] args) {
- DatagramSocket rtpSocket = null;
- DatagramSocket rtcpSocket = null;
- try {
- rtpSocket = new DatagramSocket(6002);
- rtcpSocket = new DatagramSocket(6003);
- } catch (Exception e) {
- System.out.println("RTPSession failed to obtain port");
- }
- RTPSession rtpSession = new RTPSession(rtpSocket, rtcpSocket);
-
- ParticipantDatabase partDb = new ParticipantDatabase(rtpSession);
-
- Participant part0 = new Participant("127.0.0.1", 4545, 4555);
- Participant part1 = new Participant("127.0.0.1", 4546, 4556);
- Participant part2 = new Participant("127.0.0.1", 4547, 4556);
-
- partDb.addParticipant(0,part0);
- partDb.addParticipant(0,part1);
- partDb.addParticipant(0,part2);
-
- partDb.debugPrint();
-
- System.out.println("********************* Removing Participant 1 (4546) ***********************");
- partDb.removeParticipant(part1);
- partDb.debugPrint();
-
-
- InetAddress inetAdr = null;
- try { inetAdr = InetAddress.getByName("127.0.0.1"); } catch (Exception e) { };
-
- //Participant part3 = partDb.getParticipant(inetAdr);
- //part3.ssrc = 12345678;
- System.out.println("********************* Updating Participant 3 (4546) ***********************");
- //partDb.updateParticipant(part3);
-
- partDb.debugPrint();
- }
-
-}
--- a/src/jlibrtp/ValidatePktBuffer.java Thu May 28 14:26:06 2009 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,108 +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.DatagramSocket;
-
-
-/**
- * Validates the PktBuffer and associated classes.
- *
- * @author Arne Kepp
- *
- */
-public class ValidatePktBuffer {
-
- /**
- * Instantiates a buffer, creates some packets, adds them and sorts them.
- * @param args
- */
- public static void main(String[] args) {
- // TODO Auto-generated method stub
- DatagramSocket rtpSocket = null;
- DatagramSocket rtcpSocket = null;
- try {
- rtpSocket = new DatagramSocket(6002);
- rtcpSocket = new DatagramSocket(6003);
- } catch (Exception e) {
- System.out.println("RTPSession failed to obtain port");
- }
- RTPSession rtpSession = new RTPSession(rtpSocket, rtcpSocket);
-
-
- String str1 = "ab";
- String str2 = "cd";
- String str3 = "ef";
- String str4 = "gh";
- String str5 = "ij";
- String str6 = "kl";
- //String str7 = "mn";
-
- long syncSource1 = 1;
- int seqNumber1 = 1;
- //int seqNumber2 = 1;
- RtpPkt pkt1 = new RtpPkt(10, syncSource1, 1, 0, str1.getBytes());
- RtpPkt pkt2 = new RtpPkt(20, syncSource1, 2, 0, str2.getBytes());
- RtpPkt pkt3 = new RtpPkt(30, syncSource1, 3, 0, str3.getBytes());
- RtpPkt pkt4 = new RtpPkt(40, syncSource1, 4, 0, str4.getBytes());
- RtpPkt pkt6 = new RtpPkt(60, syncSource1, 6, 0, str5.getBytes());
- RtpPkt pkt7 = new RtpPkt(70, syncSource1, 7, 0, str6.getBytes());
-
- Participant p = new Participant();
-
- PktBuffer pktBuf = new PktBuffer(rtpSession, p, pkt1);
- pktBuf.addPkt(pkt3); //2
- pktBuf.addPkt(pkt2); //3
- DataFrame aFrame = pktBuf.popOldestFrame();
- String outStr = new String(aFrame.getConcatenatedData());
- System.out.println("** 1 Data from first frame: " + outStr + ", should be ab");
- pktBuf.addPkt(pkt4); //3
- pktBuf.addPkt(pkt7); //4
- System.out.println("** 1.5 sixth");
- pktBuf.addPkt(pkt6); //5
- System.out.println("** 2 Duplicate, should be dropped");
- pktBuf.addPkt(pkt3); //5
- // Pop second frame
- aFrame = pktBuf.popOldestFrame(); //4
- outStr = new String(aFrame.getConcatenatedData());
- System.out.println("** 3 Data from second frame: " + outStr + ", should be cd");
-
- // Pop third frame
- aFrame = pktBuf.popOldestFrame(); //3
- outStr = new String(aFrame.getConcatenatedData());
- System.out.println("** 4 Data from third frame: " + outStr + ", should be ef");
- System.out.println("** 5 pktBuf.getLength is " + pktBuf.getLength() + ", should be 3");
-
- System.out.println("** 6 Late arrival, should be dropped");
- pktBuf.addPkt(pkt2);
-
- aFrame = pktBuf.popOldestFrame();
- outStr = new String(aFrame.getConcatenatedData());
- System.out.println("** 7 Data from fourth frame: " + outStr + ", should be gh");
-
- aFrame = pktBuf.popOldestFrame();
- outStr = new String(aFrame.getConcatenatedData());
- System.out.println("** 8 Data from fifth frame: " + outStr + ", should be ij");
-
- aFrame = pktBuf.popOldestFrame();
- outStr = new String(aFrame.getConcatenatedData());
- System.out.println("** 9 Data from fifth frame: " + outStr + ", should be kl");
- }
-
-}
--- a/src/jlibrtp/ValidateRtcpPkt.java Thu May 28 14:26:06 2009 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,140 +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.util.*;
-import java.net.*;
-
-public class ValidateRtcpPkt {
-
- public static void main(String[] args) {
- DatagramSocket rtpSock = null;
- DatagramSocket rtcpSock = null;
-
- try {
- rtpSock = new DatagramSocket(1233);
- rtcpSock = new DatagramSocket(1234);
- } catch (Exception e) {
- //do nothing
- }
- RTPSession rtpSession = new RTPSession(rtpSock, rtcpSock);
-
- System.out.println("************************** SSRC: " + rtpSession.ssrc + " **************************");
- ParticipantDatabase partDb = new ParticipantDatabase(rtpSession);
- //InetAddress test = InetAddress.getByName("127.0.0.1");
- Participant part1 = new Participant("127.0.0.1",12, 34);
- Participant part2 = new Participant("127.0.0.2",56, 78);
-
- part1.ssrc = 123;
- part2.ssrc = 345;
-
- InetSocketAddress testadr = null;
-
- try {
- testadr = InetSocketAddress.createUnresolved("localhost", 12371);
- } catch (Exception e) {
- // Do nothing
- }
-
- part1.cname = "test3";
- part2.cname = "test2";
- part1.loc = "1231231231";
- part2.loc = "Asker";
- part1.phone = "+452 1231231";
- part2.phone = "aasdasda.asdasdas";
- part1.lastSeqNumber = 111;
- part2.lastSeqNumber = 222;
- part1.timeStampLSR = 111111;
- part2.timeStampLSR = 222222;
- partDb.addParticipant(0,part1);
- partDb.addParticipant(0,part2);
-
- Participant[] partArray = new Participant[2];
- partArray[0] = part1;
- partArray[1] = part2;
-
- RtcpPktRR rrpkt = new RtcpPktRR(partArray,123456789);
- RtcpPktSR srpkt = new RtcpPktSR(rtpSession.ssrc,12,21,rrpkt);
- //RtcpPktSR srpkt2 = new RtcpPktSR(rtpSession.ssrc,12,21,null);
- //rrpkt = new RtcpPktRR(partArray,1234512311);
-
- //srpkt.debugPrint();
- //rrpkt.debugPrint();
-
- CompRtcpPkt compkt = new CompRtcpPkt();
- compkt.addPacket(srpkt);
- compkt.addPacket(rrpkt);
- compkt.addPacket(rrpkt);
-
- byte[] test2 = compkt.encode();
- //System.out.print(StaticProcs.bitsOfBytes(test));
- System.out.println("****************************** DONE ENCODING *******************************");
- CompRtcpPkt decomppkt = new CompRtcpPkt(test2,test2.length,testadr,rtpSession);
- System.out.println("****************************** DONE DECODING *******************************");
- System.out.println("Problem code:" + decomppkt.problem);
-
- ListIterator iter = decomppkt.rtcpPkts.listIterator();
- int i = 0;
-
- while(iter.hasNext()) {
- System.out.println(" i:" + i + " ");
- i++;
-
- Object aPkt = iter.next();
- if( aPkt.getClass() == RtcpPktRR.class) {
- RtcpPktRR pkt = (RtcpPktRR) aPkt;
- pkt.debugPrint();
- } else if(aPkt.getClass() == RtcpPktSR.class) {
- RtcpPktSR pkt = (RtcpPktSR) aPkt;
- pkt.debugPrint();
- }
- }
-
- System.out.println("****************************** BYE *******************************");
- long[] tempArray = {rtpSession.ssrc};
- byte[] tempReason = "tas".getBytes();
- RtcpPktBYE byepkt = new RtcpPktBYE(tempArray,tempReason);
- //byepkt.debugPrint();
- byepkt.encode();
- byte[] rawpktbye = byepkt.rawPkt;
-
- RtcpPktBYE byepkt2 = new RtcpPktBYE(rawpktbye,0);
- byepkt2.debugPrint();
-
- System.out.println("****************************** SDES *******************************");
- RtcpPktSDES sdespkt = new RtcpPktSDES(true,rtpSession,null);
- rtpSession.cname = "cname123@localhost";
- //rtpSession.loc = "right here";
- sdespkt.encode();
- //rtpSession.cname = "cname124@localhost";
- //rtpSession.loc = "right hera";
- byte[] rawpktsdes = sdespkt.rawPkt;
- InetSocketAddress tmpAdr = (InetSocketAddress) rtpSock.getLocalSocketAddress();
- RtcpPktSDES decsdespkt = new RtcpPktSDES(rawpktsdes, 0, (InetSocketAddress) rtpSock.getLocalSocketAddress() , partDb);
- decsdespkt.debugPrint();
- //partDb.debugPrint();
-
- CompRtcpPkt compkt2 = new CompRtcpPkt();
- compkt2.addPacket(srpkt);
- compkt2.addPacket(sdespkt);
- byte[] compkt2Raw = compkt.encode();
-
- CompRtcpPkt compkt3 = new CompRtcpPkt(compkt2Raw,compkt2Raw.length,tmpAdr,rtpSession);
- }
-}
--- a/src/jlibrtp/ValidateStaticProcs.java Thu May 28 14:26:06 2009 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,127 +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;
-
-
-/**
- * Validates the StaticProcs.
- *
- * @author Arne Kepp
- *
- */
-public class ValidateStaticProcs {
-
- /**
- * @param args
- */
- public static void main(String[] args) {
- // TODO Auto-generated method stub
- long one = 100;
- long two = 1;
- long three = 9999000;
-
- byte aByte = (byte) 7;
- System.out.println("aByte.hex: " + StaticProcs.hexOfByte(aByte));
-
- //byte[] oneb = StaticProcs.longToByteWord(one);
- byte[] twob = StaticProcs.uIntLongToByteWord(two);
- //byte[] threeb = StaticProcs.longToByteWord(three);
-
- for(int i = 0; i< 4; i++) {
- StaticProcs.printBits(twob[i]);
- }
- //one = StaticProcs.combineBytes(oneb[0], oneb[1], oneb[2], oneb[3]);
- two = StaticProcs.bytesToUIntLong(twob,0);
- //three = StaticProcs.combineBytes(threeb[0], threeb[1], threeb[2], threeb[3]);
-
- System.out.println(" one " + one + " two " + two + " three " + three);
-
- twob = StaticProcs.uIntLongToByteWord(two);
-
- for(int i = 0; i< 4; i++) {
- StaticProcs.printBits(twob[i]);
- }
-
- byte[] bytes = new byte[2];
- int check = 0;
- for(int i=0; i< 65536; i++) {
- bytes = StaticProcs.uIntIntToByteWord(i);
- check = StaticProcs.bytesToUIntInt(bytes, 0);
- if(check != i) {
- System.out.println(" oops:" + check +" != "+ i);
- StaticProcs.printBits(bytes[0]);
- StaticProcs.printBits(bytes[1]);
- }
- }
- int a = 65534;
- bytes = StaticProcs.uIntIntToByteWord(a);
- StaticProcs.printBits(bytes[0]);
- StaticProcs.printBits(bytes[1]);
- check = StaticProcs.bytesToUIntInt(bytes, 0);
- System.out.println(check);
-
- byte[] arbytes = new byte[22];
- arbytes[13] = -127;
- arbytes[14] = 127;
- arbytes[15] = -1;
- arbytes[16] = 127;
- arbytes[17] = -127;
- System.out.println("arbitrary length:");
- StaticProcs.printBits(arbytes[14]);
- StaticProcs.printBits(arbytes[15]);
- StaticProcs.printBits(arbytes[16]);
- //long arbTest = StaticProcs.bytesToUintLong(arbytes, 14, 16);
- //byte[] reArBytes = StaticProcs.uIntLongToByteWord(arbTest);
- //System.out.println("arbitrary length recode: " + Long.toString(arbTest));
- //StaticProcs.printBits(reArBytes[0]);
- //StaticProcs.printBits(reArBytes[1]);
- //StaticProcs.printBits(reArBytes[2]);
- //StaticProcs.printBits(reArBytes[3]);
-
- byte[] tmp = new byte[4];
- tmp[0] = -127;
- tmp[1] = 127;
- tmp[2] = -49;
- tmp[3] = -1;
-
- String str2 = "";
- for(int i=0; i<tmp.length; i++) {
- str2 += StaticProcs.hexOfByte(tmp[i]);
- }
- System.out.println(str2);
-
- byte temp2[] = str2.getBytes();
- byte temp4[] = new byte[temp2.length / 2];
- byte[] temp3 = new byte[2];
-
- for(int i=0; i<temp4.length; i++) {
- temp3[0] = temp2[i*2];
- temp3[1] = temp2[i*2+1];
- temp4[i] = StaticProcs.byteOfHex(temp3);
- }
-
- for(int i=0; i<tmp.length; i++) {
- if(tmp[i] == temp4[i]) {
- System.out.println("ok");
- } else {
- System.out.println("nope");
- }
- }
- }
-}
--- a/src/jlibrtp/package.html Thu May 28 14:26:06 2009 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,22 +0,0 @@
-<html>
-<body>
-<p>The jlibrtp package contains the core classes of jlibrtp. Most of these classes
- are protected or private, developers looking to use jlibrtp should only concern
- themselves with</p>
- <ul>
- <li>RTPSession - the main session object
- <li>Participant - participant objects
- <li>DataFrame - the containers in which data is returned
- <li>RTPAppIntf - the mininum callback interface
- <li>RTPCAppIntf - optional interface for receing RTCP packets
- <li>RTCPAVPFIntf - optional interface for RTP with feedback
- <li>DebugAppIntf - optional interface for debugging
- </ul>
- <p>
- DebugAppIntf is great for checking network problems and keeping track of packets.
- If you need extensive debugging you should statically change the debug values in RTPSession.java
- and pay attention to the standard output.
- </p>
-
-</body>
-</html>
\ No newline at end of file