author | Chris Pearce <cpearce@mozilla.com> |
Wed, 29 Aug 2012 15:55:57 +1200 | |
changeset 110034 | e6517dae3b952faed11a8c5e4f7e9f23d98a0278 |
parent 110033 | 4a4696fcfd03c2a81c4f442fdab6a5ab9da37dc0 |
child 110035 | 747584155b62aaf0c2a9919104c730df29fe63d1 |
push id | 1708 |
push user | akeybl@mozilla.com |
push date | Mon, 19 Nov 2012 21:10:21 +0000 |
treeherder | mozilla-beta@27b14fe50103 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | roc |
bugs | 785909 |
milestone | 18.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/content/media/MediaResource.cpp +++ b/content/media/MediaResource.cpp @@ -913,17 +913,18 @@ ChannelMediaResource::PossiblyResume() } } class FileMediaResource : public MediaResource { public: FileMediaResource(nsMediaDecoder* aDecoder, nsIChannel* aChannel, nsIURI* aURI) : MediaResource(aDecoder, aChannel, aURI), mSize(-1), - mLock("FileMediaResource.mLock") + mLock("FileMediaResource.mLock"), + mSizeInitialized(false) { } ~FileMediaResource() { } // Main thread virtual nsresult Open(nsIStreamListener** aStreamListener); @@ -950,17 +951,21 @@ public: virtual void Pin() {} virtual void Unpin() {} virtual double GetDownloadRate(bool* aIsReliable) { // The data's all already here *aIsReliable = true; return 100*1024*1024; // arbitray, use 100MB/s } - virtual int64_t GetLength() { return mSize; } + virtual int64_t GetLength() { + MutexAutoLock lock(mLock); + EnsureLengthInitialized(); + return mSize; + } virtual int64_t GetNextCachedData(int64_t aOffset) { return (aOffset < mSize) ? aOffset : -1; } virtual int64_t GetCachedDataEnd(int64_t aOffset) { return NS_MAX(aOffset, mSize); } virtual bool IsDataCachedToEndOfResource(int64_t aOffset) { return true; } virtual bool IsSuspendedByCache(MediaResource** aActiveResource) { @@ -969,16 +974,19 @@ public: } return false; } virtual bool IsSuspended() { return false; } nsresult GetCachedRanges(nsTArray<MediaByteRange>& aRanges); private: + // Ensures mSize is initialized, if it can be. + void EnsureLengthInitialized(); + // The file size, or -1 if not known. Immutable after Open(). int64_t mSize; // This lock handles synchronisation between calls to Close() and // the Read, Seek, etc calls. Close must not be called while a // Read or Seek is in progress since it resets various internal // values to null. // This lock protects mSeekable and mInput. @@ -986,16 +994,21 @@ private: // Seekable stream interface to file. This can be used from any // thread. nsCOMPtr<nsISeekableStream> mSeekable; // Input stream for the media data. This can be used from any // thread. nsCOMPtr<nsIInputStream> mInput; + + // Whether we've attempted to initialize mSize. Note that mSize can be -1 + // when mSizeInitialized is true if we tried and failed to get the size + // of the file. + bool mSizeInitialized; }; class LoadedEvent : public nsRunnable { public: LoadedEvent(nsMediaDecoder* aDecoder) : mDecoder(aDecoder) { @@ -1010,18 +1023,37 @@ public: mDecoder->NotifyDownloadEnded(NS_OK); return NS_OK; } private: nsRefPtr<nsMediaDecoder> mDecoder; }; +void FileMediaResource::EnsureLengthInitialized() +{ + mLock.AssertCurrentThreadOwns(); + if (mSizeInitialized) { + return; + } + mSizeInitialized = true; + // Get the file size and inform the decoder. + uint64_t size; + nsresult res = mInput->Available(&size); + if (NS_SUCCEEDED(res) && size <= PR_INT64_MAX) { + mSize = (int64_t)size; + nsCOMPtr<nsIRunnable> event = new LoadedEvent(mDecoder); + NS_DispatchToMainThread(event, NS_DISPATCH_NORMAL); + } +} + nsresult FileMediaResource::GetCachedRanges(nsTArray<MediaByteRange>& aRanges) { + MutexAutoLock lock(mLock); + EnsureLengthInitialized(); if (mSize == -1) { return NS_ERROR_FAILURE; } aRanges.AppendElement(MediaByteRange(0, mSize)); return NS_OK; } nsresult FileMediaResource::Open(nsIStreamListener** aStreamListener) @@ -1066,26 +1098,16 @@ nsresult FileMediaResource::Open(nsIStre if (!mSeekable) { // XXX The file may just be a .url or similar // shortcut that points to a Web site. We need to fix this by // doing an async open and waiting until we locate the real resource, // then using that (if it's still a file!). return NS_ERROR_FAILURE; } - // Get the file size and inform the decoder. - uint64_t size; - rv = mInput->Available(&size); - NS_ENSURE_SUCCESS(rv, rv); - NS_ENSURE_TRUE(size <= PR_INT64_MAX, NS_ERROR_FILE_TOO_BIG); - - mSize = (int64_t)size; - - nsCOMPtr<nsIRunnable> event = new LoadedEvent(mDecoder); - NS_DispatchToMainThread(event, NS_DISPATCH_NORMAL); return NS_OK; } nsresult FileMediaResource::Close() { NS_ASSERTION(NS_IsMainThread(), "Only call on main thread"); MutexAutoLock lock(mLock); @@ -1135,16 +1157,17 @@ MediaResource* FileMediaResource::CloneD return nullptr; return new FileMediaResource(aDecoder, channel, mURI); } nsresult FileMediaResource::ReadFromCache(char* aBuffer, int64_t aOffset, uint32_t aCount) { MutexAutoLock lock(mLock); + EnsureLengthInitialized(); if (!mInput || !mSeekable) return NS_ERROR_FAILURE; int64_t offset = 0; nsresult res = mSeekable->Tell(&offset); NS_ENSURE_SUCCESS(res,res); res = mSeekable->Seek(nsISeekableStream::NS_SEEK_SET, aOffset); NS_ENSURE_SUCCESS(res,res); uint32_t bytesRead = 0; @@ -1164,38 +1187,41 @@ nsresult FileMediaResource::ReadFromCach // Else we succeed if the reset-seek succeeds. return seekres; } nsresult FileMediaResource::Read(char* aBuffer, uint32_t aCount, uint32_t* aBytes) { MutexAutoLock lock(mLock); + EnsureLengthInitialized(); if (!mInput) return NS_ERROR_FAILURE; return mInput->Read(aBuffer, aCount, aBytes); } nsresult FileMediaResource::Seek(int32_t aWhence, int64_t aOffset) { NS_ASSERTION(!NS_IsMainThread(), "Don't call on main thread"); MutexAutoLock lock(mLock); if (!mSeekable) return NS_ERROR_FAILURE; + EnsureLengthInitialized(); return mSeekable->Seek(aWhence, aOffset); } int64_t FileMediaResource::Tell() { NS_ASSERTION(!NS_IsMainThread(), "Don't call on main thread"); MutexAutoLock lock(mLock); if (!mSeekable) return 0; + EnsureLengthInitialized(); int64_t offset = 0; mSeekable->Tell(&offset); return offset; } MediaResource* MediaResource::Create(nsMediaDecoder* aDecoder, nsIChannel* aChannel)