blob: 566bae1311bbf276ba289685a2fc0d2a43ac0e94 [file] [log] [blame]
solenberg566ef242015-11-06 15:34:49 -08001/*
2 * Copyright (c) 2015 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
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020011#include "audio/audio_state.h"
solenberg566ef242015-11-06 15:34:49 -080012
Fredrik Solenberg2a877972017-12-15 16:42:15 +010013#include <algorithm>
Mirko Bonadei317a1f02019-09-17 17:06:18 +020014#include <memory>
Fredrik Solenberg2a877972017-12-15 16:42:15 +010015#include <utility>
16#include <vector>
17
Fredrik Solenbergd5247512017-12-18 22:41:03 +010018#include "audio/audio_receive_stream.h"
Tim Nab8c775a2020-01-10 10:33:05 -080019#include "audio/audio_send_stream.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020020#include "modules/audio_device/include/audio_device.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020021#include "rtc_base/checks.h"
22#include "rtc_base/logging.h"
Steve Anton10542f22019-01-11 09:11:00 -080023#include "rtc_base/ref_counted_object.h"
henrika5f6bf242017-11-01 11:06:56 +010024#include "rtc_base/thread.h"
solenberg566ef242015-11-06 15:34:49 -080025
26namespace webrtc {
27namespace internal {
28
29AudioState::AudioState(const AudioState::Config& config)
aleloidd310712016-11-17 06:28:59 -080030 : config_(config),
Olga Sharonova09ceed22020-09-30 18:27:39 +020031 audio_transport_(config_.audio_mixer,
32 config_.audio_processing.get(),
33 config_.async_audio_processing_factory.get()) {
Sebastian Janssonc01367d2019-04-08 15:20:44 +020034 process_thread_checker_.Detach();
aleloi10111bc2016-11-17 06:48:48 -080035 RTC_DCHECK(config_.audio_mixer);
Fredrik Solenbergaaedf752017-12-18 13:09:12 +010036 RTC_DCHECK(config_.audio_device_module);
solenberg566ef242015-11-06 15:34:49 -080037}
38
39AudioState::~AudioState() {
Sebastian Janssonc01367d2019-04-08 15:20:44 +020040 RTC_DCHECK(thread_checker_.IsCurrent());
Fredrik Solenbergd5247512017-12-18 22:41:03 +010041 RTC_DCHECK(receiving_streams_.empty());
Fredrik Solenberg2a877972017-12-15 16:42:15 +010042 RTC_DCHECK(sending_streams_.empty());
solenberg566ef242015-11-06 15:34:49 -080043}
44
Mirko Bonadei8fdcac32018-08-28 16:30:18 +020045AudioProcessing* AudioState::audio_processing() {
Mirko Bonadei8fdcac32018-08-28 16:30:18 +020046 return config_.audio_processing.get();
47}
48
49AudioTransport* AudioState::audio_transport() {
50 return &audio_transport_;
51}
52
solenberg566ef242015-11-06 15:34:49 -080053bool AudioState::typing_noise_detected() const {
Sebastian Janssonc01367d2019-04-08 15:20:44 +020054 RTC_DCHECK(thread_checker_.IsCurrent());
Fredrik Solenberg2a877972017-12-15 16:42:15 +010055 return audio_transport_.typing_noise_detected();
56}
57
Fredrik Solenbergd5247512017-12-18 22:41:03 +010058void AudioState::AddReceivingStream(webrtc::AudioReceiveStream* stream) {
Sebastian Janssonc01367d2019-04-08 15:20:44 +020059 RTC_DCHECK(thread_checker_.IsCurrent());
Fredrik Solenbergd5247512017-12-18 22:41:03 +010060 RTC_DCHECK_EQ(0, receiving_streams_.count(stream));
61 receiving_streams_.insert(stream);
62 if (!config_.audio_mixer->AddSource(
Yves Gerey665174f2018-06-19 15:03:05 +020063 static_cast<internal::AudioReceiveStream*>(stream))) {
Jonas Olsson24ea8222018-01-25 10:14:29 +010064 RTC_DLOG(LS_ERROR) << "Failed to add source to mixer.";
Fredrik Solenbergd5247512017-12-18 22:41:03 +010065 }
66
67 // Make sure playback is initialized; start playing if enabled.
Gustaf Ullbergdabdde62019-10-17 11:32:10 +020068 UpdateNullAudioPollerState();
Fredrik Solenbergd5247512017-12-18 22:41:03 +010069 auto* adm = config_.audio_device_module.get();
70 if (!adm->Playing()) {
71 if (adm->InitPlayout() == 0) {
72 if (playout_enabled_) {
73 adm->StartPlayout();
74 }
75 } else {
76 RTC_DLOG_F(LS_ERROR) << "Failed to initialize playout.";
77 }
78 }
79}
80
81void AudioState::RemoveReceivingStream(webrtc::AudioReceiveStream* stream) {
Sebastian Janssonc01367d2019-04-08 15:20:44 +020082 RTC_DCHECK(thread_checker_.IsCurrent());
Fredrik Solenbergd5247512017-12-18 22:41:03 +010083 auto count = receiving_streams_.erase(stream);
84 RTC_DCHECK_EQ(1, count);
85 config_.audio_mixer->RemoveSource(
86 static_cast<internal::AudioReceiveStream*>(stream));
Gustaf Ullbergdabdde62019-10-17 11:32:10 +020087 UpdateNullAudioPollerState();
Fredrik Solenbergd5247512017-12-18 22:41:03 +010088 if (receiving_streams_.empty()) {
89 config_.audio_device_module->StopPlayout();
90 }
91}
92
Fredrik Solenberg2a877972017-12-15 16:42:15 +010093void AudioState::AddSendingStream(webrtc::AudioSendStream* stream,
Yves Gerey665174f2018-06-19 15:03:05 +020094 int sample_rate_hz,
95 size_t num_channels) {
Sebastian Janssonc01367d2019-04-08 15:20:44 +020096 RTC_DCHECK(thread_checker_.IsCurrent());
Fredrik Solenberg2a877972017-12-15 16:42:15 +010097 auto& properties = sending_streams_[stream];
98 properties.sample_rate_hz = sample_rate_hz;
99 properties.num_channels = num_channels;
100 UpdateAudioTransportWithSendingStreams();
Fredrik Solenbergaaedf752017-12-18 13:09:12 +0100101
102 // Make sure recording is initialized; start recording if enabled.
103 auto* adm = config_.audio_device_module.get();
104 if (!adm->Recording()) {
105 if (adm->InitRecording() == 0) {
106 if (recording_enabled_) {
107 adm->StartRecording();
108 }
109 } else {
110 RTC_DLOG_F(LS_ERROR) << "Failed to initialize recording.";
111 }
112 }
Fredrik Solenberg2a877972017-12-15 16:42:15 +0100113}
114
115void AudioState::RemoveSendingStream(webrtc::AudioSendStream* stream) {
Sebastian Janssonc01367d2019-04-08 15:20:44 +0200116 RTC_DCHECK(thread_checker_.IsCurrent());
Fredrik Solenberg2a877972017-12-15 16:42:15 +0100117 auto count = sending_streams_.erase(stream);
118 RTC_DCHECK_EQ(1, count);
119 UpdateAudioTransportWithSendingStreams();
Fredrik Solenbergaaedf752017-12-18 13:09:12 +0100120 if (sending_streams_.empty()) {
121 config_.audio_device_module->StopRecording();
122 }
solenberg566ef242015-11-06 15:34:49 -0800123}
124
henrika5f6bf242017-11-01 11:06:56 +0100125void AudioState::SetPlayout(bool enabled) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100126 RTC_LOG(INFO) << "SetPlayout(" << enabled << ")";
Sebastian Janssonc01367d2019-04-08 15:20:44 +0200127 RTC_DCHECK(thread_checker_.IsCurrent());
Fredrik Solenbergd5247512017-12-18 22:41:03 +0100128 if (playout_enabled_ != enabled) {
129 playout_enabled_ = enabled;
130 if (enabled) {
Gustaf Ullbergdabdde62019-10-17 11:32:10 +0200131 UpdateNullAudioPollerState();
Fredrik Solenbergd5247512017-12-18 22:41:03 +0100132 if (!receiving_streams_.empty()) {
133 config_.audio_device_module->StartPlayout();
134 }
135 } else {
136 config_.audio_device_module->StopPlayout();
Gustaf Ullbergdabdde62019-10-17 11:32:10 +0200137 UpdateNullAudioPollerState();
Fredrik Solenbergd5247512017-12-18 22:41:03 +0100138 }
henrika5f6bf242017-11-01 11:06:56 +0100139 }
140}
141
142void AudioState::SetRecording(bool enabled) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100143 RTC_LOG(INFO) << "SetRecording(" << enabled << ")";
Sebastian Janssonc01367d2019-04-08 15:20:44 +0200144 RTC_DCHECK(thread_checker_.IsCurrent());
Fredrik Solenbergaaedf752017-12-18 13:09:12 +0100145 if (recording_enabled_ != enabled) {
146 recording_enabled_ = enabled;
147 if (enabled) {
148 if (!sending_streams_.empty()) {
149 config_.audio_device_module->StartRecording();
150 }
151 } else {
152 config_.audio_device_module->StopRecording();
153 }
154 }
Fredrik Solenberg2a877972017-12-15 16:42:15 +0100155}
156
Fredrik Solenberg2a877972017-12-15 16:42:15 +0100157void AudioState::SetStereoChannelSwapping(bool enable) {
Sebastian Janssonc01367d2019-04-08 15:20:44 +0200158 RTC_DCHECK(thread_checker_.IsCurrent());
Fredrik Solenberg2a877972017-12-15 16:42:15 +0100159 audio_transport_.SetStereoChannelSwapping(enable);
henrika5f6bf242017-11-01 11:06:56 +0100160}
161
Fredrik Solenberg2a877972017-12-15 16:42:15 +0100162void AudioState::UpdateAudioTransportWithSendingStreams() {
Sebastian Janssonc01367d2019-04-08 15:20:44 +0200163 RTC_DCHECK(thread_checker_.IsCurrent());
Tim Nab8c775a2020-01-10 10:33:05 -0800164 std::vector<AudioSender*> audio_senders;
Fredrik Solenberg2a877972017-12-15 16:42:15 +0100165 int max_sample_rate_hz = 8000;
166 size_t max_num_channels = 1;
167 for (const auto& kv : sending_streams_) {
Tim Nab8c775a2020-01-10 10:33:05 -0800168 audio_senders.push_back(kv.first);
Fredrik Solenberg2a877972017-12-15 16:42:15 +0100169 max_sample_rate_hz = std::max(max_sample_rate_hz, kv.second.sample_rate_hz);
170 max_num_channels = std::max(max_num_channels, kv.second.num_channels);
171 }
Tim Nab8c775a2020-01-10 10:33:05 -0800172 audio_transport_.UpdateAudioSenders(std::move(audio_senders),
173 max_sample_rate_hz, max_num_channels);
Fredrik Solenberg2a877972017-12-15 16:42:15 +0100174}
Gustaf Ullbergdabdde62019-10-17 11:32:10 +0200175
176void AudioState::UpdateNullAudioPollerState() {
177 // Run NullAudioPoller when there are receiving streams and playout is
178 // disabled.
179 if (!receiving_streams_.empty() && !playout_enabled_) {
Sebastian Janssonfdbbada2020-01-30 18:13:54 +0000180 if (!null_audio_poller_)
181 null_audio_poller_ = std::make_unique<NullAudioPoller>(&audio_transport_);
Gustaf Ullbergdabdde62019-10-17 11:32:10 +0200182 } else {
Sebastian Janssonfdbbada2020-01-30 18:13:54 +0000183 null_audio_poller_.reset();
Gustaf Ullbergdabdde62019-10-17 11:32:10 +0200184 }
185}
solenberg566ef242015-11-06 15:34:49 -0800186} // namespace internal
187
188rtc::scoped_refptr<AudioState> AudioState::Create(
189 const AudioState::Config& config) {
Niels Möllerac63ac72019-01-08 13:47:12 +0100190 return new rtc::RefCountedObject<internal::AudioState>(config);
solenberg566ef242015-11-06 15:34:49 -0800191}
192} // namespace webrtc