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