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