Move media configuration for PC level tests into separate class

Bug: webrtc:11479
Change-Id: I325e5c6f5d571dde0fdb5d579bf85cf32a81e174
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/172783
Reviewed-by: Mirko Bonadei <mbonadei@webrtc.org>
Commit-Queue: Artem Titov <titovartem@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#30985}
This commit is contained in:
Artem Titov
2020-04-02 16:31:40 +02:00
committed by Commit Bot
parent 06d3559b79
commit 68063a25de
7 changed files with 384 additions and 251 deletions

View File

@ -70,4 +70,7 @@ specific_include_rules = {
"+pc", "+pc",
"+p2p", "+p2p",
], ],
".*test_video_capturer_video_track_source.h": [
"+pc",
]
} }

View File

@ -258,6 +258,29 @@ if (rtc_include_tests) {
] ]
} }
rtc_library("media_helper") {
visibility = [ "*" ]
testonly = true
sources = [
"media/media_helper.cc",
"media/media_helper.h",
"media/test_video_capturer_video_track_source.h",
]
deps = [
":test_peer",
":video_quality_analyzer_injection_helper",
"../..:fileutils",
"../..:platform_video_capturer",
"../..:video_test_common",
"../..:video_test_support",
"../../../api:create_frame_generator",
"../../../api:frame_generator_api",
"../../../api:peer_connection_quality_test_fixture_api",
"../../../api/video:video_frame",
"../../../pc:peerconnection",
]
}
rtc_library("peerconnection_quality_test") { rtc_library("peerconnection_quality_test") {
visibility = [ "*" ] visibility = [ "*" ]
testonly = true testonly = true
@ -270,6 +293,7 @@ if (rtc_include_tests) {
":analyzer_helper", ":analyzer_helper",
":default_audio_quality_analyzer", ":default_audio_quality_analyzer",
":default_video_quality_analyzer", ":default_video_quality_analyzer",
":media_helper",
":peer_connection_quality_test_params", ":peer_connection_quality_test_params",
":sdp_changer", ":sdp_changer",
":single_process_encoded_image_data_injector", ":single_process_encoded_image_data_injector",
@ -279,11 +303,8 @@ if (rtc_include_tests) {
":video_quality_analyzer_injection_helper", ":video_quality_analyzer_injection_helper",
":video_quality_metrics_reporter", ":video_quality_metrics_reporter",
"../..:field_trial", "../..:field_trial",
"../..:platform_video_capturer", "../..:fileutils",
"../..:video_test_common",
"../../../api:audio_quality_analyzer_api", "../../../api:audio_quality_analyzer_api",
"../../../api:create_frame_generator",
"../../../api:frame_generator_api",
"../../../api:libjingle_peerconnection_api", "../../../api:libjingle_peerconnection_api",
"../../../api:media_stream_interface", "../../../api:media_stream_interface",
"../../../api:peer_connection_quality_test_fixture_api", "../../../api:peer_connection_quality_test_fixture_api",
@ -295,20 +316,17 @@ if (rtc_include_tests) {
"../../../api/task_queue:default_task_queue_factory", "../../../api/task_queue:default_task_queue_factory",
"../../../api/units:time_delta", "../../../api/units:time_delta",
"../../../api/units:timestamp", "../../../api/units:timestamp",
"../../../api/video:video_frame",
"../../../pc:pc_test_utils", "../../../pc:pc_test_utils",
"../../../pc:peerconnection", "../../../pc:peerconnection",
"../../../rtc_base", "../../../rtc_base",
"../../../rtc_base:gunit_helpers", "../../../rtc_base:gunit_helpers",
"../../../rtc_base:macromagic",
"../../../rtc_base:rtc_base_approved", "../../../rtc_base:rtc_base_approved",
"../../../rtc_base:rtc_task_queue",
"../../../rtc_base:safe_conversions", "../../../rtc_base:safe_conversions",
"../../../rtc_base:task_queue_for_test", "../../../rtc_base:task_queue_for_test",
"../../../rtc_base/task_utils:repeating_task", "../../../rtc_base/task_utils:repeating_task",
"../../../system_wrappers", "../../../system_wrappers",
"../../../system_wrappers:field_trial", "../../../system_wrappers:field_trial",
"../../../test:fileutils",
"../../../test:video_test_support",
] ]
} }

View File

@ -0,0 +1,217 @@
/*
* Copyright (c) 2020 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.
*/
#include "test/pc/e2e/media/media_helper.h"
#include <utility>
#include "api/test/create_frame_generator.h"
#include "test/frame_generator_capturer.h"
#include "test/platform_video_capturer.h"
#include "test/testsupport/file_utils.h"
namespace webrtc {
namespace webrtc_pc_e2e {
namespace {
using VideoConfig =
::webrtc::webrtc_pc_e2e::PeerConnectionE2EQualityTestFixture::VideoConfig;
using AudioConfig =
::webrtc::webrtc_pc_e2e::PeerConnectionE2EQualityTestFixture::AudioConfig;
using VideoGeneratorType = ::webrtc::webrtc_pc_e2e::
PeerConnectionE2EQualityTestFixture::VideoGeneratorType;
} // namespace
MediaHelper::~MediaHelper() {
for (const auto& video_writer : video_writers_) {
video_writer->Close();
}
video_writers_.clear();
}
void MediaHelper::MaybeAddAudio(TestPeer* peer) {
if (!peer->params()->audio_config) {
return;
}
const AudioConfig& audio_config = peer->params()->audio_config.value();
rtc::scoped_refptr<webrtc::AudioSourceInterface> source =
peer->pc_factory()->CreateAudioSource(audio_config.audio_options);
rtc::scoped_refptr<AudioTrackInterface> track =
peer->pc_factory()->CreateAudioTrack(*audio_config.stream_label, source);
std::string sync_group = audio_config.sync_group
? audio_config.sync_group.value()
: audio_config.stream_label.value();
peer->AddTrack(track, {sync_group, *audio_config.stream_label});
}
std::vector<rtc::scoped_refptr<TestVideoCapturerVideoTrackSource>>
MediaHelper::MaybeAddVideo(TestPeer* peer) {
// Params here valid because of pre-run validation.
Params* params = peer->params();
std::vector<rtc::scoped_refptr<TestVideoCapturerVideoTrackSource>> out;
for (size_t i = 0; i < params->video_configs.size(); ++i) {
auto video_config = params->video_configs[i];
// Setup input video source into peer connection.
test::VideoFrameWriter* writer =
MaybeCreateVideoWriter(video_config.input_dump_file_name, video_config);
std::unique_ptr<test::TestVideoCapturer> capturer = CreateVideoCapturer(
video_config, peer->ReleaseVideoGenerator(i),
video_quality_analyzer_injection_helper_->CreateFramePreprocessor(
video_config, writer));
rtc::scoped_refptr<TestVideoCapturerVideoTrackSource> source =
new rtc::RefCountedObject<TestVideoCapturerVideoTrackSource>(
std::move(capturer),
/*is_screencast=*/video_config.screen_share_config &&
video_config.screen_share_config->use_text_content_hint);
out.push_back(source);
RTC_LOG(INFO) << "Adding video with video_config.stream_label="
<< video_config.stream_label.value();
rtc::scoped_refptr<VideoTrackInterface> track =
peer->pc_factory()->CreateVideoTrack(video_config.stream_label.value(),
source);
if (video_config.screen_share_config &&
video_config.screen_share_config->use_text_content_hint) {
track->set_content_hint(VideoTrackInterface::ContentHint::kText);
}
std::string sync_group = video_config.sync_group
? video_config.sync_group.value()
: video_config.stream_label.value();
RTCErrorOr<rtc::scoped_refptr<RtpSenderInterface>> sender =
peer->AddTrack(track, {sync_group, *video_config.stream_label});
RTC_CHECK(sender.ok());
if (video_config.temporal_layers_count) {
RtpParameters rtp_parameters = sender.value()->GetParameters();
for (auto& encoding_parameters : rtp_parameters.encodings) {
encoding_parameters.num_temporal_layers =
video_config.temporal_layers_count;
}
RTCError res = sender.value()->SetParameters(rtp_parameters);
RTC_CHECK(res.ok()) << "Failed to set RTP parameters";
}
}
return out;
}
test::VideoFrameWriter* MediaHelper::MaybeCreateVideoWriter(
absl::optional<std::string> file_name,
const VideoConfig& config) {
if (!file_name) {
return nullptr;
}
// TODO(titovartem) create only one file writer for simulcast video track.
// For now this code will be invoked for each simulcast stream separately, but
// only one file will be used.
auto video_writer = std::make_unique<test::Y4mVideoFrameWriterImpl>(
file_name.value(), config.width, config.height, config.fps);
test::VideoFrameWriter* out = video_writer.get();
video_writers_.push_back(std::move(video_writer));
return out;
}
std::unique_ptr<test::TestVideoCapturer> MediaHelper::CreateVideoCapturer(
const VideoConfig& video_config,
std::unique_ptr<test::FrameGeneratorInterface> generator,
std::unique_ptr<test::TestVideoCapturer::FramePreprocessor>
frame_preprocessor) {
if (video_config.capturing_device_index) {
std::unique_ptr<test::TestVideoCapturer> capturer =
test::CreateVideoCapturer(video_config.width, video_config.height,
video_config.fps,
*video_config.capturing_device_index);
RTC_CHECK(capturer)
<< "Failed to obtain input stream from capturing device #"
<< *video_config.capturing_device_index;
capturer->SetFramePreprocessor(std::move(frame_preprocessor));
return capturer;
}
std::unique_ptr<test::FrameGeneratorInterface> frame_generator = nullptr;
if (generator) {
frame_generator = std::move(generator);
}
if (video_config.generator) {
absl::optional<test::FrameGeneratorInterface::OutputType>
frame_generator_type = absl::nullopt;
if (video_config.generator == VideoGeneratorType::kDefault) {
frame_generator_type = test::FrameGeneratorInterface::OutputType::kI420;
} else if (video_config.generator == VideoGeneratorType::kI420A) {
frame_generator_type = test::FrameGeneratorInterface::OutputType::kI420A;
} else if (video_config.generator == VideoGeneratorType::kI010) {
frame_generator_type = test::FrameGeneratorInterface::OutputType::kI010;
}
frame_generator =
test::CreateSquareFrameGenerator(static_cast<int>(video_config.width),
static_cast<int>(video_config.height),
frame_generator_type, absl::nullopt);
}
if (video_config.input_file_name) {
frame_generator = test::CreateFromYuvFileFrameGenerator(
std::vector<std::string>(/*count=*/1,
video_config.input_file_name.value()),
video_config.width, video_config.height, /*frame_repeat_count=*/1);
}
if (video_config.screen_share_config) {
frame_generator = CreateScreenShareFrameGenerator(video_config);
}
RTC_CHECK(frame_generator) << "Unsupported video_config input source";
auto capturer = std::make_unique<test::FrameGeneratorCapturer>(
clock_, std::move(frame_generator), video_config.fps,
*task_queue_factory_);
capturer->SetFramePreprocessor(std::move(frame_preprocessor));
capturer->Init();
return capturer;
}
std::unique_ptr<test::FrameGeneratorInterface>
MediaHelper::CreateScreenShareFrameGenerator(const VideoConfig& video_config) {
RTC_CHECK(video_config.screen_share_config);
if (video_config.screen_share_config->generate_slides) {
return test::CreateSlideFrameGenerator(
video_config.width, video_config.height,
video_config.screen_share_config->slide_change_interval.seconds() *
video_config.fps);
}
std::vector<std::string> slides =
video_config.screen_share_config->slides_yuv_file_names;
if (slides.empty()) {
// If slides is empty we need to add default slides as source. In such case
// video width and height is validated to be equal to kDefaultSlidesWidth
// and kDefaultSlidesHeight.
slides.push_back(test::ResourcePath("web_screenshot_1850_1110", "yuv"));
slides.push_back(test::ResourcePath("presentation_1850_1110", "yuv"));
slides.push_back(test::ResourcePath("photo_1850_1110", "yuv"));
slides.push_back(test::ResourcePath("difficult_photo_1850_1110", "yuv"));
}
if (!video_config.screen_share_config->scrolling_params) {
// Cycle image every slide_change_interval seconds.
return test::CreateFromYuvFileFrameGenerator(
slides, video_config.width, video_config.height,
video_config.screen_share_config->slide_change_interval.seconds() *
video_config.fps);
}
// |pause_duration| is nonnegative. It is validated in ValidateParams(...).
TimeDelta pause_duration =
video_config.screen_share_config->slide_change_interval -
video_config.screen_share_config->scrolling_params->duration;
return test::CreateScrollingInputFromYuvFilesFrameGenerator(
clock_, slides,
video_config.screen_share_config->scrolling_params->source_width,
video_config.screen_share_config->scrolling_params->source_height,
video_config.width, video_config.height,
video_config.screen_share_config->scrolling_params->duration.ms(),
pause_duration.ms());
}
} // namespace webrtc_pc_e2e
} // namespace webrtc

View File

@ -0,0 +1,70 @@
/*
* Copyright (c) 2020 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.
*/
#ifndef TEST_PC_E2E_MEDIA_MEDIA_HELPER_H_
#define TEST_PC_E2E_MEDIA_MEDIA_HELPER_H_
#include <memory>
#include <string>
#include <vector>
#include "api/test/frame_generator_interface.h"
#include "api/test/peerconnection_quality_test_fixture.h"
#include "test/pc/e2e/analyzer/video/video_quality_analyzer_injection_helper.h"
#include "test/pc/e2e/media/test_video_capturer_video_track_source.h"
#include "test/pc/e2e/test_peer.h"
#include "test/testsupport/video_frame_writer.h"
namespace webrtc {
namespace webrtc_pc_e2e {
class MediaHelper {
public:
MediaHelper(VideoQualityAnalyzerInjectionHelper*
video_quality_analyzer_injection_helper,
TaskQueueFactory* task_queue_factory)
: clock_(Clock::GetRealTimeClock()),
task_queue_factory_(task_queue_factory),
video_quality_analyzer_injection_helper_(
video_quality_analyzer_injection_helper) {}
~MediaHelper();
void MaybeAddAudio(TestPeer* peer);
std::vector<rtc::scoped_refptr<TestVideoCapturerVideoTrackSource>>
MaybeAddVideo(TestPeer* peer);
// Creates a video file writer if |file_name| is not empty. Created writer
// will be owned by MediaHelper and will be closed on MediaHelper destruction.
// If |file_name| is empty will return nullptr.
test::VideoFrameWriter* MaybeCreateVideoWriter(
absl::optional<std::string> file_name,
const PeerConnectionE2EQualityTestFixture::VideoConfig& config);
private:
std::unique_ptr<test::TestVideoCapturer> CreateVideoCapturer(
const PeerConnectionE2EQualityTestFixture::VideoConfig& video_config,
std::unique_ptr<test::FrameGeneratorInterface> generator,
std::unique_ptr<test::TestVideoCapturer::FramePreprocessor>
frame_preprocessor);
std::unique_ptr<test::FrameGeneratorInterface>
CreateScreenShareFrameGenerator(
const PeerConnectionE2EQualityTestFixture::VideoConfig& video_config);
Clock* const clock_;
TaskQueueFactory* const task_queue_factory_;
VideoQualityAnalyzerInjectionHelper* video_quality_analyzer_injection_helper_;
std::vector<std::unique_ptr<test::VideoFrameWriter>> video_writers_;
};
} // namespace webrtc_pc_e2e
} // namespace webrtc
#endif // TEST_PC_E2E_MEDIA_MEDIA_HELPER_H_

View File

@ -0,0 +1,55 @@
/*
* Copyright (c) 2020 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.
*/
#ifndef TEST_PC_E2E_MEDIA_TEST_VIDEO_CAPTURER_VIDEO_TRACK_SOURCE_H_
#define TEST_PC_E2E_MEDIA_TEST_VIDEO_CAPTURER_VIDEO_TRACK_SOURCE_H_
#include <memory>
#include <utility>
#include "api/video/video_frame.h"
#include "api/video/video_source_interface.h"
#include "pc/video_track_source.h"
#include "test/test_video_capturer.h"
namespace webrtc {
namespace webrtc_pc_e2e {
class TestVideoCapturerVideoTrackSource : public VideoTrackSource {
public:
TestVideoCapturerVideoTrackSource(
std::unique_ptr<test::TestVideoCapturer> video_capturer,
bool is_screencast)
: VideoTrackSource(/*remote=*/false),
video_capturer_(std::move(video_capturer)),
is_screencast_(is_screencast) {}
~TestVideoCapturerVideoTrackSource() = default;
void Start() { SetState(kLive); }
void Stop() { SetState(kMuted); }
bool is_screencast() const override { return is_screencast_; }
protected:
rtc::VideoSourceInterface<VideoFrame>* source() override {
return video_capturer_.get();
}
private:
std::unique_ptr<test::TestVideoCapturer> video_capturer_;
const bool is_screencast_;
};
} // namespace webrtc_pc_e2e
} // namespace webrtc
#endif // TEST_PC_E2E_MEDIA_TEST_VIDEO_CAPTURER_VIDEO_TRACK_SOURCE_H_

View File

@ -21,10 +21,8 @@
#include "api/rtc_event_log_output_file.h" #include "api/rtc_event_log_output_file.h"
#include "api/scoped_refptr.h" #include "api/scoped_refptr.h"
#include "api/task_queue/default_task_queue_factory.h" #include "api/task_queue/default_task_queue_factory.h"
#include "api/test/create_frame_generator.h"
#include "api/test/video_quality_analyzer_interface.h" #include "api/test/video_quality_analyzer_interface.h"
#include "api/units/time_delta.h" #include "api/units/time_delta.h"
#include "api/video/video_source_interface.h"
#include "pc/sdp_utils.h" #include "pc/sdp_utils.h"
#include "pc/test/mock_peer_connection_observers.h" #include "pc/test/mock_peer_connection_observers.h"
#include "rtc_base/bind.h" #include "rtc_base/bind.h"
@ -32,13 +30,11 @@
#include "rtc_base/numerics/safe_conversions.h" #include "rtc_base/numerics/safe_conversions.h"
#include "system_wrappers/include/cpu_info.h" #include "system_wrappers/include/cpu_info.h"
#include "system_wrappers/include/field_trial.h" #include "system_wrappers/include/field_trial.h"
#include "test/frame_generator_capturer.h"
#include "test/pc/e2e/analyzer/audio/default_audio_quality_analyzer.h" #include "test/pc/e2e/analyzer/audio/default_audio_quality_analyzer.h"
#include "test/pc/e2e/analyzer/video/default_video_quality_analyzer.h" #include "test/pc/e2e/analyzer/video/default_video_quality_analyzer.h"
#include "test/pc/e2e/analyzer/video/video_quality_metrics_reporter.h" #include "test/pc/e2e/analyzer/video/video_quality_metrics_reporter.h"
#include "test/pc/e2e/stats_poller.h" #include "test/pc/e2e/stats_poller.h"
#include "test/pc/e2e/test_peer_factory.h" #include "test/pc/e2e/test_peer_factory.h"
#include "test/platform_video_capturer.h"
#include "test/testsupport/file_utils.h" #include "test/testsupport/file_utils.h"
namespace webrtc { namespace webrtc {
@ -271,6 +267,9 @@ void PeerConnectionE2EQualityTest::Run(RunParams run_params) {
const std::unique_ptr<rtc::Thread> signaling_thread = rtc::Thread::Create(); const std::unique_ptr<rtc::Thread> signaling_thread = rtc::Thread::Create();
signaling_thread->SetName(kSignalThreadName, nullptr); signaling_thread->SetName(kSignalThreadName, nullptr);
signaling_thread->Start(); signaling_thread->Start();
media_helper_ = std::make_unique<MediaHelper>(
video_quality_analyzer_injection_helper_.get(),
task_queue_factory_.get());
// Create a |task_queue_|. // Create a |task_queue_|.
task_queue_ = std::make_unique<TaskQueueForTest>("pc_e2e_quality_test"); task_queue_ = std::make_unique<TaskQueueForTest>("pc_e2e_quality_test");
@ -449,11 +448,10 @@ void PeerConnectionE2EQualityTest::Run(RunParams run_params) {
// Audio dumps. // Audio dumps.
RTC_CHECK(!alice_); RTC_CHECK(!alice_);
RTC_CHECK(!bob_); RTC_CHECK(!bob_);
// Ensuring that TestVideoCapturerVideoTrackSource and VideoFrameWriter // Ensuring that TestVideoCapturerVideoTrackSource are destroyed on the right
// are destroyed on the right thread. // thread.
RTC_CHECK(alice_video_sources_.empty()); RTC_CHECK(alice_video_sources_.empty());
RTC_CHECK(bob_video_sources_.empty()); RTC_CHECK(bob_video_sources_.empty());
RTC_CHECK(video_writers_.empty());
} }
void PeerConnectionE2EQualityTest::SetDefaultValuesForMissingParams( void PeerConnectionE2EQualityTest::SetDefaultValuesForMissingParams(
@ -649,7 +647,7 @@ void PeerConnectionE2EQualityTest::OnTrackCallback(
} }
} }
RTC_CHECK(video_config); RTC_CHECK(video_config);
test::VideoFrameWriter* writer = MaybeCreateVideoWriter( test::VideoFrameWriter* writer = media_helper_->MaybeCreateVideoWriter(
video_config->output_dump_file_name, *video_config); video_config->output_dump_file_name, *video_config);
// It is safe to cast here, because it is checked above that // It is safe to cast here, because it is checked above that
// track->kind() is kVideoKind. // track->kind() is kVideoKind.
@ -727,8 +725,10 @@ void PeerConnectionE2EQualityTest::SetupCallOnSignalingThread(
} }
// Then add media for Alice and Bob // Then add media for Alice and Bob
alice_video_sources_ = MaybeAddMedia(alice_.get()); media_helper_->MaybeAddAudio(alice_.get());
bob_video_sources_ = MaybeAddMedia(bob_.get()); alice_video_sources_ = media_helper_->MaybeAddVideo(alice_.get());
media_helper_->MaybeAddAudio(bob_.get());
bob_video_sources_ = media_helper_->MaybeAddVideo(bob_.get());
SetPeerCodecPreferences(alice_.get(), run_params); SetPeerCodecPreferences(alice_.get(), run_params);
SetPeerCodecPreferences(bob_.get(), run_params); SetPeerCodecPreferences(bob_.get(), run_params);
@ -740,175 +740,6 @@ void PeerConnectionE2EQualityTest::TearDownCallOnSignalingThread() {
TearDownCall(); TearDownCall();
} }
std::vector<rtc::scoped_refptr<TestVideoCapturerVideoTrackSource>>
PeerConnectionE2EQualityTest::MaybeAddMedia(TestPeer* peer) {
MaybeAddAudio(peer);
return MaybeAddVideo(peer);
}
std::vector<rtc::scoped_refptr<TestVideoCapturerVideoTrackSource>>
PeerConnectionE2EQualityTest::MaybeAddVideo(TestPeer* peer) {
// Params here valid because of pre-run validation.
Params* params = peer->params();
std::vector<rtc::scoped_refptr<TestVideoCapturerVideoTrackSource>> out;
for (size_t i = 0; i < params->video_configs.size(); ++i) {
auto video_config = params->video_configs[i];
// Setup input video source into peer connection.
test::VideoFrameWriter* writer =
MaybeCreateVideoWriter(video_config.input_dump_file_name, video_config);
std::unique_ptr<test::TestVideoCapturer> capturer = CreateVideoCapturer(
video_config, peer->ReleaseVideoGenerator(i),
video_quality_analyzer_injection_helper_->CreateFramePreprocessor(
video_config, writer));
rtc::scoped_refptr<TestVideoCapturerVideoTrackSource> source =
new rtc::RefCountedObject<TestVideoCapturerVideoTrackSource>(
std::move(capturer),
/*is_screencast=*/video_config.screen_share_config &&
video_config.screen_share_config->use_text_content_hint);
out.push_back(source);
RTC_LOG(INFO) << "Adding video with video_config.stream_label="
<< video_config.stream_label.value();
rtc::scoped_refptr<VideoTrackInterface> track =
peer->pc_factory()->CreateVideoTrack(video_config.stream_label.value(),
source);
if (video_config.screen_share_config &&
video_config.screen_share_config->use_text_content_hint) {
track->set_content_hint(VideoTrackInterface::ContentHint::kText);
}
std::string sync_group = video_config.sync_group
? video_config.sync_group.value()
: video_config.stream_label.value();
RTCErrorOr<rtc::scoped_refptr<RtpSenderInterface>> sender =
peer->AddTrack(track, {sync_group, *video_config.stream_label});
RTC_CHECK(sender.ok());
if (video_config.temporal_layers_count) {
RtpParameters rtp_parameters = sender.value()->GetParameters();
for (auto& encoding_parameters : rtp_parameters.encodings) {
encoding_parameters.num_temporal_layers =
video_config.temporal_layers_count;
}
RTCError res = sender.value()->SetParameters(rtp_parameters);
RTC_CHECK(res.ok()) << "Failed to set RTP parameters";
}
}
return out;
}
std::unique_ptr<test::TestVideoCapturer>
PeerConnectionE2EQualityTest::CreateVideoCapturer(
const VideoConfig& video_config,
std::unique_ptr<test::FrameGeneratorInterface> generator,
std::unique_ptr<test::TestVideoCapturer::FramePreprocessor>
frame_preprocessor) {
if (video_config.capturing_device_index) {
std::unique_ptr<test::TestVideoCapturer> capturer =
test::CreateVideoCapturer(video_config.width, video_config.height,
video_config.fps,
*video_config.capturing_device_index);
RTC_CHECK(capturer)
<< "Failed to obtain input stream from capturing device #"
<< *video_config.capturing_device_index;
capturer->SetFramePreprocessor(std::move(frame_preprocessor));
return capturer;
}
std::unique_ptr<test::FrameGeneratorInterface> frame_generator = nullptr;
if (generator) {
frame_generator = std::move(generator);
}
if (video_config.generator) {
absl::optional<test::FrameGeneratorInterface::OutputType>
frame_generator_type = absl::nullopt;
if (video_config.generator == VideoGeneratorType::kDefault) {
frame_generator_type = test::FrameGeneratorInterface::OutputType::kI420;
} else if (video_config.generator == VideoGeneratorType::kI420A) {
frame_generator_type = test::FrameGeneratorInterface::OutputType::kI420A;
} else if (video_config.generator == VideoGeneratorType::kI010) {
frame_generator_type = test::FrameGeneratorInterface::OutputType::kI010;
}
frame_generator =
test::CreateSquareFrameGenerator(static_cast<int>(video_config.width),
static_cast<int>(video_config.height),
frame_generator_type, absl::nullopt);
}
if (video_config.input_file_name) {
frame_generator = test::CreateFromYuvFileFrameGenerator(
std::vector<std::string>(/*count=*/1,
video_config.input_file_name.value()),
video_config.width, video_config.height, /*frame_repeat_count=*/1);
}
if (video_config.screen_share_config) {
frame_generator = CreateScreenShareFrameGenerator(video_config);
}
RTC_CHECK(frame_generator) << "Unsupported video_config input source";
auto capturer = std::make_unique<test::FrameGeneratorCapturer>(
clock_, std::move(frame_generator), video_config.fps,
*task_queue_factory_);
capturer->SetFramePreprocessor(std::move(frame_preprocessor));
capturer->Init();
return capturer;
}
std::unique_ptr<test::FrameGeneratorInterface>
PeerConnectionE2EQualityTest::CreateScreenShareFrameGenerator(
const VideoConfig& video_config) {
RTC_CHECK(video_config.screen_share_config);
if (video_config.screen_share_config->generate_slides) {
return test::CreateSlideFrameGenerator(
video_config.width, video_config.height,
video_config.screen_share_config->slide_change_interval.seconds() *
video_config.fps);
}
std::vector<std::string> slides =
video_config.screen_share_config->slides_yuv_file_names;
if (slides.empty()) {
// If slides is empty we need to add default slides as source. In such case
// video width and height is validated to be equal to kDefaultSlidesWidth
// and kDefaultSlidesHeight.
slides.push_back(test::ResourcePath("web_screenshot_1850_1110", "yuv"));
slides.push_back(test::ResourcePath("presentation_1850_1110", "yuv"));
slides.push_back(test::ResourcePath("photo_1850_1110", "yuv"));
slides.push_back(test::ResourcePath("difficult_photo_1850_1110", "yuv"));
}
if (!video_config.screen_share_config->scrolling_params) {
// Cycle image every slide_change_interval seconds.
return test::CreateFromYuvFileFrameGenerator(
slides, video_config.width, video_config.height,
video_config.screen_share_config->slide_change_interval.seconds() *
video_config.fps);
}
// |pause_duration| is nonnegative. It is validated in ValidateParams(...).
TimeDelta pause_duration =
video_config.screen_share_config->slide_change_interval -
video_config.screen_share_config->scrolling_params->duration;
return test::CreateScrollingInputFromYuvFilesFrameGenerator(
clock_, slides,
video_config.screen_share_config->scrolling_params->source_width,
video_config.screen_share_config->scrolling_params->source_height,
video_config.width, video_config.height,
video_config.screen_share_config->scrolling_params->duration.ms(),
pause_duration.ms());
}
void PeerConnectionE2EQualityTest::MaybeAddAudio(TestPeer* peer) {
if (!peer->params()->audio_config) {
return;
}
const AudioConfig& audio_config = peer->params()->audio_config.value();
rtc::scoped_refptr<webrtc::AudioSourceInterface> source =
peer->pc_factory()->CreateAudioSource(audio_config.audio_options);
rtc::scoped_refptr<AudioTrackInterface> track =
peer->pc_factory()->CreateAudioTrack(*audio_config.stream_label, source);
std::string sync_group = audio_config.sync_group
? audio_config.sync_group.value()
: audio_config.stream_label.value();
peer->AddTrack(track, {sync_group, *audio_config.stream_label});
}
void PeerConnectionE2EQualityTest::SetPeerCodecPreferences( void PeerConnectionE2EQualityTest::SetPeerCodecPreferences(
TestPeer* peer, TestPeer* peer,
const RunParams& run_params) { const RunParams& run_params) {
@ -1065,24 +896,7 @@ void PeerConnectionE2EQualityTest::TearDownCall() {
alice_.reset(); alice_.reset();
bob_.reset(); bob_.reset();
for (const auto& video_writer : video_writers_) { media_helper_.reset();
video_writer->Close();
}
video_writers_.clear();
}
test::VideoFrameWriter* PeerConnectionE2EQualityTest::MaybeCreateVideoWriter(
absl::optional<std::string> file_name,
const VideoConfig& config) {
if (!file_name) {
return nullptr;
}
// TODO(titovartem) create only one file writer for simulcast video track.
auto video_writer = std::make_unique<test::Y4mVideoFrameWriterImpl>(
file_name.value(), config.width, config.height, config.fps);
test::VideoFrameWriter* out = video_writer.get();
video_writers_.push_back(std::move(video_writer));
return out;
} }
Timestamp PeerConnectionE2EQualityTest::Now() const { Timestamp PeerConnectionE2EQualityTest::Now() const {

View File

@ -17,11 +17,9 @@
#include "api/task_queue/task_queue_factory.h" #include "api/task_queue/task_queue_factory.h"
#include "api/test/audio_quality_analyzer_interface.h" #include "api/test/audio_quality_analyzer_interface.h"
#include "api/test/frame_generator_interface.h"
#include "api/test/peerconnection_quality_test_fixture.h" #include "api/test/peerconnection_quality_test_fixture.h"
#include "api/units/time_delta.h" #include "api/units/time_delta.h"
#include "api/units/timestamp.h" #include "api/units/timestamp.h"
#include "pc/video_track_source.h"
#include "rtc_base/task_queue_for_test.h" #include "rtc_base/task_queue_for_test.h"
#include "rtc_base/task_utils/repeating_task.h" #include "rtc_base/task_utils/repeating_task.h"
#include "rtc_base/thread.h" #include "rtc_base/thread.h"
@ -31,10 +29,10 @@
#include "test/pc/e2e/analyzer/video/single_process_encoded_image_data_injector.h" #include "test/pc/e2e/analyzer/video/single_process_encoded_image_data_injector.h"
#include "test/pc/e2e/analyzer/video/video_quality_analyzer_injection_helper.h" #include "test/pc/e2e/analyzer/video/video_quality_analyzer_injection_helper.h"
#include "test/pc/e2e/analyzer_helper.h" #include "test/pc/e2e/analyzer_helper.h"
#include "test/pc/e2e/media/media_helper.h"
#include "test/pc/e2e/peer_connection_quality_test_params.h" #include "test/pc/e2e/peer_connection_quality_test_params.h"
#include "test/pc/e2e/sdp/sdp_changer.h" #include "test/pc/e2e/sdp/sdp_changer.h"
#include "test/pc/e2e/test_peer.h" #include "test/pc/e2e/test_peer.h"
#include "test/testsupport/video_frame_writer.h"
namespace webrtc { namespace webrtc {
namespace webrtc_pc_e2e { namespace webrtc_pc_e2e {
@ -184,33 +182,6 @@ class PeerConfigurerImpl final
std::vector<std::unique_ptr<test::FrameGeneratorInterface>> video_generators_; std::vector<std::unique_ptr<test::FrameGeneratorInterface>> video_generators_;
}; };
class TestVideoCapturerVideoTrackSource : public VideoTrackSource {
public:
TestVideoCapturerVideoTrackSource(
std::unique_ptr<test::TestVideoCapturer> video_capturer,
bool is_screencast)
: VideoTrackSource(/*remote=*/false),
video_capturer_(std::move(video_capturer)),
is_screencast_(is_screencast) {}
~TestVideoCapturerVideoTrackSource() = default;
void Start() { SetState(kLive); }
void Stop() { SetState(kMuted); }
bool is_screencast() const override { return is_screencast_; }
protected:
rtc::VideoSourceInterface<VideoFrame>* source() override {
return video_capturer_.get();
}
private:
std::unique_ptr<test::TestVideoCapturer> video_capturer_;
const bool is_screencast_;
};
class PeerConnectionE2EQualityTest class PeerConnectionE2EQualityTest
: public PeerConnectionE2EQualityTestFixture { : public PeerConnectionE2EQualityTestFixture {
public: public:
@ -291,18 +262,6 @@ class PeerConnectionE2EQualityTest
// Have to be run on the signaling thread. // Have to be run on the signaling thread.
void SetupCallOnSignalingThread(const RunParams& run_params); void SetupCallOnSignalingThread(const RunParams& run_params);
void TearDownCallOnSignalingThread(); void TearDownCallOnSignalingThread();
std::vector<rtc::scoped_refptr<TestVideoCapturerVideoTrackSource>>
MaybeAddMedia(TestPeer* peer);
std::vector<rtc::scoped_refptr<TestVideoCapturerVideoTrackSource>>
MaybeAddVideo(TestPeer* peer);
std::unique_ptr<test::TestVideoCapturer> CreateVideoCapturer(
const VideoConfig& video_config,
std::unique_ptr<test::FrameGeneratorInterface> generator,
std::unique_ptr<test::TestVideoCapturer::FramePreprocessor>
frame_preprocessor);
std::unique_ptr<test::FrameGeneratorInterface>
CreateScreenShareFrameGenerator(const VideoConfig& video_config);
void MaybeAddAudio(TestPeer* peer);
void SetPeerCodecPreferences(TestPeer* peer, const RunParams& run_params); void SetPeerCodecPreferences(TestPeer* peer, const RunParams& run_params);
void SetupCall(const RunParams& run_params); void SetupCall(const RunParams& run_params);
void ExchangeOfferAnswer(SignalingInterceptor* signaling_interceptor); void ExchangeOfferAnswer(SignalingInterceptor* signaling_interceptor);
@ -311,9 +270,6 @@ class PeerConnectionE2EQualityTest
const std::vector<rtc::scoped_refptr<TestVideoCapturerVideoTrackSource>>& const std::vector<rtc::scoped_refptr<TestVideoCapturerVideoTrackSource>>&
sources); sources);
void TearDownCall(); void TearDownCall();
test::VideoFrameWriter* MaybeCreateVideoWriter(
absl::optional<std::string> file_name,
const VideoConfig& config);
Timestamp Now() const; Timestamp Now() const;
Clock* const clock_; Clock* const clock_;
@ -321,6 +277,7 @@ class PeerConnectionE2EQualityTest
std::string test_case_name_; std::string test_case_name_;
std::unique_ptr<VideoQualityAnalyzerInjectionHelper> std::unique_ptr<VideoQualityAnalyzerInjectionHelper>
video_quality_analyzer_injection_helper_; video_quality_analyzer_injection_helper_;
std::unique_ptr<MediaHelper> media_helper_;
std::unique_ptr<SingleProcessEncodedImageDataInjector> std::unique_ptr<SingleProcessEncodedImageDataInjector>
encoded_image_id_controller_; encoded_image_id_controller_;
std::unique_ptr<AudioQualityAnalyzerInterface> audio_quality_analyzer_; std::unique_ptr<AudioQualityAnalyzerInterface> audio_quality_analyzer_;
@ -338,7 +295,6 @@ class PeerConnectionE2EQualityTest
alice_video_sources_; alice_video_sources_;
std::vector<rtc::scoped_refptr<TestVideoCapturerVideoTrackSource>> std::vector<rtc::scoped_refptr<TestVideoCapturerVideoTrackSource>>
bob_video_sources_; bob_video_sources_;
std::vector<std::unique_ptr<test::VideoFrameWriter>> video_writers_;
std::vector<std::unique_ptr<rtc::VideoSinkInterface<VideoFrame>>> std::vector<std::unique_ptr<rtc::VideoSinkInterface<VideoFrame>>>
output_video_sinks_; output_video_sinks_;
AnalyzerHelper analyzer_helper_; AnalyzerHelper analyzer_helper_;