Bug 1399751. P1 - pass a block index to AllocateAndWriteBlock() so it doesn't depend on mChannelOffset. draft
authorJW Wang <jwwang@mozilla.com>
Thu, 14 Sep 2017 10:39:06 +0800
changeset 665184 dbdfd7f4373d77569c9b01bbcb5e7cd3977329ff
parent 664593 22af46a970619fb5cf7a2821123275b5c19c1b2d
child 665185 49aab0220d67918fc7f570dba98b4b4f732dea5a
push id79953
push userjwwang@mozilla.com
push dateFri, 15 Sep 2017 00:49:52 +0000
bugs1399751
milestone57.0a1
Bug 1399751. P1 - pass a block index to AllocateAndWriteBlock() so it doesn't depend on mChannelOffset. MozReview-Commit-ID: EJmxrE5X6nA
dom/media/MediaCache.cpp
--- a/dom/media/MediaCache.cpp
+++ b/dom/media/MediaCache.cpp
@@ -168,18 +168,21 @@ public:
   // and to handle reads and writes.
   // Add aStream to the list of streams.
   void OpenStream(MediaCacheStream* aStream);
   // Remove aStream from the list of streams.
   void ReleaseStream(MediaCacheStream* aStream);
   // Free all blocks belonging to aStream.
   void ReleaseStreamBlocks(MediaCacheStream* aStream);
   // Find a cache entry for this data, and write the data into it
-  void AllocateAndWriteBlock(MediaCacheStream* aStream,
-    MediaCacheStream::ReadMode aMode, Span<const uint8_t> aData1,
+  void AllocateAndWriteBlock(
+    MediaCacheStream* aStream,
+    int32_t aStreamBlockIndex,
+    MediaCacheStream::ReadMode aMode,
+    Span<const uint8_t> aData1,
     Span<const uint8_t> aData2 = Span<const uint8_t>());
 
   // mReentrantMonitor must be held; can be called on any thread
   // Notify the cache that a seek has been requested. Some blocks may
   // need to change their class between PLAYED_BLOCK and READAHEAD_BLOCK.
   // This does not trigger channel seeks directly, the next Update()
   // will do that if necessary. The caller will call QueueUpdate().
   void NoteSeek(MediaCacheStream* aStream, int64_t aOldOffset);
@@ -1571,51 +1574,55 @@ MediaCache::InsertReadaheadBlock(BlockOw
     readaheadIndex = stream->mReadaheadBlocks.GetPrevBlock(readaheadIndex);
   }
 
   stream->mReadaheadBlocks.AddFirstBlock(aBlockIndex);
   Verify();
 }
 
 void
