blob: c22aa131454b344539a2f860faeae81e3bfb80c2 [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
13#include <cassert>
14
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"
25#include "webrtc/video_engine/vie_file_player.h"
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +000026
niklase@google.com470e71d2011-07-07 08:21:25 +000027namespace webrtc {
28
andresp@webrtc.org7707d062013-05-13 10:50:50 +000029ViEInputManager::ViEInputManager(const int engine_id, const Config& config)
30 : config_(config),
31 engine_id_(engine_id),
mflodman@webrtc.orgd32c4472011-12-22 14:17:53 +000032 map_cs_(CriticalSectionWrapper::CreateCriticalSection()),
pbos@webrtc.org927296f2013-03-08 13:12:29 +000033 device_info_cs_(CriticalSectionWrapper::CreateCriticalSection()),
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +000034 vie_frame_provider_map_(),
35 capture_device_info_(NULL),
36 module_process_thread_(NULL) {
37 WEBRTC_TRACE(webrtc::kTraceMemory, webrtc::kTraceVideo, ViEId(engine_id_),
38 "%s", __FUNCTION__);
niklase@google.com470e71d2011-07-07 08:21:25 +000039
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +000040 for (int idx = 0; idx < kViEMaxCaptureDevices; idx++) {
41 free_capture_device_id_[idx] = true;
42 }
pbos@webrtc.org927296f2013-03-08 13:12:29 +000043
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +000044 for (int idx = 0; idx < kViEMaxFilePlayers; idx++) {
45 free_file_id_[idx] = true;
46 }
47}
niklase@google.com470e71d2011-07-07 08:21:25 +000048
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +000049ViEInputManager::~ViEInputManager() {
50 WEBRTC_TRACE(webrtc::kTraceMemory, webrtc::kTraceVideo, ViEId(engine_id_),
51 "%s", __FUNCTION__);
52 while (vie_frame_provider_map_.Size() != 0) {
53 MapItem* item = vie_frame_provider_map_.First();
54 assert(item);
55 ViEFrameProviderBase* frame_provider =
56 static_cast<ViEFrameProviderBase*>(item->GetItem());
57 vie_frame_provider_map_.Erase(item);
58 delete frame_provider;
59 }
60
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +000061 if (capture_device_info_) {
62 delete capture_device_info_;
63 capture_device_info_ = NULL;
64 }
65}
66void ViEInputManager::SetModuleProcessThread(
mflodman@webrtc.org8baed512012-06-21 12:11:50 +000067 ProcessThread* module_process_thread) {
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +000068 assert(!module_process_thread_);
mflodman@webrtc.org8baed512012-06-21 12:11:50 +000069 module_process_thread_ = module_process_thread;
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +000070}
71
72int ViEInputManager::NumberOfCaptureDevices() {
73 WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo, ViEId(engine_id_), "%s",
niklase@google.com470e71d2011-07-07 08:21:25 +000074 __FUNCTION__);
pbos@webrtc.org927296f2013-03-08 13:12:29 +000075 CriticalSectionScoped cs(device_info_cs_.get());
76 if (capture_device_info_ == NULL)
77 capture_device_info_ = VideoCaptureFactory::CreateDeviceInfo(
78 ViEModuleId(engine_id_));
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +000079 assert(capture_device_info_);
80 return capture_device_info_->NumberOfDevices();
niklase@google.com470e71d2011-07-07 08:21:25 +000081}
82
pbos@webrtc.orgb238d122013-04-09 13:41:51 +000083int ViEInputManager::GetDeviceName(uint32_t device_number,
leozwang@webrtc.org1745e932012-03-01 16:30:40 +000084 char* device_nameUTF8,
pbos@webrtc.orgb238d122013-04-09 13:41:51 +000085 uint32_t device_name_length,
leozwang@webrtc.org1745e932012-03-01 16:30:40 +000086 char* device_unique_idUTF8,
pbos@webrtc.orgb238d122013-04-09 13:41:51 +000087 uint32_t device_unique_idUTF8Length) {
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +000088 WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo, ViEId(engine_id_),
89 "%s(device_number: %d)", __FUNCTION__, device_number);
pbos@webrtc.org927296f2013-03-08 13:12:29 +000090 CriticalSectionScoped cs(device_info_cs_.get());
91 if (capture_device_info_ == NULL)
92 capture_device_info_ = VideoCaptureFactory::CreateDeviceInfo(
93 ViEModuleId(engine_id_));
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +000094 assert(capture_device_info_);
95 return capture_device_info_->GetDeviceName(device_number, device_nameUTF8,
96 device_name_length,
97 device_unique_idUTF8,
98 device_unique_idUTF8Length);
niklase@google.com470e71d2011-07-07 08:21:25 +000099}
100
niklase@google.com470e71d2011-07-07 08:21:25 +0000101int ViEInputManager::NumberOfCaptureCapabilities(
leozwang@webrtc.org1745e932012-03-01 16:30:40 +0000102 const char* device_unique_idUTF8) {
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000103 WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo, ViEId(engine_id_), "%s",
niklase@google.com470e71d2011-07-07 08:21:25 +0000104 __FUNCTION__);
pbos@webrtc.org927296f2013-03-08 13:12:29 +0000105 CriticalSectionScoped cs(device_info_cs_.get());
106 if (capture_device_info_ == NULL)
107 capture_device_info_ = VideoCaptureFactory::CreateDeviceInfo(
108 ViEModuleId(engine_id_));
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000109 assert(capture_device_info_);
110 return capture_device_info_->NumberOfCapabilities(device_unique_idUTF8);
niklase@google.com470e71d2011-07-07 08:21:25 +0000111}
112
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000113int ViEInputManager::GetCaptureCapability(
leozwang@webrtc.org1745e932012-03-01 16:30:40 +0000114 const char* device_unique_idUTF8,
pbos@webrtc.orgb238d122013-04-09 13:41:51 +0000115 const uint32_t device_capability_number,
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000116 CaptureCapability& capability) {
117 WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo, ViEId(engine_id_),
118 "%s(device_unique_idUTF8: %s, device_capability_number: %d)",
119 __FUNCTION__, device_unique_idUTF8, device_capability_number);
pbos@webrtc.org927296f2013-03-08 13:12:29 +0000120 CriticalSectionScoped cs(device_info_cs_.get());
121 if (capture_device_info_ == NULL)
122 capture_device_info_ = VideoCaptureFactory::CreateDeviceInfo(
123 ViEModuleId(engine_id_));
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000124 assert(capture_device_info_);
125 VideoCaptureCapability module_capability;
126 int result = capture_device_info_->GetCapability(device_unique_idUTF8,
127 device_capability_number,
128 module_capability);
129 if (result != 0)
niklase@google.com470e71d2011-07-07 08:21:25 +0000130 return result;
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000131
132 // Copy from module type to public type.
133 capability.expectedCaptureDelay = module_capability.expectedCaptureDelay;
134 capability.height = module_capability.height;
135 capability.width = module_capability.width;
136 capability.interlaced = module_capability.interlaced;
137 capability.rawType = module_capability.rawType;
138 capability.codecType = module_capability.codecType;
139 capability.maxFPS = module_capability.maxFPS;
140 return result;
niklase@google.com470e71d2011-07-07 08:21:25 +0000141}
142
leozwang@webrtc.org1745e932012-03-01 16:30:40 +0000143int ViEInputManager::GetOrientation(const char* device_unique_idUTF8,
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000144 RotateCapturedFrame& orientation) {
145 WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo, ViEId(engine_id_),
146 "%s(device_unique_idUTF8: %s,)", __FUNCTION__,
147 device_unique_idUTF8);
pbos@webrtc.org927296f2013-03-08 13:12:29 +0000148 CriticalSectionScoped cs(device_info_cs_.get());
149 if (capture_device_info_ == NULL)
150 capture_device_info_ = VideoCaptureFactory::CreateDeviceInfo(
151 ViEModuleId(engine_id_));
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000152 assert(capture_device_info_);
153 VideoCaptureRotation module_orientation;
154 int result = capture_device_info_->GetOrientation(device_unique_idUTF8,
155 module_orientation);
156 // Copy from module type to public type.
157 switch (module_orientation) {
158 case kCameraRotate0:
159 orientation = RotateCapturedFrame_0;
160 break;
161 case kCameraRotate90:
162 orientation = RotateCapturedFrame_90;
163 break;
164 case kCameraRotate180:
165 orientation = RotateCapturedFrame_180;
166 break;
167 case kCameraRotate270:
168 orientation = RotateCapturedFrame_270;
169 break;
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000170 }
171 return result;
niklase@google.com470e71d2011-07-07 08:21:25 +0000172}
173
niklase@google.com470e71d2011-07-07 08:21:25 +0000174int ViEInputManager::DisplayCaptureSettingsDialogBox(
leozwang@webrtc.org1745e932012-03-01 16:30:40 +0000175 const char* device_unique_idUTF8,
176 const char* dialog_titleUTF8,
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000177 void* parent_window,
pbos@webrtc.orgb238d122013-04-09 13:41:51 +0000178 uint32_t positionX,
179 uint32_t positionY) {
pbos@webrtc.org927296f2013-03-08 13:12:29 +0000180 CriticalSectionScoped cs(device_info_cs_.get());
181 if (capture_device_info_ == NULL)
182 capture_device_info_ = VideoCaptureFactory::CreateDeviceInfo(
183 ViEModuleId(engine_id_));
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000184 assert(capture_device_info_);
185 return capture_device_info_->DisplayCaptureSettingsDialogBox(
186 device_unique_idUTF8, dialog_titleUTF8, parent_window, positionX,
187 positionY);
niklase@google.com470e71d2011-07-07 08:21:25 +0000188}
189
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000190int ViEInputManager::CreateCaptureDevice(
leozwang@webrtc.org1745e932012-03-01 16:30:40 +0000191 const char* device_unique_idUTF8,
pbos@webrtc.orgb238d122013-04-09 13:41:51 +0000192 const uint32_t device_unique_idUTF8Length,
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000193 int& capture_id) {
194 WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo, ViEId(engine_id_),
195 "%s(device_unique_id: %s)", __FUNCTION__, device_unique_idUTF8);
mflodman@webrtc.orgd32c4472011-12-22 14:17:53 +0000196 CriticalSectionScoped cs(map_cs_.get());
niklase@google.com470e71d2011-07-07 08:21:25 +0000197
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000198 // Make sure the device is not already allocated.
199 for (MapItem* item = vie_frame_provider_map_.First(); item != NULL;
200 item = vie_frame_provider_map_.Next(item)) {
201 // Make sure this is a capture device.
202 if (item->GetId() >= kViECaptureIdBase &&
203 item->GetId() <= kViECaptureIdMax) {
204 ViECapturer* vie_capture = static_cast<ViECapturer*>(item->GetItem());
205 assert(vie_capture);
206 // TODO(mflodman) Can we change input to avoid this cast?
207 const char* device_name =
208 reinterpret_cast<const char*>(vie_capture->CurrentDeviceName());
209 if (strncmp(device_name,
210 reinterpret_cast<const char*>(device_unique_idUTF8),
211 strlen(device_name)) == 0) {
212 return kViECaptureDeviceAlreadyAllocated;
213 }
214 }
215 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000216
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000217 // Make sure the device name is valid.
218 bool found_device = false;
pbos@webrtc.org927296f2013-03-08 13:12:29 +0000219 CriticalSectionScoped cs_devinfo(device_info_cs_.get());
220 if (capture_device_info_ == NULL)
221 capture_device_info_ = VideoCaptureFactory::CreateDeviceInfo(
222 ViEModuleId(engine_id_));
223 assert(capture_device_info_);
pbos@webrtc.orgb238d122013-04-09 13:41:51 +0000224 for (uint32_t device_index = 0;
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000225 device_index < capture_device_info_->NumberOfDevices(); ++device_index) {
226 if (device_unique_idUTF8Length > kVideoCaptureUniqueNameLength) {
227 // User's string length is longer than the max.
228 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +0000229 }
230
leozwang@webrtc.org1745e932012-03-01 16:30:40 +0000231 char found_name[kVideoCaptureDeviceNameLength] = "";
232 char found_unique_name[kVideoCaptureUniqueNameLength] = "";
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000233 capture_device_info_->GetDeviceName(device_index, found_name,
234 kVideoCaptureDeviceNameLength,
235 found_unique_name,
236 kVideoCaptureUniqueNameLength);
237
238 // TODO(mflodman) Can we change input to avoid this cast?
239 const char* cast_id = reinterpret_cast<const char*>(device_unique_idUTF8);
240 if (strncmp(cast_id, reinterpret_cast<const char*>(found_unique_name),
241 strlen(cast_id)) == 0) {
242 WEBRTC_TRACE(webrtc::kTraceDebug, webrtc::kTraceVideo, ViEId(engine_id_),
243 "%s:%d Capture device was found by unique ID: %s. Returning",
244 __FUNCTION__, __LINE__, device_unique_idUTF8);
245 found_device = true;
246 break;
niklase@google.com470e71d2011-07-07 08:21:25 +0000247 }
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000248 }
249 if (!found_device) {
250 WEBRTC_TRACE(webrtc::kTraceDebug, webrtc::kTraceVideo, ViEId(engine_id_),
251 "%s:%d Capture device NOT found by unique ID: %s. Returning",
252 __FUNCTION__, __LINE__, device_unique_idUTF8);
253 return kViECaptureDeviceDoesNotExist;
254 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000255
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000256 int newcapture_id = 0;
mflodman@webrtc.org8baed512012-06-21 12:11:50 +0000257 if (GetFreeCaptureId(&newcapture_id) == false) {
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000258 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo, ViEId(engine_id_),
259 "%s: Maximum supported number of capture devices already in "
260 "use", __FUNCTION__);
261 return kViECaptureDeviceMaxNoDevicesAllocated;
262 }
263 ViECapturer* vie_capture = ViECapturer::CreateViECapture(
andresp@webrtc.org7707d062013-05-13 10:50:50 +0000264 newcapture_id, engine_id_, config_, device_unique_idUTF8,
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000265 device_unique_idUTF8Length, *module_process_thread_);
266 if (!vie_capture) {
267 ReturnCaptureId(newcapture_id);
268 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo, ViEId(engine_id_),
269 "%s: Could not create capture module for %s", __FUNCTION__,
270 device_unique_idUTF8);
271 return kViECaptureDeviceUnknownError;
272 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000273
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000274 if (vie_frame_provider_map_.Insert(newcapture_id, vie_capture) != 0) {
275 ReturnCaptureId(newcapture_id);
276 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo, ViEId(engine_id_),
277 "%s: Could not insert capture module for %s", __FUNCTION__,
278 device_unique_idUTF8);
279 return kViECaptureDeviceUnknownError;
280 }
281 capture_id = newcapture_id;
282 WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo, ViEId(engine_id_),
283 "%s(device_unique_id: %s, capture_id: %d)", __FUNCTION__,
284 device_unique_idUTF8, capture_id);
285 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000286}
287
mflodman@webrtc.org8baed512012-06-21 12:11:50 +0000288int ViEInputManager::CreateCaptureDevice(VideoCaptureModule* capture_module,
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000289 int& capture_id) {
290 WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo, ViEId(engine_id_), "%s",
niklase@google.com470e71d2011-07-07 08:21:25 +0000291 __FUNCTION__);
niklase@google.com470e71d2011-07-07 08:21:25 +0000292
mflodman@webrtc.orgd32c4472011-12-22 14:17:53 +0000293 CriticalSectionScoped cs(map_cs_.get());
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000294 int newcapture_id = 0;
mflodman@webrtc.org8baed512012-06-21 12:11:50 +0000295 if (!GetFreeCaptureId(&newcapture_id)) {
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000296 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo, ViEId(engine_id_),
297 "%s: Maximum supported number of capture devices already in "
298 "use", __FUNCTION__);
299 return kViECaptureDeviceMaxNoDevicesAllocated;
300 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000301
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000302 ViECapturer* vie_capture = ViECapturer::CreateViECapture(
andresp@webrtc.org7707d062013-05-13 10:50:50 +0000303 newcapture_id, engine_id_, config_,
304 capture_module, *module_process_thread_);
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000305 if (!vie_capture) {
306 ReturnCaptureId(newcapture_id);
307 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo, ViEId(engine_id_),
308 "%s: Could attach capture module.", __FUNCTION__);
309 return kViECaptureDeviceUnknownError;
310 }
311 if (vie_frame_provider_map_.Insert(newcapture_id, vie_capture) != 0) {
312 ReturnCaptureId(newcapture_id);
313 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo, ViEId(engine_id_),
314 "%s: Could not insert capture module", __FUNCTION__);
315 return kViECaptureDeviceUnknownError;
316 }
317 capture_id = newcapture_id;
318 WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo, ViEId(engine_id_),
319 "%s, capture_id: %d", __FUNCTION__, capture_id);
320 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000321}
322
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000323int ViEInputManager::DestroyCaptureDevice(const int capture_id) {
324 WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo, ViEId(engine_id_),
325 "%s(capture_id: %d)", __FUNCTION__, capture_id);
326 ViECapturer* vie_capture = NULL;
327 {
328 // We need exclusive access to the object to delete it.
329 // Take this write lock first since the read lock is taken before map_cs_.
mflodman@webrtc.orgcee447a2012-06-28 07:29:46 +0000330 ViEManagerWriteScoped wl(this);
mflodman@webrtc.orgd32c4472011-12-22 14:17:53 +0000331 CriticalSectionScoped cs(map_cs_.get());
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000332
333 vie_capture = ViECapturePtr(capture_id);
334 if (!vie_capture) {
335 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo, ViEId(engine_id_),
336 "%s(capture_id: %d) - No such capture device id",
337 __FUNCTION__, capture_id);
338 return -1;
339 }
pbos@webrtc.orgb238d122013-04-09 13:41:51 +0000340 uint32_t num_callbacks =
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000341 vie_capture->NumberOfRegisteredFrameCallbacks();
342 if (num_callbacks > 0) {
343 WEBRTC_TRACE(webrtc::kTraceWarning, webrtc::kTraceVideo,
344 ViEId(engine_id_), "%s(capture_id: %d) - %u registered "
345 "callbacks when destroying capture device",
346 __FUNCTION__, capture_id, num_callbacks);
347 }
348 vie_frame_provider_map_.Erase(capture_id);
349 ReturnCaptureId(capture_id);
350 // Leave cs before deleting the capture object. This is because deleting the
351 // object might cause deletions of renderers so we prefer to not have a lock
352 // at that time.
353 }
354 delete vie_capture;
355 return 0;
356}
357
358int ViEInputManager::CreateExternalCaptureDevice(
359 ViEExternalCapture*& external_capture,
360 int& capture_id) {
361 WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo, ViEId(engine_id_), "%s",
362 __FUNCTION__);
mflodman@webrtc.orgd32c4472011-12-22 14:17:53 +0000363 CriticalSectionScoped cs(map_cs_.get());
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000364
365 int newcapture_id = 0;
mflodman@webrtc.org8baed512012-06-21 12:11:50 +0000366 if (GetFreeCaptureId(&newcapture_id) == false) {
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000367 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo, ViEId(engine_id_),
368 "%s: Maximum supported number of capture devices already in "
369 "use", __FUNCTION__);
370 return kViECaptureDeviceMaxNoDevicesAllocated;
371 }
372
373 ViECapturer* vie_capture = ViECapturer::CreateViECapture(
andresp@webrtc.org7707d062013-05-13 10:50:50 +0000374 newcapture_id, engine_id_, config_, NULL, 0, *module_process_thread_);
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000375 if (!vie_capture) {
376 ReturnCaptureId(newcapture_id);
377 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo, ViEId(engine_id_),
378 "%s: Could not create capture module for external capture.",
379 __FUNCTION__);
380 return kViECaptureDeviceUnknownError;
381 }
382
383 if (vie_frame_provider_map_.Insert(newcapture_id, vie_capture) != 0) {
384 ReturnCaptureId(newcapture_id);
385 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo, ViEId(engine_id_),
386 "%s: Could not insert capture module for external capture.",
387 __FUNCTION__);
388 return kViECaptureDeviceUnknownError;
389 }
390 capture_id = newcapture_id;
391 external_capture = vie_capture;
392 WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo, ViEId(engine_id_),
393 "%s, capture_id: %d)", __FUNCTION__, capture_id);
394 return 0;
395}
396
leozwang@webrtc.org1745e932012-03-01 16:30:40 +0000397int ViEInputManager::CreateFilePlayer(const char* file_nameUTF8,
niklase@google.com470e71d2011-07-07 08:21:25 +0000398 const bool loop,
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000399 const webrtc::FileFormats file_format,
400 VoiceEngine* voe_ptr, int& file_id) {
401 WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo, ViEId(engine_id_),
402 "%s(device_unique_id: %s)", __FUNCTION__, file_nameUTF8);
niklase@google.com470e71d2011-07-07 08:21:25 +0000403
mflodman@webrtc.orgd32c4472011-12-22 14:17:53 +0000404 CriticalSectionScoped cs(map_cs_.get());
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000405 int new_file_id = 0;
mflodman@webrtc.org8baed512012-06-21 12:11:50 +0000406 if (GetFreeFileId(&new_file_id) == false) {
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000407 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo, ViEId(engine_id_),
408 "%s: Maximum supported number of file players already in use",
409 __FUNCTION__);
410 return kViEFileMaxNoOfFilesOpened;
411 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000412
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000413 ViEFilePlayer* vie_file_player = ViEFilePlayer::CreateViEFilePlayer(
mflodman@webrtc.org8baed512012-06-21 12:11:50 +0000414 new_file_id, engine_id_, file_nameUTF8, loop, file_format, voe_ptr);
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000415 if (!vie_file_player) {
416 ReturnFileId(new_file_id);
417 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo, ViEId(engine_id_),
418 "%s: Could not open file %s for playback", __FUNCTION__,
419 file_nameUTF8);
420 return kViEFileUnknownError;
421 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000422
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000423 if (vie_frame_provider_map_.Insert(new_file_id, vie_file_player) != 0) {
424 ReturnCaptureId(new_file_id);
425 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo, ViEId(engine_id_),
426 "%s: Could not insert file player for %s", __FUNCTION__,
427 file_nameUTF8);
428 delete vie_file_player;
429 return kViEFileUnknownError;
430 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000431
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000432 file_id = new_file_id;
433 WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo, ViEId(engine_id_),
434 "%s(filename: %s, file_id: %d)", __FUNCTION__, file_nameUTF8,
435 new_file_id);
436 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000437}
438
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000439int ViEInputManager::DestroyFilePlayer(int file_id) {
440 WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo, ViEId(engine_id_),
441 "%s(file_id: %d)", __FUNCTION__, file_id);
niklase@google.com470e71d2011-07-07 08:21:25 +0000442
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000443 ViEFilePlayer* vie_file_player = NULL;
444 {
445 // We need exclusive access to the object to delete it.
446 // Take this write lock first since the read lock is taken before map_cs_.
mflodman@webrtc.orgcee447a2012-06-28 07:29:46 +0000447 ViEManagerWriteScoped wl(this);
niklase@google.com470e71d2011-07-07 08:21:25 +0000448
mflodman@webrtc.orgd32c4472011-12-22 14:17:53 +0000449 CriticalSectionScoped cs(map_cs_.get());
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000450 vie_file_player = ViEFilePlayerPtr(file_id);
451 if (!vie_file_player) {
452 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo, ViEId(engine_id_),
453 "%s(file_id: %d) - No such file player", __FUNCTION__,
454 file_id);
455 return -1;
456 }
457 int num_callbacks = vie_file_player->NumberOfRegisteredFrameCallbacks();
458 if (num_callbacks > 0) {
459 WEBRTC_TRACE(webrtc::kTraceWarning, webrtc::kTraceVideo,
460 ViEId(engine_id_), "%s(file_id: %d) - %u registered "
461 "callbacks when destroying file player", __FUNCTION__,
462 file_id, num_callbacks);
463 }
464 vie_frame_provider_map_.Erase(file_id);
465 ReturnFileId(file_id);
466 // Leave cs before deleting the file object. This is because deleting the
467 // object might cause deletions of renderers so we prefer to not have a lock
468 // at that time.
469 }
470 delete vie_file_player;
471 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000472}
473
mflodman@webrtc.org8baed512012-06-21 12:11:50 +0000474bool ViEInputManager::GetFreeCaptureId(int* freecapture_id) {
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000475 WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo, ViEId(engine_id_), "%s",
476 __FUNCTION__);
477 for (int id = 0; id < kViEMaxCaptureDevices; id++) {
478 if (free_capture_device_id_[id]) {
479 // We found a free capture device id.
480 free_capture_device_id_[id] = false;
mflodman@webrtc.org8baed512012-06-21 12:11:50 +0000481 *freecapture_id = id + kViECaptureIdBase;
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000482 WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo, ViEId(engine_id_),
mflodman@webrtc.org8baed512012-06-21 12:11:50 +0000483 "%s: new id: %d", __FUNCTION__, *freecapture_id);
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000484 return true;
485 }
486 }
487 return false;
488}
niklase@google.com470e71d2011-07-07 08:21:25 +0000489
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000490void ViEInputManager::ReturnCaptureId(int capture_id) {
491 WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo, ViEId(engine_id_),
492 "%s(%d)", __FUNCTION__, capture_id);
mflodman@webrtc.orgd32c4472011-12-22 14:17:53 +0000493 CriticalSectionScoped cs(map_cs_.get());
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000494 if (capture_id >= kViECaptureIdBase &&
495 capture_id < kViEMaxCaptureDevices + kViECaptureIdBase) {
496 free_capture_device_id_[capture_id - kViECaptureIdBase] = true;
497 }
498 return;
499}
niklase@google.com470e71d2011-07-07 08:21:25 +0000500
mflodman@webrtc.org8baed512012-06-21 12:11:50 +0000501bool ViEInputManager::GetFreeFileId(int* free_file_id) {
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000502 WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo, ViEId(engine_id_), "%s",
niklase@google.com470e71d2011-07-07 08:21:25 +0000503 __FUNCTION__);
504
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000505 for (int id = 0; id < kViEMaxFilePlayers; id++) {
506 if (free_file_id_[id]) {
507 // We found a free capture device id.
508 free_file_id_[id] = false;
mflodman@webrtc.org8baed512012-06-21 12:11:50 +0000509 *free_file_id = id + kViEFileIdBase;
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000510 WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo, ViEId(engine_id_),
mflodman@webrtc.org8baed512012-06-21 12:11:50 +0000511 "%s: new id: %d", __FUNCTION__, *free_file_id);
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000512 return true;
niklase@google.com470e71d2011-07-07 08:21:25 +0000513 }
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000514 }
515 return false;
niklase@google.com470e71d2011-07-07 08:21:25 +0000516}
517
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000518void ViEInputManager::ReturnFileId(int file_id) {
519 WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo, ViEId(engine_id_),
520 "%s(%d)", __FUNCTION__, file_id);
niklase@google.com470e71d2011-07-07 08:21:25 +0000521
mflodman@webrtc.orgd32c4472011-12-22 14:17:53 +0000522 CriticalSectionScoped cs(map_cs_.get());
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000523 if (file_id >= kViEFileIdBase &&
524 file_id < kViEMaxFilePlayers + kViEFileIdBase) {
525 free_file_id_[file_id - kViEFileIdBase] = true;
526 }
527 return;
niklase@google.com470e71d2011-07-07 08:21:25 +0000528}
529
niklase@google.com470e71d2011-07-07 08:21:25 +0000530ViEFrameProviderBase* ViEInputManager::ViEFrameProvider(
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000531 const ViEFrameCallback* capture_observer) const {
532 assert(capture_observer);
mflodman@webrtc.orgd32c4472011-12-22 14:17:53 +0000533 CriticalSectionScoped cs(map_cs_.get());
niklase@google.com470e71d2011-07-07 08:21:25 +0000534
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000535 for (MapItem* provider_item = vie_frame_provider_map_.First(); provider_item
536 != NULL; provider_item = vie_frame_provider_map_.Next(provider_item)) {
537 ViEFrameProviderBase* vie_frame_provider =
538 static_cast<ViEFrameProviderBase*>(provider_item->GetItem());
539 assert(vie_frame_provider != NULL);
niklase@google.com470e71d2011-07-07 08:21:25 +0000540
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000541 if (vie_frame_provider->IsFrameCallbackRegistered(capture_observer)) {
542 // We found it.
543 return vie_frame_provider;
niklase@google.com470e71d2011-07-07 08:21:25 +0000544 }
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000545 }
546 // No capture device set for this channel.
547 return NULL;
548}
549
550ViEFrameProviderBase* ViEInputManager::ViEFrameProvider(int provider_id) const {
mflodman@webrtc.orgd32c4472011-12-22 14:17:53 +0000551 CriticalSectionScoped cs(map_cs_.get());
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000552 MapItem* map_item = vie_frame_provider_map_.Find(provider_id);
553 if (!map_item) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000554 return NULL;
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000555 }
556 ViEFrameProviderBase* vie_frame_provider =
557 static_cast<ViEFrameProviderBase*>(map_item->GetItem());
558 return vie_frame_provider;
niklase@google.com470e71d2011-07-07 08:21:25 +0000559}
560
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000561ViECapturer* ViEInputManager::ViECapturePtr(int capture_id) const {
562 if (!(capture_id >= kViECaptureIdBase &&
563 capture_id <= kViECaptureIdBase + kViEMaxCaptureDevices))
564 return NULL;
niklase@google.com470e71d2011-07-07 08:21:25 +0000565
mflodman@webrtc.orgd32c4472011-12-22 14:17:53 +0000566 CriticalSectionScoped cs(map_cs_.get());
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000567 MapItem* map_item = vie_frame_provider_map_.Find(capture_id);
568 if (!map_item) {
569 return NULL;
570 }
571 ViECapturer* vie_capture = static_cast<ViECapturer*>(map_item->GetItem());
572 return vie_capture;
niklase@google.com470e71d2011-07-07 08:21:25 +0000573}
574
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000575ViEFilePlayer* ViEInputManager::ViEFilePlayerPtr(int file_id) const {
576 if (file_id < kViEFileIdBase || file_id > kViEFileIdMax) {
577 return NULL;
578 }
mflodman@webrtc.orgd32c4472011-12-22 14:17:53 +0000579 CriticalSectionScoped cs(map_cs_.get());
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000580 MapItem* map_item = vie_frame_provider_map_.Find(file_id);
581 if (!map_item) {
582 return NULL;
583 }
584 ViEFilePlayer* vie_file_player =
585 static_cast<ViEFilePlayer*>(map_item->GetItem());
586 return vie_file_player;
niklase@google.com470e71d2011-07-07 08:21:25 +0000587}
588
niklase@google.com470e71d2011-07-07 08:21:25 +0000589ViEInputManagerScoped::ViEInputManagerScoped(
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000590 const ViEInputManager& vie_input_manager)
591 : ViEManagerScopedBase(vie_input_manager) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000592}
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000593
594ViECapturer* ViEInputManagerScoped::Capture(int capture_id) const {
595 return static_cast<const ViEInputManager*>(vie_manager_)->ViECapturePtr(
596 capture_id);
niklase@google.com470e71d2011-07-07 08:21:25 +0000597}
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000598
niklase@google.com470e71d2011-07-07 08:21:25 +0000599ViEFrameProviderBase* ViEInputManagerScoped::FrameProvider(
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000600 const ViEFrameCallback* capture_observer) const {
601 return static_cast<const ViEInputManager*>(vie_manager_)->ViEFrameProvider(
602 capture_observer);
niklase@google.com470e71d2011-07-07 08:21:25 +0000603}
604
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000605ViEFrameProviderBase* ViEInputManagerScoped::FrameProvider(
606 int provider_id) const {
607 return static_cast<const ViEInputManager*>(vie_manager_)->ViEFrameProvider(
608 provider_id);
niklase@google.com470e71d2011-07-07 08:21:25 +0000609}
610
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000611ViEFilePlayer* ViEInputManagerScoped::FilePlayer(int file_id) const {
612 return static_cast<const ViEInputManager*>(vie_manager_)->ViEFilePlayerPtr(
613 file_id);
614}
615
616} // namespace webrtc