LCOV - code coverage report
Current view: top level - dom/media - AudioBufferUtils.h (source / functions) Hit Total Coverage
Test: output.info Lines: 0 49 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 10 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 MOZILLA_SCRATCHBUFFER_H_
       7             : #define MOZILLA_SCRATCHBUFFER_H_
       8             : #include <mozilla/PodOperations.h>
       9             : #include <algorithm>
      10             : 
      11             : namespace mozilla {
      12             : 
      13             : /**
      14             :  * The classes in this file provide a interface that uses frames as a unit.
      15             :  * However, they store their offsets in samples (because it's handy for pointer
      16             :  * operations). Those functions can convert between the two units.
      17             :  */
      18           0 : static inline uint32_t FramesToSamples(uint32_t aChannels, uint32_t aFrames) {
      19           0 :   return aFrames * aChannels;
      20             : }
      21             : 
      22           0 : static inline uint32_t SamplesToFrames(uint32_t aChannels, uint32_t aSamples) {
      23           0 :   MOZ_ASSERT(!(aSamples % aChannels), "Frame alignment is wrong.");
      24           0 :   return aSamples / aChannels;
      25             : }
      26             : 
      27             : /**
      28             :  * Class that gets a buffer pointer from an audio callback and provides a safe
      29             :  * interface to manipulate this buffer, and to ensure we are not missing frames
      30             :  * by the end of the callback.
      31             :  */
      32             : template<typename T, uint32_t CHANNELS>
      33             : class AudioCallbackBufferWrapper
      34             : {
      35             : public:
      36           0 :   AudioCallbackBufferWrapper()
      37             :     : mBuffer(nullptr),
      38             :       mSamples(0),
      39           0 :       mSampleWriteOffset(1)
      40           0 :   {}
      41             :   /**
      42             :    * Set the buffer in this wrapper. This is to be called at the beginning of
      43             :    * the callback.
      44             :    */
      45           0 :   void SetBuffer(T* aBuffer, uint32_t aFrames) {
      46           0 :     MOZ_ASSERT(!mBuffer && !mSamples,
      47             :         "SetBuffer called twice.");
      48           0 :     mBuffer = aBuffer;
      49           0 :     mSamples = FramesToSamples(CHANNELS, aFrames);
      50           0 :     mSampleWriteOffset = 0;
      51           0 :   }
      52             : 
      53             :   /**
      54             :    * Write some frames to the internal buffer. Free space in the buffer should
      55             :    * be check prior to calling this.
      56             :    */
      57           0 :   void WriteFrames(T* aBuffer, uint32_t aFrames) {
      58           0 :     MOZ_ASSERT(aFrames <= Available(),
      59             :         "Writing more that we can in the audio buffer.");
      60             : 
      61           0 :     PodCopy(mBuffer + mSampleWriteOffset, aBuffer, FramesToSamples(CHANNELS,
      62             :                                                                    aFrames));
      63           0 :     mSampleWriteOffset += FramesToSamples(CHANNELS, aFrames);
      64           0 :   }
      65             : 
      66             :   /**
      67             :    * Number of frames that can be written to the buffer.
      68             :    */
      69           0 :   uint32_t Available() {
      70           0 :     return SamplesToFrames(CHANNELS, mSamples - mSampleWriteOffset);
      71             :   }
      72             : 
      73             :   /**
      74             :    * Check that the buffer is completly filled, and reset internal state so this
      75             :    * instance can be reused.
      76             :    */
      77           0 :   void BufferFilled() {
      78             :     // It's okay to have exactly zero samples here, it can happen we have an
      79             :     // audio callback driver because of a hint on MSG creation, but the
      80             :     // AudioOutputStream has not been created yet, or if all the streams have finished
      81             :     // but we're still running.
      82             :     // Note: it's also ok if we had data in the scratch buffer - and we usually do - and
      83             :     // all the streams were ended (no mixer callback occured).
      84             :     // XXX Remove this warning, or find a way to avoid it if the mixer callback
      85             :     // isn't called.
      86           0 :     NS_WARNING_ASSERTION(
      87             :       Available() == 0 || mSampleWriteOffset == 0,
      88             :       "Audio Buffer is not full by the end of the callback.");
      89             :     // Make sure the data returned is always set and not random!
      90           0 :     if (Available()) {
      91           0 :       PodZero(mBuffer + mSampleWriteOffset, FramesToSamples(CHANNELS, Available()));
      92             :     }
      93           0 :     MOZ_ASSERT(mSamples, "Buffer not set.");
      94           0 :     mSamples = 0;
      95           0 :     mSampleWriteOffset = 0;
      96           0 :     mBuffer = nullptr;
      97           0 :   }
      98             : 
      99             : private:
     100             :   /* This is not an owned pointer, but the pointer passed to use via the audio
     101             :    * callback. */
     102             :   T* mBuffer;
     103             :   /* The number of samples of this audio buffer. */
     104             :   uint32_t mSamples;
     105             :   /* The position at which new samples should be written. We want to return to
     106             :    * the audio callback iff this is equal to mSamples. */
     107             :   uint32_t mSampleWriteOffset;
     108             : };
     109             : 
     110             : /**
     111             :  * This is a class that interfaces with the AudioCallbackBufferWrapper, and is
     112             :  * responsible for storing the excess of data produced by the MediaStreamGraph
     113             :  * because of different rounding constraints, to be used the next time the audio
     114             :  * backend calls back.
     115             :  */
     116             : template<typename T, uint32_t BLOCK_SIZE, uint32_t CHANNELS>
     117             : class SpillBuffer
     118             : {
     119             : public:
     120           0 :   SpillBuffer()
     121           0 :   : mPosition(0)
     122             :   {
     123           0 :     PodArrayZero(mBuffer);
     124           0 :   }
     125             :   /* Empty the spill buffer into the buffer of the audio callback. This returns
     126             :    * the number of frames written. */
     127           0 :   uint32_t Empty(AudioCallbackBufferWrapper<T, CHANNELS>& aBuffer) {
     128           0 :     uint32_t framesToWrite = std::min(aBuffer.Available(),
     129           0 :                                       SamplesToFrames(CHANNELS, mPosition));
     130             : 
     131           0 :     aBuffer.WriteFrames(mBuffer, framesToWrite);
     132             : 
     133           0 :     mPosition -= FramesToSamples(CHANNELS, framesToWrite);
     134             :     // If we didn't empty the spill buffer for some reason, shift the remaining data down
     135           0 :     if (mPosition > 0) {
     136           0 :       PodMove(mBuffer, mBuffer + FramesToSamples(CHANNELS, framesToWrite),
     137           0 :               mPosition);
     138             :     }
     139             : 
     140           0 :     return framesToWrite;
     141             :   }
     142             :   /* Fill the spill buffer from aInput, containing aFrames frames, return the
     143             :    * number of frames written to the spill buffer */
     144           0 :   uint32_t Fill(T* aInput, uint32_t aFrames) {
     145             :     uint32_t framesToWrite = std::min(aFrames,
     146           0 :                                       BLOCK_SIZE - SamplesToFrames(CHANNELS,
     147           0 :                                                                    mPosition));
     148             : 
     149           0 :     PodCopy(mBuffer + mPosition, aInput, FramesToSamples(CHANNELS,
     150             :                                                          framesToWrite));
     151             : 
     152           0 :     mPosition += FramesToSamples(CHANNELS, framesToWrite);
     153             : 
     154           0 :     return framesToWrite;
     155             :   }
     156             : private:
     157             :   /* The spilled data. */
     158             :   T mBuffer[BLOCK_SIZE * CHANNELS];
     159             :   /* The current write position, in samples, in the buffer when filling, or the
     160             :    * amount of buffer filled when emptying. */
     161             :   uint32_t mPosition;
     162             : };
     163             : 
     164             : } // namespace mozilla
     165             : 
     166             : #endif // MOZILLA_SCRATCHBUFFER_H_

Generated by: LCOV version 1.13