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}
This commit is contained in:
parent
ceba6ae2a7
commit
bf9e01ab4e
@ -54,7 +54,7 @@ specific_include_rules = {
|
||||
"+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",
|
||||
]
|
||||
}
|
||||
|
||||
@ -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 @@ std::string VideoConfigSourcePresenceToString(const VideoConfig& video_config) {
|
||||
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 @@ void PeerConnectionE2EQualityTest::Run(
|
||||
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 @@ void PeerConnectionE2EQualityTest::Run(
|
||||
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 @@ void PeerConnectionE2EQualityTest::ValidateParams(std::vector<Params*> params) {
|
||||
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 @@ void PeerConnectionE2EQualityTest::AddVideo(TestPeer* peer) {
|
||||
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 @@ void PeerConnectionE2EQualityTest::AddVideo(TestPeer* peer) {
|
||||
source);
|
||||
peer->AddTransceiver(track);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
std::unique_ptr<FrameGenerator>
|
||||
@ -332,58 +414,21 @@ void PeerConnectionE2EQualityTest::SetupCall() {
|
||||
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 @@ void PeerConnectionE2EQualityTest::TearDownCall() {
|
||||
video_writer->Close();
|
||||
}
|
||||
|
||||
video_sources_.clear();
|
||||
alice_video_sources_.clear();
|
||||
bob_video_sources_.clear();
|
||||
video_writers_.clear();
|
||||
alice_.reset();
|
||||
bob_.reset();
|
||||
|
||||
@ -55,17 +55,21 @@ class PeerConnectionE2EQualityTest
|
||||
// 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 @@ class PeerConnectionE2EQualityTest
|
||||
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_;
|
||||
|
||||
@ -245,6 +245,7 @@ PeerConnectionDependencies CreatePCDependencies(
|
||||
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 @@ std::unique_ptr<TestPeer> TestPeer::CreateTestPeer(
|
||||
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,
|
||||
|
||||
@ -53,6 +53,7 @@ class TestPeer final : public PeerConnectionWrapper {
|
||||
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);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user