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 
GetInterface(VoiceEngine * voiceEngine)30 VoEBase* VoEBase::GetInterface(VoiceEngine* voiceEngine) {
31   if (nullptr == voiceEngine) {
32     return nullptr;
33   }
34   VoiceEngineImpl* s = static_cast<VoiceEngineImpl*>(voiceEngine);
35   s->AddRef();
36   return s;
37 }
38 
VoEBaseImpl(voe::SharedData * shared)39 VoEBaseImpl::VoEBaseImpl(voe::SharedData* shared)
40     : voiceEngineObserverPtr_(nullptr),
41       shared_(shared) {}
42 
~VoEBaseImpl()43 VoEBaseImpl::~VoEBaseImpl() {
44   TerminateInternal();
45 }
46 
OnErrorIsReported(const ErrorCode error)47 void VoEBaseImpl::OnErrorIsReported(const ErrorCode error) {
48   rtc::CritScope cs(&callbackCritSect_);
49   int errCode = 0;
50   if (error == AudioDeviceObserver::kRecordingError) {
51     errCode = VE_RUNTIME_REC_ERROR;
52     LOG_F(LS_ERROR) << "VE_RUNTIME_REC_ERROR";
53   } else if (error == AudioDeviceObserver::kPlayoutError) {
54     errCode = VE_RUNTIME_PLAY_ERROR;
55     LOG_F(LS_ERROR) << "VE_RUNTIME_PLAY_ERROR";
56   }
57   if (voiceEngineObserverPtr_) {
58     // Deliver callback (-1 <=> no channel dependency)
59     voiceEngineObserverPtr_->CallbackOnError(-1, errCode);
60   }
61 }
62 
OnWarningIsReported(const WarningCode warning)63 void VoEBaseImpl::OnWarningIsReported(const WarningCode warning) {
64   rtc::CritScope cs(&callbackCritSect_);
65   int warningCode = 0;
66   if (warning == AudioDeviceObserver::kRecordingWarning) {
67     warningCode = VE_RUNTIME_REC_WARNING;
68     LOG_F(LS_WARNING) << "VE_RUNTIME_REC_WARNING";
69   } else if (warning == AudioDeviceObserver::kPlayoutWarning) {
70     warningCode = VE_RUNTIME_PLAY_WARNING;
71     LOG_F(LS_WARNING) << "VE_RUNTIME_PLAY_WARNING";
72   }
73   if (voiceEngineObserverPtr_) {
74     // Deliver callback (-1 <=> no channel dependency)
75     voiceEngineObserverPtr_->CallbackOnError(-1, warningCode);
76   }
77 }
78 
RecordedDataIsAvailable(const void * audioSamples,const size_t nSamples,const size_t nBytesPerSample,const size_t nChannels,const uint32_t samplesPerSec,const uint32_t totalDelayMS,const int32_t clockDrift,const uint32_t currentMicLevel,const bool keyPressed,uint32_t & newMicLevel)79 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   newMicLevel = static_cast<uint32_t>(ProcessRecordedDataWithAPM(
90       nullptr, 0, audioSamples, samplesPerSec, nChannels, nSamples,
91       totalDelayMS, clockDrift, currentMicLevel, keyPressed));
92   return 0;
93 }
94 
NeedMorePlayData(const size_t nSamples,const size_t nBytesPerSample,const size_t nChannels,const uint32_t samplesPerSec,void * audioSamples,size_t & nSamplesOut,int64_t * elapsed_time_ms,int64_t * ntp_time_ms)95 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   GetPlayoutData(static_cast<int>(samplesPerSec), nChannels, nSamples, true,
104                  audioSamples, elapsed_time_ms, ntp_time_ms);
105   nSamplesOut = audioFrame_.samples_per_channel_;
106   return 0;
107 }
108 
PushCaptureData(int voe_channel,const void * audio_data,int bits_per_sample,int sample_rate,size_t number_of_channels,size_t number_of_frames)109 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   voe::ChannelOwner ch = shared_->channel_manager().GetChannel(voe_channel);
114   voe::Channel* channel_ptr = ch.channel();
115   if (!channel_ptr) return;
116 
117   if (channel_ptr->Sending()) {
118     channel_ptr->Demultiplex(static_cast<const int16_t*>(audio_data),
119                              sample_rate, number_of_frames, number_of_channels);
120     channel_ptr->PrepareEncodeAndSend(sample_rate);
121     channel_ptr->EncodeAndSend();
122   }
123 }
124 
PullRenderData(int bits_per_sample,int sample_rate,size_t number_of_channels,size_t number_of_frames,void * audio_data,int64_t * elapsed_time_ms,int64_t * ntp_time_ms)125 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   assert(bits_per_sample == 16);
132   assert(number_of_frames == static_cast<size_t>(sample_rate / 100));
133 
134   GetPlayoutData(sample_rate, number_of_channels, number_of_frames, false,
135                  audio_data, elapsed_time_ms, ntp_time_ms);
136 }
137 
RegisterVoiceEngineObserver(VoiceEngineObserver & observer)138 int VoEBaseImpl::RegisterVoiceEngineObserver(VoiceEngineObserver& observer) {
139   rtc::CritScope cs(&callbackCritSect_);
140   if (voiceEngineObserverPtr_) {
141     shared_->SetLastError(
142         VE_INVALID_OPERATION, kTraceError,
143         "RegisterVoiceEngineObserver() observer already enabled");
144     return -1;
145   }
146 
147   // Register the observer in all active channels
148   for (voe::ChannelManager::Iterator it(&shared_->channel_manager());
149        it.IsValid(); it.Increment()) {
150     it.GetChannel()->RegisterVoiceEngineObserver(observer);
151   }
152 
153   shared_->transmit_mixer()->RegisterVoiceEngineObserver(observer);
154   voiceEngineObserverPtr_ = &observer;
155   return 0;
156 }
157 
DeRegisterVoiceEngineObserver()158 int VoEBaseImpl::DeRegisterVoiceEngineObserver() {
159   rtc::CritScope cs(&callbackCritSect_);
160   if (!voiceEngineObserverPtr_) {
161     shared_->SetLastError(
162         VE_INVALID_OPERATION, kTraceError,
163         "DeRegisterVoiceEngineObserver() observer already disabled");
164     return 0;
165   }
166   voiceEngineObserverPtr_ = nullptr;
167 
168   // Deregister the observer in all active channels
169   for (voe::ChannelManager::Iterator it(&shared_->channel_manager());
170        it.IsValid(); it.Increment()) {
171     it.GetChannel()->DeRegisterVoiceEngineObserver();
172   }
173 
174   return 0;
175 }
176 
Init(AudioDeviceModule * external_adm,AudioProcessing * audioproc,const rtc::scoped_refptr<AudioDecoderFactory> & decoder_factory)177 int VoEBaseImpl::Init(
178     AudioDeviceModule* external_adm,
179     AudioProcessing* audioproc,
180     const rtc::scoped_refptr<AudioDecoderFactory>& decoder_factory) {
181   rtc::CritScope cs(shared_->crit_sec());
182   WebRtcSpl_Init();
183   if (shared_->statistics().Initialized()) {
184     return 0;
185   }
186   if (shared_->process_thread()) {
187     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   if (external_adm == nullptr) {
193 #if !defined(WEBRTC_INCLUDE_INTERNAL_AUDIO_DEVICE)
194     return -1;
195 #else
196     // Create the internal ADM implementation.
197     shared_->set_audio_device(AudioDeviceModule::Create(
198         VoEId(shared_->instance_id(), -1), shared_->audio_device_layer()));
199 
200     if (shared_->audio_device() == nullptr) {
201       shared_->SetLastError(VE_NO_MEMORY, kTraceCritical,
202                             "Init() failed to create the ADM");
203       return -1;
204     }
205 #endif  // WEBRTC_INCLUDE_INTERNAL_AUDIO_DEVICE
206   } else {
207     // Use the already existing external ADM implementation.
208     shared_->set_audio_device(external_adm);
209     LOG_F(LS_INFO)
210         << "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   if (shared_->process_thread()) {
216     shared_->process_thread()->RegisterModule(shared_->audio_device());
217   }
218 
219   bool available = false;
220 
221   // --------------------
222   // Reinitialize the ADM
223 
224   // Register the AudioObserver implementation
225   if (shared_->audio_device()->RegisterEventObserver(this) != 0) {
226     shared_->SetLastError(
227         VE_AUDIO_DEVICE_MODULE_ERROR, kTraceWarning,
228         "Init() failed to register event observer for the ADM");
229   }
230 
231   // Register the AudioTransport implementation
232   if (shared_->audio_device()->RegisterAudioCallback(this) != 0) {
233     shared_->SetLastError(
234         VE_AUDIO_DEVICE_MODULE_ERROR, kTraceWarning,
235         "Init() failed to register audio callback for the ADM");
236   }
237 
238   // ADM initialization
239   if (shared_->audio_device()->Init() != 0) {
240     shared_->SetLastError(VE_AUDIO_DEVICE_MODULE_ERROR, kTraceError,
241                           "Init() failed to initialize the ADM");
242     return -1;
243   }
244 
245   // Initialize the default speaker
246   if (shared_->audio_device()->SetPlayoutDevice(
247           WEBRTC_VOICE_ENGINE_DEFAULT_DEVICE) != 0) {
248     shared_->SetLastError(VE_AUDIO_DEVICE_MODULE_ERROR, kTraceInfo,
249                           "Init() failed to set the default output device");
250   }
251   if (shared_->audio_device()->InitSpeaker() != 0) {
252     shared_->SetLastError(VE_CANNOT_ACCESS_SPEAKER_VOL, kTraceInfo,
253                           "Init() failed to initialize the speaker");
254   }
255 
256   // Initialize the default microphone
257   if (shared_->audio_device()->SetRecordingDevice(
258           WEBRTC_VOICE_ENGINE_DEFAULT_DEVICE) != 0) {
259     shared_->SetLastError(VE_SOUNDCARD_ERROR, kTraceInfo,
260                           "Init() failed to set the default input device");
261   }
262   if (shared_->audio_device()->InitMicrophone() != 0) {
263     shared_->SetLastError(VE_CANNOT_ACCESS_MIC_VOL, kTraceInfo,
264                           "Init() failed to initialize the microphone");
265   }
266 
267   // Set number of channels
268   if (shared_->audio_device()->StereoPlayoutIsAvailable(&available) != 0) {
269     shared_->SetLastError(VE_SOUNDCARD_ERROR, kTraceWarning,
270                           "Init() failed to query stereo playout mode");
271   }
272   if (shared_->audio_device()->SetStereoPlayout(available) != 0) {
273     shared_->SetLastError(VE_SOUNDCARD_ERROR, kTraceWarning,
274                           "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   shared_->audio_device()->StereoRecordingIsAvailable(&available);
285   if (shared_->audio_device()->SetStereoRecording(available) != 0) {
286     shared_->SetLastError(VE_SOUNDCARD_ERROR, kTraceWarning,
287                           "Init() failed to set mono/stereo recording mode");
288   }
289 
290   if (!audioproc) {
291     audioproc = AudioProcessing::Create();
292     if (!audioproc) {
293       LOG(LS_ERROR) << "Failed to create AudioProcessing.";
294       shared_->SetLastError(VE_NO_MEMORY);
295       return -1;
296     }
297   }
298   shared_->set_audio_processing(audioproc);
299 
300   // Set the error state for any failures in this block.
301   shared_->SetLastError(VE_APM_ERROR);
302   // Configure AudioProcessing components.
303   if (audioproc->high_pass_filter()->Enable(true) != 0) {
304     LOG_F(LS_ERROR) << "Failed to enable high pass filter.";
305     return -1;
306   }
307   if (audioproc->echo_cancellation()->enable_drift_compensation(false) != 0) {
308     LOG_F(LS_ERROR) << "Failed to disable drift compensation.";
309     return -1;
310   }
311   if (audioproc->noise_suppression()->set_level(kDefaultNsMode) != 0) {
312     LOG_F(LS_ERROR) << "Failed to set noise suppression level: "
313         << kDefaultNsMode;
314     return -1;
315   }
316   GainControl* agc = audioproc->gain_control();
317   if (agc->set_analog_level_limits(kMinVolumeLevel, kMaxVolumeLevel) != 0) {
318     LOG_F(LS_ERROR) << "Failed to set analog level limits with minimum: "
319         << kMinVolumeLevel << " and maximum: " << kMaxVolumeLevel;
320     return -1;
321   }
322   if (agc->set_mode(kDefaultAgcMode) != 0) {
323     LOG_F(LS_ERROR) << "Failed to set mode: " << kDefaultAgcMode;
324     return -1;
325   }
326   if (agc->Enable(kDefaultAgcState) != 0) {
327     LOG_F(LS_ERROR) << "Failed to set agc state: " << kDefaultAgcState;
328     return -1;
329   }
330   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   if (decoder_factory)
344     decoder_factory_ = decoder_factory;
345   else
346     decoder_factory_ = CreateBuiltinAudioDecoderFactory();
347 
348   return shared_->statistics().SetInitialized();
349 }
350 
Terminate()351 int VoEBaseImpl::Terminate() {
352   rtc::CritScope cs(shared_->crit_sec());
353   return TerminateInternal();
354 }
355 
CreateChannel()356 int VoEBaseImpl::CreateChannel() {
357   return CreateChannel(ChannelConfig());
358 }
359 
CreateChannel(const ChannelConfig & config)360 int VoEBaseImpl::CreateChannel(const ChannelConfig& config) {
361   rtc::CritScope cs(shared_->crit_sec());
362   if (!shared_->statistics().Initialized()) {
363     shared_->SetLastError(VE_NOT_INITED, kTraceError);
364     return -1;
365   }
366 
367   ChannelConfig config_copy(config);
368   config_copy.acm_config.decoder_factory = decoder_factory_;
369   voe::ChannelOwner channel_owner =
370       shared_->channel_manager().CreateChannel(config_copy);
371   return InitializeChannel(&channel_owner);
372 }
373 
InitializeChannel(voe::ChannelOwner * channel_owner)374 int VoEBaseImpl::InitializeChannel(voe::ChannelOwner* channel_owner) {
375   if (channel_owner->channel()->SetEngineInformation(
376           shared_->statistics(), *shared_->output_mixer(),
377           *shared_->transmit_mixer(), *shared_->process_thread(),
378           *shared_->audio_device(), voiceEngineObserverPtr_,
379           &callbackCritSect_) != 0) {
380     shared_->SetLastError(
381         VE_CHANNEL_NOT_CREATED, kTraceError,
382         "CreateChannel() failed to associate engine and channel."
383         " Destroying channel.");
384     shared_->channel_manager().DestroyChannel(
385         channel_owner->channel()->ChannelId());
386     return -1;
387   } else if (channel_owner->channel()->Init() != 0) {
388     shared_->SetLastError(
389         VE_CHANNEL_NOT_CREATED, kTraceError,
390         "CreateChannel() failed to initialize channel. Destroying"
391         " channel.");
392     shared_->channel_manager().DestroyChannel(
393         channel_owner->channel()->ChannelId());
394     return -1;
395   }
396   return channel_owner->channel()->ChannelId();
397 }
398 
DeleteChannel(int channel)399 int VoEBaseImpl::DeleteChannel(int channel) {
400   rtc::CritScope cs(shared_->crit_sec());
401   if (!shared_->statistics().Initialized()) {
402     shared_->SetLastError(VE_NOT_INITED, kTraceError);
403     return -1;
404   }
405 
406   {
407     voe::ChannelOwner ch = shared_->channel_manager().GetChannel(channel);
408     voe::Channel* channelPtr = ch.channel();
409     if (channelPtr == nullptr) {
410       shared_->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
411                             "DeleteChannel() failed to locate channel");
412       return -1;
413     }
414   }
415 
416   shared_->channel_manager().DestroyChannel(channel);
417   if (StopSend() != 0) {
418     return -1;
419   }
420   if (StopPlayout() != 0) {
421     return -1;
422   }
423   return 0;
424 }
425 
StartReceive(int channel)426 int VoEBaseImpl::StartReceive(int channel) {
427   rtc::CritScope cs(shared_->crit_sec());
428   if (!shared_->statistics().Initialized()) {
429     shared_->SetLastError(VE_NOT_INITED, kTraceError);
430     return -1;
431   }
432   voe::ChannelOwner ch = shared_->channel_manager().GetChannel(channel);
433   voe::Channel* channelPtr = ch.channel();
434   if (channelPtr == nullptr) {
435     shared_->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
436                           "StartReceive() failed to locate channel");
437     return -1;
438   }
439   channelPtr->ResetDiscardedPacketCount();
440   return 0;
441 }
442 
StartPlayout(int channel)443 int VoEBaseImpl::StartPlayout(int channel) {
444   rtc::CritScope cs(shared_->crit_sec());
445   if (!shared_->statistics().Initialized()) {
446     shared_->SetLastError(VE_NOT_INITED, kTraceError);
447     return -1;
448   }
449   voe::ChannelOwner ch = shared_->channel_manager().GetChannel(channel);
450   voe::Channel* channelPtr = ch.channel();
451   if (channelPtr == nullptr) {
452     shared_->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
453                           "StartPlayout() failed to locate channel");
454     return -1;
455   }
456   if (channelPtr->Playing()) {
457     return 0;
458   }
459   if (StartPlayout() != 0) {
460     shared_->SetLastError(VE_AUDIO_DEVICE_MODULE_ERROR, kTraceError,
461                           "StartPlayout() failed to start playout");
462     return -1;
463   }
464   return channelPtr->StartPlayout();
465 }
466 
StopPlayout(int channel)467 int VoEBaseImpl::StopPlayout(int channel) {
468   rtc::CritScope cs(shared_->crit_sec());
469   if (!shared_->statistics().Initialized()) {
470     shared_->SetLastError(VE_NOT_INITED, kTraceError);
471     return -1;
472   }
473   voe::ChannelOwner ch = shared_->channel_manager().GetChannel(channel);
474   voe::Channel* channelPtr = ch.channel();
475   if (channelPtr == nullptr) {
476     shared_->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
477                           "StopPlayout() failed to locate channel");
478     return -1;
479   }
480   if (channelPtr->StopPlayout() != 0) {
481     LOG_F(LS_WARNING) << "StopPlayout() failed to stop playout for channel "
482                       << channel;
483   }
484   return StopPlayout();
485 }
486 
StartSend(int channel)487 int VoEBaseImpl::StartSend(int channel) {
488   rtc::CritScope cs(shared_->crit_sec());
489   if (!shared_->statistics().Initialized()) {
490     shared_->SetLastError(VE_NOT_INITED, kTraceError);
491     return -1;
492   }
493   voe::ChannelOwner ch = shared_->channel_manager().GetChannel(channel);
494   voe::Channel* channelPtr = ch.channel();
495   if (channelPtr == nullptr) {
496     shared_->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
497                           "StartSend() failed to locate channel");
498     return -1;
499   }
500   if (channelPtr->Sending()) {
501     return 0;
502   }
503   if (StartSend() != 0) {
504     shared_->SetLastError(VE_AUDIO_DEVICE_MODULE_ERROR, kTraceError,
505                           "StartSend() failed to start recording");
506     return -1;
507   }
508   return channelPtr->StartSend();
509 }
510 
StopSend(int channel)511 int VoEBaseImpl::StopSend(int channel) {
512   rtc::CritScope cs(shared_->crit_sec());
513   if (!shared_->statistics().Initialized()) {
514     shared_->SetLastError(VE_NOT_INITED, kTraceError);
515     return -1;
516   }
517   voe::ChannelOwner ch = shared_->channel_manager().GetChannel(channel);
518   voe::Channel* channelPtr = ch.channel();
519   if (channelPtr == nullptr) {
520     shared_->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
521                           "StopSend() failed to locate channel");
522     return -1;
523   }
524   if (channelPtr->StopSend() != 0) {
525     LOG_F(LS_WARNING) << "StopSend() failed to stop sending for channel "
526                       << channel;
527   }
528   return StopSend();
529 }
530 
GetVersion(char version[1024])531 int VoEBaseImpl::GetVersion(char version[1024]) {
532   if (version == nullptr) {
533     shared_->SetLastError(VE_INVALID_ARGUMENT, kTraceError);
534     return -1;
535   }
536 
537   std::string versionString = VoiceEngine::GetVersionString();
538 #ifdef WEBRTC_VOE_EXTERNAL_REC_AND_PLAYOUT
539   versionString += "External recording and playout build";
540 #endif
541   RTC_DCHECK_GT(1024, versionString.size() + 1);
542   char* end = std::copy(versionString.cbegin(), versionString.cend(), version);
543   end[0] = '\n';
544   end[1] = '\0';
545   return 0;
546 }
547 
LastError()548 int VoEBaseImpl::LastError() { return (shared_->statistics().LastError()); }
549 
StartPlayout()550 int32_t VoEBaseImpl::StartPlayout() {
551   if (!shared_->audio_device()->Playing()) {
552     if (!shared_->ext_playout()) {
553       if (shared_->audio_device()->InitPlayout() != 0) {
554         LOG_F(LS_ERROR) << "Failed to initialize playout";
555         return -1;
556       }
557       if (shared_->audio_device()->StartPlayout() != 0) {
558         LOG_F(LS_ERROR) << "Failed to start playout";
559         return -1;
560       }
561     }
562   }
563   return 0;
564 }
565 
StopPlayout()566 int32_t VoEBaseImpl::StopPlayout() {
567   // Stop audio-device playing if no channel is playing out
568   if (shared_->NumOfPlayingChannels() == 0) {
569     if (shared_->audio_device()->StopPlayout() != 0) {
570       shared_->SetLastError(VE_CANNOT_STOP_PLAYOUT, kTraceError,
571                             "StopPlayout() failed to stop playout");
572       return -1;
573     }
574   }
575   return 0;
576 }
577 
StartSend()578 int32_t VoEBaseImpl::StartSend() {
579   if (!shared_->ext_recording()) {
580     if (!shared_->audio_device()->RecordingIsInitialized() &&
581         !shared_->audio_device()->Recording()) {
582       if (shared_->audio_device()->InitRecording() != 0) {
583         LOG_F(LS_ERROR) << "Failed to initialize recording";
584         return -1;
585       }
586     }
587     if (!shared_->audio_device()->Recording()) {
588       if (shared_->audio_device()->StartRecording() != 0) {
589         LOG_F(LS_ERROR) << "Failed to start recording";
590         return -1;
591       }
592     }
593   }
594   return 0;
595 }
596 
StopSend()597 int32_t VoEBaseImpl::StopSend() {
598   if (shared_->NumOfSendingChannels() == 0 &&
599       !shared_->transmit_mixer()->IsRecordingMic()) {
600     // Stop audio-device recording if no channel is recording
601     if (shared_->audio_device()->StopRecording() != 0) {
602       shared_->SetLastError(VE_CANNOT_STOP_RECORDING, kTraceError,
603                             "StopSend() failed to stop recording");
604       return -1;
605     }
606     shared_->transmit_mixer()->StopSend();
607   }
608 
609   return 0;
610 }
611 
TerminateInternal()612 int32_t VoEBaseImpl::TerminateInternal() {
613   // Delete any remaining channel objects
614   shared_->channel_manager().DestroyAllChannels();
615 
616   if (shared_->process_thread()) {
617     if (shared_->audio_device()) {
618       shared_->process_thread()->DeRegisterModule(shared_->audio_device());
619     }
620     shared_->process_thread()->Stop();
621   }
622 
623   if (shared_->audio_device()) {
624     if (shared_->audio_device()->StopPlayout() != 0) {
625       shared_->SetLastError(VE_SOUNDCARD_ERROR, kTraceWarning,
626                             "TerminateInternal() failed to stop playout");
627     }
628     if (shared_->audio_device()->StopRecording() != 0) {
629       shared_->SetLastError(VE_SOUNDCARD_ERROR, kTraceWarning,
630                             "TerminateInternal() failed to stop recording");
631     }
632     if (shared_->audio_device()->RegisterEventObserver(nullptr) != 0) {
633       shared_->SetLastError(
634           VE_AUDIO_DEVICE_MODULE_ERROR, kTraceWarning,
635           "TerminateInternal() failed to de-register event observer "
636           "for the ADM");
637     }
638     if (shared_->audio_device()->RegisterAudioCallback(nullptr) != 0) {
639       shared_->SetLastError(
640           VE_AUDIO_DEVICE_MODULE_ERROR, kTraceWarning,
641           "TerminateInternal() failed to de-register audio callback "
642           "for the ADM");
643     }
644     if (shared_->audio_device()->Terminate() != 0) {
645       shared_->SetLastError(VE_AUDIO_DEVICE_MODULE_ERROR, kTraceError,
646                             "TerminateInternal() failed to terminate the ADM");
647     }
648     shared_->set_audio_device(nullptr);
649   }
650 
651   if (shared_->audio_processing()) {
652     shared_->set_audio_processing(nullptr);
653   }
654 
655   return shared_->statistics().SetUnInitialized();
656 }
657 
ProcessRecordedDataWithAPM(const int voe_channels[],size_t number_of_voe_channels,const void * audio_data,uint32_t sample_rate,size_t number_of_channels,size_t number_of_frames,uint32_t audio_delay_milliseconds,int32_t clock_drift,uint32_t volume,bool key_pressed)658 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   assert(shared_->transmit_mixer() != nullptr);
664   assert(shared_->audio_device() != nullptr);
665 
666   uint32_t max_volume = 0;
667   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   if (volume != 0) {
671     // Scale from ADM to VoE level range
672     if (shared_->audio_device()->MaxMicrophoneVolume(&max_volume) == 0) {
673       if (max_volume) {
674         voe_mic_level = static_cast<uint16_t>(
675             (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     if (voe_mic_level > kMaxVolumeLevel) {
685       voe_mic_level = kMaxVolumeLevel;
686       max_volume = volume;
687     }
688   }
689 
690   // Perform channel-independent operations
691   // (APM, mix with file, record to file, mute, etc.)
692   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       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   if (number_of_voe_channels == 0) {
703     shared_->transmit_mixer()->DemuxAndMix();
704     shared_->transmit_mixer()->EncodeAndSend();
705   } else {
706     shared_->transmit_mixer()->DemuxAndMix(voe_channels,
707                                            number_of_voe_channels);
708     shared_->transmit_mixer()->EncodeAndSend(voe_channels,
709                                              number_of_voe_channels);
710   }
711 
712   // Scale from VoE to ADM level range.
713   uint32_t new_voe_mic_level = shared_->transmit_mixer()->CaptureLevel();
714   if (new_voe_mic_level != voe_mic_level) {
715     // Return the new volume if AGC has changed the volume.
716     return static_cast<int>((new_voe_mic_level * max_volume +
717                              static_cast<int>(kMaxVolumeLevel / 2)) /
718                             kMaxVolumeLevel);
719   }
720 
721   // Return 0 to indicate no change on the volume.
722   return 0;
723 }
724 
GetPlayoutData(int sample_rate,size_t number_of_channels,size_t number_of_frames,bool feed_data_to_apm,void * audio_data,int64_t * elapsed_time_ms,int64_t * ntp_time_ms)725 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   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   shared_->output_mixer()->MixActiveChannels();
735 
736   // Additional operations on the combined signal
737   shared_->output_mixer()->DoOperationsOnCombinedSignal(feed_data_to_apm);
738 
739   // Retrieve the final output mix (resampled to match the ADM)
740   shared_->output_mixer()->GetMixedAudio(sample_rate, number_of_channels,
741                                          &audioFrame_);
742 
743   assert(number_of_frames == audioFrame_.samples_per_channel_);
744   assert(sample_rate == audioFrame_.sample_rate_hz_);
745 
746   // Deliver audio (PCM) samples to the ADM
747   memcpy(audio_data, audioFrame_.data_,
748          sizeof(int16_t) * number_of_frames * number_of_channels);
749 
750   *elapsed_time_ms = audioFrame_.elapsed_time_ms_;
751   *ntp_time_ms = audioFrame_.ntp_time_ms_;
752 }
753 
AssociateSendChannel(int channel,int accociate_send_channel)754 int VoEBaseImpl::AssociateSendChannel(int channel,
755                                       int accociate_send_channel) {
756   rtc::CritScope cs(shared_->crit_sec());
757 
758   if (!shared_->statistics().Initialized()) {
759       shared_->SetLastError(VE_NOT_INITED, kTraceError);
760       return -1;
761   }
762 
763   voe::ChannelOwner ch = shared_->channel_manager().GetChannel(channel);
764   voe::Channel* channel_ptr = ch.channel();
765   if (channel_ptr == NULL) {
766     shared_->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
767         "AssociateSendChannel() failed to locate channel");
768     return -1;
769   }
770 
771   ch = shared_->channel_manager().GetChannel(accociate_send_channel);
772   voe::Channel* accociate_send_channel_ptr = ch.channel();
773   if (accociate_send_channel_ptr == NULL) {
774     shared_->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
775         "AssociateSendChannel() failed to locate accociate_send_channel");
776     return -1;
777   }
778 
779   channel_ptr->set_associate_send_channel(ch);
780   return 0;
781 }
782 
783 }  // namespace webrtc
784