Move FrameGeneratorCapturerConfig and Create family methods

Move FrameGeneratorCapturerConfig and Create family methods from
frame_generator_capturer.h to the create_frame_generator_capturer.h

Bug: b/272350185
Change-Id: I95674f5238ac0d0a5e395840bbab7f205b160c37
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/301220
Reviewed-by: Mirko Bonadei <mbonadei@webrtc.org>
Commit-Queue: Artem Titov <titovartem@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#39850}
This commit is contained in:
Artem Titov 2023-04-13 14:34:59 +02:00 committed by WebRTC LUCI CQ
parent fb8e3de0a8
commit d77f2212b0
7 changed files with 221 additions and 206 deletions

View file

@ -129,15 +129,24 @@ rtc_library("test_video_capturer") {
rtc_library("create_frame_generator_capturer") {
visibility = [ "*" ]
testonly = true
sources = [ "create_frame_generator_capturer.h" ]
sources = [
"create_frame_generator_capturer.cc",
"create_frame_generator_capturer.h",
]
deps = [
":fileutils",
":frame_generator_capturer",
"../api:create_frame_generator",
"../api:frame_generator_api",
"../api/task_queue",
"../api/units:time_delta",
"../rtc_base:checks",
"../system_wrappers",
]
absl_deps = [ "//third_party/abseil-cpp/absl/types:optional" ]
absl_deps = [
"//third_party/abseil-cpp/absl/strings",
"//third_party/abseil-cpp/absl/types:optional",
]
}
rtc_library("frame_generator_capturer") {
@ -148,7 +157,6 @@ rtc_library("frame_generator_capturer") {
"frame_generator_capturer.h",
]
deps = [
":fileutils",
":test_video_capturer",
"../api:create_frame_generator",
"../api:frame_generator_api",
@ -693,6 +701,7 @@ if (rtc_include_tests) {
deps = [
":call_config_utils",
":copy_to_file_audio_capturer_unittest",
":create_frame_generator_capturer",
":direct_transport",
":fake_video_codecs",
":fileutils",

View file

@ -0,0 +1,133 @@
/*
* 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 "test/create_frame_generator_capturer.h"
#include <memory>
#include <string>
#include <utility>
#include <vector>
#include "absl/strings/match.h"
#include "api/task_queue/task_queue_factory.h"
#include "api/test/create_frame_generator.h"
#include "api/test/frame_generator_interface.h"
#include "api/units/time_delta.h"
#include "rtc_base/checks.h"
#include "system_wrappers/include/clock.h"
#include "test/testsupport/file_utils.h"
namespace webrtc {
namespace test {
namespace {
std::string TransformFilePath(std::string path) {
static const std::string resource_prefix = "res://";
int ext_pos = path.rfind('.');
if (ext_pos < 0) {
return test::ResourcePath(path, "yuv");
} else if (absl::StartsWith(path, resource_prefix)) {
std::string name = path.substr(resource_prefix.length(), ext_pos);
std::string ext = path.substr(ext_pos, path.size());
return test::ResourcePath(name, ext);
}
return path;
}
} // namespace
std::unique_ptr<FrameGeneratorCapturer> CreateFrameGeneratorCapturer(
Clock* clock,
TaskQueueFactory& task_queue_factory,
FrameGeneratorCapturerConfig::SquaresVideo config) {
return std::make_unique<FrameGeneratorCapturer>(
clock,
CreateSquareFrameGenerator(config.width, config.height,
config.pixel_format, config.num_squares),
config.framerate, task_queue_factory);
}
std::unique_ptr<FrameGeneratorCapturer> CreateFrameGeneratorCapturer(
Clock* clock,
TaskQueueFactory& task_queue_factory,
FrameGeneratorCapturerConfig::SquareSlides config) {
return std::make_unique<FrameGeneratorCapturer>(
clock,
CreateSlideFrameGenerator(
config.width, config.height,
/*frame_repeat_count*/ config.change_interval.seconds<double>() *
config.framerate),
config.framerate, task_queue_factory);
}
std::unique_ptr<FrameGeneratorCapturer> CreateFrameGeneratorCapturer(
Clock* clock,
TaskQueueFactory& task_queue_factory,
FrameGeneratorCapturerConfig::VideoFile config) {
RTC_CHECK(config.width && config.height);
return std::make_unique<FrameGeneratorCapturer>(
clock,
CreateFromYuvFileFrameGenerator({TransformFilePath(config.name)},
config.width, config.height,
/*frame_repeat_count*/ 1),
config.framerate, task_queue_factory);
}
std::unique_ptr<FrameGeneratorCapturer> CreateFrameGeneratorCapturer(
Clock* clock,
TaskQueueFactory& task_queue_factory,
FrameGeneratorCapturerConfig::ImageSlides config) {
std::unique_ptr<FrameGeneratorInterface> slides_generator;
std::vector<std::string> paths = config.paths;
for (std::string& path : paths)
path = TransformFilePath(path);
if (config.crop.width || config.crop.height) {
TimeDelta pause_duration =
config.change_interval - config.crop.scroll_duration;
RTC_CHECK_GE(pause_duration, TimeDelta::Zero());
int crop_width = config.crop.width.value_or(config.width);
int crop_height = config.crop.height.value_or(config.height);
RTC_CHECK_LE(crop_width, config.width);
RTC_CHECK_LE(crop_height, config.height);
slides_generator = CreateScrollingInputFromYuvFilesFrameGenerator(
clock, paths, config.width, config.height, crop_width, crop_height,
config.crop.scroll_duration.ms(), pause_duration.ms());
} else {
slides_generator = CreateFromYuvFileFrameGenerator(
paths, config.width, config.height,
/*frame_repeat_count*/ config.change_interval.seconds<double>() *
config.framerate);
}
return std::make_unique<FrameGeneratorCapturer>(
clock, std::move(slides_generator), config.framerate, task_queue_factory);
}
std::unique_ptr<FrameGeneratorCapturer> CreateFrameGeneratorCapturer(
Clock* clock,
TaskQueueFactory& task_queue_factory,
const FrameGeneratorCapturerConfig& config) {
if (config.video_file) {
return CreateFrameGeneratorCapturer(clock, task_queue_factory,
*config.video_file);
} else if (config.image_slides) {
return CreateFrameGeneratorCapturer(clock, task_queue_factory,
*config.image_slides);
} else if (config.squares_slides) {
return CreateFrameGeneratorCapturer(clock, task_queue_factory,
*config.squares_slides);
} else {
return CreateFrameGeneratorCapturer(
clock, task_queue_factory,
config.squares_video.value_or(
FrameGeneratorCapturerConfig::SquaresVideo()));
}
}
} // namespace test
} // namespace webrtc

