From 6a78e93346e76a2f9442261751b713d1ec76223c Mon Sep 17 00:00:00 2001 From: Artem Titov Date: Tue, 21 Mar 2023 13:46:47 +0100 Subject: [PATCH] [PCLF] Introduce test video source and make it more controllable Bug: b/272350185 Change-Id: I15572b7e4d0cb0ce41da676a4eedbc1e138510fc Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/298047 Reviewed-by: Mirko Bonadei Commit-Queue: Artem Titov Reviewed-by: Harald Alvestrand Cr-Commit-Position: refs/heads/main@{#39621} --- api/test/video/BUILD.gn | 24 +++++- api/test/video/DEPS | 6 ++ api/test/video/test_video_track_source.cc | 54 +++++++++++++ api/test/video/test_video_track_source.h | 78 +++++++++++++++++++ test/pc/e2e/BUILD.gn | 2 + .../test_video_capturer_video_track_source.h | 43 +++++++--- test/test_video_capturer.cc | 9 +++ test/test_video_capturer.h | 5 ++ 8 files changed, 210 insertions(+), 11 deletions(-) create mode 100644 api/test/video/DEPS create mode 100644 api/test/video/test_video_track_source.cc create mode 100644 api/test/video/test_video_track_source.h diff --git a/api/test/video/BUILD.gn b/api/test/video/BUILD.gn index d24ffa5fa6..0eae85aef3 100644 --- a/api/test/video/BUILD.gn +++ b/api/test/video/BUILD.gn @@ -11,7 +11,7 @@ import("../../../webrtc.gni") rtc_library("function_video_factory") { visibility = [ "*" ] testonly = true - public = [ + sources = [ "function_video_decoder_factory.h", "function_video_encoder_factory.h", ] @@ -25,7 +25,27 @@ rtc_library("function_video_factory") { rtc_library("video_frame_writer") { visibility = [ "*" ] testonly = true - public = [ "video_frame_writer.h" ] + sources = [ "video_frame_writer.h" ] deps = [ "../../video:video_frame" ] } + +rtc_library("test_video_track_source") { + visibility = [ "*" ] + testonly = true + sources = [ + "test_video_track_source.cc", + "test_video_track_source.h", + ] + + deps = [ + "../..:media_stream_interface", + "../..:sequence_checker", + "../../../rtc_base:checks", + "../../../rtc_base:macromagic", + "../../../rtc_base/system:no_unique_address", + "../../video:recordable_encoded_frame", + "../../video:video_frame", + ] + absl_deps = [ "//third_party/abseil-cpp/absl/types:optional" ] +} diff --git a/api/test/video/DEPS b/api/test/video/DEPS new file mode 100644 index 0000000000..2256b34db2 --- /dev/null +++ b/api/test/video/DEPS @@ -0,0 +1,6 @@ +specific_include_rules = { + "test_video_track_source\.h": [ + "+rtc_base/thread_annotations.h", + "+rtc_base/system/no_unique_address.h", + ], +} diff --git a/api/test/video/test_video_track_source.cc b/api/test/video/test_video_track_source.cc new file mode 100644 index 0000000000..c570a7a05f --- /dev/null +++ b/api/test/video/test_video_track_source.cc @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2023 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 "api/test/video/test_video_track_source.h" + +#include "api/media_stream_interface.h" +#include "api/sequence_checker.h" +#include "api/video/video_frame.h" +#include "api/video/video_sink_interface.h" +#include "api/video/video_source_interface.h" +#include "rtc_base/checks.h" + +namespace webrtc { +namespace test { + +TestVideoTrackSource::TestVideoTrackSource(bool remote) + : state_(kInitializing), remote_(remote) { + worker_thread_checker_.Detach(); +} + +VideoTrackSourceInterface::SourceState TestVideoTrackSource::state() const { + RTC_DCHECK_RUN_ON(&signaling_thread_checker_); + return state_; +} + +void TestVideoTrackSource::SetState(SourceState new_state) { + RTC_DCHECK_RUN_ON(&signaling_thread_checker_); + if (state_ != new_state) { + state_ = new_state; + FireOnChanged(); + } +} + +void TestVideoTrackSource::AddOrUpdateSink( + rtc::VideoSinkInterface* sink, + const rtc::VideoSinkWants& wants) { + RTC_DCHECK(worker_thread_checker_.IsCurrent()); + source()->AddOrUpdateSink(sink, wants); +} + +void TestVideoTrackSource::RemoveSink( + rtc::VideoSinkInterface* sink) { + RTC_DCHECK(worker_thread_checker_.IsCurrent()); + source()->RemoveSink(sink); +} + +} // namespace test +} // namespace webrtc diff --git a/api/test/video/test_video_track_source.h b/api/test/video/test_video_track_source.h new file mode 100644 index 0000000000..4e2d138be0 --- /dev/null +++ b/api/test/video/test_video_track_source.h @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2023 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 API_TEST_VIDEO_TEST_VIDEO_TRACK_SOURCE_H_ +#define API_TEST_VIDEO_TEST_VIDEO_TRACK_SOURCE_H_ + +#include "absl/types/optional.h" +#include "api/media_stream_interface.h" +#include "api/notifier.h" +#include "api/sequence_checker.h" +#include "api/video/recordable_encoded_frame.h" +#include "api/video/video_frame.h" +#include "api/video/video_sink_interface.h" +#include "api/video/video_source_interface.h" +#include "rtc_base/system/no_unique_address.h" +#include "rtc_base/thread_annotations.h" + +namespace webrtc { +namespace test { + +// Video source that can be used as input for tests. +class TestVideoTrackSource : public Notifier { + public: + explicit TestVideoTrackSource(bool remote); + ~TestVideoTrackSource() override = default; + + void SetState(SourceState new_state); + + SourceState state() const override; + bool remote() const override { return remote_; } + + bool is_screencast() const override { return false; } + absl::optional needs_denoising() const override { + return absl::nullopt; + } + + bool GetStats(Stats* stats) override { return false; } + + void AddOrUpdateSink(rtc::VideoSinkInterface* sink, + const rtc::VideoSinkWants& wants) override; + void RemoveSink(rtc::VideoSinkInterface* sink) override; + + bool SupportsEncodedOutput() const override { return false; } + void GenerateKeyFrame() override {} + void AddEncodedSink( + rtc::VideoSinkInterface* sink) override {} + void RemoveEncodedSink( + rtc::VideoSinkInterface* sink) override {} + + // Starts producing video. + virtual void Start() = 0; + + // Stops producing video. + virtual void Stop() = 0; + + virtual void SetScreencast(bool is_screencast) = 0; + + protected: + virtual rtc::VideoSourceInterface* source() = 0; + + private: + RTC_NO_UNIQUE_ADDRESS SequenceChecker worker_thread_checker_; + RTC_NO_UNIQUE_ADDRESS SequenceChecker signaling_thread_checker_; + SourceState state_ RTC_GUARDED_BY(&signaling_thread_checker_); + const bool remote_; +}; + +} // namespace test +} // namespace webrtc + +#endif // API_TEST_VIDEO_TEST_VIDEO_TRACK_SOURCE_H_ diff --git a/test/pc/e2e/BUILD.gn b/test/pc/e2e/BUILD.gn index ae9dd6414c..635b917ba0 100644 --- a/test/pc/e2e/BUILD.gn +++ b/test/pc/e2e/BUILD.gn @@ -136,8 +136,10 @@ if (!build_with_chromium) { "../../../api:create_frame_generator", "../../../api:frame_generator_api", "../../../api:media_stream_interface", + "../../../api:sequence_checker", "../../../api/test/pclf:media_configuration", "../../../api/test/pclf:peer_configurer", + "../../../api/test/video:test_video_track_source", "../../../api/video:video_frame", "../../../pc:session_description", "../../../pc:video_track_source", diff --git a/test/pc/e2e/media/test_video_capturer_video_track_source.h b/test/pc/e2e/media/test_video_capturer_video_track_source.h index c883a2e8e9..350766bb49 100644 --- a/test/pc/e2e/media/test_video_capturer_video_track_source.h +++ b/test/pc/e2e/media/test_video_capturer_video_track_source.h @@ -14,30 +14,54 @@ #include #include +#include "api/sequence_checker.h" +#include "api/test/video/test_video_track_source.h" #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 { +class TestVideoCapturerVideoTrackSource : public test::TestVideoTrackSource { public: TestVideoCapturerVideoTrackSource( std::unique_ptr video_capturer, bool is_screencast) - : VideoTrackSource(/*remote=*/false), + : TestVideoTrackSource(/*remote=*/false), video_capturer_(std::move(video_capturer)), - is_screencast_(is_screencast) {} + is_screencast_(is_screencast) { + sequence_checker_.Detach(); + } + + TestVideoCapturerVideoTrackSource(const TestVideoCapturerVideoTrackSource&) = + delete; + TestVideoCapturerVideoTrackSource& operator=( + const TestVideoCapturerVideoTrackSource&) = delete; + TestVideoCapturerVideoTrackSource(TestVideoCapturerVideoTrackSource&&) = + delete; + TestVideoCapturerVideoTrackSource& operator=( + TestVideoCapturerVideoTrackSource&&) = delete; ~TestVideoCapturerVideoTrackSource() = default; - void Start() { SetState(kLive); } + void Start() override { SetState(kLive); } - void Stop() { SetState(kMuted); } + void Stop() override { SetState(kMuted); } - bool is_screencast() const override { return is_screencast_; } + bool is_screencast() const override { + RTC_DCHECK_RUN_ON(&sequence_checker_); + return is_screencast_; + } + + void SetDisableAdaptation(bool disable_adaptation) { + video_capturer_->SetDisableAdaptation(disable_adaptation); + } + + void SetScreencast(bool is_screencast) override { + RTC_DCHECK_RUN_ON(&sequence_checker_); + is_screencast_ = is_screencast; + } protected: rtc::VideoSourceInterface* source() override { @@ -45,8 +69,9 @@ class TestVideoCapturerVideoTrackSource : public VideoTrackSource { } private: - std::unique_ptr video_capturer_; - const bool is_screencast_; + const std::unique_ptr video_capturer_; + SequenceChecker sequence_checker_; + bool is_screencast_ RTC_GUARDED_BY(sequence_checker_); }; } // namespace webrtc_pc_e2e diff --git a/test/test_video_capturer.cc b/test/test_video_capturer.cc index 4a4adc61d7..b55eefcb2f 100644 --- a/test/test_video_capturer.cc +++ b/test/test_video_capturer.cc @@ -40,6 +40,15 @@ void TestVideoCapturer::OnFrame(const VideoFrame& original_frame) { VideoFrame frame = MaybePreprocess(original_frame); + bool disable_adaptation; + { + MutexLock lock(&lock_); + disable_adaptation = disable_adaptation_; + } + if (disable_adaptation) { + broadcaster_.OnFrame(frame); + } + if (!video_adapter_.AdaptFrameResolution( frame.width(), frame.height(), frame.timestamp_us() * 1000, &cropped_width, &cropped_height, &out_width, &out_height)) { diff --git a/test/test_video_capturer.h b/test/test_video_capturer.h index 6fafd96efb..3fc03f07eb 100644 --- a/test/test_video_capturer.h +++ b/test/test_video_capturer.h @@ -41,6 +41,10 @@ class TestVideoCapturer : public rtc::VideoSourceInterface { MutexLock lock(&lock_); preprocessor_ = std::move(preprocessor); } + void SetDisableAdaptation(bool disable_adaptation) { + MutexLock lock(&lock_); + disable_adaptation_ = disable_adaptation; + } void OnOutputFormatRequest(int width, int height, const absl::optional& max_fps); @@ -55,6 +59,7 @@ class TestVideoCapturer : public rtc::VideoSourceInterface { Mutex lock_; std::unique_ptr preprocessor_ RTC_GUARDED_BY(lock_); + bool disable_adaptation_ RTC_GUARDED_BY(lock_) = false; rtc::VideoBroadcaster broadcaster_; cricket::VideoAdapter video_adapter_; };