bug 1391482 generalize WebAudioDecodeJob buffer as AudioChunk r?padenot draft
authorKarl Tomlinson <karlt+@karlt.net>
Wed, 16 Aug 2017 18:10:06 +1200
changeset 654732 1f4e95b5ef0fcb10d3aed6ca023ee630882dd29c
parent 654731 6f22ae465560f477b6eafcb02cb1a61863590e99
child 654733 cc8f6e9008cbcb1994b45853582fc42ff36ac1c0
push id76658
push userktomlinson@mozilla.com
push dateTue, 29 Aug 2017 06:20:42 +0000
reviewerspadenot
bugs1391482
milestone57.0a1
bug 1391482 generalize WebAudioDecodeJob buffer as AudioChunk r?padenot MozReview-Commit-ID: 4H3F0SzAknc
dom/media/webaudio/MediaBufferDecoder.cpp
dom/media/webaudio/MediaBufferDecoder.h
--- a/dom/media/webaudio/MediaBufferDecoder.cpp
+++ b/dom/media/webaudio/MediaBufferDecoder.cpp
@@ -344,84 +344,94 @@ MediaDecodeTask::FinishDecode()
                                      destSampleRate,
                                      SPEEX_RESAMPLER_QUALITY_DEFAULT, nullptr);
     speex_resampler_skip_zeros(resampler);
     resampledFrames += speex_resampler_get_output_latency(resampler);
   }
 
   // Allocate the channel buffers.  Note that if we end up resampling, we may
   // write fewer bytes than mResampledFrames to the output buffer, in which
-  // case mWriteIndex will tell us how many valid samples we have.
-  mDecodeJob.mBuffer = ThreadSharedFloatArrayBufferList::
+  // case writeIndex will tell us how many valid samples we have.
+  RefPtr<ThreadSharedFloatArrayBufferList> buffer =
+    ThreadSharedFloatArrayBufferList::
     Create(channelCount, resampledFrames, fallible);
