Bug 1371882 - MediaCache uses MemoryBlockCache when content length is known - r=cpearce
MozReview-Commit-ID: 35A4Vc95NtB
--- a/dom/media/MediaCache.cpp
+++ b/dom/media/MediaCache.cpp
@@ -10,16 +10,17 @@
#include "prio.h"
#include "nsContentUtils.h"
#include "nsThreadUtils.h"
#include "MediaResource.h"
#include "mozilla/Logging.h"
#include "mozilla/Preferences.h"
#include "FileBlockCache.h"
#include "MediaBlockCacheBase.h"
+#include "MemoryBlockCache.h"
#include "nsIObserverService.h"
#include "nsISeekableStream.h"
#include "nsIPrincipal.h"
#include "mozilla/Attributes.h"
#include "mozilla/Services.h"
#include "mozilla/StaticPtr.h"
#include "mozilla/Telemetry.h"
#include <algorithm>
@@ -252,18 +253,19 @@ public:
}
private:
MediaCache* mMediaCache;
int64_t mResourceID;
uint32_t mNext;
};
protected:
- MediaCache()
- : mNextResourceID(1)
+ explicit MediaCache(int64_t aContentLength)
+ : mContentLength(aContentLength)
+ , mNextResourceID(1)
, mReentrantMonitor("MediaCache.mReentrantMonitor")
, mUpdateQueued(false)
, mShutdownInsteadOfUpdating(false)
#ifdef DEBUG
, mInUpdate(false)
#endif
{
MOZ_COUNT_CTOR(MediaCache);
@@ -275,28 +277,32 @@ protected:
MediaCacheFlusher::UnregisterMediaCache(this);
NS_ASSERTION(mStreams.IsEmpty(), "Stream(s) still open!");
Truncate();
NS_ASSERTION(mIndex.Length() == 0, "Blocks leaked?");
if (mBlockCache) {
mBlockCache->Close();
mBlockCache = nullptr;
}
- LOG("MediaCache::~MediaCache(this=%p) MEDIACACHE_WATERMARK_KB=%u",
- this,
- unsigned(mIndexWatermark * MediaCache::BLOCK_SIZE / 1024));
- Telemetry::Accumulate(
- Telemetry::HistogramID::MEDIACACHE_WATERMARK_KB,
- uint32_t(mIndexWatermark * MediaCache::BLOCK_SIZE / 1024));
- LOG("MediaCache::~MediaCache(this=%p) MEDIACACHE_BLOCKOWNERS_WATERMARK=%u",
+ if (mContentLength <= 0) {
+ // Only gather "MEDIACACHE" telemetry for the file-based cache.
+ LOG("MediaCache::~MediaCache(this=%p) MEDIACACHE_WATERMARK_KB=%u",
+ this,
+ unsigned(mIndexWatermark * MediaCache::BLOCK_SIZE / 1024));
+ Telemetry::Accumulate(
+ Telemetry::HistogramID::MEDIACACHE_WATERMARK_KB,
+ uint32_t(mIndexWatermark * MediaCache::BLOCK_SIZE / 1024));
+ LOG(
+ "MediaCache::~MediaCache(this=%p) MEDIACACHE_BLOCKOWNERS_WATERMARK=%u",
this,
unsigned(mBlockOwnersWatermark));
- Telemetry::Accumulate(
- Telemetry::HistogramID::MEDIACACHE_BLOCKOWNERS_WATERMARK,
- mBlockOwnersWatermark);
+ Telemetry::Accumulate(
+ Telemetry::HistogramID::MEDIACACHE_BLOCKOWNERS_WATERMARK,
+ mBlockOwnersWatermark);
+ }
MOZ_COUNT_DTOR(MediaCache);
}
// Main thread only. Creates the backing cache file. If this fails,
// then the cache is still in a semi-valid state; mFD will be null,
// so all I/O on the cache file will fail.
nsresult Init();
@@ -393,16 +399,21 @@ protected:
// Shutdown this MediaCache, and reset gMediaCache if we are the global one.
// If there is no queued update, destroy the MediaCache immediately.
// Otherwise when the update is processed, it will destroy the MediaCache.
void ShutdownAndDestroyThis();
// There is at most one file-backed media cache.
static MediaCache* gMediaCache;
+ // Expected content length if known initially from the HTTP Content-Length
+ // header (this is a memory-backed MediaCache), otherwise -1 (file-backed
+ // MediaCache).
+ const int64_t mContentLength;
+
// This member is main-thread only. It's used to allocate unique
// resource IDs to streams.
int64_t mNextResourceID;
// The monitor protects all the data members here. Also, off-main-thread
// readers that need to block will Wait() on this monitor. When new
// data becomes available in the cache, we NotifyAll() on this monitor.
ReentrantMonitor mReentrantMonitor;
@@ -660,17 +671,23 @@ MediaCacheStream::BlockList::NotifyBlock
}
nsresult
MediaCache::Init()
{
NS_ASSERTION(NS_IsMainThread(), "Only call on main thread");
NS_ASSERTION(!mBlockCache, "Block cache already open?");
- mBlockCache = new FileBlockCache();
+ if (mContentLength <= 0) {
+ // The global MediaCache uses a file-backed storage for its resource blocks.
+ mBlockCache = new FileBlockCache();
+ } else {
+ // Non-global MediaCaches keep the whole resource in memory.
+ mBlockCache = new MemoryBlockCache(mContentLength);
+ }
nsresult rv = mBlockCache->Init();
NS_ENSURE_SUCCESS(rv,rv);
return NS_OK;
}
void
MediaCache::Flush()
@@ -742,31 +759,31 @@ MediaCache::ShutdownAndDestroyThis()
/* static */ MediaCache*
MediaCache::GetMediaCache(int64_t aContentLength)
{
NS_ASSERTION(NS_IsMainThread(), "Only call on main thread");
if (aContentLength > 0 &&
aContentLength <=
int64_t(MediaPrefs::MediaMemoryCacheMaxSize()) * 1024) {
// Small-enough resource, use a new memory-backed MediaCache.
- MediaCache* mc = new MediaCache();
+ MediaCache* mc = new MediaCache(aContentLength);
nsresult rv = mc->Init();
if (NS_SUCCEEDED(rv)) {
return mc;
}
// Memory-backed MediaCache initialization failed, clean up and try for a
// file-backed MediaCache below.
delete mc;
}
if (gMediaCache) {
return gMediaCache;
}
- gMediaCache = new MediaCache();
+ gMediaCache = new MediaCache(-1);
nsresult rv = gMediaCache->Init();
if (NS_FAILED(rv)) {
delete gMediaCache;
gMediaCache = nullptr;
}
return gMediaCache;
}