summaryrefslogtreecommitdiff
path: root/vendor/github.com/pion/webrtc/v3/rtptransceiver.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/pion/webrtc/v3/rtptransceiver.go')
-rw-r--r--vendor/github.com/pion/webrtc/v3/rtptransceiver.go187
1 files changed, 187 insertions, 0 deletions
diff --git a/vendor/github.com/pion/webrtc/v3/rtptransceiver.go b/vendor/github.com/pion/webrtc/v3/rtptransceiver.go
new file mode 100644
index 0000000..ee9de2f
--- /dev/null
+++ b/vendor/github.com/pion/webrtc/v3/rtptransceiver.go
@@ -0,0 +1,187 @@
+// +build !js
+
+package webrtc
+
+import (
+ "fmt"
+ "sync/atomic"
+
+ "github.com/pion/rtp"
+)
+
+// RTPTransceiver represents a combination of an RTPSender and an RTPReceiver that share a common mid.
+type RTPTransceiver struct {
+ mid atomic.Value // string
+ sender atomic.Value // *RTPSender
+ receiver atomic.Value // *RTPReceiver
+ direction atomic.Value // RTPTransceiverDirection
+
+ stopped bool
+ kind RTPCodecType
+}
+
+// Sender returns the RTPTransceiver's RTPSender if it has one
+func (t *RTPTransceiver) Sender() *RTPSender {
+ if v := t.sender.Load(); v != nil {
+ return v.(*RTPSender)
+ }
+
+ return nil
+}
+
+// SetSender sets the RTPSender and Track to current transceiver
+func (t *RTPTransceiver) SetSender(s *RTPSender, track TrackLocal) error {
+ t.setSender(s)
+ return t.setSendingTrack(track)
+}
+
+func (t *RTPTransceiver) setSender(s *RTPSender) {
+ t.sender.Store(s)
+}
+
+// Receiver returns the RTPTransceiver's RTPReceiver if it has one
+func (t *RTPTransceiver) Receiver() *RTPReceiver {
+ if v := t.receiver.Load(); v != nil {
+ return v.(*RTPReceiver)
+ }
+
+ return nil
+}
+
+// setMid sets the RTPTransceiver's mid. If it was already set, will return an error.
+func (t *RTPTransceiver) setMid(mid string) error {
+ if currentMid := t.Mid(); currentMid != "" {
+ return fmt.Errorf("%w: %s to %s", errRTPTransceiverCannotChangeMid, currentMid, mid)
+ }
+ t.mid.Store(mid)
+ return nil
+}
+
+// Mid gets the Transceiver's mid value. When not already set, this value will be set in CreateOffer or CreateAnswer.
+func (t *RTPTransceiver) Mid() string {
+ if v := t.mid.Load(); v != nil {
+ return v.(string)
+ }
+ return ""
+}
+
+// Kind returns RTPTransceiver's kind.
+func (t *RTPTransceiver) Kind() RTPCodecType {
+ return t.kind
+}
+
+// Direction returns the RTPTransceiver's current direction
+func (t *RTPTransceiver) Direction() RTPTransceiverDirection {
+ return t.direction.Load().(RTPTransceiverDirection)
+}
+
+// Stop irreversibly stops the RTPTransceiver
+func (t *RTPTransceiver) Stop() error {
+ if t.Sender() != nil {
+ if err := t.Sender().Stop(); err != nil {
+ return err
+ }
+ }
+ if t.Receiver() != nil {
+ if err := t.Receiver().Stop(); err != nil {
+ return err
+ }
+ }
+
+ t.setDirection(RTPTransceiverDirectionInactive)
+ return nil
+}
+
+func (t *RTPTransceiver) setReceiver(r *RTPReceiver) {
+ t.receiver.Store(r)
+}
+
+func (t *RTPTransceiver) setDirection(d RTPTransceiverDirection) {
+ t.direction.Store(d)
+}
+
+func (t *RTPTransceiver) setSendingTrack(track TrackLocal) error {
+ if err := t.Sender().ReplaceTrack(track); err != nil {
+ return err
+ }
+ if track == nil {
+ t.setSender(nil)
+ }
+
+ switch {
+ case track != nil && t.Direction() == RTPTransceiverDirectionRecvonly:
+ t.setDirection(RTPTransceiverDirectionSendrecv)
+ case track != nil && t.Direction() == RTPTransceiverDirectionInactive:
+ t.setDirection(RTPTransceiverDirectionSendonly)
+ case track == nil && t.Direction() == RTPTransceiverDirectionSendrecv:
+ t.setDirection(RTPTransceiverDirectionRecvonly)
+ case track == nil && t.Direction() == RTPTransceiverDirectionSendonly:
+ t.setDirection(RTPTransceiverDirectionInactive)
+ default:
+ return errRTPTransceiverSetSendingInvalidState
+ }
+ return nil
+}
+
+func findByMid(mid string, localTransceivers []*RTPTransceiver) (*RTPTransceiver, []*RTPTransceiver) {
+ for i, t := range localTransceivers {
+ if t.Mid() == mid {
+ return t, append(localTransceivers[:i], localTransceivers[i+1:]...)
+ }
+ }
+
+ return nil, localTransceivers
+}
+
+// Given a direction+type pluck a transceiver from the passed list
+// if no entry satisfies the requested type+direction return a inactive Transceiver
+func satisfyTypeAndDirection(remoteKind RTPCodecType, remoteDirection RTPTransceiverDirection, localTransceivers []*RTPTransceiver) (*RTPTransceiver, []*RTPTransceiver) {
+ // Get direction order from most preferred to least
+ getPreferredDirections := func() []RTPTransceiverDirection {
+ switch remoteDirection {
+ case RTPTransceiverDirectionSendrecv:
+ return []RTPTransceiverDirection{RTPTransceiverDirectionRecvonly, RTPTransceiverDirectionSendrecv}
+ case RTPTransceiverDirectionSendonly:
+ return []RTPTransceiverDirection{RTPTransceiverDirectionRecvonly}
+ case RTPTransceiverDirectionRecvonly:
+ return []RTPTransceiverDirection{RTPTransceiverDirectionSendonly, RTPTransceiverDirectionSendrecv}
+ default:
+ return []RTPTransceiverDirection{}
+ }
+ }
+
+ for _, possibleDirection := range getPreferredDirections() {
+ for i := range localTransceivers {
+ t := localTransceivers[i]
+ if t.Mid() == "" && t.kind == remoteKind && possibleDirection == t.Direction() {
+ return t, append(localTransceivers[:i], localTransceivers[i+1:]...)
+ }
+ }
+ }
+
+ return nil, localTransceivers
+}
+
+// handleUnknownRTPPacket consumes a single RTP Packet and returns information that is helpful
+// for demuxing and handling an unknown SSRC (usually for Simulcast)
+func handleUnknownRTPPacket(buf []byte, midExtensionID, streamIDExtensionID uint8) (mid, rid string, payloadType PayloadType, err error) {
+ rp := &rtp.Packet{}
+ if err = rp.Unmarshal(buf); err != nil {
+ return
+ }
+
+ if !rp.Header.Extension {
+ return
+ }
+
+ payloadType = PayloadType(rp.PayloadType)
+ if payload := rp.GetExtension(midExtensionID); payload != nil {
+ mid = string(payload)
+ }
+
+ if payload := rp.GetExtension(streamIDExtensionID); payload != nil {
+ rid = string(payload)
+ }
+
+ return
+}