-
Notifications
You must be signed in to change notification settings - Fork 1.6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
hls client: skip packets received before the 1st packet of the leading
track; make sure that the initial DTS is zero
- Loading branch information
Showing
6 changed files
with
130 additions
and
142 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
// Package mpegtstimedec contains a MPEG-TS timestamp decoder. | ||
package mpegtstimedec | ||
|
||
import ( | ||
"time" | ||
) | ||
|
||
const ( | ||
maximum = 0x1FFFFFFFF // 33 bits | ||
negativeThreshold = 0x1FFFFFFFF / 2 | ||
clockRate = 90000 | ||
) | ||
|
||
// Decoder is a MPEG-TS timestamp decoder. | ||
type Decoder struct { | ||
overall time.Duration | ||
prev int64 | ||
} | ||
|
||
// New allocates a Decoder. | ||
func New(start int64) *Decoder { | ||
return &Decoder{ | ||
prev: start, | ||
} | ||
} | ||
|
||
// Decode decodes a MPEG-TS timestamp. | ||
func (d *Decoder) Decode(ts int64) time.Duration { | ||
diff := (ts - d.prev) & maximum | ||
|
||
// negative difference | ||
if diff > negativeThreshold { | ||
diff = (d.prev - ts) & maximum | ||
d.prev = ts | ||
d.overall -= time.Duration(diff) | ||
} else { | ||
d.prev = ts | ||
d.overall += time.Duration(diff) | ||
} | ||
|
||
// avoid an int64 overflow and preserve resolution by splitting division into two parts: | ||
// first add the integer part, then the decimal part. | ||
secs := d.overall / clockRate | ||
dec := d.overall % clockRate | ||
return secs*time.Second + dec*time.Second/clockRate | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
package mpegtstimedec | ||
|
||
import ( | ||
"testing" | ||
"time" | ||
|
||
"github.com/stretchr/testify/require" | ||
) | ||
|
||
func TestNegativeDiff(t *testing.T) { | ||
d := New(64523434) | ||
|
||
ts := d.Decode(64523434 - 90000) | ||
require.Equal(t, -1*time.Second, ts) | ||
|
||
ts = d.Decode(64523434) | ||
require.Equal(t, time.Duration(0), ts) | ||
|
||
ts = d.Decode(64523434 + 90000*2) | ||
require.Equal(t, 2*time.Second, ts) | ||
|
||
ts = d.Decode(64523434 + 90000) | ||
require.Equal(t, 1*time.Second, ts) | ||
} | ||
|
||
func TestOverflow(t *testing.T) { | ||
d := New(0x1FFFFFFFF - 20) | ||
|
||
i := int64(0x1FFFFFFFF - 20) | ||
secs := time.Duration(0) | ||
const stride = 150 | ||
lim := int64(uint64(0x1FFFFFFFF - (stride * 90000))) | ||
|
||
for n := 0; n < 100; n++ { | ||
// overflow | ||
i += 90000 * stride | ||
secs += stride | ||
ts := d.Decode(i) | ||
require.Equal(t, secs*time.Second, ts) | ||
|
||
// reach 2^32 slowly | ||
secs += stride | ||
i += 90000 * stride | ||
for ; i < lim; i += 90000 * stride { | ||
ts = d.Decode(i) | ||
require.Equal(t, secs*time.Second, ts) | ||
secs += stride | ||
} | ||
} | ||
} | ||
|
||
func TestOverflowAndBack(t *testing.T) { | ||
d := New(0x1FFFFFFFF - 90000 + 1) | ||
|
||
ts := d.Decode(0x1FFFFFFFF - 90000 + 1) | ||
require.Equal(t, time.Duration(0), ts) | ||
|
||
ts = d.Decode(90000) | ||
require.Equal(t, 2*time.Second, ts) | ||
|
||
ts = d.Decode(0x1FFFFFFFF - 90000 + 1) | ||
require.Equal(t, time.Duration(0), ts) | ||
|
||
ts = d.Decode(0x1FFFFFFFF - 90000*2 + 1) | ||
require.Equal(t, -1*time.Second, ts) | ||
|
||
ts = d.Decode(0x1FFFFFFFF - 90000 + 1) | ||
require.Equal(t, time.Duration(0), ts) | ||
|
||
ts = d.Decode(90000) | ||
require.Equal(t, 2*time.Second, ts) | ||
} |