content/media/webaudio/AudioNode.h

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/content/media/webaudio/AudioNode.h	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,274 @@
     1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     1.5 +/* vim:set ts=2 sw=2 sts=2 et cindent: */
     1.6 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.9 +
    1.10 +#ifndef AudioNode_h_
    1.11 +#define AudioNode_h_
    1.12 +
    1.13 +#include "mozilla/DOMEventTargetHelper.h"
    1.14 +#include "mozilla/dom/AudioNodeBinding.h"
    1.15 +#include "nsCycleCollectionParticipant.h"
    1.16 +#include "nsAutoPtr.h"
    1.17 +#include "nsTArray.h"
    1.18 +#include "AudioContext.h"
    1.19 +#include "MediaStreamGraph.h"
    1.20 +#include "WebAudioUtils.h"
    1.21 +#include "mozilla/MemoryReporting.h"
    1.22 +
    1.23 +namespace mozilla {
    1.24 +
    1.25 +namespace dom {
    1.26 +
    1.27 +class AudioContext;
    1.28 +class AudioBufferSourceNode;
    1.29 +class AudioParam;
    1.30 +class AudioParamTimeline;
    1.31 +struct ThreeDPoint;
    1.32 +
    1.33 +template<class T>
    1.34 +class SelfReference {
    1.35 +public:
    1.36 +  SelfReference() : mHeld(false) {}
    1.37 +  ~SelfReference()
    1.38 +  {
    1.39 +    NS_ASSERTION(!mHeld, "Forgot to drop the self reference?");
    1.40 +  }
    1.41 +
    1.42 +  void Take(T* t)
    1.43 +  {
    1.44 +    if (!mHeld) {
    1.45 +      mHeld = true;
    1.46 +      t->AddRef();
    1.47 +    }
    1.48 +  }
    1.49 +  void Drop(T* t)
    1.50 +  {
    1.51 +    if (mHeld) {
    1.52 +      mHeld = false;
    1.53 +      t->Release();
    1.54 +    }
    1.55 +  }
    1.56 +
    1.57 +  operator bool() const { return mHeld; }
    1.58 +
    1.59 +private:
    1.60 +  bool mHeld;
    1.61 +};
    1.62 +
    1.63 +/**
    1.64 + * The DOM object representing a Web Audio AudioNode.
    1.65 + *
    1.66 + * Each AudioNode has a MediaStream representing the actual
    1.67 + * real-time processing and output of this AudioNode.
    1.68 + *
    1.69 + * We track the incoming and outgoing connections to other AudioNodes.
    1.70 + * Outgoing connections have strong ownership.  Also, AudioNodes that will
    1.71 + * produce sound on their output even when they have silent or no input ask
    1.72 + * the AudioContext to keep playing or tail-time references to keep them alive
    1.73 + * until the context is finished.
    1.74 + *
    1.75 + * Explicit disconnections will only remove references from output nodes after
    1.76 + * the graph is notified and the main thread receives a reply.  Similarly,
    1.77 + * nodes with playing or tail-time references release these references only
    1.78 + * after receiving notification from their engine on the graph thread that
    1.79 + * playing has stopped.  Engines notifying the main thread that they have
    1.80 + * finished do so strictly *after* producing and returning their last block.
    1.81 + * In this way, an engine that receives non-null input knows that the input
    1.82 + * comes from nodes that are still alive and will keep their output nodes
    1.83 + * alive for at least as long as it takes to process messages from the graph
    1.84 + * thread.  i.e. the engine receiving non-null input knows that its node is
    1.85 + * still alive, and will still be alive when it receives a message from the
    1.86 + * engine.
    1.87 + */
    1.88 +class AudioNode : public DOMEventTargetHelper
    1.89 +{
    1.90 +protected:
    1.91 +  // You can only use refcounting to delete this object
    1.92 +  virtual ~AudioNode();
    1.93 +
    1.94 +public:
    1.95 +  AudioNode(AudioContext* aContext,
    1.96 +            uint32_t aChannelCount,
    1.97 +            ChannelCountMode aChannelCountMode,
    1.98 +            ChannelInterpretation aChannelInterpretation);
    1.99 +
   1.100 +  // This should be idempotent (safe to call multiple times).
   1.101 +  virtual void DestroyMediaStream();
   1.102 +
   1.103 +  NS_DECL_ISUPPORTS_INHERITED
   1.104 +  NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(AudioNode,
   1.105 +                                           DOMEventTargetHelper)
   1.106 +
   1.107 +  virtual AudioBufferSourceNode* AsAudioBufferSourceNode() {
   1.108 +    return nullptr;
   1.109 +  }
   1.110 +
   1.111 +  virtual const DelayNode* AsDelayNode() const {
   1.112 +    return nullptr;
   1.113 +  }
   1.114 +
   1.115 +  AudioContext* GetParentObject() const
   1.116 +  {
   1.117 +    return mContext;
   1.118 +  }
   1.119 +
   1.120 +  AudioContext* Context() const
   1.121 +  {
   1.122 +    return mContext;
   1.123 +  }
   1.124 +
   1.125 +  virtual void Connect(AudioNode& aDestination, uint32_t aOutput,
   1.126 +                       uint32_t aInput, ErrorResult& aRv);
   1.127 +
   1.128 +  virtual void Connect(AudioParam& aDestination, uint32_t aOutput,
   1.129 +                       ErrorResult& aRv);
   1.130 +
   1.131 +  virtual void Disconnect(uint32_t aOutput, ErrorResult& aRv);
   1.132 +
   1.133 +  // The following two virtual methods must be implemented by each node type
   1.134 +  // to provide their number of input and output ports. These numbers are
   1.135 +  // constant for the lifetime of the node. Both default to 1.
   1.136 +  virtual uint16_t NumberOfInputs() const { return 1; }
   1.137 +  virtual uint16_t NumberOfOutputs() const { return 1; }
   1.138 +
   1.139 +  uint32_t ChannelCount() const { return mChannelCount; }
   1.140 +  virtual void SetChannelCount(uint32_t aChannelCount, ErrorResult& aRv)
   1.141 +  {
   1.142 +    if (aChannelCount == 0 ||
   1.143 +        aChannelCount > WebAudioUtils::MaxChannelCount) {
   1.144 +      aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
   1.145 +      return;
   1.146 +    }
   1.147 +    mChannelCount = aChannelCount;
   1.148 +    SendChannelMixingParametersToStream();
   1.149 +  }
   1.150 +  ChannelCountMode ChannelCountModeValue() const
   1.151 +  {
   1.152 +    return mChannelCountMode;
   1.153 +  }
   1.154 +  virtual void SetChannelCountModeValue(ChannelCountMode aMode, ErrorResult& aRv)
   1.155 +  {
   1.156 +    mChannelCountMode = aMode;
   1.157 +    SendChannelMixingParametersToStream();
   1.158 +  }
   1.159 +  ChannelInterpretation ChannelInterpretationValue() const
   1.160 +  {
   1.161 +    return mChannelInterpretation;
   1.162 +  }
   1.163 +  void SetChannelInterpretationValue(ChannelInterpretation aMode)
   1.164 +  {
   1.165 +    mChannelInterpretation = aMode;
   1.166 +    SendChannelMixingParametersToStream();
   1.167 +  }
   1.168 +
   1.169 +  struct InputNode {
   1.170 +    ~InputNode()
   1.171 +    {
   1.172 +      if (mStreamPort) {
   1.173 +        mStreamPort->Destroy();
   1.174 +      }
   1.175 +    }
   1.176 +
   1.177 +    size_t SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const
   1.178 +    {
   1.179 +      size_t amount = 0;
   1.180 +      if (mStreamPort) {
   1.181 +        amount += mStreamPort->SizeOfIncludingThis(aMallocSizeOf);
   1.182 +      }
   1.183 +
   1.184 +      return amount;
   1.185 +    }
   1.186 +
   1.187 +    // Weak reference.
   1.188 +    AudioNode* mInputNode;
   1.189 +    nsRefPtr<MediaInputPort> mStreamPort;
   1.190 +    // The index of the input port this node feeds into.
   1.191 +    // This is not used for connections to AudioParams.
   1.192 +    uint32_t mInputPort;
   1.193 +    // The index of the output port this node comes out of.
   1.194 +    uint32_t mOutputPort;
   1.195 +  };
   1.196 +
   1.197 +  MediaStream* Stream() { return mStream; }
   1.198 +
   1.199 +  const nsTArray<InputNode>& InputNodes() const
   1.200 +  {
   1.201 +    return mInputNodes;
   1.202 +  }
   1.203 +  const nsTArray<nsRefPtr<AudioNode> >& OutputNodes() const
   1.204 +  {
   1.205 +    return mOutputNodes;
   1.206 +  }
   1.207 +  const nsTArray<nsRefPtr<AudioParam> >& OutputParams() const
   1.208 +  {
   1.209 +    return mOutputParams;
   1.210 +  }
   1.211 +
   1.212 +  void RemoveOutputParam(AudioParam* aParam);
   1.213 +
   1.214 +  // MarkActive() asks the context to keep the AudioNode alive until the
   1.215 +  // context is finished.  This takes care of "playing" references and
   1.216 +  // "tail-time" references.
   1.217 +  void MarkActive() { Context()->RegisterActiveNode(this); }
   1.218 +  // Active nodes call MarkInactive() when they have finished producing sound
   1.219 +  // for the foreseeable future.
   1.220 +  // Do not call MarkInactive from a node destructor.  If the destructor is
   1.221 +  // called, then the node is already inactive.
   1.222 +  // MarkInactive() may delete |this|.
   1.223 +  void MarkInactive() { Context()->UnregisterActiveNode(this); }
   1.224 +
   1.225 +  virtual size_t SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const;
   1.226 +  virtual size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const;
   1.227 +
   1.228 +  virtual const char* NodeType() const = 0;
   1.229 +
   1.230 +private:
   1.231 +  friend class AudioBufferSourceNode;
   1.232 +  // This could possibly delete 'this'.
   1.233 +  void DisconnectFromGraph();
   1.234 +
   1.235 +protected:
   1.236 +  static void Callback(AudioNode* aNode) { /* not implemented */ }
   1.237 +
   1.238 +  // Helpers for sending different value types to streams
   1.239 +  void SendDoubleParameterToStream(uint32_t aIndex, double aValue);
   1.240 +  void SendInt32ParameterToStream(uint32_t aIndex, int32_t aValue);
   1.241 +  void SendThreeDPointParameterToStream(uint32_t aIndex, const ThreeDPoint& aValue);
   1.242 +  void SendChannelMixingParametersToStream();
   1.243 +  static void SendTimelineParameterToStream(AudioNode* aNode, uint32_t aIndex,
   1.244 +                                            const AudioParamTimeline& aValue);
   1.245 +
   1.246 +private:
   1.247 +  nsRefPtr<AudioContext> mContext;
   1.248 +
   1.249 +protected:
   1.250 +  // Must be set in the constructor. Must not be null.
   1.251 +  // If MaxNumberOfInputs() is > 0, then mStream must be a ProcessedMediaStream.
   1.252 +  nsRefPtr<MediaStream> mStream;
   1.253 +
   1.254 +private:
   1.255 +  // For every InputNode, there is a corresponding entry in mOutputNodes of the
   1.256 +  // InputNode's mInputNode.
   1.257 +  nsTArray<InputNode> mInputNodes;
   1.258 +  // For every mOutputNode entry, there is a corresponding entry in mInputNodes
   1.259 +  // of the mOutputNode entry. We won't necessarily be able to identify the
   1.260 +  // exact matching entry, since mOutputNodes doesn't include the port
   1.261 +  // identifiers and the same node could be connected on multiple ports.
   1.262 +  nsTArray<nsRefPtr<AudioNode> > mOutputNodes;
   1.263 +  // For every mOutputParams entry, there is a corresponding entry in
   1.264 +  // AudioParam::mInputNodes of the mOutputParams entry. We won't necessarily be
   1.265 +  // able to identify the exact matching entry, since mOutputParams doesn't
   1.266 +  // include the port identifiers and the same node could be connected on
   1.267 +  // multiple ports.
   1.268 +  nsTArray<nsRefPtr<AudioParam> > mOutputParams;
   1.269 +  uint32_t mChannelCount;
   1.270 +  ChannelCountMode mChannelCountMode;
   1.271 +  ChannelInterpretation mChannelInterpretation;
   1.272 +};
   1.273 +
   1.274 +}
   1.275 +}
   1.276 +
   1.277 +#endif

mercurial