track_remote.go 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  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. "sync"
  8. "time"
  9. "github.com/pion/interceptor"
  10. "github.com/pion/rtp"
  11. )
  12. // TrackRemote represents a single inbound source of media
  13. type TrackRemote struct {
  14. mu sync.RWMutex
  15. id string
  16. streamID string
  17. payloadType PayloadType
  18. kind RTPCodecType
  19. ssrc SSRC
  20. codec RTPCodecParameters
  21. params RTPParameters
  22. rid string
  23. receiver *RTPReceiver
  24. peeked []byte
  25. peekedAttributes interceptor.Attributes
  26. }
  27. func newTrackRemote(kind RTPCodecType, ssrc SSRC, rid string, receiver *RTPReceiver) *TrackRemote {
  28. return &TrackRemote{
  29. kind: kind,
  30. ssrc: ssrc,
  31. rid: rid,
  32. receiver: receiver,
  33. }
  34. }
  35. // ID is the unique identifier for this Track. This should be unique for the
  36. // stream, but doesn't have to globally unique. A common example would be 'audio' or 'video'
  37. // and StreamID would be 'desktop' or 'webcam'
  38. func (t *TrackRemote) ID() string {
  39. t.mu.RLock()
  40. defer t.mu.RUnlock()
  41. return t.id
  42. }
  43. // RID gets the RTP Stream ID of this Track
  44. // With Simulcast you will have multiple tracks with the same ID, but different RID values.
  45. // In many cases a TrackRemote will not have an RID, so it is important to assert it is non-zero
  46. func (t *TrackRemote) RID() string {
  47. t.mu.RLock()
  48. defer t.mu.RUnlock()
  49. return t.rid
  50. }
  51. // PayloadType gets the PayloadType of the track
  52. func (t *TrackRemote) PayloadType() PayloadType {
  53. t.mu.RLock()
  54. defer t.mu.RUnlock()
  55. return t.payloadType
  56. }
  57. // Kind gets the Kind of the track
  58. func (t *TrackRemote) Kind() RTPCodecType {
  59. t.mu.RLock()
  60. defer t.mu.RUnlock()
  61. return t.kind
  62. }
  63. // StreamID is the group this track belongs too. This must be unique
  64. func (t *TrackRemote) StreamID() string {
  65. t.mu.RLock()
  66. defer t.mu.RUnlock()
  67. return t.streamID
  68. }
  69. // SSRC gets the SSRC of the track
  70. func (t *TrackRemote) SSRC() SSRC {
  71. t.mu.RLock()
  72. defer t.mu.RUnlock()
  73. return t.ssrc
  74. }
  75. // Msid gets the Msid of the track
  76. func (t *TrackRemote) Msid() string {
  77. return t.StreamID() + " " + t.ID()
  78. }
  79. // Codec gets the Codec of the track
  80. func (t *TrackRemote) Codec() RTPCodecParameters {
  81. t.mu.RLock()
  82. defer t.mu.RUnlock()
  83. return t.codec
  84. }
  85. // Read reads data from the track.
  86. func (t *TrackRemote) Read(b []byte) (n int, attributes interceptor.Attributes, err error) {
  87. t.mu.RLock()
  88. r := t.receiver
  89. peeked := t.peeked != nil
  90. t.mu.RUnlock()
  91. if peeked {
  92. t.mu.Lock()
  93. data := t.peeked
  94. attributes = t.peekedAttributes
  95. t.peeked = nil
  96. t.peekedAttributes = nil
  97. t.mu.Unlock()
  98. // someone else may have stolen our packet when we
  99. // released the lock. Deal with it.
  100. if data != nil {
  101. n = copy(b, data)
  102. err = t.checkAndUpdateTrack(b)
  103. return
  104. }
  105. }
  106. n, attributes, err = r.readRTP(b, t)
  107. if err != nil {
  108. return
  109. }
  110. err = t.checkAndUpdateTrack(b)
  111. return
  112. }
  113. // checkAndUpdateTrack checks payloadType for every incoming packet
  114. // once a different payloadType is detected the track will be updated
  115. func (t *TrackRemote) checkAndUpdateTrack(b []byte) error {
  116. if len(b) < 2 {
  117. return errRTPTooShort
  118. }
  119. if payloadType := PayloadType(b[1] & rtpPayloadTypeBitmask); payloadType != t.PayloadType() {
  120. t.mu.Lock()
  121. defer t.mu.Unlock()
  122. params, err := t.receiver.api.mediaEngine.getRTPParametersByPayloadType(payloadType)
  123. if err != nil {
  124. return err
  125. }
  126. t.kind = t.receiver.kind
  127. t.payloadType = payloadType
  128. t.codec = params.Codecs[0]
  129. t.params = params
  130. }
  131. return nil
  132. }
  133. // ReadRTP is a convenience method that wraps Read and unmarshals for you.
  134. func (t *TrackRemote) ReadRTP() (*rtp.Packet, interceptor.Attributes, error) {
  135. b := make([]byte, t.receiver.api.settingEngine.getReceiveMTU())
  136. i, attributes, err := t.Read(b)
  137. if err != nil {
  138. return nil, nil, err
  139. }
  140. r := &rtp.Packet{}
  141. if err := r.Unmarshal(b[:i]); err != nil {
  142. return nil, nil, err
  143. }
  144. return r, attributes, nil
  145. }
  146. // peek is like Read, but it doesn't discard the packet read
  147. func (t *TrackRemote) peek(b []byte) (n int, a interceptor.Attributes, err error) {
  148. n, a, err = t.Read(b)
  149. if err != nil {
  150. return
  151. }
  152. t.mu.Lock()
  153. // this might overwrite data if somebody peeked between the Read
  154. // and us getting the lock. Oh well, we'll just drop a packet in
  155. // that case.
  156. data := make([]byte, n)
  157. n = copy(data, b[:n])
  158. t.peeked = data
  159. t.peekedAttributes = a
  160. t.mu.Unlock()
  161. return
  162. }
  163. // SetReadDeadline sets the max amount of time the RTP stream will block before returning. 0 is forever.
  164. func (t *TrackRemote) SetReadDeadline(deadline time.Time) error {
  165. return t.receiver.setRTPReadDeadline(deadline, t)
  166. }