Add simulated time support for PC level test.
Bug: webrtc:11743 Change-Id: If69ab07618a30ec1a66dd5f36b3198486bee55fa Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/178608 Reviewed-by: Mirko Bonadei <mbonadei@webrtc.org> Reviewed-by: Andrey Logvin <landrey@webrtc.org> Reviewed-by: Tommi <tommi@webrtc.org> Commit-Queue: Tommi <tommi@webrtc.org> Cr-Commit-Position: refs/heads/master@{#31639}
This commit is contained in:
parent
a166a353fb
commit
0ef4a2488a
@ -22,12 +22,12 @@ namespace webrtc_pc_e2e {
|
||||
std::unique_ptr<PeerConnectionE2EQualityTestFixture>
|
||||
CreatePeerConnectionE2EQualityTestFixture(
|
||||
std::string test_case_name,
|
||||
TimeController& /*time_controller*/,
|
||||
TimeController& time_controller,
|
||||
std::unique_ptr<AudioQualityAnalyzerInterface> audio_quality_analyzer,
|
||||
std::unique_ptr<VideoQualityAnalyzerInterface> video_quality_analyzer) {
|
||||
return std::make_unique<PeerConnectionE2EQualityTest>(
|
||||
std::move(test_case_name), std::move(audio_quality_analyzer),
|
||||
std::move(video_quality_analyzer));
|
||||
std::move(test_case_name), time_controller,
|
||||
std::move(audio_quality_analyzer), std::move(video_quality_analyzer));
|
||||
}
|
||||
|
||||
} // namespace webrtc_pc_e2e
|
||||
|
||||
@ -46,6 +46,7 @@ class TimeController {
|
||||
const char* thread_name) = 0;
|
||||
// Creates an rtc::Thread instance. If |socket_server| is nullptr, a default
|
||||
// noop socket server is created.
|
||||
// Returned thread is not null and started.
|
||||
virtual std::unique_ptr<rtc::Thread> CreateThread(
|
||||
const std::string& name,
|
||||
std::unique_ptr<rtc::SocketServer> socket_server = nullptr) = 0;
|
||||
|
||||
@ -260,6 +260,7 @@ if (!build_with_chromium) {
|
||||
":test_peer",
|
||||
":video_quality_analyzer_injection_helper",
|
||||
"../..:copy_to_file_audio_capturer",
|
||||
"../../../api:create_time_controller",
|
||||
"../../../api:peer_connection_quality_test_fixture_api",
|
||||
"../../../api:time_controller",
|
||||
"../../../api/rtc_event_log:rtc_event_log_factory",
|
||||
@ -385,6 +386,7 @@ if (!build_with_chromium) {
|
||||
"../../../api:peer_connection_quality_test_fixture_api",
|
||||
"../../../api:rtc_event_log_output_file",
|
||||
"../../../api:scoped_refptr",
|
||||
"../../../api:time_controller",
|
||||
"../../../api:video_quality_analyzer_api",
|
||||
"../../../api/rtc_event_log",
|
||||
"../../../api/task_queue",
|
||||
|
||||
@ -120,13 +120,19 @@ bool operator==(const InternalStatsKey& a, const InternalStatsKey& b) {
|
||||
a.receiver == b.receiver;
|
||||
}
|
||||
|
||||
DefaultVideoQualityAnalyzer::DefaultVideoQualityAnalyzer(
|
||||
webrtc::Clock* clock,
|
||||
DefaultVideoQualityAnalyzerOptions options)
|
||||
: options_(options), clock_(clock) {}
|
||||
DefaultVideoQualityAnalyzer::DefaultVideoQualityAnalyzer(
|
||||
bool heavy_metrics_computation_enabled,
|
||||
size_t max_frames_in_flight_per_stream_count)
|
||||
: heavy_metrics_computation_enabled_(heavy_metrics_computation_enabled),
|
||||
max_frames_in_flight_per_stream_count_(
|
||||
max_frames_in_flight_per_stream_count),
|
||||
clock_(Clock::GetRealTimeClock()) {}
|
||||
: clock_(Clock::GetRealTimeClock()) {
|
||||
options_.heavy_metrics_computation_enabled =
|
||||
heavy_metrics_computation_enabled;
|
||||
options_.max_frames_in_flight_per_stream_count =
|
||||
max_frames_in_flight_per_stream_count;
|
||||
}
|
||||
DefaultVideoQualityAnalyzer::~DefaultVideoQualityAnalyzer() {
|
||||
Stop();
|
||||
}
|
||||
@ -256,7 +262,8 @@ uint16_t DefaultVideoQualityAnalyzer::OnFrameCaptured(
|
||||
|
||||
// If state has too many frames that are in flight => remove the oldest
|
||||
// queued frame in order to avoid to use too much memory.
|
||||
if (state->GetAliveFramesCount() > max_frames_in_flight_per_stream_count_) {
|
||||
if (state->GetAliveFramesCount() >
|
||||
options_.max_frames_in_flight_per_stream_count) {
|
||||
uint16_t frame_id_to_remove = state->MarkNextAliveFrameAsDead();
|
||||
auto it = captured_frames_in_flight_.find(frame_id_to_remove);
|
||||
RTC_CHECK(it != captured_frames_in_flight_.end())
|
||||
@ -677,7 +684,7 @@ void DefaultVideoQualityAnalyzer::ProcessComparison(
|
||||
// Perform expensive psnr and ssim calculations while not holding lock.
|
||||
double psnr = -1.0;
|
||||
double ssim = -1.0;
|
||||
if (heavy_metrics_computation_enabled_ && comparison.captured &&
|
||||
if (options_.heavy_metrics_computation_enabled && comparison.captured &&
|
||||
!comparison.dropped) {
|
||||
psnr = I420PSNR(&*comparison.captured, &*comparison.rendered);
|
||||
ssim = I420SSIM(&*comparison.captured, &*comparison.rendered);
|
||||
|
||||
@ -166,8 +166,24 @@ struct InternalStatsKey {
|
||||
bool operator<(const InternalStatsKey& a, const InternalStatsKey& b);
|
||||
bool operator==(const InternalStatsKey& a, const InternalStatsKey& b);
|
||||
|
||||
struct DefaultVideoQualityAnalyzerOptions {
|
||||
// Tells DefaultVideoQualityAnalyzer if heavy metrics like PSNR and SSIM have
|
||||
// to be computed or not.
|
||||
bool heavy_metrics_computation_enabled = true;
|
||||
// Amount of frames that are queued in the DefaultVideoQualityAnalyzer from
|
||||
// the point they were captured to the point they were rendered on all
|
||||
// receivers per stream.
|
||||
size_t max_frames_in_flight_per_stream_count =
|
||||
kDefaultMaxFramesInFlightPerStream;
|
||||
};
|
||||
|
||||
class DefaultVideoQualityAnalyzer : public VideoQualityAnalyzerInterface {
|
||||
public:
|
||||
explicit DefaultVideoQualityAnalyzer(
|
||||
webrtc::Clock* clock,
|
||||
DefaultVideoQualityAnalyzerOptions options =
|
||||
DefaultVideoQualityAnalyzerOptions());
|
||||
// Keep for backward compatibility during migration. Will be removed soon.
|
||||
explicit DefaultVideoQualityAnalyzer(
|
||||
bool heavy_metrics_computation_enabled = true,
|
||||
size_t max_frames_in_flight_per_stream_count =
|
||||
@ -483,8 +499,8 @@ class DefaultVideoQualityAnalyzer : public VideoQualityAnalyzerInterface {
|
||||
void StopExcludingCpuThreadTime();
|
||||
double GetCpuUsagePercent();
|
||||
|
||||
const bool heavy_metrics_computation_enabled_;
|
||||
const size_t max_frames_in_flight_per_stream_count_;
|
||||
// TODO(titovartem) restore const when old constructor will be removed.
|
||||
DefaultVideoQualityAnalyzerOptions options_;
|
||||
webrtc::Clock* const clock_;
|
||||
std::atomic<uint16_t> next_frame_id_{0};
|
||||
|
||||
|
||||
@ -37,6 +37,13 @@ constexpr char kStreamLabel[] = "video-stream";
|
||||
constexpr char kSenderPeerName[] = "alice";
|
||||
constexpr char kReceiverPeerName[] = "bob";
|
||||
|
||||
DefaultVideoQualityAnalyzerOptions AnalyzerOptionsForTest() {
|
||||
DefaultVideoQualityAnalyzerOptions options;
|
||||
options.heavy_metrics_computation_enabled = false;
|
||||
options.max_frames_in_flight_per_stream_count = kMaxFramesInFlightPerStream;
|
||||
return options;
|
||||
}
|
||||
|
||||
VideoFrame NextFrame(test::FrameGeneratorInterface* frame_generator,
|
||||
int64_t timestamp_us) {
|
||||
test::FrameGeneratorInterface::VideoFrameData frame_data =
|
||||
@ -94,8 +101,8 @@ TEST(DefaultVideoQualityAnalyzerTest,
|
||||
/*type=*/absl::nullopt,
|
||||
/*num_squares=*/absl::nullopt);
|
||||
|
||||
DefaultVideoQualityAnalyzer analyzer(
|
||||
/*heavy_metrics_computation_enabled=*/false, kMaxFramesInFlightPerStream);
|
||||
DefaultVideoQualityAnalyzer analyzer(Clock::GetRealTimeClock(),
|
||||
AnalyzerOptionsForTest());
|
||||
analyzer.Start("test_case",
|
||||
std::vector<std::string>{kSenderPeerName, kReceiverPeerName},
|
||||
kAnalyzerMaxThreadsCount);
|
||||
@ -145,8 +152,8 @@ TEST(DefaultVideoQualityAnalyzerTest,
|
||||
/*type=*/absl::nullopt,
|
||||
/*num_squares=*/absl::nullopt);
|
||||
|
||||
DefaultVideoQualityAnalyzer analyzer(
|
||||
/*heavy_metrics_computation_enabled=*/false, kMaxFramesInFlightPerStream);
|
||||
DefaultVideoQualityAnalyzer analyzer(Clock::GetRealTimeClock(),
|
||||
AnalyzerOptionsForTest());
|
||||
analyzer.Start("test_case",
|
||||
std::vector<std::string>{kSenderPeerName, kReceiverPeerName},
|
||||
kAnalyzerMaxThreadsCount);
|
||||
@ -226,8 +233,8 @@ TEST(DefaultVideoQualityAnalyzerTest,
|
||||
/*type=*/absl::nullopt,
|
||||
/*num_squares=*/absl::nullopt);
|
||||
|
||||
DefaultVideoQualityAnalyzer analyzer(
|
||||
/*heavy_metrics_computation_enabled=*/false, kMaxFramesInFlightPerStream);
|
||||
DefaultVideoQualityAnalyzer analyzer(Clock::GetRealTimeClock(),
|
||||
AnalyzerOptionsForTest());
|
||||
analyzer.Start("test_case",
|
||||
std::vector<std::string>{kSenderPeerName, kReceiverPeerName},
|
||||
kAnalyzerMaxThreadsCount);
|
||||
@ -276,8 +283,8 @@ TEST(DefaultVideoQualityAnalyzerTest, NormalScenario) {
|
||||
/*type=*/absl::nullopt,
|
||||
/*num_squares=*/absl::nullopt);
|
||||
|
||||
DefaultVideoQualityAnalyzer analyzer(
|
||||
/*heavy_metrics_computation_enabled=*/false, kMaxFramesInFlightPerStream);
|
||||
DefaultVideoQualityAnalyzer analyzer(Clock::GetRealTimeClock(),
|
||||
AnalyzerOptionsForTest());
|
||||
analyzer.Start("test_case",
|
||||
std::vector<std::string>{kSenderPeerName, kReceiverPeerName},
|
||||
kAnalyzerMaxThreadsCount);
|
||||
@ -334,8 +341,8 @@ TEST(DefaultVideoQualityAnalyzerTest, OneFrameReceivedTwice) {
|
||||
/*type=*/absl::nullopt,
|
||||
/*num_squares=*/absl::nullopt);
|
||||
|
||||
DefaultVideoQualityAnalyzer analyzer(
|
||||
/*heavy_metrics_computation_enabled=*/false, kMaxFramesInFlightPerStream);
|
||||
DefaultVideoQualityAnalyzer analyzer(Clock::GetRealTimeClock(),
|
||||
AnalyzerOptionsForTest());
|
||||
analyzer.Start("test_case",
|
||||
std::vector<std::string>{kSenderPeerName, kReceiverPeerName},
|
||||
kAnalyzerMaxThreadsCount);
|
||||
@ -390,8 +397,8 @@ TEST(DefaultVideoQualityAnalyzerTest, NormalScenario2Receivers) {
|
||||
constexpr char kBob[] = "bob";
|
||||
constexpr char kCharlie[] = "charlie";
|
||||
|
||||
DefaultVideoQualityAnalyzer analyzer(
|
||||
/*heavy_metrics_computation_enabled=*/false, kMaxFramesInFlightPerStream);
|
||||
DefaultVideoQualityAnalyzer analyzer(Clock::GetRealTimeClock(),
|
||||
AnalyzerOptionsForTest());
|
||||
analyzer.Start("test_case", std::vector<std::string>{kAlice, kBob, kCharlie},
|
||||
kAnalyzerMaxThreadsCount);
|
||||
|
||||
@ -508,8 +515,8 @@ TEST(DefaultVideoQualityAnalyzerTest, OneFrameReceivedTwiceWith2Receivers) {
|
||||
constexpr char kBob[] = "bob";
|
||||
constexpr char kCharlie[] = "charlie";
|
||||
|
||||
DefaultVideoQualityAnalyzer analyzer(
|
||||
/*heavy_metrics_computation_enabled=*/false, kMaxFramesInFlightPerStream);
|
||||
DefaultVideoQualityAnalyzer analyzer(Clock::GetRealTimeClock(),
|
||||
AnalyzerOptionsForTest());
|
||||
analyzer.Start("test_case", std::vector<std::string>{kAlice, kBob, kCharlie},
|
||||
kAnalyzerMaxThreadsCount);
|
||||
|
||||
|
||||
@ -74,7 +74,8 @@ class PeerConnectionE2EQualityTestSmokeTest : public ::testing::Test {
|
||||
|
||||
// Create analyzers.
|
||||
std::unique_ptr<VideoQualityAnalyzerInterface> video_quality_analyzer =
|
||||
std::make_unique<DefaultVideoQualityAnalyzer>();
|
||||
std::make_unique<DefaultVideoQualityAnalyzer>(
|
||||
network_emulation_manager->time_controller()->GetClock());
|
||||
// This is only done for the sake of smoke testing. In general there should
|
||||
// be no need to explicitly pull data from analyzers after the run.
|
||||
auto* video_analyzer_ptr =
|
||||
|
||||
@ -22,6 +22,7 @@
|
||||
#include "api/rtc_event_log_output_file.h"
|
||||
#include "api/scoped_refptr.h"
|
||||
#include "api/task_queue/default_task_queue_factory.h"
|
||||
#include "api/test/time_controller.h"
|
||||
#include "api/test/video_quality_analyzer_interface.h"
|
||||
#include "pc/sdp_utils.h"
|
||||
#include "pc/test/mock_peer_connection_observers.h"
|
||||
@ -46,7 +47,7 @@ namespace {
|
||||
using VideoConfig = PeerConnectionE2EQualityTestFixture::VideoConfig;
|
||||
using VideoCodecConfig = PeerConnectionE2EQualityTestFixture::VideoCodecConfig;
|
||||
|
||||
constexpr int kDefaultTimeoutMs = 10000;
|
||||
constexpr TimeDelta kDefaultTimeout = TimeDelta::Seconds(10);
|
||||
constexpr char kSignalThreadName[] = "signaling_thread";
|
||||
// 1 signaling, 2 network, 2 worker and 2 extra for codecs etc.
|
||||
constexpr int kPeerConnectionUsedThreads = 7;
|
||||
@ -59,7 +60,7 @@ constexpr TimeDelta kStatsUpdateInterval = TimeDelta::Seconds(1);
|
||||
|
||||
constexpr TimeDelta kAliveMessageLogInterval = TimeDelta::Seconds(30);
|
||||
|
||||
constexpr int kQuickTestModeRunDurationMs = 100;
|
||||
constexpr TimeDelta kQuickTestModeRunDuration = TimeDelta::Millis(100);
|
||||
|
||||
// Field trials to enable Flex FEC advertising and receiving.
|
||||
constexpr char kFlexFecEnabledFieldTrials[] =
|
||||
@ -104,17 +105,20 @@ class FixturePeerConnectionObserver : public MockPeerConnectionObserver {
|
||||
|
||||
PeerConnectionE2EQualityTest::PeerConnectionE2EQualityTest(
|
||||
std::string test_case_name,
|
||||
TimeController& time_controller,
|
||||
std::unique_ptr<AudioQualityAnalyzerInterface> audio_quality_analyzer,
|
||||
std::unique_ptr<VideoQualityAnalyzerInterface> video_quality_analyzer)
|
||||
: clock_(Clock::GetRealTimeClock()),
|
||||
: time_controller_(time_controller),
|
||||
task_queue_factory_(CreateDefaultTaskQueueFactory()),
|
||||
test_case_name_(std::move(test_case_name)),
|
||||
executor_(std::make_unique<TestActivitiesExecutor>(clock_)) {
|
||||
executor_(std::make_unique<TestActivitiesExecutor>(
|
||||
time_controller_.GetClock())) {
|
||||
// Create default video quality analyzer. We will always create an analyzer,
|
||||
// even if there are no video streams, because it will be installed into video
|
||||
// encoder/decoder factories.
|
||||
if (video_quality_analyzer == nullptr) {
|
||||
video_quality_analyzer = std::make_unique<DefaultVideoQualityAnalyzer>();
|
||||
video_quality_analyzer = std::make_unique<DefaultVideoQualityAnalyzer>(
|
||||
time_controller_.GetClock());
|
||||
}
|
||||
encoded_image_id_controller_ =
|
||||
std::make_unique<SingleProcessEncodedImageDataInjector>();
|
||||
@ -189,15 +193,16 @@ void PeerConnectionE2EQualityTest::Run(RunParams run_params) {
|
||||
<< "; audio="
|
||||
<< bob_configurer->params()->audio_config.has_value();
|
||||
|
||||
const std::unique_ptr<rtc::Thread> signaling_thread = rtc::Thread::Create();
|
||||
signaling_thread->SetName(kSignalThreadName, nullptr);
|
||||
signaling_thread->Start();
|
||||
const std::unique_ptr<rtc::Thread> signaling_thread =
|
||||
time_controller_.CreateThread(kSignalThreadName);
|
||||
media_helper_ = std::make_unique<MediaHelper>(
|
||||
video_quality_analyzer_injection_helper_.get(),
|
||||
task_queue_factory_.get());
|
||||
|
||||
// Create a |task_queue_|.
|
||||
task_queue_ = std::make_unique<TaskQueueForTest>("pc_e2e_quality_test");
|
||||
task_queue_ = std::make_unique<webrtc::TaskQueueForTest>(
|
||||
time_controller_.GetTaskQueueFactory()->CreateTaskQueue(
|
||||
"pc_e2e_quality_test", webrtc::TaskQueueFactory::Priority::NORMAL));
|
||||
|
||||
// Create call participants: Alice and Bob.
|
||||
// Audio streams are intercepted in AudioDeviceModule, so if it is required to
|
||||
@ -217,8 +222,8 @@ void PeerConnectionE2EQualityTest::Run(RunParams run_params) {
|
||||
std::string bob_name = bob_configurer->params()->name.value();
|
||||
|
||||
TestPeerFactory test_peer_factory(
|
||||
signaling_thread.get(), video_quality_analyzer_injection_helper_.get(),
|
||||
task_queue_.get());
|
||||
signaling_thread.get(), time_controller_,
|
||||
video_quality_analyzer_injection_helper_.get(), task_queue_.get());
|
||||
alice_ = test_peer_factory.CreateTestPeer(
|
||||
std::move(alice_configurer),
|
||||
std::make_unique<FixturePeerConnectionObserver>(
|
||||
@ -252,7 +257,8 @@ void PeerConnectionE2EQualityTest::Run(RunParams run_params) {
|
||||
std::min(video_analyzer_threads, kMaxVideoAnalyzerThreads);
|
||||
RTC_LOG(INFO) << "video_analyzer_threads=" << video_analyzer_threads;
|
||||
quality_metrics_reporters_.push_back(
|
||||
std::make_unique<VideoQualityMetricsReporter>(clock_));
|
||||
std::make_unique<VideoQualityMetricsReporter>(
|
||||
time_controller_.GetClock()));
|
||||
quality_metrics_reporters_.push_back(
|
||||
std::make_unique<CrossMediaMetricsReporter>());
|
||||
|
||||
@ -310,15 +316,29 @@ void PeerConnectionE2EQualityTest::Run(RunParams run_params) {
|
||||
RTC_FROM_HERE,
|
||||
rtc::Bind(&PeerConnectionE2EQualityTest::SetupCallOnSignalingThread, this,
|
||||
run_params));
|
||||
std::unique_ptr<SignalingInterceptor> signaling_interceptor =
|
||||
CreateSignalingInterceptor(run_params);
|
||||
// Connect peers.
|
||||
signaling_thread->Invoke<void>(
|
||||
RTC_FROM_HERE,
|
||||
rtc::Bind(&PeerConnectionE2EQualityTest::ExchangeOfferAnswer, this,
|
||||
signaling_interceptor.get()));
|
||||
WaitUntilIceCandidatesGathered(signaling_thread.get());
|
||||
|
||||
signaling_thread->Invoke<void>(
|
||||
RTC_FROM_HERE,
|
||||
rtc::Bind(&PeerConnectionE2EQualityTest::ExchangeIceCandidates, this,
|
||||
signaling_interceptor.get()));
|
||||
WaitUntilPeersAreConnected(signaling_thread.get());
|
||||
|
||||
executor_->Start(task_queue_.get());
|
||||
Timestamp start_time = Now();
|
||||
|
||||
rtc::Event done;
|
||||
bool is_quick_test_enabled = field_trial::IsEnabled("WebRTC-QuickPerfTest");
|
||||
if (is_quick_test_enabled) {
|
||||
done.Wait(kQuickTestModeRunDurationMs);
|
||||
time_controller_.AdvanceTime(kQuickTestModeRunDuration);
|
||||
} else {
|
||||
done.Wait(run_params.run_duration.ms());
|
||||
time_controller_.AdvanceTime(run_params.run_duration);
|
||||
}
|
||||
|
||||
RTC_LOG(INFO) << "Test is done, initiating disconnect sequence.";
|
||||
@ -483,8 +503,6 @@ void PeerConnectionE2EQualityTest::SetupCallOnSignalingThread(
|
||||
|
||||
SetPeerCodecPreferences(alice_.get(), run_params);
|
||||
SetPeerCodecPreferences(bob_.get(), run_params);
|
||||
|
||||
SetupCall(run_params);
|
||||
}
|
||||
|
||||
void PeerConnectionE2EQualityTest::TearDownCallOnSignalingThread() {
|
||||
@ -527,7 +545,9 @@ void PeerConnectionE2EQualityTest::SetPeerCodecPreferences(
|
||||
}
|
||||
}
|
||||
|
||||
void PeerConnectionE2EQualityTest::SetupCall(const RunParams& run_params) {
|
||||
std::unique_ptr<SignalingInterceptor>
|
||||
PeerConnectionE2EQualityTest::CreateSignalingInterceptor(
|
||||
const RunParams& run_params) {
|
||||
std::map<std::string, int> stream_label_to_simulcast_streams_count;
|
||||
// We add only Alice here, because simulcast/svc is supported only from the
|
||||
// first peer.
|
||||
@ -541,21 +561,32 @@ void PeerConnectionE2EQualityTest::SetupCall(const RunParams& run_params) {
|
||||
PatchingParams patching_params(run_params.video_codecs,
|
||||
run_params.use_conference_mode,
|
||||
stream_label_to_simulcast_streams_count);
|
||||
SignalingInterceptor signaling_interceptor(patching_params);
|
||||
// Connect peers.
|
||||
ExchangeOfferAnswer(&signaling_interceptor);
|
||||
// Do the SDP negotiation, and also exchange ice candidates.
|
||||
ASSERT_EQ_WAIT(alice_->signaling_state(), PeerConnectionInterface::kStable,
|
||||
kDefaultTimeoutMs);
|
||||
ASSERT_TRUE_WAIT(alice_->IsIceGatheringDone(), kDefaultTimeoutMs);
|
||||
ASSERT_TRUE_WAIT(bob_->IsIceGatheringDone(), kDefaultTimeoutMs);
|
||||
return std::make_unique<SignalingInterceptor>(patching_params);
|
||||
}
|
||||
|
||||
ExchangeIceCandidates(&signaling_interceptor);
|
||||
void PeerConnectionE2EQualityTest::WaitUntilIceCandidatesGathered(
|
||||
rtc::Thread* signaling_thread) {
|
||||
ASSERT_TRUE(time_controller_.Wait(
|
||||
[&]() {
|
||||
return signaling_thread->Invoke<bool>(RTC_FROM_HERE, [&]() {
|
||||
return alice_->IsIceGatheringDone() && bob_->IsIceGatheringDone();
|
||||
});
|
||||
},
|
||||
2 * kDefaultTimeout));
|
||||
}
|
||||
|
||||
void PeerConnectionE2EQualityTest::WaitUntilPeersAreConnected(
|
||||
rtc::Thread* signaling_thread) {
|
||||
// This means that ICE and DTLS are connected.
|
||||
WAIT(bob_->IsIceConnected(), kDefaultTimeoutMs);
|
||||
bob_connected_ = bob_->IsIceConnected();
|
||||
WAIT(alice_->IsIceConnected(), kDefaultTimeoutMs);
|
||||
time_controller_.Wait(
|
||||
[&]() {
|
||||
return signaling_thread->Invoke<bool>(RTC_FROM_HERE, [&]() {
|
||||
return alice_->IsIceConnected() && bob_->IsIceConnected();
|
||||
});
|
||||
},
|
||||
2 * kDefaultTimeout);
|
||||
alice_connected_ = alice_->IsIceConnected();
|
||||
bob_connected_ = bob_->IsIceConnected();
|
||||
}
|
||||
|
||||
void PeerConnectionE2EQualityTest::ExchangeOfferAnswer(
|
||||
@ -663,7 +694,7 @@ void PeerConnectionE2EQualityTest::ReportGeneralTestResults() {
|
||||
}
|
||||
|
||||
Timestamp PeerConnectionE2EQualityTest::Now() const {
|
||||
return clock_->CurrentTime();
|
||||
return time_controller_.GetClock()->CurrentTime();
|
||||
}
|
||||
|
||||
} // namespace webrtc_pc_e2e
|
||||
|
||||
@ -19,6 +19,7 @@
|
||||
#include "api/task_queue/task_queue_factory.h"
|
||||
#include "api/test/audio_quality_analyzer_interface.h"
|
||||
#include "api/test/peerconnection_quality_test_fixture.h"
|
||||
#include "api/test/time_controller.h"
|
||||
#include "api/units/time_delta.h"
|
||||
#include "api/units/timestamp.h"
|
||||
#include "rtc_base/task_queue_for_test.h"
|
||||
@ -52,6 +53,7 @@ class PeerConnectionE2EQualityTest
|
||||
|
||||
PeerConnectionE2EQualityTest(
|
||||
std::string test_case_name,
|
||||
TimeController& time_controller,
|
||||
std::unique_ptr<AudioQualityAnalyzerInterface> audio_quality_analyzer,
|
||||
std::unique_ptr<VideoQualityAnalyzerInterface> video_quality_analyzer);
|
||||
|
||||
@ -88,7 +90,10 @@ class PeerConnectionE2EQualityTest
|
||||
void SetupCallOnSignalingThread(const RunParams& run_params);
|
||||
void TearDownCallOnSignalingThread();
|
||||
void SetPeerCodecPreferences(TestPeer* peer, const RunParams& run_params);
|
||||
void SetupCall(const RunParams& run_params);
|
||||
std::unique_ptr<SignalingInterceptor> CreateSignalingInterceptor(
|
||||
const RunParams& run_params);
|
||||
void WaitUntilIceCandidatesGathered(rtc::Thread* signaling_thread);
|
||||
void WaitUntilPeersAreConnected(rtc::Thread* signaling_thread);
|
||||
void ExchangeOfferAnswer(SignalingInterceptor* signaling_interceptor);
|
||||
void ExchangeIceCandidates(SignalingInterceptor* signaling_interceptor);
|
||||
void StartVideo(
|
||||
@ -98,7 +103,7 @@ class PeerConnectionE2EQualityTest
|
||||
void ReportGeneralTestResults();
|
||||
Timestamp Now() const;
|
||||
|
||||
Clock* const clock_;
|
||||
TimeController& time_controller_;
|
||||
const std::unique_ptr<TaskQueueFactory> task_queue_factory_;
|
||||
std::string test_case_name_;
|
||||
std::unique_ptr<VideoQualityAnalyzerInjectionHelper>
|
||||
|
||||
@ -43,10 +43,12 @@ TestPeer::TestPeer(
|
||||
std::unique_ptr<MockPeerConnectionObserver> observer,
|
||||
std::unique_ptr<Params> params,
|
||||
std::vector<PeerConfigurerImpl::VideoSource> video_sources,
|
||||
rtc::scoped_refptr<AudioProcessing> audio_processing)
|
||||
: PeerConnectionWrapper::PeerConnectionWrapper(std::move(pc_factory),
|
||||
std::move(pc),
|
||||
std::move(observer)),
|
||||
rtc::scoped_refptr<AudioProcessing> audio_processing,
|
||||
std::unique_ptr<rtc::Thread> worker_thread)
|
||||
: worker_thread_(std::move(worker_thread)),
|
||||
wrapper_(std::make_unique<PeerConnectionWrapper>(std::move(pc_factory),
|
||||
std::move(pc),
|
||||
std::move(observer))),
|
||||
params_(std::move(params)),
|
||||
video_sources_(std::move(video_sources)),
|
||||
audio_processing_(audio_processing) {}
|
||||
|
||||
@ -26,15 +26,66 @@ namespace webrtc {
|
||||
namespace webrtc_pc_e2e {
|
||||
|
||||
// Describes a single participant in the call.
|
||||
class TestPeer final : public PeerConnectionWrapper {
|
||||
class TestPeer final {
|
||||
public:
|
||||
using PeerConnectionWrapper::PeerConnectionWrapper;
|
||||
|
||||
Params* params() const { return params_.get(); }
|
||||
PeerConfigurerImpl::VideoSource ReleaseVideoSource(size_t i) {
|
||||
return std::move(video_sources_[i]);
|
||||
}
|
||||
|
||||
PeerConnectionFactoryInterface* pc_factory() {
|
||||
return wrapper_->pc_factory();
|
||||
}
|
||||
PeerConnectionInterface* pc() { return wrapper_->pc(); }
|
||||
MockPeerConnectionObserver* observer() { return wrapper_->observer(); }
|
||||
|
||||
std::unique_ptr<SessionDescriptionInterface> CreateOffer() {
|
||||
return wrapper_->CreateOffer();
|
||||
}
|
||||
|
||||
std::unique_ptr<SessionDescriptionInterface> CreateAnswer() {
|
||||
return wrapper_->CreateAnswer();
|
||||
}
|
||||
|
||||
bool SetLocalDescription(std::unique_ptr<SessionDescriptionInterface> desc,
|
||||
std::string* error_out = nullptr) {
|
||||
return wrapper_->SetLocalDescription(std::move(desc), error_out);
|
||||
}
|
||||
|
||||
bool SetRemoteDescription(std::unique_ptr<SessionDescriptionInterface> desc,
|
||||
std::string* error_out = nullptr) {
|
||||
return wrapper_->SetRemoteDescription(std::move(desc), error_out);
|
||||
}
|
||||
|
||||
rtc::scoped_refptr<RtpTransceiverInterface> AddTransceiver(
|
||||
cricket::MediaType media_type,
|
||||
const RtpTransceiverInit& init) {
|
||||
return wrapper_->AddTransceiver(media_type, init);
|
||||
}
|
||||
|
||||
rtc::scoped_refptr<RtpSenderInterface> AddTrack(
|
||||
rtc::scoped_refptr<MediaStreamTrackInterface> track,
|
||||
const std::vector<std::string>& stream_ids = {}) {
|
||||
return wrapper_->AddTrack(track, stream_ids);
|
||||
}
|
||||
|
||||
rtc::scoped_refptr<DataChannelInterface> CreateDataChannel(
|
||||
const std::string& label) {
|
||||
return wrapper_->CreateDataChannel(label);
|
||||
}
|
||||
|
||||
PeerConnectionInterface::SignalingState signaling_state() {
|
||||
return wrapper_->signaling_state();
|
||||
}
|
||||
|
||||
bool IsIceGatheringDone() { return wrapper_->IsIceGatheringDone(); }
|
||||
|
||||
bool IsIceConnected() { return wrapper_->IsIceConnected(); }
|
||||
|
||||
rtc::scoped_refptr<const RTCStatsReport> GetStats() {
|
||||
return wrapper_->GetStats();
|
||||
}
|
||||
|
||||
void DetachAecDump() {
|
||||
if (audio_processing_) {
|
||||
audio_processing_->DetachAecDump();
|
||||
@ -52,9 +103,13 @@ class TestPeer final : public PeerConnectionWrapper {
|
||||
std::unique_ptr<MockPeerConnectionObserver> observer,
|
||||
std::unique_ptr<Params> params,
|
||||
std::vector<PeerConfigurerImpl::VideoSource> video_sources,
|
||||
rtc::scoped_refptr<AudioProcessing> audio_processing);
|
||||
rtc::scoped_refptr<AudioProcessing> audio_processing,
|
||||
std::unique_ptr<rtc::Thread> worker_thread);
|
||||
|
||||
private:
|
||||
// Keeps ownership of worker thread. It has to be destroyed after |wrapper_|.
|
||||
std::unique_ptr<rtc::Thread> worker_thread_;
|
||||
std::unique_ptr<PeerConnectionWrapper> wrapper_;
|
||||
std::unique_ptr<Params> params_;
|
||||
std::vector<PeerConfigurerImpl::VideoSource> video_sources_;
|
||||
rtc::scoped_refptr<AudioProcessing> audio_processing_;
|
||||
|
||||
@ -14,6 +14,8 @@
|
||||
#include "absl/memory/memory.h"
|
||||
#include "absl/strings/string_view.h"
|
||||
#include "api/task_queue/default_task_queue_factory.h"
|
||||
#include "api/test/create_time_controller.h"
|
||||
#include "api/test/time_controller.h"
|
||||
#include "api/video_codecs/builtin_video_decoder_factory.h"
|
||||
#include "api/video_codecs/builtin_video_encoder_factory.h"
|
||||
#include "media/engine/webrtc_media_engine.h"
|
||||
@ -43,17 +45,19 @@ constexpr int kDefaultSamplingFrequencyInHz = 48000;
|
||||
// and |pc_dependencies| if they are omitted. Also setup required
|
||||
// dependencies, that won't be specially provided by factory and will be just
|
||||
// transferred to peer connection creation code.
|
||||
void SetMandatoryEntities(InjectableComponents* components) {
|
||||
void SetMandatoryEntities(InjectableComponents* components,
|
||||
TimeController& time_controller) {
|
||||
RTC_DCHECK(components->pcf_dependencies);
|
||||
RTC_DCHECK(components->pc_dependencies);
|
||||
|
||||
// Setup required peer connection factory dependencies.
|
||||
if (components->pcf_dependencies->task_queue_factory == nullptr) {
|
||||
components->pcf_dependencies->task_queue_factory =
|
||||
CreateDefaultTaskQueueFactory();
|
||||
time_controller.CreateTaskQueueFactory();
|
||||
}
|
||||
if (components->pcf_dependencies->call_factory == nullptr) {
|
||||
components->pcf_dependencies->call_factory = webrtc::CreateCallFactory();
|
||||
components->pcf_dependencies->call_factory =
|
||||
CreateTimeControllerBasedCallFactory(&time_controller);
|
||||
}
|
||||
if (components->pcf_dependencies->event_log_factory == nullptr) {
|
||||
components->pcf_dependencies->event_log_factory =
|
||||
@ -211,10 +215,12 @@ PeerConnectionFactoryDependencies CreatePCFDependencies(
|
||||
std::unique_ptr<PeerConnectionFactoryComponents> pcf_dependencies,
|
||||
std::unique_ptr<cricket::MediaEngineInterface> media_engine,
|
||||
rtc::Thread* signaling_thread,
|
||||
rtc::Thread* worker_thread,
|
||||
rtc::Thread* network_thread) {
|
||||
PeerConnectionFactoryDependencies pcf_deps;
|
||||
pcf_deps.network_thread = network_thread;
|
||||
pcf_deps.signaling_thread = signaling_thread;
|
||||
pcf_deps.worker_thread = worker_thread;
|
||||
pcf_deps.network_thread = network_thread;
|
||||
pcf_deps.media_engine = std::move(media_engine);
|
||||
|
||||
pcf_deps.call_factory = std::move(pcf_dependencies->call_factory);
|
||||
@ -282,13 +288,10 @@ absl::optional<RemotePeerAudioConfig> RemotePeerAudioConfig::Create(
|
||||
std::unique_ptr<TestPeer> TestPeerFactory::CreateTestPeer(
|
||||
std::unique_ptr<PeerConfigurerImpl> configurer,
|
||||
std::unique_ptr<MockPeerConnectionObserver> observer,
|
||||
VideoQualityAnalyzerInjectionHelper* video_analyzer_helper,
|
||||
rtc::Thread* signaling_thread,
|
||||
absl::optional<RemotePeerAudioConfig> remote_audio_config,
|
||||
double bitrate_multiplier,
|
||||
absl::optional<PeerConnectionE2EQualityTestFixture::EchoEmulationConfig>
|
||||
echo_emulation_config,
|
||||
rtc::TaskQueue* task_queue) {
|
||||
echo_emulation_config) {
|
||||
std::unique_ptr<InjectableComponents> components =
|
||||
configurer->ReleaseComponents();
|
||||
std::unique_ptr<Params> params = configurer->ReleaseParams();
|
||||
@ -297,7 +300,7 @@ std::unique_ptr<TestPeer> TestPeerFactory::CreateTestPeer(
|
||||
RTC_DCHECK(components);
|
||||
RTC_DCHECK(params);
|
||||
RTC_DCHECK_EQ(params->video_configs.size(), video_sources.size());
|
||||
SetMandatoryEntities(components.get());
|
||||
SetMandatoryEntities(components.get(), time_controller_);
|
||||
params->rtc_configuration.sdp_semantics = SdpSemantics::kUnifiedPlan;
|
||||
|
||||
// Create peer connection factory.
|
||||
@ -305,7 +308,7 @@ std::unique_ptr<TestPeer> TestPeerFactory::CreateTestPeer(
|
||||
webrtc::AudioProcessingBuilder().Create();
|
||||
if (params->aec_dump_path && audio_processing) {
|
||||
audio_processing->CreateAndAttachAecDump(*params->aec_dump_path, -1,
|
||||
task_queue);
|
||||
task_queue_);
|
||||
}
|
||||
rtc::scoped_refptr<AudioDeviceModule> audio_device_module =
|
||||
CreateAudioDeviceModule(
|
||||
@ -314,16 +317,19 @@ std::unique_ptr<TestPeer> TestPeerFactory::CreateTestPeer(
|
||||
WrapVideoEncoderFactory(
|
||||
params->name.value(), bitrate_multiplier,
|
||||
CalculateRequiredSpatialIndexPerStream(params->video_configs),
|
||||
components->pcf_dependencies.get(), video_analyzer_helper);
|
||||
components->pcf_dependencies.get(), video_analyzer_helper_);
|
||||
WrapVideoDecoderFactory(params->name.value(),
|
||||
components->pcf_dependencies.get(),
|
||||
video_analyzer_helper);
|
||||
video_analyzer_helper_);
|
||||
std::unique_ptr<cricket::MediaEngineInterface> media_engine =
|
||||
CreateMediaEngine(components->pcf_dependencies.get(), audio_device_module,
|
||||
audio_processing);
|
||||
|
||||
std::unique_ptr<rtc::Thread> worker_thread =
|
||||
time_controller_.CreateThread("worker_thread");
|
||||
PeerConnectionFactoryDependencies pcf_deps = CreatePCFDependencies(
|
||||
std::move(components->pcf_dependencies), std::move(media_engine),
|
||||
signaling_thread, components->network_thread);
|
||||
signaling_thread_, worker_thread.get(), components->network_thread);
|
||||
rtc::scoped_refptr<PeerConnectionFactoryInterface> peer_connection_factory =
|
||||
CreateModularPeerConnectionFactory(std::move(pcf_deps));
|
||||
|
||||
@ -337,20 +343,8 @@ std::unique_ptr<TestPeer> TestPeerFactory::CreateTestPeer(
|
||||
|
||||
return absl::WrapUnique(new TestPeer(
|
||||
peer_connection_factory, peer_connection, std::move(observer),
|
||||
std::move(params), std::move(video_sources), audio_processing));
|
||||
}
|
||||
|
||||
std::unique_ptr<TestPeer> TestPeerFactory::CreateTestPeer(
|
||||
std::unique_ptr<PeerConfigurerImpl> configurer,
|
||||
std::unique_ptr<MockPeerConnectionObserver> observer,
|
||||
absl::optional<RemotePeerAudioConfig> remote_audio_config,
|
||||
double bitrate_multiplier,
|
||||
absl::optional<PeerConnectionE2EQualityTestFixture::EchoEmulationConfig>
|
||||
echo_emulation_config) {
|
||||
return CreateTestPeer(std::move(configurer), std::move(observer),
|
||||
video_analyzer_helper_, signaling_thread_,
|
||||
remote_audio_config, bitrate_multiplier,
|
||||
echo_emulation_config, task_queue_);
|
||||
std::move(params), std::move(video_sources), audio_processing,
|
||||
std::move(worker_thread)));
|
||||
}
|
||||
|
||||
} // namespace webrtc_pc_e2e
|
||||
|
||||
@ -58,15 +58,7 @@ class TestPeerFactory {
|
||||
VideoQualityAnalyzerInjectionHelper* video_analyzer_helper,
|
||||
rtc::TaskQueue* task_queue)
|
||||
: signaling_thread_(signaling_thread),
|
||||
video_analyzer_helper_(video_analyzer_helper),
|
||||
task_queue_(task_queue) {}
|
||||
|
||||
// Same as previous. Created for keeping backward compatibility during
|
||||
// migration. Will be removed soon.
|
||||
TestPeerFactory(rtc::Thread* signaling_thread,
|
||||
VideoQualityAnalyzerInjectionHelper* video_analyzer_helper,
|
||||
rtc::TaskQueue* task_queue)
|
||||
: signaling_thread_(signaling_thread),
|
||||
time_controller_(time_controller),
|
||||
video_analyzer_helper_(video_analyzer_helper),
|
||||
task_queue_(task_queue) {}
|
||||
|
||||
@ -74,19 +66,6 @@ class TestPeerFactory {
|
||||
// PeerConnectionFactory and PeerConnection creation methods,
|
||||
// also will setup dependencies, that are required for media analyzers
|
||||
// injection.
|
||||
//
|
||||
// |signaling_thread| will be provided by test fixture implementation.
|
||||
static std::unique_ptr<TestPeer> CreateTestPeer(
|
||||
std::unique_ptr<PeerConfigurerImpl> configurer,
|
||||
std::unique_ptr<MockPeerConnectionObserver> observer,
|
||||
VideoQualityAnalyzerInjectionHelper* video_analyzer_helper,
|
||||
rtc::Thread* signaling_thread,
|
||||
absl::optional<RemotePeerAudioConfig> remote_audio_config,
|
||||
double bitrate_multiplier,
|
||||
absl::optional<PeerConnectionE2EQualityTestFixture::EchoEmulationConfig>
|
||||
echo_emulation_config,
|
||||
rtc::TaskQueue* task_queue);
|
||||
|
||||
std::unique_ptr<TestPeer> CreateTestPeer(
|
||||
std::unique_ptr<PeerConfigurerImpl> configurer,
|
||||
std::unique_ptr<MockPeerConnectionObserver> observer,
|
||||
@ -97,6 +76,7 @@ class TestPeerFactory {
|
||||
|
||||
private:
|
||||
rtc::Thread* signaling_thread_;
|
||||
TimeController& time_controller_;
|
||||
VideoQualityAnalyzerInjectionHelper* video_analyzer_helper_;
|
||||
rtc::TaskQueue* task_queue_;
|
||||
};
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user