Bug 1405697 - Move MediaResourceIndex implementation to MediaResource.cpp. r=jwwang
MozReview-Commit-ID: 7GCgaA8jJmU
--- a/dom/media/MediaResource.cpp
+++ b/dom/media/MediaResource.cpp
@@ -36,16 +36,28 @@ MediaResource::Destroy()
NewNonOwningRunnableMethod(
"MediaResource::Destroy", this, &MediaResource::Destroy));
MOZ_ALWAYS_SUCCEEDS(rv);
}
NS_IMPL_ADDREF(MediaResource)
NS_IMPL_RELEASE_WITH_DESTROY(MediaResource, Destroy())
+MediaResourceIndex::MediaResourceIndex(MediaResource* aResource)
+ : mResource(aResource)
+ , mOffset(0)
+ , mCacheBlockSize(aResource->ShouldCacheReads()
+ ? SelectCacheSize(MediaPrefs::MediaResourceIndexCache())
+ : 0)
+ , mCachedOffset(0)
+ , mCachedBytes(0)
+ , mCachedBlock(MakeUnique<char[]>(mCacheBlockSize))
+{
+}
+
nsresult
MediaResourceIndex::Read(char* aBuffer, uint32_t aCount, uint32_t* aBytes)
{
NS_ASSERTION(!NS_IsMainThread(), "Don't call on main thread");
// We purposefuly don't check that we may attempt to read past
// mResource->GetLength() as the resource's length may change over time.
@@ -495,12 +507,108 @@ MediaResourceIndex::Seek(int32_t aWhence
if (aOffset < 0) {
return NS_ERROR_ILLEGAL_VALUE;
}
mOffset = aOffset;
return NS_OK;
}
+already_AddRefed<MediaByteBuffer>
+MediaResourceIndex::MediaReadAt(int64_t aOffset, uint32_t aCount) const
+{
+ RefPtr<MediaByteBuffer> bytes = new MediaByteBuffer();
+ if (aOffset < 0) {
+ return bytes.forget();
+ }
+ bool ok = bytes->SetLength(aCount, fallible);
+ NS_ENSURE_TRUE(ok, nullptr);
+ char* curr = reinterpret_cast<char*>(bytes->Elements());
+ const char* start = curr;
+ while (aCount > 0) {
+ uint32_t bytesRead;
+ nsresult rv = mResource->ReadAt(aOffset, curr, aCount, &bytesRead);
+ NS_ENSURE_SUCCESS(rv, nullptr);
+ if (!bytesRead) {
+ break;
+ }
+ aOffset += bytesRead;
+ if (aOffset < 0) {
+ // Very unlikely overflow.
+ break;
+ }
+ aCount -= bytesRead;
+ curr += bytesRead;
+ }
+ bytes->SetLength(curr - start);
+ return bytes.forget();
+}
+
+already_AddRefed<MediaByteBuffer>
+MediaResourceIndex::CachedMediaReadAt(int64_t aOffset, uint32_t aCount) const
+{
+ RefPtr<MediaByteBuffer> bytes = new MediaByteBuffer();
+ bool ok = bytes->SetLength(aCount, fallible);
+ NS_ENSURE_TRUE(ok, nullptr);
+ char* curr = reinterpret_cast<char*>(bytes->Elements());
+ nsresult rv = mResource->ReadFromCache(curr, aOffset, aCount);
+ NS_ENSURE_SUCCESS(rv, nullptr);
+ return bytes.forget();
+}
+
+// Get the length of the stream in bytes. Returns -1 if not known.
+// This can change over time; after a seek operation, a misbehaving
+// server may give us a resource of a different length to what it had
+// reported previously --- or it may just lie in its Content-Length
+// header and give us more or less data than it reported. We will adjust
+// the result of GetLength to reflect the data that's actually arriving.
+int64_t
+MediaResourceIndex::GetLength() const
+{
+ return mResource->GetLength();
+}
+
+// Select the next power of 2 (in range 32B-128KB, or 0 -> no cache)
+/* static */
+uint32_t
+MediaResourceIndex::SelectCacheSize(uint32_t aHint)
+{
+ if (aHint == 0) {
+ return 0;
+ }
+ if (aHint <= 32) {
+ return 32;
+ }
+ if (aHint > 64 * 1024) {
+ return 128 * 1024;
+ }
+ // 32-bit next power of 2, from:
+ // http://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2
+ aHint--;
+ aHint |= aHint >> 1;
+ aHint |= aHint >> 2;
+ aHint |= aHint >> 4;
+ aHint |= aHint >> 8;
+ aHint |= aHint >> 16;
+ aHint++;
+ return aHint;
+}
+
+uint32_t
+MediaResourceIndex::IndexInCache(int64_t aOffsetInFile) const
+{
+ const uint32_t index = uint32_t(aOffsetInFile) & (mCacheBlockSize - 1);
+ MOZ_ASSERT(index == aOffsetInFile % mCacheBlockSize);
+ return index;
+}
+
+int64_t
+MediaResourceIndex::CacheOffsetContaining(int64_t aOffsetInFile) const
+{
+ const int64_t offset = aOffsetInFile & ~(int64_t(mCacheBlockSize) - 1);
+ MOZ_ASSERT(offset == aOffsetInFile - IndexInCache(aOffsetInFile));
+ return offset;
+}
+
} // namespace mozilla
// avoid redefined macro in unified build
#undef ILOG
--- a/dom/media/MediaResource.h
+++ b/dom/media/MediaResource.h
@@ -151,30 +151,20 @@ private:
/*
* MediaResourceIndex provides a way to access MediaResource objects.
* Read, Seek and Tell must only be called on non-main threads.
* In the case of the Ogg Decoder they are called on the Decode thread for
* example. You must ensure that no threads are calling these methods once
* the MediaResource has been Closed.
*/
-
class MediaResourceIndex
{
public:
- explicit MediaResourceIndex(MediaResource* aResource)
- : mResource(aResource)
- , mOffset(0)
- , mCacheBlockSize(aResource->ShouldCacheReads()
- ? SelectCacheSize(MediaPrefs::MediaResourceIndexCache())
- : 0 )
- , mCachedOffset(0)
- , mCachedBytes(0)
- , mCachedBlock(MakeUnique<char[]>(mCacheBlockSize))
- {}
+ explicit MediaResourceIndex(MediaResource* aResource);
// Read up to aCount bytes from the stream. The buffer must have
// enough room for at least aCount bytes. Stores the number of
// actual bytes read in aBytes (0 on end of file).
// May read less than aCount bytes if the number of
// available bytes is less than aCount. Always check *aBytes after
// read, and call again if necessary.
nsresult Read(char* aBuffer, uint32_t aCount, uint32_t* aBytes);
@@ -246,115 +236,49 @@ public:
uint32_t aExtraCount,
uint32_t* aBytes) const;
// This method returns nullptr if anything fails.
// Otherwise, it returns an owned buffer.
// MediaReadAt may return fewer bytes than requested if end of stream is
// encountered. There is no need to call it again to get more data.
// Note this method will not update mOffset.
- already_AddRefed<MediaByteBuffer> MediaReadAt(int64_t aOffset, uint32_t aCount) const
- {
- RefPtr<MediaByteBuffer> bytes = new MediaByteBuffer();
- if (aOffset < 0) {
- return bytes.forget();
- }
- bool ok = bytes->SetLength(aCount, fallible);
- NS_ENSURE_TRUE(ok, nullptr);
- char* curr = reinterpret_cast<char*>(bytes->Elements());
- const char* start = curr;
- while (aCount > 0) {
- uint32_t bytesRead;
- nsresult rv = mResource->ReadAt(aOffset, curr, aCount, &bytesRead);
- NS_ENSURE_SUCCESS(rv, nullptr);
- if (!bytesRead) {
- break;
- }
- aOffset += bytesRead;
- if (aOffset < 0) {
- // Very unlikely overflow.
- break;
- }
- aCount -= bytesRead;
- curr += bytesRead;
- }
- bytes->SetLength(curr - start);
- return bytes.forget();
- }
+ already_AddRefed<MediaByteBuffer> MediaReadAt(int64_t aOffset,
+ uint32_t aCount) const;
already_AddRefed<MediaByteBuffer> CachedMediaReadAt(int64_t aOffset,
- uint32_t aCount) const
- {
- RefPtr<MediaByteBuffer> bytes = new MediaByteBuffer();
- bool ok = bytes->SetLength(aCount, fallible);
- NS_ENSURE_TRUE(ok, nullptr);
- char* curr = reinterpret_cast<char*>(bytes->Elements());
- nsresult rv = mResource->ReadFromCache(curr, aOffset, aCount);
- NS_ENSURE_SUCCESS(rv, nullptr);
- return bytes.forget();
- }
+ uint32_t aCount) const;
// Get the length of the stream in bytes. Returns -1 if not known.
// This can change over time; after a seek operation, a misbehaving
// server may give us a resource of a different length to what it had
// reported previously --- or it may just lie in its Content-Length
// header and give us more or less data than it reported. We will adjust
// the result of GetLength to reflect the data that's actually arriving.
- int64_t GetLength() const { return mResource->GetLength(); }
+ int64_t GetLength() const;
private:
// If the resource has cached data past the requested range, try to grab it
// into our local cache.
// If there is no cached data, or attempting to read it fails, fallback on
// a (potentially-blocking) read of just what was requested, so that we don't
// get unexpected side-effects by trying to read more than intended.
nsresult CacheOrReadAt(int64_t aOffset,
char* aBuffer,
uint32_t aCount,
uint32_t* aBytes);
// Select the next power of 2 (in range 32B-128KB, or 0 -> no cache)
- static uint32_t SelectCacheSize(uint32_t aHint)
- {
- if (aHint == 0) {
- return 0;
- }
- if (aHint <= 32) {
- return 32;
- }
- if (aHint > 64*1024) {
- return 128*1024;
- }
- // 32-bit next power of 2, from:
- // http://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2
- aHint--;
- aHint |= aHint >> 1;
- aHint |= aHint >> 2;
- aHint |= aHint >> 4;
- aHint |= aHint >> 8;
- aHint |= aHint >> 16;
- aHint++;
- return aHint;
- }
+ static uint32_t SelectCacheSize(uint32_t aHint);
// Maps a file offset to a mCachedBlock index.
- uint32_t IndexInCache(int64_t aOffsetInFile) const
- {
- const uint32_t index = uint32_t(aOffsetInFile) & (mCacheBlockSize - 1);
- MOZ_ASSERT(index == aOffsetInFile % mCacheBlockSize);
- return index;
- }
+ uint32_t IndexInCache(int64_t aOffsetInFile) const;
// Starting file offset of the cache block that contains a given file offset.
- int64_t CacheOffsetContaining(int64_t aOffsetInFile) const
- {
- const int64_t offset = aOffsetInFile & ~(int64_t(mCacheBlockSize) - 1);
- MOZ_ASSERT(offset == aOffsetInFile - IndexInCache(aOffsetInFile));
- return offset;
- }
+ int64_t CacheOffsetContaining(int64_t aOffsetInFile) const;
RefPtr<MediaResource> mResource;
int64_t mOffset;
// Local cache used by ReadAt().
// mCachedBlock is valid when mCachedBytes != 0, in which case it contains
// data of length mCachedBytes, starting at offset `mCachedOffset` in the
// resource, located at index `IndexInCache(mCachedOffset)` in mCachedBlock.