Bug 513144. Make nsMediaChannelStream::CloneData clone the underlying cache stream, which adds the new stream as co-owner of all the nsMediaCache blocks currently cached for the original stream. Also, use NS_NEW_RUNNABLE_METHOD instead of the SuspendedStatusChanged class. r=doublec

--HG--
extra : rebase_source : 982c38bf513865033a2c51554ded3f3f365eeb3a
This commit is contained in:
Robert O'Callahan 2009-09-15 14:30:44 +12:00
parent cc7de63946
commit 3f9249f428
3 changed files with 73 additions and 29 deletions

View File

@ -159,6 +159,9 @@ public:
// call QueueUpdate().
void NoteBlockUsage(nsMediaCacheStream* aStream, PRInt32 aBlockIndex,
nsMediaCacheStream::ReadMode aMode, TimeStamp aNow);
// Mark aStream as having the block, adding it as an owner.
void AddBlockOwnerAsReadahead(PRInt32 aBlockIndex, nsMediaCacheStream* aStream,
PRInt32 aStreamBlockIndex);
// This queues a call to Update() on the main thread.
void QueueUpdate();
@ -840,6 +843,23 @@ nsMediaCache::RemoveBlockOwner(PRInt32 aBlockIndex, nsMediaCacheStream* aStream)
}
}
void
nsMediaCache::AddBlockOwnerAsReadahead(PRInt32 aBlockIndex,
nsMediaCacheStream* aStream,
PRInt32 aStreamBlockIndex)
{
Block* block = &mIndex[aBlockIndex];
if (block->mOwners.IsEmpty()) {
mFreeBlocks.RemoveBlock(aBlockIndex);
}
BlockOwner* bo = block->mOwners.AppendElement();
bo->mStream = aStream;
bo->mStreamBlock = aStreamBlockIndex;
aStream->mBlocks[aStreamBlockIndex] = aBlockIndex;
bo->mClass = READAHEAD_BLOCK;
InsertReadaheadBlock(bo, aBlockIndex);
}
void
nsMediaCache::FreeBlock(PRInt32 aBlock)
{
@ -1996,9 +2016,44 @@ nsMediaCacheStream::Init()
{
NS_ASSERTION(NS_IsMainThread(), "Only call on main thread");
if (mInitialized)
return NS_OK;
InitMediaCache();
if (!gMediaCache)
return NS_ERROR_FAILURE;
gMediaCache->OpenStream(this);
mInitialized = PR_TRUE;
return NS_OK;
}
nsresult
nsMediaCacheStream::InitAsClone(nsMediaCacheStream* aOriginal)
{
if (mInitialized)
return NS_OK;
nsresult rv = Init();
if (NS_FAILED(rv))
return rv;
// Grab cache blocks from aOriginal as readahead blocks for our stream
nsAutoMonitor mon(gMediaCache->Monitor());
mPrincipal = aOriginal->mPrincipal;
mStreamLength = aOriginal->mStreamLength;
mIsSeekable = aOriginal->mIsSeekable;
for (PRUint32 i = 0; i < aOriginal->mBlocks.Length(); ++i) {
PRInt32 cacheBlockIndex = aOriginal->mBlocks[i];
if (cacheBlockIndex < 0)
continue;
while (i >= mBlocks.Length()) {
mBlocks.AppendElement(-1);
}
gMediaCache->AddBlockOwnerAsReadahead(cacheBlockIndex, this, i);
}
return NS_OK;
}

View File

@ -222,17 +222,24 @@ public:
nsMediaCacheStream(nsMediaChannelStream* aClient)
: mClient(aClient), mChannelOffset(0),
mStreamOffset(0), mStreamLength(-1), mPlaybackBytesPerSecond(10000),
mPinCount(0), mCurrentMode(MODE_PLAYBACK), mClosed(PR_FALSE),
mPinCount(0), mCurrentMode(MODE_PLAYBACK),
mInitialized(PR_FALSE), mClosed(PR_FALSE),
mIsSeekable(PR_FALSE), mCacheSuspended(PR_FALSE),
mMetadataInPartialBlockBuffer(PR_FALSE),
mUsingNullPrincipal(PR_FALSE) {}
~nsMediaCacheStream();
// Set up this stream with the cache. Can fail on OOM. Must be called
// before other methods on this object; no other methods may be called
// if this fails.
// Set up this stream with the cache. Can fail on OOM. One
// of InitAsClone or Init must be called before any other method on
// this class. Does nothing if already initialized.
nsresult Init();
// Set up this stream with the cache, assuming it's for the same data
// as the aOriginal stream. Can fail on OOM. Exactly one
// of InitAsClone or Init must be called before any other method on
// this class. Does nothing if already initialized.
nsresult InitAsClone(nsMediaCacheStream* aOriginal);
// These are called on the main thread.
// Tell us whether the stream is seekable or not. Non-seekable streams
// will always pass 0 for aOffset to CacheClientSeek. This should only
@ -447,6 +454,8 @@ private:
PRUint32 mPinCount;
// The last reported read mode
ReadMode mCurrentMode;
// Set to true when Init or InitAsClone has been called
PRPackedBool mInitialized;
// Set to true when the stream has been closed either explicitly or
// due to an internal cache error
PRPackedBool mClosed;

View File

@ -452,7 +452,7 @@ nsMediaStream* nsMediaChannelStream::CloneData(nsMediaDecoder* aDecoder)
nsMediaChannelStream* stream = new nsMediaChannelStream(aDecoder, nsnull, mURI);
if (stream) {
stream->RecreateChannel();
// XXXroc need to clone mCacheStream's data here
stream->mCacheStream.InitAsClone(&mCacheStream);
}
return stream;
}
@ -614,28 +614,6 @@ nsMediaChannelStream::CacheClientSeek(PRInt64 aOffset, PRBool aResume)
return OpenChannel(nsnull);
}
class SuspendedStatusChanged : public nsRunnable
{
public:
SuspendedStatusChanged(nsMediaDecoder* aDecoder) :
mDecoder(aDecoder)
{
MOZ_COUNT_CTOR(SuspendedStatusChanged);
}
~SuspendedStatusChanged()
{
MOZ_COUNT_DTOR(SuspendedStatusChanged);
}
NS_IMETHOD Run() {
mDecoder->NotifySuspendedStatusChanged();
return NS_OK;
}
private:
nsRefPtr<nsMediaDecoder> mDecoder;
};
nsresult
nsMediaChannelStream::CacheClientSuspend()
{
@ -648,7 +626,8 @@ nsMediaChannelStream::CacheClientSuspend()
// We have to spawn an event here since we're being called back from
// a sensitive place in nsMediaCache, which doesn't want us to reenter
// the decoder and cause deadlocks or other unpleasantness
nsCOMPtr<nsIRunnable> event = new SuspendedStatusChanged(mDecoder);
nsCOMPtr<nsIRunnable> event =
NS_NEW_RUNNABLE_METHOD(nsMediaDecoder, mDecoder, NotifySuspendedStatusChanged);
NS_DispatchToMainThread(event, NS_DISPATCH_NORMAL);
return NS_OK;
}
@ -665,7 +644,8 @@ nsMediaChannelStream::CacheClientResume()
// We have to spawn an event here since we're being called back from
// a sensitive place in nsMediaCache, which doesn't want us to reenter
// the decoder and cause deadlocks or other unpleasantness
nsCOMPtr<nsIRunnable> event = new SuspendedStatusChanged(mDecoder);
nsCOMPtr<nsIRunnable> event =
NS_NEW_RUNNABLE_METHOD(nsMediaDecoder, mDecoder, NotifySuspendedStatusChanged);
NS_DispatchToMainThread(event, NS_DISPATCH_NORMAL);
return NS_OK;
}