Bug 1371882 - MediaCacheStream accesses its MediaCache through a member pointer - r?cpearce draft
authorGerald Squelart <gsquelart@mozilla.com>
Thu, 08 Jun 2017 17:30:40 +1200
changeset 593023 cb68fd5a14f589053a90d1f5264e2e49b9dab8a8
parent 593022 9b4cf5428bbcd8fd506fdc4702c612c816d93cef
child 593024 a275e44391cb01245e5dcbbd4a76ee6d41ae63bb
push id63579
push usergsquelart@mozilla.com
push dateTue, 13 Jun 2017 05:16:04 +0000
reviewerscpearce
bugs1371882
milestone56.0a1
Bug 1371882 - MediaCacheStream accesses its MediaCache through a member pointer - r?cpearce MozReview-Commit-ID: CM1rXqAc4FT
dom/media/MediaCache.cpp
dom/media/MediaCache.h
--- a/dom/media/MediaCache.cpp
+++ b/dom/media/MediaCache.cpp
@@ -424,17 +424,18 @@ MediaCacheFlusher::Observe(nsISupports *
     }
     return NS_OK;
   }
   return NS_OK;
 }
 
 MediaCacheStream::MediaCacheStream(ChannelMediaResource* aClient,
                                    bool aIsPrivateBrowsing)
-  : mClient(aClient),
+  : mMediaCache(nullptr),
+    mClient(aClient),
     mInitialized(false),
     mHasHadUpdate(false),
     mClosed(false),
     mDidNotifyDataEnded(false),
     mResourceID(0),
     mIsTransportSeekable(false),
     mCacheSuspended(false),
     mChannelEnded(false),
@@ -1792,26 +1793,26 @@ MediaCacheStream::NotifyDataLength(int64
     LOG("MediaCacheStream::NotifyDataLength(this=%p) "
         "MEDIACACHESTREAM_NOTIFIED_LENGTH=%" PRIu32,
         this,
         length);
     Telemetry::Accumulate(
       Telemetry::HistogramID::MEDIACACHESTREAM_NOTIFIED_LENGTH, length);
   }
 
