Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(402)

Unified Diff: media/capture/video/fake_video_capture_device_factory.cc

Issue 2715513008: Make FakeVideoCaptureDeviceFactory configurable to arbitrary fake device configurations (Closed)
Patch Set: emircan@ suggestions Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: media/capture/video/fake_video_capture_device_factory.cc
diff --git a/media/capture/video/fake_video_capture_device_factory.cc b/media/capture/video/fake_video_capture_device_factory.cc
index cbe2fa9912c8b9ab9a1cc619708ba6f68a8d3b18..cba70d49f8226e0cf76abd9b60ff2976e228fc22 100644
--- a/media/capture/video/fake_video_capture_device_factory.cc
+++ b/media/capture/video/fake_video_capture_device_factory.cc
@@ -4,16 +4,16 @@
#include "media/capture/video/fake_video_capture_device_factory.h"
-#include "base/command_line.h"
+#include <array>
+#include <vector>
+
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_split.h"
#include "base/strings/string_tokenizer.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
-#include "build/build_config.h"
#include "media/base/media_switches.h"
-namespace media {
namespace {
static const size_t kDepthDeviceIndex = 1;
@@ -21,53 +21,166 @@ static const size_t kDepthDeviceIndex = 1;
// Cap the frame rate command line input to reasonable values.
static const float kFakeCaptureMinFrameRate = 5.0f;
static const float kFakeCaptureMaxFrameRate = 60.0f;
-// Default rate if none is specified as part of the command line.
-static const float kFakeCaptureDefaultFrameRate = 20.0f;
+
// Cap the device count command line input to reasonable values.
-static const int kFakeCaptureMinDeviceCount = 1;
+static const int kFakeCaptureMinDeviceCount = 0;
static const int kFakeCaptureMaxDeviceCount = 10;
+static const int kDefaultDeviceCount = 1;
+
+static const char* kDefaultDeviceIdMask = "/dev/video%d";
+static const media::FakeVideoCaptureDevice::DeliveryMode kDefaultDeliveryMode =
+ media::FakeVideoCaptureDevice::DeliveryMode::USE_DEVICE_INTERNAL_BUFFERS;
+static constexpr std::array<gfx::Size, 5> kDefaultResolutions{
+ {gfx::Size(96, 96), gfx::Size(320, 240), gfx::Size(640, 480),
+ gfx::Size(1280, 720), gfx::Size(1920, 1080)}};
+static constexpr std::array<float, 1> kDefaultFrameRates{{20.0f}};
-FakeVideoCaptureDeviceMaker::PixelFormat GetPixelFormatFromDeviceId(
- const std::string& device_id) {
- if (device_id == "/dev/video1")
- return FakeVideoCaptureDeviceMaker::PixelFormat::Y16;
- if (device_id == "/dev/video2")
- return FakeVideoCaptureDeviceMaker::PixelFormat::MJPEG;
- return FakeVideoCaptureDeviceMaker::PixelFormat::I420;
+static const double kInitialZoom = 100.0;
+
+static const media::VideoPixelFormat kSupportedPixelFormats[] = {
+ media::PIXEL_FORMAT_I420, media::PIXEL_FORMAT_Y16,
+ media::PIXEL_FORMAT_MJPEG};
+
+template <typename TElement, size_t TSize>
+std::vector<TElement> ArrayToVector(const std::array<TElement, TSize>& arr) {
+ return std::vector<TElement>(arr.begin(), arr.end());
}
+media::VideoPixelFormat GetPixelFormatFromDeviceIndex(int device_index) {
+ if (device_index == 1)
+ return media::PIXEL_FORMAT_Y16;
+ if (device_index == 2)
+ return media::PIXEL_FORMAT_MJPEG;
+ return media::PIXEL_FORMAT_I420;
+}
+
+void AppendAllCombinationsToFormatsContainer(
+ const std::vector<media::VideoPixelFormat>& pixel_formats,
+ const std::vector<gfx::Size>& resolutions,
+ const std::vector<float>& frame_rates,
+ media::VideoCaptureFormats* output) {
+ for (const auto& pixel_format : pixel_formats) {
+ for (const auto& resolution : resolutions) {
+ for (const auto& frame_rate : frame_rates)
+ output->emplace_back(resolution, frame_rate, pixel_format);
+ }
+ }
+}
+
+class ErrorFakeDevice : public media::VideoCaptureDevice {
+ public:
+ // VideoCaptureDevice implementation.
+ void AllocateAndStart(const media::VideoCaptureParams& params,
+ std::unique_ptr<Client> client) override {
+ client->OnError(FROM_HERE, "Device has no supported formats.");
+ }
+
+ void StopAndDeAllocate() override {}
+ void GetPhotoCapabilities(GetPhotoCapabilitiesCallback callback) override {}
+ void SetPhotoOptions(media::mojom::PhotoSettingsPtr settings,
+ SetPhotoOptionsCallback callback) override {}
+ void TakePhoto(TakePhotoCallback callback) override {}
+};
+
} // anonymous namespace
-FakeVideoCaptureDeviceFactory::FakeVideoCaptureDeviceFactory()
- : number_of_devices_(1),
- delivery_mode_(FakeVideoCaptureDeviceMaker::DeliveryMode::
- USE_DEVICE_INTERNAL_BUFFERS),
- frame_rate_(kFakeCaptureDefaultFrameRate) {}
+namespace media {
+
+FakeVideoCaptureDeviceSettings::FakeVideoCaptureDeviceSettings() = default;
+
+FakeVideoCaptureDeviceSettings::~FakeVideoCaptureDeviceSettings() = default;
+
+FakeVideoCaptureDeviceSettings::FakeVideoCaptureDeviceSettings(
+ const FakeVideoCaptureDeviceSettings& other) = default;
+
+FakeVideoCaptureDeviceFactory::FakeVideoCaptureDeviceFactory() {
+ // The default |devices_config_| is the one obtained from an empty options
+ // string.
+ ParseFakeDevicesConfigFromOptionsString("", &devices_config_);
+}
+
+FakeVideoCaptureDeviceFactory::~FakeVideoCaptureDeviceFactory() = default;
+
+// static
+std::unique_ptr<VideoCaptureDevice>
+FakeVideoCaptureDeviceFactory::CreateDeviceWithSupportedFormats(
+ FakeVideoCaptureDevice::DeliveryMode delivery_mode,
+ const VideoCaptureFormats& formats) {
+ if (formats.empty())
+ return CreateErrorDevice();
+
+ for (const auto& entry : formats) {
+ bool pixel_format_supported = false;
+ for (const auto& supported_pixel_format : kSupportedPixelFormats) {
+ if (entry.pixel_format == supported_pixel_format) {
+ pixel_format_supported = true;
+ break;
+ }
+ }
+ if (!pixel_format_supported) {
+ DLOG(ERROR) << "Requested an unsupported pixel format "
+ << VideoPixelFormatToString(entry.pixel_format);
+ return nullptr;
+ }
+ }
+
+ const VideoCaptureFormat& initial_format = formats.front();
+ auto device_state = base::MakeUnique<FakeDeviceState>(
+ kInitialZoom, initial_format.frame_rate, initial_format.pixel_format);
+
+ auto photo_frame_painter = base::MakeUnique<PacmanFramePainter>(
+ PacmanFramePainter::Format::SK_N32, device_state.get());
+ auto photo_device = base::MakeUnique<FakePhotoDevice>(
+ std::move(photo_frame_painter), device_state.get());
+
+ return base::MakeUnique<FakeVideoCaptureDevice>(
+ formats,
+ base::MakeUnique<FrameDelivererFactory>(delivery_mode,
+ device_state.get()),
+ std::move(photo_device), std::move(device_state));
+}
+
+// static
+std::unique_ptr<VideoCaptureDevice>
+FakeVideoCaptureDeviceFactory::CreateDeviceWithDefaultResolutions(
+ VideoPixelFormat pixel_format,
+ FakeVideoCaptureDevice::DeliveryMode delivery_mode,
+ float frame_rate) {
+ VideoCaptureFormats formats;
+ for (const gfx::Size& resolution : kDefaultResolutions)
+ formats.emplace_back(resolution, frame_rate, pixel_format);
+ return CreateDeviceWithSupportedFormats(delivery_mode, formats);
+}
+
+// static
+std::unique_ptr<VideoCaptureDevice>
+FakeVideoCaptureDeviceFactory::CreateErrorDevice() {
+ return base::MakeUnique<ErrorFakeDevice>();
+}
+
+void FakeVideoCaptureDeviceFactory::SetToDefaultDevicesConfig(
+ int device_count) {
+ devices_config_.clear();
+ ParseFakeDevicesConfigFromOptionsString(
+ base::StringPrintf("device-count=%d", device_count), &devices_config_);
+}
+
+void FakeVideoCaptureDeviceFactory::SetToCustomDevicesConfig(
+ const std::vector<FakeVideoCaptureDeviceSettings>& config) {
+ devices_config_ = config;
+}
std::unique_ptr<VideoCaptureDevice> FakeVideoCaptureDeviceFactory::CreateDevice(
const VideoCaptureDeviceDescriptor& device_descriptor) {
DCHECK(thread_checker_.CalledOnValidThread());
- ParseCommandLine();
-
- for (int n = 0; n < number_of_devices_; ++n) {
- std::string possible_id = base::StringPrintf("/dev/video%d", n);
- if (device_descriptor.device_id.compare(possible_id) == 0) {
- FakeVideoCaptureDeviceMaker::PixelFormat pixel_format =
- GetPixelFormatFromDeviceId(possible_id);
- FakeVideoCaptureDeviceMaker::DeliveryMode delivery_mode = delivery_mode_;
- if (delivery_mode == FakeVideoCaptureDeviceMaker::DeliveryMode::
- USE_CLIENT_PROVIDED_BUFFERS &&
- pixel_format == FakeVideoCaptureDeviceMaker::PixelFormat::MJPEG) {
- // Incompatible options. Fall back to using internal buffers.
- delivery_mode = FakeVideoCaptureDeviceMaker::DeliveryMode::
- USE_DEVICE_INTERNAL_BUFFERS;
- }
- return FakeVideoCaptureDeviceMaker::MakeInstance(
- pixel_format, delivery_mode, frame_rate_);
- }
+ for (const auto& entry : devices_config_) {
+ if (device_descriptor.device_id != entry.device_id)
+ continue;
+ return CreateDeviceWithSupportedFormats(entry.delivery_mode,
+ entry.supported_formats);
}
- return std::unique_ptr<VideoCaptureDevice>();
+ return nullptr;
}
void FakeVideoCaptureDeviceFactory::GetDeviceDescriptors(
@@ -75,24 +188,24 @@ void FakeVideoCaptureDeviceFactory::GetDeviceDescriptors(
DCHECK(thread_checker_.CalledOnValidThread());
DCHECK(device_descriptors->empty());
- ParseCommandLine();
-
- for (int n = 0; n < number_of_devices_; ++n) {
- device_descriptors->emplace_back(base::StringPrintf("fake_device_%d", n),
- base::StringPrintf("/dev/video%d", n),
+ int entry_index = 0;
+ for (const auto& entry : devices_config_) {
+ device_descriptors->emplace_back(
+ base::StringPrintf("fake_device_%d", entry_index), entry.device_id,
#if defined(OS_LINUX)
- VideoCaptureApi::LINUX_V4L2_SINGLE_PLANE
+ VideoCaptureApi::LINUX_V4L2_SINGLE_PLANE
#elif defined(OS_MACOSX)
- VideoCaptureApi::MACOSX_AVFOUNDATION
+ VideoCaptureApi::MACOSX_AVFOUNDATION
#elif defined(OS_WIN)
- VideoCaptureApi::WIN_DIRECT_SHOW
+ VideoCaptureApi::WIN_DIRECT_SHOW
#elif defined(OS_ANDROID)
- VideoCaptureApi::ANDROID_API2_LEGACY
+ VideoCaptureApi::ANDROID_API2_LEGACY
#endif
- );
+ );
+ entry_index++;
}
- // Video device on index 1 (kDepthDeviceIndex) is depth video capture device.
+ // Video device on index |kDepthDeviceIndex| is depth video capture device.
// Fill the camera calibration information only for it.
if (device_descriptors->size() <= kDepthDeviceIndex)
return;
@@ -110,65 +223,74 @@ void FakeVideoCaptureDeviceFactory::GetSupportedFormats(
VideoCaptureFormats* supported_formats) {
DCHECK(thread_checker_.CalledOnValidThread());
- ParseCommandLine();
-
- const VideoPixelFormat pixel_format = static_cast<VideoPixelFormat>(
- GetPixelFormatFromDeviceId(device_descriptor.device_id));
- const VideoPixelStorage pixel_storage = PIXEL_STORAGE_CPU;
- std::vector<gfx::Size> supported_sizes;
- FakeVideoCaptureDeviceMaker::GetSupportedSizes(&supported_sizes);
- for (const auto& supported_size : supported_sizes) {
- supported_formats->emplace_back(supported_size, frame_rate_, pixel_format,
- pixel_storage);
+ for (const auto& entry : devices_config_) {
+ if (device_descriptor.device_id != entry.device_id)
+ continue;
+ supported_formats->insert(supported_formats->end(),
+ entry.supported_formats.begin(),
+ entry.supported_formats.end());
}
}
-// Optional comma delimited parameters to the command line can specify buffer
-// ownership, device count, and the fake video devices FPS.
-// Examples: "ownership=client, device-count=2, fps=60" "fps=30"
-void FakeVideoCaptureDeviceFactory::ParseCommandLine() {
- if (command_line_parsed_)
- return;
- command_line_parsed_ = true;
-
- const std::string option =
- base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
- switches::kUseFakeDeviceForMediaStream);
- base::StringTokenizer option_tokenizer(option, ", ");
+// static
+void FakeVideoCaptureDeviceFactory::ParseFakeDevicesConfigFromOptionsString(
+ const std::string options_string,
+ std::vector<FakeVideoCaptureDeviceSettings>* config) {
+ base::StringTokenizer option_tokenizer(options_string, ", ");
option_tokenizer.set_quote_chars("\"");
+ FakeVideoCaptureDevice::DeliveryMode delivery_mode = kDefaultDeliveryMode;
+ std::vector<gfx::Size> resolutions = ArrayToVector(kDefaultResolutions);
+ std::vector<float> frame_rates = ArrayToVector(kDefaultFrameRates);
+ int device_count = kDefaultDeviceCount;
+
while (option_tokenizer.GetNext()) {
std::vector<std::string> param =
base::SplitString(option_tokenizer.token(), "=", base::TRIM_WHITESPACE,
base::SPLIT_WANT_NONEMPTY);
if (param.size() != 2u) {
- LOG(WARNING) << "Forget a value '" << option << "'? Use name=value for "
+ LOG(WARNING) << "Forget a value '" << options_string
+ << "'? Use name=value for "
<< switches::kUseFakeDeviceForMediaStream << ".";
return;
}
if (base::EqualsCaseInsensitiveASCII(param.front(), "ownership") &&
base::EqualsCaseInsensitiveASCII(param.back(), "client")) {
- delivery_mode_ = FakeVideoCaptureDeviceMaker::DeliveryMode::
- USE_CLIENT_PROVIDED_BUFFERS;
+ delivery_mode =
+ FakeVideoCaptureDevice::DeliveryMode::USE_CLIENT_PROVIDED_BUFFERS;
} else if (base::EqualsCaseInsensitiveASCII(param.front(), "fps")) {
- double fps = 0;
- if (base::StringToDouble(param.back(), &fps)) {
- frame_rate_ =
- std::max(kFakeCaptureMinFrameRate, static_cast<float>(fps));
- frame_rate_ = std::min(kFakeCaptureMaxFrameRate, frame_rate_);
+ double parsed_fps = 0;
+ if (base::StringToDouble(param.back(), &parsed_fps)) {
+ float capped_frame_rate =
+ std::max(kFakeCaptureMinFrameRate, static_cast<float>(parsed_fps));
+ capped_frame_rate =
+ std::min(kFakeCaptureMaxFrameRate, capped_frame_rate);
+ frame_rates.clear();
+ frame_rates.push_back(capped_frame_rate);
}
} else if (base::EqualsCaseInsensitiveASCII(param.front(),
"device-count")) {
unsigned int count = 0;
if (base::StringToUint(param.back(), &count)) {
- number_of_devices_ = std::min(
+ device_count = std::min(
kFakeCaptureMaxDeviceCount,
std::max(kFakeCaptureMinDeviceCount, static_cast<int>(count)));
}
}
}
+
+ for (int device_index = 0; device_index < device_count; device_index++) {
+ std::vector<VideoPixelFormat> pixel_formats;
+ pixel_formats.push_back(GetPixelFormatFromDeviceIndex(device_index));
+ FakeVideoCaptureDeviceSettings settings;
+ settings.delivery_mode = delivery_mode;
+ settings.device_id = base::StringPrintf(kDefaultDeviceIdMask, device_index);
+ AppendAllCombinationsToFormatsContainer(
+ pixel_formats, resolutions, frame_rates, &settings.supported_formats);
+ config->push_back(settings);
+ }
}
} // namespace media

Powered by Google App Engine
This is Rietveld 408576698