Bug 486991. Convert nsMediaCache to use TimeStmap/TimeDuration. r=doublec

This commit is contained in:
Robert O'Callahan 2009-04-11 21:39:02 +12:00
Родитель 5457f988ef
Коммит fa2d01d562
2 изменённых файлов: 40 добавлений и 34 удалений

Просмотреть файл

@ -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);