summaryrefslogtreecommitdiffstats
path: root/dom/media/webaudio/MediaStreamAudioDestinationNode.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'dom/media/webaudio/MediaStreamAudioDestinationNode.cpp')
-rw-r--r--dom/media/webaudio/MediaStreamAudioDestinationNode.cpp150
1 files changed, 150 insertions, 0 deletions
diff --git a/dom/media/webaudio/MediaStreamAudioDestinationNode.cpp b/dom/media/webaudio/MediaStreamAudioDestinationNode.cpp
new file mode 100644
index 0000000000..704adaa304
--- /dev/null
+++ b/dom/media/webaudio/MediaStreamAudioDestinationNode.cpp
@@ -0,0 +1,150 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "MediaStreamAudioDestinationNode.h"
+#include "mozilla/dom/Document.h"
+#include "mozilla/dom/MediaStreamAudioDestinationNodeBinding.h"
+#include "AudioNodeEngine.h"
+#include "AudioNodeTrack.h"
+#include "AudioStreamTrack.h"
+#include "DOMMediaStream.h"
+#include "ForwardedInputTrack.h"
+
+namespace mozilla::dom {
+
+class AudioDestinationTrackSource final : public MediaStreamTrackSource {
+ public:
+ NS_DECL_ISUPPORTS_INHERITED
+ NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(AudioDestinationTrackSource,
+ MediaStreamTrackSource)
+
+ AudioDestinationTrackSource(MediaStreamAudioDestinationNode* aNode,
+ mozilla::MediaTrack* aInputTrack,
+ ProcessedMediaTrack* aTrack,
+ nsIPrincipal* aPrincipal)
+ : MediaStreamTrackSource(
+ aPrincipal, nsString(),
+ // We pass 0 here because tracking ids are video only for now.
+ TrackingId(TrackingId::Source::AudioDestinationNode, 0)),
+ mTrack(aTrack),
+ mPort(mTrack->AllocateInputPort(aInputTrack)),
+ mNode(aNode) {}
+
+ void Destroy() override {
+ if (!mTrack->IsDestroyed()) {
+ mTrack->Destroy();
+ mPort->Destroy();
+ }
+ if (mNode) {
+ mNode->DestroyMediaTrack();
+ mNode = nullptr;
+ }
+ }
+
+ MediaSourceEnum GetMediaSource() const override {
+ return MediaSourceEnum::AudioCapture;
+ }
+
+ void Stop() override { Destroy(); }
+
+ void Disable() override {}
+
+ void Enable() override {}
+
+ const RefPtr<ProcessedMediaTrack> mTrack;
+ const RefPtr<MediaInputPort> mPort;
+
+ private:
+ ~AudioDestinationTrackSource() = default;
+
+ RefPtr<MediaStreamAudioDestinationNode> mNode;
+};
+
+NS_IMPL_ADDREF_INHERITED(AudioDestinationTrackSource, MediaStreamTrackSource)
+NS_IMPL_RELEASE_INHERITED(AudioDestinationTrackSource, MediaStreamTrackSource)
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(AudioDestinationTrackSource)
+NS_INTERFACE_MAP_END_INHERITING(MediaStreamTrackSource)
+NS_IMPL_CYCLE_COLLECTION_INHERITED(AudioDestinationTrackSource,
+ MediaStreamTrackSource, mNode)
+
+NS_IMPL_CYCLE_COLLECTION_INHERITED(MediaStreamAudioDestinationNode, AudioNode,
+ mDOMStream)
+
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(MediaStreamAudioDestinationNode)
+NS_INTERFACE_MAP_END_INHERITING(AudioNode)
+
+NS_IMPL_ADDREF_INHERITED(MediaStreamAudioDestinationNode, AudioNode)
+NS_IMPL_RELEASE_INHERITED(MediaStreamAudioDestinationNode, AudioNode)
+
+MediaStreamAudioDestinationNode::MediaStreamAudioDestinationNode(
+ AudioContext* aContext)
+ : AudioNode(aContext, 2, ChannelCountMode::Explicit,
+ ChannelInterpretation::Speakers),
+ mDOMStream(MakeAndAddRef<DOMMediaStream>(GetOwner())) {
+ // Ensure an audio track with the correct ID is exposed to JS. If we can't get
+ // a principal here because the document is not available, pass in a null
+ // principal. This happens in edge cases when the document is being unloaded
+ // and it does not matter too much to have something working as long as it's
+ // not dangerous.
+ nsCOMPtr<nsIPrincipal> principal = nullptr;
+ if (aContext->GetParentObject()) {
+ Document* doc = aContext->GetParentObject()->GetExtantDoc();
+ principal = doc->NodePrincipal();
+ }
+ mTrack = AudioNodeTrack::Create(aContext, new AudioNodeEngine(this),
+ AudioNodeTrack::EXTERNAL_OUTPUT,
+ aContext->Graph());
+ auto source = MakeRefPtr<AudioDestinationTrackSource>(
+ this, mTrack,
+ aContext->Graph()->CreateForwardedInputTrack(MediaSegment::AUDIO),
+ principal);
+ auto track = MakeRefPtr<AudioStreamTrack>(GetOwner(), source->mTrack, source);
+ mDOMStream->AddTrackInternal(track);
+}
+
+/* static */
+already_AddRefed<MediaStreamAudioDestinationNode>
+MediaStreamAudioDestinationNode::Create(AudioContext& aAudioContext,
+ const AudioNodeOptions& aOptions,
+ ErrorResult& aRv) {
+ // The spec has a pointless check here. See
+ // https://github.com/WebAudio/web-audio-api/issues/2149
+ MOZ_RELEASE_ASSERT(!aAudioContext.IsOffline(), "Bindings messed up?");
+
+ RefPtr<MediaStreamAudioDestinationNode> audioNode =
+ new MediaStreamAudioDestinationNode(&aAudioContext);
+
+ audioNode->Initialize(aOptions, aRv);
+ if (NS_WARN_IF(aRv.Failed())) {
+ return nullptr;
+ }
+
+ return audioNode.forget();
+}
+
+size_t MediaStreamAudioDestinationNode::SizeOfExcludingThis(
+ MallocSizeOf aMallocSizeOf) const {
+ // Future:
+ // - mDOMStream
+ size_t amount = AudioNode::SizeOfExcludingThis(aMallocSizeOf);
+ return amount;
+}
+
+size_t MediaStreamAudioDestinationNode::SizeOfIncludingThis(
+ MallocSizeOf aMallocSizeOf) const {
+ return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf);
+}
+
+void MediaStreamAudioDestinationNode::DestroyMediaTrack() {
+ AudioNode::DestroyMediaTrack();
+}
+
+JSObject* MediaStreamAudioDestinationNode::WrapObject(
+ JSContext* aCx, JS::Handle<JSObject*> aGivenProto) {
+ return MediaStreamAudioDestinationNode_Binding::Wrap(aCx, this, aGivenProto);
+}
+
+} // namespace mozilla::dom