Implement legacy offer_to_receive options for Unified Plan
This implements the WebRTC specification for handling the legacy offer options offer_to_receive_audio and offer_to_receive_video. They are not implemented for CreateAnswer. With Unified Plan semantics, clients should switch to the RtpTransceiver API for ensuring the correct media sections are offered. Bug: webrtc:7600 Change-Id: I6ced00b86b165a352bd0ca3d64b48fadcfd12235 Reviewed-on: https://webrtc-review.googlesource.com/41341 Reviewed-by: Peter Thatcher <pthatcher@webrtc.org> Reviewed-by: Taylor Brandstetter <deadbeef@webrtc.org> Commit-Queue: Steve Anton <steveanton@webrtc.org> Cr-Commit-Position: refs/heads/master@{#21784}
This commit is contained in:
@ -1259,7 +1259,8 @@ RTCErrorOr<rtc::scoped_refptr<RtpTransceiverInterface>>
|
|||||||
PeerConnection::AddTransceiver(
|
PeerConnection::AddTransceiver(
|
||||||
cricket::MediaType media_type,
|
cricket::MediaType media_type,
|
||||||
rtc::scoped_refptr<MediaStreamTrackInterface> track,
|
rtc::scoped_refptr<MediaStreamTrackInterface> track,
|
||||||
const RtpTransceiverInit& init) {
|
const RtpTransceiverInit& init,
|
||||||
|
bool fire_callback) {
|
||||||
RTC_DCHECK((media_type == cricket::MEDIA_TYPE_AUDIO ||
|
RTC_DCHECK((media_type == cricket::MEDIA_TYPE_AUDIO ||
|
||||||
media_type == cricket::MEDIA_TYPE_VIDEO));
|
media_type == cricket::MEDIA_TYPE_VIDEO));
|
||||||
if (track) {
|
if (track) {
|
||||||
@ -1285,7 +1286,9 @@ PeerConnection::AddTransceiver(
|
|||||||
auto transceiver = CreateAndAddTransceiver(sender, receiver);
|
auto transceiver = CreateAndAddTransceiver(sender, receiver);
|
||||||
transceiver->internal()->set_direction(init.direction);
|
transceiver->internal()->set_direction(init.direction);
|
||||||
|
|
||||||
|
if (fire_callback) {
|
||||||
observer_->OnRenegotiationNeeded();
|
observer_->OnRenegotiationNeeded();
|
||||||
|
}
|
||||||
|
|
||||||
return rtc::scoped_refptr<RtpTransceiverInterface>(transceiver);
|
return rtc::scoped_refptr<RtpTransceiverInterface>(transceiver);
|
||||||
}
|
}
|
||||||
@ -1565,11 +1568,80 @@ void PeerConnection::CreateOffer(CreateSessionDescriptionObserver* observer,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Legacy handling for offer_to_receive_audio and offer_to_receive_video.
|
||||||
|
// Specified in WebRTC section 4.4.3.2 "Legacy configuration extensions".
|
||||||
|
if (IsUnifiedPlan()) {
|
||||||
|
RTCError error = HandleLegacyOfferOptions(options);
|
||||||
|
if (!error.ok()) {
|
||||||
|
PostCreateSessionDescriptionFailure(observer, error.message());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
cricket::MediaSessionOptions session_options;
|
cricket::MediaSessionOptions session_options;
|
||||||
GetOptionsForOffer(options, &session_options);
|
GetOptionsForOffer(options, &session_options);
|
||||||
webrtc_session_desc_factory_->CreateOffer(observer, options, session_options);
|
webrtc_session_desc_factory_->CreateOffer(observer, options, session_options);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RTCError PeerConnection::HandleLegacyOfferOptions(
|
||||||
|
const RTCOfferAnswerOptions& options) {
|
||||||
|
RTC_DCHECK(IsUnifiedPlan());
|
||||||
|
|
||||||
|
if (options.offer_to_receive_audio == 0) {
|
||||||
|
RemoveRecvDirectionFromReceivingTransceiversOfType(
|
||||||
|
cricket::MEDIA_TYPE_AUDIO);
|
||||||
|
} else if (options.offer_to_receive_audio == 1) {
|
||||||
|
AddUpToOneReceivingTransceiverOfType(cricket::MEDIA_TYPE_AUDIO);
|
||||||
|
} else if (options.offer_to_receive_audio > 1) {
|
||||||
|
LOG_AND_RETURN_ERROR(RTCErrorType::UNSUPPORTED_PARAMETER,
|
||||||
|
"offer_to_receive_audio > 1 is not supported.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (options.offer_to_receive_video == 0) {
|
||||||
|
RemoveRecvDirectionFromReceivingTransceiversOfType(
|
||||||
|
cricket::MEDIA_TYPE_VIDEO);
|
||||||
|
} else if (options.offer_to_receive_video == 1) {
|
||||||
|
AddUpToOneReceivingTransceiverOfType(cricket::MEDIA_TYPE_VIDEO);
|
||||||
|
} else if (options.offer_to_receive_video > 1) {
|
||||||
|
LOG_AND_RETURN_ERROR(RTCErrorType::UNSUPPORTED_PARAMETER,
|
||||||
|
"offer_to_receive_video > 1 is not supported.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return RTCError::OK();
|
||||||
|
}
|
||||||
|
|
||||||
|
void PeerConnection::RemoveRecvDirectionFromReceivingTransceiversOfType(
|
||||||
|
cricket::MediaType media_type) {
|
||||||
|
for (auto transceiver : GetReceivingTransceiversOfType(media_type)) {
|
||||||
|
transceiver->internal()->set_direction(
|
||||||
|
RtpTransceiverDirectionWithRecvSet(transceiver->direction(), false));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PeerConnection::AddUpToOneReceivingTransceiverOfType(
|
||||||
|
cricket::MediaType media_type) {
|
||||||
|
if (GetReceivingTransceiversOfType(media_type).empty()) {
|
||||||
|
RtpTransceiverInit init;
|
||||||
|
init.direction = RtpTransceiverDirection::kRecvOnly;
|
||||||
|
AddTransceiver(media_type, nullptr, init, /*fire_callback=*/false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<rtc::scoped_refptr<RtpTransceiverProxyWithInternal<RtpTransceiver>>>
|
||||||
|
PeerConnection::GetReceivingTransceiversOfType(cricket::MediaType media_type) {
|
||||||
|
std::vector<
|
||||||
|
rtc::scoped_refptr<RtpTransceiverProxyWithInternal<RtpTransceiver>>>
|
||||||
|
receiving_transceivers;
|
||||||
|
for (auto transceiver : transceivers_) {
|
||||||
|
if (!transceiver->stopped() &&
|
||||||
|
transceiver->internal()->media_type() == media_type &&
|
||||||
|
RtpTransceiverDirectionHasRecv(transceiver->direction())) {
|
||||||
|
receiving_transceivers.push_back(transceiver);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return receiving_transceivers;
|
||||||
|
}
|
||||||
|
|
||||||
void PeerConnection::CreateAnswer(
|
void PeerConnection::CreateAnswer(
|
||||||
CreateSessionDescriptionObserver* observer,
|
CreateSessionDescriptionObserver* observer,
|
||||||
const MediaConstraintsInterface* constraints) {
|
const MediaConstraintsInterface* constraints) {
|
||||||
@ -1615,6 +1687,19 @@ void PeerConnection::CreateAnswer(CreateSessionDescriptionObserver* observer,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (IsUnifiedPlan()) {
|
||||||
|
if (options.offer_to_receive_audio != RTCOfferAnswerOptions::kUndefined) {
|
||||||
|
RTC_LOG(LS_WARNING) << "CreateAnswer: offer_to_receive_audio is not "
|
||||||
|
"supported with Unified Plan semantics. Use the "
|
||||||
|
"RtpTransceiver API instead.";
|
||||||
|
}
|
||||||
|
if (options.offer_to_receive_video != RTCOfferAnswerOptions::kUndefined) {
|
||||||
|
RTC_LOG(LS_WARNING) << "CreateAnswer: offer_to_receive_video is not "
|
||||||
|
"supported with Unified Plan semantics. Use the "
|
||||||
|
"RtpTransceiver API instead.";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
cricket::MediaSessionOptions session_options;
|
cricket::MediaSessionOptions session_options;
|
||||||
GetOptionsForAnswer(options, &session_options);
|
GetOptionsForAnswer(options, &session_options);
|
||||||
|
|
||||||
|
|||||||
@ -354,10 +354,13 @@ class PeerConnection : public PeerConnectionInternal,
|
|||||||
rtc::scoped_refptr<RtpTransceiverProxyWithInternal<RtpTransceiver>>
|
rtc::scoped_refptr<RtpTransceiverProxyWithInternal<RtpTransceiver>>
|
||||||
FindTransceiverBySender(rtc::scoped_refptr<RtpSenderInterface> sender);
|
FindTransceiverBySender(rtc::scoped_refptr<RtpSenderInterface> sender);
|
||||||
|
|
||||||
|
// Internal implementation for AddTransceiver family of methods. If
|
||||||
|
// |fire_callback| is set, fires OnRenegotiationNeeded callback if successful.
|
||||||
RTCErrorOr<rtc::scoped_refptr<RtpTransceiverInterface>> AddTransceiver(
|
RTCErrorOr<rtc::scoped_refptr<RtpTransceiverInterface>> AddTransceiver(
|
||||||
cricket::MediaType media_type,
|
cricket::MediaType media_type,
|
||||||
rtc::scoped_refptr<MediaStreamTrackInterface> track,
|
rtc::scoped_refptr<MediaStreamTrackInterface> track,
|
||||||
const RtpTransceiverInit& init);
|
const RtpTransceiverInit& init,
|
||||||
|
bool fire_callback = true);
|
||||||
|
|
||||||
rtc::scoped_refptr<RtpSenderProxyWithInternal<RtpSenderInternal>>
|
rtc::scoped_refptr<RtpSenderProxyWithInternal<RtpSenderInternal>>
|
||||||
CreateSender(cricket::MediaType media_type,
|
CreateSender(cricket::MediaType media_type,
|
||||||
@ -482,6 +485,14 @@ class PeerConnection : public PeerConnectionInternal,
|
|||||||
offer_answer_options,
|
offer_answer_options,
|
||||||
cricket::MediaSessionOptions* session_options);
|
cricket::MediaSessionOptions* session_options);
|
||||||
|
|
||||||
|
RTCError HandleLegacyOfferOptions(const RTCOfferAnswerOptions& options);
|
||||||
|
void RemoveRecvDirectionFromReceivingTransceiversOfType(
|
||||||
|
cricket::MediaType media_type);
|
||||||
|
void AddUpToOneReceivingTransceiverOfType(cricket::MediaType media_type);
|
||||||
|
std::vector<
|
||||||
|
rtc::scoped_refptr<RtpTransceiverProxyWithInternal<RtpTransceiver>>>
|
||||||
|
GetReceivingTransceiversOfType(cricket::MediaType media_type);
|
||||||
|
|
||||||
// Returns a MediaSessionOptions struct with options decided by
|
// Returns a MediaSessionOptions struct with options decided by
|
||||||
// |constraints|, the local MediaStreams and DataChannels.
|
// |constraints|, the local MediaStreams and DataChannels.
|
||||||
void GetOptionsForAnswer(const RTCOfferAnswerOptions& offer_answer_options,
|
void GetOptionsForAnswer(const RTCOfferAnswerOptions& offer_answer_options,
|
||||||
|
|||||||
@ -361,39 +361,38 @@ TEST_P(PeerConnectionMediaTest, NewStreamInRemoteOfferAddsRecvStreams) {
|
|||||||
// Test that a new stream in a subsequent answer causes a new send stream to be
|
// Test that a new stream in a subsequent answer causes a new send stream to be
|
||||||
// created on the callee when added locally.
|
// created on the callee when added locally.
|
||||||
TEST_P(PeerConnectionMediaTest, NewStreamInLocalAnswerAddsSendStreams) {
|
TEST_P(PeerConnectionMediaTest, NewStreamInLocalAnswerAddsSendStreams) {
|
||||||
// TODO(bugs.webrtc.org/8765): Enable this test under Unified Plan once
|
|
||||||
// offer_to_receive_audio is implemented.
|
|
||||||
if (IsUnifiedPlan()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto caller = CreatePeerConnection();
|
auto caller = CreatePeerConnection();
|
||||||
auto callee = CreatePeerConnectionWithAudioVideo();
|
auto callee = CreatePeerConnectionWithAudioVideo();
|
||||||
|
|
||||||
RTCOfferAnswerOptions options;
|
RTCOfferAnswerOptions offer_options;
|
||||||
options.offer_to_receive_audio =
|
offer_options.offer_to_receive_audio =
|
||||||
RTCOfferAnswerOptions::kOfferToReceiveMediaTrue;
|
RTCOfferAnswerOptions::kOfferToReceiveMediaTrue;
|
||||||
options.offer_to_receive_video =
|
offer_options.offer_to_receive_video =
|
||||||
RTCOfferAnswerOptions::kOfferToReceiveMediaTrue;
|
RTCOfferAnswerOptions::kOfferToReceiveMediaTrue;
|
||||||
|
RTCOfferAnswerOptions answer_options;
|
||||||
|
|
||||||
ASSERT_TRUE(
|
ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get(), offer_options,
|
||||||
callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal(options)));
|
answer_options));
|
||||||
ASSERT_TRUE(
|
|
||||||
caller->SetRemoteDescription(callee->CreateAnswerAndSetAsLocal()));
|
|
||||||
|
|
||||||
// Add second set of tracks to the callee.
|
// Add second set of tracks to the callee.
|
||||||
callee->AddAudioTrack("a2");
|
callee->AddAudioTrack("a2");
|
||||||
callee->AddVideoTrack("v2");
|
callee->AddVideoTrack("v2");
|
||||||
|
|
||||||
ASSERT_TRUE(
|
ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get(), offer_options,
|
||||||
callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal(options)));
|
answer_options));
|
||||||
ASSERT_TRUE(
|
|
||||||
caller->SetRemoteDescription(callee->CreateAnswerAndSetAsLocal()));
|
|
||||||
|
|
||||||
auto callee_voice = callee->media_engine()->GetVoiceChannel(0);
|
auto callee_voice = callee->media_engine()->GetVoiceChannel(0);
|
||||||
EXPECT_EQ(2u, callee_voice->send_streams().size());
|
ASSERT_TRUE(callee_voice);
|
||||||
auto callee_video = callee->media_engine()->GetVideoChannel(0);
|
auto callee_video = callee->media_engine()->GetVideoChannel(0);
|
||||||
|
ASSERT_TRUE(callee_video);
|
||||||
|
|
||||||
|
if (IsUnifiedPlan()) {
|
||||||
|
EXPECT_EQ(1u, callee_voice->send_streams().size());
|
||||||
|
EXPECT_EQ(1u, callee_video->send_streams().size());
|
||||||
|
} else {
|
||||||
|
EXPECT_EQ(2u, callee_voice->send_streams().size());
|
||||||
EXPECT_EQ(2u, callee_video->send_streams().size());
|
EXPECT_EQ(2u, callee_video->send_streams().size());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// A PeerConnection with no local streams and no explicit answer constraints
|
// A PeerConnection with no local streams and no explicit answer constraints
|
||||||
@ -438,11 +437,6 @@ class PeerConnectionMediaOfferDirectionTest
|
|||||||
// Tests that the correct direction is set on the media description according
|
// Tests that the correct direction is set on the media description according
|
||||||
// to the presence of a local media track and the offer_to_receive setting.
|
// to the presence of a local media track and the offer_to_receive setting.
|
||||||
TEST_P(PeerConnectionMediaOfferDirectionTest, VerifyDirection) {
|
TEST_P(PeerConnectionMediaOfferDirectionTest, VerifyDirection) {
|
||||||
// TODO(bugs.webrtc.org/8765): Enable this test under Unified Plan once
|
|
||||||
// offer_to_receive_audio is implemented.
|
|
||||||
if (IsUnifiedPlan()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
auto caller = CreatePeerConnection();
|
auto caller = CreatePeerConnection();
|
||||||
if (send_media_) {
|
if (send_media_) {
|
||||||
caller->AddAudioTrack("a");
|
caller->AddAudioTrack("a");
|
||||||
@ -496,11 +490,13 @@ class PeerConnectionMediaAnswerDirectionTest
|
|||||||
// in the offer, the presence of a local media track on the receive side and the
|
// in the offer, the presence of a local media track on the receive side and the
|
||||||
// offer_to_receive setting.
|
// offer_to_receive setting.
|
||||||
TEST_P(PeerConnectionMediaAnswerDirectionTest, VerifyDirection) {
|
TEST_P(PeerConnectionMediaAnswerDirectionTest, VerifyDirection) {
|
||||||
// TODO(bugs.webrtc.org/8765): Enable this test under Unified Plan once
|
if (IsUnifiedPlan() &&
|
||||||
// offer_to_receive_audio is implemented.
|
offer_to_receive_ != RTCOfferAnswerOptions::kUndefined) {
|
||||||
if (IsUnifiedPlan()) {
|
// offer_to_receive_ is not implemented when creating answers with Unified
|
||||||
|
// Plan semantics specified.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto caller = CreatePeerConnection();
|
auto caller = CreatePeerConnection();
|
||||||
caller->AddAudioTrack("a");
|
caller->AddAudioTrack("a");
|
||||||
|
|
||||||
@ -544,11 +540,13 @@ TEST_P(PeerConnectionMediaAnswerDirectionTest, VerifyDirection) {
|
|||||||
// local media track and has set offer_to_receive to 0, no matter which
|
// local media track and has set offer_to_receive to 0, no matter which
|
||||||
// direction the caller indicated in the offer.
|
// direction the caller indicated in the offer.
|
||||||
TEST_P(PeerConnectionMediaAnswerDirectionTest, VerifyRejected) {
|
TEST_P(PeerConnectionMediaAnswerDirectionTest, VerifyRejected) {
|
||||||
// TODO(bugs.webrtc.org/8765): Enable this test under Unified Plan once
|
if (IsUnifiedPlan() &&
|
||||||
// offer_to_receive_audio is implemented.
|
offer_to_receive_ != RTCOfferAnswerOptions::kUndefined) {
|
||||||
if (IsUnifiedPlan()) {
|
// offer_to_receive_ is not implemented when creating answers with Unified
|
||||||
|
// Plan semantics specified.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto caller = CreatePeerConnection();
|
auto caller = CreatePeerConnection();
|
||||||
caller->AddAudioTrack("a");
|
caller->AddAudioTrack("a");
|
||||||
|
|
||||||
@ -587,12 +585,6 @@ INSTANTIATE_TEST_CASE_P(PeerConnectionMediaTest,
|
|||||||
Values(-1, 0, 1)));
|
Values(-1, 0, 1)));
|
||||||
|
|
||||||
TEST_P(PeerConnectionMediaTest, OfferHasDifferentDirectionForAudioVideo) {
|
TEST_P(PeerConnectionMediaTest, OfferHasDifferentDirectionForAudioVideo) {
|
||||||
// TODO(bugs.webrtc.org/8765): Enable this test under Unified Plan once
|
|
||||||
// offer_to_receive_audio is implemented.
|
|
||||||
if (IsUnifiedPlan()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto caller = CreatePeerConnection();
|
auto caller = CreatePeerConnection();
|
||||||
caller->AddVideoTrack("v");
|
caller->AddVideoTrack("v");
|
||||||
|
|
||||||
@ -608,9 +600,9 @@ TEST_P(PeerConnectionMediaTest, OfferHasDifferentDirectionForAudioVideo) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST_P(PeerConnectionMediaTest, AnswerHasDifferentDirectionsForAudioVideo) {
|
TEST_P(PeerConnectionMediaTest, AnswerHasDifferentDirectionsForAudioVideo) {
|
||||||
// TODO(bugs.webrtc.org/8765): Enable this test under Unified Plan once
|
|
||||||
// offer_to_receive_audio is implemented.
|
|
||||||
if (IsUnifiedPlan()) {
|
if (IsUnifiedPlan()) {
|
||||||
|
// offer_to_receive_ is not implemented when creating answers with Unified
|
||||||
|
// Plan semantics specified.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -780,9 +772,9 @@ INSTANTIATE_TEST_CASE_P(
|
|||||||
// a series of offer/answers where audio/video are both sent, then audio is
|
// a series of offer/answers where audio/video are both sent, then audio is
|
||||||
// rejected, then both audio/video sent again.
|
// rejected, then both audio/video sent again.
|
||||||
TEST_P(PeerConnectionMediaTest, TestAVOfferWithAudioOnlyAnswer) {
|
TEST_P(PeerConnectionMediaTest, TestAVOfferWithAudioOnlyAnswer) {
|
||||||
// TODO(bugs.webrtc.org/8765): Enable this test under Unified Plan once
|
|
||||||
// offer_to_receive_audio is implemented.
|
|
||||||
if (IsUnifiedPlan()) {
|
if (IsUnifiedPlan()) {
|
||||||
|
// offer_to_receive_ is not implemented when creating answers with Unified
|
||||||
|
// Plan semantics specified.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -844,9 +836,9 @@ TEST_P(PeerConnectionMediaTest, TestAVOfferWithAudioOnlyAnswer) {
|
|||||||
// a series of offer/answers where audio/video are both sent, then video is
|
// a series of offer/answers where audio/video are both sent, then video is
|
||||||
// rejected, then both audio/video sent again.
|
// rejected, then both audio/video sent again.
|
||||||
TEST_P(PeerConnectionMediaTest, TestAVOfferWithVideoOnlyAnswer) {
|
TEST_P(PeerConnectionMediaTest, TestAVOfferWithVideoOnlyAnswer) {
|
||||||
// TODO(bugs.webrtc.org/8765): Enable this test under Unified Plan once
|
|
||||||
// offer_to_receive_audio is implemented.
|
|
||||||
if (IsUnifiedPlan()) {
|
if (IsUnifiedPlan()) {
|
||||||
|
// offer_to_receive_ is not implemented when creating answers with Unified
|
||||||
|
// Plan semantics specified.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -24,6 +24,8 @@
|
|||||||
|
|
||||||
namespace webrtc {
|
namespace webrtc {
|
||||||
|
|
||||||
|
using RTCOfferAnswerOptions = PeerConnectionInterface::RTCOfferAnswerOptions;
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
const uint32_t kDefaultTimeout = 10000U;
|
const uint32_t kDefaultTimeout = 10000U;
|
||||||
}
|
}
|
||||||
@ -57,7 +59,7 @@ MockPeerConnectionObserver* PeerConnectionWrapper::observer() {
|
|||||||
|
|
||||||
std::unique_ptr<SessionDescriptionInterface>
|
std::unique_ptr<SessionDescriptionInterface>
|
||||||
PeerConnectionWrapper::CreateOffer() {
|
PeerConnectionWrapper::CreateOffer() {
|
||||||
return CreateOffer(PeerConnectionInterface::RTCOfferAnswerOptions());
|
return CreateOffer(RTCOfferAnswerOptions());
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<SessionDescriptionInterface> PeerConnectionWrapper::CreateOffer(
|
std::unique_ptr<SessionDescriptionInterface> PeerConnectionWrapper::CreateOffer(
|
||||||
@ -72,8 +74,7 @@ std::unique_ptr<SessionDescriptionInterface> PeerConnectionWrapper::CreateOffer(
|
|||||||
|
|
||||||
std::unique_ptr<SessionDescriptionInterface>
|
std::unique_ptr<SessionDescriptionInterface>
|
||||||
PeerConnectionWrapper::CreateOfferAndSetAsLocal() {
|
PeerConnectionWrapper::CreateOfferAndSetAsLocal() {
|
||||||
return CreateOfferAndSetAsLocal(
|
return CreateOfferAndSetAsLocal(RTCOfferAnswerOptions());
|
||||||
PeerConnectionInterface::RTCOfferAnswerOptions());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<SessionDescriptionInterface>
|
std::unique_ptr<SessionDescriptionInterface>
|
||||||
@ -89,7 +90,7 @@ PeerConnectionWrapper::CreateOfferAndSetAsLocal(
|
|||||||
|
|
||||||
std::unique_ptr<SessionDescriptionInterface>
|
std::unique_ptr<SessionDescriptionInterface>
|
||||||
PeerConnectionWrapper::CreateAnswer() {
|
PeerConnectionWrapper::CreateAnswer() {
|
||||||
return CreateAnswer(PeerConnectionInterface::RTCOfferAnswerOptions());
|
return CreateAnswer(RTCOfferAnswerOptions());
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<SessionDescriptionInterface>
|
std::unique_ptr<SessionDescriptionInterface>
|
||||||
@ -105,8 +106,7 @@ PeerConnectionWrapper::CreateAnswer(
|
|||||||
|
|
||||||
std::unique_ptr<SessionDescriptionInterface>
|
std::unique_ptr<SessionDescriptionInterface>
|
||||||
PeerConnectionWrapper::CreateAnswerAndSetAsLocal() {
|
PeerConnectionWrapper::CreateAnswerAndSetAsLocal() {
|
||||||
return CreateAnswerAndSetAsLocal(
|
return CreateAnswerAndSetAsLocal(RTCOfferAnswerOptions());
|
||||||
PeerConnectionInterface::RTCOfferAnswerOptions());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<SessionDescriptionInterface>
|
std::unique_ptr<SessionDescriptionInterface>
|
||||||
@ -181,12 +181,20 @@ bool PeerConnectionWrapper::SetSdp(
|
|||||||
|
|
||||||
bool PeerConnectionWrapper::ExchangeOfferAnswerWith(
|
bool PeerConnectionWrapper::ExchangeOfferAnswerWith(
|
||||||
PeerConnectionWrapper* answerer) {
|
PeerConnectionWrapper* answerer) {
|
||||||
|
return ExchangeOfferAnswerWith(answerer, RTCOfferAnswerOptions(),
|
||||||
|
RTCOfferAnswerOptions());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PeerConnectionWrapper::ExchangeOfferAnswerWith(
|
||||||
|
PeerConnectionWrapper* answerer,
|
||||||
|
const PeerConnectionInterface::RTCOfferAnswerOptions& offer_options,
|
||||||
|
const PeerConnectionInterface::RTCOfferAnswerOptions& answer_options) {
|
||||||
RTC_DCHECK(answerer);
|
RTC_DCHECK(answerer);
|
||||||
if (answerer == this) {
|
if (answerer == this) {
|
||||||
RTC_LOG(LS_ERROR) << "Cannot exchange offer/answer with ourself!";
|
RTC_LOG(LS_ERROR) << "Cannot exchange offer/answer with ourself!";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
auto offer = CreateOffer();
|
auto offer = CreateOffer(offer_options);
|
||||||
EXPECT_TRUE(offer);
|
EXPECT_TRUE(offer);
|
||||||
if (!offer) {
|
if (!offer) {
|
||||||
return false;
|
return false;
|
||||||
@ -202,7 +210,7 @@ bool PeerConnectionWrapper::ExchangeOfferAnswerWith(
|
|||||||
if (!set_remote_offer) {
|
if (!set_remote_offer) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
auto answer = answerer->CreateAnswer();
|
auto answer = answerer->CreateAnswer(answer_options);
|
||||||
EXPECT_TRUE(answer);
|
EXPECT_TRUE(answer);
|
||||||
if (!answer) {
|
if (!answer) {
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@ -97,16 +97,20 @@ class PeerConnectionWrapper {
|
|||||||
// generating the offer and the given PeerConnectionWrapper generating the
|
// generating the offer and the given PeerConnectionWrapper generating the
|
||||||
// answer.
|
// answer.
|
||||||
// Equivalent to:
|
// Equivalent to:
|
||||||
// 1. this->CreateOffer()
|
// 1. this->CreateOffer(offer_options)
|
||||||
// 2. this->SetLocalDescription(offer)
|
// 2. this->SetLocalDescription(offer)
|
||||||
// 3. answerer->SetRemoteDescription(offer)
|
// 3. answerer->SetRemoteDescription(offer)
|
||||||
// 4. answerer->CreateAnswer()
|
// 4. answerer->CreateAnswer(answer_options)
|
||||||
// 5. answerer->SetLocalDescription(answer)
|
// 5. answerer->SetLocalDescription(answer)
|
||||||
// 6. this->SetRemoteDescription(answer)
|
// 6. this->SetRemoteDescription(answer)
|
||||||
// Returns true if all steps succeed, false otherwise.
|
// Returns true if all steps succeed, false otherwise.
|
||||||
// Suggested usage:
|
// Suggested usage:
|
||||||
// ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get()));
|
// ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get()));
|
||||||
bool ExchangeOfferAnswerWith(PeerConnectionWrapper* answerer);
|
bool ExchangeOfferAnswerWith(PeerConnectionWrapper* answerer);
|
||||||
|
bool ExchangeOfferAnswerWith(
|
||||||
|
PeerConnectionWrapper* answerer,
|
||||||
|
const PeerConnectionInterface::RTCOfferAnswerOptions& offer_options,
|
||||||
|
const PeerConnectionInterface::RTCOfferAnswerOptions& answer_options);
|
||||||
|
|
||||||
// The following are wrappers for the underlying PeerConnection's
|
// The following are wrappers for the underlying PeerConnection's
|
||||||
// AddTransceiver method. They return the result of calling AddTransceiver
|
// AddTransceiver method. They return the result of calling AddTransceiver
|
||||||
|
|||||||
@ -50,6 +50,20 @@ RtpTransceiverDirection RtpTransceiverDirectionReversed(
|
|||||||
return direction;
|
return direction;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RtpTransceiverDirection RtpTransceiverDirectionWithSendSet(
|
||||||
|
RtpTransceiverDirection direction,
|
||||||
|
bool send) {
|
||||||
|
return RtpTransceiverDirectionFromSendRecv(
|
||||||
|
send, RtpTransceiverDirectionHasRecv(direction));
|
||||||
|
}
|
||||||
|
|
||||||
|
RtpTransceiverDirection RtpTransceiverDirectionWithRecvSet(
|
||||||
|
RtpTransceiverDirection direction,
|
||||||
|
bool recv) {
|
||||||
|
return RtpTransceiverDirectionFromSendRecv(
|
||||||
|
RtpTransceiverDirectionHasSend(direction), recv);
|
||||||
|
}
|
||||||
|
|
||||||
const char* RtpTransceiverDirectionToString(RtpTransceiverDirection direction) {
|
const char* RtpTransceiverDirectionToString(RtpTransceiverDirection direction) {
|
||||||
switch (direction) {
|
switch (direction) {
|
||||||
case RtpTransceiverDirection::kSendRecv:
|
case RtpTransceiverDirection::kSendRecv:
|
||||||
|
|||||||
@ -31,6 +31,16 @@ bool RtpTransceiverDirectionHasRecv(RtpTransceiverDirection direction);
|
|||||||
RtpTransceiverDirection RtpTransceiverDirectionReversed(
|
RtpTransceiverDirection RtpTransceiverDirectionReversed(
|
||||||
RtpTransceiverDirection direction);
|
RtpTransceiverDirection direction);
|
||||||
|
|
||||||
|
// Returns the RtpTransceiverDirection with its send component set to |send|.
|
||||||
|
RtpTransceiverDirection RtpTransceiverDirectionWithSendSet(
|
||||||
|
RtpTransceiverDirection direction,
|
||||||
|
bool send = true);
|
||||||
|
|
||||||
|
// Returns the RtpTransceiverDirection with its recv component set to |recv|.
|
||||||
|
RtpTransceiverDirection RtpTransceiverDirectionWithRecvSet(
|
||||||
|
RtpTransceiverDirection direction,
|
||||||
|
bool recv = true);
|
||||||
|
|
||||||
// Returns an unspecified string representation of the given direction.
|
// Returns an unspecified string representation of the given direction.
|
||||||
const char* RtpTransceiverDirectionToString(RtpTransceiverDirection direction);
|
const char* RtpTransceiverDirectionToString(RtpTransceiverDirection direction);
|
||||||
|
|
||||||
|
|||||||
@ -8,16 +8,24 @@
|
|||||||
* be found in the AUTHORS file in the root of the source tree.
|
* be found in the AUTHORS file in the root of the source tree.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <tuple>
|
||||||
|
|
||||||
#include "pc/rtpmediautils.h"
|
#include "pc/rtpmediautils.h"
|
||||||
#include "test/gtest.h"
|
#include "test/gtest.h"
|
||||||
|
|
||||||
namespace webrtc {
|
namespace webrtc {
|
||||||
|
|
||||||
|
using ::testing::Bool;
|
||||||
|
using ::testing::Combine;
|
||||||
using ::testing::Values;
|
using ::testing::Values;
|
||||||
|
using ::testing::ValuesIn;
|
||||||
|
|
||||||
|
RtpTransceiverDirection kAllDirections[] = {
|
||||||
|
RtpTransceiverDirection::kSendRecv, RtpTransceiverDirection::kSendOnly,
|
||||||
|
RtpTransceiverDirection::kRecvOnly, RtpTransceiverDirection::kInactive};
|
||||||
|
|
||||||
class EnumerateAllDirectionsTest
|
class EnumerateAllDirectionsTest
|
||||||
: public ::testing::Test,
|
: public ::testing::TestWithParam<RtpTransceiverDirection> {};
|
||||||
public ::testing::WithParamInterface<RtpTransceiverDirection> {};
|
|
||||||
|
|
||||||
// Test that converting the direction to send/recv and back again results in the
|
// Test that converting the direction to send/recv and back again results in the
|
||||||
// same direction.
|
// same direction.
|
||||||
@ -51,9 +59,38 @@ TEST_P(EnumerateAllDirectionsTest, TestReversedIdentity) {
|
|||||||
|
|
||||||
INSTANTIATE_TEST_CASE_P(RtpTransceiverDirectionTest,
|
INSTANTIATE_TEST_CASE_P(RtpTransceiverDirectionTest,
|
||||||
EnumerateAllDirectionsTest,
|
EnumerateAllDirectionsTest,
|
||||||
Values(RtpTransceiverDirection::kSendRecv,
|
ValuesIn(kAllDirections));
|
||||||
RtpTransceiverDirection::kSendOnly,
|
|
||||||
RtpTransceiverDirection::kRecvOnly,
|
class EnumerateAllDirectionsAndBool
|
||||||
RtpTransceiverDirection::kInactive));
|
: public ::testing::TestWithParam<
|
||||||
|
std::tuple<RtpTransceiverDirection, bool>> {};
|
||||||
|
|
||||||
|
TEST_P(EnumerateAllDirectionsAndBool, TestWithSendSet) {
|
||||||
|
RtpTransceiverDirection direction = std::get<0>(GetParam());
|
||||||
|
bool send = std::get<1>(GetParam());
|
||||||
|
|
||||||
|
RtpTransceiverDirection result =
|
||||||
|
RtpTransceiverDirectionWithSendSet(direction, send);
|
||||||
|
|
||||||
|
EXPECT_EQ(send, RtpTransceiverDirectionHasSend(result));
|
||||||
|
EXPECT_EQ(RtpTransceiverDirectionHasRecv(direction),
|
||||||
|
RtpTransceiverDirectionHasRecv(result));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_P(EnumerateAllDirectionsAndBool, TestWithRecvSet) {
|
||||||
|
RtpTransceiverDirection direction = std::get<0>(GetParam());
|
||||||
|
bool recv = std::get<1>(GetParam());
|
||||||
|
|
||||||
|
RtpTransceiverDirection result =
|
||||||
|
RtpTransceiverDirectionWithRecvSet(direction, recv);
|
||||||
|
|
||||||
|
EXPECT_EQ(RtpTransceiverDirectionHasSend(direction),
|
||||||
|
RtpTransceiverDirectionHasSend(result));
|
||||||
|
EXPECT_EQ(recv, RtpTransceiverDirectionHasRecv(result));
|
||||||
|
}
|
||||||
|
|
||||||
|
INSTANTIATE_TEST_CASE_P(RtpTransceiverDirectionTest,
|
||||||
|
EnumerateAllDirectionsAndBool,
|
||||||
|
Combine(ValuesIn(kAllDirections), Bool()));
|
||||||
|
|
||||||
} // namespace webrtc
|
} // namespace webrtc
|
||||||
|
|||||||
Reference in New Issue
Block a user