Bug 878015. Make RoundUpToAudioBlock always advance to the next audio block. r=padenot
authorRobert O'Callahan <robert@ocallahan.org>
Fri, 02 Aug 2013 21:27:58 +1200
changeset 141080 e1ee60e77157f1a91441b5d2f47e158ef01ae74b
parent 141079 9435e3497e306726f3b527c3b7fe5e1e418da50b
child 141081 a51321e4a846c21cb598dd7f14d95096f162750b
push id31980
push userrocallahan@mozilla.com
push dateFri, 02 Aug 2013 09:32:25 +0000
treeherdermozilla-inbound@a51321e4a846 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerspadenot
bugs878015
milestone25.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 878015. Make RoundUpToAudioBlock always advance to the next audio block. r=padenot
content/media/MediaStreamGraph.cpp
--- a/content/media/MediaStreamGraph.cpp
+++ b/content/media/MediaStreamGraph.cpp
@@ -978,39 +978,51 @@ MediaStreamGraphImpl::EnsureNextIteratio
     return;
   mNeedAnotherIteration = true;
   if (mWaitState == WAITSTATE_WAITING_INDEFINITELY) {
     mWaitState = WAITSTATE_WAKING_UP;
     aLock.Notify();
   }
 }
 
+/**
+ * Returns smallest value of t such that
+ * TimeToTicksRoundUp(aSampleRate, t) is a multiple of WEBAUDIO_BLOCK_SIZE
+ * and floor(TimeToTicksRoundUp(aSampleRate, t)/WEBAUDIO_BLOCK_SIZE) >
+ * floor(TimeToTicksRoundUp(aSampleRate, aTime)/WEBAUDIO_BLOCK_SIZE).
+ */
 static GraphTime
-RoundUpToAudioBlock(TrackRate aSampleRate, GraphTime aTime)
+RoundUpToNextAudioBlock(TrackRate aSampleRate, GraphTime aTime)
 {
-  int64_t ticksAtIdealaSampleRate = (aTime*aSampleRate) >> MEDIA_TIME_FRAC_BITS;
-  // Round up to nearest block boundary
-  int64_t blocksAtIdealaSampleRate =
-    (ticksAtIdealaSampleRate + (WEBAUDIO_BLOCK_SIZE - 1)) >>
-    WEBAUDIO_BLOCK_SIZE_BITS;
-  // Round up to nearest MediaTime unit
-  return
-    ((((blocksAtIdealaSampleRate + 1)*WEBAUDIO_BLOCK_SIZE) << MEDIA_TIME_FRAC_BITS)
-     + aSampleRate - 1)/aSampleRate;
+  TrackTicks ticks = TimeToTicksRoundUp(aSampleRate, aTime);
+  uint64_t block = ticks >> WEBAUDIO_BLOCK_SIZE_BITS;
+  uint64_t nextBlock = block + 1;
+  TrackTicks nextTicks = nextBlock << WEBAUDIO_BLOCK_SIZE_BITS;
+  // Find the smallest time t such that TimeToTicksRoundUp(aSampleRate,t) == nextTicks
+  // That's the smallest integer t such that
+  //   t*aSampleRate > ((nextTicks - 1) << MEDIA_TIME_FRAC_BITS)
+  // Both sides are integers, so this is equivalent to
+  //   t*aSampleRate >= ((nextTicks - 1) << MEDIA_TIME_FRAC_BITS) + 1
+  //   t >= (((nextTicks - 1) << MEDIA_TIME_FRAC_BITS) + 1)/aSampleRate
+  //   t = ceil((((nextTicks - 1) << MEDIA_TIME_FRAC_BITS) + 1)/aSampleRate)
+  // Using integer division, that's
+  //   t = (((nextTicks - 1) << MEDIA_TIME_FRAC_BITS) + 1 + aSampleRate - 1)/aSampleRate
+  //     = ((nextTicks - 1) << MEDIA_TIME_FRAC_BITS)/aSampleRate + 1
+  return ((nextTicks - 1) << MEDIA_TIME_FRAC_BITS)/aSampleRate + 1;
 }
 
 void
 MediaStreamGraphImpl::ProduceDataForStreamsBlockByBlock(uint32_t aStreamIndex,
                                                         TrackRate aSampleRate,
                                                         GraphTime aFrom,
                                                         GraphTime aTo)
 {
   GraphTime t = aFrom;
   while (t < aTo) {
-    GraphTime next = RoundUpToAudioBlock(aSampleRate, t + 1);
+    GraphTime next = RoundUpToNextAudioBlock(aSampleRate, t);
     for (uint32_t i = aStreamIndex; i < mStreams.Length(); ++i) {
       nsRefPtr<ProcessedMediaStream> ps = mStreams[i]->AsProcessedStream();
       if (ps) {
         ps->ProduceOutput(t, next);
       }
     }
     t = next;
   }
@@ -1064,17 +1076,17 @@ MediaStreamGraphImpl::RunThread()
           // We know that the rest of the streams will run at the same rate.
           sampleRate = n->SampleRate();
           break;
         }
       }
     }
 
     GraphTime endBlockingDecisions =
-      RoundUpToAudioBlock(sampleRate, mCurrentTime + MillisecondsToMediaTime(AUDIO_TARGET_MS));
+      RoundUpToNextAudioBlock(sampleRate, mCurrentTime + MillisecondsToMediaTime(AUDIO_TARGET_MS));
     bool ensureNextIteration = false;
 
     // Grab pending stream input.
     for (uint32_t i = 0; i < mStreams.Length(); ++i) {
       SourceMediaStream* is = mStreams[i]->AsSourceStream();
       if (is) {
         UpdateConsumptionState(is);
         ExtractPendingInput(is, endBlockingDecisions, &ensureNextIteration);