Skip to content

Commit

Permalink
Implemented AddTransceiverFrom* methods
Browse files Browse the repository at this point in the history
This allows to have SendOnly transceivers while keeping the API
relatively consistent with the browser's
  • Loading branch information
rviscarra committed Jul 31, 2019
1 parent fd9dfab commit 1464ad4
Show file tree
Hide file tree
Showing 3 changed files with 279 additions and 7 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ Check out the **[contributing wiki](https://github.com/pion/webrtc/wiki/Contribu
* [Slugalisk](https://github.com/slugalisk)
* [Agugua Kenechukwu](https://github.com/spaceCh1mp)
* [Ato Araki](https://github.com/atotto)
* [Rafael Viscarra](https://github.com/rviscarra)

### License
MIT License - see [LICENSE](LICENSE) for full text
65 changes: 58 additions & 7 deletions peerconnection.go
Original file line number Diff line number Diff line change
Expand Up @@ -1336,23 +1336,29 @@ func (pc *PeerConnection) AddTrack(track *Track) (*RTPSender, error) {
}

// AddTransceiver Create a new RTCRtpTransceiver and add it to the set of transceivers.
// Deprecated: Use AddTrack, AddTransceiverFromKind or AddTransceiverFromTrack
func (pc *PeerConnection) AddTransceiver(trackOrKind RTPCodecType, init ...RtpTransceiverInit) (*RTPTransceiver, error) {
return pc.AddTransceiverFromKind(trackOrKind, init...)
}

// AddTransceiverFromKind Create a new RTCRtpTransceiver(SendRecv or RecvOnly) and add it to the set of transceivers.
func (pc *PeerConnection) AddTransceiverFromKind(kind RTPCodecType, init ...RtpTransceiverInit) (*RTPTransceiver, error) {
direction := RTPTransceiverDirectionSendrecv
if len(init) > 1 {
return nil, fmt.Errorf("AddTransceiver only accepts one RtpTransceiverInit")
return nil, fmt.Errorf("AddTransceiverFromKind only accepts one RtpTransceiverInit")
} else if len(init) == 1 {
direction = init[0].Direction
}

switch direction {
case RTPTransceiverDirectionSendrecv:
receiver, err := pc.api.NewRTPReceiver(trackOrKind, pc.dtlsTransport)
receiver, err := pc.api.NewRTPReceiver(kind, pc.dtlsTransport)
if err != nil {
return nil, err
}

payloadType := DefaultPayloadTypeOpus
if trackOrKind == RTPCodecTypeVideo {
if kind == RTPCodecTypeVideo {
payloadType = DefaultPayloadTypeVP8
}

Expand All @@ -1370,11 +1376,11 @@ func (pc *PeerConnection) AddTransceiver(trackOrKind RTPCodecType, init ...RtpTr
receiver,
sender,
RTPTransceiverDirectionSendrecv,
trackOrKind,
kind,
), nil

case RTPTransceiverDirectionRecvonly:
receiver, err := pc.api.NewRTPReceiver(trackOrKind, pc.dtlsTransport)
receiver, err := pc.api.NewRTPReceiver(kind, pc.dtlsTransport)
if err != nil {
return nil, err
}
Expand All @@ -1383,10 +1389,55 @@ func (pc *PeerConnection) AddTransceiver(trackOrKind RTPCodecType, init ...RtpTr
receiver,
nil,
RTPTransceiverDirectionRecvonly,
trackOrKind,
kind,
), nil
default:
return nil, fmt.Errorf("AddTransceiverFromKind currently only supports recvonly and sendrecv")
}
}

// AddTransceiverFromTrack Creates a new send only transceiver and add it to the set of
func (pc *PeerConnection) AddTransceiverFromTrack(track *Track, init ...RtpTransceiverInit) (*RTPTransceiver, error) {
direction := RTPTransceiverDirectionSendrecv
if len(init) > 1 {
return nil, fmt.Errorf("AddTransceiverFromTrack only accepts one RtpTransceiverInit")
} else if len(init) == 1 {
direction = init[0].Direction
}

switch direction {
case RTPTransceiverDirectionSendrecv:
receiver, err := pc.api.NewRTPReceiver(track.Kind(), pc.dtlsTransport)
if err != nil {
return nil, err
}

sender, err := pc.api.NewRTPSender(track, pc.dtlsTransport)
if err != nil {
return nil, err
}

return pc.newRTPTransceiver(
receiver,
sender,
RTPTransceiverDirectionSendrecv,
track.Kind(),
), nil

case RTPTransceiverDirectionSendonly:
sender, err := pc.api.NewRTPSender(track, pc.dtlsTransport)
if err != nil {
return nil, err
}

return pc.newRTPTransceiver(
nil,
sender,
RTPTransceiverDirectionSendonly,
track.Kind(),
), nil
default:
return nil, fmt.Errorf("AddTransceiver currently only suports recvonly and sendrecv")
return nil, fmt.Errorf("AddTransceiverFromTrack currently only supports sendonly and sendrecv")
}
}

Expand Down
220 changes: 220 additions & 0 deletions peerconnection_media_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,19 @@ import (
"github.com/pion/sdp/v2"
"github.com/pion/transport/test"
"github.com/pion/webrtc/v2/pkg/media"
"github.com/stretchr/testify/assert"
)

func offerMediaHasDirection(offer SessionDescription, kind RTPCodecType, direction RTPTransceiverDirection) bool {
for _, media := range offer.parsed.MediaDescriptions {
if media.MediaName.Media == kind.String() {
_, exists := media.Attribute(direction.String())
return exists
}
}
return false
}

func TestSRTPDrainLeak(t *testing.T) {
lim := test.TimeOut(time.Second * 30)
defer lim.Stop()
Expand Down Expand Up @@ -622,3 +633,212 @@ func TestOfferRejectionMissingCodec(t *testing.T) {
t.Fatalf("rejecting unknown codec: sdp m=%s, want trailing 0", *videoDesc.MediaName.String())
}
}

func TestAddTransceiverFromTrackSendOnly(t *testing.T) {

pc, err := NewPeerConnection(Configuration{})
if err != nil {
t.Error(err.Error())
}

track, err := pc.NewTrack(
DefaultPayloadTypeOpus,
0xDEADBEEF,
"track-id",
"track-label",
)

if err != nil {
t.Error(err.Error())
}

transceiver, err := pc.AddTransceiverFromTrack(track, RtpTransceiverInit{
Direction: RTPTransceiverDirectionSendonly,
})
if err != nil {
t.Error(err.Error())
}

if transceiver.Receiver != nil {
t.Errorf("Transceiver shouldn't have a receiver")
}

if transceiver.Sender == nil {
t.Errorf("Transceiver should have a sender")
}

if len(pc.GetTransceivers()) != 1 {
t.Errorf("PeerConnection should have one transceiver but has %d", len(pc.GetTransceivers()))
}

if len(pc.GetSenders()) != 1 {
t.Errorf("PeerConnection should have one sender but has %d", len(pc.GetSenders()))
}

offer, err := pc.CreateOffer(nil)
if err != nil {
t.Error(err.Error())
}

if !offerMediaHasDirection(offer, RTPCodecTypeAudio, RTPTransceiverDirectionSendonly) {
t.Errorf("Direction on SDP is not %s", RTPTransceiverDirectionSendonly)
}
}

func TestAddTransceiverFromTrackSendRecv(t *testing.T) {

pc, err := NewPeerConnection(Configuration{})
if err != nil {
t.Error(err.Error())
}

track, err := pc.NewTrack(
DefaultPayloadTypeOpus,
0xDEADBEEF,
"track-id",
"track-label",
)

if err != nil {
t.Error(err.Error())
}

transceiver, err := pc.AddTransceiverFromTrack(track, RtpTransceiverInit{
Direction: RTPTransceiverDirectionSendrecv,
})
if err != nil {
t.Error(err.Error())
}

if transceiver.Receiver == nil {
t.Errorf("Transceiver should have a receiver")
}

if transceiver.Sender == nil {
t.Errorf("Transceiver should have a sender")
}

if len(pc.GetTransceivers()) != 1 {
t.Errorf("PeerConnection should have one transceiver but has %d", len(pc.GetTransceivers()))
}

offer, err := pc.CreateOffer(nil)
if err != nil {
t.Error(err.Error())
}

if !offerMediaHasDirection(offer, RTPCodecTypeAudio, RTPTransceiverDirectionSendrecv) {
t.Errorf("Direction on SDP is not %s", RTPTransceiverDirectionSendrecv)
}
}

func TestAddTransceiver(t *testing.T) {

pc, err := NewPeerConnection(Configuration{})
if err != nil {
t.Error(err.Error())
}

transceiver, err := pc.AddTransceiver(RTPCodecTypeVideo, RtpTransceiverInit{
Direction: RTPTransceiverDirectionSendrecv,
})
if err != nil {
t.Error(err.Error())
}

if transceiver.Receiver == nil {
t.Errorf("Transceiver should have a receiver")
}

if transceiver.Sender == nil {
t.Errorf("Transceiver should have a sender")
}

offer, err := pc.CreateOffer(nil)
if err != nil {
t.Error(err.Error())
}

if !offerMediaHasDirection(offer, RTPCodecTypeVideo, RTPTransceiverDirectionSendrecv) {
t.Errorf("Direction on SDP is not %s", RTPTransceiverDirectionSendrecv)
}
}

func TestAddTransceiverFromKind(t *testing.T) {

pc, err := NewPeerConnection(Configuration{})
if err != nil {
t.Error(err.Error())
}

transceiver, err := pc.AddTransceiverFromKind(RTPCodecTypeVideo, RtpTransceiverInit{
Direction: RTPTransceiverDirectionRecvonly,
})
if err != nil {
t.Error(err.Error())
}

if transceiver.Receiver == nil {
t.Errorf("Transceiver should have a receiver")
}

if transceiver.Sender != nil {
t.Errorf("Transceiver shouldn't have a sender")
}

offer, err := pc.CreateOffer(nil)
if err != nil {
t.Error(err.Error())
}

if !offerMediaHasDirection(offer, RTPCodecTypeVideo, RTPTransceiverDirectionRecvonly) {
t.Errorf("Direction on SDP is not %s", RTPTransceiverDirectionRecvonly)
}
}

func TestAddTransceiverFromKindFailsSendOnly(t *testing.T) {

pc, err := NewPeerConnection(Configuration{})
if err != nil {
t.Error(err.Error())
}

transceiver, err := pc.AddTransceiverFromKind(RTPCodecTypeVideo, RtpTransceiverInit{
Direction: RTPTransceiverDirectionSendonly,
})

if transceiver != nil {
t.Error("AddTransceiverFromKind shouldn't succeed with Direction RTPTransceiverDirectionSendonly")
}

assert.NotNil(t, err)
}

func TestAddTransceiverFromTrackFailsRecvOnly(t *testing.T) {

pc, err := NewPeerConnection(Configuration{})
if err != nil {
t.Error(err.Error())
}

track, err := pc.NewTrack(
DefaultPayloadTypeH264,
0xDEADBEEF,
"track-id",
"track-label",
)

if err != nil {
t.Error(err.Error())
}

transceiver, err := pc.AddTransceiverFromTrack(track, RtpTransceiverInit{
Direction: RTPTransceiverDirectionRecvonly,
})

if transceiver != nil {
t.Error("AddTransceiverFromTrack shouldn't succeed with Direction RTPTransceiverDirectionRecvonly")
}

assert.NotNil(t, err)
}

0 comments on commit 1464ad4

Please sign in to comment.