if (header == null) {
throw new ProtocolException("Header is null, check for error");
}
rtmp.setLastReadHeader(channelId, header);
// check to see if this is a new packets or continue decoding an existing one
Packet packet = rtmp.getLastReadPacket(channelId);
if (packet == null) {
packet = new Packet(header.clone());
rtmp.setLastReadPacket(channelId, packet);
}
final IoBuffer buf = packet.getData();
final int readRemaining = header.getSize() - buf.position();
final int chunkSize = rtmp.getReadChunkSize();
final int readAmount = (readRemaining > chunkSize) ? chunkSize : readRemaining;
if (in.remaining() < readAmount) {
log.debug("Chunk too small, buffering ({},{})", in.remaining(), readAmount);
// skip the position back to the start
in.position(position);
state.bufferDecoding(headerLength + readAmount);
return null;
}
BufferUtils.put(buf, in, readAmount);
if (buf.position() < header.getSize()) {
state.continueDecoding();
return null;
}
if (buf.position() > header.getSize()) {
log.warn("Packet size expanded from {} to {} ({})", new Object[] { (header.getSize()), buf.position(), header });
}
buf.flip();
try {
final IRTMPEvent message = decodeMessage(conn, packet.getHeader(), buf);
message.setHeader(packet.getHeader());
// Unfortunately flash will, especially when resetting a video stream with a new key frame, sometime
// send an earlier time stamp. To avoid dropping it, we just give it the minimal increment since the
// last message. But to avoid relative time stamps being mis-computed, we don't reset the header we stored.
final Header lastReadHeader = rtmp.getLastReadPacketHeader(channelId);
if (lastReadHeader != null && (message instanceof AudioData || message instanceof VideoData)
&& RTMPUtils.compareTimestamps(lastReadHeader.getTimer(), packet.getHeader().getTimer()) >= 0) {
log.trace("Non-monotonically increasing timestamps; type: {}; adjusting to {}; ts: {}; last: {}", new Object[] { header.getDataType(),
lastReadHeader.getTimer() + 1, header.getTimer(), lastReadHeader.getTimer() });
message.setTimestamp(lastReadHeader.getTimer() + 1);
} else {
message.setTimestamp(header.getTimer());
}
rtmp.setLastReadPacketHeader(channelId, packet.getHeader());
packet.setMessage(message);
if (message instanceof ChunkSize) {
ChunkSize chunkSizeMsg = (ChunkSize) message;
rtmp.setReadChunkSize(chunkSizeMsg.getSize());
} else if (message instanceof Abort) {
log.debug("Abort packet detected");