github.com/bluenviron/mediacommon@v1.9.3/pkg/formats/mpegts/time_decoder.go (about)

     1  package mpegts
     2  
     3  import (
     4  	"time"
     5  )
     6  
     7  const (
     8  	maximum           = 0x1FFFFFFFF // 33 bits
     9  	negativeThreshold = 0x1FFFFFFFF / 2
    10  	clockRate         = 90000
    11  )
    12  
    13  // avoid an int64 overflow and preserve resolution by splitting division into two parts:
    14  // first add the integer part, then the decimal part.
    15  func multiplyAndDivide(v, m, d time.Duration) time.Duration {
    16  	secs := v / d
    17  	dec := v % d
    18  	return (secs*m + dec*m/d)
    19  }
    20  
    21  // TimeDecoder is a MPEG-TS timestamp decoder.
    22  type TimeDecoder struct {
    23  	overall time.Duration
    24  	prev    int64
    25  }
    26  
    27  // NewTimeDecoder allocates a TimeDecoder.
    28  func NewTimeDecoder(start int64) *TimeDecoder {
    29  	return &TimeDecoder{
    30  		prev: start,
    31  	}
    32  }
    33  
    34  // Decode decodes a MPEG-TS timestamp.
    35  func (d *TimeDecoder) Decode(ts int64) time.Duration {
    36  	diff := (ts - d.prev) & maximum
    37  
    38  	// negative difference
    39  	if diff > negativeThreshold {
    40  		diff = (d.prev - ts) & maximum
    41  		d.prev = ts
    42  		d.overall -= time.Duration(diff)
    43  	} else {
    44  		d.prev = ts
    45  		d.overall += time.Duration(diff)
    46  	}
    47  
    48  	return multiplyAndDivide(d.overall, time.Second, clockRate)
    49  }