change rtptime.Encoder signature and initialize time to a random value (#525)

This commit is contained in:
Alessandro Ros
2024-02-25 23:25:44 +01:00
committed by GitHub
parent f040e20ac4
commit ce46aee084
3 changed files with 60 additions and 19 deletions

View File

@@ -45,7 +45,11 @@ func main() {
} }
// setup timestamp generator // setup timestamp generator
rtpTime := rtptime.NewEncoder(forma.ClockRate(), 0) rtpTime := &rtptime.Encoder{ClockRate: forma.ClockRate()}
err = rtpTime.Initialize()
if err != nil {
panic(err)
}
start := time.Now() start := time.Now()
// setup a ticker to sleep between frames // setup a ticker to sleep between frames
@@ -89,7 +93,7 @@ func main() {
} }
// get current timestamp // get current timestamp
ts := rtpTime.Encode(time.Now().Sub(start)) ts := rtpTime.Encode(time.Since(start))
// write packets to the server // write packets to the server
for _, pkt := range pkts { for _, pkt := range pkts {

View File

@@ -1,6 +1,7 @@
package rtptime package rtptime
import ( import (
"crypto/rand"
"time" "time"
) )
@@ -12,23 +13,47 @@ func divCeil(n, d uint64) uint64 {
return v return v
} }
// Encoder is a RTP timestamp encoder. func randUint32() (uint32, error) {
type Encoder struct { var b [4]byte
clockRate time.Duration _, err := rand.Read(b[:])
initialTimestamp time.Duration if err != nil {
return 0, err
}
return uint32(b[0])<<24 | uint32(b[1])<<16 | uint32(b[2])<<8 | uint32(b[3]), nil
} }
// NewEncoder allocates an Encoder. // Encoder is a RTP timestamp encoder.
func NewEncoder(clockRate int, initialTimestamp uint32) *Encoder { type Encoder struct {
return &Encoder{ // Clock rate.
clockRate: time.Duration(clockRate), ClockRate int
// ((2^32) * 1000000000) is less than 2^63
initialTimestamp: time.Duration(divCeil(uint64(initialTimestamp)*uint64(time.Second), uint64(clockRate))), // (optional) initial timestamp.
// It defaults to a random value.
InitialTimestamp *uint32
clockRateTD time.Duration
initialTimestampTD time.Duration
}
// Initialize initializes an Encoder.
func (e *Encoder) Initialize() error {
e.clockRateTD = time.Duration(e.ClockRate)
if e.InitialTimestamp == nil {
v, err := randUint32()
if err != nil {
return err
}
e.InitialTimestamp = &v
} }
e.initialTimestampTD = time.Duration(divCeil(uint64(*e.InitialTimestamp)*uint64(time.Second), uint64(e.ClockRate)))
return nil
} }
// Encode encodes a timestamp. // Encode encodes a timestamp.
func (e *Encoder) Encode(ts time.Duration) uint32 { func (e *Encoder) Encode(ts time.Duration) uint32 {
ts = e.initialTimestamp + ts ts += e.initialTimestampTD
return uint32(multiplyAndDivide(ts, e.clockRate, time.Second)) return uint32(multiplyAndDivide(ts, e.clockRateTD, time.Second))
} }

View File

@@ -7,8 +7,17 @@ import (
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
) )
func uint32Ptr(v uint32) *uint32 {
return &v
}
func TestEncoder(t *testing.T) { func TestEncoder(t *testing.T) {
e := NewEncoder(90000, 12345) e := &Encoder{
ClockRate: 90000,
InitialTimestamp: uint32Ptr(12345),
}
err := e.Initialize()
require.NoError(t, err)
ts := e.Encode(0) ts := e.Encode(0)
require.Equal(t, uint32(12345), ts) require.Equal(t, uint32(12345), ts)
@@ -18,10 +27,13 @@ func TestEncoder(t *testing.T) {
} }
func BenchmarkEncoder(b *testing.B) { func BenchmarkEncoder(b *testing.B) {
e := &Encoder{
ClockRate: 90000,
InitialTimestamp: uint32Ptr(12345),
}
e.Initialize() //nolint:errcheck
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
func() { e.Encode(200 * time.Second)
d := NewEncoder(90000, 0)
d.Encode(200 * time.Second)
}()
} }
} }