⚠ Archived content — this site is no longer maintained.   Current WebKit documentation is at docs.webkit.org.

Changeset 268758 in webkit


Ignore:
Timestamp:
Oct 20, 2020, 1:42:08 PM (6 years ago)
Author:
Peng Liu
Message:

[Media in GPU Process] Some WebAudio layout tests generate strange noises
https://bugs.webkit.org/show_bug.cgi?id=217921

Reviewed by Eric Carlson.

RemoteAudioDestination::render() should not return noErr unless we can provide the requested
samples to the provided AudioBufferList. Otherwise, the audio output unit of CoreAudio will output
the samples in the AudioBufferList, which might be invalid data at the beginning of a rendering.
We have observed that happens in some layout tests and some WebAudio example pages.

Currently, RemoteAudioDestination::render() always returns noErr in the render thread (immediately),
but the AudioBufferList (ioData) is updated in the main thread (later). This patch fixes that by only
setting the bounds of CARingBuffer in the completion handler of sendWithAsyncReply() in the main thread,
and fetching AudioBuffer(s) from the CARingBuffer in the render thread. Also, RemoteAudioDestination
tracks the progress of fetching, so RemoteAudioDestinationProxy does not need to send startFrame
and numberOfFramesToRender to RemoteAudioDestination in response to a buffer request.

  • GPUProcess/media/RemoteAudioDestinationManager.cpp:

(WebKit::RemoteAudioDestination::audioSamplesStorageChanged):
(WebKit::RemoteAudioDestination::render): Only return noErr if the function renders the requested
sample successfully.

  • WebProcess/GPU/media/RemoteAudioDestinationProxy.cpp:

(WebKit::RemoteAudioDestinationProxy::requestBuffer): Remove unused parameters.
(WebKit::RemoteAudioDestinationProxy::renderOnRenderingThead): Ditto.

  • WebProcess/GPU/media/RemoteAudioDestinationProxy.h: Ditto.
  • WebProcess/GPU/media/RemoteAudioDestinationProxy.messages.in: Ditto.
