mirror of
https://github.com/mollyim/webrtc.git
synced 2025-05-12 21:30:45 +01:00

This is a reland of commit 33c7edd58a
taking into account GFD which can be enabled by field trials and somewhat conflicts with DD
Original change's description:
> Enable DD and VLA header extensions by default for Simulcast/SVC
>
> When Simulcast (more than one encoding) or SVC (a scalability mode
> other than the default L1T1) is used, enable the AV1 Dependency
> Descriptor and the video-layer-allocations RTP header extensions by
> default.
>
> The RTP header extensions API can be used to disable them if needed.
>
> BUG=webrtc:15378
>
> Change-Id: I587ac32c9d681461496a136f6950b007e72da86d
> Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/326100
> Reviewed-by: Harald Alvestrand <hta@webrtc.org>
> Reviewed-by: Danil Chapovalov <danilchap@webrtc.org>
> Commit-Queue: Philipp Hancke <phancke@microsoft.com>
> Cr-Commit-Position: refs/heads/main@{#41332}
Bug: webrtc:15378
Change-Id: I190edc9435083c0a0a65a6959363f3c41e4a3d1b
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/330563
Commit-Queue: Philipp Hancke <phancke@microsoft.com>
Reviewed-by: Harald Alvestrand <hta@webrtc.org>
Reviewed-by: Florent Castelli <orphis@webrtc.org>
Reviewed-by: Danil Chapovalov <danilchap@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#41615}
561 lines
24 KiB
C++
561 lines
24 KiB
C++
/*
|
|
* 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 <utility>
|
|
|
|
#include "absl/strings/string_view.h"
|
|
#include "absl/types/optional.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
|