Backed out changeset ca140e7557d6 (bug 883731)
authorCarsten "Tomcat" Book <cbook@mozilla.com>
Mon, 29 Sep 2014 10:57:28 +0200
changeset 207672 ff03c5e417b4a811905b5de41b68f59adf305238
parent 207671 e45884ac36e6647a1aeb5733ad960c1d6e845c53
child 207673 1f9df75e4ee865179c9ced78985dff3e0fdea41c
push id27564
push userryanvm@gmail.com
push dateMon, 29 Sep 2014 18:57:04 +0000
treeherdermozilla-central@ce9a0b34225e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs883731
milestone35.0a1
backs outca140e7557d6051c7966b60b81dbf38c405165a2
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
Backed out changeset ca140e7557d6 (bug 883731)
content/html/content/src/HTMLMediaElement.cpp
content/media/MediaDecoder.cpp
content/media/MediaDecoderOwner.h
content/media/MediaDecoderStateMachine.cpp
content/media/omx/AudioOffloadPlayer.cpp
--- a/content/html/content/src/HTMLMediaElement.cpp
+++ b/content/html/content/src/HTMLMediaElement.cpp
@@ -2947,16 +2947,28 @@ void HTMLMediaElement::FirstFrameLoaded(
 
   ChangeDelayLoadStatus(false);
 
   if (mDecoder && mAllowSuspendAfterFirstFrame && mPaused &&
       !HasAttr(kNameSpaceID_None, nsGkAtoms::autoplay) &&
       mPreloadAction == HTMLMediaElement::PRELOAD_METADATA) {
     mSuspendedAfterFirstFrame = true;
     mDecoder->Suspend();
+  } else if (mDownloadSuspendedByCache &&
+             mDecoder && !mDecoder->IsEnded()) {
+    // We've already loaded the first frame, and the decoder has signalled
+    // that the download has been suspended by the media cache. So move
+    // readyState into HAVE_ENOUGH_DATA, in case there's script waiting
+    // for a "canplaythrough" event; without this forced transition, we will
+    // never fire the "canplaythrough" event if the media cache is so small
+    // that the download was suspended before the first frame was loaded.
+    // Don't force this transition if the decoder is in ended state; the
+    // readyState should remain at HAVE_CURRENT_DATA in this case.
+    ChangeReadyState(nsIDOMHTMLMediaElement::HAVE_ENOUGH_DATA);
+    return;
   }
 }
 
 void HTMLMediaElement::NetworkError()
 {
   Error(nsIDOMMediaError::MEDIA_ERR_NETWORK);
 }
 
