Diff
Modified: trunk/LayoutTests/ChangeLog (283804 => 283805)
--- trunk/LayoutTests/ChangeLog 2021-10-08 15:51:03 UTC (rev 283804)
+++ trunk/LayoutTests/ChangeLog 2021-10-08 16:05:25 UTC (rev 283805)
@@ -1,3 +1,13 @@
+2021-10-08 Youenn Fablet <[email protected]>
+
+ Move deviceChange handling from CoreAudioSharedUnit to BaseAudioSharedUnit
+ https://bugs.webkit.org/show_bug.cgi?id=231284
+
+ Reviewed by Eric Carlson.
+
+ * fast/mediastream/microphone-change-while-capturing-expected.txt: Added.
+ * fast/mediastream/microphone-change-while-capturing.html: Added.
+
2021-10-08 Ayumi Kojima <[email protected]>
[ iOS14 EWS ] http/tests/privateClickMeasurement/attribution-conversion-through-fetch-keepalive.html is a flaky crash.
Added: trunk/LayoutTests/fast/mediastream/microphone-change-while-capturing-expected.txt (0 => 283805)
--- trunk/LayoutTests/fast/mediastream/microphone-change-while-capturing-expected.txt (rev 0)
+++ trunk/LayoutTests/fast/mediastream/microphone-change-while-capturing-expected.txt 2021-10-08 16:05:25 UTC (rev 283805)
@@ -0,0 +1,5 @@
+
+
+PASS Detection of missing capturing device should trigger capture to fail
+PASS Adding or removing a new device should not fail ongoing capture
+
Added: trunk/LayoutTests/fast/mediastream/microphone-change-while-capturing.html (0 => 283805)
--- trunk/LayoutTests/fast/mediastream/microphone-change-while-capturing.html (rev 0)
+++ trunk/LayoutTests/fast/mediastream/microphone-change-while-capturing.html 2021-10-08 16:05:25 UTC (rev 283805)
@@ -0,0 +1,47 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Testing change of device while capturing.</title>
+ <script src=""
+ <script src=""
+</head>
+<body>
+ <video id="video"></video>
+ <script>
+ let setup = async (test) => {
+ if (!window.testRunner)
+ return Promise.reject("test requires internal API");
+
+ test.add_cleanup(() => { testRunner.resetMockMediaDevices(); });
+ }
+
+ promise_test(async (test) => {
+ await setup(test);
+
+ testRunner.addMockMicrophoneDevice("usbmic", "my USB microphone");
+ video.srcObject = await navigator.mediaDevices.getUserMedia({ audio: { deviceId: "usbmic" } });
+ await video.play();
+
+ testRunner.removeMockMediaDevice("usbmic");
+ return new Promise((resolve, reject) => {
+ video.srcObject.getAudioTracks()[0]._onended_ = resolve();
+ setTimeout(reject, 2000);
+ });
+ }, "Detection of missing capturing device should trigger capture to fail");
+
+ promise_test(async (test) => {
+ await setup(test);
+
+ testRunner.addMockMicrophoneDevice("usbmic1", "my USB microphone");
+ testRunner.addMockMicrophoneDevice("usbmic2", "my second USB microphone");
+ video.srcObject = await navigator.mediaDevices.getUserMedia({ audio: { deviceId: "usbmic1" } });
+ await video.play();
+ testRunner.removeMockMediaDevice("usbmic2");
+ testRunner.addMockMicrophoneDevice("usbmic3", "my third USB microphone");
+ await new Promise(resolve => setTimeout(resolve, 200));
+ assert_equals(video.srcObject.getAudioTracks()[0].readyState, "live");
+ }, "Adding or removing a new device should not fail ongoing capture");
+ </script>
+</body>
+</html>
Modified: trunk/Source/WebCore/ChangeLog (283804 => 283805)
--- trunk/Source/WebCore/ChangeLog 2021-10-08 15:51:03 UTC (rev 283804)
+++ trunk/Source/WebCore/ChangeLog 2021-10-08 16:05:25 UTC (rev 283805)
@@ -1,3 +1,35 @@
+2021-10-08 Youenn Fablet <[email protected]>
+
+ Move deviceChange handling from CoreAudioSharedUnit to BaseAudioSharedUnit
+ https://bugs.webkit.org/show_bug.cgi?id=231284
+
+ Reviewed by Eric Carlson.
+
+ Previously setting capture devices was done in CoreAudioSharedUnit and MockAudioSharedUnit.
+ Detection of missing devices was done in CoreAudioSharedUnit.
+ Move this code to BaseAudioSharedUnit and add a test based on mock to cover this code.
+
+ Test: fast/mediastream/microphone-change-while-capturing.html
+
+ * platform/mediastream/mac/BaseAudioSharedUnit.cpp:
+ (WebCore::BaseAudioSharedUnit::prepareForNewCapture):
+ (WebCore::BaseAudioSharedUnit::setCaptureDevice):
+ (WebCore::BaseAudioSharedUnit::devicesChanged):
+ (WebCore::BaseAudioSharedUnit::captureFailed):
+ * platform/mediastream/mac/BaseAudioSharedUnit.h:
+ (WebCore::BaseAudioSharedUnit::persistentID const):
+ (WebCore::BaseAudioSharedUnit::captureDeviceID const):
+ * platform/mediastream/mac/CoreAudioCaptureSource.cpp:
+ (WebCore::CoreAudioSharedUnit::captureDeviceChanged):
+ (WebCore::CoreAudioSharedUnit::setupAudioUnit):
+ (WebCore::CoreAudioSharedUnit::setCaptureDevice): Deleted.
+ (WebCore::CoreAudioSharedUnit::devicesChanged): Deleted.
+ * platform/mediastream/mac/MockAudioSharedUnit.h:
+ * platform/mediastream/mac/MockAudioSharedUnit.mm:
+ (WebCore::MockAudioSharedUnit::resetSampleRate):
+ (WebCore::MockAudioSharedUnit::captureDeviceChanged):
+ (WebCore::MockAudioSharedUnit::setCaptureDevice): Deleted.
+
2021-10-08 Antti Koivisto <[email protected]>
REGRESSION (r277818): XHR with requestType document broken for larger HTML files
Modified: trunk/Source/WebCore/platform/mediastream/mac/BaseAudioSharedUnit.cpp (283804 => 283805)
--- trunk/Source/WebCore/platform/mediastream/mac/BaseAudioSharedUnit.cpp 2021-10-08 15:51:03 UTC (rev 283804)
+++ trunk/Source/WebCore/platform/mediastream/mac/BaseAudioSharedUnit.cpp 2021-10-08 16:05:25 UTC (rev 283805)
@@ -128,13 +128,35 @@
if (!m_producingCount)
return;
- RELEASE_LOG_ERROR(WebRTC, "CoreAudioSharedUnit::prepareForNewCapture, notifying suspended sources of capture failure");
+ RELEASE_LOG_ERROR(WebRTC, "BaseAudioSharedUnit::prepareForNewCapture, notifying suspended sources of capture failure");
captureFailed();
}
+void BaseAudioSharedUnit::setCaptureDevice(String&& persistentID, uint32_t captureDeviceID)
+{
+ bool hasChanged = this->persistentID() != persistentID || this->captureDeviceID() != captureDeviceID;
+ m_capturingDevice = { WTFMove(persistentID), captureDeviceID };
+
+ if (hasChanged)
+ captureDeviceChanged();
+}
+
+void BaseAudioSharedUnit::devicesChanged(const Vector<CaptureDevice>& devices)
+{
+ if (!m_producingCount)
+ return;
+
+ auto persistentID = this->persistentID();
+ if (WTF::anyOf(devices, [&persistentID] (auto& device) { return persistentID == device.persistentId(); }))
+ return;
+
+ RELEASE_LOG_ERROR(WebRTC, "BaseAudioSharedUnit::devicesChanged - failing capture, capturing device is missing");
+ captureFailed();
+}
+
void BaseAudioSharedUnit::captureFailed()
{
- RELEASE_LOG_ERROR(WebRTC, "CoreAudioSharedUnit::captureFailed - capture failed");
+ RELEASE_LOG_ERROR(WebRTC, "BaseAudioSharedUnit::captureFailed");
forEachClient([](auto& client) {
client.captureFailed();
});
Modified: trunk/Source/WebCore/platform/mediastream/mac/BaseAudioSharedUnit.h (283804 => 283805)
--- trunk/Source/WebCore/platform/mediastream/mac/BaseAudioSharedUnit.h 2021-10-08 15:51:03 UTC (rev 283804)
+++ trunk/Source/WebCore/platform/mediastream/mac/BaseAudioSharedUnit.h 2021-10-08 16:05:25 UTC (rev 283805)
@@ -37,6 +37,7 @@
namespace WebCore {
class AudioStreamDescription;
+class CaptureDevice;
class CoreAudioCaptureSource;
class PlatformAudioData;
@@ -72,10 +73,12 @@
void clearClients();
virtual bool hasAudioUnit() const = 0;
- virtual void setCaptureDevice(String&&, uint32_t) = 0;
+ void setCaptureDevice(String&&, uint32_t);
virtual CapabilityValueOrRange sampleRateCapacities() const = 0;
+ void devicesChanged(const Vector<CaptureDevice>&);
+
protected:
void forEachClient(const Function<void(CoreAudioCaptureSource&)>&) const;
bool hasClients() const { return !m_clients.isEmpty(); }
@@ -86,11 +89,15 @@
virtual void stopInternal() = 0;
virtual OSStatus reconfigureAudioUnit() = 0;
virtual void resetSampleRate();
+ virtual void captureDeviceChanged() = 0;
void setSuspended(bool value) { m_suspended = value; }
void audioSamplesAvailable(const MediaTime&, const PlatformAudioData&, const AudioStreamDescription&, size_t /*numberOfFrames*/);
+ const String& persistentID() const { return m_capturingDevice ? m_capturingDevice->first : emptyString(); }
+ uint32_t captureDeviceID() const { return m_capturingDevice ? m_capturingDevice->second : 0; }
+
private:
OSStatus startUnit();
@@ -102,6 +109,8 @@
int32_t m_producingCount { 0 };
+ std::optional<std::pair<String, uint32_t>> m_capturingDevice;
+
HashSet<CoreAudioCaptureSource*> m_clients;
Vector<CoreAudioCaptureSource*> m_audioThreadClients WTF_GUARDED_BY_LOCK(m_audioThreadClientsLock);
Lock m_audioThreadClientsLock;
Modified: trunk/Source/WebCore/platform/mediastream/mac/CoreAudioCaptureSource.cpp (283804 => 283805)
--- trunk/Source/WebCore/platform/mediastream/mac/CoreAudioCaptureSource.cpp 2021-10-08 15:51:03 UTC (rev 283804)
+++ trunk/Source/WebCore/platform/mediastream/mac/CoreAudioCaptureSource.cpp 2021-10-08 16:05:25 UTC (rev 283805)
@@ -77,8 +77,6 @@
static BaseAudioSharedUnit& singleton() { return unit(); }
CoreAudioSharedUnit();
- void devicesChanged(const Vector<CaptureDevice>&);
-
private:
static size_t preferredIOBufferSize();
@@ -86,7 +84,7 @@
const CAAudioStreamDescription& microphoneFormat() const { return m_microphoneProcFormat; }
bool hasAudioUnit() const final { return m_ioUnit; }
- void setCaptureDevice(String&&, uint32_t) final;
+ void captureDeviceChanged() final;
OSStatus reconfigureAudioUnit() final;
OSStatus setupAudioUnit();
@@ -110,7 +108,6 @@
void unduck();
void verifyIsCapturing();
- void devicesChanged();
AudioUnit m_ioUnit { nullptr };
@@ -117,10 +114,6 @@
// Only read/modified from the IO thread.
Vector<Ref<AudioSampleDataSource>> m_activeSources;
-#if PLATFORM(MAC)
- uint32_t m_captureDeviceID { 0 };
-#endif
-
CAAudioStreamDescription m_microphoneProcFormat;
RefPtr<AudioSampleBufferList> m_microphoneSampleBuffer;
uint64_t m_latestMicTimeStamp { 0 };
@@ -143,8 +136,6 @@
uint64_t m_speakerProcsCalled { 0 };
#endif
- String m_persistentID;
-
uint64_t m_microphoneProcsCalled { 0 };
uint64_t m_microphoneProcsCalledLastTime { 0 };
Timer m_verifyCapturingTimer;
@@ -161,37 +152,15 @@
{
}
-void CoreAudioSharedUnit::setCaptureDevice(String&& persistentID, uint32_t captureDeviceID)
+void CoreAudioSharedUnit::captureDeviceChanged()
{
- if (m_persistentID == persistentID)
- return;
-
- m_persistentID = WTFMove(persistentID);
-
#if PLATFORM(MAC)
- if (m_captureDeviceID == captureDeviceID)
- return;
-
- m_captureDeviceID = captureDeviceID;
reconfigureAudioUnit();
#else
- UNUSED_PARAM(captureDeviceID);
- AVAudioSessionCaptureDeviceManager::singleton().setPreferredAudioSessionDeviceUID(m_persistentID);
+ AVAudioSessionCaptureDeviceManager::singleton().setPreferredAudioSessionDeviceUID(persistentID());
#endif
}
-void CoreAudioSharedUnit::devicesChanged(const Vector<CaptureDevice>& devices)
-{
- if (!m_ioUnit)
- return;
-
- if (WTF::anyOf(devices, [this] (auto& device) { return m_persistentID == device.persistentId(); }))
- return;
-
- RELEASE_LOG_ERROR(WebRTC, "CoreAudioSharedUnit::devicesChanged - failing capture");
- captureFailed();
-}
-
size_t CoreAudioSharedUnit::preferredIOBufferSize()
{
return AudioSession::sharedSession().bufferSize();
@@ -255,15 +224,16 @@
return err;
}
#else
- if (!m_captureDeviceID) {
- err = defaultInputDevice(&m_captureDeviceID);
+ auto deviceID = captureDeviceID();
+ if (!deviceID) {
+ err = defaultInputDevice(&deviceID);
if (err)
return err;
}
- err = PAL::AudioUnitSetProperty(m_ioUnit, kAudioOutputUnitProperty_CurrentDevice, kAudioUnitScope_Global, inputBus, &m_captureDeviceID, sizeof(m_captureDeviceID));
+ err = PAL::AudioUnitSetProperty(m_ioUnit, kAudioOutputUnitProperty_CurrentDevice, kAudioUnitScope_Global, inputBus, &deviceID, sizeof(deviceID));
if (err) {
- RELEASE_LOG_ERROR(WebRTC, "CoreAudioSharedUnit::setupAudioUnit(%p) unable to set vpio unit capture device ID %d, error %d (%.4s)", this, (int)m_captureDeviceID, (int)err, (char*)&err);
+ RELEASE_LOG_ERROR(WebRTC, "CoreAudioSharedUnit::setupAudioUnit(%p) unable to set vpio unit capture device ID %d, error %d (%.4s)", this, (int)deviceID, (int)err, (char*)&err);
return err;
}
#endif
Modified: trunk/Source/WebCore/platform/mediastream/mac/MockAudioSharedUnit.h (283804 => 283805)
--- trunk/Source/WebCore/platform/mediastream/mac/MockAudioSharedUnit.h 2021-10-08 15:51:03 UTC (rev 283804)
+++ trunk/Source/WebCore/platform/mediastream/mac/MockAudioSharedUnit.h 2021-10-08 16:05:25 UTC (rev 283805)
@@ -47,11 +47,11 @@
WEBCORE_EXPORT static MockAudioSharedUnit& singleton();
MockAudioSharedUnit();
- void setDeviceID(const String& deviceID) { m_deviceID = deviceID; }
+ void setDeviceID(const String& deviceID) { setCaptureDevice(String { deviceID }, 0); }
private:
bool hasAudioUnit() const final;
- void setCaptureDevice(String&&, uint32_t) final;
+ void captureDeviceChanged() final;
OSStatus reconfigureAudioUnit() final;
void resetSampleRate() final;
@@ -90,7 +90,6 @@
Ref<WorkQueue> m_workQueue;
unsigned m_channelCount { 2 };
- String m_deviceID;
};
} // namespace WebCore
Modified: trunk/Source/WebCore/platform/mediastream/mac/MockAudioSharedUnit.mm (283804 => 283805)
--- trunk/Source/WebCore/platform/mediastream/mac/MockAudioSharedUnit.mm 2021-10-08 15:51:03 UTC (rev 283804)
+++ trunk/Source/WebCore/platform/mediastream/mac/MockAudioSharedUnit.mm 2021-10-08 16:05:25 UTC (rev 283805)
@@ -108,7 +108,7 @@
void MockAudioSharedUnit::resetSampleRate()
{
- if (auto device = MockRealtimeMediaSourceCenter::mockDeviceWithPersistentID(m_deviceID))
+ if (auto device = MockRealtimeMediaSourceCenter::mockDeviceWithPersistentID(persistentID()))
setSampleRate(WTF::get<MockMicrophoneProperties>(device->properties).defaultSampleRate);
}
@@ -117,9 +117,8 @@
return m_hasAudioUnit;
}
-void MockAudioSharedUnit::setCaptureDevice(String&& deviceID, uint32_t)
+void MockAudioSharedUnit::captureDeviceChanged()
{
- m_deviceID = WTFMove(deviceID);
reconfigureAudioUnit();
}