Location:
trunk/Source/WebKit
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebKit/ChangeLog

    r268736 r268758  
     12020-10-20  Peng Liu  <peng.liu6@apple.com>
     2
     3        [Media in GPU Process] Some WebAudio layout tests generate strange noises
     4        https://bugs.webkit.org/show_bug.cgi?id=217921
     5
     6        Reviewed by Eric Carlson.
     7
     8        RemoteAudioDestination::render() should not return `noErr` unless we can provide the requested
     9        samples to the provided AudioBufferList. Otherwise, the audio output unit of CoreAudio will output
     10        the samples in the AudioBufferList, which might be invalid data at the beginning of a rendering.
     11        We have observed that happens in some layout tests and some WebAudio example pages.
     12
     13        Currently, RemoteAudioDestination::render() always returns `noErr` in the render thread (immediately),
     14        but the AudioBufferList (ioData) is updated in the main thread (later). This patch fixes that by only
     15        setting the bounds of CARingBuffer in the completion handler of sendWithAsyncReply() in the main thread,
     16        and fetching AudioBuffer(s) from the CARingBuffer in the render thread. Also, RemoteAudioDestination
     17        tracks the progress of fetching, so RemoteAudioDestinationProxy does not need to send `startFrame`
     18        and `numberOfFramesToRender` to RemoteAudioDestination in response to a buffer request.
     19
     20        * GPUProcess/media/RemoteAudioDestinationManager.cpp:
     21        (WebKit::RemoteAudioDestination::audioSamplesStorageChanged):
     22        (WebKit::RemoteAudioDestination::render): Only return `noErr` if the function renders the requested
     23        sample successfully.
     24
     25        * WebProcess/GPU/media/RemoteAudioDestinationProxy.cpp:
     26        (WebKit::RemoteAudioDestinationProxy::requestBuffer): Remove unused parameters.
     27        (WebKit::RemoteAudioDestinationProxy::renderOnRenderingThead): Ditto.
     28        * WebProcess/GPU/media/RemoteAudioDestinationProxy.h: Ditto.
     29        * WebProcess/GPU/media/RemoteAudioDestinationProxy.messages.in: Ditto.
     30
    1312020-10-20  Chris Dumez  <cdumez@apple.com>
    232
  • trunk/Source/WebKit/GPUProcess/media/RemoteAudioDestinationManager.cpp

    r268690 r268758  
    8383        storage().setStorage(WTFMove(memory));
    8484        storage().setReadOnly(true);
    85 
    8685        m_ringBuffer->allocate(description, numberOfFrames);
    8786    }
     
    139138        ASSERT(!isMainThread());
    140139
    141         if (m_protectThisDuringGracefulShutdown)
    142             return noErr;
    143 
    144         m_connection.connection().sendWithAsyncReply(Messages::RemoteAudioDestinationProxy::RequestBuffer(sampleTime, hostTime, numberOfFrames), CompletionHandler<void(uint64_t, uint64_t, uint64_t, uint64_t)>([this, protectedThis = makeRef(*this), ioData](auto startFrame, auto numberOfFramesToRender, auto boundsStartFrame, auto boundsEndFrame) mutable {
     140        OSStatus status = -1;
     141
     142        if (m_protectThisDuringGracefulShutdown || !m_isPlaying)
     143            return status;
     144
     145        uint64_t start;
     146        uint64_t end;
     147        m_ringBuffer->getCurrentFrameBounds(start, end);
     148        if (m_startFrame >= start && m_startFrame + numberOfFrames <= end) {
     149            m_ringBuffer->fetch(ioData, numberOfFrames, m_startFrame);
     150            m_startFrame += numberOfFrames;
     151            status = noErr;
     152        }
     153
     154        m_connection.connection().sendWithAsyncReply(Messages::RemoteAudioDestinationProxy::RequestBuffer(sampleTime, hostTime, numberOfFrames), CompletionHandler<void(uint64_t, uint64_t)>([this, protectedThis = makeRef(*this)](auto boundsStartFrame, auto boundsEndFrame) mutable {
    145155            ASSERT(isMainThread());
    146             m_ringBuffer->setCurrentFrameBounds(boundsStartFrame, boundsEndFrame);
    147             m_ringBuffer->fetch(ioData, numberOfFramesToRender, startFrame);
     156            if (boundsEndFrame)
     157                m_ringBuffer->setCurrentFrameBounds(boundsStartFrame, boundsEndFrame);
    148158        }, CompletionHandlerCallThread::MainThread), m_id.toUInt64());
    149159
    150         return noErr;
     160        return status;
    151161    }
    152162#endif
     
    162172    WebCore::CAAudioStreamDescription m_description;
    163173    UniqueRef<WebCore::CARingBuffer> m_ringBuffer;
     174    uint64_t m_startFrame { 0 };
    164175#endif
    165176
  • trunk/Source/WebKit/WebProcess/GPU/media/RemoteAudioDestinationProxy.cpp

    r268632 r268758  
    124124
    125125#if PLATFORM(COCOA)
    126 void RemoteAudioDestinationProxy::requestBuffer(double sampleTime, uint64_t hostTime, uint64_t numberOfFrames, CompletionHandler<void(uint64_t, uint64_t, uint64_t, uint64_t)>&& completionHandler)
     126void RemoteAudioDestinationProxy::requestBuffer(double sampleTime, uint64_t hostTime, uint64_t numberOfFrames, CompletionHandler<void(uint64_t, uint64_t)>&& completionHandler)
    127127{
    128128    ASSERT(!isMainThread());
    129129
    130130    if (!hasEnoughFrames(numberOfFrames))
    131         completionHandler(0, 0, 0, 0);
     131        completionHandler(0, 0);
    132132
    133133    m_renderCompletionHandler = WTFMove(completionHandler);
     
    151151    uint64_t boundsEndFrame;
    152152    m_ringBuffer->getCurrentFrameBounds(boundsStartFrame, boundsEndFrame);
    153     m_renderCompletionHandler(startFrame, framesToRender, boundsStartFrame, boundsEndFrame);
     153    m_renderCompletionHandler(boundsStartFrame, boundsEndFrame);
    154154}
    155155#endif
  • trunk/Source/WebKit/WebProcess/GPU/media/RemoteAudioDestinationProxy.h

    r268632 r268758  
    7272
    7373#if PLATFORM(COCOA)
    74     void requestBuffer(double sampleTime, uint64_t hostTime, uint64_t numberOfFrames, CompletionHandler<void(uint64_t startFrame, uint64_t numberOfFramesToRender, uint64_t boundsStartFrame, uint64_t boundsEndFrame)>&&);
     74    void requestBuffer(double sampleTime, uint64_t hostTime, uint64_t numberOfFrames, CompletionHandler<void(uint64_t boundsStartFrame, uint64_t boundsEndFrame)>&&);
    7575#endif
    7676
     
    106106    std::unique_ptr<WebCore::WebAudioBufferList> m_audioBufferList;
    107107    uint64_t m_currentFrame { 0 };
    108     WTF::Function<void(uint64_t, uint64_t, uint64_t, uint64_t)> m_renderCompletionHandler;
     108    WTF::Function<void(uint64_t, uint64_t)> m_renderCompletionHandler;
    109109#endif
    110110
  • trunk/Source/WebKit/WebProcess/GPU/media/RemoteAudioDestinationProxy.messages.in

    r268632 r268758  
    2626messages -> RemoteAudioDestinationProxy NotRefCounted {
    2727#if PLATFORM(COCOA)
    28     RequestBuffer(double sampleTime, uint64_t hostTime, uint64_t numberOfFrames) -> (uint64_t startFrame, uint64_t numberOfFramesToRender, uint64_t boundsStartFrame, uint64_t boundsEndFrame) Async
     28    RequestBuffer(double sampleTime, uint64_t hostTime, uint64_t numberOfFrames) -> (uint64_t boundsStartFrame, uint64_t boundsEndFrame) Async
    2929#endif
    3030}
Note: See TracChangeset for help on using the changeset viewer.