in src/videodownlinkbandwidthpolicy/VideoPriorityBasedPolicy.ts [284:420]
protected calculateOptimalReceiveStreams(): void {
const chosenStreams: VideoStreamDescription[] = [];
const remoteInfos: VideoStreamDescription[] = this.videoIndex.remoteStreamDescriptions();
if (remoteInfos.length === 0 || this.videoPreferences?.isEmpty()) {
this.optimalReceiveStreams = [];
return;
}
const lastProbeState = this.rateProbeState;
this.cleanBwPausedTiles(remoteInfos);
this.handleAppPausedStreams(chosenStreams, remoteInfos);
const sameStreamChoices = this.availStreamsSameAsLast(remoteInfos);
// If no major changes then don't allow subscribes for the allowed amount of time
const noMajorChange = !this.startupPeriod && sameStreamChoices;
// subscribe interval will be changed if probe failed, will take this temporary interval into account
if (
noMajorChange &&
this.probeFailed &&
Date.now() - this.lastSubscribeTimestamp < this.timeBeforeAllowSubscribeMs
) {
return;
}
this.probeFailed = false;
// Sort streams by bitrate ascending.
remoteInfos.sort((a, b) => {
if (a.maxBitrateKbps === b.maxBitrateKbps) {
return a.streamId - b.streamId;
}
return a.maxBitrateKbps - b.maxBitrateKbps;
});
// Convert 0 avg bitrates to max and handle special cases
for (const info of remoteInfos) {
if (info.avgBitrateKbps === 0 || info.avgBitrateKbps > info.maxBitrateKbps) {
// Content can be a special case
if (info.attendeeId.endsWith(ContentShareConstants.Modality) && info.maxBitrateKbps < 100) {
info.maxBitrateKbps = info.avgBitrateKbps;
} else {
info.avgBitrateKbps = info.maxBitrateKbps;
}
}
}
const rates: PolicyRates = {
targetDownlinkBitrate: 0,
chosenTotalBitrate: 0,
deltaToNextUpgrade: 0,
};
rates.targetDownlinkBitrate = this.determineTargetRate();
// calculate subscribe delay based on bandwidth increasing/decreasing
const numberOfParticipants = this.subscribedReceiveSet.size();
const prevEstimated = this.prevDownlinkStats.bandwidthEstimateKbps;
const currEstimated = this.downlinkStats.bandwidthEstimateKbps;
if (currEstimated > prevEstimated) {
// if bw increases, we use recovery delay
this.timeBeforeAllowSubscribeMs = this.getSubscribeDelay(
NetworkEvent.Increase,
numberOfParticipants
);
} else if (currEstimated < prevEstimated) {
// if bw decreases, we use response delay
this.timeBeforeAllowSubscribeMs = this.getSubscribeDelay(
NetworkEvent.Decrease,
numberOfParticipants
);
}
// If no major changes then don't allow subscribes for the allowed amount of time
if (
noMajorChange &&
Date.now() - this.lastSubscribeTimestamp < this.timeBeforeAllowSubscribeMs
) {
return;
}
const upgradeStream: VideoStreamDescription = this.priorityPolicy(
rates,
remoteInfos,
chosenStreams
);
let subscriptionChoice = UseReceiveSet.NewOptimal;
// Look for probing or override opportunities
if (!this.startupPeriod && sameStreamChoices) {
if (this.rateProbeState === RateProbeState.Probing) {
subscriptionChoice = this.handleProbe(chosenStreams, rates.targetDownlinkBitrate);
} else if (rates.deltaToNextUpgrade !== 0) {
subscriptionChoice = this.maybeOverrideOrProbe(chosenStreams, rates, upgradeStream);
}
} else {
// If there was a change in streams to choose from, then cancel any probing or upgrades
this.setProbeState(RateProbeState.NotProbing);
this.lastUpgradeRateKbps = 0;
}
this.prevRemoteInfos = remoteInfos;
this.videoPreferencesUpdated = false;
if (subscriptionChoice === UseReceiveSet.PreviousOptimal) {
this.logger.info(`bwe: keepSameSubscriptions stats:${JSON.stringify(this.downlinkStats)}`);
this.prevTargetRateKbps = rates.targetDownlinkBitrate;
return;
}
if (subscriptionChoice === UseReceiveSet.PreProbe) {
const subscribedRate = this.calculateSubscribeRate(this.preProbeNonPausedReceiveStreams);
this.optimalReceiveStreams = this.preProbeReceiveStreams.slice();
this.processBwPausedStreams(remoteInfos, this.preProbeNonPausedReceiveStreams);
this.logger.info('bwe: Use Pre-Probe subscription subscribedRate:' + subscribedRate);
return;
}
this.optimalNonPausedReceiveStreams = chosenStreams.slice();
const lastNumberPaused = this.pausedBwAttendeeIds.size;
this.processBwPausedStreams(remoteInfos, chosenStreams);
if (
this.logger.getLogLevel() <= LogLevel.INFO &&
(this.logCount % 15 === 0 ||
this.rateProbeState !== lastProbeState ||
this.optimalReceiveStreams.length !== chosenStreams.length ||
lastNumberPaused !== this.pausedBwAttendeeIds.size)
) {
this.logger.info(this.policyStateLogStr(remoteInfos, rates.targetDownlinkBitrate));
this.logCount = 0;
}
this.logCount++;
this.prevTargetRateKbps = rates.targetDownlinkBitrate;
this.optimalReceiveStreams = chosenStreams.slice();
}