async attach(mediaElement, initializeMediaSource = true) {
    // Do not allow the player to be used after |destroy| is called.
    if (this.loadMode_ == shaka.Player.LoadMode.DESTROYED) {
      throw this.createAbortLoadError_();
    }

    const noop = this.video_ && this.video_ == mediaElement;

    if (this.video_ && this.video_ != mediaElement) {
      await this.detach();
    }

    if (await this.atomicOperationAcquireMutex_('attach')) {
      return;
    }

    try {
      if (!noop) {
        this.makeStateChangeEvent_('attach');

        const onError = (error) => this.onVideoError_(error);
        this.attachEventManager_.listen(mediaElement, 'error', onError);
        this.video_ = mediaElement;
        if (this.cmcdManager_) {
          this.cmcdManager_.setMediaElement(mediaElement);
        }
      }

      // Only initialize media source if the platform supports it.
      const device = shaka.device.DeviceFactory.getDevice();
      if (initializeMediaSource && device.supportsMediaSource() &&
          !this.mediaSourceEngine_) {
        await this.initializeMediaSourceEngineInner_();
      }
    } catch (error) {
      await this.detach();
      throw error;
    } finally {
      this.mutex_.release();
    }
  }
Attaches the player to a media element.
If the player was already attached to a media element, first detaches from
that media element.

@param {!HTMLMediaElement} mediaElement
@param {boolean=} initializeMediaSource
@return {!Promise}
@export