Bug 639391 - Make nsMediaStream responsible for determining cached media data in a threadsafe manner. r=roc

This commit is contained in:
Chris Pearce 2011-03-24 11:28:58 +13:00
Родитель 36d6e56061
Коммит f709c45bea
4 изменённых файлов: 74 добавлений и 0 удалений

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

@ -2293,3 +2293,26 @@ nsMediaCacheStream::InitAsClone(nsMediaCacheStream* aOriginal)
return NS_OK;
}
nsresult nsMediaCacheStream::GetCachedRanges(nsTArray<nsByteRange>& aRanges)
{
// Take the monitor, so that the cached data ranges can't grow while we're
// trying to loop over them.
nsAutoMonitor mon(gMediaCache->Monitor());
// 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");
PRInt64 startOffset = GetNextCachedData(0);
while (startOffset >= 0) {
PRInt64 endOffset = GetCachedDataEnd(startOffset);
NS_ASSERTION(startOffset < endOffset, "Buffered range must end after its start");
// Bytes [startOffset..endOffset] are cached.
aRanges.AppendElement(nsByteRange(startOffset, endOffset));
startOffset = GetNextCachedData(endOffset);
NS_ASSERTION(startOffset == -1 || startOffset > endOffset,
"Must have advanced to start of next range, or hit end of stream");
}
return NS_OK;
}

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

@ -44,6 +44,8 @@
#include "nsIPrincipal.h"
#include "nsCOMPtr.h"
class nsByteRange;
/**
* Media applications want fast, "on demand" random access to media data,
* for pausing, seeking, etc. But we are primarily interested
@ -310,6 +312,11 @@ public:
// Returns the offset of the first byte of cached data at or after aOffset,
// or -1 if there is no such cached data.
PRInt64 GetNextCachedData(PRInt64 aOffset);
// Fills aRanges with the ByteRanges representing the data which is currently
// cached. Locks the media cache while running, to prevent any ranges
// growing. The stream should be pinned while this runs and while its results
// are used, to ensure no data is evicted.
nsresult GetCachedRanges(nsTArray<nsByteRange>& aRanges);
// Reads from buffered data only. Will fail if not all data to be read is
// in the cache. Will not mark blocks as read. Can be called from the main

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

@ -605,6 +605,11 @@ PRInt64 nsMediaChannelStream::Tell()
return mCacheStream.Tell();
}
nsresult nsMediaChannelStream::GetCachedRanges(nsTArray<nsByteRange>& aRanges)
{
return mCacheStream.GetCachedRanges(aRanges);
}
void nsMediaChannelStream::Suspend(PRBool aCloseImmediately)
{
NS_ASSERTION(NS_IsMainThread(), "Don't call on non-main thread");
@ -919,6 +924,8 @@ public:
virtual PRBool IsSuspendedByCache() { return PR_FALSE; }
virtual PRBool IsSuspended() { return PR_FALSE; }
nsresult GetCachedRanges(nsTArray<nsByteRange>& aRanges);
private:
// The file size, or -1 if not known. Immutable after Open().
PRInt64 mSize;
@ -961,6 +968,15 @@ private:
nsRefPtr<nsMediaDecoder> mDecoder;
};
nsresult nsMediaFileStream::GetCachedRanges(nsTArray<nsByteRange>& aRanges)
{
if (mSize == -1) {
return NS_ERROR_FAILURE;
}
aRanges.AppendElement(nsByteRange(0, mSize));
return NS_OK;
}
nsresult nsMediaFileStream::Open(nsIStreamListener** aStreamListener)
{
NS_ASSERTION(NS_IsMainThread(), "Only call on main thread");

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

@ -127,6 +127,25 @@ private:
PRPackedBool mIsStarted;
};
// Represents a section of contiguous media, with a start and end offset.
// Used to denote ranges of data which are cached.
class nsByteRange {
public:
nsByteRange() : mStart(0), mEnd(0) {}
nsByteRange(PRInt64 aStart, PRInt64 aEnd)
: mStart(aStart), mEnd(aEnd)
{
NS_ASSERTION(mStart < mEnd, "Range should end after start!");
}
PRBool IsNull() const {
return mStart == 0 && mEnd == 0;
}
PRInt64 mStart, mEnd;
};
/*
Provides the ability to open, read and seek into a media stream
(audio, video). Handles the underlying machinery to do range
@ -275,6 +294,13 @@ public:
*/
virtual nsresult Open(nsIStreamListener** aStreamListener) = 0;
/**
* Fills aRanges with ByteRanges representing the data which is cached
* in the media cache. Stream should be pinned during call and while
* aRanges is being used.
*/
virtual nsresult GetCachedRanges(nsTArray<nsByteRange>& aRanges) = 0;
protected:
nsMediaStream(nsMediaDecoder* aDecoder, nsIChannel* aChannel, nsIURI* aURI) :
mDecoder(aDecoder),
@ -395,6 +421,8 @@ public:
};
friend class Listener;
nsresult GetCachedRanges(nsTArray<nsByteRange>& aRanges);
protected:
// These are called on the main thread by Listener.
nsresult OnStartRequest(nsIRequest* aRequest);