Bug 952756 - Always remember offset and duration from Start(). r=padenot, a=abillings
authorKarl Tomlinson <karlt+@karlt.net>
Tue, 07 Jan 2014 12:53:47 +1300
changeset 174615 c76cad3681d52c58a1a4917a3e2e0ce78fd516d5
parent 174614 bcdc6180d7c446fee25f2b6180af4d0c93159ba8
child 174616 9a310e42b187cf447d8f9b8587ff2487cc8de51d
push id3224
push userlsblakk@mozilla.com
push dateTue, 04 Feb 2014 01:06:49 +0000
treeherdermozilla-beta@60c04d0987f1 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerspadenot, abillings
bugs952756
milestone28.0a2
Bug 952756 - Always remember offset and duration from Start(). r=padenot, a=abillings
content/media/webaudio/AudioBufferSourceNode.cpp
content/media/webaudio/AudioBufferSourceNode.h
--- a/content/media/webaudio/AudioBufferSourceNode.cpp
+++ b/content/media/webaudio/AudioBufferSourceNode.cpp
@@ -467,18 +467,17 @@ public:
 
 AudioBufferSourceNode::AudioBufferSourceNode(AudioContext* aContext)
   : AudioNode(aContext,
               2,
               ChannelCountMode::Max,
               ChannelInterpretation::Speakers)
   , mLoopStart(0.0)
   , mLoopEnd(0.0)
