Title: [285027] trunk/Source/WebCore
Revision
285027
Author
[email protected]
Date
2021-10-29 06:36:03 -0700 (Fri, 29 Oct 2021)

Log Message

Ensure synchronized rendering of incoming audio tracks
https://bugs.webkit.org/show_bug.cgi?id=232375

Reviewed by Eric Carlson.

WebRTC incoming audio tracks are guaranteed to be synchronized based on the audio module clock.
Previously, we were mixing all audio tracks together, but we were not handling synchronization of tracks that have the same clock.
This can cause some lower quality audio rendering.
To prevent this, all WebRTC incoming audio tracks are now mixed together in a single track that is then mixed with all other non synchronized tracks.
To do so we introduce IncomingAudioMediaStreamTrackRendererUnit which will receive all incoming audio tracks.
It then sends the mix to the actual AudioMediaStreamTrackRendererUnit.
To ensure tight synchronization, we introduce AudioSampleDataSource::pullAvailableSampleChunk which reads data using the provided timestamp relative to the input offset.
We do a refactoring to make it easy to either use IncomingAudioMediaStreamTrackRendererUnit or AudioMediaStreamTrackRendererUnit by having a base class called BaseAudioMediaStreamTrackRendererUnit.

Manually tested.

* Modules/mediastream/libwebrtc/LibWebRTCPeerConnectionBackend.cpp:
* Modules/mediastream/libwebrtc/LibWebRTCRtpReceiverBackend.cpp:
* Modules/mediastream/libwebrtc/LibWebRTCRtpReceiverBackend.h:
* SourcesCocoa.txt:
* WebCore.xcodeproj/project.pbxproj:
* loader/EmptyClients.cpp:
* platform/audio/cocoa/AudioSampleDataSource.h:
* platform/audio/cocoa/AudioSampleDataSource.mm:
* platform/mediastream/AudioMediaStreamTrackRenderer.cpp:
* platform/mediastream/AudioMediaStreamTrackRenderer.h:
* platform/mediastream/AudioTrackPrivateMediaStream.cpp:
* platform/mediastream/RealtimeIncomingAudioSource.cpp:
* platform/mediastream/RealtimeIncomingAudioSource.h:
* platform/mediastream/cocoa/AudioMediaStreamTrackRendererCocoa.cpp:
* platform/mediastream/cocoa/AudioMediaStreamTrackRendererCocoa.h:
* platform/mediastream/cocoa/AudioMediaStreamTrackRendererUnit.h:
* platform/mediastream/cocoa/BaseAudioMediaStreamTrackRendererUnit.h: Added.
* platform/mediastream/cocoa/IncomingAudioMediaStreamTrackRendererUnit.cpp: Added.
* platform/mediastream/cocoa/IncomingAudioMediaStreamTrackRendererUnit.h: Added.
* platform/mediastream/libwebrtc/LibWebRTCAudioModule.cpp:
* platform/mediastream/libwebrtc/LibWebRTCAudioModule.h:
* platform/mediastream/libwebrtc/LibWebRTCProvider.cpp:
* platform/mediastream/libwebrtc/LibWebRTCProvider.h:
* platform/mediastream/mac/RealtimeIncomingAudioSourceCocoa.cpp:

Modified Paths

Added Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (285026 => 285027)


--- trunk/Source/WebCore/ChangeLog	2021-10-29 13:04:17 UTC (rev 285026)
+++ trunk/Source/WebCore/ChangeLog	2021-10-29 13:36:03 UTC (rev 285027)
@@ -1,5 +1,48 @@
 2021-10-29  Youenn Fablet  <[email protected]>
 
+        Ensure synchronized rendering of incoming audio tracks
+        https://bugs.webkit.org/show_bug.cgi?id=232375
+
+        Reviewed by Eric Carlson.
+
+        WebRTC incoming audio tracks are guaranteed to be synchronized based on the audio module clock.
+        Previously, we were mixing all audio tracks together, but we were not handling synchronization of tracks that have the same clock.
+        This can cause some lower quality audio rendering.
+        To prevent this, all WebRTC incoming audio tracks are now mixed together in a single track that is then mixed with all other non synchronized tracks.
+        To do so we introduce IncomingAudioMediaStreamTrackRendererUnit which will receive all incoming audio tracks.
+        It then sends the mix to the actual AudioMediaStreamTrackRendererUnit.
+        To ensure tight synchronization, we introduce AudioSampleDataSource::pullAvailableSampleChunk which reads data using the provided timestamp relative to the input offset.
+        We do a refactoring to make it easy to either use IncomingAudioMediaStreamTrackRendererUnit or AudioMediaStreamTrackRendererUnit by having a base class called BaseAudioMediaStreamTrackRendererUnit.
+
+        Manually tested.
+
+        * Modules/mediastream/libwebrtc/LibWebRTCPeerConnectionBackend.cpp:
+        * Modules/mediastream/libwebrtc/LibWebRTCRtpReceiverBackend.cpp:
+        * Modules/mediastream/libwebrtc/LibWebRTCRtpReceiverBackend.h:
+        * SourcesCocoa.txt:
+        * WebCore.xcodeproj/project.pbxproj:
+        * loader/EmptyClients.cpp:
+        * platform/audio/cocoa/AudioSampleDataSource.h:
+        * platform/audio/cocoa/AudioSampleDataSource.mm:
+        * platform/mediastream/AudioMediaStreamTrackRenderer.cpp:
+        * platform/mediastream/AudioMediaStreamTrackRenderer.h:
+        * platform/mediastream/AudioTrackPrivateMediaStream.cpp:
+        * platform/mediastream/RealtimeIncomingAudioSource.cpp:
+        * platform/mediastream/RealtimeIncomingAudioSource.h:
+        * platform/mediastream/cocoa/AudioMediaStreamTrackRendererCocoa.cpp:
+        * platform/mediastream/cocoa/AudioMediaStreamTrackRendererCocoa.h:
+        * platform/mediastream/cocoa/AudioMediaStreamTrackRendererUnit.h:
+        * platform/mediastream/cocoa/BaseAudioMediaStreamTrackRendererUnit.h: Added.
+        * platform/mediastream/cocoa/IncomingAudioMediaStreamTrackRendererUnit.cpp: Added.
+        * platform/mediastream/cocoa/IncomingAudioMediaStreamTrackRendererUnit.h: Added.
+        * platform/mediastream/libwebrtc/LibWebRTCAudioModule.cpp:
+        * platform/mediastream/libwebrtc/LibWebRTCAudioModule.h:
+        * platform/mediastream/libwebrtc/LibWebRTCProvider.cpp:
+        * platform/mediastream/libwebrtc/LibWebRTCProvider.h:
+        * platform/mediastream/mac/RealtimeIncomingAudioSourceCocoa.cpp:
+
+2021-10-29  Youenn Fablet  <[email protected]>
+
         Fix potential race in AudioMediaStreamTrackRendererCocoa::pushSamples
         https://bugs.webkit.org/show_bug.cgi?id=232430
 

Modified: trunk/Source/WebCore/Modules/mediastream/libwebrtc/LibWebRTCPeerConnectionBackend.cpp (285026 => 285027)


--- trunk/Source/WebCore/Modules/mediastream/libwebrtc/LibWebRTCPeerConnectionBackend.cpp	2021-10-29 13:04:17 UTC (rev 285026)
+++ trunk/Source/WebCore/Modules/mediastream/libwebrtc/LibWebRTCPeerConnectionBackend.cpp	2021-10-29 13:36:03 UTC (rev 285027)
@@ -29,8 +29,10 @@
 
 #include "Document.h"
 #include "IceCandidate.h"
+#include "LibWebRTCAudioModule.h"
 #include "LibWebRTCDataChannelHandler.h"
 #include "LibWebRTCMediaEndpoint.h"
+#include "LibWebRTCProvider.h"
 #include "LibWebRTCRtpReceiverBackend.h"
 #include "LibWebRTCRtpSenderBackend.h"
 #include "LibWebRTCRtpTransceiverBackend.h"
