Bug 1411504. P3 - handle CacheClientSeek off the main thread for we will run Update() off the main thread.
MozReview-Commit-ID: 7eavgwkTXx0
--- 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);