-  if (!mDecodeJob.mBuffer) {
+  if (!buffer) {
     ReportFailureOnMainThread(WebAudioDecodeJob::UnknownError);
     return;
   }
+  mDecodeJob.mBuffer.mChannelData.SetLength(channelCount);
+  for (uint32_t i = 0; i < channelCount; ++i) {
+    mDecodeJob.mBuffer.mChannelData[i] = buffer->GetData(i);
+  }
+  mDecodeJob.mBuffer.mBuffer = buffer.forget();
+  mDecodeJob.mBuffer.mVolume = 1.0f;
+  mDecodeJob.mBuffer.mBufferFormat = AUDIO_FORMAT_FLOAT32;
 
+  uint32_t writeIndex = 0;
   RefPtr<AudioData> audioData;
   while ((audioData = mAudioQueue.PopFront())) {
     audioData->EnsureAudioBuffer(); // could lead to a copy :(
     AudioDataValue* bufferData = static_cast<AudioDataValue*>
       (audioData->mAudioBuffer->Data());
 
     if (sampleRate != destSampleRate) {
-      const uint32_t maxOutSamples = resampledFrames - mDecodeJob.mWriteIndex;
+      const uint32_t maxOutSamples = resampledFrames - writeIndex;
 
       for (uint32_t i = 0; i < audioData->mChannels; ++i) {
         uint32_t inSamples = audioData->mFrames;
         uint32_t outSamples = maxOutSamples;
         float* outData =
-          mDecodeJob.mBuffer->GetDataForWrite(i) + mDecodeJob.mWriteIndex;
+          mDecodeJob.mBuffer.ChannelDataForWrite<float>(i) + writeIndex;
 
         WebAudioUtils::SpeexResamplerProcess(
             resampler, i, &bufferData[i * audioData->mFrames], &inSamples,
             outData, &outSamples);
 
         if (i == audioData->mChannels - 1) {
-          mDecodeJob.mWriteIndex += outSamples;
-          MOZ_ASSERT(mDecodeJob.mWriteIndex <= resampledFrames);
+          writeIndex += outSamples;
+          MOZ_ASSERT(writeIndex <= resampledFrames);
           MOZ_ASSERT(inSamples == audioData->mFrames);
         }
       }
     } else {
       for (uint32_t i = 0; i < audioData->mChannels; ++i) {
         float* outData =
-          mDecodeJob.mBuffer->GetDataForWrite(i) + mDecodeJob.mWriteIndex;
+          mDecodeJob.mBuffer.ChannelDataForWrite<float>(i) + writeIndex;
         ConvertAudioSamples(&bufferData[i * audioData->mFrames],
                             outData, audioData->mFrames);
 
         if (i == audioData->mChannels - 1) {
-          mDecodeJob.mWriteIndex += audioData->mFrames;
+          writeIndex += audioData->mFrames;
         }
       }
     }
   }
 
   if (sampleRate != destSampleRate) {
     uint32_t inputLatency = speex_resampler_get_input_latency(resampler);
-    const uint32_t maxOutSamples = resampledFrames - mDecodeJob.mWriteIndex;
+    const uint32_t maxOutSamples = resampledFrames - writeIndex;
     for (uint32_t i = 0; i < channelCount; ++i) {
       uint32_t inSamples = inputLatency;
       uint32_t outSamples = maxOutSamples;
       float* outData =
-        mDecodeJob.mBuffer->GetDataForWrite(i) + mDecodeJob.mWriteIndex;
+        mDecodeJob.mBuffer.ChannelDataForWrite<float>(i) + writeIndex;
 
       WebAudioUtils::SpeexResamplerProcess(
           resampler, i, (AudioDataValue*)nullptr, &inSamples,
           outData, &outSamples);
 
       if (i == channelCount - 1) {
-        mDecodeJob.mWriteIndex += outSamples;
-        MOZ_ASSERT(mDecodeJob.mWriteIndex <= resampledFrames);
+        writeIndex += outSamples;
+        MOZ_ASSERT(writeIndex <= resampledFrames);
         MOZ_ASSERT(inSamples == inputLatency);
       }
     }
   }
 
+  mDecodeJob.mBuffer.mDuration = writeIndex;
   mPhase = PhaseEnum::AllocateBuffer;
   mMainThread->Dispatch(do_AddRef(this));
 }
 
 void
 MediaDecodeTask::AllocateBuffer()
 {
   MOZ_ASSERT(NS_IsMainThread());
@@ -448,22 +458,19 @@ MediaDecodeTask::CallbackTheResult()
 
 bool
 WebAudioDecodeJob::AllocateBuffer()
 {
   MOZ_ASSERT(!mOutput);
   MOZ_ASSERT(NS_IsMainThread());
 
   // Now create the AudioBuffer
-  ErrorResult rv;
-  uint32_t channelCount = mBuffer->GetChannels();
-  mOutput = AudioBuffer::Create(mContext->GetOwner(), channelCount,
-                                mWriteIndex, mContext->SampleRate(),
-                                mBuffer.forget(), rv);
-  return !rv.Failed();
+  mOutput = AudioBuffer::Create(mContext->GetOwner(),
+                                mContext->SampleRate(), Move(mBuffer));
+  return mOutput != nullptr;
 }
 
 void
 AsyncDecodeWebAudio(const char* aContentType, uint8_t* aBuffer,
                     uint32_t aLength, WebAudioDecodeJob& aDecodeJob)
 {
   Maybe<MediaContainerType> containerType = MakeMediaContainerType(aContentType);
   // Do not attempt to decode the media if we were not successful at sniffing
@@ -499,17 +506,16 @@ AsyncDecodeWebAudio(const char* aContent
 }
 
 WebAudioDecodeJob::WebAudioDecodeJob(const nsACString& aContentType,
                                      AudioContext* aContext,
                                      Promise* aPromise,
                                      DecodeSuccessCallback* aSuccessCallback,
                                      DecodeErrorCallback* aFailureCallback)
   : mContentType(aContentType)
-  , mWriteIndex(0)
   , mContext(aContext)
   , mPromise(aPromise)
   , mSuccessCallback(aSuccessCallback)
   , mFailureCallback(aFailureCallback)
 {
   MOZ_ASSERT(aContext);
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_COUNT_CTOR(WebAudioDecodeJob);
@@ -599,19 +605,17 @@ WebAudioDecodeJob::SizeOfExcludingThis(M
     amount += mSuccessCallback->SizeOfIncludingThis(aMallocSizeOf);
   }
   if (mFailureCallback) {
     amount += mFailureCallback->SizeOfIncludingThis(aMallocSizeOf);
   }
   if (mOutput) {
     amount += mOutput->SizeOfIncludingThis(aMallocSizeOf);
   }
-  if (mBuffer) {
-    amount += mBuffer->SizeOfIncludingThis(aMallocSizeOf);
-  }
+  amount += mBuffer.SizeOfExcludingThis(aMallocSizeOf, false);
   return amount;
 }
 
 size_t
 WebAudioDecodeJob::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
 {
   return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf);
 }
--- a/dom/media/webaudio/MediaBufferDecoder.h
+++ b/dom/media/webaudio/MediaBufferDecoder.h
@@ -2,16 +2,17 @@
 /* vim:set ts=2 sw=2 sts=2 et cindent: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef MediaBufferDecoder_h_
 #define MediaBufferDecoder_h_
 
+#include "AudioSegment.h"
 #include "nsWrapperCache.h"
 #include "nsCOMPtr.h"
 #include "nsString.h"
 #include "nsTArray.h"
 #include "mozilla/dom/TypedArray.h"
 #include "mozilla/MemoryReporting.h"
 
 namespace mozilla {
@@ -50,24 +51,23 @@ struct WebAudioDecodeJob final
   void OnSuccess(ErrorCode /* ignored */);
   void OnFailure(ErrorCode aErrorCode);
 
   bool AllocateBuffer();
 
   size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
   size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
 
+  AudioChunk mBuffer;
   nsCString mContentType;
-  uint32_t mWriteIndex;
   RefPtr<dom::AudioContext> mContext;
   RefPtr<dom::Promise> mPromise;
   RefPtr<dom::DecodeSuccessCallback> mSuccessCallback;
   RefPtr<dom::DecodeErrorCallback> mFailureCallback; // can be null
   RefPtr<dom::AudioBuffer> mOutput;
-  RefPtr<ThreadSharedFloatArrayBufferList> mBuffer;
 };
 
 void AsyncDecodeWebAudio(const char* aContentType, uint8_t* aBuffer,
                          uint32_t aLength, WebAudioDecodeJob& aDecodeJob);
 
 } // namespace mozilla
 
 #endif