michael@0: /* vim:set ts=2 sw=2 sts=2 et cindent: */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #if !defined(BufferMediaResource_h_) michael@0: #define BufferMediaResource_h_ michael@0: michael@0: #include "MediaResource.h" michael@0: #include "nsISeekableStream.h" michael@0: #include "nsIPrincipal.h" michael@0: #include michael@0: michael@0: namespace mozilla { michael@0: michael@0: // A simple MediaResource based on an in memory buffer. This class accepts michael@0: // the address and the length of the buffer, and simulates a read/seek API michael@0: // on top of it. The Read implementation involves copying memory, which is michael@0: // unfortunate, but the MediaResource interface mandates that. michael@0: class BufferMediaResource : public MediaResource michael@0: { michael@0: public: michael@0: BufferMediaResource(const uint8_t* aBuffer, michael@0: uint32_t aLength, michael@0: nsIPrincipal* aPrincipal, michael@0: const nsACString& aContentType) : michael@0: mBuffer(aBuffer), michael@0: mLength(aLength), michael@0: mOffset(0), michael@0: mPrincipal(aPrincipal), michael@0: mContentType(aContentType) michael@0: { michael@0: MOZ_COUNT_CTOR(BufferMediaResource); michael@0: } michael@0: michael@0: virtual ~BufferMediaResource() michael@0: { michael@0: MOZ_COUNT_DTOR(BufferMediaResource); michael@0: } michael@0: michael@0: virtual nsresult Close() { return NS_OK; } michael@0: virtual void Suspend(bool aCloseImmediately) {} michael@0: virtual void Resume() {} michael@0: // Get the current principal for the channel michael@0: virtual already_AddRefed GetCurrentPrincipal() michael@0: { michael@0: nsCOMPtr principal = mPrincipal; michael@0: return principal.forget(); michael@0: } michael@0: virtual bool CanClone() { return false; } michael@0: virtual already_AddRefed CloneData(MediaDecoder* aDecoder) michael@0: { michael@0: return nullptr; michael@0: } michael@0: michael@0: // These methods are called off the main thread. michael@0: // The mode is initially MODE_PLAYBACK. michael@0: virtual void SetReadMode(MediaCacheStream::ReadMode aMode) {} michael@0: virtual void SetPlaybackRate(uint32_t aBytesPerSecond) {} michael@0: virtual nsresult Read(char* aBuffer, uint32_t aCount, uint32_t* aBytes) michael@0: { michael@0: *aBytes = std::min(mLength - mOffset, aCount); michael@0: memcpy(aBuffer, mBuffer + mOffset, *aBytes); michael@0: mOffset += *aBytes; michael@0: MOZ_ASSERT(mOffset <= mLength); michael@0: return NS_OK; michael@0: } michael@0: virtual nsresult ReadAt(int64_t aOffset, char* aBuffer, michael@0: uint32_t aCount, uint32_t* aBytes) michael@0: { michael@0: nsresult rv = Seek(nsISeekableStream::NS_SEEK_SET, aOffset); michael@0: if (NS_FAILED(rv)) return rv; michael@0: return Read(aBuffer, aCount, aBytes); michael@0: } michael@0: virtual nsresult Seek(int32_t aWhence, int64_t aOffset) michael@0: { michael@0: MOZ_ASSERT(aOffset <= UINT32_MAX); michael@0: switch (aWhence) { michael@0: case nsISeekableStream::NS_SEEK_SET: michael@0: if (aOffset < 0 || aOffset > mLength) { michael@0: return NS_ERROR_FAILURE; michael@0: } michael@0: mOffset = static_cast (aOffset); michael@0: break; michael@0: case nsISeekableStream::NS_SEEK_CUR: michael@0: if (aOffset >= mLength - mOffset) { michael@0: return NS_ERROR_FAILURE; michael@0: } michael@0: mOffset += static_cast (aOffset); michael@0: break; michael@0: case nsISeekableStream::NS_SEEK_END: michael@0: if (aOffset < 0 || aOffset > mLength) { michael@0: return NS_ERROR_FAILURE; michael@0: } michael@0: mOffset = mLength - aOffset; michael@0: break; michael@0: } michael@0: michael@0: return NS_OK; michael@0: } michael@0: virtual void StartSeekingForMetadata() {} michael@0: virtual void EndSeekingForMetadata() {} michael@0: virtual int64_t Tell() { return mOffset; } michael@0: michael@0: virtual void Pin() {} michael@0: virtual void Unpin() {} michael@0: virtual double GetDownloadRate(bool* aIsReliable) { return 0.; } michael@0: virtual int64_t GetLength() { return mLength; } michael@0: virtual int64_t GetNextCachedData(int64_t aOffset) { return aOffset; } michael@0: virtual int64_t GetCachedDataEnd(int64_t aOffset) { return mLength; } michael@0: virtual bool IsDataCachedToEndOfResource(int64_t aOffset) { return true; } michael@0: virtual bool IsSuspendedByCache() { return false; } michael@0: virtual bool IsSuspended() { return false; } michael@0: virtual nsresult ReadFromCache(char* aBuffer, michael@0: int64_t aOffset, michael@0: uint32_t aCount) michael@0: { michael@0: if (aOffset < 0) { michael@0: return NS_ERROR_FAILURE; michael@0: } michael@0: michael@0: uint32_t bytes = std::min(mLength - static_cast(aOffset), aCount); michael@0: memcpy(aBuffer, mBuffer + aOffset, bytes); michael@0: return NS_OK; michael@0: } michael@0: michael@0: virtual nsresult Open(nsIStreamListener** aStreamListener) michael@0: { michael@0: return NS_ERROR_FAILURE; michael@0: } michael@0: michael@0: virtual nsresult GetCachedRanges(nsTArray& aRanges) michael@0: { michael@0: aRanges.AppendElement(MediaByteRange(0, mLength)); michael@0: return NS_OK; michael@0: } michael@0: michael@0: bool IsTransportSeekable() MOZ_OVERRIDE { return true; } michael@0: michael@0: virtual const nsCString& GetContentType() const MOZ_OVERRIDE michael@0: { michael@0: return mContentType; michael@0: } michael@0: michael@0: virtual size_t SizeOfExcludingThis( michael@0: MallocSizeOf aMallocSizeOf) const MOZ_OVERRIDE michael@0: { michael@0: // Not owned: michael@0: // - mBuffer michael@0: // - mPrincipal michael@0: size_t size = MediaResource::SizeOfExcludingThis(aMallocSizeOf); michael@0: size += mContentType.SizeOfExcludingThisIfUnshared(aMallocSizeOf); michael@0: michael@0: return size; michael@0: } michael@0: michael@0: virtual size_t SizeOfIncludingThis( michael@0: MallocSizeOf aMallocSizeOf) const MOZ_OVERRIDE michael@0: { michael@0: return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf); michael@0: } michael@0: michael@0: private: michael@0: const uint8_t * mBuffer; michael@0: uint32_t mLength; michael@0: uint32_t mOffset; michael@0: nsCOMPtr mPrincipal; michael@0: const nsAutoCString mContentType; michael@0: }; michael@0: michael@0: } michael@0: michael@0: #endif