-  ReentrantMonitorAutoEnter mon(gMediaCache->GetReentrantMonitor());
+  ReentrantMonitorAutoEnter mon(mMediaCache->GetReentrantMonitor());
   mStreamLength = aLength;
 }
 
 void
 MediaCacheStream::NotifyDataStarted(int64_t aOffset)
 {
   NS_ASSERTION(NS_IsMainThread(), "Only call on main thread");
 
-  ReentrantMonitorAutoEnter mon(gMediaCache->GetReentrantMonitor());
+  ReentrantMonitorAutoEnter mon(mMediaCache->GetReentrantMonitor());
   NS_WARNING_ASSERTION(aOffset == mChannelOffset,
                        "Server is giving us unexpected offset");
   MOZ_ASSERT(aOffset >= 0);
   mChannelOffset = aOffset;
   if (mStreamLength >= 0) {
     // If we started reading at a certain offset, then for sure
     // the stream is at least that long.
     mStreamLength = std::max(mStreamLength, mChannelOffset);
@@ -1835,25 +1836,25 @@ MediaCacheStream::NotifyDataReceived(int
   }
 
   // Update principals before putting the data in the cache. This is important,
   // we want to make sure all principals are updated before any consumer
   // can see the new data.
   // We do this without holding the cache monitor, in case the client wants
   // to do something that takes a lock.
   {
-    MediaCache::ResourceStreamIterator iter(*gMediaCache, mResourceID);
+    MediaCache::ResourceStreamIterator iter(*mMediaCache, mResourceID);
     while (MediaCacheStream* stream = iter.Next()) {
       if (stream->UpdatePrincipal(aPrincipal)) {
         stream->mClient->CacheClientNotifyPrincipalChanged();
       }
     }
   }
 
-  ReentrantMonitorAutoEnter mon(gMediaCache->GetReentrantMonitor());
+  ReentrantMonitorAutoEnter mon(mMediaCache->GetReentrantMonitor());
   int64_t size = aSize;
   const char* data = aData;
 
   LOG("Stream %p DataReceived at %" PRId64 " count=%" PRId64,
       this, mChannelOffset, aSize);
 
   // We process the data one block (or part of a block) at a time
   while (size > 0) {
@@ -1871,27 +1872,27 @@ MediaCacheStream::NotifyDataReceived(int
       ? MODE_METADATA : MODE_PLAYBACK;
 
     if (blockOffset + chunkSize == BLOCK_SIZE) {
       // We have a whole block now to write it out.
       auto data1 = MakeSpan<const uint8_t>(
         mPartialBlockBuffer.get(), blockOffset);
       auto data2 = MakeSpan<const uint8_t>(
         reinterpret_cast<const uint8_t*>(data), chunkSize);
-      gMediaCache->AllocateAndWriteBlock(this, mode, data1, data2);
+      mMediaCache->AllocateAndWriteBlock(this, mode, data1, data2);
     } else {
       memcpy(mPartialBlockBuffer.get() + blockOffset, data, chunkSize);
     }
 
     mChannelOffset += chunkSize;
     size -= chunkSize;
     data += chunkSize;
   }
 
-  MediaCache::ResourceStreamIterator iter(*gMediaCache, mResourceID);
+  MediaCache::ResourceStreamIterator iter(*mMediaCache, mResourceID);
   while (MediaCacheStream* stream = iter.Next()) {
     if (stream->mStreamLength >= 0) {
       // The stream is at least as long as what we've read
       stream->mStreamLength = std::max(stream->mStreamLength, mChannelOffset);
     }
     stream->mClient->CacheClientNotifyDataReceived();
   }
 
@@ -1913,17 +1914,17 @@ MediaCacheStream::FlushPartialBlockInter
         "mStreamOffset [%" PRId64 "] mChannelOffset[%"
         PRId64 "] mStreamLength [%" PRId64 "] notifying: [%s]",
         this, blockOffset, mStreamOffset, mChannelOffset, mStreamLength,
         aNotifyAll ? "yes" : "no");
 
     // Write back the partial block
     memset(mPartialBlockBuffer.get() + blockOffset, 0, BLOCK_SIZE - blockOffset);
     auto data = MakeSpan<const uint8_t>(mPartialBlockBuffer.get(), BLOCK_SIZE);
-    gMediaCache->AllocateAndWriteBlock(this,
+    mMediaCache->AllocateAndWriteBlock(this,
       mMetadataInPartialBlockBuffer ? MODE_METADATA : MODE_PLAYBACK, data);
   }
 
   // |mChannelOffset == 0| means download ends with no bytes received.
   // We should also wake up those readers who are waiting for data
   // that will never come.
   if ((blockOffset > 0 || mChannelOffset == 0) && aNotifyAll) {
     // Wake up readers who may be waiting for this data
@@ -1931,48 +1932,48 @@ MediaCacheStream::FlushPartialBlockInter
   }
 }
 
 void
 MediaCacheStream::FlushPartialBlock()
 {
   NS_ASSERTION(NS_IsMainThread(), "Only call on main thread");
 
-  ReentrantMonitorAutoEnter mon(gMediaCache->GetReentrantMonitor());
+  ReentrantMonitorAutoEnter mon(mMediaCache->GetReentrantMonitor());
 
   // Write the current partial block to memory.
   // Note: This writes a full block, so if data is not at the end of the
   // stream, the decoder must subsequently choose correct start and end offsets
   // for reading/seeking.
   FlushPartialBlockInternal(false, mon);
 
-  gMediaCache->QueueUpdate();
+  mMediaCache->QueueUpdate();
 }
 
 void
 MediaCacheStream::NotifyDataEnded(nsresult aStatus)
 {
   NS_ASSERTION(NS_IsMainThread(), "Only call on main thread");
 
-  ReentrantMonitorAutoEnter mon(gMediaCache->GetReentrantMonitor());
+  ReentrantMonitorAutoEnter mon(mMediaCache->GetReentrantMonitor());
 
   if (NS_FAILED(aStatus)) {
     // Disconnect from other streams sharing our resource, since they
     // should continue trying to load. Our load might have been deliberately
     // canceled and that shouldn't affect other streams.
-    mResourceID = gMediaCache->AllocateResourceID();
+    mResourceID = mMediaCache->AllocateResourceID();
   }
 
   // It is prudent to update channel/cache status before calling
   // CacheClientNotifyDataEnded() which will read |mChannelEnded|.
   FlushPartialBlockInternal(true, mon);
   mChannelEnded = true;
-  gMediaCache->QueueUpdate();
+  mMediaCache->QueueUpdate();
 
-  MediaCache::ResourceStreamIterator iter(*gMediaCache, mResourceID);
+  MediaCache::ResourceStreamIterator iter(*mMediaCache, mResourceID);
   while (MediaCacheStream* stream = iter.Next()) {
     if (NS_SUCCEEDED(aStatus)) {
       // We read the whole stream, so remember the true length
       stream->mStreamLength = mChannelOffset;
     }
     if (!stream->mDidNotifyDataEnded) {
       stream->mDidNotifyDataEnded = true;
       stream->mNotifyDataEndedStatus = aStatus;
@@ -1980,66 +1981,66 @@ MediaCacheStream::NotifyDataEnded(nsresu
     }
   }
 }
 
 void
 MediaCacheStream::NotifyChannelRecreated()
 {
   NS_ASSERTION(NS_IsMainThread(), "Only call on main thread");
-  ReentrantMonitorAutoEnter mon(gMediaCache->GetReentrantMonitor());
+  ReentrantMonitorAutoEnter mon(mMediaCache->GetReentrantMonitor());
   mChannelEnded = false;
   mDidNotifyDataEnded = false;
 }
 
 MediaCacheStream::~MediaCacheStream()
 {
   NS_ASSERTION(NS_IsMainThread(), "Only call on main thread");
   NS_ASSERTION(!mPinCount, "Unbalanced Pin");
 
-  if (gMediaCache) {
+  if (mMediaCache) {
     NS_ASSERTION(mClosed, "Stream was not closed");
-    gMediaCache->ReleaseStream(this);
-    gMediaCache->MaybeShutdown();
+    mMediaCache->ReleaseStream(this);
+    mMediaCache->MaybeShutdown();
   }
 
   uint32_t lengthKb = uint32_t(
     std::min(std::max(mStreamLength, int64_t(0)) / 1024, int64_t(UINT32_MAX)));
   LOG("MediaCacheStream::~MediaCacheStream(this=%p) "
       "MEDIACACHESTREAM_LENGTH_KB=%" PRIu32,
       this,
       lengthKb);
   Telemetry::Accumulate(Telemetry::HistogramID::MEDIACACHESTREAM_LENGTH_KB,
                         lengthKb);
 }
 
 void
 MediaCacheStream::SetTransportSeekable(bool aIsTransportSeekable)
 {
-  ReentrantMonitorAutoEnter mon(gMediaCache->GetReentrantMonitor());
+  ReentrantMonitorAutoEnter mon(mMediaCache->GetReentrantMonitor());
   NS_ASSERTION(mIsTransportSeekable || aIsTransportSeekable ||
                mChannelOffset == 0, "channel offset must be zero when we become non-seekable");
   mIsTransportSeekable = aIsTransportSeekable;
   // Queue an Update since we may change our strategy for dealing
   // with this stream
-  gMediaCache->QueueUpdate();
+  mMediaCache->QueueUpdate();
 }
 
 bool
 MediaCacheStream::IsTransportSeekable()
 {
-  ReentrantMonitorAutoEnter mon(gMediaCache->GetReentrantMonitor());
+  ReentrantMonitorAutoEnter mon(mMediaCache->GetReentrantMonitor());
   return mIsTransportSeekable;
 }
 
 bool
 MediaCacheStream::AreAllStreamsForResourceSuspended()
 {
-  ReentrantMonitorAutoEnter mon(gMediaCache->GetReentrantMonitor());
-  MediaCache::ResourceStreamIterator iter(*gMediaCache, mResourceID);
+  ReentrantMonitorAutoEnter mon(mMediaCache->GetReentrantMonitor());
+  MediaCache::ResourceStreamIterator iter(*mMediaCache, mResourceID);
   // Look for a stream that's able to read the data we need
   int64_t dataOffset = -1;
   while (MediaCacheStream* stream = iter.Next()) {
     if (stream->mCacheSuspended || stream->mChannelEnded || stream->mClosed) {
       continue;
     }
     if (dataOffset < 0) {
       dataOffset = GetCachedDataEndInternal(mStreamOffset);
@@ -2057,104 +2058,104 @@ MediaCacheStream::AreAllStreamsForResour
 void
 MediaCacheStream::Close()
 {
   NS_ASSERTION(NS_IsMainThread(), "Only call on main thread");
 
   if (!mInitialized)
     return;
 
-  ReentrantMonitorAutoEnter mon(gMediaCache->GetReentrantMonitor());
+  ReentrantMonitorAutoEnter mon(mMediaCache->GetReentrantMonitor());
   CloseInternal(mon);
   // Queue an Update since we may have created more free space. Don't do
   // it from CloseInternal since that gets called by Update() itself
   // sometimes, and we try to not to queue updates from Update().
-  gMediaCache->QueueUpdate();
+  mMediaCache->QueueUpdate();
 }
 
 void
 MediaCacheStream::EnsureCacheUpdate()
 {
   if (mHasHadUpdate)
     return;
-  gMediaCache->Update();
+  mMediaCache->Update();
 }
 
 void
 MediaCacheStream::CloseInternal(ReentrantMonitorAutoEnter& aReentrantMonitor)
 {
   NS_ASSERTION(NS_IsMainThread(), "Only call on main thread");
 
   if (mClosed)
     return;
   mClosed = true;
   // Closing a stream will change the return value of
   // MediaCacheStream::AreAllStreamsForResourceSuspended as well as
   // ChannelMediaResource::IsSuspendedByCache. Let's notify it.
-  gMediaCache->QueueSuspendedStatusUpdate(mResourceID);
-  gMediaCache->ReleaseStreamBlocks(this);
+  mMediaCache->QueueSuspendedStatusUpdate(mResourceID);
+  mMediaCache->ReleaseStreamBlocks(this);
   // Wake up any blocked readers
   aReentrantMonitor.NotifyAll();
 }
 
 void
 MediaCacheStream::Pin()
 {
-  ReentrantMonitorAutoEnter mon(gMediaCache->GetReentrantMonitor());
+  ReentrantMonitorAutoEnter mon(mMediaCache->GetReentrantMonitor());
   ++mPinCount;
   // Queue an Update since we may no longer want to read more into the
   // cache, if this stream's block have become non-evictable
-  gMediaCache->QueueUpdate();
+  mMediaCache->QueueUpdate();
 }
 
 void
 MediaCacheStream::Unpin()
 {
-  ReentrantMonitorAutoEnter mon(gMediaCache->GetReentrantMonitor());
+  ReentrantMonitorAutoEnter mon(mMediaCache->GetReentrantMonitor());
   NS_ASSERTION(mPinCount > 0, "Unbalanced Unpin");
   --mPinCount;
   // Queue an Update since we may be able to read more into the
   // cache, if this stream's block have become evictable
-  gMediaCache->QueueUpdate();
+  mMediaCache->QueueUpdate();
 }
 
 int64_t
 MediaCacheStream::GetLength()
 {
-  ReentrantMonitorAutoEnter mon(gMediaCache->GetReentrantMonitor());
+  ReentrantMonitorAutoEnter mon(mMediaCache->GetReentrantMonitor());
   return mStreamLength;
 }
 
 int64_t
 MediaCacheStream::GetNextCachedData(int64_t aOffset)
 {
-  ReentrantMonitorAutoEnter mon(gMediaCache->GetReentrantMonitor());
+  ReentrantMonitorAutoEnter mon(mMediaCache->GetReentrantMonitor());
   return GetNextCachedDataInternal(aOffset);
 }
 
 int64_t
 MediaCacheStream::GetCachedDataEnd(int64_t aOffset)
 {
-  ReentrantMonitorAutoEnter mon(gMediaCache->GetReentrantMonitor());
+  ReentrantMonitorAutoEnter mon(mMediaCache->GetReentrantMonitor());
   return GetCachedDataEndInternal(aOffset);
 }
 
 bool
 MediaCacheStream::IsDataCachedToEndOfStream(int64_t aOffset)
 {
-  ReentrantMonitorAutoEnter mon(gMediaCache->GetReentrantMonitor());
+  ReentrantMonitorAutoEnter mon(mMediaCache->GetReentrantMonitor());
   if (mStreamLength < 0)
     return false;
   return GetCachedDataEndInternal(aOffset) >= mStreamLength;
 }
 
 int64_t
 MediaCacheStream::GetCachedDataEndInternal(int64_t aOffset)
 {
-  gMediaCache->GetReentrantMonitor().AssertCurrentThreadIn();
+  mMediaCache->GetReentrantMonitor().AssertCurrentThreadIn();
   uint32_t startBlockIndex = aOffset/BLOCK_SIZE;
   uint32_t blockIndex = startBlockIndex;
   while (blockIndex < mBlocks.Length() && mBlocks[blockIndex] != -1) {
     ++blockIndex;
   }
   int64_t result = blockIndex*BLOCK_SIZE;
   if (blockIndex == mChannelOffset/BLOCK_SIZE) {
     // The block containing mChannelOffset may be partially read but not
@@ -2167,17 +2168,17 @@ MediaCacheStream::GetCachedDataEndIntern
     result = std::min(result, mStreamLength);
   }
   return std::max(result, aOffset);
 }
 
 int64_t
 MediaCacheStream::GetNextCachedDataInternal(int64_t aOffset)
 {
-  gMediaCache->GetReentrantMonitor().AssertCurrentThreadIn();
+  mMediaCache->GetReentrantMonitor().AssertCurrentThreadIn();
   if (aOffset == mStreamLength)
     return -1;
 
   uint32_t startBlockIndex = aOffset/BLOCK_SIZE;
   uint32_t channelBlockIndex = mChannelOffset/BLOCK_SIZE;
 
   if (startBlockIndex == channelBlockIndex &&
       aOffset < mChannelOffset) {
@@ -2214,40 +2215,40 @@ MediaCacheStream::GetNextCachedDataInter
 
   NS_NOTREACHED("Should return in loop");
   return -1;
 }
 
 void
 MediaCacheStream::SetReadMode(ReadMode aMode)
 {
-  ReentrantMonitorAutoEnter mon(gMediaCache->GetReentrantMonitor());
+  ReentrantMonitorAutoEnter mon(mMediaCache->GetReentrantMonitor());
   if (aMode == mCurrentMode)
     return;
   mCurrentMode = aMode;
-  gMediaCache->QueueUpdate();
+  mMediaCache->QueueUpdate();
 }
 
 void
 MediaCacheStream::SetPlaybackRate(uint32_t aBytesPerSecond)
 {
   NS_ASSERTION(aBytesPerSecond > 0, "Zero playback rate not allowed");
-  ReentrantMonitorAutoEnter mon(gMediaCache->GetReentrantMonitor());
+  ReentrantMonitorAutoEnter mon(mMediaCache->GetReentrantMonitor());
   if (aBytesPerSecond == mPlaybackBytesPerSecond)
     return;
   mPlaybackBytesPerSecond = aBytesPerSecond;
-  gMediaCache->QueueUpdate();
+  mMediaCache->QueueUpdate();
 }
 
 nsresult
 MediaCacheStream::Seek(int32_t aWhence, int64_t aOffset)
 {
   NS_ASSERTION(!NS_IsMainThread(), "Don't call on main thread");
 
-  ReentrantMonitorAutoEnter mon(gMediaCache->GetReentrantMonitor());
+  ReentrantMonitorAutoEnter mon(mMediaCache->GetReentrantMonitor());
   if (mClosed)
     return NS_ERROR_FAILURE;
 
   int64_t oldOffset = mStreamOffset;
   int64_t newOffset = mStreamOffset;
   switch (aWhence) {
   case PR_SEEK_END:
     if (mStreamLength < 0)
@@ -2265,47 +2266,47 @@ MediaCacheStream::Seek(int32_t aWhence, 
     return NS_ERROR_FAILURE;
   }
 
   if (newOffset < 0)
     return NS_ERROR_FAILURE;
   mStreamOffset = newOffset;
 
   LOG("Stream %p Seek to %" PRId64, this, mStreamOffset);
-  gMediaCache->NoteSeek(this, oldOffset);
+  mMediaCache->NoteSeek(this, oldOffset);
 
-  gMediaCache->QueueUpdate();
+  mMediaCache->QueueUpdate();
   return NS_OK;
 }
 
 void
 MediaCacheStream::ThrottleReadahead(bool bThrottle)
 {
   MOZ_ASSERT(NS_IsMainThread());
   if (mThrottleReadahead != bThrottle) {
     LOGI("Stream %p ThrottleReadahead %d", this, bThrottle);
     mThrottleReadahead = bThrottle;
-    ReentrantMonitorAutoEnter mon(gMediaCache->GetReentrantMonitor());
-    gMediaCache->QueueUpdate();
+    ReentrantMonitorAutoEnter mon(mMediaCache->GetReentrantMonitor());
+    mMediaCache->QueueUpdate();
   }
 }
 
 int64_t
 MediaCacheStream::Tell()
 {
-  ReentrantMonitorAutoEnter mon(gMediaCache->GetReentrantMonitor());
+  ReentrantMonitorAutoEnter mon(mMediaCache->GetReentrantMonitor());
   return mStreamOffset;
 }
 
 nsresult
 MediaCacheStream::Read(char* aBuffer, uint32_t aCount, uint32_t* aBytes)
 {
   NS_ASSERTION(!NS_IsMainThread(), "Don't call on main thread");
 
-  ReentrantMonitorAutoEnter mon(gMediaCache->GetReentrantMonitor());
+  ReentrantMonitorAutoEnter mon(mMediaCache->GetReentrantMonitor());
   if (mClosed)
     return NS_ERROR_FAILURE;
 
   // Cache the offset in case it is changed again when we are waiting for the
   // monitor to be notified to avoid reading at the wrong position.
   auto streamOffset = mStreamOffset;
 
   uint32_t count = 0;
@@ -2337,17 +2338,17 @@ MediaCacheStream::Read(char* aBuffer, ui
         break;
       }
 
       // See if the data is available in the partial cache block of any
       // stream reading this resource. We need to do this in case there is
       // another stream with this resource that has all the data to the end of
       // the stream but the data doesn't end on a block boundary.
       MediaCacheStream* streamWithPartialBlock = nullptr;
-      MediaCache::ResourceStreamIterator iter(*gMediaCache, mResourceID);
+      MediaCache::ResourceStreamIterator iter(*mMediaCache, mResourceID);
       while (MediaCacheStream* stream = iter.Next()) {
         if (uint32_t(stream->mChannelOffset/BLOCK_SIZE) == streamBlock &&
             streamOffset < stream->mChannelOffset) {
           streamWithPartialBlock = stream;
           break;
         }
       }
       if (streamWithPartialBlock) {
@@ -2373,67 +2374,67 @@ MediaCacheStream::Read(char* aBuffer, ui
       if (mClosed) {
         // We may have successfully read some data, but let's just throw
         // that out.
         return NS_ERROR_FAILURE;
       }
       continue;
     }
 
-    gMediaCache->NoteBlockUsage(this, cacheBlock, streamOffset, mCurrentMode, TimeStamp::Now());
+    mMediaCache->NoteBlockUsage(this, cacheBlock, streamOffset, mCurrentMode, TimeStamp::Now());
 
     int64_t offset = cacheBlock*BLOCK_SIZE + offsetInStreamBlock;
     int32_t bytes;
     MOZ_ASSERT(size >= 0 && size <= INT32_MAX, "Size out of range.");
-    nsresult rv = gMediaCache->ReadCacheFile(offset, aBuffer + count, int32_t(size), &bytes);
+    nsresult rv = mMediaCache->ReadCacheFile(offset, aBuffer + count, int32_t(size), &bytes);
     if (NS_FAILED(rv)) {
       if (count == 0)
         return rv;
       // If we did successfully read some data, may as well return it
       break;
     }
     streamOffset += bytes;
     count += bytes;
   }
 
   if (count > 0) {
     // Some data was read, so queue an update since block priorities may
     // have changed
-    gMediaCache->QueueUpdate();
+    mMediaCache->QueueUpdate();
   }
   LOG("Stream %p Read at %" PRId64 " count=%d", this, streamOffset-count, count);
   *aBytes = count;
   mStreamOffset = streamOffset;
   return NS_OK;
 }
 
 nsresult
 MediaCacheStream::ReadAt(int64_t aOffset, char* aBuffer,
                          uint32_t aCount, uint32_t* aBytes)
 {
   NS_ASSERTION(!NS_IsMainThread(), "Don't call on main thread");
 
-  ReentrantMonitorAutoEnter mon(gMediaCache->GetReentrantMonitor());
+  ReentrantMonitorAutoEnter mon(mMediaCache->GetReentrantMonitor());
   nsresult rv = Seek(nsISeekableStream::NS_SEEK_SET, aOffset);
   if (NS_FAILED(rv)) return rv;
   return Read(aBuffer, aCount, aBytes);
 }
 
 nsresult
 MediaCacheStream::ReadFromCache(char* aBuffer, int64_t aOffset, int64_t aCount)
 {
-  ReentrantMonitorAutoEnter mon(gMediaCache->GetReentrantMonitor());
+  ReentrantMonitorAutoEnter mon(mMediaCache->GetReentrantMonitor());
 
   // Read one block (or part of a block) at a time
   uint32_t count = 0;
   int64_t streamOffset = aOffset;
   while (count < aCount) {
     if (mClosed) {
       // We need to check |mClosed| in each iteration which might be changed
-      // after calling |gMediaCache->ReadCacheFile|.
+      // after calling |mMediaCache->ReadCacheFile|.
       return NS_ERROR_FAILURE;
     }
     uint32_t streamBlock = uint32_t(streamOffset/BLOCK_SIZE);
     uint32_t offsetInStreamBlock =
       uint32_t(streamOffset - streamBlock*BLOCK_SIZE);
     int64_t size = std::min<int64_t>(aCount - count, BLOCK_SIZE - offsetInStreamBlock);
 
     if (mStreamLength >= 0) {
@@ -2462,17 +2463,17 @@ MediaCacheStream::ReadFromCache(char* aB
         mPartialBlockBuffer.get() + offsetInStreamBlock, bytes);
     } else {
       if (cacheBlock < 0) {
         // We expect all blocks to be cached! Fail!
         return NS_ERROR_FAILURE;
       }
       int64_t offset = cacheBlock*BLOCK_SIZE + offsetInStreamBlock;
       MOZ_ASSERT(size >= 0 && size <= INT32_MAX, "Size out of range.");
-      nsresult rv = gMediaCache->ReadCacheFile(offset, aBuffer + count, int32_t(size), &bytes);
+      nsresult rv = mMediaCache->ReadCacheFile(offset, aBuffer + count, int32_t(size), &bytes);
       if (NS_FAILED(rv)) {
         return rv;
       }
     }
     streamOffset += bytes;
     count += bytes;
   }
 
@@ -2482,21 +2483,21 @@ MediaCacheStream::ReadFromCache(char* aB
 nsresult
 MediaCacheStream::Init()
 {
   NS_ASSERTION(NS_IsMainThread(), "Only call on main thread");
 
   if (mInitialized)
     return NS_OK;
 
-  MediaCache::GetMediaCache();
-  if (!gMediaCache) {
+  mMediaCache = MediaCache::GetMediaCache();
+  if (!mMediaCache) {
     return NS_ERROR_FAILURE;
   }
-  gMediaCache->OpenStream(this);
+  mMediaCache->OpenStream(this);
   mInitialized = true;
   return NS_OK;
 }
 
 nsresult
 MediaCacheStream::InitAsClone(MediaCacheStream* aOriginal)
 {
   if (!aOriginal->IsAvailableForSharing())
@@ -2506,17 +2507,17 @@ MediaCacheStream::InitAsClone(MediaCache
     return NS_OK;
 
   nsresult rv = Init();
   if (NS_FAILED(rv))
     return rv;
   mResourceID = aOriginal->mResourceID;
 
   // Grab cache blocks from aOriginal as readahead blocks for our stream
-  ReentrantMonitorAutoEnter mon(gMediaCache->GetReentrantMonitor());
+  ReentrantMonitorAutoEnter mon(mMediaCache->GetReentrantMonitor());
 
   mPrincipal = aOriginal->mPrincipal;
   mStreamLength = aOriginal->mStreamLength;
   mIsTransportSeekable = aOriginal->mIsTransportSeekable;
 
   // Cloned streams are initially suspended, since there is no channel open
   // initially for a clone.
   mCacheSuspended = true;
@@ -2533,27 +2534,27 @@ MediaCacheStream::InitAsClone(MediaCache
     if (cacheBlockIndex < 0)
       continue;
 
     while (i >= mBlocks.Length()) {
       mBlocks.AppendElement(-1);
     }
     // Every block is a readahead block for the clone because the clone's initial
     // stream offset is zero
-    gMediaCache->AddBlockOwnerAsReadahead(cacheBlockIndex, this, i);
+    mMediaCache->AddBlockOwnerAsReadahead(cacheBlockIndex, this, i);
   }
 
   return NS_OK;
 }
 
 nsresult MediaCacheStream::GetCachedRanges(MediaByteRangeSet& aRanges)
 {
   // Take the monitor, so that the cached data ranges can't grow while we're
   // trying to loop over them.
-  ReentrantMonitorAutoEnter mon(gMediaCache->GetReentrantMonitor());
+  ReentrantMonitorAutoEnter mon(mMediaCache->GetReentrantMonitor());
 
   // We must be pinned while running this, otherwise the cached data ranges may
   // shrink while we're trying to loop over them.
   NS_ASSERTION(mPinCount > 0, "Must be pinned");
 
   int64_t startOffset = GetNextCachedDataInternal(0);
   while (startOffset >= 0) {
     int64_t endOffset = GetCachedDataEndInternal(startOffset);
--- a/dom/media/MediaCache.h
+++ b/dom/media/MediaCache.h
@@ -433,16 +433,19 @@ private:
   // that the cache monitor is held. Main thread only.
   // aReentrantMonitor is the nsAutoReentrantMonitor wrapper holding the cache monitor.
   // This is used to NotifyAll to wake up threads that might be
   // blocked on reading from this stream.
   void CloseInternal(ReentrantMonitorAutoEnter& aReentrantMonitor);
   // Update mPrincipal given that data has been received from aPrincipal
   bool UpdatePrincipal(nsIPrincipal* aPrincipal);
 
+  // Instance of MediaCache to use with this MediaCacheStream.
+  MediaCache* mMediaCache;
+
   // These fields are main-thread-only.
   ChannelMediaResource*  mClient;
   nsCOMPtr<nsIPrincipal> mPrincipal;
   // Set to true when Init or InitAsClone has been called
   bool                   mInitialized;
   // Set to true when MediaCache::Update() has finished while this stream
   // was present.
   bool                   mHasHadUpdate;