<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[284674] trunk/Source</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/284674">284674</a></dd>
<dt>Author</dt> <dd>youenn@apple.com</dd>
<dt>Date</dt> <dd>2021-10-22 01:44:57 -0700 (Fri, 22 Oct 2021)</dd>
</dl>

<h3>Log Message</h3>
<pre>Audio over peer connection becomes latent when changing the output
https://bugs.webkit.org/show_bug.cgi?id=231110
<rdar://problem/84049005>

Reviewed by Eric Carlson.

Source/WebCore:

Add support for detecting change of timeline by looking at sample times. This happens when changing audio output.
Make AudioMediaStreamTrackRendererInternalUnit call a callback to let the unit deal with it.
When switching output, audio data is kept growing but is not read for some time by the remote unit, even though the remote unit is running.
The unit can ask its sources to update their offset to not keep extra buffered data.

Manually tested.

* platform/audio/cocoa/AudioSampleDataSource.h:
* platform/mediastream/cocoa/AudioMediaStreamTrackRendererCocoa.cpp:
* platform/mediastream/cocoa/AudioMediaStreamTrackRendererCocoa.h:
* platform/mediastream/cocoa/AudioMediaStreamTrackRendererInternalUnit.cpp:
* platform/mediastream/cocoa/AudioMediaStreamTrackRendererInternalUnit.h:
* platform/mediastream/cocoa/AudioMediaStreamTrackRendererUnit.cpp:
* platform/mediastream/cocoa/AudioMediaStreamTrackRendererUnit.h:

Source/WebKit:

When detecting an audio timeline change, send it from GPUProcess to WebProcess.
Let the WebProcess reset the sources to properly restart.

