Add support of fast media sending in peer connection e2e test
Start sending media from the peer when it's ICE connection state is
connected.
Bug: webrtc:10138
Change-Id: I9f5a1cd917317a3ebadd7c156563035b0bbecf2a
Reviewed-on: https://webrtc-review.googlesource.com/c/121956
Reviewed-by: Mirko Bonadei <mbonadei@webrtc.org>
Reviewed-by: Peter Slatala <psla@webrtc.org>
Commit-Queue: Artem Titov <titovartem@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#26698}
diff --git a/test/DEPS b/test/DEPS
index 712dc6b..d69c889 100644
--- a/test/DEPS
+++ b/test/DEPS
@@ -54,7 +54,7 @@
"+pc/test/mock_peer_connection_observers.h",
"+p2p/client/basic_port_allocator.h",
],
- ".*peer_connection_quality_test\.h": [
+ ".*peer_connection_quality_test\.(h|cc)": [
"+pc",
]
}
diff --git a/test/pc/e2e/peer_connection_quality_test.cc b/test/pc/e2e/peer_connection_quality_test.cc
index 44170c4..4f293fa 100644
--- a/test/pc/e2e/peer_connection_quality_test.cc
+++ b/test/pc/e2e/peer_connection_quality_test.cc
@@ -1,3 +1,5 @@
+#include <utility>
+
/*
* Copyright (c) 2019 The WebRTC project authors. All Rights Reserved.
*
@@ -13,9 +15,11 @@
#include <utility>
#include "absl/memory/memory.h"
+#include "api/media_stream_interface.h"
#include "api/peer_connection_interface.h"
#include "api/scoped_refptr.h"
#include "api/units/time_delta.h"
+#include "pc/test/mock_peer_connection_observers.h"
#include "rtc_base/bind.h"
#include "rtc_base/gunit.h"
#include "system_wrappers/include/cpu_info.h"
@@ -49,6 +53,41 @@
return builder.str();
}
+class FixturePeerConnectionObserver : public MockPeerConnectionObserver {
+ public:
+ // |on_track_callback| will be called when any new track will be added to peer
+ // connection.
+ // |on_connected_callback| will be called when peer connection will come to
+ // either connected or completed state. Client should notice that in the case
+ // of reconnect this callback can be called again, so it should be tolerant
+ // to such behavior.
+ FixturePeerConnectionObserver(
+ std::function<void(rtc::scoped_refptr<RtpTransceiverInterface>)>
+ on_track_callback,
+ std::function<void()> on_connected_callback)
+ : on_track_callback_(std::move(on_track_callback)),
+ on_connected_callback_(std::move(on_connected_callback)) {}
+
+ void OnTrack(
+ rtc::scoped_refptr<RtpTransceiverInterface> transceiver) override {
+ MockPeerConnectionObserver::OnTrack(transceiver);
+ on_track_callback_(transceiver);
+ }
+
+ void OnIceConnectionChange(
+ PeerConnectionInterface::IceConnectionState new_state) override {
+ MockPeerConnectionObserver::OnIceConnectionChange(new_state);
+ if (ice_connected_) {
+ on_connected_callback_();
+ }
+ }
+
+ private:
+ std::function<void(rtc::scoped_refptr<RtpTransceiverInterface>)>
+ on_track_callback_;
+ std::function<void()> on_connected_callback_;
+};
+
} // namespace
PeerConnectionE2EQualityTest::PeerConnectionE2EQualityTest(
@@ -110,12 +149,28 @@
alice_params->audio_config
? alice_params->audio_config->output_dump_file_name
: absl::nullopt;
+ // Copy Alice and Bob video configs to correctly pass them into lambdas.
+ std::vector<VideoConfig> alice_video_configs = alice_params->video_configs;
+ std::vector<VideoConfig> bob_video_configs = bob_params->video_configs;
+
alice_ = TestPeer::CreateTestPeer(
std::move(alice_components), std::move(alice_params),
+ absl::make_unique<FixturePeerConnectionObserver>(
+ [this, bob_video_configs](
+ rtc::scoped_refptr<RtpTransceiverInterface> transceiver) {
+ SetupVideoSink(transceiver, bob_video_configs);
+ },
+ [this]() { StartVideo(alice_video_sources_); }),
video_quality_analyzer_injection_helper_.get(), signaling_thread.get(),
alice_audio_output_dump_file_name);
bob_ = TestPeer::CreateTestPeer(
std::move(bob_components), std::move(bob_params),
+ absl::make_unique<FixturePeerConnectionObserver>(
+ [this, alice_video_configs](
+ rtc::scoped_refptr<RtpTransceiverInterface> transceiver) {
+ SetupVideoSink(transceiver, alice_video_configs);
+ },
+ [this]() { StartVideo(bob_video_sources_); }),
video_quality_analyzer_injection_helper_.get(), signaling_thread.get(),
bob_audio_output_dump_file_name);
@@ -144,7 +199,8 @@
RTC_CHECK(!bob_);
// Ensuring that FrameGeneratorCapturerVideoTrackSource and VideoFrameWriter
// are destroyed on the right thread.
- RTC_CHECK(video_sources_.empty());
+ RTC_CHECK(alice_video_sources_.empty());
+ RTC_CHECK(bob_video_sources_.empty());
RTC_CHECK(video_writers_.empty());
}
@@ -211,35 +267,60 @@
RTC_CHECK_GT(media_streams_count, 0) << "No media in the call.";
}
+void PeerConnectionE2EQualityTest::SetupVideoSink(
+ rtc::scoped_refptr<RtpTransceiverInterface> transceiver,
+ std::vector<VideoConfig> remote_video_configs) {
+ const rtc::scoped_refptr<MediaStreamTrackInterface>& track =
+ transceiver->receiver()->track();
+ if (track->kind() != MediaStreamTrackInterface::kVideoKind) {
+ return;
+ }
+
+ VideoConfig* video_config = nullptr;
+ for (auto& config : remote_video_configs) {
+ if (config.stream_label == track->id()) {
+ video_config = &config;
+ break;
+ }
+ }
+ RTC_CHECK(video_config);
+
+ VideoFrameWriter* writer = MaybeCreateVideoWriter(
+ video_config->output_dump_file_name, *video_config);
+ // It is safe to cast here, because it is checked above that
+ // track->kind() is kVideoKind.
+ auto* video_track = static_cast<VideoTrackInterface*>(track.get());
+ std::unique_ptr<rtc::VideoSinkInterface<VideoFrame>> video_sink =
+ video_quality_analyzer_injection_helper_->CreateVideoSink(writer);
+ video_track->AddOrUpdateSink(video_sink.get(), rtc::VideoSinkWants());
+ output_video_sinks_.push_back(std::move(video_sink));
+}
+
void PeerConnectionE2EQualityTest::RunOnSignalingThread(RunParams run_params) {
- AddMedia(alice_.get());
- AddMedia(bob_.get());
+ alice_video_sources_ = AddMedia(alice_.get());
+ bob_video_sources_ = AddMedia(bob_.get());
SetupCall();
- WaitForTransceiversSetup(alice_->params(), bob_.get());
- WaitForTransceiversSetup(bob_->params(), alice_.get());
- SetupVideoSink(alice_->params(), bob_.get());
- SetupVideoSink(bob_->params(), alice_.get());
-
- StartVideo();
-
rtc::Event done;
done.Wait(static_cast<int>(run_params.run_duration.ms()));
TearDownCall();
}
-void PeerConnectionE2EQualityTest::AddMedia(TestPeer* peer) {
- AddVideo(peer);
+std::vector<rtc::scoped_refptr<FrameGeneratorCapturerVideoTrackSource>>
+PeerConnectionE2EQualityTest::AddMedia(TestPeer* peer) {
if (peer->params()->audio_config) {
AddAudio(peer);
}
+ return AddVideo(peer);
}
-void PeerConnectionE2EQualityTest::AddVideo(TestPeer* peer) {
+std::vector<rtc::scoped_refptr<FrameGeneratorCapturerVideoTrackSource>>
+PeerConnectionE2EQualityTest::AddVideo(TestPeer* peer) {
// Params here valid because of pre-run validation.
Params* params = peer->params();
+ std::vector<rtc::scoped_refptr<FrameGeneratorCapturerVideoTrackSource>> out;
for (auto video_config : params->video_configs) {
// Create video generator.
std::unique_ptr<FrameGenerator> frame_generator =
@@ -261,7 +342,7 @@
rtc::scoped_refptr<FrameGeneratorCapturerVideoTrackSource> source =
new rtc::RefCountedObject<FrameGeneratorCapturerVideoTrackSource>(
move(capturer));
- video_sources_.push_back(source);
+ out.push_back(source);
RTC_LOG(INFO) << "Adding video with video_config.stream_label="
<< video_config.stream_label.value();
rtc::scoped_refptr<VideoTrackInterface> track =
@@ -269,6 +350,7 @@
source);
peer->AddTransceiver(track);
}
+ return out;
}
std::unique_ptr<FrameGenerator>
@@ -332,58 +414,21 @@
ASSERT_TRUE_WAIT(alice_->IsIceConnected(), kDefaultTimeoutMs);
}
-void PeerConnectionE2EQualityTest::WaitForTransceiversSetup(
- Params* params,
- TestPeer* remote_peer) {
- uint64_t expected_remote_transceivers =
- params->video_configs.size() + (params->audio_config ? 1 : 0);
- ASSERT_EQ_WAIT(remote_peer->observer()->on_track_transceivers_.size(),
- expected_remote_transceivers, kDefaultTimeoutMs);
-}
-
-void PeerConnectionE2EQualityTest::SetupVideoSink(Params* params,
- TestPeer* remote_peer) {
- if (params->video_configs.empty()) {
- return;
- }
- std::map<std::string, VideoConfig*> video_configs_by_label;
- for (auto& video_config : params->video_configs) {
- video_configs_by_label.insert(std::pair<std::string, VideoConfig*>(
- video_config.stream_label.value(), &video_config));
- }
-
- for (const auto& transceiver :
- remote_peer->observer()->on_track_transceivers_) {
- const rtc::scoped_refptr<MediaStreamTrackInterface>& track =
- transceiver->receiver()->track();
- if (track->kind() != MediaStreamTrackInterface::kVideoKind) {
- continue;
+void PeerConnectionE2EQualityTest::StartVideo(
+ const std::vector<
+ rtc::scoped_refptr<FrameGeneratorCapturerVideoTrackSource>>& sources) {
+ for (auto& source : sources) {
+ if (source->state() != MediaSourceInterface::SourceState::kLive) {
+ source->Start();
}
-
- auto it = video_configs_by_label.find(track->id());
- RTC_CHECK(it != video_configs_by_label.end());
- VideoConfig* video_config = it->second;
-
- VideoFrameWriter* writer = MaybeCreateVideoWriter(
- video_config->output_dump_file_name, *video_config);
- // It is safe to cast here, because it is checked above that track->kind()
- // is kVideoKind.
- auto* video_track = static_cast<VideoTrackInterface*>(track.get());
- std::unique_ptr<rtc::VideoSinkInterface<VideoFrame>> video_sink =
- video_quality_analyzer_injection_helper_->CreateVideoSink(writer);
- video_track->AddOrUpdateSink(video_sink.get(), rtc::VideoSinkWants());
- output_video_sinks_.push_back(std::move(video_sink));
- }
-}
-
-void PeerConnectionE2EQualityTest::StartVideo() {
- for (const auto& video_source : video_sources_) {
- video_source->Start();
}
}
void PeerConnectionE2EQualityTest::TearDownCall() {
- for (const auto& video_source : video_sources_) {
+ for (const auto& video_source : alice_video_sources_) {
+ video_source->Stop();
+ }
+ for (const auto& video_source : bob_video_sources_) {
video_source->Stop();
}
@@ -394,7 +439,8 @@
video_writer->Close();
}
- video_sources_.clear();
+ alice_video_sources_.clear();
+ bob_video_sources_.clear();
video_writers_.clear();
alice_.reset();
bob_.reset();
diff --git a/test/pc/e2e/peer_connection_quality_test.h b/test/pc/e2e/peer_connection_quality_test.h
index 8cce506..b19a4fe 100644
--- a/test/pc/e2e/peer_connection_quality_test.h
+++ b/test/pc/e2e/peer_connection_quality_test.h
@@ -55,17 +55,21 @@
// Validate peer's parameters, also ensure uniqueness of all video stream
// labels.
void ValidateParams(std::vector<Params*> params);
+ void SetupVideoSink(rtc::scoped_refptr<RtpTransceiverInterface> transceiver,
+ std::vector<VideoConfig> remote_video_configs);
// Have to be run on the signaling thread.
void RunOnSignalingThread(RunParams run_params);
- void AddMedia(TestPeer* peer);
- void AddVideo(TestPeer* peer);
+ std::vector<rtc::scoped_refptr<FrameGeneratorCapturerVideoTrackSource>>
+ AddMedia(TestPeer* peer);
+ std::vector<rtc::scoped_refptr<FrameGeneratorCapturerVideoTrackSource>>
+ AddVideo(TestPeer* peer);
std::unique_ptr<FrameGenerator> CreateFrameGenerator(
const VideoConfig& video_config);
void AddAudio(TestPeer* peer);
void SetupCall();
- void WaitForTransceiversSetup(Params* params, TestPeer* remote_peer);
- void SetupVideoSink(Params* params, TestPeer* remote_peer);
- void StartVideo();
+ void StartVideo(
+ const std::vector<
+ rtc::scoped_refptr<FrameGeneratorCapturerVideoTrackSource>>& sources);
void TearDownCall();
VideoFrameWriter* MaybeCreateVideoWriter(
absl::optional<std::string> file_name,
@@ -81,7 +85,9 @@
std::unique_ptr<TestPeer> bob_;
std::vector<rtc::scoped_refptr<FrameGeneratorCapturerVideoTrackSource>>
- video_sources_;
+ alice_video_sources_;
+ std::vector<rtc::scoped_refptr<FrameGeneratorCapturerVideoTrackSource>>
+ bob_video_sources_;
std::vector<std::unique_ptr<VideoFrameWriter>> video_writers_;
std::vector<std::unique_ptr<rtc::VideoSinkInterface<VideoFrame>>>
output_video_sinks_;
diff --git a/test/pc/e2e/test_peer.cc b/test/pc/e2e/test_peer.cc
index 8c46206..d0e7e5a 100644
--- a/test/pc/e2e/test_peer.cc
+++ b/test/pc/e2e/test_peer.cc
@@ -245,6 +245,7 @@
std::unique_ptr<TestPeer> TestPeer::CreateTestPeer(
std::unique_ptr<InjectableComponents> components,
std::unique_ptr<Params> params,
+ std::unique_ptr<MockPeerConnectionObserver> observer,
VideoQualityAnalyzerInjectionHelper* video_analyzer_helper,
rtc::Thread* signaling_thread,
absl::optional<std::string> audio_output_file_name) {
@@ -253,9 +254,6 @@
SetMandatoryEntities(components.get());
params->rtc_configuration.sdp_semantics = SdpSemantics::kUnifiedPlan;
- std::unique_ptr<MockPeerConnectionObserver> observer =
- absl::make_unique<MockPeerConnectionObserver>();
-
// Create peer connection factory.
PeerConnectionFactoryDependencies pcf_deps = CreatePCFDependencies(
std::move(components->pcf_dependencies), params->audio_config,
diff --git a/test/pc/e2e/test_peer.h b/test/pc/e2e/test_peer.h
index f6e878d..3ee96c2 100644
--- a/test/pc/e2e/test_peer.h
+++ b/test/pc/e2e/test_peer.h
@@ -53,6 +53,7 @@
static std::unique_ptr<TestPeer> CreateTestPeer(
std::unique_ptr<InjectableComponents> components,
std::unique_ptr<Params> params,
+ std::unique_ptr<MockPeerConnectionObserver> observer,
VideoQualityAnalyzerInjectionHelper* video_analyzer_helper,
rtc::Thread* signaling_thread,
absl::optional<std::string> audio_output_file_name);