From cc7f43c817bd13b646be5ca51ed03c8c5ea640bc Mon Sep 17 00:00:00 2001 From: Karl Tomlinson Date: Tue, 1 Apr 2014 10:25:45 +1300 Subject: [PATCH] b=987976 make AudioNodeExternalInputStream output channel count match stream, unless > MaxChannelCount r=padenot The difference from Blink here is that Blink plays silence for if element channel counts are > 32, but here more channels are down-mixed. Media stream channel counts are also fixed to 2 in Blink, but that restriction is not applied here. Leaving the "inline" const static/class member initialization of MaxChannelCount left missing symbols with gcc 4.7.3. --HG-- extra : transplant_source : %C9%BA%84%0F%E8%89%E2%85p%B8%28%EF%E9M%CC%81%B9ob/ --- content/media/AudioNodeExternalInputStream.cpp | 9 ++++----- content/media/webaudio/WebAudioUtils.cpp | 4 ++++ content/media/webaudio/WebAudioUtils.h | 4 +--- .../webaudio/test/test_mediaStreamAudioSourceNode.html | 5 ++++- 4 files changed, 13 insertions(+), 9 deletions(-) diff --git a/content/media/AudioNodeExternalInputStream.cpp b/content/media/AudioNodeExternalInputStream.cpp index 50c8cba32ae5..c2ff882a4048 100644 --- a/content/media/AudioNodeExternalInputStream.cpp +++ b/content/media/AudioNodeExternalInputStream.cpp @@ -58,7 +58,8 @@ AudioNodeExternalInputStream::GetTrackMapEntry(const StreamBuffer::Track& aTrack // Create a speex resampler with the same sample rate and number of channels // as the track. SpeexResamplerState* resampler = nullptr; - uint32_t channelCount = (*ci).mChannelData.Length(); + uint32_t channelCount = std::min((*ci).mChannelData.Length(), + WebAudioUtils::MaxChannelCount); if (aTrack.GetRate() != mSampleRate) { resampler = speex_resampler_init(channelCount, aTrack.GetRate(), mSampleRate, SPEEX_RESAMPLER_QUALITY_DEFAULT, nullptr); @@ -436,10 +437,8 @@ AudioNodeExternalInputStream::ProcessInput(GraphTime aFrom, GraphTime aTo, } } - uint32_t outputChannels = ComputeFinalOuputChannelCount(inputChannels); - - if (outputChannels) { - AllocateAudioBlock(outputChannels, &mLastChunks[0]); + if (inputChannels) { + AllocateAudioBlock(inputChannels, &mLastChunks[0]); nsAutoTArray downmixBuffer; for (uint32_t i = 0; i < audioSegments.Length(); ++i) { AudioChunk tmpChunk; diff --git a/content/media/webaudio/WebAudioUtils.cpp b/content/media/webaudio/WebAudioUtils.cpp index 87088c4dd340..ddfb6d80690b 100644 --- a/content/media/webaudio/WebAudioUtils.cpp +++ b/content/media/webaudio/WebAudioUtils.cpp @@ -14,6 +14,10 @@ namespace mozilla { namespace dom { +// 32 is the minimum required by the spec and matches what is used by blink. +// The limit protects against large memory allocations. +const uint32_t WebAudioUtils::MaxChannelCount = 32; + struct ConvertTimeToTickHelper { AudioNodeStream* mSourceStream; diff --git a/content/media/webaudio/WebAudioUtils.h b/content/media/webaudio/WebAudioUtils.h index 2d926e0615ca..8ba876176ed9 100644 --- a/content/media/webaudio/WebAudioUtils.h +++ b/content/media/webaudio/WebAudioUtils.h @@ -26,9 +26,7 @@ namespace dom { class AudioParamTimeline; struct WebAudioUtils { - // This is an arbitrary large number used to protect against OOMs. - // We can adjust it later if needed. - static const uint32_t MaxChannelCount = 32; + static const uint32_t MaxChannelCount; static bool FuzzyEqual(float v1, float v2) { diff --git a/content/media/webaudio/test/test_mediaStreamAudioSourceNode.html b/content/media/webaudio/test/test_mediaStreamAudioSourceNode.html index 2d0e806614e7..379675691a9e 100644 --- a/content/media/webaudio/test/test_mediaStreamAudioSourceNode.html +++ b/content/media/webaudio/test/test_mediaStreamAudioSourceNode.html @@ -15,7 +15,7 @@ function createBuffer(context, delay) { var buffer = context.createBuffer(2, 2048, context.sampleRate); for (var i = 0; i < 2048 - delay; ++i) { buffer.getChannelData(0)[i + delay] = Math.sin(440 * 2 * Math.PI * i / context.sampleRate); - buffer.getChannelData(1)[i + delay] = buffer.getChannelData(0)[i + delay]; + buffer.getChannelData(1)[i + delay] = -buffer.getChannelData(0)[i + delay]; } return buffer; } @@ -32,6 +32,9 @@ var gTest = { source.start(0); var mediaStreamSource = context.createMediaStreamSource(dest.stream); + // channelCount and channelCountMode should have no effect + mediaStreamSource.channelCount = 1; + mediaStreamSource.channelCountMode = "explicit"; return mediaStreamSource; }, createExpectedBuffers: function(context) {