Title: [247211] trunk/Source/WebCore
Revision
247211
Author
[email protected]
Date
2019-07-08 10:46:27 -0700 (Mon, 08 Jul 2019)

Log Message

MediaStreamTrackPrivate should always call readyStateChanged on the main thread
https://bugs.webkit.org/show_bug.cgi?id=199538
<rdar://problem/52709106>

Reviewed by Eric Carlson.

MediaStreamTrackPrivate is sometimes calling readyStateChanged in a
background thread inside its audioSamplesAvailable method.
Instead of doing that, we hop to the main thread to call readyStateChanged.
Once the call is made in the main thread, MediaStreamTrackPrivate will
send the audio samples to its observers.

To make mock audio source closer to real capture audio sources,
audioSamplesAvailable is called on a background thread.
RealtimeMediaSource is updated to always be destroyed in the main
run loop since it is WebKit2 only.

Covered by existing tests and making sure the mock audio source calls
the audioSamplesAvailable method on a background thread.

* platform/mediastream/MediaStreamTrackPrivate.cpp:
(WebCore::MediaStreamTrackPrivate::videoSampleAvailable):
(WebCore::MediaStreamTrackPrivate::audioSamplesAvailable):
* platform/mediastream/MediaStreamTrackPrivate.h:
* platform/mediastream/RealtimeMediaSource.cpp:
(WebCore::RealtimeMediaSource::scheduleDeferredTask):
scheduleDeferredTask may be called from a background thread.
It is thus safer to ref the source instead of creating a weak pointer.
* platform/mediastream/RealtimeMediaSource.h:
* platform/mediastream/mac/MockRealtimeAudioSourceMac.mm:
(WebCore::MockRealtimeAudioSourceMac::MockRealtimeAudioSourceMac):
(WebCore::MockRealtimeAudioSourceMac::emitSampleBuffers):
(WebCore::MockRealtimeAudioSourceMac::reconfigure):
(WebCore::MockRealtimeAudioSourceMac::render):
(WebCore::MockRealtimeAudioSourceMac::settingsDidChange):
* platform/mock/MockRealtimeAudioSource.cpp:
(WebCore::MockRealtimeAudioSource::MockRealtimeAudioSource):
(WebCore::MockRealtimeAudioSource::tick):
* platform/mock/MockRealtimeAudioSource.h:

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (247210 => 247211)


--- trunk/Source/WebCore/ChangeLog	2019-07-08 16:51:28 UTC (rev 247210)
+++ trunk/Source/WebCore/ChangeLog	2019-07-08 17:46:27 UTC (rev 247211)
@@ -1,5 +1,47 @@
 2019-07-08  Youenn Fablet  <[email protected]>
 
+        MediaStreamTrackPrivate should always call readyStateChanged on the main thread
+        https://bugs.webkit.org/show_bug.cgi?id=199538
+        <rdar://problem/52709106>
+
+        Reviewed by Eric Carlson.
+
+        MediaStreamTrackPrivate is sometimes calling readyStateChanged in a
+        background thread inside its audioSamplesAvailable method.
+        Instead of doing that, we hop to the main thread to call readyStateChanged.
+        Once the call is made in the main thread, MediaStreamTrackPrivate will
+        send the audio samples to its observers.
+
+        To make mock audio source closer to real capture audio sources,
+        audioSamplesAvailable is called on a background thread.
+        RealtimeMediaSource is updated to always be destroyed in the main
+        run loop since it is WebKit2 only.
+
+        Covered by existing tests and making sure the mock audio source calls
+        the audioSamplesAvailable method on a background thread.
+
+        * platform/mediastream/MediaStreamTrackPrivate.cpp:
+        (WebCore::MediaStreamTrackPrivate::videoSampleAvailable):
+        (WebCore::MediaStreamTrackPrivate::audioSamplesAvailable):
+        * platform/mediastream/MediaStreamTrackPrivate.h:
+        * platform/mediastream/RealtimeMediaSource.cpp:
+        (WebCore::RealtimeMediaSource::scheduleDeferredTask):
+        scheduleDeferredTask may be called from a background thread.
+        It is thus safer to ref the source instead of creating a weak pointer.
+        * platform/mediastream/RealtimeMediaSource.h:
+        * platform/mediastream/mac/MockRealtimeAudioSourceMac.mm:
+        (WebCore::MockRealtimeAudioSourceMac::MockRealtimeAudioSourceMac):
+        (WebCore::MockRealtimeAudioSourceMac::emitSampleBuffers):
+        (WebCore::MockRealtimeAudioSourceMac::reconfigure):
+        (WebCore::MockRealtimeAudioSourceMac::render):
+        (WebCore::MockRealtimeAudioSourceMac::settingsDidChange):
+        * platform/mock/MockRealtimeAudioSource.cpp:
+        (WebCore::MockRealtimeAudioSource::MockRealtimeAudioSource):
+        (WebCore::MockRealtimeAudioSource::tick):
+        * platform/mock/MockRealtimeAudioSource.h:
+
+2019-07-08  Youenn Fablet  <[email protected]>
+
         Register a MediaStreamTrack as media producer only if it is a capture track
         https://bugs.webkit.org/show_bug.cgi?id=199566
 

