Bug 1411504. P3 - handle CacheClientSeek off the main thread for we will run Update() off the main thread. draft
authorJW Wang <jwwang@mozilla.com>
Tue, 24 Oct 2017 09:23:12 +0800
changeset 686105 0038aba0babf1e120552b9e55770f072ea7f0436
parent 686104 a827191f9e551b405c0ba5ea902c649960f4f1c6
child 686106 7ca7d23fe3c7bba124556333b328e42b78414b93
push id86100
push userjwwang@mozilla.com
push dateWed, 25 Oct 2017 13:23:40 +0000
bugs1411504
milestone58.0a1
Bug 1411504. P3 - handle CacheClientSeek off the main thread for we will run Update() off the main thread. MozReview-Commit-ID: 7eavgwkTXx0
dom/media/ChannelMediaResource.cpp
dom/media/ChannelMediaResource.h
dom/media/MediaCache.cpp
--- a/dom/media/ChannelMediaResource.cpp
+++ b/dom/media/ChannelMediaResource.cpp
@@ -384,17 +384,17 @@ ChannelMediaResource::OnStopRequest(nsIR
       aStatus != NS_BINDING_ABORTED &&
       (GetOffset() == 0 || (GetLength() > 0 && GetOffset() != GetLength() &&
                             mCacheStream.IsTransportSeekable()))) {
     // If the stream did close normally, restart the channel if we're either
     // at the start of the resource, or if the server is seekable and we're
     // not at the end of stream. We don't restart the stream if we're at the
     // end because not all web servers handle this case consistently; see:
     // https://bugzilla.mozilla.org/show_bug.cgi?id=1373618#c36
-    nsresult rv = CacheClientSeek(GetOffset(), false);
+    nsresult rv = Seek(GetOffset(), false);
     if (NS_SUCCEEDED(rv)) {
       return rv;
     }
     // If the reopen/reseek fails, just fall through and treat this
     // error as fatal.
   }
 
   mCacheStream.NotifyDataEnded(aStatus);
@@ -848,22 +848,20 @@ ChannelMediaResource::UpdatePrincipal()
 void
 ChannelMediaResource::CacheClientNotifySuspendedStatusChanged()
 {
   NS_ASSERTION(NS_IsMainThread(), "Don't call on non-main thread");
   mCallback->NotifySuspendedStatusChanged(IsSuspendedByCache());
 }
 
 nsresult
-ChannelMediaResource::CacheClientSeek(int64_t aOffset, bool aResume)
+ChannelMediaResource::Seek(int64_t aOffset, bool aResume)
 {
-  NS_ASSERTION(NS_IsMainThread(), "Don't call on non-main thread");
-
-  LOG("CacheClientSeek requested for aOffset [%" PRId64 "] for decoder [%p]",
-      aOffset, mCallback.get());
+  MOZ_ASSERT(NS_IsMainThread());
+  LOG("Seek requested for aOffset [%" PRId64 "]", aOffset);
 
   CloseChannel();
 
   if (aResume) {
     mSuspendAgent.Resume();
   }
 
   // Don't create a new channel if we are still suspended. The channel will
@@ -873,16 +871,33 @@ ChannelMediaResource::CacheClientSeek(in
   }
 
   nsresult rv = RecreateChannel();
   NS_ENSURE_SUCCESS(rv, rv);
 
   return OpenChannel(aOffset);
 }
 
+void
+ChannelMediaResource::CacheClientSeek(int64_t aOffset, bool aResume)
+{
+  RefPtr<ChannelMediaResource> self = this;
+  nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction(
+    "ChannelMediaResource::Seek", [self, aOffset, aResume]() {
+      nsresult rv = self->Seek(aOffset, aResume);
+      if (NS_FAILED(rv)) {
+        // Close the streams that failed due to error. This will cause all
+        // client Read and Seek operations on those streams to fail. Blocked
+        // Reads will also be woken up.
+        self->Close();
+      }
+    });
+  mCallback->AbstractMainThread()->Dispatch(r.forget());
+}
+
 nsresult
 ChannelMediaResource::CacheClientSuspend()
 {
   Suspend(false);
   return NS_OK;
 }
 
 nsresult
--- a/dom/media/ChannelMediaResource.h
+++ b/dom/media/ChannelMediaResource.h
@@ -96,18 +96,17 @@ public:
   void CacheClientNotifySuspendedStatusChanged();
 
   // These are called on the main thread by MediaCache. These shouldn't block,
   // but they may grab locks --- the media cache is not holding its lock
   // when these are called.
   // Start a new load at the given aOffset. The old load is cancelled
   // and no more data from the old load will be notified via
   // MediaCacheStream::NotifyDataReceived/Ended.
-  // This can fail.
-  nsresult CacheClientSeek(int64_t aOffset, bool aResume);
+  void CacheClientSeek(int64_t aOffset, bool aResume);
   // Suspend the current load since data is currently not wanted
   nsresult CacheClientSuspend();
   // Resume the current load since data is wanted again
   nsresult CacheClientResume();
 
   bool IsSuspended();
 
   void ThrottleReadahead(bool bThrottle) override;
@@ -191,16 +190,18 @@ public:
     const int64_t mOffset;
     const uint32_t mLoadID;
   };
   friend class Listener;
 
   nsresult GetCachedRanges(MediaByteRangeSet& aRanges) override;
 
 protected:
+  nsresult Seek(int64_t aOffset, bool aResume);
+
   bool IsSuspendedByCache();
   // These are called on the main thread by Listener.
   nsresult OnStartRequest(nsIRequest* aRequest, int64_t aRequestOffset);
   nsresult OnStopRequest(nsIRequest* aRequest, nsresult aStatus);
   nsresult OnDataAvailable(uint32_t aLoadID,
                            nsIInputStream* aStream,
                            uint32_t aCount);
   nsresult OnChannelRedirect(nsIChannel* aOld,
--- a/dom/media/MediaCache.cpp
+++ b/dom/media/MediaCache.cpp
@@ -1492,25 +1492,25 @@ MediaCache::Update()
         break;
       default:
         break;
     }
   }
 
   for (uint32_t i = 0; i < mStreams.Length(); ++i) {
     MediaCacheStream* stream = mStreams[i];
-    nsresult rv;
+    nsresult rv = NS_OK;
     switch (actions[i].mTag) {
       case StreamAction::SEEK:
         LOG("Stream %p CacheSeek to %" PRId64 " (resume=%d)",
             stream,
             actions[i].mSeekTarget,
             actions[i].mResume);
-        rv = stream->mClient->CacheClientSeek(actions[i].mSeekTarget,
-                                              actions[i].mResume);
+        stream->mClient->CacheClientSeek(actions[i].mSeekTarget,
+                                         actions[i].mResume);
         break;
       case StreamAction::RESUME:
         LOG("Stream %p Resumed", stream);
         rv = stream->mClient->CacheClientResume();
         QueueSuspendedStatusUpdate(stream->mResourceID);
         break;
       case StreamAction::SUSPEND:
         LOG("Stream %p Suspended", stream);