1 /* 2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. 3 * 4 * Use of this source code is governed by a BSD-style license 5 * that can be found in the LICENSE file in the root of the source 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 11 #include "webrtc/video_engine/vie_capture_impl.h" 12 13 #include <map> 14 15 #include "webrtc/system_wrappers/interface/logging.h" 16 #include "webrtc/video_engine/include/vie_errors.h" 17 #include "webrtc/video_engine/vie_capturer.h" 18 #include "webrtc/video_engine/vie_channel.h" 19 #include "webrtc/video_engine/vie_channel_manager.h" 20 #include "webrtc/video_engine/vie_defines.h" 21 #include "webrtc/video_engine/vie_encoder.h" 22 #include "webrtc/video_engine/vie_impl.h" 23 #include "webrtc/video_engine/vie_input_manager.h" 24 #include "webrtc/video_engine/vie_shared_data.h" 25 26 namespace webrtc { 27 28 class CpuOveruseObserver; 29 30 ViECapture* ViECapture::GetInterface(VideoEngine* video_engine) { 31 #ifdef WEBRTC_VIDEO_ENGINE_CAPTURE_API 32 if (!video_engine) { 33 return NULL; 34 } 35 VideoEngineImpl* vie_impl = static_cast<VideoEngineImpl*>(video_engine); 36 ViECaptureImpl* vie_capture_impl = vie_impl; 37 // Increase ref count. 38 (*vie_capture_impl)++; 39 return vie_capture_impl; 40 #else 41 return NULL; 42 #endif 43 } 44 45 int ViECaptureImpl::Release() { 46 // Decrease ref count 47 (*this)--; 48 49 int32_t ref_count = GetCount(); 50 if (ref_count < 0) { 51 LOG(LS_WARNING) << "ViECapture released too many times."; 52 shared_data_->SetLastError(kViEAPIDoesNotExist); 53 return -1; 54 } 55 return ref_count; 56 } 57 58 ViECaptureImpl::ViECaptureImpl(ViESharedData* shared_data) 59 : shared_data_(shared_data) {} 60 61 ViECaptureImpl::~ViECaptureImpl() {} 62 63 int ViECaptureImpl::NumberOfCaptureDevices() { 64 return shared_data_->input_manager()->NumberOfCaptureDevices(); 65 } 66 67 68 int ViECaptureImpl::GetCaptureDevice(unsigned int list_number, 69 char* device_nameUTF8, 70 unsigned int device_nameUTF8Length, 71 char* unique_idUTF8, 72 unsigned int unique_idUTF8Length) { 73 return shared_data_->input_manager()->GetDeviceName( 74 list_number, 75 device_nameUTF8, device_nameUTF8Length, 76 unique_idUTF8, unique_idUTF8Length); 77 } 78 79 int ViECaptureImpl::AllocateCaptureDevice( 80 const char* unique_idUTF8, 81 const unsigned int unique_idUTF8Length, 82 int& capture_id) { 83 LOG(LS_INFO) << "AllocateCaptureDevice " << unique_idUTF8; 84 const int32_t result = 85 shared_data_->input_manager()->CreateCaptureDevice( 86 unique_idUTF8, 87 static_cast<const uint32_t>(unique_idUTF8Length), 88 capture_id); 89 if (result != 0) { 90 shared_data_->SetLastError(result); 91 return -1; 92 } 93 return 0; 94 } 95 96 int ViECaptureImpl::AllocateExternalCaptureDevice( 97 int& capture_id, ViEExternalCapture*& external_capture) { 98 const int32_t result = 99 shared_data_->input_manager()->CreateExternalCaptureDevice( 100 external_capture, capture_id); 101 102 if (result != 0) { 103 shared_data_->SetLastError(result); 104 return -1; 105 } 106 LOG(LS_INFO) << "External capture device allocated: " << capture_id; 107 return 0; 108 } 109 110 int ViECaptureImpl::AllocateCaptureDevice( 111 VideoCaptureModule& capture_module, int& capture_id) { // NOLINT 112 int32_t result = shared_data_->input_manager()->CreateCaptureDevice( 113 &capture_module, capture_id); 114 if (result != 0) { 115 shared_data_->SetLastError(result); 116 return -1; 117 } 118 LOG(LS_INFO) << "External capture device, by module, allocated: " 119 << capture_id; 120 return 0; 121 } 122 123 124 int ViECaptureImpl::ReleaseCaptureDevice(const int capture_id) { 125 LOG(LS_INFO) << "ReleaseCaptureDevice " << capture_id; 126 { 127 ViEInputManagerScoped is((*(shared_data_->input_manager()))); 128 ViECapturer* vie_capture = is.Capture(capture_id); 129 if (!vie_capture) { 130 shared_data_->SetLastError(kViECaptureDeviceDoesNotExist); 131 return -1; 132 } 133 } 134 return shared_data_->input_manager()->DestroyCaptureDevice(capture_id); 135 } 136 137 int ViECaptureImpl::ConnectCaptureDevice(const int capture_id, 138 const int video_channel) { 139 LOG(LS_INFO) << "Connect capture id " << capture_id 140 << " to channel " << video_channel; 141 142 ViEInputManagerScoped is(*(shared_data_->input_manager())); 143 ViECapturer* vie_capture = is.Capture(capture_id); 144 if (!vie_capture) { 145 shared_data_->SetLastError(kViECaptureDeviceDoesNotExist); 146 return -1; 147 } 148 149 ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); 150 ViEEncoder* vie_encoder = cs.Encoder(video_channel); 151 if (!vie_encoder) { 152 LOG(LS_ERROR) << "Channel doesn't exist."; 153 shared_data_->SetLastError(kViECaptureDeviceInvalidChannelId); 154 return -1; 155 } 156 if (vie_encoder->Owner() != video_channel) { 157 LOG(LS_ERROR) << "Can't connect capture device to a receive device."; 158 shared_data_->SetLastError(kViECaptureDeviceInvalidChannelId); 159 return -1; 160 } 161 // Check if the encoder already has a connected frame provider 162 if (is.FrameProvider(vie_encoder) != NULL) { 163 LOG(LS_ERROR) << "Channel already connected to capture device."; 164 shared_data_->SetLastError(kViECaptureDeviceAlreadyConnected); 165 return -1; 166 } 167 if (vie_capture->RegisterFrameCallback(video_channel, vie_encoder) != 0) { 168 shared_data_->SetLastError(kViECaptureDeviceUnknownError); 169 return -1; 170 } 171 std::map<int, CpuOveruseObserver*>::iterator it = 172 shared_data_->overuse_observers()->find(video_channel); 173 if (it != shared_data_->overuse_observers()->end()) { 174 vie_capture->RegisterCpuOveruseObserver(it->second); 175 } 176 return 0; 177 } 178 179 180 int ViECaptureImpl::DisconnectCaptureDevice(const int video_channel) { 181 LOG(LS_INFO) << "DisconnectCaptureDevice " << video_channel; 182 183 ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); 184 ViEEncoder* vie_encoder = cs.Encoder(video_channel); 185 if (!vie_encoder) { 186 LOG(LS_ERROR) << "Channel doesn't exist."; 187 shared_data_->SetLastError(kViECaptureDeviceInvalidChannelId); 188 return -1; 189 } 190 191 ViEInputManagerScoped is(*(shared_data_->input_manager())); 192 ViEFrameProviderBase* frame_provider = is.FrameProvider(vie_encoder); 193 if (!frame_provider) { 194 shared_data_->SetLastError(kViECaptureDeviceNotConnected); 195 return -1; 196 } 197 if (frame_provider->Id() < kViECaptureIdBase || 198 frame_provider->Id() > kViECaptureIdMax) { 199 shared_data_->SetLastError(kViECaptureDeviceNotConnected); 200 return -1; 201 } 202 203 ViECapturer* vie_capture = is.Capture(frame_provider->Id()); 204 assert(vie_capture); 205 vie_capture->RegisterCpuOveruseObserver(NULL); 206 if (frame_provider->DeregisterFrameCallback(vie_encoder) != 0) { 207 shared_data_->SetLastError(kViECaptureDeviceUnknownError); 208 return -1; 209 } 210 211 return 0; 212 } 213 214 int ViECaptureImpl::StartCapture(const int capture_id, 215 const CaptureCapability& capture_capability) { 216 LOG(LS_INFO) << "StartCapture " << capture_id; 217 218 ViEInputManagerScoped is(*(shared_data_->input_manager())); 219 ViECapturer* vie_capture = is.Capture(capture_id); 220 if (!vie_capture) { 221 shared_data_->SetLastError(kViECaptureDeviceDoesNotExist); 222 return -1; 223 } 224 if (vie_capture->Started()) { 225 shared_data_->SetLastError(kViECaptureDeviceAlreadyStarted); 226 return -1; 227 } 228 if (vie_capture->Start(capture_capability) != 0) { 229 shared_data_->SetLastError(kViECaptureDeviceUnknownError); 230 return -1; 231 } 232 return 0; 233 } 234 235 int ViECaptureImpl::StopCapture(const int capture_id) { 236 LOG(LS_INFO) << "StopCapture " << capture_id; 237 238 ViEInputManagerScoped is(*(shared_data_->input_manager())); 239 ViECapturer* vie_capture = is.Capture(capture_id); 240 if (!vie_capture) { 241 shared_data_->SetLastError(kViECaptureDeviceDoesNotExist); 242 return -1; 243 } 244 if (!vie_capture->Started()) { 245 shared_data_->SetLastError(kViECaptureDeviceNotStarted); 246 return 0; 247 } 248 if (vie_capture->Stop() != 0) { 249 shared_data_->SetLastError(kViECaptureDeviceUnknownError); 250 return -1; 251 } 252 return 0; 253 } 254 255 int ViECaptureImpl::SetRotateCapturedFrames( 256 const int capture_id, 257 const RotateCapturedFrame rotation) { 258 int i_rotation = -1; 259 switch (rotation) { 260 case RotateCapturedFrame_0: 261 i_rotation = 0; 262 break; 263 case RotateCapturedFrame_90: 264 i_rotation = 90; 265 break; 266 case RotateCapturedFrame_180: 267 i_rotation = 180; 268 break; 269 case RotateCapturedFrame_270: 270 i_rotation = 270; 271 break; 272 } 273 LOG(LS_INFO) << "SetRotateCaptureFrames for " << capture_id 274 << ", rotation " << i_rotation; 275 276 ViEInputManagerScoped is(*(shared_data_->input_manager())); 277 ViECapturer* vie_capture = is.Capture(capture_id); 278 if (!vie_capture) { 279 shared_data_->SetLastError(kViECaptureDeviceDoesNotExist); 280 return -1; 281 } 282 if (vie_capture->SetRotateCapturedFrames(rotation) != 0) { 283 shared_data_->SetLastError(kViECaptureDeviceUnknownError); 284 return -1; 285 } 286 return 0; 287 } 288 289 int ViECaptureImpl::SetCaptureDelay(const int capture_id, 290 const unsigned int capture_delay_ms) { 291 LOG(LS_INFO) << "SetCaptureDelay " << capture_delay_ms 292 << ", for device " << capture_id; 293 294 ViEInputManagerScoped is(*(shared_data_->input_manager())); 295 ViECapturer* vie_capture = is.Capture(capture_id); 296 if (!vie_capture) { 297 shared_data_->SetLastError(kViECaptureDeviceDoesNotExist); 298 return -1; 299 } 300 301 if (vie_capture->SetCaptureDelay(capture_delay_ms) != 0) { 302 shared_data_->SetLastError(kViECaptureDeviceUnknownError); 303 return -1; 304 } 305 return 0; 306 } 307 308 int ViECaptureImpl::NumberOfCapabilities( 309 const char* unique_idUTF8, 310 const unsigned int unique_idUTF8Length) { 311 312 #if defined(WEBRTC_MAC) 313 // TODO(mflodman) Move to capture module! 314 // QTKit framework handles all capabilities and capture settings 315 // automatically (mandatory). 316 // Thus this function cannot be supported on the Mac platform. 317 shared_data_->SetLastError(kViECaptureDeviceMacQtkitNotSupported); 318 LOG_F(LS_ERROR) << "API not supported on Mac OS X."; 319 return -1; 320 #endif 321 return shared_data_->input_manager()->NumberOfCaptureCapabilities( 322 unique_idUTF8); 323 } 324 325 326 int ViECaptureImpl::GetCaptureCapability(const char* unique_idUTF8, 327 const unsigned int unique_idUTF8Length, 328 const unsigned int capability_number, 329 CaptureCapability& capability) { 330 331 #if defined(WEBRTC_MAC) 332 // TODO(mflodman) Move to capture module! 333 // QTKit framework handles all capabilities and capture settings 334 // automatically (mandatory). 335 // Thus this function cannot be supported on the Mac platform. 336 LOG_F(LS_ERROR) << "API not supported on Mac OS X."; 337 shared_data_->SetLastError(kViECaptureDeviceMacQtkitNotSupported); 338 return -1; 339 #endif 340 if (shared_data_->input_manager()->GetCaptureCapability( 341 unique_idUTF8, capability_number, capability) != 0) { 342 shared_data_->SetLastError(kViECaptureDeviceUnknownError); 343 return -1; 344 } 345 return 0; 346 } 347 348 int ViECaptureImpl::ShowCaptureSettingsDialogBox( 349 const char* unique_idUTF8, 350 const unsigned int unique_idUTF8Length, 351 const char* dialog_title, 352 void* parent_window, 353 const unsigned int x, 354 const unsigned int y) { 355 #if defined(WEBRTC_MAC) 356 // TODO(mflodman) Move to capture module 357 // QTKit framework handles all capabilities and capture settings 358 // automatically (mandatory). 359 // Thus this function cannot be supported on the Mac platform. 360 shared_data_->SetLastError(kViECaptureDeviceMacQtkitNotSupported); 361 LOG_F(LS_ERROR) << "API not supported on Mac OS X."; 362 return -1; 363 #endif 364 return shared_data_->input_manager()->DisplayCaptureSettingsDialogBox( 365 unique_idUTF8, dialog_title, 366 parent_window, x, y); 367 } 368 369 int ViECaptureImpl::GetOrientation(const char* unique_idUTF8, 370 RotateCapturedFrame& orientation) { 371 if (shared_data_->input_manager()->GetOrientation( 372 unique_idUTF8, 373 orientation) != 0) { 374 shared_data_->SetLastError(kViECaptureDeviceUnknownError); 375 return -1; 376 } 377 return 0; 378 } 379 380 381 int ViECaptureImpl::EnableBrightnessAlarm(const int capture_id, 382 const bool enable) { 383 LOG(LS_INFO) << "EnableBrightnessAlarm for device " << capture_id 384 << ", status " << enable; 385 ViEInputManagerScoped is(*(shared_data_->input_manager())); 386 ViECapturer* vie_capture = is.Capture(capture_id); 387 if (!vie_capture) { 388 shared_data_->SetLastError(kViECaptureDeviceDoesNotExist); 389 return -1; 390 } 391 if (vie_capture->EnableBrightnessAlarm(enable) != 0) { 392 shared_data_->SetLastError(kViECaptureDeviceUnknownError); 393 return -1; 394 } 395 return 0; 396 } 397 398 int ViECaptureImpl::RegisterObserver(const int capture_id, 399 ViECaptureObserver& observer) { 400 LOG(LS_INFO) << "Register capture observer " << capture_id; 401 ViEInputManagerScoped is(*(shared_data_->input_manager())); 402 ViECapturer* vie_capture = is.Capture(capture_id); 403 if (!vie_capture) { 404 shared_data_->SetLastError(kViECaptureDeviceDoesNotExist); 405 return -1; 406 } 407 if (vie_capture->IsObserverRegistered()) { 408 LOG_F(LS_ERROR) << "Observer already registered."; 409 shared_data_->SetLastError(kViECaptureObserverAlreadyRegistered); 410 return -1; 411 } 412 if (vie_capture->RegisterObserver(&observer) != 0) { 413 shared_data_->SetLastError(kViECaptureDeviceUnknownError); 414 return -1; 415 } 416 return 0; 417 } 418 419 int ViECaptureImpl::DeregisterObserver(const int capture_id) { 420 ViEInputManagerScoped is(*(shared_data_->input_manager())); 421 ViECapturer* vie_capture = is.Capture(capture_id); 422 if (!vie_capture) { 423 shared_data_->SetLastError(kViECaptureDeviceDoesNotExist); 424 return -1; 425 } 426 if (!vie_capture->IsObserverRegistered()) { 427 shared_data_->SetLastError(kViECaptureDeviceObserverNotRegistered); 428 return -1; 429 } 430 431 if (vie_capture->DeRegisterObserver() != 0) { 432 shared_data_->SetLastError(kViECaptureDeviceUnknownError); 433 return -1; 434 } 435 return 0; 436 } 437 438 } // namespace webrtc 439