Bug 1137511 - Account for audio frames already pushed to audio hardware but not yet played when computing OutOfDecodedAudio. r=kinetik
authorBobby Holley <bobbyholley@gmail.com>
Thu, 26 Feb 2015 13:37:03 -0800
changeset 231225 3148c577bfd9cfd80ee20481163bfd40d8bc027b
parent 231224 5801ebeeb3b626af6a98cc1368efa83da4eff025
child 231226 3e9cc0ba5dfb5fe1af0a264d784a9c6f35204c8f
push id28348
push userkwierso@gmail.com
push dateMon, 02 Mar 2015 20:13:43 +0000
treeherdermozilla-central@abb7f0d180da [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskinetik
bugs1137511
milestone39.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 1137511 - Account for audio frames already pushed to audio hardware but not yet played when computing OutOfDecodedAudio. r=kinetik
dom/media/AudioSink.cpp
dom/media/AudioSink.h
dom/media/MediaDecoderStateMachine.cpp
dom/media/MediaDecoderStateMachine.h
--- a/dom/media/AudioSink.cpp
+++ b/dom/media/AudioSink.cpp
@@ -80,16 +80,25 @@ AudioSink::GetPosition()
       (pos = mAudioStream->GetPosition()) >= 0) {
     // Update the last good position when we got a good one.
     mLastGoodPosition = pos;
   }
 
   return mLastGoodPosition;
 }
 
+bool
+AudioSink::HasUnplayedFrames()
+{
+  AssertCurrentThreadInMonitor();
+  // Experimentation suggests that GetPositionInFrames() is zero-indexed,
+  // so we need to add 1 here before comparing it to mWritten.
+  return mAudioStream && mAudioStream->GetPositionInFrames() + 1 < mWritten;
+}
+
 void
 AudioSink::PrepareToShutdown()
 {
   AssertCurrentThreadInMonitor();
   mStopAudioThread = true;
   if (mAudioStream) {
     mAudioStream->Cancel();
   }
--- a/dom/media/AudioSink.h
+++ b/dom/media/AudioSink.h
@@ -22,16 +22,20 @@ public:
 
   AudioSink(MediaDecoderStateMachine* aStateMachine,
             int64_t aStartTime, AudioInfo aInfo, dom::AudioChannel aChannel);
 
   nsresult Init();
 
   int64_t GetPosition();
 
+  // Check whether we've pushed more frames to the audio hardware than it has
+  // played.
+  bool HasUnplayedFrames();
+
   // Tell the AudioSink to stop processing and initiate shutdown.  Must be
   // called with the decoder monitor held.
   void PrepareToShutdown();
 
   // Shut down the AudioSink's resources.  The decoder monitor must not be
   // held during this call, as it may block processing thread event queues.
   void Shutdown();
 
--- a/dom/media/MediaDecoderStateMachine.cpp
+++ b/dom/media/MediaDecoderStateMachine.cpp
@@ -2098,16 +2098,23 @@ bool MediaDecoderStateMachine::HasLowDec
   // provided we've not decoded to the end of the audio stream, or
   // if we're low on video frames, provided
   // we've not decoded to the end of the video stream.
   return ((IsAudioDecoding() && AudioDecodedUsecs() < aAudioUsecs) ||
          (IsVideoDecoding() &&
           static_cast<uint32_t>(VideoQueue().GetSize()) < LOW_VIDEO_FRAMES));
 }
 
+bool MediaDecoderStateMachine::OutOfDecodedAudio()
+{
+    return IsAudioDecoding() && !AudioQueue().IsFinished() &&
+           AudioQueue().GetSize() == 0 &&
+           (!mAudioSink || !mAudioSink->HasUnplayedFrames());
+}
+
 bool MediaDecoderStateMachine::HasLowUndecodedData()
 {
   return HasLowUndecodedData(mLowDataThresholdUsecs);
 }
 
 bool MediaDecoderStateMachine::HasLowUndecodedData(int64_t aUsecs)
 {
   AssertCurrentThreadInMonitor();
--- a/dom/media/MediaDecoderStateMachine.h
+++ b/dom/media/MediaDecoderStateMachine.h
@@ -491,20 +491,17 @@ protected:
   bool NeedToDecodeVideo();
 
   // Returns true if we've got less than aAudioUsecs microseconds of decoded
   // and playable data. The decoder monitor must be held.
   //
   // May not be invoked when mReader->UseBufferingHeuristics() is false.
   bool HasLowDecodedData(int64_t aAudioUsecs);
 
-  bool OutOfDecodedAudio()
-  {
-    return IsAudioDecoding() && !AudioQueue().IsFinished() && AudioQueue().GetSize() == 0;
-  }
+  bool OutOfDecodedAudio();
 
   bool OutOfDecodedVideo()
   {
     // In buffering mode, we keep the last already-played frame in the queue.
     int emptyVideoSize = mState == DECODER_STATE_BUFFERING ? 1 : 0;
     return IsVideoDecoding() && !VideoQueue().IsFinished() && VideoQueue().GetSize() <= emptyVideoSize;
   }