diff --git a/examples/broadcast/main.go b/examples/broadcast/main.go index 2ca9c00d..147679bf 100644 --- a/examples/broadcast/main.go +++ b/examples/broadcast/main.go @@ -8,17 +8,13 @@ import ( "errors" "fmt" "io" - "time" - "github.com/pion/rtcp" + "github.com/pion/interceptor" + "github.com/pion/interceptor/pkg/intervalpli" "github.com/pion/webrtc/v3" "github.com/pion/webrtc/v3/examples/internal/signal" ) -const ( - rtcpPLIInterval = time.Second * 3 -) - func main() { // nolint:gocognit sdpChan := signal.HTTPSDPServer() @@ -35,8 +31,34 @@ func main() { // nolint:gocognit }, } + m := &webrtc.MediaEngine{} + if err := m.RegisterDefaultCodecs(); err != nil { + 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) + } + + // Register a intervalpli factory + // This interceptor sends a PLI every 3 seconds. A PLI causes a video keyframe to be generated by the sender. + // This makes our video seekable and more error resilent, but at a cost of lower picture quality and higher bitrates + // A real world application should process incoming RTCP packets from viewers and forward them to senders + intervalPliFactory, err := intervalpli.NewReceiverInterceptor() + if err != nil { + panic(err) + } + i.Add(intervalPliFactory) + // Create a new RTCPeerConnection - peerConnection, err := webrtc.NewPeerConnection(peerConnectionConfig) + peerConnection, err := webrtc.NewAPI(webrtc.WithMediaEngine(m), webrtc.WithInterceptorRegistry(i)).NewPeerConnection(peerConnectionConfig) if err != nil { panic(err) } @@ -55,17 +77,6 @@ func main() { // nolint:gocognit // Set a handler for when a new remote track starts, this just distributes all our packets // to connected peers peerConnection.OnTrack(func(remoteTrack *webrtc.TrackRemote, receiver *webrtc.RTPReceiver) { - // Send a PLI on an interval so that the publisher is pushing a keyframe every rtcpPLIInterval - // This can be less wasteful by processing incoming RTCP events, then we would emit a NACK/PLI when a viewer requests it - go func() { - ticker := time.NewTicker(rtcpPLIInterval) - for range ticker.C { - if rtcpSendErr := peerConnection.WriteRTCP([]rtcp.Packet{&rtcp.PictureLossIndication{MediaSSRC: uint32(remoteTrack.SSRC())}}); rtcpSendErr != nil { - fmt.Println(rtcpSendErr) - } - } - }() - // Create a local track, all our SFU clients will be fed via this track localTrack, newTrackErr := webrtc.NewTrackLocalStaticRTP(remoteTrack.Codec().RTPCodecCapability, "video", "pion") if newTrackErr != nil { diff --git a/examples/reflect/main.go b/examples/reflect/main.go index 6fd5ddcd..99f93254 100644 --- a/examples/reflect/main.go +++ b/examples/reflect/main.go @@ -7,10 +7,9 @@ package main import ( "fmt" "os" - "time" "github.com/pion/interceptor" - "github.com/pion/rtcp" + "github.com/pion/interceptor/pkg/intervalpli" "github.com/pion/webrtc/v3" "github.com/pion/webrtc/v3/examples/internal/signal" ) @@ -42,6 +41,16 @@ func main() { panic(err) } + // Register a intervalpli factory + // This interceptor sends a PLI every 3 seconds. A PLI causes a video keyframe to be generated by the sender. + // This makes our video seekable and more error resilent, but at a cost of lower picture quality and higher bitrates + // A real world application should process incoming RTCP packets from viewers and forward them to senders + intervalPliFactory, err := intervalpli.NewReceiverInterceptor() + if err != nil { + panic(err) + } + i.Add(intervalPliFactory) + // Create the API object with the MediaEngine api := webrtc.NewAPI(webrtc.WithMediaEngine(m), webrtc.WithInterceptorRegistry(i)) @@ -101,18 +110,6 @@ func main() { // Set a handler for when a new remote track starts, this handler copies inbound RTP packets, // replaces the SSRC and sends them back peerConnection.OnTrack(func(track *webrtc.TrackRemote, receiver *webrtc.RTPReceiver) { - // Send a PLI on an interval so that the publisher is pushing a keyframe every rtcpPLIInterval - // This is a temporary fix until we implement incoming RTCP events, then we would push a PLI only when a viewer requests it - go func() { - ticker := time.NewTicker(time.Second * 3) - for range ticker.C { - errSend := peerConnection.WriteRTCP([]rtcp.Packet{&rtcp.PictureLossIndication{MediaSSRC: uint32(track.SSRC())}}) - if errSend != nil { - fmt.Println(errSend) - } - } - }() - fmt.Printf("Track has started, of type %d: %s \n", track.PayloadType(), track.Codec().MimeType) for { // Read RTP packets being sent to Pion diff --git a/examples/rtp-forwarder/main.go b/examples/rtp-forwarder/main.go index 992e28ae..221cf2a7 100644 --- a/examples/rtp-forwarder/main.go +++ b/examples/rtp-forwarder/main.go @@ -9,10 +9,9 @@ import ( "fmt" "net" "os" - "time" "github.com/pion/interceptor" - "github.com/pion/rtcp" + "github.com/pion/interceptor/pkg/intervalpli" "github.com/pion/rtp" "github.com/pion/webrtc/v3" "github.com/pion/webrtc/v3/examples/internal/signal" @@ -50,8 +49,18 @@ func main() { // for each PeerConnection. i := &interceptor.Registry{} + // Register a intervalpli factory + // This interceptor sends a PLI every 3 seconds. A PLI causes a video keyframe to be generated by the sender. + // This makes our video seekable and more error resilent, but at a cost of lower picture quality and higher bitrates + // A real world application should process incoming RTCP packets from viewers and forward them to senders + intervalPliFactory, err := intervalpli.NewReceiverInterceptor() + if err != nil { + panic(err) + } + i.Add(intervalPliFactory) + // Use the default set of Interceptors - if err := webrtc.RegisterDefaultInterceptors(m, i); err != nil { + if err = webrtc.RegisterDefaultInterceptors(m, i); err != nil { panic(err) } @@ -126,16 +135,6 @@ func main() { return } - // Send a PLI on an interval so that the publisher is pushing a keyframe every rtcpPLIInterval - go func() { - ticker := time.NewTicker(time.Second * 2) - for range ticker.C { - if rtcpErr := peerConnection.WriteRTCP([]rtcp.Packet{&rtcp.PictureLossIndication{MediaSSRC: uint32(track.SSRC())}}); rtcpErr != nil { - fmt.Println(rtcpErr) - } - } - }() - b := make([]byte, 1500) rtpPacket := &rtp.Packet{} for { diff --git a/examples/save-to-disk-av1/main.go b/examples/save-to-disk-av1/main.go index 73b45076..72432851 100644 --- a/examples/save-to-disk-av1/main.go +++ b/examples/save-to-disk-av1/main.go @@ -8,10 +8,9 @@ import ( "fmt" "os" "strings" - "time" "github.com/pion/interceptor" - "github.com/pion/rtcp" + "github.com/pion/interceptor/pkg/intervalpli" "github.com/pion/webrtc/v3" "github.com/pion/webrtc/v3/examples/internal/signal" "github.com/pion/webrtc/v3/pkg/media" @@ -57,8 +56,18 @@ func main() { // for each PeerConnection. i := &interceptor.Registry{} + // Register a intervalpli factory + // This interceptor sends a PLI every 3 seconds. A PLI causes a video keyframe to be generated by the sender. + // This makes our video seekable and more error resilent, but at a cost of lower picture quality and higher bitrates + // A real world application should process incoming RTCP packets from viewers and forward them to senders + intervalPliFactory, err := intervalpli.NewReceiverInterceptor() + if err != nil { + panic(err) + } + i.Add(intervalPliFactory) + // Use the default set of Interceptors - if err := webrtc.RegisterDefaultInterceptors(m, i); err != nil { + if err = webrtc.RegisterDefaultInterceptors(m, i); err != nil { panic(err) } @@ -88,17 +97,6 @@ func main() { // an ivf file, since we could have multiple video tracks we provide a counter. // In your application this is where you would handle/process video peerConnection.OnTrack(func(track *webrtc.TrackRemote, receiver *webrtc.RTPReceiver) { - // Send a PLI on an interval so that the publisher is pushing a keyframe every rtcpPLIInterval - go func() { - ticker := time.NewTicker(time.Second * 3) - for range ticker.C { - errSend := peerConnection.WriteRTCP([]rtcp.Packet{&rtcp.PictureLossIndication{MediaSSRC: uint32(track.SSRC())}}) - if errSend != nil { - fmt.Println(errSend) - } - } - }() - if strings.EqualFold(track.Codec().MimeType, webrtc.MimeTypeAV1) { fmt.Println("Got AV1 track, saving to disk as output.ivf") saveToDisk(ivfFile, track) diff --git a/examples/save-to-disk/main.go b/examples/save-to-disk/main.go index 5075ac9b..ae1ae3d1 100644 --- a/examples/save-to-disk/main.go +++ b/examples/save-to-disk/main.go @@ -8,10 +8,9 @@ import ( "fmt" "os" "strings" - "time" "github.com/pion/interceptor" - "github.com/pion/rtcp" + "github.com/pion/interceptor/pkg/intervalpli" "github.com/pion/webrtc/v3" "github.com/pion/webrtc/v3/examples/internal/signal" "github.com/pion/webrtc/v3/pkg/media" @@ -65,8 +64,18 @@ func main() { // for each PeerConnection. i := &interceptor.Registry{} + // Register a intervalpli factory + // This interceptor sends a PLI every 3 seconds. A PLI causes a video keyframe to be generated by the sender. + // This makes our video seekable and more error resilent, but at a cost of lower picture quality and higher bitrates + // A real world application should process incoming RTCP packets from viewers and forward them to senders + intervalPliFactory, err := intervalpli.NewReceiverInterceptor() + if err != nil { + panic(err) + } + i.Add(intervalPliFactory) + // Use the default set of Interceptors - if err := webrtc.RegisterDefaultInterceptors(m, i); err != nil { + if err = webrtc.RegisterDefaultInterceptors(m, i); err != nil { panic(err) } @@ -108,17 +117,6 @@ func main() { // an ivf file, since we could have multiple video tracks we provide a counter. // In your application this is where you would handle/process video peerConnection.OnTrack(func(track *webrtc.TrackRemote, receiver *webrtc.RTPReceiver) { - // Send a PLI on an interval so that the publisher is pushing a keyframe every rtcpPLIInterval - go func() { - ticker := time.NewTicker(time.Second * 3) - for range ticker.C { - errSend := peerConnection.WriteRTCP([]rtcp.Packet{&rtcp.PictureLossIndication{MediaSSRC: uint32(track.SSRC())}}) - if errSend != nil { - fmt.Println(errSend) - } - } - }() - codec := track.Codec() if strings.EqualFold(codec.MimeType, webrtc.MimeTypeOpus) { fmt.Println("Got Opus track, saving to disk as output.opus (48 kHz, 2 channels)") diff --git a/go.mod b/go.mod index a71d1068..d27029c1 100644 --- a/go.mod +++ b/go.mod @@ -8,7 +8,7 @@ require ( github.com/pion/datachannel v1.5.5 github.com/pion/dtls/v2 v2.2.6 github.com/pion/ice/v2 v2.3.2 - github.com/pion/interceptor v0.1.14 + github.com/pion/interceptor v0.1.15 github.com/pion/logging v0.2.2 github.com/pion/randutil v0.1.0 github.com/pion/rtcp v1.2.10 diff --git a/go.sum b/go.sum index e54d83e1..6d98760b 100644 --- a/go.sum +++ b/go.sum @@ -46,8 +46,8 @@ github.com/pion/dtls/v2 v2.2.6 h1:yXMxKr0Skd+Ub6A8UqXTRLSywskx93ooMRHsQUtd+Z4= github.com/pion/dtls/v2 v2.2.6/go.mod h1:t8fWJCIquY5rlQZwA2yWxUS1+OCrAdXrhVKXB5oD/wY= github.com/pion/ice/v2 v2.3.2 h1:vh+fi4RkZ8H5fB4brZ/jm3j4BqFgMmNs+aB3X52Hu7M= github.com/pion/ice/v2 v2.3.2/go.mod h1:AMIpuJqcpe+UwloocNebmTSWhCZM1TUCo9v7nW50jX0= -github.com/pion/interceptor v0.1.14 h1:066aWutplETQ6I/jxMwECPgAkP9nQC1IsqVqu9KlFtg= -github.com/pion/interceptor v0.1.14/go.mod h1:SY8kpmfVBvrbUzvj2bsXz7OJt5JvmVNZ+4Kjq7FcwrI= +github.com/pion/interceptor v0.1.15 h1:vBjnKoSqcNYg2Xq3kz/2m7qp57c0yVH0n/2HJ2rP0hQ= +github.com/pion/interceptor v0.1.15/go.mod h1:SY8kpmfVBvrbUzvj2bsXz7OJt5JvmVNZ+4Kjq7FcwrI= 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.7 h1:P0UB4Sr6xDWEox0kTVxF0LmQihtCbSAdW0H2nEgkA3U=