2022-04-21 01:39:05 +02:00
|
|
|
// package jitter implements a jitter estimator
|
2020-05-02 16:21:48 +02:00
|
|
|
package jitter
|
|
|
|
|
|
|
|
import (
|
|
|
|
"sync/atomic"
|
|
|
|
|
2020-12-19 17:37:48 +01:00
|
|
|
"github.com/jech/galene/rtptime"
|
2020-05-02 16:21:48 +02:00
|
|
|
)
|
|
|
|
|
|
|
|
type Estimator struct {
|
|
|
|
hz uint32
|
|
|
|
timestamp uint32
|
2020-06-03 20:12:25 +02:00
|
|
|
time uint32
|
2020-05-02 16:21:48 +02:00
|
|
|
|
|
|
|
jitter uint32 // atomic
|
|
|
|
}
|
|
|
|
|
2022-04-21 01:39:05 +02:00
|
|
|
// New returns a new jitter estimator that uses units of 1/hz seconds.
|
2020-05-02 16:21:48 +02:00
|
|
|
func New(hz uint32) *Estimator {
|
|
|
|
return &Estimator{hz: hz}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (e *Estimator) accumulate(timestamp, now uint32) {
|
|
|
|
if e.time == 0 {
|
|
|
|
e.timestamp = timestamp
|
|
|
|
e.time = now
|
|
|
|
}
|
|
|
|
|
|
|
|
d := uint32((e.time - now) - (e.timestamp - timestamp))
|
2020-06-03 20:12:25 +02:00
|
|
|
if d&0x80000000 != 0 {
|
2020-05-02 16:21:48 +02:00
|
|
|
d = uint32(-int32(d))
|
|
|
|
}
|
|
|
|
oldjitter := atomic.LoadUint32(&e.jitter)
|
2020-06-03 20:12:25 +02:00
|
|
|
jitter := (oldjitter*15 + d) / 16
|
2020-05-02 16:21:48 +02:00
|
|
|
atomic.StoreUint32(&e.jitter, jitter)
|
|
|
|
|
|
|
|
e.timestamp = timestamp
|
|
|
|
e.time = now
|
|
|
|
}
|
|
|
|
|
2022-04-21 01:39:05 +02:00
|
|
|
// Accumulate accumulates a new sample for the jitter estimator.
|
2020-05-02 16:21:48 +02:00
|
|
|
func (e *Estimator) Accumulate(timestamp uint32) {
|
2020-06-03 20:12:25 +02:00
|
|
|
e.accumulate(timestamp, uint32(rtptime.Now(e.hz)))
|
2020-05-02 16:21:48 +02:00
|
|
|
}
|
|
|
|
|
2022-04-21 01:39:05 +02:00
|
|
|
// Jitter returns the estimated jitter, in units of 1/hz seconds.
|
|
|
|
// This function is safe to call concurrently.
|
2020-05-02 16:21:48 +02:00
|
|
|
func (e *Estimator) Jitter() uint32 {
|
|
|
|
return atomic.LoadUint32(&e.jitter)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (e *Estimator) HZ() uint32 {
|
|
|
|
return e.hz
|
|
|
|
}
|