Bug 1375772 - don't evict the block which is in the current cached range. draft
authorJW Wang <jwwang@mozilla.com>
Thu, 02 Nov 2017 18:12:20 +0800
changeset 693320 ab5e347c0cb4b8f7d444f10bba558ebdee18c220
parent 693319 849017ffe2976f7721c20c3625d8fafeb3cce8dd
child 693321 f3a9a0eef18e80254731c2131a3e83310c4feec5
push id87753
push userjwwang@mozilla.com
push dateSun, 05 Nov 2017 15:10:09 +0000
bugs1375772, 1347174
milestone58.0a1
Bug 1375772 - don't evict the block which is in the current cached range. Evicting the block will result in a gap in the current cached range starting from mStreamOffset to mChannelOffset. Then we have |GetCachedDataEndInternal(mStreamOffset) < mChannelOffset| and MediaCache will open a new channel to fill the gap which is bad. This is exactly the issue described in bug 1347174 where we limit the readahead size to prevent the problem above from happening. However bug 1347174 is indeed a workaround instead of a fix. It works around the issue by suspending the download before the cache is full and has to evict some blocks to allow new data to come in. We should let MediaCache suspend the channel if it is full or evict played blocks if possible. MozReview-Commit-ID: HuUsZLdHGuh
dom/media/MediaCache.cpp
--- a/dom/media/MediaCache.cpp
+++ b/dom/media/MediaCache.cpp
@@ -1250,16 +1250,33 @@ MediaCache::Update()
       FindReusableBlock(now, block->mOwners[0].mStream,
                         block->mOwners[0].mStreamBlock, maxBlocks);
     if (destinationBlockIndex < 0) {
       // Nowhere to place this overflow block. We won't be able to
       // place any more overflow blocks.
       break;
     }
 
+    // Don't evict |destinationBlockIndex| if it is within [cur, end) otherwise
+    // a new channel will be opened to download this block again which is bad.
+    bool inCurrentCachedRange = false;
+    for (BlockOwner& owner : mIndex[destinationBlockIndex].mOwners) {
+      MediaCacheStream* stream = owner.mStream;
+      int64_t end = OffsetToBlockIndexUnchecked(
+        stream->GetCachedDataEndInternal(stream->mStreamOffset));
+      int64_t cur = OffsetToBlockIndexUnchecked(stream->mStreamOffset);
+      if (cur <= owner.mStreamBlock && owner.mStreamBlock < end) {
+        inCurrentCachedRange = true;
+        break;
+      }
+    }
+    if (inCurrentCachedRange) {
+      continue;
+    }
+
     if (IsBlockFree(destinationBlockIndex) ||
         PredictNextUse(now, destinationBlockIndex) > latestPredictedUseForOverflow) {
       // Reuse blocks in the main part of the cache that are less useful than
       // the least useful overflow blocks
 
       nsresult rv = mBlockCache->MoveBlock(blockIndex, destinationBlockIndex);
 
       if (NS_SUCCEEDED(rv)) {