1 /* vim:set ts=2 sw=2 sts=2 et cindent: */ 2 /* This Source Code Form is subject to the terms of the Mozilla Public 3 * License, v. 2.0. If a copy of the MPL was not distributed with this 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 5 6 #ifndef mozilla_dom_media_FileMediaResource_h 7 #define mozilla_dom_media_FileMediaResource_h 8 9 #include "BaseMediaResource.h" 10 #include "mozilla/Mutex.h" 11 12 namespace mozilla { 13 14 class FileMediaResource : public BaseMediaResource { 15 public: 16 FileMediaResource(MediaResourceCallback* aCallback, nsIChannel* aChannel, 17 nsIURI* aURI, int64_t aSize = -1 /* unknown size */) BaseMediaResource(aCallback,aChannel,aURI)18 : BaseMediaResource(aCallback, aChannel, aURI), 19 mSize(aSize), 20 mLock("FileMediaResource.mLock"), 21 mSizeInitialized(aSize != -1) {} 22 ~FileMediaResource() = default; 23 24 // Main thread 25 nsresult Open(nsIStreamListener** aStreamListener) override; 26 RefPtr<GenericPromise> Close() override; Suspend(bool aCloseImmediately)27 void Suspend(bool aCloseImmediately) override {} Resume()28 void Resume() override {} 29 already_AddRefed<nsIPrincipal> GetCurrentPrincipal() override; 30 bool HadCrossOriginRedirects() override; 31 nsresult ReadFromCache(char* aBuffer, int64_t aOffset, 32 uint32_t aCount) override; 33 34 // These methods are called off the main thread. 35 36 // Other thread SetReadMode(MediaCacheStream::ReadMode aMode)37 void SetReadMode(MediaCacheStream::ReadMode aMode) override {} SetPlaybackRate(uint32_t aBytesPerSecond)38 void SetPlaybackRate(uint32_t aBytesPerSecond) override {} 39 nsresult ReadAt(int64_t aOffset, char* aBuffer, uint32_t aCount, 40 uint32_t* aBytes) override; 41 // (Probably) file-based, caching recommended. ShouldCacheReads()42 bool ShouldCacheReads() override { return true; } 43 44 // Any thread Pin()45 void Pin() override {} Unpin()46 void Unpin() override {} GetDownloadRate(bool * aIsReliable)47 double GetDownloadRate(bool* aIsReliable) override { 48 // The data's all already here 49 *aIsReliable = true; 50 return 100 * 1024 * 1024; // arbitray, use 100MB/s 51 } 52 GetLength()53 int64_t GetLength() override { 54 MutexAutoLock lock(mLock); 55 56 EnsureSizeInitialized(); 57 return mSizeInitialized ? mSize : 0; 58 } 59 GetNextCachedData(int64_t aOffset)60 int64_t GetNextCachedData(int64_t aOffset) override { 61 MutexAutoLock lock(mLock); 62 63 EnsureSizeInitialized(); 64 return (aOffset < mSize) ? aOffset : -1; 65 } 66 GetCachedDataEnd(int64_t aOffset)67 int64_t GetCachedDataEnd(int64_t aOffset) override { 68 MutexAutoLock lock(mLock); 69 70 EnsureSizeInitialized(); 71 return std::max(aOffset, mSize); 72 } IsDataCachedToEndOfResource(int64_t aOffset)73 bool IsDataCachedToEndOfResource(int64_t aOffset) override { return true; } IsTransportSeekable()74 bool IsTransportSeekable() override { return true; } 75 76 nsresult GetCachedRanges(MediaByteRangeSet& aRanges) override; 77 SizeOfExcludingThis(MallocSizeOf aMallocSizeOf)78 size_t SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const override { 79 // Might be useful to track in the future: 80 // - mInput 81 return BaseMediaResource::SizeOfExcludingThis(aMallocSizeOf); 82 } 83 SizeOfIncludingThis(MallocSizeOf aMallocSizeOf)84 size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const override { 85 return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf); 86 } 87 88 protected: 89 // These Unsafe variants of Read and Seek perform their operations 90 // without acquiring mLock. The caller must obtain the lock before 91 // calling. The implmentation of Read, Seek and ReadAt obtains the 92 // lock before calling these Unsafe variants to read or seek. 93 nsresult UnsafeRead(char* aBuffer, uint32_t aCount, uint32_t* aBytes); 94 nsresult UnsafeSeek(int32_t aWhence, int64_t aOffset); 95 96 private: 97 // Ensures mSize is initialized, if it can be. 98 // mLock must be held when this is called, and mInput must be non-null. 99 void EnsureSizeInitialized(); 100 already_AddRefed<MediaByteBuffer> UnsafeMediaReadAt(int64_t aOffset, 101 uint32_t aCount); 102 103 // The file size, or -1 if not known. Immutable after Open(). 104 // Can be used from any thread. 105 int64_t mSize; 106 107 // This lock handles synchronisation between calls to Close() and 108 // the Read, Seek, etc calls. Close must not be called while a 109 // Read or Seek is in progress since it resets various internal 110 // values to null. 111 // This lock protects mSeekable, mInput, mSize, and mSizeInitialized. 112 Mutex mLock; 113 114 // Seekable stream interface to file. This can be used from any 115 // thread. 116 nsCOMPtr<nsISeekableStream> mSeekable; 117 118 // Input stream for the media data. This can be used from any 119 // thread. 120 nsCOMPtr<nsIInputStream> mInput; 121 122 // Whether we've attempted to initialize mSize. Note that mSize can be -1 123 // when mSizeInitialized is true if we tried and failed to get the size 124 // of the file. 125 bool mSizeInitialized; 126 // Set to true if NotifyDataEnded callback has been processed (which only 127 // occurs if resource size is known) 128 bool mNotifyDataEndedProcessed = false; 129 }; 130 131 } // namespace mozilla 132 133 #endif // mozilla_dom_media_FileMediaResource_h 134