@@ -3041,16 +3053,17 @@ void HTMLMediaElement::PlaybackEnded()
 
 void HTMLMediaElement::SeekStarted()
 {
   DispatchAsyncEvent(NS_LITERAL_STRING("seeking"));
   // Set the Variable if the Seekstarted while active playing
   if(mPlayingThroughTheAudioChannel) {
     mPlayingThroughTheAudioChannelBeforeSeek = true;
   }
+  ChangeReadyState(nsIDOMHTMLMediaElement::HAVE_METADATA);
   FireTimeUpdate(false);
 }
 
 void HTMLMediaElement::SeekCompleted()
 {
   mPlayingBeforeSeek = false;
   SetPlayedOrSeeked(true);
   DispatchAsyncEvent(NS_LITERAL_STRING("seeked"));
@@ -3116,21 +3129,16 @@ void HTMLMediaElement::UpdateReadyStateF
   // Section 2.4.3.1 of the Media Source Extensions spec requires
   // changing to HAVE_METADATA when seeking into an unbuffered
   // range.
   if (aNextFrame == MediaDecoderOwner::NEXT_FRAME_WAIT_FOR_MSE_DATA) {
     ChangeReadyState(nsIDOMHTMLMediaElement::HAVE_METADATA);
     return;
   }
 
-  if (aNextFrame == MediaDecoderOwner::NEXT_FRAME_UNAVAILABLE_SEEKING) {
-    ChangeReadyState(nsIDOMHTMLMediaElement::HAVE_METADATA);
-    return;
-  }
-
   if (mDownloadSuspendedByCache && mDecoder && !mDecoder->IsEnded()) {
     // The decoder has signaled that the download has been suspended by the
     // media cache. So move readyState into HAVE_ENOUGH_DATA, in case there's
     // script waiting for a "canplaythrough" event; without this forced
     // transition, we will never fire the "canplaythrough" event if the
     // media cache is too small, and scripts are bound to fail. Don't force
     // this transition if the decoder is in ended state; the readyState
     // should remain at HAVE_CURRENT_DATA in this case.
@@ -3195,17 +3203,17 @@ void HTMLMediaElement::ChangeReadyState(
   }
 
   LOG(PR_LOG_DEBUG, ("%p Ready state changed to %s", this, gReadyStateToString[aState]));
 
   UpdateAudioChannelPlayingState();
 
   // Handle raising of "waiting" event during seek (see 4.8.10.9)
   if (mPlayingBeforeSeek &&
-      mReadyState < nsIDOMHTMLMediaElement::HAVE_FUTURE_DATA) {
+      oldState < nsIDOMHTMLMediaElement::HAVE_FUTURE_DATA) {
     DispatchAsyncEvent(NS_LITERAL_STRING("waiting"));
   }
 
   if (oldState < nsIDOMHTMLMediaElement::HAVE_CURRENT_DATA &&
       mReadyState >= nsIDOMHTMLMediaElement::HAVE_CURRENT_DATA &&
       !mLoadedDataFired) {
     DispatchAsyncEvent(NS_LITERAL_STRING("loadeddata"));
     mLoadedDataFired = true;
--- a/content/media/MediaDecoder.cpp
+++ b/content/media/MediaDecoder.cpp
@@ -937,30 +937,33 @@ void MediaDecoder::UpdatePlaybackRate()
     rate = std::max(rate, 10000u);
   }
   mResource->SetPlaybackRate(rate);
 }
 
 void MediaDecoder::NotifySuspendedStatusChanged()
 {
   MOZ_ASSERT(NS_IsMainThread());
-  if (mResource && mOwner) {
-    bool suspended = mResource->IsSuspendedByCache();
+  if (!mResource)
+    return;
+  bool suspended = mResource->IsSuspendedByCache();
+  if (mOwner) {
     mOwner->NotifySuspendedByCache(suspended);
     UpdateReadyStateForData();
   }
 }
 
 void MediaDecoder::NotifyBytesDownloaded()
 {
   MOZ_ASSERT(NS_IsMainThread());
   {
     ReentrantMonitorAutoEnter mon(GetReentrantMonitor());
     UpdatePlaybackRate();
   }
+  UpdateReadyStateForData();
   Progress(false);
 }
 
 void MediaDecoder::NotifyDownloadEnded(nsresult aStatus)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   DECODER_LOG("NotifyDownloadEnded, status=%x", aStatus);
@@ -974,20 +977,19 @@ void MediaDecoder::NotifyDownloadEnded(n
   }
 
   {
     ReentrantMonitorAutoEnter mon(GetReentrantMonitor());
     UpdatePlaybackRate();
   }
 
   if (NS_SUCCEEDED(aStatus)) {
+    UpdateReadyStateForData();
     // A final progress event will be fired by the MediaResource calling
     // DownloadSuspended on the element.
-    // Also NotifySuspendedStatusChanged() will be called to update readyState
-    // if download ended with success.
   } else if (aStatus != NS_BASE_STREAM_CLOSED) {
     NetworkError();
   }
 }
 
 void MediaDecoder::NotifyPrincipalChanged()
 {
   if (mOwner) {
--- a/content/media/MediaDecoderOwner.h
+++ b/content/media/MediaDecoderOwner.h
@@ -103,18 +103,16 @@ public:
 
   // The status of the next frame which might be available from the decoder
   enum NextFrameStatus {
     // The next frame of audio/video is available
     NEXT_FRAME_AVAILABLE,
     // The next frame of audio/video is unavailable because the decoder
     // is paused while it buffers up data
     NEXT_FRAME_UNAVAILABLE_BUFFERING,
-    // The next frame of audio/video is unavailable for the decoder is seeking.
-    NEXT_FRAME_UNAVAILABLE_SEEKING,
     // The next frame of audio/video is unavailable for some other reasons
     NEXT_FRAME_UNAVAILABLE,
     // The next frame is unavailable due to waiting for more Media Source
     // Extensions data to become available.
     NEXT_FRAME_WAIT_FOR_MSE_DATA,
     // Sentinel value
     NEXT_FRAME_UNINITIALIZED
   };
--- a/content/media/MediaDecoderStateMachine.cpp
+++ b/content/media/MediaDecoderStateMachine.cpp
@@ -1207,20 +1207,18 @@ void MediaDecoderStateMachine::ClearPosi
   AssertCurrentThreadInMonitor();
 
   mPositionChangeQueued = false;
 }
 
 MediaDecoderOwner::NextFrameStatus MediaDecoderStateMachine::GetNextFrameStatus()
 {
   ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
-  if (IsBuffering()) {
+  if (IsBuffering() || IsSeeking()) {
     return MediaDecoderOwner::NEXT_FRAME_UNAVAILABLE_BUFFERING;
-  } else if (IsSeeking()) {
-    return MediaDecoderOwner::NEXT_FRAME_UNAVAILABLE_SEEKING;
   } else if (HaveNextFrameData()) {
     return MediaDecoderOwner::NEXT_FRAME_AVAILABLE;
   }
   return MediaDecoderOwner::NEXT_FRAME_UNAVAILABLE;
 }
 
 static const char* const gMachineStateStr[] = {
   "NONE",
@@ -2883,20 +2881,16 @@ void MediaDecoderStateMachine::SetStartT
   mAudioStartTime = mStartTime;
   DECODER_LOG("Set media start time to %lld", mStartTime);
 }
 
 void MediaDecoderStateMachine::UpdateReadyState() {
   AssertCurrentThreadInMonitor();
 
   MediaDecoderOwner::NextFrameStatus nextFrameStatus = GetNextFrameStatus();
-  // FIXME: This optimization could result in inconsistent next frame status
-  // between the decoder and state machine when GetNextFrameStatus() is called
-  // by the decoder without updating mLastFrameStatus.
-  // Note not to regress bug 882027 when fixing this bug.
   if (nextFrameStatus == mLastFrameStatus) {
     return;
   }
   mLastFrameStatus = nextFrameStatus;
 
   /* This is a bit tricky. MediaDecoder::UpdateReadyStateForData will run on
    * the main thread and re-evaluate GetNextFrameStatus there, passing it to
    * HTMLMediaElement::UpdateReadyStateForData. It doesn't use the value of
--- a/content/media/omx/AudioOffloadPlayer.cpp
+++ b/content/media/omx/AudioOffloadPlayer.cpp
@@ -664,17 +664,17 @@ nsresult AudioOffloadPlayer::StopTimeUpd
   mTimeUpdateTimer = nullptr;
   return rv;
 }
 
 MediaDecoderOwner::NextFrameStatus AudioOffloadPlayer::GetNextFrameStatus()
 {
   MOZ_ASSERT(NS_IsMainThread());
   if (mPlayState == MediaDecoder::PLAY_STATE_SEEKING) {
-    return MediaDecoderOwner::NEXT_FRAME_UNAVAILABLE_SEEKING;
+    return MediaDecoderOwner::NEXT_FRAME_UNAVAILABLE_BUFFERING;
   } else if (mPlayState == MediaDecoder::PLAY_STATE_ENDED) {
     return MediaDecoderOwner::NEXT_FRAME_UNAVAILABLE;
   } else {
     return MediaDecoderOwner::NEXT_FRAME_AVAILABLE;
   }
 }
 
 void AudioOffloadPlayer::SendMetaDataToHal(sp<AudioSink>& aSink,