Skip to content
This repository was archived by the owner on Jun 24, 2022. It is now read-only.

Commit a28e4d7

Browse files
[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. git-svn-id: http://svn.webkit.org/repository/webkit/trunk@268758 268f45cc-cd09-0410-ab3c-d52691b4dbfc
1 parent bad103e commit a28e4d7

File tree

5 files changed

+54
-13
lines changed

5 files changed

+54
-13
lines changed

Source/WebKit/ChangeLog

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,33 @@
1+
2020-10-20 Peng Liu <[email protected]>
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+
131
2020-10-20 Chris Dumez <[email protected]>
232

333
Drop legacy code using AssertionServices

Source/WebKit/GPUProcess/media/RemoteAudioDestinationManager.cpp

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,6 @@ class RemoteAudioDestination
8282
auto memory = SharedMemory::map(ipcHandle.handle, SharedMemory::Protection::ReadOnly);
8383
storage().setStorage(WTFMove(memory));
8484
storage().setReadOnly(true);
85-
8685
m_ringBuffer->allocate(description, numberOfFrames);
8786
}
8887
#endif
@@ -138,16 +137,27 @@ class RemoteAudioDestination
138137
{
139138
ASSERT(!isMainThread());
140139

141-
if (m_protectThisDuringGracefulShutdown)
142-
return noErr;
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+
}
143153

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 {
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
153163

@@ -161,6 +171,7 @@ class RemoteAudioDestination
161171

162172
WebCore::CAAudioStreamDescription m_description;
163173
UniqueRef<WebCore::CARingBuffer> m_ringBuffer;
174+
uint64_t m_startFrame { 0 };
164175
#endif
165176

166177
bool m_isPlaying { false };

Source/WebKit/WebProcess/GPU/media/RemoteAudioDestinationProxy.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -123,12 +123,12 @@ void RemoteAudioDestinationProxy::stop()
123123
}
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)
126+
void 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);
134134
m_audioBufferList->setSampleCount(numberOfFrames);
@@ -150,7 +150,7 @@ void RemoteAudioDestinationProxy::renderOnRenderingThead(size_t framesToRender)
150150
uint64_t boundsStartFrame;
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
156156

Source/WebKit/WebProcess/GPU/media/RemoteAudioDestinationProxy.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ class RemoteAudioDestinationProxy
7171
void didReceiveMessageFromGPUProcess(IPC::Connection& connection, IPC::Decoder& decoder) { didReceiveMessage(connection, decoder); }
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

7777
private:
@@ -105,7 +105,7 @@ class RemoteAudioDestinationProxy
105105
std::unique_ptr<WebCore::CARingBuffer> m_ringBuffer;
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

111111
Function<void(Function<void()>&&)> m_dispatchToRenderThread;

Source/WebKit/WebProcess/GPU/media/RemoteAudioDestinationProxy.messages.in

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525

2626
messages -> 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
}
3131

0 commit comments

Comments
 (0)