From d1415f98f641e0502f7e60f9b105d9ffa6781c74 Mon Sep 17 00:00:00 2001 From: Paul Adenot Date: Mon, 21 Sep 2020 17:40:45 +0000 Subject: [PATCH] Bug 1659244 - Allow processing planar audio in the AudibilityMonitor. r=pehrsons This is essentially the same code as the interleaved version, but backwards, since the memory layout is the opposite, we want to take advantage of memory locality, and only touch audio samples once each. The `ProcessAudioData` method has been renamed, because of the similarity between the `AudioData` type and `ProcessAudioData`, since it can now process `AudioBlock`s. Differential Revision: https://phabricator.services.mozilla.com/D90431 --- dom/media/AudibilityMonitor.h | 31 ++++++++++++++++++++++++++- dom/media/mediasink/AudioSink.cpp | 2 +- dom/media/mediasink/DecodedStream.cpp | 2 +- 3 files changed, 32 insertions(+), 3 deletions(-) diff --git a/dom/media/AudibilityMonitor.h b/dom/media/AudibilityMonitor.h index d869d1c7601d..e5be7bda491e 100644 --- a/dom/media/AudibilityMonitor.h +++ b/dom/media/AudibilityMonitor.h @@ -11,6 +11,7 @@ #include "AudioSampleFormat.h" #include "WebAudioUtils.h" +#include "AudioBlock.h" namespace mozilla { @@ -25,10 +26,38 @@ class AudibilityMonitor { mSilentFramesInARow(0), mEverAudible(false) {} - void ProcessAudioData(const AudioData* aData) { + void Process(const AudioData* aData) { ProcessInterleaved(aData->Data(), aData->mChannels); } + void Process(const AudioBlock& aData) { + if (aData.IsNull() || aData.IsMuted()) { + mSilentFramesInARow += aData.GetDuration(); + return; + } + ProcessPlanar(aData.ChannelData(), aData.GetDuration()); + } + + void ProcessPlanar(const nsTArray& aPlanar, + TrackTime aFrames) { + uint32_t lastFrameAudibleAccrossChannels = 0; + for (uint32_t channel = 0; channel < aPlanar.Length(); channel++) { + uint32_t lastSampleAudible = 0; + for (uint32_t frame = 0; frame < aFrames; frame++) { + float dbfs = dom::WebAudioUtils::ConvertLinearToDecibels( + abs(AudioSampleToFloat(aPlanar[channel][frame])), -100.f); + if (dbfs > AUDIBILITY_THREHSOLD) { + mEverAudible = true; + mSilentFramesInARow = 0; + lastSampleAudible = frame; + } + } + lastFrameAudibleAccrossChannels = + std::max(lastFrameAudibleAccrossChannels, lastSampleAudible); + } + mSilentFramesInARow += aFrames - lastFrameAudibleAccrossChannels - 1; + } + void ProcessInterleaved(const Span& aInterleaved, size_t aChannels) { MOZ_ASSERT(aInterleaved.Length() % aChannels == 0); diff --git a/dom/media/mediasink/AudioSink.cpp b/dom/media/mediasink/AudioSink.cpp index 7e6d8c51b4b7..0fc520b6d109 100644 --- a/dom/media/mediasink/AudioSink.cpp +++ b/dom/media/mediasink/AudioSink.cpp @@ -320,7 +320,7 @@ void AudioSink::Errored() { void AudioSink::CheckIsAudible(const AudioData* aData) { MOZ_ASSERT(aData); - mAudibilityMonitor.ProcessAudioData(aData); + mAudibilityMonitor.Process(aData); bool isAudible = mAudibilityMonitor.RecentlyAudible(); if (isAudible != mIsAudioDataAudible) { diff --git a/dom/media/mediasink/DecodedStream.cpp b/dom/media/mediasink/DecodedStream.cpp index fafa5f457179..4fd91e18374e 100644 --- a/dom/media/mediasink/DecodedStream.cpp +++ b/dom/media/mediasink/DecodedStream.cpp @@ -679,7 +679,7 @@ void DecodedStream::SendAudio(double aVolume, void DecodedStream::CheckIsDataAudible(const AudioData* aData) { MOZ_ASSERT(aData); - mAudibilityMonitor->ProcessAudioData(aData); + mAudibilityMonitor->Process(aData); bool isAudible = mAudibilityMonitor->RecentlyAudible(); if (isAudible != mIsAudioDataAudible) {