github.com/pion/webrtc/v4@v4.0.1/track_remote.go (about)

     1  // SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly>
     2  // SPDX-License-Identifier: MIT
     3  
     4  //go:build !js
     5  // +build !js
     6  
     7  package webrtc
     8  
     9  import (
    10  	"sync"
    11  	"time"
    12  
    13  	"github.com/pion/interceptor"
    14  	"github.com/pion/rtp"
    15  )
    16  
    17  // TrackRemote represents a single inbound source of media
    18  type TrackRemote struct {
    19  	mu sync.RWMutex
    20  
    21  	id       string
    22  	streamID string
    23  
    24  	payloadType PayloadType
    25  	kind        RTPCodecType
    26  	ssrc        SSRC
    27  	rtxSsrc     SSRC
    28  	codec       RTPCodecParameters
    29  	params      RTPParameters
    30  	rid         string
    31  
    32  	receiver         *RTPReceiver
    33  	peeked           []byte
    34  	peekedAttributes interceptor.Attributes
    35  }
    36  
    37  func newTrackRemote(kind RTPCodecType, ssrc, rtxSsrc SSRC, rid string, receiver *RTPReceiver) *TrackRemote {
    38  	return &TrackRemote{
    39  		kind:     kind,
    40  		ssrc:     ssrc,
    41  		rtxSsrc:  rtxSsrc,
    42  		rid:      rid,
    43  		receiver: receiver,
    44  	}
    45  }
    46  
    47  // ID is the unique identifier for this Track. This should be unique for the
    48  // stream, but doesn't have to globally unique. A common example would be 'audio' or 'video'
    49  // and StreamID would be 'desktop' or 'webcam'
    50  func (t *TrackRemote) ID() string {
    51  	t.mu.RLock()
    52  	defer t.mu.RUnlock()
    53  	return t.id
    54  }
    55  
    56  // RID gets the RTP Stream ID of this Track
    57  // With Simulcast you will have multiple tracks with the same ID, but different RID values.
    58  // In many cases a TrackRemote will not have an RID, so it is important to assert it is non-zero
    59  func (t *TrackRemote) RID() string {
    60  	t.mu.RLock()
    61  	defer t.mu.RUnlock()
    62  
    63  	return t.rid
    64  }
    65  
    66  // PayloadType gets the PayloadType of the track
    67  func (t *TrackRemote) PayloadType() PayloadType {
    68  	t.mu.RLock()
    69  	defer t.mu.RUnlock()
    70  	return t.payloadType
    71  }
    72  
    73  // Kind gets the Kind of the track
    74  func (t *TrackRemote) Kind() RTPCodecType {
    75  	t.mu.RLock()
    76  	defer t.mu.RUnlock()
    77  	return t.kind
    78  }
    79  
    80  // StreamID is the group this track belongs too. This must be unique
    81  func (t *TrackRemote) StreamID() string {
    82  	t.mu.RLock()
    83  	defer t.mu.RUnlock()
    84  	return t.streamID
    85  }
    86  
    87  // SSRC gets the SSRC of the track
    88  func (t *TrackRemote) SSRC() SSRC {
    89  	t.mu.RLock()
    90  	defer t.mu.RUnlock()
    91  	return t.ssrc
    92  }
    93  
    94  // Msid gets the Msid of the track
    95  func (t *TrackRemote) Msid() string {
    96  	return t.StreamID() + " " + t.ID()
    97  }
    98  
    99  // Codec gets the Codec of the track
   100  func (t *TrackRemote) Codec() RTPCodecParameters {
   101  	t.mu.RLock()
   102  	defer t.mu.RUnlock()
   103  	return t.codec
   104  }
   105  
   106  // Read reads data from the track.
   107  func (t *TrackRemote) Read(b []byte) (n int, attributes interceptor.Attributes, err error) {
   108  	t.mu.RLock()
   109  	r := t.receiver
   110  	peeked := t.peeked != nil
   111  	t.mu.RUnlock()
   112  
   113  	if peeked {
   114  		t.mu.Lock()
   115  		data := t.peeked
   116  		attributes = t.peekedAttributes
   117  
   118  		t.peeked = nil
   119  		t.peekedAttributes = nil
   120  		t.mu.Unlock()
   121  		// someone else may have stolen our packet when we
   122  		// released the lock.  Deal with it.
   123  		if data != nil {
   124  			n = copy(b, data)
   125  			err = t.checkAndUpdateTrack(b)
   126  			return
   127  		}
   128  	}
   129  
   130  	// If there's a separate RTX track and an RTX packet is available, return that
   131  	if rtxPacketReceived := r.readRTX(t); rtxPacketReceived != nil {
   132  		n = copy(b, rtxPacketReceived.pkt)
   133  		attributes = rtxPacketReceived.attributes
   134  		rtxPacketReceived.release()
   135  		err = nil
   136  	} else {
   137  		// If there's no separate RTX track (or there's a separate RTX track but no RTX packet waiting), wait for and return
   138  		// a packet from the main track
   139  		n, attributes, err = r.readRTP(b, t)
   140  		if err != nil {
   141  			return
   142  		}
   143  		err = t.checkAndUpdateTrack(b)
   144  	}
   145  
   146  	return n, attributes, err
   147  }
   148  
   149  // checkAndUpdateTrack checks payloadType for every incoming packet
   150  // once a different payloadType is detected the track will be updated
   151  func (t *TrackRemote) checkAndUpdateTrack(b []byte) error {
   152  	if len(b) < 2 {
   153  		return errRTPTooShort
   154  	}
   155  
   156  	payloadType := PayloadType(b[1] & rtpPayloadTypeBitmask)
   157  	if payloadType != t.PayloadType() || len(t.params.Codecs) == 0 {
   158  		t.mu.Lock()
   159  		defer t.mu.Unlock()
   160  
   161  		params, err := t.receiver.api.mediaEngine.getRTPParametersByPayloadType(payloadType)
   162  		if err != nil {
   163  			return err
   164  		}
   165  
   166  		t.kind = t.receiver.kind
   167  		t.payloadType = payloadType
   168  		t.codec = params.Codecs[0]
   169  		t.params = params
   170  	}
   171  
   172  	return nil
   173  }
   174  
   175  // ReadRTP is a convenience method that wraps Read and unmarshals for you.
   176  func (t *TrackRemote) ReadRTP() (*rtp.Packet, interceptor.Attributes, error) {
   177  	b := make([]byte, t.receiver.api.settingEngine.getReceiveMTU())
   178  	i, attributes, err := t.Read(b)
   179  	if err != nil {
   180  		return nil, nil, err
   181  	}
   182  
   183  	r := &rtp.Packet{}
   184  	if err := r.Unmarshal(b[:i]); err != nil {
   185  		return nil, nil, err
   186  	}
   187  	return r, attributes, nil
   188  }
   189  
   190  // peek is like Read, but it doesn't discard the packet read
   191  func (t *TrackRemote) peek(b []byte) (n int, a interceptor.Attributes, err error) {
   192  	n, a, err = t.Read(b)
   193  	if err != nil {
   194  		return
   195  	}
   196  
   197  	t.mu.Lock()
   198  	// this might overwrite data if somebody peeked between the Read
   199  	// and us getting the lock.  Oh well, we'll just drop a packet in
   200  	// that case.
   201  	data := make([]byte, n)
   202  	n = copy(data, b[:n])
   203  	t.peeked = data
   204  	t.peekedAttributes = a
   205  	t.mu.Unlock()
   206  	return
   207  }
   208  
   209  // SetReadDeadline sets the max amount of time the RTP stream will block before returning. 0 is forever.
   210  func (t *TrackRemote) SetReadDeadline(deadline time.Time) error {
   211  	return t.receiver.setRTPReadDeadline(deadline, t)
   212  }
   213  
   214  // RtxSSRC returns the RTX SSRC for a track, or 0 if track does not have a separate RTX stream
   215  func (t *TrackRemote) RtxSSRC() SSRC {
   216  	t.mu.RLock()
   217  	defer t.mu.RUnlock()
   218  	return t.rtxSsrc
   219  }
   220  
   221  // HasRTX returns true if the track has a separate RTX stream
   222  func (t *TrackRemote) HasRTX() bool {
   223  	t.mu.RLock()
   224  	defer t.mu.RUnlock()
   225  	return t.rtxSsrc != 0
   226  }
   227  
   228  func (t *TrackRemote) setRtxSSRC(ssrc SSRC) {
   229  	t.mu.Lock()
   230  	defer t.mu.Unlock()
   231  	t.rtxSsrc = ssrc
   232  }