async resync(contentType, timestampOffset) {
    const ContentType = shaka.util.ManifestParserUtils.ContentType;

    if (contentType == ContentType.TEXT) {
      // This operation is for audio and video only.
      return;
    }

    // Reset the promise in case the timestamp offset changed during
    // a period/discontinuity transition.
    if (contentType == ContentType.VIDEO) {
      this.textSequenceModeOffset_ = new shaka.util.PublicPromise();
    }

    if (!this.sequenceMode_) {
      return;
    }

    // Avoid changing timestampOffset when the difference is less than 100 ms
    // from the end of the current buffer.
    const bufferEnd = this.bufferEnd(contentType);
    if (bufferEnd && Math.abs(bufferEnd - timestampOffset) < 0.1) {
      return;
    }

    // Queue an abort() to help MSE splice together overlapping segments.
    // We set appendWindowEnd when we change periods in DASH content, and the
    // period transition may result in overlap.
    //
    // An abort() also helps with MPEG2-TS.  When we append a TS segment, we
    // always enter a PARSING_MEDIA_SEGMENT state and we can't change the
    // timestamp offset.  By calling abort(), we reset the state so we can
    // set it.
    this.enqueueOperation_(
        contentType,
        () => this.abort_(contentType),
        null);
    if (this.needSplitMuxedContent_) {
      this.enqueueOperation_(
          ContentType.AUDIO,
          () => this.abort_(ContentType.AUDIO),
          null);
    }
    await this.enqueueOperation_(
        contentType,
        () => this.setTimestampOffset_(contentType, timestampOffset),
        null);
    if (this.needSplitMuxedContent_) {
      await this.enqueueOperation_(
          ContentType.AUDIO,
          () => this.setTimestampOffset_(ContentType.AUDIO, timestampOffset),
          null);
    }
  }
Adjust timestamp offset to maintain AV sync across discontinuities.

@param {shaka.util.ManifestParserUtils.ContentType} contentType
@param {number} timestampOffset
@return {!Promise}