github.com/pion/webrtc/v3@v3.2.24/interceptor.go (about)

     1  // SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly>
     2  // SPDX-License-Identifier: MIT
     3  
     4  //go:build !js
     5  // +build !js
     6  
     7  package webrtc
     8  
     9  import (
    10  	"sync/atomic"
    11  
    12  	"github.com/pion/interceptor"
    13  	"github.com/pion/interceptor/pkg/nack"
    14  	"github.com/pion/interceptor/pkg/report"
    15  	"github.com/pion/interceptor/pkg/twcc"
    16  	"github.com/pion/rtp"
    17  	"github.com/pion/sdp/v3"
    18  )
    19  
    20  // RegisterDefaultInterceptors will register some useful interceptors.
    21  // If you want to customize which interceptors are loaded, you should copy the
    22  // code from this method and remove unwanted interceptors.
    23  func RegisterDefaultInterceptors(mediaEngine *MediaEngine, interceptorRegistry *interceptor.Registry) error {
    24  	if err := ConfigureNack(mediaEngine, interceptorRegistry); err != nil {
    25  		return err
    26  	}
    27  
    28  	if err := ConfigureRTCPReports(interceptorRegistry); err != nil {
    29  		return err
    30  	}
    31  
    32  	return ConfigureTWCCSender(mediaEngine, interceptorRegistry)
    33  }
    34  
    35  // ConfigureRTCPReports will setup everything necessary for generating Sender and Receiver Reports
    36  func ConfigureRTCPReports(interceptorRegistry *interceptor.Registry) error {
    37  	reciver, err := report.NewReceiverInterceptor()
    38  	if err != nil {
    39  		return err
    40  	}
    41  
    42  	sender, err := report.NewSenderInterceptor()
    43  	if err != nil {
    44  		return err
    45  	}
    46  
    47  	interceptorRegistry.Add(reciver)
    48  	interceptorRegistry.Add(sender)
    49  	return nil
    50  }
    51  
    52  // ConfigureNack will setup everything necessary for handling generating/responding to nack messages.
    53  func ConfigureNack(mediaEngine *MediaEngine, interceptorRegistry *interceptor.Registry) error {
    54  	generator, err := nack.NewGeneratorInterceptor()
    55  	if err != nil {
    56  		return err
    57  	}
    58  
    59  	responder, err := nack.NewResponderInterceptor()
    60  	if err != nil {
    61  		return err
    62  	}
    63  
    64  	mediaEngine.RegisterFeedback(RTCPFeedback{Type: "nack"}, RTPCodecTypeVideo)
    65  	mediaEngine.RegisterFeedback(RTCPFeedback{Type: "nack", Parameter: "pli"}, RTPCodecTypeVideo)
    66  	interceptorRegistry.Add(responder)
    67  	interceptorRegistry.Add(generator)
    68  	return nil
    69  }
    70  
    71  // ConfigureTWCCHeaderExtensionSender will setup everything necessary for adding
    72  // a TWCC header extension to outgoing RTP packets. This will allow the remote peer to generate TWCC reports.
    73  func ConfigureTWCCHeaderExtensionSender(mediaEngine *MediaEngine, interceptorRegistry *interceptor.Registry) error {
    74  	if err := mediaEngine.RegisterHeaderExtension(RTPHeaderExtensionCapability{URI: sdp.TransportCCURI}, RTPCodecTypeVideo); err != nil {
    75  		return err
    76  	}
    77  
    78  	if err := mediaEngine.RegisterHeaderExtension(RTPHeaderExtensionCapability{URI: sdp.TransportCCURI}, RTPCodecTypeAudio); err != nil {
    79  		return err
    80  	}
    81  
    82  	i, err := twcc.NewHeaderExtensionInterceptor()
    83  	if err != nil {
    84  		return err
    85  	}
    86  
    87  	interceptorRegistry.Add(i)
    88  	return nil
    89  }
    90  
    91  // ConfigureTWCCSender will setup everything necessary for generating TWCC reports.
    92  func ConfigureTWCCSender(mediaEngine *MediaEngine, interceptorRegistry *interceptor.Registry) error {
    93  	mediaEngine.RegisterFeedback(RTCPFeedback{Type: TypeRTCPFBTransportCC}, RTPCodecTypeVideo)
    94  	if err := mediaEngine.RegisterHeaderExtension(RTPHeaderExtensionCapability{URI: sdp.TransportCCURI}, RTPCodecTypeVideo); err != nil {
    95  		return err
    96  	}
    97  
    98  	mediaEngine.RegisterFeedback(RTCPFeedback{Type: TypeRTCPFBTransportCC}, RTPCodecTypeAudio)
    99  	if err := mediaEngine.RegisterHeaderExtension(RTPHeaderExtensionCapability{URI: sdp.TransportCCURI}, RTPCodecTypeAudio); err != nil {
   100  		return err
   101  	}
   102  
   103  	generator, err := twcc.NewSenderInterceptor()
   104  	if err != nil {
   105  		return err
   106  	}
   107  
   108  	interceptorRegistry.Add(generator)
   109  	return nil
   110  }
   111  
   112  type interceptorToTrackLocalWriter struct{ interceptor atomic.Value } // interceptor.RTPWriter }
   113  
   114  func (i *interceptorToTrackLocalWriter) WriteRTP(header *rtp.Header, payload []byte) (int, error) {
   115  	if writer, ok := i.interceptor.Load().(interceptor.RTPWriter); ok && writer != nil {
   116  		return writer.Write(header, payload, interceptor.Attributes{})
   117  	}
   118  
   119  	return 0, nil
   120  }
   121  
   122  func (i *interceptorToTrackLocalWriter) Write(b []byte) (int, error) {
   123  	packet := &rtp.Packet{}
   124  	if err := packet.Unmarshal(b); err != nil {
   125  		return 0, err
   126  	}
   127  
   128  	return i.WriteRTP(&packet.Header, packet.Payload)
   129  }
   130  
   131  func createStreamInfo(id string, ssrc SSRC, payloadType PayloadType, codec RTPCodecCapability, webrtcHeaderExtensions []RTPHeaderExtensionParameter) *interceptor.StreamInfo {
   132  	headerExtensions := make([]interceptor.RTPHeaderExtension, 0, len(webrtcHeaderExtensions))
   133  	for _, h := range webrtcHeaderExtensions {
   134  		headerExtensions = append(headerExtensions, interceptor.RTPHeaderExtension{ID: h.ID, URI: h.URI})
   135  	}
   136  
   137  	feedbacks := make([]interceptor.RTCPFeedback, 0, len(codec.RTCPFeedback))
   138  	for _, f := range codec.RTCPFeedback {
   139  		feedbacks = append(feedbacks, interceptor.RTCPFeedback{Type: f.Type, Parameter: f.Parameter})
   140  	}
   141  
   142  	return &interceptor.StreamInfo{
   143  		ID:                  id,
   144  		Attributes:          interceptor.Attributes{},
   145  		SSRC:                uint32(ssrc),
   146  		PayloadType:         uint8(payloadType),
   147  		RTPHeaderExtensions: headerExtensions,
   148  		MimeType:            codec.MimeType,
   149  		ClockRate:           codec.ClockRate,
   150  		Channels:            codec.Channels,
   151  		SDPFmtpLine:         codec.SDPFmtpLine,
   152  		RTCPFeedback:        feedbacks,
   153  	}
   154  }