content/media/webaudio/AudioNode.h

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

michael@0 1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
michael@0 2 /* vim:set ts=2 sw=2 sts=2 et cindent: */
michael@0 3 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 4 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 6
michael@0 7 #ifndef AudioNode_h_
michael@0 8 #define AudioNode_h_
michael@0 9
michael@0 10 #include "mozilla/DOMEventTargetHelper.h"
michael@0 11 #include "mozilla/dom/AudioNodeBinding.h"
michael@0 12 #include "nsCycleCollectionParticipant.h"
michael@0 13 #include "nsAutoPtr.h"
michael@0 14 #include "nsTArray.h"
michael@0 15 #include "AudioContext.h"
michael@0 16 #include "MediaStreamGraph.h"
michael@0 17 #include "WebAudioUtils.h"
michael@0 18 #include "mozilla/MemoryReporting.h"
michael@0 19
michael@0 20 namespace mozilla {
michael@0 21
michael@0 22 namespace dom {
michael@0 23
michael@0 24 class AudioContext;
michael@0 25 class AudioBufferSourceNode;
michael@0 26 class AudioParam;
michael@0 27 class AudioParamTimeline;
michael@0 28 struct ThreeDPoint;
michael@0 29
michael@0 30 template<class T>
michael@0 31 class SelfReference {
michael@0 32 public:
michael@0 33 SelfReference() : mHeld(false) {}
michael@0 34 ~SelfReference()
michael@0 35 {
michael@0 36 NS_ASSERTION(!mHeld, "Forgot to drop the self reference?");
michael@0 37 }
michael@0 38
michael@0 39 void Take(T* t)
michael@0 40 {
michael@0 41 if (!mHeld) {
michael@0 42 mHeld = true;
michael@0 43 t->AddRef();
michael@0 44 }
michael@0 45 }
michael@0 46 void Drop(T* t)
michael@0 47 {
michael@0 48 if (mHeld) {
michael@0 49 mHeld = false;
michael@0 50 t->Release();
michael@0 51 }
michael@0 52 }
michael@0 53
michael@0 54 operator bool() const { return mHeld; }
michael@0 55
michael@0 56 private:
michael@0 57 bool mHeld;
michael@0 58 };
michael@0 59
michael@0 60 /**
michael@0 61 * The DOM object representing a Web Audio AudioNode.
michael@0 62 *
michael@0 63 * Each AudioNode has a MediaStream representing the actual
michael@0 64 * real-time processing and output of this AudioNode.
michael@0 65 *
michael@0 66 * We track the incoming and outgoing connections to other AudioNodes.
michael@0 67 * Outgoing connections have strong ownership. Also, AudioNodes that will
michael@0 68 * produce sound on their output even when they have silent or no input ask
michael@0 69 * the AudioContext to keep playing or tail-time references to keep them alive
michael@0 70 * until the context is finished.
michael@0 71 *
michael@0 72 * Explicit disconnections will only remove references from output nodes after
michael@0 73 * the graph is notified and the main thread receives a reply. Similarly,
michael@0 74 * nodes with playing or tail-time references release these references only
michael@0 75 * after receiving notification from their engine on the graph thread that
michael@0 76 * playing has stopped. Engines notifying the main thread that they have
michael@0 77 * finished do so strictly *after* producing and returning their last block.
michael@0 78 * In this way, an engine that receives non-null input knows that the input
michael@0 79 * comes from nodes that are still alive and will keep their output nodes
michael@0 80 * alive for at least as long as it takes to process messages from the graph
michael@0 81 * thread. i.e. the engine receiving non-null input knows that its node is
michael@0 82 * still alive, and will still be alive when it receives a message from the
michael@0 83 * engine.
michael@0 84 */
michael@0 85 class AudioNode : public DOMEventTargetHelper
michael@0 86 {
michael@0 87 protected:
michael@0 88 // You can only use refcounting to delete this object
michael@0 89 virtual ~AudioNode();
michael@0 90
michael@0 91 public:
michael@0 92 AudioNode(AudioContext* aContext,
michael@0 93 uint32_t aChannelCount,
michael@0 94 ChannelCountMode aChannelCountMode,
michael@0 95 ChannelInterpretation aChannelInterpretation);
michael@0 96
michael@0 97 // This should be idempotent (safe to call multiple times).
michael@0 98 virtual void DestroyMediaStream();
michael@0 99
michael@0 100 NS_DECL_ISUPPORTS_INHERITED
michael@0 101 NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(AudioNode,
michael@0 102 DOMEventTargetHelper)
michael@0 103
michael@0 104 virtual AudioBufferSourceNode* AsAudioBufferSourceNode() {
michael@0 105 return nullptr;
michael@0 106 }
michael@0 107
michael@0 108 virtual const DelayNode* AsDelayNode() const {
michael@0 109 return nullptr;
michael@0 110 }
michael@0 111
michael@0 112 AudioContext* GetParentObject() const
michael@0 113 {
michael@0 114 return mContext;
michael@0 115 }
michael@0 116
michael@0 117 AudioContext* Context() const
michael@0 118 {
michael@0 119 return mContext;
michael@0 120 }
michael@0 121
michael@0 122 virtual void Connect(AudioNode& aDestination, uint32_t aOutput,
michael@0 123 uint32_t aInput, ErrorResult& aRv);
michael@0 124
michael@0 125 virtual void Connect(AudioParam& aDestination, uint32_t aOutput,
michael@0 126 ErrorResult& aRv);
michael@0 127
michael@0 128 virtual void Disconnect(uint32_t aOutput, ErrorResult& aRv);
michael@0 129
michael@0 130 // The following two virtual methods must be implemented by each node type
michael@0 131 // to provide their number of input and output ports. These numbers are
michael@0 132 // constant for the lifetime of the node. Both default to 1.
michael@0 133 virtual uint16_t NumberOfInputs() const { return 1; }
michael@0 134 virtual uint16_t NumberOfOutputs() const { return 1; }
michael@0 135
michael@0 136 uint32_t ChannelCount() const { return mChannelCount; }
michael@0 137 virtual void SetChannelCount(uint32_t aChannelCount, ErrorResult& aRv)
michael@0 138 {
michael@0 139 if (aChannelCount == 0 ||
michael@0 140 aChannelCount > WebAudioUtils::MaxChannelCount) {
michael@0 141 aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
michael@0 142 return;
michael@0 143 }
michael@0 144 mChannelCount = aChannelCount;
michael@0 145 SendChannelMixingParametersToStream();
michael@0 146 }
michael@0 147 ChannelCountMode ChannelCountModeValue() const
michael@0 148 {
michael@0 149 return mChannelCountMode;
michael@0 150 }
michael@0 151 virtual void SetChannelCountModeValue(ChannelCountMode aMode, ErrorResult& aRv)
michael@0 152 {
michael@0 153 mChannelCountMode = aMode;
michael@0 154 SendChannelMixingParametersToStream();
michael@0 155 }
michael@0 156 ChannelInterpretation ChannelInterpretationValue() const
michael@0 157 {
michael@0 158 return mChannelInterpretation;
michael@0 159 }
michael@0 160 void SetChannelInterpretationValue(ChannelInterpretation aMode)
michael@0 161 {
michael@0 162 mChannelInterpretation = aMode;
michael@0 163 SendChannelMixingParametersToStream();
michael@0 164 }
michael@0 165
michael@0 166 struct InputNode {
michael@0 167 ~InputNode()
michael@0 168 {
michael@0 169 if (mStreamPort) {
michael@0 170 mStreamPort->Destroy();
michael@0 171 }
michael@0 172 }
michael@0 173
michael@0 174 size_t SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const
michael@0 175 {
michael@0 176 size_t amount = 0;
michael@0 177 if (mStreamPort) {
michael@0 178 amount += mStreamPort->SizeOfIncludingThis(aMallocSizeOf);
michael@0 179 }
michael@0 180
michael@0 181 return amount;
michael@0 182 }
michael@0 183
michael@0 184 // Weak reference.
michael@0 185 AudioNode* mInputNode;
michael@0 186 nsRefPtr<MediaInputPort> mStreamPort;
michael@0 187 // The index of the input port this node feeds into.
michael@0 188 // This is not used for connections to AudioParams.
michael@0 189 uint32_t mInputPort;
michael@0 190 // The index of the output port this node comes out of.
michael@0 191 uint32_t mOutputPort;
michael@0 192 };
michael@0 193
michael@0 194 MediaStream* Stream() { return mStream; }
michael@0 195
michael@0 196 const nsTArray<InputNode>& InputNodes() const
michael@0 197 {
michael@0 198 return mInputNodes;
michael@0 199 }
michael@0 200 const nsTArray<nsRefPtr<AudioNode> >& OutputNodes() const
michael@0 201 {
michael@0 202 return mOutputNodes;
michael@0 203 }
michael@0 204 const nsTArray<nsRefPtr<AudioParam> >& OutputParams() const
michael@0 205 {
michael@0 206 return mOutputParams;
michael@0 207 }
michael@0 208
michael@0 209 void RemoveOutputParam(AudioParam* aParam);
michael@0 210
michael@0 211 // MarkActive() asks the context to keep the AudioNode alive until the
michael@0 212 // context is finished. This takes care of "playing" references and
michael@0 213 // "tail-time" references.
michael@0 214 void MarkActive() { Context()->RegisterActiveNode(this); }
michael@0 215 // Active nodes call MarkInactive() when they have finished producing sound
michael@0 216 // for the foreseeable future.
michael@0 217 // Do not call MarkInactive from a node destructor. If the destructor is
michael@0 218 // called, then the node is already inactive.
michael@0 219 // MarkInactive() may delete |this|.
michael@0 220 void MarkInactive() { Context()->UnregisterActiveNode(this); }
michael@0 221
michael@0 222 virtual size_t SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const;
michael@0 223 virtual size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const;
michael@0 224
michael@0 225 virtual const char* NodeType() const = 0;
michael@0 226
michael@0 227 private:
michael@0 228 friend class AudioBufferSourceNode;
michael@0 229 // This could possibly delete 'this'.
michael@0 230 void DisconnectFromGraph();
michael@0 231
michael@0 232 protected:
michael@0 233 static void Callback(AudioNode* aNode) { /* not implemented */ }
michael@0 234
michael@0 235 // Helpers for sending different value types to streams
michael@0 236 void SendDoubleParameterToStream(uint32_t aIndex, double aValue);
michael@0 237 void SendInt32ParameterToStream(uint32_t aIndex, int32_t aValue);
michael@0 238 void SendThreeDPointParameterToStream(uint32_t aIndex, const ThreeDPoint& aValue);
michael@0 239 void SendChannelMixingParametersToStream();
michael@0 240 static void SendTimelineParameterToStream(AudioNode* aNode, uint32_t aIndex,
michael@0 241 const AudioParamTimeline& aValue);
michael@0 242
michael@0 243 private:
michael@0 244 nsRefPtr<AudioContext> mContext;
michael@0 245
michael@0 246 protected:
michael@0 247 // Must be set in the constructor. Must not be null.
michael@0 248 // If MaxNumberOfInputs() is > 0, then mStream must be a ProcessedMediaStream.
michael@0 249 nsRefPtr<MediaStream> mStream;
michael@0 250
michael@0 251 private:
michael@0 252 // For every InputNode, there is a corresponding entry in mOutputNodes of the
michael@0 253 // InputNode's mInputNode.
michael@0 254 nsTArray<InputNode> mInputNodes;
michael@0 255 // For every mOutputNode entry, there is a corresponding entry in mInputNodes
michael@0 256 // of the mOutputNode entry. We won't necessarily be able to identify the
michael@0 257 // exact matching entry, since mOutputNodes doesn't include the port
michael@0 258 // identifiers and the same node could be connected on multiple ports.
michael@0 259 nsTArray<nsRefPtr<AudioNode> > mOutputNodes;
michael@0 260 // For every mOutputParams entry, there is a corresponding entry in
michael@0 261 // AudioParam::mInputNodes of the mOutputParams entry. We won't necessarily be
michael@0 262 // able to identify the exact matching entry, since mOutputParams doesn't
michael@0 263 // include the port identifiers and the same node could be connected on
michael@0 264 // multiple ports.
michael@0 265 nsTArray<nsRefPtr<AudioParam> > mOutputParams;
michael@0 266 uint32_t mChannelCount;
michael@0 267 ChannelCountMode mChannelCountMode;
michael@0 268 ChannelInterpretation mChannelInterpretation;
michael@0 269 };
michael@0 270
michael@0 271 }
michael@0 272 }
michael@0 273
michael@0 274 #endif

mercurial