rtptransceiver.go 8.2 KB

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