mirror of
https://github.com/pion/webrtc.git
synced 2025-12-24 11:51:03 +08:00
Set answer as sendonly in case of a recvonly offer
When a local peer connection has a single transceiver with a sendrecv direction, and the remote has a transceiver with a recvonly direction, the local peer connection must change the transceiver direction to sendonly. When a local peer connection has a single transceiver with a recvonly direction, and the remote has a transceiver with a recvonly direction, the local peer connection must create another transceiver with a sendonly direction. A unit test is added to cover all possible cases.
This commit is contained in:
@@ -1049,10 +1049,21 @@ func (pc *PeerConnection) SetRemoteDescription(desc SessionDescription) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
t = pc.newRTPTransceiver(receiver, nil, RTPTransceiverDirectionRecvonly, kind)
|
||||
|
||||
localDirection := RTPTransceiverDirectionRecvonly
|
||||
if direction == RTPTransceiverDirectionRecvonly {
|
||||
localDirection = RTPTransceiverDirectionSendonly
|
||||
}
|
||||
|
||||
t = pc.newRTPTransceiver(receiver, nil, localDirection, kind)
|
||||
|
||||
pc.onNegotiationNeeded()
|
||||
} else if direction == RTPTransceiverDirectionRecvonly {
|
||||
if t.Direction() == RTPTransceiverDirectionSendrecv {
|
||||
t.setDirection(RTPTransceiverDirectionSendonly)
|
||||
}
|
||||
}
|
||||
|
||||
if t.Mid() == "" {
|
||||
if err := t.setMid(midValue); err != nil {
|
||||
return err
|
||||
|
||||
@@ -1228,3 +1228,125 @@ func TestICELite(t *testing.T) {
|
||||
|
||||
assert.NoError(t, peerConnection.Close())
|
||||
}
|
||||
|
||||
func TestPeerConnection_TransceiverDirection(t *testing.T) {
|
||||
lim := test.TimeOut(time.Second * 30)
|
||||
defer lim.Stop()
|
||||
|
||||
report := test.CheckRoutines(t)
|
||||
defer report()
|
||||
|
||||
createTransceiver := func(pc *PeerConnection, dir RTPTransceiverDirection) error {
|
||||
// AddTransceiverFromKind() can't be used with sendonly
|
||||
if dir == RTPTransceiverDirectionSendonly {
|
||||
codecs := pc.api.mediaEngine.getCodecsByKind(RTPCodecTypeVideo)
|
||||
|
||||
track, err := NewTrackLocalStaticSample(codecs[0].RTPCodecCapability, util.MathRandAlpha(16), util.MathRandAlpha(16))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = pc.AddTransceiverFromTrack(track, []RtpTransceiverInit{
|
||||
{Direction: dir},
|
||||
}...)
|
||||
return err
|
||||
}
|
||||
|
||||
_, err := pc.AddTransceiverFromKind(
|
||||
RTPCodecTypeVideo,
|
||||
RtpTransceiverInit{Direction: dir},
|
||||
)
|
||||
return err
|
||||
}
|
||||
|
||||
for _, test := range []struct {
|
||||
name string
|
||||
offerDirection RTPTransceiverDirection
|
||||
answerStartDirection RTPTransceiverDirection
|
||||
answerFinalDirections []RTPTransceiverDirection
|
||||
}{
|
||||
{
|
||||
"offer sendrecv answer sendrecv",
|
||||
RTPTransceiverDirectionSendrecv,
|
||||
RTPTransceiverDirectionSendrecv,
|
||||
[]RTPTransceiverDirection{RTPTransceiverDirectionSendrecv},
|
||||
},
|
||||
{
|
||||
"offer sendonly answer sendrecv",
|
||||
RTPTransceiverDirectionSendonly,
|
||||
RTPTransceiverDirectionSendrecv,
|
||||
[]RTPTransceiverDirection{RTPTransceiverDirectionSendrecv, RTPTransceiverDirectionRecvonly},
|
||||
},
|
||||
{
|
||||
"offer recvonly answer sendrecv",
|
||||
RTPTransceiverDirectionRecvonly,
|
||||
RTPTransceiverDirectionSendrecv,
|
||||
[]RTPTransceiverDirection{RTPTransceiverDirectionSendonly},
|
||||
},
|
||||
{
|
||||
"offer sendrecv answer sendonly",
|
||||
RTPTransceiverDirectionSendrecv,
|
||||
RTPTransceiverDirectionSendonly,
|
||||
[]RTPTransceiverDirection{RTPTransceiverDirectionSendonly, RTPTransceiverDirectionRecvonly},
|
||||
},
|
||||
{
|
||||
"offer sendonly answer sendonly",
|
||||
RTPTransceiverDirectionSendonly,
|
||||
RTPTransceiverDirectionSendonly,
|
||||
[]RTPTransceiverDirection{RTPTransceiverDirectionSendonly, RTPTransceiverDirectionRecvonly},
|
||||
},
|
||||
{
|
||||
"offer recvonly answer sendonly",
|
||||
RTPTransceiverDirectionRecvonly,
|
||||
RTPTransceiverDirectionSendonly,
|
||||
[]RTPTransceiverDirection{RTPTransceiverDirectionSendonly},
|
||||
},
|
||||
{
|
||||
"offer sendrecv answer recvonly",
|
||||
RTPTransceiverDirectionSendrecv,
|
||||
RTPTransceiverDirectionRecvonly,
|
||||
[]RTPTransceiverDirection{RTPTransceiverDirectionRecvonly},
|
||||
},
|
||||
{
|
||||
"offer sendonly answer recvonly",
|
||||
RTPTransceiverDirectionSendonly,
|
||||
RTPTransceiverDirectionRecvonly,
|
||||
[]RTPTransceiverDirection{RTPTransceiverDirectionRecvonly},
|
||||
},
|
||||
{
|
||||
"offer recvonly answer recvonly",
|
||||
RTPTransceiverDirectionRecvonly,
|
||||
RTPTransceiverDirectionRecvonly,
|
||||
[]RTPTransceiverDirection{RTPTransceiverDirectionRecvonly, RTPTransceiverDirectionSendonly},
|
||||
},
|
||||
} {
|
||||
offerDirection := test.offerDirection
|
||||
answerStartDirection := test.answerStartDirection
|
||||
answerFinalDirections := test.answerFinalDirections
|
||||
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
pcOffer, pcAnswer, err := newPair()
|
||||
assert.NoError(t, err)
|
||||
|
||||
err = createTransceiver(pcOffer, offerDirection)
|
||||
assert.NoError(t, err)
|
||||
|
||||
offer, err := pcOffer.CreateOffer(nil)
|
||||
assert.NoError(t, err)
|
||||
|
||||
err = createTransceiver(pcAnswer, answerStartDirection)
|
||||
assert.NoError(t, err)
|
||||
|
||||
assert.NoError(t, pcAnswer.SetRemoteDescription(offer))
|
||||
|
||||
assert.Equal(t, len(answerFinalDirections), len(pcAnswer.GetTransceivers()))
|
||||
|
||||
for i, tr := range pcAnswer.GetTransceivers() {
|
||||
assert.Equal(t, answerFinalDirections[i], tr.Direction())
|
||||
}
|
||||
|
||||
assert.NoError(t, pcOffer.Close())
|
||||
assert.NoError(t, pcAnswer.Close())
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -142,7 +142,7 @@ func satisfyTypeAndDirection(remoteKind RTPCodecType, remoteDirection RTPTransce
|
||||
case RTPTransceiverDirectionSendrecv:
|
||||
return []RTPTransceiverDirection{RTPTransceiverDirectionRecvonly, RTPTransceiverDirectionSendrecv}
|
||||
case RTPTransceiverDirectionSendonly:
|
||||
return []RTPTransceiverDirection{RTPTransceiverDirectionRecvonly, RTPTransceiverDirectionSendrecv}
|
||||
return []RTPTransceiverDirection{RTPTransceiverDirectionRecvonly}
|
||||
case RTPTransceiverDirectionRecvonly:
|
||||
return []RTPTransceiverDirection{RTPTransceiverDirectionSendonly, RTPTransceiverDirectionSendrecv}
|
||||
default:
|
||||
|
||||
Reference in New Issue
Block a user