Home | History | Annotate | Download | only in devices
      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 
     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 
     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 
     70 DeviceManager::~DeviceManager() {
     71   if (initialized()) {
     72     Terminate();
     73   }
     74 }
     75 
     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 
     86 void DeviceManager::Terminate() {
     87   if (initialized()) {
     88     watcher()->Stop();
     89     set_initialized(false);
     90   }
     91 }
     92 
     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 
    108 bool DeviceManager::GetAudioInputDevices(std::vector<Device>* devices) {
    109   return GetAudioDevices(true, devices);
    110 }
    111 
    112 bool DeviceManager::GetAudioOutputDevices(std::vector<Device>* devices) {
    113   return GetAudioDevices(false, devices);
    114 }
    115 
    116 bool DeviceManager::GetAudioInputDevice(const std::string& name, Device* out) {
    117   return GetAudioDevice(true, name, out);
    118 }
    119 
    120 bool DeviceManager::GetAudioOutputDevice(const std::string& name, Device* out) {
    121   return GetAudioDevice(false, name, out);
    122 }
    123 
    124 bool DeviceManager::GetVideoCaptureDevices(std::vector<Device>* devices) {
    125   devices->clear();
    126 #if defined(ANDROID) || defined(WEBRTC_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 
    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 
    166 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 
    181 void DeviceManager::SetVideoCaptureDeviceMaxFormat(
    182     const std::string& usb_id,
    183     const VideoFormat& max_format) {
    184   max_formats_[usb_id] = max_format;
    185 }
    186 
    187 void DeviceManager::ClearVideoCaptureDeviceMaxFormat(
    188     const std::string& usb_id) {
    189   max_formats_.erase(usb_id);
    190 }
    191 
    192 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 
    216 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(FileVideoCapturer::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 
    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 
    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 
    255 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 
    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 
    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 
    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 
    314 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 
    326 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 
    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 
    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