diff options
Diffstat (limited to 'vendor/github.com/pion/webrtc/v3/track_remote.go')
-rw-r--r-- | vendor/github.com/pion/webrtc/v3/track_remote.go | 183 |
1 files changed, 183 insertions, 0 deletions
diff --git a/vendor/github.com/pion/webrtc/v3/track_remote.go b/vendor/github.com/pion/webrtc/v3/track_remote.go new file mode 100644 index 0000000..6733b7c --- /dev/null +++ b/vendor/github.com/pion/webrtc/v3/track_remote.go @@ -0,0 +1,183 @@ +// +build !js + +package webrtc + +import ( + "sync" + "time" + + "github.com/pion/interceptor" + "github.com/pion/rtp" +) + +// TrackRemote represents a single inbound source of media +type TrackRemote struct { + mu sync.RWMutex + + id string + streamID string + + payloadType PayloadType + kind RTPCodecType + ssrc SSRC + codec RTPCodecParameters + params RTPParameters + rid string + + receiver *RTPReceiver + peeked []byte + peekedAttributes interceptor.Attributes +} + +func newTrackRemote(kind RTPCodecType, ssrc SSRC, rid string, receiver *RTPReceiver) *TrackRemote { + return &TrackRemote{ + kind: kind, + ssrc: ssrc, + rid: rid, + receiver: receiver, + } +} + +// ID is the unique identifier for this Track. This should be unique for the +// stream, but doesn't have to globally unique. A common example would be 'audio' or 'video' +// and StreamID would be 'desktop' or 'webcam' +func (t *TrackRemote) ID() string { + t.mu.RLock() + defer t.mu.RUnlock() + return t.id +} + +// RID gets the RTP Stream ID of this Track +// With Simulcast you will have multiple tracks with the same ID, but different RID values. +// In many cases a TrackRemote will not have an RID, so it is important to assert it is non-zero +func (t *TrackRemote) RID() string { + t.mu.RLock() + defer t.mu.RUnlock() + + return t.rid +} + +// PayloadType gets the PayloadType of the track +func (t *TrackRemote) PayloadType() PayloadType { + t.mu.RLock() + defer t.mu.RUnlock() + return t.payloadType +} + +// Kind gets the Kind of the track +func (t *TrackRemote) Kind() RTPCodecType { + t.mu.RLock() + defer t.mu.RUnlock() + return t.kind +} + +// StreamID is the group this track belongs too. This must be unique +func (t *TrackRemote) StreamID() string { + t.mu.RLock() + defer t.mu.RUnlock() + return t.streamID +} + +// SSRC gets the SSRC of the track +func (t *TrackRemote) SSRC() SSRC { + t.mu.RLock() + defer t.mu.RUnlock() + return t.ssrc +} + +// Msid gets the Msid of the track +func (t *TrackRemote) Msid() string { + return t.StreamID() + " " + t.ID() +} + +// Codec gets the Codec of the track +func (t *TrackRemote) Codec() RTPCodecParameters { + t.mu.RLock() + defer t.mu.RUnlock() + return t.codec +} + +// Read reads data from the track. +func (t *TrackRemote) Read(b []byte) (n int, attributes interceptor.Attributes, err error) { + t.mu.RLock() + r := t.receiver + peeked := t.peeked != nil + t.mu.RUnlock() + + if peeked { + t.mu.Lock() + data := t.peeked + attributes = t.peekedAttributes + + t.peeked = nil + t.peekedAttributes = nil + t.mu.Unlock() + // someone else may have stolen our packet when we + // released the lock. Deal with it. + if data != nil { + n = copy(b, data) + return + } + } + + return r.readRTP(b, t) +} + +// ReadRTP is a convenience method that wraps Read and unmarshals for you. +func (t *TrackRemote) ReadRTP() (*rtp.Packet, interceptor.Attributes, error) { + b := make([]byte, receiveMTU) + i, attributes, err := t.Read(b) + if err != nil { + return nil, nil, err + } + + r := &rtp.Packet{} + if err := r.Unmarshal(b[:i]); err != nil { + return nil, nil, err + } + return r, attributes, nil +} + +// determinePayloadType blocks and reads a single packet to determine the PayloadType for this Track +// this is useful because we can't announce it to the user until we know the payloadType +func (t *TrackRemote) determinePayloadType() error { + b := make([]byte, receiveMTU) + n, _, err := t.peek(b) + if err != nil { + return err + } + r := rtp.Packet{} + if err := r.Unmarshal(b[:n]); err != nil { + return err + } + + t.mu.Lock() + t.payloadType = PayloadType(r.PayloadType) + defer t.mu.Unlock() + + return nil +} + +// peek is like Read, but it doesn't discard the packet read +func (t *TrackRemote) peek(b []byte) (n int, a interceptor.Attributes, err error) { + n, a, err = t.Read(b) + if err != nil { + return + } + + t.mu.Lock() + // this might overwrite data if somebody peeked between the Read + // and us getting the lock. Oh well, we'll just drop a packet in + // that case. + data := make([]byte, n) + n = copy(data, b[:n]) + t.peeked = data + t.peekedAttributes = a + t.mu.Unlock() + return +} + +// SetReadDeadline sets the max amount of time the RTP stream will block before returning. 0 is forever. +func (t *TrackRemote) SetReadDeadline(deadline time.Time) error { + return t.receiver.setRTPReadDeadline(deadline, t) +} |