| /* |
| * Copyright 2018 The WebRTC project authors. All Rights Reserved. |
| * |
| * Use of this source code is governed by a BSD-style license |
| * that can be found in the LICENSE file in the root of the source |
| * tree. An additional intellectual property rights grant can be found |
| * in the file PATENTS. All contributing project authors may |
| * be found in the AUTHORS file in the root of the source tree. |
| */ |
| |
| // This file contains tests for `RtpTransceiver`. |
| |
| #include "pc/rtp_transceiver.h" |
| |
| #include <memory> |
| #include <optional> |
| #include <utility> |
| |
| #include "absl/strings/string_view.h" |
| #include "api/environment/environment_factory.h" |
| #include "api/peer_connection_interface.h" |
| #include "api/rtp_parameters.h" |
| #include "media/base/media_engine.h" |
| #include "pc/test/enable_fake_media.h" |
| #include "pc/test/mock_channel_interface.h" |
| #include "pc/test/mock_rtp_receiver_internal.h" |
| #include "pc/test/mock_rtp_sender_internal.h" |
| #include "rtc_base/thread.h" |
| #include "test/gmock.h" |
| #include "test/gtest.h" |
| |
| using ::testing::_; |
| using ::testing::ElementsAre; |
| using ::testing::Field; |
| using ::testing::Optional; |
| using ::testing::Property; |
| using ::testing::Return; |
| using ::testing::ReturnRef; |
| |
| namespace webrtc { |
| |
| namespace { |
| |
| class RtpTransceiverTest : public testing::Test { |
| public: |
| RtpTransceiverTest() |
| : dependencies_(MakeDependencies()), |
| context_( |
| ConnectionContext::Create(CreateEnvironment(), &dependencies_)) {} |
| |
| protected: |
| cricket::MediaEngineInterface* media_engine() { |
| return context_->media_engine(); |
| } |
| ConnectionContext* context() { return context_.get(); } |
| |
| private: |
| rtc::AutoThread main_thread_; |
| |
| static PeerConnectionFactoryDependencies MakeDependencies() { |
| PeerConnectionFactoryDependencies d; |
| d.network_thread = rtc::Thread::Current(); |
| d.worker_thread = rtc::Thread::Current(); |
| d.signaling_thread = rtc::Thread::Current(); |
| EnableFakeMedia(d); |
| return d; |
| } |
| |
| PeerConnectionFactoryDependencies dependencies_; |
| rtc::scoped_refptr<ConnectionContext> context_; |
| }; |
| |
| // Checks that a channel cannot be set on a stopped `RtpTransceiver`. |
| TEST_F(RtpTransceiverTest, CannotSetChannelOnStoppedTransceiver) { |
| const std::string content_name("my_mid"); |
| auto transceiver = rtc::make_ref_counted<RtpTransceiver>( |
| cricket::MediaType::MEDIA_TYPE_AUDIO, context()); |
| auto channel1 = std::make_unique<cricket::MockChannelInterface>(); |
| EXPECT_CALL(*channel1, media_type()) |
| .WillRepeatedly(Return(cricket::MediaType::MEDIA_TYPE_AUDIO)); |
| EXPECT_CALL(*channel1, mid()).WillRepeatedly(ReturnRef(content_name)); |
| EXPECT_CALL(*channel1, SetFirstPacketReceivedCallback(_)); |
| EXPECT_CALL(*channel1, SetRtpTransport(_)).WillRepeatedly(Return(true)); |
| auto channel1_ptr = channel1.get(); |
| transceiver->SetChannel(std::move(channel1), [&](const std::string& mid) { |
| EXPECT_EQ(mid, content_name); |
| return nullptr; |
| }); |
| EXPECT_EQ(channel1_ptr, transceiver->channel()); |
| |
| // Stop the transceiver. |
| transceiver->StopInternal(); |
| EXPECT_EQ(channel1_ptr, transceiver->channel()); |
| |
| auto channel2 = std::make_unique<cricket::MockChannelInterface>(); |
| EXPECT_CALL(*channel2, media_type()) |
| .WillRepeatedly(Return(cricket::MediaType::MEDIA_TYPE_AUDIO)); |
| |
| // Clear the current channel - required to allow SetChannel() |
| EXPECT_CALL(*channel1_ptr, SetFirstPacketReceivedCallback(_)); |
| transceiver->ClearChannel(); |
| // Channel can no longer be set, so this call should be a no-op. |
| transceiver->SetChannel(std::move(channel2), |
| [](const std::string&) { return nullptr; }); |
| EXPECT_EQ(nullptr, transceiver->channel()); |
| } |
| |
| // Checks that a channel can be unset on a stopped `RtpTransceiver` |
| TEST_F(RtpTransceiverTest, CanUnsetChannelOnStoppedTransceiver) { |
| const std::string content_name("my_mid"); |
| auto transceiver = rtc::make_ref_counted<RtpTransceiver>( |
| cricket::MediaType::MEDIA_TYPE_VIDEO, context()); |
| auto channel = std::make_unique<cricket::MockChannelInterface>(); |
| EXPECT_CALL(*channel, media_type()) |
| .WillRepeatedly(Return(cricket::MediaType::MEDIA_TYPE_VIDEO)); |
| EXPECT_CALL(*channel, mid()).WillRepeatedly(ReturnRef(content_name)); |
| EXPECT_CALL(*channel, SetFirstPacketReceivedCallback(_)) |
| .WillRepeatedly(testing::Return()); |
| EXPECT_CALL(*channel, SetRtpTransport(_)).WillRepeatedly(Return(true)); |
| |
| auto channel_ptr = channel.get(); |
| transceiver->SetChannel(std::move(channel), [&](const std::string& mid) { |
| EXPECT_EQ(mid, content_name); |
| return nullptr; |
| }); |
| EXPECT_EQ(channel_ptr, transceiver->channel()); |
| |
| // Stop the transceiver. |
| transceiver->StopInternal(); |
| EXPECT_EQ(channel_ptr, transceiver->channel()); |
| |
| // Set the channel to `nullptr`. |
| transceiver->ClearChannel(); |
| EXPECT_EQ(nullptr, transceiver->channel()); |
| } |
| |
| class RtpTransceiverUnifiedPlanTest : public RtpTransceiverTest { |
| public: |
| RtpTransceiverUnifiedPlanTest() |
| : transceiver_(rtc::make_ref_counted<RtpTransceiver>( |
| RtpSenderProxyWithInternal<RtpSenderInternal>::Create( |
| rtc::Thread::Current(), |
| sender_), |
| RtpReceiverProxyWithInternal<RtpReceiverInternal>::Create( |
| rtc::Thread::Current(), |
| rtc::Thread::Current(), |
| receiver_), |
| context(), |
| media_engine()->voice().GetRtpHeaderExtensions(), |
| /* on_negotiation_needed= */ [] {})) {} |
| |
| static rtc::scoped_refptr<MockRtpReceiverInternal> MockReceiver() { |
| auto receiver = rtc::make_ref_counted<MockRtpReceiverInternal>(); |
| EXPECT_CALL(*receiver.get(), media_type()) |
| .WillRepeatedly(Return(cricket::MediaType::MEDIA_TYPE_AUDIO)); |
| return receiver; |
| } |
| |
| static rtc::scoped_refptr<MockRtpSenderInternal> MockSender() { |
| auto sender = rtc::make_ref_counted<MockRtpSenderInternal>(); |
| EXPECT_CALL(*sender.get(), media_type()) |
| .WillRepeatedly(Return(cricket::MediaType::MEDIA_TYPE_AUDIO)); |
| return sender; |
| } |
| |
| rtc::AutoThread main_thread_; |
| rtc::scoped_refptr<MockRtpReceiverInternal> receiver_ = MockReceiver(); |
| rtc::scoped_refptr<MockRtpSenderInternal> sender_ = MockSender(); |
| rtc::scoped_refptr<RtpTransceiver> transceiver_; |
| }; |
| |
| // Basic tests for Stop() |
| TEST_F(RtpTransceiverUnifiedPlanTest, StopSetsDirection) { |
| EXPECT_CALL(*receiver_.get(), Stop()); |
| EXPECT_CALL(*receiver_.get(), SetMediaChannel(_)); |
| EXPECT_CALL(*sender_.get(), SetTransceiverAsStopped()); |
| EXPECT_CALL(*sender_.get(), Stop()); |
| |
| EXPECT_EQ(RtpTransceiverDirection::kInactive, transceiver_->direction()); |
| EXPECT_FALSE(transceiver_->current_direction()); |
| transceiver_->StopStandard(); |
| EXPECT_EQ(RtpTransceiverDirection::kStopped, transceiver_->direction()); |
| EXPECT_FALSE(transceiver_->current_direction()); |
| transceiver_->StopTransceiverProcedure(); |
| EXPECT_TRUE(transceiver_->current_direction()); |
| EXPECT_EQ(RtpTransceiverDirection::kStopped, transceiver_->direction()); |
| EXPECT_EQ(RtpTransceiverDirection::kStopped, |
| *transceiver_->current_direction()); |
| } |
| |
| class RtpTransceiverTestForHeaderExtensions : public RtpTransceiverTest { |
| public: |
| RtpTransceiverTestForHeaderExtensions() |
| : extensions_( |
| {RtpHeaderExtensionCapability("uri1", |
| 1, |
| RtpTransceiverDirection::kSendOnly), |
| RtpHeaderExtensionCapability("uri2", |
| 2, |
| RtpTransceiverDirection::kRecvOnly), |
| RtpHeaderExtensionCapability(RtpExtension::kMidUri, |
| 3, |
| RtpTransceiverDirection::kSendRecv), |
| RtpHeaderExtensionCapability(RtpExtension::kVideoRotationUri, |
| 4, |
| RtpTransceiverDirection::kSendRecv)}), |
| transceiver_(rtc::make_ref_counted<RtpTransceiver>( |
| RtpSenderProxyWithInternal<RtpSenderInternal>::Create( |
| rtc::Thread::Current(), |
| sender_), |
| RtpReceiverProxyWithInternal<RtpReceiverInternal>::Create( |
| rtc::Thread::Current(), |
| rtc::Thread::Current(), |
| receiver_), |
| context(), |
| extensions_, |
| /* on_negotiation_needed= */ [] {})) {} |
| |
| static rtc::scoped_refptr<MockRtpReceiverInternal> MockReceiver() { |
| auto receiver = rtc::make_ref_counted<MockRtpReceiverInternal>(); |
| EXPECT_CALL(*receiver.get(), media_type()) |
| .WillRepeatedly(Return(cricket::MediaType::MEDIA_TYPE_AUDIO)); |
| return receiver; |
| } |
| |
| static rtc::scoped_refptr<MockRtpSenderInternal> MockSender() { |
| auto sender = rtc::make_ref_counted<MockRtpSenderInternal>(); |
| EXPECT_CALL(*sender.get(), media_type()) |
| .WillRepeatedly(Return(cricket::MediaType::MEDIA_TYPE_AUDIO)); |
| return sender; |
| } |
| |
| void ClearChannel() { |
| EXPECT_CALL(*sender_.get(), SetMediaChannel(_)); |
| transceiver_->ClearChannel(); |
| } |
| |
| rtc::AutoThread main_thread_; |
| rtc::scoped_refptr<MockRtpReceiverInternal> receiver_ = MockReceiver(); |
| rtc::scoped_refptr<MockRtpSenderInternal> sender_ = MockSender(); |
| |
| std::vector<RtpHeaderExtensionCapability> extensions_; |
| rtc::scoped_refptr<RtpTransceiver> transceiver_; |
| }; |
| |
| TEST_F(RtpTransceiverTestForHeaderExtensions, OffersChannelManagerList) { |
| EXPECT_CALL(*receiver_.get(), Stop()); |
| EXPECT_CALL(*receiver_.get(), SetMediaChannel(_)); |
| EXPECT_CALL(*sender_.get(), SetTransceiverAsStopped()); |
| EXPECT_CALL(*sender_.get(), Stop()); |
| |
| EXPECT_EQ(transceiver_->GetHeaderExtensionsToNegotiate(), extensions_); |
| } |
| |
| TEST_F(RtpTransceiverTestForHeaderExtensions, ModifiesDirection) { |
| EXPECT_CALL(*receiver_.get(), Stop()); |
| EXPECT_CALL(*receiver_.get(), SetMediaChannel(_)); |
| EXPECT_CALL(*sender_.get(), SetTransceiverAsStopped()); |
| EXPECT_CALL(*sender_.get(), Stop()); |
| |
| auto modified_extensions = extensions_; |
| modified_extensions[0].direction = RtpTransceiverDirection::kSendOnly; |
| EXPECT_TRUE( |
| transceiver_->SetHeaderExtensionsToNegotiate(modified_extensions).ok()); |
| EXPECT_EQ(transceiver_->GetHeaderExtensionsToNegotiate(), |
| modified_extensions); |
| modified_extensions[0].direction = RtpTransceiverDirection::kRecvOnly; |
| EXPECT_TRUE( |
| transceiver_->SetHeaderExtensionsToNegotiate(modified_extensions).ok()); |
| EXPECT_EQ(transceiver_->GetHeaderExtensionsToNegotiate(), |
| modified_extensions); |
| modified_extensions[0].direction = RtpTransceiverDirection::kSendRecv; |
| EXPECT_TRUE( |
| transceiver_->SetHeaderExtensionsToNegotiate(modified_extensions).ok()); |
| EXPECT_EQ(transceiver_->GetHeaderExtensionsToNegotiate(), |
| modified_extensions); |
| modified_extensions[0].direction = RtpTransceiverDirection::kInactive; |
| EXPECT_TRUE( |
| transceiver_->SetHeaderExtensionsToNegotiate(modified_extensions).ok()); |
| EXPECT_EQ(transceiver_->GetHeaderExtensionsToNegotiate(), |
| modified_extensions); |
| } |
| |
| TEST_F(RtpTransceiverTestForHeaderExtensions, AcceptsStoppedExtension) { |
| EXPECT_CALL(*receiver_.get(), Stop()); |
| EXPECT_CALL(*receiver_.get(), SetMediaChannel(_)); |
| EXPECT_CALL(*sender_.get(), SetTransceiverAsStopped()); |
| EXPECT_CALL(*sender_.get(), Stop()); |
| |
| auto modified_extensions = extensions_; |
| modified_extensions[0].direction = RtpTransceiverDirection::kStopped; |
| EXPECT_TRUE( |
| transceiver_->SetHeaderExtensionsToNegotiate(modified_extensions).ok()); |
| EXPECT_EQ(transceiver_->GetHeaderExtensionsToNegotiate(), |
| modified_extensions); |
| } |
| |
| TEST_F(RtpTransceiverTestForHeaderExtensions, RejectsDifferentSize) { |
| EXPECT_CALL(*receiver_.get(), Stop()); |
| EXPECT_CALL(*receiver_.get(), SetMediaChannel(_)); |
| EXPECT_CALL(*sender_.get(), SetTransceiverAsStopped()); |
| EXPECT_CALL(*sender_.get(), Stop()); |
| |
| auto modified_extensions = extensions_; |
| modified_extensions.pop_back(); |
| |
| EXPECT_THAT(transceiver_->SetHeaderExtensionsToNegotiate(modified_extensions), |
| Property(&RTCError::type, RTCErrorType::INVALID_MODIFICATION)); |
| EXPECT_EQ(transceiver_->GetHeaderExtensionsToNegotiate(), extensions_); |
| } |
| |
| TEST_F(RtpTransceiverTestForHeaderExtensions, RejectsChangedUri) { |
| EXPECT_CALL(*receiver_.get(), Stop()); |
| EXPECT_CALL(*receiver_.get(), SetMediaChannel(_)); |
| EXPECT_CALL(*sender_.get(), SetTransceiverAsStopped()); |
| EXPECT_CALL(*sender_.get(), Stop()); |
| |
| auto modified_extensions = extensions_; |
| ASSERT_TRUE(!modified_extensions.empty()); |
| modified_extensions[0].uri = "http://webrtc.org"; |
| |
| EXPECT_THAT(transceiver_->SetHeaderExtensionsToNegotiate(modified_extensions), |
| Property(&RTCError::type, RTCErrorType::INVALID_MODIFICATION)); |
| EXPECT_EQ(transceiver_->GetHeaderExtensionsToNegotiate(), extensions_); |
| } |
| |
| TEST_F(RtpTransceiverTestForHeaderExtensions, RejectsReorder) { |
| EXPECT_CALL(*receiver_.get(), Stop()); |
| EXPECT_CALL(*receiver_.get(), SetMediaChannel(_)); |
| EXPECT_CALL(*sender_.get(), SetTransceiverAsStopped()); |
| EXPECT_CALL(*sender_.get(), Stop()); |
| |
| auto modified_extensions = extensions_; |
| ASSERT_GE(modified_extensions.size(), 2u); |
| std::swap(modified_extensions[0], modified_extensions[1]); |
| |
| EXPECT_THAT(transceiver_->SetHeaderExtensionsToNegotiate(modified_extensions), |
| Property(&RTCError::type, RTCErrorType::INVALID_MODIFICATION)); |
| EXPECT_EQ(transceiver_->GetHeaderExtensionsToNegotiate(), extensions_); |
| } |
| |
| TEST_F(RtpTransceiverTestForHeaderExtensions, |
| RejectsStoppedMandatoryExtensions) { |
| EXPECT_CALL(*receiver_.get(), Stop()); |
| EXPECT_CALL(*receiver_.get(), SetMediaChannel(_)); |
| EXPECT_CALL(*sender_.get(), SetTransceiverAsStopped()); |
| EXPECT_CALL(*sender_.get(), Stop()); |
| |
| std::vector<RtpHeaderExtensionCapability> modified_extensions = extensions_; |
| // Attempting to stop the mandatory MID extension. |
| modified_extensions[2].direction = RtpTransceiverDirection::kStopped; |
| EXPECT_THAT(transceiver_->SetHeaderExtensionsToNegotiate(modified_extensions), |
| Property(&RTCError::type, RTCErrorType::INVALID_MODIFICATION)); |
| EXPECT_EQ(transceiver_->GetHeaderExtensionsToNegotiate(), extensions_); |
| } |
| |
| TEST_F(RtpTransceiverTestForHeaderExtensions, |
| NoNegotiatedHdrExtsWithoutChannel) { |
| EXPECT_CALL(*receiver_.get(), Stop()); |
| EXPECT_CALL(*receiver_.get(), SetMediaChannel(_)); |
| EXPECT_CALL(*sender_.get(), SetTransceiverAsStopped()); |
| EXPECT_CALL(*sender_.get(), Stop()); |
| EXPECT_THAT(transceiver_->GetNegotiatedHeaderExtensions(), |
| ElementsAre(Field(&RtpHeaderExtensionCapability::direction, |
| RtpTransceiverDirection::kStopped), |
| Field(&RtpHeaderExtensionCapability::direction, |
| RtpTransceiverDirection::kStopped), |
| Field(&RtpHeaderExtensionCapability::direction, |
| RtpTransceiverDirection::kStopped), |
| Field(&RtpHeaderExtensionCapability::direction, |
| RtpTransceiverDirection::kStopped))); |
| } |
| |
| TEST_F(RtpTransceiverTestForHeaderExtensions, |
| NoNegotiatedHdrExtsWithChannelWithoutNegotiation) { |
| const std::string content_name("my_mid"); |
| EXPECT_CALL(*receiver_.get(), SetMediaChannel(_)).WillRepeatedly(Return()); |
| EXPECT_CALL(*receiver_.get(), Stop()).WillRepeatedly(Return()); |
| EXPECT_CALL(*sender_.get(), SetMediaChannel(_)); |
| EXPECT_CALL(*sender_.get(), SetTransceiverAsStopped()); |
| EXPECT_CALL(*sender_.get(), Stop()); |
| auto mock_channel = std::make_unique<cricket::MockChannelInterface>(); |
| auto mock_channel_ptr = mock_channel.get(); |
| EXPECT_CALL(*mock_channel, SetFirstPacketReceivedCallback(_)); |
| EXPECT_CALL(*mock_channel, media_type()) |
| .WillRepeatedly(Return(cricket::MediaType::MEDIA_TYPE_AUDIO)); |
| EXPECT_CALL(*mock_channel, voice_media_send_channel()) |
| .WillRepeatedly(Return(nullptr)); |
| EXPECT_CALL(*mock_channel, mid()).WillRepeatedly(ReturnRef(content_name)); |
| EXPECT_CALL(*mock_channel, SetRtpTransport(_)).WillRepeatedly(Return(true)); |
| transceiver_->SetChannel(std::move(mock_channel), |
| [](const std::string&) { return nullptr; }); |
| EXPECT_THAT(transceiver_->GetNegotiatedHeaderExtensions(), |
| ElementsAre(Field(&RtpHeaderExtensionCapability::direction, |
| RtpTransceiverDirection::kStopped), |
| Field(&RtpHeaderExtensionCapability::direction, |
| RtpTransceiverDirection::kStopped), |
| Field(&RtpHeaderExtensionCapability::direction, |
| RtpTransceiverDirection::kStopped), |
| Field(&RtpHeaderExtensionCapability::direction, |
| RtpTransceiverDirection::kStopped))); |
| |
| EXPECT_CALL(*mock_channel_ptr, SetFirstPacketReceivedCallback(_)); |
| ClearChannel(); |
| } |
| |
| TEST_F(RtpTransceiverTestForHeaderExtensions, ReturnsNegotiatedHdrExts) { |
| const std::string content_name("my_mid"); |
| EXPECT_CALL(*receiver_.get(), SetMediaChannel(_)).WillRepeatedly(Return()); |
| EXPECT_CALL(*receiver_.get(), Stop()).WillRepeatedly(Return()); |
| EXPECT_CALL(*sender_.get(), SetMediaChannel(_)); |
| EXPECT_CALL(*sender_.get(), SetTransceiverAsStopped()); |
| EXPECT_CALL(*sender_.get(), Stop()); |
| |
| auto mock_channel = std::make_unique<cricket::MockChannelInterface>(); |
| auto mock_channel_ptr = mock_channel.get(); |
| EXPECT_CALL(*mock_channel, SetFirstPacketReceivedCallback(_)); |
| EXPECT_CALL(*mock_channel, media_type()) |
| .WillRepeatedly(Return(cricket::MediaType::MEDIA_TYPE_AUDIO)); |
| EXPECT_CALL(*mock_channel, voice_media_send_channel()) |
| .WillRepeatedly(Return(nullptr)); |
| EXPECT_CALL(*mock_channel, mid()).WillRepeatedly(ReturnRef(content_name)); |
| EXPECT_CALL(*mock_channel, SetRtpTransport(_)).WillRepeatedly(Return(true)); |
| |
| cricket::RtpHeaderExtensions extensions = {RtpExtension("uri1", 1), |
| RtpExtension("uri2", 2)}; |
| cricket::AudioContentDescription description; |
| description.set_rtp_header_extensions(extensions); |
| transceiver_->OnNegotiationUpdate(SdpType::kAnswer, &description); |
| |
| transceiver_->SetChannel(std::move(mock_channel), |
| [](const std::string&) { return nullptr; }); |
| |
| EXPECT_THAT(transceiver_->GetNegotiatedHeaderExtensions(), |
| ElementsAre(Field(&RtpHeaderExtensionCapability::direction, |
| RtpTransceiverDirection::kSendRecv), |
| Field(&RtpHeaderExtensionCapability::direction, |
| RtpTransceiverDirection::kSendRecv), |
| Field(&RtpHeaderExtensionCapability::direction, |
| RtpTransceiverDirection::kStopped), |
| Field(&RtpHeaderExtensionCapability::direction, |
| RtpTransceiverDirection::kStopped))); |
| EXPECT_CALL(*mock_channel_ptr, SetFirstPacketReceivedCallback(_)); |
| ClearChannel(); |
| } |
| |
| TEST_F(RtpTransceiverTestForHeaderExtensions, |
| ReturnsNegotiatedHdrExtsSecondTime) { |
| EXPECT_CALL(*receiver_.get(), Stop()); |
| EXPECT_CALL(*receiver_.get(), SetMediaChannel(_)); |
| EXPECT_CALL(*sender_.get(), SetTransceiverAsStopped()); |
| EXPECT_CALL(*sender_.get(), Stop()); |
| |
| cricket::RtpHeaderExtensions extensions = {RtpExtension("uri1", 1), |
| RtpExtension("uri2", 2)}; |
| cricket::AudioContentDescription description; |
| description.set_rtp_header_extensions(extensions); |
| transceiver_->OnNegotiationUpdate(SdpType::kAnswer, &description); |
| |
| EXPECT_THAT(transceiver_->GetNegotiatedHeaderExtensions(), |
| ElementsAre(Field(&RtpHeaderExtensionCapability::direction, |
| RtpTransceiverDirection::kSendRecv), |
| Field(&RtpHeaderExtensionCapability::direction, |
| RtpTransceiverDirection::kSendRecv), |
| Field(&RtpHeaderExtensionCapability::direction, |
| RtpTransceiverDirection::kStopped), |
| Field(&RtpHeaderExtensionCapability::direction, |
| RtpTransceiverDirection::kStopped))); |
| extensions = {RtpExtension("uri3", 4), RtpExtension("uri5", 6)}; |
| description.set_rtp_header_extensions(extensions); |
| transceiver_->OnNegotiationUpdate(SdpType::kAnswer, &description); |
| |
| EXPECT_THAT(transceiver_->GetNegotiatedHeaderExtensions(), |
| ElementsAre(Field(&RtpHeaderExtensionCapability::direction, |
| RtpTransceiverDirection::kStopped), |
| Field(&RtpHeaderExtensionCapability::direction, |
| RtpTransceiverDirection::kStopped), |
| Field(&RtpHeaderExtensionCapability::direction, |
| RtpTransceiverDirection::kStopped), |
| Field(&RtpHeaderExtensionCapability::direction, |
| RtpTransceiverDirection::kStopped))); |
| } |
| |
| TEST_F(RtpTransceiverTestForHeaderExtensions, |
| SimulcastOrSvcEnablesExtensionsByDefault) { |
| std::vector<RtpHeaderExtensionCapability> extensions = { |
| {RtpExtension::kDependencyDescriptorUri, 1, |
| RtpTransceiverDirection::kStopped}, |
| {RtpExtension::kVideoLayersAllocationUri, 2, |
| RtpTransceiverDirection::kStopped}, |
| }; |
| |
| // Default is stopped. |
| auto sender = rtc::make_ref_counted<MockRtpSenderInternal>(); |
| auto transceiver = rtc::make_ref_counted<RtpTransceiver>( |
| RtpSenderProxyWithInternal<RtpSenderInternal>::Create( |
| rtc::Thread::Current(), sender), |
| RtpReceiverProxyWithInternal<RtpReceiverInternal>::Create( |
| rtc::Thread::Current(), rtc::Thread::Current(), receiver_), |
| context(), extensions, |
| /* on_negotiation_needed= */ [] {}); |
| std::vector<webrtc::RtpHeaderExtensionCapability> header_extensions = |
| transceiver->GetHeaderExtensionsToNegotiate(); |
| ASSERT_EQ(header_extensions.size(), 2u); |
| EXPECT_EQ(header_extensions[0].uri, RtpExtension::kDependencyDescriptorUri); |
| EXPECT_EQ(header_extensions[0].direction, RtpTransceiverDirection::kStopped); |
| EXPECT_EQ(header_extensions[1].uri, RtpExtension::kVideoLayersAllocationUri); |
| EXPECT_EQ(header_extensions[1].direction, RtpTransceiverDirection::kStopped); |
| |
| // Simulcast, i.e. more than one encoding. |
| RtpParameters simulcast_parameters; |
| simulcast_parameters.encodings.resize(2); |
| auto simulcast_sender = rtc::make_ref_counted<MockRtpSenderInternal>(); |
| EXPECT_CALL(*simulcast_sender, GetParametersInternal()) |
| .WillRepeatedly(Return(simulcast_parameters)); |
| auto simulcast_transceiver = rtc::make_ref_counted<RtpTransceiver>( |
| RtpSenderProxyWithInternal<RtpSenderInternal>::Create( |
| rtc::Thread::Current(), simulcast_sender), |
| RtpReceiverProxyWithInternal<RtpReceiverInternal>::Create( |
| rtc::Thread::Current(), rtc::Thread::Current(), receiver_), |
| context(), extensions, |
| /* on_negotiation_needed= */ [] {}); |
| auto simulcast_extensions = |
| simulcast_transceiver->GetHeaderExtensionsToNegotiate(); |
| ASSERT_EQ(simulcast_extensions.size(), 2u); |
| EXPECT_EQ(simulcast_extensions[0].uri, |
| RtpExtension::kDependencyDescriptorUri); |
| EXPECT_EQ(simulcast_extensions[0].direction, |
| RtpTransceiverDirection::kSendRecv); |
| EXPECT_EQ(simulcast_extensions[1].uri, |
| RtpExtension::kVideoLayersAllocationUri); |
| EXPECT_EQ(simulcast_extensions[1].direction, |
| RtpTransceiverDirection::kSendRecv); |
| |
| // SVC, a single encoding with a scalabilityMode other than L1T1. |
| webrtc::RtpParameters svc_parameters; |
| svc_parameters.encodings.resize(1); |
| svc_parameters.encodings[0].scalability_mode = "L3T3"; |
| |
| auto svc_sender = rtc::make_ref_counted<MockRtpSenderInternal>(); |
| EXPECT_CALL(*svc_sender, GetParametersInternal()) |
| .WillRepeatedly(Return(svc_parameters)); |
| auto svc_transceiver = rtc::make_ref_counted<RtpTransceiver>( |
| RtpSenderProxyWithInternal<RtpSenderInternal>::Create( |
| rtc::Thread::Current(), svc_sender), |
| RtpReceiverProxyWithInternal<RtpReceiverInternal>::Create( |
| rtc::Thread::Current(), rtc::Thread::Current(), receiver_), |
| context(), extensions, |
| /* on_negotiation_needed= */ [] {}); |
| std::vector<webrtc::RtpHeaderExtensionCapability> svc_extensions = |
| svc_transceiver->GetHeaderExtensionsToNegotiate(); |
| ASSERT_EQ(svc_extensions.size(), 2u); |
| EXPECT_EQ(svc_extensions[0].uri, RtpExtension::kDependencyDescriptorUri); |
| EXPECT_EQ(svc_extensions[0].direction, RtpTransceiverDirection::kSendRecv); |
| EXPECT_EQ(svc_extensions[1].uri, RtpExtension::kVideoLayersAllocationUri); |
| EXPECT_EQ(svc_extensions[1].direction, RtpTransceiverDirection::kSendRecv); |
| } |
| |
| } // namespace |
| |
| } // namespace webrtc |