Fix call setup: change way of adding media to the call.

To correctly send media from Bob to Alice, when Alice is calling Bob
we have to add transceivers for Bob's media to Alice first, because
it is forbidden to add new media sections into answer in Unified Plan,
so Alice's offer have to contain media sections for Bob's media tracks.

Bug: webrtc:10138
Change-Id: I8a5f19aa5ed6051a981472d5c79493362365f587
Reviewed-on: https://webrtc-review.googlesource.com/c/124492
Commit-Queue: Artem Titov <titovartem@webrtc.org>
Reviewed-by: Henrik Boström <hbos@webrtc.org>
Reviewed-by: Ilya Nikolaevskiy <ilnik@webrtc.org>
Reviewed-by: Peter Slatala <psla@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#26892}
This commit is contained in:
Artem Titov 2019-02-28 10:25:52 +01:00 committed by Commit Bot
parent 03257b049e
commit 7c5541557b
3 changed files with 77 additions and 28 deletions

View File

@ -38,6 +38,16 @@ std::unique_ptr<rtc::NetworkManager> CreateFakeNetworkManager(
return network_manager;
}
void PrintFrameCounters(const std::string& name,
const FrameCounters& counters) {
RTC_LOG(INFO) << "[" << name << "] Captured : " << counters.captured;
RTC_LOG(INFO) << "[" << name << "] Pre encoded : " << counters.pre_encoded;
RTC_LOG(INFO) << "[" << name << "] Encoded : " << counters.encoded;
RTC_LOG(INFO) << "[" << name << "] Received : " << counters.received;
RTC_LOG(INFO) << "[" << name << "] Rendered : " << counters.rendered;
RTC_LOG(INFO) << "[" << name << "] Dropped : " << counters.dropped;
}
} // namespace
TEST(PeerConnectionE2EQualityTestSmokeTest, RunWithEmulatedNetwork) {
@ -65,6 +75,21 @@ TEST(PeerConnectionE2EQualityTestSmokeTest, RunWithEmulatedNetwork) {
/*input_dump_file_name=*/absl::nullopt,
/*output_dump_file_name=*/absl::nullopt, cricket::AudioOptions()};
auto bob_params = absl::make_unique<Params>();
VideoConfig bob_video_config;
bob_video_config.width = 1280;
bob_video_config.height = 720;
bob_video_config.fps = 30;
bob_video_config.stream_label = "bob-video";
bob_video_config.generator = VideoGeneratorType::kDefault;
bob_params->video_configs.push_back(bob_video_config);
bob_params->audio_config = AudioConfig{
AudioConfig::Mode::kGenerated,
/*input_file_name=*/absl::nullopt,
/*input_dump_file_name=*/absl::nullopt,
/*output_dump_file_name=*/absl::nullopt, cricket::AudioOptions()};
// Setup emulated network
NetworkEmulationManager network_emulation_manager;
@ -113,19 +138,25 @@ TEST(PeerConnectionE2EQualityTestSmokeTest, RunWithEmulatedNetwork) {
"smoke_test", std::move(audio_quality_analyzer),
std::move(video_quality_analyzer));
fixture->Run(std::move(alice_components), std::move(alice_params),
std::move(bob_components), absl::make_unique<Params>(),
std::move(bob_components), std::move(bob_params),
RunParams{TimeDelta::seconds(5)});
// 150 = 30fps * 5s. On some devices pipeline can be too slow, so it can
// happen, that frames will stuck in the middle, so we actually can't force
// real constraints here, so lets just check, that at least 1 frame passed
// whole pipeline.
EXPECT_GE(video_analyzer_ptr->GetGlobalCounters().captured, 150);
EXPECT_GE(video_analyzer_ptr->GetGlobalCounters().pre_encoded, 1);
EXPECT_GE(video_analyzer_ptr->GetGlobalCounters().encoded, 1);
EXPECT_GE(video_analyzer_ptr->GetGlobalCounters().received, 1);
EXPECT_GE(video_analyzer_ptr->GetGlobalCounters().decoded, 1);
EXPECT_GE(video_analyzer_ptr->GetGlobalCounters().rendered, 1);
PrintFrameCounters("Global", video_analyzer_ptr->GetGlobalCounters());
for (auto stream_label : video_analyzer_ptr->GetKnownVideoStreams()) {
FrameCounters stream_conters =
video_analyzer_ptr->GetPerStreamCounters().at(stream_label);
PrintFrameCounters(stream_label, stream_conters);
// 150 = 30fps * 5s. On some devices pipeline can be too slow, so it can
// happen, that frames will stuck in the middle, so we actually can't force
// real constraints here, so lets just check, that at least 1 frame passed
// whole pipeline.
EXPECT_GE(stream_conters.captured, 150);
EXPECT_GE(stream_conters.pre_encoded, 1);
EXPECT_GE(stream_conters.encoded, 1);
EXPECT_GE(stream_conters.received, 1);
EXPECT_GE(stream_conters.decoded, 1);
EXPECT_GE(stream_conters.rendered, 1);
}
}
} // namespace test

