Title: [259816] trunk/Source
Revision
259816
Author
you...@apple.com
Date
2020-04-09 12:44:21 -0700 (Thu, 09 Apr 2020)

Log Message

Introduce a RealtimeMediaSource observer dedicated to receiving audio samples
https://bugs.webkit.org/show_bug.cgi?id=210180

Reviewed by Eric Carlson.

Source/WebCore:

RealtimeMediaSource::Observer was called on various threads which was making iterating through them difficult.
Observers were copied to a vector for iterating each time and locking was happening for each indivudual observer.

Instead of doing that, RealtimeMediaSource::Observer no longer gives access to audio samples, all its methods are called from the main thread.
AudioSampleObserver is introduced with a single method to receive audio samples.
RealtimeMediaSource keeps a set of AudioSampleObserver separated from its existing Observer hashset.
These observers can only be added/removed from the main thread while audio sample delivery usually happens from a background thread.
We no longer need to copy the audio sample observers in a vector and lock only once when iterating the audio sample observers.

This change requires to update MediaStreamTrackPrivate and RealtimeMediaSource observers.
This includes WebAudio, Audio Renderer and Media Recorder.
Each corresponding class is now registering itself as a MediaStreamTrackPrivate::Observer and when needed as a RealtimeMediaSource::Observer.
This allows removing the additional copy-in-vector/lock that was happening when iterating over MediaStreamTrackPrivate::Observers for audio samples.

This change also allows for a consumer to always observe the MediaStreamTrackPrivate but receive audio samples only when needed.
We change the AudioTrackPrivateMediaStream implementation so that, if the renderer is muted, not playing, the track is muted or not enabled,
it no longer receives audio samples.
This is especially useful in the typical case where a video element displays the locally captured stream (including a local audio track) but is muted
to prevent feedback loop.
For that reason, the player is now setting the muted state of the renderer instead of setting volume to 0.

Covered by existing test sets.

* Modules/mediarecorder/MediaRecorder.cpp:
(WebCore::MediaRecorder::createMediaRecorderPrivate):
* Modules/mediarecorder/MediaRecorder.h:
* Modules/mediarecorder/MediaRecorderProvider.cpp:
(WebCore::MediaRecorderProvider::createMediaRecorderPrivate):
* Modules/mediarecorder/MediaRecorderProvider.h:
* loader/EmptyClients.cpp:
* platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaStreamAVFObjC.mm:
(WebCore::MediaPlayerPrivateMediaStreamAVFObjC::setVolume):
(WebCore::MediaPlayerPrivateMediaStreamAVFObjC::setMuted):
* platform/mediarecorder/MediaRecorderPrivate.cpp:
(WebCore::MediaRecorderPrivate::selectTracks):
* platform/mediarecorder/MediaRecorderPrivate.h:
(WebCore::MediaRecorderPrivate::setAudioSource):
(WebCore::MediaRecorderPrivate::~MediaRecorderPrivate):
* platform/mediarecorder/MediaRecorderPrivateAVFImpl.cpp:
(WebCore::MediaRecorderPrivateAVFImpl::create):
(WebCore::MediaRecorderPrivateAVFImpl::~MediaRecorderPrivateAVFImpl):
(WebCore::MediaRecorderPrivateAVFImpl::audioSamplesAvailable):
(WebCore::MediaRecorderPrivateAVFImpl::stopRecording):
(WebCore::MediaRecorderPrivateAVFImpl::fetchData):
* platform/mediarecorder/MediaRecorderPrivateAVFImpl.h:
* platform/mediarecorder/MediaRecorderPrivateMock.cpp:
(WebCore::MediaRecorderPrivateMock::MediaRecorderPrivateMock):
(WebCore::MediaRecorderPrivateMock::~MediaRecorderPrivateMock):
(WebCore::MediaRecorderPrivateMock::stopRecording):
(WebCore::MediaRecorderPrivateMock::sampleBufferUpdated):
(WebCore::MediaRecorderPrivateMock::audioSamplesAvailable):
(WebCore::MediaRecorderPrivateMock::generateMockCounterString):
(WebCore::MediaRecorderPrivateMock::fetchData):
* platform/mediarecorder/MediaRecorderPrivateMock.h:
* platform/mediastream/AudioTrackPrivateMediaStream.cpp:
(WebCore::AudioTrackPrivateMediaStream::AudioTrackPrivateMediaStream):
(WebCore::AudioTrackPrivateMediaStream::clear):
(WebCore::AudioTrackPrivateMediaStream::play):
(WebCore::AudioTrackPrivateMediaStream::pause):
(WebCore::AudioTrackPrivateMediaStream::setMuted):
(WebCore::AudioTrackPrivateMediaStream::audioSamplesAvailable):
(WebCore::AudioTrackPrivateMediaStream::trackMutedChanged):
(WebCore::AudioTrackPrivateMediaStream::trackEnabledChanged):
(WebCore::AudioTrackPrivateMediaStream::trackEnded):
(WebCore::AudioTrackPrivateMediaStream::updateRenderer):
(WebCore::AudioTrackPrivateMediaStream::startRenderer):
(WebCore::AudioTrackPrivateMediaStream::stopRenderer):
* platform/mediastream/AudioTrackPrivateMediaStream.h:
* platform/mediastream/gstreamer/GStreamerMediaStreamSource.cpp:
(WebCore::webkitMediaStreamSrcFinalize):
(WebCore::webkitMediaStreamSrcChangeState):
(WebCore::webkitMediaStreamSrcSetupSrc):
* platform/mediastream/MediaStreamPrivate.cpp:
(WebCore::MediaStreamPrivate::forEachTrack):
* platform/mediastream/MediaStreamPrivate.h:
* platform/mediastream/MediaStreamTrackPrivate.cpp:
(WebCore::MediaStreamTrackPrivate::forEachObserver const):
(WebCore::MediaStreamTrackPrivate::addObserver):
(WebCore::MediaStreamTrackPrivate::removeObserver):
(WebCore::MediaStreamTrackPrivate::hasStartedProducingAudioData):
* platform/mediastream/MediaStreamTrackPrivate.h:
* platform/mediastream/RealtimeMediaSource.cpp:
(WebCore::RealtimeMediaSource::addAudioSampleObserver):
(WebCore::RealtimeMediaSource::removeAudioSampleObserver):
(WebCore::RealtimeMediaSource::addObserver):
(WebCore::RealtimeMediaSource::removeObserver):
(WebCore::RealtimeMediaSource::forEachObserver const):
(WebCore::RealtimeMediaSource::audioSamplesAvailable):
* platform/mediastream/RealtimeMediaSource.h:
* platform/mediastream/RealtimeOutgoingAudioSource.cpp:
(WebCore::RealtimeOutgoingAudioSource::~RealtimeOutgoingAudioSource):
(WebCore::RealtimeOutgoingAudioSource::observeSource):
(WebCore::RealtimeOutgoingAudioSource::unobserveSource):
* platform/mediastream/RealtimeOutgoingAudioSource.h:
* platform/mediastream/WebAudioSourceProvider.h:
* platform/mediastream/mac/WebAudioSourceProviderAVFObjC.h:
* platform/mediastream/mac/WebAudioSourceProviderAVFObjC.mm:
(WebCore::WebAudioSourceProviderAVFObjC::WebAudioSourceProviderAVFObjC):
(WebCore::WebAudioSourceProviderAVFObjC::~WebAudioSourceProviderAVFObjC):
(WebCore::WebAudioSourceProviderAVFObjC::trackEnabledChanged):
(WebCore::WebAudioSourceProviderAVFObjC::audioSamplesAvailable):
* testing/Internals.cpp:
(WebCore::Internals::~Internals):
(WebCore::createRecorderMockSource):
(WebCore::Internals::observeMediaStreamTrack):
(WebCore::Internals::videoSampleAvailable):
* testing/Internals.h:

Source/WebKit:

Update SourceProxy to be an AudioSampleObserver.
Update MediaRecorder to only listen for audio samples if GPU remote writer is successfully created.
It also stops listening to audio samples as soon as stopping the recording.

* UIProcess/Cocoa/UserMediaCaptureManagerProxy.cpp:
(WebKit::UserMediaCaptureManagerProxy::SourceProxy::SourceProxy):
(WebKit::UserMediaCaptureManagerProxy::SourceProxy::~SourceProxy):
* WebProcess/GPU/webrtc/MediaRecorderPrivate.cpp:
(WebKit::MediaRecorderPrivate::MediaRecorderPrivate):
(WebKit::MediaRecorderPrivate::~MediaRecorderPrivate):
(WebKit::MediaRecorderPrivate::audioSamplesAvailable):
(WebKit::MediaRecorderPrivate::stopRecording):
* WebProcess/GPU/webrtc/MediaRecorderPrivate.h:
* WebProcess/GPU/webrtc/MediaRecorderProvider.cpp:
(WebKit::MediaRecorderProvider::createMediaRecorderPrivate):
* WebProcess/GPU/webrtc/MediaRecorderProvider.h:

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (259815 => 259816)


