content/media/webaudio/AudioNode.h

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

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

mercurial