Skip to content
This repository has been archived by the owner on Jan 12, 2019. It is now read-only.

Seek to seekable start when before the seekable window #1260

Merged
merged 3 commits into from
Sep 20, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 28 additions & 14 deletions src/playback-watcher.js
Original file line number Diff line number Diff line change
Expand Up @@ -154,18 +154,32 @@ export default class PlaybackWatcher {
* @private
*/
fixesBadSeeks_() {
let seekable = this.seekable();
let currentTime = this.tech_.currentTime();
const seeking = this.tech_.seeking();
const seekable = this.seekable();
const currentTime = this.tech_.currentTime();
let seekTo;

if (this.tech_.seeking() &&
this.outsideOfSeekableWindow_(seekable, currentTime)) {
let seekableEnd = seekable.end(seekable.length - 1);
if (seeking && this.afterSeekableWindow_(seekable, currentTime)) {
const seekableEnd = seekable.end(seekable.length - 1);

// sync to live point (if VOD, our seekable was updated and we're simply adjusting)
seekTo = seekableEnd;
}

if (seeking && this.beforeSeekableWindow_(seekable, currentTime)) {
const seekableStart = seekable.start(0);

// sync to the beginning of the live window
// provide a buffer of .1 seconds to handle rounding/imprecise numbers
seekTo = seekableStart + 0.1;
}

if (typeof seekTo !== 'undefined') {
this.logger_(`Trying to seek outside of seekable at time ${currentTime} with ` +
`seekable range ${Ranges.printableRange(seekable)}. Seeking to ` +
`${seekableEnd}.`);
this.tech_.setCurrentTime(seekableEnd);
`seekable range ${Ranges.printableRange(seekable)}. Seeking to ` +
`${seekTo}.`);

this.tech_.setCurrentTime(seekTo);
return true;
}

Expand Down Expand Up @@ -231,7 +245,7 @@ export default class PlaybackWatcher {
return true;
}

if (this.fellOutOfLiveWindow_(seekable, currentTime)) {
if (this.beforeSeekableWindow_(seekable, currentTime)) {
let livePoint = seekable.end(seekable.length - 1);

this.logger_(`Fell out of live window at time ${currentTime}. Seeking to ` +
Expand Down Expand Up @@ -278,26 +292,26 @@ export default class PlaybackWatcher {
return false;
}

outsideOfSeekableWindow_(seekable, currentTime) {
afterSeekableWindow_(seekable, currentTime) {
if (!seekable.length) {
// we can't make a solid case if there's no seekable, default to false
return false;
}

// provide a buffer of .1 seconds to handle rounding/imprecise numbers
if (currentTime < seekable.start(0) - 0.1 ||
currentTime > seekable.end(seekable.length - 1) + 0.1) {
if (currentTime > seekable.end(seekable.length - 1) + 0.1) {
return true;
}

return false;
}

fellOutOfLiveWindow_(seekable, currentTime) {
beforeSeekableWindow_(seekable, currentTime) {
if (seekable.length &&
// can't fall before 0 and 0 seekable start identifies VOD stream
seekable.start(0) > 0 &&
currentTime < seekable.start(0)) {
// provide a buffer of .1 seconds to handle rounding/imprecise numbers
currentTime < seekable.start(0) - 0.1) {
return true;
}

Expand Down
56 changes: 28 additions & 28 deletions test/playback-watcher.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -458,14 +458,14 @@ QUnit.test('fixes bad seeks', function(assert) {
currentTime = 0;
assert.ok(playbackWatcher.fixesBadSeeks_(), 'acts when seek before seekable range');
assert.equal(seeks.length, 2, 'seeked');
assert.equal(seeks[1], 45, 'player seeked to live point');
assert.equal(seeks[1], 1.1, 'player seeked to start of the live window');

currentTime = 30;
assert.ok(!playbackWatcher.fixesBadSeeks_(), 'does nothing when time within range');
assert.equal(seeks.length, 2, 'did not seek');
});

QUnit.test('seeks to live point if we try to seek outside of seekable', function(assert) {
QUnit.test('corrects seek outside of seekable', function(assert) {
// set an arbitrary live source
this.player.src({
src: 'liveStart30sBefore.m3u8',
Expand Down Expand Up @@ -512,7 +512,7 @@ QUnit.test('seeks to live point if we try to seek outside of seekable', function
currentTime = 0;
this.player.tech_.trigger('waiting');
assert.equal(seeks.length, 2, 'seeked');
assert.equal(seeks[1], 45, 'player seeked to live point');
assert.equal(seeks[1], 1.1, 'player seeked to start of the live window');

// inside of seekable range
currentTime = 10;
Expand All @@ -538,7 +538,7 @@ QUnit.test('seeks to live point if we try to seek outside of seekable', function
currentTime = 0;
playbackWatcher.checkCurrentTime_();
assert.equal(seeks.length, 4, 'seeked');
assert.equal(seeks[3], 45, 'player seeked to live point');
assert.equal(seeks[3], 1.1, 'player seeked to live point');

currentTime = 10;
playbackWatcher.checkCurrentTime_();
Expand Down Expand Up @@ -651,66 +651,66 @@ QUnit.test('skips gap from video underflow', function(assert) {
});

QUnit.test('detects live window falloff', function(assert) {
let fellOutOfLiveWindow_ =
this.playbackWatcher.fellOutOfLiveWindow_.bind(this.playbackWatcher);
let beforeSeekableWindow_ =
this.playbackWatcher.beforeSeekableWindow_.bind(this.playbackWatcher);

assert.ok(
fellOutOfLiveWindow_(videojs.createTimeRanges([[11, 20]]), 10),
beforeSeekableWindow_(videojs.createTimeRanges([[11, 20]]), 10),
'true if playlist live and current time before seekable');

assert.ok(
!fellOutOfLiveWindow_(videojs.createTimeRanges([]), 10),
!beforeSeekableWindow_(videojs.createTimeRanges([]), 10),
'false if no seekable range');
assert.ok(
!fellOutOfLiveWindow_(videojs.createTimeRanges([[0, 10]]), -1),
!beforeSeekableWindow_(videojs.createTimeRanges([[0, 10]]), -1),
'false if seekable range starts at 0');
assert.ok(
!fellOutOfLiveWindow_(videojs.createTimeRanges([[11, 20]]), 11),
!beforeSeekableWindow_(videojs.createTimeRanges([[11, 20]]), 11),
'false if current time at seekable start');
assert.ok(
!fellOutOfLiveWindow_(videojs.createTimeRanges([[11, 20]]), 20),
!beforeSeekableWindow_(videojs.createTimeRanges([[11, 20]]), 20),
'false if current time at seekable end');
assert.ok(
!fellOutOfLiveWindow_(videojs.createTimeRanges([[11, 20]]), 15),
!beforeSeekableWindow_(videojs.createTimeRanges([[11, 20]]), 15),
'false if current time within seekable range');
assert.ok(
!fellOutOfLiveWindow_(videojs.createTimeRanges([[11, 20]]), 21),
!beforeSeekableWindow_(videojs.createTimeRanges([[11, 20]]), 21),
'false if current time past seekable range');
assert.ok(
fellOutOfLiveWindow_(videojs.createTimeRanges([[11, 20]]), 0),
beforeSeekableWindow_(videojs.createTimeRanges([[11, 20]]), 0),
'true if current time is 0 and earlier than seekable range');
});

QUnit.test('detects outside of seekable window', function(assert) {
let outsideOfSeekableWindow =
this.playbackWatcher.outsideOfSeekableWindow_.bind(this.playbackWatcher);
QUnit.test('detects beyond seekable window', function(assert) {
let afterSeekableWindow_ =
this.playbackWatcher.afterSeekableWindow_.bind(this.playbackWatcher);

assert.ok(
outsideOfSeekableWindow(videojs.createTimeRanges([[11, 20]]), 10.8),
'true if before seekable range');
!afterSeekableWindow_(videojs.createTimeRanges([[11, 20]]), 10.8),
'false if before seekable range');
assert.ok(
outsideOfSeekableWindow(videojs.createTimeRanges([[11, 20]]), 20.2),
afterSeekableWindow_(videojs.createTimeRanges([[11, 20]]), 20.2),
'true if after seekable range');
assert.ok(
!outsideOfSeekableWindow(videojs.createTimeRanges([[11, 20]]), 10.9),
!afterSeekableWindow_(videojs.createTimeRanges([[11, 20]]), 10.9),
'false if within starting seekable range buffer');
assert.ok(
!outsideOfSeekableWindow(videojs.createTimeRanges([[11, 20]]), 20.1),
!afterSeekableWindow_(videojs.createTimeRanges([[11, 20]]), 20.1),
'false if within ending seekable range buffer');

assert.ok(
!outsideOfSeekableWindow(videojs.createTimeRanges(), 10),
!afterSeekableWindow_(videojs.createTimeRanges(), 10),
'false if no seekable range');
assert.ok(
outsideOfSeekableWindow(videojs.createTimeRanges([[0, 10]]), -0.2),
'true even if current time is negative');
!afterSeekableWindow_(videojs.createTimeRanges([[0, 10]]), -0.2),
'false if current time is negative');
assert.ok(
!outsideOfSeekableWindow(videojs.createTimeRanges([[0, 10]]), 5),
!afterSeekableWindow_(videojs.createTimeRanges([[0, 10]]), 5),
'false if within seekable range');
assert.ok(
!outsideOfSeekableWindow(videojs.createTimeRanges([[0, 10]]), 0),
!afterSeekableWindow_(videojs.createTimeRanges([[0, 10]]), 0),
'false if within seekable range');
assert.ok(
!outsideOfSeekableWindow(videojs.createTimeRanges([[0, 10]]), 10),
!afterSeekableWindow_(videojs.createTimeRanges([[0, 10]]), 10),
'false if within seekable range');
});