|
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 #if !defined(BufferMediaResource_h_) |
|
7 #define BufferMediaResource_h_ |
|
8 |
|
9 #include "MediaResource.h" |
|
10 #include "nsISeekableStream.h" |
|
11 #include "nsIPrincipal.h" |
|
12 #include <algorithm> |
|
13 |
|
14 namespace mozilla { |
|
15 |
|
16 // A simple MediaResource based on an in memory buffer. This class accepts |
|
17 // the address and the length of the buffer, and simulates a read/seek API |
|
18 // on top of it. The Read implementation involves copying memory, which is |
|
19 // unfortunate, but the MediaResource interface mandates that. |
|
20 class BufferMediaResource : public MediaResource |
|
21 { |
|
22 public: |
|
23 BufferMediaResource(const uint8_t* aBuffer, |
|
24 uint32_t aLength, |
|
25 nsIPrincipal* aPrincipal, |
|
26 const nsACString& aContentType) : |
|
27 mBuffer(aBuffer), |
|
28 mLength(aLength), |
|
29 mOffset(0), |
|
30 mPrincipal(aPrincipal), |
|
31 mContentType(aContentType) |
|
32 { |
|
33 MOZ_COUNT_CTOR(BufferMediaResource); |
|
34 } |
|
35 |
|
36 virtual ~BufferMediaResource() |
|
37 { |
|
38 MOZ_COUNT_DTOR(BufferMediaResource); |
|
39 } |
|
40 |
|
41 virtual nsresult Close() { return NS_OK; } |
|
42 virtual void Suspend(bool aCloseImmediately) {} |
|
43 virtual void Resume() {} |
|
44 // Get the current principal for the channel |
|
45 virtual already_AddRefed<nsIPrincipal> GetCurrentPrincipal() |
|
46 { |
|
47 nsCOMPtr<nsIPrincipal> principal = mPrincipal; |
|
48 return principal.forget(); |
|
49 } |
|
50 virtual bool CanClone() { return false; } |
|
51 virtual already_AddRefed<MediaResource> CloneData(MediaDecoder* aDecoder) |
|
52 { |
|
53 return nullptr; |
|
54 } |
|
55 |
|
56 // These methods are called off the main thread. |
|
57 // The mode is initially MODE_PLAYBACK. |
|
58 virtual void SetReadMode(MediaCacheStream::ReadMode aMode) {} |
|
59 virtual void SetPlaybackRate(uint32_t aBytesPerSecond) {} |
|
60 virtual nsresult Read(char* aBuffer, uint32_t aCount, uint32_t* aBytes) |
|
61 { |
|
62 *aBytes = std::min(mLength - mOffset, aCount); |
|
63 memcpy(aBuffer, mBuffer + mOffset, *aBytes); |
|
64 mOffset += *aBytes; |
|
65 MOZ_ASSERT(mOffset <= mLength); |
|
66 return NS_OK; |
|
67 } |
|
68 virtual nsresult ReadAt(int64_t aOffset, char* aBuffer, |
|
69 uint32_t aCount, uint32_t* aBytes) |
|
70 { |
|
71 nsresult rv = Seek(nsISeekableStream::NS_SEEK_SET, aOffset); |
|
72 if (NS_FAILED(rv)) return rv; |
|
73 return Read(aBuffer, aCount, aBytes); |
|
74 } |
|
75 virtual nsresult Seek(int32_t aWhence, int64_t aOffset) |
|
76 { |
|
77 MOZ_ASSERT(aOffset <= UINT32_MAX); |
|
78 switch (aWhence) { |
|
79 case nsISeekableStream::NS_SEEK_SET: |
|
80 if (aOffset < 0 || aOffset > mLength) { |
|
81 return NS_ERROR_FAILURE; |
|
82 } |
|
83 mOffset = static_cast<uint32_t> (aOffset); |
|
84 break; |
|
85 case nsISeekableStream::NS_SEEK_CUR: |
|
86 if (aOffset >= mLength - mOffset) { |
|
87 return NS_ERROR_FAILURE; |
|
88 } |
|
89 mOffset += static_cast<uint32_t> (aOffset); |
|
90 break; |
|
91 case nsISeekableStream::NS_SEEK_END: |
|
92 if (aOffset < 0 || aOffset > mLength) { |
|
93 return NS_ERROR_FAILURE; |
|
94 } |
|
95 mOffset = mLength - aOffset; |
|
96 break; |
|
97 } |
|
98 |
|
99 return NS_OK; |
|
100 } |
|
101 virtual void StartSeekingForMetadata() {} |
|
102 virtual void EndSeekingForMetadata() {} |
|
103 virtual int64_t Tell() { return mOffset; } |
|
104 |
|
105 virtual void Pin() {} |
|
106 virtual void Unpin() {} |
|
107 virtual double GetDownloadRate(bool* aIsReliable) { return 0.; } |
|
108 virtual int64_t GetLength() { return mLength; } |
|
109 virtual int64_t GetNextCachedData(int64_t aOffset) { return aOffset; } |
|
110 virtual int64_t GetCachedDataEnd(int64_t aOffset) { return mLength; } |
|
111 virtual bool IsDataCachedToEndOfResource(int64_t aOffset) { return true; } |
|
112 virtual bool IsSuspendedByCache() { return false; } |
|
113 virtual bool IsSuspended() { return false; } |
|
114 virtual nsresult ReadFromCache(char* aBuffer, |
|
115 int64_t aOffset, |
|
116 uint32_t aCount) |
|
117 { |
|
118 if (aOffset < 0) { |
|
119 return NS_ERROR_FAILURE; |
|
120 } |
|
121 |
|
122 uint32_t bytes = std::min(mLength - static_cast<uint32_t>(aOffset), aCount); |
|
123 memcpy(aBuffer, mBuffer + aOffset, bytes); |
|
124 return NS_OK; |
|
125 } |
|
126 |
|
127 virtual nsresult Open(nsIStreamListener** aStreamListener) |
|
128 { |
|
129 return NS_ERROR_FAILURE; |
|
130 } |
|
131 |
|
132 virtual nsresult GetCachedRanges(nsTArray<MediaByteRange>& aRanges) |
|
133 { |
|
134 aRanges.AppendElement(MediaByteRange(0, mLength)); |
|
135 return NS_OK; |
|
136 } |
|
137 |
|
138 bool IsTransportSeekable() MOZ_OVERRIDE { return true; } |
|
139 |
|
140 virtual const nsCString& GetContentType() const MOZ_OVERRIDE |
|
141 { |
|
142 return mContentType; |
|
143 } |
|
144 |
|
145 virtual size_t SizeOfExcludingThis( |
|
146 MallocSizeOf aMallocSizeOf) const MOZ_OVERRIDE |
|
147 { |
|
148 // Not owned: |
|
149 // - mBuffer |
|
150 // - mPrincipal |
|
151 size_t size = MediaResource::SizeOfExcludingThis(aMallocSizeOf); |
|
152 size += mContentType.SizeOfExcludingThisIfUnshared(aMallocSizeOf); |
|
153 |
|
154 return size; |
|
155 } |
|
156 |
|
157 virtual size_t SizeOfIncludingThis( |
|
158 MallocSizeOf aMallocSizeOf) const MOZ_OVERRIDE |
|
159 { |
|
160 return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf); |
|
161 } |
|
162 |
|
163 private: |
|
164 const uint8_t * mBuffer; |
|
165 uint32_t mLength; |
|
166 uint32_t mOffset; |
|
167 nsCOMPtr<nsIPrincipal> mPrincipal; |
|
168 const nsAutoCString mContentType; |
|
169 }; |
|
170 |
|
171 } |
|
172 |
|
173 #endif |