Bug 1258673. Part 1 - cache mStreamOffset so we won't read at the wrong position when Other Read() interrupt the current Read(). r=jya. a=ritu
authorJW Wang <jwwang@mozilla.com>
Wed, 23 Mar 2016 21:40:18 +0800
changeset 325590 1fbeb5120d66c87a748eb835d088b5d54b4fe9b1
parent 325589 b7c702322cfd0e26df173656165447eb21f4c852
child 325591 4852e88b04f3ff5ea79adf95a49000f819fd7d4e
push id1128
push userjlund@mozilla.com
push dateWed, 01 Jun 2016 01:31:59 +0000
treeherdermozilla-release@fe0d30de989d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjya, ritu
bugs1258673
milestone47.0a2
Bug 1258673. Part 1 - cache mStreamOffset so we won't read at the wrong position when Other Read() interrupt the current Read(). r=jya. a=ritu MozReview-Commit-ID: 9ghZYMdUopa
dom/media/MediaCache.cpp
--- a/dom/media/MediaCache.cpp
+++ b/dom/media/MediaCache.cpp
@@ -2204,27 +2204,30 @@ 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());
   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;
   // Read one block (or part of a block) at a time
   while (count < aCount) {
-    uint32_t streamBlock = uint32_t(mStreamOffset/BLOCK_SIZE);
-    uint32_t offsetInStreamBlock =
-      uint32_t(mStreamOffset - streamBlock*BLOCK_SIZE);
+    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) {
       // Don't try to read beyond the end of the stream
-      int64_t bytesRemaining = mStreamLength - mStreamOffset;
+      int64_t bytesRemaining = mStreamLength - streamOffset;
       if (bytesRemaining <= 0) {
         // Get out of here and return NS_OK
         break;
       }
       size = std::min(size, bytesRemaining);
       // Clamp size until 64-bit file size issues are fixed.
       size = std::min(size, int64_t(INT32_MAX));
     }
@@ -2242,35 +2245,35 @@ MediaCacheStream::Read(char* aBuffer, ui
       // 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(mResourceID);
       while (MediaCacheStream* stream = iter.Next()) {
         if (uint32_t(stream->mChannelOffset/BLOCK_SIZE) == streamBlock &&
-            mStreamOffset < stream->mChannelOffset) {
+            streamOffset < stream->mChannelOffset) {
           streamWithPartialBlock = stream;
           break;
         }
       }
       if (streamWithPartialBlock) {
         // We can just use the data in mPartialBlockBuffer. In fact we should
         // use it rather than waiting for the block to fill and land in
         // the cache.
-        int64_t bytes = std::min<int64_t>(size, streamWithPartialBlock->mChannelOffset - mStreamOffset);
+        int64_t bytes = std::min<int64_t>(size, streamWithPartialBlock->mChannelOffset - streamOffset);
         // Clamp bytes until 64-bit file size issues are fixed.
         bytes = std::min(bytes, int64_t(INT32_MAX));
         MOZ_ASSERT(bytes >= 0 && bytes <= aCount, "Bytes out of range.");
         memcpy(aBuffer,
           reinterpret_cast<char*>(streamWithPartialBlock->mPartialBlockBuffer.get()) + offsetInStreamBlock, bytes);
         if (mCurrentMode == MODE_METADATA) {
           streamWithPartialBlock->mMetadataInPartialBlockBuffer = true;
         }
-        mStreamOffset += bytes;
+        streamOffset += bytes;
         count = bytes;
         break;
       }
 
       // No data has been read yet, so block
       mon.Wait();
       if (mClosed) {
         // We may have successfully read some data, but let's just throw
@@ -2287,28 +2290,28 @@ MediaCacheStream::Read(char* aBuffer, ui
     MOZ_ASSERT(size >= 0 && size <= INT32_MAX, "Size out of range.");
     nsresult rv = gMediaCache->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;
     }
-    mStreamOffset += bytes;
+    streamOffset += bytes;
     count += bytes;
   }
 
   if (count > 0) {
     // Some data was read, so queue an update since block priorities may
     // have changed
     gMediaCache->QueueUpdate();
   }
-  CACHE_LOG(LogLevel::Debug,
-            ("Stream %p Read at %lld count=%d", this, (long long)(mStreamOffset-count), count));
+  CACHE_LOG(LogLevel::Debug, ("Stream %p Read at %lld 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");