bug 975782 bring media resource loads out of background while they delay the load event r=cpearce
authorKarl Tomlinson <karlt+@karlt.net>
Tue, 23 Dec 2014 14:16:05 +1300
changeset 221413 edaf95c2be5776cfce40bc1dabb2d9c063e79a6f
parent 221412 745e52e4f7baf24fef485d3c9a053016c9af9f7b
child 221414 2393682aeb6ae35484ca7fd50f185dfa697bae87
push id53337
push userktomlinson@mozilla.com
push dateSat, 27 Dec 2014 04:34:02 +0000
treeherdermozilla-inbound@2393682aeb6a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerscpearce
bugs975782
milestone37.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 975782 bring media resource loads out of background while they delay the load event r=cpearce 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.
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
@@ -3747,25 +3747,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
@@ -1384,21 +1384,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
@@ -1575,43 +1575,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 { 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.
  *