src/jlibrtp/RTPSession.java
changeset 834 e8d6255306f8
parent 833 f5a5d9237d69
child 835 4e40f3481f23
--- a/src/jlibrtp/RTPSession.java	Sat Jan 23 21:48:58 2010 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1301 +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.DatagramSocket;
-import java.net.InetAddress;
-import java.net.InetSocketAddress;
-import java.net.MulticastSocket;
-import java.util.Enumeration;
-import java.util.Iterator;
-import java.util.Random;
-import java.util.concurrent.locks.Condition;
-import java.util.concurrent.locks.Lock;
-import java.util.concurrent.locks.ReentrantLock;
-
-import org.sipdroid.net.tools.DataFramePool;
-import org.sipdroid.net.tools.DatagramPool;
-import org.sipdroid.net.tools.PktBufNodePool;
-import org.sipdroid.net.tools.RtpPktPool;
-
-import android.util.Log;
-
-/**
- * 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 = 1;
-	/**
-	 * 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 = 1;
-
-	/** 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);
-	/** First participant */
-	protected Participant firstPart;
-	/** 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;
-		}
-	}
-
-	public AppCallerThread getAppCallerThrd() {
-		return appCallerThrd;
-	}
-
-	public RTPReceiverThread getRTPRecvThrd() {
-		return recvThrd;
-	}
-
-	/**
-	 * 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 = RtpPktPool.getInstance().borrowPkt();
-			pkt.initPacket(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;
-	}
-
-	public void sendData(DatagramPacket packet, RtpPkt pkt) {
-		if (RTPSession.rtpDebugLevel > 5) {
-			System.out.println("-> RTPSession.sendData(byte[])");
-		}
-
-		pkt.setTimeStamp(System.currentTimeMillis());
-		pkt.setSsrc(ssrc);
-		pkt.setSeqNumber(getNextSeqNum());
-
-		// Creates a raw packet
-		pkt.writeHeader();
-
-		// Pre-flight check, are resolving an SSRC conflict?
-		if (this.conflict) {
-			System.out
-			.println("RTPSession.sendData() called while trying to resolve conflict.");
-			return;
-		}
-
-		if (this.mcSession) {
-			try {
-				packet.setPort(this.rtpMCSock.getPort());
-				packet.setAddress(this.mcGroup);
-			} catch (Exception e) {
-				System.out
-				.println("RTPSession.sendData() packet creation failed.");
-				e.printStackTrace();
-				return;
-			}
-			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;
-			}
-
-		} else {
-			try {
-				packet.setSocketAddress(firstPart.rtpAddress);
-			} catch (Exception e) {
-				System.out
-				.println("RTPSession.sendData() packet creation failed.");
-				e.printStackTrace();
-				return;
-			}
-
-			// Actually send the packet
-			try {
-				
-				rtpSock.send(packet);
-				//Log.d("RTP", "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;
-			}
-		}
-
-		// Update our stats
-		this.sentPktCount++;
-		this.sentOctetCount++;
-		if (RTPSession.rtpDebugLevel > 5) {
-			System.out.println("<- RTPSession.sendData(byte[]) "
-					+ pkt.getSeqNumber());
-		}
-	}
-
-	/**
-	 * 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
-		firstPart = p;
-		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();
-			}
-		}
-		DatagramPool.removeInstance();
-		PktBufNodePool.removeInstance();
-		DataFramePool.removeInstance();
-		RtpPktPool.removeInstance();
-	}
-
-	/**
-	 * 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();
-		}
-	}
-}