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