_fixVideo (videoTrack) {
    const samples = videoTrack.samples

    if (!samples.length) return
    samples.forEach(x => {
      x.dts -= this._needForceFixLargeGap ? this._baseVideoDts : this._baseDts
      x.pts -= this._needForceFixLargeGap ? this._baseVideoDts : this._baseDts
    })

    if (this._videoNextDts === undefined) {
      const samp0 = samples[0]
      this._videoNextDts = samp0.dts
    }

    const len = samples.length
    let sampleDuration = 0
    const firstSample = samples[0]
    const nextSample = samples[1]
    const vDelta = this._videoNextDts - firstSample.dts

    if (Math.abs(vDelta) > MAX_DTS_DELTA_WITH_NEXT_CHUNK) {
      videoTrack.warnings.push({
        type: WarningType.LARGE_VIDEO_GAP_BETWEEN_CHUNK,
        nextDts: this._videoNextDts / 90,
        firstSampleDts: firstSample.dts / 90,
        nextSampleDts: (samples[1]?.dts || 0) / 90,
        sampleDuration: vDelta / 90
      })

      // resolve first frame first
      firstSample.dts += vDelta
      firstSample.pts += vDelta


      // check to ajust the whole segment
      if (nextSample && Math.abs(nextSample.dts - firstSample.dts) > MAX_VIDEO_FRAME_DURATION) {
        this._videoTimestampBreak = true
        samples.forEach((x, i) => {
          if (i === 0) return
          x.dts += vDelta
          x.pts += vDelta
        })
      } else {
        for (let i = 1; i <= len - 1; i++) {
          const dts = samples[i]?.dts
          const prevDts = samples[i - 1 ].dts
          if (dts && dts - prevDts < 0) {
            samples[i].dts += vDelta
            samples[i].pts += vDelta
          }
        }
      }
    }

    let refSampleDurationInt
    if (videoTrack.fpsNum && videoTrack.fpsDen) {
      refSampleDurationInt = videoTrack.timescale * (videoTrack.fpsDen / videoTrack.fpsNum)
    }

    // fps inaccuracy
    if (refSampleDurationInt < 90 * 10) { // < 10ms per frame
      refSampleDurationInt = 0
    }

    if (!refSampleDurationInt) {
      const first = videoTrack.samples[0]
      const second = videoTrack.samples[1]
      // 100ms default
      refSampleDurationInt = len === 1 ? 9000 : Math.floor((second.dts - first.dts))
    }

    for (let i = 0; i < len; i++) {
      const dts = samples[i].dts
      const nextSample = samples[i + 1]
      if (i < len - 1) {
        sampleDuration = nextSample.dts - dts
      } else if (samples[i - 1]) {
        sampleDuration = Math.min(dts - samples[i - 1].dts, refSampleDurationInt)
      } else {
        sampleDuration = refSampleDurationInt
      }

      if (sampleDuration > MAX_VIDEO_FRAME_DURATION || sampleDuration < 0) {
        // dts exception of adjacent frame
        this._videoTimestampBreak = true

        // check if only video breaked!
        sampleDuration = this._audioTimestampBreak ? refSampleDurationInt : Math.max(sampleDuration, 30 * 90) // 30ms

        // check if sample breaked within current fragment
        const expectFragEnd = (this._audioNextPts || 0)
        if (nextSample && nextSample.dts > expectFragEnd) {
          sampleDuration = refSampleDurationInt
        }

        videoTrack.warnings.push({
          type: WarningType.LARGE_VIDEO_GAP,
          time: dts / videoTrack.timescale,
          dts,
          originDts: samples[i].originDts,
          nextDts: this._videoNextDts,
          sampleDuration,
          refSampleDuration: refSampleDurationInt
        })
      }

      samples[i].duration = sampleDuration
      this._videoNextDts += sampleDuration
    }
  }
segment.start = min(a, v)
 segment.start
     |
     a
      -- vaDelta --
                  v