• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * libjingle
3  * Copyright 2004 Google Inc.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *
8  *  1. Redistributions of source code must retain the above copyright notice,
9  *     this list of conditions and the following disclaimer.
10  *  2. Redistributions in binary form must reproduce the above copyright notice,
11  *     this list of conditions and the following disclaimer in the documentation
12  *     and/or other materials provided with the distribution.
13  *  3. The name of the author may not be used to endorse or promote products
14  *     derived from this software without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
19  * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27 
28 #include "talk/media/devices/devicemanager.h"
29 
30 #include "talk/media/base/mediacommon.h"
31 #include "talk/media/base/videocapturerfactory.h"
32 #include "talk/media/devices/deviceinfo.h"
33 #include "talk/media/devices/filevideocapturer.h"
34 #include "talk/media/devices/yuvframescapturer.h"
35 #include "webrtc/base/fileutils.h"
36 #include "webrtc/base/logging.h"
37 #include "webrtc/base/pathutils.h"
38 #include "webrtc/base/stringutils.h"
39 #include "webrtc/base/thread.h"
40 #include "webrtc/base/windowpicker.h"
41 #include "webrtc/base/windowpickerfactory.h"
42 
43 #ifdef HAVE_WEBRTC_VIDEO
44 #include "talk/media/webrtc/webrtcvideocapturerfactory.h"
45 #endif  // HAVE_WEBRTC_VIDEO
46 
47 namespace {
48 
StringMatchWithWildcard(const std::pair<const std::basic_string<char>,cricket::VideoFormat> key,const std::string & val)49 bool StringMatchWithWildcard(
50     const std::pair<const std::basic_string<char>, cricket::VideoFormat> key,
51     const std::string& val) {
52   return rtc::string_match(val.c_str(), key.first.c_str());
53 }
54 
55 }  // namespace
56 
57 namespace cricket {
58 
59 // Initialize to empty string.
60 const char DeviceManagerInterface::kDefaultDeviceName[] = "";
61 
DeviceManager()62 DeviceManager::DeviceManager()
63     : initialized_(false),
64       window_picker_(rtc::WindowPickerFactory::CreateWindowPicker()) {
65 #ifdef HAVE_WEBRTC_VIDEO
66   SetVideoDeviceCapturerFactory(new WebRtcVideoDeviceCapturerFactory());
67 #endif  // HAVE_WEBRTC_VIDEO
68 }
69 
~DeviceManager()70 DeviceManager::~DeviceManager() {
71   if (initialized()) {
72     Terminate();
73   }
74 }
75 
Init()76 bool DeviceManager::Init() {
77   if (!initialized()) {
78     if (!watcher()->Start()) {
79       return false;
80     }
81     set_initialized(true);
82   }
83   return true;
84 }
85 
Terminate()86 void DeviceManager::Terminate() {
87   if (initialized()) {
88     watcher()->Stop();
89     set_initialized(false);
90   }
91 }
92 
GetCapabilities()93 int DeviceManager::GetCapabilities() {
94   std::vector<Device> devices;
95   int caps = VIDEO_RECV;
96   if (GetAudioInputDevices(&devices) && !devices.empty()) {
97     caps |= AUDIO_SEND;
98   }
99   if (GetAudioOutputDevices(&devices) && !devices.empty()) {
100     caps |= AUDIO_RECV;
101   }
102   if (GetVideoCaptureDevices(&devices) && !devices.empty()) {
103     caps |= VIDEO_SEND;
104   }
105   return caps;
106 }
107 
GetAudioInputDevices(std::vector<Device> * devices)108 bool DeviceManager::GetAudioInputDevices(std::vector<Device>* devices) {
109   return GetAudioDevices(true, devices);
110 }
111 
GetAudioOutputDevices(std::vector<Device> * devices)112 bool DeviceManager::GetAudioOutputDevices(std::vector<Device>* devices) {
113   return GetAudioDevices(false, devices);
114 }
115 
GetAudioInputDevice(const std::string & name,Device * out)116 bool DeviceManager::GetAudioInputDevice(const std::string& name, Device* out) {
117   return GetAudioDevice(true, name, out);
118 }
119 
GetAudioOutputDevice(const std::string & name,Device * out)120 bool DeviceManager::GetAudioOutputDevice(const std::string& name, Device* out) {
121   return GetAudioDevice(false, name, out);
122 }
123 
GetVideoCaptureDevices(std::vector<Device> * devices)124 bool DeviceManager::GetVideoCaptureDevices(std::vector<Device>* devices) {
125   devices->clear();
126 #if defined(ANDROID) || defined(IOS)
127   // On Android and iOS, we treat the camera(s) as a single device. Even if
128   // there are multiple cameras, that's abstracted away at a higher level.
129   Device dev("camera", "1");    // name and ID
130   devices->push_back(dev);
131   return true;
132 #else
133   return false;
134 #endif
135 }
136 
GetVideoCaptureDevice(const std::string & name,Device * out)137 bool DeviceManager::GetVideoCaptureDevice(const std::string& name,
138                                           Device* out) {
139   // If the name is empty, return the default device.
140   if (name.empty() || name == kDefaultDeviceName) {
141     return GetDefaultVideoCaptureDevice(out);
142   }
143 
144   std::vector<Device> devices;
145   if (!GetVideoCaptureDevices(&devices)) {
146     return false;
147   }
148 
149   for (std::vector<Device>::const_iterator it = devices.begin();
150       it != devices.end(); ++it) {
151     if (name == it->name) {
152       *out = *it;
153       return true;
154     }
155   }
156 
157   // If |name| is a valid name for a file or yuvframedevice,
158   // return a fake video capturer device.
159   if (GetFakeVideoCaptureDevice(name, out)) {
160     return true;
161   }
162 
163   return false;
164 }
165 
GetFakeVideoCaptureDevice(const std::string & name,Device * out) const166 bool DeviceManager::GetFakeVideoCaptureDevice(const std::string& name,
167                                               Device* out) const {
168   if (rtc::Filesystem::IsFile(name)) {
169     *out = FileVideoCapturer::CreateFileVideoCapturerDevice(name);
170     return true;
171   }
172 
173   if (name == YuvFramesCapturer::kYuvFrameDeviceName) {
174     *out = YuvFramesCapturer::CreateYuvFramesCapturerDevice();
175     return true;
176   }
177 
178   return false;
179 }
180 
SetVideoCaptureDeviceMaxFormat(const std::string & usb_id,const VideoFormat & max_format)181 void DeviceManager::SetVideoCaptureDeviceMaxFormat(
182     const std::string& usb_id,
183     const VideoFormat& max_format) {
184   max_formats_[usb_id] = max_format;
185 }
186 
ClearVideoCaptureDeviceMaxFormat(const std::string & usb_id)187 void DeviceManager::ClearVideoCaptureDeviceMaxFormat(
188     const std::string& usb_id) {
189   max_formats_.erase(usb_id);
190 }
191 
CreateVideoCapturer(const Device & device) const192 VideoCapturer* DeviceManager::CreateVideoCapturer(const Device& device) const {
193   VideoCapturer* capturer = MaybeConstructFakeVideoCapturer(device);
194   if (capturer) {
195     return capturer;
196   }
197 
198   if (!video_device_capturer_factory_) {
199     LOG(LS_ERROR) << "No video capturer factory for devices.";
200     return NULL;
201   }
202   capturer = video_device_capturer_factory_->Create(device);
203   if (!capturer) {
204     return NULL;
205   }
206   LOG(LS_INFO) << "Created VideoCapturer for " << device.name;
207   VideoFormat video_format;
208   bool has_max = GetMaxFormat(device, &video_format);
209   capturer->set_enable_camera_list(has_max);
210   if (has_max) {
211     capturer->ConstrainSupportedFormats(video_format);
212   }
213   return capturer;
214 }
215 
MaybeConstructFakeVideoCapturer(const Device & device) const216 VideoCapturer* DeviceManager::MaybeConstructFakeVideoCapturer(
217     const Device& device) const {
218   // TODO(hellner): Throw out the creation of a file video capturer once the
219   // refactoring is completed.
220   if (FileVideoCapturer::IsFileVideoCapturerDevice(device)) {
221     FileVideoCapturer* capturer = new FileVideoCapturer;
222     if (!capturer->Init(device)) {
223       delete capturer;
224       return NULL;
225     }
226     LOG(LS_INFO) << "Created file video capturer " << device.name;
227     capturer->set_repeat(rtc::kForever);
228     return capturer;
229   }
230 
231   if (YuvFramesCapturer::IsYuvFramesCapturerDevice(device)) {
232     YuvFramesCapturer* capturer = new YuvFramesCapturer();
233     capturer->Init();
234     return capturer;
235   }
236   return NULL;
237 }
238 
GetWindows(std::vector<rtc::WindowDescription> * descriptions)239 bool DeviceManager::GetWindows(
240     std::vector<rtc::WindowDescription>* descriptions) {
241   if (!window_picker_) {
242     return false;
243   }
244   return window_picker_->GetWindowList(descriptions);
245 }
246 
GetDesktops(std::vector<rtc::DesktopDescription> * descriptions)247 bool DeviceManager::GetDesktops(
248     std::vector<rtc::DesktopDescription>* descriptions) {
249   if (!window_picker_) {
250     return false;
251   }
252   return window_picker_->GetDesktopList(descriptions);
253 }
254 
CreateScreenCapturer(const ScreencastId & screenid) const255 VideoCapturer* DeviceManager::CreateScreenCapturer(
256     const ScreencastId& screenid) const {
257   if (!screen_capturer_factory_) {
258     LOG(LS_ERROR) << "No video capturer factory for screens.";
259     return NULL;
260   }
261   return screen_capturer_factory_->Create(screenid);
262 }
263 
GetAudioDevices(bool input,std::vector<Device> * devs)264 bool DeviceManager::GetAudioDevices(bool input,
265                                     std::vector<Device>* devs) {
266   devs->clear();
267 #if defined(ANDROID)
268   // Under Android, 0 is always required for the playout device and 0 is the
269   // default for the recording device.
270   devs->push_back(Device("default-device", 0));
271   return true;
272 #else
273   // Other platforms either have their own derived class implementation
274   // (desktop) or don't use device manager for audio devices (iOS).
275   return false;
276 #endif
277 }
278 
GetAudioDevice(bool is_input,const std::string & name,Device * out)279 bool DeviceManager::GetAudioDevice(bool is_input, const std::string& name,
280                                    Device* out) {
281   // If the name is empty, return the default device id.
282   if (name.empty() || name == kDefaultDeviceName) {
283     *out = Device(name, -1);
284     return true;
285   }
286 
287   std::vector<Device> devices;
288   bool ret = is_input ? GetAudioInputDevices(&devices) :
289                         GetAudioOutputDevices(&devices);
290   if (ret) {
291     ret = false;
292     for (size_t i = 0; i < devices.size(); ++i) {
293       if (devices[i].name == name) {
294         *out = devices[i];
295         ret = true;
296         break;
297       }
298     }
299   }
300   return ret;
301 }
302 
GetDefaultVideoCaptureDevice(Device * device)303 bool DeviceManager::GetDefaultVideoCaptureDevice(Device* device) {
304   bool ret = false;
305   // We just return the first device.
306   std::vector<Device> devices;
307   ret = (GetVideoCaptureDevices(&devices) && !devices.empty());
308   if (ret) {
309     *device = devices[0];
310   }
311   return ret;
312 }
313 
IsInWhitelist(const std::string & key,VideoFormat * video_format) const314 bool DeviceManager::IsInWhitelist(const std::string& key,
315                                   VideoFormat* video_format) const {
316   std::map<std::string, VideoFormat>::const_iterator found =
317       std::search_n(max_formats_.begin(), max_formats_.end(), 1, key,
318                     StringMatchWithWildcard);
319   if (found == max_formats_.end()) {
320     return false;
321   }
322   *video_format = found->second;
323   return true;
324 }
325 
GetMaxFormat(const Device & device,VideoFormat * video_format) const326 bool DeviceManager::GetMaxFormat(const Device& device,
327                                  VideoFormat* video_format) const {
328   // Match USB ID if available. Failing that, match device name.
329   std::string usb_id;
330   if (GetUsbId(device, &usb_id) && IsInWhitelist(usb_id, video_format)) {
331       return true;
332   }
333   return IsInWhitelist(device.name, video_format);
334 }
335 
ShouldDeviceBeIgnored(const std::string & device_name,const char * const exclusion_list[])336 bool DeviceManager::ShouldDeviceBeIgnored(const std::string& device_name,
337     const char* const exclusion_list[]) {
338   // If exclusion_list is empty return directly.
339   if (!exclusion_list)
340     return false;
341 
342   int i = 0;
343   while (exclusion_list[i]) {
344     if (strnicmp(device_name.c_str(), exclusion_list[i],
345         strlen(exclusion_list[i])) == 0) {
346       LOG(LS_INFO) << "Ignoring device " << device_name;
347       return true;
348     }
349     ++i;
350   }
351   return false;
352 }
353 
FilterDevices(std::vector<Device> * devices,const char * const exclusion_list[])354 bool DeviceManager::FilterDevices(std::vector<Device>* devices,
355     const char* const exclusion_list[]) {
356   if (!devices) {
357     return false;
358   }
359 
360   for (std::vector<Device>::iterator it = devices->begin();
361        it != devices->end(); ) {
362     if (ShouldDeviceBeIgnored(it->name, exclusion_list)) {
363       it = devices->erase(it);
364     } else {
365       ++it;
366     }
367   }
368   return true;
369 }
370 
371 }  // namespace cricket
372