Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: seeking live streams when missing mediaSource.setLiveSeekableRange #26

Merged
merged 8 commits into from
Jun 30, 2022
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
3 changes: 2 additions & 1 deletion index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,8 @@ declare namespace dashjs {
longFormContentDurationThreshold?: number,
stallThreshold?: number,
useAppendWindow?: boolean,
setStallState?: boolean
setStallState?: boolean,
enableLiveSeekableRangeFix?: boolean
},
gaps?: {
jumpGaps?: boolean,
Expand Down
2 changes: 1 addition & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "dashjs",
"version": "4.3.4",
"version": "4.3.5",
"description": "A reference client implementation for the playback of MPEG DASH via Javascript and compliant browsers.",
"author": "Dash Industry Forum",
"license": "BSD-3-Clause",
Expand Down
8 changes: 6 additions & 2 deletions src/core/Settings.js
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,8 @@ import {HTTPRequest} from '../streaming/vo/metrics/HTTPRequest';
* longFormContentDurationThreshold: 600,
* stallThreshold: 0.5,
* useAppendWindow: true,
* setStallState: false
* setStallState: false,
* enableLiveSeekableRangeFix: true
* },
* gaps: {
* jumpGaps: true,
Expand Down Expand Up @@ -301,6 +302,8 @@ import {HTTPRequest} from '../streaming/vo/metrics/HTTPRequest';
* Specifies if the appendWindow attributes of the MSE SourceBuffers should be set according to content duration from manifest.
* @property {boolean} [setStallState=false]
* Specifies if we fire manual waiting events once the stall threshold is reached
* @property {boolean} [enableLiveSeekableRangeFix=true]
* Sets `mediaSource.duration` when live seekable range changes if `mediaSource.setLiveSeekableRange` is unavailable.
*/

/**
Expand Down Expand Up @@ -801,7 +804,8 @@ function Settings() {
longFormContentDurationThreshold: 600,
stallThreshold: 0.3,
useAppendWindow: true,
setStallState: true
setStallState: true,
enableLiveSeekableRangeFix: true
},
gaps: {
jumpGaps: true,
Expand Down
38 changes: 33 additions & 5 deletions src/streaming/controllers/MediaSourceController.js
Original file line number Diff line number Diff line change
Expand Up @@ -70,27 +70,55 @@ function MediaSourceController() {
videoModel.setSource(null);
}

function setDuration(value) {
function setDuration(value, log = true) {
if (!mediaSource || mediaSource.readyState !== 'open') return;
if (value === null && isNaN(value)) return;
if (mediaSource.duration === value) return;

if (!isBufferUpdating(mediaSource)) {
logger.info('Set MediaSource duration:' + value);
if (log) {
logger.info('Set MediaSource duration:' + value);
}
mediaSource.duration = value;
} else {
setTimeout(setDuration.bind(null, value), 50);
}
}

function setSeekable(start, end) {
if (mediaSource && typeof mediaSource.setLiveSeekableRange === 'function' && typeof mediaSource.clearLiveSeekableRange === 'function' &&
mediaSource.readyState === 'open' && start >= 0 && start < end) {
function setSeekable(start, end, enableLiveSeekableRangeFix) {
if (!mediaSource || mediaSource.readyState !== 'open') return;
if (start < 0 || end <= start) return;

if (typeof mediaSource.setLiveSeekableRange === 'function' && typeof mediaSource.clearLiveSeekableRange === 'function') {
mediaSource.clearLiveSeekableRange();
mediaSource.setLiveSeekableRange(start, end);
} else if (enableLiveSeekableRangeFix) {
try {
const bufferedRangeEnd = getBufferedRangeEnd(mediaSource);
const targetMediaSourceDuration = Math.max(end, bufferedRangeEnd);
if (!isFinite(mediaSource.duration) || mediaSource.duration < targetMediaSourceDuration) {
setDuration(targetMediaSourceDuration, false);
}
} catch (e) {
logger.error(`Failed to set MediaSource duration! ` + e.toString());
}
}
}

function getBufferedRangeEnd(source) {
let max = 0;
const buffers = source.sourceBuffers;

for (let i = 0; i < buffers.length; i++) {
if (buffers[i].buffered.length > 0) {
const end = buffers[i].buffered.end(buffers[i].buffered.length - 1);
max = Math.max(end, max);
}
}

return max;
}

function signalEndOfStream(source) {
if (!source || source.readyState !== 'open') {
return;
Expand Down
8 changes: 6 additions & 2 deletions src/streaming/controllers/StreamController.js
Original file line number Diff line number Diff line change
Expand Up @@ -423,7 +423,7 @@ function StreamController() {

_setMediaDuration();
const dvrInfo = dashMetrics.getCurrentDVRInfo();
mediaSourceController.setSeekable(dvrInfo.range.start, dvrInfo.range.end);
mediaSourceController.setSeekable(dvrInfo.range.start, dvrInfo.range.end, _enableLiveSeekableRangeFix());
_activateStream(seekTime, keepBuffers);
}

Expand Down Expand Up @@ -611,6 +611,10 @@ function StreamController() {
}
}

function _enableLiveSeekableRangeFix() {
return settings.get().streaming.buffer.enableLiveSeekableRangeFix;
}

/**
* Initiate the preloading of the next stream
* @param {object} nextStream
Expand Down Expand Up @@ -1487,7 +1491,7 @@ function StreamController() {
//Should we normalize and union the two?
const targetMediaType = hasAudioTrack() ? Constants.AUDIO : Constants.VIDEO;
if (e.mediaType === targetMediaType) {
mediaSourceController.setSeekable(e.value.range.start, e.value.range.end);
mediaSourceController.setSeekable(e.value.range.start, e.value.range.end, _enableLiveSeekableRangeFix());
}
}
}
Expand Down