Bug 1172778 - Update readyState when audio samples are popped by AudioSink. r=cpearce.
authorJW Wang <jwwang@mozilla.com>
Wed, 10 Jun 2015 10:55:56 +0800
changeset 247868 c9212e60f6c676b269aac119cbb7f3a3a5ec66c0
parent 247867 83b6715ed8f914e59ea5de8a3b849930f5d3a6cb
child 247869 05ac4287dd7974e3d3e9b3982d127e3c9ff13cfc
push id28885
push usercbook@mozilla.com
push dateWed, 10 Jun 2015 13:18:59 +0000
treeherderautoland@e101c589c242 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerscpearce
bugs1172778
milestone41.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 1172778 - Update readyState when audio samples are popped by AudioSink. r=cpearce.
dom/media/MediaDecoderStateMachine.cpp
dom/media/MediaDecoderStateMachine.h
--- a/dom/media/MediaDecoderStateMachine.cpp
+++ b/dom/media/MediaDecoderStateMachine.cpp
@@ -267,16 +267,24 @@ MediaDecoderStateMachine::MediaDecoderSt
 #ifdef XP_WIN
   // Ensure high precision timers are enabled on Windows, otherwise the state
   // machine isn't woken up at reliable intervals to set the next frame,
   // and we drop frames while painting. Note that multiple calls to this
   // function per-process is OK, provided each call is matched by a corresponding
   // timeEndPeriod() call.
   timeBeginPeriod(1);
 #endif
