Skip to content

Commit

Permalink
Use time.Ticker in play-from-disk
Browse files Browse the repository at this point in the history
time.Sleep is not precise, instead use a ticker.

Relates to golang/go#44343

Co-authored-by: Twometer <twometer@outlook.de>
  • Loading branch information
ourwarmhouse and Twometer committed Aug 13, 2021
1 parent 99633ae commit 883e653
Show file tree
Hide file tree
Showing 3 changed files with 23 additions and 11 deletions.
9 changes: 6 additions & 3 deletions examples/play-from-disk-renegotation/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -167,15 +167,18 @@ func writeVideoToTrack(t *webrtc.TrackLocalStaticSample) {

// Send our video file frame at a time. Pace our sending so we send it at the same speed it should be played back as.
// This isn't required since the video is timestamped, but we will such much higher loss if we send all at once.
sleepTime := time.Millisecond * time.Duration((float32(header.TimebaseNumerator)/float32(header.TimebaseDenominator))*1000)
for {
//
// It is important to use a time.Ticker instead of time.Sleep because
// * avoids accumulating skew, just calling time.Sleep didn't compensate for the time spent parsing the data
// * works around latency issues with Sleep (see https://github.com/golang/go/issues/44343)
ticker := time.NewTicker(time.Millisecond * time.Duration((float32(header.TimebaseNumerator)/float32(header.TimebaseDenominator))*1000))
for ; true; <-ticker.C {
frame, _, err := ivf.ParseNextFrame()
if err != nil {
fmt.Printf("Finish writing video track: %s ", err)
return
}

time.Sleep(sleepTime)
if err = t.WriteSample(media.Sample{Data: frame, Duration: time.Second}); err != nil {
fmt.Printf("Finish writing video track: %s ", err)
return
Expand Down
2 changes: 2 additions & 0 deletions examples/play-from-disk/README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# play-from-disk
play-from-disk demonstrates how to send video and/or audio to your browser from files saved to disk.

For an example of playing H264 from disk see [play-from-disk-h264](https://github.com/pion/example-webrtc-applications/tree/master/play-from-disk-h264)

## Instructions
### Create IVF named `output.ivf` that contains a VP8 track and/or `output.ogg` that contains a Opus track
```
Expand Down
23 changes: 15 additions & 8 deletions examples/play-from-disk/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,9 @@ import (
)

const (
audioFileName = "output.ogg"
videoFileName = "output.ivf"
audioFileName = "output.ogg"
videoFileName = "output.ivf"
oggPageDuration = time.Millisecond * 20
)

func main() {
Expand Down Expand Up @@ -93,8 +94,12 @@ func main() {

// Send our video file frame at a time. Pace our sending so we send it at the same speed it should be played back as.
// This isn't required since the video is timestamped, but we will such much higher loss if we send all at once.
sleepTime := time.Millisecond * time.Duration((float32(header.TimebaseNumerator)/float32(header.TimebaseDenominator))*1000)
for {
//
// It is important to use a time.Ticker instead of time.Sleep because
// * avoids accumulating skew, just calling time.Sleep didn't compensate for the time spent parsing the data
// * works around latency issues with Sleep (see https://github.com/golang/go/issues/44343)
ticker := time.NewTicker(time.Millisecond * time.Duration((float32(header.TimebaseNumerator)/float32(header.TimebaseDenominator))*1000))
for ; true; <-ticker.C {
frame, _, ivfErr := ivf.ParseNextFrame()
if ivfErr == io.EOF {
fmt.Printf("All video frames parsed and sent")
Expand All @@ -105,7 +110,6 @@ func main() {
panic(ivfErr)
}

time.Sleep(sleepTime)
if ivfErr = videoTrack.WriteSample(media.Sample{Data: frame, Duration: time.Second}); ivfErr != nil {
panic(ivfErr)
}
Expand Down Expand Up @@ -155,7 +159,12 @@ func main() {

// Keep track of last granule, the difference is the amount of samples in the buffer
var lastGranule uint64
for {

// It is important to use a time.Ticker instead of time.Sleep because
// * avoids accumulating skew, just calling time.Sleep didn't compensate for the time spent parsing the data
// * works around latency issues with Sleep (see https://github.com/golang/go/issues/44343)
ticker := time.NewTicker(oggPageDuration)
for ; true; <-ticker.C {
pageData, pageHeader, oggErr := ogg.ParseNextPage()
if oggErr == io.EOF {
fmt.Printf("All audio pages parsed and sent")
Expand All @@ -174,8 +183,6 @@ func main() {
if oggErr = audioTrack.WriteSample(media.Sample{Data: pageData, Duration: sampleDuration}); oggErr != nil {
panic(oggErr)
}

time.Sleep(sampleDuration)
}
}()
}
Expand Down

0 comments on commit 883e653

Please sign in to comment.