Modified: trunk/Source/WebCore/platform/mediastream/MediaStreamTrackPrivate.cpp (247210 => 247211)


--- trunk/Source/WebCore/platform/mediastream/MediaStreamTrackPrivate.cpp	2019-07-08 16:51:28 UTC (rev 247210)
+++ trunk/Source/WebCore/platform/mediastream/MediaStreamTrackPrivate.cpp	2019-07-08 17:46:27 UTC (rev 247211)
@@ -242,6 +242,7 @@
 
 void MediaStreamTrackPrivate::videoSampleAvailable(MediaSample& mediaSample)
 {
+    ASSERT(isMainThread());
     if (!m_haveProducedData) {
         m_haveProducedData = true;
         updateReadyState();
@@ -259,9 +260,15 @@
 // May get called on a background thread.
 void MediaStreamTrackPrivate::audioSamplesAvailable(const MediaTime& mediaTime, const PlatformAudioData& data, const AudioStreamDescription& description, size_t sampleCount)
 {
-    if (!m_haveProducedData) {
-        m_haveProducedData = true;
-        updateReadyState();
+    if (!m_hasSentStartProducedData) {
+        callOnMainThread([this, protectedThis = makeRef(*this)] {
+            if (!m_haveProducedData) {
+                m_haveProducedData = true;
+                updateReadyState();
+            }
+            m_hasSentStartProducedData = true;
+        });
+        return;
     }
 
     forEachObserver([&](auto& observer) {
@@ -269,7 +276,6 @@
     });
 }
 
-
 void MediaStreamTrackPrivate::updateReadyState()
 {
     ReadyState state = ReadyState::None;

Modified: trunk/Source/WebCore/platform/mediastream/MediaStreamTrackPrivate.h (247210 => 247211)


--- trunk/Source/WebCore/platform/mediastream/MediaStreamTrackPrivate.h	2019-07-08 16:51:28 UTC (rev 247210)
+++ trunk/Source/WebCore/platform/mediastream/MediaStreamTrackPrivate.h	2019-07-08 17:46:27 UTC (rev 247211)
@@ -41,7 +41,7 @@
 class WebAudioSourceProvider;
 
 class MediaStreamTrackPrivate final
-    : public RefCounted<MediaStreamTrackPrivate>
+    : public ThreadSafeRefCounted<MediaStreamTrackPrivate, WTF::DestructionThread::Main>
     , public RealtimeMediaSource::Observer
 #if !RELEASE_LOG_DISABLED
     , private LoggerHelper
@@ -151,6 +151,7 @@
     bool m_isEnabled { true };
     bool m_isEnded { false };
     bool m_haveProducedData { false };
+    bool m_hasSentStartProducedData { false };
     HintValue m_contentHint { HintValue::Empty };
     RefPtr<WebAudioSourceProvider> m_audioSourceProvider;
     Ref<const Logger> m_logger;

Modified: trunk/Source/WebCore/platform/mediastream/RealtimeMediaSource.cpp (247210 => 247211)


--- trunk/Source/WebCore/platform/mediastream/RealtimeMediaSource.cpp	2019-07-08 16:51:28 UTC (rev 247210)
+++ trunk/Source/WebCore/platform/mediastream/RealtimeMediaSource.cpp	2019-07-08 17:46:27 UTC (rev 247211)
@@ -1035,13 +1035,10 @@
     notifySettingsDidChangeObservers(RealtimeMediaSourceSettings::Flag::EchoCancellation);
 }
 
-void RealtimeMediaSource::scheduleDeferredTask(WTF::Function<void()>&& function)
+void RealtimeMediaSource::scheduleDeferredTask(Function<void()>&& function)
 {
     ASSERT(function);
-    callOnMainThread([weakThis = makeWeakPtr(*this), function = WTFMove(function)] {
-        if (!weakThis)
-            return;
-
+    callOnMainThread([protectedThis = makeRef(*this), function = WTFMove(function)] {
         function();
     });
 }

Modified: trunk/Source/WebCore/platform/mediastream/RealtimeMediaSource.h (247210 => 247211)


--- trunk/Source/WebCore/platform/mediastream/RealtimeMediaSource.h	2019-07-08 16:51:28 UTC (rev 247210)
+++ trunk/Source/WebCore/platform/mediastream/RealtimeMediaSource.h	2019-07-08 17:46:27 UTC (rev 247211)
@@ -67,7 +67,7 @@
 struct CaptureSourceOrError;
 
 class WEBCORE_EXPORT RealtimeMediaSource
-    : public ThreadSafeRefCounted<RealtimeMediaSource>
+    : public ThreadSafeRefCounted<RealtimeMediaSource, WTF::DestructionThread::MainRunLoop>
     , public CanMakeWeakPtr<RealtimeMediaSource>
 #if !RELEASE_LOG_DISABLED
     , private LoggerHelper

Modified: trunk/Source/WebCore/platform/mediastream/mac/MockRealtimeAudioSourceMac.mm (247210 => 247211)


--- trunk/Source/WebCore/platform/mediastream/mac/MockRealtimeAudioSourceMac.mm	2019-07-08 16:51:28 UTC (rev 247210)
+++ trunk/Source/WebCore/platform/mediastream/mac/MockRealtimeAudioSourceMac.mm	2019-07-08 17:46:27 UTC (rev 247211)
@@ -106,10 +106,12 @@
 MockRealtimeAudioSourceMac::MockRealtimeAudioSourceMac(String&& deviceID, String&& name, String&& hashSalt)
     : MockRealtimeAudioSource(WTFMove(deviceID), WTFMove(name), WTFMove(hashSalt))
 {
+    ASSERT(isMainThread());
 }
 
 void MockRealtimeAudioSourceMac::emitSampleBuffers(uint32_t frameCount)
 {
+    ASSERT(!isMainThread());
     ASSERT(m_formatDescription);
 
     CMTime startTime = CMTimeMake(m_samplesEmitted, sampleRate());
@@ -120,6 +122,7 @@
 
 void MockRealtimeAudioSourceMac::reconfigure()
 {
+    ASSERT(!isMainThread());
     m_maximiumFrameCount = WTF::roundUpToPowerOfTwo(renderInterval().seconds() * sampleRate() * 2);
     ASSERT(m_maximiumFrameCount);
 
@@ -140,6 +143,7 @@
 
 void MockRealtimeAudioSourceMac::render(Seconds delta)
 {
+    ASSERT(!isMainThread());
     if (!m_audioBufferList)
         reconfigure();
 
@@ -168,21 +172,23 @@
 void MockRealtimeAudioSourceMac::settingsDidChange(OptionSet<RealtimeMediaSourceSettings::Flag> settings)
 {
     if (settings.contains(RealtimeMediaSourceSettings::Flag::SampleRate)) {
-        m_formatDescription = nullptr;
-        m_audioBufferList = nullptr;
+        m_workQueue->dispatch([this, protectedThis = makeRef(*this)] {
+            m_formatDescription = nullptr;
+            m_audioBufferList = nullptr;
 
-        auto rate = sampleRate();
-        size_t sampleCount = 2 * rate;
+            auto rate = sampleRate();
+            size_t sampleCount = 2 * rate;
 
-        m_bipBopBuffer.grow(sampleCount);
-        m_bipBopBuffer.fill(0);
+            m_bipBopBuffer.grow(sampleCount);
+            m_bipBopBuffer.fill(0);
 
-        size_t bipBopSampleCount = ceil(BipBopDuration * rate);
-        size_t bipStart = 0;
-        size_t bopStart = rate;
+            size_t bipBopSampleCount = ceil(BipBopDuration * rate);
+            size_t bipStart = 0;
+            size_t bopStart = rate;
 
-        addHum(BipBopVolume, BipFrequency, rate, 0, m_bipBopBuffer.data() + bipStart, bipBopSampleCount);
-        addHum(BipBopVolume, BopFrequency, rate, 0, m_bipBopBuffer.data() + bopStart, bipBopSampleCount);
+            addHum(BipBopVolume, BipFrequency, rate, 0, m_bipBopBuffer.data() + bipStart, bipBopSampleCount);
+            addHum(BipBopVolume, BopFrequency, rate, 0, m_bipBopBuffer.data() + bopStart, bipBopSampleCount);
+        });
     }
 
     MockRealtimeAudioSource::settingsDidChange(settings);

Modified: trunk/Source/WebCore/platform/mock/MockRealtimeAudioSource.cpp (247210 => 247211)


--- trunk/Source/WebCore/platform/mock/MockRealtimeAudioSource.cpp	2019-07-08 16:51:28 UTC (rev 247210)
+++ trunk/Source/WebCore/platform/mock/MockRealtimeAudioSource.cpp	2019-07-08 17:46:27 UTC (rev 247211)
@@ -62,6 +62,7 @@
 
 MockRealtimeAudioSource::MockRealtimeAudioSource(String&& deviceID, String&& name, String&& hashSalt)
     : RealtimeMediaSource(RealtimeMediaSource::Type::Audio, WTFMove(name), WTFMove(deviceID), WTFMove(hashSalt))
+    , m_workQueue(WorkQueue::create("MockRealtimeAudioSource Render Queue"))
     , m_timer(RunLoop::current(), this, &MockRealtimeAudioSource::tick)
 {
     auto device = MockRealtimeMediaSourceCenter::mockDeviceWithPersistentID(persistentID());
@@ -151,7 +152,10 @@
 
     Seconds delta = now - m_lastRenderTime;
     m_lastRenderTime = now;
-    render(delta);
+
+    m_workQueue->dispatch([this, delta, protectedThis = makeRef(*this)] {
+        render(delta);
+    });
 }
 
 void MockRealtimeAudioSource::delaySamples(Seconds delta)

Modified: trunk/Source/WebCore/platform/mock/MockRealtimeAudioSource.h (247210 => 247211)


--- trunk/Source/WebCore/platform/mock/MockRealtimeAudioSource.h	2019-07-08 16:51:28 UTC (rev 247210)
+++ trunk/Source/WebCore/platform/mock/MockRealtimeAudioSource.h	2019-07-08 17:46:27 UTC (rev 247211)
@@ -36,23 +36,19 @@
 #include "MockMediaDevice.h"
 #include "RealtimeMediaSourceFactory.h"
 #include <wtf/RunLoop.h>
+#include <wtf/WorkQueue.h>
 
 namespace WebCore {
 
 class MockRealtimeAudioSource : public RealtimeMediaSource {
 public:
-
     static CaptureSourceOrError create(String&& deviceID, String&& name, String&& hashSalt, const MediaConstraints*);
-
     virtual ~MockRealtimeAudioSource();
 
 protected:
     MockRealtimeAudioSource(String&& deviceID, String&& name, String&& hashSalt);
 
-    void startProducingData() final;
-    void stopProducingData() final;
-
-    virtual void render(Seconds) { }
+    virtual void render(Seconds) = 0;
     void settingsDidChange(OptionSet<RealtimeMediaSourceSettings::Flag>) override;
 
     static Seconds renderInterval() { return 60_ms; }
@@ -61,7 +57,8 @@
     const RealtimeMediaSourceCapabilities& capabilities() final;
     const RealtimeMediaSourceSettings& settings() final;
 
-    void tick();
+    void startProducingData() final;
+    void stopProducingData() final;
 
     bool isCaptureSource() const final { return true; }
     CaptureDevice::DeviceType deviceType() const final { return CaptureDevice::DeviceType::Microphone; }
@@ -68,6 +65,12 @@
 
     void delaySamples(Seconds) final;
 
+    void tick();
+
+protected:
+    Ref<WorkQueue> m_workQueue;
+
+private:
     Optional<RealtimeMediaSourceCapabilities> m_capabilities;
     Optional<RealtimeMediaSourceSettings> m_currentSettings;
     RealtimeMediaSourceSupportedConstraints m_supportedConstraints;
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to