/******************************************************************************* * Copyright 2015 alladin-IT GmbH * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. *******************************************************************************/ package at.alladin.rmbt.util.net.rtp; import java.nio.ByteOrder; import java.util.Arrays; import at.alladin.rmbt.util.ByteUtil; import at.alladin.rmbt.util.net.rtp.RealtimeTransportProtocol.PayloadType; import at.alladin.rmbt.util.net.rtp.RealtimeTransportProtocol.RtpException; import at.alladin.rmbt.util.net.rtp.RealtimeTransportProtocol.RtpException.RtpErrorType; import at.alladin.rmbt.util.net.rtp.RealtimeTransportProtocol.RtpVersion; /** * rtp packet including header and payload * @author lb * */ public class RtpPacket { byte[] header; byte[] csrcIdentifier; byte[] payload; public RtpPacket(PayloadType payloadType, int csrcCount, long[] csrc, int seqNumber, long timeStamp, long ssrc) { this(payloadType, csrcCount, csrc, seqNumber, timeStamp, ssrc, null); } public RtpPacket(PayloadType payloadType, int csrcCount, long[] csrc, int seqNumber, long timeStamp, long ssrc, byte[] payload) { this.header = RealtimeTransportProtocol.createHeaderBytes(RtpVersion.VER2, false, false, csrcCount, false, payloadType, seqNumber, timeStamp, ssrc); this.csrcIdentifier = RealtimeTransportProtocol.createCsrcIdentifierBytes(csrc); this.payload = payload; } public RtpPacket(byte[] packet) throws RtpException { if (packet == null || packet.length < 12) { throw new RtpException(RtpErrorType.PACKET_SIZE_TOO_SMALL); } try { header = new byte[12]; System.arraycopy(packet, 0, header, 0, header.length); int curPos = header.length; int csrsCount = getCsrcCount(); if (csrsCount > 0) { csrcIdentifier = new byte[csrsCount * 4]; System.arraycopy(packet, curPos, csrcIdentifier, 0, csrcIdentifier.length); curPos += csrcIdentifier.length; } if (packet.length > curPos) { int payloadSize = packet.length - curPos; payload = new byte[payloadSize]; System.arraycopy(packet, curPos, payload, 0, payload.length); } } catch (Exception e) { throw new RtpException(RtpErrorType.INVALID_HEADER); } } public byte[] getHeader() { return header; } public void setHeader(byte[] header) { this.header = header; } public byte[] getCsrcIdentifier() { return csrcIdentifier; } public void setCsrcIdentifier(byte[] csrcIdentifier) { this.csrcIdentifier = csrcIdentifier; } public byte[] getPayload() { return payload; } public void setPayload(byte[] payload) { this.payload = payload; } /** * * @param packet * @return */ public PayloadType getPayloadType() { return PayloadType.getByCodecValue(header[1] & 0x7F); } /** * * @param packet * @param payloadType */ public void setPayloadType( PayloadType payloadType) { header[1] = ByteUtil.setRightBitsValue(header[1], 7, payloadType.getValue()); } /** * * @param packet * @return */ public boolean hasMarker() { return ByteUtil.getBit(header[1], 7); } /** * * @param packet * @param hasMarker */ public void setHasMarker(boolean hasMarker) { header[1] = ByteUtil.setBit(header[1], 7, hasMarker); } /** * * @param packet * @return */ public RtpVersion getVersion() { return RtpUtil.getVersion(header[0]); } /** * * @param version */ public void setVersion(RtpVersion version) { header[0] = ByteUtil.setLeftBitsValue(header[0], 2, version.getVersion()); } /** * * @param packet * @return */ public int getCsrcCount() { return (header[0] & 0x0F); } /** * * @param csrcCount */ public void setCsrcCount(int csrcCount) { header[0] = ByteUtil.setRightBitsValue(header[0], 4, csrcCount); } /** * * @return */ public long[] getCsrcIdentifiersAsLong() { if (csrcIdentifier != null && csrcIdentifier.length > 0) { long[] csrcIds = new long[csrcIdentifier.length / 4]; for (int i = 0; i < csrcIds.length; i++) { csrcIds[i] = ByteUtil.getLong(csrcIdentifier, i*4, 3 + i*4, ByteOrder.BIG_ENDIAN); } return csrcIds; } return new long[] {}; } /** * * @param packet * @return */ public boolean hasPadding() { return ByteUtil.getBit(header[0], 5); } /** * * @param hasPadding */ public void setHasPadding(boolean hasPadding) { header[0] = ByteUtil.setBit(header[0], 5, hasPadding); } /** * * @param packet * @return */ public boolean hasExtension() { return ByteUtil.getBit(header[0], 4); } /** * * @param hasExtension */ public void setHasExtension(boolean hasExtension) { header[0] = ByteUtil.setBit(header[0], 4, hasExtension); } /** * * @return */ public int getSequnceNumber() { return ByteUtil.getInt(header, 2, 3, ByteOrder.BIG_ENDIAN); } /** * * @param seqNumber */ public void setSequnceNumber(int seqNumber) { header = ByteUtil.setInt(header, 2, 3, seqNumber, ByteOrder.BIG_ENDIAN); } /** * * @param delta */ public void increaseSequenceNumber(int delta) { setSequnceNumber(getSequnceNumber() + delta); } /** * * @return */ public long getTimestamp() { return ByteUtil.getLong(header, 4, 7, ByteOrder.BIG_ENDIAN); } /** * * @param timestamp */ public void setTimestamp(long timestamp) { header = ByteUtil.setLong(header, 4, 7, timestamp, ByteOrder.BIG_ENDIAN); } /** * * @param delta */ public void increaseTimestamp(long delta) { setTimestamp(getTimestamp() + delta); } /** * * @return */ public long getSsrc() { return ByteUtil.getLong(header, 8, 11, ByteOrder.BIG_ENDIAN); } /** * * @param ssrc * @return */ public void setSsrc(long ssrc) { header = ByteUtil.setLong(header, 8, 11, ssrc, ByteOrder.BIG_ENDIAN); } /** * * @return */ public byte[] getBytes() { final byte[] d = new byte[header.length + (csrcIdentifier != null ? csrcIdentifier.length : 0) + (payload != null ? payload.length : 0)]; int curPos = 0; System.arraycopy(header, 0, d, 0, header.length); curPos += header.length; if (csrcIdentifier != null) { System.arraycopy(csrcIdentifier, 0, d, curPos, csrcIdentifier.length); curPos += csrcIdentifier.length; } if (payload != null) { System.arraycopy(payload, 0, d, curPos, payload.length); } return d; } @Override public String toString() { return "RtpPacket [payload=" + Arrays.toString(payload) + ", getPayloadType()=" + getPayloadType() + ", hasMarker()=" + hasMarker() + ", getVersion()=" + getVersion() + ", getCsrcCount()=" + getCsrcCount() + ", getCsrcIdentifiersAsLong()=" + Arrays.toString(getCsrcIdentifiersAsLong()) + ", hasPadding()=" + hasPadding() + ", hasExtension()=" + hasExtension() + ", getSequnceNumber()=" + getSequnceNumber() + ", getTimestamp()=" + getTimestamp() + ", getSsrc()=" + getSsrc() + "]"; } }