diff --git a/pkg/rtptimedec/decoder.go b/pkg/rtptimedec/decoder.go index 2949e6ac..1220d338 100644 --- a/pkg/rtptimedec/decoder.go +++ b/pkg/rtptimedec/decoder.go @@ -22,17 +22,24 @@ func New(clockRate int) *Decoder { // Decode decodes a RTP timestamp. func (d *Decoder) Decode(ts uint32) time.Duration { - ts64 := int64(ts) + d.tsAdd + ts64 := int64(ts) - if d.tsPrev != nil && (ts64-*d.tsPrev) < -0xFFFF { - ts64 += 0xFFFFFFFF - d.tsAdd += 0xFFFFFFFF + if d.tsPrev != nil { + diff := ts64 - *d.tsPrev + switch { + case diff < -0xFFFFFF: // overflow + d.tsAdd += 0xFFFFFFFF + + case diff > 0xFFFFFF: // timestamp overflowed then went back + d.tsAdd -= 0xFFFFFFFF + } } + d.tsPrev = &ts64 if d.tsInitial == nil { d.tsInitial = &ts64 } - return time.Duration(ts64-*d.tsInitial) * time.Second / d.clockRate + return time.Duration(ts64+d.tsAdd-*d.tsInitial) * time.Second / d.clockRate } diff --git a/pkg/rtptimedec/decoder_test.go b/pkg/rtptimedec/decoder_test.go index 395f9f23..df174233 100644 --- a/pkg/rtptimedec/decoder_test.go +++ b/pkg/rtptimedec/decoder_test.go @@ -9,16 +9,32 @@ import ( func TestOverflow(t *testing.T) { d := New(90000) - var pts time.Duration - for _, ts := range []uint32{ - 4294877296, - 90001, - 3240090001, - 565122706, - } { - pts = d.Decode(ts) - } + pts := d.Decode(4294877295) + require.Equal(t, time.Duration(0), pts) - require.Equal(t, 15*60*60*time.Second+2*time.Second, pts) + pts = d.Decode(90000) + require.Equal(t, 2*time.Second, pts) +} + +func TestOverflowAndBack(t *testing.T) { + d := New(90000) + + pts := d.Decode(4294877296) + require.Equal(t, time.Duration(0), pts) + + pts = d.Decode(90001) + require.Equal(t, 2*time.Second, pts) + + pts = d.Decode(4294877296) + require.Equal(t, time.Duration(0), pts) + + pts = d.Decode(4294877296 - 90000) + require.Equal(t, -1*time.Second, pts) + + pts = d.Decode(4294877296) + require.Equal(t, time.Duration(0), pts) + + pts = d.Decode(90001) + require.Equal(t, 2*time.Second, pts) }