Title: [283805] trunk
Revision
283805
Author
[email protected]
Date
2021-10-08 09:05:25 -0700 (Fri, 08 Oct 2021)

Log Message

Move deviceChange handling from CoreAudioSharedUnit to BaseAudioSharedUnit
https://bugs.webkit.org/show_bug.cgi?id=231284

Reviewed by Eric Carlson.

Source/WebCore:

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.

LayoutTests:

* fast/mediastream/microphone-change-while-capturing-expected.txt: Added.
* fast/mediastream/microphone-change-while-capturing.html: Added.

Modified Paths

Added Paths

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();
 }
 
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to