From 489ba348dfa9f5e71d84989cd3010ec1206dd9cf Mon Sep 17 00:00:00 2001 From: Sean DuBois Date: Wed, 17 Feb 2021 21:45:01 -0800 Subject: [PATCH] Enable Sender and Receiver Reports by default The play-from-disk examples sees the average bitrate using Chromium 90.0.4412.3 when enabled on loopback for a 3 minute session. Before: 744.443 After: 3927.669 Introduced with pion/interceptor@v0.0.10 --- examples/ice-tcp/main.go | 10 +--------- examples/reflect/main.go | 16 ++++++++++++++-- examples/rtp-forwarder/README.md | 2 ++ examples/rtp-forwarder/main.go | 16 ++++++++++++++-- examples/save-to-disk/main.go | 16 ++++++++++++++-- examples/simulcast/README.md | 5 +++++ examples/simulcast/main.go | 19 +++++++++++++------ go.mod | 2 +- go.sum | 4 ++-- interceptor.go | 22 ++++++++++++++++++++++ 10 files changed, 88 insertions(+), 24 deletions(-) diff --git a/examples/ice-tcp/main.go b/examples/ice-tcp/main.go index e60d0767a5d..105d2912357 100644 --- a/examples/ice-tcp/main.go +++ b/examples/ice-tcp/main.go @@ -18,11 +18,6 @@ func doSignaling(w http.ResponseWriter, r *http.Request) { var err error if peerConnection == nil { - m := webrtc.MediaEngine{} - if err = m.RegisterDefaultCodecs(); err != nil { - panic(err) - } - settingEngine := webrtc.SettingEngine{} // Enable support only for TCP ICE candidates. @@ -46,10 +41,7 @@ func doSignaling(w http.ResponseWriter, r *http.Request) { tcpMux := webrtc.NewICETCPMux(nil, tcpListener, 8) settingEngine.SetICETCPMux(tcpMux) - api := webrtc.NewAPI( - webrtc.WithMediaEngine(&m), - webrtc.WithSettingEngine(settingEngine), - ) + api := webrtc.NewAPI(webrtc.WithSettingEngine(settingEngine)) if peerConnection, err = api.NewPeerConnection(webrtc.Configuration{}); err != nil { panic(err) } diff --git a/examples/reflect/main.go b/examples/reflect/main.go index 66c4749bd1b..0b4766705b6 100644 --- a/examples/reflect/main.go +++ b/examples/reflect/main.go @@ -6,6 +6,7 @@ import ( "fmt" "time" + "github.com/pion/interceptor" "github.com/pion/rtcp" "github.com/pion/webrtc/v3" "github.com/pion/webrtc/v3/examples/internal/signal" @@ -15,7 +16,7 @@ func main() { // Everything below is the Pion WebRTC API! Thanks for using it ❤️. // Create a MediaEngine object to configure the supported codec - m := webrtc.MediaEngine{} + m := &webrtc.MediaEngine{} // Setup the codecs you want to use. // We'll use a VP8 and Opus but you can also define your own @@ -26,8 +27,19 @@ func main() { panic(err) } + // Create a InterceptorRegistry. This is the user configurable RTP/RTCP Pipeline. + // This provides NACKs, RTCP Reports and other features. If you use `webrtc.NewPeerConnection` + // this is enabled by default. If you are manually managing You MUST create a InterceptorRegistry + // for each PeerConnection. + i := &interceptor.Registry{} + + // Use the default set of Interceptors + if err := webrtc.RegisterDefaultInterceptors(m, i); err != nil { + panic(err) + } + // Create the API object with the MediaEngine - api := webrtc.NewAPI(webrtc.WithMediaEngine(&m)) + api := webrtc.NewAPI(webrtc.WithMediaEngine(m), webrtc.WithInterceptorRegistry(i)) // Prepare the configuration config := webrtc.Configuration{ diff --git a/examples/rtp-forwarder/README.md b/examples/rtp-forwarder/README.md index 633bd2638e3..100d9a368b3 100644 --- a/examples/rtp-forwarder/README.md +++ b/examples/rtp-forwarder/README.md @@ -33,5 +33,7 @@ Run `ffprobe -i rtp-forwarder.sdp -protocol_whitelist file,udp,rtp` to get more Run `ffplay -i rtp-forwarder.sdp -protocol_whitelist file,udp,rtp` to play your streams +You can add `-fflags nobuffer` to lower the latency. You will have worse playback in networks with jitter. + #### Twitch/RTMP `ffmpeg -protocol_whitelist file,udp,rtp -i rtp-forwarder.sdp -c:v libx264 -preset veryfast -b:v 3000k -maxrate 3000k -bufsize 6000k -pix_fmt yuv420p -g 50 -c:a aac -b:a 160k -ac 2 -ar 44100 -f flv rtmp://live.twitch.tv/app/$STREAM_KEY` Make sure to replace `$STREAM_KEY` at the end of the URL first. diff --git a/examples/rtp-forwarder/main.go b/examples/rtp-forwarder/main.go index 17a711578aa..a1b6c639878 100644 --- a/examples/rtp-forwarder/main.go +++ b/examples/rtp-forwarder/main.go @@ -8,6 +8,7 @@ import ( "net" "time" + "github.com/pion/interceptor" "github.com/pion/rtcp" "github.com/pion/rtp" "github.com/pion/webrtc/v3" @@ -24,7 +25,7 @@ func main() { // Everything below is the Pion WebRTC API! Thanks for using it ❤️. // Create a MediaEngine object to configure the supported codec - m := webrtc.MediaEngine{} + m := &webrtc.MediaEngine{} // Setup the codecs you want to use. // We'll use a VP8 and Opus but you can also define your own @@ -39,8 +40,19 @@ func main() { panic(err) } + // Create a InterceptorRegistry. This is the user configurable RTP/RTCP Pipeline. + // This provides NACKs, RTCP Reports and other features. If you use `webrtc.NewPeerConnection` + // this is enabled by default. If you are manually managing You MUST create a InterceptorRegistry + // for each PeerConnection. + i := &interceptor.Registry{} + + // Use the default set of Interceptors + if err := webrtc.RegisterDefaultInterceptors(m, i); err != nil { + panic(err) + } + // Create the API object with the MediaEngine - api := webrtc.NewAPI(webrtc.WithMediaEngine(&m)) + api := webrtc.NewAPI(webrtc.WithMediaEngine(m), webrtc.WithInterceptorRegistry(i)) // Prepare the configuration config := webrtc.Configuration{ diff --git a/examples/save-to-disk/main.go b/examples/save-to-disk/main.go index 38524aac139..c2b68c83250 100644 --- a/examples/save-to-disk/main.go +++ b/examples/save-to-disk/main.go @@ -8,6 +8,7 @@ import ( "strings" "time" + "github.com/pion/interceptor" "github.com/pion/rtcp" "github.com/pion/webrtc/v3" "github.com/pion/webrtc/v3/examples/internal/signal" @@ -38,7 +39,7 @@ func main() { // Everything below is the Pion WebRTC API! Thanks for using it ❤️. // Create a MediaEngine object to configure the supported codec - m := webrtc.MediaEngine{} + m := &webrtc.MediaEngine{} // Setup the codecs you want to use. // We'll use a VP8 and Opus but you can also define your own @@ -55,8 +56,19 @@ func main() { panic(err) } + // Create a InterceptorRegistry. This is the user configurable RTP/RTCP Pipeline. + // This provides NACKs, RTCP Reports and other features. If you use `webrtc.NewPeerConnection` + // this is enabled by default. If you are manually managing You MUST create a InterceptorRegistry + // for each PeerConnection. + i := &interceptor.Registry{} + + // Use the default set of Interceptors + if err := webrtc.RegisterDefaultInterceptors(m, i); err != nil { + panic(err) + } + // Create the API object with the MediaEngine - api := webrtc.NewAPI(webrtc.WithMediaEngine(&m)) + api := webrtc.NewAPI(webrtc.WithMediaEngine(m), webrtc.WithInterceptorRegistry(i)) // Prepare the configuration config := webrtc.Configuration{ diff --git a/examples/simulcast/README.md b/examples/simulcast/README.md index a19ddd04133..d48bf11b869 100644 --- a/examples/simulcast/README.md +++ b/examples/simulcast/README.md @@ -1,9 +1,14 @@ # simulcast demonstrates of how to handle incoming track with multiple simulcast rtp streams and show all them back. +The browser will not send higher quality streams unless it has the available bandwidth. You can look at +the bandwidth estimation in `chrome://webrtc-internals`. It is under `VideoBwe` when `Read Stats From: Legacy non-Standard` +is selected. + ## Instructions ### Download simulcast ``` +export GO111MODULE=on go get github.com/pion/webrtc/v3/examples/simulcast ``` diff --git a/examples/simulcast/main.go b/examples/simulcast/main.go index e16d530fbd2..b81b5c56b96 100644 --- a/examples/simulcast/main.go +++ b/examples/simulcast/main.go @@ -8,6 +8,7 @@ import ( "io" "time" + "github.com/pion/interceptor" "github.com/pion/rtcp" "github.com/pion/webrtc/v3" "github.com/pion/webrtc/v3/examples/internal/signal" @@ -40,8 +41,19 @@ func main() { } } + // Create a InterceptorRegistry. This is the user configurable RTP/RTCP Pipeline. + // This provides NACKs, RTCP Reports and other features. If you use `webrtc.NewPeerConnection` + // this is enabled by default. If you are manually managing You MUST create a InterceptorRegistry + // for each PeerConnection. + i := &interceptor.Registry{} + + // Use the default set of Interceptors + if err := webrtc.RegisterDefaultInterceptors(m, i); err != nil { + panic(err) + } + // Create a new RTCPeerConnection - peerConnection, err := webrtc.NewAPI(webrtc.WithMediaEngine(m)).NewPeerConnection(config) + peerConnection, err := webrtc.NewAPI(webrtc.WithMediaEngine(m), webrtc.WithInterceptorRegistry(i)).NewPeerConnection(config) if err != nil { panic(err) } @@ -114,11 +126,6 @@ func main() { if writeErr := peerConnection.WriteRTCP([]rtcp.Packet{&rtcp.PictureLossIndication{MediaSSRC: uint32(track.SSRC())}}); writeErr != nil { fmt.Println(writeErr) } - // Send a remb message with a very high bandwidth to trigger chrome to send also the high bitrate stream - fmt.Printf("Sending remb for stream with rid: %q, ssrc: %d\n", track.RID(), track.SSRC()) - if writeErr := peerConnection.WriteRTCP([]rtcp.Packet{&rtcp.ReceiverEstimatedMaximumBitrate{Bitrate: 10000000, SenderSSRC: uint32(track.SSRC())}}); writeErr != nil { - fmt.Println(writeErr) - } } }() for { diff --git a/go.mod b/go.mod index a7c950a85f5..648fadd3798 100644 --- a/go.mod +++ b/go.mod @@ -8,7 +8,7 @@ require ( github.com/pion/datachannel v1.4.21 github.com/pion/dtls/v2 v2.0.7 github.com/pion/ice/v2 v2.0.15 - github.com/pion/interceptor v0.0.9 + github.com/pion/interceptor v0.0.10 github.com/pion/logging v0.2.2 github.com/pion/randutil v0.1.0 github.com/pion/rtcp v1.2.6 diff --git a/go.sum b/go.sum index 5885157594b..4df561b35db 100644 --- a/go.sum +++ b/go.sum @@ -42,8 +42,8 @@ github.com/pion/dtls/v2 v2.0.7 h1:PNcUs/G1l9hb4jzMEorgFMxIBdp7fRN4LIApOTMtCYs= github.com/pion/dtls/v2 v2.0.7/go.mod h1:QuDII+8FVvk9Dp5t5vYIMTo7hh7uBkra+8QIm7QGm10= github.com/pion/ice/v2 v2.0.15 h1:KZrwa2ciL9od8+TUVJiYTNsCW9J5lktBjGwW1MacEnQ= github.com/pion/ice/v2 v2.0.15/go.mod h1:ZIiVGevpgAxF/cXiIVmuIUtCb3Xs4gCzCbXB6+nFkSI= -github.com/pion/interceptor v0.0.9 h1:fk5hTdyLO3KURQsf/+RjMpEm4NE3yeTY9Kh97b5BvwA= -github.com/pion/interceptor v0.0.9/go.mod h1:dHgEP5dtxOTf21MObuBAjJeAayPxLUAZjerGH8Xr07c= +github.com/pion/interceptor v0.0.10 h1:dXFyFWRJFwmzQqyn0U8dUAbOJu+JJnMVAqxmvTu30B4= +github.com/pion/interceptor v0.0.10/go.mod h1:qzeuWuD/ZXvPqOnxNcnhWfkCZ2e1kwwslicyyPnhoK4= github.com/pion/logging v0.2.2 h1:M9+AIj/+pxNsDfAT64+MAVgJO0rsyLnoJKCqf//DoeY= github.com/pion/logging v0.2.2/go.mod h1:k0/tDVsRCX2Mb2ZEmTqNa7CWsQPc+YYCB7Q+5pahoms= github.com/pion/mdns v0.0.4 h1:O4vvVqr4DGX63vzmO6Fw9vpy3lfztVWHGCQfyw0ZLSY= diff --git a/interceptor.go b/interceptor.go index d76793b99b2..eff94962d84 100644 --- a/interceptor.go +++ b/interceptor.go @@ -7,6 +7,7 @@ import ( "github.com/pion/interceptor" "github.com/pion/interceptor/pkg/nack" + "github.com/pion/interceptor/pkg/report" "github.com/pion/rtp" ) @@ -18,6 +19,27 @@ func RegisterDefaultInterceptors(mediaEngine *MediaEngine, interceptorRegistry * return err } + if err := ConfigureRTCPReports(interceptorRegistry); err != nil { + return err + } + + return nil +} + +// ConfigureRTCPReports will setup everything necessary for generating Sender and Receiver Reports +func ConfigureRTCPReports(interceptorRegistry *interceptor.Registry) error { + reciver, err := report.NewReceiverInterceptor() + if err != nil { + return err + } + + sender, err := report.NewSenderInterceptor() + if err != nil { + return err + } + + interceptorRegistry.Add(reciver) + interceptorRegistry.Add(sender) return nil }