Bug 943461. Part 18: Ensure AudioBufferSourceNode's engine always produces an audio block when ProduceAudioBlock is called, and add an assertion to catch this kind of error directly. r=karl
authorRobert O'Callahan <robert@ocallahan.org>
Fri, 13 Dec 2013 01:33:01 +1300
changeset 162335 0279107b81d321e2c5279d2e7c33fc9563d1be73
parent 162334 75ca7a7c5df7cd5bde7f409c412a0a58bc753e04
child 162336 7677ea877c089aec20d93fa55e49f1fc12fa1752
push idunknown
push userunknown
push dateunknown
reviewerskarl
bugs943461
milestone29.0a1
Bug 943461. Part 18: Ensure AudioBufferSourceNode's engine always produces an audio block when ProduceAudioBlock is called, and add an assertion to catch this kind of error directly. r=karl
content/media/AudioNodeStream.cpp
content/media/webaudio/AudioBufferSourceNode.cpp
--- a/content/media/AudioNodeStream.cpp
+++ b/content/media/AudioNodeStream.cpp
@@ -407,33 +407,39 @@ AudioNodeStream::ProduceOutput(GraphTime
   uint16_t outputCount = std::max(uint16_t(1), mEngine->OutputCount());
   mLastChunks.SetLength(outputCount);
 
   if (mMuted || IsFinishedOnGraphThread()) {
     for (uint16_t i = 0; i < outputCount; ++i) {
       mLastChunks[i].SetNull(WEBAUDIO_BLOCK_SIZE);
     }
   } else {
-    for (uint16_t i = 0; i < outputCount; ++i) {
-      mLastChunks[i].SetNull(0);
-    }
-
     // We need to generate at least one input
     uint16_t maxInputs = std::max(uint16_t(1), mEngine->InputCount());
     OutputChunks inputChunks;
     inputChunks.SetLength(maxInputs);
     for (uint16_t i = 0; i < maxInputs; ++i) {
       ObtainInputBlock(inputChunks[i], i);
     }
     bool finished = false;
+#ifdef DEBUG
+    for (uint16_t i = 0; i < outputCount; ++i) {
+      // Clear chunks so we can detect if ProduceAudioBlock fails to set them.
+      mLastChunks[i].SetNull(0);
+    }
+#endif
     if (maxInputs <= 1 && mEngine->OutputCount() <= 1) {
       mEngine->ProduceAudioBlock(this, inputChunks[0], &mLastChunks[0], &finished);
     } else {
       mEngine->ProduceAudioBlocksOnPorts(this, inputChunks, mLastChunks, &finished);
     }
+    for (uint16_t i = 0; i < outputCount; ++i) {
+      NS_ASSERTION(mLastChunks[i].GetDuration() == WEBAUDIO_BLOCK_SIZE,
+                   "Invalid WebAudio chunk size");
+    }
     if (finished) {
       mMarkAsFinishedAfterThisBlock = true;
     }
   }
 
   if (mDisabledTrackIDs.Contains(static_cast<TrackID>(AUDIO_TRACK))) {
     for (uint32_t i = 0; i < mLastChunks.Length(); ++i) {
       mLastChunks[i].SetNull(WEBAUDIO_BLOCK_SIZE);
--- a/content/media/webaudio/AudioBufferSourceNode.cpp
+++ b/content/media/webaudio/AudioBufferSourceNode.cpp
@@ -387,16 +387,17 @@ public:
   }
 
   virtual void ProduceAudioBlock(AudioNodeStream* aStream,
                                  const AudioChunk& aInput,
                                  AudioChunk* aOutput,
                                  bool* aFinished)
   {
     if (!mBuffer || !mDuration) {
+      aOutput->SetNull(WEBAUDIO_BLOCK_SIZE);
       return;
     }
 
     uint32_t channels = mBuffer->GetChannels();
     if (!channels) {
       aOutput->SetNull(WEBAUDIO_BLOCK_SIZE);
       return;
     }