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;