| /* |
| * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. |
| * |
| * Use of this source code is governed by a BSD-style license |
| * that can be found in the LICENSE file in the root of the source |
| * tree. An additional intellectual property rights grant can be found |
| * in the file PATENTS. All contributing project authors may |
| * be found in the AUTHORS file in the root of the source tree. |
| */ |
| |
| #include "webrtc/video_engine/vie_capture_impl.h" |
| |
| #include <map> |
| |
| #include "webrtc/system_wrappers/interface/logging.h" |
| #include "webrtc/video_engine/include/vie_errors.h" |
| #include "webrtc/video_engine/vie_capturer.h" |
| #include "webrtc/video_engine/vie_channel.h" |
| #include "webrtc/video_engine/vie_channel_manager.h" |
| #include "webrtc/video_engine/vie_defines.h" |
| #include "webrtc/video_engine/vie_encoder.h" |
| #include "webrtc/video_engine/vie_impl.h" |
| #include "webrtc/video_engine/vie_input_manager.h" |
| #include "webrtc/video_engine/vie_shared_data.h" |
| |
| namespace webrtc { |
| |
| class CpuOveruseObserver; |
| |
| ViECapture* ViECapture::GetInterface(VideoEngine* video_engine) { |
| #ifdef WEBRTC_VIDEO_ENGINE_CAPTURE_API |
| if (!video_engine) { |
| return NULL; |
| } |
| VideoEngineImpl* vie_impl = static_cast<VideoEngineImpl*>(video_engine); |
| ViECaptureImpl* vie_capture_impl = vie_impl; |
| // Increase ref count. |
| (*vie_capture_impl)++; |
| return vie_capture_impl; |
| #else |
| return NULL; |
| #endif |
| } |
| |
| int ViECaptureImpl::Release() { |
| // Decrease ref count |
| (*this)--; |
| |
| int32_t ref_count = GetCount(); |
| if (ref_count < 0) { |
| LOG(LS_WARNING) << "ViECapture released too many times."; |
| shared_data_->SetLastError(kViEAPIDoesNotExist); |
| return -1; |
| } |
| return ref_count; |
| } |
| |
| ViECaptureImpl::ViECaptureImpl(ViESharedData* shared_data) |
| : shared_data_(shared_data) {} |
| |
| ViECaptureImpl::~ViECaptureImpl() {} |
| |
| int ViECaptureImpl::NumberOfCaptureDevices() { |
| return shared_data_->input_manager()->NumberOfCaptureDevices(); |
| } |
| |
| |
| int ViECaptureImpl::GetCaptureDevice(unsigned int list_number, |
| char* device_nameUTF8, |
| unsigned int device_nameUTF8Length, |
| char* unique_idUTF8, |
| unsigned int unique_idUTF8Length) { |
| return shared_data_->input_manager()->GetDeviceName( |
| list_number, |
| device_nameUTF8, device_nameUTF8Length, |
| unique_idUTF8, unique_idUTF8Length); |
| } |
| |
| int ViECaptureImpl::AllocateCaptureDevice( |
| const char* unique_idUTF8, |
| const unsigned int unique_idUTF8Length, |
| int& capture_id) { |
| LOG(LS_INFO) << "AllocateCaptureDevice " << unique_idUTF8; |
| const int32_t result = |
| shared_data_->input_manager()->CreateCaptureDevice( |
| unique_idUTF8, |
| static_cast<const uint32_t>(unique_idUTF8Length), |
| capture_id); |
| if (result != 0) { |
| shared_data_->SetLastError(result); |
| return -1; |
| } |
| return 0; |
| } |
| |
| int ViECaptureImpl::AllocateExternalCaptureDevice( |
| int& capture_id, ViEExternalCapture*& external_capture) { |
| const int32_t result = |
| shared_data_->input_manager()->CreateExternalCaptureDevice( |
| external_capture, capture_id); |
| |
| if (result != 0) { |
| shared_data_->SetLastError(result); |
| return -1; |
| } |
| LOG(LS_INFO) << "External capture device allocated: " << capture_id; |
| return 0; |
| } |
| |
| int ViECaptureImpl::AllocateCaptureDevice( |
| VideoCaptureModule& capture_module, int& capture_id) { // NOLINT |
| int32_t result = shared_data_->input_manager()->CreateCaptureDevice( |
| &capture_module, capture_id); |
| if (result != 0) { |
| shared_data_->SetLastError(result); |
| return -1; |
| } |
| LOG(LS_INFO) << "External capture device, by module, allocated: " |
| << capture_id; |
| return 0; |
| } |
| |
| |
| int ViECaptureImpl::ReleaseCaptureDevice(const int capture_id) { |
| LOG(LS_INFO) << "ReleaseCaptureDevice " << capture_id; |
| { |
| ViEInputManagerScoped is((*(shared_data_->input_manager()))); |
| ViECapturer* vie_capture = is.Capture(capture_id); |
| if (!vie_capture) { |
| shared_data_->SetLastError(kViECaptureDeviceDoesNotExist); |
| return -1; |
| } |
| } |
| return shared_data_->input_manager()->DestroyCaptureDevice(capture_id); |
| } |
| |
| int ViECaptureImpl::ConnectCaptureDevice(const int capture_id, |
| const int video_channel) { |
| LOG(LS_INFO) << "Connect capture id " << capture_id |
| << " to channel " << video_channel; |
| |
| ViEInputManagerScoped is(*(shared_data_->input_manager())); |
| ViECapturer* vie_capture = is.Capture(capture_id); |
| if (!vie_capture) { |
| shared_data_->SetLastError(kViECaptureDeviceDoesNotExist); |
| return -1; |
| } |
| |
| ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); |
| ViEEncoder* vie_encoder = cs.Encoder(video_channel); |
| if (!vie_encoder) { |
| LOG(LS_ERROR) << "Channel doesn't exist."; |
| shared_data_->SetLastError(kViECaptureDeviceInvalidChannelId); |
| return -1; |
| } |
| if (vie_encoder->Owner() != video_channel) { |
| LOG(LS_ERROR) << "Can't connect capture device to a receive device."; |
| shared_data_->SetLastError(kViECaptureDeviceInvalidChannelId); |
| return -1; |
| } |
| // Check if the encoder already has a connected frame provider |
| if (is.FrameProvider(vie_encoder) != NULL) { |
| LOG(LS_ERROR) << "Channel already connected to capture device."; |
| shared_data_->SetLastError(kViECaptureDeviceAlreadyConnected); |
| return -1; |
| } |
| if (vie_capture->RegisterFrameCallback(video_channel, vie_encoder) != 0) { |
| shared_data_->SetLastError(kViECaptureDeviceUnknownError); |
| return -1; |
| } |
| std::map<int, CpuOveruseObserver*>::iterator it = |
| shared_data_->overuse_observers()->find(video_channel); |
| if (it != shared_data_->overuse_observers()->end()) { |
| vie_capture->RegisterCpuOveruseObserver(it->second); |
| } |
| return 0; |
| } |
| |
| |
| int ViECaptureImpl::DisconnectCaptureDevice(const int video_channel) { |
| LOG(LS_INFO) << "DisconnectCaptureDevice " << video_channel; |
| |
| ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); |
| ViEEncoder* vie_encoder = cs.Encoder(video_channel); |
| if (!vie_encoder) { |
| LOG(LS_ERROR) << "Channel doesn't exist."; |
| shared_data_->SetLastError(kViECaptureDeviceInvalidChannelId); |
| return -1; |
| } |
| |
| ViEInputManagerScoped is(*(shared_data_->input_manager())); |
| ViEFrameProviderBase* frame_provider = is.FrameProvider(vie_encoder); |
| if (!frame_provider) { |
| shared_data_->SetLastError(kViECaptureDeviceNotConnected); |
| return -1; |
| } |
| if (frame_provider->Id() < kViECaptureIdBase || |
| frame_provider->Id() > kViECaptureIdMax) { |
| shared_data_->SetLastError(kViECaptureDeviceNotConnected); |
| return -1; |
| } |
| |
| ViECapturer* vie_capture = is.Capture(frame_provider->Id()); |
| assert(vie_capture); |
| vie_capture->RegisterCpuOveruseObserver(NULL); |
| if (frame_provider->DeregisterFrameCallback(vie_encoder) != 0) { |
| shared_data_->SetLastError(kViECaptureDeviceUnknownError); |
| return -1; |
| } |
| |
| return 0; |
| } |
| |
| int ViECaptureImpl::StartCapture(const int capture_id, |
| const CaptureCapability& capture_capability) { |
| LOG(LS_ERROR) << "StartCapture " << capture_id; |
| |
| ViEInputManagerScoped is(*(shared_data_->input_manager())); |
| ViECapturer* vie_capture = is.Capture(capture_id); |
| if (!vie_capture) { |
| shared_data_->SetLastError(kViECaptureDeviceDoesNotExist); |
| return -1; |
| } |
| if (vie_capture->Started()) { |
| shared_data_->SetLastError(kViECaptureDeviceAlreadyStarted); |
| return -1; |
| } |
| if (vie_capture->Start(capture_capability) != 0) { |
| shared_data_->SetLastError(kViECaptureDeviceUnknownError); |
| return -1; |
| } |
| return 0; |
| } |
| |
| int ViECaptureImpl::StopCapture(const int capture_id) { |
| LOG(LS_INFO) << "StopCapture " << capture_id; |
| |
| ViEInputManagerScoped is(*(shared_data_->input_manager())); |
| ViECapturer* vie_capture = is.Capture(capture_id); |
| if (!vie_capture) { |
| shared_data_->SetLastError(kViECaptureDeviceDoesNotExist); |
| return -1; |
| } |
| if (!vie_capture->Started()) { |
| shared_data_->SetLastError(kViECaptureDeviceNotStarted); |
| return 0; |
| } |
| if (vie_capture->Stop() != 0) { |
| shared_data_->SetLastError(kViECaptureDeviceUnknownError); |
| return -1; |
| } |
| return 0; |
| } |
| |
| int ViECaptureImpl::SetRotateCapturedFrames( |
| const int capture_id, |
| const RotateCapturedFrame rotation) { |
| int i_rotation = -1; |
| switch (rotation) { |
| case RotateCapturedFrame_0: |
| i_rotation = 0; |
| break; |
| case RotateCapturedFrame_90: |
| i_rotation = 90; |
| break; |
| case RotateCapturedFrame_180: |
| i_rotation = 180; |
| break; |
| case RotateCapturedFrame_270: |
| i_rotation = 270; |
| break; |
| } |
| LOG(LS_INFO) << "SetRotateCaptureFrames for " << capture_id |
| << ", rotation " << i_rotation; |
| |
| ViEInputManagerScoped is(*(shared_data_->input_manager())); |
| ViECapturer* vie_capture = is.Capture(capture_id); |
| if (!vie_capture) { |
| shared_data_->SetLastError(kViECaptureDeviceDoesNotExist); |
| return -1; |
| } |
| if (vie_capture->SetRotateCapturedFrames(rotation) != 0) { |
| shared_data_->SetLastError(kViECaptureDeviceUnknownError); |
| return -1; |
| } |
| return 0; |
| } |
| |
| int ViECaptureImpl::SetCaptureDelay(const int capture_id, |
| const unsigned int capture_delay_ms) { |
| LOG(LS_INFO) << "SetCaptureDelay " << capture_delay_ms |
| << ", for device " << capture_id; |
| |
| ViEInputManagerScoped is(*(shared_data_->input_manager())); |
| ViECapturer* vie_capture = is.Capture(capture_id); |
| if (!vie_capture) { |
| shared_data_->SetLastError(kViECaptureDeviceDoesNotExist); |
| return -1; |
| } |
| |
| if (vie_capture->SetCaptureDelay(capture_delay_ms) != 0) { |
| shared_data_->SetLastError(kViECaptureDeviceUnknownError); |
| return -1; |
| } |
| return 0; |
| } |
| |
| int ViECaptureImpl::NumberOfCapabilities( |
| const char* unique_idUTF8, |
| const unsigned int unique_idUTF8Length) { |
| |
| #if defined(WEBRTC_MAC) |
| // TODO(mflodman) Move to capture module! |
| // QTKit framework handles all capabilities and capture settings |
| // automatically (mandatory). |
| // Thus this function cannot be supported on the Mac platform. |
| shared_data_->SetLastError(kViECaptureDeviceMacQtkitNotSupported); |
| LOG_F(LS_ERROR) << "API not supported on Mac OS X."; |
| return -1; |
| #endif |
| return shared_data_->input_manager()->NumberOfCaptureCapabilities( |
| unique_idUTF8); |
| } |
| |
| |
| int ViECaptureImpl::GetCaptureCapability(const char* unique_idUTF8, |
| const unsigned int unique_idUTF8Length, |
| const unsigned int capability_number, |
| CaptureCapability& capability) { |
| |
| #if defined(WEBRTC_MAC) |
| // TODO(mflodman) Move to capture module! |
| // QTKit framework handles all capabilities and capture settings |
| // automatically (mandatory). |
| // Thus this function cannot be supported on the Mac platform. |
| LOG_F(LS_ERROR) << "API not supported on Mac OS X."; |
| shared_data_->SetLastError(kViECaptureDeviceMacQtkitNotSupported); |
| return -1; |
| #endif |
| if (shared_data_->input_manager()->GetCaptureCapability( |
| unique_idUTF8, capability_number, capability) != 0) { |
| shared_data_->SetLastError(kViECaptureDeviceUnknownError); |
| return -1; |
| } |
| return 0; |
| } |
| |
| int ViECaptureImpl::ShowCaptureSettingsDialogBox( |
| const char* unique_idUTF8, |
| const unsigned int unique_idUTF8Length, |
| const char* dialog_title, |
| void* parent_window, |
| const unsigned int x, |
| const unsigned int y) { |
| #if defined(WEBRTC_MAC) |
| // TODO(mflodman) Move to capture module |
| // QTKit framework handles all capabilities and capture settings |
| // automatically (mandatory). |
| // Thus this function cannot be supported on the Mac platform. |
| shared_data_->SetLastError(kViECaptureDeviceMacQtkitNotSupported); |
| LOG_F(LS_ERROR) << "API not supported on Mac OS X."; |
| return -1; |
| #endif |
| return shared_data_->input_manager()->DisplayCaptureSettingsDialogBox( |
| unique_idUTF8, dialog_title, |
| parent_window, x, y); |
| } |
| |
| int ViECaptureImpl::GetOrientation(const char* unique_idUTF8, |
| RotateCapturedFrame& orientation) { |
| if (shared_data_->input_manager()->GetOrientation( |
| unique_idUTF8, |
| orientation) != 0) { |
| shared_data_->SetLastError(kViECaptureDeviceUnknownError); |
| return -1; |
| } |
| return 0; |
| } |
| |
| |
| int ViECaptureImpl::EnableBrightnessAlarm(const int capture_id, |
| const bool enable) { |
| LOG(LS_INFO) << "EnableBrightnessAlarm for device " << capture_id |
| << ", status " << enable; |
| ViEInputManagerScoped is(*(shared_data_->input_manager())); |
| ViECapturer* vie_capture = is.Capture(capture_id); |
| if (!vie_capture) { |
| shared_data_->SetLastError(kViECaptureDeviceDoesNotExist); |
| return -1; |
| } |
| if (vie_capture->EnableBrightnessAlarm(enable) != 0) { |
| shared_data_->SetLastError(kViECaptureDeviceUnknownError); |
| return -1; |
| } |
| return 0; |
| } |
| |
| int ViECaptureImpl::RegisterObserver(const int capture_id, |
| ViECaptureObserver& observer) { |
| LOG(LS_INFO) << "Register capture observer " << capture_id; |
| ViEInputManagerScoped is(*(shared_data_->input_manager())); |
| ViECapturer* vie_capture = is.Capture(capture_id); |
| if (!vie_capture) { |
| shared_data_->SetLastError(kViECaptureDeviceDoesNotExist); |
| return -1; |
| } |
| if (vie_capture->IsObserverRegistered()) { |
| LOG_F(LS_ERROR) << "Observer already registered."; |
| shared_data_->SetLastError(kViECaptureObserverAlreadyRegistered); |
| return -1; |
| } |
| if (vie_capture->RegisterObserver(&observer) != 0) { |
| shared_data_->SetLastError(kViECaptureDeviceUnknownError); |
| return -1; |
| } |
| return 0; |
| } |
| |
| int ViECaptureImpl::DeregisterObserver(const int capture_id) { |
| ViEInputManagerScoped is(*(shared_data_->input_manager())); |
| ViECapturer* vie_capture = is.Capture(capture_id); |
| if (!vie_capture) { |
| shared_data_->SetLastError(kViECaptureDeviceDoesNotExist); |
| return -1; |
| } |
| if (!vie_capture->IsObserverRegistered()) { |
| shared_data_->SetLastError(kViECaptureDeviceObserverNotRegistered); |
| return -1; |
| } |
| |
| if (vie_capture->DeRegisterObserver() != 0) { |
| shared_data_->SetLastError(kViECaptureDeviceUnknownError); |
| return -1; |
| } |
| return 0; |
| } |
| |
| } // namespace webrtc |