1// +build !js 2 3package webrtc 4 5import ( 6 "sync/atomic" 7 8 "github.com/pion/interceptor" 9 "github.com/pion/interceptor/pkg/nack" 10 "github.com/pion/interceptor/pkg/report" 11 "github.com/pion/rtp" 12) 13 14// RegisterDefaultInterceptors will register some useful interceptors. 15// If you want to customize which interceptors are loaded, you should copy the 16// code from this method and remove unwanted interceptors. 17func RegisterDefaultInterceptors(mediaEngine *MediaEngine, interceptorRegistry *interceptor.Registry) error { 18 if err := ConfigureNack(mediaEngine, interceptorRegistry); err != nil { 19 return err 20 } 21 22 if err := ConfigureRTCPReports(interceptorRegistry); err != nil { 23 return err 24 } 25 26 return nil 27} 28 29// ConfigureRTCPReports will setup everything necessary for generating Sender and Receiver Reports 30func ConfigureRTCPReports(interceptorRegistry *interceptor.Registry) error { 31 reciver, err := report.NewReceiverInterceptor() 32 if err != nil { 33 return err 34 } 35 36 sender, err := report.NewSenderInterceptor() 37 if err != nil { 38 return err 39 } 40 41 interceptorRegistry.Add(reciver) 42 interceptorRegistry.Add(sender) 43 return nil 44} 45 46// ConfigureNack will setup everything necessary for handling generating/responding to nack messages. 47func ConfigureNack(mediaEngine *MediaEngine, interceptorRegistry *interceptor.Registry) error { 48 generator, err := nack.NewGeneratorInterceptor() 49 if err != nil { 50 return err 51 } 52 53 responder, err := nack.NewResponderInterceptor() 54 if err != nil { 55 return err 56 } 57 58 mediaEngine.RegisterFeedback(RTCPFeedback{Type: "nack"}, RTPCodecTypeVideo) 59 mediaEngine.RegisterFeedback(RTCPFeedback{Type: "nack", Parameter: "pli"}, RTPCodecTypeVideo) 60 interceptorRegistry.Add(responder) 61 interceptorRegistry.Add(generator) 62 return nil 63} 64 65type interceptorToTrackLocalWriter struct{ interceptor atomic.Value } // interceptor.RTPWriter } 66 67func (i *interceptorToTrackLocalWriter) WriteRTP(header *rtp.Header, payload []byte) (int, error) { 68 if writer, ok := i.interceptor.Load().(interceptor.RTPWriter); ok && writer != nil { 69 return writer.Write(header, payload, interceptor.Attributes{}) 70 } 71 72 return 0, nil 73} 74 75func (i *interceptorToTrackLocalWriter) Write(b []byte) (int, error) { 76 packet := &rtp.Packet{} 77 if err := packet.Unmarshal(b); err != nil { 78 return 0, err 79 } 80 81 return i.WriteRTP(&packet.Header, packet.Payload) 82} 83 84func createStreamInfo(id string, ssrc SSRC, payloadType PayloadType, codec RTPCodecCapability, webrtcHeaderExtensions []RTPHeaderExtensionParameter) interceptor.StreamInfo { 85 headerExtensions := make([]interceptor.RTPHeaderExtension, 0, len(webrtcHeaderExtensions)) 86 for _, h := range webrtcHeaderExtensions { 87 headerExtensions = append(headerExtensions, interceptor.RTPHeaderExtension{ID: h.ID, URI: h.URI}) 88 } 89 90 feedbacks := make([]interceptor.RTCPFeedback, 0, len(codec.RTCPFeedback)) 91 for _, f := range codec.RTCPFeedback { 92 feedbacks = append(feedbacks, interceptor.RTCPFeedback{Type: f.Type, Parameter: f.Parameter}) 93 } 94 95 return interceptor.StreamInfo{ 96 ID: id, 97 Attributes: interceptor.Attributes{}, 98 SSRC: uint32(ssrc), 99 PayloadType: uint8(payloadType), 100 RTPHeaderExtensions: headerExtensions, 101 MimeType: codec.MimeType, 102 ClockRate: codec.ClockRate, 103 Channels: codec.Channels, 104 SDPFmtpLine: codec.SDPFmtpLine, 105 RTCPFeedback: feedbacks, 106 } 107} 108