-  , mOffset(0.0)
-  , mDuration(std::numeric_limits<double>::min())
+  // mOffset and mDuration are initialized in Start().
   , mPlaybackRate(new AudioParam(MOZ_THIS_IN_INITIALIZER_LIST(),
                   SendPlaybackRateToStream, 1.0f))
   , mLoop(false)
   , mStartCalled(false)
   , mStopped(false)
 {
   AudioBufferSourceNodeEngine* engine = new AudioBufferSourceNodeEngine(this, aContext->Destination());
   mStream = aContext->Graph()->CreateAudioNodeStream(engine, MediaStreamGraph::SOURCE_STREAM);
@@ -516,29 +515,24 @@ AudioBufferSourceNode::Start(double aWhe
   mStartCalled = true;
 
   AudioNodeStream* ns = static_cast<AudioNodeStream*>(mStream.get());
   if (!ns) {
     // Nothing to play, or we're already dead for some reason
     return;
   }
 
+  // Remember our arguments so that we can use them when we get a new buffer.
+  mOffset = aOffset;
+  mDuration = aDuration.WasPassed() ? aDuration.Value()
+                                    : std::numeric_limits<double>::min();
+  // We can't send these parameters without a buffer because we don't know the
+  // buffer's sample rate or length.
   if (mBuffer) {
-    double duration = aDuration.WasPassed() ?
-                      aDuration.Value() :
-                      std::numeric_limits<double>::min();
-    SendOffsetAndDurationParametersToStream(ns, aOffset, duration);
-  } else {
-    // Remember our arguments so that we can use them once we have a buffer.
-    // We can't send these parameters now because we don't know the buffer
-    // sample rate.
-    mOffset = aOffset;
-    mDuration = aDuration.WasPassed() ?
-                aDuration.Value() :
-                std::numeric_limits<double>::min();
+    SendOffsetAndDurationParametersToStream(ns);
   }
 
   // Don't set parameter unnecessarily
   if (aWhen > 0.0) {
     ns->SetStreamTimeParameter(START, Context()->DestinationStream(), aWhen);
   }
 
   MarkActive();
@@ -553,34 +547,32 @@ AudioBufferSourceNode::SendBufferParamet
   if (mBuffer) {
     float rate = mBuffer->SampleRate();
     nsRefPtr<ThreadSharedFloatArrayBufferList> data =
       mBuffer->GetThreadSharedChannelsForRate(aCx);
     ns->SetBuffer(data.forget());
     ns->SetInt32Parameter(SAMPLE_RATE, rate);
 
     if (mStartCalled) {
-      SendOffsetAndDurationParametersToStream(ns, mOffset, mDuration);
+      SendOffsetAndDurationParametersToStream(ns);
     }
   } else {
     ns->SetBuffer(nullptr);
   }
 }
 
 void
-AudioBufferSourceNode::SendOffsetAndDurationParametersToStream(AudioNodeStream* aStream,
-                                                               double aOffset,
-                                                               double aDuration)
+AudioBufferSourceNode::SendOffsetAndDurationParametersToStream(AudioNodeStream* aStream)
 {
   NS_ASSERTION(mBuffer && mStartCalled,
                "Only call this when we have a buffer and start() has been called");
 
   float rate = mBuffer->SampleRate();
   int32_t bufferLength = mBuffer->Length();
-  int32_t offsetSamples = std::max(0, NS_lround(aOffset * rate));
+  int32_t offsetSamples = std::max(0, NS_lround(mOffset * rate));
 
   if (offsetSamples >= bufferLength) {
     // The offset falls past the end of the buffer.  In this case, we need to
     // stop the playback immediately if it's in progress.
     // Note that we can't call Stop() here since that might be overridden if
     // web content calls Stop() too, so we just null out the buffer.
     if (mStartCalled) {
       aStream->SetBuffer(nullptr);
@@ -588,18 +580,18 @@ AudioBufferSourceNode::SendOffsetAndDura
     return;
   }
   // Don't set parameter unnecessarily
   if (offsetSamples > 0) {
     aStream->SetInt32Parameter(OFFSET, offsetSamples);
   }
 
   int32_t playingLength = bufferLength - offsetSamples;
-  if (aDuration != std::numeric_limits<double>::min()) {
-    playingLength = std::min(NS_lround(aDuration * rate), playingLength);
+  if (mDuration != std::numeric_limits<double>::min()) {
+    playingLength = std::min(NS_lround(mDuration * rate), playingLength);
   }
   aStream->SetInt32Parameter(DURATION, playingLength);
 }
 
 void
 AudioBufferSourceNode::Stop(double aWhen, ErrorResult& aRv)
 {
   if (!WebAudioUtils::IsTimeValid(aWhen)) {
--- a/content/media/webaudio/AudioBufferSourceNode.h
+++ b/content/media/webaudio/AudioBufferSourceNode.h
@@ -106,37 +106,36 @@ public:
   void SendDopplerShiftToStream(double aDopplerShift);
 
   IMPL_EVENT_HANDLER(ended)
 
   virtual void NotifyMainThreadStateChanged() MOZ_OVERRIDE;
 
 private:
   friend class AudioBufferSourceNodeEngine;
-  // START, OFFSET and DURATION are always set by start() (along with setting
-  // mBuffer to something non-null).
-  // STOP is set by stop().
+  // START is sent during Start().
+  // STOP is sent during Stop().
+  // OFFSET and DURATION are sent when SetBuffer() and Start() have
+  // been called (along with sending the buffer).
   enum EngineParameters {
     SAMPLE_RATE,
     START,
     STOP,
     OFFSET,
     DURATION,
     LOOP,
     LOOPSTART,
     LOOPEND,
     PLAYBACKRATE,
     DOPPLERSHIFT
   };
 
   void SendLoopParametersToStream();
   void SendBufferParameterToStream(JSContext* aCx);
-  void SendOffsetAndDurationParametersToStream(AudioNodeStream* aStream,
-                                               double aOffset,
-                                               double aDuration);
+  void SendOffsetAndDurationParametersToStream(AudioNodeStream* aStream);
   static void SendPlaybackRateToStream(AudioNode* aNode);
 
 private:
   double mLoopStart;
   double mLoopEnd;
   double mOffset;
   double mDuration;
   nsRefPtr<AudioBuffer> mBuffer;