private determineTargetRate()

in src/videodownlinkbandwidthpolicy/VideoPriorityBasedPolicy.ts [583:683]


  private determineTargetRate(): number {
    let targetBitrate = 0;

    const now = Date.now();
    // Startup phase handling.  During this period the estimate can be 0 or
    // could still be slowly hunting for a steady state.  This startup ramp up
    // can cause a series of subscribes which can be distracting. During this
    // time just use our configured default value
    if (this.downlinkStats.bandwidthEstimateKbps !== 0) {
      if (this.firstEstimateTimestamp === 0) {
        this.firstEstimateTimestamp = now;
      }

      // handle startup state where estimator is still converging.
      if (this.startupPeriod) {
        // Drop out of startup period if
        // - estimate is above default
        // - get packet loss and have a valid estimate
        // - startup period has expired and rate is not still increasing
        if (
          this.downlinkStats.bandwidthEstimateKbps >
            VideoPriorityBasedPolicy.DEFAULT_BANDWIDTH_KBPS ||
          this.downlinkStats.packetsLost > 0 ||
          (now - this.firstEstimateTimestamp > VideoPriorityBasedPolicy.STARTUP_PERIOD_MS &&
            this.downlinkStats.bandwidthEstimateKbps <=
              this.prevDownlinkStats.bandwidthEstimateKbps)
        ) {
          this.startupPeriod = false;
          this.prevTargetRateKbps = this.downlinkStats.bandwidthEstimateKbps;
        }
      }
      // If we are in the startup period and we haven't detected any packet loss, then
      // keep it at the default to let the estimation get to a steady state
      if (this.startupPeriod) {
        targetBitrate = VideoPriorityBasedPolicy.DEFAULT_BANDWIDTH_KBPS;
      } else {
        // We rely on our target bitrate being above what we are receiving to mark a probe as complete,
        // however in browsers, the estimate can heavily lag behind the actual receive rate, especially when low.
        //
        // To mitigate this we override with the actual estimate plus some buffer if we aren't seeing packet loss.
        if (
          this.rateProbeState === RateProbeState.Probing &&
          this.downlinkStats.usedBandwidthKbps > this.downlinkStats.bandwidthEstimateKbps &&
          this.downlinkStats.packetsLost < VideoPriorityBasedPolicy.SPURIOUS_PACKET_LOST_THRESHOLD
        ) {
          this.logger.info(
            `bwe: In probe state, overriding estimate ${this.downlinkStats.bandwidthEstimateKbps} with actual receive bitrate ${this.downlinkStats.usedBandwidthKbps}`
          );
          targetBitrate =
            this.downlinkStats.usedBandwidthKbps +
            VideoPriorityBasedPolicy.USED_BANDWIDTH_OVERRIDE_BUFFER_KBPS;
        } else {
          targetBitrate = this.downlinkStats.bandwidthEstimateKbps;
        }
      }
    } else {
      if (this.firstEstimateTimestamp === 0) {
        targetBitrate = VideoPriorityBasedPolicy.DEFAULT_BANDWIDTH_KBPS;
      } else {
        targetBitrate = this.prevTargetRateKbps;
      }
    }

    // Estimated downlink rate can follow actual bandwidth or fall for a short period of time
    // due to the absolute send time estimator incorrectly thinking that a delay in packets is
    // a precursor to packet loss.  We have seen too many false positives on this, so we
    // will ignore largish drops in the estimate if there is no packet loss
    if (
      !this.startupPeriod &&
      ((this.usingPrevTargetRate &&
        this.downlinkStats.bandwidthEstimateKbps < this.prevTargetRateKbps) ||
        this.downlinkStats.bandwidthEstimateKbps <
          (this.prevTargetRateKbps *
            (100 - VideoPriorityBasedPolicy.LARGE_RATE_CHANGE_TRIGGER_PERCENT)) /
            100 ||
        this.downlinkStats.bandwidthEstimateKbps <
          (this.downlinkStats.usedBandwidthKbps *
            VideoPriorityBasedPolicy.LARGE_RATE_CHANGE_TRIGGER_PERCENT) /
            100) &&
      this.downlinkStats.packetsLost === 0
    ) {
      // Set target to be the same as last
      this.logger.debug(() => {
        return 'bwe: ValidateRate: Using Previous rate ' + this.prevTargetRateKbps;
      });
      this.usingPrevTargetRate = true;
      targetBitrate = this.prevTargetRateKbps;
    } else {
      this.usingPrevTargetRate = false;
    }

    // Cap total receive bitrate at 15000 kbps
    if (targetBitrate > 15000) {
      this.logger.warn(
        'bwe: ' +
          targetBitrate +
          ' exceeds maximum limit (15000). Limit TargetDisplaySize with VideoPreferences to avoid this.'
      );
    }
    return Math.min(targetBitrate, 15000);
  }