LCOV - code coverage report
Current view: top level - media/webrtc/trunk/webrtc/voice_engine - voe_base_impl.cc (source / functions) Hit Total Coverage
Test: output.info Lines: 0 430 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 33 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
       3             :  *
       4             :  *  Use of this source code is governed by a BSD-style license
       5             :  *  that can be found in the LICENSE file in the root of the source
       6             :  *  tree. An additional intellectual property rights grant can be found
       7             :  *  in the file PATENTS.  All contributing project authors may
       8             :  *  be found in the AUTHORS file in the root of the source tree.
       9             :  */
      10             : 
      11             : #include "webrtc/voice_engine/voe_base_impl.h"
      12             : 
      13             : #include "webrtc/base/format_macros.h"
      14             : #include "webrtc/base/logging.h"
      15             : #include "webrtc/common_audio/signal_processing/include/signal_processing_library.h"
      16             : #include "webrtc/modules/audio_coding/codecs/builtin_audio_decoder_factory.h"
      17             : #include "webrtc/modules/audio_coding/include/audio_coding_module.h"
      18             : #include "webrtc/modules/audio_device/audio_device_impl.h"
      19             : #include "webrtc/modules/audio_processing/include/audio_processing.h"
      20             : #include "webrtc/system_wrappers/include/file_wrapper.h"
      21             : #include "webrtc/voice_engine/channel.h"
      22             : #include "webrtc/voice_engine/include/voe_errors.h"
      23             : #include "webrtc/voice_engine/output_mixer.h"
      24             : #include "webrtc/voice_engine/transmit_mixer.h"
      25             : #include "webrtc/voice_engine/utility.h"
      26             : #include "webrtc/voice_engine/voice_engine_impl.h"
      27             : 
      28             : namespace webrtc {
      29             : 
      30           0 : VoEBase* VoEBase::GetInterface(VoiceEngine* voiceEngine) {
      31           0 :   if (nullptr == voiceEngine) {
      32           0 :     return nullptr;
      33             :   }
      34           0 :   VoiceEngineImpl* s = static_cast<VoiceEngineImpl*>(voiceEngine);
      35           0 :   s->AddRef();
      36           0 :   return s;
      37             : }
      38             : 
      39           0 : VoEBaseImpl::VoEBaseImpl(voe::SharedData* shared)
      40             :     : voiceEngineObserverPtr_(nullptr),
      41           0 :       shared_(shared) {}
      42             : 
      43           0 : VoEBaseImpl::~VoEBaseImpl() {
      44           0 :   TerminateInternal();
      45           0 : }
      46             : 
      47           0 : void VoEBaseImpl::OnErrorIsReported(const ErrorCode error) {
      48           0 :   rtc::CritScope cs(&callbackCritSect_);
      49           0 :   int errCode = 0;
      50           0 :   if (error == AudioDeviceObserver::kRecordingError) {
      51           0 :     errCode = VE_RUNTIME_REC_ERROR;
      52           0 :     LOG_F(LS_ERROR) << "VE_RUNTIME_REC_ERROR";
      53           0 :   } else if (error == AudioDeviceObserver::kPlayoutError) {
      54           0 :     errCode = VE_RUNTIME_PLAY_ERROR;
      55           0 :     LOG_F(LS_ERROR) << "VE_RUNTIME_PLAY_ERROR";
      56             :   }
      57           0 :   if (voiceEngineObserverPtr_) {
      58             :     // Deliver callback (-1 <=> no channel dependency)
      59           0 :     voiceEngineObserverPtr_->CallbackOnError(-1, errCode);
      60             :   }
      61           0 : }
      62             : 
      63           0 : void VoEBaseImpl::OnWarningIsReported(const WarningCode warning) {
      64           0 :   rtc::CritScope cs(&callbackCritSect_);
      65           0 :   int warningCode = 0;
      66           0 :   if (warning == AudioDeviceObserver::kRecordingWarning) {
      67           0 :     warningCode = VE_RUNTIME_REC_WARNING;
      68           0 :     LOG_F(LS_WARNING) << "VE_RUNTIME_REC_WARNING";
      69           0 :   } else if (warning == AudioDeviceObserver::kPlayoutWarning) {
      70           0 :     warningCode = VE_RUNTIME_PLAY_WARNING;
      71           0 :     LOG_F(LS_WARNING) << "VE_RUNTIME_PLAY_WARNING";
      72             :   }
      73           0 :   if (voiceEngineObserverPtr_) {
      74             :     // Deliver callback (-1 <=> no channel dependency)
      75           0 :     voiceEngineObserverPtr_->CallbackOnError(-1, warningCode);
      76             :   }
      77           0 : }
      78             : 
      79           0 : int32_t VoEBaseImpl::RecordedDataIsAvailable(const void* audioSamples,
      80             :                                              const size_t nSamples,
      81             :                                              const size_t nBytesPerSample,
      82             :                                              const size_t nChannels,
      83             :                                              const uint32_t samplesPerSec,
      84             :                                              const uint32_t totalDelayMS,
      85             :                                              const int32_t clockDrift,
      86             :                                              const uint32_t currentMicLevel,
      87             :                                              const bool keyPressed,
      88             :                                              uint32_t& newMicLevel) {
      89           0 :   newMicLevel = static_cast<uint32_t>(ProcessRecordedDataWithAPM(
      90             :       nullptr, 0, audioSamples, samplesPerSec, nChannels, nSamples,
      91             :       totalDelayMS, clockDrift, currentMicLevel, keyPressed));
      92           0 :   return 0;
      93             : }
      94             : 
      95           0 : int32_t VoEBaseImpl::NeedMorePlayData(const size_t nSamples,
      96             :                                       const size_t nBytesPerSample,
      97             :                                       const size_t nChannels,
      98             :                                       const uint32_t samplesPerSec,
      99             :                                       void* audioSamples,
     100             :                                       size_t& nSamplesOut,
     101             :                                       int64_t* elapsed_time_ms,
     102             :                                       int64_t* ntp_time_ms) {
     103           0 :   GetPlayoutData(static_cast<int>(samplesPerSec), nChannels, nSamples, true,
     104           0 :                  audioSamples, elapsed_time_ms, ntp_time_ms);
     105           0 :   nSamplesOut = audioFrame_.samples_per_channel_;
     106           0 :   return 0;
     107             : }
     108             : 
     109           0 : void VoEBaseImpl::PushCaptureData(int voe_channel, const void* audio_data,
     110             :                                   int bits_per_sample, int sample_rate,
     111             :                                   size_t number_of_channels,
     112             :                                   size_t number_of_frames) {
     113           0 :   voe::ChannelOwner ch = shared_->channel_manager().GetChannel(voe_channel);
     114           0 :   voe::Channel* channel_ptr = ch.channel();
     115           0 :   if (!channel_ptr) return;
     116             : 
     117           0 :   if (channel_ptr->Sending()) {
     118             :     channel_ptr->Demultiplex(static_cast<const int16_t*>(audio_data),
     119           0 :                              sample_rate, number_of_frames, number_of_channels);
     120           0 :     channel_ptr->PrepareEncodeAndSend(sample_rate);
     121           0 :     channel_ptr->EncodeAndSend();
     122             :   }
     123             : }
     124             : 
     125           0 : void VoEBaseImpl::PullRenderData(int bits_per_sample,
     126             :                                  int sample_rate,
     127             :                                  size_t number_of_channels,
     128             :                                  size_t number_of_frames,
     129             :                                  void* audio_data, int64_t* elapsed_time_ms,
     130             :                                  int64_t* ntp_time_ms) {
     131           0 :   assert(bits_per_sample == 16);
     132           0 :   assert(number_of_frames == static_cast<size_t>(sample_rate / 100));
     133             : 
     134             :   GetPlayoutData(sample_rate, number_of_channels, number_of_frames, false,
     135           0 :                  audio_data, elapsed_time_ms, ntp_time_ms);
     136           0 : }
     137             : 
     138           0 : int VoEBaseImpl::RegisterVoiceEngineObserver(VoiceEngineObserver& observer) {
     139           0 :   rtc::CritScope cs(&callbackCritSect_);
     140           0 :   if (voiceEngineObserverPtr_) {
     141           0 :     shared_->SetLastError(
     142             :         VE_INVALID_OPERATION, kTraceError,
     143           0 :         "RegisterVoiceEngineObserver() observer already enabled");
     144           0 :     return -1;
     145             :   }
     146             : 
     147             :   // Register the observer in all active channels
     148           0 :   for (voe::ChannelManager::Iterator it(&shared_->channel_manager());
     149           0 :        it.IsValid(); it.Increment()) {
     150           0 :     it.GetChannel()->RegisterVoiceEngineObserver(observer);
     151             :   }
     152             : 
     153           0 :   shared_->transmit_mixer()->RegisterVoiceEngineObserver(observer);
     154           0 :   voiceEngineObserverPtr_ = &observer;
     155           0 :   return 0;
     156             : }
     157             : 
     158           0 : int VoEBaseImpl::DeRegisterVoiceEngineObserver() {
     159           0 :   rtc::CritScope cs(&callbackCritSect_);
     160           0 :   if (!voiceEngineObserverPtr_) {
     161           0 :     shared_->SetLastError(
     162             :         VE_INVALID_OPERATION, kTraceError,
     163           0 :         "DeRegisterVoiceEngineObserver() observer already disabled");
     164           0 :     return 0;
     165             :   }
     166           0 :   voiceEngineObserverPtr_ = nullptr;
     167             : 
     168             :   // Deregister the observer in all active channels
     169           0 :   for (voe::ChannelManager::Iterator it(&shared_->channel_manager());
     170           0 :        it.IsValid(); it.Increment()) {
     171           0 :     it.GetChannel()->DeRegisterVoiceEngineObserver();
     172             :   }
     173             : 
     174           0 :   return 0;
     175             : }
     176             : 
     177           0 : int VoEBaseImpl::Init(
     178             :     AudioDeviceModule* external_adm,
     179             :     AudioProcessing* audioproc,
     180             :     const rtc::scoped_refptr<AudioDecoderFactory>& decoder_factory) {
     181           0 :   rtc::CritScope cs(shared_->crit_sec());
     182           0 :   WebRtcSpl_Init();
     183           0 :   if (shared_->statistics().Initialized()) {
     184           0 :     return 0;
     185             :   }
     186           0 :   if (shared_->process_thread()) {
     187           0 :     shared_->process_thread()->Start();
     188             :   }
     189             : 
     190             :   // Create an internal ADM if the user has not added an external
     191             :   // ADM implementation as input to Init().
     192           0 :   if (external_adm == nullptr) {
     193             : #if !defined(WEBRTC_INCLUDE_INTERNAL_AUDIO_DEVICE)
     194             :     return -1;
     195             : #else
     196             :     // Create the internal ADM implementation.
     197           0 :     shared_->set_audio_device(AudioDeviceModule::Create(
     198           0 :         VoEId(shared_->instance_id(), -1), shared_->audio_device_layer()));
     199             : 
     200           0 :     if (shared_->audio_device() == nullptr) {
     201           0 :       shared_->SetLastError(VE_NO_MEMORY, kTraceCritical,
     202           0 :                             "Init() failed to create the ADM");
     203           0 :       return -1;
     204             :     }
     205             : #endif  // WEBRTC_INCLUDE_INTERNAL_AUDIO_DEVICE
     206             :   } else {
     207             :     // Use the already existing external ADM implementation.
     208           0 :     shared_->set_audio_device(external_adm);
     209           0 :     LOG_F(LS_INFO)
     210           0 :         << "An external ADM implementation will be used in VoiceEngine";
     211             :   }
     212             : 
     213             :   // Register the ADM to the process thread, which will drive the error
     214             :   // callback mechanism
     215           0 :   if (shared_->process_thread()) {
     216           0 :     shared_->process_thread()->RegisterModule(shared_->audio_device());
     217             :   }
     218             : 
     219           0 :   bool available = false;
     220             : 
     221             :   // --------------------
     222             :   // Reinitialize the ADM
     223             : 
     224             :   // Register the AudioObserver implementation
     225           0 :   if (shared_->audio_device()->RegisterEventObserver(this) != 0) {
     226           0 :     shared_->SetLastError(
     227             :         VE_AUDIO_DEVICE_MODULE_ERROR, kTraceWarning,
     228           0 :         "Init() failed to register event observer for the ADM");
     229             :   }
     230             : 
     231             :   // Register the AudioTransport implementation
     232           0 :   if (shared_->audio_device()->RegisterAudioCallback(this) != 0) {
     233           0 :     shared_->SetLastError(
     234             :         VE_AUDIO_DEVICE_MODULE_ERROR, kTraceWarning,
     235           0 :         "Init() failed to register audio callback for the ADM");
     236             :   }
     237             : 
     238             :   // ADM initialization
     239           0 :   if (shared_->audio_device()->Init() != 0) {
     240           0 :     shared_->SetLastError(VE_AUDIO_DEVICE_MODULE_ERROR, kTraceError,
     241           0 :                           "Init() failed to initialize the ADM");
     242           0 :     return -1;
     243             :   }
     244             : 
     245             :   // Initialize the default speaker
     246           0 :   if (shared_->audio_device()->SetPlayoutDevice(
     247           0 :           WEBRTC_VOICE_ENGINE_DEFAULT_DEVICE) != 0) {
     248           0 :     shared_->SetLastError(VE_AUDIO_DEVICE_MODULE_ERROR, kTraceInfo,
     249           0 :                           "Init() failed to set the default output device");
     250             :   }
     251           0 :   if (shared_->audio_device()->InitSpeaker() != 0) {
     252           0 :     shared_->SetLastError(VE_CANNOT_ACCESS_SPEAKER_VOL, kTraceInfo,
     253           0 :                           "Init() failed to initialize the speaker");
     254             :   }
     255             : 
     256             :   // Initialize the default microphone
     257           0 :   if (shared_->audio_device()->SetRecordingDevice(
     258           0 :           WEBRTC_VOICE_ENGINE_DEFAULT_DEVICE) != 0) {
     259           0 :     shared_->SetLastError(VE_SOUNDCARD_ERROR, kTraceInfo,
     260           0 :                           "Init() failed to set the default input device");
     261             :   }
     262           0 :   if (shared_->audio_device()->InitMicrophone() != 0) {
     263           0 :     shared_->SetLastError(VE_CANNOT_ACCESS_MIC_VOL, kTraceInfo,
     264           0 :                           "Init() failed to initialize the microphone");
     265             :   }
     266             : 
     267             :   // Set number of channels
     268           0 :   if (shared_->audio_device()->StereoPlayoutIsAvailable(&available) != 0) {
     269           0 :     shared_->SetLastError(VE_SOUNDCARD_ERROR, kTraceWarning,
     270           0 :                           "Init() failed to query stereo playout mode");
     271             :   }
     272           0 :   if (shared_->audio_device()->SetStereoPlayout(available) != 0) {
     273           0 :     shared_->SetLastError(VE_SOUNDCARD_ERROR, kTraceWarning,
     274           0 :                           "Init() failed to set mono/stereo playout mode");
     275             :   }
     276             : 
     277             :   // TODO(andrew): These functions don't tell us whether stereo recording
     278             :   // is truly available. We simply set the AudioProcessing input to stereo
     279             :   // here, because we have to wait until receiving the first frame to
     280             :   // determine the actual number of channels anyway.
     281             :   //
     282             :   // These functions may be changed; tracked here:
     283             :   // http://code.google.com/p/webrtc/issues/detail?id=204
     284           0 :   shared_->audio_device()->StereoRecordingIsAvailable(&available);
     285           0 :   if (shared_->audio_device()->SetStereoRecording(available) != 0) {
     286           0 :     shared_->SetLastError(VE_SOUNDCARD_ERROR, kTraceWarning,
     287           0 :                           "Init() failed to set mono/stereo recording mode");
     288             :   }
     289             : 
     290           0 :   if (!audioproc) {
     291           0 :     audioproc = AudioProcessing::Create();
     292           0 :     if (!audioproc) {
     293           0 :       LOG(LS_ERROR) << "Failed to create AudioProcessing.";
     294           0 :       shared_->SetLastError(VE_NO_MEMORY);
     295           0 :       return -1;
     296             :     }
     297             :   }
     298           0 :   shared_->set_audio_processing(audioproc);
     299             : 
     300             :   // Set the error state for any failures in this block.
     301           0 :   shared_->SetLastError(VE_APM_ERROR);
     302             :   // Configure AudioProcessing components.
     303           0 :   if (audioproc->high_pass_filter()->Enable(true) != 0) {
     304           0 :     LOG_F(LS_ERROR) << "Failed to enable high pass filter.";
     305           0 :     return -1;
     306             :   }
     307           0 :   if (audioproc->echo_cancellation()->enable_drift_compensation(false) != 0) {
     308           0 :     LOG_F(LS_ERROR) << "Failed to disable drift compensation.";
     309           0 :     return -1;
     310             :   }
     311           0 :   if (audioproc->noise_suppression()->set_level(kDefaultNsMode) != 0) {
     312           0 :     LOG_F(LS_ERROR) << "Failed to set noise suppression level: "
     313           0 :         << kDefaultNsMode;
     314           0 :     return -1;
     315             :   }
     316           0 :   GainControl* agc = audioproc->gain_control();
     317           0 :   if (agc->set_analog_level_limits(kMinVolumeLevel, kMaxVolumeLevel) != 0) {
     318           0 :     LOG_F(LS_ERROR) << "Failed to set analog level limits with minimum: "
     319           0 :         << kMinVolumeLevel << " and maximum: " << kMaxVolumeLevel;
     320           0 :     return -1;
     321             :   }
     322           0 :   if (agc->set_mode(kDefaultAgcMode) != 0) {
     323           0 :     LOG_F(LS_ERROR) << "Failed to set mode: " << kDefaultAgcMode;
     324           0 :     return -1;
     325             :   }
     326           0 :   if (agc->Enable(kDefaultAgcState) != 0) {
     327           0 :     LOG_F(LS_ERROR) << "Failed to set agc state: " << kDefaultAgcState;
     328           0 :     return -1;
     329             :   }
     330           0 :   shared_->SetLastError(0);  // Clear error state.
     331             : 
     332             : #ifdef WEBRTC_VOICE_ENGINE_AGC
     333             :   bool agc_enabled =
     334             :       agc->mode() == GainControl::kAdaptiveAnalog && agc->is_enabled();
     335             :   if (shared_->audio_device()->SetAGC(agc_enabled) != 0) {
     336             :     LOG_F(LS_ERROR) << "Failed to set agc to enabled: " << agc_enabled;
     337             :     shared_->SetLastError(VE_AUDIO_DEVICE_MODULE_ERROR);
     338             :     // TODO(ajm): No error return here due to
     339             :     // https://code.google.com/p/webrtc/issues/detail?id=1464
     340             :   }
     341             : #endif
     342             : 
     343           0 :   if (decoder_factory)
     344           0 :     decoder_factory_ = decoder_factory;
     345             :   else
     346           0 :     decoder_factory_ = CreateBuiltinAudioDecoderFactory();
     347             : 
     348           0 :   return shared_->statistics().SetInitialized();
     349             : }
     350             : 
     351           0 : int VoEBaseImpl::Terminate() {
     352           0 :   rtc::CritScope cs(shared_->crit_sec());
     353           0 :   return TerminateInternal();
     354             : }
     355             : 
     356           0 : int VoEBaseImpl::CreateChannel() {
     357           0 :   return CreateChannel(ChannelConfig());
     358             : }
     359             : 
     360           0 : int VoEBaseImpl::CreateChannel(const ChannelConfig& config) {
     361           0 :   rtc::CritScope cs(shared_->crit_sec());
     362           0 :   if (!shared_->statistics().Initialized()) {
     363           0 :     shared_->SetLastError(VE_NOT_INITED, kTraceError);
     364           0 :     return -1;
     365             :   }
     366             : 
     367           0 :   ChannelConfig config_copy(config);
     368           0 :   config_copy.acm_config.decoder_factory = decoder_factory_;
     369             :   voe::ChannelOwner channel_owner =
     370           0 :       shared_->channel_manager().CreateChannel(config_copy);
     371           0 :   return InitializeChannel(&channel_owner);
     372             : }
     373             : 
     374           0 : int VoEBaseImpl::InitializeChannel(voe::ChannelOwner* channel_owner) {
     375           0 :   if (channel_owner->channel()->SetEngineInformation(
     376           0 :           shared_->statistics(), *shared_->output_mixer(),
     377           0 :           *shared_->transmit_mixer(), *shared_->process_thread(),
     378           0 :           *shared_->audio_device(), voiceEngineObserverPtr_,
     379             :           &callbackCritSect_) != 0) {
     380           0 :     shared_->SetLastError(
     381             :         VE_CHANNEL_NOT_CREATED, kTraceError,
     382             :         "CreateChannel() failed to associate engine and channel."
     383           0 :         " Destroying channel.");
     384           0 :     shared_->channel_manager().DestroyChannel(
     385           0 :         channel_owner->channel()->ChannelId());
     386           0 :     return -1;
     387           0 :   } else if (channel_owner->channel()->Init() != 0) {
     388           0 :     shared_->SetLastError(
     389             :         VE_CHANNEL_NOT_CREATED, kTraceError,
     390             :         "CreateChannel() failed to initialize channel. Destroying"
     391           0 :         " channel.");
     392           0 :     shared_->channel_manager().DestroyChannel(
     393           0 :         channel_owner->channel()->ChannelId());
     394           0 :     return -1;
     395             :   }
     396           0 :   return channel_owner->channel()->ChannelId();
     397             : }
     398             : 
     399           0 : int VoEBaseImpl::DeleteChannel(int channel) {
     400           0 :   rtc::CritScope cs(shared_->crit_sec());
     401           0 :   if (!shared_->statistics().Initialized()) {
     402           0 :     shared_->SetLastError(VE_NOT_INITED, kTraceError);
     403           0 :     return -1;
     404             :   }
     405             : 
     406             :   {
     407           0 :     voe::ChannelOwner ch = shared_->channel_manager().GetChannel(channel);
     408           0 :     voe::Channel* channelPtr = ch.channel();
     409           0 :     if (channelPtr == nullptr) {
     410           0 :       shared_->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
     411           0 :                             "DeleteChannel() failed to locate channel");
     412           0 :       return -1;
     413             :     }
     414             :   }
     415             : 
     416           0 :   shared_->channel_manager().DestroyChannel(channel);
     417           0 :   if (StopSend() != 0) {
     418           0 :     return -1;
     419             :   }
     420           0 :   if (StopPlayout() != 0) {
     421           0 :     return -1;
     422             :   }
     423           0 :   return 0;
     424             : }
     425             : 
     426           0 : int VoEBaseImpl::StartReceive(int channel) {
     427           0 :   rtc::CritScope cs(shared_->crit_sec());
     428           0 :   if (!shared_->statistics().Initialized()) {
     429           0 :     shared_->SetLastError(VE_NOT_INITED, kTraceError);
     430           0 :     return -1;
     431             :   }
     432           0 :   voe::ChannelOwner ch = shared_->channel_manager().GetChannel(channel);
     433           0 :   voe::Channel* channelPtr = ch.channel();
     434           0 :   if (channelPtr == nullptr) {
     435           0 :     shared_->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
     436           0 :                           "StartReceive() failed to locate channel");
     437           0 :     return -1;
     438             :   }
     439           0 :   channelPtr->ResetDiscardedPacketCount();
     440           0 :   return 0;
     441             : }
     442             : 
     443           0 : int VoEBaseImpl::StartPlayout(int channel) {
     444           0 :   rtc::CritScope cs(shared_->crit_sec());
     445           0 :   if (!shared_->statistics().Initialized()) {
     446           0 :     shared_->SetLastError(VE_NOT_INITED, kTraceError);
     447           0 :     return -1;
     448             :   }
     449           0 :   voe::ChannelOwner ch = shared_->channel_manager().GetChannel(channel);
     450           0 :   voe::Channel* channelPtr = ch.channel();
     451           0 :   if (channelPtr == nullptr) {
     452           0 :     shared_->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
     453           0 :                           "StartPlayout() failed to locate channel");
     454           0 :     return -1;
     455             :   }
     456           0 :   if (channelPtr->Playing()) {
     457           0 :     return 0;
     458             :   }
     459           0 :   if (StartPlayout() != 0) {
     460           0 :     shared_->SetLastError(VE_AUDIO_DEVICE_MODULE_ERROR, kTraceError,
     461           0 :                           "StartPlayout() failed to start playout");
     462           0 :     return -1;
     463             :   }
     464           0 :   return channelPtr->StartPlayout();
     465             : }
     466             : 
     467           0 : int VoEBaseImpl::StopPlayout(int channel) {
     468           0 :   rtc::CritScope cs(shared_->crit_sec());
     469           0 :   if (!shared_->statistics().Initialized()) {
     470           0 :     shared_->SetLastError(VE_NOT_INITED, kTraceError);
     471           0 :     return -1;
     472             :   }
     473           0 :   voe::ChannelOwner ch = shared_->channel_manager().GetChannel(channel);
     474           0 :   voe::Channel* channelPtr = ch.channel();
     475           0 :   if (channelPtr == nullptr) {
     476           0 :     shared_->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
     477           0 :                           "StopPlayout() failed to locate channel");
     478           0 :     return -1;
     479             :   }
     480           0 :   if (channelPtr->StopPlayout() != 0) {
     481           0 :     LOG_F(LS_WARNING) << "StopPlayout() failed to stop playout for channel "
     482           0 :                       << channel;
     483             :   }
     484           0 :   return StopPlayout();
     485             : }
     486             : 
     487           0 : int VoEBaseImpl::StartSend(int channel) {
     488           0 :   rtc::CritScope cs(shared_->crit_sec());
     489           0 :   if (!shared_->statistics().Initialized()) {
     490           0 :     shared_->SetLastError(VE_NOT_INITED, kTraceError);
     491           0 :     return -1;
     492             :   }
     493           0 :   voe::ChannelOwner ch = shared_->channel_manager().GetChannel(channel);
     494           0 :   voe::Channel* channelPtr = ch.channel();
     495           0 :   if (channelPtr == nullptr) {
     496           0 :     shared_->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
     497           0 :                           "StartSend() failed to locate channel");
     498           0 :     return -1;
     499             :   }
     500           0 :   if (channelPtr->Sending()) {
     501           0 :     return 0;
     502             :   }
     503           0 :   if (StartSend() != 0) {
     504           0 :     shared_->SetLastError(VE_AUDIO_DEVICE_MODULE_ERROR, kTraceError,
     505           0 :                           "StartSend() failed to start recording");
     506           0 :     return -1;
     507             :   }
     508           0 :   return channelPtr->StartSend();
     509             : }
     510             : 
     511           0 : int VoEBaseImpl::StopSend(int channel) {
     512           0 :   rtc::CritScope cs(shared_->crit_sec());
     513           0 :   if (!shared_->statistics().Initialized()) {
     514           0 :     shared_->SetLastError(VE_NOT_INITED, kTraceError);
     515           0 :     return -1;
     516             :   }
     517           0 :   voe::ChannelOwner ch = shared_->channel_manager().GetChannel(channel);
     518           0 :   voe::Channel* channelPtr = ch.channel();
     519           0 :   if (channelPtr == nullptr) {
     520           0 :     shared_->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
     521           0 :                           "StopSend() failed to locate channel");
     522           0 :     return -1;
     523             :   }
     524           0 :   if (channelPtr->StopSend() != 0) {
     525           0 :     LOG_F(LS_WARNING) << "StopSend() failed to stop sending for channel "
     526           0 :                       << channel;
     527             :   }
     528           0 :   return StopSend();
     529             : }
     530             : 
     531           0 : int VoEBaseImpl::GetVersion(char version[1024]) {
     532           0 :   if (version == nullptr) {
     533           0 :     shared_->SetLastError(VE_INVALID_ARGUMENT, kTraceError);
     534           0 :     return -1;
     535             :   }
     536             : 
     537           0 :   std::string versionString = VoiceEngine::GetVersionString();
     538             : #ifdef WEBRTC_VOE_EXTERNAL_REC_AND_PLAYOUT
     539           0 :   versionString += "External recording and playout build";
     540             : #endif
     541           0 :   RTC_DCHECK_GT(1024, versionString.size() + 1);
     542           0 :   char* end = std::copy(versionString.cbegin(), versionString.cend(), version);
     543           0 :   end[0] = '\n';
     544           0 :   end[1] = '\0';
     545           0 :   return 0;
     546             : }
     547             : 
     548           0 : int VoEBaseImpl::LastError() { return (shared_->statistics().LastError()); }
     549             : 
     550           0 : int32_t VoEBaseImpl::StartPlayout() {
     551           0 :   if (!shared_->audio_device()->Playing()) {
     552           0 :     if (!shared_->ext_playout()) {
     553           0 :       if (shared_->audio_device()->InitPlayout() != 0) {
     554           0 :         LOG_F(LS_ERROR) << "Failed to initialize playout";
     555           0 :         return -1;
     556             :       }
     557           0 :       if (shared_->audio_device()->StartPlayout() != 0) {
     558           0 :         LOG_F(LS_ERROR) << "Failed to start playout";
     559           0 :         return -1;
     560             :       }
     561             :     }
     562             :   }
     563           0 :   return 0;
     564             : }
     565             : 
     566           0 : int32_t VoEBaseImpl::StopPlayout() {
     567             :   // Stop audio-device playing if no channel is playing out
     568           0 :   if (shared_->NumOfPlayingChannels() == 0) {
     569           0 :     if (shared_->audio_device()->StopPlayout() != 0) {
     570           0 :       shared_->SetLastError(VE_CANNOT_STOP_PLAYOUT, kTraceError,
     571           0 :                             "StopPlayout() failed to stop playout");
     572           0 :       return -1;
     573             :     }
     574             :   }
     575           0 :   return 0;
     576             : }
     577             : 
     578           0 : int32_t VoEBaseImpl::StartSend() {
     579           0 :   if (!shared_->ext_recording()) {
     580           0 :     if (!shared_->audio_device()->RecordingIsInitialized() &&
     581           0 :         !shared_->audio_device()->Recording()) {
     582           0 :       if (shared_->audio_device()->InitRecording() != 0) {
     583           0 :         LOG_F(LS_ERROR) << "Failed to initialize recording";
     584           0 :         return -1;
     585             :       }
     586             :     }
     587           0 :     if (!shared_->audio_device()->Recording()) {
     588           0 :       if (shared_->audio_device()->StartRecording() != 0) {
     589           0 :         LOG_F(LS_ERROR) << "Failed to start recording";
     590           0 :         return -1;
     591             :       }
     592             :     }
     593             :   }
     594           0 :   return 0;
     595             : }
     596             : 
     597           0 : int32_t VoEBaseImpl::StopSend() {
     598           0 :   if (shared_->NumOfSendingChannels() == 0 &&
     599           0 :       !shared_->transmit_mixer()->IsRecordingMic()) {
     600             :     // Stop audio-device recording if no channel is recording
     601           0 :     if (shared_->audio_device()->StopRecording() != 0) {
     602           0 :       shared_->SetLastError(VE_CANNOT_STOP_RECORDING, kTraceError,
     603           0 :                             "StopSend() failed to stop recording");
     604           0 :       return -1;
     605             :     }
     606           0 :     shared_->transmit_mixer()->StopSend();
     607             :   }
     608             : 
     609           0 :   return 0;
     610             : }
     611             : 
     612           0 : int32_t VoEBaseImpl::TerminateInternal() {
     613             :   // Delete any remaining channel objects
     614           0 :   shared_->channel_manager().DestroyAllChannels();
     615             : 
     616           0 :   if (shared_->process_thread()) {
     617           0 :     if (shared_->audio_device()) {
     618           0 :       shared_->process_thread()->DeRegisterModule(shared_->audio_device());
     619             :     }
     620           0 :     shared_->process_thread()->Stop();
     621             :   }
     622             : 
     623           0 :   if (shared_->audio_device()) {
     624           0 :     if (shared_->audio_device()->StopPlayout() != 0) {
     625           0 :       shared_->SetLastError(VE_SOUNDCARD_ERROR, kTraceWarning,
     626           0 :                             "TerminateInternal() failed to stop playout");
     627             :     }
     628           0 :     if (shared_->audio_device()->StopRecording() != 0) {
     629           0 :       shared_->SetLastError(VE_SOUNDCARD_ERROR, kTraceWarning,
     630           0 :                             "TerminateInternal() failed to stop recording");
     631             :     }
     632           0 :     if (shared_->audio_device()->RegisterEventObserver(nullptr) != 0) {
     633           0 :       shared_->SetLastError(
     634             :           VE_AUDIO_DEVICE_MODULE_ERROR, kTraceWarning,
     635             :           "TerminateInternal() failed to de-register event observer "
     636           0 :           "for the ADM");
     637             :     }
     638           0 :     if (shared_->audio_device()->RegisterAudioCallback(nullptr) != 0) {
     639           0 :       shared_->SetLastError(
     640             :           VE_AUDIO_DEVICE_MODULE_ERROR, kTraceWarning,
     641             :           "TerminateInternal() failed to de-register audio callback "
     642           0 :           "for the ADM");
     643             :     }
     644           0 :     if (shared_->audio_device()->Terminate() != 0) {
     645           0 :       shared_->SetLastError(VE_AUDIO_DEVICE_MODULE_ERROR, kTraceError,
     646           0 :                             "TerminateInternal() failed to terminate the ADM");
     647             :     }
     648           0 :     shared_->set_audio_device(nullptr);
     649             :   }
     650             : 
     651           0 :   if (shared_->audio_processing()) {
     652           0 :     shared_->set_audio_processing(nullptr);
     653             :   }
     654             : 
     655           0 :   return shared_->statistics().SetUnInitialized();
     656             : }
     657             : 
     658           0 : int VoEBaseImpl::ProcessRecordedDataWithAPM(
     659             :     const int voe_channels[], size_t number_of_voe_channels,
     660             :     const void* audio_data, uint32_t sample_rate, size_t number_of_channels,
     661             :     size_t number_of_frames, uint32_t audio_delay_milliseconds,
     662             :     int32_t clock_drift, uint32_t volume, bool key_pressed) {
     663           0 :   assert(shared_->transmit_mixer() != nullptr);
     664           0 :   assert(shared_->audio_device() != nullptr);
     665             : 
     666           0 :   uint32_t max_volume = 0;
     667           0 :   uint16_t voe_mic_level = 0;
     668             :   // Check for zero to skip this calculation; the consumer may use this to
     669             :   // indicate no volume is available.
     670           0 :   if (volume != 0) {
     671             :     // Scale from ADM to VoE level range
     672           0 :     if (shared_->audio_device()->MaxMicrophoneVolume(&max_volume) == 0) {
     673           0 :       if (max_volume) {
     674           0 :         voe_mic_level = static_cast<uint16_t>(
     675           0 :             (volume * kMaxVolumeLevel + static_cast<int>(max_volume / 2)) /
     676             :             max_volume);
     677             :       }
     678             :     }
     679             :     // We learned that on certain systems (e.g Linux) the voe_mic_level
     680             :     // can be greater than the maxVolumeLevel therefore
     681             :     // we are going to cap the voe_mic_level to the maxVolumeLevel
     682             :     // and change the maxVolume to volume if it turns out that
     683             :     // the voe_mic_level is indeed greater than the maxVolumeLevel.
     684           0 :     if (voe_mic_level > kMaxVolumeLevel) {
     685           0 :       voe_mic_level = kMaxVolumeLevel;
     686           0 :       max_volume = volume;
     687             :     }
     688             :   }
     689             : 
     690             :   // Perform channel-independent operations
     691             :   // (APM, mix with file, record to file, mute, etc.)
     692           0 :   shared_->transmit_mixer()->PrepareDemux(
     693             :       audio_data, number_of_frames, number_of_channels, sample_rate,
     694             :       static_cast<uint16_t>(audio_delay_milliseconds), clock_drift,
     695           0 :       voe_mic_level, key_pressed);
     696             : 
     697             :   // Copy the audio frame to each sending channel and perform
     698             :   // channel-dependent operations (file mixing, mute, etc.), encode and
     699             :   // packetize+transmit the RTP packet. When |number_of_voe_channels| == 0,
     700             :   // do the operations on all the existing VoE channels; otherwise the
     701             :   // operations will be done on specific channels.
     702           0 :   if (number_of_voe_channels == 0) {
     703           0 :     shared_->transmit_mixer()->DemuxAndMix();
     704           0 :     shared_->transmit_mixer()->EncodeAndSend();
     705             :   } else {
     706           0 :     shared_->transmit_mixer()->DemuxAndMix(voe_channels,
     707           0 :                                            number_of_voe_channels);
     708           0 :     shared_->transmit_mixer()->EncodeAndSend(voe_channels,
     709           0 :                                              number_of_voe_channels);
     710             :   }
     711             : 
     712             :   // Scale from VoE to ADM level range.
     713           0 :   uint32_t new_voe_mic_level = shared_->transmit_mixer()->CaptureLevel();
     714           0 :   if (new_voe_mic_level != voe_mic_level) {
     715             :     // Return the new volume if AGC has changed the volume.
     716           0 :     return static_cast<int>((new_voe_mic_level * max_volume +
     717           0 :                              static_cast<int>(kMaxVolumeLevel / 2)) /
     718           0 :                             kMaxVolumeLevel);
     719             :   }
     720             : 
     721             :   // Return 0 to indicate no change on the volume.
     722           0 :   return 0;
     723             : }
     724             : 
     725           0 : void VoEBaseImpl::GetPlayoutData(int sample_rate, size_t number_of_channels,
     726             :                                  size_t number_of_frames, bool feed_data_to_apm,
     727             :                                  void* audio_data, int64_t* elapsed_time_ms,
     728             :                                  int64_t* ntp_time_ms) {
     729           0 :   assert(shared_->output_mixer() != nullptr);
     730             : 
     731             :   // TODO(andrew): if the device is running in mono, we should tell the mixer
     732             :   // here so that it will only request mono from AudioCodingModule.
     733             :   // Perform mixing of all active participants (channel-based mixing)
     734           0 :   shared_->output_mixer()->MixActiveChannels();
     735             : 
     736             :   // Additional operations on the combined signal
     737           0 :   shared_->output_mixer()->DoOperationsOnCombinedSignal(feed_data_to_apm);
     738             : 
     739             :   // Retrieve the final output mix (resampled to match the ADM)
     740           0 :   shared_->output_mixer()->GetMixedAudio(sample_rate, number_of_channels,
     741           0 :                                          &audioFrame_);
     742             : 
     743           0 :   assert(number_of_frames == audioFrame_.samples_per_channel_);
     744           0 :   assert(sample_rate == audioFrame_.sample_rate_hz_);
     745             : 
     746             :   // Deliver audio (PCM) samples to the ADM
     747           0 :   memcpy(audio_data, audioFrame_.data_,
     748           0 :          sizeof(int16_t) * number_of_frames * number_of_channels);
     749             : 
     750           0 :   *elapsed_time_ms = audioFrame_.elapsed_time_ms_;
     751           0 :   *ntp_time_ms = audioFrame_.ntp_time_ms_;
     752           0 : }
     753             : 
     754           0 : int VoEBaseImpl::AssociateSendChannel(int channel,
     755             :                                       int accociate_send_channel) {
     756           0 :   rtc::CritScope cs(shared_->crit_sec());
     757             : 
     758           0 :   if (!shared_->statistics().Initialized()) {
     759           0 :       shared_->SetLastError(VE_NOT_INITED, kTraceError);
     760           0 :       return -1;
     761             :   }
     762             : 
     763           0 :   voe::ChannelOwner ch = shared_->channel_manager().GetChannel(channel);
     764           0 :   voe::Channel* channel_ptr = ch.channel();
     765           0 :   if (channel_ptr == NULL) {
     766           0 :     shared_->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
     767           0 :         "AssociateSendChannel() failed to locate channel");
     768           0 :     return -1;
     769             :   }
     770             : 
     771           0 :   ch = shared_->channel_manager().GetChannel(accociate_send_channel);
     772           0 :   voe::Channel* accociate_send_channel_ptr = ch.channel();
     773           0 :   if (accociate_send_channel_ptr == NULL) {
     774           0 :     shared_->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
     775           0 :         "AssociateSendChannel() failed to locate accociate_send_channel");
     776           0 :     return -1;
     777             :   }
     778             : 
     779           0 :   channel_ptr->set_associate_send_channel(ch);
     780           0 :   return 0;
     781             : }
     782             : 
     783             : }  // namespace webrtc

Generated by: LCOV version 1.13