Bug 1371882 - MediaCacheStream::Init forwards the known content length to the MediaCache factory - r=cpearce
This will give enough information (for now) for GetMediaCache to decide whether
to use the (one global shared) file-backed MediaCache, or a discrete memory-
backed MediaCache.
(Note that GetMediaCache doesn't use this length yet in this patch.)
MozReview-Commit-ID: 5B2E3sIsc4k
--- a/dom/media/MediaCache.cpp
+++ b/dom/media/MediaCache.cpp
@@ -123,19 +123,25 @@ MediaCacheFlusher::UnregisterMediaCache(
}
class MediaCache {
public:
friend class MediaCacheStream::BlockList;
typedef MediaCacheStream::BlockList BlockList;
static const int64_t BLOCK_SIZE = MediaCacheStream::BLOCK_SIZE;
- // Get an instance of the file-backed MediaCache.
- // Returns nullptr if initialization failed.
- static MediaCache* GetMediaCache();
+ // Get an instance of a MediaCache (or nullptr if initialization failed).
+ // aContentLength is the content length if known already, otherwise -1.
+ // If the length is known and considered small enough, a discrete MediaCache
+ // with memory backing will be given. Otherwise the one MediaCache with
+ // file backing will be provided.
+ // The caller adds a reference to the MediaCache object by calling
+ // OpenStream(); and later must release it by calling ReleaseStream() and
+ // then MaybeShutdown().
+ static MediaCache* GetMediaCache(int64_t aContentLength);
// Shut down the cache if it's no longer needed. We shut down
// the cache as soon as there are no streams. This means that during
// normal operation we are likely to start up the cache and shut it down
// many times, but that's OK since starting it up is cheap and
// shutting it down cleans things up and releases disk space.
void MaybeShutdown();
@@ -728,17 +734,17 @@ MediaCache::ShutdownAndDestroyThis()
mShutdownInsteadOfUpdating = true;
return;
}
delete this;
}
/* static */ MediaCache*
-MediaCache::GetMediaCache()
+MediaCache::GetMediaCache(int64_t aContentLength)
{
NS_ASSERTION(NS_IsMainThread(), "Only call on main thread");
if (gMediaCache) {
return gMediaCache;
}
gMediaCache = new MediaCache();
nsresult rv = gMediaCache->Init();
@@ -2533,25 +2539,29 @@ MediaCacheStream::ReadFromCache(char* aB
streamOffset += bytes;
count += bytes;
}
return NS_OK;
}
nsresult
-MediaCacheStream::Init()
+MediaCacheStream::Init(int64_t aContentLength)
{
NS_ASSERTION(NS_IsMainThread(), "Only call on main thread");
if (mMediaCache) {
return NS_OK;
}
- mMediaCache = MediaCache::GetMediaCache();
+ if (aContentLength > 0) {
+ mStreamLength = aContentLength;
+ }
+
+ mMediaCache = MediaCache::GetMediaCache(aContentLength);
if (!mMediaCache) {
return NS_ERROR_FAILURE;
}
mMediaCache->OpenStream(this);
return NS_OK;
}
nsresult
@@ -2559,19 +2569,22 @@ MediaCacheStream::InitAsClone(MediaCache
{
if (!aOriginal->IsAvailableForSharing())
return NS_ERROR_FAILURE;
if (mMediaCache) {
return NS_OK;
}
- nsresult rv = Init();
- if (NS_FAILED(rv))
- return rv;
+ NS_ASSERTION(aOriginal->mMediaCache, "Don't clone an uninitialized stream");
+ // Use the same MediaCache as our clone.
+ mMediaCache = aOriginal->mMediaCache;
+
+ mMediaCache->OpenStream(this);
+
mResourceID = aOriginal->mResourceID;
// Grab cache blocks from aOriginal as readahead blocks for our stream
ReentrantMonitorAutoEnter mon(mMediaCache->GetReentrantMonitor());
mPrincipal = aOriginal->mPrincipal;
mStreamLength = aOriginal->mStreamLength;
mIsTransportSeekable = aOriginal->mIsTransportSeekable;
--- a/dom/media/MediaCache.h
+++ b/dom/media/MediaCache.h
@@ -193,25 +193,26 @@ public:
MODE_PLAYBACK
};
// aClient provides the underlying transport that cache will use to read
// data for this stream.
MediaCacheStream(ChannelMediaResource* aClient, bool aIsPrivateBrowsing);
~MediaCacheStream();
- // 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. Can fail on OOM.
+ // aContentLength is the content length if known, otherwise -1.
+ // Exactly one of InitAsClone or Init must be called before any other method
+ // on this class. Does nothing if already initialized.
+ nsresult Init(int64_t aContentLength);
// 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.
+ // 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(MediaCacheStream* 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
// be called while the stream is at channel offset 0. Seekability can
// change during the lifetime of the MediaCacheStream --- every time
// we do an HTTP load the seekability may be different (and sometimes
--- a/dom/media/MediaResource.cpp
+++ b/dom/media/MediaResource.cpp
@@ -527,17 +527,27 @@ ChannelMediaResource::OnDataAvailable(ns
return NS_OK;
}
nsresult ChannelMediaResource::Open(nsIStreamListener **aStreamListener)
{
NS_ASSERTION(NS_IsMainThread(), "Only call on main thread");
- nsresult rv = mCacheStream.Init();
+ int64_t cl = -1;
+ if (mChannel) {
+ nsCOMPtr<nsIHttpChannel> hc = do_QueryInterface(mChannel);
+ if (hc) {
+ if (NS_FAILED(hc->GetContentLength(&cl))) {
+ cl = -1;
+ }
+ }
+ }
+
+ nsresult rv = mCacheStream.Init(cl);
if (NS_FAILED(rv))
return rv;
NS_ASSERTION(mOffset == 0, "Who set mOffset already?");
if (!mChannel) {
// When we're a clone, the decoder might ask us to Open even though
// we haven't established an mChannel (because we might not need one)
NS_ASSERTION(!aStreamListener,