--- trunk/Source/WebCore/ChangeLog	2020-04-09 19:42:02 UTC (rev 259815)
+++ trunk/Source/WebCore/ChangeLog	2020-04-09 19:44:21 UTC (rev 259816)
@@ -1,3 +1,118 @@
+2020-04-09  Youenn Fablet  <you...@apple.com>
+
+        Introduce a RealtimeMediaSource observer dedicated to receiving audio samples
+        https://bugs.webkit.org/show_bug.cgi?id=210180
+
+        Reviewed by Eric Carlson.
+
+        RealtimeMediaSource::Observer was called on various threads which was making iterating through them difficult.
+        Observers were copied to a vector for iterating each time and locking was happening for each indivudual observer.
+
+        Instead of doing that, RealtimeMediaSource::Observer no longer gives access to audio samples, all its methods are called from the main thread.
+        AudioSampleObserver is introduced with a single method to receive audio samples.
+        RealtimeMediaSource keeps a set of AudioSampleObserver separated from its existing Observer hashset.
+        These observers can only be added/removed from the main thread while audio sample delivery usually happens from a background thread.
+        We no longer need to copy the audio sample observers in a vector and lock only once when iterating the audio sample observers.
+
+        This change requires to update MediaStreamTrackPrivate and RealtimeMediaSource observers.
+        This includes WebAudio, Audio Renderer and Media Recorder.
+        Each corresponding class is now registering itself as a MediaStreamTrackPrivate::Observer and when needed as a RealtimeMediaSource::Observer.
+        This allows removing the additional copy-in-vector/lock that was happening when iterating over MediaStreamTrackPrivate::Observers for audio samples.
+
+        This change also allows for a consumer to always observe the MediaStreamTrackPrivate but receive audio samples only when needed.
+        We change the AudioTrackPrivateMediaStream implementation so that, if the renderer is muted, not playing, the track is muted or not enabled,
+        it no longer receives audio samples.
+        This is especially useful in the typical case where a video element displays the locally captured stream (including a local audio track) but is muted
+        to prevent feedback loop.
+        For that reason, the player is now setting the muted state of the renderer instead of setting volume to 0.
+
+        Covered by existing test sets.
+
+        * Modules/mediarecorder/MediaRecorder.cpp:
+        (WebCore::MediaRecorder::createMediaRecorderPrivate):
+        * Modules/mediarecorder/MediaRecorder.h:
+        * Modules/mediarecorder/MediaRecorderProvider.cpp:
+        (WebCore::MediaRecorderProvider::createMediaRecorderPrivate):
+        * Modules/mediarecorder/MediaRecorderProvider.h:
+        * loader/EmptyClients.cpp:
+        * platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaStreamAVFObjC.mm:
+        (WebCore::MediaPlayerPrivateMediaStreamAVFObjC::setVolume):
+        (WebCore::MediaPlayerPrivateMediaStreamAVFObjC::setMuted):
+        * platform/mediarecorder/MediaRecorderPrivate.cpp:
+        (WebCore::MediaRecorderPrivate::selectTracks):
+        * platform/mediarecorder/MediaRecorderPrivate.h:
+        (WebCore::MediaRecorderPrivate::setAudioSource):
+        (WebCore::MediaRecorderPrivate::~MediaRecorderPrivate):
+        * platform/mediarecorder/MediaRecorderPrivateAVFImpl.cpp:
+        (WebCore::MediaRecorderPrivateAVFImpl::create):
+        (WebCore::MediaRecorderPrivateAVFImpl::~MediaRecorderPrivateAVFImpl):
+        (WebCore::MediaRecorderPrivateAVFImpl::audioSamplesAvailable):
+        (WebCore::MediaRecorderPrivateAVFImpl::stopRecording):
+        (WebCore::MediaRecorderPrivateAVFImpl::fetchData):
+        * platform/mediarecorder/MediaRecorderPrivateAVFImpl.h:
+        * platform/mediarecorder/MediaRecorderPrivateMock.cpp:
+        (WebCore::MediaRecorderPrivateMock::MediaRecorderPrivateMock):
+        (WebCore::MediaRecorderPrivateMock::~MediaRecorderPrivateMock):
+        (WebCore::MediaRecorderPrivateMock::stopRecording):
+        (WebCore::MediaRecorderPrivateMock::sampleBufferUpdated):
+        (WebCore::MediaRecorderPrivateMock::audioSamplesAvailable):
+        (WebCore::MediaRecorderPrivateMock::generateMockCounterString):
+        (WebCore::MediaRecorderPrivateMock::fetchData):
+        * platform/mediarecorder/MediaRecorderPrivateMock.h:
+        * platform/mediastream/AudioTrackPrivateMediaStream.cpp:
+        (WebCore::AudioTrackPrivateMediaStream::AudioTrackPrivateMediaStream):
+        (WebCore::AudioTrackPrivateMediaStream::clear):
+        (WebCore::AudioTrackPrivateMediaStream::play):
+        (WebCore::AudioTrackPrivateMediaStream::pause):
+        (WebCore::AudioTrackPrivateMediaStream::setMuted):
+        (WebCore::AudioTrackPrivateMediaStream::audioSamplesAvailable):
+        (WebCore::AudioTrackPrivateMediaStream::trackMutedChanged):
+        (WebCore::AudioTrackPrivateMediaStream::trackEnabledChanged):
+        (WebCore::AudioTrackPrivateMediaStream::trackEnded):
+        (WebCore::AudioTrackPrivateMediaStream::updateRenderer):
+        (WebCore::AudioTrackPrivateMediaStream::startRenderer):
+        (WebCore::AudioTrackPrivateMediaStream::stopRenderer):
+        * platform/mediastream/AudioTrackPrivateMediaStream.h:
+        * platform/mediastream/gstreamer/GStreamerMediaStreamSource.cpp:
+        (WebCore::webkitMediaStreamSrcFinalize):
+        (WebCore::webkitMediaStreamSrcChangeState):
+        (WebCore::webkitMediaStreamSrcSetupSrc):
+        * platform/mediastream/MediaStreamPrivate.cpp:
+        (WebCore::MediaStreamPrivate::forEachTrack):
+        * platform/mediastream/MediaStreamPrivate.h:
+        * platform/mediastream/MediaStreamTrackPrivate.cpp:
+        (WebCore::MediaStreamTrackPrivate::forEachObserver const):
+        (WebCore::MediaStreamTrackPrivate::addObserver):
+        (WebCore::MediaStreamTrackPrivate::removeObserver):
+        (WebCore::MediaStreamTrackPrivate::hasStartedProducingAudioData):
+        * platform/mediastream/MediaStreamTrackPrivate.h:
+        * platform/mediastream/RealtimeMediaSource.cpp:
+        (WebCore::RealtimeMediaSource::addAudioSampleObserver):
+        (WebCore::RealtimeMediaSource::removeAudioSampleObserver):
+        (WebCore::RealtimeMediaSource::addObserver):
+        (WebCore::RealtimeMediaSource::removeObserver):
+        (WebCore::RealtimeMediaSource::forEachObserver const):
+        (WebCore::RealtimeMediaSource::audioSamplesAvailable):
+        * platform/mediastream/RealtimeMediaSource.h:
+        * platform/mediastream/RealtimeOutgoingAudioSource.cpp:
+        (WebCore::RealtimeOutgoingAudioSource::~RealtimeOutgoingAudioSource):
+        (WebCore::RealtimeOutgoingAudioSource::observeSource):
+        (WebCore::RealtimeOutgoingAudioSource::unobserveSource):
+        * platform/mediastream/RealtimeOutgoingAudioSource.h:
+        * platform/mediastream/WebAudioSourceProvider.h:
+        * platform/mediastream/mac/WebAudioSourceProviderAVFObjC.h:
+        * platform/mediastream/mac/WebAudioSourceProviderAVFObjC.mm:
+        (WebCore::WebAudioSourceProviderAVFObjC::WebAudioSourceProviderAVFObjC):
+        (WebCore::WebAudioSourceProviderAVFObjC::~WebAudioSourceProviderAVFObjC):
+        (WebCore::WebAudioSourceProviderAVFObjC::trackEnabledChanged):
+        (WebCore::WebAudioSourceProviderAVFObjC::audioSamplesAvailable):
+        * testing/Internals.cpp:
+        (WebCore::Internals::~Internals):
+        (WebCore::createRecorderMockSource):
+        (WebCore::Internals::observeMediaStreamTrack):
+        (WebCore::Internals::videoSampleAvailable):
+        * testing/Internals.h:
+
 2020-04-09  Antti Koivisto  <an...@apple.com>
 
         Removed unused fields and functions from StylePropertyShorthand

Modified: trunk/Source/WebCore/Modules/mediarecorder/MediaRecorder.cpp (259815 => 259816)


--- trunk/Source/WebCore/Modules/mediarecorder/MediaRecorder.cpp	2020-04-09 19:42:02 UTC (rev 259815)
+++ trunk/Source/WebCore/Modules/mediarecorder/MediaRecorder.cpp	2020-04-09 19:44:21 UTC (rev 259816)
@@ -44,7 +44,7 @@
 
 WTF_MAKE_ISO_ALLOCATED_IMPL(MediaRecorder);
 
-creatorFunction MediaRecorder::m_customCreator = nullptr;
+MediaRecorder::CreatorFunction MediaRecorder::m_customCreator = nullptr;
 
 ExceptionOr<Ref<MediaRecorder>> MediaRecorder::create(Document& document, Ref<MediaStream>&& stream, Options&& options)
 {
@@ -59,15 +59,15 @@
     return recorder;
 }
 
-void MediaRecorder::setCustomPrivateRecorderCreator(creatorFunction creator)
+void MediaRecorder::setCustomPrivateRecorderCreator(CreatorFunction creator)
 {
     m_customCreator = creator;
 }
 
-std::unique_ptr<MediaRecorderPrivate> MediaRecorder::createMediaRecorderPrivate(Document& document, const MediaStreamPrivate& stream)
+std::unique_ptr<MediaRecorderPrivate> MediaRecorder::createMediaRecorderPrivate(Document& document, MediaStreamPrivate& stream)
 {
     if (m_customCreator)
-        return m_customCreator();
+        return m_customCreator(stream);
 
 #if PLATFORM(COCOA)
     auto* page = document.page();
@@ -227,11 +227,6 @@
     m_private->sampleBufferUpdated(track, mediaSample);
 }
 
