From fc048ad57c3f2eb6c64cf15b3a0af2a9b284a54f Mon Sep 17 00:00:00 2001 From: Hongchan Choi Date: Wed, 30 Aug 2017 23:28:53 +0000 Subject: [PATCH] Synchronize AudioWorkletProcessor information upon script evaluation Spec: https://webaudio.github.io/web-audio-api/#dfn-node-name-to-parameter-descriptor-map Upon the evaluation of script in AudioWorkletGlobalScope, the associated AudioWokrletMessagingProxy (which is associated with a BaseAudioContext) needs to be updated with the data from the script. Bug: 755566 Change-Id: I9013adf67710b9d8cf932efc94be27116727dd95 Reviewed-on: https://chromium-review.googlesource.com/622067 Reviewed-by: Raymond Toy Reviewed-by: Hiroki Nakagawa Commit-Queue: Hongchan Choi Cr-Commit-Position: refs/heads/master@{#498664} --- .../webaudio/AudioWorkletGlobalScope.cpp | 18 +++++ .../webaudio/AudioWorkletGlobalScope.h | 7 ++ .../webaudio/AudioWorkletMessagingProxy.cpp | 29 ++++++-- .../webaudio/AudioWorkletMessagingProxy.h | 22 +++++- .../webaudio/AudioWorkletObjectProxy.cpp | 27 +++++--- .../AudioWorkletProcessorDefinition.h | 6 ++ .../WebKit/Source/modules/webaudio/BUILD.gn | 1 + .../CrossThreadAudioWorkletProcessorInfo.h | 68 +++++++++++++++++++ 8 files changed, 159 insertions(+), 19 deletions(-) create mode 100644 third_party/WebKit/Source/modules/webaudio/CrossThreadAudioWorkletProcessorInfo.h diff --git a/third_party/WebKit/Source/modules/webaudio/AudioWorkletGlobalScope.cpp b/third_party/WebKit/Source/modules/webaudio/AudioWorkletGlobalScope.cpp index 358d129ff7f164..ecbdd708b3060b 100644 --- a/third_party/WebKit/Source/modules/webaudio/AudioWorkletGlobalScope.cpp +++ b/third_party/WebKit/Source/modules/webaudio/AudioWorkletGlobalScope.cpp @@ -11,6 +11,7 @@ #include "bindings/core/v8/WorkerOrWorkletScriptController.h" #include "bindings/modules/v8/V8AudioParamDescriptor.h" #include "core/dom/ExceptionCode.h" +#include "modules/webaudio/CrossThreadAudioWorkletProcessorInfo.h" #include "modules/webaudio/AudioBuffer.h" #include "modules/webaudio/AudioParamDescriptor.h" #include "modules/webaudio/AudioWorkletProcessor.h" @@ -208,6 +209,23 @@ AudioWorkletProcessorDefinition* AudioWorkletGlobalScope::FindDefinition( return processor_definition_map_.at(name); } +unsigned AudioWorkletGlobalScope::NumberOfRegisteredDefinitions() { + return processor_definition_map_.size(); +} + +std::unique_ptr> +AudioWorkletGlobalScope::WorkletProcessorInfoListForSynchronization() { + auto processor_info_list = + WTF::MakeUnique>(); + for (auto definition_entry : processor_definition_map_) { + if (!definition_entry.value->IsSynchronized()) { + definition_entry.value->MarkAsSynchronized(); + processor_info_list->emplace_back(*definition_entry.value); + } + } + return processor_info_list; +} + DEFINE_TRACE(AudioWorkletGlobalScope) { visitor->Trace(processor_definition_map_); visitor->Trace(processor_instances_); diff --git a/third_party/WebKit/Source/modules/webaudio/AudioWorkletGlobalScope.h b/third_party/WebKit/Source/modules/webaudio/AudioWorkletGlobalScope.h index 9023befb22d129..b32f2d4531c1e7 100644 --- a/third_party/WebKit/Source/modules/webaudio/AudioWorkletGlobalScope.h +++ b/third_party/WebKit/Source/modules/webaudio/AudioWorkletGlobalScope.h @@ -9,6 +9,7 @@ #include "core/dom/ExecutionContext.h" #include "core/workers/ThreadedWorkletGlobalScope.h" #include "modules/ModulesExport.h" +#include "modules/webaudio/AudioParamDescriptor.h" #include "platform/bindings/ScriptWrappable.h" namespace blink { @@ -16,6 +17,7 @@ namespace blink { class AudioBuffer; class AudioWorkletProcessor; class AudioWorkletProcessorDefinition; +class CrossThreadAudioWorkletProcessorInfo; class ExceptionState; // This is constructed and destroyed on a worker thread, and all methods also @@ -50,6 +52,11 @@ class MODULES_EXPORT AudioWorkletGlobalScope final AudioWorkletProcessorDefinition* FindDefinition(const String& name); + unsigned NumberOfRegisteredDefinitions(); + + std::unique_ptr> + WorkletProcessorInfoListForSynchronization(); + DECLARE_TRACE(); DECLARE_TRACE_WRAPPERS(); diff --git a/third_party/WebKit/Source/modules/webaudio/AudioWorkletMessagingProxy.cpp b/third_party/WebKit/Source/modules/webaudio/AudioWorkletMessagingProxy.cpp index f9d23c1b8e5870..64893c1664ff91 100644 --- a/third_party/WebKit/Source/modules/webaudio/AudioWorkletMessagingProxy.cpp +++ b/third_party/WebKit/Source/modules/webaudio/AudioWorkletMessagingProxy.cpp @@ -4,6 +4,7 @@ #include "modules/webaudio/AudioWorkletMessagingProxy.h" +#include "modules/webaudio/CrossThreadAudioWorkletProcessorInfo.h" #include "modules/webaudio/AudioWorkletObjectProxy.h" #include "modules/webaudio/AudioWorkletThread.h" @@ -16,18 +17,32 @@ AudioWorkletMessagingProxy::AudioWorkletMessagingProxy( AudioWorkletMessagingProxy::~AudioWorkletMessagingProxy() {} -void AudioWorkletMessagingProxy::SynchronizeWorkletData() { +void AudioWorkletMessagingProxy::SynchronizeWorkletProcessorInfoList( + std::unique_ptr> info_list) { DCHECK(IsMainThread()); - // TODO(crbug.com/755566): the argument will be a set of a node name and - // parameter descriptors. Use the information to update the copy in - // AudioWorkletMessagingProxy. + for (auto& processor_info : *info_list) { + processor_info_map_.insert(processor_info.Name(), + processor_info.ParamInfoList()); + } +} + +bool AudioWorkletMessagingProxy::IsProcessorRegistered( + const String& name) const { + return processor_info_map_.Contains(name); +} + +const Vector +AudioWorkletMessagingProxy::GetParamInfoListForProcessor( + const String& name) const { + DCHECK(IsProcessorRegistered(name)); + return processor_info_map_.at(name); } std::unique_ptr - AudioWorkletMessagingProxy::CreateObjectProxy( - ThreadedWorkletMessagingProxy* messaging_proxy, - ParentFrameTaskRunners* parent_frame_task_runners) { +AudioWorkletMessagingProxy::CreateObjectProxy( + ThreadedWorkletMessagingProxy* messaging_proxy, + ParentFrameTaskRunners* parent_frame_task_runners) { return WTF::MakeUnique( static_cast(messaging_proxy), parent_frame_task_runners); diff --git a/third_party/WebKit/Source/modules/webaudio/AudioWorkletMessagingProxy.h b/third_party/WebKit/Source/modules/webaudio/AudioWorkletMessagingProxy.h index 216f208a4ff899..b20d4d5c5fa7d3 100644 --- a/third_party/WebKit/Source/modules/webaudio/AudioWorkletMessagingProxy.h +++ b/third_party/WebKit/Source/modules/webaudio/AudioWorkletMessagingProxy.h @@ -10,6 +10,8 @@ namespace blink { +class CrossThreadAudioParamInfo; +class CrossThreadAudioWorkletProcessorInfo; class ExecutionContext; class WorkerThread; @@ -20,9 +22,20 @@ class AudioWorkletMessagingProxy final : public ThreadedWorkletMessagingProxy { public: AudioWorkletMessagingProxy(ExecutionContext*, WorkerClients*); - // Invoked by AudioWorkletObjectProxy to synchronize the information from - // AudioWorkletGlobalScope after the script code evaluation. - void SynchronizeWorkletData(); + // Invoked by AudioWorkletObjectProxy on AudioWorkletThread to fetch the + // information from AudioWorkletGlobalScope to AudioWorkletMessagingProxy + // after the script code evaluation. It copies the information about newly + // added AudioWorkletProcessor since the previous synchronization. (e.g. + // processor name and AudioParam list) + void SynchronizeWorkletProcessorInfoList( + std::unique_ptr>); + + // Returns true if the processor with given name is registered in + // AudioWorkletGlobalScope. + bool IsProcessorRegistered(const String& name) const; + + const Vector GetParamInfoListForProcessor( + const String& name) const; private: ~AudioWorkletMessagingProxy() override; @@ -33,6 +46,9 @@ class AudioWorkletMessagingProxy final : public ThreadedWorkletMessagingProxy { ParentFrameTaskRunners*) override; std::unique_ptr CreateWorkerThread() override; + + // Each entry consists of processor name and associated AudioParam list. + HashMap> processor_info_map_; }; } // namespace blink diff --git a/third_party/WebKit/Source/modules/webaudio/AudioWorkletObjectProxy.cpp b/third_party/WebKit/Source/modules/webaudio/AudioWorkletObjectProxy.cpp index 5829a1e0241d68..479180dbcef0c3 100644 --- a/third_party/WebKit/Source/modules/webaudio/AudioWorkletObjectProxy.cpp +++ b/third_party/WebKit/Source/modules/webaudio/AudioWorkletObjectProxy.cpp @@ -6,6 +6,7 @@ #include "core/workers/ThreadedWorkletMessagingProxy.h" #include "core/workers/WorkerThread.h" +#include "modules/webaudio/CrossThreadAudioWorkletProcessorInfo.h" #include "modules/webaudio/AudioWorkletGlobalScope.h" #include "modules/webaudio/AudioWorkletMessagingProxy.h" #include "platform/CrossThreadFunctional.h" @@ -26,15 +27,23 @@ void AudioWorkletObjectProxy::DidCreateWorkerGlobalScope( void AudioWorkletObjectProxy::DidEvaluateModuleScript(bool success) { DCHECK(global_scope_); - // TODO(crbug.com/755566): Extract/build the information for synchronization - // and send it to the associated AudioWorkletMessagingProxy. Currently this - // is an empty cross-thread call for the future implementation. - GetParentFrameTaskRunners()->Get(TaskType::kUnthrottled) - ->PostTask( - BLINK_FROM_HERE, - CrossThreadBind( - &AudioWorkletMessagingProxy::SynchronizeWorkletData, - GetAudioWorkletMessagingProxyWeakPtr())); + + if (!success || global_scope_->NumberOfRegisteredDefinitions() == 0) + return; + + std::unique_ptr> + processor_info_list = + global_scope_->WorkletProcessorInfoListForSynchronization(); + + if (processor_info_list->size() == 0) + return; + + GetParentFrameTaskRunners()->Get(TaskType::kUnthrottled)->PostTask( + BLINK_FROM_HERE, + CrossThreadBind( + &AudioWorkletMessagingProxy::SynchronizeWorkletProcessorInfoList, + GetAudioWorkletMessagingProxyWeakPtr(), + WTF::Passed(std::move(processor_info_list)))); } void AudioWorkletObjectProxy::WillDestroyWorkerGlobalScope() { diff --git a/third_party/WebKit/Source/modules/webaudio/AudioWorkletProcessorDefinition.h b/third_party/WebKit/Source/modules/webaudio/AudioWorkletProcessorDefinition.h index bc08de389cc0c2..d3f20f529abfa1 100644 --- a/third_party/WebKit/Source/modules/webaudio/AudioWorkletProcessorDefinition.h +++ b/third_party/WebKit/Source/modules/webaudio/AudioWorkletProcessorDefinition.h @@ -41,6 +41,11 @@ class MODULES_EXPORT AudioWorkletProcessorDefinition final const Vector GetAudioParamDescriptorNames() const; const AudioParamDescriptor* GetAudioParamDescriptor(const String& key) const; + // Flag for data synchronization of definition between + // AudioWorkletMessagingProxy and AudioWorkletGlobalScope. + bool IsSynchronized() const { return is_synchronized_; } + void MarkAsSynchronized() { is_synchronized_ = true; } + DEFINE_INLINE_TRACE() { visitor->Trace(audio_param_descriptors_); }; DECLARE_TRACE_WRAPPERS(); @@ -52,6 +57,7 @@ class MODULES_EXPORT AudioWorkletProcessorDefinition final v8::Local process); const String name_; + bool is_synchronized_ = false; // The definition is per global scope. The active instance of // |AudioProcessorWorklet| should be passed into these to perform JS function. diff --git a/third_party/WebKit/Source/modules/webaudio/BUILD.gn b/third_party/WebKit/Source/modules/webaudio/BUILD.gn index fe0f3da4e25ef8..c487eb82a8b918 100644 --- a/third_party/WebKit/Source/modules/webaudio/BUILD.gn +++ b/third_party/WebKit/Source/modules/webaudio/BUILD.gn @@ -72,6 +72,7 @@ blink_modules_sources("webaudio") { "ConstantSourceNode.h", "ConvolverNode.cpp", "ConvolverNode.h", + "CrossThreadAudioWorkletProcessorInfo.h", "DefaultAudioDestinationNode.cpp", "DefaultAudioDestinationNode.h", "DeferredTaskHandler.cpp", diff --git a/third_party/WebKit/Source/modules/webaudio/CrossThreadAudioWorkletProcessorInfo.h b/third_party/WebKit/Source/modules/webaudio/CrossThreadAudioWorkletProcessorInfo.h new file mode 100644 index 00000000000000..c556ff128f15e2 --- /dev/null +++ b/third_party/WebKit/Source/modules/webaudio/CrossThreadAudioWorkletProcessorInfo.h @@ -0,0 +1,68 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CrossThreadAudioWorkletProcessorInfo_h +#define CrossThreadAudioWorkletProcessorInfo_h + +#include "modules/webaudio/AudioParamDescriptor.h" +#include "modules/webaudio/AudioWorkletProcessorDefinition.h" + +namespace blink { + +// A class for shallow repackage of |AudioParamDescriptor|. This is created only +// when requested when the synchronization between AudioWorkletMessagingProxy +// and AudioWorkletGlobalScope. +class CrossThreadAudioParamInfo { + DISALLOW_NEW_EXCEPT_PLACEMENT_NEW(); + + public: + explicit CrossThreadAudioParamInfo(const AudioParamDescriptor* descriptor) + : name_(descriptor->name().IsolatedCopy()), + default_value_(descriptor->defaultValue()), + max_value_(descriptor->maxValue()), + min_value_(descriptor->minValue()) {} + + const String& Name() const { return name_; } + float DefaultValue() const { return default_value_; } + float MaxValue() const { return max_value_; } + float MinValue() const { return min_value_; } + + private: + const String name_; + const float default_value_; + const float max_value_; + const float min_value_; +}; + +// A class for shallow repackage of |AudioWorkletProcessorDefinition|. This is +// created only when requested when the synchronization between +// AudioWorkletMessagingProxy and AudioWorkletGlobalScope. +class CrossThreadAudioWorkletProcessorInfo { + DISALLOW_NEW_EXCEPT_PLACEMENT_NEW(); + + public: + explicit CrossThreadAudioWorkletProcessorInfo( + const AudioWorkletProcessorDefinition& definition) + : name_(definition.GetName().IsolatedCopy()) { + // To avoid unnecessary reallocations of the vector. + param_info_list_.ReserveInitialCapacity( + definition.GetAudioParamDescriptorNames().size()); + + for (const String& name : definition.GetAudioParamDescriptorNames()) { + param_info_list_.emplace_back( + definition.GetAudioParamDescriptor(name)); + } + } + + const String& Name() const { return name_; } + Vector ParamInfoList() { return param_info_list_; } + + private: + const String name_; + Vector param_info_list_; +}; + +} // namespace blink + +#endif // CrossThreadAudioWorkletProcessorInfo_h