1470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com/* 279af734807109d119573ce23daa1a2bff0f0eecaxians@webrtc.org * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. 3470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com * 4470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com * Use of this source code is governed by a BSD-style license 5470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com * that can be found in the LICENSE file in the root of the source 6470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com * tree. An additional intellectual property rights grant can be found 7470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com * in the file PATENTS. All contributing project authors may 8470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com * be found in the AUTHORS file in the root of the source tree. 9470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com */ 10470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 11956aa7e0874f2e08c335a82a2c32f400fac8b031pbos@webrtc.org#include "webrtc/voice_engine/voe_external_media_impl.h" 12470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 1398f53510b222f71fdd8b799b2f33737ceeb28c61Henrik Kjellander#include "webrtc/system_wrappers/include/critical_section_wrapper.h" 1498f53510b222f71fdd8b799b2f33737ceeb28c61Henrik Kjellander#include "webrtc/system_wrappers/include/trace.h" 15956aa7e0874f2e08c335a82a2c32f400fac8b031pbos@webrtc.org#include "webrtc/voice_engine/channel.h" 16956aa7e0874f2e08c335a82a2c32f400fac8b031pbos@webrtc.org#include "webrtc/voice_engine/include/voe_errors.h" 17956aa7e0874f2e08c335a82a2c32f400fac8b031pbos@webrtc.org#include "webrtc/voice_engine/output_mixer.h" 18956aa7e0874f2e08c335a82a2c32f400fac8b031pbos@webrtc.org#include "webrtc/voice_engine/transmit_mixer.h" 19956aa7e0874f2e08c335a82a2c32f400fac8b031pbos@webrtc.org#include "webrtc/voice_engine/voice_engine_impl.h" 20470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 21470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comnamespace webrtc { 22470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 230d266054acece70259fc1e85026194154f41e5a0Jelena MarusicVoEExternalMedia* VoEExternalMedia::GetInterface(VoiceEngine* voiceEngine) { 24470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#ifndef WEBRTC_VOICE_ENGINE_EXTERNAL_MEDIA_API 250d266054acece70259fc1e85026194154f41e5a0Jelena Marusic return NULL; 26470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#else 270d266054acece70259fc1e85026194154f41e5a0Jelena Marusic if (NULL == voiceEngine) { 280d266054acece70259fc1e85026194154f41e5a0Jelena Marusic return NULL; 290d266054acece70259fc1e85026194154f41e5a0Jelena Marusic } 300d266054acece70259fc1e85026194154f41e5a0Jelena Marusic VoiceEngineImpl* s = static_cast<VoiceEngineImpl*>(voiceEngine); 310d266054acece70259fc1e85026194154f41e5a0Jelena Marusic s->AddRef(); 320d266054acece70259fc1e85026194154f41e5a0Jelena Marusic return s; 33470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#endif 34470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 35470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 36470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#ifdef WEBRTC_VOICE_ENGINE_EXTERNAL_MEDIA_API 37470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 38851becd00ce814f0e02a5c5a56ac0322a7f9494dtommi@webrtc.orgVoEExternalMediaImpl::VoEExternalMediaImpl(voe::SharedData* shared) 393f9db3735ee760803fbd687189743b22747f6e54wjia@webrtc.org : 403f9db3735ee760803fbd687189743b22747f6e54wjia@webrtc.org#ifdef WEBRTC_VOE_EXTERNAL_REC_AND_PLAYOUT 410d266054acece70259fc1e85026194154f41e5a0Jelena Marusic playout_delay_ms_(0), 423f9db3735ee760803fbd687189743b22747f6e54wjia@webrtc.org#endif 430d266054acece70259fc1e85026194154f41e5a0Jelena Marusic shared_(shared) { 440d266054acece70259fc1e85026194154f41e5a0Jelena Marusic WEBRTC_TRACE(kTraceMemory, kTraceVoice, VoEId(shared_->instance_id(), -1), 450d266054acece70259fc1e85026194154f41e5a0Jelena Marusic "VoEExternalMediaImpl() - ctor"); 46470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 47470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 480d266054acece70259fc1e85026194154f41e5a0Jelena MarusicVoEExternalMediaImpl::~VoEExternalMediaImpl() { 490d266054acece70259fc1e85026194154f41e5a0Jelena Marusic WEBRTC_TRACE(kTraceMemory, kTraceVoice, VoEId(shared_->instance_id(), -1), 500d266054acece70259fc1e85026194154f41e5a0Jelena Marusic "~VoEExternalMediaImpl() - dtor"); 51470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 52470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 53470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint VoEExternalMediaImpl::RegisterExternalMediaProcessing( 54470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com int channel, 55470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com ProcessingTypes type, 560d266054acece70259fc1e85026194154f41e5a0Jelena Marusic VoEMediaProcess& processObject) { 570d266054acece70259fc1e85026194154f41e5a0Jelena Marusic WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(shared_->instance_id(), -1), 580d266054acece70259fc1e85026194154f41e5a0Jelena Marusic "RegisterExternalMediaProcessing(channel=%d, type=%d, " 590d266054acece70259fc1e85026194154f41e5a0Jelena Marusic "processObject=0x%x)", 600d266054acece70259fc1e85026194154f41e5a0Jelena Marusic channel, type, &processObject); 610d266054acece70259fc1e85026194154f41e5a0Jelena Marusic if (!shared_->statistics().Initialized()) { 620d266054acece70259fc1e85026194154f41e5a0Jelena Marusic shared_->SetLastError(VE_NOT_INITED, kTraceError); 630d266054acece70259fc1e85026194154f41e5a0Jelena Marusic return -1; 640d266054acece70259fc1e85026194154f41e5a0Jelena Marusic } 650d266054acece70259fc1e85026194154f41e5a0Jelena Marusic switch (type) { 660d266054acece70259fc1e85026194154f41e5a0Jelena Marusic case kPlaybackPerChannel: 670d266054acece70259fc1e85026194154f41e5a0Jelena Marusic case kRecordingPerChannel: { 680d266054acece70259fc1e85026194154f41e5a0Jelena Marusic voe::ChannelOwner ch = shared_->channel_manager().GetChannel(channel); 690d266054acece70259fc1e85026194154f41e5a0Jelena Marusic voe::Channel* channelPtr = ch.channel(); 700d266054acece70259fc1e85026194154f41e5a0Jelena Marusic if (channelPtr == NULL) { 710d266054acece70259fc1e85026194154f41e5a0Jelena Marusic shared_->SetLastError( 720d266054acece70259fc1e85026194154f41e5a0Jelena Marusic VE_CHANNEL_NOT_VALID, kTraceError, 730d266054acece70259fc1e85026194154f41e5a0Jelena Marusic "RegisterExternalMediaProcessing() failed to locate " 740d266054acece70259fc1e85026194154f41e5a0Jelena Marusic "channel"); 75470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return -1; 760d266054acece70259fc1e85026194154f41e5a0Jelena Marusic } 770d266054acece70259fc1e85026194154f41e5a0Jelena Marusic return channelPtr->RegisterExternalMediaProcessing(type, processObject); 78470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 790d266054acece70259fc1e85026194154f41e5a0Jelena Marusic case kPlaybackAllChannelsMixed: { 800d266054acece70259fc1e85026194154f41e5a0Jelena Marusic return shared_->output_mixer()->RegisterExternalMediaProcessing( 810d266054acece70259fc1e85026194154f41e5a0Jelena Marusic processObject); 82470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 830d266054acece70259fc1e85026194154f41e5a0Jelena Marusic case kRecordingAllChannelsMixed: 840d266054acece70259fc1e85026194154f41e5a0Jelena Marusic case kRecordingPreprocessing: { 850d266054acece70259fc1e85026194154f41e5a0Jelena Marusic return shared_->transmit_mixer()->RegisterExternalMediaProcessing( 860d266054acece70259fc1e85026194154f41e5a0Jelena Marusic &processObject, type); 870d266054acece70259fc1e85026194154f41e5a0Jelena Marusic } 880d266054acece70259fc1e85026194154f41e5a0Jelena Marusic } 890d266054acece70259fc1e85026194154f41e5a0Jelena Marusic return -1; 90470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 91470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 92470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint VoEExternalMediaImpl::DeRegisterExternalMediaProcessing( 93470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com int channel, 940d266054acece70259fc1e85026194154f41e5a0Jelena Marusic ProcessingTypes type) { 950d266054acece70259fc1e85026194154f41e5a0Jelena Marusic WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(shared_->instance_id(), -1), 960d266054acece70259fc1e85026194154f41e5a0Jelena Marusic "DeRegisterExternalMediaProcessing(channel=%d)", channel); 970d266054acece70259fc1e85026194154f41e5a0Jelena Marusic if (!shared_->statistics().Initialized()) { 980d266054acece70259fc1e85026194154f41e5a0Jelena Marusic shared_->SetLastError(VE_NOT_INITED, kTraceError); 990d266054acece70259fc1e85026194154f41e5a0Jelena Marusic return -1; 1000d266054acece70259fc1e85026194154f41e5a0Jelena Marusic } 1010d266054acece70259fc1e85026194154f41e5a0Jelena Marusic switch (type) { 1020d266054acece70259fc1e85026194154f41e5a0Jelena Marusic case kPlaybackPerChannel: 1030d266054acece70259fc1e85026194154f41e5a0Jelena Marusic case kRecordingPerChannel: { 1040d266054acece70259fc1e85026194154f41e5a0Jelena Marusic voe::ChannelOwner ch = shared_->channel_manager().GetChannel(channel); 1050d266054acece70259fc1e85026194154f41e5a0Jelena Marusic voe::Channel* channelPtr = ch.channel(); 1060d266054acece70259fc1e85026194154f41e5a0Jelena Marusic if (channelPtr == NULL) { 1070d266054acece70259fc1e85026194154f41e5a0Jelena Marusic shared_->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError, 1080d266054acece70259fc1e85026194154f41e5a0Jelena Marusic "RegisterExternalMediaProcessing() " 1090d266054acece70259fc1e85026194154f41e5a0Jelena Marusic "failed to locate channel"); 110470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return -1; 1110d266054acece70259fc1e85026194154f41e5a0Jelena Marusic } 1120d266054acece70259fc1e85026194154f41e5a0Jelena Marusic return channelPtr->DeRegisterExternalMediaProcessing(type); 113470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 1140d266054acece70259fc1e85026194154f41e5a0Jelena Marusic case kPlaybackAllChannelsMixed: { 1150d266054acece70259fc1e85026194154f41e5a0Jelena Marusic return shared_->output_mixer()->DeRegisterExternalMediaProcessing(); 116470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 1170d266054acece70259fc1e85026194154f41e5a0Jelena Marusic case kRecordingAllChannelsMixed: 1180d266054acece70259fc1e85026194154f41e5a0Jelena Marusic case kRecordingPreprocessing: { 1190d266054acece70259fc1e85026194154f41e5a0Jelena Marusic return shared_->transmit_mixer()->DeRegisterExternalMediaProcessing(type); 1200d266054acece70259fc1e85026194154f41e5a0Jelena Marusic } 1210d266054acece70259fc1e85026194154f41e5a0Jelena Marusic } 1220d266054acece70259fc1e85026194154f41e5a0Jelena Marusic return -1; 123470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 124470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 1251b60ceb499ee35460886f2bfaecee1f47319f925roosa@google.comint VoEExternalMediaImpl::GetAudioFrame(int channel, int desired_sample_rate_hz, 1261b60ceb499ee35460886f2bfaecee1f47319f925roosa@google.com AudioFrame* frame) { 1270d266054acece70259fc1e85026194154f41e5a0Jelena Marusic if (!shared_->statistics().Initialized()) { 1280d266054acece70259fc1e85026194154f41e5a0Jelena Marusic shared_->SetLastError(VE_NOT_INITED, kTraceError); 1290d266054acece70259fc1e85026194154f41e5a0Jelena Marusic return -1; 1300d266054acece70259fc1e85026194154f41e5a0Jelena Marusic } 1310d266054acece70259fc1e85026194154f41e5a0Jelena Marusic voe::ChannelOwner ch = shared_->channel_manager().GetChannel(channel); 1320d266054acece70259fc1e85026194154f41e5a0Jelena Marusic voe::Channel* channelPtr = ch.channel(); 1330d266054acece70259fc1e85026194154f41e5a0Jelena Marusic if (channelPtr == NULL) { 1340d266054acece70259fc1e85026194154f41e5a0Jelena Marusic shared_->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError, 1350d266054acece70259fc1e85026194154f41e5a0Jelena Marusic "GetAudioFrame() failed to locate channel"); 1360d266054acece70259fc1e85026194154f41e5a0Jelena Marusic return -1; 1370d266054acece70259fc1e85026194154f41e5a0Jelena Marusic } 1380d266054acece70259fc1e85026194154f41e5a0Jelena Marusic if (!channelPtr->ExternalMixing()) { 1390d266054acece70259fc1e85026194154f41e5a0Jelena Marusic shared_->SetLastError(VE_INVALID_OPERATION, kTraceError, 1400d266054acece70259fc1e85026194154f41e5a0Jelena Marusic "GetAudioFrame() was called on channel that is not" 1410d266054acece70259fc1e85026194154f41e5a0Jelena Marusic " externally mixed."); 1420d266054acece70259fc1e85026194154f41e5a0Jelena Marusic return -1; 1430d266054acece70259fc1e85026194154f41e5a0Jelena Marusic } 1440d266054acece70259fc1e85026194154f41e5a0Jelena Marusic if (!channelPtr->Playing()) { 1450d266054acece70259fc1e85026194154f41e5a0Jelena Marusic shared_->SetLastError( 1460d266054acece70259fc1e85026194154f41e5a0Jelena Marusic VE_INVALID_OPERATION, kTraceError, 1470d266054acece70259fc1e85026194154f41e5a0Jelena Marusic "GetAudioFrame() was called on channel that is not playing."); 1480d266054acece70259fc1e85026194154f41e5a0Jelena Marusic return -1; 1490d266054acece70259fc1e85026194154f41e5a0Jelena Marusic } 1500d266054acece70259fc1e85026194154f41e5a0Jelena Marusic if (desired_sample_rate_hz == -1) { 1510d266054acece70259fc1e85026194154f41e5a0Jelena Marusic shared_->SetLastError(VE_BAD_ARGUMENT, kTraceError, 1520d266054acece70259fc1e85026194154f41e5a0Jelena Marusic "GetAudioFrame() was called with bad sample rate."); 1530d266054acece70259fc1e85026194154f41e5a0Jelena Marusic return -1; 1540d266054acece70259fc1e85026194154f41e5a0Jelena Marusic } 1550d266054acece70259fc1e85026194154f41e5a0Jelena Marusic frame->sample_rate_hz_ = 1560d266054acece70259fc1e85026194154f41e5a0Jelena Marusic desired_sample_rate_hz == 0 ? -1 : desired_sample_rate_hz; 1570f4b3731c34e796da92572380855dbc7321c8cfeminyuel return channelPtr->GetAudioFrame(channel, frame); 1581b60ceb499ee35460886f2bfaecee1f47319f925roosa@google.com} 1591b60ceb499ee35460886f2bfaecee1f47319f925roosa@google.com 1601b60ceb499ee35460886f2bfaecee1f47319f925roosa@google.comint VoEExternalMediaImpl::SetExternalMixing(int channel, bool enable) { 1610d266054acece70259fc1e85026194154f41e5a0Jelena Marusic WEBRTC_TRACE(kTraceApiCall, kTraceVoice, 1620d266054acece70259fc1e85026194154f41e5a0Jelena Marusic VoEId(shared_->instance_id(), channel), 1630d266054acece70259fc1e85026194154f41e5a0Jelena Marusic "SetExternalMixing(channel=%d, enable=%d)", channel, enable); 1640d266054acece70259fc1e85026194154f41e5a0Jelena Marusic if (!shared_->statistics().Initialized()) { 1650d266054acece70259fc1e85026194154f41e5a0Jelena Marusic shared_->SetLastError(VE_NOT_INITED, kTraceError); 1660d266054acece70259fc1e85026194154f41e5a0Jelena Marusic return -1; 1670d266054acece70259fc1e85026194154f41e5a0Jelena Marusic } 1680d266054acece70259fc1e85026194154f41e5a0Jelena Marusic voe::ChannelOwner ch = shared_->channel_manager().GetChannel(channel); 1690d266054acece70259fc1e85026194154f41e5a0Jelena Marusic voe::Channel* channelPtr = ch.channel(); 1700d266054acece70259fc1e85026194154f41e5a0Jelena Marusic if (channelPtr == NULL) { 1710d266054acece70259fc1e85026194154f41e5a0Jelena Marusic shared_->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError, 1720d266054acece70259fc1e85026194154f41e5a0Jelena Marusic "SetExternalMixing() failed to locate channel"); 1730d266054acece70259fc1e85026194154f41e5a0Jelena Marusic return -1; 1740d266054acece70259fc1e85026194154f41e5a0Jelena Marusic } 1750d266054acece70259fc1e85026194154f41e5a0Jelena Marusic return channelPtr->SetExternalMixing(enable); 1761b60ceb499ee35460886f2bfaecee1f47319f925roosa@google.com} 1771b60ceb499ee35460886f2bfaecee1f47319f925roosa@google.com 178470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#endif // WEBRTC_VOICE_ENGINE_EXTERNAL_MEDIA_API 179470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 180470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} // namespace webrtc 181