- generate key frames regularly instead of just when the user joins. This allows us to enable
dropping of packets for slow connections in red5
This commit is contained in:
parent
134facbbf4
commit
bef5e77357
@ -22,6 +22,7 @@ import java.io.IOException;
|
||||
import java.util.Collection;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CopyOnWriteArraySet;
|
||||
|
||||
import org.red5.logging.Red5LoggerFactory;
|
||||
import org.red5.server.api.event.IEvent;
|
||||
import org.red5.server.api.scope.IScope;
|
||||
@ -38,12 +39,12 @@ import org.red5.server.messaging.PipeConnectionEvent;
|
||||
import org.red5.server.net.rtmp.event.IRTMPEvent;
|
||||
import org.red5.server.net.rtmp.event.Notify;
|
||||
import org.red5.server.net.rtmp.event.VideoData;
|
||||
import org.red5.server.net.rtmp.message.Constants;
|
||||
import org.red5.server.stream.message.RTMPMessage;
|
||||
import org.red5.codec.IVideoStreamCodec;
|
||||
import org.red5.codec.IStreamCodecInfo;
|
||||
import org.red5.codec.StreamCodecInfo;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
import org.red5.server.api.stream.IStreamPacket;;
|
||||
|
||||
public class ScreenVideoBroadcastStream implements IBroadcastStream, IProvider, IPipeConnectionListener {
|
||||
@ -189,7 +190,7 @@ public class ScreenVideoBroadcastStream implements IBroadcastStream, IProvider,
|
||||
if (event instanceof IRTMPEvent) {
|
||||
IRTMPEvent rtmpEvent = (IRTMPEvent) event;
|
||||
if (livePipe != null) {
|
||||
RTMPMessage msg = RTMPMessage.build(rtmpEvent);
|
||||
RTMPMessage msg = RTMPMessage.build(rtmpEvent, Constants.SOURCE_TYPE_LIVE);
|
||||
|
||||
if (creationTime == null)
|
||||
creationTime = (long)rtmpEvent.getTimestamp();
|
||||
@ -199,7 +200,7 @@ public class ScreenVideoBroadcastStream implements IBroadcastStream, IProvider,
|
||||
streamCodecInfo.setHasVideo(true);
|
||||
streamCodecInfo.setVideoCodec(videoStreamCodec);
|
||||
videoStreamCodec.reset();
|
||||
videoStreamCodec.addData(((VideoData) rtmpEvent).getData());
|
||||
videoStreamCodec.addData(((VideoData) rtmpEvent).getData());
|
||||
livePipe.pushMessage(msg);
|
||||
|
||||
// Notify listeners about received packet
|
||||
|
@ -44,10 +44,12 @@ class SessionSVC(sessionManager:SessionManagerSVC, room: String, screenDim: Dime
|
||||
private var stop = true
|
||||
private var mouseLoc:Point = new Point(100,100)
|
||||
private var pendingGenKeyFrameRequest = false
|
||||
private var timestamp = 0L;
|
||||
private var lastUserKeyFrameRequest = 0L
|
||||
private var sentInitialKeyFrame = false;
|
||||
|
||||
private var lastKeyFrameSentOn = 0L
|
||||
private var streamStartedOn = 0L
|
||||
private var streamStarted = false
|
||||
|
||||
/*
|
||||
* Schedule to generate a key frame after 30seconds of a request.
|
||||
* This prevents us from generating unnecessary key frames when
|
||||
@ -64,13 +66,23 @@ class SessionSVC(sessionManager:SessionManagerSVC, room: String, screenDim: Dime
|
||||
}
|
||||
}
|
||||
|
||||
def scheduleGenerateFrame() {
|
||||
val mainActor = self
|
||||
actor {
|
||||
Thread.sleep(interframeInterval)
|
||||
mainActor ! "GenerateFrame"
|
||||
}
|
||||
}
|
||||
def scheduleGenerateFrame() {
|
||||
val mainActor = self
|
||||
actor {
|
||||
Thread.sleep(interframeInterval)
|
||||
val now = System.currentTimeMillis()
|
||||
if ((now - lastKeyFrameSentOn) > 60000) {
|
||||
// Generate a key frame every 1 minute. The reason is that if
|
||||
// packets are dropped for a user with slow connection, packets
|
||||
// will continue to be dropped for that user until a key frame
|
||||
// is sent. (ralam july 15, 2015)
|
||||
mainActor ! "GenerateAKeyFrame"
|
||||
} else {
|
||||
mainActor ! "GenerateFrame"
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
def act() = {
|
||||
loop {
|
||||
@ -87,20 +99,20 @@ class SessionSVC(sessionManager:SessionManagerSVC, room: String, screenDim: Dime
|
||||
}
|
||||
}
|
||||
case GenerateKeyFrame => {
|
||||
val now = System.currentTimeMillis()
|
||||
// Wait 30sec between keyframe request from the users. This prevents
|
||||
// creating many keyframes when users join the session close to one
|
||||
// another.
|
||||
if (now - lastUserKeyFrameRequest > 30000) {
|
||||
lastUserKeyFrameRequest = now
|
||||
scheduleGenerateKeyFrame(keyFrameInterval)
|
||||
}
|
||||
|
||||
// do not generate a key frame every time a user joins as we
|
||||
// generate key frames regularly now.
|
||||
//scheduleGenerateKeyFrame(keyFrameInterval)
|
||||
}
|
||||
case "GenerateAKeyFrame" => {
|
||||
pendingGenKeyFrameRequest = false
|
||||
log.debug("Session: Generating Key Frame for room %s", room)
|
||||
generateFrame(true)
|
||||
pendingGenKeyFrameRequest = false
|
||||
log.debug("Session: Generating Key Frame for room %s", room)
|
||||
generateFrame(true)
|
||||
lastKeyFrameSentOn = System.currentTimeMillis()
|
||||
if (!stop) {
|
||||
scheduleGenerateFrame()
|
||||
} else {
|
||||
exit()
|
||||
}
|
||||
}
|
||||
case b: UpdateSessionBlock => updateBlock(b.position, b.blockData, b.keyframe, b.seqNum)
|
||||
case m: Any => log.warning("Session: Unknown message [%s]", m)
|
||||
@ -153,8 +165,15 @@ class SessionSVC(sessionManager:SessionManagerSVC, room: String, screenDim: Dime
|
||||
sessionManager ! new RemoveSession(room)
|
||||
} else {
|
||||
if (blockManager != null) {
|
||||
timestamp += 50;
|
||||
stream ! new UpdateStream(room, blockManager.generateFrame(keyframe), timestamp)
|
||||
|
||||
val now = System.currentTimeMillis()
|
||||
if (!streamStarted) {
|
||||
streamStarted = true
|
||||
streamStartedOn = now
|
||||
}
|
||||
|
||||
val ts = now - streamStartedOn
|
||||
stream ! new UpdateStream(room, blockManager.generateFrame(keyframe), ts)
|
||||
stream ! new UpdateStreamMouseLocation(room, mouseLoc)
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user