Title: [272730] trunk/Source/WebCore
Revision
272730
Author
[email protected]
Date
2021-02-11 08:28:12 -0800 (Thu, 11 Feb 2021)

Log Message

Audio is sometimes distorted when using createMediaElementSource
https://bugs.webkit.org/show_bug.cgi?id=221553

Reviewed by Eric Carlson.

AudioSourceProviderAVFObjC::provideInput() was calculating the number of
frames available in the RingBuffer like so:
`endFrame - (m_readCount + writeAheadCount)`

The issue is that when writeAheadCount is greater than 0, (m_readCount + writeAheadCount)
can become greater than endFrame, causing us to end up with a super large number of
available frames. This can lead us to render garbage because we may be reading more
frames than available the RingBuffer.

I have also made a change in the case where rendering has already started were we ignore
writeAheadCount and render whatever we have in the RingBuffer. After we've started rendering,
deciding not to render because of writeAheadCount, even though there are available frames
in the RingBuffer, is really hurtful to user experience. This was reproducible on
https://www.waveplayer.info/createmediaelementsource-test/ where we would start rendering
for a bit, then output silence and then pick up rendering again (this time for good).

* platform/graphics/avfoundation/AudioSourceProviderAVFObjC.mm:
(WebCore::AudioSourceProviderAVFObjC::provideInput):

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (272729 => 272730)


--- trunk/Source/WebCore/ChangeLog	2021-02-11 16:22:34 UTC (rev 272729)
+++ trunk/Source/WebCore/ChangeLog	2021-02-11 16:28:12 UTC (rev 272730)
@@ -1,3 +1,29 @@
+2021-02-11  Chris Dumez  <[email protected]>
+
+        Audio is sometimes distorted when using createMediaElementSource
+        https://bugs.webkit.org/show_bug.cgi?id=221553
+
+        Reviewed by Eric Carlson.
+
+        AudioSourceProviderAVFObjC::provideInput() was calculating the number of
+        frames available in the RingBuffer like so:
+        `endFrame - (m_readCount + writeAheadCount)`
+
+        The issue is that when writeAheadCount is greater than 0, (m_readCount + writeAheadCount)
+        can become greater than endFrame, causing us to end up with a super large number of
+        available frames. This can lead us to render garbage because we may be reading more
+        frames than available the RingBuffer.
+
+        I have also made a change in the case where rendering has already started were we ignore
+        writeAheadCount and render whatever we have in the RingBuffer. After we've started rendering,
+        deciding not to render because of writeAheadCount, even though there are available frames
+        in the RingBuffer, is really hurtful to user experience. This was reproducible on
+        https://www.waveplayer.info/createmediaelementsource-test/ where we would start rendering
+        for a bit, then output silence and then pick up rendering again (this time for good).
+
+        * platform/graphics/avfoundation/AudioSourceProviderAVFObjC.mm:
+        (WebCore::AudioSourceProviderAVFObjC::provideInput):
+
 2021-02-11  Chris Lord  <[email protected]>
 
         Remove FontSelector dependence in CSSFontFace when creating a new FontFace wrapper

Modified: trunk/Source/WebCore/platform/graphics/avfoundation/AudioSourceProviderAVFObjC.mm (272729 => 272730)


--- trunk/Source/WebCore/platform/graphics/avfoundation/AudioSourceProviderAVFObjC.mm	2021-02-11 16:22:34 UTC (rev 272729)
+++ trunk/Source/WebCore/platform/graphics/avfoundation/AudioSourceProviderAVFObjC.mm	2021-02-11 16:28:12 UTC (rev 272730)
@@ -120,17 +120,24 @@
 
     m_ringBuffer->getCurrentFrameBounds(startFrame, endFrame);
 
-    size_t framesAvailable = static_cast<size_t>(endFrame - (m_readCount + writeAheadCount));
-    if (!framesAvailable) {
-        bus->zero();
-        return;
+    if (!m_readCount || m_readCount == seekTo) {
+        // We have not started rendering yet. If there aren't enough frames in the buffer, then output
+        // silence until there is.
+        if (endFrame <= m_readCount + writeAheadCount + framesToProcess) {
+            bus->zero();
+            return;
+        }
+    } else {
+        // We've started rendering. Don't output silence unless we really have to.
+        size_t framesAvailable = static_cast<size_t>(endFrame - m_readCount);
+        if (framesAvailable < framesToProcess) {
+            bus->zero();
+            if (!framesAvailable)
+                return;
+            framesToProcess = framesAvailable;
+        }
     }
 
-    if (framesAvailable < framesToProcess) {
-        framesToProcess = framesAvailable;
-        bus->zero();
-    }
-
     ASSERT(bus->numberOfChannels() == m_ringBuffer->channelCount());
 
     for (unsigned i = 0; i < m_list->mNumberBuffers; ++i) {
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to