-void MediaRecorder::audioSamplesAvailable(MediaStreamTrackPrivate& track, const MediaTime& mediaTime, const PlatformAudioData& audioData, const AudioStreamDescription& description, size_t sampleCount)
-{
-    m_private->audioSamplesAvailable(track, mediaTime, audioData, description, sampleCount);
-}
-
 bool MediaRecorder::virtualHasPendingActivity() const
 {
     return m_state != RecordingState::Inactive;

Modified: trunk/Source/WebCore/Modules/mediarecorder/MediaRecorder.h (259815 => 259816)


--- trunk/Source/WebCore/Modules/mediarecorder/MediaRecorder.h	2020-04-09 19:42:02 UTC (rev 259815)
+++ trunk/Source/WebCore/Modules/mediarecorder/MediaRecorder.h	2020-04-09 19:44:21 UTC (rev 259816)
@@ -38,8 +38,6 @@
 class Document;
 class MediaRecorderPrivate;
 
-typedef std::unique_ptr<MediaRecorderPrivate>(*creatorFunction)();
-
 class MediaRecorder final
     : public ActiveDOMObject
     , public RefCounted<MediaRecorder>
@@ -62,7 +60,9 @@
     
     static ExceptionOr<Ref<MediaRecorder>> create(Document&, Ref<MediaStream>&&, Options&& = { });
     
-    WEBCORE_EXPORT static void setCustomPrivateRecorderCreator(creatorFunction);
+    using CreatorFunction = std::unique_ptr<MediaRecorderPrivate>(*)(MediaStreamPrivate&);
+
+    WEBCORE_EXPORT static void setCustomPrivateRecorderCreator(CreatorFunction);
     
     RecordingState state() const { return m_state; }
     
@@ -78,7 +78,7 @@
 private:
     MediaRecorder(Document&, Ref<MediaStream>&&, std::unique_ptr<MediaRecorderPrivate>&&, Options&& = { });
 
-    static std::unique_ptr<MediaRecorderPrivate> createMediaRecorderPrivate(Document&, const MediaStreamPrivate&);
+    static std::unique_ptr<MediaRecorderPrivate> createMediaRecorderPrivate(Document&, MediaStreamPrivate&);
     
     Document* document() const;
 
@@ -107,10 +107,9 @@
     void trackSettingsChanged(MediaStreamTrackPrivate&) final { };
     void trackEnabledChanged(MediaStreamTrackPrivate&) final { };
     void sampleBufferUpdated(MediaStreamTrackPrivate&, MediaSample&) final;
-    void audioSamplesAvailable(MediaStreamTrackPrivate&, const MediaTime&, const PlatformAudioData&, const AudioStreamDescription&, size_t) final;
+
+    static CreatorFunction m_customCreator;
     
-    static creatorFunction m_customCreator;
-    
     Options m_options;
     Ref<MediaStream> m_stream;
     std::unique_ptr<MediaRecorderPrivate> m_private;

Modified: trunk/Source/WebCore/Modules/mediarecorder/MediaRecorderProvider.cpp (259815 => 259816)


--- trunk/Source/WebCore/Modules/mediarecorder/MediaRecorderProvider.cpp	2020-04-09 19:42:02 UTC (rev 259815)
+++ trunk/Source/WebCore/Modules/mediarecorder/MediaRecorderProvider.cpp	2020-04-09 19:44:21 UTC (rev 259816)
@@ -32,7 +32,7 @@
 
 namespace WebCore {
 
-std::unique_ptr<MediaRecorderPrivate> MediaRecorderProvider::createMediaRecorderPrivate(const MediaStreamPrivate& stream)
+std::unique_ptr<MediaRecorderPrivate> MediaRecorderProvider::createMediaRecorderPrivate(MediaStreamPrivate& stream)
 {
     return MediaRecorderPrivateAVFImpl::create(stream);
 }

Modified: trunk/Source/WebCore/Modules/mediarecorder/MediaRecorderProvider.h (259815 => 259816)


--- trunk/Source/WebCore/Modules/mediarecorder/MediaRecorderProvider.h	2020-04-09 19:42:02 UTC (rev 259815)
+++ trunk/Source/WebCore/Modules/mediarecorder/MediaRecorderProvider.h	2020-04-09 19:44:21 UTC (rev 259816)
@@ -37,7 +37,7 @@
     virtual ~MediaRecorderProvider() = default;
 
 #if ENABLE(MEDIA_STREAM) && PLATFORM(COCOA)
-    virtual std::unique_ptr<MediaRecorderPrivate> createMediaRecorderPrivate(const MediaStreamPrivate&);
+    virtual std::unique_ptr<MediaRecorderPrivate> createMediaRecorderPrivate(MediaStreamPrivate&);
 #endif
 
     void setUseGPUProcess(bool value) { m_useGPUProcess = value; }

Modified: trunk/Source/WebCore/loader/EmptyClients.cpp (259815 => 259816)


--- trunk/Source/WebCore/loader/EmptyClients.cpp	2020-04-09 19:42:02 UTC (rev 259815)
+++ trunk/Source/WebCore/loader/EmptyClients.cpp	2020-04-09 19:44:21 UTC (rev 259816)
@@ -582,7 +582,7 @@
     EmptyMediaRecorderProvider() = default;
 private:
 #if ENABLE(MEDIA_STREAM) && PLATFORM(COCOA)
-    std::unique_ptr<MediaRecorderPrivate> createMediaRecorderPrivate(const MediaStreamPrivate&) final { return nullptr; }
+    std::unique_ptr<MediaRecorderPrivate> createMediaRecorderPrivate(MediaStreamPrivate&) final { return nullptr; }
 #endif
 };
 

Modified: trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaStreamAVFObjC.mm (259815 => 259816)


--- trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaStreamAVFObjC.mm	2020-04-09 19:42:02 UTC (rev 259815)
+++ trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaStreamAVFObjC.mm	2020-04-09 19:44:21 UTC (rev 259816)
@@ -560,7 +560,7 @@
     ALWAYS_LOG(LOGIDENTIFIER, volume);
     m_volume = volume;
     for (const auto& track : m_audioTrackMap.values())
-        track->setVolume(m_muted ? 0 : m_volume);
+        track->setVolume(m_volume);
 }
 
 void MediaPlayerPrivateMediaStreamAVFObjC::setMuted(bool muted)
@@ -571,7 +571,7 @@
     ALWAYS_LOG(LOGIDENTIFIER, muted);
     m_muted = muted;
     for (const auto& track : m_audioTrackMap.values())
-        track->setVolume(m_muted ? 0 : m_volume);
+        track->setMuted(m_muted);
 }
 
 bool MediaPlayerPrivateMediaStreamAVFObjC::hasVideo() const

Modified: trunk/Source/WebCore/platform/mediarecorder/MediaRecorderPrivate.cpp (259815 => 259816)


