Skip to content

Commit f48bd24

Browse files
authored
[Mac] Allow audio device selection (#21)
* first attempt * remove unused dep * init playout / recording * use AudioDeviceID as guid * switch device method * equality * default device * `isDefault` property * dont format default device name * type param * bypass * refactor * fix * append Audio to thread labels * ref * lk headers * low level apis * fix thread checks Some methods of ADM needs to be run on worker thread, otherwise RTC's thread check will fail. * switch to default device when removed * close mixerManager if didn't switch to default device * default audio device switched * expose devices update handler * fix ios compile * fix bug: don't always recreate RTCAudioDeviceModule
1 parent 57b3569 commit f48bd24

25 files changed

+880
-74
lines changed

modules/audio_device/audio_device_data_observer.cc

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -288,6 +288,10 @@ class ADMWrapper : public AudioDeviceModule, public AudioTransport {
288288
}
289289
#endif // WEBRTC_IOS
290290

291+
int32_t SetAudioDeviceSink(AudioDeviceSink* sink) const override {
292+
return impl_->SetAudioDeviceSink(sink);
293+
}
294+
291295
protected:
292296
rtc::scoped_refptr<AudioDeviceModule> impl_;
293297
AudioDeviceDataObserver* legacy_observer_ = nullptr;

modules/audio_device/audio_device_generic.cc

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,4 +63,10 @@ int AudioDeviceGeneric::GetRecordAudioParameters(
6363
}
6464
#endif // WEBRTC_IOS
6565

66+
int32_t AudioDeviceGeneric::SetAudioDeviceSink(AudioDeviceSink* sink) {
67+
RTC_LOG(LS_INFO) << __FUNCTION__ << "(" << sink << ")";
68+
audio_device_module_sink_ = sink;
69+
return 0;
70+
}
71+
6672
} // namespace webrtc

modules/audio_device/audio_device_generic.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,9 +135,14 @@ class AudioDeviceGeneric {
135135
virtual int GetRecordAudioParameters(AudioParameters* params) const;
136136
#endif // WEBRTC_IOS
137137

138+
int32_t SetAudioDeviceSink(AudioDeviceSink* sink);
139+
138140
virtual void AttachAudioBuffer(AudioDeviceBuffer* audioBuffer) = 0;
139141

140142
virtual ~AudioDeviceGeneric() {}
143+
144+
protected:
145+
AudioDeviceSink* audio_device_module_sink_ = nullptr;
141146
};
142147

143148
} // namespace webrtc

