Upstream version 11.40.277.0
[platform/framework/web/crosswalk.git] / src / third_party / webrtc / voice_engine / voe_base_impl.cc
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/common.h"
14 #include "webrtc/common_audio/signal_processing/include/signal_processing_library.h"
15 #include "webrtc/modules/audio_coding/main/interface/audio_coding_module.h"
16 #include "webrtc/modules/audio_device/audio_device_impl.h"
17 #include "webrtc/modules/audio_processing/include/audio_processing.h"
18 #include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
19 #include "webrtc/system_wrappers/interface/file_wrapper.h"
20 #include "webrtc/system_wrappers/interface/trace.h"
21 #include "webrtc/voice_engine/channel.h"
22 #include "webrtc/voice_engine/include/voe_errors.h"
23 #include "webrtc/voice_engine/output_mixer.h"
24 #include "webrtc/voice_engine/transmit_mixer.h"
25 #include "webrtc/voice_engine/utility.h"
26 #include "webrtc/voice_engine/voice_engine_impl.h"
27
28 namespace webrtc
29 {
30
31 VoEBase* VoEBase::GetInterface(VoiceEngine* voiceEngine)
32 {
33     if (NULL == voiceEngine)
34     {
35         return NULL;
36     }
37     VoiceEngineImpl* s = static_cast<VoiceEngineImpl*>(voiceEngine);
38     s->AddRef();
39     return s;
40 }
41
42 VoEBaseImpl::VoEBaseImpl(voe::SharedData* shared) :
43     _voiceEngineObserverPtr(NULL),
44     _callbackCritSect(*CriticalSectionWrapper::CreateCriticalSection()),
45     _voiceEngineObserver(false), _shared(shared)
46 {
47     WEBRTC_TRACE(kTraceMemory, kTraceVoice, VoEId(_shared->instance_id(), -1),
48                  "VoEBaseImpl() - ctor");
49 }
50
51 VoEBaseImpl::~VoEBaseImpl()
52 {
53     WEBRTC_TRACE(kTraceMemory, kTraceVoice, VoEId(_shared->instance_id(), -1),
54                  "~VoEBaseImpl() - dtor");
55
56     TerminateInternal();
57
58     delete &_callbackCritSect;
59 }
60
61 void VoEBaseImpl::OnErrorIsReported(ErrorCode error)
62 {
63     CriticalSectionScoped cs(&_callbackCritSect);
64     if (_voiceEngineObserver)
65     {
66         if (_voiceEngineObserverPtr)
67         {
68             int errCode(0);
69             if (error == AudioDeviceObserver::kRecordingError)
70             {
71                 errCode = VE_RUNTIME_REC_ERROR;
72                 WEBRTC_TRACE(kTraceInfo, kTraceVoice,
73                     VoEId(_shared->instance_id(), -1),
74                     "VoEBaseImpl::OnErrorIsReported() => VE_RUNTIME_REC_ERROR");
75             }
76             else if (error == AudioDeviceObserver::kPlayoutError)
77             {
78                 errCode = VE_RUNTIME_PLAY_ERROR;
79                 WEBRTC_TRACE(kTraceInfo, kTraceVoice,
80                     VoEId(_shared->instance_id(), -1),
81                     "VoEBaseImpl::OnErrorIsReported() => "
82                     "VE_RUNTIME_PLAY_ERROR");
83             }
84             // Deliver callback (-1 <=> no channel dependency)
85             _voiceEngineObserverPtr->CallbackOnError(-1, errCode);
86         }
87     }
88 }
89
90 void VoEBaseImpl::OnWarningIsReported(WarningCode warning)
91 {
92     CriticalSectionScoped cs(&_callbackCritSect);
93     if (_voiceEngineObserver)
94     {
95         if (_voiceEngineObserverPtr)
96         {
97             int warningCode(0);
98             if (warning == AudioDeviceObserver::kRecordingWarning)
99             {
100                 warningCode = VE_RUNTIME_REC_WARNING;
101                 WEBRTC_TRACE(kTraceInfo, kTraceVoice,
102                     VoEId(_shared->instance_id(), -1),
103                     "VoEBaseImpl::OnErrorIsReported() => "
104                     "VE_RUNTIME_REC_WARNING");
105             }
106             else if (warning == AudioDeviceObserver::kPlayoutWarning)
107             {
108                 warningCode = VE_RUNTIME_PLAY_WARNING;
109                 WEBRTC_TRACE(kTraceInfo, kTraceVoice,
110                     VoEId(_shared->instance_id(), -1),
111                     "VoEBaseImpl::OnErrorIsReported() => "
112                     "VE_RUNTIME_PLAY_WARNING");
113             }
114             // Deliver callback (-1 <=> no channel dependency)
115             _voiceEngineObserverPtr->CallbackOnError(-1, warningCode);
116         }
117     }
118 }
119
120 int32_t VoEBaseImpl::RecordedDataIsAvailable(
121         const void* audioSamples,
122         uint32_t nSamples,
123         uint8_t nBytesPerSample,
124         uint8_t nChannels,
125         uint32_t samplesPerSec,
126         uint32_t totalDelayMS,
127         int32_t clockDrift,
128         uint32_t micLevel,
129         bool keyPressed,
130         uint32_t& newMicLevel)
131 {
132     WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_shared->instance_id(), -1),
133                  "VoEBaseImpl::RecordedDataIsAvailable(nSamples=%u, "
134                      "nBytesPerSample=%u, nChannels=%u, samplesPerSec=%u, "
135                      "totalDelayMS=%u, clockDrift=%d, micLevel=%u)",
136                  nSamples, nBytesPerSample, nChannels, samplesPerSec,
137                  totalDelayMS, clockDrift, micLevel);
138     newMicLevel = static_cast<uint32_t>(ProcessRecordedDataWithAPM(
139         NULL, 0, audioSamples, samplesPerSec, nChannels, nSamples,
140         totalDelayMS, clockDrift, micLevel, keyPressed));
141
142     return 0;
143 }
144
145 int32_t VoEBaseImpl::NeedMorePlayData(
146         uint32_t nSamples,
147         uint8_t nBytesPerSample,
148         uint8_t nChannels,
149         uint32_t samplesPerSec,
150         void* audioSamples,
151         uint32_t& nSamplesOut,
152         int64_t* elapsed_time_ms,
153         int64_t* ntp_time_ms)
154 {
155   WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_shared->instance_id(), -1),
156                "VoEBaseImpl::NeedMorePlayData(nSamples=%u, "
157                "nBytesPerSample=%d, nChannels=%d, samplesPerSec=%u)",
158                nSamples, nBytesPerSample, nChannels, samplesPerSec);
159
160   GetPlayoutData(static_cast<int>(samplesPerSec),
161                  static_cast<int>(nChannels),
162                  static_cast<int>(nSamples), true, audioSamples,
163                  elapsed_time_ms, ntp_time_ms);
164
165   nSamplesOut = _audioFrame.samples_per_channel_;
166
167   return 0;
168 }
169
170 int VoEBaseImpl::OnDataAvailable(const int voe_channels[],
171                                  int number_of_voe_channels,
172                                  const int16_t* audio_data,
173                                  int sample_rate,
174                                  int number_of_channels,
175                                  int number_of_frames,
176                                  int audio_delay_milliseconds,
177                                  int volume,
178                                  bool key_pressed,
179                                  bool need_audio_processing) {
180   WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_shared->instance_id(), -1),
181                "VoEBaseImpl::OnDataAvailable(number_of_voe_channels=%d, "
182                "sample_rate=%d, number_of_channels=%d, number_of_frames=%d, "
183                "audio_delay_milliseconds=%d, volume=%d, "
184                "key_pressed=%d, need_audio_processing=%d)",
185                number_of_voe_channels, sample_rate, number_of_channels,
186                number_of_frames, audio_delay_milliseconds, volume,
187                key_pressed, need_audio_processing);
188   if (number_of_voe_channels == 0)
189     return 0;
190
191   if (need_audio_processing) {
192     return ProcessRecordedDataWithAPM(
193         voe_channels, number_of_voe_channels, audio_data, sample_rate,
194         number_of_channels, number_of_frames, audio_delay_milliseconds,
195         0, volume, key_pressed);
196   }
197
198   // No need to go through the APM, demultiplex the data to each VoE channel,
199   // encode and send to the network.
200   for (int i = 0; i < number_of_voe_channels; ++i) {
201     // TODO(ajm): In the case where multiple channels are using the same codec
202     // rate, this path needlessly does extra conversions. We should convert once
203     // and share between channels.
204     PushCaptureData(voe_channels[i], audio_data, 16, sample_rate,
205                     number_of_channels, number_of_frames);
206   }
207
208   // Return 0 to indicate no need to change the volume.
209   return 0;
210 }
211
212 void VoEBaseImpl::OnData(int voe_channel, const void* audio_data,
213                          int bits_per_sample, int sample_rate,
214                          int number_of_channels,
215                          int number_of_frames) {
216   PushCaptureData(voe_channel, audio_data, bits_per_sample, sample_rate,
217                   number_of_channels, number_of_frames);
218 }
219
220 void VoEBaseImpl::PushCaptureData(int voe_channel, const void* audio_data,
221                                   int bits_per_sample, int sample_rate,
222                                   int number_of_channels,
223                                   int number_of_frames) {
224   voe::ChannelOwner ch = _shared->channel_manager().GetChannel(voe_channel);
225   voe::Channel* channel_ptr = ch.channel();
226   if (!channel_ptr)
227     return;
228
229   if (channel_ptr->Sending()) {
230     channel_ptr->Demultiplex(static_cast<const int16_t*>(audio_data),
231                              sample_rate, number_of_frames, number_of_channels);
232     channel_ptr->PrepareEncodeAndSend(sample_rate);
233     channel_ptr->EncodeAndSend();
234   }
235 }
236
237 void VoEBaseImpl::PullRenderData(int bits_per_sample, int sample_rate,
238                                  int number_of_channels, int number_of_frames,
239                                  void* audio_data,
240                                  int64_t* elapsed_time_ms,
241                                  int64_t* ntp_time_ms) {
242   assert(bits_per_sample == 16);
243   assert(number_of_frames == static_cast<int>(sample_rate / 100));
244
245   GetPlayoutData(sample_rate, number_of_channels, number_of_frames, false,
246                  audio_data, elapsed_time_ms, ntp_time_ms);
247 }
248
249 int VoEBaseImpl::RegisterVoiceEngineObserver(VoiceEngineObserver& observer)
250 {
251     WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
252                  "RegisterVoiceEngineObserver(observer=0x%d)", &observer);
253     CriticalSectionScoped cs(&_callbackCritSect);
254     if (_voiceEngineObserverPtr)
255     {
256         _shared->SetLastError(VE_INVALID_OPERATION, kTraceError,
257             "RegisterVoiceEngineObserver() observer already enabled");
258         return -1;
259     }
260
261     // Register the observer in all active channels
262     for (voe::ChannelManager::Iterator it(&_shared->channel_manager());
263          it.IsValid();
264          it.Increment()) {
265       it.GetChannel()->RegisterVoiceEngineObserver(observer);
266     }
267
268     _shared->transmit_mixer()->RegisterVoiceEngineObserver(observer);
269
270     _voiceEngineObserverPtr = &observer;
271     _voiceEngineObserver = true;
272
273     return 0;
274 }
275
276 int VoEBaseImpl::DeRegisterVoiceEngineObserver()
277 {
278     WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
279                  "DeRegisterVoiceEngineObserver()");
280     CriticalSectionScoped cs(&_callbackCritSect);
281     if (!_voiceEngineObserverPtr)
282     {
283         _shared->SetLastError(VE_INVALID_OPERATION, kTraceError,
284             "DeRegisterVoiceEngineObserver() observer already disabled");
285         return 0;
286     }
287
288     _voiceEngineObserver = false;
289     _voiceEngineObserverPtr = NULL;
290
291     // Deregister the observer in all active channels
292     for (voe::ChannelManager::Iterator it(&_shared->channel_manager());
293          it.IsValid();
294          it.Increment()) {
295       it.GetChannel()->DeRegisterVoiceEngineObserver();
296     }
297
298     return 0;
299 }
300
301 int VoEBaseImpl::Init(AudioDeviceModule* external_adm,
302                       AudioProcessing* audioproc)
303 {
304     WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
305         "Init(external_adm=0x%p)", external_adm);
306     CriticalSectionScoped cs(_shared->crit_sec());
307
308     WebRtcSpl_Init();
309
310     if (_shared->statistics().Initialized())
311     {
312         return 0;
313     }
314
315     if (_shared->process_thread())
316     {
317         if (_shared->process_thread()->Start() != 0)
318         {
319             _shared->SetLastError(VE_THREAD_ERROR, kTraceError,
320                 "Init() failed to start module process thread");
321             return -1;
322         }
323     }
324
325     // Create an internal ADM if the user has not added an external
326     // ADM implementation as input to Init().
327     if (external_adm == NULL)
328     {
329         // Create the internal ADM implementation.
330         _shared->set_audio_device(AudioDeviceModuleImpl::Create(
331             VoEId(_shared->instance_id(), -1), _shared->audio_device_layer()));
332
333         if (_shared->audio_device() == NULL)
334         {
335             _shared->SetLastError(VE_NO_MEMORY, kTraceCritical,
336                 "Init() failed to create the ADM");
337             return -1;
338         }
339     }
340     else
341     {
342         // Use the already existing external ADM implementation.
343         _shared->set_audio_device(external_adm);
344         WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_shared->instance_id(), -1),
345             "An external ADM implementation will be used in VoiceEngine");
346     }
347
348     // Register the ADM to the process thread, which will drive the error
349     // callback mechanism
350     if (_shared->process_thread() &&
351         _shared->process_thread()->RegisterModule(_shared->audio_device()) != 0)
352     {
353         _shared->SetLastError(VE_AUDIO_DEVICE_MODULE_ERROR, kTraceError,
354             "Init() failed to register the ADM");
355         return -1;
356     }
357
358     bool available(false);
359
360     // --------------------
361     // Reinitialize the ADM
362
363     // Register the AudioObserver implementation
364     if (_shared->audio_device()->RegisterEventObserver(this) != 0) {
365       _shared->SetLastError(VE_AUDIO_DEVICE_MODULE_ERROR, kTraceWarning,
366           "Init() failed to register event observer for the ADM");
367     }
368
369     // Register the AudioTransport implementation
370     if (_shared->audio_device()->RegisterAudioCallback(this) != 0) {
371       _shared->SetLastError(VE_AUDIO_DEVICE_MODULE_ERROR, kTraceWarning,
372           "Init() failed to register audio callback for the ADM");
373     }
374
375     // ADM initialization
376     if (_shared->audio_device()->Init() != 0)
377     {
378         _shared->SetLastError(VE_AUDIO_DEVICE_MODULE_ERROR, kTraceError,
379             "Init() failed to initialize the ADM");
380         return -1;
381     }
382
383     // Initialize the default speaker
384     if (_shared->audio_device()->SetPlayoutDevice(
385             WEBRTC_VOICE_ENGINE_DEFAULT_DEVICE) != 0)
386     {
387         _shared->SetLastError(VE_AUDIO_DEVICE_MODULE_ERROR, kTraceInfo,
388             "Init() failed to set the default output device");
389     }
390     if (_shared->audio_device()->InitSpeaker() != 0)
391     {
392         _shared->SetLastError(VE_CANNOT_ACCESS_SPEAKER_VOL, kTraceInfo,
393             "Init() failed to initialize the speaker");
394     }
395
396     // Initialize the default microphone
397     if (_shared->audio_device()->SetRecordingDevice(
398             WEBRTC_VOICE_ENGINE_DEFAULT_DEVICE) != 0)
399     {
400         _shared->SetLastError(VE_SOUNDCARD_ERROR, kTraceInfo,
401             "Init() failed to set the default input device");
402     }
403     if (_shared->audio_device()->InitMicrophone() != 0)
404     {
405         _shared->SetLastError(VE_CANNOT_ACCESS_MIC_VOL, kTraceInfo,
406             "Init() failed to initialize the microphone");
407     }
408
409     // Set number of channels
410     if (_shared->audio_device()->StereoPlayoutIsAvailable(&available) != 0) {
411       _shared->SetLastError(VE_SOUNDCARD_ERROR, kTraceWarning,
412           "Init() failed to query stereo playout mode");
413     }
414     if (_shared->audio_device()->SetStereoPlayout(available) != 0)
415     {
416         _shared->SetLastError(VE_SOUNDCARD_ERROR, kTraceWarning,
417             "Init() failed to set mono/stereo playout mode");
418     }
419
420     // TODO(andrew): These functions don't tell us whether stereo recording
421     // is truly available. We simply set the AudioProcessing input to stereo
422     // here, because we have to wait until receiving the first frame to
423     // determine the actual number of channels anyway.
424     //
425     // These functions may be changed; tracked here:
426     // http://code.google.com/p/webrtc/issues/detail?id=204
427     _shared->audio_device()->StereoRecordingIsAvailable(&available);
428     if (_shared->audio_device()->SetStereoRecording(available) != 0)
429     {
430         _shared->SetLastError(VE_SOUNDCARD_ERROR, kTraceWarning,
431             "Init() failed to set mono/stereo recording mode");
432     }
433
434     if (!audioproc) {
435       audioproc = AudioProcessing::Create(VoEId(_shared->instance_id(), -1));
436       if (!audioproc) {
437         LOG(LS_ERROR) << "Failed to create AudioProcessing.";
438         _shared->SetLastError(VE_NO_MEMORY);
439         return -1;
440       }
441     }
442     _shared->set_audio_processing(audioproc);
443
444     // Set the error state for any failures in this block.
445     _shared->SetLastError(VE_APM_ERROR);
446     // Configure AudioProcessing components.
447     if (audioproc->high_pass_filter()->Enable(true) != 0) {
448       LOG_FERR1(LS_ERROR, high_pass_filter()->Enable, true);
449       return -1;
450     }
451     if (audioproc->echo_cancellation()->enable_drift_compensation(false) != 0) {
452       LOG_FERR1(LS_ERROR, enable_drift_compensation, false);
453       return -1;
454     }
455     if (audioproc->noise_suppression()->set_level(kDefaultNsMode) != 0) {
456       LOG_FERR1(LS_ERROR, noise_suppression()->set_level, kDefaultNsMode);
457       return -1;
458     }
459     GainControl* agc = audioproc->gain_control();
460     if (agc->set_analog_level_limits(kMinVolumeLevel, kMaxVolumeLevel) != 0) {
461       LOG_FERR2(LS_ERROR, agc->set_analog_level_limits, kMinVolumeLevel,
462                 kMaxVolumeLevel);
463       return -1;
464     }
465     if (agc->set_mode(kDefaultAgcMode) != 0) {
466       LOG_FERR1(LS_ERROR, agc->set_mode, kDefaultAgcMode);
467       return -1;
468     }
469     if (agc->Enable(kDefaultAgcState) != 0) {
470       LOG_FERR1(LS_ERROR, agc->Enable, kDefaultAgcState);
471       return -1;
472     }
473     _shared->SetLastError(0);  // Clear error state.
474
475 #ifdef WEBRTC_VOICE_ENGINE_AGC
476     bool agc_enabled = agc->mode() == GainControl::kAdaptiveAnalog &&
477                        agc->is_enabled();
478     if (_shared->audio_device()->SetAGC(agc_enabled) != 0) {
479       LOG_FERR1(LS_ERROR, audio_device()->SetAGC, agc_enabled);
480       _shared->SetLastError(VE_AUDIO_DEVICE_MODULE_ERROR);
481       // TODO(ajm): No error return here due to
482       // https://code.google.com/p/webrtc/issues/detail?id=1464
483     }
484 #endif
485
486     return _shared->statistics().SetInitialized();
487 }
488
489 int VoEBaseImpl::Terminate()
490 {
491     WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
492                  "Terminate()");
493     CriticalSectionScoped cs(_shared->crit_sec());
494     return TerminateInternal();
495 }
496
497 int VoEBaseImpl::CreateChannel() {
498   WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
499                "CreateChannel()");
500   CriticalSectionScoped cs(_shared->crit_sec());
501   if (!_shared->statistics().Initialized()) {
502       _shared->SetLastError(VE_NOT_INITED, kTraceError);
503       return -1;
504   }
505
506   voe::ChannelOwner channel_owner = _shared->channel_manager().CreateChannel();
507
508   return InitializeChannel(&channel_owner);
509 }
510
511 int VoEBaseImpl::CreateChannel(const Config& config) {
512   CriticalSectionScoped cs(_shared->crit_sec());
513   if (!_shared->statistics().Initialized()) {
514       _shared->SetLastError(VE_NOT_INITED, kTraceError);
515       return -1;
516   }
517   voe::ChannelOwner channel_owner = _shared->channel_manager().CreateChannel(
518       config);
519   return InitializeChannel(&channel_owner);
520 }
521
522 int VoEBaseImpl::InitializeChannel(voe::ChannelOwner* channel_owner)
523 {
524     if (channel_owner->channel()->SetEngineInformation(
525             _shared->statistics(),
526             *_shared->output_mixer(),
527             *_shared->transmit_mixer(),
528             *_shared->process_thread(),
529             *_shared->audio_device(),
530             _voiceEngineObserverPtr,
531             &_callbackCritSect) != 0) {
532       _shared->SetLastError(
533           VE_CHANNEL_NOT_CREATED,
534           kTraceError,
535           "CreateChannel() failed to associate engine and channel."
536           " Destroying channel.");
537       _shared->channel_manager()
538           .DestroyChannel(channel_owner->channel()->ChannelId());
539       return -1;
540     } else if (channel_owner->channel()->Init() != 0) {
541       _shared->SetLastError(
542           VE_CHANNEL_NOT_CREATED,
543           kTraceError,
544           "CreateChannel() failed to initialize channel. Destroying"
545           " channel.");
546       _shared->channel_manager()
547           .DestroyChannel(channel_owner->channel()->ChannelId());
548       return -1;
549     }
550
551     WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
552         VoEId(_shared->instance_id(), -1),
553         "CreateChannel() => %d", channel_owner->channel()->ChannelId());
554     return channel_owner->channel()->ChannelId();
555 }
556
557 int VoEBaseImpl::DeleteChannel(int channel)
558 {
559     WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
560                  "DeleteChannel(channel=%d)", channel);
561     CriticalSectionScoped cs(_shared->crit_sec());
562
563     if (!_shared->statistics().Initialized())
564     {
565         _shared->SetLastError(VE_NOT_INITED, kTraceError);
566         return -1;
567     }
568
569     {
570         voe::ChannelOwner ch = _shared->channel_manager().GetChannel(channel);
571         voe::Channel* channelPtr = ch.channel();
572         if (channelPtr == NULL)
573         {
574             _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
575                 "DeleteChannel() failed to locate channel");
576             return -1;
577         }
578     }
579
580     _shared->channel_manager().DestroyChannel(channel);
581
582     if (StopSend() != 0)
583     {
584         return -1;
585     }
586
587     if (StopPlayout() != 0)
588     {
589         return -1;
590     }
591
592     return 0;
593 }
594
595 int VoEBaseImpl::StartReceive(int channel)
596 {
597     WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
598                  "StartReceive(channel=%d)", channel);
599     CriticalSectionScoped cs(_shared->crit_sec());
600     if (!_shared->statistics().Initialized())
601     {
602         _shared->SetLastError(VE_NOT_INITED, kTraceError);
603         return -1;
604     }
605     voe::ChannelOwner ch = _shared->channel_manager().GetChannel(channel);
606     voe::Channel* channelPtr = ch.channel();
607     if (channelPtr == NULL)
608     {
609         _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
610             "StartReceive() failed to locate channel");
611         return -1;
612     }
613     return channelPtr->StartReceiving();
614 }
615
616 int VoEBaseImpl::StopReceive(int channel)
617 {
618     WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
619                  "StopListen(channel=%d)", channel);
620     CriticalSectionScoped cs(_shared->crit_sec());
621     if (!_shared->statistics().Initialized())
622     {
623         _shared->SetLastError(VE_NOT_INITED, kTraceError);
624         return -1;
625     }
626     voe::ChannelOwner ch = _shared->channel_manager().GetChannel(channel);
627     voe::Channel* channelPtr = ch.channel();
628     if (channelPtr == NULL)
629     {
630         _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
631             "SetLocalReceiver() failed to locate channel");
632         return -1;
633     }
634     return channelPtr->StopReceiving();
635 }
636
637 int VoEBaseImpl::StartPlayout(int channel)
638 {
639     WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
640                  "StartPlayout(channel=%d)", channel);
641     CriticalSectionScoped cs(_shared->crit_sec());
642     if (!_shared->statistics().Initialized())
643     {
644         _shared->SetLastError(VE_NOT_INITED, kTraceError);
645         return -1;
646     }
647     voe::ChannelOwner ch = _shared->channel_manager().GetChannel(channel);
648     voe::Channel* channelPtr = ch.channel();
649     if (channelPtr == NULL)
650     {
651         _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
652             "StartPlayout() failed to locate channel");
653         return -1;
654     }
655     if (channelPtr->Playing())
656     {
657         return 0;
658     }
659     if (StartPlayout() != 0)
660     {
661         _shared->SetLastError(VE_AUDIO_DEVICE_MODULE_ERROR, kTraceError,
662             "StartPlayout() failed to start playout");
663         return -1;
664     }
665     return channelPtr->StartPlayout();
666 }
667
668 int VoEBaseImpl::StopPlayout(int channel)
669 {
670     WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
671                  "StopPlayout(channel=%d)", channel);
672     CriticalSectionScoped cs(_shared->crit_sec());
673     if (!_shared->statistics().Initialized())
674     {
675         _shared->SetLastError(VE_NOT_INITED, kTraceError);
676         return -1;
677     }
678     voe::ChannelOwner ch = _shared->channel_manager().GetChannel(channel);
679     voe::Channel* channelPtr = ch.channel();
680     if (channelPtr == NULL)
681     {
682         _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
683             "StopPlayout() failed to locate channel");
684         return -1;
685     }
686     if (channelPtr->StopPlayout() != 0)
687     {
688         WEBRTC_TRACE(kTraceWarning, kTraceVoice,
689             VoEId(_shared->instance_id(), -1),
690             "StopPlayout() failed to stop playout for channel %d", channel);
691     }
692     return StopPlayout();
693 }
694
695 int VoEBaseImpl::StartSend(int channel)
696 {
697     WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
698                  "StartSend(channel=%d)", channel);
699     CriticalSectionScoped cs(_shared->crit_sec());
700     if (!_shared->statistics().Initialized())
701     {
702         _shared->SetLastError(VE_NOT_INITED, kTraceError);
703         return -1;
704     }
705     voe::ChannelOwner ch = _shared->channel_manager().GetChannel(channel);
706     voe::Channel* channelPtr = ch.channel();
707     if (channelPtr == NULL)
708     {
709         _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
710             "StartSend() failed to locate channel");
711         return -1;
712     }
713     if (channelPtr->Sending())
714     {
715         return 0;
716     }
717     if (StartSend() != 0)
718     {
719         _shared->SetLastError(VE_AUDIO_DEVICE_MODULE_ERROR, kTraceError,
720             "StartSend() failed to start recording");
721         return -1;
722     }
723     return channelPtr->StartSend();
724 }
725
726 int VoEBaseImpl::StopSend(int channel)
727 {
728     WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
729                  "StopSend(channel=%d)", channel);
730     CriticalSectionScoped cs(_shared->crit_sec());
731     if (!_shared->statistics().Initialized())
732     {
733         _shared->SetLastError(VE_NOT_INITED, kTraceError);
734         return -1;
735     }
736     voe::ChannelOwner ch = _shared->channel_manager().GetChannel(channel);
737     voe::Channel* channelPtr = ch.channel();
738     if (channelPtr == NULL)
739     {
740         _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
741             "StopSend() failed to locate channel");
742         return -1;
743     }
744     if (channelPtr->StopSend() != 0)
745     {
746         WEBRTC_TRACE(kTraceWarning, kTraceVoice,
747             VoEId(_shared->instance_id(), -1),
748             "StopSend() failed to stop sending for channel %d", channel);
749     }
750     return StopSend();
751 }
752
753 int VoEBaseImpl::GetVersion(char version[1024])
754 {
755     WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
756                  "GetVersion(version=?)");
757     assert(kVoiceEngineVersionMaxMessageSize == 1024);
758
759     if (version == NULL)
760     {
761         _shared->SetLastError(VE_INVALID_ARGUMENT, kTraceError);
762         return (-1);
763     }
764
765     char versionBuf[kVoiceEngineVersionMaxMessageSize];
766     char* versionPtr = versionBuf;
767
768     int32_t len = 0;
769     int32_t accLen = 0;
770
771     len = AddVoEVersion(versionPtr);
772     if (len == -1)
773     {
774         return -1;
775     }
776     versionPtr += len;
777     accLen += len;
778     assert(accLen < kVoiceEngineVersionMaxMessageSize);
779
780 #ifdef WEBRTC_EXTERNAL_TRANSPORT
781     len = AddExternalTransportBuild(versionPtr);
782     if (len == -1)
783     {
784          return -1;
785     }
786     versionPtr += len;
787     accLen += len;
788     assert(accLen < kVoiceEngineVersionMaxMessageSize);
789 #endif
790
791     memcpy(version, versionBuf, accLen);
792     version[accLen] = '\0';
793
794     // to avoid the truncation in the trace, split the string into parts
795     char partOfVersion[256];
796     WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
797         VoEId(_shared->instance_id(), -1), "GetVersion() =>");
798     for (int partStart = 0; partStart < accLen;)
799     {
800         memset(partOfVersion, 0, sizeof(partOfVersion));
801         int partEnd = partStart + 180;
802         while (version[partEnd] != '\n' && version[partEnd] != '\0')
803         {
804             partEnd--;
805         }
806         if (partEnd < accLen)
807         {
808             memcpy(partOfVersion, &version[partStart], partEnd - partStart);
809         }
810         else
811         {
812             memcpy(partOfVersion, &version[partStart], accLen - partStart);
813         }
814         partStart = partEnd;
815         WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
816             VoEId(_shared->instance_id(), -1), "%s", partOfVersion);
817     }
818
819     return 0;
820 }
821
822 int32_t VoEBaseImpl::AddVoEVersion(char* str) const
823 {
824     return sprintf(str, "VoiceEngine 4.1.0\n");
825 }
826
827 #ifdef WEBRTC_EXTERNAL_TRANSPORT
828 int32_t VoEBaseImpl::AddExternalTransportBuild(char* str) const
829 {
830     return sprintf(str, "External transport build\n");
831 }
832 #endif
833
834 int VoEBaseImpl::LastError()
835 {
836     WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
837                  "LastError()");
838     return (_shared->statistics().LastError());
839 }
840
841 int32_t VoEBaseImpl::StartPlayout()
842 {
843     WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_shared->instance_id(), -1),
844                  "VoEBaseImpl::StartPlayout()");
845     if (_shared->audio_device()->Playing())
846     {
847         return 0;
848     }
849     if (!_shared->ext_playout())
850     {
851         if (_shared->audio_device()->InitPlayout() != 0)
852         {
853             WEBRTC_TRACE(kTraceError, kTraceVoice,
854                 VoEId(_shared->instance_id(), -1),
855                 "StartPlayout() failed to initialize playout");
856             return -1;
857         }
858         if (_shared->audio_device()->StartPlayout() != 0)
859         {
860             WEBRTC_TRACE(kTraceError, kTraceVoice,
861                 VoEId(_shared->instance_id(), -1),
862                 "StartPlayout() failed to start playout");
863             return -1;
864         }
865     }
866     return 0;
867 }
868
869 int32_t VoEBaseImpl::StopPlayout() {
870   WEBRTC_TRACE(kTraceInfo,
871                kTraceVoice,
872                VoEId(_shared->instance_id(), -1),
873                "VoEBaseImpl::StopPlayout()");
874   // Stop audio-device playing if no channel is playing out
875   if (_shared->NumOfPlayingChannels() == 0) {
876     if (_shared->audio_device()->StopPlayout() != 0) {
877       _shared->SetLastError(VE_CANNOT_STOP_PLAYOUT,
878                             kTraceError,
879                             "StopPlayout() failed to stop playout");
880       return -1;
881     }
882   }
883   return 0;
884 }
885
886 int32_t VoEBaseImpl::StartSend()
887 {
888     WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_shared->instance_id(), -1),
889                  "VoEBaseImpl::StartSend()");
890     if (_shared->audio_device()->Recording())
891     {
892         return 0;
893     }
894     if (!_shared->ext_recording())
895     {
896         if (_shared->audio_device()->InitRecording() != 0)
897         {
898             WEBRTC_TRACE(kTraceError, kTraceVoice,
899                 VoEId(_shared->instance_id(), -1),
900                 "StartSend() failed to initialize recording");
901             return -1;
902         }
903         if (_shared->audio_device()->StartRecording() != 0)
904         {
905             WEBRTC_TRACE(kTraceError, kTraceVoice,
906                 VoEId(_shared->instance_id(), -1),
907                 "StartSend() failed to start recording");
908             return -1;
909         }
910     }
911
912     return 0;
913 }
914
915 int32_t VoEBaseImpl::StopSend()
916 {
917     WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_shared->instance_id(), -1),
918                  "VoEBaseImpl::StopSend()");
919
920     if (_shared->NumOfSendingChannels() == 0 &&
921         !_shared->transmit_mixer()->IsRecordingMic())
922     {
923         // Stop audio-device recording if no channel is recording
924         if (_shared->audio_device()->StopRecording() != 0)
925         {
926             _shared->SetLastError(VE_CANNOT_STOP_RECORDING, kTraceError,
927                 "StopSend() failed to stop recording");
928             return -1;
929         }
930         _shared->transmit_mixer()->StopSend();
931     }
932
933     return 0;
934 }
935
936 int32_t VoEBaseImpl::TerminateInternal()
937 {
938     WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_shared->instance_id(), -1),
939                  "VoEBaseImpl::TerminateInternal()");
940
941     // Delete any remaining channel objects
942     _shared->channel_manager().DestroyAllChannels();
943
944     if (_shared->process_thread())
945     {
946         if (_shared->audio_device())
947         {
948             if (_shared->process_thread()->
949                     DeRegisterModule(_shared->audio_device()) != 0)
950             {
951                 _shared->SetLastError(VE_THREAD_ERROR, kTraceError,
952                     "TerminateInternal() failed to deregister ADM");
953             }
954         }
955         if (_shared->process_thread()->Stop() != 0)
956         {
957             _shared->SetLastError(VE_THREAD_ERROR, kTraceError,
958                 "TerminateInternal() failed to stop module process thread");
959         }
960     }
961
962     if (_shared->audio_device())
963     {
964         if (_shared->audio_device()->StopPlayout() != 0)
965         {
966             _shared->SetLastError(VE_SOUNDCARD_ERROR, kTraceWarning,
967                 "TerminateInternal() failed to stop playout");
968         }
969         if (_shared->audio_device()->StopRecording() != 0)
970         {
971             _shared->SetLastError(VE_SOUNDCARD_ERROR, kTraceWarning,
972                 "TerminateInternal() failed to stop recording");
973         }
974         if (_shared->audio_device()->RegisterEventObserver(NULL) != 0) {
975           _shared->SetLastError(VE_AUDIO_DEVICE_MODULE_ERROR, kTraceWarning,
976               "TerminateInternal() failed to de-register event observer "
977               "for the ADM");
978         }
979         if (_shared->audio_device()->RegisterAudioCallback(NULL) != 0) {
980           _shared->SetLastError(VE_AUDIO_DEVICE_MODULE_ERROR, kTraceWarning,
981               "TerminateInternal() failed to de-register audio callback "
982               "for the ADM");
983         }
984         if (_shared->audio_device()->Terminate() != 0)
985         {
986             _shared->SetLastError(VE_AUDIO_DEVICE_MODULE_ERROR, kTraceError,
987                 "TerminateInternal() failed to terminate the ADM");
988         }
989         _shared->set_audio_device(NULL);
990     }
991
992     if (_shared->audio_processing()) {
993         _shared->set_audio_processing(NULL);
994     }
995
996     return _shared->statistics().SetUnInitialized();
997 }
998
999 int VoEBaseImpl::ProcessRecordedDataWithAPM(
1000     const int voe_channels[],
1001     int number_of_voe_channels,
1002     const void* audio_data,
1003     uint32_t sample_rate,
1004     uint8_t number_of_channels,
1005     uint32_t number_of_frames,
1006     uint32_t audio_delay_milliseconds,
1007     int32_t clock_drift,
1008     uint32_t volume,
1009     bool key_pressed) {
1010   assert(_shared->transmit_mixer() != NULL);
1011   assert(_shared->audio_device() != NULL);
1012
1013   uint32_t max_volume = 0;
1014   uint16_t voe_mic_level = 0;
1015   // Check for zero to skip this calculation; the consumer may use this to
1016   // indicate no volume is available.
1017   if (volume != 0) {
1018     // Scale from ADM to VoE level range
1019     if (_shared->audio_device()->MaxMicrophoneVolume(&max_volume) == 0) {
1020       if (max_volume) {
1021         voe_mic_level = static_cast<uint16_t>(
1022             (volume * kMaxVolumeLevel +
1023                 static_cast<int>(max_volume / 2)) / max_volume);
1024       }
1025     }
1026     // We learned that on certain systems (e.g Linux) the voe_mic_level
1027     // can be greater than the maxVolumeLevel therefore
1028     // we are going to cap the voe_mic_level to the maxVolumeLevel
1029     // and change the maxVolume to volume if it turns out that
1030     // the voe_mic_level is indeed greater than the maxVolumeLevel.
1031     if (voe_mic_level > kMaxVolumeLevel) {
1032       voe_mic_level = kMaxVolumeLevel;
1033       max_volume = volume;
1034     }
1035   }
1036
1037   // Perform channel-independent operations
1038   // (APM, mix with file, record to file, mute, etc.)
1039   _shared->transmit_mixer()->PrepareDemux(
1040       audio_data, number_of_frames, number_of_channels, sample_rate,
1041       static_cast<uint16_t>(audio_delay_milliseconds), clock_drift,
1042       voe_mic_level, key_pressed);
1043
1044   // Copy the audio frame to each sending channel and perform
1045   // channel-dependent operations (file mixing, mute, etc.), encode and
1046   // packetize+transmit the RTP packet. When |number_of_voe_channels| == 0,
1047   // do the operations on all the existing VoE channels; otherwise the
1048   // operations will be done on specific channels.
1049   if (number_of_voe_channels == 0) {
1050     _shared->transmit_mixer()->DemuxAndMix();
1051     _shared->transmit_mixer()->EncodeAndSend();
1052   } else {
1053     _shared->transmit_mixer()->DemuxAndMix(voe_channels,
1054                                            number_of_voe_channels);
1055     _shared->transmit_mixer()->EncodeAndSend(voe_channels,
1056                                              number_of_voe_channels);
1057   }
1058
1059   // Scale from VoE to ADM level range.
1060   uint32_t new_voe_mic_level = _shared->transmit_mixer()->CaptureLevel();
1061
1062   if (new_voe_mic_level != voe_mic_level) {
1063     // Return the new volume if AGC has changed the volume.
1064     return static_cast<int>(
1065         (new_voe_mic_level * max_volume +
1066             static_cast<int>(kMaxVolumeLevel / 2)) / kMaxVolumeLevel);
1067   }
1068
1069   // Return 0 to indicate no change on the volume.
1070   return 0;
1071 }
1072
1073 void VoEBaseImpl::GetPlayoutData(int sample_rate, int number_of_channels,
1074                                  int number_of_frames, bool feed_data_to_apm,
1075                                  void* audio_data,
1076                                  int64_t* elapsed_time_ms,
1077                                  int64_t* ntp_time_ms) {
1078   assert(_shared->output_mixer() != NULL);
1079
1080   // TODO(andrew): if the device is running in mono, we should tell the mixer
1081   // here so that it will only request mono from AudioCodingModule.
1082   // Perform mixing of all active participants (channel-based mixing)
1083   _shared->output_mixer()->MixActiveChannels();
1084
1085   // Additional operations on the combined signal
1086   _shared->output_mixer()->DoOperationsOnCombinedSignal(feed_data_to_apm);
1087
1088   // Retrieve the final output mix (resampled to match the ADM)
1089   _shared->output_mixer()->GetMixedAudio(sample_rate, number_of_channels,
1090                                          &_audioFrame);
1091
1092   assert(number_of_frames == _audioFrame.samples_per_channel_);
1093   assert(sample_rate == _audioFrame.sample_rate_hz_);
1094
1095   // Deliver audio (PCM) samples to the ADM
1096   memcpy(audio_data, _audioFrame.data_,
1097          sizeof(int16_t) * number_of_frames * number_of_channels);
1098
1099   *elapsed_time_ms = _audioFrame.elapsed_time_ms_;
1100   *ntp_time_ms = _audioFrame.ntp_time_ms_;
1101 }
1102
1103 }  // namespace webrtc