Title: [286235] branches/safari-612-branch/Source/WebKit
Revision
286235
Author
repst...@apple.com
Date
2021-11-29 11:37:57 -0800 (Mon, 29 Nov 2021)

Log Message

Cherry-pick r285550. rdar://problem/85075538

    REGRESSION (Safari 15): AudioContext.currentTime speeds up (and audio won't play) when Bluetooth speaker connected
    https://bugs.webkit.org/show_bug.cgi?id=232728
    <rdar://problem/85075538>

    Reviewed by Jer Noble.

    This was a regression from us moving WebAudio to the GPUProcess in Safari 15. The issue occurred because the
    WebProcess (writer) would get further and further ahead of the GPUProcess (reader) after a hardware sample
    rate change.

    When rendering on https://mdn.github.io/webaudio-examples/audiocontext-states/ with a hardware sample rate of
    96Khz, RemoteAudioDestination::render() would get called with a numberOfFrame=128. Each time
    RemoteAudioDestination::render() was called, it would signal the IPC semaphore, causing the WebProcess to
    produce one WebAudio rendering quantum (128 frames). This would match perfectly and there would be no issues.
    However, if during playback, the hardware sample rate changes (which can happen when connecting to bluetooth
    speakers), CoreAudio would start calling RemoteAudioDestination::render() with a different numberOfFrame.
    For example, when switching the hardware sample rate to 44.1Khz, numberOfFrames would be 278. Every time it
    is called, render() would signal the semaphore 3 times, causing the WebProcess to produce 3 WebAudio rendering
    quantums (3 * 128 = 384 frames). So each time render() is called, the WebProcess would generate `384 - 278 = 105`
    frames too many, causing it to get further and further ahead of the GPUProcess. One symptom would be that
    AudioContext.currentTime would progress too fast. Also, eventually, our RingBuffer between the 2 process would
    fill up and lead to rendering issues.

    To address the issue, I updated RemoteAudioDestination::render() to keep track of how many extra samples it
    requested from the WebProcess previously. This avoids signalling the IPC semaphore too many times and the
    WebProcess can no longer get too far ahead of the GPUProcess. The logic matches what was already done in
    RemoteAudioMediaStreamTrackRendererInternalUnitManager::Unit::render().

    * GPUProcess/media/RemoteAudioDestinationManager.cpp:

    git-svn-id: https://svn.webkit.org/repository/webkit/trunk@285550 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Modified Paths

Diff

Modified: branches/safari-612-branch/Source/WebKit/ChangeLog (286234 => 286235)


--- branches/safari-612-branch/Source/WebKit/ChangeLog	2021-11-29 19:37:54 UTC (rev 286234)
+++ branches/safari-612-branch/Source/WebKit/ChangeLog	2021-11-29 19:37:57 UTC (rev 286235)
@@ -1,5 +1,74 @@
 2021-11-11  Alan Coon  <alanc...@apple.com>
 
+        Cherry-pick r285550. rdar://problem/85075538
+
+    REGRESSION (Safari 15): AudioContext.currentTime speeds up (and audio won't play) when Bluetooth speaker connected
+    https://bugs.webkit.org/show_bug.cgi?id=232728
+    <rdar://problem/85075538>
+    
+    Reviewed by Jer Noble.
+    
+    This was a regression from us moving WebAudio to the GPUProcess in Safari 15. The issue occurred because the
+    WebProcess (writer) would get further and further ahead of the GPUProcess (reader) after a hardware sample
+    rate change.
+    
+    When rendering on https://mdn.github.io/webaudio-examples/audiocontext-states/ with a hardware sample rate of
+    96Khz, RemoteAudioDestination::render() would get called with a numberOfFrame=128. Each time
+    RemoteAudioDestination::render() was called, it would signal the IPC semaphore, causing the WebProcess to
+    produce one WebAudio rendering quantum (128 frames). This would match perfectly and there would be no issues.
+    However, if during playback, the hardware sample rate changes (which can happen when connecting to bluetooth
+    speakers), CoreAudio would start calling RemoteAudioDestination::render() with a different numberOfFrame.
+    For example, when switching the hardware sample rate to 44.1Khz, numberOfFrames would be 278. Every time it
+    is called, render() would signal the semaphore 3 times, causing the WebProcess to produce 3 WebAudio rendering
+    quantums (3 * 128 = 384 frames). So each time render() is called, the WebProcess would generate `384 - 278 = 105`
+    frames too many, causing it to get further and further ahead of the GPUProcess. One symptom would be that
+    AudioContext.currentTime would progress too fast. Also, eventually, our RingBuffer between the 2 process would
+    fill up and lead to rendering issues.
+    
+    To address the issue, I updated RemoteAudioDestination::render() to keep track of how many extra samples it
+    requested from the WebProcess previously. This avoids signalling the IPC semaphore too many times and the
+    WebProcess can no longer get too far ahead of the GPUProcess. The logic matches what was already done in
+    RemoteAudioMediaStreamTrackRendererInternalUnitManager::Unit::render().
+    
+    * GPUProcess/media/RemoteAudioDestinationManager.cpp:
+    
+    
+    git-svn-id: https://svn.webkit.org/repository/webkit/trunk@285550 268f45cc-cd09-0410-ab3c-d52691b4dbfc
+
+    2021-11-09  Chris Dumez  <cdu...@apple.com>
+
+            REGRESSION (Safari 15): AudioContext.currentTime speeds up (and audio won't play) when Bluetooth speaker connected
+            https://bugs.webkit.org/show_bug.cgi?id=232728
+            <rdar://problem/85075538>
+
+            Reviewed by Jer Noble.
+
+            This was a regression from us moving WebAudio to the GPUProcess in Safari 15. The issue occurred because the
+            WebProcess (writer) would get further and further ahead of the GPUProcess (reader) after a hardware sample
+            rate change.
+
+            When rendering on https://mdn.github.io/webaudio-examples/audiocontext-states/ with a hardware sample rate of
+            96Khz, RemoteAudioDestination::render() would get called with a numberOfFrame=128. Each time
+            RemoteAudioDestination::render() was called, it would signal the IPC semaphore, causing the WebProcess to
+            produce one WebAudio rendering quantum (128 frames). This would match perfectly and there would be no issues.
+            However, if during playback, the hardware sample rate changes (which can happen when connecting to bluetooth
+            speakers), CoreAudio would start calling RemoteAudioDestination::render() with a different numberOfFrame.
+            For example, when switching the hardware sample rate to 44.1Khz, numberOfFrames would be 278. Every time it
+            is called, render() would signal the semaphore 3 times, causing the WebProcess to produce 3 WebAudio rendering
+            quantums (3 * 128 = 384 frames). So each time render() is called, the WebProcess would generate `384 - 278 = 105`
+            frames too many, causing it to get further and further ahead of the GPUProcess. One symptom would be that
+            AudioContext.currentTime would progress too fast. Also, eventually, our RingBuffer between the 2 process would
+            fill up and lead to rendering issues.
+
+            To address the issue, I updated RemoteAudioDestination::render() to keep track of how many extra samples it
+            requested from the WebProcess previously. This avoids signalling the IPC semaphore too many times and the
+            WebProcess can no longer get too far ahead of the GPUProcess. The logic matches what was already done in
+            RemoteAudioMediaStreamTrackRendererInternalUnitManager::Unit::render().
+
+            * GPUProcess/media/RemoteAudioDestinationManager.cpp:
+
+2021-11-11  Alan Coon  <alanc...@apple.com>
+
         Cherry-pick r285509. rdar://problem/83381842
 
     Fix wrong frame count of CARingBuffer in SpeechRecognitionRemoteRealtimeMediaSource

Modified: branches/safari-612-branch/Source/WebKit/GPUProcess/media/RemoteAudioDestinationManager.cpp (286234 => 286235)


--- branches/safari-612-branch/Source/WebKit/GPUProcess/media/RemoteAudioDestinationManager.cpp	2021-11-29 19:37:54 UTC (rev 286234)
+++ branches/safari-612-branch/Source/WebKit/GPUProcess/media/RemoteAudioDestinationManager.cpp	2021-11-29 19:37:57 UTC (rev 286235)
@@ -113,10 +113,12 @@
             status = noErr;
         }
 
-        for (unsigned i = 0; i < numberOfFrames; i += WebCore::AudioUtilities::renderQuantumSize) {
+        unsigned requestedSamplesCount = m_extraRequestedFrames;
+        for (; requestedSamplesCount < numberOfFrames; requestedSamplesCount += WebCore::AudioUtilities::renderQuantumSize) {
             // Ask the audio thread in the WebContent process to render a quantum.
             m_renderSemaphore.signal();
         }
+        m_extraRequestedFrames = requestedSamplesCount - numberOfFrames;
 
         return status;
     }
@@ -129,6 +131,7 @@
 
     UniqueRef<WebCore::CARingBuffer> m_ringBuffer;
     uint64_t m_startFrame { 0 };
+    unsigned m_extraRequestedFrames { 0 };
 #endif
     IPC::Semaphore m_renderSemaphore;
 
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to