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