--- a/src/com/beem/project/beem/jingle/JingleService.java Sat Jan 23 21:48:58 2010 +0100
+++ b/src/com/beem/project/beem/jingle/JingleService.java Sat Jan 23 22:19:43 2010 +0100
@@ -57,7 +57,6 @@
import org.jivesoftware.smackx.jingle.media.PayloadType;
import org.jivesoftware.smackx.jingle.nat.BasicTransportManager;
import org.jivesoftware.smackx.jingle.nat.TransportCandidate;
-import org.sipdroid.media.codecs.CodecManager;
import android.content.Context;
import android.net.Uri;
--- a/src/com/beem/project/beem/jingle/RTPAudioSession.java Sat Jan 23 21:48:58 2010 +0100
+++ b/src/com/beem/project/beem/jingle/RTPAudioSession.java Sat Jan 23 22:19:43 2010 +0100
@@ -1,15 +1,11 @@
package com.beem.project.beem.jingle;
-import jlibrtp.Participant;
-import jlibrtp.RTPSession;
-
import org.jivesoftware.smackx.jingle.JingleSession;
import org.jivesoftware.smackx.jingle.media.JingleMediaSession;
import org.jivesoftware.smackx.jingle.media.PayloadType;
import org.jivesoftware.smackx.jingle.nat.TransportCandidate;
import org.sipdroid.media.RtpStreamReceiver;
import org.sipdroid.media.RtpStreamSender;
-import org.sipdroid.media.codecs.CodecManager;
import org.sipdroid.net.SipdroidSocket;
import android.content.Context;
@@ -97,11 +93,7 @@
rtpSocket = new SipdroidSocket(src_port);
rtcpSocket = new SipdroidSocket(src_port + 1);
} catch (Exception e) {
+ e.printStackTrace();
}
- rtpSession = new RTPSession(rtpSocket, rtcpSocket);
- Participant p = new Participant(dest_addr,dest_port, dest_port + 1);
- rtpSession.addParticipant(p);
- rtpSession.naivePktReception(true);
- rtpSession.packetBufferBehavior(3);
}
}
--- a/src/jlibrtp/AppCallerThread.java Sat Jan 23 21:48:58 2010 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,170 +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");
- }
- }
-
- public DataFrame getNextDataFrame() {
- if (RTPSession.rtpDebugLevel > 3) {
- System.out.println("-> AppCallerThread.run()");
- }
- //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 = rtpSession.firstPart;
-
- 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 {
- return aFrame;
- }
- }
- //}
-
- } finally {
- //rtpSession.pktBufLock.unlock();
- }
- if (RTPSession.rtpDebugLevel > 3) {
- System.out.println("<- AppCallerThread.run() terminating");
- }
- return null;
- }
-
-}
--- a/src/jlibrtp/CompRtcpPkt.java Sat Jan 23 21:48:58 2010 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,268 +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;
-import java.util.LinkedList;
-import java.util.ListIterator;
-
-/**
- * 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 void init(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 Sat Jan 23 21:48:58 2010 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,295 +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 org.sipdroid.net.tools.DatagramPool;
-import org.sipdroid.net.tools.PktBufNodePool;
-import org.sipdroid.net.tools.RtpPktPool;
-
-/**
- * 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;
- private RtpPkt[] pkts = new RtpPkt[5];
-
- /**
- * 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) {
- initDataFrame(aBufNode, p, noPkts);
- }
-
- protected void initDataFrame(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;
- PktBufNode tempNode;
-
- // 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();
- //seqNum = new int[aBufNode.pktCount];
- //marks = new boolean[aBufNode.pktCount];
- if (pktCount > 5) {
- System.out.println("PKT COUNT TOO HIGH " + pktCount);
- }
- // Concatenate the data of the packets
- int i;
- for (i = 0; i < pktCount; i++) {
- aPkt = aBufNode.pkt;
- pkts[i] = aPkt;
- // System.out.println("i " + i + " seqNum[i] " + seqNum[i] +
- // " aBufNode" + aBufNode);
- //seqNum[i] = aBufNode.seqNum;
- if (aBufNode.pkt.isMarked())
- anyMarked = true;
-
- // Get next node
- tempNode = aBufNode;
- aBufNode = aBufNode.nextFrameNode;
- PktBufNodePool.getInstance().returnBufNode(tempNode);
- lastSeqNum = aPkt.getSeqNumber();
- }
-
- 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: "
- + pkts.length);
- }
- }
-
- public DataFrame(){
- }
-
- /**
- * 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;
- }*/
-
- public RtpPkt[] getPkt(){
- return this.pkts ;
- }
-
- /**
- * 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;
- }
-
- public void release() {
- for(RtpPkt pkt : this.pkts) {
- if (pkt != null) {
- if (pkt.getDatagramPacket() != null)
- DatagramPool.getInstance().returnPacket(pkt.getDatagramPacket());
- RtpPktPool.getInstance().returnPkt(pkt);
- }
- }
- }
-}
--- a/src/jlibrtp/DebugAppIntf.java Sat Jan 23 21:48:58 2010 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,90 +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 Sat Jan 23 21:48:58 2010 +0100
+++ /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 Sat Jan 23 21:48:58 2010 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,464 +0,0 @@
-/**
- * Java RTP Library (jlibrtp)
- * Copyright (C) 2006 Arne Kepp
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-package jlibrtp;
-
-import java.net.InetSocketAddress;
-
-/**
- * A participant represents a peer in an RTPSession. Based on the information
- * stored on these objects, packets are processed and statistics generated for
- * RTCP.
- */
-public class Participant {
- /**
- * Whether the participant is unexpected, e.g. arrived through unicast with
- * SDES
- */
- protected boolean unexpected = false;
- /** Where to send RTP packets (unicast) */
- protected InetSocketAddress rtpAddress = null;
- /** Where to send RTCP packets (unicast) */
- protected InetSocketAddress rtcpAddress = null;
- /** Where the first RTP packet was received from */
- protected InetSocketAddress rtpReceivedFromAddress = null;
- /** Where the first RTCP packet was received from */
- protected InetSocketAddress rtcpReceivedFromAddress = null;
-
- /** SSRC of participant */
- protected long ssrc = -1;
- /** SDES CNAME */
- protected String cname = null;
- /** SDES The participant's real name */
- protected String name = null;
- /** SDES The participant's email */
- protected String email = null;
- /** SDES The participant's phone number */
- protected String phone = null;
- /** SDES The participant's location */
- protected String loc = null;
- /** SDES The tool the participants is using */
- protected String tool = null;
- /** SDES A note */
- protected String note = null;
- /** SDES A priv string, loosely defined */
- protected String priv = null;
-
- // Receiver Report Items
- /** RR First sequence number */
- protected int firstSeqNumber = -1;
- /** RR Last sequence number */
- protected int lastSeqNumber = 0;
- /** RR Number of times sequence number has rolled over */
- protected long seqRollOverCount = 0;
- /** RR Number of packets received */
- protected long receivedPkts = 0;
- /** RR Number of octets received */
- protected long receivedOctets = 0;
- /** RR Number of packets received since last SR */
- protected int receivedSinceLastSR = 0;
- /** RR Sequence number associated with last SR */
- protected int lastSRRseqNumber = 0;
- /** RR Interarrival jitter */
- protected double interArrivalJitter = -1.0;
- /** RR Last received RTP Timestamp */
- protected long lastRtpTimestamp = 0;
-
- /** RR Middle 32 bits of the NTP timestamp in the last SR */
- protected long timeStampLSR = 0;
- /** RR The time when we actually got the last SR */
- protected long timeReceivedLSR = 0;
-
- /** Gradient where UNIX timestamp = ntpGradient*RTPTimestamp * ntpOffset */
- protected double ntpGradient = -1;
- /** Offset where UNIX timestamp = ntpGradient*RTPTimestamp * ntpOffset */
- protected long ntpOffset = -1;
- /** Last NTP received in SR packet, MSB */
- protected long lastNtpTs1 = 0; // 32 bits
- /** Last NTP received in SR packet, LSB */
- protected long lastNtpTs2 = 0; // 32 bits
- /** RTP Timestamp in last SR packet */
- protected long lastSRRtpTs = 0; // 32 bits
-
- /** UNIX time when a BYE was received from this participant, for pruning */
- protected long timestampBYE = -1; // The user said BYE at this time
-
- /** Store the packets received from this participant */
- protected PktBuffer pktBuffer = null;
-
- /**
- * UNIX time of last RTP packet, to check whether this participant has sent
- * anything recently
- */
- protected long lastRtpPkt = -1; // Time of last RTP packet
- /**
- * UNIX time of last RTCP packet, to check whether this participant has sent
- * anything recently
- */
- protected long lastRtcpPkt = -1; // Time of last RTCP packet
- /**
- * UNIX time this participant was added by application, to check whether we
- * ever heard back
- */
- protected long addedByApp = -1; // Time the participant was added by
- // application
- /** UNIX time of last time we sent an RR to this user */
- protected long lastRtcpRRPkt = -1; // Timestamp of last time we sent this
- // person an RR packet
- /** Unix time of second to last time we sent and RR to this user */
- protected long secondLastRtcpRRPkt = -1; // Timestamp of 2nd to last time we
- // sent this person an RR Packet
-
- /**
- * Create a basic participant. If this is a <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 Sat Jan 23 21:48:58 2010 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,277 +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.util.Iterator;
-import java.util.LinkedList;
-import java.util.concurrent.ConcurrentHashMap;
-
-/**
- * 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 Sat Jan 23 21:48:58 2010 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,71 +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) {
- initPktBufNode(aPkt);
- }
-
- public PktBufNode(){
- }
-
- public void initPktBufNode(RtpPkt aPkt) {
- pkt = aPkt;
- timeStamp = aPkt.getTimeStamp();
- seqNum = aPkt.getSeqNumber();
- pktCount = 1;
- }
-}
--- a/src/jlibrtp/PktBuffer.java Sat Jan 23 21:48:58 2010 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,533 +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 org.sipdroid.net.tools.DataFramePool;
-import org.sipdroid.net.tools.PktBufNodePool;
-
-/**
- * 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 = PktBufNodePool.getInstance().borrowBufNode();
- newNode.initPktBufNode(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 = PktBufNodePool.getInstance().borrowBufNode();
- newNode.initPktBufNode(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);
- DataFrame df = DataFramePool.getInstance().borrowFrame();
- df.initDataFrame(retNode, this.p, rtpSession.appIntf
- .frameSize(oldest.pkt.getPayloadType()));
- return df;
- } 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 = DataFramePool.getInstance().borrowFrame();
- df.initDataFrame(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 Sat Jan 23 21:48:58 2010 +0100
+++ /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 Sat Jan 23 21:48:58 2010 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,102 +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 Sat Jan 23 21:48:58 2010 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,150 +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 Sat Jan 23 21:48:58 2010 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,446 +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;
-
-import org.sipdroid.net.tools.DatagramPool;
-import org.sipdroid.net.tools.GenericPool;
-
-/**
- * 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;
-
- private GenericPool<CompRtcpPkt> rtcpPacketPool;
-
- /**
- * 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;
-
- rtcpPacketPool = new GenericPool<CompRtcpPkt>(10);
-
- 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 = rtcpPacketPool.borrowItem();
- compPkt.init(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
- DatagramPacket packet = DatagramPool.getInstance().borrowPacket();
-
- // 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 Sat Jan 23 21:48:58 2010 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,496 +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.Enumeration;
-import java.util.Iterator;
-
-/**
- * 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 Sat Jan 23 21:48:58 2010 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,565 +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;
-import java.net.MulticastSocket;
-import java.util.Arrays;
-import java.util.Enumeration;
-import java.util.Hashtable;
-import java.util.LinkedList;
-import java.util.ListIterator;
-
-/**
- * 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 Sat Jan 23 21:48:58 2010 +0100
+++ /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 Sat Jan 23 21:48:58 2010 +0100
+++ /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.net.SocketException;
-
-import org.sipdroid.net.tools.DatagramPool;
-import org.sipdroid.net.tools.RtpPktPool;
-
-/**
- * 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;
- DatagramPool datagramPool = null;
-
- RTPReceiverThread(RTPSession session) {
- rtpSession = session;
- datagramPool = DatagramPool.getInstance();
- if (RTPSession.rtpDebugLevel > 1) {
- System.out.println("<-> RTPReceiverThread created");
- }
- }
- public void init() {
- 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());
- }
- }
-
- android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_AUDIO);
-
- DatagramPacket packet = datagramPool.borrowPacket();
- try {
- rtpSession.rtpSock.setSoTimeout(1);
- for (;;)
- rtpSession.rtpSock.receive(packet);
- } catch (SocketException e2) {
-
- } catch (IOException e) {
- }
- datagramPool.returnPacket(packet);
- try {
- rtpSession.rtpSock.setSoTimeout(1000);
- } catch (SocketException e2) {
- }
- }
-
- public void readPacketToBuffer() {
- 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
- //DatagramPacket packet = new DatagramPacket(rawPkt, rawPkt.length);
- DatagramPacket packet = datagramPool.borrowPacket();
- // Wait for it to arrive
- if (!rtpSession.mcSession) {
- // Unicast
- try {
- rtpSession.rtpSock.receive(packet);
- } catch (IOException e) {
- if (!rtpSession.endSession) {
- e.printStackTrace();
- } else {
- return;
- }
- }
- } else {
- // Multicast
- try {
- rtpSession.rtpMCSock.receive(packet);
- } catch (IOException e) {
- if (!rtpSession.endSession) {
- e.printStackTrace();
- } else {
- return;
- }
- }
- }
- // Parse the received RTP (?) packet
- RtpPkt pkt = RtpPktPool.getInstance().borrowPkt();
- pkt.initPacket(packet.getData(), packet.getLength(), packet);
-
- // Check whether it was valid.
- if (pkt == null) {
- System.out.println("Received invalid RTP packet. Ignoring");
- return;
- }
-
- 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) {
- System.out.println("-> RTPReceiverThread.run() payload is "
- + pkt.getPayloadLength());
- }
- }
-
- // Find the participant in the database based on SSRC
- //Participant part = rtpSession.partDb.getParticipant(pktSsrc);
- Participant part = rtpSession.firstPart;
- 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();
- }*/
- }
-
- 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());
- }
- }
-
- android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_AUDIO);
-
- DatagramPacket packet = datagramPool.borrowPacket();
- try {
- rtpSession.rtpSock.setSoTimeout(1);
- for (;;)
- rtpSession.rtpSock.receive(packet);
- } catch (SocketException e2) {
-
- } catch (IOException e) {
- }
- datagramPool.returnPacket(packet);
- try {
- rtpSession.rtpSock.setSoTimeout(0);
- } catch (SocketException e2) {
- }
- 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
- //DatagramPacket packet = new DatagramPacket(rawPkt, rawPkt.length);
- packet = datagramPool.borrowPacket();
- // 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 = RtpPktPool.getInstance().borrowPkt();
- pkt.initPacket(packet.getData(), packet.getLength(), packet);
-
- // 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) {
- System.out.println("-> RTPReceiverThread.run() payload is "
- + pkt.getPayloadLength());
- }
- }
-
- // 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 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();
- }
- }
-}
--- a/src/jlibrtp/RtcpPkt.java Sat Jan 23 21:48:58 2010 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,143 +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!");
- StaticProcs.uIntIntToByteWord((rawPkt.length / 4) - 1, rawPkt, 2);
- }
-
- /**
- * 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 Sat Jan 23 21:48:58 2010 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,101 +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 Sat Jan 23 21:48:58 2010 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,115 +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 Sat Jan 23 21:48:58 2010 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,411 +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 Sat Jan 23 21:48:58 2010 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,235 +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)
- StaticProcs.uIntLongToByteWord(super.ssrc, super.rawPkt, 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;
- StaticProcs.uIntLongToByteWord(reportees[i].ssrc, ret, offset);
-
- // Cumulative number of packets lost
- StaticProcs.uIntLongToByteWord(reportees[i]
- .getLostPktCount(), ret, 4 + offset);
-
- // Write Cumulative number of packets lost and loss fraction to
- // packet:
- System.arraycopy(reportees[i].getFractionLost(), 0, ret, 4 + offset, 1);
-
- // Extended highest sequence received
- StaticProcs.uIntLongToByteWord(reportees[i]
- .getExtHighSeqRecv(), ret, 8 + offset);
-
- // Interarrival jitter
- if (reportees[i].interArrivalJitter >= 0) {
- StaticProcs
- .uIntLongToByteWord((long) reportees[i].interArrivalJitter, ret, 12 + offset);
- } else {
- StaticProcs.uIntLongToByteWord(0, ret, 12 + offset);
- }
-
- // Timestamp last sender report received
- StaticProcs
- .uIntLongToByteWord(reportees[i].timeStampLSR, ret, 16 + offset);
-
- // Delay since last sender report received, in terms of 1/655536 s =
- // 0.02 ms
- if (reportees[i].timeReceivedLSR > 0) {
- StaticProcs.uIntLongToByteWord(reportees[i]
- .delaySinceLastSR(), ret, 20 + offset);
- } else {
- StaticProcs.uIntLongToByteWord(0,ret, 20 + offset);
- }
- }
- 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 Sat Jan 23 21:48:58 2010 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,165 +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 Sat Jan 23 21:48:58 2010 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,308 +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 Sat Jan 23 21:48:58 2010 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,190 +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
- StaticProcs.uIntLongToByteWord(super.ssrc, super.rawPkt, 4);
- StaticProcs.uIntLongToByteWord(ntpTs1, super.rawPkt, 8);
- StaticProcs.uIntLongToByteWord(ntpTs2, super.rawPkt, 12);
- StaticProcs.uIntLongToByteWord(rtpTs, super.rawPkt, 16);
- StaticProcs.uIntLongToByteWord(sendersPktCount, super.rawPkt, 20);
- StaticProcs.uIntLongToByteWord(sendersOctCount, super.rawPkt, 24);
-
- 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 Sat Jan 23 21:48:58 2010 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,465 +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;
-
-/**
- * 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 = new long[0];//
-
- /** Contains the actual data (eventually) */
- private byte[] rawPkt = null;
-
-
-
- /** The actual data, without any RTP stuff */
- //private byte[] payload = null;
- private DatagramPacket datagramPacket;
-
- /**
- * 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 void initPacket(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); //TODO: faire d'une manière propre
- datagramPacket = null;
- 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
- */
- public RtpPkt(byte[] aRawPkt, int packetSize, DatagramPacket packet) {
- initPacket(aRawPkt, packetSize, packet);
- }
-
- public RtpPkt() {
- }
-
- public RtpPkt(long aTimeStamp, long syncSource, int seqNum, int plt,
- byte[] pl) {
- initPacket(aTimeStamp, syncSource, seqNum, plt, pl);
- }
-
- protected void initPacket(byte[] aRawPkt, int packetSize, DatagramPacket packet) {
- 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
- datagramPacket = 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 rawPkt.length - getHeaderLength();
- }
-
- // 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;
- }
-
- public 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();
- android.util.Log.d("RtpPkt", "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)");
- }
-
- }
-
- /*********************************************************************************************************
- * Setting stuff
- *********************************************************************************************************/
- protected void setMarked(boolean mark) {
- rawPktCurrent = false;
- if (mark) {
- marker = 1;
- } else {
- marker = 0;
- }
- }
-
- // public int setHeaderExtension() {
- // TODO
- // }
- public 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;
- }
- }*/
-
- public byte[] getPayload() {
- return rawPkt;
- }
-
- /*********************************************************************************************************
- * 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;
- }
-
- void writeHeader() {
- //int bytes = rawPkt.length - 12;
- //int headerLen = getHeaderLength();
- int csrcLen = getCsrcCount();
-
- // The first line contains, version and various bits
- writeFirstLine();
- StaticProcs.uIntLongToByteWord(timeStamp, rawPkt, 4);
- // System.out.println("writePkt timeStamp:" + rawPkt[7]);
-
- StaticProcs.uIntLongToByteWord(ssrc, rawPkt, 8);
- //System.arraycopy(someBytes, 0, rawPkt, 8, 4);
- // System.out.println("writePkt ssrc:" + rawPkt[11]);
-
- for (int i = 0; i < csrcLen; i++) {
- StaticProcs.uIntLongToByteWord(csrcArray[i], rawPkt, 12 + 4 * 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
- protected 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;
- StaticProcs.uIntIntToByteWord(seqNumber, rawPkt, 2);
- }
-
- // 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);
- }*/
-
- public void setRawPkt(byte[] rawPkt) {
- this.rawPkt = rawPkt;
- }
-
- public DatagramPacket getDatagramPacket() {
- return datagramPacket;
- }
-}
\ No newline at end of file
--- a/src/jlibrtp/StaticProcs.java Sat Jan 23 21:48:58 2010 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,298 +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;
- }
-
- public static void uIntIntToByteWord(int i, byte[] byteWord, int srcPos) {
- byteWord[0 + srcPos] = (byte) ((i >> 8) & 0x000000FF);
- byteWord[1 + srcPos] = (byte) (i & 0x00FF);
- }
-
- /**
- * 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;
- }
-
- public static void uIntLongToByteWord(long j, byte[] byteword, int srcPos) {
- int i = (int) j;
- byteword[0 + srcPos] = (byte) ((i >>> 24) & 0x000000FF);
- byteword[1 + srcPos] = (byte) ((i >> 16) & 0x000000FF);
- byteword[2 + srcPos] = (byte) ((i >> 8) & 0x000000FF);
- byteword[3 + srcPos] = (byte) (i & 0x00FF);
- }
-
- /**
- * 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/package.html Sat Jan 23 21:48:58 2010 +0100
+++ /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
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/org/sipdroid/media/G711.java Sat Jan 23 22:19:43 2010 +0100
@@ -0,0 +1,397 @@
+package src.org.sipdroid.media;
+
+/**
+ * G.711 codec. This class provides methods for u-law, A-law and linear PCM
+ * conversions.
+ */
+public class G711 {
+ /*
+ * Copyright 1992 by Jutta Degener and Carsten Bormann, Technische
+ * Universitaet Berlin. See the accompanying file "COPYRIGHT" for
+ * details. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE.
+ */
+
+ static final short[] a2s = new short[256];
+ static final int[] _a2s = {
+
+ 60032, 60288, 59520, 59776, 61056, 61312, 60544, 60800,
+ 57984, 58240, 57472, 57728, 59008, 59264, 58496, 58752,
+ 62784, 62912, 62528, 62656, 63296, 63424, 63040, 63168,
+ 61760, 61888, 61504, 61632, 62272, 62400, 62016, 62144,
+ 43520, 44544, 41472, 42496, 47616, 48640, 45568, 46592,
+ 35328, 36352, 33280, 34304, 39424, 40448, 37376, 38400,
+ 54528, 55040, 53504, 54016, 56576, 57088, 55552, 56064,
+ 50432, 50944, 49408, 49920, 52480, 52992, 51456, 51968,
+ 65192, 65208, 65160, 65176, 65256, 65272, 65224, 65240,
+ 65064, 65080, 65032, 65048, 65128, 65144, 65096, 65112,
+ 65448, 65464, 65416, 65432, 65512, 65528, 65480, 65496,
+ 65320, 65336, 65288, 65304, 65384, 65400, 65352, 65368,
+ 64160, 64224, 64032, 64096, 64416, 64480, 64288, 64352,
+ 63648, 63712, 63520, 63584, 63904, 63968, 63776, 63840,
+ 64848, 64880, 64784, 64816, 64976, 65008, 64912, 64944,
+ 64592, 64624, 64528, 64560, 64720, 64752, 64656, 64688,
+ 5504, 5248, 6016, 5760, 4480, 4224, 4992, 4736,
+ 7552, 7296, 8064, 7808, 6528, 6272, 7040, 6784,
+ 2752, 2624, 3008, 2880, 2240, 2112, 2496, 2368,
+ 3776, 3648, 4032, 3904, 3264, 3136, 3520, 3392,
+ 22016, 20992, 24064, 23040, 17920, 16896, 19968, 18944,
+ 30208, 29184, 32256, 31232, 26112, 25088, 28160, 27136,
+ 11008, 10496, 12032, 11520, 8960, 8448, 9984, 9472,
+ 15104, 14592, 16128, 15616, 13056, 12544, 14080, 13568,
+ 344, 328, 376, 360, 280, 264, 312, 296,
+ 472, 456, 504, 488, 408, 392, 440, 424,
+ 88, 72, 120, 104, 24, 8, 56, 40,
+ 216, 200, 248, 232, 152, 136, 184, 168,
+ 1376, 1312, 1504, 1440, 1120, 1056, 1248, 1184,
+ 1888, 1824, 2016, 1952, 1632, 1568, 1760, 1696,
+ 688, 656, 752, 720, 560, 528, 624, 592,
+ 944, 912, 1008, 976, 816, 784, 880, 848
+
+ };
+
+ static final byte[] s2a = new byte[65536];
+ static final int[] _s2a = {
+
+ 213,212,215,214,209,208,211,210,221,220,223,222,217,216,219,218,
+ 197,196,199,198,193,192,195,194,205,204,207,206,201,200,203,202,
+ 245,245,244,244,247,247,246,246,241,241,240,240,243,243,242,242,
+ 253,253,252,252,255,255,254,254,249,249,248,248,251,251,250,250,
+ 229,229,229,229,228,228,228,228,231,231,231,231,230,230,230,230,
+ 225,225,225,225,224,224,224,224,227,227,227,227,226,226,226,226,
+ 237,237,237,237,236,236,236,236,239,239,239,239,238,238,238,238,
+ 233,233,233,233,232,232,232,232,235,235,235,235,234,234,234,234,
+ 149,149,149,149,149,149,149,149,148,148,148,148,148,148,148,148,
+ 151,151,151,151,151,151,151,151,150,150,150,150,150,150,150,150,
+ 145,145,145,145,145,145,145,145,144,144,144,144,144,144,144,144,
+ 147,147,147,147,147,147,147,147,146,146,146,146,146,146,146,146,
+ 157,157,157,157,157,157,157,157,156,156,156,156,156,156,156,156,
+ 159,159,159,159,159,159,159,159,158,158,158,158,158,158,158,158,
+ 153,153,153,153,153,153,153,153,152,152,152,152,152,152,152,152,
+ 155,155,155,155,155,155,155,155,154,154,154,154,154,154,154,154,
+ 133,133,133,133,133,133,133,133,133,133,133,133,133,133,133,133,
+ 132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,
+ 135,135,135,135,135,135,135,135,135,135,135,135,135,135,135,135,
+ 134,134,134,134,134,134,134,134,134,134,134,134,134,134,134,134,
+ 129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,
+ 128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+ 131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,
+ 130,130,130,130,130,130,130,130,130,130,130,130,130,130,130,130,
+ 141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,
+ 140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,
+ 143,143,143,143,143,143,143,143,143,143,143,143,143,143,143,143,
+ 142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,
+ 137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,
+ 136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,
+ 139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,
+ 138,138,138,138,138,138,138,138,138,138,138,138,138,138,138,138,
+ 181,181,181,181,181,181,181,181,181,181,181,181,181,181,181,181,
+ 181,181,181,181,181,181,181,181,181,181,181,181,181,181,181,181,
+ 180,180,180,180,180,180,180,180,180,180,180,180,180,180,180,180,
+ 180,180,180,180,180,180,180,180,180,180,180,180,180,180,180,180,
+ 183,183,183,183,183,183,183,183,183,183,183,183,183,183,183,183,
+ 183,183,183,183,183,183,183,183,183,183,183,183,183,183,183,183,
+ 182,182,182,182,182,182,182,182,182,182,182,182,182,182,182,182,
+ 182,182,182,182,182,182,182,182,182,182,182,182,182,182,182,182,
+ 177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,
+ 177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,
+ 176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,
+ 176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,
+ 179,179,179,179,179,179,179,179,179,179,179,179,179,179,179,179,
+ 179,179,179,179,179,179,179,179,179,179,179,179,179,179,179,179,
+ 178,178,178,178,178,178,178,178,178,178,178,178,178,178,178,178,
+ 178,178,178,178,178,178,178,178,178,178,178,178,178,178,178,178,
+ 189,189,189,189,189,189,189,189,189,189,189,189,189,189,189,189,
+ 189,189,189,189,189,189,189,189,189,189,189,189,189,189,189,189,
+ 188,188,188,188,188,188,188,188,188,188,188,188,188,188,188,188,
+ 188,188,188,188,188,188,188,188,188,188,188,188,188,188,188,188,
+ 191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,
+ 191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,
+ 190,190,190,190,190,190,190,190,190,190,190,190,190,190,190,190,
+ 190,190,190,190,190,190,190,190,190,190,190,190,190,190,190,190,
+ 185,185,185,185,185,185,185,185,185,185,185,185,185,185,185,185,
+ 185,185,185,185,185,185,185,185,185,185,185,185,185,185,185,185,
+ 184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,
+ 184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,
+ 187,187,187,187,187,187,187,187,187,187,187,187,187,187,187,187,
+ 187,187,187,187,187,187,187,187,187,187,187,187,187,187,187,187,
+ 186,186,186,186,186,186,186,186,186,186,186,186,186,186,186,186,
+ 186,186,186,186,186,186,186,186,186,186,186,186,186,186,186,186,
+ 165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,
+ 165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,
+ 165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,
+ 165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,
+ 164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,
+ 164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,
+ 164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,
+ 164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,
+ 167,167,167,167,167,167,167,167,167,167,167,167,167,167,167,167,
+ 167,167,167,167,167,167,167,167,167,167,167,167,167,167,167,167,
+ 167,167,167,167,167,167,167,167,167,167,167,167,167,167,167,167,
+ 167,167,167,167,167,167,167,167,167,167,167,167,167,167,167,167,
+ 166,166,166,166,166,166,166,166,166,166,166,166,166,166,166,166,
+ 166,166,166,166,166,166,166,166,166,166,166,166,166,166,166,166,
+ 166,166,166,166,166,166,166,166,166,166,166,166,166,166,166,166,
+ 166,166,166,166,166,166,166,166,166,166,166,166,166,166,166,166,
+ 161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,
+ 161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,
+ 161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,
+ 161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,
+ 160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,
+ 160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,
+ 160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,
+ 160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,
+ 163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+ 163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+ 163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+ 163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+ 162,162,162,162,162,162,162,162,162,162,162,162,162,162,162,162,
+ 162,162,162,162,162,162,162,162,162,162,162,162,162,162,162,162,
+ 162,162,162,162,162,162,162,162,162,162,162,162,162,162,162,162,
+ 162,162,162,162,162,162,162,162,162,162,162,162,162,162,162,162,
+ 173,173,173,173,173,173,173,173,173,173,173,173,173,173,173,173,
+ 173,173,173,173,173,173,173,173,173,173,173,173,173,173,173,173,
+ 173,173,173,173,173,173,173,173,173,173,173,173,173,173,173,173,
+ 173,173,173,173,173,173,173,173,173,173,173,173,173,173,173,173,
+ 172,172,172,172,172,172,172,172,172,172,172,172,172,172,172,172,
+ 172,172,172,172,172,172,172,172,172,172,172,172,172,172,172,172,
+ 172,172,172,172,172,172,172,172,172,172,172,172,172,172,172,172,
+ 172,172,172,172,172,172,172,172,172,172,172,172,172,172,172,172,
+ 175,175,175,175,175,175,175,175,175,175,175,175,175,175,175,175,
+ 175,175,175,175,175,175,175,175,175,175,175,175,175,175,175,175,
+ 175,175,175,175,175,175,175,175,175,175,175,175,175,175,175,175,
+ 175,175,175,175,175,175,175,175,175,175,175,175,175,175,175,175,
+ 174,174,174,174,174,174,174,174,174,174,174,174,174,174,174,174,
+ 174,174,174,174,174,174,174,174,174,174,174,174,174,174,174,174,
+ 174,174,174,174,174,174,174,174,174,174,174,174,174,174,174,174,
+ 174,174,174,174,174,174,174,174,174,174,174,174,174,174,174,174,
+ 169,169,169,169,169,169,169,169,169,169,169,169,169,169,169,169,
+ 169,169,169,169,169,169,169,169,169,169,169,169,169,169,169,169,
+ 169,169,169,169,169,169,169,169,169,169,169,169,169,169,169,169,
+ 169,169,169,169,169,169,169,169,169,169,169,169,169,169,169,169,
+ 168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,
+ 168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,
+ 168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,
+ 168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,
+ 171,171,171,171,171,171,171,171,171,171,171,171,171,171,171,171,
+ 171,171,171,171,171,171,171,171,171,171,171,171,171,171,171,171,
+ 171,171,171,171,171,171,171,171,171,171,171,171,171,171,171,171,
+ 171,171,171,171,171,171,171,171,171,171,171,171,171,171,171,171,
+ 170,170,170,170,170,170,170,170,170,170,170,170,170,170,170,170,
+ 170,170,170,170,170,170,170,170,170,170,170,170,170,170,170,170,
+ 170,170,170,170,170,170,170,170,170,170,170,170,170,170,170,170,
+ 170,170,170,170,170,170,170,170,170,170,170,170,170,170,170,170,
+ 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42,
+ 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42,
+ 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42,
+ 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42,
+ 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43,
+ 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43,
+ 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43,
+ 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43,
+ 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40,
+ 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40,
+ 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40,
+ 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40,
+ 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41,
+ 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41,
+ 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41,
+ 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41,
+ 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46,
+ 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46,
+ 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46,
+ 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46,
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
+ 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44,
+ 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44,
+ 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44,
+ 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44,
+ 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
+ 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
+ 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
+ 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
+ 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
+ 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
+ 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
+ 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
+ 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
+ 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
+ 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
+ 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33,
+ 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33,
+ 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33,
+ 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33,
+ 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38,
+ 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38,
+ 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38,
+ 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38,
+ 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39,
+ 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39,
+ 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39,
+ 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39,
+ 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,
+ 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,
+ 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,
+ 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,
+ 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
+ 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
+ 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
+ 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
+ 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
+ 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
+ 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
+ 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
+ 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56,
+ 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56,
+ 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57,
+ 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57,
+ 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62,
+ 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62,
+ 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63,
+ 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63,
+ 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60,
+ 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60,
+ 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61,
+ 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61,
+ 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50,
+ 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50,
+ 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
+ 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
+ 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
+ 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
+ 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49,
+ 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49,
+ 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54,
+ 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54,
+ 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
+ 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
+ 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52,
+ 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52,
+ 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53,
+ 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53,
+ 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+ 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+ 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+ 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+ 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27,
+ 24, 24, 24, 24, 24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25,
+ 30, 30, 30, 30, 30, 30, 30, 30, 31, 31, 31, 31, 31, 31, 31, 31,
+ 28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29,
+ 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19, 19, 19, 19, 19,
+ 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 17, 17, 17, 17,
+ 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23,
+ 20, 20, 20, 20, 20, 20, 20, 20, 21, 21, 21, 21, 21, 21, 21, 21,
+ 106,106,106,106,107,107,107,107,104,104,104,104,105,105,105,105,
+ 110,110,110,110,111,111,111,111,108,108,108,108,109,109,109,109,
+ 98, 98, 98, 98, 99, 99, 99, 99, 96, 96, 96, 96, 97, 97, 97, 97,
+ 102,102,102,102,103,103,103,103,100,100,100,100,101,101,101,101,
+ 122,122,123,123,120,120,121,121,126,126,127,127,124,124,125,125,
+ 114,114,115,115,112,112,113,113,118,118,119,119,116,116,117,117,
+ 74, 75, 72, 73, 78, 79, 76, 77, 66, 67, 64, 65, 70, 71, 68, 69,
+ 90, 91, 88, 89, 94, 95, 92, 93, 82, 83, 80, 81, 86, 87, 84, 85
+ };
+
+ //change G711 ulaw start
+ static final int _u2a[] = { /* u- to A-law conversions */
+ 1, 1, 2, 2, 3, 3, 4, 4,
+ 5, 5, 6, 6, 7, 7, 8, 8,
+ 9, 10, 11, 12, 13, 14, 15, 16,
+ 17, 18, 19, 20, 21, 22, 23, 24,
+ 25, 27, 29, 31, 33, 34, 35, 36,
+ 37, 38, 39, 40, 41, 42, 43, 44,
+ 46, 48, 49, 50, 51, 52, 53, 54,
+ 55, 56, 57, 58, 59, 60, 61, 62,
+ 64, 65, 66, 67, 68, 69, 70, 71,
+ 72, 73, 74, 75, 76, 77, 78, 79,
+ 81, 82, 83, 84, 85, 86, 87, 88,
+ 89, 90, 91, 92, 93, 94, 95, 96,
+ 97, 98, 99, 100, 101, 102, 103, 104,
+ 105, 106, 107, 108, 109, 110, 111, 112,
+ 113, 114, 115, 116, 117, 118, 119, 120,
+ 121, 122, 123, 124, 125, 126, 127, 128};
+
+ static final int _a2u[] = { /* A- to u-law conversions */
+ 1, 3, 5, 7, 9, 11, 13, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23,
+ 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 32, 33, 33, 34, 34, 35, 35,
+ 36, 37, 38, 39, 40, 41, 42, 43,
+ 44, 45, 46, 47, 48, 48, 49, 49,
+ 50, 51, 52, 53, 54, 55, 56, 57,
+ 58, 59, 60, 61, 62, 63, 64, 64,
+ 65, 66, 67, 68, 69, 70, 71, 72,
+ 73, 74, 75, 76, 77, 78, 79, 80,
+ 80, 81, 82, 83, 84, 85, 86, 87,
+ 88, 89, 90, 91, 92, 93, 94, 95,
+ 96, 97, 98, 99, 100, 101, 102, 103,
+ 104, 105, 106, 107, 108, 109, 110, 111,
+ 112, 113, 114, 115, 116, 117, 118, 119,
+ 120, 121, 122, 123, 124, 125, 126, 127};
+
+ //change end
+
+ public static void init() {
+ }
+
+ static {
+ int i;
+ for (i = 0; i < 256; i++)
+ a2s[i] = (short)_a2s[i];
+ for (i = 0; i < 65536; i++)
+ s2a[i] = (byte)_s2a[i >> 4];
+ }
+
+ public static void alaw2linear(byte alaw[],short lin[],int frames) {
+ int i;
+ for (i = 0; i < frames; i++)
+ lin[i] = a2s[alaw[i+12] & 0xff];
+ }
+
+ public static void linear2alaw(short lin[],int offset,byte alaw[],int frames) {
+ int i;
+ for (i = 0; i < frames; i++)
+ alaw[i+12] = s2a[lin[i+offset] & 0xffff];
+ }
+
+ //change g711 ulaw start
+ protected static int alaw2ulaw(int aval)
+ { aval&=0xff;
+ return ((aval & 0x80)!=0)? (0xFF^_a2u[aval^0xD5]) : (0x7F^_a2u[aval^0x55]);
+ }
+
+ protected static int ulaw2alaw(int uval)
+ { uval&=0xff;
+ return ((uval&0x80)!=0)? (0xD5^(_u2a[0xFF^uval]-1)) : (0x55^(_u2a[0x7F^uval]-1));
+ }
+
+ public static void ulaw2linear(byte ulaw[],short lin[],int frames) {
+ int i;
+ for (i = 0; i < frames; i++)
+ lin[i] = a2s[ulaw2alaw(ulaw[i+12] & 0xff)];
+ }
+ public static void linear2ulaw(short lin[],int offset,byte ulaw[],int frames) {
+ int i;
+ for (i = 0; i < frames; i++)
+ ulaw[i+12] = (byte)alaw2ulaw(s2a[lin[i+offset] & 0xffff]);
+ }
+ //change end
+}
--- a/src/org/sipdroid/media/RtpStreamReceiver.java Sat Jan 23 21:48:58 2010 +0100
+++ b/src/org/sipdroid/media/RtpStreamReceiver.java Sat Jan 23 22:19:43 2010 +0100
@@ -19,18 +19,19 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-package org.sipdroid.media;
+package src.org.sipdroid.media;
+
+import java.io.IOException;
+import java.net.SocketException;
-import jlibrtp.AppCallerThread;
-import jlibrtp.DataFrame;
-import jlibrtp.Participant;
-import jlibrtp.RTPAppIntf;
-import jlibrtp.RTPReceiverThread;
-import jlibrtp.RTPSession;
+import org.sipdroid.sipua.UserAgent;
+import org.sipdroid.sipua.ui.Receiver;
+import org.sipdroid.sipua.ui.Sipdroid;
+import org.sipdroid.pjlib.Codec;
-import org.sipdroid.media.codecs.Codec;
-import org.sipdroid.net.tools.DataFramePool;
-import org.sipdroid.net.tools.DatagramPool;
+import src.org.sipdroid.net.RtpPacket;
+import src.org.sipdroid.net.RtpSocket;
+import src.org.sipdroid.net.SipdroidSocket;
import android.content.ContentResolver;
import android.content.Context;
@@ -39,6 +40,7 @@
import android.media.AudioManager;
import android.media.AudioTrack;
import android.media.ToneGenerator;
+import android.os.PowerManager;
import android.preference.PreferenceManager;
import android.provider.Settings;
@@ -46,11 +48,14 @@
* RtpStreamReceiver is a generic stream receiver. It receives packets from RTP
* and writes them into an OutputStream.
*/
-public class RtpStreamReceiver extends Thread implements RTPAppIntf{
+public class RtpStreamReceiver extends Thread {
/** Whether working in debug mode. */
public static boolean DEBUG = true;
+ /** Payload type */
+ int p_type;
+
/** Size of the read buffer */
public static final int BUFFER_SIZE = 1024;
@@ -58,61 +63,31 @@
public static final int SO_TIMEOUT = 200;
/** The RtpSocket */
- RTPSession rtpSession = null;
- byte[] buffer;
-
- /** The codec */
- private Codec codec;
- private Context mContext;
-
- private int frame_size;
- private int codec_frame_size;
- private int sampling_rate;
+ RtpSocket rtp_socket = null;
/** Whether it is running */
boolean running;
AudioManager am;
ContentResolver cr;
-
- private int codec_divider;
public static int speakermode;
-
- short lin[];
- short lin2[];
- int user, server, lserver, luser, cnt, todo, headroom, len, timeout = 1, seq = 0, cnt2 = 0, m = 1,
- expseq, getseq, vm = 1, gap, oldvol;
- boolean islate;
-
- Codec.Context codecCtx;
-
- AudioTrack track;
-
+
/**
* Constructs a RtpStreamReceiver.
- * @param ctx
- * @param remoteAddr
*
* @param output_stream
* the stream sink
* @param socket
* the local receiver SipdroidSocket
*/
- public RtpStreamReceiver(Codec ci, RTPSession rtpSession, Context ctx) {
- init(ci, rtpSession, ctx);
+ public RtpStreamReceiver(SipdroidSocket socket, int payload_type) {
+ init(socket);
+ p_type = payload_type;
}
- /** Inits the RtpStreamReceiver
- * @param ctx
- * @param remoteAddr
- **/
- private void init(Codec ci, RTPSession rtpSession, Context ctx) {
- this.rtpSession = rtpSession;
- codec = ci;
- codec_frame_size = codec.getInfo().codecFrameSize;
- codec_divider = codec.getInfo().rtpSampleDivider;
- frame_size = 160 * codec_divider;
- sampling_rate = codec.getInfo().samplingRate;
- mContext = ctx;
+ /** Inits the RtpStreamReceiver */
+ private void init(SipdroidSocket socket) {
+ if (socket != null)
+ rtp_socket = new RtpSocket(socket);
}
/** Whether is running */
@@ -124,25 +99,25 @@
public void halt() {
running = false;
}
-
+
public int speaker(int mode) {
int old = speakermode;
-
+
+ if (Receiver.headset > 0 && mode == AudioManager.MODE_NORMAL)
+ return old;
saveVolume();
- speakermode = mode;
+ setMode(speakermode = mode);
restoreVolume();
return old;
}
double smin = 200,s;
-
- private int REAL_BUFFER_SIZE;
public static int nearend;
-
+
void calc(short[] lin,int off,int len) {
int i,j;
double sm = 30000,r;
-
+
for (i = 0; i < len; i += 5) {
j = lin[i+off];
s = 0.03*Math.abs(j) + 0.97*s;
@@ -162,30 +137,58 @@
r = (double)len/100000;
smin = sm*r + smin*(1-r);
}
-
+
+ static void setStreamVolume(final int stream,final int vol,final int flags) {
+ (new Thread() {
+ public void run() {
+ AudioManager am = (AudioManager) Receiver.mContext.getSystemService(Context.AUDIO_SERVICE);
+ am.setStreamVolume(stream, vol, flags);
+ if (stream == AudioManager.STREAM_MUSIC) restored = true;
+ }
+ }).start();
+ }
+
+ static boolean restored;
+
void restoreVolume() {
- am.setStreamVolume(AudioManager.STREAM_MUSIC,
- PreferenceManager.getDefaultSharedPreferences(mContext).getInt("volume"+speakermode,
- am.getStreamMaxVolume(AudioManager.STREAM_MUSIC)*
- (speakermode == AudioManager.MODE_NORMAL?4:3)/4
+ switch (am.getMode()) {
+ case AudioManager.MODE_IN_CALL:
+ setStreamVolume(AudioManager.STREAM_RING,(int)(
+ am.getStreamMaxVolume(AudioManager.STREAM_RING)*
+ org.sipdroid.sipua.ui.Settings.getEarGain()), 0);
+ track.setStereoVolume(AudioTrack.getMaxVolume()*
+ org.sipdroid.sipua.ui.Settings.getEarGain()
+ ,AudioTrack.getMaxVolume()*
+ org.sipdroid.sipua.ui.Settings.getEarGain());
+ break;
+ case AudioManager.MODE_NORMAL:
+ track.setStereoVolume(AudioTrack.getMaxVolume(),AudioTrack.getMaxVolume());
+ break;
+ }
+ setStreamVolume(AudioManager.STREAM_MUSIC,
+ PreferenceManager.getDefaultSharedPreferences(Receiver.mContext).getInt("volume"+speakermode,
+ am.getStreamMaxVolume(AudioManager.STREAM_MUSIC)*
+ (speakermode == AudioManager.MODE_NORMAL?4:3)/4
),0);
}
-
+
void saveVolume() {
- Editor edit = PreferenceManager.getDefaultSharedPreferences(mContext).edit();
- edit.putInt("volume"+speakermode,am.getStreamVolume(AudioManager.STREAM_MUSIC));
- edit.commit();
+ if (restored) {
+ Editor edit = PreferenceManager.getDefaultSharedPreferences(Receiver.mContext).edit();
+ edit.putInt("volume"+speakermode,am.getStreamVolume(AudioManager.STREAM_MUSIC));
+ edit.commit();
+ }
}
-
+
void saveSettings() {
- if (!PreferenceManager.getDefaultSharedPreferences(mContext).getBoolean("oldvalid",false)) {
+ if (!PreferenceManager.getDefaultSharedPreferences(Receiver.mContext).getBoolean("oldvalid",false)) {
int oldvibrate = am.getVibrateSetting(AudioManager.VIBRATE_TYPE_RINGER);
int oldvibrate2 = am.getVibrateSetting(AudioManager.VIBRATE_TYPE_NOTIFICATION);
- if (!PreferenceManager.getDefaultSharedPreferences(mContext).contains("oldvibrate2"))
+ if (!PreferenceManager.getDefaultSharedPreferences(Receiver.mContext).contains("oldvibrate2"))
oldvibrate2 = AudioManager.VIBRATE_SETTING_ON;
int oldpolicy = android.provider.Settings.System.getInt(cr, android.provider.Settings.System.WIFI_SLEEP_POLICY,
Settings.System.WIFI_SLEEP_POLICY_DEFAULT);
- Editor edit = PreferenceManager.getDefaultSharedPreferences(mContext).edit();
+ Editor edit = PreferenceManager.getDefaultSharedPreferences(Receiver.mContext).edit();
edit.putInt("oldvibrate", oldvibrate);
edit.putInt("oldvibrate2", oldvibrate2);
edit.putInt("oldpolicy", oldpolicy);
@@ -194,164 +197,287 @@
edit.commit();
}
}
+
+ public static void setMode(int mode) {
+ Editor edit = PreferenceManager.getDefaultSharedPreferences(Receiver.mContext).edit();
+ edit.putBoolean("setmode", mode != AudioManager.MODE_NORMAL);
+ edit.commit();
+ AudioManager am = (AudioManager) Receiver.mContext.getSystemService(Context.AUDIO_SERVICE);
+ am.setMode(mode);
+ }
+
+ public static void restoreMode() {
+ if (PreferenceManager.getDefaultSharedPreferences(Receiver.mContext).getBoolean("setmode",true)) {
+ if (Receiver.pstn_state == null || Receiver.pstn_state.equals("IDLE"))
+ setMode(AudioManager.MODE_NORMAL);
+ else {
+ Editor edit = PreferenceManager.getDefaultSharedPreferences(Receiver.mContext).edit();
+ edit.putBoolean("setmode", false);
+ edit.commit();
+ }
+ }
+ }
- void restoreSettings() {
- int oldvibrate = PreferenceManager.getDefaultSharedPreferences(mContext).getInt("oldvibrate",0);
- int oldvibrate2 = PreferenceManager.getDefaultSharedPreferences(mContext).getInt("oldvibrate2",0);
- int oldpolicy = PreferenceManager.getDefaultSharedPreferences(mContext).getInt("oldpolicy",0);
- am.setVibrateSetting(AudioManager.VIBRATE_TYPE_RINGER,oldvibrate);
- am.setVibrateSetting(AudioManager.VIBRATE_TYPE_NOTIFICATION,oldvibrate2);
- Settings.System.putInt(cr, Settings.System.WIFI_SLEEP_POLICY, oldpolicy);
- am.setStreamVolume(AudioManager.STREAM_RING, PreferenceManager.getDefaultSharedPreferences(mContext).getInt("oldring",0), 0);
- Editor edit = PreferenceManager.getDefaultSharedPreferences(mContext).edit();
- edit.putBoolean("oldvalid", false);
- edit.commit();
+ public static void restoreSettings() {
+ if (PreferenceManager.getDefaultSharedPreferences(Receiver.mContext).getBoolean("oldvalid",true)) {
+ AudioManager am = (AudioManager) Receiver.mContext.getSystemService(Context.AUDIO_SERVICE);
+ ContentResolver cr = Receiver.mContext.getContentResolver();
+ int oldvibrate = PreferenceManager.getDefaultSharedPreferences(Receiver.mContext).getInt("oldvibrate",0);
+ int oldvibrate2 = PreferenceManager.getDefaultSharedPreferences(Receiver.mContext).getInt("oldvibrate2",0);
+ int oldpolicy = PreferenceManager.getDefaultSharedPreferences(Receiver.mContext).getInt("oldpolicy",0);
+ am.setVibrateSetting(AudioManager.VIBRATE_TYPE_RINGER,oldvibrate);
+ am.setVibrateSetting(AudioManager.VIBRATE_TYPE_NOTIFICATION,oldvibrate2);
+ Settings.System.putInt(cr, Settings.System.WIFI_SLEEP_POLICY, oldpolicy);
+ setStreamVolume(AudioManager.STREAM_RING, PreferenceManager.getDefaultSharedPreferences(Receiver.mContext).getInt("oldring",0), 0);
+ Editor edit = PreferenceManager.getDefaultSharedPreferences(Receiver.mContext).edit();
+ edit.putBoolean("oldvalid", false);
+ edit.commit();
+ PowerManager pm = (PowerManager) Receiver.mContext.getSystemService(Context.POWER_SERVICE);
+ PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK |
+ PowerManager.ACQUIRE_CAUSES_WAKEUP, "Sipdroid.RtpStreamReceiver");
+ wl.acquire(1000);
+ }
+ restoreMode();
}
public static float good, late, lost, loss;
-
+ public static int timeout;
+
+ void empty() {
+ try {
+ rtp_socket.getDatagramSocket().setSoTimeout(1);
+ for (;;)
+ rtp_socket.receive(rtp_packet);
+ } catch (SocketException e2) {
+ if (!Sipdroid.release) e2.printStackTrace();
+ } catch (IOException e) {
+ }
+ try {
+ rtp_socket.getDatagramSocket().setSoTimeout(1000);
+ } catch (SocketException e2) {
+ if (!Sipdroid.release) e2.printStackTrace();
+ }
+ }
+
+ RtpPacket rtp_packet;
+ AudioTrack track;
+
/** Runs it in a new Thread. */
- @Override
public void run() {
- REAL_BUFFER_SIZE = BUFFER_SIZE * codec_divider;
- speakermode = AudioManager.MODE_IN_CALL;
- android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_AUDIO);
- am = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
- cr = mContext.getContentResolver();
- //saveSettings();
+ boolean nodata = PreferenceManager.getDefaultSharedPreferences(Receiver.mContext).getBoolean("nodata",false);
+
+ if (rtp_socket == null) {
+ if (DEBUG)
+ println("ERROR: RTP socket is null");
+ return;
+ }
- Settings.System.putInt(cr, Settings.System.WIFI_SLEEP_POLICY,Settings.System.WIFI_SLEEP_POLICY_NEVER);
- //am.setVibrateSetting(AudioManager.VIBRATE_TYPE_RINGER,AudioManager.VIBRATE_SETTING_OFF);
- //am.setVibrateSetting(AudioManager.VIBRATE_TYPE_NOTIFICATION,AudioManager.VIBRATE_SETTING_OFF);
- //oldvol = am.getStreamVolume(AudioManager.STREAM_MUSIC);
- restoreVolume();
+ byte[] buffer = new byte[BUFFER_SIZE+12];
+ byte[] buffer_gsm = new byte[33+12];
+ int i;
+ rtp_packet = new RtpPacket(buffer, 0);
+
+ if (DEBUG)
+ println("Reading blocks of max " + buffer.length + " bytes");
- track = new AudioTrack(AudioManager.STREAM_MUSIC, sampling_rate, AudioFormat.CHANNEL_CONFIGURATION_MONO, AudioFormat.ENCODING_PCM_16BIT,
- REAL_BUFFER_SIZE*2*2, AudioTrack.MODE_STREAM);
+ running = true;
+ speakermode = Receiver.docked > 0?AudioManager.MODE_NORMAL:AudioManager.MODE_IN_CALL;
+ restored = false;
+
+ android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_AUDIO);
+ am = (AudioManager) Receiver.mContext.getSystemService(Context.AUDIO_SERVICE);
+ cr = Receiver.mContext.getContentResolver();
+ saveSettings();
+ Settings.System.putInt(cr, Settings.System.WIFI_SLEEP_POLICY,Settings.System.WIFI_SLEEP_POLICY_NEVER);
+ am.setVibrateSetting(AudioManager.VIBRATE_TYPE_RINGER,AudioManager.VIBRATE_SETTING_OFF);
+ am.setVibrateSetting(AudioManager.VIBRATE_TYPE_NOTIFICATION,AudioManager.VIBRATE_SETTING_OFF);
+ int oldvol = am.getStreamVolume(AudioManager.STREAM_MUSIC);
+ track = new AudioTrack(AudioManager.STREAM_MUSIC, 8000, AudioFormat.CHANNEL_CONFIGURATION_MONO, AudioFormat.ENCODING_PCM_16BIT,
+ BUFFER_SIZE*2*2, AudioTrack.MODE_STREAM);
+ short lin[] = new short[BUFFER_SIZE];
+ short lin2[] = new short[BUFFER_SIZE];
+ int user, server, lserver, luser, cnt, todo, headroom, len = 0, seq = 0, cnt2 = 0, m = 1,
+ expseq, getseq, vm = 1, gap, gseq;
+ timeout = 1;
+ boolean islate;
+ user = 0;
+ lserver = 0;
+ luser = -8000;
+ cnt = 0;
+ switch (p_type) {
+ case 3:
+ Codec.init();
+ break;
+ case 0:
+ case 8:
+ G711.init();
+ break;
+ }
+ ToneGenerator tg = new ToneGenerator(AudioManager.STREAM_MUSIC,(int)(ToneGenerator.MAX_VOLUME*2*org.sipdroid.sipua.ui.Settings.getEarGain()));
track.play();
- lin = new short[REAL_BUFFER_SIZE];
- lin2 = new short[REAL_BUFFER_SIZE];
- user = 0; //number of samples written
- server = 0; // number of samples played
- lserver = 0; // last number of samples played
- luser = -sampling_rate; // last number of samples written
- cnt = 0;
- codecCtx = codec.initDecoder();
- System.gc();
- println("DEBUG: rtpStreamReceiver session launch");
- running = true;
- AppCallerThread appCall = rtpSession.getAppCallerThrd();
- RTPReceiverThread recv = rtpSession.getRTPRecvThrd();
- DataFrame frame = null;
- recv.init();
+ if (Receiver.headset > 0 && Receiver.oRingtone != null) {
+ ToneGenerator tg2 = new ToneGenerator(AudioManager.STREAM_RING,(int)(ToneGenerator.MAX_VOLUME*2*org.sipdroid.sipua.ui.Settings.getEarGain()));
+ tg2.startTone(ToneGenerator.TONE_SUP_RINGTONE);
+ System.gc();
+ tg2.stopTone();
+ } else
+ System.gc();
while (running) {
- recv.readPacketToBuffer();
- frame = appCall.getNextDataFrame();
- if (frame == null)
- continue;
- buffer = (frame.getPkt()[0]).getPayload();
- if (timeout != 0) { //on ecrit du blanc sur l'audiotrack
- user += track.write(lin,0,REAL_BUFFER_SIZE);
- user += track.write(lin,0,REAL_BUFFER_SIZE);
+ if (Receiver.call_state == UserAgent.UA_STATE_HOLD) {
+ tg.stopTone();
+ track.pause();
+ while (running && Receiver.call_state == UserAgent.UA_STATE_HOLD) {
+ try {
+ sleep(1000);
+ } catch (InterruptedException e1) {
+ }
+ }
+ track.play();
+ System.gc();
+ timeout = 1;
+ seq = 0;
}
- timeout = 0;
- if (running) {
-
- //println("seq " + seq + " frame seq " + (frame.getPkt()[0]).getSeqNumber());
- if (seq == (frame.getPkt()[0]).getSeqNumber()) {
- m++;
- continue;
+ try {
+ rtp_socket.receive(rtp_packet);
+ if (timeout != 0) {
+ tg.stopTone();
+ track.pause();
+ user += track.write(lin2,0,BUFFER_SIZE);
+ user += track.write(lin2,0,BUFFER_SIZE);
+ track.play();
+ cnt += 2*BUFFER_SIZE;
+ empty();
+ }
+ timeout = 0;
+ } catch (IOException e) {
+ if (timeout == 0 && nodata) {
+ tg.startTone(ToneGenerator.TONE_SUP_RINGTONE);
+ }
+ rtp_socket.getDatagramSocket().disconnect();
+ if (++timeout > 22) {
+ Receiver.engine(Receiver.mContext).rejectcall();
+ break;
}
+ }
+ if (running && timeout == 0) {
+ gseq = rtp_packet.getSequenceNumber();
+ if (seq == gseq) {
+ m++;
+ continue;
+ }
+
+ server = track.getPlaybackHeadPosition();
+ headroom = user-server;
+
+ if (headroom > 1500)
+ cnt += len;
+ else
+ cnt = 0;
+
+ if (lserver == server)
+ cnt2++;
+ else
+ cnt2 = 0;
- codec.decode(codecCtx, buffer, 12, codec_frame_size, lin, 0);
- len = frame_size;
-
- if (speakermode == AudioManager.MODE_NORMAL)
- calc(lin,0,len);
-
- server = track.getPlaybackHeadPosition(); // on récupère la position actuel de la tete de lecture
- headroom = user-server; // on recalcule la différence entre la position de la tete de lecture et ce qu'on a écrit sur la piste
- //println("headroom " + headroom + " user " + user + " server " + server);
- if (headroom < 250 * codec_divider) { // si le headroom est trop petit, il faut rattraper le retard en écrivant du blanc/répétant ce qu'il y a à ecrire
- todo = 625 * codec_divider - headroom;
- //println("insert "+todo);
- android.util.Log.d("RECV", "insert");
+ if (cnt <= 500 || cnt2 >= 2 || headroom - 875 < len) {
+ switch (rtp_packet.getPayloadType()) {
+ case 0:
+ len = rtp_packet.getPayloadLength();
+ G711.ulaw2linear(buffer, lin, len);
+ break;
+ case 8:
+ len = rtp_packet.getPayloadLength();
+ G711.alaw2linear(buffer, lin, len);
+ break;
+ case 3:
+ for (i = 12; i < 45; i++)
+ buffer_gsm[i] = buffer[i];
+ len = Codec.decode(buffer_gsm, lin, 0);
+ break;
+ }
+
+ if (speakermode == AudioManager.MODE_NORMAL)
+ calc(lin,0,len);
+ }
+
+ if (headroom < 250) {
+ todo = 875 - headroom;
+ println("insert "+todo);
islate = true;
- if (todo < len)
- user += track.write(lin,0,todo); // on écrit le packet reçu tel quel
- else
- user += track.write(lin2,0,todo); // ecriture de blanc de taille 625 - headroom, avant l'écriture du packet
- } else
+ user += track.write(lin2,0,todo);
+ } else
islate = false;
- if (headroom > 1000 * codec_divider) // si le headroom est trop grand, on calcule l'écart.
- cnt += len; // on additione le nombre de sample ou il y a eu un headroom supérieur a 1000
- else
- cnt = 0;
-
- if (lserver == server) // on compte le nombre de boucle que l'on a fait sans qu'aucun sample n'ai été joué.
- cnt2++;
- else
- cnt2 = 0;
-
- if (cnt > 1000 * codec_divider && cnt2 < 2) { // si la position de la tete de lecture n'a pas bougé durant 2 tours et que le nombre de sample ou le headroom a été supérieur à 1000 est > 1000
- todo = headroom - 625 * codec_divider;
- try {
- //android.util.Log.d("RECV", "cut");
- sleep(20);
- } catch (InterruptedException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- }
- user += track.write(lin,0,len);
- m = 1;
- seq = (frame.getPkt()[0]).getSeqNumber();
- DataFramePool.getInstance().returnFrame(frame);
- //println("headroom " + headroom + " user " + user + " server " + server + " luser " + luser + " lserver " + lserver);
- if (user >= luser + sampling_rate) {
- /*if (am.getMode() != speakermode) {
- am.setMode(speakermode);
- switch (speakermode) {
- case AudioManager.MODE_IN_CALL:
- am.setStreamVolume(AudioManager.STREAM_RING,(int)(
- am.getStreamMaxVolume(AudioManager.STREAM_RING)*
- com.mbdsys.sfrdroid.ui.Settings.getEarGain()), 0);
- track.setStereoVolume(AudioTrack.getMaxVolume()*
- com.mbdsys.sfrdroid.ui.Settings.getEarGain()
- ,AudioTrack.getMaxVolume()*
- com.mbdsys.sfrdroid.ui.Settings.getEarGain());
- //running = false;
- case AudioManager.MODE_NORMAL:
- track.setStereoVolume(AudioTrack.getMaxVolume(),AudioTrack.getMaxVolume());
- //running = false;
- }
- }*/
- luser = user;
- }
- lserver = server;
- System.arraycopy(lin, 0, lin2, 0, REAL_BUFFER_SIZE);
+ if (cnt > 500 && cnt2 < 2) {
+ todo = headroom - 875;
+ println("cut "+todo);
+ if (todo < len)
+ user += track.write(lin,todo,len-todo);
+ } else
+ user += track.write(lin,0,len);
+
+ if (seq != 0) {
+ getseq = gseq&0xff;
+ expseq = ++seq&0xff;
+ if (m == RtpStreamSender.m) vm = m;
+ gap = (getseq - expseq) & 0xff;
+ if (gap > 0) {
+ if (gap > 100) gap = 1;
+ loss += gap;
+ lost += gap;
+ good += gap - 1;
+ } else {
+ if (m < vm)
+ loss++;
+ if (islate)
+ late++;
+ }
+ good++;
+ if (good > 100) {
+ good *= 0.99;
+ lost *= 0.99;
+ loss *= 0.99;
+ late *= 0.99;
+ }
+ }
+ m = 1;
+ seq = gseq;
+
+ if (user >= luser + 8000 && Receiver.call_state == UserAgent.UA_STATE_INCALL) {
+ if (luser == -8000 || am.getMode() != speakermode) {
+ saveVolume();
+ setMode(speakermode);
+ restoreVolume();
+ }
+ luser = user;
+ }
+ lserver = server;
}
}
track.stop();
- ToneGenerator tg = new ToneGenerator(AudioManager.STREAM_RING,ToneGenerator.MAX_VOLUME/4*3);
+ saveVolume();
+ setStreamVolume(AudioManager.STREAM_MUSIC,oldvol,0);
+ restoreSettings();
+ setStreamVolume(AudioManager.STREAM_MUSIC,oldvol,0);
+ tg.stopTone();
+ tg = new ToneGenerator(AudioManager.STREAM_RING,ToneGenerator.MAX_VOLUME/4*3);
tg.startTone(ToneGenerator.TONE_PROP_PROMPT);
try {
- Thread.sleep(500);
+ sleep(500);
} catch (InterruptedException e) {
}
tg.stopTone();
- rtpSession = null;
- track = null;
- codec.cleanDecoder(codecCtx);
- codec = null;
- println("rtp receiver terminated");
+
+ rtp_socket.close();
+ rtp_socket = null;
+
+ if (DEBUG)
+ println("rtp receiver terminated");
}
/** Debug output */
- static int i = 0;
private static void println(String str) {
- System.out.println("RtpStreamReceiver "+ i++ +": " + str);
+ if (!Sipdroid.release) System.out.println("RtpStreamReceiver: " + str);
}
public static int byte2int(byte b) { // return (b>=0)? b : -((b^0xFF)+1);
@@ -362,23 +488,4 @@
public static int byte2int(byte b1, byte b2) {
return (((b1 + 0x100) % 0x100) << 8) + (b2 + 0x100) % 0x100;
}
-
- @Override
- public int frameSize(int payloadType) {
- // TODO Auto-generated method stub
- return 0;
- }
-
- @Override
- public void receiveData(DataFrame frame, Participant participant) {
- // TODO Auto-generated method stub
-
- }
-
- @Override
- public void userEvent(int type, Participant[] participant) {
- // TODO Auto-generated method stub
-
- }
-
}
--- a/src/org/sipdroid/media/RtpStreamSender.java Sat Jan 23 21:48:58 2010 +0100
+++ b/src/org/sipdroid/media/RtpStreamSender.java Sat Jan 23 22:19:43 2010 +0100
@@ -19,42 +19,50 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-package org.sipdroid.media;
+package src.org.sipdroid.media;
+import java.io.IOException;
import java.io.InputStream;
-import java.net.DatagramPacket;
+import java.net.InetAddress;
import java.util.Random;
-import jlibrtp.RTPSession;
-import jlibrtp.RtpPkt;
+import org.sipdroid.sipua.UserAgent;
+import org.sipdroid.sipua.ui.Receiver;
+import org.sipdroid.sipua.ui.Settings;
+import org.sipdroid.sipua.ui.Sipdroid;
+import org.sipdroid.pjlib.Codec;
-import org.sipdroid.media.codecs.Codec;
+import src.org.sipdroid.net.RtpPacket;
+import src.org.sipdroid.net.RtpSocket;
+import src.org.sipdroid.net.SipdroidSocket;
+import android.content.Context;
import android.media.AudioFormat;
import android.media.AudioManager;
import android.media.AudioRecord;
import android.media.MediaRecorder;
+import android.preference.PreferenceManager;
+import android.telephony.TelephonyManager;
/**
* RtpStreamSender is a generic stream sender. It takes an InputStream and sends
* it through RTP.
*/
-public class RtpStreamSender extends Thread{
-
- private static final boolean DEBUG = true;
+public class RtpStreamSender extends Thread {
+ /** Whether working in debug mode. */
+ public static boolean DEBUG = true;
/** The RtpSocket */
- private RTPSession rtpSession = null;
+ RtpSocket rtp_socket = null;
- /** Codec */
- private Codec codec;
+ /** Payload type */
+ int p_type;
- private int sampling_rate;
+ /** Number of frame per second */
+ long frame_rate;
/** Number of bytes per frame */
- private int frame_size;
-
- private int codec_frame_size;
+ int frame_size;
/**
* Whether it works synchronously with a local clock, or it it acts as slave
@@ -62,33 +70,64 @@
*/
boolean do_sync = true;
+ /**
+ * Synchronization correction value, in milliseconds. It accellarates the
+ * sending rate respect to the nominal value, in order to compensate program
+ * latencies.
+ */
int sync_adj = 0;
/** Whether it is running */
boolean running = false;
boolean muted = false;
- private int codec_divider;
-
/**
* Constructs a RtpStreamSender.
*
+ * @param input_stream
+ * the stream to be sent
+ * @param do_sync
+ * whether time synchronization must be performed by the
+ * RtpStreamSender, or it is performed by the InputStream (e.g.
+ * the system audio input)
+ * @param payload_type
+ * the payload type
+ * @param frame_rate
+ * the frame rate, i.e. the number of frames that should be sent
+ * per second; it is used to calculate the nominal packet time
+ * and,in case of do_sync==true, the next departure time
+ * @param frame_size
+ * the size of the payload
+ * @param src_socket
+ * the socket used to send the RTP packet
+ * @param dest_addr
+ * the destination address
+ * @param dest_port
+ * the destination port
*/
- public RtpStreamSender(Codec co, RTPSession rtpSession) {
- init(co, rtpSession);
+ public RtpStreamSender(boolean do_sync,
+ int payload_type, long frame_rate, int frame_size,
+ SipdroidSocket src_socket, String dest_addr, int dest_port) {
+ init(do_sync, payload_type, frame_rate, frame_size,
+ src_socket, dest_addr, dest_port);
}
/** Inits the RtpStreamSender */
- private void init(Codec co, RTPSession rtpSession) {
- this.rtpSession = rtpSession;
- codec = co;
- sampling_rate = codec.getInfo().samplingRate;
- codec_frame_size = codec.getInfo().codecFrameSize;
- codec_divider = codec.getInfo().rtpSampleDivider;
- frame_size = 160 * codec_divider;
- rtpSession.payloadType(codec.getInfo().rtpPayloadCode);
-
- this.do_sync = true;
+ private void init(boolean do_sync,
+ int payload_type, long frame_rate, int frame_size,
+ SipdroidSocket src_socket, String dest_addr,
+ int dest_port) {
+ this.p_type = payload_type;
+ this.frame_rate = frame_rate;
+ this.frame_size = PreferenceManager.getDefaultSharedPreferences(Receiver.mContext).getString("server","").equals("pbxes.org")?
+ (payload_type == 3?960:1024):frame_size; //15
+ this.do_sync = do_sync;
+ try {
+ rtp_socket = new RtpSocket(src_socket, InetAddress
+ .getByName(dest_addr), dest_port);
+ } catch (Exception e) {
+ if (!Sipdroid.release) e.printStackTrace();
+ }
}
/** Sets the synchronization adjustment time (in milliseconds). */
@@ -100,13 +139,13 @@
public boolean isRunning() {
return running;
}
-
+
public boolean mute() {
return muted = !muted;
}
public static int delay = 0;
-
+
/** Stops running */
public void halt() {
running = false;
@@ -115,11 +154,11 @@
Random random;
double smin = 200,s;
int nearend;
-
+
void calc(short[] lin,int off,int len) {
int i,j;
double sm = 30000,r;
-
+
for (i = 0; i < len; i += 5) {
j = lin[i+off];
s = 0.03*Math.abs(j) + 0.97*s;
@@ -140,6 +179,43 @@
smin = sm*r + smin*(1-r);
}
+ void calc1(short[] lin,int off,int len) {
+ int i,j;
+
+ for (i = 0; i < len; i++) {
+ j = lin[i+off];
+ lin[i+off] = (short)(j>>1);
+ }
+ }
+
+ void calc5(short[] lin,int off,int len) {
+ int i,j;
+
+ for (i = 0; i < len; i++) {
+ j = lin[i+off];
+ if (j > 16350)
+ lin[i+off] = 16350<<1;
+ else if (j < -16350)
+ lin[i+off] = -16350<<1;
+ else
+ lin[i+off] = (short)(j<<1);
+ }
+ }
+
+ void calc10(short[] lin,int off,int len) {
+ int i,j;
+
+ for (i = 0; i < len; i++) {
+ j = lin[i+off];
+ if (j > 8150)
+ lin[i+off] = 8150<<2;
+ else if (j < -8150)
+ lin[i+off] = -8150<<2;
+ else
+ lin[i+off] = (short)(j<<2);
+ }
+ }
+
void noise(short[] lin,int off,int len,double power) {
int i,r = (int)(power*2);
short ran;
@@ -153,21 +229,23 @@
lin[i+off+3] = ran;
}
}
-
+
public static int m;
-
+
/** Runs it in a new Thread. */
public void run() {
- if (rtpSession == null)
+ if (rtp_socket == null)
return;
- byte[] buffer = new byte[codec_frame_size + 12];
- DatagramPacket packet = new DatagramPacket(buffer, codec_frame_size + 12);
- RtpPkt pkt = new RtpPkt();
- pkt.setRawPkt(buffer);
- pkt.setPayloadType(codec.getInfo().rtpPayloadCode);
+ byte[] buffer = new byte[frame_size + 12];
+ RtpPacket rtp_packet = new RtpPacket(buffer, 0);
+ rtp_packet.setPayloadType(p_type);
int seqn = 0;
long time = 0;
double p = 0;
+ TelephonyManager tm = (TelephonyManager) Receiver.mContext.getSystemService(Context.TELEPHONY_SERVICE);
+ boolean improve = PreferenceManager.getDefaultSharedPreferences(Receiver.mContext).getBoolean("improve",false);
+ boolean useGSM = !PreferenceManager.getDefaultSharedPreferences(Receiver.mContext).getString("compression","edge").equals("never");
+ int micgain = (int)(Settings.getMicGain()*10);
running = true;
m = 1;
@@ -175,45 +253,127 @@
println("Reading blocks of " + buffer.length + " bytes");
android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_URGENT_AUDIO);
-
- Codec.Context codecCtx = codec.initEncoder();
-
- AudioRecord record = new AudioRecord(MediaRecorder.AudioSource.MIC, sampling_rate, AudioFormat.CHANNEL_CONFIGURATION_MONO, AudioFormat.ENCODING_PCM_16BIT,
- AudioRecord.getMinBufferSize(sampling_rate,
+ AudioRecord record = new AudioRecord(MediaRecorder.AudioSource.MIC, 8000, AudioFormat.CHANNEL_CONFIGURATION_MONO, AudioFormat.ENCODING_PCM_16BIT,
+ AudioRecord.getMinBufferSize(8000,
AudioFormat.CHANNEL_CONFIGURATION_MONO,
- AudioFormat.ENCODING_PCM_16BIT)*2);
- record.startRecording();
+ AudioFormat.ENCODING_PCM_16BIT)*3/2);
short[] lin = new short[frame_size*11];
int num,ring = 0;
random = new Random();
+ InputStream alerting = null;
+ try {
+ alerting = Receiver.mContext.getAssets().open("alerting");
+ } catch (IOException e2) {
+ if (!Sipdroid.release) e2.printStackTrace();
+ }
+ switch (p_type) {
+ case 3:
+ Codec.init();
+ break;
+ case 0:
+ case 8:
+ G711.init();
+ break;
+ }
+ record.startRecording();
while (running) {
- num = record.read(lin,(ring+delay)%(frame_size*11),frame_size);
- if (RtpStreamReceiver.speakermode == AudioManager.MODE_NORMAL) {
- calc(lin,(ring+delay)%(frame_size*11),num);
- if (RtpStreamReceiver.nearend != 0)
- noise(lin,(ring+delay)%(frame_size*11),num,p);
- else if (nearend == 0)
- p = 0.9*p + 0.1*s;
- }
- codec.encode(codecCtx, lin, ring%(frame_size*11), frame_size, buffer, 12);
- ring += frame_size;
- rtpSession.sendData(packet, pkt);
- if (m == 2) {
- rtpSession.sendData(packet, pkt);
- println("retransmit");
- }
- seqn++;
- time += num;
+ if (muted || Receiver.call_state == UserAgent.UA_STATE_HOLD) {
+ record.stop();
+ while (running && (muted || Receiver.call_state == UserAgent.UA_STATE_HOLD)) {
+ try {
+ sleep(1000);
+ } catch (InterruptedException e1) {
+ }
+ }
+ record.startRecording();
+ }
+ num = record.read(lin,(ring+delay)%(frame_size*11),frame_size);
+
+ if (RtpStreamReceiver.speakermode == AudioManager.MODE_NORMAL) {
+ calc(lin,(ring+delay)%(frame_size*11),num);
+ if (RtpStreamReceiver.nearend != 0)
+ noise(lin,(ring+delay)%(frame_size*11),num,p);
+ else if (nearend == 0)
+ p = 0.9*p + 0.1*s;
+ } else switch (micgain) {
+ case 1:
+ calc1(lin,(ring+delay)%(frame_size*11),num);
+ break;
+ case 5:
+ calc5(lin,(ring+delay)%(frame_size*11),num);
+ break;
+ case 10:
+ calc10(lin,(ring+delay)%(frame_size*11),num);
+ break;
+ }
+ if (Receiver.call_state != UserAgent.UA_STATE_INCALL && alerting != null) {
+ try {
+ if (alerting.available() < num)
+ alerting.reset();
+ alerting.read(buffer,12,num);
+ } catch (IOException e) {
+ if (!Sipdroid.release) e.printStackTrace();
+ }
+ switch (p_type) {// have to add ulaw case?
+ case 3:
+ G711.alaw2linear(buffer, lin, num);
+ num = Codec.encode(lin, 0, buffer, num);
+ break;
+ case 0:
+ G711.alaw2linear(buffer, lin, num);
+ G711.linear2ulaw(lin, 0, buffer, num);
+ break;
+ }
+ } else {
+ switch (p_type) {
+ case 3:
+ num = Codec.encode(lin, ring%(frame_size*11), buffer, num);
+ break;
+ case 0:
+ G711.linear2ulaw(lin, ring%(frame_size*11), buffer, num);
+ break;
+ case 8:
+ G711.linear2alaw(lin, ring%(frame_size*11), buffer, num);
+ break;
+ }
+ }
+ ring += frame_size;
+ rtp_packet.setSequenceNumber(seqn++);
+ rtp_packet.setTimestamp(time);
+ rtp_packet.setPayloadLength(num);
+ try {
+ rtp_socket.send(rtp_packet);
+ if (m == 2)
+ rtp_socket.send(rtp_packet);
+ } catch (IOException e) {
+ }
+ time += frame_size;
+ if (improve && RtpStreamReceiver.good != 0 &&
+ RtpStreamReceiver.loss/RtpStreamReceiver.good > 0.01 &&
+ (Receiver.on_wlan || tm.getNetworkType() != TelephonyManager.NETWORK_TYPE_EDGE))
+ m = 2;
+ else
+ m = 1;
+ if (useGSM && p_type == 8 && !Receiver.on_wlan && tm.getNetworkType() == TelephonyManager.NETWORK_TYPE_EDGE) {
+ rtp_packet.setPayloadType(p_type = 3);
+ if (frame_size == 1024) {
+ frame_size = 960;
+ ring = 0;
+ }
+ }
}
record.stop();
- rtpSession = null;
- codec.cleanEncoder(codecCtx);
+
+ rtp_socket.close();
+ rtp_socket = null;
+
if (DEBUG)
println("rtp sender terminated");
}
/** Debug output */
private static void println(String str) {
- android.util.Log.d("DEBUG","RtpStreamSender: " + str);
+ if (!Sipdroid.release) System.out.println("RtpStreamSender: " + str);
}
-}
+
+}
\ No newline at end of file
--- a/src/org/sipdroid/media/codecs/Codec.java Sat Jan 23 21:48:58 2010 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,19 +0,0 @@
-package org.sipdroid.media.codecs;
-
-public abstract class Codec {
-
- public abstract class Context {
- };
-
- public abstract Context initEncoder();
- public abstract Context initDecoder();
- public abstract void cleanEncoder(Context ctx);
- public abstract void cleanDecoder(Context ctx);
-
-
- public abstract int encode(Context ctx, short[] insample, int inoffset, int size, byte[] outdata, int outoffset);
- public abstract int decode(Context ctx, byte[] indata, int inoffset, int size, short[] outsample, int outoffset);
-
- public abstract CodecInfo getInfo();
-
-}
--- a/src/org/sipdroid/media/codecs/CodecInfo.java Sat Jan 23 21:48:58 2010 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,43 +0,0 @@
-package org.sipdroid.media.codecs;
-
-/**
- * @author vadim
- *
- */
-public class CodecInfo {
- /**
- * String to show in config dialog
- */
- public String displayName;
- /**
- * codec spec string to use in SDP
- */
- public String rtpPayloadName;
- /**
- * prefered RTP payload code
- */
- public int rtpPayloadCode;
- /**
- * sampling rate for this codec
- */
- public int samplingRate;
- /**
- * divider for sampling rate to use when computing rtp timestamp
- */
- public int rtpSampleDivider;
- /**
- * minimum frameSize in milliseconds
- */
- public int minFrameTimeMsecs;
- /**
- * codec description to display in configuration dialog
- */
- public String description;
-
- /**
- * codec frame size
- */
- public int codecFrameSize;
-
-
-}
--- a/src/org/sipdroid/media/codecs/CodecManager.java Sat Jan 23 21:48:58 2010 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,46 +0,0 @@
-/**
- *
- */
-package org.sipdroid.media.codecs;
-
-import java.util.LinkedList;
-
-/**
- * @author vadim
- *
- */
-public class CodecManager {
-
- public static void load() {
- GSM.load();
- G711.load();
- G722.load();
- }
-
- public static LinkedList<Codec> audioCodecs = new LinkedList<Codec>();
-
- public static Codec getCodecByDisplayName(String cn) {
-
- for (Codec c : audioCodecs) {
- if (c.getInfo().displayName.equals(cn))
- return c;
- }
-
- return null;
- }
-
- public static Codec getCodecByRtpName(String cn) {
-
- for (Codec c : audioCodecs) {
- if (c.getInfo().rtpPayloadName.equals(cn))
- return c;
- }
-
- return null;
- }
-
-
- public static void registerAudioCodec(Codec c) {
- audioCodecs.addLast(c);
- }
-}
--- a/src/org/sipdroid/media/codecs/G711.java Sat Jan 23 21:48:58 2010 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,393 +0,0 @@
-package org.sipdroid.media.codecs;
-
-/**
- * G.711 codec. This class provides methods for u-law, A-law and linear PCM
- * conversions.
- */
-public class G711 extends Codec {
- /*
- * Copyright 1992 by Jutta Degener and Carsten Bormann, Technische
- * Universitaet Berlin. See the accompanying file "COPYRIGHT" for
- * details. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE.
- */
- public static final CodecInfo mCodecInfo = new CodecInfo();
-
- static {
- mCodecInfo.displayName = "aLaw";
- mCodecInfo.rtpPayloadName = "PCMA";
- mCodecInfo.description = "G711 aLaw codec";
- mCodecInfo.rtpPayloadCode = 8;
- mCodecInfo.samplingRate = 8000;
- mCodecInfo.rtpSampleDivider = 1;
- mCodecInfo.minFrameTimeMsecs = 20;
- mCodecInfo.codecFrameSize = 160;
- CodecManager.registerAudioCodec(new G711());
- }
-
- private static final int[] _a2s = {
-
- 60032, 60288, 59520, 59776, 61056, 61312, 60544, 60800,
- 57984, 58240, 57472, 57728, 59008, 59264, 58496, 58752,
- 62784, 62912, 62528, 62656, 63296, 63424, 63040, 63168,
- 61760, 61888, 61504, 61632, 62272, 62400, 62016, 62144,
- 43520, 44544, 41472, 42496, 47616, 48640, 45568, 46592,
- 35328, 36352, 33280, 34304, 39424, 40448, 37376, 38400,
- 54528, 55040, 53504, 54016, 56576, 57088, 55552, 56064,
- 50432, 50944, 49408, 49920, 52480, 52992, 51456, 51968,
- 65192, 65208, 65160, 65176, 65256, 65272, 65224, 65240,
- 65064, 65080, 65032, 65048, 65128, 65144, 65096, 65112,
- 65448, 65464, 65416, 65432, 65512, 65528, 65480, 65496,
- 65320, 65336, 65288, 65304, 65384, 65400, 65352, 65368,
- 64160, 64224, 64032, 64096, 64416, 64480, 64288, 64352,
- 63648, 63712, 63520, 63584, 63904, 63968, 63776, 63840,
- 64848, 64880, 64784, 64816, 64976, 65008, 64912, 64944,
- 64592, 64624, 64528, 64560, 64720, 64752, 64656, 64688,
- 5504, 5248, 6016, 5760, 4480, 4224, 4992, 4736,
- 7552, 7296, 8064, 7808, 6528, 6272, 7040, 6784,
- 2752, 2624, 3008, 2880, 2240, 2112, 2496, 2368,
- 3776, 3648, 4032, 3904, 3264, 3136, 3520, 3392,
- 22016, 20992, 24064, 23040, 17920, 16896, 19968, 18944,
- 30208, 29184, 32256, 31232, 26112, 25088, 28160, 27136,
- 11008, 10496, 12032, 11520, 8960, 8448, 9984, 9472,
- 15104, 14592, 16128, 15616, 13056, 12544, 14080, 13568,
- 344, 328, 376, 360, 280, 264, 312, 296,
- 472, 456, 504, 488, 408, 392, 440, 424,
- 88, 72, 120, 104, 24, 8, 56, 40,
- 216, 200, 248, 232, 152, 136, 184, 168,
- 1376, 1312, 1504, 1440, 1120, 1056, 1248, 1184,
- 1888, 1824, 2016, 1952, 1632, 1568, 1760, 1696,
- 688, 656, 752, 720, 560, 528, 624, 592,
- 944, 912, 1008, 976, 816, 784, 880, 848
-
- };
-
- private static final int[] _s2a = {
-
- 213,212,215,214,209,208,211,210,221,220,223,222,217,216,219,218,
- 197,196,199,198,193,192,195,194,205,204,207,206,201,200,203,202,
- 245,245,244,244,247,247,246,246,241,241,240,240,243,243,242,242,
- 253,253,252,252,255,255,254,254,249,249,248,248,251,251,250,250,
- 229,229,229,229,228,228,228,228,231,231,231,231,230,230,230,230,
- 225,225,225,225,224,224,224,224,227,227,227,227,226,226,226,226,
- 237,237,237,237,236,236,236,236,239,239,239,239,238,238,238,238,
- 233,233,233,233,232,232,232,232,235,235,235,235,234,234,234,234,
- 149,149,149,149,149,149,149,149,148,148,148,148,148,148,148,148,
- 151,151,151,151,151,151,151,151,150,150,150,150,150,150,150,150,
- 145,145,145,145,145,145,145,145,144,144,144,144,144,144,144,144,
- 147,147,147,147,147,147,147,147,146,146,146,146,146,146,146,146,
- 157,157,157,157,157,157,157,157,156,156,156,156,156,156,156,156,
- 159,159,159,159,159,159,159,159,158,158,158,158,158,158,158,158,
- 153,153,153,153,153,153,153,153,152,152,152,152,152,152,152,152,
- 155,155,155,155,155,155,155,155,154,154,154,154,154,154,154,154,
- 133,133,133,133,133,133,133,133,133,133,133,133,133,133,133,133,
- 132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,
- 135,135,135,135,135,135,135,135,135,135,135,135,135,135,135,135,
- 134,134,134,134,134,134,134,134,134,134,134,134,134,134,134,134,
- 129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,
- 128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
- 131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,
- 130,130,130,130,130,130,130,130,130,130,130,130,130,130,130,130,
- 141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,
- 140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,
- 143,143,143,143,143,143,143,143,143,143,143,143,143,143,143,143,
- 142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,
- 137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,
- 136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,
- 139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,
- 138,138,138,138,138,138,138,138,138,138,138,138,138,138,138,138,
- 181,181,181,181,181,181,181,181,181,181,181,181,181,181,181,181,
- 181,181,181,181,181,181,181,181,181,181,181,181,181,181,181,181,
- 180,180,180,180,180,180,180,180,180,180,180,180,180,180,180,180,
- 180,180,180,180,180,180,180,180,180,180,180,180,180,180,180,180,
- 183,183,183,183,183,183,183,183,183,183,183,183,183,183,183,183,
- 183,183,183,183,183,183,183,183,183,183,183,183,183,183,183,183,
- 182,182,182,182,182,182,182,182,182,182,182,182,182,182,182,182,
- 182,182,182,182,182,182,182,182,182,182,182,182,182,182,182,182,
- 177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,
- 177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,
- 176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,
- 176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,
- 179,179,179,179,179,179,179,179,179,179,179,179,179,179,179,179,
- 179,179,179,179,179,179,179,179,179,179,179,179,179,179,179,179,
- 178,178,178,178,178,178,178,178,178,178,178,178,178,178,178,178,
- 178,178,178,178,178,178,178,178,178,178,178,178,178,178,178,178,
- 189,189,189,189,189,189,189,189,189,189,189,189,189,189,189,189,
- 189,189,189,189,189,189,189,189,189,189,189,189,189,189,189,189,
- 188,188,188,188,188,188,188,188,188,188,188,188,188,188,188,188,
- 188,188,188,188,188,188,188,188,188,188,188,188,188,188,188,188,
- 191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,
- 191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,
- 190,190,190,190,190,190,190,190,190,190,190,190,190,190,190,190,
- 190,190,190,190,190,190,190,190,190,190,190,190,190,190,190,190,
- 185,185,185,185,185,185,185,185,185,185,185,185,185,185,185,185,
- 185,185,185,185,185,185,185,185,185,185,185,185,185,185,185,185,
- 184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,
- 184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,
- 187,187,187,187,187,187,187,187,187,187,187,187,187,187,187,187,
- 187,187,187,187,187,187,187,187,187,187,187,187,187,187,187,187,
- 186,186,186,186,186,186,186,186,186,186,186,186,186,186,186,186,
- 186,186,186,186,186,186,186,186,186,186,186,186,186,186,186,186,
- 165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,
- 165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,
- 165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,
- 165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,
- 164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,
- 164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,
- 164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,
- 164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,
- 167,167,167,167,167,167,167,167,167,167,167,167,167,167,167,167,
- 167,167,167,167,167,167,167,167,167,167,167,167,167,167,167,167,
- 167,167,167,167,167,167,167,167,167,167,167,167,167,167,167,167,
- 167,167,167,167,167,167,167,167,167,167,167,167,167,167,167,167,
- 166,166,166,166,166,166,166,166,166,166,166,166,166,166,166,166,
- 166,166,166,166,166,166,166,166,166,166,166,166,166,166,166,166,
- 166,166,166,166,166,166,166,166,166,166,166,166,166,166,166,166,
- 166,166,166,166,166,166,166,166,166,166,166,166,166,166,166,166,
- 161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,
- 161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,
- 161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,
- 161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,
- 160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,
- 160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,
- 160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,
- 160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,
- 163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
- 163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
- 163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
- 163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
- 162,162,162,162,162,162,162,162,162,162,162,162,162,162,162,162,
- 162,162,162,162,162,162,162,162,162,162,162,162,162,162,162,162,
- 162,162,162,162,162,162,162,162,162,162,162,162,162,162,162,162,
- 162,162,162,162,162,162,162,162,162,162,162,162,162,162,162,162,
- 173,173,173,173,173,173,173,173,173,173,173,173,173,173,173,173,
- 173,173,173,173,173,173,173,173,173,173,173,173,173,173,173,173,
- 173,173,173,173,173,173,173,173,173,173,173,173,173,173,173,173,
- 173,173,173,173,173,173,173,173,173,173,173,173,173,173,173,173,
- 172,172,172,172,172,172,172,172,172,172,172,172,172,172,172,172,
- 172,172,172,172,172,172,172,172,172,172,172,172,172,172,172,172,
- 172,172,172,172,172,172,172,172,172,172,172,172,172,172,172,172,
- 172,172,172,172,172,172,172,172,172,172,172,172,172,172,172,172,
- 175,175,175,175,175,175,175,175,175,175,175,175,175,175,175,175,
- 175,175,175,175,175,175,175,175,175,175,175,175,175,175,175,175,
- 175,175,175,175,175,175,175,175,175,175,175,175,175,175,175,175,
- 175,175,175,175,175,175,175,175,175,175,175,175,175,175,175,175,
- 174,174,174,174,174,174,174,174,174,174,174,174,174,174,174,174,
- 174,174,174,174,174,174,174,174,174,174,174,174,174,174,174,174,
- 174,174,174,174,174,174,174,174,174,174,174,174,174,174,174,174,
- 174,174,174,174,174,174,174,174,174,174,174,174,174,174,174,174,
- 169,169,169,169,169,169,169,169,169,169,169,169,169,169,169,169,
- 169,169,169,169,169,169,169,169,169,169,169,169,169,169,169,169,
- 169,169,169,169,169,169,169,169,169,169,169,169,169,169,169,169,
- 169,169,169,169,169,169,169,169,169,169,169,169,169,169,169,169,
- 168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,
- 168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,
- 168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,
- 168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,
- 171,171,171,171,171,171,171,171,171,171,171,171,171,171,171,171,
- 171,171,171,171,171,171,171,171,171,171,171,171,171,171,171,171,
- 171,171,171,171,171,171,171,171,171,171,171,171,171,171,171,171,
- 171,171,171,171,171,171,171,171,171,171,171,171,171,171,171,171,
- 170,170,170,170,170,170,170,170,170,170,170,170,170,170,170,170,
- 170,170,170,170,170,170,170,170,170,170,170,170,170,170,170,170,
- 170,170,170,170,170,170,170,170,170,170,170,170,170,170,170,170,
- 170,170,170,170,170,170,170,170,170,170,170,170,170,170,170,170,
- 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42,
- 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42,
- 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42,
- 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42,
- 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43,
- 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43,
- 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43,
- 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43,
- 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40,
- 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40,
- 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40,
- 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40,
- 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41,
- 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41,
- 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41,
- 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41,
- 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46,
- 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46,
- 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46,
- 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46,
- 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
- 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
- 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
- 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
- 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44,
- 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44,
- 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44,
- 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
- 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
- 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
- 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
- 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
- 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
- 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
- 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
- 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33,
- 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33,
- 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33,
- 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33,
- 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38,
- 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38,
- 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38,
- 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38,
- 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39,
- 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39,
- 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39,
- 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39,
- 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,
- 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,
- 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,
- 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,
- 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
- 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
- 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
- 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
- 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
- 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56,
- 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56,
- 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57,
- 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57,
- 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62,
- 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62,
- 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63,
- 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63,
- 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60,
- 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60,
- 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61,
- 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61,
- 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50,
- 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50,
- 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
- 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
- 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
- 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
- 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49,
- 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49,
- 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54,
- 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54,
- 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
- 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
- 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52,
- 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52,
- 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53,
- 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53,
- 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
- 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
- 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
- 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
- 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
- 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
- 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
- 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27,
- 24, 24, 24, 24, 24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25,
- 30, 30, 30, 30, 30, 30, 30, 30, 31, 31, 31, 31, 31, 31, 31, 31,
- 28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29,
- 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19, 19, 19, 19, 19,
- 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 17, 17, 17, 17,
- 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23,
- 20, 20, 20, 20, 20, 20, 20, 20, 21, 21, 21, 21, 21, 21, 21, 21,
- 106,106,106,106,107,107,107,107,104,104,104,104,105,105,105,105,
- 110,110,110,110,111,111,111,111,108,108,108,108,109,109,109,109,
- 98, 98, 98, 98, 99, 99, 99, 99, 96, 96, 96, 96, 97, 97, 97, 97,
- 102,102,102,102,103,103,103,103,100,100,100,100,101,101,101,101,
- 122,122,123,123,120,120,121,121,126,126,127,127,124,124,125,125,
- 114,114,115,115,112,112,113,113,118,118,119,119,116,116,117,117,
- 74, 75, 72, 73, 78, 79, 76, 77, 66, 67, 64, 65, 70, 71, 68, 69,
- 90, 91, 88, 89, 94, 95, 92, 93, 82, 83, 80, 81, 86, 87, 84, 85
- };
-
-
- public class G711Context extends Context {
- public final short[] a2s = new short[256];
- public final byte[] s2a = new byte[65536];
- }
-
- public void init(G711Context ctx) {
- int i;
- for (i = 0; i < 256; i++)
- ctx.a2s[i] = (short)_a2s[i];
- for (i = 0; i < 65536; i++)
- ctx.s2a[i] = (byte)_s2a[i >> 4];
- }
-
- private void alaw2linear(G711Context ctx, byte alaw[], int inoffset, int size, short lin[], int outoffset) {
- int i;
- for (i = 0; i < size; i++)
- lin[i + outoffset] = ctx.a2s[alaw[i + inoffset] & 0xff];
- }
-
- private void linear2alaw(G711Context ctx, short lin[], int inoffset, byte alaw[], int outoffset, int size) {
- int i;
- for (i = 0; i < size; i++)
- alaw[i + outoffset] = ctx.s2a[lin[i + inoffset] & 0xffff];
- }
-
- @Override
- public Context initDecoder() {
- G711Context ctx = new G711Context();
- init(ctx);
- return ctx;
- }
-
- @Override
- public Context initEncoder() {
- G711Context ctx = new G711Context();
- init(ctx);
- return ctx;
- }
-
- @Override
- public void cleanDecoder(Context ctx) {
- }
-
- @Override
- public void cleanEncoder(Context ctx) {
- }
-
- @Override
- public int decode(Context ctx, byte[] indata, int inoffset, int size,
- short[] outsample, int outoffset) {
- alaw2linear((G711Context) ctx, indata, inoffset, size, outsample, outoffset);
- return size;
- }
-
- @Override
- public int encode(Context ctx, short[] insample, int inoffset, int size,
- byte[] outdata, int outoffset) {
- linear2alaw((G711Context) ctx, insample, inoffset, outdata, outoffset, size);
- return 0;
- }
-
- @Override
- public CodecInfo getInfo() {
- return mCodecInfo;
- }
-
- static public void load(){
- }
-}
--- a/src/org/sipdroid/media/codecs/G722.java Sat Jan 23 21:48:58 2010 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,68 +0,0 @@
-package org.sipdroid.media.codecs;
-
-public class G722 extends Codec {
-
- public static final CodecInfo mCodecInfo = new CodecInfo();
-
- static {
- System.loadLibrary("g722");
- mCodecInfo.displayName = "G722";
- mCodecInfo.rtpPayloadName = "G722";
- mCodecInfo.description = "G722 16kHz codec";
- mCodecInfo.rtpPayloadCode = 9;
- mCodecInfo.samplingRate = 16000;
- mCodecInfo.rtpSampleDivider = 2;
- mCodecInfo.minFrameTimeMsecs = 20;
- mCodecInfo.codecFrameSize = 160;
- CodecManager.registerAudioCodec(new G722());
- }
-
- public class G722Context extends Context {
- public long ctx;
- }
-
- @Override
- public Context initDecoder() {
- G722Context decoderCtx = new G722Context();
- decoderCtx.ctx = G722JNI.decodeInit(decoderCtx.ctx, mCodecInfo.codecFrameSize, 0);
- return decoderCtx;
- }
-
- @Override
- public Context initEncoder() {
- G722Context encoderCtx = new G722Context();
- encoderCtx.ctx = G722JNI.encodeInit(encoderCtx.ctx, mCodecInfo.codecFrameSize, 0);
- return encoderCtx;
- }
-
- @Override
- public void cleanDecoder(Context ctx) {
- G722JNI.decodeRelease(((G722Context)ctx).ctx);
- }
-
- @Override
- public void cleanEncoder(Context ctx) {
- G722JNI.encodeRelease(((G722Context)ctx).ctx);
- }
-
- @Override
- public int decode(Context ctx, byte[] indata, int inoffset, int size,
- short[] outsample, int outoffset) {
- return G722JNI.decode(((G722Context)ctx).ctx, indata, inoffset, outsample, outoffset, size);
- }
-
- @Override
- public int encode(Context ctx, short[] insample, int inoffset, int size,
- byte[] outdata, int outoffset) {
- G722JNI.encode(((G722Context)ctx).ctx, insample, inoffset, outdata, outoffset, size);
- return size;
- }
-
- @Override
- public CodecInfo getInfo() {
- return mCodecInfo;
- }
-
- static public void load(){
- }
-}
--- a/src/org/sipdroid/media/codecs/G722JNI.java Sat Jan 23 21:48:58 2010 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,10 +0,0 @@
-package org.sipdroid.media.codecs;
-
-public class G722JNI {
- public static native long encodeInit(long g722State, int rate, int options);
- public static native int encodeRelease(long g722State);
- public static native int encode(long g722State, short[] signal, long srcPos, byte[] g722Byte, long destPos, int len);
- public static native long decodeInit(long g722State, int rate, int options);
- public static native int decodeRelease(long g722State);
- public static native int decode(long g722State, byte[] g722Byte, long srcPos, short[] signal, long destPos, int len);
-}
--- a/src/org/sipdroid/media/codecs/GSM.java Sat Jan 23 21:48:58 2010 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,68 +0,0 @@
-package org.sipdroid.media.codecs;
-
-public class GSM extends Codec {
-
- public static final CodecInfo mCodecInfo = new CodecInfo();
-
- static {
- System.loadLibrary("gsm");
- mCodecInfo.displayName = "GSM";
- mCodecInfo.rtpPayloadName = "GSM";
- mCodecInfo.description = "GSM Full Rate codec";
- mCodecInfo.rtpPayloadCode = 3;
- mCodecInfo.samplingRate = 8000;
- mCodecInfo.rtpSampleDivider = 1;
- mCodecInfo.minFrameTimeMsecs = 20;
- mCodecInfo.codecFrameSize = 33;
- CodecManager.registerAudioCodec(new GSM());
- }
-
- public class GSMContext extends Context {
- public long ctx;
- }
-
- @Override
- public Context initDecoder() {
- GSMContext decoderCtx = new GSMContext();
- decoderCtx.ctx = GSMJNI.create();
- return decoderCtx;
- }
-
- @Override
- public Context initEncoder() {
- GSMContext encoderCtx = new GSMContext();
- encoderCtx.ctx = GSMJNI.create();
- return encoderCtx;
- }
-
- @Override
- public void cleanDecoder(Context ctx) {
- GSMJNI.destroy(((GSMContext)ctx).ctx);
- }
-
- @Override
- public void cleanEncoder(Context ctx) {
- GSMJNI.destroy(((GSMContext)ctx).ctx);
- }
-
- @Override
- public int decode(Context ctx, byte[] indata, int inoffset, int size,
- short[] outsample, int outoffset) {
- return GSMJNI.decode(((GSMContext)ctx).ctx, indata, inoffset, outsample, outoffset);
- }
-
- @Override
- public int encode(Context ctx, short[] insample, int inoffset, int size,
- byte[] outdata, int outoffset) {
- GSMJNI.encode(((GSMContext)ctx).ctx, insample, inoffset, outdata, outoffset);
- return size;
- }
-
- @Override
- public CodecInfo getInfo() {
- return mCodecInfo;
- }
-
- static public void load(){
- }
-}
--- a/src/org/sipdroid/media/codecs/GSMJNI.java Sat Jan 23 21:48:58 2010 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,8 +0,0 @@
-package org.sipdroid.media.codecs;
-
-public class GSMJNI {
- public static native long create();
- public static native void destroy(long gsm);
- public static native int decode(long gsm, byte[] gsmByte, long srcPos, short[] signal, long destPos);
- public static native void encode(long gsm, short[] signal, long srcPos, byte[] gsmByte, long destPos);
-}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/org/sipdroid/net/RtpPacket.java Sat Jan 23 22:19:43 2010 +0100
@@ -0,0 +1,318 @@
+/*
+ * Copyright (C) 2009 The Sipdroid Open Source Project
+ * Copyright (C) 2005 Luca Veltri - University of Parma - Italy
+ *
+ * This file is part of Sipdroid (http://www.sipdroid.org)
+ *
+ * Sipdroid is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This source code 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this source code; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+package src.org.sipdroid.net;
+
+import org.zoolu.tools.Random;
+
+/**
+ * RtpPacket implements a RTP packet.
+ */
+public class RtpPacket {
+ /* RTP packet buffer containing both the RTP header and payload */
+ byte[] packet;
+
+ /* RTP packet length */
+ int packet_len;
+
+ /* RTP header length */
+ // int header_len;
+ /** Gets the RTP packet */
+ public byte[] getPacket() {
+ return packet;
+ }
+
+ /** Gets the RTP packet length */
+ public int getLength() {
+ return packet_len;
+ }
+
+ /** Gets the RTP header length */
+ public int getHeaderLength() {
+ if (packet_len >= 12)
+ return 12 + 4 * getCscrCount();
+ else
+ return packet_len; // broken packet
+ }
+
+ /** Gets the RTP header length */
+ public int getPayloadLength() {
+ if (packet_len >= 12)
+ return packet_len - getHeaderLength();
+ else
+ return 0; // broken packet
+ }
+
+ /** Sets the RTP payload length */
+ public void setPayloadLength(int len) {
+ packet_len = getHeaderLength() + len;
+ }
+
+ // version (V): 2 bits
+ // padding (P): 1 bit
+ // extension (X): 1 bit
+ // CSRC count (CC): 4 bits
+ // marker (M): 1 bit
+ // payload type (PT): 7 bits
+ // sequence number: 16 bits
+ // timestamp: 32 bits
+ // SSRC: 32 bits
+ // CSRC list: 0 to 15 items, 32 bits each
+
+ /** Gets the version (V) */
+ public int getVersion() {
+ if (packet_len >= 12)
+ return (packet[0] >> 6 & 0x03);
+ else
+ return 0; // broken packet
+ }
+
+ /** Sets the version (V) */
+ public void setVersion(int v) {
+ if (packet_len >= 12)
+ packet[0] = (byte) ((packet[0] & 0x3F) | ((v & 0x03) << 6));
+ }
+
+ /** Whether has padding (P) */
+ public boolean hasPadding() {
+ if (packet_len >= 12)
+ return getBit(packet[0], 5);
+ else
+ return false; // broken packet
+ }
+
+ /** Set padding (P) */
+ public void setPadding(boolean p) {
+ if (packet_len >= 12)
+ packet[0] = setBit(p, packet[0], 5);
+ }
+
+ /** Whether has extension (X) */
+ public boolean hasExtension() {
+ if (packet_len >= 12)
+ return getBit(packet[0], 4);
+ else
+ return false; // broken packet
+ }
+
+ /** Set extension (X) */
+ public void setExtension(boolean x) {
+ if (packet_len >= 12)
+ packet[0] = setBit(x, packet[0], 4);
+ }
+
+ /** Gets the CSCR count (CC) */
+ public int getCscrCount() {
+ if (packet_len >= 12)
+ return (packet[0] & 0x0F);
+ else
+ return 0; // broken packet
+ }
+
+ /** Whether has marker (M) */
+ public boolean hasMarker() {
+ if (packet_len >= 12)
+ return getBit(packet[1], 7);
+ else
+ return false; // broken packet
+ }
+
+ /** Set marker (M) */
+ public void setMarker(boolean m) {
+ if (packet_len >= 12)
+ packet[1] = setBit(m, packet[1], 7);
+ }
+
+ /** Gets the payload type (PT) */
+ public int getPayloadType() {
+ if (packet_len >= 12)
+ return (packet[1] & 0x7F);
+ else
+ return -1; // broken packet
+ }
+
+ /** Sets the payload type (PT) */
+ public void setPayloadType(int pt) {
+ if (packet_len >= 12)
+ packet[1] = (byte) ((packet[1] & 0x80) | (pt & 0x7F));
+ }
+
+ /** Gets the sequence number */
+ public int getSequenceNumber() {
+ if (packet_len >= 12)
+ return getInt(packet, 2, 4);
+ else
+ return 0; // broken packet
+ }
+
+ /** Sets the sequence number */
+ public void setSequenceNumber(int sn) {
+ if (packet_len >= 12)
+ setInt(sn, packet, 2, 4);
+ }
+
+ /** Gets the timestamp */
+ public long getTimestamp() {
+ if (packet_len >= 12)
+ return getLong(packet, 4, 8);
+ else
+ return 0; // broken packet
+ }
+
+ /** Sets the timestamp */
+ public void setTimestamp(long timestamp) {
+ if (packet_len >= 12)
+ setLong(timestamp, packet, 4, 8);
+ }
+
+ /** Gets the SSCR */
+ public long getSscr() {
+ if (packet_len >= 12)
+ return getLong(packet, 8, 12);
+ else
+ return 0; // broken packet
+ }
+
+ /** Sets the SSCR */
+ public void setSscr(long ssrc) {
+ if (packet_len >= 12)
+ setLong(ssrc, packet, 8, 12);
+ }
+
+ /** Gets the CSCR list */
+ public long[] getCscrList() {
+ int cc = getCscrCount();
+ long[] cscr = new long[cc];
+ for (int i = 0; i < cc; i++)
+ cscr[i] = getLong(packet, 12 + 4 * i, 16 + 4 * i);
+ return cscr;
+ }
+
+ /** Sets the CSCR list */
+ public void setCscrList(long[] cscr) {
+ if (packet_len >= 12) {
+ int cc = cscr.length;
+ if (cc > 15)
+ cc = 15;
+ packet[0] = (byte) (((packet[0] >> 4) << 4) + cc);
+ cscr = new long[cc];
+ for (int i = 0; i < cc; i++)
+ setLong(cscr[i], packet, 12 + 4 * i, 16 + 4 * i);
+ // header_len=12+4*cc;
+ }
+ }
+
+ /** Sets the payload */
+ public void setPayload(byte[] payload, int len) {
+ if (packet_len >= 12) {
+ int header_len = getHeaderLength();
+ for (int i = 0; i < len; i++)
+ packet[header_len + i] = payload[i];
+ packet_len = header_len + len;
+ }
+ }
+
+ /** Gets the payload */
+ public byte[] getPayload() {
+ int header_len = getHeaderLength();
+ int len = packet_len - header_len;
+ byte[] payload = new byte[len];
+ for (int i = 0; i < len; i++)
+ payload[i] = packet[header_len + i];
+ return payload;
+ }
+
+ /** Creates a new RTP packet */
+ public RtpPacket(byte[] buffer, int packet_length) {
+ packet = buffer;
+ packet_len = packet_length;
+ if (packet_len < 12)
+ packet_len = 12;
+ init(0x0F);
+ }
+
+ /** init the RTP packet header (only PT) */
+ public void init(int ptype) {
+ init(ptype, Random.nextLong());
+ }
+
+ /** init the RTP packet header (PT and SSCR) */
+ public void init(int ptype, long sscr) {
+ init(ptype, Random.nextInt(), Random.nextLong(), sscr);
+ }
+
+ /** init the RTP packet header (PT, SQN, TimeStamp, SSCR) */
+ public void init(int ptype, int seqn, long timestamp, long sscr) {
+ setVersion(2);
+ setPayloadType(ptype);
+ setSequenceNumber(seqn);
+ setTimestamp(timestamp);
+ setSscr(sscr);
+ }
+
+ // *********************** Private and Static ***********************
+
+ /** Gets int value */
+ private static int getInt(byte b) {
+ return ((int) b + 256) % 256;
+ }
+
+ /** Gets long value */
+ private static long getLong(byte[] data, int begin, int end) {
+ long n = 0;
+ for (; begin < end; begin++) {
+ n <<= 8;
+ n += data[begin];
+ }
+ return n;
+ }
+
+ /** Sets long value */
+ private static void setLong(long n, byte[] data, int begin, int end) {
+ for (end--; end >= begin; end--) {
+ data[end] = (byte) (n % 256);
+ n >>= 8;
+ }
+ }
+
+ /** Gets Int value */
+ private static int getInt(byte[] data, int begin, int end) {
+ return (int) getLong(data, begin, end);
+ }
+
+ /** Sets Int value */
+ private static void setInt(int n, byte[] data, int begin, int end) {
+ setLong(n, data, begin, end);
+ }
+
+ /** Gets bit value */
+ private static boolean getBit(byte b, int bit) {
+ return (b >> bit) == 1;
+ }
+
+ /** Sets bit value */
+ private static byte setBit(boolean value, byte b, int bit) {
+ if (value)
+ return (byte) (b | (1 << bit));
+ else
+ return (byte) ((b | (1 << bit)) ^ (1 << bit));
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/org/sipdroid/net/RtpSocket.java Sat Jan 23 22:19:43 2010 +0100
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2009 The Sipdroid Open Source Project
+ * Copyright (C) 2005 Luca Veltri - University of Parma - Italy
+ *
+ * This file is part of Sipdroid (http://www.sipdroid.org)
+ *
+ * Sipdroid is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This source code 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this source code; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+package src.org.sipdroid.net;
+
+import java.net.InetAddress;
+import java.net.DatagramPacket;
+import java.io.IOException;
+
+
+
+/**
+ * RtpSocket implements a RTP socket for receiving and sending RTP packets.
+ * <p>
+ * RtpSocket is associated to a DatagramSocket that is used to send and/or
+ * receive RtpPackets.
+ */
+public class RtpSocket {
+ /** UDP socket */
+ SipdroidSocket socket;
+ DatagramPacket datagram;
+
+ /** Remote address */
+ InetAddress r_addr;
+
+ /** Remote port */
+ int r_port;
+
+ /** Creates a new RTP socket (only receiver) */
+ public RtpSocket(SipdroidSocket datagram_socket) {
+ socket = datagram_socket;
+ r_addr = null;
+ r_port = 0;
+ datagram = new DatagramPacket(new byte[1],1);
+ }
+
+ /** Creates a new RTP socket (sender and receiver) */
+ public RtpSocket(SipdroidSocket datagram_socket,
+ InetAddress remote_address, int remote_port) {
+ socket = datagram_socket;
+ r_addr = remote_address;
+ r_port = remote_port;
+ datagram = new DatagramPacket(new byte[1],1);
+ }
+
+ /** Returns the RTP SipdroidSocket */
+ public SipdroidSocket getDatagramSocket() {
+ return socket;
+ }
+
+ /** Receives a RTP packet from this socket */
+ public void receive(RtpPacket rtpp) throws IOException {
+ datagram.setData(rtpp.packet);
+ datagram.setLength(rtpp.packet.length);
+ socket.receive(datagram);
+ if (!socket.isConnected())
+ socket.connect(datagram.getAddress(),datagram.getPort());
+ rtpp.packet_len = datagram.getLength();
+ }
+
+ /** Sends a RTP packet from this socket */
+ public void send(RtpPacket rtpp) throws IOException {
+ datagram.setData(rtpp.packet);
+ datagram.setLength(rtpp.packet_len);
+ datagram.setAddress(r_addr);
+ datagram.setPort(r_port);
+ socket.send(datagram);
+ }
+
+ /** Closes this socket */
+ public void close() { // socket.close();
+ }
+
+}
--- a/src/org/sipdroid/net/SipdroidSocket.java Sat Jan 23 21:48:58 2010 +0100
+++ b/src/org/sipdroid/net/SipdroidSocket.java Sat Jan 23 22:19:43 2010 +0100
@@ -18,7 +18,7 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-package org.sipdroid.net;
+package src.org.sipdroid.net;
import java.io.IOException;
import java.net.DatagramPacket;
@@ -79,8 +79,11 @@
}
static {
+ try {
System.loadLibrary("OSNetworkSystem");
OSNetworkSystem.getOSNetworkSystem().oneTimeInitialization(true);
SipdroidSocket.loaded = true;
+ } catch (Throwable e) {
+ }
}
}
--- a/src/org/sipdroid/net/impl/OSNetworkSystem.java Sat Jan 23 21:48:58 2010 +0100
+++ b/src/org/sipdroid/net/impl/OSNetworkSystem.java Sat Jan 23 22:19:43 2010 +0100
@@ -22,7 +22,7 @@
// address length was changed from long to int for performance reasons.
// END android-note
-package org.sipdroid.net.impl;
+package src.org.sipdroid.net.impl;
import java.io.FileDescriptor;
import java.io.IOException;
--- a/src/org/sipdroid/net/impl/PlainDatagramSocketImpl.java Sat Jan 23 21:48:58 2010 +0100
+++ b/src/org/sipdroid/net/impl/PlainDatagramSocketImpl.java Sat Jan 23 22:19:43 2010 +0100
@@ -18,7 +18,7 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-package org.sipdroid.net.impl;
+package src.org.sipdroid.net.impl;
import java.io.FileDescriptor;
import java.io.IOException;
@@ -76,7 +76,7 @@
private OSNetworkSystem netImpl = OSNetworkSystem.getOSNetworkSystem();
- private volatile boolean isNativeConnected = false;
+ private volatile boolean isNativeConnected;
public int receiveTimeout;
--- a/src/org/sipdroid/net/tools/DataFramePool.java Sat Jan 23 21:48:58 2010 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,44 +0,0 @@
-package org.sipdroid.net.tools;
-
-import jlibrtp.DataFrame;
-
-public class DataFramePool extends ObjectPool {
-
- private static DataFramePool instance = null;
- public static DataFramePool getInstance() {
- if(instance == null) {
- instance = new DataFramePool(20);
- }
- return instance;
- }
-
- public static void removeInstance() {
- instance = null;
- }
-
- protected DataFramePool(int nbObject) {
- super(nbObject);
- for(int i = 0; i < nbObject; ++i) {
- checkIn(create());
- }
- }
-
- @Override
- Object create() {
- return new DataFrame();
- }
-
- @Override
- boolean validate(Object o) {
- return true;
- }
-
- public DataFrame borrowFrame() {
- return (DataFrame) super.checkOut();
- }
-
- public void returnFrame(DataFrame o) {
- o.release();
- super.checkIn(o);
- }
-}
--- a/src/org/sipdroid/net/tools/DatagramPool.java Sat Jan 23 21:48:58 2010 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,45 +0,0 @@
-package org.sipdroid.net.tools;
-
-import java.net.DatagramPacket;
-
-public class DatagramPool extends ObjectPool {
-
- private static DatagramPool instance = null;
- public static DatagramPool getInstance() {
- if(instance == null) {
- instance = new DatagramPool(20);
- }
- return instance;
- }
-
- public static void removeInstance() {
- instance = null;
- }
-
- protected DatagramPool(int nbDatagram) {
- super(nbDatagram);
- for(int i = 0; i < nbDatagram; ++i) {
- checkIn(create());
- }
- }
-
- @Override
- Object create() {
- byte[] rawPkt = new byte[1500];
- DatagramPacket packet = new DatagramPacket(rawPkt, rawPkt.length);
- return packet;
- }
-
- @Override
- boolean validate(Object o) {
- return true;
- }
-
- public DatagramPacket borrowPacket() {
- return (DatagramPacket) super.checkOut();
- }
-
- public void returnPacket(DatagramPacket packet) {
- super.checkIn(packet);
- }
-}
--- a/src/org/sipdroid/net/tools/GenericPool.java Sat Jan 23 21:48:58 2010 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,31 +0,0 @@
-package org.sipdroid.net.tools;
-
-public class GenericPool<E> extends ObjectPool<Object> {
-
- public GenericPool(int size) {
- super(size);
- for(int i = 0; i < size; ++i) {
- checkIn(create());
- }
- }
-
- @Override
- protected E create() {
- return (E)new Object();
- }
-
- @Override
- protected boolean validate(Object o) {
- // TODO Auto-generated method stub
- return false;
- }
-
- public E borrowItem() {
- return (E) super.checkOut();
- }
-
- public void returnItem(E o) {
- super.checkIn(o);
- }
-
-}
--- a/src/org/sipdroid/net/tools/ObjectPool.java Sat Jan 23 21:48:58 2010 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,37 +0,0 @@
-package org.sipdroid.net.tools;
-
-import java.util.ArrayList;
-
-public abstract class ObjectPool<E> {
- private ArrayList<Object> locked, unlocked;
-
- ObjectPool(int size){
- locked = new ArrayList<Object>(size);
- unlocked = new ArrayList<Object>(size);
- }
-
- public int getPoolSize() {
- return locked.size() + unlocked.size();
- }
-
- abstract Object create();
- abstract boolean validate( Object o );
- synchronized Object checkOut(){
- if(unlocked.size() > 0){
- Object cur = unlocked.get(0);
- unlocked.remove(cur);
- locked.add(cur);
- return(cur);
- }
- // no objects available, create a new one
- Object o = create();
- locked.add(o);
- return(o);
- }
-
- synchronized void checkIn( Object o ) {
- locked.remove( o );
- unlocked.add(o);
- }
-
-}
--- a/src/org/sipdroid/net/tools/PktBufNodePool.java Sat Jan 23 21:48:58 2010 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,44 +0,0 @@
-package org.sipdroid.net.tools;
-
-import jlibrtp.PktBufNode;
-
-public class PktBufNodePool extends ObjectPool {
-
- private static PktBufNodePool instance = null;
- public static PktBufNodePool getInstance() {
- if(instance == null) {
- instance = new PktBufNodePool(20);
- }
- return instance;
- }
-
- public static void removeInstance() {
- instance = null;
- }
-
- protected PktBufNodePool(int nbObject) {
- super(nbObject);
- for(int i = 0; i < nbObject; ++i) {
- checkIn(create());
- }
- }
-
- @Override
- Object create() {
- return new PktBufNode();
- }
-
- @Override
- boolean validate(Object o) {
- return true;
- }
-
- public PktBufNode borrowBufNode() {
- return (PktBufNode) super.checkOut();
- }
-
- public void returnBufNode(PktBufNode o) {
- super.checkIn(o);
- }
-
-}
--- a/src/org/sipdroid/net/tools/RtpPktPool.java Sat Jan 23 21:48:58 2010 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,44 +0,0 @@
-package org.sipdroid.net.tools;
-
-import jlibrtp.RtpPkt;
-
-public class RtpPktPool extends ObjectPool {
-
- private static RtpPktPool instance = null;
- public static RtpPktPool getInstance() {
- if(instance == null) {
- instance = new RtpPktPool(20);
- }
- return instance;
- }
-
- public static void removeInstance() {
- instance = null;
- }
-
- protected RtpPktPool(int nbObject) {
- super(nbObject);
- for(int i = 0; i < nbObject; ++i) {
- checkIn(create());
- }
- }
-
- @Override
- Object create() {
- return new RtpPkt();
- }
-
- @Override
- boolean validate(Object o) {
- return true;
- }
-
- public RtpPkt borrowPkt() {
- return (RtpPkt) super.checkOut();
- }
-
- public void returnPkt(RtpPkt o) {
- super.checkIn(o);
- }
-
-}