Skip to content

Commit

Permalink
Update gap controller to observe buffer gaps regardless of max buffer…
Browse files Browse the repository at this point in the history
… hole
  • Loading branch information
Rob Walch committed Dec 3, 2019
1 parent 2cfbe31 commit 189655b
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 25 deletions.
12 changes: 6 additions & 6 deletions src/controller/gap-controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import Event from '../events';
import { logger } from '../utils/logger';

export const STALL_MINIMUM_DURATION_MS = 250;
export const JUMP_THRESHOLD_SECONDS = 0.5; // tolerance needed as some browsers stalls playback before reaching buffered range end
export const MAX_START_GAP_JUMP = 2.0;
export const SKIP_BUFFER_HOLE_STEP_SECONDS = 0.1;
export const SKIP_BUFFER_RANGE_START = 0.05;
Expand Down Expand Up @@ -61,7 +60,7 @@ export default class GapController {
return;
}

const bufferInfo = BufferHelper.bufferInfo(media, currentTime, config.maxBufferHole);
const bufferInfo = BufferHelper.bufferInfo(media, currentTime, 0);
const isBuffered = bufferInfo.len > 0;

// There is no playable buffer (waiting for buffer append)
Expand Down Expand Up @@ -102,7 +101,8 @@ export default class GapController {
this._reportStall(bufferInfo.len);
}

this._tryFixBufferStall(bufferInfo, stalledDuration);
const bufferedWithHoles = BufferHelper.bufferInfo(media, currentTime, config.maxBufferHole);
this._tryFixBufferStall(bufferedWithHoles, stalledDuration);
}

/**
Expand Down Expand Up @@ -131,7 +131,7 @@ export default class GapController {
// we may just have to "nudge" the playlist as the browser decoding/rendering engine
// needs to cross some sort of threshold covering all source-buffers content
// to start playing properly.
if (bufferInfo.len > JUMP_THRESHOLD_SECONDS &&
if (bufferInfo.len > config.maxBufferHole &&
stalledDurationMs > config.highBufferWatchdogPeriod * 1000) {
logger.warn('Trying to nudge playhead over buffer-hole');
// Try to nudge currentTime over a buffer hole if we've been stalling for the configured amount of seconds
Expand Down Expand Up @@ -168,13 +168,13 @@ export default class GapController {
* @private
*/
_trySkipBufferHole (partial) {
const { hls, media } = this;
const { config, hls, media } = this;
const currentTime = media.currentTime;
let lastEndTime = 0;
// Check if currentTime is between unbuffered regions of partial fragments
for (let i = 0; i < media.buffered.length; i++) {
const startTime = media.buffered.start(i);
if (currentTime + JUMP_THRESHOLD_SECONDS >= lastEndTime && currentTime < startTime) {
if (currentTime + config.maxBufferHole >= lastEndTime && currentTime < startTime) {
const targetTime = Math.max(startTime + SKIP_BUFFER_RANGE_START, media.currentTime + SKIP_BUFFER_HOLE_STEP_SECONDS);
logger.warn(`skipping hole, adjusting currentTime from ${currentTime} to ${targetTime}`);
this.moved = true;
Expand Down
42 changes: 23 additions & 19 deletions src/utils/buffer-helper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,30 +92,34 @@ export class BufferHelper {
});

let buffered2: BufferTimeRange[] = [];
// there might be some small holes between buffer time range
// consider that holes smaller than maxHoleDuration are irrelevant and build another
// buffer time range representations that discards those holes
for (let i = 0; i < buffered.length; i++) {
let buf2len = buffered2.length;
if (buf2len) {
let buf2end = buffered2[buf2len - 1].end;
// if small hole (value between 0 or maxHoleDuration ) or overlapping (negative)
if ((buffered[i].start - buf2end) < maxHoleDuration) {
// merge overlapping time ranges
// update lastRange.end only if smaller than item.end
// e.g. [ 1, 15] with [ 2,8] => [ 1,15] (no need to modify lastRange.end)
// whereas [ 1, 8] with [ 2,15] => [ 1,15] ( lastRange should switch from [1,8] to [1,15])
if (buffered[i].end > buf2end) {
buffered2[buf2len - 1].end = buffered[i].end;
if (maxHoleDuration) {
// there might be some small holes between buffer time range
// consider that holes smaller than maxHoleDuration are irrelevant and build another
// buffer time range representations that discards those holes
for (let i = 0; i < buffered.length; i++) {
let buf2len = buffered2.length;
if (buf2len) {
let buf2end = buffered2[buf2len - 1].end;
// if small hole (value between 0 or maxHoleDuration ) or overlapping (negative)
if ((buffered[i].start - buf2end) < maxHoleDuration) {
// merge overlapping time ranges
// update lastRange.end only if smaller than item.end
// e.g. [ 1, 15] with [ 2,8] => [ 1,15] (no need to modify lastRange.end)
// whereas [ 1, 8] with [ 2,15] => [ 1,15] ( lastRange should switch from [1,8] to [1,15])
if (buffered[i].end > buf2end) {
buffered2[buf2len - 1].end = buffered[i].end;
}
} else {
// big hole
buffered2.push(buffered[i]);
}
} else {
// big hole
// first value
buffered2.push(buffered[i]);
}
} else {
// first value
buffered2.push(buffered[i]);
}
} else {
buffered2 = buffered;
}

let bufferLen = 0;
Expand Down

0 comments on commit 189655b

Please sign in to comment.