Skip to content

Commit f288ab0

Browse files
Add Low Latency Stall Threshold (Dash-Industry-Forum#4689)
* Update checkIfSufficientBuffer logic * Add lowLatencyStallThreshold to settings * Add stall threshold options to reference player * Removed duplication
1 parent 621c54e commit f288ab0

File tree

5 files changed

+66
-10
lines changed

5 files changed

+66
-10
lines changed

index.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1685,6 +1685,7 @@ declare namespace dashjs {
16851685
bufferTimeDefault?: number,
16861686
longFormContentDurationThreshold?: number,
16871687
stallThreshold?: number,
1688+
lowLatencyStallThreshold?: number,
16881689
useAppendWindow?: boolean,
16891690
setStallState?: boolean
16901691
avoidCurrentTimeRangePruning?: boolean

samples/dash-if-reference-player/app/main.js

Lines changed: 42 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -332,6 +332,9 @@ app.controller('DashController', ['$scope', '$window', 'sources', 'contributors'
332332
$scope.cmcdMode = 'query';
333333
$scope.cmcdAllKeys = ['br', 'd', 'ot', 'tb', 'bl', 'dl', 'mtp', 'nor', 'nrr', 'su', 'bs', 'rtp', 'cid', 'pr', 'sf', 'sid', 'st', 'v']
334334

335+
$scope.stallThreshold = 0.3;
336+
$scope.lowLatencyStallThreshold = 0.3;
337+
335338
// Persistent license
336339
$scope.persistentSessionId = {};
337340
$scope.selectedKeySystem = null;
@@ -778,6 +781,26 @@ app.controller('DashController', ['$scope', '$window', 'sources', 'contributors'
778781
});
779782
};
780783

784+
$scope.updateStallThreshold = function () {
785+
$scope.player.updateSettings({
786+
streaming: {
787+
buffer: {
788+
stallThreshold: parseFloat($scope.stallThreshold)
789+
}
790+
}
791+
});
792+
}
793+
794+
$scope.updateLowLatencyStallThreshold = function () {
795+
$scope.player.updateSettings({
796+
streaming: {
797+
buffer: {
798+
lowLatencyStallThreshold: parseFloat($scope.lowLatencyStallThreshold)
799+
}
800+
}
801+
});
802+
}
803+
781804
$scope.updateInitialRoleVideo = function () {
782805
$scope.player.setInitialMediaSettingsFor('video', {
783806
role: $scope.initialSettings.video
@@ -813,7 +836,7 @@ app.controller('DashController', ['$scope', '$window', 'sources', 'contributors'
813836

814837
$scope._backconvertRoleScheme = function (setting) {
815838
var scheme = 'off';
816-
839+
817840
if (setting) {
818841
scheme = undefined;
819842
switch (setting.schemeIdUri) {
@@ -1136,6 +1159,16 @@ app.controller('DashController', ['$scope', '$window', 'sources', 'contributors'
11361159
config.streaming.abr.maxBitrate = { 'video': maxBitrate };
11371160
}
11381161

1162+
const stallThreshold = parseFloat($scope.stallThreshold);
1163+
if (!isNaN(stallThreshold)) {
1164+
config.streaming.buffer.stallThreshold = stallThreshold;
1165+
}
1166+
1167+
const lowLatencyStallThreshold = parseFloat($scope.lowLatencyStallThreshold);
1168+
if (!isNaN(lowLatencyStallThreshold)) {
1169+
config.streaming.buffer.lowLatencyStallThreshold = lowLatencyStallThreshold;
1170+
}
1171+
11391172
config.streaming.cmcd.sid = $scope.cmcdSessionId ? $scope.cmcdSessionId : null;
11401173
config.streaming.cmcd.cid = $scope.cmcdContentId ? $scope.cmcdContentId : null;
11411174
config.streaming.cmcd.rtp = $scope.cmcdRtp ? $scope.cmcdRtp : null;
@@ -1935,7 +1968,7 @@ app.controller('DashController', ['$scope', '$window', 'sources', 'contributors'
19351968
if (scheme === 'off') {
19361969
delete settings.accessibility;
19371970
} else {
1938-
Object.assign(settings, {accessibility: $scope._genSettingsAudioAccessibility(scheme, $scope.initialSettings.audioAccessibility)} );
1971+
Object.assign(settings, { accessibility: $scope._genSettingsAudioAccessibility(scheme, $scope.initialSettings.audioAccessibility) });
19391972
}
19401973
$scope.player.setInitialMediaSettingsFor('audio', settings);
19411974
break;
@@ -2308,6 +2341,12 @@ app.controller('DashController', ['$scope', '$window', 'sources', 'contributors'
23082341
$scope.useSuggestedPresentationDelay = currentConfig.streaming.delay.useSuggestedPresentationDelay;
23092342
}
23102343

2344+
function setStallThresholdOptions() {
2345+
var currentConfig = $scope.player.getSettings();
2346+
$scope.stallThreshold = currentConfig.streaming.buffer.stallThreshold;
2347+
$scope.lowLatencyStallThreshold = currentConfig.streaming.buffer.lowLatencyStallThreshold;
2348+
}
2349+
23112350
function setInitialSettings() {
23122351
var currentConfig = $scope.player.getSettings();
23132352
if (currentConfig.streaming.abr.initialBitrate.video !== -1) {
@@ -2468,6 +2507,7 @@ app.controller('DashController', ['$scope', '$window', 'sources', 'contributors'
24682507
setDrmOptions();
24692508
setTextOptions();
24702509
setLiveDelayOptions();
2510+
setStallThresholdOptions()
24712511
setInitialSettings();
24722512
setTrackSwitchModeSettings();
24732513
setInitialLogLevel();

samples/dash-if-reference-player/index.html

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -673,6 +673,19 @@
673673
</div>
674674
</div>
675675
</div>
676+
<div class="options-item">
677+
<div class="options-item-title">Buffer</div>
678+
<div class="options-item-body">
679+
<div class="sub-options-item-body">
680+
<label class="options-label">Stall Threshold:</label>
681+
<input type="text" class="form-control" placeholder="value in seconds" ng-model="stallThreshold"
682+
ng-change="updateStallThreshold()">
683+
<label class="options-label">Low Latency Stall Threshold:</label>
684+
<input type="text" class="form-control" placeholder="value in seconds" ng-model="lowLatencyStallThreshold"
685+
ng-change="updateLowLatencyStallThreshold()">
686+
</div>
687+
</div>
688+
</div>
676689
<div class="options-item">
677690
<div class="options-item-title">Initial Settings</div>
678691
<div class="options-item-body">

src/core/Settings.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,7 @@ import Events from './events/Events.js';
120120
* bufferTimeDefault: 18,
121121
* longFormContentDurationThreshold: 600,
122122
* stallThreshold: 0.3,
123+
* lowLatencyStallThreshold: 0.3,
123124
* useAppendWindow: true,
124125
* setStallState: true,
125126
* avoidCurrentTimeRangePruning: false,
@@ -429,6 +430,8 @@ import Events from './events/Events.js';
429430
* Initial buffer level before playback starts
430431
* @property {number} [stallThreshold=0.3]
431432
* Stall threshold used in BufferController.js to determine whether a track should still be changed and which buffer range to prune.
433+
* @property {number} [lowLatencyStallThreshold=0.3]
434+
* Low Latency stall threshold used in BufferController.js to determine whether a track should still be changed and which buffer range to prune.
432435
* @property {boolean} [useAppendWindow=true]
433436
* Specifies if the appendWindow attributes of the MSE SourceBuffers should be set according to content duration from manifest.
434437
* @property {boolean} [setStallState=true]
@@ -1147,6 +1150,7 @@ function Settings() {
11471150
bufferTimeDefault: 18,
11481151
longFormContentDurationThreshold: 600,
11491152
stallThreshold: 0.3,
1153+
lowLatencyStallThreshold: 0.3,
11501154
useAppendWindow: true,
11511155
setStallState: true,
11521156
avoidCurrentTimeRangePruning: false,

src/streaming/controllers/BufferController.js

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -894,15 +894,13 @@ function BufferController(config) {
894894
return;
895895
}
896896

897-
// When the player is working in low latency mode, the buffer is often below STALL_THRESHOLD.
898-
// So, when in low latency mode, change dash.js behavior so it notifies a stall just when
899-
// buffer reach 0 seconds
900-
if (((!playbackController.getLowLatencyModeEnabled() && bufferLevel < settings.get().streaming.buffer.stallThreshold) || bufferLevel === 0) && !isBufferingCompleted) {
897+
//Set stall threshold based on player mode
898+
const stallThreshold = playbackController.getLowLatencyModeEnabled() ? settings.get().streaming.buffer.lowLatencyStallThreshold : settings.get().streaming.buffer.stallThreshold;
899+
900+
if ((bufferLevel <= stallThreshold) && !isBufferingCompleted) {
901901
_notifyBufferStateChanged(MetricsConstants.BUFFER_EMPTY);
902-
} else {
903-
if (isBufferingCompleted || bufferLevel >= settings.get().streaming.buffer.stallThreshold || (playbackController.getLowLatencyModeEnabled() && bufferLevel > 0)) {
904-
_notifyBufferStateChanged(MetricsConstants.BUFFER_LOADED);
905-
}
902+
} else if (isBufferingCompleted || bufferLevel > stallThreshold) {
903+
_notifyBufferStateChanged(MetricsConstants.BUFFER_LOADED);
906904
}
907905
}
908906

0 commit comments

Comments
 (0)