Bug 1297429 - Fix video suspend intermittent failures. r=jwwang draft
authorDan Glastonbury <dglastonbury@mozilla.com>
Thu, 25 Aug 2016 12:10:05 +1000
changeset 405277 8fced390d5fd56512c4a1a32c6642e476561138c
parent 404988 01748a2b1a463f24efd9cd8abad9ccfd76b037b8
child 529408 6d04341eca9a8ee357e9bf59d2e92464380649cb
push id27456
push userbmo:dglastonbury@mozilla.com
push dateThu, 25 Aug 2016 07:36:49 +0000
reviewersjwwang
bugs1297429
milestone51.0a1
Bug 1297429 - Fix video suspend intermittent failures. r=jwwang On Linux x64 PGO try, HTMLMediaElement was reliably invoking decoder->NotifyOwnerActivityChanged() after SetVisible(false) was called. This caused the pending suspend to be cancelled and the test waits for an event that never arrives. Fixed by adding 'forced hidden' to MediaDecoder that overrides the element visibility that comes from HTMLMediaElement. MozReview-Commit-ID: 5aRhxxZ5cZd
dom/html/HTMLMediaElement.cpp
dom/media/MediaDecoder.cpp
dom/media/MediaDecoder.h
--- a/dom/html/HTMLMediaElement.cpp
+++ b/dom/html/HTMLMediaElement.cpp
@@ -793,18 +793,17 @@ HTMLMediaElement::MozDumpDebugInfo()
 
 void
 HTMLMediaElement::SetVisible(bool aVisible)
 {
   if (!mDecoder) {
     return;
   }
 
-  mDecoder->NotifyOwnerActivityChanged(aVisible);
-
+  mDecoder->SetForcedHidden(!aVisible);
 }
 
 already_AddRefed<DOMMediaStream>
 HTMLMediaElement::GetSrcObject() const
 {
   NS_ASSERTION(!mSrcAttrStream || mSrcAttrStream->GetPlaybackStream(),
                "MediaStream should have been set up properly");
   RefPtr<DOMMediaStream> stream = mSrcAttrStream;
--- a/dom/media/MediaDecoder.cpp
+++ b/dom/media/MediaDecoder.cpp
@@ -503,16 +503,18 @@ MediaDecoder::MediaDecoder(MediaDecoderO
   , mFrameStats(new FrameStatistics())
   , mVideoFrameContainer(aOwner->GetVideoFrameContainer())
   , mPlaybackStatistics(new MediaChannelStatistics())
   , mPinnedForSeek(false)
   , mPausedForPlaybackRateNull(false)
   , mMinimizePreroll(false)
   , mMediaTracksConstructed(false)
   , mFiredMetadataLoaded(false)
+  , mElementVisible(!aOwner->IsHidden())
+  , mForcedHidden(false)
   , mIsDormant(false)
   , mIsHeuristicDormantSupported(
       Preferences::GetBool("media.decoder.heuristic.dormant.enabled", false))
   , mHeuristicDormantTimeout(
       Preferences::GetInt("media.decoder.heuristic.dormant.timeout",
                           DEFAULT_HEURISTIC_DORMANT_TIMEOUT_MSECS))
   , mIsHeuristicDormant(false)
   , INIT_MIRROR(mStateMachineIsShutdown, true)
@@ -1358,17 +1360,26 @@ MediaDecoder::DurationChanged()
     Seek(mDuration, SeekTarget::Accurate);
   }
 }
 
 void
 MediaDecoder::SetElementVisibility(bool aIsVisible)
 {
   MOZ_ASSERT(NS_IsMainThread());
-  mIsVisible = aIsVisible;
+  mElementVisible = aIsVisible;
+  mIsVisible = !mForcedHidden && mElementVisible;
+}
+
+void
+MediaDecoder::SetForcedHidden(bool aForcedHidden)
+{
+  MOZ_ASSERT(NS_IsMainThread());
+  mForcedHidden = aForcedHidden;
+  SetElementVisibility(mElementVisible);
 }
 
 void
 MediaDecoder::UpdateEstimatedMediaDuration(int64_t aDuration)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   if (mPlayState <= PLAY_STATE_LOADING) {
--- a/dom/media/MediaDecoder.h
+++ b/dom/media/MediaDecoder.h
@@ -373,16 +373,20 @@ private:
   virtual bool CanPlayThrough();
 
   void SetAudioChannel(dom::AudioChannel aChannel) { mAudioChannel = aChannel; }
   dom::AudioChannel GetAudioChannel() { return mAudioChannel; }
 
   // Called from HTMLMediaElement when owner document activity changes
   virtual void SetElementVisibility(bool aIsVisible);
 
+  // Force override the visible state to hidden.
+  // Called from HTMLMediaElement when testing of video decode suspend from mochitests.
+  void SetForcedHidden(bool aForcedHidden);
+
   /******
    * The following methods must only be called on the main
    * thread.
    ******/
 
   // Change to a new play state. This updates the mState variable and
   // notifies any thread blocking on this object's monitor of the
   // change. Call on the main thread only.
@@ -698,16 +702,22 @@ protected:
 
   // True if we've already fired metadataloaded.
   bool mFiredMetadataLoaded;
 
   // Stores media info, including info of audio tracks and video tracks, should
   // only be accessed from main thread.
   nsAutoPtr<MediaInfo> mInfo;
 
+  // Tracks the visiblity status from HTMLMediaElement
+  bool mElementVisible;
+
+  // If true, forces the decoder to be considered hidden.
+  bool mForcedHidden;
+
   // True if MediaDecoder is in dormant state.
   bool mIsDormant;
 
   // True if heuristic dormant is supported.
   const bool mIsHeuristicDormantSupported;
 
   // Timeout ms of heuristic dormant timer.
   const int mHeuristicDormantTimeout;