diff --git a/api/BUILD.gn b/api/BUILD.gn index 48d377000f..4265f97cd7 100644 --- a/api/BUILD.gn +++ b/api/BUILD.gn @@ -374,6 +374,20 @@ rtc_source_set("peer_connection_quality_test_fixture_api") { ] } +rtc_source_set("frame_generator_api") { + visibility = [ "*" ] + testonly = true + sources = [ + "test/frame_generator_interface.h", + ] + + deps = [ + ":scoped_refptr", + "video:video_frame", + "//third_party/abseil-cpp/absl/types:optional", + ] +} + rtc_library("test_dependency_factory") { visibility = [ "*" ] testonly = true @@ -433,6 +447,21 @@ if (rtc_include_tests) { "../test/pc/e2e:peerconnection_quality_test", ] } + + rtc_library("create_frame_generator") { + visibility = [ "*" ] + testonly = true + sources = [ + "test/create_frame_generator.cc", + "test/create_frame_generator.h", + ] + deps = [ + ":frame_generator_api", + "../system_wrappers", + "../test:video_test_common", + "//third_party/abseil-cpp/absl/types:optional", + ] + } } rtc_source_set("libjingle_logging_api") { diff --git a/api/test/DEPS b/api/test/DEPS index 1fced5d066..b5bbed6ca6 100644 --- a/api/test/DEPS +++ b/api/test/DEPS @@ -37,4 +37,7 @@ specific_include_rules = { "+rtc_base/synchronization/yield_policy.h", "+system_wrappers/include/clock.h", ], + "create_frame_generator\.h": [ + "+system_wrappers/include/clock.h", + ], } diff --git a/api/test/create_frame_generator.cc b/api/test/create_frame_generator.cc new file mode 100644 index 0000000000..b6e62a4d97 --- /dev/null +++ b/api/test/create_frame_generator.cc @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2019 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/create_frame_generator.h" + +#include + +#include "test/frame_generator.h" + +namespace webrtc { +namespace test { + +std::unique_ptr CreateSquareFrameGenerator( + int width, + int height, + absl::optional type, + absl::optional num_squares) { + return FrameGenerator::CreateSquareGenerator(width, height, type, + num_squares); +} + +std::unique_ptr CreateFromYuvFileFrameGenerator( + std::vector files, + size_t width, + size_t height, + int frame_repeat_count) { + return FrameGenerator::CreateFromYuvFile(std::move(files), width, height, + frame_repeat_count); +} + +std::unique_ptr +CreateScrollingInputFromYuvFilesFrameGenerator( + Clock* clock, + std::vector filenames, + size_t source_width, + size_t source_height, + size_t target_width, + size_t target_height, + int64_t scroll_time_ms, + int64_t pause_time_ms) { + return FrameGenerator::CreateScrollingInputFromYuvFiles( + clock, std::move(filenames), source_width, source_height, target_width, + target_height, scroll_time_ms, pause_time_ms); +} + +std::unique_ptr +CreateSlideFrameGenerator(int width, int height, int frame_repeat_count) { + return FrameGenerator::CreateSlideGenerator(width, height, + frame_repeat_count); +} + +} // namespace test +} // namespace webrtc diff --git a/api/test/create_frame_generator.h b/api/test/create_frame_generator.h new file mode 100644 index 0000000000..692c964638 --- /dev/null +++ b/api/test/create_frame_generator.h @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2019 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_CREATE_FRAME_GENERATOR_H_ +#define API_TEST_CREATE_FRAME_GENERATOR_H_ + +#include +#include +#include + +#include "absl/types/optional.h" +#include "api/test/frame_generator_interface.h" +#include "system_wrappers/include/clock.h" + +namespace webrtc { +namespace test { + +// Creates a frame generator that produces frames with small squares that +// move randomly towards the lower right corner. +// |type| has the default value FrameGeneratorInterface::OutputType::I420. +// |num_squares| has the default value 10. +std::unique_ptr CreateSquareFrameGenerator( + int width, + int height, + absl::optional type, + absl::optional num_squares); + +// Creates a frame generator that repeatedly plays a set of yuv files. +// The frame_repeat_count determines how many times each frame is shown, +// with 1 = show each frame once, etc. +std::unique_ptr CreateFromYuvFileFrameGenerator( + std::vector files, + size_t width, + size_t height, + int frame_repeat_count); + +// Creates a frame generator which takes a set of yuv files (wrapping a +// frame generator created by CreateFromYuvFile() above), but outputs frames +// that have been cropped to specified resolution: source_width/source_height +// is the size of the source images, target_width/target_height is the size of +// the cropped output. For each source image read, the cropped viewport will +// be scrolled top to bottom/left to right for scroll_tim_ms milliseconds. +// After that the image will stay in place for pause_time_ms milliseconds, +// and then this will be repeated with the next file from the input set. +std::unique_ptr +CreateScrollingInputFromYuvFilesFrameGenerator( + Clock* clock, + std::vector filenames, + size_t source_width, + size_t source_height, + size_t target_width, + size_t target_height, + int64_t scroll_time_ms, + int64_t pause_time_ms); + +// Creates a frame generator that produces randomly generated slides. It fills +// the frames with randomly sized and colored squares. +// |frame_repeat_count| determines how many times each slide is shown. +std::unique_ptr +CreateSlideFrameGenerator(int width, int height, int frame_repeat_count); + +} // namespace test +} // namespace webrtc + +#endif // API_TEST_CREATE_FRAME_GENERATOR_H_ diff --git a/api/test/frame_generator_interface.h b/api/test/frame_generator_interface.h new file mode 100644 index 0000000000..691b6ee3f7 --- /dev/null +++ b/api/test/frame_generator_interface.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2019 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_FRAME_GENERATOR_INTERFACE_H_ +#define API_TEST_FRAME_GENERATOR_INTERFACE_H_ + +#include + +#include "absl/types/optional.h" +#include "api/scoped_refptr.h" +#include "api/video/video_frame.h" +#include "api/video/video_frame_buffer.h" + +namespace webrtc { +namespace test { + +class FrameGeneratorInterface { + public: + struct VideoFrameData { + VideoFrameData(rtc::scoped_refptr buffer, + absl::optional update_rect) + : buffer(std::move(buffer)), update_rect(update_rect) {} + + rtc::scoped_refptr buffer; + absl::optional update_rect; + }; + + enum class OutputType { kI420, kI420A, kI010 }; + + virtual ~FrameGeneratorInterface() = default; + + // Returns VideoFrameBuffer and area where most of update was done to set them + // on the VideoFrame object. + virtual VideoFrameData NextFrame() = 0; + + // Change the capture resolution. + virtual void ChangeResolution(size_t width, size_t height) = 0; +}; + +} // namespace test +} // namespace webrtc + +#endif // API_TEST_FRAME_GENERATOR_INTERFACE_H_ diff --git a/test/BUILD.gn b/test/BUILD.gn index 8c22c928c0..a5519d2d56 100644 --- a/test/BUILD.gn +++ b/test/BUILD.gn @@ -53,6 +53,7 @@ rtc_library("video_test_common") { deps = [ ":fileutils", + "../api:frame_generator_api", "../api:scoped_refptr", "../api/task_queue", "../api/video:video_frame", diff --git a/test/frame_generator.h b/test/frame_generator.h index 95b710fada..47251b3a9e 100644 --- a/test/frame_generator.h +++ b/test/frame_generator.h @@ -14,6 +14,7 @@ #include #include +#include "api/test/frame_generator_interface.h" #include "api/video/video_frame.h" #include "api/video/video_source_interface.h" #include "rtc_base/critical_section.h" @@ -45,31 +46,12 @@ class FrameForwarder : public rtc::VideoSourceInterface { rtc::VideoSinkWants sink_wants_ RTC_GUARDED_BY(crit_); }; -class FrameGenerator { +class FrameGenerator : public FrameGeneratorInterface { public: - struct VideoFrameData { - VideoFrameData(rtc::scoped_refptr buffer, - absl::optional update_rect) - : buffer(std::move(buffer)), update_rect(update_rect) {} - - rtc::scoped_refptr buffer; - absl::optional update_rect; - }; - virtual ~FrameGenerator() = default; - // Returns VideoFrameBuffer and area where most of update was done to set them - // on the VideoFrame object. Returned frames can share same buffer. - virtual VideoFrameData NextFrame() = 0; - // Change the capture resolution. - virtual void ChangeResolution(size_t width, size_t height); - - enum class OutputType { - kI420, - kI420A, - kI010 - }; + void ChangeResolution(size_t width, size_t height) override; // Creates a frame generator that produces frames with small squares that // move randomly towards the lower right corner. diff --git a/test/frame_generator_capturer.cc b/test/frame_generator_capturer.cc index 5f1c6e0225..e817db9c5f 100644 --- a/test/frame_generator_capturer.cc +++ b/test/frame_generator_capturer.cc @@ -44,7 +44,7 @@ std::string TransformFilePath(std::string path) { FrameGeneratorCapturer::FrameGeneratorCapturer( Clock* clock, - std::unique_ptr frame_generator, + std::unique_ptr frame_generator, int target_fps, TaskQueueFactory& task_queue_factory) : clock_(clock), diff --git a/test/frame_generator_capturer.h b/test/frame_generator_capturer.h index faf049843d..6220870948 100644 --- a/test/frame_generator_capturer.h +++ b/test/frame_generator_capturer.h @@ -96,10 +96,11 @@ class FrameGeneratorCapturer : public TestVideoCapturer { virtual ~SinkWantsObserver() {} }; - FrameGeneratorCapturer(Clock* clock, - std::unique_ptr frame_generator, - int target_fps, - TaskQueueFactory& task_queue_factory); + FrameGeneratorCapturer( + Clock* clock, + std::unique_ptr frame_generator, + int target_fps, + TaskQueueFactory& task_queue_factory); virtual ~FrameGeneratorCapturer(); static std::unique_ptr Create( @@ -154,7 +155,7 @@ class FrameGeneratorCapturer : public TestVideoCapturer { SinkWantsObserver* sink_wants_observer_ RTC_GUARDED_BY(&lock_); rtc::CriticalSection lock_; - std::unique_ptr frame_generator_; + std::unique_ptr frame_generator_; int source_fps_ RTC_GUARDED_BY(&lock_); int target_capture_fps_ RTC_GUARDED_BY(&lock_); diff --git a/test/pc/e2e/BUILD.gn b/test/pc/e2e/BUILD.gn index ae6bc7404f..926301437b 100644 --- a/test/pc/e2e/BUILD.gn +++ b/test/pc/e2e/BUILD.gn @@ -292,6 +292,8 @@ if (rtc_include_tests) { "../..:platform_video_capturer", "../..:video_test_common", "../../../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", diff --git a/test/pc/e2e/peer_connection_quality_test.cc b/test/pc/e2e/peer_connection_quality_test.cc index a5fa65ad49..9baa3de9a9 100644 --- a/test/pc/e2e/peer_connection_quality_test.cc +++ b/test/pc/e2e/peer_connection_quality_test.cc @@ -21,6 +21,7 @@ #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" @@ -791,24 +792,24 @@ PeerConnectionE2EQualityTest::CreateVideoCapturer( return capturer; } - std::unique_ptr frame_generator = nullptr; + std::unique_ptr frame_generator = nullptr; if (video_config.generator) { - absl::optional frame_generator_type = - absl::nullopt; + absl::optional + frame_generator_type = absl::nullopt; if (video_config.generator == VideoGeneratorType::kDefault) { - frame_generator_type = test::FrameGenerator::OutputType::kI420; + frame_generator_type = test::FrameGeneratorInterface::OutputType::kI420; } else if (video_config.generator == VideoGeneratorType::kI420A) { - frame_generator_type = test::FrameGenerator::OutputType::kI420A; + frame_generator_type = test::FrameGeneratorInterface::OutputType::kI420A; } else if (video_config.generator == VideoGeneratorType::kI010) { - frame_generator_type = test::FrameGenerator::OutputType::kI010; + frame_generator_type = test::FrameGeneratorInterface::OutputType::kI010; } - frame_generator = test::FrameGenerator::CreateSquareGenerator( - static_cast(video_config.width), - static_cast(video_config.height), frame_generator_type, - absl::nullopt); + frame_generator = + test::CreateSquareFrameGenerator(static_cast(video_config.width), + static_cast(video_config.height), + frame_generator_type, absl::nullopt); } if (video_config.input_file_name) { - frame_generator = test::FrameGenerator::CreateFromYuvFile( + frame_generator = test::CreateFromYuvFileFrameGenerator( std::vector(/*count=*/1, video_config.input_file_name.value()), video_config.width, video_config.height, /*frame_repeat_count=*/1); @@ -826,12 +827,12 @@ PeerConnectionE2EQualityTest::CreateVideoCapturer( return capturer; } -std::unique_ptr +std::unique_ptr PeerConnectionE2EQualityTest::CreateScreenShareFrameGenerator( const VideoConfig& video_config) { RTC_CHECK(video_config.screen_share_config); if (video_config.screen_share_config->generate_slides) { - return test::FrameGenerator::CreateSlideGenerator( + return test::CreateSlideFrameGenerator( video_config.width, video_config.height, video_config.screen_share_config->slide_change_interval.seconds() * video_config.fps); @@ -849,7 +850,7 @@ PeerConnectionE2EQualityTest::CreateScreenShareFrameGenerator( } if (!video_config.screen_share_config->scrolling_params) { // Cycle image every slide_change_interval seconds. - return test::FrameGenerator::CreateFromYuvFile( + return test::CreateFromYuvFileFrameGenerator( slides, video_config.width, video_config.height, video_config.screen_share_config->slide_change_interval.seconds() * video_config.fps); @@ -860,7 +861,7 @@ PeerConnectionE2EQualityTest::CreateScreenShareFrameGenerator( video_config.screen_share_config->slide_change_interval - video_config.screen_share_config->scrolling_params->duration; - return test::FrameGenerator::CreateScrollingInputFromYuvFiles( + return test::CreateScrollingInputFromYuvFilesFrameGenerator( clock_, slides, video_config.screen_share_config->scrolling_params->source_width, video_config.screen_share_config->scrolling_params->source_height, diff --git a/test/pc/e2e/peer_connection_quality_test.h b/test/pc/e2e/peer_connection_quality_test.h index 669cdb311a..aeff087675 100644 --- a/test/pc/e2e/peer_connection_quality_test.h +++ b/test/pc/e2e/peer_connection_quality_test.h @@ -17,6 +17,7 @@ #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" @@ -289,8 +290,8 @@ class PeerConnectionE2EQualityTest std::unique_ptr> source, std::unique_ptr frame_preprocessor); - std::unique_ptr CreateScreenShareFrameGenerator( - const VideoConfig& video_config); + std::unique_ptr + CreateScreenShareFrameGenerator(const VideoConfig& video_config); void MaybeAddAudio(TestPeer* peer); void SetPeerCodecPreferences(TestPeer* peer, const RunParams& run_params); void SetupCall(const RunParams& run_params);