Skip to content

Commit

Permalink
Refactor the InsufficientBufferRule.js and allow parameter configurat…
Browse files Browse the repository at this point in the history
…ion via Settings.js (#4373)
  • Loading branch information
dsilhavy authored Jan 27, 2024
1 parent 19ddc54 commit 015d0ff
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 14 deletions.
6 changes: 5 additions & 1 deletion src/core/Settings.js
Original file line number Diff line number Diff line change
Expand Up @@ -1041,7 +1041,11 @@ function Settings() {
active: true
},
insufficientBufferRule: {
active: true
active: true,
parameters: {
throughputSafetyFactor: 0.7,
segmentIgnoreCount: 2
}
},
switchHistoryRule: {
active: true
Expand Down
31 changes: 18 additions & 13 deletions src/streaming/rules/abr/InsufficientBufferRule.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,16 +36,16 @@ import SwitchRequest from '../SwitchRequest.js';
import Constants from '../../constants/Constants.js';
import MetricsConstants from '../../constants/MetricsConstants.js';
import MediaPlayerEvents from '../../MediaPlayerEvents.js';
import Settings from '../../../core/Settings.js';

function InsufficientBufferRule(config) {

config = config || {};
const INSUFFICIENT_BUFFER_SAFETY_FACTOR = 0.5;
const SEGMENT_IGNORE_COUNT = 2;

const context = this.context;
const eventBus = EventBus(context).getInstance();
const dashMetrics = config.dashMetrics;
const settings = Settings(context).getInstance();

let instance,
logger,
Expand Down Expand Up @@ -83,10 +83,7 @@ function InsufficientBufferRule(config) {
const scheduleController = rulesContext.getScheduleController();
const playbackController = scheduleController.getPlaybackController();


// Don't ask for a bitrate change if there is no info about buffer state or if fragmentDuration is not defined
const lowLatencyEnabled = playbackController.getLowLatencyModeEnabled();
if (_shouldIgnore(lowLatencyEnabled, mediaType) || !fragmentDuration) {
if (!_shouldExecuteRule(playbackController, mediaType, fragmentDuration)) {
return switchRequest;
}

Expand All @@ -95,28 +92,36 @@ function InsufficientBufferRule(config) {
if (currentBufferState && currentBufferState.state === MetricsConstants.BUFFER_EMPTY) {
logger.debug('[' + mediaType + '] Switch to index 0; buffer is empty.');
switchRequest.representation = abrController.getOptimalRepresentationForBitrate(mediaInfo, 0, true);
switchRequest.reason = 'InsufficientBufferRule: Buffer is empty';
switchRequest.reason = {
message: '[InsufficientBufferRule]: Switching to lowest Representation because buffer is empty'
};
} else {
const throughputController = rulesContext.getThroughputController();
const bufferLevel = dashMetrics.getCurrentBufferLevel(mediaType);
const throughput = throughputController.getAverageThroughput(mediaType, null, NaN);
const bitrate = throughput * (bufferLevel / fragmentDuration) * INSUFFICIENT_BUFFER_SAFETY_FACTOR;
const safeThroughput = throughput * settings.get().streaming.abr.rules.insufficientBufferRule.parameters.throughputSafetyFactor;
const bitrate = safeThroughput * bufferLevel / fragmentDuration

switchRequest.representation = abrController.getOptimalRepresentationForBitrate(mediaInfo, bitrate, true);
switchRequest.reason = 'InsufficientBufferRule: being conservative to avoid immediate rebuffering';
switchRequest.reason = {
message: '[InsufficientBufferRule]: Limiting maximum bitrate to avoid a buffer underrun.',
bitrate
};
}

return switchRequest;
}

function _shouldIgnore(lowLatencyEnabled, mediaType) {
return !lowLatencyEnabled && bufferStateDict[mediaType].ignoreCount > 0;
function _shouldExecuteRule(playbackController, mediaType, fragmentDuration) {
const lowLatencyEnabled = playbackController.getLowLatencyModeEnabled();
return !lowLatencyEnabled && bufferStateDict[mediaType].ignoreCount <= 0 && fragmentDuration;
}

function _resetInitialSettings() {
const segmentIgnoreCount = settings.get().streaming.abr.rules.insufficientBufferRule.parameters.segmentIgnoreCount
bufferStateDict = {};
bufferStateDict[Constants.VIDEO] = { ignoreCount: SEGMENT_IGNORE_COUNT };
bufferStateDict[Constants.AUDIO] = { ignoreCount: SEGMENT_IGNORE_COUNT };
bufferStateDict[Constants.VIDEO] = { ignoreCount: segmentIgnoreCount };
bufferStateDict[Constants.AUDIO] = { ignoreCount: segmentIgnoreCount };
}

function _onPlaybackSeeking() {
Expand Down

0 comments on commit 015d0ff

Please sign in to comment.