Bug 1426056. P1 - move the decision of resuming download to another thread. draft
authorJW Wang <jwwang@mozilla.com>
Thu, 07 Dec 2017 15:43:36 +0800
changeset 712930 18561df2afa39cf3eb66d22369f1872fbfdc92ad
parent 712870 7c4579e705c4a3a3610183fe6f44affff3ad57ef
child 712931 632c38573ef7e4580b1071bae67f690ba8e7bdc8
child 713281 24a97ff28e1b244eb37866769eb963b94922d7a7
push id93495
push userjwwang@mozilla.com
push dateTue, 19 Dec 2017 06:36:21 +0000
bugs1426056
milestone59.0a1
Bug 1426056. P1 - move the decision of resuming download to another thread. So we won't access mStreamLength/mChannelOffset (which are protected by the cache monitor) on the main thread. MozReview-Commit-ID: 2pKEttZOfB9
dom/media/ChannelMediaResource.cpp
dom/media/MediaCache.cpp
dom/media/MediaCache.h
--- a/dom/media/ChannelMediaResource.cpp
+++ b/dom/media/ChannelMediaResource.cpp
@@ -685,34 +685,17 @@ ChannelMediaResource::Resume()
   dom::HTMLMediaElement* element = owner->GetMediaElement();
   MOZ_DIAGNOSTIC_ASSERT(element);
 
   if (mSuspendAgent.Resume()) {
     if (mChannel) {
       // Just wake up our existing channel
       element->DownloadResumed();
     } else {
-      int64_t totalLength = GetLength();
-      // If mOffset is at the end of the stream, then we shouldn't try to
-      // seek to it. The seek will fail and be wasted anyway. We can leave
-      // the channel dead; if the media cache wants to read some other data
-      // in the future, it will call CacheClientSeek itself which will reopen the
-      // channel.
-      if (totalLength < 0 || GetOffset() < totalLength) {
-        // There is (or may be) data to read, so start reading it.
-        // Need to recreate the channel.
-        int64_t offset =
-          mPendingSeekOffset != -1 ? mPendingSeekOffset : GetOffset();
-        mPendingSeekOffset = -1;
-        Seek(offset, false);
-        element->DownloadResumed();
-      } else {
-        // The channel remains dead. Do not notify DownloadResumed() which
-        // will leave the media element in NETWORK_LOADING state.
-      }
+      mCacheStream.NotifyResume();
     }
   }
 }
 
 nsresult
 ChannelMediaResource::RecreateChannel()
 {
   MOZ_DIAGNOSTIC_ASSERT(!mClosed);
--- a/dom/media/MediaCache.cpp
+++ b/dom/media/MediaCache.cpp
@@ -2295,16 +2295,41 @@ MediaCacheStream::NotifyClientSuspended(
         // mClientSuspended changes the decision of reading streams.
         mMediaCache->QueueUpdate(lock);
         UpdateDownloadStatistics(lock);
       }
     });
   OwnerThread()->Dispatch(r.forget());
 }
 
+void
+MediaCacheStream::NotifyResume()
+{
+  MOZ_ASSERT(NS_IsMainThread());
+
+  nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction(
+    "MediaCacheStream::NotifyResume",
+    [ this, client = RefPtr<ChannelMediaResource>(mClient) ]() {
+      AutoLock lock(mMediaCache->Monitor());
+      if (mClosed) {
+        return;
+      }
+      // Don't resume download if we are already at the end of the stream for
+      // seek will fail and be wasted anyway.
+      if (mStreamLength < 0 || mChannelOffset < mStreamLength) {
+        int64_t offset = mSeekTarget != -1 ? mSeekTarget : mChannelOffset;
+        mClient->CacheClientSeek(offset, false);
+        // DownloadResumed() will be notified when a new channel is opened.
+      }
+      // The channel remains dead. If we want to read some other data in the
+      // future, CacheClientSeek() will be called to reopen the channel.
+    });
+  OwnerThread()->Dispatch(r.forget());
+}
+
 MediaCacheStream::~MediaCacheStream()
 {
   NS_ASSERTION(NS_IsMainThread(), "Only call on main thread");
   NS_ASSERTION(!mPinCount, "Unbalanced Pin");
 
   if (mMediaCache) {
     NS_ASSERTION(mClosed, "Stream was not closed");
     mMediaCache->ReleaseStream(this);
--- a/dom/media/MediaCache.h
+++ b/dom/media/MediaCache.h
@@ -284,16 +284,19 @@ public:
   void NotifyDataEnded(uint32_t aLoadID,
                        nsresult aStatus,
                        bool aReopenOnError = false);
 
   // Notifies the stream that the suspend status of the client has changed.
   // Main thread only.
   void NotifyClientSuspended(bool aSuspended);
 
+  // Notifies the stream to resume download at the current offset.
+  void NotifyResume();
+
   // These methods can be called on any thread.
   // Cached blocks associated with this stream will not be evicted
   // while the stream is pinned.
   void Pin();
   void Unpin();
   // See comments above for NotifyDataStarted about how the length
   // can vary over time. Returns -1 if no length is known. Returns the
   // reported length if we haven't got any better information. If