LCOV - code coverage report
Current view: top level - dom/media - GraphDriver.h (source / functions) Hit Total Coverage
Test: output.info Lines: 0 42 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 25 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             : /* This Source Code Form is subject to the terms of the Mozilla Public
       3             :  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
       4             :  * You can obtain one at http://mozilla.org/MPL/2.0/. */
       5             : 
       6             : #ifndef GRAPHDRIVER_H_
       7             : #define GRAPHDRIVER_H_
       8             : 
       9             : #include "nsAutoRef.h"
      10             : #include "AudioBufferUtils.h"
      11             : #include "AudioMixer.h"
      12             : #include "AudioSegment.h"
      13             : #include "SelfRef.h"
      14             : #include "mozilla/Atomics.h"
      15             : #include "mozilla/SharedThreadPool.h"
      16             : #include "mozilla/StaticPtr.h"
      17             : 
      18             : struct cubeb_stream;
      19             : 
      20             : template <>
      21           0 : class nsAutoRefTraits<cubeb_stream> : public nsPointerRefTraits<cubeb_stream>
      22             : {
      23             : public:
      24           0 :   static void Release(cubeb_stream* aStream) { cubeb_stream_destroy(aStream); }
      25             : };
      26             : 
      27             : namespace mozilla {
      28             : 
      29             : /**
      30             :  * Assume we can run an iteration of the MediaStreamGraph loop in this much time
      31             :  * or less.
      32             :  * We try to run the control loop at this rate.
      33             :  */
      34             : static const int MEDIA_GRAPH_TARGET_PERIOD_MS = 10;
      35             : 
      36             : /**
      37             :  * Assume that we might miss our scheduled wakeup of the MediaStreamGraph by
      38             :  * this much.
      39             :  */
      40             : static const int SCHEDULE_SAFETY_MARGIN_MS = 10;
      41             : 
      42             : /**
      43             :  * Try have this much audio buffered in streams and queued to the hardware.
      44             :  * The maximum delay to the end of the next control loop
      45             :  * is 2*MEDIA_GRAPH_TARGET_PERIOD_MS + SCHEDULE_SAFETY_MARGIN_MS.
      46             :  * There is no point in buffering more audio than this in a stream at any
      47             :  * given time (until we add processing).
      48             :  * This is not optimal yet.
      49             :  */
      50             : static const int AUDIO_TARGET_MS = 2*MEDIA_GRAPH_TARGET_PERIOD_MS +
      51             :     SCHEDULE_SAFETY_MARGIN_MS;
      52             : 
      53             : class MediaStreamGraphImpl;
      54             : 
      55             : class AudioCallbackDriver;
      56             : class OfflineClockDriver;
      57             : class SystemClockDriver;
      58             : 
      59             : /**
      60             :  * A driver is responsible for the scheduling of the processing, the thread
      61             :  * management, and give the different clocks to a MediaStreamGraph. This is an
      62             :  * abstract base class. A MediaStreamGraph can be driven by an
      63             :  * OfflineClockDriver, if the graph is offline, or a SystemClockDriver, if the
      64             :  * graph is real time.
      65             :  * A MediaStreamGraph holds an owning reference to its driver.
      66             :  *
      67             :  * The lifetime of drivers is a complicated affair. Here are the different
      68             :  * scenarii that can happen:
      69             :  *
      70             :  * Starting a MediaStreamGraph with an AudioCallbackDriver
      71             :  * - A new thread T is created, from the main thread.
      72             :  * - On this thread T, cubeb is initialized if needed, and a cubeb_stream is
      73             :  *   created and started
      74             :  * - The thread T posts a message to the main thread to terminate itself.
      75             :  * - The graph runs off the audio thread
      76             :  *
      77             :  * Starting a MediaStreamGraph with a SystemClockDriver:
      78             :  * - A new thread T is created from the main thread.
      79             :  * - The graph runs off this thread.
      80             :  *
      81             :  * Switching from a SystemClockDriver to an AudioCallbackDriver:
      82             :  * - A new AudioCallabackDriver is created and initialized on the graph thread
      83             :  * - At the end of the MSG iteration, the SystemClockDriver transfers its timing
      84             :  *   info and a reference to itself to the AudioCallbackDriver. It then starts
      85             :  *   the AudioCallbackDriver.
      86             :  * - When the AudioCallbackDriver starts, it checks if it has been switched from
      87             :  *   a SystemClockDriver, and if that is the case, sends a message to the main
      88             :  *   thread to shut the SystemClockDriver thread down.
      89             :  * - The graph now runs off an audio callback
      90             :  *
      91             :  * Switching from an AudioCallbackDriver to a SystemClockDriver:
      92             :  * - A new SystemClockDriver is created, and set as mNextDriver.
      93             :  * - At the end of the MSG iteration, the AudioCallbackDriver transfers its
      94             :  *   timing info and a reference to itself to the SystemClockDriver. A new
      95             :  *   SystemClockDriver is started from the current audio thread.
      96             :  * - When starting, the SystemClockDriver checks if it has been switched from an
      97             :  *   AudioCallbackDriver. If yes, it creates a new temporary thread to release
      98             :  *   the cubeb_streams. This temporary thread closes the cubeb_stream, and
      99             :  *   then dispatches a message to the main thread to be terminated.
     100             :  * - The graph now runs off a normal thread.
     101             :  *
     102             :  * Two drivers cannot run at the same time for the same graph. The thread safety
     103             :  * of the different attributes of drivers, and they access pattern is documented
     104             :  * next to the members themselves.
     105             :  *
     106             :  */
     107             : class GraphDriver
     108             : {
     109             : public:
     110             :   explicit GraphDriver(MediaStreamGraphImpl* aGraphImpl);
     111             : 
     112           0 :   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(GraphDriver);
     113             :   /* For real-time graphs, this waits until it's time to process more data. For
     114             :    * offline graphs, this is a no-op. */
     115             :   virtual void WaitForNextIteration() = 0;
     116             :   /* Wakes up the graph if it is waiting. */
     117             :   virtual void WakeUp() = 0;
     118           0 :   virtual void Destroy() {}
     119             :   /* Start the graph, init the driver, start the thread. */
     120             :   virtual void Start() = 0;
     121             :   /* Stop the graph, shutting down the thread. */
     122             :   virtual void Stop() = 0;
     123             :   /* Resume after a stop */
     124             :   virtual void Resume() = 0;
     125             :   /* Revive this driver, as more messages just arrived. */
     126             :   virtual void Revive() = 0;
     127             :   /* Remove Mixer callbacks when switching */
     128             :   virtual void RemoveCallback() = 0;
     129             :   /* Shutdown GraphDriver (synchronously) */
     130             :   void Shutdown();
     131             :   /* Rate at which the GraphDriver runs, in ms. This can either be user
     132             :    * controlled (because we are using a {System,Offline}ClockDriver, and decide
     133             :    * how often we want to wakeup/how much we want to process per iteration), or
     134             :    * it can be indirectly set by the latency of the audio backend, and the
     135             :    * number of buffers of this audio backend: say we have four buffers, and 40ms
     136             :    * latency, we will get a callback approximately every 10ms. */
     137             :   virtual uint32_t IterationDuration() = 0;
     138             : 
     139             :   /* Return whether we are switching or not. */
     140             :   bool Switching();
     141             : 
     142             :   // Those are simply or setting the associated pointer, but assert that the
     143             :   // lock is held.
     144             :   GraphDriver* NextDriver();
     145             :   GraphDriver* PreviousDriver();
     146             :   void SetNextDriver(GraphDriver* aNextDriver);
     147             :   void SetPreviousDriver(GraphDriver* aPreviousDriver);
     148             : 
     149             :   /**
     150             :    * If we are running a real time graph, get the current time stamp to schedule
     151             :    * video frames. This has to be reimplemented by real time drivers.
     152             :    */
     153           0 :   virtual TimeStamp GetCurrentTimeStamp() {
     154           0 :     return mCurrentTimeStamp;
     155             :   }
     156             : 
     157           0 :   GraphTime IterationEnd() {
     158           0 :     return mIterationEnd;
     159             :   }
     160             : 
     161           0 :   virtual AudioCallbackDriver* AsAudioCallbackDriver() {
     162           0 :     return nullptr;
     163             :   }
     164             : 
     165           0 :   virtual OfflineClockDriver* AsOfflineClockDriver() {
     166           0 :     return nullptr;
     167             :   }
     168             : 
     169           0 :   virtual SystemClockDriver* AsSystemClockDriver() {
     170           0 :     return nullptr;
     171             :   }
     172             : 
     173             :   /**
     174             :    * Tell the driver it has to stop and return the current time of the graph, so
     175             :    * another driver can start from the right point in time.
     176             :    */
     177             :   virtual void SwitchAtNextIteration(GraphDriver* aDriver);
     178             : 
     179             :   /**
     180             :    * Set the time for a graph, on a driver. This is used so a new driver just
     181             :    * created can start at the right point in time.
     182             :    */
     183             :   void SetGraphTime(GraphDriver* aPreviousDriver,
     184             :                     GraphTime aLastSwitchNextIterationStart,
     185             :                     GraphTime aLastSwitchNextIterationEnd);
     186             :   /**
     187             :    * Call this to indicate that another iteration of the control loop is
     188             :    * required on its regular schedule. The monitor must not be held.
     189             :    * This function has to be idempotent.
     190             :    */
     191             :   void EnsureNextIteration();
     192             : 
     193             :   /**
     194             :    * Same thing, but not locked.
     195             :    */
     196             :   void EnsureNextIterationLocked();
     197             : 
     198           0 :   MediaStreamGraphImpl* GraphImpl() {
     199           0 :     return mGraphImpl;
     200             :   }
     201             : 
     202             :   virtual bool OnThread() = 0;
     203             : 
     204             : protected:
     205             :   GraphTime StateComputedTime() const;
     206             : 
     207             :   // Time of the start of this graph iteration. This must be accessed while
     208             :   // having the monitor.
     209             :   GraphTime mIterationStart;
     210             :   // Time of the end of this graph iteration. This must be accessed while having
     211             :   // the monitor.
     212             :   GraphTime mIterationEnd;
     213             :   // The MediaStreamGraphImpl that owns this driver. This has a lifetime longer
     214             :   // than the driver, and will never be null. Hence, it can be accesed without
     215             :   // monitor.
     216             :   MediaStreamGraphImpl* mGraphImpl;
     217             : 
     218             :   // This enum specifies the wait state of the driver.
     219             :   enum WaitState {
     220             :     // RunThread() is running normally
     221             :     WAITSTATE_RUNNING,
     222             :     // RunThread() is paused waiting for its next iteration, which will
     223             :     // happen soon
     224             :     WAITSTATE_WAITING_FOR_NEXT_ITERATION,
     225             :     // RunThread() is paused indefinitely waiting for something to change
     226             :     WAITSTATE_WAITING_INDEFINITELY,
     227             :     // Something has signaled RunThread() to wake up immediately,
     228             :     // but it hasn't done so yet
     229             :     WAITSTATE_WAKING_UP
     230             :   };
     231             :   // This must be access with the monitor.
     232             :   WaitState mWaitState;
     233             : 
     234             :   // This is used on the main thread (during initialization), and the graph
     235             :   // thread. No monitor needed because we know the graph thread does not run
     236             :   // during the initialization.
     237             :   TimeStamp mCurrentTimeStamp;
     238             :   // This is non-null only when this driver has recently switched from an other
     239             :   // driver, and has not cleaned it up yet (for example because the audio stream
     240             :   // is currently calling the callback during initialization).
     241             :   //
     242             :   // This is written to when changing driver, from the previous driver's thread,
     243             :   // or a thread created for the occasion. This is read each time we need to
     244             :   // check whether we're changing driver (in Switching()), from the graph
     245             :   // thread.
     246             :   // This must be accessed using the {Set,Get}PreviousDriver methods.
     247             :   RefPtr<GraphDriver> mPreviousDriver;
     248             :   // This is non-null only when this driver is going to switch to an other
     249             :   // driver at the end of this iteration.
     250             :   // This must be accessed using the {Set,Get}NextDriver methods.
     251             :   RefPtr<GraphDriver> mNextDriver;
     252           0 :   virtual ~GraphDriver()
     253           0 :   { }
     254             : };
     255             : 
     256             : class MediaStreamGraphInitThreadRunnable;
     257             : 
     258             : /**
     259             :  * This class is a driver that manages its own thread.
     260             :  */
     261             : class ThreadedDriver : public GraphDriver
     262             : {
     263             : public:
     264             :   explicit ThreadedDriver(MediaStreamGraphImpl* aGraphImpl);
     265             :   virtual ~ThreadedDriver();
     266             :   void Start() override;
     267             :   void Stop() override;
     268             :   void Resume() override;
     269             :   void Revive() override;
     270             :   void RemoveCallback() override;
     271             :   /**
     272             :    * Runs main control loop on the graph thread. Normally a single invocation
     273             :    * of this runs for the entire lifetime of the graph thread.
     274             :    */
     275             :   void RunThread();
     276             :   friend class MediaStreamGraphInitThreadRunnable;
     277           0 :   uint32_t IterationDuration() override {
     278           0 :     return MEDIA_GRAPH_TARGET_PERIOD_MS;
     279             :   }
     280             : 
     281           0 :   bool OnThread() override { return !mThread || mThread->EventTarget()->IsOnCurrentThread(); }
     282             : 
     283             :   /* When the graph wakes up to do an iteration, implementations return the
     284             :    * range of time that will be processed.  This is called only once per
     285             :    * iteration; it may determine the interval from state in a previous
     286             :    * call. */
     287             :   virtual MediaTime GetIntervalForIteration() = 0;
     288             : protected:
     289             :   nsCOMPtr<nsIThread> mThread;
     290             : };
     291             : 
     292             : /**
     293             :  * A SystemClockDriver drives a MediaStreamGraph using a system clock, and waits
     294             :  * using a monitor, between each iteration.
     295             :  */
     296             : class SystemClockDriver : public ThreadedDriver
     297             : {
     298             : public:
     299             :   explicit SystemClockDriver(MediaStreamGraphImpl* aGraphImpl);
     300             :   virtual ~SystemClockDriver();
     301             :   MediaTime GetIntervalForIteration() override;
     302             :   void WaitForNextIteration() override;
     303             :   void WakeUp() override;
     304             :   void MarkAsFallback();
     305             :   bool IsFallback();
     306           0 :   SystemClockDriver* AsSystemClockDriver() override {
     307           0 :     return this;
     308             :   }
     309             : 
     310             : private:
     311             :   // Those are only modified (after initialization) on the graph thread. The
     312             :   // graph thread does not run during the initialization.
     313             :   TimeStamp mInitialTimeStamp;
     314             :   TimeStamp mLastTimeStamp;
     315             :   // This is true if this SystemClockDriver runs the graph because we could not
     316             :   // open an audio stream.
     317             :   bool mIsFallback;
     318             : };
     319             : 
     320             : /**
     321             :  * An OfflineClockDriver runs the graph as fast as possible, without waiting
     322             :  * between iteration.
     323             :  */
     324             : class OfflineClockDriver : public ThreadedDriver
     325             : {
     326             : public:
     327             :   OfflineClockDriver(MediaStreamGraphImpl* aGraphImpl, GraphTime aSlice);
     328             :   virtual ~OfflineClockDriver();
     329             :   MediaTime GetIntervalForIteration() override;
     330             :   void WaitForNextIteration() override;
     331             :   void WakeUp() override;
     332             :   TimeStamp GetCurrentTimeStamp() override;
     333           0 :   OfflineClockDriver* AsOfflineClockDriver() override {
     334           0 :     return this;
     335             :   }
     336             : 
     337             : private:
     338             :   // Time, in GraphTime, for each iteration
     339             :   GraphTime mSlice;
     340             : };
     341             : 
     342           0 : struct StreamAndPromiseForOperation
     343             : {
     344             :   StreamAndPromiseForOperation(MediaStream* aStream,
     345             :                                void* aPromise,
     346             :                                dom::AudioContextOperation aOperation);
     347             :   RefPtr<MediaStream> mStream;
     348             :   void* mPromise;
     349             :   dom::AudioContextOperation mOperation;
     350             : };
     351             : 
     352             : enum AsyncCubebOperation {
     353             :   INIT,
     354             :   SHUTDOWN
     355             : };
     356             : 
     357             : /**
     358             :  * This is a graph driver that is based on callback functions called by the
     359             :  * audio api. This ensures minimal audio latency, because it means there is no
     360             :  * buffering happening: the audio is generated inside the callback.
     361             :  *
     362             :  * This design is less flexible than running our own thread:
     363             :  * - We have no control over the thread:
     364             :  * - It cannot block, and it has to run for a shorter amount of time than the
     365             :  *   buffer it is going to fill, or an under-run is going to occur (short burst
     366             :  *   of silence in the final audio output).
     367             :  * - We can't know for sure when the callback function is going to be called
     368             :  *   (although we compute an estimation so we can schedule video frames)
     369             :  * - Creating and shutting the thread down is a blocking operation, that can
     370             :  *   take _seconds_ in some cases (because IPC has to be set up, and
     371             :  *   sometimes hardware components are involved and need to be warmed up)
     372             :  * - We have no control on how much audio we generate, we have to return exactly
     373             :  *   the number of frames asked for by the callback. Since for the Web Audio
     374             :  *   API, we have to do block processing at 128 frames per block, we need to
     375             :  *   keep a little spill buffer to store the extra frames.
     376             :  */
     377             : class AudioCallbackDriver : public GraphDriver,
     378             :                             public MixerCallbackReceiver
     379             : {
     380             : public:
     381             :   explicit AudioCallbackDriver(MediaStreamGraphImpl* aGraphImpl);
     382             :   virtual ~AudioCallbackDriver();
     383             : 
     384             :   void Destroy() override;
     385             :   void Start() override;
     386             :   void Stop() override;
     387             :   void Resume() override;
     388             :   void Revive() override;
     389             :   void RemoveCallback() override;
     390             :   void WaitForNextIteration() override;
     391             :   void WakeUp() override;
     392             : 
     393             :   /* Static wrapper function cubeb calls back. */
     394             :   static long DataCallback_s(cubeb_stream * aStream,
     395             :                              void * aUser,
     396             :                              const void * aInputBuffer,
     397             :                              void * aOutputBuffer,
     398             :                              long aFrames);
     399             :   static void StateCallback_s(cubeb_stream* aStream, void * aUser,
     400             :                               cubeb_state aState);
     401             :   static void DeviceChangedCallback_s(void * aUser);
     402             :   /* This function is called by the underlying audio backend when a refill is
     403             :    * needed. This is what drives the whole graph when it is used to output
     404             :    * audio. If the return value is exactly aFrames, this function will get
     405             :    * called again. If it is less than aFrames, the stream will go in draining
     406             :    * mode, and this function will not be called again. */
     407             :   long DataCallback(const AudioDataValue* aInputBuffer, AudioDataValue* aOutputBuffer, long aFrames);
     408             :   /* This function is called by the underlying audio backend, but is only used
     409             :    * for informational purposes at the moment. */
     410             :   void StateCallback(cubeb_state aState);
     411             :   /* This is an approximation of the number of millisecond there are between two
     412             :    * iterations of the graph. */
     413             :   uint32_t IterationDuration() override;
     414             : 
     415             :   /* This function gets called when the graph has produced the audio frames for
     416             :    * this iteration. */
     417             :   void MixerCallback(AudioDataValue* aMixedBuffer,
     418             :                      AudioSampleFormat aFormat,
     419             :                      uint32_t aChannels,
     420             :                      uint32_t aFrames,
     421             :                      uint32_t aSampleRate) override;
     422             : 
     423             :   // These are invoked on the MSG thread (we don't call this if not LIFECYCLE_RUNNING)
     424           0 :   virtual void SetInputListener(AudioDataListener *aListener) {
     425           0 :     MOZ_ASSERT(OnThread());
     426           0 :     mAudioInput = aListener;
     427           0 :   }
     428             :   // XXX do we need the param?  probably no
     429           0 :   virtual void RemoveInputListener(AudioDataListener *aListener) {
     430           0 :     MOZ_ASSERT(OnThread());
     431           0 :     mAudioInput = nullptr;
     432           0 :   }
     433             : 
     434           0 :   AudioCallbackDriver* AsAudioCallbackDriver() override {
     435           0 :     return this;
     436             :   }
     437             : 
     438             :   /* Enqueue a promise that is going to be resolved when a specific operation
     439             :    * occurs on the cubeb stream. */
     440             :   void EnqueueStreamAndPromiseForOperation(MediaStream* aStream,
     441             :                                          void* aPromise,
     442             :                                          dom::AudioContextOperation aOperation);
     443             : 
     444             :   /**
     445             :    * Whether the audio callback is processing. This is for asserting only.
     446             :    */
     447             :   bool InCallback();
     448             : 
     449           0 :   bool OnThread() override { return !mStarted || InCallback(); }
     450             : 
     451             :   /* Whether the underlying cubeb stream has been started. See comment for
     452             :    * mStarted for details. */
     453             :   bool IsStarted();
     454             : 
     455             :   /* Tell the driver whether this process is using a microphone or not. This is
     456             :    * thread safe. */
     457             :   void SetMicrophoneActive(bool aActive);
     458             : 
     459             :   void CompleteAudioContextOperations(AsyncCubebOperation aOperation);
     460             : private:
     461             :   /**
     462             :    * On certain MacBookPro, the microphone is located near the left speaker.
     463             :    * We need to pan the sound output to the right speaker if we are using the
     464             :    * mic and the built-in speaker, or we will have terrible echo.  */
     465             :   void PanOutputIfNeeded(bool aMicrophoneActive);
     466             :   /**
     467             :    * This is called when the output device used by the cubeb stream changes. */
     468             :   void DeviceChangedCallback();
     469             :   /* Start the cubeb stream */
     470             :   bool StartStream();
     471             :   friend class AsyncCubebTask;
     472             :   bool Init();
     473             :   /* MediaStreamGraphs are always down/up mixed to stereo for now. */
     474             :   static const uint32_t ChannelCount = 2;
     475             :   /* The size of this buffer comes from the fact that some audio backends can
     476             :    * call back with a number of frames lower than one block (128 frames), so we
     477             :    * need to keep at most two block in the SpillBuffer, because we always round
     478             :    * up to block boundaries during an iteration.
     479             :    * This is only ever accessed on the audio callback thread. */
     480             :   SpillBuffer<AudioDataValue, WEBAUDIO_BLOCK_SIZE * 2, ChannelCount> mScratchBuffer;
     481             :   /* Wrapper to ensure we write exactly the number of frames we need in the
     482             :    * audio buffer cubeb passes us. This is only ever accessed on the audio
     483             :    * callback thread. */
     484             :   AudioCallbackBufferWrapper<AudioDataValue, ChannelCount> mBuffer;
     485             :   /* cubeb stream for this graph. This is guaranteed to be non-null after Init()
     486             :    * has been called, and is synchronized internaly. */
     487             :   nsAutoRef<cubeb_stream> mAudioStream;
     488             :   /* The sample rate for the aforementionned cubeb stream. This is set on
     489             :    * initialization and can be read safely afterwards. */
     490             :   uint32_t mSampleRate;
     491             :   /* The number of input channels from cubeb.  Should be set before opening cubeb
     492             :    * and then be static. */
     493             :   uint32_t mInputChannels;
     494             :   /* Approximation of the time between two callbacks. This is used to schedule
     495             :    * video frames. This is in milliseconds. Only even used (after
     496             :    * inizatialization) on the audio callback thread. */
     497             :   uint32_t mIterationDurationMS;
     498             :   /* cubeb_stream_init calls the audio callback to prefill the buffers. The
     499             :    * previous driver has to be kept alive until the audio stream has been
     500             :    * started, because it is responsible to call cubeb_stream_start, so we delay
     501             :    * the cleanup of the previous driver until it has started the audio stream.
     502             :    * Otherwise, there is a race where we kill the previous driver thread
     503             :    * between cubeb_stream_init and cubeb_stream_start,
     504             :    * and callbacks after the prefill never get called.
     505             :    * This is written on the previous driver's thread (if switching) or main
     506             :    * thread (if this driver is the first one).
     507             :    * This is read on previous driver's thread (during callbacks from
     508             :    * cubeb_stream_init) and the audio thread (when switching away from this
     509             :    * driver back to a SystemClockDriver).
     510             :    * This is synchronized by the Graph's monitor.
     511             :    * */
     512             :   bool mStarted;
     513             :   /* Listener for mic input, if any. */
     514             :   RefPtr<AudioDataListener> mAudioInput;
     515             : 
     516             :   struct AutoInCallback
     517             :   {
     518             :     explicit AutoInCallback(AudioCallbackDriver* aDriver);
     519             :     ~AutoInCallback();
     520             :     AudioCallbackDriver* mDriver;
     521             :   };
     522             : 
     523             :   /* Thread for off-main-thread initialization and
     524             :    * shutdown of the audio stream. */
     525             :   nsCOMPtr<nsIThread> mInitShutdownThread;
     526             :   /* This must be accessed with the graph monitor held. */
     527             :   AutoTArray<StreamAndPromiseForOperation, 1> mPromisesForOperation;
     528             :   /* This is set during initialization, and can be read safely afterwards. */
     529             :   dom::AudioChannel mAudioChannel;
     530             :   /* Used to queue us to add the mixer callback on first run. */
     531             :   bool mAddedMixer;
     532             : 
     533             :   /* This is atomic and is set by the audio callback thread. It can be read by
     534             :    * any thread safely. */
     535             :   Atomic<bool> mInCallback;
     536             :   /**
     537             :    * True if microphone is being used by this process. This is synchronized by
     538             :    * the graph's monitor. */
     539             :   Atomic<bool> mMicrophoneActive;
     540             :   /* True if this driver was created from a driver created because of a previous
     541             :    * AudioCallbackDriver failure. */
     542             :   bool mFromFallback;
     543             : };
     544             : 
     545             : class AsyncCubebTask : public Runnable
     546             : {
     547             : public:
     548             : 
     549             :   AsyncCubebTask(AudioCallbackDriver* aDriver, AsyncCubebOperation aOperation);
     550             : 
     551           0 :   nsresult Dispatch(uint32_t aFlags = NS_DISPATCH_NORMAL)
     552             :   {
     553           0 :     nsresult rv = EnsureThread();
     554           0 :     if (!NS_FAILED(rv)) {
     555           0 :       rv = sThreadPool->Dispatch(this, aFlags);
     556             :     }
     557           0 :     return rv;
     558             :   }
     559             : 
     560             : protected:
     561             :   virtual ~AsyncCubebTask();
     562             : 
     563             : private:
     564             :   static nsresult EnsureThread();
     565             : 
     566             :   NS_IMETHOD Run() override final;
     567             :   static StaticRefPtr<nsIThreadPool> sThreadPool;
     568             :   RefPtr<AudioCallbackDriver> mDriver;
     569             :   AsyncCubebOperation mOperation;
     570             :   RefPtr<MediaStreamGraphImpl> mShutdownGrip;
     571             : };
     572             : 
     573             : } // namespace mozilla
     574             : 
     575             : #endif // GRAPHDRIVER_H_

Generated by: LCOV version 1.13