-MediaCache::AllocateAndWriteBlock(
-  MediaCacheStream* aStream, MediaCacheStream::ReadMode aMode,
-  Span<const uint8_t> aData1, Span<const uint8_t> aData2)
+MediaCache::AllocateAndWriteBlock(MediaCacheStream* aStream,
+                                  int32_t aStreamBlockIndex,
+                                  MediaCacheStream::ReadMode aMode,
+                                  Span<const uint8_t> aData1,
+                                  Span<const uint8_t> aData2)
 {
   mReentrantMonitor.AssertCurrentThreadIn();
 
-  int32_t streamBlockIndex =
-    OffsetToBlockIndexUnchecked(aStream->mChannelOffset);
-
   // Remove all cached copies of this block
   ResourceStreamIterator iter(this, aStream->mResourceID);
   while (MediaCacheStream* stream = iter.Next()) {
-    while (streamBlockIndex >= int32_t(stream->mBlocks.Length())) {
+    while (aStreamBlockIndex >= int32_t(stream->mBlocks.Length())) {
       stream->mBlocks.AppendElement(-1);
     }
-    if (stream->mBlocks[streamBlockIndex] >= 0) {
+    if (stream->mBlocks[aStreamBlockIndex] >= 0) {
       // We no longer want to own this block
-      int32_t globalBlockIndex = stream->mBlocks[streamBlockIndex];
+      int32_t globalBlockIndex = stream->mBlocks[aStreamBlockIndex];
       LOG("Released block %d from stream %p block %d(%" PRId64 ")",
-          globalBlockIndex, stream, streamBlockIndex,
-          streamBlockIndex*BLOCK_SIZE);
+          globalBlockIndex,
+          stream,
+          aStreamBlockIndex,
+          aStreamBlockIndex * BLOCK_SIZE);
       RemoveBlockOwner(globalBlockIndex, stream);
     }
   }
 
   // Extend the mBlocks array as necessary
 
   TimeStamp now = TimeStamp::Now();
   int32_t blockIndex = FindBlockForIncomingData(now, aStream);
   if (blockIndex >= 0) {
     FreeBlock(blockIndex);
 
     Block* block = &mIndex[blockIndex];
     LOG("Allocated block %d to stream %p block %d(%" PRId64 ")",
-        blockIndex, aStream, streamBlockIndex, streamBlockIndex*BLOCK_SIZE);
+        blockIndex,
+        aStream,
+        aStreamBlockIndex,
+        aStreamBlockIndex * BLOCK_SIZE);
 
     ResourceStreamIterator iter(this, aStream->mResourceID);
     while (MediaCacheStream* stream = iter.Next()) {
       BlockOwner* bo = block->mOwners.AppendElement();
       if (!bo) {
         // Roll back mOwners if any allocation fails.
         block->mOwners.Clear();
         return;
@@ -1628,20 +1635,20 @@ MediaCache::AllocateAndWriteBlock(
     if (block->mOwners.IsEmpty()) {
       // This happens when all streams with the resource id are closed. We can
       // just return here now and discard the data.
       return;
     }
 
     // Tell each stream using this resource about the new block.
     for (auto& bo : block->mOwners) {
-      bo.mStreamBlock = streamBlockIndex;
+      bo.mStreamBlock = aStreamBlockIndex;
       bo.mLastUseTime = now;
-      bo.mStream->mBlocks[streamBlockIndex] = blockIndex;
-      if (streamBlockIndex*BLOCK_SIZE < bo.mStream->mStreamOffset) {
+      bo.mStream->mBlocks[aStreamBlockIndex] = blockIndex;
+      if (aStreamBlockIndex * BLOCK_SIZE < bo.mStream->mStreamOffset) {
         bo.mClass = aMode == MediaCacheStream::MODE_PLAYBACK ? PLAYED_BLOCK
                                                              : METADATA_BLOCK;
         // This must be the most-recently-used block, since we
         // marked it as used now (which may be slightly bogus, but we'll
         // treat it as used for simplicity).
         GetListForBlock(&bo)->AddFirstBlock(blockIndex);
         Verify();
       } else {
@@ -1656,17 +1663,20 @@ MediaCache::AllocateAndWriteBlock(
     // Invariant: block->mOwners.IsEmpty() iff we can find an entry
     // in mFreeBlocks for a given blockIndex.
     MOZ_DIAGNOSTIC_ASSERT(!block->mOwners.IsEmpty());
     mFreeBlocks.RemoveBlock(blockIndex);
 
     nsresult rv = mBlockCache->WriteBlock(blockIndex, aData1, aData2);
     if (NS_FAILED(rv)) {
       LOG("Released block %d from stream %p block %d(%" PRId64 ")",
-          blockIndex, aStream, streamBlockIndex, streamBlockIndex*BLOCK_SIZE);
+          blockIndex,
+          aStream,
+          aStreamBlockIndex,
+          aStreamBlockIndex * BLOCK_SIZE);
       FreeBlock(blockIndex);
     }
   }
 
   // Queue an Update since the cache state has changed (for example
   // we might want to stop loading because the cache is full)
   QueueUpdate();
 }
@@ -1911,17 +1921,17 @@ 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);
-      mMediaCache->AllocateAndWriteBlock(this, mode, data1, data2);
+      mMediaCache->AllocateAndWriteBlock(this, blockIndex, mode, data1, data2);
     } else {
       memcpy(mPartialBlockBuffer.get() + blockOffset, data, chunkSize);
     }
 
     mChannelOffset += chunkSize;
     size -= chunkSize;
     data += chunkSize;
   }
@@ -1942,29 +1952,31 @@ MediaCacheStream::NotifyDataReceived(int
 }
 
 void
 MediaCacheStream::FlushPartialBlockInternal(bool aNotifyAll,
                                             ReentrantMonitorAutoEnter& aReentrantMonitor)
 {
   NS_ASSERTION(NS_IsMainThread(), "Only call on main thread");
 
+  int32_t blockIndex = OffsetToBlockIndexUnchecked(mChannelOffset);
   int32_t blockOffset = OffsetInBlock(mChannelOffset);
   if (blockOffset > 0) {
     LOG("Stream %p writing partial block: [%d] bytes; "
         "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);
     mMediaCache->AllocateAndWriteBlock(
       this,
+      blockIndex,
       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) {