Title: [294223] trunk/Source/WebCore
Revision
294223
Author
you...@apple.com
Date
2022-05-16 00:26:25 -0700 (Mon, 16 May 2022)

Log Message

MockAudioSharedInternalUnit should exit early when being stopped in generateSampleBuffers
https://bugs.webkit.org/show_bug.cgi?id=240421
<rdar://93279260>

Reviewed by Eric Carlson.

We used to always call generateSampleBuffers from main thread.
We are now calling it from background thread with dispatchAfter to mimick a realtime clock.
This broke the dispatchSync call we were calling when stopping the mock unit as the dispatchAfter task would be called
after the dispatchSync and |this| could potentially no longer be valid.
To prevent this, we introduce MockAudioSharedInternalUnitState which allows to safely know whether the unit is stopped or not
at any point in time. If the unit is stopped, dispatchAfter will not call generateSampleBuffers.

Covered by existing tests.

* platform/mediastream/mac/MockAudioSharedUnit.mm:
(WebCore::MockAudioSharedInternalUnitState::create):
(WebCore::MockAudioSharedInternalUnitState::isProducingData const):
(WebCore::MockAudioSharedInternalUnitState::setIsProducingData):
(WebCore::MockAudioSharedInternalUnit::MockAudioSharedInternalUnit):
(WebCore::MockAudioSharedInternalUnit::~MockAudioSharedInternalUnit):
(WebCore::MockAudioSharedInternalUnit::start):
(WebCore::MockAudioSharedInternalUnit::stop):
(WebCore::MockAudioSharedInternalUnit::uninitialize):
(WebCore::MockAudioSharedInternalUnit::generateSampleBuffers):

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (294222 => 294223)


--- trunk/Source/WebCore/ChangeLog	2022-05-16 07:14:59 UTC (rev 294222)
+++ trunk/Source/WebCore/ChangeLog	2022-05-16 07:26:25 UTC (rev 294223)
@@ -1,3 +1,31 @@
+2022-05-16  Youenn Fablet  <you...@apple.com>
+
+        MockAudioSharedInternalUnit should exit early when being stopped in generateSampleBuffers
+        https://bugs.webkit.org/show_bug.cgi?id=240421
+        <rdar://93279260>
+
+        Reviewed by Eric Carlson.
+
+        We used to always call generateSampleBuffers from main thread.
+        We are now calling it from background thread with dispatchAfter to mimick a realtime clock.
+        This broke the dispatchSync call we were calling when stopping the mock unit as the dispatchAfter task would be called
+        after the dispatchSync and |this| could potentially no longer be valid.
+        To prevent this, we introduce MockAudioSharedInternalUnitState which allows to safely know whether the unit is stopped or not
+        at any point in time. If the unit is stopped, dispatchAfter will not call generateSampleBuffers.
+
+        Covered by existing tests.
+
+        * platform/mediastream/mac/MockAudioSharedUnit.mm:
+        (WebCore::MockAudioSharedInternalUnitState::create):
+        (WebCore::MockAudioSharedInternalUnitState::isProducingData const):
+        (WebCore::MockAudioSharedInternalUnitState::setIsProducingData):
+        (WebCore::MockAudioSharedInternalUnit::MockAudioSharedInternalUnit):
+        (WebCore::MockAudioSharedInternalUnit::~MockAudioSharedInternalUnit):
+        (WebCore::MockAudioSharedInternalUnit::start):
+        (WebCore::MockAudioSharedInternalUnit::stop):
+        (WebCore::MockAudioSharedInternalUnit::uninitialize):
+        (WebCore::MockAudioSharedInternalUnit::generateSampleBuffers):
+
 2022-05-15  Youenn Fablet  <you...@apple.com>
 
         Audio playback rate sped up for few seconds when using createMediaElementSource

Modified: trunk/Source/WebCore/platform/mediastream/mac/MockAudioSharedUnit.mm (294222 => 294223)


--- trunk/Source/WebCore/platform/mediastream/mac/MockAudioSharedUnit.mm	2022-05-16 07:14:59 UTC (rev 294222)
+++ trunk/Source/WebCore/platform/mediastream/mac/MockAudioSharedUnit.mm	2022-05-16 07:26:25 UTC (rev 294223)
@@ -97,6 +97,17 @@
     return CoreAudioCaptureSource::createForTesting(WTFMove(deviceID), WTFMove(name), WTFMove(hashSalt), constraints, MockAudioSharedUnit::singleton(), pageIdentifier);
 }
 
