blob: b1f28aea5c0166d0f313b544509e056f769de2ed [file] [log] [blame]
niklase@google.com470e71d2011-07-07 08:21:25 +00001/*
mflodman@webrtc.orgc80d9d92012-02-06 10:11:25 +00002 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
niklase@google.com470e71d2011-07-07 08:21:25 +00003 *
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
pbos@webrtc.orgf5d4cb12013-05-17 13:44:48 +000011#include "webrtc/video_engine/vie_input_manager.h"
niklase@google.com470e71d2011-07-07 08:21:25 +000012
pbos@webrtc.org12dc1a32013-08-05 16:22:53 +000013#include <assert.h>
niklase@google.com470e71d2011-07-07 08:21:25 +000014
pbos@webrtc.orgf5d4cb12013-05-17 13:44:48 +000015#include "webrtc/common_types.h"
andrew@webrtc.org94caca72012-10-30 21:58:00 +000016#include "webrtc/modules/video_capture/include/video_capture_factory.h"
pbos@webrtc.orgf5d4cb12013-05-17 13:44:48 +000017#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/rw_lock_wrapper.h"
21#include "webrtc/system_wrappers/interface/trace.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"
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +000025
niklase@google.com470e71d2011-07-07 08:21:25 +000026namespace webrtc {
27
andresp@webrtc.org7707d062013-05-13 10:50:50 +000028ViEInputManager::ViEInputManager(const int engine_id, const Config& config)
29 : config_(config),
30 engine_id_(engine_id),
mflodman@webrtc.orgd32c4472011-12-22 14:17:53 +000031 map_cs_(CriticalSectionWrapper::CreateCriticalSection()),
pbos@webrtc.org927296f2013-03-08 13:12:29 +000032 device_info_cs_(CriticalSectionWrapper::CreateCriticalSection()),
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +000033 vie_frame_provider_map_(),
34 capture_device_info_(NULL),
35 module_process_thread_(NULL) {
36 WEBRTC_TRACE(webrtc::kTraceMemory, webrtc::kTraceVideo, ViEId(engine_id_),
37 "%s", __FUNCTION__);
niklase@google.com470e71d2011-07-07 08:21:25 +000038
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +000039 for (int idx = 0; idx < kViEMaxCaptureDevices; idx++) {
40 free_capture_device_id_[idx] = true;
41 }
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +000042}
niklase@google.com470e71d2011-07-07 08:21:25 +000043
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +000044ViEInputManager::~ViEInputManager() {
45 WEBRTC_TRACE(webrtc::kTraceMemory, webrtc::kTraceVideo, ViEId(engine_id_),
46 "%s", __FUNCTION__);
47 while (vie_frame_provider_map_.Size() != 0) {
48 MapItem* item = vie_frame_provider_map_.First();
49 assert(item);
50 ViEFrameProviderBase* frame_provider =
51 static_cast<ViEFrameProviderBase*>(item->GetItem());
52 vie_frame_provider_map_.Erase(item);
53 delete frame_provider;
54 }
55
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +000056 if (capture_device_info_) {
57 delete capture_device_info_;
58 capture_device_info_ = NULL;
59 }
60}
61void ViEInputManager::SetModuleProcessThread(
mflodman@webrtc.org8baed512012-06-21 12:11:50 +000062 ProcessThread* module_process_thread) {
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +000063 assert(!module_process_thread_);
mflodman@webrtc.org8baed512012-06-21 12:11:50 +000064 module_process_thread_ = module_process_thread;
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +000065}
66
67int ViEInputManager::NumberOfCaptureDevices() {
68 WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo, ViEId(engine_id_), "%s",
niklase@google.com470e71d2011-07-07 08:21:25 +000069 __FUNCTION__);
pbos@webrtc.org927296f2013-03-08 13:12:29 +000070 CriticalSectionScoped cs(device_info_cs_.get());
71 if (capture_device_info_ == NULL)
72 capture_device_info_ = VideoCaptureFactory::CreateDeviceInfo(
73 ViEModuleId(engine_id_));
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +000074 assert(capture_device_info_);
75 return capture_device_info_->NumberOfDevices();
niklase@google.com470e71d2011-07-07 08:21:25 +000076}
77
pbos@webrtc.orgb238d122013-04-09 13:41:51 +000078int ViEInputManager::GetDeviceName(uint32_t device_number,
leozwang@webrtc.org1745e932012-03-01 16:30:40 +000079 char* device_nameUTF8,
pbos@webrtc.orgb238d122013-04-09 13:41:51 +000080 uint32_t device_name_length,
leozwang@webrtc.org1745e932012-03-01 16:30:40 +000081 char* device_unique_idUTF8,
pbos@webrtc.orgb238d122013-04-09 13:41:51 +000082 uint32_t device_unique_idUTF8Length) {
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +000083 WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo, ViEId(engine_id_),
84 "%s(device_number: %d)", __FUNCTION__, device_number);
pbos@webrtc.org927296f2013-03-08 13:12:29 +000085 CriticalSectionScoped cs(device_info_cs_.get());
86 if (capture_device_info_ == NULL)
87 capture_device_info_ = VideoCaptureFactory::CreateDeviceInfo(
88 ViEModuleId(engine_id_));
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +000089 assert(capture_device_info_);
90 return capture_device_info_->GetDeviceName(device_number, device_nameUTF8,
91 device_name_length,
92 device_unique_idUTF8,
93 device_unique_idUTF8Length);
niklase@google.com470e71d2011-07-07 08:21:25 +000094}
95
niklase@google.com470e71d2011-07-07 08:21:25 +000096int ViEInputManager::NumberOfCaptureCapabilities(
leozwang@webrtc.org1745e932012-03-01 16:30:40 +000097 const char* device_unique_idUTF8) {
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +000098 WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo, ViEId(engine_id_), "%s",
niklase@google.com470e71d2011-07-07 08:21:25 +000099 __FUNCTION__);
pbos@webrtc.org927296f2013-03-08 13:12:29 +0000100 CriticalSectionScoped cs(device_info_cs_.get());
101 if (capture_device_info_ == NULL)
102 capture_device_info_ = VideoCaptureFactory::CreateDeviceInfo(
103 ViEModuleId(engine_id_));
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000104 assert(capture_device_info_);
105 return capture_device_info_->NumberOfCapabilities(device_unique_idUTF8);
niklase@google.com470e71d2011-07-07 08:21:25 +0000106}
107
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000108int ViEInputManager::GetCaptureCapability(
leozwang@webrtc.org1745e932012-03-01 16:30:40 +0000109 const char* device_unique_idUTF8,
pbos@webrtc.orgb238d122013-04-09 13:41:51 +0000110 const uint32_t device_capability_number,
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000111 CaptureCapability& capability) {
112 WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo, ViEId(engine_id_),
113 "%s(device_unique_idUTF8: %s, device_capability_number: %d)",
114 __FUNCTION__, device_unique_idUTF8, device_capability_number);
pbos@webrtc.org927296f2013-03-08 13:12:29 +0000115 CriticalSectionScoped cs(device_info_cs_.get());
116 if (capture_device_info_ == NULL)
117 capture_device_info_ = VideoCaptureFactory::CreateDeviceInfo(
118 ViEModuleId(engine_id_));
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000119 assert(capture_device_info_);
120 VideoCaptureCapability module_capability;
121 int result = capture_device_info_->GetCapability(device_unique_idUTF8,
122 device_capability_number,
123 module_capability);
124 if (result != 0)
niklase@google.com470e71d2011-07-07 08:21:25 +0000125 return result;
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000126
127 // Copy from module type to public type.
128 capability.expectedCaptureDelay = module_capability.expectedCaptureDelay;
129 capability.height = module_capability.height;
130 capability.width = module_capability.width;
131 capability.interlaced = module_capability.interlaced;
132 capability.rawType = module_capability.rawType;
133 capability.codecType = module_capability.codecType;
134 capability.maxFPS = module_capability.maxFPS;
135 return result;
niklase@google.com470e71d2011-07-07 08:21:25 +0000136}
137
leozwang@webrtc.org1745e932012-03-01 16:30:40 +0000138int ViEInputManager::GetOrientation(const char* device_unique_idUTF8,
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000139 RotateCapturedFrame& orientation) {
140 WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo, ViEId(engine_id_),
141 "%s(device_unique_idUTF8: %s,)", __FUNCTION__,
142 device_unique_idUTF8);
pbos@webrtc.org927296f2013-03-08 13:12:29 +0000143 CriticalSectionScoped cs(device_info_cs_.get());
144 if (capture_device_info_ == NULL)
145 capture_device_info_ = VideoCaptureFactory::CreateDeviceInfo(
146 ViEModuleId(engine_id_));
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000147 assert(capture_device_info_);
148 VideoCaptureRotation module_orientation;
149 int result = capture_device_info_->GetOrientation(device_unique_idUTF8,
150 module_orientation);
151 // Copy from module type to public type.
152 switch (module_orientation) {
153 case kCameraRotate0:
154 orientation = RotateCapturedFrame_0;
155 break;
156 case kCameraRotate90:
157 orientation = RotateCapturedFrame_90;
158 break;
159 case kCameraRotate180:
160 orientation = RotateCapturedFrame_180;
161 break;
162 case kCameraRotate270:
163 orientation = RotateCapturedFrame_270;
164 break;
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000165 }
166 return result;
niklase@google.com470e71d2011-07-07 08:21:25 +0000167}
168
niklase@google.com470e71d2011-07-07 08:21:25 +0000169int ViEInputManager::DisplayCaptureSettingsDialogBox(
leozwang@webrtc.org1745e932012-03-01 16:30:40 +0000170 const char* device_unique_idUTF8,
171 const char* dialog_titleUTF8,
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000172 void* parent_window,
pbos@webrtc.orgb238d122013-04-09 13:41:51 +0000173 uint32_t positionX,
174 uint32_t positionY) {
pbos@webrtc.org927296f2013-03-08 13:12:29 +0000175 CriticalSectionScoped cs(device_info_cs_.get());
176 if (capture_device_info_ == NULL)
177 capture_device_info_ = VideoCaptureFactory::CreateDeviceInfo(
178 ViEModuleId(engine_id_));
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000179 assert(capture_device_info_);
180 return capture_device_info_->DisplayCaptureSettingsDialogBox(
181 device_unique_idUTF8, dialog_titleUTF8, parent_window, positionX,
182 positionY);
niklase@google.com470e71d2011-07-07 08:21:25 +0000183}
184
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000185int ViEInputManager::CreateCaptureDevice(
leozwang@webrtc.org1745e932012-03-01 16:30:40 +0000186 const char* device_unique_idUTF8,
pbos@webrtc.orgb238d122013-04-09 13:41:51 +0000187 const uint32_t device_unique_idUTF8Length,
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000188 int& capture_id) {
189 WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo, ViEId(engine_id_),
190 "%s(device_unique_id: %s)", __FUNCTION__, device_unique_idUTF8);
mflodman@webrtc.orgd32c4472011-12-22 14:17:53 +0000191 CriticalSectionScoped cs(map_cs_.get());
niklase@google.com470e71d2011-07-07 08:21:25 +0000192
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000193 // Make sure the device is not already allocated.
194 for (MapItem* item = vie_frame_provider_map_.First(); item != NULL;
195 item = vie_frame_provider_map_.Next(item)) {
196 // Make sure this is a capture device.
197 if (item->GetId() >= kViECaptureIdBase &&
198 item->GetId() <= kViECaptureIdMax) {
199 ViECapturer* vie_capture = static_cast<ViECapturer*>(item->GetItem());
200 assert(vie_capture);
201 // TODO(mflodman) Can we change input to avoid this cast?
202 const char* device_name =
203 reinterpret_cast<const char*>(vie_capture->CurrentDeviceName());
204 if (strncmp(device_name,
205 reinterpret_cast<const char*>(device_unique_idUTF8),
206 strlen(device_name)) == 0) {
207 return kViECaptureDeviceAlreadyAllocated;
208 }
209 }
210 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000211
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000212 // Make sure the device name is valid.
213 bool found_device = false;
pbos@webrtc.org927296f2013-03-08 13:12:29 +0000214 CriticalSectionScoped cs_devinfo(device_info_cs_.get());
215 if (capture_device_info_ == NULL)
216 capture_device_info_ = VideoCaptureFactory::CreateDeviceInfo(
217 ViEModuleId(engine_id_));
218 assert(capture_device_info_);
pbos@webrtc.orgb238d122013-04-09 13:41:51 +0000219 for (uint32_t device_index = 0;
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000220 device_index < capture_device_info_->NumberOfDevices(); ++device_index) {
221 if (device_unique_idUTF8Length > kVideoCaptureUniqueNameLength) {
222 // User's string length is longer than the max.
223 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +0000224 }
225
leozwang@webrtc.org1745e932012-03-01 16:30:40 +0000226 char found_name[kVideoCaptureDeviceNameLength] = "";
227 char found_unique_name[kVideoCaptureUniqueNameLength] = "";
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000228 capture_device_info_->GetDeviceName(device_index, found_name,
229 kVideoCaptureDeviceNameLength,
230 found_unique_name,
231 kVideoCaptureUniqueNameLength);
232
233 // TODO(mflodman) Can we change input to avoid this cast?
234 const char* cast_id = reinterpret_cast<const char*>(device_unique_idUTF8);
235 if (strncmp(cast_id, reinterpret_cast<const char*>(found_unique_name),
236 strlen(cast_id)) == 0) {
237 WEBRTC_TRACE(webrtc::kTraceDebug, webrtc::kTraceVideo, ViEId(engine_id_),
238 "%s:%d Capture device was found by unique ID: %s. Returning",
239 __FUNCTION__, __LINE__, device_unique_idUTF8);
240 found_device = true;
241 break;
niklase@google.com470e71d2011-07-07 08:21:25 +0000242 }
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000243 }
244 if (!found_device) {
245 WEBRTC_TRACE(webrtc::kTraceDebug, webrtc::kTraceVideo, ViEId(engine_id_),
246 "%s:%d Capture device NOT found by unique ID: %s. Returning",
247 __FUNCTION__, __LINE__, device_unique_idUTF8);
248 return kViECaptureDeviceDoesNotExist;
249 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000250
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000251 int newcapture_id = 0;
mflodman@webrtc.org8baed512012-06-21 12:11:50 +0000252 if (GetFreeCaptureId(&newcapture_id) == false) {
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000253 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo, ViEId(engine_id_),
254 "%s: Maximum supported number of capture devices already in "
255 "use", __FUNCTION__);
256 return kViECaptureDeviceMaxNoDevicesAllocated;
257 }
258 ViECapturer* vie_capture = ViECapturer::CreateViECapture(
andresp@webrtc.org7707d062013-05-13 10:50:50 +0000259 newcapture_id, engine_id_, config_, device_unique_idUTF8,
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000260 device_unique_idUTF8Length, *module_process_thread_);
261 if (!vie_capture) {
262 ReturnCaptureId(newcapture_id);
263 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo, ViEId(engine_id_),
264 "%s: Could not create capture module for %s", __FUNCTION__,
265 device_unique_idUTF8);
266 return kViECaptureDeviceUnknownError;
267 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000268
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000269 if (vie_frame_provider_map_.Insert(newcapture_id, vie_capture) != 0) {
270 ReturnCaptureId(newcapture_id);
271 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo, ViEId(engine_id_),
272 "%s: Could not insert capture module for %s", __FUNCTION__,
273 device_unique_idUTF8);
274 return kViECaptureDeviceUnknownError;
275 }
276 capture_id = newcapture_id;
277 WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo, ViEId(engine_id_),
278 "%s(device_unique_id: %s, capture_id: %d)", __FUNCTION__,
279 device_unique_idUTF8, capture_id);
280 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000281}
282
mflodman@webrtc.org8baed512012-06-21 12:11:50 +0000283int ViEInputManager::CreateCaptureDevice(VideoCaptureModule* capture_module,
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000284 int& capture_id) {
285 WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo, ViEId(engine_id_), "%s",
niklase@google.com470e71d2011-07-07 08:21:25 +0000286 __FUNCTION__);
niklase@google.com470e71d2011-07-07 08:21:25 +0000287
mflodman@webrtc.orgd32c4472011-12-22 14:17:53 +0000288 CriticalSectionScoped cs(map_cs_.get());
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000289 int newcapture_id = 0;
mflodman@webrtc.org8baed512012-06-21 12:11:50 +0000290 if (!GetFreeCaptureId(&newcapture_id)) {
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000291 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo, ViEId(engine_id_),
292 "%s: Maximum supported number of capture devices already in "
293 "use", __FUNCTION__);
294 return kViECaptureDeviceMaxNoDevicesAllocated;
295 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000296
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000297 ViECapturer* vie_capture = ViECapturer::CreateViECapture(
andresp@webrtc.org7707d062013-05-13 10:50:50 +0000298 newcapture_id, engine_id_, config_,
299 capture_module, *module_process_thread_);
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000300 if (!vie_capture) {
301 ReturnCaptureId(newcapture_id);
302 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo, ViEId(engine_id_),
303 "%s: Could attach capture module.", __FUNCTION__);
304 return kViECaptureDeviceUnknownError;
305 }
306 if (vie_frame_provider_map_.Insert(newcapture_id, vie_capture) != 0) {
307 ReturnCaptureId(newcapture_id);
308 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo, ViEId(engine_id_),
309 "%s: Could not insert capture module", __FUNCTION__);
310 return kViECaptureDeviceUnknownError;
311 }
312 capture_id = newcapture_id;
313 WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo, ViEId(engine_id_),
314 "%s, capture_id: %d", __FUNCTION__, capture_id);
315 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000316}
317
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000318int ViEInputManager::DestroyCaptureDevice(const int capture_id) {
319 WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo, ViEId(engine_id_),
320 "%s(capture_id: %d)", __FUNCTION__, capture_id);
321 ViECapturer* vie_capture = NULL;
322 {
323 // We need exclusive access to the object to delete it.
324 // Take this write lock first since the read lock is taken before map_cs_.
mflodman@webrtc.orgcee447a2012-06-28 07:29:46 +0000325 ViEManagerWriteScoped wl(this);
mflodman@webrtc.orgd32c4472011-12-22 14:17:53 +0000326 CriticalSectionScoped cs(map_cs_.get());
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000327
328 vie_capture = ViECapturePtr(capture_id);
329 if (!vie_capture) {
330 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo, ViEId(engine_id_),
331 "%s(capture_id: %d) - No such capture device id",
332 __FUNCTION__, capture_id);
333 return -1;
334 }
pbos@webrtc.orgb238d122013-04-09 13:41:51 +0000335 uint32_t num_callbacks =
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000336 vie_capture->NumberOfRegisteredFrameCallbacks();
337 if (num_callbacks > 0) {
338 WEBRTC_TRACE(webrtc::kTraceWarning, webrtc::kTraceVideo,
339 ViEId(engine_id_), "%s(capture_id: %d) - %u registered "
340 "callbacks when destroying capture device",
341 __FUNCTION__, capture_id, num_callbacks);
342 }
343 vie_frame_provider_map_.Erase(capture_id);
344 ReturnCaptureId(capture_id);
345 // Leave cs before deleting the capture object. This is because deleting the
346 // object might cause deletions of renderers so we prefer to not have a lock
347 // at that time.
348 }
349 delete vie_capture;
350 return 0;
351}
352
353int ViEInputManager::CreateExternalCaptureDevice(
354 ViEExternalCapture*& external_capture,
355 int& capture_id) {
356 WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo, ViEId(engine_id_), "%s",
357 __FUNCTION__);
mflodman@webrtc.orgd32c4472011-12-22 14:17:53 +0000358 CriticalSectionScoped cs(map_cs_.get());
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000359
360 int newcapture_id = 0;
mflodman@webrtc.org8baed512012-06-21 12:11:50 +0000361 if (GetFreeCaptureId(&newcapture_id) == false) {
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000362 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo, ViEId(engine_id_),
363 "%s: Maximum supported number of capture devices already in "
364 "use", __FUNCTION__);
365 return kViECaptureDeviceMaxNoDevicesAllocated;
366 }
367
368 ViECapturer* vie_capture = ViECapturer::CreateViECapture(
andresp@webrtc.org7707d062013-05-13 10:50:50 +0000369 newcapture_id, engine_id_, config_, NULL, 0, *module_process_thread_);
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000370 if (!vie_capture) {
371 ReturnCaptureId(newcapture_id);
372 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo, ViEId(engine_id_),
373 "%s: Could not create capture module for external capture.",
374 __FUNCTION__);
375 return kViECaptureDeviceUnknownError;
376 }
377
378 if (vie_frame_provider_map_.Insert(newcapture_id, vie_capture) != 0) {
379 ReturnCaptureId(newcapture_id);
380 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo, ViEId(engine_id_),
381 "%s: Could not insert capture module for external capture.",
382 __FUNCTION__);
383 return kViECaptureDeviceUnknownError;
384 }
385 capture_id = newcapture_id;
386 external_capture = vie_capture;
387 WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo, ViEId(engine_id_),
388 "%s, capture_id: %d)", __FUNCTION__, capture_id);
389 return 0;
390}
391
mflodman@webrtc.org8baed512012-06-21 12:11:50 +0000392bool ViEInputManager::GetFreeCaptureId(int* freecapture_id) {
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000393 WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo, ViEId(engine_id_), "%s",
394 __FUNCTION__);
395 for (int id = 0; id < kViEMaxCaptureDevices; id++) {
396 if (free_capture_device_id_[id]) {
397 // We found a free capture device id.
398 free_capture_device_id_[id] = false;
mflodman@webrtc.org8baed512012-06-21 12:11:50 +0000399 *freecapture_id = id + kViECaptureIdBase;
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000400 WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo, ViEId(engine_id_),
mflodman@webrtc.org8baed512012-06-21 12:11:50 +0000401 "%s: new id: %d", __FUNCTION__, *freecapture_id);
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000402 return true;
403 }
404 }
405 return false;
406}
niklase@google.com470e71d2011-07-07 08:21:25 +0000407
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000408void ViEInputManager::ReturnCaptureId(int capture_id) {
409 WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo, ViEId(engine_id_),
410 "%s(%d)", __FUNCTION__, capture_id);
mflodman@webrtc.orgd32c4472011-12-22 14:17:53 +0000411 CriticalSectionScoped cs(map_cs_.get());
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000412 if (capture_id >= kViECaptureIdBase &&
413 capture_id < kViEMaxCaptureDevices + kViECaptureIdBase) {
414 free_capture_device_id_[capture_id - kViECaptureIdBase] = true;
415 }
416 return;
417}
niklase@google.com470e71d2011-07-07 08:21:25 +0000418
niklase@google.com470e71d2011-07-07 08:21:25 +0000419ViEFrameProviderBase* ViEInputManager::ViEFrameProvider(
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000420 const ViEFrameCallback* capture_observer) const {
421 assert(capture_observer);
mflodman@webrtc.orgd32c4472011-12-22 14:17:53 +0000422 CriticalSectionScoped cs(map_cs_.get());
niklase@google.com470e71d2011-07-07 08:21:25 +0000423
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000424 for (MapItem* provider_item = vie_frame_provider_map_.First(); provider_item
425 != NULL; provider_item = vie_frame_provider_map_.Next(provider_item)) {
426 ViEFrameProviderBase* vie_frame_provider =
427 static_cast<ViEFrameProviderBase*>(provider_item->GetItem());
428 assert(vie_frame_provider != NULL);
niklase@google.com470e71d2011-07-07 08:21:25 +0000429
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000430 if (vie_frame_provider->IsFrameCallbackRegistered(capture_observer)) {
431 // We found it.
432 return vie_frame_provider;
niklase@google.com470e71d2011-07-07 08:21:25 +0000433 }
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000434 }
435 // No capture device set for this channel.
436 return NULL;
437}
438
439ViEFrameProviderBase* ViEInputManager::ViEFrameProvider(int provider_id) const {
mflodman@webrtc.orgd32c4472011-12-22 14:17:53 +0000440 CriticalSectionScoped cs(map_cs_.get());
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000441 MapItem* map_item = vie_frame_provider_map_.Find(provider_id);
442 if (!map_item) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000443 return NULL;
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000444 }
445 ViEFrameProviderBase* vie_frame_provider =
446 static_cast<ViEFrameProviderBase*>(map_item->GetItem());
447 return vie_frame_provider;
niklase@google.com470e71d2011-07-07 08:21:25 +0000448}
449
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000450ViECapturer* ViEInputManager::ViECapturePtr(int capture_id) const {
451 if (!(capture_id >= kViECaptureIdBase &&
452 capture_id <= kViECaptureIdBase + kViEMaxCaptureDevices))
453 return NULL;
niklase@google.com470e71d2011-07-07 08:21:25 +0000454
mflodman@webrtc.orgd32c4472011-12-22 14:17:53 +0000455 CriticalSectionScoped cs(map_cs_.get());
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000456 MapItem* map_item = vie_frame_provider_map_.Find(capture_id);
457 if (!map_item) {
458 return NULL;
459 }
460 ViECapturer* vie_capture = static_cast<ViECapturer*>(map_item->GetItem());
461 return vie_capture;
niklase@google.com470e71d2011-07-07 08:21:25 +0000462}
463
niklase@google.com470e71d2011-07-07 08:21:25 +0000464ViEInputManagerScoped::ViEInputManagerScoped(
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000465 const ViEInputManager& vie_input_manager)
466 : ViEManagerScopedBase(vie_input_manager) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000467}
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000468
469ViECapturer* ViEInputManagerScoped::Capture(int capture_id) const {
470 return static_cast<const ViEInputManager*>(vie_manager_)->ViECapturePtr(
471 capture_id);
niklase@google.com470e71d2011-07-07 08:21:25 +0000472}
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000473
niklase@google.com470e71d2011-07-07 08:21:25 +0000474ViEFrameProviderBase* ViEInputManagerScoped::FrameProvider(
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000475 const ViEFrameCallback* capture_observer) const {
476 return static_cast<const ViEInputManager*>(vie_manager_)->ViEFrameProvider(
477 capture_observer);
niklase@google.com470e71d2011-07-07 08:21:25 +0000478}
479
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000480ViEFrameProviderBase* ViEInputManagerScoped::FrameProvider(
481 int provider_id) const {
482 return static_cast<const ViEInputManager*>(vie_manager_)->ViEFrameProvider(
483 provider_id);
niklase@google.com470e71d2011-07-07 08:21:25 +0000484}
485
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000486} // namespace webrtc