Skip to content

Commit

Permalink
AirPods removed from ears should not disturb and ongoing video call
Browse files Browse the repository at this point in the history
https://bugs.webkit.org/show_bug.cgi?id=264334
rdar://116091083

Reviewed by Eric Carlson.

When AirPods are removed from ears, AirPods are disappearing from the list of existing devices.
Before the patch, it would trigger capture failure. But web pages do not handle well capture failure.
To help web pages, if capturing with the default microphone and the microphone is disappearing, we are now
migrating to the new default microphone.
We make sure to trigger a configurationchange event on the MediaStreamTrack, which exposes the change to the web page.

* Source/WebCore/platform/mediastream/mac/BaseAudioSharedUnit.cpp:
(WebCore::BaseAudioSharedUnit::setCaptureDevice):
(WebCore::BaseAudioSharedUnit::devicesChanged):
* Source/WebCore/platform/mediastream/mac/BaseAudioSharedUnit.h:
(WebCore::BaseAudioSharedUnit::migrateToNewDefaultDevice):
* Source/WebCore/platform/mediastream/mac/CoreAudioSharedUnit.cpp:
(WebCore::CoreAudioSharedUnit::migrateToNewDefaultDevice):
* Source/WebCore/platform/mediastream/mac/CoreAudioSharedUnit.h:

Canonical link: https://commits.webkit.org/270433@main
  • Loading branch information
youennf committed Nov 9, 2023
1 parent 7d0464c commit 71ef02a
Show file tree
Hide file tree
Showing 4 changed files with 34 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,9 @@ void BaseAudioSharedUnit::setCaptureDevice(String&& persistentID, uint32_t captu
bool hasChanged = this->persistentID() != persistentID || this->captureDeviceID() != captureDeviceID;
m_capturingDevice = { WTFMove(persistentID), captureDeviceID };

auto devices = RealtimeMediaSourceCenter::singleton().audioCaptureFactory().audioCaptureDeviceManager().captureDevices();
m_isCapturingWithDefaultMicrophone = devices.size() && devices[0].persistentId() == m_capturingDevice->first;

if (hasChanged)
captureDeviceChanged();
}
Expand All @@ -174,6 +177,11 @@ void BaseAudioSharedUnit::devicesChanged()
return;
}

if (devices.size() && m_isCapturingWithDefaultMicrophone && migrateToNewDefaultDevice(devices[0])) {
RELEASE_LOG_ERROR(WebRTC, "BaseAudioSharedUnit::devicesChanged - migrating to new default device");
return;
}

RELEASE_LOG_ERROR(WebRTC, "BaseAudioSharedUnit::devicesChanged - failing capture, capturing device is missing");
captureFailed();
}
Expand Down
2 changes: 2 additions & 0 deletions Source/WebCore/platform/mediastream/mac/BaseAudioSharedUnit.h
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ class BaseAudioSharedUnit : public RealtimeMediaSourceCenter::Observer {

virtual void isProducingMicrophoneSamplesChanged() { }
virtual void validateOutputDevice(uint32_t /* currentOutputDeviceID */) { }
virtual bool migrateToNewDefaultDevice(const CaptureDevice&) { return false; }

private:
OSStatus startUnit();
Expand All @@ -140,6 +141,7 @@ class BaseAudioSharedUnit : public RealtimeMediaSourceCenter::Observer {
Vector<CheckedPtr<CoreAudioCaptureSource>> m_audioThreadClients WTF_GUARDED_BY_LOCK(m_audioThreadClientsLock);
Lock m_audioThreadClientsLock;

bool m_isCapturingWithDefaultMicrophone { false };
bool m_isProducingMicrophoneSamples { true };
Vector<Function<void()>> m_whenNotRunningCallbacks;
};
Expand Down
21 changes: 21 additions & 0 deletions Source/WebCore/platform/mediastream/mac/CoreAudioSharedUnit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,11 @@
#include "MediaCaptureStatusBarManager.h"
#endif

#if PLATFORM(MAC)
#include "CoreAudioCaptureDevice.h"
#include "CoreAudioCaptureDeviceManager.h"
#endif

#include <pal/cf/AudioToolboxSoftLink.h>
#include <pal/cf/CoreMediaSoftLink.h>

Expand Down Expand Up @@ -663,6 +668,22 @@ void CoreAudioSharedUnit::validateOutputDevice(uint32_t currentOutputDeviceID)
#endif
}

#if PLATFORM(MAC)
bool CoreAudioSharedUnit::migrateToNewDefaultDevice(const CaptureDevice& captureDevice)
{
auto newDefaultDevicePersistentId = captureDevice.persistentId();
auto device = CoreAudioCaptureDeviceManager::singleton().coreAudioDeviceWithUID(newDefaultDevicePersistentId);
if (!device)
return false;

// We were capturing with the default device which disappeared, let's move capture to the new default device.
setCaptureDevice(WTFMove(newDefaultDevicePersistentId), device->deviceID());
handleNewCurrentMicrophoneDevice(WTFMove(*device));
return true;
}
#endif


void CoreAudioSharedUnit::verifyIsCapturing()
{
if (m_microphoneProcsCalledLastTime != m_microphoneProcsCalled) {
Expand Down
3 changes: 3 additions & 0 deletions Source/WebCore/platform/mediastream/mac/CoreAudioSharedUnit.h
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,9 @@ class CoreAudioSharedUnit final : public BaseAudioSharedUnit {
bool isProducingData() const final { return m_ioUnitStarted; }
void isProducingMicrophoneSamplesChanged() final;
void validateOutputDevice(uint32_t deviceID) final;
#if PLATFORM(MAC)
bool migrateToNewDefaultDevice(const CaptureDevice&) final;
#endif
int actualSampleRate() const final;
void resetSampleRate();

Expand Down

0 comments on commit 71ef02a

Please sign in to comment.