voe_external_media_impl.cc revision 79af734807109d119573ce23daa1a2bff0f0eeca
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 11470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#include "voe_external_media_impl.h" 12470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 13470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#include "channel.h" 14470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#include "critical_section_wrapper.h" 15470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#include "output_mixer.h" 16470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#include "trace.h" 17470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#include "transmit_mixer.h" 18470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#include "voice_engine_impl.h" 19470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#include "voe_errors.h" 20470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 21470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comnamespace webrtc { 22470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 23470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comVoEExternalMedia* VoEExternalMedia::GetInterface(VoiceEngine* voiceEngine) 24470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{ 25470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#ifndef WEBRTC_VOICE_ENGINE_EXTERNAL_MEDIA_API 26470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return NULL; 27470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#else 28470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com if (NULL == voiceEngine) 29470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 30470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return NULL; 31470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 32470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com VoiceEngineImpl* s = reinterpret_cast<VoiceEngineImpl*> (voiceEngine); 33470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com VoEExternalMediaImpl* d = s; 34470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com (*d)++; 35470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return (d); 36470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#endif 37470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 38470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 39470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#ifdef WEBRTC_VOICE_ENGINE_EXTERNAL_MEDIA_API 40470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 41470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comVoEExternalMediaImpl::VoEExternalMediaImpl() 42470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com : playout_delay_ms_(0) 43470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{ 44470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com WEBRTC_TRACE(kTraceMemory, kTraceVoice, VoEId(_instanceId,-1), 45470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "VoEExternalMediaImpl() - ctor"); 46470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 47470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 48470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comVoEExternalMediaImpl::~VoEExternalMediaImpl() 49470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{ 50470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com WEBRTC_TRACE(kTraceMemory, kTraceVoice, VoEId(_instanceId,-1), 51470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "~VoEExternalMediaImpl() - dtor"); 52470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 53470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 54470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint VoEExternalMediaImpl::Release() 55470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{ 56470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_instanceId,-1), 57470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "VoEExternalMedia::Release()"); 58470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com (*this)--; 59470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com int refCount = GetCount(); 60470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com if (refCount < 0) 61470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 62470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com Reset(); 63470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _engineStatistics.SetLastError(VE_INTERFACE_NOT_FOUND, 64470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com kTraceWarning); 65470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return (-1); 66470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 67470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, VoEId(_instanceId,-1), 68470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "VoEExternalMedia reference counter = %d", refCount); 69470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return (refCount); 70470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 71470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 72470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint VoEExternalMediaImpl::RegisterExternalMediaProcessing( 73470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com int channel, 74470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com ProcessingTypes type, 75470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com VoEMediaProcess& processObject) 76470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{ 77470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_instanceId,-1), 78470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "RegisterExternalMediaProcessing(channel=%d, type=%d, " 79470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "processObject=0x%x)", channel, type, &processObject); 802638577f0326a5929e31411bb092274351324d49leozwang@webrtc.org ANDROID_NOT_SUPPORTED(_engineStatistics); 81470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com IPHONE_NOT_SUPPORTED(); 82470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com if (!_engineStatistics.Initialized()) 83470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 84470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _engineStatistics.SetLastError(VE_NOT_INITED, kTraceError); 85470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return -1; 86470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 87470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com switch (type) 88470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 89470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com case kPlaybackPerChannel: 90470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com case kRecordingPerChannel: 91470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 92470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com voe::ScopedChannel sc(_channelManager, channel); 93470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com voe::Channel* channelPtr = sc.ChannelPtr(); 94470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com if (channelPtr == NULL) 95470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 96470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _engineStatistics.SetLastError( 97470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com VE_CHANNEL_NOT_VALID, kTraceError, 98470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "RegisterExternalMediaProcessing() " 99470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "failed to locate channel"); 100470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return -1; 101470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 102470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return channelPtr->RegisterExternalMediaProcessing(type, 103470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com processObject); 104470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 105470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com case kPlaybackAllChannelsMixed: 106470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 107470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return _outputMixerPtr->RegisterExternalMediaProcessing( 108470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com processObject); 109470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 110470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com case kRecordingAllChannelsMixed: 111470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 112470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return _transmitMixerPtr->RegisterExternalMediaProcessing( 113470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com processObject); 114470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 115470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com default: 116470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 117470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _engineStatistics.SetLastError( 118470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com VE_INVALID_ARGUMENT, kTraceError, 119470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "RegisterExternalMediaProcessing() invalid process type"); 120470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return -1; 121470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 122470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 123470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return 0; 124470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 125470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 126470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint VoEExternalMediaImpl::DeRegisterExternalMediaProcessing( 127470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com int channel, 128470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com ProcessingTypes type) 129470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{ 130470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_instanceId,-1), 131470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "DeRegisterExternalMediaProcessing(channel=%d)", channel); 1322638577f0326a5929e31411bb092274351324d49leozwang@webrtc.org ANDROID_NOT_SUPPORTED(_engineStatistics); 133470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com IPHONE_NOT_SUPPORTED(); 134470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com if (!_engineStatistics.Initialized()) 135470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 136470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _engineStatistics.SetLastError(VE_NOT_INITED, kTraceError); 137470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return -1; 138470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 139470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com switch (type) 140470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 141470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com case kPlaybackPerChannel: 142470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com case kRecordingPerChannel: 143470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 144470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com voe::ScopedChannel sc(_channelManager, channel); 145470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com voe::Channel* channelPtr = sc.ChannelPtr(); 146470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com if (channelPtr == NULL) 147470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 148470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _engineStatistics.SetLastError( 149470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com VE_CHANNEL_NOT_VALID, kTraceError, 150470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "RegisterExternalMediaProcessing() " 151470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "failed to locate channel"); 152470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return -1; 153470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 154470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return channelPtr->DeRegisterExternalMediaProcessing(type); 155470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 156470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com case kPlaybackAllChannelsMixed: 157470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 158470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return _outputMixerPtr->DeRegisterExternalMediaProcessing(); 159470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 160470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com case kRecordingAllChannelsMixed: 161470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 162470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return _transmitMixerPtr->DeRegisterExternalMediaProcessing(); 163470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 164470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com default: 165470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 166470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _engineStatistics.SetLastError( 167470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com VE_INVALID_ARGUMENT, kTraceError, 168470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "RegisterExternalMediaProcessing() invalid process type"); 169470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return -1; 170470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 171470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 172470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 173470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 174470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint VoEExternalMediaImpl::SetExternalRecordingStatus(bool enable) 175470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{ 176470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_instanceId,-1), 177470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "SetExternalRecordingStatus(enable=%d)", enable); 1782638577f0326a5929e31411bb092274351324d49leozwang@webrtc.org ANDROID_NOT_SUPPORTED(_engineStatistics); 179470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com IPHONE_NOT_SUPPORTED(); 180470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#ifdef WEBRTC_VOE_EXTERNAL_REC_AND_PLAYOUT 181470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com if (_audioDevicePtr->Recording()) 182470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 183470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _engineStatistics.SetLastError( 184470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com VE_ALREADY_SENDING, 185470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com kTraceError, 186470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "SetExternalRecordingStatus() cannot set state while sending"); 187470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return -1; 188470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 189470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _externalRecording = enable; 190470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return 0; 191470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#else 192470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _engineStatistics.SetLastError( 193470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com VE_FUNC_NOT_SUPPORTED, 194470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com kTraceError, 195470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "SetExternalRecordingStatus() external recording is not supported"); 196470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return -1; 197470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#endif 198470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 199470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 200470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint VoEExternalMediaImpl::ExternalRecordingInsertData( 201470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com const WebRtc_Word16 speechData10ms[], 202470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com int lengthSamples, 203470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com int samplingFreqHz, 204470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com int current_delay_ms) 205470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{ 206470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,-1), 207470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "ExternalRecordingInsertData(speechData10ms=0x%x," 208470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com " lengthSamples=%u, samplingFreqHz=%d, current_delay_ms=%d)", 209470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com &speechData10ms[0], lengthSamples, samplingFreqHz, 210470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com current_delay_ms); 2112638577f0326a5929e31411bb092274351324d49leozwang@webrtc.org ANDROID_NOT_SUPPORTED(_engineStatistics); 212470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com IPHONE_NOT_SUPPORTED(); 213470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 214470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#ifdef WEBRTC_VOE_EXTERNAL_REC_AND_PLAYOUT 215470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com if (!_engineStatistics.Initialized()) 216470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 217470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _engineStatistics.SetLastError(VE_NOT_INITED, kTraceError); 218470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return -1; 219470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 220470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com if (!_externalRecording) 221470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 222470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _engineStatistics.SetLastError( 223470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com VE_INVALID_OPERATION, 224470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com kTraceError, 225470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "ExternalRecordingInsertData() external recording is not enabled"); 226470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return -1; 227470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 228470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com if (NumOfSendingChannels() == 0) 229470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 230470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _engineStatistics.SetLastError( 231470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com VE_ALREADY_SENDING, 232470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com kTraceError, 233470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "SetExternalRecordingStatus() no channel is sending"); 234470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return -1; 235470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 236470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com if ((16000 != samplingFreqHz) && (32000 != samplingFreqHz) && 237470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com (48000 != samplingFreqHz) && (44000 != samplingFreqHz)) 238470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 239470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _engineStatistics.SetLastError( 240470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com VE_INVALID_ARGUMENT, 241470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com kTraceError, 242470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "SetExternalRecordingStatus() invalid sample rate"); 243470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return -1; 244470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 245470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com if ((0 == lengthSamples) || 246470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com ((lengthSamples % (samplingFreqHz / 100)) != 0)) 247470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 248470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _engineStatistics.SetLastError( 249470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com VE_INVALID_ARGUMENT, 250470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com kTraceError, 251470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "SetExternalRecordingStatus() invalid buffer size"); 252470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return -1; 253470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 254470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com if (current_delay_ms < 0) 255470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 256470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _engineStatistics.SetLastError( 257470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com VE_INVALID_ARGUMENT, 258470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com kTraceError, 259470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "SetExternalRecordingStatus() invalid delay)"); 260470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return -1; 261470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 262470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 263470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com WebRtc_UWord16 blockSize = samplingFreqHz / 100; 264470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com WebRtc_UWord32 nBlocks = lengthSamples / blockSize; 265470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com WebRtc_Word16 totalDelayMS = 0; 266470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com WebRtc_UWord16 playoutDelayMS = 0; 267470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 268470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com for (WebRtc_UWord32 i = 0; i < nBlocks; i++) 269470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 270470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com if (!_externalPlayout) 271470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 272470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com // Use real playout delay if external playout is not enabled. 27379af734807109d119573ce23daa1a2bff0f0eecaxians@webrtc.org if (_audioDevicePtr->PlayoutDelay(&playoutDelayMS) != 0) { 27479af734807109d119573ce23daa1a2bff0f0eecaxians@webrtc.org _engineStatistics.SetLastError( 27579af734807109d119573ce23daa1a2bff0f0eecaxians@webrtc.org VE_AUDIO_DEVICE_MODULE_ERROR, kTraceWarning, 27679af734807109d119573ce23daa1a2bff0f0eecaxians@webrtc.org "PlayoutDelay() unable to get the playout delay"); 27779af734807109d119573ce23daa1a2bff0f0eecaxians@webrtc.org } 278470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com totalDelayMS = current_delay_ms + playoutDelayMS; 279470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 280470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com else 281470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 282470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com // Use stored delay value given the last call 283470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com // to ExternalPlayoutGetData. 284470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com totalDelayMS = current_delay_ms + playout_delay_ms_; 285470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com // Compensate for block sizes larger than 10ms 286470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com totalDelayMS -= (WebRtc_Word16)(i*10); 287470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com if (totalDelayMS < 0) 288470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com totalDelayMS = 0; 289470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 290470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _transmitMixerPtr->PrepareDemux( 291470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com (const WebRtc_Word8*)(&speechData10ms[i*blockSize]), 292470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com blockSize, 293470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 1, 294470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com samplingFreqHz, 295470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com totalDelayMS, 296470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 0, 297470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 0); 298470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 299470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _transmitMixerPtr->DemuxAndMix(); 300470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _transmitMixerPtr->EncodeAndSend(); 301470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 302470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return 0; 303470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#else 304470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _engineStatistics.SetLastError( 305470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com VE_FUNC_NOT_SUPPORTED, 306470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com kTraceError, 307470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "ExternalRecordingInsertData() external recording is not supported"); 308470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return -1; 309470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#endif 310470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 311470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 312470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint VoEExternalMediaImpl::SetExternalPlayoutStatus(bool enable) 313470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{ 314470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_instanceId,-1), 315470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "SetExternalPlayoutStatus(enable=%d)", enable); 3162638577f0326a5929e31411bb092274351324d49leozwang@webrtc.org ANDROID_NOT_SUPPORTED(_engineStatistics); 317470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com IPHONE_NOT_SUPPORTED(); 318470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#ifdef WEBRTC_VOE_EXTERNAL_REC_AND_PLAYOUT 319470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com if (_audioDevicePtr->Playing()) 320470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 321470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _engineStatistics.SetLastError( 322470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com VE_ALREADY_SENDING, 323470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com kTraceError, 324470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "SetExternalPlayoutStatus() cannot set state while playing"); 325470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return -1; 326470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 327470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _externalPlayout = enable; 328470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return 0; 329470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#else 330470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _engineStatistics.SetLastError( 331470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com VE_FUNC_NOT_SUPPORTED, 332470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com kTraceError, 333470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "SetExternalPlayoutStatus() external playout is not supported"); 334470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return -1; 335470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#endif 336470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 337470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 338470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint VoEExternalMediaImpl::ExternalPlayoutGetData( 339470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com WebRtc_Word16 speechData10ms[], 340470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com int samplingFreqHz, 341470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com int current_delay_ms, 342470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com int& lengthSamples) 343470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{ 344470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,-1), 345470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "ExternalPlayoutGetData(speechData10ms=0x%x, samplingFreqHz=%d" 346470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com ", current_delay_ms=%d)", &speechData10ms[0], samplingFreqHz, 347470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com current_delay_ms); 3482638577f0326a5929e31411bb092274351324d49leozwang@webrtc.org ANDROID_NOT_SUPPORTED(_engineStatistics); 349470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com IPHONE_NOT_SUPPORTED(); 350470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#ifdef WEBRTC_VOE_EXTERNAL_REC_AND_PLAYOUT 351470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com if (!_engineStatistics.Initialized()) 352470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 353470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _engineStatistics.SetLastError(VE_NOT_INITED, kTraceError); 354470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return -1; 355470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 356470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com if (!_externalPlayout) 357470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 358470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _engineStatistics.SetLastError( 359470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com VE_INVALID_OPERATION, 360470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com kTraceError, 361470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "ExternalPlayoutGetData() external playout is not enabled"); 362470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return -1; 363470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 364470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com if ((16000 != samplingFreqHz) && (32000 != samplingFreqHz) && 365470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com (48000 != samplingFreqHz) && (44000 != samplingFreqHz)) 366470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 367470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _engineStatistics.SetLastError( 368470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com VE_INVALID_ARGUMENT, 369470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com kTraceError, 370470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "ExternalPlayoutGetData() invalid sample rate"); 371470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return -1; 372470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 373470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com if (current_delay_ms < 0) 374470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 375470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _engineStatistics.SetLastError( 376470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com VE_INVALID_ARGUMENT, 377470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com kTraceError, 378470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "ExternalPlayoutGetData() invalid delay)"); 379470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return -1; 380470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 381470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 382470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com AudioFrame audioFrame; 383470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 384470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com // Retrieve mixed output at the specified rate 385470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _outputMixerPtr->MixActiveChannels(); 386470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _outputMixerPtr->DoOperationsOnCombinedSignal(); 387470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _outputMixerPtr->GetMixedAudio(samplingFreqHz, 1, audioFrame); 388470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 389470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com // Deliver audio (PCM) samples to the external sink 390470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com memcpy(speechData10ms, 391470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com audioFrame._payloadData, 392470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com sizeof(WebRtc_Word16)*(audioFrame._payloadDataLengthInSamples)); 393470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com lengthSamples = audioFrame._payloadDataLengthInSamples; 394470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 395470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com // Store current playout delay (to be used by ExternalRecordingInsertData). 396470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com playout_delay_ms_ = current_delay_ms; 397470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 398470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return 0; 399470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#else 400470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _engineStatistics.SetLastError( 401470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com VE_FUNC_NOT_SUPPORTED, 402470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com kTraceError, 403470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "ExternalPlayoutGetData() external playout is not supported"); 404470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return -1; 405470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#endif 406470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 407470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 408470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#endif // WEBRTC_VOICE_ENGINE_EXTERNAL_MEDIA_API 409470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 410470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} // namespace webrtc 411