    public Packet decodePacket(RTMP rtmp, ByteBuffer in) {
		final int remaining = in.remaining();
		if (remaining < 1) {
			rtmp.bufferDecoding(1);
			return null;
		}
		final int position = in.position();
		final byte headerByte = in.get();
		final byte channelId = RTMPUtils.decodeChannelId(headerByte);
		if (channelId < 0) {
			throw new ProtocolException("Bad channel id: " + channelId);
		}
		final byte headerSize = RTMPUtils.decodeHeaderSize(headerByte);
		int headerLength = RTMPUtils.getHeaderLength(headerSize);
		if (headerLength > remaining) {
			if (log.isDebugEnabled()) {
				log.debug("Header too small, buffering. remaining: " + remaining);
			}
			in.position(position);
			rtmp.bufferDecoding(headerLength);
			return null;
		}
		in.position(position);
		final Header header = decodeHeader(in, rtmp
				.getLastReadHeader(channelId));
		if (header == null) {
			throw new ProtocolException("Header is null, check for error");
		}
		rtmp.setLastReadHeader(channelId, header);
		Packet packet = rtmp.getLastReadPacket(channelId);
		if (packet == null) {
			packet = new Packet(header);
			rtmp.setLastReadPacket(channelId, packet);
		}
		final ByteBuffer buf = packet.getData();
		final int addSize = (header.getTimer() == 0xffffff ? 4 : 0);
		final int readRemaining = header.getSize() + addSize - buf.position();
		final int chunkSize = rtmp.getReadChunkSize();
		final int readAmount = (readRemaining > chunkSize) ? chunkSize
				: readRemaining;
		if (in.remaining() < readAmount) {
			if (log.isDebugEnabled()) {
				log.debug("Chunk too small, buffering (" + in.remaining() + ','
						+ readAmount);
			}
			in.position(position);
			rtmp.bufferDecoding(headerSize + readAmount);
			return null;
		}
		BufferUtils.put(buf, in, readAmount);
		if (buf.position() < header.getSize() + addSize) {
			rtmp.continueDecoding();
			return null;
		}
		buf.flip();
		final IRTMPEvent message = decodeMessage(rtmp, packet.getHeader(), buf);
		packet.setMessage(message);
		if (message instanceof ChunkSize) {
			ChunkSize chunkSizeMsg = (ChunkSize) message;
			rtmp.setReadChunkSize(chunkSizeMsg.getSize());
		}
		rtmp.setLastReadPacket(channelId, null);
		return packet;
	}

    public Packet decodePacket(RTMP rtmp, ByteBuffer in) {
		final int remaining = in.remaining();
		if (remaining < 1) {
			rtmp.bufferDecoding(1);
			return null;
		}
		final int position = in.position();
		final byte headerByte = in.get();
		final byte channelId = RTMPUtils.decodeChannelId(headerByte);
		if (channelId < 0) {
			throw new ProtocolException("Bad channel id: " + channelId);
		}
		int headerLength = RTMPUtils.getHeaderLength(RTMPUtils.decodeHeaderSize(headerByte));
		if (headerLength > remaining) {
			if (log.isDebugEnabled()) {
				log.debug("Header too small, buffering. remaining: " + remaining);
			}
			in.position(position);
			rtmp.bufferDecoding(headerLength);
			return null;
		}
		in.position(position);
		final Header header = decodeHeader(in, rtmp
				.getLastReadHeader(channelId));
		if (header == null) {
			throw new ProtocolException("Header is null, check for error");
		}
		rtmp.setLastReadHeader(channelId, header);
		Packet packet = rtmp.getLastReadPacket(channelId);
		if (packet == null) {
			packet = new Packet(header);
			rtmp.setLastReadPacket(channelId, packet);
		}
		final ByteBuffer buf = packet.getData();
		final int addSize = (header.getTimer() == 0xffffff ? 4 : 0);
		final int readRemaining = header.getSize() + addSize - buf.position();
		final int chunkSize = rtmp.getReadChunkSize();
		final int readAmount = (readRemaining > chunkSize) ? chunkSize
				: readRemaining;
		if (in.remaining() < readAmount) {
			if (log.isDebugEnabled()) {
				log.debug("Chunk too small, buffering (" + in.remaining() + ','
						+ readAmount);
			}
			in.position(position);
			rtmp.bufferDecoding(headerLength + readAmount);
			return null;
		}
		BufferUtils.put(buf, in, readAmount);
		if (buf.position() < header.getSize() + addSize) {
			rtmp.continueDecoding();
			return null;
		}
		buf.flip();
		final IRTMPEvent message = decodeMessage(rtmp, packet.getHeader(), buf);
		packet.setMessage(message);
		if (message instanceof ChunkSize) {
			ChunkSize chunkSizeMsg = (ChunkSize) message;
			rtmp.setReadChunkSize(chunkSizeMsg.getSize());
		}
		rtmp.setLastReadPacket(channelId, null);
		return packet;
	}
