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())