--- trunk/Source/WebCore/platform/mediarecorder/MediaRecorderPrivate.cpp	2020-04-09 19:42:02 UTC (rev 259815)
+++ trunk/Source/WebCore/platform/mediarecorder/MediaRecorderPrivate.cpp	2020-04-09 19:44:21 UTC (rev 259816)
@@ -32,7 +32,7 @@
 
 namespace WebCore {
 
-MediaRecorderPrivate::AudioVideoSelectedTracks MediaRecorderPrivate::selectTracks(const MediaStreamPrivate& stream)
+MediaRecorderPrivate::AudioVideoSelectedTracks MediaRecorderPrivate::selectTracks(MediaStreamPrivate& stream)
 {
     AudioVideoSelectedTracks selectedTracks;
     stream.forEachTrack([&](auto& track) {

Modified: trunk/Source/WebCore/platform/mediarecorder/MediaRecorderPrivate.h (259815 => 259816)


--- trunk/Source/WebCore/platform/mediarecorder/MediaRecorderPrivate.h	2020-04-09 19:42:02 UTC (rev 259815)
+++ trunk/Source/WebCore/platform/mediarecorder/MediaRecorderPrivate.h	2020-04-09 19:44:21 UTC (rev 259816)
@@ -27,6 +27,7 @@
 #include <wtf/CompletionHandler.h>
 #include <wtf/Forward.h>
 #include "Exception.h"
+#include "RealtimeMediaSource.h"
 
 #if ENABLE(MEDIA_STREAM)
 
@@ -43,29 +44,53 @@
 class PlatformAudioData;
 class SharedBuffer;
 
-class MediaRecorderPrivate {
+class MediaRecorderPrivate :
+    public RealtimeMediaSource::AudioSampleObserver {
 public:
-    virtual ~MediaRecorderPrivate() = default;
+    ~MediaRecorderPrivate();
 
     struct AudioVideoSelectedTracks {
-        const MediaStreamTrackPrivate* audioTrack { nullptr };
-        const MediaStreamTrackPrivate* videoTrack { nullptr };
+        MediaStreamTrackPrivate* audioTrack { nullptr };
+        MediaStreamTrackPrivate* videoTrack { nullptr };
     };
-    WEBCORE_EXPORT static AudioVideoSelectedTracks selectTracks(const MediaStreamPrivate&);
+    WEBCORE_EXPORT static AudioVideoSelectedTracks selectTracks(MediaStreamPrivate&);
 
     virtual void sampleBufferUpdated(const MediaStreamTrackPrivate&, MediaSample&) = 0;
-    virtual void audioSamplesAvailable(const MediaStreamTrackPrivate&, const WTF::MediaTime&, const PlatformAudioData&, const AudioStreamDescription&, size_t) = 0;
 
-    virtual void fetchData(CompletionHandler<void(RefPtr<SharedBuffer>&&, const String& mimeType)>&&) = 0;
-    virtual void stopRecording() { };
+    using FetchDataCallback = CompletionHandler<void(RefPtr<SharedBuffer>&&, const String& mimeType)>;
+    virtual void fetchData(FetchDataCallback&&) = 0;
+    virtual void stopRecording() = 0;
 
     using ErrorCallback = Function<void(Optional<Exception>&&)>;
     void setErrorCallback(ErrorCallback&& errorCallback) { m_errorCallback = WTFMove(errorCallback); }
 
 protected:
+    void setAudioSource(RefPtr<RealtimeMediaSource>&&);
+
+protected:
     ErrorCallback m_errorCallback;
+
+private:
+    RefPtr<RealtimeMediaSource> m_audioSource;
 };
 
+inline void MediaRecorderPrivate::setAudioSource(RefPtr<RealtimeMediaSource>&& audioSource)
+{
+    if (m_audioSource)
+        m_audioSource->removeAudioSampleObserver(*this);
+
+    m_audioSource = WTFMove(audioSource);
+
+    if (m_audioSource)
+        m_audioSource->addAudioSampleObserver(*this);
+}
+
+inline MediaRecorderPrivate::~MediaRecorderPrivate()
+{
+    if (m_audioSource)
+        m_audioSource->removeAudioSampleObserver(*this);
+}
+
 } // namespace WebCore
 
 #endif // ENABLE(MEDIA_STREAM)

Modified: trunk/Source/WebCore/platform/mediarecorder/MediaRecorderPrivateAVFImpl.cpp (259815 => 259816)


--- trunk/Source/WebCore/platform/mediarecorder/MediaRecorderPrivateAVFImpl.cpp	2020-04-09 19:42:02 UTC (rev 259815)
+++ trunk/Source/WebCore/platform/mediarecorder/MediaRecorderPrivateAVFImpl.cpp	2020-04-09 19:44:21 UTC (rev 259816)
@@ -36,7 +36,7 @@
 
 namespace WebCore {
 
-std::unique_ptr<MediaRecorderPrivateAVFImpl> MediaRecorderPrivateAVFImpl::create(const MediaStreamPrivate& stream)
+std::unique_ptr<MediaRecorderPrivateAVFImpl> MediaRecorderPrivateAVFImpl::create(MediaStreamPrivate& stream)
 {
     // FIXME: we will need to implement support for multiple audio/video tracks
     // Currently we only choose the first track as the recorded track.
@@ -51,11 +51,15 @@
     String audioTrackId;
     if (selectedTracks.audioTrack)
         audioTrackId = selectedTracks.audioTrack->id();
+
     String videoTrackId;
     if (selectedTracks.videoTrack)
         videoTrackId = selectedTracks.videoTrack->id();
 
-    return makeUnique<MediaRecorderPrivateAVFImpl>(writer.releaseNonNull(), WTFMove(audioTrackId), WTFMove(videoTrackId));
+    auto recorder = makeUnique<MediaRecorderPrivateAVFImpl>(writer.releaseNonNull(), WTFMove(audioTrackId), WTFMove(videoTrackId));
+    if (selectedTracks.audioTrack)
+        recorder->setAudioSource(&selectedTracks.audioTrack->source());
+    return recorder;
 }
 
 MediaRecorderPrivateAVFImpl::MediaRecorderPrivateAVFImpl(Ref<MediaRecorderPrivateWriter>&& writer, String&& audioTrackId, String&& videoTrackId)
@@ -65,6 +69,11 @@
 {
 }
 
+MediaRecorderPrivateAVFImpl::~MediaRecorderPrivateAVFImpl()
+{
+    setAudioSource(nullptr);
+}
+
 void MediaRecorderPrivateAVFImpl::sampleBufferUpdated(const MediaStreamTrackPrivate& track, MediaSample& sampleBuffer)
 {
     if (track.id() != m_recordedVideoTrackID)
@@ -72,10 +81,8 @@
     m_writer->appendVideoSampleBuffer(sampleBuffer.platformSample().sample.cmSampleBuffer);
 }
 
-void MediaRecorderPrivateAVFImpl::audioSamplesAvailable(const MediaStreamTrackPrivate& track, const WTF::MediaTime& mediaTime, const PlatformAudioData& data, const AudioStreamDescription& description, size_t sampleCount)
+void MediaRecorderPrivateAVFImpl::audioSamplesAvailable(const WTF::MediaTime& mediaTime, const PlatformAudioData& data, const AudioStreamDescription& description, size_t sampleCount)
 {
-    if (track.id() != m_recordedAudioTrackID)
-        return;
     ASSERT(is<WebAudioBufferList>(data));
     ASSERT(description.platformDescription().type == PlatformDescription::CAAudioStreamBasicType);
     m_writer->appendAudioSampleBuffer(data, description, mediaTime, sampleCount);
@@ -83,10 +90,11 @@
 
 void MediaRecorderPrivateAVFImpl::stopRecording()
 {
+    setAudioSource(nullptr);
     m_writer->stopRecording();
 }
 
-void MediaRecorderPrivateAVFImpl::fetchData(CompletionHandler<void(RefPtr<SharedBuffer>&&, const String&)>&& completionHandler)
+void MediaRecorderPrivateAVFImpl::fetchData(FetchDataCallback&& completionHandler)
 {
     m_writer->fetchData([completionHandler = WTFMove(completionHandler), mimeType = mimeType()](auto&& buffer) mutable {
         completionHandler(WTFMove(buffer), mimeType);

Modified: trunk/Source/WebCore/platform/mediarecorder/MediaRecorderPrivateAVFImpl.h (259815 => 259816)


--- trunk/Source/WebCore/platform/mediarecorder/MediaRecorderPrivateAVFImpl.h	2020-04-09 19:42:02 UTC (rev 259815)
+++ trunk/Source/WebCore/platform/mediarecorder/MediaRecorderPrivateAVFImpl.h	2020-04-09 19:44:21 UTC (rev 259816)
@@ -33,10 +33,12 @@
 
 class MediaStreamPrivate;
 
-class MediaRecorderPrivateAVFImpl final : public MediaRecorderPrivate {
+class MediaRecorderPrivateAVFImpl final
+    : public MediaRecorderPrivate {
     WTF_MAKE_FAST_ALLOCATED;
 public:
-    static std::unique_ptr<MediaRecorderPrivateAVFImpl> create(const MediaStreamPrivate&);
+    static std::unique_ptr<MediaRecorderPrivateAVFImpl> create(MediaStreamPrivate&);
+    ~MediaRecorderPrivateAVFImpl();
 
 private:
     MediaRecorderPrivateAVFImpl(Ref<MediaRecorderPrivateWriter>&&, String&& audioTrackId, String&& videoTrackId);
@@ -43,12 +45,14 @@
 
     friend std::unique_ptr<MediaRecorderPrivateAVFImpl> std::make_unique<MediaRecorderPrivateAVFImpl>(Ref<MediaRecorderPrivateWriter>&&, String&&, String&&);
 
+    // MediaRecorderPrivate
     void sampleBufferUpdated(const MediaStreamTrackPrivate&, MediaSample&) final;
-    void audioSamplesAvailable(const MediaStreamTrackPrivate&, const WTF::MediaTime&, const PlatformAudioData&, const AudioStreamDescription&, size_t) final;
-    void fetchData(CompletionHandler<void(RefPtr<SharedBuffer>&&, const String&)>&&) final;
+    void fetchData(FetchDataCallback&&) final;
+    void audioSamplesAvailable(const WTF::MediaTime&, const PlatformAudioData&, const AudioStreamDescription&, size_t) final;
+
     const String& mimeType();
     void stopRecording();
-    
+
     Ref<MediaRecorderPrivateWriter> m_writer;
     String m_recordedAudioTrackID;
     String m_recordedVideoTrackID;

Modified: trunk/Source/WebCore/platform/mediarecorder/MediaRecorderPrivateMock.cpp (259815 => 259816)


--- trunk/Source/WebCore/platform/mediarecorder/MediaRecorderPrivateMock.cpp	2020-04-09 19:42:02 UTC (rev 259815)
+++ trunk/Source/WebCore/platform/mediarecorder/MediaRecorderPrivateMock.cpp	2020-04-09 19:44:21 UTC (rev 259816)
@@ -33,30 +33,51 @@
 
 namespace WebCore {
 
-void MediaRecorderPrivateMock::sampleBufferUpdated(const MediaStreamTrackPrivate& track, MediaSample&)
+MediaRecorderPrivateMock::MediaRecorderPrivateMock(MediaStreamPrivate& stream)
 {
-    generateMockString(track);
+    auto selectedTracks = MediaRecorderPrivate::selectTracks(stream);
+    if (selectedTracks.audioTrack) {
+        m_audioTrackID = selectedTracks.audioTrack->id();
+        setAudioSource(&selectedTracks.audioTrack->source());
+    }
+    if (selectedTracks.videoTrack)
+        m_videoTrackID = selectedTracks.videoTrack->id();
 }
 
-void MediaRecorderPrivateMock::audioSamplesAvailable(const MediaStreamTrackPrivate& track, const WTF::MediaTime&, const PlatformAudioData&, const AudioStreamDescription&, size_t)
+MediaRecorderPrivateMock::~MediaRecorderPrivateMock()
 {
-    generateMockString(track);
+    setAudioSource(nullptr);
 }
 
-void MediaRecorderPrivateMock::generateMockString(const MediaStreamTrackPrivate& track)
+void MediaRecorderPrivateMock::stopRecording()
 {
+    setAudioSource(nullptr);
+}
+
+void MediaRecorderPrivateMock::sampleBufferUpdated(const MediaStreamTrackPrivate&, MediaSample&)
+{
     auto locker = holdLock(m_bufferLock);
-    if (track.type() == RealtimeMediaSource::Type::Audio)
-        m_buffer.append("Audio Track ID: ");
-    else
-        m_buffer.append("Video Track ID: ");
-    m_buffer.append(track.id());
+    m_buffer.append("Video Track ID: ");
+    m_buffer.append(m_videoTrackID);
+    generateMockCounterString();
+}
+
+void MediaRecorderPrivateMock::audioSamplesAvailable(const WTF::MediaTime&, const PlatformAudioData&, const AudioStreamDescription&, size_t)
+{
+    auto locker = holdLock(m_bufferLock);
+    m_buffer.append("Audio Track ID: ");
+    m_buffer.append(m_audioTrackID);
+    generateMockCounterString();
+}
+
+void MediaRecorderPrivateMock::generateMockCounterString()
+{
     m_buffer.append(" Counter: ");
     m_buffer.appendNumber(++m_counter);
     m_buffer.append("\r\n---------\r\n");
 }
 
-void MediaRecorderPrivateMock::fetchData(CompletionHandler<void(RefPtr<SharedBuffer>&&, const String&)>&& completionHandler)
+void MediaRecorderPrivateMock::fetchData(FetchDataCallback&& completionHandler)
 {
     auto locker = holdLock(m_bufferLock);
     Vector<uint8_t> value(m_buffer.length());

Modified: trunk/Source/WebCore/platform/mediarecorder/MediaRecorderPrivateMock.h (259815 => 259816)


--- trunk/Source/WebCore/platform/mediarecorder/MediaRecorderPrivateMock.h	2020-04-09 19:42:02 UTC (rev 259815)
+++ trunk/Source/WebCore/platform/mediarecorder/MediaRecorderPrivateMock.h	2020-04-09 19:44:21 UTC (rev 259816)
@@ -34,18 +34,27 @@
 
 class MediaStreamTrackPrivate;
 
-class WEBCORE_EXPORT MediaRecorderPrivateMock final : public MediaRecorderPrivate {
+class WEBCORE_EXPORT MediaRecorderPrivateMock final
+    : public MediaRecorderPrivate {
+public:
+    explicit MediaRecorderPrivateMock(MediaStreamPrivate&);
+    ~MediaRecorderPrivateMock();
+
 private:
+    // MediaRecorderPrivate
     void sampleBufferUpdated(const MediaStreamTrackPrivate&, MediaSample&) final;
-    void audioSamplesAvailable(const MediaStreamTrackPrivate&, const WTF::MediaTime&, const PlatformAudioData&, const AudioStreamDescription&, size_t) final;
-    void fetchData(CompletionHandler<void(RefPtr<SharedBuffer>&&, const String&)>&&) final;
+    void fetchData(FetchDataCallback&&) final;
+    void audioSamplesAvailable(const WTF::MediaTime&, const PlatformAudioData&, const AudioStreamDescription&, size_t) final;
+    void stopRecording() final;
+
     const String& mimeType();
-    
-    void generateMockString(const MediaStreamTrackPrivate&);
+    void generateMockCounterString();
 
     mutable Lock m_bufferLock;
     StringBuilder m_buffer;
     unsigned m_counter { 0 };
+    String m_audioTrackID;
+    String m_videoTrackID;
 };
 
 } // namespace WebCore

Modified: trunk/Source/WebCore/platform/mediastream/AudioTrackPrivateMediaStream.cpp (259815 => 259816)


--- trunk/Source/WebCore/platform/mediastream/AudioTrackPrivateMediaStream.cpp	2020-04-09 19:42:02 UTC (rev 259815)
+++ trunk/Source/WebCore/platform/mediastream/AudioTrackPrivateMediaStream.cpp	2020-04-09 19:44:21 UTC (rev 259816)
@@ -35,9 +35,9 @@
 
 AudioTrackPrivateMediaStream::AudioTrackPrivateMediaStream(MediaStreamTrackPrivate& track)
     : m_streamTrack(track)
+    , m_audioSource(track.source())
     , m_id(track.id())
     , m_label(track.label())
-    , m_timelineOffset(MediaTime::invalidTime())
     , m_renderer { AudioMediaStreamTrackRenderer::create() }
 {
     track.addObserver(*this);
@@ -62,45 +62,36 @@
         return;
 
     m_isCleared = true;
-    streamTrack().removeObserver(*this);
 
-    m_renderer->clear();
-}
-
-void AudioTrackPrivateMediaStream::playInternal()
-{
-    ASSERT(isMainThread());
-
     if (m_isPlaying)
-        return;
+        m_audioSource->removeAudioSampleObserver(*this);
 
-    m_isPlaying = true;
-    m_autoPlay = false;
-
-    m_renderer->start();
+    streamTrack().removeObserver(*this);
+    m_renderer->clear();
 }
 
 void AudioTrackPrivateMediaStream::play()
 {
-    playInternal();
+    m_shouldPlay = true;
+    updateRenderer();
 }
 
 void AudioTrackPrivateMediaStream::pause()
 {
-    ASSERT(isMainThread());
+    m_shouldPlay = false;
+    updateRenderer();
+}
 
-    if (!m_isPlaying)
-        return;
-
-    m_isPlaying = false;
-    m_autoPlay = false;
-
-    m_renderer->stop();
+void AudioTrackPrivateMediaStream::setMuted(bool muted)
+{
+    m_muted = muted;
+    updateRenderer();
 }
 
 void AudioTrackPrivateMediaStream::setVolume(float volume)
 {
     m_renderer->setVolume(volume);
+    updateRenderer();
 }
 
 float AudioTrackPrivateMediaStream::volume() const
@@ -109,48 +100,57 @@
 }
 
 // May get called on a background thread.
-void AudioTrackPrivateMediaStream::audioSamplesAvailable(MediaStreamTrackPrivate&, const MediaTime& sampleTime, const PlatformAudioData& audioData, const AudioStreamDescription& description, size_t sampleCount)
+void AudioTrackPrivateMediaStream::audioSamplesAvailable(const MediaTime& sampleTime, const PlatformAudioData& audioData, const AudioStreamDescription& description, size_t sampleCount)
 {
-    if (!m_isPlaying) {
-        m_renderer->stop();
-        return;
-    }
-
     m_renderer->pushSamples(sampleTime, audioData, description, sampleCount);
-
-    if (m_autoPlay && !m_hasStartedAutoplay) {
-        m_hasStartedAutoplay = true;
-        callOnMainThread([this, protectedThis = makeRef(*this)] {
-            if (m_autoPlay)
-                playInternal();
-        });
-    }
 }
 
 void AudioTrackPrivateMediaStream::trackMutedChanged(MediaStreamTrackPrivate&)
 {
-    updateRendererMutedState();
+    updateRenderer();
 }
 
 void AudioTrackPrivateMediaStream::trackEnabledChanged(MediaStreamTrackPrivate&)
 {
-    updateRendererMutedState();
+    updateRenderer();
 }
 
-void AudioTrackPrivateMediaStream::updateRendererMutedState()
+void AudioTrackPrivateMediaStream::trackEnded(MediaStreamTrackPrivate&)
 {
-    if (streamTrack().muted() || streamTrack().ended() || !streamTrack().enabled()) {
-        pause();
+    updateRenderer();
+}
+
+void AudioTrackPrivateMediaStream::updateRenderer()
+{
+    if (!m_shouldPlay || !volume() || m_muted || streamTrack().muted() || streamTrack().ended() || !streamTrack().enabled()) {
+        stopRenderer();
         return;
     }
-    play();
+    startRenderer();
 }
 
-void AudioTrackPrivateMediaStream::trackEnded(MediaStreamTrackPrivate&)
+void AudioTrackPrivateMediaStream::startRenderer()
 {
-    pause();
+    ASSERT(isMainThread());
+    if (m_isPlaying)
+        return;
+
+    m_isPlaying = true;
+    m_audioSource->addAudioSampleObserver(*this);
+    m_renderer->start();
 }
 
+void AudioTrackPrivateMediaStream::stopRenderer()
+{
+    ASSERT(isMainThread());
+    if (!m_isPlaying)
+        return;
+
+    m_isPlaying = false;
+    m_audioSource->removeAudioSampleObserver(*this);
+    m_renderer->stop();
+}
+
 } // namespace WebCore
 
 #endif // ENABLE(VIDEO_TRACK) && ENABLE(MEDIA_STREAM)

Modified: trunk/Source/WebCore/platform/mediastream/AudioTrackPrivateMediaStream.h (259815 => 259816)


--- trunk/Source/WebCore/platform/mediastream/AudioTrackPrivateMediaStream.h	2020-04-09 19:42:02 UTC (rev 259815)
+++ trunk/Source/WebCore/platform/mediastream/AudioTrackPrivateMediaStream.h	2020-04-09 19:44:21 UTC (rev 259816)
@@ -34,7 +34,10 @@
 
 class AudioMediaStreamTrackRenderer;
 
-class AudioTrackPrivateMediaStream final : public AudioTrackPrivate, private MediaStreamTrackPrivate::Observer {
+class AudioTrackPrivateMediaStream final
+    : public AudioTrackPrivate
+    , private MediaStreamTrackPrivate::Observer
+    , private RealtimeMediaSource::AudioSampleObserver {
     WTF_MAKE_NONCOPYABLE(AudioTrackPrivateMediaStream)
 public:
     static RefPtr<AudioTrackPrivateMediaStream> create(MediaStreamTrackPrivate& streamTrack)
@@ -47,9 +50,6 @@
 
     MediaStreamTrackPrivate& streamTrack() { return m_streamTrack.get(); }
 
-    MediaTime timelineOffset() const { return m_timelineOffset; }
-    void setTimelineOffset(const MediaTime& offset) { m_timelineOffset = offset; }
-
     void clear();
 
     void play();
@@ -59,7 +59,7 @@
     void setVolume(float);
     float volume() const;
 
-    void setMuted(bool muted) { m_muted = muted; }
+    void setMuted(bool);
     bool muted() const { return m_muted; }
 
 #if !RELEASE_LOG_DISABLED
@@ -77,30 +77,32 @@
     int trackIndex() const final { return m_index; }
 
     // MediaStreamTrackPrivate::Observer
-    void audioSamplesAvailable(MediaStreamTrackPrivate&, const MediaTime&, const PlatformAudioData&, const AudioStreamDescription&, size_t) final;
     void trackEnded(MediaStreamTrackPrivate&) final;
     void trackMutedChanged(MediaStreamTrackPrivate&)  final;
     void trackEnabledChanged(MediaStreamTrackPrivate&)  final;
     void trackSettingsChanged(MediaStreamTrackPrivate&) final { }
 
-    void playInternal();
-    void updateRendererMutedState();
+    // RealtimeMediaSource::AudioSampleObserver
+    void audioSamplesAvailable(const MediaTime&, const PlatformAudioData&, const AudioStreamDescription&, size_t) final;
 
+    void startRenderer();
+    void stopRenderer();
+    void updateRenderer();
+
     // Main thread writable members
     bool m_isPlaying { false };
-    bool m_autoPlay { false };
+    bool m_shouldPlay { false };
     bool m_muted { false };
     bool m_isCleared { false };
 
     Ref<MediaStreamTrackPrivate> m_streamTrack;
+    Ref<RealtimeMediaSource> m_audioSource;
     AtomString m_id;
     AtomString m_label;
     int m_index { 0 };
-    MediaTime m_timelineOffset;
 
     // Audio thread members
     std::unique_ptr<AudioMediaStreamTrackRenderer> m_renderer;
-    bool m_hasStartedAutoplay { false };
 };
 
 }

Modified: trunk/Source/WebCore/platform/mediastream/MediaStreamPrivate.cpp (259815 => 259816)


--- trunk/Source/WebCore/platform/mediastream/MediaStreamPrivate.cpp	2020-04-09 19:42:02 UTC (rev 259815)
+++ trunk/Source/WebCore/platform/mediastream/MediaStreamPrivate.cpp	2020-04-09 19:44:21 UTC (rev 259816)
@@ -121,6 +121,12 @@
         callback(*track);
 }
 
+void MediaStreamPrivate::forEachTrack(const Function<void(MediaStreamTrackPrivate&)>& callback)
+{
+    for (auto& track : m_trackSet.values())
+        callback(*track);
+}
+
 void MediaStreamPrivate::updateActiveState(NotifyClientOption notifyClientOption)
 {
     bool newActiveState = false;

Modified: trunk/Source/WebCore/platform/mediastream/MediaStreamPrivate.h (259815 => 259816)


--- trunk/Source/WebCore/platform/mediastream/MediaStreamPrivate.h	2020-04-09 19:42:02 UTC (rev 259815)
+++ trunk/Source/WebCore/platform/mediastream/MediaStreamPrivate.h	2020-04-09 19:44:21 UTC (rev 259816)
@@ -84,6 +84,7 @@
     MediaStreamTrackPrivateVector tracks() const;
     bool hasTracks() const { return !m_trackSet.isEmpty(); }
     void forEachTrack(const Function<void(const MediaStreamTrackPrivate&)>&) const;
+    void forEachTrack(const Function<void(MediaStreamTrackPrivate&)>&);
     MediaStreamTrackPrivate* activeVideoTrack() { return m_activeVideoTrack; }
 
     bool active() const { return m_isActive; }

Modified: trunk/Source/WebCore/platform/mediastream/MediaStreamTrackPrivate.cpp (259815 => 259816)


--- trunk/Source/WebCore/platform/mediastream/MediaStreamTrackPrivate.cpp	2020-04-09 19:42:02 UTC (rev 259815)
+++ trunk/Source/WebCore/platform/mediastream/MediaStreamTrackPrivate.cpp	2020-04-09 19:44:21 UTC (rev 259816)
@@ -78,16 +78,10 @@
     m_source->removeObserver(*this);
 }
 
-void MediaStreamTrackPrivate::forEachObserver(const WTF::Function<void(Observer&)>& apply) const
+void MediaStreamTrackPrivate::forEachObserver(const Function<void(Observer&)>& apply) const
 {
-    Vector<Observer*> observersCopy;
-    {
-        auto locker = holdLock(m_observersLock);
-        observersCopy = copyToVector(m_observers);
-    }
-    for (auto* observer : observersCopy) {
-        auto locker = holdLock(m_observersLock);
-        // Make sure the observer has not been destroyed.
+    ASSERT(isMainThread());
+    for (auto* observer : copyToVector(m_observers)) {
         if (!m_observers.contains(observer))
             continue;
         apply(*observer);
@@ -96,13 +90,13 @@
 
 void MediaStreamTrackPrivate::addObserver(MediaStreamTrackPrivate::Observer& observer)
 {
-    auto locker = holdLock(m_observersLock);
+    ASSERT(isMainThread());
     m_observers.add(&observer);
 }
 
 void MediaStreamTrackPrivate::removeObserver(MediaStreamTrackPrivate::Observer& observer)
 {
-    auto locker = holdLock(m_observersLock);
+    ASSERT(isMainThread());
     m_observers.remove(&observer);
 }
 
@@ -261,26 +255,12 @@
     });
 }
 
-// May get called on a background thread.
-void MediaStreamTrackPrivate::audioSamplesAvailable(const MediaTime& mediaTime, const PlatformAudioData& data, const AudioStreamDescription& description, size_t sampleCount)
+void MediaStreamTrackPrivate::hasStartedProducingAudioData()
 {
-    if (!m_hasSentStartProducedData) {
-        callOnMainThread([this, weakThis = makeWeakPtr(this)] {
-            if (!weakThis)
-                return;
-
-            if (!m_haveProducedData) {
-                m_haveProducedData = true;
-                updateReadyState();
-            }
-            m_hasSentStartProducedData = true;
-        });
+    if (m_haveProducedData)
         return;
-    }
-
-    forEachObserver([&](auto& observer) {
-        observer.audioSamplesAvailable(*this, mediaTime, data, description, sampleCount);
-    });
+    m_haveProducedData = true;
+    updateReadyState();
 }
 
 void MediaStreamTrackPrivate::updateReadyState()

Modified: trunk/Source/WebCore/platform/mediastream/MediaStreamTrackPrivate.h (259815 => 259816)


--- trunk/Source/WebCore/platform/mediastream/MediaStreamTrackPrivate.h	2020-04-09 19:42:02 UTC (rev 259815)
+++ trunk/Source/WebCore/platform/mediastream/MediaStreamTrackPrivate.h	2020-04-09 19:44:21 UTC (rev 259816)
@@ -62,9 +62,6 @@
         virtual void trackEnabledChanged(MediaStreamTrackPrivate&) = 0;
         virtual void sampleBufferUpdated(MediaStreamTrackPrivate&, MediaSample&) { };
         virtual void readyStateChanged(MediaStreamTrackPrivate&) { };
-
-        // May get called on a background thread.
-        virtual void audioSamplesAvailable(MediaStreamTrackPrivate&, const MediaTime&, const PlatformAudioData&, const AudioStreamDescription&, size_t) { };
     };
 
     static Ref<MediaStreamTrackPrivate> create(Ref<const Logger>&&, Ref<RealtimeMediaSource>&&);
@@ -100,6 +97,7 @@
     Ref<MediaStreamTrackPrivate> clone();
 
     RealtimeMediaSource& source() { return m_source.get(); }
+    const RealtimeMediaSource& source() const { return m_source.get(); }
     WEBCORE_EXPORT RealtimeMediaSource::Type type() const;
 
     void endTrack();
@@ -132,7 +130,7 @@
 private:
     MediaStreamTrackPrivate(Ref<const Logger>&&, Ref<RealtimeMediaSource>&&, String&& id);
 
-    // RealtimeMediaSourceObserver
+    // RealtimeMediaSource::Observer
     void sourceStarted() final;
     void sourceStopped() final;
     void sourceMutedChanged() final;
@@ -139,8 +137,8 @@
     void sourceSettingsChanged() final;
     bool preventSourceFromStopping() final;
     void videoSampleAvailable(MediaSample&) final;
-    void audioSamplesAvailable(const MediaTime&, const PlatformAudioData&, const AudioStreamDescription&, size_t) final;
     void audioUnitWillStart() final;
+    void hasStartedProducingAudioData() final;
 
     void updateReadyState();
 

Modified: trunk/Source/WebCore/platform/mediastream/RealtimeMediaSource.cpp (259815 => 259816)


--- trunk/Source/WebCore/platform/mediastream/RealtimeMediaSource.cpp	2020-04-09 19:42:02 UTC (rev 259815)
+++ trunk/Source/WebCore/platform/mediastream/RealtimeMediaSource.cpp	2020-04-09 19:44:21 UTC (rev 259816)
@@ -60,15 +60,29 @@
     m_hashedID = RealtimeMediaSourceCenter::singleton().hashStringWithSalt(m_persistentID, m_idHashSalt);
 }
 
+void RealtimeMediaSource::addAudioSampleObserver(RealtimeMediaSource::AudioSampleObserver& observer)
+{
+    ASSERT(isMainThread());
+    auto locker = holdLock(m_audioSampleObserversLock);
+    m_audioSampleObservers.add(&observer);
+}
+
+void RealtimeMediaSource::removeAudioSampleObserver(RealtimeMediaSource::AudioSampleObserver& observer)
+{
+    ASSERT(isMainThread());
+    auto locker = holdLock(m_audioSampleObserversLock);
+    m_audioSampleObservers.remove(&observer);
+}
+
 void RealtimeMediaSource::addObserver(RealtimeMediaSource::Observer& observer)
 {
-    auto locker = holdLock(m_observersLock);
+    ASSERT(isMainThread());
     m_observers.add(&observer);
 }
 
 void RealtimeMediaSource::removeObserver(RealtimeMediaSource::Observer& observer)
 {
-    auto locker = holdLock(m_observersLock);
+    ASSERT(isMainThread());
     m_observers.remove(&observer);
     if (m_observers.isEmpty())
         stopBeingObserved();
@@ -116,16 +130,10 @@
     notifyMutedChange(interrupted);
 }
 
-void RealtimeMediaSource::forEachObserver(const WTF::Function<void(Observer&)>& apply) const
+void RealtimeMediaSource::forEachObserver(const Function<void(Observer&)>& apply) const
 {
-    Vector<Observer*> observersCopy;
-    {
-        auto locker = holdLock(m_observersLock);
-        observersCopy = copyToVector(m_observers);
-    }
-    for (auto* observer : observersCopy) {
-        auto locker = holdLock(m_observersLock);
-        // Make sure the observer has not been destroyed.
+    ASSERT(isMainThread());
+    for (auto* observer : copyToVector(m_observers)) {
         if (!m_observers.contains(observer))
             continue;
         apply(*observer);
@@ -182,9 +190,22 @@
 
 void RealtimeMediaSource::audioSamplesAvailable(const MediaTime& time, const PlatformAudioData& audioData, const AudioStreamDescription& description, size_t numberOfFrames)
 {
-    forEachObserver([&](auto& observer) {
-        observer.audioSamplesAvailable(time, audioData, description, numberOfFrames);
-    });
+    if (!m_hasSentStartProducedAudioData) {
+        callOnMainThread([this, weakThis = makeWeakPtr(this)] {
+            if (!weakThis)
+                return;
+            if (m_hasSentStartProducedAudioData)
+                return;
+            m_hasSentStartProducedAudioData = true;
+            forEachObserver([&](auto& observer) {
+                observer.hasStartedProducingAudioData();
+            });
+        });
+    }
+
+    auto locker = holdLock(m_audioSampleObserversLock);
+    for (auto* observer : m_audioSampleObservers)
+        observer->audioSamplesAvailable(time, audioData, description, numberOfFrames);
 }
 
 void RealtimeMediaSource::start()

Modified: trunk/Source/WebCore/platform/mediastream/RealtimeMediaSource.h (259815 => 259816)


--- trunk/Source/WebCore/platform/mediastream/RealtimeMediaSource.h	2020-04-09 19:42:02 UTC (rev 259815)
+++ trunk/Source/WebCore/platform/mediastream/RealtimeMediaSource.h	2020-04-09 19:44:21 UTC (rev 259816)
@@ -69,7 +69,7 @@
 
 class WEBCORE_EXPORT RealtimeMediaSource
     : public ThreadSafeRefCounted<RealtimeMediaSource, WTF::DestructionThread::MainRunLoop>
-    , public CanMakeWeakPtr<RealtimeMediaSource>
+    , public CanMakeWeakPtr<RealtimeMediaSource, WeakPtrFactoryInitialization::Eager>
 #if !RELEASE_LOG_DISABLED
     , protected LoggerHelper
 #endif
@@ -92,8 +92,14 @@
         // Called on the main thread.
         virtual void videoSampleAvailable(MediaSample&) { }
 
+        virtual void hasStartedProducingAudioData() { }
+    };
+    class AudioSampleObserver {
+    public:
+        virtual ~AudioSampleObserver() = default;
+
         // May be called on a background thread.
-        virtual void audioSamplesAvailable(const MediaTime&, const PlatformAudioData&, const AudioStreamDescription&, size_t /*numberOfFrames*/) { }
+        virtual void audioSamplesAvailable(const MediaTime&, const PlatformAudioData&, const AudioStreamDescription&, size_t /*numberOfFrames*/) = 0;
     };
 
     virtual ~RealtimeMediaSource() = default;
@@ -131,6 +137,9 @@
     WEBCORE_EXPORT void addObserver(Observer&);
     WEBCORE_EXPORT void removeObserver(Observer&);
 
+    WEBCORE_EXPORT void addAudioSampleObserver(AudioSampleObserver&);
+    WEBCORE_EXPORT void removeAudioSampleObserver(AudioSampleObserver&);
+
     const IntSize size() const;
     void setSize(const IntSize&);
 
@@ -253,8 +262,11 @@
     String m_persistentID;
     Type m_type;
     String m_name;
-    mutable RecursiveLock m_observersLock;
     HashSet<Observer*> m_observers;
+
+    mutable RecursiveLock m_audioSampleObserversLock;
+    HashSet<AudioSampleObserver*> m_audioSampleObservers;
+
     IntSize m_size;
     IntSize m_intrinsicSize;
     double m_frameRate { 30 };
@@ -272,6 +284,7 @@
     bool m_interrupted { false };
     bool m_captureDidFailed { false };
     bool m_isEnded { false };
+    bool m_hasSentStartProducedAudioData { false };
 };
 
 struct CaptureSourceOrError {

Modified: trunk/Source/WebCore/platform/mediastream/RealtimeOutgoingAudioSource.cpp (259815 => 259816)


--- trunk/Source/WebCore/platform/mediastream/RealtimeOutgoingAudioSource.cpp	2020-04-09 19:42:02 UTC (rev 259815)
+++ trunk/Source/WebCore/platform/mediastream/RealtimeOutgoingAudioSource.cpp	2020-04-09 19:44:21 UTC (rev 259816)
@@ -45,7 +45,7 @@
 
 RealtimeOutgoingAudioSource::~RealtimeOutgoingAudioSource()
 {
-ASSERT(!m_audioSource->hasObserver(*this));
+    ASSERT(!m_audioSource->hasObserver(*this));
 #if ASSERT_ENABLED
     auto locker = holdLock(m_sinksLock);
 #endif
@@ -58,11 +58,13 @@
 {
     ASSERT(!m_audioSource->hasObserver(*this));
     m_audioSource->addObserver(*this);
+    m_audioSource->source().addAudioSampleObserver(*this);
     initializeConverter();
 }
 
 void RealtimeOutgoingAudioSource::unobserveSource()
 {
+    m_audioSource->source().removeAudioSampleObserver(*this);
     m_audioSource->removeObserver(*this);
 }
 

Modified: trunk/Source/WebCore/platform/mediastream/RealtimeOutgoingAudioSource.h (259815 => 259816)


--- trunk/Source/WebCore/platform/mediastream/RealtimeOutgoingAudioSource.h	2020-04-09 19:42:02 UTC (rev 259815)
+++ trunk/Source/WebCore/platform/mediastream/RealtimeOutgoingAudioSource.h	2020-04-09 19:44:21 UTC (rev 259816)
@@ -55,6 +55,7 @@
     : public ThreadSafeRefCounted<RealtimeOutgoingAudioSource, WTF::DestructionThread::Main>
     , public webrtc::AudioSourceInterface
     , private MediaStreamTrackPrivate::Observer
+    , private RealtimeMediaSource::AudioSampleObserver
 #if !RELEASE_LOG_DISABLED
     , private LoggerHelper
 #endif
@@ -108,7 +109,6 @@
 
     void sourceMutedChanged();
     void sourceEnabledChanged();
-    virtual void audioSamplesAvailable(const MediaTime&, const PlatformAudioData&, const AudioStreamDescription&, size_t) { };
 
     virtual bool isReachingBufferedAudioDataHighLimit() { return false; };
     virtual bool isReachingBufferedAudioDataLowLimit() { return false; };
@@ -118,7 +118,6 @@
     // MediaStreamTrackPrivate::Observer API
     void trackMutedChanged(MediaStreamTrackPrivate&) final { sourceMutedChanged(); }
     void trackEnabledChanged(MediaStreamTrackPrivate&) final { sourceEnabledChanged(); }
-    void audioSamplesAvailable(MediaStreamTrackPrivate&, const MediaTime& mediaTime, const PlatformAudioData& data, const AudioStreamDescription& description, size_t sampleCount) { audioSamplesAvailable(mediaTime, data, description, sampleCount); }
     void trackEnded(MediaStreamTrackPrivate&) final { }
     void trackSettingsChanged(MediaStreamTrackPrivate&) final { }
 

Modified: trunk/Source/WebCore/platform/mediastream/WebAudioSourceProvider.h (259815 => 259816)


--- trunk/Source/WebCore/platform/mediastream/WebAudioSourceProvider.h	2020-04-09 19:42:02 UTC (rev 259815)
+++ trunk/Source/WebCore/platform/mediastream/WebAudioSourceProvider.h	2020-04-09 19:44:21 UTC (rev 259816)
@@ -32,7 +32,7 @@
 
 namespace WebCore {
 
-class WebAudioSourceProvider : public ThreadSafeRefCounted<WebAudioSourceProvider>, public AudioSourceProvider {
+class WebAudioSourceProvider : public ThreadSafeRefCounted<WebAudioSourceProvider, WTF::DestructionThread::Main>, public AudioSourceProvider {
 };
 
 }

Modified: trunk/Source/WebCore/platform/mediastream/gstreamer/GStreamerMediaStreamSource.cpp (259815 => 259816)


--- trunk/Source/WebCore/platform/mediastream/gstreamer/GStreamerMediaStreamSource.cpp	2020-04-09 19:42:02 UTC (rev 259815)
+++ trunk/Source/WebCore/platform/mediastream/gstreamer/GStreamerMediaStreamSource.cpp	2020-04-09 19:44:21 UTC (rev 259816)
@@ -106,7 +106,8 @@
 }
 
 class WebKitMediaStreamTrackObserver
-    : public MediaStreamTrackPrivate::Observer {
+    : public MediaStreamTrackPrivate::Observer
+    , public RealtimeMediaSource::AudioSampleObserver {
     WTF_MAKE_FAST_ALLOCATED;
 public:
     virtual ~WebKitMediaStreamTrackObserver() { };
@@ -131,7 +132,7 @@
         webkitMediaStreamSrcPushVideoSample(m_mediaStreamSrc, gstsample);
     }
 
-    void audioSamplesAvailable(MediaStreamTrackPrivate&, const MediaTime&, const PlatformAudioData& audioData, const AudioStreamDescription&, size_t) final
+    void audioSamplesAvailable(const MediaTime&, const PlatformAudioData& audioData, const AudioStreamDescription&, size_t) final
     {
         auto audiodata = static_cast<const GStreamerAudioData&>(audioData);
 
@@ -375,9 +376,10 @@
 
     GST_OBJECT_LOCK(self);
     if (self->stream) {
-        for (auto& track : self->stream->tracks())
+        for (auto& track : self->stream->tracks()) {
+            track->source().removeAudioSampleObserver(*self->mediaStreamTrackObserver.get());
             track->removeObserver(*self->mediaStreamTrackObserver.get());
-
+        }
         self->stream->removeObserver(*self->mediaStreamObserver);
         self->stream = nullptr;
     }
@@ -396,10 +398,14 @@
 
         GST_OBJECT_LOCK(self);
         if (self->stream) {
-            for (auto& track : self->stream->tracks())
+            for (auto& track : self->stream->tracks()) {
+                track->source().removeAudioSampleObserver(*self->mediaStreamTrackObserver.get());
                 track->removeObserver(*self->mediaStreamTrackObserver.get());
-        } else if (self->track)
+            }
+        } else if (self->track) {
+            self->track->source().removeAudioSampleObserver(*self->mediaStreamTrackObserver.get());
             self->track->removeObserver(*self->mediaStreamTrackObserver.get());
+        }
         GST_OBJECT_UNLOCK(self);
     }
 
@@ -543,9 +549,10 @@
     } else
         webkitMediaStreamSrcAddPad(self, pad.get(), pad_template);
 
-    if (observe_track)
+    if (observe_track) {
         track->addObserver(*self->mediaStreamTrackObserver.get());
-
+        track->source().addAudioSampleObserver(*self->mediaStreamTrackObserver.get());
+    }
     gst_element_sync_state_with_parent(element);
     return TRUE;
 }

Modified: trunk/Source/WebCore/platform/mediastream/mac/WebAudioSourceProviderAVFObjC.h (259815 => 259816)


--- trunk/Source/WebCore/platform/mediastream/mac/WebAudioSourceProviderAVFObjC.h	2020-04-09 19:42:02 UTC (rev 259815)
+++ trunk/Source/WebCore/platform/mediastream/mac/WebAudioSourceProviderAVFObjC.h	2020-04-09 19:44:21 UTC (rev 259816)
@@ -46,7 +46,10 @@
 class AudioSampleDataSource;
 class CAAudioStreamDescription;
 
-class WEBCORE_EXPORT WebAudioSourceProviderAVFObjC final : public WebAudioSourceProvider, MediaStreamTrackPrivate::Observer {
+class WEBCORE_EXPORT WebAudioSourceProviderAVFObjC final
+    : public WebAudioSourceProvider
+    , MediaStreamTrackPrivate::Observer
+    , RealtimeMediaSource::AudioSampleObserver {
 public:
     static Ref<WebAudioSourceProviderAVFObjC> create(MediaStreamTrackPrivate&);
     virtual ~WebAudioSourceProviderAVFObjC();
@@ -62,12 +65,14 @@
     void setClient(AudioSourceProviderClient*) final;
 
     // MediaStreamTrackPrivate::Observer
-    void audioSamplesAvailable(MediaStreamTrackPrivate&, const MediaTime&, const PlatformAudioData&, const AudioStreamDescription&, size_t) final;
     void trackEnded(MediaStreamTrackPrivate&) final { }
     void trackMutedChanged(MediaStreamTrackPrivate&) final { }
     void trackSettingsChanged(MediaStreamTrackPrivate&) final { }
-    void trackEnabledChanged(MediaStreamTrackPrivate&) final { }
+    void trackEnabledChanged(MediaStreamTrackPrivate&) final;
 
+    // RealtimeMediaSource::AudioSampleObserver
+    void audioSamplesAvailable(const MediaTime&, const PlatformAudioData&, const AudioStreamDescription&, size_t) final;
+
     size_t m_listBufferSize { 0 };
     Optional<CAAudioStreamDescription> m_inputDescription;
     Optional<CAAudioStreamDescription> m_outputDescription;
@@ -77,8 +82,10 @@
     uint64_t m_readCount { 0 };
     AudioSourceProviderClient* m_client { nullptr };
     MediaStreamTrackPrivate* m_captureSource { nullptr };
+    Ref<RealtimeMediaSource> m_source;
     Lock m_mutex;
     bool m_connected { false };
+    bool m_enabled { true };
 };
 
 }

Modified: trunk/Source/WebCore/platform/mediastream/mac/WebAudioSourceProviderAVFObjC.mm (259815 => 259816)


--- trunk/Source/WebCore/platform/mediastream/mac/WebAudioSourceProviderAVFObjC.mm	2020-04-09 19:42:02 UTC (rev 259815)
+++ trunk/Source/WebCore/platform/mediastream/mac/WebAudioSourceProviderAVFObjC.mm	2020-04-09 19:44:21 UTC (rev 259816)
@@ -54,11 +54,16 @@
 
 WebAudioSourceProviderAVFObjC::WebAudioSourceProviderAVFObjC(MediaStreamTrackPrivate& source)
     : m_captureSource(&source)
+    , m_source(source.source())
+    , m_enabled(source.enabled())
 {
+    m_source->addAudioSampleObserver(*this);
 }
 
 WebAudioSourceProviderAVFObjC::~WebAudioSourceProviderAVFObjC()
 {
+    m_source->removeAudioSampleObserver(*this);
+
     auto locker = holdLock(m_mutex);
 
     if (m_connected && m_captureSource)
@@ -165,10 +170,15 @@
     }
 }
 
+void WebAudioSourceProviderAVFObjC::trackEnabledChanged(MediaStreamTrackPrivate& track)
+{
+    m_enabled = track.enabled();
+}
+
 // May get called on a background thread.
-void WebAudioSourceProviderAVFObjC::audioSamplesAvailable(MediaStreamTrackPrivate& track, const MediaTime&, const PlatformAudioData& data, const AudioStreamDescription& description, size_t frameCount)
+void WebAudioSourceProviderAVFObjC::audioSamplesAvailable(const MediaTime&, const PlatformAudioData& data, const AudioStreamDescription& description, size_t frameCount)
 {
-    if (!track.enabled())
+    if (!m_enabled || !m_connected)
         return;
 
     ASSERT(description.platformDescription().type == PlatformDescription::CAAudioStreamBasicType);

Modified: trunk/Source/WebCore/testing/Internals.cpp (259815 => 259816)


--- trunk/Source/WebCore/testing/Internals.cpp	2020-04-09 19:42:02 UTC (rev 259815)
+++ trunk/Source/WebCore/testing/Internals.cpp	2020-04-09 19:44:21 UTC (rev 259816)
@@ -466,8 +466,10 @@
 Internals::~Internals()
 {
 #if ENABLE(MEDIA_STREAM)
-    if (m_track)
-        m_track->source().removeObserver(*this);
+    if (m_trackSource) {
+        m_trackSource->removeObserver(*this);
+        m_trackSource->removeAudioSampleObserver(*this);
+    }
 #endif
 }
 
@@ -1639,9 +1641,9 @@
         page->settings().setMediaCaptureRequiresSecureConnection(enabled);
 }
 
-static std::unique_ptr<MediaRecorderPrivate> createRecorderMockSource()
+static std::unique_ptr<MediaRecorderPrivate> createRecorderMockSource(MediaStreamPrivate& stream)
 {
-    return std::unique_ptr<MediaRecorderPrivateMock>(new MediaRecorderPrivateMock);
+    return std::unique_ptr<MediaRecorderPrivateMock>(new MediaRecorderPrivateMock(stream));
 }
 
 void Internals::setCustomPrivateRecorderCreator()
@@ -4925,8 +4927,9 @@
 
 void Internals::observeMediaStreamTrack(MediaStreamTrack& track)
 {
-    m_track = &track;
-    m_track->source().addObserver(*this);
+    m_trackSource = &track.source();
+    m_trackSource->addObserver(*this);
+    m_trackSource->addAudioSampleObserver(*this);
 }
 
 void Internals::grabNextMediaStreamTrackFrame(TrackFramePromise&& promise)
@@ -4940,7 +4943,7 @@
     if (!m_nextTrackFramePromise)
         return;
 
-    auto& videoSettings = m_track->source().settings();
+    auto& videoSettings = m_trackSource->settings();
     if (!videoSettings.width() || !videoSettings.height())
         return;
     

Modified: trunk/Source/WebCore/testing/Internals.h (259815 => 259816)


--- trunk/Source/WebCore/testing/Internals.h	2020-04-09 19:42:02 UTC (rev 259815)
+++ trunk/Source/WebCore/testing/Internals.h	2020-04-09 19:44:21 UTC (rev 259816)
@@ -123,6 +123,7 @@
 class Internals final : public RefCounted<Internals>, private ContextDestructionObserver
 #if ENABLE(MEDIA_STREAM)
     , private RealtimeMediaSource::Observer
+    , private RealtimeMediaSource::AudioSampleObserver
 #endif
     {
 public:
@@ -969,15 +970,16 @@
 
     ExceptionOr<RenderedDocumentMarker*> markerAt(Node&, const String& markerType, unsigned index);
 
+#if ENABLE(MEDIA_STREAM)
     // RealtimeMediaSource::Observer API
-#if ENABLE(MEDIA_STREAM)
     void videoSampleAvailable(MediaSample&) final;
+    // RealtimeMediaSource::AudioSampleObserver API
     void audioSamplesAvailable(const MediaTime&, const PlatformAudioData&, const AudioStreamDescription&, size_t) final { m_trackAudioSampleCount++; }
 
     OrientationNotifier m_orientationNotifier;
     unsigned long m_trackVideoSampleCount { 0 };
     unsigned long m_trackAudioSampleCount { 0 };
-    RefPtr<MediaStreamTrack> m_track;
+    RefPtr<RealtimeMediaSource> m_trackSource;
     std::unique_ptr<TrackFramePromise> m_nextTrackFramePromise;
 #endif
 

Modified: trunk/Source/WebKit/ChangeLog (259815 => 259816)


--- trunk/Source/WebKit/ChangeLog	2020-04-09 19:42:02 UTC (rev 259815)
+++ trunk/Source/WebKit/ChangeLog	2020-04-09 19:44:21 UTC (rev 259816)
@@ -1,3 +1,27 @@
+2020-04-09  Youenn Fablet  <you...@apple.com>
+
+        Introduce a RealtimeMediaSource observer dedicated to receiving audio samples
+        https://bugs.webkit.org/show_bug.cgi?id=210180
+
+        Reviewed by Eric Carlson.
+
+        Update SourceProxy to be an AudioSampleObserver.
+        Update MediaRecorder to only listen for audio samples if GPU remote writer is successfully created.
+        It also stops listening to audio samples as soon as stopping the recording.
+
+        * UIProcess/Cocoa/UserMediaCaptureManagerProxy.cpp:
+        (WebKit::UserMediaCaptureManagerProxy::SourceProxy::SourceProxy):
+        (WebKit::UserMediaCaptureManagerProxy::SourceProxy::~SourceProxy):
+        * WebProcess/GPU/webrtc/MediaRecorderPrivate.cpp:
+        (WebKit::MediaRecorderPrivate::MediaRecorderPrivate):
+        (WebKit::MediaRecorderPrivate::~MediaRecorderPrivate):
+        (WebKit::MediaRecorderPrivate::audioSamplesAvailable):
+        (WebKit::MediaRecorderPrivate::stopRecording):
+        * WebProcess/GPU/webrtc/MediaRecorderPrivate.h:
+        * WebProcess/GPU/webrtc/MediaRecorderProvider.cpp:
+        (WebKit::MediaRecorderProvider::createMediaRecorderPrivate):
+        * WebProcess/GPU/webrtc/MediaRecorderProvider.h:
+
 2020-04-09  David Kilzer  <ddkil...@apple.com>
 
         WTF::Persistence::Coder and WTF::Persistence::Decoder should use WARN_UNUSED_RETURN

Modified: trunk/Source/WebKit/UIProcess/Cocoa/UserMediaCaptureManagerProxy.cpp (259815 => 259816)


--- trunk/Source/WebKit/UIProcess/Cocoa/UserMediaCaptureManagerProxy.cpp	2020-04-09 19:42:02 UTC (rev 259815)
+++ trunk/Source/WebKit/UIProcess/Cocoa/UserMediaCaptureManagerProxy.cpp	2020-04-09 19:44:21 UTC (rev 259816)
@@ -50,6 +50,7 @@
 
 class UserMediaCaptureManagerProxy::SourceProxy
     : public RealtimeMediaSource::Observer
+    , public RealtimeMediaSource::AudioSampleObserver
     , public SharedRingBufferStorage::Client {
     WTF_MAKE_FAST_ALLOCATED;
 public:
@@ -60,11 +61,13 @@
         , m_ringBuffer(makeUniqueRef<SharedRingBufferStorage>(makeUniqueRef<SharedRingBufferStorage>(this)))
     {
         m_source->addObserver(*this);
+        m_source->addAudioSampleObserver(*this);
     }
 
     ~SourceProxy()
     {
         storage().invalidate();
+        m_source->removeAudioSampleObserver(*this);
         m_source->removeObserver(*this);
     }
 

Modified: trunk/Source/WebKit/WebProcess/GPU/webrtc/MediaRecorderPrivate.cpp (259815 => 259816)


--- trunk/Source/WebKit/WebProcess/GPU/webrtc/MediaRecorderPrivate.cpp	2020-04-09 19:42:02 UTC (rev 259815)
+++ trunk/Source/WebKit/WebProcess/GPU/webrtc/MediaRecorderPrivate.cpp	2020-04-09 19:44:21 UTC (rev 259816)
@@ -43,7 +43,7 @@
 namespace WebKit {
 using namespace WebCore;
 
-MediaRecorderPrivate::MediaRecorderPrivate(const MediaStreamPrivate& stream)
+MediaRecorderPrivate::MediaRecorderPrivate(MediaStreamPrivate& stream)
     : m_identifier(MediaRecorderIdentifier::generate())
     , m_connection(WebProcess::singleton().ensureGPUProcessConnection().connection())
 {
@@ -64,15 +64,19 @@
         width = selectedTracks.videoTrack->settings().width();
     }
 
-    m_connection->sendWithAsyncReply(Messages::RemoteMediaRecorderManager::CreateRecorder { m_identifier, !!selectedTracks.audioTrack, width, height }, [this, weakThis = makeWeakPtr(this)](auto&& exception) {
-        if (!weakThis || !exception)
+    m_connection->sendWithAsyncReply(Messages::RemoteMediaRecorderManager::CreateRecorder { m_identifier, !!selectedTracks.audioTrack, width, height }, [this, weakThis = makeWeakPtr(this), audioTrack = makeRefPtr(selectedTracks.audioTrack)](auto&& exception) {
+        if (!weakThis)
             return;
-        m_errorCallback(Exception { exception->code, WTFMove(exception->message) });
+        if (exception)
+            return m_errorCallback(Exception { exception->code, WTFMove(exception->message) });
+        if (audioTrack)
+            setAudioSource(&audioTrack->source());
     }, 0);
 }
 
 MediaRecorderPrivate::~MediaRecorderPrivate()
 {
+    setAudioSource(nullptr);
     m_connection->send(Messages::RemoteMediaRecorderManager::ReleaseRecorder { m_identifier }, 0);
 }
 
@@ -88,11 +92,8 @@
 #endif
 }
 
-void MediaRecorderPrivate::audioSamplesAvailable(const WebCore::MediaStreamTrackPrivate& track, const MediaTime& time, const PlatformAudioData& audioData, const AudioStreamDescription& description, size_t numberOfFrames)
+void MediaRecorderPrivate::audioSamplesAvailable(const MediaTime& time, const PlatformAudioData& audioData, const AudioStreamDescription& description, size_t numberOfFrames)
 {
-    if (track.id() != m_recordedAudioTrackID)
-        return;
-
     if (m_description != description) {
         ASSERT(description.platformDescription().type == PlatformDescription::CAAudioStreamBasicType);
         m_description = *WTF::get<const AudioStreamBasicDescription*>(description.platformDescription().description);
@@ -130,6 +131,7 @@
 
 void MediaRecorderPrivate::stopRecording()
 {
+    setAudioSource(nullptr);
     m_connection->send(Messages::RemoteMediaRecorder::StopRecording { }, m_identifier);
 }
 

Modified: trunk/Source/WebKit/WebProcess/GPU/webrtc/MediaRecorderPrivate.h (259815 => 259816)


--- trunk/Source/WebKit/WebProcess/GPU/webrtc/MediaRecorderPrivate.h	2020-04-09 19:42:02 UTC (rev 259815)
+++ trunk/Source/WebKit/WebProcess/GPU/webrtc/MediaRecorderPrivate.h	2020-04-09 19:44:21 UTC (rev 259816)
@@ -44,18 +44,21 @@
 
 namespace WebKit {
 
-class MediaRecorderPrivate final : public WebCore::MediaRecorderPrivate, public SharedRingBufferStorage::Client, public CanMakeWeakPtr<MediaRecorderPrivate> {
+class MediaRecorderPrivate final
+    : public WebCore::MediaRecorderPrivate
+    , public SharedRingBufferStorage::Client
+    , public CanMakeWeakPtr<MediaRecorderPrivate> {
     WTF_MAKE_FAST_ALLOCATED;
 public:
-    explicit MediaRecorderPrivate(const WebCore::MediaStreamPrivate&);
+    explicit MediaRecorderPrivate(WebCore::MediaStreamPrivate&);
     ~MediaRecorderPrivate();
 
 private:
     // WebCore::MediaRecorderPrivate
     void sampleBufferUpdated(const WebCore::MediaStreamTrackPrivate&, WebCore::MediaSample&) final;
-    void audioSamplesAvailable(const WebCore::MediaStreamTrackPrivate&, const WTF::MediaTime&, const WebCore::PlatformAudioData&, const WebCore::AudioStreamDescription&, size_t) final;
     void fetchData(CompletionHandler<void(RefPtr<WebCore::SharedBuffer>&&, const String& mimeType)>&&) final;
     void stopRecording() final;
+    void audioSamplesAvailable(const WTF::MediaTime&, const WebCore::PlatformAudioData&, const WebCore::AudioStreamDescription&, size_t) final;
 
     // SharedRingBufferStorage::Client
     void storageChanged(SharedMemory*);

Modified: trunk/Source/WebKit/WebProcess/GPU/webrtc/MediaRecorderProvider.cpp (259815 => 259816)


--- trunk/Source/WebKit/WebProcess/GPU/webrtc/MediaRecorderProvider.cpp	2020-04-09 19:42:02 UTC (rev 259815)
+++ trunk/Source/WebKit/WebProcess/GPU/webrtc/MediaRecorderProvider.cpp	2020-04-09 19:44:21 UTC (rev 259816)
@@ -34,7 +34,7 @@
 namespace WebKit {
 using namespace WebCore;
 
-std::unique_ptr<WebCore::MediaRecorderPrivate> MediaRecorderProvider::createMediaRecorderPrivate(const MediaStreamPrivate& stream)
+std::unique_ptr<WebCore::MediaRecorderPrivate> MediaRecorderProvider::createMediaRecorderPrivate(MediaStreamPrivate& stream)
 {
 #if ENABLE(GPU_PROCESS)
     if (m_useGPUProcess)

Modified: trunk/Source/WebKit/WebProcess/GPU/webrtc/MediaRecorderProvider.h (259815 => 259816)


--- trunk/Source/WebKit/WebProcess/GPU/webrtc/MediaRecorderProvider.h	2020-04-09 19:42:02 UTC (rev 259815)
+++ trunk/Source/WebKit/WebProcess/GPU/webrtc/MediaRecorderProvider.h	2020-04-09 19:44:21 UTC (rev 259816)
@@ -35,7 +35,7 @@
 
 private:
 #if ENABLE(MEDIA_STREAM) && PLATFORM(COCOA)
-    std::unique_ptr<WebCore::MediaRecorderPrivate> createMediaRecorderPrivate(const WebCore::MediaStreamPrivate&) final;
+    std::unique_ptr<WebCore::MediaRecorderPrivate> createMediaRecorderPrivate(WebCore::MediaStreamPrivate&) final;
 #endif
 };
 
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to