--- a/dom/media/MediaCache.cpp
+++ b/dom/media/MediaCache.cpp
@@ -257,31 +257,37 @@ public:
ReentrantMonitor& GetReentrantMonitor() { return mReentrantMonitor; }
/**
* An iterator that makes it easy to iterate through all streams that
* have a given resource ID and are not closed.
* Can be used on the main thread or while holding the media cache lock.
*/
- class ResourceStreamIterator {
+ class ResourceStreamIterator
+ {
public:
- explicit ResourceStreamIterator(int64_t aResourceID) :
- mResourceID(aResourceID), mNext(0) {}
+ ResourceStreamIterator(MediaCache* aMediaCache, int64_t aResourceID)
+ : mMediaCache(aMediaCache)
+ , mResourceID(aResourceID)
+ , mNext(0)
+ {
+ }
MediaCacheStream* Next()
{
- while (mNext < gMediaCache->mStreams.Length()) {
- MediaCacheStream* stream = gMediaCache->mStreams[mNext];
+ while (mNext < mMediaCache->mStreams.Length()) {
+ MediaCacheStream* stream = mMediaCache->mStreams[mNext];
++mNext;
if (stream->GetResourceID() == mResourceID && !stream->IsClosed())
return stream;
}
return nullptr;
}
private:
+ MediaCache* mMediaCache;
int64_t mResourceID;
uint32_t mNext;
};
protected:
// Find a free or reusable block and return its index. If there are no
// free blocks and no reusable blocks, add a new block to the cache
// and return it. Can return -1 on OOM.
@@ -1405,17 +1411,17 @@ MediaCache::Update()
// Reads will also be woken up.
ReentrantMonitorAutoEnter mon(mReentrantMonitor);
stream->CloseInternal(mon);
}
}
// Notify streams about the suspended status changes.
for (uint32_t i = 0; i < mSuspendedStatusToNotify.Length(); ++i) {
- MediaCache::ResourceStreamIterator iter(mSuspendedStatusToNotify[i]);
+ MediaCache::ResourceStreamIterator iter(this, mSuspendedStatusToNotify[i]);
while (MediaCacheStream* stream = iter.Next()) {
stream->mClient->CacheClientNotifySuspendedStatusChanged();
}
}
mSuspendedStatusToNotify.Clear();
}
class UpdateEvent : public Runnable
@@ -1525,17 +1531,17 @@ MediaCache::AllocateAndWriteBlock(
MediaCacheStream* aStream, MediaCacheStream::ReadMode aMode,
Span<const uint8_t> aData1, Span<const uint8_t> aData2)
{
mReentrantMonitor.AssertCurrentThreadIn();
int32_t streamBlockIndex = aStream->mChannelOffset/BLOCK_SIZE;
// Remove all cached copies of this block
- ResourceStreamIterator iter(aStream->mResourceID);
+ ResourceStreamIterator iter(this, aStream->mResourceID);
while (MediaCacheStream* stream = iter.Next()) {
while (streamBlockIndex >= int32_t(stream->mBlocks.Length())) {
stream->mBlocks.AppendElement(-1);
}
if (stream->mBlocks[streamBlockIndex] >= 0) {
// We no longer want to own this block
int32_t globalBlockIndex = stream->mBlocks[streamBlockIndex];
LOG("Released block %d from stream %p block %d(%" PRId64 ")",
@@ -1551,17 +1557,17 @@ MediaCache::AllocateAndWriteBlock(
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);
- ResourceStreamIterator iter(aStream->mResourceID);
+ 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;
}
mBlockOwnersWatermark =
@@ -1825,17 +1831,17 @@ MediaCacheStream::NotifyDataReceived(int
}
// Update principals before putting the data in the cache. This is important,
// we want to make sure all principals are updated before any consumer
// can see the new data.
// We do this without holding the cache monitor, in case the client wants
// to do something that takes a lock.
{
- MediaCache::ResourceStreamIterator iter(mResourceID);
+ MediaCache::ResourceStreamIterator iter(gMediaCache, mResourceID);
while (MediaCacheStream* stream = iter.Next()) {
if (stream->UpdatePrincipal(aPrincipal)) {
stream->mClient->CacheClientNotifyPrincipalChanged();
}
}
}
ReentrantMonitorAutoEnter mon(gMediaCache->GetReentrantMonitor());
@@ -1871,17 +1877,17 @@ MediaCacheStream::NotifyDataReceived(int
memcpy(mPartialBlockBuffer.get() + blockOffset, data, chunkSize);
}
mChannelOffset += chunkSize;
size -= chunkSize;
data += chunkSize;
}
- MediaCache::ResourceStreamIterator iter(mResourceID);
+ MediaCache::ResourceStreamIterator iter(gMediaCache, mResourceID);
while (MediaCacheStream* stream = iter.Next()) {
if (stream->mStreamLength >= 0) {
// The stream is at least as long as what we've read
stream->mStreamLength = std::max(stream->mStreamLength, mChannelOffset);
}
stream->mClient->CacheClientNotifyDataReceived();
}
@@ -1952,17 +1958,17 @@ MediaCacheStream::NotifyDataEnded(nsresu
}
// It is prudent to update channel/cache status before calling
// CacheClientNotifyDataEnded() which will read |mChannelEnded|.
FlushPartialBlockInternal(true, mon);
mChannelEnded = true;
gMediaCache->QueueUpdate();
- MediaCache::ResourceStreamIterator iter(mResourceID);
+ MediaCache::ResourceStreamIterator iter(gMediaCache, mResourceID);
while (MediaCacheStream* stream = iter.Next()) {
if (NS_SUCCEEDED(aStatus)) {
// We read the whole stream, so remember the true length
stream->mStreamLength = mChannelOffset;
}
if (!stream->mDidNotifyDataEnded) {
stream->mDidNotifyDataEnded = true;
stream->mNotifyDataEndedStatus = aStatus;
@@ -2019,17 +2025,17 @@ MediaCacheStream::IsTransportSeekable()
ReentrantMonitorAutoEnter mon(gMediaCache->GetReentrantMonitor());
return mIsTransportSeekable;
}
bool
MediaCacheStream::AreAllStreamsForResourceSuspended()
{
ReentrantMonitorAutoEnter mon(gMediaCache->GetReentrantMonitor());
- MediaCache::ResourceStreamIterator iter(mResourceID);
+ MediaCache::ResourceStreamIterator iter(gMediaCache, 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) {
dataOffset = GetCachedDataEndInternal(mStreamOffset);
@@ -2327,17 +2333,17 @@ MediaCacheStream::Read(char* aBuffer, ui
break;
}
// 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);
+ MediaCache::ResourceStreamIterator iter(gMediaCache, mResourceID);
while (MediaCacheStream* stream = iter.Next()) {
if (uint32_t(stream->mChannelOffset/BLOCK_SIZE) == streamBlock &&
streamOffset < stream->mChannelOffset) {
streamWithPartialBlock = stream;
break;
}
}
if (streamWithPartialBlock) {