diff -r f5a5d9237d69 -r e8d6255306f8 src/jlibrtp/RtpPkt.java --- 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