rtptransceiver.go 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276
  1. //go:build !js
  2. // +build !js
  3. package webrtc
  4. import (
  5. "fmt"
  6. "sync"
  7. "sync/atomic"
  8. "github.com/pion/rtp"
  9. )
  10. // RTPTransceiver represents a combination of an RTPSender and an RTPReceiver that share a common mid.
  11. type RTPTransceiver struct {
  12. mid atomic.Value // string
  13. sender atomic.Value // *RTPSender
  14. receiver atomic.Value // *RTPReceiver
  15. direction atomic.Value // RTPTransceiverDirection
  16. codecs []RTPCodecParameters // User provided codecs via SetCodecPreferences
  17. stopped bool
  18. kind RTPCodecType
  19. api *API
  20. mu sync.RWMutex
  21. }
  22. func newRTPTransceiver(
  23. receiver *RTPReceiver,
  24. sender *RTPSender,
  25. direction RTPTransceiverDirection,
  26. kind RTPCodecType,
  27. api *API,
  28. ) *RTPTransceiver {
  29. t := &RTPTransceiver{kind: kind, api: api}
  30. t.setReceiver(receiver)
  31. t.setSender(sender)
  32. t.setDirection(direction)
  33. return t
  34. }
  35. // SetCodecPreferences sets preferred list of supported codecs
  36. // if codecs is empty or nil we reset to default from MediaEngine
  37. func (t *RTPTransceiver) SetCodecPreferences(codecs []RTPCodecParameters) error {
  38. t.mu.Lock()
  39. defer t.mu.Unlock()
  40. for _, codec := range codecs {
  41. if _, matchType := codecParametersFuzzySearch(codec, t.api.mediaEngine.getCodecsByKind(t.kind)); matchType == codecMatchNone {
  42. return fmt.Errorf("%w %s", errRTPTransceiverCodecUnsupported, codec.MimeType)
  43. }
  44. }
  45. t.codecs = codecs
  46. return nil
  47. }
  48. // Codecs returns list of supported codecs
  49. func (t *RTPTransceiver) getCodecs() []RTPCodecParameters {
  50. t.mu.RLock()
  51. defer t.mu.RUnlock()
  52. mediaEngineCodecs := t.api.mediaEngine.getCodecsByKind(t.kind)
  53. if len(t.codecs) == 0 {
  54. return mediaEngineCodecs
  55. }
  56. filteredCodecs := []RTPCodecParameters{}
  57. for _, codec := range t.codecs {
  58. if c, matchType := codecParametersFuzzySearch(codec, mediaEngineCodecs); matchType != codecMatchNone {
  59. if codec.PayloadType == 0 {
  60. codec.PayloadType = c.PayloadType
  61. }
  62. filteredCodecs = append(filteredCodecs, codec)
  63. }
  64. }
  65. return filteredCodecs
  66. }
  67. // Sender returns the RTPTransceiver's RTPSender if it has one
  68. func (t *RTPTransceiver) Sender() *RTPSender {
  69. if v, ok := t.sender.Load().(*RTPSender); ok {
  70. return v
  71. }
  72. return nil
  73. }
  74. // SetSender sets the RTPSender and Track to current transceiver
  75. func (t *RTPTransceiver) SetSender(s *RTPSender, track TrackLocal) error {
  76. t.setSender(s)
  77. return t.setSendingTrack(track)
  78. }
  79. func (t *RTPTransceiver) setSender(s *RTPSender) {
  80. if s != nil {
  81. s.setRTPTransceiver(t)
  82. }
  83. if prevSender := t.Sender(); prevSender != nil {
  84. prevSender.setRTPTransceiver(nil)
  85. }
  86. t.sender.Store(s)
  87. }
  88. // Receiver returns the RTPTransceiver's RTPReceiver if it has one
  89. func (t *RTPTransceiver) Receiver() *RTPReceiver {
  90. if v, ok := t.receiver.Load().(*RTPReceiver); ok {
  91. return v
  92. }
  93. return nil
  94. }
  95. // SetMid sets the RTPTransceiver's mid. If it was already set, will return an error.
  96. func (t *RTPTransceiver) SetMid(mid string) error {
  97. if currentMid := t.Mid(); currentMid != "" {
  98. return fmt.Errorf("%w: %s to %s", errRTPTransceiverCannotChangeMid, currentMid, mid)
  99. }
  100. t.mid.Store(mid)
  101. return nil
  102. }
  103. // Mid gets the Transceiver's mid value. When not already set, this value will be set in CreateOffer or CreateAnswer.
  104. func (t *RTPTransceiver) Mid() string {
  105. if v, ok := t.mid.Load().(string); ok {
  106. return v
  107. }
  108. return ""
  109. }
  110. // Kind returns RTPTransceiver's kind.
  111. func (t *RTPTransceiver) Kind() RTPCodecType {
  112. return t.kind
  113. }
  114. // Direction returns the RTPTransceiver's current direction
  115. func (t *RTPTransceiver) Direction() RTPTransceiverDirection {
  116. if direction, ok := t.direction.Load().(RTPTransceiverDirection); ok {
  117. return direction
  118. }
  119. return RTPTransceiverDirection(0)
  120. }
  121. // Stop irreversibly stops the RTPTransceiver
  122. func (t *RTPTransceiver) Stop() error {
  123. if sender := t.Sender(); sender != nil {
  124. if err := sender.Stop(); err != nil {
  125. return err
  126. }
  127. }
  128. if receiver := t.Receiver(); receiver != nil {
  129. if err := receiver.Stop(); err != nil {
  130. return err
  131. }
  132. }
  133. t.setDirection(RTPTransceiverDirectionInactive)
  134. return nil
  135. }
  136. func (t *RTPTransceiver) setReceiver(r *RTPReceiver) {
  137. if r != nil {
  138. r.setRTPTransceiver(t)
  139. }
  140. if prevReceiver := t.Receiver(); prevReceiver != nil {
  141. prevReceiver.setRTPTransceiver(nil)
  142. }
  143. t.receiver.Store(r)
  144. }
  145. func (t *RTPTransceiver) setDirection(d RTPTransceiverDirection) {
  146. t.direction.Store(d)
  147. }
  148. func (t *RTPTransceiver) setSendingTrack(track TrackLocal) error {
  149. if err := t.Sender().ReplaceTrack(track); err != nil {
  150. return err
  151. }
  152. if track == nil {
  153. t.setSender(nil)
  154. }
  155. switch {
  156. case track != nil && t.Direction() == RTPTransceiverDirectionRecvonly:
  157. t.setDirection(RTPTransceiverDirectionSendrecv)
  158. case track != nil && t.Direction() == RTPTransceiverDirectionInactive:
  159. t.setDirection(RTPTransceiverDirectionSendonly)
  160. case track == nil && t.Direction() == RTPTransceiverDirectionSendrecv:
  161. t.setDirection(RTPTransceiverDirectionRecvonly)
  162. case track != nil && t.Direction() == RTPTransceiverDirectionSendonly:
  163. // Handle the case where a sendonly transceiver was added by a negotiation
  164. // initiated by remote peer. For example a remote peer added a transceiver
  165. // with direction recvonly.
  166. case track != nil && t.Direction() == RTPTransceiverDirectionSendrecv:
  167. // Similar to above, but for sendrecv transceiver.
  168. case track == nil && t.Direction() == RTPTransceiverDirectionSendonly:
  169. t.setDirection(RTPTransceiverDirectionInactive)
  170. default:
  171. return errRTPTransceiverSetSendingInvalidState
  172. }
  173. return nil
  174. }
  175. func findByMid(mid string, localTransceivers []*RTPTransceiver) (*RTPTransceiver, []*RTPTransceiver) {
  176. for i, t := range localTransceivers {
  177. if t.Mid() == mid {
  178. return t, append(localTransceivers[:i], localTransceivers[i+1:]...)
  179. }
  180. }
  181. return nil, localTransceivers
  182. }
  183. // Given a direction+type pluck a transceiver from the passed list
  184. // if no entry satisfies the requested type+direction return a inactive Transceiver
  185. func satisfyTypeAndDirection(remoteKind RTPCodecType, remoteDirection RTPTransceiverDirection, localTransceivers []*RTPTransceiver) (*RTPTransceiver, []*RTPTransceiver) {
  186. // Get direction order from most preferred to least
  187. getPreferredDirections := func() []RTPTransceiverDirection {
  188. switch remoteDirection {
  189. case RTPTransceiverDirectionSendrecv:
  190. return []RTPTransceiverDirection{RTPTransceiverDirectionRecvonly, RTPTransceiverDirectionSendrecv}
  191. case RTPTransceiverDirectionSendonly:
  192. return []RTPTransceiverDirection{RTPTransceiverDirectionRecvonly}
  193. case RTPTransceiverDirectionRecvonly:
  194. return []RTPTransceiverDirection{RTPTransceiverDirectionSendonly, RTPTransceiverDirectionSendrecv}
  195. default:
  196. return []RTPTransceiverDirection{}
  197. }
  198. }
  199. for _, possibleDirection := range getPreferredDirections() {
  200. for i := range localTransceivers {
  201. t := localTransceivers[i]
  202. if t.Mid() == "" && t.kind == remoteKind && possibleDirection == t.Direction() {
  203. return t, append(localTransceivers[:i], localTransceivers[i+1:]...)
  204. }
  205. }
  206. }
  207. return nil, localTransceivers
  208. }
  209. // handleUnknownRTPPacket consumes a single RTP Packet and returns information that is helpful
  210. // for demuxing and handling an unknown SSRC (usually for Simulcast)
  211. func handleUnknownRTPPacket(buf []byte, midExtensionID, streamIDExtensionID, repairStreamIDExtensionID uint8, mid, rid, rsid *string) (payloadType PayloadType, err error) {
  212. rp := &rtp.Packet{}
  213. if err = rp.Unmarshal(buf); err != nil {
  214. return
  215. }
  216. if !rp.Header.Extension {
  217. return
  218. }
  219. payloadType = PayloadType(rp.PayloadType)
  220. if payload := rp.GetExtension(midExtensionID); payload != nil {
  221. *mid = string(payload)
  222. }
  223. if payload := rp.GetExtension(streamIDExtensionID); payload != nil {
  224. *rid = string(payload)
  225. }
  226. if payload := rp.GetExtension(repairStreamIDExtensionID); payload != nil {
  227. *rsid = string(payload)
  228. }
  229. return
  230. }