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

Changeset 270947 in webkit


Ignore:
Timestamp:
Dec 17, 2020, 2:23:39 PM (6 years ago)
Author:
Chris Dumez
Message:

[WebAudio] Simplify code related to dispatchToRenderThread
https://bugs.webkit.org/show_bug.cgi?id=219990

Reviewed by Geoffrey Garen.

Simplify code related to dispatchToRenderThread in WebAudio:

  1. AudioDestination::start() now always gets called with a non-null dispatchToRenderThread lambda. In the case where there is no AudioWorkletThread to dispatch to, the lambda simply calls its task synchronously.
  2. For Cocoa ports, make it so that only AudioDestinationCocoa needs to worry about the dispatchToRenderThread lambda. The dispatchToRenderThread lambda is no longer exposed to subclasses such as MockAudioDestinationCocoa & RemoteAudioDestinationProxy.

Source/WebCore:

  • Modules/webaudio/DefaultAudioDestinationNode.cpp:

(WebCore::Function<void):

  • platform/audio/cocoa/AudioDestinationCocoa.cpp:

(WebCore::AudioDestinationCocoa::start):
(WebCore::AudioDestinationCocoa::startRendering):
(WebCore::AudioDestinationCocoa::stop):
(WebCore::AudioDestinationCocoa::stopRendering):
(WebCore::AudioDestinationCocoa::render):

  • platform/audio/cocoa/AudioDestinationCocoa.h:
  • platform/audio/gstreamer/AudioDestinationGStreamer.cpp:

(WebCore::AudioDestinationGStreamer::start):

  • platform/mock/MockAudioDestinationCocoa.cpp:

(WebCore::MockAudioDestinationCocoa::startRendering):
(WebCore::MockAudioDestinationCocoa::stopRendering):
(WebCore::MockAudioDestinationCocoa::tick):

  • platform/mock/MockAudioDestinationCocoa.h:

Source/WebKit:

  • WebProcess/GPU/media/RemoteAudioDestinationProxy.cpp:

(WebKit::RemoteAudioDestinationProxy::startRenderingThread):
(WebKit::RemoteAudioDestinationProxy::startRendering):
(WebKit::RemoteAudioDestinationProxy::stopRendering):
(WebKit::RemoteAudioDestinationProxy::gpuProcessConnectionDidClose):

  • WebProcess/GPU/media/RemoteAudioDestinationProxy.h:
