diff --git a/examples/bandwidth-estimation-from-disk/main.go b/examples/bandwidth-estimation-from-disk/main.go index 39aa35bc720..024a1c8b401 100644 --- a/examples/bandwidth-estimation-from-disk/main.go +++ b/examples/bandwidth-estimation-from-disk/main.go @@ -64,40 +64,40 @@ func main() { panic(err) } - // Create a Congestion Controller. This analyzes inbound and outbound data and provides - // suggestions on how much we should be sending. - // - // Passing `nil` means we use the default Estimation Algorithm which is Google Congestion Control. - // You can use the other ones that Pion provides, or write your own! - congestionController, err := cc.NewInterceptor(func() (cc.BandwidthEstimator, error) { - return gcc.NewSendSideBWE(gcc.SendSideBWEInitialBitrate(lowBitrate)) - }) - if err != nil { + if err := webrtc.ConfigureTWCCHeaderExtensionSender(m, i); err != nil { panic(err) } - estimatorChan := make(chan cc.BandwidthEstimator, 1) - congestionController.OnNewPeerConnection(func(id string, estimator cc.BandwidthEstimator) { //nolint: revive - estimatorChan <- estimator - }) - - i.Add(congestionController) - if err = webrtc.ConfigureTWCCHeaderExtensionSender(m, i); err != nil { + if err := webrtc.RegisterDefaultInterceptors(m, i); err != nil { panic(err) } - if err = webrtc.RegisterDefaultInterceptors(m, i); err != nil { + api := webrtc.NewAPI( + webrtc.WithInterceptorRegistry(i), webrtc.WithMediaEngine(m), + ) + + estimator, err := gcc.NewSendSideBWE( + gcc.SendSideBWEInitialBitrate(lowBitrate), + ) + if err != nil { panic(err) } - - // Create a new RTCPeerConnection - peerConnection, err := webrtc.NewAPI(webrtc.WithInterceptorRegistry(i), webrtc.WithMediaEngine(m)).NewPeerConnection(webrtc.Configuration{ + interceptor, err := cc.NewSingleInterceptor(estimator) + if err != nil { + panic(err) + } + configuration := webrtc.Configuration{ ICEServers: []webrtc.ICEServer{ { URLs: []string{"stun:stun.l.google.com:19302"}, }, }, - }) + } + + peerConnection, err := api.NewPeerConnection( + configuration, + webrtc.WithInterceptor(interceptor), + ) if err != nil { panic(err) } @@ -107,9 +107,6 @@ func main() { } }() - // Wait until our Bandwidth Estimator has been created - estimator := <-estimatorChan - // Create a video track videoTrack, err := webrtc.NewTrackLocalStaticSample(webrtc.RTPCodecCapability{MimeType: webrtc.MimeTypeVP8}, "video", "pion") if err != nil { diff --git a/peerconnection.go b/peerconnection.go index 5e613c224cc..3e8764afc8f 100644 --- a/peerconnection.go +++ b/peerconnection.go @@ -91,6 +91,8 @@ type PeerConnection struct { log logging.LeveledLogger interceptorRTCPWriter interceptor.RTCPWriter + + extraInterceptors []interceptor.Interceptor } // NewPeerConnection creates a PeerConnection with the default codecs and interceptors. @@ -98,9 +100,9 @@ type PeerConnection struct { // If you wish to customize the set of available codecs and/or the set of active interceptors, // create an API with a custom MediaEngine and/or interceptor.Registry, // then call [(*API).NewPeerConnection] instead of this function. -func NewPeerConnection(configuration Configuration) (*PeerConnection, error) { +func NewPeerConnection(configuration Configuration, options... func (*PeerConnection) error) (*PeerConnection, error) { api := NewAPI() - return api.NewPeerConnection(configuration) + return api.NewPeerConnection(configuration, options...) } // NewPeerConnection creates a new PeerConnection with the provided configuration against the received API object. @@ -108,7 +110,7 @@ func NewPeerConnection(configuration Configuration) (*PeerConnection, error) { // the resulting PeerConnection. If this behavior is not desired, // set the set of codecs and interceptors explicitly by using // [WithMediaEngine] and [WithInterceptorRegistry] when calling [NewAPI]. -func (api *API) NewPeerConnection(configuration Configuration) (*PeerConnection, error) { +func (api *API) NewPeerConnection(configuration Configuration, options... func (*PeerConnection) error) (*PeerConnection, error) { // https://w3c.github.io/webrtc-pc/#constructor (Step #2) // Some variables defined explicitly despite their implicit zero values to // allow better readability to understand what is happening. @@ -136,12 +138,20 @@ func (api *API) NewPeerConnection(configuration Configuration) (*PeerConnection, api: api, log: api.settingEngine.LoggerFactory.NewLogger("pc"), } + + for _, option := range options { + err := option(pc) + if err != nil { + return nil, err + } + } + pc.ops = newOperations(pc.updateNegotiationNeededFlagOnEmptyChain, pc.onNegotiationNeeded) pc.iceConnectionState.Store(ICEConnectionStateNew) pc.connectionState.Store(PeerConnectionStateNew) - i, err := api.interceptorRegistry.Build("") + i, err := api.interceptorRegistry.Build("", pc.extraInterceptors...) if err != nil { return nil, err } @@ -195,6 +205,13 @@ func (api *API) NewPeerConnection(configuration Configuration) (*PeerConnection, return pc, nil } +func WithInterceptor(i interceptor.Interceptor) func (*PeerConnection) error { + return func(pc *PeerConnection) error { + pc.extraInterceptors = append(pc.extraInterceptors, i) + return nil + } +} + // initConfiguration defines validation of the specified Configuration and // its assignment to the internal configuration variable. This function differs // from its SetConfiguration counterpart because most of the checks do not