| /* |
| * 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_base_impl.h" |
| |
| #include <string> |
| #include <utility> |
| |
| #include "webrtc/base/checks.h" |
| #include "webrtc/engine_configurations.h" |
| #include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp.h" |
| #include "webrtc/modules/video_coding/main/interface/video_coding.h" |
| #include "webrtc/modules/video_processing/main/interface/video_processing.h" |
| #include "webrtc/modules/video_render/include/video_render.h" |
| #include "webrtc/system_wrappers/interface/critical_section_wrapper.h" |
| #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 { |
| |
| ViEBase* ViEBase::GetInterface(VideoEngine* video_engine) { |
| if (!video_engine) { |
| return NULL; |
| } |
| VideoEngineImpl* vie_impl = static_cast<VideoEngineImpl*>(video_engine); |
| ViEBaseImpl* vie_base_impl = vie_impl; |
| (*vie_base_impl)++; // Increase ref count. |
| |
| return vie_base_impl; |
| } |
| |
| int ViEBaseImpl::Release() { |
| (*this)--; // Decrease ref count. |
| |
| int32_t ref_count = GetCount(); |
| if (ref_count < 0) { |
| LOG(LS_WARNING) << "ViEBase released too many times."; |
| return -1; |
| } |
| return ref_count; |
| } |
| |
| ViEBaseImpl::ViEBaseImpl(const Config& config) |
| : shared_data_(config) {} |
| |
| ViEBaseImpl::~ViEBaseImpl() {} |
| |
| int ViEBaseImpl::Init() { |
| return 0; |
| } |
| |
| int ViEBaseImpl::SetVoiceEngine(VoiceEngine* voice_engine) { |
| LOG_F(LS_INFO) << "SetVoiceEngine"; |
| if (shared_data_.channel_manager()->SetVoiceEngine(voice_engine) != 0) { |
| shared_data_.SetLastError(kViEBaseVoEFailure); |
| return -1; |
| } |
| return 0; |
| } |
| |
| int ViEBaseImpl::RegisterCpuOveruseObserver(int video_channel, |
| CpuOveruseObserver* observer) { |
| LOG_F(LS_INFO) << "RegisterCpuOveruseObserver on channel " << video_channel; |
| ViEChannelManagerScoped cs(*(shared_data_.channel_manager())); |
| ViEChannel* vie_channel = cs.Channel(video_channel); |
| if (!vie_channel) { |
| shared_data_.SetLastError(kViEBaseInvalidChannelId); |
| return -1; |
| } |
| ViEEncoder* vie_encoder = cs.Encoder(video_channel); |
| assert(vie_encoder); |
| |
| ViEInputManagerScoped is(*(shared_data_.input_manager())); |
| ViEFrameProviderBase* provider = is.FrameProvider(vie_encoder); |
| if (provider) { |
| ViECapturer* capturer = is.Capture(provider->Id()); |
| assert(capturer); |
| capturer->RegisterCpuOveruseObserver(observer); |
| } |
| |
| shared_data_.overuse_observers()->insert( |
| std::pair<int, CpuOveruseObserver*>(video_channel, observer)); |
| return 0; |
| } |
| |
| int ViEBaseImpl::SetCpuOveruseOptions(int video_channel, |
| const CpuOveruseOptions& options) { |
| ViEChannelManagerScoped cs(*(shared_data_.channel_manager())); |
| ViEChannel* vie_channel = cs.Channel(video_channel); |
| if (!vie_channel) { |
| shared_data_.SetLastError(kViEBaseInvalidChannelId); |
| return -1; |
| } |
| ViEEncoder* vie_encoder = cs.Encoder(video_channel); |
| assert(vie_encoder); |
| |
| ViEInputManagerScoped is(*(shared_data_.input_manager())); |
| ViEFrameProviderBase* provider = is.FrameProvider(vie_encoder); |
| if (provider) { |
| ViECapturer* capturer = is.Capture(provider->Id()); |
| if (capturer) { |
| capturer->SetCpuOveruseOptions(options); |
| return 0; |
| } |
| } |
| return -1; |
| } |
| |
| void ViEBaseImpl::RegisterCpuOveruseMetricsObserver( |
| int video_channel, |
| CpuOveruseMetricsObserver* observer) { |
| ViEChannelManagerScoped cs(*(shared_data_.channel_manager())); |
| ViEEncoder* vie_encoder = cs.Encoder(video_channel); |
| assert(vie_encoder); |
| |
| ViEInputManagerScoped is(*(shared_data_.input_manager())); |
| ViEFrameProviderBase* provider = is.FrameProvider(vie_encoder); |
| assert(provider != NULL); |
| |
| ViECapturer* capturer = is.Capture(provider->Id()); |
| assert(capturer); |
| |
| capturer->RegisterCpuOveruseMetricsObserver(observer); |
| } |
| |
| int ViEBaseImpl::GetCpuOveruseMetrics(int video_channel, |
| CpuOveruseMetrics* metrics) { |
| ViEChannelManagerScoped cs(*(shared_data_.channel_manager())); |
| ViEChannel* vie_channel = cs.Channel(video_channel); |
| if (!vie_channel) { |
| shared_data_.SetLastError(kViEBaseInvalidChannelId); |
| return -1; |
| } |
| ViEEncoder* vie_encoder = cs.Encoder(video_channel); |
| assert(vie_encoder); |
| |
| ViEInputManagerScoped is(*(shared_data_.input_manager())); |
| ViEFrameProviderBase* provider = is.FrameProvider(vie_encoder); |
| if (provider) { |
| ViECapturer* capturer = is.Capture(provider->Id()); |
| if (capturer) { |
| capturer->GetCpuOveruseMetrics(metrics); |
| return 0; |
| } |
| } |
| return -1; |
| } |
| |
| void ViEBaseImpl::RegisterSendSideDelayObserver( |
| int channel, SendSideDelayObserver* observer) { |
| ViEChannelManagerScoped cs(*(shared_data_.channel_manager())); |
| ViEChannel* vie_channel = cs.Channel(channel); |
| assert(vie_channel); |
| vie_channel->RegisterSendSideDelayObserver(observer); |
| } |
| |
| int ViEBaseImpl::CreateChannel(int& video_channel) { // NOLINT |
| return CreateChannel(video_channel, static_cast<const Config*>(NULL)); |
| } |
| |
| int ViEBaseImpl::CreateChannel(int& video_channel, // NOLINT |
| const Config* config) { |
| if (shared_data_.channel_manager()->CreateChannel(&video_channel, |
| config) == -1) { |
| video_channel = -1; |
| shared_data_.SetLastError(kViEBaseChannelCreationFailed); |
| return -1; |
| } |
| LOG(LS_INFO) << "Video channel created: " << video_channel; |
| return 0; |
| } |
| |
| int ViEBaseImpl::CreateChannel(int& video_channel, // NOLINT |
| int original_channel) { |
| return CreateChannel(video_channel, original_channel, true, false); |
| } |
| |
| int ViEBaseImpl::CreateChannelWithoutDefaultEncoder( |
| int& video_channel, // NOLINT |
| int original_channel) { |
| return CreateChannel(video_channel, original_channel, true, true); |
| } |
| |
| ChannelGroup* ViEBaseImpl::GetChannelGroup(int channel_id) { |
| return shared_data_.channel_manager()->GetChannelGroup(channel_id); |
| } |
| |
| ViEChannel* ViEBaseImpl::GetChannel(int channel_id) { |
| ViEChannelManagerScoped cs(*(shared_data_.channel_manager())); |
| ViEChannel* vie_channel = cs.Channel(channel_id); |
| DCHECK(vie_channel); |
| return vie_channel; |
| } |
| |
| ViEEncoder* ViEBaseImpl::GetEncoder(int channel_id) { |
| ViEChannelManagerScoped cs(*(shared_data_.channel_manager())); |
| ViEEncoder* vie_encoder = cs.Encoder(channel_id); |
| DCHECK(vie_encoder); |
| return vie_encoder; |
| } |
| |
| ViERenderManager* ViEBaseImpl::GetRenderManager() { |
| return shared_data_.render_manager(); |
| } |
| |
| int ViEBaseImpl::CreateReceiveChannel(int& video_channel, // NOLINT |
| int original_channel) { |
| return CreateChannel(video_channel, original_channel, false, true); |
| } |
| |
| int ViEBaseImpl::DeleteChannel(const int video_channel) { |
| { |
| ViEChannelManagerScoped cs(*(shared_data_.channel_manager())); |
| ViEChannel* vie_channel = cs.Channel(video_channel); |
| if (!vie_channel) { |
| shared_data_.SetLastError(kViEBaseInvalidChannelId); |
| return -1; |
| } |
| |
| // Deregister the ViEEncoder if no other channel is using it. |
| ViEEncoder* vie_encoder = cs.Encoder(video_channel); |
| if (!cs.ChannelUsingViEEncoder(video_channel)) { |
| ViEInputManagerScoped is(*(shared_data_.input_manager())); |
| ViEFrameProviderBase* provider = is.FrameProvider(vie_encoder); |
| if (provider) { |
| provider->DeregisterFrameCallback(vie_encoder); |
| } |
| } |
| } |
| |
| if (shared_data_.channel_manager()->DeleteChannel(video_channel) == -1) { |
| shared_data_.SetLastError(kViEBaseUnknownError); |
| return -1; |
| } |
| LOG(LS_INFO) << "Channel deleted " << video_channel; |
| return 0; |
| } |
| |
| int ViEBaseImpl::ConnectAudioChannel(const int video_channel, |
| const int audio_channel) { |
| LOG_F(LS_INFO) << "ConnectAudioChannel, video channel " << video_channel |
| << ", audio channel " << audio_channel; |
| ViEChannelManagerScoped cs(*(shared_data_.channel_manager())); |
| if (!cs.Channel(video_channel)) { |
| shared_data_.SetLastError(kViEBaseInvalidChannelId); |
| return -1; |
| } |
| |
| if (shared_data_.channel_manager()->ConnectVoiceChannel(video_channel, |
| audio_channel) != 0) { |
| shared_data_.SetLastError(kViEBaseVoEFailure); |
| return -1; |
| } |
| return 0; |
| } |
| |
| int ViEBaseImpl::DisconnectAudioChannel(const int video_channel) { |
| LOG_F(LS_INFO) << "DisconnectAudioChannel " << video_channel; |
| ViEChannelManagerScoped cs(*(shared_data_.channel_manager())); |
| if (!cs.Channel(video_channel)) { |
| shared_data_.SetLastError(kViEBaseInvalidChannelId); |
| return -1; |
| } |
| |
| if (shared_data_.channel_manager()->DisconnectVoiceChannel( |
| video_channel) != 0) { |
| shared_data_.SetLastError(kViEBaseVoEFailure); |
| return -1; |
| } |
| return 0; |
| } |
| |
| int ViEBaseImpl::StartSend(const int video_channel) { |
| LOG_F(LS_INFO) << "StartSend: " << video_channel; |
| ViEChannelManagerScoped cs(*(shared_data_.channel_manager())); |
| ViEChannel* vie_channel = cs.Channel(video_channel); |
| if (!vie_channel) { |
| shared_data_.SetLastError(kViEBaseInvalidChannelId); |
| return -1; |
| } |
| |
| ViEEncoder* vie_encoder = cs.Encoder(video_channel); |
| assert(vie_encoder != NULL); |
| if (vie_encoder->Owner() != video_channel) { |
| LOG_F(LS_ERROR) << "Can't start send on a receive only channel."; |
| shared_data_.SetLastError(kViEBaseReceiveOnlyChannel); |
| return -1; |
| } |
| |
| // Pause and trigger a key frame. |
| vie_encoder->Pause(); |
| int32_t error = vie_channel->StartSend(); |
| if (error != 0) { |
| vie_encoder->Restart(); |
| if (error == kViEBaseAlreadySending) { |
| shared_data_.SetLastError(kViEBaseAlreadySending); |
| } |
| LOG_F(LS_ERROR) << "Could not start sending " << video_channel; |
| shared_data_.SetLastError(kViEBaseUnknownError); |
| return -1; |
| } |
| vie_encoder->SendKeyFrame(); |
| vie_encoder->Restart(); |
| return 0; |
| } |
| |
| int ViEBaseImpl::StopSend(const int video_channel) { |
| LOG_F(LS_INFO) << "StopSend " << video_channel; |
| |
| ViEChannelManagerScoped cs(*(shared_data_.channel_manager())); |
| ViEChannel* vie_channel = cs.Channel(video_channel); |
| if (!vie_channel) { |
| shared_data_.SetLastError(kViEBaseInvalidChannelId); |
| return -1; |
| } |
| |
| int32_t error = vie_channel->StopSend(); |
| if (error != 0) { |
| if (error == kViEBaseNotSending) { |
| shared_data_.SetLastError(kViEBaseNotSending); |
| } else { |
| LOG_F(LS_ERROR) << "Could not stop sending " << video_channel; |
| shared_data_.SetLastError(kViEBaseUnknownError); |
| } |
| return -1; |
| } |
| return 0; |
| } |
| |
| int ViEBaseImpl::StartReceive(const int video_channel) { |
| LOG_F(LS_INFO) << "StartReceive " << video_channel; |
| |
| ViEChannelManagerScoped cs(*(shared_data_.channel_manager())); |
| ViEChannel* vie_channel = cs.Channel(video_channel); |
| if (!vie_channel) { |
| shared_data_.SetLastError(kViEBaseInvalidChannelId); |
| return -1; |
| } |
| if (vie_channel->StartReceive() != 0) { |
| shared_data_.SetLastError(kViEBaseUnknownError); |
| return -1; |
| } |
| return 0; |
| } |
| |
| int ViEBaseImpl::StopReceive(const int video_channel) { |
| LOG_F(LS_INFO) << "StopReceive " << video_channel; |
| ViEChannelManagerScoped cs(*(shared_data_.channel_manager())); |
| ViEChannel* vie_channel = cs.Channel(video_channel); |
| if (!vie_channel) { |
| shared_data_.SetLastError(kViEBaseInvalidChannelId); |
| return -1; |
| } |
| if (vie_channel->StopReceive() != 0) { |
| shared_data_.SetLastError(kViEBaseUnknownError); |
| return -1; |
| } |
| return 0; |
| } |
| |
| int ViEBaseImpl::GetVersion(char version[1024]) { |
| assert(version != NULL); |
| strcpy(version, "VideoEngine 42"); |
| return 0; |
| } |
| |
| int ViEBaseImpl::LastError() { |
| return shared_data_.LastErrorInternal(); |
| } |
| |
| int ViEBaseImpl::CreateChannel(int& video_channel, // NOLINT |
| int original_channel, |
| bool sender, |
| bool disable_default_encoder) { |
| ViEChannelManagerScoped cs(*(shared_data_.channel_manager())); |
| if (!cs.Channel(original_channel)) { |
| shared_data_.SetLastError(kViEBaseInvalidChannelId); |
| return -1; |
| } |
| |
| if (shared_data_.channel_manager()->CreateChannel( |
| &video_channel, original_channel, sender, disable_default_encoder) == |
| -1) { |
| video_channel = -1; |
| shared_data_.SetLastError(kViEBaseChannelCreationFailed); |
| return -1; |
| } |
| LOG_F(LS_INFO) << "VideoChannel created: " << video_channel |
| << ", base channel " << original_channel |
| << ", is send channel : " << sender; |
| return 0; |
| } |
| |
| void ViEBaseImpl::RegisterSendStatisticsProxy( |
| int channel, |
| SendStatisticsProxy* send_statistics_proxy) { |
| LOG_F(LS_VERBOSE) << "RegisterSendStatisticsProxy on channel " << channel; |
| ViEChannelManagerScoped cs(*(shared_data_.channel_manager())); |
| ViEChannel* vie_channel = cs.Channel(channel); |
| if (!vie_channel) { |
| shared_data_.SetLastError(kViEBaseInvalidChannelId); |
| return; |
| } |
| ViEEncoder* vie_encoder = cs.Encoder(channel); |
| assert(vie_encoder); |
| |
| vie_encoder->RegisterSendStatisticsProxy(send_statistics_proxy); |
| } |
| |
| void ViEBaseImpl::RegisterReceiveStatisticsProxy( |
| int channel, |
| ReceiveStatisticsProxy* receive_statistics_proxy) { |
| LOG_F(LS_VERBOSE) << "RegisterReceiveStatisticsProxy on channel " << channel; |
| ViEChannelManagerScoped cs(*(shared_data_.channel_manager())); |
| ViEChannel* vie_channel = cs.Channel(channel); |
| if (!vie_channel) { |
| shared_data_.SetLastError(kViEBaseInvalidChannelId); |
| return; |
| } |
| vie_channel->RegisterReceiveStatisticsProxy(receive_statistics_proxy); |
| } |
| } // namespace webrtc |