зеркало из https://github.com/mozilla/gecko-dev.git
Bug 486991. Convert nsMediaCache to use TimeStmap/TimeDuration. r=doublec
This commit is contained in:
Родитель
5457f988ef
Коммит
fa2d01d562
|
@ -40,7 +40,6 @@
|
|||
#define nsMediaCache_h_
|
||||
|
||||
#include "nsTArray.h"
|
||||
#include "prinrval.h"
|
||||
#include "nsAutoLock.h"
|
||||
|
||||
/**
|
||||
|
|
|
@ -47,6 +47,7 @@
|
|||
#include "nsMediaStream.h"
|
||||
#include "nsMathUtils.h"
|
||||
#include "prlog.h"
|
||||
#include "nsTimeStamp.h"
|
||||
|
||||
#ifdef PR_LOGGING
|
||||
PRLogModuleInfo* gMediaCacheLog;
|
||||
|
@ -74,6 +75,9 @@ static const PRUint32 REPLAY_DELAY = 30;
|
|||
// can.
|
||||
static const PRUint32 FREE_BLOCK_SCAN_LIMIT = 16;
|
||||
|
||||
using mozilla::TimeStamp;
|
||||
using mozilla::TimeDuration;
|
||||
|
||||
class nsMediaCache {
|
||||
public:
|
||||
friend class nsMediaCacheStream::BlockList;
|
||||
|
@ -148,7 +152,7 @@ public:
|
|||
// and thus hasn't yet been committed to the cache. The caller will
|
||||
// call QueueUpdate().
|
||||
void NoteBlockUsage(PRInt32 aBlockIndex, nsMediaCacheStream::ReadMode aMode,
|
||||
PRIntervalTime aNow);
|
||||
TimeStamp aNow);
|
||||
|
||||
// This queues a call to Update() on the main thread.
|
||||
void QueueUpdate();
|
||||
|
@ -175,7 +179,7 @@ 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.
|
||||
PRInt32 FindBlockForIncomingData(PRIntervalTime aNow, nsMediaCacheStream* aStream);
|
||||
PRInt32 FindBlockForIncomingData(TimeStamp aNow, nsMediaCacheStream* aStream);
|
||||
// Find a reusable block --- a free block, if there is one, otherwise
|
||||
// the reusable block with the latest predicted-next-use, or -1 if
|
||||
// there aren't any freeable blocks. Only block indices less than
|
||||
|
@ -183,7 +187,7 @@ protected:
|
|||
// then aForStream and aForStreamBlock indicate what media data will
|
||||
// be placed; FindReusableBlock will favour returning free blocks
|
||||
// near other blocks for that point in the stream.
|
||||
PRInt32 FindReusableBlock(PRIntervalTime aNow,
|
||||
PRInt32 FindReusableBlock(TimeStamp aNow,
|
||||
nsMediaCacheStream* aForStream,
|
||||
PRInt32 aForStreamBlock,
|
||||
PRInt32 aMaxSearchBlockIndex);
|
||||
|
@ -222,7 +226,7 @@ protected:
|
|||
PRUint32 mStreamBlock;
|
||||
// Time at which this block was last used. Valid only if
|
||||
// mClass is METADATA_BLOCK or PLAYED_BLOCK.
|
||||
PRIntervalTime mLastUseTime;
|
||||
TimeStamp mLastUseTime;
|
||||
// The class is FREE_BLOCK if and only if mStream is null
|
||||
BlockClass mClass;
|
||||
// Next and previous blocks of this class (circular links, so
|
||||
|
@ -245,9 +249,9 @@ protected:
|
|||
void InsertReadaheadBlock(PRInt32 aBlockIndex);
|
||||
|
||||
// Guess the duration until block aBlock will be next used
|
||||
PRIntervalTime PredictNextUse(PRIntervalTime aNow, PRInt32 aBlock);
|
||||
TimeDuration PredictNextUse(TimeStamp aNow, PRInt32 aBlock);
|
||||
// Guess the duration until the next incoming data on aStream will be used
|
||||
PRIntervalTime PredictNextUseForIncomingData(nsMediaCacheStream* aStream);
|
||||
TimeDuration PredictNextUseForIncomingData(nsMediaCacheStream* aStream);
|
||||
|
||||
// Truncate the file and index array if there are free blocks at the
|
||||
// end
|
||||
|
@ -537,7 +541,7 @@ static PRInt32 GetMaxBlocks()
|
|||
}
|
||||
|
||||
PRInt32
|
||||
nsMediaCache::FindBlockForIncomingData(PRIntervalTime aNow,
|
||||
nsMediaCache::FindBlockForIncomingData(TimeStamp aNow,
|
||||
nsMediaCacheStream* aStream)
|
||||
{
|
||||
PR_ASSERT_CURRENT_THREAD_IN_MONITOR(mMonitor);
|
||||
|
@ -591,7 +595,7 @@ nsMediaCache::AppendMostReusableBlock(BlockList* aBlockList,
|
|||
}
|
||||
|
||||
PRInt32
|
||||
nsMediaCache::FindReusableBlock(PRIntervalTime aNow,
|
||||
nsMediaCache::FindReusableBlock(TimeStamp aNow,
|
||||
nsMediaCacheStream* aForStream,
|
||||
PRInt32 aForStreamBlock,
|
||||
PRInt32 aMaxSearchBlockIndex)
|
||||
|
@ -651,10 +655,10 @@ nsMediaCache::FindReusableBlock(PRIntervalTime aNow,
|
|||
}
|
||||
}
|
||||
|
||||
PRIntervalTime latestUse = 0;
|
||||
TimeDuration latestUse;
|
||||
PRInt32 latestUseBlock = -1;
|
||||
for (PRUint32 i = 0; i < candidates.Length(); ++i) {
|
||||
PRIntervalTime nextUse = PredictNextUse(aNow, candidates[i]);
|
||||
TimeDuration nextUse = PredictNextUse(aNow, candidates[i]);
|
||||
if (nextUse > latestUse) {
|
||||
latestUse = nextUse;
|
||||
latestUseBlock = candidates[i];
|
||||
|
@ -767,8 +771,8 @@ nsMediaCache::FreeBlock(PRInt32 aBlock)
|
|||
Verify();
|
||||
}
|
||||
|
||||
PRIntervalTime
|
||||
nsMediaCache::PredictNextUse(PRIntervalTime aNow, PRInt32 aBlock)
|
||||
TimeDuration
|
||||
nsMediaCache::PredictNextUse(TimeStamp aNow, PRInt32 aBlock)
|
||||
{
|
||||
PR_ASSERT_CURRENT_THREAD_IN_MONITOR(mMonitor);
|
||||
|
||||
|
@ -785,7 +789,8 @@ nsMediaCache::PredictNextUse(PRIntervalTime aNow, PRInt32 aBlock)
|
|||
NS_ASSERTION(PRInt64(block->mStreamBlock)*BLOCK_SIZE <
|
||||
block->mStream->mStreamOffset,
|
||||
"Played block after the current stream position?");
|
||||
return aNow - block->mLastUseTime + PR_SecondsToInterval(REPLAY_DELAY);
|
||||
return aNow - block->mLastUseTime +
|
||||
TimeDuration::FromSeconds(REPLAY_DELAY);
|
||||
case READAHEAD_BLOCK: {
|
||||
PRInt64 bytesAhead =
|
||||
PRInt64(block->mStreamBlock)*BLOCK_SIZE - block->mStream->mStreamOffset;
|
||||
|
@ -793,15 +798,16 @@ nsMediaCache::PredictNextUse(PRIntervalTime aNow, PRInt32 aBlock)
|
|||
"Readahead block before the current stream position?");
|
||||
PRInt64 millisecondsAhead =
|
||||
bytesAhead*1000/block->mStream->mPlaybackBytesPerSecond;
|
||||
return PR_MillisecondsToInterval(PRUint32(PR_MIN(millisecondsAhead, PR_INT32_MAX)));
|
||||
return TimeDuration::FromMilliseconds(
|
||||
PR_MIN(millisecondsAhead, PR_INT32_MAX));
|
||||
}
|
||||
default:
|
||||
NS_ERROR("Invalid class for predicting next use");
|
||||
return 0;
|
||||
return TimeDuration(0);
|
||||
}
|
||||
}
|
||||
|
||||
PRIntervalTime
|
||||
TimeDuration
|
||||
nsMediaCache::PredictNextUseForIncomingData(nsMediaCacheStream* aStream)
|
||||
{
|
||||
PR_ASSERT_CURRENT_THREAD_IN_MONITOR(mMonitor);
|
||||
|
@ -809,12 +815,13 @@ nsMediaCache::PredictNextUseForIncomingData(nsMediaCacheStream* aStream)
|
|||
PRInt64 bytesAhead = aStream->mChannelOffset - aStream->mStreamOffset;
|
||||
if (bytesAhead <= -BLOCK_SIZE) {
|
||||
// Hmm, no idea when data behind us will be used. Guess 24 hours.
|
||||
return PR_SecondsToInterval(24*60*60);
|
||||
return TimeDuration::FromSeconds(24*60*60);
|
||||
}
|
||||
if (bytesAhead <= 0)
|
||||
return PR_SecondsToInterval(0);
|
||||
return TimeDuration(0);
|
||||
PRInt64 millisecondsAhead = bytesAhead*1000/aStream->mPlaybackBytesPerSecond;
|
||||
return PR_MillisecondsToInterval(PRUint32(PR_MIN(millisecondsAhead, PR_INT32_MAX)));
|
||||
return TimeDuration::FromMilliseconds(
|
||||
PR_MIN(millisecondsAhead, PR_INT32_MAX));
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -829,7 +836,7 @@ nsMediaCache::Update()
|
|||
#endif
|
||||
|
||||
PRInt32 maxBlocks = GetMaxBlocks();
|
||||
PRIntervalTime now = PR_IntervalNow();
|
||||
TimeStamp now = TimeStamp::Now();
|
||||
|
||||
PRInt32 freeBlockCount = mFreeBlocks.GetCount();
|
||||
// Try to trim back the cache to its desired maximum size. The cache may
|
||||
|
@ -846,7 +853,7 @@ nsMediaCache::Update()
|
|||
// to avoid that since it requires HTTP seeks.
|
||||
// We also use this loop to eliminate overflowing blocks from
|
||||
// freeBlockCount.
|
||||
PRIntervalTime latestPredictedUseForOverflow = 0;
|
||||
TimeDuration latestPredictedUseForOverflow = 0;
|
||||
for (PRInt32 blockIndex = mIndex.Length() - 1; blockIndex >= maxBlocks;
|
||||
--blockIndex) {
|
||||
nsMediaCacheStream* stream = mIndex[blockIndex].mStream;
|
||||
|
@ -855,7 +862,7 @@ nsMediaCache::Update()
|
|||
--freeBlockCount;
|
||||
continue;
|
||||
}
|
||||
PRIntervalTime predictedUse = PredictNextUse(now, blockIndex);
|
||||
TimeDuration predictedUse = PredictNextUse(now, blockIndex);
|
||||
latestPredictedUseForOverflow = PR_MAX(latestPredictedUseForOverflow, predictedUse);
|
||||
}
|
||||
|
||||
|
@ -926,7 +933,7 @@ nsMediaCache::Update()
|
|||
|
||||
// If freeBlockCount is zero, then compute the latest of
|
||||
// the predicted next-uses for all blocks
|
||||
PRIntervalTime latestNextUse = 0;
|
||||
TimeDuration latestNextUse;
|
||||
if (freeBlockCount == 0) {
|
||||
PRInt32 reusableBlock = FindReusableBlock(now, nsnull, 0, maxBlocks);
|
||||
if (reusableBlock >= 0) {
|
||||
|
@ -1006,16 +1013,16 @@ nsMediaCache::Update()
|
|||
// Free blocks in the cache, so keep reading
|
||||
LOG(PR_LOG_DEBUG, ("Stream %p reading since there are free blocks", stream));
|
||||
enableReading = PR_TRUE;
|
||||
} else if (latestNextUse <= 0) {
|
||||
} else if (latestNextUse <= TimeDuration(0)) {
|
||||
// No reusable blocks, so can't read anything
|
||||
LOG(PR_LOG_DEBUG, ("Stream %p throttling due to no reusable blocks", stream));
|
||||
enableReading = PR_FALSE;
|
||||
} else {
|
||||
// Read ahead if the data we expect to read is more valuable than
|
||||
// the least valuable block in the main part of the cache
|
||||
PRIntervalTime predictedNewDataUse = PredictNextUseForIncomingData(stream);
|
||||
LOG(PR_LOG_DEBUG, ("Stream %p predict next data in %lld, current worst block is %lld",
|
||||
stream, (long long)predictedNewDataUse, (long long)latestNextUse));
|
||||
TimeDuration predictedNewDataUse = PredictNextUseForIncomingData(stream);
|
||||
LOG(PR_LOG_DEBUG, ("Stream %p predict next data in %f, current worst block is %f",
|
||||
stream, predictedNewDataUse.ToSeconds(), latestNextUse.ToSeconds()));
|
||||
enableReading = predictedNewDataUse < latestNextUse;
|
||||
}
|
||||
|
||||
|
@ -1167,7 +1174,7 @@ nsMediaCache::AllocateAndWriteBlock(nsMediaCacheStream* aStream, const void* aDa
|
|||
FreeBlock(globalBlockIndex);
|
||||
}
|
||||
|
||||
PRIntervalTime now = PR_IntervalNow();
|
||||
TimeStamp now = TimeStamp::Now();
|
||||
PRInt32 blockIndex = FindBlockForIncomingData(now, aStream);
|
||||
if (blockIndex >= 0) {
|
||||
Block* block = &mIndex[blockIndex];
|
||||
|
@ -1273,7 +1280,7 @@ nsMediaCache::Truncate()
|
|||
void
|
||||
nsMediaCache::NoteBlockUsage(PRInt32 aBlockIndex,
|
||||
nsMediaCacheStream::ReadMode aMode,
|
||||
PRIntervalTime aNow)
|
||||
TimeStamp aNow)
|
||||
{
|
||||
PR_ASSERT_CURRENT_THREAD_IN_MONITOR(mMonitor);
|
||||
|
||||
|
@ -1300,7 +1307,7 @@ nsMediaCache::NoteBlockUsage(PRInt32 aBlockIndex,
|
|||
// Since this is just being used now, it can definitely be at the front
|
||||
// of mMetadataBlocks or mPlayedBlocks
|
||||
GetListForBlock(block)->AddFirstBlock(aBlockIndex);
|
||||
block->mLastUseTime = PR_IntervalNow();
|
||||
block->mLastUseTime = aNow;
|
||||
Verify();
|
||||
}
|
||||
|
||||
|
@ -1317,7 +1324,7 @@ nsMediaCache::NoteSeek(nsMediaCacheStream* aStream, PRInt64 aOldOffset)
|
|||
PRInt32 endIndex =
|
||||
PR_MIN((aStream->mStreamOffset + BLOCK_SIZE - 1)/BLOCK_SIZE,
|
||||
aStream->mBlocks.Length());
|
||||
PRIntervalTime now = PR_IntervalNow();
|
||||
TimeStamp now = TimeStamp::Now();
|
||||
while (blockIndex < endIndex) {
|
||||
PRInt32 cacheBlockIndex = aStream->mBlocks[blockIndex];
|
||||
if (cacheBlockIndex >= 0) {
|
||||
|
@ -1686,7 +1693,7 @@ nsMediaCacheStream::Read(char* aBuffer, PRUint32 aCount, PRUint32* aBytes)
|
|||
if (mCurrentMode == MODE_METADATA) {
|
||||
mMetadataInPartialBlockBuffer = PR_TRUE;
|
||||
}
|
||||
gMediaCache->NoteBlockUsage(cacheBlock, mCurrentMode, PR_IntervalNow());
|
||||
gMediaCache->NoteBlockUsage(cacheBlock, mCurrentMode, TimeStamp::Now());
|
||||
} else {
|
||||
if (cacheBlock < 0) {
|
||||
if (count > 0) {
|
||||
|
@ -1705,7 +1712,7 @@ nsMediaCacheStream::Read(char* aBuffer, PRUint32 aCount, PRUint32* aBytes)
|
|||
continue;
|
||||
}
|
||||
|
||||
gMediaCache->NoteBlockUsage(cacheBlock, mCurrentMode, PR_IntervalNow());
|
||||
gMediaCache->NoteBlockUsage(cacheBlock, mCurrentMode, TimeStamp::Now());
|
||||
|
||||
PRInt64 offset = cacheBlock*BLOCK_SIZE + offsetInStreamBlock;
|
||||
nsresult rv = gMediaCache->ReadCacheFile(offset, aBuffer + count, size, &bytes);
|
||||
|
|
Загрузка…
Ссылка в новой задаче