View File

@ -336,15 +336,16 @@ void PeerConnectionE2EQualityTest::SetupVideoSink(
return;
}
RTC_CHECK_EQ(transceiver->receiver()->stream_ids().size(), 1);
std::string stream_label = transceiver->receiver()->stream_ids().front();
VideoConfig* video_config = nullptr;
for (auto& config : remote_video_configs) {
if (config.stream_label == track->id()) {
if (config.stream_label == stream_label) {
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
@ -357,8 +358,25 @@ void PeerConnectionE2EQualityTest::SetupVideoSink(
}
void PeerConnectionE2EQualityTest::SetupCallOnSignalingThread() {
alice_video_sources_ = AddMedia(alice_.get());
bob_video_sources_ = AddMedia(bob_.get());
// We need receive-only transceivers for Bob's media stream, so there will
// be media section in SDP for that streams in Alice's offer, because it is
// forbidden to add new media sections in answer in Unified Plan.
RtpTransceiverInit receive_only_transceiver_init;
receive_only_transceiver_init.direction = RtpTransceiverDirection::kRecvOnly;
if (bob_->params()->audio_config) {
// Setup receive audio transceiver if Bob has audio to send. If we'll need
// multiple audio streams, then we need transceiver for each Bob's audio
// stream.
alice_->AddTransceiver(cricket::MediaType::MEDIA_TYPE_AUDIO,
receive_only_transceiver_init);
}
for (size_t i = 0; i < bob_->params()->video_configs.size(); ++i) {
alice_->AddTransceiver(cricket::MediaType::MEDIA_TYPE_VIDEO,
receive_only_transceiver_init);
}
// Then add media for Alice and Bob
alice_video_sources_ = MaybeAddMedia(alice_.get());
bob_video_sources_ = MaybeAddMedia(bob_.get());
SetupCall();
}
@ -368,15 +386,13 @@ void PeerConnectionE2EQualityTest::TearDownCallOnSignalingThread() {
}
std::vector<rtc::scoped_refptr<FrameGeneratorCapturerVideoTrackSource>>
PeerConnectionE2EQualityTest::AddMedia(TestPeer* peer) {
if (peer->params()->audio_config) {
AddAudio(peer);
}
return AddVideo(peer);
PeerConnectionE2EQualityTest::MaybeAddMedia(TestPeer* peer) {
MaybeAddAudio(peer);
return MaybeAddVideo(peer);
}
std::vector<rtc::scoped_refptr<FrameGeneratorCapturerVideoTrackSource>>
PeerConnectionE2EQualityTest::AddVideo(TestPeer* peer) {
PeerConnectionE2EQualityTest::MaybeAddVideo(TestPeer* peer) {
// Params here valid because of pre-run validation.
Params* params = peer->params();
std::vector<rtc::scoped_refptr<FrameGeneratorCapturerVideoTrackSource>> out;
@ -407,7 +423,7 @@ PeerConnectionE2EQualityTest::AddVideo(TestPeer* peer) {
rtc::scoped_refptr<VideoTrackInterface> track =
peer->pc_factory()->CreateVideoTrack(video_config.stream_label.value(),
source);
peer->AddTransceiver(track);
peer->AddTrack(track, {video_config.stream_label.value()});
}
return out;
}
@ -446,14 +462,16 @@ PeerConnectionE2EQualityTest::CreateFrameGenerator(
return nullptr;
}
void PeerConnectionE2EQualityTest::AddAudio(TestPeer* peer) {
RTC_CHECK(peer->params()->audio_config);
void PeerConnectionE2EQualityTest::MaybeAddAudio(TestPeer* peer) {
if (!peer->params()->audio_config) {
return;
}
rtc::scoped_refptr<webrtc::AudioSourceInterface> source =
peer->pc_factory()->CreateAudioSource(
peer->params()->audio_config->audio_options);
rtc::scoped_refptr<AudioTrackInterface> track =
peer->pc_factory()->CreateAudioTrack("audio", source);
peer->AddTransceiver(track);
peer->AddTrack(track, {"audio"});
}
void PeerConnectionE2EQualityTest::SetupCall() {

View File

@ -67,12 +67,12 @@ class PeerConnectionE2EQualityTest
void SetupCallOnSignalingThread();
void TearDownCallOnSignalingThread();
std::vector<rtc::scoped_refptr<FrameGeneratorCapturerVideoTrackSource>>
AddMedia(TestPeer* peer);
MaybeAddMedia(TestPeer* peer);
std::vector<rtc::scoped_refptr<FrameGeneratorCapturerVideoTrackSource>>
AddVideo(TestPeer* peer);
MaybeAddVideo(TestPeer* peer);
std::unique_ptr<FrameGenerator> CreateFrameGenerator(
const VideoConfig& video_config);
void AddAudio(TestPeer* peer);
void MaybeAddAudio(TestPeer* peer);
void SetupCall();
void StartVideo(
const std::vector<