@@ -293,7 +295,8 @@
 {
     auto& document = downcast<Document>(*m_peerConnection.scriptExecutionContext());
 
-    auto source = backend->createSource();
+    auto source = backend->createSource(document);
+
     // Remote source is initially muted and will be unmuted when receiving the first packet.
     source->setMuted(true);
     auto trackID = source->persistentID();

Modified: trunk/Source/WebCore/Modules/mediastream/libwebrtc/LibWebRTCRtpReceiverBackend.cpp (285026 => 285027)


--- trunk/Source/WebCore/Modules/mediastream/libwebrtc/LibWebRTCRtpReceiverBackend.cpp	2021-10-29 13:04:17 UTC (rev 285026)
+++ trunk/Source/WebCore/Modules/mediastream/libwebrtc/LibWebRTCRtpReceiverBackend.cpp	2021-10-29 13:36:03 UTC (rev 285027)
@@ -25,9 +25,13 @@
 #include "config.h"
 #include "LibWebRTCRtpReceiverBackend.h"
 
+#include "Document.h"
+#include "LibWebRTCAudioModule.h"
 #include "LibWebRTCDtlsTransportBackend.h"
+#include "LibWebRTCProvider.h"
 #include "LibWebRTCRtpReceiverTransformBackend.h"
 #include "LibWebRTCUtils.h"
+#include "Page.h"
 #include "RTCRtpTransformBackend.h"
 #include "RealtimeIncomingAudioSource.h"
 #include "RealtimeIncomingVideoSource.h"
@@ -99,7 +103,7 @@
     return sources;
 }
 
