Skip to content

Commit

Permalink
WPE fix: Avoid pruning buffered ranges already enqueued for playback
Browse files Browse the repository at this point in the history
In WPE WebKit, the buffered range of the currentTime has high chances to
have been internally enqueued for playback (an action that can't be
undone, there's no way to unenqueue other than flushing the whole playback
pipeline). If that range is pruned, an internal flush is triggered, but
in order to keep playing from the currentTime onwards, the needed samples
must be enqueued again at least since the previous sync sample. This
can cause a lot of stress to the video decoder and generate stuttering.

This patch solves the problem by avoiding pruning (deleting) ranges
belonging to the same buffered range where the currentTime (or seek
target) is.

This behaviour is protected by the streaming.buffer.enableCurrentTimeRangePruning
setting, which is enabled by default and triggers the new behaviour when
disabled on purpose by the webpage embedding dash.js.
  • Loading branch information
eocanha committed Sep 15, 2022
1 parent 931ddf6 commit a47975e
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 2 deletions.
10 changes: 8 additions & 2 deletions src/core/Settings.js
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,8 @@ import Events from './events/Events';
* longFormContentDurationThreshold: 600,
* stallThreshold: 0.5,
* useAppendWindow: true,
* setStallState: true
* setStallState: true,
* enableCurrentTimeRangePruning: true
* },
* gaps: {
* jumpGaps: true,
Expand Down Expand Up @@ -304,6 +305,10 @@ import Events from './events/Events';
* Specifies if the appendWindow attributes of the MSE SourceBuffers should be set according to content duration from manifest.
* @property {boolean} [setStallState=true]
* Specifies if we fire manual waiting events once the stall threshold is reached
* @property {boolean} [enableCurrentTimeRangePruning=true]
* Enables pruning of the current blayback time buffered range.
*
* The pruning of a buffered range that contains the current playback time (so it's likely to have been enqueued for playback) causes a flush and reenqueue in WPE and WebKitGTK based browsers. This stresses the video decoder and can cause stuttering on embedded platforms.
*/

/**
Expand Down Expand Up @@ -801,7 +806,8 @@ function Settings() {
longFormContentDurationThreshold: 600,
stallThreshold: 0.3,
useAppendWindow: true,
setStallState: true
setStallState: true,
enableCurrentTimeRangePruning: true
},
gaps: {
jumpGaps: true,
Expand Down
19 changes: 19 additions & 0 deletions src/streaming/controllers/BufferController.js
Original file line number Diff line number Diff line change
Expand Up @@ -559,6 +559,25 @@ function BufferController(config) {
if (currentTimeRequest) {
rangeStart = Math.max(currentTimeRequest.startTime + currentTimeRequest.duration, rangeStart);
}

// Never remove the contiguous range of targetTime in order to avoid flushes & reenqueues when the user doesn't want it
const enableCurrentTimeRangePruning = settings.get().streaming.buffer.enableCurrentTimeRangePruning;
if (!enableCurrentTimeRangePruning) {
for (let i = 0; i < ranges.length; i++) {
if (ranges.start(i) <= targetTime && targetTime <= ranges.end(i)
&& ranges.start(i) <= rangeStart && rangeStart <= ranges.end(i)) {
let oldRangeStart = rangeStart;
if (i + 1 < ranges.length) {
rangeStart = ranges.start(i+1);
} else {
rangeStart = ranges.end(i) + 1;
}
logger.debug('Buffered range [' + ranges.start(i) + ', ' + ranges.end(i) + '] overlaps with targetTime ' + targetTime + ' and range to be pruned [' + oldRangeStart + ', ' + endOfBuffer + '], using [' + rangeStart + ', ' + endOfBuffer +'] instead');
break;
}
}
}

if (rangeStart < endOfBuffer) {
return {
start: rangeStart,
Expand Down

0 comments on commit a47975e

Please sign in to comment.