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
--- 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