blob: f77555746bf630d0f154f64aad276780d64ae702 [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
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +000011#include "video_engine/vie_input_manager.h"
niklase@google.com470e71d2011-07-07 08:21:25 +000012
13#include <cassert>
14
mflodman@webrtc.org8baed512012-06-21 12:11:50 +000015#include "common_types.h" // NOLINT
andrew@webrtc.org94caca72012-10-30 21:58:00 +000016#include "webrtc/modules/video_capture/include/video_capture_factory.h"
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +000017#include "modules/video_coding/main/interface/video_coding.h"
18#include "modules/video_coding/main/interface/video_coding_defines.h"
19#include "system_wrappers/interface/critical_section_wrapper.h"
20#include "system_wrappers/interface/rw_lock_wrapper.h"
21#include "system_wrappers/interface/trace.h"
mflodman@webrtc.orga4863db2011-12-22 08:51:52 +000022#include "video_engine/include/vie_errors.h"
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +000023#include "video_engine/vie_capturer.h"
24#include "video_engine/vie_defines.h"
25#include "video_engine/vie_file_player.h"
26
niklase@google.com470e71d2011-07-07 08:21:25 +000027namespace webrtc {
28
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +000029ViEInputManager::ViEInputManager(const int engine_id)
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 }
pbos@webrtc.org927296f2013-03-08 13:12:29 +000042
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +000043 for (int idx = 0; idx < kViEMaxFilePlayers; idx++) {
44 free_file_id_[idx] = true;
45 }
46}
niklase@google.com470e71d2011-07-07 08:21:25 +000047
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +000048ViEInputManager::~ViEInputManager() {
49 WEBRTC_TRACE(webrtc::kTraceMemory, webrtc::kTraceVideo, ViEId(engine_id_),
50 "%s", __FUNCTION__);
51 while (vie_frame_provider_map_.Size() != 0) {
52 MapItem* item = vie_frame_provider_map_.First();
53 assert(item);
54 ViEFrameProviderBase* frame_provider =
55 static_cast<ViEFrameProviderBase*>(item->GetItem());
56 vie_frame_provider_map_.Erase(item);
57 delete frame_provider;
58 }
59
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +000060 if (capture_device_info_) {
61 delete capture_device_info_;
62 capture_device_info_ = NULL;
63 }
64}
65void ViEInputManager::SetModuleProcessThread(
mflodman@webrtc.org8baed512012-06-21 12:11:50 +000066 ProcessThread* module_process_thread) {
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +000067 assert(!module_process_thread_);
mflodman@webrtc.org8baed512012-06-21 12:11:50 +000068 module_process_thread_ = module_process_thread;
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +000069}
70
71int ViEInputManager::NumberOfCaptureDevices() {
72 WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo, ViEId(engine_id_), "%s",
niklase@google.com470e71d2011-07-07 08:21:25 +000073 __FUNCTION__);
pbos@webrtc.org927296f2013-03-08 13:12:29 +000074 CriticalSectionScoped cs(device_info_cs_.get());
75 if (capture_device_info_ == NULL)
76 capture_device_info_ = VideoCaptureFactory::CreateDeviceInfo(
77 ViEModuleId(engine_id_));
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +000078 assert(capture_device_info_);
79 return capture_device_info_->NumberOfDevices();
niklase@google.com470e71d2011-07-07 08:21:25 +000080}
81
pbos@webrtc.orgb238d122013-04-09 13:41:51 +000082int ViEInputManager::GetDeviceName(uint32_t device_number,
leozwang@webrtc.org1745e932012-03-01 16:30:40 +000083 char* device_nameUTF8,
pbos@webrtc.orgb238d122013-04-09 13:41:51 +000084 uint32_t device_name_length,
leozwang@webrtc.org1745e932012-03-01 16:30:40 +000085 char* device_unique_idUTF8,
pbos@webrtc.orgb238d122013-04-09 13:41:51 +000086 uint32_t device_unique_idUTF8Length) {
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +000087 WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo, ViEId(engine_id_),
88 "%s(device_number: %d)", __FUNCTION__, device_number);
pbos@webrtc.org927296f2013-03-08 13:12:29 +000089 CriticalSectionScoped cs(device_info_cs_.get());
90 if (capture_device_info_ == NULL)
91 capture_device_info_ = VideoCaptureFactory::CreateDeviceInfo(
92 ViEModuleId(engine_id_));
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +000093 assert(capture_device_info_);
94 return capture_device_info_->GetDeviceName(device_number, device_nameUTF8,
95 device_name_length,
96 device_unique_idUTF8,
97 device_unique_idUTF8Length);
niklase@google.com470e71d2011-07-07 08:21:25 +000098}
99
niklase@google.com470e71d2011-07-07 08:21:25 +0000100int ViEInputManager::NumberOfCaptureCapabilities(
leozwang@webrtc.org1745e932012-03-01 16:30:40 +0000101 const char* device_unique_idUTF8) {
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000102 WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo, ViEId(engine_id_), "%s",
niklase@google.com470e71d2011-07-07 08:21:25 +0000103 __FUNCTION__);
pbos@webrtc.org927296f2013-03-08 13:12:29 +0000104 CriticalSectionScoped cs(device_info_cs_.get());
105 if (capture_device_info_ == NULL)
106 capture_device_info_ = VideoCaptureFactory::CreateDeviceInfo(
107 ViEModuleId(engine_id_));
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000108 assert(capture_device_info_);
109 return capture_device_info_->NumberOfCapabilities(device_unique_idUTF8);
niklase@google.com470e71d2011-07-07 08:21:25 +0000110}
111
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000112int ViEInputManager::GetCaptureCapability(
leozwang@webrtc.org1745e932012-03-01 16:30:40 +0000113 const char* device_unique_idUTF8,
pbos@webrtc.orgb238d122013-04-09 13:41:51 +0000114 const uint32_t device_capability_number,
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000115 CaptureCapability& capability) {
116 WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo, ViEId(engine_id_),
117 "%s(device_unique_idUTF8: %s, device_capability_number: %d)",
118 __FUNCTION__, device_unique_idUTF8, device_capability_number);
pbos@webrtc.org927296f2013-03-08 13:12:29 +0000119 CriticalSectionScoped cs(device_info_cs_.get());
120 if (capture_device_info_ == NULL)
121 capture_device_info_ = VideoCaptureFactory::CreateDeviceInfo(
122 ViEModuleId(engine_id_));
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000123 assert(capture_device_info_);
124 VideoCaptureCapability module_capability;
125 int result = capture_device_info_->GetCapability(device_unique_idUTF8,
126 device_capability_number,
127 module_capability);
128 if (result != 0)
niklase@google.com470e71d2011-07-07 08:21:25 +0000129 return result;
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000130
131 // Copy from module type to public type.
132 capability.expectedCaptureDelay = module_capability.expectedCaptureDelay;
133 capability.height = module_capability.height;
134 capability.width = module_capability.width;
135 capability.interlaced = module_capability.interlaced;
136 capability.rawType = module_capability.rawType;
137 capability.codecType = module_capability.codecType;
138 capability.maxFPS = module_capability.maxFPS;
139 return result;
niklase@google.com470e71d2011-07-07 08:21:25 +0000140}
141
leozwang@webrtc.org1745e932012-03-01 16:30:40 +0000142int ViEInputManager::GetOrientation(const char* device_unique_idUTF8,
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000143 RotateCapturedFrame& orientation) {
144 WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo, ViEId(engine_id_),
145 "%s(device_unique_idUTF8: %s,)", __FUNCTION__,
146 device_unique_idUTF8);
pbos@webrtc.org927296f2013-03-08 13:12:29 +0000147 CriticalSectionScoped cs(device_info_cs_.get());
148 if (capture_device_info_ == NULL)
149 capture_device_info_ = VideoCaptureFactory::CreateDeviceInfo(
150 ViEModuleId(engine_id_));
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000151 assert(capture_device_info_);
152 VideoCaptureRotation module_orientation;
153 int result = capture_device_info_->GetOrientation(device_unique_idUTF8,
154 module_orientation);
155 // Copy from module type to public type.
156 switch (module_orientation) {
157 case kCameraRotate0:
158 orientation = RotateCapturedFrame_0;
159 break;
160 case kCameraRotate90:
161 orientation = RotateCapturedFrame_90;
162 break;
163 case kCameraRotate180:
164 orientation = RotateCapturedFrame_180;
165 break;
166 case kCameraRotate270:
167 orientation = RotateCapturedFrame_270;
168 break;
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000169 }
170 return result;
niklase@google.com470e71d2011-07-07 08:21:25 +0000171}
172
niklase@google.com470e71d2011-07-07 08:21:25 +0000173int ViEInputManager::DisplayCaptureSettingsDialogBox(
leozwang@webrtc.org1745e932012-03-01 16:30:40 +0000174 const char* device_unique_idUTF8,
175 const char* dialog_titleUTF8,
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000176 void* parent_window,
pbos@webrtc.orgb238d122013-04-09 13:41:51 +0000177 uint32_t positionX,
178 uint32_t positionY) {
pbos@webrtc.org927296f2013-03-08 13:12:29 +0000179 CriticalSectionScoped cs(device_info_cs_.get());
180 if (capture_device_info_ == NULL)
181 capture_device_info_ = VideoCaptureFactory::CreateDeviceInfo(
182 ViEModuleId(engine_id_));
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000183 assert(capture_device_info_);
184 return capture_device_info_->DisplayCaptureSettingsDialogBox(
185 device_unique_idUTF8, dialog_titleUTF8, parent_window, positionX,
186 positionY);
niklase@google.com470e71d2011-07-07 08:21:25 +0000187}
188
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000189int ViEInputManager::CreateCaptureDevice(
leozwang@webrtc.org1745e932012-03-01 16:30:40 +0000190 const char* device_unique_idUTF8,
pbos@webrtc.orgb238d122013-04-09 13:41:51 +0000191 const uint32_t device_unique_idUTF8Length,
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000192 int& capture_id) {
193 WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo, ViEId(engine_id_),
194 "%s(device_unique_id: %s)", __FUNCTION__, device_unique_idUTF8);
mflodman@webrtc.orgd32c4472011-12-22 14:17:53 +0000195 CriticalSectionScoped cs(map_cs_.get());
niklase@google.com470e71d2011-07-07 08:21:25 +0000196
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000197 // Make sure the device is not already allocated.
198 for (MapItem* item = vie_frame_provider_map_.First(); item != NULL;
199 item = vie_frame_provider_map_.Next(item)) {
200 // Make sure this is a capture device.
201 if (item->GetId() >= kViECaptureIdBase &&
202 item->GetId() <= kViECaptureIdMax) {
203 ViECapturer* vie_capture = static_cast<ViECapturer*>(item->GetItem());
204 assert(vie_capture);
205 // TODO(mflodman) Can we change input to avoid this cast?
206 const char* device_name =
207 reinterpret_cast<const char*>(vie_capture->CurrentDeviceName());
208 if (strncmp(device_name,
209 reinterpret_cast<const char*>(device_unique_idUTF8),
210 strlen(device_name)) == 0) {
211 return kViECaptureDeviceAlreadyAllocated;
212 }
213 }
214 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000215
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000216 // Make sure the device name is valid.
217 bool found_device = false;
pbos@webrtc.org927296f2013-03-08 13:12:29 +0000218 CriticalSectionScoped cs_devinfo(device_info_cs_.get());
219 if (capture_device_info_ == NULL)
220 capture_device_info_ = VideoCaptureFactory::CreateDeviceInfo(
221 ViEModuleId(engine_id_));
222 assert(capture_device_info_);
pbos@webrtc.orgb238d122013-04-09 13:41:51 +0000223 for (uint32_t device_index = 0;
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000224 device_index < capture_device_info_->NumberOfDevices(); ++device_index) {
225 if (device_unique_idUTF8Length > kVideoCaptureUniqueNameLength) {
226 // User's string length is longer than the max.
227 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +0000228 }
229
leozwang@webrtc.org1745e932012-03-01 16:30:40 +0000230 char found_name[kVideoCaptureDeviceNameLength] = "";
231 char found_unique_name[kVideoCaptureUniqueNameLength] = "";
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000232 capture_device_info_->GetDeviceName(device_index, found_name,
233 kVideoCaptureDeviceNameLength,
234 found_unique_name,
235 kVideoCaptureUniqueNameLength);
236
237 // TODO(mflodman) Can we change input to avoid this cast?
238 const char* cast_id = reinterpret_cast<const char*>(device_unique_idUTF8);
239 if (strncmp(cast_id, reinterpret_cast<const char*>(found_unique_name),
240 strlen(cast_id)) == 0) {
241 WEBRTC_TRACE(webrtc::kTraceDebug, webrtc::kTraceVideo, ViEId(engine_id_),
242 "%s:%d Capture device was found by unique ID: %s. Returning",
243 __FUNCTION__, __LINE__, device_unique_idUTF8);
244 found_device = true;
245 break;
niklase@google.com470e71d2011-07-07 08:21:25 +0000246 }
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000247 }
248 if (!found_device) {
249 WEBRTC_TRACE(webrtc::kTraceDebug, webrtc::kTraceVideo, ViEId(engine_id_),
250 "%s:%d Capture device NOT found by unique ID: %s. Returning",
251 __FUNCTION__, __LINE__, device_unique_idUTF8);
252 return kViECaptureDeviceDoesNotExist;
253 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000254
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000255 int newcapture_id = 0;
mflodman@webrtc.org8baed512012-06-21 12:11:50 +0000256 if (GetFreeCaptureId(&newcapture_id) == false) {
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000257 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo, ViEId(engine_id_),
258 "%s: Maximum supported number of capture devices already in "
259 "use", __FUNCTION__);
260 return kViECaptureDeviceMaxNoDevicesAllocated;
261 }
262 ViECapturer* vie_capture = ViECapturer::CreateViECapture(
263 newcapture_id, engine_id_, device_unique_idUTF8,
264 device_unique_idUTF8Length, *module_process_thread_);
265 if (!vie_capture) {
266 ReturnCaptureId(newcapture_id);
267 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo, ViEId(engine_id_),
268 "%s: Could not create capture module for %s", __FUNCTION__,
269 device_unique_idUTF8);
270 return kViECaptureDeviceUnknownError;
271 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000272
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000273 if (vie_frame_provider_map_.Insert(newcapture_id, vie_capture) != 0) {
274 ReturnCaptureId(newcapture_id);
275 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo, ViEId(engine_id_),
276 "%s: Could not insert capture module for %s", __FUNCTION__,
277 device_unique_idUTF8);
278 return kViECaptureDeviceUnknownError;
279 }
280 capture_id = newcapture_id;
281 WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo, ViEId(engine_id_),
282 "%s(device_unique_id: %s, capture_id: %d)", __FUNCTION__,
283 device_unique_idUTF8, capture_id);
284 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000285}
286
mflodman@webrtc.org8baed512012-06-21 12:11:50 +0000287int ViEInputManager::CreateCaptureDevice(VideoCaptureModule* capture_module,
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000288 int& capture_id) {
289 WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo, ViEId(engine_id_), "%s",
niklase@google.com470e71d2011-07-07 08:21:25 +0000290 __FUNCTION__);
niklase@google.com470e71d2011-07-07 08:21:25 +0000291
mflodman@webrtc.orgd32c4472011-12-22 14:17:53 +0000292 CriticalSectionScoped cs(map_cs_.get());
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000293 int newcapture_id = 0;
mflodman@webrtc.org8baed512012-06-21 12:11:50 +0000294 if (!GetFreeCaptureId(&newcapture_id)) {
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000295 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo, ViEId(engine_id_),
296 "%s: Maximum supported number of capture devices already in "
297 "use", __FUNCTION__);
298 return kViECaptureDeviceMaxNoDevicesAllocated;
299 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000300
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000301 ViECapturer* vie_capture = ViECapturer::CreateViECapture(
302 newcapture_id, engine_id_, capture_module, *module_process_thread_);
303 if (!vie_capture) {
304 ReturnCaptureId(newcapture_id);
305 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo, ViEId(engine_id_),
306 "%s: Could attach capture module.", __FUNCTION__);
307 return kViECaptureDeviceUnknownError;
308 }
309 if (vie_frame_provider_map_.Insert(newcapture_id, vie_capture) != 0) {
310 ReturnCaptureId(newcapture_id);
311 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo, ViEId(engine_id_),
312 "%s: Could not insert capture module", __FUNCTION__);
313 return kViECaptureDeviceUnknownError;
314 }
315 capture_id = newcapture_id;
316 WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo, ViEId(engine_id_),
317 "%s, capture_id: %d", __FUNCTION__, capture_id);
318 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000319}
320
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000321int ViEInputManager::DestroyCaptureDevice(const int capture_id) {
322 WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo, ViEId(engine_id_),
323 "%s(capture_id: %d)", __FUNCTION__, capture_id);
324 ViECapturer* vie_capture = NULL;
325 {
326 // We need exclusive access to the object to delete it.
327 // Take this write lock first since the read lock is taken before map_cs_.
mflodman@webrtc.orgcee447a2012-06-28 07:29:46 +0000328 ViEManagerWriteScoped wl(this);
mflodman@webrtc.orgd32c4472011-12-22 14:17:53 +0000329 CriticalSectionScoped cs(map_cs_.get());
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000330
331 vie_capture = ViECapturePtr(capture_id);
332 if (!vie_capture) {
333 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo, ViEId(engine_id_),
334 "%s(capture_id: %d) - No such capture device id",
335 __FUNCTION__, capture_id);
336 return -1;
337 }
pbos@webrtc.orgb238d122013-04-09 13:41:51 +0000338 uint32_t num_callbacks =
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000339 vie_capture->NumberOfRegisteredFrameCallbacks();
340 if (num_callbacks > 0) {
341 WEBRTC_TRACE(webrtc::kTraceWarning, webrtc::kTraceVideo,
342 ViEId(engine_id_), "%s(capture_id: %d) - %u registered "
343 "callbacks when destroying capture device",
344 __FUNCTION__, capture_id, num_callbacks);
345 }
346 vie_frame_provider_map_.Erase(capture_id);
347 ReturnCaptureId(capture_id);
348 // Leave cs before deleting the capture object. This is because deleting the
349 // object might cause deletions of renderers so we prefer to not have a lock
350 // at that time.
351 }
352 delete vie_capture;
353 return 0;
354}
355
356int ViEInputManager::CreateExternalCaptureDevice(
357 ViEExternalCapture*& external_capture,
358 int& capture_id) {
359 WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo, ViEId(engine_id_), "%s",
360 __FUNCTION__);
mflodman@webrtc.orgd32c4472011-12-22 14:17:53 +0000361 CriticalSectionScoped cs(map_cs_.get());
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000362
363 int newcapture_id = 0;
mflodman@webrtc.org8baed512012-06-21 12:11:50 +0000364 if (GetFreeCaptureId(&newcapture_id) == false) {
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000365 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo, ViEId(engine_id_),
366 "%s: Maximum supported number of capture devices already in "
367 "use", __FUNCTION__);
368 return kViECaptureDeviceMaxNoDevicesAllocated;
369 }
370
371 ViECapturer* vie_capture = ViECapturer::CreateViECapture(
372 newcapture_id, engine_id_, NULL, 0, *module_process_thread_);
373 if (!vie_capture) {
374 ReturnCaptureId(newcapture_id);
375 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo, ViEId(engine_id_),
376 "%s: Could not create capture module for external capture.",
377 __FUNCTION__);
378 return kViECaptureDeviceUnknownError;
379 }
380
381 if (vie_frame_provider_map_.Insert(newcapture_id, vie_capture) != 0) {
382 ReturnCaptureId(newcapture_id);
383 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo, ViEId(engine_id_),
384 "%s: Could not insert capture module for external capture.",
385 __FUNCTION__);
386 return kViECaptureDeviceUnknownError;
387 }
388 capture_id = newcapture_id;
389 external_capture = vie_capture;
390 WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo, ViEId(engine_id_),
391 "%s, capture_id: %d)", __FUNCTION__, capture_id);
392 return 0;
393}
394
leozwang@webrtc.org1745e932012-03-01 16:30:40 +0000395int ViEInputManager::CreateFilePlayer(const char* file_nameUTF8,
niklase@google.com470e71d2011-07-07 08:21:25 +0000396 const bool loop,
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000397 const webrtc::FileFormats file_format,
398 VoiceEngine* voe_ptr, int& file_id) {
399 WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo, ViEId(engine_id_),
400 "%s(device_unique_id: %s)", __FUNCTION__, file_nameUTF8);
niklase@google.com470e71d2011-07-07 08:21:25 +0000401
mflodman@webrtc.orgd32c4472011-12-22 14:17:53 +0000402 CriticalSectionScoped cs(map_cs_.get());
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000403 int new_file_id = 0;
mflodman@webrtc.org8baed512012-06-21 12:11:50 +0000404 if (GetFreeFileId(&new_file_id) == false) {
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000405 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo, ViEId(engine_id_),
406 "%s: Maximum supported number of file players already in use",
407 __FUNCTION__);
408 return kViEFileMaxNoOfFilesOpened;
409 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000410
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000411 ViEFilePlayer* vie_file_player = ViEFilePlayer::CreateViEFilePlayer(
mflodman@webrtc.org8baed512012-06-21 12:11:50 +0000412 new_file_id, engine_id_, file_nameUTF8, loop, file_format, voe_ptr);
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000413 if (!vie_file_player) {
414 ReturnFileId(new_file_id);
415 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo, ViEId(engine_id_),
416 "%s: Could not open file %s for playback", __FUNCTION__,
417 file_nameUTF8);
418 return kViEFileUnknownError;
419 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000420
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000421 if (vie_frame_provider_map_.Insert(new_file_id, vie_file_player) != 0) {
422 ReturnCaptureId(new_file_id);
423 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo, ViEId(engine_id_),
424 "%s: Could not insert file player for %s", __FUNCTION__,
425 file_nameUTF8);
426 delete vie_file_player;
427 return kViEFileUnknownError;
428 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000429
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000430 file_id = new_file_id;
431 WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo, ViEId(engine_id_),
432 "%s(filename: %s, file_id: %d)", __FUNCTION__, file_nameUTF8,
433 new_file_id);
434 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000435}
436
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000437int ViEInputManager::DestroyFilePlayer(int file_id) {
438 WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo, ViEId(engine_id_),
439 "%s(file_id: %d)", __FUNCTION__, file_id);
niklase@google.com470e71d2011-07-07 08:21:25 +0000440
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000441 ViEFilePlayer* vie_file_player = NULL;
442 {
443 // We need exclusive access to the object to delete it.
444 // Take this write lock first since the read lock is taken before map_cs_.
mflodman@webrtc.orgcee447a2012-06-28 07:29:46 +0000445 ViEManagerWriteScoped wl(this);
niklase@google.com470e71d2011-07-07 08:21:25 +0000446
mflodman@webrtc.orgd32c4472011-12-22 14:17:53 +0000447 CriticalSectionScoped cs(map_cs_.get());
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000448 vie_file_player = ViEFilePlayerPtr(file_id);
449 if (!vie_file_player) {
450 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo, ViEId(engine_id_),
451 "%s(file_id: %d) - No such file player", __FUNCTION__,
452 file_id);
453 return -1;
454 }
455 int num_callbacks = vie_file_player->NumberOfRegisteredFrameCallbacks();
456 if (num_callbacks > 0) {
457 WEBRTC_TRACE(webrtc::kTraceWarning, webrtc::kTraceVideo,
458 ViEId(engine_id_), "%s(file_id: %d) - %u registered "
459 "callbacks when destroying file player", __FUNCTION__,
460 file_id, num_callbacks);
461 }
462 vie_frame_provider_map_.Erase(file_id);
463 ReturnFileId(file_id);
464 // Leave cs before deleting the file object. This is because deleting the
465 // object might cause deletions of renderers so we prefer to not have a lock
466 // at that time.
467 }
468 delete vie_file_player;
469 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000470}
471
mflodman@webrtc.org8baed512012-06-21 12:11:50 +0000472bool ViEInputManager::GetFreeCaptureId(int* freecapture_id) {
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000473 WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo, ViEId(engine_id_), "%s",
474 __FUNCTION__);
475 for (int id = 0; id < kViEMaxCaptureDevices; id++) {
476 if (free_capture_device_id_[id]) {
477 // We found a free capture device id.
478 free_capture_device_id_[id] = false;
mflodman@webrtc.org8baed512012-06-21 12:11:50 +0000479 *freecapture_id = id + kViECaptureIdBase;
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000480 WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo, ViEId(engine_id_),
mflodman@webrtc.org8baed512012-06-21 12:11:50 +0000481 "%s: new id: %d", __FUNCTION__, *freecapture_id);
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000482 return true;
483 }
484 }
485 return false;
486}
niklase@google.com470e71d2011-07-07 08:21:25 +0000487
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000488void ViEInputManager::ReturnCaptureId(int capture_id) {
489 WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo, ViEId(engine_id_),
490 "%s(%d)", __FUNCTION__, capture_id);
mflodman@webrtc.orgd32c4472011-12-22 14:17:53 +0000491 CriticalSectionScoped cs(map_cs_.get());
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000492 if (capture_id >= kViECaptureIdBase &&
493 capture_id < kViEMaxCaptureDevices + kViECaptureIdBase) {
494 free_capture_device_id_[capture_id - kViECaptureIdBase] = true;
495 }
496 return;
497}
niklase@google.com470e71d2011-07-07 08:21:25 +0000498
mflodman@webrtc.org8baed512012-06-21 12:11:50 +0000499bool ViEInputManager::GetFreeFileId(int* free_file_id) {
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000500 WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo, ViEId(engine_id_), "%s",
niklase@google.com470e71d2011-07-07 08:21:25 +0000501 __FUNCTION__);
502
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000503 for (int id = 0; id < kViEMaxFilePlayers; id++) {
504 if (free_file_id_[id]) {
505 // We found a free capture device id.
506 free_file_id_[id] = false;
mflodman@webrtc.org8baed512012-06-21 12:11:50 +0000507 *free_file_id = id + kViEFileIdBase;
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000508 WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo, ViEId(engine_id_),
mflodman@webrtc.org8baed512012-06-21 12:11:50 +0000509 "%s: new id: %d", __FUNCTION__, *free_file_id);
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000510 return true;
niklase@google.com470e71d2011-07-07 08:21:25 +0000511 }
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000512 }
513 return false;
niklase@google.com470e71d2011-07-07 08:21:25 +0000514}
515
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000516void ViEInputManager::ReturnFileId(int file_id) {
517 WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo, ViEId(engine_id_),
518 "%s(%d)", __FUNCTION__, file_id);
niklase@google.com470e71d2011-07-07 08:21:25 +0000519
mflodman@webrtc.orgd32c4472011-12-22 14:17:53 +0000520 CriticalSectionScoped cs(map_cs_.get());
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000521 if (file_id >= kViEFileIdBase &&
522 file_id < kViEMaxFilePlayers + kViEFileIdBase) {
523 free_file_id_[file_id - kViEFileIdBase] = true;
524 }
525 return;
niklase@google.com470e71d2011-07-07 08:21:25 +0000526}
527
niklase@google.com470e71d2011-07-07 08:21:25 +0000528ViEFrameProviderBase* ViEInputManager::ViEFrameProvider(
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000529 const ViEFrameCallback* capture_observer) const {
530 assert(capture_observer);
mflodman@webrtc.orgd32c4472011-12-22 14:17:53 +0000531 CriticalSectionScoped cs(map_cs_.get());
niklase@google.com470e71d2011-07-07 08:21:25 +0000532
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000533 for (MapItem* provider_item = vie_frame_provider_map_.First(); provider_item
534 != NULL; provider_item = vie_frame_provider_map_.Next(provider_item)) {
535 ViEFrameProviderBase* vie_frame_provider =
536 static_cast<ViEFrameProviderBase*>(provider_item->GetItem());
537 assert(vie_frame_provider != NULL);
niklase@google.com470e71d2011-07-07 08:21:25 +0000538
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000539 if (vie_frame_provider->IsFrameCallbackRegistered(capture_observer)) {
540 // We found it.
541 return vie_frame_provider;
niklase@google.com470e71d2011-07-07 08:21:25 +0000542 }
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000543 }
544 // No capture device set for this channel.
545 return NULL;
546}
547
548ViEFrameProviderBase* ViEInputManager::ViEFrameProvider(int provider_id) const {
mflodman@webrtc.orgd32c4472011-12-22 14:17:53 +0000549 CriticalSectionScoped cs(map_cs_.get());
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000550 MapItem* map_item = vie_frame_provider_map_.Find(provider_id);
551 if (!map_item) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000552 return NULL;
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000553 }
554 ViEFrameProviderBase* vie_frame_provider =
555 static_cast<ViEFrameProviderBase*>(map_item->GetItem());
556 return vie_frame_provider;
niklase@google.com470e71d2011-07-07 08:21:25 +0000557}
558
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000559ViECapturer* ViEInputManager::ViECapturePtr(int capture_id) const {
560 if (!(capture_id >= kViECaptureIdBase &&
561 capture_id <= kViECaptureIdBase + kViEMaxCaptureDevices))
562 return NULL;
niklase@google.com470e71d2011-07-07 08:21:25 +0000563
mflodman@webrtc.orgd32c4472011-12-22 14:17:53 +0000564 CriticalSectionScoped cs(map_cs_.get());
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000565 MapItem* map_item = vie_frame_provider_map_.Find(capture_id);
566 if (!map_item) {
567 return NULL;
568 }
569 ViECapturer* vie_capture = static_cast<ViECapturer*>(map_item->GetItem());
570 return vie_capture;
niklase@google.com470e71d2011-07-07 08:21:25 +0000571}
572
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000573ViEFilePlayer* ViEInputManager::ViEFilePlayerPtr(int file_id) const {
574 if (file_id < kViEFileIdBase || file_id > kViEFileIdMax) {
575 return NULL;
576 }
mflodman@webrtc.orgd32c4472011-12-22 14:17:53 +0000577 CriticalSectionScoped cs(map_cs_.get());
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000578 MapItem* map_item = vie_frame_provider_map_.Find(file_id);
579 if (!map_item) {
580 return NULL;
581 }
582 ViEFilePlayer* vie_file_player =
583 static_cast<ViEFilePlayer*>(map_item->GetItem());
584 return vie_file_player;
niklase@google.com470e71d2011-07-07 08:21:25 +0000585}
586
niklase@google.com470e71d2011-07-07 08:21:25 +0000587ViEInputManagerScoped::ViEInputManagerScoped(
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000588 const ViEInputManager& vie_input_manager)
589 : ViEManagerScopedBase(vie_input_manager) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000590}
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000591
592ViECapturer* ViEInputManagerScoped::Capture(int capture_id) const {
593 return static_cast<const ViEInputManager*>(vie_manager_)->ViECapturePtr(
594 capture_id);
niklase@google.com470e71d2011-07-07 08:21:25 +0000595}
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000596
niklase@google.com470e71d2011-07-07 08:21:25 +0000597ViEFrameProviderBase* ViEInputManagerScoped::FrameProvider(
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000598 const ViEFrameCallback* capture_observer) const {
599 return static_cast<const ViEInputManager*>(vie_manager_)->ViEFrameProvider(
600 capture_observer);
niklase@google.com470e71d2011-07-07 08:21:25 +0000601}
602
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000603ViEFrameProviderBase* ViEInputManagerScoped::FrameProvider(
604 int provider_id) const {
605 return static_cast<const ViEInputManager*>(vie_manager_)->ViEFrameProvider(
606 provider_id);
niklase@google.com470e71d2011-07-07 08:21:25 +0000607}
608
mflodman@webrtc.orge8be22c2011-12-15 10:19:29 +0000609ViEFilePlayer* ViEInputManagerScoped::FilePlayer(int file_id) const {
610 return static_cast<const ViEInputManager*>(vie_manager_)->ViEFilePlayerPtr(
611 file_id);
612}
613
614} // namespace webrtc