* GPUProcess/webrtc/RemoteAudioMediaStreamTrackRendererInternalUnitManager.cpp:
* WebProcess/GPU/GPUProcessConnection.cpp:
* WebProcess/GPU/GPUProcessConnection.h:
* WebProcess/GPU/GPUProcessConnection.messages.in:
* WebProcess/GPU/webrtc/AudioMediaStreamTrackRendererInternalUnitManager.cpp:
* WebProcess/GPU/webrtc/AudioMediaStreamTrackRendererInternalUnitManager.h:
* WebProcess/WebProcess.cpp:
* WebProcess/cocoa/UserMediaCaptureManager.cpp:</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCoreplatformaudiococoaAudioSampleDataSourceh">trunk/Source/WebCore/platform/audio/cocoa/AudioSampleDataSource.h</a></li>
<li><a href="#trunkSourceWebCoreplatformaudiococoaAudioSampleDataSourcemm">trunk/Source/WebCore/platform/audio/cocoa/AudioSampleDataSource.mm</a></li>
<li><a href="#trunkSourceWebCoreplatformmediastreamcocoaAudioMediaStreamTrackRendererCocoacpp">trunk/Source/WebCore/platform/mediastream/cocoa/AudioMediaStreamTrackRendererCocoa.cpp</a></li>
<li><a href="#trunkSourceWebCoreplatformmediastreamcocoaAudioMediaStreamTrackRendererCocoah">trunk/Source/WebCore/platform/mediastream/cocoa/AudioMediaStreamTrackRendererCocoa.h</a></li>
<li><a href="#trunkSourceWebCoreplatformmediastreamcocoaAudioMediaStreamTrackRendererInternalUnitcpp">trunk/Source/WebCore/platform/mediastream/cocoa/AudioMediaStreamTrackRendererInternalUnit.cpp</a></li>
<li><a href="#trunkSourceWebCoreplatformmediastreamcocoaAudioMediaStreamTrackRendererInternalUnith">trunk/Source/WebCore/platform/mediastream/cocoa/AudioMediaStreamTrackRendererInternalUnit.h</a></li>
<li><a href="#trunkSourceWebCoreplatformmediastreamcocoaAudioMediaStreamTrackRendererUnitcpp">trunk/Source/WebCore/platform/mediastream/cocoa/AudioMediaStreamTrackRendererUnit.cpp</a></li>
<li><a href="#trunkSourceWebCoreplatformmediastreamcocoaAudioMediaStreamTrackRendererUnith">trunk/Source/WebCore/platform/mediastream/cocoa/AudioMediaStreamTrackRendererUnit.h</a></li>
<li><a href="#trunkSourceWebKitChangeLog">trunk/Source/WebKit/ChangeLog</a></li>
<li><a href="#trunkSourceWebKitGPUProcesswebrtcRemoteAudioMediaStreamTrackRendererInternalUnitManagercpp">trunk/Source/WebKit/GPUProcess/webrtc/RemoteAudioMediaStreamTrackRendererInternalUnitManager.cpp</a></li>
<li><a href="#trunkSourceWebKitWebProcessGPUGPUProcessConnectioncpp">trunk/Source/WebKit/WebProcess/GPU/GPUProcessConnection.cpp</a></li>
<li><a href="#trunkSourceWebKitWebProcessGPUGPUProcessConnectionh">trunk/Source/WebKit/WebProcess/GPU/GPUProcessConnection.h</a></li>
<li><a href="#trunkSourceWebKitWebProcessGPUGPUProcessConnectionmessagesin">trunk/Source/WebKit/WebProcess/GPU/GPUProcessConnection.messages.in</a></li>
<li><a href="#trunkSourceWebKitWebProcessGPUwebrtcAudioMediaStreamTrackRendererInternalUnitManagercpp">trunk/Source/WebKit/WebProcess/GPU/webrtc/AudioMediaStreamTrackRendererInternalUnitManager.cpp</a></li>
<li><a href="#trunkSourceWebKitWebProcessGPUwebrtcAudioMediaStreamTrackRendererInternalUnitManagerh">trunk/Source/WebKit/WebProcess/GPU/webrtc/AudioMediaStreamTrackRendererInternalUnitManager.h</a></li>
<li><a href="#trunkSourceWebKitWebProcessWebProcesscpp">trunk/Source/WebKit/WebProcess/WebProcess.cpp</a></li>
<li><a href="#trunkSourceWebKitWebProcesscocoaUserMediaCaptureManagercpp">trunk/Source/WebKit/WebProcess/cocoa/UserMediaCaptureManager.cpp</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (284673 => 284674)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog   2021-10-22 08:44:02 UTC (rev 284673)
+++ trunk/Source/WebCore/ChangeLog      2021-10-22 08:44:57 UTC (rev 284674)
</span><span class="lines">@@ -1,3 +1,26 @@
</span><ins>+2021-10-22  Youenn Fablet  <youenn@apple.com>
+
+        Audio over peer connection becomes latent when changing the output
+        https://bugs.webkit.org/show_bug.cgi?id=231110
+        <rdar://problem/84049005>
+
+        Reviewed by Eric Carlson.
+
+        Add support for detecting change of timeline by looking at sample times. This happens when changing audio output.
+        Make AudioMediaStreamTrackRendererInternalUnit call a callback to let the unit deal with it.
+        When switching output, audio data is kept growing but is not read for some time by the remote unit, even though the remote unit is running.
+        The unit can ask its sources to update their offset to not keep extra buffered data.
+
+        Manually tested.
+
+        * platform/audio/cocoa/AudioSampleDataSource.h:
+        * platform/mediastream/cocoa/AudioMediaStreamTrackRendererCocoa.cpp:
+        * platform/mediastream/cocoa/AudioMediaStreamTrackRendererCocoa.h:
+        * platform/mediastream/cocoa/AudioMediaStreamTrackRendererInternalUnit.cpp:
+        * platform/mediastream/cocoa/AudioMediaStreamTrackRendererInternalUnit.h:
+        * platform/mediastream/cocoa/AudioMediaStreamTrackRendererUnit.cpp:
+        * platform/mediastream/cocoa/AudioMediaStreamTrackRendererUnit.h:
+
</ins><span class="cx"> 2021-10-22  Antti Koivisto  <antti@apple.com>
</span><span class="cx"> 
</span><span class="cx">         Remove Style::Resolver::m_isDeleted
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformaudiococoaAudioSampleDataSourceh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/audio/cocoa/AudioSampleDataSource.h (284673 => 284674)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/audio/cocoa/AudioSampleDataSource.h        2021-10-22 08:44:02 UTC (rev 284673)
+++ trunk/Source/WebCore/platform/audio/cocoa/AudioSampleDataSource.h   2021-10-22 08:44:57 UTC (rev 284674)
</span><span class="lines">@@ -70,6 +70,8 @@
</span><span class="cx"> 
</span><span class="cx">     const CAAudioStreamDescription* inputDescription() const { return m_inputDescription ? &m_inputDescription.value() : nullptr; }
</span><span class="cx"> 
</span><ins>+    void recomputeSampleOffset() { m_shouldComputeOutputSampleOffset = true; }
+
</ins><span class="cx"> #if !RELEASE_LOG_DISABLED
</span><span class="cx">     const Logger& logger() const final { return m_logger; }
</span><span class="cx">     const void* logIdentifier() const final { return m_logIdentifier; }
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformaudiococoaAudioSampleDataSourcemm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/audio/cocoa/AudioSampleDataSource.mm (284673 => 284674)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/audio/cocoa/AudioSampleDataSource.mm       2021-10-22 08:44:02 UTC (rev 284673)
+++ trunk/Source/WebCore/platform/audio/cocoa/AudioSampleDataSource.mm  2021-10-22 08:44:57 UTC (rev 284674)
</span><span class="lines">@@ -234,7 +234,8 @@
</span><span class="cx">     if (m_shouldComputeOutputSampleOffset) {
</span><span class="cx">         uint64_t buffered = endFrame - startFrame;
</span><span class="cx">         if (m_isFirstPull) {
</span><del>-            if (buffered >= m_waitToStartForPushCount * m_lastPushedSampleCount) {
</del><ins>+            auto minimumBuffer = m_waitToStartForPushCount * m_lastPushedSampleCount;
+            if (buffered >= minimumBuffer) {
</ins><span class="cx">                 m_outputSampleOffset = startFrame - timeStamp;
</span><span class="cx">                 m_shouldComputeOutputSampleOffset = false;
</span><span class="cx">                 m_endFrameWhenNotEnoughData = 0;
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformmediastreamcocoaAudioMediaStreamTrackRendererCocoacpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/mediastream/cocoa/AudioMediaStreamTrackRendererCocoa.cpp (284673 => 284674)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/mediastream/cocoa/AudioMediaStreamTrackRendererCocoa.cpp   2021-10-22 08:44:02 UTC (rev 284673)
+++ trunk/Source/WebCore/platform/mediastream/cocoa/AudioMediaStreamTrackRendererCocoa.cpp      2021-10-22 08:44:57 UTC (rev 284674)
</span><span class="lines">@@ -36,7 +36,10 @@
</span><span class="cx"> 
</span><span class="cx"> namespace WebCore {
</span><span class="cx"> 
</span><del>-AudioMediaStreamTrackRendererCocoa::AudioMediaStreamTrackRendererCocoa() = default;
</del><ins>+AudioMediaStreamTrackRendererCocoa::AudioMediaStreamTrackRendererCocoa()
+    : m_resetObserver([this] { reset(); })
+{
+}
</ins><span class="cx"> 
</span><span class="cx"> AudioMediaStreamTrackRendererCocoa::~AudioMediaStreamTrackRendererCocoa() = default;
</span><span class="cx"> 
</span><span class="lines">@@ -72,11 +75,17 @@
</span><span class="cx">         m_dataSource->setVolume(volume);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void AudioMediaStreamTrackRendererCocoa::reset()
+{
+    if (m_dataSource)
+        m_dataSource->recomputeSampleOffset();
+}
+
</ins><span class="cx"> void AudioMediaStreamTrackRendererCocoa::setAudioOutputDevice(const String& deviceId)
</span><span class="cx"> {
</span><span class="cx">     // FIXME: We should create a unit for ourselves here or use the default unit if deviceId is matching.
</span><span class="cx">     AudioMediaStreamTrackRendererUnit::singleton().setAudioOutputDevice(deviceId);
</span><del>-    m_shouldReset = true;
</del><ins>+    m_shouldRecreateDataSource = true;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> static unsigned pollSamplesCount()
</span><span class="lines">@@ -92,7 +101,7 @@
</span><span class="cx"> {
</span><span class="cx">     ASSERT(!isMainThread());
</span><span class="cx">     ASSERT(description.platformDescription().type == PlatformDescription::CAAudioStreamBasicType);
</span><del>-    if (!m_dataSource || m_shouldReset || !m_dataSource->inputDescription() || *m_dataSource->inputDescription() != description) {
</del><ins>+    if (!m_dataSource || m_shouldRecreateDataSource || !m_dataSource->inputDescription() || *m_dataSource->inputDescription() != description) {
</ins><span class="cx">         DisableMallocRestrictionsForCurrentThreadScope scope;
</span><span class="cx"> 
</span><span class="cx">         // FIXME: For non libwebrtc sources, we can probably reduce poll samples count to 2.
</span><span class="lines">@@ -120,10 +129,11 @@
</span><span class="cx">                 AudioMediaStreamTrackRendererUnit::singleton().removeSource(*oldSource);
</span><span class="cx"> 
</span><span class="cx">             newSource->setVolume(volume());
</span><ins>+            AudioMediaStreamTrackRendererUnit::singleton().addResetObserver(m_resetObserver);
</ins><span class="cx">             AudioMediaStreamTrackRendererUnit::singleton().addSource(WTFMove(newSource));
</span><span class="cx">         });
</span><span class="cx">         m_dataSource = WTFMove(dataSource);
</span><del>-        m_shouldReset = false;
</del><ins>+        m_shouldRecreateDataSource = false;
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     m_dataSource->pushSamples(sampleTime, audioData, sampleCount);
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformmediastreamcocoaAudioMediaStreamTrackRendererCocoah"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/mediastream/cocoa/AudioMediaStreamTrackRendererCocoa.h (284673 => 284674)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/mediastream/cocoa/AudioMediaStreamTrackRendererCocoa.h     2021-10-22 08:44:02 UTC (rev 284673)
+++ trunk/Source/WebCore/platform/mediastream/cocoa/AudioMediaStreamTrackRendererCocoa.h        2021-10-22 08:44:57 UTC (rev 284674)
</span><span class="lines">@@ -28,6 +28,7 @@
</span><span class="cx"> #if ENABLE(MEDIA_STREAM)
</span><span class="cx"> 
</span><span class="cx"> #include "AudioMediaStreamTrackRenderer.h"
</span><ins>+#include "AudioMediaStreamTrackRendererUnit.h"
</ins><span class="cx"> #include "Logging.h"
</span><span class="cx"> #include <wtf/WeakPtr.h>
</span><span class="cx"> 
</span><span class="lines">@@ -55,9 +56,12 @@
</span><span class="cx">     void setVolume(float) final;
</span><span class="cx">     void setAudioOutputDevice(const String&) final;
</span><span class="cx"> 
</span><ins>+    void reset();
+
</ins><span class="cx">     std::unique_ptr<CAAudioStreamDescription> m_outputDescription;
</span><span class="cx">     RefPtr<AudioSampleDataSource> m_dataSource;
</span><del>-    bool m_shouldReset { false };
</del><ins>+    bool m_shouldRecreateDataSource { false };
+    WebCore::AudioMediaStreamTrackRendererUnit::ResetObserver m_resetObserver;
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformmediastreamcocoaAudioMediaStreamTrackRendererInternalUnitcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/mediastream/cocoa/AudioMediaStreamTrackRendererInternalUnit.cpp (284673 => 284674)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/mediastream/cocoa/AudioMediaStreamTrackRendererInternalUnit.cpp    2021-10-22 08:44:02 UTC (rev 284673)
+++ trunk/Source/WebCore/platform/mediastream/cocoa/AudioMediaStreamTrackRendererInternalUnit.cpp       2021-10-22 08:44:57 UTC (rev 284674)
</span><span class="lines">@@ -50,7 +50,7 @@
</span><span class="cx"> class LocalAudioMediaStreamTrackRendererInternalUnit final : public AudioMediaStreamTrackRendererInternalUnit {
</span><span class="cx">     WTF_MAKE_FAST_ALLOCATED;
</span><span class="cx"> public:
</span><del>-    explicit LocalAudioMediaStreamTrackRendererInternalUnit(RenderCallback&&);
</del><ins>+    LocalAudioMediaStreamTrackRendererInternalUnit(RenderCallback&&, ResetCallback&&);
</ins><span class="cx"> 
</span><span class="cx"> private:
</span><span class="cx">     void createAudioUnitIfNeeded();
</span><span class="lines">@@ -61,24 +61,28 @@
</span><span class="cx">     void retrieveFormatDescription(CompletionHandler<void(const CAAudioStreamDescription*)>&&) final;
</span><span class="cx">     void setAudioOutputDevice(const String&) final;
</span><span class="cx"> 
</span><ins>+    OSStatus render(AudioUnitRenderActionFlags*, const AudioTimeStamp*, UInt32 sampleCount, AudioBufferList*);
</ins><span class="cx">     static OSStatus renderingCallback(void*, AudioUnitRenderActionFlags*, const AudioTimeStamp*, UInt32 inBusNumber, UInt32 sampleCount, AudioBufferList*);
</span><span class="cx"> 
</span><span class="cx">     RenderCallback m_renderCallback;
</span><ins>+    ResetCallback m_resetCallback;
</ins><span class="cx">     std::unique_ptr<CAAudioStreamDescription> m_outputDescription;
</span><span class="cx">     AudioComponentInstance m_remoteIOUnit { nullptr };
</span><span class="cx">     bool m_isStarted { false };
</span><ins>+    uint64_t m_sampleTime { 0 };
</ins><span class="cx"> #if PLATFORM(MAC)
</span><span class="cx">     uint32_t m_deviceID { 0 };
</span><span class="cx"> #endif
</span><span class="cx"> };
</span><span class="cx"> 
</span><del>-UniqueRef<AudioMediaStreamTrackRendererInternalUnit> AudioMediaStreamTrackRendererInternalUnit::createLocalInternalUnit(RenderCallback&& renderCallback)
</del><ins>+UniqueRef<AudioMediaStreamTrackRendererInternalUnit> AudioMediaStreamTrackRendererInternalUnit::createLocalInternalUnit(RenderCallback&& renderCallback, ResetCallback&& resetCallback)
</ins><span class="cx"> {
</span><del>-    return makeUniqueRef<LocalAudioMediaStreamTrackRendererInternalUnit>(WTFMove(renderCallback));
</del><ins>+    return makeUniqueRef<LocalAudioMediaStreamTrackRendererInternalUnit>(WTFMove(renderCallback), WTFMove(resetCallback));
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-LocalAudioMediaStreamTrackRendererInternalUnit::LocalAudioMediaStreamTrackRendererInternalUnit(RenderCallback&& renderCallback)
</del><ins>+LocalAudioMediaStreamTrackRendererInternalUnit::LocalAudioMediaStreamTrackRendererInternalUnit(RenderCallback&& renderCallback, ResetCallback&& resetCallback)
</ins><span class="cx">     : m_renderCallback(WTFMove(renderCallback))
</span><ins>+    , m_resetCallback(WTFMove(resetCallback))
</ins><span class="cx"> {
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -125,6 +129,7 @@
</span><span class="cx">     if (!m_remoteIOUnit)
</span><span class="cx">         return;
</span><span class="cx"> 
</span><ins>+    m_sampleTime = 0;
</ins><span class="cx">     if (auto error = PAL::AudioOutputUnitStart(m_remoteIOUnit)) {
</span><span class="cx">         RELEASE_LOG_ERROR(WebRTC, "AudioMediaStreamTrackRendererInternalUnit::start AudioOutputUnitStart failed, error = %d", error);
</span><span class="cx">         PAL::AudioComponentInstanceDispose(m_remoteIOUnit);
</span><span class="lines">@@ -230,9 +235,20 @@
</span><span class="cx">     m_remoteIOUnit = remoteIOUnit;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+OSStatus LocalAudioMediaStreamTrackRendererInternalUnit::render(AudioUnitRenderActionFlags* actionFlags, const AudioTimeStamp* timeStamp, UInt32 sampleCount, AudioBufferList* ioData)
+{
+    auto sampleTime = timeStamp->mSampleTime;
+    // If we observe an irregularity in the timeline, we trigger a reset.
+    if (m_sampleTime && (m_sampleTime + 2 * sampleCount < sampleTime || sampleTime <= m_sampleTime))
+        m_resetCallback();
+    m_sampleTime = sampleTime < std::numeric_limits<Float64>::max() - sampleCount ? sampleTime : 0;
+
+    return m_renderCallback(sampleCount, *ioData, sampleTime, timeStamp->mHostTime, *actionFlags);
+}
+
</ins><span class="cx"> OSStatus LocalAudioMediaStreamTrackRendererInternalUnit::renderingCallback(void* processor, AudioUnitRenderActionFlags* actionFlags, const AudioTimeStamp* timeStamp, UInt32, UInt32 sampleCount, AudioBufferList* ioData)
</span><span class="cx"> {
</span><del>-    return static_cast<LocalAudioMediaStreamTrackRendererInternalUnit*>(processor)->m_renderCallback(sampleCount, *ioData, timeStamp->mSampleTime, timeStamp->mHostTime, *actionFlags);
</del><ins>+    return static_cast<LocalAudioMediaStreamTrackRendererInternalUnit*>(processor)->render(actionFlags, timeStamp, sampleCount, ioData);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> } // namespace WebCore
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformmediastreamcocoaAudioMediaStreamTrackRendererInternalUnith"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/mediastream/cocoa/AudioMediaStreamTrackRendererInternalUnit.h (284673 => 284674)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/mediastream/cocoa/AudioMediaStreamTrackRendererInternalUnit.h      2021-10-22 08:44:02 UTC (rev 284673)
+++ trunk/Source/WebCore/platform/mediastream/cocoa/AudioMediaStreamTrackRendererInternalUnit.h 2021-10-22 08:44:57 UTC (rev 284674)
</span><span class="lines">@@ -40,7 +40,8 @@
</span><span class="cx">     virtual ~AudioMediaStreamTrackRendererInternalUnit() = default;
</span><span class="cx"> 
</span><span class="cx">     using RenderCallback = Function<OSStatus(size_t sampleCount, AudioBufferList&, uint64_t sampleTime, double hostTime, AudioUnitRenderActionFlags&)>;
</span><del>-    WEBCORE_EXPORT static UniqueRef<AudioMediaStreamTrackRendererInternalUnit> createLocalInternalUnit(RenderCallback&&);
</del><ins>+    using ResetCallback = Function<void()>;
+    WEBCORE_EXPORT static UniqueRef<AudioMediaStreamTrackRendererInternalUnit> createLocalInternalUnit(RenderCallback&&, ResetCallback&&);
</ins><span class="cx"> 
</span><span class="cx">     virtual void start() = 0;
</span><span class="cx">     virtual void stop() = 0;
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformmediastreamcocoaAudioMediaStreamTrackRendererUnitcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/mediastream/cocoa/AudioMediaStreamTrackRendererUnit.cpp (284673 => 284674)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/mediastream/cocoa/AudioMediaStreamTrackRendererUnit.cpp    2021-10-22 08:44:02 UTC (rev 284673)
+++ trunk/Source/WebCore/platform/mediastream/cocoa/AudioMediaStreamTrackRendererUnit.cpp       2021-10-22 08:44:57 UTC (rev 284674)
</span><span class="lines">@@ -46,16 +46,17 @@
</span><span class="cx"> 
</span><span class="cx"> static UniqueRef<AudioMediaStreamTrackRendererInternalUnit> createInternalUnit(AudioMediaStreamTrackRendererUnit& unit)
</span><span class="cx"> {
</span><del>-    AudioMediaStreamTrackRendererInternalUnit::RenderCallback callback = [&unit](auto sampleCount, auto& list, auto sampleTime, auto hostTime, auto& flags) {
</del><ins>+    AudioMediaStreamTrackRendererInternalUnit::RenderCallback renderCallback = [&unit](auto sampleCount, auto& list, auto sampleTime, auto hostTime, auto& flags) {
</ins><span class="cx">         unit.render(sampleCount, list, sampleTime, hostTime, flags);
</span><span class="cx">         return 0;
</span><span class="cx">     };
</span><ins>+    AudioMediaStreamTrackRendererInternalUnit::ResetCallback startCallback = [&unit]() { unit.reset(); };
</ins><span class="cx"> 
</span><span class="cx">     auto& function = getCreateInternalUnitFunction();
</span><span class="cx">     if (function)
</span><del>-        return function(WTFMove(callback));
</del><ins>+        return function(WTFMove(renderCallback), WTFMove(startCallback));
</ins><span class="cx"> 
</span><del>-    return AudioMediaStreamTrackRendererInternalUnit::createLocalInternalUnit(WTFMove(callback));
</del><ins>+    return AudioMediaStreamTrackRendererInternalUnit::createLocalInternalUnit(WTFMove(renderCallback), WTFMove(startCallback));
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> AudioMediaStreamTrackRendererUnit& AudioMediaStreamTrackRendererUnit::singleton()
</span><span class="lines">@@ -137,6 +138,16 @@
</span><span class="cx">     m_internalUnit->stop();
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void AudioMediaStreamTrackRendererUnit::reset()
+{
+    RELEASE_LOG(WebRTC, "AudioMediaStreamTrackRendererUnit::reset");
+    ASSERT(isMainThread());
+
+    m_resetObservers.forEach([](auto& observer) {
+        observer();
+    });
+}
+
</ins><span class="cx"> void AudioMediaStreamTrackRendererUnit::retrieveFormatDescription(CompletionHandler<void(const CAAudioStreamDescription*)>&& callback)
</span><span class="cx"> {
</span><span class="cx">     ASSERT(isMainThread());
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformmediastreamcocoaAudioMediaStreamTrackRendererUnith"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/mediastream/cocoa/AudioMediaStreamTrackRendererUnit.h (284673 => 284674)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/mediastream/cocoa/AudioMediaStreamTrackRendererUnit.h      2021-10-22 08:44:02 UTC (rev 284673)
+++ trunk/Source/WebCore/platform/mediastream/cocoa/AudioMediaStreamTrackRendererUnit.h 2021-10-22 08:44:57 UTC (rev 284674)
</span><span class="lines">@@ -31,8 +31,10 @@
</span><span class="cx"> #include <wtf/Forward.h>
</span><span class="cx"> #include <wtf/HashSet.h>
</span><span class="cx"> #include <wtf/Lock.h>
</span><ins>+#include <wtf/Observer.h>
</ins><span class="cx"> #include <wtf/UniqueRef.h>
</span><span class="cx"> #include <wtf/Vector.h>
</span><ins>+#include <wtf/WeakHashSet.h>
</ins><span class="cx"> 
</span><span class="cx"> namespace WebCore {
</span><span class="cx"> 
</span><span class="lines">@@ -48,10 +50,11 @@
</span><span class="cx">     AudioMediaStreamTrackRendererUnit();
</span><span class="cx">     ~AudioMediaStreamTrackRendererUnit();
</span><span class="cx"> 
</span><del>-    using CreateInternalUnitFunction = Function<UniqueRef<AudioMediaStreamTrackRendererInternalUnit>(AudioMediaStreamTrackRendererInternalUnit::RenderCallback&&)>;
</del><ins>+    using CreateInternalUnitFunction = Function<UniqueRef<AudioMediaStreamTrackRendererInternalUnit>(AudioMediaStreamTrackRendererInternalUnit::RenderCallback&&, AudioMediaStreamTrackRendererInternalUnit::ResetCallback&&)>;
</ins><span class="cx">     WEBCORE_EXPORT static void setCreateInternalUnitFunction(CreateInternalUnitFunction&&);
</span><span class="cx"> 
</span><span class="cx">     WEBCORE_EXPORT void render(size_t sampleCount, AudioBufferList&, uint64_t sampleTime, double hostTime, AudioUnitRenderActionFlags&);
</span><ins>+    void reset();
</ins><span class="cx"> 
</span><span class="cx">     void setAudioOutputDevice(const String&);
</span><span class="cx"> 
</span><span class="lines">@@ -58,6 +61,8 @@
</span><span class="cx">     void addSource(Ref<AudioSampleDataSource>&&);
</span><span class="cx">     void removeSource(AudioSampleDataSource&);
</span><span class="cx"> 
</span><ins>+    using ResetObserver = Observer<void()>;
+    void addResetObserver(ResetObserver& observer) { m_resetObservers.add(observer); }
</ins><span class="cx">     void retrieveFormatDescription(CompletionHandler<void(const CAAudioStreamDescription*)>&&);
</span><span class="cx"> 
</span><span class="cx"> private:
</span><span class="lines">@@ -73,6 +78,7 @@
</span><span class="cx">     bool m_hasPendingRenderSources WTF_GUARDED_BY_LOCK(m_pendingRenderSourcesLock) { false };
</span><span class="cx">     Lock m_pendingRenderSourcesLock;
</span><span class="cx">     UniqueRef<AudioMediaStreamTrackRendererInternalUnit> m_internalUnit;
</span><ins>+    WeakHashSet<ResetObserver> m_resetObservers;
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceWebKitChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/ChangeLog (284673 => 284674)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/ChangeLog    2021-10-22 08:44:02 UTC (rev 284673)
+++ trunk/Source/WebKit/ChangeLog       2021-10-22 08:44:57 UTC (rev 284674)
</span><span class="lines">@@ -1,3 +1,23 @@
</span><ins>+2021-10-22  Youenn Fablet  <youenn@apple.com>
+
+        Audio over peer connection becomes latent when changing the output
+        https://bugs.webkit.org/show_bug.cgi?id=231110
+        <rdar://problem/84049005>
+
+        Reviewed by Eric Carlson.
+
+        When detecting an audio timeline change, send it from GPUProcess to WebProcess.
+        Let the WebProcess reset the sources to properly restart.
+
+        * GPUProcess/webrtc/RemoteAudioMediaStreamTrackRendererInternalUnitManager.cpp:
+        * WebProcess/GPU/GPUProcessConnection.cpp:
+        * WebProcess/GPU/GPUProcessConnection.h:
+        * WebProcess/GPU/GPUProcessConnection.messages.in:
+        * WebProcess/GPU/webrtc/AudioMediaStreamTrackRendererInternalUnitManager.cpp:
+        * WebProcess/GPU/webrtc/AudioMediaStreamTrackRendererInternalUnitManager.h:
+        * WebProcess/WebProcess.cpp:
+        * WebProcess/cocoa/UserMediaCaptureManager.cpp:
+
</ins><span class="cx"> 2021-10-22  Kimmo Kinnunen  <kkinnunen@apple.com>
</span><span class="cx"> 
</span><span class="cx">         StreamConnectionWorkQueue is not thread-safe
</span></span></pre></div>
<a id="trunkSourceWebKitGPUProcesswebrtcRemoteAudioMediaStreamTrackRendererInternalUnitManagercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/GPUProcess/webrtc/RemoteAudioMediaStreamTrackRendererInternalUnitManager.cpp (284673 => 284674)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/GPUProcess/webrtc/RemoteAudioMediaStreamTrackRendererInternalUnitManager.cpp 2021-10-22 08:44:02 UTC (rev 284673)
+++ trunk/Source/WebKit/GPUProcess/webrtc/RemoteAudioMediaStreamTrackRendererInternalUnitManager.cpp    2021-10-22 08:44:57 UTC (rev 284674)
</span><span class="lines">@@ -57,6 +57,7 @@
</span><span class="cx">     void stop();
</span><span class="cx">     void setAudioOutputDevice(const String&);
</span><span class="cx">     OSStatus render(size_t sampleCount, AudioBufferList&, uint64_t sampleTime, double hostTime, AudioUnitRenderActionFlags&);
</span><ins>+    void notifyReset();
</ins><span class="cx"> 
</span><span class="cx"> private:
</span><span class="cx">     void storageChanged(SharedMemory*, const WebCore::CAAudioStreamDescription&, size_t);
</span><span class="lines">@@ -123,10 +124,17 @@
</span><span class="cx">     };
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+static WebCore::AudioMediaStreamTrackRendererInternalUnit::ResetCallback resetCallback(RemoteAudioMediaStreamTrackRendererInternalUnitManager::Unit& unit)
+{
+    return [&unit]() {
+        return unit.notifyReset();
+    };
+}
+
</ins><span class="cx"> RemoteAudioMediaStreamTrackRendererInternalUnitManager::Unit::Unit(AudioMediaStreamTrackRendererInternalUnitIdentifier identifier, Ref<IPC::Connection>&& connection, CompletionHandler<void(const WebCore::CAAudioStreamDescription&, size_t)>&& callback)
</span><span class="cx">     : m_identifier(identifier)
</span><span class="cx">     , m_connection(WTFMove(connection))
</span><del>-    , m_localUnit(WebCore::AudioMediaStreamTrackRendererInternalUnit::createLocalInternalUnit(renderCallback(*this)))
</del><ins>+    , m_localUnit(WebCore::AudioMediaStreamTrackRendererInternalUnit::createLocalInternalUnit(renderCallback(*this), resetCallback(*this)))
</ins><span class="cx"> {
</span><span class="cx">     m_localUnit->retrieveFormatDescription([weakThis = WeakPtr { *this }, this, callback = WTFMove(callback)](auto&& description) mutable {
</span><span class="cx">         if (!weakThis || !description) {
</span><span class="lines">@@ -144,6 +152,11 @@
</span><span class="cx">     stop();
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void RemoteAudioMediaStreamTrackRendererInternalUnitManager::Unit::notifyReset()
+{
+    m_connection->send(Messages::GPUProcessConnection::ResetAudioMediaStreamTrackRendererInternalUnit { m_identifier }, 0);
+}
+
</ins><span class="cx"> void RemoteAudioMediaStreamTrackRendererInternalUnitManager::Unit::start(const SharedMemory::Handle& handle, const WebCore::CAAudioStreamDescription& description, uint64_t numberOfFrames, IPC::Semaphore&& semaphore)
</span><span class="cx"> {
</span><span class="cx">     if (m_isPlaying)
</span></span></pre></div>
<a id="trunkSourceWebKitWebProcessGPUGPUProcessConnectioncpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/WebProcess/GPU/GPUProcessConnection.cpp (284673 => 284674)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/WebProcess/GPU/GPUProcessConnection.cpp      2021-10-22 08:44:02 UTC (rev 284673)
+++ trunk/Source/WebKit/WebProcess/GPU/GPUProcessConnection.cpp 2021-10-22 08:44:57 UTC (rev 284674)
</span><span class="lines">@@ -28,6 +28,7 @@
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(GPU_PROCESS)
</span><span class="cx"> 
</span><ins>+#include "AudioMediaStreamTrackRendererInternalUnitManager.h"
</ins><span class="cx"> #include "DataReference.h"
</span><span class="cx"> #include "GPUConnectionToWebProcessMessages.h"
</span><span class="cx"> #include "GPUProcessConnectionInitializationParameters.h"
</span><span class="lines">@@ -152,6 +153,11 @@
</span><span class="cx">         m_sampleBufferDisplayLayerManager = makeUnique<SampleBufferDisplayLayerManager>();
</span><span class="cx">     return *m_sampleBufferDisplayLayerManager;
</span><span class="cx"> }
</span><ins>+
+void GPUProcessConnection::resetAudioMediaStreamTrackRendererInternalUnit(AudioMediaStreamTrackRendererInternalUnitIdentifier identifier)
+{
+    WebProcess::singleton().audioMediaStreamTrackRendererInternalUnitManager().reset(identifier);
+}
</ins><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="cx"> RemoteMediaPlayerManager& GPUProcessConnection::mediaPlayerManager()
</span></span></pre></div>
<a id="trunkSourceWebKitWebProcessGPUGPUProcessConnectionh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/WebProcess/GPU/GPUProcessConnection.h (284673 => 284674)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/WebProcess/GPU/GPUProcessConnection.h        2021-10-22 08:44:02 UTC (rev 284673)
+++ trunk/Source/WebKit/WebProcess/GPU/GPUProcessConnection.h   2021-10-22 08:44:57 UTC (rev 284674)
</span><span class="lines">@@ -74,6 +74,7 @@
</span><span class="cx"> #endif
</span><span class="cx"> #if PLATFORM(COCOA) && ENABLE(MEDIA_STREAM)
</span><span class="cx">     SampleBufferDisplayLayerManager& sampleBufferDisplayLayerManager();
</span><ins>+    void resetAudioMediaStreamTrackRendererInternalUnit(AudioMediaStreamTrackRendererInternalUnitIdentifier);
</ins><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="cx">     RemoteMediaPlayerManager& mediaPlayerManager();
</span></span></pre></div>
<a id="trunkSourceWebKitWebProcessGPUGPUProcessConnectionmessagesin"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/WebProcess/GPU/GPUProcessConnection.messages.in (284673 => 284674)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/WebProcess/GPU/GPUProcessConnection.messages.in      2021-10-22 08:44:02 UTC (rev 284673)
+++ trunk/Source/WebKit/WebProcess/GPU/GPUProcessConnection.messages.in 2021-10-22 08:44:57 UTC (rev 284674)
</span><span class="lines">@@ -29,6 +29,9 @@
</span><span class="cx">     BeginRoutingArbitrationWithCategory(enum:uint8_t WebCore::AudioSession::CategoryType category) -> (enum:uint8_t WebKit::AudioSessionRoutingArbitratorProxy::RoutingArbitrationError error, enum:bool WebKit::AudioSessionRoutingArbitratorProxy::DefaultRouteChanged defaultRouteChanged) Async
</span><span class="cx">     EndRoutingArbitration();
</span><span class="cx"> #endif
</span><ins>+#if ENABLE(MEDIA_STREAM) && PLATFORM(COCOA)
+    ResetAudioMediaStreamTrackRendererInternalUnit(WebKit::AudioMediaStreamTrackRendererInternalUnitIdentifier identifier)
+#endif
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> #endif // ENABLE(GPU_PROCESS)
</span></span></pre></div>
<a id="trunkSourceWebKitWebProcessGPUwebrtcAudioMediaStreamTrackRendererInternalUnitManagercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/WebProcess/GPU/webrtc/AudioMediaStreamTrackRendererInternalUnitManager.cpp (284673 => 284674)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/WebProcess/GPU/webrtc/AudioMediaStreamTrackRendererInternalUnitManager.cpp   2021-10-22 08:44:02 UTC (rev 284673)
+++ trunk/Source/WebKit/WebProcess/GPU/webrtc/AudioMediaStreamTrackRendererInternalUnitManager.cpp      2021-10-22 08:44:57 UTC (rev 284674)
</span><span class="lines">@@ -45,12 +45,13 @@
</span><span class="cx"> class AudioMediaStreamTrackRendererInternalUnitManager::Proxy final : public WebCore::AudioMediaStreamTrackRendererInternalUnit, public CanMakeWeakPtr<Proxy> {
</span><span class="cx">     WTF_MAKE_FAST_ALLOCATED;
</span><span class="cx"> public:
</span><del>-    explicit Proxy(WebCore::AudioMediaStreamTrackRendererInternalUnit::RenderCallback&&);
</del><ins>+    Proxy(WebCore::AudioMediaStreamTrackRendererInternalUnit::RenderCallback&&, WebCore::AudioMediaStreamTrackRendererInternalUnit::ResetCallback&&);
</ins><span class="cx">     ~Proxy();
</span><span class="cx"> 
</span><span class="cx">     AudioMediaStreamTrackRendererInternalUnitIdentifier identifier() const { return m_identifier; }
</span><span class="cx"> 
</span><del>-    void restartIfNeeded();
</del><ins>+    enum class IsClosed { No, Yes };
+    void reset(IsClosed);
</ins><span class="cx"> 
</span><span class="cx"> private:
</span><span class="cx">     // AudioMediaStreamTrackRendererUnit::InternalUnit API.
</span><span class="lines">@@ -67,6 +68,7 @@
</span><span class="cx">     void createRemoteUnit();
</span><span class="cx"> 
</span><span class="cx">     WebCore::AudioMediaStreamTrackRendererInternalUnit::RenderCallback m_renderCallback;
</span><ins>+    WebCore::AudioMediaStreamTrackRendererInternalUnit::ResetCallback m_resetCallback;
</ins><span class="cx">     AudioMediaStreamTrackRendererInternalUnitIdentifier m_identifier;
</span><span class="cx"> 
</span><span class="cx">     Deque<CompletionHandler<void(const WebCore::CAAudioStreamDescription*)>> m_descriptionCallbacks;
</span><span class="lines">@@ -97,19 +99,27 @@
</span><span class="cx">     m_proxies.remove(proxy.identifier());
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-UniqueRef<WebCore::AudioMediaStreamTrackRendererInternalUnit> AudioMediaStreamTrackRendererInternalUnitManager::createRemoteInternalUnit(WebCore::AudioMediaStreamTrackRendererInternalUnit::RenderCallback&& callback)
</del><ins>+UniqueRef<WebCore::AudioMediaStreamTrackRendererInternalUnit> AudioMediaStreamTrackRendererInternalUnitManager::createRemoteInternalUnit(WebCore::AudioMediaStreamTrackRendererInternalUnit::RenderCallback&& renderCallback, WebCore::AudioMediaStreamTrackRendererInternalUnit::ResetCallback&& resetCallback)
</ins><span class="cx"> {
</span><del>-    return makeUniqueRef<AudioMediaStreamTrackRendererInternalUnitManager::Proxy>(WTFMove(callback));
</del><ins>+    return makeUniqueRef<AudioMediaStreamTrackRendererInternalUnitManager::Proxy>(WTFMove(renderCallback), WTFMove(resetCallback));
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-void AudioMediaStreamTrackRendererInternalUnitManager::gpuProcessConnectionClosed()
</del><ins>+void AudioMediaStreamTrackRendererInternalUnitManager::reset(AudioMediaStreamTrackRendererInternalUnitIdentifier identifier)
</ins><span class="cx"> {
</span><del>-    for (auto proxy : m_proxies.values())
-        proxy->restartIfNeeded();
</del><ins>+    if (auto proxy = m_proxies.get(identifier))
+        proxy->reset(Proxy::IsClosed::No);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-AudioMediaStreamTrackRendererInternalUnitManager::Proxy::Proxy(WebCore::AudioMediaStreamTrackRendererInternalUnit::RenderCallback&& renderCallback)
</del><ins>+void AudioMediaStreamTrackRendererInternalUnitManager::restartAllUnits()
+{
+    auto proxies = std::exchange(m_proxies, { });
+    for (auto proxy : proxies.values())
+        proxy->reset(Proxy::IsClosed::Yes);
+}
+
+AudioMediaStreamTrackRendererInternalUnitManager::Proxy::Proxy(WebCore::AudioMediaStreamTrackRendererInternalUnit::RenderCallback&& renderCallback, WebCore::AudioMediaStreamTrackRendererInternalUnit::ResetCallback&& resetCallback)
</ins><span class="cx">     : m_renderCallback(WTFMove(renderCallback))
</span><ins>+    , m_resetCallback(WTFMove(resetCallback))
</ins><span class="cx">     , m_identifier(AudioMediaStreamTrackRendererInternalUnitIdentifier::generate())
</span><span class="cx"> {
</span><span class="cx">     WebProcess::singleton().audioMediaStreamTrackRendererInternalUnitManager().add(*this);
</span><span class="lines">@@ -258,10 +268,11 @@
</span><span class="cx">     m_thread = Thread::create("AudioMediaStreamTrackRendererInternalUnit thread", WTFMove(threadLoop), ThreadType::Audio, Thread::QOS::UserInteractive);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void AudioMediaStreamTrackRendererInternalUnitManager::Proxy::restartIfNeeded()
</del><ins>+void AudioMediaStreamTrackRendererInternalUnitManager::Proxy::reset(IsClosed isClosed)
</ins><span class="cx"> {
</span><span class="cx">     stopThread();
</span><del>-    m_didClose = true;
</del><ins>+    m_didClose = isClosed == IsClosed::Yes;
+    m_resetCallback();
</ins><span class="cx">     if (m_isPlaying)
</span><span class="cx">         start();
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceWebKitWebProcessGPUwebrtcAudioMediaStreamTrackRendererInternalUnitManagerh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/WebProcess/GPU/webrtc/AudioMediaStreamTrackRendererInternalUnitManager.h (284673 => 284674)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/WebProcess/GPU/webrtc/AudioMediaStreamTrackRendererInternalUnitManager.h     2021-10-22 08:44:02 UTC (rev 284673)
+++ trunk/Source/WebKit/WebProcess/GPU/webrtc/AudioMediaStreamTrackRendererInternalUnitManager.h        2021-10-22 08:44:57 UTC (rev 284674)
</span><span class="lines">@@ -47,13 +47,14 @@
</span><span class="cx"> public:
</span><span class="cx">     AudioMediaStreamTrackRendererInternalUnitManager() = default;
</span><span class="cx"> 
</span><del>-    UniqueRef<WebCore::AudioMediaStreamTrackRendererInternalUnit> createRemoteInternalUnit(WebCore::AudioMediaStreamTrackRendererInternalUnit::RenderCallback&&);
</del><ins>+    UniqueRef<WebCore::AudioMediaStreamTrackRendererInternalUnit> createRemoteInternalUnit(WebCore::AudioMediaStreamTrackRendererInternalUnit::RenderCallback&&, WebCore::AudioMediaStreamTrackRendererInternalUnit::ResetCallback&&);
</ins><span class="cx"> 
</span><span class="cx">     class Proxy;
</span><span class="cx">     void add(Proxy&);
</span><span class="cx">     void remove(Proxy&);
</span><span class="cx"> 
</span><del>-    void gpuProcessConnectionClosed();
</del><ins>+    void reset(AudioMediaStreamTrackRendererInternalUnitIdentifier);
+    void restartAllUnits();
</ins><span class="cx"> 
</span><span class="cx"> private:
</span><span class="cx">     HashMap<AudioMediaStreamTrackRendererInternalUnitIdentifier, WeakPtr<Proxy>> m_proxies;
</span></span></pre></div>
<a id="trunkSourceWebKitWebProcessWebProcesscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/WebProcess/WebProcess.cpp (284673 => 284674)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/WebProcess/WebProcess.cpp    2021-10-22 08:44:02 UTC (rev 284673)
+++ trunk/Source/WebKit/WebProcess/WebProcess.cpp       2021-10-22 08:44:57 UTC (rev 284674)
</span><span class="lines">@@ -1310,7 +1310,7 @@
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(MEDIA_STREAM) && PLATFORM(COCOA)
</span><span class="cx">     if (m_audioMediaStreamTrackRendererInternalUnitManager)
</span><del>-        m_audioMediaStreamTrackRendererInternalUnitManager->gpuProcessConnectionClosed();
</del><ins>+        m_audioMediaStreamTrackRendererInternalUnitManager->restartAllUnits();
</ins><span class="cx"> #endif
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebKitWebProcesscocoaUserMediaCaptureManagercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/WebProcess/cocoa/UserMediaCaptureManager.cpp (284673 => 284674)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/WebProcess/cocoa/UserMediaCaptureManager.cpp 2021-10-22 08:44:02 UTC (rev 284673)
+++ trunk/Source/WebKit/WebProcess/cocoa/UserMediaCaptureManager.cpp    2021-10-22 08:44:57 UTC (rev 284674)
</span><span class="lines">@@ -81,8 +81,8 @@
</span><span class="cx">     m_videoFactory.setShouldCaptureInGPUProcess(shouldCaptureVideoInGPUProcess);
</span><span class="cx"> 
</span><span class="cx">     if (shouldCaptureAudioInGPUProcess) {
</span><del>-        WebCore::AudioMediaStreamTrackRendererUnit::setCreateInternalUnitFunction([](auto&& renderCallback) {
-            return WebProcess::singleton().audioMediaStreamTrackRendererInternalUnitManager().createRemoteInternalUnit(WTFMove(renderCallback));
</del><ins>+        WebCore::AudioMediaStreamTrackRendererUnit::setCreateInternalUnitFunction([](auto&& renderCallback, auto&& resetCallback) {
+            return WebProcess::singleton().audioMediaStreamTrackRendererInternalUnitManager().createRemoteInternalUnit(WTFMove(renderCallback), WTFMove(resetCallback));
</ins><span class="cx">         });
</span><span class="cx">     }
</span><span class="cx"> 
</span></span></pre>
</div>
</div>

</body>
</html>