package relay import ( "github.com/pion/ice/v4" "github.com/pion/interceptor" "github.com/pion/webrtc/v4" "log" ) var globalWebRTCAPI *webrtc.API var globalWebRTCConfig = webrtc.Configuration{ ICETransportPolicy: webrtc.ICETransportPolicyAll, BundlePolicy: webrtc.BundlePolicyBalanced, SDPSemantics: webrtc.SDPSemanticsUnifiedPlan, } func InitWebRTCAPI() error { var err error flags := GetFlags() // Media engine mediaEngine := &webrtc.MediaEngine{} // Default codecs cover most of our needs err = mediaEngine.RegisterDefaultCodecs() if err != nil { return err } // Add H.265 for special cases videoRTCPFeedback := []webrtc.RTCPFeedback{{"goog-remb", ""}, {"ccm", "fir"}, {"nack", ""}, {"nack", "pli"}} for _, codec := range []webrtc.RTPCodecParameters{ { RTPCodecCapability: webrtc.RTPCodecCapability{MimeType: webrtc.MimeTypeH265, ClockRate: 90000, RTCPFeedback: videoRTCPFeedback}, PayloadType: 48, }, { RTPCodecCapability: webrtc.RTPCodecCapability{MimeType: webrtc.MimeTypeRTX, ClockRate: 90000, SDPFmtpLine: "apt=48"}, PayloadType: 49, }, } { if err = mediaEngine.RegisterCodec(codec, webrtc.RTPCodecTypeVideo); err != nil { return err } } // Interceptor registry interceptorRegistry := &interceptor.Registry{} // Use default set err = webrtc.RegisterDefaultInterceptors(mediaEngine, interceptorRegistry) if err != nil { return err } // Setting engine settingEngine := webrtc.SettingEngine{} // New in v4, reduces CPU usage and latency when enabled settingEngine.EnableSCTPZeroChecksum(true) nat11IPs := GetFlags().NAT11IPs if len(nat11IPs) > 0 { settingEngine.SetNAT1To1IPs(nat11IPs, webrtc.ICECandidateTypeHost) } muxPort := GetFlags().UDPMuxPort if muxPort > 0 { mux, err := ice.NewMultiUDPMuxFromPort(muxPort) if err != nil { return err } settingEngine.SetICEUDPMux(mux) } else { // Set the UDP port range used by WebRTC err = settingEngine.SetEphemeralUDPPortRange(uint16(flags.WebRTCUDPStart), uint16(flags.WebRTCUDPEnd)) if err != nil { return err } } settingEngine.SetIncludeLoopbackCandidate(true) // Just in case // Create a new API object with our customized settings globalWebRTCAPI = webrtc.NewAPI(webrtc.WithMediaEngine(mediaEngine), webrtc.WithSettingEngine(settingEngine), webrtc.WithInterceptorRegistry(interceptorRegistry)) return nil } // GetWebRTCAPI returns the global WebRTC API func GetWebRTCAPI() *webrtc.API { return globalWebRTCAPI } // CreatePeerConnection sets up a new peer connection func CreatePeerConnection(onClose func()) (*webrtc.PeerConnection, error) { pc, err := globalWebRTCAPI.NewPeerConnection(globalWebRTCConfig) if err != nil { return nil, err } // Log connection state changes and handle failed/disconnected connections pc.OnConnectionStateChange(func(connectionState webrtc.PeerConnectionState) { // Close PeerConnection in cases if connectionState == webrtc.PeerConnectionStateFailed || connectionState == webrtc.PeerConnectionStateDisconnected || connectionState == webrtc.PeerConnectionStateClosed { err = pc.Close() if err != nil { log.Printf("Error closing PeerConnection: %s\n", err.Error()) } onClose() } }) return pc, nil }