computeHlsOffset_(headerBlock, time) {
    // https://bit.ly/2K92l7y
    // The 'X-TIMESTAMP-MAP' header is used in HLS to align text with
    // the rest of the media.
    // The header format is 'X-TIMESTAMP-MAP=MPEGTS:n,LOCAL:m'
    // (the attributes can go in any order)
    // where n is MPEG-2 time and m is cue time it maps to.
    // For example 'X-TIMESTAMP-MAP=LOCAL:00:00:00.000,MPEGTS:900000'
    // means an offset of 10 seconds
    // 900000/MPEG_TIMESCALE - cue time.
    const cueTimeMatch = headerBlock.match(
        /LOCAL:((?:(\d{1,}):)?(\d{2}):(\d{2})\.(\d{3}))/m);
    const mpegTimeMatch = headerBlock.match(/MPEGTS:(\d+)/m);

    if (!cueTimeMatch || !mpegTimeMatch) {
      throw new shaka.util.Error(
          shaka.util.Error.Severity.CRITICAL,
          shaka.util.Error.Category.TEXT,
          shaka.util.Error.Code.INVALID_TEXT_HEADER);
    }

    const cueTime = shaka.util.TextParser.parseTime(cueTimeMatch[1]);
    if (cueTime == null) {
      throw new shaka.util.Error(
          shaka.util.Error.Severity.CRITICAL,
          shaka.util.Error.Category.TEXT,
          shaka.util.Error.Code.INVALID_TEXT_HEADER);
    }

    let mpegTime = Number(mpegTimeMatch[1]);
    const mpegTimescale = shaka.text.VttTextParser.MPEG_TIMESCALE_;

    const rolloverSeconds =
        shaka.text.VttTextParser.TS_ROLLOVER_ / mpegTimescale;
    let segmentStart = time.segmentStart - time.periodStart;
    while (segmentStart >= rolloverSeconds) {
      segmentStart -= rolloverSeconds;
      mpegTime += shaka.text.VttTextParser.TS_ROLLOVER_;
    }

    return time.periodStart + mpegTime / mpegTimescale - cueTime;
  }
@param {string} headerBlock Contains X-TIMESTAMP-MAP.
@param {shaka.extern.TextParser.TimeContext} time
@return {number}
@private