/*
* This file is part of AirReceiver.
*
* AirReceiver 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.
* AirReceiver 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 AirReceiver. If not, see <http://www.gnu.org/licenses/>.
*/
package org.dyndns.jkiddo.raop.server.airreceiver;
import org.jboss.netty.buffer.*;
/**
* Basic RTP packet as described by RFC 3550
*/
public class RtpPacket
{
public static final int Length = 4;
final private ChannelBuffer m_buffer;
protected RtpPacket(final int size)
{
assert size >= Length;
m_buffer = ChannelBuffers.buffer(size);
m_buffer.writeZero(size);
setVersion((byte) 2);
}
public RtpPacket(final ChannelBuffer buffer)
{
m_buffer = buffer;
}
public RtpPacket(final ChannelBuffer buffer, final int minimumSize) throws ProtocolException
{
this(buffer);
if(buffer.capacity() < minimumSize)
throw new InvalidPacketException("Packet had invalid size " + buffer.capacity() + " instead of at least " + minimumSize);
}
public ChannelBuffer getBuffer()
{
return m_buffer;
}
public int getLength()
{
return m_buffer.capacity();
}
/**
* Get the RTP version number. Always 2.
*
* @return RTP version number
*/
public byte getVersion()
{
return (byte) ((m_buffer.getByte(0) & (0xC0)) >> 6);
}
/**
* Sets the RTP version number. Should be 2.
*
* @param version
* RTP version number
*/
public void setVersion(final byte version)
{
assert (version & ~0x03) == 0;
m_buffer.setByte(0, (m_buffer.getByte(0) & ~(0xC0)) | (version << 6));
}
/**
* Gets the RTP padding flag
*
* @return RTP padding flag
*/
public boolean getPadding()
{
return (m_buffer.getByte(0) & (0x20)) != 0;
}
/**
* Sets the RTP padding flag
*
* @param padding
* RTP padding flag
*/
public void setPadding(final boolean padding)
{
m_buffer.setByte(0, (m_buffer.getByte(0) & ~0x20) | (padding ? 0x20 : 0x00));
}
/**
* Gets the RTP padding flag
*
* @return RTP padding flag
*/
public boolean getExtension()
{
return (m_buffer.getByte(0) & (0x10)) != 0;
}
/**
* Sets the RTP padding flag
*
* @param padding
* RTP padding flag
*/
public void setExtension(final boolean extension)
{
m_buffer.setByte(0, (m_buffer.getByte(0) & ~0x10) | (extension ? 0x10 : 0x00));
}
/**
* Gets the number of CSRC (contributing source) identifiers included in the packet header.
* <p>
*
* @return nubmer of CSRC ids
*/
public byte getCsrcCount()
{
return (byte) (m_buffer.getByte(0) & (0x0f));
}
/**
* Sets the number of CSRC (contributing source) identifiers included in the packet header. Should be zero.
* <p>
*
* @param csrcCount
* nubmer of CSRC ids
*/
public void setCsrcCount(final byte csrcCount)
{
assert (csrcCount & ~0x0f) == 0;
m_buffer.setByte(0, (m_buffer.getByte(0) & ~0x0f) | csrcCount);
}
/**
* Sets the RTP marker flag
*
* @param marker
* RTP marker flag
*/
public boolean getMarker()
{
return (m_buffer.getByte(1) & (0x80)) != 0;
}
/**
* Sets the RTP marker flag
*
* @param marker
* RTP marker flag
*/
public void setMarker(final boolean marker)
{
m_buffer.setByte(1, (m_buffer.getByte(1) & ~0x80) | (marker ? 0x80 : 0x00));
}
/**
* Gets the packet's payload type
*
* @return packet's payload type
*/
public byte getPayloadType()
{
return (byte) (m_buffer.getByte(1) & (0x7f));
}
/**
* Sets the packet's payload type
*
* @param payloadType
* packet's payload type
*/
public void setPayloadType(final byte payloadType)
{
assert (payloadType & ~0x7f) == 0;
m_buffer.setByte(1, (m_buffer.getByte(1) & ~0x7f) | payloadType);
}
/**
* Gets the packet's sequence number
*
* @return packet's sequence number
*/
public int getSequence()
{
return ((m_buffer.getByte(2) & 0xff) << 8) | ((m_buffer.getByte(3) & 0xff) << 0);
}
/**
* Sets the packet's sequence number
*
* @param value
* packet's sequence number
*/
public void setSequence(final int sequence)
{
assert (sequence & ~0xffff) == 0;
m_buffer.setByte(2, (sequence & 0xff00) >> 8);
m_buffer.setByte(3, (sequence & 0x00ff) >> 0);
}
@Override
public String toString()
{
final StringBuilder s = new StringBuilder();
s.append(this.getClass().getSimpleName());
s.append("(");
s.append(Integer.toHexString(getPayloadType()));
s.append(")");
s.append(" ");
s.append("ver=");
s.append(getVersion());
s.append(" ");
s.append("pad=");
s.append(getPadding());
s.append(" ");
s.append("ext=");
s.append(getExtension());
s.append(" ");
s.append("csrcc=");
s.append(getCsrcCount());
s.append(" ");
s.append("marker=");
s.append(getMarker());
s.append(" ");
s.append("seq=");
s.append(getSequence());
return s.toString();
}
}