rtptransceiver.go 8.3 KB

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