-Ref<RealtimeMediaSource> LibWebRTCRtpReceiverBackend::createSource()
+Ref<RealtimeMediaSource> LibWebRTCRtpReceiverBackend::createSource(Document& document)
 {
     auto rtcTrack = m_rtcReceiver->track();
     switch (m_rtcReceiver->media_type()) {
@@ -108,7 +112,10 @@
         break;
     case cricket::MEDIA_TYPE_AUDIO: {
         rtc::scoped_refptr<webrtc::AudioTrackInterface> audioTrack = static_cast<webrtc::AudioTrackInterface*>(rtcTrack.get());
-        return RealtimeIncomingAudioSource::create(WTFMove(audioTrack), fromStdString(rtcTrack->id()));
+        auto source = RealtimeIncomingAudioSource::create(WTFMove(audioTrack), fromStdString(rtcTrack->id()));
+        if (document.page())
+            source->setAudioModule(document.page()->libWebRTCProvider().audioModule());
+        return source;
     }
     case cricket::MEDIA_TYPE_VIDEO: {
         rtc::scoped_refptr<webrtc::VideoTrackInterface> videoTrack = static_cast<webrtc::VideoTrackInterface*>(rtcTrack.get());

Modified: trunk/Source/WebCore/Modules/mediastream/libwebrtc/LibWebRTCRtpReceiverBackend.h (285026 => 285027)


--- trunk/Source/WebCore/Modules/mediastream/libwebrtc/LibWebRTCRtpReceiverBackend.h	2021-10-29 13:04:17 UTC (rev 285026)
+++ trunk/Source/WebCore/Modules/mediastream/libwebrtc/LibWebRTCRtpReceiverBackend.h	2021-10-29 13:36:03 UTC (rev 285027)
@@ -35,7 +35,7 @@
 }
 
 namespace WebCore {
-
+class Document;
 class RealtimeMediaSource;
 
 class LibWebRTCRtpReceiverBackend final : public RTCRtpReceiverBackend {
@@ -46,7 +46,7 @@
 
     webrtc::RtpReceiverInterface* rtcReceiver() { return m_rtcReceiver.get(); }
 
-    Ref<RealtimeMediaSource> createSource();
+    Ref<RealtimeMediaSource> createSource(Document&);
 
 private:
     RTCRtpParameters getParameters() final;

Modified: trunk/Source/WebCore/SourcesCocoa.txt (285026 => 285027)


--- trunk/Source/WebCore/SourcesCocoa.txt	2021-10-29 13:04:17 UTC (rev 285026)
+++ trunk/Source/WebCore/SourcesCocoa.txt	2021-10-29 13:36:03 UTC (rev 285027)
@@ -526,6 +526,7 @@
 platform/mediastream/cocoa/AudioMediaStreamTrackRendererInternalUnit.cpp
 platform/mediastream/cocoa/AudioMediaStreamTrackRendererUnit.cpp
 platform/mediastream/cocoa/DisplayCaptureSourceCocoa.cpp
+platform/mediastream/cocoa/IncomingAudioMediaStreamTrackRendererUnit.cpp
 platform/mediastream/ios/AVAudioSessionCaptureDevice.mm
 platform/mediastream/ios/AVAudioSessionCaptureDeviceManager.mm @no-unify
 platform/mediastream/ios/CoreAudioCaptureSourceIOS.mm

Modified: trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj (285026 => 285027)


--- trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj	2021-10-29 13:04:17 UTC (rev 285026)
+++ trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj	2021-10-29 13:36:03 UTC (rev 285027)
@@ -1180,6 +1180,7 @@
 		4186BD3F213EE3430001826F /* LibWebRTCRtpSenderBackend.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 41D1A04B213EDDFE0063FB6B /* LibWebRTCRtpSenderBackend.cpp */; };
 		4186BD40213EE3450001826F /* LibWebRTCRtpReceiverBackend.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 41D1A04A213EDDFE0063FB6B /* LibWebRTCRtpReceiverBackend.cpp */; };
 		4186BD4E2140B9E80001826F /* LibWebRTCRtpTransceiverBackend.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4186BD4D2140B9E80001826F /* LibWebRTCRtpTransceiverBackend.cpp */; };
+		41878FAD27294721002E1EDD /* BaseAudioMediaStreamTrackRendererUnit.h in Headers */ = {isa = PBXBuildFile; fileRef = 41878FA827282055002E1EDD /* BaseAudioMediaStreamTrackRendererUnit.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		41885B9311B6FDA6003383BB /* FormSubmission.h in Headers */ = {isa = PBXBuildFile; fileRef = 41885B9111B6FDA6003383BB /* FormSubmission.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		4188D55C26C54D6F004858C8 /* RTCDtlsTransportBackend.h in Headers */ = {isa = PBXBuildFile; fileRef = 4188D55A26C54D6F004858C8 /* RTCDtlsTransportBackend.h */; };
 		4188D56326C551B1004858C8 /* RTCDtlsTransportState.h in Headers */ = {isa = PBXBuildFile; fileRef = 4188D56226C551B1004858C8 /* RTCDtlsTransportState.h */; };
@@ -8158,6 +8159,9 @@
 		4186BD46214072B60001826F /* RTCRtpTransceiverBackend.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RTCRtpTransceiverBackend.h; sourceTree = "<group>"; };
 		4186BD4B2140A8050001826F /* LibWebRTCRtpTransceiverBackend.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LibWebRTCRtpTransceiverBackend.h; path = libwebrtc/LibWebRTCRtpTransceiverBackend.h; sourceTree = "<group>"; };
 		4186BD4D2140B9E80001826F /* LibWebRTCRtpTransceiverBackend.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LibWebRTCRtpTransceiverBackend.cpp; path = libwebrtc/LibWebRTCRtpTransceiverBackend.cpp; sourceTree = "<group>"; };
+		41878FA827282055002E1EDD /* BaseAudioMediaStreamTrackRendererUnit.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BaseAudioMediaStreamTrackRendererUnit.h; sourceTree = "<group>"; };
+		41878FAA27282057002E1EDD /* IncomingAudioMediaStreamTrackRendererUnit.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = IncomingAudioMediaStreamTrackRendererUnit.h; sourceTree = "<group>"; };
+		41878FAB272934E6002E1EDD /* IncomingAudioMediaStreamTrackRendererUnit.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = IncomingAudioMediaStreamTrackRendererUnit.cpp; sourceTree = "<group>"; };
 		418807DF24E4558300DDAF94 /* AbortAlgorithm.idl */ = {isa = PBXFileReference; lastKnownFileType = text; path = AbortAlgorithm.idl; sourceTree = "<group>"; };
 		418807E124E458C300DDAF94 /* AbortAlgorithm.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AbortAlgorithm.h; sourceTree = "<group>"; };
 		41885B9111B6FDA6003383BB /* FormSubmission.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FormSubmission.h; sourceTree = "<group>"; };
@@ -20172,8 +20176,11 @@
 				41C3B89F2649B1B7004ED4DE /* AudioMediaStreamTrackRendererInternalUnit.h */,
 				41C3B8A02649B1B7004ED4DE /* AudioMediaStreamTrackRendererUnit.cpp */,
 				41C3B89B2649B1B6004ED4DE /* AudioMediaStreamTrackRendererUnit.h */,
+				41878FA827282055002E1EDD /* BaseAudioMediaStreamTrackRendererUnit.h */,
 				07BB1E6E27176CCA001DF289 /* DisplayCaptureSourceCocoa.cpp */,
 				07BB1E6F27176CCA001DF289 /* DisplayCaptureSourceCocoa.h */,
+				41878FAB272934E6002E1EDD /* IncomingAudioMediaStreamTrackRendererUnit.cpp */,
+				41878FAA27282057002E1EDD /* IncomingAudioMediaStreamTrackRendererUnit.h */,
 			);
 			path = cocoa;
 			sourceTree = "<group>";
@@ -31928,6 +31935,7 @@
 				BC124EE80C2641CD009E2349 /* BarProp.h in Headers */,
 				460BB6161D0A1BF000221812 /* Base64Utilities.h in Headers */,
 				83198FBF24A160DD00420B05 /* BaseAudioContext.h in Headers */,
+				41878FAD27294721002E1EDD /* BaseAudioMediaStreamTrackRendererUnit.h in Headers */,
 				412DEF1F23A918A300D840F6 /* BaseAudioSharedUnit.h in Headers */,
 				379E61CA126CA5C400B63E8D /* BaseButtonInputType.h in Headers */,
 				379E61CC126CA5C400B63E8D /* BaseCheckableInputType.h in Headers */,

Modified: trunk/Source/WebCore/loader/EmptyClients.cpp (285026 => 285027)


--- trunk/Source/WebCore/loader/EmptyClients.cpp	2021-10-29 13:04:17 UTC (rev 285026)
+++ trunk/Source/WebCore/loader/EmptyClients.cpp	2021-10-29 13:36:03 UTC (rev 285027)
@@ -57,6 +57,7 @@
 #include "HistoryItem.h"
 #include "IDBConnectionToServer.h"
 #include "InspectorClient.h"
+#include "LibWebRTCAudioModule.h"
 #include "LibWebRTCProvider.h"
 #include "MediaRecorderPrivate.h"
 #include "MediaRecorderProvider.h"

Modified: trunk/Source/WebCore/platform/audio/cocoa/AudioSampleDataSource.h (285026 => 285027)


--- trunk/Source/WebCore/platform/audio/cocoa/AudioSampleDataSource.h	2021-10-29 13:04:17 UTC (rev 285026)
+++ trunk/Source/WebCore/platform/audio/cocoa/AudioSampleDataSource.h	2021-10-29 13:36:03 UTC (rev 285027)
@@ -61,6 +61,7 @@
     bool pullSamples(AudioBufferList&, size_t, uint64_t, double, PullMode);
 
     bool pullAvailableSamplesAsChunks(AudioBufferList&, size_t frameCount, uint64_t timeStamp, Function<void()>&&);
+    bool pullAvailableSampleChunk(AudioBufferList&, size_t frameCount, uint64_t timeStamp, PullMode);
 
     void setVolume(float volume) { m_volume = volume; }
     float volume() const { return m_volume; }
@@ -69,6 +70,7 @@
     bool muted() const { return m_muted; }
 
     const CAAudioStreamDescription* inputDescription() const { return m_inputDescription ? &m_inputDescription.value() : nullptr; }
+    const CAAudioStreamDescription* outputDescription() const { return m_outputDescription ? &m_outputDescription.value() : nullptr; }
 
     void recomputeSampleOffset() { m_shouldComputeOutputSampleOffset = true; }
 
@@ -86,6 +88,7 @@
     OSStatus setupConverter();
 
     void pushSamplesInternal(const AudioBufferList&, const MediaTime&, size_t frameCount);
+    bool pullSamplesInternal(AudioBufferList&, size_t sampleCount, uint64_t timeStamp, PullMode);
 
     std::optional<CAAudioStreamDescription> m_inputDescription;
     std::optional<CAAudioStreamDescription> m_outputDescription;

Modified: trunk/Source/WebCore/platform/audio/cocoa/AudioSampleDataSource.mm (285026 => 285027)


--- trunk/Source/WebCore/platform/audio/cocoa/AudioSampleDataSource.mm	2021-10-29 13:04:17 UTC (rev 285026)
+++ trunk/Source/WebCore/platform/audio/cocoa/AudioSampleDataSource.mm	2021-10-29 13:36:03 UTC (rev 285027)
@@ -286,6 +286,11 @@
 
     m_isFirstPull = false;
 
+    return pullSamplesInternal(buffer, sampleCount, timeStamp, mode);
+}
+
+bool AudioSampleDataSource::pullSamplesInternal(AudioBufferList& buffer, size_t sampleCount, uint64_t timeStamp, PullMode mode)
+{
     if (mode == Copy) {
         m_ringBuffer->fetch(&buffer, sampleCount, timeStamp, CARingBuffer::Copy);
         if (m_volume < EquivalentToMaxVolume)
@@ -309,6 +314,25 @@
     return true;
 }
 
+bool AudioSampleDataSource::pullAvailableSampleChunk(AudioBufferList& buffer, size_t sampleCount, uint64_t timeStamp, PullMode mode)
+{
+    ASSERT(buffer.mNumberBuffers == m_ringBuffer->channelCount());
+    if (buffer.mNumberBuffers != m_ringBuffer->channelCount())
+        return false;
+
+    if (m_muted)
+        return false;
+
+    if (m_shouldComputeOutputSampleOffset) {
+        m_shouldComputeOutputSampleOffset = false;
+        m_outputSampleOffset = m_inputSampleOffset.timeValue() * m_outputDescription->sampleRate() / m_inputSampleOffset.timeScale();
+    }
+
+    timeStamp += m_outputSampleOffset;
+
+    return pullSamplesInternal(buffer, sampleCount, timeStamp, mode);
+}
+
 bool AudioSampleDataSource::pullAvailableSamplesAsChunks(AudioBufferList& buffer, size_t sampleCountPerChunk, uint64_t timeStamp, Function<void()>&& consumeFilledBuffer)
 {
     ASSERT(buffer.mNumberBuffers == m_ringBuffer->channelCount());

Modified: trunk/Source/WebCore/platform/mediastream/AudioMediaStreamTrackRenderer.cpp (285026 => 285027)


--- trunk/Source/WebCore/platform/mediastream/AudioMediaStreamTrackRenderer.cpp	2021-10-29 13:04:17 UTC (rev 285026)
+++ trunk/Source/WebCore/platform/mediastream/AudioMediaStreamTrackRenderer.cpp	2021-10-29 13:36:03 UTC (rev 285027)
@@ -40,31 +40,28 @@
 
 namespace WebCore {
 
-AudioMediaStreamTrackRenderer::RendererCreator AudioMediaStreamTrackRenderer::m_rendererCreator = nullptr;
-void AudioMediaStreamTrackRenderer::setCreator(RendererCreator creator)
+std::unique_ptr<AudioMediaStreamTrackRenderer> AudioMediaStreamTrackRenderer::create(Init&& init)
 {
-    m_rendererCreator = creator;
-}
-
-std::unique_ptr<AudioMediaStreamTrackRenderer> AudioMediaStreamTrackRenderer::create()
-{
-    if (m_rendererCreator)
-        return m_rendererCreator();
-
 #if PLATFORM(COCOA)
-    return makeUnique<AudioMediaStreamTrackRendererCocoa>();
+    return makeUnique<AudioMediaStreamTrackRendererCocoa>(WTFMove(init));
 #else
     return nullptr;
 #endif
 }
 
+AudioMediaStreamTrackRenderer::AudioMediaStreamTrackRenderer(Init&& init)
+    : m_crashCallback(WTFMove(init.crashCallback))
+#if USE(LIBWEBRTC)
+    , m_audioModule(WTFMove(init.audioModule))
+#endif
 #if !RELEASE_LOG_DISABLED
-void AudioMediaStreamTrackRenderer::setLogger(const Logger& logger, const void* identifier)
+    , m_logger(init.logger)
+    , m_logIdentifier(init.logIdentifier)
+#endif
 {
-    m_logger = &logger;
-    m_logIdentifier = identifier;
 }
 
+#if !RELEASE_LOG_DISABLED
 WTFLogChannel& AudioMediaStreamTrackRenderer::logChannel() const
 {
     return LogMedia;

Modified: trunk/Source/WebCore/platform/mediastream/AudioMediaStreamTrackRenderer.h (285026 => 285027)


--- trunk/Source/WebCore/platform/mediastream/AudioMediaStreamTrackRenderer.h	2021-10-29 13:04:17 UTC (rev 285026)
+++ trunk/Source/WebCore/platform/mediastream/AudioMediaStreamTrackRenderer.h	2021-10-29 13:36:03 UTC (rev 285027)
@@ -37,12 +37,23 @@
 namespace WebCore {
 
 class AudioStreamDescription;
+class LibWebRTCAudioModule;
 class PlatformAudioData;
 
 class WEBCORE_EXPORT AudioMediaStreamTrackRenderer : public LoggerHelper {
     WTF_MAKE_FAST_ALLOCATED;
 public:
-    static std::unique_ptr<AudioMediaStreamTrackRenderer> create();
+    struct Init {
+        Function<void()>&& crashCallback;
+#if USE(LIBWEBRTC)
+        RefPtr<LibWebRTCAudioModule> audioModule;
+#endif
+#if !RELEASE_LOG_DISABLED
+        const Logger& logger;
+        const void* logIdentifier;
+#endif
+    };
+    static std::unique_ptr<AudioMediaStreamTrackRenderer> create(Init&&);
     virtual ~AudioMediaStreamTrackRenderer() = default;
 
     virtual void start(CompletionHandler<void()>&&) = 0;
@@ -56,16 +67,9 @@
 
     virtual void setAudioOutputDevice(const String&);
 
-#if !RELEASE_LOG_DISABLED
-    void setLogger(const Logger&, const void*);
-#endif
+protected:
+    explicit AudioMediaStreamTrackRenderer(Init&&);
 
-    using RendererCreator = std::unique_ptr<AudioMediaStreamTrackRenderer> (*)();
-    static void setCreator(RendererCreator);
-
-    void setCrashCallback(Function<void()>&& callback) { m_crashCallback = WTFMove(callback); }
-
-protected:
 #if !RELEASE_LOG_DISABLED
     const Logger& logger() const final;
     const void* logIdentifier() const final;
@@ -74,17 +78,23 @@
     WTFLogChannel& logChannel() const final;
 #endif
 
+#if USE(LIBWEBRTC)
+    LibWebRTCAudioModule* audioModule();
+#endif
+
     void crashed();
 
 private:
-    static RendererCreator m_rendererCreator;
-
     // Main thread writable members
     float m_volume { 1 };
     Function<void()> m_crashCallback;
 
+#if USE(LIBWEBRTC)
+    RefPtr<LibWebRTCAudioModule> m_audioModule;
+#endif
+
 #if !RELEASE_LOG_DISABLED
-    RefPtr<const Logger> m_logger;
+    Ref<const Logger> m_logger;
     const void* m_logIdentifier;
 #endif
 };
@@ -105,10 +115,17 @@
         m_crashCallback();
 }
 
+#if USE(LIBWEBRTC)
+inline LibWebRTCAudioModule* AudioMediaStreamTrackRenderer::audioModule()
+{
+    return m_audioModule.get();
+}
+#endif
+
 #if !RELEASE_LOG_DISABLED
 inline const Logger& AudioMediaStreamTrackRenderer::logger() const
 {
-    return *m_logger;
+    return m_logger.get();
     
 }
 

Modified: trunk/Source/WebCore/platform/mediastream/AudioTrackPrivateMediaStream.cpp (285026 => 285027)


--- trunk/Source/WebCore/platform/mediastream/AudioTrackPrivateMediaStream.cpp	2021-10-29 13:04:17 UTC (rev 285026)
+++ trunk/Source/WebCore/platform/mediastream/AudioTrackPrivateMediaStream.cpp	2021-10-29 13:36:03 UTC (rev 285027)
@@ -29,7 +29,9 @@
 #if ENABLE(MEDIA_STREAM)
 
 #include "AudioMediaStreamTrackRenderer.h"
+#include "LibWebRTCAudioModule.h"
 #include "Logging.h"
+#include "RealtimeIncomingAudioSource.h"
 
 namespace WebCore {
 
@@ -48,20 +50,31 @@
     clear();
 }
 
+#if USE(LIBWEBRTC)
+static RefPtr<LibWebRTCAudioModule> audioModuleFromSource(RealtimeMediaSource& source)
+{
+    if (!is<RealtimeIncomingAudioSource>(source))
+        return nullptr;
+    return downcast<RealtimeIncomingAudioSource>(source).audioModule();
+}
+#endif
+
 std::unique_ptr<AudioMediaStreamTrackRenderer> AudioTrackPrivateMediaStream::createRenderer(AudioTrackPrivateMediaStream& stream)
 {
-    auto renderer = AudioMediaStreamTrackRenderer::create();
-    if (!renderer)
-        return nullptr;
-#if !RELEASE_LOG_DISABLED
     auto& track = stream.m_streamTrack.get();
-    renderer->setLogger(track.logger(), track.logIdentifier());
+    return AudioMediaStreamTrackRenderer::create(AudioMediaStreamTrackRenderer::Init {
+        [stream = WeakPtr { stream }] {
+            if (stream)
+                stream->createNewRenderer();
+        }
+#if USE(LIBWEBRTC)
+        , audioModuleFromSource(stream.m_audioSource.get())
 #endif
-    renderer->setCrashCallback([stream = WeakPtr { stream }] {
-        if (stream)
-            stream->createNewRenderer();
+#if !RELEASE_LOG_DISABLED
+        , track.logger()
+        , track.logIdentifier()
+#endif
     });
-    return renderer;
 }
 
 void AudioTrackPrivateMediaStream::clear()

Modified: trunk/Source/WebCore/platform/mediastream/RealtimeIncomingAudioSource.cpp (285026 => 285027)


--- trunk/Source/WebCore/platform/mediastream/RealtimeIncomingAudioSource.cpp	2021-10-29 13:04:17 UTC (rev 285026)
+++ trunk/Source/WebCore/platform/mediastream/RealtimeIncomingAudioSource.cpp	2021-10-29 13:36:03 UTC (rev 285027)
@@ -34,6 +34,7 @@
 #if USE(LIBWEBRTC)
 
 #include "LibWebRTCAudioFormat.h"
+#include "LibWebRTCAudioModule.h"
 #include "Logging.h"
 
 namespace WebCore {
@@ -80,6 +81,12 @@
     return m_currentSettings;
 }
 
+void RealtimeIncomingAudioSource::setAudioModule(RefPtr<LibWebRTCAudioModule>&& audioModule)
+{
+    ASSERT(!m_audioModule);
+    m_audioModule = WTFMove(audioModule);
 }
 
+}
+
 #endif // USE(LIBWEBRTC)

Modified: trunk/Source/WebCore/platform/mediastream/RealtimeIncomingAudioSource.h (285026 => 285027)


--- trunk/Source/WebCore/platform/mediastream/RealtimeIncomingAudioSource.h	2021-10-29 13:04:17 UTC (rev 285026)
+++ trunk/Source/WebCore/platform/mediastream/RealtimeIncomingAudioSource.h	2021-10-29 13:36:03 UTC (rev 285027)
@@ -45,6 +45,8 @@
 
 namespace WebCore {
 
+class LibWebRTCAudioModule;
+
 class RealtimeIncomingAudioSource
     : public RealtimeMediaSource
     , private webrtc::AudioTrackSinkInterface
@@ -53,6 +55,9 @@
 public:
     static Ref<RealtimeIncomingAudioSource> create(rtc::scoped_refptr<webrtc::AudioTrackInterface>&&, String&&);
 
+    void setAudioModule(RefPtr<LibWebRTCAudioModule>&&);
+    LibWebRTCAudioModule* audioModule() { return m_audioModule.get(); }
+
 protected:
     RealtimeIncomingAudioSource(rtc::scoped_refptr<webrtc::AudioTrackInterface>&&, String&&);
     ~RealtimeIncomingAudioSource();
@@ -79,6 +84,7 @@
 
     RealtimeMediaSourceSettings m_currentSettings;
     rtc::scoped_refptr<webrtc::AudioTrackInterface> m_audioTrack;
+    RefPtr<LibWebRTCAudioModule> m_audioModule;
 
 #if !RELEASE_LOG_DISABLED
     mutable RefPtr<const Logger> m_logger;

Modified: trunk/Source/WebCore/platform/mediastream/cocoa/AudioMediaStreamTrackRendererCocoa.cpp (285026 => 285027)


--- trunk/Source/WebCore/platform/mediastream/cocoa/AudioMediaStreamTrackRendererCocoa.cpp	2021-10-29 13:04:17 UTC (rev 285026)
+++ trunk/Source/WebCore/platform/mediastream/cocoa/AudioMediaStreamTrackRendererCocoa.cpp	2021-10-29 13:36:03 UTC (rev 285027)
@@ -36,8 +36,9 @@
 
 namespace WebCore {
 
-AudioMediaStreamTrackRendererCocoa::AudioMediaStreamTrackRendererCocoa()
-    : m_resetObserver([this] { reset(); })
+AudioMediaStreamTrackRendererCocoa::AudioMediaStreamTrackRendererCocoa(Init&& init)
+    : AudioMediaStreamTrackRenderer(WTFMove(init))
+    , m_resetObserver([this] { reset(); })
 {
 }
 
@@ -59,12 +60,19 @@
     });
 }
 
+BaseAudioMediaStreamTrackRendererUnit& AudioMediaStreamTrackRendererCocoa::rendererUnit()
+{
+    if (auto* audioModule = this->audioModule())
+        return audioModule->incomingAudioMediaStreamTrackRendererUnit();
+    return AudioMediaStreamTrackRendererUnit::singleton();
+}
+
 void AudioMediaStreamTrackRendererCocoa::stop()
 {
     ASSERT(isMainThread());
 
     if (m_registeredDataSource)
-        AudioMediaStreamTrackRendererUnit::singleton().removeSource(*m_registeredDataSource);
+        rendererUnit().removeSource(*m_registeredDataSource);
 }
 
 void AudioMediaStreamTrackRendererCocoa::clear()
@@ -95,7 +103,7 @@
 void AudioMediaStreamTrackRendererCocoa::setAudioOutputDevice(const String& deviceId)
 {
     // FIXME: We should create a unit for ourselves here or use the default unit if deviceId is matching.
-    AudioMediaStreamTrackRendererUnit::singleton().setAudioOutputDevice(deviceId);
+    rendererUnit().setAudioOutputDevice(deviceId);
     m_shouldRecreateDataSource = true;
 }
 
@@ -104,7 +112,7 @@
     ASSERT(isMainThread());
 
     if (m_registeredDataSource)
-        AudioMediaStreamTrackRendererUnit::singleton().removeSource(*m_registeredDataSource);
+        rendererUnit().removeSource(*m_registeredDataSource);
 
     if (!m_outputDescription)
         return;
@@ -115,8 +123,8 @@
 
     m_registeredDataSource->setLogger(logger(), logIdentifier());
     m_registeredDataSource->setVolume(volume());
-    AudioMediaStreamTrackRendererUnit::singleton().addResetObserver(m_resetObserver);
-    AudioMediaStreamTrackRendererUnit::singleton().addSource(*m_registeredDataSource);
+    rendererUnit().addResetObserver(m_resetObserver);
+    rendererUnit().addSource(*m_registeredDataSource);
 }
 
 static unsigned pollSamplesCount()

Modified: trunk/Source/WebCore/platform/mediastream/cocoa/AudioMediaStreamTrackRendererCocoa.h (285026 => 285027)


--- trunk/Source/WebCore/platform/mediastream/cocoa/AudioMediaStreamTrackRendererCocoa.h	2021-10-29 13:04:17 UTC (rev 285026)
+++ trunk/Source/WebCore/platform/mediastream/cocoa/AudioMediaStreamTrackRendererCocoa.h	2021-10-29 13:36:03 UTC (rev 285027)
@@ -39,12 +39,13 @@
 
 class AudioSampleDataSource;
 class AudioSampleBufferList;
+class BaseAudioMediaStreamTrackRendererUnit;
 class CAAudioStreamDescription;
 
 class AudioMediaStreamTrackRendererCocoa : public AudioMediaStreamTrackRenderer, public CanMakeWeakPtr<AudioMediaStreamTrackRendererCocoa, WeakPtrFactoryInitialization::Eager> {
     WTF_MAKE_FAST_ALLOCATED;
 public:
-    AudioMediaStreamTrackRendererCocoa();
+    AudioMediaStreamTrackRendererCocoa(Init&&);
     ~AudioMediaStreamTrackRendererCocoa();
 
 private:
@@ -59,6 +60,8 @@
     void reset();
     void setRegisteredDataSource(RefPtr<AudioSampleDataSource>&&);
 
+    BaseAudioMediaStreamTrackRendererUnit& rendererUnit();
+
     std::unique_ptr<CAAudioStreamDescription> m_outputDescription;
     RefPtr<AudioSampleDataSource> m_dataSource; // Used in background thread.
     RefPtr<AudioSampleDataSource> m_registeredDataSource; // Used in main thread.

Modified: trunk/Source/WebCore/platform/mediastream/cocoa/AudioMediaStreamTrackRendererUnit.h (285026 => 285027)


--- trunk/Source/WebCore/platform/mediastream/cocoa/AudioMediaStreamTrackRendererUnit.h	2021-10-29 13:04:17 UTC (rev 285026)
+++ trunk/Source/WebCore/platform/mediastream/cocoa/AudioMediaStreamTrackRendererUnit.h	2021-10-29 13:36:03 UTC (rev 285027)
@@ -28,10 +28,9 @@
 #if ENABLE(MEDIA_STREAM)
 
 #include "AudioMediaStreamTrackRendererInternalUnit.h"
-#include <wtf/Forward.h>
+#include "BaseAudioMediaStreamTrackRendererUnit.h"
 #include <wtf/HashSet.h>
 #include <wtf/Lock.h>
-#include <wtf/Observer.h>
 #include <wtf/UniqueRef.h>
 #include <wtf/Vector.h>
 #include <wtf/WeakHashSet.h>
@@ -43,7 +42,7 @@
 class CAAudioStreamDescription;
 class AudioMediaStreamTrackRendererInternalUnit;
 
-class AudioMediaStreamTrackRendererUnit {
+class AudioMediaStreamTrackRendererUnit : public BaseAudioMediaStreamTrackRendererUnit {
 public:
     WEBCORE_EXPORT static AudioMediaStreamTrackRendererUnit& singleton();
 
@@ -56,15 +55,14 @@
     WEBCORE_EXPORT void render(size_t sampleCount, AudioBufferList&, uint64_t sampleTime, double hostTime, AudioUnitRenderActionFlags&);
     void reset();
 
-    void setAudioOutputDevice(const String&);
+    void retrieveFormatDescription(CompletionHandler<void(const CAAudioStreamDescription*)>&&);
 
-    void addSource(Ref<AudioSampleDataSource>&&);
-    void removeSource(AudioSampleDataSource&);
+    // BaseAudioMediaStreamTrackRendererUnit
+    void setAudioOutputDevice(const String&) final;
+    void addSource(Ref<AudioSampleDataSource>&&) final;
+    void removeSource(AudioSampleDataSource&) final;
+    void addResetObserver(ResetObserver& observer) final { m_resetObservers.add(observer); }
 
-    using ResetObserver = Observer<void()>;
-    void addResetObserver(ResetObserver& observer) { m_resetObservers.add(observer); }
-    void retrieveFormatDescription(CompletionHandler<void(const CAAudioStreamDescription*)>&&);
-
 private:
     void start();
     void stop();

Copied: trunk/Source/WebCore/platform/mediastream/cocoa/BaseAudioMediaStreamTrackRendererUnit.h (from rev 285026, trunk/Source/WebCore/platform/mediastream/AudioMediaStreamTrackRenderer.cpp) (0 => 285027)


--- trunk/Source/WebCore/platform/mediastream/cocoa/BaseAudioMediaStreamTrackRendererUnit.h	                        (rev 0)
+++ trunk/Source/WebCore/platform/mediastream/cocoa/BaseAudioMediaStreamTrackRendererUnit.h	2021-10-29 13:36:03 UTC (rev 285027)
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2021 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#if ENABLE(MEDIA_STREAM)
+
+#include <wtf/Forward.h>
+#include <wtf/Observer.h>
+
+namespace WebCore {
+
+class AudioSampleDataSource;
+
+class BaseAudioMediaStreamTrackRendererUnit {
+public:
+    virtual ~BaseAudioMediaStreamTrackRendererUnit() = default;
+
+    virtual void addSource(Ref<AudioSampleDataSource>&&) = 0;
+    virtual void removeSource(AudioSampleDataSource&) = 0;
+
+    virtual void setAudioOutputDevice(const String&) = 0;
+
+    using ResetObserver = Observer<void()>;
+    virtual void addResetObserver(ResetObserver&) = 0;
+};
+
+}
+
+#endif // ENABLE(MEDIA_STREAM)

Added: trunk/Source/WebCore/platform/mediastream/cocoa/IncomingAudioMediaStreamTrackRendererUnit.cpp (0 => 285027)


--- trunk/Source/WebCore/platform/mediastream/cocoa/IncomingAudioMediaStreamTrackRendererUnit.cpp	                        (rev 0)
+++ trunk/Source/WebCore/platform/mediastream/cocoa/IncomingAudioMediaStreamTrackRendererUnit.cpp	2021-10-29 13:36:03 UTC (rev 285027)
@@ -0,0 +1,203 @@
+/*
+ * Copyright (C) 2021 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "IncomingAudioMediaStreamTrackRendererUnit.h"
+
+#if ENABLE(MEDIA_STREAM)
+
+#include "AudioMediaStreamTrackRendererUnit.h"
+#include "AudioSampleDataSource.h"
+#include "LibWebRTCAudioFormat.h"
+#include "LibWebRTCAudioModule.h"
+#include "Logging.h"
+#include "WebAudioBufferList.h"
+#include <pal/avfoundation/MediaTimeAVFoundation.h>
+#include <wtf/WorkQueue.h>
+
+#include <pal/cf/CoreMediaSoftLink.h>
+
+namespace WebCore {
+
+IncomingAudioMediaStreamTrackRendererUnit::IncomingAudioMediaStreamTrackRendererUnit(LibWebRTCAudioModule& audioModule)
+    : m_audioModule(audioModule)
+    , m_queue(WorkQueue::create("IncomingAudioMediaStreamTrackRendererUnit", WorkQueue::QOS::UserInitiated))
+#if !RELEASE_LOG_DISABLED
+    , m_logIdentifier(LoggerHelper::uniqueLogIdentifier())
+#endif
+{
+}
+
+IncomingAudioMediaStreamTrackRendererUnit::~IncomingAudioMediaStreamTrackRendererUnit()
+{
+}
+
+void IncomingAudioMediaStreamTrackRendererUnit::setAudioOutputDevice(const String& deviceID)
+{
+    AudioMediaStreamTrackRendererUnit::singleton().setAudioOutputDevice(deviceID);
+}
+
+void IncomingAudioMediaStreamTrackRendererUnit::addResetObserver(ResetObserver& observer)
+{
+    AudioMediaStreamTrackRendererUnit::singleton().addResetObserver(observer);
+}
+
+void IncomingAudioMediaStreamTrackRendererUnit::addSource(Ref<AudioSampleDataSource>&& source)
+{
+#if !RELEASE_LOG_DISABLED
+    source->logger().logAlways(LogWebRTC, "IncomingAudioMediaStreamTrackRendererUnit::addSource ", source->logIdentifier());
+#endif
+    ASSERT(isMainThread());
+#if !RELEASE_LOG_DISABLED
+        if (!m_logger)
+            m_logger = &source->logger();
+#endif
+
+    ASSERT(source->outputDescription());
+    if (!source->outputDescription())
+        return;
+    auto outputDescription = *source->outputDescription();
+
+    ASSERT(!m_sources.contains(source.get()));
+    bool shouldStart = m_sources.isEmpty();
+    m_sources.add(WTFMove(source));
+
+    postTask([this, newSources = copyToVector(m_sources), shouldStart, outputDescription]() mutable {
+        m_renderSources = WTFMove(newSources);
+        if (!shouldStart)
+            return;
+
+        m_outputStreamDescription = outputDescription;
+        m_audioBufferList = makeUnique<WebAudioBufferList>(m_outputStreamDescription);
+        m_sampleCount = m_outputStreamDescription.sampleRate() / 100;
+        m_audioBufferList->setSampleCount(m_sampleCount);
+        m_mixedSource = AudioSampleDataSource::create(m_outputStreamDescription.sampleRate() * 0.5, *this, LibWebRTCAudioModule::PollSamplesCount + 1);
+        m_mixedSource->setInputFormat(outputDescription);
+        m_mixedSource->setOutputFormat(outputDescription);
+        m_writeCount = 0;
+        callOnMainThread([this, protectedModule = Ref { m_audioModule }, source = m_mixedSource]() mutable {
+            m_registeredMixedSource = WTFMove(source);
+            start();
+        });
+    });
+}
+
+void IncomingAudioMediaStreamTrackRendererUnit::removeSource(AudioSampleDataSource& source)
+{
+#if !RELEASE_LOG_DISABLED
+    source.logger().logAlways(LogWebRTC, "IncomingAudioMediaStreamTrackRendererUnit::removeSource ", source.logIdentifier());
+#endif
+    ASSERT(isMainThread());
+
+    bool shouldStop = !m_sources.isEmpty();
+    m_sources.remove(source);
+    shouldStop &= m_sources.isEmpty();
+
+    postTask([this, newSources = copyToVector(m_sources), shouldStop]() mutable {
+        m_renderSources = WTFMove(newSources);
+        if (!shouldStop)
+            return;
+
+        callOnMainThread([this, protectedModule = Ref { m_audioModule }] {
+            stop();
+        });
+    });
+
+}
+
+void IncomingAudioMediaStreamTrackRendererUnit::start()
+{
+    RELEASE_LOG(WebRTC, "IncomingAudioMediaStreamTrackRendererUnit::start");
+    ASSERT(isMainThread());
+
+    AudioMediaStreamTrackRendererUnit::singleton().addSource(*m_registeredMixedSource);
+    m_audioModule.startIncomingAudioRendering();
+}
+
+void IncomingAudioMediaStreamTrackRendererUnit::stop()
+{
+    RELEASE_LOG(WebRTC, "IncomingAudioMediaStreamTrackRendererUnit::stop");
+    ASSERT(isMainThread());
+
+    AudioMediaStreamTrackRendererUnit::singleton().removeSource(*m_registeredMixedSource);
+    m_registeredMixedSource = nullptr;
+    m_audioModule.stopIncomingAudioRendering();
+}
+
+void IncomingAudioMediaStreamTrackRendererUnit::postTask(Function<void()>&& callback)
+{
+    // We protect 'this' by taking a ref to its audio module.
+    m_queue->dispatch([protectedModule = Ref { m_audioModule }, callback = WTFMove(callback)]() mutable {
+        callback();
+    });
+}
+
+void IncomingAudioMediaStreamTrackRendererUnit::newAudioChunkPushed()
+{
+    DisableMallocRestrictionsForCurrentThreadScope disableMallocRestrictions;
+    postTask([this, currentAudioSampleCount = m_audioModule.currentAudioSampleCount()] {
+        renderAudioChunk(currentAudioSampleCount);
+    });
+}
+
+void IncomingAudioMediaStreamTrackRendererUnit::renderAudioChunk(uint64_t currentAudioSampleCount)
+{
+    ASSERT(!isMainThread());
+
+    uint64_t timeStamp = currentAudioSampleCount * m_outputStreamDescription.sampleRate() / LibWebRTCAudioFormat::sampleRate;
+
+    // Mix all sources.
+    bool hasCopiedData = false;
+    for (auto& source : m_renderSources) {
+        if (source->pullAvailableSampleChunk(*m_audioBufferList, m_sampleCount, timeStamp, hasCopiedData ? AudioSampleDataSource::Mix : AudioSampleDataSource::Copy))
+            hasCopiedData = true;
+    }
+
+    CMTime startTime = PAL::CMTimeMake(m_writeCount, m_outputStreamDescription.sampleRate());
+    if (hasCopiedData)
+        m_mixedSource->pushSamples(PAL::toMediaTime(startTime), *m_audioBufferList, m_sampleCount);
+    m_writeCount += m_sampleCount;
+}
+
+#if !RELEASE_LOG_DISABLED
+const Logger& IncomingAudioMediaStreamTrackRendererUnit::logger() const
+{
+    return *m_logger;
+}
+
+WTFLogChannel& IncomingAudioMediaStreamTrackRendererUnit::logChannel() const
+{
+    return LogWebRTC;
+}
+
+const void* IncomingAudioMediaStreamTrackRendererUnit::logIdentifier() const
+{
+    return m_logIdentifier;
+}
+#endif
+
+} // namespace WebCore
+
+#endif // ENABLE(MEDIA_STREAM)

Added: trunk/Source/WebCore/platform/mediastream/cocoa/IncomingAudioMediaStreamTrackRendererUnit.h (0 => 285027)


--- trunk/Source/WebCore/platform/mediastream/cocoa/IncomingAudioMediaStreamTrackRendererUnit.h	                        (rev 0)
+++ trunk/Source/WebCore/platform/mediastream/cocoa/IncomingAudioMediaStreamTrackRendererUnit.h	2021-10-29 13:36:03 UTC (rev 285027)
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2021 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#if ENABLE(MEDIA_STREAM)
+
+#include "BaseAudioMediaStreamTrackRendererUnit.h"
+#include "CAAudioStreamDescription.h"
+#include <wtf/FastMalloc.h>
+#include <wtf/Forward.h>
+#include <wtf/HashSet.h>
+#include <wtf/LoggerHelper.h>
+#include <wtf/Vector.h>
+
+namespace WTF {
+class WorkQueue;
+}
+
+namespace WebCore {
+
+class AudioMediaStreamTrackRendererInternalUnit;
+class AudioSampleDataSource;
+class AudioSampleBufferList;
+class CAAudioStreamDescription;
+class LibWebRTCAudioModule;
+class WebAudioBufferList;
+
+class IncomingAudioMediaStreamTrackRendererUnit : public BaseAudioMediaStreamTrackRendererUnit
+#if !RELEASE_LOG_DISABLED
+    , public LoggerHelper
+#endif
+{
+    WTF_MAKE_FAST_ALLOCATED;
+public:
+    explicit IncomingAudioMediaStreamTrackRendererUnit(LibWebRTCAudioModule&);
+    ~IncomingAudioMediaStreamTrackRendererUnit();
+
+    void newAudioChunkPushed();
+
+private:
+    void start();
+    void stop();
+    void postTask(Function<void()>&&);
+    void renderAudioChunk(uint64_t currentAudioSampleCount);
+
+    // BaseAudioMediaStreamTrackRendererUnit
+    void setAudioOutputDevice(const String&) final;
+    void addResetObserver(ResetObserver&) final;
+    void addSource(Ref<AudioSampleDataSource>&&) final;
+    void removeSource(AudioSampleDataSource&) final;
+
+#if !RELEASE_LOG_DISABLED
+    // LoggerHelper.
+    const Logger& logger() const final;
+    const char* logClassName() const final { return "IncomingAudioMediaStreamTrackRendererUnit"; }
+    WTFLogChannel& logChannel() const final;
+    const void* logIdentifier() const final;
+#endif
+
+    // Main thread variables.
+    LibWebRTCAudioModule& m_audioModule;
+    Ref<WTF::WorkQueue> m_queue;
+    HashSet<Ref<AudioSampleDataSource>> m_sources;
+    RefPtr<AudioSampleDataSource> m_registeredMixedSource;
+
+    // Background thread variables.
+    Vector<Ref<AudioSampleDataSource>> m_renderSources;
+    RefPtr<AudioSampleDataSource> m_mixedSource;
+    CAAudioStreamDescription m_outputStreamDescription;
+    std::unique_ptr<WebAudioBufferList> m_audioBufferList;
+    size_t m_sampleCount { 0 };
+    size_t m_writeCount { 0 };
+
+#if !RELEASE_LOG_DISABLED
+    RefPtr<const Logger> m_logger;
+    const void* m_logIdentifier;
+#endif
+};
+
+}
+
+#endif // ENABLE(MEDIA_STREAM)

Modified: trunk/Source/WebCore/platform/mediastream/libwebrtc/LibWebRTCAudioModule.cpp (285026 => 285027)


--- trunk/Source/WebCore/platform/mediastream/libwebrtc/LibWebRTCAudioModule.cpp	2021-10-29 13:04:17 UTC (rev 285026)
+++ trunk/Source/WebCore/platform/mediastream/libwebrtc/LibWebRTCAudioModule.cpp	2021-10-29 13:36:03 UTC (rev 285027)
@@ -32,6 +32,10 @@
 #include "Logging.h"
 #include <wtf/FastMalloc.h>
 
+#if PLATFORM(COCOA)
+#include "IncomingAudioMediaStreamTrackRendererUnit.h"
+#endif
+
 namespace WebCore {
 
 LibWebRTCAudioModule::LibWebRTCAudioModule()
@@ -40,6 +44,10 @@
 {
 }
 
+LibWebRTCAudioModule::~LibWebRTCAudioModule()
+{
+}
+
 int32_t LibWebRTCAudioModule::RegisterAudioCallback(webrtc::AudioTransport* audioTransport)
 {
     RELEASE_LOG(WebRTC, "LibWebRTCAudioModule::RegisterAudioCallback %d", !!audioTransport);
@@ -62,6 +70,9 @@
 
     m_queue->dispatch([this, protectedThis = rtc::scoped_refptr<webrtc::AudioDeviceModule>(this)] {
         m_pollingTime = MonotonicTime::now();
+#if PLATFORM(COCOA)
+        m_currentAudioSampleCount = 0;
+#endif
         pollAudioData();
     });
     return 0;
@@ -129,9 +140,23 @@
         int64_t ntpTime = -1;
         char data[LibWebRTCAudioFormat::sampleByteSize * channels * LibWebRTCAudioFormat::chunkSampleCount];
         m_audioTransport->PullRenderData(LibWebRTCAudioFormat::sampleByteSize * 8, LibWebRTCAudioFormat::sampleRate, channels, LibWebRTCAudioFormat::chunkSampleCount, data, &elapsedTime, &ntpTime);
+#if PLATFORM(COCOA)
+        if (m_isRenderingIncomingAudio)
+            m_incomingAudioMediaStreamTrackRendererUnit->newAudioChunkPushed();
+        m_currentAudioSampleCount += LibWebRTCAudioFormat::chunkSampleCount;
+#endif
     }
 }
 
+#if PLATFORM(COCOA)
+BaseAudioMediaStreamTrackRendererUnit& LibWebRTCAudioModule::incomingAudioMediaStreamTrackRendererUnit()
+{
+    if (!m_incomingAudioMediaStreamTrackRendererUnit)
+        m_incomingAudioMediaStreamTrackRendererUnit = makeUnique<IncomingAudioMediaStreamTrackRendererUnit>(*this);
+    return *m_incomingAudioMediaStreamTrackRendererUnit;
+}
+#endif
+
 } // namespace WebCore
 
 #endif // USE(LIBWEBRTC)

Modified: trunk/Source/WebCore/platform/mediastream/libwebrtc/LibWebRTCAudioModule.h (285026 => 285027)


--- trunk/Source/WebCore/platform/mediastream/libwebrtc/LibWebRTCAudioModule.h	2021-10-29 13:04:17 UTC (rev 285026)
+++ trunk/Source/WebCore/platform/mediastream/libwebrtc/LibWebRTCAudioModule.h	2021-10-29 13:36:03 UTC (rev 285027)
@@ -39,6 +39,8 @@
 ALLOW_UNUSED_PARAMETERS_END
 
 namespace WebCore {
+class BaseAudioMediaStreamTrackRendererUnit;
+class IncomingAudioMediaStreamTrackRendererUnit;
 
 // LibWebRTCAudioModule is pulling streamed data to ensure audio data is passed to the audio track.
 class LibWebRTCAudioModule : public webrtc::AudioDeviceModule {
@@ -45,9 +47,19 @@
     WTF_MAKE_FAST_ALLOCATED;
 public:
     LibWebRTCAudioModule();
+    ~LibWebRTCAudioModule();
 
     static constexpr unsigned PollSamplesCount = 1;
+    void ref() { AddRef(); }
+    void deref() { Release(); }
 
+#if PLATFORM(COCOA)
+    void startIncomingAudioRendering() { m_isRenderingIncomingAudio = true; }
+    void stopIncomingAudioRendering() { m_isRenderingIncomingAudio = false; }
+    BaseAudioMediaStreamTrackRendererUnit& incomingAudioMediaStreamTrackRendererUnit();
+    uint64_t currentAudioSampleCount() const { return m_currentAudioSampleCount; }
+#endif
+
 private:
     template<typename U> U shouldNotBeCalled(U value) const
     {
@@ -135,6 +147,12 @@
     MonotonicTime m_pollingTime;
     Timer m_logTimer;
     int m_timeSpent { 0 };
+
+#if PLATFORM(COCOA)
+    uint64_t m_currentAudioSampleCount { 0 };
+    bool m_isRenderingIncomingAudio { false };
+    std::unique_ptr<IncomingAudioMediaStreamTrackRendererUnit> m_incomingAudioMediaStreamTrackRendererUnit;
+#endif
 };
 
 } // namespace WebCore

Modified: trunk/Source/WebCore/platform/mediastream/libwebrtc/LibWebRTCProvider.cpp (285026 => 285027)


--- trunk/Source/WebCore/platform/mediastream/libwebrtc/LibWebRTCProvider.cpp	2021-10-29 13:04:17 UTC (rev 285026)
+++ trunk/Source/WebCore/platform/mediastream/libwebrtc/LibWebRTCProvider.cpp	2021-10-29 13:36:03 UTC (rev 285027)
@@ -70,6 +70,16 @@
 }
 #endif
 
+#if USE(LIBWEBRTC)
+LibWebRTCProvider::LibWebRTCProvider()
+{
+}
+#endif
+
+LibWebRTCProvider::~LibWebRTCProvider()
+{
+}
+
 #if !USE(LIBWEBRTC) || !PLATFORM(COCOA)
 void LibWebRTCProvider::registerWebKitVP9Decoder()
 {
@@ -271,9 +281,17 @@
     return m_factory;
 }
 
+void LibWebRTCProvider::clearFactory()
+{
+    m_audioModule = nullptr;
+    m_factory = nullptr;
+}
+
 rtc::scoped_refptr<webrtc::PeerConnectionFactoryInterface> LibWebRTCProvider::createPeerConnectionFactory(rtc::Thread* networkThread, rtc::Thread* signalingThread)
 {
-    auto audioModule = rtc::scoped_refptr<webrtc::AudioDeviceModule>(new rtc::RefCountedObject<LibWebRTCAudioModule>());
+    ASSERT(!m_audioModule);
+    auto audioModule = rtc::scoped_refptr<LibWebRTCAudioModule>(new rtc::RefCountedObject<LibWebRTCAudioModule>());
+    m_audioModule = audioModule.get();
 
     return webrtc::CreatePeerConnectionFactory(networkThread, signalingThread, signalingThread, WTFMove(audioModule), webrtc::CreateBuiltinAudioEncoderFactory(), webrtc::CreateBuiltinAudioDecoderFactory(), createEncoderFactory(), createDecoderFactory(), nullptr, nullptr, nullptr);
 }

Modified: trunk/Source/WebCore/platform/mediastream/libwebrtc/LibWebRTCProvider.h (285026 => 285027)


--- trunk/Source/WebCore/platform/mediastream/libwebrtc/LibWebRTCProvider.h	2021-10-29 13:04:17 UTC (rev 285026)
+++ trunk/Source/WebCore/platform/mediastream/libwebrtc/LibWebRTCProvider.h	2021-10-29 13:36:03 UTC (rev 285027)
@@ -79,7 +79,7 @@
 public:
     static UniqueRef<LibWebRTCProvider> create();
 
-    virtual ~LibWebRTCProvider() = default;
+    virtual ~LibWebRTCProvider();
 
     static bool webRTCAvailable();
     static void registerWebKitVP9Decoder();
@@ -103,6 +103,7 @@
     virtual rtc::scoped_refptr<webrtc::PeerConnectionInterface> createPeerConnection(DocumentIdentifier, webrtc::PeerConnectionObserver&, rtc::PacketSocketFactory*, webrtc::PeerConnectionInterface::RTCConfiguration&&);
 
     webrtc::PeerConnectionFactoryInterface* factory();
+    LibWebRTCAudioModule* audioModule();
 
     // FIXME: Make these methods not static.
     static void callOnWebRTCNetworkThread(Function<void()>&&);
@@ -134,7 +135,7 @@
     std::optional<RTCRtpCapabilities> receiverCapabilities(const String& kind);
     std::optional<RTCRtpCapabilities> senderCapabilities(const String& kind);
 
-    void clearFactory() { m_factory = nullptr; }
+    void clearFactory();
 
     virtual void setLoggingLevel(WTFLogLevel);
     void setEnableWebRTCEncryption(bool);
@@ -150,7 +151,7 @@
     virtual std::unique_ptr<SuspendableSocketFactory> createSocketFactory(String&& /* userAgent */, bool /* isFirstParty */, RegistrableDomain&&) { return nullptr; }
 
 protected:
-    LibWebRTCProvider() = default;
+    LibWebRTCProvider();
 
     rtc::scoped_refptr<webrtc::PeerConnectionInterface> createPeerConnection(webrtc::PeerConnectionObserver&, rtc::NetworkManager&, rtc::PacketSocketFactory&, webrtc::PeerConnectionInterface::RTCConfiguration&&, std::unique_ptr<webrtc::AsyncResolverFactory>&&);
 
@@ -171,6 +172,7 @@
     // FIXME: Remove m_useNetworkThreadWithSocketServer member variable and make it a global.
     bool m_useNetworkThreadWithSocketServer { true };
 
+    RefPtr<LibWebRTCAudioModule> m_audioModule;
     rtc::scoped_refptr<webrtc::PeerConnectionFactoryInterface> m_factory;
     bool m_disableNonLocalhostConnections { false };
     bool m_supportsH265 { false };
@@ -187,4 +189,11 @@
 #endif
 };
 
+#if USE(LIBWEBRTC)
+inline LibWebRTCAudioModule* LibWebRTCProvider::audioModule()
+{
+    return m_audioModule.get();
+}
+#endif
+
 } // namespace WebCore

Modified: trunk/Source/WebCore/platform/mediastream/mac/RealtimeIncomingAudioSourceCocoa.cpp (285026 => 285027)


--- trunk/Source/WebCore/platform/mediastream/mac/RealtimeIncomingAudioSourceCocoa.cpp	2021-10-29 13:04:17 UTC (rev 285026)
+++ trunk/Source/WebCore/platform/mediastream/mac/RealtimeIncomingAudioSourceCocoa.cpp	2021-10-29 13:36:03 UTC (rev 285027)
@@ -132,7 +132,7 @@
             m_numberOfFrames = 0;
     }
 
-    CMTime startTime = PAL::CMTimeMake(m_numberOfFrames, sampleRate);
+    CMTime startTime = PAL::CMTimeMake(audioModule() ? audioModule()->currentAudioSampleCount() : m_numberOfFrames, LibWebRTCAudioFormat::sampleRate);
     auto mediaTime = PAL::toMediaTime(startTime);
     m_numberOfFrames += numberOfFrames;
 
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to