async srcEqualsInner_(startTimeOfLoad, mimeType) {
    this.makeStateChangeEvent_('src-equals');

    goog.asserts.assert(
        this.video_, 'We should have a media element when loading.');
    goog.asserts.assert(
        this.assetUri_, 'We should have a valid uri when loading.');

    const mediaElement = this.video_;

    this.playhead_ = new shaka.media.SrcEqualsPlayhead(mediaElement);

    // This flag is used below in the language preference setup to check if
    // this load was canceled before the necessary awaits completed.
    let unloaded = false;
    this.cleanupOnUnload_.push(() => {
      unloaded = true;
    });

    this.dispatchEvent(shaka.Player.makeEvent_(
        shaka.util.FakeEvent.EventName.CanUpdateStartTime));

    if (this.startTime_ != null) {
      this.playhead_.setStartTime(this.startTime_);
    }

    this.playheadObservers_ =
        this.createPlayheadObserversForSrcEquals_(this.startTime_ || 0);

    this.playRateController_ = new shaka.media.PlayRateController({
      getRate: () => mediaElement.playbackRate,
      getDefaultRate: () => mediaElement.defaultPlaybackRate,
      setRate: (rate) => { mediaElement.playbackRate = rate; },
      movePlayhead: (delta) => { mediaElement.currentTime += delta; },
    });

    this.startBufferManagement_(mediaElement, /* srcEquals= */ true);

    if (mediaElement.textTracks) {
      this.createAndConfigureTextDisplayer_();
      const setMode = (showing) => {
        if (!(this.textDisplayer_ instanceof shaka.text.NativeTextDisplayer)) {
          const track = this.getFilteredTextTracks_()
              .find((t) => t.mode !== 'disabled');
          if (track) {
            track.mode = showing ? 'showing' : 'hidden';
          }
          if (this.textDisplayer_ instanceof shaka.text.SimpleTextDisplayer) {
            const generatedTrack = this.getGeneratedTextTrack_();
            if (generatedTrack) {
              generatedTrack.mode =
                !showing && this.textDisplayer_.isTextVisible() ?
                'showing' : 'hidden';
            }
          }
        }
      };
      this.loadEventManager_.listen(mediaElement, 'enterpictureinpicture',
          () => setMode(true));
      this.loadEventManager_.listen(mediaElement, 'leavepictureinpicture',
          () => setMode(false));
      if (mediaElement.remote) {
        this.loadEventManager_.listen(mediaElement.remote, 'connect',
            () => setMode(false));
        this.loadEventManager_.listen(mediaElement.remote, 'connecting',
            () => setMode(false));
        this.loadEventManager_.listen(mediaElement.remote, 'disconnect',
            () => setMode(false));
      } else if ('webkitCurrentPlaybackTargetIsWireless' in mediaElement) {
        this.loadEventManager_.listen(mediaElement,
            'webkitcurrentplaybacktargetiswirelesschanged',
            () => setMode(false));
      }
      const video = /** @type {HTMLVideoElement} */(mediaElement);
      if (video.webkitSupportsFullscreen) {
        this.loadEventManager_.listen(video, 'webkitpresentationmodechanged',
            () => setMode(video.webkitPresentationMode !== 'inline'));
      }
    }
    // Add all media element listeners.
    this.addBasicMediaListeners_(mediaElement, startTimeOfLoad);

    // By setting |src| we are done "loading" with src=. We don't need to set
    // the current time because |playhead| will do that for us.
    let playbackUri = this.cmcdManager_.appendSrcData(this.assetUri_, mimeType);
    // Apply temporal clipping using playRangeStart and playRangeEnd based
    // in https://www.w3.org/TR/media-frags/
    if (!playbackUri.includes('#t=') &&
        (this.config_.playRangeStart > 0 ||
        isFinite(this.config_.playRangeEnd))) {
      playbackUri += '#t=';
      if (this.config_.playRangeStart > 0) {
        playbackUri += this.config_.playRangeStart;
      }
      if (isFinite(this.config_.playRangeEnd)) {
        playbackUri += ',' + this.config_.playRangeEnd;
      }
    }

    if (this.mediaSourceEngine_ ) {
      await this.mediaSourceEngine_.destroy();
      this.mediaSourceEngine_ = null;
    }
    shaka.util.Dom.clearSourceFromVideo(mediaElement);

    mediaElement.src = playbackUri;

    const device = shaka.device.DeviceFactory.getDevice();

    // Tizen 3 / WebOS won't load anything unless you call load() explicitly,
    // no matter the value of the preload attribute.  This is harmful on some
    // other platforms by triggering unbounded loading of media data, but is
    // necessary here.
    if (device.getDeviceType() == shaka.device.IDevice.DeviceType.TV) {
      mediaElement.load();
    }

    // In Safari using HLS won't load anything unless you call load()
    // explicitly, no matter the value of the preload attribute.
    // Note: this only happens when there are not autoplay.
    if (mediaElement.preload != 'none' && !mediaElement.autoplay &&
        shaka.util.MimeUtils.isHlsType(mimeType) &&
        device.getBrowserEngine() ===
          shaka.device.IDevice.BrowserEngine.WEBKIT) {
      mediaElement.load();
    }

    // Set the load mode last so that we know that all our components are
    // initialized.
    this.loadMode_ = shaka.Player.LoadMode.SRC_EQUALS;

    // The event doesn't mean as much for src= playback, since we don't
    // control streaming.  But we should fire it in this path anyway since
    // some applications may be expecting it as a life-cycle event.
    this.dispatchEvent(shaka.Player.makeEvent_(
        shaka.util.FakeEvent.EventName.Streaming));

    // The "load" Promise is resolved when we have loaded the metadata.  If we
    // wait for the full data, that won't happen on Safari until the play
    // button is hit.
    const fullyLoaded = new shaka.util.PublicPromise();
    shaka.util.MediaReadyState.waitForReadyState(mediaElement,
        HTMLMediaElement.HAVE_METADATA,
        this.loadEventManager_,
        () => {
          this.playhead_.ready();
          fullyLoaded.resolve();
        });

    const waitForNativeTracks = () => {
      return new Promise((resolve) => {
        const GRACE_PERIOD = 0.5;
        const timer = new shaka.util.Timer(resolve);
        // Applying the text preference too soon can result in it being
        // reverted.  Wait for native HLS to pick something first.
        this.loadEventManager_.listen(mediaElement.textTracks,
            'change', () => timer.tickAfter(GRACE_PERIOD));
        timer.tickAfter(GRACE_PERIOD);
      });
    };

    // We can't switch to preferred languages, though, until the data is
    // loaded.
    shaka.util.MediaReadyState.waitForReadyState(mediaElement,
        HTMLMediaElement.HAVE_CURRENT_DATA,
        this.loadEventManager_,
        async () => {
          await waitForNativeTracks();
          // If we have moved on to another piece of content while waiting for
          // the above event/timer, we should not change tracks here.
          if (unloaded) {
            return;
          }

          this.setupPreferredAudioOnSrc_();

          const textTracks = this.getFilteredTextTracks_();
          // If Safari native picked one for us, we'll set text visible.
          if (textTracks.some((t) => t.mode === 'showing')) {
            this.isTextVisible_ = true;
            this.textDisplayer_.setTextVisibility(true);
          }

          if (
            !(this.textDisplayer_ instanceof shaka.text.NativeTextDisplayer)
          ) {
            if (textTracks.length) {
              if (this.textDisplayer_.enableTextDisplayer) {
                this.textDisplayer_.enableTextDisplayer();
              } else {
                shaka.Deprecate.deprecateFeature(
                    5,
                    'Text displayer w/ enableTextDisplayer',
                    'Text displayer should have a "enableTextDisplayer" method',
                );
              }
            }

            let enabledNativeTrack = false;
            for (const track of textTracks) {
              if (track.mode !== 'disabled') {
                if (!enabledNativeTrack) {
                  this.enableNativeTrack_(track);
                  enabledNativeTrack = true;
                } else {
                  track.mode = 'disabled';
                  shaka.log.alwaysWarn(
                      'Found more than one enabled text track, disabling it',
                      track);
                }
              }
            }
          }

          this.setupPreferredTextOnSrc_();
        });

    if (mediaElement.error) {
      // Already failed!
      fullyLoaded.reject(this.videoErrorToShakaError_());
    } else if (mediaElement.preload == 'none') {
      shaka.log.alwaysWarn(
          'With <video preload="none">, the browser will not load anything ' +
          'until play() is called. We are unable to measure load latency ' +
          'in a meaningful way, and we cannot provide track info yet. ' +
          'Please do not use preload="none" with Shaka Player.');
      // We can't wait for an event load loadedmetadata, since that will be
      // blocked until a user interaction.  So resolve the Promise now.
      fullyLoaded.resolve();
    }

    this.loadEventManager_.listenOnce(mediaElement, 'error', () => {
      fullyLoaded.reject(this.videoErrorToShakaError_());
    });

    await shaka.util.Functional.promiseWithTimeout(
        this.config_.streaming.loadTimeout, fullyLoaded);

    const isLive = this.isLive();

    if ((isLive && ((this.config_.streaming.liveSync &&
        this.config_.streaming.liveSync.enabled) ||
        this.config_.streaming.liveSync.panicMode)) ||
        this.config_.streaming.vodDynamicPlaybackRate) {
      const onTimeUpdate = () => this.onTimeUpdate_();
      this.loadEventManager_.listen(mediaElement, 'timeupdate', onTimeUpdate);
    }
    if (!isLive) {
      const onVideoProgress = () => this.onVideoProgress_();
      this.loadEventManager_.listen(
          mediaElement, 'timeupdate', onVideoProgress);
      this.onVideoProgress_();
    }

    if (this.adManager_) {
      this.adManager_.onManifestUpdated(isLive);
      // There is no good way to detect when the manifest has been updated,
      // so we use seekRange().end so we can tell when it has been updated.
      if (isLive) {
        let prevSeekRangeEnd = this.seekRange().end;
        this.loadEventManager_.listen(mediaElement, 'progress', () => {
          const newSeekRangeEnd = this.seekRange().end;
          if (prevSeekRangeEnd != newSeekRangeEnd) {
            this.adManager_.onManifestUpdated(this.isLive());
            prevSeekRangeEnd = newSeekRangeEnd;
          }
        });
      }
    }

    this.fullyLoaded_ = true;
  }
Passes the asset URI along to the media element, so it can be played src
equals style.

@param {number} startTimeOfLoad
@param {string} mimeType
@return {!Promise}

@private