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