OLD | NEW |
---|---|
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 == | |
60 FakeVideoCaptureDeviceMaker::DeliveryMode:: | |
61 USE_CLIENT_PROVIDED_BUFFERS && | |
62 pixel_format == FakeVideoCaptureDeviceMaker::PixelFormat::MJPEG) { | |
63 // Incompatible options. Fall back to using internal buffers. | |
64 delivery_mode = FakeVideoCaptureDeviceMaker::DeliveryMode:: | |
65 USE_DEVICE_INTERNAL_BUFFERS; | |
66 } | |
67 return FakeVideoCaptureDeviceMaker::MakeInstance( | |
68 pixel_format, delivery_mode, frame_rate_); | |
69 } | |
70 } | 182 } |
71 return std::unique_ptr<VideoCaptureDevice>(); | 183 return nullptr; |
72 } | 184 } |
73 | 185 |
74 void FakeVideoCaptureDeviceFactory::GetDeviceDescriptors( | 186 void FakeVideoCaptureDeviceFactory::GetDeviceDescriptors( |
75 VideoCaptureDeviceDescriptors* device_descriptors) { | 187 VideoCaptureDeviceDescriptors* device_descriptors) { |
76 DCHECK(thread_checker_.CalledOnValidThread()); | 188 DCHECK(thread_checker_.CalledOnValidThread()); |
77 DCHECK(device_descriptors->empty()); | 189 DCHECK(device_descriptors->empty()); |
78 | 190 |
79 ParseCommandLine(); | 191 int entry_index = 0; |
80 | 192 for (const auto& entry : devices_config_) { |
81 for (int n = 0; n < number_of_devices_; ++n) { | 193 device_descriptors->emplace_back( |
82 device_descriptors->emplace_back(base::StringPrintf("fake_device_%d", n), | 194 base::StringPrintf("fake_device_%d", entry_index), entry.device_id, |
83 base::StringPrintf("/dev/video%d", n), | |
84 #if defined(OS_LINUX) | 195 #if defined(OS_LINUX) |
85 VideoCaptureApi::LINUX_V4L2_SINGLE_PLANE | 196 VideoCaptureApi::LINUX_V4L2_SINGLE_PLANE |
86 #elif defined(OS_MACOSX) | 197 #elif defined(OS_MACOSX) |
87 VideoCaptureApi::MACOSX_AVFOUNDATION | 198 VideoCaptureApi::MACOSX_AVFOUNDATION |
88 #elif defined(OS_WIN) | 199 #elif defined(OS_WIN) |
89 VideoCaptureApi::WIN_DIRECT_SHOW | 200 VideoCaptureApi::WIN_DIRECT_SHOW |
90 #elif defined(OS_ANDROID) | 201 #elif defined(OS_ANDROID) |
91 VideoCaptureApi::ANDROID_API2_LEGACY | 202 VideoCaptureApi::ANDROID_API2_LEGACY |
92 #endif | 203 #endif |
93 ); | 204 ); |
205 entry_index++; | |
94 } | 206 } |
95 | 207 |
96 // Video device on index 1 (kDepthDeviceIndex) is depth video capture device. | 208 // Video device on index |kDepthDeviceIndex| is depth video capture device. |
97 // Fill the camera calibration information only for it. | 209 // Fill the camera calibration information only for it. |
98 if (device_descriptors->size() <= kDepthDeviceIndex) | 210 if (device_descriptors->size() <= kDepthDeviceIndex) |
99 return; | 211 return; |
100 VideoCaptureDeviceDescriptor& depth_device( | 212 VideoCaptureDeviceDescriptor& depth_device( |
101 (*device_descriptors)[kDepthDeviceIndex]); | 213 (*device_descriptors)[kDepthDeviceIndex]); |
102 depth_device.camera_calibration.emplace(); | 214 depth_device.camera_calibration.emplace(); |
103 depth_device.camera_calibration->focal_length_x = 135.0; | 215 depth_device.camera_calibration->focal_length_x = 135.0; |
104 depth_device.camera_calibration->focal_length_y = 135.6; | 216 depth_device.camera_calibration->focal_length_y = 135.6; |
105 depth_device.camera_calibration->depth_near = 0.0; | 217 depth_device.camera_calibration->depth_near = 0.0; |
106 depth_device.camera_calibration->depth_far = 65.535; | 218 depth_device.camera_calibration->depth_far = 65.535; |
107 } | 219 } |
108 | 220 |
109 void FakeVideoCaptureDeviceFactory::GetSupportedFormats( | 221 void FakeVideoCaptureDeviceFactory::GetSupportedFormats( |
110 const VideoCaptureDeviceDescriptor& device_descriptor, | 222 const VideoCaptureDeviceDescriptor& device_descriptor, |
111 VideoCaptureFormats* supported_formats) { | 223 VideoCaptureFormats* supported_formats) { |
112 DCHECK(thread_checker_.CalledOnValidThread()); | 224 DCHECK(thread_checker_.CalledOnValidThread()); |
113 | 225 |
114 ParseCommandLine(); | 226 for (const auto& entry : devices_config_) { |
115 | 227 if (device_descriptor.device_id != entry.device_id) |
116 const VideoPixelFormat pixel_format = static_cast<VideoPixelFormat>( | 228 continue; |
117 GetPixelFormatFromDeviceId(device_descriptor.device_id)); | 229 supported_formats->insert(supported_formats->end(), |
118 const VideoPixelStorage pixel_storage = PIXEL_STORAGE_CPU; | 230 entry.supported_formats.begin(), |
119 std::vector<gfx::Size> supported_sizes; | 231 entry.supported_formats.end()); |
120 FakeVideoCaptureDeviceMaker::GetSupportedSizes(&supported_sizes); | |
121 for (const auto& supported_size : supported_sizes) { | |
122 supported_formats->emplace_back(supported_size, frame_rate_, pixel_format, | |
123 pixel_storage); | |
124 } | 232 } |
125 } | 233 } |
126 | 234 |
127 // Optional comma delimited parameters to the command line can specify buffer | 235 // static |
128 // ownership, device count, and the fake video devices FPS. | 236 void FakeVideoCaptureDeviceFactory::ParseFakeDevicesConfigFromOptionsString( |
129 // Examples: "ownership=client, device-count=2, fps=60" "fps=30" | 237 const std::string options_string, |
130 void FakeVideoCaptureDeviceFactory::ParseCommandLine() { | 238 std::vector<FakeVideoCaptureDeviceSettings>* config) { |
131 if (command_line_parsed_) | 239 base::StringTokenizer option_tokenizer(options_string, ", "); |
132 return; | 240 option_tokenizer.set_quote_chars("\""); |
133 command_line_parsed_ = true; | |
134 | 241 |
135 const std::string option = | 242 FakeVideoCaptureDevice::DeliveryMode delivery_mode = kDefaultDeliveryMode; |
136 base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII( | 243 std::vector<gfx::Size> resolutions = ArrayToVector(kDefaultResolutions); |
emircan
2017/03/01 18:58:59
Is it necessary to copy them into vector? AFAICT Y
chfremer
2017/03/01 21:55:48
It is true that |resolutions| is currently never m
| |
137 switches::kUseFakeDeviceForMediaStream); | 244 std::vector<float> frame_rates = ArrayToVector(kDefaultFrameRates); |
138 base::StringTokenizer option_tokenizer(option, ", "); | 245 int device_count = kDefaultDeviceCount; |
139 option_tokenizer.set_quote_chars("\""); | |
140 | 246 |
141 while (option_tokenizer.GetNext()) { | 247 while (option_tokenizer.GetNext()) { |
142 std::vector<std::string> param = | 248 std::vector<std::string> param = |
143 base::SplitString(option_tokenizer.token(), "=", base::TRIM_WHITESPACE, | 249 base::SplitString(option_tokenizer.token(), "=", base::TRIM_WHITESPACE, |
144 base::SPLIT_WANT_NONEMPTY); | 250 base::SPLIT_WANT_NONEMPTY); |
145 | 251 |
146 if (param.size() != 2u) { | 252 if (param.size() != 2u) { |
147 LOG(WARNING) << "Forget a value '" << option << "'? Use name=value for " | 253 LOG(WARNING) << "Forget a value '" << options_string |
254 << "'? Use name=value for " | |
148 << switches::kUseFakeDeviceForMediaStream << "."; | 255 << switches::kUseFakeDeviceForMediaStream << "."; |
149 return; | 256 return; |
150 } | 257 } |
151 | 258 |
152 if (base::EqualsCaseInsensitiveASCII(param.front(), "ownership") && | 259 if (base::EqualsCaseInsensitiveASCII(param.front(), "ownership") && |
153 base::EqualsCaseInsensitiveASCII(param.back(), "client")) { | 260 base::EqualsCaseInsensitiveASCII(param.back(), "client")) { |
154 delivery_mode_ = FakeVideoCaptureDeviceMaker::DeliveryMode:: | 261 delivery_mode = |
155 USE_CLIENT_PROVIDED_BUFFERS; | 262 FakeVideoCaptureDevice::DeliveryMode::USE_CLIENT_PROVIDED_BUFFERS; |
156 } else if (base::EqualsCaseInsensitiveASCII(param.front(), "fps")) { | 263 } else if (base::EqualsCaseInsensitiveASCII(param.front(), "fps")) { |
157 double fps = 0; | 264 double parsed_fps = 0; |
158 if (base::StringToDouble(param.back(), &fps)) { | 265 if (base::StringToDouble(param.back(), &parsed_fps)) { |
159 frame_rate_ = | 266 float capped_frame_rate = |
160 std::max(kFakeCaptureMinFrameRate, static_cast<float>(fps)); | 267 std::max(kFakeCaptureMinFrameRate, static_cast<float>(parsed_fps)); |
161 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); | |
162 } | 272 } |
163 } else if (base::EqualsCaseInsensitiveASCII(param.front(), | 273 } else if (base::EqualsCaseInsensitiveASCII(param.front(), |
164 "device-count")) { | 274 "device-count")) { |
165 unsigned int count = 0; | 275 unsigned int count = 0; |
166 if (base::StringToUint(param.back(), &count)) { | 276 if (base::StringToUint(param.back(), &count)) { |
167 number_of_devices_ = std::min( | 277 device_count = std::min( |
168 kFakeCaptureMaxDeviceCount, | 278 kFakeCaptureMaxDeviceCount, |
169 std::max(kFakeCaptureMinDeviceCount, static_cast<int>(count))); | 279 std::max(kFakeCaptureMinDeviceCount, static_cast<int>(count))); |
170 } | 280 } |
171 } | 281 } |
172 } | 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 } | |
173 } | 294 } |
174 | 295 |
175 } // namespace media | 296 } // namespace media |
OLD | NEW |