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:
@ -70,4 +70,7 @@ specific_include_rules = {
|
||||
"+pc",
|
||||
"+p2p",
|
||||
],
|
||||
".*test_video_capturer_video_track_source.h": [
|
||||
"+pc",
|
||||
]
|
||||
}
|
||||
|
@ -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") {
|
||||
visibility = [ "*" ]
|
||||
testonly = true
|
||||
@ -270,6 +293,7 @@ if (rtc_include_tests) {
|
||||
":analyzer_helper",
|
||||
":default_audio_quality_analyzer",
|
||||
":default_video_quality_analyzer",
|
||||
":media_helper",
|
||||
":peer_connection_quality_test_params",
|
||||
":sdp_changer",
|
||||
":single_process_encoded_image_data_injector",
|
||||
@ -279,11 +303,8 @@ if (rtc_include_tests) {
|
||||
":video_quality_analyzer_injection_helper",
|
||||
":video_quality_metrics_reporter",
|
||||
"../..:field_trial",
|
||||
"../..:platform_video_capturer",
|
||||
"../..:video_test_common",
|
||||
"../..:fileutils",
|
||||
"../../../api:audio_quality_analyzer_api",
|
||||
"../../../api:create_frame_generator",
|
||||
"../../../api:frame_generator_api",
|
||||
"../../../api:libjingle_peerconnection_api",
|
||||
"../../../api:media_stream_interface",
|
||||
"../../../api:peer_connection_quality_test_fixture_api",
|
||||
@ -295,20 +316,17 @@ if (rtc_include_tests) {
|
||||
"../../../api/task_queue:default_task_queue_factory",
|
||||
"../../../api/units:time_delta",
|
||||
"../../../api/units:timestamp",
|
||||
"../../../api/video:video_frame",
|
||||
"../../../pc:pc_test_utils",
|
||||
"../../../pc:peerconnection",
|
||||
"../../../rtc_base",
|
||||
"../../../rtc_base:gunit_helpers",
|
||||
"../../../rtc_base:macromagic",
|
||||
"../../../rtc_base:rtc_base_approved",
|
||||
"../../../rtc_base:rtc_task_queue",
|
||||
"../../../rtc_base:safe_conversions",
|
||||
"../../../rtc_base:task_queue_for_test",
|
||||
"../../../rtc_base/task_utils:repeating_task",
|
||||
"../../../system_wrappers",
|
||||
"../../../system_wrappers:field_trial",
|
||||
"../../../test:fileutils",
|
||||
"../../../test:video_test_support",
|
||||
]
|
||||
}
|
||||
|
||||
|
217
test/pc/e2e/media/media_helper.cc
Normal file
217
test/pc/e2e/media/media_helper.cc
Normal 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
|
70
test/pc/e2e/media/media_helper.h
Normal file
70
test/pc/e2e/media/media_helper.h
Normal 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_
|
55
test/pc/e2e/media/test_video_capturer_video_track_source.h
Normal file
55
test/pc/e2e/media/test_video_capturer_video_track_source.h
Normal 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_
|
@ -21,10 +21,8 @@
|
||||
#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/create_frame_generator.h"
|
||||
#include "api/test/video_quality_analyzer_interface.h"
|
||||
#include "api/units/time_delta.h"
|
||||
#include "api/video/video_source_interface.h"
|
||||
#include "pc/sdp_utils.h"
|
||||
#include "pc/test/mock_peer_connection_observers.h"
|
||||
#include "rtc_base/bind.h"
|
||||
@ -32,13 +30,11 @@
|
||||
#include "rtc_base/numerics/safe_conversions.h"
|
||||
#include "system_wrappers/include/cpu_info.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/video/default_video_quality_analyzer.h"
|
||||
#include "test/pc/e2e/analyzer/video/video_quality_metrics_reporter.h"
|
||||
#include "test/pc/e2e/stats_poller.h"
|
||||
#include "test/pc/e2e/test_peer_factory.h"
|
||||
#include "test/platform_video_capturer.h"
|
||||
#include "test/testsupport/file_utils.h"
|
||||
|
||||
namespace webrtc {
|
||||
@ -271,6 +267,9 @@ void PeerConnectionE2EQualityTest::Run(RunParams run_params) {
|
||||
const std::unique_ptr<rtc::Thread> signaling_thread = rtc::Thread::Create();
|
||||
signaling_thread->SetName(kSignalThreadName, nullptr);
|
||||
signaling_thread->Start();
|
||||
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");
|
||||
@ -449,11 +448,10 @@ void PeerConnectionE2EQualityTest::Run(RunParams run_params) {
|
||||
// Audio dumps.
|
||||
RTC_CHECK(!alice_);
|
||||
RTC_CHECK(!bob_);
|
||||
// Ensuring that TestVideoCapturerVideoTrackSource and VideoFrameWriter
|
||||
// are destroyed on the right thread.
|
||||
// Ensuring that TestVideoCapturerVideoTrackSource are destroyed on the right
|
||||
// thread.
|
||||
RTC_CHECK(alice_video_sources_.empty());
|
||||
RTC_CHECK(bob_video_sources_.empty());
|
||||
RTC_CHECK(video_writers_.empty());
|
||||
}
|
||||
|
||||
void PeerConnectionE2EQualityTest::SetDefaultValuesForMissingParams(
|
||||
@ -649,7 +647,7 @@ void PeerConnectionE2EQualityTest::OnTrackCallback(
|
||||
}
|
||||
}
|
||||
RTC_CHECK(video_config);
|
||||
test::VideoFrameWriter* writer = MaybeCreateVideoWriter(
|
||||
test::VideoFrameWriter* writer = media_helper_->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.
|
||||
@ -727,8 +725,10 @@ void PeerConnectionE2EQualityTest::SetupCallOnSignalingThread(
|
||||
}
|
||||
|
||||
// Then add media for Alice and Bob
|
||||
alice_video_sources_ = MaybeAddMedia(alice_.get());
|
||||
bob_video_sources_ = MaybeAddMedia(bob_.get());
|
||||
media_helper_->MaybeAddAudio(alice_.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(bob_.get(), run_params);
|
||||
@ -740,175 +740,6 @@ void PeerConnectionE2EQualityTest::TearDownCallOnSignalingThread() {
|
||||
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(
|
||||
TestPeer* peer,
|
||||
const RunParams& run_params) {
|
||||
@ -1065,24 +896,7 @@ void PeerConnectionE2EQualityTest::TearDownCall() {
|
||||
alice_.reset();
|
||||
bob_.reset();
|
||||
|
||||
for (const auto& video_writer : video_writers_) {
|
||||
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;
|
||||
media_helper_.reset();
|
||||
}
|
||||
|
||||
Timestamp PeerConnectionE2EQualityTest::Now() const {
|
||||
|
@ -17,11 +17,9 @@
|
||||
|
||||
#include "api/task_queue/task_queue_factory.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/units/time_delta.h"
|
||||
#include "api/units/timestamp.h"
|
||||
#include "pc/video_track_source.h"
|
||||
#include "rtc_base/task_queue_for_test.h"
|
||||
#include "rtc_base/task_utils/repeating_task.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/video_quality_analyzer_injection_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/sdp/sdp_changer.h"
|
||||
#include "test/pc/e2e/test_peer.h"
|
||||
#include "test/testsupport/video_frame_writer.h"
|
||||
|
||||
namespace webrtc {
|
||||
namespace webrtc_pc_e2e {
|
||||
@ -184,33 +182,6 @@ class PeerConfigurerImpl final
|
||||
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
|
||||
: public PeerConnectionE2EQualityTestFixture {
|
||||
public:
|
||||
@ -291,18 +262,6 @@ class PeerConnectionE2EQualityTest
|
||||
// Have to be run on the signaling thread.
|
||||
void SetupCallOnSignalingThread(const RunParams& run_params);
|
||||
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 SetupCall(const RunParams& run_params);
|
||||
void ExchangeOfferAnswer(SignalingInterceptor* signaling_interceptor);
|
||||
@ -311,9 +270,6 @@ class PeerConnectionE2EQualityTest
|
||||
const std::vector<rtc::scoped_refptr<TestVideoCapturerVideoTrackSource>>&
|
||||
sources);
|
||||
void TearDownCall();
|
||||
test::VideoFrameWriter* MaybeCreateVideoWriter(
|
||||
absl::optional<std::string> file_name,
|
||||
const VideoConfig& config);
|
||||
Timestamp Now() const;
|
||||
|
||||
Clock* const clock_;
|
||||
@ -321,6 +277,7 @@ class PeerConnectionE2EQualityTest
|
||||
std::string test_case_name_;
|
||||
std::unique_ptr<VideoQualityAnalyzerInjectionHelper>
|
||||
video_quality_analyzer_injection_helper_;
|
||||
std::unique_ptr<MediaHelper> media_helper_;
|
||||
std::unique_ptr<SingleProcessEncodedImageDataInjector>
|
||||
encoded_image_id_controller_;
|
||||
std::unique_ptr<AudioQualityAnalyzerInterface> audio_quality_analyzer_;
|
||||
@ -338,7 +295,6 @@ class PeerConnectionE2EQualityTest
|
||||
alice_video_sources_;
|
||||
std::vector<rtc::scoped_refptr<TestVideoCapturerVideoTrackSource>>
|
||||
bob_video_sources_;
|
||||
std::vector<std::unique_ptr<test::VideoFrameWriter>> video_writers_;
|
||||
std::vector<std::unique_ptr<rtc::VideoSinkInterface<VideoFrame>>>
|
||||
output_video_sinks_;
|
||||
AnalyzerHelper analyzer_helper_;
|
||||
|
Reference in New Issue
Block a user