mirror of
https://github.com/gyurix1968/guacamole-client.git
synced 2025-09-06 13:17:41 +00:00
GUACAMOLE-462: Continue playback only after keyframe import.
If this is not done, asynchronous decoding of the keyframe via text() may complete AFTER replay continues, effectively ignoring the keyframe, leaving currentFrame untouched, and unnecessarily replaying instructions.
This commit is contained in:
@@ -577,11 +577,12 @@ Guacamole.SessionRecording = function SessionRecording(source) {
|
|||||||
* @param {function} callback
|
* @param {function} callback
|
||||||
* The callback to invoke once the seek operation has completed.
|
* The callback to invoke once the seek operation has completed.
|
||||||
*
|
*
|
||||||
* @param {number} [delay=0]
|
* @param {number} [nextRealTimestamp]
|
||||||
* The number of milliseconds that the seek operation should be
|
* The timestamp of the point in time that the given frame should be
|
||||||
* scheduled to take.
|
* displayed, as would be returned by new Date().getTime(). If omitted,
|
||||||
|
* the frame will be displayed as soon as possible.
|
||||||
*/
|
*/
|
||||||
var seekToFrame = function seekToFrame(index, callback, delay) {
|
var seekToFrame = function seekToFrame(index, callback, nextRealTimestamp) {
|
||||||
|
|
||||||
// Abort any in-progress seek
|
// Abort any in-progress seek
|
||||||
abortSeek();
|
abortSeek();
|
||||||
@@ -591,35 +592,7 @@ Guacamole.SessionRecording = function SessionRecording(source) {
|
|||||||
aborted : false
|
aborted : false
|
||||||
};
|
};
|
||||||
|
|
||||||
var startIndex;
|
var startIndex = index;
|
||||||
|
|
||||||
// Back up until startIndex represents current state
|
|
||||||
for (startIndex = index; startIndex >= 0; startIndex--) {
|
|
||||||
|
|
||||||
var frame = frames[startIndex];
|
|
||||||
|
|
||||||
// If we've reached the current frame, startIndex represents
|
|
||||||
// current state by definition
|
|
||||||
if (startIndex === currentFrame)
|
|
||||||
break;
|
|
||||||
|
|
||||||
// If frame has associated absolute state, make that frame the
|
|
||||||
// current state
|
|
||||||
if (frame.clientState) {
|
|
||||||
frame.clientState.text().then(function textReady(text) {
|
|
||||||
|
|
||||||
// Cancel seek if aborted
|
|
||||||
if (thisSeek.aborted)
|
|
||||||
return;
|
|
||||||
|
|
||||||
playbackClient.importState(JSON.parse(text));
|
|
||||||
currentFrame = startIndex;
|
|
||||||
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// Replay any applicable incremental frames
|
// Replay any applicable incremental frames
|
||||||
var continueReplay = function continueReplay() {
|
var continueReplay = function continueReplay() {
|
||||||
@@ -646,10 +619,38 @@ Guacamole.SessionRecording = function SessionRecording(source) {
|
|||||||
|
|
||||||
// Continue replay after requested delay has elapsed, or
|
// Continue replay after requested delay has elapsed, or
|
||||||
// immediately if no delay was requested
|
// immediately if no delay was requested
|
||||||
|
var continueAfterRequiredDelay = function continueAfterRequiredDelay() {
|
||||||
|
var delay = nextRealTimestamp ? Math.max(nextRealTimestamp - new Date().getTime(), 0) : 0;
|
||||||
if (delay)
|
if (delay)
|
||||||
window.setTimeout(continueReplay, delay);
|
window.setTimeout(continueReplay, delay);
|
||||||
else
|
else
|
||||||
continueReplay();
|
continueReplay();
|
||||||
|
};
|
||||||
|
|
||||||
|
// Back up until startIndex represents current state
|
||||||
|
for (; startIndex >= 0; startIndex--) {
|
||||||
|
|
||||||
|
var frame = frames[startIndex];
|
||||||
|
|
||||||
|
// If we've reached the current frame, startIndex represents
|
||||||
|
// current state by definition
|
||||||
|
if (startIndex === currentFrame)
|
||||||
|
break;
|
||||||
|
|
||||||
|
// If frame has associated absolute state, make that frame the
|
||||||
|
// current state
|
||||||
|
if (frame.clientState) {
|
||||||
|
frame.clientState.text().then(function textReady(text) {
|
||||||
|
playbackClient.importState(JSON.parse(text));
|
||||||
|
currentFrame = startIndex;
|
||||||
|
continueAfterRequiredDelay();
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
continueAfterRequiredDelay();
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -685,14 +686,10 @@ Guacamole.SessionRecording = function SessionRecording(source) {
|
|||||||
// frame begins
|
// frame begins
|
||||||
var nextRealTimestamp = next.timestamp - startVideoTimestamp + startRealTimestamp;
|
var nextRealTimestamp = next.timestamp - startVideoTimestamp + startRealTimestamp;
|
||||||
|
|
||||||
// Calculate the relative delay between the current time and
|
|
||||||
// the next frame start
|
|
||||||
var delay = Math.max(nextRealTimestamp - new Date().getTime(), 0);
|
|
||||||
|
|
||||||
// Advance to next frame after enough time has elapsed
|
// Advance to next frame after enough time has elapsed
|
||||||
seekToFrame(currentFrame + 1, function frameDelayElapsed() {
|
seekToFrame(currentFrame + 1, function frameDelayElapsed() {
|
||||||
continuePlayback();
|
continuePlayback();
|
||||||
}, delay);
|
}, nextRealTimestamp);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user