modules/audio_device/audio_device_impl.cc

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -72,15 +72,17 @@ namespace webrtc {
7272

7373
rtc::scoped_refptr<AudioDeviceModule> AudioDeviceModule::Create(
7474
AudioLayer audio_layer,
75-
TaskQueueFactory* task_queue_factory) {
75+
TaskQueueFactory* task_queue_factory,
76+
bool bypass_voice_processing) {
7677
RTC_DLOG(LS_INFO) << __FUNCTION__;
77-
return AudioDeviceModule::CreateForTest(audio_layer, task_queue_factory);
78+
return AudioDeviceModule::CreateForTest(audio_layer, task_queue_factory, bypass_voice_processing);
7879
}
7980

8081
// static
8182
rtc::scoped_refptr<AudioDeviceModuleForTest> AudioDeviceModule::CreateForTest(
8283
AudioLayer audio_layer,
83-
TaskQueueFactory* task_queue_factory) {
84+
TaskQueueFactory* task_queue_factory,
85+
bool bypass_voice_processing) {
8486
RTC_DLOG(LS_INFO) << __FUNCTION__;
8587

8688
// The "AudioDeviceModule::kWindowsCoreAudio2" audio layer has its own
@@ -93,7 +95,7 @@ rtc::scoped_refptr<AudioDeviceModuleForTest> AudioDeviceModule::CreateForTest(
9395

9496
// Create the generic reference counted (platform independent) implementation.
9597
auto audio_device = rtc::make_ref_counted<AudioDeviceModuleImpl>(
96-
audio_layer, task_queue_factory);
98+
audio_layer, task_queue_factory, bypass_voice_processing);
9799

98100
// Ensure that the current platform is supported.
99101
if (audio_device->CheckPlatform() == -1) {
@@ -116,8 +118,13 @@ rtc::scoped_refptr<AudioDeviceModuleForTest> AudioDeviceModule::CreateForTest(
116118

117119
AudioDeviceModuleImpl::AudioDeviceModuleImpl(
118120
AudioLayer audio_layer,
119-
TaskQueueFactory* task_queue_factory)
120-
: audio_layer_(audio_layer), audio_device_buffer_(task_queue_factory) {
121+
TaskQueueFactory* task_queue_factory,
122+
bool bypass_voice_processing)
123+
: audio_layer_(audio_layer),
124+
#if defined(WEBRTC_IOS)
125+
bypass_voice_processing_(bypass_voice_processing),
126+
#endif
127+
audio_device_buffer_(task_queue_factory) {
121128
RTC_DLOG(LS_INFO) << __FUNCTION__;
122129
}
123130

@@ -280,7 +287,7 @@ int32_t AudioDeviceModuleImpl::CreatePlatformSpecificObjects() {
280287
#if defined(WEBRTC_IOS)
281288
if (audio_layer == kPlatformDefaultAudio) {
282289
audio_device_.reset(
283-
new ios_adm::AudioDeviceIOS(/*bypass_voice_processing=*/false));
290+
new ios_adm::AudioDeviceIOS(/*bypass_voice_processing=*/bypass_voice_processing_));
284291
RTC_LOG(LS_INFO) << "iPhone Audio APIs will be utilized.";
285292
}
286293
// END #if defined(WEBRTC_IOS)
@@ -937,6 +944,13 @@ int AudioDeviceModuleImpl::GetRecordAudioParameters(
937944
}
938945
#endif // WEBRTC_IOS
939946

947+
int32_t AudioDeviceModuleImpl::SetAudioDeviceSink(AudioDeviceSink* sink) const {
948+
RTC_LOG(LS_INFO) << __FUNCTION__ << "(" << sink << ")";
949+
int32_t ok = audio_device_->SetAudioDeviceSink(sink);
950+
RTC_LOG(LS_INFO) << "output: " << ok;
951+
return ok;
952+
}
953+
940954
AudioDeviceModuleImpl::PlatformType AudioDeviceModuleImpl::Platform() const {
941955
RTC_LOG(LS_INFO) << __FUNCTION__;
942956
return platform_type_;

modules/audio_device/audio_device_impl.h

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,8 @@ class AudioDeviceModuleImpl : public AudioDeviceModuleForTest {
4343
int32_t AttachAudioBuffer();
4444

4545
AudioDeviceModuleImpl(AudioLayer audio_layer,
46-
TaskQueueFactory* task_queue_factory);
46+
TaskQueueFactory* task_queue_factory,
47+
bool bypass_voice_processing = false);
4748
~AudioDeviceModuleImpl() override;
4849

4950
// Retrieve the currently utilized audio layer
@@ -145,6 +146,8 @@ class AudioDeviceModuleImpl : public AudioDeviceModuleForTest {
145146
int GetRecordAudioParameters(AudioParameters* params) const override;
146147
#endif // WEBRTC_IOS
147148

149+
int32_t SetAudioDeviceSink(AudioDeviceSink* sink) const override;
150+
148151
#if defined(WEBRTC_ANDROID)
149152
// Only use this acccessor for test purposes on Android.
150153
AudioManager* GetAndroidAudioManagerForTest() {
@@ -165,7 +168,9 @@ class AudioDeviceModuleImpl : public AudioDeviceModuleForTest {
165168
AudioLayer audio_layer_;
166169
PlatformType platform_type_ = kPlatformNotSupported;
167170
bool initialized_ = false;
168-
#if defined(WEBRTC_ANDROID)
171+
#if defined(WEBRTC_IOS)
172+
bool bypass_voice_processing_;
173+
#elif defined(WEBRTC_ANDROID)
169174
// Should be declared first to ensure that it outlives other resources.
170175
std::unique_ptr<AudioManager> audio_manager_android_;
171176
#endif

modules/audio_device/include/audio_device.h

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,15 @@ namespace webrtc {
2020

2121
class AudioDeviceModuleForTest;
2222

23+
// Sink for callbacks related to a audio device.
24+
class AudioDeviceSink {
25+
public:
26+
virtual ~AudioDeviceSink() = default;
27+
28+
// input/output devices updated or default device changed
29+
virtual void OnDevicesUpdated() {}
30+
};
31+
2332
class AudioDeviceModule : public rtc::RefCountInterface {
2433
public:
2534
enum AudioLayer {
@@ -45,12 +54,14 @@ class AudioDeviceModule : public rtc::RefCountInterface {
4554
// Creates a default ADM for usage in production code.
4655
static rtc::scoped_refptr<AudioDeviceModule> Create(
4756
AudioLayer audio_layer,
48-
TaskQueueFactory* task_queue_factory);
57+
TaskQueueFactory* task_queue_factory,
58+
bool bypass_voice_processing = false);
4959
// Creates an ADM with support for extra test methods. Don't use this factory
5060
// in production code.
5161
static rtc::scoped_refptr<AudioDeviceModuleForTest> CreateForTest(
5262
AudioLayer audio_layer,
53-
TaskQueueFactory* task_queue_factory);
63+
TaskQueueFactory* task_queue_factory,
64+
bool bypass_voice_processing = false);
5465

5566
// Retrieve the currently utilized audio layer
5667
virtual int32_t ActiveAudioLayer(AudioLayer* audioLayer) const = 0;
@@ -156,6 +167,8 @@ class AudioDeviceModule : public rtc::RefCountInterface {
156167
virtual int GetRecordAudioParameters(AudioParameters* params) const = 0;
157168
#endif // WEBRTC_IOS
158169

170+
virtual int32_t SetAudioDeviceSink(AudioDeviceSink* sink) const = 0;
171+
159172
protected:
160173
~AudioDeviceModule() override {}
161174
};

modules/audio_device/include/test_audio_device.cc

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,11 @@ class TestAudioDeviceModuleImpl
141141
return capturing_;
142142
}
143143

144+
int32_t SetAudioDeviceSink(AudioDeviceSink* sink) const override {
145+
// no-op
146+
return 0;
147+
}
148+
144149
// Blocks until the Renderer refuses to receive data.
145150
// Returns false if `timeout_ms` passes before that happens.
146151
bool WaitForPlayoutEnd(int timeout_ms = rtc::Event::kForever) override {

0 commit comments

Comments
 (0)