+
+  AudioQueue().AddPopListener(
+    NS_NewRunnableMethod(this, &MediaDecoderStateMachine::OnAudioPopped),
+    mTaskQueue);
+
+  VideoQueue().AddPopListener(
+    NS_NewRunnableMethod(this, &MediaDecoderStateMachine::OnVideoPopped),
+    mTaskQueue);
 }
 
 MediaDecoderStateMachine::~MediaDecoderStateMachine()
 {
   MOZ_ASSERT(NS_IsMainThread(), "Should be on main thread.");
   MOZ_COUNT_DTOR(MediaDecoderStateMachine);
   NS_ASSERTION(!mPendingWakeDecoder.get(),
                "WakeDecoder should have been revoked already");
@@ -576,17 +584,17 @@ void MediaDecoderStateMachine::SendStrea
   while (true) {
     const AudioData* a = AudioQueue().PeekFront();
     // If we discard audio samples fed to the stream immediately, we will
     // keep decoding audio samples till the end and consume a lot of memory.
     // Therefore we only discard those behind the stream clock to throttle
     // the decoding speed.
     if (a && a->mTime <= clockTime) {
       OnAudioEndTimeUpdate(std::max(mAudioEndTime, a->GetEndTime()));
-      nsRefPtr<AudioData> releaseMe = PopAudio();
+      nsRefPtr<AudioData> releaseMe = AudioQueue().PopFront();
       continue;
     }
     break;
   }
 
   // To be consistent with AudioSink, |mAudioCompleted| is not set
   // until all samples are drained.
   if (finished && AudioQueue().GetSize() == 0) {
@@ -900,32 +908,35 @@ MediaDecoderStateMachine::PushFront(Vide
 {
   MOZ_ASSERT(OnTaskQueue());
   MOZ_ASSERT(aSample);
 
   VideoQueue().PushFront(aSample);
   UpdateNextFrameStatus();
 }
 
-already_AddRefed<AudioData>
-MediaDecoderStateMachine::PopAudio()
+void
+MediaDecoderStateMachine::OnAudioPopped()
 {
   MOZ_ASSERT(OnTaskQueue());
-  nsRefPtr<AudioData> sample = AudioQueue().PopFront();
+  ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
   UpdateNextFrameStatus();
-  return sample.forget();
+  DispatchAudioDecodeTaskIfNeeded();
 }
 
-already_AddRefed<VideoData>
-MediaDecoderStateMachine::PopVideo()
+void
+MediaDecoderStateMachine::OnVideoPopped()
 {
   MOZ_ASSERT(OnTaskQueue());
-  nsRefPtr<VideoData> sample = VideoQueue().PopFront();
+  ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
   UpdateNextFrameStatus();
-  return sample.forget();
+  DispatchVideoDecodeTaskIfNeeded();
+  // Notify the decode thread that the video queue's buffers may have
+  // free'd up space for more frames.
+  mDecoder->GetReentrantMonitor().NotifyAll();
 }
 
 void
 MediaDecoderStateMachine::OnNotDecoded(MediaData::Type aType,
                                        MediaDecoderReader::NotDecodedReason aReason)
 {
   MOZ_ASSERT(OnTaskQueue());
   ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
@@ -2278,27 +2289,16 @@ MediaDecoderStateMachine::CallDecodeFirs
 nsresult
 MediaDecoderStateMachine::DecodeFirstFrame()
 {
   MOZ_ASSERT(OnTaskQueue());
   AssertCurrentThreadInMonitor();
   MOZ_ASSERT(mState == DECODER_STATE_DECODING_FIRSTFRAME);
   DECODER_LOG("DecodeFirstFrame started");
 
-  if (HasAudio()) {
-    RefPtr<nsIRunnable> decodeTask(
-      NS_NewRunnableMethod(this, &MediaDecoderStateMachine::DispatchAudioDecodeTaskIfNeeded));
-    AudioQueue().AddPopListener(decodeTask, TaskQueue());
-  }
-  if (HasVideo()) {
-    RefPtr<nsIRunnable> decodeTask(
-      NS_NewRunnableMethod(this, &MediaDecoderStateMachine::DispatchVideoDecodeTaskIfNeeded));
-    VideoQueue().AddPopListener(decodeTask, TaskQueue());
-  }
-
   if (IsRealTime()) {
     SetStartTime(0);
     nsresult res = FinishDecodeFirstFrame();
     NS_ENSURE_SUCCESS(res, res);
   } else if (mSentFirstFrameLoadedEvent) {
     // We're resuming from dormant state, so we don't need to request
     // the first samples in order to determine the media start time,
     // we have the start time from last time we loaded.
@@ -2920,20 +2920,17 @@ void MediaDecoderStateMachine::AdvanceFr
     while (IsRealTime() || clock_time >= frame->mTime) {
       mVideoFrameEndTime = frame->GetEndTime();
       if (currentFrame) {
         mDecoder->NotifyDecodedFrames(0, 0, 1);
         VERBOSE_LOG("discarding video frame mTime=%lld clock_time=%lld (%d so far)",
                     currentFrame->mTime, clock_time, ++droppedFrames);
       }
       currentFrame = frame;
-      nsRefPtr<VideoData> releaseMe = PopVideo();
-      // Notify the decode thread that the video queue's buffers may have
-      // free'd up space for more frames.
-      mDecoder->GetReentrantMonitor().NotifyAll();
+      nsRefPtr<VideoData> releaseMe = VideoQueue().PopFront();
       OnPlaybackOffsetUpdate(frame->mOffset);
       if (VideoQueue().GetSize() == 0)
         break;
       frame = VideoQueue().PeekFront();
     }
     // Current frame has already been presented, wait until it's time to
     // present the next frame.
     if (frame && !currentFrame) {
--- a/dom/media/MediaDecoderStateMachine.h
+++ b/dom/media/MediaDecoderStateMachine.h
@@ -415,22 +415,18 @@ protected:
 
   // Inserts MediaData* samples into their respective MediaQueues.
   // aSample must not be null.
   void Push(AudioData* aSample);
   void Push(VideoData* aSample);
   void PushFront(AudioData* aSample);
   void PushFront(VideoData* aSample);
 
-  // Pops MediaData* samples from their respective MediaQueues.
-  // Note that the audio queue is also drained on the audio thread,
-  // which we can't easily react to - This should be fixed when we
-  // remove the audio thread in bug 750596.
-  already_AddRefed<AudioData> PopAudio();
-  already_AddRefed<VideoData> PopVideo();
+  void OnAudioPopped();
+  void OnVideoPopped();
 
   void VolumeChanged();
   void LogicalPlaybackRateChanged();
   void PreservesPitchChanged();
 
   class WakeDecoderRunnable : public nsRunnable {
   public:
     explicit WakeDecoderRunnable(MediaDecoderStateMachine* aSM)