Diff
Modified: trunk/LayoutTests/ChangeLog (248045 => 248046)
--- trunk/LayoutTests/ChangeLog 2019-07-31 16:28:02 UTC (rev 248045)
+++ trunk/LayoutTests/ChangeLog 2019-07-31 17:31:17 UTC (rev 248046)
@@ -1,3 +1,14 @@
+2019-07-31 Youenn Fablet <[email protected]>
+
+ Owners of MultiChannelResampler should make sure that the output bus given to it has the same number of channels
+ https://bugs.webkit.org/show_bug.cgi?id=200248
+ <rdar://problem/53411051>
+
+ Reviewed by Eric Carlson.
+
+ * fast/mediastream/getUserMedia-webaudio-expected.txt:
+ * fast/mediastream/getUserMedia-webaudio.html:
+
2019-07-31 Chris Dumez <[email protected]>
Element.outerHTML is missing attribute prefixes in some cases in HTML documents
Modified: trunk/LayoutTests/fast/mediastream/getUserMedia-webaudio-expected.txt (248045 => 248046)
--- trunk/LayoutTests/fast/mediastream/getUserMedia-webaudio-expected.txt 2019-07-31 16:28:02 UTC (rev 248045)
+++ trunk/LayoutTests/fast/mediastream/getUserMedia-webaudio-expected.txt 2019-07-31 17:31:17 UTC (rev 248046)
@@ -1,3 +1,4 @@
PASS Plugging in getUserMedia audio stream into Web Audio
+PASS Web Audio should work even if number of channels of a track increases from 1 to 2
Modified: trunk/LayoutTests/fast/mediastream/getUserMedia-webaudio.html (248045 => 248046)
--- trunk/LayoutTests/fast/mediastream/getUserMedia-webaudio.html 2019-07-31 16:28:02 UTC (rev 248045)
+++ trunk/LayoutTests/fast/mediastream/getUserMedia-webaudio.html 2019-07-31 17:31:17 UTC (rev 248046)
@@ -38,6 +38,33 @@
});
});
}, "Plugging in getUserMedia audio stream into Web Audio");
+
+function waitFor(duration)
+{
+ return new Promise(resolve => setTimeout(resolve, duration));
+}
+
+promise_test(async (test) => {
+ if (!window.internals)
+ return Promise.reject("Internals API required");
+
+ const stream = await navigator.mediaDevices.getUserMedia({ audio: {deviceId: true}});
+ internals.setMockAudioTrackChannelNumber(stream.getAudioTracks()[0], 1);
+
+ var audioContext = new webkitAudioContext();
+ var script = audioContext.createScriptProcessor(2048, 1, 1);
+ let source = audioContext.createMediaStreamSource(stream);
+ source.connect(script);
+ script.connect(audioContext.destination);
+
+ await waitFor(200);
+
+ internals.setMockAudioTrackChannelNumber(stream.getAudioTracks()[0], 2);
+ await waitFor(200);
+
+ source.disconnect(script);
+ script.disconnect(audioContext.destination);
+}, "Web Audio should work even if number of channels of a track increases from 1 to 2");
</script>
</body>
</html>
Modified: trunk/Source/WebCore/ChangeLog (248045 => 248046)
--- trunk/Source/WebCore/ChangeLog 2019-07-31 16:28:02 UTC (rev 248045)
+++ trunk/Source/WebCore/ChangeLog 2019-07-31 17:31:17 UTC (rev 248046)
@@ -1,3 +1,43 @@
+2019-07-31 Youenn Fablet <[email protected]>
+
+ Owners of MultiChannelResampler should make sure that the output bus given to it has the same number of channels
+ https://bugs.webkit.org/show_bug.cgi?id=200248
+ <rdar://problem/53411051>
+
+ Reviewed by Eric Carlson.
+
+ When a track's number of channels changes, MediaStreamAudioSourceNode is expected
+ to update its MultiChannelResampler and its output number of channels.
+ MultiChannelResampler expects to have the same number of channels as the output
+ but it is not always the case since the channel numbers are changed in different threads
+ and locks do not help there.
+
+ Instead, whenever detecting that the number of channels do not match, render silence
+ and wait for the next rendering where the number of channels should again match.
+
+ Add internals API to change the number of channels from 2 to 1 or 1 to 2
+ to allow testing that code path (iOS only as MacOS audio capture is in UIProcess).
+ Covered by updated test.
+
+ * Modules/webaudio/MediaElementAudioSourceNode.cpp:
+ (WebCore::MediaElementAudioSourceNode::process):
+ * Modules/webaudio/MediaStreamAudioSourceNode.cpp:
+ (WebCore::MediaStreamAudioSourceNode::process):
+ * platform/audio/MultiChannelResampler.cpp:
+ (WebCore::MultiChannelResampler::process):
+ * platform/mediastream/RealtimeMediaSource.h:
+ * platform/mediastream/mac/MockRealtimeAudioSourceMac.mm:
+ (WebCore::MockRealtimeAudioSourceMac::reconfigure):
+ * platform/mock/MockRealtimeAudioSource.cpp:
+ (WebCore::MockRealtimeAudioSource::setChannelCount):
+ * platform/mock/MockRealtimeAudioSource.h:
+ (isType):
+ * platform/mock/MockRealtimeVideoSource.h:
+ * testing/Internals.cpp:
+ (WebCore::Internals::setMockAudioTrackChannelNumber):
+ * testing/Internals.h:
+ * testing/Internals.idl:
+
2019-07-31 Chris Dumez <[email protected]>
Element.outerHTML is missing attribute prefixes in some cases in HTML documents
Modified: trunk/Source/WebCore/Modules/webaudio/MediaElementAudioSourceNode.cpp (248045 => 248046)
--- trunk/Source/WebCore/Modules/webaudio/MediaElementAudioSourceNode.cpp 2019-07-31 16:28:02 UTC (rev 248045)
+++ trunk/Source/WebCore/Modules/webaudio/MediaElementAudioSourceNode.cpp 2019-07-31 17:31:17 UTC (rev 248046)
@@ -137,6 +137,10 @@
outputBus->zero();
return;
}
+ if (m_sourceNumberOfChannels != outputBus->numberOfChannels()) {
+ outputBus->zero();
+ return;
+ }
if (AudioSourceProvider* provider = mediaElement().audioSourceProvider()) {
if (m_multiChannelResampler.get()) {
Modified: trunk/Source/WebCore/Modules/webaudio/MediaStreamAudioSourceNode.cpp (248045 => 248046)
--- trunk/Source/WebCore/Modules/webaudio/MediaStreamAudioSourceNode.cpp 2019-07-31 16:28:02 UTC (rev 248045)
+++ trunk/Source/WebCore/Modules/webaudio/MediaStreamAudioSourceNode.cpp 2019-07-31 17:31:17 UTC (rev 248046)
@@ -126,6 +126,10 @@
outputBus->zero();
return;
}
+ if (m_sourceNumberOfChannels != outputBus->numberOfChannels()) {
+ outputBus->zero();
+ return;
+ }
if (m_multiChannelResampler.get()) {
ASSERT(m_sourceSampleRate != sampleRate());
Modified: trunk/Source/WebCore/platform/audio/MultiChannelResampler.cpp (248045 => 248046)
--- trunk/Source/WebCore/platform/audio/MultiChannelResampler.cpp 2019-07-31 16:28:02 UTC (rev 248045)
+++ trunk/Source/WebCore/platform/audio/MultiChannelResampler.cpp 2019-07-31 17:31:17 UTC (rev 248046)
@@ -102,6 +102,8 @@
void MultiChannelResampler::process(AudioSourceProvider* provider, AudioBus* destination, size_t framesToProcess)
{
+ ASSERT(m_numberOfChannels == destination->numberOfChannels());
+
// The provider can provide us with multi-channel audio data. But each of our single-channel resamplers (kernels)
// below requires a provider which provides a single unique channel of data.
// channelProvider wraps the original multi-channel provider and dishes out one channel at a time.
Modified: trunk/Source/WebCore/platform/mediastream/RealtimeMediaSource.h (248045 => 248046)
--- trunk/Source/WebCore/platform/mediastream/RealtimeMediaSource.h 2019-07-31 16:28:02 UTC (rev 248045)
+++ trunk/Source/WebCore/platform/mediastream/RealtimeMediaSource.h 2019-07-31 17:31:17 UTC (rev 248046)
@@ -172,6 +172,7 @@
virtual bool isIsolated() const { return false; }
+ virtual bool isMockSource() const { return false; }
virtual bool isCaptureSource() const { return false; }
virtual CaptureDevice::DeviceType deviceType() const { return CaptureDevice::DeviceType::Unknown; }
Modified: trunk/Source/WebCore/platform/mediastream/mac/MockRealtimeAudioSourceMac.mm (248045 => 248046)
--- trunk/Source/WebCore/platform/mediastream/mac/MockRealtimeAudioSourceMac.mm 2019-07-31 16:28:02 UTC (rev 248045)
+++ trunk/Source/WebCore/platform/mediastream/mac/MockRealtimeAudioSourceMac.mm 2019-07-31 17:31:17 UTC (rev 248046)
@@ -128,7 +128,7 @@
const int bytesPerFloat = sizeof(Float32);
const int bitsPerByte = 8;
- const int channelCount = 2;
+ const int channelCount = m_channelCount;
const bool isFloat = true;
const bool isBigEndian = false;
const bool isNonInterleaved = true;
Modified: trunk/Source/WebCore/platform/mock/MockRealtimeAudioSource.cpp (248045 => 248046)
--- trunk/Source/WebCore/platform/mock/MockRealtimeAudioSource.cpp 2019-07-31 16:28:02 UTC (rev 248045)
+++ trunk/Source/WebCore/platform/mock/MockRealtimeAudioSource.cpp 2019-07-31 17:31:17 UTC (rev 248046)
@@ -98,6 +98,15 @@
return m_currentSettings.value();
}
+void MockRealtimeAudioSource::setChannelCount(unsigned channelCount)
+{
+ if (channelCount > 2)
+ return;
+
+ m_channelCount = channelCount;
+ settingsDidChange(RealtimeMediaSourceSettings::Flag::SampleRate);
+}
+
const RealtimeMediaSourceCapabilities& MockRealtimeAudioSource::capabilities()
{
if (!m_capabilities) {
Modified: trunk/Source/WebCore/platform/mock/MockRealtimeAudioSource.h (248045 => 248046)
--- trunk/Source/WebCore/platform/mock/MockRealtimeAudioSource.h 2019-07-31 16:28:02 UTC (rev 248045)
+++ trunk/Source/WebCore/platform/mock/MockRealtimeAudioSource.h 2019-07-31 17:31:17 UTC (rev 248046)
@@ -45,6 +45,8 @@
static CaptureSourceOrError create(String&& deviceID, String&& name, String&& hashSalt, const MediaConstraints*);
virtual ~MockRealtimeAudioSource();
+ WEBCORE_EXPORT void setChannelCount(unsigned);
+
protected:
MockRealtimeAudioSource(String&& deviceID, String&& name, String&& hashSalt);
@@ -64,11 +66,13 @@
CaptureDevice::DeviceType deviceType() const final { return CaptureDevice::DeviceType::Microphone; }
void delaySamples(Seconds) final;
+ bool isMockSource() const final { return true; }
void tick();
protected:
Ref<WorkQueue> m_workQueue;
+ unsigned m_channelCount { 2 };
private:
Optional<RealtimeMediaSourceCapabilities> m_capabilities;
@@ -85,4 +89,9 @@
} // namespace WebCore
+SPECIALIZE_TYPE_TRAITS_BEGIN(WebCore::MockRealtimeAudioSource)
+ static bool isType(const WebCore::RealtimeMediaSource& source) { return source.isCaptureSource() && source.isMockSource() && source.deviceType() == WebCore::CaptureDevice::DeviceType::Microphone; }
+SPECIALIZE_TYPE_TRAITS_END()
+
+
#endif // ENABLE(MEDIA_STREAM)
Modified: trunk/Source/WebCore/platform/mock/MockRealtimeVideoSource.h (248045 => 248046)
--- trunk/Source/WebCore/platform/mock/MockRealtimeVideoSource.h 2019-07-31 16:28:02 UTC (rev 248045)
+++ trunk/Source/WebCore/platform/mock/MockRealtimeVideoSource.h 2019-07-31 17:31:17 UTC (rev 248046)
@@ -78,6 +78,8 @@
void generatePresets() final;
+ bool isMockSource() const final { return true; }
+
// OrientationNotifier::Observer
void orientationChanged(int orientation) final;
void monitorOrientation(OrientationNotifier&) final;
Modified: trunk/Source/WebCore/testing/Internals.cpp (248045 => 248046)
--- trunk/Source/WebCore/testing/Internals.cpp 2019-07-31 16:28:02 UTC (rev 248045)
+++ trunk/Source/WebCore/testing/Internals.cpp 2019-07-31 17:31:17 UTC (rev 248046)
@@ -4705,6 +4705,13 @@
#endif
#if ENABLE(MEDIA_STREAM)
+void Internals::setMockAudioTrackChannelNumber(MediaStreamTrack& track, unsigned short channelNumber)
+{
+ auto& source = track.source();
+ if (!is<MockRealtimeAudioSource>(source))
+ return;
+ downcast<MockRealtimeAudioSource>(source).setChannelCount(channelNumber);
+}
void Internals::setCameraMediaStreamTrackOrientation(MediaStreamTrack& track, int orientation)
{
Modified: trunk/Source/WebCore/testing/Internals.h (248045 => 248046)
--- trunk/Source/WebCore/testing/Internals.h 2019-07-31 16:28:02 UTC (rev 248045)
+++ trunk/Source/WebCore/testing/Internals.h 2019-07-31 17:31:17 UTC (rev 248046)
@@ -709,6 +709,7 @@
#endif
#if ENABLE(MEDIA_STREAM)
+ void setMockAudioTrackChannelNumber(MediaStreamTrack&, unsigned short);
void setCameraMediaStreamTrackOrientation(MediaStreamTrack&, int orientation);
unsigned long trackAudioSampleCount() const { return m_trackAudioSampleCount; }
unsigned long trackVideoSampleCount() const { return m_trackVideoSampleCount; }
Modified: trunk/Source/WebCore/testing/Internals.idl (248045 => 248046)
--- trunk/Source/WebCore/testing/Internals.idl 2019-07-31 16:28:02 UTC (rev 248045)
+++ trunk/Source/WebCore/testing/Internals.idl 2019-07-31 17:31:17 UTC (rev 248046)
@@ -694,6 +694,7 @@
[Conditional=WEB_RTC] void setH264HardwareEncoderAllowed(boolean allowed);
[Conditional=WEB_RTC] void applyRotationForOutgoingVideoSources(RTCPeerConnection connection);
+ [Conditional=MEDIA_STREAM] void setMockAudioTrackChannelNumber(MediaStreamTrack track, unsigned short count);
[Conditional=MEDIA_STREAM] void setShouldInterruptAudioOnPageVisibilityChange(boolean shouldInterrupt);
[Conditional=MEDIA_STREAM] void setCameraMediaStreamTrackOrientation(MediaStreamTrack track, short orientation);
[Conditional=MEDIA_STREAM] void observeMediaStreamTrack(MediaStreamTrack track);