mirror of
https://github.com/pion/mediadevices.git
synced 2025-09-26 20:41:46 +08:00
Fix bitrate measurement stability
- improve accuracy of bitrate calculation - reduce test input timing error
This commit is contained in:

committed by
Lukas Herman

parent
6471064956
commit
305b7086e3
@@ -11,12 +11,15 @@ import (
|
||||
func MeasureBitRate(r io.Reader, dur time.Duration) (float64, error) {
|
||||
var n, totalBytes int
|
||||
var err error
|
||||
|
||||
buf := make([]byte, 1024)
|
||||
start := time.Now()
|
||||
now := start
|
||||
end := now.Add(dur)
|
||||
for now.Before(end) {
|
||||
for {
|
||||
n, err = r.Read(buf)
|
||||
now = time.Now()
|
||||
|
||||
if err != nil {
|
||||
if e, ok := err.(*mio.InsufficientBufferError); ok {
|
||||
buf = make([]byte, 2*e.RequiredSize)
|
||||
@@ -24,6 +27,7 @@ func MeasureBitRate(r io.Reader, dur time.Duration) (float64, error) {
|
||||
}
|
||||
|
||||
if err == io.EOF {
|
||||
dur = now.Sub(start)
|
||||
totalBytes += n
|
||||
break
|
||||
}
|
||||
@@ -31,11 +35,12 @@ func MeasureBitRate(r io.Reader, dur time.Duration) (float64, error) {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
totalBytes += n
|
||||
now = time.Now()
|
||||
if now.After(end) {
|
||||
break
|
||||
}
|
||||
totalBytes += n // count bytes if the data arrived within the period
|
||||
}
|
||||
|
||||
elapsed := time.Now().Sub(start).Seconds()
|
||||
avg := float64(totalBytes*8) / elapsed
|
||||
avg := float64(totalBytes*8) / dur.Seconds()
|
||||
return avg, nil
|
||||
}
|
||||
|
@@ -9,18 +9,25 @@ import (
|
||||
|
||||
func TestMeasureBitRateStatic(t *testing.T) {
|
||||
r, w := io.Pipe()
|
||||
dur := time.Second * 5
|
||||
dataSize := 1000
|
||||
var precision float64 = 8 // 1 byte
|
||||
const (
|
||||
dataSize = 1000
|
||||
dur = 5 * time.Second
|
||||
packetInterval = time.Second
|
||||
precision = 8.0 // 1 byte
|
||||
)
|
||||
var wg sync.WaitGroup
|
||||
wg.Add(1)
|
||||
done := make(chan struct{})
|
||||
|
||||
go func() {
|
||||
data := make([]byte, dataSize)
|
||||
ticker := time.NewTicker(packetInterval)
|
||||
|
||||
// Wait half interval
|
||||
time.Sleep(packetInterval / 2)
|
||||
|
||||
// Make sure that this goroutine is synchronized with main goroutine
|
||||
wg.Done()
|
||||
ticker := time.NewTicker(time.Second)
|
||||
|
||||
for {
|
||||
select {
|
||||
@@ -48,30 +55,34 @@ func TestMeasureBitRateStatic(t *testing.T) {
|
||||
|
||||
func TestMeasureBitRateDynamic(t *testing.T) {
|
||||
r, w := io.Pipe()
|
||||
dur := time.Second * 5
|
||||
dataSize := 1000
|
||||
var precision float64 = 8 // 1 byte
|
||||
const (
|
||||
dataSize = 1000
|
||||
dur = 5 * time.Second
|
||||
packetInterval = time.Millisecond * 250
|
||||
precision = 8.0 // 1 byte
|
||||
)
|
||||
var wg sync.WaitGroup
|
||||
wg.Add(1)
|
||||
done := make(chan struct{})
|
||||
|
||||
go func() {
|
||||
data := make([]byte, dataSize)
|
||||
wg.Done()
|
||||
ticker := time.NewTicker(time.Millisecond * 500)
|
||||
var count int
|
||||
ticker := time.NewTicker(packetInterval)
|
||||
|
||||
// Wait half interval
|
||||
time.Sleep(packetInterval / 2)
|
||||
|
||||
wg.Done()
|
||||
|
||||
var count int
|
||||
for {
|
||||
select {
|
||||
case <-ticker.C:
|
||||
w.Write(data)
|
||||
count++
|
||||
// Wait until 4 slow ticks, which is also equal to 2 seconds
|
||||
if count == 4 {
|
||||
ticker.Stop()
|
||||
// Speed up the tick by 2 times for the rest
|
||||
ticker = time.NewTicker(time.Millisecond * 250)
|
||||
// 4 x 500ms ticks and 250ms ticks
|
||||
if count%2 == 1 || count >= 8 {
|
||||
w.Write(data)
|
||||
}
|
||||
count++
|
||||
case <-done:
|
||||
w.Close()
|
||||
return
|
||||
|
Reference in New Issue
Block a user