View file

@ -24,40 +24,92 @@
namespace webrtc {
namespace test {
std::unique_ptr<FrameGeneratorCapturer> CreateFrameGeneratorCapturer(
Clock* clock,
TaskQueueFactory& task_queue_factory,
FrameGeneratorCapturerConfig::SquaresVideo config) {
return FrameGeneratorCapturer::Create(clock, task_queue_factory, config);
}
namespace frame_gen_cap_impl {
template <typename T>
class AutoOpt : public absl::optional<T> {
public:
using absl::optional<T>::optional;
T* operator->() {
if (!absl::optional<T>::has_value())
this->emplace(T());
return absl::optional<T>::operator->();
}
};
} // namespace frame_gen_cap_impl
struct FrameGeneratorCapturerConfig {
struct SquaresVideo {
int framerate = 30;
FrameGeneratorInterface::OutputType pixel_format =
FrameGeneratorInterface::OutputType::kI420;
int width = 320;
int height = 180;
int num_squares = 10;
};
struct SquareSlides {
int framerate = 30;
TimeDelta change_interval = TimeDelta::Seconds(10);
int width = 1600;
int height = 1200;
};
struct VideoFile {
int framerate = 30;
std::string name;
// Must be set to width and height of the source video file.
int width = 0;
int height = 0;
};
struct ImageSlides {
int framerate = 30;
TimeDelta change_interval = TimeDelta::Seconds(10);
struct Crop {
TimeDelta scroll_duration = TimeDelta::Seconds(0);
absl::optional<int> width;
absl::optional<int> height;
} crop;
int width = 1850;
int height = 1110;
std::vector<std::string> paths = {
"web_screenshot_1850_1110",
"presentation_1850_1110",
"photo_1850_1110",
"difficult_photo_1850_1110",
};
};
frame_gen_cap_impl::AutoOpt<SquaresVideo> squares_video;
frame_gen_cap_impl::AutoOpt<SquareSlides> squares_slides;
frame_gen_cap_impl::AutoOpt<VideoFile> video_file;
frame_gen_cap_impl::AutoOpt<ImageSlides> image_slides;
};
std::unique_ptr<FrameGeneratorCapturer> CreateFrameGeneratorCapturer(
Clock* clock,
TaskQueueFactory& task_queue_factory,
FrameGeneratorCapturerConfig::SquareSlides config) {
return FrameGeneratorCapturer::Create(clock, task_queue_factory, config);
}
FrameGeneratorCapturerConfig::SquaresVideo config);
std::unique_ptr<FrameGeneratorCapturer> CreateFrameGeneratorCapturer(
Clock* clock,
TaskQueueFactory& task_queue_factory,
FrameGeneratorCapturerConfig::VideoFile config) {
return FrameGeneratorCapturer::Create(clock, task_queue_factory, config);
}
FrameGeneratorCapturerConfig::SquareSlides config);
std::unique_ptr<FrameGeneratorCapturer> CreateFrameGeneratorCapturer(
Clock* clock,
TaskQueueFactory& task_queue_factory,
FrameGeneratorCapturerConfig::ImageSlides config) {
return FrameGeneratorCapturer::Create(clock, task_queue_factory, config);
}
FrameGeneratorCapturerConfig::VideoFile config);
std::unique_ptr<FrameGeneratorCapturer> CreateFrameGeneratorCapturer(
Clock* clock,
TaskQueueFactory& task_queue_factory,
const FrameGeneratorCapturerConfig& config) {
return FrameGeneratorCapturer::Create(clock, task_queue_factory, config);
}
FrameGeneratorCapturerConfig::ImageSlides config);
std::unique_ptr<FrameGeneratorCapturer> CreateFrameGeneratorCapturer(
Clock* clock,
TaskQueueFactory& task_queue_factory,
const FrameGeneratorCapturerConfig& config);
} // namespace test
} // namespace webrtc

