tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

AudioNode.h (11399B)


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