diff --git a/blink/renderer/modules/webaudio/analyser_node.cc b/blink/renderer/modules/webaudio/analyser_node.cc index 7e4099b18aee441f128c00f1baa7aa4499f394d9..4881bd090e93634b706273585cb46c2644de4abb 100644 --- a/blink/renderer/modules/webaudio/analyser_node.cc +++ b/blink/renderer/modules/webaudio/analyser_node.cc @@ -54,9 +54,14 @@ AnalyserHandler::~AnalyserHandler() { } void AnalyserHandler::Process(uint32_t frames_to_process) { - AudioBus* output_bus = Output(0).Bus(); + DCHECK(Context()->IsAudioThread()); - if (!IsInitialized()) { + // It's possible that output is not connected. Assign nullptr to indicate + // such case. + AudioBus* output_bus = Output(0).RenderingFanOutCount() > 0 + ? Output(0).Bus() : nullptr; + + if (!IsInitialized() && output_bus) { output_bus->Zero(); return; } @@ -68,6 +73,11 @@ void AnalyserHandler::Process(uint32_t frames_to_process) { // Analyser reflects the current input. analyser_.WriteInput(input_bus.get(), frames_to_process); + // Subsequent steps require `output_bus` to be valid. + if (!output_bus) { + return; + } + if (!Input(0).IsConnected()) { // No inputs, so clear the output, and propagate the silence hint. output_bus->Zero(); diff --git a/blink/renderer/modules/webaudio/audio_worklet_node.cc b/blink/renderer/modules/webaudio/audio_worklet_node.cc index 4538425395e8b7e25871c30fc6e217f545cc725b..9ae11ba5ceec761eaf8a0967964964647e88345e 100644 --- a/blink/renderer/modules/webaudio/audio_worklet_node.cc +++ b/blink/renderer/modules/webaudio/audio_worklet_node.cc @@ -105,12 +105,14 @@ void AudioWorkletHandler::Process(uint32_t frames_to_process) { // We also need to check if the global scope is valid before we request // the rendering in the AudioWorkletGlobalScope. if (processor_ && !processor_->hasErrorOccurred()) { - // If the input is not connected, inform the processor with nullptr. + // If the input or the output is not connected, inform the processor with + // nullptr. for (unsigned i = 0; i < NumberOfInputs(); ++i) { inputs_[i] = Input(i).IsConnected() ? Input(i).Bus() : nullptr; } for (unsigned i = 0; i < NumberOfOutputs(); ++i) { - outputs_[i] = WrapRefCounted(Output(i).Bus()); + outputs_[i] = Output(i).RenderingFanOutCount() > 0 + ? WrapRefCounted(Output(i).Bus()) : nullptr; } for (const auto& param_name : param_value_map_.Keys()) { diff --git a/blink/renderer/modules/webaudio/audio_worklet_processor.cc b/blink/renderer/modules/webaudio/audio_worklet_processor.cc index e366b21fbff7423e14c0d4346c6ccb254d5c6578..1f021d0f2d3cdf50a8eed4f55322d6ae927d11c1 100644 --- a/blink/renderer/modules/webaudio/audio_worklet_processor.cc +++ b/blink/renderer/modules/webaudio/audio_worklet_processor.cc @@ -356,6 +356,12 @@ void AudioWorkletProcessor::CopyArrayBuffersToPort( for (uint32_t bus_index = 0; bus_index < audio_port.size(); ++bus_index) { const scoped_refptr& audio_bus = audio_port[bus_index]; + + // nullptr indicates the output bus is not connected. Do not proceed. + if (!audio_bus) { + break; + } + for (uint32_t channel_index = 0; channel_index < audio_bus->NumberOfChannels(); ++channel_index) { auto backing_store = array_buffers[bus_index][channel_index] diff --git a/blink/renderer/modules/webaudio/deferred_task_handler.cc b/blink/renderer/modules/webaudio/deferred_task_handler.cc index 28107a546e550009999a3c168dd5b6d0db589eb7..ffa26c53a563d75c0eea89808e47402b7221c868 100644 --- a/blink/renderer/modules/webaudio/deferred_task_handler.cc +++ b/blink/renderer/modules/webaudio/deferred_task_handler.cc @@ -171,6 +171,16 @@ void DeferredTaskHandler::UpdateAutomaticPullNodes() { if (try_locker.Locked()) { CopyToVector(automatic_pull_handlers_, rendering_automatic_pull_handlers_); + + // In rare cases, it is possible for automatic pull nodes' output bus + // to become stale. Make sure update their rendering output counts. + // crbug.com/1505080. + for (auto& handler : rendering_automatic_pull_handlers_) { + for (unsigned i = 0; i < handler->NumberOfOutputs(); ++i) { + handler->Output(i).UpdateRenderingState(); + } + } + automatic_pull_handlers_need_updating_ = false; } }