Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / third_party / libjingle / source / talk / media / devices / devicemanager.cc
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/base/fileutils.h"
31 #include "talk/base/logging.h"
32 #include "talk/base/pathutils.h"
33 #include "talk/base/stringutils.h"
34 #include "talk/base/thread.h"
35 #include "talk/base/windowpicker.h"
36 #include "talk/base/windowpickerfactory.h"
37 #include "talk/media/base/mediacommon.h"
38 #include "talk/media/devices/deviceinfo.h"
39 #include "talk/media/devices/filevideocapturer.h"
40 #include "talk/media/devices/yuvframescapturer.h"
41
42 #if !defined(IOS)
43
44 #if defined(HAVE_WEBRTC_VIDEO)
45 #include "talk/media/webrtc/webrtcvideocapturer.h"
46 #endif
47
48
49 #if defined(HAVE_WEBRTC_VIDEO)
50 #define VIDEO_CAPTURER_NAME WebRtcVideoCapturer
51 #endif
52
53
54 #endif
55
56 namespace {
57
58 bool StringMatchWithWildcard(
59     const std::pair<const std::basic_string<char>, cricket::VideoFormat> key,
60     const std::string& val) {
61   return talk_base::string_match(val.c_str(), key.first.c_str());
62 }
63
64 }  // namespace
65
66 namespace cricket {
67
68 // Initialize to empty string.
69 const char DeviceManagerInterface::kDefaultDeviceName[] = "";
70
71 class DefaultVideoCapturerFactory : public VideoCapturerFactory {
72  public:
73   DefaultVideoCapturerFactory() {}
74   virtual ~DefaultVideoCapturerFactory() {}
75
76   VideoCapturer* Create(const Device& device) {
77 #if defined(VIDEO_CAPTURER_NAME)
78     VIDEO_CAPTURER_NAME* return_value = new VIDEO_CAPTURER_NAME;
79     if (!return_value->Init(device)) {
80       delete return_value;
81       return NULL;
82     }
83     return return_value;
84 #else
85     return NULL;
86 #endif
87   }
88 };
89
90 DeviceManager::DeviceManager()
91     : initialized_(false),
92       device_video_capturer_factory_(new DefaultVideoCapturerFactory),
93       window_picker_(talk_base::WindowPickerFactory::CreateWindowPicker()) {
94 }
95
96 DeviceManager::~DeviceManager() {
97   if (initialized()) {
98     Terminate();
99   }
100 }
101
102 bool DeviceManager::Init() {
103   if (!initialized()) {
104     if (!watcher()->Start()) {
105       return false;
106     }
107     set_initialized(true);
108   }
109   return true;
110 }
111
112 void DeviceManager::Terminate() {
113   if (initialized()) {
114     watcher()->Stop();
115     set_initialized(false);
116   }
117 }
118
119 int DeviceManager::GetCapabilities() {
120   std::vector<Device> devices;
121   int caps = VIDEO_RECV;
122   if (GetAudioInputDevices(&devices) && !devices.empty()) {
123     caps |= AUDIO_SEND;
124   }
125   if (GetAudioOutputDevices(&devices) && !devices.empty()) {
126     caps |= AUDIO_RECV;
127   }
128   if (GetVideoCaptureDevices(&devices) && !devices.empty()) {
129     caps |= VIDEO_SEND;
130   }
131   return caps;
132 }
133
134 bool DeviceManager::GetAudioInputDevices(std::vector<Device>* devices) {
135   return GetAudioDevices(true, devices);
136 }
137
138 bool DeviceManager::GetAudioOutputDevices(std::vector<Device>* devices) {
139   return GetAudioDevices(false, devices);
140 }
141
142 bool DeviceManager::GetAudioInputDevice(const std::string& name, Device* out) {
143   return GetAudioDevice(true, name, out);
144 }
145
146 bool DeviceManager::GetAudioOutputDevice(const std::string& name, Device* out) {
147   return GetAudioDevice(false, name, out);
148 }
149
150 bool DeviceManager::GetVideoCaptureDevices(std::vector<Device>* devices) {
151   devices->clear();
152 #if defined(ANDROID) || defined(IOS)
153   // On Android and iOS, we treat the camera(s) as a single device. Even if
154   // there are multiple cameras, that's abstracted away at a higher level.
155   Device dev("camera", "1");    // name and ID
156   devices->push_back(dev);
157   return true;
158 #else
159   return false;
160 #endif
161 }
162
163 bool DeviceManager::GetVideoCaptureDevice(const std::string& name,
164                                           Device* out) {
165   // If the name is empty, return the default device.
166   if (name.empty() || name == kDefaultDeviceName) {
167     return GetDefaultVideoCaptureDevice(out);
168   }
169
170   std::vector<Device> devices;
171   if (!GetVideoCaptureDevices(&devices)) {
172     return false;
173   }
174
175   for (std::vector<Device>::const_iterator it = devices.begin();
176       it != devices.end(); ++it) {
177     if (name == it->name) {
178       *out = *it;
179       return true;
180     }
181   }
182
183   // If |name| is a valid name for a file or yuvframedevice,
184   // return a fake video capturer device.
185   if (GetFakeVideoCaptureDevice(name, out)) {
186     return true;
187   }
188
189   return false;
190 }
191
192 bool DeviceManager::GetFakeVideoCaptureDevice(const std::string& name,
193                                               Device* out) const {
194   if (talk_base::Filesystem::IsFile(name)) {
195     *out = FileVideoCapturer::CreateFileVideoCapturerDevice(name);
196     return true;
197   }
198
199   if (name == YuvFramesCapturer::kYuvFrameDeviceName) {
200     *out = YuvFramesCapturer::CreateYuvFramesCapturerDevice();
201     return true;
202   }
203
204   return false;
205 }
206
207 void DeviceManager::SetVideoCaptureDeviceMaxFormat(
208     const std::string& usb_id,
209     const VideoFormat& max_format) {
210   max_formats_[usb_id] = max_format;
211 }
212
213 void DeviceManager::ClearVideoCaptureDeviceMaxFormat(
214     const std::string& usb_id) {
215   max_formats_.erase(usb_id);
216 }
217
218 VideoCapturer* DeviceManager::CreateVideoCapturer(const Device& device) const {
219 #if defined(IOS)
220   LOG_F(LS_ERROR) << " should never be called!";
221   return NULL;
222 #else
223   VideoCapturer* capturer = ConstructFakeVideoCapturer(device);
224   if (capturer) {
225     return capturer;
226   }
227
228   capturer = device_video_capturer_factory_->Create(device);
229   if (!capturer) {
230     return NULL;
231   }
232   LOG(LS_INFO) << "Created VideoCapturer for " << device.name;
233   VideoFormat video_format;
234   bool has_max = GetMaxFormat(device, &video_format);
235   capturer->set_enable_camera_list(has_max);
236   if (has_max) {
237     capturer->ConstrainSupportedFormats(video_format);
238   }
239   return capturer;
240 #endif
241 }
242
243 VideoCapturer* DeviceManager::ConstructFakeVideoCapturer(
244     const Device& device) const {
245   // TODO(hellner): Throw out the creation of a file video capturer once the
246   // refactoring is completed.
247   if (FileVideoCapturer::IsFileVideoCapturerDevice(device)) {
248     FileVideoCapturer* capturer = new FileVideoCapturer;
249     if (!capturer->Init(device)) {
250       delete capturer;
251       return NULL;
252     }
253     LOG(LS_INFO) << "Created file video capturer " << device.name;
254     capturer->set_repeat(talk_base::kForever);
255     return capturer;
256   }
257
258   if (YuvFramesCapturer::IsYuvFramesCapturerDevice(device)) {
259     YuvFramesCapturer* capturer = new YuvFramesCapturer();
260     capturer->Init();
261     return capturer;
262   }
263   return NULL;
264 }
265
266 bool DeviceManager::GetWindows(
267     std::vector<talk_base::WindowDescription>* descriptions) {
268   if (!window_picker_) {
269     return false;
270   }
271   return window_picker_->GetWindowList(descriptions);
272 }
273
274 VideoCapturer* DeviceManager::CreateWindowCapturer(talk_base::WindowId window) {
275 #if defined(WINDOW_CAPTURER_NAME)
276   WINDOW_CAPTURER_NAME* window_capturer = new WINDOW_CAPTURER_NAME();
277   if (!window_capturer->Init(window)) {
278     delete window_capturer;
279     return NULL;
280   }
281   return window_capturer;
282 #else
283   return NULL;
284 #endif
285 }
286
287 bool DeviceManager::GetDesktops(
288     std::vector<talk_base::DesktopDescription>* descriptions) {
289   if (!window_picker_) {
290     return false;
291   }
292   return window_picker_->GetDesktopList(descriptions);
293 }
294
295 VideoCapturer* DeviceManager::CreateDesktopCapturer(
296     talk_base::DesktopId desktop) {
297 #if defined(DESKTOP_CAPTURER_NAME)
298   DESKTOP_CAPTURER_NAME* desktop_capturer = new DESKTOP_CAPTURER_NAME();
299   if (!desktop_capturer->Init(desktop.index())) {
300     delete desktop_capturer;
301     return NULL;
302   }
303   return desktop_capturer;
304 #else
305   return NULL;
306 #endif
307 }
308
309 bool DeviceManager::GetAudioDevices(bool input,
310                                     std::vector<Device>* devs) {
311   devs->clear();
312 #if defined(ANDROID)
313   // Under Android, 0 is always required for the playout device and 0 is the
314   // default for the recording device.
315   devs->push_back(Device("default-device", 0));
316   return true;
317 #else
318   // Other platforms either have their own derived class implementation
319   // (desktop) or don't use device manager for audio devices (iOS).
320   return false;
321 #endif
322 }
323
324 bool DeviceManager::GetAudioDevice(bool is_input, const std::string& name,
325                                    Device* out) {
326   // If the name is empty, return the default device id.
327   if (name.empty() || name == kDefaultDeviceName) {
328     *out = Device(name, -1);
329     return true;
330   }
331
332   std::vector<Device> devices;
333   bool ret = is_input ? GetAudioInputDevices(&devices) :
334                         GetAudioOutputDevices(&devices);
335   if (ret) {
336     ret = false;
337     for (size_t i = 0; i < devices.size(); ++i) {
338       if (devices[i].name == name) {
339         *out = devices[i];
340         ret = true;
341         break;
342       }
343     }
344   }
345   return ret;
346 }
347
348 bool DeviceManager::GetDefaultVideoCaptureDevice(Device* device) {
349   bool ret = false;
350   // We just return the first device.
351   std::vector<Device> devices;
352   ret = (GetVideoCaptureDevices(&devices) && !devices.empty());
353   if (ret) {
354     *device = devices[0];
355   }
356   return ret;
357 }
358
359 bool DeviceManager::IsInWhitelist(const std::string& key,
360                                   VideoFormat* video_format) const {
361   std::map<std::string, VideoFormat>::const_iterator found =
362       std::search_n(max_formats_.begin(), max_formats_.end(), 1, key,
363                     StringMatchWithWildcard);
364   if (found == max_formats_.end()) {
365     return false;
366   }
367   *video_format = found->second;
368   return true;
369 }
370
371 bool DeviceManager::GetMaxFormat(const Device& device,
372                                  VideoFormat* video_format) const {
373   // Match USB ID if available. Failing that, match device name.
374   std::string usb_id;
375   if (GetUsbId(device, &usb_id) && IsInWhitelist(usb_id, video_format)) {
376       return true;
377   }
378   return IsInWhitelist(device.name, video_format);
379 }
380
381 bool DeviceManager::ShouldDeviceBeIgnored(const std::string& device_name,
382     const char* const exclusion_list[]) {
383   // If exclusion_list is empty return directly.
384   if (!exclusion_list)
385     return false;
386
387   int i = 0;
388   while (exclusion_list[i]) {
389     if (strnicmp(device_name.c_str(), exclusion_list[i],
390         strlen(exclusion_list[i])) == 0) {
391       LOG(LS_INFO) << "Ignoring device " << device_name;
392       return true;
393     }
394     ++i;
395   }
396   return false;
397 }
398
399 bool DeviceManager::FilterDevices(std::vector<Device>* devices,
400     const char* const exclusion_list[]) {
401   if (!devices) {
402     return false;
403   }
404
405   for (std::vector<Device>::iterator it = devices->begin();
406        it != devices->end(); ) {
407     if (ShouldDeviceBeIgnored(it->name, exclusion_list)) {
408       it = devices->erase(it);
409     } else {
410       ++it;
411     }
412   }
413   return true;
414 }
415
416 }  // namespace cricket