View file

@ -17,33 +17,15 @@
#include <utility>
#include <vector>
#include "absl/strings/match.h"
#include "api/test/create_frame_generator.h"
#include "rtc_base/checks.h"
#include "rtc_base/logging.h"
#include "rtc_base/task_queue.h"
#include "rtc_base/time_utils.h"
#include "system_wrappers/include/clock.h"
#include "test/testsupport/file_utils.h"
namespace webrtc {
namespace test {
namespace {
std::string TransformFilePath(std::string path) {
static const std::string resource_prefix = "res://";
int ext_pos = path.rfind('.');
if (ext_pos < 0) {
return test::ResourcePath(path, "yuv");
} else if (absl::StartsWith(path, resource_prefix)) {
std::string name = path.substr(resource_prefix.length(), ext_pos);
std::string ext = path.substr(ext_pos, path.size());
return test::ResourcePath(name, ext);
}
return path;
}
} // namespace
FrameGeneratorCapturer::FrameGeneratorCapturer(
Clock* clock,
@ -68,88 +50,6 @@ FrameGeneratorCapturer::~FrameGeneratorCapturer() {
Stop();
}
std::unique_ptr<FrameGeneratorCapturer> FrameGeneratorCapturer::Create(
Clock* clock,
TaskQueueFactory& task_queue_factory,
FrameGeneratorCapturerConfig::SquaresVideo config) {
return std::make_unique<FrameGeneratorCapturer>(
clock,
CreateSquareFrameGenerator(config.width, config.height,
config.pixel_format, config.num_squares),
config.framerate, task_queue_factory);
}
std::unique_ptr<FrameGeneratorCapturer> FrameGeneratorCapturer::Create(
Clock* clock,
TaskQueueFactory& task_queue_factory,
FrameGeneratorCapturerConfig::SquareSlides config) {
return std::make_unique<FrameGeneratorCapturer>(
clock,
CreateSlideFrameGenerator(
config.width, config.height,
/*frame_repeat_count*/ config.change_interval.seconds<double>() *
config.framerate),
config.framerate, task_queue_factory);
}
std::unique_ptr<FrameGeneratorCapturer> FrameGeneratorCapturer::Create(
Clock* clock,
TaskQueueFactory& task_queue_factory,
FrameGeneratorCapturerConfig::VideoFile config) {
RTC_CHECK(config.width && config.height);
return std::make_unique<FrameGeneratorCapturer>(
clock,
CreateFromYuvFileFrameGenerator({TransformFilePath(config.name)},
config.width, config.height,
/*frame_repeat_count*/ 1),
config.framerate, task_queue_factory);
}
std::unique_ptr<FrameGeneratorCapturer> FrameGeneratorCapturer::Create(
Clock* clock,
TaskQueueFactory& task_queue_factory,
FrameGeneratorCapturerConfig::ImageSlides config) {
std::unique_ptr<FrameGeneratorInterface> slides_generator;
std::vector<std::string> paths = config.paths;
for (std::string& path : paths)
path = TransformFilePath(path);
if (config.crop.width || config.crop.height) {
TimeDelta pause_duration =
config.change_interval - config.crop.scroll_duration;
RTC_CHECK_GE(pause_duration, TimeDelta::Zero());
int crop_width = config.crop.width.value_or(config.width);
int crop_height = config.crop.height.value_or(config.height);
RTC_CHECK_LE(crop_width, config.width);
RTC_CHECK_LE(crop_height, config.height);
slides_generator = CreateScrollingInputFromYuvFilesFrameGenerator(
clock, paths, config.width, config.height, crop_width, crop_height,
config.crop.scroll_duration.ms(), pause_duration.ms());
} else {
slides_generator = CreateFromYuvFileFrameGenerator(
paths, config.width, config.height,
/*frame_repeat_count*/ config.change_interval.seconds<double>() *
config.framerate);
}
return std::make_unique<FrameGeneratorCapturer>(
clock, std::move(slides_generator), config.framerate, task_queue_factory);
}
std::unique_ptr<FrameGeneratorCapturer> FrameGeneratorCapturer::Create(
Clock* clock,
TaskQueueFactory& task_queue_factory,
const FrameGeneratorCapturerConfig& config) {
if (config.video_file) {
return Create(clock, task_queue_factory, *config.video_file);
} else if (config.image_slides) {
return Create(clock, task_queue_factory, *config.image_slides);
} else if (config.squares_slides) {
return Create(clock, task_queue_factory, *config.squares_slides);
} else {
return Create(clock, task_queue_factory,
config.squares_video.value_or(
FrameGeneratorCapturerConfig::SquaresVideo()));
}
}
void FrameGeneratorCapturer::SetFakeRotation(VideoRotation rotation) {
MutexLock lock(&lock_);
fake_rotation_ = rotation;

View file

@ -23,68 +23,7 @@
#include "test/test_video_capturer.h"
namespace webrtc {
namespace test {
namespace frame_gen_cap_impl {
template <typename T>
class AutoOpt : public absl::optional<T> {
public:
using absl::optional<T>::optional;
T* operator->() {
if (!absl::optional<T>::has_value())
this->emplace(T());
return absl::optional<T>::operator->();
}
};
} // namespace frame_gen_cap_impl
struct FrameGeneratorCapturerConfig {
struct SquaresVideo {
int framerate = 30;
FrameGeneratorInterface::OutputType pixel_format =
FrameGeneratorInterface::OutputType::kI420;
int width = 320;
int height = 180;
int num_squares = 10;
};
struct SquareSlides {
int framerate = 30;
TimeDelta change_interval = TimeDelta::Seconds(10);
int width = 1600;
int height = 1200;
};
struct VideoFile {
int framerate = 30;
std::string name;
// Must be set to width and height of the source video file.
int width = 0;
int height = 0;
};
struct ImageSlides {
int framerate = 30;
TimeDelta change_interval = TimeDelta::Seconds(10);
struct Crop {
TimeDelta scroll_duration = TimeDelta::Seconds(0);
absl::optional<int> width;
absl::optional<int> height;
} crop;
int width = 1850;
int height = 1110;
std::vector<std::string> paths = {
"web_screenshot_1850_1110",
"presentation_1850_1110",
"photo_1850_1110",
"difficult_photo_1850_1110",
};
};
frame_gen_cap_impl::AutoOpt<SquaresVideo> squares_video;
frame_gen_cap_impl::AutoOpt<SquareSlides> squares_slides;
frame_gen_cap_impl::AutoOpt<VideoFile> video_file;
frame_gen_cap_impl::AutoOpt<ImageSlides> image_slides;
};
class FrameGeneratorCapturer : public TestVideoCapturer {
public:
@ -106,27 +45,6 @@ class FrameGeneratorCapturer : public TestVideoCapturer {
TaskQueueFactory& task_queue_factory);
virtual ~FrameGeneratorCapturer();
static std::unique_ptr<FrameGeneratorCapturer> Create(
Clock* clock,
TaskQueueFactory& task_queue_factory,
FrameGeneratorCapturerConfig::SquaresVideo config);
static std::unique_ptr<FrameGeneratorCapturer> Create(
Clock* clock,
TaskQueueFactory& task_queue_factory,
FrameGeneratorCapturerConfig::SquareSlides config);
static std::unique_ptr<FrameGeneratorCapturer> Create(
Clock* clock,
TaskQueueFactory& task_queue_factory,
FrameGeneratorCapturerConfig::VideoFile config);
static std::unique_ptr<FrameGeneratorCapturer> Create(
Clock* clock,
TaskQueueFactory& task_queue_factory,
FrameGeneratorCapturerConfig::ImageSlides config);
static std::unique_ptr<FrameGeneratorCapturer> Create(
Clock* clock,
TaskQueueFactory& task_queue_factory,
const FrameGeneratorCapturerConfig& config);
void Start();
void Stop();
void ChangeResolution(size_t width, size_t height);

View file

@ -9,6 +9,8 @@
*/
#include "test/frame_generator_capturer.h"
#include "test/create_frame_generator_capturer.h"
#include "test/gmock.h"
#include "test/gtest.h"
#include "test/time_controller/simulated_time_controller.h"
@ -36,7 +38,7 @@ TEST(FrameGeneratorCapturerTest, CreateFromConfig) {
config.squares_video->width = 300;
config.squares_video->height = 200;
config.squares_video->framerate = 20;
auto capturer = FrameGeneratorCapturer::Create(
auto capturer = CreateFrameGeneratorCapturer(
time.GetClock(), *time.GetTaskQueueFactory(), config);
testing::StrictMock<MockVideoSinkInterfaceVideoFrame> mock_sink;
capturer->AddOrUpdateSink(&mock_sink, rtc::VideoSinkWants());
@ -52,7 +54,7 @@ TEST(FrameGeneratorCapturerTest, OnOutputFormatRequest) {
config.squares_video->width = kWidth;
config.squares_video->height = kHeight;
config.squares_video->framerate = 20;
auto capturer = FrameGeneratorCapturer::Create(
auto capturer = CreateFrameGeneratorCapturer(
time.GetClock(), *time.GetTaskQueueFactory(), config);
testing::StrictMock<MockVideoSinkInterfaceVideoFrame> mock_sink;
capturer->AddOrUpdateSink(&mock_sink, rtc::VideoSinkWants());
@ -69,7 +71,7 @@ TEST(FrameGeneratorCapturerTest, ChangeResolution) {
config.squares_video->width = kWidth;
config.squares_video->height = kHeight;
config.squares_video->framerate = 20;
auto capturer = FrameGeneratorCapturer::Create(
auto capturer = CreateFrameGeneratorCapturer(
time.GetClock(), *time.GetTaskQueueFactory(), config);
EXPECT_TRUE(capturer->GetResolution());
EXPECT_EQ(kWidth, capturer->GetResolution()->width);

View file

@ -22,6 +22,7 @@
#include "api/test/network_emulation_manager.h"
#include "api/test/time_controller.h"
#include "pc/test/frame_generator_capturer_video_track_source.h"
#include "test/create_frame_generator_capturer.h"
#include "test/logging/log_writer.h"
namespace webrtc {