/** {@inheritDoc} */
public void pushMessage(IPipe pipe, IMessage message) throws IOException {
if (message instanceof RTMPMessage) {
RTMPMessage rtmpMessage = (RTMPMessage) message;
IRTMPEvent body = rtmpMessage.getBody();
if (body instanceof IStreamData) {
// the subscriber paused
if (subscriberStream.getState() == StreamState.PAUSED) {
log.debug("Dropping packet because we are paused");
videoFrameDropper.dropPacket(rtmpMessage);
return;
}
if (body instanceof VideoData) {
if (msgIn instanceof IBroadcastScope) {
IBroadcastStream stream = (IBroadcastStream) ((IBroadcastScope) msgIn).getClientBroadcastStream();
if (stream != null && stream.getCodecInfo() != null) {
IVideoStreamCodec videoCodec = stream.getCodecInfo().getVideoCodec();
//dont try to drop frames if video codec is null - related to SN-77
if (videoCodec != null && videoCodec.canDropFrames()) {
if (!receiveVideo) {
// The client disabled video or the app doesn't have enough bandwidth
// allowed for this stream.
log.debug("Dropping packet because we cant receive video or token acquire failed");
videoFrameDropper.dropPacket(rtmpMessage);
return;
}
// Only check for frame dropping if the codec supports it
long pendingVideos = pendingVideoMessages();
if (!videoFrameDropper.canSendPacket(rtmpMessage, pendingVideos)) {
// Drop frame as it depends on other frames that were dropped before.
log.debug("Dropping packet because frame dropper says we cant send it");
return;
}
// increment the number of times we had pending video frames sequentially
if (pendingVideos > 1) {
numSequentialPendingVideoFrames++;
} else {
// reset number of sequential pending frames if 1 or 0 are pending.
numSequentialPendingVideoFrames = 0;
}
if (pendingVideos > maxPendingVideoFramesThreshold || numSequentialPendingVideoFrames > maxSequentialPendingVideoFrames) {
log.debug("Pending: {} Threshold: {} Sequential: {}", new Object[] { pendingVideos, maxPendingVideoFramesThreshold,
numSequentialPendingVideoFrames });
// We drop because the client has insufficient bandwidth.
long now = System.currentTimeMillis();
if (bufferCheckInterval > 0 && now >= nextCheckBufferUnderrun) {
// Notify client about frame dropping (keyframe)
sendInsufficientBandwidthStatus(currentItem);
nextCheckBufferUnderrun = now + bufferCheckInterval;
}
videoFrameDropper.dropPacket(rtmpMessage);
return;
}
}
}
}
} else if (body instanceof AudioData) {
if (!receiveAudio && sendBlankAudio) {
// Send blank audio packet to reset player
sendBlankAudio = false;
body = new AudioData();
if (lastMessageTs > 0) {
body.setTimestamp(lastMessageTs);
} else {
body.setTimestamp(0);
}
rtmpMessage = RTMPMessage.build(body);
} else if (!receiveAudio) {
return;
}
}
sendMessage(rtmpMessage);
} else {
throw new RuntimeException(String.format("Expected IStreamData but got %s (type %s)", body.getClass(), body.getDataType()));
}
} else if (message instanceof ResetMessage) {
sendReset();
} else {
msgOut.pushMessage(message);