--- a/dom/media/MediaCache.cpp
+++ b/dom/media/MediaCache.cpp
@@ -828,16 +828,17 @@ OffsetInBlock(int64_t aOffset)
return int32_t(aOffset % MediaCache::BLOCK_SIZE);
}
int32_t
MediaCache::FindBlockForIncomingData(TimeStamp aNow,
MediaCacheStream* aStream,
int32_t aStreamBlockIndex)
{
+ MOZ_ASSERT(sThread->IsOnCurrentThread());
mReentrantMonitor.AssertCurrentThreadIn();
int32_t blockIndex =
FindReusableBlock(aNow, aStream, aStreamBlockIndex, INT32_MAX);
if (blockIndex < 0 || !IsBlockFree(blockIndex)) {
// The block returned is already allocated.
// Don't reuse it if a) there's room to expand the cache or
@@ -858,16 +859,18 @@ MediaCache::FindBlockForIncomingData(Tim
}
return blockIndex;
}
bool
MediaCache::BlockIsReusable(int32_t aBlockIndex)
{
+ mReentrantMonitor.AssertCurrentThreadIn();
+
Block* block = &mIndex[aBlockIndex];
for (uint32_t i = 0; i < block->mOwners.Length(); ++i) {
MediaCacheStream* stream = block->mOwners[i].mStream;
if (stream->mPinCount > 0 ||
uint32_t(OffsetToBlockIndex(stream->mStreamOffset)) ==
block->mOwners[i].mStreamBlock) {
return false;
}
@@ -899,16 +902,17 @@ MediaCache::AppendMostReusableBlock(Bloc
}
int32_t
MediaCache::FindReusableBlock(TimeStamp aNow,
MediaCacheStream* aForStream,
int32_t aForStreamBlock,
int32_t aMaxSearchBlockIndex)
{
+ MOZ_ASSERT(sThread->IsOnCurrentThread());
mReentrantMonitor.AssertCurrentThreadIn();
uint32_t length = std::min(uint32_t(aMaxSearchBlockIndex), uint32_t(mIndex.Length()));
if (aForStream && aForStreamBlock > 0 &&
uint32_t(aForStreamBlock) <= aForStream->mBlocks.Length()) {
int32_t prevCacheBlock = aForStream->mBlocks[aForStreamBlock - 1];
if (prevCacheBlock >= 0) {
@@ -963,16 +967,18 @@ MediaCache::FindReusableBlock(TimeStamp
}
return latestUseBlock;
}
MediaCache::BlockList*
MediaCache::GetListForBlock(BlockOwner* aBlock)
{
+ mReentrantMonitor.AssertCurrentThreadIn();
+
switch (aBlock->mClass) {
case METADATA_BLOCK:
NS_ASSERTION(aBlock->mStream, "Metadata block has no stream?");
return &aBlock->mStream->mMetadataBlocks;
case PLAYED_BLOCK:
NS_ASSERTION(aBlock->mStream, "Metadata block has no stream?");
return &aBlock->mStream->mPlayedBlocks;
case READAHEAD_BLOCK:
@@ -982,16 +988,18 @@ MediaCache::GetListForBlock(BlockOwner*
NS_ERROR("Invalid block class");
return nullptr;
}
}
MediaCache::BlockOwner*
MediaCache::GetBlockOwner(int32_t aBlockIndex, MediaCacheStream* aStream)
{
+ mReentrantMonitor.AssertCurrentThreadIn();
+
Block* block = &mIndex[aBlockIndex];
for (uint32_t i = 0; i < block->mOwners.Length(); ++i) {
if (block->mOwners[i].mStream == aStream)
return &block->mOwners[i];
}
return nullptr;
}
@@ -1037,16 +1045,18 @@ MediaCache::SwapBlocks(int32_t aBlockInd
}
Verify();
}
void
MediaCache::RemoveBlockOwner(int32_t aBlockIndex, MediaCacheStream* aStream)
{
+ mReentrantMonitor.AssertCurrentThreadIn();
+
Block* block = &mIndex[aBlockIndex];
for (uint32_t i = 0; i < block->mOwners.Length(); ++i) {
BlockOwner* bo = &block->mOwners[i];
if (bo->mStream == aStream) {
GetListForBlock(bo)->RemoveBlock(aBlockIndex);
bo->mStream->mBlocks[bo->mStreamBlock] = -1;
block->mOwners.RemoveElementAt(i);
if (block->mOwners.IsEmpty()) {
@@ -1057,16 +1067,18 @@ MediaCache::RemoveBlockOwner(int32_t aBl
}
}
void
MediaCache::AddBlockOwnerAsReadahead(int32_t aBlockIndex,
MediaCacheStream* aStream,
int32_t aStreamBlockIndex)
{
+ mReentrantMonitor.AssertCurrentThreadIn();
+
Block* block = &mIndex[aBlockIndex];
if (block->mOwners.IsEmpty()) {
mFreeBlocks.RemoveBlock(aBlockIndex);
}
BlockOwner* bo = block->mOwners.AppendElement();
mBlockOwnersWatermark =
std::max(mBlockOwnersWatermark, uint32_t(block->mOwners.Length()));
bo->mStream = aStream;
@@ -1097,16 +1109,17 @@ MediaCache::FreeBlock(int32_t aBlock)
block->mOwners.Clear();
mFreeBlocks.AddFirstBlock(aBlock);
Verify();
}
TimeDuration
MediaCache::PredictNextUse(TimeStamp aNow, int32_t aBlock)
{
+ MOZ_ASSERT(sThread->IsOnCurrentThread());
mReentrantMonitor.AssertCurrentThreadIn();
NS_ASSERTION(!IsBlockFree(aBlock), "aBlock is free");
Block* block = &mIndex[aBlock];
// Blocks can be belong to multiple streams. The predicted next use
// time is the earliest time predicted by any of the streams.
TimeDuration result;
for (uint32_t i = 0; i < block->mOwners.Length(); ++i) {
@@ -1152,16 +1165,17 @@ MediaCache::PredictNextUse(TimeStamp aNo
}
}
return result;
}
TimeDuration
MediaCache::PredictNextUseForIncomingData(MediaCacheStream* aStream)
{
+ MOZ_ASSERT(sThread->IsOnCurrentThread());
mReentrantMonitor.AssertCurrentThreadIn();
int64_t bytesAhead = aStream->mChannelOffset - aStream->mStreamOffset;
if (bytesAhead <= -BLOCK_SIZE) {
// Hmm, no idea when data behind us will be used. Guess 24 hours.
return TimeDuration::FromSeconds(24*60*60);
}
if (bytesAhead <= 0)
@@ -1622,18 +1636,17 @@ MediaCache::Verify()
lastStreamBlock = nextStreamBlock;
block = stream->mReadaheadBlocks.GetNextBlock(block);
}
}
}
#endif
void
-MediaCache::InsertReadaheadBlock(BlockOwner* aBlockOwner,
- int32_t aBlockIndex)
+MediaCache::InsertReadaheadBlock(BlockOwner* aBlockOwner, int32_t aBlockIndex)
{
mReentrantMonitor.AssertCurrentThreadIn();
// Find the last block whose stream block is before aBlockIndex's
// stream block, and insert after it
MediaCacheStream* stream = aBlockOwner->mStream;
int32_t readaheadIndex = stream->mReadaheadBlocks.GetLastBlock();
while (readaheadIndex >= 0) {
@@ -1654,16 +1667,17 @@ MediaCache::InsertReadaheadBlock(BlockOw
void
MediaCache::AllocateAndWriteBlock(MediaCacheStream* aStream,
int32_t aStreamBlockIndex,
MediaCacheStream::ReadMode aMode,
Span<const uint8_t> aData1,
Span<const uint8_t> aData2)
{
+ MOZ_ASSERT(sThread->IsOnCurrentThread());
mReentrantMonitor.AssertCurrentThreadIn();
// Remove all cached copies of this block
ResourceStreamIterator iter(this, aStream->mResourceID);
while (MediaCacheStream* stream = iter.Next()) {
while (aStreamBlockIndex >= int32_t(stream->mBlocks.Length())) {
stream->mBlocks.AppendElement(-1);
}
@@ -2100,16 +2114,18 @@ MediaCacheStream::NotifyDataReceived(uin
// avoid waking up reader threads unnecessarily
mon.NotifyAll();
}
void
MediaCacheStream::FlushPartialBlockInternal(bool aNotifyAll,
ReentrantMonitorAutoEnter& aReentrantMonitor)
{
+ MOZ_ASSERT(OwnerThread()->IsOnCurrentThread());
+
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");
@@ -2133,16 +2149,17 @@ MediaCacheStream::FlushPartialBlockInter
}
}
void
MediaCacheStream::NotifyDataEndedInternal(uint32_t aLoadID,
nsresult aStatus,
bool aReopenOnError)
{
+ MOZ_ASSERT(OwnerThread()->IsOnCurrentThread());
ReentrantMonitorAutoEnter mon(mMediaCache->GetReentrantMonitor());
if (mClosed || aLoadID != mLoadID) {
// Nothing to do if the stream is closed or a new load has begun.
return;
}
// Note that aStatus might have succeeded --- this might be a normal close
@@ -2268,17 +2285,19 @@ MediaCacheStream::~MediaCacheStream()
lengthKb);
Telemetry::Accumulate(Telemetry::HistogramID::MEDIACACHESTREAM_LENGTH_KB,
lengthKb);
}
bool
MediaCacheStream::AreAllStreamsForResourceSuspended()
{
+ MOZ_ASSERT(!NS_IsMainThread());
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) {
@@ -2319,65 +2338,72 @@ MediaCacheStream::Close()
// it from CloseInternal since that gets called by Update() itself
// sometimes, and we try to not to queue updates from Update().
mMediaCache->QueueUpdate();
}
void
MediaCacheStream::Pin()
{
+ // TODO: Assert non-main thread.
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
mMediaCache->QueueUpdate();
}
void
MediaCacheStream::Unpin()
{
+ // TODO: Assert non-main thread.
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
mMediaCache->QueueUpdate();
}
int64_t
MediaCacheStream::GetLength()
{
+ // TODO: Assert non-main thread.
ReentrantMonitorAutoEnter mon(mMediaCache->GetReentrantMonitor());
return mStreamLength;
}
int64_t
MediaCacheStream::GetOffset() const
{
+ // TODO: Assert non-main thread.
ReentrantMonitorAutoEnter mon(mMediaCache->GetReentrantMonitor());
return mChannelOffset;
}
int64_t
MediaCacheStream::GetNextCachedData(int64_t aOffset)
{
+ MOZ_ASSERT(!NS_IsMainThread());
ReentrantMonitorAutoEnter mon(mMediaCache->GetReentrantMonitor());
return GetNextCachedDataInternal(aOffset);
}
int64_t
MediaCacheStream::GetCachedDataEnd(int64_t aOffset)
{
+ // TODO: Assert non-main thread.
ReentrantMonitorAutoEnter mon(mMediaCache->GetReentrantMonitor());
return GetCachedDataEndInternal(aOffset);
}
bool
MediaCacheStream::IsDataCachedToEndOfStream(int64_t aOffset)
{
+ MOZ_ASSERT(!NS_IsMainThread());
ReentrantMonitorAutoEnter mon(mMediaCache->GetReentrantMonitor());
if (mStreamLength < 0)
return false;
return GetCachedDataEndInternal(aOffset) >= mStreamLength;
}
int64_t
MediaCacheStream::GetCachedDataEndInternal(int64_t aOffset)
@@ -2452,16 +2478,17 @@ MediaCacheStream::GetNextCachedDataInter
NS_NOTREACHED("Should return in loop");
return -1;
}
void
MediaCacheStream::SetReadMode(ReadMode aMode)
{
+ // TODO: Assert non-main thread.
ReentrantMonitorAutoEnter mon(mMediaCache->GetReentrantMonitor());
if (aMode == mCurrentMode)
return;
mCurrentMode = aMode;
mMediaCache->QueueUpdate();
}
void
@@ -2591,18 +2618,17 @@ MediaCacheStream::ReadBlockFromCache(int
}
return bytesRead;
}
nsresult
MediaCacheStream::Read(char* aBuffer, uint32_t aCount, uint32_t* aBytes)
{
- NS_ASSERTION(!NS_IsMainThread(), "Don't call on main thread");
-
+ MOZ_ASSERT(!NS_IsMainThread());
ReentrantMonitorAutoEnter mon(mMediaCache->GetReentrantMonitor());
// 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;
// The buffer we are about to fill.
auto buffer = MakeSpan<char>(aBuffer, aCount);
@@ -2689,27 +2715,27 @@ MediaCacheStream::Read(char* aBuffer, ui
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");
-
+ MOZ_ASSERT(!NS_IsMainThread());
ReentrantMonitorAutoEnter mon(mMediaCache->GetReentrantMonitor());
nsresult rv = Seek(aOffset);
if (NS_FAILED(rv)) return rv;
return Read(aBuffer, aCount, aBytes);
}
nsresult
MediaCacheStream::ReadFromCache(char* aBuffer, int64_t aOffset, uint32_t aCount)
{
+ MOZ_ASSERT(!NS_IsMainThread());
ReentrantMonitorAutoEnter mon(mMediaCache->GetReentrantMonitor());
// The buffer we are about to fill.
auto buffer = MakeSpan<char>(aBuffer, aCount);
// Read one block (or part of a block) at a time
int64_t streamOffset = aOffset;
while (!buffer.IsEmpty()) {
@@ -2837,16 +2863,17 @@ MediaCacheStream::InitAsClone(MediaCache
nsIEventTarget*
MediaCacheStream::OwnerThread() const
{
return mMediaCache->OwnerThread();
}
nsresult MediaCacheStream::GetCachedRanges(MediaByteRangeSet& aRanges)
{
+ MOZ_ASSERT(!NS_IsMainThread());
// Take the monitor, so that the cached data ranges can't grow while we're
// trying to loop over them.
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");