Location:
trunk/Source
Files:
12 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r270943 r270947  
     12020-12-17  Chris Dumez  <cdumez@apple.com>
     2
     3        [WebAudio] Simplify code related to dispatchToRenderThread
     4        https://bugs.webkit.org/show_bug.cgi?id=219990
     5
     6        Reviewed by Geoffrey Garen.
     7
     8        Simplify code related to dispatchToRenderThread in WebAudio:
     9        1. AudioDestination::start() now always gets called with a non-null dispatchToRenderThread lambda.
     10           In the case where there is no AudioWorkletThread to dispatch to, the lambda simply calls its
     11           task synchronously.
     12        2. For Cocoa ports, make it so that only AudioDestinationCocoa needs to worry about the
     13           dispatchToRenderThread lambda. The dispatchToRenderThread lambda is no longer exposed to
     14           subclasses such as MockAudioDestinationCocoa & RemoteAudioDestinationProxy.
     15
     16        * Modules/webaudio/DefaultAudioDestinationNode.cpp:
     17        (WebCore::Function<void):
     18        * platform/audio/cocoa/AudioDestinationCocoa.cpp:
     19        (WebCore::AudioDestinationCocoa::start):
     20        (WebCore::AudioDestinationCocoa::startRendering):
     21        (WebCore::AudioDestinationCocoa::stop):
     22        (WebCore::AudioDestinationCocoa::stopRendering):
     23        (WebCore::AudioDestinationCocoa::render):
     24        * platform/audio/cocoa/AudioDestinationCocoa.h:
     25        * platform/audio/gstreamer/AudioDestinationGStreamer.cpp:
     26        (WebCore::AudioDestinationGStreamer::start):
     27        * platform/mock/MockAudioDestinationCocoa.cpp:
     28        (WebCore::MockAudioDestinationCocoa::startRendering):
     29        (WebCore::MockAudioDestinationCocoa::stopRendering):
     30        (WebCore::MockAudioDestinationCocoa::tick):
     31        * platform/mock/MockAudioDestinationCocoa.h:
     32
    1332020-12-17  Jer Noble  <jer.noble@apple.com>
    234
  • trunk/Source/WebCore/Headers.cmake

    r270587 r270947  
    11171117    platform/audio/PlatformMediaSessionManager.h
    11181118    platform/audio/PushPullFIFO.h
     1119
     1120    platform/audio/gstreamer/AudioDestinationGStreamer.h
    11191121
    11201122    platform/encryptedmedia/CDMEncryptionScheme.h
  • trunk/Source/WebCore/Modules/webaudio/DefaultAudioDestinationNode.cpp

    r270840 r270947  
    134134        };
    135135    }
    136     return { };
     136    return [](Function<void()>&& function) { function(); };
    137137}
    138138
  • trunk/Source/WebCore/platform/audio/cocoa/AudioDestinationCocoa.cpp

    r270840 r270947  
    105105void AudioDestinationCocoa::start(Function<void(Function<void()>&&)>&& dispatchToRenderThread, CompletionHandler<void(bool)>&& completionHandler)
    106106{
     107    ASSERT(isMainThread());
    107108    LOG(Media, "AudioDestinationCocoa::start");
    108     m_dispatchToRenderThread = WTFMove(dispatchToRenderThread);
     109    {
     110        auto locker = holdLock(m_dispatchToRenderThreadLock);
     111        m_dispatchToRenderThread = WTFMove(dispatchToRenderThread);
     112    }
     113    startRendering(WTFMove(completionHandler));
     114}
     115
     116void AudioDestinationCocoa::startRendering(CompletionHandler<void(bool)>&& completionHandler)
     117{
     118    ASSERT(isMainThread());
    109119    auto success = m_audioOutputUnitAdaptor.start() == noErr;
    110120    if (success)
     
    118128void AudioDestinationCocoa::stop(CompletionHandler<void(bool)>&& completionHandler)
    119129{
     130    ASSERT(isMainThread());
    120131    LOG(Media, "AudioDestinationCocoa::stop");
     132    stopRendering(WTFMove(completionHandler));
     133    {
     134        auto locker = holdLock(m_dispatchToRenderThreadLock);
     135        m_dispatchToRenderThread = nullptr;
     136    }
     137}
     138
     139void AudioDestinationCocoa::stopRendering(CompletionHandler<void(bool)>&& completionHandler)
     140{
     141    ASSERT(isMainThread());
    121142    auto success = m_audioOutputUnitAdaptor.stop() == noErr;
    122     auto dispatchToRenderThread = std::exchange(m_dispatchToRenderThread, nullptr);
    123143    if (success)
    124144        setIsPlaying(false);
    125145
    126     auto callCompletionHandlerOnMainThread = [completionHandler = WTFMove(completionHandler), success]() mutable {
    127         callOnMainThread([completionHandler = WTFMove(completionHandler), success]() mutable {
    128             completionHandler(success);
    129         });
    130     };
    131 
    132     if (dispatchToRenderThread) {
    133         // Do a round-trip to the worklet thread to make sure we call the completion handler after
    134         // the last rendering quantum has been processed by the worklet thread.
    135         dispatchToRenderThread(WTFMove(callCompletionHandlerOnMainThread));
    136     } else
    137         callCompletionHandlerOnMainThread();
     146    callOnMainThread([completionHandler = WTFMove(completionHandler), success]() mutable {
     147        completionHandler(success);
     148    });
    138149}
    139150
     
    188199OSStatus AudioDestinationCocoa::render(double sampleTime, uint64_t hostTime, UInt32 numberOfFrames, AudioBufferList* ioData)
    189200{
     201    ASSERT(!isMainThread());
     202
    190203    if (!hasEnoughFrames(numberOfFrames))
    191204        return noErr;
     
    209222
    210223    // When there is a AudioWorklet, we do rendering on the AudioWorkletThread.
    211     if (m_dispatchToRenderThread) {
    212         m_dispatchToRenderThread([this, protectedThis = makeRef(*this), framesToRender]() mutable {
    213             auto locker = tryHoldLock(m_isPlayingLock);
    214             if (locker && m_isPlaying)
    215                 renderOnRenderingThead(framesToRender);
    216         });
    217     } else
    218         renderOnRenderingThead(framesToRender);
     224    auto locker = tryHoldLock(m_dispatchToRenderThreadLock);
     225    if (!locker || !m_dispatchToRenderThread)
     226        return -1;
     227
     228    m_dispatchToRenderThread([this, protectedThis = makeRef(*this), framesToRender]() mutable {
     229        auto locker = tryHoldLock(m_isPlayingLock);
     230        if (locker && m_isPlaying)
     231            renderOnRenderingThead(framesToRender);
     232    });
    219233
    220234    return noErr;
  • trunk/Source/WebCore/platform/audio/cocoa/AudioDestinationCocoa.h

    r270840 r270947  
    6666    friend Ref<AudioDestination> AudioDestination::create(AudioIOCallback&, const String&, unsigned, unsigned, float);
    6767
    68     void start(Function<void(Function<void()>&&)>&&, CompletionHandler<void(bool)>&&) override;
    69     void stop(CompletionHandler<void(bool)>&&) override;
     68    WEBCORE_EXPORT void start(Function<void(Function<void()>&&)>&& dispatchToRenderThread, CompletionHandler<void(bool)>&&) final;
     69    WEBCORE_EXPORT void stop(CompletionHandler<void(bool)>&&) final;
     70
     71    virtual void startRendering(CompletionHandler<void(bool)>&&);
     72    virtual void stopRendering(CompletionHandler<void(bool)>&&);
    7073
    7174    void renderOnRenderingThead(size_t framesToRender);
     
    8790    AudioIOPosition m_outputTimestamp;
    8891
     92    Lock m_dispatchToRenderThreadLock;
    8993    Function<void(Function<void()>&&)> m_dispatchToRenderThread;
    9094
  • trunk/Source/WebCore/platform/audio/gstreamer/AudioDestinationGStreamer.cpp

    r270840 r270947  
    220220void AudioDestinationGStreamer::start(Function<void(Function<void()>&&)>&& dispatchToRenderThread, CompletionHandler<void(bool)>&& completionHandler)
    221221{
     222    webkitWebAudioSourceSetDispatchToRenderThreadCallback(WEBKIT_WEB_AUDIO_SRC(m_src.get()), WTFMove(dispatchToRenderThread));
     223    startRendering(WTFMove(completionHandler));
     224}
     225
     226void AudioDestinationGStreamer::startRendering(CompletionHandler<void(bool)>&& completionHandler)
     227{
    222228    ASSERT(m_audioSinkAvailable);
    223229    bool success = false;
    224230    if (m_audioSinkAvailable) {
    225         if (dispatchToRenderThread)
    226             webkitWebAudioSourceSetDispatchToRenderThreadCallback(WEBKIT_WEB_AUDIO_SRC(m_src.get()), WTFMove(dispatchToRenderThread));
    227 
    228231        GST_DEBUG("Starting");
    229232        if (gst_element_set_state(m_pipeline.get(), GST_STATE_PLAYING) == GST_STATE_CHANGE_FAILURE) {
     
    243246void AudioDestinationGStreamer::stop(CompletionHandler<void(bool)>&& completionHandler)
    244247{
     248    stopRendering(WTFMove(completionHandler));
     249}
     250
     251void AudioDestinationGStreamer::stopRendering(CompletionHandler<void(bool)>&& completionHandler)
     252{
    245253    ASSERT(m_audioSinkAvailable);
    246254    bool success = false;
  • trunk/Source/WebCore/platform/audio/gstreamer/AudioDestinationGStreamer.h

    r270840 r270947  
    3535    virtual ~AudioDestinationGStreamer();
    3636
    37     void start(Function<void(Function<void()>&&)>&& dispatchToRenderThread, CompletionHandler<void(bool)>&&) override;
    38     void stop(CompletionHandler<void(bool)>&&) override;
     37    WEBCORE_EXPORT void start(Function<void(Function<void()>&&)>&& dispatchToRenderThread, CompletionHandler<void(bool)>&&) final;
     38    WEBCORE_EXPORT void stop(CompletionHandler<void(bool)>&&) final;
    3939
    4040    bool isPlaying() override { return m_isPlaying; }
     
    4343
    4444    gboolean handleMessage(GstMessage*);
     45
     46protected:
     47    virtual void startRendering(CompletionHandler<void(bool)>&&);
     48    virtual void stopRendering(CompletionHandler<void(bool)>&&);
    4549
    4650private:
  • trunk/Source/WebCore/platform/mock/MockAudioDestinationCocoa.cpp

    r269630 r270947  
    4646MockAudioDestinationCocoa::~MockAudioDestinationCocoa() = default;
    4747
    48 void MockAudioDestinationCocoa::start(Function<void(Function<void()>&&)>&& dispatchToRenderThread, CompletionHandler<void(bool)>&& completionHandler)
     48void MockAudioDestinationCocoa::startRendering(CompletionHandler<void(bool)>&& completionHandler)
    4949{
    50     m_dispatchToRenderThread = WTFMove(dispatchToRenderThread);
    51     if (!m_dispatchToRenderThread) {
    52         m_dispatchToRenderThread = [this](Function<void()>&& function) {
    53             m_workQueue->dispatch(WTFMove(function));
    54         };
    55     }
    56 
    5750    m_timer.startRepeating(Seconds { m_numberOfFramesToProcess / sampleRate() });
    5851    setIsPlaying(true);
     
    6356}
    6457
    65 void MockAudioDestinationCocoa::stop(CompletionHandler<void(bool)>&& completionHandler)
     58void MockAudioDestinationCocoa::stopRendering(CompletionHandler<void(bool)>&& completionHandler)
    6659{
    6760    m_timer.stop();
    6861    setIsPlaying(false);
    6962
    70     m_dispatchToRenderThread([completionHandler = WTFMove(completionHandler)]() mutable {
    71         callOnMainThread([completionHandler = WTFMove(completionHandler)]() mutable {
    72             completionHandler(true);
    73         });
     63    callOnMainThread([completionHandler = WTFMove(completionHandler)]() mutable {
     64        completionHandler(true);
    7465    });
    7566}
     
    7768void MockAudioDestinationCocoa::tick()
    7869{
    79     m_dispatchToRenderThread([this, sampleRate = sampleRate(), numberOfFramesToProcess = m_numberOfFramesToProcess] {
     70    m_workQueue->dispatch([this, protectedThis = makeRef(*this), sampleRate = sampleRate(), numberOfFramesToProcess = m_numberOfFramesToProcess] {
    8071        AudioStreamBasicDescription streamFormat;
    8172        getAudioStreamBasicDescription(streamFormat);
  • trunk/Source/WebCore/platform/mock/MockAudioDestinationCocoa.h

    r270808 r270947  
    4848
    4949private:
    50     void start(Function<void(Function<void()>&&)>&&, CompletionHandler<void(bool)>&&) final;
    51     void stop(CompletionHandler<void(bool)>&&) final;
     50    void startRendering(CompletionHandler<void(bool)>&&) final;
     51    void stopRendering(CompletionHandler<void(bool)>&&) final;
    5252
    5353    void tick();
     
    5555    Ref<WorkQueue> m_workQueue;
    5656    RunLoop::Timer<MockAudioDestinationCocoa> m_timer;
    57     Function<void(Function<void()>&&)> m_dispatchToRenderThread;
    5857    uint32_t m_numberOfFramesToProcess { 384 };
    5958};
  • trunk/Source/WebKit/ChangeLog

    r270946 r270947  
     12020-12-17  Chris Dumez  <cdumez@apple.com>
     2
     3        [WebAudio] Simplify code related to dispatchToRenderThread
     4        https://bugs.webkit.org/show_bug.cgi?id=219990
     5
     6        Reviewed by Geoffrey Garen.
     7
     8        Simplify code related to dispatchToRenderThread in WebAudio:
     9        1. AudioDestination::start() now always gets called with a non-null dispatchToRenderThread lambda.
     10           In the case where there is no AudioWorkletThread to dispatch to, the lambda simply calls its
     11           task synchronously.
     12        2. For Cocoa ports, make it so that only AudioDestinationCocoa needs to worry about the
     13           dispatchToRenderThread lambda. The dispatchToRenderThread lambda is no longer exposed to
     14           subclasses such as MockAudioDestinationCocoa & RemoteAudioDestinationProxy.
     15
     16        * WebProcess/GPU/media/RemoteAudioDestinationProxy.cpp:
     17        (WebKit::RemoteAudioDestinationProxy::startRenderingThread):
     18        (WebKit::RemoteAudioDestinationProxy::startRendering):
     19        (WebKit::RemoteAudioDestinationProxy::stopRendering):
     20        (WebKit::RemoteAudioDestinationProxy::gpuProcessConnectionDidClose):
     21        * WebProcess/GPU/media/RemoteAudioDestinationProxy.h:
     22
    1232020-12-17  Alex Christensen  <achristensen@webkit.org>
    224
  • trunk/Source/WebKit/WebProcess/GPU/media/RemoteAudioDestinationProxy.cpp

    r270938 r270947  
    6464    , m_sampleRate(hardwareSampleRate())
    6565#else
    66     : WebCore::AudioDestination(callback)
     66    : WebCore::AudioDestinationGStreamer(callback, numberOfOutputChannels, sampleRate)
    6767    , m_numberOfOutputChannels(numberOfOutputChannels)
    6868#endif
     
    8484                break;
    8585
    86             if (m_dispatchToRenderThread) {
    87                 // If there is an AudioWorklet active, we need to render the quantum on the AudioWorkletThread.
    88                 m_dispatchToRenderThread([this, protectedThis = makeRef(*this)] {
    89                     renderQuantum();
    90                 });
    91             } else
    92                 renderQuantum();
     86            renderQuantum();
    9387        } while (!m_shouldStopThread);
    9488    };
     
    159153}
    160154
    161 void RemoteAudioDestinationProxy::start(Function<void(Function<void()>&&)>&& dispatchToRenderThread, CompletionHandler<void(bool)>&& completionHandler)
    162 {
    163     WebProcess::singleton().ensureGPUProcessConnection().connection().sendWithAsyncReply(Messages::RemoteAudioDestinationManager::StartAudioDestination(m_destinationID), [this, protectedThis = makeRef(*this), completionHandler = WTFMove(completionHandler), dispatchToRenderThread = WTFMove(dispatchToRenderThread)](bool isPlaying) mutable {
    164         m_dispatchToRenderThread = WTFMove(dispatchToRenderThread);
     155void RemoteAudioDestinationProxy::startRendering(CompletionHandler<void(bool)>&& completionHandler)
     156{
     157    WebProcess::singleton().ensureGPUProcessConnection().connection().sendWithAsyncReply(Messages::RemoteAudioDestinationManager::StartAudioDestination(m_destinationID), [this, protectedThis = makeRef(*this), completionHandler = WTFMove(completionHandler)](bool isPlaying) mutable {
    165158        setIsPlaying(isPlaying);
    166159        completionHandler(isPlaying);
     
    168161}
    169162
    170 void RemoteAudioDestinationProxy::stop(CompletionHandler<void(bool)>&& completionHandler)
     163void RemoteAudioDestinationProxy::stopRendering(CompletionHandler<void(bool)>&& completionHandler)
    171164{
    172165    WebProcess::singleton().ensureGPUProcessConnection().connection().sendWithAsyncReply(Messages::RemoteAudioDestinationManager::StopAudioDestination(m_destinationID), [this, protectedThis = makeRef(*this), completionHandler = WTFMove(completionHandler)](bool isPlaying) mutable {
    173166        setIsPlaying(isPlaying);
    174         auto callCompletionHandler = [completionHandler = WTFMove(completionHandler), isPlaying]() mutable {
    175             completionHandler(!isPlaying);
    176         };
    177         auto dispatchToRenderThread = std::exchange(m_dispatchToRenderThread, nullptr);
    178         if (dispatchToRenderThread) {
    179             // Do a round-trip to the worklet thread to make sure we call the completion handler after
    180             // the last rendering quantum has been processed by the worklet thread.
    181             dispatchToRenderThread([callCompletionHandler = WTFMove(callCompletionHandler)]() mutable {
    182                 callOnMainThread(WTFMove(callCompletionHandler));
    183             });
    184         } else
    185             callCompletionHandler();
     167        completionHandler(!isPlaying);
    186168    });
    187169}
     
    232214
    233215    if (isPlaying())
    234         start(std::exchange(m_dispatchToRenderThread, nullptr), [](bool) { });
     216        startRendering([](bool) { });
    235217}
    236218
  • trunk/Source/WebKit/WebProcess/GPU/media/RemoteAudioDestinationProxy.h

    r270938 r270947  
    4040#include <WebCore/AudioDestinationCocoa.h>
    4141#else
    42 #include <WebCore/AudioDestination.h>
     42#include <WebCore/AudioDestinationGStreamer.h>
    4343#endif
    4444
     
    5858class SharedRingBufferFrameBounds;
    5959
    60 class RemoteAudioDestinationProxy
     60class RemoteAudioDestinationProxy final
    6161#if PLATFORM(COCOA)
    6262    : public WebCore::AudioDestinationCocoa
    6363#else
    64     : public WebCore::AudioDestination
     64    : public WebCore::AudioDestinationGStreamer
    6565#endif
    6666    , public GPUProcessConnection::Client {
     
    7777
    7878private:
    79     void start(Function<void(Function<void()>&&)>&& dispatchToRenderThread, CompletionHandler<void(bool)>&&) final;
    80     void stop(CompletionHandler<void(bool)>&&) final;
     79    void startRendering(CompletionHandler<void(bool)>&&) final;
     80    void stopRendering(CompletionHandler<void(bool)>&&) final;
    8181
    8282    void startRenderingThread();
     
    9393    void setIsPlaying(bool) { }
    9494    float sampleRate() const final { return 0; }
    95     unsigned framesPerBuffer() const final { return 0; }
    9695    unsigned numberOfOutputChannels() const { return m_numberOfOutputChannels; }
    9796#endif
     
    117116    unsigned m_numberOfInputChannels;
    118117
    119     Function<void(Function<void()>&&)> m_dispatchToRenderThread;
    120118    RefPtr<Thread> m_renderThread;
    121119    std::atomic<bool> m_shouldStopThread { false };
Note: See TracChangeset for help on using the changeset viewer.