mirror of
https://github.com/aler9/gortsplib
synced 2025-10-07 08:01:14 +08:00
fix wrong timestamp computation that happened at 28h28m
this was caused by a int64 overflow.
This commit is contained in:
@@ -8,9 +8,8 @@ import (
|
|||||||
// Decoder is a RTP timestamp decoder.
|
// Decoder is a RTP timestamp decoder.
|
||||||
type Decoder struct {
|
type Decoder struct {
|
||||||
clockRate time.Duration
|
clockRate time.Duration
|
||||||
tsAdd int64
|
tsAdd *int64
|
||||||
tsInitial *int64
|
tsPrev int64
|
||||||
tsPrev *int64
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// New allocates a Decoder.
|
// New allocates a Decoder.
|
||||||
@@ -24,22 +23,29 @@ func New(clockRate int) *Decoder {
|
|||||||
func (d *Decoder) Decode(ts uint32) time.Duration {
|
func (d *Decoder) Decode(ts uint32) time.Duration {
|
||||||
ts64 := int64(ts)
|
ts64 := int64(ts)
|
||||||
|
|
||||||
if d.tsPrev != nil {
|
if d.tsAdd == nil {
|
||||||
diff := ts64 - *d.tsPrev
|
d.tsPrev = ts64
|
||||||
|
ts64 = -ts64
|
||||||
|
d.tsAdd = &ts64
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
diff := ts64 - d.tsPrev
|
||||||
|
d.tsPrev = ts64
|
||||||
|
|
||||||
switch {
|
switch {
|
||||||
case diff < -0xFFFFFF: // overflow
|
case diff < -0xFFFFFF: // overflow
|
||||||
d.tsAdd += 0x100000000
|
*d.tsAdd += 0x100000000
|
||||||
|
|
||||||
case diff > 0xFFFFFF: // timestamp overflowed then went back
|
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 {
|
// avoid an int64 overflow and preserve resolution by splitting division into two parts:
|
||||||
d.tsInitial = &ts64
|
// first add seconds, then the decimal part.
|
||||||
}
|
secs := tot / d.clockRate
|
||||||
|
dec := tot % d.clockRate
|
||||||
return time.Duration(ts64+d.tsAdd-*d.tsInitial) * time.Second / d.clockRate
|
return secs*time.Second + dec*time.Second/d.clockRate
|
||||||
}
|
}
|
||||||
|
@@ -11,24 +11,29 @@ func TestOverflow(t *testing.T) {
|
|||||||
d := New(90000)
|
d := New(90000)
|
||||||
|
|
||||||
i := uint32(4294877296)
|
i := uint32(4294877296)
|
||||||
|
secs := time.Duration(0)
|
||||||
pts := d.Decode(i)
|
pts := d.Decode(i)
|
||||||
require.Equal(t, time.Duration(0), pts)
|
require.Equal(t, time.Duration(0), pts)
|
||||||
|
|
||||||
// 1st overflow
|
const stride = 150
|
||||||
i += 90000 * 2
|
lim := uint32(uint64(4294967296 - (stride * 90000)))
|
||||||
pts = d.Decode(i)
|
|
||||||
require.Equal(t, 2*time.Second, pts)
|
|
||||||
|
|
||||||
// reach 4294890000 slowly
|
for n := 0; n < 100; n++ {
|
||||||
for ; i < 4294890000; i += 90000 * 10 {
|
// overflow
|
||||||
|
i += 90000 * stride
|
||||||
|
secs += stride
|
||||||
pts = d.Decode(i)
|
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) {
|
func TestOverflowAndBack(t *testing.T) {
|
||||||
|
Reference in New Issue
Block a user