fix wrong timestamp computation that happened at 28h28m

this was caused by a int64 overflow.
This commit is contained in:
aler9
2022-02-13 17:00:13 +01:00
parent ab50034c93
commit a235613fd6
2 changed files with 39 additions and 28 deletions

View File

@@ -8,9 +8,8 @@ import (
// Decoder is a RTP timestamp decoder.
type Decoder struct {
clockRate time.Duration
tsAdd int64
tsInitial *int64
tsPrev *int64
tsAdd *int64
tsPrev int64
}
// New allocates a Decoder.
@@ -24,22 +23,29 @@ func New(clockRate int) *Decoder {
func (d *Decoder) Decode(ts uint32) time.Duration {
ts64 := int64(ts)
if d.tsPrev != nil {
diff := ts64 - *d.tsPrev
if d.tsAdd == nil {
d.tsPrev = ts64
ts64 = -ts64
d.tsAdd = &ts64
return 0
}
diff := ts64 - d.tsPrev
d.tsPrev = ts64
switch {
case diff < -0xFFFFFF: // overflow
d.tsAdd += 0x100000000
*d.tsAdd += 0x100000000
case diff > 0xFFFFFF: // timestamp overflowed then went back
d.tsAdd -= 0x100000000
}
*d.tsAdd -= 0x100000000
}
d.tsPrev = &ts64
tot := time.Duration(ts64 + *d.tsAdd)
if d.tsInitial == nil {
d.tsInitial = &ts64
}
return time.Duration(ts64+d.tsAdd-*d.tsInitial) * time.Second / d.clockRate
// avoid an int64 overflow and preserve resolution by splitting division into two parts:
// first add seconds, then the decimal part.
secs := tot / d.clockRate
dec := tot % d.clockRate
return secs*time.Second + dec*time.Second/d.clockRate
}

View File

@@ -11,24 +11,29 @@ func TestOverflow(t *testing.T) {
d := New(90000)
i := uint32(4294877296)
secs := time.Duration(0)
pts := d.Decode(i)
require.Equal(t, time.Duration(0), pts)
// 1st overflow
i += 90000 * 2
pts = d.Decode(i)
require.Equal(t, 2*time.Second, pts)
const stride = 150
lim := uint32(uint64(4294967296 - (stride * 90000)))
// reach 4294890000 slowly
for ; i < 4294890000; i += 90000 * 10 {
for n := 0; n < 100; n++ {
// overflow
i += 90000 * stride
secs += stride
pts = d.Decode(i)
require.Equal(t, 2*time.Second+time.Second*time.Duration(i-90000)/90000, pts)
require.Equal(t, secs*time.Second, pts)
// reach 2^32 slowly
secs += stride
i += 90000 * stride
for ; i < lim; i += 90000 * stride {
pts = d.Decode(i)
require.Equal(t, secs*time.Second, pts)
secs += stride
}
}
// 2nd overflow
i += 90000 * 10
pts = d.Decode(i)
require.Equal(t, 47732*time.Second, pts)
}
func TestOverflowAndBack(t *testing.T) {