LCOV - code coverage report
Current view: top level - dom/media/webaudio - AudioContext.h (source / functions) Hit Total Coverage
Test: output.info Lines: 0 15 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 19 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       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 AudioContext_h_
       8             : #define AudioContext_h_
       9             : 
      10             : #include "mozilla/dom/AudioChannelBinding.h"
      11             : #include "MediaBufferDecoder.h"
      12             : #include "mozilla/Attributes.h"
      13             : #include "mozilla/DOMEventTargetHelper.h"
      14             : #include "mozilla/MemoryReporting.h"
      15             : #include "mozilla/dom/TypedArray.h"
      16             : #include "mozilla/UniquePtr.h"
      17             : #include "nsCOMPtr.h"
      18             : #include "nsCycleCollectionParticipant.h"
      19             : #include "nsHashKeys.h"
      20             : #include "nsTHashtable.h"
      21             : #include "js/TypeDecls.h"
      22             : #include "nsIMemoryReporter.h"
      23             : 
      24             : // X11 has a #define for CurrentTime. Unbelievable :-(.
      25             : // See dom/media/DOMMediaStream.h for more fun!
      26             : #ifdef CurrentTime
      27             : #undef CurrentTime
      28             : #endif
      29             : 
      30             : namespace WebCore {
      31             :   class PeriodicWave;
      32             : } // namespace WebCore
      33             : 
      34             : class nsPIDOMWindowInner;
      35             : 
      36             : namespace mozilla {
      37             : 
      38             : class DOMMediaStream;
      39             : class ErrorResult;
      40             : class MediaStream;
      41             : class MediaStreamGraph;
      42             : class AudioNodeStream;
      43             : 
      44             : namespace dom {
      45             : 
      46             : enum class AudioContextState : uint8_t;
      47             : class AnalyserNode;
      48             : class AudioBuffer;
      49             : class AudioBufferSourceNode;
      50             : class AudioDestinationNode;
      51             : class AudioListener;
      52             : class AudioNode;
      53             : class BiquadFilterNode;
      54             : class ChannelMergerNode;
      55             : class ChannelSplitterNode;
      56             : class ConstantSourceNode;
      57             : class ConvolverNode;
      58             : class DelayNode;
      59             : class DynamicsCompressorNode;
      60             : class GainNode;
      61             : class GlobalObject;
      62             : class HTMLMediaElement;
      63             : class IIRFilterNode;
      64             : class MediaElementAudioSourceNode;
      65             : class MediaStreamAudioDestinationNode;
      66             : class MediaStreamAudioSourceNode;
      67             : class OscillatorNode;
      68             : class PannerNode;
      69             : class ScriptProcessorNode;
      70             : class StereoPannerNode;
      71             : class WaveShaperNode;
      72             : class PeriodicWave;
      73             : struct PeriodicWaveConstraints;
      74             : class Promise;
      75             : enum class OscillatorType : uint8_t;
      76             : 
      77             : // This is addrefed by the OscillatorNodeEngine on the main thread
      78             : // and then used from the MSG thread.
      79             : // It can be released either from the graph thread or the main thread.
      80             : class BasicWaveFormCache
      81             : {
      82             : public:
      83             :   explicit BasicWaveFormCache(uint32_t aSampleRate);
      84           0 :   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(BasicWaveFormCache)
      85             :   WebCore::PeriodicWave* GetBasicWaveForm(OscillatorType aType);
      86             : private:
      87             :   ~BasicWaveFormCache();
      88             :   RefPtr<WebCore::PeriodicWave> mSawtooth;
      89             :   RefPtr<WebCore::PeriodicWave> mSquare;
      90             :   RefPtr<WebCore::PeriodicWave> mTriangle;
      91             :   uint32_t mSampleRate;
      92             : };
      93             : 
      94             : 
      95             : /* This runnable allows the MSG to notify the main thread when audio is actually
      96             :  * flowing */
      97           0 : class StateChangeTask final : public Runnable
      98             : {
      99             : public:
     100             :   /* This constructor should be used when this event is sent from the main
     101             :    * thread. */
     102             :   StateChangeTask(AudioContext* aAudioContext, void* aPromise, AudioContextState aNewState);
     103             : 
     104             :   /* This constructor should be used when this event is sent from the audio
     105             :    * thread. */
     106             :   StateChangeTask(AudioNodeStream* aStream, void* aPromise, AudioContextState aNewState);
     107             : 
     108             :   NS_IMETHOD Run() override;
     109             : 
     110             : private:
     111             :   RefPtr<AudioContext> mAudioContext;
     112             :   void* mPromise;
     113             :   RefPtr<AudioNodeStream> mAudioNodeStream;
     114             :   AudioContextState mNewState;
     115             : };
     116             : 
     117             : enum class AudioContextOperation { Suspend, Resume, Close };
     118             : 
     119             : class AudioContext final : public DOMEventTargetHelper,
     120             :                            public nsIMemoryReporter
     121             : {
     122             :   AudioContext(nsPIDOMWindowInner* aParentWindow,
     123             :                bool aIsOffline,
     124             :                AudioChannel aChannel,
     125             :                uint32_t aNumberOfChannels = 0,
     126             :                uint32_t aLength = 0,
     127             :                float aSampleRate = 0.0f);
     128             :   ~AudioContext();
     129             : 
     130             :   nsresult Init();
     131             : 
     132             : public:
     133             :   typedef uint64_t AudioContextId;
     134             : 
     135             :   NS_DECL_ISUPPORTS_INHERITED
     136           0 :   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(AudioContext,
     137             :                                            DOMEventTargetHelper)
     138           0 :   MOZ_DEFINE_MALLOC_SIZE_OF(MallocSizeOf)
     139             : 
     140           0 :   nsPIDOMWindowInner* GetParentObject() const
     141             :   {
     142           0 :     return GetOwner();
     143             :   }
     144             : 
     145             :   virtual void DisconnectFromOwner() override;
     146             : 
     147             :   void Shutdown(); // idempotent
     148             : 
     149             :   JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
     150             : 
     151             :   using DOMEventTargetHelper::DispatchTrustedEvent;
     152             : 
     153             :   // Constructor for regular AudioContext
     154             :   static already_AddRefed<AudioContext>
     155             :   Constructor(const GlobalObject& aGlobal, ErrorResult& aRv);
     156             : 
     157             :   // Constructor for offline AudioContext
     158             :   static already_AddRefed<AudioContext>
     159             :   Constructor(const GlobalObject& aGlobal,
     160             :               uint32_t aNumberOfChannels,
     161             :               uint32_t aLength,
     162             :               float aSampleRate,
     163             :               ErrorResult& aRv);
     164             : 
     165             :   // AudioContext methods
     166             : 
     167           0 :   AudioDestinationNode* Destination() const
     168             :   {
     169           0 :     return mDestination;
     170             :   }
     171             : 
     172           0 :   float SampleRate() const
     173             :   {
     174           0 :     return mSampleRate;
     175             :   }
     176             : 
     177           0 :   bool ShouldSuspendNewStream() const { return mSuspendCalled; }
     178             : 
     179             :   double CurrentTime() const;
     180             : 
     181             :   AudioListener* Listener();
     182             : 
     183           0 :   AudioContextState State() const { return mAudioContextState; }
     184             : 
     185             :   // Those three methods return a promise to content, that is resolved when an
     186             :   // (possibly long) operation is completed on the MSG (and possibly other)
     187             :   // thread(s). To avoid having to match the calls and asychronous result when
     188             :   // the operation is completed, we keep a reference to the promises on the main
     189             :   // thread, and then send the promises pointers down the MSG thread, as a void*
     190             :   // (to make it very clear that the pointer is to merely be treated as an ID).
     191             :   // When back on the main thread, we can resolve or reject the promise, by
     192             :   // casting it back to a `Promise*` while asserting we're back on the main
     193             :   // thread and removing the reference we added.
     194             :   already_AddRefed<Promise> Suspend(ErrorResult& aRv);
     195             :   already_AddRefed<Promise> Resume(ErrorResult& aRv);
     196             :   already_AddRefed<Promise> Close(ErrorResult& aRv);
     197           0 :   IMPL_EVENT_HANDLER(statechange)
     198             : 
     199             :   already_AddRefed<AudioBufferSourceNode> CreateBufferSource(ErrorResult& aRv);
     200             : 
     201             :   already_AddRefed<ConstantSourceNode> CreateConstantSource(ErrorResult& aRv);
     202             : 
     203             :   already_AddRefed<AudioBuffer>
     204             :   CreateBuffer(uint32_t aNumberOfChannels, uint32_t aLength, float aSampleRate,
     205             :                ErrorResult& aRv);
     206             : 
     207             :   already_AddRefed<MediaStreamAudioDestinationNode>
     208             :   CreateMediaStreamDestination(ErrorResult& aRv);
     209             : 
     210             :   already_AddRefed<ScriptProcessorNode>
     211             :   CreateScriptProcessor(uint32_t aBufferSize,
     212             :                         uint32_t aNumberOfInputChannels,
     213             :                         uint32_t aNumberOfOutputChannels,
     214             :                         ErrorResult& aRv);
     215             : 
     216             :   already_AddRefed<StereoPannerNode>
     217             :   CreateStereoPanner(ErrorResult& aRv);
     218             : 
     219             :   already_AddRefed<AnalyserNode>
     220             :   CreateAnalyser(ErrorResult& aRv);
     221             : 
     222             :   already_AddRefed<GainNode>
     223             :   CreateGain(ErrorResult& aRv);
     224             : 
     225             :   already_AddRefed<WaveShaperNode>
     226             :   CreateWaveShaper(ErrorResult& aRv);
     227             : 
     228             :   already_AddRefed<MediaElementAudioSourceNode>
     229             :   CreateMediaElementSource(HTMLMediaElement& aMediaElement, ErrorResult& aRv);
     230             :   already_AddRefed<MediaStreamAudioSourceNode>
     231             :   CreateMediaStreamSource(DOMMediaStream& aMediaStream, ErrorResult& aRv);
     232             : 
     233             :   already_AddRefed<DelayNode>
     234             :   CreateDelay(double aMaxDelayTime, ErrorResult& aRv);
     235             : 
     236             :   already_AddRefed<PannerNode>
     237             :   CreatePanner(ErrorResult& aRv);
     238             : 
     239             :   already_AddRefed<ConvolverNode>
     240             :   CreateConvolver(ErrorResult& aRv);
     241             : 
     242             :   already_AddRefed<ChannelSplitterNode>
     243             :   CreateChannelSplitter(uint32_t aNumberOfOutputs, ErrorResult& aRv);
     244             : 
     245             :   already_AddRefed<ChannelMergerNode>
     246             :   CreateChannelMerger(uint32_t aNumberOfInputs, ErrorResult& aRv);
     247             : 
     248             :   already_AddRefed<DynamicsCompressorNode>
     249             :   CreateDynamicsCompressor(ErrorResult& aRv);
     250             : 
     251             :   already_AddRefed<BiquadFilterNode>
     252             :   CreateBiquadFilter(ErrorResult& aRv);
     253             : 
     254             :   already_AddRefed<IIRFilterNode>
     255             :   CreateIIRFilter(const Sequence<double>& aFeedforward,
     256             :                   const Sequence<double>& aFeedback,
     257             :                   mozilla::ErrorResult& aRv);
     258             : 
     259             :   already_AddRefed<OscillatorNode>
     260             :   CreateOscillator(ErrorResult& aRv);
     261             : 
     262             :   already_AddRefed<PeriodicWave>
     263             :   CreatePeriodicWave(const Float32Array& aRealData, const Float32Array& aImagData,
     264             :                      const PeriodicWaveConstraints& aConstraints,
     265             :                      ErrorResult& aRv);
     266             : 
     267             :   already_AddRefed<Promise>
     268             :   DecodeAudioData(const ArrayBuffer& aBuffer,
     269             :                   const Optional<OwningNonNull<DecodeSuccessCallback> >& aSuccessCallback,
     270             :                   const Optional<OwningNonNull<DecodeErrorCallback> >& aFailureCallback,
     271             :                   ErrorResult& aRv);
     272             : 
     273             :   // OfflineAudioContext methods
     274             :   already_AddRefed<Promise> StartRendering(ErrorResult& aRv);
     275           0 :   IMPL_EVENT_HANDLER(complete)
     276             :   unsigned long Length();
     277             : 
     278           0 :   bool IsOffline() const { return mIsOffline; }
     279             : 
     280             :   MediaStreamGraph* Graph() const;
     281             :   MediaStream* DestinationStream() const;
     282             : 
     283             :   // Nodes register here if they will produce sound even if they have silent
     284             :   // or no input connections.  The AudioContext will keep registered nodes
     285             :   // alive until the context is collected.  This takes care of "playing"
     286             :   // references and "tail-time" references.
     287             :   void RegisterActiveNode(AudioNode* aNode);
     288             :   // Nodes unregister when they have finished producing sound for the
     289             :   // foreseeable future.
     290             :   // Do NOT call UnregisterActiveNode from an AudioNode destructor.
     291             :   // If the destructor is called, then the Node has already been unregistered.
     292             :   // The destructor may be called during hashtable enumeration, during which
     293             :   // unregistering would not be safe.
     294             :   void UnregisterActiveNode(AudioNode* aNode);
     295             : 
     296             :   void UnregisterAudioBufferSourceNode(AudioBufferSourceNode* aNode);
     297             :   void UnregisterPannerNode(PannerNode* aNode);
     298             :   void UpdatePannerSource();
     299             : 
     300             :   uint32_t MaxChannelCount() const;
     301             : 
     302             :   uint32_t ActiveNodeCount() const;
     303             : 
     304             :   void Mute() const;
     305             :   void Unmute() const;
     306             : 
     307             :   JSObject* GetGlobalJSObject() const;
     308             : 
     309             :   void RegisterNode(AudioNode* aNode);
     310             :   void UnregisterNode(AudioNode* aNode);
     311             : 
     312             :   void OnStateChanged(void* aPromise, AudioContextState aNewState);
     313             : 
     314             :   BasicWaveFormCache* GetBasicWaveFormCache();
     315             : 
     316             :   bool CheckClosed(ErrorResult& aRv);
     317             : 
     318             :   void Dispatch(already_AddRefed<nsIRunnable>&& aRunnable);
     319             : 
     320             : private:
     321             :   void DisconnectFromWindow();
     322             :   void RemoveFromDecodeQueue(WebAudioDecodeJob* aDecodeJob);
     323             :   void ShutdownDecoder();
     324             : 
     325             :   size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
     326             :   NS_DECL_NSIMEMORYREPORTER
     327             : 
     328             :   friend struct ::mozilla::WebAudioDecodeJob;
     329             : 
     330             :   nsTArray<MediaStream*> GetAllStreams() const;
     331             : 
     332             : private:
     333             :   // Each AudioContext has an id, that is passed down the MediaStreams that
     334             :   // back the AudioNodes, so we can easily compute the set of all the
     335             :   // MediaStreams for a given context, on the MediasStreamGraph side.
     336             :   const AudioContextId mId;
     337             :   // Note that it's important for mSampleRate to be initialized before
     338             :   // mDestination, as mDestination's constructor needs to access it!
     339             :   const float mSampleRate;
     340             :   AudioContextState mAudioContextState;
     341             :   RefPtr<AudioDestinationNode> mDestination;
     342             :   RefPtr<AudioListener> mListener;
     343             :   nsTArray<UniquePtr<WebAudioDecodeJob> > mDecodeJobs;
     344             :   // This array is used to keep the suspend/resume/close promises alive until
     345             :   // they are resolved, so we can safely pass them accross threads.
     346             :   nsTArray<RefPtr<Promise>> mPromiseGripArray;
     347             :   // See RegisterActiveNode.  These will keep the AudioContext alive while it
     348             :   // is rendering and the window remains alive.
     349             :   nsTHashtable<nsRefPtrHashKey<AudioNode> > mActiveNodes;
     350             :   // Raw (non-owning) references to all AudioNodes for this AudioContext.
     351             :   nsTHashtable<nsPtrHashKey<AudioNode> > mAllNodes;
     352             :   // Hashsets containing all the PannerNodes, to compute the doppler shift.
     353             :   // These are weak pointers.
     354             :   nsTHashtable<nsPtrHashKey<PannerNode> > mPannerNodes;
     355             :   // Cache to avoid recomputing basic waveforms all the time.
     356             :   RefPtr<BasicWaveFormCache> mBasicWaveFormCache;
     357             :   // Number of channels passed in the OfflineAudioContext ctor.
     358             :   uint32_t mNumberOfChannels;
     359             :   bool mIsOffline;
     360             :   bool mIsStarted;
     361             :   bool mIsShutDown;
     362             :   // Close has been called, reject suspend and resume call.
     363             :   bool mCloseCalled;
     364             :   // Suspend has been called with no following resume.
     365             :   bool mSuspendCalled;
     366             :   bool mIsDisconnecting;
     367             : };
     368             : 
     369             : static const dom::AudioContext::AudioContextId NO_AUDIO_CONTEXT = 0;
     370             : 
     371             : } // namespace dom
     372             : } // namespace mozilla
     373             : 
     374             : #endif
     375             : 

Generated by: LCOV version 1.13