+class MockAudioSharedInternalUnitState : public ThreadSafeRefCounted<MockAudioSharedInternalUnitState> {
+public:
+    static Ref<MockAudioSharedInternalUnitState> create() { return adoptRef(*new MockAudioSharedInternalUnitState()); }
+
+    bool isProducingData() const { return m_isProducingData; }
+    void setIsProducingData(bool value) { m_isProducingData = value; }
+
+private:
+    bool m_isProducingData { false };
+};
+
 class MockAudioSharedInternalUnit :  public CoreAudioSharedUnit::InternalUnit {
     WTF_MAKE_FAST_ALLOCATED;
 public:
@@ -105,7 +116,7 @@
 
 private:
     OSStatus initialize() final;
-    OSStatus uninitialize() final { return 0; }
+    OSStatus uninitialize() final;
     OSStatus start() final;
     OSStatus stop() final;
     OSStatus set(AudioUnitPropertyID, AudioUnitScope, AudioUnitElement, const void*, UInt32) final;
@@ -136,7 +147,7 @@
 
     Vector<float> m_bipBopBuffer;
     bool m_hasAudioUnit { false };
-    bool m_isProducingData { false };
+    Ref<MockAudioSharedInternalUnitState> m_isProducingState;
     bool m_enableEchoCancellation { true };
     RunLoop::Timer<MockAudioSharedInternalUnit> m_timer;
     MonotonicTime m_lastRenderTime { MonotonicTime::nan() };
@@ -177,7 +188,8 @@
 }
 
 MockAudioSharedInternalUnit::MockAudioSharedInternalUnit()
-    : m_timer(RunLoop::current(), [this] { this->start(); })
+    : m_isProducingState(MockAudioSharedInternalUnitState::create())
+    , m_timer(RunLoop::current(), [this] { this->start(); })
     , m_workQueue(WorkQueue::create("MockAudioSharedInternalUnit Capture Queue", WorkQueue::QOS::UserInteractive))
 {
     m_streamFormat = m_outputStreamFormat = createAudioFormat(44100, 2);
@@ -185,7 +197,7 @@
 
 MockAudioSharedInternalUnit::~MockAudioSharedInternalUnit()
 {
-    ASSERT(!m_isProducingData);
+    ASSERT(!m_isProducingState->isProducingData());
 }
 
 OSStatus MockAudioSharedInternalUnit::initialize()
@@ -203,7 +215,8 @@
         m_hasAudioUnit = true;
 
     m_lastRenderTime = MonotonicTime::now();
-    m_isProducingData = true;
+
+    m_isProducingState->setIsProducingData(true);
     m_workQueue->dispatch([this, renderTime = m_lastRenderTime] {
         generateSampleBuffers(renderTime);
     });
@@ -212,7 +225,7 @@
 
 OSStatus MockAudioSharedInternalUnit::stop()
 {
-    m_isProducingData = false;
+    m_isProducingState->setIsProducingData(false);
     if (m_hasAudioUnit)
         m_lastRenderTime = MonotonicTime::nan();
 
@@ -221,6 +234,12 @@
     return 0;
 }
 
+OSStatus MockAudioSharedInternalUnit::uninitialize()
+{
+    ASSERT(!m_isProducingState->isProducingData());
+    return 0;
+}
+
 void MockAudioSharedInternalUnit::delaySamples(Seconds delta)
 {
     stop();
@@ -283,10 +302,6 @@
 
 void MockAudioSharedInternalUnit::generateSampleBuffers(MonotonicTime renderTime)
 {
-    ASSERT(!isMainThread());
-    if (!m_isProducingData)
-        return;
-
     auto delta = renderInterval();
     auto currentTime = MonotonicTime::now();
     auto nextRenderTime = renderTime + delta;
@@ -295,8 +310,10 @@
         nextRenderTime = currentTime;
         nextRenderDelay = 0_s;
     }
-    m_workQueue->dispatchAfter(nextRenderDelay, [this, nextRenderTime] {
-        generateSampleBuffers(nextRenderTime);
+
+    m_workQueue->dispatchAfter(nextRenderDelay, [this, nextRenderTime, state = m_isProducingState] {
+        if (state->isProducingData())
+            generateSampleBuffers(nextRenderTime);
     });
 
     if (!m_audioBufferList || !m_bipBopBuffer.size())
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to