demux (data, discontinuity = false, contiguous = true) {
    const { audioTrack, videoTrack, metadataTrack } = this

    if (discontinuity) {
      this._pmtId = -1
      videoTrack.reset()
      audioTrack.reset()
      metadataTrack.reset()
    }

    if (!contiguous || discontinuity) {
      this._remainingPacketData = null
      this._videoPesData = []
      this._audioPesData = []
    } else {
      videoTrack.samples = []
      audioTrack.samples = []
      metadataTrack.seiSamples = []
      videoTrack.warnings = []
      audioTrack.warnings = []

      if (this._remainingPacketData) {
        data = concatUint8Array(this._remainingPacketData, data)
        this._remainingPacketData = null
      }
    }

    let dataLen = data.length
    const remainingLength = dataLen % 188
    if (remainingLength) {
      this._remainingPacketData = data.subarray(dataLen - remainingLength)
      dataLen -= remainingLength
    }

    let videoPid = videoTrack.pid
    let audioPid = audioTrack.pid

    for (let start = 0; start < dataLen; start += 188) {
      if (data[start] !== 0x47) throw new Error('TS packet did not start with 0x47')
      const payloadUnitStartIndicator = !!(data[start + 1] & 0x40)
      const pid = ((data[start + 1] & 0x1f) << 8) + data[start + 2]
      const adaptationFiledControl = (data[start + 3] & 0x30) >> 4

      let offset
      if (adaptationFiledControl > 1) {
        offset = start + 5 + data[start + 4]
        if (offset === start + 188) continue
      } else {
        offset = start + 4
      }

      switch (pid) {
        case 0: // PAT
          if (payloadUnitStartIndicator) offset += data[offset] + 1
          this._pmtId = ((data[offset + 10] & 0x1f) << 8) | data[offset + 11]
          break
        case this._pmtId: {
          if (payloadUnitStartIndicator) offset += data[offset] + 1
          const tableEnd = offset + 3 + (((data[offset + 1] & 0x0f) << 8) | data[offset + 2]) - 4
          const programInfoLength = ((data[offset + 10] & 0x0f) << 8) | data[offset + 11]
          offset += 12 + programInfoLength

          while (offset < tableEnd) {
            const esPid = ((data[offset + 1] & 0x1f) << 8) | data[offset + 2]
            switch (data[offset]) {
              case 0x0f: // AAC ADTS
                audioTrack.pid = audioPid = esPid
                break
              case 0x03:
              case 0x04:
                if (audioTrack.pid === -1) {
                  audioTrack.pid = audioPid = esPid
                  audioTrack.codecType = AudioCodecType.MP3
                }
                break
              case 0x1b: // AVC
                if (videoPid !== -1) break
                videoTrack.codecType = VideoCodecType.AVC
                videoTrack.pid = videoPid = esPid
                break
              case 0x24: // HEVC
                if (videoPid !== -1) break
                videoTrack.codecType = VideoCodecType.HEVC
                videoTrack.pid = videoPid = esPid
                break
              default:
                logger.warn(`Unsupported stream. type: ${data[offset]}, pid: ${esPid}`)
            }

            offset += (((data[offset + 3] & 0x0f) << 8) | data[offset + 4]) + 5
          }
        }
          break
        case videoPid:
          if (payloadUnitStartIndicator && this._videoPesData.length) {
            this._parseVideoData()
          }
          this._videoPesData.push(data.subarray(offset, start + 188))
          break
        case audioPid:
          if (payloadUnitStartIndicator && this._audioPesData.length) {
            this._parseAudioData()
          }
          this._audioPesData.push(data.subarray(offset, start + 188))
          break
        case 17:
        case 0x1fff:
          break
        default:
          logger.warn(`Unknown pid: ${pid}`)
      }
    }

    this._parseVideoData()
    this._parseAudioData()

    audioTrack.formatTimescale = videoTrack.formatTimescale = videoTrack.timescale = metadataTrack.timescale = 90000

    audioTrack.timescale = audioTrack.sampleRate || 0

    return {
      videoTrack,
      audioTrack,
      metadataTrack
    }
  }
@param {Uint8Array} data
@param {boolean} [discontinuity=false]
@param {boolean} [contiguous=true]
@returns {import('../flv').DemuxResult}