Coverage Report

Created: 2018-09-25 14:53

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