Bug 1378070 - Update AudioConverter to use destination buffer. r?jya draft
authorAlex Chronopoulos <achronop@gmail.com>
Mon, 28 Aug 2017 17:15:46 +0300
changeset 654304 d275e7fb60ed9742e22c89b7506c5b4052a8d7de
parent 649622 7dddbd85047c6dc73ddbe1e423cd643a217845b3
child 654305 942b1ab187b55e2a794473f907aebb7eaadbd2e4
push id76533
push userachronop@gmail.com
push dateMon, 28 Aug 2017 14:27:14 +0000
reviewersjya
bugs1378070
milestone57.0a1
Bug 1378070 - Update AudioConverter to use destination buffer. r?jya MozReview-Commit-ID: KCheY0DCjh4
dom/media/AudioConverter.cpp
dom/media/AudioConverter.h
--- a/dom/media/AudioConverter.cpp
+++ b/dom/media/AudioConverter.cpp
@@ -60,16 +60,19 @@ AudioConverter::CanWorkInPlace() const
   // perform any upsampling in place (e.g. if incoming rate >= outgoing rate)
   return !needUpmix && (!needDownmix || canDownmixInPlace) &&
          (!needResample || canResampleInPlace);
 }
 
 size_t
 AudioConverter::ProcessInternal(void* aOut, const void* aIn, size_t aFrames)
 {
+  if (!aFrames) {
+    return 0;
+  }
   if (mIn.Channels() > mOut.Channels()) {
     return DownmixAudio(aOut, aIn, aFrames);
   } else if (mIn.Channels() < mOut.Channels()) {
     return UpmixAudio(aOut, aIn, aFrames);
   } else if (mIn.Layout() != mOut.Layout() && CanReorderAudio()) {
     ReOrderInterleavedChannels(aOut, aIn, aFrames);
   } else if (aIn != aOut) {
     memmove(aOut, aIn, FramesOutToBytes(aFrames));
--- a/dom/media/AudioConverter.h
+++ b/dom/media/AudioConverter.h
@@ -126,23 +126,18 @@ public:
   // Providing an empty buffer and resampling is expected, the resampler
   // will be drained.
   template <AudioConfig::SampleFormat Format, typename Value>
   AudioDataBuffer<Format, Value> Process(AudioDataBuffer<Format, Value>&& aBuffer)
   {
     MOZ_DIAGNOSTIC_ASSERT(mIn.Format() == mOut.Format() && mIn.Format() == Format);
     AudioDataBuffer<Format, Value> buffer = Move(aBuffer);
     if (CanWorkInPlace()) {
-      size_t frames = SamplesInToFrames(buffer.Length());
-      frames = ProcessInternal(buffer.Data(), buffer.Data(), frames);
-      if (frames && mIn.Rate() != mOut.Rate()) {
-        frames = ResampleAudio(buffer.Data(), buffer.Data(), frames);
-      }
       AlignedBuffer<Value> temp = buffer.Forget();
-      temp.SetLength(FramesOutToSamples(frames));
+      Process(temp, temp.Data(), SamplesInToFrames(temp.Length()));
       return AudioDataBuffer<Format, Value>(Move(temp));;
     }
     return Process(buffer);
   }
 
   template <AudioConfig::SampleFormat Format, typename Value>
   AudioDataBuffer<Format, Value> Process(const AudioDataBuffer<Format, Value>& aBuffer)
   {
@@ -191,16 +186,48 @@ public:
     }
     size_t frames = ProcessInternal(aBuffer, aBuffer, aFrames);
     if (frames && mIn.Rate() != mOut.Rate()) {
       frames = ResampleAudio(aBuffer, aBuffer, aFrames);
     }
     return frames;
   }
 
+  template <typename Value>
+  size_t Process(AlignedBuffer<Value>& aOutBuffer, const Value* aInBuffer, size_t aFrames)
+  {
+    MOZ_DIAGNOSTIC_ASSERT(mIn.Format() == mOut.Format());
+    MOZ_ASSERT((aFrames && aInBuffer) || !aFrames);
+    // Up/down mixing first
+    if (!aOutBuffer.SetLength(FramesOutToSamples(aFrames))) {
+      MOZ_ALWAYS_TRUE(aOutBuffer.SetLength(0));
+      return 0;
+    }
+    size_t frames = ProcessInternal(aOutBuffer.Data(), aInBuffer, aFrames);
+    MOZ_ASSERT(frames == aFrames);
+    // Check if resampling is needed
+    if (mIn.Rate() == mOut.Rate()) {
+      return frames;
+    }
+    // Prepare output in cases of drain or up-sampling
+    if ((!frames || mOut.Rate() > mIn.Rate()) &&
+        !aOutBuffer.SetLength(FramesOutToSamples(ResampleRecipientFrames(frames)))) {
+      MOZ_ALWAYS_TRUE(aOutBuffer.SetLength(0));
+      return 0;
+    }
+    if (!frames) {
+      frames = DrainResampler(aOutBuffer.Data());
+    } else {
+      frames = ResampleAudio(aOutBuffer.Data(), aInBuffer, frames);
+    }
+    // Update with the actual buffer length
+    MOZ_ALWAYS_TRUE(aOutBuffer.SetLength(FramesOutToSamples(frames)));
+    return frames;
+  }
+
   bool CanWorkInPlace() const;
   bool CanReorderAudio() const
   {
     return mIn.Layout().MappingTable(mOut.Layout());
   }
 
   const AudioConfig& InputConfig() const { return mIn; }
   const AudioConfig& OutputConfig() const { return mOut; }