Bug 975782 - Bring media resource loads out of background while they delay the load event. r=cpearce, a=sledru
authorKarl Tomlinson <karlt+@karlt.net>
Wed, 14 Jan 2015 00:41:00 -0500
changeset 242835 cdd335426a39
parent 242834 3956d52ad3f0
child 242836 3abc61cb0abd
push id4319
push userryanvm@gmail.com
push date2015-01-14 14:36 +0000
treeherdermozilla-beta@f6d5f2303fea [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerscpearce, sledru
bugs975782
milestone36.0
Bug 975782 - Bring media resource loads out of background while they delay the load event. r=cpearce, a=sledru This will happen after a stalled load doesn't delay the load event but such a load then delays the load event again when it receives progress. --HG-- extra : rebase_source : a04dd7416f86306cfc62aabba20fb30415572d98 Conflicts in dom/media/MediaResource.h resolved in favour of MOZ_OVERRIDE.
dom/html/HTMLMediaElement.cpp
dom/media/MediaDecoder.cpp
dom/media/MediaDecoder.h
dom/media/MediaResource.cpp
dom/media/MediaResource.h
--- a/dom/html/HTMLMediaElement.cpp
+++ b/dom/html/HTMLMediaElement.cpp
@@ -3730,25 +3730,24 @@ nsIContent* HTMLMediaElement::GetNextSou
 
 void HTMLMediaElement::ChangeDelayLoadStatus(bool aDelay)
 {
   if (mDelayingLoadEvent == aDelay)
     return;
 
   mDelayingLoadEvent = aDelay;
 
+  LOG(PR_LOG_DEBUG, ("%p ChangeDelayLoadStatus(%d) doc=0x%p", this, aDelay, mLoadBlockedDoc.get()));
+  if (mDecoder) {
+    mDecoder->SetLoadInBackground(!aDelay);
+  }
   if (aDelay) {
     mLoadBlockedDoc = OwnerDoc();
     mLoadBlockedDoc->BlockOnload();
-    LOG(PR_LOG_DEBUG, ("%p ChangeDelayLoadStatus(%d) doc=0x%p", this, aDelay, mLoadBlockedDoc.get()));
   } else {
-    if (mDecoder) {
-      mDecoder->MoveLoadsToBackground();
-    }
-    LOG(PR_LOG_DEBUG, ("%p ChangeDelayLoadStatus(%d) doc=0x%p", this, aDelay, mLoadBlockedDoc.get()));
     // mLoadBlockedDoc might be null due to GC unlinking
     if (mLoadBlockedDoc) {
       mLoadBlockedDoc->UnblockOnload(false);
       mLoadBlockedDoc = nullptr;
     }
   }
 
   // We changed mDelayingLoadEvent which can affect AddRemoveSelfReference
--- a/dom/media/MediaDecoder.cpp
+++ b/dom/media/MediaDecoder.cpp
@@ -1385,21 +1385,21 @@ void MediaDecoder::StartProgressUpdates(
   GetReentrantMonitor().AssertCurrentThreadIn();
   mIgnoreProgressData = false;
   if (mResource) {
     mResource->SetReadMode(MediaCacheStream::MODE_PLAYBACK);
     mDecoderPosition = mPlaybackPosition = mResource->Tell();
   }
 }
 
-void MediaDecoder::MoveLoadsToBackground()
+void MediaDecoder::SetLoadInBackground(bool aLoadInBackground)
 {
   MOZ_ASSERT(NS_IsMainThread());
   if (mResource) {
-    mResource->MoveLoadsToBackground();
+    mResource->SetLoadInBackground(aLoadInBackground);
   }
 }
 
 void MediaDecoder::UpdatePlaybackOffset(int64_t aOffset)
 {
   ReentrantMonitorAutoEnter mon(GetReentrantMonitor());
   mPlaybackPosition = std::max(aOffset, mPlaybackPosition);
 }
--- a/dom/media/MediaDecoder.h
+++ b/dom/media/MediaDecoder.h
@@ -642,22 +642,22 @@ public:
   // media element when it is restored from the bfcache, or when we need
   // to stop throttling the download. Call on the main thread only.
   // The download will only actually resume once as many Resume calls
   // have been made as Suspend calls. When aForceBuffering is true,
   // we force the decoder to go into buffering state before resuming
   // playback.
   virtual void Resume(bool aForceBuffering);
 
-  // Moves any existing channel loads into the background, so that they don't
-  // block the load event. This is called when we stop delaying the load
-  // event. Any new loads initiated (for example to seek) will also be in the
-  // background. Implementations of this must call MoveLoadsToBackground() on
-  // their MediaResource.
-  virtual void MoveLoadsToBackground();
+  // Moves any existing channel loads into or out of background. Background
+  // loads don't block the load event. This is called when we stop or restart
+  // delaying the load event. This also determines whether any new loads
+  // initiated (for example to seek) will be in the background.  This calls
+  // SetLoadInBackground() on mResource.
+  void SetLoadInBackground(bool aLoadInBackground);
 
   // Returns a weak reference to the media decoder owner.
   MediaDecoderOwner* GetMediaOwner() const;
 
   // Called by the state machine to notify the decoder that the duration
   // has changed.
   void DurationChanged();
 
--- a/dom/media/MediaResource.cpp
+++ b/dom/media/MediaResource.cpp
@@ -1572,43 +1572,49 @@ MediaResource::Create(MediaDecoder* aDec
   } else if (IsRtspURI(uri)) {
     resource = new RtspMediaResource(aDecoder, aChannel, uri, contentType);
   } else {
     resource = new ChannelMediaResource(aDecoder, aChannel, uri, contentType);
   }
   return resource.forget();
 }
 
-void BaseMediaResource::MoveLoadsToBackground() {
-  NS_ASSERTION(!mLoadInBackground, "Why are you calling this more than once?");
-  mLoadInBackground = true;
+void BaseMediaResource::SetLoadInBackground(bool aLoadInBackground) {
+  if (aLoadInBackground == mLoadInBackground) {
+    return;
+  }
+  mLoadInBackground = aLoadInBackground;
   if (!mChannel) {
     // No channel, resource is probably already loaded.
     return;
   }
 
   MediaDecoderOwner* owner = mDecoder->GetMediaOwner();
   if (!owner) {
-    NS_WARNING("Null owner in MediaResource::MoveLoadsToBackground()");
+    NS_WARNING("Null owner in MediaResource::SetLoadInBackground()");
     return;
   }
   dom::HTMLMediaElement* element = owner->GetMediaElement();
   if (!element) {
-    NS_WARNING("Null element in MediaResource::MoveLoadsToBackground()");
+    NS_WARNING("Null element in MediaResource::SetLoadInBackground()");
     return;
   }
 
   bool isPending = false;
   if (NS_SUCCEEDED(mChannel->IsPending(&isPending)) &&
       isPending) {
     nsLoadFlags loadFlags;
     DebugOnly<nsresult> rv = mChannel->GetLoadFlags(&loadFlags);
     NS_ASSERTION(NS_SUCCEEDED(rv), "GetLoadFlags() failed!");
 
-    loadFlags |= nsIRequest::LOAD_BACKGROUND;
+    if (aLoadInBackground) {
+      loadFlags |= nsIRequest::LOAD_BACKGROUND;
+    } else {
+      loadFlags &= ~nsIRequest::LOAD_BACKGROUND;
+    }
     ModifyLoadFlags(loadFlags);
   }
 }
 
 void BaseMediaResource::ModifyLoadFlags(nsLoadFlags aFlags)
 {
   nsCOMPtr<nsILoadGroup> loadGroup;
   DebugOnly<nsresult> rv = mChannel->GetLoadGroup(getter_AddRefs(loadGroup));
--- a/dom/media/MediaResource.h
+++ b/dom/media/MediaResource.h
@@ -310,20 +310,20 @@ public:
   // a blocked read which it handles by causing the listener to close
   // the pipe, as per the http case.
   //
   // The file strategy doesn't block for any great length of time so
   // is fine for a no-op cancel.
   virtual nsresult Seek(int32_t aWhence, int64_t aOffset) = 0;
   // Report the current offset in bytes from the start of the stream.
   virtual int64_t Tell() = 0;
-  // Moves any existing channel loads into the background, so that they don't
-  // block the load event. Any new loads initiated (for example to seek)
-  // will also be in the background.
-  virtual void MoveLoadsToBackground() {}
+  // Moves any existing channel loads into or out of background. Background
+  // loads don't block the load event. This also determines whether or not any
+  // new loads initiated (for example to seek) will be in the background.
+  virtual void SetLoadInBackground(bool aLoadInBackground) {}
   // Ensures that the value returned by IsSuspendedByCache below is up to date
   // (i.e. the cache has examined this stream at least once).
   virtual void EnsureCacheUpToDate() {}
 
   // These can be called on any thread.
   // Cached blocks associated with this stream will not be evicted
   // while the stream is pinned.
   virtual void Pin() = 0;
@@ -426,17 +426,17 @@ protected:
 
 private:
   void Destroy();
 };
 
 class BaseMediaResource : public MediaResource {
 public:
   virtual nsIURI* URI() const MOZ_OVERRIDE { return mURI; }
-  virtual void MoveLoadsToBackground();
+  virtual void SetLoadInBackground(bool aLoadInBackground) MOZ_OVERRIDE;
 
   virtual size_t SizeOfExcludingThis(
                   MallocSizeOf aMallocSizeOf) const MOZ_OVERRIDE
   {
     // Might be useful to track in the future:
     // - mChannel
     // - mURI (possibly owned, looks like just a ref from mChannel)
     // Not owned:
@@ -499,18 +499,20 @@ protected:
   // main thread only.
   nsCOMPtr<nsIURI> mURI;
 
   // Content-Type of the channel. This is copied from the nsIChannel when the
   // MediaResource is created. This is constant, so accessing from any thread
   // is safe.
   const nsAutoCString mContentType;
 
-  // True if MoveLoadsToBackground() has been called, i.e. the load event
-  // has been fired, and all channel loads will be in the background.
+  // True if SetLoadInBackground() has been called with
+  // aLoadInBackground = true, i.e. when the document load event is not
+  // blocked by this resource, and all channel loads will be in the
+  // background.
   bool mLoadInBackground;
 };
 
 /**
  * This is the MediaResource implementation that wraps Necko channels.
  * Much of its functionality is actually delegated to MediaCache via
  * an underlying MediaCacheStream.
  *