interceptor.go 5.0 KB

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