LCOV - code coverage report
Current view: top level - dom/media/webaudio - AudioBlock.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 69 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 15 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             : #include "AudioBlock.h"
       8             : #include "AlignmentUtils.h"
       9             : 
      10             : namespace mozilla {
      11             : 
      12             : /**
      13             :  * Heap-allocated buffer of channels of 128-sample float arrays, with
      14             :  * threadsafe refcounting.  Typically you would allocate one of these, fill it
      15             :  * in, and then treat it as immutable while it's shared.
      16             :  *
      17             :  * Downstream references are accounted specially so that the creator of the
      18             :  * buffer can reuse and modify its contents next iteration if other references
      19             :  * are all downstream temporary references held by AudioBlock.
      20             :  *
      21             :  * We guarantee 16 byte alignment of the channel data.
      22             :  */
      23             : class AudioBlockBuffer final : public ThreadSharedObject {
      24             : public:
      25             : 
      26           0 :   virtual AudioBlockBuffer* AsAudioBlockBuffer() override { return this; };
      27             : 
      28           0 :   float* ChannelData(uint32_t aChannel)
      29             :   {
      30           0 :     float* base = reinterpret_cast<float*>(((uintptr_t)(this + 1) + 15) & ~0x0F);
      31           0 :     ASSERT_ALIGNED16(base);
      32           0 :     return base + aChannel * WEBAUDIO_BLOCK_SIZE;
      33             :   }
      34             : 
      35           0 :   static already_AddRefed<AudioBlockBuffer> Create(uint32_t aChannelCount)
      36             :   {
      37           0 :     CheckedInt<size_t> size = WEBAUDIO_BLOCK_SIZE;
      38           0 :     size *= aChannelCount;
      39           0 :     size *= sizeof(float);
      40           0 :     size += sizeof(AudioBlockBuffer);
      41           0 :     size += 15;  //padding for alignment
      42           0 :     if (!size.isValid()) {
      43           0 :       MOZ_CRASH();
      44             :     }
      45             : 
      46           0 :     void* m = moz_xmalloc(size.value());
      47           0 :     RefPtr<AudioBlockBuffer> p = new (m) AudioBlockBuffer();
      48           0 :     NS_ASSERTION((reinterpret_cast<char*>(p.get() + 1) - reinterpret_cast<char*>(p.get())) % 4 == 0,
      49             :                  "AudioBlockBuffers should be at least 4-byte aligned");
      50           0 :     return p.forget();
      51             :   }
      52             : 
      53             :   // Graph thread only.
      54           0 :   void DownstreamRefAdded() { ++mDownstreamRefCount; }
      55           0 :   void DownstreamRefRemoved() {
      56           0 :     MOZ_ASSERT(mDownstreamRefCount > 0);
      57           0 :     --mDownstreamRefCount;
      58           0 :   }
      59             :   // Whether this is shared by any owners that are not downstream.
      60             :   // Called only from owners with a reference that is not a downstream
      61             :   // reference.  Graph thread only.
      62           0 :   bool HasLastingShares()
      63             :   {
      64             :     // mRefCnt is atomic and so reading its value is defined even when
      65             :     // modifications may happen on other threads.  mDownstreamRefCount is
      66             :     // not modified on any other thread.
      67             :     //
      68             :     // If all other references are downstream references (managed on this, the
      69             :     // graph thread), then other threads are not using this buffer and cannot
      70             :     // add further references.  This method can safely return false.  The
      71             :     // buffer contents can be modified.
      72             :     //
      73             :     // If there are other references that are not downstream references, then
      74             :     // this method will return true.  The buffer will be assumed to be still
      75             :     // in use and so will not be reused.
      76           0 :     nsrefcnt count = mRefCnt;
      77             :     // This test is strictly less than because the caller has a reference
      78             :     // that is not a downstream reference.
      79           0 :     MOZ_ASSERT(mDownstreamRefCount < count);
      80           0 :     return count != mDownstreamRefCount + 1;
      81             :   }
      82             : 
      83           0 :   virtual size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const override
      84             :   {
      85           0 :     return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf);
      86             :   }
      87             : 
      88             : private:
      89           0 :   AudioBlockBuffer() {}
      90           0 :   ~AudioBlockBuffer() override { MOZ_ASSERT(mDownstreamRefCount == 0); }
      91             : 
      92             :   nsAutoRefCnt mDownstreamRefCount;
      93             : };
      94             : 
      95           0 : AudioBlock::~AudioBlock()
      96             : {
      97           0 :   ClearDownstreamMark();
      98           0 : }
      99             : 
     100             : void
     101           0 : AudioBlock::SetBuffer(ThreadSharedObject* aNewBuffer)
     102             : {
     103           0 :   if (aNewBuffer == mBuffer) {
     104           0 :     return;
     105             :   }
     106             : 
     107           0 :   ClearDownstreamMark();
     108             : 
     109           0 :   mBuffer = aNewBuffer;
     110             : 
     111           0 :   if (!aNewBuffer) {
     112           0 :     return;
     113             :   }
     114             : 
     115           0 :   AudioBlockBuffer* buffer = aNewBuffer->AsAudioBlockBuffer();
     116           0 :   if (buffer) {
     117           0 :     buffer->DownstreamRefAdded();
     118           0 :     mBufferIsDownstreamRef = true;
     119             :   }
     120             : }
     121             : 
     122             : void
     123           0 : AudioBlock::ClearDownstreamMark() {
     124           0 :   if (mBufferIsDownstreamRef) {
     125           0 :     mBuffer->AsAudioBlockBuffer()->DownstreamRefRemoved();
     126           0 :     mBufferIsDownstreamRef = false;
     127             :   }
     128           0 : }
     129             : 
     130             : bool
     131           0 : AudioBlock::CanWrite() {
     132             :   // If mBufferIsDownstreamRef is set then the buffer is not ours to use.
     133             :   // It may be in use by another node which is not downstream.
     134           0 :   return !mBufferIsDownstreamRef &&
     135           0 :     !mBuffer->AsAudioBlockBuffer()->HasLastingShares();
     136             : }
     137             : 
     138             : void
     139           0 : AudioBlock::AllocateChannels(uint32_t aChannelCount)
     140             : {
     141           0 :   MOZ_ASSERT(mDuration == WEBAUDIO_BLOCK_SIZE);
     142             : 
     143           0 :   if (mBufferIsDownstreamRef) {
     144             :     // This is not our buffer to re-use.
     145           0 :     ClearDownstreamMark();
     146           0 :   } else if (mBuffer && ChannelCount() == aChannelCount) {
     147           0 :     AudioBlockBuffer* buffer = mBuffer->AsAudioBlockBuffer();
     148           0 :     if (buffer && !buffer->HasLastingShares()) {
     149           0 :       MOZ_ASSERT(mBufferFormat == AUDIO_FORMAT_FLOAT32);
     150             :       // No need to allocate again.
     151           0 :       mVolume = 1.0f;
     152           0 :       return;
     153             :     }
     154             :   }
     155             : 
     156           0 :   RefPtr<AudioBlockBuffer> buffer = AudioBlockBuffer::Create(aChannelCount);
     157           0 :   mChannelData.SetLength(aChannelCount);
     158           0 :   for (uint32_t i = 0; i < aChannelCount; ++i) {
     159           0 :     mChannelData[i] = buffer->ChannelData(i);
     160             :   }
     161           0 :   mBuffer = buffer.forget();
     162           0 :   mVolume = 1.0f;
     163           0 :   mBufferFormat = AUDIO_FORMAT_FLOAT32;
     164             : }
     165             : 
     166             : } // namespace mozilla

Generated by: LCOV version 1.13