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 == 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 |
OLD | NEW |