blob: a94c29c8a697c107e812ec10873ecd22b89297f3 [file] [log] [blame]
/*
* Copyright (c) 2011 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 "video_engine/vie_capture_impl.h"
#include "system_wrappers/interface/trace.h"
#include "video_engine/include/vie_errors.h"
#include "video_engine/vie_capturer.h"
#include "video_engine/vie_channel.h"
#include "video_engine/vie_channel_manager.h"
#include "video_engine/vie_defines.h"
#include "video_engine/vie_encoder.h"
#include "video_engine/vie_impl.h"
#include "video_engine/vie_input_manager.h"
#include "video_engine/vie_shared_data.h"
namespace webrtc {
ViECapture* ViECapture::GetInterface(VideoEngine* video_engine) {
#ifdef WEBRTC_VIDEO_ENGINE_CAPTURE_API
if (!video_engine) {
return NULL;
}
VideoEngineImpl* vie_impl = reinterpret_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() {
WEBRTC_TRACE(kTraceApiCall, kTraceVideo, shared_data_->instance_id(),
"ViECapture::Release()");
// Decrease ref count
(*this)--;
WebRtc_Word32 ref_count = GetCount();
if (ref_count < 0) {
WEBRTC_TRACE(kTraceWarning, kTraceVideo, shared_data_->instance_id(),
"ViECapture release too many times");
shared_data_->SetLastError(kViEAPIDoesNotExist);
return -1;
}
WEBRTC_TRACE(kTraceInfo, kTraceVideo, shared_data_->instance_id(),
"ViECapture reference count: %d", ref_count);
return ref_count;
}
ViECaptureImpl::ViECaptureImpl(ViESharedData* shared_data)
: shared_data_(shared_data) {
WEBRTC_TRACE(kTraceMemory, kTraceVideo, shared_data_->instance_id(),
"ViECaptureImpl::ViECaptureImpl() Ctor");
}
ViECaptureImpl::~ViECaptureImpl() {
WEBRTC_TRACE(kTraceMemory, kTraceVideo, shared_data_->instance_id(),
"ViECaptureImpl::~ViECaptureImpl() Dtor");
}
int ViECaptureImpl::NumberOfCaptureDevices() {
WEBRTC_TRACE(kTraceApiCall, kTraceVideo, ViEId(shared_data_->instance_id()),
"%s", __FUNCTION__);
if (!shared_data_->Initialized()) {
shared_data_->SetLastError(kViENotInitialized);
WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(shared_data_->instance_id()),
"%s - ViE instance %d not initialized", __FUNCTION__,
shared_data_->instance_id());
return -1;
}
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) {
WEBRTC_TRACE(kTraceApiCall, kTraceVideo, ViEId(shared_data_->instance_id()),
"%s(list_number: %d)", __FUNCTION__, list_number);
if (!shared_data_->Initialized()) {
shared_data_->SetLastError(kViENotInitialized);
WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(shared_data_->instance_id()),
"%s - ViE instance %d not initialized", __FUNCTION__,
shared_data_->instance_id());
return -1;
}
return shared_data_->input_manager()->GetDeviceName(
list_number,
reinterpret_cast<WebRtc_UWord8*>(device_nameUTF8), device_nameUTF8Length,
reinterpret_cast<WebRtc_UWord8*>(unique_idUTF8), unique_idUTF8Length);
}
int ViECaptureImpl::AllocateCaptureDevice(
const char* unique_idUTF8,
const unsigned int unique_idUTF8Length,
int& capture_id) {
WEBRTC_TRACE(kTraceApiCall, kTraceVideo, ViEId(shared_data_->instance_id()),
"%s(unique_idUTF8: %s)", __FUNCTION__, unique_idUTF8);
if (!shared_data_->Initialized()) {
shared_data_->SetLastError(kViENotInitialized);
WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(shared_data_->instance_id()),
"%s - ViE instance %d not initialized", __FUNCTION__,
shared_data_->instance_id());
return -1;
}
const WebRtc_Word32 result =
shared_data_->input_manager()->CreateCaptureDevice(
reinterpret_cast<const WebRtc_UWord8*>(unique_idUTF8),
static_cast<const WebRtc_UWord32>(unique_idUTF8Length), capture_id);
if (result != 0) {
shared_data_->SetLastError(result);
return -1;
}
return 0;
}
int ViECaptureImpl::AllocateExternalCaptureDevice(
int& capture_id, ViEExternalCapture*& external_capture) {
WEBRTC_TRACE(kTraceApiCall, kTraceVideo, ViEId(shared_data_->instance_id()),
"%s", __FUNCTION__);
if (!shared_data_->Initialized()) {
shared_data_->SetLastError(kViENotInitialized);
WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(shared_data_->instance_id()),
"%s - ViE instance %d not initialized", __FUNCTION__,
shared_data_->instance_id());
return -1;
}
const WebRtc_Word32 result =
shared_data_->input_manager()->CreateExternalCaptureDevice(
external_capture, capture_id);
if (result != 0) {
shared_data_->SetLastError(result);
return -1;
}
return 0;
}
int ViECaptureImpl::AllocateCaptureDevice(VideoCaptureModule& capture_module,
int& capture_id) {
WEBRTC_TRACE(kTraceApiCall, kTraceVideo, ViEId(shared_data_->instance_id()),
"%s", __FUNCTION__);
if (!shared_data_->Initialized()) {
shared_data_->SetLastError(kViENotInitialized);
WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(shared_data_->instance_id()),
"%s - ViE instance %d not initialized", __FUNCTION__,
shared_data_->instance_id());
return -1;
}
const WebRtc_Word32 result =
shared_data_->input_manager()->CreateCaptureDevice(capture_module,
capture_id);
if (result != 0) {
shared_data_->SetLastError(result);
return -1;
}
return 0;
}
int ViECaptureImpl::ReleaseCaptureDevice(const int capture_id) {
WEBRTC_TRACE(kTraceApiCall, kTraceVideo, ViEId(shared_data_->instance_id()),
"%s(capture_id: %d)", __FUNCTION__, capture_id);
{
ViEInputManagerScoped is((*(shared_data_->input_manager())));
ViECapturer* vie_capture = is.Capture(capture_id);
if (!vie_capture) {
WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(shared_data_->instance_id()),
"%s: Capture device %d doesn't exist", __FUNCTION__,
capture_id);
shared_data_->SetLastError(kViECaptureDeviceDoesNotExist);
return -1;
}
}
// Destroy the capture device.
return shared_data_->input_manager()->DestroyCaptureDevice(capture_id);
}
int ViECaptureImpl::ConnectCaptureDevice(const int capture_id,
const int video_channel) {
WEBRTC_TRACE(kTraceApiCall, kTraceVideo,
ViEId(shared_data_->instance_id(), video_channel),
"%s(capture_id: %d, video_channel: %d)", __FUNCTION__,
capture_id, video_channel);
ViEInputManagerScoped is(*(shared_data_->input_manager()));
ViECapturer* vie_capture = is.Capture(capture_id);
if (!vie_capture) {
WEBRTC_TRACE(kTraceError, kTraceVideo,
ViEId(shared_data_->instance_id(), video_channel),
"%s: Capture device %d doesn't exist", __FUNCTION__,
capture_id);
shared_data_->SetLastError(kViECaptureDeviceDoesNotExist);
return -1;
}
ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
ViEEncoder* vie_encoder = cs.Encoder(video_channel);
if (!vie_encoder) {
WEBRTC_TRACE(kTraceError, kTraceVideo,
ViEId(shared_data_->instance_id(), video_channel),
"%s: Channel %d doesn't exist", __FUNCTION__,
video_channel);
shared_data_->SetLastError(kViECaptureDeviceInvalidChannelId);
return -1;
}
// Check if the encoder already has a connected frame provider
if (is.FrameProvider(vie_encoder) != NULL) {
WEBRTC_TRACE(kTraceError, kTraceVideo,
ViEId(shared_data_->instance_id(), video_channel),
"%s: Channel %d already connected to a capture device.",
__FUNCTION__, video_channel);
shared_data_->SetLastError(kViECaptureDeviceAlreadyConnected);
return -1;
}
VideoCodec codec;
bool use_hardware_encoder = false;
if (vie_encoder->GetEncoder(codec) == 0) {
// Try to provide the encoder with pre-encoded frames if possible.
if (vie_capture->PreEncodeToViEEncoder(codec, *vie_encoder,
video_channel) == 0) {
use_hardware_encoder = true;
}
}
// If we don't use the camera as hardware encoder, we register the vie_encoder
// for callbacks.
if (!use_hardware_encoder &&
vie_capture->RegisterFrameCallback(video_channel, vie_encoder) != 0) {
shared_data_->SetLastError(kViECaptureDeviceUnknownError);
return -1;
}
return 0;
}
int ViECaptureImpl::DisconnectCaptureDevice(const int video_channel) {
WEBRTC_TRACE(kTraceApiCall, kTraceVideo,
ViEId(shared_data_->instance_id(), video_channel),
"%s(video_channel: %d)", __FUNCTION__, video_channel);
ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
ViEEncoder* vie_encoder = cs.Encoder(video_channel);
if (!vie_encoder) {
WEBRTC_TRACE(kTraceError, kTraceVideo,
ViEId(shared_data_->instance_id()),
"%s: Channel %d doesn't exist", __FUNCTION__,
video_channel);
shared_data_->SetLastError(kViECaptureDeviceInvalidChannelId);
return -1;
}
ViEInputManagerScoped is(*(shared_data_->input_manager()));
ViEFrameProviderBase* frame_provider = is.FrameProvider(vie_encoder);
if (!frame_provider) {
WEBRTC_TRACE(kTraceWarning, kTraceVideo,
ViEId(shared_data_->instance_id()),
"%s: No capture device connected to channel %d",
__FUNCTION__, video_channel);
shared_data_->SetLastError(kViECaptureDeviceNotConnected);
return -1;
}
if (frame_provider->Id() < kViECaptureIdBase ||
frame_provider->Id() > kViECaptureIdMax) {
WEBRTC_TRACE(kTraceWarning, kTraceVideo,
ViEId(shared_data_->instance_id()),
"%s: No capture device connected to channel %d",
__FUNCTION__, video_channel);
shared_data_->SetLastError(kViECaptureDeviceNotConnected);
return -1;
}
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) {
WEBRTC_TRACE(kTraceApiCall, kTraceVideo, ViEId(shared_data_->instance_id()),
"%s(capture_id: %d)", __FUNCTION__, capture_id);
ViEInputManagerScoped is(*(shared_data_->input_manager()));
ViECapturer* vie_capture = is.Capture(capture_id);
if (!vie_capture) {
WEBRTC_TRACE(kTraceError, kTraceVideo,
ViEId(shared_data_->instance_id(), capture_id),
"%s: Capture device %d doesn't exist", __FUNCTION__,
capture_id);
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) {
WEBRTC_TRACE(kTraceApiCall, kTraceVideo, ViEId(shared_data_->instance_id()),
"%s(capture_id: %d)", __FUNCTION__, capture_id);
ViEInputManagerScoped is(*(shared_data_->input_manager()));
ViECapturer* vie_capture = is.Capture(capture_id);
if (!vie_capture) {
WEBRTC_TRACE(kTraceError, kTraceVideo,
ViEId(shared_data_->instance_id(), capture_id),
"%s: Capture device %d doesn't exist", __FUNCTION__,
capture_id);
shared_data_->SetLastError(kViECaptureDeviceDoesNotExist);
return -1;
}
if (!vie_capture->Started()) {
shared_data_->SetLastError(kViECaptureDeviceNotStarted);
return -1;
}
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;
}
WEBRTC_TRACE(kTraceApiCall, kTraceVideo, ViEId(shared_data_->instance_id()),
"%s(rotation: %d)", __FUNCTION__, i_rotation);
ViEInputManagerScoped is(*(shared_data_->input_manager()));
ViECapturer* vie_capture = is.Capture(capture_id);
if (!vie_capture) {
WEBRTC_TRACE(kTraceError, kTraceVideo,
ViEId(shared_data_->instance_id(), capture_id),
"%s: Capture device %d doesn't exist", __FUNCTION__,
capture_id);
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) {
WEBRTC_TRACE(kTraceApiCall, kTraceVideo, ViEId(shared_data_->instance_id()),
"%s(capture_id: %d, capture_delay_ms %u)", __FUNCTION__,
capture_id, capture_delay_ms);
ViEInputManagerScoped is(*(shared_data_->input_manager()));
ViECapturer* vie_capture = is.Capture(capture_id);
if (!vie_capture) {
WEBRTC_TRACE(kTraceError, kTraceVideo,
ViEId(shared_data_->instance_id(), capture_id),
"%s: Capture device %d doesn't exist", __FUNCTION__,
capture_id);
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) {
WEBRTC_TRACE(kTraceApiCall, kTraceVideo, ViEId(shared_data_->instance_id()),
"%s(capture_device_name: %s)", __FUNCTION__, unique_idUTF8);
#if defined(WEBRTC_MAC_INTEL)
// 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);
WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(shared_data_->instance_id()),
"%s This API is not supported on Mac OS", __FUNCTION__,
shared_data_->instance_id());
return -1;
#endif
if (!shared_data_->Initialized()) {
shared_data_->SetLastError(kViENotInitialized);
WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(shared_data_->instance_id()),
"%s - ViE instance %d not initialized", __FUNCTION__,
shared_data_->instance_id());
return -1;
}
return shared_data_->input_manager()->NumberOfCaptureCapabilities(
reinterpret_cast<const WebRtc_UWord8*>(unique_idUTF8));
}
int ViECaptureImpl::GetCaptureCapability(const char* unique_idUTF8,
const unsigned int unique_idUTF8Length,
const unsigned int capability_number,
CaptureCapability& capability) {
WEBRTC_TRACE(kTraceApiCall, kTraceVideo, ViEId(shared_data_->instance_id()),
"%s(capture_device_name: %s)", __FUNCTION__, unique_idUTF8);
#if defined(WEBRTC_MAC_INTEL)
// 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);
WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(shared_data_->instance_id()),
"%s This API is not supported on Mac OS", __FUNCTION__,
shared_data_->instance_id());
return -1;
#endif
if (!shared_data_->Initialized()) {
shared_data_->SetLastError(kViENotInitialized);
WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(shared_data_->instance_id()),
"%s - ViE instance %d not initialized", __FUNCTION__,
shared_data_->instance_id());
return -1;
}
if (shared_data_->input_manager()->GetCaptureCapability(
reinterpret_cast<const WebRtc_UWord8*>(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_INTEL)
// 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);
WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(shared_data_->instance_id()),
"%s This API is not supported on Mac OS", __FUNCTION__,
shared_data_->instance_id());
return -1;
#endif
WEBRTC_TRACE(kTraceApiCall, kTraceVideo, ViEId(shared_data_->instance_id()),
"%s capture_id (capture_device_name: %s)", __FUNCTION__,
unique_idUTF8);
return shared_data_->input_manager()->DisplayCaptureSettingsDialogBox(
reinterpret_cast<const WebRtc_UWord8*>(unique_idUTF8),
reinterpret_cast<const WebRtc_UWord8*>(dialog_title),
parent_window, x, y);
}
int ViECaptureImpl::GetOrientation(const char* unique_idUTF8,
RotateCapturedFrame& orientation) {
WEBRTC_TRACE(kTraceApiCall, kTraceVideo, ViEId(shared_data_->instance_id()),
"%s (capture_device_name: %s)", __FUNCTION__, unique_idUTF8);
if (!shared_data_->Initialized()) {
shared_data_->SetLastError(kViENotInitialized);
WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(shared_data_->instance_id()),
"%s - ViE instance %d not initialized", __FUNCTION__,
shared_data_->instance_id());
return -1;
}
if (shared_data_->input_manager()->GetOrientation(
reinterpret_cast<const WebRtc_UWord8*>(unique_idUTF8),
orientation) != 0) {
shared_data_->SetLastError(kViECaptureDeviceUnknownError);
return -1;
}
return 0;
}
int ViECaptureImpl::EnableBrightnessAlarm(const int capture_id,
const bool enable) {
ViEInputManagerScoped is(*(shared_data_->input_manager()));
ViECapturer* vie_capture = is.Capture(capture_id);
if (!vie_capture) {
WEBRTC_TRACE(kTraceError, kTraceVideo,
ViEId(shared_data_->instance_id(), capture_id),
"%s: Capture device %d doesn't exist", __FUNCTION__,
capture_id);
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) {
ViEInputManagerScoped is(*(shared_data_->input_manager()));
ViECapturer* vie_capture = is.Capture(capture_id);
if (!vie_capture) {
WEBRTC_TRACE(kTraceError, kTraceVideo,
ViEId(shared_data_->instance_id(), capture_id),
"%s: Capture device %d doesn't exist", __FUNCTION__,
capture_id);
shared_data_->SetLastError(kViECaptureDeviceDoesNotExist);
return -1;
}
if (vie_capture->IsObserverRegistered()) {
WEBRTC_TRACE(kTraceError, kTraceVideo,
ViEId(shared_data_->instance_id(), capture_id),
"%s: Observer already registered", __FUNCTION__);
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) {
WEBRTC_TRACE(kTraceError, kTraceVideo,
ViEId(shared_data_->instance_id(), capture_id),
"%s: Capture device %d doesn't exist", __FUNCTION__,
capture_id);
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