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

Side by Side 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, 9 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 unified diff | Download patch
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "media/capture/video/fake_video_capture_device_factory.h" 5 #include "media/capture/video/fake_video_capture_device_factory.h"
6 6
7 #include "base/command_line.h" 7 #include <array>
8 #include <vector>
9
8 #include "base/strings/string_number_conversions.h" 10 #include "base/strings/string_number_conversions.h"
9 #include "base/strings/string_split.h" 11 #include "base/strings/string_split.h"
10 #include "base/strings/string_tokenizer.h" 12 #include "base/strings/string_tokenizer.h"
11 #include "base/strings/string_util.h" 13 #include "base/strings/string_util.h"
12 #include "base/strings/stringprintf.h" 14 #include "base/strings/stringprintf.h"
13 #include "build/build_config.h"
14 #include "media/base/media_switches.h" 15 #include "media/base/media_switches.h"
15 16
16 namespace media {
17 namespace { 17 namespace {
18 18
19 static const size_t kDepthDeviceIndex = 1; 19 static const size_t kDepthDeviceIndex = 1;
20 20
21 // Cap the frame rate command line input to reasonable values. 21 // Cap the frame rate command line input to reasonable values.
22 static const float kFakeCaptureMinFrameRate = 5.0f; 22 static const float kFakeCaptureMinFrameRate = 5.0f;
23 static const float kFakeCaptureMaxFrameRate = 60.0f; 23 static const float kFakeCaptureMaxFrameRate = 60.0f;
24 // Default rate if none is specified as part of the command line. 24
25 static const float kFakeCaptureDefaultFrameRate = 20.0f;
26 // Cap the device count command line input to reasonable values. 25 // Cap the device count command line input to reasonable values.
27 static const int kFakeCaptureMinDeviceCount = 1; 26 static const int kFakeCaptureMinDeviceCount = 0;
28 static const int kFakeCaptureMaxDeviceCount = 10; 27 static const int kFakeCaptureMaxDeviceCount = 10;
28 static const int kDefaultDeviceCount = 1;
29 29
30 FakeVideoCaptureDeviceMaker::PixelFormat GetPixelFormatFromDeviceId( 30 static const char* kDefaultDeviceIdMask = "/dev/video%d";
31 const std::string& device_id) { 31 static const media::FakeVideoCaptureDevice::DeliveryMode kDefaultDeliveryMode =
32 if (device_id == "/dev/video1") 32 media::FakeVideoCaptureDevice::DeliveryMode::USE_DEVICE_INTERNAL_BUFFERS;
33 return FakeVideoCaptureDeviceMaker::PixelFormat::Y16; 33 static constexpr std::array<gfx::Size, 5> kDefaultResolutions{
34 if (device_id == "/dev/video2") 34 {gfx::Size(96, 96), gfx::Size(320, 240), gfx::Size(640, 480),
35 return FakeVideoCaptureDeviceMaker::PixelFormat::MJPEG; 35 gfx::Size(1280, 720), gfx::Size(1920, 1080)}};
36 return FakeVideoCaptureDeviceMaker::PixelFormat::I420; 36 static constexpr std::array<float, 1> kDefaultFrameRates{{20.0f}};
37
38 static const double kInitialZoom = 100.0;
39
40 static const media::VideoPixelFormat kSupportedPixelFormats[] = {
41 media::PIXEL_FORMAT_I420, media::PIXEL_FORMAT_Y16,
42 media::PIXEL_FORMAT_MJPEG};
43
44 template <typename TElement, size_t TSize>
45 std::vector<TElement> ArrayToVector(const std::array<TElement, TSize>& arr) {
46 return std::vector<TElement>(arr.begin(), arr.end());
37 } 47 }
38 48
49 media::VideoPixelFormat GetPixelFormatFromDeviceIndex(int device_index) {
50 if (device_index == 1)
51 return media::PIXEL_FORMAT_Y16;
52 if (device_index == 2)
53 return media::PIXEL_FORMAT_MJPEG;
54 return media::PIXEL_FORMAT_I420;
55 }
56
57 void AppendAllCombinationsToFormatsContainer(
58 const std::vector<media::VideoPixelFormat>& pixel_formats,
59 const std::vector<gfx::Size>& resolutions,
60 const std::vector<float>& frame_rates,
61 media::VideoCaptureFormats* output) {
62 for (const auto& pixel_format : pixel_formats) {
63 for (const auto& resolution : resolutions) {
64 for (const auto& frame_rate : frame_rates)
65 output->emplace_back(resolution, frame_rate, pixel_format);
66 }
67 }
68 }
69
70 class ErrorFakeDevice : public media::VideoCaptureDevice {
71 public:
72 // VideoCaptureDevice implementation.
73 void AllocateAndStart(const media::VideoCaptureParams& params,
74 std::unique_ptr<Client> client) override {
75 client->OnError(FROM_HERE, "Device has no supported formats.");
76 }
77
78 void StopAndDeAllocate() override {}
79 void GetPhotoCapabilities(GetPhotoCapabilitiesCallback callback) override {}
80 void SetPhotoOptions(media::mojom::PhotoSettingsPtr settings,
81 SetPhotoOptionsCallback callback) override {}
82 void TakePhoto(TakePhotoCallback callback) override {}
83 };
84
39 } // anonymous namespace 85 } // anonymous namespace
40 86
41 FakeVideoCaptureDeviceFactory::FakeVideoCaptureDeviceFactory() 87 namespace media {
42 : number_of_devices_(1), 88
43 delivery_mode_(FakeVideoCaptureDeviceMaker::DeliveryMode:: 89 FakeVideoCaptureDeviceSettings::FakeVideoCaptureDeviceSettings() = default;
44 USE_DEVICE_INTERNAL_BUFFERS), 90
45 frame_rate_(kFakeCaptureDefaultFrameRate) {} 91 FakeVideoCaptureDeviceSettings::~FakeVideoCaptureDeviceSettings() = default;
92
93 FakeVideoCaptureDeviceSettings::FakeVideoCaptureDeviceSettings(
94 const FakeVideoCaptureDeviceSettings& other) = default;
95
96 FakeVideoCaptureDeviceFactory::FakeVideoCaptureDeviceFactory() {
97 // The default |devices_config_| is the one obtained from an empty options
98 // string.
99 ParseFakeDevicesConfigFromOptionsString("", &devices_config_);
100 }
101
102 FakeVideoCaptureDeviceFactory::~FakeVideoCaptureDeviceFactory() = default;
103
104 // static
105 std::unique_ptr<VideoCaptureDevice>
106 FakeVideoCaptureDeviceFactory::CreateDeviceWithSupportedFormats(
107 FakeVideoCaptureDevice::DeliveryMode delivery_mode,
108 const VideoCaptureFormats& formats) {
109 if (formats.empty())
110 return CreateErrorDevice();
111
112 for (const auto& entry : formats) {
113 bool pixel_format_supported = false;
114 for (const auto& supported_pixel_format : kSupportedPixelFormats) {
115 if (entry.pixel_format == supported_pixel_format) {
116 pixel_format_supported = true;
117 break;
118 }
119 }
120 if (!pixel_format_supported) {
121 DLOG(ERROR) << "Requested an unsupported pixel format "
122 << VideoPixelFormatToString(entry.pixel_format);
123 return nullptr;
124 }
125 }
126
127 const VideoCaptureFormat& initial_format = formats.front();
128 auto device_state = base::MakeUnique<FakeDeviceState>(
129 kInitialZoom, initial_format.frame_rate, initial_format.pixel_format);
130
131 auto photo_frame_painter = base::MakeUnique<PacmanFramePainter>(
132 PacmanFramePainter::Format::SK_N32, device_state.get());
133 auto photo_device = base::MakeUnique<FakePhotoDevice>(
134 std::move(photo_frame_painter), device_state.get());
135
136 return base::MakeUnique<FakeVideoCaptureDevice>(
137 formats,
138 base::MakeUnique<FrameDelivererFactory>(delivery_mode,
139 device_state.get()),
140 std::move(photo_device), std::move(device_state));
141 }
142
143 // static
144 std::unique_ptr<VideoCaptureDevice>
145 FakeVideoCaptureDeviceFactory::CreateDeviceWithDefaultResolutions(
146 VideoPixelFormat pixel_format,
147 FakeVideoCaptureDevice::DeliveryMode delivery_mode,
148 float frame_rate) {
149 VideoCaptureFormats formats;
150 for (const gfx::Size& resolution : kDefaultResolutions)
151 formats.emplace_back(resolution, frame_rate, pixel_format);
152 return CreateDeviceWithSupportedFormats(delivery_mode, formats);
153 }
154
155 // static
156 std::unique_ptr<VideoCaptureDevice>
157 FakeVideoCaptureDeviceFactory::CreateErrorDevice() {
158 return base::MakeUnique<ErrorFakeDevice>();
159 }
160
161 void FakeVideoCaptureDeviceFactory::SetToDefaultDevicesConfig(
162 int device_count) {
163 devices_config_.clear();
164 ParseFakeDevicesConfigFromOptionsString(
165 base::StringPrintf("device-count=%d", device_count), &devices_config_);
166 }
167
168 void FakeVideoCaptureDeviceFactory::SetToCustomDevicesConfig(
169 const std::vector<FakeVideoCaptureDeviceSettings>& config) {
170 devices_config_ = config;
171 }
46 172
47 std::unique_ptr<VideoCaptureDevice> FakeVideoCaptureDeviceFactory::CreateDevice( 173 std::unique_ptr<VideoCaptureDevice> FakeVideoCaptureDeviceFactory::CreateDevice(
48 const VideoCaptureDeviceDescriptor& device_descriptor) { 174 const VideoCaptureDeviceDescriptor& device_descriptor) {
49 DCHECK(thread_checker_.CalledOnValidThread()); 175 DCHECK(thread_checker_.CalledOnValidThread());
50 176
51 ParseCommandLine(); 177 for (const auto& entry : devices_config_) {
52 178 if (device_descriptor.device_id != entry.device_id)
53 for (int n = 0; n < number_of_devices_; ++n) { 179 continue;
54 std::string possible_id = base::StringPrintf("/dev/video%d", n); 180 return CreateDeviceWithSupportedFormats(entry.delivery_mode,
55 if (device_descriptor.device_id.compare(possible_id) == 0) { 181 entry.supported_formats);
56 FakeVideoCaptureDeviceMaker::PixelFormat pixel_format =
57 GetPixelFormatFromDeviceId(possible_id);
58 FakeVideoCaptureDeviceMaker::DeliveryMode delivery_mode = delivery_mode_;
59 if (delivery_mode == FakeVideoCaptureDeviceMaker::DeliveryMode::
60 USE_CLIENT_PROVIDED_BUFFERS &&
61 pixel_format == FakeVideoCaptureDeviceMaker::PixelFormat::MJPEG) {
62 // Incompatible options. Fall back to using internal buffers.
63 delivery_mode = FakeVideoCaptureDeviceMaker::DeliveryMode::
64 USE_DEVICE_INTERNAL_BUFFERS;
65 }
66 return FakeVideoCaptureDeviceMaker::MakeInstance(
67 pixel_format, delivery_mode, frame_rate_);
68 }
69 } 182 }
70 return std::unique_ptr<VideoCaptureDevice>(); 183 return nullptr;
71 } 184 }
72 185
73 void FakeVideoCaptureDeviceFactory::GetDeviceDescriptors( 186 void FakeVideoCaptureDeviceFactory::GetDeviceDescriptors(
74 VideoCaptureDeviceDescriptors* device_descriptors) { 187 VideoCaptureDeviceDescriptors* device_descriptors) {
75 DCHECK(thread_checker_.CalledOnValidThread()); 188 DCHECK(thread_checker_.CalledOnValidThread());
76 DCHECK(device_descriptors->empty()); 189 DCHECK(device_descriptors->empty());
77 190
78 ParseCommandLine(); 191 int entry_index = 0;
79 192 for (const auto& entry : devices_config_) {
80 for (int n = 0; n < number_of_devices_; ++n) { 193 device_descriptors->emplace_back(
81 device_descriptors->emplace_back(base::StringPrintf("fake_device_%d", n), 194 base::StringPrintf("fake_device_%d", entry_index), entry.device_id,
82 base::StringPrintf("/dev/video%d", n),
83 #if defined(OS_LINUX) 195 #if defined(OS_LINUX)
84 VideoCaptureApi::LINUX_V4L2_SINGLE_PLANE 196 VideoCaptureApi::LINUX_V4L2_SINGLE_PLANE
85 #elif defined(OS_MACOSX) 197 #elif defined(OS_MACOSX)
86 VideoCaptureApi::MACOSX_AVFOUNDATION 198 VideoCaptureApi::MACOSX_AVFOUNDATION
87 #elif defined(OS_WIN) 199 #elif defined(OS_WIN)
88 VideoCaptureApi::WIN_DIRECT_SHOW 200 VideoCaptureApi::WIN_DIRECT_SHOW
89 #elif defined(OS_ANDROID) 201 #elif defined(OS_ANDROID)
90 VideoCaptureApi::ANDROID_API2_LEGACY 202 VideoCaptureApi::ANDROID_API2_LEGACY
91 #endif 203 #endif
92 ); 204 );
205 entry_index++;
93 } 206 }
94 207
95 // Video device on index 1 (kDepthDeviceIndex) is depth video capture device. 208 // Video device on index |kDepthDeviceIndex| is depth video capture device.
96 // Fill the camera calibration information only for it. 209 // Fill the camera calibration information only for it.
97 if (device_descriptors->size() <= kDepthDeviceIndex) 210 if (device_descriptors->size() <= kDepthDeviceIndex)
98 return; 211 return;
99 VideoCaptureDeviceDescriptor& depth_device( 212 VideoCaptureDeviceDescriptor& depth_device(
100 (*device_descriptors)[kDepthDeviceIndex]); 213 (*device_descriptors)[kDepthDeviceIndex]);
101 depth_device.camera_calibration.emplace(); 214 depth_device.camera_calibration.emplace();
102 depth_device.camera_calibration->focal_length_x = 135.0; 215 depth_device.camera_calibration->focal_length_x = 135.0;
103 depth_device.camera_calibration->focal_length_y = 135.6; 216 depth_device.camera_calibration->focal_length_y = 135.6;
104 depth_device.camera_calibration->depth_near = 0.0; 217 depth_device.camera_calibration->depth_near = 0.0;
105 depth_device.camera_calibration->depth_far = 65.535; 218 depth_device.camera_calibration->depth_far = 65.535;
106 } 219 }
107 220
108 void FakeVideoCaptureDeviceFactory::GetSupportedFormats( 221 void FakeVideoCaptureDeviceFactory::GetSupportedFormats(
109 const VideoCaptureDeviceDescriptor& device_descriptor, 222 const VideoCaptureDeviceDescriptor& device_descriptor,
110 VideoCaptureFormats* supported_formats) { 223 VideoCaptureFormats* supported_formats) {
111 DCHECK(thread_checker_.CalledOnValidThread()); 224 DCHECK(thread_checker_.CalledOnValidThread());
112 225
113 ParseCommandLine(); 226 for (const auto& entry : devices_config_) {
114 227 if (device_descriptor.device_id != entry.device_id)
115 const VideoPixelFormat pixel_format = static_cast<VideoPixelFormat>( 228 continue;
116 GetPixelFormatFromDeviceId(device_descriptor.device_id)); 229 supported_formats->insert(supported_formats->end(),
117 const VideoPixelStorage pixel_storage = PIXEL_STORAGE_CPU; 230 entry.supported_formats.begin(),
118 std::vector<gfx::Size> supported_sizes; 231 entry.supported_formats.end());
119 FakeVideoCaptureDeviceMaker::GetSupportedSizes(&supported_sizes);
120 for (const auto& supported_size : supported_sizes) {
121 supported_formats->emplace_back(supported_size, frame_rate_, pixel_format,
122 pixel_storage);
123 } 232 }
124 } 233 }
125 234
126 // Optional comma delimited parameters to the command line can specify buffer 235 // static
127 // ownership, device count, and the fake video devices FPS. 236 void FakeVideoCaptureDeviceFactory::ParseFakeDevicesConfigFromOptionsString(
128 // Examples: "ownership=client, device-count=2, fps=60" "fps=30" 237 const std::string options_string,
129 void FakeVideoCaptureDeviceFactory::ParseCommandLine() { 238 std::vector<FakeVideoCaptureDeviceSettings>* config) {
130 if (command_line_parsed_) 239 base::StringTokenizer option_tokenizer(options_string, ", ");
131 return; 240 option_tokenizer.set_quote_chars("\"");
132 command_line_parsed_ = true;
133 241
134 const std::string option = 242 FakeVideoCaptureDevice::DeliveryMode delivery_mode = kDefaultDeliveryMode;
135 base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII( 243 std::vector<gfx::Size> resolutions = ArrayToVector(kDefaultResolutions);
136 switches::kUseFakeDeviceForMediaStream); 244 std::vector<float> frame_rates = ArrayToVector(kDefaultFrameRates);
137 base::StringTokenizer option_tokenizer(option, ", "); 245 int device_count = kDefaultDeviceCount;
138 option_tokenizer.set_quote_chars("\"");
139 246
140 while (option_tokenizer.GetNext()) { 247 while (option_tokenizer.GetNext()) {
141 std::vector<std::string> param = 248 std::vector<std::string> param =
142 base::SplitString(option_tokenizer.token(), "=", base::TRIM_WHITESPACE, 249 base::SplitString(option_tokenizer.token(), "=", base::TRIM_WHITESPACE,
143 base::SPLIT_WANT_NONEMPTY); 250 base::SPLIT_WANT_NONEMPTY);
144 251
145 if (param.size() != 2u) { 252 if (param.size() != 2u) {
146 LOG(WARNING) << "Forget a value '" << option << "'? Use name=value for " 253 LOG(WARNING) << "Forget a value '" << options_string
254 << "'? Use name=value for "
147 << switches::kUseFakeDeviceForMediaStream << "."; 255 << switches::kUseFakeDeviceForMediaStream << ".";
148 return; 256 return;
149 } 257 }
150 258
151 if (base::EqualsCaseInsensitiveASCII(param.front(), "ownership") && 259 if (base::EqualsCaseInsensitiveASCII(param.front(), "ownership") &&
152 base::EqualsCaseInsensitiveASCII(param.back(), "client")) { 260 base::EqualsCaseInsensitiveASCII(param.back(), "client")) {
153 delivery_mode_ = FakeVideoCaptureDeviceMaker::DeliveryMode:: 261 delivery_mode =
154 USE_CLIENT_PROVIDED_BUFFERS; 262 FakeVideoCaptureDevice::DeliveryMode::USE_CLIENT_PROVIDED_BUFFERS;
155 } else if (base::EqualsCaseInsensitiveASCII(param.front(), "fps")) { 263 } else if (base::EqualsCaseInsensitiveASCII(param.front(), "fps")) {
156 double fps = 0; 264 double parsed_fps = 0;
157 if (base::StringToDouble(param.back(), &fps)) { 265 if (base::StringToDouble(param.back(), &parsed_fps)) {
158 frame_rate_ = 266 float capped_frame_rate =
159 std::max(kFakeCaptureMinFrameRate, static_cast<float>(fps)); 267 std::max(kFakeCaptureMinFrameRate, static_cast<float>(parsed_fps));
160 frame_rate_ = std::min(kFakeCaptureMaxFrameRate, frame_rate_); 268 capped_frame_rate =
269 std::min(kFakeCaptureMaxFrameRate, capped_frame_rate);
270 frame_rates.clear();
271 frame_rates.push_back(capped_frame_rate);
161 } 272 }
162 } else if (base::EqualsCaseInsensitiveASCII(param.front(), 273 } else if (base::EqualsCaseInsensitiveASCII(param.front(),
163 "device-count")) { 274 "device-count")) {
164 unsigned int count = 0; 275 unsigned int count = 0;
165 if (base::StringToUint(param.back(), &count)) { 276 if (base::StringToUint(param.back(), &count)) {
166 number_of_devices_ = std::min( 277 device_count = std::min(
167 kFakeCaptureMaxDeviceCount, 278 kFakeCaptureMaxDeviceCount,
168 std::max(kFakeCaptureMinDeviceCount, static_cast<int>(count))); 279 std::max(kFakeCaptureMinDeviceCount, static_cast<int>(count)));
169 } 280 }
170 } 281 }
171 } 282 }
283
284 for (int device_index = 0; device_index < device_count; device_index++) {
285 std::vector<VideoPixelFormat> pixel_formats;
286 pixel_formats.push_back(GetPixelFormatFromDeviceIndex(device_index));
287 FakeVideoCaptureDeviceSettings settings;
288 settings.delivery_mode = delivery_mode;
289 settings.device_id = base::StringPrintf(kDefaultDeviceIdMask, device_index);
290 AppendAllCombinationsToFormatsContainer(
291 pixel_formats, resolutions, frame_rates, &settings.supported_formats);
292 config->push_back(settings);
293 }
172 } 294 }
173 295
174 } // namespace media 296 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698