blob: 5d49872620840e8d331e1e13cbbcd751e64a898b [file] [log] [blame]
niklase@google.com470e71d2011-07-07 08:21:25 +00001/*
xians@webrtc.org79af7342012-01-31 12:22:14 +00002 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
niklase@google.com470e71d2011-07-07 08:21:25 +00003 *
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
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020011#include "voice_engine/voe_base_impl.h"
niklase@google.com470e71d2011-07-07 08:21:25 +000012
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020013#include "common_audio/signal_processing/include/signal_processing_library.h"
14#include "modules/audio_coding/include/audio_coding_module.h"
15#include "modules/audio_device/audio_device_impl.h"
16#include "modules/audio_processing/include/audio_processing.h"
17#include "rtc_base/format_macros.h"
18#include "rtc_base/location.h"
19#include "rtc_base/logging.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020020#include "voice_engine/channel.h"
21#include "voice_engine/include/voe_errors.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020022#include "voice_engine/transmit_mixer.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020023#include "voice_engine/voice_engine_impl.h"
niklase@google.com470e71d2011-07-07 08:21:25 +000024
Jelena Marusic2dd6a272015-04-14 09:47:00 +020025namespace webrtc {
niklase@google.com470e71d2011-07-07 08:21:25 +000026
Jelena Marusic2dd6a272015-04-14 09:47:00 +020027VoEBase* VoEBase::GetInterface(VoiceEngine* voiceEngine) {
28 if (nullptr == voiceEngine) {
29 return nullptr;
30 }
31 VoiceEngineImpl* s = static_cast<VoiceEngineImpl*>(voiceEngine);
32 s->AddRef();
33 return s;
niklase@google.com470e71d2011-07-07 08:21:25 +000034}
35
Jelena Marusic2dd6a272015-04-14 09:47:00 +020036VoEBaseImpl::VoEBaseImpl(voe::SharedData* shared)
solenbergfc3a2e32017-09-26 09:35:01 -070037 : shared_(shared) {}
Jelena Marusic2dd6a272015-04-14 09:47:00 +020038
39VoEBaseImpl::~VoEBaseImpl() {
40 TerminateInternal();
niklase@google.com470e71d2011-07-07 08:21:25 +000041}
42
henrikaec6fbd22017-03-31 05:43:36 -070043int32_t VoEBaseImpl::RecordedDataIsAvailable(
44 const void* audio_data,
45 const size_t number_of_frames,
46 const size_t bytes_per_sample,
47 const size_t number_of_channels,
48 const uint32_t sample_rate,
49 const uint32_t audio_delay_milliseconds,
50 const int32_t clock_drift,
51 const uint32_t volume,
52 const bool key_pressed,
53 uint32_t& new_mic_volume) {
54 RTC_DCHECK_EQ(2 * number_of_channels, bytes_per_sample);
55 RTC_DCHECK(shared_->transmit_mixer() != nullptr);
56 RTC_DCHECK(shared_->audio_device() != nullptr);
57
Fredrik Solenberg55900fd2017-11-23 20:22:55 +010058 constexpr uint32_t kMaxVolumeLevel = 255;
59
henrikaec6fbd22017-03-31 05:43:36 -070060 uint32_t max_volume = 0;
61 uint16_t voe_mic_level = 0;
62 // Check for zero to skip this calculation; the consumer may use this to
63 // indicate no volume is available.
64 if (volume != 0) {
65 // Scale from ADM to VoE level range
66 if (shared_->audio_device()->MaxMicrophoneVolume(&max_volume) == 0) {
67 if (max_volume) {
68 voe_mic_level = static_cast<uint16_t>(
69 (volume * kMaxVolumeLevel + static_cast<int>(max_volume / 2)) /
70 max_volume);
71 }
72 }
73 // We learned that on certain systems (e.g Linux) the voe_mic_level
74 // can be greater than the maxVolumeLevel therefore
75 // we are going to cap the voe_mic_level to the maxVolumeLevel
76 // and change the maxVolume to volume if it turns out that
77 // the voe_mic_level is indeed greater than the maxVolumeLevel.
78 if (voe_mic_level > kMaxVolumeLevel) {
79 voe_mic_level = kMaxVolumeLevel;
80 max_volume = volume;
81 }
82 }
83
84 // Perform channel-independent operations
85 // (APM, mix with file, record to file, mute, etc.)
86 shared_->transmit_mixer()->PrepareDemux(
87 audio_data, number_of_frames, number_of_channels, sample_rate,
88 static_cast<uint16_t>(audio_delay_milliseconds), clock_drift,
89 voe_mic_level, key_pressed);
90
91 // Copy the audio frame to each sending channel and perform
92 // channel-dependent operations (file mixing, mute, etc.), encode and
93 // packetize+transmit the RTP packet.
94 shared_->transmit_mixer()->ProcessAndEncodeAudio();
95
96 // Scale from VoE to ADM level range.
97 uint32_t new_voe_mic_level = shared_->transmit_mixer()->CaptureLevel();
98 if (new_voe_mic_level != voe_mic_level) {
99 // Return the new volume if AGC has changed the volume.
100 return static_cast<int>((new_voe_mic_level * max_volume +
101 static_cast<int>(kMaxVolumeLevel / 2)) /
102 kMaxVolumeLevel);
103 }
104
Jelena Marusic2dd6a272015-04-14 09:47:00 +0200105 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000106}
107
solenberg13725082015-11-25 08:16:52 -0800108int32_t VoEBaseImpl::NeedMorePlayData(const size_t nSamples,
109 const size_t nBytesPerSample,
Peter Kasting69558702016-01-12 16:26:35 -0800110 const size_t nChannels,
solenberg13725082015-11-25 08:16:52 -0800111 const uint32_t samplesPerSec,
112 void* audioSamples,
113 size_t& nSamplesOut,
Jelena Marusic2dd6a272015-04-14 09:47:00 +0200114 int64_t* elapsed_time_ms,
115 int64_t* ntp_time_ms) {
solenberg2397b9a2017-09-22 06:48:10 -0700116 RTC_NOTREACHED();
xians@webrtc.org56925312014-04-14 10:50:37 +0000117 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000118}
119
xians@webrtc.org56925312014-04-14 10:50:37 +0000120void VoEBaseImpl::PushCaptureData(int voe_channel, const void* audio_data,
121 int bits_per_sample, int sample_rate,
Peter Kasting69558702016-01-12 16:26:35 -0800122 size_t number_of_channels,
Peter Kastingdce40cf2015-08-24 14:52:23 -0700123 size_t number_of_frames) {
Jelena Marusic2dd6a272015-04-14 09:47:00 +0200124 voe::ChannelOwner ch = shared_->channel_manager().GetChannel(voe_channel);
henrikaec6fbd22017-03-31 05:43:36 -0700125 voe::Channel* channel = ch.channel();
126 if (!channel)
127 return;
128 if (channel->Sending()) {
129 // Send the audio to each channel directly without using the APM in the
130 // transmit mixer.
131 channel->ProcessAndEncodeAudio(static_cast<const int16_t*>(audio_data),
132 sample_rate, number_of_frames,
133 number_of_channels);
xians@webrtc.org07e51962014-01-29 13:54:02 +0000134 }
135}
136
Peter Kastingdce40cf2015-08-24 14:52:23 -0700137void VoEBaseImpl::PullRenderData(int bits_per_sample,
138 int sample_rate,
Peter Kasting69558702016-01-12 16:26:35 -0800139 size_t number_of_channels,
Peter Kastingdce40cf2015-08-24 14:52:23 -0700140 size_t number_of_frames,
Jelena Marusic2dd6a272015-04-14 09:47:00 +0200141 void* audio_data, int64_t* elapsed_time_ms,
wu@webrtc.orgcb711f72014-05-19 17:39:11 +0000142 int64_t* ntp_time_ms) {
solenberg2397b9a2017-09-22 06:48:10 -0700143 RTC_NOTREACHED();
xians@webrtc.org56925312014-04-14 10:50:37 +0000144}
145
ossu5f7cfa52016-05-30 08:11:28 -0700146int VoEBaseImpl::Init(
Fredrik Solenbergd3195342017-11-21 20:33:05 +0100147 AudioDeviceModule* audio_device,
peahe67bedb2017-07-07 04:25:11 -0700148 AudioProcessing* audio_processing,
ossu5f7cfa52016-05-30 08:11:28 -0700149 const rtc::scoped_refptr<AudioDecoderFactory>& decoder_factory) {
Fredrik Solenbergd3195342017-11-21 20:33:05 +0100150 RTC_DCHECK(audio_device);
peahe67bedb2017-07-07 04:25:11 -0700151 RTC_DCHECK(audio_processing);
tommi31fc21f2016-01-21 10:37:37 -0800152 rtc::CritScope cs(shared_->crit_sec());
Jelena Marusic2dd6a272015-04-14 09:47:00 +0200153 if (shared_->process_thread()) {
154 shared_->process_thread()->Start();
155 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000156
Fredrik Solenbergd3195342017-11-21 20:33:05 +0100157 shared_->set_audio_device(audio_device);
peahe67bedb2017-07-07 04:25:11 -0700158 shared_->set_audio_processing(audio_processing);
niklas.enbom@webrtc.orge33a1022011-11-16 10:33:53 +0000159
Karl Wibergf3850f62017-11-02 13:04:41 +0100160 RTC_DCHECK(decoder_factory);
161 decoder_factory_ = decoder_factory;
ossu5f7cfa52016-05-30 08:11:28 -0700162
solenberg1c239d42017-09-29 06:00:28 -0700163 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000164}
165
Fredrik Solenberg55900fd2017-11-23 20:22:55 +0100166void VoEBaseImpl::Terminate() {
tommi31fc21f2016-01-21 10:37:37 -0800167 rtc::CritScope cs(shared_->crit_sec());
Fredrik Solenberg55900fd2017-11-23 20:22:55 +0100168 TerminateInternal();
niklase@google.com470e71d2011-07-07 08:21:25 +0000169}
170
turaj@webrtc.org03f33702013-11-13 00:02:48 +0000171int VoEBaseImpl::CreateChannel() {
solenberg88499ec2016-09-07 07:34:41 -0700172 return CreateChannel(ChannelConfig());
turaj@webrtc.org03f33702013-11-13 00:02:48 +0000173}
174
solenberg88499ec2016-09-07 07:34:41 -0700175int VoEBaseImpl::CreateChannel(const ChannelConfig& config) {
tommi31fc21f2016-01-21 10:37:37 -0800176 rtc::CritScope cs(shared_->crit_sec());
solenberg88499ec2016-09-07 07:34:41 -0700177 ChannelConfig config_copy(config);
178 config_copy.acm_config.decoder_factory = decoder_factory_;
Jelena Marusic2dd6a272015-04-14 09:47:00 +0200179 voe::ChannelOwner channel_owner =
solenberg88499ec2016-09-07 07:34:41 -0700180 shared_->channel_manager().CreateChannel(config_copy);
turaj@webrtc.org03f33702013-11-13 00:02:48 +0000181 return InitializeChannel(&channel_owner);
182}
183
Jelena Marusic2dd6a272015-04-14 09:47:00 +0200184int VoEBaseImpl::InitializeChannel(voe::ChannelOwner* channel_owner) {
185 if (channel_owner->channel()->SetEngineInformation(
solenberg796b8f92017-03-01 17:02:23 -0800186 *shared_->process_thread(), *shared_->audio_device(),
solenberg1c239d42017-09-29 06:00:28 -0700187 shared_->encoder_queue()) != 0) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100188 RTC_LOG(LS_ERROR)
189 << "CreateChannel() failed to associate engine and channel."
190 " Destroying channel.";
Jelena Marusic2dd6a272015-04-14 09:47:00 +0200191 shared_->channel_manager().DestroyChannel(
192 channel_owner->channel()->ChannelId());
193 return -1;
194 } else if (channel_owner->channel()->Init() != 0) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100195 RTC_LOG(LS_ERROR)
196 << "CreateChannel() failed to initialize channel. Destroying"
197 " channel.";
Jelena Marusic2dd6a272015-04-14 09:47:00 +0200198 shared_->channel_manager().DestroyChannel(
199 channel_owner->channel()->ChannelId());
200 return -1;
201 }
Jelena Marusic2dd6a272015-04-14 09:47:00 +0200202 return channel_owner->channel()->ChannelId();
niklase@google.com470e71d2011-07-07 08:21:25 +0000203}
204
Jelena Marusic2dd6a272015-04-14 09:47:00 +0200205int VoEBaseImpl::DeleteChannel(int channel) {
tommi31fc21f2016-01-21 10:37:37 -0800206 rtc::CritScope cs(shared_->crit_sec());
Jelena Marusic2dd6a272015-04-14 09:47:00 +0200207 {
208 voe::ChannelOwner ch = shared_->channel_manager().GetChannel(channel);
209 voe::Channel* channelPtr = ch.channel();
210 if (channelPtr == nullptr) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100211 RTC_LOG(LS_ERROR) << "DeleteChannel() failed to locate channel";
Jelena Marusic2dd6a272015-04-14 09:47:00 +0200212 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +0000213 }
Jelena Marusic2dd6a272015-04-14 09:47:00 +0200214 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000215
Jelena Marusic2dd6a272015-04-14 09:47:00 +0200216 shared_->channel_manager().DestroyChannel(channel);
217 if (StopSend() != 0) {
218 return -1;
219 }
220 if (StopPlayout() != 0) {
221 return -1;
222 }
223 return 0;
224}
niklase@google.com470e71d2011-07-07 08:21:25 +0000225
Jelena Marusic2dd6a272015-04-14 09:47:00 +0200226int VoEBaseImpl::StartPlayout(int channel) {
tommi31fc21f2016-01-21 10:37:37 -0800227 rtc::CritScope cs(shared_->crit_sec());
Jelena Marusic2dd6a272015-04-14 09:47:00 +0200228 voe::ChannelOwner ch = shared_->channel_manager().GetChannel(channel);
229 voe::Channel* channelPtr = ch.channel();
230 if (channelPtr == nullptr) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100231 RTC_LOG(LS_ERROR) << "StartPlayout() failed to locate channel";
Jelena Marusic2dd6a272015-04-14 09:47:00 +0200232 return -1;
233 }
234 if (channelPtr->Playing()) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000235 return 0;
Jelena Marusic2dd6a272015-04-14 09:47:00 +0200236 }
237 if (StartPlayout() != 0) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100238 RTC_LOG(LS_ERROR) << "StartPlayout() failed to start playout";
Jelena Marusic2dd6a272015-04-14 09:47:00 +0200239 return -1;
240 }
241 return channelPtr->StartPlayout();
niklase@google.com470e71d2011-07-07 08:21:25 +0000242}
243
Jelena Marusic2dd6a272015-04-14 09:47:00 +0200244int VoEBaseImpl::StopPlayout(int channel) {
tommi31fc21f2016-01-21 10:37:37 -0800245 rtc::CritScope cs(shared_->crit_sec());
Jelena Marusic2dd6a272015-04-14 09:47:00 +0200246 voe::ChannelOwner ch = shared_->channel_manager().GetChannel(channel);
247 voe::Channel* channelPtr = ch.channel();
248 if (channelPtr == nullptr) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100249 RTC_LOG(LS_ERROR) << "StopPlayout() failed to locate channel";
Jelena Marusic2dd6a272015-04-14 09:47:00 +0200250 return -1;
251 }
252 if (channelPtr->StopPlayout() != 0) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100253 RTC_LOG_F(LS_WARNING) << "StopPlayout() failed to stop playout for channel "
254 << channel;
Jelena Marusic2dd6a272015-04-14 09:47:00 +0200255 }
256 return StopPlayout();
niklase@google.com470e71d2011-07-07 08:21:25 +0000257}
258
Jelena Marusic2dd6a272015-04-14 09:47:00 +0200259int VoEBaseImpl::StartSend(int channel) {
tommi31fc21f2016-01-21 10:37:37 -0800260 rtc::CritScope cs(shared_->crit_sec());
Jelena Marusic2dd6a272015-04-14 09:47:00 +0200261 voe::ChannelOwner ch = shared_->channel_manager().GetChannel(channel);
262 voe::Channel* channelPtr = ch.channel();
263 if (channelPtr == nullptr) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100264 RTC_LOG(LS_ERROR) << "StartSend() failed to locate channel";
Jelena Marusic2dd6a272015-04-14 09:47:00 +0200265 return -1;
266 }
267 if (channelPtr->Sending()) {
268 return 0;
269 }
270 if (StartSend() != 0) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100271 RTC_LOG(LS_ERROR) << "StartSend() failed to start recording";
Jelena Marusic2dd6a272015-04-14 09:47:00 +0200272 return -1;
273 }
274 return channelPtr->StartSend();
niklase@google.com470e71d2011-07-07 08:21:25 +0000275}
276
Jelena Marusic2dd6a272015-04-14 09:47:00 +0200277int VoEBaseImpl::StopSend(int channel) {
tommi31fc21f2016-01-21 10:37:37 -0800278 rtc::CritScope cs(shared_->crit_sec());
Jelena Marusic2dd6a272015-04-14 09:47:00 +0200279 voe::ChannelOwner ch = shared_->channel_manager().GetChannel(channel);
280 voe::Channel* channelPtr = ch.channel();
281 if (channelPtr == nullptr) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100282 RTC_LOG(LS_ERROR) << "StopSend() failed to locate channel";
Jelena Marusic2dd6a272015-04-14 09:47:00 +0200283 return -1;
284 }
henrikaec6fbd22017-03-31 05:43:36 -0700285 channelPtr->StopSend();
Jelena Marusic2dd6a272015-04-14 09:47:00 +0200286 return StopSend();
niklase@google.com470e71d2011-07-07 08:21:25 +0000287}
288
Jelena Marusic2dd6a272015-04-14 09:47:00 +0200289int32_t VoEBaseImpl::StartPlayout() {
solenberge313e022015-09-08 02:16:04 -0700290 if (!shared_->audio_device()->Playing()) {
Jelena Marusic2dd6a272015-04-14 09:47:00 +0200291 if (shared_->audio_device()->InitPlayout() != 0) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100292 RTC_LOG_F(LS_ERROR) << "Failed to initialize playout";
Jelena Marusic2dd6a272015-04-14 09:47:00 +0200293 return -1;
294 }
henrika5f6bf242017-11-01 11:06:56 +0100295 if (playout_enabled_ && shared_->audio_device()->StartPlayout() != 0) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100296 RTC_LOG_F(LS_ERROR) << "Failed to start playout";
Jelena Marusic2dd6a272015-04-14 09:47:00 +0200297 return -1;
298 }
299 }
300 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000301}
302
pbos@webrtc.org676ff1e2013-08-07 17:57:36 +0000303int32_t VoEBaseImpl::StopPlayout() {
henrika5f6bf242017-11-01 11:06:56 +0100304 if (!playout_enabled_) {
305 return 0;
306 }
307 // Stop audio-device playing if no channel is playing out.
Jelena Marusic2dd6a272015-04-14 09:47:00 +0200308 if (shared_->NumOfPlayingChannels() == 0) {
309 if (shared_->audio_device()->StopPlayout() != 0) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100310 RTC_LOG(LS_ERROR) << "StopPlayout() failed to stop playout";
pbos@webrtc.org676ff1e2013-08-07 17:57:36 +0000311 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +0000312 }
pbos@webrtc.org676ff1e2013-08-07 17:57:36 +0000313 }
314 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000315}
316
Jelena Marusic2dd6a272015-04-14 09:47:00 +0200317int32_t VoEBaseImpl::StartSend() {
henrika5f6bf242017-11-01 11:06:56 +0100318 if (!shared_->audio_device()->Recording()) {
Jelena Marusic2dd6a272015-04-14 09:47:00 +0200319 if (shared_->audio_device()->InitRecording() != 0) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100320 RTC_LOG_F(LS_ERROR) << "Failed to initialize recording";
Jelena Marusic2dd6a272015-04-14 09:47:00 +0200321 return -1;
322 }
henrika5f6bf242017-11-01 11:06:56 +0100323 if (recording_enabled_ && shared_->audio_device()->StartRecording() != 0) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100324 RTC_LOG_F(LS_ERROR) << "Failed to start recording";
Jelena Marusic2dd6a272015-04-14 09:47:00 +0200325 return -1;
326 }
327 }
Jelena Marusic2dd6a272015-04-14 09:47:00 +0200328 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000329}
330
Jelena Marusic2dd6a272015-04-14 09:47:00 +0200331int32_t VoEBaseImpl::StopSend() {
henrika5f6bf242017-11-01 11:06:56 +0100332 if (!recording_enabled_) {
333 return 0;
334 }
335 // Stop audio-device recording if no channel is recording.
solenbergb63310a2017-09-18 03:04:12 -0700336 if (shared_->NumOfSendingChannels() == 0) {
Jelena Marusic2dd6a272015-04-14 09:47:00 +0200337 if (shared_->audio_device()->StopRecording() != 0) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100338 RTC_LOG(LS_ERROR) << "StopSend() failed to stop recording";
Jelena Marusic2dd6a272015-04-14 09:47:00 +0200339 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +0000340 }
Jelena Marusic2dd6a272015-04-14 09:47:00 +0200341 shared_->transmit_mixer()->StopSend();
342 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000343
Jelena Marusic2dd6a272015-04-14 09:47:00 +0200344 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000345}
346
henrika5f6bf242017-11-01 11:06:56 +0100347int32_t VoEBaseImpl::SetPlayout(bool enabled) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100348 RTC_LOG(INFO) << "SetPlayout(" << enabled << ")";
henrika5f6bf242017-11-01 11:06:56 +0100349 if (playout_enabled_ == enabled) {
350 return 0;
351 }
352 playout_enabled_ = enabled;
353 if (shared_->NumOfPlayingChannels() == 0) {
354 // If there are no channels attempting to play out yet, there's nothing to
355 // be done; we should be in a "not playing out" state either way.
356 return 0;
357 }
358 int32_t ret;
359 if (enabled) {
360 ret = shared_->audio_device()->StartPlayout();
361 if (ret != 0) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100362 RTC_LOG(LS_ERROR) << "SetPlayout(true) failed to start playout";
henrika5f6bf242017-11-01 11:06:56 +0100363 }
364 } else {
365 ret = shared_->audio_device()->StopPlayout();
366 if (ret != 0) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100367 RTC_LOG(LS_ERROR) << "SetPlayout(false) failed to stop playout";
henrika5f6bf242017-11-01 11:06:56 +0100368 }
369 }
370 return ret;
371}
372
373int32_t VoEBaseImpl::SetRecording(bool enabled) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100374 RTC_LOG(INFO) << "SetRecording(" << enabled << ")";
henrika5f6bf242017-11-01 11:06:56 +0100375 if (recording_enabled_ == enabled) {
376 return 0;
377 }
378 recording_enabled_ = enabled;
379 if (shared_->NumOfSendingChannels() == 0) {
380 // If there are no channels attempting to record out yet, there's nothing to
381 // be done; we should be in a "not recording" state either way.
382 return 0;
383 }
384 int32_t ret;
385 if (enabled) {
386 ret = shared_->audio_device()->StartRecording();
387 if (ret != 0) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100388 RTC_LOG(LS_ERROR) << "SetRecording(true) failed to start recording";
henrika5f6bf242017-11-01 11:06:56 +0100389 }
390 } else {
391 ret = shared_->audio_device()->StopRecording();
392 if (ret != 0) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100393 RTC_LOG(LS_ERROR) << "SetRecording(false) failed to stop recording";
henrika5f6bf242017-11-01 11:06:56 +0100394 }
395 }
396 return ret;
397}
398
Fredrik Solenberg55900fd2017-11-23 20:22:55 +0100399void VoEBaseImpl::TerminateInternal() {
Jelena Marusic2dd6a272015-04-14 09:47:00 +0200400 // Delete any remaining channel objects
401 shared_->channel_manager().DestroyAllChannels();
niklase@google.com470e71d2011-07-07 08:21:25 +0000402
Jelena Marusic2dd6a272015-04-14 09:47:00 +0200403 if (shared_->process_thread()) {
Jelena Marusic2dd6a272015-04-14 09:47:00 +0200404 shared_->process_thread()->Stop();
405 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000406
Fredrik Solenbergd3195342017-11-21 20:33:05 +0100407 shared_->set_audio_device(nullptr);
peaha9cc40b2017-06-29 08:32:09 -0700408 shared_->set_audio_processing(nullptr);
niklase@google.com470e71d2011-07-07 08:21:25 +0000409}
pbos@webrtc.orgd900e8b2013-07-03 15:12:26 +0000410} // namespace webrtc