chooseVariant() {
    let maxHeight = Infinity;
    let maxWidth = Infinity;

    if (this.config_.restrictToScreenSize) {
      const devicePixelRatio = this.config_.ignoreDevicePixelRatio ?
          1 : this.windowToCheck_.devicePixelRatio;
      maxHeight = this.windowToCheck_.screen.height * devicePixelRatio;
      maxWidth = this.windowToCheck_.screen.width * devicePixelRatio;
    }

    if (this.resizeObserver_ && this.config_.restrictToElementSize) {
      const devicePixelRatio = this.config_.ignoreDevicePixelRatio ?
          1 : this.windowToCheck_.devicePixelRatio;
      let height = this.mediaElement_.clientHeight;
      let width = this.mediaElement_.clientWidth;
      if (this.pictureInPictureWindow_ && document.pictureInPictureElement &&
          document.pictureInPictureElement == this.mediaElement_) {
        height = this.pictureInPictureWindow_.height;
        width = this.pictureInPictureWindow_.width;
      }
      maxHeight = Math.min(maxHeight, height * devicePixelRatio);
      maxWidth = Math.min(maxWidth, width * devicePixelRatio);
    }

    let normalVariants = this.variants_.filter((variant) => {
      return variant && !shaka.util.StreamUtils.isFastSwitching(variant);
    });
    if (!normalVariants.length) {
      normalVariants = this.variants_;
    }

    let variants = normalVariants;
    if (normalVariants.length != this.variants_.length) {
      variants = this.variants_.filter((variant) => {
        return variant && shaka.util.StreamUtils.isFastSwitching(variant);
      });
    }

    // Get sorted Variants.
    let sortedVariants = this.filterAndSortVariants_(
        this.config_.restrictions, variants,
        /* maxHeight= */ Infinity, /* maxWidth= */ Infinity);

    if (maxHeight != Infinity || maxWidth != Infinity) {
      const resolutions = this.getResolutionList_(sortedVariants);
      for (const resolution of resolutions) {
        if (resolution.height >= maxHeight && resolution.width >= maxWidth) {
          maxHeight = resolution.height;
          maxWidth = resolution.width;
          break;
        }
      }

      sortedVariants = this.filterAndSortVariants_(
          this.config_.restrictions, variants, maxHeight, maxWidth);
    }

    const currentBandwidth = this.getBandwidthEstimate();

    if (variants.length && !sortedVariants.length) {
      // If we couldn't meet the ABR restrictions, we should still play
      // something.
      // These restrictions are not "hard" restrictions in the way that
      // top-level or DRM-based restrictions are.  Sort the variants without
      // restrictions and keep just the first (lowest-bandwidth) one.
      shaka.log.warning('No variants met the ABR restrictions. ' +
                        'Choosing a variant by lowest bandwidth.');
      sortedVariants = this.filterAndSortVariants_(
          /* restrictions= */ null, variants,
          /* maxHeight= */ Infinity, /* maxWidth= */ Infinity);
      sortedVariants = [sortedVariants[0]];
    }

    // Start by assuming that we will use the first Stream.
    let chosen = sortedVariants[0] || null;

    for (let i = 0; i < sortedVariants.length; i++) {
      const item = sortedVariants[i];
      const playbackRate =
          !isNaN(this.playbackRate_) ? Math.abs(this.playbackRate_) : 1;
      const itemBandwidth = playbackRate * item.bandwidth;
      const minBandwidth =
          itemBandwidth / this.config_.bandwidthDowngradeTarget;
      let next = {bandwidth: Infinity};
      for (let j = i + 1; j < sortedVariants.length; j++) {
        if (item.bandwidth != sortedVariants[j].bandwidth) {
          next = sortedVariants[j];
          break;
        }
      }
      const nextBandwidth = playbackRate * next.bandwidth;
      const maxBandwidth = nextBandwidth / this.config_.bandwidthUpgradeTarget;
      shaka.log.v2('Bandwidth ranges:',
          (itemBandwidth / 1e6).toFixed(3),
          (minBandwidth / 1e6).toFixed(3),
          (maxBandwidth / 1e6).toFixed(3));

      if (currentBandwidth >= minBandwidth &&
          currentBandwidth <= maxBandwidth &&
          (chosen.bandwidth != item.bandwidth ||
          this.isSameBandwidthAndHigherResolution_(chosen, item))) {
        chosen = item;
      }
    }

    this.lastTimeChosenMs_ = Date.now();
    return chosen;
  }
@return {shaka.extern.Variant}
@override
@export