/** * BigBlueButton open source conferencing system - http://www.bigbluebutton.org/ * * Copyright (c) 2012 BigBlueButton Inc. and by respective authors (see below). * * This program 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 3.0 of the License, or (at your option) any later * version. * * BigBlueButton 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 BigBlueButton; if not, see <http://www.gnu.org/licenses/>. * */ package org.bigbluebutton.voiceconf.red5.media.net; public class RtpPacket { private static final int HEADER_LENGTH = 12; private byte[] packet; private int packetLength; long temp; public RtpPacket(byte[] buffer, int packet_length) { packet = buffer; packetLength = packet_length; setVersion(2); if (packetLength < HEADER_LENGTH) packetLength = HEADER_LENGTH; } public byte[] getPacket() { return packet; } public int getLength() { return packetLength; } public void setPacketLength(int length) { packetLength = length; } public int getHeaderLength() { if (packetLength >= HEADER_LENGTH) return HEADER_LENGTH + 4 * getCscrCount(); else return packetLength; // broken packet } public int getPayloadLength() { if (packetLength >= HEADER_LENGTH) return packetLength - getHeaderLength(); else return 0; // broken packet } /** Sets the RTP payload length */ public void setPayloadLength(int len) { packetLength = 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 public int getVersion() { if (packetLength >= HEADER_LENGTH) /* 0xC0 = 1100 0000 */ return ((packet[0] & 0xC0) >> 6); else return 0; // broken packet } public void setVersion(int v) { if (packetLength >= HEADER_LENGTH) // Should check the if version is greater that 2-bits packet[0] = (byte)((v << 6) | packet[0]); } public boolean hasPadding() { if (packetLength >= HEADER_LENGTH) /* 0x20 = 0010 0000 */ return ((packet[0] & 0x20) >> 5) == 1; else return false; // broken packet } public void setPadding(boolean p) { if (packetLength >= HEADER_LENGTH) { if (p) { /* 0x20 = 0010 0000 */ packet[0] = (byte) (packet[0] | 0x20); } else { /* 0xDF = 1101 1111 */ packet[0] = (byte) (packet[0] & 0xDF); } } } public boolean hasExtension() { if (packetLength >= HEADER_LENGTH) /* 0x10 = 0001 0000 */ return ((packet[0] & 0x10) >> 4) == 1; else return false; // broken packet } public void setExtension(boolean x) { if (packetLength >= HEADER_LENGTH) { if (x) { /* 0x10 = 0001 0000 */ packet[0] = (byte) (packet[0] | 0x10); } else { /* 0xEF = 1110 1111 */ packet[0] = (byte) (packet[0] & 0xEF); } } } public int getCscrCount() { if (packetLength >= HEADER_LENGTH) return (packet[0] & 0x0F); else return 0; // broken packet } public void setCscrCount(int count) { if (packetLength >= HEADER_LENGTH) // Should check the if version is greater that 4-bits packet[0] = (byte) ((packet[0] & 0xF0) | (count & 0x0F)); } public boolean hasMarker() { if (packetLength >= HEADER_LENGTH) { return ((packet[1] & 0x80) >> 7) == 1; } else return false; // broken packet } public void setMarker(boolean m) { if (packetLength >= HEADER_LENGTH) { if (m) { /* 0x80 = 1000 0000 */ packet[1] = (byte) (packet[1] | 0x80); } else { /* 0x7F = 0111 1111 */ packet[1] = (byte) (packet[1] & 0x7F); } } } public int getPayloadType() { if (packetLength >= HEADER_LENGTH) return (packet[1] & 0x7F); else return -1; // broken packet } public void setPayloadType(int pt) { if (packetLength >= HEADER_LENGTH) packet[1] = (byte)((packet[1] & 0x80) | (pt & 0x7F)); } public int getSeqNum() { if (packetLength >= HEADER_LENGTH) { return getInt(packet, 2); } else return 0; // broken packet } public void setSeqNum(int sn) { if (packetLength >= HEADER_LENGTH) { setInt(sn, packet, 2); } } public long getTimestamp() { if (packetLength >= HEADER_LENGTH) { return getLong(packet, 4); } else return 0; // broken packet } public void setTimestamp(long timestamp) { if (packetLength >= HEADER_LENGTH) { setLong(timestamp, packet, 4); } } public long getSsrc() { if (packetLength >= HEADER_LENGTH) { return getLong(packet, 8); } else return 0; // broken packet } public void setSsrc(long ssrc) { if (packetLength >= HEADER_LENGTH) { setLong(ssrc, packet, 8); } } public long[] getCscrList() { int cc = getCscrCount(); long[] cscr = new long[cc]; for (int i = 0; i < cc; i++) cscr[i] = getLong(packet, HEADER_LENGTH + 4 * i); return cscr; } public void setCscrList(long[] cscr) { if (packetLength >= HEADER_LENGTH) { int cc = cscr.length; setCscrCount(cc); for (int i = 0; i < cc; i++) setLong(cscr[i], packet, HEADER_LENGTH + 4 * i); } } /** Sets the payload */ public void setPayload(byte[] payload, int len) { if (packetLength >= HEADER_LENGTH) { int header_len = getHeaderLength(); System.arraycopy(payload, 0, packet, getHeaderLength(), len); packetLength = header_len + len; } } /** Gets the payload */ public byte[] getPayload() { int len = packetLength - getHeaderLength(); byte[] payload = new byte[len]; System.arraycopy(packet, getHeaderLength(), payload, 0, len); return payload; } public boolean isRtcpPacket() { int payloadType = (packet[1] & 0xFF); if ((payloadType >= 200) && (payloadType <= 204)) return true; return false; } public int getRtcpPayloadType() { return (packet[1] & 0xFF); } // *********************** 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 start) { return ((int) ((data[start] << 24) & 0xFF000000) + ((int) (data[start + 1] << 16) & 0xFF0000) + ((int) (data[start + 2] << 8) & 0xFF00) + ((int) (data[start + 3] & 0xFF))); } private static void setLong(long n, byte[] data, int start) { data[start] = (byte) ((int) n >> 24); data[start + 1] = (byte) ((int) n >> 16); data[start + 2] = (byte) ((int) n >> 8); data[start + 3] = (byte) ((int) n & 0xFF); } /** Gets Int value */ private static int getInt(byte[] data, int start) { return ((int) (data[start] << 8) & 0xFF00) + ((int) (data[start + 1] & 0xFF)); } /** Sets Int value */ private static void setInt(int n, byte[] data, int start) { data[start] = (byte) ((int) n >> 8); data[start + 1] = (byte) ((int) n & 0xFF); } /** 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)); } }