Changeset 270947 in webkit
- Timestamp:
- Dec 17, 2020, 2:23:39 PM (6 years ago)
- Location:
- trunk/Source
- Files:
-
- 12 edited
-
WebCore/ChangeLog (modified) (1 diff)
-
WebCore/Headers.cmake (modified) (1 diff)
-
WebCore/Modules/webaudio/DefaultAudioDestinationNode.cpp (modified) (1 diff)
-
WebCore/platform/audio/cocoa/AudioDestinationCocoa.cpp (modified) (4 diffs)
-
WebCore/platform/audio/cocoa/AudioDestinationCocoa.h (modified) (2 diffs)
-
WebCore/platform/audio/gstreamer/AudioDestinationGStreamer.cpp (modified) (2 diffs)
-
WebCore/platform/audio/gstreamer/AudioDestinationGStreamer.h (modified) (2 diffs)
-
WebCore/platform/mock/MockAudioDestinationCocoa.cpp (modified) (3 diffs)
-
WebCore/platform/mock/MockAudioDestinationCocoa.h (modified) (2 diffs)
-
WebKit/ChangeLog (modified) (1 diff)
-
WebKit/WebProcess/GPU/media/RemoteAudioDestinationProxy.cpp (modified) (5 diffs)
-
WebKit/WebProcess/GPU/media/RemoteAudioDestinationProxy.h (modified) (5 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r270943 r270947 1 2020-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 1 33 2020-12-17 Jer Noble <jer.noble@apple.com> 2 34 -
trunk/Source/WebCore/Headers.cmake
r270587 r270947 1117 1117 platform/audio/PlatformMediaSessionManager.h 1118 1118 platform/audio/PushPullFIFO.h 1119 1120 platform/audio/gstreamer/AudioDestinationGStreamer.h 1119 1121 1120 1122 platform/encryptedmedia/CDMEncryptionScheme.h -
trunk/Source/WebCore/Modules/webaudio/DefaultAudioDestinationNode.cpp
r270840 r270947 134 134 }; 135 135 } 136 return {};136 return [](Function<void()>&& function) { function(); }; 137 137 } 138 138 -
trunk/Source/WebCore/platform/audio/cocoa/AudioDestinationCocoa.cpp
r270840 r270947 105 105 void AudioDestinationCocoa::start(Function<void(Function<void()>&&)>&& dispatchToRenderThread, CompletionHandler<void(bool)>&& completionHandler) 106 106 { 107 ASSERT(isMainThread()); 107 108 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 116 void AudioDestinationCocoa::startRendering(CompletionHandler<void(bool)>&& completionHandler) 117 { 118 ASSERT(isMainThread()); 109 119 auto success = m_audioOutputUnitAdaptor.start() == noErr; 110 120 if (success) … … 118 128 void AudioDestinationCocoa::stop(CompletionHandler<void(bool)>&& completionHandler) 119 129 { 130 ASSERT(isMainThread()); 120 131 LOG(Media, "AudioDestinationCocoa::stop"); 132 stopRendering(WTFMove(completionHandler)); 133 { 134 auto locker = holdLock(m_dispatchToRenderThreadLock); 135 m_dispatchToRenderThread = nullptr; 136 } 137 } 138 139 void AudioDestinationCocoa::stopRendering(CompletionHandler<void(bool)>&& completionHandler) 140 { 141 ASSERT(isMainThread()); 121 142 auto success = m_audioOutputUnitAdaptor.stop() == noErr; 122 auto dispatchToRenderThread = std::exchange(m_dispatchToRenderThread, nullptr);123 143 if (success) 124 144 setIsPlaying(false); 125 145 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 }); 138 149 } 139 150 … … 188 199 OSStatus AudioDestinationCocoa::render(double sampleTime, uint64_t hostTime, UInt32 numberOfFrames, AudioBufferList* ioData) 189 200 { 201 ASSERT(!isMainThread()); 202 190 203 if (!hasEnoughFrames(numberOfFrames)) 191 204 return noErr; … … 209 222 210 223 // 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 }); 219 233 220 234 return noErr; -
trunk/Source/WebCore/platform/audio/cocoa/AudioDestinationCocoa.h
r270840 r270947 66 66 friend Ref<AudioDestination> AudioDestination::create(AudioIOCallback&, const String&, unsigned, unsigned, float); 67 67 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)>&&); 70 73 71 74 void renderOnRenderingThead(size_t framesToRender); … … 87 90 AudioIOPosition m_outputTimestamp; 88 91 92 Lock m_dispatchToRenderThreadLock; 89 93 Function<void(Function<void()>&&)> m_dispatchToRenderThread; 90 94 -
trunk/Source/WebCore/platform/audio/gstreamer/AudioDestinationGStreamer.cpp
r270840 r270947 220 220 void AudioDestinationGStreamer::start(Function<void(Function<void()>&&)>&& dispatchToRenderThread, CompletionHandler<void(bool)>&& completionHandler) 221 221 { 222 webkitWebAudioSourceSetDispatchToRenderThreadCallback(WEBKIT_WEB_AUDIO_SRC(m_src.get()), WTFMove(dispatchToRenderThread)); 223 startRendering(WTFMove(completionHandler)); 224 } 225 226 void AudioDestinationGStreamer::startRendering(CompletionHandler<void(bool)>&& completionHandler) 227 { 222 228 ASSERT(m_audioSinkAvailable); 223 229 bool success = false; 224 230 if (m_audioSinkAvailable) { 225 if (dispatchToRenderThread)226 webkitWebAudioSourceSetDispatchToRenderThreadCallback(WEBKIT_WEB_AUDIO_SRC(m_src.get()), WTFMove(dispatchToRenderThread));227 228 231 GST_DEBUG("Starting"); 229 232 if (gst_element_set_state(m_pipeline.get(), GST_STATE_PLAYING) == GST_STATE_CHANGE_FAILURE) { … … 243 246 void AudioDestinationGStreamer::stop(CompletionHandler<void(bool)>&& completionHandler) 244 247 { 248 stopRendering(WTFMove(completionHandler)); 249 } 250 251 void AudioDestinationGStreamer::stopRendering(CompletionHandler<void(bool)>&& completionHandler) 252 { 245 253 ASSERT(m_audioSinkAvailable); 246 254 bool success = false; -
trunk/Source/WebCore/platform/audio/gstreamer/AudioDestinationGStreamer.h
r270840 r270947 35 35 virtual ~AudioDestinationGStreamer(); 36 36 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; 39 39 40 40 bool isPlaying() override { return m_isPlaying; } … … 43 43 44 44 gboolean handleMessage(GstMessage*); 45 46 protected: 47 virtual void startRendering(CompletionHandler<void(bool)>&&); 48 virtual void stopRendering(CompletionHandler<void(bool)>&&); 45 49 46 50 private: -
trunk/Source/WebCore/platform/mock/MockAudioDestinationCocoa.cpp
r269630 r270947 46 46 MockAudioDestinationCocoa::~MockAudioDestinationCocoa() = default; 47 47 48 void MockAudioDestinationCocoa::start (Function<void(Function<void()>&&)>&& dispatchToRenderThread,CompletionHandler<void(bool)>&& completionHandler)48 void MockAudioDestinationCocoa::startRendering(CompletionHandler<void(bool)>&& completionHandler) 49 49 { 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 57 50 m_timer.startRepeating(Seconds { m_numberOfFramesToProcess / sampleRate() }); 58 51 setIsPlaying(true); … … 63 56 } 64 57 65 void MockAudioDestinationCocoa::stop (CompletionHandler<void(bool)>&& completionHandler)58 void MockAudioDestinationCocoa::stopRendering(CompletionHandler<void(bool)>&& completionHandler) 66 59 { 67 60 m_timer.stop(); 68 61 setIsPlaying(false); 69 62 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); 74 65 }); 75 66 } … … 77 68 void MockAudioDestinationCocoa::tick() 78 69 { 79 m_ dispatchToRenderThread([this, sampleRate = sampleRate(), numberOfFramesToProcess = m_numberOfFramesToProcess] {70 m_workQueue->dispatch([this, protectedThis = makeRef(*this), sampleRate = sampleRate(), numberOfFramesToProcess = m_numberOfFramesToProcess] { 80 71 AudioStreamBasicDescription streamFormat; 81 72 getAudioStreamBasicDescription(streamFormat); -
trunk/Source/WebCore/platform/mock/MockAudioDestinationCocoa.h
r270808 r270947 48 48 49 49 private: 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; 52 52 53 53 void tick(); … … 55 55 Ref<WorkQueue> m_workQueue; 56 56 RunLoop::Timer<MockAudioDestinationCocoa> m_timer; 57 Function<void(Function<void()>&&)> m_dispatchToRenderThread;58 57 uint32_t m_numberOfFramesToProcess { 384 }; 59 58 }; -
trunk/Source/WebKit/ChangeLog
r270946 r270947 1 2020-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 1 23 2020-12-17 Alex Christensen <achristensen@webkit.org> 2 24 -
trunk/Source/WebKit/WebProcess/GPU/media/RemoteAudioDestinationProxy.cpp
r270938 r270947 64 64 , m_sampleRate(hardwareSampleRate()) 65 65 #else 66 : WebCore::AudioDestination (callback)66 : WebCore::AudioDestinationGStreamer(callback, numberOfOutputChannels, sampleRate) 67 67 , m_numberOfOutputChannels(numberOfOutputChannels) 68 68 #endif … … 84 84 break; 85 85 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(); 93 87 } while (!m_shouldStopThread); 94 88 }; … … 159 153 } 160 154 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); 155 void 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 { 165 158 setIsPlaying(isPlaying); 166 159 completionHandler(isPlaying); … … 168 161 } 169 162 170 void RemoteAudioDestinationProxy::stop (CompletionHandler<void(bool)>&& completionHandler)163 void RemoteAudioDestinationProxy::stopRendering(CompletionHandler<void(bool)>&& completionHandler) 171 164 { 172 165 WebProcess::singleton().ensureGPUProcessConnection().connection().sendWithAsyncReply(Messages::RemoteAudioDestinationManager::StopAudioDestination(m_destinationID), [this, protectedThis = makeRef(*this), completionHandler = WTFMove(completionHandler)](bool isPlaying) mutable { 173 166 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); 186 168 }); 187 169 } … … 232 214 233 215 if (isPlaying()) 234 start (std::exchange(m_dispatchToRenderThread, nullptr),[](bool) { });216 startRendering([](bool) { }); 235 217 } 236 218 -
trunk/Source/WebKit/WebProcess/GPU/media/RemoteAudioDestinationProxy.h
r270938 r270947 40 40 #include <WebCore/AudioDestinationCocoa.h> 41 41 #else 42 #include <WebCore/AudioDestination .h>42 #include <WebCore/AudioDestinationGStreamer.h> 43 43 #endif 44 44 … … 58 58 class SharedRingBufferFrameBounds; 59 59 60 class RemoteAudioDestinationProxy 60 class RemoteAudioDestinationProxy final 61 61 #if PLATFORM(COCOA) 62 62 : public WebCore::AudioDestinationCocoa 63 63 #else 64 : public WebCore::AudioDestination 64 : public WebCore::AudioDestinationGStreamer 65 65 #endif 66 66 , public GPUProcessConnection::Client { … … 77 77 78 78 private: 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; 81 81 82 82 void startRenderingThread(); … … 93 93 void setIsPlaying(bool) { } 94 94 float sampleRate() const final { return 0; } 95 unsigned framesPerBuffer() const final { return 0; }96 95 unsigned numberOfOutputChannels() const { return m_numberOfOutputChannels; } 97 96 #endif … … 117 116 unsigned m_numberOfInputChannels; 118 117 119 Function<void(Function<void()>&&)> m_dispatchToRenderThread;120 118 RefPtr<Thread> m_renderThread; 121 119 std::atomic<bool> m_shouldStopThread { false };
Note:
See TracChangeset
for help on using the changeset viewer.