• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
3  *
4  *  Use of this source code is governed by a BSD-style license
5  *  that can be found in the LICENSE file in the root of the source
6  *  tree. An additional intellectual property rights grant can be found
7  *  in the file PATENTS.  All contributing project authors may
8  *  be found in the AUTHORS file in the root of the source tree.
9  */
10 
11 #include "webrtc/video_engine/vie_input_manager.h"
12 
13 #include <assert.h>
14 
15 #include "webrtc/common_types.h"
16 #include "webrtc/modules/video_capture/include/video_capture_factory.h"
17 #include "webrtc/modules/video_coding/main/interface/video_coding.h"
18 #include "webrtc/modules/video_coding/main/interface/video_coding_defines.h"
19 #include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
20 #include "webrtc/system_wrappers/interface/logging.h"
21 #include "webrtc/system_wrappers/interface/rw_lock_wrapper.h"
22 #include "webrtc/video_engine/include/vie_errors.h"
23 #include "webrtc/video_engine/vie_capturer.h"
24 #include "webrtc/video_engine/vie_defines.h"
25 
26 namespace webrtc {
27 
ViEInputManager(const int engine_id,const Config & config)28 ViEInputManager::ViEInputManager(const int engine_id, const Config& config)
29     : config_(config),
30       engine_id_(engine_id),
31       map_cs_(CriticalSectionWrapper::CreateCriticalSection()),
32       device_info_cs_(CriticalSectionWrapper::CreateCriticalSection()),
33       vie_frame_provider_map_(),
34       capture_device_info_(NULL),
35       module_process_thread_(NULL) {
36   for (int idx = 0; idx < kViEMaxCaptureDevices; idx++) {
37     free_capture_device_id_[idx] = true;
38   }
39 }
40 
~ViEInputManager()41 ViEInputManager::~ViEInputManager() {
42   for (FrameProviderMap::iterator it = vie_frame_provider_map_.begin();
43        it != vie_frame_provider_map_.end();
44        ++it) {
45     delete it->second;
46   }
47 
48   delete capture_device_info_;
49 }
SetModuleProcessThread(ProcessThread * module_process_thread)50 void ViEInputManager::SetModuleProcessThread(
51     ProcessThread* module_process_thread) {
52   assert(!module_process_thread_);
53   module_process_thread_ = module_process_thread;
54 }
55 
NumberOfCaptureDevices()56 int ViEInputManager::NumberOfCaptureDevices() {
57   CriticalSectionScoped cs(device_info_cs_.get());
58   if (capture_device_info_ == NULL)
59     capture_device_info_ = VideoCaptureFactory::CreateDeviceInfo(
60         ViEModuleId(engine_id_));
61   assert(capture_device_info_);
62   return capture_device_info_->NumberOfDevices();
63 }
64 
GetDeviceName(uint32_t device_number,char * device_nameUTF8,uint32_t device_name_length,char * device_unique_idUTF8,uint32_t device_unique_idUTF8Length)65 int ViEInputManager::GetDeviceName(uint32_t device_number,
66                                    char* device_nameUTF8,
67                                    uint32_t device_name_length,
68                                    char* device_unique_idUTF8,
69                                    uint32_t device_unique_idUTF8Length) {
70   CriticalSectionScoped cs(device_info_cs_.get());
71   if (capture_device_info_ == NULL)
72     capture_device_info_ = VideoCaptureFactory::CreateDeviceInfo(
73         ViEModuleId(engine_id_));
74   assert(capture_device_info_);
75   return capture_device_info_->GetDeviceName(device_number, device_nameUTF8,
76                                              device_name_length,
77                                              device_unique_idUTF8,
78                                              device_unique_idUTF8Length);
79 }
80 
NumberOfCaptureCapabilities(const char * device_unique_idUTF8)81 int ViEInputManager::NumberOfCaptureCapabilities(
82   const char* device_unique_idUTF8) {
83   CriticalSectionScoped cs(device_info_cs_.get());
84   if (capture_device_info_ == NULL)
85     capture_device_info_ = VideoCaptureFactory::CreateDeviceInfo(
86         ViEModuleId(engine_id_));
87   assert(capture_device_info_);
88   return capture_device_info_->NumberOfCapabilities(device_unique_idUTF8);
89 }
90 
GetCaptureCapability(const char * device_unique_idUTF8,const uint32_t device_capability_number,CaptureCapability & capability)91 int ViEInputManager::GetCaptureCapability(
92     const char* device_unique_idUTF8,
93     const uint32_t device_capability_number,
94     CaptureCapability& capability) {
95   CriticalSectionScoped cs(device_info_cs_.get());
96   if (capture_device_info_ == NULL)
97     capture_device_info_ = VideoCaptureFactory::CreateDeviceInfo(
98         ViEModuleId(engine_id_));
99   assert(capture_device_info_);
100   VideoCaptureCapability module_capability;
101   int result = capture_device_info_->GetCapability(device_unique_idUTF8,
102                                                    device_capability_number,
103                                                    module_capability);
104   if (result != 0)
105     return result;
106 
107   // Copy from module type to public type.
108   capability.expectedCaptureDelay = module_capability.expectedCaptureDelay;
109   capability.height = module_capability.height;
110   capability.width = module_capability.width;
111   capability.interlaced = module_capability.interlaced;
112   capability.rawType = module_capability.rawType;
113   capability.codecType = module_capability.codecType;
114   capability.maxFPS = module_capability.maxFPS;
115   return result;
116 }
117 
GetOrientation(const char * device_unique_idUTF8,RotateCapturedFrame & orientation)118 int ViEInputManager::GetOrientation(const char* device_unique_idUTF8,
119                                     RotateCapturedFrame& orientation) {
120   CriticalSectionScoped cs(device_info_cs_.get());
121   if (capture_device_info_ == NULL)
122     capture_device_info_ = VideoCaptureFactory::CreateDeviceInfo(
123         ViEModuleId(engine_id_));
124   assert(capture_device_info_);
125   VideoCaptureRotation module_orientation;
126   int result = capture_device_info_->GetOrientation(device_unique_idUTF8,
127                                                     module_orientation);
128   // Copy from module type to public type.
129   switch (module_orientation) {
130     case kCameraRotate0:
131       orientation = RotateCapturedFrame_0;
132       break;
133     case kCameraRotate90:
134       orientation = RotateCapturedFrame_90;
135       break;
136     case kCameraRotate180:
137       orientation = RotateCapturedFrame_180;
138       break;
139     case kCameraRotate270:
140       orientation = RotateCapturedFrame_270;
141       break;
142   }
143   return result;
144 }
145 
DisplayCaptureSettingsDialogBox(const char * device_unique_idUTF8,const char * dialog_titleUTF8,void * parent_window,uint32_t positionX,uint32_t positionY)146 int ViEInputManager::DisplayCaptureSettingsDialogBox(
147     const char* device_unique_idUTF8,
148     const char* dialog_titleUTF8,
149     void* parent_window,
150     uint32_t positionX,
151     uint32_t positionY) {
152   CriticalSectionScoped cs(device_info_cs_.get());
153   if (capture_device_info_ == NULL)
154     capture_device_info_ = VideoCaptureFactory::CreateDeviceInfo(
155         ViEModuleId(engine_id_));
156   assert(capture_device_info_);
157   return capture_device_info_->DisplayCaptureSettingsDialogBox(
158            device_unique_idUTF8, dialog_titleUTF8, parent_window, positionX,
159            positionY);
160 }
161 
CreateCaptureDevice(const char * device_unique_idUTF8,const uint32_t device_unique_idUTF8Length,int & capture_id)162 int ViEInputManager::CreateCaptureDevice(
163     const char* device_unique_idUTF8,
164     const uint32_t device_unique_idUTF8Length,
165     int& capture_id) {
166   CriticalSectionScoped cs(map_cs_.get());
167 
168   // Make sure the device is not already allocated.
169   for (FrameProviderMap::iterator it = vie_frame_provider_map_.begin();
170        it != vie_frame_provider_map_.end();
171        ++it) {
172     // Make sure this is a capture device.
173     if (it->first >= kViECaptureIdBase && it->first <= kViECaptureIdMax) {
174       ViECapturer* vie_capture = static_cast<ViECapturer*>(it->second);
175       assert(vie_capture);
176       // TODO(mflodman) Can we change input to avoid this cast?
177       const char* device_name =
178           reinterpret_cast<const char*>(vie_capture->CurrentDeviceName());
179       if (strncmp(device_name, device_unique_idUTF8,
180                   strlen(device_name)) == 0) {
181         return kViECaptureDeviceAlreadyAllocated;
182       }
183     }
184   }
185 
186   // Make sure the device name is valid.
187   bool found_device = false;
188   CriticalSectionScoped cs_devinfo(device_info_cs_.get());
189   if (capture_device_info_ == NULL)
190     capture_device_info_ = VideoCaptureFactory::CreateDeviceInfo(
191         ViEModuleId(engine_id_));
192   assert(capture_device_info_);
193   for (uint32_t device_index = 0;
194        device_index < capture_device_info_->NumberOfDevices(); ++device_index) {
195     if (device_unique_idUTF8Length > kVideoCaptureUniqueNameLength) {
196       // User's string length is longer than the max.
197       return -1;
198     }
199 
200     char found_name[kVideoCaptureDeviceNameLength] = "";
201     char found_unique_name[kVideoCaptureUniqueNameLength] = "";
202     capture_device_info_->GetDeviceName(device_index, found_name,
203                                         kVideoCaptureDeviceNameLength,
204                                         found_unique_name,
205                                         kVideoCaptureUniqueNameLength);
206 
207     // TODO(mflodman) Can we change input to avoid this cast?
208     const char* cast_id = reinterpret_cast<const char*>(device_unique_idUTF8);
209     if (strncmp(cast_id, reinterpret_cast<const char*>(found_unique_name),
210                 strlen(cast_id)) == 0) {
211       found_device = true;
212       break;
213     }
214   }
215   if (!found_device) {
216     LOG(LS_ERROR) << "Capture device not found: " << device_unique_idUTF8;
217     return kViECaptureDeviceDoesNotExist;
218   }
219 
220   int newcapture_id = 0;
221   if (!GetFreeCaptureId(&newcapture_id)) {
222     LOG(LS_ERROR) << "All capture devices already allocated.";
223     return kViECaptureDeviceMaxNoDevicesAllocated;
224   }
225   ViECapturer* vie_capture = ViECapturer::CreateViECapture(
226       newcapture_id, engine_id_, config_, device_unique_idUTF8,
227       device_unique_idUTF8Length, *module_process_thread_);
228   if (!vie_capture) {
229     ReturnCaptureId(newcapture_id);
230     return kViECaptureDeviceUnknownError;
231   }
232 
233   vie_frame_provider_map_[newcapture_id] = vie_capture;
234   capture_id = newcapture_id;
235   return 0;
236 }
237 
CreateCaptureDevice(VideoCaptureModule * capture_module,int & capture_id)238 int ViEInputManager::CreateCaptureDevice(VideoCaptureModule* capture_module,
239                                          int& capture_id) {
240   CriticalSectionScoped cs(map_cs_.get());
241   int newcapture_id = 0;
242   if (!GetFreeCaptureId(&newcapture_id)) {
243     LOG(LS_ERROR) << "All capture devices already allocated.";
244     return kViECaptureDeviceMaxNoDevicesAllocated;
245   }
246 
247   ViECapturer* vie_capture = ViECapturer::CreateViECapture(
248       newcapture_id, engine_id_, config_,
249       capture_module, *module_process_thread_);
250   if (!vie_capture) {
251     ReturnCaptureId(newcapture_id);
252     return kViECaptureDeviceUnknownError;
253   }
254   vie_frame_provider_map_[newcapture_id] = vie_capture;
255   capture_id = newcapture_id;
256   return 0;
257 }
258 
DestroyCaptureDevice(const int capture_id)259 int ViEInputManager::DestroyCaptureDevice(const int capture_id) {
260   ViECapturer* vie_capture = NULL;
261   {
262     // We need exclusive access to the object to delete it.
263     // Take this write lock first since the read lock is taken before map_cs_.
264     ViEManagerWriteScoped wl(this);
265     CriticalSectionScoped cs(map_cs_.get());
266 
267     vie_capture = ViECapturePtr(capture_id);
268     if (!vie_capture) {
269       LOG(LS_ERROR) << "No such capture device id: " << capture_id;
270       return -1;
271     }
272     uint32_t num_callbacks =
273         vie_capture->NumberOfRegisteredFrameCallbacks();
274     if (num_callbacks > 0) {
275       LOG(LS_WARNING) << num_callbacks << " still registered to capture id "
276                       << capture_id << " when destroying capture device.";
277     }
278     vie_frame_provider_map_.erase(capture_id);
279     ReturnCaptureId(capture_id);
280     // Leave cs before deleting the capture object. This is because deleting the
281     // object might cause deletions of renderers so we prefer to not have a lock
282     // at that time.
283   }
284   delete vie_capture;
285   return 0;
286 }
287 
CreateExternalCaptureDevice(ViEExternalCapture * & external_capture,int & capture_id)288 int ViEInputManager::CreateExternalCaptureDevice(
289     ViEExternalCapture*& external_capture,
290     int& capture_id) {
291   CriticalSectionScoped cs(map_cs_.get());
292 
293   int newcapture_id = 0;
294   if (GetFreeCaptureId(&newcapture_id) == false) {
295     LOG(LS_ERROR) << "All capture devices already allocated.";
296     return kViECaptureDeviceMaxNoDevicesAllocated;
297   }
298 
299   ViECapturer* vie_capture = ViECapturer::CreateViECapture(
300       newcapture_id, engine_id_, config_, NULL, 0, *module_process_thread_);
301   if (!vie_capture) {
302     ReturnCaptureId(newcapture_id);
303     return kViECaptureDeviceUnknownError;
304   }
305 
306   vie_frame_provider_map_[newcapture_id] = vie_capture;
307   capture_id = newcapture_id;
308   external_capture = vie_capture;
309   return 0;
310 }
311 
GetFreeCaptureId(int * freecapture_id)312 bool ViEInputManager::GetFreeCaptureId(int* freecapture_id) {
313   for (int id = 0; id < kViEMaxCaptureDevices; id++) {
314     if (free_capture_device_id_[id]) {
315       // We found a free capture device id.
316       free_capture_device_id_[id] = false;
317       *freecapture_id = id + kViECaptureIdBase;
318       return true;
319     }
320   }
321   return false;
322 }
323 
ReturnCaptureId(int capture_id)324 void ViEInputManager::ReturnCaptureId(int capture_id) {
325   CriticalSectionScoped cs(map_cs_.get());
326   if (capture_id >= kViECaptureIdBase &&
327       capture_id < kViEMaxCaptureDevices + kViECaptureIdBase) {
328     free_capture_device_id_[capture_id - kViECaptureIdBase] = true;
329   }
330   return;
331 }
332 
ViEFrameProvider(const ViEFrameCallback * capture_observer) const333 ViEFrameProviderBase* ViEInputManager::ViEFrameProvider(
334     const ViEFrameCallback* capture_observer) const {
335   assert(capture_observer);
336   CriticalSectionScoped cs(map_cs_.get());
337 
338   for (FrameProviderMap::const_iterator it = vie_frame_provider_map_.begin();
339        it != vie_frame_provider_map_.end();
340        ++it) {
341     if (it->second->IsFrameCallbackRegistered(capture_observer))
342       return it->second;
343   }
344 
345   // No capture device set for this channel.
346   return NULL;
347 }
348 
ViEFrameProvider(int provider_id) const349 ViEFrameProviderBase* ViEInputManager::ViEFrameProvider(int provider_id) const {
350   CriticalSectionScoped cs(map_cs_.get());
351 
352   FrameProviderMap::const_iterator it =
353       vie_frame_provider_map_.find(provider_id);
354   if (it == vie_frame_provider_map_.end())
355     return NULL;
356   return it->second;
357 }
358 
ViECapturePtr(int capture_id) const359 ViECapturer* ViEInputManager::ViECapturePtr(int capture_id) const {
360   if (!(capture_id >= kViECaptureIdBase &&
361         capture_id <= kViECaptureIdBase + kViEMaxCaptureDevices)) {
362     LOG(LS_ERROR) << "Capture device doesn't exist " << capture_id << ".";
363     return NULL;
364   }
365 
366   return static_cast<ViECapturer*>(ViEFrameProvider(capture_id));
367 }
368 
ViEInputManagerScoped(const ViEInputManager & vie_input_manager)369 ViEInputManagerScoped::ViEInputManagerScoped(
370     const ViEInputManager& vie_input_manager)
371     : ViEManagerScopedBase(vie_input_manager) {
372 }
373 
Capture(int capture_id) const374 ViECapturer* ViEInputManagerScoped::Capture(int capture_id) const {
375   return static_cast<const ViEInputManager*>(vie_manager_)->ViECapturePtr(
376       capture_id);
377 }
378 
FrameProvider(const ViEFrameCallback * capture_observer) const379 ViEFrameProviderBase* ViEInputManagerScoped::FrameProvider(
380     const ViEFrameCallback* capture_observer) const {
381   return static_cast<const ViEInputManager*>(vie_manager_)->ViEFrameProvider(
382       capture_observer);
383 }
384 
FrameProvider(int provider_id) const385 ViEFrameProviderBase* ViEInputManagerScoped::FrameProvider(
386     int provider_id) const {
387   return static_cast<const ViEInputManager*>(vie_manager_)->ViEFrameProvider(
388       provider_id);
389 }
390 
391 }  // namespace webrtc
392