/* * Copyright (C) 2005 Luca Veltri - University of Parma - Italy * * This source code 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 2 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 * * Author(s): * Luca Veltri (luca.veltri@unipr.it) */ package local.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) 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) 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) 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); } // use this if you don't want to overwrite header of received rtp packet with 'default' values public RtpPacket(byte[] buffer) { packet=buffer; packet_len=buffer.length; if (packet_len<12) packet_len=12; } /** 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; } */ private static long getLong(byte[] data, int begin, int end) { long n=0; for (; begin<end; begin++) { n<<=8; n+=(data[begin] & 0xff); } //return n & 0xff^(end-begin+1); return n; } /** Sets long value */ private static void setLong(long n, byte[] data, int begin, int end) { //int v=end-begin-1; for (end-- ; end>=begin; end--) { data[end]=(byte)(n%256); n>>=8; //data[end]=(byte)((n >>> 8*v) & 0xFF); //v--; } } /** 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((long)n,data,begin,end); } /** Gets bit value */ private static boolean getBit(byte b, int bit) { return (b>>bit)==1; } /** Sets bit value */ private static void setBit(boolean value, byte b, int bit) { if (value) b=(byte)(b|(1<<bit)); else b=(byte)((b|(1<<bit))^(1<<bit)); } public void setContent(byte[] buffer, int packet_length) { packet=buffer; packet_len=packet_length; if (packet_len<12) packet_len=12; } }