summaryrefslogtreecommitdiff
path: root/chromium/third_party/blink/renderer/modules/webaudio/media_stream_audio_destination_node.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/third_party/blink/renderer/modules/webaudio/media_stream_audio_destination_node.cc')
-rw-r--r--chromium/third_party/blink/renderer/modules/webaudio/media_stream_audio_destination_node.cc191
1 files changed, 191 insertions, 0 deletions
diff --git a/chromium/third_party/blink/renderer/modules/webaudio/media_stream_audio_destination_node.cc b/chromium/third_party/blink/renderer/modules/webaudio/media_stream_audio_destination_node.cc
new file mode 100644
index 00000000000..ef84d6b2a0f
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/webaudio/media_stream_audio_destination_node.cc
@@ -0,0 +1,191 @@
+/*
+ * Copyright (C) 2012, Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ */
+
+#include "third_party/blink/public/platform/web_rtc_peer_connection_handler.h"
+#include "third_party/blink/renderer/bindings/core/v8/exception_messages.h"
+#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
+#include "third_party/blink/renderer/core/dom/exception_code.h"
+#include "third_party/blink/renderer/modules/webaudio/audio_node_input.h"
+#include "third_party/blink/renderer/modules/webaudio/audio_node_options.h"
+#include "third_party/blink/renderer/modules/webaudio/base_audio_context.h"
+#include "third_party/blink/renderer/modules/webaudio/media_stream_audio_destination_node.h"
+#include "third_party/blink/renderer/platform/mediastream/media_stream_center.h"
+#include "third_party/blink/renderer/platform/uuid.h"
+#include "third_party/blink/renderer/platform/wtf/locker.h"
+
+namespace blink {
+
+// WebAudioCapturerSource ignores the channel count beyond 8, so we set the
+// block here to avoid anything can cause the crash.
+static const unsigned long kMaxChannelCount = 8;
+
+MediaStreamAudioDestinationHandler::MediaStreamAudioDestinationHandler(
+ AudioNode& node,
+ size_t number_of_channels)
+ : AudioBasicInspectorHandler(kNodeTypeMediaStreamAudioDestination,
+ node,
+ node.context()->sampleRate(),
+ number_of_channels),
+ mix_bus_(AudioBus::Create(number_of_channels,
+ AudioUtilities::kRenderQuantumFrames)) {
+ source_ = MediaStreamSource::Create("WebAudio-" + CreateCanonicalUUIDString(),
+ MediaStreamSource::kTypeAudio,
+ "MediaStreamAudioDestinationNode", false,
+ MediaStreamSource::kReadyStateLive, true);
+ MediaStreamSourceVector audio_sources;
+ audio_sources.push_back(source_.Get());
+ MediaStreamSourceVector video_sources;
+ stream_ = MediaStream::Create(
+ node.context()->GetExecutionContext(),
+ MediaStreamDescriptor::Create(audio_sources, video_sources));
+ MediaStreamCenter::Instance().DidCreateMediaStreamAndTracks(
+ stream_->Descriptor());
+
+ source_->SetAudioFormat(number_of_channels, node.context()->sampleRate());
+
+ SetInternalChannelCountMode(kExplicit);
+ Initialize();
+}
+
+scoped_refptr<MediaStreamAudioDestinationHandler>
+MediaStreamAudioDestinationHandler::Create(AudioNode& node,
+ size_t number_of_channels) {
+ return base::AdoptRef(
+ new MediaStreamAudioDestinationHandler(node, number_of_channels));
+}
+
+MediaStreamAudioDestinationHandler::~MediaStreamAudioDestinationHandler() {
+ Uninitialize();
+}
+
+void MediaStreamAudioDestinationHandler::Process(size_t number_of_frames) {
+ // Conform the input bus into the internal mix bus, which represents
+ // MediaStreamDestination's channel count.
+
+ // Synchronize with possible dynamic changes to the channel count.
+ MutexTryLocker try_locker(process_lock_);
+
+ // If we can get the lock, we can process normally by updating the
+ // mix bus to a new channel count, if needed. If not, just use the
+ // old mix bus to do the mixing; we'll update the bus next time
+ // around.
+ if (try_locker.Locked()) {
+ unsigned count = ChannelCount();
+ if (count != mix_bus_->NumberOfChannels()) {
+ mix_bus_ = AudioBus::Create(count, AudioUtilities::kRenderQuantumFrames);
+ // setAudioFormat has an internal lock. This can cause audio to
+ // glitch. This is outside of our control.
+ source_->SetAudioFormat(count, Context()->sampleRate());
+ }
+ }
+
+ mix_bus_->CopyFrom(*Input(0).Bus());
+
+ // consumeAudio has an internal lock (also used by setAudioFormat).
+ // This can cause audio to glitch. This is outside of our control.
+ source_->ConsumeAudio(mix_bus_.get(), number_of_frames);
+}
+
+void MediaStreamAudioDestinationHandler::SetChannelCount(
+ unsigned long channel_count,
+ ExceptionState& exception_state) {
+ DCHECK(IsMainThread());
+
+ // Currently the maximum channel count supported for this node is 8,
+ // which is constrained by m_source (WebAudioCapturereSource). Although
+ // it has its own safety check for the excessive channels, throwing an
+ // exception here is useful to developers.
+ if (channel_count < 1 || channel_count > MaxChannelCount()) {
+ exception_state.ThrowDOMException(
+ kNotSupportedError,
+ ExceptionMessages::IndexOutsideRange<unsigned>(
+ "channel count", channel_count, 1,
+ ExceptionMessages::kInclusiveBound, MaxChannelCount(),
+ ExceptionMessages::kInclusiveBound));
+ return;
+ }
+
+ // Synchronize changes in the channel count with process() which
+ // needs to update m_mixBus.
+ MutexLocker locker(process_lock_);
+
+ AudioHandler::SetChannelCount(channel_count, exception_state);
+}
+
+unsigned long MediaStreamAudioDestinationHandler::MaxChannelCount() const {
+ return kMaxChannelCount;
+}
+
+// ----------------------------------------------------------------
+
+MediaStreamAudioDestinationNode::MediaStreamAudioDestinationNode(
+ BaseAudioContext& context,
+ size_t number_of_channels)
+ : AudioBasicInspectorNode(context) {
+ SetHandler(
+ MediaStreamAudioDestinationHandler::Create(*this, number_of_channels));
+}
+
+MediaStreamAudioDestinationNode* MediaStreamAudioDestinationNode::Create(
+ BaseAudioContext& context,
+ size_t number_of_channels,
+ ExceptionState& exception_state) {
+ DCHECK(IsMainThread());
+
+ if (context.IsContextClosed()) {
+ context.ThrowExceptionForClosedState(exception_state);
+ return nullptr;
+ }
+
+ return new MediaStreamAudioDestinationNode(context, number_of_channels);
+}
+
+MediaStreamAudioDestinationNode* MediaStreamAudioDestinationNode::Create(
+ BaseAudioContext* context,
+ const AudioNodeOptions& options,
+ ExceptionState& exception_state) {
+ DCHECK(IsMainThread());
+
+ // Default to stereo; |options| will update it approriately if needed.
+ MediaStreamAudioDestinationNode* node =
+ new MediaStreamAudioDestinationNode(*context, 2);
+
+ // Need to handle channelCount here ourselves because the upper
+ // limit is different from the normal AudioNode::setChannelCount
+ // limit of 32. Error messages will sometimes show the wrong
+ // limits.
+ if (options.hasChannelCount())
+ node->setChannelCount(options.channelCount(), exception_state);
+
+ node->HandleChannelOptions(options, exception_state);
+
+ return node;
+}
+
+MediaStream* MediaStreamAudioDestinationNode::stream() const {
+ return static_cast<MediaStreamAudioDestinationHandler&>(Handler()).Stream();
+}
+
+} // namespace blink