1 /*
2 * Copyright (c) 2020 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 "audio/voip/voip_core.h"
12
13 #include <algorithm>
14 #include <memory>
15 #include <utility>
16
17 #include "api/audio_codecs/audio_format.h"
18 #include "rtc_base/logging.h"
19
20 namespace webrtc {
21
22 namespace {
23
24 // For Windows, use specific enum type to initialize default audio device as
25 // defined in AudioDeviceModule::WindowsDeviceType.
26 #if defined(WEBRTC_WIN)
27 constexpr AudioDeviceModule::WindowsDeviceType kAudioDeviceId =
28 AudioDeviceModule::WindowsDeviceType::kDefaultCommunicationDevice;
29 #else
30 constexpr uint16_t kAudioDeviceId = 0;
31 #endif // defined(WEBRTC_WIN)
32
33 // Maximum value range limit on ChannelId. This can be increased without any
34 // side effect and only set at this moderate value for better readability for
35 // logging.
36 static constexpr int kMaxChannelId = 100000;
37
38 } // namespace
39
Init(rtc::scoped_refptr<AudioEncoderFactory> encoder_factory,rtc::scoped_refptr<AudioDecoderFactory> decoder_factory,std::unique_ptr<TaskQueueFactory> task_queue_factory,rtc::scoped_refptr<AudioDeviceModule> audio_device_module,rtc::scoped_refptr<AudioProcessing> audio_processing)40 bool VoipCore::Init(rtc::scoped_refptr<AudioEncoderFactory> encoder_factory,
41 rtc::scoped_refptr<AudioDecoderFactory> decoder_factory,
42 std::unique_ptr<TaskQueueFactory> task_queue_factory,
43 rtc::scoped_refptr<AudioDeviceModule> audio_device_module,
44 rtc::scoped_refptr<AudioProcessing> audio_processing) {
45 encoder_factory_ = std::move(encoder_factory);
46 decoder_factory_ = std::move(decoder_factory);
47 task_queue_factory_ = std::move(task_queue_factory);
48 audio_device_module_ = std::move(audio_device_module);
49
50 process_thread_ = ProcessThread::Create("ModuleProcessThread");
51 audio_mixer_ = AudioMixerImpl::Create();
52
53 if (audio_processing) {
54 audio_processing_ = std::move(audio_processing);
55 AudioProcessing::Config apm_config = audio_processing_->GetConfig();
56 apm_config.echo_canceller.enabled = true;
57 audio_processing_->ApplyConfig(apm_config);
58 }
59
60 // AudioTransportImpl depends on audio mixer and audio processing instances.
61 audio_transport_ = std::make_unique<AudioTransportImpl>(
62 audio_mixer_.get(), audio_processing_.get());
63
64 // Initialize ADM.
65 if (audio_device_module_->Init() != 0) {
66 RTC_LOG(LS_ERROR) << "Failed to initialize the ADM.";
67 return false;
68 }
69
70 // Note that failures on initializing default recording/speaker devices are
71 // not considered to be fatal here. In certain case, caller may not care about
72 // recording device functioning (e.g webinar where only speaker is available).
73 // It's also possible that there are other audio devices available that may
74 // work.
75 // TODO(natim@webrtc.org): consider moving this part out of initialization.
76
77 // Initialize default speaker device.
78 if (audio_device_module_->SetPlayoutDevice(kAudioDeviceId) != 0) {
79 RTC_LOG(LS_WARNING) << "Unable to set playout device.";
80 }
81 if (audio_device_module_->InitSpeaker() != 0) {
82 RTC_LOG(LS_WARNING) << "Unable to access speaker.";
83 }
84
85 // Initialize default recording device.
86 if (audio_device_module_->SetRecordingDevice(kAudioDeviceId) != 0) {
87 RTC_LOG(LS_WARNING) << "Unable to set recording device.";
88 }
89 if (audio_device_module_->InitMicrophone() != 0) {
90 RTC_LOG(LS_WARNING) << "Unable to access microphone.";
91 }
92
93 // Set number of channels on speaker device.
94 bool available = false;
95 if (audio_device_module_->StereoPlayoutIsAvailable(&available) != 0) {
96 RTC_LOG(LS_WARNING) << "Unable to query stereo playout.";
97 }
98 if (audio_device_module_->SetStereoPlayout(available) != 0) {
99 RTC_LOG(LS_WARNING) << "Unable to set mono/stereo playout mode.";
100 }
101
102 // Set number of channels on recording device.
103 available = false;
104 if (audio_device_module_->StereoRecordingIsAvailable(&available) != 0) {
105 RTC_LOG(LS_WARNING) << "Unable to query stereo recording.";
106 }
107 if (audio_device_module_->SetStereoRecording(available) != 0) {
108 RTC_LOG(LS_WARNING) << "Unable to set stereo recording mode.";
109 }
110
111 if (audio_device_module_->RegisterAudioCallback(audio_transport_.get()) !=
112 0) {
113 RTC_LOG(LS_WARNING) << "Unable to register audio callback.";
114 }
115
116 return true;
117 }
118
CreateChannel(Transport * transport,absl::optional<uint32_t> local_ssrc)119 absl::optional<ChannelId> VoipCore::CreateChannel(
120 Transport* transport,
121 absl::optional<uint32_t> local_ssrc) {
122 absl::optional<ChannelId> channel;
123
124 // Set local ssrc to random if not set by caller.
125 if (!local_ssrc) {
126 Random random(rtc::TimeMicros());
127 local_ssrc = random.Rand<uint32_t>();
128 }
129
130 rtc::scoped_refptr<AudioChannel> audio_channel =
131 new rtc::RefCountedObject<AudioChannel>(
132 transport, local_ssrc.value(), task_queue_factory_.get(),
133 process_thread_.get(), audio_mixer_.get(), decoder_factory_);
134
135 {
136 MutexLock lock(&lock_);
137
138 channel = static_cast<ChannelId>(next_channel_id_);
139 channels_[*channel] = audio_channel;
140 next_channel_id_++;
141 if (next_channel_id_ >= kMaxChannelId) {
142 next_channel_id_ = 0;
143 }
144 }
145
146 // Set ChannelId in audio channel for logging/debugging purpose.
147 audio_channel->SetId(*channel);
148
149 return channel;
150 }
151
ReleaseChannel(ChannelId channel)152 void VoipCore::ReleaseChannel(ChannelId channel) {
153 // Destroy channel outside of the lock.
154 rtc::scoped_refptr<AudioChannel> audio_channel;
155 {
156 MutexLock lock(&lock_);
157
158 auto iter = channels_.find(channel);
159 if (iter != channels_.end()) {
160 audio_channel = std::move(iter->second);
161 channels_.erase(iter);
162 }
163 }
164 if (!audio_channel) {
165 RTC_LOG(LS_WARNING) << "Channel " << channel << " not found";
166 }
167 }
168
GetChannel(ChannelId channel)169 rtc::scoped_refptr<AudioChannel> VoipCore::GetChannel(ChannelId channel) {
170 rtc::scoped_refptr<AudioChannel> audio_channel;
171 {
172 MutexLock lock(&lock_);
173 auto iter = channels_.find(channel);
174 if (iter != channels_.end()) {
175 audio_channel = iter->second;
176 }
177 }
178 if (!audio_channel) {
179 RTC_LOG(LS_ERROR) << "Channel " << channel << " not found";
180 }
181 return audio_channel;
182 }
183
UpdateAudioTransportWithSenders()184 bool VoipCore::UpdateAudioTransportWithSenders() {
185 std::vector<AudioSender*> audio_senders;
186
187 // Gather a list of audio channel that are currently sending along with
188 // highest sampling rate and channel numbers to configure into audio
189 // transport.
190 int max_sampling_rate = 8000;
191 size_t max_num_channels = 1;
192 {
193 MutexLock lock(&lock_);
194 // Reserve to prevent run time vector re-allocation.
195 audio_senders.reserve(channels_.size());
196 for (auto kv : channels_) {
197 rtc::scoped_refptr<AudioChannel>& channel = kv.second;
198 if (channel->IsSendingMedia()) {
199 auto encoder_format = channel->GetEncoderFormat();
200 if (!encoder_format) {
201 RTC_LOG(LS_ERROR)
202 << "channel " << channel->GetId() << " encoder is not set";
203 continue;
204 }
205 audio_senders.push_back(channel->GetAudioSender());
206 max_sampling_rate =
207 std::max(max_sampling_rate, encoder_format->clockrate_hz);
208 max_num_channels =
209 std::max(max_num_channels, encoder_format->num_channels);
210 }
211 }
212 }
213
214 audio_transport_->UpdateAudioSenders(audio_senders, max_sampling_rate,
215 max_num_channels);
216
217 // Depending on availability of senders, turn on or off ADM recording.
218 if (!audio_senders.empty()) {
219 if (!audio_device_module_->Recording()) {
220 if (audio_device_module_->InitRecording() != 0) {
221 RTC_LOG(LS_ERROR) << "InitRecording failed";
222 return false;
223 }
224 if (audio_device_module_->StartRecording() != 0) {
225 RTC_LOG(LS_ERROR) << "StartRecording failed";
226 return false;
227 }
228 }
229 } else {
230 if (audio_device_module_->Recording() &&
231 audio_device_module_->StopRecording() != 0) {
232 RTC_LOG(LS_ERROR) << "StopRecording failed";
233 return false;
234 }
235 }
236 return true;
237 }
238
StartSend(ChannelId channel)239 bool VoipCore::StartSend(ChannelId channel) {
240 auto audio_channel = GetChannel(channel);
241 if (!audio_channel) {
242 return false;
243 }
244
245 audio_channel->StartSend();
246
247 return UpdateAudioTransportWithSenders();
248 }
249
StopSend(ChannelId channel)250 bool VoipCore::StopSend(ChannelId channel) {
251 auto audio_channel = GetChannel(channel);
252 if (!audio_channel) {
253 return false;
254 }
255
256 audio_channel->StopSend();
257
258 return UpdateAudioTransportWithSenders();
259 }
260
StartPlayout(ChannelId channel)261 bool VoipCore::StartPlayout(ChannelId channel) {
262 auto audio_channel = GetChannel(channel);
263 if (!audio_channel) {
264 return false;
265 }
266
267 audio_channel->StartPlay();
268
269 if (!audio_device_module_->Playing()) {
270 if (audio_device_module_->InitPlayout() != 0) {
271 RTC_LOG(LS_ERROR) << "InitPlayout failed";
272 return false;
273 }
274 if (audio_device_module_->StartPlayout() != 0) {
275 RTC_LOG(LS_ERROR) << "StartPlayout failed";
276 return false;
277 }
278 }
279 return true;
280 }
281
StopPlayout(ChannelId channel)282 bool VoipCore::StopPlayout(ChannelId channel) {
283 auto audio_channel = GetChannel(channel);
284 if (!audio_channel) {
285 return false;
286 }
287
288 audio_channel->StopPlay();
289
290 bool stop_device = true;
291 {
292 MutexLock lock(&lock_);
293 for (auto kv : channels_) {
294 rtc::scoped_refptr<AudioChannel>& channel = kv.second;
295 if (channel->IsPlaying()) {
296 stop_device = false;
297 break;
298 }
299 }
300 }
301
302 if (stop_device && audio_device_module_->Playing()) {
303 if (audio_device_module_->StopPlayout() != 0) {
304 RTC_LOG(LS_ERROR) << "StopPlayout failed";
305 return false;
306 }
307 }
308 return true;
309 }
310
ReceivedRTPPacket(ChannelId channel,rtc::ArrayView<const uint8_t> rtp_packet)311 void VoipCore::ReceivedRTPPacket(ChannelId channel,
312 rtc::ArrayView<const uint8_t> rtp_packet) {
313 // Failure to locate channel is logged internally in GetChannel.
314 if (auto audio_channel = GetChannel(channel)) {
315 audio_channel->ReceivedRTPPacket(rtp_packet);
316 }
317 }
318
ReceivedRTCPPacket(ChannelId channel,rtc::ArrayView<const uint8_t> rtcp_packet)319 void VoipCore::ReceivedRTCPPacket(ChannelId channel,
320 rtc::ArrayView<const uint8_t> rtcp_packet) {
321 // Failure to locate channel is logged internally in GetChannel.
322 if (auto audio_channel = GetChannel(channel)) {
323 audio_channel->ReceivedRTCPPacket(rtcp_packet);
324 }
325 }
326
SetSendCodec(ChannelId channel,int payload_type,const SdpAudioFormat & encoder_format)327 void VoipCore::SetSendCodec(ChannelId channel,
328 int payload_type,
329 const SdpAudioFormat& encoder_format) {
330 // Failure to locate channel is logged internally in GetChannel.
331 if (auto audio_channel = GetChannel(channel)) {
332 auto encoder = encoder_factory_->MakeAudioEncoder(
333 payload_type, encoder_format, absl::nullopt);
334 audio_channel->SetEncoder(payload_type, encoder_format, std::move(encoder));
335 }
336 }
337
SetReceiveCodecs(ChannelId channel,const std::map<int,SdpAudioFormat> & decoder_specs)338 void VoipCore::SetReceiveCodecs(
339 ChannelId channel,
340 const std::map<int, SdpAudioFormat>& decoder_specs) {
341 // Failure to locate channel is logged internally in GetChannel.
342 if (auto audio_channel = GetChannel(channel)) {
343 audio_channel->SetReceiveCodecs(decoder_specs);
344 }
345 }
346
347 } // namespace webrtc
348